pRxNetDescriptor CParaNdisRX::CreateRxDescriptorOnInit() { //For RX packets we allocate following pages // 1 page for virtio header and indirect buffers array // X pages needed to fit maximal length buffer of data // The assumption is virtio header and indirect buffers array fit 1 page ULONG ulNumPages = m_Context->MaxPacketSize.nMaxDataSizeHwRx / PAGE_SIZE + 2; pRxNetDescriptor p = (pRxNetDescriptor)ParaNdis_AllocateMemory(m_Context, sizeof(*p)); if (p == NULL) return NULL; NdisZeroMemory(p, sizeof(*p)); p->BufferSGArray = (struct VirtIOBufferDescriptor *) ParaNdis_AllocateMemory(m_Context, sizeof(*p->BufferSGArray) * ulNumPages); if (p->BufferSGArray == NULL) goto error_exit; p->PhysicalPages = (tCompletePhysicalAddress *) ParaNdis_AllocateMemory(m_Context, sizeof(*p->PhysicalPages) * ulNumPages); if (p->PhysicalPages == NULL) goto error_exit; for (p->PagesAllocated = 0; p->PagesAllocated < ulNumPages; p->PagesAllocated++) { p->PhysicalPages[p->PagesAllocated].size = PAGE_SIZE; if (!InitialAllocatePhysicalMemory(&p->PhysicalPages[p->PagesAllocated])) goto error_exit; p->BufferSGArray[p->PagesAllocated].physAddr = p->PhysicalPages[p->PagesAllocated].Physical; p->BufferSGArray[p->PagesAllocated].length = PAGE_SIZE; } //First page is for virtio header, size needs to be adjusted correspondingly p->BufferSGArray[0].length = m_Context->nVirtioHeaderSize; //Pre-cache indirect area addresses p->IndirectArea.Physical.QuadPart = p->PhysicalPages[0].Physical.QuadPart + m_Context->nVirtioHeaderSize; p->IndirectArea.Virtual = RtlOffsetToPointer(p->PhysicalPages[0].Virtual, m_Context->nVirtioHeaderSize); p->IndirectArea.size = PAGE_SIZE - m_Context->nVirtioHeaderSize; if (!ParaNdis_BindRxBufferToPacket(m_Context, p)) goto error_exit; return p; error_exit: ParaNdis_FreeRxBufferDescriptor(m_Context, p); return NULL; }
/********************************************************** NDIS5.X handler of power management ***********************************************************/ NDIS_STATUS ParaNdis_OnSetPower(PARANDIS_ADAPTER *pContext, tOidDesc *pOid) { NDIS_STATUS status; NDIS_DEVICE_POWER_STATE newState; DEBUG_ENTRY(0); status = ParaNdis_OidSetCopy(pOid, &newState, sizeof(newState)); if (status == NDIS_STATUS_SUCCESS) { tPowerWorkItem *pwi = ParaNdis_AllocateMemory(pContext, sizeof(tPowerWorkItem)); status = NDIS_STATUS_FAILURE; if (pwi) { pwi->pContext = pContext; pwi->state = newState; NdisInitializeWorkItem(&pwi->wi, OnSetPowerWorkItem, pwi); if (NdisScheduleWorkItem(&pwi->wi) == NDIS_STATUS_SUCCESS) { status = NDIS_STATUS_PENDING; } else NdisFreeMemory(pwi, 0, 0); } } return status; }
/************************************************************* Required NDIS procedure Called when some procedure (like OID handler) returns PENDING and does not complete or when CheckForHang return TRUE *************************************************************/ static NDIS_STATUS ParaNdis5_Reset( OUT PBOOLEAN AddressingReset, IN NDIS_HANDLE MiniportAdapterContext) { NDIS_STATUS status; tGeneralWorkItem *pwi; PARANDIS_ADAPTER *pContext = (PARANDIS_ADAPTER *)MiniportAdapterContext; DEBUG_ENTRY(0); ParaNdis_DebugHistory(pContext, hopSysReset, NULL, 1, 0, 0); status = NDIS_STATUS_FAILURE; pwi = ParaNdis_AllocateMemory(pContext, sizeof(tGeneralWorkItem)); if (pwi) { pwi->pContext = pContext; NdisInitializeWorkItem(&pwi->wi, OnResetWorkItem, pwi); if (NdisScheduleWorkItem(&pwi->wi) == NDIS_STATUS_SUCCESS) { status = NDIS_STATUS_PENDING; } else { NdisFreeMemory(pwi, 0, 0); } } if (status != NDIS_STATUS_PENDING) { ParaNdis_DebugHistory(pContext, hopSysReset, NULL, 0, status, 0); } return 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; }
/******************************************************** Allocate and fill our capabilities, dependent on registry setting Note than NDIS test of WLK1.2 and 1.3 fail (offloadmisc) if CS capability indicated and passes if only LSO indicated ********************************************************/ NDIS_STATUS CreateOffloadInfo5Internal( PARANDIS_ADAPTER *pContext, PVOID *ppInfo, PULONG pulSize, PCCHAR reason, NDIS_TASK_OFFLOAD_HEADER *pHeader) { NDIS_STATUS status = NDIS_STATUS_RESOURCES; ULONG size = sizeof(NDIS_TASK_OFFLOAD_HEADER) + sizeof(NDIS_TASK_OFFLOAD) + sizeof(NDIS_TASK_TCP_IP_CHECKSUM) + sizeof(NDIS_TASK_OFFLOAD) + sizeof(NDIS_TASK_TCP_LARGE_SEND); *ppInfo = ParaNdis_AllocateMemory(pContext, size); if (*ppInfo) { ULONG flags = 0; NDIS_TASK_TCP_IP_CHECKSUM cs; NDIS_TASK_TCP_LARGE_SEND lso; flags |= GetTcpIpCheckSumCapabilities(pContext, &cs) ? 2 : 0; flags |= GetLargeSendCapabilities(pContext, &lso) ? 1 : 0; if (flags) { NDIS_TASK_OFFLOAD_HEADER *ph; NDIS_TASK_OFFLOAD *pto; UINT i = 0; ULONG *pOffset; PVOID base; *pulSize = size; NdisZeroMemory(*ppInfo, size); ph = (NDIS_TASK_OFFLOAD_HEADER *)*ppInfo; *ph = *pHeader; pto = (NDIS_TASK_OFFLOAD *)(ph + 1); base = ph; pOffset = &ph->OffsetFirstTask; ph->OffsetFirstTask = 0; do { if (flags & (1 << i)) { flags &= ~(1 << i); pto->Version = NDIS_TASK_OFFLOAD_VERSION; pto->Size = sizeof(*pto); *pOffset = RtlPointerToOffset(base, pto); base = pto; pOffset = &pto->OffsetNextTask; switch(i) { case 1: { NDIS_TASK_TCP_IP_CHECKSUM *pcs = (NDIS_TASK_TCP_IP_CHECKSUM *)pto->TaskBuffer; pto->Task = TcpIpChecksumNdisTask; pto->TaskBufferLength = sizeof(*pcs); NdisMoveMemory(pcs, &cs, sizeof(cs)); pto = (NDIS_TASK_OFFLOAD *)(pcs + 1); break; } case 0: { NDIS_TASK_TCP_LARGE_SEND *pls = (NDIS_TASK_TCP_LARGE_SEND *)pto->TaskBuffer; pto->Task = TcpLargeSendNdisTask; pto->TaskBufferLength = sizeof(*pls); NdisMoveMemory(pls, &lso, sizeof(lso)); pto = (NDIS_TASK_OFFLOAD *)(pls + 1); break; } default: break; } } ++i; } while (flags); status = ParseOffload(pContext, ph, size, FALSE, reason, FALSE); } else { NdisFreeMemory(*ppInfo, 0, 0); *ppInfo = NULL; status = NDIS_STATUS_NOT_SUPPORTED; } } return status; }
/****************************************************** 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; }
/********************************************************** 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; }
pRxNetDescriptor CParaNdisRX::CreateRxDescriptorOnInit() { //For RX packets we allocate following pages // 1 page for virtio header and indirect buffers array // X pages needed to fit maximal length buffer of data // The assumption is virtio header and indirect buffers array fit 1 page ULONG ulNumPages = m_Context->MaxPacketSize.nMaxDataSizeHwRx / PAGE_SIZE + 2; pRxNetDescriptor p = (pRxNetDescriptor)ParaNdis_AllocateMemory(m_Context, sizeof(*p)); if (p == NULL) return NULL; NdisZeroMemory(p, sizeof(*p)); p->BufferSGArray = (struct VirtIOBufferDescriptor *) ParaNdis_AllocateMemory(m_Context, sizeof(*p->BufferSGArray) * ulNumPages); if (p->BufferSGArray == NULL) goto error_exit; p->PhysicalPages = (tCompletePhysicalAddress *) ParaNdis_AllocateMemory(m_Context, sizeof(*p->PhysicalPages) * ulNumPages); if (p->PhysicalPages == NULL) goto error_exit; p->BufferSGLength = 0; while (ulNumPages > 0) { // Allocate the first page separately, the rest can be one contiguous block ULONG ulPagesToAlloc = (p->BufferSGLength == 0 ? 1 : ulNumPages); while (!ParaNdis_InitialAllocatePhysicalMemory( m_Context, PAGE_SIZE * ulPagesToAlloc, &p->PhysicalPages[p->BufferSGLength])) { // Retry with half the pages if (ulPagesToAlloc == 1) goto error_exit; else ulPagesToAlloc /= 2; } p->BufferSGArray[p->BufferSGLength].physAddr = p->PhysicalPages[p->BufferSGLength].Physical; p->BufferSGArray[p->BufferSGLength].length = p->PhysicalPages[p->BufferSGLength].size; ulNumPages -= ulPagesToAlloc; p->BufferSGLength++; } //First page is for virtio header, size needs to be adjusted correspondingly p->BufferSGArray[0].length = m_Context->nVirtioHeaderSize; ULONG indirectAreaOffset = ALIGN_UP(m_Context->nVirtioHeaderSize, ULONGLONG); //Pre-cache indirect area addresses p->IndirectArea.Physical.QuadPart = p->PhysicalPages[0].Physical.QuadPart + indirectAreaOffset; p->IndirectArea.Virtual = RtlOffsetToPointer(p->PhysicalPages[0].Virtual, indirectAreaOffset); p->IndirectArea.size = PAGE_SIZE - indirectAreaOffset; if (!ParaNdis_BindRxBufferToPacket(m_Context, p)) goto error_exit; return p; error_exit: ParaNdis_FreeRxBufferDescriptor(m_Context, p); return NULL; }