summaryrefslogtreecommitdiffstats
path: root/private/ntos/ndis/loop/loop.c
diff options
context:
space:
mode:
Diffstat (limited to 'private/ntos/ndis/loop/loop.c')
-rw-r--r--private/ntos/ndis/loop/loop.c1378
1 files changed, 1378 insertions, 0 deletions
diff --git a/private/ntos/ndis/loop/loop.c b/private/ntos/ndis/loop/loop.c
new file mode 100644
index 000000000..39cfe2332
--- /dev/null
+++ b/private/ntos/ndis/loop/loop.c
@@ -0,0 +1,1378 @@
+#include <ndis.h>
+#include <efilter.h>
+#include <tfilter.h>
+#include <ffilter.h>
+
+#include "debug.h"
+#include "loop.h"
+
+#if DBG
+extern LONG LoopDebugLevel = DBG_LEVEL_FATAL;
+extern LONG LoopDebugComponent = DBG_COMP_ALL;
+#endif
+
+NDIS_STATUS
+LoopAddAdapter(
+ IN NDIS_HANDLE MacAdapterContext,
+ IN NDIS_HANDLE ConfigurationHandle,
+ IN PNDIS_STRING AdapterName
+ );
+
+NDIS_STATUS
+LoopCloseAdapter(
+ IN NDIS_HANDLE MacBindingHandle
+ );
+
+NDIS_STATUS
+LoopOpenAdapter(
+ 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 AddressingOptions OPTIONAL
+ );
+
+VOID
+LoopRemoveAdapter(
+ IN NDIS_HANDLE MacAdapterContext
+ );
+
+NDIS_STATUS
+LoopReset(
+ IN NDIS_HANDLE MacBindingHandle
+ );
+
+NDIS_STATUS
+LoopTransferData(
+ IN NDIS_HANDLE MacBindingHandle,
+ IN NDIS_HANDLE MacReceiveContext,
+ IN UINT ByteOffset,
+ IN UINT BytesToTransfer,
+ OUT PNDIS_PACKET Packet,
+ OUT PUINT BytesTransferred
+ );
+
+VOID
+LoopUnload(
+ IN NDIS_HANDLE MacMacContext
+ );
+
+
+STATIC
+NDIS_STATUS
+LoopRegisterAdapter(
+ IN NDIS_HANDLE LoopMacHandle,
+ IN PNDIS_STRING AdapterName,
+ IN NDIS_MEDIUM AdapterMedium,
+ IN PVOID NetAddress,
+ IN NDIS_HANDLE ConfigurationHandle
+ );
+
+STATIC
+NDIS_STATUS
+LoopChangeFilter(
+ IN UINT OldFilterClasses,
+ IN UINT NewFilterClasses,
+ IN NDIS_HANDLE MacBindingHandle,
+ IN PNDIS_REQUEST NdisRequest,
+ IN BOOLEAN Set
+ );
+
+STATIC
+VOID
+LoopCloseAction(
+ IN NDIS_HANDLE MacBindingHandle
+ );
+
+STATIC
+NDIS_STATUS
+LoopEthChangeAddress(
+ IN UINT OldFilterCount,
+ IN CHAR OldAddresses[][ETH_LENGTH_OF_ADDRESS],
+ IN UINT NewFilterCouunt,
+ IN CHAR NewAddresses[][ETH_LENGTH_OF_ADDRESS],
+ IN NDIS_HANDLE MacBindingHandle,
+ IN PNDIS_REQUEST NdisRequest,
+ IN BOOLEAN Set
+ );
+
+STATIC
+NDIS_STATUS
+LoopTrChangeAddress(
+ IN TR_FUNCTIONAL_ADDRESS OldFunctionalAddresses,
+ IN TR_FUNCTIONAL_ADDRESS NewFunctionalAddresses,
+ IN NDIS_HANDLE MacBindingHandle,
+ IN PNDIS_REQUEST NdisRequest,
+ IN BOOLEAN Set
+ );
+
+STATIC
+NDIS_STATUS
+LoopFddiChangeAddress(
+ IN UINT OldLongAddressCount,
+ IN CHAR OldLongAddresses[][FDDI_LENGTH_OF_LONG_ADDRESS],
+ IN UINT NewLongAddressCouunt,
+ IN CHAR NewLongAddresses[][FDDI_LENGTH_OF_LONG_ADDRESS],
+ IN UINT OldShortAddressCount,
+ IN CHAR OldShortAddresses[][FDDI_LENGTH_OF_SHORT_ADDRESS],
+ IN UINT NewShortAddressCouunt,
+ IN CHAR NewShortAddresses[][FDDI_LENGTH_OF_SHORT_ADDRESS],
+ IN NDIS_HANDLE MacBindingHandle,
+ IN PNDIS_REQUEST NdisRequest,
+ IN BOOLEAN Set
+ );
+
+STATIC NDIS_HANDLE LoopWrapperHandle;
+STATIC NDIS_HANDLE LoopMacHandle;
+
+// !! need to verify filters !!
+#define PACKET_FILTER_802_3 0xF07F
+#define PACKET_FILTER_802_5 0xF07F
+#define PACKET_FILTER_DIX 0xF07F
+#define PACKET_FILTER_FDDI 0xF07F
+#define PACKET_FILTER_LTALK 0x8009
+#define PACKET_FILTER_ARCNET 0x8009
+
+static const NDIS_PHYSICAL_ADDRESS physicalConst = NDIS_PHYSICAL_ADDRESS_CONST(-1,-1);
+
+
+NTSTATUS
+DriverEntry(
+ IN PDRIVER_OBJECT DriverObject,
+ IN PUNICODE_STRING RegistryPath
+ )
+{
+ NDIS_STATUS Status;
+ NDIS_MAC_CHARACTERISTICS LoopChar;
+ NDIS_STRING MacName = NDIS_STRING_CONST("LoopBack");
+
+ DBGPRINT(DBG_COMP_INIT, DBG_LEVEL_INFO, (" --> DriverEntry\n"));
+
+ NdisInitializeWrapper(
+ &LoopWrapperHandle,
+ DriverObject,
+ RegistryPath,
+ NULL
+ );
+
+ LoopChar.MajorNdisVersion = LOOP_NDIS_MAJOR_VERSION;
+ LoopChar.MinorNdisVersion = LOOP_NDIS_MINOR_VERSION;
+ LoopChar.OpenAdapterHandler = LoopOpenAdapter;
+ LoopChar.CloseAdapterHandler = LoopCloseAdapter;
+ LoopChar.RequestHandler = LoopRequest;
+ LoopChar.SendHandler = LoopSend;
+ LoopChar.TransferDataHandler = LoopTransferData;
+ LoopChar.ResetHandler = LoopReset;
+ LoopChar.UnloadMacHandler = LoopUnload;
+ LoopChar.QueryGlobalStatisticsHandler = LoopQueryGlobalStats;
+ LoopChar.AddAdapterHandler = LoopAddAdapter;
+ LoopChar.RemoveAdapterHandler = LoopRemoveAdapter;
+ LoopChar.Name = MacName;
+
+ NdisRegisterMac(
+ &Status,
+ &LoopMacHandle,
+ LoopWrapperHandle,
+ NULL,
+ &LoopChar,
+ sizeof(LoopChar)
+ );
+
+ if (Status == NDIS_STATUS_SUCCESS)
+ return STATUS_SUCCESS;
+
+ // Can only get here if something went wrong registering the MAC or
+ // all of the adapters
+ NdisTerminateWrapper(LoopWrapperHandle, DriverObject);
+ return STATUS_UNSUCCESSFUL;
+}
+
+NDIS_STATUS
+LoopAddAdapter(
+ IN NDIS_HANDLE MacAdapterContext,
+ IN NDIS_HANDLE ConfigurationHandle,
+ IN PNDIS_STRING AdapterName
+ )
+{
+ NDIS_STATUS Status = NDIS_STATUS_SUCCESS;
+ NDIS_HANDLE ConfigHandle;
+ PNDIS_CONFIGURATION_PARAMETER Parameter;
+ NDIS_STRING MediumKey = NDIS_STRING_CONST("Medium");
+ PUCHAR NetAddressBuffer[6];
+ PVOID NetAddress;
+ UINT Length;
+ NDIS_MEDIUM AdapterMedium;
+
+ DBGPRINT(DBG_COMP_INIT, DBG_LEVEL_INFO, (" --> LoopAddAdapter\n"));
+ DBGPRINT(DBG_COMP_INIT, DBG_LEVEL_INFO, ("Reading Config Info\n"));
+
+ // configuration info present, let's get it
+
+ NdisOpenConfiguration(
+ &Status,
+ &ConfigHandle,
+ ConfigurationHandle
+ );
+
+ if (Status != NDIS_STATUS_SUCCESS) {
+
+ // would like to log this, but adapter not registered yet
+ DBGPRINT(DBG_COMP_REGISTRY, DBG_LEVEL_FATAL,
+ ("Unable to open configuration database!\n"));
+
+ return Status;
+ }
+
+ NdisReadConfiguration(
+ &Status,
+ &Parameter,
+ ConfigHandle,
+ &MediumKey,
+ NdisParameterInteger
+ );
+
+ AdapterMedium = (NDIS_MEDIUM)Parameter->ParameterData.IntegerData;
+
+ if ((Status != NDIS_STATUS_SUCCESS) ||
+ !((AdapterMedium == NdisMedium802_3) ||
+ (AdapterMedium == NdisMedium802_5) ||
+ (AdapterMedium == NdisMediumFddi) ||
+ (AdapterMedium == NdisMediumLocalTalk) ||
+ (AdapterMedium == NdisMediumArcnet878_2))) {
+
+ // would like to log this, but adapter not registered yet
+ DBGPRINT(DBG_COMP_REGISTRY, DBG_LEVEL_FATAL,
+ ("Unable to find 'Medium' keyword or invalid value!\n"));
+
+ NdisCloseConfiguration(ConfigHandle);
+ return Status;
+ }
+
+ NdisReadNetworkAddress(
+ &Status,
+ &NetAddress,
+ &Length,
+ ConfigHandle
+ );
+
+ if (Status == NDIS_STATUS_SUCCESS) {
+
+ // verify the address is appropriate for the specific media and
+ // ensure that the locally administered address bit is set
+
+ switch (AdapterMedium) {
+ case NdisMedium802_3:
+ if ((Length != ETH_LENGTH_OF_ADDRESS) ||
+ ETH_IS_MULTICAST(NetAddress) ||
+ !(((PUCHAR)NetAddress)[0] & 0x02)) { // U/L bit
+ Length = 0;
+ }
+ break;
+ case NdisMedium802_5:
+ if ((Length != TR_LENGTH_OF_ADDRESS) ||
+ (((PUCHAR)NetAddress)[0] & 0x80) || // I/G bit
+ !(((PUCHAR)NetAddress)[0] & 0x40)) { // U/L bit
+ Length = 0;
+ }
+ break;
+ case NdisMediumFddi:
+ if ((Length != FDDI_LENGTH_OF_LONG_ADDRESS) ||
+ (((PUCHAR)NetAddress)[0] & 0x01) || // I/G bit
+ !(((PUCHAR)NetAddress)[0] & 0x02)) { // U/L bit
+ Length = 0;
+ }
+ break;
+ case NdisMediumLocalTalk:
+ if ((Length != 1) || LOOP_LT_IS_BROADCAST(*(PUCHAR)NetAddress)) {
+ Length = 0;
+ }
+ break;
+ case NdisMediumArcnet878_2:
+ if ((Length != 1) || LOOP_ARC_IS_BROADCAST(*(PUCHAR)NetAddress)) {
+ Length = 0;
+ }
+ break;
+ }
+
+ if (Length == 0) {
+ DBGPRINT(DBG_COMP_REGISTRY, DBG_LEVEL_FATAL,
+ ("Invalid NetAddress in registry!\n"));
+ NdisCloseConfiguration(ConfigHandle);
+ return NDIS_STATUS_FAILURE;
+ }
+
+ // have to save away the address as the info may be gone
+ // when we close the registry. we assume the length will
+ // be 6 bytes max
+
+ NdisMoveMemory(
+ NetAddressBuffer,
+ NetAddress,
+ Length
+ );
+ NetAddress = (PVOID)NetAddressBuffer;
+
+ }
+ else
+ NetAddress = NULL;
+
+ NdisCloseConfiguration(ConfigHandle);
+
+ Status = LoopRegisterAdapter(
+ LoopMacHandle,
+ AdapterName,
+ AdapterMedium,
+ NetAddress,
+ ConfigurationHandle
+ );
+ return Status;
+}
+
+NDIS_STATUS
+LoopCloseAdapter(
+ IN NDIS_HANDLE MacBindingHandle
+ )
+{
+ PLOOP_ADAPTER Adapter;
+ PLOOP_OPEN Open;
+ NDIS_STATUS StatusToReturn;
+
+ DBGPRINT(DBG_COMP_MISC, DBG_LEVEL_INFO, (" --> LoopCloseAdapter\n"));
+
+ Adapter = PLOOP_ADAPTER_FROM_BINDING_HANDLE(MacBindingHandle);
+
+ NdisAcquireSpinLock(&Adapter->Lock);
+ Adapter->References++;
+
+ Open = PLOOP_OPEN_FROM_BINDING_HANDLE(MacBindingHandle);
+
+ DBGPRINT(DBG_COMP_MISC, DBG_LEVEL_INFO,
+ ("Closing Open %lx, reference count = %ld\n",Open,Open->References));
+
+ if (!Open->BindingClosing) {
+
+ Open->BindingClosing = TRUE;
+ RemoveEntryList(&Open->OpenList);
+ Adapter->OpenCount--;
+ Adapter->References--;
+
+ //
+ // shouldn't be called unless there isn't anything running in the
+ // binding. if there is we're hosed.
+ //
+
+ switch (Adapter->Medium) {
+ case NdisMedium802_3:
+ case NdisMediumDix:
+ StatusToReturn = EthDeleteFilterOpenAdapter(
+ Adapter->Filter.Eth,
+ Open->NdisFilterHandle,
+ NULL
+ );
+ // needs to handle pending delete, but should be ok
+ // since our close action routine doesn't pend
+ break;
+ case NdisMedium802_5:
+ StatusToReturn = TrDeleteFilterOpenAdapter(
+ Adapter->Filter.Tr,
+ Open->NdisFilterHandle,
+ NULL
+ );
+ // needs to handle pending delete, but should be ok
+ // since our close action routine doesn't pend
+ break;
+ case NdisMediumFddi:
+ StatusToReturn = FddiDeleteFilterOpenAdapter(
+ Adapter->Filter.Fddi,
+ Open->NdisFilterHandle,
+ NULL
+ );
+ // needs to handle pending delete, but should be ok
+ // since our close action routine doesn't pend
+ break;
+ case NdisMediumLocalTalk:
+ case NdisMediumArcnet878_2:
+ break;
+ default:
+ ASSERT(FALSE);
+ break;
+ }
+
+ NdisFreeMemory(
+ Open,
+ sizeof(LOOP_OPEN),
+ 0
+ );
+
+ StatusToReturn = NDIS_STATUS_SUCCESS;
+
+ }
+ else
+ StatusToReturn = NDIS_STATUS_CLOSING;
+
+ Adapter->References--;
+ NdisReleaseSpinLock(&Adapter->Lock);
+
+ return StatusToReturn;
+}
+
+
+NDIS_STATUS
+LoopOpenAdapter(
+ 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 AddressingOptions OPTIONAL
+ )
+{
+ PLOOP_ADAPTER Adapter = PLOOP_ADAPTER_FROM_CONTEXT_HANDLE(MacAdapterContext);
+ PLOOP_OPEN NewOpen;
+ NDIS_STATUS StatusToReturn;
+ UINT i;
+
+ DBGPRINT(DBG_COMP_MISC, DBG_LEVEL_INFO, (" --> LoopOpenAdapter\n"));
+
+ DBGPRINT(DBG_COMP_MISC, DBG_LEVEL_INFO,
+ ("Opening binding for Adapter %lx\n",Adapter));
+
+ for (i=0;i < MediumArraySize; i++) {
+ if (MediumArray[i] == Adapter->Medium)
+ break;
+ }
+
+ if (i == MediumArraySize)
+ return NDIS_STATUS_UNSUPPORTED_MEDIA;
+
+ *SelectedMediumIndex = i;
+
+ NdisAcquireSpinLock(&Adapter->Lock);
+ Adapter->References++;
+
+ NdisAllocateMemory(
+ (PVOID)&NewOpen,
+ sizeof(LOOP_OPEN),
+ 0,
+ physicalConst
+ );
+
+ if (NewOpen != NULL) {
+
+ //
+ // Setup new Open Binding struct
+ //
+
+ DBGPRINT(DBG_COMP_MISC, DBG_LEVEL_INFO, ("new Open = %lx\n",NewOpen));
+
+ NdisZeroMemory(
+ NewOpen,
+ sizeof(LOOP_OPEN)
+ );
+
+ switch (Adapter->Medium) {
+ case NdisMedium802_3:
+ case NdisMediumDix:
+ StatusToReturn = (NDIS_STATUS)EthNoteFilterOpenAdapter(
+ Adapter->Filter.Eth,
+ NewOpen,
+ NdisBindingContext,
+ &NewOpen->NdisFilterHandle
+ );
+
+ DBGPRINT(DBG_COMP_MISC, DBG_LEVEL_INFO, ("new EthFilter Open = %lx\n",NewOpen->NdisFilterHandle));
+ break;
+ case NdisMedium802_5:
+ StatusToReturn = (NDIS_STATUS)TrNoteFilterOpenAdapter(
+ Adapter->Filter.Tr,
+ NewOpen,
+ NdisBindingContext,
+ &NewOpen->NdisFilterHandle
+ );
+
+ DBGPRINT(DBG_COMP_MISC, DBG_LEVEL_INFO, ("new TrFilter Open = %lx\n",NewOpen->NdisFilterHandle));
+ break;
+ case NdisMediumFddi:
+ StatusToReturn = (NDIS_STATUS)FddiNoteFilterOpenAdapter(
+ Adapter->Filter.Fddi,
+ NewOpen,
+ NdisBindingContext,
+ &NewOpen->NdisFilterHandle
+ );
+
+ DBGPRINT(DBG_COMP_MISC, DBG_LEVEL_INFO, ("new FddiFilter Open = %lx\n",NewOpen->NdisFilterHandle));
+ break;
+ default:
+ StatusToReturn = (NDIS_STATUS)TRUE;
+ break;
+ }
+
+ if (!StatusToReturn) {
+
+ DBGPRINT(DBG_COMP_MEMORY, DBG_LEVEL_ERR,
+ ("unable to create filter for binding %lx\n",NewOpen));
+
+ NdisWriteErrorLogEntry(
+ Adapter->NdisAdapterHandle,
+ NDIS_ERROR_CODE_OUT_OF_RESOURCES,
+ 0
+ );
+
+ NdisFreeMemory(
+ NewOpen,
+ sizeof(LOOP_OPEN),
+ 0);
+
+ Adapter->References--;
+ NdisReleaseSpinLock(&Adapter->Lock);
+
+ return NDIS_STATUS_FAILURE;
+ }
+
+ *MacBindingHandle = BINDING_HANDLE_FROM_PLOOP_OPEN(NewOpen);
+
+ InitializeListHead(&NewOpen->OpenList);
+ NewOpen->BindingClosing = FALSE;
+ NewOpen->Flags = 0;
+ NewOpen->NdisBindingContext = NdisBindingContext;
+ NewOpen->OwningLoop = Adapter;
+ NewOpen->References = 1;
+ NewOpen->CurrentLookAhead = LOOP_MAX_LOOKAHEAD;
+ NewOpen->CurrentPacketFilter = 0;
+
+ //
+ // Add the binding to the owning adapter
+ //
+
+ InsertTailList(&Adapter->OpenBindings,&NewOpen->OpenList);
+ Adapter->OpenCount++;
+ Adapter->References++;
+ Adapter->MaxLookAhead = LOOP_MAX_LOOKAHEAD;
+
+ StatusToReturn = NDIS_STATUS_SUCCESS;
+
+ }
+
+ else {
+
+ DBGPRINT(DBG_COMP_MEMORY, DBG_LEVEL_ERR,
+ ("unable to allocate binding struct for adapter %lx\n",Adapter));
+
+ NdisWriteErrorLogEntry(
+ Adapter->NdisAdapterHandle,
+ NDIS_ERROR_CODE_OUT_OF_RESOURCES,
+ 0
+ );
+
+ StatusToReturn = NDIS_STATUS_RESOURCES;
+
+ }
+
+ Adapter->References--;
+ NdisReleaseSpinLock(&Adapter->Lock);
+
+ return StatusToReturn;
+}
+
+
+VOID
+LoopRemoveAdapter(
+ IN NDIS_HANDLE MacAdapterContext
+ )
+//
+// All bindings should be closed before this gets called
+//
+{
+ PLOOP_ADAPTER Adapter = PLOOP_ADAPTER_FROM_CONTEXT_HANDLE(MacAdapterContext);
+ BOOLEAN TimerCancel;
+
+ DBGPRINT(DBG_COMP_MISC, DBG_LEVEL_INFO, (" --> LoopRemoveAdapter\n"));
+
+ DBGPRINT(DBG_COMP_MISC, DBG_LEVEL_INFO,
+ ("Removing adapter %lx\n",Adapter));
+
+ NdisCancelTimer(&Adapter->LoopTimer,&TimerCancel);
+
+ switch (Adapter->Medium) {
+ case NdisMedium802_3:
+ case NdisMediumDix:
+ DBGPRINT(DBG_COMP_MISC, DBG_LEVEL_INFO,
+ ("deleting EthFilter %lx\n",Adapter->Filter.Eth));
+ EthDeleteFilter(Adapter->Filter.Eth);
+ break;
+ case NdisMedium802_5:
+ DBGPRINT(DBG_COMP_MISC, DBG_LEVEL_INFO,
+ ("deleting TrFilter %lx\n",Adapter->Filter.Tr));
+ TrDeleteFilter(Adapter->Filter.Tr);
+ break;
+ case NdisMediumFddi:
+ DBGPRINT(DBG_COMP_MISC, DBG_LEVEL_INFO,
+ ("deleting FddiFilter %lx\n",Adapter->Filter.Fddi));
+ FddiDeleteFilter(Adapter->Filter.Fddi);
+ break;
+ default:
+ break;
+ }
+
+ NdisDeregisterAdapter(Adapter->NdisAdapterHandle);
+
+ NdisFreeSpinLock(&Adapter->Lock);
+
+ NdisFreeMemory(
+ Adapter->DeviceName.Buffer,
+ Adapter->DeviceNameLength,
+ 0
+ );
+
+ NdisFreeMemory(
+ Adapter,
+ sizeof(LOOP_ADAPTER),
+ 0
+ );
+}
+
+
+NDIS_STATUS
+LoopReset(
+ IN NDIS_HANDLE MacBindingHandle
+ )
+{
+ PLOOP_ADAPTER Adapter = PLOOP_ADAPTER_FROM_BINDING_HANDLE(MacBindingHandle);
+ NDIS_STATUS Status = NDIS_STATUS_SUCCESS;
+
+ DBGPRINT(DBG_COMP_MISC, DBG_LEVEL_INFO, (" --> LoopReset\n"));
+
+ NdisAcquireSpinLock(&Adapter->Lock);
+ Adapter->References++;
+
+ if (!Adapter->ResetInProgress) {
+
+ PLOOP_OPEN Open = PLOOP_OPEN_FROM_BINDING_HANDLE(MacBindingHandle);
+
+ if (!Open->BindingClosing) {
+
+ Open->References++;
+
+ //
+ // notify all bindings of beginning of reset
+ //
+ {
+ PLOOP_OPEN Open;
+ PLIST_ENTRY CurrentLink;
+
+ CurrentLink = Adapter->OpenBindings.Flink;
+ while(CurrentLink != &Adapter->OpenBindings) {
+
+ Open = CONTAINING_RECORD(
+ CurrentLink,
+ LOOP_OPEN,
+ OpenList
+ );
+
+ DBGPRINT(DBG_COMP_MISC, DBG_LEVEL_INFO,
+ ("Signaling reset start to binding %lx\n",Open));
+
+ if (Open->BindingClosing) {
+ CurrentLink = CurrentLink->Flink;
+ continue;
+ }
+ Open->References++;
+ NdisReleaseSpinLock(&Adapter->Lock);
+ NdisIndicateStatus(
+ Open->NdisBindingContext,
+ NDIS_STATUS_RESET_START,
+ NULL,
+ 0
+ );
+ NdisAcquireSpinLock(&Adapter->Lock);
+ Open->References--;
+ CurrentLink = CurrentLink->Flink;
+ }
+ }
+
+ Adapter->ResetInProgress = TRUE;
+
+ //
+ // Loop through the loopback queue and abort any pending sends
+ //
+
+ {
+ PNDIS_PACKET AbortPacket;
+ PLOOP_PACKET_RESERVED Reserved;
+ PLOOP_OPEN Open;
+
+ while (Adapter->Loopback != NULL) {
+
+ AbortPacket = Adapter->Loopback;
+ Reserved = PLOOP_RESERVED_FROM_PACKET(AbortPacket);
+ Adapter->Loopback = Reserved->Next;
+
+ Open = PLOOP_OPEN_FROM_BINDING_HANDLE(Reserved->MacBindingHandle);
+ NdisReleaseSpinLock(&Adapter->Lock);
+
+ NdisCompleteSend(
+ Open->NdisBindingContext,
+ AbortPacket,
+ NDIS_STATUS_REQUEST_ABORTED
+ );
+
+ NdisAcquireSpinLock(&Adapter->Lock);
+ Open->References--;
+ }
+
+ Adapter->CurrentLoopback = NULL;
+ Adapter->LastLoopback = NULL;
+ }
+
+ //
+ // notify all bindings of reset end
+ //
+ {
+ PLOOP_OPEN Open;
+ PLIST_ENTRY CurrentLink;
+
+ CurrentLink = Adapter->OpenBindings.Flink;
+ while(CurrentLink != &Adapter->OpenBindings) {
+
+ Open = CONTAINING_RECORD(
+ CurrentLink,
+ LOOP_OPEN,
+ OpenList
+ );
+
+ DBGPRINT(DBG_COMP_INIT, DBG_LEVEL_INFO,
+ ("Signaling reset end to binding %lx\n",Open));
+
+ if (Open->BindingClosing) {
+ CurrentLink = CurrentLink->Flink;
+ continue;
+ }
+ Open->References++;
+ NdisReleaseSpinLock(&Adapter->Lock);
+ NdisIndicateStatus(
+ Open->NdisBindingContext,
+ NDIS_STATUS_RESET_END,
+ NULL,
+ 0
+ );
+ NdisAcquireSpinLock(&Adapter->Lock);
+ Open->References--;
+ CurrentLink = CurrentLink->Flink;
+ }
+ }
+
+ Open->References--;
+ Adapter->ResetInProgress = FALSE;
+
+ }
+ else
+ Status = NDIS_STATUS_CLOSING;
+ }
+ else
+ Status = NDIS_STATUS_RESET_IN_PROGRESS;
+
+ Adapter->References--;
+ NdisReleaseSpinLock(&Adapter->Lock);
+ return Status;
+}
+
+
+NDIS_STATUS
+LoopTransferData(
+ IN NDIS_HANDLE MacBindingHandle,
+ IN NDIS_HANDLE MacReceiveContext,
+ IN UINT ByteOffset,
+ IN UINT BytesToTransfer,
+ OUT PNDIS_PACKET Packet,
+ OUT PUINT BytesTransferred
+ )
+{
+ PLOOP_ADAPTER Adapter = PLOOP_ADAPTER_FROM_BINDING_HANDLE(MacBindingHandle);
+ NDIS_STATUS StatusToReturn;
+
+ DBGPRINT(DBG_COMP_MISC, DBG_LEVEL_INFO, (" --> LoopTransferData\n"));
+
+ NdisAcquireSpinLock(&Adapter->Lock);
+ Adapter->References++;
+
+ if (!Adapter->ResetInProgress) {
+ PLOOP_OPEN Open = PLOOP_OPEN_FROM_BINDING_HANDLE(MacBindingHandle);
+
+ if (!Open->BindingClosing) {
+
+ Open->References++;
+
+ NdisReleaseSpinLock(&Adapter->Lock);
+
+ if (MacReceiveContext == NULL) {
+ NdisCopyFromPacketToPacket(
+ Packet,
+ 0,
+ BytesToTransfer,
+ Adapter->CurrentLoopback,
+ ByteOffset+(PLOOP_RESERVED_FROM_PACKET(Adapter->CurrentLoopback)->HeaderLength),
+ BytesTransferred
+ );
+ StatusToReturn = NDIS_STATUS_SUCCESS;
+ }
+ else {
+
+ //
+ // shouldn't get here as we never pass a non-NULL receive context
+ //
+
+ DBGPRINT(DBG_COMP_MISC, DBG_LEVEL_FATAL,
+ ("transfer data failed! passed a receive context of %lx\n",MacReceiveContext));
+ StatusToReturn = NDIS_STATUS_FAILURE;
+ }
+
+ NdisAcquireSpinLock(&Adapter->Lock);
+ Open->References--;
+
+ }
+ else
+ StatusToReturn = NDIS_STATUS_REQUEST_ABORTED;
+
+ }
+ else
+ StatusToReturn = NDIS_STATUS_RESET_IN_PROGRESS;
+
+ Adapter->References--;
+ NdisReleaseSpinLock(&Adapter->Lock);
+ return StatusToReturn;
+}
+
+
+VOID
+LoopUnload(
+ IN NDIS_HANDLE MacMacContext
+ )
+{
+ NDIS_STATUS Status;
+
+ DBGPRINT(DBG_COMP_MISC, DBG_LEVEL_INFO, (" --> LoopUnload\n"));
+
+ NdisDeregisterMac(
+ &Status,
+ LoopMacHandle
+ );
+ NdisTerminateWrapper(
+ LoopWrapperHandle,
+ NULL
+ );
+}
+
+STATIC
+NDIS_STATUS
+LoopRegisterAdapter(
+ IN NDIS_HANDLE LoopMacHandle,
+ IN PNDIS_STRING AdapterName,
+ IN NDIS_MEDIUM AdapterMedium,
+ IN PVOID NetAddress,
+ IN NDIS_HANDLE ConfigurationHandle
+ )
+{
+static const MEDIA_INFO MediaParams[] = {
+ /* NdisMedium802_3 */ { 1500, 14, PACKET_FILTER_802_3, 100000},
+ /* NdisMedium802_5 */ { 4082, 14, PACKET_FILTER_802_5, 40000},
+ /* NdisMediumFddi */ { 4486, 13, PACKET_FILTER_FDDI, 1000000},
+ /* NdisMediumWan */ { 0, 0, 0, 0},
+ /* NdisMediumLocalTalk */ { 600, 3, PACKET_FILTER_LTALK, 2300},
+ /* NdisMediumDix */ { 1500, 14, PACKET_FILTER_DIX, 100000},
+ /* NdisMediumArcnetRaw */ { 1512, 3, PACKET_FILTER_ARCNET, 25000},
+ /* NdisMediumArcnet878_2 */ {1512, 3, PACKET_FILTER_ARCNET, 25000} };
+
+ //
+ // Pointer to the adapter
+ //
+ PLOOP_ADAPTER Adapter;
+
+ //
+ // status of various NDIS calls
+ //
+ NDIS_STATUS Status;
+
+ //
+ // info for registering the adapter
+ //
+ NDIS_ADAPTER_INFORMATION AdapterInfo;
+
+ DBGPRINT(DBG_COMP_INIT, DBG_LEVEL_INFO, (" --> LoopRegisterAdapter\n"));
+
+ //
+ // allocate the adapter block
+ //
+ NdisAllocateMemory(
+ (PVOID)&Adapter,
+ sizeof(LOOP_ADAPTER),
+ 0,
+ physicalConst
+ );
+
+ if (Adapter != NULL) {
+
+ DBGPRINT(DBG_COMP_INIT, DBG_LEVEL_INFO, ("new Adapter = %lx\n",Adapter));
+
+ NdisZeroMemory(
+ Adapter,
+ sizeof(LOOP_ADAPTER)
+ );
+ Adapter->NdisMacHandle = LoopMacHandle;
+
+ //
+ // allocate memory for the name of the device
+ //
+
+ NdisAllocateMemory(
+ (PVOID)&Adapter->DeviceName.Buffer,
+ AdapterName->Length+2,
+ 0,
+ physicalConst
+ );
+
+ if (Adapter->DeviceName.Buffer != NULL) {
+
+ Adapter->DeviceNameLength = AdapterName->Length+2;
+ Adapter->DeviceName.MaximumLength = AdapterName->Length+2;
+ NdisZeroMemory(
+ Adapter->DeviceName.Buffer,
+ AdapterName->Length+2
+ );
+
+ #ifdef NDIS_NT
+
+ RtlCopyUnicodeString(
+ &Adapter->DeviceName,
+ AdapterName
+ );
+
+ #else
+
+ #error Need to copy a NDIS_STRING.
+
+ #endif
+
+ //
+ // set up the AdapterInfo structure
+ //
+
+ NdisZeroMemory(
+ &AdapterInfo,
+ sizeof(NDIS_ADAPTER_INFORMATION)
+ );
+ AdapterInfo.DmaChannel = 0;
+ AdapterInfo.Master = FALSE;
+ AdapterInfo.Dma32BitAddresses = FALSE;
+ AdapterInfo.AdapterType = NdisInterfaceInternal;
+ AdapterInfo.PhysicalMapRegistersNeeded = 0;
+ AdapterInfo.MaximumPhysicalMapping = 0;
+ AdapterInfo.NumberOfPortDescriptors = 0;
+
+ if ((Status = NdisRegisterAdapter(
+ &Adapter->NdisAdapterHandle,
+ Adapter->NdisMacHandle,
+ Adapter,
+ ConfigurationHandle,
+ AdapterName,
+ &AdapterInfo
+ )) == NDIS_STATUS_SUCCESS) {
+
+ InitializeListHead(&Adapter->OpenBindings);
+ Adapter->OpenCount = 0;
+
+ NdisAllocateSpinLock(&Adapter->Lock);
+ Adapter->InTimerProc = FALSE;
+ Adapter->TimerSet = FALSE;
+ Adapter->References = 1;
+ Adapter->Loopback = NULL;
+ Adapter->LastLoopback = NULL;
+ Adapter->CurrentLoopback = NULL;
+ NdisZeroMemory(
+ &Adapter->LoopBuffer,
+ LOOP_MAX_LOOKAHEAD
+ );
+
+ Adapter->ResetInProgress = FALSE;
+ Adapter->MaxLookAhead = 0;
+
+ Adapter->Medium = AdapterMedium;
+ Adapter->MediumLinkSpeed = MediaParams[(UINT)AdapterMedium].LinkSpeed;
+ Adapter->MediumMinPacketLen = MediaParams[(UINT)AdapterMedium].MacHeaderLen;
+ Adapter->MediumMaxPacketLen = MediaParams[(UINT)AdapterMedium].MacHeaderLen+
+ MediaParams[(UINT)AdapterMedium].MaxFrameLen;
+ Adapter->MediumMacHeaderLen = MediaParams[(UINT)AdapterMedium].MacHeaderLen;
+ Adapter->MediumMaxFrameLen = MediaParams[(UINT)AdapterMedium].MaxFrameLen;
+ Adapter->MediumPacketFilters = MediaParams[(UINT)AdapterMedium].PacketFilters;
+
+ switch (AdapterMedium) {
+ case NdisMedium802_3:
+ case NdisMediumDix:
+
+ NdisMoveMemory(
+ (PVOID)&Adapter->PermanentAddress,
+ LOOP_ETH_CARD_ADDRESS,
+ ETH_LENGTH_OF_ADDRESS
+ );
+
+ if (NetAddress != NULL) {
+ NdisMoveMemory(
+ (PVOID)&Adapter->CurrentAddress,
+ NetAddress,
+ ETH_LENGTH_OF_ADDRESS
+ );
+ }
+ else {
+ NdisMoveMemory(
+ (PVOID)&Adapter->CurrentAddress,
+ LOOP_ETH_CARD_ADDRESS,
+ ETH_LENGTH_OF_ADDRESS
+ );
+ }
+
+ Status = (NDIS_STATUS)EthCreateFilter(
+ LOOP_ETH_MAX_MULTICAST_ADDRESS,
+ LoopEthChangeAddress,
+ LoopChangeFilter,
+ LoopCloseAction,
+ Adapter->CurrentAddress,
+ &Adapter->Lock,
+ &Adapter->Filter.Eth
+ );
+ DBGPRINT(DBG_COMP_INIT, DBG_LEVEL_INFO,
+ ("new EthFilter = %lx\n",Adapter->Filter.Eth));
+ break;
+
+ case NdisMedium802_5:
+
+ NdisMoveMemory(
+ (PVOID)&Adapter->PermanentAddress,
+ LOOP_TR_CARD_ADDRESS,
+ TR_LENGTH_OF_ADDRESS
+ );
+
+ if (NetAddress != NULL) {
+ NdisMoveMemory(
+ (PVOID)&Adapter->CurrentAddress,
+ NetAddress,
+ TR_LENGTH_OF_ADDRESS
+ );
+ }
+ else {
+ NdisMoveMemory(
+ (PVOID)&Adapter->CurrentAddress,
+ LOOP_TR_CARD_ADDRESS,
+ TR_LENGTH_OF_ADDRESS
+ );
+ }
+
+ Status = (NDIS_STATUS)TrCreateFilter(
+ LoopTrChangeAddress,
+ LoopTrChangeAddress,
+ LoopChangeFilter,
+ LoopCloseAction,
+ Adapter->CurrentAddress,
+ &Adapter->Lock,
+ &Adapter->Filter.Tr
+ );
+ DBGPRINT(DBG_COMP_INIT, DBG_LEVEL_INFO,
+ ("new TrFilter = %lx\n",Adapter->Filter.Tr));
+ break;
+
+ case NdisMediumFddi:
+
+ // the short address will simply be the first 2
+ // bytes of the long address
+
+ NdisMoveMemory(
+ (PVOID)&Adapter->PermanentAddress,
+ LOOP_FDDI_CARD_ADDRESS,
+ FDDI_LENGTH_OF_LONG_ADDRESS
+ );
+
+ if (NetAddress != NULL) {
+ NdisMoveMemory(
+ (PVOID)&Adapter->CurrentAddress,
+ NetAddress,
+ FDDI_LENGTH_OF_LONG_ADDRESS
+ );
+ }
+ else {
+ NdisMoveMemory(
+ (PVOID)&Adapter->CurrentAddress,
+ LOOP_FDDI_CARD_ADDRESS,
+ FDDI_LENGTH_OF_LONG_ADDRESS
+ );
+ }
+
+ Status = (NDIS_STATUS)FddiCreateFilter(
+ LOOP_FDDI_MAX_MULTICAST_LONG,
+ LOOP_FDDI_MAX_MULTICAST_SHORT,
+ LoopFddiChangeAddress,
+ LoopChangeFilter,
+ LoopCloseAction,
+ Adapter->CurrentAddress,
+ Adapter->CurrentAddress,
+ &Adapter->Lock,
+ &Adapter->Filter.Fddi
+ );
+ DBGPRINT(DBG_COMP_INIT, DBG_LEVEL_INFO,
+ ("new FddiFilter = %lx\n",Adapter->Filter.Fddi));
+ break;
+
+ case NdisMediumLocalTalk:
+
+ Adapter->PermanentAddress[0] = LOOP_LTALK_CARD_ADDRESS;
+
+ if (NetAddress != NULL)
+ Adapter->CurrentAddress[0] = ((PUCHAR)NetAddress)[0];
+ else
+ Adapter->CurrentAddress[0] = LOOP_LTALK_CARD_ADDRESS;
+
+ // dumb line to satisfy the following status check
+ Status = (NDIS_STATUS)TRUE;
+
+ break;
+
+ case NdisMediumArcnet878_2:
+
+ Adapter->PermanentAddress[0] = LOOP_ARC_CARD_ADDRESS;
+
+ if (NetAddress != NULL)
+ Adapter->CurrentAddress[0] = ((PUCHAR)NetAddress)[0];
+ else
+ Adapter->CurrentAddress[0] = LOOP_ARC_CARD_ADDRESS;
+
+ // dumb line to satisfy the following status check
+ Status = (NDIS_STATUS)TRUE;
+
+ break;
+
+ default:
+ // shouldn't get here...
+ ASSERTMSG("LoopRegisterAdapter: received invalid medium\n",FALSE);
+ break;
+ }
+
+ if (!Status) {
+
+ DBGPRINT(DBG_COMP_MEMORY,DBG_LEVEL_FATAL,
+ ("%wS: Unable to configure media specific information\n",AdapterName));
+
+ NdisWriteErrorLogEntry(
+ Adapter->NdisAdapterHandle,
+ NDIS_ERROR_CODE_DRIVER_FAILURE,
+ 0
+ );
+
+ NdisDeregisterAdapter(Adapter->NdisAdapterHandle);
+
+ NdisFreeSpinLock(&Adapter->Lock);
+
+ NdisFreeMemory(
+ Adapter->DeviceName.Buffer,
+ Adapter->DeviceNameLength,
+ 0
+ );
+
+ NdisFreeMemory(
+ Adapter,
+ sizeof(LOOP_ADAPTER),
+ 0
+ );
+
+ return NDIS_STATUS_FAILURE;
+ }
+
+ NdisInitializeTimer(
+ &(Adapter->LoopTimer),
+ LoopTimerProc,
+ (PVOID)Adapter
+ );
+
+ NdisZeroMemory(
+ &Adapter->GeneralMandatory,
+ GM_ARRAY_SIZE * sizeof(ULONG)
+ );
+
+ return NDIS_STATUS_SUCCESS;
+
+ }
+
+ else {
+
+ //
+ // NdisRegisterAdapter failed
+ //
+
+ DBGPRINT(DBG_COMP_MEMORY,DBG_LEVEL_FATAL,
+ ("%wS: Unable to register adapter, Error = %x\n",AdapterName,Status));
+
+ NdisFreeMemory(
+ Adapter->DeviceName.Buffer,
+ Adapter->DeviceNameLength,
+ 0
+ );
+
+ NdisFreeMemory(
+ Adapter,
+ sizeof(LOOP_ADAPTER),
+ 0
+ );
+
+ return Status;
+ }
+
+ }
+ else {
+
+ //
+ // failed to allocate device name
+ //
+
+ DBGPRINT(DBG_COMP_MEMORY,DBG_LEVEL_FATAL,
+ ("%wS: Unable to allocate the device name\n",AdapterName));
+
+ NdisFreeMemory(
+ Adapter,
+ sizeof(LOOP_ADAPTER),
+ 0
+ );
+
+ return NDIS_STATUS_RESOURCES;
+
+ }
+
+ }
+
+ else {
+
+ //
+ // failed to allocate Adapter object
+ //
+
+ DBGPRINT(DBG_COMP_MEMORY,DBG_LEVEL_FATAL,
+ ("%wS: Unable to allocate the adapter object\n",AdapterName));
+
+ return NDIS_STATUS_RESOURCES;
+
+ }
+
+}
+
+STATIC
+NDIS_STATUS
+LoopChangeFilter(
+ IN UINT OldFilterClasses,
+ IN UINT NewFilterClasses,
+ IN NDIS_HANDLE MacBindingHandle,
+ IN PNDIS_REQUEST NdisRequest,
+ IN BOOLEAN Set
+ )
+{
+ PLOOP_ADAPTER Adapter = PLOOP_ADAPTER_FROM_BINDING_HANDLE(MacBindingHandle);
+ NDIS_STATUS StatusToReturn;
+
+ DBGPRINT(DBG_COMP_MISC, DBG_LEVEL_INFO, (" --> LoopChangeFilter\n"));
+
+ if (!Adapter->ResetInProgress)
+ StatusToReturn = NDIS_STATUS_SUCCESS;
+ else
+ StatusToReturn = NDIS_STATUS_RESET_IN_PROGRESS;
+
+ return StatusToReturn;
+}
+
+STATIC
+VOID
+LoopCloseAction(
+ IN NDIS_HANDLE MacBindingHandle
+ )
+{
+ DBGPRINT(DBG_COMP_MISC, DBG_LEVEL_INFO, (" --> LoopCloseAction\n"));
+
+ PLOOP_OPEN_FROM_BINDING_HANDLE(MacBindingHandle)->References--;
+}
+
+STATIC
+NDIS_STATUS
+LoopEthChangeAddress(
+ IN UINT OldFilterCount,
+ IN CHAR OldAddresses[][ETH_LENGTH_OF_ADDRESS],
+ IN UINT NewFilterCouunt,
+ IN CHAR NewAddresses[][ETH_LENGTH_OF_ADDRESS],
+ IN NDIS_HANDLE MacBindingHandle,
+ IN PNDIS_REQUEST NdisRequest,
+ IN BOOLEAN Set
+ )
+{
+ PLOOP_ADAPTER Adapter = PLOOP_ADAPTER_FROM_BINDING_HANDLE(MacBindingHandle);
+ NDIS_STATUS StatusToReturn;
+
+ DBGPRINT(DBG_COMP_MISC, DBG_LEVEL_INFO, (" --> LoopEthChangeAddress\n"));
+
+ if (!Adapter->ResetInProgress)
+ StatusToReturn = NDIS_STATUS_SUCCESS;
+ else
+ StatusToReturn = NDIS_STATUS_RESET_IN_PROGRESS;
+
+ return StatusToReturn;
+}
+
+STATIC
+NDIS_STATUS
+LoopTrChangeAddress(
+ IN TR_FUNCTIONAL_ADDRESS OldFunctionalAddresses,
+ IN TR_FUNCTIONAL_ADDRESS NewFunctionalAddresses,
+ IN NDIS_HANDLE MacBindingHandle,
+ IN PNDIS_REQUEST NdisRequest,
+ IN BOOLEAN Set
+ )
+{
+ PLOOP_ADAPTER Adapter = PLOOP_ADAPTER_FROM_BINDING_HANDLE(MacBindingHandle);
+ NDIS_STATUS StatusToReturn;
+
+ DBGPRINT(DBG_COMP_MISC, DBG_LEVEL_INFO, (" --> LoopTrChangeAddress\n"));
+
+ if (!Adapter->ResetInProgress)
+ StatusToReturn = NDIS_STATUS_SUCCESS;
+ else
+ StatusToReturn = NDIS_STATUS_RESET_IN_PROGRESS;
+
+ return StatusToReturn;
+}
+
+STATIC
+NDIS_STATUS
+LoopFddiChangeAddress(
+ IN UINT OldLongAddressCount,
+ IN CHAR OldLongAddresses[][FDDI_LENGTH_OF_LONG_ADDRESS],
+ IN UINT NewLongAddressCouunt,
+ IN CHAR NewLongAddresses[][FDDI_LENGTH_OF_LONG_ADDRESS],
+ IN UINT OldShortAddressCount,
+ IN CHAR OldShortAddresses[][FDDI_LENGTH_OF_SHORT_ADDRESS],
+ IN UINT NewShortAddressCouunt,
+ IN CHAR NewShortAddresses[][FDDI_LENGTH_OF_SHORT_ADDRESS],
+ IN NDIS_HANDLE MacBindingHandle,
+ IN PNDIS_REQUEST NdisRequest,
+ IN BOOLEAN Set
+ )
+{
+ PLOOP_ADAPTER Adapter = PLOOP_ADAPTER_FROM_BINDING_HANDLE(MacBindingHandle);
+ NDIS_STATUS StatusToReturn;
+
+ DBGPRINT(DBG_COMP_MISC, DBG_LEVEL_INFO, (" --> LoopFddiChangeAddress\n"));
+
+ if (!Adapter->ResetInProgress)
+ StatusToReturn = NDIS_STATUS_SUCCESS;
+ else
+ StatusToReturn = NDIS_STATUS_RESET_IN_PROGRESS;
+
+ return StatusToReturn;
+}