xref: /reactos/drivers/network/dd/dc21x4/media140.c (revision 9c544a55)
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