mirror of
https://github.com/reactos/reactos.git
synced 2024-12-29 10:35:28 +00:00
b79fbe2333
The driver supports all nVidia chipset models from 2001 until 2010, starting from nForce. All NICs are compatible with x86 and amd64 devices only. Tested by Daniel Reimer on OG Xbox and by me on MCP board. CORE-15872 CORE-16216
885 lines
25 KiB
C
885 lines
25 KiB
C
/*
|
|
* 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 <di.sean@protonmail.com>
|
|
*/
|
|
|
|
/* 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;
|
|
}
|