1 /* 2 * PROJECT: ReactOS nVidia nForce Ethernet Controller Driver 3 * LICENSE: GPL-2.0-or-later (https://spdx.org/licenses/GPL-2.0-or-later) 4 * PURPOSE: Re-seeding random values for the backoff algorithms 5 * COPYRIGHT: Copyright 2021-2022 Dmitry Borisov <di.sean@protonmail.com> 6 */ 7 8 /* 9 * HW access code was taken from the Linux forcedeth driver 10 * Copyright (C) 2003,4,5 Manfred Spraul 11 * Copyright (C) 2004 Andrew de Quincey 12 * Copyright (C) 2004 Carl-Daniel Hailfinger 13 * Copyright (c) 2004,2005,2006,2007,2008,2009 NVIDIA Corporation 14 */ 15 16 /* INCLUDES *******************************************************************/ 17 18 #include "nvnet.h" 19 20 #define NDEBUG 21 #include "debug.h" 22 23 /* GLOBALS ********************************************************************/ 24 25 #define BACKOFF_SEEDSET_ROWS 8 26 #define BACKOFF_SEEDSET_LFSRS 15 27 28 #define REVERSE_SEED(s) ((((s) & 0xF00) >> 8) | ((s) & 0x0F0) | (((s) & 0x00F) << 8)) 29 30 static const ULONG NvpMainSeedSet[BACKOFF_SEEDSET_ROWS][BACKOFF_SEEDSET_LFSRS] = 31 { 32 {145, 155, 165, 175, 185, 196, 235, 245, 255, 265, 275, 285, 660, 690, 874}, 33 {245, 255, 265, 575, 385, 298, 335, 345, 355, 366, 375, 385, 761, 790, 974}, 34 {145, 155, 165, 175, 185, 196, 235, 245, 255, 265, 275, 285, 660, 690, 874}, 35 {245, 255, 265, 575, 385, 298, 335, 345, 355, 366, 375, 386, 761, 790, 974}, 36 {266, 265, 276, 585, 397, 208, 345, 355, 365, 376, 385, 396, 771, 700, 984}, 37 {266, 265, 276, 586, 397, 208, 346, 355, 365, 376, 285, 396, 771, 700, 984}, 38 {366, 365, 376, 686, 497, 308, 447, 455, 466, 476, 485, 496, 871, 800, 84}, 39 {466, 465, 476, 786, 597, 408, 547, 555, 566, 576, 585, 597, 971, 900, 184} 40 }; 41 42 static const ULONG NvpGearSeedSet[BACKOFF_SEEDSET_ROWS][BACKOFF_SEEDSET_LFSRS] = 43 { 44 {251, 262, 273, 324, 319, 508, 375, 364, 341, 371, 398, 193, 375, 30, 295}, 45 {351, 375, 373, 469, 551, 639, 477, 464, 441, 472, 498, 293, 476, 130, 395}, 46 {351, 375, 373, 469, 551, 639, 477, 464, 441, 472, 498, 293, 476, 130, 397}, 47 {251, 262, 273, 324, 319, 508, 375, 364, 341, 371, 398, 193, 375, 30, 295}, 48 {251, 262, 273, 324, 319, 508, 375, 364, 341, 371, 398, 193, 375, 30, 295}, 49 {351, 375, 373, 469, 551, 639, 477, 464, 441, 472, 498, 293, 476, 130, 395}, 50 {351, 375, 373, 469, 551, 639, 477, 464, 441, 472, 498, 293, 476, 130, 395}, 51 {351, 375, 373, 469, 551, 639, 477, 464, 441, 472, 498, 293, 476, 130, 395} 52 }; 53 54 /* FUNCTIONS ******************************************************************/ 55 56 CODE_SEG("PAGE") 57 VOID 58 NvNetBackoffSetSlotTime( 59 _In_ PNVNET_ADAPTER Adapter) 60 { 61 LARGE_INTEGER Sample = KeQueryPerformanceCounter(NULL); 62 63 PAGED_CODE(); 64 65 if ((Sample.LowPart & NVREG_SLOTTIME_MASK) == 0) 66 { 67 Sample.LowPart = 8; 68 } 69 70 if (Adapter->Features & (DEV_HAS_HIGH_DMA | DEV_HAS_LARGEDESC)) 71 { 72 if (Adapter->Features & DEV_HAS_GEAR_MODE) 73 { 74 NV_WRITE(Adapter, NvRegSlotTime, NVREG_SLOTTIME_10_100_FULL); 75 NvNetBackoffReseedEx(Adapter); 76 } 77 else 78 { 79 NV_WRITE(Adapter, NvRegSlotTime, (Sample.LowPart & NVREG_SLOTTIME_MASK) | 80 NVREG_SLOTTIME_LEGBF_ENABLED | NVREG_SLOTTIME_10_100_FULL); 81 } 82 } 83 else 84 { 85 NV_WRITE(Adapter, NvRegSlotTime, 86 (Sample.LowPart & NVREG_SLOTTIME_MASK) | NVREG_SLOTTIME_DEFAULT); 87 } 88 } 89 90 VOID 91 NvNetBackoffReseed( 92 _In_ PNVNET_ADAPTER Adapter) 93 { 94 ULONG SlotTime; 95 BOOLEAN RestartTransmitter = FALSE; 96 LARGE_INTEGER Sample = KeQueryPerformanceCounter(NULL); 97 98 NDIS_DbgPrint(MIN_TRACE, ("()\n")); 99 100 if ((Sample.LowPart & NVREG_SLOTTIME_MASK) == 0) 101 { 102 Sample.LowPart = 8; 103 } 104 105 SlotTime = NV_READ(Adapter, NvRegSlotTime) & ~NVREG_SLOTTIME_MASK; 106 SlotTime |= Sample.LowPart & NVREG_SLOTTIME_MASK; 107 108 if (NV_READ(Adapter, NvRegTransmitterControl) & NVREG_XMITCTL_START) 109 { 110 RestartTransmitter = TRUE; 111 NvNetStopTransmitter(Adapter); 112 } 113 NvNetStopReceiver(Adapter); 114 115 NV_WRITE(Adapter, NvRegSlotTime, SlotTime); 116 117 if (RestartTransmitter) 118 { 119 NvNetStartTransmitter(Adapter); 120 } 121 NvNetStartReceiver(Adapter); 122 } 123 124 VOID 125 NvNetBackoffReseedEx( 126 _In_ PNVNET_ADAPTER Adapter) 127 { 128 LARGE_INTEGER Sample; 129 ULONG Seed[3], ReversedSeed[2], CombinedSeed, SeedSet; 130 ULONG i, Temp; 131 132 NDIS_DbgPrint(MIN_TRACE, ("()\n")); 133 134 Sample = KeQueryPerformanceCounter(NULL); 135 Seed[0] = Sample.LowPart & 0x0FFF; 136 if (Seed[0] == 0) 137 { 138 Seed[0] = 0x0ABC; 139 } 140 141 Sample = KeQueryPerformanceCounter(NULL); 142 Seed[1] = Sample.LowPart & 0x0FFF; 143 if (Seed[1] == 0) 144 { 145 Seed[1] = 0x0ABC; 146 } 147 ReversedSeed[0] = REVERSE_SEED(Seed[1]); 148 149 Sample = KeQueryPerformanceCounter(NULL); 150 Seed[2] = Sample.LowPart & 0x0FFF; 151 if (Seed[2] == 0) 152 { 153 Seed[2] = 0x0ABC; 154 } 155 ReversedSeed[1] = REVERSE_SEED(Seed[2]); 156 157 CombinedSeed = ((Seed[0] ^ ReversedSeed[0]) << 12) | (Seed[1] ^ ReversedSeed[1]); 158 if ((CombinedSeed & NVREG_BKOFFCTRL_SEED_MASK) == 0) 159 { 160 CombinedSeed |= 8; 161 } 162 if ((CombinedSeed & (NVREG_BKOFFCTRL_SEED_MASK << NVREG_BKOFFCTRL_GEAR)) == 0) 163 { 164 CombinedSeed |= 8 << NVREG_BKOFFCTRL_GEAR; 165 } 166 167 /* No need to disable transmitter here */ 168 Temp = NVREG_BKOFFCTRL_DEFAULT | (0 << NVREG_BKOFFCTRL_SELECT); 169 Temp |= CombinedSeed & NVREG_BKOFFCTRL_SEED_MASK; 170 Temp |= CombinedSeed >> NVREG_BKOFFCTRL_GEAR; 171 NV_WRITE(Adapter, NvRegBackOffControl, Temp); 172 173 /* Setup seeds for all gear LFSRs */ 174 Sample = KeQueryPerformanceCounter(NULL); 175 SeedSet = Sample.LowPart % BACKOFF_SEEDSET_ROWS; 176 for (i = 1; i <= BACKOFF_SEEDSET_LFSRS; ++i) 177 { 178 Temp = NVREG_BKOFFCTRL_DEFAULT | (i << NVREG_BKOFFCTRL_SELECT); 179 Temp |= NvpMainSeedSet[SeedSet][i - 1] & NVREG_BKOFFCTRL_SEED_MASK; 180 Temp |= (NvpGearSeedSet[SeedSet][i - 1] & NVREG_BKOFFCTRL_SEED_MASK) 181 << NVREG_BKOFFCTRL_GEAR; 182 NV_WRITE(Adapter, NvRegBackOffControl, Temp); 183 } 184 } 185