/************************************************************* Required NDIS procedure Stops TX and RX path and finished the function of adapter *************************************************************/ static VOID ParaNdis5_Halt( IN NDIS_HANDLE MiniportAdapterContext) { NDIS_STATUS status = NDIS_STATUS_SUCCESS; BOOLEAN bUnused; PARANDIS_ADAPTER *pContext = (PARANDIS_ADAPTER *)MiniportAdapterContext; DEBUG_ENTRY(0); ParaNdis_DebugHistory(pContext, hopHalt, NULL, 1, 0, 0); NdisCancelTimer(&pContext->ConnectTimer, &bUnused); NdisResetEvent(&pContext->HaltEvent); if (NDIS_STATUS_PENDING != ParaNdis5_StopSend(pContext, TRUE, OnSendStopped)) NdisSetEvent(&pContext->HaltEvent); WaitHaltEvent(pContext, "Send"); NdisResetEvent(&pContext->HaltEvent); if (NDIS_STATUS_PENDING != ParaNdis5_StopReceive(pContext, TRUE, OnReceiveStopped)) NdisSetEvent(&pContext->HaltEvent); WaitHaltEvent(pContext, "Receive"); ParaNdis_CleanupContext(pContext); NdisCancelTimer(&pContext->DPCPostProcessTimer, &bUnused); ParaNdis_DebugHistory(pContext, hopHalt, NULL, 0, 0, 0); ParaNdis_DebugRegisterMiniport(pContext, FALSE); NdisFreeMemory(pContext, 0, 0); DEBUG_EXIT_STATUS(0, status); }
/********************************************************** Required NDIS handler for RESET operation Never happens under normal condition, only if OID or other call returns PENDING and not completed or if ParaNdis6_CheckForHang returns true ***********************************************************/ static NDIS_STATUS ParaNdis6_Reset( NDIS_HANDLE miniportAdapterContext, PBOOLEAN pAddressingReset) { NDIS_STATUS status = NDIS_STATUS_FAILURE; PARANDIS_ADAPTER *pContext = (PARANDIS_ADAPTER *)miniportAdapterContext; NDIS_HANDLE hwo; tGeneralWorkItem *pwi; DEBUG_ENTRY(0); *pAddressingReset = TRUE; ParaNdis_DebugHistory(pContext, hopSysReset, NULL, 1, 0, 0); hwo = NdisAllocateIoWorkItem(pContext->MiniportHandle); pwi = ParaNdis_AllocateMemory(pContext, sizeof(tGeneralWorkItem)); if (pwi && hwo) { pwi->pContext = pContext; pwi->WorkItem = hwo; NdisQueueIoWorkItem(hwo, OnResetWorkItem, pwi); status = NDIS_STATUS_PENDING; } else { if (pwi) NdisFreeMemory(pwi, 0, 0); if (hwo) NdisFreeIoWorkItem(hwo); ParaNdis_DebugHistory(pContext, hopSysReset, NULL, 0, status, 0); } DEBUG_EXIT_STATUS(0, status); return status; }
/********************************************************** Deregister driver Clean up WPP ***********************************************************/ static VOID ParaNdis6_Unload(IN PDRIVER_OBJECT pDriverObject) { DEBUG_ENTRY(0); if (DriverHandle) NdisMDeregisterMiniportDriver(DriverHandle); DEBUG_EXIT_STATUS(2, 0); ParaNdis_DebugCleanup(pDriverObject); }
/********************************************************** called at IRQL = PASSIVE_LEVEL Called on disable, on removal, on standby (if required) ***********************************************************/ static VOID ParaNdis6_Halt(NDIS_HANDLE miniportAdapterContext, NDIS_HALT_ACTION haltAction) { PARANDIS_ADAPTER *pContext = (PARANDIS_ADAPTER *)miniportAdapterContext; DEBUG_ENTRY(0); ParaNdis_DebugHistory(pContext, hopHalt, NULL, 1, haltAction, 0); ParaNdis_CleanupContext(pContext); ParaNdis_DebugHistory(pContext, hopHalt, NULL, 0, 0, 0); ParaNdis_DebugRegisterMiniport(pContext, FALSE); NdisFreeMemory(pContext, 0, 0); DEBUG_EXIT_STATUS(2, 0); }
/************************************************************* Required NDIS procedure Responsible for hardware interrupt handling *************************************************************/ static VOID ParaNdis5_MiniportISR(OUT PBOOLEAN InterruptRecognized, OUT PBOOLEAN QueueMiniportHandleInterrupt, IN NDIS_HANDLE MiniportAdapterContext) { PARANDIS_ADAPTER *pContext = (PARANDIS_ADAPTER *)MiniportAdapterContext; BOOLEAN b; *QueueMiniportHandleInterrupt = FALSE; b = ParaNdis_OnLegacyInterrupt(pContext, QueueMiniportHandleInterrupt); *InterruptRecognized = b; DEBUG_EXIT_STATUS(7, (ULONG)b); }
/* We enter this procedure in two cases: - number of MSIX vectors is at least nPathBundles*2 + 1 - there is single MSIX vector and one path bundle */ NDIS_STATUS ParaNdis_ConfigureMSIXVectors(PARANDIS_ADAPTER *pContext) { NDIS_STATUS status = NDIS_STATUS_RESOURCES; UINT i; PIO_INTERRUPT_MESSAGE_INFO pTable = pContext->pMSIXInfoTable; bool bSingleVector = pContext->pMSIXInfoTable->MessageCount == 1; if (pTable && pTable->MessageCount) { status = NDIS_STATUS_SUCCESS; DPrintf(0, ("[%s] Using MSIX interrupts (%d messages, irql %d)\n", __FUNCTION__, pTable->MessageCount, pTable->UnifiedIrql)); for (i = 0; i < pContext->pMSIXInfoTable->MessageCount; ++i) { DPrintf(0, ("[%s] MSIX message%d=%08X=>%I64X\n", __FUNCTION__, i, pTable->MessageInfo[i].MessageData, pTable->MessageInfo[i].MessageAddress)); } for (UINT j = 0; j < pContext->nPathBundles && status == NDIS_STATUS_SUCCESS; ++j) { u16 vector = 2 * u16(j); status = pContext->pPathBundles[j].txPath.SetupMessageIndex(vector); if (status == NDIS_STATUS_SUCCESS) { if (!bSingleVector) vector++; status = pContext->pPathBundles[j].rxPath.SetupMessageIndex(vector); } DPrintf(0, ("[%s] Using messages %u/%u for RX/TX queue %u\n", __FUNCTION__, pContext->pPathBundles[j].rxPath.getMessageIndex(), pContext->pPathBundles[j].txPath.getMessageIndex(), j)); } if (status == NDIS_STATUS_SUCCESS && pContext->bCXPathCreated) { /* Usually there is own vector for control queue. In corner case of single vector control queue uses the same vector as RX and TX */ if (bSingleVector) { status = pContext->CXPath.SetupMessageIndex(0); } else { status = pContext->CXPath.SetupMessageIndex(2 * u16(pContext->nPathBundles)); } } } DEBUG_EXIT_STATUS(0, status); return status; }
NDIS_STATUS ParaNdis_ConfigureMSIXVectors(PARANDIS_ADAPTER *pContext) { NDIS_STATUS status = NDIS_STATUS_RESOURCES; UINT i; PIO_INTERRUPT_MESSAGE_INFO pTable = pContext->pMSIXInfoTable; if (pTable && pTable->MessageCount) { status = NDIS_STATUS_SUCCESS; DPrintf(0, ("[%s] Using MSIX interrupts (%d messages, irql %d)\n", __FUNCTION__, pTable->MessageCount, pTable->UnifiedIrql)); for (i = 0; i < pContext->pMSIXInfoTable->MessageCount; ++i) { DPrintf(0, ("[%s] MSIX message%d=%08X=>%I64X\n", __FUNCTION__, i, pTable->MessageInfo[i].MessageData, pTable->MessageInfo[i].MessageAddress)); } for (UINT j = 0; j < pContext->nPathBundles && status == NDIS_STATUS_SUCCESS; ++j) { status = pContext->pPathBundles[j].rxPath.SetupMessageIndex(2 * u16(j) + 1); status = pContext->pPathBundles[j].txPath.SetupMessageIndex(2 * u16(j)); } if (pContext->bCXPathCreated) { pContext->CXPath.SetupMessageIndex(2 * u16(pContext->nPathBundles)); } } if (status == NDIS_STATUS_SUCCESS) { for (UINT j = 0; j < pContext->nPathBundles && status == NDIS_STATUS_SUCCESS; ++j) { DPrintf(0, ("[%s] Using messages %u/%u for RX/TX queue %u\n", __FUNCTION__, pContext->pPathBundles[j].rxPath.getMessageIndex(), pContext->pPathBundles[j].txPath.getMessageIndex(), j)); } if (pContext->bCXPathCreated) { DPrintf(0, ("[%s] Using message %u for controls\n", __FUNCTION__, pContext->CXPath.getMessageIndex())); } else { DPrintf(0, ("[%s] - No control path\n", __FUNCTION__)); } } DEBUG_EXIT_STATUS(2, status); return status; }
/********************************************************** Implements opening of adapter-specific configuration Parameters: Return value: NDIS_HANDLE Handle of open configuration NULL on error ***********************************************************/ NDIS_HANDLE ParaNdis_OpenNICConfiguration(PARANDIS_ADAPTER *pContext) { NDIS_CONFIGURATION_OBJECT co; NDIS_HANDLE cfg; NDIS_STATUS status; DEBUG_ENTRY(2); co.Header.Type = NDIS_OBJECT_TYPE_CONFIGURATION_OBJECT; co.Header.Revision = NDIS_CONFIGURATION_OBJECT_REVISION_1; co.Header.Size = sizeof(co); co.Flags = 0; co.NdisHandle = pContext->MiniportHandle; status = NdisOpenConfigurationEx(&co, &cfg); if (status != NDIS_STATUS_SUCCESS) cfg = NULL; DEBUG_EXIT_STATUS(status == NDIS_STATUS_SUCCESS ? 2 : 0, status); return cfg; }
/********************************************************** Required NDIS handler called at IRQL = PASSIVE_LEVEL Must pause RX and TX Called upon startup, on resume, upon protocols activation ***********************************************************/ static NDIS_STATUS ParaNdis6_Restart( NDIS_HANDLE miniportAdapterContext, PNDIS_MINIPORT_RESTART_PARAMETERS miniportRestartParameters) { NDIS_STATUS status = NDIS_STATUS_SUCCESS; PARANDIS_ADAPTER *pContext = (PARANDIS_ADAPTER *)miniportAdapterContext; DEBUG_ENTRY(0); UNREFERENCED_PARAMETER(miniportRestartParameters); ParaNdis_DebugHistory(pContext, hopSysResume, NULL, 1, 0, 0); ParaNdis6_SendPauseRestart(pContext, FALSE, NULL); ParaNdis6_ReceivePauseRestart(pContext, FALSE, NULL); ParaNdis_DebugHistory(pContext, hopSysResume, NULL, 0, 0, 0); DEBUG_EXIT_STATUS(2, status); return status; }
VOID ParaNdis_Suspend(PARANDIS_ADAPTER *pContext) { DEBUG_ENTRY(0); NdisResetEvent(&pContext->ResetEvent); if (NDIS_STATUS_PENDING != ParaNdis5_StopSend(pContext, TRUE, OnSendStoppedOnReset)) { NdisSetEvent(&pContext->ResetEvent); } NdisWaitEvent(&pContext->ResetEvent, 0); NdisResetEvent(&pContext->ResetEvent); if (NDIS_STATUS_PENDING != ParaNdis5_StopReceive(pContext, TRUE, OnReceiveStoppedOnReset)) { NdisSetEvent(&pContext->ResetEvent); } NdisWaitEvent(&pContext->ResetEvent, 0); NdisResetEvent(&pContext->ResetEvent); DEBUG_EXIT_STATUS(0, 0); }
/********************************************************** Required NDIS handler called at IRQL = PASSIVE_LEVEL Must pause RX and TX Called before halt, on standby, upon protocols activation ***********************************************************/ static NDIS_STATUS ParaNdis6_Pause( NDIS_HANDLE miniportAdapterContext, PNDIS_MINIPORT_PAUSE_PARAMETERS miniportPauseParameters) { NDIS_STATUS status; PARANDIS_ADAPTER *pContext = (PARANDIS_ADAPTER *)miniportAdapterContext; DEBUG_ENTRY(0); UNREFERENCED_PARAMETER(miniportPauseParameters); ParaNdis_DebugHistory(pContext, hopSysPause, NULL, 1, 0, 0); status = ParaNdis6_SendPauseRestart(pContext, TRUE, OnSendPauseComplete); if (status != NDIS_STATUS_PENDING) { status = ParaNdis6_ReceivePauseRestart(pContext, TRUE, OnReceivePauseComplete); } DEBUG_EXIT_STATUS(0, status); if (status == STATUS_SUCCESS) { // pause exit ParaNdis_DebugHistory(pContext, hopSysPause, NULL, 0, 0, 0); } return status; }
VOID ParaNdis_Suspend(PARANDIS_ADAPTER *pContext) { DPrintf(0, ("[%s]%s\n", __FUNCTION__, pContext->bFastSuspendInProcess ? "(Fast)" : "")); NdisResetEvent(&pContext->ResetEvent); if (NDIS_STATUS_PENDING != ParaNdis6_SendPauseRestart(pContext, TRUE, OnSendPauseCompleteOnReset)) { NdisSetEvent(&pContext->ResetEvent); } NdisWaitEvent(&pContext->ResetEvent, 0); if (!pContext->bFastSuspendInProcess) { NdisResetEvent(&pContext->ResetEvent); if (NDIS_STATUS_PENDING != ParaNdis6_ReceivePauseRestart(pContext, TRUE, OnReceivePauseCompleteOnReset)) { NdisSetEvent(&pContext->ResetEvent); } NdisWaitEvent(&pContext->ResetEvent, 0); } else { ParaNdis6_ReceivePauseRestart(pContext, TRUE, NULL); } DEBUG_EXIT_STATUS(0, 0); }
/****************************************************** Required NDIS procedure Allocates and initializes adapter context Finally sets send and receive to Enabled state and reports connect Returns: NDIS_STATUS SUCCESS or some error code *******************************************************/ static NDIS_STATUS ParaNdis5_Initialize(OUT PNDIS_STATUS OpenErrorStatus, OUT PUINT SelectedMediumIndex, IN PNDIS_MEDIUM MediumArray, IN UINT MediumArraySize, IN NDIS_HANDLE MiniportAdapterHandle, IN NDIS_HANDLE WrapperConfigurationContext) { NDIS_STATUS status = NDIS_STATUS_UNSUPPORTED_MEDIA; PARANDIS_ADAPTER *pContext = NULL; UINT i; for(i = 0; i < MediumArraySize; ++i) { if(MediumArray[i] == NdisMedium802_3) { *SelectedMediumIndex = i; status = NDIS_STATUS_SUCCESS; break; } } if (status == NDIS_STATUS_SUCCESS) { pContext = (PARANDIS_ADAPTER *)ParaNdis_AllocateMemory(NULL, sizeof(PARANDIS_ADAPTER)); if (!pContext) { status = NDIS_STATUS_RESOURCES; } } if (status == NDIS_STATUS_SUCCESS) { PVOID pResourceList = &status; UINT uSize = 0; NdisZeroMemory(pContext, sizeof(PARANDIS_ADAPTER)); pContext->ulUniqueID = InterlockedIncrement(&gID); pContext->DriverHandle = DriverHandle; pContext->MiniportHandle = MiniportAdapterHandle; pContext->WrapperConfigurationHandle = WrapperConfigurationContext; NdisMQueryAdapterResources(&status, WrapperConfigurationContext, pResourceList, &uSize); if (uSize > 0) pResourceList = ParaNdis_AllocateMemory(MiniportAdapterHandle, uSize); else pResourceList = NULL; if (!pResourceList) status = uSize > 0 ? NDIS_STATUS_RESOURCES : NDIS_STATUS_FAILURE; else { ULONG attributes; attributes = NDIS_ATTRIBUTE_DESERIALIZE | NDIS_ATTRIBUTE_BUS_MASTER; // in XP SP2, if this flag is NOT set, the NDIS halts miniport // upon transition to S1..S4. // it seems that XP SP3 ignores it and always sends SET_POWER to D3 #ifndef NO_XP_POWER_MANAGEMENT attributes |= NDIS_ATTRIBUTE_NO_HALT_ON_SUSPEND; #endif #ifdef NDIS50_MINIPORT //TODO: this is wrong, I think // this API is for XP and // it should be used only if you never need virtual addresses of sent buffers // so I comment it out //attributes |= NDIS_ATTRIBUTE_USES_SAFE_BUFFER_APIS; #endif NdisMSetAttributesEx( MiniportAdapterHandle, pContext, 0, attributes, NdisInterfacePci); NdisMQueryAdapterResources(&status, WrapperConfigurationContext, pResourceList, &uSize); status = ParaNdis_InitializeContext(pContext, (PNDIS_RESOURCE_LIST)pResourceList); NdisFreeMemory(pResourceList, 0, 0); } } if (status == NDIS_STATUS_SUCCESS) { status = ParaNdis_FinishInitialization(pContext); if (status == NDIS_STATUS_SUCCESS) { #ifdef NDIS50_MINIPORT NdisMRegisterAdapterShutdownHandler( MiniportAdapterHandle, pContext, (ADAPTER_SHUTDOWN_HANDLER)ParaNdis5_Shutdown); #endif //NDIS50_MINIPORT ParaNdis_DebugRegisterMiniport(pContext, TRUE); ParaNdis_IndicateConnect(pContext, FALSE, TRUE); ParaNdis5_StopSend(pContext, FALSE, NULL); ParaNdis5_StopReceive(pContext, FALSE, NULL); if (!pContext->ulMilliesToConnect) { ParaNdis_ReportLinkStatus(pContext, FALSE); } else { NdisSetTimer(&pContext->ConnectTimer, pContext->ulMilliesToConnect); } } else { ParaNdis_CleanupContext(pContext); } } if (status != NDIS_STATUS_SUCCESS && pContext) { NdisFreeMemory(pContext, 0, 0); } DEBUG_EXIT_STATUS(0, status); return status; }
/************************************************************* Driver's entry point Parameters: as usual Return value: SUCCESS or error code *************************************************************/ NDIS_STATUS DriverEntry(PVOID DriverObject,PVOID RegistryPath) { NDIS_STATUS status; NDIS_MINIPORT_CHARACTERISTICS chars; ParaNdis_DebugInitialize(DriverObject, RegistryPath); status = NDIS_STATUS_FAILURE; DEBUG_ENTRY(0); _LogOutString(0, __DATE__ " " __TIME__); NdisMInitializeWrapper(&DriverHandle, DriverObject, RegistryPath, NULL ); if (DriverHandle) { NdisZeroMemory(&chars, sizeof(chars)); //NDIS version of the miniport chars.MajorNdisVersion = NDIS_MINIPORT_MAJOR_VERSION; chars.MinorNdisVersion = NDIS_MINIPORT_MINOR_VERSION; //Init and destruction chars.InitializeHandler = ParaNdis5_Initialize; chars.HaltHandler = ParaNdis5_Halt; //Interrupt and DPC handling chars.HandleInterruptHandler = ParaNdis5_HandleDPC; chars.ISRHandler = ParaNdis5_MiniportISR; //Packet transfer - send path and notification on the send packet chars.SendPacketsHandler = ParaNdis5_SendPackets; chars.ReturnPacketHandler = ParaNdis5_ReturnPacket; //OID set\get chars.SetInformationHandler = ParaNdis5_SetOID; chars.QueryInformationHandler = ParaNdis5_QueryOID; //Reset chars.ResetHandler = ParaNdis5_Reset; chars.CheckForHangHandler = ParaNdis5_CheckForHang; //optional #ifdef NDIS51_MINIPORT chars.CancelSendPacketsHandler = ParaNdis5_CancelSendPackets; chars.PnPEventNotifyHandler = ParaNdis5_PnPEventNotify; chars.AdapterShutdownHandler = ParaNdis5_Shutdown; #endif status = NdisMRegisterMiniport( DriverHandle, &chars, sizeof(chars)); } if (status == NDIS_STATUS_SUCCESS) { NdisMRegisterUnloadHandler(DriverHandle, ParaVirtualNICUnload); } else if (DriverHandle) { DPrintf(0, ("NdisMRegisterMiniport failed")); NdisTerminateWrapper(DriverHandle, NULL); } else { DPrintf(0, ("NdisMInitializeWrapper failed")); } DEBUG_EXIT_STATUS(status ? 0 : 4, status); return status; }
/********************************************************** NDIS6-related final initialization: Installing interrupt handler Allocate buffer list pool Parameters: Return value: ***********************************************************/ NDIS_STATUS ParaNdis_FinishSpecificInitialization(PARANDIS_ADAPTER *pContext) { NDIS_STATUS status = NDIS_STATUS_SUCCESS; NET_BUFFER_LIST_POOL_PARAMETERS PoolParams; NDIS_MINIPORT_INTERRUPT_CHARACTERISTICS mic; DEBUG_ENTRY(0); NdisZeroMemory(&mic, sizeof(mic)); mic.Header.Type = NDIS_OBJECT_TYPE_MINIPORT_INTERRUPT; mic.Header.Revision = NDIS_MINIPORT_INTERRUPT_REVISION_1; mic.Header.Size = NDIS_SIZEOF_MINIPORT_INTERRUPT_CHARACTERISTICS_REVISION_1; mic.DisableInterruptHandler = MiniportDisableInterruptEx; mic.EnableInterruptHandler = MiniportEnableInterruptEx; mic.InterruptDpcHandler = MiniportInterruptDPC; mic.InterruptHandler = MiniportInterrupt; if (pContext->bUsingMSIX) { mic.MsiSupported = TRUE; mic.MsiSyncWithAllMessages = TRUE; mic.EnableMessageInterruptHandler = MiniportEnableMSIInterrupt; mic.DisableMessageInterruptHandler = MiniportDisableMSIInterrupt; mic.MessageInterruptHandler = MiniportMSIInterrupt; mic.MessageInterruptDpcHandler = MiniportMSIInterruptDpc; } PoolParams.Header.Type = NDIS_OBJECT_TYPE_DEFAULT; PoolParams.Header.Size = sizeof(PoolParams); PoolParams.Header.Revision = NET_BUFFER_LIST_POOL_PARAMETERS_REVISION_1; PoolParams.ProtocolId = NDIS_PROTOCOL_ID_DEFAULT; PoolParams.fAllocateNetBuffer = TRUE; PoolParams.ContextSize = 0; PoolParams.PoolTag = PARANDIS_MEMORY_TAG; PoolParams.DataSize = 0; pContext->BufferListsPool = NdisAllocateNetBufferListPool(pContext->MiniportHandle, &PoolParams); if (!pContext->BufferListsPool) { status = NDIS_STATUS_RESOURCES; } if (status == NDIS_STATUS_SUCCESS) { status = NdisMRegisterInterruptEx(pContext->MiniportHandle, pContext, &mic, &pContext->InterruptHandle); } if (pContext->bUsingMSIX) { DPrintf(0, ("[%s] MSIX message table %savailable, count = %u\n", __FUNCTION__, (mic.MessageInfoTable == nullptr ? "not " : ""), (mic.MessageInfoTable == nullptr ? 0 : mic.MessageInfoTable->MessageCount))); } else { DPrintf(0, ("[%s] Not using MSIX\n", __FUNCTION__)); } if (status == NDIS_STATUS_SUCCESS) { NDIS_SG_DMA_DESCRIPTION sgDesc; sgDesc.Header.Type = NDIS_OBJECT_TYPE_SG_DMA_DESCRIPTION; sgDesc.Header.Revision = NDIS_SG_DMA_DESCRIPTION_REVISION_1; sgDesc.Header.Size = sizeof(sgDesc); sgDesc.Flags = NDIS_SG_DMA_64_BIT_ADDRESS; sgDesc.MaximumPhysicalMapping = 0x10000; // 64K sgDesc.ProcessSGListHandler = ProcessSGListHandler; sgDesc.SharedMemAllocateCompleteHandler = SharedMemAllocateCompleteHandler; sgDesc.ScatterGatherListSize = 0; // OUT value status = NdisMRegisterScatterGatherDma(pContext->MiniportHandle, &sgDesc, &pContext->DmaHandle); if (status != NDIS_STATUS_SUCCESS) { DPrintf(0, ("[%s] ERROR: NdisMRegisterScatterGatherDma failed (%X)!\n", __FUNCTION__, status)); } else { DPrintf(0, ("[%s] SG recommended size %d\n", __FUNCTION__, sgDesc.ScatterGatherListSize)); } } if (status == NDIS_STATUS_SUCCESS) { if (NDIS_CONNECT_MESSAGE_BASED == mic.InterruptType) { pContext->pMSIXInfoTable = mic.MessageInfoTable; } else if (pContext->bUsingMSIX) { DPrintf(0, ("[%s] ERROR: Interrupt type %d, message table %p\n", __FUNCTION__, mic.InterruptType, mic.MessageInfoTable)); status = NDIS_STATUS_RESOURCE_CONFLICT; } ParaNdis6_ApplyOffloadPersistentConfiguration(pContext); DebugParseOffloadBits(); } DEBUG_EXIT_STATUS(0, status); return status; }
/********************************************************** Required NDIS handler Initialize adapter context, prepare it for operation, set in PAUSED STATE Return value: SUCCESS or kind of error ***********************************************************/ static NDIS_STATUS ParaNdis6_Initialize( NDIS_HANDLE miniportAdapterHandle, NDIS_HANDLE miniportDriverContext, PNDIS_MINIPORT_INIT_PARAMETERS miniportInitParameters) { NDIS_MINIPORT_ADAPTER_ATTRIBUTES miniportAttributes; NDIS_STATUS status = NDIS_STATUS_SUCCESS; BOOLEAN bNoPauseOnSuspend = FALSE; PARANDIS_ADAPTER *pContext; UNREFERENCED_PARAMETER(miniportDriverContext); DEBUG_ENTRY(0); #pragma warning( suppress: 28197) /* allocate context structure */ pContext = (PARANDIS_ADAPTER *) NdisAllocateMemoryWithTagPriority( miniportAdapterHandle, sizeof(PARANDIS_ADAPTER), PARANDIS_MEMORY_TAG, NormalPoolPriority); /* This call is for Static Driver Verifier only - has no real functionality*/ __sdv_save_adapter_context(pContext); if (!pContext) { DPrintf(0, ("[%s] ERROR: Memory allocation failed!\n", __FUNCTION__)); status = NDIS_STATUS_RESOURCES; } if (status == NDIS_STATUS_SUCCESS) { /* set mandatory fields which Common use */ NdisZeroMemory(pContext, sizeof(PARANDIS_ADAPTER)); pContext->ulUniqueID = NdisInterlockedIncrement(&gID); pContext->DriverHandle = DriverHandle; pContext->MiniportHandle = miniportAdapterHandle; } if (status == NDIS_STATUS_SUCCESS) { NdisZeroMemory(&miniportAttributes, sizeof(miniportAttributes)); miniportAttributes.RegistrationAttributes.Header.Type = NDIS_OBJECT_TYPE_MINIPORT_ADAPTER_REGISTRATION_ATTRIBUTES; miniportAttributes.RegistrationAttributes.Header.Revision = NDIS_MINIPORT_ADAPTER_REGISTRATION_ATTRIBUTES_REVISION_1; miniportAttributes.RegistrationAttributes.Header.Size = NDIS_SIZEOF_MINIPORT_ADAPTER_REGISTRATION_ATTRIBUTES_REVISION_1; miniportAttributes.RegistrationAttributes.MiniportAdapterContext = pContext; miniportAttributes.RegistrationAttributes.AttributeFlags = // actual for USB // NDIS_MINIPORT_ATTRIBUTES_SURPRISE_REMOVE_OK NDIS_MINIPORT_ATTRIBUTES_HARDWARE_DEVICE | NDIS_MINIPORT_ATTRIBUTES_BUS_MASTER; #ifndef NO_VISTA_POWER_MANAGEMENT miniportAttributes.RegistrationAttributes.AttributeFlags |= NDIS_MINIPORT_ATTRIBUTES_NO_HALT_ON_SUSPEND; #endif #if NDIS_SUPPORT_NDIS630 miniportAttributes.RegistrationAttributes.AttributeFlags |= NDIS_MINIPORT_ATTRIBUTES_NO_PAUSE_ON_SUSPEND; bNoPauseOnSuspend = TRUE; #endif miniportAttributes.RegistrationAttributes.CheckForHangTimeInSeconds = 4; miniportAttributes.RegistrationAttributes.InterfaceType = NdisInterfacePci; status = NdisMSetMiniportAttributes(miniportAdapterHandle, &miniportAttributes); if (status != NDIS_STATUS_SUCCESS) { DPrintf(0, ("[%s] ERROR: NdisMSetMiniportAttributes 1 failed (%X)!\n", __FUNCTION__, status)); } } if (status == NDIS_STATUS_SUCCESS) { /* prepare statistics struct for further reports */ pContext->Statistics.Header.Type = NDIS_OBJECT_TYPE_DEFAULT; pContext->Statistics.Header.Revision = NDIS_STATISTICS_INFO_REVISION_1; pContext->Statistics.Header.Size = NDIS_SIZEOF_STATISTICS_INFO_REVISION_1; /* let Common do all the rest */ status = ParaNdis_InitializeContext(pContext, miniportInitParameters->AllocatedResources); if (status != NDIS_STATUS_SUCCESS) { DPrintf(0, ("[%s] ERROR: ParaNdis6_InitializeContext failed (%X)!\n", __FUNCTION__, status)); } pContext->bNoPauseOnSuspend = bNoPauseOnSuspend; } if (status == NDIS_STATUS_SUCCESS) { ULONG i; NDIS_PNP_CAPABILITIES power60Caps; #if NDIS_SUPPORT_NDIS620 NDIS_PM_CAPABILITIES power620Caps; #endif #ifdef NO_VISTA_POWER_MANAGEMENT pPowerCaps = NULL; #endif ParaNdis_FillPowerCapabilities(&power60Caps); NdisZeroMemory(&miniportAttributes, sizeof(miniportAttributes)); miniportAttributes.GeneralAttributes.Header.Type = NDIS_OBJECT_TYPE_MINIPORT_ADAPTER_GENERAL_ATTRIBUTES; miniportAttributes.GeneralAttributes.Header.Revision = NDIS_MINIPORT_ADAPTER_GENERAL_ATTRIBUTES_REVISION_1; miniportAttributes.GeneralAttributes.Header.Size = NDIS_SIZEOF_MINIPORT_ADAPTER_GENERAL_ATTRIBUTES_REVISION_1; #if NDIS_SUPPORT_NDIS620 miniportAttributes.GeneralAttributes.Header.Revision = NDIS_MINIPORT_ADAPTER_GENERAL_ATTRIBUTES_REVISION_2; miniportAttributes.GeneralAttributes.Header.Size = NDIS_SIZEOF_MINIPORT_ADAPTER_GENERAL_ATTRIBUTES_REVISION_2; miniportAttributes.GeneralAttributes.PowerManagementCapabilitiesEx = &power620Caps; ParaNdis6_Fill620PowerCapabilities(&power620Caps); #else miniportAttributes.GeneralAttributes.PowerManagementCapabilities = &power60Caps; #endif miniportAttributes.GeneralAttributes.MediaType = NdisMedium802_3; miniportAttributes.GeneralAttributes.PhysicalMediumType = NdisPhysicalMedium802_3; miniportAttributes.GeneralAttributes.MtuSize = pContext->MaxPacketSize.nMaxDataSize; miniportAttributes.GeneralAttributes.LookaheadSize = pContext->MaxPacketSize.nMaxFullSizeOS; miniportAttributes.GeneralAttributes.MaxXmitLinkSpeed = miniportAttributes.GeneralAttributes.MaxRcvLinkSpeed = PARANDIS_FORMAL_LINK_SPEED; miniportAttributes.GeneralAttributes.MediaConnectState = pContext->bConnected ? MediaConnectStateConnected : MediaConnectStateDisconnected; miniportAttributes.GeneralAttributes.XmitLinkSpeed = miniportAttributes.GeneralAttributes.RcvLinkSpeed = pContext->bConnected ? PARANDIS_FORMAL_LINK_SPEED : NDIS_LINK_SPEED_UNKNOWN; miniportAttributes.GeneralAttributes.MediaDuplexState = MediaDuplexStateFull; miniportAttributes.GeneralAttributes.MacOptions = NDIS_MAC_OPTION_COPY_LOOKAHEAD_DATA | /* NIC has no internal loopback support */ NDIS_MAC_OPTION_TRANSFERS_NOT_PEND | /* Must be set since using NdisMIndicateReceivePacket */ NDIS_MAC_OPTION_NO_LOOPBACK; /* NIC has no internal loopback support */ if (IsPrioritySupported(pContext)) miniportAttributes.GeneralAttributes.MacOptions |= NDIS_MAC_OPTION_8021P_PRIORITY; if (IsVlanSupported(pContext)) miniportAttributes.GeneralAttributes.MacOptions |= NDIS_MAC_OPTION_8021Q_VLAN; miniportAttributes.GeneralAttributes.SupportedPacketFilters = PARANDIS_PACKET_FILTERS; miniportAttributes.GeneralAttributes.MaxMulticastListSize = PARANDIS_MULTICAST_LIST_SIZE; miniportAttributes.GeneralAttributes.MacAddressLength = ETH_LENGTH_OF_ADDRESS; #if PARANDIS_SUPPORT_RSS if(pContext->bRSSOffloadSupported) { miniportAttributes.GeneralAttributes.RecvScaleCapabilities = ParaNdis6_RSSCreateConfiguration( &pContext->RSSParameters, &pContext->RSSCapabilities, pContext->RSSMaxQueuesNumber); pContext->bRSSInitialized = TRUE; } #endif for(i = 0; i < ARRAYSIZE(pContext->ReceiveQueues); i++) { NdisAllocateSpinLock(&pContext->ReceiveQueues[i].Lock); InitializeListHead(&pContext->ReceiveQueues[i].BuffersList); pContext->ReceiveQueues[i].BatchReceiveArray = ParaNdis_AllocateMemory(pContext, sizeof(*pContext->ReceiveQueues[i].BatchReceiveArray)*pContext->NetMaxReceiveBuffers); if(!pContext->ReceiveQueues[i].BatchReceiveArray) { pContext->ReceiveQueues[i].BatchReceiveArray = &pContext->ReceiveQueues[i].BatchReceiveEmergencyItem; pContext->ReceiveQueues[i].BatchReceiveArraySize = 1; } else { pContext->ReceiveQueues[i].BatchReceiveArraySize = pContext->NetMaxReceiveBuffers; } } pContext->ReceiveQueuesInitialized = TRUE; miniportAttributes.GeneralAttributes.AccessType = NET_IF_ACCESS_BROADCAST; miniportAttributes.GeneralAttributes.DirectionType = NET_IF_DIRECTION_SENDRECEIVE; miniportAttributes.GeneralAttributes.IfType = IF_TYPE_ETHERNET_CSMACD; miniportAttributes.GeneralAttributes.IfConnectorPresent = TRUE; miniportAttributes.GeneralAttributes.ConnectionType = NET_IF_CONNECTION_DEDICATED; ETH_COPY_NETWORK_ADDRESS(miniportAttributes.GeneralAttributes.PermanentMacAddress, pContext->PermanentMacAddress); ETH_COPY_NETWORK_ADDRESS(miniportAttributes.GeneralAttributes.CurrentMacAddress, pContext->CurrentMacAddress); ParaNdis6_GetSupportedOid(&miniportAttributes.GeneralAttributes); /* update also SupportedStatistics in ready to use statistics block */ pContext->Statistics.SupportedStatistics = ParaNdis6_GetSupportedStatisticsFlags(); status = NdisMSetMiniportAttributes(miniportAdapterHandle, &miniportAttributes); if (status != NDIS_STATUS_SUCCESS) { DPrintf(0, ("[%s] ERROR: NdisMSetMiniportAttributes 2 failed (%X)!\n", __FUNCTION__, status)); } } if (pContext && status != NDIS_STATUS_SUCCESS && status != NDIS_STATUS_PENDING) { // no need to cleanup NdisFreeMemory(pContext, 0, 0); pContext = NULL; } if (pContext && status == NDIS_STATUS_SUCCESS) { status = ParaNdis_FinishInitialization(pContext); if (status != NDIS_STATUS_SUCCESS) { ParaNdis_CleanupContext(pContext); NdisFreeMemory(pContext, 0, 0); pContext = NULL; } } if (pContext && status == NDIS_STATUS_SUCCESS) { if (NDIS_STATUS_SUCCESS == ParaNdis6_GetRegistrationOffloadInfo(pContext, &miniportAttributes.OffloadAttributes)) status = NdisMSetMiniportAttributes(miniportAdapterHandle, &miniportAttributes); if (status != NDIS_STATUS_SUCCESS) { DPrintf(0, ("[%s] ERROR: NdisMSetMiniportAttributes 3 failed (%X)!\n", __FUNCTION__, status)); } } if (pContext && status == NDIS_STATUS_SUCCESS) { ParaNdis_DebugRegisterMiniport(pContext, TRUE); } DEBUG_EXIT_STATUS(status ? 0 : 2, status); return status; }
VOID ParaNdis_Resume(PARANDIS_ADAPTER *pContext) { ParaNdis5_StopSend(pContext, FALSE, NULL); ParaNdis5_StopReceive(pContext, FALSE, NULL); DEBUG_EXIT_STATUS(0, 0); }
NTSTATUS DriverEntry(PDRIVER_OBJECT pDriverObject, PUNICODE_STRING pRegistryPath) { NDIS_STATUS status = NDIS_STATUS_FAILURE; NDIS_MINIPORT_DRIVER_CHARACTERISTICS chars; #ifdef DEBUG_TIMING LARGE_INTEGER TickCount; LARGE_INTEGER SysTime; #endif DEBUG_TIMING ParaNdis_DebugInitialize(); DEBUG_ENTRY(0); DPrintf(0, (__DATE__ " " __TIME__ "built %d.%d\n", NDIS_MINIPORT_MAJOR_VERSION, NDIS_MINIPORT_MINOR_VERSION)); #ifdef DEBUG_TIMING KeQueryTickCount(&TickCount); NdisGetCurrentSystemTime(&SysTime); DPrintf(0, ("\n%s>> CPU #%d, perf-counter %I64d, tick count %I64d, NDIS_sys_time %I64d\n", __FUNCTION__, KeGetCurrentProcessorNumber(), KeQueryPerformanceCounter(NULL).QuadPart,TickCount.QuadPart, SysTime.QuadPart)); #endif NdisZeroMemory(&chars, sizeof(chars)); chars.Header.Type = NDIS_OBJECT_TYPE_MINIPORT_DRIVER_CHARACTERISTICS; chars.Header.Revision = NDIS_MINIPORT_DRIVER_CHARACTERISTICS_REVISION_1; chars.Header.Size = NDIS_SIZEOF_MINIPORT_DRIVER_CHARACTERISTICS_REVISION_1; chars.MajorNdisVersion = NDIS_MINIPORT_MAJOR_VERSION; chars.MinorNdisVersion = NDIS_MINIPORT_MINOR_VERSION; /* stupid thing, they are at least short */ chars.MajorDriverVersion = (UCHAR)(PARANDIS_MAJOR_DRIVER_VERSION & 0xFF); chars.MinorDriverVersion = (UCHAR)(PARANDIS_MINOR_DRIVER_VERSION & 0xFF); // possible value for regular miniport NDIS_WDM_DRIVER - for USB or 1394 // chars.Flags = 0; chars.InitializeHandlerEx = ParaNdis6_Initialize; chars.HaltHandlerEx = ParaNdis6_Halt; chars.UnloadHandler = ParaNdis6_Unload; chars.PauseHandler = ParaNdis6_Pause; chars.RestartHandler = ParaNdis6_Restart; chars.OidRequestHandler = ParaNdis6_OidRequest; chars.CancelOidRequestHandler = ParaNdis6_OidCancelRequest; chars.SendNetBufferListsHandler = ParaNdis6_SendNetBufferLists; chars.CancelSendHandler = ParaNdis6_CancelSendNetBufferLists; chars.ReturnNetBufferListsHandler = ParaNdis6_ReturnNetBufferLists; chars.CheckForHangHandlerEx = ParaNdis6_CheckForHang; chars.ResetHandlerEx = ParaNdis6_Reset; chars.ShutdownHandlerEx = ParaNdis6_AdapterShutdown; chars.DevicePnPEventNotifyHandler = ParaNdis6_DevicePnPEvent; chars.SetOptionsHandler = ParaNdis6_SetOptions; #if NDIS_SUPPORT_NDIS61 chars.Header.Revision = NDIS_MINIPORT_DRIVER_CHARACTERISTICS_REVISION_2; chars.Header.Size = NDIS_SIZEOF_MINIPORT_DRIVER_CHARACTERISTICS_REVISION_2; chars.DirectOidRequestHandler = ParaNdis6x_DirectOidRequest; chars.CancelDirectOidRequestHandler = ParaNdis6x_CancelDirectOidRequest; #endif status = NdisMRegisterMiniportDriver( pDriverObject, pRegistryPath, NULL, &chars, &DriverHandle); if (status == NDIS_STATUS_SUCCESS) { RetrieveDriverConfiguration(); } DEBUG_EXIT_STATUS(status ? 0 : 4, status); return status; }