xref: /reactos/drivers/network/dd/dc21x4/media041.c (revision d6eebaa4)
1 /*
2  * PROJECT:     ReactOS DC21x4 Driver
3  * LICENSE:     GPL-2.0-or-later (https://spdx.org/licenses/GPL-2.0-or-later)
4  * PURPOSE:     21041 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 MediaLinkStateChange21041(
18     _In_ PDC21X4_ADAPTER Adapter,
19     _In_ ULONG InterruptStatus)
20 {
21     NdisDprAcquireSpinLock(&Adapter->ModeLock);
22 
23     if (InterruptStatus & DC_IRQ_LINK_PASS)
24     {
25         INFO_VERB("Link passed, CSR12 %08lx\n", DC_READ(Adapter, DcCsr12_SiaStatus));
26 
27         /* 10Base-T is the active port now */
28         if (MEDIA_IS_AUI_BNC(Adapter->MediaNumber))
29         {
30             /* Switch to TP medium */
31             if (!MEDIA_IS_FIXED(Adapter))
32             {
33                 Adapter->MediaNumber = MEDIA_10T;
34                 MediaSiaSelect(Adapter);
35 
36                 NdisMSetTimer(&Adapter->MediaMonitorTimer, 3000);
37             }
38         }
39 
40         /* 10Base-T link is up */
41         if (!MEDIA_IS_AUI_BNC(Adapter->MediaNumber))
42         {
43             MediaIndicateConnect(Adapter, TRUE);
44         }
45     }
46     else // DC_IRQ_LINK_FAIL
47     {
48         INFO_VERB("Link failed, CSR12 %08lx\n", DC_READ(Adapter, DcCsr12_SiaStatus));
49 
50         /* 10Base-T link is down */
51         if (!MEDIA_IS_AUI_BNC(Adapter->MediaNumber))
52         {
53             MediaIndicateConnect(Adapter, FALSE);
54         }
55     }
56 
57     NdisDprReleaseSpinLock(&Adapter->ModeLock);
58 }
59 
60 static
61 VOID
62 Media041SelectNextMedia(
63     _In_ PDC21X4_ADAPTER Adapter)
64 {
65     if (Adapter->MediaNumber == MEDIA_AUI)
66         Adapter->ModeFlags |= DC_MODE_AUI_FAILED;
67     else if (Adapter->MediaNumber == MEDIA_BNC)
68         Adapter->ModeFlags |= DC_MODE_BNC_FAILED;
69 
70     if ((Adapter->ModeFlags & (DC_MODE_AUI_FAILED | DC_MODE_BNC_FAILED)) ==
71         (DC_MODE_AUI_FAILED | DC_MODE_BNC_FAILED))
72     {
73         Adapter->MediaNumber = MEDIA_10T;
74     }
75     else
76     {
77         Adapter->MediaNumber = (MEDIA_BNC + MEDIA_AUI) - Adapter->MediaNumber;
78     }
79 
80     MediaSiaSelect(Adapter);
81 }
82 
83 VOID
84 NTAPI
85 MediaMonitor21041Dpc(
86     _In_ PVOID SystemSpecific1,
87     _In_ PVOID FunctionContext,
88     _In_ PVOID SystemSpecific2,
89     _In_ PVOID SystemSpecific3)
90 {
91     PDC21X4_ADAPTER Adapter = FunctionContext;
92     BOOLEAN LinkUp, Report;
93     ULONG DelayMs, SiaStatus;
94 
95     UNREFERENCED_PARAMETER(SystemSpecific1);
96     UNREFERENCED_PARAMETER(SystemSpecific2);
97     UNREFERENCED_PARAMETER(SystemSpecific3);
98 
99     if (!(Adapter->Flags & DC_ACTIVE))
100         return;
101 
102     Report = FALSE;
103     DelayMs = 5000;
104 
105     NdisDprAcquireSpinLock(&Adapter->ModeLock);
106 
107     SiaStatus = DC_READ(Adapter, DcCsr12_SiaStatus);
108 
109     if (MEDIA_IS_AUI_BNC(Adapter->MediaNumber))
110     {
111         if ((Adapter->ModeFlags & DC_MODE_PORT_AUTOSENSE))
112         {
113             Adapter->ModeFlags &= ~DC_MODE_PORT_AUTOSENSE;
114 
115             /* Select the other port */
116             if (!(SiaStatus & DC_SIA_STATUS_SELECTED_PORT_ACTIVITY))
117             {
118                 Adapter->MediaNumber = MEDIA_BNC;
119                 MediaSiaSelect(Adapter);
120             }
121 
122             DelayMs = 1000;
123         }
124         else
125         {
126             ULONG ReceiveActivity = (ULONG)Adapter->Statistics.ReceiveOk;
127 
128             if (!(Adapter->ModeFlags & DC_MODE_TEST_PACKET))
129             {
130                 if ((Adapter->MediaNumber == MEDIA_AUI) &&
131                     (SiaStatus & DC_SIA_STATUS_SELECTED_PORT_ACTIVITY))
132                 {
133                     /* Clear the selected port activity bit */
134                     DC_WRITE(Adapter, DcCsr12_SiaStatus, DC_SIA_STATUS_SELECTED_PORT_ACTIVITY);
135 
136                     LinkUp = TRUE;
137                     Report = TRUE;
138                 }
139                 /* Check for any received packets */
140                 else if (ReceiveActivity != Adapter->LastReceiveActivity)
141                 {
142                     LinkUp = TRUE;
143                     Report = TRUE;
144 
145                     DelayMs = 3000;
146                 }
147                 else
148                 {
149                     /* Send a loopback packet */
150                     NdisDprAcquireSpinLock(&Adapter->SendLock);
151                     DcTestPacket(Adapter);
152                     NdisDprReleaseSpinLock(&Adapter->SendLock);
153 
154                     DelayMs = 3000;
155                 }
156             }
157             else
158             {
159                 Adapter->ModeFlags &= ~DC_MODE_TEST_PACKET;
160 
161                 LinkUp = !!Adapter->MediaTestStatus;
162                 Report = TRUE;
163 
164                 /* Select the other port */
165                 if (!LinkUp && !MEDIA_IS_FIXED(Adapter))
166                 {
167                     Media041SelectNextMedia(Adapter);
168 
169                     DelayMs = 3000;
170                 }
171             }
172             Adapter->LastReceiveActivity = ReceiveActivity;
173         }
174     }
175     else // 10Base-T
176     {
177         Report = TRUE;
178         LinkUp = !(SiaStatus & (DC_SIA_STATUS_NETWORK_CONNECTION_ERROR |
179                                 DC_SIA_STATUS_10T_LINK_FAIL));
180 
181         if (!LinkUp)
182         {
183             DelayMs = 3000;
184 
185             /* Select the AUI or BNC port */
186             if (!MEDIA_IS_FIXED(Adapter) && (Adapter->MediaBitmap & MEDIA_AUI_BNC_MASK))
187             {
188                 Adapter->ModeFlags &= ~(DC_MODE_AUI_FAILED |
189                                         DC_MODE_BNC_FAILED |
190                                         DC_MODE_TEST_PACKET);
191 
192                 if (SiaStatus & DC_SIA_STATUS_NONSEL_PORT_ACTIVITY)
193                 {
194                     Adapter->MediaNumber = MEDIA_AUI;
195                     Adapter->ModeFlags |= DC_MODE_PORT_AUTOSENSE;
196                 }
197                 else
198                 {
199                     Adapter->MediaNumber = MEDIA_BNC;
200                 }
201                 MediaSiaSelect(Adapter);
202 
203                 Adapter->LastReceiveActivity = (ULONG)Adapter->Statistics.ReceiveOk;
204 
205                 /* Clear the port activity bits */
206                 DC_WRITE(Adapter, DcCsr12_SiaStatus, DC_SIA_STATUS_SELECTED_PORT_ACTIVITY |
207                                                      DC_SIA_STATUS_NONSEL_PORT_ACTIVITY);
208 
209                 DelayMs = 1000;
210             }
211         }
212     }
213 
214     if (Report)
215     {
216         MediaIndicateConnect(Adapter, LinkUp);
217     }
218 
219     NdisDprReleaseSpinLock(&Adapter->ModeLock);
220 
221     NdisMSetTimer(&Adapter->MediaMonitorTimer, DelayMs);
222 }
223