1 /* 2 * PROJECT: ReactOS DC21x4 Driver 3 * LICENSE: GPL-2.0-or-later (https://spdx.org/licenses/GPL-2.0-or-later) 4 * PURPOSE: 21140 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 static 17 BOOLEAN 18 MediaGprCheckLink( 19 _In_ PDC21X4_ADAPTER Adapter) 20 { 21 ULONG GpioData; 22 PDC_MEDIA Media; 23 24 Media = &Adapter->Media[Adapter->MediaNumber]; 25 26 /* No media activity indicator */ 27 if (Media->LinkMask == 0) 28 { 29 TRACE("No activity indicator\n"); 30 31 /* Assume we have a link */ 32 if (MEDIA_IS_FIXED(Adapter)) 33 return TRUE; 34 35 return FALSE; 36 } 37 38 GpioData = DC_READ(Adapter, DcCsr12_Gpio); 39 40 TRACE("CSR12 %08lx\n", GpioData); 41 42 /* This media supports link indication via GPIO pins */ 43 return !!((GpioData & Media->LinkMask) ^ Media->Polarity); 44 } 45 46 static 47 ULONG 48 MediaGprNextMedia( 49 _In_ PDC21X4_ADAPTER Adapter) 50 { 51 ULONG i; 52 53 /* No half-duplex media in the media list */ 54 if (!(Adapter->MediaBitmap & ~MEDIA_FD_MASK)) 55 { 56 return Adapter->MediaNumber; 57 } 58 59 /* Find the next half-duplex media */ 60 i = Adapter->MediaNumber; 61 while (TRUE) 62 { 63 /* We have reached the end of the media list, try the first media */ 64 if (i == 0) 65 { 66 _BitScanReverse(&i, Adapter->MediaBitmap); 67 } 68 else 69 { 70 --i; 71 } 72 73 if ((Adapter->MediaBitmap & (1 << i)) && !MEDIA_IS_FD(i)) 74 { 75 return i; 76 } 77 } 78 } 79 80 VOID 81 NTAPI 82 MediaMonitor21140Dpc( 83 _In_ PVOID SystemSpecific1, 84 _In_ PVOID FunctionContext, 85 _In_ PVOID SystemSpecific2, 86 _In_ PVOID SystemSpecific3) 87 { 88 PDC21X4_ADAPTER Adapter = FunctionContext; 89 ULONG DelayMs, MediaNumber; 90 BOOLEAN LinkUp; 91 92 UNREFERENCED_PARAMETER(SystemSpecific1); 93 UNREFERENCED_PARAMETER(SystemSpecific2); 94 UNREFERENCED_PARAMETER(SystemSpecific3); 95 96 if (!(Adapter->Flags & DC_ACTIVE)) 97 return; 98 99 NdisDprAcquireSpinLock(&Adapter->ModeLock); 100 101 if (Adapter->MediaNumber == MEDIA_MII) 102 { 103 LinkUp = MediaMiiCheckLink(Adapter); 104 105 DelayMs = 5000; 106 } 107 else 108 { 109 LinkUp = MediaGprCheckLink(Adapter); 110 111 /* This media is unconnected, try the next media */ 112 if (!LinkUp && !MEDIA_IS_FIXED(Adapter)) 113 { 114 MediaNumber = MediaGprNextMedia(Adapter); 115 116 if (Adapter->MediaNumber != MediaNumber) 117 { 118 Adapter->MediaNumber = MediaNumber; 119 MediaGprSelect(Adapter); 120 } 121 122 DelayMs = 3000; 123 } 124 else 125 { 126 /* If we are forcing media, then we need to poll the media less frequently */ 127 DelayMs = 5000; 128 } 129 } 130 131 MediaIndicateConnect(Adapter, LinkUp); 132 133 NdisDprReleaseSpinLock(&Adapter->ModeLock); 134 135 NdisMSetTimer(&Adapter->MediaMonitorTimer, DelayMs); 136 } 137