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
NICQueryStatisticCounter(_In_ PE1000_ADAPTER Adapter,_In_ NDIS_OID Oid)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
NICFillPowerManagementCapabilities(_In_ PE1000_ADAPTER Adapter,_Out_ PNDIS_PNP_CAPABILITIES Capabilities)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
MiniportQueryInformation(IN NDIS_HANDLE MiniportAdapterContext,IN NDIS_OID Oid,IN PVOID InformationBuffer,IN ULONG InformationBufferLength,OUT PULONG BytesWritten,OUT PULONG BytesNeeded)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
MiniportSetInformation(IN NDIS_HANDLE MiniportAdapterContext,IN NDIS_OID Oid,IN PVOID InformationBuffer,IN ULONG InformationBufferLength,OUT PULONG BytesRead,OUT PULONG BytesNeeded)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