xref: /reactos/drivers/network/dd/dc21x4/media143.c (revision 59d8a77d)
1*59d8a77dSDmitry Borisov /*
2*59d8a77dSDmitry Borisov  * PROJECT:     ReactOS DC21x4 Driver
3*59d8a77dSDmitry Borisov  * LICENSE:     GPL-2.0-or-later (https://spdx.org/licenses/GPL-2.0-or-later)
4*59d8a77dSDmitry Borisov  * PURPOSE:     21142/21143/21145 media support code
5*59d8a77dSDmitry Borisov  * COPYRIGHT:   Copyright 2023 Dmitry Borisov <di.sean@protonmail.com>
6*59d8a77dSDmitry Borisov  */
7*59d8a77dSDmitry Borisov 
8*59d8a77dSDmitry Borisov /* INCLUDES *******************************************************************/
9*59d8a77dSDmitry Borisov 
10*59d8a77dSDmitry Borisov #include "dc21x4.h"
11*59d8a77dSDmitry Borisov 
12*59d8a77dSDmitry Borisov #include <debug.h>
13*59d8a77dSDmitry Borisov 
14*59d8a77dSDmitry Borisov /* FUNCTIONS ******************************************************************/
15*59d8a77dSDmitry Borisov 
16*59d8a77dSDmitry Borisov static
17*59d8a77dSDmitry Borisov VOID
Media143SelectNextSerialMedia(_In_ PDC21X4_ADAPTER Adapter)18*59d8a77dSDmitry Borisov Media143SelectNextSerialMedia(
19*59d8a77dSDmitry Borisov     _In_ PDC21X4_ADAPTER Adapter)
20*59d8a77dSDmitry Borisov {
21*59d8a77dSDmitry Borisov     ULONG MediaNumber;
22*59d8a77dSDmitry Borisov 
23*59d8a77dSDmitry Borisov     MediaNumber = Adapter->MediaNumber;
24*59d8a77dSDmitry Borisov 
25*59d8a77dSDmitry Borisov     /* The HMR media isn't checked as HMR boards use it instead of AUI and BNC */
26*59d8a77dSDmitry Borisov     if (MediaNumber == MEDIA_AUI || MediaNumber == MEDIA_BNC)
27*59d8a77dSDmitry Borisov     {
28*59d8a77dSDmitry Borisov         if (MediaNumber == MEDIA_AUI)
29*59d8a77dSDmitry Borisov             Adapter->ModeFlags |= DC_MODE_AUI_FAILED;
30*59d8a77dSDmitry Borisov         else if (MediaNumber == MEDIA_BNC)
31*59d8a77dSDmitry Borisov             Adapter->ModeFlags |= DC_MODE_BNC_FAILED;
32*59d8a77dSDmitry Borisov 
33*59d8a77dSDmitry Borisov         if ((Adapter->ModeFlags & (DC_MODE_AUI_FAILED | DC_MODE_BNC_FAILED)) !=
34*59d8a77dSDmitry Borisov             (DC_MODE_AUI_FAILED | DC_MODE_BNC_FAILED))
35*59d8a77dSDmitry Borisov         {
36*59d8a77dSDmitry Borisov             MediaNumber = (MEDIA_BNC + MEDIA_AUI) - MediaNumber;
37*59d8a77dSDmitry Borisov 
38*59d8a77dSDmitry Borisov             if (Adapter->MediaBitmap & (1 << MediaNumber))
39*59d8a77dSDmitry Borisov             {
40*59d8a77dSDmitry Borisov                 Adapter->MediaNumber = MediaNumber;
41*59d8a77dSDmitry Borisov                 MediaSiaSelect(Adapter);
42*59d8a77dSDmitry Borisov                 return;
43*59d8a77dSDmitry Borisov             }
44*59d8a77dSDmitry Borisov         }
45*59d8a77dSDmitry Borisov     }
46*59d8a77dSDmitry Borisov 
47*59d8a77dSDmitry Borisov     if (Adapter->Features & DC_HAS_MII)
48*59d8a77dSDmitry Borisov     {
49*59d8a77dSDmitry Borisov         Adapter->MediaNumber = MEDIA_MII;
50*59d8a77dSDmitry Borisov 
51*59d8a77dSDmitry Borisov         DcStopTxRxProcess(Adapter);
52*59d8a77dSDmitry Borisov         MediaSelectMiiPort(Adapter, FALSE);
53*59d8a77dSDmitry Borisov         MediaMiiSelect(Adapter);
54*59d8a77dSDmitry Borisov     }
55*59d8a77dSDmitry Borisov     else
56*59d8a77dSDmitry Borisov     {
57*59d8a77dSDmitry Borisov         Adapter->MediaNumber = MEDIA_10T;
58*59d8a77dSDmitry Borisov         MediaSiaSelect(Adapter);
59*59d8a77dSDmitry Borisov     }
60*59d8a77dSDmitry Borisov }
61*59d8a77dSDmitry Borisov 
62*59d8a77dSDmitry Borisov static
63*59d8a77dSDmitry Borisov VOID
Media143SelectNextMedia(_In_ PDC21X4_ADAPTER Adapter,_In_ ULONG SiaStatus)64*59d8a77dSDmitry Borisov Media143SelectNextMedia(
65*59d8a77dSDmitry Borisov     _In_ PDC21X4_ADAPTER Adapter,
66*59d8a77dSDmitry Borisov     _In_ ULONG SiaStatus)
67*59d8a77dSDmitry Borisov {
68*59d8a77dSDmitry Borisov     ULONG MediaBitmap, MediaNumber;
69*59d8a77dSDmitry Borisov 
70*59d8a77dSDmitry Borisov     MediaIndicateConnect(Adapter, FALSE);
71*59d8a77dSDmitry Borisov 
72*59d8a77dSDmitry Borisov     MediaBitmap = Adapter->MediaBitmap;
73*59d8a77dSDmitry Borisov 
74*59d8a77dSDmitry Borisov     if (MediaBitmap & (1 << MEDIA_HMR))
75*59d8a77dSDmitry Borisov     {
76*59d8a77dSDmitry Borisov         MediaNumber = MEDIA_HMR;
77*59d8a77dSDmitry Borisov     }
78*59d8a77dSDmitry Borisov     else if ((MediaBitmap & MEDIA_AUI_BNC_MASK) == MEDIA_AUI_BNC_MASK)
79*59d8a77dSDmitry Borisov     {
80*59d8a77dSDmitry Borisov         if (SiaStatus & DC_SIA_STATUS_AUI_ACTIVITY)
81*59d8a77dSDmitry Borisov         {
82*59d8a77dSDmitry Borisov             MediaNumber = MEDIA_AUI;
83*59d8a77dSDmitry Borisov         }
84*59d8a77dSDmitry Borisov         else
85*59d8a77dSDmitry Borisov         {
86*59d8a77dSDmitry Borisov             MediaNumber = MEDIA_BNC;
87*59d8a77dSDmitry Borisov         }
88*59d8a77dSDmitry Borisov     }
89*59d8a77dSDmitry Borisov     else if (MediaBitmap & (1 << MEDIA_AUI))
90*59d8a77dSDmitry Borisov     {
91*59d8a77dSDmitry Borisov         MediaNumber = MEDIA_AUI;
92*59d8a77dSDmitry Borisov     }
93*59d8a77dSDmitry Borisov     else if (MediaBitmap & (1 << MEDIA_BNC))
94*59d8a77dSDmitry Borisov     {
95*59d8a77dSDmitry Borisov         MediaNumber = MEDIA_BNC;
96*59d8a77dSDmitry Borisov     }
97*59d8a77dSDmitry Borisov     else
98*59d8a77dSDmitry Borisov     {
99*59d8a77dSDmitry Borisov         MediaNumber = MEDIA_10T;
100*59d8a77dSDmitry Borisov     }
101*59d8a77dSDmitry Borisov 
102*59d8a77dSDmitry Borisov     Adapter->ModeFlags &= ~DC_MODE_AUTONEG_MASK;
103*59d8a77dSDmitry Borisov     Adapter->ModeFlags |= DC_MODE_AUTONEG_NONE;
104*59d8a77dSDmitry Borisov     NdisMSetTimer(&Adapter->MediaMonitorTimer, 3000);
105*59d8a77dSDmitry Borisov 
106*59d8a77dSDmitry Borisov     if (Adapter->MediaNumber != MediaNumber)
107*59d8a77dSDmitry Borisov     {
108*59d8a77dSDmitry Borisov         Adapter->MediaNumber = MediaNumber;
109*59d8a77dSDmitry Borisov         MediaSiaSelect(Adapter);
110*59d8a77dSDmitry Borisov     }
111*59d8a77dSDmitry Borisov 
112*59d8a77dSDmitry Borisov     Adapter->ModeFlags &= ~(DC_MODE_TEST_PACKET |
113*59d8a77dSDmitry Borisov                             DC_MODE_AUI_FAILED |
114*59d8a77dSDmitry Borisov                             DC_MODE_BNC_FAILED);
115*59d8a77dSDmitry Borisov     Adapter->LastReceiveActivity = (ULONG)Adapter->Statistics.ReceiveOk;
116*59d8a77dSDmitry Borisov }
117*59d8a77dSDmitry Borisov 
118*59d8a77dSDmitry Borisov static
119*59d8a77dSDmitry Borisov VOID
Media143Handle10LinkFail(_In_ PDC21X4_ADAPTER Adapter,_In_ ULONG SiaStatus)120*59d8a77dSDmitry Borisov Media143Handle10LinkFail(
121*59d8a77dSDmitry Borisov     _In_ PDC21X4_ADAPTER Adapter,
122*59d8a77dSDmitry Borisov     _In_ ULONG SiaStatus)
123*59d8a77dSDmitry Borisov {
124*59d8a77dSDmitry Borisov     INFO_VERB("Link failed, CSR12 %08lx\n", SiaStatus);
125*59d8a77dSDmitry Borisov 
126*59d8a77dSDmitry Borisov     /* 10Base-T link is down */
127*59d8a77dSDmitry Borisov     MediaIndicateConnect(Adapter, FALSE);
128*59d8a77dSDmitry Borisov 
129*59d8a77dSDmitry Borisov     /* Select the other port */
130*59d8a77dSDmitry Borisov     if (!MEDIA_IS_FIXED(Adapter))
131*59d8a77dSDmitry Borisov     {
132*59d8a77dSDmitry Borisov         Media143SelectNextMedia(Adapter, SiaStatus);
133*59d8a77dSDmitry Borisov     }
134*59d8a77dSDmitry Borisov }
135*59d8a77dSDmitry Borisov 
136*59d8a77dSDmitry Borisov static
137*59d8a77dSDmitry Borisov VOID
Media143Handle10LinkPass(_In_ PDC21X4_ADAPTER Adapter,_In_ ULONG SiaStatus)138*59d8a77dSDmitry Borisov Media143Handle10LinkPass(
139*59d8a77dSDmitry Borisov     _In_ PDC21X4_ADAPTER Adapter,
140*59d8a77dSDmitry Borisov     _In_ ULONG SiaStatus)
141*59d8a77dSDmitry Borisov {
142*59d8a77dSDmitry Borisov     INFO_VERB("Link passed, CSR12 %08lx\n", SiaStatus);
143*59d8a77dSDmitry Borisov 
144*59d8a77dSDmitry Borisov     /* 10Base-T is the active port now */
145*59d8a77dSDmitry Borisov     if (!MEDIA_IS_10T(Adapter->MediaNumber))
146*59d8a77dSDmitry Borisov     {
147*59d8a77dSDmitry Borisov         /* Switch to TP medium */
148*59d8a77dSDmitry Borisov         if (!MEDIA_IS_FIXED(Adapter))
149*59d8a77dSDmitry Borisov         {
150*59d8a77dSDmitry Borisov             Adapter->MediaNumber = MEDIA_10T;
151*59d8a77dSDmitry Borisov             MediaSiaSelect(Adapter);
152*59d8a77dSDmitry Borisov 
153*59d8a77dSDmitry Borisov             /* Wait for a link pass interrupt to signal the link test completed */
154*59d8a77dSDmitry Borisov             Adapter->ModeFlags &= ~DC_MODE_AUTONEG_MASK;
155*59d8a77dSDmitry Borisov             Adapter->ModeFlags |= DC_MODE_AUTONEG_WAIT_INTERRUPT;
156*59d8a77dSDmitry Borisov             NdisMSetTimer(&Adapter->MediaMonitorTimer, 3000);
157*59d8a77dSDmitry Borisov         }
158*59d8a77dSDmitry Borisov     }
159*59d8a77dSDmitry Borisov     else
160*59d8a77dSDmitry Borisov     {
161*59d8a77dSDmitry Borisov         /* 10Base-T link is up */
162*59d8a77dSDmitry Borisov         MediaIndicateConnect(Adapter, TRUE);
163*59d8a77dSDmitry Borisov     }
164*59d8a77dSDmitry Borisov }
165*59d8a77dSDmitry Borisov 
166*59d8a77dSDmitry Borisov static
167*59d8a77dSDmitry Borisov VOID
Media143Handle100LinkChange(_In_ PDC21X4_ADAPTER Adapter,_In_ ULONG SiaStatus)168*59d8a77dSDmitry Borisov Media143Handle100LinkChange(
169*59d8a77dSDmitry Borisov     _In_ PDC21X4_ADAPTER Adapter,
170*59d8a77dSDmitry Borisov     _In_ ULONG SiaStatus)
171*59d8a77dSDmitry Borisov {
172*59d8a77dSDmitry Borisov     BOOLEAN LinkUp;
173*59d8a77dSDmitry Borisov 
174*59d8a77dSDmitry Borisov     INFO_VERB("Link changed, CSR12 %08lx\n", SiaStatus);
175*59d8a77dSDmitry Borisov 
176*59d8a77dSDmitry Borisov     LinkUp = !(SiaStatus & DC_SIA_STATUS_100T_LINK_FAIL);
177*59d8a77dSDmitry Borisov 
178*59d8a77dSDmitry Borisov     if (MEDIA_IS_FIXED(Adapter))
179*59d8a77dSDmitry Borisov     {
180*59d8a77dSDmitry Borisov         MediaIndicateConnect(Adapter, LinkUp);
181*59d8a77dSDmitry Borisov     }
182*59d8a77dSDmitry Borisov     else
183*59d8a77dSDmitry Borisov     {
184*59d8a77dSDmitry Borisov         /* Select the other port */
185*59d8a77dSDmitry Borisov         if (!LinkUp)
186*59d8a77dSDmitry Borisov         {
187*59d8a77dSDmitry Borisov             Media143SelectNextMedia(Adapter, SiaStatus);
188*59d8a77dSDmitry Borisov         }
189*59d8a77dSDmitry Borisov         else
190*59d8a77dSDmitry Borisov         {
191*59d8a77dSDmitry Borisov             /* Ignore this hint */
192*59d8a77dSDmitry Borisov         }
193*59d8a77dSDmitry Borisov     }
194*59d8a77dSDmitry Borisov }
195*59d8a77dSDmitry Borisov 
196*59d8a77dSDmitry Borisov static
197*59d8a77dSDmitry Borisov VOID
Media143HandleNWayComplete(_In_ PDC21X4_ADAPTER Adapter,_In_ ULONG SiaStatus)198*59d8a77dSDmitry Borisov Media143HandleNWayComplete(
199*59d8a77dSDmitry Borisov     _In_ PDC21X4_ADAPTER Adapter,
200*59d8a77dSDmitry Borisov     _In_ ULONG SiaStatus)
201*59d8a77dSDmitry Borisov {
202*59d8a77dSDmitry Borisov     ULONG MediaNumber, AdvLpa;
203*59d8a77dSDmitry Borisov 
204*59d8a77dSDmitry Borisov     /* Select media according to auto-negotiation result */
205*59d8a77dSDmitry Borisov     if (SiaStatus & DC_SIA_STATUS_LP_AUTONED_SUPPORTED)
206*59d8a77dSDmitry Borisov     {
207*59d8a77dSDmitry Borisov         INFO_VERB("Auto-negotiation has completed, LPA %08lx ADV %08lx\n",
208*59d8a77dSDmitry Borisov                   SiaStatus, Adapter->SymAdvertising);
209*59d8a77dSDmitry Borisov 
210*59d8a77dSDmitry Borisov         AdvLpa = (SiaStatus >> DC_SIA_STATUS_LP_CODE_WORD_SHIFT) & Adapter->SymAdvertising;
211*59d8a77dSDmitry Borisov         if (AdvLpa & MII_ADV_100T_FD)
212*59d8a77dSDmitry Borisov         {
213*59d8a77dSDmitry Borisov             MediaNumber = MEDIA_100TX_FD;
214*59d8a77dSDmitry Borisov         }
215*59d8a77dSDmitry Borisov         else if (AdvLpa & MII_ADV_100T4)
216*59d8a77dSDmitry Borisov         {
217*59d8a77dSDmitry Borisov             MediaNumber = MEDIA_100T4;
218*59d8a77dSDmitry Borisov         }
219*59d8a77dSDmitry Borisov         else if (AdvLpa & MII_ADV_100T_HD)
220*59d8a77dSDmitry Borisov         {
221*59d8a77dSDmitry Borisov             MediaNumber = MEDIA_100TX_HD;
222*59d8a77dSDmitry Borisov         }
223*59d8a77dSDmitry Borisov         else if (AdvLpa & MII_ADV_10T_FD)
224*59d8a77dSDmitry Borisov         {
225*59d8a77dSDmitry Borisov             MediaNumber = MEDIA_10T_FD;
226*59d8a77dSDmitry Borisov         }
227*59d8a77dSDmitry Borisov         else if (AdvLpa & MII_ADV_10T_HD)
228*59d8a77dSDmitry Borisov         {
229*59d8a77dSDmitry Borisov             MediaNumber = MEDIA_10T;
230*59d8a77dSDmitry Borisov         }
231*59d8a77dSDmitry Borisov         else
232*59d8a77dSDmitry Borisov         {
233*59d8a77dSDmitry Borisov             INFO_VERB("No common mode\n");
234*59d8a77dSDmitry Borisov 
235*59d8a77dSDmitry Borisov             /* No common mode, select the other port */
236*59d8a77dSDmitry Borisov             Media143SelectNextMedia(Adapter, SiaStatus);
237*59d8a77dSDmitry Borisov             return;
238*59d8a77dSDmitry Borisov         }
239*59d8a77dSDmitry Borisov     }
240*59d8a77dSDmitry Borisov     else
241*59d8a77dSDmitry Borisov     {
242*59d8a77dSDmitry Borisov         INFO_VERB("Link partner does not support auto-negotiation, CSR12 %08lx\n", SiaStatus);
243*59d8a77dSDmitry Borisov 
244*59d8a77dSDmitry Borisov         /* Check the results of parallel detection */
245*59d8a77dSDmitry Borisov         if (!(SiaStatus & DC_SIA_STATUS_100T_LINK_FAIL))
246*59d8a77dSDmitry Borisov         {
247*59d8a77dSDmitry Borisov             MediaNumber = MEDIA_100TX_HD;
248*59d8a77dSDmitry Borisov         }
249*59d8a77dSDmitry Borisov         else if (!(SiaStatus & DC_SIA_STATUS_10T_LINK_FAIL))
250*59d8a77dSDmitry Borisov         {
251*59d8a77dSDmitry Borisov             MediaNumber = MEDIA_10T;
252*59d8a77dSDmitry Borisov         }
253*59d8a77dSDmitry Borisov         else
254*59d8a77dSDmitry Borisov         {
255*59d8a77dSDmitry Borisov             /* No link detected, select the other port */
256*59d8a77dSDmitry Borisov             Media143SelectNextMedia(Adapter, SiaStatus);
257*59d8a77dSDmitry Borisov             return;
258*59d8a77dSDmitry Borisov         }
259*59d8a77dSDmitry Borisov     }
260*59d8a77dSDmitry Borisov 
261*59d8a77dSDmitry Borisov     if (MEDIA_IS_10T(MediaNumber) && (MediaNumber != Adapter->MediaNumber))
262*59d8a77dSDmitry Borisov     {
263*59d8a77dSDmitry Borisov         /* Set the time limit for auto-negotiation */
264*59d8a77dSDmitry Borisov         Adapter->ModeFlags &= ~DC_MODE_AUTONEG_MASK;
265*59d8a77dSDmitry Borisov         Adapter->ModeFlags |= DC_MODE_AUTONEG_WAIT_INTERRUPT;
266*59d8a77dSDmitry Borisov         NdisMSetTimer(&Adapter->MediaMonitorTimer, 5000);
267*59d8a77dSDmitry Borisov     }
268*59d8a77dSDmitry Borisov     else
269*59d8a77dSDmitry Borisov     {
270*59d8a77dSDmitry Borisov         /* Wait for the link integrity test to complete before we can read the link status */
271*59d8a77dSDmitry Borisov         Adapter->ModeFlags &= ~DC_MODE_AUTONEG_MASK;
272*59d8a77dSDmitry Borisov         Adapter->ModeFlags |= DC_MODE_AUTONEG_LINK_STATUS_CHECK;
273*59d8a77dSDmitry Borisov         NdisMSetTimer(&Adapter->MediaMonitorTimer, 1000);
274*59d8a77dSDmitry Borisov     }
275*59d8a77dSDmitry Borisov 
276*59d8a77dSDmitry Borisov     if (Adapter->MediaNumber != MediaNumber)
277*59d8a77dSDmitry Borisov     {
278*59d8a77dSDmitry Borisov         Adapter->MediaNumber = MediaNumber;
279*59d8a77dSDmitry Borisov         MediaSiaSelect(Adapter);
280*59d8a77dSDmitry Borisov     }
281*59d8a77dSDmitry Borisov }
282*59d8a77dSDmitry Borisov 
283*59d8a77dSDmitry Borisov VOID
MediaLinkStateChange21143(_In_ PDC21X4_ADAPTER Adapter,_In_ ULONG InterruptStatus)284*59d8a77dSDmitry Borisov MediaLinkStateChange21143(
285*59d8a77dSDmitry Borisov     _In_ PDC21X4_ADAPTER Adapter,
286*59d8a77dSDmitry Borisov     _In_ ULONG InterruptStatus)
287*59d8a77dSDmitry Borisov {
288*59d8a77dSDmitry Borisov     ULONG SiaStatus;
289*59d8a77dSDmitry Borisov 
290*59d8a77dSDmitry Borisov     INFO_VERB("Link interrupt, CSR5 %08lx\n", InterruptStatus);
291*59d8a77dSDmitry Borisov 
292*59d8a77dSDmitry Borisov     NdisDprAcquireSpinLock(&Adapter->ModeLock);
293*59d8a77dSDmitry Borisov 
294*59d8a77dSDmitry Borisov     /* Ignore link changes caused by media being estabilished */
295*59d8a77dSDmitry Borisov     if ((Adapter->ModeFlags & DC_MODE_AUTONEG_MASK) == DC_MODE_AUTONEG_LINK_STATUS_CHECK)
296*59d8a77dSDmitry Borisov     {
297*59d8a77dSDmitry Borisov         NdisDprReleaseSpinLock(&Adapter->ModeLock);
298*59d8a77dSDmitry Borisov         return;
299*59d8a77dSDmitry Borisov     }
300*59d8a77dSDmitry Borisov 
301*59d8a77dSDmitry Borisov     SiaStatus = DC_READ(Adapter, DcCsr12_SiaStatus);
302*59d8a77dSDmitry Borisov 
303*59d8a77dSDmitry Borisov     if ((InterruptStatus & DC_IRQ_LINK_FAIL) && MEDIA_IS_10T(Adapter->MediaNumber))
304*59d8a77dSDmitry Borisov     {
305*59d8a77dSDmitry Borisov         /* Link has failed */
306*59d8a77dSDmitry Borisov         Media143Handle10LinkFail(Adapter, SiaStatus);
307*59d8a77dSDmitry Borisov     }
308*59d8a77dSDmitry Borisov     else if (InterruptStatus & DC_IRQ_LINK_PASS)
309*59d8a77dSDmitry Borisov     {
310*59d8a77dSDmitry Borisov         if (DC_READ(Adapter, DcCsr14_SiaTxRx) & DC_SIA_TXRX_AUTONEG)
311*59d8a77dSDmitry Borisov         {
312*59d8a77dSDmitry Borisov             /* Auto-negotiation has completed */
313*59d8a77dSDmitry Borisov             Media143HandleNWayComplete(Adapter, SiaStatus);
314*59d8a77dSDmitry Borisov         }
315*59d8a77dSDmitry Borisov         else
316*59d8a77dSDmitry Borisov         {
317*59d8a77dSDmitry Borisov             /* Link has passed */
318*59d8a77dSDmitry Borisov             Media143Handle10LinkPass(Adapter, SiaStatus);
319*59d8a77dSDmitry Borisov         }
320*59d8a77dSDmitry Borisov     }
321*59d8a77dSDmitry Borisov     else
322*59d8a77dSDmitry Borisov     {
323*59d8a77dSDmitry Borisov         /* NOTE: The Link Changed bit is reserved on the 21142 and always reads as 1 */
324*59d8a77dSDmitry Borisov         if (InterruptStatus & Adapter->LinkStateChangeMask & DC_IRQ_LINK_CHANGED)
325*59d8a77dSDmitry Borisov         {
326*59d8a77dSDmitry Borisov             /* Link has changed */
327*59d8a77dSDmitry Borisov             Media143Handle100LinkChange(Adapter, SiaStatus);
328*59d8a77dSDmitry Borisov         }
329*59d8a77dSDmitry Borisov     }
330*59d8a77dSDmitry Borisov 
331*59d8a77dSDmitry Borisov     NdisDprReleaseSpinLock(&Adapter->ModeLock);
332*59d8a77dSDmitry Borisov }
333*59d8a77dSDmitry Borisov 
334*59d8a77dSDmitry Borisov static
335*59d8a77dSDmitry Borisov BOOLEAN
Media143CheckLink(_In_ PDC21X4_ADAPTER Adapter,_In_ ULONG SiaStatus)336*59d8a77dSDmitry Borisov Media143CheckLink(
337*59d8a77dSDmitry Borisov     _In_ PDC21X4_ADAPTER Adapter,
338*59d8a77dSDmitry Borisov     _In_ ULONG SiaStatus)
339*59d8a77dSDmitry Borisov {
340*59d8a77dSDmitry Borisov     if (MEDIA_IS_100(Adapter->MediaNumber))
341*59d8a77dSDmitry Borisov     {
342*59d8a77dSDmitry Borisov         if (SiaStatus & DC_SIA_STATUS_100T_LINK_FAIL)
343*59d8a77dSDmitry Borisov             return FALSE;
344*59d8a77dSDmitry Borisov     }
345*59d8a77dSDmitry Borisov     else
346*59d8a77dSDmitry Borisov     {
347*59d8a77dSDmitry Borisov         /* The auto-negotiation process can be restarted upon link failure in 10Base-T mode */
348*59d8a77dSDmitry Borisov         if ((SiaStatus & DC_SIA_STATUS_ANS_MASK) != DC_SIA_STATUS_ANS_AUTONEG_COMPLETE)
349*59d8a77dSDmitry Borisov             return FALSE;
350*59d8a77dSDmitry Borisov 
351*59d8a77dSDmitry Borisov         if (SiaStatus & DC_SIA_STATUS_10T_LINK_FAIL)
352*59d8a77dSDmitry Borisov             return FALSE;
353*59d8a77dSDmitry Borisov     }
354*59d8a77dSDmitry Borisov 
355*59d8a77dSDmitry Borisov     return TRUE;
356*59d8a77dSDmitry Borisov }
357*59d8a77dSDmitry Borisov 
358*59d8a77dSDmitry Borisov static
359*59d8a77dSDmitry Borisov VOID
MediaMonitor143(_In_ PDC21X4_ADAPTER Adapter)360*59d8a77dSDmitry Borisov MediaMonitor143(
361*59d8a77dSDmitry Borisov     _In_ PDC21X4_ADAPTER Adapter)
362*59d8a77dSDmitry Borisov {
363*59d8a77dSDmitry Borisov     ULONG SiaStatus;
364*59d8a77dSDmitry Borisov     BOOLEAN LinkUp;
365*59d8a77dSDmitry Borisov 
366*59d8a77dSDmitry Borisov     SiaStatus = DC_READ(Adapter, DcCsr12_SiaStatus);
367*59d8a77dSDmitry Borisov 
368*59d8a77dSDmitry Borisov     switch (Adapter->ModeFlags & DC_MODE_AUTONEG_MASK)
369*59d8a77dSDmitry Borisov     {
370*59d8a77dSDmitry Borisov         case DC_MODE_AUTONEG_WAIT_INTERRUPT:
371*59d8a77dSDmitry Borisov         {
372*59d8a77dSDmitry Borisov             /* Timeout, select the other port */
373*59d8a77dSDmitry Borisov             Media143SelectNextMedia(Adapter, SiaStatus);
374*59d8a77dSDmitry Borisov             break;
375*59d8a77dSDmitry Borisov         }
376*59d8a77dSDmitry Borisov 
377*59d8a77dSDmitry Borisov         case DC_MODE_AUTONEG_LINK_STATUS_CHECK:
378*59d8a77dSDmitry Borisov         {
379*59d8a77dSDmitry Borisov             /* Check the link status */
380*59d8a77dSDmitry Borisov             LinkUp = Media143CheckLink(Adapter, SiaStatus);
381*59d8a77dSDmitry Borisov             if (LinkUp)
382*59d8a77dSDmitry Borisov             {
383*59d8a77dSDmitry Borisov                 Adapter->ModeFlags &= ~DC_MODE_AUTONEG_MASK;
384*59d8a77dSDmitry Borisov                 Adapter->ModeFlags |= DC_MODE_AUTONEG_NONE;
385*59d8a77dSDmitry Borisov 
386*59d8a77dSDmitry Borisov                 MediaIndicateConnect(Adapter, TRUE);
387*59d8a77dSDmitry Borisov             }
388*59d8a77dSDmitry Borisov             else
389*59d8a77dSDmitry Borisov             {
390*59d8a77dSDmitry Borisov                 /* No link detected, select the other port */
391*59d8a77dSDmitry Borisov                 Media143SelectNextMedia(Adapter, SiaStatus);
392*59d8a77dSDmitry Borisov             }
393*59d8a77dSDmitry Borisov             break;
394*59d8a77dSDmitry Borisov         }
395*59d8a77dSDmitry Borisov 
396*59d8a77dSDmitry Borisov         case DC_MODE_AUTONEG_NONE:
397*59d8a77dSDmitry Borisov         {
398*59d8a77dSDmitry Borisov             break;
399*59d8a77dSDmitry Borisov         }
400*59d8a77dSDmitry Borisov 
401*59d8a77dSDmitry Borisov         default:
402*59d8a77dSDmitry Borisov             ASSERT(FALSE);
403*59d8a77dSDmitry Borisov             UNREACHABLE;
404*59d8a77dSDmitry Borisov             break;
405*59d8a77dSDmitry Borisov     }
406*59d8a77dSDmitry Borisov }
407*59d8a77dSDmitry Borisov 
408*59d8a77dSDmitry Borisov VOID
409*59d8a77dSDmitry Borisov NTAPI
MediaMonitor21143Dpc(_In_ PVOID SystemSpecific1,_In_ PVOID FunctionContext,_In_ PVOID SystemSpecific2,_In_ PVOID SystemSpecific3)410*59d8a77dSDmitry Borisov MediaMonitor21143Dpc(
411*59d8a77dSDmitry Borisov     _In_ PVOID SystemSpecific1,
412*59d8a77dSDmitry Borisov     _In_ PVOID FunctionContext,
413*59d8a77dSDmitry Borisov     _In_ PVOID SystemSpecific2,
414*59d8a77dSDmitry Borisov     _In_ PVOID SystemSpecific3)
415*59d8a77dSDmitry Borisov {
416*59d8a77dSDmitry Borisov     PDC21X4_ADAPTER Adapter = FunctionContext;
417*59d8a77dSDmitry Borisov     ULONG DelayMs;
418*59d8a77dSDmitry Borisov     BOOLEAN LinkUp;
419*59d8a77dSDmitry Borisov 
420*59d8a77dSDmitry Borisov     UNREFERENCED_PARAMETER(SystemSpecific1);
421*59d8a77dSDmitry Borisov     UNREFERENCED_PARAMETER(SystemSpecific2);
422*59d8a77dSDmitry Borisov     UNREFERENCED_PARAMETER(SystemSpecific3);
423*59d8a77dSDmitry Borisov 
424*59d8a77dSDmitry Borisov     if (!(Adapter->Flags & DC_ACTIVE))
425*59d8a77dSDmitry Borisov         return;
426*59d8a77dSDmitry Borisov 
427*59d8a77dSDmitry Borisov     NdisDprAcquireSpinLock(&Adapter->ModeLock);
428*59d8a77dSDmitry Borisov 
429*59d8a77dSDmitry Borisov     switch (Adapter->MediaNumber)
430*59d8a77dSDmitry Borisov     {
431*59d8a77dSDmitry Borisov         case MEDIA_MII:
432*59d8a77dSDmitry Borisov         {
433*59d8a77dSDmitry Borisov             LinkUp = MediaMiiCheckLink(Adapter);
434*59d8a77dSDmitry Borisov 
435*59d8a77dSDmitry Borisov             MediaIndicateConnect(Adapter, LinkUp);
436*59d8a77dSDmitry Borisov 
437*59d8a77dSDmitry Borisov             NdisMSetTimer(&Adapter->MediaMonitorTimer, 5000);
438*59d8a77dSDmitry Borisov             break;
439*59d8a77dSDmitry Borisov         }
440*59d8a77dSDmitry Borisov 
441*59d8a77dSDmitry Borisov         case MEDIA_AUI:
442*59d8a77dSDmitry Borisov         case MEDIA_BNC:
443*59d8a77dSDmitry Borisov         case MEDIA_HMR:
444*59d8a77dSDmitry Borisov         {
445*59d8a77dSDmitry Borisov             ULONG ReceiveActivity = (ULONG)Adapter->Statistics.ReceiveOk;
446*59d8a77dSDmitry Borisov 
447*59d8a77dSDmitry Borisov             if (!(Adapter->ModeFlags & DC_MODE_TEST_PACKET))
448*59d8a77dSDmitry Borisov             {
449*59d8a77dSDmitry Borisov                 if ((Adapter->MediaNumber == MEDIA_AUI || Adapter->MediaNumber == MEDIA_HMR) &&
450*59d8a77dSDmitry Borisov                     (DC_READ(Adapter, DcCsr12_SiaStatus) & DC_SIA_STATUS_AUI_ACTIVITY))
451*59d8a77dSDmitry Borisov                 {
452*59d8a77dSDmitry Borisov                     /* Clear the AUI/HMR port activity bit */
453*59d8a77dSDmitry Borisov                     DC_WRITE(Adapter, DcCsr12_SiaStatus, DC_SIA_STATUS_AUI_ACTIVITY);
454*59d8a77dSDmitry Borisov 
455*59d8a77dSDmitry Borisov                     MediaIndicateConnect(Adapter, TRUE);
456*59d8a77dSDmitry Borisov 
457*59d8a77dSDmitry Borisov                     DelayMs = 5000;
458*59d8a77dSDmitry Borisov                 }
459*59d8a77dSDmitry Borisov                 /* Check for any received packets */
460*59d8a77dSDmitry Borisov                 else if (ReceiveActivity != Adapter->LastReceiveActivity)
461*59d8a77dSDmitry Borisov                 {
462*59d8a77dSDmitry Borisov                     MediaIndicateConnect(Adapter, TRUE);
463*59d8a77dSDmitry Borisov 
464*59d8a77dSDmitry Borisov                     DelayMs = 3000;
465*59d8a77dSDmitry Borisov                 }
466*59d8a77dSDmitry Borisov                 else
467*59d8a77dSDmitry Borisov                 {
468*59d8a77dSDmitry Borisov                     /* Send a loopback packet */
469*59d8a77dSDmitry Borisov                     NdisDprAcquireSpinLock(&Adapter->SendLock);
470*59d8a77dSDmitry Borisov                     DcTestPacket(Adapter);
471*59d8a77dSDmitry Borisov                     NdisDprReleaseSpinLock(&Adapter->SendLock);
472*59d8a77dSDmitry Borisov 
473*59d8a77dSDmitry Borisov                     DelayMs = 3000;
474*59d8a77dSDmitry Borisov                 }
475*59d8a77dSDmitry Borisov             }
476*59d8a77dSDmitry Borisov             else
477*59d8a77dSDmitry Borisov             {
478*59d8a77dSDmitry Borisov                 Adapter->ModeFlags &= ~DC_MODE_TEST_PACKET;
479*59d8a77dSDmitry Borisov 
480*59d8a77dSDmitry Borisov                 LinkUp = !!Adapter->MediaTestStatus;
481*59d8a77dSDmitry Borisov 
482*59d8a77dSDmitry Borisov                 MediaIndicateConnect(Adapter, LinkUp);
483*59d8a77dSDmitry Borisov 
484*59d8a77dSDmitry Borisov                 /* Select the other port */
485*59d8a77dSDmitry Borisov                 if (!LinkUp && !MEDIA_IS_FIXED(Adapter))
486*59d8a77dSDmitry Borisov                 {
487*59d8a77dSDmitry Borisov                     Media143SelectNextSerialMedia(Adapter);
488*59d8a77dSDmitry Borisov 
489*59d8a77dSDmitry Borisov                     DelayMs = 3000;
490*59d8a77dSDmitry Borisov                 }
491*59d8a77dSDmitry Borisov                 else
492*59d8a77dSDmitry Borisov                 {
493*59d8a77dSDmitry Borisov                     DelayMs = 5000;
494*59d8a77dSDmitry Borisov                 }
495*59d8a77dSDmitry Borisov             }
496*59d8a77dSDmitry Borisov             Adapter->LastReceiveActivity = ReceiveActivity;
497*59d8a77dSDmitry Borisov 
498*59d8a77dSDmitry Borisov             NdisMSetTimer(&Adapter->MediaMonitorTimer, DelayMs);
499*59d8a77dSDmitry Borisov             break;
500*59d8a77dSDmitry Borisov         }
501*59d8a77dSDmitry Borisov 
502*59d8a77dSDmitry Borisov         default:
503*59d8a77dSDmitry Borisov         {
504*59d8a77dSDmitry Borisov             MediaMonitor143(Adapter);
505*59d8a77dSDmitry Borisov             break;
506*59d8a77dSDmitry Borisov         }
507*59d8a77dSDmitry Borisov     }
508*59d8a77dSDmitry Borisov 
509*59d8a77dSDmitry Borisov     NdisDprReleaseSpinLock(&Adapter->ModeLock);
510*59d8a77dSDmitry Borisov }
511