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
20 * Define to 1 to get a debugger breakpoint at the end of NdisInitializeWrapper
21 * for each new miniport starting up
23 #define BREAK_ON_MINIPORT_INIT 0
26 * This has to be big enough to hold the results of querying the Route value
27 * from the Linkage key. Please re-code me to determine this dynamically.
29 #define ROUTE_DATA_SIZE 256
31 /* Number of media we know */
32 #define MEDIA_ARRAY_SIZE 15
34 static NDIS_MEDIUM MediaArray
[MEDIA_ARRAY_SIZE
] =
43 NdisMediumArcnet878_2
,
45 NdisMediumWirelessWan
,
53 /* global list and lock of Miniports NDIS has registered */
54 LIST_ENTRY MiniportListHead
;
55 KSPIN_LOCK MiniportListLock
;
57 /* global list and lock of adapters NDIS has registered */
58 LIST_ENTRY AdapterListHead
;
59 KSPIN_LOCK AdapterListLock
;
68 if ((DebugTraceLevel
& DEBUG_PACKET
) > 0) {
69 Length
= CopyPacketToBuffer(
75 DbgPrint("*** PACKET START ***");
77 for (i
= 0; i
< Length
; i
++) {
79 DbgPrint("\n%04X ", i
);
80 DbgPrint("%02X ", Buffer
[i
]);
83 DbgPrint("*** PACKET STOP ***\n");
91 UINT HeaderBufferSize
,
92 PVOID LookaheadBuffer
,
93 UINT LookaheadBufferSize
)
96 if ((DebugTraceLevel
& DEBUG_PACKET
) > 0) {
100 DbgPrint("*** RECEIVE PACKET START ***\n");
103 for (i
= 0; i
< HeaderBufferSize
; i
++) {
105 DbgPrint("\n%04X ", i
);
106 DbgPrint("%02X ", *p
++);
109 DbgPrint("\nFRAME:");
112 Length
= (LookaheadBufferSize
< 64)? LookaheadBufferSize
: 64;
113 for (i
= 0; i
< Length
; i
++) {
115 DbgPrint("\n%04X ", i
);
116 DbgPrint("%02X ", *p
++);
119 DbgPrint("\n*** RECEIVE PACKET STOP ***\n");
124 PNDIS_MINIPORT_WORK_ITEM
125 MiniGetFirstWorkItem(
126 PLOGICAL_ADAPTER Adapter
,
127 NDIS_WORK_ITEM_TYPE Type
)
129 PNDIS_MINIPORT_WORK_ITEM CurrentEntry
= Adapter
->WorkQueueHead
;
133 if (CurrentEntry
->WorkItemType
== Type
)
136 CurrentEntry
= (PNDIS_MINIPORT_WORK_ITEM
)CurrentEntry
->Link
.Next
;
144 PLOGICAL_ADAPTER Adapter
,
145 NDIS_WORK_ITEM_TYPE Type
)
147 BOOLEAN Busy
= FALSE
;
150 KeAcquireSpinLock(&Adapter
->NdisMiniportBlock
.Lock
, &OldIrql
);
152 if (Type
== NdisWorkItemRequest
&&
153 (Adapter
->NdisMiniportBlock
.PendingRequest
|| MiniGetFirstWorkItem(Adapter
, NdisWorkItemRequest
)))
157 else if (Type
== NdisWorkItemSend
&&
158 (Adapter
->NdisMiniportBlock
.FirstPendingPacket
|| MiniGetFirstWorkItem(Adapter
, NdisWorkItemSend
)))
162 else if (Type
== NdisWorkItemResetRequested
&&
163 (Adapter
->NdisMiniportBlock
.ResetStatus
== NDIS_STATUS_PENDING
|| MiniGetFirstWorkItem(Adapter
, NdisWorkItemResetRequested
)))
168 KeReleaseSpinLock(&Adapter
->NdisMiniportBlock
.Lock
, OldIrql
);
176 PLOGICAL_ADAPTER Adapter
,
177 NDIS_HANDLE MacReceiveContext
,
179 UINT HeaderBufferSize
,
180 PVOID LookaheadBuffer
,
181 UINT LookaheadBufferSize
,
184 * FUNCTION: Indicate received data to bound protocols
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
196 PLIST_ENTRY CurrentEntry
;
197 PADAPTER_BINDING AdapterBinding
;
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
));
203 MiniDisplayPacket2(HeaderBuffer
, HeaderBufferSize
, LookaheadBuffer
, LookaheadBufferSize
);
205 NDIS_DbgPrint(MAX_TRACE
, ("acquiring miniport block lock\n"));
206 KeAcquireSpinLock(&Adapter
->NdisMiniportBlock
.Lock
, &OldIrql
);
208 CurrentEntry
= Adapter
->ProtocolListHead
.Flink
;
209 NDIS_DbgPrint(DEBUG_MINIPORT
, ("CurrentEntry = %x\n", CurrentEntry
));
211 if (CurrentEntry
== &Adapter
->ProtocolListHead
)
213 NDIS_DbgPrint(MIN_TRACE
, ("WARNING: No upper protocol layer.\n"));
216 while (CurrentEntry
!= &Adapter
->ProtocolListHead
)
218 AdapterBinding
= CONTAINING_RECORD(CurrentEntry
, ADAPTER_BINDING
, AdapterListEntry
);
219 NDIS_DbgPrint(DEBUG_MINIPORT
, ("AdapterBinding = %x\n", AdapterBinding
));
223 ("XXX (%x) %x %x %x %x %x %x %x XXX\n",
224 *AdapterBinding
->ProtocolBinding
->Chars
.ReceiveHandler
,
225 AdapterBinding
->NdisOpenBlock
.ProtocolBindingContext
,
233 /* call the receive handler */
234 (*AdapterBinding
->ProtocolBinding
->Chars
.ReceiveHandler
)(
235 AdapterBinding
->NdisOpenBlock
.ProtocolBindingContext
,
243 CurrentEntry
= CurrentEntry
->Flink
;
246 KeReleaseSpinLock(&Adapter
->NdisMiniportBlock
.Lock
, OldIrql
);
248 NDIS_DbgPrint(MAX_TRACE
, ("Leaving.\n"));
253 MiniIndicateReceivePacket(
254 IN NDIS_HANDLE MiniportAdapterHandle
,
255 IN PPNDIS_PACKET PacketArray
,
256 IN UINT NumberOfPackets
)
258 * FUNCTION: receives miniport packet array indications
260 * MiniportAdapterHandle: Miniport handle for the adapter
261 * PacketArray: pointer to a list of packet pointers to indicate
262 * NumberOfPackets: number of packets to indicate
266 PLOGICAL_ADAPTER Adapter
= MiniportAdapterHandle
;
267 PLIST_ENTRY CurrentEntry
;
268 PADAPTER_BINDING AdapterBinding
;
272 KeAcquireSpinLock(&Adapter
->NdisMiniportBlock
.Lock
, &OldIrql
);
274 CurrentEntry
= Adapter
->ProtocolListHead
.Flink
;
276 while (CurrentEntry
!= &Adapter
->ProtocolListHead
)
278 AdapterBinding
= CONTAINING_RECORD(CurrentEntry
, ADAPTER_BINDING
, AdapterListEntry
);
280 for (i
= 0; i
< NumberOfPackets
; i
++)
282 if (AdapterBinding
->ProtocolBinding
->Chars
.ReceivePacketHandler
&&
283 NDIS_GET_PACKET_STATUS(PacketArray
[i
]) != NDIS_STATUS_RESOURCES
)
285 (*AdapterBinding
->ProtocolBinding
->Chars
.ReceivePacketHandler
)(
286 AdapterBinding
->NdisOpenBlock
.ProtocolBindingContext
,
291 UINT FirstBufferLength
, TotalBufferLength
, LookAheadSize
, HeaderSize
;
292 PNDIS_BUFFER NdisBuffer
;
293 PVOID NdisBufferVA
, LookAheadBuffer
;
294 NDIS_STATUS NdisStatus
;
297 NdisGetFirstBufferFromPacket(PacketArray
[i
],
303 HeaderSize
= NDIS_GET_PACKET_HEADER_SIZE(PacketArray
[i
]);
305 if (Adapter
->NdisMiniportBlock
.CurrentLookahead
< (TotalBufferLength
- HeaderSize
))
307 LookAheadSize
= Adapter
->NdisMiniportBlock
.CurrentLookahead
;
311 LookAheadSize
= TotalBufferLength
- HeaderSize
;
315 LookAheadBuffer
= ExAllocatePool(NonPagedPool
, LookAheadSize
);
316 if (!LookAheadBuffer
)
318 NDIS_DbgPrint(MIN_TRACE
, ("Failed to allocate lookahead buffer!\n"));
322 CopyBufferChainToBuffer(LookAheadBuffer
,
327 NdisStatus
= (*AdapterBinding
->ProtocolBinding
->Chars
.ReceiveHandler
)(
328 AdapterBinding
->NdisOpenBlock
.ProtocolBindingContext
,
329 AdapterBinding
->NdisOpenBlock
.MacHandle
,
334 TotalBufferLength
- HeaderSize
);
336 NDIS_SET_PACKET_STATUS(PacketArray
[i
], NdisStatus
);
338 ExFreePool(LookAheadBuffer
);
342 CurrentEntry
= CurrentEntry
->Flink
;
345 KeReleaseSpinLock(&Adapter
->NdisMiniportBlock
.Lock
, OldIrql
);
351 IN NDIS_HANDLE MiniportAdapterHandle
,
352 IN NDIS_STATUS Status
,
353 IN BOOLEAN AddressingReset
)
355 PLOGICAL_ADAPTER Adapter
= MiniportAdapterHandle
;
356 PLIST_ENTRY CurrentEntry
;
357 PADAPTER_BINDING AdapterBinding
;
361 MiniDoAddressingReset(Adapter
);
363 NdisMIndicateStatus(Adapter
, NDIS_STATUS_RESET_END
, NULL
, 0);
364 NdisMIndicateStatusComplete(Adapter
);
366 KeAcquireSpinLock(&Adapter
->NdisMiniportBlock
.Lock
, &OldIrql
);
368 if (Adapter
->NdisMiniportBlock
.ResetStatus
!= NDIS_STATUS_PENDING
)
370 KeBugCheckEx(BUGCODE_ID_DRIVER
,
371 (ULONG_PTR
)MiniportAdapterHandle
,
373 (ULONG_PTR
)AddressingReset
,
377 Adapter
->NdisMiniportBlock
.ResetStatus
= Status
;
379 CurrentEntry
= Adapter
->ProtocolListHead
.Flink
;
381 while (CurrentEntry
!= &Adapter
->ProtocolListHead
)
383 AdapterBinding
= CONTAINING_RECORD(CurrentEntry
, ADAPTER_BINDING
, AdapterListEntry
);
385 (*AdapterBinding
->ProtocolBinding
->Chars
.ResetCompleteHandler
)(
386 AdapterBinding
->NdisOpenBlock
.ProtocolBindingContext
,
389 CurrentEntry
= CurrentEntry
->Flink
;
392 KeReleaseSpinLock(&Adapter
->NdisMiniportBlock
.Lock
, OldIrql
);
397 IN NDIS_HANDLE MiniportAdapterHandle
,
398 IN NDIS_STATUS Status
)
400 PLOGICAL_ADAPTER Adapter
= (PLOGICAL_ADAPTER
)MiniportAdapterHandle
;
401 PNDIS_REQUEST Request
;
402 PNDIS_REQUEST_MAC_BLOCK MacBlock
;
405 NDIS_DbgPrint(DEBUG_MINIPORT
, ("Called.\n"));
407 KeRaiseIrql(DISPATCH_LEVEL
, &OldIrql
);
409 KeAcquireSpinLockAtDpcLevel(&Adapter
->NdisMiniportBlock
.Lock
);
410 Request
= Adapter
->NdisMiniportBlock
.PendingRequest
;
411 KeReleaseSpinLockFromDpcLevel(&Adapter
->NdisMiniportBlock
.Lock
);
413 MacBlock
= (PNDIS_REQUEST_MAC_BLOCK
)Request
->MacReserved
;
415 if( MacBlock
->Binding
->RequestCompleteHandler
) {
416 (*MacBlock
->Binding
->RequestCompleteHandler
)(
417 MacBlock
->Binding
->ProtocolBindingContext
,
422 KeAcquireSpinLockAtDpcLevel(&Adapter
->NdisMiniportBlock
.Lock
);
423 Adapter
->NdisMiniportBlock
.PendingRequest
= NULL
;
424 KeReleaseSpinLockFromDpcLevel(&Adapter
->NdisMiniportBlock
.Lock
);
426 KeLowerIrql(OldIrql
);
431 IN NDIS_HANDLE MiniportAdapterHandle
,
432 IN PNDIS_PACKET Packet
,
433 IN NDIS_STATUS Status
)
435 * FUNCTION: Forwards a message to the initiating protocol saying
436 * that a packet was handled
438 * NdisAdapterHandle = Handle input to MiniportInitialize
439 * Packet = Pointer to NDIS packet that was sent
440 * Status = Status of send operation
443 PLOGICAL_ADAPTER Adapter
= MiniportAdapterHandle
;
444 PADAPTER_BINDING AdapterBinding
;
446 PSCATTER_GATHER_LIST SGList
;
448 NDIS_DbgPrint(DEBUG_MINIPORT
, ("Called.\n"));
450 AdapterBinding
= (PADAPTER_BINDING
)Packet
->Reserved
[1];
452 KeRaiseIrql(DISPATCH_LEVEL
, &OldIrql
);
454 if (Adapter
->NdisMiniportBlock
.ScatterGatherListSize
!= 0)
456 NDIS_DbgPrint(MAX_TRACE
, ("Freeing Scatter/Gather list\n"));
458 SGList
= NDIS_PER_PACKET_INFO_FROM_PACKET(Packet
,
459 ScatterGatherListPacketInfo
);
461 Adapter
->NdisMiniportBlock
.SystemAdapterObject
->
462 DmaOperations
->PutScatterGatherList(
463 Adapter
->NdisMiniportBlock
.SystemAdapterObject
,
467 NDIS_PER_PACKET_INFO_FROM_PACKET(Packet
,
468 ScatterGatherListPacketInfo
) = NULL
;
471 (*AdapterBinding
->ProtocolBinding
->Chars
.SendCompleteHandler
)(
472 AdapterBinding
->NdisOpenBlock
.ProtocolBindingContext
,
476 KeLowerIrql(OldIrql
);
481 MiniSendResourcesAvailable(
482 IN NDIS_HANDLE MiniportAdapterHandle
)
491 MiniTransferDataComplete(
492 IN NDIS_HANDLE MiniportAdapterHandle
,
493 IN PNDIS_PACKET Packet
,
494 IN NDIS_STATUS Status
,
495 IN UINT BytesTransferred
)
497 PADAPTER_BINDING AdapterBinding
;
500 NDIS_DbgPrint(DEBUG_MINIPORT
, ("Called.\n"));
502 AdapterBinding
= (PADAPTER_BINDING
)Packet
->Reserved
[1];
504 KeRaiseIrql(DISPATCH_LEVEL
, &OldIrql
);
505 (*AdapterBinding
->ProtocolBinding
->Chars
.TransferDataCompleteHandler
)(
506 AdapterBinding
->NdisOpenBlock
.ProtocolBindingContext
,
510 KeLowerIrql(OldIrql
);
515 MiniAdapterHasAddress(
516 PLOGICAL_ADAPTER Adapter
,
519 * FUNCTION: Determines whether a packet has the same destination address as an adapter
521 * Adapter = Pointer to logical adapter object
522 * Packet = Pointer to NDIS packet
524 * TRUE if the destination address is that of the adapter, FALSE if not
530 PNDIS_BUFFER NdisBuffer
;
533 NDIS_DbgPrint(DEBUG_MINIPORT
, ("Called.\n"));
538 NDIS_DbgPrint(MIN_TRACE
, ("Adapter object was null\n"));
544 NDIS_DbgPrint(MIN_TRACE
, ("Packet was null\n"));
549 NdisQueryPacket(Packet
, NULL
, NULL
, &NdisBuffer
, NULL
);
553 NDIS_DbgPrint(MIN_TRACE
, ("Packet contains no buffers.\n"));
557 NdisQueryBuffer(NdisBuffer
, (PVOID
)&Start2
, &BufferLength
);
559 /* FIXME: Should handle fragmented packets */
561 switch (Adapter
->NdisMiniportBlock
.MediaType
)
563 case NdisMedium802_3
:
564 Length
= ETH_LENGTH_OF_ADDRESS
;
565 /* Destination address is the first field */
569 NDIS_DbgPrint(MIN_TRACE
, ("Adapter has unsupported media type (0x%X).\n", Adapter
->NdisMiniportBlock
.MediaType
));
573 if (BufferLength
< Length
)
575 NDIS_DbgPrint(MIN_TRACE
, ("Buffer is too small.\n"));
579 Start1
= (PUCHAR
)&Adapter
->Address
;
580 NDIS_DbgPrint(MAX_TRACE
, ("packet address: %x:%x:%x:%x:%x:%x adapter address: %x:%x:%x:%x:%x:%x\n",
581 *((char *)Start1
), *(((char *)Start1
)+1), *(((char *)Start1
)+2), *(((char *)Start1
)+3), *(((char *)Start1
)+4), *(((char *)Start1
)+5),
582 *((char *)Start2
), *(((char *)Start2
)+1), *(((char *)Start2
)+2), *(((char *)Start2
)+3), *(((char *)Start2
)+4), *(((char *)Start2
)+5))
585 return (RtlCompareMemory((PVOID
)Start1
, (PVOID
)Start2
, Length
) == Length
);
591 PNDIS_STRING AdapterName
)
593 * FUNCTION: Finds an adapter object by name
595 * AdapterName = Pointer to name of adapter
597 * Pointer to logical adapter object, or NULL if none was found.
598 * If found, the adapter is referenced for the caller. The caller
599 * is responsible for dereferencing after use
603 PLIST_ENTRY CurrentEntry
;
604 PLOGICAL_ADAPTER Adapter
= 0;
608 NDIS_DbgPrint(DEBUG_MINIPORT
, ("Called.\n"));
610 if(IsListEmpty(&AdapterListHead
))
612 NDIS_DbgPrint(MIN_TRACE
, ("No registered miniports for protocol to bind to\n"));
616 KeAcquireSpinLock(&AdapterListLock
, &OldIrql
);
618 CurrentEntry
= AdapterListHead
.Flink
;
620 while (CurrentEntry
!= &AdapterListHead
)
622 Adapter
= CONTAINING_RECORD(CurrentEntry
, LOGICAL_ADAPTER
, ListEntry
);
626 NDIS_DbgPrint(DEBUG_MINIPORT
, ("Examining adapter 0x%lx\n", Adapter
));
627 NDIS_DbgPrint(DEBUG_MINIPORT
, ("AdapterName = %wZ\n", AdapterName
));
628 NDIS_DbgPrint(DEBUG_MINIPORT
, ("DeviceName = %wZ\n", &Adapter
->NdisMiniportBlock
.MiniportName
));
630 if (RtlCompareUnicodeString(AdapterName
, &Adapter
->NdisMiniportBlock
.MiniportName
, TRUE
) == 0)
636 CurrentEntry
= CurrentEntry
->Flink
;
639 KeReleaseSpinLock(&AdapterListLock
, OldIrql
);
643 NDIS_DbgPrint(DEBUG_MINIPORT
, ("Leaving. Adapter found at 0x%x\n", Adapter
));
647 NDIS_DbgPrint(MIN_TRACE
, ("Leaving (adapter not found for %wZ).\n", AdapterName
));
655 PLOGICAL_ADAPTER Adapter
,
661 NDIS_STATUS NdisStatus
;
662 PNDIS_REQUEST NdisRequest
;
664 NDIS_DbgPrint(DEBUG_MINIPORT
, ("Called.\n"));
666 NdisRequest
= ExAllocatePool(NonPagedPool
, sizeof(NDIS_REQUEST
));
668 NDIS_DbgPrint(MIN_TRACE
, ("Insufficient resources\n"));
669 return NDIS_STATUS_RESOURCES
;
672 RtlZeroMemory(NdisRequest
, sizeof(NDIS_REQUEST
));
674 NdisRequest
->RequestType
= NdisRequestSetInformation
;
675 NdisRequest
->DATA
.SET_INFORMATION
.Oid
= Oid
;
676 NdisRequest
->DATA
.SET_INFORMATION
.InformationBuffer
= Buffer
;
677 NdisRequest
->DATA
.SET_INFORMATION
.InformationBufferLength
= Size
;
679 NdisStatus
= MiniDoRequest(Adapter
, NdisRequest
);
681 /* FIXME: Wait in pending case! */
683 ASSERT(NdisStatus
!= NDIS_STATUS_PENDING
);
685 *BytesRead
= NdisRequest
->DATA
.SET_INFORMATION
.BytesRead
;
687 ExFreePool(NdisRequest
);
693 MiniQueryInformation(
694 PLOGICAL_ADAPTER Adapter
,
700 * FUNCTION: Queries a logical adapter for properties
702 * Adapter = Pointer to the logical adapter object to query
703 * Oid = Specifies the Object ID to query for
704 * Size = Size of the passed buffer
705 * Buffer = Buffer for the output
706 * BytesWritten = Address of buffer to place number of bytes written
708 * Status of operation
711 NDIS_STATUS NdisStatus
;
712 PNDIS_REQUEST NdisRequest
;
714 NDIS_DbgPrint(DEBUG_MINIPORT
, ("Called.\n"));
716 NdisRequest
= ExAllocatePool(NonPagedPool
, sizeof(NDIS_REQUEST
));
718 NDIS_DbgPrint(MIN_TRACE
, ("Insufficient resources\n"));
719 return NDIS_STATUS_RESOURCES
;
722 RtlZeroMemory(NdisRequest
, sizeof(NDIS_REQUEST
));
724 NdisRequest
->RequestType
= NdisRequestQueryInformation
;
725 NdisRequest
->DATA
.QUERY_INFORMATION
.Oid
= Oid
;
726 NdisRequest
->DATA
.QUERY_INFORMATION
.InformationBuffer
= Buffer
;
727 NdisRequest
->DATA
.QUERY_INFORMATION
.InformationBufferLength
= Size
;
729 NdisStatus
= MiniDoRequest(Adapter
, NdisRequest
);
731 /* FIXME: Wait in pending case! */
733 ASSERT(NdisStatus
!= NDIS_STATUS_PENDING
);
735 *BytesWritten
= NdisRequest
->DATA
.QUERY_INFORMATION
.BytesWritten
;
737 ExFreePool(NdisRequest
);
743 MiniCheckForHang( PLOGICAL_ADAPTER Adapter
)
745 * FUNCTION: Checks to see if the miniport is hung
747 * Adapter = Pointer to the logical adapter object
749 * TRUE if the miniport is hung
750 * FALSE if the miniport is not hung
756 KeRaiseIrql(DISPATCH_LEVEL
, &OldIrql
);
757 if (Adapter
->NdisMiniportBlock
.DriverHandle
->MiniportCharacteristics
.CheckForHangHandler
)
758 Ret
= (*Adapter
->NdisMiniportBlock
.DriverHandle
->MiniportCharacteristics
.CheckForHangHandler
)(
759 Adapter
->NdisMiniportBlock
.MiniportAdapterContext
);
760 KeLowerIrql(OldIrql
);
766 MiniDoAddressingReset(PLOGICAL_ADAPTER Adapter
)
770 MiniSetInformation(Adapter
,
771 OID_GEN_CURRENT_LOOKAHEAD
,
773 &Adapter
->NdisMiniportBlock
.CurrentLookahead
,
776 /* FIXME: Set more stuff */
781 PLOGICAL_ADAPTER Adapter
)
783 * FUNCTION: Resets the miniport
785 * Adapter = Pointer to the logical adapter object
787 * Status of the operation
792 BOOLEAN AddressingReset
= TRUE
;
794 if (MiniIsBusy(Adapter
, NdisWorkItemResetRequested
)) {
795 MiniQueueWorkItem(Adapter
, NdisWorkItemResetRequested
, NULL
, FALSE
);
796 return NDIS_STATUS_PENDING
;
799 NdisMIndicateStatus(Adapter
, NDIS_STATUS_RESET_START
, NULL
, 0);
800 NdisMIndicateStatusComplete(Adapter
);
802 KeRaiseIrql(DISPATCH_LEVEL
, &OldIrql
);
803 Status
= (*Adapter
->NdisMiniportBlock
.DriverHandle
->MiniportCharacteristics
.ResetHandler
)(
804 Adapter
->NdisMiniportBlock
.MiniportAdapterContext
,
807 KeAcquireSpinLockAtDpcLevel(&Adapter
->NdisMiniportBlock
.Lock
);
808 Adapter
->NdisMiniportBlock
.ResetStatus
= Status
;
809 KeReleaseSpinLockFromDpcLevel(&Adapter
->NdisMiniportBlock
.Lock
);
811 KeLowerIrql(OldIrql
);
813 if (Status
!= NDIS_STATUS_PENDING
) {
815 MiniDoAddressingReset(Adapter
);
817 NdisMIndicateStatus(Adapter
, NDIS_STATUS_RESET_END
, NULL
, 0);
818 NdisMIndicateStatusComplete(Adapter
);
827 PVOID DeferredContext
,
828 PVOID SystemArgument1
,
829 PVOID SystemArgument2
)
831 PLOGICAL_ADAPTER Adapter
= DeferredContext
;
833 if (MiniCheckForHang(Adapter
)) {
834 NDIS_DbgPrint(MIN_TRACE
, ("Miniport detected adapter hang\n"));
843 PLOGICAL_ADAPTER Adapter
,
844 NDIS_WORK_ITEM_TYPE WorkItemType
,
845 PVOID WorkItemContext
,
848 * FUNCTION: Queues a work item for execution at a later time
850 * Adapter = Pointer to the logical adapter object to queue work item on
851 * WorkItemType = Type of work item to queue
852 * WorkItemContext = Pointer to context information for work item
854 * Status of operation
857 PNDIS_MINIPORT_WORK_ITEM MiniportWorkItem
;
858 PIO_WORKITEM IoWorkItem
;
861 NDIS_DbgPrint(MAX_TRACE
, ("Called.\n"));
865 KeAcquireSpinLock(&Adapter
->NdisMiniportBlock
.Lock
, &OldIrql
);
868 if (WorkItemType
== NdisWorkItemSend
)
870 NDIS_DbgPrint(MIN_TRACE
, ("Requeuing failed packet (%x).\n", WorkItemContext
));
871 Adapter
->NdisMiniportBlock
.FirstPendingPacket
= WorkItemContext
;
875 //This should never happen
881 MiniportWorkItem
= ExAllocatePool(NonPagedPool
, sizeof(NDIS_MINIPORT_WORK_ITEM
));
882 if (!MiniportWorkItem
)
884 KeReleaseSpinLock(&Adapter
->NdisMiniportBlock
.Lock
, OldIrql
);
885 NDIS_DbgPrint(MIN_TRACE
, ("Insufficient resources.\n"));
889 MiniportWorkItem
->WorkItemType
= WorkItemType
;
890 MiniportWorkItem
->WorkItemContext
= WorkItemContext
;
892 /* safe due to adapter lock held */
893 MiniportWorkItem
->Link
.Next
= NULL
;
894 if (!Adapter
->WorkQueueHead
)
896 Adapter
->WorkQueueHead
= MiniportWorkItem
;
897 Adapter
->WorkQueueTail
= MiniportWorkItem
;
901 Adapter
->WorkQueueTail
->Link
.Next
= (PSINGLE_LIST_ENTRY
)MiniportWorkItem
;
902 Adapter
->WorkQueueTail
= MiniportWorkItem
;
906 IoWorkItem
= IoAllocateWorkItem(Adapter
->NdisMiniportBlock
.DeviceObject
);
908 IoQueueWorkItem(IoWorkItem
, MiniportWorker
, DelayedWorkQueue
, IoWorkItem
);
910 KeReleaseSpinLock(&Adapter
->NdisMiniportBlock
.Lock
, OldIrql
);
917 PLOGICAL_ADAPTER Adapter
,
918 NDIS_WORK_ITEM_TYPE
*WorkItemType
,
919 PVOID
*WorkItemContext
)
921 * FUNCTION: Dequeues a work item from the work queue of a logical adapter
923 * Adapter = Pointer to the logical adapter object to dequeue work item from
924 * AdapterBinding = Address of buffer for adapter binding for this request
925 * WorkItemType = Address of buffer for work item type
926 * WorkItemContext = Address of buffer for pointer to context information
928 * Adapter lock must be held when called
930 * Status of operation
933 PNDIS_MINIPORT_WORK_ITEM MiniportWorkItem
;
936 NDIS_DbgPrint(MAX_TRACE
, ("Called.\n"));
938 MiniportWorkItem
= Adapter
->WorkQueueHead
;
940 if ((Packet
= Adapter
->NdisMiniportBlock
.FirstPendingPacket
))
942 Adapter
->NdisMiniportBlock
.FirstPendingPacket
= NULL
;
944 *WorkItemType
= NdisWorkItemSend
;
945 *WorkItemContext
= Packet
;
947 return NDIS_STATUS_SUCCESS
;
949 else if (MiniportWorkItem
)
951 /* safe due to adapter lock held */
952 Adapter
->WorkQueueHead
= (PNDIS_MINIPORT_WORK_ITEM
)MiniportWorkItem
->Link
.Next
;
954 if (MiniportWorkItem
== Adapter
->WorkQueueTail
)
955 Adapter
->WorkQueueTail
= NULL
;
957 *WorkItemType
= MiniportWorkItem
->WorkItemType
;
958 *WorkItemContext
= MiniportWorkItem
->WorkItemContext
;
960 ExFreePool(MiniportWorkItem
);
962 return NDIS_STATUS_SUCCESS
;
966 NDIS_DbgPrint(MIN_TRACE
, ("No work item to dequeue\n"));
968 return NDIS_STATUS_FAILURE
;
975 PLOGICAL_ADAPTER Adapter
,
976 PNDIS_REQUEST NdisRequest
)
978 * FUNCTION: Sends a request to a miniport
980 * AdapterBinding = Pointer to binding used in the request
981 * NdisRequest = Pointer to NDIS request structure describing request
983 * Status of operation
988 NDIS_DbgPrint(DEBUG_MINIPORT
, ("Called.\n"));
990 KeRaiseIrql(DISPATCH_LEVEL
, &OldIrql
);
992 KeAcquireSpinLockAtDpcLevel(&Adapter
->NdisMiniportBlock
.Lock
);
993 Adapter
->NdisMiniportBlock
.PendingRequest
= NdisRequest
;
994 KeReleaseSpinLockFromDpcLevel(&Adapter
->NdisMiniportBlock
.Lock
);
996 if (!Adapter
->NdisMiniportBlock
.DriverHandle
->MiniportCharacteristics
.CoRequestHandler
)
998 switch (NdisRequest
->RequestType
)
1000 case NdisRequestQueryInformation
:
1001 Status
= (*Adapter
->NdisMiniportBlock
.DriverHandle
->MiniportCharacteristics
.QueryInformationHandler
)(
1002 Adapter
->NdisMiniportBlock
.MiniportAdapterContext
,
1003 NdisRequest
->DATA
.QUERY_INFORMATION
.Oid
,
1004 NdisRequest
->DATA
.QUERY_INFORMATION
.InformationBuffer
,
1005 NdisRequest
->DATA
.QUERY_INFORMATION
.InformationBufferLength
,
1006 (PULONG
)&NdisRequest
->DATA
.QUERY_INFORMATION
.BytesWritten
,
1007 (PULONG
)&NdisRequest
->DATA
.QUERY_INFORMATION
.BytesNeeded
);
1010 case NdisRequestSetInformation
:
1011 Status
= (*Adapter
->NdisMiniportBlock
.DriverHandle
->MiniportCharacteristics
.SetInformationHandler
)(
1012 Adapter
->NdisMiniportBlock
.MiniportAdapterContext
,
1013 NdisRequest
->DATA
.SET_INFORMATION
.Oid
,
1014 NdisRequest
->DATA
.SET_INFORMATION
.InformationBuffer
,
1015 NdisRequest
->DATA
.SET_INFORMATION
.InformationBufferLength
,
1016 (PULONG
)&NdisRequest
->DATA
.SET_INFORMATION
.BytesRead
,
1017 (PULONG
)&NdisRequest
->DATA
.SET_INFORMATION
.BytesNeeded
);
1021 NDIS_DbgPrint(MIN_TRACE
, ("Bad request type\n"));
1022 Status
= NDIS_STATUS_FAILURE
;
1027 Status
= (*Adapter
->NdisMiniportBlock
.DriverHandle
->MiniportCharacteristics
.CoRequestHandler
)(
1028 Adapter
->NdisMiniportBlock
.MiniportAdapterContext
,
1033 if (Status
!= NDIS_STATUS_PENDING
) {
1034 KeAcquireSpinLockAtDpcLevel(&Adapter
->NdisMiniportBlock
.Lock
);
1035 Adapter
->NdisMiniportBlock
.PendingRequest
= NULL
;
1036 KeReleaseSpinLockFromDpcLevel(&Adapter
->NdisMiniportBlock
.Lock
);
1039 KeLowerIrql(OldIrql
);
1047 #undef NdisMSetInformationComplete
1050 NdisMSetInformationComplete(
1051 IN NDIS_HANDLE MiniportAdapterHandle
,
1052 IN NDIS_STATUS Status
)
1054 PLOGICAL_ADAPTER Adapter
=
1055 (PLOGICAL_ADAPTER
)MiniportAdapterHandle
;
1058 KeRaiseIrql(DISPATCH_LEVEL
, &OldIrql
);
1059 if (Adapter
->NdisMiniportBlock
.SetCompleteHandler
)
1060 (Adapter
->NdisMiniportBlock
.SetCompleteHandler
)(MiniportAdapterHandle
, Status
);
1061 KeLowerIrql(OldIrql
);
1068 #undef NdisMQueryInformationComplete
1071 NdisMQueryInformationComplete(
1072 IN NDIS_HANDLE MiniportAdapterHandle
,
1073 IN NDIS_STATUS Status
)
1075 PLOGICAL_ADAPTER Adapter
=
1076 (PLOGICAL_ADAPTER
)MiniportAdapterHandle
;
1079 KeRaiseIrql(DISPATCH_LEVEL
, &OldIrql
);
1080 if( Adapter
->NdisMiniportBlock
.QueryCompleteHandler
)
1081 (Adapter
->NdisMiniportBlock
.QueryCompleteHandler
)(MiniportAdapterHandle
, Status
);
1082 KeLowerIrql(OldIrql
);
1087 MiniportWorker(IN PDEVICE_OBJECT DeviceObject
, IN PVOID Context
)
1089 PLOGICAL_ADAPTER Adapter
= DeviceObject
->DeviceExtension
;
1090 KIRQL OldIrql
, RaiseOldIrql
;
1091 NDIS_STATUS NdisStatus
;
1092 PVOID WorkItemContext
;
1093 NDIS_WORK_ITEM_TYPE WorkItemType
;
1094 BOOLEAN AddressingReset
;
1096 IoFreeWorkItem((PIO_WORKITEM
)Context
);
1098 KeAcquireSpinLock(&Adapter
->NdisMiniportBlock
.Lock
, &OldIrql
);
1102 (Adapter
, &WorkItemType
, &WorkItemContext
);
1104 KeReleaseSpinLock(&Adapter
->NdisMiniportBlock
.Lock
, OldIrql
);
1106 if (NdisStatus
== NDIS_STATUS_SUCCESS
)
1108 switch (WorkItemType
)
1110 case NdisWorkItemSend
:
1112 * called by ProSend when protocols want to send packets to the miniport
1115 if(Adapter
->NdisMiniportBlock
.DriverHandle
->MiniportCharacteristics
.SendPacketsHandler
)
1117 if(Adapter
->NdisMiniportBlock
.Flags
& NDIS_ATTRIBUTE_DESERIALIZE
)
1119 NDIS_DbgPrint(MAX_TRACE
, ("Calling miniport's SendPackets handler\n"));
1120 (*Adapter
->NdisMiniportBlock
.DriverHandle
->MiniportCharacteristics
.SendPacketsHandler
)(
1121 Adapter
->NdisMiniportBlock
.MiniportAdapterContext
, (PPNDIS_PACKET
)&WorkItemContext
, 1);
1122 NdisStatus
= NDIS_STATUS_PENDING
;
1126 /* SendPackets is called at DISPATCH_LEVEL for all serialized miniports */
1127 KeRaiseIrql(DISPATCH_LEVEL
, &RaiseOldIrql
);
1129 NDIS_DbgPrint(MAX_TRACE
, ("Calling miniport's SendPackets handler\n"));
1130 (*Adapter
->NdisMiniportBlock
.DriverHandle
->MiniportCharacteristics
.SendPacketsHandler
)(
1131 Adapter
->NdisMiniportBlock
.MiniportAdapterContext
, (PPNDIS_PACKET
)&WorkItemContext
, 1);
1133 KeLowerIrql(RaiseOldIrql
);
1135 NdisStatus
= NDIS_GET_PACKET_STATUS((PNDIS_PACKET
)WorkItemContext
);
1136 if( NdisStatus
== NDIS_STATUS_RESOURCES
) {
1137 MiniQueueWorkItem(Adapter
, WorkItemType
, WorkItemContext
, TRUE
);
1144 if(Adapter
->NdisMiniportBlock
.Flags
& NDIS_ATTRIBUTE_DESERIALIZE
)
1146 NDIS_DbgPrint(MAX_TRACE
, ("Calling miniport's Send handler\n"));
1147 NdisStatus
= (*Adapter
->NdisMiniportBlock
.DriverHandle
->MiniportCharacteristics
.SendHandler
)(
1148 Adapter
->NdisMiniportBlock
.MiniportAdapterContext
, (PNDIS_PACKET
)WorkItemContext
,
1149 ((PNDIS_PACKET
)WorkItemContext
)->Private
.Flags
);
1150 NDIS_DbgPrint(MAX_TRACE
, ("back from miniport's send handler\n"));
1154 /* Send is called at DISPATCH_LEVEL for all serialized miniports */
1155 KeRaiseIrql(DISPATCH_LEVEL
, &RaiseOldIrql
);
1156 NDIS_DbgPrint(MAX_TRACE
, ("Calling miniport's Send handler\n"));
1157 NdisStatus
= (*Adapter
->NdisMiniportBlock
.DriverHandle
->MiniportCharacteristics
.SendHandler
)(
1158 Adapter
->NdisMiniportBlock
.MiniportAdapterContext
, (PNDIS_PACKET
)WorkItemContext
,
1159 ((PNDIS_PACKET
)WorkItemContext
)->Private
.Flags
);
1160 NDIS_DbgPrint(MAX_TRACE
, ("back from miniport's send handler\n"));
1161 KeLowerIrql(RaiseOldIrql
);
1162 if( NdisStatus
== NDIS_STATUS_RESOURCES
) {
1163 MiniQueueWorkItem(Adapter
, WorkItemType
, WorkItemContext
, TRUE
);
1169 if( NdisStatus
!= NDIS_STATUS_PENDING
) {
1171 ( Adapter
, (PNDIS_PACKET
)WorkItemContext
, NdisStatus
);
1175 case NdisWorkItemSendLoopback
:
1177 * called by ProSend when protocols want to send loopback packets
1179 /* XXX atm ProIndicatePacket sends a packet up via the loopback adapter only */
1180 NdisStatus
= ProIndicatePacket(Adapter
, (PNDIS_PACKET
)WorkItemContext
);
1182 if( NdisStatus
!= NDIS_STATUS_PENDING
)
1183 MiniSendComplete((NDIS_HANDLE
)Adapter
, (PNDIS_PACKET
)WorkItemContext
, NdisStatus
);
1186 case NdisWorkItemReturnPackets
:
1189 case NdisWorkItemResetRequested
:
1190 NdisMIndicateStatus(Adapter
, NDIS_STATUS_RESET_START
, NULL
, 0);
1191 NdisMIndicateStatusComplete(Adapter
);
1193 KeRaiseIrql(DISPATCH_LEVEL
, &OldIrql
);
1194 NdisStatus
= (*Adapter
->NdisMiniportBlock
.DriverHandle
->MiniportCharacteristics
.ResetHandler
)(
1195 Adapter
->NdisMiniportBlock
.MiniportAdapterContext
,
1198 KeAcquireSpinLockAtDpcLevel(&Adapter
->NdisMiniportBlock
.Lock
);
1199 Adapter
->NdisMiniportBlock
.ResetStatus
= NdisStatus
;
1200 KeReleaseSpinLockFromDpcLevel(&Adapter
->NdisMiniportBlock
.Lock
);
1202 KeLowerIrql(OldIrql
);
1204 if (NdisStatus
!= NDIS_STATUS_PENDING
)
1205 MiniResetComplete(Adapter
, NdisStatus
, AddressingReset
);
1208 case NdisWorkItemResetInProgress
:
1211 case NdisWorkItemMiniportCallback
:
1214 case NdisWorkItemRequest
:
1215 NdisStatus
= MiniDoRequest(Adapter
, (PNDIS_REQUEST
)WorkItemContext
);
1217 if (NdisStatus
== NDIS_STATUS_PENDING
)
1220 switch (((PNDIS_REQUEST
)WorkItemContext
)->RequestType
)
1222 case NdisRequestQueryInformation
:
1223 NdisMQueryInformationComplete((NDIS_HANDLE
)Adapter
, NdisStatus
);
1226 case NdisRequestSetInformation
:
1227 NdisMSetInformationComplete((NDIS_HANDLE
)Adapter
, NdisStatus
);
1231 NDIS_DbgPrint(MIN_TRACE
, ("Unknown NDIS request type.\n"));
1237 NDIS_DbgPrint(MIN_TRACE
, ("Unknown NDIS work item type (%d).\n", WorkItemType
));
1248 IN NDIS_HANDLE MiniportHandle
,
1249 IN NDIS_STATUS GeneralStatus
,
1250 IN PVOID StatusBuffer
,
1251 IN UINT StatusBufferSize
)
1253 PLOGICAL_ADAPTER Adapter
= MiniportHandle
;
1254 PLIST_ENTRY CurrentEntry
;
1255 PADAPTER_BINDING AdapterBinding
;
1258 KeAcquireSpinLock(&Adapter
->NdisMiniportBlock
.Lock
, &OldIrql
);
1260 CurrentEntry
= Adapter
->ProtocolListHead
.Flink
;
1262 while (CurrentEntry
!= &Adapter
->ProtocolListHead
)
1264 AdapterBinding
= CONTAINING_RECORD(CurrentEntry
, ADAPTER_BINDING
, AdapterListEntry
);
1266 (*AdapterBinding
->ProtocolBinding
->Chars
.StatusHandler
)(
1267 AdapterBinding
->NdisOpenBlock
.ProtocolBindingContext
,
1272 CurrentEntry
= CurrentEntry
->Flink
;
1275 KeReleaseSpinLock(&Adapter
->NdisMiniportBlock
.Lock
, OldIrql
);
1282 IN NDIS_HANDLE MiniportAdapterHandle
)
1284 PLOGICAL_ADAPTER Adapter
= MiniportAdapterHandle
;
1285 PLIST_ENTRY CurrentEntry
;
1286 PADAPTER_BINDING AdapterBinding
;
1289 KeAcquireSpinLock(&Adapter
->NdisMiniportBlock
.Lock
, &OldIrql
);
1291 CurrentEntry
= Adapter
->ProtocolListHead
.Flink
;
1293 while (CurrentEntry
!= &Adapter
->ProtocolListHead
)
1295 AdapterBinding
= CONTAINING_RECORD(CurrentEntry
, ADAPTER_BINDING
, AdapterListEntry
);
1297 (*AdapterBinding
->ProtocolBinding
->Chars
.StatusCompleteHandler
)(
1298 AdapterBinding
->NdisOpenBlock
.ProtocolBindingContext
);
1300 CurrentEntry
= CurrentEntry
->Flink
;
1303 KeReleaseSpinLock(&Adapter
->NdisMiniportBlock
.Lock
, OldIrql
);
1313 IN NDIS_HANDLE LogHandle
)
1315 PNDIS_LOG Log
= (PNDIS_LOG
)LogHandle
;
1316 PNDIS_MINIPORT_BLOCK Miniport
= Log
->Miniport
;
1319 NDIS_DbgPrint(MAX_TRACE
, ("called: LogHandle 0x%x\n", LogHandle
));
1321 KeAcquireSpinLock(&(Miniport
)->Lock
, &OldIrql
);
1322 Miniport
->Log
= NULL
;
1323 KeReleaseSpinLock(&(Miniport
)->Lock
, OldIrql
);
1334 IN NDIS_HANDLE MiniportAdapterHandle
,
1336 OUT PNDIS_HANDLE LogHandle
)
1338 PLOGICAL_ADAPTER Adapter
= MiniportAdapterHandle
;
1342 NDIS_DbgPrint(MAX_TRACE
, ("called: MiniportAdapterHandle 0x%x, Size %ld\n", MiniportAdapterHandle
, Size
));
1344 KeAcquireSpinLock(&Adapter
->NdisMiniportBlock
.Lock
, &OldIrql
);
1346 if (Adapter
->NdisMiniportBlock
.Log
)
1349 return NDIS_STATUS_FAILURE
;
1352 Log
= ExAllocatePool(NonPagedPool
, Size
+ sizeof(NDIS_LOG
));
1356 return NDIS_STATUS_RESOURCES
;
1359 Adapter
->NdisMiniportBlock
.Log
= Log
;
1361 KeInitializeSpinLock(&Log
->LogLock
);
1363 Log
->Miniport
= &Adapter
->NdisMiniportBlock
;
1364 Log
->TotalSize
= Size
;
1365 Log
->CurrentSize
= 0;
1372 KeReleaseSpinLock(&Adapter
->NdisMiniportBlock
.Lock
, OldIrql
);
1374 return NDIS_STATUS_SUCCESS
;
1382 NdisMDeregisterAdapterShutdownHandler(
1383 IN NDIS_HANDLE MiniportHandle
)
1385 * FUNCTION: de-registers a shutdown handler
1386 * ARGUMENTS: MiniportHandle: Handle passed into MiniportInitialize
1389 PLOGICAL_ADAPTER Adapter
= (PLOGICAL_ADAPTER
)MiniportHandle
;
1391 NDIS_DbgPrint(DEBUG_MINIPORT
, ("Called.\n"));
1393 if(Adapter
->BugcheckContext
->ShutdownHandler
) {
1394 KeDeregisterBugCheckCallback(Adapter
->BugcheckContext
->CallbackRecord
);
1395 IoUnregisterShutdownNotification(Adapter
->NdisMiniportBlock
.DeviceObject
);
1405 IN NDIS_HANDLE LogHandle
)
1407 PNDIS_LOG Log
= (PNDIS_LOG
) LogHandle
;
1410 NDIS_DbgPrint(MAX_TRACE
, ("called: LogHandle 0x%x\n", LogHandle
));
1413 KeAcquireSpinLock(&Log
->LogLock
, &OldIrql
);
1415 /* Set buffers size */
1416 Log
->CurrentSize
= 0;
1421 KeReleaseSpinLock(&Log
->LogLock
, OldIrql
);
1427 #undef NdisMIndicateStatus
1430 NdisMIndicateStatus(
1431 IN NDIS_HANDLE MiniportAdapterHandle
,
1432 IN NDIS_STATUS GeneralStatus
,
1433 IN PVOID StatusBuffer
,
1434 IN UINT StatusBufferSize
)
1436 MiniStatus(MiniportAdapterHandle
, GeneralStatus
, StatusBuffer
, StatusBufferSize
);
1442 #undef NdisMIndicateStatusComplete
1445 NdisMIndicateStatusComplete(
1446 IN NDIS_HANDLE MiniportAdapterHandle
)
1448 MiniStatusComplete(MiniportAdapterHandle
);
1457 NdisInitializeWrapper(
1458 OUT PNDIS_HANDLE NdisWrapperHandle
,
1459 IN PVOID SystemSpecific1
,
1460 IN PVOID SystemSpecific2
,
1461 IN PVOID SystemSpecific3
)
1463 * FUNCTION: Notifies the NDIS library that a new miniport is initializing
1465 * NdisWrapperHandle = Address of buffer to place NDIS wrapper handle
1466 * SystemSpecific1 = Pointer to the driver's driver object
1467 * SystemSpecific2 = Pointer to the driver's registry path
1468 * SystemSpecific3 = Always NULL
1470 * - SystemSpecific2 goes invalid so we copy it
1473 PNDIS_M_DRIVER_BLOCK Miniport
;
1474 PUNICODE_STRING RegistryPath
;
1475 WCHAR
*RegistryBuffer
;
1477 NDIS_DbgPrint(MAX_TRACE
, ("Called.\n"));
1479 ASSERT(NdisWrapperHandle
);
1481 *NdisWrapperHandle
= NULL
;
1483 #if BREAK_ON_MINIPORT_INIT
1487 Miniport
= ExAllocatePool(NonPagedPool
, sizeof(NDIS_M_DRIVER_BLOCK
));
1491 NDIS_DbgPrint(MIN_TRACE
, ("Insufficient resources.\n"));
1495 RtlZeroMemory(Miniport
, sizeof(NDIS_M_DRIVER_BLOCK
));
1497 KeInitializeSpinLock(&Miniport
->Lock
);
1499 Miniport
->DriverObject
= (PDRIVER_OBJECT
)SystemSpecific1
;
1501 /* set the miniport's driver registry path */
1502 RegistryPath
= ExAllocatePool(PagedPool
, sizeof(UNICODE_STRING
));
1505 ExFreePool(Miniport
);
1506 NDIS_DbgPrint(MIN_TRACE
, ("Insufficient resources.\n"));
1510 RegistryPath
->Length
= ((PUNICODE_STRING
)SystemSpecific2
)->Length
;
1511 RegistryPath
->MaximumLength
= RegistryPath
->Length
+ sizeof(WCHAR
); /* room for 0-term */
1513 RegistryBuffer
= ExAllocatePool(PagedPool
, RegistryPath
->MaximumLength
);
1516 NDIS_DbgPrint(MIN_TRACE
, ("Insufficient resources.\n"));
1517 ExFreePool(Miniport
);
1518 ExFreePool(RegistryPath
);
1522 RtlCopyMemory(RegistryBuffer
, ((PUNICODE_STRING
)SystemSpecific2
)->Buffer
, RegistryPath
->Length
);
1523 RegistryBuffer
[RegistryPath
->Length
/sizeof(WCHAR
)] = 0;
1525 RegistryPath
->Buffer
= RegistryBuffer
;
1526 Miniport
->RegistryPath
= RegistryPath
;
1528 InitializeListHead(&Miniport
->DeviceList
);
1530 /* Put miniport in global miniport list */
1531 ExInterlockedInsertTailList(&MiniportListHead
, &Miniport
->ListEntry
, &MiniportListLock
);
1533 *NdisWrapperHandle
= Miniport
;
1537 VOID NTAPI
NdisIBugcheckCallback(
1541 * FUNCTION: Internal callback for handling bugchecks - calls adapter's shutdown handler
1543 * Buffer: Pointer to a bugcheck callback context
1547 PMINIPORT_BUGCHECK_CONTEXT Context
= (PMINIPORT_BUGCHECK_CONTEXT
)Buffer
;
1548 ADAPTER_SHUTDOWN_HANDLER sh
= (ADAPTER_SHUTDOWN_HANDLER
)Context
->ShutdownHandler
;
1550 NDIS_DbgPrint(DEBUG_MINIPORT
, ("Called.\n"));
1553 sh(Context
->DriverContext
);
1562 NdisMRegisterAdapterShutdownHandler(
1563 IN NDIS_HANDLE MiniportHandle
,
1564 IN PVOID ShutdownContext
,
1565 IN ADAPTER_SHUTDOWN_HANDLER ShutdownHandler
)
1567 * FUNCTION: Register a shutdown handler for an adapter
1569 * MiniportHandle: Handle originally passed into MiniportInitialize
1570 * ShutdownContext: Pre-initialized bugcheck context
1571 * ShutdownHandler: Function to call to handle the bugcheck
1573 * - I'm not sure about ShutdownContext
1576 PLOGICAL_ADAPTER Adapter
= (PLOGICAL_ADAPTER
)MiniportHandle
;
1577 PMINIPORT_BUGCHECK_CONTEXT BugcheckContext
;
1579 NDIS_DbgPrint(DEBUG_MINIPORT
, ("Called.\n"));
1581 BugcheckContext
= ExAllocatePool(NonPagedPool
, sizeof(MINIPORT_BUGCHECK_CONTEXT
));
1582 if(!BugcheckContext
)
1584 NDIS_DbgPrint(MIN_TRACE
, ("Insufficient resources.\n"));
1588 BugcheckContext
->ShutdownHandler
= ShutdownHandler
;
1589 BugcheckContext
->DriverContext
= ShutdownContext
;
1591 BugcheckContext
->CallbackRecord
= ExAllocatePool(NonPagedPool
, sizeof(KBUGCHECK_CALLBACK_RECORD
));
1592 if (!BugcheckContext
->CallbackRecord
) {
1593 ExFreePool(BugcheckContext
);
1597 Adapter
->BugcheckContext
= BugcheckContext
;
1599 KeInitializeCallbackRecord(BugcheckContext
->CallbackRecord
);
1601 KeRegisterBugCheckCallback(BugcheckContext
->CallbackRecord
, NdisIBugcheckCallback
,
1602 BugcheckContext
, sizeof(BugcheckContext
), (PUCHAR
)"Ndis Miniport");
1604 IoRegisterShutdownNotification(Adapter
->NdisMiniportBlock
.DeviceObject
);
1610 PLOGICAL_ADAPTER Adapter
,
1611 NDIS_OID AddressOID
)
1613 * FUNCTION: Queries miniport for information
1615 * Adapter = Pointer to logical adapter
1616 * AddressOID = OID to use to query for current address
1618 * Status of operation
1622 NDIS_STATUS NdisStatus
;
1624 NDIS_DbgPrint(MAX_TRACE
, ("Called.\n"));
1626 /* Get MAC options for adapter */
1627 NdisStatus
= MiniQueryInformation(Adapter
, OID_GEN_MAC_OPTIONS
, sizeof(UINT
),
1628 &Adapter
->NdisMiniportBlock
.MacOptions
,
1631 if (NdisStatus
!= NDIS_STATUS_SUCCESS
)
1633 NDIS_DbgPrint(MIN_TRACE
, ("OID_GEN_MAC_OPTIONS failed. NdisStatus (0x%X).\n", NdisStatus
));
1637 NDIS_DbgPrint(DEBUG_MINIPORT
, ("MacOptions (0x%X).\n", Adapter
->NdisMiniportBlock
.MacOptions
));
1639 /* Get current hardware address of adapter */
1640 NdisStatus
= MiniQueryInformation(Adapter
, AddressOID
, Adapter
->AddressLength
,
1641 &Adapter
->Address
, &BytesWritten
);
1643 if (NdisStatus
!= NDIS_STATUS_SUCCESS
)
1645 NDIS_DbgPrint(MIN_TRACE
, ("Address OID (0x%X) failed. NdisStatus (0x%X).\n", AddressOID
, NdisStatus
));
1653 PUCHAR A
= (PUCHAR
)&Adapter
->Address
.Type
.Medium802_3
;
1655 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]));
1659 /* Get maximum lookahead buffer size of adapter */
1660 NdisStatus
= MiniQueryInformation(Adapter
, OID_GEN_MAXIMUM_LOOKAHEAD
, sizeof(ULONG
),
1661 &Adapter
->NdisMiniportBlock
.MaximumLookahead
, &BytesWritten
);
1663 if (NdisStatus
!= NDIS_STATUS_SUCCESS
)
1665 NDIS_DbgPrint(MIN_TRACE
, ("OID_GEN_MAXIMUM_LOOKAHEAD failed. NdisStatus (0x%X).\n", NdisStatus
));
1669 NDIS_DbgPrint(DEBUG_MINIPORT
, ("MaxLookaheadLength (0x%X).\n", Adapter
->NdisMiniportBlock
.MaximumLookahead
));
1671 /* Get current lookahead buffer size of adapter */
1672 NdisStatus
= MiniQueryInformation(Adapter
, OID_GEN_CURRENT_LOOKAHEAD
, sizeof(ULONG
),
1673 &Adapter
->NdisMiniportBlock
.CurrentLookahead
, &BytesWritten
);
1675 if (NdisStatus
!= NDIS_STATUS_SUCCESS
)
1677 NDIS_DbgPrint(MIN_TRACE
, ("OID_GEN_CURRENT_LOOKAHEAD failed. NdisStatus (0x%X).\n", NdisStatus
));
1681 NdisStatus
= MiniQueryInformation(Adapter
, OID_GEN_MAXIMUM_SEND_PACKETS
, sizeof(ULONG
),
1682 &Adapter
->NdisMiniportBlock
.MaxSendPackets
, &BytesWritten
);
1684 if (NdisStatus
!= NDIS_STATUS_SUCCESS
)
1686 NDIS_DbgPrint(MIN_TRACE
, ("OID_GEN_MAXIMUM_SEND_PACKETS failed. NdisStatus (0x%X).\n", NdisStatus
));
1688 /* Set it to 1 if it fails because some drivers don't support this (?)*/
1689 Adapter
->NdisMiniportBlock
.MaxSendPackets
= 1;
1692 NDIS_DbgPrint(DEBUG_MINIPORT
, ("CurLookaheadLength (0x%X).\n", Adapter
->NdisMiniportBlock
.CurrentLookahead
));
1694 return STATUS_SUCCESS
;
1700 NdisIForwardIrpAndWaitCompletionRoutine(
1705 PKEVENT Event
= Context
;
1707 if (Irp
->PendingReturned
)
1708 KeSetEvent(Event
, IO_NO_INCREMENT
, FALSE
);
1710 return STATUS_MORE_PROCESSING_REQUIRED
;
1716 NdisIForwardIrpAndWait(PLOGICAL_ADAPTER Adapter
, PIRP Irp
)
1721 KeInitializeEvent(&Event
, NotificationEvent
, FALSE
);
1722 IoCopyCurrentIrpStackLocationToNext(Irp
);
1723 IoSetCompletionRoutine(Irp
, NdisIForwardIrpAndWaitCompletionRoutine
, &Event
,
1725 Status
= IoCallDriver(Adapter
->NdisMiniportBlock
.NextDeviceObject
, Irp
);
1726 if (Status
== STATUS_PENDING
)
1728 KeWaitForSingleObject(&Event
, Executive
, KernelMode
, FALSE
, NULL
);
1729 Status
= Irp
->IoStatus
.Status
;
1737 IN PDEVICE_OBJECT DeviceObject
,
1740 Irp
->IoStatus
.Status
= STATUS_SUCCESS
;
1741 Irp
->IoStatus
.Information
= 0;
1743 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
1745 return STATUS_SUCCESS
;
1751 NdisIPnPStartDevice(
1752 IN PDEVICE_OBJECT DeviceObject
,
1755 * FUNCTION: Handle the PnP start device event
1757 * DeviceObejct = Functional Device Object
1758 * Irp = IRP_MN_START_DEVICE I/O request packet
1760 * Status of operation
1763 PIO_STACK_LOCATION Stack
= IoGetCurrentIrpStackLocation(Irp
);
1764 PLOGICAL_ADAPTER Adapter
= (PLOGICAL_ADAPTER
)DeviceObject
->DeviceExtension
;
1765 NDIS_WRAPPER_CONTEXT WrapperContext
;
1766 NDIS_STATUS NdisStatus
;
1767 NDIS_STATUS OpenErrorStatus
;
1769 UINT SelectedMediumIndex
= 0;
1770 NDIS_OID AddressOID
;
1771 BOOLEAN Success
= FALSE
;
1772 ULONG ResourceCount
;
1773 ULONG ResourceListSize
;
1774 UNICODE_STRING ParamName
;
1775 PNDIS_CONFIGURATION_PARAMETER ConfigParam
;
1776 NDIS_HANDLE ConfigHandle
;
1778 LARGE_INTEGER Timeout
;
1779 UINT MaxMulticastAddresses
;
1781 PLIST_ENTRY CurrentEntry
;
1782 PPROTOCOL_BINDING ProtocolBinding
;
1785 * Prepare wrapper context used by HW and configuration routines.
1788 NDIS_DbgPrint(DEBUG_MINIPORT
, ("Start Device %wZ\n", &Adapter
->NdisMiniportBlock
.MiniportName
));
1790 NDIS_DbgPrint(MAX_TRACE
, ("Inserting adapter 0x%x into adapter list\n", Adapter
));
1792 /* Put adapter in global adapter list */
1793 ExInterlockedInsertTailList(&AdapterListHead
, &Adapter
->ListEntry
, &AdapterListLock
);
1795 Status
= IoOpenDeviceRegistryKey(
1796 Adapter
->NdisMiniportBlock
.PhysicalDeviceObject
, PLUGPLAY_REGKEY_DRIVER
,
1797 KEY_ALL_ACCESS
, &WrapperContext
.RegistryHandle
);
1798 if (!NT_SUCCESS(Status
))
1800 NDIS_DbgPrint(MIN_TRACE
,("failed to open adapter-specific reg key\n"));
1801 ExInterlockedRemoveEntryList( &Adapter
->ListEntry
, &AdapterListLock
);
1805 NDIS_DbgPrint(MAX_TRACE
, ("opened device reg key\n"));
1807 WrapperContext
.DeviceObject
= Adapter
->NdisMiniportBlock
.DeviceObject
;
1810 * Store the adapter resources used by HW routines such as
1811 * NdisMQueryAdapterResources.
1814 if (Stack
->Parameters
.StartDevice
.AllocatedResources
!= NULL
)
1816 ResourceCount
= Stack
->Parameters
.StartDevice
.AllocatedResources
->List
[0].
1817 PartialResourceList
.Count
;
1819 FIELD_OFFSET(CM_RESOURCE_LIST
, List
[0].PartialResourceList
.
1820 PartialDescriptors
[ResourceCount
]);
1822 Adapter
->NdisMiniportBlock
.AllocatedResources
=
1823 ExAllocatePool(PagedPool
, ResourceListSize
);
1824 if (Adapter
->NdisMiniportBlock
.AllocatedResources
== NULL
)
1826 NDIS_DbgPrint(MIN_TRACE
, ("Insufficient resources\n"));
1827 ExInterlockedRemoveEntryList( &Adapter
->ListEntry
, &AdapterListLock
);
1828 return STATUS_INSUFFICIENT_RESOURCES
;
1831 Adapter
->NdisMiniportBlock
.Resources
=
1832 ExAllocatePool(PagedPool
, ResourceListSize
);
1833 if (!Adapter
->NdisMiniportBlock
.Resources
)
1835 NDIS_DbgPrint(MIN_TRACE
, ("Insufficient resources\n"));
1836 ExFreePool(Adapter
->NdisMiniportBlock
.AllocatedResources
);
1837 ExInterlockedRemoveEntryList(&Adapter
->ListEntry
, &AdapterListLock
);
1838 return STATUS_INSUFFICIENT_RESOURCES
;
1841 RtlCopyMemory(Adapter
->NdisMiniportBlock
.Resources
,
1842 Stack
->Parameters
.StartDevice
.AllocatedResources
,
1845 RtlCopyMemory(Adapter
->NdisMiniportBlock
.AllocatedResources
,
1846 Stack
->Parameters
.StartDevice
.AllocatedResources
,
1850 if (Stack
->Parameters
.StartDevice
.AllocatedResourcesTranslated
!= NULL
)
1852 ResourceCount
= Stack
->Parameters
.StartDevice
.AllocatedResourcesTranslated
->List
[0].
1853 PartialResourceList
.Count
;
1855 FIELD_OFFSET(CM_RESOURCE_LIST
, List
[0].PartialResourceList
.
1856 PartialDescriptors
[ResourceCount
]);
1858 Adapter
->NdisMiniportBlock
.AllocatedResourcesTranslated
=
1859 ExAllocatePool(PagedPool
, ResourceListSize
);
1860 if (Adapter
->NdisMiniportBlock
.AllocatedResourcesTranslated
== NULL
)
1862 NDIS_DbgPrint(MIN_TRACE
, ("Insufficient resources\n"));
1863 ExInterlockedRemoveEntryList( &Adapter
->ListEntry
, &AdapterListLock
);
1864 return STATUS_INSUFFICIENT_RESOURCES
;
1867 RtlCopyMemory(Adapter
->NdisMiniportBlock
.AllocatedResourcesTranslated
,
1868 Stack
->Parameters
.StartDevice
.AllocatedResourcesTranslated
,
1873 * Store the Bus Type, Bus Number and Slot information. It's used by
1874 * the hardware routines then.
1877 NdisOpenConfiguration(&NdisStatus
, &ConfigHandle
, (NDIS_HANDLE
)&WrapperContext
);
1878 if (NdisStatus
!= NDIS_STATUS_SUCCESS
)
1880 NDIS_DbgPrint(MIN_TRACE
, ("Failed to open configuration key\n"));
1881 ExInterlockedRemoveEntryList( &Adapter
->ListEntry
, &AdapterListLock
);
1885 Size
= sizeof(ULONG
);
1886 Status
= IoGetDeviceProperty(Adapter
->NdisMiniportBlock
.PhysicalDeviceObject
,
1887 DevicePropertyLegacyBusType
, Size
,
1888 &Adapter
->NdisMiniportBlock
.BusType
, &Size
);
1889 if (!NT_SUCCESS(Status
) || (INTERFACE_TYPE
)Adapter
->NdisMiniportBlock
.BusType
== InterfaceTypeUndefined
)
1891 NdisInitUnicodeString(&ParamName
, L
"BusType");
1892 NdisReadConfiguration(&NdisStatus
, &ConfigParam
, ConfigHandle
,
1893 &ParamName
, NdisParameterInteger
);
1894 if (NdisStatus
== NDIS_STATUS_SUCCESS
)
1895 Adapter
->NdisMiniportBlock
.BusType
= ConfigParam
->ParameterData
.IntegerData
;
1897 Adapter
->NdisMiniportBlock
.BusType
= Isa
;
1900 Status
= IoGetDeviceProperty(Adapter
->NdisMiniportBlock
.PhysicalDeviceObject
,
1901 DevicePropertyBusNumber
, Size
,
1902 &Adapter
->NdisMiniportBlock
.BusNumber
, &Size
);
1903 if (!NT_SUCCESS(Status
) || Adapter
->NdisMiniportBlock
.BusNumber
== 0xFFFFFFF0)
1905 NdisInitUnicodeString(&ParamName
, L
"BusNumber");
1906 NdisReadConfiguration(&NdisStatus
, &ConfigParam
, ConfigHandle
,
1907 &ParamName
, NdisParameterInteger
);
1908 if (NdisStatus
== NDIS_STATUS_SUCCESS
)
1909 Adapter
->NdisMiniportBlock
.BusNumber
= ConfigParam
->ParameterData
.IntegerData
;
1911 Adapter
->NdisMiniportBlock
.BusNumber
= 0;
1913 WrapperContext
.BusNumber
= Adapter
->NdisMiniportBlock
.BusNumber
;
1915 Status
= IoGetDeviceProperty(Adapter
->NdisMiniportBlock
.PhysicalDeviceObject
,
1916 DevicePropertyAddress
, Size
,
1917 &Adapter
->NdisMiniportBlock
.SlotNumber
, &Size
);
1918 if (!NT_SUCCESS(Status
) || Adapter
->NdisMiniportBlock
.SlotNumber
== (NDIS_INTERFACE_TYPE
)-1)
1920 NdisInitUnicodeString(&ParamName
, L
"SlotNumber");
1921 NdisReadConfiguration(&NdisStatus
, &ConfigParam
, ConfigHandle
,
1922 &ParamName
, NdisParameterInteger
);
1923 if (NdisStatus
== NDIS_STATUS_SUCCESS
)
1924 Adapter
->NdisMiniportBlock
.SlotNumber
= ConfigParam
->ParameterData
.IntegerData
;
1926 Adapter
->NdisMiniportBlock
.SlotNumber
= 0;
1930 /* Convert slotnumber to PCI_SLOT_NUMBER */
1931 ULONG PciSlotNumber
= Adapter
->NdisMiniportBlock
.SlotNumber
;
1932 PCI_SLOT_NUMBER SlotNumber
;
1934 SlotNumber
.u
.AsULONG
= 0;
1935 SlotNumber
.u
.bits
.DeviceNumber
= (PciSlotNumber
>> 16) & 0xFFFF;
1936 SlotNumber
.u
.bits
.FunctionNumber
= PciSlotNumber
& 0xFFFF;
1938 Adapter
->NdisMiniportBlock
.SlotNumber
= SlotNumber
.u
.AsULONG
;
1940 WrapperContext
.SlotNumber
= Adapter
->NdisMiniportBlock
.SlotNumber
;
1942 NdisCloseConfiguration(ConfigHandle
);
1944 /* Set handlers (some NDIS macros require these) */
1945 Adapter
->NdisMiniportBlock
.EthRxCompleteHandler
= EthFilterDprIndicateReceiveComplete
;
1946 Adapter
->NdisMiniportBlock
.EthRxIndicateHandler
= EthFilterDprIndicateReceive
;
1947 Adapter
->NdisMiniportBlock
.SendCompleteHandler
= MiniSendComplete
;
1948 Adapter
->NdisMiniportBlock
.SendResourcesHandler
= MiniSendResourcesAvailable
;
1949 Adapter
->NdisMiniportBlock
.ResetCompleteHandler
= MiniResetComplete
;
1950 Adapter
->NdisMiniportBlock
.TDCompleteHandler
= MiniTransferDataComplete
;
1951 Adapter
->NdisMiniportBlock
.PacketIndicateHandler
= MiniIndicateReceivePacket
;
1952 Adapter
->NdisMiniportBlock
.StatusHandler
= MiniStatus
;
1953 Adapter
->NdisMiniportBlock
.StatusCompleteHandler
= MiniStatusComplete
;
1954 Adapter
->NdisMiniportBlock
.SendPacketsHandler
= ProSendPackets
;
1955 Adapter
->NdisMiniportBlock
.QueryCompleteHandler
= MiniRequestComplete
;
1956 Adapter
->NdisMiniportBlock
.SetCompleteHandler
= MiniRequestComplete
;
1959 * Call MiniportInitialize.
1962 NDIS_DbgPrint(MID_TRACE
, ("calling MiniportInitialize\n"));
1963 NdisStatus
= (*Adapter
->NdisMiniportBlock
.DriverHandle
->MiniportCharacteristics
.InitializeHandler
)(
1964 &OpenErrorStatus
, &SelectedMediumIndex
, &MediaArray
[0],
1965 MEDIA_ARRAY_SIZE
, Adapter
, (NDIS_HANDLE
)&WrapperContext
);
1967 ZwClose(WrapperContext
.RegistryHandle
);
1969 if (NdisStatus
!= NDIS_STATUS_SUCCESS
)
1971 NDIS_DbgPrint(MIN_TRACE
, ("MiniportInitialize() failed for an adapter.\n"));
1972 ExInterlockedRemoveEntryList( &Adapter
->ListEntry
, &AdapterListLock
);
1973 if (Adapter
->NdisMiniportBlock
.Interrupt
)
1975 KeBugCheckEx(BUGCODE_ID_DRIVER
,
1977 (ULONG_PTR
)Adapter
->NdisMiniportBlock
.Interrupt
,
1978 (ULONG_PTR
)Adapter
->NdisMiniportBlock
.TimerQueue
,
1981 if (Adapter
->NdisMiniportBlock
.TimerQueue
)
1983 KeBugCheckEx(BUGCODE_ID_DRIVER
,
1985 (ULONG_PTR
)Adapter
->NdisMiniportBlock
.Interrupt
,
1986 (ULONG_PTR
)Adapter
->NdisMiniportBlock
.TimerQueue
,
1992 if (SelectedMediumIndex
>= MEDIA_ARRAY_SIZE
)
1994 NDIS_DbgPrint(MIN_TRACE
, ("MiniportInitialize() selected a bad index\n"));
1995 ExInterlockedRemoveEntryList( &Adapter
->ListEntry
, &AdapterListLock
);
1996 return NDIS_STATUS_UNSUPPORTED_MEDIA
;
1999 Adapter
->NdisMiniportBlock
.MediaType
= MediaArray
[SelectedMediumIndex
];
2001 switch (Adapter
->NdisMiniportBlock
.MediaType
)
2003 case NdisMedium802_3
:
2004 Adapter
->MediumHeaderSize
= 14; /* XXX figure out what to do about LLC */
2005 AddressOID
= OID_802_3_CURRENT_ADDRESS
;
2006 Adapter
->AddressLength
= ETH_LENGTH_OF_ADDRESS
;
2007 NdisStatus
= DoQueries(Adapter
, AddressOID
);
2008 if (NdisStatus
== NDIS_STATUS_SUCCESS
)
2010 NdisStatus
= MiniQueryInformation(Adapter
, OID_802_3_MAXIMUM_LIST_SIZE
, sizeof(UINT
),
2011 &MaxMulticastAddresses
, &BytesWritten
);
2013 if (NdisStatus
!= NDIS_STATUS_SUCCESS
)
2015 ExInterlockedRemoveEntryList( &Adapter
->ListEntry
, &AdapterListLock
);
2016 NDIS_DbgPrint(MIN_TRACE
, ("MiniQueryInformation failed (%x)\n", NdisStatus
));
2020 Success
= EthCreateFilter(MaxMulticastAddresses
,
2021 Adapter
->Address
.Type
.Medium802_3
,
2022 &Adapter
->NdisMiniportBlock
.EthDB
);
2024 ((PETHI_FILTER
)Adapter
->NdisMiniportBlock
.EthDB
)->Miniport
= (PNDIS_MINIPORT_BLOCK
)Adapter
;
2026 NdisStatus
= NDIS_STATUS_RESOURCES
;
2031 /* FIXME: Support other types of media */
2032 NDIS_DbgPrint(MIN_TRACE
, ("error: unsupported media\n"));
2034 ExInterlockedRemoveEntryList( &Adapter
->ListEntry
, &AdapterListLock
);
2035 return STATUS_UNSUCCESSFUL
;
2038 if (NdisStatus
!= NDIS_STATUS_SUCCESS
)
2040 NDIS_DbgPrint(MIN_TRACE
, ("couldn't create filter (%x)\n", NdisStatus
));
2044 /* Check for a hang every two seconds if it wasn't set in MiniportInitialize */
2045 if (Adapter
->NdisMiniportBlock
.CheckForHangSeconds
== 0)
2046 Adapter
->NdisMiniportBlock
.CheckForHangSeconds
= 2;
2048 Adapter
->NdisMiniportBlock
.OldPnPDeviceState
= Adapter
->NdisMiniportBlock
.PnPDeviceState
;
2049 Adapter
->NdisMiniportBlock
.PnPDeviceState
= NdisPnPDeviceStarted
;
2051 IoSetDeviceInterfaceState(&Adapter
->NdisMiniportBlock
.SymbolicLinkName
, TRUE
);
2053 Timeout
.QuadPart
= Int32x32To64(Adapter
->NdisMiniportBlock
.CheckForHangSeconds
, -1000000);
2054 KeSetTimerEx(&Adapter
->NdisMiniportBlock
.WakeUpDpcTimer
.Timer
, Timeout
,
2055 Adapter
->NdisMiniportBlock
.CheckForHangSeconds
* 1000,
2056 &Adapter
->NdisMiniportBlock
.WakeUpDpcTimer
.Dpc
);
2058 /* Put adapter in adapter list for this miniport */
2059 ExInterlockedInsertTailList(&Adapter
->NdisMiniportBlock
.DriverHandle
->DeviceList
, &Adapter
->MiniportListEntry
, &Adapter
->NdisMiniportBlock
.DriverHandle
->Lock
);
2061 /* Refresh bindings for all protocols */
2062 CurrentEntry
= ProtocolListHead
.Flink
;
2063 while (CurrentEntry
!= &ProtocolListHead
)
2065 ProtocolBinding
= CONTAINING_RECORD(CurrentEntry
, PROTOCOL_BINDING
, ListEntry
);
2067 ndisBindMiniportsToProtocol(&NdisStatus
, ProtocolBinding
);
2069 CurrentEntry
= CurrentEntry
->Flink
;
2072 return STATUS_SUCCESS
;
2079 IN PDEVICE_OBJECT DeviceObject
,
2082 * FUNCTION: Handle the PnP stop device event
2084 * DeviceObejct = Functional Device Object
2085 * Irp = IRP_MN_STOP_DEVICE I/O request packet
2087 * Status of operation
2090 PLOGICAL_ADAPTER Adapter
= (PLOGICAL_ADAPTER
)DeviceObject
->DeviceExtension
;
2092 /* Remove adapter from adapter list for this miniport */
2093 ExInterlockedRemoveEntryList(&Adapter
->MiniportListEntry
, &Adapter
->NdisMiniportBlock
.DriverHandle
->Lock
);
2095 /* Remove adapter from global adapter list */
2096 ExInterlockedRemoveEntryList(&Adapter
->ListEntry
, &AdapterListLock
);
2098 KeCancelTimer(&Adapter
->NdisMiniportBlock
.WakeUpDpcTimer
.Timer
);
2100 (*Adapter
->NdisMiniportBlock
.DriverHandle
->MiniportCharacteristics
.HaltHandler
)(Adapter
);
2102 IoSetDeviceInterfaceState(&Adapter
->NdisMiniportBlock
.SymbolicLinkName
, FALSE
);
2104 if (Adapter
->NdisMiniportBlock
.AllocatedResources
)
2106 ExFreePool(Adapter
->NdisMiniportBlock
.AllocatedResources
);
2107 Adapter
->NdisMiniportBlock
.AllocatedResources
= NULL
;
2109 if (Adapter
->NdisMiniportBlock
.AllocatedResourcesTranslated
)
2111 ExFreePool(Adapter
->NdisMiniportBlock
.AllocatedResourcesTranslated
);
2112 Adapter
->NdisMiniportBlock
.AllocatedResourcesTranslated
= NULL
;
2115 if (Adapter
->NdisMiniportBlock
.Resources
)
2117 ExFreePool(Adapter
->NdisMiniportBlock
.Resources
);
2118 Adapter
->NdisMiniportBlock
.Resources
= NULL
;
2121 if (Adapter
->NdisMiniportBlock
.EthDB
)
2123 EthDeleteFilter(Adapter
->NdisMiniportBlock
.EthDB
);
2124 Adapter
->NdisMiniportBlock
.EthDB
= NULL
;
2127 Adapter
->NdisMiniportBlock
.OldPnPDeviceState
= Adapter
->NdisMiniportBlock
.PnPDeviceState
;
2128 Adapter
->NdisMiniportBlock
.PnPDeviceState
= NdisPnPDeviceStopped
;
2130 return STATUS_SUCCESS
;
2136 IN PDEVICE_OBJECT DeviceObject
,
2139 PLOGICAL_ADAPTER Adapter
= DeviceObject
->DeviceExtension
;
2140 PMINIPORT_BUGCHECK_CONTEXT Context
= Adapter
->BugcheckContext
;
2141 ADAPTER_SHUTDOWN_HANDLER ShutdownHandler
= Context
->ShutdownHandler
;
2143 ASSERT(ShutdownHandler
);
2145 ShutdownHandler(Context
->DriverContext
);
2147 Irp
->IoStatus
.Status
= STATUS_SUCCESS
;
2148 Irp
->IoStatus
.Information
= 0;
2150 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
2152 return STATUS_SUCCESS
;
2157 NdisIDeviceIoControl(
2158 IN PDEVICE_OBJECT DeviceObject
,
2161 PLOGICAL_ADAPTER Adapter
= (PLOGICAL_ADAPTER
)DeviceObject
->DeviceExtension
;
2162 PIO_STACK_LOCATION Stack
= IoGetCurrentIrpStackLocation(Irp
);
2163 NDIS_STATUS Status
= STATUS_NOT_SUPPORTED
;
2166 Irp
->IoStatus
.Information
= 0;
2170 switch (Stack
->Parameters
.DeviceIoControl
.IoControlCode
)
2172 case IOCTL_NDIS_QUERY_GLOBAL_STATS
:
2173 Status
= MiniQueryInformation(Adapter
,
2174 *(PNDIS_OID
)Irp
->AssociatedIrp
.SystemBuffer
,
2175 Stack
->Parameters
.DeviceIoControl
.OutputBufferLength
,
2176 MmGetSystemAddressForMdl(Irp
->MdlAddress
),
2178 Irp
->IoStatus
.Information
= Written
;
2186 if (Status
!= NDIS_STATUS_PENDING
)
2188 Irp
->IoStatus
.Status
= Status
;
2189 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
2192 IoMarkIrpPending(Irp
);
2201 IN PDEVICE_OBJECT DeviceObject
,
2204 PIO_STACK_LOCATION Stack
= IoGetCurrentIrpStackLocation(Irp
);
2205 PLOGICAL_ADAPTER Adapter
= (PLOGICAL_ADAPTER
)DeviceObject
->DeviceExtension
;
2208 switch (Stack
->MinorFunction
)
2210 case IRP_MN_START_DEVICE
:
2211 Status
= NdisIForwardIrpAndWait(Adapter
, Irp
);
2212 if (NT_SUCCESS(Status
) && NT_SUCCESS(Irp
->IoStatus
.Status
))
2214 Status
= NdisIPnPStartDevice(DeviceObject
, Irp
);
2217 NDIS_DbgPrint(MIN_TRACE
, ("Lower driver failed device start\n"));
2218 Irp
->IoStatus
.Status
= Status
;
2219 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
2222 case IRP_MN_STOP_DEVICE
:
2223 Status
= NdisIForwardIrpAndWait(Adapter
, Irp
);
2224 if (NT_SUCCESS(Status
) && NT_SUCCESS(Irp
->IoStatus
.Status
))
2226 Status
= NdisIPnPStopDevice(DeviceObject
, Irp
);
2229 NDIS_DbgPrint(MIN_TRACE
, ("Lower driver failed device stop\n"));
2230 Irp
->IoStatus
.Status
= Status
;
2231 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
2234 case IRP_MN_QUERY_REMOVE_DEVICE
:
2235 case IRP_MN_QUERY_STOP_DEVICE
:
2236 Status
= NdisIPnPQueryStopDevice(DeviceObject
, Irp
);
2237 Irp
->IoStatus
.Status
= Status
;
2238 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
2241 case IRP_MN_CANCEL_REMOVE_DEVICE
:
2242 case IRP_MN_CANCEL_STOP_DEVICE
:
2243 Status
= NdisIPnPCancelStopDevice(DeviceObject
, Irp
);
2244 Irp
->IoStatus
.Status
= Status
;
2245 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
2248 case IRP_MN_QUERY_PNP_DEVICE_STATE
:
2249 Status
= NDIS_STATUS_SUCCESS
;
2250 Irp
->IoStatus
.Status
= Status
;
2251 Irp
->IoStatus
.Information
|= Adapter
->NdisMiniportBlock
.PnPFlags
;
2252 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
2256 IoSkipCurrentIrpStackLocation(Irp
);
2257 Status
= IoCallDriver(Adapter
->NdisMiniportBlock
.NextDeviceObject
, Irp
);
2268 IN PDRIVER_OBJECT DriverObject
,
2269 IN PDEVICE_OBJECT PhysicalDeviceObject
)
2271 * FUNCTION: Create a device for an adapter found using PnP
2273 * DriverObject = Pointer to the miniport driver object
2274 * PhysicalDeviceObject = Pointer to the PDO for our adapter
2277 static const WCHAR ClassKeyName
[] = {'C','l','a','s','s','\\'};
2278 static const WCHAR LinkageKeyName
[] = {'\\','L','i','n','k','a','g','e',0};
2279 PNDIS_M_DRIVER_BLOCK Miniport
;
2280 PNDIS_M_DRIVER_BLOCK
*MiniportPtr
;
2281 WCHAR
*LinkageKeyBuffer
;
2282 ULONG DriverKeyLength
;
2283 RTL_QUERY_REGISTRY_TABLE QueryTable
[2];
2284 UNICODE_STRING ExportName
;
2285 PDEVICE_OBJECT DeviceObject
;
2286 PLOGICAL_ADAPTER Adapter
;
2290 * Gain the access to the miniport data structure first.
2293 MiniportPtr
= IoGetDriverObjectExtension(DriverObject
, (PVOID
)'NMID');
2294 if (MiniportPtr
== NULL
)
2296 NDIS_DbgPrint(MIN_TRACE
, ("Can't get driver object extension.\n"));
2297 return NDIS_STATUS_FAILURE
;
2299 Miniport
= *MiniportPtr
;
2302 * Get name of the Linkage registry key for our adapter. It's located under
2303 * the driver key for our driver and so we have basicly two ways to do it.
2304 * Either we can use IoOpenDriverRegistryKey or compose it using information
2305 * gathered by IoGetDeviceProperty. I choosed the second because
2306 * IoOpenDriverRegistryKey wasn't implemented at the time of writing.
2309 Status
= IoGetDeviceProperty(PhysicalDeviceObject
, DevicePropertyDriverKeyName
,
2310 0, NULL
, &DriverKeyLength
);
2311 if (Status
!= STATUS_BUFFER_TOO_SMALL
&& Status
!= STATUS_BUFFER_OVERFLOW
&& Status
!= STATUS_SUCCESS
)
2313 NDIS_DbgPrint(MIN_TRACE
, ("Can't get miniport driver key length.\n"));
2317 LinkageKeyBuffer
= ExAllocatePool(PagedPool
, DriverKeyLength
+
2318 sizeof(ClassKeyName
) + sizeof(LinkageKeyName
));
2319 if (LinkageKeyBuffer
== NULL
)
2321 NDIS_DbgPrint(MIN_TRACE
, ("Can't allocate memory for driver key name.\n"));
2322 return STATUS_INSUFFICIENT_RESOURCES
;
2325 Status
= IoGetDeviceProperty(PhysicalDeviceObject
, DevicePropertyDriverKeyName
,
2326 DriverKeyLength
, LinkageKeyBuffer
+
2327 (sizeof(ClassKeyName
) / sizeof(WCHAR
)),
2329 if (!NT_SUCCESS(Status
))
2331 NDIS_DbgPrint(MIN_TRACE
, ("Can't get miniport driver key.\n"));
2332 ExFreePool(LinkageKeyBuffer
);
2336 /* Compose the linkage key name. */
2337 RtlCopyMemory(LinkageKeyBuffer
, ClassKeyName
, sizeof(ClassKeyName
));
2338 RtlCopyMemory(LinkageKeyBuffer
+ ((sizeof(ClassKeyName
) + DriverKeyLength
) /
2339 sizeof(WCHAR
)) - 1, LinkageKeyName
, sizeof(LinkageKeyName
));
2341 NDIS_DbgPrint(DEBUG_MINIPORT
, ("LinkageKey: %S.\n", LinkageKeyBuffer
));
2344 * Now open the linkage key and read the "Export" and "RootDevice" values
2345 * which contains device name and root service respectively.
2348 RtlZeroMemory(QueryTable
, sizeof(QueryTable
));
2349 RtlInitUnicodeString(&ExportName
, NULL
);
2350 QueryTable
[0].Flags
= RTL_QUERY_REGISTRY_REQUIRED
| RTL_QUERY_REGISTRY_DIRECT
;
2351 QueryTable
[0].Name
= L
"Export";
2352 QueryTable
[0].EntryContext
= &ExportName
;
2354 Status
= RtlQueryRegistryValues(RTL_REGISTRY_CONTROL
, LinkageKeyBuffer
,
2355 QueryTable
, NULL
, NULL
);
2356 ExFreePool(LinkageKeyBuffer
);
2357 if (!NT_SUCCESS(Status
))
2359 NDIS_DbgPrint(MIN_TRACE
, ("Can't get miniport device name. (%x)\n", Status
));
2364 * Create the device object.
2367 NDIS_DbgPrint(MAX_TRACE
, ("creating device %wZ\n", &ExportName
));
2369 Status
= IoCreateDevice(Miniport
->DriverObject
, sizeof(LOGICAL_ADAPTER
),
2370 &ExportName
, FILE_DEVICE_PHYSICAL_NETCARD
,
2371 0, FALSE
, &DeviceObject
);
2372 if (!NT_SUCCESS(Status
))
2374 NDIS_DbgPrint(MIN_TRACE
, ("Could not create device object.\n"));
2375 RtlFreeUnicodeString(&ExportName
);
2380 * Initialize the adapter structure.
2383 Adapter
= (PLOGICAL_ADAPTER
)DeviceObject
->DeviceExtension
;
2384 KeInitializeSpinLock(&Adapter
->NdisMiniportBlock
.Lock
);
2385 InitializeListHead(&Adapter
->ProtocolListHead
);
2387 Status
= IoRegisterDeviceInterface(PhysicalDeviceObject
,
2388 &GUID_DEVINTERFACE_NET
,
2390 &Adapter
->NdisMiniportBlock
.SymbolicLinkName
);
2392 if (!NT_SUCCESS(Status
))
2394 NDIS_DbgPrint(MIN_TRACE
, ("Could not create device interface.\n"));
2395 IoDeleteDevice(DeviceObject
);
2396 RtlFreeUnicodeString(&ExportName
);
2400 Adapter
->NdisMiniportBlock
.DriverHandle
= Miniport
;
2401 Adapter
->NdisMiniportBlock
.MiniportName
= ExportName
;
2402 Adapter
->NdisMiniportBlock
.DeviceObject
= DeviceObject
;
2403 Adapter
->NdisMiniportBlock
.PhysicalDeviceObject
= PhysicalDeviceObject
;
2404 Adapter
->NdisMiniportBlock
.NextDeviceObject
=
2405 IoAttachDeviceToDeviceStack(Adapter
->NdisMiniportBlock
.DeviceObject
,
2406 PhysicalDeviceObject
);
2408 Adapter
->NdisMiniportBlock
.OldPnPDeviceState
= 0;
2409 Adapter
->NdisMiniportBlock
.PnPDeviceState
= NdisPnPDeviceAdded
;
2411 KeInitializeTimer(&Adapter
->NdisMiniportBlock
.WakeUpDpcTimer
.Timer
);
2412 KeInitializeDpc(&Adapter
->NdisMiniportBlock
.WakeUpDpcTimer
.Dpc
, MiniportHangDpc
, Adapter
);
2414 DeviceObject
->Flags
&= ~DO_DEVICE_INITIALIZING
;
2416 return STATUS_SUCCESS
;
2425 NdisMRegisterMiniport(
2426 IN NDIS_HANDLE NdisWrapperHandle
,
2427 IN PNDIS_MINIPORT_CHARACTERISTICS MiniportCharacteristics
,
2428 IN UINT CharacteristicsLength
)
2430 * FUNCTION: Registers a miniport's MiniportXxx entry points with the NDIS library
2432 * NdisWrapperHandle = Pointer to handle returned by NdisMInitializeWrapper
2433 * MiniportCharacteristics = Pointer to a buffer with miniport characteristics
2434 * CharacteristicsLength = Number of bytes in characteristics buffer
2436 * Status of operation
2440 PNDIS_M_DRIVER_BLOCK Miniport
= GET_MINIPORT_DRIVER(NdisWrapperHandle
);
2441 PNDIS_M_DRIVER_BLOCK
*MiniportPtr
;
2444 NDIS_DbgPrint(MAX_TRACE
, ("Called.\n"));
2446 switch (MiniportCharacteristics
->MajorNdisVersion
)
2449 MinSize
= sizeof(NDIS30_MINIPORT_CHARACTERISTICS
);
2453 MinSize
= sizeof(NDIS40_MINIPORT_CHARACTERISTICS
);
2457 MinSize
= sizeof(NDIS50_MINIPORT_CHARACTERISTICS
);
2461 NDIS_DbgPrint(MIN_TRACE
, ("Bad miniport characteristics version.\n"));
2462 return NDIS_STATUS_BAD_VERSION
;
2465 NDIS_DbgPrint(MIN_TRACE
, ("Initializing an NDIS %u.%u miniport\n",
2466 MiniportCharacteristics
->MajorNdisVersion
,
2467 MiniportCharacteristics
->MinorNdisVersion
));
2469 if (CharacteristicsLength
< MinSize
)
2471 NDIS_DbgPrint(MIN_TRACE
, ("Bad miniport characteristics length.\n"));
2472 return NDIS_STATUS_BAD_CHARACTERISTICS
;
2475 /* Check if mandatory MiniportXxx functions are specified */
2476 if ((!MiniportCharacteristics
->HaltHandler
) ||
2477 (!MiniportCharacteristics
->InitializeHandler
)||
2478 (!MiniportCharacteristics
->ResetHandler
))
2480 NDIS_DbgPrint(MIN_TRACE
, ("Bad miniport characteristics.\n"));
2481 return NDIS_STATUS_BAD_CHARACTERISTICS
;
2484 if (MiniportCharacteristics
->MajorNdisVersion
< 0x05)
2486 if ((!MiniportCharacteristics
->QueryInformationHandler
) ||
2487 (!MiniportCharacteristics
->SetInformationHandler
))
2489 NDIS_DbgPrint(MIN_TRACE
, ("Bad miniport characteristics. (Set/Query)\n"));
2490 return NDIS_STATUS_BAD_CHARACTERISTICS
;
2495 if (((!MiniportCharacteristics
->QueryInformationHandler
) ||
2496 (!MiniportCharacteristics
->SetInformationHandler
)) &&
2497 (!MiniportCharacteristics
->CoRequestHandler
))
2499 NDIS_DbgPrint(MIN_TRACE
, ("Bad miniport characteristics. (Set/Query)\n"));
2500 return NDIS_STATUS_BAD_CHARACTERISTICS
;
2504 if (MiniportCharacteristics
->MajorNdisVersion
== 0x03)
2506 if (!MiniportCharacteristics
->SendHandler
)
2508 NDIS_DbgPrint(MIN_TRACE
, ("Bad miniport characteristics. (NDIS 3.0)\n"));
2509 return NDIS_STATUS_BAD_CHARACTERISTICS
;
2512 else if (MiniportCharacteristics
->MajorNdisVersion
== 0x04)
2515 if ((!MiniportCharacteristics
->SendHandler
) &&
2516 (!MiniportCharacteristics
->SendPacketsHandler
))
2518 NDIS_DbgPrint(MIN_TRACE
, ("Bad miniport characteristics. (NDIS 4.0)\n"));
2519 return NDIS_STATUS_BAD_CHARACTERISTICS
;
2522 else if (MiniportCharacteristics
->MajorNdisVersion
== 0x05)
2524 /* TODO: Add more checks here */
2526 if ((!MiniportCharacteristics
->SendHandler
) &&
2527 (!MiniportCharacteristics
->SendPacketsHandler
) &&
2528 (!MiniportCharacteristics
->CoSendPacketsHandler
))
2530 NDIS_DbgPrint(MIN_TRACE
, ("Bad miniport characteristics. (NDIS 5.0)\n"));
2531 return NDIS_STATUS_BAD_CHARACTERISTICS
;
2535 /* TODO: verify NDIS5 and NDIS5.1 */
2537 RtlCopyMemory(&Miniport
->MiniportCharacteristics
, MiniportCharacteristics
, MinSize
);
2540 * NOTE: This is VERY unoptimal! Should we store the NDIS_M_DRIVER_BLOCK
2541 * structure in the driver extension or what?
2544 Status
= IoAllocateDriverObjectExtension(Miniport
->DriverObject
, (PVOID
)'NMID',
2545 sizeof(PNDIS_M_DRIVER_BLOCK
), (PVOID
*)&MiniportPtr
);
2546 if (!NT_SUCCESS(Status
))
2548 NDIS_DbgPrint(MIN_TRACE
, ("Can't allocate driver object extension.\n"));
2549 return NDIS_STATUS_RESOURCES
;
2552 *MiniportPtr
= Miniport
;
2554 Miniport
->DriverObject
->MajorFunction
[IRP_MJ_CREATE
] = NdisICreateClose
;
2555 Miniport
->DriverObject
->MajorFunction
[IRP_MJ_CLOSE
] = NdisICreateClose
;
2556 Miniport
->DriverObject
->MajorFunction
[IRP_MJ_PNP
] = NdisIDispatchPnp
;
2557 Miniport
->DriverObject
->MajorFunction
[IRP_MJ_SHUTDOWN
] = NdisIShutdown
;
2558 Miniport
->DriverObject
->MajorFunction
[IRP_MJ_DEVICE_CONTROL
] = NdisIDeviceIoControl
;
2559 Miniport
->DriverObject
->DriverExtension
->AddDevice
= NdisIAddDevice
;
2561 return NDIS_STATUS_SUCCESS
;
2568 #undef NdisMResetComplete
2572 IN NDIS_HANDLE MiniportAdapterHandle
,
2573 IN NDIS_STATUS Status
,
2574 IN BOOLEAN AddressingReset
)
2576 MiniResetComplete(MiniportAdapterHandle
, Status
, AddressingReset
);
2583 #undef NdisMSendComplete
2587 IN NDIS_HANDLE MiniportAdapterHandle
,
2588 IN PNDIS_PACKET Packet
,
2589 IN NDIS_STATUS Status
)
2591 * FUNCTION: Forwards a message to the initiating protocol saying
2592 * that a packet was handled
2594 * NdisAdapterHandle = Handle input to MiniportInitialize
2595 * Packet = Pointer to NDIS packet that was sent
2596 * Status = Status of send operation
2599 MiniSendComplete(MiniportAdapterHandle
, Packet
, Status
);
2606 #undef NdisMSendResourcesAvailable
2609 NdisMSendResourcesAvailable(
2610 IN NDIS_HANDLE MiniportAdapterHandle
)
2612 MiniSendResourcesAvailable(MiniportAdapterHandle
);
2619 #undef NdisMTransferDataComplete
2622 NdisMTransferDataComplete(
2623 IN NDIS_HANDLE MiniportAdapterHandle
,
2624 IN PNDIS_PACKET Packet
,
2625 IN NDIS_STATUS Status
,
2626 IN UINT BytesTransferred
)
2628 MiniTransferDataComplete(MiniportAdapterHandle
, Packet
, Status
, BytesTransferred
);
2635 #undef NdisMSetAttributes
2639 IN NDIS_HANDLE MiniportAdapterHandle
,
2640 IN NDIS_HANDLE MiniportAdapterContext
,
2641 IN BOOLEAN BusMaster
,
2642 IN NDIS_INTERFACE_TYPE AdapterType
)
2644 * FUNCTION: Informs the NDIS library of significant features of the caller's NIC
2646 * MiniportAdapterHandle = Handle input to MiniportInitialize
2647 * MiniportAdapterContext = Pointer to context information
2648 * BusMaster = Specifies TRUE if the caller's NIC is a busmaster DMA device
2649 * AdapterType = Specifies the I/O bus interface of the caller's NIC
2652 NDIS_DbgPrint(MAX_TRACE
, ("Called.\n"));
2653 NdisMSetAttributesEx(MiniportAdapterHandle
, MiniportAdapterContext
, 0,
2654 BusMaster
? NDIS_ATTRIBUTE_BUS_MASTER
: 0,
2664 NdisMSetAttributesEx(
2665 IN NDIS_HANDLE MiniportAdapterHandle
,
2666 IN NDIS_HANDLE MiniportAdapterContext
,
2667 IN UINT CheckForHangTimeInSeconds OPTIONAL
,
2668 IN ULONG AttributeFlags
,
2669 IN NDIS_INTERFACE_TYPE AdapterType
)
2671 * FUNCTION: Informs the NDIS library of significant features of the caller's NIC
2673 * MiniportAdapterHandle = Handle input to MiniportInitialize
2674 * MiniportAdapterContext = Pointer to context information
2675 * CheckForHangTimeInSeconds = Specifies interval in seconds at which
2676 * MiniportCheckForHang should be called
2677 * AttributeFlags = Bitmask that indicates specific attributes
2678 * AdapterType = Specifies the I/O bus interface of the caller's NIC
2681 PLOGICAL_ADAPTER Adapter
= GET_LOGICAL_ADAPTER(MiniportAdapterHandle
);
2683 NDIS_DbgPrint(MAX_TRACE
, ("Called.\n"));
2685 Adapter
->NdisMiniportBlock
.MiniportAdapterContext
= MiniportAdapterContext
;
2686 Adapter
->NdisMiniportBlock
.Flags
= AttributeFlags
;
2687 Adapter
->NdisMiniportBlock
.AdapterType
= AdapterType
;
2688 if (CheckForHangTimeInSeconds
> 0)
2689 Adapter
->NdisMiniportBlock
.CheckForHangSeconds
= CheckForHangTimeInSeconds
;
2690 if (AttributeFlags
& NDIS_ATTRIBUTE_INTERMEDIATE_DRIVER
)
2691 NDIS_DbgPrint(MAX_TRACE
, ("Intermediate drivers not supported yet.\n"));
2694 if (Adapter
->NdisMiniportBlock
.DriverHandle
->MiniportCharacteristics
.AdapterShutdownHandler
)
2696 NDIS_DbgPrint(MAX_TRACE
, ("Miniport set AdapterShutdownHandler in MiniportCharacteristics\n"));
2697 NdisMRegisterAdapterShutdownHandler(Adapter
,
2698 Adapter
->NdisMiniportBlock
.MiniportAdapterContext
,
2699 Adapter
->NdisMiniportBlock
.DriverHandle
->MiniportCharacteristics
.AdapterShutdownHandler
);
2710 IN ULONG MicrosecondsToSleep
)
2712 * FUNCTION: delay the thread's execution for MicrosecondsToSleep
2714 * MicrosecondsToSleep: duh...
2716 * - Because this is a blocking call, current IRQL must be < DISPATCH_LEVEL
2720 LARGE_INTEGER DueTime
;
2724 DueTime
.QuadPart
= (-1) * 10 * MicrosecondsToSleep
;
2726 KeInitializeTimer(&Timer
);
2727 KeSetTimer(&Timer
, DueTime
, 0);
2728 KeWaitForSingleObject(&Timer
, Executive
, KernelMode
, FALSE
, 0);
2737 NdisMSynchronizeWithInterrupt(
2738 IN PNDIS_MINIPORT_INTERRUPT Interrupt
,
2739 IN PVOID SynchronizeFunction
,
2740 IN PVOID SynchronizeContext
)
2742 return(KeSynchronizeExecution(Interrupt
->InterruptObject
,
2743 (PKSYNCHRONIZE_ROUTINE
)SynchronizeFunction
,
2744 SynchronizeContext
));
2754 IN NDIS_HANDLE LogHandle
,
2756 IN UINT LogBufferSize
)
2758 PUCHAR Buffer
= LogBuffer
;
2762 for (i
= 0; i
< LogBufferSize
; i
+= 16)
2764 DbgPrint("%08x |", i
);
2765 for (j
= 0; j
< 16; j
++)
2768 if (idx
< LogBufferSize
)
2769 DbgPrint(" %02x", Buffer
[idx
]);
2774 for (j
= 0; j
< 16; j
++)
2777 if (idx
== LogBufferSize
)
2779 if (Buffer
[idx
] >= ' ') /* FIXME: not portable! replace by if (isprint(Buffer[idx])) ? */
2780 DbgPrint("%c", Buffer
[idx
]);
2787 return NDIS_STATUS_FAILURE
;
2796 NdisTerminateWrapper(
2797 IN NDIS_HANDLE NdisWrapperHandle
,
2798 IN PVOID SystemSpecific
)
2800 * FUNCTION: Releases resources allocated by a call to NdisInitializeWrapper
2802 * NdisWrapperHandle = Handle returned by NdisInitializeWrapper (NDIS_M_DRIVER_BLOCK)
2803 * SystemSpecific = Always NULL
2806 PNDIS_M_DRIVER_BLOCK Miniport
= GET_MINIPORT_DRIVER(NdisWrapperHandle
);
2808 NDIS_DbgPrint(MAX_TRACE
, ("Called.\n"));
2810 ExFreePool(Miniport
->RegistryPath
->Buffer
);
2811 ExFreePool(Miniport
->RegistryPath
);
2812 ExInterlockedRemoveEntryList(&Miniport
->ListEntry
, &MiniportListLock
);
2813 ExFreePool(Miniport
);
2822 NdisMQueryAdapterInstanceName(
2823 OUT PNDIS_STRING AdapterInstanceName
,
2824 IN NDIS_HANDLE MiniportAdapterHandle
)
2832 PLOGICAL_ADAPTER Adapter
= (PLOGICAL_ADAPTER
)MiniportAdapterHandle
;
2833 UNICODE_STRING AdapterName
;
2835 NDIS_DbgPrint(MAX_TRACE
, ("Called.\n"));
2837 AdapterName
.Length
= 0;
2838 AdapterName
.MaximumLength
= Adapter
->NdisMiniportBlock
.MiniportName
.MaximumLength
;
2839 AdapterName
.Buffer
= ExAllocatePool(PagedPool
, AdapterName
.MaximumLength
);
2840 if (!AdapterName
.Buffer
) {
2841 NDIS_DbgPrint(MIN_TRACE
, ("Insufficient resources\n"));
2842 return NDIS_STATUS_RESOURCES
;
2845 RtlCopyUnicodeString(&AdapterName
, &Adapter
->NdisMiniportBlock
.MiniportName
);
2847 *AdapterInstanceName
= AdapterName
;
2849 return NDIS_STATUS_SUCCESS
;
2857 NdisDeregisterAdapterShutdownHandler(
2858 IN NDIS_HANDLE NdisAdapterHandle
)
2866 NdisMDeregisterAdapterShutdownHandler(NdisAdapterHandle
);
2875 NdisRegisterAdapterShutdownHandler(
2876 IN NDIS_HANDLE NdisAdapterHandle
,
2877 IN PVOID ShutdownContext
,
2878 IN ADAPTER_SHUTDOWN_HANDLER ShutdownHandler
)
2886 NdisMRegisterAdapterShutdownHandler(NdisAdapterHandle
,
2896 NdisMGetDeviceProperty(
2897 IN NDIS_HANDLE MiniportAdapterHandle
,
2898 IN OUT PDEVICE_OBJECT
*PhysicalDeviceObject OPTIONAL
,
2899 IN OUT PDEVICE_OBJECT
*FunctionalDeviceObject OPTIONAL
,
2900 IN OUT PDEVICE_OBJECT
*NextDeviceObject OPTIONAL
,
2901 IN OUT PCM_RESOURCE_LIST
*AllocatedResources OPTIONAL
,
2902 IN OUT PCM_RESOURCE_LIST
*AllocatedResourcesTranslated OPTIONAL
)
2910 PLOGICAL_ADAPTER Adapter
= MiniportAdapterHandle
;
2912 NDIS_DbgPrint(MAX_TRACE
, ("Called\n"));
2914 if (PhysicalDeviceObject
!= NULL
)
2915 *PhysicalDeviceObject
= Adapter
->NdisMiniportBlock
.PhysicalDeviceObject
;
2917 if (FunctionalDeviceObject
!= NULL
)
2918 *FunctionalDeviceObject
= Adapter
->NdisMiniportBlock
.DeviceObject
;
2920 if (NextDeviceObject
!= NULL
)
2921 *NextDeviceObject
= Adapter
->NdisMiniportBlock
.NextDeviceObject
;
2923 if (AllocatedResources
!= NULL
)
2924 *AllocatedResources
= Adapter
->NdisMiniportBlock
.AllocatedResources
;
2926 if (AllocatedResourcesTranslated
!= NULL
)
2927 *AllocatedResourcesTranslated
= Adapter
->NdisMiniportBlock
.AllocatedResourcesTranslated
;
2935 NdisMRegisterUnloadHandler(
2936 IN NDIS_HANDLE NdisWrapperHandle
,
2937 IN PDRIVER_UNLOAD UnloadHandler
)
2945 PNDIS_M_DRIVER_BLOCK DriverBlock
= NdisWrapperHandle
;
2947 NDIS_DbgPrint(MAX_TRACE
, ("Miniport registered unload handler\n"));
2949 DriverBlock
->DriverObject
->DriverUnload
= UnloadHandler
;
2957 NdisMRegisterDevice(
2958 IN NDIS_HANDLE NdisWrapperHandle
,
2959 IN PNDIS_STRING DeviceName
,
2960 IN PNDIS_STRING SymbolicName
,
2961 IN PDRIVER_DISPATCH MajorFunctions
[],
2962 OUT PDEVICE_OBJECT
*pDeviceObject
,
2963 OUT NDIS_HANDLE
*NdisDeviceHandle
)
2971 PNDIS_M_DRIVER_BLOCK DriverBlock
= NdisWrapperHandle
;
2972 PNDIS_M_DEVICE_BLOCK DeviceBlock
;
2973 PDEVICE_OBJECT DeviceObject
;
2977 NDIS_DbgPrint(MAX_TRACE
, ("Called\n"));
2979 Status
= IoCreateDevice(DriverBlock
->DriverObject
,
2980 0, /* This space is reserved for us. Should we use it? */
2982 FILE_DEVICE_NETWORK
,
2987 if (!NT_SUCCESS(Status
))
2989 NDIS_DbgPrint(MIN_TRACE
, ("IoCreateDevice failed (%x)\n", Status
));
2993 Status
= IoCreateSymbolicLink(SymbolicName
, DeviceName
);
2995 if (!NT_SUCCESS(Status
))
2997 NDIS_DbgPrint(MIN_TRACE
, ("IoCreateSymbolicLink failed (%x)\n", Status
));
2998 IoDeleteDevice(DeviceObject
);
3002 DeviceBlock
= ExAllocatePool(NonPagedPool
, sizeof(NDIS_M_DEVICE_BLOCK
));
3006 NDIS_DbgPrint(MIN_TRACE
, ("Insufficient resources\n"));
3007 IoDeleteDevice(DeviceObject
);
3008 IoDeleteSymbolicLink(SymbolicName
);
3009 return NDIS_STATUS_RESOURCES
;
3012 for (i
= 0; i
<= IRP_MJ_MAXIMUM_FUNCTION
; i
++)
3013 DriverBlock
->DriverObject
->MajorFunction
[i
] = MajorFunctions
[i
];
3015 DriverBlock
->DriverObject
->MajorFunction
[IRP_MJ_PNP
] = NdisIDispatchPnp
;
3017 if (!DriverBlock
->DriverObject
->MajorFunction
[IRP_MJ_CREATE
])
3018 DriverBlock
->DriverObject
->MajorFunction
[IRP_MJ_CREATE
] = NdisICreateClose
;
3020 if (!DriverBlock
->DriverObject
->MajorFunction
[IRP_MJ_CLOSE
])
3021 DriverBlock
->DriverObject
->MajorFunction
[IRP_MJ_CLOSE
] = NdisICreateClose
;
3023 DeviceBlock
->DeviceObject
= DeviceObject
;
3024 DeviceBlock
->SymbolicName
= SymbolicName
;
3026 *pDeviceObject
= DeviceObject
;
3027 *NdisDeviceHandle
= DeviceBlock
;
3029 return NDIS_STATUS_SUCCESS
;
3037 NdisMDeregisterDevice(
3038 IN NDIS_HANDLE NdisDeviceHandle
)
3046 PNDIS_M_DEVICE_BLOCK DeviceBlock
= NdisDeviceHandle
;
3048 IoDeleteDevice(DeviceBlock
->DeviceObject
);
3050 IoDeleteSymbolicLink(DeviceBlock
->SymbolicName
);
3052 ExFreePool(DeviceBlock
);
3054 return NDIS_STATUS_SUCCESS
;
3062 NdisQueryAdapterInstanceName(
3063 OUT PNDIS_STRING AdapterInstanceName
,
3064 IN NDIS_HANDLE NdisBindingHandle
)
3072 PADAPTER_BINDING AdapterBinding
= NdisBindingHandle
;
3073 PLOGICAL_ADAPTER Adapter
= AdapterBinding
->Adapter
;
3075 return NdisMQueryAdapterInstanceName(AdapterInstanceName
,
3084 NdisCompletePnPEvent(
3085 IN NDIS_STATUS Status
,
3086 IN NDIS_HANDLE NdisBindingHandle
,
3087 IN PNET_PNP_EVENT NetPnPEvent
)
3095 PIRP Irp
= (PIRP
)NetPnPEvent
->NdisReserved
[0];
3096 PLIST_ENTRY CurrentEntry
= (PLIST_ENTRY
)NetPnPEvent
->NdisReserved
[1];
3097 PADAPTER_BINDING AdapterBinding
= NdisBindingHandle
;
3098 PLOGICAL_ADAPTER Adapter
= AdapterBinding
->Adapter
;
3099 NDIS_STATUS NdisStatus
;
3101 if (Status
!= NDIS_STATUS_SUCCESS
)
3103 if (NetPnPEvent
->Buffer
) ExFreePool(NetPnPEvent
->Buffer
);
3104 ExFreePool(NetPnPEvent
);
3105 Irp
->IoStatus
.Status
= Status
;
3106 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
3110 while (CurrentEntry
!= &Adapter
->ProtocolListHead
)
3112 AdapterBinding
= CONTAINING_RECORD(CurrentEntry
, ADAPTER_BINDING
, AdapterListEntry
);
3114 NdisStatus
= (*AdapterBinding
->ProtocolBinding
->Chars
.PnPEventHandler
)(
3115 AdapterBinding
->NdisOpenBlock
.ProtocolBindingContext
,
3118 if (NdisStatus
== NDIS_STATUS_PENDING
)
3120 NetPnPEvent
->NdisReserved
[1] = (ULONG_PTR
)CurrentEntry
->Flink
;
3123 else if (NdisStatus
!= NDIS_STATUS_SUCCESS
)
3125 if (NetPnPEvent
->Buffer
) ExFreePool(NetPnPEvent
->Buffer
);
3126 ExFreePool(NetPnPEvent
);
3127 Irp
->IoStatus
.Status
= NdisStatus
;
3128 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
3132 CurrentEntry
= CurrentEntry
->Flink
;
3135 if (NetPnPEvent
->Buffer
) ExFreePool(NetPnPEvent
->Buffer
);
3136 ExFreePool(NetPnPEvent
);
3138 Irp
->IoStatus
.Status
= NDIS_STATUS_SUCCESS
;
3139 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
3147 NdisCancelSendPackets(
3148 IN NDIS_HANDLE NdisBindingHandle
,
3151 PADAPTER_BINDING AdapterBinding
= NdisBindingHandle
;
3152 PLOGICAL_ADAPTER Adapter
= AdapterBinding
->Adapter
;
3154 NDIS_DbgPrint(MAX_TRACE
, ("Called for ID %x.\n", CancelId
));
3156 if (Adapter
->NdisMiniportBlock
.DriverHandle
->MiniportCharacteristics
.CancelSendPacketsHandler
)
3158 (*Adapter
->NdisMiniportBlock
.DriverHandle
->MiniportCharacteristics
.CancelSendPacketsHandler
)(
3159 Adapter
->NdisMiniportBlock
.MiniportAdapterContext
,
3170 NdisIMGetBindingContext(
3171 IN NDIS_HANDLE NdisBindingHandle
)
3179 PADAPTER_BINDING AdapterBinding
= NdisBindingHandle
;
3180 PLOGICAL_ADAPTER Adapter
= AdapterBinding
->Adapter
;
3182 NDIS_DbgPrint(MAX_TRACE
, ("Called.\n"));
3184 return Adapter
->NdisMiniportBlock
.DeviceContext
;
3193 NdisIMGetDeviceContext(
3194 IN NDIS_HANDLE MiniportAdapterHandle
)
3202 PLOGICAL_ADAPTER Adapter
= MiniportAdapterHandle
;
3204 NDIS_DbgPrint(MAX_TRACE
, ("Called.\n"));
3206 return Adapter
->NdisMiniportBlock
.DeviceContext
;