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)
9 * CSH 01/08-2000 Created
10 * 20 Aug 2003 vizzini - DMA support
11 * 3 Oct 2003 vizzini - SendPackets support
19 #undef NdisMSendComplete
23 IN NDIS_HANDLE MiniportAdapterHandle
,
24 IN PNDIS_PACKET Packet
,
25 IN NDIS_STATUS Status
);
27 /* Root of the scm database */
28 #define SERVICES_ROOT L"\\Registry\\Machine\\System\\CurrentControlSet\\Services\\"
31 * Define to 1 to get a debugger breakpoint at the end of NdisInitializeWrapper
32 * for each new miniport starting up
34 #define BREAK_ON_MINIPORT_INIT 0
37 * This has to be big enough to hold the results of querying the Route value
38 * from the Linkage key. Please re-code me to determine this dynamically.
40 #define ROUTE_DATA_SIZE 256
42 /* Number of media we know */
43 #define MEDIA_ARRAY_SIZE 15
45 static NDIS_MEDIUM MediaArray
[MEDIA_ARRAY_SIZE
] =
54 NdisMediumArcnet878_2
,
56 NdisMediumWirelessWan
,
64 /* global list and lock of Miniports NDIS has registered */
65 LIST_ENTRY MiniportListHead
;
66 KSPIN_LOCK MiniportListLock
;
68 /* global list and lock of adapters NDIS has registered */
69 LIST_ENTRY AdapterListHead
;
70 KSPIN_LOCK AdapterListLock
;
79 if ((DebugTraceLevel
& DEBUG_PACKET
) > 0) {
80 Length
= CopyPacketToBuffer(
86 DbgPrint("*** PACKET START ***");
88 for (i
= 0; i
< Length
; i
++) {
90 DbgPrint("\n%04X ", i
);
91 DbgPrint("%02X ", Buffer
[i
]);
94 DbgPrint("*** PACKET STOP ***\n");
102 UINT HeaderBufferSize
,
103 PVOID LookaheadBuffer
,
104 UINT LookaheadBufferSize
)
107 if ((DebugTraceLevel
& DEBUG_PACKET
) > 0) {
111 DbgPrint("*** RECEIVE PACKET START ***\n");
114 for (i
= 0; i
< HeaderBufferSize
; i
++) {
116 DbgPrint("\n%04X ", i
);
117 DbgPrint("%02X ", *p
++);
120 DbgPrint("\nFRAME:");
123 Length
= (LookaheadBufferSize
< 64)? LookaheadBufferSize
: 64;
124 for (i
= 0; i
< Length
; i
++) {
126 DbgPrint("\n%04X ", i
);
127 DbgPrint("%02X ", *p
++);
130 DbgPrint("\n*** RECEIVE PACKET STOP ***\n");
135 PNDIS_MINIPORT_WORK_ITEM
136 MiniGetFirstWorkItem(
137 PLOGICAL_ADAPTER Adapter
,
138 NDIS_WORK_ITEM_TYPE Type
)
140 PNDIS_MINIPORT_WORK_ITEM CurrentEntry
= Adapter
->WorkQueueHead
;
144 if (CurrentEntry
->WorkItemType
== Type
)
147 CurrentEntry
= (PNDIS_MINIPORT_WORK_ITEM
)CurrentEntry
->Link
.Next
;
155 PLOGICAL_ADAPTER Adapter
,
156 NDIS_WORK_ITEM_TYPE Type
)
158 BOOLEAN Busy
= FALSE
;
161 KeAcquireSpinLock(&Adapter
->NdisMiniportBlock
.Lock
, &OldIrql
);
163 if (Type
== NdisWorkItemRequest
&&
164 (Adapter
->NdisMiniportBlock
.PendingRequest
|| MiniGetFirstWorkItem(Adapter
, NdisWorkItemRequest
)))
168 else if (Type
== NdisWorkItemSend
&&
169 (Adapter
->NdisMiniportBlock
.FirstPendingPacket
|| MiniGetFirstWorkItem(Adapter
, NdisWorkItemSend
)))
173 else if (Type
== NdisWorkItemResetRequested
&&
174 (Adapter
->NdisMiniportBlock
.ResetStatus
== NDIS_STATUS_PENDING
|| MiniGetFirstWorkItem(Adapter
, NdisWorkItemResetRequested
)))
179 KeReleaseSpinLock(&Adapter
->NdisMiniportBlock
.Lock
, OldIrql
);
187 PLOGICAL_ADAPTER Adapter
,
188 NDIS_HANDLE MacReceiveContext
,
190 UINT HeaderBufferSize
,
191 PVOID LookaheadBuffer
,
192 UINT LookaheadBufferSize
,
195 * FUNCTION: Indicate received data to bound protocols
197 * Adapter = Pointer to logical adapter
198 * MacReceiveContext = MAC receive context handle
199 * HeaderBuffer = Pointer to header buffer
200 * HeaderBufferSize = Size of header buffer
201 * LookaheadBuffer = Pointer to lookahead buffer
202 * LookaheadBufferSize = Size of lookahead buffer
203 * PacketSize = Total size of received packet
207 PLIST_ENTRY CurrentEntry
;
208 PADAPTER_BINDING AdapterBinding
;
210 NDIS_DbgPrint(DEBUG_MINIPORT
, ("Called. Adapter (0x%X) HeaderBuffer (0x%X) "
211 "HeaderBufferSize (0x%X) LookaheadBuffer (0x%X) LookaheadBufferSize (0x%X).\n",
212 Adapter
, HeaderBuffer
, HeaderBufferSize
, LookaheadBuffer
, LookaheadBufferSize
));
214 MiniDisplayPacket2(HeaderBuffer
, HeaderBufferSize
, LookaheadBuffer
, LookaheadBufferSize
);
216 NDIS_DbgPrint(MAX_TRACE
, ("acquiring miniport block lock\n"));
217 KeAcquireSpinLock(&Adapter
->NdisMiniportBlock
.Lock
, &OldIrql
);
219 CurrentEntry
= Adapter
->ProtocolListHead
.Flink
;
220 NDIS_DbgPrint(DEBUG_MINIPORT
, ("CurrentEntry = %x\n", CurrentEntry
));
222 if (CurrentEntry
== &Adapter
->ProtocolListHead
)
224 NDIS_DbgPrint(DEBUG_MINIPORT
, ("WARNING: No upper protocol layer.\n"));
227 while (CurrentEntry
!= &Adapter
->ProtocolListHead
)
229 AdapterBinding
= CONTAINING_RECORD(CurrentEntry
, ADAPTER_BINDING
, AdapterListEntry
);
230 NDIS_DbgPrint(DEBUG_MINIPORT
, ("AdapterBinding = %x\n", AdapterBinding
));
234 ("XXX (%x) %x %x %x %x %x %x %x XXX\n",
235 *AdapterBinding
->ProtocolBinding
->Chars
.ReceiveHandler
,
236 AdapterBinding
->NdisOpenBlock
.ProtocolBindingContext
,
244 /* call the receive handler */
245 (*AdapterBinding
->ProtocolBinding
->Chars
.ReceiveHandler
)(
246 AdapterBinding
->NdisOpenBlock
.ProtocolBindingContext
,
254 CurrentEntry
= CurrentEntry
->Flink
;
257 KeReleaseSpinLock(&Adapter
->NdisMiniportBlock
.Lock
, OldIrql
);
259 NDIS_DbgPrint(MAX_TRACE
, ("Leaving.\n"));
264 IN NDIS_HANDLE MiniportAdapterHandle
,
265 IN NDIS_STATUS Status
)
272 IN NDIS_HANDLE MiniportAdapterHandle
,
273 IN NDIS_STATUS Status
)
280 MiniIndicateReceivePacket(
281 IN NDIS_HANDLE MiniportAdapterHandle
,
282 IN PPNDIS_PACKET PacketArray
,
283 IN UINT NumberOfPackets
)
285 * FUNCTION: receives miniport packet array indications
287 * MiniportAdapterHandle: Miniport handle for the adapter
288 * PacketArray: pointer to a list of packet pointers to indicate
289 * NumberOfPackets: number of packets to indicate
293 PLOGICAL_ADAPTER Adapter
= MiniportAdapterHandle
;
294 PLIST_ENTRY CurrentEntry
;
295 PADAPTER_BINDING AdapterBinding
;
299 KeAcquireSpinLock(&Adapter
->NdisMiniportBlock
.Lock
, &OldIrql
);
301 CurrentEntry
= Adapter
->ProtocolListHead
.Flink
;
303 while (CurrentEntry
!= &Adapter
->ProtocolListHead
)
305 AdapterBinding
= CONTAINING_RECORD(CurrentEntry
, ADAPTER_BINDING
, AdapterListEntry
);
307 if (AdapterBinding
->ProtocolBinding
->Chars
.ReceivePacketHandler
)
309 for (i
= 0; i
< NumberOfPackets
; i
++)
311 (*AdapterBinding
->ProtocolBinding
->Chars
.ReceivePacketHandler
)(
312 AdapterBinding
->NdisOpenBlock
.ProtocolBindingContext
,
318 for (i
= 0; i
< NumberOfPackets
; i
++)
320 UINT FirstBufferLength
, TotalBufferLength
, LookAheadSize
, HeaderSize
;
321 PNDIS_BUFFER NdisBuffer
;
322 PVOID NdisBufferVA
, LookAheadBuffer
;
323 NDIS_STATUS NdisStatus
;
326 NdisGetFirstBufferFromPacket(PacketArray
[i
],
332 HeaderSize
= NDIS_GET_PACKET_HEADER_SIZE(PacketArray
[i
]);
334 if (Adapter
->NdisMiniportBlock
.CurrentLookahead
< (TotalBufferLength
- HeaderSize
))
336 LookAheadSize
= Adapter
->NdisMiniportBlock
.CurrentLookahead
;
340 LookAheadSize
= TotalBufferLength
- HeaderSize
;
344 LookAheadBuffer
= ExAllocatePool(NonPagedPool
, LookAheadSize
);
345 if (!LookAheadBuffer
)
347 NDIS_DbgPrint(MIN_TRACE
, ("Failed to allocate lookahead buffer!\n"));
351 CopyBufferChainToBuffer(LookAheadBuffer
,
356 NdisStatus
= (*AdapterBinding
->ProtocolBinding
->Chars
.ReceiveHandler
)(
357 AdapterBinding
->NdisOpenBlock
.ProtocolBindingContext
,
358 AdapterBinding
->NdisOpenBlock
.MacHandle
,
363 TotalBufferLength
- HeaderSize
);
365 NDIS_SET_PACKET_STATUS(PacketArray
[i
], NdisStatus
);
367 ExFreePool(LookAheadBuffer
);
371 CurrentEntry
= CurrentEntry
->Flink
;
374 KeReleaseSpinLock(&Adapter
->NdisMiniportBlock
.Lock
, OldIrql
);
380 IN NDIS_HANDLE MiniportAdapterHandle
,
381 IN NDIS_STATUS Status
,
382 IN BOOLEAN AddressingReset
)
384 PLOGICAL_ADAPTER Adapter
= MiniportAdapterHandle
;
385 PLIST_ENTRY CurrentEntry
;
386 PADAPTER_BINDING AdapterBinding
;
389 NdisMIndicateStatus(Adapter
, NDIS_STATUS_RESET_END
, NULL
, 0);
390 NdisMIndicateStatusComplete(Adapter
);
392 KeAcquireSpinLock(&Adapter
->NdisMiniportBlock
.Lock
, &OldIrql
);
394 Adapter
->NdisMiniportBlock
.ResetStatus
= Status
;
396 CurrentEntry
= Adapter
->ProtocolListHead
.Flink
;
398 while (CurrentEntry
!= &Adapter
->ProtocolListHead
)
400 AdapterBinding
= CONTAINING_RECORD(CurrentEntry
, ADAPTER_BINDING
, AdapterListEntry
);
402 (*AdapterBinding
->ProtocolBinding
->Chars
.ResetCompleteHandler
)(
403 AdapterBinding
->NdisOpenBlock
.ProtocolBindingContext
,
406 CurrentEntry
= CurrentEntry
->Flink
;
409 KeReleaseSpinLock(&Adapter
->NdisMiniportBlock
.Lock
, OldIrql
);
416 IN PNDIS_HANDLE MiniportAdapterHandle
,
417 IN PNDIS_REQUEST Request
,
418 IN NDIS_STATUS Status
)
420 PLOGICAL_ADAPTER Adapter
= (PLOGICAL_ADAPTER
)MiniportAdapterHandle
;
421 PNDIS_REQUEST_MAC_BLOCK MacBlock
= (PNDIS_REQUEST_MAC_BLOCK
)Request
->MacReserved
;
424 NDIS_DbgPrint(DEBUG_MINIPORT
, ("Called.\n"));
426 KeRaiseIrql(DISPATCH_LEVEL
, &OldIrql
);
428 KeAcquireSpinLockAtDpcLevel(&Adapter
->NdisMiniportBlock
.Lock
);
429 Adapter
->NdisMiniportBlock
.PendingRequest
= NULL
;
430 KeReleaseSpinLockFromDpcLevel(&Adapter
->NdisMiniportBlock
.Lock
);
432 if( MacBlock
->Binding
->RequestCompleteHandler
) {
433 (*MacBlock
->Binding
->RequestCompleteHandler
)(
434 MacBlock
->Binding
->ProtocolBindingContext
,
438 KeLowerIrql(OldIrql
);
443 IN NDIS_HANDLE MiniportAdapterHandle
,
444 IN PNDIS_PACKET Packet
,
445 IN NDIS_STATUS Status
)
447 * FUNCTION: Forwards a message to the initiating protocol saying
448 * that a packet was handled
450 * NdisAdapterHandle = Handle input to MiniportInitialize
451 * Packet = Pointer to NDIS packet that was sent
452 * Status = Status of send operation
455 PADAPTER_BINDING AdapterBinding
;
458 NDIS_DbgPrint(DEBUG_MINIPORT
, ("Called.\n"));
460 AdapterBinding
= (PADAPTER_BINDING
)Packet
->Reserved
[0];
462 KeRaiseIrql(DISPATCH_LEVEL
, &OldIrql
);
463 (*AdapterBinding
->ProtocolBinding
->Chars
.SendCompleteHandler
)(
464 AdapterBinding
->NdisOpenBlock
.ProtocolBindingContext
,
467 KeLowerIrql(OldIrql
);
472 MiniSendResourcesAvailable(
473 IN NDIS_HANDLE MiniportAdapterHandle
)
482 MiniTransferDataComplete(
483 IN NDIS_HANDLE MiniportAdapterHandle
,
484 IN PNDIS_PACKET Packet
,
485 IN NDIS_STATUS Status
,
486 IN UINT BytesTransferred
)
488 PADAPTER_BINDING AdapterBinding
;
491 NDIS_DbgPrint(DEBUG_MINIPORT
, ("Called.\n"));
493 AdapterBinding
= (PADAPTER_BINDING
)Packet
->Reserved
[0];
495 KeRaiseIrql(DISPATCH_LEVEL
, &OldIrql
);
496 (*AdapterBinding
->ProtocolBinding
->Chars
.TransferDataCompleteHandler
)(
497 AdapterBinding
->NdisOpenBlock
.ProtocolBindingContext
,
501 KeLowerIrql(OldIrql
);
506 MiniAdapterHasAddress(
507 PLOGICAL_ADAPTER Adapter
,
510 * FUNCTION: Determines whether a packet has the same destination address as an adapter
512 * Adapter = Pointer to logical adapter object
513 * Packet = Pointer to NDIS packet
515 * TRUE if the destination address is that of the adapter, FALSE if not
521 PNDIS_BUFFER NdisBuffer
;
524 NDIS_DbgPrint(DEBUG_MINIPORT
, ("Called.\n"));
529 NDIS_DbgPrint(MID_TRACE
, ("Adapter object was null\n"));
535 NDIS_DbgPrint(MID_TRACE
, ("Packet was null\n"));
540 NdisQueryPacket(Packet
, NULL
, NULL
, &NdisBuffer
, NULL
);
544 NDIS_DbgPrint(MID_TRACE
, ("Packet contains no buffers.\n"));
548 NdisQueryBuffer(NdisBuffer
, (PVOID
)&Start2
, &BufferLength
);
550 /* FIXME: Should handle fragmented packets */
552 switch (Adapter
->NdisMiniportBlock
.MediaType
)
554 case NdisMedium802_3
:
555 Length
= ETH_LENGTH_OF_ADDRESS
;
556 /* Destination address is the first field */
560 NDIS_DbgPrint(MIN_TRACE
, ("Adapter has unsupported media type (0x%X).\n", Adapter
->NdisMiniportBlock
.MediaType
));
564 if (BufferLength
< Length
)
566 NDIS_DbgPrint(MID_TRACE
, ("Buffer is too small.\n"));
570 Start1
= (PUCHAR
)&Adapter
->Address
;
571 NDIS_DbgPrint(MAX_TRACE
, ("packet address: %x:%x:%x:%x:%x:%x adapter address: %x:%x:%x:%x:%x:%x\n",
572 *((char *)Start1
), *(((char *)Start1
)+1), *(((char *)Start1
)+2), *(((char *)Start1
)+3), *(((char *)Start1
)+4), *(((char *)Start1
)+5),
573 *((char *)Start2
), *(((char *)Start2
)+1), *(((char *)Start2
)+2), *(((char *)Start2
)+3), *(((char *)Start2
)+4), *(((char *)Start2
)+5))
576 return (RtlCompareMemory((PVOID
)Start1
, (PVOID
)Start2
, Length
) == Length
);
582 PNDIS_STRING AdapterName
)
584 * FUNCTION: Finds an adapter object by name
586 * AdapterName = Pointer to name of adapter
588 * Pointer to logical adapter object, or NULL if none was found.
589 * If found, the adapter is referenced for the caller. The caller
590 * is responsible for dereferencing after use
594 PLIST_ENTRY CurrentEntry
;
595 PLOGICAL_ADAPTER Adapter
= 0;
599 NDIS_DbgPrint(DEBUG_MINIPORT
, ("Called.\n"));
601 if(IsListEmpty(&AdapterListHead
))
603 NDIS_DbgPrint(DEBUG_MINIPORT
, ("No registered miniports for protocol to bind to\n"));
607 KeAcquireSpinLock(&AdapterListLock
, &OldIrql
);
609 CurrentEntry
= AdapterListHead
.Flink
;
611 while (CurrentEntry
!= &AdapterListHead
)
613 Adapter
= CONTAINING_RECORD(CurrentEntry
, LOGICAL_ADAPTER
, ListEntry
);
617 NDIS_DbgPrint(DEBUG_MINIPORT
, ("Examining adapter 0x%lx\n", Adapter
));
618 NDIS_DbgPrint(DEBUG_MINIPORT
, ("AdapterName = %wZ\n", AdapterName
));
619 NDIS_DbgPrint(DEBUG_MINIPORT
, ("DeviceName = %wZ\n", &Adapter
->NdisMiniportBlock
.MiniportName
));
621 if (RtlCompareUnicodeString(AdapterName
, &Adapter
->NdisMiniportBlock
.MiniportName
, TRUE
) == 0)
627 CurrentEntry
= CurrentEntry
->Flink
;
630 KeReleaseSpinLock(&AdapterListLock
, OldIrql
);
634 NDIS_DbgPrint(DEBUG_MINIPORT
, ("Leaving. Adapter found at 0x%x\n", Adapter
));
638 NDIS_DbgPrint(DEBUG_MINIPORT
, ("Leaving (adapter not found).\n"));
646 MiniQueryInformation(
647 PLOGICAL_ADAPTER Adapter
,
653 * FUNCTION: Queries a logical adapter for properties
655 * Adapter = Pointer to the logical adapter object to query
656 * Oid = Specifies the Object ID to query for
657 * Size = Size of the passed buffer
658 * Buffer = Buffer for the output
659 * BytesWritten = Address of buffer to place number of bytes written
661 * If the specified buffer is too small, a new buffer is allocated,
662 * and the query is attempted again
664 * Status of operation
666 * Is there any way to use the buffer provided by the protocol?
669 NDIS_STATUS NdisStatus
;
673 NDIS_DbgPrint(DEBUG_MINIPORT
, ("Called.\n"));
675 /* call the miniport's queryinfo handler */
676 KeRaiseIrql(DISPATCH_LEVEL
, &OldIrql
);
677 NdisStatus
= (*Adapter
->NdisMiniportBlock
.DriverHandle
->MiniportCharacteristics
.QueryInformationHandler
)(
678 Adapter
->NdisMiniportBlock
.MiniportAdapterContext
,
684 KeLowerIrql(OldIrql
);
686 /* FIXME: Wait in pending case! */
692 MiniCheckForHang( PLOGICAL_ADAPTER Adapter
)
694 * FUNCTION: Checks to see if the miniport is hung
696 * Adapter = Pointer to the logical adapter object
698 * TRUE if the miniport is hung
699 * FALSE if the miniport is not hung
705 KeRaiseIrql(DISPATCH_LEVEL
, &OldIrql
);
706 if (Adapter
->NdisMiniportBlock
.DriverHandle
->MiniportCharacteristics
.CheckForHangHandler
)
707 Ret
= (*Adapter
->NdisMiniportBlock
.DriverHandle
->MiniportCharacteristics
.CheckForHangHandler
)(
708 Adapter
->NdisMiniportBlock
.MiniportAdapterContext
);
709 KeLowerIrql(OldIrql
);
716 PLOGICAL_ADAPTER Adapter
,
717 PBOOLEAN AddressingReset
)
719 * FUNCTION: Resets the miniport
721 * Adapter = Pointer to the logical adapter object
722 * AddressingReset = Set to TRUE if we need to call MiniportSetInformation later
724 * Status of the operation
730 if (MiniIsBusy(Adapter
, NdisWorkItemResetRequested
)) {
731 MiniQueueWorkItem(Adapter
, NdisWorkItemResetRequested
, NULL
, FALSE
);
732 return NDIS_STATUS_PENDING
;
735 NdisMIndicateStatus(Adapter
, NDIS_STATUS_RESET_START
, NULL
, 0);
736 NdisMIndicateStatusComplete(Adapter
);
738 KeRaiseIrql(DISPATCH_LEVEL
, &OldIrql
);
739 Status
= (*Adapter
->NdisMiniportBlock
.DriverHandle
->MiniportCharacteristics
.ResetHandler
)(
740 Adapter
->NdisMiniportBlock
.MiniportAdapterContext
,
743 KeAcquireSpinLockAtDpcLevel(&Adapter
->NdisMiniportBlock
.Lock
);
744 Adapter
->NdisMiniportBlock
.ResetStatus
= Status
;
745 KeReleaseSpinLockFromDpcLevel(&Adapter
->NdisMiniportBlock
.Lock
);
747 KeLowerIrql(OldIrql
);
749 if (Status
!= NDIS_STATUS_PENDING
) {
750 NdisMIndicateStatus(Adapter
, NDIS_STATUS_RESET_END
, NULL
, 0);
751 NdisMIndicateStatusComplete(Adapter
);
760 PVOID DeferredContext
,
761 PVOID SystemArgument1
,
762 PVOID SystemArgument2
)
764 PLOGICAL_ADAPTER Adapter
= DeferredContext
;
765 BOOLEAN AddressingReset
= FALSE
;
768 if (MiniCheckForHang(Adapter
)) {
769 NDIS_DbgPrint(MIN_TRACE
, ("Miniport detected adapter hang\n"));
770 MiniReset(Adapter
, &AddressingReset
);
773 /* FIXME: We should call MiniportSetInformation if AddressingReset is TRUE */
780 PLOGICAL_ADAPTER Adapter
,
781 NDIS_WORK_ITEM_TYPE WorkItemType
,
782 PVOID WorkItemContext
,
785 * FUNCTION: Queues a work item for execution at a later time
787 * Adapter = Pointer to the logical adapter object to queue work item on
788 * WorkItemType = Type of work item to queue
789 * WorkItemContext = Pointer to context information for work item
791 * Status of operation
794 PNDIS_MINIPORT_WORK_ITEM MiniportWorkItem
;
795 PIO_WORKITEM IoWorkItem
;
798 NDIS_DbgPrint(MAX_TRACE
, ("Called.\n"));
802 KeAcquireSpinLock(&Adapter
->NdisMiniportBlock
.Lock
, &OldIrql
);
805 if (WorkItemType
== NdisWorkItemSend
)
807 NDIS_DbgPrint(MIN_TRACE
, ("Requeuing failed packet (%x).\n", WorkItemContext
));
808 Adapter
->NdisMiniportBlock
.FirstPendingPacket
= WorkItemContext
;
812 //This should never happen
818 MiniportWorkItem
= ExAllocatePool(NonPagedPool
, sizeof(NDIS_MINIPORT_WORK_ITEM
));
819 if (!MiniportWorkItem
)
821 KeReleaseSpinLock(&Adapter
->NdisMiniportBlock
.Lock
, OldIrql
);
822 NDIS_DbgPrint(MIN_TRACE
, ("Insufficient resources.\n"));
826 MiniportWorkItem
->WorkItemType
= WorkItemType
;
827 MiniportWorkItem
->WorkItemContext
= WorkItemContext
;
829 /* safe due to adapter lock held */
830 MiniportWorkItem
->Link
.Next
= NULL
;
831 if (!Adapter
->WorkQueueHead
)
833 Adapter
->WorkQueueHead
= MiniportWorkItem
;
834 Adapter
->WorkQueueTail
= MiniportWorkItem
;
838 Adapter
->WorkQueueTail
->Link
.Next
= (PSINGLE_LIST_ENTRY
)MiniportWorkItem
;
839 Adapter
->WorkQueueTail
= MiniportWorkItem
;
843 IoWorkItem
= IoAllocateWorkItem(Adapter
->NdisMiniportBlock
.DeviceObject
);
845 IoQueueWorkItem(IoWorkItem
, MiniportWorker
, DelayedWorkQueue
, IoWorkItem
);
847 KeReleaseSpinLock(&Adapter
->NdisMiniportBlock
.Lock
, OldIrql
);
854 PLOGICAL_ADAPTER Adapter
,
855 NDIS_WORK_ITEM_TYPE
*WorkItemType
,
856 PVOID
*WorkItemContext
)
858 * FUNCTION: Dequeues a work item from the work queue of a logical adapter
860 * Adapter = Pointer to the logical adapter object to dequeue work item from
861 * AdapterBinding = Address of buffer for adapter binding for this request
862 * WorkItemType = Address of buffer for work item type
863 * WorkItemContext = Address of buffer for pointer to context information
865 * Adapter lock must be held when called
867 * Status of operation
870 PNDIS_MINIPORT_WORK_ITEM MiniportWorkItem
;
873 NDIS_DbgPrint(MAX_TRACE
, ("Called.\n"));
875 MiniportWorkItem
= Adapter
->WorkQueueHead
;
877 if ((Packet
= Adapter
->NdisMiniportBlock
.FirstPendingPacket
))
879 Adapter
->NdisMiniportBlock
.FirstPendingPacket
= NULL
;
881 *WorkItemType
= NdisWorkItemSend
;
882 *WorkItemContext
= Packet
;
884 return NDIS_STATUS_SUCCESS
;
886 else if (MiniportWorkItem
)
888 /* safe due to adapter lock held */
889 Adapter
->WorkQueueHead
= (PNDIS_MINIPORT_WORK_ITEM
)MiniportWorkItem
->Link
.Next
;
891 if (MiniportWorkItem
== Adapter
->WorkQueueTail
)
892 Adapter
->WorkQueueTail
= NULL
;
894 *WorkItemType
= MiniportWorkItem
->WorkItemType
;
895 *WorkItemContext
= MiniportWorkItem
->WorkItemContext
;
897 ExFreePool(MiniportWorkItem
);
899 return NDIS_STATUS_SUCCESS
;
903 return NDIS_STATUS_FAILURE
;
910 PLOGICAL_ADAPTER Adapter
,
911 PNDIS_REQUEST NdisRequest
)
913 * FUNCTION: Sends a request to a miniport
915 * AdapterBinding = Pointer to binding used in the request
916 * NdisRequest = Pointer to NDIS request structure describing request
918 * Status of operation
923 NDIS_DbgPrint(DEBUG_MINIPORT
, ("Called.\n"));
925 KeRaiseIrql(DISPATCH_LEVEL
, &OldIrql
);
927 KeAcquireSpinLockAtDpcLevel(&Adapter
->NdisMiniportBlock
.Lock
);
928 Adapter
->NdisMiniportBlock
.PendingRequest
= NdisRequest
;
929 KeReleaseSpinLockFromDpcLevel(&Adapter
->NdisMiniportBlock
.Lock
);
931 switch (NdisRequest
->RequestType
)
933 case NdisRequestQueryInformation
:
934 Status
= (*Adapter
->NdisMiniportBlock
.DriverHandle
->MiniportCharacteristics
.QueryInformationHandler
)(
935 Adapter
->NdisMiniportBlock
.MiniportAdapterContext
,
936 NdisRequest
->DATA
.QUERY_INFORMATION
.Oid
,
937 NdisRequest
->DATA
.QUERY_INFORMATION
.InformationBuffer
,
938 NdisRequest
->DATA
.QUERY_INFORMATION
.InformationBufferLength
,
939 (PULONG
)&NdisRequest
->DATA
.QUERY_INFORMATION
.BytesWritten
,
940 (PULONG
)&NdisRequest
->DATA
.QUERY_INFORMATION
.BytesNeeded
);
943 case NdisRequestSetInformation
:
944 Status
= (*Adapter
->NdisMiniportBlock
.DriverHandle
->MiniportCharacteristics
.SetInformationHandler
)(
945 Adapter
->NdisMiniportBlock
.MiniportAdapterContext
,
946 NdisRequest
->DATA
.SET_INFORMATION
.Oid
,
947 NdisRequest
->DATA
.SET_INFORMATION
.InformationBuffer
,
948 NdisRequest
->DATA
.SET_INFORMATION
.InformationBufferLength
,
949 (PULONG
)&NdisRequest
->DATA
.SET_INFORMATION
.BytesRead
,
950 (PULONG
)&NdisRequest
->DATA
.SET_INFORMATION
.BytesNeeded
);
954 Status
= NDIS_STATUS_FAILURE
;
957 if (Status
!= NDIS_STATUS_PENDING
) {
958 KeAcquireSpinLockAtDpcLevel(&Adapter
->NdisMiniportBlock
.Lock
);
959 Adapter
->NdisMiniportBlock
.PendingRequest
= NULL
;
960 KeReleaseSpinLockFromDpcLevel(&Adapter
->NdisMiniportBlock
.Lock
);
963 KeLowerIrql(OldIrql
);
971 #undef NdisMSetInformationComplete
974 NdisMSetInformationComplete(
975 IN NDIS_HANDLE MiniportAdapterHandle
,
976 IN NDIS_STATUS Status
)
978 PLOGICAL_ADAPTER Adapter
=
979 (PLOGICAL_ADAPTER
)MiniportAdapterHandle
;
982 KeRaiseIrql(DISPATCH_LEVEL
, &OldIrql
);
983 if (Adapter
->NdisMiniportBlock
.SetCompleteHandler
)
984 (Adapter
->NdisMiniportBlock
.SetCompleteHandler
)(MiniportAdapterHandle
, Status
);
985 KeLowerIrql(OldIrql
);
992 #undef NdisMQueryInformationComplete
995 NdisMQueryInformationComplete(
996 IN NDIS_HANDLE MiniportAdapterHandle
,
997 IN NDIS_STATUS Status
)
999 PLOGICAL_ADAPTER Adapter
=
1000 (PLOGICAL_ADAPTER
)MiniportAdapterHandle
;
1003 KeRaiseIrql(DISPATCH_LEVEL
, &OldIrql
);
1004 if( Adapter
->NdisMiniportBlock
.QueryCompleteHandler
)
1005 (Adapter
->NdisMiniportBlock
.QueryCompleteHandler
)(MiniportAdapterHandle
, Status
);
1006 KeLowerIrql(OldIrql
);
1011 MiniportWorker(IN PDEVICE_OBJECT DeviceObject
, IN PVOID Context
)
1013 PLOGICAL_ADAPTER Adapter
= DeviceObject
->DeviceExtension
;
1014 KIRQL OldIrql
, RaiseOldIrql
;
1015 NDIS_STATUS NdisStatus
;
1016 PVOID WorkItemContext
;
1017 NDIS_WORK_ITEM_TYPE WorkItemType
;
1018 BOOLEAN AddressingReset
;
1020 IoFreeWorkItem((PIO_WORKITEM
)Context
);
1022 KeAcquireSpinLock(&Adapter
->NdisMiniportBlock
.Lock
, &OldIrql
);
1026 (Adapter
, &WorkItemType
, &WorkItemContext
);
1028 KeReleaseSpinLock(&Adapter
->NdisMiniportBlock
.Lock
, OldIrql
);
1030 if (NdisStatus
== NDIS_STATUS_SUCCESS
)
1032 switch (WorkItemType
)
1034 case NdisWorkItemSend
:
1036 * called by ProSend when protocols want to send packets to the miniport
1039 if(Adapter
->NdisMiniportBlock
.DriverHandle
->MiniportCharacteristics
.SendPacketsHandler
)
1041 if(Adapter
->NdisMiniportBlock
.Flags
& NDIS_ATTRIBUTE_DESERIALIZE
)
1043 NDIS_DbgPrint(MAX_TRACE
, ("Calling miniport's SendPackets handler\n"));
1044 (*Adapter
->NdisMiniportBlock
.DriverHandle
->MiniportCharacteristics
.SendPacketsHandler
)(
1045 Adapter
->NdisMiniportBlock
.MiniportAdapterContext
, (PPNDIS_PACKET
)&WorkItemContext
, 1);
1046 NdisStatus
= NDIS_STATUS_PENDING
;
1050 /* SendPackets is called at DISPATCH_LEVEL for all serialized miniports */
1051 KeRaiseIrql(DISPATCH_LEVEL
, &RaiseOldIrql
);
1053 NDIS_DbgPrint(MAX_TRACE
, ("Calling miniport's SendPackets handler\n"));
1054 (*Adapter
->NdisMiniportBlock
.DriverHandle
->MiniportCharacteristics
.SendPacketsHandler
)(
1055 Adapter
->NdisMiniportBlock
.MiniportAdapterContext
, (PPNDIS_PACKET
)&WorkItemContext
, 1);
1057 KeLowerIrql(RaiseOldIrql
);
1059 NdisStatus
= NDIS_GET_PACKET_STATUS((PNDIS_PACKET
)WorkItemContext
);
1060 if( NdisStatus
== NDIS_STATUS_RESOURCES
) {
1061 MiniQueueWorkItem(Adapter
, WorkItemType
, WorkItemContext
, TRUE
);
1068 if(Adapter
->NdisMiniportBlock
.Flags
& NDIS_ATTRIBUTE_DESERIALIZE
)
1070 NDIS_DbgPrint(MAX_TRACE
, ("Calling miniport's Send handler\n"));
1071 NdisStatus
= (*Adapter
->NdisMiniportBlock
.DriverHandle
->MiniportCharacteristics
.SendHandler
)(
1072 Adapter
->NdisMiniportBlock
.MiniportAdapterContext
, (PNDIS_PACKET
)WorkItemContext
,
1073 ((PNDIS_PACKET
)WorkItemContext
)->Private
.Flags
);
1074 NDIS_DbgPrint(MAX_TRACE
, ("back from miniport's send handler\n"));
1078 /* Send is called at DISPATCH_LEVEL for all serialized miniports */
1079 KeRaiseIrql(DISPATCH_LEVEL
, &RaiseOldIrql
);
1080 NDIS_DbgPrint(MAX_TRACE
, ("Calling miniport's Send handler\n"));
1081 NdisStatus
= (*Adapter
->NdisMiniportBlock
.DriverHandle
->MiniportCharacteristics
.SendHandler
)(
1082 Adapter
->NdisMiniportBlock
.MiniportAdapterContext
, (PNDIS_PACKET
)WorkItemContext
,
1083 ((PNDIS_PACKET
)WorkItemContext
)->Private
.Flags
);
1084 NDIS_DbgPrint(MAX_TRACE
, ("back from miniport's send handler\n"));
1085 KeLowerIrql(RaiseOldIrql
);
1086 if( NdisStatus
== NDIS_STATUS_RESOURCES
) {
1087 MiniQueueWorkItem(Adapter
, WorkItemType
, WorkItemContext
, TRUE
);
1093 if( NdisStatus
!= NDIS_STATUS_PENDING
) {
1095 ( Adapter
, (PNDIS_PACKET
)WorkItemContext
, NdisStatus
);
1099 case NdisWorkItemSendLoopback
:
1101 * called by ProSend when protocols want to send loopback packets
1103 /* XXX atm ProIndicatePacket sends a packet up via the loopback adapter only */
1104 NdisStatus
= ProIndicatePacket(Adapter
, (PNDIS_PACKET
)WorkItemContext
);
1106 if( NdisStatus
!= NDIS_STATUS_PENDING
)
1107 MiniSendComplete((NDIS_HANDLE
)Adapter
, (PNDIS_PACKET
)WorkItemContext
, NdisStatus
);
1110 case NdisWorkItemReturnPackets
:
1113 case NdisWorkItemResetRequested
:
1114 NdisMIndicateStatus(Adapter
, NDIS_STATUS_RESET_START
, NULL
, 0);
1115 NdisMIndicateStatusComplete(Adapter
);
1117 KeRaiseIrql(DISPATCH_LEVEL
, &OldIrql
);
1118 NdisStatus
= (*Adapter
->NdisMiniportBlock
.DriverHandle
->MiniportCharacteristics
.ResetHandler
)(
1119 Adapter
->NdisMiniportBlock
.MiniportAdapterContext
,
1122 if (NdisStatus
== NDIS_STATUS_PENDING
)
1124 KeAcquireSpinLockAtDpcLevel(&Adapter
->NdisMiniportBlock
.Lock
);
1125 Adapter
->NdisMiniportBlock
.ResetStatus
= NDIS_STATUS_PENDING
;
1126 KeReleaseSpinLockFromDpcLevel(&Adapter
->NdisMiniportBlock
.Lock
);
1129 KeLowerIrql(OldIrql
);
1131 if (NdisStatus
!= NDIS_STATUS_PENDING
)
1132 MiniResetComplete(Adapter
, NdisStatus
, AddressingReset
);
1135 case NdisWorkItemResetInProgress
:
1138 case NdisWorkItemMiniportCallback
:
1141 case NdisWorkItemRequest
:
1142 NdisStatus
= MiniDoRequest(Adapter
, (PNDIS_REQUEST
)WorkItemContext
);
1144 if (NdisStatus
== NDIS_STATUS_PENDING
)
1147 switch (((PNDIS_REQUEST
)WorkItemContext
)->RequestType
)
1149 case NdisRequestQueryInformation
:
1150 NdisMQueryInformationComplete((NDIS_HANDLE
)Adapter
, NdisStatus
);
1151 MiniRequestComplete( (NDIS_HANDLE
)Adapter
, (PNDIS_REQUEST
)WorkItemContext
, NdisStatus
);
1154 case NdisRequestSetInformation
:
1155 NdisMSetInformationComplete((NDIS_HANDLE
)Adapter
, NdisStatus
);
1156 MiniRequestComplete( (NDIS_HANDLE
)Adapter
, (PNDIS_REQUEST
)WorkItemContext
, NdisStatus
);
1160 NDIS_DbgPrint(MIN_TRACE
, ("Unknown NDIS request type.\n"));
1161 MiniRequestComplete( (NDIS_HANDLE
)Adapter
, (PNDIS_REQUEST
)WorkItemContext
, NdisStatus
);
1167 NDIS_DbgPrint(MIN_TRACE
, ("Unknown NDIS work item type (%d).\n", WorkItemType
));
1178 IN NDIS_HANDLE MiniportHandle
,
1179 IN NDIS_STATUS GeneralStatus
,
1180 IN PVOID StatusBuffer
,
1181 IN UINT StatusBufferSize
)
1183 PLOGICAL_ADAPTER Adapter
= MiniportHandle
;
1184 PLIST_ENTRY CurrentEntry
;
1185 PADAPTER_BINDING AdapterBinding
;
1188 KeAcquireSpinLock(&Adapter
->NdisMiniportBlock
.Lock
, &OldIrql
);
1190 CurrentEntry
= Adapter
->ProtocolListHead
.Flink
;
1192 while (CurrentEntry
!= &Adapter
->ProtocolListHead
)
1194 AdapterBinding
= CONTAINING_RECORD(CurrentEntry
, ADAPTER_BINDING
, AdapterListEntry
);
1196 (*AdapterBinding
->ProtocolBinding
->Chars
.StatusHandler
)(
1197 AdapterBinding
->NdisOpenBlock
.ProtocolBindingContext
,
1202 CurrentEntry
= CurrentEntry
->Flink
;
1205 KeReleaseSpinLock(&Adapter
->NdisMiniportBlock
.Lock
, OldIrql
);
1212 IN NDIS_HANDLE MiniportAdapterHandle
)
1214 PLOGICAL_ADAPTER Adapter
= MiniportAdapterHandle
;
1215 PLIST_ENTRY CurrentEntry
;
1216 PADAPTER_BINDING AdapterBinding
;
1219 KeAcquireSpinLock(&Adapter
->NdisMiniportBlock
.Lock
, &OldIrql
);
1221 CurrentEntry
= Adapter
->ProtocolListHead
.Flink
;
1223 while (CurrentEntry
!= &Adapter
->ProtocolListHead
)
1225 AdapterBinding
= CONTAINING_RECORD(CurrentEntry
, ADAPTER_BINDING
, AdapterListEntry
);
1227 (*AdapterBinding
->ProtocolBinding
->Chars
.StatusCompleteHandler
)(
1228 AdapterBinding
->NdisOpenBlock
.ProtocolBindingContext
);
1230 CurrentEntry
= CurrentEntry
->Flink
;
1233 KeReleaseSpinLock(&Adapter
->NdisMiniportBlock
.Lock
, OldIrql
);
1243 IN NDIS_HANDLE LogHandle
)
1245 PNDIS_LOG Log
= (PNDIS_LOG
)LogHandle
;
1246 PNDIS_MINIPORT_BLOCK Miniport
= Log
->Miniport
;
1249 NDIS_DbgPrint(MAX_TRACE
, ("called: LogHandle 0x%x\n", LogHandle
));
1251 KeAcquireSpinLock(&(Miniport
)->Lock
, &OldIrql
);
1252 Miniport
->Log
= NULL
;
1253 KeReleaseSpinLock(&(Miniport
)->Lock
, OldIrql
);
1264 IN NDIS_HANDLE MiniportAdapterHandle
,
1266 OUT PNDIS_HANDLE LogHandle
)
1268 PLOGICAL_ADAPTER Adapter
= MiniportAdapterHandle
;
1272 NDIS_DbgPrint(MAX_TRACE
, ("called: MiniportAdapterHandle 0x%x, Size %ld\n", MiniportAdapterHandle
, Size
));
1274 KeAcquireSpinLock(&Adapter
->NdisMiniportBlock
.Lock
, &OldIrql
);
1276 if (Adapter
->NdisMiniportBlock
.Log
)
1279 return NDIS_STATUS_FAILURE
;
1282 Log
= ExAllocatePool(NonPagedPool
, Size
+ sizeof(NDIS_LOG
));
1286 return NDIS_STATUS_RESOURCES
;
1289 Adapter
->NdisMiniportBlock
.Log
= Log
;
1291 KeInitializeSpinLock(&Log
->LogLock
);
1293 Log
->Miniport
= &Adapter
->NdisMiniportBlock
;
1294 Log
->TotalSize
= Size
;
1295 Log
->CurrentSize
= 0;
1302 KeReleaseSpinLock(&Adapter
->NdisMiniportBlock
.Lock
, OldIrql
);
1304 return NDIS_STATUS_SUCCESS
;
1312 NdisMDeregisterAdapterShutdownHandler(
1313 IN NDIS_HANDLE MiniportHandle
)
1315 * FUNCTION: de-registers a shutdown handler
1316 * ARGUMENTS: MiniportHandle: Handle passed into MiniportInitialize
1319 PLOGICAL_ADAPTER Adapter
= (PLOGICAL_ADAPTER
)MiniportHandle
;
1321 NDIS_DbgPrint(DEBUG_MINIPORT
, ("Called.\n"));
1323 if(Adapter
->BugcheckContext
->ShutdownHandler
) {
1324 KeDeregisterBugCheckCallback(Adapter
->BugcheckContext
->CallbackRecord
);
1325 IoUnregisterShutdownNotification(Adapter
->NdisMiniportBlock
.DeviceObject
);
1335 IN NDIS_HANDLE LogHandle
)
1337 PNDIS_LOG Log
= (PNDIS_LOG
) LogHandle
;
1340 NDIS_DbgPrint(MAX_TRACE
, ("called: LogHandle 0x%x\n", LogHandle
));
1343 KeAcquireSpinLock(&Log
->LogLock
, &OldIrql
);
1345 /* Set buffers size */
1346 Log
->CurrentSize
= 0;
1351 KeReleaseSpinLock(&Log
->LogLock
, OldIrql
);
1357 #undef NdisMIndicateStatus
1360 NdisMIndicateStatus(
1361 IN NDIS_HANDLE MiniportAdapterHandle
,
1362 IN NDIS_STATUS GeneralStatus
,
1363 IN PVOID StatusBuffer
,
1364 IN UINT StatusBufferSize
)
1366 MiniStatus(MiniportAdapterHandle
, GeneralStatus
, StatusBuffer
, StatusBufferSize
);
1372 #undef NdisMIndicateStatusComplete
1375 NdisMIndicateStatusComplete(
1376 IN NDIS_HANDLE MiniportAdapterHandle
)
1378 MiniStatusComplete(MiniportAdapterHandle
);
1387 NdisInitializeWrapper(
1388 OUT PNDIS_HANDLE NdisWrapperHandle
,
1389 IN PVOID SystemSpecific1
,
1390 IN PVOID SystemSpecific2
,
1391 IN PVOID SystemSpecific3
)
1393 * FUNCTION: Notifies the NDIS library that a new miniport is initializing
1395 * NdisWrapperHandle = Address of buffer to place NDIS wrapper handle
1396 * SystemSpecific1 = Pointer to the driver's driver object
1397 * SystemSpecific2 = Pointer to the driver's registry path
1398 * SystemSpecific3 = Always NULL
1400 * - SystemSpecific2 goes invalid so we copy it
1403 PNDIS_M_DRIVER_BLOCK Miniport
;
1404 PUNICODE_STRING RegistryPath
;
1405 WCHAR
*RegistryBuffer
;
1407 NDIS_DbgPrint(MAX_TRACE
, ("Called.\n"));
1409 ASSERT(NdisWrapperHandle
);
1411 *NdisWrapperHandle
= NULL
;
1413 #if BREAK_ON_MINIPORT_INIT
1414 __asm__ ("int $3\n");
1417 Miniport
= ExAllocatePool(NonPagedPool
, sizeof(NDIS_M_DRIVER_BLOCK
));
1421 NDIS_DbgPrint(MIN_TRACE
, ("Insufficient resources.\n"));
1425 RtlZeroMemory(Miniport
, sizeof(NDIS_M_DRIVER_BLOCK
));
1427 KeInitializeSpinLock(&Miniport
->Lock
);
1429 Miniport
->DriverObject
= (PDRIVER_OBJECT
)SystemSpecific1
;
1431 /* set the miniport's driver registry path */
1432 RegistryPath
= ExAllocatePool(PagedPool
, sizeof(UNICODE_STRING
));
1435 ExFreePool(Miniport
);
1436 NDIS_DbgPrint(MIN_TRACE
, ("Insufficient resources.\n"));
1440 RegistryPath
->Length
= ((PUNICODE_STRING
)SystemSpecific2
)->Length
;
1441 RegistryPath
->MaximumLength
= RegistryPath
->Length
+ sizeof(WCHAR
); /* room for 0-term */
1443 RegistryBuffer
= ExAllocatePool(PagedPool
, RegistryPath
->MaximumLength
);
1446 NDIS_DbgPrint(MIN_TRACE
, ("Insufficient resources.\n"));
1447 ExFreePool(Miniport
);
1448 ExFreePool(RegistryPath
);
1452 RtlCopyMemory(RegistryBuffer
, ((PUNICODE_STRING
)SystemSpecific2
)->Buffer
, RegistryPath
->Length
);
1453 RegistryBuffer
[RegistryPath
->Length
/sizeof(WCHAR
)] = 0;
1455 RegistryPath
->Buffer
= RegistryBuffer
;
1456 Miniport
->RegistryPath
= RegistryPath
;
1458 InitializeListHead(&Miniport
->DeviceList
);
1460 /* Put miniport in global miniport list */
1461 ExInterlockedInsertTailList(&MiniportListHead
, &Miniport
->ListEntry
, &MiniportListLock
);
1463 *NdisWrapperHandle
= Miniport
;
1467 VOID NTAPI
NdisIBugcheckCallback(
1471 * FUNCTION: Internal callback for handling bugchecks - calls adapter's shutdown handler
1473 * Buffer: Pointer to a bugcheck callback context
1477 PMINIPORT_BUGCHECK_CONTEXT Context
= (PMINIPORT_BUGCHECK_CONTEXT
)Buffer
;
1478 ADAPTER_SHUTDOWN_HANDLER sh
= (ADAPTER_SHUTDOWN_HANDLER
)Context
->ShutdownHandler
;
1480 NDIS_DbgPrint(DEBUG_MINIPORT
, ("Called.\n"));
1483 sh(Context
->DriverContext
);
1492 NdisMRegisterAdapterShutdownHandler(
1493 IN NDIS_HANDLE MiniportHandle
,
1494 IN PVOID ShutdownContext
,
1495 IN ADAPTER_SHUTDOWN_HANDLER ShutdownHandler
)
1497 * FUNCTION: Register a shutdown handler for an adapter
1499 * MiniportHandle: Handle originally passed into MiniportInitialize
1500 * ShutdownContext: Pre-initialized bugcheck context
1501 * ShutdownHandler: Function to call to handle the bugcheck
1503 * - I'm not sure about ShutdownContext
1506 PLOGICAL_ADAPTER Adapter
= (PLOGICAL_ADAPTER
)MiniportHandle
;
1507 PMINIPORT_BUGCHECK_CONTEXT BugcheckContext
;
1509 NDIS_DbgPrint(DEBUG_MINIPORT
, ("Called.\n"));
1511 BugcheckContext
= ExAllocatePool(NonPagedPool
, sizeof(MINIPORT_BUGCHECK_CONTEXT
));
1512 if(!BugcheckContext
)
1514 NDIS_DbgPrint(MIN_TRACE
, ("Insufficient resources.\n"));
1518 BugcheckContext
->ShutdownHandler
= ShutdownHandler
;
1519 BugcheckContext
->DriverContext
= ShutdownContext
;
1521 BugcheckContext
->CallbackRecord
= ExAllocatePool(NonPagedPool
, sizeof(KBUGCHECK_CALLBACK_RECORD
));
1522 if (!BugcheckContext
->CallbackRecord
) {
1523 ExFreePool(BugcheckContext
);
1527 Adapter
->BugcheckContext
= BugcheckContext
;
1529 KeInitializeCallbackRecord(BugcheckContext
->CallbackRecord
);
1531 KeRegisterBugCheckCallback(BugcheckContext
->CallbackRecord
, NdisIBugcheckCallback
,
1532 BugcheckContext
, sizeof(BugcheckContext
), (PUCHAR
)"Ndis Miniport");
1534 IoRegisterShutdownNotification(Adapter
->NdisMiniportBlock
.DeviceObject
);
1540 PLOGICAL_ADAPTER Adapter
,
1541 NDIS_OID AddressOID
)
1543 * FUNCTION: Queries miniport for information
1545 * Adapter = Pointer to logical adapter
1546 * AddressOID = OID to use to query for current address
1548 * Status of operation
1552 NDIS_STATUS NdisStatus
;
1554 NDIS_DbgPrint(MAX_TRACE
, ("Called.\n"));
1556 /* Get MAC options for adapter */
1557 NdisStatus
= MiniQueryInformation(Adapter
, OID_GEN_MAC_OPTIONS
, sizeof(UINT
),
1558 &Adapter
->NdisMiniportBlock
.MacOptions
,
1561 if (NdisStatus
!= NDIS_STATUS_SUCCESS
)
1563 NDIS_DbgPrint(MIN_TRACE
, ("OID_GEN_MAC_OPTIONS failed. NdisStatus (0x%X).\n", NdisStatus
));
1567 NDIS_DbgPrint(DEBUG_MINIPORT
, ("MacOptions (0x%X).\n", Adapter
->NdisMiniportBlock
.MacOptions
));
1569 /* Get current hardware address of adapter */
1570 NdisStatus
= MiniQueryInformation(Adapter
, AddressOID
, Adapter
->AddressLength
,
1571 &Adapter
->Address
, &BytesWritten
);
1573 if (NdisStatus
!= NDIS_STATUS_SUCCESS
)
1575 NDIS_DbgPrint(MIN_TRACE
, ("Address OID (0x%X) failed. NdisStatus (0x%X).\n", AddressOID
, NdisStatus
));
1583 PUCHAR A
= (PUCHAR
)&Adapter
->Address
.Type
.Medium802_3
;
1585 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]));
1589 /* Get maximum lookahead buffer size of adapter */
1590 NdisStatus
= MiniQueryInformation(Adapter
, OID_GEN_MAXIMUM_LOOKAHEAD
, sizeof(ULONG
),
1591 &Adapter
->NdisMiniportBlock
.MaximumLookahead
, &BytesWritten
);
1593 if (NdisStatus
!= NDIS_STATUS_SUCCESS
)
1595 NDIS_DbgPrint(MIN_TRACE
, ("OID_GEN_MAXIMUM_LOOKAHEAD failed. NdisStatus (0x%X).\n", NdisStatus
));
1599 NDIS_DbgPrint(DEBUG_MINIPORT
, ("MaxLookaheadLength (0x%X).\n", Adapter
->NdisMiniportBlock
.MaximumLookahead
));
1601 /* Get current lookahead buffer size of adapter */
1602 NdisStatus
= MiniQueryInformation(Adapter
, OID_GEN_CURRENT_LOOKAHEAD
, sizeof(ULONG
),
1603 &Adapter
->NdisMiniportBlock
.CurrentLookahead
, &BytesWritten
);
1605 if (NdisStatus
!= NDIS_STATUS_SUCCESS
)
1607 NDIS_DbgPrint(MIN_TRACE
, ("OID_GEN_CURRENT_LOOKAHEAD failed. NdisStatus (0x%X).\n", NdisStatus
));
1612 NDIS_DbgPrint(MIN_TRACE
, ("Current lookahead is %ld\n", Adapter
->NdisMiniportBlock
.CurrentLookahead
));
1613 NDIS_DbgPrint(MIN_TRACE
, ("Maximum lookahead is %ld\n", Adapter
->NdisMiniportBlock
.MaximumLookahead
));
1615 NdisStatus
= MiniQueryInformation(Adapter
, OID_GEN_MAXIMUM_SEND_PACKETS
, sizeof(ULONG
),
1616 &Adapter
->NdisMiniportBlock
.MaxSendPackets
, &BytesWritten
);
1618 if (NdisStatus
!= NDIS_STATUS_SUCCESS
)
1620 NDIS_DbgPrint(MIN_TRACE
, ("OID_GEN_MAXIMUM_SEND_PACKETS failed. NdisStatus (0x%X).\n", NdisStatus
));
1622 /* Set it to 1 if it fails because some drivers don't support this (?)*/
1623 Adapter
->NdisMiniportBlock
.MaxSendPackets
= 1;
1626 NDIS_DbgPrint(DEBUG_MINIPORT
, ("CurLookaheadLength (0x%X).\n", Adapter
->NdisMiniportBlock
.CurrentLookahead
));
1628 return STATUS_SUCCESS
;
1634 NdisIForwardIrpAndWaitCompletionRoutine(
1639 PKEVENT Event
= Context
;
1641 if (Irp
->PendingReturned
)
1642 KeSetEvent(Event
, IO_NO_INCREMENT
, FALSE
);
1644 return STATUS_MORE_PROCESSING_REQUIRED
;
1650 NdisIForwardIrpAndWait(PLOGICAL_ADAPTER Adapter
, PIRP Irp
)
1655 KeInitializeEvent(&Event
, NotificationEvent
, FALSE
);
1656 IoCopyCurrentIrpStackLocationToNext(Irp
);
1657 IoSetCompletionRoutine(Irp
, NdisIForwardIrpAndWaitCompletionRoutine
, &Event
,
1659 Status
= IoCallDriver(Adapter
->NdisMiniportBlock
.NextDeviceObject
, Irp
);
1660 if (Status
== STATUS_PENDING
)
1662 KeWaitForSingleObject(&Event
, Executive
, KernelMode
, FALSE
, NULL
);
1663 Status
= Irp
->IoStatus
.Status
;
1671 NdisIPnPStartDevice(
1672 IN PDEVICE_OBJECT DeviceObject
,
1675 * FUNCTION: Handle the PnP start device event
1677 * DeviceObejct = Functional Device Object
1678 * Irp = IRP_MN_START_DEVICE I/O request packet
1680 * Status of operation
1683 PIO_STACK_LOCATION Stack
= IoGetCurrentIrpStackLocation(Irp
);
1684 PLOGICAL_ADAPTER Adapter
= (PLOGICAL_ADAPTER
)DeviceObject
->DeviceExtension
;
1685 NDIS_WRAPPER_CONTEXT WrapperContext
;
1686 NDIS_STATUS NdisStatus
;
1687 NDIS_STATUS OpenErrorStatus
;
1689 UINT SelectedMediumIndex
= 0;
1690 NDIS_OID AddressOID
;
1691 BOOLEAN Success
= FALSE
;
1692 ULONG ResourceCount
;
1693 ULONG ResourceListSize
;
1694 UNICODE_STRING ParamName
;
1695 PNDIS_CONFIGURATION_PARAMETER ConfigParam
;
1696 NDIS_HANDLE ConfigHandle
;
1698 LARGE_INTEGER Timeout
;
1699 UINT MaxMulticastAddresses
;
1703 * Prepare wrapper context used by HW and configuration routines.
1706 NDIS_DbgPrint(DEBUG_MINIPORT
, ("Start Device %wZ\n", &Adapter
->NdisMiniportBlock
.MiniportName
));
1708 NDIS_DbgPrint(MAX_TRACE
, ("Inserting adapter 0x%x into adapter list\n", Adapter
));
1710 /* Put adapter in global adapter list */
1711 ExInterlockedInsertTailList(&AdapterListHead
, &Adapter
->ListEntry
, &AdapterListLock
);
1713 Status
= IoOpenDeviceRegistryKey(
1714 Adapter
->NdisMiniportBlock
.PhysicalDeviceObject
, PLUGPLAY_REGKEY_DRIVER
,
1715 KEY_ALL_ACCESS
, &WrapperContext
.RegistryHandle
);
1716 if (!NT_SUCCESS(Status
))
1718 NDIS_DbgPrint(MIN_TRACE
,("failed to open adapter-specific reg key\n"));
1719 ExInterlockedRemoveEntryList( &Adapter
->ListEntry
, &AdapterListLock
);
1723 NDIS_DbgPrint(MAX_TRACE
, ("opened device reg key\n"));
1725 WrapperContext
.DeviceObject
= Adapter
->NdisMiniportBlock
.DeviceObject
;
1728 * Store the adapter resources used by HW routines such as
1729 * NdisMQueryAdapterResources.
1732 if (Stack
->Parameters
.StartDevice
.AllocatedResources
!= NULL
)
1734 ResourceCount
= Stack
->Parameters
.StartDevice
.AllocatedResources
->List
[0].
1735 PartialResourceList
.Count
;
1737 FIELD_OFFSET(CM_RESOURCE_LIST
, List
[0].PartialResourceList
.
1738 PartialDescriptors
[ResourceCount
]);
1740 Adapter
->NdisMiniportBlock
.AllocatedResources
=
1741 ExAllocatePool(PagedPool
, ResourceListSize
);
1742 if (Adapter
->NdisMiniportBlock
.AllocatedResources
== NULL
)
1744 ExInterlockedRemoveEntryList( &Adapter
->ListEntry
, &AdapterListLock
);
1745 return STATUS_INSUFFICIENT_RESOURCES
;
1748 RtlCopyMemory(Adapter
->NdisMiniportBlock
.AllocatedResources
,
1749 Stack
->Parameters
.StartDevice
.AllocatedResources
,
1753 if (Stack
->Parameters
.StartDevice
.AllocatedResourcesTranslated
!= NULL
)
1755 ResourceCount
= Stack
->Parameters
.StartDevice
.AllocatedResourcesTranslated
->List
[0].
1756 PartialResourceList
.Count
;
1758 FIELD_OFFSET(CM_RESOURCE_LIST
, List
[0].PartialResourceList
.
1759 PartialDescriptors
[ResourceCount
]);
1761 Adapter
->NdisMiniportBlock
.AllocatedResourcesTranslated
=
1762 ExAllocatePool(PagedPool
, ResourceListSize
);
1763 if (Adapter
->NdisMiniportBlock
.AllocatedResourcesTranslated
== NULL
)
1765 ExInterlockedRemoveEntryList( &Adapter
->ListEntry
, &AdapterListLock
);
1766 return STATUS_INSUFFICIENT_RESOURCES
;
1769 RtlCopyMemory(Adapter
->NdisMiniportBlock
.AllocatedResourcesTranslated
,
1770 Stack
->Parameters
.StartDevice
.AllocatedResourcesTranslated
,
1775 * Store the Bus Type, Bus Number and Slot information. It's used by
1776 * the hardware routines then.
1779 NdisOpenConfiguration(&NdisStatus
, &ConfigHandle
, (NDIS_HANDLE
)&WrapperContext
);
1781 Size
= sizeof(ULONG
);
1782 Status
= IoGetDeviceProperty(Adapter
->NdisMiniportBlock
.PhysicalDeviceObject
,
1783 DevicePropertyLegacyBusType
, Size
,
1784 &Adapter
->NdisMiniportBlock
.BusType
, &Size
);
1785 if (!NT_SUCCESS(Status
) || (INTERFACE_TYPE
)Adapter
->NdisMiniportBlock
.BusType
== InterfaceTypeUndefined
)
1787 NdisInitUnicodeString(&ParamName
, L
"BusType");
1788 NdisReadConfiguration(&NdisStatus
, &ConfigParam
, ConfigHandle
,
1789 &ParamName
, NdisParameterInteger
);
1790 if (NdisStatus
== NDIS_STATUS_SUCCESS
)
1791 Adapter
->NdisMiniportBlock
.BusType
= ConfigParam
->ParameterData
.IntegerData
;
1793 Adapter
->NdisMiniportBlock
.BusType
= Isa
;
1796 Status
= IoGetDeviceProperty(Adapter
->NdisMiniportBlock
.PhysicalDeviceObject
,
1797 DevicePropertyBusNumber
, Size
,
1798 &Adapter
->NdisMiniportBlock
.BusNumber
, &Size
);
1799 if (!NT_SUCCESS(Status
) || Adapter
->NdisMiniportBlock
.BusNumber
== 0xFFFFFFF0)
1801 NdisInitUnicodeString(&ParamName
, L
"BusNumber");
1802 NdisReadConfiguration(&NdisStatus
, &ConfigParam
, ConfigHandle
,
1803 &ParamName
, NdisParameterInteger
);
1804 if (NdisStatus
== NDIS_STATUS_SUCCESS
)
1805 Adapter
->NdisMiniportBlock
.BusNumber
= ConfigParam
->ParameterData
.IntegerData
;
1807 Adapter
->NdisMiniportBlock
.BusNumber
= 0;
1809 WrapperContext
.BusNumber
= Adapter
->NdisMiniportBlock
.BusNumber
;
1811 Status
= IoGetDeviceProperty(Adapter
->NdisMiniportBlock
.PhysicalDeviceObject
,
1812 DevicePropertyAddress
, Size
,
1813 &Adapter
->NdisMiniportBlock
.SlotNumber
, &Size
);
1814 if (!NT_SUCCESS(Status
) || Adapter
->NdisMiniportBlock
.SlotNumber
== (NDIS_INTERFACE_TYPE
)-1)
1816 NdisInitUnicodeString(&ParamName
, L
"SlotNumber");
1817 NdisReadConfiguration(&NdisStatus
, &ConfigParam
, ConfigHandle
,
1818 &ParamName
, NdisParameterInteger
);
1819 if (NdisStatus
== NDIS_STATUS_SUCCESS
)
1820 Adapter
->NdisMiniportBlock
.SlotNumber
= ConfigParam
->ParameterData
.IntegerData
;
1822 Adapter
->NdisMiniportBlock
.SlotNumber
= 0;
1826 /* Convert slotnumber to PCI_SLOT_NUMBER */
1827 ULONG PciSlotNumber
= Adapter
->NdisMiniportBlock
.SlotNumber
;
1828 PCI_SLOT_NUMBER SlotNumber
;
1830 SlotNumber
.u
.AsULONG
= 0;
1831 SlotNumber
.u
.bits
.DeviceNumber
= (PciSlotNumber
>> 16) & 0xFFFF;
1832 SlotNumber
.u
.bits
.FunctionNumber
= PciSlotNumber
& 0xFFFF;
1834 Adapter
->NdisMiniportBlock
.SlotNumber
= SlotNumber
.u
.AsULONG
;
1836 NdisCloseConfiguration(ConfigHandle
);
1838 /* Set handlers (some NDIS macros require these) */
1839 Adapter
->NdisMiniportBlock
.EthRxCompleteHandler
= EthFilterDprIndicateReceiveComplete
;
1840 Adapter
->NdisMiniportBlock
.EthRxIndicateHandler
= EthFilterDprIndicateReceive
;
1841 Adapter
->NdisMiniportBlock
.SendCompleteHandler
= MiniSendComplete
;
1842 Adapter
->NdisMiniportBlock
.SendResourcesHandler
= MiniSendResourcesAvailable
;
1843 Adapter
->NdisMiniportBlock
.ResetCompleteHandler
= MiniResetComplete
;
1844 Adapter
->NdisMiniportBlock
.TDCompleteHandler
= MiniTransferDataComplete
;
1845 Adapter
->NdisMiniportBlock
.PacketIndicateHandler
= MiniIndicateReceivePacket
;
1846 Adapter
->NdisMiniportBlock
.StatusHandler
= MiniStatus
;
1847 Adapter
->NdisMiniportBlock
.StatusCompleteHandler
= MiniStatusComplete
;
1848 Adapter
->NdisMiniportBlock
.SendPacketsHandler
= ProSendPackets
;
1849 Adapter
->NdisMiniportBlock
.QueryCompleteHandler
= MiniQueryComplete
;
1850 Adapter
->NdisMiniportBlock
.SetCompleteHandler
= MiniSetComplete
;
1853 * Call MiniportInitialize.
1856 NDIS_DbgPrint(MID_TRACE
, ("calling MiniportInitialize\n"));
1857 NdisStatus
= (*Adapter
->NdisMiniportBlock
.DriverHandle
->MiniportCharacteristics
.InitializeHandler
)(
1858 &OpenErrorStatus
, &SelectedMediumIndex
, &MediaArray
[0],
1859 MEDIA_ARRAY_SIZE
, Adapter
, (NDIS_HANDLE
)&WrapperContext
);
1861 ZwClose(WrapperContext
.RegistryHandle
);
1863 if (NdisStatus
!= NDIS_STATUS_SUCCESS
)
1865 NDIS_DbgPrint(MIN_TRACE
, ("MiniportInitialize() failed for an adapter.\n"));
1866 ExInterlockedRemoveEntryList( &Adapter
->ListEntry
, &AdapterListLock
);
1870 if (SelectedMediumIndex
>= MEDIA_ARRAY_SIZE
)
1872 NDIS_DbgPrint(MIN_TRACE
, ("MiniportInitialize() failed for an adapter\n"));
1873 ExInterlockedRemoveEntryList( &Adapter
->ListEntry
, &AdapterListLock
);
1874 return NDIS_STATUS_UNSUPPORTED_MEDIA
;
1877 Adapter
->NdisMiniportBlock
.MediaType
= MediaArray
[SelectedMediumIndex
];
1879 switch (Adapter
->NdisMiniportBlock
.MediaType
)
1881 case NdisMedium802_3
:
1882 Adapter
->MediumHeaderSize
= 14; /* XXX figure out what to do about LLC */
1883 AddressOID
= OID_802_3_CURRENT_ADDRESS
;
1884 Adapter
->AddressLength
= ETH_LENGTH_OF_ADDRESS
;
1885 NdisStatus
= DoQueries(Adapter
, AddressOID
);
1886 if (NdisStatus
== NDIS_STATUS_SUCCESS
)
1888 NdisStatus
= MiniQueryInformation(Adapter
, OID_802_3_MAXIMUM_LIST_SIZE
, sizeof(UINT
),
1889 &MaxMulticastAddresses
, &BytesWritten
);
1891 if (NdisStatus
!= NDIS_STATUS_SUCCESS
)
1893 ExInterlockedRemoveEntryList( &Adapter
->ListEntry
, &AdapterListLock
);
1894 NDIS_DbgPrint(MAX_TRACE
, ("MiniQueryInformation failed (%x)\n", NdisStatus
));
1898 Success
= EthCreateFilter(MaxMulticastAddresses
,
1899 Adapter
->Address
.Type
.Medium802_3
,
1900 &Adapter
->NdisMiniportBlock
.EthDB
);
1902 ((PETHI_FILTER
)Adapter
->NdisMiniportBlock
.EthDB
)->Miniport
= (PNDIS_MINIPORT_BLOCK
)Adapter
;
1904 NdisStatus
= NDIS_STATUS_RESOURCES
;
1909 /* FIXME: Support other types of media */
1910 NDIS_DbgPrint(MIN_TRACE
, ("error: unsupported media\n"));
1912 /* FIXME - KeReleaseSpinLock(&Adapter->NdisMiniportBlock.Lock, OldIrql); */
1913 ExInterlockedRemoveEntryList( &Adapter
->ListEntry
, &AdapterListLock
);
1914 return STATUS_UNSUCCESSFUL
;
1917 if (NdisStatus
!= NDIS_STATUS_SUCCESS
)
1919 NDIS_DbgPrint(MAX_TRACE
, ("couldn't create filter (%x)\n", NdisStatus
));
1923 /* Check for a hang every two seconds if it wasn't set in MiniportInitialize */
1924 if (Adapter
->NdisMiniportBlock
.CheckForHangSeconds
== 0)
1925 Adapter
->NdisMiniportBlock
.CheckForHangSeconds
= 2;
1927 Adapter
->NdisMiniportBlock
.OldPnPDeviceState
= Adapter
->NdisMiniportBlock
.PnPDeviceState
;
1928 Adapter
->NdisMiniportBlock
.PnPDeviceState
= NdisPnPDeviceStarted
;
1930 Timeout
.QuadPart
= (LONGLONG
)Adapter
->NdisMiniportBlock
.CheckForHangSeconds
* -1000000;
1931 KeSetTimerEx(&Adapter
->NdisMiniportBlock
.WakeUpDpcTimer
.Timer
, Timeout
,
1932 Adapter
->NdisMiniportBlock
.CheckForHangSeconds
* 1000,
1933 &Adapter
->NdisMiniportBlock
.WakeUpDpcTimer
.Dpc
);
1935 /* Put adapter in adapter list for this miniport */
1936 ExInterlockedInsertTailList(&Adapter
->NdisMiniportBlock
.DriverHandle
->DeviceList
, &Adapter
->MiniportListEntry
, &Adapter
->NdisMiniportBlock
.DriverHandle
->Lock
);
1938 return STATUS_SUCCESS
;
1945 IN PDEVICE_OBJECT DeviceObject
,
1948 * FUNCTION: Handle the PnP stop device event
1950 * DeviceObejct = Functional Device Object
1951 * Irp = IRP_MN_STOP_DEVICE I/O request packet
1953 * Status of operation
1956 PLOGICAL_ADAPTER Adapter
= (PLOGICAL_ADAPTER
)DeviceObject
->DeviceExtension
;
1958 /* Remove adapter from adapter list for this miniport */
1959 ExInterlockedRemoveEntryList(&Adapter
->MiniportListEntry
, &Adapter
->NdisMiniportBlock
.DriverHandle
->Lock
);
1961 /* Remove adapter from global adapter list */
1962 ExInterlockedRemoveEntryList(&Adapter
->ListEntry
, &AdapterListLock
);
1964 KeCancelTimer(&Adapter
->NdisMiniportBlock
.WakeUpDpcTimer
.Timer
);
1966 (*Adapter
->NdisMiniportBlock
.DriverHandle
->MiniportCharacteristics
.HaltHandler
)(Adapter
);
1968 if (Adapter
->NdisMiniportBlock
.AllocatedResources
)
1970 ExFreePool(Adapter
->NdisMiniportBlock
.AllocatedResources
);
1971 Adapter
->NdisMiniportBlock
.AllocatedResources
= NULL
;
1973 if (Adapter
->NdisMiniportBlock
.AllocatedResourcesTranslated
)
1975 ExFreePool(Adapter
->NdisMiniportBlock
.AllocatedResourcesTranslated
);
1976 Adapter
->NdisMiniportBlock
.AllocatedResourcesTranslated
= NULL
;
1979 if (Adapter
->NdisMiniportBlock
.EthDB
)
1981 EthDeleteFilter(Adapter
->NdisMiniportBlock
.EthDB
);
1982 Adapter
->NdisMiniportBlock
.EthDB
= NULL
;
1985 Adapter
->NdisMiniportBlock
.OldPnPDeviceState
= Adapter
->NdisMiniportBlock
.PnPDeviceState
;
1986 Adapter
->NdisMiniportBlock
.PnPDeviceState
= NdisPnPDeviceStopped
;
1988 return STATUS_SUCCESS
;
1994 IN PDEVICE_OBJECT DeviceObject
,
1997 PLOGICAL_ADAPTER Adapter
= DeviceObject
->DeviceExtension
;
1998 PMINIPORT_BUGCHECK_CONTEXT Context
= Adapter
->BugcheckContext
;
1999 ADAPTER_SHUTDOWN_HANDLER ShutdownHandler
= Context
->ShutdownHandler
;
2001 ASSERT(ShutdownHandler
);
2003 ShutdownHandler(Context
->DriverContext
);
2005 Irp
->IoStatus
.Status
= STATUS_SUCCESS
;
2006 Irp
->IoStatus
.Information
= 0;
2008 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
2010 return STATUS_SUCCESS
;
2017 IN PDEVICE_OBJECT DeviceObject
,
2020 PIO_STACK_LOCATION Stack
= IoGetCurrentIrpStackLocation(Irp
);
2021 PLOGICAL_ADAPTER Adapter
= (PLOGICAL_ADAPTER
)DeviceObject
->DeviceExtension
;
2024 switch (Stack
->MinorFunction
)
2026 case IRP_MN_START_DEVICE
:
2027 Status
= NdisIForwardIrpAndWait(Adapter
, Irp
);
2028 if (NT_SUCCESS(Status
) && NT_SUCCESS(Irp
->IoStatus
.Status
))
2030 Status
= NdisIPnPStartDevice(DeviceObject
, Irp
);
2032 Irp
->IoStatus
.Status
= Status
;
2033 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
2036 case IRP_MN_STOP_DEVICE
:
2037 Status
= NdisIForwardIrpAndWait(Adapter
, Irp
);
2038 if (NT_SUCCESS(Status
) && NT_SUCCESS(Irp
->IoStatus
.Status
))
2040 Status
= NdisIPnPStopDevice(DeviceObject
, Irp
);
2042 Irp
->IoStatus
.Status
= Status
;
2043 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
2046 case IRP_MN_QUERY_DEVICE_RELATIONS
:
2047 Status
= STATUS_NOT_SUPPORTED
;
2048 Irp
->IoStatus
.Status
= Status
;
2049 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
2053 IoSkipCurrentIrpStackLocation(Irp
);
2054 Status
= IoCallDriver(Adapter
->NdisMiniportBlock
.NextDeviceObject
, Irp
);
2065 IN PDRIVER_OBJECT DriverObject
,
2066 IN PDEVICE_OBJECT PhysicalDeviceObject
)
2068 * FUNCTION: Create a device for an adapter found using PnP
2070 * DriverObject = Pointer to the miniport driver object
2071 * PhysicalDeviceObject = Pointer to the PDO for our adapter
2074 static const WCHAR ClassKeyName
[] = {'C','l','a','s','s','\\'};
2075 static const WCHAR LinkageKeyName
[] = {'\\','L','i','n','k','a','g','e',0};
2076 PNDIS_M_DRIVER_BLOCK Miniport
;
2077 PNDIS_M_DRIVER_BLOCK
*MiniportPtr
;
2078 WCHAR
*LinkageKeyBuffer
;
2079 ULONG DriverKeyLength
;
2080 RTL_QUERY_REGISTRY_TABLE QueryTable
[2];
2081 UNICODE_STRING ExportName
;
2082 PDEVICE_OBJECT DeviceObject
;
2083 PLOGICAL_ADAPTER Adapter
;
2087 * Gain the access to the miniport data structure first.
2090 MiniportPtr
= IoGetDriverObjectExtension(DriverObject
, (PVOID
)TAG('D','I','M','N'));
2091 if (MiniportPtr
== NULL
)
2093 NDIS_DbgPrint(DEBUG_MINIPORT
, ("Can't get driver object extension.\n"));
2094 return STATUS_UNSUCCESSFUL
;
2096 Miniport
= *MiniportPtr
;
2099 * Get name of the Linkage registry key for our adapter. It's located under
2100 * the driver key for our driver and so we have basicly two ways to do it.
2101 * Either we can use IoOpenDriverRegistryKey or compose it using information
2102 * gathered by IoGetDeviceProperty. I choosed the second because
2103 * IoOpenDriverRegistryKey wasn't implemented at the time of writing.
2106 Status
= IoGetDeviceProperty(PhysicalDeviceObject
, DevicePropertyDriverKeyName
,
2107 0, NULL
, &DriverKeyLength
);
2108 if (Status
!= STATUS_BUFFER_TOO_SMALL
&& Status
!= STATUS_BUFFER_OVERFLOW
&& Status
!= STATUS_SUCCESS
)
2110 NDIS_DbgPrint(DEBUG_MINIPORT
, ("Can't get miniport driver key length.\n"));
2114 LinkageKeyBuffer
= ExAllocatePool(PagedPool
, DriverKeyLength
+
2115 sizeof(ClassKeyName
) + sizeof(LinkageKeyName
));
2116 if (LinkageKeyBuffer
== NULL
)
2118 NDIS_DbgPrint(DEBUG_MINIPORT
, ("Can't allocate memory for driver key name.\n"));
2119 return STATUS_INSUFFICIENT_RESOURCES
;
2122 Status
= IoGetDeviceProperty(PhysicalDeviceObject
, DevicePropertyDriverKeyName
,
2123 DriverKeyLength
, LinkageKeyBuffer
+
2124 (sizeof(ClassKeyName
) / sizeof(WCHAR
)),
2126 if (!NT_SUCCESS(Status
))
2128 NDIS_DbgPrint(DEBUG_MINIPORT
, ("Can't get miniport driver key.\n"));
2129 ExFreePool(LinkageKeyBuffer
);
2133 /* Compose the linkage key name. */
2134 RtlCopyMemory(LinkageKeyBuffer
, ClassKeyName
, sizeof(ClassKeyName
));
2135 RtlCopyMemory(LinkageKeyBuffer
+ ((sizeof(ClassKeyName
) + DriverKeyLength
) /
2136 sizeof(WCHAR
)) - 1, LinkageKeyName
, sizeof(LinkageKeyName
));
2138 NDIS_DbgPrint(DEBUG_MINIPORT
, ("LinkageKey: %S.\n", LinkageKeyBuffer
));
2141 * Now open the linkage key and read the "Export" and "RootDevice" values
2142 * which contains device name and root service respectively.
2145 RtlZeroMemory(QueryTable
, sizeof(QueryTable
));
2146 RtlInitUnicodeString(&ExportName
, NULL
);
2147 QueryTable
[0].Flags
= RTL_QUERY_REGISTRY_REQUIRED
| RTL_QUERY_REGISTRY_DIRECT
;
2148 QueryTable
[0].Name
= L
"Export";
2149 QueryTable
[0].EntryContext
= &ExportName
;
2151 Status
= RtlQueryRegistryValues(RTL_REGISTRY_CONTROL
, LinkageKeyBuffer
,
2152 QueryTable
, NULL
, NULL
);
2153 ExFreePool(LinkageKeyBuffer
);
2154 if (!NT_SUCCESS(Status
))
2156 NDIS_DbgPrint(DEBUG_MINIPORT
, ("Can't get miniport device name. (%x)\n", Status
));
2161 * Create the device object.
2164 NDIS_DbgPrint(MAX_TRACE
, ("creating device %wZ\n", &ExportName
));
2166 Status
= IoCreateDevice(Miniport
->DriverObject
, sizeof(LOGICAL_ADAPTER
),
2167 &ExportName
, FILE_DEVICE_PHYSICAL_NETCARD
,
2168 0, FALSE
, &DeviceObject
);
2169 if (!NT_SUCCESS(Status
))
2171 NDIS_DbgPrint(MIN_TRACE
, ("Could not create device object.\n"));
2172 RtlFreeUnicodeString(&ExportName
);
2177 * Initialize the adapter structure.
2180 Adapter
= (PLOGICAL_ADAPTER
)DeviceObject
->DeviceExtension
;
2181 KeInitializeSpinLock(&Adapter
->NdisMiniportBlock
.Lock
);
2182 InitializeListHead(&Adapter
->ProtocolListHead
);
2183 Adapter
->NdisMiniportBlock
.DriverHandle
= Miniport
;
2185 Adapter
->NdisMiniportBlock
.MiniportName
= ExportName
;
2187 Adapter
->NdisMiniportBlock
.DeviceObject
= DeviceObject
;
2188 Adapter
->NdisMiniportBlock
.PhysicalDeviceObject
= PhysicalDeviceObject
;
2189 Adapter
->NdisMiniportBlock
.NextDeviceObject
=
2190 IoAttachDeviceToDeviceStack(Adapter
->NdisMiniportBlock
.DeviceObject
,
2191 PhysicalDeviceObject
);
2193 Adapter
->NdisMiniportBlock
.OldPnPDeviceState
= 0;
2194 Adapter
->NdisMiniportBlock
.PnPDeviceState
= NdisPnPDeviceAdded
;
2196 KeInitializeTimer(&Adapter
->NdisMiniportBlock
.WakeUpDpcTimer
.Timer
);
2197 KeInitializeDpc(&Adapter
->NdisMiniportBlock
.WakeUpDpcTimer
.Dpc
, MiniportHangDpc
, Adapter
);
2199 DeviceObject
->Flags
&= ~DO_DEVICE_INITIALIZING
;
2201 return STATUS_SUCCESS
;
2210 NdisMRegisterMiniport(
2211 IN NDIS_HANDLE NdisWrapperHandle
,
2212 IN PNDIS_MINIPORT_CHARACTERISTICS MiniportCharacteristics
,
2213 IN UINT CharacteristicsLength
)
2215 * FUNCTION: Registers a miniport's MiniportXxx entry points with the NDIS library
2217 * NdisWrapperHandle = Pointer to handle returned by NdisMInitializeWrapper
2218 * MiniportCharacteristics = Pointer to a buffer with miniport characteristics
2219 * CharacteristicsLength = Number of bytes in characteristics buffer
2221 * Status of operation
2225 PNDIS_M_DRIVER_BLOCK Miniport
= GET_MINIPORT_DRIVER(NdisWrapperHandle
);
2226 PNDIS_M_DRIVER_BLOCK
*MiniportPtr
;
2229 NDIS_DbgPrint(MAX_TRACE
, ("Called.\n"));
2231 switch (MiniportCharacteristics
->MajorNdisVersion
)
2234 MinSize
= sizeof(NDIS30_MINIPORT_CHARACTERISTICS
);
2238 MinSize
= sizeof(NDIS40_MINIPORT_CHARACTERISTICS
);
2242 MinSize
= sizeof(NDIS50_MINIPORT_CHARACTERISTICS
);
2246 NDIS_DbgPrint(DEBUG_MINIPORT
, ("Bad miniport characteristics version.\n"));
2247 return NDIS_STATUS_BAD_VERSION
;
2250 if (CharacteristicsLength
< MinSize
)
2252 NDIS_DbgPrint(DEBUG_MINIPORT
, ("Bad miniport characteristics.\n"));
2253 return NDIS_STATUS_BAD_CHARACTERISTICS
;
2256 /* Check if mandatory MiniportXxx functions are specified */
2257 if ((!MiniportCharacteristics
->HaltHandler
) ||
2258 (!MiniportCharacteristics
->InitializeHandler
)||
2259 (!MiniportCharacteristics
->QueryInformationHandler
) ||
2260 (!MiniportCharacteristics
->ResetHandler
) ||
2261 (!MiniportCharacteristics
->SetInformationHandler
))
2263 NDIS_DbgPrint(DEBUG_MINIPORT
, ("Bad miniport characteristics.\n"));
2264 return NDIS_STATUS_BAD_CHARACTERISTICS
;
2267 if (MiniportCharacteristics
->MajorNdisVersion
== 0x03)
2269 if (!MiniportCharacteristics
->SendHandler
)
2271 NDIS_DbgPrint(DEBUG_MINIPORT
, ("Bad miniport characteristics.\n"));
2272 return NDIS_STATUS_BAD_CHARACTERISTICS
;
2275 else if (MiniportCharacteristics
->MajorNdisVersion
>= 0x04)
2278 if ((!MiniportCharacteristics
->SendHandler
) &&
2279 (!MiniportCharacteristics
->SendPacketsHandler
))
2281 NDIS_DbgPrint(DEBUG_MINIPORT
, ("Bad miniport characteristics.\n"));
2282 return NDIS_STATUS_BAD_CHARACTERISTICS
;
2286 /* TODO: verify NDIS5 and NDIS5.1 */
2288 RtlCopyMemory(&Miniport
->MiniportCharacteristics
, MiniportCharacteristics
, MinSize
);
2291 * NOTE: This is VERY unoptimal! Should we store the NDIS_M_DRIVER_BLOCK
2292 * structure in the driver extension or what?
2295 Status
= IoAllocateDriverObjectExtension(Miniport
->DriverObject
, (PVOID
)TAG('D','I','M','N'),
2296 sizeof(PNDIS_M_DRIVER_BLOCK
), (PVOID
*)&MiniportPtr
);
2297 if (!NT_SUCCESS(Status
))
2299 NDIS_DbgPrint(DEBUG_MINIPORT
, ("Can't allocate driver object extension.\n"));
2300 return NDIS_STATUS_RESOURCES
;
2303 *MiniportPtr
= Miniport
;
2305 Miniport
->DriverObject
->MajorFunction
[IRP_MJ_PNP
] = NdisIDispatchPnp
;
2306 Miniport
->DriverObject
->MajorFunction
[IRP_MJ_SHUTDOWN
] = NdisIShutdown
;
2307 Miniport
->DriverObject
->DriverExtension
->AddDevice
= NdisIAddDevice
;
2309 return NDIS_STATUS_SUCCESS
;
2316 #undef NdisMResetComplete
2320 IN NDIS_HANDLE MiniportAdapterHandle
,
2321 IN NDIS_STATUS Status
,
2322 IN BOOLEAN AddressingReset
)
2324 MiniResetComplete(MiniportAdapterHandle
, Status
, AddressingReset
);
2331 #undef NdisMSendComplete
2335 IN NDIS_HANDLE MiniportAdapterHandle
,
2336 IN PNDIS_PACKET Packet
,
2337 IN NDIS_STATUS Status
)
2339 * FUNCTION: Forwards a message to the initiating protocol saying
2340 * that a packet was handled
2342 * NdisAdapterHandle = Handle input to MiniportInitialize
2343 * Packet = Pointer to NDIS packet that was sent
2344 * Status = Status of send operation
2347 MiniSendComplete(MiniportAdapterHandle
, Packet
, Status
);
2354 #undef NdisMSendResourcesAvailable
2357 NdisMSendResourcesAvailable(
2358 IN NDIS_HANDLE MiniportAdapterHandle
)
2360 MiniSendResourcesAvailable(MiniportAdapterHandle
);
2367 #undef NdisMTransferDataComplete
2370 NdisMTransferDataComplete(
2371 IN NDIS_HANDLE MiniportAdapterHandle
,
2372 IN PNDIS_PACKET Packet
,
2373 IN NDIS_STATUS Status
,
2374 IN UINT BytesTransferred
)
2376 MiniTransferDataComplete(MiniportAdapterHandle
, Packet
, Status
, BytesTransferred
);
2383 #undef NdisMSetAttributes
2387 IN NDIS_HANDLE MiniportAdapterHandle
,
2388 IN NDIS_HANDLE MiniportAdapterContext
,
2389 IN BOOLEAN BusMaster
,
2390 IN NDIS_INTERFACE_TYPE AdapterType
)
2392 * FUNCTION: Informs the NDIS library of significant features of the caller's NIC
2394 * MiniportAdapterHandle = Handle input to MiniportInitialize
2395 * MiniportAdapterContext = Pointer to context information
2396 * BusMaster = Specifies TRUE if the caller's NIC is a busmaster DMA device
2397 * AdapterType = Specifies the I/O bus interface of the caller's NIC
2400 NDIS_DbgPrint(MAX_TRACE
, ("Called.\n"));
2401 NdisMSetAttributesEx(MiniportAdapterHandle
, MiniportAdapterContext
, 0,
2402 BusMaster
? NDIS_ATTRIBUTE_BUS_MASTER
: 0,
2412 NdisMSetAttributesEx(
2413 IN NDIS_HANDLE MiniportAdapterHandle
,
2414 IN NDIS_HANDLE MiniportAdapterContext
,
2415 IN UINT CheckForHangTimeInSeconds OPTIONAL
,
2416 IN ULONG AttributeFlags
,
2417 IN NDIS_INTERFACE_TYPE AdapterType
)
2419 * FUNCTION: Informs the NDIS library of significant features of the caller's NIC
2421 * MiniportAdapterHandle = Handle input to MiniportInitialize
2422 * MiniportAdapterContext = Pointer to context information
2423 * CheckForHangTimeInSeconds = Specifies interval in seconds at which
2424 * MiniportCheckForHang should be called
2425 * AttributeFlags = Bitmask that indicates specific attributes
2426 * AdapterType = Specifies the I/O bus interface of the caller's NIC
2429 PLOGICAL_ADAPTER Adapter
= GET_LOGICAL_ADAPTER(MiniportAdapterHandle
);
2431 NDIS_DbgPrint(MAX_TRACE
, ("Called.\n"));
2433 Adapter
->NdisMiniportBlock
.MiniportAdapterContext
= MiniportAdapterContext
;
2434 Adapter
->NdisMiniportBlock
.Flags
= AttributeFlags
;
2435 Adapter
->NdisMiniportBlock
.AdapterType
= AdapterType
;
2436 if (CheckForHangTimeInSeconds
> 0)
2437 Adapter
->NdisMiniportBlock
.CheckForHangSeconds
= CheckForHangTimeInSeconds
;
2438 if (AttributeFlags
& NDIS_ATTRIBUTE_INTERMEDIATE_DRIVER
)
2439 NDIS_DbgPrint(MAX_TRACE
, ("Intermediate drivers not supported yet.\n"));
2449 IN ULONG MicrosecondsToSleep
)
2451 * FUNCTION: delay the thread's execution for MicrosecondsToSleep
2453 * MicrosecondsToSleep: duh...
2455 * - Because this is a blocking call, current IRQL must be < DISPATCH_LEVEL
2459 LARGE_INTEGER DueTime
;
2463 DueTime
.QuadPart
= (-1) * 10 * MicrosecondsToSleep
;
2465 KeInitializeTimer(&Timer
);
2466 KeSetTimer(&Timer
, DueTime
, 0);
2467 KeWaitForSingleObject(&Timer
, Executive
, KernelMode
, FALSE
, 0);
2476 NdisMSynchronizeWithInterrupt(
2477 IN PNDIS_MINIPORT_INTERRUPT Interrupt
,
2478 IN PVOID SynchronizeFunction
,
2479 IN PVOID SynchronizeContext
)
2481 return(KeSynchronizeExecution(Interrupt
->InterruptObject
,
2482 (PKSYNCHRONIZE_ROUTINE
)SynchronizeFunction
,
2483 SynchronizeContext
));
2493 IN NDIS_HANDLE LogHandle
,
2495 IN UINT LogBufferSize
)
2497 PUCHAR Buffer
= LogBuffer
;
2501 for (i
= 0; i
< LogBufferSize
; i
+= 16)
2503 DbgPrint("%08x |", i
);
2504 for (j
= 0; j
< 16; j
++)
2507 if (idx
< LogBufferSize
)
2508 DbgPrint(" %02x", Buffer
[idx
]);
2513 for (j
= 0; j
< 16; j
++)
2516 if (idx
== LogBufferSize
)
2518 if (Buffer
[idx
] >= ' ') /* FIXME: not portable! replace by if (isprint(Buffer[idx])) ? */
2519 DbgPrint("%c", Buffer
[idx
]);
2526 return NDIS_STATUS_FAILURE
;
2535 NdisTerminateWrapper(
2536 IN NDIS_HANDLE NdisWrapperHandle
,
2537 IN PVOID SystemSpecific
)
2539 * FUNCTION: Releases resources allocated by a call to NdisInitializeWrapper
2541 * NdisWrapperHandle = Handle returned by NdisInitializeWrapper (NDIS_M_DRIVER_BLOCK)
2542 * SystemSpecific = Always NULL
2545 PNDIS_M_DRIVER_BLOCK Miniport
= GET_MINIPORT_DRIVER(NdisWrapperHandle
);
2547 NDIS_DbgPrint(MAX_TRACE
, ("Called.\n"));
2549 ExFreePool(Miniport
->RegistryPath
->Buffer
);
2550 ExFreePool(Miniport
->RegistryPath
);
2551 ExInterlockedRemoveEntryList(&Miniport
->ListEntry
, &MiniportListLock
);
2552 ExFreePool(Miniport
);
2561 NdisMQueryAdapterInstanceName(
2562 OUT PNDIS_STRING AdapterInstanceName
,
2563 IN NDIS_HANDLE MiniportAdapterHandle
)
2571 PLOGICAL_ADAPTER Adapter
= (PLOGICAL_ADAPTER
)MiniportAdapterHandle
;
2572 UNICODE_STRING AdapterName
;
2574 NDIS_DbgPrint(MAX_TRACE
, ("Called.\n"));
2576 AdapterName
.Length
= 0;
2577 AdapterName
.MaximumLength
= Adapter
->NdisMiniportBlock
.MiniportName
.MaximumLength
;
2578 AdapterName
.Buffer
= ExAllocatePool(PagedPool
, AdapterName
.MaximumLength
);
2579 if (!AdapterName
.Buffer
)
2580 return NDIS_STATUS_RESOURCES
;
2582 RtlCopyUnicodeString(&AdapterName
, &Adapter
->NdisMiniportBlock
.MiniportName
);
2584 *AdapterInstanceName
= AdapterName
;
2586 return NDIS_STATUS_SUCCESS
;
2594 NdisDeregisterAdapterShutdownHandler(
2595 IN NDIS_HANDLE NdisAdapterHandle
)
2603 NdisMDeregisterAdapterShutdownHandler(NdisAdapterHandle
);
2612 NdisRegisterAdapterShutdownHandler(
2613 IN NDIS_HANDLE NdisAdapterHandle
,
2614 IN PVOID ShutdownContext
,
2615 IN ADAPTER_SHUTDOWN_HANDLER ShutdownHandler
)
2623 NdisMRegisterAdapterShutdownHandler(NdisAdapterHandle
,
2633 NdisMGetDeviceProperty(
2634 IN NDIS_HANDLE MiniportAdapterHandle
,
2635 IN OUT PDEVICE_OBJECT
*PhysicalDeviceObject OPTIONAL
,
2636 IN OUT PDEVICE_OBJECT
*FunctionalDeviceObject OPTIONAL
,
2637 IN OUT PDEVICE_OBJECT
*NextDeviceObject OPTIONAL
,
2638 IN OUT PCM_RESOURCE_LIST
*AllocatedResources OPTIONAL
,
2639 IN OUT PCM_RESOURCE_LIST
*AllocatedResourcesTranslated OPTIONAL
)
2647 PLOGICAL_ADAPTER Adapter
= MiniportAdapterHandle
;
2649 NDIS_DbgPrint(MAX_TRACE
, ("Called\n"));
2651 if (PhysicalDeviceObject
!= NULL
)
2652 *PhysicalDeviceObject
= Adapter
->NdisMiniportBlock
.PhysicalDeviceObject
;
2654 if (FunctionalDeviceObject
!= NULL
)
2655 *FunctionalDeviceObject
= Adapter
->NdisMiniportBlock
.DeviceObject
;
2657 if (NextDeviceObject
!= NULL
)
2658 *NextDeviceObject
= Adapter
->NdisMiniportBlock
.NextDeviceObject
;
2660 if (AllocatedResources
!= NULL
)
2661 *AllocatedResources
= Adapter
->NdisMiniportBlock
.AllocatedResources
;
2663 if (AllocatedResourcesTranslated
!= NULL
)
2664 *AllocatedResourcesTranslated
= Adapter
->NdisMiniportBlock
.AllocatedResourcesTranslated
;