Sync with trunk r63430.
[reactos.git] / drivers / network / ndis / ndis / miniport.c
1 /*
2 * COPYRIGHT: See COPYING in the top level directory
3 * PROJECT: ReactOS NDIS library
4 * FILE: ndis/miniport.c
5 * PURPOSE: Routines used by NDIS miniport drivers
6 * PROGRAMMERS: Casper S. Hornstrup (chorns@users.sourceforge.net)
7 * Vizzini (vizzini@plasmic.com)
8 * REVISIONS:
9 * CSH 01/08-2000 Created
10 * 20 Aug 2003 vizzini - DMA support
11 * 3 Oct 2003 vizzini - SendPackets support
12 */
13
14 #include "ndissys.h"
15
16 #include <ndisguid.h>
17
18 /*
19 * Define to 1 to get a debugger breakpoint at the end of NdisInitializeWrapper
20 * for each new miniport starting up
21 */
22 #define BREAK_ON_MINIPORT_INIT 0
23
24 /*
25 * This has to be big enough to hold the results of querying the Route value
26 * from the Linkage key. Please re-code me to determine this dynamically.
27 */
28 #define ROUTE_DATA_SIZE 256
29
30 /* Number of media we know */
31 #define MEDIA_ARRAY_SIZE 15
32
33 static NDIS_MEDIUM MediaArray[MEDIA_ARRAY_SIZE] =
34 {
35 NdisMedium802_3,
36 NdisMedium802_5,
37 NdisMediumFddi,
38 NdisMediumWan,
39 NdisMediumLocalTalk,
40 NdisMediumDix,
41 NdisMediumArcnetRaw,
42 NdisMediumArcnet878_2,
43 NdisMediumAtm,
44 NdisMediumWirelessWan,
45 NdisMediumIrda,
46 NdisMediumBpc,
47 NdisMediumCoWan,
48 NdisMedium1394,
49 NdisMediumMax
50 };
51
52 /* global list and lock of Miniports NDIS has registered */
53 LIST_ENTRY MiniportListHead;
54 KSPIN_LOCK MiniportListLock;
55
56 /* global list and lock of adapters NDIS has registered */
57 LIST_ENTRY AdapterListHead;
58 KSPIN_LOCK AdapterListLock;
59
60 VOID
61 MiniDisplayPacket(
62 PNDIS_PACKET Packet)
63 {
64 #if DBG
65 ULONG i, Length;
66 UCHAR Buffer[64];
67 if ((DebugTraceLevel & DEBUG_PACKET) > 0) {
68 Length = CopyPacketToBuffer(
69 Buffer,
70 Packet,
71 0,
72 64);
73
74 DbgPrint("*** PACKET START ***");
75
76 for (i = 0; i < Length; i++) {
77 if (i % 12 == 0)
78 DbgPrint("\n%04X ", i);
79 DbgPrint("%02X ", Buffer[i]);
80 }
81
82 DbgPrint("*** PACKET STOP ***\n");
83 }
84 #endif /* DBG */
85 }
86
87 VOID
88 MiniDisplayPacket2(
89 PVOID HeaderBuffer,
90 UINT HeaderBufferSize,
91 PVOID LookaheadBuffer,
92 UINT LookaheadBufferSize)
93 {
94 #if DBG
95 if ((DebugTraceLevel & DEBUG_PACKET) > 0) {
96 ULONG i, Length;
97 PUCHAR p;
98
99 DbgPrint("*** RECEIVE PACKET START ***\n");
100 DbgPrint("HEADER:");
101 p = HeaderBuffer;
102 for (i = 0; i < HeaderBufferSize; i++) {
103 if (i % 16 == 0)
104 DbgPrint("\n%04X ", i);
105 DbgPrint("%02X ", *p++);
106 }
107
108 DbgPrint("\nFRAME:");
109
110 p = LookaheadBuffer;
111 Length = (LookaheadBufferSize < 64)? LookaheadBufferSize : 64;
112 for (i = 0; i < Length; i++) {
113 if (i % 16 == 0)
114 DbgPrint("\n%04X ", i);
115 DbgPrint("%02X ", *p++);
116 }
117
118 DbgPrint("\n*** RECEIVE PACKET STOP ***\n");
119 }
120 #endif /* DBG */
121 }
122
123 PNDIS_MINIPORT_WORK_ITEM
124 MiniGetFirstWorkItem(
125 PLOGICAL_ADAPTER Adapter,
126 NDIS_WORK_ITEM_TYPE Type)
127 {
128 PNDIS_MINIPORT_WORK_ITEM CurrentEntry = Adapter->WorkQueueHead;
129
130 while (CurrentEntry)
131 {
132 if (CurrentEntry->WorkItemType == Type || Type == NdisMaxWorkItems)
133 return CurrentEntry;
134
135 CurrentEntry = (PNDIS_MINIPORT_WORK_ITEM)CurrentEntry->Link.Next;
136 }
137
138 return NULL;
139 }
140
141 BOOLEAN
142 MiniIsBusy(
143 PLOGICAL_ADAPTER Adapter,
144 NDIS_WORK_ITEM_TYPE Type)
145 {
146 BOOLEAN Busy = FALSE;
147 KIRQL OldIrql;
148
149 KeAcquireSpinLock(&Adapter->NdisMiniportBlock.Lock, &OldIrql);
150
151 if (MiniGetFirstWorkItem(Adapter, Type))
152 {
153 Busy = TRUE;
154 }
155 else if (Type == NdisWorkItemRequest && Adapter->NdisMiniportBlock.PendingRequest)
156 {
157 Busy = TRUE;
158 }
159 else if (Type == NdisWorkItemSend && Adapter->NdisMiniportBlock.FirstPendingPacket)
160 {
161 Busy = TRUE;
162 }
163 else if (Type == NdisWorkItemResetRequested &&
164 Adapter->NdisMiniportBlock.ResetStatus == NDIS_STATUS_PENDING)
165 {
166 Busy = TRUE;
167 }
168
169 KeReleaseSpinLock(&Adapter->NdisMiniportBlock.Lock, OldIrql);
170
171 return Busy;
172 }
173
174 VOID
175 MiniIndicateData(
176 PLOGICAL_ADAPTER Adapter,
177 NDIS_HANDLE MacReceiveContext,
178 PVOID HeaderBuffer,
179 UINT HeaderBufferSize,
180 PVOID LookaheadBuffer,
181 UINT LookaheadBufferSize,
182 UINT PacketSize)
183 /*
184 * FUNCTION: Indicate received data to bound protocols
185 * ARGUMENTS:
186 * Adapter = Pointer to logical adapter
187 * MacReceiveContext = MAC receive context handle
188 * HeaderBuffer = Pointer to header buffer
189 * HeaderBufferSize = Size of header buffer
190 * LookaheadBuffer = Pointer to lookahead buffer
191 * LookaheadBufferSize = Size of lookahead buffer
192 * PacketSize = Total size of received packet
193 */
194 {
195 KIRQL OldIrql;
196 PLIST_ENTRY CurrentEntry;
197 PADAPTER_BINDING AdapterBinding;
198
199 NDIS_DbgPrint(DEBUG_MINIPORT, ("Called. Adapter (0x%X) HeaderBuffer (0x%X) "
200 "HeaderBufferSize (0x%X) LookaheadBuffer (0x%X) LookaheadBufferSize (0x%X).\n",
201 Adapter, HeaderBuffer, HeaderBufferSize, LookaheadBuffer, LookaheadBufferSize));
202
203 MiniDisplayPacket2(HeaderBuffer, HeaderBufferSize, LookaheadBuffer, LookaheadBufferSize);
204
205 NDIS_DbgPrint(MAX_TRACE, ("acquiring miniport block lock\n"));
206 KeAcquireSpinLock(&Adapter->NdisMiniportBlock.Lock, &OldIrql);
207 {
208 CurrentEntry = Adapter->ProtocolListHead.Flink;
209 NDIS_DbgPrint(DEBUG_MINIPORT, ("CurrentEntry = %x\n", CurrentEntry));
210
211 if (CurrentEntry == &Adapter->ProtocolListHead)
212 {
213 NDIS_DbgPrint(MIN_TRACE, ("WARNING: No upper protocol layer.\n"));
214 }
215
216 while (CurrentEntry != &Adapter->ProtocolListHead)
217 {
218 AdapterBinding = CONTAINING_RECORD(CurrentEntry, ADAPTER_BINDING, AdapterListEntry);
219 NDIS_DbgPrint(DEBUG_MINIPORT, ("AdapterBinding = %x\n", AdapterBinding));
220
221 NDIS_DbgPrint
222 (MID_TRACE,
223 ("XXX (%x) %x %x %x %x %x %x %x XXX\n",
224 *AdapterBinding->ProtocolBinding->Chars.ReceiveHandler,
225 AdapterBinding->NdisOpenBlock.ProtocolBindingContext,
226 MacReceiveContext,
227 HeaderBuffer,
228 HeaderBufferSize,
229 LookaheadBuffer,
230 LookaheadBufferSize,
231 PacketSize));
232
233 /* call the receive handler */
234 (*AdapterBinding->ProtocolBinding->Chars.ReceiveHandler)(
235 AdapterBinding->NdisOpenBlock.ProtocolBindingContext,
236 MacReceiveContext,
237 HeaderBuffer,
238 HeaderBufferSize,
239 LookaheadBuffer,
240 LookaheadBufferSize,
241 PacketSize);
242
243 CurrentEntry = CurrentEntry->Flink;
244 }
245 }
246 KeReleaseSpinLock(&Adapter->NdisMiniportBlock.Lock, OldIrql);
247
248 NDIS_DbgPrint(MAX_TRACE, ("Leaving.\n"));
249 }
250
251 /*
252 * @implemented
253 */
254 VOID
255 EXPORT
256 NdisReturnPackets(
257 IN PNDIS_PACKET *PacketsToReturn,
258 IN UINT NumberOfPackets)
259 /*
260 * FUNCTION: Releases ownership of one or more packets
261 * ARGUMENTS:
262 * PacketsToReturn = Pointer to an array of pointers to packet descriptors
263 * NumberOfPackets = Number of pointers in descriptor pointer array
264 */
265 {
266 UINT i;
267 PLOGICAL_ADAPTER Adapter;
268 KIRQL OldIrql;
269
270 NDIS_DbgPrint(MID_TRACE, ("Returning %d packets\n", NumberOfPackets));
271
272 for (i = 0; i < NumberOfPackets; i++)
273 {
274 PacketsToReturn[i]->WrapperReserved[0]--;
275 if (PacketsToReturn[i]->WrapperReserved[0] == 0)
276 {
277 Adapter = (PVOID)(ULONG_PTR)PacketsToReturn[i]->Reserved[1];
278
279 NDIS_DbgPrint(MAX_TRACE, ("Freeing packet %d (adapter = 0x%p)\n", i, Adapter));
280
281 KeRaiseIrql(DISPATCH_LEVEL, &OldIrql);
282 Adapter->NdisMiniportBlock.DriverHandle->MiniportCharacteristics.ReturnPacketHandler(
283 Adapter->NdisMiniportBlock.MiniportAdapterContext,
284 PacketsToReturn[i]);
285 KeLowerIrql(OldIrql);
286 }
287 }
288 }
289
290 VOID NTAPI
291 MiniIndicateReceivePacket(
292 IN NDIS_HANDLE MiniportAdapterHandle,
293 IN PPNDIS_PACKET PacketArray,
294 IN UINT NumberOfPackets)
295 /*
296 * FUNCTION: receives miniport packet array indications
297 * ARGUMENTS:
298 * MiniportAdapterHandle: Miniport handle for the adapter
299 * PacketArray: pointer to a list of packet pointers to indicate
300 * NumberOfPackets: number of packets to indicate
301 *
302 */
303 {
304 PLOGICAL_ADAPTER Adapter = MiniportAdapterHandle;
305 PLIST_ENTRY CurrentEntry;
306 PADAPTER_BINDING AdapterBinding;
307 KIRQL OldIrql;
308 UINT i;
309
310 KeAcquireSpinLock(&Adapter->NdisMiniportBlock.Lock, &OldIrql);
311
312 CurrentEntry = Adapter->ProtocolListHead.Flink;
313
314 while (CurrentEntry != &Adapter->ProtocolListHead)
315 {
316 AdapterBinding = CONTAINING_RECORD(CurrentEntry, ADAPTER_BINDING, AdapterListEntry);
317
318 for (i = 0; i < NumberOfPackets; i++)
319 {
320 /* Store the indicating miniport in the packet */
321 PacketArray[i]->Reserved[1] = (ULONG_PTR)Adapter;
322
323 if (AdapterBinding->ProtocolBinding->Chars.ReceivePacketHandler &&
324 NDIS_GET_PACKET_STATUS(PacketArray[i]) != NDIS_STATUS_RESOURCES)
325 {
326 NDIS_DbgPrint(MID_TRACE, ("Indicating packet to protocol's ReceivePacket handler\n"));
327 PacketArray[i]->WrapperReserved[0] += (*AdapterBinding->ProtocolBinding->Chars.ReceivePacketHandler)(
328 AdapterBinding->NdisOpenBlock.ProtocolBindingContext,
329 PacketArray[i]);
330 NDIS_DbgPrint(MID_TRACE, ("Protocol is holding %d references to the packet\n", PacketArray[i]->WrapperReserved[0]));
331 }
332 else
333 {
334 UINT FirstBufferLength, TotalBufferLength, LookAheadSize, HeaderSize;
335 PNDIS_BUFFER NdisBuffer;
336 PVOID NdisBufferVA, LookAheadBuffer;
337
338 NdisGetFirstBufferFromPacket(PacketArray[i],
339 &NdisBuffer,
340 &NdisBufferVA,
341 &FirstBufferLength,
342 &TotalBufferLength);
343
344 HeaderSize = NDIS_GET_PACKET_HEADER_SIZE(PacketArray[i]);
345
346 LookAheadSize = TotalBufferLength - HeaderSize;
347
348 LookAheadBuffer = ExAllocatePool(NonPagedPool, LookAheadSize);
349 if (!LookAheadBuffer)
350 {
351 NDIS_DbgPrint(MIN_TRACE, ("Failed to allocate lookahead buffer!\n"));
352 KeReleaseSpinLock(&Adapter->NdisMiniportBlock.Lock, OldIrql);
353 return;
354 }
355
356 CopyBufferChainToBuffer(LookAheadBuffer,
357 NdisBuffer,
358 HeaderSize,
359 LookAheadSize);
360
361 NDIS_DbgPrint(MID_TRACE, ("Indicating packet to protocol's legacy Receive handler\n"));
362 (*AdapterBinding->ProtocolBinding->Chars.ReceiveHandler)(
363 AdapterBinding->NdisOpenBlock.ProtocolBindingContext,
364 AdapterBinding->NdisOpenBlock.MacHandle,
365 NdisBufferVA,
366 HeaderSize,
367 LookAheadBuffer,
368 LookAheadSize,
369 TotalBufferLength - HeaderSize);
370
371 ExFreePool(LookAheadBuffer);
372 }
373 }
374
375 CurrentEntry = CurrentEntry->Flink;
376 }
377
378 /* Loop the packet array to get everything
379 * set up for return the packets to the miniport */
380 for (i = 0; i < NumberOfPackets; i++)
381 {
382 /* First, check the initial packet status */
383 if (NDIS_GET_PACKET_STATUS(PacketArray[i]) == NDIS_STATUS_RESOURCES)
384 {
385 /* The miniport driver gets it back immediately so nothing to do here */
386 NDIS_DbgPrint(MID_TRACE, ("Miniport needs the packet back immediately\n"));
387 continue;
388 }
389
390 /* Different behavior depending on whether it's serialized or not */
391 if (Adapter->NdisMiniportBlock.Flags & NDIS_ATTRIBUTE_DESERIALIZE)
392 {
393 /* We need to check the reference count */
394 if (PacketArray[i]->WrapperReserved[0] == 0)
395 {
396 /* NOTE: Unlike serialized miniports, this is REQUIRED to be called for each
397 * packet received that can be reused immediately, it is not implied! */
398 Adapter->NdisMiniportBlock.DriverHandle->MiniportCharacteristics.ReturnPacketHandler(
399 Adapter->NdisMiniportBlock.MiniportAdapterContext,
400 PacketArray[i]);
401 NDIS_DbgPrint(MID_TRACE, ("Packet has been returned to miniport (Deserialized)\n"));
402 }
403 else
404 {
405 /* Packet will be returned by the protocol's call to NdisReturnPackets */
406 NDIS_DbgPrint(MID_TRACE, ("Packet will be returned to miniport later (Deserialized)\n"));
407 }
408 }
409 else
410 {
411 /* Check the reference count */
412 if (PacketArray[i]->WrapperReserved[0] == 0)
413 {
414 /* NDIS_STATUS_SUCCESS means the miniport can have the packet back immediately */
415 NDIS_SET_PACKET_STATUS(PacketArray[i], NDIS_STATUS_SUCCESS);
416
417 NDIS_DbgPrint(MID_TRACE, ("Packet has been returned to miniport (Serialized)\n"));
418 }
419 else
420 {
421 /* NDIS_STATUS_PENDING means the miniport needs to wait for MiniportReturnPacket */
422 NDIS_SET_PACKET_STATUS(PacketArray[i], NDIS_STATUS_PENDING);
423
424 NDIS_DbgPrint(MID_TRACE, ("Packet will be returned to miniport later (Serialized)\n"));
425 }
426 }
427 }
428
429 KeReleaseSpinLock(&Adapter->NdisMiniportBlock.Lock, OldIrql);
430 }
431
432 VOID NTAPI
433 MiniResetComplete(
434 IN NDIS_HANDLE MiniportAdapterHandle,
435 IN NDIS_STATUS Status,
436 IN BOOLEAN AddressingReset)
437 {
438 PLOGICAL_ADAPTER Adapter = MiniportAdapterHandle;
439 PLIST_ENTRY CurrentEntry;
440 PADAPTER_BINDING AdapterBinding;
441 KIRQL OldIrql;
442
443 if (AddressingReset)
444 MiniDoAddressingReset(Adapter);
445
446 NdisMIndicateStatus(Adapter, NDIS_STATUS_RESET_END, NULL, 0);
447 NdisMIndicateStatusComplete(Adapter);
448
449 KeAcquireSpinLock(&Adapter->NdisMiniportBlock.Lock, &OldIrql);
450
451 if (Adapter->NdisMiniportBlock.ResetStatus != NDIS_STATUS_PENDING)
452 {
453 KeBugCheckEx(BUGCODE_ID_DRIVER,
454 (ULONG_PTR)MiniportAdapterHandle,
455 (ULONG_PTR)Status,
456 (ULONG_PTR)AddressingReset,
457 0);
458 }
459
460 Adapter->NdisMiniportBlock.ResetStatus = Status;
461
462 CurrentEntry = Adapter->ProtocolListHead.Flink;
463
464 while (CurrentEntry != &Adapter->ProtocolListHead)
465 {
466 AdapterBinding = CONTAINING_RECORD(CurrentEntry, ADAPTER_BINDING, AdapterListEntry);
467
468 (*AdapterBinding->ProtocolBinding->Chars.ResetCompleteHandler)(
469 AdapterBinding->NdisOpenBlock.ProtocolBindingContext,
470 Status);
471
472 CurrentEntry = CurrentEntry->Flink;
473 }
474
475 KeReleaseSpinLock(&Adapter->NdisMiniportBlock.Lock, OldIrql);
476 }
477
478 VOID NTAPI
479 MiniRequestComplete(
480 IN NDIS_HANDLE MiniportAdapterHandle,
481 IN NDIS_STATUS Status)
482 {
483 PLOGICAL_ADAPTER Adapter = (PLOGICAL_ADAPTER)MiniportAdapterHandle;
484 PNDIS_REQUEST Request;
485 PNDIS_REQUEST_MAC_BLOCK MacBlock;
486 KIRQL OldIrql;
487
488 NDIS_DbgPrint(DEBUG_MINIPORT, ("Called.\n"));
489
490 KeRaiseIrql(DISPATCH_LEVEL, &OldIrql);
491
492 KeAcquireSpinLockAtDpcLevel(&Adapter->NdisMiniportBlock.Lock);
493 Request = Adapter->NdisMiniportBlock.PendingRequest;
494 KeReleaseSpinLockFromDpcLevel(&Adapter->NdisMiniportBlock.Lock);
495
496 MacBlock = (PNDIS_REQUEST_MAC_BLOCK)Request->MacReserved;
497
498 if( MacBlock->Binding->RequestCompleteHandler ) {
499 (*MacBlock->Binding->RequestCompleteHandler)(
500 MacBlock->Binding->ProtocolBindingContext,
501 Request,
502 Status);
503 }
504
505 KeAcquireSpinLockAtDpcLevel(&Adapter->NdisMiniportBlock.Lock);
506 Adapter->NdisMiniportBlock.PendingRequest = NULL;
507 KeReleaseSpinLockFromDpcLevel(&Adapter->NdisMiniportBlock.Lock);
508 KeLowerIrql(OldIrql);
509
510 MiniWorkItemComplete(Adapter, NdisWorkItemRequest);
511 }
512
513 VOID NTAPI
514 MiniSendComplete(
515 IN NDIS_HANDLE MiniportAdapterHandle,
516 IN PNDIS_PACKET Packet,
517 IN NDIS_STATUS Status)
518 /*
519 * FUNCTION: Forwards a message to the initiating protocol saying
520 * that a packet was handled
521 * ARGUMENTS:
522 * NdisAdapterHandle = Handle input to MiniportInitialize
523 * Packet = Pointer to NDIS packet that was sent
524 * Status = Status of send operation
525 */
526 {
527 PLOGICAL_ADAPTER Adapter = MiniportAdapterHandle;
528 PADAPTER_BINDING AdapterBinding;
529 KIRQL OldIrql;
530 PSCATTER_GATHER_LIST SGList;
531
532 NDIS_DbgPrint(DEBUG_MINIPORT, ("Called.\n"));
533
534 AdapterBinding = (PADAPTER_BINDING)Packet->Reserved[1];
535
536 KeRaiseIrql(DISPATCH_LEVEL, &OldIrql);
537
538 if (Adapter->NdisMiniportBlock.ScatterGatherListSize != 0)
539 {
540 NDIS_DbgPrint(MAX_TRACE, ("Freeing Scatter/Gather list\n"));
541
542 SGList = NDIS_PER_PACKET_INFO_FROM_PACKET(Packet,
543 ScatterGatherListPacketInfo);
544
545 Adapter->NdisMiniportBlock.SystemAdapterObject->
546 DmaOperations->PutScatterGatherList(
547 Adapter->NdisMiniportBlock.SystemAdapterObject,
548 SGList,
549 TRUE);
550
551 NDIS_PER_PACKET_INFO_FROM_PACKET(Packet,
552 ScatterGatherListPacketInfo) = NULL;
553 }
554
555 (*AdapterBinding->ProtocolBinding->Chars.SendCompleteHandler)(
556 AdapterBinding->NdisOpenBlock.ProtocolBindingContext,
557 Packet,
558 Status);
559
560 KeLowerIrql(OldIrql);
561
562 MiniWorkItemComplete(Adapter, NdisWorkItemSend);
563 }
564
565
566 VOID NTAPI
567 MiniSendResourcesAvailable(
568 IN NDIS_HANDLE MiniportAdapterHandle)
569 {
570 /* Run the work if anything is waiting */
571 MiniWorkItemComplete((PLOGICAL_ADAPTER)MiniportAdapterHandle, NdisWorkItemSend);
572 }
573
574
575 VOID NTAPI
576 MiniTransferDataComplete(
577 IN NDIS_HANDLE MiniportAdapterHandle,
578 IN PNDIS_PACKET Packet,
579 IN NDIS_STATUS Status,
580 IN UINT BytesTransferred)
581 {
582 PADAPTER_BINDING AdapterBinding;
583 KIRQL OldIrql;
584
585 NDIS_DbgPrint(DEBUG_MINIPORT, ("Called.\n"));
586
587 AdapterBinding = (PADAPTER_BINDING)Packet->Reserved[1];
588
589 KeRaiseIrql(DISPATCH_LEVEL, &OldIrql);
590 (*AdapterBinding->ProtocolBinding->Chars.TransferDataCompleteHandler)(
591 AdapterBinding->NdisOpenBlock.ProtocolBindingContext,
592 Packet,
593 Status,
594 BytesTransferred);
595 KeLowerIrql(OldIrql);
596 }
597
598
599 BOOLEAN
600 MiniAdapterHasAddress(
601 PLOGICAL_ADAPTER Adapter,
602 PNDIS_PACKET Packet)
603 /*
604 * FUNCTION: Determines whether a packet has the same destination address as an adapter
605 * ARGUMENTS:
606 * Adapter = Pointer to logical adapter object
607 * Packet = Pointer to NDIS packet
608 * RETURNS:
609 * TRUE if the destination address is that of the adapter, FALSE if not
610 */
611 {
612 UINT Length;
613 PUCHAR Start1;
614 PUCHAR Start2;
615 PNDIS_BUFFER NdisBuffer;
616 UINT BufferLength;
617
618 NDIS_DbgPrint(DEBUG_MINIPORT, ("Called.\n"));
619
620 #if DBG
621 if(!Adapter)
622 {
623 NDIS_DbgPrint(MIN_TRACE, ("Adapter object was null\n"));
624 return FALSE;
625 }
626
627 if(!Packet)
628 {
629 NDIS_DbgPrint(MIN_TRACE, ("Packet was null\n"));
630 return FALSE;
631 }
632 #endif
633
634 NdisQueryPacket(Packet, NULL, NULL, &NdisBuffer, NULL);
635
636 if (!NdisBuffer)
637 {
638 NDIS_DbgPrint(MIN_TRACE, ("Packet contains no buffers.\n"));
639 return FALSE;
640 }
641
642 NdisQueryBuffer(NdisBuffer, (PVOID)&Start2, &BufferLength);
643
644 /* FIXME: Should handle fragmented packets */
645
646 switch (Adapter->NdisMiniportBlock.MediaType)
647 {
648 case NdisMedium802_3:
649 Length = ETH_LENGTH_OF_ADDRESS;
650 /* Destination address is the first field */
651 break;
652
653 default:
654 NDIS_DbgPrint(MIN_TRACE, ("Adapter has unsupported media type (0x%X).\n", Adapter->NdisMiniportBlock.MediaType));
655 return FALSE;
656 }
657
658 if (BufferLength < Length)
659 {
660 NDIS_DbgPrint(MIN_TRACE, ("Buffer is too small.\n"));
661 return FALSE;
662 }
663
664 Start1 = (PUCHAR)&Adapter->Address;
665 NDIS_DbgPrint(MAX_TRACE, ("packet address: %x:%x:%x:%x:%x:%x adapter address: %x:%x:%x:%x:%x:%x\n",
666 *((char *)Start1), *(((char *)Start1)+1), *(((char *)Start1)+2), *(((char *)Start1)+3), *(((char *)Start1)+4), *(((char *)Start1)+5),
667 *((char *)Start2), *(((char *)Start2)+1), *(((char *)Start2)+2), *(((char *)Start2)+3), *(((char *)Start2)+4), *(((char *)Start2)+5)));
668
669 return (RtlCompareMemory((PVOID)Start1, (PVOID)Start2, Length) == Length);
670 }
671
672
673 PLOGICAL_ADAPTER
674 MiniLocateDevice(
675 PNDIS_STRING AdapterName)
676 /*
677 * FUNCTION: Finds an adapter object by name
678 * ARGUMENTS:
679 * AdapterName = Pointer to name of adapter
680 * RETURNS:
681 * Pointer to logical adapter object, or NULL if none was found.
682 * If found, the adapter is referenced for the caller. The caller
683 * is responsible for dereferencing after use
684 */
685 {
686 KIRQL OldIrql;
687 PLIST_ENTRY CurrentEntry;
688 PLOGICAL_ADAPTER Adapter = 0;
689
690 ASSERT(AdapterName);
691
692 NDIS_DbgPrint(DEBUG_MINIPORT, ("Called.\n"));
693
694 if(IsListEmpty(&AdapterListHead))
695 {
696 NDIS_DbgPrint(MIN_TRACE, ("No registered miniports for protocol to bind to\n"));
697 return NULL;
698 }
699
700 NDIS_DbgPrint(DEBUG_MINIPORT, ("AdapterName = %wZ\n", AdapterName));
701
702 KeAcquireSpinLock(&AdapterListLock, &OldIrql);
703 {
704 CurrentEntry = AdapterListHead.Flink;
705
706 while (CurrentEntry != &AdapterListHead)
707 {
708 Adapter = CONTAINING_RECORD(CurrentEntry, LOGICAL_ADAPTER, ListEntry);
709
710 ASSERT(Adapter);
711
712 NDIS_DbgPrint(DEBUG_MINIPORT, ("Examining adapter 0x%lx\n", Adapter));
713
714 /* We're technically not allowed to call this above PASSIVE_LEVEL, but it doesn't break
715 * right now and I'd rather use a working API than reimplement it here */
716 if (RtlCompareUnicodeString(AdapterName, &Adapter->NdisMiniportBlock.MiniportName, TRUE) == 0)
717 {
718 break;
719 }
720
721 Adapter = NULL;
722 CurrentEntry = CurrentEntry->Flink;
723 }
724 }
725 KeReleaseSpinLock(&AdapterListLock, OldIrql);
726
727 if(Adapter)
728 {
729 NDIS_DbgPrint(DEBUG_MINIPORT, ("Leaving. Adapter found at 0x%x\n", Adapter));
730 }
731 else
732 {
733 NDIS_DbgPrint(MIN_TRACE, ("Leaving (adapter not found for %wZ).\n", AdapterName));
734 }
735
736 return Adapter;
737 }
738
739 NDIS_STATUS
740 MiniSetInformation(
741 PLOGICAL_ADAPTER Adapter,
742 NDIS_OID Oid,
743 ULONG Size,
744 PVOID Buffer,
745 PULONG BytesRead)
746 {
747 NDIS_STATUS NdisStatus;
748 PNDIS_REQUEST NdisRequest;
749
750 NDIS_DbgPrint(DEBUG_MINIPORT, ("Called.\n"));
751
752 NdisRequest = ExAllocatePool(NonPagedPool, sizeof(NDIS_REQUEST));
753 if (!NdisRequest) {
754 NDIS_DbgPrint(MIN_TRACE, ("Insufficient resources\n"));
755 return NDIS_STATUS_RESOURCES;
756 }
757
758 RtlZeroMemory(NdisRequest, sizeof(NDIS_REQUEST));
759
760 NdisRequest->RequestType = NdisRequestSetInformation;
761 NdisRequest->DATA.SET_INFORMATION.Oid = Oid;
762 NdisRequest->DATA.SET_INFORMATION.InformationBuffer = Buffer;
763 NdisRequest->DATA.SET_INFORMATION.InformationBufferLength = Size;
764
765 NdisStatus = MiniDoRequest(Adapter, NdisRequest);
766
767 /* FIXME: Wait in pending case! */
768
769 ASSERT(NdisStatus != NDIS_STATUS_PENDING);
770
771 *BytesRead = NdisRequest->DATA.SET_INFORMATION.BytesRead;
772
773 ExFreePool(NdisRequest);
774
775 return NdisStatus;
776 }
777
778 NDIS_STATUS
779 MiniQueryInformation(
780 PLOGICAL_ADAPTER Adapter,
781 NDIS_OID Oid,
782 ULONG Size,
783 PVOID Buffer,
784 PULONG BytesWritten)
785 /*
786 * FUNCTION: Queries a logical adapter for properties
787 * ARGUMENTS:
788 * Adapter = Pointer to the logical adapter object to query
789 * Oid = Specifies the Object ID to query for
790 * Size = Size of the passed buffer
791 * Buffer = Buffer for the output
792 * BytesWritten = Address of buffer to place number of bytes written
793 * RETURNS:
794 * Status of operation
795 */
796 {
797 NDIS_STATUS NdisStatus;
798 PNDIS_REQUEST NdisRequest;
799
800 NDIS_DbgPrint(DEBUG_MINIPORT, ("Called.\n"));
801
802 NdisRequest = ExAllocatePool(NonPagedPool, sizeof(NDIS_REQUEST));
803 if (!NdisRequest) {
804 NDIS_DbgPrint(MIN_TRACE, ("Insufficient resources\n"));
805 return NDIS_STATUS_RESOURCES;
806 }
807
808 RtlZeroMemory(NdisRequest, sizeof(NDIS_REQUEST));
809
810 NdisRequest->RequestType = NdisRequestQueryInformation;
811 NdisRequest->DATA.QUERY_INFORMATION.Oid = Oid;
812 NdisRequest->DATA.QUERY_INFORMATION.InformationBuffer = Buffer;
813 NdisRequest->DATA.QUERY_INFORMATION.InformationBufferLength = Size;
814
815 NdisStatus = MiniDoRequest(Adapter, NdisRequest);
816
817 /* FIXME: Wait in pending case! */
818
819 ASSERT(NdisStatus != NDIS_STATUS_PENDING);
820
821 *BytesWritten = NdisRequest->DATA.QUERY_INFORMATION.BytesWritten;
822
823 ExFreePool(NdisRequest);
824
825 return NdisStatus;
826 }
827
828 BOOLEAN
829 MiniCheckForHang( PLOGICAL_ADAPTER Adapter )
830 /*
831 * FUNCTION: Checks to see if the miniport is hung
832 * ARGUMENTS:
833 * Adapter = Pointer to the logical adapter object
834 * RETURNS:
835 * TRUE if the miniport is hung
836 * FALSE if the miniport is not hung
837 */
838 {
839 BOOLEAN Ret = FALSE;
840 KIRQL OldIrql;
841
842 KeRaiseIrql(DISPATCH_LEVEL, &OldIrql);
843 if (Adapter->NdisMiniportBlock.DriverHandle->MiniportCharacteristics.CheckForHangHandler)
844 Ret = (*Adapter->NdisMiniportBlock.DriverHandle->MiniportCharacteristics.CheckForHangHandler)(
845 Adapter->NdisMiniportBlock.MiniportAdapterContext);
846 KeLowerIrql(OldIrql);
847
848 return Ret;
849 }
850
851 VOID
852 MiniDoAddressingReset(PLOGICAL_ADAPTER Adapter)
853 {
854 ULONG BytesRead;
855
856 MiniSetInformation(Adapter,
857 OID_GEN_CURRENT_LOOKAHEAD,
858 sizeof(ULONG),
859 &Adapter->NdisMiniportBlock.CurrentLookahead,
860 &BytesRead);
861
862 /* FIXME: Set more stuff */
863 }
864
865 NDIS_STATUS
866 MiniReset(
867 PLOGICAL_ADAPTER Adapter)
868 /*
869 * FUNCTION: Resets the miniport
870 * ARGUMENTS:
871 * Adapter = Pointer to the logical adapter object
872 * RETURNS:
873 * Status of the operation
874 */
875 {
876 NDIS_STATUS Status;
877 KIRQL OldIrql;
878 BOOLEAN AddressingReset = TRUE;
879
880 if (MiniIsBusy(Adapter, NdisWorkItemResetRequested)) {
881 MiniQueueWorkItem(Adapter, NdisWorkItemResetRequested, NULL, FALSE);
882 return NDIS_STATUS_PENDING;
883 }
884
885 NdisMIndicateStatus(Adapter, NDIS_STATUS_RESET_START, NULL, 0);
886 NdisMIndicateStatusComplete(Adapter);
887
888 KeRaiseIrql(DISPATCH_LEVEL, &OldIrql);
889 Status = (*Adapter->NdisMiniportBlock.DriverHandle->MiniportCharacteristics.ResetHandler)(
890 Adapter->NdisMiniportBlock.MiniportAdapterContext,
891 &AddressingReset);
892
893 KeAcquireSpinLockAtDpcLevel(&Adapter->NdisMiniportBlock.Lock);
894 Adapter->NdisMiniportBlock.ResetStatus = Status;
895 KeReleaseSpinLockFromDpcLevel(&Adapter->NdisMiniportBlock.Lock);
896
897 KeLowerIrql(OldIrql);
898
899 if (Status != NDIS_STATUS_PENDING) {
900 if (AddressingReset)
901 MiniDoAddressingReset(Adapter);
902
903 NdisMIndicateStatus(Adapter, NDIS_STATUS_RESET_END, NULL, 0);
904 NdisMIndicateStatusComplete(Adapter);
905
906 MiniWorkItemComplete(Adapter, NdisWorkItemResetRequested);
907 }
908
909 return Status;
910 }
911
912 VOID NTAPI
913 MiniportHangDpc(
914 PKDPC Dpc,
915 PVOID DeferredContext,
916 PVOID SystemArgument1,
917 PVOID SystemArgument2)
918 {
919 PLOGICAL_ADAPTER Adapter = DeferredContext;
920
921 if (MiniCheckForHang(Adapter)) {
922 NDIS_DbgPrint(MIN_TRACE, ("Miniport detected adapter hang\n"));
923 MiniReset(Adapter);
924 }
925 }
926
927 VOID
928 MiniWorkItemComplete(
929 PLOGICAL_ADAPTER Adapter,
930 NDIS_WORK_ITEM_TYPE WorkItemType)
931 {
932 PIO_WORKITEM IoWorkItem;
933
934 /* Check if there's anything queued to run after this work item */
935 if (!MiniIsBusy(Adapter, WorkItemType))
936 return;
937
938 /* There is, so fire the worker */
939 IoWorkItem = IoAllocateWorkItem(Adapter->NdisMiniportBlock.DeviceObject);
940 if (IoWorkItem)
941 IoQueueWorkItem(IoWorkItem, MiniportWorker, DelayedWorkQueue, IoWorkItem);
942 }
943
944 VOID
945 FASTCALL
946 MiniQueueWorkItem(
947 PLOGICAL_ADAPTER Adapter,
948 NDIS_WORK_ITEM_TYPE WorkItemType,
949 PVOID WorkItemContext,
950 BOOLEAN Top)
951 /*
952 * FUNCTION: Queues a work item for execution at a later time
953 * ARGUMENTS:
954 * Adapter = Pointer to the logical adapter object to queue work item on
955 * WorkItemType = Type of work item to queue
956 * WorkItemContext = Pointer to context information for work item
957 * RETURNS:
958 * Status of operation
959 */
960 {
961 PNDIS_MINIPORT_WORK_ITEM MiniportWorkItem;
962 KIRQL OldIrql;
963
964 NDIS_DbgPrint(MAX_TRACE, ("Called.\n"));
965
966 ASSERT(Adapter);
967
968 KeAcquireSpinLock(&Adapter->NdisMiniportBlock.Lock, &OldIrql);
969 if (Top)
970 {
971 if (WorkItemType == NdisWorkItemSend)
972 {
973 NDIS_DbgPrint(MIN_TRACE, ("Requeuing failed packet (%x).\n", WorkItemContext));
974 Adapter->NdisMiniportBlock.FirstPendingPacket = WorkItemContext;
975 }
976 else
977 {
978 //This should never happen
979 ASSERT(FALSE);
980 }
981 }
982 else
983 {
984 MiniportWorkItem = ExAllocatePool(NonPagedPool, sizeof(NDIS_MINIPORT_WORK_ITEM));
985 if (!MiniportWorkItem)
986 {
987 KeReleaseSpinLock(&Adapter->NdisMiniportBlock.Lock, OldIrql);
988 NDIS_DbgPrint(MIN_TRACE, ("Insufficient resources.\n"));
989 return;
990 }
991
992 MiniportWorkItem->WorkItemType = WorkItemType;
993 MiniportWorkItem->WorkItemContext = WorkItemContext;
994
995 /* safe due to adapter lock held */
996 MiniportWorkItem->Link.Next = NULL;
997 if (!Adapter->WorkQueueHead)
998 {
999 Adapter->WorkQueueHead = MiniportWorkItem;
1000 Adapter->WorkQueueTail = MiniportWorkItem;
1001 }
1002 else
1003 {
1004 Adapter->WorkQueueTail->Link.Next = (PSINGLE_LIST_ENTRY)MiniportWorkItem;
1005 Adapter->WorkQueueTail = MiniportWorkItem;
1006 }
1007 }
1008
1009 KeReleaseSpinLock(&Adapter->NdisMiniportBlock.Lock, OldIrql);
1010 }
1011
1012 NDIS_STATUS
1013 FASTCALL
1014 MiniDequeueWorkItem(
1015 PLOGICAL_ADAPTER Adapter,
1016 NDIS_WORK_ITEM_TYPE *WorkItemType,
1017 PVOID *WorkItemContext)
1018 /*
1019 * FUNCTION: Dequeues a work item from the work queue of a logical adapter
1020 * ARGUMENTS:
1021 * Adapter = Pointer to the logical adapter object to dequeue work item from
1022 * AdapterBinding = Address of buffer for adapter binding for this request
1023 * WorkItemType = Address of buffer for work item type
1024 * WorkItemContext = Address of buffer for pointer to context information
1025 * NOTES:
1026 * Adapter lock must be held when called
1027 * RETURNS:
1028 * Status of operation
1029 */
1030 {
1031 PNDIS_MINIPORT_WORK_ITEM MiniportWorkItem;
1032 PNDIS_PACKET Packet;
1033
1034 NDIS_DbgPrint(MAX_TRACE, ("Called.\n"));
1035
1036 MiniportWorkItem = Adapter->WorkQueueHead;
1037
1038 if ((Packet = Adapter->NdisMiniportBlock.FirstPendingPacket))
1039 {
1040 Adapter->NdisMiniportBlock.FirstPendingPacket = NULL;
1041
1042 *WorkItemType = NdisWorkItemSend;
1043 *WorkItemContext = Packet;
1044
1045 return NDIS_STATUS_SUCCESS;
1046 }
1047 else if (MiniportWorkItem)
1048 {
1049 /* safe due to adapter lock held */
1050 Adapter->WorkQueueHead = (PNDIS_MINIPORT_WORK_ITEM)MiniportWorkItem->Link.Next;
1051
1052 if (MiniportWorkItem == Adapter->WorkQueueTail)
1053 Adapter->WorkQueueTail = NULL;
1054
1055 *WorkItemType = MiniportWorkItem->WorkItemType;
1056 *WorkItemContext = MiniportWorkItem->WorkItemContext;
1057
1058 ExFreePool(MiniportWorkItem);
1059
1060 return NDIS_STATUS_SUCCESS;
1061 }
1062 else
1063 {
1064 NDIS_DbgPrint(MIN_TRACE, ("No work item to dequeue\n"));
1065
1066 return NDIS_STATUS_FAILURE;
1067 }
1068 }
1069
1070 NDIS_STATUS
1071 MiniDoRequest(
1072 PLOGICAL_ADAPTER Adapter,
1073 PNDIS_REQUEST NdisRequest)
1074 /*
1075 * FUNCTION: Sends a request to a miniport
1076 * ARGUMENTS:
1077 * AdapterBinding = Pointer to binding used in the request
1078 * NdisRequest = Pointer to NDIS request structure describing request
1079 * RETURNS:
1080 * Status of operation
1081 */
1082 {
1083 NDIS_STATUS Status;
1084 KIRQL OldIrql;
1085 NDIS_DbgPrint(DEBUG_MINIPORT, ("Called.\n"));
1086
1087 KeRaiseIrql(DISPATCH_LEVEL, &OldIrql);
1088
1089 KeAcquireSpinLockAtDpcLevel(&Adapter->NdisMiniportBlock.Lock);
1090 Adapter->NdisMiniportBlock.PendingRequest = NdisRequest;
1091 KeReleaseSpinLockFromDpcLevel(&Adapter->NdisMiniportBlock.Lock);
1092
1093 if (!Adapter->NdisMiniportBlock.DriverHandle->MiniportCharacteristics.CoRequestHandler)
1094 {
1095 switch (NdisRequest->RequestType)
1096 {
1097 case NdisRequestQueryInformation:
1098 Status = (*Adapter->NdisMiniportBlock.DriverHandle->MiniportCharacteristics.QueryInformationHandler)(
1099 Adapter->NdisMiniportBlock.MiniportAdapterContext,
1100 NdisRequest->DATA.QUERY_INFORMATION.Oid,
1101 NdisRequest->DATA.QUERY_INFORMATION.InformationBuffer,
1102 NdisRequest->DATA.QUERY_INFORMATION.InformationBufferLength,
1103 (PULONG)&NdisRequest->DATA.QUERY_INFORMATION.BytesWritten,
1104 (PULONG)&NdisRequest->DATA.QUERY_INFORMATION.BytesNeeded);
1105 break;
1106
1107 case NdisRequestSetInformation:
1108 Status = (*Adapter->NdisMiniportBlock.DriverHandle->MiniportCharacteristics.SetInformationHandler)(
1109 Adapter->NdisMiniportBlock.MiniportAdapterContext,
1110 NdisRequest->DATA.SET_INFORMATION.Oid,
1111 NdisRequest->DATA.SET_INFORMATION.InformationBuffer,
1112 NdisRequest->DATA.SET_INFORMATION.InformationBufferLength,
1113 (PULONG)&NdisRequest->DATA.SET_INFORMATION.BytesRead,
1114 (PULONG)&NdisRequest->DATA.SET_INFORMATION.BytesNeeded);
1115 break;
1116
1117 default:
1118 NDIS_DbgPrint(MIN_TRACE, ("Bad request type\n"));
1119 Status = NDIS_STATUS_FAILURE;
1120 }
1121 }
1122 else
1123 {
1124 Status = (*Adapter->NdisMiniportBlock.DriverHandle->MiniportCharacteristics.CoRequestHandler)(
1125 Adapter->NdisMiniportBlock.MiniportAdapterContext,
1126 NULL, /* FIXME */
1127 NdisRequest);
1128 }
1129
1130 if (Status != NDIS_STATUS_PENDING) {
1131 KeAcquireSpinLockAtDpcLevel(&Adapter->NdisMiniportBlock.Lock);
1132 Adapter->NdisMiniportBlock.PendingRequest = NULL;
1133 KeReleaseSpinLockFromDpcLevel(&Adapter->NdisMiniportBlock.Lock);
1134 }
1135
1136 KeLowerIrql(OldIrql);
1137
1138 if (Status != NDIS_STATUS_PENDING) {
1139 MiniWorkItemComplete(Adapter, NdisWorkItemRequest);
1140 }
1141
1142 return Status;
1143 }
1144
1145 /*
1146 * @implemented
1147 */
1148 #undef NdisMSetInformationComplete
1149 VOID
1150 EXPORT
1151 NdisMSetInformationComplete(
1152 IN NDIS_HANDLE MiniportAdapterHandle,
1153 IN NDIS_STATUS Status)
1154 {
1155 PLOGICAL_ADAPTER Adapter =
1156 (PLOGICAL_ADAPTER)MiniportAdapterHandle;
1157 KIRQL OldIrql;
1158 ASSERT(Adapter);
1159 KeRaiseIrql(DISPATCH_LEVEL, &OldIrql);
1160 if (Adapter->NdisMiniportBlock.SetCompleteHandler)
1161 (Adapter->NdisMiniportBlock.SetCompleteHandler)(MiniportAdapterHandle, Status);
1162 KeLowerIrql(OldIrql);
1163 }
1164
1165 /*
1166 * @implemented
1167 */
1168 #undef NdisMQueryInformationComplete
1169 VOID
1170 EXPORT
1171 NdisMQueryInformationComplete(
1172 IN NDIS_HANDLE MiniportAdapterHandle,
1173 IN NDIS_STATUS Status)
1174 {
1175 PLOGICAL_ADAPTER Adapter =
1176 (PLOGICAL_ADAPTER)MiniportAdapterHandle;
1177 KIRQL OldIrql;
1178 ASSERT(Adapter);
1179 KeRaiseIrql(DISPATCH_LEVEL, &OldIrql);
1180 if( Adapter->NdisMiniportBlock.QueryCompleteHandler )
1181 (Adapter->NdisMiniportBlock.QueryCompleteHandler)(MiniportAdapterHandle, Status);
1182 KeLowerIrql(OldIrql);
1183 }
1184
1185 VOID
1186 NTAPI
1187 MiniportWorker(IN PDEVICE_OBJECT DeviceObject, IN PVOID Context)
1188 {
1189 PLOGICAL_ADAPTER Adapter = DeviceObject->DeviceExtension;
1190 KIRQL OldIrql, RaiseOldIrql;
1191 NDIS_STATUS NdisStatus;
1192 PVOID WorkItemContext;
1193 NDIS_WORK_ITEM_TYPE WorkItemType;
1194 BOOLEAN AddressingReset;
1195
1196 IoFreeWorkItem((PIO_WORKITEM)Context);
1197
1198 KeAcquireSpinLock(&Adapter->NdisMiniportBlock.Lock, &OldIrql);
1199
1200 NdisStatus =
1201 MiniDequeueWorkItem
1202 (Adapter, &WorkItemType, &WorkItemContext);
1203
1204 KeReleaseSpinLock(&Adapter->NdisMiniportBlock.Lock, OldIrql);
1205
1206 if (NdisStatus == NDIS_STATUS_SUCCESS)
1207 {
1208 switch (WorkItemType)
1209 {
1210 case NdisWorkItemSend:
1211 /*
1212 * called by ProSend when protocols want to send packets to the miniport
1213 */
1214
1215 if(Adapter->NdisMiniportBlock.DriverHandle->MiniportCharacteristics.SendPacketsHandler)
1216 {
1217 if(Adapter->NdisMiniportBlock.Flags & NDIS_ATTRIBUTE_DESERIALIZE)
1218 {
1219 NDIS_DbgPrint(MAX_TRACE, ("Calling miniport's SendPackets handler\n"));
1220 (*Adapter->NdisMiniportBlock.DriverHandle->MiniportCharacteristics.SendPacketsHandler)(
1221 Adapter->NdisMiniportBlock.MiniportAdapterContext, (PPNDIS_PACKET)&WorkItemContext, 1);
1222 NdisStatus = NDIS_STATUS_PENDING;
1223 }
1224 else
1225 {
1226 /* SendPackets is called at DISPATCH_LEVEL for all serialized miniports */
1227 KeRaiseIrql(DISPATCH_LEVEL, &RaiseOldIrql);
1228 {
1229 NDIS_DbgPrint(MAX_TRACE, ("Calling miniport's SendPackets handler\n"));
1230 (*Adapter->NdisMiniportBlock.DriverHandle->MiniportCharacteristics.SendPacketsHandler)(
1231 Adapter->NdisMiniportBlock.MiniportAdapterContext, (PPNDIS_PACKET)&WorkItemContext, 1);
1232 }
1233 KeLowerIrql(RaiseOldIrql);
1234
1235 NdisStatus = NDIS_GET_PACKET_STATUS((PNDIS_PACKET)WorkItemContext);
1236 if( NdisStatus == NDIS_STATUS_RESOURCES ) {
1237 MiniQueueWorkItem(Adapter, WorkItemType, WorkItemContext, TRUE);
1238 break;
1239 }
1240 }
1241 }
1242 else
1243 {
1244 if(Adapter->NdisMiniportBlock.Flags & NDIS_ATTRIBUTE_DESERIALIZE)
1245 {
1246 NDIS_DbgPrint(MAX_TRACE, ("Calling miniport's Send handler\n"));
1247 NdisStatus = (*Adapter->NdisMiniportBlock.DriverHandle->MiniportCharacteristics.SendHandler)(
1248 Adapter->NdisMiniportBlock.MiniportAdapterContext, (PNDIS_PACKET)WorkItemContext,
1249 ((PNDIS_PACKET)WorkItemContext)->Private.Flags);
1250 NDIS_DbgPrint(MAX_TRACE, ("back from miniport's send handler\n"));
1251 }
1252 else
1253 {
1254 /* Send is called at DISPATCH_LEVEL for all serialized miniports */
1255 KeRaiseIrql(DISPATCH_LEVEL, &RaiseOldIrql);
1256 NDIS_DbgPrint(MAX_TRACE, ("Calling miniport's Send handler\n"));
1257 NdisStatus = (*Adapter->NdisMiniportBlock.DriverHandle->MiniportCharacteristics.SendHandler)(
1258 Adapter->NdisMiniportBlock.MiniportAdapterContext, (PNDIS_PACKET)WorkItemContext,
1259 ((PNDIS_PACKET)WorkItemContext)->Private.Flags);
1260 NDIS_DbgPrint(MAX_TRACE, ("back from miniport's send handler\n"));
1261 KeLowerIrql(RaiseOldIrql);
1262 if( NdisStatus == NDIS_STATUS_RESOURCES ) {
1263 MiniQueueWorkItem(Adapter, WorkItemType, WorkItemContext, TRUE);
1264 break;
1265 }
1266 }
1267 }
1268
1269 if( NdisStatus != NDIS_STATUS_PENDING ) {
1270 MiniSendComplete
1271 ( Adapter, (PNDIS_PACKET)WorkItemContext, NdisStatus );
1272 }
1273 break;
1274
1275 case NdisWorkItemSendLoopback:
1276 /*
1277 * called by ProSend when protocols want to send loopback packets
1278 */
1279 /* XXX atm ProIndicatePacket sends a packet up via the loopback adapter only */
1280 NdisStatus = ProIndicatePacket(Adapter, (PNDIS_PACKET)WorkItemContext);
1281
1282 if( NdisStatus != NDIS_STATUS_PENDING )
1283 MiniSendComplete((NDIS_HANDLE)Adapter, (PNDIS_PACKET)WorkItemContext, NdisStatus);
1284 break;
1285
1286 case NdisWorkItemReturnPackets:
1287 break;
1288
1289 case NdisWorkItemResetRequested:
1290 NdisMIndicateStatus(Adapter, NDIS_STATUS_RESET_START, NULL, 0);
1291 NdisMIndicateStatusComplete(Adapter);
1292
1293 KeRaiseIrql(DISPATCH_LEVEL, &OldIrql);
1294 NdisStatus = (*Adapter->NdisMiniportBlock.DriverHandle->MiniportCharacteristics.ResetHandler)(
1295 Adapter->NdisMiniportBlock.MiniportAdapterContext,
1296 &AddressingReset);
1297
1298 KeAcquireSpinLockAtDpcLevel(&Adapter->NdisMiniportBlock.Lock);
1299 Adapter->NdisMiniportBlock.ResetStatus = NdisStatus;
1300 KeReleaseSpinLockFromDpcLevel(&Adapter->NdisMiniportBlock.Lock);
1301
1302 KeLowerIrql(OldIrql);
1303
1304 if (NdisStatus != NDIS_STATUS_PENDING)
1305 MiniResetComplete(Adapter, NdisStatus, AddressingReset);
1306 break;
1307
1308 case NdisWorkItemResetInProgress:
1309 break;
1310
1311 case NdisWorkItemMiniportCallback:
1312 break;
1313
1314 case NdisWorkItemRequest:
1315 NdisStatus = MiniDoRequest(Adapter, (PNDIS_REQUEST)WorkItemContext);
1316
1317 if (NdisStatus == NDIS_STATUS_PENDING)
1318 break;
1319
1320 Adapter->NdisMiniportBlock.PendingRequest = (PNDIS_REQUEST)WorkItemContext;
1321 switch (((PNDIS_REQUEST)WorkItemContext)->RequestType)
1322 {
1323 case NdisRequestQueryInformation:
1324 NdisMQueryInformationComplete((NDIS_HANDLE)Adapter, NdisStatus);
1325 break;
1326
1327 case NdisRequestSetInformation:
1328 NdisMSetInformationComplete((NDIS_HANDLE)Adapter, NdisStatus);
1329 break;
1330
1331 default:
1332 NDIS_DbgPrint(MIN_TRACE, ("Unknown NDIS request type.\n"));
1333 break;
1334 }
1335 Adapter->NdisMiniportBlock.PendingRequest = NULL;
1336 break;
1337
1338 default:
1339 NDIS_DbgPrint(MIN_TRACE, ("Unknown NDIS work item type (%d).\n", WorkItemType));
1340 break;
1341 }
1342 }
1343 }
1344
1345
1346 VOID
1347 NTAPI
1348 MiniStatus(
1349 IN NDIS_HANDLE MiniportHandle,
1350 IN NDIS_STATUS GeneralStatus,
1351 IN PVOID StatusBuffer,
1352 IN UINT StatusBufferSize)
1353 {
1354 PLOGICAL_ADAPTER Adapter = MiniportHandle;
1355 PLIST_ENTRY CurrentEntry;
1356 PADAPTER_BINDING AdapterBinding;
1357 KIRQL OldIrql;
1358
1359 KeAcquireSpinLock(&Adapter->NdisMiniportBlock.Lock, &OldIrql);
1360
1361 CurrentEntry = Adapter->ProtocolListHead.Flink;
1362
1363 while (CurrentEntry != &Adapter->ProtocolListHead)
1364 {
1365 AdapterBinding = CONTAINING_RECORD(CurrentEntry, ADAPTER_BINDING, AdapterListEntry);
1366
1367 (*AdapterBinding->ProtocolBinding->Chars.StatusHandler)(
1368 AdapterBinding->NdisOpenBlock.ProtocolBindingContext,
1369 GeneralStatus,
1370 StatusBuffer,
1371 StatusBufferSize);
1372
1373 CurrentEntry = CurrentEntry->Flink;
1374 }
1375
1376 KeReleaseSpinLock(&Adapter->NdisMiniportBlock.Lock, OldIrql);
1377 }
1378
1379 VOID
1380 NTAPI
1381 MiniStatusComplete(
1382 IN NDIS_HANDLE MiniportAdapterHandle)
1383 {
1384 PLOGICAL_ADAPTER Adapter = MiniportAdapterHandle;
1385 PLIST_ENTRY CurrentEntry;
1386 PADAPTER_BINDING AdapterBinding;
1387 KIRQL OldIrql;
1388
1389 KeAcquireSpinLock(&Adapter->NdisMiniportBlock.Lock, &OldIrql);
1390
1391 CurrentEntry = Adapter->ProtocolListHead.Flink;
1392
1393 while (CurrentEntry != &Adapter->ProtocolListHead)
1394 {
1395 AdapterBinding = CONTAINING_RECORD(CurrentEntry, ADAPTER_BINDING, AdapterListEntry);
1396
1397 (*AdapterBinding->ProtocolBinding->Chars.StatusCompleteHandler)(
1398 AdapterBinding->NdisOpenBlock.ProtocolBindingContext);
1399
1400 CurrentEntry = CurrentEntry->Flink;
1401 }
1402
1403 KeReleaseSpinLock(&Adapter->NdisMiniportBlock.Lock, OldIrql);
1404 }
1405
1406 /*
1407 * @implemented
1408 */
1409 VOID
1410 EXPORT
1411 NdisMCloseLog(
1412 IN NDIS_HANDLE LogHandle)
1413 {
1414 PNDIS_LOG Log = (PNDIS_LOG)LogHandle;
1415 PNDIS_MINIPORT_BLOCK Miniport = Log->Miniport;
1416 KIRQL OldIrql;
1417
1418 NDIS_DbgPrint(MAX_TRACE, ("called: LogHandle 0x%x\n", LogHandle));
1419
1420 KeAcquireSpinLock(&(Miniport)->Lock, &OldIrql);
1421 Miniport->Log = NULL;
1422 KeReleaseSpinLock(&(Miniport)->Lock, OldIrql);
1423
1424 ExFreePool(Log);
1425 }
1426
1427 /*
1428 * @implemented
1429 */
1430 NDIS_STATUS
1431 EXPORT
1432 NdisMCreateLog(
1433 IN NDIS_HANDLE MiniportAdapterHandle,
1434 IN UINT Size,
1435 OUT PNDIS_HANDLE LogHandle)
1436 {
1437 PLOGICAL_ADAPTER Adapter = MiniportAdapterHandle;
1438 PNDIS_LOG Log;
1439 KIRQL OldIrql;
1440
1441 NDIS_DbgPrint(MAX_TRACE, ("called: MiniportAdapterHandle 0x%x, Size %ld\n", MiniportAdapterHandle, Size));
1442
1443 KeAcquireSpinLock(&Adapter->NdisMiniportBlock.Lock, &OldIrql);
1444
1445 if (Adapter->NdisMiniportBlock.Log)
1446 {
1447 *LogHandle = NULL;
1448 return NDIS_STATUS_FAILURE;
1449 }
1450
1451 Log = ExAllocatePool(NonPagedPool, Size + sizeof(NDIS_LOG));
1452 if (!Log)
1453 {
1454 *LogHandle = NULL;
1455 return NDIS_STATUS_RESOURCES;
1456 }
1457
1458 Adapter->NdisMiniportBlock.Log = Log;
1459
1460 KeInitializeSpinLock(&Log->LogLock);
1461
1462 Log->Miniport = &Adapter->NdisMiniportBlock;
1463 Log->TotalSize = Size;
1464 Log->CurrentSize = 0;
1465 Log->OutPtr = 0;
1466 Log->InPtr = 0;
1467 Log->Irp = NULL;
1468
1469 *LogHandle = Log;
1470
1471 KeReleaseSpinLock(&Adapter->NdisMiniportBlock.Lock, OldIrql);
1472
1473 return NDIS_STATUS_SUCCESS;
1474 }
1475
1476 /*
1477 * @implemented
1478 */
1479 VOID
1480 EXPORT
1481 NdisMDeregisterAdapterShutdownHandler(
1482 IN NDIS_HANDLE MiniportHandle)
1483 /*
1484 * FUNCTION: de-registers a shutdown handler
1485 * ARGUMENTS: MiniportHandle: Handle passed into MiniportInitialize
1486 */
1487 {
1488 PLOGICAL_ADAPTER Adapter = (PLOGICAL_ADAPTER)MiniportHandle;
1489
1490 NDIS_DbgPrint(DEBUG_MINIPORT, ("Called.\n"));
1491
1492 if(Adapter->BugcheckContext->ShutdownHandler) {
1493 KeDeregisterBugCheckCallback(Adapter->BugcheckContext->CallbackRecord);
1494 IoUnregisterShutdownNotification(Adapter->NdisMiniportBlock.DeviceObject);
1495 }
1496 }
1497
1498 /*
1499 * @implemented
1500 */
1501 VOID
1502 EXPORT
1503 NdisMFlushLog(
1504 IN NDIS_HANDLE LogHandle)
1505 {
1506 PNDIS_LOG Log = (PNDIS_LOG) LogHandle;
1507 KIRQL OldIrql;
1508
1509 NDIS_DbgPrint(MAX_TRACE, ("called: LogHandle 0x%x\n", LogHandle));
1510
1511 /* Lock object */
1512 KeAcquireSpinLock(&Log->LogLock, &OldIrql);
1513
1514 /* Set buffers size */
1515 Log->CurrentSize = 0;
1516 Log->OutPtr = 0;
1517 Log->InPtr = 0;
1518
1519 /* Unlock object */
1520 KeReleaseSpinLock(&Log->LogLock, OldIrql);
1521 }
1522
1523 /*
1524 * @implemented
1525 */
1526 #undef NdisMIndicateStatus
1527 VOID
1528 EXPORT
1529 NdisMIndicateStatus(
1530 IN NDIS_HANDLE MiniportAdapterHandle,
1531 IN NDIS_STATUS GeneralStatus,
1532 IN PVOID StatusBuffer,
1533 IN UINT StatusBufferSize)
1534 {
1535 MiniStatus(MiniportAdapterHandle, GeneralStatus, StatusBuffer, StatusBufferSize);
1536 }
1537
1538 /*
1539 * @implemented
1540 */
1541 #undef NdisMIndicateStatusComplete
1542 VOID
1543 EXPORT
1544 NdisMIndicateStatusComplete(
1545 IN NDIS_HANDLE MiniportAdapterHandle)
1546 {
1547 MiniStatusComplete(MiniportAdapterHandle);
1548 }
1549
1550 /*
1551 * @implemented
1552 */
1553 VOID
1554 EXPORT
1555 NdisInitializeWrapper(
1556 OUT PNDIS_HANDLE NdisWrapperHandle,
1557 IN PVOID SystemSpecific1,
1558 IN PVOID SystemSpecific2,
1559 IN PVOID SystemSpecific3)
1560 /*
1561 * FUNCTION: Notifies the NDIS library that a new miniport is initializing
1562 * ARGUMENTS:
1563 * NdisWrapperHandle = Address of buffer to place NDIS wrapper handle
1564 * SystemSpecific1 = Pointer to the driver's driver object
1565 * SystemSpecific2 = Pointer to the driver's registry path
1566 * SystemSpecific3 = Always NULL
1567 * NOTES:
1568 * - SystemSpecific2 goes invalid so we copy it
1569 */
1570 {
1571 PNDIS_M_DRIVER_BLOCK Miniport;
1572 PUNICODE_STRING RegistryPath;
1573 WCHAR *RegistryBuffer;
1574
1575 NDIS_DbgPrint(MAX_TRACE, ("Called.\n"));
1576
1577 ASSERT(NdisWrapperHandle);
1578
1579 *NdisWrapperHandle = NULL;
1580
1581 #if BREAK_ON_MINIPORT_INIT
1582 DbgBreakPoint();
1583 #endif
1584
1585 Miniport = ExAllocatePool(NonPagedPool, sizeof(NDIS_M_DRIVER_BLOCK));
1586
1587 if (!Miniport)
1588 {
1589 NDIS_DbgPrint(MIN_TRACE, ("Insufficient resources.\n"));
1590 return;
1591 }
1592
1593 RtlZeroMemory(Miniport, sizeof(NDIS_M_DRIVER_BLOCK));
1594
1595 KeInitializeSpinLock(&Miniport->Lock);
1596
1597 Miniport->DriverObject = (PDRIVER_OBJECT)SystemSpecific1;
1598
1599 /* set the miniport's driver registry path */
1600 RegistryPath = ExAllocatePool(PagedPool, sizeof(UNICODE_STRING));
1601 if(!RegistryPath)
1602 {
1603 ExFreePool(Miniport);
1604 NDIS_DbgPrint(MIN_TRACE, ("Insufficient resources.\n"));
1605 return;
1606 }
1607
1608 RegistryPath->Length = ((PUNICODE_STRING)SystemSpecific2)->Length;
1609 RegistryPath->MaximumLength = RegistryPath->Length + sizeof(WCHAR); /* room for 0-term */
1610
1611 RegistryBuffer = ExAllocatePool(PagedPool, RegistryPath->MaximumLength);
1612 if(!RegistryBuffer)
1613 {
1614 NDIS_DbgPrint(MIN_TRACE, ("Insufficient resources.\n"));
1615 ExFreePool(Miniport);
1616 ExFreePool(RegistryPath);
1617 return;
1618 }
1619
1620 RtlCopyMemory(RegistryBuffer, ((PUNICODE_STRING)SystemSpecific2)->Buffer, RegistryPath->Length);
1621 RegistryBuffer[RegistryPath->Length/sizeof(WCHAR)] = 0;
1622
1623 RegistryPath->Buffer = RegistryBuffer;
1624 Miniport->RegistryPath = RegistryPath;
1625
1626 InitializeListHead(&Miniport->DeviceList);
1627
1628 /* Put miniport in global miniport list */
1629 ExInterlockedInsertTailList(&MiniportListHead, &Miniport->ListEntry, &MiniportListLock);
1630
1631 *NdisWrapperHandle = Miniport;
1632 }
1633
1634 VOID NTAPI NdisIBugcheckCallback(
1635 IN PVOID Buffer,
1636 IN ULONG Length)
1637 /*
1638 * FUNCTION: Internal callback for handling bugchecks - calls adapter's shutdown handler
1639 * ARGUMENTS:
1640 * Buffer: Pointer to a bugcheck callback context
1641 * Length: Unused
1642 */
1643 {
1644 PMINIPORT_BUGCHECK_CONTEXT Context = (PMINIPORT_BUGCHECK_CONTEXT)Buffer;
1645 ADAPTER_SHUTDOWN_HANDLER sh = (ADAPTER_SHUTDOWN_HANDLER)Context->ShutdownHandler;
1646
1647 NDIS_DbgPrint(DEBUG_MINIPORT, ("Called.\n"));
1648
1649 if(sh)
1650 sh(Context->DriverContext);
1651 }
1652
1653 /*
1654 * @implemented
1655 */
1656 VOID
1657 EXPORT
1658 NdisMRegisterAdapterShutdownHandler(
1659 IN NDIS_HANDLE MiniportHandle,
1660 IN PVOID ShutdownContext,
1661 IN ADAPTER_SHUTDOWN_HANDLER ShutdownHandler)
1662 /*
1663 * FUNCTION: Register a shutdown handler for an adapter
1664 * ARGUMENTS:
1665 * MiniportHandle: Handle originally passed into MiniportInitialize
1666 * ShutdownContext: Pre-initialized bugcheck context
1667 * ShutdownHandler: Function to call to handle the bugcheck
1668 * NOTES:
1669 * - I'm not sure about ShutdownContext
1670 */
1671 {
1672 PLOGICAL_ADAPTER Adapter = (PLOGICAL_ADAPTER)MiniportHandle;
1673 PMINIPORT_BUGCHECK_CONTEXT BugcheckContext;
1674
1675 NDIS_DbgPrint(DEBUG_MINIPORT, ("Called.\n"));
1676
1677 BugcheckContext = ExAllocatePool(NonPagedPool, sizeof(MINIPORT_BUGCHECK_CONTEXT));
1678 if(!BugcheckContext)
1679 {
1680 NDIS_DbgPrint(MIN_TRACE, ("Insufficient resources.\n"));
1681 return;
1682 }
1683
1684 BugcheckContext->ShutdownHandler = ShutdownHandler;
1685 BugcheckContext->DriverContext = ShutdownContext;
1686
1687 BugcheckContext->CallbackRecord = ExAllocatePool(NonPagedPool, sizeof(KBUGCHECK_CALLBACK_RECORD));
1688 if (!BugcheckContext->CallbackRecord) {
1689 ExFreePool(BugcheckContext);
1690 return;
1691 }
1692
1693 Adapter->BugcheckContext = BugcheckContext;
1694
1695 KeInitializeCallbackRecord(BugcheckContext->CallbackRecord);
1696
1697 KeRegisterBugCheckCallback(BugcheckContext->CallbackRecord, NdisIBugcheckCallback,
1698 BugcheckContext, sizeof(*BugcheckContext), (PUCHAR)"Ndis Miniport");
1699
1700 IoRegisterShutdownNotification(Adapter->NdisMiniportBlock.DeviceObject);
1701 }
1702
1703 NDIS_STATUS
1704 DoQueries(
1705 PLOGICAL_ADAPTER Adapter,
1706 NDIS_OID AddressOID)
1707 /*
1708 * FUNCTION: Queries miniport for information
1709 * ARGUMENTS:
1710 * Adapter = Pointer to logical adapter
1711 * AddressOID = OID to use to query for current address
1712 * RETURNS:
1713 * Status of operation
1714 */
1715 {
1716 ULONG BytesWritten;
1717 NDIS_STATUS NdisStatus;
1718
1719 NDIS_DbgPrint(MAX_TRACE, ("Called.\n"));
1720
1721 /* Get MAC options for adapter */
1722 NdisStatus = MiniQueryInformation(Adapter, OID_GEN_MAC_OPTIONS, sizeof(UINT),
1723 &Adapter->NdisMiniportBlock.MacOptions,
1724 &BytesWritten);
1725
1726 if (NdisStatus != NDIS_STATUS_SUCCESS)
1727 {
1728 NDIS_DbgPrint(MIN_TRACE, ("OID_GEN_MAC_OPTIONS failed. NdisStatus (0x%X).\n", NdisStatus));
1729 return NdisStatus;
1730 }
1731
1732 NDIS_DbgPrint(DEBUG_MINIPORT, ("MacOptions (0x%X).\n", Adapter->NdisMiniportBlock.MacOptions));
1733
1734 /* Get current hardware address of adapter */
1735 NdisStatus = MiniQueryInformation(Adapter, AddressOID, Adapter->AddressLength,
1736 &Adapter->Address, &BytesWritten);
1737
1738 if (NdisStatus != NDIS_STATUS_SUCCESS)
1739 {
1740 NDIS_DbgPrint(MIN_TRACE, ("Address OID (0x%X) failed. NdisStatus (0x%X).\n", AddressOID, NdisStatus));
1741 return NdisStatus;
1742 }
1743
1744 #if DBG
1745 {
1746 /* 802.3 only */
1747
1748 PUCHAR A = (PUCHAR)&Adapter->Address.Type.Medium802_3;
1749
1750 NDIS_DbgPrint(MAX_TRACE, ("Adapter address is (%02X %02X %02X %02X %02X %02X).\n", A[0], A[1], A[2], A[3], A[4], A[5]));
1751 }
1752 #endif /* DBG */
1753
1754 /* Get maximum lookahead buffer size of adapter */
1755 NdisStatus = MiniQueryInformation(Adapter, OID_GEN_MAXIMUM_LOOKAHEAD, sizeof(ULONG),
1756 &Adapter->NdisMiniportBlock.MaximumLookahead, &BytesWritten);
1757
1758 if (NdisStatus != NDIS_STATUS_SUCCESS)
1759 {
1760 NDIS_DbgPrint(MIN_TRACE, ("OID_GEN_MAXIMUM_LOOKAHEAD failed. NdisStatus (0x%X).\n", NdisStatus));
1761 return NdisStatus;
1762 }
1763
1764 NDIS_DbgPrint(DEBUG_MINIPORT, ("MaxLookaheadLength (0x%X).\n", Adapter->NdisMiniportBlock.MaximumLookahead));
1765
1766 /* Get current lookahead buffer size of adapter */
1767 NdisStatus = MiniQueryInformation(Adapter, OID_GEN_CURRENT_LOOKAHEAD, sizeof(ULONG),
1768 &Adapter->NdisMiniportBlock.CurrentLookahead, &BytesWritten);
1769
1770 if (NdisStatus != NDIS_STATUS_SUCCESS)
1771 {
1772 NDIS_DbgPrint(MIN_TRACE, ("OID_GEN_CURRENT_LOOKAHEAD failed. NdisStatus (0x%X).\n", NdisStatus));
1773 return NdisStatus;
1774 }
1775
1776 NdisStatus = MiniQueryInformation(Adapter, OID_GEN_MAXIMUM_SEND_PACKETS, sizeof(ULONG),
1777 &Adapter->NdisMiniportBlock.MaxSendPackets, &BytesWritten);
1778
1779 if (NdisStatus != NDIS_STATUS_SUCCESS)
1780 {
1781 NDIS_DbgPrint(MIN_TRACE, ("OID_GEN_MAXIMUM_SEND_PACKETS failed. NdisStatus (0x%X).\n", NdisStatus));
1782
1783 /* Set it to 1 if it fails because some drivers don't support this (?)*/
1784 Adapter->NdisMiniportBlock.MaxSendPackets = 1;
1785 }
1786
1787 NDIS_DbgPrint(DEBUG_MINIPORT, ("CurLookaheadLength (0x%X).\n", Adapter->NdisMiniportBlock.CurrentLookahead));
1788
1789 return STATUS_SUCCESS;
1790 }
1791
1792 NTSTATUS
1793 NTAPI
1794 NdisIForwardIrpAndWaitCompletionRoutine(
1795 PDEVICE_OBJECT Fdo,
1796 PIRP Irp,
1797 PVOID Context)
1798 {
1799 PKEVENT Event = Context;
1800
1801 if (Irp->PendingReturned)
1802 KeSetEvent(Event, IO_NO_INCREMENT, FALSE);
1803
1804 return STATUS_MORE_PROCESSING_REQUIRED;
1805 }
1806
1807 NTSTATUS
1808 NTAPI
1809 NdisIForwardIrpAndWait(PLOGICAL_ADAPTER Adapter, PIRP Irp)
1810 {
1811 KEVENT Event;
1812 NTSTATUS Status;
1813
1814 KeInitializeEvent(&Event, NotificationEvent, FALSE);
1815 IoCopyCurrentIrpStackLocationToNext(Irp);
1816 IoSetCompletionRoutine(Irp, NdisIForwardIrpAndWaitCompletionRoutine, &Event,
1817 TRUE, TRUE, TRUE);
1818 Status = IoCallDriver(Adapter->NdisMiniportBlock.NextDeviceObject, Irp);
1819 if (Status == STATUS_PENDING)
1820 {
1821 KeWaitForSingleObject(&Event, Executive, KernelMode, FALSE, NULL);
1822 Status = Irp->IoStatus.Status;
1823 }
1824 return Status;
1825 }
1826
1827 NTSTATUS
1828 NTAPI
1829 NdisICreateClose(
1830 IN PDEVICE_OBJECT DeviceObject,
1831 IN PIRP Irp)
1832 {
1833 Irp->IoStatus.Status = STATUS_SUCCESS;
1834 Irp->IoStatus.Information = 0;
1835
1836 IoCompleteRequest(Irp, IO_NO_INCREMENT);
1837
1838 return STATUS_SUCCESS;
1839 }
1840
1841 NTSTATUS
1842 NTAPI
1843 NdisIPnPStartDevice(
1844 IN PDEVICE_OBJECT DeviceObject,
1845 PIRP Irp)
1846 /*
1847 * FUNCTION: Handle the PnP start device event
1848 * ARGUMENTS:
1849 * DeviceObejct = Functional Device Object
1850 * Irp = IRP_MN_START_DEVICE I/O request packet
1851 * RETURNS:
1852 * Status of operation
1853 */
1854 {
1855 PIO_STACK_LOCATION Stack = IoGetCurrentIrpStackLocation(Irp);
1856 PLOGICAL_ADAPTER Adapter = (PLOGICAL_ADAPTER)DeviceObject->DeviceExtension;
1857 NDIS_WRAPPER_CONTEXT WrapperContext;
1858 NDIS_STATUS NdisStatus;
1859 NDIS_STATUS OpenErrorStatus;
1860 NTSTATUS Status;
1861 UINT SelectedMediumIndex = 0;
1862 NDIS_OID AddressOID;
1863 BOOLEAN Success = FALSE;
1864 ULONG ResourceCount;
1865 ULONG ResourceListSize;
1866 UNICODE_STRING ParamName;
1867 PNDIS_CONFIGURATION_PARAMETER ConfigParam;
1868 NDIS_HANDLE ConfigHandle;
1869 ULONG Size;
1870 LARGE_INTEGER Timeout;
1871 UINT MaxMulticastAddresses;
1872 ULONG BytesWritten;
1873 PLIST_ENTRY CurrentEntry;
1874 PPROTOCOL_BINDING ProtocolBinding;
1875
1876 /*
1877 * Prepare wrapper context used by HW and configuration routines.
1878 */
1879
1880 NDIS_DbgPrint(DEBUG_MINIPORT, ("Start Device %wZ\n", &Adapter->NdisMiniportBlock.MiniportName));
1881
1882 NDIS_DbgPrint(MAX_TRACE, ("Inserting adapter 0x%x into adapter list\n", Adapter));
1883
1884 /* Put adapter in global adapter list */
1885 ExInterlockedInsertTailList(&AdapterListHead, &Adapter->ListEntry, &AdapterListLock);
1886
1887 Status = IoOpenDeviceRegistryKey(
1888 Adapter->NdisMiniportBlock.PhysicalDeviceObject, PLUGPLAY_REGKEY_DRIVER,
1889 KEY_ALL_ACCESS, &WrapperContext.RegistryHandle);
1890 if (!NT_SUCCESS(Status))
1891 {
1892 NDIS_DbgPrint(MIN_TRACE,("failed to open adapter-specific reg key\n"));
1893 ExInterlockedRemoveEntryList( &Adapter->ListEntry, &AdapterListLock );
1894 return Status;
1895 }
1896
1897 NDIS_DbgPrint(MAX_TRACE, ("opened device reg key\n"));
1898
1899 WrapperContext.DeviceObject = Adapter->NdisMiniportBlock.DeviceObject;
1900
1901 /*
1902 * Store the adapter resources used by HW routines such as
1903 * NdisMQueryAdapterResources.
1904 */
1905
1906 if (Stack->Parameters.StartDevice.AllocatedResources != NULL)
1907 {
1908 ResourceCount = Stack->Parameters.StartDevice.AllocatedResources->List[0].
1909 PartialResourceList.Count;
1910 ResourceListSize =
1911 FIELD_OFFSET(CM_RESOURCE_LIST, List[0].PartialResourceList.
1912 PartialDescriptors[ResourceCount]);
1913
1914 Adapter->NdisMiniportBlock.AllocatedResources =
1915 ExAllocatePool(PagedPool, ResourceListSize);
1916 if (Adapter->NdisMiniportBlock.AllocatedResources == NULL)
1917 {
1918 NDIS_DbgPrint(MIN_TRACE, ("Insufficient resources\n"));
1919 ExInterlockedRemoveEntryList( &Adapter->ListEntry, &AdapterListLock );
1920 return STATUS_INSUFFICIENT_RESOURCES;
1921 }
1922
1923 Adapter->NdisMiniportBlock.Resources =
1924 ExAllocatePool(PagedPool, ResourceListSize);
1925 if (!Adapter->NdisMiniportBlock.Resources)
1926 {
1927 NDIS_DbgPrint(MIN_TRACE, ("Insufficient resources\n"));
1928 ExFreePool(Adapter->NdisMiniportBlock.AllocatedResources);
1929 ExInterlockedRemoveEntryList(&Adapter->ListEntry, &AdapterListLock);
1930 return STATUS_INSUFFICIENT_RESOURCES;
1931 }
1932
1933 RtlCopyMemory(Adapter->NdisMiniportBlock.Resources,
1934 Stack->Parameters.StartDevice.AllocatedResources,
1935 ResourceListSize);
1936
1937 RtlCopyMemory(Adapter->NdisMiniportBlock.AllocatedResources,
1938 Stack->Parameters.StartDevice.AllocatedResources,
1939 ResourceListSize);
1940 }
1941
1942 if (Stack->Parameters.StartDevice.AllocatedResourcesTranslated != NULL)
1943 {
1944 ResourceCount = Stack->Parameters.StartDevice.AllocatedResourcesTranslated->List[0].
1945 PartialResourceList.Count;
1946 ResourceListSize =
1947 FIELD_OFFSET(CM_RESOURCE_LIST, List[0].PartialResourceList.
1948 PartialDescriptors[ResourceCount]);
1949
1950 Adapter->NdisMiniportBlock.AllocatedResourcesTranslated =
1951 ExAllocatePool(PagedPool, ResourceListSize);
1952 if (Adapter->NdisMiniportBlock.AllocatedResourcesTranslated == NULL)
1953 {
1954 NDIS_DbgPrint(MIN_TRACE, ("Insufficient resources\n"));
1955 ExInterlockedRemoveEntryList( &Adapter->ListEntry, &AdapterListLock );
1956 return STATUS_INSUFFICIENT_RESOURCES;
1957 }
1958
1959 RtlCopyMemory(Adapter->NdisMiniportBlock.AllocatedResourcesTranslated,
1960 Stack->Parameters.StartDevice.AllocatedResourcesTranslated,
1961 ResourceListSize);
1962 }
1963
1964 /*
1965 * Store the Bus Type, Bus Number and Slot information. It's used by
1966 * the hardware routines then.
1967 */
1968
1969 NdisOpenConfiguration(&NdisStatus, &ConfigHandle, (NDIS_HANDLE)&WrapperContext);
1970 if (NdisStatus != NDIS_STATUS_SUCCESS)
1971 {
1972 NDIS_DbgPrint(MIN_TRACE, ("Failed to open configuration key\n"));
1973 ExInterlockedRemoveEntryList( &Adapter->ListEntry, &AdapterListLock );
1974 return NdisStatus;
1975 }
1976
1977 Size = sizeof(ULONG);
1978 Status = IoGetDeviceProperty(Adapter->NdisMiniportBlock.PhysicalDeviceObject,
1979 DevicePropertyLegacyBusType, Size,
1980 &Adapter->NdisMiniportBlock.BusType, &Size);
1981 if (!NT_SUCCESS(Status) || (INTERFACE_TYPE)Adapter->NdisMiniportBlock.BusType == InterfaceTypeUndefined)
1982 {
1983 NdisInitUnicodeString(&ParamName, L"BusType");
1984 NdisReadConfiguration(&NdisStatus, &ConfigParam, ConfigHandle,
1985 &ParamName, NdisParameterInteger);
1986 if (NdisStatus == NDIS_STATUS_SUCCESS)
1987 Adapter->NdisMiniportBlock.BusType = ConfigParam->ParameterData.IntegerData;
1988 else
1989 Adapter->NdisMiniportBlock.BusType = Isa;
1990 }
1991
1992 Status = IoGetDeviceProperty(Adapter->NdisMiniportBlock.PhysicalDeviceObject,
1993 DevicePropertyBusNumber, Size,
1994 &Adapter->NdisMiniportBlock.BusNumber, &Size);
1995 if (!NT_SUCCESS(Status) || Adapter->NdisMiniportBlock.BusNumber == 0xFFFFFFF0)
1996 {
1997 NdisInitUnicodeString(&ParamName, L"BusNumber");
1998 NdisReadConfiguration(&NdisStatus, &ConfigParam, ConfigHandle,
1999 &ParamName, NdisParameterInteger);
2000 if (NdisStatus == NDIS_STATUS_SUCCESS)
2001 Adapter->NdisMiniportBlock.BusNumber = ConfigParam->ParameterData.IntegerData;
2002 else
2003 Adapter->NdisMiniportBlock.BusNumber = 0;
2004 }
2005 WrapperContext.BusNumber = Adapter->NdisMiniportBlock.BusNumber;
2006
2007 Status = IoGetDeviceProperty(Adapter->NdisMiniportBlock.PhysicalDeviceObject,
2008 DevicePropertyAddress, Size,
2009 &Adapter->NdisMiniportBlock.SlotNumber, &Size);
2010 if (!NT_SUCCESS(Status) || Adapter->NdisMiniportBlock.SlotNumber == (NDIS_INTERFACE_TYPE)-1)
2011 {
2012 NdisInitUnicodeString(&ParamName, L"SlotNumber");
2013 NdisReadConfiguration(&NdisStatus, &ConfigParam, ConfigHandle,
2014 &ParamName, NdisParameterInteger);
2015 if (NdisStatus == NDIS_STATUS_SUCCESS)
2016 Adapter->NdisMiniportBlock.SlotNumber = ConfigParam->ParameterData.IntegerData;
2017 else
2018 Adapter->NdisMiniportBlock.SlotNumber = 0;
2019 }
2020 else
2021 {
2022 /* Convert slotnumber to PCI_SLOT_NUMBER */
2023 ULONG PciSlotNumber = Adapter->NdisMiniportBlock.SlotNumber;
2024 PCI_SLOT_NUMBER SlotNumber;
2025
2026 SlotNumber.u.AsULONG = 0;
2027 SlotNumber.u.bits.DeviceNumber = (PciSlotNumber >> 16) & 0xFFFF;
2028 SlotNumber.u.bits.FunctionNumber = PciSlotNumber & 0xFFFF;
2029
2030 Adapter->NdisMiniportBlock.SlotNumber = SlotNumber.u.AsULONG;
2031 }
2032 WrapperContext.SlotNumber = Adapter->NdisMiniportBlock.SlotNumber;
2033
2034 NdisCloseConfiguration(ConfigHandle);
2035
2036 /* Set handlers (some NDIS macros require these) */
2037 Adapter->NdisMiniportBlock.EthRxCompleteHandler = EthFilterDprIndicateReceiveComplete;
2038 Adapter->NdisMiniportBlock.EthRxIndicateHandler = EthFilterDprIndicateReceive;
2039 Adapter->NdisMiniportBlock.SendCompleteHandler = MiniSendComplete;
2040 Adapter->NdisMiniportBlock.SendResourcesHandler = MiniSendResourcesAvailable;
2041 Adapter->NdisMiniportBlock.ResetCompleteHandler = MiniResetComplete;
2042 Adapter->NdisMiniportBlock.TDCompleteHandler = MiniTransferDataComplete;
2043 Adapter->NdisMiniportBlock.PacketIndicateHandler= MiniIndicateReceivePacket;
2044 Adapter->NdisMiniportBlock.StatusHandler = MiniStatus;
2045 Adapter->NdisMiniportBlock.StatusCompleteHandler= MiniStatusComplete;
2046 Adapter->NdisMiniportBlock.SendPacketsHandler = ProSendPackets;
2047 Adapter->NdisMiniportBlock.QueryCompleteHandler = MiniRequestComplete;
2048 Adapter->NdisMiniportBlock.SetCompleteHandler = MiniRequestComplete;
2049
2050 /*
2051 * Call MiniportInitialize.
2052 */
2053
2054 NDIS_DbgPrint(MID_TRACE, ("calling MiniportInitialize\n"));
2055 NdisStatus = (*Adapter->NdisMiniportBlock.DriverHandle->MiniportCharacteristics.InitializeHandler)(
2056 &OpenErrorStatus, &SelectedMediumIndex, &MediaArray[0],
2057 MEDIA_ARRAY_SIZE, Adapter, (NDIS_HANDLE)&WrapperContext);
2058
2059 ZwClose(WrapperContext.RegistryHandle);
2060
2061 if (NdisStatus != NDIS_STATUS_SUCCESS)
2062 {
2063 NDIS_DbgPrint(MIN_TRACE, ("MiniportInitialize() failed for an adapter.\n"));
2064 ExInterlockedRemoveEntryList( &Adapter->ListEntry, &AdapterListLock );
2065 if (Adapter->NdisMiniportBlock.Interrupt)
2066 {
2067 KeBugCheckEx(BUGCODE_ID_DRIVER,
2068 (ULONG_PTR)Adapter,
2069 (ULONG_PTR)Adapter->NdisMiniportBlock.Interrupt,
2070 (ULONG_PTR)Adapter->NdisMiniportBlock.TimerQueue,
2071 1);
2072 }
2073 if (Adapter->NdisMiniportBlock.TimerQueue)
2074 {
2075 KeBugCheckEx(BUGCODE_ID_DRIVER,
2076 (ULONG_PTR)Adapter,
2077 (ULONG_PTR)Adapter->NdisMiniportBlock.Interrupt,
2078 (ULONG_PTR)Adapter->NdisMiniportBlock.TimerQueue,
2079 1);
2080 }
2081 return NdisStatus;
2082 }
2083
2084 if (SelectedMediumIndex >= MEDIA_ARRAY_SIZE)
2085 {
2086 NDIS_DbgPrint(MIN_TRACE, ("MiniportInitialize() selected a bad index\n"));
2087 ExInterlockedRemoveEntryList( &Adapter->ListEntry, &AdapterListLock );
2088 return NDIS_STATUS_UNSUPPORTED_MEDIA;
2089 }
2090
2091 Adapter->NdisMiniportBlock.MediaType = MediaArray[SelectedMediumIndex];
2092
2093 switch (Adapter->NdisMiniportBlock.MediaType)
2094 {
2095 case NdisMedium802_3:
2096 Adapter->MediumHeaderSize = 14; /* XXX figure out what to do about LLC */
2097 AddressOID = OID_802_3_CURRENT_ADDRESS;
2098 Adapter->AddressLength = ETH_LENGTH_OF_ADDRESS;
2099 NdisStatus = DoQueries(Adapter, AddressOID);
2100 if (NdisStatus == NDIS_STATUS_SUCCESS)
2101 {
2102 NdisStatus = MiniQueryInformation(Adapter, OID_802_3_MAXIMUM_LIST_SIZE, sizeof(UINT),
2103 &MaxMulticastAddresses, &BytesWritten);
2104
2105 if (NdisStatus != NDIS_STATUS_SUCCESS)
2106 {
2107 ExInterlockedRemoveEntryList( &Adapter->ListEntry, &AdapterListLock );
2108 NDIS_DbgPrint(MIN_TRACE, ("MiniQueryInformation failed (%x)\n", NdisStatus));
2109 return NdisStatus;
2110 }
2111
2112 Success = EthCreateFilter(MaxMulticastAddresses,
2113 Adapter->Address.Type.Medium802_3,
2114 &Adapter->NdisMiniportBlock.EthDB);
2115 if (Success)
2116 ((PETHI_FILTER)Adapter->NdisMiniportBlock.EthDB)->Miniport = (PNDIS_MINIPORT_BLOCK)Adapter;
2117 else
2118 NdisStatus = NDIS_STATUS_RESOURCES;
2119 }
2120 break;
2121
2122 default:
2123 /* FIXME: Support other types of media */
2124 NDIS_DbgPrint(MIN_TRACE, ("error: unsupported media\n"));
2125 ASSERT(FALSE);
2126 ExInterlockedRemoveEntryList( &Adapter->ListEntry, &AdapterListLock );
2127 return STATUS_UNSUCCESSFUL;
2128 }
2129
2130 if (NdisStatus != NDIS_STATUS_SUCCESS)
2131 {
2132 NDIS_DbgPrint(MIN_TRACE, ("couldn't create filter (%x)\n", NdisStatus));
2133 return NdisStatus;
2134 }
2135
2136 /* Check for a hang every two seconds if it wasn't set in MiniportInitialize */
2137 if (Adapter->NdisMiniportBlock.CheckForHangSeconds == 0)
2138 Adapter->NdisMiniportBlock.CheckForHangSeconds = 2;
2139
2140 Adapter->NdisMiniportBlock.OldPnPDeviceState = Adapter->NdisMiniportBlock.PnPDeviceState;
2141 Adapter->NdisMiniportBlock.PnPDeviceState = NdisPnPDeviceStarted;
2142
2143 IoSetDeviceInterfaceState(&Adapter->NdisMiniportBlock.SymbolicLinkName, TRUE);
2144
2145 Timeout.QuadPart = Int32x32To64(Adapter->NdisMiniportBlock.CheckForHangSeconds, -1000000);
2146 KeSetTimerEx(&Adapter->NdisMiniportBlock.WakeUpDpcTimer.Timer, Timeout,
2147 Adapter->NdisMiniportBlock.CheckForHangSeconds * 1000,
2148 &Adapter->NdisMiniportBlock.WakeUpDpcTimer.Dpc);
2149
2150 /* Put adapter in adapter list for this miniport */
2151 ExInterlockedInsertTailList(&Adapter->NdisMiniportBlock.DriverHandle->DeviceList, &Adapter->MiniportListEntry, &Adapter->NdisMiniportBlock.DriverHandle->Lock);
2152
2153 /* Refresh bindings for all protocols */
2154 CurrentEntry = ProtocolListHead.Flink;
2155 while (CurrentEntry != &ProtocolListHead)
2156 {
2157 ProtocolBinding = CONTAINING_RECORD(CurrentEntry, PROTOCOL_BINDING, ListEntry);
2158
2159 ndisBindMiniportsToProtocol(&NdisStatus, ProtocolBinding);
2160
2161 CurrentEntry = CurrentEntry->Flink;
2162 }
2163
2164 return STATUS_SUCCESS;
2165 }
2166
2167 NTSTATUS
2168 NTAPI
2169 NdisIPnPStopDevice(
2170 IN PDEVICE_OBJECT DeviceObject,
2171 PIRP Irp)
2172 /*
2173 * FUNCTION: Handle the PnP stop device event
2174 * ARGUMENTS:
2175 * DeviceObejct = Functional Device Object
2176 * Irp = IRP_MN_STOP_DEVICE I/O request packet
2177 * RETURNS:
2178 * Status of operation
2179 */
2180 {
2181 PLOGICAL_ADAPTER Adapter = (PLOGICAL_ADAPTER)DeviceObject->DeviceExtension;
2182
2183 /* Remove adapter from adapter list for this miniport */
2184 ExInterlockedRemoveEntryList(&Adapter->MiniportListEntry, &Adapter->NdisMiniportBlock.DriverHandle->Lock);
2185
2186 /* Remove adapter from global adapter list */
2187 ExInterlockedRemoveEntryList(&Adapter->ListEntry, &AdapterListLock);
2188
2189 KeCancelTimer(&Adapter->NdisMiniportBlock.WakeUpDpcTimer.Timer);
2190
2191 /* Set this here so MiniportISR will be forced to run for interrupts generated in MiniportHalt */
2192 Adapter->NdisMiniportBlock.OldPnPDeviceState = Adapter->NdisMiniportBlock.PnPDeviceState;
2193 Adapter->NdisMiniportBlock.PnPDeviceState = NdisPnPDeviceStopped;
2194
2195 (*Adapter->NdisMiniportBlock.DriverHandle->MiniportCharacteristics.HaltHandler)(Adapter);
2196
2197 IoSetDeviceInterfaceState(&Adapter->NdisMiniportBlock.SymbolicLinkName, FALSE);
2198
2199 if (Adapter->NdisMiniportBlock.AllocatedResources)
2200 {
2201 ExFreePool(Adapter->NdisMiniportBlock.AllocatedResources);
2202 Adapter->NdisMiniportBlock.AllocatedResources = NULL;
2203 }
2204 if (Adapter->NdisMiniportBlock.AllocatedResourcesTranslated)
2205 {
2206 ExFreePool(Adapter->NdisMiniportBlock.AllocatedResourcesTranslated);
2207 Adapter->NdisMiniportBlock.AllocatedResourcesTranslated = NULL;
2208 }
2209
2210 if (Adapter->NdisMiniportBlock.Resources)
2211 {
2212 ExFreePool(Adapter->NdisMiniportBlock.Resources);
2213 Adapter->NdisMiniportBlock.Resources = NULL;
2214 }
2215
2216 if (Adapter->NdisMiniportBlock.EthDB)
2217 {
2218 EthDeleteFilter(Adapter->NdisMiniportBlock.EthDB);
2219 Adapter->NdisMiniportBlock.EthDB = NULL;
2220 }
2221
2222 return STATUS_SUCCESS;
2223 }
2224
2225 NTSTATUS
2226 NTAPI
2227 NdisIShutdown(
2228 IN PDEVICE_OBJECT DeviceObject,
2229 PIRP Irp)
2230 {
2231 PLOGICAL_ADAPTER Adapter = DeviceObject->DeviceExtension;
2232 PMINIPORT_BUGCHECK_CONTEXT Context = Adapter->BugcheckContext;
2233 ADAPTER_SHUTDOWN_HANDLER ShutdownHandler = Context->ShutdownHandler;
2234
2235 ASSERT(ShutdownHandler);
2236
2237 ShutdownHandler(Context->DriverContext);
2238
2239 Irp->IoStatus.Status = STATUS_SUCCESS;
2240 Irp->IoStatus.Information = 0;
2241
2242 IoCompleteRequest(Irp, IO_NO_INCREMENT);
2243
2244 return STATUS_SUCCESS;
2245 }
2246
2247 NTSTATUS
2248 NTAPI
2249 NdisIDeviceIoControl(
2250 IN PDEVICE_OBJECT DeviceObject,
2251 PIRP Irp)
2252 {
2253 PLOGICAL_ADAPTER Adapter = (PLOGICAL_ADAPTER)DeviceObject->DeviceExtension;
2254 PIO_STACK_LOCATION Stack = IoGetCurrentIrpStackLocation(Irp);
2255 NDIS_STATUS Status = STATUS_NOT_SUPPORTED;
2256 ULONG Written;
2257
2258 Irp->IoStatus.Information = 0;
2259
2260 ASSERT(Adapter);
2261
2262 switch (Stack->Parameters.DeviceIoControl.IoControlCode)
2263 {
2264 case IOCTL_NDIS_QUERY_GLOBAL_STATS:
2265 Status = MiniQueryInformation(Adapter,
2266 *(PNDIS_OID)Irp->AssociatedIrp.SystemBuffer,
2267 Stack->Parameters.DeviceIoControl.OutputBufferLength,
2268 MmGetSystemAddressForMdl(Irp->MdlAddress),
2269 &Written);
2270 Irp->IoStatus.Information = Written;
2271 break;
2272
2273 default:
2274 ASSERT(FALSE);
2275 break;
2276 }
2277
2278 if (Status != NDIS_STATUS_PENDING)
2279 {
2280 Irp->IoStatus.Status = Status;
2281 IoCompleteRequest(Irp, IO_NO_INCREMENT);
2282 }
2283 else
2284 IoMarkIrpPending(Irp);
2285
2286 return Status;
2287 }
2288
2289 NTSTATUS
2290 NTAPI
2291 NdisIDispatchPnp(
2292 IN PDEVICE_OBJECT DeviceObject,
2293 PIRP Irp)
2294 {
2295 PIO_STACK_LOCATION Stack = IoGetCurrentIrpStackLocation(Irp);
2296 PLOGICAL_ADAPTER Adapter = (PLOGICAL_ADAPTER)DeviceObject->DeviceExtension;
2297 NTSTATUS Status;
2298
2299 switch (Stack->MinorFunction)
2300 {
2301 case IRP_MN_START_DEVICE:
2302 Status = NdisIForwardIrpAndWait(Adapter, Irp);
2303 if (NT_SUCCESS(Status) && NT_SUCCESS(Irp->IoStatus.Status))
2304 {
2305 Status = NdisIPnPStartDevice(DeviceObject, Irp);
2306 }
2307 else
2308 NDIS_DbgPrint(MIN_TRACE, ("Lower driver failed device start\n"));
2309 Irp->IoStatus.Status = Status;
2310 IoCompleteRequest(Irp, IO_NO_INCREMENT);
2311 return Status;
2312
2313 case IRP_MN_STOP_DEVICE:
2314 Status = NdisIPnPStopDevice(DeviceObject, Irp);
2315 if (!NT_SUCCESS(Status))
2316 NDIS_DbgPrint(MIN_TRACE, ("WARNING: Ignoring halt device failure! Passing the IRP down anyway\n"));
2317 Irp->IoStatus.Status = STATUS_SUCCESS;
2318 break;
2319
2320 case IRP_MN_QUERY_REMOVE_DEVICE:
2321 case IRP_MN_QUERY_STOP_DEVICE:
2322 Status = NdisIPnPQueryStopDevice(DeviceObject, Irp);
2323 Irp->IoStatus.Status = Status;
2324 if (Status != STATUS_SUCCESS)
2325 {
2326 IoCompleteRequest(Irp, IO_NO_INCREMENT);
2327 NDIS_DbgPrint(MIN_TRACE, ("Failing miniport halt request\n"));
2328 return Status;
2329 }
2330 break;
2331
2332 case IRP_MN_CANCEL_REMOVE_DEVICE:
2333 case IRP_MN_CANCEL_STOP_DEVICE:
2334 Status = NdisIForwardIrpAndWait(Adapter, Irp);
2335 if (NT_SUCCESS(Status) && NT_SUCCESS(Irp->IoStatus.Status))
2336 {
2337 Status = NdisIPnPCancelStopDevice(DeviceObject, Irp);
2338 }
2339 else
2340 {
2341 NDIS_DbgPrint(MIN_TRACE, ("Lower driver failed cancel stop/remove request\n"));
2342 }
2343 Irp->IoStatus.Status = Status;
2344 IoCompleteRequest(Irp, IO_NO_INCREMENT);
2345 return Status;
2346
2347 case IRP_MN_QUERY_PNP_DEVICE_STATE:
2348 Status = NDIS_STATUS_SUCCESS;
2349 Irp->IoStatus.Status = Status;
2350 Irp->IoStatus.Information |= Adapter->NdisMiniportBlock.PnPFlags;
2351 break;
2352
2353 default:
2354 break;
2355 }
2356
2357 IoSkipCurrentIrpStackLocation(Irp);
2358 return IoCallDriver(Adapter->NdisMiniportBlock.NextDeviceObject, Irp);
2359 }
2360
2361 NTSTATUS
2362 NTAPI
2363 NdisIAddDevice(
2364 IN PDRIVER_OBJECT DriverObject,
2365 IN PDEVICE_OBJECT PhysicalDeviceObject)
2366 /*
2367 * FUNCTION: Create a device for an adapter found using PnP
2368 * ARGUMENTS:
2369 * DriverObject = Pointer to the miniport driver object
2370 * PhysicalDeviceObject = Pointer to the PDO for our adapter
2371 */
2372 {
2373 static const WCHAR ClassKeyName[] = {'C','l','a','s','s','\\'};
2374 static const WCHAR LinkageKeyName[] = {'\\','L','i','n','k','a','g','e',0};
2375 PNDIS_M_DRIVER_BLOCK Miniport;
2376 PNDIS_M_DRIVER_BLOCK *MiniportPtr;
2377 WCHAR *LinkageKeyBuffer;
2378 ULONG DriverKeyLength;
2379 RTL_QUERY_REGISTRY_TABLE QueryTable[2];
2380 UNICODE_STRING ExportName;
2381 PDEVICE_OBJECT DeviceObject;
2382 PLOGICAL_ADAPTER Adapter;
2383 NTSTATUS Status;
2384
2385 /*
2386 * Gain the access to the miniport data structure first.
2387 */
2388
2389 MiniportPtr = IoGetDriverObjectExtension(DriverObject, (PVOID)'NMID');
2390 if (MiniportPtr == NULL)
2391 {
2392 NDIS_DbgPrint(MIN_TRACE, ("Can't get driver object extension.\n"));
2393 return NDIS_STATUS_FAILURE;
2394 }
2395 Miniport = *MiniportPtr;
2396
2397 /*
2398 * Get name of the Linkage registry key for our adapter. It's located under
2399 * the driver key for our driver and so we have basicly two ways to do it.
2400 * Either we can use IoOpenDriverRegistryKey or compose it using information
2401 * gathered by IoGetDeviceProperty. I choosed the second because
2402 * IoOpenDriverRegistryKey wasn't implemented at the time of writing.
2403 */
2404
2405 Status = IoGetDeviceProperty(PhysicalDeviceObject, DevicePropertyDriverKeyName,
2406 0, NULL, &DriverKeyLength);
2407 if (Status != STATUS_BUFFER_TOO_SMALL && Status != STATUS_BUFFER_OVERFLOW && Status != STATUS_SUCCESS)
2408 {
2409 NDIS_DbgPrint(MIN_TRACE, ("Can't get miniport driver key length.\n"));
2410 return Status;
2411 }
2412
2413 LinkageKeyBuffer = ExAllocatePool(PagedPool, DriverKeyLength +
2414 sizeof(ClassKeyName) + sizeof(LinkageKeyName));
2415 if (LinkageKeyBuffer == NULL)
2416 {
2417 NDIS_DbgPrint(MIN_TRACE, ("Can't allocate memory for driver key name.\n"));
2418 return STATUS_INSUFFICIENT_RESOURCES;
2419 }
2420
2421 Status = IoGetDeviceProperty(PhysicalDeviceObject, DevicePropertyDriverKeyName,
2422 DriverKeyLength, LinkageKeyBuffer +
2423 (sizeof(ClassKeyName) / sizeof(WCHAR)),
2424 &DriverKeyLength);
2425 if (!NT_SUCCESS(Status))
2426 {
2427 NDIS_DbgPrint(MIN_TRACE, ("Can't get miniport driver key.\n"));
2428 ExFreePool(LinkageKeyBuffer);
2429 return Status;
2430 }
2431
2432 /* Compose the linkage key name. */
2433 RtlCopyMemory(LinkageKeyBuffer, ClassKeyName, sizeof(ClassKeyName));
2434 RtlCopyMemory(LinkageKeyBuffer + ((sizeof(ClassKeyName) + DriverKeyLength) /
2435 sizeof(WCHAR)) - 1, LinkageKeyName, sizeof(LinkageKeyName));
2436
2437 NDIS_DbgPrint(DEBUG_MINIPORT, ("LinkageKey: %S.\n", LinkageKeyBuffer));
2438
2439 /*
2440 * Now open the linkage key and read the "Export" and "RootDevice" values
2441 * which contains device name and root service respectively.
2442 */
2443
2444 RtlZeroMemory(QueryTable, sizeof(QueryTable));
2445 RtlInitUnicodeString(&ExportName, NULL);
2446 QueryTable[0].Flags = RTL_QUERY_REGISTRY_REQUIRED | RTL_QUERY_REGISTRY_DIRECT;
2447 QueryTable[0].Name = L"Export";
2448 QueryTable[0].EntryContext = &ExportName;
2449
2450 Status = RtlQueryRegistryValues(RTL_REGISTRY_CONTROL, LinkageKeyBuffer,
2451 QueryTable, NULL, NULL);
2452 ExFreePool(LinkageKeyBuffer);
2453 if (!NT_SUCCESS(Status))
2454 {
2455 NDIS_DbgPrint(MIN_TRACE, ("Can't get miniport device name. (%x)\n", Status));
2456 return Status;
2457 }
2458
2459 /*
2460 * Create the device object.
2461 */
2462
2463 NDIS_DbgPrint(MAX_TRACE, ("creating device %wZ\n", &ExportName));
2464
2465 Status = IoCreateDevice(Miniport->DriverObject, sizeof(LOGICAL_ADAPTER),
2466 &ExportName, FILE_DEVICE_PHYSICAL_NETCARD,
2467 0, FALSE, &DeviceObject);
2468 if (!NT_SUCCESS(Status))
2469 {
2470 NDIS_DbgPrint(MIN_TRACE, ("Could not create device object.\n"));
2471 RtlFreeUnicodeString(&ExportName);
2472 return Status;
2473 }
2474
2475 /*
2476 * Initialize the adapter structure.
2477 */
2478
2479 Adapter = (PLOGICAL_ADAPTER)DeviceObject->DeviceExtension;
2480 KeInitializeSpinLock(&Adapter->NdisMiniportBlock.Lock);
2481 InitializeListHead(&Adapter->ProtocolListHead);
2482
2483 Status = IoRegisterDeviceInterface(PhysicalDeviceObject,
2484 &GUID_DEVINTERFACE_NET,
2485 NULL,
2486 &Adapter->NdisMiniportBlock.SymbolicLinkName);
2487
2488 if (!NT_SUCCESS(Status))
2489 {
2490 NDIS_DbgPrint(MIN_TRACE, ("Could not create device interface.\n"));
2491 IoDeleteDevice(DeviceObject);
2492 RtlFreeUnicodeString(&ExportName);
2493 return Status;
2494 }
2495
2496 Adapter->NdisMiniportBlock.DriverHandle = Miniport;
2497 Adapter->NdisMiniportBlock.MiniportName = ExportName;
2498 Adapter->NdisMiniportBlock.DeviceObject = DeviceObject;
2499 Adapter->NdisMiniportBlock.PhysicalDeviceObject = PhysicalDeviceObject;
2500 Adapter->NdisMiniportBlock.NextDeviceObject =
2501 IoAttachDeviceToDeviceStack(Adapter->NdisMiniportBlock.DeviceObject,
2502 PhysicalDeviceObject);
2503
2504 Adapter->NdisMiniportBlock.OldPnPDeviceState = 0;
2505 Adapter->NdisMiniportBlock.PnPDeviceState = NdisPnPDeviceAdded;
2506
2507 KeInitializeTimer(&Adapter->NdisMiniportBlock.WakeUpDpcTimer.Timer);
2508 KeInitializeDpc(&Adapter->NdisMiniportBlock.WakeUpDpcTimer.Dpc, MiniportHangDpc, Adapter);
2509
2510 DeviceObject->Flags &= ~DO_DEVICE_INITIALIZING;
2511
2512 return STATUS_SUCCESS;
2513 }
2514
2515 NTSTATUS
2516 NTAPI
2517 NdisGenericIrpHandler(
2518 IN PDEVICE_OBJECT DeviceObject,
2519 IN PIRP Irp)
2520 {
2521 PIO_STACK_LOCATION IrpSp = IoGetCurrentIrpStackLocation(Irp);
2522
2523 /* Use the characteristics to classify the device */
2524 if (DeviceObject->DeviceType == FILE_DEVICE_PHYSICAL_NETCARD)
2525 {
2526 if ((IrpSp->MajorFunction == IRP_MJ_CREATE) ||
2527 (IrpSp->MajorFunction == IRP_MJ_CLOSE))
2528 {
2529 return NdisICreateClose(DeviceObject, Irp);
2530 }
2531 else if (IrpSp->MajorFunction == IRP_MJ_PNP)
2532 {
2533 return NdisIDispatchPnp(DeviceObject, Irp);
2534 }
2535 else if (IrpSp->MajorFunction == IRP_MJ_SHUTDOWN)
2536 {
2537 return NdisIShutdown(DeviceObject, Irp);
2538 }
2539 else if (IrpSp->MajorFunction == IRP_MJ_DEVICE_CONTROL)
2540 {
2541 return NdisIDeviceIoControl(DeviceObject, Irp);
2542 }
2543 }
2544 else if (DeviceObject->DeviceType == FILE_DEVICE_NETWORK)
2545 {
2546 PNDIS_M_DEVICE_BLOCK DeviceBlock = DeviceObject->DeviceExtension;
2547
2548 ASSERT(DeviceBlock->DeviceObject == DeviceObject);
2549
2550 if (DeviceBlock->MajorFunction[IrpSp->MajorFunction] != NULL)
2551 {
2552 return DeviceBlock->MajorFunction[IrpSp->MajorFunction](DeviceObject, Irp);
2553 }
2554 }
2555 else
2556 {
2557 ASSERT(FALSE);
2558 }
2559
2560 Irp->IoStatus.Status = STATUS_INVALID_DEVICE_REQUEST;
2561 Irp->IoStatus.Information = 0;
2562
2563 IoCompleteRequest(Irp, IO_NO_INCREMENT);
2564
2565 return STATUS_INVALID_DEVICE_REQUEST;
2566 }
2567
2568 /*
2569 * @implemented
2570 */
2571 NDIS_STATUS
2572 EXPORT
2573 NdisMRegisterMiniport(
2574 IN NDIS_HANDLE NdisWrapperHandle,
2575 IN PNDIS_MINIPORT_CHARACTERISTICS MiniportCharacteristics,
2576 IN UINT CharacteristicsLength)
2577 /*
2578 * FUNCTION: Registers a miniport's MiniportXxx entry points with the NDIS library
2579 * ARGUMENTS:
2580 * NdisWrapperHandle = Pointer to handle returned by NdisMInitializeWrapper
2581 * MiniportCharacteristics = Pointer to a buffer with miniport characteristics
2582 * CharacteristicsLength = Number of bytes in characteristics buffer
2583 * RETURNS:
2584 * Status of operation
2585 */
2586 {
2587 UINT MinSize;
2588 PNDIS_M_DRIVER_BLOCK Miniport = GET_MINIPORT_DRIVER(NdisWrapperHandle);
2589 PNDIS_M_DRIVER_BLOCK *MiniportPtr;
2590 NTSTATUS Status;
2591 ULONG i;
2592
2593 NDIS_DbgPrint(MAX_TRACE, ("Called.\n"));
2594
2595 switch (MiniportCharacteristics->MajorNdisVersion)
2596 {
2597 case 0x03:
2598 MinSize = sizeof(NDIS30_MINIPORT_CHARACTERISTICS);
2599 break;
2600
2601 case 0x04:
2602 MinSize = sizeof(NDIS40_MINIPORT_CHARACTERISTICS);
2603 break;
2604
2605 case 0x05:
2606 switch (MiniportCharacteristics->MinorNdisVersion)
2607 {
2608 case 0x00:
2609 MinSize = sizeof(NDIS50_MINIPORT_CHARACTERISTICS);
2610 break;
2611
2612 case 0x01:
2613 MinSize = sizeof(NDIS51_MINIPORT_CHARACTERISTICS);
2614 break;
2615
2616 default:
2617 NDIS_DbgPrint(MIN_TRACE, ("Bad 5.x minor characteristics version.\n"));
2618 return NDIS_STATUS_BAD_VERSION;
2619 }
2620 break;
2621
2622 default:
2623 NDIS_DbgPrint(MIN_TRACE, ("Bad miniport characteristics version.\n"));
2624 return NDIS_STATUS_BAD_VERSION;
2625 }
2626
2627 NDIS_DbgPrint(MIN_TRACE, ("Initializing an NDIS %u.%u miniport\n",
2628 MiniportCharacteristics->MajorNdisVersion,
2629 MiniportCharacteristics->MinorNdisVersion));
2630
2631 if (CharacteristicsLength < MinSize)
2632 {
2633 NDIS_DbgPrint(MIN_TRACE, ("Bad miniport characteristics length.\n"));
2634 return NDIS_STATUS_BAD_CHARACTERISTICS;
2635 }
2636
2637 /* Check if mandatory MiniportXxx functions are specified */
2638 if ((!MiniportCharacteristics->HaltHandler) ||
2639 (!MiniportCharacteristics->InitializeHandler)||
2640 (!MiniportCharacteristics->ResetHandler))
2641 {
2642 NDIS_DbgPrint(MIN_TRACE, ("Bad miniport characteristics.\n"));
2643 return NDIS_STATUS_BAD_CHARACTERISTICS;
2644 }
2645
2646 if (MiniportCharacteristics->MajorNdisVersion < 0x05)
2647 {
2648 if ((!MiniportCharacteristics->QueryInformationHandler) ||
2649 (!MiniportCharacteristics->SetInformationHandler))
2650 {
2651 NDIS_DbgPrint(MIN_TRACE, ("Bad miniport characteristics. (Set/Query)\n"));
2652 return NDIS_STATUS_BAD_CHARACTERISTICS;
2653 }
2654 }
2655 else
2656 {
2657 if (((!MiniportCharacteristics->QueryInformationHandler) ||
2658 (!MiniportCharacteristics->SetInformationHandler)) &&
2659 (!MiniportCharacteristics->CoRequestHandler))
2660 {
2661 NDIS_DbgPrint(MIN_TRACE, ("Bad miniport characteristics. (Set/Query)\n"));
2662 return NDIS_STATUS_BAD_CHARACTERISTICS;
2663 }
2664 }
2665
2666 if (MiniportCharacteristics->MajorNdisVersion == 0x03)
2667 {
2668 if (!MiniportCharacteristics->SendHandler)
2669 {
2670 NDIS_DbgPrint(MIN_TRACE, ("Bad miniport characteristics. (NDIS 3.0)\n"));
2671 return NDIS_STATUS_BAD_CHARACTERISTICS;
2672 }
2673 }
2674 else if (MiniportCharacteristics->MajorNdisVersion == 0x04)
2675 {
2676 /* NDIS 4.0 */
2677 if ((!MiniportCharacteristics->SendHandler) &&
2678 (!MiniportCharacteristics->SendPacketsHandler))
2679 {
2680 NDIS_DbgPrint(MIN_TRACE, ("Bad miniport characteristics. (NDIS 4.0)\n"));
2681 return NDIS_STATUS_BAD_CHARACTERISTICS;
2682 }
2683 }
2684 else if (MiniportCharacteristics->MajorNdisVersion == 0x05)
2685 {
2686 /* TODO: Add more checks here */
2687
2688 if ((!MiniportCharacteristics->SendHandler) &&
2689 (!MiniportCharacteristics->SendPacketsHandler) &&
2690 (!MiniportCharacteristics->CoSendPacketsHandler))
2691 {
2692 NDIS_DbgPrint(MIN_TRACE, ("Bad miniport characteristics. (NDIS 5.0)\n"));
2693 return NDIS_STATUS_BAD_CHARACTERISTICS;
2694 }
2695 }
2696
2697 RtlCopyMemory(&Miniport->MiniportCharacteristics, MiniportCharacteristics, MinSize);
2698
2699 /*
2700 * NOTE: This is VERY unoptimal! Should we store the NDIS_M_DRIVER_BLOCK
2701 * structure in the driver extension or what?
2702 */
2703
2704 Status = IoAllocateDriverObjectExtension(Miniport->DriverObject, (PVOID)'NMID',
2705 sizeof(PNDIS_M_DRIVER_BLOCK), (PVOID*)&MiniportPtr);
2706 if (!NT_SUCCESS(Status))
2707 {
2708 NDIS_DbgPrint(MIN_TRACE, ("Can't allocate driver object extension.\n"));
2709 return NDIS_STATUS_RESOURCES;
2710 }
2711
2712 *MiniportPtr = Miniport;
2713
2714 /* We have to register for all of these so handler registered in NdisMRegisterDevice work */
2715 for (i = 0; i <= IRP_MJ_MAXIMUM_FUNCTION; i++)
2716 {
2717 Miniport->DriverObject->MajorFunction[i] = NdisGenericIrpHandler;
2718 }
2719
2720 Miniport->DriverObject->DriverExtension->AddDevice = NdisIAddDevice;
2721
2722 return NDIS_STATUS_SUCCESS;
2723 }
2724
2725 /*
2726 * @implemented
2727 */
2728 #undef NdisMResetComplete
2729 VOID
2730 EXPORT
2731 NdisMResetComplete(
2732 IN NDIS_HANDLE MiniportAdapterHandle,
2733 IN NDIS_STATUS Status,
2734 IN BOOLEAN AddressingReset)
2735 {
2736 MiniResetComplete(MiniportAdapterHandle, Status, AddressingReset);
2737 }
2738
2739 /*
2740 * @implemented
2741 */
2742 #undef NdisMSendComplete
2743 VOID
2744 EXPORT
2745 NdisMSendComplete(
2746 IN NDIS_HANDLE MiniportAdapterHandle,
2747 IN PNDIS_PACKET Packet,
2748 IN NDIS_STATUS Status)
2749 /*
2750 * FUNCTION: Forwards a message to the initiating protocol saying
2751 * that a packet was handled
2752 * ARGUMENTS:
2753 * NdisAdapterHandle = Handle input to MiniportInitialize
2754 * Packet = Pointer to NDIS packet that was sent
2755 * Status = Status of send operation
2756 */
2757 {
2758 MiniSendComplete(MiniportAdapterHandle, Packet, Status);
2759 }
2760
2761 /*
2762 * @implemented
2763 */
2764 #undef NdisMSendResourcesAvailable
2765 VOID
2766 EXPORT
2767 NdisMSendResourcesAvailable(
2768 IN NDIS_HANDLE MiniportAdapterHandle)
2769 {
2770 MiniSendResourcesAvailable(MiniportAdapterHandle);
2771 }
2772
2773 /*
2774 * @implemented
2775 */
2776 #undef NdisMTransferDataComplete
2777 VOID
2778 EXPORT
2779 NdisMTransferDataComplete(
2780 IN NDIS_HANDLE MiniportAdapterHandle,
2781 IN PNDIS_PACKET Packet,
2782 IN NDIS_STATUS Status,
2783 IN UINT BytesTransferred)
2784 {
2785 MiniTransferDataComplete(MiniportAdapterHandle, Packet, Status, BytesTransferred);
2786 }
2787
2788 /*
2789 * @implemented
2790 */
2791 #undef NdisMSetAttributes
2792 VOID
2793 EXPORT
2794 NdisMSetAttributes(
2795 IN NDIS_HANDLE MiniportAdapterHandle,
2796 IN NDIS_HANDLE MiniportAdapterContext,
2797 IN BOOLEAN BusMaster,
2798 IN NDIS_INTERFACE_TYPE AdapterType)
2799 /*
2800 * FUNCTION: Informs the NDIS library of significant features of the caller's NIC
2801 * ARGUMENTS:
2802 * MiniportAdapterHandle = Handle input to MiniportInitialize
2803 * MiniportAdapterContext = Pointer to context information
2804 * BusMaster = Specifies TRUE if the caller's NIC is a busmaster DMA device
2805 * AdapterType = Specifies the I/O bus interface of the caller's NIC
2806 */
2807 {
2808 NDIS_DbgPrint(MAX_TRACE, ("Called.\n"));
2809 NdisMSetAttributesEx(MiniportAdapterHandle, MiniportAdapterContext, 0,
2810 BusMaster ? NDIS_ATTRIBUTE_BUS_MASTER : 0,
2811 AdapterType);
2812 }
2813
2814 /*
2815 * @implemented
2816 */
2817 VOID
2818 EXPORT
2819 NdisMSetAttributesEx(
2820 IN NDIS_HANDLE MiniportAdapterHandle,
2821 IN NDIS_HANDLE MiniportAdapterContext,
2822 IN UINT CheckForHangTimeInSeconds OPTIONAL,
2823 IN ULONG AttributeFlags,
2824 IN NDIS_INTERFACE_TYPE AdapterType)
2825 /*
2826 * FUNCTION: Informs the NDIS library of significant features of the caller's NIC
2827 * ARGUMENTS:
2828 * MiniportAdapterHandle = Handle input to MiniportInitialize
2829 * MiniportAdapterContext = Pointer to context information
2830 * CheckForHangTimeInSeconds = Specifies interval in seconds at which
2831 * MiniportCheckForHang should be called
2832 * AttributeFlags = Bitmask that indicates specific attributes
2833 * AdapterType = Specifies the I/O bus interface of the caller's NIC
2834 */
2835 {
2836 PLOGICAL_ADAPTER Adapter = GET_LOGICAL_ADAPTER(MiniportAdapterHandle);
2837
2838 NDIS_DbgPrint(MAX_TRACE, ("Called.\n"));
2839
2840 Adapter->NdisMiniportBlock.MiniportAdapterContext = MiniportAdapterContext;
2841 Adapter->NdisMiniportBlock.Flags = AttributeFlags;
2842 Adapter->NdisMiniportBlock.AdapterType = AdapterType;
2843 if (CheckForHangTimeInSeconds > 0)
2844 Adapter->NdisMiniportBlock.CheckForHangSeconds = CheckForHangTimeInSeconds;
2845 if (AttributeFlags & NDIS_ATTRIBUTE_INTERMEDIATE_DRIVER)
2846 NDIS_DbgPrint(MIN_TRACE, ("Intermediate drivers not supported yet.\n"));
2847
2848 NDIS_DbgPrint(MIN_TRACE, ("Miniport attribute flags: 0x%x\n", AttributeFlags));
2849
2850 if (Adapter->NdisMiniportBlock.DriverHandle->MiniportCharacteristics.AdapterShutdownHandler)
2851 {
2852 NDIS_DbgPrint(MAX_TRACE, ("Miniport set AdapterShutdownHandler in MiniportCharacteristics\n"));
2853 NdisMRegisterAdapterShutdownHandler(Adapter,
2854 Adapter->NdisMiniportBlock.MiniportAdapterContext,
2855 Adapter->NdisMiniportBlock.DriverHandle->MiniportCharacteristics.AdapterShutdownHandler);
2856 }
2857 }
2858
2859 /*
2860 * @implemented
2861 */
2862 VOID
2863 EXPORT
2864 NdisMSleep(
2865 IN ULONG MicrosecondsToSleep)
2866 /*
2867 * FUNCTION: delay the thread's execution for MicrosecondsToSleep
2868 * ARGUMENTS:
2869 * MicrosecondsToSleep: duh...
2870 * NOTES:
2871 * - Because this is a blocking call, current IRQL must be < DISPATCH_LEVEL
2872 */
2873 {
2874 KTIMER Timer;
2875 LARGE_INTEGER DueTime;
2876
2877 PAGED_CODE();
2878
2879 DueTime.QuadPart = (-1) * 10 * MicrosecondsToSleep;
2880
2881 KeInitializeTimer(&Timer);
2882 KeSetTimer(&Timer, DueTime, 0);
2883 KeWaitForSingleObject(&Timer, Executive, KernelMode, FALSE, 0);
2884 }
2885
2886 /*
2887 * @implemented
2888 */
2889 BOOLEAN
2890 EXPORT
2891 NdisMSynchronizeWithInterrupt(
2892 IN PNDIS_MINIPORT_INTERRUPT Interrupt,
2893 IN PVOID SynchronizeFunction,
2894 IN PVOID SynchronizeContext)
2895 {
2896 return(KeSynchronizeExecution(Interrupt->InterruptObject,
2897 (PKSYNCHRONIZE_ROUTINE)SynchronizeFunction,
2898 SynchronizeContext));
2899 }
2900
2901 /*
2902 * @unimplemented
2903 */
2904 NDIS_STATUS
2905 EXPORT
2906 NdisMWriteLogData(
2907 IN NDIS_HANDLE LogHandle,
2908 IN PVOID LogBuffer,
2909 IN UINT LogBufferSize)
2910 {
2911 PUCHAR Buffer = LogBuffer;
2912 UINT i, j, idx;
2913
2914 UNIMPLEMENTED;
2915 for (i = 0; i < LogBufferSize; i += 16)
2916 {
2917 DbgPrint("%08x |", i);
2918 for (j = 0; j < 16; j++)
2919 {
2920 idx = i + j;
2921 if (idx < LogBufferSize)
2922 DbgPrint(" %02x", Buffer[idx]);
2923 else
2924 DbgPrint(" ");
2925 }
2926 DbgPrint(" | ");
2927 for (j = 0; j < 16; j++)
2928 {
2929 idx = i + j;
2930 if (idx == LogBufferSize)
2931 break;
2932 if (Buffer[idx] >= ' ') /* FIXME: not portable! replace by if (isprint(Buffer[idx])) ? */
2933 DbgPrint("%c", Buffer[idx]);
2934 else
2935 DbgPrint(".");
2936 }
2937 DbgPrint("\n");
2938 }
2939
2940 return NDIS_STATUS_FAILURE;
2941 }
2942
2943 /*
2944 * @implemented
2945 */
2946 VOID
2947 EXPORT
2948 NdisTerminateWrapper(
2949 IN NDIS_HANDLE NdisWrapperHandle,
2950 IN PVOID SystemSpecific)
2951 /*
2952 * FUNCTION: Releases resources allocated by a call to NdisInitializeWrapper
2953 * ARGUMENTS:
2954 * NdisWrapperHandle = Handle returned by NdisInitializeWrapper (NDIS_M_DRIVER_BLOCK)
2955 * SystemSpecific = Always NULL
2956 */
2957 {
2958 PNDIS_M_DRIVER_BLOCK Miniport = GET_MINIPORT_DRIVER(NdisWrapperHandle);
2959
2960 NDIS_DbgPrint(MAX_TRACE, ("Called.\n"));
2961
2962 ExFreePool(Miniport->RegistryPath->Buffer);
2963 ExFreePool(Miniport->RegistryPath);
2964 ExInterlockedRemoveEntryList(&Miniport->ListEntry, &MiniportListLock);
2965 ExFreePool(Miniport);
2966 }
2967
2968
2969 /*
2970 * @implemented
2971 */
2972 NDIS_STATUS
2973 EXPORT
2974 NdisMQueryAdapterInstanceName(
2975 OUT PNDIS_STRING AdapterInstanceName,
2976 IN NDIS_HANDLE MiniportAdapterHandle)
2977 /*
2978 * FUNCTION:
2979 * ARGUMENTS:
2980 * NOTES:
2981 * NDIS 5.0
2982 */
2983 {
2984 PLOGICAL_ADAPTER Adapter = (PLOGICAL_ADAPTER)MiniportAdapterHandle;
2985 UNICODE_STRING AdapterName;
2986
2987 NDIS_DbgPrint(MAX_TRACE, ("Called.\n"));
2988
2989 AdapterName.Length = 0;
2990 AdapterName.MaximumLength = Adapter->NdisMiniportBlock.MiniportName.MaximumLength;
2991 AdapterName.Buffer = ExAllocatePool(PagedPool, AdapterName.MaximumLength);
2992 if (!AdapterName.Buffer) {
2993 NDIS_DbgPrint(MIN_TRACE, ("Insufficient resources\n"));
2994 return NDIS_STATUS_RESOURCES;
2995 }
2996
2997 RtlCopyUnicodeString(&AdapterName, &Adapter->NdisMiniportBlock.MiniportName);
2998
2999 *AdapterInstanceName = AdapterName;
3000
3001 return NDIS_STATUS_SUCCESS;
3002 }
3003
3004 /*
3005 * @implemented
3006 */
3007 VOID
3008 EXPORT
3009 NdisDeregisterAdapterShutdownHandler(
3010 IN NDIS_HANDLE NdisAdapterHandle)
3011 /*
3012 * FUNCTION:
3013 * ARGUMENTS:
3014 * NOTES:
3015 * NDIS 4.0
3016 */
3017 {
3018 NdisMDeregisterAdapterShutdownHandler(NdisAdapterHandle);
3019 }
3020
3021
3022 /*
3023 * @implemented
3024 */
3025 VOID
3026 EXPORT
3027 NdisRegisterAdapterShutdownHandler(
3028 IN NDIS_HANDLE NdisAdapterHandle,
3029 IN PVOID ShutdownContext,
3030 IN ADAPTER_SHUTDOWN_HANDLER ShutdownHandler)
3031 /*
3032 * FUNCTION:
3033 * ARGUMENTS:
3034 * NOTES:
3035 * NDIS 4.0
3036 */
3037 {
3038 NdisMRegisterAdapterShutdownHandler(NdisAdapterHandle,
3039 ShutdownContext,
3040 ShutdownHandler);
3041 }
3042
3043 /*
3044 * @implemented
3045 */
3046 VOID
3047 EXPORT
3048 NdisMGetDeviceProperty(
3049 IN NDIS_HANDLE MiniportAdapterHandle,
3050 IN OUT PDEVICE_OBJECT *PhysicalDeviceObject OPTIONAL,
3051 IN OUT PDEVICE_OBJECT *FunctionalDeviceObject OPTIONAL,
3052 IN OUT PDEVICE_OBJECT *NextDeviceObject OPTIONAL,
3053 IN OUT PCM_RESOURCE_LIST *AllocatedResources OPTIONAL,
3054 IN OUT PCM_RESOURCE_LIST *AllocatedResourcesTranslated OPTIONAL)
3055 /*
3056 * FUNCTION:
3057 * ARGUMENTS:
3058 * NOTES:
3059 * NDIS 5.0
3060 */
3061 {
3062 PLOGICAL_ADAPTER Adapter = MiniportAdapterHandle;
3063
3064 NDIS_DbgPrint(MAX_TRACE, ("Called\n"));
3065
3066 if (PhysicalDeviceObject != NULL)
3067 *PhysicalDeviceObject = Adapter->NdisMiniportBlock.PhysicalDeviceObject;
3068
3069 if (FunctionalDeviceObject != NULL)
3070 *FunctionalDeviceObject = Adapter->NdisMiniportBlock.DeviceObject;
3071
3072 if (NextDeviceObject != NULL)
3073 *NextDeviceObject = Adapter->NdisMiniportBlock.NextDeviceObject;
3074
3075 if (AllocatedResources != NULL)
3076 *AllocatedResources = Adapter->NdisMiniportBlock.AllocatedResources;
3077
3078 if (AllocatedResourcesTranslated != NULL)
3079 *AllocatedResourcesTranslated = Adapter->NdisMiniportBlock.AllocatedResourcesTranslated;
3080 }
3081
3082 /*
3083 * @implemented
3084 */
3085 VOID
3086 EXPORT
3087 NdisMRegisterUnloadHandler(
3088 IN NDIS_HANDLE NdisWrapperHandle,
3089 IN PDRIVER_UNLOAD UnloadHandler)
3090 /*
3091 * FUNCTION:
3092 * ARGUMENTS:
3093 * NOTES:
3094 * NDIS 5.0
3095 */
3096 {
3097 PNDIS_M_DRIVER_BLOCK DriverBlock = NdisWrapperHandle;
3098
3099 NDIS_DbgPrint(MAX_TRACE, ("Miniport registered unload handler\n"));
3100
3101 DriverBlock->DriverObject->DriverUnload = UnloadHandler;
3102 }
3103
3104 /*
3105 * @implemented
3106 */
3107 NDIS_STATUS
3108 EXPORT
3109 NdisMRegisterDevice(
3110 IN NDIS_HANDLE NdisWrapperHandle,
3111 IN PNDIS_STRING DeviceName,
3112 IN PNDIS_STRING SymbolicName,
3113 IN PDRIVER_DISPATCH MajorFunctions[],
3114 OUT PDEVICE_OBJECT *pDeviceObject,
3115 OUT NDIS_HANDLE *NdisDeviceHandle)
3116 /*
3117 * FUNCTION:
3118 * ARGUMENTS:
3119 * NOTES:
3120 * NDIS 5.0
3121 */
3122 {
3123 PNDIS_M_DRIVER_BLOCK DriverBlock = NdisWrapperHandle;
3124 PNDIS_M_DEVICE_BLOCK DeviceBlock;
3125 PDEVICE_OBJECT DeviceObject;
3126 NDIS_STATUS Status;
3127 UINT i;
3128
3129 NDIS_DbgPrint(MAX_TRACE, ("Called\n"));
3130
3131 Status = IoCreateDevice(DriverBlock->DriverObject,
3132 sizeof(NDIS_M_DEVICE_BLOCK),
3133 DeviceName,
3134 FILE_DEVICE_NETWORK,
3135 0,
3136 FALSE,
3137 &DeviceObject);
3138
3139 if (!NT_SUCCESS(Status))
3140 {
3141 NDIS_DbgPrint(MIN_TRACE, ("IoCreateDevice failed (%x)\n", Status));
3142 return Status;
3143 }
3144
3145 Status = IoCreateSymbolicLink(SymbolicName, DeviceName);
3146
3147 if (!NT_SUCCESS(Status))
3148 {
3149 NDIS_DbgPrint(MIN_TRACE, ("IoCreateSymbolicLink failed (%x)\n", Status));
3150 IoDeleteDevice(DeviceObject);
3151 return Status;
3152 }
3153
3154 DeviceBlock = DeviceObject->DeviceExtension;
3155
3156 if (!DeviceBlock)
3157 {
3158 NDIS_DbgPrint(MIN_TRACE, ("Insufficient resources\n"));
3159 IoDeleteDevice(DeviceObject);
3160 IoDeleteSymbolicLink(SymbolicName);
3161 return NDIS_STATUS_RESOURCES;
3162 }
3163
3164 for (i = 0; i <= IRP_MJ_MAXIMUM_FUNCTION; i++)
3165 DeviceBlock->MajorFunction[i] = MajorFunctions[i];
3166
3167 DeviceBlock->DeviceObject = DeviceObject;
3168 DeviceBlock->SymbolicName = SymbolicName;
3169
3170 *pDeviceObject = DeviceObject;
3171 *NdisDeviceHandle = DeviceBlock;
3172
3173 return NDIS_STATUS_SUCCESS;
3174 }
3175
3176 /*
3177 * @implemented
3178 */
3179 NDIS_STATUS
3180 EXPORT
3181 NdisMDeregisterDevice(
3182 IN NDIS_HANDLE NdisDeviceHandle)
3183 /*
3184 * FUNCTION:
3185 * ARGUMENTS:
3186 * NOTES:
3187 * NDIS 5.0
3188 */
3189 {
3190 PNDIS_M_DEVICE_BLOCK DeviceBlock = NdisDeviceHandle;
3191
3192 IoDeleteDevice(DeviceBlock->DeviceObject);
3193
3194 IoDeleteSymbolicLink(DeviceBlock->SymbolicName);
3195
3196 return NDIS_STATUS_SUCCESS;
3197 }
3198
3199 /*
3200 * @implemented
3201 */
3202 NDIS_STATUS
3203 EXPORT
3204 NdisQueryAdapterInstanceName(
3205 OUT PNDIS_STRING AdapterInstanceName,
3206 IN NDIS_HANDLE NdisBindingHandle)
3207 /*
3208 * FUNCTION:
3209 * ARGUMENTS:
3210 * NOTES:
3211 * NDIS 5.0
3212 */
3213 {
3214 PADAPTER_BINDING AdapterBinding = NdisBindingHandle;
3215 PLOGICAL_ADAPTER Adapter = AdapterBinding->Adapter;
3216
3217 return NdisMQueryAdapterInstanceName(AdapterInstanceName,
3218 Adapter);
3219 }
3220
3221 /*
3222 * @implemented
3223 */
3224 VOID
3225 EXPORT
3226 NdisCompletePnPEvent(
3227 IN NDIS_STATUS Status,
3228 IN NDIS_HANDLE NdisBindingHandle,
3229 IN PNET_PNP_EVENT NetPnPEvent)
3230 /*
3231 * FUNCTION:
3232 * ARGUMENTS:
3233 * NOTES:
3234 * NDIS 5.0
3235 */
3236 {
3237 PIRP Irp = (PIRP)NetPnPEvent->NdisReserved[0];
3238 PLIST_ENTRY CurrentEntry = (PLIST_ENTRY)NetPnPEvent->NdisReserved[1];
3239 PADAPTER_BINDING AdapterBinding = NdisBindingHandle;
3240 PLOGICAL_ADAPTER Adapter = AdapterBinding->Adapter;
3241 NDIS_STATUS NdisStatus;
3242
3243 if (Status != NDIS_STATUS_SUCCESS)
3244 {
3245 if (NetPnPEvent->Buffer) ExFreePool(NetPnPEvent->Buffer);
3246 ExFreePool(NetPnPEvent);
3247 Irp->IoStatus.Status = Status;
3248 IoCompleteRequest(Irp, IO_NO_INCREMENT);
3249 return;
3250 }
3251
3252 while (CurrentEntry != &Adapter->ProtocolListHead)
3253 {
3254 AdapterBinding = CONTAINING_RECORD(CurrentEntry, ADAPTER_BINDING, AdapterListEntry);
3255
3256 NdisStatus = (*AdapterBinding->ProtocolBinding->Chars.PnPEventHandler)(
3257 AdapterBinding->NdisOpenBlock.ProtocolBindingContext,
3258 NetPnPEvent);
3259
3260 if (NdisStatus == NDIS_STATUS_PENDING)
3261 {
3262 NetPnPEvent->NdisReserved[1] = (ULONG_PTR)CurrentEntry->Flink;
3263 return;
3264 }
3265 else if (NdisStatus != NDIS_STATUS_SUCCESS)
3266 {
3267 if (NetPnPEvent->Buffer) ExFreePool(NetPnPEvent->Buffer);
3268 ExFreePool(NetPnPEvent);
3269 Irp->IoStatus.Status = NdisStatus;
3270 IoCompleteRequest(Irp, IO_NO_INCREMENT);
3271 return;
3272 }
3273
3274 CurrentEntry = CurrentEntry->Flink;
3275 }
3276
3277 if (NetPnPEvent->Buffer) ExFreePool(NetPnPEvent->Buffer);
3278 ExFreePool(NetPnPEvent);
3279
3280 Irp->IoStatus.Status = NDIS_STATUS_SUCCESS;
3281 IoCompleteRequest(Irp, IO_NO_INCREMENT);
3282 }
3283
3284 /*
3285 * @implemented
3286 */
3287 VOID
3288 EXPORT
3289 NdisCancelSendPackets(
3290 IN NDIS_HANDLE NdisBindingHandle,
3291 IN PVOID CancelId)
3292 {
3293 PADAPTER_BINDING AdapterBinding = NdisBindingHandle;
3294 PLOGICAL_ADAPTER Adapter = AdapterBinding->Adapter;
3295
3296 NDIS_DbgPrint(MAX_TRACE, ("Called for ID %x.\n", CancelId));
3297
3298 if (Adapter->NdisMiniportBlock.DriverHandle->MiniportCharacteristics.CancelSendPacketsHandler)
3299 {
3300 (*Adapter->NdisMiniportBlock.DriverHandle->MiniportCharacteristics.CancelSendPacketsHandler)(
3301 Adapter->NdisMiniportBlock.MiniportAdapterContext,
3302 CancelId);
3303 }
3304 }
3305
3306
3307 /*
3308 * @implemented
3309 */
3310 NDIS_HANDLE
3311 EXPORT
3312 NdisIMGetBindingContext(
3313 IN NDIS_HANDLE NdisBindingHandle)
3314 /*
3315 * FUNCTION:
3316 * ARGUMENTS:
3317 * NOTES:
3318 * NDIS 5.0
3319 */
3320 {
3321 PADAPTER_BINDING AdapterBinding = NdisBindingHandle;
3322 PLOGICAL_ADAPTER Adapter = AdapterBinding->Adapter;
3323
3324 NDIS_DbgPrint(MAX_TRACE, ("Called.\n"));
3325
3326 return Adapter->NdisMiniportBlock.DeviceContext;
3327 }
3328
3329
3330 /*
3331 * @implemented
3332 */
3333 NDIS_HANDLE
3334 EXPORT
3335 NdisIMGetDeviceContext(
3336 IN NDIS_HANDLE MiniportAdapterHandle)
3337 /*
3338 * FUNCTION:
3339 * ARGUMENTS:
3340 * NOTES:
3341 * NDIS 5.0
3342 */
3343 {
3344 PLOGICAL_ADAPTER Adapter = MiniportAdapterHandle;
3345
3346 NDIS_DbgPrint(MAX_TRACE, ("Called.\n"));
3347
3348 return Adapter->NdisMiniportBlock.DeviceContext;
3349 }
3350
3351 /* EOF */