1 /*
2 * PROJECT: ReactOS DC21x4 Driver
3 * LICENSE: GPL-2.0-or-later (https://spdx.org/licenses/GPL-2.0-or-later)
4 * PURPOSE: Miniport information callbacks
5 * COPYRIGHT: Copyright 2023 Dmitry Borisov <di.sean@protonmail.com>
6 */
7
8 /* INCLUDES *******************************************************************/
9
10 #include "dc21x4.h"
11
12 #include <debug.h>
13
14 /* GLOBALS ********************************************************************/
15
16 static const NDIS_OID DcpSupportedOidList[] =
17 {
18 OID_GEN_SUPPORTED_LIST,
19 OID_GEN_CURRENT_PACKET_FILTER,
20 OID_GEN_HARDWARE_STATUS,
21 OID_GEN_MEDIA_SUPPORTED,
22 OID_GEN_MEDIA_IN_USE,
23 OID_GEN_MAXIMUM_LOOKAHEAD,
24 OID_GEN_MAXIMUM_FRAME_SIZE,
25 OID_GEN_MAXIMUM_SEND_PACKETS,
26 OID_GEN_LINK_SPEED,
27 OID_GEN_TRANSMIT_BUFFER_SPACE,
28 OID_GEN_RECEIVE_BUFFER_SPACE,
29 OID_GEN_RECEIVE_BLOCK_SIZE,
30 OID_GEN_TRANSMIT_BLOCK_SIZE,
31 OID_GEN_VENDOR_ID,
32 OID_GEN_VENDOR_DESCRIPTION,
33 OID_GEN_VENDOR_DRIVER_VERSION,
34 OID_GEN_CURRENT_LOOKAHEAD,
35 OID_GEN_DRIVER_VERSION,
36 OID_GEN_MAXIMUM_TOTAL_SIZE,
37 OID_GEN_MAC_OPTIONS,
38 OID_GEN_MEDIA_CONNECT_STATUS,
39 OID_802_3_PERMANENT_ADDRESS,
40 OID_802_3_CURRENT_ADDRESS,
41 OID_802_3_MULTICAST_LIST,
42 OID_802_3_MAXIMUM_LIST_SIZE,
43
44 /* Statistics */
45 OID_GEN_XMIT_OK,
46 OID_GEN_RCV_OK,
47 OID_GEN_XMIT_ERROR,
48 OID_GEN_RCV_ERROR,
49 OID_GEN_RCV_NO_BUFFER,
50 OID_GEN_DIRECTED_FRAMES_RCV,
51 OID_GEN_MULTICAST_FRAMES_RCV,
52 OID_GEN_BROADCAST_FRAMES_RCV,
53 OID_GEN_RCV_CRC_ERROR,
54 OID_GEN_TRANSMIT_QUEUE_LENGTH,
55 OID_802_3_RCV_ERROR_ALIGNMENT,
56 OID_802_3_XMIT_ONE_COLLISION,
57 OID_802_3_XMIT_MORE_COLLISIONS,
58 OID_802_3_XMIT_DEFERRED,
59 OID_802_3_XMIT_MAX_COLLISIONS,
60 OID_802_3_RCV_OVERRUN,
61 OID_802_3_XMIT_UNDERRUN,
62 OID_802_3_XMIT_HEARTBEAT_FAILURE,
63 OID_802_3_XMIT_TIMES_CRS_LOST,
64 OID_802_3_XMIT_LATE_COLLISIONS,
65
66 /* Power management */
67 OID_PNP_CAPABILITIES,
68 OID_PNP_SET_POWER,
69 OID_PNP_QUERY_POWER,
70 OID_PNP_ADD_WAKE_UP_PATTERN,
71 OID_PNP_REMOVE_WAKE_UP_PATTERN,
72 OID_PNP_ENABLE_WAKE_UP
73 };
74
75 /* FUNCTIONS ******************************************************************/
76
77 static
78 VOID
DcQueryStatisticCounter(_In_ PDC21X4_ADAPTER Adapter,_In_ NDIS_OID Oid,_Out_ PULONG64 Counter)79 DcQueryStatisticCounter(
80 _In_ PDC21X4_ADAPTER Adapter,
81 _In_ NDIS_OID Oid,
82 _Out_ PULONG64 Counter)
83 {
84 /* When there is no workaround, this function is used to read the hardware RX counters */
85 if (!(Adapter->Features & DC_NEED_RX_OVERFLOW_WORKAROUND))
86 {
87 ULONG RxCounters;
88
89 /*
90 * Read the RX missed frame counter. Note that the RX overflow counter is not supported
91 * on older chips without the workaround enabled and reads will return 0xFFFE****.
92 */
93 RxCounters = DC_READ(Adapter, DcCsr8_RxCounters);
94
95 Adapter->Statistics.ReceiveNoBuffers += RxCounters & DC_COUNTER_RX_NO_BUFFER_MASK;
96 }
97
98 switch (Oid)
99 {
100 case OID_GEN_XMIT_OK:
101 *Counter = Adapter->Statistics.TransmitOk;
102 break;
103 case OID_GEN_RCV_OK:
104 *Counter = Adapter->Statistics.ReceiveOk;
105 break;
106 case OID_GEN_XMIT_ERROR:
107 *Counter = Adapter->Statistics.TransmitErrors;
108 break;
109 case OID_GEN_RCV_ERROR:
110 *Counter = Adapter->Statistics.ReceiveErrors;
111 break;
112 case OID_GEN_RCV_NO_BUFFER:
113 *Counter = Adapter->Statistics.ReceiveNoBuffers;
114 break;
115 case OID_GEN_DIRECTED_FRAMES_RCV:
116 *Counter = Adapter->Statistics.ReceiveUnicast;
117 break;
118 case OID_GEN_MULTICAST_FRAMES_RCV:
119 *Counter = Adapter->Statistics.ReceiveMulticast;
120 break;
121 case OID_GEN_BROADCAST_FRAMES_RCV:
122 *Counter = Adapter->Statistics.ReceiveBroadcast;
123 break;
124 case OID_GEN_RCV_CRC_ERROR:
125 *Counter = Adapter->Statistics.ReceiveCrcErrors;
126 break;
127 case OID_802_3_RCV_ERROR_ALIGNMENT:
128 *Counter = Adapter->Statistics.ReceiveAlignmentErrors;
129 break;
130 case OID_802_3_XMIT_ONE_COLLISION:
131 *Counter = Adapter->Statistics.TransmitOneRetry;
132 break;
133 case OID_802_3_XMIT_MORE_COLLISIONS:
134 *Counter = Adapter->Statistics.TransmitMoreCollisions;
135 break;
136 case OID_802_3_XMIT_DEFERRED:
137 *Counter = Adapter->Statistics.TransmitDeferred;
138 break;
139 case OID_802_3_XMIT_MAX_COLLISIONS:
140 *Counter = Adapter->Statistics.TransmitExcessiveCollisions;
141 break;
142 case OID_802_3_RCV_OVERRUN:
143 *Counter = Adapter->Statistics.ReceiveOverrunErrors;
144 break;
145 case OID_802_3_XMIT_UNDERRUN:
146 *Counter = Adapter->Statistics.TransmitUnderrunErrors;
147 break;
148 case OID_802_3_XMIT_HEARTBEAT_FAILURE:
149 *Counter = Adapter->Statistics.TransmitHeartbeatErrors;
150 break;
151 case OID_802_3_XMIT_TIMES_CRS_LOST:
152 *Counter = Adapter->Statistics.TransmitLostCarrierSense;
153 break;
154 case OID_802_3_XMIT_LATE_COLLISIONS:
155 *Counter = Adapter->Statistics.TransmitLateCollisions;
156 break;
157
158 default:
159 ASSERT(FALSE);
160 UNREACHABLE;
161 break;
162 }
163 }
164
165 static
166 ULONG
DcGetLinkSpeed(_In_ PDC21X4_ADAPTER Adapter)167 DcGetLinkSpeed(
168 _In_ PDC21X4_ADAPTER Adapter)
169 {
170 ULONG LinkSpeedMbps;
171
172 switch (Adapter->MediaNumber)
173 {
174 case MEDIA_HMR:
175 LinkSpeedMbps = 1;
176 break;
177
178 case MEDIA_10T:
179 case MEDIA_BNC:
180 case MEDIA_AUI:
181 case MEDIA_10T_FD:
182 LinkSpeedMbps = 10;
183 break;
184
185 case MEDIA_100TX_HD:
186 case MEDIA_100TX_FD:
187 case MEDIA_100T4:
188 case MEDIA_100FX_HD:
189 case MEDIA_100FX_FD:
190 LinkSpeedMbps = 100;
191 break;
192
193 case MEDIA_MII:
194 LinkSpeedMbps = Adapter->LinkSpeedMbps;
195 break;
196
197 default:
198 ASSERT(FALSE);
199 UNREACHABLE;
200 break;
201 }
202
203 return LinkSpeedMbps;
204 }
205
206 NDIS_STATUS
207 NTAPI
DcQueryInformation(_In_ NDIS_HANDLE MiniportAdapterContext,_In_ NDIS_OID Oid,_In_ PVOID InformationBuffer,_In_ ULONG InformationBufferLength,_Out_ PULONG BytesWritten,_Out_ PULONG BytesNeeded)208 DcQueryInformation(
209 _In_ NDIS_HANDLE MiniportAdapterContext,
210 _In_ NDIS_OID Oid,
211 _In_ PVOID InformationBuffer,
212 _In_ ULONG InformationBufferLength,
213 _Out_ PULONG BytesWritten,
214 _Out_ PULONG BytesNeeded)
215 {
216 PDC21X4_ADAPTER Adapter = (PDC21X4_ADAPTER)MiniportAdapterContext;
217 NDIS_STATUS Status = NDIS_STATUS_SUCCESS;
218 ULONG InfoLength;
219 PVOID InfoPtr;
220 union _GENERIC_INFORMATION
221 {
222 USHORT Ushort;
223 ULONG Ulong;
224 ULONG64 Ulong64;
225 NDIS_MEDIUM Medium;
226 NDIS_HARDWARE_STATUS Status;
227 NDIS_DEVICE_POWER_STATE PowerState;
228 } GenericInfo;
229
230 InfoLength = sizeof(ULONG);
231 InfoPtr = &GenericInfo;
232
233 switch (Oid)
234 {
235 case OID_GEN_SUPPORTED_LIST:
236 InfoPtr = (PVOID)&DcpSupportedOidList;
237 InfoLength = sizeof(DcpSupportedOidList);
238 break;
239
240 case OID_GEN_CURRENT_PACKET_FILTER:
241 GenericInfo.Ulong = Adapter->PacketFilter;
242 break;
243
244 case OID_802_3_MULTICAST_LIST:
245 InfoPtr = Adapter->MulticastList;
246 InfoLength = Adapter->MulticastCount * ETH_LENGTH_OF_ADDRESS;
247 break;
248
249 case OID_802_3_MAXIMUM_LIST_SIZE:
250 GenericInfo.Ulong = Adapter->MulticastMaxEntries;
251 break;
252
253 case OID_GEN_MEDIA_SUPPORTED:
254 case OID_GEN_MEDIA_IN_USE:
255 {
256 GenericInfo.Medium = NdisMedium802_3;
257 InfoLength = sizeof(NDIS_MEDIUM);
258 break;
259 }
260
261 case OID_GEN_HARDWARE_STATUS:
262 {
263 ULONG InterruptStatus;
264
265 /* NOTE: Reading the status register has no effect on the events */
266 InterruptStatus = DC_READ(Adapter, DcCsr5_Status);
267
268 /* Inserted into the motherboard */
269 if (InterruptStatus != 0xFFFFFFFF)
270 GenericInfo.Status = NdisHardwareStatusReady;
271 else
272 GenericInfo.Status = NdisHardwareStatusNotReady;
273
274 InfoLength = sizeof(NDIS_HARDWARE_STATUS);
275 break;
276 }
277
278 case OID_GEN_MAXIMUM_FRAME_SIZE:
279 case OID_GEN_MAXIMUM_LOOKAHEAD:
280 case OID_GEN_CURRENT_LOOKAHEAD:
281 GenericInfo.Ulong = DC_MAXIMUM_FRAME_SIZE - DC_ETHERNET_HEADER_SIZE;
282 break;
283
284 case OID_GEN_MAXIMUM_TOTAL_SIZE:
285 GenericInfo.Ulong = DC_MAXIMUM_FRAME_SIZE;
286 break;
287
288 case OID_GEN_TRANSMIT_BLOCK_SIZE:
289 GenericInfo.Ulong = DC_TRANSMIT_BLOCK_SIZE;
290 break;
291
292 case OID_GEN_TRANSMIT_BUFFER_SPACE:
293 GenericInfo.Ulong = DC_TRANSMIT_BLOCK_SIZE * DC_TRANSMIT_BLOCKS;
294 break;
295
296 case OID_GEN_RECEIVE_BLOCK_SIZE:
297 GenericInfo.Ulong = DC_RECEIVE_BLOCK_SIZE;
298 break;
299
300 case OID_GEN_RECEIVE_BUFFER_SPACE:
301 GenericInfo.Ulong = DC_RECEIVE_BLOCK_SIZE * Adapter->RcbCount;
302 break;
303
304 case OID_GEN_LINK_SPEED:
305 GenericInfo.Ulong = DcGetLinkSpeed(Adapter) * 10000;
306 break;
307
308 case OID_GEN_VENDOR_ID:
309 GenericInfo.Ulong = 0;
310 GenericInfo.Ulong |= (Adapter->PermanentMacAddress[0] << 16);
311 GenericInfo.Ulong |= (Adapter->PermanentMacAddress[1] << 8);
312 GenericInfo.Ulong |= (Adapter->PermanentMacAddress[2] & 0xFF);
313 break;
314
315 case OID_GEN_VENDOR_DESCRIPTION:
316 {
317 static const CHAR VendorDesc[] = "DC21x4 compatible Ethernet Adapter";
318 InfoPtr = (PVOID)&VendorDesc;
319 InfoLength = sizeof(VendorDesc);
320 break;
321 }
322
323 case OID_GEN_VENDOR_DRIVER_VERSION:
324 /* 1.0.0 */
325 GenericInfo.Ulong = 0x100;
326 break;
327
328 case OID_GEN_DRIVER_VERSION:
329 {
330 InfoLength = sizeof(USHORT);
331 GenericInfo.Ushort = (NDIS_MINIPORT_MAJOR_VERSION << 8) | NDIS_MINIPORT_MINOR_VERSION;
332 break;
333 }
334
335 case OID_GEN_MAXIMUM_SEND_PACKETS:
336 GenericInfo.Ulong = DC_TRANSMIT_BLOCKS - DC_TCB_RESERVE;
337 break;
338
339 case OID_GEN_MAC_OPTIONS:
340 GenericInfo.Ulong = NDIS_MAC_OPTION_COPY_LOOKAHEAD_DATA |
341 NDIS_MAC_OPTION_TRANSFERS_NOT_PEND |
342 NDIS_MAC_OPTION_NO_LOOPBACK;
343 break;
344
345 case OID_GEN_MEDIA_CONNECT_STATUS:
346 GenericInfo.Ulong = Adapter->LinkUp ? NdisMediaStateConnected
347 : NdisMediaStateDisconnected;
348 break;
349
350 case OID_802_3_PERMANENT_ADDRESS:
351 InfoPtr = Adapter->PermanentMacAddress;
352 InfoLength = ETH_LENGTH_OF_ADDRESS;
353 break;
354
355 case OID_802_3_CURRENT_ADDRESS:
356 InfoPtr = Adapter->CurrentMacAddress;
357 InfoLength = ETH_LENGTH_OF_ADDRESS;
358 break;
359
360 case OID_GEN_XMIT_OK:
361 case OID_GEN_RCV_OK:
362 case OID_GEN_XMIT_ERROR:
363 case OID_GEN_RCV_ERROR:
364 case OID_GEN_RCV_NO_BUFFER:
365 case OID_GEN_DIRECTED_FRAMES_RCV:
366 case OID_GEN_MULTICAST_FRAMES_RCV:
367 case OID_GEN_BROADCAST_FRAMES_RCV:
368 case OID_GEN_RCV_CRC_ERROR:
369 case OID_802_3_RCV_ERROR_ALIGNMENT:
370 case OID_802_3_XMIT_ONE_COLLISION:
371 case OID_802_3_XMIT_MORE_COLLISIONS:
372 case OID_802_3_XMIT_DEFERRED:
373 case OID_802_3_XMIT_MAX_COLLISIONS:
374 case OID_802_3_RCV_OVERRUN:
375 case OID_802_3_XMIT_UNDERRUN:
376 case OID_802_3_XMIT_HEARTBEAT_FAILURE:
377 case OID_802_3_XMIT_TIMES_CRS_LOST:
378 case OID_802_3_XMIT_LATE_COLLISIONS:
379 {
380 DcQueryStatisticCounter(Adapter, Oid, &GenericInfo.Ulong64);
381
382 *BytesNeeded = sizeof(ULONG64);
383 if (InformationBufferLength < sizeof(ULONG))
384 {
385 *BytesWritten = 0;
386 return NDIS_STATUS_BUFFER_TOO_SHORT;
387 }
388 if (InformationBufferLength >= sizeof(ULONG64))
389 {
390 *BytesWritten = sizeof(ULONG64);
391 NdisMoveMemory(InformationBuffer, InfoPtr, sizeof(ULONG64));
392 }
393 else
394 {
395 *BytesWritten = sizeof(ULONG);
396 NdisMoveMemory(InformationBuffer, InfoPtr, sizeof(ULONG));
397 }
398
399 return NDIS_STATUS_SUCCESS;
400 }
401
402 case OID_GEN_TRANSMIT_QUEUE_LENGTH:
403 GenericInfo.Ulong = (DC_TRANSMIT_BLOCKS - DC_TCB_RESERVE) - Adapter->TcbSlots;
404 break;
405
406 case OID_PNP_CAPABILITIES:
407 {
408 PNDIS_PNP_CAPABILITIES Capabilities;
409
410 InfoLength = sizeof(NDIS_PNP_CAPABILITIES);
411
412 if (InformationBufferLength < InfoLength)
413 {
414 *BytesWritten = 0;
415 *BytesNeeded = InfoLength;
416 return NDIS_STATUS_BUFFER_TOO_SHORT;
417 }
418
419 if (!(Adapter->Features & DC_HAS_POWER_MANAGEMENT))
420 return NDIS_STATUS_NOT_SUPPORTED;
421
422 *BytesWritten = InfoLength;
423 *BytesNeeded = 0;
424
425 Capabilities = InformationBuffer;
426 Capabilities->WakeUpCapabilities.MinMagicPacketWakeUp = NdisDeviceStateD3;
427 Capabilities->WakeUpCapabilities.MinPatternWakeUp = NdisDeviceStateD3;
428 Capabilities->WakeUpCapabilities.MinLinkChangeWakeUp = NdisDeviceStateD3;
429
430 return NDIS_STATUS_SUCCESS;
431 }
432
433 case OID_PNP_QUERY_POWER:
434 {
435 if (!(Adapter->Features & DC_HAS_POWER_MANAGEMENT))
436 return NDIS_STATUS_NOT_SUPPORTED;
437
438 return NDIS_STATUS_SUCCESS;
439 }
440
441 case OID_PNP_ENABLE_WAKE_UP:
442 {
443 if (!(Adapter->Features & DC_HAS_POWER_MANAGEMENT))
444 return NDIS_STATUS_NOT_SUPPORTED;
445
446 GenericInfo.Ulong = Adapter->WakeUpFlags & (NDIS_PNP_WAKE_UP_MAGIC_PACKET |
447 NDIS_PNP_WAKE_UP_PATTERN_MATCH |
448 NDIS_PNP_WAKE_UP_LINK_CHANGE);
449 break;
450 }
451
452 default:
453 Status = NDIS_STATUS_INVALID_OID;
454 break;
455 }
456
457 if (Status == NDIS_STATUS_SUCCESS)
458 {
459 if (InfoLength > InformationBufferLength)
460 {
461 *BytesWritten = 0;
462 *BytesNeeded = InfoLength;
463 Status = NDIS_STATUS_BUFFER_TOO_SHORT;
464 }
465 else
466 {
467 NdisMoveMemory(InformationBuffer, InfoPtr, InfoLength);
468 *BytesWritten = InfoLength;
469 *BytesNeeded = 0;
470 }
471 }
472 else
473 {
474 *BytesWritten = 0;
475 *BytesNeeded = 0;
476 }
477
478 return Status;
479 }
480
481 NDIS_STATUS
482 NTAPI
DcSetInformation(_In_ NDIS_HANDLE MiniportAdapterContext,_In_ NDIS_OID Oid,_In_ PVOID InformationBuffer,_In_ ULONG InformationBufferLength,_Out_ PULONG BytesRead,_Out_ PULONG BytesNeeded)483 DcSetInformation(
484 _In_ NDIS_HANDLE MiniportAdapterContext,
485 _In_ NDIS_OID Oid,
486 _In_ PVOID InformationBuffer,
487 _In_ ULONG InformationBufferLength,
488 _Out_ PULONG BytesRead,
489 _Out_ PULONG BytesNeeded)
490 {
491 PDC21X4_ADAPTER Adapter = (PDC21X4_ADAPTER)MiniportAdapterContext;
492 NDIS_STATUS Status = NDIS_STATUS_SUCCESS;
493 ULONG GenericUlong;
494
495 *BytesRead = 0;
496 *BytesNeeded = 0;
497
498 switch (Oid)
499 {
500 case OID_GEN_CURRENT_PACKET_FILTER:
501 {
502 if (InformationBufferLength < sizeof(ULONG))
503 {
504 *BytesNeeded = sizeof(ULONG);
505 Status = NDIS_STATUS_INVALID_LENGTH;
506 break;
507 }
508
509 *BytesRead = sizeof(ULONG);
510 NdisMoveMemory(&GenericUlong, InformationBuffer, sizeof(ULONG));
511
512 if (GenericUlong & ~DC_PACKET_FILTERS)
513 {
514 Status = NDIS_STATUS_NOT_SUPPORTED;
515 break;
516 }
517
518 Status = DcApplyPacketFilter(Adapter, GenericUlong);
519 break;
520 }
521
522 case OID_802_3_MULTICAST_LIST:
523 {
524 ULONG Size;
525
526 if (InformationBufferLength % ETH_LENGTH_OF_ADDRESS)
527 {
528 *BytesNeeded = (InformationBufferLength / ETH_LENGTH_OF_ADDRESS) *
529 ETH_LENGTH_OF_ADDRESS;
530 Status = NDIS_STATUS_INVALID_LENGTH;
531 break;
532 }
533
534 Size = Adapter->MulticastMaxEntries * ETH_LENGTH_OF_ADDRESS;
535 if (InformationBufferLength > Size)
536 {
537 *BytesNeeded = Size;
538 Status = NDIS_STATUS_MULTICAST_FULL;
539 break;
540 }
541
542 *BytesRead = InformationBufferLength;
543 NdisMoveMemory(Adapter->MulticastList, InformationBuffer, InformationBufferLength);
544
545 Adapter->MulticastCount = InformationBufferLength / ETH_LENGTH_OF_ADDRESS;
546
547 Status = DcUpdateMulticastList(Adapter);
548 break;
549 }
550
551 case OID_GEN_CURRENT_LOOKAHEAD:
552 {
553 if (InformationBufferLength < sizeof(ULONG))
554 {
555 *BytesNeeded = sizeof(ULONG);
556 Status = NDIS_STATUS_INVALID_LENGTH;
557 break;
558 }
559
560 /* Nothing to do */
561 *BytesRead = sizeof(ULONG);
562 break;
563 }
564
565 case OID_PNP_ENABLE_WAKE_UP:
566 {
567 if (InformationBufferLength < sizeof(ULONG))
568 {
569 *BytesNeeded = sizeof(ULONG);
570 Status = NDIS_STATUS_INVALID_LENGTH;
571 break;
572 }
573
574 if (!(Adapter->Features & DC_HAS_POWER_MANAGEMENT))
575 {
576 return NDIS_STATUS_NOT_SUPPORTED;
577 }
578
579 *BytesRead = sizeof(ULONG);
580 NdisMoveMemory(&GenericUlong, InformationBuffer, sizeof(ULONG));
581
582 Adapter->WakeUpFlags = GenericUlong;
583 break;
584 }
585
586 case OID_PNP_ADD_WAKE_UP_PATTERN:
587 {
588 if (InformationBufferLength < sizeof(NDIS_PM_PACKET_PATTERN))
589 {
590 *BytesNeeded = sizeof(NDIS_PM_PACKET_PATTERN);
591 Status = NDIS_STATUS_INVALID_LENGTH;
592 break;
593 }
594
595 if (!(Adapter->Features & DC_HAS_POWER_MANAGEMENT))
596 {
597 return NDIS_STATUS_NOT_SUPPORTED;
598 }
599
600 *BytesRead = sizeof(NDIS_PM_PACKET_PATTERN);
601
602 Status = DcAddWakeUpPattern(Adapter, InformationBuffer);
603 break;
604 }
605
606 case OID_PNP_REMOVE_WAKE_UP_PATTERN:
607 {
608 if (InformationBufferLength < sizeof(NDIS_PM_PACKET_PATTERN))
609 {
610 *BytesNeeded = sizeof(NDIS_PM_PACKET_PATTERN);
611 Status = NDIS_STATUS_INVALID_LENGTH;
612 break;
613 }
614
615 if (!(Adapter->Features & DC_HAS_POWER_MANAGEMENT))
616 {
617 return NDIS_STATUS_NOT_SUPPORTED;
618 }
619
620 *BytesRead = sizeof(NDIS_PM_PACKET_PATTERN);
621
622 Status = DcRemoveWakeUpPattern(Adapter, InformationBuffer);
623 break;
624 }
625
626 case OID_PNP_SET_POWER:
627 {
628 if (InformationBufferLength < sizeof(NDIS_DEVICE_POWER_STATE))
629 {
630 *BytesNeeded = sizeof(NDIS_DEVICE_POWER_STATE);
631 Status = NDIS_STATUS_INVALID_LENGTH;
632 break;
633 }
634
635 if (!(Adapter->Features & DC_HAS_POWER_MANAGEMENT))
636 {
637 return NDIS_STATUS_NOT_SUPPORTED;
638 }
639
640 *BytesRead = sizeof(ULONG);
641 NdisMoveMemory(&GenericUlong, InformationBuffer, sizeof(ULONG));
642
643 if (GenericUlong < NdisDeviceStateD0 || GenericUlong > NdisDeviceStateD3)
644 {
645 ASSERT(FALSE);
646 Status = NDIS_STATUS_INVALID_DATA;
647 break;
648 }
649
650 DcSetPower(Adapter, GenericUlong);
651 break;
652 }
653
654 default:
655 Status = NDIS_STATUS_NOT_SUPPORTED;
656 break;
657 }
658
659 return Status;
660 }
661