/* * PROJECT: ReactOS nVidia nForce Ethernet Controller Driver * LICENSE: GPL-2.0-or-later (https://spdx.org/licenses/GPL-2.0-or-later) * PURPOSE: Miniport initialization helper routines * COPYRIGHT: Copyright 2021-2022 Dmitry Borisov */ /* INCLUDES *******************************************************************/ #include "nvnet.h" #define NDEBUG #include "debug.h" /* FUNCTIONS ******************************************************************/ static CODE_SEG("PAGE") VOID QueryInteger( _In_ NDIS_HANDLE ConfigurationHandle, _In_ PCWSTR EntryName, _Out_ PULONG EntryContext, _In_ ULONG DefaultValue, _In_ ULONG Minimum, _In_ ULONG Maximum) { NDIS_STATUS Status; UNICODE_STRING Keyword; PNDIS_CONFIGURATION_PARAMETER ConfigurationParameter; PAGED_CODE(); NdisInitUnicodeString(&Keyword, EntryName); NdisReadConfiguration(&Status, &ConfigurationParameter, ConfigurationHandle, &Keyword, NdisParameterInteger); if (Status != NDIS_STATUS_SUCCESS) { NDIS_DbgPrint(MIN_TRACE, ("'%S' request failed\n", EntryName)); *EntryContext = DefaultValue; } else { if (ConfigurationParameter->ParameterData.IntegerData >= Minimum && ConfigurationParameter->ParameterData.IntegerData <= Maximum) { *EntryContext = ConfigurationParameter->ParameterData.IntegerData; } else { NDIS_DbgPrint(MAX_TRACE, ("'%S' value out of range\n", EntryName)); *EntryContext = DefaultValue; } } NDIS_DbgPrint(MIN_TRACE, ("Set '%S' to %d\n", EntryName, *EntryContext)); } static CODE_SEG("PAGE") NDIS_STATUS NvNetReadConfiguration( _Inout_ PNVNET_ADAPTER Adapter) { NDIS_STATUS Status; NDIS_HANDLE ConfigurationHandle; PUCHAR NetworkAddress; UINT Length; ULONG GenericUlong; PAGED_CODE(); NDIS_DbgPrint(MIN_TRACE, ("()\n")); NdisOpenConfiguration(&Status, &ConfigurationHandle, Adapter->WrapperConfigurationHandle); if (Status != NDIS_STATUS_SUCCESS) return Status; QueryInteger(ConfigurationHandle, L"OptimizationMode", &GenericUlong, NV_OPTIMIZATION_MODE_DYNAMIC, NV_OPTIMIZATION_MODE_THROUGHPUT, NV_OPTIMIZATION_MODE_DYNAMIC); Adapter->OptimizationMode = GenericUlong; QueryInteger(ConfigurationHandle, L"FlowControl", &GenericUlong, NV_FLOW_CONTROL_AUTO, NV_FLOW_CONTROL_DISABLE, NV_FLOW_CONTROL_RX_TX); Adapter->FlowControlMode = GenericUlong; QueryInteger(ConfigurationHandle, L"SpeedDuplex", &GenericUlong, 0, 0, 4); switch (GenericUlong) { case 1: Adapter->Flags |= NV_FORCE_SPEED_AND_DUPLEX; break; case 2: Adapter->Flags |= (NV_FORCE_SPEED_AND_DUPLEX | NV_FORCE_FULL_DUPLEX); break; case 3: Adapter->Flags |= (NV_FORCE_SPEED_AND_DUPLEX | NV_USER_SPEED_100); break; case 4: Adapter->Flags |= (NV_FORCE_SPEED_AND_DUPLEX | NV_FORCE_FULL_DUPLEX | NV_USER_SPEED_100); break; default: break; } QueryInteger(ConfigurationHandle, L"ChecksumOffload", &GenericUlong, 0, 0, 1); if (GenericUlong) Adapter->Flags |= NV_SEND_CHECKSUM; QueryInteger(ConfigurationHandle, L"LargeSendOffload", &GenericUlong, 0, 0, 1); if (GenericUlong) Adapter->Flags |= NV_SEND_LARGE_SEND; QueryInteger(ConfigurationHandle, L"JumboSize", &GenericUlong, NVNET_MAXIMUM_FRAME_SIZE, NVNET_MAXIMUM_FRAME_SIZE, NVNET_MAXIMUM_FRAME_SIZE_JUMBO); Adapter->MaximumFrameSize = GenericUlong; QueryInteger(ConfigurationHandle, L"Priority", &GenericUlong, 0, 0, 1); if (GenericUlong) Adapter->Flags |= NV_PACKET_PRIORITY; QueryInteger(ConfigurationHandle, L"VlanTag", &GenericUlong, 0, 0, 1); if (GenericUlong) Adapter->Flags |= NV_VLAN_TAGGING; QueryInteger(ConfigurationHandle, L"VlanID", &GenericUlong, 0, 0, NVNET_MAXIMUM_VLAN_ID); NdisReadNetworkAddress(&Status, (PVOID*)&NetworkAddress, &Length, ConfigurationHandle); if ((Status == NDIS_STATUS_SUCCESS) && (Length == ETH_LENGTH_OF_ADDRESS)) { if ((ETH_IS_MULTICAST(NetworkAddress) || ETH_IS_BROADCAST(NetworkAddress)) || !ETH_IS_LOCALLY_ADMINISTERED(NetworkAddress)) { NDIS_DbgPrint(MAX_TRACE, ("Invalid software MAC: %02x:%02x:%02x:%02x:%02x:%02x\n", NetworkAddress[0], NetworkAddress[1], NetworkAddress[2], NetworkAddress[3], NetworkAddress[4], NetworkAddress[5])); } else { NDIS_DbgPrint(MIN_TRACE, ("Using software MAC\n")); ETH_COPY_NETWORK_ADDRESS(Adapter->CurrentMacAddress, NetworkAddress); Adapter->Flags |= NV_USE_SOFT_MAC_ADDRESS; } } Status = NDIS_STATUS_SUCCESS; NdisCloseConfiguration(ConfigurationHandle); return Status; } static CODE_SEG("PAGE") NDIS_STATUS NvNetInitializeAdapterResources( _Inout_ PNVNET_ADAPTER Adapter) { NDIS_STATUS Status; PNDIS_RESOURCE_LIST AssignedResources = NULL; UINT i, ResourceListSize = 0; PAGED_CODE(); NDIS_DbgPrint(MIN_TRACE, ("()\n")); NdisMQueryAdapterResources(&Status, Adapter->WrapperConfigurationHandle, AssignedResources, &ResourceListSize); if (Status != NDIS_STATUS_RESOURCES) { NvNetLogError(Adapter, NDIS_ERROR_CODE_RESOURCE_CONFLICT); return NDIS_STATUS_FAILURE; } Status = NdisAllocateMemoryWithTag((PVOID*)&AssignedResources, ResourceListSize, NVNET_TAG); if (Status != NDIS_STATUS_SUCCESS) { NvNetLogError(Adapter, NDIS_ERROR_CODE_OUT_OF_RESOURCES); return Status; } NdisMQueryAdapterResources(&Status, Adapter->WrapperConfigurationHandle, AssignedResources, &ResourceListSize); if (Status != NDIS_STATUS_SUCCESS) { NvNetLogError(Adapter, NDIS_ERROR_CODE_RESOURCE_CONFLICT); goto Cleanup; } for (i = 0; i < AssignedResources->Count; ++i) { PCM_PARTIAL_RESOURCE_DESCRIPTOR Descriptor = &AssignedResources->PartialDescriptors[i]; switch (Descriptor->Type) { case CmResourceTypeMemory: { Adapter->IoAddress = Descriptor->u.Memory.Start; Adapter->IoLength = Descriptor->u.Memory.Length; break; } case CmResourceTypeInterrupt: { Adapter->InterruptVector = Descriptor->u.Interrupt.Vector; Adapter->InterruptLevel = Descriptor->u.Interrupt.Level; Adapter->InterruptShared = (Descriptor->ShareDisposition == CmResourceShareShared); Adapter->InterruptFlags = Descriptor->Flags; break; } default: break; } } if (!Adapter->IoAddress.QuadPart || !Adapter->InterruptVector) { Status = NDIS_STATUS_RESOURCES; NvNetLogError(Adapter, NDIS_ERROR_CODE_RESOURCE_CONFLICT); goto Cleanup; } NDIS_DbgPrint(MIN_TRACE, ("MEM at [%I64X-%I64X]\n", Adapter->IoAddress.QuadPart, Adapter->IoAddress.QuadPart + Adapter->IoLength)); NDIS_DbgPrint(MIN_TRACE, ("IRQ Vector %d Level %d\n", Adapter->InterruptVector, Adapter->InterruptLevel)); Status = NdisMMapIoSpace((PVOID*)&Adapter->IoBase, Adapter->AdapterHandle, Adapter->IoAddress, Adapter->IoLength); if (Status != NDIS_STATUS_SUCCESS) { NvNetLogError(Adapter, NDIS_ERROR_CODE_RESOURCE_CONFLICT); goto Cleanup; } Cleanup: NdisFreeMemory(AssignedResources, ResourceListSize, 0); return Status; } static CODE_SEG("PAGE") NDIS_STATUS AllocateTransmitBuffers( _In_ PNVNET_ADAPTER Adapter) { ULONG i; BOOLEAN HasBuffer = FALSE; PNVNET_TX_BUFFER CoalesceBuffer; NDIS_STATUS Status; PAGED_CODE(); Status = NdisAllocateMemoryWithTag((PVOID*)&CoalesceBuffer, NVNET_TRANSMIT_BUFFERS * sizeof(NVNET_TX_BUFFER), NVNET_TAG); if (Status != NDIS_STATUS_SUCCESS) return Status; NdisZeroMemory(CoalesceBuffer, NVNET_TRANSMIT_BUFFERS * sizeof(NVNET_TX_BUFFER)); Adapter->SendBuffer = CoalesceBuffer; for (i = 0; i < NVNET_TRANSMIT_BUFFERS; ++i) { PVOID VirtualAddress; NDIS_PHYSICAL_ADDRESS PhysicalAddress; NdisMAllocateSharedMemory(Adapter->AdapterHandle, Adapter->MaximumFrameSize + NVNET_ALIGNMENT, TRUE, /* Cached */ &VirtualAddress, &PhysicalAddress); if (!VirtualAddress) continue; CoalesceBuffer->VirtualAddress = ALIGN_UP_POINTER_BY(VirtualAddress, NVNET_ALIGNMENT); CoalesceBuffer->PhysicalAddress.QuadPart = ALIGN_UP_BY(PhysicalAddress.QuadPart, NVNET_ALIGNMENT); Adapter->SendBufferAllocationData[i].PhysicalAddress.QuadPart = PhysicalAddress.QuadPart; Adapter->SendBufferAllocationData[i].VirtualAddress = VirtualAddress; PushEntryList(&Adapter->Send.BufferList, &CoalesceBuffer->Link); ++CoalesceBuffer; HasBuffer = TRUE; } if (!HasBuffer) { return NDIS_STATUS_RESOURCES; } return NDIS_STATUS_SUCCESS; } static CODE_SEG("PAGE") NDIS_STATUS AllocateTransmitBlocks( _In_ PNVNET_ADAPTER Adapter) { PNVNET_TCB Tcb; NDIS_STATUS Status; PAGED_CODE(); Status = NdisAllocateMemoryWithTag((PVOID*)&Tcb, NVNET_TRANSMIT_BLOCKS * sizeof(NVNET_TCB), NVNET_TAG); if (Status != NDIS_STATUS_SUCCESS) return Status; NdisZeroMemory(Tcb, NVNET_TRANSMIT_BLOCKS * sizeof(NVNET_TCB)); Adapter->Send.TailTcb = Tcb + (NVNET_TRANSMIT_BLOCKS - 1); Adapter->Send.HeadTcb = Tcb; Adapter->Send.CurrentTcb = Tcb; Adapter->Send.LastTcb = Tcb; return NDIS_STATUS_SUCCESS; } static CODE_SEG("PAGE") NDIS_STATUS AllocateTransmitDescriptors( _In_ PNVNET_ADAPTER Adapter) { NVNET_TBD Tbd; ULONG Size; PAGED_CODE(); if (Adapter->Features & DEV_HAS_HIGH_DMA) { Size = sizeof(NVNET_DESCRIPTOR_64); } else { Size = sizeof(NVNET_DESCRIPTOR_32); } NdisMAllocateSharedMemory(Adapter->AdapterHandle, Size * NVNET_TRANSMIT_DESCRIPTORS + NVNET_ALIGNMENT, TRUE, /* Cached */ &Adapter->TbdOriginal, &Adapter->TbdPhysOriginal); if (!Adapter->TbdOriginal) return NDIS_STATUS_RESOURCES; Tbd.Memory = ALIGN_UP_POINTER_BY(Adapter->TbdOriginal, NVNET_ALIGNMENT); Adapter->TbdPhys.QuadPart = ALIGN_UP_BY(Adapter->TbdPhysOriginal.QuadPart, NVNET_ALIGNMENT); Adapter->Send.HeadTbd = Tbd; Adapter->Send.CurrentTbd = Tbd; if (Adapter->Features & DEV_HAS_HIGH_DMA) { Adapter->Send.TailTbd.x64 = Tbd.x64 + (NVNET_TRANSMIT_DESCRIPTORS - 1); } else { Adapter->Send.TailTbd.x32 = Tbd.x32 + (NVNET_TRANSMIT_DESCRIPTORS - 1); } return NDIS_STATUS_SUCCESS; } static CODE_SEG("PAGE") NDIS_STATUS AllocateReceiveDescriptors( _In_ PNVNET_ADAPTER Adapter) { ULONG Size; PAGED_CODE(); if (Adapter->Features & DEV_HAS_HIGH_DMA) { Size = sizeof(NVNET_DESCRIPTOR_64); } else { Size = sizeof(NVNET_DESCRIPTOR_32); } NdisMAllocateSharedMemory(Adapter->AdapterHandle, Size * NVNET_RECEIVE_DESCRIPTORS + NVNET_ALIGNMENT, TRUE, /* Cached */ &Adapter->RbdOriginal, &Adapter->RbdPhysOriginal); if (!Adapter->RbdOriginal) return NDIS_STATUS_RESOURCES; Adapter->Receive.NvRbd.Memory = ALIGN_UP_POINTER_BY(Adapter->RbdOriginal, NVNET_ALIGNMENT); Adapter->RbdPhys.QuadPart = ALIGN_UP_BY(Adapter->RbdPhysOriginal.QuadPart, NVNET_ALIGNMENT); return NDIS_STATUS_SUCCESS; } static CODE_SEG("PAGE") NDIS_STATUS AllocateReceiveBuffers( _In_ PNVNET_ADAPTER Adapter) { PAGED_CODE(); NdisMAllocateSharedMemory(Adapter->AdapterHandle, NVNET_RECEIVE_BUFFER_SIZE * NVNET_RECEIVE_DESCRIPTORS, TRUE, /* Cached */ (PVOID*)&Adapter->ReceiveBuffer, &Adapter->ReceiveBufferPhys); if (!Adapter->ReceiveBuffer) { return NDIS_STATUS_RESOURCES; } return NDIS_STATUS_SUCCESS; } static CODE_SEG("PAGE") NDIS_STATUS AllocateAdapterMemory( _In_ PNVNET_ADAPTER Adapter) { NDIS_STATUS Status; PAGED_CODE(); Status = AllocateTransmitBuffers(Adapter); if (Status != NDIS_STATUS_SUCCESS) return Status; Status = AllocateTransmitBlocks(Adapter); if (Status != NDIS_STATUS_SUCCESS) return Status; Status = AllocateTransmitDescriptors(Adapter); if (Status != NDIS_STATUS_SUCCESS) return Status; Status = AllocateReceiveDescriptors(Adapter); if (Status != NDIS_STATUS_SUCCESS) return Status; Status = AllocateReceiveBuffers(Adapter); if (Status != NDIS_STATUS_SUCCESS) return Status; NdisAllocateSpinLock(&Adapter->Send.Lock); NdisAllocateSpinLock(&Adapter->Receive.Lock); NdisAllocateSpinLock(&Adapter->Lock); return NDIS_STATUS_SUCCESS; } CODE_SEG("PAGE") VOID NvNetInitTransmitMemory( _In_ PNVNET_ADAPTER Adapter) { PAGED_CODE(); Adapter->Send.TcbSlots = NVNET_TRANSMIT_BLOCKS; Adapter->Send.TbdSlots = NVNET_TRANSMIT_DESCRIPTORS; if (Adapter->Features & DEV_HAS_HIGH_DMA) { NdisZeroMemory(Adapter->Send.HeadTbd.x64, sizeof(NVNET_DESCRIPTOR_64) * NVNET_TRANSMIT_DESCRIPTORS); } else { NdisZeroMemory(Adapter->Send.HeadTbd.x32, sizeof(NVNET_DESCRIPTOR_32) * NVNET_TRANSMIT_DESCRIPTORS); } } static CODE_SEG("PAGE") VOID NvNetInitReceiveMemory( _In_ PNVNET_ADAPTER Adapter) { NV_RBD NvRbd; ULONG i; PAGED_CODE(); Adapter->CurrentRx = 0; if (Adapter->Features & DEV_HAS_HIGH_DMA) { for (i = 0; i < NVNET_RECEIVE_DESCRIPTORS; ++i) { NvRbd.x64 = &Adapter->Receive.NvRbd.x64[i]; NvRbd.x64->AddressHigh = NdisGetPhysicalAddressHigh(Adapter->ReceiveBufferPhys) + i * NVNET_RECEIVE_BUFFER_SIZE; NvRbd.x64->AddressLow = NdisGetPhysicalAddressLow(Adapter->ReceiveBufferPhys) + i * NVNET_RECEIVE_BUFFER_SIZE; NvRbd.x64->VlanTag = 0; NvRbd.x64->FlagsLength = NV_RX2_AVAIL | NVNET_RECEIVE_BUFFER_SIZE; } } else { for (i = 0; i < NVNET_RECEIVE_DESCRIPTORS; ++i) { NvRbd.x32 = &Adapter->Receive.NvRbd.x32[i]; NvRbd.x32->Address = NdisGetPhysicalAddressLow(Adapter->ReceiveBufferPhys) + i * NVNET_RECEIVE_BUFFER_SIZE; NvRbd.x32->FlagsLength = NV_RX_AVAIL | NVNET_RECEIVE_BUFFER_SIZE; } } } CODE_SEG("PAGE") VOID NvNetFreeAdapter( _In_ PNVNET_ADAPTER Adapter) { ULONG i; ULONG DescriptorSize; PAGED_CODE(); NDIS_DbgPrint(MIN_TRACE, ("()\n")); for (i = 0; i < RTL_NUMBER_OF(Adapter->WakeFrames); ++i) { PNVNET_WAKE_FRAME WakeFrame = Adapter->WakeFrames[i]; if (!WakeFrame) continue; NdisFreeMemory(WakeFrame, sizeof(*WakeFrame), 0); } if (Adapter->Interrupt.InterruptObject) { NdisMDeregisterInterrupt(&Adapter->Interrupt); Adapter->Interrupt.InterruptObject = NULL; } if (Adapter->Features & DEV_HAS_HIGH_DMA) { DescriptorSize = sizeof(NVNET_DESCRIPTOR_64); } else { DescriptorSize = sizeof(NVNET_DESCRIPTOR_32); } if (Adapter->TbdOriginal) { NdisMFreeSharedMemory(Adapter->AdapterHandle, DescriptorSize * NVNET_TRANSMIT_DESCRIPTORS, FALSE, Adapter->TbdOriginal, Adapter->TbdPhysOriginal); Adapter->TbdOriginal = NULL; } if (Adapter->RbdOriginal) { NdisMFreeSharedMemory(Adapter->AdapterHandle, DescriptorSize * NVNET_RECEIVE_DESCRIPTORS, FALSE, Adapter->RbdOriginal, Adapter->RbdPhysOriginal); Adapter->RbdOriginal = NULL; } if (Adapter->SendBuffer) { ULONG Length = ALIGN_UP_BY(Adapter->MaximumFrameSize, NVNET_ALIGNMENT); for (i = 0; i < NVNET_TRANSMIT_BUFFERS; ++i) { PNVNET_TX_BUFFER_DATA SendBufferData = &Adapter->SendBufferAllocationData[i]; if (!SendBufferData->VirtualAddress) continue; NdisMFreeSharedMemory(Adapter->AdapterHandle, Length, TRUE, SendBufferData->VirtualAddress, SendBufferData->PhysicalAddress); } NdisFreeMemory(Adapter->SendBuffer, NVNET_TRANSMIT_BUFFERS * sizeof(NVNET_TX_BUFFER), 0); Adapter->SendBuffer = NULL; } if (Adapter->ReceiveBuffer) { NdisMFreeSharedMemory(Adapter->AdapterHandle, NVNET_RECEIVE_BUFFER_SIZE * NVNET_RECEIVE_DESCRIPTORS, FALSE, Adapter->ReceiveBuffer, Adapter->ReceiveBufferPhys); Adapter->ReceiveBuffer = NULL; } if (Adapter->IoBase) { NdisMUnmapIoSpace(Adapter->AdapterHandle, Adapter->IoBase, Adapter->IoLength); Adapter->IoBase = NULL; } if (Adapter->Lock.SpinLock) NdisFreeSpinLock(&Adapter->Lock); if (Adapter->Send.Lock.SpinLock) NdisFreeSpinLock(&Adapter->Send.Lock); if (Adapter->Receive.Lock.SpinLock) NdisFreeSpinLock(&Adapter->Receive.Lock); NdisFreeMemory(Adapter->AdapterOriginal, sizeof(NVNET_ADAPTER), 0); } CODE_SEG("PAGE") NDIS_STATUS NTAPI MiniportInitialize( _Out_ PNDIS_STATUS OpenErrorStatus, _Out_ PUINT SelectedMediumIndex, _In_ PNDIS_MEDIUM MediumArray, _In_ UINT MediumArraySize, _In_ NDIS_HANDLE MiniportAdapterHandle, _In_ NDIS_HANDLE WrapperConfigurationContext) { UINT i; ULONG Size; PVOID UnalignedAdapter; PNVNET_ADAPTER Adapter; NDIS_STATUS Status; PAGED_CODE(); NDIS_DbgPrint(MIN_TRACE, ("()\n")); for (i = 0; i < MediumArraySize; ++i) { if (MediumArray[i] == NdisMedium802_3) { *SelectedMediumIndex = i; break; } } if (i == MediumArraySize) { NDIS_DbgPrint(MAX_TRACE, ("No supported media\n")); return NDIS_STATUS_UNSUPPORTED_MEDIA; } Size = sizeof(NVNET_ADAPTER) + NdisGetSharedDataAlignment(); Status = NdisAllocateMemoryWithTag((PVOID*)&UnalignedAdapter, Size, NVNET_TAG); if (Status != NDIS_STATUS_SUCCESS) { NDIS_DbgPrint(MAX_TRACE, ("Failed to allocate adapter\n")); return NDIS_STATUS_RESOURCES; } NdisZeroMemory(UnalignedAdapter, Size); Adapter = ALIGN_UP_POINTER_BY(UnalignedAdapter, NdisGetSharedDataAlignment()); Adapter->AdapterOriginal = UnalignedAdapter; Adapter->AdapterHandle = MiniportAdapterHandle; Adapter->WrapperConfigurationHandle = WrapperConfigurationContext; Status = NvNetReadConfiguration(Adapter); if (Status != NDIS_STATUS_SUCCESS) { goto Failure; } NdisMSetAttributesEx(MiniportAdapterHandle, Adapter, 0, NDIS_ATTRIBUTE_USES_SAFE_BUFFER_APIS | // NDIS_ATTRIBUTE_DESERIALIZE | TODO NDIS_ATTRIBUTE_BUS_MASTER, NdisInterfacePci); Status = NvNetRecognizeHardware(Adapter); if (Status != NDIS_STATUS_SUCCESS) { if (Status == NDIS_STATUS_ADAPTER_NOT_FOUND) { NvNetLogError(Adapter, NDIS_ERROR_CODE_ADAPTER_NOT_FOUND); } else if (Status == NDIS_STATUS_NOT_RECOGNIZED) { NvNetLogError(Adapter, NDIS_ERROR_CODE_UNSUPPORTED_CONFIGURATION); } goto Failure; } Status = NvNetInitializeAdapterResources(Adapter); if (Status != NDIS_STATUS_SUCCESS) { goto Failure; } Status = NdisMInitializeScatterGatherDma(Adapter->AdapterHandle, !!(Adapter->Features & DEV_HAS_HIGH_DMA), NVNET_MAXIMUM_FRAME_SIZE); // ^TODO: NVNET_MAX_DMA_TRANSFER); if (Status != NDIS_STATUS_SUCCESS) { NvNetLogError(Adapter, NDIS_ERROR_CODE_OUT_OF_RESOURCES); goto Failure; } Status = AllocateAdapterMemory(Adapter); if (Status != NDIS_STATUS_SUCCESS) { NDIS_DbgPrint(MAX_TRACE, ("Failed to allocate adapter memory\n")); NvNetLogError(Adapter, NDIS_ERROR_CODE_OUT_OF_RESOURCES); goto Failure; } NvNetInitTransmitMemory(Adapter); NvNetInitReceiveMemory(Adapter); if (Adapter->Features & DEV_HAS_HIGH_DMA) { Adapter->TransmitPacket = NvNetTransmitPacket64; Adapter->ProcessTransmit = ProcessTransmitDescriptors64; } else { Adapter->TransmitPacket = NvNetTransmitPacket32; if (Adapter->Features & DEV_HAS_LARGEDESC) { Adapter->ProcessTransmit = ProcessTransmitDescriptors32; } else { Adapter->ProcessTransmit = ProcessTransmitDescriptorsLegacy; } } Status = NvNetGetPermanentMacAddress(Adapter, Adapter->PermanentMacAddress); if (Status != NDIS_STATUS_SUCCESS) { NvNetLogError(Adapter, NDIS_ERROR_CODE_NETWORK_ADDRESS); goto Failure; } if (!(Adapter->Flags & NV_USE_SOFT_MAC_ADDRESS)) { ETH_COPY_NETWORK_ADDRESS(Adapter->CurrentMacAddress, Adapter->PermanentMacAddress); } NvNetSetupMacAddress(Adapter, Adapter->CurrentMacAddress); Status = NvNetInitNIC(Adapter, TRUE); if (Status != NDIS_STATUS_SUCCESS) { NDIS_DbgPrint(MAX_TRACE, ("Failed to initialize the NIC\n")); NvNetLogError(Adapter, NDIS_ERROR_CODE_HARDWARE_FAILURE); goto Failure; } NvNetDisableInterrupts(Adapter); NV_WRITE(Adapter, NvRegMIIStatus, NVREG_MIISTAT_MASK_ALL); NV_WRITE(Adapter, NvRegIrqStatus, NVREG_IRQSTAT_MASK); /* FIXME: Bug in the PIC HAL? */ #if defined(SARCH_XBOX) Status = NdisMRegisterInterrupt(&Adapter->Interrupt, Adapter->AdapterHandle, Adapter->InterruptVector, Adapter->InterruptLevel, TRUE, /* Request ISR calls */ FALSE, NdisInterruptLatched); #else Status = NdisMRegisterInterrupt(&Adapter->Interrupt, Adapter->AdapterHandle, Adapter->InterruptVector, Adapter->InterruptLevel, TRUE, /* Request ISR calls */ TRUE, /* Shared */ NdisInterruptLevelSensitive); #endif if (Status != NDIS_STATUS_SUCCESS) { NvNetLogError(Adapter, NDIS_ERROR_CODE_INTERRUPT_CONNECT); goto Failure; } NvNetStartAdapter(Adapter); return NDIS_STATUS_SUCCESS; Failure: NvNetFreeAdapter(Adapter); return Status; }