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