xref: /reactos/drivers/network/dd/dc21x4/media040.c (revision 14d3b53c)
1 /*
2  * PROJECT:     ReactOS DC21x4 Driver
3  * LICENSE:     GPL-2.0-or-later (https://spdx.org/licenses/GPL-2.0-or-later)
4  * PURPOSE:     21040 media support code
5  * COPYRIGHT:   Copyright 2023 Dmitry Borisov <di.sean@protonmail.com>
6  */
7 
8 /* INCLUDES *******************************************************************/
9 
10 #include "dc21x4.h"
11 
12 #include <debug.h>
13 
14 /* FUNCTIONS ******************************************************************/
15 
16 VOID
17 MediaLinkStateChange21040(
18     _In_ PDC21X4_ADAPTER Adapter,
19     _In_ ULONG InterruptStatus)
20 {
21     UNREFERENCED_PARAMETER(InterruptStatus);
22 
23     INFO_VERB("Link failed, CSR12 %08lx\n", DC_READ(Adapter, DcCsr12_SiaStatus));
24 
25     NdisDprAcquireSpinLock(&Adapter->ModeLock);
26 
27     /* Start the media timer when the 10Base-T link has changed state */
28     if (Adapter->MediaNumber != MEDIA_BNC)
29     {
30         MediaIndicateConnect(Adapter, FALSE);
31 
32         NdisMSetTimer(&Adapter->MediaMonitorTimer, 3000);
33     }
34 
35     NdisDprReleaseSpinLock(&Adapter->ModeLock);
36 }
37 
38 VOID
39 NTAPI
40 MediaMonitor21040Dpc(
41     _In_ PVOID SystemSpecific1,
42     _In_ PVOID FunctionContext,
43     _In_ PVOID SystemSpecific2,
44     _In_ PVOID SystemSpecific3)
45 {
46     PDC21X4_ADAPTER Adapter = FunctionContext;
47     BOOLEAN LinkUp, Report, RunAgain;
48 
49     UNREFERENCED_PARAMETER(SystemSpecific1);
50     UNREFERENCED_PARAMETER(SystemSpecific2);
51     UNREFERENCED_PARAMETER(SystemSpecific3);
52 
53     if (!(Adapter->Flags & DC_ACTIVE))
54         return;
55 
56     LinkUp = FALSE;
57     Report = FALSE;
58     RunAgain = TRUE;
59 
60     NdisDprAcquireSpinLock(&Adapter->ModeLock);
61 
62     if (Adapter->MediaNumber != MEDIA_BNC)
63     {
64         ULONG SiaStatus = DC_READ(Adapter, DcCsr12_SiaStatus);
65 
66         Report = TRUE;
67         LinkUp = !(SiaStatus & (DC_SIA_STATUS_NETWORK_CONNECTION_ERROR |
68                                 DC_SIA_STATUS_10T_LINK_FAIL));
69 
70         if (!LinkUp)
71         {
72             /* Select the other port */
73             if (!MEDIA_IS_FIXED(Adapter))
74             {
75                 Adapter->MediaNumber = MEDIA_BNC;
76 
77                 DcWriteSia(Adapter,
78                            Adapter->Media[MEDIA_BNC].Csr13,
79                            Adapter->Media[MEDIA_BNC].Csr14,
80                            Adapter->Media[MEDIA_BNC].Csr15);
81 
82                 Adapter->LastReceiveActivity = (ULONG)Adapter->Statistics.ReceiveOk;
83             }
84         }
85         else
86         {
87             /* Wait until the next link change event */
88             RunAgain = FALSE;
89         }
90     }
91     else
92     {
93         ULONG ReceiveActivity = (ULONG)Adapter->Statistics.ReceiveOk;
94 
95         if (!(Adapter->ModeFlags & DC_MODE_TEST_PACKET))
96         {
97             /* Check for any received packets */
98             if (ReceiveActivity != Adapter->LastReceiveActivity)
99             {
100                 LinkUp = TRUE;
101                 Report = TRUE;
102             }
103             else
104             {
105                 /* Send a loopback packet */
106                 NdisDprAcquireSpinLock(&Adapter->SendLock);
107                 DcTestPacket(Adapter);
108                 NdisDprReleaseSpinLock(&Adapter->SendLock);
109             }
110         }
111         else
112         {
113             Adapter->ModeFlags &= ~DC_MODE_TEST_PACKET;
114 
115             LinkUp = !!Adapter->MediaTestStatus;
116             Report = TRUE;
117 
118             /* Select the other port */
119             if (!LinkUp && !MEDIA_IS_FIXED(Adapter))
120             {
121                 Adapter->MediaNumber = MEDIA_10T;
122 
123                 DcWriteSia(Adapter,
124                            Adapter->Media[MEDIA_10T].Csr13,
125                            Adapter->Media[MEDIA_10T].Csr14,
126                            Adapter->Media[MEDIA_10T].Csr15);
127             }
128         }
129         Adapter->LastReceiveActivity = ReceiveActivity;
130     }
131 
132     if (Report)
133     {
134         MediaIndicateConnect(Adapter, LinkUp);
135     }
136 
137     NdisDprReleaseSpinLock(&Adapter->ModeLock);
138 
139     if (RunAgain)
140     {
141         NdisMSetTimer(&Adapter->MediaMonitorTimer, LinkUp ? 6000 : 3000);
142     }
143 }
144