reactos/drivers/network/dd/nvnet/backoff.c
Dmitry Borisov b79fbe2333 [NVNET] Add driver for nForce-based NICs
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
2022-04-16 11:54:24 +03:00

185 lines
5.9 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: Re-seeding random values for the backoff algorithms
* COPYRIGHT: Copyright 2021-2022 Dmitry Borisov <di.sean@protonmail.com>
*/
/*
* HW access code was taken from the Linux forcedeth driver
* Copyright (C) 2003,4,5 Manfred Spraul
* Copyright (C) 2004 Andrew de Quincey
* Copyright (C) 2004 Carl-Daniel Hailfinger
* Copyright (c) 2004,2005,2006,2007,2008,2009 NVIDIA Corporation
*/
/* INCLUDES *******************************************************************/
#include "nvnet.h"
#define NDEBUG
#include "debug.h"
/* GLOBALS ********************************************************************/
#define BACKOFF_SEEDSET_ROWS 8
#define BACKOFF_SEEDSET_LFSRS 15
#define REVERSE_SEED(s) ((((s) & 0xF00) >> 8) | ((s) & 0x0F0) | (((s) & 0x00F) << 8))
static const ULONG NvpMainSeedSet[BACKOFF_SEEDSET_ROWS][BACKOFF_SEEDSET_LFSRS] =
{
{145, 155, 165, 175, 185, 196, 235, 245, 255, 265, 275, 285, 660, 690, 874},
{245, 255, 265, 575, 385, 298, 335, 345, 355, 366, 375, 385, 761, 790, 974},
{145, 155, 165, 175, 185, 196, 235, 245, 255, 265, 275, 285, 660, 690, 874},
{245, 255, 265, 575, 385, 298, 335, 345, 355, 366, 375, 386, 761, 790, 974},
{266, 265, 276, 585, 397, 208, 345, 355, 365, 376, 385, 396, 771, 700, 984},
{266, 265, 276, 586, 397, 208, 346, 355, 365, 376, 285, 396, 771, 700, 984},
{366, 365, 376, 686, 497, 308, 447, 455, 466, 476, 485, 496, 871, 800, 84},
{466, 465, 476, 786, 597, 408, 547, 555, 566, 576, 585, 597, 971, 900, 184}
};
static const ULONG NvpGearSeedSet[BACKOFF_SEEDSET_ROWS][BACKOFF_SEEDSET_LFSRS] =
{
{251, 262, 273, 324, 319, 508, 375, 364, 341, 371, 398, 193, 375, 30, 295},
{351, 375, 373, 469, 551, 639, 477, 464, 441, 472, 498, 293, 476, 130, 395},
{351, 375, 373, 469, 551, 639, 477, 464, 441, 472, 498, 293, 476, 130, 397},
{251, 262, 273, 324, 319, 508, 375, 364, 341, 371, 398, 193, 375, 30, 295},
{251, 262, 273, 324, 319, 508, 375, 364, 341, 371, 398, 193, 375, 30, 295},
{351, 375, 373, 469, 551, 639, 477, 464, 441, 472, 498, 293, 476, 130, 395},
{351, 375, 373, 469, 551, 639, 477, 464, 441, 472, 498, 293, 476, 130, 395},
{351, 375, 373, 469, 551, 639, 477, 464, 441, 472, 498, 293, 476, 130, 395}
};
/* FUNCTIONS ******************************************************************/
CODE_SEG("PAGE")
VOID
NvNetBackoffSetSlotTime(
_In_ PNVNET_ADAPTER Adapter)
{
LARGE_INTEGER Sample = KeQueryPerformanceCounter(NULL);
PAGED_CODE();
if ((Sample.LowPart & NVREG_SLOTTIME_MASK) == 0)
{
Sample.LowPart = 8;
}
if (Adapter->Features & (DEV_HAS_HIGH_DMA | DEV_HAS_LARGEDESC))
{
if (Adapter->Features & DEV_HAS_GEAR_MODE)
{
NV_WRITE(Adapter, NvRegSlotTime, NVREG_SLOTTIME_10_100_FULL);
NvNetBackoffReseedEx(Adapter);
}
else
{
NV_WRITE(Adapter, NvRegSlotTime, (Sample.LowPart & NVREG_SLOTTIME_MASK) |
NVREG_SLOTTIME_LEGBF_ENABLED | NVREG_SLOTTIME_10_100_FULL);
}
}
else
{
NV_WRITE(Adapter, NvRegSlotTime,
(Sample.LowPart & NVREG_SLOTTIME_MASK) | NVREG_SLOTTIME_DEFAULT);
}
}
VOID
NvNetBackoffReseed(
_In_ PNVNET_ADAPTER Adapter)
{
ULONG SlotTime;
BOOLEAN RestartTransmitter = FALSE;
LARGE_INTEGER Sample = KeQueryPerformanceCounter(NULL);
NDIS_DbgPrint(MIN_TRACE, ("()\n"));
if ((Sample.LowPart & NVREG_SLOTTIME_MASK) == 0)
{
Sample.LowPart = 8;
}
SlotTime = NV_READ(Adapter, NvRegSlotTime) & ~NVREG_SLOTTIME_MASK;
SlotTime |= Sample.LowPart & NVREG_SLOTTIME_MASK;
if (NV_READ(Adapter, NvRegTransmitterControl) & NVREG_XMITCTL_START)
{
RestartTransmitter = TRUE;
NvNetStopTransmitter(Adapter);
}
NvNetStopReceiver(Adapter);
NV_WRITE(Adapter, NvRegSlotTime, SlotTime);
if (RestartTransmitter)
{
NvNetStartTransmitter(Adapter);
}
NvNetStartReceiver(Adapter);
}
VOID
NvNetBackoffReseedEx(
_In_ PNVNET_ADAPTER Adapter)
{
LARGE_INTEGER Sample;
ULONG Seed[3], ReversedSeed[2], CombinedSeed, SeedSet;
ULONG i, Temp;
NDIS_DbgPrint(MIN_TRACE, ("()\n"));
Sample = KeQueryPerformanceCounter(NULL);
Seed[0] = Sample.LowPart & 0x0FFF;
if (Seed[0] == 0)
{
Seed[0] = 0x0ABC;
}
Sample = KeQueryPerformanceCounter(NULL);
Seed[1] = Sample.LowPart & 0x0FFF;
if (Seed[1] == 0)
{
Seed[1] = 0x0ABC;
}
ReversedSeed[0] = REVERSE_SEED(Seed[1]);
Sample = KeQueryPerformanceCounter(NULL);
Seed[2] = Sample.LowPart & 0x0FFF;
if (Seed[2] == 0)
{
Seed[2] = 0x0ABC;
}
ReversedSeed[1] = REVERSE_SEED(Seed[2]);
CombinedSeed = ((Seed[0] ^ ReversedSeed[0]) << 12) | (Seed[1] ^ ReversedSeed[1]);
if ((CombinedSeed & NVREG_BKOFFCTRL_SEED_MASK) == 0)
{
CombinedSeed |= 8;
}
if ((CombinedSeed & (NVREG_BKOFFCTRL_SEED_MASK << NVREG_BKOFFCTRL_GEAR)) == 0)
{
CombinedSeed |= 8 << NVREG_BKOFFCTRL_GEAR;
}
/* No need to disable transmitter here */
Temp = NVREG_BKOFFCTRL_DEFAULT | (0 << NVREG_BKOFFCTRL_SELECT);
Temp |= CombinedSeed & NVREG_BKOFFCTRL_SEED_MASK;
Temp |= CombinedSeed >> NVREG_BKOFFCTRL_GEAR;
NV_WRITE(Adapter, NvRegBackOffControl, Temp);
/* Setup seeds for all gear LFSRs */
Sample = KeQueryPerformanceCounter(NULL);
SeedSet = Sample.LowPart % BACKOFF_SEEDSET_ROWS;
for (i = 1; i <= BACKOFF_SEEDSET_LFSRS; ++i)
{
Temp = NVREG_BKOFFCTRL_DEFAULT | (i << NVREG_BKOFFCTRL_SELECT);
Temp |= NvpMainSeedSet[SeedSet][i - 1] & NVREG_BKOFFCTRL_SEED_MASK;
Temp |= (NvpGearSeedSet[SeedSet][i - 1] & NVREG_BKOFFCTRL_SEED_MASK)
<< NVREG_BKOFFCTRL_GEAR;
NV_WRITE(Adapter, NvRegBackOffControl, Temp);
}
}