summaryrefslogtreecommitdiffstats
path: root/private/ntos/ndis/ibmtok/ibmtok.c
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--private/ntos/ndis/ibmtok/ibmtok.c5906
1 files changed, 5906 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;
+
+}