xref: /reactos/drivers/network/dd/rtl8139/info.c (revision 34593d93)
1 /*
2  * ReactOS Realtek 8139 Driver
3  *
4  * Copyright (C) 2013 Cameron Gutman
5  *
6  * This program is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation; either version 2 of the License, or
9  * (at your option) any later version.
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License along
17  * with this program; if not, write to the Free Software Foundation, Inc.,
18  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
19  *
20  */
21 
22 #include "nic.h"
23 
24 #define NDEBUG
25 #include <debug.h>
26 
27 static ULONG SupportedOidList[] =
28 {
29     OID_GEN_SUPPORTED_LIST,
30     OID_GEN_HARDWARE_STATUS,
31     OID_GEN_MEDIA_SUPPORTED,
32     OID_GEN_MEDIA_IN_USE,
33     OID_GEN_MAXIMUM_LOOKAHEAD,
34     OID_GEN_MAXIMUM_FRAME_SIZE,
35     OID_GEN_LINK_SPEED,
36     OID_GEN_TRANSMIT_BUFFER_SPACE,
37     OID_GEN_RECEIVE_BUFFER_SPACE,
38     OID_GEN_RECEIVE_BLOCK_SIZE,
39     OID_GEN_TRANSMIT_BLOCK_SIZE,
40     OID_GEN_VENDOR_ID,
41     OID_GEN_VENDOR_DESCRIPTION,
42     OID_GEN_VENDOR_DRIVER_VERSION,
43     OID_GEN_CURRENT_PACKET_FILTER,
44     OID_GEN_CURRENT_LOOKAHEAD,
45     OID_GEN_DRIVER_VERSION,
46     OID_GEN_MAXIMUM_TOTAL_SIZE,
47     OID_GEN_PROTOCOL_OPTIONS,
48     OID_GEN_MAC_OPTIONS,
49     OID_GEN_MEDIA_CONNECT_STATUS,
50     OID_GEN_MAXIMUM_SEND_PACKETS,
51     OID_GEN_XMIT_OK,
52     OID_GEN_RCV_OK,
53     OID_GEN_XMIT_ERROR,
54     OID_GEN_RCV_ERROR,
55     OID_GEN_RCV_NO_BUFFER,
56     OID_GEN_RCV_CRC_ERROR,
57     OID_802_3_PERMANENT_ADDRESS,
58     OID_802_3_CURRENT_ADDRESS,
59     OID_802_3_MULTICAST_LIST,
60     OID_802_3_MAXIMUM_LIST_SIZE,
61     OID_802_3_MAC_OPTIONS,
62     OID_802_3_RCV_ERROR_ALIGNMENT,
63     OID_802_3_XMIT_ONE_COLLISION,
64     OID_802_3_XMIT_MORE_COLLISIONS
65 };
66 
67 NDIS_STATUS
68 NTAPI
MiniportQueryInformation(IN NDIS_HANDLE MiniportAdapterContext,IN NDIS_OID Oid,IN PVOID InformationBuffer,IN ULONG InformationBufferLength,OUT PULONG BytesWritten,OUT PULONG BytesNeeded)69 MiniportQueryInformation (
70     IN NDIS_HANDLE MiniportAdapterContext,
71     IN NDIS_OID Oid,
72     IN PVOID InformationBuffer,
73     IN ULONG InformationBufferLength,
74     OUT PULONG BytesWritten,
75     OUT PULONG BytesNeeded
76     )
77 {
78     PRTL_ADAPTER adapter = (PRTL_ADAPTER)MiniportAdapterContext;
79     ULONG genericUlong;
80     ULONG copyLength;
81     PVOID copySource;
82     NDIS_STATUS status;
83 
84     status = NDIS_STATUS_SUCCESS;
85     copySource = &genericUlong;
86     copyLength = sizeof(ULONG);
87 
88     NdisAcquireSpinLock(&adapter->Lock);
89 
90     switch (Oid)
91     {
92         case OID_GEN_SUPPORTED_LIST:
93             copySource = (PVOID)&SupportedOidList;
94             copyLength = sizeof(SupportedOidList);
95             break;
96 
97         case OID_GEN_CURRENT_PACKET_FILTER:
98             genericUlong = adapter->PacketFilter;
99             break;
100 
101         case OID_GEN_HARDWARE_STATUS:
102             genericUlong = (ULONG)NdisHardwareStatusReady; //FIXME
103             break;
104 
105         case OID_GEN_MEDIA_SUPPORTED:
106         case OID_GEN_MEDIA_IN_USE:
107         {
108             static const NDIS_MEDIUM medium = NdisMedium802_3;
109             copySource = (PVOID)&medium;
110             copyLength = sizeof(medium);
111             break;
112         }
113 
114         case OID_GEN_RECEIVE_BLOCK_SIZE:
115         case OID_GEN_TRANSMIT_BLOCK_SIZE:
116         case OID_GEN_CURRENT_LOOKAHEAD:
117         case OID_GEN_MAXIMUM_LOOKAHEAD:
118         case OID_GEN_MAXIMUM_FRAME_SIZE:
119             genericUlong = MAXIMUM_FRAME_SIZE - sizeof(ETH_HEADER);
120             break;
121 
122         case OID_GEN_LINK_SPEED:
123             genericUlong = adapter->LinkSpeedMbps * 1000;
124             break;
125 
126         case OID_GEN_TRANSMIT_BUFFER_SPACE:
127             genericUlong = MAXIMUM_FRAME_SIZE;
128             break;
129 
130         case OID_GEN_RECEIVE_BUFFER_SPACE:
131             genericUlong = RECEIVE_BUFFER_SIZE;
132             break;
133 
134         case OID_GEN_VENDOR_ID:
135             //
136             // The 3 bytes of the MAC address is the vendor ID
137             //
138             genericUlong = 0;
139             genericUlong |= (adapter->PermanentMacAddress[0] << 16);
140             genericUlong |= (adapter->PermanentMacAddress[1] << 8);
141             genericUlong |= (adapter->PermanentMacAddress[2] & 0xFF);
142             break;
143 
144         case OID_GEN_VENDOR_DESCRIPTION:
145         {
146             static UCHAR vendorDesc[] = "ReactOS Team";
147             copySource = vendorDesc;
148             copyLength = sizeof(vendorDesc);
149             break;
150         }
151 
152         case OID_GEN_VENDOR_DRIVER_VERSION:
153             genericUlong = DRIVER_VERSION;
154             break;
155 
156         case OID_GEN_DRIVER_VERSION:
157         {
158             static const USHORT driverVersion =
159                  (NDIS_MINIPORT_MAJOR_VERSION << 8) + NDIS_MINIPORT_MINOR_VERSION;
160             copySource = (PVOID)&driverVersion;
161             copyLength = sizeof(driverVersion);
162             break;
163         }
164 
165         case OID_GEN_MAXIMUM_TOTAL_SIZE:
166             genericUlong = MAXIMUM_FRAME_SIZE;
167             break;
168 
169         case OID_GEN_PROTOCOL_OPTIONS:
170             NDIS_DbgPrint(MIN_TRACE, ("OID_GEN_PROTOCOL_OPTIONS is unimplemented\n"));
171             status = NDIS_STATUS_NOT_SUPPORTED;
172             break;
173 
174         case OID_GEN_MAC_OPTIONS:
175             genericUlong = NDIS_MAC_OPTION_RECEIVE_SERIALIZED |
176                            NDIS_MAC_OPTION_COPY_LOOKAHEAD_DATA |
177                            NDIS_MAC_OPTION_TRANSFERS_NOT_PEND |
178                            NDIS_MAC_OPTION_NO_LOOPBACK;
179             break;
180 
181         case OID_GEN_MEDIA_CONNECT_STATUS:
182             genericUlong = adapter->MediaState;
183             break;
184 
185         case OID_GEN_MAXIMUM_SEND_PACKETS:
186             genericUlong = 1;
187             break;
188 
189         case OID_802_3_CURRENT_ADDRESS:
190             copySource = adapter->CurrentMacAddress;
191             copyLength = IEEE_802_ADDR_LENGTH;
192             break;
193 
194         case OID_802_3_PERMANENT_ADDRESS:
195             copySource = adapter->PermanentMacAddress;
196             copyLength = IEEE_802_ADDR_LENGTH;
197             break;
198 
199         case OID_802_3_MAXIMUM_LIST_SIZE:
200             genericUlong = MAXIMUM_MULTICAST_ADDRESSES;
201             break;
202 
203         case OID_GEN_XMIT_OK:
204             genericUlong = adapter->TransmitOk;
205             break;
206 
207         case OID_GEN_RCV_OK:
208             genericUlong = adapter->ReceiveOk;
209             break;
210 
211         case OID_GEN_XMIT_ERROR:
212             genericUlong = adapter->TransmitError;
213             break;
214 
215         case OID_GEN_RCV_ERROR:
216             genericUlong = adapter->ReceiveError;
217             break;
218 
219         case OID_GEN_RCV_NO_BUFFER:
220             genericUlong = adapter->ReceiveNoBufferSpace;
221             break;
222 
223         case OID_GEN_RCV_CRC_ERROR:
224             genericUlong = adapter->ReceiveCrcError;
225             break;
226 
227         case OID_802_3_RCV_ERROR_ALIGNMENT:
228             genericUlong = adapter->ReceiveAlignmentError;
229             break;
230 
231         case OID_802_3_XMIT_ONE_COLLISION:
232             genericUlong = adapter->TransmitOneCollision;
233             break;
234 
235         case OID_802_3_XMIT_MORE_COLLISIONS:
236             genericUlong = adapter->TransmitMoreCollisions;
237             break;
238 
239         default:
240             NDIS_DbgPrint(MIN_TRACE, ("Unknown OID\n"));
241             status = NDIS_STATUS_NOT_SUPPORTED;
242             break;
243     }
244 
245     if (status == NDIS_STATUS_SUCCESS)
246     {
247         if (copyLength > InformationBufferLength)
248         {
249             *BytesNeeded = copyLength;
250             *BytesWritten = 0;
251             status = NDIS_STATUS_INVALID_LENGTH;
252         }
253         else
254         {
255             NdisMoveMemory(InformationBuffer, copySource, copyLength);
256             *BytesWritten = copyLength;
257             *BytesNeeded = copyLength;
258         }
259     }
260     else
261     {
262         *BytesWritten = 0;
263         *BytesNeeded = 0;
264     }
265 
266     NdisReleaseSpinLock(&adapter->Lock);
267 
268     NDIS_DbgPrint(MAX_TRACE, ("Query OID 0x%x: Completed with status 0x%x (%d, %d)\n",
269                               Oid, status, *BytesWritten, *BytesNeeded));
270 
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 {
285     PRTL_ADAPTER adapter = (PRTL_ADAPTER)MiniportAdapterContext;
286     ULONG genericUlong;
287     NDIS_STATUS status;
288 
289     status = NDIS_STATUS_SUCCESS;
290 
291     NdisAcquireSpinLock(&adapter->Lock);
292 
293     switch (Oid)
294     {
295         case OID_GEN_CURRENT_PACKET_FILTER:
296             if (InformationBufferLength < sizeof(ULONG))
297             {
298                 *BytesRead = 0;
299                 *BytesNeeded = sizeof(ULONG);
300                 status = NDIS_STATUS_INVALID_LENGTH;
301                 break;
302             }
303 
304             NdisMoveMemory(&genericUlong, InformationBuffer, sizeof(ULONG));
305 
306             if (genericUlong &
307                 (NDIS_PACKET_TYPE_ALL_FUNCTIONAL |
308                  NDIS_PACKET_TYPE_FUNCTIONAL |
309                  NDIS_PACKET_TYPE_GROUP |
310                  NDIS_PACKET_TYPE_MAC_FRAME |
311                  NDIS_PACKET_TYPE_SMT |
312                  NDIS_PACKET_TYPE_SOURCE_ROUTING))
313             {
314                 *BytesRead = sizeof(ULONG);
315                 *BytesNeeded = sizeof(ULONG);
316                 status = NDIS_STATUS_NOT_SUPPORTED;
317                 break;
318             }
319 
320             adapter->PacketFilter = genericUlong;
321 
322             status = NICApplyPacketFilter(adapter);
323             if (status != NDIS_STATUS_SUCCESS)
324             {
325                 NDIS_DbgPrint(MIN_TRACE, ("Failed to apply new packet filter\n"));
326                 break;
327             }
328 
329             break;
330 
331         case OID_GEN_CURRENT_LOOKAHEAD:
332             if (InformationBufferLength < sizeof(ULONG))
333             {
334                 *BytesRead = 0;
335                 *BytesNeeded = sizeof(ULONG);
336                 status = NDIS_STATUS_INVALID_LENGTH;
337                 break;
338             }
339 
340             NdisMoveMemory(&genericUlong, InformationBuffer, sizeof(ULONG));
341 
342             if (genericUlong > MAXIMUM_FRAME_SIZE - sizeof(ETH_HEADER))
343             {
344                 status = NDIS_STATUS_INVALID_DATA;
345             }
346             else
347             {
348                 // Ignore this...
349             }
350 
351             break;
352 
353         case OID_802_3_MULTICAST_LIST:
354             if (InformationBufferLength % IEEE_802_ADDR_LENGTH)
355             {
356                 *BytesRead = 0;
357                 *BytesNeeded = InformationBufferLength + (InformationBufferLength % IEEE_802_ADDR_LENGTH);
358                 status = NDIS_STATUS_INVALID_LENGTH;
359                 break;
360             }
361 
362             if (InformationBufferLength / 6 > MAXIMUM_MULTICAST_ADDRESSES)
363             {
364                 *BytesNeeded = MAXIMUM_MULTICAST_ADDRESSES * IEEE_802_ADDR_LENGTH;
365                 *BytesRead = 0;
366                 status = NDIS_STATUS_INVALID_LENGTH;
367                 break;
368             }
369 
370             NdisMoveMemory(adapter->MulticastList, InformationBuffer, InformationBufferLength);
371 
372             // FIXME: Write to device
373 
374             break;
375 
376         default:
377             NDIS_DbgPrint(MIN_TRACE, ("Unknown OID\n"));
378             status = NDIS_STATUS_NOT_SUPPORTED;
379             *BytesRead = 0;
380             *BytesNeeded = 0;
381             break;
382     }
383 
384     if (status == NDIS_STATUS_SUCCESS)
385     {
386         *BytesRead = InformationBufferLength;
387         *BytesNeeded = 0;
388     }
389 
390     NdisReleaseSpinLock(&adapter->Lock);
391 
392     return status;
393 }
394