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