xref: /reactos/drivers/network/dd/e1000/info.c (revision 1734f297)
1 /*
2  * PROJECT:     ReactOS Intel PRO/1000 Driver
3  * LICENSE:     GPL-2.0+ (https://spdx.org/licenses/GPL-2.0+)
4  * PURPOSE:     Miniport information callbacks
5  * COPYRIGHT:   2013 Cameron Gutman (cameron.gutman@reactos.org)
6  *              2018 Mark Jansen (mark.jansen@reactos.org)
7  */
8 
9 #include "nic.h"
10 
11 #include <debug.h>
12 
13 static NDIS_OID SupportedOidList[] =
14 {
15     OID_GEN_SUPPORTED_LIST,
16     OID_GEN_CURRENT_PACKET_FILTER,
17     OID_GEN_HARDWARE_STATUS,
18     OID_GEN_MEDIA_SUPPORTED,
19     OID_GEN_MEDIA_IN_USE,
20     OID_GEN_MAXIMUM_LOOKAHEAD,
21     OID_GEN_MAXIMUM_FRAME_SIZE,
22     OID_GEN_MAXIMUM_SEND_PACKETS,
23     OID_GEN_LINK_SPEED,
24     OID_GEN_TRANSMIT_BUFFER_SPACE,
25     OID_GEN_RECEIVE_BUFFER_SPACE,
26     OID_GEN_RECEIVE_BLOCK_SIZE,
27     OID_GEN_TRANSMIT_BLOCK_SIZE,
28     OID_GEN_VENDOR_ID,
29     OID_GEN_VENDOR_DESCRIPTION,
30     OID_GEN_VENDOR_DRIVER_VERSION,
31     OID_GEN_CURRENT_LOOKAHEAD,
32     OID_802_3_MULTICAST_LIST,
33     OID_GEN_DRIVER_VERSION,
34     OID_GEN_MAXIMUM_TOTAL_SIZE,
35     OID_GEN_MAC_OPTIONS,
36     OID_GEN_MEDIA_CONNECT_STATUS,
37     OID_802_3_PERMANENT_ADDRESS,
38     OID_802_3_CURRENT_ADDRESS,
39     OID_802_3_MAXIMUM_LIST_SIZE,
40 
41     /* Statistics */
42     OID_GEN_XMIT_OK,
43     OID_GEN_RCV_OK,
44     OID_GEN_XMIT_ERROR,
45     OID_GEN_RCV_ERROR,
46     OID_GEN_RCV_NO_BUFFER,
47 
48     OID_PNP_CAPABILITIES,
49 };
50 
51 static
52 ULONG64
53 NICQueryStatisticCounter(
54     _In_ PE1000_ADAPTER Adapter,
55     _In_ NDIS_OID Oid)
56 {
57     /* TODO */
58     return 0;
59 }
60 
61 static
62 NDIS_STATUS
63 NICFillPowerManagementCapabilities(
64     _In_ PE1000_ADAPTER Adapter,
65     _Out_ PNDIS_PNP_CAPABILITIES Capabilities)
66 {
67     /* TODO */
68     return NDIS_STATUS_NOT_SUPPORTED;
69 }
70 
71 NDIS_STATUS
72 NTAPI
73 MiniportQueryInformation(
74     IN NDIS_HANDLE MiniportAdapterContext,
75     IN NDIS_OID Oid,
76     IN PVOID InformationBuffer,
77     IN ULONG InformationBufferLength,
78     OUT PULONG BytesWritten,
79     OUT PULONG BytesNeeded)
80 {
81     PE1000_ADAPTER Adapter = (PE1000_ADAPTER)MiniportAdapterContext;
82     ULONG copyLength;
83     PVOID copySource;
84     NDIS_STATUS status;
85     union _GENERIC_INFORMATION
86     {
87         USHORT Ushort;
88         ULONG Ulong;
89         ULONG64 Ulong64;
90         NDIS_MEDIUM Medium;
91         NDIS_PNP_CAPABILITIES PmCapabilities;
92     } GenericInfo;
93 
94     status = NDIS_STATUS_SUCCESS;
95     copySource = &GenericInfo;
96     copyLength = sizeof(ULONG);
97 
98     switch (Oid)
99     {
100     case OID_GEN_SUPPORTED_LIST:
101         copySource = (PVOID)&SupportedOidList;
102         copyLength = sizeof(SupportedOidList);
103         break;
104 
105     case OID_GEN_CURRENT_PACKET_FILTER:
106         GenericInfo.Ulong = Adapter->PacketFilter;
107         break;
108 
109     case OID_GEN_HARDWARE_STATUS:
110         UNIMPLEMENTED_DBGBREAK();
111         GenericInfo.Ulong = (ULONG)NdisHardwareStatusReady; //FIXME
112         break;
113 
114     case OID_GEN_MEDIA_SUPPORTED:
115     case OID_GEN_MEDIA_IN_USE:
116     {
117         GenericInfo.Medium = NdisMedium802_3;
118         copyLength = sizeof(NDIS_MEDIUM);
119         break;
120     }
121 
122     case OID_GEN_RECEIVE_BLOCK_SIZE:
123     case OID_GEN_TRANSMIT_BLOCK_SIZE:
124     case OID_GEN_CURRENT_LOOKAHEAD:
125     case OID_GEN_MAXIMUM_LOOKAHEAD:
126     case OID_GEN_MAXIMUM_FRAME_SIZE:
127         GenericInfo.Ulong = MAXIMUM_FRAME_SIZE - sizeof(ETH_HEADER);
128         break;
129 
130     case OID_802_3_MULTICAST_LIST:
131         copySource = Adapter->MulticastList;
132         copyLength = Adapter->MulticastListSize * IEEE_802_ADDR_LENGTH;
133         break;
134 
135     case OID_802_3_MAXIMUM_LIST_SIZE:
136         GenericInfo.Ulong = MAXIMUM_MULTICAST_ADDRESSES;
137         break;
138 
139     case OID_GEN_LINK_SPEED:
140         GenericInfo.Ulong = Adapter->LinkSpeedMbps * 10000;
141         break;
142 
143     case OID_GEN_TRANSMIT_BUFFER_SPACE:
144         GenericInfo.Ulong = MAXIMUM_FRAME_SIZE;
145         break;
146 
147     case OID_GEN_RECEIVE_BUFFER_SPACE:
148         GenericInfo.Ulong = RECEIVE_BUFFER_SIZE;
149         break;
150 
151     case OID_GEN_VENDOR_ID:
152         /* The 3 bytes of the MAC address is the vendor ID */
153         GenericInfo.Ulong = 0;
154         GenericInfo.Ulong |= (Adapter->PermanentMacAddress[0] << 16);
155         GenericInfo.Ulong |= (Adapter->PermanentMacAddress[1] << 8);
156         GenericInfo.Ulong |= (Adapter->PermanentMacAddress[2] & 0xFF);
157         break;
158 
159     case OID_GEN_VENDOR_DESCRIPTION:
160     {
161         static UCHAR vendorDesc[] = "ReactOS Team";
162         copySource = vendorDesc;
163         copyLength = sizeof(vendorDesc);
164         break;
165     }
166 
167     case OID_GEN_VENDOR_DRIVER_VERSION:
168         GenericInfo.Ulong = DRIVER_VERSION;
169         break;
170 
171     case OID_GEN_DRIVER_VERSION:
172     {
173         copyLength = sizeof(USHORT);
174         GenericInfo.Ushort = (NDIS_MINIPORT_MAJOR_VERSION << 8) + NDIS_MINIPORT_MINOR_VERSION;
175         break;
176     }
177 
178     case OID_GEN_MAXIMUM_TOTAL_SIZE:
179         GenericInfo.Ulong = MAXIMUM_FRAME_SIZE;
180         break;
181 
182     case OID_GEN_MAXIMUM_SEND_PACKETS:
183         GenericInfo.Ulong = 1;
184         break;
185 
186     case OID_GEN_MAC_OPTIONS:
187         GenericInfo.Ulong = NDIS_MAC_OPTION_RECEIVE_SERIALIZED |
188             NDIS_MAC_OPTION_COPY_LOOKAHEAD_DATA |
189             NDIS_MAC_OPTION_TRANSFERS_NOT_PEND |
190             NDIS_MAC_OPTION_NO_LOOPBACK;
191         break;
192 
193     case OID_GEN_MEDIA_CONNECT_STATUS:
194         GenericInfo.Ulong = Adapter->MediaState;
195         break;
196 
197     case OID_802_3_CURRENT_ADDRESS:
198         copySource = Adapter->MulticastList[0].MacAddress;
199         copyLength = IEEE_802_ADDR_LENGTH;
200         break;
201 
202     case OID_802_3_PERMANENT_ADDRESS:
203         copySource = Adapter->PermanentMacAddress;
204         copyLength = IEEE_802_ADDR_LENGTH;
205         break;
206 
207     case OID_GEN_XMIT_OK:
208     case OID_GEN_RCV_OK:
209     case OID_GEN_XMIT_ERROR:
210     case OID_GEN_RCV_ERROR:
211     case OID_GEN_RCV_NO_BUFFER:
212     {
213         GenericInfo.Ulong64 = NICQueryStatisticCounter(Adapter, Oid);
214 
215         *BytesNeeded = sizeof(ULONG64);
216         if (InformationBufferLength >= sizeof(ULONG64))
217         {
218             *BytesWritten = sizeof(ULONG64);
219             NdisMoveMemory(InformationBuffer, copySource, sizeof(ULONG64));
220         }
221         else if (InformationBufferLength >= sizeof(ULONG))
222         {
223             *BytesWritten = sizeof(ULONG);
224             NdisMoveMemory(InformationBuffer, copySource, sizeof(ULONG));
225         }
226         else
227         {
228             *BytesWritten = 0;
229             return NDIS_STATUS_BUFFER_TOO_SHORT;
230         }
231         return NDIS_STATUS_SUCCESS;
232     }
233 
234     case OID_PNP_CAPABILITIES:
235     {
236         copyLength = sizeof(NDIS_PNP_CAPABILITIES);
237 
238         status = NICFillPowerManagementCapabilities(Adapter, &GenericInfo.PmCapabilities);
239         break;
240     }
241 
242     default:
243         NDIS_DbgPrint(MIN_TRACE, ("Unknown OID 0x%x(%s)\n", Oid, Oid2Str(Oid)));
244         status = NDIS_STATUS_NOT_SUPPORTED;
245         break;
246     }
247 
248     if (status == NDIS_STATUS_SUCCESS)
249     {
250         if (copyLength > InformationBufferLength)
251         {
252             *BytesNeeded = copyLength;
253             *BytesWritten = 0;
254             status = NDIS_STATUS_BUFFER_TOO_SHORT;
255         }
256         else
257         {
258             NdisMoveMemory(InformationBuffer, copySource, copyLength);
259             *BytesWritten = copyLength;
260             *BytesNeeded = copyLength;
261         }
262     }
263     else
264     {
265         *BytesWritten = 0;
266         *BytesNeeded = 0;
267     }
268 
269     NDIS_DbgPrint(MAX_TRACE, ("Query OID 0x%x(%s): Completed with status 0x%x (%d, %d)\n",
270                               Oid, Oid2Str(Oid), status, *BytesWritten, *BytesNeeded));
271     return status;
272 }
273 
274 NDIS_STATUS
275 NTAPI
276 MiniportSetInformation(
277     IN NDIS_HANDLE MiniportAdapterContext,
278     IN NDIS_OID Oid,
279     IN PVOID InformationBuffer,
280     IN ULONG InformationBufferLength,
281     OUT PULONG BytesRead,
282     OUT PULONG BytesNeeded)
283 {
284     PE1000_ADAPTER Adapter = (PE1000_ADAPTER)MiniportAdapterContext;
285     ULONG genericUlong;
286     NDIS_STATUS status;
287 
288     status = NDIS_STATUS_SUCCESS;
289 
290     switch (Oid)
291     {
292     case OID_GEN_CURRENT_PACKET_FILTER:
293         if (InformationBufferLength < sizeof(ULONG))
294         {
295             *BytesRead = 0;
296             *BytesNeeded = sizeof(ULONG);
297             status = NDIS_STATUS_INVALID_LENGTH;
298             break;
299         }
300 
301         NdisMoveMemory(&genericUlong, InformationBuffer, sizeof(ULONG));
302 
303         if (genericUlong &
304             ~(NDIS_PACKET_TYPE_DIRECTED |
305               NDIS_PACKET_TYPE_MULTICAST |
306               NDIS_PACKET_TYPE_ALL_MULTICAST |
307               NDIS_PACKET_TYPE_BROADCAST |
308               NDIS_PACKET_TYPE_PROMISCUOUS |
309               NDIS_PACKET_TYPE_MAC_FRAME))
310         {
311             *BytesRead = sizeof(ULONG);
312             *BytesNeeded = sizeof(ULONG);
313             status = NDIS_STATUS_NOT_SUPPORTED;
314             break;
315         }
316 
317         if (Adapter->PacketFilter == genericUlong)
318         {
319             break;
320         }
321 
322         Adapter->PacketFilter = genericUlong;
323 
324         status = NICApplyPacketFilter(Adapter);
325         if (status != NDIS_STATUS_SUCCESS)
326         {
327             NDIS_DbgPrint(MIN_TRACE, ("Failed to apply new packet filter (0x%x)\n", status));
328             break;
329         }
330 
331         break;
332 
333     case OID_GEN_CURRENT_LOOKAHEAD:
334         if (InformationBufferLength < sizeof(ULONG))
335         {
336             *BytesRead = 0;
337             *BytesNeeded = sizeof(ULONG);
338             status = NDIS_STATUS_INVALID_LENGTH;
339             break;
340         }
341 
342         NdisMoveMemory(&genericUlong, InformationBuffer, sizeof(ULONG));
343 
344         if (genericUlong > MAXIMUM_FRAME_SIZE - sizeof(ETH_HEADER))
345         {
346             status = NDIS_STATUS_INVALID_DATA;
347         }
348         else
349         {
350             // Ignore this...
351         }
352 
353         break;
354 
355     case OID_802_3_MULTICAST_LIST:
356         if (InformationBufferLength % IEEE_802_ADDR_LENGTH)
357         {
358             *BytesRead = 0;
359             *BytesNeeded = InformationBufferLength + (InformationBufferLength % IEEE_802_ADDR_LENGTH);
360             status = NDIS_STATUS_INVALID_LENGTH;
361             break;
362         }
363 
364         if (InformationBufferLength > sizeof(Adapter->MulticastList))
365         {
366             *BytesNeeded = sizeof(Adapter->MulticastList);
367             *BytesRead = 0;
368             status = NDIS_STATUS_MULTICAST_FULL;
369             break;
370         }
371 
372         NdisMoveMemory(Adapter->MulticastList, InformationBuffer, InformationBufferLength);
373 
374         Adapter->MulticastListSize = InformationBufferLength / IEEE_802_ADDR_LENGTH;
375 
376         NICUpdateMulticastList(Adapter);
377         break;
378 
379     default:
380         NDIS_DbgPrint(MIN_TRACE, ("Unknown OID 0x%x(%s)\n", Oid, Oid2Str(Oid)));
381         status = NDIS_STATUS_NOT_SUPPORTED;
382         *BytesRead = 0;
383         *BytesNeeded = 0;
384         break;
385     }
386 
387     if (status == NDIS_STATUS_SUCCESS)
388     {
389         *BytesRead = InformationBufferLength;
390         *BytesNeeded = 0;
391     }
392 
393     return status;
394 }
395 
396