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