xref: /reactos/drivers/network/dd/pcnet/requests.c (revision 3e1f4074)
1 /*
2  * ReactOS AMD PCNet Driver
3  *
4  * Copyright (C) 2000 Casper Hornstrup <chorns@users.sourceforge.net>
5  * Copyright (C) 2003 Vizzini <vizzini@plasmic.com>
6  * Copyright (C) 2004 Filip Navara <navaraf@reactos.com>
7  *
8  * This program is free software; you can redistribute it and/or modify
9  * it under the terms of the GNU General Public License as published by
10  * the Free Software Foundation; either version 2 of the License, or
11  * (at your option) any later version.
12  *
13  * This program is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16  * GNU General Public License for more details.
17  *
18  * You should have received a copy of the GNU General Public License along
19  * with this program; if not, write to the Free Software Foundation, Inc.,
20  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
21  *
22  * PROGRAMMERS:
23  *     Vizzini (vizzini@plasmic.com),
24  *     borrowed very heavily from the ReactOS ne2000 driver by
25  *     Casper S. Hornstrup (chorns@users.sourceforge.net)
26  * REVISIONS:
27  *     14-Sep-2003 vizzini - Created
28  *     17-Oct-2004 navaraf - Add multicast support.
29  *                         - Add media state detection support.
30  *                         - Protect the adapter context with spinlock
31  *                           and move code talking to card to inside
32  *                           NdisMSynchronizeWithInterrupt calls where
33  *                           necessary.
34  */
35 
36 #include "pcnet.h"
37 
38 #define NDEBUG
39 #include <debug.h>
40 
41 /* List of supported OIDs */
42 static ULONG MiniportOIDList[] =
43 {
44   OID_GEN_SUPPORTED_LIST,
45   OID_GEN_HARDWARE_STATUS,
46   OID_GEN_MEDIA_SUPPORTED,
47   OID_GEN_MEDIA_IN_USE,
48   OID_GEN_MAXIMUM_LOOKAHEAD,
49   OID_GEN_MAXIMUM_FRAME_SIZE,
50   OID_GEN_LINK_SPEED,
51   OID_GEN_TRANSMIT_BUFFER_SPACE,
52   OID_GEN_RECEIVE_BUFFER_SPACE,
53   OID_GEN_TRANSMIT_BLOCK_SIZE,
54   OID_GEN_RECEIVE_BLOCK_SIZE,
55   OID_GEN_VENDOR_ID,
56   OID_GEN_VENDOR_DESCRIPTION,
57   OID_GEN_VENDOR_DRIVER_VERSION,
58   OID_GEN_CURRENT_PACKET_FILTER,
59   OID_GEN_CURRENT_LOOKAHEAD,
60   OID_GEN_DRIVER_VERSION,
61   OID_GEN_MAXIMUM_TOTAL_SIZE,
62   OID_GEN_PROTOCOL_OPTIONS,
63   OID_GEN_MAC_OPTIONS,
64   OID_GEN_MEDIA_CONNECT_STATUS,
65   OID_GEN_MAXIMUM_SEND_PACKETS,
66   OID_GEN_XMIT_OK,
67   OID_GEN_RCV_OK,
68   OID_GEN_XMIT_ERROR,
69   OID_GEN_RCV_ERROR,
70   OID_GEN_RCV_NO_BUFFER,
71   OID_GEN_RCV_CRC_ERROR,
72   OID_802_3_PERMANENT_ADDRESS,
73   OID_802_3_CURRENT_ADDRESS,
74   OID_802_3_MULTICAST_LIST,
75   OID_802_3_MAXIMUM_LIST_SIZE,
76   OID_802_3_MAC_OPTIONS,
77   OID_802_3_RCV_ERROR_ALIGNMENT,
78   OID_802_3_XMIT_ONE_COLLISION,
79   OID_802_3_XMIT_MORE_COLLISIONS
80 };
81 
82 
83 NDIS_STATUS
84 NTAPI
85 MiniportQueryInformation(
86     IN NDIS_HANDLE MiniportAdapterContext,
87     IN NDIS_OID Oid,
88     IN PVOID InformationBuffer,
89     IN ULONG InformationBufferLength,
90     OUT PULONG BytesWritten,
91     OUT PULONG BytesNeeded)
92 /*
93  * FUNCTION: Query an OID from the driver
94  * ARGUMENTS:
95  *     MiniportAdapterContext: context originally passed to NdisMSetAttributes
96  *     Oid: OID NDIS is querying
97  *     InformationBuffer: pointer to buffer into which to write the results of the query
98  *     InformationBufferLength: size in bytes of InformationBuffer
99  *     BytesWritten: number of bytes written into InformationBuffer in response to the query
100  *     BytesNeeded: number of bytes needed to answer the query
101  * RETURNS:
102  *     NDIS_STATUS_SUCCESS on all queries
103  * NOTES:
104  *     - Called by NDIS at DISPATCH_LEVEL
105  *     - If InformationBufferLength is insufficient to store the results, return the amount
106  *       needed in BytesNeeded and return NDIS_STATUS_INVALID_LENGTH
107  * TODO:
108  *     - Update to verify input buffer & size and return insufficient buffer codes
109  */
110 {
111   NDIS_STATUS Status;
112   PVOID CopyFrom;
113   UINT CopySize;
114   ULONG GenericULONG;
115   PADAPTER Adapter = (PADAPTER)MiniportAdapterContext;
116 
117   DPRINT("Called. OID 0x%x\n", Oid);
118 
119   ASSERT(Adapter);
120 
121   NdisAcquireSpinLock(&Adapter->Lock);
122 
123   Status   = NDIS_STATUS_SUCCESS;
124   CopyFrom = (PVOID)&GenericULONG;
125   CopySize = sizeof(ULONG);
126 
127   switch (Oid)
128     {
129     case OID_GEN_SUPPORTED_LIST:
130         {
131           CopyFrom = (PVOID)&MiniportOIDList;
132           CopySize = sizeof(MiniportOIDList);
133           break;
134         }
135 
136     case OID_GEN_HARDWARE_STATUS:
137         {
138           GenericULONG = (ULONG)NdisHardwareStatusReady;
139           break;
140         }
141 
142     case OID_GEN_MEDIA_SUPPORTED:
143     case OID_GEN_MEDIA_IN_USE:
144         {
145           static const NDIS_MEDIUM Medium = NdisMedium802_3;
146           CopyFrom = (PVOID)&Medium;
147           CopySize = sizeof(NDIS_MEDIUM);
148           break;
149         }
150 
151     case OID_GEN_CURRENT_LOOKAHEAD:
152     case OID_GEN_MAXIMUM_LOOKAHEAD:
153         {
154           GenericULONG = 1500;
155           break;
156         }
157 
158     case OID_GEN_MAXIMUM_FRAME_SIZE:
159         {
160           /*
161            * The value returned by this OID must be equal to
162            * OID_GEN_MAXIMUM_TOTAL_SIZE - sizeof(ETHERNET_HEADER)
163            * where sizeof(ETHERNET_HEADER) is 14.
164            */
165           GenericULONG = 1500;
166           break;
167         }
168 
169     case OID_GEN_LINK_SPEED:
170         {
171           GenericULONG = Adapter->MediaSpeed * 10000;
172           break;
173         }
174 
175     case OID_GEN_TRANSMIT_BUFFER_SPACE:
176         {
177           /* XXX fix me */
178           GenericULONG = BUFFER_SIZE;
179           break;
180         }
181 
182     case OID_GEN_RECEIVE_BUFFER_SPACE:
183         {
184           /* XXX fix me */
185           GenericULONG = BUFFER_SIZE;
186           break;
187         }
188 
189     case OID_GEN_TRANSMIT_BLOCK_SIZE:
190         {
191           GenericULONG = BUFFER_SIZE;
192           break;
193         }
194 
195     case OID_GEN_RECEIVE_BLOCK_SIZE:
196         {
197           GenericULONG = BUFFER_SIZE;
198           break;
199         }
200 
201     case OID_GEN_VENDOR_ID:
202         {
203           UCHAR *CharPtr = (UCHAR *)&GenericULONG;
204           GenericULONG = 0;
205           /* Read the first three bytes of the permanent MAC address */
206           NdisRawReadPortUchar(Adapter->PortOffset, CharPtr);
207           NdisRawReadPortUchar(Adapter->PortOffset + 1, CharPtr + 1);
208           NdisRawReadPortUchar(Adapter->PortOffset + 2, CharPtr + 2);
209           break;
210         }
211 
212     case OID_GEN_VENDOR_DESCRIPTION:
213         {
214           static UCHAR VendorDesc[] = "ReactOS Team";
215           CopyFrom = VendorDesc;
216           CopySize = sizeof(VendorDesc);
217           break;
218         }
219 
220     case OID_GEN_VENDOR_DRIVER_VERSION:
221         {
222           /* XXX implement me */
223           GenericULONG = 1;
224           break;
225         }
226 
227     case OID_GEN_CURRENT_PACKET_FILTER:
228         {
229           GenericULONG = Adapter->CurrentPacketFilter;
230           break;
231         }
232 
233     case OID_GEN_DRIVER_VERSION:
234         {
235           /* NDIS version used by the driver. */
236           static const USHORT DriverVersion =
237             (NDIS_MINIPORT_MAJOR_VERSION << 8) + NDIS_MINIPORT_MINOR_VERSION;
238           CopyFrom = (PVOID)&DriverVersion;
239           CopySize = sizeof(DriverVersion);
240           break;
241         }
242 
243     case OID_GEN_MAXIMUM_TOTAL_SIZE:
244         {
245           /* See comment in OID_GEN_MAXIMUM_FRAME_SIZE. */
246           GenericULONG = 1514;
247           break;
248         }
249 
250     case OID_GEN_PROTOCOL_OPTIONS:
251         {
252           DPRINT("OID_GEN_PROTOCOL_OPTIONS.\n");
253           Status = NDIS_STATUS_NOT_SUPPORTED;
254           break;
255         }
256 
257     case OID_GEN_MAC_OPTIONS:
258         {
259           GenericULONG = NDIS_MAC_OPTION_COPY_LOOKAHEAD_DATA |
260                          NDIS_MAC_OPTION_RECEIVE_SERIALIZED  |
261                          NDIS_MAC_OPTION_TRANSFERS_NOT_PEND  |
262                          NDIS_MAC_OPTION_NO_LOOPBACK;
263           break;
264         }
265 
266     case OID_GEN_MEDIA_CONNECT_STATUS:
267         {
268           GenericULONG = (ULONG)NdisMediaStateConnected; /* Adapter->MediaState */
269           break;
270         }
271 
272     case OID_GEN_MAXIMUM_SEND_PACKETS:
273         {
274           GenericULONG = 1;
275           break;
276         }
277 
278     case OID_802_3_CURRENT_ADDRESS:
279     case OID_802_3_PERMANENT_ADDRESS:
280         {
281           CopyFrom = (PVOID)&Adapter->InitializationBlockVirt->PADR;
282           CopySize = 6;
283           break;
284         }
285 
286     case OID_802_3_MAXIMUM_LIST_SIZE:
287         {
288           GenericULONG = MAX_MULTICAST_ADDRESSES;
289           break;
290         }
291 
292     case OID_GEN_XMIT_OK:
293         GenericULONG = Adapter->Statistics.XmtGoodFrames;
294         break;
295 
296     case OID_GEN_RCV_OK:
297         GenericULONG = Adapter->Statistics.RcvGoodFrames;
298         break;
299 
300     case OID_GEN_XMIT_ERROR:
301         GenericULONG = Adapter->Statistics.XmtRetryErrors +
302                        Adapter->Statistics.XmtLossesOfCarrier +
303                        Adapter->Statistics.XmtCollisions +
304                        Adapter->Statistics.XmtLateCollisions +
305                        Adapter->Statistics.XmtExcessiveDeferrals +
306                        Adapter->Statistics.XmtBufferUnderflows +
307                        Adapter->Statistics.XmtBufferErrors;
308         break;
309 
310     case OID_GEN_RCV_ERROR:
311         GenericULONG = Adapter->Statistics.RcvBufferErrors +
312                        Adapter->Statistics.RcvCrcErrors +
313                        Adapter->Statistics.RcvOverflowErrors +
314                        Adapter->Statistics.RcvFramingErrors;
315         break;
316 
317     case OID_GEN_RCV_NO_BUFFER:
318         GenericULONG = Adapter->Statistics.RcvBufferErrors +
319                        Adapter->Statistics.RcvOverflowErrors;
320         break;
321 
322     case OID_GEN_RCV_CRC_ERROR:
323         GenericULONG = Adapter->Statistics.RcvCrcErrors;
324         break;
325 
326     case OID_802_3_RCV_ERROR_ALIGNMENT:
327         GenericULONG = Adapter->Statistics.RcvFramingErrors;
328         break;
329 
330     case OID_802_3_XMIT_ONE_COLLISION:
331         GenericULONG = Adapter->Statistics.XmtOneRetry;
332         break;
333 
334     case OID_802_3_XMIT_MORE_COLLISIONS:
335         GenericULONG = Adapter->Statistics.XmtMoreThanOneRetry;
336         break;
337 
338     default:
339         {
340           DPRINT1("Unknown OID\n");
341           Status = NDIS_STATUS_NOT_SUPPORTED;
342           break;
343         }
344     }
345 
346   if (Status == NDIS_STATUS_SUCCESS)
347     {
348       if (CopySize > InformationBufferLength)
349         {
350           *BytesNeeded = CopySize;
351           *BytesWritten = 0;
352           Status        = NDIS_STATUS_INVALID_LENGTH;
353         }
354       else
355         {
356           NdisMoveMemory(InformationBuffer, CopyFrom, CopySize);
357           *BytesWritten = CopySize;
358           *BytesNeeded  = CopySize;
359          }
360     }
361    else
362     {
363        *BytesWritten = 0;
364        *BytesNeeded = 0;
365     }
366 
367   NdisReleaseSpinLock(&Adapter->Lock);
368 
369   DPRINT("Leaving. Status is 0x%x\n", Status);
370 
371   return Status;
372 }
373 
374 NDIS_STATUS
375 NTAPI
376 MiniportSetInformation(
377     IN NDIS_HANDLE MiniportAdapterContext,
378     IN NDIS_OID Oid,
379     IN PVOID InformationBuffer,
380     IN ULONG InformationBufferLength,
381     OUT PULONG BytesRead,
382     OUT PULONG BytesNeeded)
383 /*
384  * FUNCTION: Set a miniport variable (OID)
385  * ARGUMENTS:
386  *     MiniportAdapterContext: context originally passed into NdisMSetAttributes
387  *     Oid: the variable being set
388  *     InformationBuffer: the data to set the variable to
389  *     InformationBufferLength: number of bytes in InformationBuffer
390  *     BytesRead: number of bytes read by us out of the buffer
391  *     BytesNeeded: number of bytes required to satisfy the request if InformationBufferLength
392  *                  is insufficient
393  * RETURNS:
394  *     NDIS_STATUS_SUCCESS on all requests
395  * NOTES:
396  *     - Called by NDIS at DISPATCH_LEVEL
397  *     - verify buffer space as mentioned in previous function notes
398  */
399 {
400   ULONG GenericULONG;
401   NDIS_STATUS Status   = NDIS_STATUS_SUCCESS;
402   PADAPTER Adapter = (PADAPTER)MiniportAdapterContext;
403 
404   ASSERT(Adapter);
405 
406   DPRINT("Called, OID 0x%x\n", Oid);
407 
408   NdisAcquireSpinLock(&Adapter->Lock);
409 
410   switch (Oid)
411     {
412     case OID_GEN_CURRENT_PACKET_FILTER:
413       {
414         /* Verify length */
415         if (InformationBufferLength < sizeof(ULONG))
416           {
417             *BytesRead   = 0;
418             *BytesNeeded = sizeof(ULONG);
419             Status       = NDIS_STATUS_INVALID_LENGTH;
420             break;
421           }
422 
423         NdisMoveMemory(&GenericULONG, InformationBuffer, sizeof(ULONG));
424 
425         /* Check for properties the driver don't support */
426         if (GenericULONG &
427            (NDIS_PACKET_TYPE_ALL_FUNCTIONAL |
428             NDIS_PACKET_TYPE_FUNCTIONAL     |
429             NDIS_PACKET_TYPE_GROUP          |
430             NDIS_PACKET_TYPE_MAC_FRAME      |
431             NDIS_PACKET_TYPE_SMT            |
432             NDIS_PACKET_TYPE_SOURCE_ROUTING)
433            )
434           {
435             *BytesRead   = sizeof(ULONG);
436             *BytesNeeded = 0;
437             Status       = NDIS_STATUS_NOT_SUPPORTED;
438             break;
439           }
440 
441         Adapter->CurrentPacketFilter = GenericULONG;
442 
443         /* FIXME: Set filter on hardware */
444 
445         break;
446       }
447 
448     case OID_GEN_CURRENT_LOOKAHEAD:
449       {
450         /* Verify length */
451         if (InformationBufferLength < sizeof(ULONG))
452           {
453             *BytesRead   = 0;
454             *BytesNeeded = sizeof(ULONG);
455             Status = NDIS_STATUS_INVALID_LENGTH;
456             break;
457           }
458 
459         NdisMoveMemory(&GenericULONG, InformationBuffer, sizeof(ULONG));
460 
461         if (GenericULONG > 1500)
462           Status = NDIS_STATUS_INVALID_DATA;
463         else
464           Adapter->CurrentLookaheadSize = GenericULONG;
465 
466         break;
467       }
468 
469     case OID_802_3_MULTICAST_LIST:
470       {
471         /* Verify length. Must be multiple of hardware address length */
472         if ((InformationBufferLength % 6) != 0)
473           {
474             *BytesRead   = 0;
475             *BytesNeeded = InformationBufferLength + (InformationBufferLength % 6);
476             Status       = NDIS_STATUS_INVALID_LENGTH;
477             break;
478           }
479 
480         ASSERT((InformationBufferLength / 6) <= MAX_MULTICAST_ADDRESSES);
481 
482         /* Set new multicast address list */
483         //NdisMoveMemory(Adapter->Addresses, InformationBuffer, InformationBufferLength);
484 
485         /* Update hardware */
486         Status = MiSetMulticast(Adapter, InformationBuffer, InformationBufferLength / 6);
487 
488         break;
489       }
490 
491     default:
492       {
493         DPRINT1("Invalid object ID (0x%X).\n", Oid);
494         *BytesRead   = 0;
495         *BytesNeeded = 0;
496         Status       = NDIS_STATUS_NOT_SUPPORTED;
497         break;
498       }
499     }
500 
501   if (Status == NDIS_STATUS_SUCCESS)
502     {
503       *BytesRead   = InformationBufferLength;
504       *BytesNeeded = 0;
505     }
506 
507   NdisReleaseSpinLock(&Adapter->Lock);
508 
509   DPRINT("Leaving. Status (0x%X).\n", Status);
510 
511   return Status;
512 }
513