summaryrefslogtreecommitdiffstats
path: root/private/ntos/ndis/ndiswan/ndiswan.c
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--private/ntos/ndis/ndiswan/ndiswan.c1346
1 files changed, 1346 insertions, 0 deletions
diff --git a/private/ntos/ndis/ndiswan/ndiswan.c b/private/ntos/ndis/ndiswan/ndiswan.c
new file mode 100644
index 000000000..da5771b79
--- /dev/null
+++ b/private/ntos/ndis/ndiswan/ndiswan.c
@@ -0,0 +1,1346 @@
+/*++
+
+Copyright (c) 1990-1995 Microsoft Corporation
+
+Module Name:
+
+ Ndiswan.c
+
+Abstract:
+
+ This is the initialization file for the NdisWan driver. This driver
+ is a shim between the protocols, where it conforms to the NDIS 3.1
+ Miniport interface spec, and the WAN Miniport drivers, where it exports
+ the WAN Extensions for Miniports (it looks like a protocol to the WAN
+ Miniport drivers).
+
+Author:
+
+ Tony Bell (TonyBe) June 06, 1995
+
+Environment:
+
+ Kernel Mode
+
+Revision History:
+
+ TonyBe 06/06/95 Created
+
+--*/
+
+
+//
+// We want to initialize all of the global variables now!
+//
+#include "wan.h"
+
+EXPORT
+VOID
+NdisTapiRegisterProvider(
+ IN NDIS_HANDLE DriverHandle,
+ IN PVOID RequestProc
+ );
+
+//
+// Globals
+//
+NDISWANCB NdisWanCB; // Global control block for NdisWan
+
+WAN_GLOBAL_LIST ThresholdEventQueue; // Global thresholdevent queue
+
+WAN_GLOBAL_LIST RecvPacketQueue; // Global receive packet queue
+
+WAN_GLOBAL_LIST FreeBundleCBList; // List of free BundleCB's
+
+WAN_GLOBAL_LIST AdapterCBList; // List of NdisWan AdapterCB's
+
+WAN_GLOBAL_LIST WanAdapterCBList; // List of WAN Miniport structures
+
+WAN_GLOBAL_LIST GlobalRecvDescPool; // Global pool of free recvdesc's
+
+PCONNECTION_TABLE ConnectionTable = NULL; // Pointer to connection table
+
+PPPP_PROTOCOL_TABLE PPP_ProtocolTable = NULL; // Pointer to the PPP/Protocol lookup table
+
+NDIS_PHYSICAL_ADDRESS HighestAcceptableAddress = NDIS_PHYSICAL_ADDRESS_CONST(-1, -1);
+
+#ifdef NT
+
+NTSTATUS
+DriverEntry(
+ IN PDRIVER_OBJECT DriverObject,
+ IN PUNICODE_STRING RegistryPath
+ )
+/*++
+Routine Name:
+
+ DriverEntry
+
+Routine Description:
+
+ This is the NT OS specific driver entry point. It kicks off initialization
+ for the driver. We return from this routine only after NdisWan has installed
+ itself as: a Miniport driver, a "transport" to the WAN Miniport drivers, and
+ has been bound to the WAN Miniport drivers.
+
+Arguments:
+
+ DriverObject - NT OS specific Object
+ RegistryPath - NT OS specific pointer to registry location for NdisWan
+
+Return Values:
+
+ STATUS_SUCCESS
+ STATUS_FAILURE
+
+--*/
+{
+ NDIS_STATUS Status = NDIS_STATUS_SUCCESS;
+ NDIS_STRING SymbolicName = NDIS_STRING_CONST("\\DosDevices\\NdisWan");
+ NDIS_STRING Name = NDIS_STRING_CONST("\\Device\\NdisWan");
+ ULONG i;
+
+ NdisZeroMemory(&NdisWanCB, sizeof(NdisWanCB));
+
+ NdisWanCB.ulTraceLevel = DBG_CRITICAL_ERROR;
+ NdisWanCB.ulTraceMask = DBG_ALL;
+
+ NdisWanDbgOut(DBG_TRACE, DBG_INIT, ("DriverEntry: Enter"));
+
+ //
+ // Initialize as a Miniport MAC driver first
+ //
+ NdisMInitializeWrapper(&(NdisWanCB.hNdisWrapperHandle),
+ DriverObject,
+ RegistryPath,
+ NULL);
+
+ //
+ // Initialize globals
+ //
+ NdisAllocateSpinLock(&NdisWanCB.Lock);
+
+ NdisWanCB.pDriverObject = DriverObject;
+
+ NdisZeroMemory(&AdapterCBList, sizeof(WAN_GLOBAL_LIST));
+ InitializeListHead(&(AdapterCBList.List));
+ NdisAllocateSpinLock(&AdapterCBList.Lock);
+
+ NdisZeroMemory(&WanAdapterCBList, sizeof(WAN_GLOBAL_LIST));
+ InitializeListHead(&(WanAdapterCBList.List));
+ NdisAllocateSpinLock(&WanAdapterCBList.Lock);
+
+ NdisZeroMemory(&ThresholdEventQueue, sizeof(WAN_GLOBAL_LIST));
+ InitializeListHead(&(ThresholdEventQueue.List));
+ NdisAllocateSpinLock(&ThresholdEventQueue.Lock);
+
+ NdisZeroMemory(&RecvPacketQueue, sizeof(WAN_GLOBAL_LIST));
+ InitializeListHead(&(RecvPacketQueue.List));
+ NdisAllocateSpinLock(&RecvPacketQueue.Lock);
+
+ NdisZeroMemory(&FreeBundleCBList, sizeof(WAN_GLOBAL_LIST));
+ InitializeListHead(&(FreeBundleCBList.List));
+ NdisAllocateSpinLock(&FreeBundleCBList.Lock);
+
+ NdisZeroMemory(&GlobalRecvDescPool, sizeof(WAN_GLOBAL_LIST));
+ InitializeListHead(&GlobalRecvDescPool.List);
+ NdisAllocateSpinLock(&GlobalRecvDescPool.Lock);
+
+ Status = NdisWanCreatePPPProtocolTable();
+
+ if (Status != NDIS_STATUS_SUCCESS) {
+
+ NdisWanDbgOut(DBG_CRITICAL_ERROR, DBG_INIT,
+ ("NdisWanInitProtocolLookupTable Failed! Status: 0x%x - %s",
+ Status, NdisWanGetNdisStatus(Status)));
+
+ goto DriverEntryError;
+ }
+
+ //
+ // Initialize as a Miniport driver to the transports
+ //
+ Status = DoMiniportInit();
+
+ if (Status != NDIS_STATUS_SUCCESS) {
+
+ NdisWanDbgOut(DBG_CRITICAL_ERROR, DBG_INIT,
+ ("DoMiniportInit Failed! Status: 0x%x - %s",
+ Status, NdisWanGetNdisStatus(Status)));
+
+ goto DriverEntryError;
+ }
+
+ //
+ // Now initialzie as a "Protocol" to the WAN Miniport drivers
+ //
+ Status = DoProtocolInit(RegistryPath);
+
+ if (Status != NDIS_STATUS_SUCCESS) {
+
+ NdisWanDbgOut(DBG_CRITICAL_ERROR, DBG_INIT,
+ ("DoProtocolInit Failed! Status: 0x%x - %s",
+ Status, NdisWanGetNdisStatus(Status)));
+
+ goto DriverEntryError;
+ }
+
+ NdisWanReadRegistry(RegistryPath);
+
+ //
+ // Bind NdisWan to the WAN Miniport drivers
+ //
+ Status = DoWanMiniportInit();
+
+ if (Status != NDIS_STATUS_SUCCESS) {
+
+ NdisWanDbgOut(DBG_CRITICAL_ERROR, DBG_INIT,
+ ("DoWanMiniportInit Failed! Status: 0x%x - %s",
+ Status, NdisWanGetNdisStatus(Status)));
+
+ goto DriverEntryError;
+
+ }
+
+//
+// Code commented out for PNP. We may go through DriverEntry and not have
+// any miniports bound to us yet. We will get called to bind to a WanMiniport
+// at a later time by the ProtocolBindHandler call (?).
+//
+/*
+ NdisAcquireSpinLock(&WanAdapterCBList.Lock);
+
+ if (WanAdapterCBList.ulCount == 0) {
+ NdisWanDbgOut(DBG_CRITICAL_ERROR, DBG_INIT, ("No WanAdapters installed!"));
+
+ NdisReleaseSpinLock(&WanAdapterCBList.Lock);
+
+ goto DriverEntryError;
+ }
+
+ NdisReleaseSpinLock(&WanAdapterCBList.Lock);
+*/
+
+ //
+ // Allocate and initialize the ConnectionTable
+ //
+ Status = NdisWanCreateConnectionTable(NdisWanCB.ulNumberOfLinks + 10);
+
+ if (Status != NDIS_STATUS_SUCCESS) {
+
+ NdisWanDbgOut(DBG_CRITICAL_ERROR, DBG_INIT,
+ ("NdisWanInitConnectionTable Failed! Status: 0x%x - %s",
+ Status, NdisWanGetNdisStatus(Status)));
+
+ goto DriverEntryError;
+
+ }
+
+ //
+ // Initialize the Ioctl interface
+ //
+ for (i = 0; i <= IRP_MJ_MAXIMUM_FUNCTION; i++) {
+
+ NdisWanCB.MajorFunction[i] = (PVOID)DriverObject->MajorFunction[i];
+ DriverObject->MajorFunction[i] = NdisWanIrpStub;
+ }
+
+ DriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL] = NdisWanIoctl;
+
+ IoCreateDevice(DriverObject,
+ sizeof(LIST_ENTRY),
+ &Name,
+ FILE_DEVICE_NDISWAN,
+ 0,
+ FALSE,
+ (PDEVICE_OBJECT*)&NdisWanCB.pDeviceObject);
+
+ NdisWanDbgOut(DBG_INFO, DBG_INIT,
+ ("IoCreateSymbolicLink: %ls -> %ls",
+ SymbolicName.Buffer, Name.Buffer));
+
+ ((PDEVICE_OBJECT)NdisWanCB.pDeviceObject)->Flags |= DO_BUFFERED_IO;
+
+ IoCreateSymbolicLink(&SymbolicName,
+ &Name);
+
+ NdisWanDbgOut(DBG_TRACE, DBG_INIT, ("DriverEntry: Exit"));
+
+ return (STATUS_SUCCESS);
+
+ //
+ // An error occured so we need to cleanup things
+ //
+DriverEntryError:
+ NdisWanGlobalCleanup();
+
+// NdisTerminateWrapper(NdisWanCB.hNdisWrapperHandle,
+// NdisWanCB.pDriverObject);
+
+ NdisWanDbgOut(DBG_TRACE, DBG_INIT, ("DriverEntry: Exit Error!"));
+
+ return (STATUS_UNSUCCESSFUL);
+
+}
+
+
+VOID
+NdisWanReadRegistry(
+ IN PUNICODE_STRING RegistryPath
+ )
+/*++
+
+Routine Name:
+
+ NdisWanReadRegistry
+
+Routine Description:
+
+ This routine will read the registry values for NdisWan. These values only
+ need to be read once for all adapters as their information is global.
+
+Arguments:
+
+ WrapperConfigurationContext - Handle to registry key where NdisWan information
+ is stored.
+
+Return Values:
+
+ None
+
+--*/
+{
+ NDIS_STATUS Status;
+ PWSTR ParameterKey = L"NdisWan\\Parameters";
+ PWSTR BindKeyWord = L"Bind";
+ PWSTR ProtocolKeyWord = L"ProtocolType";
+ PWSTR PPPKeyWord = L"PPPProtocolType";
+ PWSTR FragmentSizeKeyWord = L"MinimumFragmentSize";
+ PWSTR DebugLevelKeyWord = L"DebugLevel";
+ PWSTR DebugIDKeyWord = L"DebugIdentifier";
+ RTL_QUERY_REGISTRY_TABLE QueryTable[2];
+ ULONG GenericULong;
+
+ NdisWanDbgOut(DBG_TRACE, DBG_INIT, ("NdisWanReadRegistry: Enter"));
+
+ //
+ // Read the Bind Parameter MULTI_SZ
+ //
+ NdisZeroMemory(&QueryTable, sizeof(QueryTable));
+ QueryTable[0].QueryRoutine = BindQueryRoutine;
+ QueryTable[0].Flags = RTL_QUERY_REGISTRY_REQUIRED;
+ QueryTable[0].Name = BindKeyWord;
+ QueryTable[0].EntryContext = NULL;
+ QueryTable[0].DefaultType = 0;
+ Status = RtlQueryRegistryValues(RTL_REGISTRY_SERVICES,
+ ParameterKey,
+ &QueryTable[0],
+ NULL,
+ NULL);
+
+
+ NdisWanDbgOut(DBG_INFO, DBG_INIT,
+ ("RtlQueryRegistry - 'Bind' Status: 0x%x",
+ Status));
+
+ //
+ // Read the ProtocolType parameter MULTI_SZ
+ //
+ NdisZeroMemory(&QueryTable, sizeof(QueryTable));
+ QueryTable[0].QueryRoutine = ProtocolTypeQueryRoutine;
+ QueryTable[0].Flags = RTL_QUERY_REGISTRY_REQUIRED;
+ QueryTable[0].Name = ProtocolKeyWord;
+ QueryTable[0].EntryContext = (PVOID)PROTOCOL_TYPE;
+ QueryTable[0].DefaultType = 0;
+ Status = RtlQueryRegistryValues(RTL_REGISTRY_SERVICES,
+ ParameterKey,
+ &QueryTable[0],
+ NULL,
+ NULL);
+
+ NdisWanDbgOut(DBG_INFO, DBG_INIT,
+ ("RtlQueryRegistry - 'ProtocolType' Status: 0x%x",
+ Status));
+ //
+ // Read the PPPProtocolType parameter MULTI_SZ
+ //
+ NdisZeroMemory(&QueryTable, sizeof(QueryTable));
+ QueryTable[0].QueryRoutine = ProtocolTypeQueryRoutine;
+ QueryTable[0].Flags = RTL_QUERY_REGISTRY_REQUIRED;
+ QueryTable[0].Name = PPPKeyWord;
+ QueryTable[0].EntryContext = (PVOID)PPP_TYPE;
+ QueryTable[0].DefaultType = 0;
+ Status = RtlQueryRegistryValues(RTL_REGISTRY_SERVICES,
+ ParameterKey,
+ &QueryTable[0],
+ NULL,
+ NULL);
+
+ NdisWanDbgOut(DBG_INFO, DBG_INIT,
+ ("RtlQueryRegistry - 'PPPProtocolType' Status: 0x%x",
+ Status));
+
+ //
+ // Read the MinFragmentSize parameter DWORD
+ //
+ NdisWanCB.ulMinFragmentSize = 100;
+ NdisZeroMemory(&QueryTable, sizeof(QueryTable));
+ QueryTable[0].QueryRoutine = NULL;
+ QueryTable[0].Flags = RTL_QUERY_REGISTRY_DIRECT | RTL_QUERY_REGISTRY_REQUIRED;
+ QueryTable[0].Name = FragmentSizeKeyWord;
+ QueryTable[0].EntryContext = (PVOID)&GenericULong;
+ QueryTable[0].DefaultType = 0;
+ Status = RtlQueryRegistryValues(RTL_REGISTRY_SERVICES,
+ ParameterKey,
+ &QueryTable[0],
+ NULL,
+ NULL);
+
+ NdisWanDbgOut(DBG_INFO, DBG_INIT,
+ ("RtlQueryRegistry - 'MinimumFragmentSize' Status: 0x%x",
+ Status));
+
+ if (Status == NDIS_STATUS_SUCCESS) {
+ NdisWanCB.ulMinFragmentSize = GenericULong;
+ }
+
+
+ //
+ // Read the DebugLevel parameter DWORD
+ //
+ NdisZeroMemory(&QueryTable, sizeof(QueryTable));
+ QueryTable[0].QueryRoutine = NULL;
+ QueryTable[0].Flags = RTL_QUERY_REGISTRY_DIRECT | RTL_QUERY_REGISTRY_REQUIRED;
+ QueryTable[0].Name = DebugLevelKeyWord;
+ QueryTable[0].EntryContext = (PVOID)&GenericULong;
+ QueryTable[0].DefaultType = 0;
+ Status = RtlQueryRegistryValues(RTL_REGISTRY_SERVICES,
+ ParameterKey,
+ &QueryTable[0],
+ NULL,
+ NULL);
+
+ NdisWanDbgOut(DBG_INFO, DBG_INIT,
+ ("RtlQueryRegistry - 'DebugLevel' Status: 0x%x",
+ Status));
+
+ if (Status == NDIS_STATUS_SUCCESS) {
+ NdisWanCB.ulTraceLevel = GenericULong;
+ }
+
+ //
+ // Read the DebugIdentifier parameter DWORD
+ //
+ NdisZeroMemory(&QueryTable, sizeof(QueryTable));
+ QueryTable[0].QueryRoutine = NULL;
+ QueryTable[0].Flags = RTL_QUERY_REGISTRY_DIRECT | RTL_QUERY_REGISTRY_REQUIRED;
+ QueryTable[0].Name = DebugIDKeyWord;
+ QueryTable[0].EntryContext = (PVOID)&GenericULong;
+ QueryTable[0].DefaultType = 0;
+ Status = RtlQueryRegistryValues(RTL_REGISTRY_SERVICES,
+ ParameterKey,
+ &QueryTable[0],
+ NULL,
+ NULL);
+
+ NdisWanDbgOut(DBG_INFO, DBG_INIT,
+ ("RtlQueryRegistry - 'DebugID' Status: 0x%x",
+ Status));
+
+ if (Status == NDIS_STATUS_SUCCESS) {
+ NdisWanCB.ulTraceMask = GenericULong;
+ }
+
+ NdisWanDbgOut(DBG_TRACE, DBG_INIT, ("NdisWanReadRegistry: Exit"));
+}
+
+NTSTATUS
+BindQueryRoutine(
+ IN PWSTR ValueName,
+ IN ULONG ValueType,
+ IN PVOID ValueData,
+ IN ULONG ValueLength,
+ IN PVOID Context,
+ IN PVOID EntryContext
+ )
+/*++
+
+Routine Name:
+
+Routine Description:
+
+Arguments:
+
+Return Values:
+
+--*/
+{
+ NTSTATUS Status = STATUS_SUCCESS;
+
+ NdisWanDbgOut(DBG_TRACE, DBG_INIT, ("BindQueryRoutine: Enter"));
+ NdisWanDbgOut(DBG_TRACE, DBG_INIT, ("MiniportName %ls", ValueData));
+
+ //
+ // Create the WanAdapterCB
+ //
+ Status = NdisWanCreateWanAdapterCB(ValueData);
+
+ if (Status != NDIS_STATUS_SUCCESS) {
+ NdisWanDbgOut(DBG_CRITICAL_ERROR, DBG_INIT,
+ ("NdisWanCreateWanAdapterCB Failed! Status: 0x%x - %s",
+ Status, NdisWanGetNdisStatus(Status)));
+
+ }
+
+ NdisWanDbgOut(DBG_TRACE, DBG_INIT, ("BindQueryRoutine: Exit Status: 0x%x", Status));
+
+ return (Status);
+}
+
+NTSTATUS
+ProtocolTypeQueryRoutine(
+ IN PWSTR ValueName,
+ IN ULONG ValueType,
+ IN PVOID ValueData,
+ IN ULONG ValueLength,
+ IN PVOID Context,
+ IN PVOID EntryContext
+ )
+/*++
+
+Routine Name:
+
+Routine Description:
+
+Arguments:
+
+Return Values:
+
+--*/
+{
+ NDIS_STRING String;
+ ULONG Value;
+ NTSTATUS Status = STATUS_SUCCESS;
+
+ NdisWanDbgOut(DBG_TRACE, DBG_INIT, ("ProtocolTypeQueryRoutine: Enter"));
+
+ //
+ // Convert to an NDIS_STRING
+ //
+ NdisWanStringToNdisString(&String, ValueData);
+
+ //
+ // Convert to an integer
+ //
+ NdisWanNdisStringToInteger(&String, &Value);
+
+ NdisWanDbgOut(DBG_TRACE, DBG_INIT, ("ProtocolID 0x%x", Value));
+
+ NdisWanFreeNdisString(&String);
+
+ //
+ // Place in table
+ //
+ InsertPPP_ProtocolID(Value, (ULONG)EntryContext);
+
+ NdisWanDbgOut(DBG_TRACE, DBG_INIT, ("ProtocolTypeQueryRoutine: Exit"));
+
+ return (Status);
+}
+
+
+#endif // NT specific code
+
+
+
+NDIS_STATUS
+DoMiniportInit(
+ VOID
+ )
+/*++
+
+Routine Name:
+
+ DoMiniportInit
+
+Routine Description:
+
+ This routines registers NdisWan as a Miniport driver with the NDIS wrapper.
+ The wrapper will now call NdisWanInitialize once for each adapter instance
+ of NdisWan that is in the registry.
+
+Arguments:
+
+ None
+
+Return Values:
+
+ NDIS_STATUS_SUCCESS
+ NDIS_STATUS_BAD_VERSION
+ NDIS_STATUS_FAILURE
+
+--*/
+{
+ NDIS_STATUS Status = NDIS_STATUS_SUCCESS;
+ NDIS_MINIPORT_CHARACTERISTICS MiniportChars;
+
+ NdisWanDbgOut(DBG_TRACE, DBG_INIT, ("DoMiniportInit: Enter"));
+
+ NdisZeroMemory(&MiniportChars, sizeof(MiniportChars));
+
+ MiniportChars.MajorNdisVersion = 3;
+ MiniportChars.MinorNdisVersion = 0;
+ MiniportChars.HaltHandler = NdisWanHalt;
+ MiniportChars.InitializeHandler = NdisWanInitialize;
+ MiniportChars.QueryInformationHandler = NdisWanQueryInformation;
+ MiniportChars.ReconfigureHandler = NdisWanReconfigure;
+ MiniportChars.ResetHandler = NdisWanReset;
+ MiniportChars.SendHandler = NdisWanSend;
+ MiniportChars.SetInformationHandler = NdisWanSetInformation;
+ MiniportChars.TransferDataHandler = NdisWanTransferData;
+
+ //
+ // Since we don't have any hardware to worry about we will
+ // not handle any of the interrupt stuff!
+ //
+ MiniportChars.DisableInterruptHandler = NULL;
+ MiniportChars.EnableInterruptHandler = NULL;
+ MiniportChars.HandleInterruptHandler = NULL;
+ MiniportChars.ISRHandler = NULL;
+
+ //
+ // We will disable the check for hang timeout so we do not
+ // need a check for hang handler!
+ //
+// MiniportChars.CheckForHangHandler = NdisWanCheckForHang;
+ MiniportChars.CheckForHangHandler = NULL;
+
+ Status = NdisMRegisterMiniport(NdisWanCB.hNdisWrapperHandle,
+ &MiniportChars,
+ sizeof(MiniportChars));
+
+ NdisWanDbgOut(DBG_TRACE, DBG_INIT, ("DoMiniportInit: Exit"));
+
+ return (Status);
+}
+
+
+
+NDIS_STATUS
+DoProtocolInit(
+ IN PUNICODE_STRING RegistryPath
+ )
+/*++
+
+Routine Name:
+
+ DoProtocolInit
+
+Routine Description:
+
+ This function registers NdisWan as a protocol with the NDIS wrapper.
+
+Arguments:
+
+ None
+
+Return Values:
+
+ NDIS_STATUS_BAD_CHARACTERISTICS
+ NDIS_STATUS_BAD_VERSION
+ NDIS_STATUS_RESOURCES
+ NDIS_STATUS_SUCCESS
+
+--*/
+{
+//
+// The name of the "transport" side of NdisWan
+//
+ NDIS_PROTOCOL_CHARACTERISTICS ProtocolChars;
+ NDIS_STATUS Status;
+ NDIS_STRING NdisWanName = NDIS_STRING_CONST("\\Device\\NdisWan");
+
+
+ NdisWanDbgOut(DBG_TRACE, DBG_INIT, ("DoProtocolInit: Enter"));
+
+ NdisZeroMemory(&ProtocolChars, sizeof(ProtocolChars));
+
+
+ ProtocolChars.Name.Length = NdisWanName.Length;
+ ProtocolChars.Name.Buffer = (PVOID)NdisWanName.Buffer;
+
+ ProtocolChars.MajorNdisVersion = 3;
+ ProtocolChars.MinorNdisVersion = 0;
+ ProtocolChars.CloseAdapterCompleteHandler = NdisWanCloseAdapterComplete;
+ ProtocolChars.StatusHandler = NdisWanIndicateStatus;
+ ProtocolChars.StatusCompleteHandler = NdisWanIndicateStatusComplete;
+ ProtocolChars.OpenAdapterCompleteHandler = NdisWanOpenAdapterComplete;
+ ProtocolChars.RequestCompleteHandler = NdisWanRequestComplete;
+ ProtocolChars.ResetCompleteHandler = NdisWanResetComplete;
+ ProtocolChars.WanSendCompleteHandler = NdisWanSendCompleteHandler;
+ ProtocolChars.TransferDataCompleteHandler = NdisWanTransferDataComplete;
+ ProtocolChars.WanReceiveHandler = NdisWanReceiveIndication;
+ ProtocolChars.ReceiveCompleteHandler = NdisWanReceiveComplete;
+
+ NdisRegisterProtocol(&Status,
+ &NdisWanCB.hProtocolHandle,
+ (PNDIS_PROTOCOL_CHARACTERISTICS)&ProtocolChars,
+ sizeof(NDIS_PROTOCOL_CHARACTERISTICS) + ProtocolChars.Name.Length);
+
+ NdisWanDbgOut(DBG_TRACE, DBG_INIT, ("DoProtocolInit: Exit"));
+
+ return (Status);
+}
+
+NDIS_STATUS
+DoWanMiniportInit(
+ VOID
+ )
+/*++
+
+Routine Name:
+
+Routine Description:
+
+Arguments:
+
+Return Values:
+
+--*/
+{
+ PWAN_ADAPTERCB pWanAdapterCB;
+ NDIS_STATUS Status = NDIS_STATUS_SUCCESS;
+ NDIS_MEDIUM WanMediumSubType;
+ NDIS_WAN_INFO WanInfo;
+ NDIS_REQUEST NdisRequest;
+
+ //
+ // For each WAN Miniport that we have a WANAdapterCB for we will
+ // open the WAN Miniport thus binding to it. We will also query
+ // each WAN Miniport adapter to get information about it.
+ //
+ NdisWanDbgOut(DBG_TRACE, DBG_INIT, ("DoWanMiniportInit: Enter"));
+
+ NdisAcquireSpinLock(&WanAdapterCBList.Lock);
+
+ for (pWanAdapterCB = (PWAN_ADAPTERCB)WanAdapterCBList.List.Flink;
+ (PVOID)pWanAdapterCB != (PVOID)&(WanAdapterCBList.List);
+ pWanAdapterCB = (PWAN_ADAPTERCB)pWanAdapterCB->Linkage.Flink) {
+
+ NdisReleaseSpinLock(&WanAdapterCBList.Lock);
+
+ Status = NdisWanOpenWanAdapter(pWanAdapterCB);
+
+ if (Status != NDIS_STATUS_SUCCESS) {
+ PWAN_ADAPTERCB pPrevWanAdapterCB = (PWAN_ADAPTERCB)pWanAdapterCB->Linkage.Blink;
+
+ RemoveEntryList(&pWanAdapterCB->Linkage);
+ WanAdapterCBList.ulCount--;
+
+ NdisWanDbgOut(DBG_CRITICAL_ERROR, DBG_INIT, ("Failed to bind to %ls! Error 0x%x - %s",
+ pWanAdapterCB->MiniportName.Buffer, Status, NdisWanGetNdisStatus(Status)));
+
+ NdisWanDestroyWanAdapterCB(pWanAdapterCB);
+
+ pWanAdapterCB = pPrevWanAdapterCB;
+
+ NdisAcquireSpinLock(&WanAdapterCBList.Lock);
+ continue;
+ }
+
+ NdisWanDbgOut(DBG_TRACE, DBG_INIT, ("Successful Binding to %ls!",
+ pWanAdapterCB->MiniportName.Buffer));
+
+ //
+ // Get the medium subtype. We don't use this info right now but
+ // maybe someday...
+ //
+ NdisRequest.RequestType = NdisRequestQueryInformation;
+ NdisRequest.DATA.QUERY_INFORMATION.Oid = OID_WAN_MEDIUM_SUBTYPE;
+ NdisRequest.DATA.QUERY_INFORMATION.InformationBuffer = &WanMediumSubType;
+ NdisRequest.DATA.QUERY_INFORMATION.InformationBufferLength = sizeof(WanMediumSubType);
+
+ Status = NdisWanSubmitNdisRequest(pWanAdapterCB,
+ &NdisRequest,
+ SYNC,
+ NDISWAN);
+
+ if (Status != NDIS_STATUS_SUCCESS) {
+ NdisWanDbgOut(DBG_FAILURE, DBG_INIT, ("Error returned from OID_WAN_MEDIUM_SUBTYPE! Error 0x%x - %s",
+ Status, NdisWanGetNdisStatus(Status)));
+
+ NdisAcquireSpinLock(&WanAdapterCBList.Lock);
+ continue;
+ }
+
+ pWanAdapterCB->MediumSubType = WanMediumSubType;
+
+ //
+ // Get more information about the WAN Miniport that we are bound to!
+ //
+ NdisZeroMemory(&WanInfo, sizeof(WanInfo));
+ NdisRequest.RequestType = NdisRequestQueryInformation;
+ NdisRequest.DATA.QUERY_INFORMATION.Oid = OID_WAN_GET_INFO;
+ NdisRequest.DATA.QUERY_INFORMATION.InformationBuffer = &WanInfo;
+ NdisRequest.DATA.QUERY_INFORMATION.InformationBufferLength = sizeof(WanInfo);
+
+ Status = NdisWanSubmitNdisRequest(pWanAdapterCB,
+ &NdisRequest,
+ SYNC,
+ NDISWAN);
+
+ if (Status != NDIS_STATUS_SUCCESS) {
+ NdisWanDbgOut(DBG_FAILURE, DBG_INIT, ("Error returned from OID_WAN_GET_INFO! Error 0x%x - %s",
+ Status, NdisWanGetNdisStatus(Status)));
+
+ NdisAcquireSpinLock(&WanAdapterCBList.Lock);
+ continue;
+ }
+
+ NdisMoveMemory(&pWanAdapterCB->WanInfo, &WanInfo, sizeof(NDIS_WAN_INFO));
+
+ NdisWanCB.ulNumberOfLinks += pWanAdapterCB->WanInfo.Endpoints;
+
+ NdisAcquireSpinLock(&FreeBundleCBList.Lock);
+ FreeBundleCBList.ulMaxCount = NdisWanCB.ulNumberOfLinks;
+ NdisReleaseSpinLock(&FreeBundleCBList.Lock);
+
+ if (pWanAdapterCB->WanInfo.FramingBits & TAPI_PROVIDER) {
+
+ //
+ // Tell tapi about this device
+ //
+ NdisTapiRegisterProvider(pWanAdapterCB, NdisWanTapiRequestProc);
+
+ }
+
+ NdisAcquireSpinLock(&WanAdapterCBList.Lock);
+ }
+
+//
+// The following lines are commented out to take into account pnp.
+// We may not have any miniports to bind to initially but get called
+// to bind to them later!
+//
+// if (WanAdapterCBList.ulCount == 0)
+// Status = NDIS_STATUS_ADAPTER_NOT_FOUND;
+// else
+ Status = NDIS_STATUS_SUCCESS;
+
+ NdisReleaseSpinLock(&WanAdapterCBList.Lock);
+
+ NdisWanDbgOut(DBG_TRACE, DBG_INIT, ("DoWanMiniportInit: Exit"));
+
+ return (Status);
+}
+
+VOID
+InsertPPP_ProtocolID(
+ IN ULONG Value,
+ IN ULONG ValueType
+ )
+/*++
+
+Routine Name:
+
+ InsertPPP_ProtocolID
+
+Routine Description:
+
+ This routine takes a protocol value or a PPP protocol value and inserts it
+ into the appropriate lookup table.
+
+Arguments:
+
+ Value - Either a ProtocolID or PPP ProtocolID
+
+ ValueType - Either PROTOCOL_TYPE or PPP_TYPE
+
+Return Values:
+
+--*/
+{
+ ULONG i;
+ ULONG ArraySize = PPP_ProtocolTable->ulArraySize;
+ PUSHORT ValueArray;
+
+ //
+ // Figure out which array we should be looking at for
+ // this value type
+ //
+ if (ValueType == PROTOCOL_TYPE) {
+ ValueArray = PPP_ProtocolTable->ProtocolID;
+ } else {
+ ValueArray = PPP_ProtocolTable->PPPProtocolID;
+ }
+
+ NdisAcquireSpinLock(&PPP_ProtocolTable->Lock);
+
+ //
+ // First check to see if this value is already in the array
+ //
+ for (i = 0; i < ArraySize; i++) {
+
+ if (ValueArray[i] == (USHORT)Value) {
+
+ //
+ // If it is then we just update the value
+ //
+ ValueArray[i] = (USHORT)Value;
+ break;
+
+ }
+ }
+
+ //
+ // We did not find the value in the array so
+ // we will add it at the 1st available spot
+ //
+ if (i >= ArraySize) {
+
+ for (i = 0; i < ArraySize; i++) {
+
+ //
+ // We are looking for an empty slot to add
+ // the new value to
+ //
+ if (ValueArray[i] == 0) {
+
+ ValueArray[i] = (USHORT)Value;
+
+ if (ValueType == PROTOCOL_TYPE) {
+ NdisWanCB.ulNumberOfProtocols++;
+ }
+
+ break;
+ }
+ }
+ }
+
+ NdisReleaseSpinLock(&PPP_ProtocolTable->Lock);
+}
+
+USHORT
+GetPPP_ProtocolID(
+ IN USHORT Value,
+ IN ULONG ValueType
+ )
+/*++
+
+Routine Name:
+
+Routine Description:
+
+Arguments:
+
+Return Values:
+
+--*/
+{
+ ULONG i;
+ ULONG ArraySize = PPP_ProtocolTable->ulArraySize;
+ PUSHORT ValueArray, ReturnValueArray;
+ USHORT ReturnValue = INVALID_PROTOCOL;
+
+ //
+ // Figure out which array we should be looking at for
+ // this value type
+ //
+ if (ValueType == PROTOCOL_TYPE) {
+ ValueArray = PPP_ProtocolTable->ProtocolID;
+ ReturnValueArray = PPP_ProtocolTable->PPPProtocolID;
+ } else {
+ ValueArray = PPP_ProtocolTable->PPPProtocolID;
+ ReturnValueArray = PPP_ProtocolTable->ProtocolID;
+ }
+
+ NdisAcquireSpinLock(&PPP_ProtocolTable->Lock);
+
+ for (i = 0; i < ArraySize; i++) {
+ if (ValueArray[i] == Value) {
+ ReturnValue = ReturnValueArray[i];
+ break;
+ }
+ }
+
+ NdisReleaseSpinLock(&PPP_ProtocolTable->Lock);
+
+ return (ReturnValue);
+}
+
+NDIS_HANDLE
+InsertLinkInConnectionTable(
+ IN PLINKCB LinkCB
+ )
+/*++
+
+Routine Name:
+
+Routine Description:
+
+Arguments:
+
+Return Values:
+
+--*/
+{
+ ULONG Index;
+ PLINKCB *LinkArray = ConnectionTable->LinkArray;
+
+ NdisAcquireSpinLock(&ConnectionTable->Lock);
+
+ //
+ // We are doing a linear search for an empty spot in
+ // the link array
+ //
+ for (Index = 1; Index < ConnectionTable->ulArraySize; Index++) {
+ if (LinkArray[Index] == NULL) {
+ LinkArray[Index] = LinkCB;
+ ConnectionTable->ulNumActiveLinks++;
+ LinkCB->hLinkHandle = (NDIS_HANDLE)Index;
+ break;
+ }
+ }
+
+ ASSERT(Index < ConnectionTable->ulArraySize);
+
+ NdisReleaseSpinLock(&ConnectionTable->Lock);
+
+ return ((NDIS_HANDLE)Index);
+}
+
+VOID
+RemoveLinkFromConnectionTable(
+ IN PLINKCB LinkCB
+ )
+/*++
+
+Routine Name:
+
+Routine Description:
+
+Arguments:
+
+Return Values:
+
+--*/
+{
+ ULONG Index = (ULONG)LinkCB->hLinkHandle;
+ PLINKCB *LinkArray = ConnectionTable->LinkArray;
+
+ NdisAcquireSpinLock(&ConnectionTable->Lock);
+
+ if (LinkArray[Index] != NULL) {
+
+ ASSERT(LinkCB == LinkArray[Index]);
+
+ LinkArray[Index] = NULL;
+
+ ConnectionTable->ulNumActiveLinks--;
+ } else {
+ NdisWanDbgOut(DBG_CRITICAL_ERROR, DBG_INIT, ("LinkCB not in connection table! LinkCB: 0x%8.8x", LinkCB));
+ ASSERT(0);
+ }
+
+ NdisReleaseSpinLock(&ConnectionTable->Lock);
+}
+
+NDIS_HANDLE
+InsertBundleInConnectionTable(
+ IN PBUNDLECB BundleCB
+ )
+/*++
+
+Routine Name:
+
+Routine Description:
+
+Arguments:
+
+Return Values:
+
+--*/
+{
+ ULONG Index;
+ PBUNDLECB *BundleArray = ConnectionTable->BundleArray;
+
+ NdisAcquireSpinLock(&ConnectionTable->Lock);
+
+ //
+ // We are doing a linear search for an empty spot in
+ // the link array
+ //
+ for (Index = 1; Index < ConnectionTable->ulArraySize; Index++) {
+ if (BundleArray[Index] == NULL) {
+ BundleArray[Index] = BundleCB;
+ ConnectionTable->ulNumActiveBundles++;
+ BundleCB->hBundleHandle = (NDIS_HANDLE)Index;
+ break;
+ }
+ }
+
+ InsertTailList(&ConnectionTable->BundleList, &BundleCB->Linkage);
+
+ ASSERT(Index != ConnectionTable->ulArraySize);
+
+ NdisReleaseSpinLock(&ConnectionTable->Lock);
+
+ return ((NDIS_HANDLE)Index);
+}
+
+VOID
+RemoveBundleFromConnectionTable(
+ IN PBUNDLECB BundleCB
+ )
+/*++
+
+Routine Name:
+
+Routine Description:
+
+Arguments:
+
+Return Values:
+
+--*/
+{
+ ULONG Index = (ULONG)BundleCB->hBundleHandle;
+ PBUNDLECB *BundleArray = ConnectionTable->BundleArray;
+
+ NdisAcquireSpinLock(&ConnectionTable->Lock);
+
+ if (BundleArray[Index] != NULL) {
+
+ ASSERT(BundleCB == BundleArray[Index]);
+
+ RemoveEntryList(&BundleCB->Linkage);
+
+ BundleArray[Index] = NULL;
+
+ ConnectionTable->ulNumActiveBundles--;
+ } else {
+ NdisWanDbgOut(DBG_CRITICAL_ERROR, DBG_INIT, ("BundleCB not in connection table! BundleCB: 0x%8.8x", BundleCB));
+ ASSERT(0);
+ }
+
+ NdisReleaseSpinLock(&ConnectionTable->Lock);
+}
+
+VOID
+NdisWanGlobalCleanup(
+ VOID
+ )
+/*++
+
+Routine Name:
+
+ NdisWanGlobalCleanup
+
+Routine Description:
+ This routine is responsible for cleaning up all allocated resources.
+
+Arguments:
+
+ None
+
+Return Values:
+
+ None
+
+--*/
+{
+ //
+ // Stop all timers
+ //
+
+ //
+ // Complete all outstanding requests
+ //
+
+ //
+ // Free all of the AdapterCB's
+ //
+ NdisAcquireSpinLock(&AdapterCBList.Lock);
+ while (!IsListEmpty(&AdapterCBList.List)) {
+ PADAPTERCB AdapterCB;
+
+ AdapterCB = (PADAPTERCB)RemoveHeadList(&AdapterCBList.List);
+ NdisWanFreeMemory(AdapterCB);
+ }
+ NdisReleaseSpinLock(&AdapterCBList.Lock);
+
+ //
+ // Free all of the WanAdapterCB's
+ //
+ NdisAcquireSpinLock(&WanAdapterCBList.Lock);
+ while (!IsListEmpty(&WanAdapterCBList.List)) {
+ PWAN_ADAPTERCB WanAdapterCB;
+
+ WanAdapterCB = (PWAN_ADAPTERCB)RemoveHeadList(&WanAdapterCBList.List);
+ NdisWanFreeMemory(WanAdapterCB);
+ }
+ NdisReleaseSpinLock(&WanAdapterCBList.Lock);
+
+ //
+ // Free all of the BundleCB's
+ //
+
+ //
+ // Free all of the LinkCB's
+ //
+
+ //
+ // Free globals
+ //
+ if (ConnectionTable != NULL) {
+ NdisWanFreeMemory(ConnectionTable);
+ }
+
+ if (PPP_ProtocolTable != NULL) {
+ NdisWanFreeMemory(PPP_ProtocolTable);
+ }
+
+ //
+ // Terminate the wrapper
+ //
+ NdisTerminateWrapper(NdisWanCB.hNdisWrapperHandle,
+ NdisWanCB.pDriverObject);
+}
+
+BOOLEAN
+IsHandleValid(
+ USHORT usHandleType,
+ NDIS_HANDLE hHandle
+ )
+/*++
+
+Routine Name:
+
+Routine Description:
+
+Arguments:
+
+Return Values:
+
+--*/
+{
+ BOOLEAN RetValue = FALSE;
+ PVOID Cb;
+
+ if (usHandleType == LINKHANDLE) {
+
+ LINKCB_FROM_LINKH((PLINKCB)Cb, hHandle);
+
+ } else if (usHandleType == BUNDLEHANDLE) {
+
+ BUNDLECB_FROM_BUNDLEH((PBUNDLECB)Cb, hHandle);
+
+ }
+
+ if (Cb != NULL) {
+ RetValue = TRUE;
+ }
+
+ return (RetValue);
+}
+
+
+#if DBG // Debug
+
+PUCHAR
+NdisWanGetNdisStatus(
+ NDIS_STATUS GeneralStatus
+ )
+/*++
+
+Routine Name:
+
+ NdisWanGetNdisStatus
+
+Routine Description:
+
+ This routine returns a pointer to the string describing the NDIS error
+ denoted by GeneralStatus
+
+Arguments:
+
+ GeneralStatus - The NDIS status you wish to make readable
+
+Return Values:
+
+ Returns a pointer to a string describing GeneralStatus
+
+--*/
+{
+ static NDIS_STATUS Status[] = {
+ NDIS_STATUS_SUCCESS,
+ NDIS_STATUS_PENDING,
+
+ NDIS_STATUS_ADAPTER_NOT_FOUND,
+ NDIS_STATUS_ADAPTER_NOT_OPEN,
+ NDIS_STATUS_ADAPTER_NOT_READY,
+ NDIS_STATUS_ADAPTER_REMOVED,
+ NDIS_STATUS_BAD_CHARACTERISTICS,
+ NDIS_STATUS_BAD_VERSION,
+ NDIS_STATUS_CLOSING,
+ NDIS_STATUS_DEVICE_FAILED,
+ NDIS_STATUS_FAILURE,
+ NDIS_STATUS_INVALID_DATA,
+ NDIS_STATUS_INVALID_LENGTH,
+ NDIS_STATUS_INVALID_OID,
+ NDIS_STATUS_INVALID_PACKET,
+ NDIS_STATUS_MULTICAST_FULL,
+ NDIS_STATUS_NOT_INDICATING,
+ NDIS_STATUS_NOT_RECOGNIZED,
+ NDIS_STATUS_NOT_RESETTABLE,
+ NDIS_STATUS_NOT_SUPPORTED,
+ NDIS_STATUS_OPEN_FAILED,
+ NDIS_STATUS_OPEN_LIST_FULL,
+ NDIS_STATUS_REQUEST_ABORTED,
+ NDIS_STATUS_RESET_IN_PROGRESS,
+ NDIS_STATUS_RESOURCES,
+ NDIS_STATUS_UNSUPPORTED_MEDIA
+ };
+ static PUCHAR String[] = {
+ "SUCCESS",
+ "PENDING",
+
+ "ADAPTER_NOT_FOUND",
+ "ADAPTER_NOT_OPEN",
+ "ADAPTER_NOT_READY",
+ "ADAPTER_REMOVED",
+ "BAD_CHARACTERISTICS",
+ "BAD_VERSION",
+ "CLOSING",
+ "DEVICE_FAILED",
+ "FAILURE",
+ "INVALID_DATA",
+ "INVALID_LENGTH",
+ "INVALID_OID",
+ "INVALID_PACKET",
+ "MULTICAST_FULL",
+ "NOT_INDICATING",
+ "NOT_RECOGNIZED",
+ "NOT_RESETTABLE",
+ "NOT_SUPPORTED",
+ "OPEN_FAILED",
+ "OPEN_LIST_FULL",
+ "REQUEST_ABORTED",
+ "RESET_IN_PROGRESS",
+ "RESOURCES",
+ "UNSUPPORTED_MEDIA"
+ };
+
+ static UCHAR BadStatus[] = "UNDEFINED";
+#define StatusCount (sizeof(Status)/sizeof(NDIS_STATUS))
+ INT i;
+
+ for (i=0; i<StatusCount; i++)
+ if (GeneralStatus == Status[i])
+ return String[i];
+ return BadStatus;
+#undef StatusCount
+}
+#endif // End Debug
+
+