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