xref: /reactos/drivers/network/dd/nvnet/backoff.c (revision b79fbe23)
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