diff options
Diffstat (limited to '')
-rw-r--r-- | private/ntos/ndis/loop/loop.c | 1378 |
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; +} |