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
NvNetBackoffSetSlotTime(_In_ PNVNET_ADAPTER Adapter)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
NvNetBackoffReseed(_In_ PNVNET_ADAPTER Adapter)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
NvNetBackoffReseedEx(_In_ PNVNET_ADAPTER Adapter)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