summaryrefslogtreecommitdiffstats
path: root/private/ntos/ndis/ibmtok
diff options
context:
space:
mode:
Diffstat (limited to 'private/ntos/ndis/ibmtok')
-rw-r--r--private/ntos/ndis/ibmtok/ibmtok.c5906
-rw-r--r--private/ntos/ndis/ibmtok/ibmtok.rc39
-rw-r--r--private/ntos/ndis/ibmtok/interrup.c4855
-rw-r--r--private/ntos/ndis/ibmtok/keywords.h54
-rw-r--r--private/ntos/ndis/ibmtok/makefile6
-rw-r--r--private/ntos/ndis/ibmtok/packet.c732
-rw-r--r--private/ntos/ndis/ibmtok/send.c322
-rw-r--r--private/ntos/ndis/ibmtok/sources48
-rw-r--r--private/ntos/ndis/ibmtok/tokhrd.h667
-rw-r--r--private/ntos/ndis/ibmtok/toksft.h1373
-rw-r--r--private/ntos/ndis/ibmtok/transfer.c412
11 files changed, 14414 insertions, 0 deletions
diff --git a/private/ntos/ndis/ibmtok/ibmtok.c b/private/ntos/ndis/ibmtok/ibmtok.c
new file mode 100644
index 000000000..30e4da708
--- /dev/null
+++ b/private/ntos/ndis/ibmtok/ibmtok.c
@@ -0,0 +1,5906 @@
+/*++
+
+Copyright (c) 1990 Microsoft Corporation
+
+Module Name:
+
+ ibmtok.c
+
+Abstract:
+
+ This is the main file for the IBM Token-Ring 16/4 Adapter.
+ This driver conforms to the NDIS 3.0 interface.
+
+ The overall structure and much of the code is taken from
+ the Lance NDIS driver by Tony Ercolano.
+
+Author:
+
+ Anthony V. Ercolano (Tonye) 20-Jul-1990
+ Adam Barr (adamba) 15-Feb-1990
+
+Environment:
+
+ Kernel Mode - Or whatever is the equivalent.
+
+Revision History:
+
+ Sean Selitrennikoff -- 9/15/91:
+ Added code to handle Microchannel with PC I/O bus handling.
+ Fixed bugs.
+ Sean Selitrennikoff -- 10/15/91:
+ Converted to Ndis 3.0 spec.
+ George Joy -- 12/1/91
+ Changed for compilation under DOS as well as NT
+ Sean Selitrennikoff -- 1/8/92:
+ Added error logging
+ Brian E. Moore -- 8/8/95
+ Added AutoRingSpeed Support for the PCMCIA token-ring III card.
+
+ Sanjay Deshpande -- 11/22/95
+ PCMCIA MMIO and RAM is read from registry always .... no default values
+--*/
+
+
+#include <ndis.h>
+
+
+#include <tfilter.h>
+#include <tokhrd.h>
+#include <toksft.h>
+
+#include "keywords.h"
+
+//
+// This constant is used for places where NdisAllocateMemory
+// needs to be called and the HighestAcceptableAddress does
+// not matter.
+//
+
+const NDIS_PHYSICAL_ADDRESS HighestAcceptableMax =
+ NDIS_PHYSICAL_ADDRESS_CONST(-1,-1);
+
+
+//
+// If you add to this, make sure to add the
+// a case in IbmtokFillInGlobalData() and in
+// IbmtokQueryGlobalStatistics()
+//
+static const UINT IbmtokGlobalSupportedOids[] = {
+ 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_MAC_OPTIONS,
+ OID_GEN_PROTOCOL_OPTIONS,
+ 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_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_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
+ };
+
+//
+// If you add to this, make sure to add the
+// a case in IbmtokQueryGlobalStatistics() and in
+// IbmtokQueryProtocolInformation()
+//
+static const UINT IbmtokProtocolSupportedOids[] = {
+ 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_MAC_OPTIONS,
+ OID_GEN_PROTOCOL_OPTIONS,
+ 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_802_5_PERMANENT_ADDRESS,
+ OID_802_5_CURRENT_ADDRESS,
+ OID_802_5_CURRENT_FUNCTIONAL,
+ OID_802_5_CURRENT_GROUP
+ };
+
+
+//
+// On a development build, don't define functions as static
+// so we can set breakpoints on them.
+//
+
+
+#if DEVL
+#define STATIC
+#else
+#define STATIC static
+#endif
+
+
+#if DBG
+INT IbmtokDbg = 0;
+#define LOG 1
+#else
+#define LOG 0
+#endif
+
+
+//
+// Get from configuration file.
+//
+
+#define MAX_MULTICAST_ADDRESS ((UINT)16)
+#define MAX_ADAPTERS ((UINT)4)
+
+
+//
+// This macro determines if the directed address
+// filtering in the CAM is actually necessary given
+// the current filter.
+//
+#define CAM_DIRECTED_SIGNIFICANT(_Filter) \
+ ((((_Filter) & NDIS_PACKET_TYPE_DIRECTED) && \
+ (!((_Filter) & NDIS_PACKET_TYPE_PROMISCUOUS))) ? 1 : 0)
+
+
+//
+// This macro determines if the multicast filtering in
+// the CAM are actually necessary given the current filter.
+//
+#define CAM_MULTICAST_SIGNIFICANT(_Filter) \
+ ((((_Filter) & NDIS_PACKET_TYPE_MULTICAST) && \
+ (!((_Filter) & (NDIS_PACKET_TYPE_ALL_MULTICAST | \
+ NDIS_PACKET_TYPE_PROMISCUOUS)))) ? 1 : 0)
+
+
+STATIC
+NDIS_STATUS
+IbmtokOpenAdapter(
+ OUT PNDIS_STATUS OpenErrorStatus,
+ OUT NDIS_HANDLE *MacBindingHandle,
+ OUT PUINT SelectedMediumIndex,
+ IN PNDIS_MEDIUM MediumArray,
+ IN UINT MediumArraySize,
+ IN NDIS_HANDLE NdisBindingContext,
+ IN NDIS_HANDLE MacAdapterContext,
+ IN UINT OpenOptions,
+ IN PSTRING AddressingInformation OPTIONAL
+ );
+
+STATIC
+NDIS_STATUS
+IbmtokCloseAdapter(
+ IN NDIS_HANDLE MacBindingHandle
+ );
+
+
+STATIC
+NDIS_STATUS
+IbmtokRequest(
+ IN NDIS_HANDLE MacBindingHandle,
+ IN PNDIS_REQUEST NdisRequest
+ );
+
+STATIC
+NDIS_STATUS
+IbmtokQueryInformation(
+ IN PIBMTOK_ADAPTER Adapter,
+ IN PIBMTOK_OPEN Open,
+ IN PNDIS_REQUEST NdisRequest
+ );
+
+
+STATIC
+NDIS_STATUS
+IbmtokSetInformation(
+ IN PIBMTOK_ADAPTER Adapter,
+ IN PIBMTOK_OPEN Open,
+ IN PNDIS_REQUEST NdisRequest
+ );
+
+STATIC
+NDIS_STATUS
+IbmtokQueryGlobalStatistics(
+ IN NDIS_HANDLE MacAdapterContext,
+ IN PNDIS_REQUEST NdisRequest
+ );
+
+NDIS_STATUS
+IbmtokAddAdapter(
+ IN NDIS_HANDLE MacMacContext,
+ IN NDIS_HANDLE ConfigurationHandle,
+ IN PNDIS_STRING AdaptName
+ );
+
+VOID
+IbmtokRemoveAdapter(
+ IN PVOID MacAdapterContext
+ );
+
+STATIC
+NDIS_STATUS
+IbmtokSetPacketFilter(
+ IN PIBMTOK_ADAPTER Adapter,
+ IN PIBMTOK_OPEN Open,
+ IN PNDIS_REQUEST NdisRequest,
+ IN UINT PacketFilter
+ );
+
+STATIC
+NDIS_STATUS
+IbmtokSetGroupAddress(
+ IN PIBMTOK_ADAPTER Adapter,
+ IN PIBMTOK_OPEN Open,
+ IN PNDIS_REQUEST NdisRequest,
+ IN PUCHAR Address
+ );
+
+STATIC
+NDIS_STATUS
+IbmtokChangeFunctionalAddress(
+ IN PIBMTOK_ADAPTER Adapter,
+ IN PIBMTOK_OPEN Open,
+ IN PNDIS_REQUEST NdisRequest,
+ IN PUCHAR Address
+ );
+
+STATIC
+NDIS_STATUS
+IbmtokReset(
+ IN NDIS_HANDLE MacBindingHandle
+ );
+
+STATIC
+NDIS_STATUS
+IbmtokTest(
+ IN NDIS_HANDLE MacBindingHandle
+ );
+
+STATIC
+NDIS_STATUS
+IbmtokChangeFilter(
+ IN UINT OldFilterClasses,
+ IN UINT NewFilterClasses,
+ IN NDIS_HANDLE MacBindingHandle,
+ IN PNDIS_REQUEST NdisRequest,
+ IN BOOLEAN Set
+ );
+
+STATIC
+NDIS_STATUS
+IbmtokChangeAddress(
+ IN TR_FUNCTIONAL_ADDRESS OldFunctionalAddress,
+ IN TR_FUNCTIONAL_ADDRESS NewFunctionalAddress,
+ IN NDIS_HANDLE MacBindingHandle,
+ IN PNDIS_REQUEST NdisRequest,
+ IN BOOLEAN Set
+ );
+
+STATIC
+NDIS_STATUS
+IbmtokChangeGroupAddress(
+ IN TR_FUNCTIONAL_ADDRESS OldGroupAddress,
+ IN TR_FUNCTIONAL_ADDRESS NewGroupAddress,
+ IN NDIS_HANDLE MacBindingHandle,
+ IN PNDIS_REQUEST NdisRequest,
+ IN BOOLEAN Set
+ );
+
+STATIC
+BOOLEAN
+IbmtokHardwareDetails(
+ IN PIBMTOK_ADAPTER Adapter
+ );
+
+STATIC
+NDIS_STATUS
+IbmtokRegisterAdapter(
+ IN PIBMTOK_ADAPTER Adapter,
+ IN NDIS_HANDLE ConfigurationHandle,
+ IN PNDIS_STRING DeviceName,
+ IN BOOLEAN McaCard,
+ IN BOOLEAN ConfigError
+ );
+
+STATIC
+VOID
+SetInitializeVariables(
+ IN PIBMTOK_ADAPTER Adapter
+ );
+
+VOID
+SetResetVariables(
+ IN PIBMTOK_ADAPTER Adapter
+ );
+
+extern
+VOID
+IbmtokStartAdapterReset(
+ IN PIBMTOK_ADAPTER Adapter
+ );
+
+STATIC
+VOID
+IbmtokCloseAction(
+ IN NDIS_HANDLE MacBindingHandle
+ );
+
+STATIC
+VOID
+IbmtokSetupRegistersAndInit(
+ IN PIBMTOK_ADAPTER Adapter
+ );
+
+STATIC
+NDIS_STATUS
+IbmtokInitialInit(
+ IN PIBMTOK_ADAPTER Adapter
+ );
+
+VOID
+IbmtokUnload(
+ IN NDIS_HANDLE MacMacContext
+ );
+
+NTSTATUS
+DriverEntry(
+ IN PDRIVER_OBJECT DriverObject,
+ IN PUNICODE_STRING RegistryPath
+ );
+
+#pragma NDIS_INIT_FUNCTION(DriverEntry)
+
+NTSTATUS
+DriverEntry(
+ IN PDRIVER_OBJECT DriverObject,
+ IN PUNICODE_STRING RegistryPath
+ )
+/*++
+
+Routine Description:
+
+ This is the primary initialization routine for the ibmtok driver.
+ It is simply responsible for the intializing the wrapper and registering
+ the MAC. It then calls a system and architecture specific routine that
+ will initialize and register each adapter.
+
+Arguments:
+
+ DriverObject - Pointer to driver object created by the system.
+
+Return Value:
+
+ The status of the operation.
+
+--*/
+
+{
+
+
+ //
+ // Receives the status of the NdisRegisterMac operation.
+ //
+ NDIS_STATUS InitStatus;
+ PIBMTOK_MAC IbmtokMac;
+ NDIS_HANDLE NdisWrapperHandle;
+ char Tmp[sizeof(NDIS_MAC_CHARACTERISTICS)];
+ PNDIS_MAC_CHARACTERISTICS IbmtokChar = (PNDIS_MAC_CHARACTERISTICS)(PVOID)Tmp;
+ NDIS_STRING MacName = NDIS_STRING_CONST("IbmTok");
+
+#if NDIS_WIN
+ UCHAR pIds[sizeof (EISA_MCA_ADAPTER_IDS) + 2 * sizeof (USHORT)];
+#endif
+
+#if NDIS_WIN
+ ((PEISA_MCA_ADAPTER_IDS)pIds)->nEisaAdapters=0;
+ ((PEISA_MCA_ADAPTER_IDS)pIds)->nMcaAdapters=2;
+ *((PUSHORT)(((PEISA_MCA_ADAPTER_IDS)pIds)->IdArray) + 0)=IBMTOK1_ADAPTER_ID;
+ *((PUSHORT)(((PEISA_MCA_ADAPTER_IDS)pIds)->IdArray) + 1)=IBMTOK2_ADAPTER_ID;
+ (PVOID) DriverObject = (PVOID) pIds;
+#endif
+
+ //
+ // Initialize the wrapper.
+ //
+
+ NdisInitializeWrapper(
+ &NdisWrapperHandle,
+ DriverObject,
+ RegistryPath,
+ NULL
+ );
+
+ //
+ // Now allocate memory for our global structure.
+ //
+
+ InitStatus = IBMTOK_ALLOC_PHYS(&IbmtokMac, sizeof(IBMTOK_MAC));
+
+ if (InitStatus != NDIS_STATUS_SUCCESS) {
+
+ return NDIS_STATUS_RESOURCES;
+
+ }
+
+ IbmtokMac->NdisWrapperHandle = NdisWrapperHandle;
+
+ //
+ // Initialize the MAC characteristics for the call to
+ // NdisRegisterMac.
+ //
+
+
+ IbmtokChar->MajorNdisVersion = IBMTOK_NDIS_MAJOR_VERSION;
+ IbmtokChar->MinorNdisVersion = IBMTOK_NDIS_MINOR_VERSION;
+ IbmtokChar->OpenAdapterHandler = (OPEN_ADAPTER_HANDLER) IbmtokOpenAdapter;
+ IbmtokChar->CloseAdapterHandler = (CLOSE_ADAPTER_HANDLER) IbmtokCloseAdapter;
+ IbmtokChar->RequestHandler = IbmtokRequest;
+ IbmtokChar->SendHandler = IbmtokSend;
+ IbmtokChar->TransferDataHandler = IbmtokTransferData;
+ IbmtokChar->ResetHandler = IbmtokReset;
+ IbmtokChar->UnloadMacHandler = IbmtokUnload;
+ IbmtokChar->QueryGlobalStatisticsHandler = IbmtokQueryGlobalStatistics;
+ IbmtokChar->AddAdapterHandler = IbmtokAddAdapter;
+ IbmtokChar->RemoveAdapterHandler = IbmtokRemoveAdapter;
+
+ IbmtokChar->Name = MacName;
+
+ NdisRegisterMac(
+ &InitStatus,
+ &IbmtokMac->NdisMacHandle,
+ NdisWrapperHandle,
+ (PVOID)IbmtokMac,
+ IbmtokChar,
+ sizeof(*IbmtokChar)
+ );
+
+ if (InitStatus != NDIS_STATUS_SUCCESS) {
+
+ NdisTerminateWrapper(NdisWrapperHandle, NULL);
+
+ return NDIS_STATUS_FAILURE;
+
+ }
+
+ return NDIS_STATUS_SUCCESS;
+
+}
+
+
+
+#pragma NDIS_INIT_FUNCTION(IbmtokRegisterAdapter)
+
+STATIC
+NDIS_STATUS
+IbmtokRegisterAdapter(
+ IN PIBMTOK_ADAPTER Adapter,
+ IN NDIS_HANDLE ConfigurationHandle,
+ IN PNDIS_STRING DeviceName,
+ IN BOOLEAN McaCard,
+ IN BOOLEAN ConfigError
+ )
+
+/*++
+
+Routine Description:
+
+ This routine (and its interface) are not portable. They are
+ defined by the OS, the architecture, and the particular IBMTOK
+ implementation.
+
+ This routine is responsible for the allocation of the datastructures
+ for the driver as well as any hardware specific details necessary
+ to talk with the device.
+
+Arguments:
+
+ Adapter - Pointer to the adapter block.
+
+ ConfigurationHandle - Handle passed to MacAddAdapter, to be passed to
+ NdisRegisterAdapter.
+
+ DeviceName - Name of this adapter.
+
+ McaCard - This is an MCA bus.
+
+ ConfigError - TRUE if a configuration error was found earlier.
+
+Return Value:
+
+ Returns NDIS_STATUS_SUCCESS if everything goes ok, else
+ if anything occurred that prevents the initialization
+ of the adapter it returns an appropriate NDIS error.
+
+--*/
+
+{
+
+ NDIS_STATUS Status;
+
+ //
+ // Holds information needed when registering the adapter.
+ //
+
+ NDIS_ADAPTER_INFORMATION AdapterInformation;
+
+ // We put in this assertion to make sure that ushort are 2 bytes.
+ // if they aren't then the initialization block definition needs
+ // to be changed.
+ //
+ // Also all of the logic that deals with status registers assumes
+ // that control registers are only 2 bytes.
+ //
+
+ ASSERT(sizeof(USHORT) == 2);
+
+ //
+ // Get the interrupt number and MMIO address.
+ //
+
+ //
+ // Set the adapter state.
+ //
+
+ SetInitializeVariables(Adapter);
+
+ SetResetVariables(Adapter);
+
+ //
+ // Set up the AdapterInformation structure; zero it
+ // first in case it is extended later.
+ //
+
+ IBMTOK_ZERO_MEMORY (&AdapterInformation, sizeof(NDIS_ADAPTER_INFORMATION));
+ AdapterInformation.AdapterType = (McaCard ? NdisInterfaceMca : NdisInterfaceIsa);
+ AdapterInformation.NumberOfPortDescriptors = 1;
+ AdapterInformation.PortDescriptors[0].InitialPort = Adapter->IbmtokPortAddress;
+ AdapterInformation.PortDescriptors[0].NumberOfPorts = 4;
+
+ //
+ // Register the adapter with Ndis.
+ //
+
+ Status = NdisRegisterAdapter(
+ &Adapter->NdisAdapterHandle,
+ Adapter->NdisMacHandle,
+ Adapter,
+ ConfigurationHandle,
+ DeviceName,
+ &AdapterInformation
+ );
+
+ if (Status != NDIS_STATUS_SUCCESS) {
+
+ return(Status);
+
+ }
+
+ if (ConfigError) {
+
+ //
+ // Error and quit
+ //
+
+ NdisWriteErrorLogEntry(
+ Adapter->NdisAdapterHandle,
+ NDIS_ERROR_CODE_UNSUPPORTED_CONFIGURATION,
+ 0
+ );
+
+ NdisDeregisterAdapter(Adapter->NdisAdapterHandle);
+
+ return(NDIS_STATUS_FAILURE);
+
+ }
+
+
+
+ if (!IbmtokHardwareDetails(Adapter)) {
+
+ NdisDeregisterAdapter(Adapter->NdisAdapterHandle);
+ return NDIS_STATUS_ADAPTER_NOT_FOUND;
+
+ }
+
+
+ //
+ // Reset the card to put it in a valid state.
+ //
+
+ if (Adapter->SharedRamPaging) {
+
+ WRITE_ADAPTER_REGISTER(Adapter, SRPR_LOW, 0xc0);
+
+ }
+
+ //
+ // OK, do the reset as detailed in the Tech Ref...
+ //
+
+ WRITE_ADAPTER_PORT(Adapter, RESET_LATCH, 0);
+
+ NdisStallExecution(50000);
+
+ WRITE_ADAPTER_PORT(Adapter, RESET_RELEASE, 0);
+
+ //
+ // Initialize the interrupt.
+ //
+
+ NdisAllocateSpinLock(&Adapter->InterruptLock);
+
+ NdisInitializeInterrupt(
+ &Status,
+ &Adapter->Interrupt,
+ Adapter->NdisAdapterHandle,
+ IbmtokISR,
+ Adapter,
+ IbmtokDPC,
+ Adapter->InterruptLevel,
+ Adapter->InterruptLevel,
+ FALSE,
+ (Adapter->UsingPcIoBus)?NdisInterruptLatched:
+ NdisInterruptLevelSensitive
+ );
+
+ if (Status == NDIS_STATUS_SUCCESS){
+
+ //
+ // Set up the Adapter variables. (We have to do the
+ // initial init to get the network address before we
+ // create the filter DB.)
+ //
+ if (IbmtokInitialInit(Adapter) != NDIS_STATUS_SUCCESS) {
+
+ NdisWriteErrorLogEntry(
+ Adapter->NdisAdapterHandle,
+ NDIS_ERROR_CODE_ADAPTER_NOT_FOUND,
+ 2,
+ registerAdapter,
+ IBMTOK_ERRMSG_NOT_FOUND
+ );
+
+ NdisRemoveInterrupt(&Adapter->Interrupt);
+
+ NdisDeregisterAdapter(Adapter->NdisAdapterHandle);
+ NdisFreeSpinLock(&(Adapter->Lock));
+ return NDIS_STATUS_ADAPTER_NOT_FOUND;
+
+ } else {
+
+ if (!TrCreateFilter(
+ IbmtokChangeAddress,
+ IbmtokChangeGroupAddress,
+ IbmtokChangeFilter,
+ IbmtokCloseAction,
+ Adapter->NetworkAddress,
+ &Adapter->Lock,
+ &Adapter->FilterDB
+ )) {
+
+ NdisWriteErrorLogEntry(
+ Adapter->NdisAdapterHandle,
+ NDIS_ERROR_CODE_OUT_OF_RESOURCES,
+ 2,
+ registerAdapter,
+ IBMTOK_ERRMSG_CREATE_DB
+ );
+
+ NdisRemoveInterrupt(&Adapter->Interrupt);
+ NdisDeregisterAdapter(Adapter->NdisAdapterHandle);
+ NdisFreeSpinLock(&(Adapter->Lock));
+ return NDIS_STATUS_RESOURCES;
+
+ } else {
+
+ //
+ // Initialize the wake up timer to catch interrupts that
+ // don't complete. It fires continuously
+ // every thirty seconds, and we check if there are any
+ // uncompleted operations from the previous two-second
+ // period.
+ //
+
+ Adapter->WakeUpDpc = (PVOID)IbmtokWakeUpDpc;
+
+ NdisInitializeTimer(&Adapter->WakeUpTimer,
+ (PVOID)(Adapter->WakeUpDpc),
+ Adapter );
+
+ NdisSetTimer(
+ &Adapter->WakeUpTimer,
+ 30000
+ );
+
+ NdisRegisterAdapterShutdownHandler(
+ Adapter->NdisAdapterHandle,
+ (PVOID)Adapter,
+ IbmtokShutdown
+ );
+
+ return(NDIS_STATUS_SUCCESS);
+
+ }
+
+ }
+
+ } else {
+
+ NdisWriteErrorLogEntry(
+ Adapter->NdisAdapterHandle,
+ NDIS_ERROR_CODE_INTERRUPT_CONNECT,
+ 2,
+ registerAdapter,
+ IBMTOK_ERRMSG_INIT_INTERRUPT
+ );
+
+ NdisDeregisterAdapter(Adapter->NdisAdapterHandle);
+ NdisFreeSpinLock(&(Adapter->Lock));
+ return(Status);
+ }
+
+}
+
+
+#pragma NDIS_INIT_FUNCTION(SetInitializeVariables)
+
+STATIC
+VOID
+SetInitializeVariables(
+ IN PIBMTOK_ADAPTER Adapter
+ )
+
+/*++
+
+Routine Description:
+
+ This routine initializes all the variables in the Adapter
+ structure that should only be set during adapter initialization
+ (i.e. not during a reset).
+
+Arguments:
+
+ Adapter - The adapter for the hardware.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+ InitializeListHead(&Adapter->OpenBindings);
+ InitializeListHead(&Adapter->CloseList);
+ InitializeListHead(&Adapter->CloseDuringResetList);
+
+ NdisAllocateSpinLock(&Adapter->Lock);
+
+ //
+ // If this is not true, then uncomment below
+ //
+
+ ASSERT(FALSE == (BOOLEAN)0);
+
+ // Adapter->HandleSrbRunning = FALSE;
+ // Adapter->HandleArbRunning = FALSE;
+
+ // Adapter->OpenInProgress = FALSE;
+
+ Adapter->AdapterNotOpen = TRUE;
+ Adapter->NotAcceptingRequests = TRUE;
+
+ // Adapter->ResetInProgress = FALSE;
+ // Adapter->ResettingOpen = NULL;
+ // Adapter->ResetInterruptAllowed = FALSE;
+ // Adapter->ResetInterruptHasArrived = FALSE;
+
+ // Adapter->BringUp = FALSE;
+
+ //
+ // Note: These assume that the SAP info will not
+ // take up more than 218 bytes. This is ok, for now, since
+ // we open the card with 0 SAPs allowed.
+ //
+
+ Adapter->ReceiveBufferLength = 256;
+ Adapter->NumberOfTransmitBuffers = 1;
+
+ //
+ // Note: The following fields are set in the interrupt handler after
+ // the card tells us if the ring is 16 or 4 Mbps.
+ //
+ //
+ // TransmitBufferLength
+ // NumberOfReceiveBuffers
+ // MaximumTransmittablePacket
+ //
+
+ // Adapter->IsrpDeferredBits = 0;
+
+ Adapter->FirstInitialization = TRUE;
+
+ // Adapter->OutstandingAsbFreeRequest = FALSE;
+}
+
+
+VOID
+SetResetVariables(
+ IN PIBMTOK_ADAPTER Adapter
+ )
+
+/*++
+
+Routine Description:
+
+ This routine initializes all the variables in the Adapter
+ structure that are set both during an initialization and
+ after a reset.
+
+Arguments:
+
+ Adapter - The adapter for the hardware.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+ Adapter->FirstTransmit = NULL;
+ Adapter->LastTransmit = NULL;
+ Adapter->FirstWaitingForAsb = NULL;
+ Adapter->LastWaitingForAsb = NULL;
+ Adapter->TransmittingPacket = NULL;
+
+ IBMTOK_ZERO_MEMORY(Adapter->CorrelatorArray,
+ sizeof(PNDIS_PACKET) * MAX_COMMAND_CORRELATOR);
+
+ Adapter->PendQueue = NULL;
+ Adapter->EndOfPendQueue = NULL;
+
+ Adapter->SrbAvailable = TRUE;
+ Adapter->AsbAvailable = TRUE;
+
+ Adapter->IsrpBits = 0;
+ Adapter->IsrpLowBits = 0;
+
+ Adapter->NextCorrelatorToComplete = 0;
+ Adapter->ReceiveWaitingForAsbList = (USHORT)-1;
+ Adapter->ReceiveWaitingForAsbEnd = (USHORT)-1;
+ Adapter->UseNextAsbForReceive = TRUE;
+}
+
+#pragma NDIS_INIT_FUNCTION(IbmtokInitialInit)
+
+NDIS_STATUS
+IbmtokInitialInit(
+ IN PIBMTOK_ADAPTER Adapter
+ )
+
+/*++
+
+Routine Description:
+
+ This routine sets up the initial init of the driver.
+
+Arguments:
+
+ Adapter - The adapter for the hardware.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+ USHORT RegValue;
+ UINT Time = 50; // Number of 100 milliseconds to delay while waiting
+ // for the card to initialize.
+
+
+
+ IbmtokSetupRegistersAndInit(Adapter);
+
+ //
+ // Delay execution for 5 seconds to give the ring
+ // time to initialize.
+ //
+
+ while((!Adapter->BringUp) && (Time != 0)){
+
+ NdisStallExecution(100000);
+
+ Time--;
+
+ }
+
+ if (!Adapter->BringUp){
+
+ return(NDIS_STATUS_ADAPTER_NOT_FOUND);
+
+ } else {
+
+ //
+ // Do remaining initialization.
+ //
+
+ USHORT WrbOffset;
+ PSRB_BRING_UP_RESULT BringUpSrb;
+ PUCHAR EncodedAddress;
+ UCHAR Value1, Value2;
+
+ READ_ADAPTER_REGISTER(Adapter, WRBR_LOW, &Value1);
+ READ_ADAPTER_REGISTER(Adapter, WRBR_HIGH, &Value2);
+
+ WrbOffset = (((USHORT)Value1) << 8) + (USHORT)Value2;
+
+ Adapter->InitialWrbOffset = WrbOffset;
+
+#if DBG
+ if (IbmtokDbg) {
+
+ DbgPrint("IBMTOK: Initial Offset = 0x%x\n", WrbOffset);
+
+ }
+#endif
+
+ BringUpSrb = (PSRB_BRING_UP_RESULT)
+ (Adapter->SharedRam + WrbOffset);
+
+ NdisReadRegisterUshort(&(BringUpSrb->ReturnCode), &RegValue);
+
+ if (RegValue != 0x0000) {
+
+ if (RegValue == 0x30){
+
+ NdisWriteErrorLogEntry(
+ Adapter->NdisAdapterHandle,
+ NDIS_ERROR_CODE_UNSUPPORTED_CONFIGURATION,
+ 0x32,
+ handleSrbSsb,
+ IBMTOK_ERRMSG_BRINGUP_FAILURE
+ );
+
+
+ return(NDIS_STATUS_ADAPTER_NOT_FOUND);
+
+ } else {
+
+ NdisWriteErrorLogEntry(
+ Adapter->NdisAdapterHandle,
+ NDIS_ERROR_CODE_HARDWARE_FAILURE,
+ 3,
+ handleSrbSsb,
+ IBMTOK_ERRMSG_BRINGUP_FAILURE,
+ (ULONG)RegValue
+ );
+
+ return(NDIS_STATUS_ADAPTER_NOT_FOUND);
+
+
+ }
+
+ } else {
+
+ Adapter->FirstInitialization = FALSE;
+ Adapter->BringUp = TRUE;
+
+ }
+
+ NdisReadRegisterUchar(&(BringUpSrb->InitStatus), &RegValue);
+
+// The following routine assumes that the AutoRingSpeed keyword is set in
+// the registry. If the adapter doesn't support RingSpeedListen, turn off flag.
+
+
+ if (!(RegValue & RINGSPEEDLISTEN)) {
+
+ Adapter->RingSpeedListen = FALSE;
+
+#if DBG
+ if (IbmtokDbg) DbgPrint("IBMTOK: Adapter doesn't support Ring Speed Listen.\n");
+#endif
+
+ }
+
+ if (RegValue & 0x01) {
+
+#if DBG
+ if (IbmtokDbg) DbgPrint("IBMTOK: 16 Mbps\n");
+#endif
+
+ Adapter->Running16Mbps = TRUE;
+
+ } else {
+
+ Adapter->Running16Mbps = FALSE;
+
+ }
+
+ //
+ // ZZZ: This code assumes that there is no shared ram paging and
+ // that the MappedSharedRam is all that is available.
+ //
+
+
+#if DBG
+ if (IbmtokDbg) DbgPrint( "IBMTOK: shared RAM size is %x (%d)\n", Adapter->MappedSharedRam, Adapter->MappedSharedRam );
+#endif
+ if (Adapter->MappedSharedRam > 0x2000){
+
+ ULONG RamAvailable;
+ UCHAR NumTransmitBuffers = (UCHAR)Adapter->NumberOfTransmitBuffers;
+
+ //
+ // 2096 is the amount of shared ram that is current sucked
+ // up by the areas found on page 7-27 of the Tech. Ref.
+ //
+ //
+
+ RamAvailable = Adapter->MappedSharedRam;
+
+ if (Adapter->MappedSharedRam == 0x10000){
+
+ //
+ // Subtract an extra 8K to account for when we map
+ // MMIO space to the top 8K of RAM.
+ //
+
+ RamAvailable = RamAvailable - 2096 - 0x2000;
+
+ } else {
+
+ RamAvailable = RamAvailable - 1584;
+
+ }
+#if DBG
+ if (IbmtokDbg) DbgPrint( "IBMTOK: RAM available is %x (%d)\n", RamAvailable, RamAvailable );
+#endif
+
+ //
+ // The card has more than 8K of ram, so adjust
+ // transmit buffer size to abuse this.
+ //
+
+ if (Adapter->Running16Mbps) {
+
+ //
+ // Use the maximum allowed
+ //
+
+ Adapter->TransmitBufferLength = Adapter->Max16MbpsDhb;
+#if DBG
+ if (IbmtokDbg) DbgPrint( "IBMTOK: 16 MB ring. Transmit buffer length is %x (%d)\n", Adapter->TransmitBufferLength, Adapter->TransmitBufferLength );
+#endif
+
+ } else {
+
+ //
+ // Use the maximum allowed
+ //
+ Adapter->TransmitBufferLength = Adapter->Max4MbpsDhb;
+#if DBG
+ if (IbmtokDbg) DbgPrint( "IBMTOK: 4 MB ring. Transmit buffer length is %x (%d)\n", Adapter->TransmitBufferLength, Adapter->TransmitBufferLength );
+#endif
+
+ }
+
+ //
+ // First we subtract off buffer space for receiving the
+ // maximum sized packet that can be on the wire. This is
+ // the *minimum* number of receive buffers and may be
+ // modified below if the transmit space does not take up
+ // the rest.
+ //
+
+#if DBG
+ if (IbmtokDbg) DbgPrint( "IBMTOK: Receive buffer length is %x (%d)\n", Adapter->ReceiveBufferLength, Adapter->ReceiveBufferLength );
+#endif
+ if (RamAvailable < Adapter->TransmitBufferLength) {
+
+ //
+ // There is not enough buffer space for even a single maximum
+ // sized frame. So, just divide the buffer space into two
+ // equally sized areas -- receive and transmit.
+ //
+
+ Adapter->NumberOfReceiveBuffers = (USHORT)((RamAvailable / 2) /
+ Adapter->ReceiveBufferLength)
+ + 1;
+#if DBG
+ if (IbmtokDbg) DbgPrint( "IBMTOK: RAM too small. # receive buffers is %x (%d)\n", Adapter->NumberOfReceiveBuffers, Adapter->NumberOfReceiveBuffers );
+#endif
+
+ } else {
+
+ Adapter->NumberOfReceiveBuffers = (USHORT)(Adapter->TransmitBufferLength /
+ Adapter->ReceiveBufferLength) + 1;
+#if DBG
+ if (IbmtokDbg) DbgPrint( "IBMTOK: RAM large enough. # receive buffers is %x (%d)\n", Adapter->NumberOfReceiveBuffers, Adapter->NumberOfReceiveBuffers );
+#endif
+
+ }
+
+ RamAvailable = RamAvailable -
+ (Adapter->NumberOfReceiveBuffers * Adapter->ReceiveBufferLength);
+#if DBG
+ if (IbmtokDbg) {
+ DbgPrint( "IBMTOK: RAM available for transmit is %x (%d)\n", RamAvailable, RamAvailable );
+ DbgPrint( "IBMTOK: # transmit buffers is %x (%d)\n", NumTransmitBuffers, NumTransmitBuffers );
+ }
+#endif
+
+ if (Adapter->TransmitBufferLength > (RamAvailable / NumTransmitBuffers)) {
+
+ if ((RamAvailable / NumTransmitBuffers) < 0x1000) {
+
+ Adapter->TransmitBufferLength = 0x800;
+
+ } else if ((RamAvailable / NumTransmitBuffers) < 0x2000) {
+
+ Adapter->TransmitBufferLength = 0x1000;
+
+ } else if ((RamAvailable / NumTransmitBuffers) < 0x4000) {
+
+ Adapter->TransmitBufferLength = 0x2000;
+
+ } else {
+
+ Adapter->TransmitBufferLength = 0x4000;
+
+ }
+
+#if DBG
+ if (IbmtokDbg) DbgPrint( "IBMTOK: RAM too small. Transmit buffer length is %x (%d)\n", Adapter->TransmitBufferLength, Adapter->TransmitBufferLength );
+#endif
+ }
+
+
+ //
+ // If computed value is greater than the value that the
+ // registry allows, then use the registry value.
+ //
+
+#if DBG
+ if (IbmtokDbg) DbgPrint( "IBMTOK: Original max transmit length is %x (%d)\n", Adapter->MaxTransmittablePacket, Adapter->MaxTransmittablePacket );
+#endif
+ if (Adapter->TransmitBufferLength > Adapter->MaxTransmittablePacket) {
+
+ Adapter->TransmitBufferLength = Adapter->MaxTransmittablePacket;
+#if DBG
+ if (IbmtokDbg) DbgPrint( "IBMTOK: Max too small. Transmit buffer length is %x (%d)\n", Adapter->TransmitBufferLength, Adapter->TransmitBufferLength );
+#endif
+
+ }
+
+ Adapter->MaxTransmittablePacket = Adapter->TransmitBufferLength - 6;
+#if DBG
+ if (IbmtokDbg) DbgPrint( "IBMTOK: New max transmit length is %x (%d)\n", Adapter->MaxTransmittablePacket, Adapter->MaxTransmittablePacket );
+#endif
+
+ //
+ // Remove space taken up by transmit buffers.
+ //
+
+ RamAvailable = RamAvailable - ((ULONG)NumTransmitBuffers *
+ (ULONG)Adapter->TransmitBufferLength);
+
+ //
+ // Add in any left over space for receive buffers.
+ //
+
+ Adapter->NumberOfReceiveBuffers += (USHORT)(RamAvailable /
+ Adapter->ReceiveBufferLength);
+#if DBG
+ if (IbmtokDbg) DbgPrint( "IBMTOK: New # receive buffers is %x (%d)\n", Adapter->NumberOfReceiveBuffers, Adapter->NumberOfReceiveBuffers );
+#endif
+
+ } else {
+
+ Adapter->TransmitBufferLength = 0x800;
+ Adapter->NumberOfTransmitBuffers = 1;
+#if DBG
+ if (IbmtokDbg) {
+ DbgPrint( "IBMTOK: Only 8K shared RAM. Transmit buffer length is %x (%d)\n", Adapter->TransmitBufferLength, Adapter->TransmitBufferLength );
+ DbgPrint( "IBMTOK: Transmit buffer length is %x (%d)\n", Adapter->TransmitBufferLength, Adapter->TransmitBufferLength );
+ }
+#endif
+
+ //
+ // There is only 8K of buffer space, which is not enough space for
+ // receiving and transmitting packets on even a 4Mbit ring. So,
+ // use some reasonable values for transmit and receive space.
+ //
+
+ // If computed value is greater than the value that the
+ // registry allows, then use the registry value.
+ //
+
+#if DBG
+ if (IbmtokDbg) DbgPrint( "IBMTOK: Original max transmit length is %x (%d)\n", Adapter->MaxTransmittablePacket, Adapter->MaxTransmittablePacket );
+#endif
+ if (Adapter->TransmitBufferLength > Adapter->MaxTransmittablePacket) {
+
+ Adapter->TransmitBufferLength = Adapter->MaxTransmittablePacket;
+#if DBG
+ if (IbmtokDbg) DbgPrint( "IBMTOK: Max too small. Transmit buffer length is %x (%d)\n", Adapter->TransmitBufferLength, Adapter->TransmitBufferLength );
+#endif
+
+ }
+
+ Adapter->MaxTransmittablePacket = Adapter->TransmitBufferLength - 6;
+
+ Adapter->NumberOfReceiveBuffers = 15;
+#if DBG
+ if (IbmtokDbg) {
+ DbgPrint( "IBMTOK: New max transmit length is %x (%d)\n", Adapter->MaxTransmittablePacket, Adapter->MaxTransmittablePacket );
+ DbgPrint( "IBMTOK: # receive buffers is %x (%d)\n", Adapter->NumberOfReceiveBuffers, Adapter->NumberOfReceiveBuffers );
+ }
+#endif
+
+ }
+
+#if DBG
+ if (IbmtokDbg) {
+ DbgPrint("IBMTOK: Space: 0x%x, # Rcv: 0x%x, TransmitSize: 0x%x\n",
+ Adapter->RrrLowValue,
+ Adapter->NumberOfReceiveBuffers,
+ Adapter->MaxTransmittablePacket
+ );
+ }
+#endif
+
+ NdisReadRegisterUshort(&(BringUpSrb->EncodedAddressPointer), &RegValue);
+
+ EncodedAddress = (PUCHAR)
+ SRAM_PTR_TO_PVOID(Adapter,RegValue);
+
+ IBMTOK_MOVE_FROM_MAPPED_MEMORY(Adapter->PermanentNetworkAddress, EncodedAddress,
+ TR_LENGTH_OF_ADDRESS);
+
+
+ if ((Adapter->NetworkAddress[0] == 0x00) &&
+ (Adapter->NetworkAddress[1] == 0x00) &&
+ (Adapter->NetworkAddress[2] == 0x00) &&
+ (Adapter->NetworkAddress[3] == 0x00) &&
+ (Adapter->NetworkAddress[4] == 0x00) &&
+ (Adapter->NetworkAddress[5] == 0x00)) {
+
+
+ IBMTOK_MOVE_FROM_MAPPED_MEMORY(Adapter->NetworkAddress, EncodedAddress,
+ TR_LENGTH_OF_ADDRESS);
+ }
+
+ //
+ // If required, we have to zero the upper section
+ // of the Shared RAM now.
+ //
+ //
+ // THIS DOESN'T WORK! It hangs the system while
+ // zeroing the first address. (One gets an infinite number of
+ // hardware interrupts w/o any reason)
+ //
+
+#if 0
+ if (Adapter->UpperSharedRamZero) {
+
+ PUCHAR ZeroPointer;
+ UINT i;
+ PUCHAR OldSharedRam;
+ NDIS_PHYSICAL_ADDRESS PhysicalAddress;
+
+#if DBG
+ if (IbmtokDbg) DbgPrint("IBMTOK: Zeroing Memory\n");
+#endif
+
+
+ if (Adapter->MappedSharedRam < 0x10000) {
+
+ //
+ // This portion of memory is not currently mapped, so do it.
+ //
+
+ OldSharedRam = Adapter->SharedRam;
+
+ NdisSetPhysicalAddressHigh(PhysicalAddress, 0);
+ NdisSetPhysicalAddressLow(PhysicalAddress, (Adapter->RrrLowValue << 12) + (0x10000 - 512));
+
+ NdisMapIoSpace(
+ &Status,
+ &(Adapter->SharedRam),
+ Adapter->NdisAdapterHandle,
+ PhysicalAddress,
+ 512);
+
+ if (Status != NDIS_STATUS_SUCCESS) {
+
+ NdisWriteErrorLogEntry(
+ Adapter->NdisAdapterHandle,
+ NDIS_ERROR_CODE_RESOURCE_CONFLICT,
+ 0
+ );
+
+ return(Status);
+
+ }
+
+ }
+
+ if (Adapter->SharedRamPaging){
+
+ SETUP_SRPR(Adapter, SHARED_RAM_ZERO_OFFSET);
+
+#if DBG
+ if (IbmtokDbg) DbgPrint("IBMTOK: Shared RAM paging enabled\n");
+#endif
+
+ ZeroPointer =
+ SHARED_RAM_ADDRESS(Adapter,
+ SHARED_RAM_LOW_BITS(SHARED_RAM_ZERO_OFFSET));
+
+ } else {
+
+ if (Adapter->MappedSharedRam < 0x10000) {
+
+ //
+ // No offset for this portion, since we just mapped it.
+ //
+ //
+
+ ZeroPointer = SHARED_RAM_ADDRESS(Adapter, 0);
+
+ } else {
+
+ ZeroPointer =
+ SHARED_RAM_ADDRESS(Adapter, SHARED_RAM_ZERO_OFFSET);
+
+ }
+
+ }
+
+ for (i=0; i<SHARED_RAM_ZERO_LENGTH; i++) {
+
+ NdisWriteRegisterUchar(&(ZeroPointer[i]), 0x00);
+
+ }
+
+ if (Adapter->MappedSharedRam < 0x10000) {
+
+ //
+ // Unmap it
+ //
+
+ NdisUnmapIoSpace(Adapter->NdisAdapterHandle,
+ Adapter->SharedRam,
+ 512);
+
+ Adapter->SharedRam = OldSharedRam;
+
+ }
+
+ }
+#endif
+
+
+ //
+ // Now set the timer to the maximum...we still need it
+ // as a card heartbeat.
+ //
+
+ WRITE_ADAPTER_REGISTER(Adapter, TVR_HIGH, 0xff);
+
+ return NDIS_STATUS_SUCCESS;
+
+ }
+
+}
+
+
+#pragma NDIS_PAGABLE_FUNCTION(IbmtokOpenAdapter)
+
+STATIC
+NDIS_STATUS
+IbmtokOpenAdapter(
+ OUT PNDIS_STATUS OpenErrorStatus,
+ OUT NDIS_HANDLE *MacBindingHandle,
+ OUT PUINT SelectedMediumIndex,
+ IN PNDIS_MEDIUM MediumArray,
+ IN UINT MediumArraySize,
+ IN NDIS_HANDLE NdisBindingContext,
+ IN NDIS_HANDLE MacAdapterContext,
+ IN UINT OpenOptions,
+ IN PSTRING AddressingInformation OPTIONAL
+ )
+
+/*++
+
+Routine Description:
+
+ OpenErrorStatus - Returns more information about the error status. In
+ this card it is not used, since this code returns either success or
+ pending, no failure is possible.
+
+ This routine is used to create an open instance of an adapter, in effect
+ creating a binding between an upper-level module and the MAC module over
+ the adapter.
+
+Arguments:
+
+ OpenErrorStatus - Returns more information about the error status. In
+ this card it is not used, since this code returns either success or
+ pending, no failure is possible.
+
+ MacBindingHandle - A pointer to a location in which the MAC stores
+ a context value that it uses to represent this binding.
+
+
+ SelectedMediumIndex - An index into the MediumArray of the medium
+ typedef that the MAC wishes to viewed as.
+
+ MediumArray - An array of medium types which the protocol supports.
+
+ MediumArraySize - The number of elements in MediumArray.
+
+ NdisBindingContext - A value to be recorded by the MAC and passed as
+ context whenever an indication is delivered by the MAC for this binding.
+
+ MacAdapterContext - The value associated with the adapter that is being
+ opened when the MAC registered the adapter with NdisRegisterAdapter.
+
+ IN UINT OpenOptions,
+
+ AddressingInformation - An optional pointer to a variable length string
+ containing hardware-specific information that can be used to program the
+ device. (This is not used by this MAC.)
+
+Return Value:
+
+ The function value is the status of the operation. If the MAC does not
+ complete this request synchronously, the value would be
+ NDIS_STATUS_PENDING.
+
+
+--*/
+
+{
+
+ //
+ // The IBMTOK_ADAPTER that this open binding should belong too.
+ //
+ PIBMTOK_ADAPTER Adapter;
+
+ //
+ // Holds the status that should be returned to the caller.
+ //
+ NDIS_STATUS StatusToReturn = NDIS_STATUS_SUCCESS;
+
+ //
+ // Pointer to the space allocated for the binding.
+ //
+ PIBMTOK_OPEN NewOpen;
+
+ //
+ // Generic loop variable
+ //
+ UINT i;
+
+
+ UNREFERENCED_PARAMETER(AddressingInformation);
+
+ *OpenErrorStatus = (NDIS_STATUS)0;
+
+ //
+ // Search for the medium type (token ring)
+ //
+
+ for(i=0; i < MediumArraySize; i++){
+
+ if (MediumArray[i] == NdisMedium802_5){
+
+ break;
+
+ }
+
+ }
+
+ if (i == MediumArraySize){
+
+ return(NDIS_STATUS_UNSUPPORTED_MEDIA);
+
+ }
+
+ *SelectedMediumIndex = i;
+
+ Adapter = PIBMTOK_ADAPTER_FROM_CONTEXT_HANDLE(MacAdapterContext);
+
+ NdisInterlockedAddUlong((PULONG)&Adapter->References, 1, &Adapter->Lock);
+
+ //
+ // Allocate the space for the open binding. Fill in the fields.
+ //
+
+ if (IBMTOK_ALLOC_PHYS(&NewOpen, sizeof(IBMTOK_OPEN)) ==
+ NDIS_STATUS_SUCCESS){
+
+ *MacBindingHandle = BINDING_HANDLE_FROM_PIBMTOK_OPEN(NewOpen);
+ InitializeListHead(&NewOpen->OpenList);
+ NewOpen->NdisBindingContext = NdisBindingContext;
+ NewOpen->References = 0;
+ NewOpen->BindingShuttingDown = FALSE;
+ NewOpen->OwningIbmtok = Adapter;
+ NewOpen->OpenPending = FALSE;
+
+ NdisAcquireSpinLock(&Adapter->Lock);
+ if (!TrNoteFilterOpenAdapter(
+ NewOpen->OwningIbmtok->FilterDB,
+ NewOpen,
+ NdisBindingContext,
+ &NewOpen->NdisFilterHandle
+ )) {
+
+ NdisReleaseSpinLock(&Adapter->Lock);
+
+ NdisWriteErrorLogEntry(
+ Adapter->NdisAdapterHandle,
+ NDIS_ERROR_CODE_OUT_OF_RESOURCES,
+ 2,
+ openAdapter,
+ IBMTOK_ERRMSG_OPEN_DB
+ );
+
+ IBMTOK_FREE_PHYS(NewOpen, sizeof(IBMTOK_OPEN));
+
+ StatusToReturn = NDIS_STATUS_FAILURE;
+ NdisAcquireSpinLock(&Adapter->Lock);
+
+ } else {
+
+ //
+ // Everything has been filled in. Synchronize access to the
+ // adapter block and link the new open adapter in and increment
+ // the opens reference count to account for the fact that the
+ // filter routines have a "reference" to the open.
+ //
+
+ NewOpen->LookAhead = IBMTOK_MAX_LOOKAHEAD;
+
+ Adapter->LookAhead = IBMTOK_MAX_LOOKAHEAD;
+
+ InsertTailList(&Adapter->OpenBindings,&NewOpen->OpenList);
+ NewOpen->References++;
+
+ //
+ // Now see if the adapter is currently open.
+ //
+
+ if (Adapter->AdapterNotOpen) {
+
+ //
+ // The adapter is not open, so this has to pend.
+ //
+ NewOpen->OpenPending = TRUE;
+
+ StatusToReturn = NDIS_STATUS_PENDING;
+
+ if (!Adapter->OpenInProgress) {
+
+ //
+ // Fill in the SRB for the open if this is the first
+ // one for the card.
+ //
+
+ PSRB_OPEN_ADAPTER OpenSrb;
+
+ IF_LOG('o');
+
+ Adapter->OpenInProgress = TRUE;
+ Adapter->CurrentRingState = NdisRingStateOpening;
+
+ NdisReleaseSpinLock(&Adapter->Lock);
+
+ OpenSrb = (PSRB_OPEN_ADAPTER)
+ (Adapter->SharedRam + Adapter->InitialWrbOffset);
+
+ IBMTOK_ZERO_MAPPED_MEMORY(OpenSrb, sizeof(SRB_OPEN_ADAPTER));
+
+ NdisWriteRegisterUchar(
+ (PUCHAR)&OpenSrb->Command,
+ SRB_CMD_OPEN_ADAPTER);
+
+ NdisWriteRegisterUshort(
+ (PUSHORT)&OpenSrb->OpenOptions,
+ (USHORT)(OPEN_CONTENDER |
+ (Adapter->RingSpeedListen ?
+ OPEN_REMOTE_PROGRAM_LOAD :
+ 0))
+ );
+
+ for (i=0; i < TR_LENGTH_OF_ADDRESS; i++) {
+ NdisWriteRegisterUchar((PCHAR)&OpenSrb->NodeAddress[i],
+ Adapter->NetworkAddress[i]
+ );
+ }
+
+ WRITE_IBMSHORT(OpenSrb->ReceiveBufferNum,
+ Adapter->NumberOfReceiveBuffers);
+ WRITE_IBMSHORT(OpenSrb->ReceiveBufferLen,
+ Adapter->ReceiveBufferLength);
+
+ WRITE_IBMSHORT(OpenSrb->TransmitBufferLen,
+ Adapter->TransmitBufferLength);
+ NdisWriteRegisterUchar(
+ (PUCHAR)&OpenSrb->TransmitBufferNum,
+ (UCHAR)Adapter->NumberOfTransmitBuffers);
+
+ WRITE_ADAPTER_REGISTER(Adapter, ISRA_HIGH_SET,
+ ISRA_HIGH_COMMAND_IN_SRB);
+
+ NdisAcquireSpinLock(&Adapter->Lock);
+
+ }
+
+ }
+
+ }
+
+ } else {
+
+ NdisWriteErrorLogEntry(
+ Adapter->NdisAdapterHandle,
+ NDIS_ERROR_CODE_OUT_OF_RESOURCES,
+ 2,
+ openAdapter,
+ IBMTOK_ERRMSG_ALLOC_MEM
+ );
+
+ return(NDIS_STATUS_RESOURCES);
+
+ }
+
+
+
+
+ //
+ // This macro assumes it is called with the lock held,
+ // and releases it.
+ //
+
+ IBMTOK_DO_DEFERRED(Adapter);
+ return StatusToReturn;
+}
+
+
+VOID
+IbmtokAdjustMaxLookAhead(
+ IN PIBMTOK_ADAPTER Adapter
+ )
+/*++
+
+Routine Description:
+
+ This routine finds the open with the maximum lookahead value and
+ stores that in the adapter block.
+
+Arguments:
+
+ Adapter - A pointer to the adapter block.
+
+Returns:
+
+ None.
+
+--*/
+{
+ ULONG CurrentMax = 0;
+ PLIST_ENTRY CurrentLink;
+ PIBMTOK_OPEN TempOpen;
+
+ CurrentLink = Adapter->OpenBindings.Flink;
+
+ while (CurrentLink != &(Adapter->OpenBindings)){
+
+ TempOpen = CONTAINING_RECORD(
+ CurrentLink,
+ IBMTOK_OPEN,
+ OpenList
+ );
+
+ if (TempOpen->LookAhead > CurrentMax) {
+
+ CurrentMax = TempOpen->LookAhead;
+
+ }
+
+ CurrentLink = CurrentLink->Flink;
+
+ }
+
+ if (CurrentMax == 0) {
+
+ CurrentMax = IBMTOK_MAX_LOOKAHEAD;
+
+ }
+
+ Adapter->LookAhead = CurrentMax;
+
+}
+
+STATIC
+NDIS_STATUS
+IbmtokCloseAdapter(
+ IN NDIS_HANDLE MacBindingHandle
+ )
+
+/*++
+
+Routine Description:
+
+ This routine causes the MAC to close an open handle (binding).
+
+Arguments:
+
+ MacBindingHandle - The context value returned by the MAC when the
+ adapter was opened. In reality it is a PIBMTOK_OPEN.
+
+Return Value:
+
+ The function value is the status of the operation.
+
+
+--*/
+
+{
+
+ PIBMTOK_ADAPTER Adapter;
+ PIBMTOK_OPEN Open;
+
+ NDIS_STATUS StatusToReturn = NDIS_STATUS_SUCCESS;
+
+ Adapter = PIBMTOK_ADAPTER_FROM_BINDING_HANDLE(MacBindingHandle);
+ Open = PIBMTOK_OPEN_FROM_BINDING_HANDLE(MacBindingHandle);
+
+ //
+ // Hold the lock while we update the reference counts for the
+ // adapter and the open.
+ //
+
+ NdisAcquireSpinLock(&Adapter->Lock);
+ Adapter->References++;
+
+ if (!Open->BindingShuttingDown) {
+
+ Open->References++;
+
+ StatusToReturn = TrDeleteFilterOpenAdapter(
+ Adapter->FilterDB,
+ Open->NdisFilterHandle,
+ NULL
+ );
+
+ //
+ // If the status is successful that merely implies that
+ // we were able to delete the reference to the open binding
+ // from the filtering code. If we have a successful status
+ // at this point we still need to check whether the reference
+ // count to determine whether we can close.
+ //
+ //
+ // The delete filter routine can return a "special" status
+ // that indicates that there is a current NdisIndicateReceive
+ // on this binding.
+ //
+
+
+ if (StatusToReturn == NDIS_STATUS_SUCCESS)
+ {
+ //
+ // Check whether the reference count is two. If
+ // it is then we can get rid of the memory for
+ // this open.
+ //
+ // A count of two indicates one for this routine
+ // and one for the filter which we *know* we can
+ // get rid of.
+ //
+
+ if (Open->References == 2) {
+
+ RemoveEntryList(&Open->OpenList);
+
+ //
+ // We are the only reference to the open. Remove
+ // it from the open list and delete the memory.
+ //
+
+ RemoveEntryList(&Open->OpenList);
+
+ if (Open->LookAhead == Adapter->LookAhead) {
+
+ IbmtokAdjustMaxLookAhead(Adapter);
+
+ }
+
+ IBMTOK_FREE_PHYS(Open,sizeof(IBMTOK_OPEN));
+
+ } else {
+
+ Open->BindingShuttingDown = TRUE;
+
+ //
+ // Remove the open from the open list and put it on
+ // the closing list.
+ //
+
+ RemoveEntryList(&Open->OpenList);
+ InsertTailList(&Adapter->CloseList,&Open->OpenList);
+
+ //
+ // Account for this routines reference to the open
+ // as well as reference because of the filtering.
+ //
+
+ Open->References -= 2;
+
+ //
+ // Change the status to indicate that we will
+ // be closing this later.
+ //
+
+ StatusToReturn = NDIS_STATUS_PENDING;
+
+ }
+
+ }
+ else if (StatusToReturn == NDIS_STATUS_PENDING)
+ {
+ //
+ // If it pended, there may be
+ // operations queued.
+ //
+ if (Adapter->CardType == IBM_TOKEN_RING_PCMCIA)
+ {
+ //
+ // Check if the card is still in the machine
+ //
+ ULONG AdapterId;
+ ULONG PcIoBusId = 0x5049434f;
+ UINT j;
+ UCHAR TmpUchar;
+
+ AdapterId = 0;
+
+ for (j = 0; j < 16; j += 2)
+ {
+ READ_ADAPTER_REGISTER(
+ Adapter,
+ CHANNEL_IDENTIFIER + (16 + j),
+ &TmpUchar
+ );
+
+ AdapterId = (AdapterId << 4) + (TmpUchar & 0x0f);
+ }
+
+ if (AdapterId != PcIoBusId)
+ {
+ Adapter->InvalidValue = TRUE;
+#if DBG
+ if (IbmtokDbg)
+ DbgPrint("IBMTOK: Card was removed or undocked\n");
+#endif
+ }
+ else
+ {
+ Adapter->InvalidValue = FALSE;
+ }
+ }
+
+ if (Adapter->InvalidValue)
+ {
+ IbmtokAbortPending (Adapter, STATUS_SUCCESS);
+ }
+ else
+ {
+ IbmtokProcessSrbRequests(Adapter);
+ }
+
+ //
+ // Now start closing down this open.
+ //
+
+ Open->BindingShuttingDown = TRUE;
+
+ //
+ // Remove the open from the open list and put it on
+ // the closing list.
+ //
+
+ RemoveEntryList(&Open->OpenList);
+ InsertTailList(&Adapter->CloseList,&Open->OpenList);
+
+ //
+ // Account for this routines reference to the open
+ // as well as reference because of the filtering.
+ //
+
+ Open->References -= 2;
+
+ } else if (StatusToReturn == NDIS_STATUS_CLOSING_INDICATING) {
+
+ //
+ // When we have this status it indicates that the filtering
+ // code was currently doing an NdisIndicateReceive. It
+ // would not be wise to delete the memory for the open at
+ // this point. The filtering code will call our close action
+ // routine upon return from NdisIndicateReceive and that
+ // action routine will decrement the reference count for
+ // the open.
+ //
+
+ Open->BindingShuttingDown = TRUE;
+
+ //
+ // This status is private to the filtering routine. Just
+ // tell the caller the the close is pending.
+ //
+
+ StatusToReturn = NDIS_STATUS_PENDING;
+
+ //
+ // Remove the open from the open list and put it on
+ // the closing list.
+ //
+
+ RemoveEntryList(&Open->OpenList);
+ InsertTailList(&Adapter->CloseList,&Open->OpenList);
+
+ //
+ // Account for this routines reference to the open.
+ //
+
+ Open->References--;
+
+ } else if (StatusToReturn == NDIS_STATUS_RESET_IN_PROGRESS) {
+
+ Open->BindingShuttingDown = TRUE;
+
+ //
+ // Remove the open from the open list and put it on
+ // the closing list.
+ //
+
+ RemoveEntryList(&Open->OpenList);
+ InsertTailList(&Adapter->CloseDuringResetList,&Open->OpenList);
+
+
+ //
+ // Account for this routines reference to the open.
+ //
+
+ Open->References--;
+
+ StatusToReturn = NDIS_STATUS_PENDING;
+
+ } else {
+
+ NdisWriteErrorLogEntry(
+ Adapter->NdisAdapterHandle,
+ NDIS_ERROR_CODE_DRIVER_FAILURE,
+ 2,
+ IBMTOK_ERRMSG_INVALID_STATUS,
+ 1
+ );
+
+ }
+
+ } else {
+
+ StatusToReturn = NDIS_STATUS_CLOSING;
+
+ }
+
+
+ //
+ // This macro assumes it is called with the lock held,
+ // and releases it.
+ //
+
+ IBMTOK_DO_DEFERRED(Adapter);
+ return StatusToReturn;
+
+}
+
+STATIC
+NDIS_STATUS
+IbmtokRequest(
+ IN NDIS_HANDLE MacBindingHandle,
+ IN PNDIS_REQUEST NdisRequest
+ )
+
+/*++
+
+Routine Description:
+
+ The IbmtokRequest allows a protocol to query and set information
+ about the MAC.
+
+Arguments:
+
+ MacBindingHandle - The context value returned by the MAC when the
+ adapter was opened. In reality, it is a pointer to IBMTOK_OPEN.
+
+ NdisRequest - A structure which contains the request type (Set or
+ Query), an array of operations to perform, and an array for holding
+ the results of the operations.
+
+Return Value:
+
+ The function value is the status of the operation.
+
+--*/
+
+{
+ NDIS_STATUS StatusToReturn = NDIS_STATUS_SUCCESS;
+
+ PIBMTOK_ADAPTER Adapter = PIBMTOK_ADAPTER_FROM_BINDING_HANDLE(MacBindingHandle);
+ PIBMTOK_OPEN Open = PIBMTOK_OPEN_FROM_BINDING_HANDLE(MacBindingHandle);
+
+ NdisAcquireSpinLock(&(Adapter->Lock));
+
+ Adapter->References++;
+
+ //
+ // Process request
+ //
+
+ if (NdisRequest->RequestType == NdisRequestQueryInformation) {
+
+ StatusToReturn = IbmtokQueryInformation(Adapter, Open, NdisRequest);
+
+ } else if (NdisRequest->RequestType == NdisRequestSetInformation) {
+
+
+ //
+ // Make sure Adapter is in a valid state.
+ //
+
+ if (Adapter->Unplugged) {
+
+ StatusToReturn = NDIS_STATUS_DEVICE_FAILED;
+
+ } else if (!Adapter->NotAcceptingRequests) {
+
+ //
+ // Make sure the open instance is valid
+ //
+
+ if (!Open->BindingShuttingDown) {
+
+ StatusToReturn = IbmtokSetInformation(Adapter,Open,NdisRequest);
+
+ } else {
+
+ StatusToReturn = NDIS_STATUS_CLOSING;
+
+ }
+
+ } else {
+
+ if (Adapter->ResetInProgress) {
+
+ StatusToReturn = NDIS_STATUS_RESET_IN_PROGRESS;
+
+ } else if (Adapter->AdapterNotOpen) {
+
+ StatusToReturn = NDIS_STATUS_FAILURE;
+
+ } else {
+
+ NdisWriteErrorLogEntry(
+ Adapter->NdisAdapterHandle,
+ NDIS_ERROR_CODE_DRIVER_FAILURE,
+ 2,
+ IBMTOK_ERRMSG_INVALID_STATE,
+ 3
+ );
+
+ }
+ }
+ } else {
+
+ StatusToReturn = NDIS_STATUS_NOT_RECOGNIZED;
+
+ }
+
+ IBMTOK_DO_DEFERRED(Adapter);
+
+ return(StatusToReturn);
+
+}
+
+STATIC
+NDIS_STATUS
+IbmtokQueryProtocolInformation(
+ IN PIBMTOK_ADAPTER Adapter,
+ IN PIBMTOK_OPEN Open,
+ IN NDIS_OID Oid,
+ IN BOOLEAN GlobalMode,
+ IN PVOID InfoBuffer,
+ IN UINT BytesLeft,
+ OUT PUINT BytesNeeded,
+ OUT PUINT BytesWritten
+)
+
+/*++
+
+Routine Description:
+
+ The IbmtokQueryProtocolInformation process a Query request for
+ NDIS_OIDs that are specific to a binding about the MAC. Note that
+ some of the OIDs that are specific to bindings are also queryable
+ on a global basis. Rather than recreate this code to handle the
+ global queries, I use a flag to indicate if this is a query for the
+ global data or the binding specific data.
+
+Arguments:
+
+ Adapter - a pointer to the adapter.
+
+ Open - a pointer to the open instance.
+
+ Oid - the NDIS_OID to process.
+
+ GlobalMode - Some of the binding specific information is also used
+ when querying global statistics. This is a flag to specify whether
+ to return the global value, or the binding specific value.
+
+ InfoBuffer - a pointer into the NdisRequest->InformationBuffer
+ into which store the result of the query.
+
+ BytesLeft - the number of bytes left in 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.
+
+ BytesWritten - a pointer to the number of bytes written into the
+ InformationBuffer.
+
+Return Value:
+
+ The function value is the status of the operation.
+
+--*/
+
+{
+ NDIS_MEDIUM Medium = NdisMedium802_5;
+ ULONG GenericULong;
+ USHORT GenericUShort;
+ UCHAR GenericArray[6];
+
+ NDIS_STATUS StatusToReturn = NDIS_STATUS_SUCCESS;
+
+ //
+ // Common variables for pointing to result of query
+ //
+
+ PVOID MoveSource = (PVOID)(&GenericULong);
+ ULONG MoveBytes = sizeof(GenericULong);
+
+ NDIS_HARDWARE_STATUS HardwareStatus = NdisHardwareStatusReady;
+
+ //
+ // General Algorithm:
+ //
+ // Switch(Request)
+ // Get requested information
+ // Store results in a common variable.
+ // Copy result in common variable to result buffer.
+ //
+
+ //
+ // Switch on request type
+ //
+
+ switch (Oid) {
+
+ case OID_GEN_MAC_OPTIONS:
+
+ GenericULong = (ULONG)(NDIS_MAC_OPTION_TRANSFERS_NOT_PEND |
+ NDIS_MAC_OPTION_RECEIVE_SERIALIZED
+ );
+
+ break;
+
+ case OID_GEN_SUPPORTED_LIST:
+
+ if (!GlobalMode){
+ MoveSource = (PVOID)(IbmtokProtocolSupportedOids);
+ MoveBytes = sizeof(IbmtokProtocolSupportedOids);
+ } else {
+ MoveSource = (PVOID)(IbmtokGlobalSupportedOids);
+ MoveBytes = sizeof(IbmtokGlobalSupportedOids);
+ }
+ break;
+
+ case OID_GEN_HARDWARE_STATUS:
+
+
+ if (Adapter->ResetInProgress){
+
+ HardwareStatus = NdisHardwareStatusReset;
+
+ } else if ((Adapter->FirstInitialization) ||
+ (Adapter->OpenInProgress)){
+
+ HardwareStatus = NdisHardwareStatusInitializing;
+
+ } else if (Adapter->NotAcceptingRequests){
+
+ HardwareStatus = NdisHardwareStatusNotReady;
+
+ } else
+ HardwareStatus = NdisHardwareStatusReady;
+
+
+ MoveSource = (PVOID)(&HardwareStatus);
+ MoveBytes = sizeof(NDIS_HARDWARE_STATUS);
+
+ break;
+
+ case OID_GEN_MEDIA_SUPPORTED:
+ case OID_GEN_MEDIA_IN_USE:
+
+ MoveSource = (PVOID) (&Medium);
+ MoveBytes = sizeof(NDIS_MEDIUM);
+ break;
+
+ case OID_GEN_MAXIMUM_LOOKAHEAD:
+
+ GenericULong = IBMTOK_MAX_LOOKAHEAD;
+
+ break;
+
+
+ case OID_GEN_MAXIMUM_FRAME_SIZE:
+ case OID_GEN_MAXIMUM_TOTAL_SIZE:
+
+ GenericULong = (ULONG)(Adapter->MaxTransmittablePacket);
+
+ if (Oid == OID_GEN_MAXIMUM_FRAME_SIZE) {
+
+ //
+ // For the receive frame size, we subtract the minimum
+ // header size from the number.
+ //
+
+ GenericULong -= 14;
+ }
+
+ break;
+
+
+ case OID_GEN_LINK_SPEED:
+
+ GenericULong = (ULONG)(Adapter->Running16Mbps? 160000 : 40000);
+
+ break;
+
+
+ case OID_GEN_TRANSMIT_BUFFER_SPACE:
+
+ GenericULong = (ULONG)(Adapter->NumberOfTransmitBuffers *
+ Adapter->TransmitBufferLength);
+
+ break;
+
+ case OID_GEN_RECEIVE_BUFFER_SPACE:
+
+ GenericULong = (ULONG)(Adapter->NumberOfReceiveBuffers *
+ Adapter->ReceiveBufferLength);
+
+ break;
+
+ case OID_GEN_TRANSMIT_BLOCK_SIZE:
+
+ GenericULong = (ULONG)(Adapter->TransmitBufferLength);
+
+ break;
+
+ case OID_GEN_RECEIVE_BLOCK_SIZE:
+
+ GenericULong = (ULONG)(Adapter->ReceiveBufferLength);
+
+ break;
+
+ case OID_GEN_VENDOR_ID:
+
+ NdisMoveMemory(
+ (PVOID)&GenericULong,
+ Adapter->PermanentNetworkAddress,
+ 3
+ );
+ GenericULong &= 0xFFFFFF00;
+
+ if (Adapter->UsingPcIoBus) {
+
+ GenericULong |= 0x01;
+
+ }
+
+ MoveSource = (PVOID)(&GenericULong);
+ MoveBytes = sizeof(GenericULong);
+ break;
+
+ case OID_GEN_VENDOR_DESCRIPTION:
+
+ if (Adapter->UsingPcIoBus){
+ MoveSource = (PVOID)"Ibm Token Ring Network Card for PC I/O bus.";
+ MoveBytes = 44;
+ } else {
+ MoveSource = (PVOID)"Ibm Token Ring Network Card for MCA bus.";
+ MoveBytes = 41;
+ }
+ break;
+
+ case OID_GEN_DRIVER_VERSION:
+
+ GenericUShort = (USHORT)((IBMTOK_NDIS_MAJOR_VERSION << 8) | IBMTOK_NDIS_MINOR_VERSION);
+
+ MoveSource = (PVOID)(&GenericUShort);
+ MoveBytes = sizeof(GenericUShort);
+ break;
+
+
+ case OID_GEN_CURRENT_PACKET_FILTER:
+
+ if (GlobalMode) {
+
+ GenericULong = (ULONG)(Adapter->CurrentPacketFilter);
+
+ } else {
+
+ GenericULong = (ULONG)(TR_QUERY_PACKET_FILTER(
+ Adapter->FilterDB,
+ Open->NdisFilterHandle));
+
+ }
+
+ break;
+
+ case OID_GEN_CURRENT_LOOKAHEAD:
+
+ if (!GlobalMode){
+
+ GenericULong = Open->LookAhead;
+
+ } else {
+
+ PLIST_ENTRY CurrentLink;
+ PIBMTOK_OPEN TempOpen;
+
+ CurrentLink = Adapter->OpenBindings.Flink;
+
+ GenericULong = 0;
+
+ while (CurrentLink != &(Adapter->OpenBindings)){
+
+ TempOpen = CONTAINING_RECORD(
+ CurrentLink,
+ IBMTOK_OPEN,
+ OpenList
+ );
+
+ if (TempOpen->LookAhead > GenericULong) {
+
+ GenericULong = TempOpen->LookAhead;
+
+ if (GenericULong == IBMTOK_MAX_LOOKAHEAD) {
+
+ break;
+
+ }
+ }
+
+ CurrentLink = CurrentLink->Flink;
+
+ }
+
+ }
+
+ break;
+
+ case OID_802_5_PERMANENT_ADDRESS:
+
+ TR_COPY_NETWORK_ADDRESS((PCHAR)GenericArray,
+ Adapter->PermanentNetworkAddress);
+
+ MoveSource = (PVOID)(GenericArray);
+ MoveBytes = sizeof(Adapter->PermanentNetworkAddress);
+
+ break;
+
+ case OID_802_5_CURRENT_ADDRESS:
+
+ TR_COPY_NETWORK_ADDRESS((PCHAR)GenericArray,
+ Adapter->NetworkAddress);
+
+ MoveSource = (PVOID)(GenericArray);
+ MoveBytes = sizeof(Adapter->NetworkAddress);
+
+ break;
+
+ case OID_802_5_CURRENT_FUNCTIONAL:
+
+ if (!GlobalMode){
+
+ GenericULong = TR_QUERY_FILTER_BINDING_ADDRESS(
+ Adapter->FilterDB,
+ Open->NdisFilterHandle);
+
+ } else {
+
+ GenericULong = Adapter->CurrentCardFunctional & 0xffffffff;
+
+ }
+
+ //
+ // Now we need to reverse the crazy thing.
+ //
+
+ GenericULong = (ULONG)(
+ ((GenericULong >> 24) & 0xFF) |
+ ((GenericULong >> 8) & 0xFF00) |
+ ((GenericULong << 8) & 0xFF0000) |
+ ((GenericULong << 24) & 0xFF000000)
+ );
+
+ break;
+
+ case OID_802_5_CURRENT_GROUP:
+
+ GenericULong = Adapter->CurrentCardGroup & 0xffffffff;
+
+ //
+ // Now we need to reverse the crazy thing.
+ //
+
+ GenericULong = (ULONG)(
+ ((GenericULong >> 24) & 0xFF) |
+ ((GenericULong >> 8) & 0xFF00) |
+ ((GenericULong << 8) & 0xFF0000) |
+ ((GenericULong << 24) & 0xFF000000)
+ );
+
+ break;
+
+ default:
+
+ StatusToReturn = NDIS_STATUS_NOT_SUPPORTED;
+ break;
+ }
+
+ if (StatusToReturn == NDIS_STATUS_SUCCESS){
+
+ if (MoveBytes > BytesLeft){
+
+ //
+ // Not enough room in InformationBuffer. Punt
+ //
+
+ *BytesNeeded = MoveBytes;
+
+ StatusToReturn = NDIS_STATUS_INVALID_LENGTH;
+
+ } else {
+
+ //
+ // Store result.
+ //
+
+ IBMTOK_MOVE_MEMORY(InfoBuffer, MoveSource, MoveBytes);
+
+ (*BytesWritten) += MoveBytes;
+
+ }
+ }
+
+ return(StatusToReturn);
+}
+
+STATIC
+NDIS_STATUS
+IbmtokQueryInformation(
+ IN PIBMTOK_ADAPTER Adapter,
+ IN PIBMTOK_OPEN Open,
+ IN PNDIS_REQUEST NdisRequest
+ )
+/*++
+
+Routine Description:
+
+ The IbmtokQueryInformation is used by IbmtokRequest to query information
+ about the MAC.
+
+Arguments:
+
+ Adapter - A pointer to the adapter.
+
+ Open - A pointer to a particular open instance.
+
+ NdisRequest - A structure which contains the request type (Query),
+ an array of operations to perform, and an array for holding
+ the results of the operations.
+
+Return Value:
+
+ The function value is the status of the operation.
+
+--*/
+
+{
+
+ UINT BytesWritten = 0;
+ UINT BytesNeeded = 0;
+ UINT BytesLeft = NdisRequest->DATA.QUERY_INFORMATION.InformationBufferLength;
+ PUCHAR InfoBuffer = (PUCHAR)(NdisRequest->DATA.QUERY_INFORMATION.InformationBuffer);
+
+ NDIS_STATUS StatusToReturn = NDIS_STATUS_SUCCESS;
+
+
+ StatusToReturn = IbmtokQueryProtocolInformation(
+ Adapter,
+ Open,
+ NdisRequest->DATA.QUERY_INFORMATION.Oid,
+ FALSE,
+ InfoBuffer,
+ BytesLeft,
+ &BytesNeeded,
+ &BytesWritten
+ );
+
+ NdisRequest->DATA.QUERY_INFORMATION.BytesWritten = BytesWritten;
+
+ NdisRequest->DATA.QUERY_INFORMATION.BytesNeeded = BytesNeeded;
+
+ return(StatusToReturn);
+}
+
+STATIC
+NDIS_STATUS
+IbmtokSetInformation(
+ IN PIBMTOK_ADAPTER Adapter,
+ IN PIBMTOK_OPEN Open,
+ IN PNDIS_REQUEST NdisRequest
+ )
+/*++
+
+Routine Description:
+
+ The IbmtokSetInformation is used by IbmtokRequest to set information
+ about the MAC.
+
+Arguments:
+
+ Adapter - A pointer to the adapter.
+
+ Open - A pointer to an open instance.
+
+ NdisRequest - A structure which contains the request type (Set),
+ an array of operations to perform, and an array for holding
+ the results of the operations.
+
+Return Value:
+
+ The function value is the status of the operation.
+
+--*/
+
+{
+
+ //
+ // General Algorithm:
+ //
+ // Verify length
+ // Switch(Request)
+ // Process Request
+ //
+
+ UINT BytesNeeded = 0;
+ UINT BytesLeft = NdisRequest->DATA.SET_INFORMATION.InformationBufferLength;
+ PUCHAR InfoBuffer = (PUCHAR)(NdisRequest->DATA.SET_INFORMATION.InformationBuffer);
+
+ //
+ // Variables for the request
+ //
+
+ NDIS_OID Oid;
+ UINT OidLength;
+
+ //
+ // Variables for holding the new values to be used.
+ //
+
+ ULONG LookAhead;
+ ULONG Filter;
+
+ NDIS_STATUS StatusToReturn = NDIS_STATUS_SUCCESS;
+
+
+ //
+ // Get Oid and Length of request
+ //
+
+ Oid = NdisRequest->DATA.SET_INFORMATION.Oid;
+
+ OidLength = BytesLeft;
+
+ //
+ // Verify length
+ //
+
+ if (OidLength != 4){
+
+ StatusToReturn = NDIS_STATUS_INVALID_LENGTH;
+
+ NdisRequest->DATA.SET_INFORMATION.BytesRead = 0;
+ NdisRequest->DATA.SET_INFORMATION.BytesNeeded = 0;
+
+ return(StatusToReturn);
+ }
+
+ switch (Oid) {
+
+ case OID_802_5_CURRENT_FUNCTIONAL:
+
+ StatusToReturn = IbmtokChangeFunctionalAddress(
+ Adapter,
+ Open,
+ NdisRequest,
+ InfoBuffer
+ );
+
+ break;
+
+ case OID_GEN_CURRENT_PACKET_FILTER:
+
+ IBMTOK_MOVE_MEMORY(&Filter, InfoBuffer, 4);
+
+ StatusToReturn = IbmtokSetPacketFilter(Adapter,
+ Open,
+ NdisRequest,
+ Filter);
+
+ break;
+
+ case OID_802_5_CURRENT_GROUP:
+
+ StatusToReturn = IbmtokSetGroupAddress(
+ Adapter,
+ Open,
+ NdisRequest,
+ InfoBuffer
+ );
+
+ break;
+
+
+ case OID_GEN_PROTOCOL_OPTIONS:
+
+ StatusToReturn = NDIS_STATUS_SUCCESS;
+
+ break;
+
+ case OID_GEN_CURRENT_LOOKAHEAD:
+
+ IBMTOK_MOVE_MEMORY(&LookAhead, InfoBuffer, 4);
+
+ if (LookAhead <= IBMTOK_MAX_LOOKAHEAD) {
+
+ if (LookAhead > Adapter->LookAhead) {
+
+ Open->LookAhead = LookAhead;
+
+ Adapter->LookAhead = LookAhead;
+
+ } else {
+
+ if ((Open->LookAhead == Adapter->LookAhead) &&
+ (LookAhead < Open->LookAhead)) {
+
+ Open->LookAhead = LookAhead;
+
+ IbmtokAdjustMaxLookAhead(Adapter);
+
+ } else {
+
+ Open->LookAhead = LookAhead;
+
+ }
+
+ }
+
+ } else {
+
+ StatusToReturn = NDIS_STATUS_INVALID_LENGTH;
+
+ }
+
+ break;
+
+ default:
+
+ StatusToReturn = NDIS_STATUS_INVALID_OID;
+
+ NdisRequest->DATA.SET_INFORMATION.BytesRead = 0;
+ NdisRequest->DATA.SET_INFORMATION.BytesNeeded = 0;
+
+ break;
+ }
+
+ if (StatusToReturn == NDIS_STATUS_SUCCESS){
+
+ NdisRequest->DATA.SET_INFORMATION.BytesRead = OidLength;
+ NdisRequest->DATA.SET_INFORMATION.BytesNeeded = 0;
+
+ }
+
+
+
+ return(StatusToReturn);
+}
+
+STATIC
+NDIS_STATUS
+IbmtokSetPacketFilter(
+ IN PIBMTOK_ADAPTER Adapter,
+ IN PIBMTOK_OPEN Open,
+ IN PNDIS_REQUEST NdisRequest,
+ IN UINT PacketFilter
+ )
+
+/*++
+
+Routine Description:
+
+ This routine processes the stages necessary to implement changing
+ the packets that a protocol receives from the MAC.
+
+Arguments:
+
+ Adapter - A pointer to the Adapter.
+
+ Open - A pointer to the open instance.
+
+ NdisRequest - A pointer to the request submitting the set command.
+
+ PacketFilter - A bit mask that contains flags that correspond to specific
+ classes of received packets. If a particular bit is set in the mask,
+ then packet reception for that class of packet is enabled. If the
+ bit is clear, then packets that fall into that class are not received
+ by the client. A single exception to this rule is that if the promiscuous
+ bit is set, then the client receives all packets on the network, regardless
+ of the state of the other flags.
+
+Return Value:
+
+ The function value is the status of the operation.
+
+--*/
+
+{
+
+ //
+ // Keeps track of the *MAC's* status. The status will only be
+ // reset if the filter change action routine is called.
+ //
+ NDIS_STATUS StatusOfFilterChange = NDIS_STATUS_SUCCESS;
+
+ //
+ // Verify bits
+ //
+
+ if (PacketFilter & (NDIS_PACKET_TYPE_SOURCE_ROUTING |
+ NDIS_PACKET_TYPE_MULTICAST |
+ NDIS_PACKET_TYPE_PROMISCUOUS |
+ NDIS_PACKET_TYPE_ALL_MULTICAST |
+ NDIS_PACKET_TYPE_SMT |
+ NDIS_PACKET_TYPE_MAC_FRAME
+ )) {
+
+ return(NDIS_STATUS_NOT_SUPPORTED);
+
+ }
+
+ //
+ // Increment the open while it is going through the filtering
+ // routines.
+ //
+
+ Open->References++;
+
+ StatusOfFilterChange = TrFilterAdjust(
+ Adapter->FilterDB,
+ Open->NdisFilterHandle,
+ NdisRequest,
+ PacketFilter,
+ TRUE
+ );
+ Open->References--;
+
+ if (StatusOfFilterChange == NDIS_STATUS_PENDING) {
+
+ //
+ // If it pended, it will be in the pend
+ // queue so we should start that up.
+ //
+
+ IbmtokProcessSrbRequests(Adapter);
+
+ }
+
+ return StatusOfFilterChange;
+}
+
+STATIC
+NDIS_STATUS
+IbmtokChangeFunctionalAddress(
+ IN PIBMTOK_ADAPTER Adapter,
+ IN PIBMTOK_OPEN Open,
+ IN PNDIS_REQUEST NdisRequest,
+ IN PUCHAR Address
+ )
+
+/*++
+
+Routine Description:
+
+ This routine processes the stages necessary to implement changing
+ the packets that a protocol receives from the MAC.
+
+
+ Note: The spin lock must be held before entering this routine.
+
+Arguments:
+
+ Adapter - A pointer to the Adapter.
+
+ Open - A pointer to the open instance.
+
+ NdisRequest - A pointer to the request submitting the set command.
+
+ Address - The new functional address.
+
+Return Value:
+
+ The function value is the status of the operation.
+
+--*/
+
+{
+
+ //
+ // Keeps track of the *MAC's* status. The status will only be
+ // reset if the address change action routine is called.
+ //
+ NDIS_STATUS StatusOfChange = NDIS_STATUS_SUCCESS;
+
+ //
+ // Increment the open while it is going through the filtering
+ // routines.
+ //
+
+ Open->References++;
+
+ StatusOfChange = TrChangeFunctionalAddress(
+ Open->OwningIbmtok->FilterDB,
+ Open->NdisFilterHandle,
+ NdisRequest,
+ Address,
+ TRUE
+ );
+
+ Open->References--;
+
+ if (StatusOfChange == NDIS_STATUS_PENDING) {
+
+ //
+ // If it pended, it will be in the pend
+ // queue so we should start that up.
+ //
+
+ IbmtokProcessSrbRequests(Adapter);
+
+ }
+
+ return StatusOfChange;
+}
+
+STATIC
+NDIS_STATUS
+IbmtokSetGroupAddress(
+ IN PIBMTOK_ADAPTER Adapter,
+ IN PIBMTOK_OPEN Open,
+ IN PNDIS_REQUEST NdisRequest,
+ IN PUCHAR Address
+ )
+
+/*++
+
+Routine Description:
+
+ This routine processes the stages necessary to implement changing
+ the packets that a protocol receives from the MAC.
+
+
+ Note: The spin lock must be held before entering this routine.
+
+Arguments:
+
+ Adapter - A pointer to the Adapter.
+
+ Open - A pointer to the open instance.
+
+ NdisRequest - A pointer to the request submitting the set command.
+
+ Address - The new group address.
+
+Return Value:
+
+ The function value is the status of the operation.
+
+--*/
+
+{
+
+ //
+ // Keeps track of the *MAC's* status. The status will only be
+ // reset if the address change action routine is called.
+ //
+ NDIS_STATUS StatusOfChange = NDIS_STATUS_SUCCESS;
+
+ //
+ // Increment the open while it is going through the filtering
+ // routines.
+ //
+
+ Open->References++;
+
+ StatusOfChange = TrChangeGroupAddress(
+ Open->OwningIbmtok->FilterDB,
+ Open->NdisFilterHandle,
+ NdisRequest,
+ Address,
+ TRUE
+ );
+
+ Open->References--;
+
+ if (StatusOfChange == NDIS_STATUS_PENDING) {
+
+ //
+ // If it pended, it will be in the pend
+ // queue so we should start that up.
+ //
+
+ IbmtokProcessSrbRequests(Adapter);
+
+ }
+
+ return StatusOfChange;
+}
+
+NDIS_STATUS
+IbmtokFillInGlobalData(
+ IN PIBMTOK_ADAPTER Adapter,
+ IN PNDIS_REQUEST NdisRequest
+ )
+
+/*++
+
+Routine Description:
+
+ This routine completes a GlobalStatistics request. It is critical that
+ if information is needed from the Adapter->* fields, they have been
+ updated before this routine is called.
+
+Arguments:
+
+ Adapter - A pointer to the Adapter.
+
+ NdisRequest - A structure which contains the request type (Global
+ Query), an array of operations to perform, and an array for holding
+ the results of the operations.
+
+Return Value:
+
+ The function value is the status of the operation.
+
+--*/
+{
+ //
+ // General Algorithm:
+ //
+ // Switch(Request)
+ // Get requested information
+ // Store results in a common variable.
+ // default:
+ // Try protocol query information
+ // If that fails, fail query.
+ //
+ // Copy result in common variable to result buffer.
+ // Finish processing
+
+ UINT BytesWritten = 0;
+ UINT BytesNeeded = 0;
+ UINT BytesLeft = NdisRequest->DATA.QUERY_INFORMATION.InformationBufferLength;
+ PUCHAR InfoBuffer = (PUCHAR)(NdisRequest->DATA.QUERY_INFORMATION.InformationBuffer);
+
+ NDIS_STATUS StatusToReturn = NDIS_STATUS_SUCCESS;
+
+ //
+ // This variable holds result of query
+ //
+
+ ULONG GenericULong;
+ ULONG MoveBytes = sizeof(ULONG) * 2 + sizeof(NDIS_OID);
+
+
+ StatusToReturn = IbmtokQueryProtocolInformation(
+ Adapter,
+ NULL,
+ NdisRequest->DATA.QUERY_INFORMATION.Oid,
+ TRUE,
+ InfoBuffer,
+ BytesLeft,
+ &BytesNeeded,
+ &BytesWritten
+ );
+
+
+ if (StatusToReturn == NDIS_STATUS_NOT_SUPPORTED){
+
+ StatusToReturn = NDIS_STATUS_SUCCESS;
+
+ //
+ // Switch on request type
+ //
+
+ switch (NdisRequest->DATA.QUERY_INFORMATION.Oid) {
+
+ case OID_GEN_XMIT_OK:
+
+ GenericULong = (ULONG)(Adapter->FramesTransmitted);
+
+ break;
+
+ case OID_GEN_RCV_OK:
+
+ GenericULong = (ULONG)(Adapter->FramesReceived);
+
+ break;
+
+ case OID_GEN_XMIT_ERROR:
+
+ GenericULong = (ULONG)(Adapter->FrameTransmitErrors);
+
+ break;
+
+ case OID_GEN_RCV_ERROR:
+
+ GenericULong = (ULONG)(Adapter->FrameReceiveErrors);
+
+ break;
+
+ case OID_GEN_RCV_NO_BUFFER:
+
+ GenericULong = (ULONG)(Adapter->ReceiveCongestionCount);
+
+ break;
+
+ case OID_802_5_LINE_ERRORS:
+
+ GenericULong = (ULONG)(Adapter->LineErrors);
+
+ break;
+
+ case OID_802_5_LOST_FRAMES:
+
+ GenericULong = (ULONG)(Adapter->LostFrames);
+
+ break;
+
+ case OID_802_5_LAST_OPEN_STATUS:
+
+ GenericULong = (ULONG)(NDIS_STATUS_TOKEN_RING_OPEN_ERROR |
+ (NDIS_STATUS)(Adapter->OpenErrorCode));
+
+ break;
+
+ case OID_802_5_CURRENT_RING_STATUS:
+
+ GenericULong = (ULONG)(Adapter->LastNotifyStatus);
+
+ break;
+
+ case OID_802_5_CURRENT_RING_STATE:
+
+ GenericULong = (ULONG)(Adapter->CurrentRingState);
+
+ break;
+
+ default:
+
+ StatusToReturn = NDIS_STATUS_INVALID_OID;
+
+ break;
+
+ }
+
+ if (StatusToReturn == NDIS_STATUS_SUCCESS){
+
+ //
+ // Check to make sure there is enough room in the
+ // buffer to store the result.
+ //
+
+ if (BytesLeft >= sizeof(ULONG)) {
+
+ //
+ // Store the result.
+ //
+
+ IBMTOK_MOVE_MEMORY(
+ (PVOID)InfoBuffer,
+ (PVOID)(&GenericULong),
+ sizeof(ULONG)
+ );
+
+ BytesWritten += sizeof(ULONG);
+
+ } else {
+
+ BytesNeeded = sizeof(ULONG) - BytesLeft;
+
+ StatusToReturn = NDIS_STATUS_INVALID_LENGTH;
+
+ }
+
+ }
+
+ }
+
+ NdisRequest->DATA.QUERY_INFORMATION.BytesWritten = BytesWritten;
+
+ NdisRequest->DATA.QUERY_INFORMATION.BytesNeeded = BytesNeeded;
+
+ return(StatusToReturn);
+}
+
+STATIC
+NDIS_STATUS
+IbmtokQueryGlobalStatistics(
+ IN NDIS_HANDLE MacAdapterContext,
+ IN PNDIS_REQUEST NdisRequest
+ )
+
+/*++
+
+Routine Description:
+
+ The IbmtokQueryGlobalStatistics is used by the protocol to query
+ global information about the MAC.
+
+Arguments:
+
+ MacAdapterContext - The value associated with the adapter that is being
+ opened when the MAC registered the adapter with NdisRegisterAdapter.
+
+ NdisRequest - A structure which contains the request type (Query),
+ an array of operations to perform, and an array for holding
+ the results of the operations.
+
+Return Value:
+
+ The function value is the status of the operation.
+
+--*/
+
+{
+
+ //
+ // General Algorithm:
+ //
+ //
+ // Check if a request is going to pend...
+ // If so, pend the entire operation.
+ //
+ // Else
+ // Fill in the request block.
+ //
+ //
+
+ PIBMTOK_ADAPTER Adapter = PIBMTOK_ADAPTER_FROM_CONTEXT_HANDLE(MacAdapterContext);
+
+ NDIS_STATUS StatusToReturn = NDIS_STATUS_SUCCESS;
+
+ //
+ // Check if a request is valid and going to pend...
+ // If so, pend the entire operation.
+ //
+
+ NdisInterlockedAddUlong((PULONG)&Adapter->References, 1 ,&(Adapter->Lock));
+
+ //
+ // Switch on request type
+ //
+
+ switch (NdisRequest->DATA.QUERY_INFORMATION.Oid) {
+ case OID_GEN_SUPPORTED_LIST:
+ case OID_GEN_HARDWARE_STATUS:
+ case OID_GEN_MEDIA_SUPPORTED:
+ case OID_GEN_MEDIA_IN_USE:
+ case OID_GEN_MAXIMUM_LOOKAHEAD:
+ case OID_GEN_MAXIMUM_FRAME_SIZE:
+ case OID_GEN_MAXIMUM_TOTAL_SIZE:
+ case OID_GEN_MAC_OPTIONS:
+ case OID_GEN_LINK_SPEED:
+ case OID_GEN_TRANSMIT_BUFFER_SPACE:
+ case OID_GEN_RECEIVE_BUFFER_SPACE:
+ case OID_GEN_TRANSMIT_BLOCK_SIZE:
+ case OID_GEN_RECEIVE_BLOCK_SIZE:
+ case OID_GEN_VENDOR_ID:
+ case OID_GEN_VENDOR_DESCRIPTION:
+ case OID_GEN_DRIVER_VERSION:
+ case OID_GEN_CURRENT_PACKET_FILTER:
+ case OID_GEN_CURRENT_LOOKAHEAD:
+ case OID_802_5_CURRENT_GROUP:
+ case OID_802_5_LAST_OPEN_STATUS:
+ case OID_802_5_CURRENT_RING_STATUS:
+ case OID_802_5_CURRENT_RING_STATE:
+ case OID_802_5_PERMANENT_ADDRESS:
+ case OID_802_5_CURRENT_ADDRESS:
+ case OID_802_5_CURRENT_FUNCTIONAL:
+ break;
+
+ case OID_GEN_XMIT_OK:
+ case OID_GEN_RCV_OK:
+ case OID_GEN_XMIT_ERROR:
+ case OID_GEN_RCV_ERROR:
+ case OID_GEN_RCV_NO_BUFFER:
+ case OID_802_5_LINE_ERRORS:
+ case OID_802_5_LOST_FRAMES:
+
+ StatusToReturn = NDIS_STATUS_PENDING;
+
+ break;
+
+ default:
+
+ StatusToReturn = NDIS_STATUS_INVALID_OID;
+
+ break;
+ }
+
+ if (StatusToReturn == NDIS_STATUS_PENDING) {
+
+ //
+ // Build a pending operation
+ //
+
+ PIBMTOK_PEND_DATA PendOp = PIBMTOK_PEND_DATA_FROM_PNDIS_REQUEST(NdisRequest);
+
+ PendOp->Next = NULL;
+ PendOp->COMMAND.NDIS.STATISTICS.ReadLogPending = FALSE;
+
+ NdisAcquireSpinLock(&Adapter->Lock);
+
+ if (Adapter->PendQueue == NULL){
+
+ Adapter->PendQueue = Adapter->EndOfPendQueue = PendOp;
+
+ } else {
+
+ Adapter->EndOfPendQueue->Next = PendOp;
+
+ }
+
+
+ //
+ // It is now in the pend
+ // queue so we should start that up.
+ //
+
+ IbmtokProcessSrbRequests(Adapter);
+
+ NdisReleaseSpinLock(&Adapter->Lock);
+
+ //
+ // Defer subtracting from Adapter->Reference until the
+ // request completes (see IbmtokFinishPendQueueOp()).
+ //
+
+ return(StatusToReturn);
+
+ }
+
+ if (StatusToReturn == NDIS_STATUS_SUCCESS){
+
+ StatusToReturn = IbmtokFillInGlobalData(Adapter, NdisRequest);
+
+ }
+
+ NdisAcquireSpinLock(&Adapter->Lock);
+
+ IBMTOK_DO_DEFERRED(Adapter);
+
+ return(StatusToReturn);
+}
+
+STATIC
+NDIS_STATUS
+IbmtokReset(
+ IN NDIS_HANDLE MacBindingHandle
+ )
+
+/*++
+
+Routine Description:
+
+ The IbmtokReset request instructs the MAC to issue a hardware reset
+ to the network adapter. The MAC also resets its software state. See
+ the description of NdisReset for a detailed description of this request.
+
+Arguments:
+
+ MacBindingHandle - The context value returned by the MAC when the
+ adapter was opened. In reality, it is a pointer to IBMTOK_OPEN.
+
+Return Value:
+
+ The function value is the status of the operation.
+
+
+--*/
+
+{
+
+ //
+ // Holds the status that should be returned to the caller.
+ //
+ NDIS_STATUS StatusToReturn = NDIS_STATUS_PENDING;
+
+ PIBMTOK_ADAPTER Adapter =
+ PIBMTOK_ADAPTER_FROM_BINDING_HANDLE(MacBindingHandle);
+
+ PIBMTOK_OPEN Open;
+
+ //
+ // Hold the locks while we update the reference counts on the
+ // adapter and the open.
+ //
+
+ NdisAcquireSpinLock(&Adapter->Lock);
+ Open = PIBMTOK_OPEN_FROM_BINDING_HANDLE(MacBindingHandle);
+
+ Adapter->References++;
+
+ if (Adapter->ResetInProgress) {
+
+ StatusToReturn = NDIS_STATUS_RESET_IN_PROGRESS;
+
+ } else if (Adapter->AdapterNotOpen) {
+
+ StatusToReturn = NDIS_STATUS_FAILURE;
+
+ } else {
+
+ if (!Open->BindingShuttingDown) {
+
+ Open->References++;
+ IbmtokSetupForReset(
+ Adapter,
+ PIBMTOK_OPEN_FROM_BINDING_HANDLE(MacBindingHandle)
+ );
+ Open->References--;
+
+ } else {
+
+ StatusToReturn = NDIS_STATUS_CLOSING;
+
+ }
+
+ }
+
+ //
+ // This macro assumes it is called with the lock held,
+ // and releases it.
+ //
+
+ IBMTOK_DO_DEFERRED(Adapter);
+ return StatusToReturn;
+
+}
+
+STATIC
+NDIS_STATUS
+IbmtokChangeFilter(
+ IN UINT OldFilterClasses,
+ IN UINT NewFilterClasses,
+ IN NDIS_HANDLE MacBindingHandle,
+ IN PNDIS_REQUEST NdisRequest,
+ IN BOOLEAN Set
+ )
+
+/*++
+
+Routine Description:
+
+ Action routine that will get called when a particular filter
+ class is first used or last cleared.
+
+ NOTE: This routine assumes that it is called with the lock
+ acquired.
+
+Arguments:
+
+ OldFilterClasses - The values of the class filter before it
+ was changed.
+
+ NewFilterClasses - The current value of the class filter
+
+ MacBindingHandle - The context value returned by the MAC when the
+ adapter was opened. In reality, it is a pointer to IBMTOK_OPEN.
+
+ Set - If true the change resulted from a set, otherwise the
+ change resulted from a open closing.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+
+
+ PIBMTOK_ADAPTER Adapter = PIBMTOK_ADAPTER_FROM_BINDING_HANDLE(MacBindingHandle);
+
+ //
+ // The open that made this request.
+ //
+ PIBMTOK_OPEN Open = PIBMTOK_OPEN_FROM_BINDING_HANDLE(MacBindingHandle);
+
+ //
+ // Holds the change that should be returned to the filtering package.
+ //
+ NDIS_STATUS StatusOfChange;
+
+ if (NdisRequest == NULL) {
+
+ NdisRequest = &(Open->CloseRequestChangeFilter);
+
+ NdisRequest->RequestType = NdisRequestClose;
+
+
+ }
+
+
+ if (Adapter->ResetInProgress) {
+
+ StatusOfChange = NDIS_STATUS_RESET_IN_PROGRESS;
+
+ } else {
+
+ //
+ // The whole purpose of this routine is to determine whether
+ // the filtering changes need to result in the hardware being
+ // reset.
+ //
+
+ ASSERT(OldFilterClasses != NewFilterClasses);
+
+#if DBG
+ if (IbmtokDbg) DbgPrint("IBMTOK: Change filter\n");
+#endif
+
+ if (NewFilterClasses &
+ (NDIS_PACKET_TYPE_PROMISCUOUS | NDIS_PACKET_TYPE_SOURCE_ROUTING)) {
+
+ //
+ // The adapter cannot support promiscuous mode, or
+ // source routing which implies promiscuous.
+ //
+
+ StatusOfChange = NDIS_STATUS_FAILURE;
+
+ } else {
+
+ //
+ // Queue this request.
+ //
+
+ PIBMTOK_PEND_DATA PendOp = PIBMTOK_PEND_DATA_FROM_PNDIS_REQUEST(NdisRequest);
+
+ //
+ // Store open block.
+ //
+
+ PendOp->COMMAND.NDIS.SET_FILTER.Open = Open;
+
+ //
+ // Hold new Filter value
+ //
+
+ if (PendOp->RequestType == NdisRequestClose){
+
+ PendOp->COMMAND.NDIS.CLOSE.NewFilterValue = NewFilterClasses;
+
+ } else {
+
+ PendOp->COMMAND.NDIS.SET_FILTER.NewFilterValue = NewFilterClasses;
+
+ }
+
+
+ //
+ // Insert into queue.
+ //
+
+ PendOp->Next = NULL;
+
+ if (Adapter->PendQueue == NULL) {
+
+ Adapter->PendQueue = Adapter->EndOfPendQueue = PendOp;
+
+ } else {
+
+ Adapter->EndOfPendQueue->Next = PendOp;
+
+ }
+
+ Open->References++;
+
+ StatusOfChange = NDIS_STATUS_PENDING;
+
+
+ }
+
+ }
+
+ return StatusOfChange;
+
+}
+
+STATIC
+NDIS_STATUS
+IbmtokChangeAddress(
+ IN TR_FUNCTIONAL_ADDRESS OldFunctionalAddress,
+ IN TR_FUNCTIONAL_ADDRESS NewFunctionalAddress,
+ IN NDIS_HANDLE MacBindingHandle,
+ IN PNDIS_REQUEST NdisRequest,
+ IN BOOLEAN Set
+ )
+
+
+/*++
+
+Routine Description:
+
+ Action routine that will get called when an address is added to
+ the filter that wasn't referenced by any other open binding.
+
+ NOTE: This routine assumes that it is called with the lock
+ acquired.
+
+Arguments:
+
+ OldFunctionalAddress - The previous functional address.
+
+ NewFunctionalAddress - The new functional address.
+
+ MacBindingHandle - The context value returned by the MAC when the
+ adapter was opened. In reality, it is a pointer to IBMTOK_OPEN.
+
+ NdisRequest - A pointer to the Request that submitted the set command.
+
+ Set - If true the change resulted from a set, otherwise the
+ change resulted from a open closing.
+
+Return Value:
+
+ None.
+
+
+--*/
+
+{
+
+ PIBMTOK_ADAPTER Adapter = PIBMTOK_ADAPTER_FROM_BINDING_HANDLE(MacBindingHandle);
+
+ //
+ // Holds the status that should be returned to the filtering package.
+ //
+ NDIS_STATUS StatusOfChange;
+
+ //
+ // The open that made this request.
+ //
+ PIBMTOK_OPEN Open = PIBMTOK_OPEN_FROM_BINDING_HANDLE(MacBindingHandle);
+
+#if DBG
+ if (IbmtokDbg) {
+ DbgPrint("IBMTOK: Queueing:\n");
+ DbgPrint(" Req : 0x%x\n", NdisRequest);
+ DbgPrint(" Old : 0x%x\n", OldFunctionalAddress);
+ DbgPrint(" New : 0x%x\n", NewFunctionalAddress);
+ }
+#endif
+
+ // Check to see if the device is already resetting. If it is
+ // then reject this change.
+ //
+
+ if (NdisRequest == NULL) {
+
+ NdisRequest = &(Open->CloseRequestChangeAddress);
+
+ NdisRequest->RequestType = NdisRequestGeneric2; // Close, set address
+
+ }
+
+
+ if (Adapter->ResetInProgress) {
+
+#if DBG
+ if (IbmtokDbg) {
+ DbgPrint("IBMTOK: ResetInProgress\n\n");
+ }
+#endif
+
+ StatusOfChange = NDIS_STATUS_RESET_IN_PROGRESS;
+
+ } else {
+
+ //
+ // Queue this request.
+ //
+
+ PIBMTOK_PEND_DATA PendOp = PIBMTOK_PEND_DATA_FROM_PNDIS_REQUEST(NdisRequest);
+
+
+ //
+ // Store open block.
+ //
+
+ PendOp->COMMAND.NDIS.SET_ADDRESS.Open = Open;
+
+ //
+ // Hold new Address value
+ //
+
+ PendOp->COMMAND.NDIS.SET_ADDRESS.NewAddressValue = NewFunctionalAddress;
+
+
+ //
+ // Insert into queue.
+ //
+
+ PendOp->Next = NULL;
+
+ if (Adapter->PendQueue == NULL) {
+
+ Adapter->PendQueue = Adapter->EndOfPendQueue = PendOp;
+
+ } else {
+
+ Adapter->EndOfPendQueue->Next = PendOp;
+
+ }
+
+ Open->References++;
+
+ StatusOfChange = NDIS_STATUS_PENDING;
+
+ }
+
+ return StatusOfChange;
+
+}
+
+STATIC
+NDIS_STATUS
+IbmtokChangeGroupAddress(
+ IN TR_FUNCTIONAL_ADDRESS OldGroupAddress,
+ IN TR_FUNCTIONAL_ADDRESS NewGroupAddress,
+ IN NDIS_HANDLE MacBindingHandle,
+ IN PNDIS_REQUEST NdisRequest,
+ IN BOOLEAN Set
+ )
+
+/*++
+
+Routine Description:
+
+ Action routine that will get called when a group address is to
+ be changed.
+
+ NOTE: This routine assumes that it is called with the lock
+ acquired.
+
+Arguments:
+
+ OldGroupAddress - The previous group address.
+
+ NewGroupAddress - The new group address.
+
+ MacBindingHandle - The context value returned by the MAC when the
+ adapter was opened. In reality, it is a pointer to IBMTOK_OPEN.
+
+ NdisRequest - A pointer to the Request that submitted the set command.
+
+ Set - If true the change resulted from a set, otherwise the
+ change resulted from a open closing.
+
+Return Value:
+
+ None.
+
+
+--*/
+
+{
+
+ PIBMTOK_ADAPTER Adapter = PIBMTOK_ADAPTER_FROM_BINDING_HANDLE(MacBindingHandle);
+
+ //
+ // Holds the status that should be returned to the filtering package.
+ //
+ NDIS_STATUS StatusOfChange;
+
+ //
+ // The open that made this request.
+ //
+ PIBMTOK_OPEN Open = PIBMTOK_OPEN_FROM_BINDING_HANDLE(MacBindingHandle);
+
+
+ if (NdisRequest == NULL) {
+
+ NdisRequest = &(Open->CloseRequestChangeGroupAddress);
+
+ NdisRequest->RequestType = NdisRequestGeneric3; // Close, set group address
+
+ }
+
+
+ //
+ // Check to see if the device is already resetting. If it is
+ // then reject this change.
+ //
+
+ if (Adapter->ResetInProgress) {
+
+ StatusOfChange = NDIS_STATUS_RESET_IN_PROGRESS;
+
+ } else {
+
+ //
+ // Queue this request.
+ //
+
+ PIBMTOK_PEND_DATA PendOp = PIBMTOK_PEND_DATA_FROM_PNDIS_REQUEST(NdisRequest);
+
+
+ //
+ // Store open block.
+ //
+
+ PendOp->COMMAND.NDIS.SET_ADDRESS.Open = Open;
+
+ //
+ // Hold new Address value
+ //
+
+ PendOp->COMMAND.NDIS.SET_ADDRESS.NewAddressValue = NewGroupAddress;
+
+
+ //
+ // Insert into queue.
+ //
+
+ PendOp->Next = NULL;
+
+ if (Adapter->PendQueue == NULL) {
+
+ Adapter->PendQueue = Adapter->EndOfPendQueue = PendOp;
+
+ } else {
+
+ Adapter->EndOfPendQueue->Next = PendOp;
+
+ }
+
+ Open->References++;
+
+ StatusOfChange = NDIS_STATUS_PENDING;
+
+ }
+
+ return StatusOfChange;
+
+}
+
+STATIC
+VOID
+IbmtokCloseAction(
+ IN NDIS_HANDLE MacBindingHandle
+ )
+
+/*++
+
+Routine Description:
+
+ Action routine that will get called when a particular binding
+ was closed while it was indicating through NdisIndicateReceive
+
+ All this routine needs to do is to decrement the reference count
+ of the binding.
+
+ NOTE: This routine assumes that it is called with the lock acquired.
+
+Arguments:
+
+ MacBindingHandle - The context value returned by the MAC when the
+ adapter was opened. In reality, it is a pointer to IBMTOK_OPEN.
+
+Return Value:
+
+ None.
+
+
+--*/
+
+{
+
+ PIBMTOK_OPEN_FROM_BINDING_HANDLE(MacBindingHandle)->References--;
+
+}
+
+extern
+VOID
+IbmtokStartAdapterReset(
+ IN PIBMTOK_ADAPTER Adapter
+ )
+
+/*++
+
+Routine Description:
+
+ This is the first phase of resetting the adapter hardware.
+
+ It makes the following assumptions:
+
+ 1) That the hardware has been stopped.
+
+ 2) That it can not be preempted.
+
+ 3) That no other adapter activity can occur.
+
+ When this routine is finished all of the adapter information
+ will be as if the driver was just initialized.
+
+Arguments:
+
+ Adapter - The adapter whose hardware is to be reset.
+
+Return Value:
+
+ None.
+
+--*/
+{
+
+ //
+ // Disable these so no pending interrupts
+ // will fire.
+ //
+ CLEAR_ISRP_BITS(Adapter);
+
+ //
+ // OK, do the reset as detailed in the Tech Ref...
+ //
+
+ WRITE_ADAPTER_PORT(Adapter, RESET_LATCH, 0);
+
+ NdisStallExecution(50000);
+
+ WRITE_ADAPTER_PORT(Adapter, RESET_RELEASE, 0);
+
+ //
+ // Have to write this now to enable Shared RAM paging.
+ //
+ if (Adapter->SharedRamPaging) {
+
+ WRITE_ADAPTER_REGISTER(Adapter, SRPR_LOW, 0xc0);
+
+ }
+
+
+ if (Adapter->CardType == IBM_TOKEN_RING_PCMCIA)
+ {
+ UINT Nibble0;
+ UINT Nibble1;
+ UINT Nibble2;
+ UINT Nibble3;
+ ULONG MmioAddress;
+
+ //
+ // Configure the card to match registry
+ // Use the Default MMIO value here (this never changes from system to system)
+ //
+ MmioAddress = Adapter->MmioAddress;
+
+ //
+ // Nibble 0 - ROM address
+ //
+ Nibble0 = NIBBLE_0 | ((UINT)(MmioAddress >> 16 ) & 0x0F);
+
+ //
+ // Nibble 1 - ROM address, INT 0
+ //
+ Nibble1 = NIBBLE_1 | ((UINT)(MmioAddress >> 12) & 0x0F);
+
+ //
+ // Nibble 2 - INT1, F ROS, SRAM, S RST
+ //
+ Nibble2 = NIBBLE_2 | DEFAULT_NIBBLE_2;
+
+ //
+ // Nibble 3 - Ring Speed, RAM size, Prim/Alt
+ //
+ Nibble3 = NIBBLE_3;
+
+ if (Adapter->RingSpeed == 16)
+ {
+ Nibble3 |= RING_SPEED_16_MPS;
+ }
+ else
+ {
+ Nibble3 |= RING_SPEED_4_MPS;
+ }
+
+ switch (Adapter->RamSize)
+ {
+ case 0x10000:
+ Nibble3 |= SHARED_RAM_64K;
+ break;
+
+ case 0x8000:
+ Nibble3 |= SHARED_RAM_32K;
+ break;
+
+ case 0x4000:
+ Nibble3 |= SHARED_RAM_16K;
+ break;
+
+ case 0x2000:
+ Nibble3 |= SHARED_RAM_8K;
+ break;
+ }
+
+ // if ( Adapter->IbmtokPortAddress == PRIMARY_ADAPTER_OFFSET)
+ // {
+ // Nibble3 |= PRIMARY;
+ // }
+ // else
+ // {
+ // Nibble3 |= ALTERNATE;
+ // }
+
+ //
+ // Write everything to the Token-Ring Controller Configuration Register
+ //
+ WRITE_ADAPTER_PORT(Adapter, SWITCH_READ_2, Nibble0);
+ WRITE_ADAPTER_PORT(Adapter, SWITCH_READ_1, Nibble0);
+
+ WRITE_ADAPTER_PORT(Adapter, SWITCH_READ_2, Nibble1);
+ WRITE_ADAPTER_PORT(Adapter, SWITCH_READ_1, Nibble1);
+
+ WRITE_ADAPTER_PORT(Adapter, SWITCH_READ_2, Nibble2);
+ WRITE_ADAPTER_PORT(Adapter, SWITCH_READ_1, Nibble2);
+
+ WRITE_ADAPTER_PORT(Adapter, SWITCH_READ_2, Nibble3);
+ WRITE_ADAPTER_PORT(Adapter, SWITCH_READ_1, Nibble3);
+
+ WRITE_ADAPTER_PORT(Adapter, SWITCH_READ_2, RELEASE_TR_CONTROLLER);
+ WRITE_ADAPTER_PORT(Adapter, SWITCH_READ_1, RELEASE_TR_CONTROLLER);
+
+ WRITE_ADAPTER_REGISTER(Adapter, RRR_LOW, Adapter->RrrLowValue);
+ }
+ else if (Adapter->UsingPcIoBus)
+ {
+ //
+ // If this is a PC I/O Bus....
+ // Set up the shared RAM to be right after the MMIO.
+ //
+ WRITE_ADAPTER_REGISTER(Adapter, RRR_LOW, Adapter->RrrLowValue);
+ }
+
+
+ //
+ // Allow the reset complete interrupt to be
+ // serviced correctly.
+ //
+ if (Adapter->CardType != IBM_TOKEN_RING_PCMCIA)
+ {
+ SET_INTERRUPT_RESET_FLAG(Adapter);
+ }
+ else
+ {
+ UCHAR Temp;
+
+ //
+ // disable interrupts on the card,
+ // since we don't trust ndissyncint to work
+ //
+ READ_ADAPTER_REGISTER(Adapter, ISRP_LOW, &Temp);
+
+ WRITE_ADAPTER_REGISTER(
+ Adapter,
+ ISRP_LOW,
+ (UCHAR)(Temp & (~(ISRP_LOW_NO_CHANNEL_CHECK | ISRP_LOW_INTERRUPT_ENABLE)))
+ );
+
+ //
+ // Set the reset flag
+ //
+ Adapter->ResetInterruptAllowed = TRUE;
+
+ //
+ // reenable interrupts on the card
+ //
+ WRITE_ADAPTER_REGISTER(
+ Adapter,
+ ISRP_LOW,
+ ISRP_LOW_NO_CHANNEL_CHECK | ISRP_LOW_INTERRUPT_ENABLE
+ );
+ }
+
+ //
+ // Enable card interrupts to get the reset interrupt.
+ //
+
+ WRITE_ADAPTER_REGISTER(Adapter, ISRP_LOW,
+ ISRP_LOW_NO_CHANNEL_CHECK | ISRP_LOW_INTERRUPT_ENABLE);
+
+
+ //
+ // The remaining processing is done in the
+ // interrupt handler.
+ //
+
+
+
+ //
+ // OK, now abort pending requests before we nuke
+ // everything.
+ //
+
+ NdisDprAcquireSpinLock (&Adapter->Lock);
+
+ IbmtokAbortSends (Adapter, NDIS_STATUS_REQUEST_ABORTED);
+
+ NdisDprReleaseSpinLock (&Adapter->Lock);
+
+}
+
+extern
+VOID
+IbmtokFinishAdapterReset(
+ IN PIBMTOK_ADAPTER Adapter
+ )
+
+/*++
+
+Routine Description:
+
+ Called by HandleResetStaging when the last piece
+ of the adapter reset is complete and normal
+ operation can resume.
+
+ Called with the lock held and returns with it held.
+
+Arguments:
+
+ Adapter - The adapter that the reset is for.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+ PLIST_ENTRY CurrentLink;
+ PIBMTOK_OPEN TempOpen;
+
+
+ SetResetVariables(Adapter);
+
+ if (Adapter->UnpluggedResetInProgress) {
+ Adapter->UnpluggedResetInProgress = FALSE;
+ Adapter->Unplugged = FALSE;
+ Adapter->LobeWireFaultIndicated = FALSE;
+ }
+
+ Adapter->ResetInProgress = FALSE;
+ Adapter->ResetInterruptAllowed = FALSE;
+ Adapter->ResetInterruptHasArrived = FALSE;
+ Adapter->NotAcceptingRequests = FALSE;
+
+ //
+ // Get any interrupts that have been deferred
+ // while NotAcceptingRequests was TRUE.
+ //
+ IbmtokForceAdapterInterrupt(Adapter);
+
+ if (Adapter->ResettingOpen != NULL) {
+
+ PIBMTOK_OPEN ResettingOpen = Adapter->ResettingOpen;
+
+ //
+ // Indicate reset complete to everybody
+ //
+
+ CurrentLink = Adapter->OpenBindings.Flink;
+
+ while (CurrentLink != &(Adapter->OpenBindings)){
+
+ TempOpen = CONTAINING_RECORD(
+ CurrentLink,
+ IBMTOK_OPEN,
+ OpenList
+ );
+
+ NdisReleaseSpinLock(&Adapter->Lock);
+
+ NdisIndicateStatus(TempOpen->NdisBindingContext,
+ NDIS_STATUS_RESET_END,
+ NULL,
+ 0
+ );
+
+ NdisIndicateStatusComplete(TempOpen->NdisBindingContext);
+
+ NdisAcquireSpinLock(&Adapter->Lock);
+
+ CurrentLink = CurrentLink->Flink;
+
+ }
+
+ //
+ // Decrement the reference count that was incremented
+ // in SetupForReset.
+ //
+ ResettingOpen->References--;
+
+ NdisReleaseSpinLock(&Adapter->Lock);
+
+ NdisCompleteReset(
+ ResettingOpen->NdisBindingContext,
+ NDIS_STATUS_SUCCESS
+ );
+
+ NdisAcquireSpinLock(&Adapter->Lock);
+
+ }
+
+}
+
+#pragma NDIS_INIT_FUNCTION(IbmtokSetupRegistersAndInit)
+
+STATIC
+VOID
+IbmtokSetupRegistersAndInit(
+ IN PIBMTOK_ADAPTER Adapter
+ )
+
+/*++
+
+Routine Description:
+
+ It is this routines responsibility to make sure that the
+ initialization block is filled and the chip is initialized
+ *but not* started.
+
+ NOTE: This routine assumes that it is called with the lock
+ acquired OR that only a single thread of execution is working
+ with this particular adapter.
+
+Arguments:
+
+ Adapter - The adapter whose hardware is to be initialized.
+
+Return Value:
+
+ None.
+
+--*/
+{
+
+ //
+ // Enable card interrupts to get the reset interrupt.
+ //
+
+ WRITE_ADAPTER_REGISTER(Adapter, ISRP_LOW,
+ ISRP_LOW_NO_CHANNEL_CHECK | ISRP_LOW_INTERRUPT_ENABLE);
+
+ //
+ // Set the timer to 10 milliseconds...this seems to
+ // be necessary for proper operation (according to
+ // ChandanC).
+ //
+
+ WRITE_ADAPTER_REGISTER(Adapter, TVR_HIGH, 0x01);
+
+
+ //
+ // Start the timer and set it to reload, but not to
+ // interrupt us (TCR_LOW_INTERRUPT_MASK is off). This
+ // will still cause bit 4 in the ISRP Low to go on,
+ // but it won't cause an interrupt.
+ //
+
+#if 0
+ WRITE_ADAPTER_REGISTER(Adapter, TCR_LOW,
+// TCR_LOW_INTERRUPT_MASK |
+ TCR_LOW_RELOAD_TIMER | TCR_LOW_COUNTER_ENABLE);
+#endif
+ WRITE_ADAPTER_REGISTER(Adapter, TCR_LOW, 0);
+
+
+
+ //
+ // If this is a PC I/O Bus...
+ // Set up the shared RAM to be right after the MMIO.
+ //
+
+ if (Adapter->UsingPcIoBus)
+ {
+ WRITE_ADAPTER_REGISTER(Adapter, RRR_LOW, Adapter->RrrLowValue);
+ }
+ else if (Adapter->CardType == IBM_TOKEN_RING_PCMCIA)
+ {
+ WRITE_ADAPTER_REGISTER(Adapter, RRR_LOW, (UCHAR)(Adapter->Ram >> 12));
+ }
+
+
+ //
+ // The remaining initialization processing is done in
+ // the interrupt handler.
+ //
+
+}
+
+
+STATIC
+VOID
+IbmtokSetupForReset(
+ IN PIBMTOK_ADAPTER Adapter,
+ IN PIBMTOK_OPEN Open
+ )
+
+/*++
+
+Routine Description:
+
+ This routine is used to fill in the who and why a reset is
+ being set up as well as setting the appropriate fields in the
+ adapter.
+
+ NOTE: This routine must be called with the lock acquired.
+
+Arguments:
+
+ Adapter - The adapter whose hardware is to be initialized.
+
+ Open - A (possibly NULL) pointer to an sonic open structure.
+ The reason it could be null is if the adapter is initiating the
+ reset on its own.
+
+Return Value:
+
+ None.
+
+--*/
+{
+ //
+ // Notify of reset start
+ //
+
+ PLIST_ENTRY CurrentLink;
+ PIBMTOK_OPEN TempOpen;
+
+ if (Open != NULL) {
+
+ CurrentLink = Adapter->OpenBindings.Flink;
+
+ while (CurrentLink != &(Adapter->OpenBindings)){
+
+ TempOpen = CONTAINING_RECORD(
+ CurrentLink,
+ IBMTOK_OPEN,
+ OpenList
+ );
+
+ NdisReleaseSpinLock(&Adapter->Lock);
+
+ NdisIndicateStatus(TempOpen->NdisBindingContext,
+ NDIS_STATUS_RESET_START,
+ NULL,
+ 0
+ );
+
+ NdisAcquireSpinLock(&Adapter->Lock);
+
+ CurrentLink = CurrentLink->Flink;
+
+ }
+ }
+
+
+ Adapter->ResetInProgress = TRUE;
+ Adapter->NotAcceptingRequests = TRUE;
+
+ Adapter->ResettingOpen = Open;
+
+ //
+ // This will go to 1 when StartAdapterReset is called.
+ //
+ Adapter->CurrentResetStage = 0;
+
+ //
+ // If there is a valid open we should up the reference count
+ // so that the open can't be deleted before we indicate that
+ // their request is finished.
+ //
+
+ if (Open != NULL) {
+
+ Open->References++;
+
+ }
+
+}
+
+
+#pragma NDIS_INIT_FUNCTION(IbmtokAddAdapter)
+
+NDIS_STATUS
+IbmtokAddAdapter(
+ IN NDIS_HANDLE MacMacContext,
+ IN NDIS_HANDLE ConfigurationHandle,
+ IN PNDIS_STRING AdapterName
+ )
+
+/*++
+
+Routine Description:
+
+ This routine is used to initialize each adapter card/chip.
+
+Arguments:
+
+ see NDIS 3.0 spec...
+
+Return Value:
+
+
+ NDIS_STATUS_SUCCESS - Adapter was successfully added.
+ NDIS_STATUS_FAILURE - Adapter was not added, also MAC deregistered.
+
+--*/
+
+{
+ PIBMTOK_ADAPTER Adapter;
+
+ NDIS_HANDLE ConfigHandle;
+ PNDIS_CONFIGURATION_PARAMETER ReturnedValue;
+ NDIS_STRING CardTypeStr = NDIS_STRING_CONST("CardType");
+ NDIS_STRING BusTypeStr = NDIS_STRING_CONST("BusType");
+ NDIS_STRING IOAddressStr = IOADDRESS;
+ NDIS_STRING NetworkAddressStr = NETWORK_ADDRESS;
+ NDIS_STRING PacketSizeStr = MAXPACKETSIZE;
+ NDIS_STRING TokenReleaseStr = TOKEN_RELEASE;
+
+ NDIS_STATUS Status = NDIS_STATUS_SUCCESS;
+
+ BOOLEAN PrimaryAdapter = TRUE;
+ BOOLEAN ConfigError = FALSE;
+ BOOLEAN McaCard = FALSE;
+
+ UINT SlotNumber;
+ NDIS_MCA_POS_DATA McaData;
+
+ PVOID NetAddress;
+ ULONG Length;
+
+ //
+ // Allocate the Adapter block.
+ //
+
+ if (IBMTOK_ALLOC_PHYS(&Adapter, sizeof(IBMTOK_ADAPTER)) !=
+ NDIS_STATUS_SUCCESS
+ )
+ {
+ return(NDIS_STATUS_RESOURCES);
+ }
+
+ IBMTOK_ZERO_MEMORY(Adapter, sizeof(IBMTOK_ADAPTER));
+
+ Adapter->MaxTransmittablePacket = 17960;
+ Adapter->CurrentRingState = NdisRingStateClosed;
+
+ Adapter->NdisMacHandle = ((PIBMTOK_MAC)MacMacContext)->NdisMacHandle;
+
+ NdisOpenConfiguration(
+ &Status,
+ &ConfigHandle,
+ ConfigurationHandle
+ );
+ if (Status != NDIS_STATUS_SUCCESS)
+ {
+ IBMTOK_FREE_PHYS(Adapter, sizeof(IBMTOK_ADAPTER));
+
+ return(NDIS_STATUS_FAILURE);
+ }
+
+ //
+ // Determine the type of the card;
+ // IBM_TOKEN_RING_ISA, IBM_TOKEN_RING_PCMCIA.
+ //
+ NdisReadConfiguration(
+ &Status,
+ &ReturnedValue,
+ ConfigHandle,
+ &CardTypeStr,
+ NdisParameterInteger
+ );
+ if (NDIS_STATUS_SUCCESS == Status)
+ Adapter->CardType = (UINT)ReturnedValue->ParameterData.IntegerData;
+
+ //
+ // Read Bus Type
+ //
+ NdisReadConfiguration(
+ &Status,
+ &ReturnedValue,
+ ConfigHandle,
+ &BusTypeStr,
+ NdisParameterHexInteger
+ );
+ if (NDIS_STATUS_SUCCESS == Status)
+ {
+ if (ReturnedValue->ParameterData.IntegerData ==
+ (ULONG)NdisInterfaceMca)
+ {
+ McaCard = TRUE;
+ }
+ }
+
+ //
+ // Get I/O Address
+ //
+
+ if (McaCard)
+ {
+ //
+ // Get I/O Address from Mca Pos info.
+ //
+ NdisReadMcaPosInformation(
+ &Status,
+ ConfigurationHandle,
+ &SlotNumber,
+ &McaData
+ );
+ if (Status != NDIS_STATUS_SUCCESS)
+ {
+ ConfigError = TRUE;
+ goto RegisterAdapter;
+ }
+
+ //
+ // Now interperet the data
+ //
+ switch (McaData.PosData2 & 0x1)
+ {
+ case 0x00:
+ Adapter->IbmtokPortAddress = PRIMARY_ADAPTER_OFFSET;
+ break;
+
+ case 0x01:
+ Adapter->IbmtokPortAddress = ALTERNATE_ADAPTER_OFFSET;
+ break;
+
+ }
+ }
+ else if (IBM_TOKEN_RING_PCMCIA == Adapter->CardType)
+ {
+ //
+ // Read I/O Address.
+ //
+ NdisReadConfiguration(
+ &Status,
+ &ReturnedValue,
+ ConfigHandle,
+ &IOAddressStr,
+ NdisParameterHexInteger
+ );
+ if (NDIS_STATUS_SUCCESS == Status)
+ {
+ Adapter->IbmtokPortAddress =
+ (ULONG)ReturnedValue->ParameterData.IntegerData;
+ }
+ }
+ else
+ {
+ //
+ // Read I/O Address
+ //
+ NdisReadConfiguration(
+ &Status,
+ &ReturnedValue,
+ ConfigHandle,
+ &IOAddressStr,
+ NdisParameterInteger
+ );
+ if (NDIS_STATUS_SUCCESS == Status)
+ {
+ PrimaryAdapter =
+ (ReturnedValue->ParameterData.IntegerData == 1) ? TRUE : FALSE;
+ }
+
+ if (PrimaryAdapter)
+ {
+ Adapter->IbmtokPortAddress = PRIMARY_ADAPTER_OFFSET;
+ }
+ else
+ {
+ Adapter->IbmtokPortAddress = ALTERNATE_ADAPTER_OFFSET;
+ }
+ }
+
+ // if IBM_TOKEN_RING_16_4_CREDIT_CARD_ADAPTER, read in bunch of stuff
+ // like mmio, ringspeed, interrupt, ramsize, so we can set the card to match
+ //
+ if (IBM_TOKEN_RING_PCMCIA == Adapter->CardType)
+ {
+ // The following strings were changed to match the correct Registry entries
+
+ // NDIS_STRING AttributeAddressStr1 = NDIS_STRING_CONST("PCCARDAttributeMemoryAddress");
+ // NDIS_STRING AttributeAddressStr2 = NDIS_STRING_CONST("PCCARDAttributeMemoryAddress_1");
+ // NDIS_STRING AttributeSizeStr1 = NDIS_STRING_CONST("PCCARDAttributeMemorySize");
+ // NDIS_STRING AttributeSizeStr2 = NDIS_STRING_CONST("PCCARDAttributeMemorySize_1");
+
+ NDIS_STRING AttributeAddressStr1 = NDIS_STRING_CONST("MemoryMappedBaseAddress");
+ NDIS_STRING AttributeAddressStr2 = NDIS_STRING_CONST("MemoryMappedBaseAddress_1");
+ NDIS_STRING AttributeSizeStr1 = NDIS_STRING_CONST("MemoryMappedSize");
+ NDIS_STRING AttributeSizeStr2 = NDIS_STRING_CONST("MemoryMappedSize_1");
+ NDIS_STRING RingSpeedStr = NDIS_STRING_CONST("RingSpeed");
+ NDIS_STRING InterruptNumberStr = NDIS_STRING_CONST("InterruptNumber");
+ NDIS_STRING AutoRingSpeedStr = NDIS_STRING_CONST("AutoRingSpeed");
+ ULONG BaseAddress;
+ ULONG Size;
+
+ //
+ // Get the memory mapped I/O attribute window.
+ //
+ NdisReadConfiguration(
+ &Status,
+ &ReturnedValue,
+ ConfigHandle,
+ &AttributeAddressStr1,
+ NdisParameterInteger
+ );
+ if (NDIS_STATUS_SUCCESS == Status)
+ {
+ //
+ // Save the memory mapped io base address.
+ //
+ BaseAddress = (ULONG)ReturnedValue->ParameterData.IntegerData;
+ }
+ else
+ {
+ //
+ // BAD BAD BAD
+ //
+ NdisWriteErrorLogEntry(
+ Adapter->NdisAdapterHandle,
+ NDIS_ERROR_CODE_UNSUPPORTED_CONFIGURATION,
+ 1,
+ 0x11111111
+ );
+
+ ConfigError = TRUE;
+ goto RegisterAdapter;
+ }
+
+ //
+ // Get the size of the memory mapped I/O attribute window.
+ //
+ NdisReadConfiguration(
+ &Status,
+ &ReturnedValue,
+ ConfigHandle,
+ &AttributeSizeStr1,
+ NdisParameterInteger
+ );
+
+ //
+ // Save the size of the memory mapped io space.
+ //
+ Size = (ULONG)ReturnedValue->ParameterData.IntegerData;
+
+ if ((Status != NDIS_STATUS_SUCCESS) || (Size != 0x2000))
+ {
+ //
+ // BAD BAD BAD
+ //
+ NdisWriteErrorLogEntry(
+ Adapter->NdisAdapterHandle,
+ NDIS_ERROR_CODE_UNSUPPORTED_CONFIGURATION,
+ 1,
+ 0x22222222
+ );
+
+ ConfigError = TRUE;
+ goto RegisterAdapter;
+ }
+
+ //
+ // Save the memory mapped address in the adapter block.
+ //
+ Adapter->MmioAddress = BaseAddress;
+
+ //
+ // Get the shared ram attribute window.
+ //
+ NdisReadConfiguration(
+ &Status,
+ &ReturnedValue,
+ ConfigHandle,
+ &AttributeAddressStr2,
+ NdisParameterInteger
+ );
+ if (NDIS_STATUS_SUCCESS == Status)
+ {
+ BaseAddress = (ULONG)ReturnedValue->ParameterData.IntegerData;
+ }
+ else
+ {
+ //
+ // BAD BAD BAD
+ //
+ NdisWriteErrorLogEntry(
+ Adapter->NdisAdapterHandle,
+ NDIS_ERROR_CODE_UNSUPPORTED_CONFIGURATION,
+ 1,
+ 0x33333333
+ );
+
+ ConfigError = TRUE;
+ goto RegisterAdapter;
+ }
+
+ //
+ // Get the size of the shared ram attribute window.
+ //
+ NdisReadConfiguration(
+ &Status,
+ &ReturnedValue,
+ ConfigHandle,
+ &AttributeSizeStr2,
+ NdisParameterInteger
+ );
+
+ Size = (ULONG)ReturnedValue->ParameterData.IntegerData;
+
+ if ((Status != NDIS_STATUS_SUCCESS) ||
+ ((Size != 0x2000) && (Size != 0x4000) &&
+ (Size != 0x8000) && (Size != 0x10000))
+ )
+ {
+ //
+ // BAD BAD BAD
+ //
+ NdisWriteErrorLogEntry(
+ Adapter->NdisAdapterHandle,
+ NDIS_ERROR_CODE_UNSUPPORTED_CONFIGURATION,
+ 1,
+ 0x44444444
+ );
+
+ ConfigError = TRUE;
+ goto RegisterAdapter;
+ }
+
+ Adapter->RamSize = Size;
+ Adapter->Ram = BaseAddress;
+
+ //
+ // Find out ring speed
+ //
+ NdisReadConfiguration(
+ &Status,
+ &ReturnedValue,
+ ConfigHandle,
+ &RingSpeedStr,
+ NdisParameterInteger
+ );
+ if (NDIS_STATUS_SUCCESS == Status)
+ Adapter->RingSpeed = ReturnedValue->ParameterData.IntegerData;
+
+ //
+ // Determine if Ring Speed Listen is desired BEM PCMCIA card
+ //
+
+
+ NdisReadConfiguration(
+ &Status,
+ &ReturnedValue,
+ ConfigHandle,
+ &AutoRingSpeedStr,
+ NdisParameterInteger
+ );
+
+ if (Status == NDIS_STATUS_SUCCESS) {
+
+ Adapter->RingSpeedListen = (BOOLEAN) ReturnedValue->ParameterData.IntegerData;
+
+ }
+
+ //
+ // Get the interrupt level.
+ //
+ NdisReadConfiguration(
+ &Status,
+ &ReturnedValue,
+ ConfigHandle,
+ &InterruptNumberStr,
+ NdisParameterInteger
+ );
+ if (NDIS_STATUS_SUCCESS == Status)
+ Adapter->InterruptLevel = ReturnedValue->ParameterData.IntegerData;
+
+#if DBG
+ if (IbmtokDbg)
+ {
+ DbgPrint("MMIO = %x\n", Adapter->MmioAddress);
+ DbgPrint("RAM = %x\n",Adapter->Ram);
+ DbgPrint("RAMSIZE = %x\n", Adapter->RamSize);
+ DbgPrint("RINGSPEED = %d\n", Adapter->RingSpeed);
+ DbgPrint("IO Base = %x\n", Adapter->IbmtokPortAddress);
+ DbgPrint("INT = %x\n", Adapter->InterruptLevel);
+ }
+#endif
+ }
+
+ //
+ // Read PacketSize
+ //
+ NdisReadConfiguration(
+ &Status,
+ &ReturnedValue,
+ ConfigHandle,
+ &PacketSizeStr,
+ NdisParameterInteger
+ );
+ if (Status == NDIS_STATUS_SUCCESS)
+ {
+ Adapter->MaxTransmittablePacket =
+ ReturnedValue->ParameterData.IntegerData;
+ }
+
+ //
+ // Read net address
+ //
+ NdisReadNetworkAddress(
+ &Status,
+ &NetAddress,
+ &Length,
+ ConfigHandle
+ );
+ if (Status == NDIS_STATUS_SUCCESS)
+ {
+ if (Length == TR_LENGTH_OF_ADDRESS)
+ {
+ TR_COPY_NETWORK_ADDRESS(
+ Adapter->NetworkAddress,
+ NetAddress
+ );
+ }
+ else if (Length != 0)
+ {
+ ConfigError = TRUE;
+ goto RegisterAdapter;
+ }
+ }
+
+ //
+ // Read token release
+ //
+ NdisReadConfiguration(
+ &Status,
+ &ReturnedValue,
+ ConfigHandle,
+ &TokenReleaseStr,
+ NdisParameterInteger
+ );
+
+ Adapter->EarlyTokenRelease = TRUE;
+
+ if (Status == NDIS_STATUS_SUCCESS)
+ {
+ if (ReturnedValue->ParameterData.IntegerData == 0)
+ {
+ Adapter->EarlyTokenRelease = FALSE;
+ }
+ }
+
+RegisterAdapter:
+
+ NdisCloseConfiguration(ConfigHandle);
+
+ Status = IbmtokRegisterAdapter(
+ Adapter,
+ ConfigurationHandle,
+ AdapterName,
+ McaCard,
+ ConfigError
+ );
+ if (Status != NDIS_STATUS_SUCCESS)
+ {
+ IBMTOK_FREE_PHYS(Adapter, sizeof(IBMTOK_ADAPTER));
+ }
+
+ return(Status);
+}
+
+
+
+VOID
+IbmtokRemoveAdapter(
+ IN PVOID MacAdapterContext
+ )
+
+
+/*++
+
+Routine Description:
+
+ This routine is called when an adapter is to be removed.
+
+Arguments:
+
+ MacAdapterContext - Pointer to global list of adapter blocks.
+
+Return Value:
+
+ None
+
+--*/
+
+{
+ PIBMTOK_ADAPTER Adapter;
+ BOOLEAN Canceled;
+
+ Adapter = PIBMTOK_ADAPTER_FROM_CONTEXT_HANDLE(MacAdapterContext);
+
+ //
+ // There are no opens left, so remove ourselves.
+ //
+
+ NdisDeregisterAdapterShutdownHandler(Adapter->NdisAdapterHandle);
+
+ NdisCancelTimer(&Adapter->WakeUpTimer, &Canceled);
+
+ if ( !Canceled ) {
+
+ NdisStallExecution(500000);
+ }
+
+ NdisRemoveInterrupt(&(Adapter->Interrupt));
+
+ NdisUnmapIoSpace(Adapter->NdisAdapterHandle,
+ Adapter->SharedRam,
+ (Adapter->MappedSharedRam == 0x10000) ?
+ 0x8000 :
+ Adapter->MappedSharedRam
+ );
+
+ TrDeleteFilter(Adapter->FilterDB);
+
+ NdisFreeSpinLock(&Adapter->Lock);
+
+ NdisDeregisterAdapter(Adapter->NdisAdapterHandle);
+
+ IBMTOK_FREE_PHYS(Adapter, sizeof(IBMTOK_ADAPTER));
+
+ return;
+
+}
+
+
+VOID
+IbmtokShutdown(
+ IN PVOID ShutdownContext
+ )
+
+/*++
+
+Routine Description:
+
+ Turns off the card during a powerdown of the system.
+
+Arguments:
+
+ ShutdownContext - Really a pointer to the adapter structure.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+ PIBMTOK_ADAPTER Adapter = (PIBMTOK_ADAPTER)(ShutdownContext);
+
+ //
+ // Set the flag
+ //
+
+ Adapter->NotAcceptingRequests = TRUE;
+
+ //
+ // Shutdown the card gracefully if we can, else submit a reset to remove it.
+ //
+
+ if ((Adapter->SrbAvailable) && (Adapter->SrbAddress != 0)) {
+
+ PSRB_CLOSE_ADAPTER CloseSrb = (PSRB_CLOSE_ADAPTER)Adapter->SrbAddress;
+
+ //
+ // Mask off all interrupts
+ //
+ WRITE_ADAPTER_REGISTER(Adapter, ISRP_LOW, ISRP_LOW_NO_CHANNEL_CHECK);
+
+ //
+ // Fill in the SRB for the close.
+ //
+
+ IBMTOK_ZERO_MAPPED_MEMORY(CloseSrb, sizeof(SRB_CLOSE_ADAPTER));
+
+ NdisWriteRegisterUchar((PUCHAR)&CloseSrb->Command, SRB_CMD_CLOSE_ADAPTER);
+
+ WRITE_ADAPTER_REGISTER(Adapter, ISRA_HIGH_SET, ISRA_HIGH_COMMAND_IN_SRB);
+
+ } else {
+
+ //
+ // Set the reset latch and leave it. This should turn the card
+ // off and it will be removed from the ring, but is not as graceful
+ // as actually removing ourselves as above.
+ //
+
+ WRITE_ADAPTER_PORT(Adapter, RESET_LATCH, 0);
+
+ }
+}
+
+
+VOID
+IbmtokUnload(
+ IN NDIS_HANDLE MacMacContext
+ )
+
+/*++
+
+Routine Description:
+
+ IbmtokUnload is called when the MAC is to unload itself.
+
+Arguments:
+
+ MacMacContext - nothing.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+ NDIS_STATUS InitStatus;
+
+ UNREFERENCED_PARAMETER(MacMacContext);
+
+ NdisDeregisterMac(
+ &InitStatus,
+ ((PIBMTOK_MAC)MacMacContext)->NdisMacHandle
+ );
+
+ NdisTerminateWrapper(
+ ((PIBMTOK_MAC)MacMacContext)->NdisWrapperHandle,
+ NULL
+ );
+
+ return;
+}
+
+#pragma NDIS_INIT_FUNCTION(IbmtokHardwareDetails)
+
+STATIC
+BOOLEAN
+IbmtokHardwareDetails(
+ IN PIBMTOK_ADAPTER Adapter
+ )
+
+/*++
+
+Routine Description:
+
+ This routine gets the MMIO address and interrupt level.
+ It also maps the MMIO and Shared RAM.
+
+Arguments:
+
+ Adapter - Where to store the network address.
+
+Return Value:
+
+ TRUE if successful.
+
+--*/
+
+{
+
+ NDIS_STATUS Status;
+
+ //
+ // Holds the value read from the SWITCH_READ_1 port.
+ //
+ UCHAR SwitchRead1;
+
+ //
+ // Holds the value read from the SWITCH_READ_2 port in
+ // the Microchannel Bus.
+ //
+ UCHAR SwitchRead2;
+
+ //
+ // Holds the physical address of the MMIO region.
+ //
+ ULONG MmioAddress;
+
+ NDIS_PHYSICAL_ADDRESS PhysicalAddress;
+
+ //
+ // The interrupt level;
+ //
+ UINT InterruptLevel;
+
+ //
+ // The RRR bits indicating the Shared RAM size:
+ // 0 = 8K, 1 = 16K, 2 = 32K, 3 = 64K.
+ //
+ UCHAR SharedRamBits;
+
+ //
+ // The actual size of Shared RAM from RRR bits 2,3 in
+ // the PC I/O Bus adapter.
+ //
+ UINT RrrSharedRamSize;
+
+ //
+ // Common variable for storing total Shared RAM Size.
+ //
+ UINT SharedRamSize;
+
+ //
+ // The actual address of Shared RAM from the SWITCH_READ_2
+ // port in the Microchannel adapter.
+ //
+ UINT McaSharedRam;
+
+ //
+ // The boundary needed for the Shared RAM mapping.
+ //
+ UCHAR BoundaryNeeded;
+
+ //
+ // The value read from the Shared RAM paging byte of
+ // the AIP.
+ //
+ UCHAR AipSharedRamPaging;
+
+ UCHAR RegValue;
+
+ if (IBM_TOKEN_RING_PCMCIA == Adapter->CardType)
+ {
+ UINT Nibble0;
+ UINT Nibble1;
+ UINT Nibble2;
+ UINT Nibble3;
+
+ //
+ // Configure the card to match registry
+ // Use the Default MMIO value here
+ // (this never changes from system to system)
+ //
+ MmioAddress = Adapter->MmioAddress;
+
+ //
+ // Nibble 0 - ROM address
+ //
+ Nibble0 = NIBBLE_0 | ( ( UINT )( MmioAddress >> 16 ) & 0x0F );
+
+ //
+ // Nibble 1 - ROM address, INT 0
+ //
+ Nibble1 = NIBBLE_1 | ( ( UINT )( MmioAddress >> 12) & 0x0F );
+
+ //
+ // Nibble 2 - INT1, F ROS, SRAM, S RST
+ //
+ Nibble2 = NIBBLE_2 | DEFAULT_NIBBLE_2;
+
+ //
+ // Nibble 3 - Ring Speed, RAM size, Prim/Alt
+ //
+ Nibble3 = NIBBLE_3;
+
+ if (Adapter->RingSpeed == 16)
+ {
+ Nibble3 |= RING_SPEED_16_MPS;
+ }
+ else
+ {
+ Nibble3 |= RING_SPEED_4_MPS;
+ }
+
+ switch (Adapter->RamSize)
+ {
+ case 0x10000:
+ Nibble3 |= SHARED_RAM_64K;
+ break;
+
+ case 0x8000:
+ Nibble3 |= SHARED_RAM_32K;
+ break;
+
+ case 0x4000:
+ Nibble3 |= SHARED_RAM_16K;
+ break;
+
+ case 0x2000:
+ Nibble3 |= SHARED_RAM_8K;
+ break;
+ }
+
+ if ( Adapter->IbmtokPortAddress == PRIMARY_ADAPTER_OFFSET)
+ {
+ Nibble3 |= PRIMARY;
+ }
+ else
+ {
+ Nibble3 |= ALTERNATE;
+ }
+
+#if DBG
+ if (IbmtokDbg)
+ {
+ DbgPrint("Nibble0 = %x\n",Nibble0);
+ DbgPrint("Nibble1 = %x\n",Nibble1);
+ DbgPrint("Nibble2 = %x\n",Nibble2);
+ DbgPrint("Nibble3 = %x\n",Nibble3);
+ }
+#endif
+ //
+ // Write everything to the Token-Ring
+ // Controller Configuration Register
+ //
+ WRITE_ADAPTER_PORT(Adapter, SWITCH_READ_1, Nibble0);
+ WRITE_ADAPTER_PORT(Adapter, SWITCH_READ_1, Nibble1);
+ WRITE_ADAPTER_PORT(Adapter, SWITCH_READ_1, Nibble2);
+ WRITE_ADAPTER_PORT(Adapter, SWITCH_READ_1, Nibble3);
+ WRITE_ADAPTER_PORT(Adapter, SWITCH_READ_1, RELEASE_TR_CONTROLLER);
+
+ //
+ // Use the MMIO provided by ConfigMgr here
+ //
+ MmioAddress = Adapter->MmioAddress;
+
+ NdisSetPhysicalAddressHigh(PhysicalAddress, 0);
+ NdisSetPhysicalAddressLow(PhysicalAddress, MmioAddress);
+
+ NdisMapIoSpace(
+ &Status,
+ (PVOID *)&(Adapter->MmioRegion),
+ Adapter->NdisAdapterHandle,
+ PhysicalAddress,
+ 0x2000
+ );
+
+ if (Status != NDIS_STATUS_SUCCESS)
+ {
+ NdisWriteErrorLogEntry(
+ Adapter->NdisAdapterHandle,
+ NDIS_ERROR_CODE_RESOURCE_CONFLICT,
+ 0
+ );
+
+ return(FALSE);
+ }
+
+ {
+ //
+ // Will hold the Adapter ID as read from the card.
+ //
+ ULONG AdapterId[3];
+
+ //
+ // What AdapterId should contain for a PC I/O bus card.
+ //
+ static ULONG PcIoBusId[3] = { 0x5049434f, 0x36313130, 0x39393020 };
+
+ //
+ // What AdapterId should contain for a Micro Channel card.
+ //
+ static ULONG MicroChannelId[3] = { 0x4d415253, 0x36335834, 0x35313820 };
+
+ //
+ // Loop counters.
+ //
+ UINT i, j;
+
+ UCHAR TmpUchar;
+
+ for (i = 0; i < 3; i++)
+ {
+ AdapterId[i] = 0;
+
+ for (j = 0; j < 16; j += 2)
+ {
+ ULONG Port;
+
+ Port = CHANNEL_IDENTIFIER + (i * 16) + j;
+ READ_ADAPTER_REGISTER(
+ Adapter,
+ Port,
+ &TmpUchar
+ );
+
+ AdapterId[i] = (AdapterId[i] << 4) + (TmpUchar & 0x0f);
+ }
+ }
+
+ if ((AdapterId[0] == PcIoBusId[0]) &&
+ (AdapterId[1] == PcIoBusId[1]) &&
+ (AdapterId[2] == PcIoBusId[2])
+ )
+ {
+ Adapter->UsingPcIoBus = TRUE;
+ }
+ else
+ {
+ //
+ // Unknown channel type.
+ //
+ NdisUnmapIoSpace(
+ Adapter->NdisAdapterHandle,
+ Adapter->MmioRegion,
+ 0x2000
+ );
+
+ NdisWriteErrorLogEntry(
+ Adapter->NdisAdapterHandle,
+ NDIS_ERROR_CODE_BAD_IO_BASE_ADDRESS,
+ 0
+ );
+
+ return(FALSE);
+ }
+ }
+
+ NdisSetPhysicalAddressHigh(PhysicalAddress, 0);
+ NdisSetPhysicalAddressLow(PhysicalAddress, Adapter->Ram);
+
+ NdisMapIoSpace(
+ &Status,
+ (PVOID *)&(Adapter->SharedRam),
+ Adapter->NdisAdapterHandle,
+ PhysicalAddress,
+ Adapter->RamSize
+ );
+
+ if (Status != NDIS_STATUS_SUCCESS)
+ {
+ NdisUnmapIoSpace(
+ Adapter->NdisAdapterHandle,
+ Adapter->MmioRegion,
+ 0x2000
+ );
+
+ NdisWriteErrorLogEntry(
+ Adapter->NdisAdapterHandle,
+ NDIS_ERROR_CODE_RESOURCE_CONFLICT,
+ 0
+ );
+
+ return(FALSE);
+ }
+
+ Adapter->SharedRamPaging = FALSE;
+ Adapter->MappedSharedRam = Adapter->RamSize;
+ Adapter->RrrLowValue = (UCHAR)(Adapter->Ram >> 12);
+ WRITE_ADAPTER_REGISTER(Adapter, RRR_LOW, Adapter->RrrLowValue);
+
+
+#if DBG
+ if (IbmtokDbg)
+ {
+ DbgPrint ("mmio in hw = %x\n",Adapter->MmioAddress);
+ DbgPrint ("mmio in adapter = %x\n",Adapter->MmioRegion);
+ DbgPrint ("Adapter->SharedRam = %x\n",Adapter->SharedRam);
+ DbgPrint ("Adapter->Ram = %x\n",Adapter->Ram);
+ DbgPrint ("DEFAULT_RAM = %x\n",DEFAULT_RAM);
+ {
+ UCHAR Fred;
+ READ_ADAPTER_REGISTER(Adapter, RRR_LOW, &Fred);
+ DbgPrint("RRR_LOW = %x\n",Fred);
+ READ_ADAPTER_REGISTER(Adapter, RRR_HIGH, &Fred);
+ DbgPrint("RRR_HIGH = %x\n",Fred);
+ }
+ }
+#endif
+ }
+ else
+ {
+ //
+ // SwitchRead1 contains the interrupt code in the low 2 bits,
+ // and bits 18 through 13 of the MMIO address in the high
+ // 6 bits.
+ //
+
+ READ_ADAPTER_PORT(Adapter, SWITCH_READ_1, &SwitchRead1);
+
+ //
+ // SwitchRead2 contains Bit 19 of the MMIO address in the
+ // low bit. It is always 1 for PC I/O Bus and possibly 0
+ // for the Microchannel bus
+ //
+
+ READ_ADAPTER_PORT(Adapter, SWITCH_READ_2, &SwitchRead2);
+
+ //
+ // To compute MmioAddress, we mask off the low 2 bits of
+ // SwitchRead1, shift it out by 11 (so that the high 6 bits
+ // are moved to the right place), and add in the 19th bit value.
+ //
+
+ MmioAddress = ((SwitchRead1 & 0xfc) << 11) | ((SwitchRead2 & 1) << 19);
+
+ NdisSetPhysicalAddressHigh(PhysicalAddress, 0);
+ NdisSetPhysicalAddressLow(PhysicalAddress, MmioAddress);
+
+ NdisMapIoSpace(
+ &Status,
+ (PVOID *)&(Adapter->MmioRegion),
+ Adapter->NdisAdapterHandle,
+ PhysicalAddress,
+ 0x2000);
+
+ if (Status != NDIS_STATUS_SUCCESS) {
+
+ NdisWriteErrorLogEntry(
+ Adapter->NdisAdapterHandle,
+ NDIS_ERROR_CODE_RESOURCE_CONFLICT,
+ 0
+ );
+
+ return(FALSE);
+
+ }
+
+
+ //
+ // Now we have mapped the MMIO, look at the AIP. First
+ // determine the channel identifier.
+ //
+
+ {
+ //
+ // Will hold the Adapter ID as read from the card.
+ //
+ ULONG AdapterId[3];
+
+ //
+ // What AdapterId should contain for a PC I/O bus card.
+ //
+ static ULONG PcIoBusId[3] = { 0x5049434f, 0x36313130, 0x39393020 };
+
+ //
+ // What AdapterId should contain for a Micro Channel card.
+ //
+ static ULONG MicroChannelId[3] = { 0x4d415253, 0x36335834, 0x35313820 };
+
+ //
+ // Loop counters.
+ //
+ UINT i, j;
+
+ UCHAR TmpUchar;
+
+ //
+ // Read in AdapterId.
+ //
+ // Turns out that the bytes which identify the card are stored
+ // in a very odd manner. There are 48 bytes on the card. The
+ // even numbered bytes contain 4 bits of the card signature.
+ //
+
+ for (i=0; i<3; i++) {
+
+ AdapterId[i] = 0;
+
+ for (j=0; j<16; j+=2) {
+
+ READ_ADAPTER_REGISTER(Adapter,
+ CHANNEL_IDENTIFIER + (i*16 + j),
+ &TmpUchar
+ );
+
+ AdapterId[i] = (AdapterId[i] << 4) + (TmpUchar & 0x0F);
+
+
+ }
+
+ }
+
+ if ((AdapterId[0] == PcIoBusId[0]) &&
+ (AdapterId[1] == PcIoBusId[1]) &&
+ (AdapterId[2] == PcIoBusId[2])) {
+
+ Adapter->UsingPcIoBus = TRUE;
+
+ } else if ((AdapterId[0] == MicroChannelId[0]) &&
+ (AdapterId[1] == MicroChannelId[1]) &&
+ (AdapterId[2] == MicroChannelId[2])) {
+
+ Adapter->UsingPcIoBus = FALSE;
+
+ } else {
+
+ //
+ // Unknown channel type.
+ //
+
+
+ NdisUnmapIoSpace(Adapter->NdisAdapterHandle,
+ Adapter->MmioRegion,
+ 0x2000);
+
+ NdisWriteErrorLogEntry(
+ Adapter->NdisAdapterHandle,
+ NDIS_ERROR_CODE_BAD_IO_BASE_ADDRESS,
+ 0
+ );
+
+ return FALSE;
+
+ }
+
+ }
+
+ //
+ // We can read the network address from the AIP but we won't,
+ // we read it from the bring-up SRB instead.
+ //
+
+ //
+ // Read the RRR High to get the Shared RAM size (we are
+ // only interested in bits 2 and 3).
+ //
+
+ READ_ADAPTER_REGISTER(Adapter, RRR_HIGH, &SharedRamBits);
+
+ SharedRamBits = ((SharedRamBits & 0x0c) >> 2);
+
+ if (Adapter->UsingPcIoBus) {
+
+ //
+ // Here we have to tell the Adapter where Shared RAM is
+ // going to be. To do this we first find the lowest
+ // address it could be at, and then advance the address
+ // such that it falls on a correct page boudary.
+ //
+
+
+ //
+ // To get value to put in RRR Low, which indicates where
+ // the Shared RAM is mapped, we first compute the lowest
+ // possible value, which is right after the MMIO region.
+ // We take the high six bits of SwitchRead and shift
+ // them right one (so bits 18-13 of the address are in
+ // bits 6-1), then we turn on bit 7 to indicate that bit
+ // 19 of the address is on, and leave bit 0 zero since
+ // it must be.
+ //
+
+ Adapter->RrrLowValue = (UCHAR)
+ ((((SwitchRead1 & 0xfc) >> 1) | 0x80) + 0x02);
+
+ //
+ // We now have to move up to a memory boundary
+ // based on the value of SharedRamBits; 0 (8K) = 16K boundary,
+ // 1 (16K) = 16K boundary, 2 (32K) = 32K boundary, and
+ // 3 (64K) = 64K Boundary. Remember that the way the
+ // address bits are shifted over in RrrLowValue, bit 1
+ // is really bit 13 of the final address (turning it on
+ // adds 8K), bit 2 if bit 14, etc. We compute Boundary
+ // Needed in this frame of reference.
+ //
+
+ switch (SharedRamBits) {
+
+ case 0:
+ case 1:
+
+ //
+ // 8K or 16K needs a 16K boundary.
+ //
+
+ RrrSharedRamSize = (SharedRamBits == 0) ? 0x2000 : 0x4000;
+ BoundaryNeeded = 0x04;
+ break;
+
+ case 2:
+
+ //
+ // 32K needs a 32K boundary.
+ //
+
+ RrrSharedRamSize = 0x8000;
+ BoundaryNeeded = 0x08;
+ break;
+
+ case 3:
+
+ //
+ // 64K needs a 64K boundary.
+ //
+
+ RrrSharedRamSize = 0x10000;
+ BoundaryNeeded = 0x10;
+ break;
+
+ }
+
+
+ //
+ // If RrrLowValue is not on the proper boundary, move it
+ // forward until it is.
+ //
+
+ if (Adapter->RrrLowValue & (BoundaryNeeded-1)) {
+
+ Adapter->RrrLowValue = (UCHAR)
+ ((Adapter->RrrLowValue & ~(BoundaryNeeded-1)) + BoundaryNeeded);
+
+ }
+
+ Adapter->MappedSharedRam = SharedRamSize = RrrSharedRamSize;
+
+ NdisSetPhysicalAddressHigh(PhysicalAddress, 0);
+ NdisSetPhysicalAddressLow(PhysicalAddress, Adapter->RrrLowValue << 12);
+
+ NdisMapIoSpace(&Status,
+ (PVOID *)&(Adapter->SharedRam),
+ Adapter->NdisAdapterHandle,
+ PhysicalAddress,
+ RrrSharedRamSize
+ );
+
+ if (Status != NDIS_STATUS_SUCCESS) {
+
+ NdisUnmapIoSpace(Adapter->NdisAdapterHandle,
+ Adapter->MmioRegion,
+ 0x2000);
+
+ NdisWriteErrorLogEntry(
+ Adapter->NdisAdapterHandle,
+ NDIS_ERROR_CODE_RESOURCE_CONFLICT,
+ 0
+ );
+
+ return(FALSE);
+
+ }
+
+ } else {
+
+ //
+ // Using Microchannel
+ //
+ // No need to set Adapter->RrrLowValue since it is not
+ // used in the Microchannel adapter.
+ //
+
+ switch (SharedRamBits){
+ case 0:
+ SharedRamSize = 0x2000;
+ break;
+ case 1:
+ SharedRamSize = 0x4000;
+ break;
+ case 2:
+ SharedRamSize = 0x8000;
+ break;
+ case 3:
+ SharedRamSize = 0x10000;
+ break;
+ }
+
+ McaSharedRam = ((SwitchRead2 & 0xfe) << 12);
+
+ NdisSetPhysicalAddressHigh(PhysicalAddress, 0);
+ NdisSetPhysicalAddressLow(PhysicalAddress, McaSharedRam);
+
+ NdisMapIoSpace(&Status,
+ (PVOID *)&(Adapter->SharedRam),
+ Adapter->NdisAdapterHandle,
+ PhysicalAddress,
+ SharedRamSize);
+
+ if (Status != NDIS_STATUS_SUCCESS) {
+
+ NdisUnmapIoSpace(Adapter->NdisAdapterHandle,
+ Adapter->MmioRegion,
+ 0x2000);
+
+ NdisWriteErrorLogEntry(
+ Adapter->NdisAdapterHandle,
+ NDIS_ERROR_CODE_RESOURCE_CONFLICT,
+ 0
+ );
+
+ return(FALSE);
+
+ }
+
+ Adapter->MappedSharedRam = SharedRamSize;
+
+ }
+
+
+
+ //
+ // Get the interrupt level...note that a switch being
+ // "off" shows up as a 1, "on" is 0.
+ //
+
+ switch (SwitchRead1 & 0x03) {
+
+ case 0: InterruptLevel = 2; break;
+ case 1: InterruptLevel = 3; break;
+ case 2: InterruptLevel = (Adapter->UsingPcIoBus)?6:10; break;
+ case 3: InterruptLevel = (Adapter->UsingPcIoBus)?7:11; break;
+
+ }
+
+ Adapter->InterruptLevel = InterruptLevel;
+
+ //
+ // Now determine how much memory the adapter has, and
+ // whether to use Shared RAM paging.
+ //
+
+ Adapter->UpperSharedRamZero = FALSE;
+
+ READ_ADAPTER_REGISTER(Adapter, TOTAL_ADAPTER_RAM, &RegValue);
+
+ RegValue &= 0x0F;
+
+ switch (RegValue) {
+
+ //
+ // These values are described on page 7-26 of the
+ // Technical Reference.
+ //
+
+ case 0xf:
+
+ Adapter->TotalSharedRam = SharedRamSize;
+ break;
+
+ case 0xe:
+
+ Adapter->TotalSharedRam = 0x2000;
+ break;
+
+ case 0xd:
+
+ Adapter->TotalSharedRam = 0x4000;
+ break;
+
+ case 0xc:
+
+ Adapter->TotalSharedRam = 0x8000;
+ break;
+
+ case 0xb:
+
+ Adapter->TotalSharedRam = 0x10000;
+
+ Adapter->UpperSharedRamZero = TRUE;
+ break;
+
+ case 0xa:
+
+ Adapter->TotalSharedRam = 0x10000;
+ break;
+
+ default:
+
+ NdisWriteErrorLogEntry(
+ Adapter->NdisAdapterHandle,
+ NDIS_ERROR_CODE_UNSUPPORTED_CONFIGURATION,
+ 3,
+ hardwareDetails,
+ IBMTOK_ERRMSG_UNSUPPORTED_RAM,
+ (ULONG)RegValue
+ );
+
+ NdisUnmapIoSpace(Adapter->NdisAdapterHandle,
+ Adapter->MmioRegion,
+ 0x2000);
+
+ if (Adapter->UsingPcIoBus) {
+ NdisUnmapIoSpace(
+ Adapter->NdisAdapterHandle,
+ Adapter->SharedRam,
+ SharedRamSize);
+ } else {
+ NdisUnmapIoSpace(
+ Adapter->NdisAdapterHandle,
+ Adapter->SharedRam,
+ SharedRamSize);
+ }
+
+ return FALSE;
+
+ }
+
+ //
+ // Only allow Shared RAM paging if we have 16K selected
+ // on SharedRamSize, 64K of total adapter memory, and it is allowed
+ // as specified on p. 7-26 of the Technical Reference.
+ //
+
+ READ_ADAPTER_REGISTER(Adapter, SHARED_RAM_PAGING, &AipSharedRamPaging);
+#if 0
+ if (SharedRamSize == 0x4000 &&
+ Adapter->TotalSharedRam == 0x10000 &&
+ (AipSharedRamPaging == 0xe || AipSharedRamPaging == 0xc)) {
+
+ Adapter->SharedRamPaging = TRUE;
+
+ } else {
+
+ Adapter->SharedRamPaging = FALSE;
+
+ }
+#else
+ Adapter->SharedRamPaging = FALSE;
+#endif
+ }
+
+
+ //
+ // Read in the maximum sizes allowed for DHBs based on
+ // the speed of the adapter (which we don't know yet).
+ //
+
+ READ_ADAPTER_REGISTER(Adapter, MAX_4_MBPS_DHB, &RegValue);
+
+ RegValue &= 0x0F;
+
+ switch (RegValue) {
+
+ case 0xf:
+ default:
+
+ Adapter->Max4MbpsDhb = 2048;
+ break;
+
+ case 0xe:
+
+ Adapter->Max4MbpsDhb = 4096;
+ break;
+
+ case 0xd:
+
+ Adapter->Max4MbpsDhb = 4464;
+ break;
+
+ }
+
+ READ_ADAPTER_REGISTER(Adapter, MAX_16_MBPS_DHB, &RegValue);
+
+ RegValue &= 0x0F;
+
+ switch (RegValue) {
+
+ case 0xf:
+ default:
+
+ Adapter->Max16MbpsDhb = 2048;
+ break;
+
+ case 0xe:
+
+ Adapter->Max16MbpsDhb = 4096;
+ break;
+
+ case 0xd:
+
+ Adapter->Max16MbpsDhb = 8192;
+ break;
+
+ case 0xc:
+
+ Adapter->Max16MbpsDhb = 16384;
+ break;
+
+ case 0xb:
+
+ Adapter->Max16MbpsDhb = 17960;
+ break;
+
+ }
+
+
+ return TRUE;
+
+}
diff --git a/private/ntos/ndis/ibmtok/ibmtok.rc b/private/ntos/ndis/ibmtok/ibmtok.rc
new file mode 100644
index 000000000..ef5e6e0fb
--- /dev/null
+++ b/private/ntos/ndis/ibmtok/ibmtok.rc
@@ -0,0 +1,39 @@
+#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 "IBM Token Ring 4, 16, 16/4 and 16/4A network driver"
+#define VER_INTERNALNAME_STR "IBMTOK.SYS"
+#define VER_ORIGINALFILENAME_STR "IBMTOK.SYS"
+
+#include "common.ver"
+
diff --git a/private/ntos/ndis/ibmtok/interrup.c b/private/ntos/ndis/ibmtok/interrup.c
new file mode 100644
index 000000000..eb406b02a
--- /dev/null
+++ b/private/ntos/ndis/ibmtok/interrup.c
@@ -0,0 +1,4855 @@
+/*++
+
+Copyright (c) 1990 Microsoft Corporation
+
+Module Name:
+
+ interrup.c
+
+Abstract:
+
+ This is a part of the driver for the IBM IBMTOK
+ Token-ring controller. It contains the interrupt-handling routines.
+ This driver conforms to the NDIS 3.0 interface.
+
+ The overall structure and much of the code is taken from
+ the Lance NDIS driver by Tony Ercolano.
+
+Author:
+
+ Adam Barr (adamba) 16-Jan-1991
+
+Environment:
+
+ Kernel Mode - Or whatever is the equivalent.
+
+Revision History:
+
+ Sean Selitrennikoff - 10/91
+ Fixed synchronization bugs.
+
+ Sean Selitrennikoff - 10/15/91
+ Converted to Ndis 3.0
+
+ Sean Selitrennikoff - 1/8/92
+ Added error logging
+
+ Brian E. Moore - 9/7/94
+ Added PCMCIA support
+
+--*/
+
+#pragma optimize("",off)
+
+#include <ndis.h>
+
+
+#include <tfilter.h>
+#include <tokhrd.h>
+#include <toksft.h>
+
+
+#if DEVL
+#define STATIC
+#else
+#define STATIC static
+#endif
+
+#if DBG
+extern INT IbmtokDbg;
+#endif
+
+//
+// This section contains all the functions and definitions for
+// doing logging of input and output to/from the card.
+//
+
+#if LOG
+
+//
+// Place in the circular buffer.
+//
+UCHAR IbmtokLogPlace;
+
+//
+// Circular buffer for storing log information.
+//
+UCHAR IbmtokLog[256];
+
+#endif
+
+VOID
+SetResetVariables(
+ IN PIBMTOK_ADAPTER Adapter
+ );
+
+STATIC
+VOID
+IbmtokHandleSrbSsb(
+ IN PIBMTOK_ADAPTER Adapter
+ );
+
+STATIC
+VOID
+IbmtokHandleArbAsb(
+ IN PIBMTOK_ADAPTER Adapter
+ );
+
+
+STATIC
+VOID
+HandleResetStaging(
+ IN PIBMTOK_ADAPTER Adapter
+ );
+
+STATIC
+BOOLEAN
+IbmtokSynchGetSrbSsbBits(
+ IN PVOID Context
+ );
+
+STATIC
+BOOLEAN
+IbmtokSynchGetArbAsbBits(
+ IN PVOID Context
+ );
+
+STATIC
+VOID
+PutPacketOnWaitingForAsb(
+ IN PIBMTOK_ADAPTER Adapter,
+ IN PNDIS_PACKET Packet
+ );
+
+STATIC
+PNDIS_PACKET
+RemoveTransmitFromSrb(
+ IN PIBMTOK_ADAPTER Adapter,
+ OUT PBOOLEAN PacketRemoved
+ );
+
+STATIC
+VOID
+SetupTransmitFrameSrb(
+ IN PIBMTOK_ADAPTER Adapter,
+ IN PNDIS_PACKET Packet
+ );
+
+STATIC
+VOID
+SetupTransmitStatusAsb(
+ IN PIBMTOK_ADAPTER Adapter,
+ IN PNDIS_PACKET Packet
+ );
+
+STATIC
+VOID
+GetAdapterStatisticsFromSrb(
+ PIBMTOK_ADAPTER Adapter
+ );
+
+STATIC
+VOID
+GetAdapterErrorsFromSrb(
+ PIBMTOK_ADAPTER Adapter
+ );
+
+
+STATIC
+NDIS_STATUS
+StartPendQueueOp(
+ IN PIBMTOK_ADAPTER Adapter
+ );
+
+STATIC
+NDIS_STATUS
+FinishSetOperation(
+ IN PIBMTOK_ADAPTER Adapter,
+ IN PIBMTOK_PEND_DATA PendOp
+ );
+
+
+STATIC
+BOOLEAN
+FinishPendQueueOp(
+ IN PIBMTOK_ADAPTER Adapter,
+ IN BOOLEAN Successful
+ );
+
+STATIC
+NDIS_STATUS
+SetAdapterFunctionalAddress(
+ IN PIBMTOK_ADAPTER Adapter
+ );
+
+STATIC
+VOID
+SetupFunctionalSrb(
+ IN PIBMTOK_ADAPTER Adapter,
+ IN TR_FUNCTIONAL_ADDRESS FunctionalAddress
+ );
+
+STATIC
+NDIS_STATUS
+SetAdapterGroupAddress(
+ IN PIBMTOK_ADAPTER Adapter
+ );
+
+STATIC
+VOID
+SetupGroupSrb(
+ IN PIBMTOK_ADAPTER Adapter,
+ IN TR_FUNCTIONAL_ADDRESS FunctionalAddress
+ );
+
+STATIC
+VOID
+SetupReceivedDataAsb(
+ IN PIBMTOK_ADAPTER Adapter,
+ IN SRAM_PTR ReceiveBuffer
+ );
+
+
+//
+// These macros are used to set the SRPR correctly.
+//
+#define SET_SRB_SRPR(Adapter) \
+ if (Adapter->SharedRamPaging) { \
+ WRITE_ADAPTER_REGISTER(Adapter, SRPR_LOW, Adapter->SrbSrprLow) \
+ }
+
+#define SET_SSB_SRPR(Adapter) \
+ if (Adapter->SharedRamPaging) { \
+ WRITE_ADAPTER_REGISTER(Adapter, SRPR_LOW, Adapter->SsbSrprLow) \
+ }
+
+#define SET_ARB_SRPR(Adapter) \
+ if (Adapter->SharedRamPaging) { \
+ WRITE_ADAPTER_REGISTER(Adapter, SRPR_LOW, Adapter->ArbSrprLow) \
+ }
+
+#define SET_ASB_SRPR(Adapter) \
+ if (Adapter->SharedRamPaging) { \
+ WRITE_ADAPTER_REGISTER(Adapter, SRPR_LOW, Adapter->AsbSrprLow) \
+ }
+
+
+
+typedef struct _IBMTOK_SYNCH_CONTEXT {
+
+ //
+ // Pointer to the ibmtok adapter for which interrupts are
+ // being synchronized.
+ //
+ PIBMTOK_ADAPTER Adapter;
+
+ //
+ // Points to the variable on to which the relevant
+ // interrupt bits should be ORed.
+ //
+ PVOID Local;
+
+} IBMTOK_SYNCH_CONTEXT, * PIBMTOK_SYNCH_CONTEXT;
+
+//
+// This macro is to synchronize execution with interrupts. It
+// gets the stored value of the SRB/SSB bits and clears the
+// old value.
+//
+#define GET_SRB_SSB_BITS(A,L) \
+{ \
+ PIBMTOK_ADAPTER _A = A; \
+ IBMTOK_SYNCH_CONTEXT _C; \
+ _C.Adapter = _A; \
+ _C.Local = (PVOID)(L); \
+ NdisSynchronizeWithInterrupt( \
+ &(_A->Interrupt), \
+ (PVOID) IbmtokSynchGetSrbSsbBits, \
+ &_C \
+ ); \
+}
+
+//
+// This macro is to synchronize execution with interrupts. It
+// gets the stored value of the ARB/ASB bits and clears the
+// old value.
+//
+#define GET_ARB_ASB_BITS(A,L) \
+{ \
+ PIBMTOK_ADAPTER _A = A; \
+ IBMTOK_SYNCH_CONTEXT _C; \
+ _C.Adapter = _A; \
+ _C.Local = (PVOID)(L); \
+ NdisSynchronizeWithInterrupt( \
+ &(_A->Interrupt), \
+ (PVOID) IbmtokSynchGetArbAsbBits, \
+ &_C \
+ ); \
+}
+
+
+//++
+//
+// PNDIS_PACKET
+// FindPacketGivenCorrelator(
+// IN PIBMTOK_ADAPTER Adapter,
+// IN UCHAR CommandCorrelator
+// )
+//
+//
+// Routine Description:
+//
+// This looks a packet up on the command correlator array.
+//
+// This routine should be called with the spinlock held.
+//
+// Arguments:
+//
+// Adapter - The adapter that this packet is coming through.
+//
+// CommandCorrelator - The command correlator to search based on.
+//
+// Return Value:
+//
+// The packet if found, NULL otherwise.
+//
+//--
+
+#define FindPacketGivenCorrelator(_Adapter, _CommandCorrelator) \
+ ((_Adapter)->CorrelatorArray[_CommandCorrelator])
+
+
+STATIC
+BOOLEAN
+IbmtokSynchGetSrbSsbBits(
+ IN PVOID Context
+ )
+
+/*++
+
+Routine Description:
+
+ This routine is used by the normal interrupt processing routine
+ to synchronize with interrupts from the card. It will or
+ the value of the stored SRB/SSB bits into the other passed address
+ in the context and clear the stored value.
+
+Arguments:
+
+ Context - This is really a pointer to a record type peculiar
+ to this routine. The record contains a pointer to the adapter
+ and a pointer to an address in which to place the contents
+ of the ISRP.
+
+Return Value:
+
+ Always returns true.
+
+--*/
+
+{
+ PIBMTOK_SYNCH_CONTEXT C = (PIBMTOK_SYNCH_CONTEXT)Context;
+
+ *((PUCHAR)C->Local) = (C->Adapter->IsrpBits) &
+ (ISRP_HIGH_SRB_RESPONSE | ISRP_HIGH_SSB_RESPONSE);
+
+ C->Adapter->IsrpBits = (C->Adapter->IsrpBits) &
+ (~(ISRP_HIGH_SRB_RESPONSE | ISRP_HIGH_SSB_RESPONSE));
+
+ return TRUE;
+}
+
+ULONG PCMCIAStall = 0;
+
+STATIC
+BOOLEAN
+IbmtokSynchGetArbAsbBits(
+ IN PVOID Context
+ )
+
+/*++
+
+Routine Description:
+
+ This routine is used by the normal interrupt processing routine
+ to synchronize with interrupts from the card. It will or
+ the value of the stored ARB/ASB bits into the other passed address
+ in the context and clear the stored value.
+
+Arguments:
+
+ Context - This is really a pointer to a record type peculiar
+ to this routine. The record contains a pointer to the adapter
+ and a pointer to an address in which to place the contents
+ of the ISRP.
+Return Value:
+
+ Always returns true.
+
+--*/
+
+{
+ PIBMTOK_SYNCH_CONTEXT C = (PIBMTOK_SYNCH_CONTEXT)Context;
+ UCHAR Test,i;
+IF_LOG('*');
+
+ if (C->Adapter->CardType == IBM_TOKEN_RING_PCMCIA)
+ {
+ NdisStallExecution(PCMCIAStall);
+ }
+
+ *((PUCHAR)C->Local) = (C->Adapter->IsrpBits) &
+ (ISRP_HIGH_ARB_COMMAND | ISRP_HIGH_ASB_FREE);
+
+ C->Adapter->IsrpBits = (C->Adapter->IsrpBits) &
+ (~(ISRP_HIGH_ARB_COMMAND | ISRP_HIGH_ASB_FREE));
+
+ return TRUE;
+}
+
+extern
+BOOLEAN
+IbmtokSynchSetReset(
+ IN PVOID Context
+ )
+
+/*++
+
+Routine Description:
+
+ This routine is called by the SET_INTERRUPT_RESET_FLAG macro.
+ It sets the ResetInterruptAllowed flag to TRUE.
+
+Arguments:
+
+ Context - A pointer to the Adapter structure.
+
+Return Value:
+
+ Always returns true.
+
+--*/
+
+{
+ PIBMTOK_ADAPTER Adapter = (PIBMTOK_ADAPTER)Context;
+
+ Adapter->ResetInterruptAllowed = TRUE;
+
+ return TRUE;
+}
+
+extern
+BOOLEAN
+IbmtokSynchClearIsrpBits(
+ IN PVOID Context
+ )
+
+/*++
+
+Routine Description:
+
+ This routine is called by the CLEAR_ISRP_BITS macro.
+ It clears the SRB/SSB and ARB/ASB bits. This is used
+ when a reset has started to prevent a previously
+ queued interrupt handler to come in and start
+ playing with an adapter that is being reset.
+
+Arguments:
+
+ Context - A pointer to the Adapter structure.
+
+Return Value:
+
+ Always returns true.
+
+--*/
+
+{
+ PIBMTOK_ADAPTER Adapter = (PIBMTOK_ADAPTER)Context;
+
+ Adapter->IsrpBits = 0;
+
+ return TRUE;
+}
+
+extern
+BOOLEAN
+IbmtokISR(
+ IN PVOID Context
+ )
+
+/*++
+
+Routine Description:
+
+ Interrupt service routine for the token-ring card. It's main job is
+ to get the value of ISR and record the changes in the
+ adapters own list of interrupt reasons.
+
+Arguments:
+
+ Context - Really a pointer to the adapter.
+
+Return Value:
+
+ Returns true if the card ISR is non-zero.
+
+--*/
+
+{
+
+ //
+ // Holds the pointer to the adapter.
+ //
+ PIBMTOK_ADAPTER Adapter = Context;
+
+ //
+ // Holds the value of the ISRP High
+ //
+ UCHAR IsrpHigh;
+
+ READ_ADAPTER_REGISTER(Adapter, ISRP_HIGH, &IsrpHigh);
+
+ if (!Adapter->BringUp)
+ {
+ Adapter->ContinuousIsrs++;
+
+ if (Adapter->ContinuousIsrs == 0xFF)
+ {
+ //
+ // We seemed to be confused since the DPCs aren't getting in.
+ // Shutdown and exit.
+ //
+#if DBG
+ if (IbmtokDbg)
+ DbgPrint("IBMTOK: Continuous ISRs received\n");
+#endif
+
+ WRITE_ADAPTER_PORT(Adapter, RESET_LATCH, 0);
+
+ return(FALSE);
+ }
+ }
+
+
+#if DBG
+ if (IbmtokDbg) DbgPrint("ISRP High: %x\n", IsrpHigh);
+#endif
+
+ IF_LOG('i');
+
+ //
+ // Acknowledge all the interrupts we got in IsrpHigh.
+ //
+ WRITE_ADAPTER_REGISTER(Adapter, ISRP_HIGH_RESET, (UCHAR)(~IsrpHigh));
+
+ //
+ // If the adapter is not accepting requests, ignore everything
+ // but SRB_RESPONSE interrupts, saving any others until
+ // NotAcceptingRequests goes to FALSE (note that we have
+ // already turned off ALL bits in ISRP_HIGH).
+ //
+ if (Adapter->NotAcceptingRequests)
+ {
+ Adapter->IsrpDeferredBits |= (IsrpHigh & (~ISRP_HIGH_SRB_RESPONSE));
+
+ IsrpHigh &= ISRP_HIGH_SRB_RESPONSE;
+ }
+ else
+ {
+ //
+ // Put the deferred bits back on (after the first time
+ // through they will be 0).
+ //
+ IsrpHigh |= Adapter->IsrpDeferredBits;
+
+ Adapter->IsrpDeferredBits = 0;
+ }
+
+ //
+ // Now store the bits for the DPC.
+ //
+ Adapter->IsrpBits |= IsrpHigh;
+
+ //
+ // If this is the reset interrupt, set the flag.
+ //
+ if (Adapter->ResetInterruptAllowed)
+ {
+ Adapter->ResetInterruptHasArrived = TRUE;
+ }
+
+ if (Adapter->FirstInitialization)
+ {
+ USHORT WrbOffset;
+ PSRB_BRING_UP_RESULT BringUpSrb;
+ UCHAR Value1, Value2;
+ USHORT RegValue;
+
+ READ_ADAPTER_REGISTER(Adapter, WRBR_LOW, &Value1);
+ READ_ADAPTER_REGISTER(Adapter, WRBR_HIGH, &Value2);
+
+ WrbOffset = (((USHORT)Value1) << 8) + (USHORT)Value2;
+
+ if (WrbOffset & 0x1)
+ {
+ //
+ // Mis-aligned WRB, fail to load
+ //
+ if (Adapter->UsingPcIoBus)
+ {
+ WRITE_ADAPTER_PORT(Adapter, INTERRUPT_RELEASE_ISA_ONLY, 1);
+ }
+
+ return(FALSE);
+ }
+
+ Adapter->InitialWrbOffset = WrbOffset;
+
+ BringUpSrb = (PSRB_BRING_UP_RESULT)(Adapter->SharedRam + WrbOffset);
+
+ NdisReadRegisterUshort(&(BringUpSrb->ReturnCode), &RegValue);
+
+ if (RegValue == 0x0000)
+ {
+ Adapter->BringUp = TRUE;
+ }
+
+ //
+ // If we are using the PC I/O Bus then we have to re-enable
+ // interrupts because the card is blocking all other interrupts
+ //
+ if (Adapter->UsingPcIoBus)
+ {
+ WRITE_ADAPTER_PORT(Adapter, INTERRUPT_RELEASE_ISA_ONLY, 1);
+ }
+
+ IF_LOG('I');
+
+ //
+ // no DPC for the first init.
+ //
+ return(FALSE);
+ }
+
+ //
+ // If we are using the PC I/O Bus then we have to re-enable
+ // interrupts because the card is blocking all other interrupts
+ //
+ if (Adapter->UsingPcIoBus)
+ {
+ WRITE_ADAPTER_PORT(Adapter, INTERRUPT_RELEASE_ISA_ONLY, 1);
+ }
+
+ if (IsrpHigh == 0x0)
+ {
+ //
+ // This means that the interrupt was generated from the IsrpLow
+ // and needs to be cleared.
+ //
+ READ_ADAPTER_REGISTER(Adapter, ISRP_LOW, &IsrpHigh);
+
+ //
+ // Mask off the bits we need.
+ //
+ IsrpHigh &= 0x1C;
+
+ Adapter->IsrpLowBits = IsrpHigh;
+
+ //
+ // Acknowledge all the interrupts we got in IsrpLow.
+ //
+ WRITE_ADAPTER_REGISTER(Adapter, ISRP_LOW_RESET, (UCHAR)(~IsrpHigh));
+ }
+
+ IF_LOG('I');
+
+ if (Adapter->IsrpBits != 0)
+ {
+ return TRUE;
+ }
+ else
+ {
+ return FALSE;
+ }
+}
+
+extern
+VOID
+IbmtokDPC(
+ IN PVOID SystemSpecific1,
+ IN PVOID Context,
+ IN PVOID SystemArgument1,
+ IN PVOID SystemArgument2
+ )
+
+/*++
+
+Routine Description:
+
+ This DPC routine is queued by Ndis after interrupt service routine
+ has run. It's main job is to call the interrupt processing code.
+
+Arguments:
+
+ SystemSpecific1 - Not used.
+
+ Context - Really a pointer to the adapter.
+
+ SystemArgument1(2) - Neither of these arguments used.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+ PIBMTOK_ADAPTER Adapter = (PIBMTOK_ADAPTER)Context;
+
+ NdisDprAcquireSpinLock(&Adapter->Lock);
+
+ Adapter->ContinuousIsrs = 0;
+
+ IF_LOG('d');
+
+ if (Adapter->IsrpLowBits)
+ {
+ Adapter->IsrpLowBits = 0;
+ }
+
+ if ((Adapter->IsrpBits & (ISRP_HIGH_ARB_COMMAND | ISRP_HIGH_ASB_FREE)) &&
+ (!Adapter->HandleArbRunning))
+ {
+ IbmtokHandleArbAsb(Adapter);
+
+ NdisDprAcquireSpinLock(&(Adapter->Lock));
+ }
+
+ if ((Adapter->IsrpBits & (ISRP_HIGH_SRB_RESPONSE | ISRP_HIGH_SSB_RESPONSE)) &&
+ (!Adapter->HandleSrbRunning))
+ {
+ IbmtokHandleSrbSsb(Adapter);
+ }
+ else
+ {
+ NdisDprReleaseSpinLock(&Adapter->Lock);
+ }
+
+#if DBG
+ NdisDprAcquireSpinLock(&Adapter->Lock);
+ IF_LOG('D');
+ NdisDprReleaseSpinLock(&Adapter->Lock);
+#endif
+}
+
+extern
+VOID
+IbmtokHandleSrbSsb(
+ IN PIBMTOK_ADAPTER Adapter
+ )
+
+/*++
+
+Routine Description:
+
+ This routine is called by the DPC routine
+ and other routines within the driver that notice that
+ some deferred processing needs to be done. It's main
+ job is to call the interrupt processing code.
+
+ NOTE: THIS ROUTINE IS CALLED WITH THE LOCK HELD!! AND RETURNS
+ WITH IT RELEASED!!
+
+Arguments:
+
+ Adapter - A pointer to the adapter.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+ UCHAR IsrpHigh;
+ UCHAR TmpUchar;
+ USHORT TmpUshort;
+ UCHAR Temp;
+ UINT Nibble3;
+
+ IF_LOG('h');
+
+ Adapter->References++;
+
+ if (Adapter->ResetInProgress)
+ {
+ if (Adapter->ResetInterruptHasArrived)
+ {
+ //
+ // This is the interrupt after a reset,
+ // continue things along.
+ //
+ HandleResetStaging(Adapter);
+
+ IBMTOK_DO_DEFERRED(Adapter);
+
+ return;
+ }
+ }
+
+ //
+ // If ResetInProgress is TRUE but this is an old
+ // interrupt, proceed as usual (once the reset
+ // actually starts, GET_SRB_SSB_BITS will return
+ // nothing so no work will get done).
+ //
+ Adapter->HandleSrbRunning = TRUE;
+
+ if (Adapter->CardType != IBM_TOKEN_RING_PCMCIA)
+ {
+ GET_SRB_SSB_BITS(Adapter, &IsrpHigh);
+ }
+ else
+ {
+ //
+ // disable interrupts on the card,
+ // since we don't trust ndissyncint to work
+ //
+ READ_ADAPTER_REGISTER(Adapter, ISRP_LOW, &Temp);
+
+ WRITE_ADAPTER_REGISTER(
+ Adapter,
+ ISRP_LOW,
+ Temp & ~(ISRP_LOW_NO_CHANNEL_CHECK | ISRP_LOW_INTERRUPT_ENABLE));
+
+ //
+ // update arb_asb
+ //
+ IsrpHigh = (Adapter->IsrpBits) & (ISRP_HIGH_SRB_RESPONSE | ISRP_HIGH_SSB_RESPONSE);
+ Adapter->IsrpBits = (Adapter->IsrpBits) & (~(ISRP_HIGH_SRB_RESPONSE | ISRP_HIGH_SSB_RESPONSE));
+
+ //
+ // reenable interrupts on the card
+ //
+ WRITE_ADAPTER_REGISTER(
+ Adapter,
+ ISRP_LOW,
+ ISRP_LOW_NO_CHANNEL_CHECK | ISRP_LOW_INTERRUPT_ENABLE);
+ }
+
+ while (IsrpHigh & (ISRP_HIGH_SRB_RESPONSE | ISRP_HIGH_SSB_RESPONSE))
+ {
+ IF_LOG((UCHAR)(Adapter->OpenInProgress));
+
+ if (Adapter->Unplugged && !Adapter->UnpluggedResetInProgress)
+ {
+ //
+ // Do, nothing. This is most likely a stale interrupt. We
+ // wait until we get a ring status interrupt telling us that
+ // the cable is plugged in.
+ //
+ break;
+ }
+
+ if (IsrpHigh & ISRP_HIGH_SRB_RESPONSE)
+ {
+ if (Adapter->OpenInProgress)
+ {
+ //
+ // Handle the result of the DIR.OPEN.ADAPTER command.
+ //
+ PSRB_OPEN_RESPONSE OpenResponseSrb;
+ PIBMTOK_OPEN Open;
+ PLIST_ENTRY CurrentLink;
+ UCHAR ReturnCode;
+
+ OpenResponseSrb = (PSRB_OPEN_RESPONSE)
+ (Adapter->SharedRam + Adapter->InitialWrbOffset);
+
+ NdisReadRegisterUchar(&(OpenResponseSrb->ReturnCode), &ReturnCode);
+
+#if DBG
+ if (IbmtokDbg)
+ DbgPrint("IBMTOK: OPEN, Return code = %x, at %lx\n",
+ ReturnCode,
+ OpenResponseSrb);
+#endif
+
+//
+ if (ReturnCode == 0x0)
+ {
+ NdisDprReleaseSpinLock(&(Adapter->Lock));
+
+ if (Adapter->SharedRamPaging)
+ {
+ NdisReadRegisterUshort(&(OpenResponseSrb->SrbPointer), &TmpUshort);
+
+ TmpUshort = IBMSHORT_TO_USHORT(TmpUshort);
+
+ Adapter->SrbAddress = SHARED_RAM_ADDRESS(Adapter,
+ SHARED_RAM_LOW_BITS(TmpUshort));
+ Adapter->SrbSrprLow = (UCHAR)(TmpUshort >> 14);
+
+
+ NdisReadRegisterUshort(&(OpenResponseSrb->SsbPointer), &TmpUshort);
+
+ TmpUshort = IBMSHORT_TO_USHORT(TmpUshort);
+
+ Adapter->SsbAddress = SHARED_RAM_ADDRESS(Adapter,
+ SHARED_RAM_LOW_BITS(TmpUshort));
+ Adapter->SsbSrprLow = (UCHAR)(TmpUshort >> 14);
+
+
+ NdisReadRegisterUshort(&(OpenResponseSrb->ArbPointer), &TmpUshort);
+
+ TmpUshort = IBMSHORT_TO_USHORT(TmpUshort);
+
+ Adapter->ArbAddress = SHARED_RAM_ADDRESS(Adapter,
+ SHARED_RAM_LOW_BITS(TmpUshort));
+ Adapter->ArbSrprLow = (UCHAR)(TmpUshort >> 14);
+
+
+ NdisReadRegisterUshort(&(OpenResponseSrb->AsbPointer), &TmpUshort);
+
+ TmpUshort = IBMSHORT_TO_USHORT(TmpUshort);
+
+ Adapter->AsbAddress = SHARED_RAM_ADDRESS(Adapter,
+ SHARED_RAM_LOW_BITS(TmpUshort));
+ Adapter->AsbSrprLow = (UCHAR)(TmpUshort >> 14);
+ }
+ else
+ {
+ NdisReadRegisterUshort(&(OpenResponseSrb->SrbPointer), &TmpUshort);
+ Adapter->SrbAddress = SRAM_PTR_TO_PVOID(Adapter, TmpUshort);
+
+ NdisReadRegisterUshort(&(OpenResponseSrb->SsbPointer), &TmpUshort);
+ Adapter->SsbAddress = SRAM_PTR_TO_PVOID(Adapter, TmpUshort);
+
+ NdisReadRegisterUshort(&(OpenResponseSrb->ArbPointer), &TmpUshort);
+ Adapter->ArbAddress = SRAM_PTR_TO_PVOID(Adapter, TmpUshort);
+
+ NdisReadRegisterUshort(&(OpenResponseSrb->AsbPointer), &TmpUshort);
+ Adapter->AsbAddress = SRAM_PTR_TO_PVOID(Adapter, TmpUshort);
+ }
+
+ if (((ULONG)Adapter->SrbAddress >
+ (ULONG)(Adapter->SharedRam + Adapter->MappedSharedRam)) ||
+ ((ULONG)Adapter->SsbAddress >
+ (ULONG)(Adapter->SharedRam + Adapter->MappedSharedRam)) ||
+ ((ULONG)Adapter->ArbAddress >
+ (ULONG)(Adapter->SharedRam + Adapter->MappedSharedRam)) ||
+ ((ULONG)Adapter->AsbAddress >
+ (ULONG)(Adapter->SharedRam + Adapter->MappedSharedRam)))
+ {
+ //
+ // Something is definitely wrong. Fail!
+ //
+ goto OpenFailed;
+ }
+
+#if DBG
+ if (IbmtokDbg)
+ {
+ USHORT TmpUshort1;
+ USHORT TmpUshort2;
+ USHORT TmpUshort3;
+ USHORT TmpUshort4;
+ NdisReadRegisterUshort(&(OpenResponseSrb->SrbPointer), &TmpUshort1);
+ NdisReadRegisterUshort(&(OpenResponseSrb->SsbPointer), &TmpUshort2);
+ NdisReadRegisterUshort(&(OpenResponseSrb->ArbPointer), &TmpUshort3);
+ NdisReadRegisterUshort(&(OpenResponseSrb->AsbPointer), &TmpUshort4);
+ DbgPrint("IBMTOK: Offsets: SRB %x SSB %x ARB %x ASB %x\n",
+ IBMSHORT_TO_USHORT(TmpUshort1),
+ IBMSHORT_TO_USHORT(TmpUshort2),
+ IBMSHORT_TO_USHORT(TmpUshort3),
+ IBMSHORT_TO_USHORT(TmpUshort4));
+ }
+#endif
+
+ //
+ // Now we have to start worrying about synchronization.
+ //
+ NdisDprAcquireSpinLock(&(Adapter->Lock));
+
+ Adapter->CurrentRingState = NdisRingStateOpened;
+ Adapter->OpenInProgress = FALSE;
+ Adapter->OpenErrorCode = 0;
+ Adapter->AdapterNotOpen = FALSE;
+ Adapter->NotAcceptingRequests = FALSE;
+
+ //
+ // Complete all opens that pended during this operation.
+ //
+ CurrentLink = Adapter->OpenBindings.Flink;
+
+ while (CurrentLink != &(Adapter->OpenBindings))
+ {
+ Open = CONTAINING_RECORD(CurrentLink, IBMTOK_OPEN, OpenList);
+ if (Open->OpenPending)
+ {
+ Open->OpenPending = FALSE;
+ NdisDprReleaseSpinLock(&(Adapter->Lock));
+
+ NdisCompleteOpenAdapter(
+ Open->NdisBindingContext,
+ NDIS_STATUS_SUCCESS,
+ 0);
+
+ NdisDprAcquireSpinLock(&(Adapter->Lock));
+ }
+
+ CurrentLink = CurrentLink->Flink;
+ }
+
+ //
+ // Get any interrupts that have been deferred
+ // while NotAcceptingRequests was TRUE.
+ //
+ IbmtokForceAdapterInterrupt(Adapter);
+ }
+ else
+ {
+ //
+ // Open Failed!
+ //
+ // Here is where I check the return code from the Open and see if it
+ // indicates an incorrect ring speed. If it does, I change the ring speed
+ // and reissue the OpenAdapter. BEM
+ //
+ NdisReadRegisterUshort(
+ &(OpenResponseSrb->ErrorCode),
+ &(TmpUshort));
+
+ //
+ // If a catastrophic error and a frequency error and we want ring speed listen
+ // and the number of retries > 0, bail out. We have already tried a different
+ // speed
+ //
+ if ((ReturnCode == 0x07) && // catastrophic error
+ (TmpUshort == 0x2400) && // frequency error
+ Adapter->RingSpeedListen && // we want ring speed listen
+ (Adapter->RingSpeedRetries == 0)) // have not tried before
+ {
+#if DBG
+ if (IbmtokDbg)
+ DbgPrint("IBMTOK: Incorrect Ring Speed, Changing.\n");
+#endif
+ //
+ //
+ // Change the ring speed
+ //
+
+ if (Adapter->Running16Mbps == TRUE)
+ Adapter->Running16Mbps == FALSE;
+ else
+ Adapter->Running16Mbps == TRUE;
+
+ Nibble3 = NIBBLE_3;
+
+ if (Adapter->RingSpeed == 16)
+ { // swap speeds
+ Nibble3 |= RING_SPEED_4_MPS;
+ }
+ else
+ {
+ Nibble3 |= RING_SPEED_16_MPS;
+ }
+
+ switch (Adapter->RamSize)
+ {
+ case 0x10000:
+ Nibble3 |= SHARED_RAM_64K;
+ break;
+ case 0x8000:
+ Nibble3 |= SHARED_RAM_32K;
+ break;
+ case 0x4000:
+ Nibble3 |= SHARED_RAM_16K;
+ break;
+ case 0x2000:
+ Nibble3 |= SHARED_RAM_8K;
+ break;
+ }
+
+ WRITE_ADAPTER_PORT(Adapter, SWITCH_READ_1, Nibble3);
+
+ //
+ // Now to reissue the Open Adapter SRB with the necessary changes.
+ //
+ // Reset these fields in the SRB for the Open Adapter.
+ //
+ OpenResponseSrb->ReturnCode = 0xFE;
+ OpenResponseSrb->ErrorCode = 0x0000;
+
+ // DbgBreakPoint();
+ //
+ // Tell the adapter to handle the change.
+ //
+ WRITE_ADAPTER_REGISTER(
+ Adapter,
+ ISRA_HIGH_SET,
+ ISRA_HIGH_COMMAND_IN_SRB);
+
+ Adapter->RingSpeedRetries++; // first retry
+
+ // end of check for incorrect ring speed
+ }
+ else
+ {
+OpenFailed:
+#if DBG
+ if (IbmtokDbg)
+ {
+ DbgPrint("IBMTOK: Open failed!\n");
+ }
+#endif
+ //
+ // Now we have to start worrying about synchronization.
+ //
+ Adapter->CurrentRingState = NdisRingStateOpenFailure;
+ Adapter->OpenInProgress = FALSE;
+ NdisReadRegisterUshort(
+ &(OpenResponseSrb->ErrorCode),
+ &(Adapter->OpenErrorCode));
+ Adapter->OpenErrorCode = IBMSHORT_TO_USHORT(Adapter->OpenErrorCode);
+ Adapter->AdapterNotOpen = TRUE;
+ Adapter->NotAcceptingRequests = TRUE;
+
+ //
+ // Fail all opens that pended during this operation.
+ //
+ CurrentLink = Adapter->OpenBindings.Flink;
+
+ while (CurrentLink != &(Adapter->OpenBindings))
+ {
+ Open = CONTAINING_RECORD(
+ CurrentLink,
+ IBMTOK_OPEN,
+ OpenList);
+
+ if (Open->OpenPending)
+ {
+ Open->OpenPending = FALSE;
+
+ NdisDprReleaseSpinLock(&(Adapter->Lock));
+
+ NdisCompleteOpenAdapter(
+ Open->NdisBindingContext,
+ NDIS_STATUS_OPEN_FAILED,
+ NDIS_STATUS_TOKEN_RING_OPEN_ERROR |
+ (NDIS_STATUS)(Adapter->OpenErrorCode));
+
+ NdisDprAcquireSpinLock(&(Adapter->Lock));
+
+ CurrentLink = CurrentLink->Flink;
+
+ RemoveEntryList(&(Open->OpenList));
+
+ IBMTOK_FREE_PHYS(Open, sizeof(IBMTOK_OPEN));
+
+ Adapter->References--;
+ }
+ else
+ {
+ //
+ // Note: All opens are pending, otherwise the
+ // adapter would have already been open.
+ //
+ }
+ }
+ }
+ }
+ }
+ else
+ {
+#if DBG
+ if (IbmtokDbg)
+ DbgPrint("IBMTOK: SRB Response\n");
+#endif
+ IF_LOG('>');
+
+ if (Adapter->TransmittingPacket != (PNDIS_PACKET)NULL)
+ {
+ BOOLEAN PacketRemoved;
+
+ //
+ // Happens if the transmit failed.
+ //
+ (PVOID)RemoveTransmitFromSrb(Adapter, &PacketRemoved);
+
+ //
+ // If the packet was successfully removed, then
+ // start the next command.
+ //
+ // This will release the spin lock.
+ //
+ if (PacketRemoved)
+ {
+ //
+ // SrbAvailable will still be FALSE here,
+ // as required.
+ //
+ SetupSrbCommand(Adapter);
+ }
+ }
+ else if (!Adapter->SrbAvailable)
+ {
+ PSRB_GENERIC GenericSrb = (PSRB_GENERIC)Adapter->SrbAddress;
+ UCHAR ReturnCode;
+
+ //
+ // Another command in progress, complete it unless
+ // it was an INTERRUPT command.
+ //
+ NdisReadRegisterUchar(&(GenericSrb->ReturnCode), &ReturnCode);
+
+ IF_LOG('N');
+
+ NdisReadRegisterUchar(&(GenericSrb->Command), &TmpUchar);
+
+ if (TmpUchar != SRB_CMD_INTERRUPT)
+ {
+ if ((TmpUchar != SRB_CMD_READ_LOG) &&
+ (TmpUchar != SRB_CMD_SET_FUNCTIONAL_ADDRESS) &&
+ (TmpUchar != SRB_CMD_SET_GROUP_ADDRESS) &&
+ (TmpUchar != SRB_CMD_DLC_STATISTICS))
+ {
+ //
+ // We have an invalid response. Log an error an exit.
+ //
+ NdisWriteErrorLogEntry(
+ Adapter->NdisAdapterHandle,
+ NDIS_ERROR_CODE_INVALID_VALUE_FROM_ADAPTER,
+ 3,
+ handleSrbSsb,
+ IBMTOK_ERRMSG_INVALID_CMD,
+ (ULONG)TmpUchar);
+ }
+ else
+ {
+ //
+ // This interrupt had to come from a pended op.
+ //
+ ASSERT(Adapter->PendData != NULL);
+
+ if (Adapter->PendData->RequestType == NdisRequestGeneric1)
+ {
+ //
+ // If no request, it came as a result of the
+ // card overflowing a counter and then we
+ // submitted the correcting operation.
+ //
+ if (ReturnCode == 0x00)
+ {
+ if (Adapter->PendData->COMMAND.MAC.ReadLogPending)
+ {
+ //
+ // We are getting an SRB_CMD_READ_LOG from
+ // we sent as a result to a RING_STATUS_CHANGE.
+ //
+ GetAdapterErrorsFromSrb(Adapter);
+ }
+ else
+ {
+ //
+ // We are getting an SRB_CMD_DLC_STATISTICS from
+ // we sent as a result to a DLC_STATUS.
+ //
+ GetAdapterStatisticsFromSrb(Adapter);
+ }
+ }
+
+ //
+ // Free up pend operation.
+ //
+ IBMTOK_FREE_PHYS(Adapter->PendData, sizeof(IBMTOK_PEND_DATA));
+
+ Adapter->PendData = NULL;
+
+ //
+ // Fire off next command.
+ //
+ SetupSrbCommand(Adapter);
+ }
+ else
+ {
+ //
+ // This is the result of a pending op from Ndis.
+ //
+ if (FinishPendQueueOp(
+ Adapter,
+ (BOOLEAN)(ReturnCode == 0x00 ? TRUE : FALSE)))
+ {
+
+ //
+ // Fire off next command.
+ //
+ SetupSrbCommand(Adapter);
+ }
+ }
+ }
+ }
+ else
+ {
+ SetupSrbCommand(Adapter);
+ }
+ }
+ else
+ {
+ //
+ // Nothing to do -- we get here when an SRB_FREE_REQUEST
+ // comes through after the ARB to transfer the data has
+ // already come through.
+ //
+ }
+ }
+ }
+
+ if (IsrpHigh & ISRP_HIGH_SSB_RESPONSE)
+ {
+ //
+ // This has to be a transmit completing since
+ // that is the only operation we do that pends.
+ //
+ PSSB_TRANSMIT_COMPLETE ResponseSsb =
+ (PSSB_TRANSMIT_COMPLETE)Adapter->SsbAddress;
+
+ NdisReadRegisterUchar(&(ResponseSsb->Command), &TmpUchar);
+
+ if (TmpUchar == SRB_CMD_TRANSMIT_DIR_FRAME)
+ {
+ UCHAR CorrelatorInSrb;
+ NDIS_STATUS SendStatus;
+ UCHAR SrbReturnCode;
+
+ //
+ // Initialize this to one less since the loop starts by
+ // incrementing it.
+ //
+ UCHAR CurrentCorrelator = (UCHAR)
+ ((Adapter->NextCorrelatorToComplete +
+ (MAX_COMMAND_CORRELATOR-1)) %
+ MAX_COMMAND_CORRELATOR);
+
+ NdisReadRegisterUchar(&(ResponseSsb->CommandCorrelator), &CorrelatorInSrb);
+
+ //
+ // Have to loop to complete since supposedly one
+ // of these can indicate multiple completing sends.
+ //
+
+ //
+ // Figure out what the return code should be.
+ //
+ NdisReadRegisterUchar(&(ResponseSsb->ReturnCode), &SrbReturnCode);
+
+ if (SrbReturnCode == 0x00)
+ {
+ SendStatus = NDIS_STATUS_SUCCESS;
+ }
+ else if (SrbReturnCode == 0x22)
+ {
+ //
+ // Check the frame status.
+ //
+ UCHAR FrameStatus;
+ UCHAR HighAc;
+ UCHAR LowAc;
+
+ NdisReadRegisterUchar(&(ResponseSsb->ErrorFrameStatus), &FrameStatus);
+ HighAc = GET_FRAME_STATUS_HIGH_AC(FrameStatus);
+ LowAc = GET_FRAME_STATUS_LOW_AC(FrameStatus);
+
+ if (HighAc != LowAc ||
+ (HighAc != AC_NOT_RECOGNIZED))
+ {
+ SendStatus = NDIS_STATUS_NOT_RECOGNIZED;
+ }
+ else
+ {
+ SendStatus = NDIS_STATUS_SUCCESS;
+ }
+
+#if DBG
+ if (IbmtokDbg) DbgPrint("IBMTOK: Send failed, code %x err %x\n",
+ SrbReturnCode,
+ FrameStatus);
+#endif
+
+ }
+ else
+ {
+ SendStatus = NDIS_STATUS_FAILURE;
+#if DBG
+ if (IbmtokDbg) DbgPrint("IBMTOK: Send failed, code %x\n",
+ SrbReturnCode);
+#endif
+ }
+
+ NdisDprReleaseSpinLock(&(Adapter->Lock));
+
+ do
+ {
+ PNDIS_PACKET TransmitPacket;
+ PIBMTOK_RESERVED Reserved;
+ PIBMTOK_OPEN Open;
+
+ CurrentCorrelator = (UCHAR)((CurrentCorrelator + 1) %
+ MAX_COMMAND_CORRELATOR);
+
+ //
+ // Complete the transmit.
+ //
+ TransmitPacket =
+ FindPacketGivenCorrelator(Adapter, CurrentCorrelator);
+
+ if (TransmitPacket == (PNDIS_PACKET)NULL)
+ {
+#if DBG
+ if (IbmtokDbg) DbgPrint("IBMTOK: Missing %d to complete, %d to %d\n",
+ CurrentCorrelator,
+ Adapter->NextCorrelatorToComplete,
+ CorrelatorInSrb);
+#endif
+ continue;
+ }
+
+ RemovePacketFromCorrelatorArray(Adapter, TransmitPacket);
+
+ Reserved = PIBMTOK_RESERVED_FROM_PACKET(TransmitPacket);
+
+ Open =
+ PIBMTOK_OPEN_FROM_BINDING_HANDLE(Reserved->MacBindingHandle);
+
+ //
+ // If doing LOOPBACK, this should really be a check
+ // of ReadyToComplete etc.
+ //
+#ifdef CHECK_DUP_SENDS
+ {
+ VOID IbmtokRemovePacketFromList(PIBMTOK_ADAPTER, PNDIS_PACKET);
+ IbmtokRemovePacketFromList(Adapter, TransmitPacket);
+ }
+#endif
+
+ if (SendStatus == NDIS_STATUS_SUCCESS)
+ {
+ Adapter->FramesTransmitted++;
+ }
+ else
+ {
+ Adapter->FrameTransmitErrors++;
+ }
+
+ NdisCompleteSend(
+ Open->NdisBindingContext,
+ Reserved->Packet,
+ SendStatus);
+
+ //
+ // Decrement the reference count for the open.
+ //
+#if DBG
+ NdisDprAcquireSpinLock(&(Adapter->Lock));
+ IF_LOG('C');
+ NdisDprReleaseSpinLock(&(Adapter->Lock));
+#endif
+ NdisInterlockedAddUlong((PULONG)&Open->References, (UINT)-1, &Adapter->Lock);
+
+ } while (CurrentCorrelator != CorrelatorInSrb);
+
+ NdisDprAcquireSpinLock(&(Adapter->Lock));
+
+ Adapter->SendTimeout = FALSE;
+
+ Adapter->NextCorrelatorToComplete =
+ (UCHAR)((CurrentCorrelator + 1) % MAX_COMMAND_CORRELATOR);
+
+ //
+ // We know that SrbAvailable is FALSE...
+ //
+ IF_LOG('<');
+
+ SetupSrbCommand(Adapter);
+ }
+ else
+ {
+ //
+ // Nothing else should pend!!
+ //
+ NdisWriteErrorLogEntry(
+ Adapter->NdisAdapterHandle,
+ NDIS_ERROR_CODE_INVALID_VALUE_FROM_ADAPTER,
+ 3,
+ handleSrbSsb,
+ IBMTOK_ERRMSG_INVALID_CMD,
+ (ULONG)TmpUchar);
+
+#if DBG
+ if (IbmtokDbg) DbgPrint("IBMTOK: Error! Got Cmd %x\n",TmpUchar);
+#endif
+ }
+
+ WRITE_ADAPTER_REGISTER(
+ Adapter,
+ ISRA_HIGH_SET,
+ ISRA_HIGH_SSB_FREE);
+ }
+
+ if (Adapter->CardType != IBM_TOKEN_RING_PCMCIA)
+ {
+ GET_SRB_SSB_BITS(Adapter, &IsrpHigh);
+ }
+ else
+ {
+ //
+ // disable interrupts on the card, since we don't trust ndissyncint to work
+ //
+ READ_ADAPTER_REGISTER(Adapter, ISRP_LOW, &Temp);
+
+ WRITE_ADAPTER_REGISTER(
+ Adapter,
+ ISRP_LOW,
+ Temp & (~(ISRP_LOW_NO_CHANNEL_CHECK | ISRP_LOW_INTERRUPT_ENABLE) ) );
+
+ //
+ // update arb_asb
+ //
+ IsrpHigh = (Adapter->IsrpBits) & (ISRP_HIGH_SRB_RESPONSE | ISRP_HIGH_SSB_RESPONSE);
+ Adapter->IsrpBits = (Adapter->IsrpBits) & (~(ISRP_HIGH_SRB_RESPONSE | ISRP_HIGH_SSB_RESPONSE));
+
+ //
+ // reenable interrupts on the card
+ //
+ WRITE_ADAPTER_REGISTER(
+ Adapter,
+ ISRP_LOW,
+ ISRP_LOW_NO_CHANNEL_CHECK | ISRP_LOW_INTERRUPT_ENABLE);
+ }
+ }
+
+ Adapter->HandleSrbRunning = FALSE;
+
+ IF_LOG('H');
+
+ //
+ // This macro assumes it is called with the lock held,
+ // and releases it.
+ //
+ IBMTOK_DO_DEFERRED(Adapter);
+}
+
+extern
+VOID
+IbmtokHandleArbAsb(
+ IN PIBMTOK_ADAPTER Adapter
+ )
+
+/*++
+
+Routine Description:
+
+ This routine is called by the DPC
+ and other routines within the driver that notice that
+ some deferred processing needs to be done. It's main
+ job is to call the interrupt processing code.
+
+ NOTE: THIS ROUTINE IS CALLED WITH THE LOCK HELD!! AND RETURNS WITH
+ THE LOCK REALEASED!!
+
+Arguments:
+
+ Adapter - A pointer to the adapter.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+ UCHAR IsrpHigh;
+
+ PARB_TRANSMIT_DATA_REQUEST TransmitDataArb;
+
+ PARB_RECEIVED_DATA ReceivedDataArb;
+
+ PNDIS_PACKET TransmitPacket;
+
+ SRAM_PTR ReceiveBufferPointer;
+
+ PRECEIVE_BUFFER ReceiveBuffer;
+
+ UINT PacketLength, DummyBytesCopied;
+
+ BOOLEAN FreedSrb;
+
+ PIBMTOK_RESERVED Reserved;
+
+ PUCHAR DhbAddress;
+
+ UINT PacketSize, LookaheadSize;
+
+ PUCHAR FrameData;
+
+ ULONG HeaderLength;
+
+ UCHAR TmpUchar;
+
+ USHORT TmpUshort;
+
+ PUCHAR LookaheadBuffer;
+
+ UCHAR Temp;
+
+ Adapter->References++;
+
+ Adapter->HandleArbRunning = TRUE;
+
+ IF_LOG('j');
+
+ if (Adapter->CardType != IBM_TOKEN_RING_PCMCIA)
+ {
+ GET_ARB_ASB_BITS(Adapter, &IsrpHigh);
+ }
+ else
+ {
+ //
+ // disable interrupts on the card, since we don't trust ndissyncint to work
+ //
+ READ_ADAPTER_REGISTER(Adapter, ISRP_LOW, &Temp);
+
+ WRITE_ADAPTER_REGISTER(
+ Adapter,
+ ISRP_LOW,
+ Temp & (~(ISRP_LOW_NO_CHANNEL_CHECK | ISRP_LOW_INTERRUPT_ENABLE) ) );
+
+ //
+ // update arb_asb
+ //
+ IsrpHigh = (Adapter->IsrpBits) & (ISRP_HIGH_ARB_COMMAND | ISRP_HIGH_ASB_FREE);
+ Adapter->IsrpBits = (Adapter->IsrpBits) & (~(ISRP_HIGH_ARB_COMMAND | ISRP_HIGH_ASB_FREE));
+
+ //
+ // reenable interrupts on the card
+ //
+ WRITE_ADAPTER_REGISTER(
+ Adapter,
+ ISRP_LOW,
+ ISRP_LOW_NO_CHANNEL_CHECK | ISRP_LOW_INTERRUPT_ENABLE);
+ }
+
+ while (IsrpHigh & (ISRP_HIGH_ARB_COMMAND | ISRP_HIGH_ASB_FREE))
+ {
+ if (IsrpHigh & ISRP_HIGH_ARB_COMMAND)
+ {
+ NdisReadRegisterUchar(&((PARB_GENERIC)Adapter->ArbAddress)->Command, &TmpUchar);
+
+ switch (TmpUchar)
+ {
+ case ARB_CMD_DLC_STATUS:
+#if DBG
+ if (IbmtokDbg)
+ {
+ NdisReadRegisterUshort(
+ &((PARB_DLC_STATUS)Adapter->ArbAddress)->Status, &TmpUshort);
+ DbgPrint("IBMTOK: DLC Status %x\n",
+ IBMSHORT_TO_USHORT(TmpUshort));
+ }
+#endif
+
+ WRITE_ADAPTER_REGISTER(Adapter, ISRA_HIGH_SET,
+ ISRA_HIGH_ARB_FREE);
+
+ IF_LOG('#');
+
+ //
+ // If it is a counter overflow, we need to queue a
+ // DLC.STATISTICS command.
+ //
+ NdisReadRegisterUshort(
+ &((PARB_RING_STATUS_CHANGE)Adapter->ArbAddress)->NetworkStatus,
+ &TmpUshort);
+
+ if (IBMSHORT_TO_USHORT(TmpUshort) & 0x0040 )
+ {
+ //
+ // Build a pending operation. It will get run ASAP
+ // by ProcessSrbCommand.
+ //
+ PIBMTOK_PEND_DATA PendOp;
+
+ if (IBMTOK_ALLOC_PHYS(&PendOp,sizeof(IBMTOK_PEND_DATA)) !=
+ NDIS_STATUS_SUCCESS)
+ {
+ NdisWriteErrorLogEntry(
+ Adapter->NdisAdapterHandle,
+ NDIS_ERROR_CODE_OUT_OF_RESOURCES,
+ 2,
+ handleSrbSsb,
+ IBMTOK_ERRMSG_ALLOC_MEM);
+
+ break;
+ }
+
+ PendOp->Next = NULL;
+ PendOp->RequestType = NdisRequestGeneric1;
+ PendOp->COMMAND.MAC.ReadLogPending = FALSE;
+
+ if (Adapter->PendQueue == NULL)
+ {
+ Adapter->PendQueue = Adapter->EndOfPendQueue = PendOp;
+ }
+ else
+ {
+ //
+ // Put this operation on the front, so it can
+ // correct the error quickly.
+ //
+ PendOp->Next = Adapter->PendQueue;
+ Adapter->PendQueue = PendOp;
+ }
+
+ //
+ // It is now in the pend
+ // queue so we should start that up.
+ //
+ IbmtokProcessSrbRequests(Adapter);
+ }
+
+ break;
+
+ case ARB_CMD_RECEIVED_DATA:
+
+#if DBG
+ if (IbmtokDbg)
+ DbgPrint("IBMTOK: Received data\n");
+#endif
+ IF_LOG('r');
+
+ if (Adapter->Unplugged && !Adapter->UnpluggedResetInProgress)
+ {
+ //
+ // Do, nothing. This is most likely a stale interrupt. We
+ // wait until we get a ring status interrupt telling us that
+ // the cable is plugged in.
+ //
+ break;
+ }
+
+ ReceivedDataArb = (PARB_RECEIVED_DATA)Adapter->ArbAddress;
+
+ NdisReadRegisterUshort(&(ReceivedDataArb->ReceiveBuffer), &ReceiveBufferPointer);
+
+ //
+ // Prepare for indication.
+ //
+ Adapter->IndicatedReceiveBuffer = ReceiveBufferPointer;
+
+ ReceiveBuffer = (PRECEIVE_BUFFER)
+ ((PUCHAR)SRAM_PTR_TO_PVOID(Adapter, ReceiveBufferPointer) + 2);
+
+ NdisReadRegisterUshort(&(ReceivedDataArb->FrameLength), &PacketSize);
+
+ PacketSize = IBMSHORT_TO_USHORT(PacketSize);
+
+ NdisReadRegisterUshort(&(ReceiveBuffer->BufferLength), &LookaheadSize);
+
+ LookaheadSize = IBMSHORT_TO_USHORT(LookaheadSize);
+
+ WRITE_ADAPTER_REGISTER(
+ Adapter,
+ ISRA_HIGH_SET,
+ ISRA_HIGH_ARB_FREE);
+
+#if DBG
+ if (IbmtokDbg)
+ DbgPrint("IBMTOK: indicate len %d, lookahead %d\n", PacketSize, LookaheadSize);
+#endif
+
+ //
+ // Calculate how big the header is for this
+ // packet.
+ //
+ FrameData = ReceiveBuffer->FrameData;
+
+ NdisReadRegisterUchar(&FrameData[8], &TmpUchar);
+
+ if (TmpUchar & 0x80)
+ {
+ //
+ // Source routing bit is on in source address.
+ //
+ NdisReadRegisterUchar(&FrameData[14], &TmpUchar);
+ HeaderLength = (TmpUchar & 0x1f) + 14;
+ }
+ else
+ {
+ HeaderLength = 14;
+ }
+
+ Adapter->IndicatedHeaderLength = (USHORT)HeaderLength;
+
+ Adapter->FramesReceived++;
+
+ NdisDprReleaseSpinLock(&Adapter->Lock);
+
+ //
+ // Call into the filter package to do the
+ // indication.
+ //
+ if (LookaheadSize < HeaderLength)
+ {
+ //
+ // Must at least have an address
+ //
+ if (LookaheadSize >= TR_LENGTH_OF_ADDRESS)
+ {
+ NdisCreateLookaheadBufferFromSharedMemory(
+ (PVOID)FrameData,
+ LookaheadSize,
+ &LookaheadBuffer);
+
+ if (LookaheadBuffer != NULL)
+ {
+ //
+ // Runt Packet
+ //
+ TrFilterIndicateReceive(
+ Adapter->FilterDB,
+ (NDIS_HANDLE)ReceiveBuffer, // context
+ LookaheadBuffer, // header
+ LookaheadSize, // header length
+ NULL, // lookahead
+ 0, // lookahead length
+ 0);
+
+ NdisDestroyLookaheadBufferFromSharedMemory(LookaheadBuffer);
+ }
+ }
+ }
+ else
+ {
+ NdisCreateLookaheadBufferFromSharedMemory(
+ (PVOID)FrameData,
+ LookaheadSize,
+ &LookaheadBuffer);
+
+ if (LookaheadBuffer != NULL)
+ {
+ TrFilterIndicateReceive(
+ Adapter->FilterDB,
+ (NDIS_HANDLE)ReceiveBuffer, // context
+ LookaheadBuffer, // header
+ HeaderLength, // header length
+ LookaheadBuffer + HeaderLength, // lookahead
+ LookaheadSize - HeaderLength, // lookahead length
+ PacketSize - HeaderLength);
+
+ NdisDestroyLookaheadBufferFromSharedMemory(LookaheadBuffer);
+ }
+ }
+
+ TrFilterIndicateReceiveComplete( Adapter->FilterDB );
+
+ //
+ // Now worry about the ASB.
+ //
+ NdisDprAcquireSpinLock(&(Adapter->Lock));
+
+ //
+ // Set response in ASB, if possible, else queue the response
+ //
+ if (Adapter->AsbAvailable)
+ {
+ Adapter->AsbAvailable = FALSE;
+
+ Adapter->UseNextAsbForReceive = FALSE;
+
+ SetupReceivedDataAsb(Adapter, ReceiveBufferPointer);
+ WRITE_ADAPTER_REGISTER(
+ Adapter,
+ ISRA_HIGH_SET,
+ ISRA_HIGH_RESPONSE_IN_ASB);
+
+ //
+ // LOOPBACK HERE!!
+ //
+ }
+ else
+ {
+#if DBG
+ if (IbmtokDbg) DbgPrint("W_ASB R\n");
+#endif
+ if (Adapter->ReceiveWaitingForAsbEnd == (USHORT)(-1))
+ {
+ Adapter->ReceiveWaitingForAsbList = ReceiveBufferPointer;
+ }
+ else
+ {
+ PVOID PEnd;
+
+ PEnd = SRAM_PTR_TO_PVOID(
+ Adapter,
+ Adapter->ReceiveWaitingForAsbEnd);
+
+ NdisWriteRegisterUshort(PEnd, ReceiveBufferPointer);
+ }
+
+ Adapter->ReceiveWaitingForAsbEnd = ReceiveBufferPointer;
+
+ if (!(Adapter->OutstandingAsbFreeRequest))
+ {
+ Adapter->OutstandingAsbFreeRequest = TRUE;
+
+ WRITE_ADAPTER_REGISTER(
+ Adapter,
+ ISRA_HIGH_SET,
+ ISRA_HIGH_ASB_FREE_REQUEST);
+
+ IF_LOG('a');
+ }
+ }
+
+ break;
+
+ case ARB_CMD_RING_STATUS_CHANGE:
+ {
+ USHORT RingStatus;
+ NDIS_STATUS NotifyStatus = 0;
+
+ NdisReadRegisterUshort(
+ &((PARB_RING_STATUS_CHANGE)Adapter->ArbAddress)->NetworkStatus,
+ &RingStatus);
+
+ RingStatus = IBMSHORT_TO_USHORT(RingStatus);
+#if DBG
+ if (IbmtokDbg)
+ DbgPrint("IBMTOK: Ring Status %x\n", RingStatus);
+#endif
+
+ WRITE_ADAPTER_REGISTER(
+ Adapter,
+ ISRA_HIGH_SET,
+ ISRA_HIGH_ARB_FREE);
+
+ //
+ // If it is a counter overflow, we need to queue a
+ // DIR.READ.LOG command.
+ //
+ if (RingStatus & 0x0080)
+ {
+ //
+ // Build a pending operation. It will get run ASAP
+ // by ProcessSrbCommand.
+ //
+ PIBMTOK_PEND_DATA PendOp;
+
+ if (IBMTOK_ALLOC_PHYS(&PendOp,sizeof(IBMTOK_PEND_DATA)) !=
+ NDIS_STATUS_SUCCESS)
+ {
+ NdisWriteErrorLogEntry(
+ Adapter->NdisAdapterHandle,
+ NDIS_ERROR_CODE_OUT_OF_RESOURCES,
+ 2,
+ handleSrbSsb,
+ IBMTOK_ERRMSG_ALLOC_MEM);
+
+ break;
+ }
+
+ PendOp->Next = NULL;
+ PendOp->RequestType = NdisRequestGeneric1;
+ PendOp->COMMAND.MAC.ReadLogPending = TRUE;
+
+ if (Adapter->PendQueue == NULL)
+ {
+ Adapter->PendQueue = Adapter->EndOfPendQueue = PendOp;
+
+ }
+ else
+ {
+ //
+ // Put this operation on the front, so it can
+ // correct the error quickly.
+ //
+ PendOp->Next = Adapter->PendQueue;
+ Adapter->PendQueue = PendOp;
+ }
+
+ //
+ // It is now in the pend
+ // queue so we should start that up.
+ // Returns with lock released
+ //
+ IbmtokProcessSrbRequests(Adapter);
+ }
+
+ if (RingStatus & 0x0020)
+ {
+ //
+ // Ring Recovery
+ //
+ NotifyStatus |= NDIS_RING_RING_RECOVERY;
+ }
+
+ if (RingStatus & 0x0040)
+ {
+ //
+ // Single Station
+ //
+ NotifyStatus |= NDIS_RING_SINGLE_STATION;
+ }
+
+ if (RingStatus & 0x0080)
+ {
+ //
+ // Counter Overflow
+ //
+ NotifyStatus |= NDIS_RING_COUNTER_OVERFLOW;
+ }
+
+ if (RingStatus & 0x0100)
+ {
+ //
+ // Remove received
+ //
+ NotifyStatus |= NDIS_RING_REMOVE_RECEIVED;
+ }
+
+ if (RingStatus & 0x0400)
+ {
+ //
+ // Auto-removal
+ //
+ NotifyStatus |= NDIS_RING_AUTO_REMOVAL_ERROR;
+ }
+
+ if (RingStatus & 0x0800)
+ {
+ //
+ // Lobe wire fault
+ //
+ NotifyStatus |= NDIS_RING_LOBE_WIRE_FAULT;
+ }
+
+ if (RingStatus & 0x1000)
+ {
+ //
+ // Transmit Beacon
+ //
+ NotifyStatus |= NDIS_RING_TRANSMIT_BEACON;
+ }
+
+ if (RingStatus & 0x2000)
+ {
+ //
+ // Soft error
+ //
+ NotifyStatus |= NDIS_RING_SOFT_ERROR;
+ }
+
+ if (RingStatus & 0x4000)
+ {
+ //
+ // Hard error
+ //
+ NotifyStatus |= NDIS_RING_HARD_ERROR;
+ }
+
+ if (RingStatus & 0x8000)
+ {
+ //
+ // Signal loss
+ //
+ NotifyStatus |= NDIS_RING_SIGNAL_LOSS;
+ }
+
+ if (NotifyStatus != 0)
+ {
+ PLIST_ENTRY CurrentLink;
+ PIBMTOK_OPEN TempOpen;
+
+ //
+ // Indicate Status to all opens
+ //
+ CurrentLink = Adapter->OpenBindings.Flink;
+
+ while (CurrentLink != &(Adapter->OpenBindings)){
+
+ TempOpen = CONTAINING_RECORD(
+ CurrentLink,
+ IBMTOK_OPEN,
+ OpenList);
+
+ TempOpen->References++;
+
+ NdisDprReleaseSpinLock(&Adapter->Lock);
+
+ NdisIndicateStatus(
+ TempOpen->NdisBindingContext,
+ NDIS_STATUS_RING_STATUS,
+ (PVOID)&NotifyStatus,
+ sizeof(NotifyStatus));
+
+ NdisIndicateStatusComplete(TempOpen->NdisBindingContext);
+
+ NdisDprAcquireSpinLock(&Adapter->Lock);
+
+ CurrentLink = CurrentLink->Flink;
+
+ TempOpen->References--;
+ }
+
+ Adapter->LastNotifyStatus = NotifyStatus;
+ }
+
+ //
+ // Handle a cable being unplugged
+ //
+ if ((RingStatus & 0x5000) == 0x5000)
+ {
+ // receive and transmit beacon
+
+ //
+ // Ok, the cable has been unplugged. We now abort all
+ // outstanding sends, etc.
+ //
+
+ Adapter->Unplugged = TRUE;
+
+ IbmtokAbortPending(Adapter, NDIS_STATUS_DEVICE_FAILED);
+
+ if ((RingStatus & 0x800) == 0x800)
+ {
+ Adapter->LobeWireFaultIndicated = TRUE;
+ }
+ }
+ else if ((RingStatus & 0x0020) &&
+ !(RingStatus & 0x4000) &&
+ (Adapter->Unplugged) &&
+ (!Adapter->UnpluggedResetInProgress))
+ {
+ //
+ // Reset the adapter to remove all stale information
+ //
+ Adapter->UnpluggedResetInProgress = TRUE;
+
+ IbmtokSetupForReset(Adapter, NULL);
+
+ IbmtokHandleDeferred(Adapter);
+ }
+ }
+
+ break;
+
+ case ARB_CMD_TRANSMIT_DATA_REQUEST:
+#if DBG
+ if (IbmtokDbg) DbgPrint("IBMTOK: Transmit data\n");
+#endif
+ if (Adapter->Unplugged && !Adapter->UnpluggedResetInProgress)
+ {
+ //
+ // Do, nothing. This is most likely a stale interrupt. We
+ // wait until we get a ring status interrupt telling us that
+ // the cable is plugged in.
+ //
+ break;
+ }
+
+ TransmitDataArb =
+ (PARB_TRANSMIT_DATA_REQUEST)Adapter->ArbAddress;
+
+ //
+ // First see if we have to assign the command correlator.
+ //
+ NdisReadRegisterUchar(&(TransmitDataArb->CommandCorrelator), &TmpUchar);
+
+ TransmitPacket = FindPacketGivenCorrelator(Adapter, TmpUchar);
+
+ if (TransmitPacket == NULL)
+ {
+ BOOLEAN PacketRemoved;
+
+ //
+ // Have to take the correlator out of the SRB
+ // ourselves. This means that the SRB must still
+ // be occupied by the request for this transmit.
+ //
+ ASSERT(!Adapter->SrbAvailable);
+
+ FreedSrb = FALSE;
+
+ //
+ // This call will remove the packet from the SRB.
+ //
+ TransmitPacket =
+ RemoveTransmitFromSrb(Adapter, &PacketRemoved);
+
+ //
+ // This will be NULL if there was an error in
+ // the transmit command, but in that case why
+ // are we getting this ARB request?? Just exit.
+ // The WakeUpDpc will reset the card if it is hosed.
+ //
+ if ((TransmitPacket == (PNDIS_PACKET)NULL) || !PacketRemoved)
+ {
+ break;
+ }
+ }
+ else
+ {
+ FreedSrb = FALSE;
+
+ Reserved =
+ PIBMTOK_RESERVED_FROM_PACKET(TransmitPacket);
+ }
+
+ NdisDprReleaseSpinLock(&(Adapter->Lock));
+
+ //
+ // Fill in the AC and FC bytes.
+ //
+ NdisReadRegisterUshort(&(TransmitDataArb->DhbPointer), &TmpUshort);
+
+ DhbAddress = (PUCHAR)SRAM_PTR_TO_PVOID(Adapter,TmpUshort);
+
+ WRITE_ADAPTER_REGISTER(Adapter, ISRA_HIGH_SET,
+ ISRA_HIGH_ARB_FREE);
+
+
+ //
+ // Now copy the data down from TransmitPacket.
+ //
+ NdisQueryPacket(
+ TransmitPacket,
+ NULL,
+ NULL,
+ NULL,
+ &PacketLength);
+
+ IbmtokCopyFromPacketToBuffer(
+ TransmitPacket,
+ 0,
+ PacketLength,
+ (PCHAR)DhbAddress,
+ &DummyBytesCopied);
+
+
+ //
+ // Now worry about the ASB.
+ //
+ NdisDprAcquireSpinLock(&(Adapter->Lock));
+
+ IF_LOG('c');
+
+ //
+ // Set response in ASB, if available, else queue response
+ //
+ if (Adapter->AsbAvailable)
+ {
+ Adapter->AsbAvailable = FALSE;
+
+ Adapter->UseNextAsbForReceive = TRUE;
+
+ SetupTransmitStatusAsb(Adapter, TransmitPacket);
+ WRITE_ADAPTER_REGISTER(Adapter, ISRA_HIGH_SET,
+ ISRA_HIGH_RESPONSE_IN_ASB);
+
+ //
+ // LOOPBACK HERE!!
+ //
+ }
+ else
+ {
+#if DBG
+ if (IbmtokDbg) DbgPrint("W_ASB T\n");
+#endif
+
+ PutPacketOnWaitingForAsb(Adapter, TransmitPacket);
+
+ if (!(Adapter->OutstandingAsbFreeRequest))
+ {
+ Adapter->OutstandingAsbFreeRequest = TRUE;
+
+ WRITE_ADAPTER_REGISTER(Adapter, ISRA_HIGH_SET,
+ ISRA_HIGH_ASB_FREE_REQUEST);
+
+ IF_LOG('a');
+ }
+
+ //
+ // FINAL RETURNCODE CHECK HERE!
+ //
+ }
+
+ //
+ // If we freed up the SRB, queue the next command
+ // if there is one.
+ // Returns with lock released
+ //
+ if (FreedSrb)
+ {
+ IbmtokProcessSrbRequests(Adapter);
+ }
+
+ break;
+
+ default:
+
+ WRITE_ADAPTER_REGISTER(Adapter, ISRA_HIGH_SET,
+ ISRA_HIGH_ARB_FREE);
+ break;
+
+ }
+ }
+
+ if (IsrpHigh & ISRP_HIGH_ASB_FREE)
+ {
+ BOOLEAN ReceiveNeedsAsb = FALSE;
+ BOOLEAN TransmitNeedsAsb = FALSE;
+
+ //
+ // Check whether we have stuff to do.
+ //
+ IF_LOG('A');
+
+ if (Adapter->Unplugged && !Adapter->UnpluggedResetInProgress)
+ {
+ //
+ // Do, nothing. This is most likely a stale interrupt. We
+ // wait until we get a ring status interrupt telling us that
+ // the cable is plugged in.
+ //
+ break;
+ }
+
+ ASSERT(Adapter->AsbAvailable == FALSE);
+
+ ASSERT(Adapter->OutstandingAsbFreeRequest == TRUE);
+
+ if (Adapter->ReceiveWaitingForAsbList != (USHORT)-1)
+ {
+ ReceiveNeedsAsb = TRUE;
+ }
+
+ if (Adapter->FirstWaitingForAsb != NULL)
+ {
+ TransmitNeedsAsb = TRUE;
+ }
+
+ if (ReceiveNeedsAsb && (!TransmitNeedsAsb || Adapter->UseNextAsbForReceive))
+ {
+
+ SRAM_PTR ReceiveBufferPointer;
+ PVOID PFront;
+
+#if DBG
+ if (IbmtokDbg) DbgPrint("ASB R\n");
+#endif
+ IF_LOG('R');
+
+ //
+ // Save ReceiveWaitingForAsb so we can release
+ // the spinlock.
+ //
+ ReceiveBufferPointer = Adapter->ReceiveWaitingForAsbList;
+
+ if (Adapter->ReceiveWaitingForAsbList == Adapter->ReceiveWaitingForAsbEnd)
+ {
+ Adapter->ReceiveWaitingForAsbList = (USHORT)-1;
+
+ Adapter->ReceiveWaitingForAsbEnd = (USHORT)-1;
+ }
+ else
+ {
+ PFront = SRAM_PTR_TO_PVOID(Adapter,ReceiveBufferPointer);
+
+ NdisReadRegisterUshort(
+ ((PUSHORT)PFront),
+ &(Adapter->ReceiveWaitingForAsbList));
+ }
+
+ Adapter->AsbAvailable = FALSE;
+
+ Adapter->UseNextAsbForReceive = FALSE;
+
+ //
+ // Fill in the ASB and submit it.
+ //
+ SetupReceivedDataAsb(Adapter, ReceiveBufferPointer);
+
+ if (TransmitNeedsAsb)
+ {
+ WRITE_ADAPTER_REGISTER(Adapter, ISRA_HIGH_SET,
+ ISRA_HIGH_RESPONSE_IN_ASB | ISRA_HIGH_ASB_FREE_REQUEST);
+ }
+ else
+ {
+ Adapter->OutstandingAsbFreeRequest = FALSE;
+ WRITE_ADAPTER_REGISTER(Adapter, ISRA_HIGH_SET,
+ ISRA_HIGH_RESPONSE_IN_ASB);
+ }
+ }
+ else if (TransmitNeedsAsb)
+ {
+ PNDIS_PACKET AsbPacket = Adapter->FirstWaitingForAsb;
+ PIBMTOK_RESERVED Reserved = PIBMTOK_RESERVED_FROM_PACKET(AsbPacket);
+
+#if DBG
+ if (IbmtokDbg) DbgPrint("ASB T\n");
+#endif
+ IF_LOG('T');
+
+ //
+ // Take the packet off of WaitingForAsb;
+ //
+ Adapter->FirstWaitingForAsb = Reserved->Next;
+
+ Adapter->AsbAvailable = FALSE;
+
+ Adapter->UseNextAsbForReceive = TRUE;
+
+ //
+ // Now fill in the ASB and fire it off.
+ //
+ SetupTransmitStatusAsb(Adapter, AsbPacket);
+
+ if (ReceiveNeedsAsb || (Adapter->FirstWaitingForAsb != NULL))
+ {
+ WRITE_ADAPTER_REGISTER(Adapter, ISRA_HIGH_SET,
+ ISRA_HIGH_RESPONSE_IN_ASB | ISRA_HIGH_ASB_FREE_REQUEST);
+ }
+ else
+ {
+ Adapter->OutstandingAsbFreeRequest = FALSE;
+ WRITE_ADAPTER_REGISTER(Adapter, ISRA_HIGH_SET,
+ ISRA_HIGH_RESPONSE_IN_ASB);
+ }
+
+ //
+ // LOOPBACK HERE!!
+ //
+ }
+ else
+ {
+
+#if DBG
+ if (IbmtokDbg) DbgPrint("ASB -\n");
+#endif
+
+ Adapter->AsbAvailable = TRUE;
+ }
+ }
+
+ if (Adapter->CardType != IBM_TOKEN_RING_PCMCIA)
+ {
+ GET_ARB_ASB_BITS(Adapter, &IsrpHigh);
+ }
+ else
+ {
+ //
+ // disable interrupts on the card, since we don't trust ndissyncint to work
+ //
+ READ_ADAPTER_REGISTER(Adapter, ISRP_LOW, &Temp);
+
+ WRITE_ADAPTER_REGISTER(Adapter, ISRP_LOW,
+ Temp & (~(ISRP_LOW_NO_CHANNEL_CHECK | ISRP_LOW_INTERRUPT_ENABLE) ) );
+
+ //
+ // update arb_asb
+ //
+ IsrpHigh = (Adapter->IsrpBits) & (ISRP_HIGH_ARB_COMMAND | ISRP_HIGH_ASB_FREE);
+ Adapter->IsrpBits = (Adapter->IsrpBits) & (~(ISRP_HIGH_ARB_COMMAND | ISRP_HIGH_ASB_FREE));
+
+ //
+ // reenable interrupts on the card
+ //
+ WRITE_ADAPTER_REGISTER(Adapter, ISRP_LOW,
+ ISRP_LOW_NO_CHANNEL_CHECK | ISRP_LOW_INTERRUPT_ENABLE);
+ }
+ }
+
+ Adapter->HandleArbRunning = FALSE;
+
+ IF_LOG('J');
+
+ //
+ // This macro assumes it is called with the lock held,
+ // and releases it.
+ //
+ IBMTOK_DO_DEFERRED(Adapter);
+}
+
+STATIC
+VOID
+CleanupResetFailure(
+ IN PIBMTOK_ADAPTER Adapter,
+ PNDIS_STATUS IndicateStatus,
+ IN ULONG FailureCode,
+ IN ULONG ResetStage
+ )
+
+/*++
+
+Routine Description:
+
+ Clean up if a reset fails partway through. Called
+ from HandleResetStaging.
+
+ Called with the lock held and returns with it held.
+
+Arguments:
+
+ Adapter - The adapter that the reset is for.
+
+ IndicateStatus - Status to indicate to the protocols, or NULL.
+
+ FailureCode - A code to include in the error log.
+
+ ResetStage - The stage of the reset where the failure occured.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+
+ PLIST_ENTRY CurrentLink;
+ PIBMTOK_OPEN TempOpen;
+
+ if (!Adapter->UnpluggedResetInProgress)
+ {
+ //
+ // signal failure....
+ //
+ Adapter->CurrentRingState = NdisRingStateRingFailure;
+
+ //
+ // Indicate Status to all opens
+ //
+ CurrentLink = Adapter->OpenBindings.Flink;
+
+ while (CurrentLink != &(Adapter->OpenBindings))
+ {
+ TempOpen = CONTAINING_RECORD(CurrentLink, IBMTOK_OPEN, OpenList);
+
+ TempOpen->References++;
+
+ NdisReleaseSpinLock(&Adapter->Lock);
+
+ if (IndicateStatus)
+ {
+ NdisIndicateStatus(TempOpen->NdisBindingContext,
+ NDIS_STATUS_CLOSED,
+ IndicateStatus,
+ sizeof(NDIS_STATUS));
+ }
+ else
+ {
+ NdisIndicateStatus(TempOpen->NdisBindingContext,
+ NDIS_STATUS_CLOSED,
+ NULL,
+ 0);
+ }
+
+ NdisIndicateStatusComplete(TempOpen->NdisBindingContext);
+
+ NdisAcquireSpinLock(&Adapter->Lock);
+
+ CurrentLink = CurrentLink->Flink;
+
+ TempOpen->References--;
+ }
+
+ NdisWriteErrorLogEntry(
+ Adapter->NdisAdapterHandle,
+ NDIS_ERROR_CODE_HARDWARE_FAILURE,
+ 4,
+ handleResetStaging,
+ IBMTOK_ERRMSG_BRINGUP_FAILURE,
+ FailureCode,
+ ResetStage);
+ }
+ else
+ {
+ //
+ // Set this to false, we will try again later.
+ //
+ Adapter->LobeWireFaultIndicated = TRUE;
+ Adapter->UnpluggedResetInProgress = FALSE;
+ }
+
+ //
+ // Set Abort
+ //
+ Adapter->CurrentResetStage = 4;
+
+ SetResetVariables(Adapter);
+
+ Adapter->OpenInProgress = FALSE;
+ Adapter->NotAcceptingRequests = TRUE;
+
+ Adapter->ResetInProgress = FALSE;
+ Adapter->ResetInterruptAllowed = FALSE;
+ Adapter->ResetInterruptHasArrived = FALSE;
+
+ if (Adapter->ResettingOpen != NULL)
+ {
+ PIBMTOK_OPEN Open = Adapter->ResettingOpen;
+
+ //
+ // Decrement the reference count that was incremented
+ // in SetupForReset.
+ //
+ Open->References--;
+
+ NdisReleaseSpinLock(&Adapter->Lock);
+
+ NdisCompleteReset(Open->NdisBindingContext, NDIS_STATUS_FAILURE);
+
+ NdisAcquireSpinLock(&Adapter->Lock);
+ }
+}
+
+STATIC
+VOID
+HandleResetStaging(
+ IN PIBMTOK_ADAPTER Adapter
+ )
+
+/*++
+
+Routine Description:
+
+ Handles the next stage of the transmit interrupt,
+ knowing that an SRB interrupt just came through.
+
+ Called with the lock held and returns with it held.
+
+Arguments:
+
+ Adapter - The adapter that the reset is for.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+ USHORT TmpUshort;
+ UCHAR TmpUchar;
+
+ switch (Adapter->CurrentResetStage)
+ {
+ case 1:
+ {
+ //
+ // The adapter just finished being reset.
+ //
+ USHORT WrbOffset;
+ PSRB_BRING_UP_RESULT BringUpSrb;
+ PSRB_OPEN_ADAPTER OpenSrb;
+ UCHAR Value1, Value2;
+
+#if DBG
+if (IbmtokDbg) DbgPrint("IBMTOK: RESET done\n");
+#endif
+
+ READ_ADAPTER_REGISTER(Adapter, WRBR_LOW, &Value1);
+ READ_ADAPTER_REGISTER(Adapter, WRBR_HIGH, &Value2);
+
+ WrbOffset = (USHORT)(((USHORT)Value1) << 8) + (USHORT)Value2;
+
+ Adapter->InitialWrbOffset = WrbOffset;
+
+ BringUpSrb = (PSRB_BRING_UP_RESULT)(Adapter->SharedRam + WrbOffset);
+
+ NdisReadRegisterUshort(&(BringUpSrb->ReturnCode), &TmpUshort);
+
+ if (TmpUshort != 0x0000)
+ {
+ CleanupResetFailure (Adapter, NULL, TmpUshort, 1);
+ break;
+ }
+
+ //
+ // Now set up the open SRB request.
+ //
+ OpenSrb = (PSRB_OPEN_ADAPTER)
+ (Adapter->SharedRam + Adapter->InitialWrbOffset);
+
+ IBMTOK_ZERO_MAPPED_MEMORY(OpenSrb, sizeof(SRB_OPEN_ADAPTER));
+
+ NdisWriteRegisterUchar(&(OpenSrb->Command), SRB_CMD_OPEN_ADAPTER);
+ NdisWriteRegisterUshort(&(OpenSrb->OpenOptions),
+ (USHORT)(OPEN_CONTENDER |
+ (Adapter->EarlyTokenRelease ?
+ 0 :
+ OPEN_MODIFIED_TOKEN_RELEASE)));
+
+ NdisMoveToMappedMemory((PCHAR)OpenSrb->NodeAddress,
+ Adapter->NetworkAddress,
+ TR_LENGTH_OF_ADDRESS);
+
+ WRITE_IBMSHORT(OpenSrb->ReceiveBufferNum,
+ Adapter->NumberOfReceiveBuffers);
+ WRITE_IBMSHORT(OpenSrb->ReceiveBufferLen,
+ Adapter->ReceiveBufferLength);
+
+ WRITE_IBMSHORT(OpenSrb->TransmitBufferLen,
+ Adapter->TransmitBufferLength);
+
+ NdisWriteRegisterUchar(&(OpenSrb->TransmitBufferNum),
+ (UCHAR)Adapter->NumberOfTransmitBuffers);
+
+ Adapter->CurrentResetStage = 2;
+
+ WRITE_ADAPTER_REGISTER(Adapter, ISRA_HIGH_SET,
+ ISRA_HIGH_COMMAND_IN_SRB | ISRA_HIGH_SRB_FREE_REQUEST);
+
+ IF_LOG('1');
+
+ break;
+ }
+
+ case 2:
+ {
+ //
+ // Handle the result of the DIR.OPEN.ADAPTER command.
+ //
+ PSRB_OPEN_RESPONSE OpenResponseSrb;
+
+#if DBG
+if (IbmtokDbg) DbgPrint("IBMTOK: OPEN done\n");
+#endif
+
+ OpenResponseSrb = (PSRB_OPEN_RESPONSE)
+ (Adapter->SharedRam + Adapter->InitialWrbOffset);
+
+ NdisReadRegisterUchar(&(OpenResponseSrb->ReturnCode), &TmpUchar);
+
+ if (TmpUchar != 0)
+ {
+ NDIS_STATUS IndicateStatus;
+
+ NdisReadRegisterUshort(&(OpenResponseSrb->ErrorCode),
+ &(Adapter->OpenErrorCode));
+ Adapter->OpenErrorCode = IBMSHORT_TO_USHORT(Adapter->OpenErrorCode);
+ IndicateStatus =
+ NDIS_STATUS_TOKEN_RING_OPEN_ERROR |
+ (NDIS_STATUS)(Adapter->OpenErrorCode);
+
+ CleanupResetFailure (Adapter, &IndicateStatus, Adapter->OpenErrorCode, 2);
+ break;
+ }
+
+ IF_LOG('2');
+
+#if DBG
+ NdisReadRegisterUchar(&(OpenResponseSrb->ReturnCode),&TmpUchar);
+ if (IbmtokDbg) DbgPrint("IBMTOK: RESET OPEN, Return code = %x, at %lx\n",
+ TmpUchar,
+ OpenResponseSrb);
+#endif
+
+ NdisReadRegisterUshort(&(OpenResponseSrb->SrbPointer), &TmpUshort);
+ Adapter->SrbAddress = SRAM_PTR_TO_PVOID(Adapter,TmpUshort);
+
+ NdisReadRegisterUshort(&(OpenResponseSrb->SsbPointer), &TmpUshort);
+ Adapter->SsbAddress = SRAM_PTR_TO_PVOID(Adapter,TmpUshort);
+
+ NdisReadRegisterUshort(&(OpenResponseSrb->ArbPointer), &TmpUshort);
+ Adapter->ArbAddress = SRAM_PTR_TO_PVOID(Adapter,TmpUshort);
+
+ NdisReadRegisterUshort(&(OpenResponseSrb->AsbPointer), &TmpUshort);
+ Adapter->AsbAddress = SRAM_PTR_TO_PVOID(Adapter,TmpUshort);
+
+#if DBG
+if (IbmtokDbg)
+{
+ USHORT TmpUshort1;
+ USHORT TmpUshort2;
+ USHORT TmpUshort3;
+ USHORT TmpUshort4;
+ NdisReadRegisterUshort(&(OpenResponseSrb->SrbPointer), &TmpUshort1);
+ NdisReadRegisterUshort(&(OpenResponseSrb->SsbPointer), &TmpUshort2);
+ NdisReadRegisterUshort(&(OpenResponseSrb->ArbPointer), &TmpUshort3);
+ NdisReadRegisterUshort(&(OpenResponseSrb->AsbPointer), &TmpUshort4);
+ DbgPrint("IBMTOK: Offsets: SRB %x SSB %x ARB %x ASB %x\n",
+ IBMSHORT_TO_USHORT(TmpUshort1),
+ IBMSHORT_TO_USHORT(TmpUshort2),
+ IBMSHORT_TO_USHORT(TmpUshort3),
+ IBMSHORT_TO_USHORT(TmpUshort4));
+}
+#endif
+
+ //
+ // Now queue a SET.FUNCT.ADDRESS command if needed.
+ //
+ Adapter->CurrentCardFunctional = (TR_FUNCTIONAL_ADDRESS)0;
+
+ if (SetAdapterFunctionalAddress(Adapter) == NDIS_STATUS_SUCCESS)
+ {
+ //
+ // This means that the command did not have to be
+ // queued, so we are done with this step.
+ //
+ if (SetAdapterGroupAddress(Adapter) == NDIS_STATUS_SUCCESS)
+ {
+ //
+ // This one did not pend either, we are done.
+ //
+ IbmtokFinishAdapterReset(Adapter);
+ }
+ else
+ {
+ Adapter->CurrentResetStage = 4;
+
+ WRITE_ADAPTER_REGISTER(Adapter, ISRA_HIGH_SET,
+ ISRA_HIGH_COMMAND_IN_SRB | ISRA_HIGH_SRB_FREE_REQUEST);
+ }
+ }
+ else
+ {
+ Adapter->CurrentResetStage = 3;
+
+ WRITE_ADAPTER_REGISTER(Adapter, ISRA_HIGH_SET,
+ ISRA_HIGH_COMMAND_IN_SRB | ISRA_HIGH_SRB_FREE_REQUEST);
+ }
+
+ break;
+ }
+
+ case 3:
+ {
+ //
+ // The SET.FUNCT.ADDRESS command finished.
+ //
+ PSRB_GENERIC GenericSrb = (PSRB_GENERIC)Adapter->SrbAddress;
+ UCHAR ReturnCode;
+
+ NdisReadRegisterUchar(&(GenericSrb->ReturnCode), &ReturnCode);
+
+ IF_LOG('3');
+
+#if DBG
+if (IbmtokDbg) DbgPrint("IBMTOK: SET FUNCT done\n");
+#endif
+ if (ReturnCode == 0x00)
+ {
+ if (SetAdapterGroupAddress(Adapter) == NDIS_STATUS_SUCCESS)
+ {
+ //
+ // This one did not pend, the dishes are done.
+ //
+ IbmtokFinishAdapterReset(Adapter);
+ }
+ else
+ {
+ Adapter->CurrentResetStage = 4;
+
+ WRITE_ADAPTER_REGISTER(Adapter, ISRA_HIGH_SET,
+ ISRA_HIGH_COMMAND_IN_SRB | ISRA_HIGH_SRB_FREE_REQUEST);
+ }
+ }
+ else if (ReturnCode != 0xfe)
+ {
+ CleanupResetFailure (Adapter, NULL, (ULONG)ReturnCode, 3);
+ }
+
+ break;
+ }
+
+ case 4:
+ {
+ //
+ // The SET.GROUP.ADDRESS command finished.
+ //
+ PSRB_GENERIC GenericSrb = (PSRB_GENERIC)Adapter->SrbAddress;
+ UCHAR ReturnCode;
+
+ NdisReadRegisterUchar(&(GenericSrb->ReturnCode), &ReturnCode);
+
+ IF_LOG('4');
+
+#if DBG
+if (IbmtokDbg) DbgPrint("IBMTOK: SET GROUP done\n");
+#endif
+ if (ReturnCode == 0x00)
+ {
+ IbmtokFinishAdapterReset(Adapter);
+ }
+ else if (ReturnCode != 0xfe)
+ {
+ CleanupResetFailure (Adapter, NULL, (ULONG)ReturnCode, 4);
+ }
+
+ break;
+ }
+ }
+}
+
+STATIC
+PNDIS_PACKET
+RemoveTransmitFromSrb(
+ IN PIBMTOK_ADAPTER Adapter,
+ OUT PBOOLEAN PacketRemoved
+ )
+
+/*++
+
+Routine Description:
+
+ Cleans a transmit out of the SRB if one was there.
+
+ NOTE : Should be called with the spinlock held!!!
+
+Arguments:
+
+ Adapter - The adapter that this packet is coming through.
+
+ PacketRemoved - TRUE if the packet was removed from the SRB.
+
+Return Value:
+
+ The packet removed.
+
+--*/
+
+{
+ PNDIS_PACKET TransmitPacket;
+ PIBMTOK_RESERVED Reserved;
+ UCHAR TmpUchar;
+ PSRB_TRANSMIT_DIR_FRAME TransmitSrb =
+ (PSRB_TRANSMIT_DIR_FRAME)Adapter->SrbAddress;
+
+
+ NdisReadRegisterUchar(&(TransmitSrb->ReturnCode), &TmpUchar);
+
+ if (TmpUchar == 0xfe)
+ {
+ //
+ // The TRANSMIT command was just put in the SRB, and
+ // the adapter has not yet had time to process it.
+ // We return now before setting SrbAvailable to TRUE,
+ // so the command is left to be processed.
+ //
+ // NOTE: If this happens on a call from inside the
+ // ARB_TRANSMIT_DATA interrupt handler, we will fail
+ // on an assertion when we return NULL.
+ //
+ *PacketRemoved = FALSE;
+
+ return (PNDIS_PACKET)NULL;
+ }
+
+ //
+ // if there was a packet in there, put it in
+ // the correlator array.
+ //
+ TransmitPacket = Adapter->TransmittingPacket;
+
+ Adapter->TransmittingPacket = (PNDIS_PACKET)NULL;
+
+ if (TransmitPacket == NULL)
+ {
+ *PacketRemoved = FALSE;
+
+ return(NULL);
+ }
+
+ //
+ // This will be TRUE whatever happens next.
+ //
+ *PacketRemoved = TRUE;
+
+ Reserved = PIBMTOK_RESERVED_FROM_PACKET(TransmitPacket);
+
+ //
+ // Check that the return code is OK.
+ //
+ if (TmpUchar != 0xff)
+ {
+ PIBMTOK_OPEN Open = PIBMTOK_OPEN_FROM_BINDING_HANDLE(Reserved->MacBindingHandle);
+ //
+ // Fail the transmit.
+ //
+
+ //
+ // If doing LOOPBACK, this should really be a check
+ // of ReadyToComplete etc.
+ //
+#if DBG
+if (IbmtokDbg) {
+ UCHAR TmpUchar1, TmpUchar2;
+ NdisReadRegisterUchar(&TransmitSrb->ReturnCode, &TmpUchar1);
+ NdisReadRegisterUchar(&TransmitSrb->Command, &TmpUchar2);
+ DbgPrint("IBMTOK: Transmit failed in SRB: %x for %x\n", TmpUchar1, TmpUchar2);
+}
+#endif
+
+#ifdef CHECK_DUP_SENDS
+ {
+ VOID IbmtokRemovePacketFromList(PIBMTOK_ADAPTER, PNDIS_PACKET);
+ IbmtokRemovePacketFromList(Adapter, TransmitPacket);
+ }
+#endif
+
+ Adapter->FrameTransmitErrors++;
+
+ NdisReleaseSpinLock(&(Adapter->Lock));
+
+ NdisCompleteSend(Open->NdisBindingContext, Reserved->Packet, NDIS_STATUS_FAILURE);
+
+ NdisAcquireSpinLock(&(Adapter->Lock));
+
+ Adapter->SendTimeout = FALSE;
+
+ //
+ // Decrement the reference count for the open.
+ //
+ Open->References--;
+
+ //
+ // This will cause an assertion failure if we were
+ // called from the ARB_TRANSMIT_DATA handler.
+ //
+ return (PNDIS_PACKET)NULL;
+ }
+
+ //
+ // Put the packet in the correlator array.
+ //
+ Reserved->CorrelatorAssigned = TRUE;
+ NdisReadRegisterUchar(&(TransmitSrb->CommandCorrelator), &(Reserved->CommandCorrelator));
+
+ PutPacketInCorrelatorArray(Adapter, TransmitPacket);
+
+ return TransmitPacket;
+}
+
+VOID
+SetupSrbCommand(
+ IN PIBMTOK_ADAPTER Adapter
+ )
+
+/*++
+
+Routine Description:
+
+ Fills in the SRB with the next request. It first checks
+ if there is a pended request outstanding, then
+ handles any queued transmits.
+
+ Called with the spinlock held.
+
+ NOTE: Should be called with Adapter->SrbAvailable == FALSE.
+
+Arguments:
+
+ Adapter - The Adapter to process interrupts for.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+ if (Adapter->PendQueue != NULL)
+ {
+ //
+ // This will copy the appropriate info out of the
+ // pend queue.
+ //
+ if (StartPendQueueOp(Adapter) == NDIS_STATUS_PENDING)
+ {
+ //
+ // Indicate the SRB command.
+ //
+ WRITE_ADAPTER_REGISTER(Adapter, ISRA_HIGH_SET,
+ ISRA_HIGH_COMMAND_IN_SRB);
+
+ return;
+ }
+ }
+
+ //
+ // If we reach here, the pend queue was empty or
+ // else StartPendQueueOp drained the entire queue
+ // without an operation needing the SRB.
+ //
+ if (Adapter->FirstTransmit != NULL)
+ {
+ //
+ // Remove the packet from the queue.
+ //
+ PNDIS_PACKET TransmitPacket = Adapter->FirstTransmit;
+
+ PIBMTOK_RESERVED Reserved =
+ PIBMTOK_RESERVED_FROM_PACKET(TransmitPacket);
+
+ Adapter->FirstTransmit = Reserved->Next;
+
+ Adapter->TransmittingPacket = TransmitPacket;
+
+ //
+ // set up the send - this sets the packet equal
+ // to Adapter->TransmittingPacket;
+ //
+ SetupTransmitFrameSrb(Adapter, TransmitPacket);
+
+ //
+ // Indicate the SRB command.
+ //
+
+ WRITE_ADAPTER_REGISTER(Adapter, ISRA_HIGH_SET,
+ ISRA_HIGH_COMMAND_IN_SRB);
+ }
+ else
+ {
+ Adapter->SrbAvailable = TRUE;
+ }
+}
+
+extern
+VOID
+IbmtokForceAdapterInterrupt(
+ IN PIBMTOK_ADAPTER Adapter
+ )
+
+/*++
+
+Routine Description:
+
+ This forces an adapter interrupt by queueing an
+ INTERRUPT SRB.
+
+ This is called with the spinlock held, and also
+ Adapter->SrbAvailable must be TRUE.
+
+Arguments:
+
+ Adapter - The Adapter to force the interrupt on.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+
+ PSRB_INTERRUPT InterruptSrb =
+ (PSRB_INTERRUPT)Adapter->SrbAddress;
+
+ ASSERT(Adapter->SrbAvailable);
+
+ Adapter->SrbAvailable = FALSE;
+
+ NdisWriteRegisterUchar(&(InterruptSrb->Command), SRB_CMD_INTERRUPT);
+ NdisWriteRegisterUchar(&(InterruptSrb->ReturnCode), 0xfe);
+
+ WRITE_ADAPTER_REGISTER(Adapter, ISRA_HIGH_SET,
+ ISRA_HIGH_COMMAND_IN_SRB);
+
+ IF_LOG('O');
+
+}
+
+STATIC
+VOID
+SetupTransmitFrameSrb(
+ IN PIBMTOK_ADAPTER Adapter,
+ IN PNDIS_PACKET Packet
+ )
+
+/*++
+
+Routine Description:
+
+ This routine sets up the SRB for a TRANSMIT.DIR.FRAME.
+
+Arguments:
+
+ Adapter - The adapter that this packet is coming through.
+
+ Packet - The packet that is being sent.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+ PSRB_TRANSMIT_DIR_FRAME TransmitSrb =
+ (PSRB_TRANSMIT_DIR_FRAME)Adapter->SrbAddress;
+
+ UNREFERENCED_PARAMETER(Packet);
+
+ NdisWriteRegisterUchar(&(TransmitSrb->Command), SRB_CMD_TRANSMIT_DIR_FRAME);
+ NdisWriteRegisterUchar(&(TransmitSrb->CommandCorrelator), 0x00);
+ NdisWriteRegisterUchar(&(TransmitSrb->ReturnCode), 0xfe); // will change to 0xff or error
+ NdisWriteRegisterUshort(&(TransmitSrb->StationId), USHORT_TO_IBMSHORT(0x00));
+
+ IF_LOG('x');
+}
+
+STATIC
+VOID
+SetupTransmitStatusAsb(
+ IN PIBMTOK_ADAPTER Adapter,
+ IN PNDIS_PACKET Packet
+ )
+
+/*++
+
+Routine Description:
+
+ This routine sets up the ASB for a response from
+ a TRANSMIT.DATA.REQUEST.
+
+Arguments:
+
+ Adapter - The adapter that this packet is coming through.
+
+ Packet - The packet that has been copied down.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+
+ PASB_TRANSMIT_DATA_STATUS TransmitDataAsb;
+ UINT PacketLength;
+ PIBMTOK_RESERVED Reserved = PIBMTOK_RESERVED_FROM_PACKET(Packet);
+
+ NdisQueryPacket(Packet, NULL, NULL, NULL, &PacketLength);
+
+ TransmitDataAsb = (PASB_TRANSMIT_DATA_STATUS)
+ Adapter->AsbAddress;
+
+ NdisWriteRegisterUchar(&(TransmitDataAsb->Command), SRB_CMD_TRANSMIT_DIR_FRAME);
+ NdisWriteRegisterUchar(&(TransmitDataAsb->CommandCorrelator),
+ Reserved->CommandCorrelator);
+ NdisWriteRegisterUchar(&(TransmitDataAsb->ReturnCode), 0x00);
+ NdisWriteRegisterUshort(&(TransmitDataAsb->FrameLength),
+ USHORT_TO_IBMSHORT(PacketLength));
+
+ IF_LOG('X');
+
+}
+
+STATIC
+VOID
+SetupAdapterStatisticsSrb(
+ IN PIBMTOK_ADAPTER Adapter
+ )
+
+/*++
+
+Routine Description:
+
+ This routine sets up the SRB for a DLC.STATISTICS.
+
+Arguments:
+
+ Adapter - A pointer to the adapter.
+
+Return Value:
+
+ None.
+
+--*/
+{
+ PSRB_DLC_STATS StatsSrb = (PSRB_DLC_STATS)(Adapter->SrbAddress);
+
+ NdisWriteRegisterUchar(&(StatsSrb->Command), SRB_CMD_DLC_STATISTICS);
+ NdisWriteRegisterUshort(&(StatsSrb->StationId), USHORT_TO_IBMSHORT(0x00));
+ NdisWriteRegisterUchar((PUCHAR)(&(StatsSrb->ReturnCode)), 0x80); // Resets counters
+
+}
+
+STATIC
+VOID
+GetAdapterStatisticsFromSrb(
+ PIBMTOK_ADAPTER Adapter
+ )
+
+/*++
+
+Routine Description:
+
+ This routine reads the statistics after a DLC.STATISTICS has completed
+ and stores the results in the adapter structure.
+
+Arguments:
+
+ Adapter - A pointer to the adapter.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+ PSRB_DLC_STATS StatsSrb = (PSRB_DLC_STATS)(Adapter->SrbAddress);
+ PDLC_COUNTERS Counters;
+ USHORT TmpUshort;
+ UCHAR TmpUchar;
+
+ NdisReadRegisterUshort(&StatsSrb->CountersOffset, &TmpUshort);
+ Counters = (PDLC_COUNTERS) (((PUCHAR)(Adapter->SrbAddress)) +
+ IBMSHORT_TO_USHORT(TmpUshort));
+
+ NdisReadRegisterUshort(&Counters->TransmitCount, &TmpUshort);
+ Adapter->FramesTransmitted += IBMSHORT_TO_USHORT(TmpUshort);
+ NdisReadRegisterUshort(&Counters->ReceiveCount, &TmpUshort);
+ Adapter->FramesReceived += IBMSHORT_TO_USHORT(TmpUshort);
+ NdisReadRegisterUchar(&Counters->TransmitErrors, &TmpUchar);
+ Adapter->FrameTransmitErrors += TmpUchar;
+ NdisReadRegisterUchar(&Counters->ReceiveErrors, &TmpUchar);
+ Adapter->FrameReceiveErrors += TmpUchar;
+
+}
+
+STATIC
+VOID
+GetAdapterErrorsFromSrb(
+ PIBMTOK_ADAPTER Adapter
+ )
+
+/*++
+
+Routine Description:
+
+ This routine reads the statistics after a DIR.READ.LOG has completed
+ and stores the results in the adapter structure.
+
+Arguments:
+
+ Adapter - A pointer to the adapter.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+ PSRB_READ_LOG ReadLogSrb = (PSRB_READ_LOG)(Adapter->SrbAddress);
+ ULONG TmpUchar;
+
+ NdisReadRegisterUchar(&ReadLogSrb->LineErrors, &TmpUchar);
+ Adapter->LineErrors += TmpUchar;
+ NdisReadRegisterUchar(&ReadLogSrb->InternalErrors, &TmpUchar);
+ Adapter->InternalErrors += TmpUchar;
+ NdisReadRegisterUchar(&ReadLogSrb->BurstErrors, &TmpUchar);
+ Adapter->BurstErrors += TmpUchar;
+ NdisReadRegisterUchar(&ReadLogSrb->AcErrors, &TmpUchar);
+ Adapter->AcErrors += TmpUchar;
+ NdisReadRegisterUchar(&ReadLogSrb->AbortDelimeters, &TmpUchar);
+ Adapter->AbortDelimeters += TmpUchar;
+ NdisReadRegisterUchar(&ReadLogSrb->LostFrames, &TmpUchar);
+ Adapter->LostFrames += TmpUchar;
+ NdisReadRegisterUchar(&ReadLogSrb->ReceiveCongestionCount, &TmpUchar);
+ Adapter->ReceiveCongestionCount += TmpUchar;
+ NdisReadRegisterUchar(&ReadLogSrb->FrameCopiedErrors, &TmpUchar);
+ Adapter->FrameCopiedErrors += TmpUchar;
+ NdisReadRegisterUchar(&ReadLogSrb->FrequencyErrors, &TmpUchar);
+ Adapter->FrequencyErrors += TmpUchar;
+ NdisReadRegisterUchar(&ReadLogSrb->TokenErrors, &TmpUchar);
+ Adapter->TokenErrors += TmpUchar;
+}
+
+STATIC
+VOID
+SetupAdapterErrorsSrb(
+ PIBMTOK_ADAPTER Adapter
+ )
+
+/*++
+
+Routine Description:
+
+ This routine sets up the SRB for a DIR.READ.LOG command.
+
+Arguments:
+
+ Adapter - A pointer to the adapter.
+
+Return Value:
+
+ None.
+
+--*/
+{
+ PSRB_READ_LOG ReadLogSrb = (PSRB_READ_LOG)(Adapter->SrbAddress);
+
+ NdisWriteRegisterUchar(&(ReadLogSrb->Command), SRB_CMD_READ_LOG);
+}
+
+STATIC
+NDIS_STATUS
+StartPendQueueOp(
+ IN PIBMTOK_ADAPTER Adapter
+ )
+
+/*++
+
+Routine Description:
+
+ This routine goes through the pending queue until it
+ is empty or it finds a request that requires an SRB
+ command and hence pends.
+
+ NOTE: This routine is called with the lock held and
+ returns with it held.
+
+Arguments:
+
+ Adapter - The adapter that the queue should be checked for.
+
+Return Value:
+
+ NDIS_STATUS_SUCCESS - If the queue was drained completely.
+ NDIS_STATUS_PENDING - If a request required the SRB.
+
+--*/
+
+{
+ //
+ // Holds the operation on the head of the queue
+ // (we know it is not empty).
+ //
+ PIBMTOK_PEND_DATA PendOp;
+
+ //
+ // Holds status temporarily.
+ //
+ NDIS_STATUS RequestStatus;
+
+ while (Adapter->PendQueue != NULL)
+ {
+ //
+ // First take the head operation off the queue.
+ //
+ PendOp = Adapter->PendQueue;
+
+ Adapter->PendQueue = Adapter->PendQueue->Next;
+
+ if (Adapter->PendQueue == NULL)
+ {
+ //
+ // We have just emptied the list.
+ //
+ Adapter->EndOfPendQueue = NULL;
+ }
+
+ if (PendOp->RequestType == NdisRequestGeneric1)
+ {
+ //
+ // The pended operation is a result of the card having
+ // a counter overflow, and now we need to send the command.
+ //
+ if (PendOp->COMMAND.MAC.ReadLogPending)
+ {
+ //
+ // A DIR.READ.LOG command is needed.
+ //
+ SetupAdapterErrorsSrb(Adapter);
+ }
+ else
+ {
+ //
+ // A DLC.STATISTICS command is needed.
+ //
+ SetupAdapterStatisticsSrb(Adapter);
+ }
+
+ //
+ // Issue adapter command.
+ //
+ WRITE_ADAPTER_REGISTER(Adapter, ISRA_HIGH_SET,
+ ISRA_HIGH_COMMAND_IN_SRB);
+
+ RequestStatus = NDIS_STATUS_PENDING;
+ }
+ else
+ {
+ switch (PendOp->RequestType)
+ {
+ case NdisRequestSetInformation:
+
+ //
+ // It's a set filter or set address command.
+ //
+ if ((PNDIS_REQUEST_FROM_PIBMTOK_PEND_DATA(PendOp))->DATA.SET_INFORMATION.Oid ==
+ OID_GEN_CURRENT_PACKET_FILTER)
+ {
+ //
+ // It's a set filter command.
+ //
+ Adapter->OldPacketFilter = Adapter->CurrentPacketFilter;
+
+ Adapter->CurrentPacketFilter =
+ PendOp->COMMAND.NDIS.SET_FILTER.NewFilterValue;
+
+ RequestStatus = SetAdapterFunctionalAddress(Adapter);
+ }
+ else
+ {
+ //
+ // It's a set address command.
+ //
+#if DBG
+ if (IbmtokDbg)
+ {
+ DbgPrint("IBMTOK: Starting Command\n");
+ }
+#endif
+
+ if ((PNDIS_REQUEST_FROM_PIBMTOK_PEND_DATA(PendOp))->DATA.SET_INFORMATION.Oid ==
+ OID_802_5_CURRENT_FUNCTIONAL)
+ {
+ Adapter->CurrentFunctionalAddress =
+ PendOp->COMMAND.NDIS.SET_ADDRESS.NewAddressValue;
+
+ RequestStatus = SetAdapterFunctionalAddress(Adapter);
+ }
+ else
+ {
+ Adapter->CurrentGroupAddress =
+ PendOp->COMMAND.NDIS.SET_ADDRESS.NewAddressValue;
+
+ RequestStatus = SetAdapterGroupAddress(Adapter);
+ }
+ }
+
+ break;
+
+ case NdisRequestClose:
+
+ //
+ // It's a set filter command.
+ //
+ Adapter->OldPacketFilter = Adapter->CurrentPacketFilter;
+
+ Adapter->CurrentPacketFilter =
+ PendOp->COMMAND.NDIS.CLOSE.NewFilterValue;
+
+ RequestStatus = SetAdapterFunctionalAddress(Adapter);
+
+ break;
+
+ case NdisRequestGeneric2:
+
+ //
+ // It's a set address command.
+ //
+ Adapter->CurrentFunctionalAddress =
+ PendOp->COMMAND.NDIS.SET_ADDRESS.NewAddressValue;
+
+
+ RequestStatus = SetAdapterFunctionalAddress(Adapter);
+
+ break;
+
+
+ case NdisRequestGeneric3:
+
+ //
+ // It's a set address command.
+ //
+ Adapter->CurrentGroupAddress =
+ PendOp->COMMAND.NDIS.SET_ADDRESS.NewAddressValue;
+
+
+ RequestStatus = SetAdapterGroupAddress(Adapter);
+
+ break;
+
+
+ case NdisRequestQueryStatistics:
+
+ //
+ // We know it's a request for statistics.
+ //
+ RequestStatus = NDIS_STATUS_PENDING;
+
+ SetupAdapterErrorsSrb(Adapter);
+
+ PendOp->COMMAND.NDIS.STATISTICS.ReadLogPending = TRUE;
+
+ //
+ // Issue adapter command.
+ //
+ WRITE_ADAPTER_REGISTER(Adapter, ISRA_HIGH_SET,
+ ISRA_HIGH_COMMAND_IN_SRB);
+
+ break;
+
+ default:
+
+ NdisWriteErrorLogEntry(
+ Adapter->NdisAdapterHandle,
+ NDIS_ERROR_CODE_DRIVER_FAILURE,
+ 3,
+ IBMTOK_ERRMSG_BAD_OP,
+ 1,
+ PendOp->RequestType);
+ }
+ }
+
+ if (RequestStatus == NDIS_STATUS_PENDING)
+ {
+ //
+ // Set this up for when the request completes.
+ //
+ Adapter->PendData = PendOp;
+
+ return NDIS_STATUS_PENDING;
+ }
+ else if (RequestStatus == NDIS_STATUS_SUCCESS)
+ {
+ PIBMTOK_OPEN TmpOpen;
+
+ switch (PendOp->RequestType)
+ {
+ case NdisRequestSetInformation:
+
+ //
+ // Complete the request.
+ //
+ TmpOpen = PendOp->COMMAND.NDIS.SET_FILTER.Open;
+
+ NdisReleaseSpinLock(&(Adapter->Lock));
+
+ NdisCompleteRequest(
+ PendOp->COMMAND.NDIS.SET_FILTER.Open->NdisBindingContext,
+ PNDIS_REQUEST_FROM_PIBMTOK_PEND_DATA(PendOp),
+ NDIS_STATUS_SUCCESS);
+
+ NdisAcquireSpinLock(&(Adapter->Lock));
+
+ Adapter->RequestTimeout = FALSE;
+
+ TmpOpen->References--;
+
+ break;
+
+ case NdisRequestClose:
+
+ PendOp->COMMAND.NDIS.CLOSE.Open->References--;
+ break;
+
+ case NdisRequestGeneric2:
+ case NdisRequestGeneric3:
+
+ PendOp->COMMAND.NDIS.SET_ADDRESS.Open->References--;
+ break;
+
+ case NdisRequestQueryStatistics:
+
+ NdisReleaseSpinLock(&(Adapter->Lock));
+
+ NdisCompleteQueryStatistics(
+ Adapter->NdisMacHandle,
+ PNDIS_REQUEST_FROM_PIBMTOK_PEND_DATA(PendOp),
+ NDIS_STATUS_SUCCESS);
+
+ NdisAcquireSpinLock(&(Adapter->Lock));
+
+ Adapter->RequestTimeout = FALSE;
+
+ Adapter->References--;
+
+ break;
+
+ default:
+
+ NdisWriteErrorLogEntry(
+ Adapter->NdisAdapterHandle,
+ NDIS_ERROR_CODE_DRIVER_FAILURE,
+ 3,
+ startPendQueueOp,
+ IBMTOK_ERRMSG_BAD_OP,
+ PendOp->RequestType);
+ }
+ }
+ else
+ {
+ NdisWriteErrorLogEntry(
+ Adapter->NdisAdapterHandle,
+ NDIS_ERROR_CODE_DRIVER_FAILURE,
+ 3,
+ startPendQueueOp,
+ IBMTOK_ERRMSG_INVALID_STATUS,
+ RequestStatus);
+ }
+ }
+
+ //
+ // We drained the entire queue without pending.
+ //
+ return NDIS_STATUS_SUCCESS;
+}
+
+STATIC
+BOOLEAN
+FinishPendQueueOp(
+ IN PIBMTOK_ADAPTER Adapter,
+ IN BOOLEAN Successful
+ )
+
+/*++
+
+Routine Description:
+
+ This routine is called when an SRB command completes.
+ It calles CompleteRequest if needed and does any other
+ cleanup required.
+
+ NOTE: This routine is called with the lock held and
+ returns with it held.
+
+ NOTE: This routine assumes that the pended operation to
+ be completed was specifically requested by the protocol
+ and, thus, that PendData->Request != NULL.
+
+Arguments:
+
+ Adapter - The adapter that the queue should be checked for.
+
+ Successful - Was the SRB command completed successfully.
+
+Return Value:
+
+ TRUE if the operation was completed, FALSE if another command
+ was submitted to the card to complete the operation.
+
+--*/
+
+{
+ PIBMTOK_PEND_DATA PendOp = Adapter->PendData;
+
+ ASSERT(PendOp != NULL);
+
+ switch (PendOp->RequestType)
+ {
+ case NdisRequestQueryStatistics:
+ //
+ // It was a request for global statistics.
+ //
+ if (Successful)
+ {
+ NDIS_STATUS StatusToReturn;
+
+ //
+ // Grab the data
+ //
+ GetAdapterErrorsFromSrb(Adapter);
+
+ //
+ // Fill in NdisRequest InformationBuffer
+ //
+ StatusToReturn = IbmtokFillInGlobalData(
+ Adapter,
+ PNDIS_REQUEST_FROM_PIBMTOK_PEND_DATA(PendOp));
+
+ //
+ // Complete statistics call
+ //
+ Adapter->PendData = NULL;
+
+ NdisReleaseSpinLock(&(Adapter->Lock));
+
+ NdisCompleteQueryStatistics(
+ Adapter->NdisMacHandle,
+ PNDIS_REQUEST_FROM_PIBMTOK_PEND_DATA(PendOp),
+ StatusToReturn);
+
+ NdisAcquireSpinLock(&(Adapter->Lock));
+
+ Adapter->RequestTimeout = FALSE;
+
+ Adapter->References--;
+ }
+ else
+ {
+ //
+ // Complete statistics call
+ //
+ Adapter->PendData = NULL;
+
+ NdisReleaseSpinLock(&(Adapter->Lock));
+
+ NdisCompleteQueryStatistics(
+ Adapter->NdisMacHandle,
+ PNDIS_REQUEST_FROM_PIBMTOK_PEND_DATA(PendOp),
+ NDIS_STATUS_FAILURE);
+
+ NdisAcquireSpinLock(&(Adapter->Lock));
+
+ Adapter->RequestTimeout = FALSE;
+
+ Adapter->References--;
+ }
+
+ break;
+
+ case NdisRequestSetInformation:
+
+
+ //
+ // It was a request for address change.
+ //
+#if DBG
+ if (IbmtokDbg)
+ {
+ if (Successful)
+ {
+ DbgPrint("IBMTOK: SUCCESS\n\n");
+ }
+ else
+ {
+ DbgPrint("IBMTOK: FAILURE\n\n");
+ }
+ }
+#endif
+
+ if (Successful)
+ {
+ PIBMTOK_OPEN TmpOpen;
+
+ //
+ // complete the operation.
+ //
+ if (PNDIS_REQUEST_FROM_PIBMTOK_PEND_DATA(Adapter->PendData)->DATA.SET_INFORMATION.Oid ==
+ OID_802_5_CURRENT_GROUP)
+ {
+ //
+ // Store new group address
+ //
+ Adapter->CurrentCardGroup = Adapter->CurrentGroupAddress;
+ }
+
+ Adapter->PendData = NULL;
+
+ TmpOpen = PendOp->COMMAND.NDIS.SET_FILTER.Open;
+
+ NdisReleaseSpinLock(&(Adapter->Lock));
+
+ NdisCompleteRequest(
+ PendOp->COMMAND.NDIS.SET_FILTER.Open->NdisBindingContext,
+ PNDIS_REQUEST_FROM_PIBMTOK_PEND_DATA(PendOp),
+ NDIS_STATUS_SUCCESS);
+
+ NdisAcquireSpinLock(&(Adapter->Lock));
+
+ Adapter->RequestTimeout = FALSE;
+
+ TmpOpen->References--;
+ }
+ else
+ {
+ //
+ // complete the operation.
+ //
+ PIBMTOK_OPEN TmpOpen;
+
+ Adapter->PendData = NULL;
+
+ TmpOpen = PendOp->COMMAND.NDIS.SET_FILTER.Open;
+
+ NdisReleaseSpinLock(&(Adapter->Lock));
+
+ NdisCompleteRequest(
+ PendOp->COMMAND.NDIS.SET_FILTER.Open->NdisBindingContext,
+ PNDIS_REQUEST_FROM_PIBMTOK_PEND_DATA(PendOp),
+ NDIS_STATUS_FAILURE);
+
+ NdisAcquireSpinLock(&(Adapter->Lock));
+
+ Adapter->RequestTimeout = FALSE;
+
+ TmpOpen->References--;
+ }
+
+ break;
+
+ case NdisRequestClose:
+ case NdisRequestGeneric2:
+ case NdisRequestGeneric3:
+
+ PendOp->COMMAND.NDIS.CLOSE.Open->References--;
+
+ break;
+ }
+
+ //
+ // Now finish up unsuccessful operations based on the type.
+ //
+ // NOTE: If we ever have cleanup for successful operations,
+ // we probably have to copy that code into the
+ // 'RequestStatus == NDIS_STATUS_SUCCESS' section
+ // in the function above.
+ //
+ if (!Successful)
+ {
+ switch (PendOp->RequestType)
+ {
+ case NdisRequestSetInformation:
+
+ //
+ // We know it was a set filter or set address.
+ //
+ if ((PNDIS_REQUEST_FROM_PIBMTOK_PEND_DATA(PendOp))->DATA.SET_INFORMATION.Oid ==
+ OID_GEN_CURRENT_PACKET_FILTER)
+ {
+ //
+ // It was a set filter.
+ //
+ Adapter->CurrentPacketFilter = Adapter->OldPacketFilter;
+
+ Adapter->CurrentCardFunctional = (TR_FUNCTIONAL_ADDRESS)0;
+ }
+ else
+ {
+ //
+ // It was a set address.
+ //
+ Adapter->CurrentFunctionalAddress = (TR_FUNCTIONAL_ADDRESS)0;
+ }
+
+ break;
+
+ case NdisRequestQueryStatistics:
+
+ break;
+
+ case NdisRequestClose:
+ case NdisRequestGeneric2:
+ case NdisRequestGeneric3:
+
+ break;
+
+ default:
+
+ NdisWriteErrorLogEntry(
+ Adapter->NdisAdapterHandle,
+ NDIS_ERROR_CODE_DRIVER_FAILURE,
+ 3,
+ finishPendQueueOp,
+ IBMTOK_ERRMSG_BAD_OP,
+ PendOp->RequestType);
+
+ break;
+ }
+ }
+
+ return(TRUE);
+}
+
+STATIC
+NDIS_STATUS
+SetAdapterFunctionalAddress(
+ IN PIBMTOK_ADAPTER Adapter
+ )
+
+
+/*++
+
+Routine Description:
+
+ This routine checks the functional address on the adapter
+ against what it should be given the current packet filter
+ and functional address specified, and queues an update
+ if necessary.
+
+ NOTE: This routine assumes that it is called with the lock
+ acquired.
+
+Arguments:
+
+ Adapter - The adapter to check.
+
+Return Value:
+
+ NDIS_STATUS_SUCCESS - If no change is necessary.
+ NDIS_STATUS_PENDING - If the change was queued.
+
+
+--*/
+{
+ //
+ // The new value we compute for the functional address that
+ // should be on the card.
+ //
+ TR_FUNCTIONAL_ADDRESS NewCardFunctional;
+
+ //
+ // Holds the value to be returned.
+ //
+ NDIS_STATUS StatusOfSet;
+
+ //
+ // Used if ALL_MULTICAST is selected.
+ //
+ ULONG AllFunctionalAddress = 0x7fffffff;
+
+ //
+ // First calculate what the new functional address
+ // should be.
+ //
+
+#if DBG
+ if (IbmtokDbg)
+ {
+ DbgPrint("IBMTOK: Current packet filter : 0x%x\n", Adapter->CurrentPacketFilter);
+ }
+#endif
+
+ if (Adapter->CurrentPacketFilter & NDIS_PACKET_TYPE_ALL_FUNCTIONAL)
+ {
+ //
+ // We have to set all the bits in the address.
+ //
+ NewCardFunctional = AllFunctionalAddress;
+ }
+ else if (Adapter->CurrentPacketFilter & NDIS_PACKET_TYPE_FUNCTIONAL)
+ {
+ NewCardFunctional = Adapter->CurrentFunctionalAddress;
+ }
+ else
+ {
+ NewCardFunctional = (TR_FUNCTIONAL_ADDRESS)0;
+ }
+
+#if DBG
+ if (IbmtokDbg)
+ {
+ DbgPrint("IBMTOK: NewFunc is 0x%x\n", NewCardFunctional);
+ }
+#endif
+
+ //
+ // Now queue it up if needed.
+ //
+ if (NewCardFunctional == Adapter->CurrentCardFunctional)
+ {
+#if DBG
+ if (IbmtokDbg)
+ {
+ DbgPrint("IBMTOK: SUCCESS\n\n");
+ }
+#endif
+ StatusOfSet = NDIS_STATUS_SUCCESS;
+ }
+ else
+ {
+ SetupFunctionalSrb(Adapter, NewCardFunctional);
+ Adapter->CurrentCardFunctional = NewCardFunctional;
+
+ StatusOfSet = NDIS_STATUS_PENDING;
+ }
+
+ return StatusOfSet;
+}
+
+STATIC
+VOID
+SetupFunctionalSrb(
+ IN PIBMTOK_ADAPTER Adapter,
+ IN TR_FUNCTIONAL_ADDRESS FunctionalAddress
+ )
+
+/*++
+
+Routine Description:
+
+ This routine sets up the SRB for a DIR.SET.FUNCT.Address.
+
+Arguments:
+
+ Adapter - The adapter that this packet is coming through.
+
+ FunctionalAddress - The address to set up.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+ //
+ // Used to set up the SRB request.
+ //
+ PSRB_SET_FUNCT_ADDRESS FunctSrb =
+ (PSRB_SET_FUNCT_ADDRESS)Adapter->SrbAddress;
+
+ //
+ // Used to hold the functional address temporarily.
+ //
+ UCHAR TempAddress[4];
+
+ //
+ // Used to copy down the functional address.
+ //
+ UINT i;
+
+ NdisWriteRegisterUchar(&(FunctSrb->Command), SRB_CMD_SET_FUNCTIONAL_ADDRESS);
+ NdisWriteRegisterUchar(&(FunctSrb->ReturnCode), 0xfe);
+
+ //
+ // Have to worry about setting the functional address
+ // since it is not aligned correctly.
+ //
+ IBMTOK_STORE_ULONG(TempAddress, FunctionalAddress);
+
+ for (i = 0; i < 4; i++)
+ {
+ NdisWriteRegisterUchar(&(FunctSrb->FunctionalAddress[i]), TempAddress[i]);
+ }
+}
+
+STATIC
+NDIS_STATUS
+SetAdapterGroupAddress(
+ IN PIBMTOK_ADAPTER Adapter
+ )
+
+
+/*++
+
+Routine Description:
+
+ This routine takes the value in Adapter->CurrentGroupAddress and
+ puts it out to the card.
+
+ NOTE: This routine assumes that it is called with the lock
+ acquired.
+
+Arguments:
+
+ Adapter - The adapter to check.
+
+Return Value:
+
+ NDIS_STATUS_PENDING - If the change was queued.
+
+
+--*/
+{
+ //
+ // Holds the value to be returned.
+ //
+ SetupGroupSrb(Adapter, Adapter->CurrentGroupAddress);
+
+ return NDIS_STATUS_PENDING;
+}
+
+STATIC
+VOID
+SetupGroupSrb(
+ IN PIBMTOK_ADAPTER Adapter,
+ IN TR_FUNCTIONAL_ADDRESS GroupAddress
+ )
+
+/*++
+
+Routine Description:
+
+ This routine sets up the SRB for a DIR.SET.GROUP.ADDRESS.
+
+Arguments:
+
+ Adapter - The adapter that this packet is coming through.
+
+ GroupAddress - The address to set up.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+ //
+ // Used to set up the SRB request.
+ //
+ PSRB_SET_GROUP_ADDRESS GroupSrb = (PSRB_SET_GROUP_ADDRESS)Adapter->SrbAddress;
+
+ //
+ // Used to hold the group address temporarily.
+ //
+ UCHAR TempAddress[4];
+
+ //
+ // Used to copy down the group address.
+ //
+ UINT i;
+
+
+ NdisWriteRegisterUchar(&(GroupSrb->Command), SRB_CMD_SET_GROUP_ADDRESS);
+ NdisWriteRegisterUchar(&(GroupSrb->ReturnCode), 0xfe);
+
+ //
+ // Have to worry about setting the group address
+ // since it is not aligned correctly.
+ //
+ IBMTOK_STORE_ULONG(TempAddress, GroupAddress);
+
+ for (i = 0; i < 4; i++)
+ {
+ NdisWriteRegisterUchar(&(GroupSrb->GroupAddress[i]), TempAddress[i]);
+ }
+}
+
+STATIC
+VOID
+SetupReceivedDataAsb(
+ IN PIBMTOK_ADAPTER Adapter,
+ IN SRAM_PTR ReceiveBuffer
+ )
+
+/*++
+
+Routine Description:
+
+ This routine sets up the ASB for a response from
+ a RECEIVED.DATA ARB.
+
+Arguments:
+
+ Adapter - The adapter that this packet is coming through.
+
+ ReceiveBuffer - The first receive buffer in the frame.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+ PASB_RECEIVED_DATA_STATUS ReceivedDataAsb;
+
+ ReceivedDataAsb = (PASB_RECEIVED_DATA_STATUS)
+ Adapter->AsbAddress;
+
+ NdisWriteRegisterUchar(&(ReceivedDataAsb->Command), ARB_CMD_RECEIVED_DATA);
+ NdisWriteRegisterUchar(&(ReceivedDataAsb->ReturnCode), 0x00);
+ NdisWriteRegisterUshort(&(ReceivedDataAsb->StationId), 0x0000);
+ NdisWriteRegisterUshort(&(ReceivedDataAsb->ReceiveBuffer), ReceiveBuffer);
+}
+
+STATIC
+VOID
+PutPacketOnWaitingForAsb(
+ IN PIBMTOK_ADAPTER Adapter,
+ IN PNDIS_PACKET Packet
+ )
+
+/*++
+
+Routine Description:
+
+ This queues a packet on the Waiting To Copy queue.
+ It is called and returns with the spinlock held.
+
+Arguments:
+
+ Adapter - The adapter that this packet is coming through.
+
+ Packet - The packet that is to be transmitted.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+ //
+ // Points to the MAC reserved portion of this packet. This
+ // interpretation of the reserved section is only valid during
+ // the allocation phase of the packet.
+ //
+ PIBMTOK_RESERVED Reserved = PIBMTOK_RESERVED_FROM_PACKET(Packet);
+
+
+ ASSERT(sizeof(IBMTOK_RESERVED) <= sizeof(Packet->MacReserved));
+
+ if (Adapter->FirstWaitingForAsb == NULL)
+ {
+ Adapter->FirstWaitingForAsb = Packet;
+ }
+ else
+ {
+ PIBMTOK_RESERVED_FROM_PACKET(Adapter->FirstWaitingForAsb)->Next = Packet;
+ }
+
+ Adapter->LastWaitingForAsb = Packet;
+
+ Reserved->Next = NULL;
+}
+extern
+VOID
+IbmtokHandleDeferred(
+ IN PIBMTOK_ADAPTER Adapter
+ )
+
+/*++
+
+Routine Description:
+
+ This routine handles any pending resets and closes.
+ It is called during interrupt processing and also at
+ the end of every routine if needed.
+
+ NOTE: This routine is called with the spinlock held
+ and returns with it held.
+
+Arguments:
+
+ Adapter - The adapter to check deferred processing on.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+ PIBMTOK_OPEN Open;
+
+ //
+ // Note that the following code depends on the fact that
+ // code above left the spinlock held.
+ //
+
+ //
+ // We will only come in here if the adapter's reference
+ // count is zero, so if a reset is in progress then we
+ // can start the reset.
+ //
+
+ //
+ // Make sure we don't start it twice!!
+ //
+ Adapter->References++;
+
+ if (Adapter->ResetInProgress && Adapter->CurrentResetStage == 0)
+ {
+ Adapter->CurrentResetStage = 1;
+
+ NdisReleaseSpinLock(&(Adapter->Lock));
+
+ IbmtokStartAdapterReset(Adapter);
+
+ NdisAcquireSpinLock(&(Adapter->Lock));
+ }
+
+ if (!Adapter->ResetInProgress && !IsListEmpty(&(Adapter->CloseDuringResetList)))
+ {
+ //
+ // Status of the Filter delete call.
+ //
+ NDIS_STATUS Status;
+
+ Open = CONTAINING_RECORD(
+ Adapter->CloseDuringResetList.Flink,
+ IBMTOK_OPEN,
+ OpenList);
+
+ Open->References++;
+#if DBG
+ if (IbmtokDbg) DbgPrint("IBMTOK: Calling TrDelete\n");
+#endif
+
+ Status = TrDeleteFilterOpenAdapter(
+ Adapter->FilterDB,
+ Open->NdisFilterHandle,
+ NULL);
+
+#if DBG
+ if (IbmtokDbg) DbgPrint("IBMTOK: TrDelete returned\n");
+#endif
+
+ //
+ // If the status is successful that merely implies that
+ // we were able to delete the reference to the open binding
+ // from the filtering code. If we have a successful status
+ // at this point we still need to check whether the reference
+ // count to determine whether we can close.
+ //
+ //
+ // The delete filter routine can return a "special" status
+ // that indicates that there is a current NdisIndicateReceive
+ // on this binding.
+ //
+ if (Status == NDIS_STATUS_SUCCESS)
+ {
+ //
+ // Check whether the reference count is two. If
+ // it is then we can get rid of the memory for
+ // this open.
+ //
+ // A count of two indicates one for this routine
+ // and one for the filter which we *know* we can
+ // get rid of.
+ //
+ if (Open->References == 2)
+ {
+ //
+ // We are the only reference to the open. Remove
+ // it from the list and delete the memory.
+ //
+ RemoveEntryList(&Open->OpenList);
+
+ //
+ // Complete the close here.
+ //
+ if (Adapter->LookAhead == Open->LookAhead)
+ {
+ IbmtokAdjustMaxLookAhead(Adapter);
+ }
+
+ NdisReleaseSpinLock(&Adapter->Lock);
+
+ NdisCompleteCloseAdapter(
+ Open->NdisBindingContext,
+ NDIS_STATUS_SUCCESS);
+
+ IBMTOK_FREE_PHYS(Open,sizeof(IBMTOK_OPEN));
+
+ NdisAcquireSpinLock(&Adapter->Lock);
+ }
+ else
+ {
+ //
+ // Remove the open from the list and put it on
+ // the closing list.
+ //
+ RemoveEntryList(&Open->OpenList);
+
+ InsertTailList(&Adapter->CloseList,&Open->OpenList);
+
+ //
+ // Account for this routines reference to the open
+ // as well as reference because of the filtering.
+ //
+ Open->References -= 2;
+ }
+ }
+ else if (Status == NDIS_STATUS_PENDING)
+ {
+ //
+ // If it pended, there may be
+ // operations queued.
+ // Returns with lock released
+ //
+ IbmtokProcessSrbRequests(Adapter);
+
+ //
+ // Now start closing down this open.
+ //
+ Open->BindingShuttingDown = TRUE;
+
+ //
+ // Remove the open from the open list and put it on
+ // the closing list.
+ //
+ RemoveEntryList(&Open->OpenList);
+ InsertTailList(&Adapter->CloseList,&Open->OpenList);
+
+ //
+ // Account for this routines reference to the open
+ // as well as reference because of the filtering.
+ //
+ Open->References -= 2;
+ }
+ else
+ {
+ //
+ // We should not get RESET_IN_PROGRESS or any other types.
+ //
+ NdisWriteErrorLogEntry(
+ Adapter->NdisAdapterHandle,
+ NDIS_ERROR_CODE_DRIVER_FAILURE,
+ 3,
+ handleDeferred,
+ IBMTOK_ERRMSG_INVALID_STATUS,
+ Status);
+ }
+ }
+
+ //
+ // If there are any opens on the closing list and their
+ // reference counts are zero then complete the close and
+ // delete them from the list.
+ //
+ //
+ if (!IsListEmpty(&(Adapter->CloseList))){
+
+ Open = CONTAINING_RECORD(
+ Adapter->CloseList.Flink,
+ IBMTOK_OPEN,
+ OpenList);
+
+ if (!Open->References)
+ {
+ if (Adapter->LookAhead == Open->LookAhead)
+ {
+ IbmtokAdjustMaxLookAhead(Adapter);
+ }
+
+ NdisReleaseSpinLock(&(Adapter->Lock));
+
+ NdisCompleteCloseAdapter(
+ Open->NdisBindingContext,
+ NDIS_STATUS_SUCCESS);
+
+ NdisAcquireSpinLock(&(Adapter->Lock));
+ RemoveEntryList(&(Open->OpenList));
+ IBMTOK_FREE_PHYS(Open, sizeof(IBMTOK_OPEN));
+ }
+ }
+
+ Adapter->References--;
+}
+
+extern
+VOID
+IbmtokAbortPending(
+ IN PIBMTOK_ADAPTER Adapter,
+ IN NDIS_STATUS AbortStatus
+ )
+
+/*++
+
+Routine Description:
+
+ This routine aborts any pending requests, and calls
+ IbmtokAbortSends to abort any pending sends.
+
+ NOTE: This routine is called with the spinlock held
+ and returns with it held.
+
+Arguments:
+
+ Adapter - The adapter to abort.
+
+ AbortStatus - The status to complete requests with.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+ PIBMTOK_OPEN Open;
+ PIBMTOK_PEND_DATA PendOp;
+
+ while (Adapter->PendQueue)
+ {
+ //
+ // Holds the operation on the head of the queue
+ //
+ PendOp = Adapter->PendQueue;
+
+ Adapter->PendQueue = Adapter->PendQueue->Next;
+
+ if (Adapter->PendQueue == NULL)
+ {
+ //
+ // We have just emptied the list.
+ //
+ Adapter->EndOfPendQueue = NULL;
+ }
+
+ switch (PendOp->RequestType)
+ {
+ case NdisRequestSetInformation:
+
+ //
+ // Complete the request.
+ //
+ Open = PendOp->COMMAND.NDIS.SET_FILTER.Open;
+
+ NdisDprReleaseSpinLock(&(Adapter->Lock));
+
+ NdisCompleteRequest(
+ Open->NdisBindingContext,
+ PNDIS_REQUEST_FROM_PIBMTOK_PEND_DATA(PendOp),
+ AbortStatus);
+
+ NdisDprAcquireSpinLock(&(Adapter->Lock));
+
+ Adapter->RequestTimeout = FALSE;
+
+ Open->References--;
+
+ break;
+
+ case NdisRequestClose:
+
+ PendOp->COMMAND.NDIS.CLOSE.Open->References--;
+ break;
+
+ case NdisRequestGeneric1:
+
+ //
+ // Submitted by the driver
+ //
+ IBMTOK_FREE_PHYS(PendOp, sizeof(IBMTOK_PEND_DATA));
+ Adapter->PendData = NULL;
+ break;
+
+ case NdisRequestGeneric2:
+ case NdisRequestGeneric3:
+
+ //
+ // Changes in address and filters due to a close
+ //
+ PendOp->COMMAND.NDIS.SET_ADDRESS.Open->References--;
+ break;
+
+
+ case NdisRequestQueryStatistics:
+
+ NdisDprReleaseSpinLock(&(Adapter->Lock));
+
+ NdisCompleteQueryStatistics(
+ Adapter->NdisMacHandle,
+ PNDIS_REQUEST_FROM_PIBMTOK_PEND_DATA(PendOp),
+ AbortStatus);
+
+ NdisDprAcquireSpinLock(&(Adapter->Lock));
+
+ Adapter->RequestTimeout = FALSE;
+
+ Adapter->References--;
+
+ break;
+ }
+ }
+
+ IbmtokAbortSends (Adapter, AbortStatus);
+}
+
+extern
+VOID
+IbmtokAbortSends(
+ IN PIBMTOK_ADAPTER Adapter,
+ IN NDIS_STATUS AbortStatus
+ )
+
+/*++
+
+Routine Description:
+
+ This routine aborts any pending sends.
+
+ NOTE: This routine is called with the spinlock held
+ and returns with it held.
+
+Arguments:
+
+ Adapter - The adapter to abort.
+
+ AbortStatus - The status to complete requests with.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+ PIBMTOK_OPEN Open;
+ PNDIS_PACKET TransmitPacket;
+ PIBMTOK_RESERVED Reserved;
+ UINT i;
+
+ //
+ // First the packet in the SRB.
+ //
+ if (Adapter->TransmittingPacket != NULL)
+ {
+ TransmitPacket = Adapter->TransmittingPacket;
+ Adapter->TransmittingPacket = NULL;
+
+ Reserved = PIBMTOK_RESERVED_FROM_PACKET(TransmitPacket);
+ Open = PIBMTOK_OPEN_FROM_BINDING_HANDLE(Reserved->MacBindingHandle);
+
+ NdisDprReleaseSpinLock(&Adapter->Lock);
+
+ NdisCompleteSend(Open->NdisBindingContext, TransmitPacket, AbortStatus);
+
+ NdisDprAcquireSpinLock(&Adapter->Lock);
+ Open->References--;
+ }
+
+ //
+ // Then any that are queued up waiting to be given to the card.
+ //
+ while (Adapter->FirstTransmit)
+ {
+ TransmitPacket = Adapter->FirstTransmit;
+
+ Reserved = PIBMTOK_RESERVED_FROM_PACKET(TransmitPacket);
+ Adapter->FirstTransmit = Reserved->Next;
+
+ Open = PIBMTOK_OPEN_FROM_BINDING_HANDLE(Reserved->MacBindingHandle);
+
+ NdisDprReleaseSpinLock(&Adapter->Lock);
+
+ NdisCompleteSend(
+ Open->NdisBindingContext,
+ TransmitPacket,
+ AbortStatus);
+
+ NdisDprAcquireSpinLock(&Adapter->Lock);
+ Open->References--;
+ }
+
+ //
+ // Finally, the Correlator array (this will include any
+ // packets on WaitingForAsb).
+ //
+
+ for (i = 0; i < MAX_COMMAND_CORRELATOR; i++)
+ {
+ TransmitPacket = Adapter->CorrelatorArray[i];
+
+ if (TransmitPacket != NULL)
+ {
+ RemovePacketFromCorrelatorArray (Adapter, TransmitPacket);
+
+ Reserved = PIBMTOK_RESERVED_FROM_PACKET(TransmitPacket);
+ Open = PIBMTOK_OPEN_FROM_BINDING_HANDLE(Reserved->MacBindingHandle);
+
+ NdisDprReleaseSpinLock(&Adapter->Lock);
+
+ NdisCompleteSend(
+ Open->NdisBindingContext,
+ Reserved->Packet,
+ AbortStatus);
+
+ NdisDprAcquireSpinLock(&Adapter->Lock);
+ Open->References--;
+ }
+ }
+
+ Adapter->FirstWaitingForAsb = NULL;
+}
+
+VOID
+IbmtokWakeUpDpc(
+ IN PVOID SystemSpecific1,
+ IN PVOID Context,
+ IN PVOID SystemSpecific2,
+ IN PVOID SystemSpecific3
+ )
+
+/*++
+
+Routine Description:
+
+ This DPC routine is queued every 2 seconds to check on the
+ queues. If an interrupt was not received
+ in the last two seconds and there should have been one,
+ then we abort all operations.
+
+Arguments:
+
+ Context - Really a pointer to the adapter.
+
+Return Value:
+
+ None.
+
+--*/
+{
+ PIBMTOK_ADAPTER Adapter = (PIBMTOK_ADAPTER)Context;
+
+ UNREFERENCED_PARAMETER(SystemSpecific1);
+ UNREFERENCED_PARAMETER(SystemSpecific2);
+ UNREFERENCED_PARAMETER(SystemSpecific3);
+
+ NdisDprAcquireSpinLock(&Adapter->Lock);
+
+ if ((Adapter->SendTimeout &&
+ ((Adapter->TransmittingPacket != NULL) ||
+ (Adapter->FirstTransmit != NULL))) ||
+ (Adapter->RequestTimeout && (Adapter->PendQueue != NULL)))
+ {
+ //
+ // We had a pending operation the last time we ran,
+ // and it has not been completed...we need to complete
+ // it now.
+ Adapter->NotAcceptingRequests = TRUE;
+
+ Adapter->SendTimeout = FALSE;
+ Adapter->RequestTimeout = FALSE;
+
+ //
+ // Complete any pending requests or sends.
+ //
+ IbmtokAbortPending(Adapter, STATUS_REQUEST_ABORTED);
+
+ Adapter->WakeUpErrorCount++;
+ IbmtokSetupForReset(Adapter, NULL);
+
+ IbmtokHandleDeferred(Adapter);
+ }
+ else
+ {
+ if ((Adapter->TransmittingPacket != NULL) ||
+ (Adapter->FirstTransmit != NULL))
+ {
+ Adapter->SendTimeout = TRUE;
+ }
+
+ if (Adapter->PendQueue != NULL)
+ {
+ Adapter->RequestTimeout = TRUE;
+ }
+ }
+
+ //
+ // If we've been unplugged, and there is not a reset in
+ // progress, try one.
+ //
+ if ((Adapter->LobeWireFaultIndicated) &&
+ (!Adapter->UnpluggedResetInProgress))
+ {
+ Adapter->UnpluggedResetInProgress = TRUE;
+
+ IbmtokSetupForReset(Adapter, NULL);
+
+ IbmtokHandleDeferred(Adapter);
+ }
+
+ NdisDprReleaseSpinLock(&Adapter->Lock);
+
+ //
+ // Fire off another Dpc to execute after 30 seconds
+ //
+ NdisSetTimer(&Adapter->WakeUpTimer, 30000);
+}
+
diff --git a/private/ntos/ndis/ibmtok/keywords.h b/private/ntos/ndis/ibmtok/keywords.h
new file mode 100644
index 000000000..0e3217834
--- /dev/null
+++ b/private/ntos/ndis/ibmtok/keywords.h
@@ -0,0 +1,54 @@
+/*++
+
+Copyright (c) 1990 Microsoft Corporation
+
+Module Name:
+
+ keywords.h
+
+Abstract:
+
+ Contains all Ndis2 and Ndis3 mac-specific keywords.
+
+Author:
+
+ Bob Noradki
+
+Environment:
+
+ This driver is expected to work in DOS, OS2 and NT at the equivalent
+ of kernal mode.
+
+ Architecturally, there is an assumption in this driver that we are
+ on a little endian machine.
+
+Notes:
+
+ optional-notes
+
+Revision History:
+
+
+
+--*/
+#ifndef NDIS2
+#define NDIS2 0
+#endif
+
+#if NDIS2
+
+#define SLOTNUMBER NDIS_STRING_CONST("SLOTNUMBER")
+#define MAXPACKETSIZE NDIS_STRING_CONST("MAXPACKETSIZE")
+#define IOADDRESS NDIS_STRING_CONST("IOBASE")
+#define NETWORK_ADDRESS NDIS_STRING_CONST("NETADDRESS")
+#define TOKEN_RELEASE NDIS_STRING_CONST("EARLYTOKENRELEASE")
+
+#else // NDIS3
+
+#define SLOTNUMBER NDIS_STRING_CONST("SlotNumber")
+#define MAXPACKETSIZE NDIS_STRING_CONST("MaximumPacketSize")
+#define IOADDRESS NDIS_STRING_CONST("IoBaseAddress")
+#define NETWORK_ADDRESS NDIS_STRING_CONST("NetworkAddress")
+#define TOKEN_RELEASE NDIS_STRING_CONST("EarlyTokenRelease")
+
+#endif
diff --git a/private/ntos/ndis/ibmtok/makefile b/private/ntos/ndis/ibmtok/makefile
new file mode 100644
index 000000000..6ee4f43fa
--- /dev/null
+++ b/private/ntos/ndis/ibmtok/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/ibmtok/packet.c b/private/ntos/ndis/ibmtok/packet.c
new file mode 100644
index 000000000..dcff44c34
--- /dev/null
+++ b/private/ntos/ndis/ibmtok/packet.c
@@ -0,0 +1,732 @@
+/*++
+
+Copyright (c) 1990 Microsoft Corporation
+
+Module Name:
+
+ transfer.c
+
+Abstract:
+
+ This module contains code to copy from ndis packets to ndis packets,
+ and also to copy from ndis packets to a buffer.
+
+Author:
+
+ Anthony V. Ercolano (Tonye) 12-Sept-1990
+
+Environment:
+
+ Works in kernel mode, but is not important that it does.
+
+Revision History:
+
+
+--*/
+
+#include <ndis.h>
+
+#include <tfilter.h>
+#include <tokhrd.h>
+#include <toksft.h>
+
+
+extern
+VOID
+IbmtokCopyFromPacketToBuffer(
+ IN PNDIS_PACKET Packet,
+ IN UINT Offset,
+ IN UINT BytesToCopy,
+ OUT PCHAR Buffer,
+ OUT PUINT BytesCopied
+ )
+
+/*++
+
+Routine Description:
+
+ Copy from an ndis packet into a buffer.
+
+Arguments:
+
+ Packet - The packet to copy from.
+
+ Offset - The offset from which to start the copy.
+
+ BytesToCopy - The number of bytes to copy from the packet.
+
+ Buffer - The destination of the copy.
+
+ BytesCopied - The number of bytes actually copied. Can be less then
+ BytesToCopy if the packet is shorter than BytesToCopy.
+
+Return Value:
+
+ None
+
+--*/
+
+{
+
+ //
+ // Holds the number of ndis buffers comprising the packet.
+ //
+ UINT NdisBufferCount;
+
+ //
+ // Points to the buffer from which we are extracting data.
+ //
+ PNDIS_BUFFER CurrentBuffer;
+
+ //
+ // Holds the virtual address of the current buffer.
+ //
+ PVOID VirtualAddress;
+
+ //
+ // Holds the length of the current buffer of the packet.
+ //
+ UINT CurrentLength;
+
+ //
+ // Keep a local variable of BytesCopied so we aren't referencing
+ // through a pointer.
+ //
+ UINT LocalBytesCopied = 0;
+
+ //
+ // Take care of boundary condition of zero length copy.
+ //
+
+ *BytesCopied = 0;
+ if (!BytesToCopy) return;
+
+ //
+ // Get the first buffer.
+ //
+
+ NdisQueryPacket(Packet,
+ NULL,
+ &NdisBufferCount,
+ &CurrentBuffer,
+ NULL
+ );
+
+ //
+ // Could have a null packet.
+ //
+
+ if (!NdisBufferCount) return;
+
+ NdisQueryBuffer(CurrentBuffer, &VirtualAddress, &CurrentLength);
+
+ while (LocalBytesCopied < BytesToCopy) {
+
+ if (!CurrentLength) {
+
+ NdisGetNextBuffer(
+ CurrentBuffer,
+ &CurrentBuffer
+ );
+
+ //
+ // We've reached the end of the packet. We return
+ // with what we've done so far. (Which must be shorter
+ // than requested.
+ //
+
+ if (CurrentBuffer == NULL) break;
+
+ NdisQueryBuffer(CurrentBuffer, &VirtualAddress, &CurrentLength);
+ continue;
+
+ }
+
+ //
+ // Try to get us up to the point to start the copy.
+ //
+
+ if (Offset) {
+
+ if (Offset > CurrentLength) {
+
+ //
+ // What we want isn't in this buffer.
+ //
+
+ Offset -= CurrentLength;
+ CurrentLength = 0;
+ continue;
+
+ } else {
+
+ VirtualAddress = (PCHAR)VirtualAddress + Offset;
+ CurrentLength -= Offset;
+ Offset = 0;
+
+ }
+
+ }
+
+ //
+ // Copy the data.
+ //
+
+
+ {
+
+ //
+ // Holds the amount of data to move.
+ //
+ UINT AmountToMove;
+
+ AmountToMove =
+ ((CurrentLength <= (BytesToCopy - LocalBytesCopied))?
+ (CurrentLength):(BytesToCopy - LocalBytesCopied));
+
+ IBMTOK_MOVE_TO_MAPPED_MEMORY(
+ Buffer,
+ VirtualAddress,
+ AmountToMove
+ );
+
+ Buffer = (PCHAR)Buffer + AmountToMove;
+ VirtualAddress = (PCHAR)VirtualAddress + AmountToMove;
+
+ LocalBytesCopied += AmountToMove;
+ CurrentLength -= AmountToMove;
+
+ }
+
+ }
+
+ *BytesCopied = LocalBytesCopied;
+
+}
+
+extern
+VOID
+IbmtokCopyFromBufferToPacket(
+ IN PCHAR Buffer,
+ IN UINT BytesToCopy,
+ IN PNDIS_PACKET Packet,
+ IN UINT Offset,
+ OUT PUINT BytesCopied
+ )
+
+/*++
+
+Routine Description:
+
+ Copy from a buffer into an ndis packet.
+
+Arguments:
+
+ Buffer - The packet to copy from.
+
+ Offset - The offset from which to start the copy.
+
+ BytesToCopy - The number of bytes to copy from the buffer.
+
+ Packet - The destination of the copy.
+
+ BytesCopied - The number of bytes actually copied. Will be less
+ than BytesToCopy if the packet is not large enough.
+
+Return Value:
+
+ None
+
+--*/
+
+{
+ //
+ // Holds the count of the number of ndis buffers comprising the
+ // destination packet.
+ //
+ UINT DestinationBufferCount;
+
+ //
+ // Points to the buffer into which we are putting data.
+ //
+ PNDIS_BUFFER DestinationCurrentBuffer;
+
+ //
+ // Points to the location in Buffer from which we are extracting data.
+ //
+ PUCHAR SourceCurrentAddress;
+
+ //
+ // Holds the virtual address of the current destination buffer.
+ //
+ PVOID DestinationVirtualAddress;
+
+ //
+ // Holds the length of the current destination buffer.
+ //
+ UINT DestinationCurrentLength;
+
+ //
+ // Keep a local variable of BytesCopied so we aren't referencing
+ // through a pointer.
+ //
+ UINT LocalBytesCopied = 0;
+
+
+ //
+ // Take care of boundary condition of zero length copy.
+ //
+
+ *BytesCopied = 0;
+ if (!BytesToCopy) return;
+
+ //
+ // Get the first buffer of the destination.
+ //
+
+ NdisQueryPacket(
+ Packet,
+ NULL,
+ &DestinationBufferCount,
+ &DestinationCurrentBuffer,
+ NULL
+ );
+
+ //
+ // Could have a null packet.
+ //
+
+ if (!DestinationBufferCount) return;
+
+ NdisQueryBuffer(
+ DestinationCurrentBuffer,
+ &DestinationVirtualAddress,
+ &DestinationCurrentLength
+ );
+
+ //
+ // Set up the source address.
+ //
+
+ SourceCurrentAddress = Buffer;
+
+
+ while (LocalBytesCopied < BytesToCopy) {
+
+ //
+ // Check to see whether we've exhausted the current destination
+ // buffer. If so, move onto the next one.
+ //
+
+ if (!DestinationCurrentLength) {
+
+ 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;
+
+ }
+
+ //
+ // Try to get us up to the point to start the copy.
+ //
+
+ if (Offset) {
+
+ if (Offset > DestinationCurrentLength) {
+
+ //
+ // What we want isn't in this buffer.
+ //
+
+ Offset -= DestinationCurrentLength;
+ DestinationCurrentLength = 0;
+ continue;
+
+ } else {
+
+ DestinationVirtualAddress = (PCHAR)DestinationVirtualAddress
+ + Offset;
+ DestinationCurrentLength -= Offset;
+ Offset = 0;
+
+ }
+
+ }
+
+
+ //
+ // Copy the data.
+ //
+
+ {
+
+ //
+ // Holds the amount of data to move.
+ //
+ UINT AmountToMove;
+
+ //
+ // Holds the amount desired remaining.
+ //
+ UINT Remaining = BytesToCopy - LocalBytesCopied;
+
+
+ AmountToMove = DestinationCurrentLength;
+
+ AmountToMove = ((Remaining < AmountToMove)?
+ (Remaining):(AmountToMove));
+
+ IBMTOK_MOVE_FROM_MAPPED_MEMORY(
+ DestinationVirtualAddress,
+ SourceCurrentAddress,
+ AmountToMove
+ );
+
+ SourceCurrentAddress += AmountToMove;
+ LocalBytesCopied += AmountToMove;
+ DestinationCurrentLength -= AmountToMove;
+
+ }
+
+ }
+
+ *BytesCopied = LocalBytesCopied;
+
+
+}
+
+extern
+VOID
+IbmtokCopyFromPacketToPacket(
+ IN PNDIS_PACKET Destination,
+ IN UINT DestinationOffset,
+ IN UINT BytesToCopy,
+ IN PNDIS_PACKET Source,
+ IN UINT SourceOffset,
+ OUT PUINT BytesCopied
+ )
+
+/*++
+
+Routine Description:
+
+ Copy from an ndis packet to an ndis packet.
+
+Arguments:
+
+ Destination - The packet should be copied in to.
+
+ DestinationOffset - The offset from the beginning of the packet
+ into which the data should start being placed.
+
+ BytesToCopy - The number of bytes to copy from the source packet.
+
+ Source - The ndis packet from which to copy data.
+
+ SourceOffset - The offset from the start of the packet from which
+ to start copying data.
+
+ BytesCopied - The number of bytes actually copied from the source
+ packet. This can be less than BytesToCopy if the source or destination
+ packet is too short.
+
+Return Value:
+
+ None
+
+--*/
+
+{
+
+ //
+ // Holds the count of the number of ndis buffers comprising the
+ // destination packet.
+ //
+ UINT DestinationBufferCount;
+
+ //
+ // Holds the count of the number of ndis buffers comprising the
+ // source packet.
+ //
+ UINT SourceBufferCount;
+
+ //
+ // Points to the buffer into which we are putting data.
+ //
+ PNDIS_BUFFER DestinationCurrentBuffer;
+
+ //
+ // Points to the buffer from which we are extracting data.
+ //
+ PNDIS_BUFFER SourceCurrentBuffer;
+
+ //
+ // Holds the virtual address of the current destination buffer.
+ //
+ PVOID DestinationVirtualAddress;
+
+ //
+ // Holds the virtual address of the current source buffer.
+ //
+ PVOID SourceVirtualAddress;
+
+ //
+ // Holds the length of the current destination buffer.
+ //
+ UINT DestinationCurrentLength;
+
+ //
+ // Holds the length of the current source buffer.
+ //
+ UINT SourceCurrentLength;
+
+ //
+ // Keep a local variable of BytesCopied so we aren't referencing
+ // through a pointer.
+ //
+ UINT LocalBytesCopied = 0;
+
+ //
+ // Take care of boundary condition of zero length copy.
+ //
+
+ *BytesCopied = 0;
+ if (!BytesToCopy) return;
+
+ //
+ // Get the first buffer of the destination.
+ //
+
+ NdisQueryPacket(
+ Destination,
+ NULL,
+ &DestinationBufferCount,
+ &DestinationCurrentBuffer,
+ NULL
+ );
+
+ //
+ // Could have a null packet.
+ //
+
+ if (!DestinationBufferCount) return;
+
+ NdisQueryBuffer(
+ DestinationCurrentBuffer,
+ &DestinationVirtualAddress,
+ &DestinationCurrentLength
+ );
+
+ //
+ // Get the first buffer of the source.
+ //
+
+ NdisQueryPacket(
+ Source,
+ NULL,
+ &SourceBufferCount,
+ &SourceCurrentBuffer,
+ NULL
+ );
+
+ //
+ // Could have a null packet.
+ //
+
+ if (!SourceBufferCount) return;
+
+ NdisQueryBuffer(
+ SourceCurrentBuffer,
+ &SourceVirtualAddress,
+ &SourceCurrentLength
+ );
+
+ while (LocalBytesCopied < BytesToCopy) {
+
+ //
+ // Check to see whether we've exhausted the current destination
+ // buffer. If so, move onto the next one.
+ //
+
+ if (!DestinationCurrentLength) {
+
+ 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;
+
+ }
+
+
+ //
+ // Check to see whether we've exhausted the current source
+ // buffer. If so, move onto the next one.
+ //
+
+ if (!SourceCurrentLength) {
+
+ NdisGetNextBuffer(
+ SourceCurrentBuffer,
+ &SourceCurrentBuffer
+ );
+
+ if (SourceCurrentBuffer == 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(
+ SourceCurrentBuffer,
+ &SourceVirtualAddress,
+ &SourceCurrentLength
+ );
+ continue;
+
+ }
+
+ //
+ // Try to get us up to the point to start the copy.
+ //
+
+ if (DestinationOffset) {
+
+ if (DestinationOffset > DestinationCurrentLength) {
+
+ //
+ // What we want isn't in this buffer.
+ //
+
+ DestinationOffset -= DestinationCurrentLength;
+ DestinationCurrentLength = 0;
+ continue;
+
+ } else {
+
+ DestinationVirtualAddress = (PCHAR)DestinationVirtualAddress
+ + DestinationOffset;
+ DestinationCurrentLength -= DestinationOffset;
+ DestinationOffset = 0;
+
+ }
+
+ }
+
+ //
+ // Try to get us up to the point to start the copy.
+ //
+
+ if (SourceOffset) {
+
+ if (SourceOffset > SourceCurrentLength) {
+
+ //
+ // What we want isn't in this buffer.
+ //
+
+ SourceOffset -= SourceCurrentLength;
+ SourceCurrentLength = 0;
+ continue;
+
+ } else {
+
+ SourceVirtualAddress = (PCHAR)SourceVirtualAddress
+ + SourceOffset;
+ SourceCurrentLength -= SourceOffset;
+ SourceOffset = 0;
+
+ }
+
+ }
+
+ //
+ // Copy the data.
+ //
+
+ {
+
+ //
+ // Holds the amount of data to move.
+ //
+ UINT AmountToMove;
+
+ //
+ // Holds the amount desired remaining.
+ //
+ UINT Remaining = BytesToCopy - LocalBytesCopied;
+
+ AmountToMove =
+ ((SourceCurrentLength <= DestinationCurrentLength)?
+ (SourceCurrentLength):(DestinationCurrentLength));
+
+ AmountToMove = ((Remaining < AmountToMove)?
+ (Remaining):(AmountToMove));
+
+ IBMTOK_MOVE_MEMORY(
+ DestinationVirtualAddress,
+ SourceVirtualAddress,
+ AmountToMove
+ );
+
+ DestinationVirtualAddress =
+ (PCHAR)DestinationVirtualAddress + AmountToMove;
+ SourceVirtualAddress =
+ (PCHAR)SourceVirtualAddress + AmountToMove;
+
+ LocalBytesCopied += AmountToMove;
+ SourceCurrentLength -= AmountToMove;
+ DestinationCurrentLength -= AmountToMove;
+
+ }
+
+ }
+
+ *BytesCopied = LocalBytesCopied;
+
+}
diff --git a/private/ntos/ndis/ibmtok/send.c b/private/ntos/ndis/ibmtok/send.c
new file mode 100644
index 000000000..a6cbddfb0
--- /dev/null
+++ b/private/ntos/ndis/ibmtok/send.c
@@ -0,0 +1,322 @@
+/*++
+
+Copyright (c) 1990 Microsoft Corporation
+
+Module Name:
+
+ send.c
+
+Abstract:
+
+ This file contains the code for putting a packet through the
+ staged allocation for transmission.
+
+ This is a process of
+
+ 1) Calculating the what would need to be done to the
+ packet so that the packet can be transmitted on the hardware.
+
+ 2) Potentially allocating adapter buffers and copying user data
+ to those buffers so that the packet data is transmitted under
+ the hardware constraints.
+
+ 3) Allocating enough hardware ring entries so that the packet
+ can be transmitted.
+
+ 4) Relinquish thos ring entries to the hardware.
+
+ The overall structure and most of the code is taken from
+ the Lance driver by Tony Ercolano.
+
+Author:
+
+ Anthony V. Ercolano (Tonye) 12-Sept-1990
+ Adam Barr (adamba) 16-Nov-1990
+
+Environment:
+
+ Kernel Mode - Or whatever is the equivalent.
+
+Revision History:
+
+
+--*/
+
+#include <ndis.h>
+
+#include <tfilter.h>
+#include <tokhrd.h>
+#include <toksft.h>
+
+
+#if DEVL
+#define STATIC
+#else
+#define STATIC static
+#endif
+
+#if DBG
+extern INT IbmtokDbg;
+
+extern UCHAR Packets[5][64];
+extern UCHAR NextPacket;
+#endif
+
+
+
+#ifdef CHECK_DUP_SENDS
+
+//
+// CHECK_DUP_SENDS enables checking ownership of packets, to
+// make sure we are not given the same packet twice, or
+// complete the same packet twice.
+//
+
+#define PACKET_LIST_SIZE 50
+
+PNDIS_PACKET IbmtokPacketList[PACKET_LIST_SIZE];
+IbmtokPacketListSize = 0;
+IbmtokPacketsAdded = 0;
+IbmtokPacketsRemoved = 0;
+
+VOID
+IbmtokAddPacketToList(
+ PIBMTOK_ADAPTER Adapter,
+ PNDIS_PACKET NewPacket
+ )
+{
+ INT i;
+
+++IbmtokPacketsAdded;
+
+ for (i=0; i<IbmtokPacketListSize; i++) {
+
+ if (IbmtokPacketList[i] == NewPacket) {
+
+ DbgPrint("IBMTOK: dup send of %lx\n", NewPacket);
+
+ }
+
+ }
+
+ IbmtokPacketList[IbmtokPacketListSize] = NewPacket;
+ ++IbmtokPacketListSize;
+
+}
+
+VOID
+IbmtokRemovePacketFromList(
+ PIBMTOK_ADAPTER Adapter,
+ PNDIS_PACKET OldPacket
+ )
+{
+ INT i;
+
+++IbmtokPacketsRemoved;
+
+ for (i=0; i<IbmtokPacketListSize; i++) {
+
+ if (IbmtokPacketList[i] == OldPacket) {
+
+ break;
+
+ }
+
+ }
+
+ if (i == IbmtokPacketListSize) {
+
+ DbgPrint("IBMTOK: bad remove of %lx\n", OldPacket);
+
+ } else {
+
+ --IbmtokPacketListSize;
+ IbmtokPacketList[i] = IbmtokPacketList[IbmtokPacketListSize];
+
+ }
+
+}
+#endif // CHECK_DUP_SENDS
+
+
+extern
+NDIS_STATUS
+IbmtokSend(
+ IN NDIS_HANDLE MacBindingHandle,
+ IN PNDIS_PACKET Packet
+ )
+
+/*++
+
+Routine Description:
+
+ The IbmtokSend request instructs a MAC to transmit a packet through
+ the adapter onto the medium.
+
+Arguments:
+
+ MacBindingHandle - The context value returned by the MAC when the
+ adapter was opened. In reality, it is a pointer to IBMTOK_OPEN.
+
+ Packet - A pointer to a descriptor for the packet that is to be
+ transmitted.
+
+Return Value:
+
+ The function value is the status of the operation.
+
+
+--*/
+
+{
+
+ //
+ // Holds the status that should be returned to the caller.
+ //
+ NDIS_STATUS StatusToReturn = NDIS_STATUS_PENDING;
+
+ //
+ // Pointer to the adapter.
+ //
+ PIBMTOK_ADAPTER Adapter;
+
+ ULONG PacketLength;
+
+ Adapter = PIBMTOK_ADAPTER_FROM_BINDING_HANDLE(MacBindingHandle);
+
+ NdisQueryPacket(
+ Packet,
+ NULL,
+ NULL,
+ NULL,
+ &PacketLength
+ );
+
+ //
+ // Check that the packet will go on the wire. Note: I do not
+ // check that we have enough receive space to receive a packet
+ // of this size -- it is up to a protocol to work this out.
+ //
+
+ if ((PacketLength < 14) ||
+ (PacketLength > Adapter->MaxTransmittablePacket)) {
+
+ return(NDIS_STATUS_INVALID_PACKET);
+
+ }
+
+ NdisAcquireSpinLock(&Adapter->Lock);
+
+ Adapter->References++;
+
+ if (Adapter->Unplugged) {
+
+ StatusToReturn = NDIS_STATUS_DEVICE_FAILED;
+
+ } else if (!Adapter->NotAcceptingRequests) {
+
+ PIBMTOK_OPEN Open;
+ PIBMTOK_RESERVED Reserved = PIBMTOK_RESERVED_FROM_PACKET(Packet);
+
+ Open = PIBMTOK_OPEN_FROM_BINDING_HANDLE(MacBindingHandle);
+
+ if (!Open->BindingShuttingDown) {
+
+ //
+ // We do not have to increment the open count. Since we hold
+ // the lock for the entire function we cannot have the open
+ // removed out from under us.
+ //
+
+ //
+ // NOTE NOTE NOTE !!!!!!
+ //
+ // There is an assumption in the code that no pointer
+ // (which are really handles) to an ndis packet will have
+ // its low bit set. (Always have even byte alignment.)
+ //
+
+ ASSERT(!((UINT)Packet & 1));
+
+ //
+ // ALL packets go on the wire (loopback is done
+ // by the card).
+ //
+#ifdef CHECK_DUP_SENDS
+ IbmtokAddPacketToList(Adapter, Packet);
+#endif
+
+ Reserved->MacBindingHandle = MacBindingHandle;
+ Reserved->Packet = Packet;
+
+ if (Adapter->FirstTransmit == NULL) {
+
+ Adapter->FirstTransmit = Packet;
+
+ } else {
+
+ PIBMTOK_RESERVED_FROM_PACKET(Adapter->LastTransmit)->Next = Packet;
+
+ }
+
+ Adapter->LastTransmit = Packet;
+
+ Reserved->Next = NULL;
+
+ //
+ // Increment the reference on the open since it
+ // will be leaving this packet around on the transmit
+ // queues.
+ //
+
+ Open->References++;
+
+ //
+ // This will send the transmit SRB command
+ // if the SRB is available.
+ //
+
+ IbmtokProcessSrbRequests(
+ Adapter
+ );
+
+ } else {
+
+ StatusToReturn = NDIS_STATUS_CLOSING;
+
+ }
+
+ } else {
+
+ if (Adapter->ResetInProgress) {
+
+ StatusToReturn = NDIS_STATUS_RESET_IN_PROGRESS;
+
+ } else if (Adapter->AdapterNotOpen) {
+
+ StatusToReturn = NDIS_STATUS_FAILURE;
+
+ } else {
+
+ NdisWriteErrorLogEntry(
+ Adapter->NdisAdapterHandle,
+ NDIS_ERROR_CODE_DRIVER_FAILURE,
+ 2,
+ IBMTOK_ERRMSG_INVALID_STATE,
+ 2
+ );
+
+ }
+
+ }
+
+
+ //
+ // This macro assumes it is called with the lock held,
+ // and releases it.
+ //
+
+ IBMTOK_DO_DEFERRED(Adapter);
+ return StatusToReturn;
+}
+
diff --git a/private/ntos/ndis/ibmtok/sources b/private/ntos/ndis/ibmtok/sources
new file mode 100644
index 000000000..1ee4f3023
--- /dev/null
+++ b/private/ntos/ndis/ibmtok/sources
@@ -0,0 +1,48 @@
+!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
+
+NOTE: Commented description of this file is in \nt\bak\bin\sources.tpl
+
+!ENDIF
+
+MAJORCOMP=ntos
+MINORCOMP=ndis2
+
+TARGETNAME=ibmtok
+TARGETPATH=\nt\public\sdk\lib
+TARGETTYPE=DRIVER
+
+C_DEFINES=$(C_DEFINES)
+
+TARGETLIBS=$(BASEDIR)\public\sdk\lib\*\ndis.lib
+
+INCLUDES=..\inc;..\..\inc
+
+SOURCES=ibmtok.c \
+ interrup.c \
+ send.c \
+ packet.c \
+ transfer.c \
+ ibmtok.rc
+
+RELATIVE_DEPTH=..\..
+
+MSC_WARNING_LEVEL=/W3 /WX
+
diff --git a/private/ntos/ndis/ibmtok/tokhrd.h b/private/ntos/ndis/ibmtok/tokhrd.h
new file mode 100644
index 000000000..ab0721177
--- /dev/null
+++ b/private/ntos/ndis/ibmtok/tokhrd.h
@@ -0,0 +1,667 @@
+/*++
+
+Copyright (c) 1990 Microsoft Corporation
+
+Module Name:
+
+ tokhrd.h
+
+Abstract:
+
+ The hardware-related definitions for the IBMTOK drivers.
+
+
+Author:
+
+ Anthony V. Ercolano (tonye) creation-date 19-Jun-1990
+ Adam Barr (adamba) 18-Feb-1991
+
+Environment:
+
+ Architecturally, there is an assumption in this driver that we are
+ on a little endian machine.
+
+Notes:
+
+ optional-notes
+
+Revision History:
+
+ Sean Selitrennikoff - 9/??/91
+ Added/Changed definitions to allow for Microchannel cards too.
+
+
+--*/
+
+#ifndef _IBMTOKHARDWARE_
+#define _IBMTOKHARDWARE_
+
+//
+// Types of adapters this driver can work with
+//
+#define IBM_TOKEN_RING_PCMCIA 1
+
+//
+// Initialization Status Flag Bit Settings
+//
+
+#define RINGSPEEDLISTEN 0x40
+
+//
+// Token-Ring Controller Configuration Register control bits
+// Used by IBM_TOKEN_RING_16_4_CREDIT_CARD_ADAPTER
+//
+// #define DEFAULT_MMIO 0xD4000
+// #define DEFAULT_RAM 0xD6
+#define DEFAULT_MMIO 0xC2000
+#define DEFAULT_RAM 0xD0
+
+#define SHARED_RAM_64K 0xC
+#define SHARED_RAM_32K 0x8
+#define SHARED_RAM_16K 0x4
+#define SHARED_RAM_8K 0x0
+
+#define RING_SPEED_16_MPS 0x2
+#define RING_SPEED_4_MPS 0x0
+
+#define PRIMARY 0x0
+#define ALTERNATE 0x1
+
+#define DEFAULT_NIBBLE_2 0x6
+
+#define NIBBLE_0 0x00
+#define NIBBLE_1 0x10
+#define NIBBLE_2 0x20
+#define NIBBLE_3 0x30
+#define RELEASE_TR_CONTROLLER 0x40
+
+
+//
+// IBM Token Ring Adapter IDs
+//
+
+#define IBMTOK1_ADAPTER_ID 0xE000
+#define IBMTOK2_ADAPTER_ID 0xE001
+
+//
+// Start of I/O ports based on which adapter it is.
+//
+
+#define PRIMARY_ADAPTER_OFFSET 0xa20
+#define ALTERNATE_ADAPTER_OFFSET 0xa24
+
+//
+// Offsets from above of the actual ports used.
+//
+
+#define SWITCH_READ_1 0x000
+#define RESET_LATCH 0x001
+#define SWITCH_READ_2 0x002
+#define RESET_RELEASE 0x002
+#define INTERRUPT_RELEASE_ISA_ONLY 0x003
+
+
+//
+// Registers in the MMIO. These are in the Attachment
+// Control Area, which starts at offset 0x1e00 of the ACA.
+//
+
+#define RRR_LOW 0x1e00
+#define RRR_HIGH 0x1e01
+#define WRBR_LOW 0x1e02
+#define WRBR_HIGH 0x1e03
+#define ISRP_LOW 0x1e08
+#define ISRP_LOW_RESET 0x1e28
+#define ISRP_LOW_SET 0x1e48
+#define ISRP_HIGH 0x1e09
+#define ISRP_HIGH_RESET 0x1e29
+#define ISRA_LOW 0x1e0a
+#define ISRA_HIGH 0x1e0b
+#define ISRA_HIGH_SET 0x1e4b
+#define TCR_LOW 0x1e0c
+#define TCR_HIGH 0x1e0d
+#define TVR_LOW 0x1e0e
+#define TVR_HIGH 0x1e0f
+#define SRPR_LOW 0x1e18
+#define SRPR_HIGH 0x1e19
+
+
+//
+// These are registers in the AIP (aka the ID PROM),
+// which starts at offset 0x1f00 of the ACA.
+//
+
+#define CHANNEL_IDENTIFIER 0x1f30
+#define TOTAL_ADAPTER_RAM 0x1fa6
+#define SHARED_RAM_PAGING 0x1fa8
+#define MAX_4_MBPS_DHB 0x1faa
+#define MAX_16_MBPS_DHB 0x1fac
+
+
+//
+// Bits in the ISRA Low (even) register.
+//
+
+#define ISRA_LOW_TIMER_INTERRUPT 0x40
+#define ISRA_LOW_INTERRUPT_MASK 0x01
+
+//
+// Bits in the ISRA High (odd) register.
+//
+
+#define ISRA_HIGH_COMMAND_IN_SRB 0x20
+#define ISRA_HIGH_RESPONSE_IN_ASB 0x10
+#define ISRA_HIGH_SRB_FREE_REQUEST 0x08
+#define ISRA_HIGH_ASB_FREE_REQUEST 0x04
+#define ISRA_HIGH_ARB_FREE 0x02
+#define ISRA_HIGH_SSB_FREE 0x01
+
+//
+// Bits in the ISRP Low (even) register.
+//
+
+#define ISRP_LOW_NO_CHANNEL_CHECK 0x80
+#define ISRP_LOW_INTERRUPT_ENABLE 0x40
+
+//
+// Bits in the ISRP High (odd) register.
+//
+
+#define ISRP_HIGH_ADAPTER_CHECK 0x40
+#define ISRP_HIGH_SRB_RESPONSE 0x20
+#define ISRP_HIGH_ASB_FREE 0x10
+#define ISRP_HIGH_ARB_COMMAND 0x08
+#define ISRP_HIGH_SSB_RESPONSE 0x04
+
+//
+// Bits in the TCR Low (even) register.
+//
+
+#define TCR_LOW_INTERRUPT_MASK 0x80
+#define TCR_LOW_RELOAD_TIMER 0x40
+#define TCR_LOW_COUNTER_ENABLE 0x20
+
+
+#define WRITE_ADAPTER_REGISTER(a, r, v) \
+ NdisWriteRegisterUchar((PUCHAR)((a)->MmioRegion + (r)), (UCHAR)(v))
+
+#define READ_ADAPTER_REGISTER(a, r, v) \
+ NdisReadRegisterUchar((PUCHAR)(a)->MmioRegion + (r), (PUCHAR)(v))
+
+
+#define WRITE_ADAPTER_PORT(a, p, v) \
+ NdisWritePortUchar((a)->NdisAdapterHandle, (ULONG)((a)->IbmtokPortAddress + (p)), (UCHAR)(v))
+
+#define READ_ADAPTER_PORT(a, p, v) \
+ NdisReadPortUchar((a)->NdisAdapterHandle, (ULONG)(a)->IbmtokPortAddress + (p), (PUCHAR)(v))
+
+
+
+//
+// An IBMSHORT is a short that is in IBM byte ordering,
+// with the high and low bytes reversed.
+//
+
+typedef USHORT IBMSHORT;
+
+
+//
+// NOTE: These are dangerous because s appears twice in them.
+//
+
+#define READ_IBMSHORT(s) (USHORT)((((PUCHAR)&s)[0] << 8) + ((PUCHAR)&s)[1])
+#define WRITE_IBMSHORT(s, val) {\
+ USHORT _tmp; \
+ _tmp = (USHORT)((((val) >> 8) & 0xff) | (((val) & 0xff) << 8)); \
+ NdisWriteRegisterUshort((PUSHORT)&s, _tmp); \
+}
+#define USHORT_TO_IBMSHORT(val) (IBMSHORT)((((val) >> 8) & 0xff) | \
+ (((val) & 0xff) << 8))
+#define IBMSHORT_TO_USHORT(val) (USHORT)((((val) >> 8) & 0xff) | \
+ (((val) & 0xff) << 8))
+
+
+//
+// An SRAM_PTR is a pointer into the Shared RAM on the adapter.
+// It uses the IBM byte ordering.
+//
+
+typedef IBMSHORT SRAM_PTR;
+
+#define NULL_SRAM_PTR ((SRAM_PTR)0x0000)
+
+#define SRAM_PTR_TO_PVOID(a, p) \
+ ((PVOID)((a)->SharedRam + IBMSHORT_TO_USHORT(p)))
+
+#define SHARED_RAM_ADDRESS(a, p) \
+ ((PVOID)((a)->SharedRam + ((ULONG)(p))))
+
+
+//
+// Macros to deal with the frame status field.
+//
+
+#define GET_FRAME_STATUS_HIGH_AC(Fs) ((UCHAR)(((Fs) & 0xc0) >> 6))
+#define GET_FRAME_STATUS_LOW_AC(Fs) ((UCHAR)(((Fs) & 0x0c) >> 2))
+
+#define AC_NOT_RECOGNIZED 0x00
+#define AC_INVALID 0x01
+#define AC_NOT_COPIED 0x10
+#define AC_COPIED 0x11
+
+
+//
+// Some adapters have to have the upper section of the
+// Shared RAM zeroed out after initialization.
+//
+
+#define SHARED_RAM_ZERO_OFFSET ((PVOID)0xfe00)
+#define SHARED_RAM_ZERO_LENGTH 0x0200
+
+
+//
+// The highest command correlator used by the adapter
+// transmit logic.
+//
+
+#define MAX_COMMAND_CORRELATOR 128
+
+
+//
+// This macro is used to set up the SRPR depending on
+// the given address (should only be called if it is
+// known that the adapter supports Shared RAM Paging!!).
+//
+
+#define SETUP_SRPR(Adapter, Address) \
+ WRITE_ADAPTER_REGISTER((Adapter), SRPR_LOW, ((ULONG)(Address) >> 14))
+
+
+//
+// This macro retrieves the part of an address that
+// is used once SETUP_SRPR has been called.
+//
+
+#define SHARED_RAM_LOW_BITS(Address) \
+ ((ULONG)(Address) & 0x3fff)
+
+
+//
+// This macro determines if an address will fit on a
+// single Shared RAM page. It makes sure that the beginning
+// and end of the sequence have the same high two bits.
+//
+
+#define SINGLE_SHARED_RAM_PAGE(Address, Length) \
+ (((ULONG)(Address) & 0xc000) == (((ULONG)(Address)+(Length)-1) & 0xc000))
+
+
+
+//
+// Various structures which are read after the adapter
+// is reset.
+//
+
+typedef struct _ADAPTER_ADDRESS {
+ UCHAR NodeAddress[6];
+ UCHAR GroupAddress[4];
+ UCHAR FunctionalAddress[4];
+} ADAPTER_ADDRESS, * PADAPTER_ADDRESS;
+
+
+typedef struct _ADAPTER_PARAMETERS {
+ UCHAR PhysicalAddress[4];
+ UCHAR NaunNodeAddress[6];
+ UCHAR NaunPhysicalAddress[4];
+ UCHAR LastPoolAddress[6];
+ UCHAR Reserved1[2];
+ IBMSHORT TransmitAccessPriority;
+ IBMSHORT SourceClassAuthorization;
+ IBMSHORT LastAttentionCode;
+ UCHAR LastSourceAddress[6];
+ IBMSHORT LastBeaconType;
+ IBMSHORT LastMajorVector;
+ IBMSHORT RingStatus;
+ IBMSHORT SoftErrorTimer;
+ IBMSHORT FrontEndError;
+ IBMSHORT LocalRingNumber;
+ IBMSHORT MonitorErrorCode;
+ IBMSHORT BeaconTransmitType;
+ IBMSHORT BeaconReceiveType;
+ IBMSHORT FrameCorrelator;
+ UCHAR BeaconNaun[6];
+ UCHAR Reserved2[4];
+ UCHAR BeaconPhysicalAddress[4];
+} ADAPTER_PARAMETERS, * PADAPTER_PARAMETERS;
+
+
+typedef struct _SRB_BRING_UP_RESULT {
+ UCHAR Command;
+ UCHAR InitStatus;
+ UCHAR Reserved1[4];
+ IBMSHORT ReturnCode;
+ SRAM_PTR EncodedAddressPointer;
+ SRAM_PTR LevelAddressPointer;
+ SRAM_PTR AdapterAddressPointer; // points to ADAPTER_ADDRESS
+ SRAM_PTR ParameterAddressPointer; // points to ADAPTER_PARAMETERS
+ SRAM_PTR MacBufferPointer;
+} SRB_BRING_UP_RESULT, * PSRB_BRING_UP_RESULT;
+
+
+
+
+//
+// Structure of the System Request Block as defined
+// for various commands.
+//
+
+typedef struct _SRB_GENERIC {
+ UCHAR Command;
+ UCHAR Reserved1[1];
+ UCHAR ReturnCode;
+} SRB_GENERIC, * PSRB_GENERIC;
+
+
+//
+// Values for the SRB Command field.
+//
+
+#define SRB_CMD_CLOSE_ADAPTER 0x04
+#define SRB_CMD_INTERRUPT 0x00
+#define SRB_CMD_MODIFY_OPEN_PARMS 0x01
+#define SRB_CMD_OPEN_ADAPTER 0x03
+#define SRB_CMD_CLOSE_ADAPTER 0x04
+#define SRB_CMD_READ_LOG 0x08
+#define SRB_CMD_RESTORE_OPEN_PARMS 0x02
+#define SRB_CMD_SET_FUNCTIONAL_ADDRESS 0x07
+#define SRB_CMD_SET_GROUP_ADDRESS 0x06
+#define SRB_CMD_TRANSMIT_DIR_FRAME 0x0a
+#define SRB_CMD_DLC_STATISTICS 0x1e
+
+
+typedef struct _SRB_OPEN_ADAPTER {
+ UCHAR Command;
+ UCHAR Reserved1[7];
+ IBMSHORT OpenOptions;
+ UCHAR NodeAddress[6];
+ UCHAR GroupAddress[4];
+ UCHAR FunctionalAddress[4];
+ IBMSHORT ReceiveBufferNum;
+ IBMSHORT ReceiveBufferLen;
+ IBMSHORT TransmitBufferLen;
+ UCHAR TransmitBufferNum;
+ UCHAR Reserved2[1];
+ UCHAR DlcValues[10];
+ UCHAR ProductId[18];
+} SRB_OPEN_ADAPTER, * PSRB_OPEN_ADAPTER;
+
+
+typedef struct _SRB_CLOSE_ADAPTER {
+ UCHAR Command;
+ UCHAR Reserved1;
+ UCHAR ReturnCode;
+} SRB_CLOSE_ADAPTER, * PSRB_CLOSE_ADAPTER;
+
+
+//
+// Bit values for the OpenOptions field (these are
+// reversed to be in IBMSHORT format).
+//
+
+#define OPEN_LOOPBACK 0x0080
+#define OPEN_DISABLE_HARD_ERROR 0x0040
+#define OPEN_DISABLE_SOFT_ERROR 0x0020
+#define OPEN_PASS_ADAPTER_MAC 0x0010
+#define OPEN_PASS_ATTENTION_MAC 0x0008
+#define OPEN_CONTENDER 0x0001
+#define OPEN_PASS_BEACON_MAC 0x8000
+#define OPEN_MODIFIED_TOKEN_RELEASE 0x1000
+#define OPEN_REMOTE_PROGRAM_LOAD 0x2000
+
+
+typedef struct _SRB_OPEN_RESPONSE {
+ UCHAR Command;
+ UCHAR Reserved1[1];
+ UCHAR ReturnCode;
+ UCHAR Reserved2[3];
+ IBMSHORT ErrorCode;
+ SRAM_PTR AsbPointer;
+ SRAM_PTR SrbPointer;
+ SRAM_PTR ArbPointer;
+ SRAM_PTR SsbPointer;
+} SRB_OPEN_RESPONSE, * PSRB_OPEN_RESPONSE;
+
+
+typedef struct _SRB_TRANSMIT_DIR_FRAME {
+ UCHAR Command;
+ UCHAR CommandCorrelator;
+ UCHAR ReturnCode;
+ UCHAR Reserved1[1];
+ IBMSHORT StationId;
+} SRB_TRANSMIT_DIR_FRAME, * PSRB_TRANSMIT_DIR_FRAME;
+
+
+typedef struct _SRB_SET_FUNCT_ADDRESS {
+ UCHAR Command;
+ UCHAR Reserved1[1];
+ UCHAR ReturnCode;
+ UCHAR Reserved2[3];
+ //
+ // Making this a TR_FUNCTIONAL_ADDRESS would cause
+ // the compiler to insert two bytes for alignment.
+ //
+ UCHAR FunctionalAddress[4];
+} SRB_SET_FUNCT_ADDRESS, * PSRB_SET_FUNCT_ADDRESS;
+
+
+typedef struct _SRB_SET_GROUP_ADDRESS {
+ UCHAR Command;
+ UCHAR Reserved1[1];
+ UCHAR ReturnCode;
+ UCHAR Reserved2[3];
+ //
+ // Making this a TR_FUNCTIONAL_ADDRESS would cause
+ // the compiler to insert two bytes for alignment.
+ //
+ UCHAR GroupAddress[4];
+} SRB_SET_GROUP_ADDRESS, * PSRB_SET_GROUP_ADDRESS;
+
+
+typedef struct _SRB_INTERRUPT {
+ UCHAR Command;
+ UCHAR Reserved1[1];
+ UCHAR ReturnCode;
+} SRB_INTERRUPT, * PSRB_INTERRUPT;
+
+
+typedef struct _SRB_READ_LOG {
+ UCHAR Command;
+ UCHAR Reserved1[1];
+ UCHAR ReturnCode;
+ UCHAR Reserved2[3];
+ UCHAR LineErrors;
+ UCHAR InternalErrors;
+ UCHAR BurstErrors;
+ UCHAR AcErrors;
+ UCHAR AbortDelimeters;
+ UCHAR Reserved3[1];
+ UCHAR LostFrames;
+ UCHAR ReceiveCongestionCount;
+ UCHAR FrameCopiedErrors;
+ UCHAR FrequencyErrors;
+ UCHAR TokenErrors;
+ UCHAR Reserved4[3];
+} SRB_READ_LOG, * PSRB_READ_LOG;
+
+
+typedef struct _SRB_DLC_STATS{
+ UCHAR Command;
+ UCHAR Reserved1;
+ UCHAR ReturnCode;
+ UCHAR Reserved2;
+ IBMSHORT StationId;
+ IBMSHORT CountersOffset;
+ IBMSHORT HeaderAddr;
+ UCHAR ResetOption;
+}SRB_DLC_STATS, *PSRB_DLC_STATS;
+
+
+typedef struct _DLC_COUNTERS{
+ IBMSHORT TransmitCount;
+ IBMSHORT ReceiveCount;
+ UCHAR TransmitErrors;
+ UCHAR ReceiveErrors;
+ IBMSHORT T1Expires;
+ UCHAR ReceivedCommand;
+ UCHAR SentCommand;
+ UCHAR PrimaryState;
+ UCHAR SecondaryState;
+ UCHAR SendState;
+ UCHAR ReceiveState;
+ UCHAR LastReceivedNr;
+}DLC_COUNTERS, *PDLC_COUNTERS;
+
+
+
+
+//
+// Structure of the Adapter Request Block as defined
+// for various commands.
+//
+
+typedef struct _ARB_GENERIC {
+ UCHAR Command;
+} ARB_GENERIC, * PARB_GENERIC;
+
+
+//
+// Values for the ARB Command field.
+//
+
+#define ARB_CMD_DLC_STATUS 0x83
+#define ARB_CMD_RECEIVED_DATA 0x81
+#define ARB_CMD_RING_STATUS_CHANGE 0x84
+#define ARB_CMD_TRANSMIT_DATA_REQUEST 0x82
+
+
+typedef struct _ARB_RING_STATUS_CHANGE {
+ UCHAR Command;
+ UCHAR Reserved1[5];
+ IBMSHORT NetworkStatus;
+} ARB_RING_STATUS_CHANGE, * PARB_RING_STATUS_CHANGE;
+
+
+typedef struct _ARB_DLC_STATUS {
+ UCHAR Command;
+ UCHAR Reserved1[3];
+ IBMSHORT StationId;
+ IBMSHORT Status;
+ UCHAR FrmrData[5];
+ UCHAR AccessPriority;
+ UCHAR RemoteAddress[6];
+ UCHAR RemoteRsapValue;
+} ARB_DLC_STATUS, * PARB_DLC_STATUS;
+
+
+typedef struct _ARB_TRANSMIT_DATA_REQUEST {
+ UCHAR Command;
+ UCHAR CommandCorrelator;
+ UCHAR Reserved1[2];
+ IBMSHORT StationId;
+ SRAM_PTR DhbPointer;
+} ARB_TRANSMIT_DATA_REQUEST, * PARB_TRANSMIT_DATA_REQUEST;
+
+
+typedef struct _ARB_RECEIVED_DATA {
+ UCHAR Command;
+ UCHAR Reserved1[3];
+ IBMSHORT StationId;
+ SRAM_PTR ReceiveBuffer; // points to a RECEIVE_BUFFER
+ UCHAR LanHeaderLength;
+ UCHAR DlcHeaderLength;
+ IBMSHORT FrameLength;
+ UCHAR MessageType;
+} ARB_RECEIVED_DATA, * PARB_RECEIVED_DATA;
+
+
+typedef struct _RECEIVE_BUFFER {
+ //
+ // Leave out the first two reserved bytes.
+ //
+ SRAM_PTR NextBuffer;
+ UCHAR Reserved2[1];
+ UCHAR ReceiveFs;
+ IBMSHORT BufferLength;
+ UCHAR FrameData[1];
+} RECEIVE_BUFFER, * PRECEIVE_BUFFER;
+
+
+
+
+//
+// Structure of the Adapter Status Block as defined
+// for various commands.
+//
+
+typedef struct _ASB_GENERIC {
+ UCHAR Command;
+ UCHAR Reserved1[1];
+ UCHAR ReturnCode;
+} ASB_GENERIC, * PASB_GENERIC;
+
+
+//
+// The ASB Command field takes the same values as the
+// ARB Command field.
+//
+
+typedef struct _ASB_TRANSMIT_DATA_STATUS {
+ UCHAR Command;
+ UCHAR CommandCorrelator;
+ UCHAR ReturnCode;
+ UCHAR Reserved1[1];
+ IBMSHORT StationId;
+ IBMSHORT FrameLength;
+ UCHAR Reserved2[2];
+} ASB_TRANSMIT_DATA_STATUS, * PASB_TRANSMIT_DATA_STATUS;
+
+
+typedef struct _ASB_RECEIVED_DATA_STATUS {
+ UCHAR Command;
+ UCHAR Reserved1[1];
+ UCHAR ReturnCode;
+ UCHAR Reserved2[1];
+ IBMSHORT StationId;
+ SRAM_PTR ReceiveBuffer;
+} ASB_RECEIVED_DATA_STATUS, * PASB_RECEIVED_DATA_STATUS;
+
+
+
+
+//
+// Structure of the System Status Block as defined
+// for various commands.
+//
+
+typedef struct _SSB_GENERIC {
+ UCHAR Command;
+} SSB_GENERIC, * PSSB_GENERIC;
+
+
+//
+// The SSB Command field takes the same values as the
+// SRB Command field.
+//
+
+typedef struct _SSB_TRANSMIT_COMPLETE {
+ UCHAR Command;
+ UCHAR CommandCorrelator;
+ UCHAR ReturnCode;
+ UCHAR Reserved1[1];
+ IBMSHORT StationId;
+ UCHAR ErrorFrameStatus;
+} SSB_TRANSMIT_COMPLETE, * PSSB_TRANSMIT_COMPLETE;
+
+
+
+#endif // _IBMTOKHARDWARE_
diff --git a/private/ntos/ndis/ibmtok/toksft.h b/private/ntos/ndis/ibmtok/toksft.h
new file mode 100644
index 000000000..5f120c1d9
--- /dev/null
+++ b/private/ntos/ndis/ibmtok/toksft.h
@@ -0,0 +1,1373 @@
+/*++
+
+Copyright (c) 1990 Microsoft Corporation
+
+Module Name:
+
+ toksft.h
+
+Abstract:
+
+ The main header for a IBMTOK NDIS driver.
+
+ The overall structure is taken from the Lance driver
+ by Tony Ercolano.
+
+Author:
+
+ Anthony V. Ercolano (tonye) creation-date 19-Jun-1990
+ Adam Barr (adamba) 20-Nov-1990
+
+Environment:
+
+ Architecturally, there is an assumption in this driver that we are
+ on a little endian machine.
+
+Notes:
+
+ optional-notes
+
+Revision History:
+
+
+--*/
+
+#ifndef _IBMTOKSFT_
+#define _IBMTOKSFT_
+
+
+#define IBMTOK_NDIS_MAJOR_VERSION 3
+#define IBMTOK_NDIS_MINOR_VERSION 0
+
+#if DBG
+#define LOG 1
+#else
+#define LOG 0
+#endif
+
+#if LOG
+
+//
+// Place in the circular buffer.
+//
+extern UCHAR IbmtokLogPlace;
+
+//
+// Circular buffer for storing log information.
+//
+extern UCHAR IbmtokLog[];
+
+#define IF_LOG(A) {IbmtokLog[IbmtokLogPlace] = (A); \
+ IbmtokLog[(IbmtokLogPlace+3) % 255] = '.'; \
+ IbmtokLogPlace = (IbmtokLogPlace+1) % 255; }
+
+#else
+
+#define IF_LOG(A)
+
+#endif
+
+extern const NDIS_PHYSICAL_ADDRESS HighestAcceptableMax;
+
+#define IBMTOK_ALLOC_PHYS(pp,s) NdisAllocateMemory((PVOID *)(pp),(s),0,HighestAcceptableMax)
+#define IBMTOK_FREE_PHYS(p,s) NdisFreeMemory((PVOID)(p),(s),0)
+#define IBMTOK_MOVE_MEMORY(Destination,Source,Length) NdisMoveMemory((PVOID)(Destination),(PVOID)(Source),Length)
+#define IBMTOK_ZERO_MEMORY(Destination,Length) NdisZeroMemory((PVOID)(Destination),Length)
+#define IBMTOK_MOVE_TO_MAPPED_MEMORY(Destination,Source,Length) NdisMoveToMappedMemory((PVOID)(Destination),(PVOID)(Source),Length)
+#define IBMTOK_MOVE_FROM_MAPPED_MEMORY(Destination,Source,Length) NdisMoveFromMappedMemory((PVOID)(Destination),(PVOID)(Source),Length)
+#define IBMTOK_ZERO_MAPPED_MEMORY(Destination,Length) NdisZeroMappedMemory((PVOID)(Destination),Length)
+#define IBMTOK_STORE_ULONG(Destination,Source)\
+{\
+ PUCHAR _D = (PUCHAR)(Destination);\
+ ULONG _S = (ULONG)(Source);\
+ _D[0] = (UCHAR)(_S >> 24);\
+ _D[1] = (UCHAR)(_S >> 16);\
+ _D[2] = (UCHAR)(_S >> 8);\
+ _D[3] = (UCHAR)(_S);\
+}
+
+
+typedef struct _IBMTOK_MAC {
+
+ //
+ // The handle returned by NdisInitializeWrapper.
+ //
+
+ NDIS_HANDLE NdisWrapperHandle;
+
+ //
+ // The handle returned by NdisRegisterMac.
+ //
+
+ NDIS_HANDLE NdisMacHandle;
+
+} IBMTOK_MAC, *PIBMTOK_MAC;
+
+
+
+//
+// This record type is inserted into the MacReserved portion
+// of the packet header when the packet is going through the
+// staged allocation of buffer space prior to the actual send.
+//
+typedef struct _IBMTOK_RESERVED {
+
+ //
+ // Points to the next packet in the chain of queued packets
+ // waiting for the SRB or the ASB.
+ //
+ // The packet will start out on the Transmit queue,
+ // then move to TransmittingPacket when its transmit is
+ // in the SRB. When the correlator is assigned it is placed
+ // in CorrelatorArray (where the Next field is not used),
+ // and at that time may also be in WaitingForAsb if it
+ // needs the ASB to acknowledge the copying down of the
+ // transmit data. Packets are completed out of the
+ // CorrelatorArray.
+ //
+ //
+ PNDIS_PACKET Next;
+
+ //
+ // This field holds the binding handle of the open binding
+ // that submitted this packet for send.
+ //
+ NDIS_HANDLE MacBindingHandle;
+
+ //
+ // This field holds the pointer to the packet so that when
+ // the send finnaly completes it can be used to indicate to
+ // the protocol.
+ //
+ PNDIS_PACKET Packet;
+
+ //
+ // TRUE if a command correlator has been assigned for this
+ // packet.
+ //
+ BOOLEAN CorrelatorAssigned;
+
+ //
+ // The value of the adapter-assigned command correlator.
+ //
+ UCHAR CommandCorrelator;
+
+} IBMTOK_RESERVED,*PIBMTOK_RESERVED;
+
+
+//
+// This macro will return a pointer to the reserved portion
+// of a packet given a pointer to a packet.
+//
+#define PIBMTOK_RESERVED_FROM_PACKET(Packet) \
+ ((PIBMTOK_RESERVED)((PVOID)((Packet)->MacReserved)))
+
+
+
+//
+// This structure is inserted into the MacReserved section of the
+// NDIS_REQUEST for operations that must pend. Note: the sizeof
+// this structure must be less than or equal to 16 bytes.
+//
+// The flags are broken down as follows....
+//
+// Type == IBMTOK_PEND_MAC for requests submitted by the MAC to clear card errors.
+// ReadLogPending == TRUE if the MAC submitted a DIR.READ.LOG command.
+// ReadLogPending == FALSE if the MAC submitted DLC.STATISTICS.
+//
+// Type == IBMTOK_PEND_NDIS_CLOSE for request submitted thru Ndis.
+// Open, the open that submitted the Ndis request.
+//
+// Type == IBMTOK_PEND_NDIS_SET_FILTER for request submitted thru Ndis.
+// Open, the open that submitted the Ndis request.
+//
+// Type == IBMTOK_PEND_NDIS_STATISTICS for request submitted thru Ndis.
+// ReadLogPending, Boolean if the DIR.READ.LOG command was submitted.
+//
+//
+//
+typedef struct _IBMTOK_PEND_DATA{
+
+ //
+ // Points to the next request in the chain of queued packets
+ // waiting for the SRB.
+ //
+ // The request will start out on the PendQueue,
+ // then move to front of the queue when its operation is
+ // in the SRB.
+ //
+ //
+ struct _IBMTOK_PEND_DATA * Next;
+
+
+ union _COMMAND{
+
+ struct _MAC{
+
+ //
+ // Whether the statistics command was a
+ // DIR.READ.LOG or DLC.STATISTICS
+ //
+
+ UINT ReadLogPending;
+
+ }MAC;
+
+ union _NDIS{
+
+ struct _CLOSE{
+
+ //
+ // This field holds the open instance which submitted the
+ // request.
+ //
+
+ struct _IBMTOK_OPEN *Open;
+
+ //
+ // This field holds the new filter value.
+ //
+
+ UINT NewFilterValue;
+
+
+ }CLOSE;
+
+
+ struct _SET_FILTER{
+
+ //
+ // The first two fields of SET_FILTER and SET_ADDRESS need
+ // to align so that the processing in FinishSetOperation
+ // is easier.
+ //
+
+
+ //
+ // This field holds the open instance which submitted the
+ // request.
+ //
+
+ struct _IBMTOK_OPEN *Open;
+
+ //
+ // This field holds the new filter value.
+ //
+
+ UINT NewFilterValue;
+
+ }SET_FILTER;
+
+
+ struct _SET_ADDRESS{
+
+ //
+ // The first two fields of SET_FILTER and SET_ADDRESS need
+ // to align so that the processing in FinishSetOperation
+ // is easier.
+ //
+
+
+ //
+ // This field holds the open instance which submitted the
+ // request.
+ //
+
+ struct _IBMTOK_OPEN *Open;
+
+ //
+ // This field holds the new address value.
+ //
+
+ TR_FUNCTIONAL_ADDRESS NewAddressValue;
+
+ }SET_ADDRESS;
+
+
+ struct _STATISTICS{
+
+ //
+ // Pointer into NdisRequest at the New filter value.
+ //
+
+ BOOLEAN ReadLogPending;
+
+
+ }STATISTICS;
+
+ }NDIS;
+
+ }COMMAND;
+
+ //
+ // Buffer to fill in Reserved section so that the next field overlaps
+ // with the RequestType in the NdisRequest.
+ //
+
+ ULONG Buffer;
+
+
+ NDIS_REQUEST_TYPE RequestType;
+
+
+}IBMTOK_PEND_DATA, *PIBMTOK_PEND_DATA;
+
+//
+// This macro will return a pointer to the reserved area of
+// a PNDIS_REQUEST.
+//
+#define PIBMTOK_PEND_DATA_FROM_PNDIS_REQUEST(Request) \
+ ((PIBMTOK_PEND_DATA)((PVOID)((Request)->MacReserved)))
+
+//
+// This macros returns the enclosing NdisRequest.
+//
+#define PNDIS_REQUEST_FROM_PIBMTOK_PEND_DATA(PendOp)\
+ ((PNDIS_REQUEST)((PVOID)(PendOp)))
+
+//
+// Define Maximum number of bytes a protocol can read during a
+// receive data indication.
+//
+#define IBMTOK_MAX_LOOKAHEAD 240
+
+
+typedef struct _IBMTOK_ADAPTER {
+
+ //
+ // Holds the interrupt object for this adapter.
+ //
+ NDIS_INTERRUPT Interrupt;
+
+ //
+ // Flag to tell if the ISR removed the interrupt.
+ //
+ UCHAR ContinuousIsrs;
+
+ PVOID WakeUpDpc;
+ NDIS_TIMER WakeUpTimer;
+ BOOLEAN SendTimeout;
+ BOOLEAN RequestTimeout;
+ UCHAR WakeUpErrorCount;
+
+ //
+ // Defines whether the adapter is an ISA or PCMCIA adapter.
+ //
+ UINT CardType;
+
+ //
+ // Boolean to turn on/off early token release
+ //
+ BOOLEAN EarlyTokenRelease;
+
+ //
+ // Flag to indicate that the card initialized.
+ //
+ BOOLEAN BringUp;
+
+ //
+ // Spinlock for the interrupt.
+ //
+ NDIS_SPIN_LOCK InterruptLock;
+
+ //
+ // The interrupt level as read from the card.
+ //
+ UINT InterruptLevel;
+
+ //
+ // Is the adapter running at 16 Mbps (versus 4 Mbps).
+ //
+ BOOLEAN Running16Mbps;
+
+ //
+ // Is the adapter using the PC I/O Bus (versus MicroChannel).
+ //
+ BOOLEAN UsingPcIoBus;
+
+ //
+ // Does the upper 512 bytes of the shared RAM have to
+ // be zeroed after initialization.
+ //
+ BOOLEAN UpperSharedRamZero;
+
+ //
+ // Are we using Shared RAM paging.
+ //
+ BOOLEAN SharedRamPaging;
+
+ //
+ // The size of the RAM on the adapter.
+ //
+ ULONG TotalSharedRam;
+
+ //
+ // The amount of Shared RAM to be mapped in.
+ //
+ ULONG MappedSharedRam;
+
+ //
+ // The maximum size of a DHB at 4 Mbps.
+ //
+ USHORT Max4MbpsDhb;
+
+ //
+ // The maximum size of a DHB at 16 Mbps.
+ //
+ USHORT Max16MbpsDhb;
+
+ //
+ // Value of the RRR Low register (address of Shared Ram).
+ //
+ UCHAR RrrLowValue;
+
+// The following fields are accessed by the ISR and must be aligned to the
+// minimum granularity of the architecture on which it runs
+
+#if defined(_ALPHA_)
+
+ union {
+ UQUAD _ForceQuadwordAlignment;
+ struct {
+
+#endif // defined(_ALPHA_)
+
+ //
+ // These variables are used to hold bits stored in the ISR
+ // and read in the DPC.
+ //
+ UCHAR IsrpBits;
+
+ //
+ // These hold ISR bits whose processing is delayed because
+ // the adapter is not accepting requests.
+ //
+ UCHAR IsrpDeferredBits;
+
+ //
+ // Any Error conditions found in the IsrpLow register
+ //
+ UCHAR IsrpLowBits;
+
+#if defined(_ALPHA_)
+
+ };
+ };
+
+#endif // defined(_ALPHA_)
+
+// End of ISR access fields
+
+ //
+ // This boolean is used as a gate to ensure that only one thread
+ // of execution is actually processing SRB interrupts
+ //
+ BOOLEAN HandleSrbRunning;
+
+ //
+ // This boolean is used as a gate to ensure that only one thread
+ // of execution is actually processing SRB interrupts
+ //
+ BOOLEAN HandleArbRunning;
+
+ //
+ // The network address in use.
+ //
+ CHAR NetworkAddress[TR_LENGTH_OF_ADDRESS];
+
+ //
+ // The network address from the hardware.
+ //
+ CHAR PermanentNetworkAddress[TR_LENGTH_OF_ADDRESS];
+
+ //
+ // Pointer to the beginning of the IBMTOK ports.
+ //
+ ULONG IbmtokPortAddress;
+
+ //
+ // Keeps a reference count on the current number of uses of
+ // this adapter block. Uses is defined to be the number of
+ // routines currently within the "external" interface.
+ //
+ UINT References;
+
+ //
+ // List head for all open bindings for this adapter.
+ //
+ LIST_ENTRY OpenBindings;
+
+ //
+ // List head for all opens that had outstanding references
+ // when an attempt was made to close them.
+ //
+ LIST_ENTRY CloseList;
+
+ //
+ // List head for all opens that were attempted to be closed
+ // during a reset.
+ LIST_ENTRY CloseDuringResetList;
+
+ //
+ // Spinlock to protect fields in this structure..
+ //
+ NDIS_SPIN_LOCK Lock;
+
+ //
+ // Handle given by NDIS when the MAC registered itself.
+ //
+ NDIS_HANDLE NdisMacHandle;
+
+ //
+ // Handle given by NDIS when the adapter was registered.
+ //
+ NDIS_HANDLE NdisAdapterHandle;
+
+ //
+ // Pointer to the filter database for the MAC.
+ //
+ PTR_FILTER FilterDB;
+
+ //
+ // Holds queued Pending operations.
+ //
+ PIBMTOK_PEND_DATA PendQueue;
+
+ //
+ // Last pending operation on queue.
+ //
+ PIBMTOK_PEND_DATA EndOfPendQueue;
+
+ //
+ // Pointer to the pended operation that is currently executing.
+ //
+ PIBMTOK_PEND_DATA PendData;
+
+ //
+ // The current packet filter.
+ //
+ UINT CurrentPacketFilter;
+
+ //
+ // The old packet filter (in case of failure to set to a new filter).
+ //
+ UINT OldPacketFilter;
+
+ //
+ // The current functional address requested.
+ //
+ TR_FUNCTIONAL_ADDRESS CurrentFunctionalAddress;
+
+ //
+ // The functional address on the card (may differ
+ // from CurrentFunctionalAddress if ALL_MULTICAST
+ // is selected).
+ //
+ TR_FUNCTIONAL_ADDRESS CurrentCardFunctional;
+
+ //
+ // The current group address requested.
+ //
+ TR_FUNCTIONAL_ADDRESS CurrentGroupAddress;
+
+ //
+ // The group address on the card
+ //
+ TR_FUNCTIONAL_ADDRESS CurrentCardGroup;
+
+ //
+ // The address that the MMIO is mapped to.
+ //
+ PUCHAR MmioRegion;
+
+ //
+ // The address that the Shared RAM is mapped to.
+ //
+ PUCHAR SharedRam;
+
+ //
+ // Initial offset of WRB in Shared RAM (contains location
+ // of bring-up SRB).
+ //
+ USHORT InitialWrbOffset;
+
+ //
+ // Addresses of the Shared RAM structures.
+ //
+ PVOID SrbAddress;
+ PVOID SsbAddress;
+ PVOID ArbAddress;
+ PVOID AsbAddress;
+
+ //
+ // For Shared RAM Paging mode, the SRPR Low value needed
+ // to talk to each of the Shared RAM structures.
+ //
+ UCHAR SrbSrprLow;
+ UCHAR SsbSrprLow;
+ UCHAR ArbSrprLow;
+ UCHAR AsbSrprLow;
+
+ //
+ // Is the SRB available.
+ //
+ BOOLEAN SrbAvailable;
+
+ //
+ // Is the ASB available.
+ //
+ BOOLEAN AsbAvailable;
+
+ //
+ // The next correlator number which we think we should
+ // be completing the send for.
+ //
+ UCHAR NextCorrelatorToComplete;
+
+ //
+ // Points to the packet being transmitted if TransmitInSrb
+ // is TRUE.
+ //
+ PNDIS_PACKET TransmittingPacket;
+
+ //
+ // The receive buffer that is waiting for the ASB.
+ //
+ SRAM_PTR ReceiveWaitingForAsbList;
+
+ //
+ // A SRAM_PTR to the last receive buffer waiting for
+ // the ASB to indicate completion.
+ //
+ SRAM_PTR ReceiveWaitingForAsbEnd;
+
+
+ //
+ // The receive buffer that the transfer data should
+ // begin at (used during receive indications).
+ //
+ SRAM_PTR IndicatedReceiveBuffer;
+
+ //
+ // Length of the header for this received indication.
+ //
+ USHORT IndicatedHeaderLength;
+
+ //
+ // Should the ASB be used for a receive next.
+ //
+ BOOLEAN UseNextAsbForReceive;
+
+ //
+ // The number of transmit buffers.
+ //
+ USHORT NumberOfTransmitBuffers;
+
+ //
+ // The size of the transmit buffers.
+ //
+ USHORT TransmitBufferLength;
+
+ //
+ // The size of the maximum packet transmittable.
+ //
+ UINT MaxTransmittablePacket;
+
+ //
+ // The number of receive buffers.
+ //
+ USHORT NumberOfReceiveBuffers;
+
+ //
+ // The size of the receive buffers.
+ //
+ USHORT ReceiveBufferLength;
+
+ //
+ // Pointers to the first and last packets at a particular stage
+ // of allocation. All packets in transmit are linked
+ // via there next field.
+ //
+ // Can only be accessed when the adapter lock
+ // is held.
+ //
+ PNDIS_PACKET FirstTransmit;
+ PNDIS_PACKET LastTransmit;
+
+ PNDIS_PACKET FirstWaitingForAsb;
+ PNDIS_PACKET LastWaitingForAsb;
+
+ //
+ // Holds counter return by DLC.STATISTICS command.
+ //
+
+ UINT FramesTransmitted;
+ UINT FramesReceived;
+ UINT FrameTransmitErrors;
+ UINT FrameReceiveErrors;
+
+
+ //
+ // Holds counter returned by the DIR.READ.LOG command.
+ //
+ UINT LineErrors;
+ UINT InternalErrors;
+ UINT BurstErrors;
+ UINT AcErrors;
+ UINT AbortDelimeters;
+ UINT LostFrames;
+ UINT ReceiveCongestionCount;
+ UINT FrameCopiedErrors;
+ UINT FrequencyErrors;
+ UINT TokenErrors;
+
+ //
+ // Holds number of different types of RING.STATUS.CHANGE
+ // indications.
+ //
+ UINT SignalLoss;
+ UINT HardError;
+ UINT SoftError;
+ UINT TransmitBeacon;
+ UINT LobeWireFault;
+ UINT AutoRemovalError;
+ UINT RemoveReceived;
+ UINT CounterOverflow;
+ UINT SingleStation;
+ UINT RingRecovery;
+
+ //
+ // Last ring status indicated to protocols.
+ //
+ NDIS_STATUS LastNotifyStatus;
+
+ //
+ // Current state of the ring.
+ //
+ NDIS_802_5_RING_STATE CurrentRingState;
+
+ //
+ // Flag that when enabled lets routines know that a reset
+ // is in progress.
+ //
+ BOOLEAN ResetInProgress;
+
+ //
+ // The progress of the reset.
+ //
+ UINT CurrentResetStage;
+
+ //
+ // LookAhead information
+ //
+
+ ULONG LookAhead;
+
+ //
+ // TRUE when the ISR is expecting the next interrupt to
+ // be the one following adapter reset.
+ //
+ BOOLEAN ResetInterruptAllowed;
+
+ //
+ // TRUE when ISR gets the reset interrupt.
+ //
+ BOOLEAN ResetInterruptHasArrived;
+
+ //
+ // Pointer to the binding that initiated the reset. This
+ // will be null if the reset is initiated by the MAC itself.
+ //
+ struct _IBMTOK_OPEN *ResettingOpen;
+
+ //
+ // Will be true the first time that the hardware is initialized
+ // by the driver initialization.
+ //
+ BOOLEAN FirstInitialization;
+
+ //
+ // Will be true if the adapter is not yet opened.
+ //
+ BOOLEAN AdapterNotOpen;
+
+ //
+ // Will be true if the driver is being opened.
+ //
+ BOOLEAN OpenInProgress;
+
+ //
+ // TRUE if ResetInProgress or OpenInProgress is TRUE.
+ //
+ BOOLEAN NotAcceptingRequests;
+
+ //
+ // Last Error Code.
+ //
+ USHORT OpenErrorCode;
+
+ //
+ // TRUE if we get a ring status indicating the cable is unplugged.
+ //
+ BOOLEAN Unplugged;
+
+ //
+ // TRUE if we are doing a reset after the cable was unplugged
+ // to try to reenter the ring.
+ //
+ BOOLEAN UnpluggedResetInProgress;
+
+ //
+ // TRUE if we have gotten a lobe wire fault indication,
+ // meaning the adapter is closed.
+ //
+ BOOLEAN LobeWireFaultIndicated;
+
+ //
+ // TRUE if there exists an outstanding ASB_FREE_REQUEST
+ //
+ BOOLEAN OutstandingAsbFreeRequest;
+
+ //
+ // The command correlator array (put this at the end since
+ // it is so big).
+ //
+ PNDIS_PACKET CorrelatorArray[MAX_COMMAND_CORRELATOR];
+
+ //
+ // IBM_TOKEN_RING_16_4_CREDIT_CARD_ADAPTER specific
+ // keywords
+ //
+ UINT RingSpeed;
+ ULONG Ram;
+ UINT RamSize;
+ ULONG MmioAddress;
+ BOOLEAN InvalidValue;
+ BOOLEAN RingSpeedListen;
+ ULONG RingSpeedRetries;
+
+} IBMTOK_ADAPTER,*PIBMTOK_ADAPTER;
+
+
+//
+// Given a MacBindingHandle this macro returns a pointer to the
+// IBMTOK_ADAPTER.
+//
+#define PIBMTOK_ADAPTER_FROM_BINDING_HANDLE(Handle) \
+ (((PIBMTOK_OPEN)((PVOID)(Handle)))->OwningIbmtok)
+
+
+//
+// Given a MacContextHandle return the PIBMTOK_ADAPTER
+// it represents.
+//
+#define PIBMTOK_ADAPTER_FROM_CONTEXT_HANDLE(Handle) \
+ ((PIBMTOK_ADAPTER)((PVOID)(Handle)))
+
+
+//
+// Given a pointer to a IBMTOK_ADAPTER return the
+// proper MacContextHandle.
+//
+#define CONTEXT_HANDLE_FROM_PIBMTOK_ADAPTER(Ptr) \
+ ((NDIS_HANDLE)((PVOID)(Ptr)))
+
+
+//
+// One of these structures is created on each MacOpenAdapter.
+//
+typedef struct _IBMTOK_OPEN {
+
+ //
+ // Linking structure for all of the open bindings of a particular
+ // adapter.
+ //
+ LIST_ENTRY OpenList;
+
+ //
+ // The Adapter that requested this open binding.
+ //
+ PIBMTOK_ADAPTER OwningIbmtok;
+
+ //
+ // Handle of this adapter in the filter database.
+ //
+ NDIS_HANDLE NdisFilterHandle;
+
+ //
+ // Given by NDIS when the adapter was opened.
+ //
+ NDIS_HANDLE NdisBindingContext;
+
+ //
+ // Counter of all the different reasons that a open binding
+ // couldn't be closed. This would be incremented each time
+ // for:
+ //
+ // While a particular interface routine is accessing this open
+ //
+ // During an indication.
+ //
+ // When the open causes a reset.
+ //
+ // A packet currently being sent.
+ //
+ // (Basically the above two mean any time the open has left
+ // some processing around to be accomplished later.)
+ //
+ // This field should only be accessed when the adapter lock is held.
+ //
+ UINT References;
+
+ //
+ // Minimum Number of bytes for a lookahead.
+ //
+ UINT LookAhead;
+
+ //
+ // A flag indicating that the open has pended.
+ //
+ BOOLEAN OpenPending;
+
+ //
+ // A flag indicating that this binding is in the process of closing.
+ //
+ BOOLEAN BindingShuttingDown;
+
+
+ //
+ // A bogus NdisRequest to queue operations during a close.
+ //
+ NDIS_REQUEST CloseRequestChangeFilter;
+ NDIS_REQUEST CloseRequestChangeAddress;
+ NDIS_REQUEST CloseRequestChangeGroupAddress;
+
+} IBMTOK_OPEN,*PIBMTOK_OPEN;
+
+
+//
+// procedures which do error logging
+//
+
+typedef enum _IBMTOK_PROC_ID{
+ registerAdapter,
+ openAdapter,
+ hardwareDetails,
+ handleResetStaging,
+ handleSrbSsb,
+ startPendQueueOp,
+ finishPendQueueOp,
+ handleDeferred,
+ ibmtokDpc
+}IBMTOK_PROC_ID;
+
+//
+// Error log values
+//
+
+#define IBMTOK_ERRMSG_NOT_FOUND (ULONG)0x01
+#define IBMTOK_ERRMSG_CREATE_DB (ULONG)0x02
+#define IBMTOK_ERRMSG_INIT_INTERRUPT (ULONG)0x03
+#define IBMTOK_ERRMSG_OPEN_DB (ULONG)0x04
+#define IBMTOK_ERRMSG_ALLOC_MEM (ULONG)0x05
+#define IBMTOK_ERRMSG_UNSUPPORTED_RAM (ULONG)0x06
+#define IBMTOK_ERRMSG_BRINGUP_FAILURE (ULONG)0x07
+#define IBMTOK_ERRMSG_INVALID_CMD (ULONG)0x08
+#define IBMTOK_ERRMSG_BAD_OP (ULONG)0x09
+#define IBMTOK_ERRMSG_INVALID_STATUS (ULONG)0x0A
+#define IBMTOK_ERRMSG_INVALID_STATE (ULONG)0x0B
+#define IBMTOK_ERRMSG_ISRP_LOW_ERROR (ULONG)0x0C
+
+//
+// This macro returns a pointer to a PIBMTOK_OPEN given a MacBindingHandle.
+//
+#define PIBMTOK_OPEN_FROM_BINDING_HANDLE(Handle) \
+ ((PIBMTOK_OPEN)((PVOID)Handle))
+
+
+//
+// This macro returns a NDIS_HANDLE from a PIBMTOK_OPEN
+//
+#define BINDING_HANDLE_FROM_PIBMTOK_OPEN(Open) \
+ ((NDIS_HANDLE)((PVOID)Open))
+
+
+//
+// This macro will act a "epilogue" to every routine in the
+// *interface*. It will check whether there any requests needed
+// to defer there processing. It will also decrement the reference
+// count on the adapter. If the reference count is zero and there
+// is deferred work to do it will insert the interrupt processing
+// routine in the DPC queue.
+//
+// Note that we don't need to include checking for blocked receives
+// since blocked receives imply that there will eventually be an
+// interrupt.
+//
+// NOTE: This macro assumes that it is called with the lock acquired.
+//
+#define IBMTOK_DO_DEFERRED(Adapter) \
+{ \
+ PIBMTOK_ADAPTER _A = (Adapter); \
+ _A->References--; \
+ if ((!_A->References) && \
+ (_A->ResetInProgress || \
+ (!IsListEmpty(&_A->CloseList)))) { \
+ IbmtokHandleDeferred(_A); \
+ NdisReleaseSpinLock(&_A->Lock); \
+ } else { \
+ NdisReleaseSpinLock(&_A->Lock); \
+ } \
+}
+
+
+//++
+//
+// VOID
+// SET_INTERRUPT_RESET_FLAG(
+// IN PIBMTOK_ADAPTER Adapter,
+// )
+//
+//
+// Routine Description:
+//
+// This routine uses NdisSynchronizeWithInterrupt to call the
+// IbmtokSynchSetReset, which sets the ResetInterruptAllowed
+// flag in the adapter structure. This is set after the
+// adapter is reset to allow the interrupt indicating the
+// end of the reset to come through (since all others
+// should be blocked during the reset).
+//
+// Arguments:
+//
+// Adapter - The adapter to set the flag for.
+//
+// Return Value:
+//
+// None.
+//
+//--
+
+#define SET_INTERRUPT_RESET_FLAG(A) \
+{ \
+ PIBMTOK_ADAPTER _A = A; \
+ NdisSynchronizeWithInterrupt( \
+ &_A->Interrupt, \
+ (PVOID) IbmtokSynchSetReset, \
+ (PVOID)_A \
+ ); \
+}
+
+
+//
+// This macro is to clear the SRB/SSB and ARB/ASB bits
+// used by the interrupt handlers.
+//
+
+#define CLEAR_ISRP_BITS(A) \
+{ \
+ PIBMTOK_ADAPTER _A = A; \
+ NdisSynchronizeWithInterrupt( \
+ &_A->Interrupt, \
+ (PVOID) IbmtokSynchClearIsrpBits, \
+ (PVOID)_A \
+ ); \
+}
+
+
+
+//
+// VOID
+// IbmtokProcessSrbRequests(
+// IN PIBMTOK_ADAPTER Adapter
+// )
+// /*++
+//
+// Routine Description:
+//
+// Check if the SRB is available, if so queue the next
+// request on it. Preferably, it is called when it is known
+// that there is something on the queue.
+//
+// NOTE: THIS IS CALLED WITH THE LOCK HELD!!!
+//
+// NOTE: THIS MUST BE CALLED WITH Adapter->SrbAvailable == TRUE !!!!!
+//
+// Arguments:
+//
+// Adapter - The Adapter to process interrupts for.
+//
+// Return Value:
+//
+// None.
+//
+// --*/
+//
+
+#define IbmtokProcessSrbRequests(_Adapter) \
+{ \
+ if (_Adapter->SrbAvailable) { \
+ (_Adapter)->SrbAvailable = FALSE;\
+ SetupSrbCommand(_Adapter); \
+ } \
+}
+
+
+// VOID
+// PutPacketInCorrelatorArray(
+// IN PIBMTOK_ADAPTER Adapter,
+// IN PNDIS_PACKET Packet
+// )
+//
+// /*++
+//
+// Routine Description:
+//
+// This inserts a packet in the correlator array, based
+// on the value of its command correlator.
+//
+// Arguments:
+//
+// Adapter - The adapter that this packet is coming through.
+//
+// Packet - The packet that is to be inserted.
+//
+// Return Value:
+//
+// None.
+//
+// --*/
+//
+#define PutPacketInCorrelatorArray( _Adapter, _Packet) \
+{ \
+ PIBMTOK_RESERVED _Reserved = PIBMTOK_RESERVED_FROM_PACKET(_Packet); \
+ ASSERT(_Reserved->CorrelatorAssigned); \
+ ASSERT((_Adapter)->CorrelatorArray[_Reserved->CommandCorrelator] == (PNDIS_PACKET)NULL); \
+ (_Adapter)->CorrelatorArray[_Reserved->CommandCorrelator] = (_Packet); \
+}
+
+
+
+// STATIC
+// VOID
+// RemovePacketFromCorrelatorArray(
+// IN PIBMTOK_ADAPTER Adapter,
+// IN PNDIS_PACKET Packet
+// )
+//
+// /*++
+//
+// Routine Description:
+//
+// This deletes a packet in the correlator array, based
+// on the value of its command correlator.
+//
+// Arguments:
+//
+// Adapter - The adapter that this packet is coming through.
+//
+// Packet - The packet that is to be removed.
+//
+// Return Value:
+//
+// None.
+//
+// --*/
+//
+#define RemovePacketFromCorrelatorArray(_Adapter, _Packet) \
+{ \
+ PIBMTOK_RESERVED _Reserved = PIBMTOK_RESERVED_FROM_PACKET(_Packet); \
+ ASSERT(_Reserved->CorrelatorAssigned); \
+ _Reserved->CorrelatorAssigned = FALSE; \
+ (_Adapter)->CorrelatorArray[_Reserved->CommandCorrelator] = (PNDIS_PACKET)NULL; \
+}
+
+
+
+
+
+//
+// We define the external interfaces to the ibmtok driver.
+// These routines are only external to permit separate
+// compilation. Given a truely fast compiler they could
+// all reside in a single file and be static.
+//
+
+
+extern
+VOID
+IbmtokAdjustMaxLookAhead(
+ IN PIBMTOK_ADAPTER Adapter
+ );
+
+
+extern
+VOID
+IbmtokDPC(
+ IN PVOID SystemSpecific1,
+ IN PVOID Context,
+ IN PVOID SystemArgument1,
+ IN PVOID SystemArgument2
+ );
+
+extern
+VOID
+SetupSrbCommand(
+ IN PIBMTOK_ADAPTER Adapter
+ );
+
+extern
+VOID
+IbmtokWakeUpDpc(
+ IN PVOID SystemSpecific1,
+ IN PVOID Context,
+ IN PVOID SystemArgument1,
+ IN PVOID SystemArgument2
+ );
+
+extern
+BOOLEAN
+IbmtokISR(
+ IN PVOID Context
+ );
+
+extern
+VOID
+IbmtokHandleDeferred(
+ IN PIBMTOK_ADAPTER Adapter
+ );
+
+extern
+NDIS_STATUS
+IbmtokSetPacketFilter(
+ IN PIBMTOK_ADAPTER Adapter,
+ IN PIBMTOK_OPEN Open,
+ IN PNDIS_REQUEST NdisRequest,
+ IN UINT PacketFilter
+ );
+
+extern
+NDIS_STATUS
+IbmtokChangeFunctionalAddress(
+ IN PIBMTOK_ADAPTER Adapter,
+ IN PIBMTOK_OPEN Open,
+ IN PNDIS_REQUEST NdisRequest,
+ IN PUCHAR Address
+ );
+
+extern
+NDIS_STATUS
+IbmtokFillInGlobalData(
+ IN PIBMTOK_ADAPTER Adapter,
+ IN PNDIS_REQUEST NdisRequest
+ );
+
+
+extern
+VOID
+IbmtokForceAdapterInterrupt(
+ IN PIBMTOK_ADAPTER Adapter
+ );
+
+extern
+VOID
+IbmtokSetupForReset(
+ IN PIBMTOK_ADAPTER Adapter,
+ IN PIBMTOK_OPEN Open
+ );
+
+extern
+VOID
+IbmtokStartAdapterReset(
+ IN PIBMTOK_ADAPTER Adapter
+ );
+
+extern
+VOID
+IbmtokFinishAdapterReset(
+ IN PIBMTOK_ADAPTER Adapter
+ );
+
+extern
+BOOLEAN
+IbmtokSynchSetReset(
+ IN PVOID Context
+ );
+
+extern
+VOID
+IbmtokAbortPending(
+ IN PIBMTOK_ADAPTER Adapter,
+ IN NDIS_STATUS AbortStatus
+ );
+
+extern
+VOID
+IbmtokAbortSends(
+ IN PIBMTOK_ADAPTER Adapter,
+ IN NDIS_STATUS AbortStatus
+ );
+
+extern
+BOOLEAN
+IbmtokSynchClearIsrpBits(
+ IN PVOID Context
+ );
+
+extern
+NDIS_STATUS
+IbmtokTransferData(
+ IN NDIS_HANDLE MacBindingHandle,
+ IN NDIS_HANDLE MacReceiveContext,
+ IN UINT ByteOffset,
+ IN UINT BytesToTransfer,
+ OUT PNDIS_PACKET Packet,
+ OUT PUINT BytesTransferred
+ );
+
+extern
+NDIS_STATUS
+IbmtokSend(
+ IN NDIS_HANDLE MacBindingHandle,
+ IN PNDIS_PACKET Packet
+ );
+
+extern
+VOID
+IbmtokCopyFromPacketToBuffer(
+ IN PNDIS_PACKET Packet,
+ IN UINT Offset,
+ IN UINT BytesToCopy,
+ OUT PCHAR Buffer,
+ OUT PUINT BytesCopied
+ );
+
+extern
+VOID
+IbmtokCopyFromBufferToPacket(
+ IN PCHAR Buffer,
+ IN UINT BytesToCopy,
+ IN PNDIS_PACKET Packet,
+ IN UINT Offset,
+ OUT PUINT BytesCopied
+ );
+
+extern
+VOID
+IbmtokCopyFromPacketToPacket(
+ IN PNDIS_PACKET Destination,
+ IN UINT DestinationOffset,
+ IN UINT BytesToCopy,
+ IN PNDIS_PACKET Source,
+ IN UINT SourceOffset,
+ OUT PUINT BytesCopied
+ );
+
+extern
+VOID
+IbmtokShutdown(
+ IN PVOID ShutdownContext
+ );
+
+#endif // _IBMTOKSFT_
+
diff --git a/private/ntos/ndis/ibmtok/transfer.c b/private/ntos/ndis/ibmtok/transfer.c
new file mode 100644
index 000000000..8ae9da411
--- /dev/null
+++ b/private/ntos/ndis/ibmtok/transfer.c
@@ -0,0 +1,412 @@
+/*++
+
+Copyright (c) 1990 Microsoft Corporation
+
+Module Name:
+
+ transfer.c
+
+Abstract:
+
+ This file contains the code to implement the MacTransferData
+ API for the ndis 3.0 interface.
+
+Author:
+
+ Anthony V. Ercolano (Tonye) 12-Sept-1990
+ Adam Barr (adamba) 15-Mar-1991
+
+Environment:
+
+ Kernel Mode - Or whatever is the equivalent.
+
+Revision History:
+
+
+--*/
+
+#include <ndis.h>
+
+#include <tfilter.h>
+#include <tokhrd.h>
+#include <toksft.h>
+
+
+extern
+NDIS_STATUS
+IbmtokTransferData(
+ IN NDIS_HANDLE MacBindingHandle,
+ IN NDIS_HANDLE MacReceiveContext,
+ IN UINT ByteOffset,
+ IN UINT BytesToTransfer,
+ OUT PNDIS_PACKET Packet,
+ OUT PUINT BytesTransferred
+ )
+
+/*++
+
+Routine Description:
+
+ A protocol calls the IbmtokTransferData request (indirectly via
+ NdisTransferData) from within its Receive event handler
+ to instruct the MAC to copy the contents of the received packet
+ a specified packet buffer.
+
+Arguments:
+
+ MacBindingHandle - The context value returned by the MAC when the
+ adapter was opened. In reality this is a pointer to IBMTOK.
+
+ MacReceiveContext - The context value passed by the MAC on its call
+ to NdisIndicateReceive. The MAC 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.
+
+Return Value:
+
+ The function value is the status of the operation.
+
+
+--*/
+
+{
+
+ PIBMTOK_ADAPTER Adapter;
+
+ NDIS_STATUS StatusToReturn;
+
+ Adapter = PIBMTOK_ADAPTER_FROM_BINDING_HANDLE(MacBindingHandle);
+
+ NdisAcquireSpinLock(&Adapter->Lock);
+ Adapter->References++;
+
+ if (!Adapter->NotAcceptingRequests) {
+
+ PIBMTOK_OPEN Open = PIBMTOK_OPEN_FROM_BINDING_HANDLE(MacBindingHandle);
+
+ if (!Open->BindingShuttingDown) {
+
+ //
+ // The code in this section is quite similar to the
+ // code in CopyFromPacketToPacket. It could easily go
+ // into its own routine, except that it is not likely
+ // to be used in any other implementation.
+ //
+ SRAM_PTR SourceReceiveBuffer =
+ Adapter->IndicatedReceiveBuffer;
+
+ //
+ // Holds the count of the number of ndis buffers comprising
+ // the destination packet.
+ //
+ UINT DestinationBufferCount;
+
+ //
+ // Points to the buffer into which we are putting data.
+ //
+ PNDIS_BUFFER DestinationCurrentBuffer;
+
+ //
+ // Holds the virtual address of the current destination
+ // buffer.
+ //
+ PVOID DestinationVirtualAddress;
+
+ //
+ // Holds the virtual address of the current source buffer.
+ //
+ PRECEIVE_BUFFER SourceBufferAddress;
+
+ //
+ // Holds the address of the data in the current source buffer.
+ //
+ PVOID SourceVirtualAddress;
+
+ //
+ // Holds the length of the current destination buffer.
+ //
+ UINT DestinationCurrentLength;
+
+ //
+ // Holds the length of the current source buffer.
+ //
+ UINT SourceCurrentLength;
+
+ //
+ // Keep a local variable of BytesTransferred so we aren't
+ // referencing through a pointer.
+ //
+ UINT LocalBytesTransferred = 0;
+
+ USHORT PortValue;
+
+ Open->References++;
+
+ NdisReleaseSpinLock(&Adapter->Lock);
+
+ *BytesTransferred = 0;
+
+ ASSERT(sizeof(UINT) >= 2);
+ ASSERT(sizeof(UINT) == sizeof(NDIS_HANDLE));
+
+ //
+ // Get the first buffer of the destination.
+ //
+
+ NdisQueryPacket(
+ Packet,
+ NULL,
+ &DestinationBufferCount,
+ &DestinationCurrentBuffer,
+ NULL
+ );
+
+ //
+ // Could have a null packet.
+ //
+
+ if (DestinationBufferCount != 0) {
+
+ NdisQueryBuffer(
+ DestinationCurrentBuffer,
+ &DestinationVirtualAddress,
+ &DestinationCurrentLength
+ );
+
+ //
+ // Get the information for the first buffer of the source.
+ //
+
+ SourceBufferAddress = (PRECEIVE_BUFFER)
+ ((PUCHAR)SRAM_PTR_TO_PVOID(Adapter,
+ SourceReceiveBuffer) + 2);
+
+ //
+ // Adjust the address and length to account for the
+ // header for this frame.
+ //
+
+ SourceVirtualAddress =
+ SourceBufferAddress->FrameData +
+ Adapter->IndicatedHeaderLength;
+
+ NdisReadRegisterUshort(&SourceBufferAddress->BufferLength,
+ &PortValue
+ );
+
+ SourceCurrentLength = IBMSHORT_TO_USHORT(PortValue) -
+ Adapter->IndicatedHeaderLength;
+
+
+
+ //
+ // Take care of boundary condition of zero length copy.
+ //
+
+ while (LocalBytesTransferred < BytesToTransfer) {
+
+ //
+ // Check to see whether we've exhausted the current
+ // destination buffer. If so, move onto the next one.
+ //
+
+ if (!DestinationCurrentLength) {
+
+ NdisGetNextBuffer(
+ DestinationCurrentBuffer,
+ &DestinationCurrentBuffer
+ );
+
+ if (!DestinationCurrentBuffer) {
+
+ //
+ // 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;
+
+ }
+
+
+ //
+ // Check to see whether we've exhausted the current
+ // source buffer. If so, move onto the next one.
+ //
+
+ if (!SourceCurrentLength) {
+
+ NdisReadRegisterUshort(
+ &SourceBufferAddress->NextBuffer,
+ &SourceReceiveBuffer
+ );
+
+ if (SourceReceiveBuffer == NULL_SRAM_PTR) {
+
+ //
+ // We've reached the end of the frame. We
+ // return with what we've done so far. (Which
+ // must be shorter than requested.)
+ //
+
+ break;
+
+ }
+
+ SourceBufferAddress = (PRECEIVE_BUFFER)
+ SRAM_PTR_TO_PVOID(Adapter, SourceReceiveBuffer);
+
+ SourceVirtualAddress =
+ (PVOID)SourceBufferAddress->FrameData;
+
+ NdisReadRegisterUshort(
+ &SourceBufferAddress->BufferLength,
+ &SourceCurrentLength
+ );
+
+ SourceCurrentLength = IBMSHORT_TO_USHORT(
+ SourceCurrentLength
+ );
+
+ continue;
+
+ }
+
+ //
+ // Try to get us up to the point to start the copy.
+ //
+
+ if (ByteOffset) {
+
+ if (ByteOffset > SourceCurrentLength) {
+
+ //
+ // What we want isn't in this buffer.
+ //
+
+ ByteOffset -= SourceCurrentLength;
+ SourceCurrentLength = 0;
+ continue;
+
+ } else {
+
+ SourceVirtualAddress =
+ (PCHAR)SourceVirtualAddress + ByteOffset;
+ SourceCurrentLength -= ByteOffset;
+ ByteOffset = 0;
+
+ }
+
+ }
+
+ //
+ // Copy the data.
+ //
+
+ {
+
+ //
+ // Holds the amount of data to move.
+ //
+ UINT AmountToMove;
+
+ //
+ // Holds the amount desired remaining.
+ //
+ UINT Remaining = BytesToTransfer
+ - LocalBytesTransferred;
+
+ AmountToMove =
+ ((SourceCurrentLength <= DestinationCurrentLength)?
+ (SourceCurrentLength):(DestinationCurrentLength));
+
+ AmountToMove = ((Remaining < AmountToMove)?
+ (Remaining):(AmountToMove));
+
+ IBMTOK_MOVE_FROM_MAPPED_MEMORY(
+ DestinationVirtualAddress,
+ SourceVirtualAddress,
+ AmountToMove
+ );
+
+ DestinationVirtualAddress =
+ (PCHAR)DestinationVirtualAddress + AmountToMove;
+ SourceVirtualAddress =
+ (PCHAR)SourceVirtualAddress + AmountToMove;
+
+ LocalBytesTransferred += AmountToMove;
+ SourceCurrentLength -= AmountToMove;
+ DestinationCurrentLength -= AmountToMove;
+
+ }
+
+ }
+
+ *BytesTransferred = LocalBytesTransferred;
+
+ }
+
+ NdisAcquireSpinLock(&Adapter->Lock);
+ Open->References--;
+ StatusToReturn = NDIS_STATUS_SUCCESS;
+
+ } else {
+
+ StatusToReturn = NDIS_STATUS_REQUEST_ABORTED;
+
+ }
+
+ } else {
+
+ if (Adapter->ResetInProgress) {
+
+ StatusToReturn = NDIS_STATUS_RESET_IN_PROGRESS;
+
+ } else if (Adapter->OpenInProgress) {
+
+ StatusToReturn = NDIS_STATUS_FAILURE;
+
+ } else {
+
+ NdisWriteErrorLogEntry(
+ Adapter->NdisAdapterHandle,
+ NDIS_ERROR_CODE_DRIVER_FAILURE,
+ 2,
+ IBMTOK_ERRMSG_INVALID_STATE,
+ 1
+ );
+
+ }
+
+ }
+
+ IBMTOK_DO_DEFERRED(Adapter);
+ return StatusToReturn;
+}