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
17 * Define to 1 to get a debugger breakpoint at the end of NdisInitializeWrapper
18 * for each new miniport starting up
20 #define BREAK_ON_MINIPORT_INIT 0
23 * This has to be big enough to hold the results of querying the Route value
24 * from the Linkage key. Please re-code me to determine this dynamically.
26 #define ROUTE_DATA_SIZE 256
28 /* Number of media we know */
29 #define MEDIA_ARRAY_SIZE 15
31 static NDIS_MEDIUM MediaArray
[MEDIA_ARRAY_SIZE
] =
40 NdisMediumArcnet878_2
,
42 NdisMediumWirelessWan
,
50 /* global list and lock of Miniports NDIS has registered */
51 LIST_ENTRY MiniportListHead
;
52 KSPIN_LOCK MiniportListLock
;
54 /* global list and lock of adapters NDIS has registered */
55 LIST_ENTRY AdapterListHead
;
56 KSPIN_LOCK AdapterListLock
;
65 if ((DebugTraceLevel
& DEBUG_PACKET
) > 0) {
66 Length
= CopyPacketToBuffer(
72 DbgPrint("*** PACKET START ***");
74 for (i
= 0; i
< Length
; i
++) {
76 DbgPrint("\n%04X ", i
);
77 DbgPrint("%02X ", Buffer
[i
]);
80 DbgPrint("*** PACKET STOP ***\n");
88 UINT HeaderBufferSize
,
89 PVOID LookaheadBuffer
,
90 UINT LookaheadBufferSize
)
93 if ((DebugTraceLevel
& DEBUG_PACKET
) > 0) {
97 DbgPrint("*** RECEIVE PACKET START ***\n");
100 for (i
= 0; i
< HeaderBufferSize
; i
++) {
102 DbgPrint("\n%04X ", i
);
103 DbgPrint("%02X ", *p
++);
106 DbgPrint("\nFRAME:");
109 Length
= (LookaheadBufferSize
< 64)? LookaheadBufferSize
: 64;
110 for (i
= 0; i
< Length
; i
++) {
112 DbgPrint("\n%04X ", i
);
113 DbgPrint("%02X ", *p
++);
116 DbgPrint("\n*** RECEIVE PACKET STOP ***\n");
121 PNDIS_MINIPORT_WORK_ITEM
122 MiniGetFirstWorkItem(
123 PLOGICAL_ADAPTER Adapter
,
124 NDIS_WORK_ITEM_TYPE Type
)
126 PNDIS_MINIPORT_WORK_ITEM CurrentEntry
= Adapter
->WorkQueueHead
;
130 if (CurrentEntry
->WorkItemType
== Type
)
133 CurrentEntry
= (PNDIS_MINIPORT_WORK_ITEM
)CurrentEntry
->Link
.Next
;
141 PLOGICAL_ADAPTER Adapter
,
142 NDIS_WORK_ITEM_TYPE Type
)
144 BOOLEAN Busy
= FALSE
;
147 KeAcquireSpinLock(&Adapter
->NdisMiniportBlock
.Lock
, &OldIrql
);
149 if (Type
== NdisWorkItemRequest
&&
150 (Adapter
->NdisMiniportBlock
.PendingRequest
|| MiniGetFirstWorkItem(Adapter
, NdisWorkItemRequest
)))
154 else if (Type
== NdisWorkItemSend
&&
155 (Adapter
->NdisMiniportBlock
.FirstPendingPacket
|| MiniGetFirstWorkItem(Adapter
, NdisWorkItemSend
)))
159 else if (Type
== NdisWorkItemResetRequested
&&
160 (Adapter
->NdisMiniportBlock
.ResetStatus
== NDIS_STATUS_PENDING
|| MiniGetFirstWorkItem(Adapter
, NdisWorkItemResetRequested
)))
165 KeReleaseSpinLock(&Adapter
->NdisMiniportBlock
.Lock
, OldIrql
);
172 PLOGICAL_ADAPTER Adapter
,
173 NDIS_HANDLE MacReceiveContext
,
175 UINT HeaderBufferSize
,
176 PVOID LookaheadBuffer
,
177 UINT LookaheadBufferSize
,
180 * FUNCTION: Indicate received data to bound protocols
182 * Adapter = Pointer to logical adapter
183 * MacReceiveContext = MAC receive context handle
184 * HeaderBuffer = Pointer to header buffer
185 * HeaderBufferSize = Size of header buffer
186 * LookaheadBuffer = Pointer to lookahead buffer
187 * LookaheadBufferSize = Size of lookahead buffer
188 * PacketSize = Total size of received packet
192 PLIST_ENTRY CurrentEntry
;
193 PADAPTER_BINDING AdapterBinding
;
195 NDIS_DbgPrint(DEBUG_MINIPORT
, ("Called. Adapter (0x%X) HeaderBuffer (0x%X) "
196 "HeaderBufferSize (0x%X) LookaheadBuffer (0x%X) LookaheadBufferSize (0x%X).\n",
197 Adapter
, HeaderBuffer
, HeaderBufferSize
, LookaheadBuffer
, LookaheadBufferSize
));
199 MiniDisplayPacket2(HeaderBuffer
, HeaderBufferSize
, LookaheadBuffer
, LookaheadBufferSize
);
201 NDIS_DbgPrint(MAX_TRACE
, ("acquiring miniport block lock\n"));
202 KeAcquireSpinLock(&Adapter
->NdisMiniportBlock
.Lock
, &OldIrql
);
204 CurrentEntry
= Adapter
->ProtocolListHead
.Flink
;
205 NDIS_DbgPrint(DEBUG_MINIPORT
, ("CurrentEntry = %x\n", CurrentEntry
));
207 if (CurrentEntry
== &Adapter
->ProtocolListHead
)
209 NDIS_DbgPrint(MIN_TRACE
, ("WARNING: No upper protocol layer.\n"));
212 while (CurrentEntry
!= &Adapter
->ProtocolListHead
)
214 AdapterBinding
= CONTAINING_RECORD(CurrentEntry
, ADAPTER_BINDING
, AdapterListEntry
);
215 NDIS_DbgPrint(DEBUG_MINIPORT
, ("AdapterBinding = %x\n", AdapterBinding
));
219 ("XXX (%x) %x %x %x %x %x %x %x XXX\n",
220 *AdapterBinding
->ProtocolBinding
->Chars
.ReceiveHandler
,
221 AdapterBinding
->NdisOpenBlock
.ProtocolBindingContext
,
229 /* call the receive handler */
230 (*AdapterBinding
->ProtocolBinding
->Chars
.ReceiveHandler
)(
231 AdapterBinding
->NdisOpenBlock
.ProtocolBindingContext
,
239 CurrentEntry
= CurrentEntry
->Flink
;
242 KeReleaseSpinLock(&Adapter
->NdisMiniportBlock
.Lock
, OldIrql
);
244 NDIS_DbgPrint(MAX_TRACE
, ("Leaving.\n"));
253 IN PNDIS_PACKET
*PacketsToReturn
,
254 IN UINT NumberOfPackets
)
256 * FUNCTION: Releases ownership of one or more packets
258 * PacketsToReturn = Pointer to an array of pointers to packet descriptors
259 * NumberOfPackets = Number of pointers in descriptor pointer array
263 PLOGICAL_ADAPTER Adapter
;
266 NDIS_DbgPrint(MID_TRACE
, ("Returning %d packets\n", NumberOfPackets
));
268 for (i
= 0; i
< NumberOfPackets
; i
++)
270 PacketsToReturn
[i
]->WrapperReserved
[0]--;
271 if (PacketsToReturn
[i
]->WrapperReserved
[0] == 0)
273 Adapter
= (PVOID
)(ULONG_PTR
)PacketsToReturn
[i
]->Reserved
[1];
275 NDIS_DbgPrint(MAX_TRACE
, ("Freeing packet %d (adapter = 0x%p)\n", i
, Adapter
));
277 KeRaiseIrql(DISPATCH_LEVEL
, &OldIrql
);
278 Adapter
->NdisMiniportBlock
.DriverHandle
->MiniportCharacteristics
.ReturnPacketHandler(
279 Adapter
->NdisMiniportBlock
.MiniportAdapterContext
,
281 KeLowerIrql(OldIrql
);
287 MiniIndicateReceivePacket(
288 IN NDIS_HANDLE MiniportAdapterHandle
,
289 IN PPNDIS_PACKET PacketArray
,
290 IN UINT NumberOfPackets
)
292 * FUNCTION: receives miniport packet array indications
294 * MiniportAdapterHandle: Miniport handle for the adapter
295 * PacketArray: pointer to a list of packet pointers to indicate
296 * NumberOfPackets: number of packets to indicate
300 PLOGICAL_ADAPTER Adapter
= MiniportAdapterHandle
;
301 PLIST_ENTRY CurrentEntry
;
302 PADAPTER_BINDING AdapterBinding
;
306 KeAcquireSpinLock(&Adapter
->NdisMiniportBlock
.Lock
, &OldIrql
);
308 CurrentEntry
= Adapter
->ProtocolListHead
.Flink
;
310 while (CurrentEntry
!= &Adapter
->ProtocolListHead
)
312 AdapterBinding
= CONTAINING_RECORD(CurrentEntry
, ADAPTER_BINDING
, AdapterListEntry
);
314 for (i
= 0; i
< NumberOfPackets
; i
++)
316 /* Store the indicating miniport in the packet */
317 PacketArray
[i
]->Reserved
[1] = (ULONG_PTR
)Adapter
;
319 if (AdapterBinding
->ProtocolBinding
->Chars
.ReceivePacketHandler
&&
320 NDIS_GET_PACKET_STATUS(PacketArray
[i
]) != NDIS_STATUS_RESOURCES
)
322 NDIS_DbgPrint(MID_TRACE
, ("Indicating packet to protocol's ReceivePacket handler\n"));
323 PacketArray
[i
]->WrapperReserved
[0] += (*AdapterBinding
->ProtocolBinding
->Chars
.ReceivePacketHandler
)(
324 AdapterBinding
->NdisOpenBlock
.ProtocolBindingContext
,
326 NDIS_DbgPrint(MID_TRACE
, ("Protocol is holding %d references to the packet\n", PacketArray
[i
]->WrapperReserved
[0]));
330 UINT FirstBufferLength
, TotalBufferLength
, LookAheadSize
, HeaderSize
;
331 PNDIS_BUFFER NdisBuffer
;
332 PVOID NdisBufferVA
, LookAheadBuffer
;
334 NdisGetFirstBufferFromPacket(PacketArray
[i
],
340 HeaderSize
= NDIS_GET_PACKET_HEADER_SIZE(PacketArray
[i
]);
342 LookAheadSize
= TotalBufferLength
- HeaderSize
;
344 LookAheadBuffer
= ExAllocatePool(NonPagedPool
, LookAheadSize
);
345 if (!LookAheadBuffer
)
347 NDIS_DbgPrint(MIN_TRACE
, ("Failed to allocate lookahead buffer!\n"));
348 KeReleaseSpinLock(&Adapter
->NdisMiniportBlock
.Lock
, OldIrql
);
352 CopyBufferChainToBuffer(LookAheadBuffer
,
357 NDIS_DbgPrint(MID_TRACE
, ("Indicating packet to protocol's legacy Receive handler\n"));
358 (*AdapterBinding
->ProtocolBinding
->Chars
.ReceiveHandler
)(
359 AdapterBinding
->NdisOpenBlock
.ProtocolBindingContext
,
360 AdapterBinding
->NdisOpenBlock
.MacHandle
,
365 TotalBufferLength
- HeaderSize
);
367 ExFreePool(LookAheadBuffer
);
371 CurrentEntry
= CurrentEntry
->Flink
;
374 /* Loop the packet array to get everything
375 * set up for return the packets to the miniport */
376 for (i
= 0; i
< NumberOfPackets
; i
++)
378 /* First, check the initial packet status */
379 if (NDIS_GET_PACKET_STATUS(PacketArray
[i
]) == NDIS_STATUS_RESOURCES
)
381 /* The miniport driver gets it back immediately so nothing to do here */
382 NDIS_DbgPrint(MID_TRACE
, ("Miniport needs the packet back immediately\n"));
386 /* Different behavior depending on whether it's serialized or not */
387 if (Adapter
->NdisMiniportBlock
.Flags
& NDIS_ATTRIBUTE_DESERIALIZE
)
389 /* We need to check the reference count */
390 if (PacketArray
[i
]->WrapperReserved
[0] == 0)
392 /* NOTE: Unlike serialized miniports, this is REQUIRED to be called for each
393 * packet received that can be reused immediately, it is not implied! */
394 Adapter
->NdisMiniportBlock
.DriverHandle
->MiniportCharacteristics
.ReturnPacketHandler(
395 Adapter
->NdisMiniportBlock
.MiniportAdapterContext
,
397 NDIS_DbgPrint(MID_TRACE
, ("Packet has been returned to miniport (Deserialized)\n"));
401 /* Packet will be returned by the protocol's call to NdisReturnPackets */
402 NDIS_DbgPrint(MID_TRACE
, ("Packet will be returned to miniport later (Deserialized)\n"));
407 /* Check the reference count */
408 if (PacketArray
[i
]->WrapperReserved
[0] == 0)
410 /* NDIS_STATUS_SUCCESS means the miniport can have the packet back immediately */
411 NDIS_SET_PACKET_STATUS(PacketArray
[i
], NDIS_STATUS_SUCCESS
);
413 NDIS_DbgPrint(MID_TRACE
, ("Packet has been returned to miniport (Serialized)\n"));
417 /* NDIS_STATUS_PENDING means the miniport needs to wait for MiniportReturnPacket */
418 NDIS_SET_PACKET_STATUS(PacketArray
[i
], NDIS_STATUS_PENDING
);
420 NDIS_DbgPrint(MID_TRACE
, ("Packet will be returned to miniport later (Serialized)\n"));
425 KeReleaseSpinLock(&Adapter
->NdisMiniportBlock
.Lock
, OldIrql
);
430 IN NDIS_HANDLE MiniportAdapterHandle
,
431 IN NDIS_STATUS Status
,
432 IN BOOLEAN AddressingReset
)
434 PLOGICAL_ADAPTER Adapter
= MiniportAdapterHandle
;
435 PLIST_ENTRY CurrentEntry
;
436 PADAPTER_BINDING AdapterBinding
;
440 MiniDoAddressingReset(Adapter
);
442 NdisMIndicateStatus(Adapter
, NDIS_STATUS_RESET_END
, NULL
, 0);
443 NdisMIndicateStatusComplete(Adapter
);
445 KeAcquireSpinLock(&Adapter
->NdisMiniportBlock
.Lock
, &OldIrql
);
447 if (Adapter
->NdisMiniportBlock
.ResetStatus
!= NDIS_STATUS_PENDING
)
449 KeBugCheckEx(BUGCODE_ID_DRIVER
,
450 (ULONG_PTR
)MiniportAdapterHandle
,
452 (ULONG_PTR
)AddressingReset
,
456 Adapter
->NdisMiniportBlock
.ResetStatus
= Status
;
458 CurrentEntry
= Adapter
->ProtocolListHead
.Flink
;
460 while (CurrentEntry
!= &Adapter
->ProtocolListHead
)
462 AdapterBinding
= CONTAINING_RECORD(CurrentEntry
, ADAPTER_BINDING
, AdapterListEntry
);
464 (*AdapterBinding
->ProtocolBinding
->Chars
.ResetCompleteHandler
)(
465 AdapterBinding
->NdisOpenBlock
.ProtocolBindingContext
,
468 CurrentEntry
= CurrentEntry
->Flink
;
471 KeReleaseSpinLock(&Adapter
->NdisMiniportBlock
.Lock
, OldIrql
);
476 IN NDIS_HANDLE MiniportAdapterHandle
,
477 IN NDIS_STATUS Status
)
479 PLOGICAL_ADAPTER Adapter
= (PLOGICAL_ADAPTER
)MiniportAdapterHandle
;
480 PNDIS_REQUEST Request
;
481 PNDIS_REQUEST_MAC_BLOCK MacBlock
;
484 NDIS_DbgPrint(DEBUG_MINIPORT
, ("Called.\n"));
486 KeRaiseIrql(DISPATCH_LEVEL
, &OldIrql
);
488 KeAcquireSpinLockAtDpcLevel(&Adapter
->NdisMiniportBlock
.Lock
);
489 Request
= Adapter
->NdisMiniportBlock
.PendingRequest
;
490 KeReleaseSpinLockFromDpcLevel(&Adapter
->NdisMiniportBlock
.Lock
);
492 MacBlock
= (PNDIS_REQUEST_MAC_BLOCK
)Request
->MacReserved
;
494 if( MacBlock
->Binding
->RequestCompleteHandler
) {
495 (*MacBlock
->Binding
->RequestCompleteHandler
)(
496 MacBlock
->Binding
->ProtocolBindingContext
,
501 KeAcquireSpinLockAtDpcLevel(&Adapter
->NdisMiniportBlock
.Lock
);
502 Adapter
->NdisMiniportBlock
.PendingRequest
= NULL
;
503 KeReleaseSpinLockFromDpcLevel(&Adapter
->NdisMiniportBlock
.Lock
);
505 KeLowerIrql(OldIrql
);
510 IN NDIS_HANDLE MiniportAdapterHandle
,
511 IN PNDIS_PACKET Packet
,
512 IN NDIS_STATUS Status
)
514 * FUNCTION: Forwards a message to the initiating protocol saying
515 * that a packet was handled
517 * NdisAdapterHandle = Handle input to MiniportInitialize
518 * Packet = Pointer to NDIS packet that was sent
519 * Status = Status of send operation
522 PLOGICAL_ADAPTER Adapter
= MiniportAdapterHandle
;
523 PADAPTER_BINDING AdapterBinding
;
525 PSCATTER_GATHER_LIST SGList
;
527 NDIS_DbgPrint(DEBUG_MINIPORT
, ("Called.\n"));
529 AdapterBinding
= (PADAPTER_BINDING
)Packet
->Reserved
[1];
531 KeRaiseIrql(DISPATCH_LEVEL
, &OldIrql
);
533 if (Adapter
->NdisMiniportBlock
.ScatterGatherListSize
!= 0)
535 NDIS_DbgPrint(MAX_TRACE
, ("Freeing Scatter/Gather list\n"));
537 SGList
= NDIS_PER_PACKET_INFO_FROM_PACKET(Packet
,
538 ScatterGatherListPacketInfo
);
540 Adapter
->NdisMiniportBlock
.SystemAdapterObject
->
541 DmaOperations
->PutScatterGatherList(
542 Adapter
->NdisMiniportBlock
.SystemAdapterObject
,
546 NDIS_PER_PACKET_INFO_FROM_PACKET(Packet
,
547 ScatterGatherListPacketInfo
) = NULL
;
550 (*AdapterBinding
->ProtocolBinding
->Chars
.SendCompleteHandler
)(
551 AdapterBinding
->NdisOpenBlock
.ProtocolBindingContext
,
555 KeLowerIrql(OldIrql
);
560 MiniSendResourcesAvailable(
561 IN NDIS_HANDLE MiniportAdapterHandle
)
570 MiniTransferDataComplete(
571 IN NDIS_HANDLE MiniportAdapterHandle
,
572 IN PNDIS_PACKET Packet
,
573 IN NDIS_STATUS Status
,
574 IN UINT BytesTransferred
)
576 PADAPTER_BINDING AdapterBinding
;
579 NDIS_DbgPrint(DEBUG_MINIPORT
, ("Called.\n"));
581 AdapterBinding
= (PADAPTER_BINDING
)Packet
->Reserved
[1];
583 KeRaiseIrql(DISPATCH_LEVEL
, &OldIrql
);
584 (*AdapterBinding
->ProtocolBinding
->Chars
.TransferDataCompleteHandler
)(
585 AdapterBinding
->NdisOpenBlock
.ProtocolBindingContext
,
589 KeLowerIrql(OldIrql
);
594 MiniAdapterHasAddress(
595 PLOGICAL_ADAPTER Adapter
,
598 * FUNCTION: Determines whether a packet has the same destination address as an adapter
600 * Adapter = Pointer to logical adapter object
601 * Packet = Pointer to NDIS packet
603 * TRUE if the destination address is that of the adapter, FALSE if not
609 PNDIS_BUFFER NdisBuffer
;
612 NDIS_DbgPrint(DEBUG_MINIPORT
, ("Called.\n"));
617 NDIS_DbgPrint(MIN_TRACE
, ("Adapter object was null\n"));
623 NDIS_DbgPrint(MIN_TRACE
, ("Packet was null\n"));
628 NdisQueryPacket(Packet
, NULL
, NULL
, &NdisBuffer
, NULL
);
632 NDIS_DbgPrint(MIN_TRACE
, ("Packet contains no buffers.\n"));
636 NdisQueryBuffer(NdisBuffer
, (PVOID
)&Start2
, &BufferLength
);
638 /* FIXME: Should handle fragmented packets */
640 switch (Adapter
->NdisMiniportBlock
.MediaType
)
642 case NdisMedium802_3
:
643 Length
= ETH_LENGTH_OF_ADDRESS
;
644 /* Destination address is the first field */
648 NDIS_DbgPrint(MIN_TRACE
, ("Adapter has unsupported media type (0x%X).\n", Adapter
->NdisMiniportBlock
.MediaType
));
652 if (BufferLength
< Length
)
654 NDIS_DbgPrint(MIN_TRACE
, ("Buffer is too small.\n"));
658 Start1
= (PUCHAR
)&Adapter
->Address
;
659 NDIS_DbgPrint(MAX_TRACE
, ("packet address: %x:%x:%x:%x:%x:%x adapter address: %x:%x:%x:%x:%x:%x\n",
660 *((char *)Start1
), *(((char *)Start1
)+1), *(((char *)Start1
)+2), *(((char *)Start1
)+3), *(((char *)Start1
)+4), *(((char *)Start1
)+5),
661 *((char *)Start2
), *(((char *)Start2
)+1), *(((char *)Start2
)+2), *(((char *)Start2
)+3), *(((char *)Start2
)+4), *(((char *)Start2
)+5)));
663 return (RtlCompareMemory((PVOID
)Start1
, (PVOID
)Start2
, Length
) == Length
);
669 PNDIS_STRING AdapterName
)
671 * FUNCTION: Finds an adapter object by name
673 * AdapterName = Pointer to name of adapter
675 * Pointer to logical adapter object, or NULL if none was found.
676 * If found, the adapter is referenced for the caller. The caller
677 * is responsible for dereferencing after use
681 PLIST_ENTRY CurrentEntry
;
682 PLOGICAL_ADAPTER Adapter
= 0;
686 NDIS_DbgPrint(DEBUG_MINIPORT
, ("Called.\n"));
688 if(IsListEmpty(&AdapterListHead
))
690 NDIS_DbgPrint(MIN_TRACE
, ("No registered miniports for protocol to bind to\n"));
694 NDIS_DbgPrint(DEBUG_MINIPORT
, ("AdapterName = %wZ\n", AdapterName
));
696 KeAcquireSpinLock(&AdapterListLock
, &OldIrql
);
698 CurrentEntry
= AdapterListHead
.Flink
;
700 while (CurrentEntry
!= &AdapterListHead
)
702 Adapter
= CONTAINING_RECORD(CurrentEntry
, LOGICAL_ADAPTER
, ListEntry
);
706 NDIS_DbgPrint(DEBUG_MINIPORT
, ("Examining adapter 0x%lx\n", Adapter
));
708 /* We're technically not allowed to call this above PASSIVE_LEVEL, but it doesn't break
709 * right now and I'd rather use a working API than reimplement it here */
710 if (RtlCompareUnicodeString(AdapterName
, &Adapter
->NdisMiniportBlock
.MiniportName
, TRUE
) == 0)
716 CurrentEntry
= CurrentEntry
->Flink
;
719 KeReleaseSpinLock(&AdapterListLock
, OldIrql
);
723 NDIS_DbgPrint(DEBUG_MINIPORT
, ("Leaving. Adapter found at 0x%x\n", Adapter
));
727 NDIS_DbgPrint(MIN_TRACE
, ("Leaving (adapter not found for %wZ).\n", AdapterName
));
735 PLOGICAL_ADAPTER Adapter
,
741 NDIS_STATUS NdisStatus
;
742 PNDIS_REQUEST NdisRequest
;
744 NDIS_DbgPrint(DEBUG_MINIPORT
, ("Called.\n"));
746 NdisRequest
= ExAllocatePool(NonPagedPool
, sizeof(NDIS_REQUEST
));
748 NDIS_DbgPrint(MIN_TRACE
, ("Insufficient resources\n"));
749 return NDIS_STATUS_RESOURCES
;
752 RtlZeroMemory(NdisRequest
, sizeof(NDIS_REQUEST
));
754 NdisRequest
->RequestType
= NdisRequestSetInformation
;
755 NdisRequest
->DATA
.SET_INFORMATION
.Oid
= Oid
;
756 NdisRequest
->DATA
.SET_INFORMATION
.InformationBuffer
= Buffer
;
757 NdisRequest
->DATA
.SET_INFORMATION
.InformationBufferLength
= Size
;
759 NdisStatus
= MiniDoRequest(Adapter
, NdisRequest
);
761 /* FIXME: Wait in pending case! */
763 ASSERT(NdisStatus
!= NDIS_STATUS_PENDING
);
765 *BytesRead
= NdisRequest
->DATA
.SET_INFORMATION
.BytesRead
;
767 ExFreePool(NdisRequest
);
773 MiniQueryInformation(
774 PLOGICAL_ADAPTER Adapter
,
780 * FUNCTION: Queries a logical adapter for properties
782 * Adapter = Pointer to the logical adapter object to query
783 * Oid = Specifies the Object ID to query for
784 * Size = Size of the passed buffer
785 * Buffer = Buffer for the output
786 * BytesWritten = Address of buffer to place number of bytes written
788 * Status of operation
791 NDIS_STATUS NdisStatus
;
792 PNDIS_REQUEST NdisRequest
;
794 NDIS_DbgPrint(DEBUG_MINIPORT
, ("Called.\n"));
796 NdisRequest
= ExAllocatePool(NonPagedPool
, sizeof(NDIS_REQUEST
));
798 NDIS_DbgPrint(MIN_TRACE
, ("Insufficient resources\n"));
799 return NDIS_STATUS_RESOURCES
;
802 RtlZeroMemory(NdisRequest
, sizeof(NDIS_REQUEST
));
804 NdisRequest
->RequestType
= NdisRequestQueryInformation
;
805 NdisRequest
->DATA
.QUERY_INFORMATION
.Oid
= Oid
;
806 NdisRequest
->DATA
.QUERY_INFORMATION
.InformationBuffer
= Buffer
;
807 NdisRequest
->DATA
.QUERY_INFORMATION
.InformationBufferLength
= Size
;
809 NdisStatus
= MiniDoRequest(Adapter
, NdisRequest
);
811 /* FIXME: Wait in pending case! */
813 ASSERT(NdisStatus
!= NDIS_STATUS_PENDING
);
815 *BytesWritten
= NdisRequest
->DATA
.QUERY_INFORMATION
.BytesWritten
;
817 ExFreePool(NdisRequest
);
823 MiniCheckForHang( PLOGICAL_ADAPTER Adapter
)
825 * FUNCTION: Checks to see if the miniport is hung
827 * Adapter = Pointer to the logical adapter object
829 * TRUE if the miniport is hung
830 * FALSE if the miniport is not hung
836 KeRaiseIrql(DISPATCH_LEVEL
, &OldIrql
);
837 if (Adapter
->NdisMiniportBlock
.DriverHandle
->MiniportCharacteristics
.CheckForHangHandler
)
838 Ret
= (*Adapter
->NdisMiniportBlock
.DriverHandle
->MiniportCharacteristics
.CheckForHangHandler
)(
839 Adapter
->NdisMiniportBlock
.MiniportAdapterContext
);
840 KeLowerIrql(OldIrql
);
846 MiniDoAddressingReset(PLOGICAL_ADAPTER Adapter
)
850 MiniSetInformation(Adapter
,
851 OID_GEN_CURRENT_LOOKAHEAD
,
853 &Adapter
->NdisMiniportBlock
.CurrentLookahead
,
856 /* FIXME: Set more stuff */
861 PLOGICAL_ADAPTER Adapter
)
863 * FUNCTION: Resets the miniport
865 * Adapter = Pointer to the logical adapter object
867 * Status of the operation
872 BOOLEAN AddressingReset
= TRUE
;
874 if (MiniIsBusy(Adapter
, NdisWorkItemResetRequested
)) {
875 MiniQueueWorkItem(Adapter
, NdisWorkItemResetRequested
, NULL
, FALSE
);
876 return NDIS_STATUS_PENDING
;
879 NdisMIndicateStatus(Adapter
, NDIS_STATUS_RESET_START
, NULL
, 0);
880 NdisMIndicateStatusComplete(Adapter
);
882 KeRaiseIrql(DISPATCH_LEVEL
, &OldIrql
);
883 Status
= (*Adapter
->NdisMiniportBlock
.DriverHandle
->MiniportCharacteristics
.ResetHandler
)(
884 Adapter
->NdisMiniportBlock
.MiniportAdapterContext
,
887 KeAcquireSpinLockAtDpcLevel(&Adapter
->NdisMiniportBlock
.Lock
);
888 Adapter
->NdisMiniportBlock
.ResetStatus
= Status
;
889 KeReleaseSpinLockFromDpcLevel(&Adapter
->NdisMiniportBlock
.Lock
);
891 KeLowerIrql(OldIrql
);
893 if (Status
!= NDIS_STATUS_PENDING
) {
895 MiniDoAddressingReset(Adapter
);
897 NdisMIndicateStatus(Adapter
, NDIS_STATUS_RESET_END
, NULL
, 0);
898 NdisMIndicateStatusComplete(Adapter
);
907 PVOID DeferredContext
,
908 PVOID SystemArgument1
,
909 PVOID SystemArgument2
)
911 PLOGICAL_ADAPTER Adapter
= DeferredContext
;
913 if (MiniCheckForHang(Adapter
)) {
914 NDIS_DbgPrint(MIN_TRACE
, ("Miniport detected adapter hang\n"));
922 PLOGICAL_ADAPTER Adapter
,
923 NDIS_WORK_ITEM_TYPE WorkItemType
,
924 PVOID WorkItemContext
,
927 * FUNCTION: Queues a work item for execution at a later time
929 * Adapter = Pointer to the logical adapter object to queue work item on
930 * WorkItemType = Type of work item to queue
931 * WorkItemContext = Pointer to context information for work item
933 * Status of operation
936 PNDIS_MINIPORT_WORK_ITEM MiniportWorkItem
;
937 PIO_WORKITEM IoWorkItem
;
940 NDIS_DbgPrint(MAX_TRACE
, ("Called.\n"));
944 KeAcquireSpinLock(&Adapter
->NdisMiniportBlock
.Lock
, &OldIrql
);
947 if (WorkItemType
== NdisWorkItemSend
)
949 NDIS_DbgPrint(MIN_TRACE
, ("Requeuing failed packet (%x).\n", WorkItemContext
));
950 Adapter
->NdisMiniportBlock
.FirstPendingPacket
= WorkItemContext
;
954 //This should never happen
960 MiniportWorkItem
= ExAllocatePool(NonPagedPool
, sizeof(NDIS_MINIPORT_WORK_ITEM
));
961 if (!MiniportWorkItem
)
963 KeReleaseSpinLock(&Adapter
->NdisMiniportBlock
.Lock
, OldIrql
);
964 NDIS_DbgPrint(MIN_TRACE
, ("Insufficient resources.\n"));
968 MiniportWorkItem
->WorkItemType
= WorkItemType
;
969 MiniportWorkItem
->WorkItemContext
= WorkItemContext
;
971 /* safe due to adapter lock held */
972 MiniportWorkItem
->Link
.Next
= NULL
;
973 if (!Adapter
->WorkQueueHead
)
975 Adapter
->WorkQueueHead
= MiniportWorkItem
;
976 Adapter
->WorkQueueTail
= MiniportWorkItem
;
980 Adapter
->WorkQueueTail
->Link
.Next
= (PSINGLE_LIST_ENTRY
)MiniportWorkItem
;
981 Adapter
->WorkQueueTail
= MiniportWorkItem
;
985 IoWorkItem
= IoAllocateWorkItem(Adapter
->NdisMiniportBlock
.DeviceObject
);
987 IoQueueWorkItem(IoWorkItem
, MiniportWorker
, DelayedWorkQueue
, IoWorkItem
);
989 KeReleaseSpinLock(&Adapter
->NdisMiniportBlock
.Lock
, OldIrql
);
995 PLOGICAL_ADAPTER Adapter
,
996 NDIS_WORK_ITEM_TYPE
*WorkItemType
,
997 PVOID
*WorkItemContext
)
999 * FUNCTION: Dequeues a work item from the work queue of a logical adapter
1001 * Adapter = Pointer to the logical adapter object to dequeue work item from
1002 * AdapterBinding = Address of buffer for adapter binding for this request
1003 * WorkItemType = Address of buffer for work item type
1004 * WorkItemContext = Address of buffer for pointer to context information
1006 * Adapter lock must be held when called
1008 * Status of operation
1011 PNDIS_MINIPORT_WORK_ITEM MiniportWorkItem
;
1012 PNDIS_PACKET Packet
;
1014 NDIS_DbgPrint(MAX_TRACE
, ("Called.\n"));
1016 MiniportWorkItem
= Adapter
->WorkQueueHead
;
1018 if ((Packet
= Adapter
->NdisMiniportBlock
.FirstPendingPacket
))
1020 Adapter
->NdisMiniportBlock
.FirstPendingPacket
= NULL
;
1022 *WorkItemType
= NdisWorkItemSend
;
1023 *WorkItemContext
= Packet
;
1025 return NDIS_STATUS_SUCCESS
;
1027 else if (MiniportWorkItem
)
1029 /* safe due to adapter lock held */
1030 Adapter
->WorkQueueHead
= (PNDIS_MINIPORT_WORK_ITEM
)MiniportWorkItem
->Link
.Next
;
1032 if (MiniportWorkItem
== Adapter
->WorkQueueTail
)
1033 Adapter
->WorkQueueTail
= NULL
;
1035 *WorkItemType
= MiniportWorkItem
->WorkItemType
;
1036 *WorkItemContext
= MiniportWorkItem
->WorkItemContext
;
1038 ExFreePool(MiniportWorkItem
);
1040 return NDIS_STATUS_SUCCESS
;
1044 NDIS_DbgPrint(MIN_TRACE
, ("No work item to dequeue\n"));
1046 return NDIS_STATUS_FAILURE
;
1052 PLOGICAL_ADAPTER Adapter
,
1053 PNDIS_REQUEST NdisRequest
)
1055 * FUNCTION: Sends a request to a miniport
1057 * AdapterBinding = Pointer to binding used in the request
1058 * NdisRequest = Pointer to NDIS request structure describing request
1060 * Status of operation
1065 NDIS_DbgPrint(DEBUG_MINIPORT
, ("Called.\n"));
1067 KeRaiseIrql(DISPATCH_LEVEL
, &OldIrql
);
1069 KeAcquireSpinLockAtDpcLevel(&Adapter
->NdisMiniportBlock
.Lock
);
1070 Adapter
->NdisMiniportBlock
.PendingRequest
= NdisRequest
;
1071 KeReleaseSpinLockFromDpcLevel(&Adapter
->NdisMiniportBlock
.Lock
);
1073 if (!Adapter
->NdisMiniportBlock
.DriverHandle
->MiniportCharacteristics
.CoRequestHandler
)
1075 switch (NdisRequest
->RequestType
)
1077 case NdisRequestQueryInformation
:
1078 Status
= (*Adapter
->NdisMiniportBlock
.DriverHandle
->MiniportCharacteristics
.QueryInformationHandler
)(
1079 Adapter
->NdisMiniportBlock
.MiniportAdapterContext
,
1080 NdisRequest
->DATA
.QUERY_INFORMATION
.Oid
,
1081 NdisRequest
->DATA
.QUERY_INFORMATION
.InformationBuffer
,
1082 NdisRequest
->DATA
.QUERY_INFORMATION
.InformationBufferLength
,
1083 (PULONG
)&NdisRequest
->DATA
.QUERY_INFORMATION
.BytesWritten
,
1084 (PULONG
)&NdisRequest
->DATA
.QUERY_INFORMATION
.BytesNeeded
);
1087 case NdisRequestSetInformation
:
1088 Status
= (*Adapter
->NdisMiniportBlock
.DriverHandle
->MiniportCharacteristics
.SetInformationHandler
)(
1089 Adapter
->NdisMiniportBlock
.MiniportAdapterContext
,
1090 NdisRequest
->DATA
.SET_INFORMATION
.Oid
,
1091 NdisRequest
->DATA
.SET_INFORMATION
.InformationBuffer
,
1092 NdisRequest
->DATA
.SET_INFORMATION
.InformationBufferLength
,
1093 (PULONG
)&NdisRequest
->DATA
.SET_INFORMATION
.BytesRead
,
1094 (PULONG
)&NdisRequest
->DATA
.SET_INFORMATION
.BytesNeeded
);
1098 NDIS_DbgPrint(MIN_TRACE
, ("Bad request type\n"));
1099 Status
= NDIS_STATUS_FAILURE
;
1104 Status
= (*Adapter
->NdisMiniportBlock
.DriverHandle
->MiniportCharacteristics
.CoRequestHandler
)(
1105 Adapter
->NdisMiniportBlock
.MiniportAdapterContext
,
1110 if (Status
!= NDIS_STATUS_PENDING
) {
1111 KeAcquireSpinLockAtDpcLevel(&Adapter
->NdisMiniportBlock
.Lock
);
1112 Adapter
->NdisMiniportBlock
.PendingRequest
= NULL
;
1113 KeReleaseSpinLockFromDpcLevel(&Adapter
->NdisMiniportBlock
.Lock
);
1116 KeLowerIrql(OldIrql
);
1123 #undef NdisMSetInformationComplete
1126 NdisMSetInformationComplete(
1127 IN NDIS_HANDLE MiniportAdapterHandle
,
1128 IN NDIS_STATUS Status
)
1130 PLOGICAL_ADAPTER Adapter
=
1131 (PLOGICAL_ADAPTER
)MiniportAdapterHandle
;
1134 KeRaiseIrql(DISPATCH_LEVEL
, &OldIrql
);
1135 if (Adapter
->NdisMiniportBlock
.SetCompleteHandler
)
1136 (Adapter
->NdisMiniportBlock
.SetCompleteHandler
)(MiniportAdapterHandle
, Status
);
1137 KeLowerIrql(OldIrql
);
1143 #undef NdisMQueryInformationComplete
1146 NdisMQueryInformationComplete(
1147 IN NDIS_HANDLE MiniportAdapterHandle
,
1148 IN NDIS_STATUS Status
)
1150 PLOGICAL_ADAPTER Adapter
=
1151 (PLOGICAL_ADAPTER
)MiniportAdapterHandle
;
1154 KeRaiseIrql(DISPATCH_LEVEL
, &OldIrql
);
1155 if( Adapter
->NdisMiniportBlock
.QueryCompleteHandler
)
1156 (Adapter
->NdisMiniportBlock
.QueryCompleteHandler
)(MiniportAdapterHandle
, Status
);
1157 KeLowerIrql(OldIrql
);
1162 MiniportWorker(IN PDEVICE_OBJECT DeviceObject
, IN PVOID Context
)
1164 PLOGICAL_ADAPTER Adapter
= DeviceObject
->DeviceExtension
;
1165 KIRQL OldIrql
, RaiseOldIrql
;
1166 NDIS_STATUS NdisStatus
;
1167 PVOID WorkItemContext
;
1168 NDIS_WORK_ITEM_TYPE WorkItemType
;
1169 BOOLEAN AddressingReset
;
1171 IoFreeWorkItem((PIO_WORKITEM
)Context
);
1173 KeAcquireSpinLock(&Adapter
->NdisMiniportBlock
.Lock
, &OldIrql
);
1177 (Adapter
, &WorkItemType
, &WorkItemContext
);
1179 KeReleaseSpinLock(&Adapter
->NdisMiniportBlock
.Lock
, OldIrql
);
1181 if (NdisStatus
== NDIS_STATUS_SUCCESS
)
1183 switch (WorkItemType
)
1185 case NdisWorkItemSend
:
1187 * called by ProSend when protocols want to send packets to the miniport
1190 if(Adapter
->NdisMiniportBlock
.DriverHandle
->MiniportCharacteristics
.SendPacketsHandler
)
1192 if(Adapter
->NdisMiniportBlock
.Flags
& NDIS_ATTRIBUTE_DESERIALIZE
)
1194 NDIS_DbgPrint(MAX_TRACE
, ("Calling miniport's SendPackets handler\n"));
1195 (*Adapter
->NdisMiniportBlock
.DriverHandle
->MiniportCharacteristics
.SendPacketsHandler
)(
1196 Adapter
->NdisMiniportBlock
.MiniportAdapterContext
, (PPNDIS_PACKET
)&WorkItemContext
, 1);
1197 NdisStatus
= NDIS_STATUS_PENDING
;
1201 /* SendPackets is called at DISPATCH_LEVEL for all serialized miniports */
1202 KeRaiseIrql(DISPATCH_LEVEL
, &RaiseOldIrql
);
1204 NDIS_DbgPrint(MAX_TRACE
, ("Calling miniport's SendPackets handler\n"));
1205 (*Adapter
->NdisMiniportBlock
.DriverHandle
->MiniportCharacteristics
.SendPacketsHandler
)(
1206 Adapter
->NdisMiniportBlock
.MiniportAdapterContext
, (PPNDIS_PACKET
)&WorkItemContext
, 1);
1208 KeLowerIrql(RaiseOldIrql
);
1210 NdisStatus
= NDIS_GET_PACKET_STATUS((PNDIS_PACKET
)WorkItemContext
);
1211 if( NdisStatus
== NDIS_STATUS_RESOURCES
) {
1212 MiniQueueWorkItem(Adapter
, WorkItemType
, WorkItemContext
, TRUE
);
1219 if(Adapter
->NdisMiniportBlock
.Flags
& NDIS_ATTRIBUTE_DESERIALIZE
)
1221 NDIS_DbgPrint(MAX_TRACE
, ("Calling miniport's Send handler\n"));
1222 NdisStatus
= (*Adapter
->NdisMiniportBlock
.DriverHandle
->MiniportCharacteristics
.SendHandler
)(
1223 Adapter
->NdisMiniportBlock
.MiniportAdapterContext
, (PNDIS_PACKET
)WorkItemContext
,
1224 ((PNDIS_PACKET
)WorkItemContext
)->Private
.Flags
);
1225 NDIS_DbgPrint(MAX_TRACE
, ("back from miniport's send handler\n"));
1229 /* Send is called at DISPATCH_LEVEL for all serialized miniports */
1230 KeRaiseIrql(DISPATCH_LEVEL
, &RaiseOldIrql
);
1231 NDIS_DbgPrint(MAX_TRACE
, ("Calling miniport's Send handler\n"));
1232 NdisStatus
= (*Adapter
->NdisMiniportBlock
.DriverHandle
->MiniportCharacteristics
.SendHandler
)(
1233 Adapter
->NdisMiniportBlock
.MiniportAdapterContext
, (PNDIS_PACKET
)WorkItemContext
,
1234 ((PNDIS_PACKET
)WorkItemContext
)->Private
.Flags
);
1235 NDIS_DbgPrint(MAX_TRACE
, ("back from miniport's send handler\n"));
1236 KeLowerIrql(RaiseOldIrql
);
1237 if( NdisStatus
== NDIS_STATUS_RESOURCES
) {
1238 MiniQueueWorkItem(Adapter
, WorkItemType
, WorkItemContext
, TRUE
);
1244 if( NdisStatus
!= NDIS_STATUS_PENDING
) {
1246 ( Adapter
, (PNDIS_PACKET
)WorkItemContext
, NdisStatus
);
1250 case NdisWorkItemSendLoopback
:
1252 * called by ProSend when protocols want to send loopback packets
1254 /* XXX atm ProIndicatePacket sends a packet up via the loopback adapter only */
1255 NdisStatus
= ProIndicatePacket(Adapter
, (PNDIS_PACKET
)WorkItemContext
);
1257 if( NdisStatus
!= NDIS_STATUS_PENDING
)
1258 MiniSendComplete((NDIS_HANDLE
)Adapter
, (PNDIS_PACKET
)WorkItemContext
, NdisStatus
);
1261 case NdisWorkItemReturnPackets
:
1264 case NdisWorkItemResetRequested
:
1265 NdisMIndicateStatus(Adapter
, NDIS_STATUS_RESET_START
, NULL
, 0);
1266 NdisMIndicateStatusComplete(Adapter
);
1268 KeRaiseIrql(DISPATCH_LEVEL
, &OldIrql
);
1269 NdisStatus
= (*Adapter
->NdisMiniportBlock
.DriverHandle
->MiniportCharacteristics
.ResetHandler
)(
1270 Adapter
->NdisMiniportBlock
.MiniportAdapterContext
,
1273 KeAcquireSpinLockAtDpcLevel(&Adapter
->NdisMiniportBlock
.Lock
);
1274 Adapter
->NdisMiniportBlock
.ResetStatus
= NdisStatus
;
1275 KeReleaseSpinLockFromDpcLevel(&Adapter
->NdisMiniportBlock
.Lock
);
1277 KeLowerIrql(OldIrql
);
1279 if (NdisStatus
!= NDIS_STATUS_PENDING
)
1280 MiniResetComplete(Adapter
, NdisStatus
, AddressingReset
);
1283 case NdisWorkItemResetInProgress
:
1286 case NdisWorkItemMiniportCallback
:
1289 case NdisWorkItemRequest
:
1290 NdisStatus
= MiniDoRequest(Adapter
, (PNDIS_REQUEST
)WorkItemContext
);
1292 if (NdisStatus
== NDIS_STATUS_PENDING
)
1295 switch (((PNDIS_REQUEST
)WorkItemContext
)->RequestType
)
1297 case NdisRequestQueryInformation
:
1298 NdisMQueryInformationComplete((NDIS_HANDLE
)Adapter
, NdisStatus
);
1301 case NdisRequestSetInformation
:
1302 NdisMSetInformationComplete((NDIS_HANDLE
)Adapter
, NdisStatus
);
1306 NDIS_DbgPrint(MIN_TRACE
, ("Unknown NDIS request type.\n"));
1312 NDIS_DbgPrint(MIN_TRACE
, ("Unknown NDIS work item type (%d).\n", WorkItemType
));
1322 IN NDIS_HANDLE MiniportHandle
,
1323 IN NDIS_STATUS GeneralStatus
,
1324 IN PVOID StatusBuffer
,
1325 IN UINT StatusBufferSize
)
1327 PLOGICAL_ADAPTER Adapter
= MiniportHandle
;
1328 PLIST_ENTRY CurrentEntry
;
1329 PADAPTER_BINDING AdapterBinding
;
1332 KeAcquireSpinLock(&Adapter
->NdisMiniportBlock
.Lock
, &OldIrql
);
1334 CurrentEntry
= Adapter
->ProtocolListHead
.Flink
;
1336 while (CurrentEntry
!= &Adapter
->ProtocolListHead
)
1338 AdapterBinding
= CONTAINING_RECORD(CurrentEntry
, ADAPTER_BINDING
, AdapterListEntry
);
1340 (*AdapterBinding
->ProtocolBinding
->Chars
.StatusHandler
)(
1341 AdapterBinding
->NdisOpenBlock
.ProtocolBindingContext
,
1346 CurrentEntry
= CurrentEntry
->Flink
;
1349 KeReleaseSpinLock(&Adapter
->NdisMiniportBlock
.Lock
, OldIrql
);
1355 IN NDIS_HANDLE MiniportAdapterHandle
)
1357 PLOGICAL_ADAPTER Adapter
= MiniportAdapterHandle
;
1358 PLIST_ENTRY CurrentEntry
;
1359 PADAPTER_BINDING AdapterBinding
;
1362 KeAcquireSpinLock(&Adapter
->NdisMiniportBlock
.Lock
, &OldIrql
);
1364 CurrentEntry
= Adapter
->ProtocolListHead
.Flink
;
1366 while (CurrentEntry
!= &Adapter
->ProtocolListHead
)
1368 AdapterBinding
= CONTAINING_RECORD(CurrentEntry
, ADAPTER_BINDING
, AdapterListEntry
);
1370 (*AdapterBinding
->ProtocolBinding
->Chars
.StatusCompleteHandler
)(
1371 AdapterBinding
->NdisOpenBlock
.ProtocolBindingContext
);
1373 CurrentEntry
= CurrentEntry
->Flink
;
1376 KeReleaseSpinLock(&Adapter
->NdisMiniportBlock
.Lock
, OldIrql
);
1385 IN NDIS_HANDLE LogHandle
)
1387 PNDIS_LOG Log
= (PNDIS_LOG
)LogHandle
;
1388 PNDIS_MINIPORT_BLOCK Miniport
= Log
->Miniport
;
1391 NDIS_DbgPrint(MAX_TRACE
, ("called: LogHandle 0x%x\n", LogHandle
));
1393 KeAcquireSpinLock(&(Miniport
)->Lock
, &OldIrql
);
1394 Miniport
->Log
= NULL
;
1395 KeReleaseSpinLock(&(Miniport
)->Lock
, OldIrql
);
1406 IN NDIS_HANDLE MiniportAdapterHandle
,
1408 OUT PNDIS_HANDLE LogHandle
)
1410 PLOGICAL_ADAPTER Adapter
= MiniportAdapterHandle
;
1414 NDIS_DbgPrint(MAX_TRACE
, ("called: MiniportAdapterHandle 0x%x, Size %ld\n", MiniportAdapterHandle
, Size
));
1416 KeAcquireSpinLock(&Adapter
->NdisMiniportBlock
.Lock
, &OldIrql
);
1418 if (Adapter
->NdisMiniportBlock
.Log
)
1421 return NDIS_STATUS_FAILURE
;
1424 Log
= ExAllocatePool(NonPagedPool
, Size
+ sizeof(NDIS_LOG
));
1428 return NDIS_STATUS_RESOURCES
;
1431 Adapter
->NdisMiniportBlock
.Log
= Log
;
1433 KeInitializeSpinLock(&Log
->LogLock
);
1435 Log
->Miniport
= &Adapter
->NdisMiniportBlock
;
1436 Log
->TotalSize
= Size
;
1437 Log
->CurrentSize
= 0;
1444 KeReleaseSpinLock(&Adapter
->NdisMiniportBlock
.Lock
, OldIrql
);
1446 return NDIS_STATUS_SUCCESS
;
1454 NdisMDeregisterAdapterShutdownHandler(
1455 IN NDIS_HANDLE MiniportHandle
)
1457 * FUNCTION: de-registers a shutdown handler
1458 * ARGUMENTS: MiniportHandle: Handle passed into MiniportInitialize
1461 PLOGICAL_ADAPTER Adapter
= (PLOGICAL_ADAPTER
)MiniportHandle
;
1463 NDIS_DbgPrint(DEBUG_MINIPORT
, ("Called.\n"));
1465 if(Adapter
->BugcheckContext
->ShutdownHandler
) {
1466 KeDeregisterBugCheckCallback(Adapter
->BugcheckContext
->CallbackRecord
);
1467 IoUnregisterShutdownNotification(Adapter
->NdisMiniportBlock
.DeviceObject
);
1477 IN NDIS_HANDLE LogHandle
)
1479 PNDIS_LOG Log
= (PNDIS_LOG
) LogHandle
;
1482 NDIS_DbgPrint(MAX_TRACE
, ("called: LogHandle 0x%x\n", LogHandle
));
1485 KeAcquireSpinLock(&Log
->LogLock
, &OldIrql
);
1487 /* Set buffers size */
1488 Log
->CurrentSize
= 0;
1493 KeReleaseSpinLock(&Log
->LogLock
, OldIrql
);
1499 #undef NdisMIndicateStatus
1502 NdisMIndicateStatus(
1503 IN NDIS_HANDLE MiniportAdapterHandle
,
1504 IN NDIS_STATUS GeneralStatus
,
1505 IN PVOID StatusBuffer
,
1506 IN UINT StatusBufferSize
)
1508 MiniStatus(MiniportAdapterHandle
, GeneralStatus
, StatusBuffer
, StatusBufferSize
);
1514 #undef NdisMIndicateStatusComplete
1517 NdisMIndicateStatusComplete(
1518 IN NDIS_HANDLE MiniportAdapterHandle
)
1520 MiniStatusComplete(MiniportAdapterHandle
);
1528 NdisInitializeWrapper(
1529 OUT PNDIS_HANDLE NdisWrapperHandle
,
1530 IN PVOID SystemSpecific1
,
1531 IN PVOID SystemSpecific2
,
1532 IN PVOID SystemSpecific3
)
1534 * FUNCTION: Notifies the NDIS library that a new miniport is initializing
1536 * NdisWrapperHandle = Address of buffer to place NDIS wrapper handle
1537 * SystemSpecific1 = Pointer to the driver's driver object
1538 * SystemSpecific2 = Pointer to the driver's registry path
1539 * SystemSpecific3 = Always NULL
1541 * - SystemSpecific2 goes invalid so we copy it
1544 PNDIS_M_DRIVER_BLOCK Miniport
;
1545 PUNICODE_STRING RegistryPath
;
1546 WCHAR
*RegistryBuffer
;
1548 NDIS_DbgPrint(MAX_TRACE
, ("Called.\n"));
1550 ASSERT(NdisWrapperHandle
);
1552 *NdisWrapperHandle
= NULL
;
1554 #if BREAK_ON_MINIPORT_INIT
1558 Miniport
= ExAllocatePool(NonPagedPool
, sizeof(NDIS_M_DRIVER_BLOCK
));
1562 NDIS_DbgPrint(MIN_TRACE
, ("Insufficient resources.\n"));
1566 RtlZeroMemory(Miniport
, sizeof(NDIS_M_DRIVER_BLOCK
));
1568 KeInitializeSpinLock(&Miniport
->Lock
);
1570 Miniport
->DriverObject
= (PDRIVER_OBJECT
)SystemSpecific1
;
1572 /* set the miniport's driver registry path */
1573 RegistryPath
= ExAllocatePool(PagedPool
, sizeof(UNICODE_STRING
));
1576 ExFreePool(Miniport
);
1577 NDIS_DbgPrint(MIN_TRACE
, ("Insufficient resources.\n"));
1581 RegistryPath
->Length
= ((PUNICODE_STRING
)SystemSpecific2
)->Length
;
1582 RegistryPath
->MaximumLength
= RegistryPath
->Length
+ sizeof(WCHAR
); /* room for 0-term */
1584 RegistryBuffer
= ExAllocatePool(PagedPool
, RegistryPath
->MaximumLength
);
1587 NDIS_DbgPrint(MIN_TRACE
, ("Insufficient resources.\n"));
1588 ExFreePool(Miniport
);
1589 ExFreePool(RegistryPath
);
1593 RtlCopyMemory(RegistryBuffer
, ((PUNICODE_STRING
)SystemSpecific2
)->Buffer
, RegistryPath
->Length
);
1594 RegistryBuffer
[RegistryPath
->Length
/sizeof(WCHAR
)] = 0;
1596 RegistryPath
->Buffer
= RegistryBuffer
;
1597 Miniport
->RegistryPath
= RegistryPath
;
1599 InitializeListHead(&Miniport
->DeviceList
);
1601 /* Put miniport in global miniport list */
1602 ExInterlockedInsertTailList(&MiniportListHead
, &Miniport
->ListEntry
, &MiniportListLock
);
1604 *NdisWrapperHandle
= Miniport
;
1607 VOID NTAPI
NdisIBugcheckCallback(
1611 * FUNCTION: Internal callback for handling bugchecks - calls adapter's shutdown handler
1613 * Buffer: Pointer to a bugcheck callback context
1617 PMINIPORT_BUGCHECK_CONTEXT Context
= (PMINIPORT_BUGCHECK_CONTEXT
)Buffer
;
1618 ADAPTER_SHUTDOWN_HANDLER sh
= (ADAPTER_SHUTDOWN_HANDLER
)Context
->ShutdownHandler
;
1620 NDIS_DbgPrint(DEBUG_MINIPORT
, ("Called.\n"));
1623 sh(Context
->DriverContext
);
1631 NdisMRegisterAdapterShutdownHandler(
1632 IN NDIS_HANDLE MiniportHandle
,
1633 IN PVOID ShutdownContext
,
1634 IN ADAPTER_SHUTDOWN_HANDLER ShutdownHandler
)
1636 * FUNCTION: Register a shutdown handler for an adapter
1638 * MiniportHandle: Handle originally passed into MiniportInitialize
1639 * ShutdownContext: Pre-initialized bugcheck context
1640 * ShutdownHandler: Function to call to handle the bugcheck
1642 * - I'm not sure about ShutdownContext
1645 PLOGICAL_ADAPTER Adapter
= (PLOGICAL_ADAPTER
)MiniportHandle
;
1646 PMINIPORT_BUGCHECK_CONTEXT BugcheckContext
;
1648 NDIS_DbgPrint(DEBUG_MINIPORT
, ("Called.\n"));
1650 BugcheckContext
= ExAllocatePool(NonPagedPool
, sizeof(MINIPORT_BUGCHECK_CONTEXT
));
1651 if(!BugcheckContext
)
1653 NDIS_DbgPrint(MIN_TRACE
, ("Insufficient resources.\n"));
1657 BugcheckContext
->ShutdownHandler
= ShutdownHandler
;
1658 BugcheckContext
->DriverContext
= ShutdownContext
;
1660 BugcheckContext
->CallbackRecord
= ExAllocatePool(NonPagedPool
, sizeof(KBUGCHECK_CALLBACK_RECORD
));
1661 if (!BugcheckContext
->CallbackRecord
) {
1662 ExFreePool(BugcheckContext
);
1666 Adapter
->BugcheckContext
= BugcheckContext
;
1668 KeInitializeCallbackRecord(BugcheckContext
->CallbackRecord
);
1670 KeRegisterBugCheckCallback(BugcheckContext
->CallbackRecord
, NdisIBugcheckCallback
,
1671 BugcheckContext
, sizeof(*BugcheckContext
), (PUCHAR
)"Ndis Miniport");
1673 IoRegisterShutdownNotification(Adapter
->NdisMiniportBlock
.DeviceObject
);
1678 PLOGICAL_ADAPTER Adapter
,
1679 NDIS_OID AddressOID
)
1681 * FUNCTION: Queries miniport for information
1683 * Adapter = Pointer to logical adapter
1684 * AddressOID = OID to use to query for current address
1686 * Status of operation
1690 NDIS_STATUS NdisStatus
;
1692 NDIS_DbgPrint(MAX_TRACE
, ("Called.\n"));
1694 /* Get MAC options for adapter */
1695 NdisStatus
= MiniQueryInformation(Adapter
, OID_GEN_MAC_OPTIONS
, sizeof(UINT
),
1696 &Adapter
->NdisMiniportBlock
.MacOptions
,
1699 if (NdisStatus
!= NDIS_STATUS_SUCCESS
)
1701 NDIS_DbgPrint(MIN_TRACE
, ("OID_GEN_MAC_OPTIONS failed. NdisStatus (0x%X).\n", NdisStatus
));
1705 NDIS_DbgPrint(DEBUG_MINIPORT
, ("MacOptions (0x%X).\n", Adapter
->NdisMiniportBlock
.MacOptions
));
1707 /* Get current hardware address of adapter */
1708 NdisStatus
= MiniQueryInformation(Adapter
, AddressOID
, Adapter
->AddressLength
,
1709 &Adapter
->Address
, &BytesWritten
);
1711 if (NdisStatus
!= NDIS_STATUS_SUCCESS
)
1713 NDIS_DbgPrint(MIN_TRACE
, ("Address OID (0x%X) failed. NdisStatus (0x%X).\n", AddressOID
, NdisStatus
));
1721 PUCHAR A
= (PUCHAR
)&Adapter
->Address
.Type
.Medium802_3
;
1723 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]));
1727 /* Get maximum lookahead buffer size of adapter */
1728 NdisStatus
= MiniQueryInformation(Adapter
, OID_GEN_MAXIMUM_LOOKAHEAD
, sizeof(ULONG
),
1729 &Adapter
->NdisMiniportBlock
.MaximumLookahead
, &BytesWritten
);
1731 if (NdisStatus
!= NDIS_STATUS_SUCCESS
)
1733 NDIS_DbgPrint(MIN_TRACE
, ("OID_GEN_MAXIMUM_LOOKAHEAD failed. NdisStatus (0x%X).\n", NdisStatus
));
1737 NDIS_DbgPrint(DEBUG_MINIPORT
, ("MaxLookaheadLength (0x%X).\n", Adapter
->NdisMiniportBlock
.MaximumLookahead
));
1739 /* Get current lookahead buffer size of adapter */
1740 NdisStatus
= MiniQueryInformation(Adapter
, OID_GEN_CURRENT_LOOKAHEAD
, sizeof(ULONG
),
1741 &Adapter
->NdisMiniportBlock
.CurrentLookahead
, &BytesWritten
);
1743 if (NdisStatus
!= NDIS_STATUS_SUCCESS
)
1745 NDIS_DbgPrint(MIN_TRACE
, ("OID_GEN_CURRENT_LOOKAHEAD failed. NdisStatus (0x%X).\n", NdisStatus
));
1749 NdisStatus
= MiniQueryInformation(Adapter
, OID_GEN_MAXIMUM_SEND_PACKETS
, sizeof(ULONG
),
1750 &Adapter
->NdisMiniportBlock
.MaxSendPackets
, &BytesWritten
);
1752 if (NdisStatus
!= NDIS_STATUS_SUCCESS
)
1754 NDIS_DbgPrint(MIN_TRACE
, ("OID_GEN_MAXIMUM_SEND_PACKETS failed. NdisStatus (0x%X).\n", NdisStatus
));
1756 /* Set it to 1 if it fails because some drivers don't support this (?)*/
1757 Adapter
->NdisMiniportBlock
.MaxSendPackets
= 1;
1760 NDIS_DbgPrint(DEBUG_MINIPORT
, ("CurLookaheadLength (0x%X).\n", Adapter
->NdisMiniportBlock
.CurrentLookahead
));
1762 return STATUS_SUCCESS
;
1767 NdisIForwardIrpAndWaitCompletionRoutine(
1772 PKEVENT Event
= Context
;
1774 if (Irp
->PendingReturned
)
1775 KeSetEvent(Event
, IO_NO_INCREMENT
, FALSE
);
1777 return STATUS_MORE_PROCESSING_REQUIRED
;
1782 NdisIForwardIrpAndWait(PLOGICAL_ADAPTER Adapter
, PIRP Irp
)
1787 KeInitializeEvent(&Event
, NotificationEvent
, FALSE
);
1788 IoCopyCurrentIrpStackLocationToNext(Irp
);
1789 IoSetCompletionRoutine(Irp
, NdisIForwardIrpAndWaitCompletionRoutine
, &Event
,
1791 Status
= IoCallDriver(Adapter
->NdisMiniportBlock
.NextDeviceObject
, Irp
);
1792 if (Status
== STATUS_PENDING
)
1794 KeWaitForSingleObject(&Event
, Executive
, KernelMode
, FALSE
, NULL
);
1795 Status
= Irp
->IoStatus
.Status
;
1803 IN PDEVICE_OBJECT DeviceObject
,
1806 Irp
->IoStatus
.Status
= STATUS_SUCCESS
;
1807 Irp
->IoStatus
.Information
= 0;
1809 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
1811 return STATUS_SUCCESS
;
1816 NdisIPnPStartDevice(
1817 IN PDEVICE_OBJECT DeviceObject
,
1820 * FUNCTION: Handle the PnP start device event
1822 * DeviceObejct = Functional Device Object
1823 * Irp = IRP_MN_START_DEVICE I/O request packet
1825 * Status of operation
1828 PIO_STACK_LOCATION Stack
= IoGetCurrentIrpStackLocation(Irp
);
1829 PLOGICAL_ADAPTER Adapter
= (PLOGICAL_ADAPTER
)DeviceObject
->DeviceExtension
;
1830 NDIS_WRAPPER_CONTEXT WrapperContext
;
1831 NDIS_STATUS NdisStatus
;
1832 NDIS_STATUS OpenErrorStatus
;
1834 UINT SelectedMediumIndex
= 0;
1835 NDIS_OID AddressOID
;
1836 BOOLEAN Success
= FALSE
;
1837 ULONG ResourceCount
;
1838 ULONG ResourceListSize
;
1839 UNICODE_STRING ParamName
;
1840 PNDIS_CONFIGURATION_PARAMETER ConfigParam
;
1841 NDIS_HANDLE ConfigHandle
;
1843 LARGE_INTEGER Timeout
;
1844 UINT MaxMulticastAddresses
;
1846 PLIST_ENTRY CurrentEntry
;
1847 PPROTOCOL_BINDING ProtocolBinding
;
1850 * Prepare wrapper context used by HW and configuration routines.
1853 NDIS_DbgPrint(DEBUG_MINIPORT
, ("Start Device %wZ\n", &Adapter
->NdisMiniportBlock
.MiniportName
));
1855 NDIS_DbgPrint(MAX_TRACE
, ("Inserting adapter 0x%x into adapter list\n", Adapter
));
1857 /* Put adapter in global adapter list */
1858 ExInterlockedInsertTailList(&AdapterListHead
, &Adapter
->ListEntry
, &AdapterListLock
);
1860 Status
= IoOpenDeviceRegistryKey(
1861 Adapter
->NdisMiniportBlock
.PhysicalDeviceObject
, PLUGPLAY_REGKEY_DRIVER
,
1862 KEY_ALL_ACCESS
, &WrapperContext
.RegistryHandle
);
1863 if (!NT_SUCCESS(Status
))
1865 NDIS_DbgPrint(MIN_TRACE
,("failed to open adapter-specific reg key\n"));
1866 ExInterlockedRemoveEntryList( &Adapter
->ListEntry
, &AdapterListLock
);
1870 NDIS_DbgPrint(MAX_TRACE
, ("opened device reg key\n"));
1872 WrapperContext
.DeviceObject
= Adapter
->NdisMiniportBlock
.DeviceObject
;
1875 * Store the adapter resources used by HW routines such as
1876 * NdisMQueryAdapterResources.
1879 if (Stack
->Parameters
.StartDevice
.AllocatedResources
!= NULL
)
1881 ResourceCount
= Stack
->Parameters
.StartDevice
.AllocatedResources
->List
[0].
1882 PartialResourceList
.Count
;
1884 FIELD_OFFSET(CM_RESOURCE_LIST
, List
[0].PartialResourceList
.
1885 PartialDescriptors
[ResourceCount
]);
1887 Adapter
->NdisMiniportBlock
.AllocatedResources
=
1888 ExAllocatePool(PagedPool
, ResourceListSize
);
1889 if (Adapter
->NdisMiniportBlock
.AllocatedResources
== NULL
)
1891 NDIS_DbgPrint(MIN_TRACE
, ("Insufficient resources\n"));
1892 ExInterlockedRemoveEntryList( &Adapter
->ListEntry
, &AdapterListLock
);
1893 return STATUS_INSUFFICIENT_RESOURCES
;
1896 Adapter
->NdisMiniportBlock
.Resources
=
1897 ExAllocatePool(PagedPool
, ResourceListSize
);
1898 if (!Adapter
->NdisMiniportBlock
.Resources
)
1900 NDIS_DbgPrint(MIN_TRACE
, ("Insufficient resources\n"));
1901 ExFreePool(Adapter
->NdisMiniportBlock
.AllocatedResources
);
1902 ExInterlockedRemoveEntryList(&Adapter
->ListEntry
, &AdapterListLock
);
1903 return STATUS_INSUFFICIENT_RESOURCES
;
1906 RtlCopyMemory(Adapter
->NdisMiniportBlock
.Resources
,
1907 Stack
->Parameters
.StartDevice
.AllocatedResources
,
1910 RtlCopyMemory(Adapter
->NdisMiniportBlock
.AllocatedResources
,
1911 Stack
->Parameters
.StartDevice
.AllocatedResources
,
1915 if (Stack
->Parameters
.StartDevice
.AllocatedResourcesTranslated
!= NULL
)
1917 ResourceCount
= Stack
->Parameters
.StartDevice
.AllocatedResourcesTranslated
->List
[0].
1918 PartialResourceList
.Count
;
1920 FIELD_OFFSET(CM_RESOURCE_LIST
, List
[0].PartialResourceList
.
1921 PartialDescriptors
[ResourceCount
]);
1923 Adapter
->NdisMiniportBlock
.AllocatedResourcesTranslated
=
1924 ExAllocatePool(PagedPool
, ResourceListSize
);
1925 if (Adapter
->NdisMiniportBlock
.AllocatedResourcesTranslated
== NULL
)
1927 NDIS_DbgPrint(MIN_TRACE
, ("Insufficient resources\n"));
1928 ExInterlockedRemoveEntryList( &Adapter
->ListEntry
, &AdapterListLock
);
1929 return STATUS_INSUFFICIENT_RESOURCES
;
1932 RtlCopyMemory(Adapter
->NdisMiniportBlock
.AllocatedResourcesTranslated
,
1933 Stack
->Parameters
.StartDevice
.AllocatedResourcesTranslated
,
1938 * Store the Bus Type, Bus Number and Slot information. It's used by
1939 * the hardware routines then.
1942 NdisOpenConfiguration(&NdisStatus
, &ConfigHandle
, (NDIS_HANDLE
)&WrapperContext
);
1943 if (NdisStatus
!= NDIS_STATUS_SUCCESS
)
1945 NDIS_DbgPrint(MIN_TRACE
, ("Failed to open configuration key\n"));
1946 ExInterlockedRemoveEntryList( &Adapter
->ListEntry
, &AdapterListLock
);
1950 Size
= sizeof(ULONG
);
1951 Status
= IoGetDeviceProperty(Adapter
->NdisMiniportBlock
.PhysicalDeviceObject
,
1952 DevicePropertyLegacyBusType
, Size
,
1953 &Adapter
->NdisMiniportBlock
.BusType
, &Size
);
1954 if (!NT_SUCCESS(Status
) || (INTERFACE_TYPE
)Adapter
->NdisMiniportBlock
.BusType
== InterfaceTypeUndefined
)
1956 NdisInitUnicodeString(&ParamName
, L
"BusType");
1957 NdisReadConfiguration(&NdisStatus
, &ConfigParam
, ConfigHandle
,
1958 &ParamName
, NdisParameterInteger
);
1959 if (NdisStatus
== NDIS_STATUS_SUCCESS
)
1960 Adapter
->NdisMiniportBlock
.BusType
= ConfigParam
->ParameterData
.IntegerData
;
1962 Adapter
->NdisMiniportBlock
.BusType
= Isa
;
1965 Status
= IoGetDeviceProperty(Adapter
->NdisMiniportBlock
.PhysicalDeviceObject
,
1966 DevicePropertyBusNumber
, Size
,
1967 &Adapter
->NdisMiniportBlock
.BusNumber
, &Size
);
1968 if (!NT_SUCCESS(Status
) || Adapter
->NdisMiniportBlock
.BusNumber
== 0xFFFFFFF0)
1970 NdisInitUnicodeString(&ParamName
, L
"BusNumber");
1971 NdisReadConfiguration(&NdisStatus
, &ConfigParam
, ConfigHandle
,
1972 &ParamName
, NdisParameterInteger
);
1973 if (NdisStatus
== NDIS_STATUS_SUCCESS
)
1974 Adapter
->NdisMiniportBlock
.BusNumber
= ConfigParam
->ParameterData
.IntegerData
;
1976 Adapter
->NdisMiniportBlock
.BusNumber
= 0;
1978 WrapperContext
.BusNumber
= Adapter
->NdisMiniportBlock
.BusNumber
;
1980 Status
= IoGetDeviceProperty(Adapter
->NdisMiniportBlock
.PhysicalDeviceObject
,
1981 DevicePropertyAddress
, Size
,
1982 &Adapter
->NdisMiniportBlock
.SlotNumber
, &Size
);
1983 if (!NT_SUCCESS(Status
) || Adapter
->NdisMiniportBlock
.SlotNumber
== (NDIS_INTERFACE_TYPE
)-1)
1985 NdisInitUnicodeString(&ParamName
, L
"SlotNumber");
1986 NdisReadConfiguration(&NdisStatus
, &ConfigParam
, ConfigHandle
,
1987 &ParamName
, NdisParameterInteger
);
1988 if (NdisStatus
== NDIS_STATUS_SUCCESS
)
1989 Adapter
->NdisMiniportBlock
.SlotNumber
= ConfigParam
->ParameterData
.IntegerData
;
1991 Adapter
->NdisMiniportBlock
.SlotNumber
= 0;
1995 /* Convert slotnumber to PCI_SLOT_NUMBER */
1996 ULONG PciSlotNumber
= Adapter
->NdisMiniportBlock
.SlotNumber
;
1997 PCI_SLOT_NUMBER SlotNumber
;
1999 SlotNumber
.u
.AsULONG
= 0;
2000 SlotNumber
.u
.bits
.DeviceNumber
= (PciSlotNumber
>> 16) & 0xFFFF;
2001 SlotNumber
.u
.bits
.FunctionNumber
= PciSlotNumber
& 0xFFFF;
2003 Adapter
->NdisMiniportBlock
.SlotNumber
= SlotNumber
.u
.AsULONG
;
2005 WrapperContext
.SlotNumber
= Adapter
->NdisMiniportBlock
.SlotNumber
;
2007 NdisCloseConfiguration(ConfigHandle
);
2009 /* Set handlers (some NDIS macros require these) */
2010 Adapter
->NdisMiniportBlock
.EthRxCompleteHandler
= EthFilterDprIndicateReceiveComplete
;
2011 Adapter
->NdisMiniportBlock
.EthRxIndicateHandler
= EthFilterDprIndicateReceive
;
2012 Adapter
->NdisMiniportBlock
.SendCompleteHandler
= MiniSendComplete
;
2013 Adapter
->NdisMiniportBlock
.SendResourcesHandler
= MiniSendResourcesAvailable
;
2014 Adapter
->NdisMiniportBlock
.ResetCompleteHandler
= MiniResetComplete
;
2015 Adapter
->NdisMiniportBlock
.TDCompleteHandler
= MiniTransferDataComplete
;
2016 Adapter
->NdisMiniportBlock
.PacketIndicateHandler
= MiniIndicateReceivePacket
;
2017 Adapter
->NdisMiniportBlock
.StatusHandler
= MiniStatus
;
2018 Adapter
->NdisMiniportBlock
.StatusCompleteHandler
= MiniStatusComplete
;
2019 Adapter
->NdisMiniportBlock
.SendPacketsHandler
= ProSendPackets
;
2020 Adapter
->NdisMiniportBlock
.QueryCompleteHandler
= MiniRequestComplete
;
2021 Adapter
->NdisMiniportBlock
.SetCompleteHandler
= MiniRequestComplete
;
2024 * Call MiniportInitialize.
2027 NDIS_DbgPrint(MID_TRACE
, ("calling MiniportInitialize\n"));
2028 NdisStatus
= (*Adapter
->NdisMiniportBlock
.DriverHandle
->MiniportCharacteristics
.InitializeHandler
)(
2029 &OpenErrorStatus
, &SelectedMediumIndex
, &MediaArray
[0],
2030 MEDIA_ARRAY_SIZE
, Adapter
, (NDIS_HANDLE
)&WrapperContext
);
2032 ZwClose(WrapperContext
.RegistryHandle
);
2034 if (NdisStatus
!= NDIS_STATUS_SUCCESS
)
2036 NDIS_DbgPrint(MIN_TRACE
, ("MiniportInitialize() failed for an adapter.\n"));
2037 ExInterlockedRemoveEntryList( &Adapter
->ListEntry
, &AdapterListLock
);
2038 if (Adapter
->NdisMiniportBlock
.Interrupt
)
2040 KeBugCheckEx(BUGCODE_ID_DRIVER
,
2042 (ULONG_PTR
)Adapter
->NdisMiniportBlock
.Interrupt
,
2043 (ULONG_PTR
)Adapter
->NdisMiniportBlock
.TimerQueue
,
2046 if (Adapter
->NdisMiniportBlock
.TimerQueue
)
2048 KeBugCheckEx(BUGCODE_ID_DRIVER
,
2050 (ULONG_PTR
)Adapter
->NdisMiniportBlock
.Interrupt
,
2051 (ULONG_PTR
)Adapter
->NdisMiniportBlock
.TimerQueue
,
2057 if (SelectedMediumIndex
>= MEDIA_ARRAY_SIZE
)
2059 NDIS_DbgPrint(MIN_TRACE
, ("MiniportInitialize() selected a bad index\n"));
2060 ExInterlockedRemoveEntryList( &Adapter
->ListEntry
, &AdapterListLock
);
2061 return NDIS_STATUS_UNSUPPORTED_MEDIA
;
2064 Adapter
->NdisMiniportBlock
.MediaType
= MediaArray
[SelectedMediumIndex
];
2066 switch (Adapter
->NdisMiniportBlock
.MediaType
)
2068 case NdisMedium802_3
:
2069 Adapter
->MediumHeaderSize
= 14; /* XXX figure out what to do about LLC */
2070 AddressOID
= OID_802_3_CURRENT_ADDRESS
;
2071 Adapter
->AddressLength
= ETH_LENGTH_OF_ADDRESS
;
2072 NdisStatus
= DoQueries(Adapter
, AddressOID
);
2073 if (NdisStatus
== NDIS_STATUS_SUCCESS
)
2075 NdisStatus
= MiniQueryInformation(Adapter
, OID_802_3_MAXIMUM_LIST_SIZE
, sizeof(UINT
),
2076 &MaxMulticastAddresses
, &BytesWritten
);
2078 if (NdisStatus
!= NDIS_STATUS_SUCCESS
)
2080 ExInterlockedRemoveEntryList( &Adapter
->ListEntry
, &AdapterListLock
);
2081 NDIS_DbgPrint(MIN_TRACE
, ("MiniQueryInformation failed (%x)\n", NdisStatus
));
2085 Success
= EthCreateFilter(MaxMulticastAddresses
,
2086 Adapter
->Address
.Type
.Medium802_3
,
2087 &Adapter
->NdisMiniportBlock
.EthDB
);
2089 ((PETHI_FILTER
)Adapter
->NdisMiniportBlock
.EthDB
)->Miniport
= (PNDIS_MINIPORT_BLOCK
)Adapter
;
2091 NdisStatus
= NDIS_STATUS_RESOURCES
;
2096 /* FIXME: Support other types of media */
2097 NDIS_DbgPrint(MIN_TRACE
, ("error: unsupported media\n"));
2099 ExInterlockedRemoveEntryList( &Adapter
->ListEntry
, &AdapterListLock
);
2100 return STATUS_UNSUCCESSFUL
;
2103 if (NdisStatus
!= NDIS_STATUS_SUCCESS
)
2105 NDIS_DbgPrint(MIN_TRACE
, ("couldn't create filter (%x)\n", NdisStatus
));
2109 /* Check for a hang every two seconds if it wasn't set in MiniportInitialize */
2110 if (Adapter
->NdisMiniportBlock
.CheckForHangSeconds
== 0)
2111 Adapter
->NdisMiniportBlock
.CheckForHangSeconds
= 2;
2113 Adapter
->NdisMiniportBlock
.OldPnPDeviceState
= Adapter
->NdisMiniportBlock
.PnPDeviceState
;
2114 Adapter
->NdisMiniportBlock
.PnPDeviceState
= NdisPnPDeviceStarted
;
2116 IoSetDeviceInterfaceState(&Adapter
->NdisMiniportBlock
.SymbolicLinkName
, TRUE
);
2118 Timeout
.QuadPart
= Int32x32To64(Adapter
->NdisMiniportBlock
.CheckForHangSeconds
, -1000000);
2119 KeSetTimerEx(&Adapter
->NdisMiniportBlock
.WakeUpDpcTimer
.Timer
, Timeout
,
2120 Adapter
->NdisMiniportBlock
.CheckForHangSeconds
* 1000,
2121 &Adapter
->NdisMiniportBlock
.WakeUpDpcTimer
.Dpc
);
2123 /* Put adapter in adapter list for this miniport */
2124 ExInterlockedInsertTailList(&Adapter
->NdisMiniportBlock
.DriverHandle
->DeviceList
, &Adapter
->MiniportListEntry
, &Adapter
->NdisMiniportBlock
.DriverHandle
->Lock
);
2126 /* Refresh bindings for all protocols */
2127 CurrentEntry
= ProtocolListHead
.Flink
;
2128 while (CurrentEntry
!= &ProtocolListHead
)
2130 ProtocolBinding
= CONTAINING_RECORD(CurrentEntry
, PROTOCOL_BINDING
, ListEntry
);
2132 ndisBindMiniportsToProtocol(&NdisStatus
, ProtocolBinding
);
2134 CurrentEntry
= CurrentEntry
->Flink
;
2137 return STATUS_SUCCESS
;
2143 IN PDEVICE_OBJECT DeviceObject
,
2146 * FUNCTION: Handle the PnP stop device event
2148 * DeviceObejct = Functional Device Object
2149 * Irp = IRP_MN_STOP_DEVICE I/O request packet
2151 * Status of operation
2154 PLOGICAL_ADAPTER Adapter
= (PLOGICAL_ADAPTER
)DeviceObject
->DeviceExtension
;
2156 /* Remove adapter from adapter list for this miniport */
2157 ExInterlockedRemoveEntryList(&Adapter
->MiniportListEntry
, &Adapter
->NdisMiniportBlock
.DriverHandle
->Lock
);
2159 /* Remove adapter from global adapter list */
2160 ExInterlockedRemoveEntryList(&Adapter
->ListEntry
, &AdapterListLock
);
2162 KeCancelTimer(&Adapter
->NdisMiniportBlock
.WakeUpDpcTimer
.Timer
);
2164 /* Set this here so MiniportISR will be forced to run for interrupts generated in MiniportHalt */
2165 Adapter
->NdisMiniportBlock
.OldPnPDeviceState
= Adapter
->NdisMiniportBlock
.PnPDeviceState
;
2166 Adapter
->NdisMiniportBlock
.PnPDeviceState
= NdisPnPDeviceStopped
;
2168 (*Adapter
->NdisMiniportBlock
.DriverHandle
->MiniportCharacteristics
.HaltHandler
)(Adapter
);
2170 IoSetDeviceInterfaceState(&Adapter
->NdisMiniportBlock
.SymbolicLinkName
, FALSE
);
2172 if (Adapter
->NdisMiniportBlock
.AllocatedResources
)
2174 ExFreePool(Adapter
->NdisMiniportBlock
.AllocatedResources
);
2175 Adapter
->NdisMiniportBlock
.AllocatedResources
= NULL
;
2177 if (Adapter
->NdisMiniportBlock
.AllocatedResourcesTranslated
)
2179 ExFreePool(Adapter
->NdisMiniportBlock
.AllocatedResourcesTranslated
);
2180 Adapter
->NdisMiniportBlock
.AllocatedResourcesTranslated
= NULL
;
2183 if (Adapter
->NdisMiniportBlock
.Resources
)
2185 ExFreePool(Adapter
->NdisMiniportBlock
.Resources
);
2186 Adapter
->NdisMiniportBlock
.Resources
= NULL
;
2189 if (Adapter
->NdisMiniportBlock
.EthDB
)
2191 EthDeleteFilter(Adapter
->NdisMiniportBlock
.EthDB
);
2192 Adapter
->NdisMiniportBlock
.EthDB
= NULL
;
2195 return STATUS_SUCCESS
;
2201 IN PDEVICE_OBJECT DeviceObject
,
2204 PLOGICAL_ADAPTER Adapter
= DeviceObject
->DeviceExtension
;
2205 PMINIPORT_BUGCHECK_CONTEXT Context
= Adapter
->BugcheckContext
;
2206 ADAPTER_SHUTDOWN_HANDLER ShutdownHandler
= Context
->ShutdownHandler
;
2208 ASSERT(ShutdownHandler
);
2210 ShutdownHandler(Context
->DriverContext
);
2212 Irp
->IoStatus
.Status
= STATUS_SUCCESS
;
2213 Irp
->IoStatus
.Information
= 0;
2215 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
2217 return STATUS_SUCCESS
;
2222 NdisIDeviceIoControl(
2223 IN PDEVICE_OBJECT DeviceObject
,
2226 PLOGICAL_ADAPTER Adapter
= (PLOGICAL_ADAPTER
)DeviceObject
->DeviceExtension
;
2227 PIO_STACK_LOCATION Stack
= IoGetCurrentIrpStackLocation(Irp
);
2228 NDIS_STATUS Status
= STATUS_NOT_SUPPORTED
;
2231 Irp
->IoStatus
.Information
= 0;
2235 switch (Stack
->Parameters
.DeviceIoControl
.IoControlCode
)
2237 case IOCTL_NDIS_QUERY_GLOBAL_STATS
:
2238 Status
= MiniQueryInformation(Adapter
,
2239 *(PNDIS_OID
)Irp
->AssociatedIrp
.SystemBuffer
,
2240 Stack
->Parameters
.DeviceIoControl
.OutputBufferLength
,
2241 MmGetSystemAddressForMdl(Irp
->MdlAddress
),
2243 Irp
->IoStatus
.Information
= Written
;
2251 if (Status
!= NDIS_STATUS_PENDING
)
2253 Irp
->IoStatus
.Status
= Status
;
2254 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
2257 IoMarkIrpPending(Irp
);
2265 IN PDEVICE_OBJECT DeviceObject
,
2268 PIO_STACK_LOCATION Stack
= IoGetCurrentIrpStackLocation(Irp
);
2269 PLOGICAL_ADAPTER Adapter
= (PLOGICAL_ADAPTER
)DeviceObject
->DeviceExtension
;
2272 switch (Stack
->MinorFunction
)
2274 case IRP_MN_START_DEVICE
:
2275 Status
= NdisIForwardIrpAndWait(Adapter
, Irp
);
2276 if (NT_SUCCESS(Status
) && NT_SUCCESS(Irp
->IoStatus
.Status
))
2278 Status
= NdisIPnPStartDevice(DeviceObject
, Irp
);
2281 NDIS_DbgPrint(MIN_TRACE
, ("Lower driver failed device start\n"));
2282 Irp
->IoStatus
.Status
= Status
;
2283 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
2286 case IRP_MN_STOP_DEVICE
:
2287 Status
= NdisIPnPStopDevice(DeviceObject
, Irp
);
2288 if (!NT_SUCCESS(Status
))
2289 NDIS_DbgPrint(MIN_TRACE
, ("WARNING: Ignoring halt device failure! Passing the IRP down anyway\n"));
2290 Irp
->IoStatus
.Status
= STATUS_SUCCESS
;
2293 case IRP_MN_QUERY_REMOVE_DEVICE
:
2294 case IRP_MN_QUERY_STOP_DEVICE
:
2295 Status
= NdisIPnPQueryStopDevice(DeviceObject
, Irp
);
2296 Irp
->IoStatus
.Status
= Status
;
2297 if (Status
!= STATUS_SUCCESS
)
2299 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
2300 NDIS_DbgPrint(MIN_TRACE
, ("Failing miniport halt request\n"));
2305 case IRP_MN_CANCEL_REMOVE_DEVICE
:
2306 case IRP_MN_CANCEL_STOP_DEVICE
:
2307 Status
= NdisIForwardIrpAndWait(Adapter
, Irp
);
2308 if (NT_SUCCESS(Status
) && NT_SUCCESS(Irp
->IoStatus
.Status
))
2310 Status
= NdisIPnPCancelStopDevice(DeviceObject
, Irp
);
2314 NDIS_DbgPrint(MIN_TRACE
, ("Lower driver failed cancel stop/remove request\n"));
2316 Irp
->IoStatus
.Status
= Status
;
2317 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
2320 case IRP_MN_QUERY_PNP_DEVICE_STATE
:
2321 Status
= NDIS_STATUS_SUCCESS
;
2322 Irp
->IoStatus
.Status
= Status
;
2323 Irp
->IoStatus
.Information
|= Adapter
->NdisMiniportBlock
.PnPFlags
;
2330 IoSkipCurrentIrpStackLocation(Irp
);
2331 return IoCallDriver(Adapter
->NdisMiniportBlock
.NextDeviceObject
, Irp
);
2337 IN PDRIVER_OBJECT DriverObject
,
2338 IN PDEVICE_OBJECT PhysicalDeviceObject
)
2340 * FUNCTION: Create a device for an adapter found using PnP
2342 * DriverObject = Pointer to the miniport driver object
2343 * PhysicalDeviceObject = Pointer to the PDO for our adapter
2346 static const WCHAR ClassKeyName
[] = {'C','l','a','s','s','\\'};
2347 static const WCHAR LinkageKeyName
[] = {'\\','L','i','n','k','a','g','e',0};
2348 PNDIS_M_DRIVER_BLOCK Miniport
;
2349 PNDIS_M_DRIVER_BLOCK
*MiniportPtr
;
2350 WCHAR
*LinkageKeyBuffer
;
2351 ULONG DriverKeyLength
;
2352 RTL_QUERY_REGISTRY_TABLE QueryTable
[2];
2353 UNICODE_STRING ExportName
;
2354 PDEVICE_OBJECT DeviceObject
;
2355 PLOGICAL_ADAPTER Adapter
;
2359 * Gain the access to the miniport data structure first.
2362 MiniportPtr
= IoGetDriverObjectExtension(DriverObject
, (PVOID
)'NMID');
2363 if (MiniportPtr
== NULL
)
2365 NDIS_DbgPrint(MIN_TRACE
, ("Can't get driver object extension.\n"));
2366 return NDIS_STATUS_FAILURE
;
2368 Miniport
= *MiniportPtr
;
2371 * Get name of the Linkage registry key for our adapter. It's located under
2372 * the driver key for our driver and so we have basicly two ways to do it.
2373 * Either we can use IoOpenDriverRegistryKey or compose it using information
2374 * gathered by IoGetDeviceProperty. I choosed the second because
2375 * IoOpenDriverRegistryKey wasn't implemented at the time of writing.
2378 Status
= IoGetDeviceProperty(PhysicalDeviceObject
, DevicePropertyDriverKeyName
,
2379 0, NULL
, &DriverKeyLength
);
2380 if (Status
!= STATUS_BUFFER_TOO_SMALL
&& Status
!= STATUS_BUFFER_OVERFLOW
&& Status
!= STATUS_SUCCESS
)
2382 NDIS_DbgPrint(MIN_TRACE
, ("Can't get miniport driver key length.\n"));
2386 LinkageKeyBuffer
= ExAllocatePool(PagedPool
, DriverKeyLength
+
2387 sizeof(ClassKeyName
) + sizeof(LinkageKeyName
));
2388 if (LinkageKeyBuffer
== NULL
)
2390 NDIS_DbgPrint(MIN_TRACE
, ("Can't allocate memory for driver key name.\n"));
2391 return STATUS_INSUFFICIENT_RESOURCES
;
2394 Status
= IoGetDeviceProperty(PhysicalDeviceObject
, DevicePropertyDriverKeyName
,
2395 DriverKeyLength
, LinkageKeyBuffer
+
2396 (sizeof(ClassKeyName
) / sizeof(WCHAR
)),
2398 if (!NT_SUCCESS(Status
))
2400 NDIS_DbgPrint(MIN_TRACE
, ("Can't get miniport driver key.\n"));
2401 ExFreePool(LinkageKeyBuffer
);
2405 /* Compose the linkage key name. */
2406 RtlCopyMemory(LinkageKeyBuffer
, ClassKeyName
, sizeof(ClassKeyName
));
2407 RtlCopyMemory(LinkageKeyBuffer
+ ((sizeof(ClassKeyName
) + DriverKeyLength
) /
2408 sizeof(WCHAR
)) - 1, LinkageKeyName
, sizeof(LinkageKeyName
));
2410 NDIS_DbgPrint(DEBUG_MINIPORT
, ("LinkageKey: %S.\n", LinkageKeyBuffer
));
2413 * Now open the linkage key and read the "Export" and "RootDevice" values
2414 * which contains device name and root service respectively.
2417 RtlZeroMemory(QueryTable
, sizeof(QueryTable
));
2418 RtlInitUnicodeString(&ExportName
, NULL
);
2419 QueryTable
[0].Flags
= RTL_QUERY_REGISTRY_REQUIRED
| RTL_QUERY_REGISTRY_DIRECT
;
2420 QueryTable
[0].Name
= L
"Export";
2421 QueryTable
[0].EntryContext
= &ExportName
;
2423 Status
= RtlQueryRegistryValues(RTL_REGISTRY_CONTROL
, LinkageKeyBuffer
,
2424 QueryTable
, NULL
, NULL
);
2425 ExFreePool(LinkageKeyBuffer
);
2426 if (!NT_SUCCESS(Status
))
2428 NDIS_DbgPrint(MIN_TRACE
, ("Can't get miniport device name. (%x)\n", Status
));
2433 * Create the device object.
2436 NDIS_DbgPrint(MAX_TRACE
, ("creating device %wZ\n", &ExportName
));
2438 Status
= IoCreateDevice(Miniport
->DriverObject
, sizeof(LOGICAL_ADAPTER
),
2439 &ExportName
, FILE_DEVICE_PHYSICAL_NETCARD
,
2440 0, FALSE
, &DeviceObject
);
2441 if (!NT_SUCCESS(Status
))
2443 NDIS_DbgPrint(MIN_TRACE
, ("Could not create device object.\n"));
2444 RtlFreeUnicodeString(&ExportName
);
2449 * Initialize the adapter structure.
2452 Adapter
= (PLOGICAL_ADAPTER
)DeviceObject
->DeviceExtension
;
2453 KeInitializeSpinLock(&Adapter
->NdisMiniportBlock
.Lock
);
2454 InitializeListHead(&Adapter
->ProtocolListHead
);
2456 Status
= IoRegisterDeviceInterface(PhysicalDeviceObject
,
2457 &GUID_DEVINTERFACE_NET
,
2459 &Adapter
->NdisMiniportBlock
.SymbolicLinkName
);
2461 if (!NT_SUCCESS(Status
))
2463 NDIS_DbgPrint(MIN_TRACE
, ("Could not create device interface.\n"));
2464 IoDeleteDevice(DeviceObject
);
2465 RtlFreeUnicodeString(&ExportName
);
2469 Adapter
->NdisMiniportBlock
.DriverHandle
= Miniport
;
2470 Adapter
->NdisMiniportBlock
.MiniportName
= ExportName
;
2471 Adapter
->NdisMiniportBlock
.DeviceObject
= DeviceObject
;
2472 Adapter
->NdisMiniportBlock
.PhysicalDeviceObject
= PhysicalDeviceObject
;
2473 Adapter
->NdisMiniportBlock
.NextDeviceObject
=
2474 IoAttachDeviceToDeviceStack(Adapter
->NdisMiniportBlock
.DeviceObject
,
2475 PhysicalDeviceObject
);
2477 Adapter
->NdisMiniportBlock
.OldPnPDeviceState
= 0;
2478 Adapter
->NdisMiniportBlock
.PnPDeviceState
= NdisPnPDeviceAdded
;
2480 KeInitializeTimer(&Adapter
->NdisMiniportBlock
.WakeUpDpcTimer
.Timer
);
2481 KeInitializeDpc(&Adapter
->NdisMiniportBlock
.WakeUpDpcTimer
.Dpc
, MiniportHangDpc
, Adapter
);
2483 DeviceObject
->Flags
&= ~DO_DEVICE_INITIALIZING
;
2485 return STATUS_SUCCESS
;
2490 NdisGenericIrpHandler(
2491 IN PDEVICE_OBJECT DeviceObject
,
2494 PIO_STACK_LOCATION IrpSp
= IoGetCurrentIrpStackLocation(Irp
);
2496 /* Use the characteristics to classify the device */
2497 if (DeviceObject
->DeviceType
== FILE_DEVICE_PHYSICAL_NETCARD
)
2499 if ((IrpSp
->MajorFunction
== IRP_MJ_CREATE
) ||
2500 (IrpSp
->MajorFunction
== IRP_MJ_CLOSE
))
2502 return NdisICreateClose(DeviceObject
, Irp
);
2504 else if (IrpSp
->MajorFunction
== IRP_MJ_PNP
)
2506 return NdisIDispatchPnp(DeviceObject
, Irp
);
2508 else if (IrpSp
->MajorFunction
== IRP_MJ_SHUTDOWN
)
2510 return NdisIShutdown(DeviceObject
, Irp
);
2512 else if (IrpSp
->MajorFunction
== IRP_MJ_DEVICE_CONTROL
)
2514 return NdisIDeviceIoControl(DeviceObject
, Irp
);
2517 else if (DeviceObject
->DeviceType
== FILE_DEVICE_NETWORK
)
2519 PNDIS_M_DEVICE_BLOCK DeviceBlock
= DeviceObject
->DeviceExtension
;
2521 ASSERT(DeviceBlock
->DeviceObject
== DeviceObject
);
2523 if (DeviceBlock
->MajorFunction
[IrpSp
->MajorFunction
] != NULL
)
2525 return DeviceBlock
->MajorFunction
[IrpSp
->MajorFunction
](DeviceObject
, Irp
);
2533 Irp
->IoStatus
.Status
= STATUS_INVALID_DEVICE_REQUEST
;
2534 Irp
->IoStatus
.Information
= 0;
2536 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
2538 return STATUS_INVALID_DEVICE_REQUEST
;
2546 NdisMRegisterMiniport(
2547 IN NDIS_HANDLE NdisWrapperHandle
,
2548 IN PNDIS_MINIPORT_CHARACTERISTICS MiniportCharacteristics
,
2549 IN UINT CharacteristicsLength
)
2551 * FUNCTION: Registers a miniport's MiniportXxx entry points with the NDIS library
2553 * NdisWrapperHandle = Pointer to handle returned by NdisMInitializeWrapper
2554 * MiniportCharacteristics = Pointer to a buffer with miniport characteristics
2555 * CharacteristicsLength = Number of bytes in characteristics buffer
2557 * Status of operation
2561 PNDIS_M_DRIVER_BLOCK Miniport
= GET_MINIPORT_DRIVER(NdisWrapperHandle
);
2562 PNDIS_M_DRIVER_BLOCK
*MiniportPtr
;
2566 NDIS_DbgPrint(MAX_TRACE
, ("Called.\n"));
2568 switch (MiniportCharacteristics
->MajorNdisVersion
)
2571 MinSize
= sizeof(NDIS30_MINIPORT_CHARACTERISTICS
);
2575 MinSize
= sizeof(NDIS40_MINIPORT_CHARACTERISTICS
);
2579 switch (MiniportCharacteristics
->MinorNdisVersion
)
2582 MinSize
= sizeof(NDIS50_MINIPORT_CHARACTERISTICS
);
2586 MinSize
= sizeof(NDIS51_MINIPORT_CHARACTERISTICS
);
2590 NDIS_DbgPrint(MIN_TRACE
, ("Bad 5.x minor characteristics version.\n"));
2591 return NDIS_STATUS_BAD_VERSION
;
2596 NDIS_DbgPrint(MIN_TRACE
, ("Bad miniport characteristics version.\n"));
2597 return NDIS_STATUS_BAD_VERSION
;
2600 NDIS_DbgPrint(MIN_TRACE
, ("Initializing an NDIS %u.%u miniport\n",
2601 MiniportCharacteristics
->MajorNdisVersion
,
2602 MiniportCharacteristics
->MinorNdisVersion
));
2604 if (CharacteristicsLength
< MinSize
)
2606 NDIS_DbgPrint(MIN_TRACE
, ("Bad miniport characteristics length.\n"));
2607 return NDIS_STATUS_BAD_CHARACTERISTICS
;
2610 /* Check if mandatory MiniportXxx functions are specified */
2611 if ((!MiniportCharacteristics
->HaltHandler
) ||
2612 (!MiniportCharacteristics
->InitializeHandler
)||
2613 (!MiniportCharacteristics
->ResetHandler
))
2615 NDIS_DbgPrint(MIN_TRACE
, ("Bad miniport characteristics.\n"));
2616 return NDIS_STATUS_BAD_CHARACTERISTICS
;
2619 if (MiniportCharacteristics
->MajorNdisVersion
< 0x05)
2621 if ((!MiniportCharacteristics
->QueryInformationHandler
) ||
2622 (!MiniportCharacteristics
->SetInformationHandler
))
2624 NDIS_DbgPrint(MIN_TRACE
, ("Bad miniport characteristics. (Set/Query)\n"));
2625 return NDIS_STATUS_BAD_CHARACTERISTICS
;
2630 if (((!MiniportCharacteristics
->QueryInformationHandler
) ||
2631 (!MiniportCharacteristics
->SetInformationHandler
)) &&
2632 (!MiniportCharacteristics
->CoRequestHandler
))
2634 NDIS_DbgPrint(MIN_TRACE
, ("Bad miniport characteristics. (Set/Query)\n"));
2635 return NDIS_STATUS_BAD_CHARACTERISTICS
;
2639 if (MiniportCharacteristics
->MajorNdisVersion
== 0x03)
2641 if (!MiniportCharacteristics
->SendHandler
)
2643 NDIS_DbgPrint(MIN_TRACE
, ("Bad miniport characteristics. (NDIS 3.0)\n"));
2644 return NDIS_STATUS_BAD_CHARACTERISTICS
;
2647 else if (MiniportCharacteristics
->MajorNdisVersion
== 0x04)
2650 if ((!MiniportCharacteristics
->SendHandler
) &&
2651 (!MiniportCharacteristics
->SendPacketsHandler
))
2653 NDIS_DbgPrint(MIN_TRACE
, ("Bad miniport characteristics. (NDIS 4.0)\n"));
2654 return NDIS_STATUS_BAD_CHARACTERISTICS
;
2657 else if (MiniportCharacteristics
->MajorNdisVersion
== 0x05)
2659 /* TODO: Add more checks here */
2661 if ((!MiniportCharacteristics
->SendHandler
) &&
2662 (!MiniportCharacteristics
->SendPacketsHandler
) &&
2663 (!MiniportCharacteristics
->CoSendPacketsHandler
))
2665 NDIS_DbgPrint(MIN_TRACE
, ("Bad miniport characteristics. (NDIS 5.0)\n"));
2666 return NDIS_STATUS_BAD_CHARACTERISTICS
;
2670 RtlCopyMemory(&Miniport
->MiniportCharacteristics
, MiniportCharacteristics
, MinSize
);
2673 * NOTE: This is VERY unoptimal! Should we store the NDIS_M_DRIVER_BLOCK
2674 * structure in the driver extension or what?
2677 Status
= IoAllocateDriverObjectExtension(Miniport
->DriverObject
, (PVOID
)'NMID',
2678 sizeof(PNDIS_M_DRIVER_BLOCK
), (PVOID
*)&MiniportPtr
);
2679 if (!NT_SUCCESS(Status
))
2681 NDIS_DbgPrint(MIN_TRACE
, ("Can't allocate driver object extension.\n"));
2682 return NDIS_STATUS_RESOURCES
;
2685 *MiniportPtr
= Miniport
;
2687 /* We have to register for all of these so handler registered in NdisMRegisterDevice work */
2688 for (i
= 0; i
<= IRP_MJ_MAXIMUM_FUNCTION
; i
++)
2690 Miniport
->DriverObject
->MajorFunction
[i
] = NdisGenericIrpHandler
;
2693 Miniport
->DriverObject
->DriverExtension
->AddDevice
= NdisIAddDevice
;
2695 return NDIS_STATUS_SUCCESS
;
2701 #undef NdisMResetComplete
2705 IN NDIS_HANDLE MiniportAdapterHandle
,
2706 IN NDIS_STATUS Status
,
2707 IN BOOLEAN AddressingReset
)
2709 MiniResetComplete(MiniportAdapterHandle
, Status
, AddressingReset
);
2715 #undef NdisMSendComplete
2719 IN NDIS_HANDLE MiniportAdapterHandle
,
2720 IN PNDIS_PACKET Packet
,
2721 IN NDIS_STATUS Status
)
2723 * FUNCTION: Forwards a message to the initiating protocol saying
2724 * that a packet was handled
2726 * NdisAdapterHandle = Handle input to MiniportInitialize
2727 * Packet = Pointer to NDIS packet that was sent
2728 * Status = Status of send operation
2731 MiniSendComplete(MiniportAdapterHandle
, Packet
, Status
);
2737 #undef NdisMSendResourcesAvailable
2740 NdisMSendResourcesAvailable(
2741 IN NDIS_HANDLE MiniportAdapterHandle
)
2743 MiniSendResourcesAvailable(MiniportAdapterHandle
);
2749 #undef NdisMTransferDataComplete
2752 NdisMTransferDataComplete(
2753 IN NDIS_HANDLE MiniportAdapterHandle
,
2754 IN PNDIS_PACKET Packet
,
2755 IN NDIS_STATUS Status
,
2756 IN UINT BytesTransferred
)
2758 MiniTransferDataComplete(MiniportAdapterHandle
, Packet
, Status
, BytesTransferred
);
2764 #undef NdisMSetAttributes
2768 IN NDIS_HANDLE MiniportAdapterHandle
,
2769 IN NDIS_HANDLE MiniportAdapterContext
,
2770 IN BOOLEAN BusMaster
,
2771 IN NDIS_INTERFACE_TYPE AdapterType
)
2773 * FUNCTION: Informs the NDIS library of significant features of the caller's NIC
2775 * MiniportAdapterHandle = Handle input to MiniportInitialize
2776 * MiniportAdapterContext = Pointer to context information
2777 * BusMaster = Specifies TRUE if the caller's NIC is a busmaster DMA device
2778 * AdapterType = Specifies the I/O bus interface of the caller's NIC
2781 NDIS_DbgPrint(MAX_TRACE
, ("Called.\n"));
2782 NdisMSetAttributesEx(MiniportAdapterHandle
, MiniportAdapterContext
, 0,
2783 BusMaster
? NDIS_ATTRIBUTE_BUS_MASTER
: 0,
2792 NdisMSetAttributesEx(
2793 IN NDIS_HANDLE MiniportAdapterHandle
,
2794 IN NDIS_HANDLE MiniportAdapterContext
,
2795 IN UINT CheckForHangTimeInSeconds OPTIONAL
,
2796 IN ULONG AttributeFlags
,
2797 IN NDIS_INTERFACE_TYPE AdapterType
)
2799 * FUNCTION: Informs the NDIS library of significant features of the caller's NIC
2801 * MiniportAdapterHandle = Handle input to MiniportInitialize
2802 * MiniportAdapterContext = Pointer to context information
2803 * CheckForHangTimeInSeconds = Specifies interval in seconds at which
2804 * MiniportCheckForHang should be called
2805 * AttributeFlags = Bitmask that indicates specific attributes
2806 * AdapterType = Specifies the I/O bus interface of the caller's NIC
2809 PLOGICAL_ADAPTER Adapter
= GET_LOGICAL_ADAPTER(MiniportAdapterHandle
);
2811 NDIS_DbgPrint(MAX_TRACE
, ("Called.\n"));
2813 Adapter
->NdisMiniportBlock
.MiniportAdapterContext
= MiniportAdapterContext
;
2814 Adapter
->NdisMiniportBlock
.Flags
= AttributeFlags
;
2815 Adapter
->NdisMiniportBlock
.AdapterType
= AdapterType
;
2816 if (CheckForHangTimeInSeconds
> 0)
2817 Adapter
->NdisMiniportBlock
.CheckForHangSeconds
= CheckForHangTimeInSeconds
;
2818 if (AttributeFlags
& NDIS_ATTRIBUTE_INTERMEDIATE_DRIVER
)
2819 NDIS_DbgPrint(MIN_TRACE
, ("Intermediate drivers not supported yet.\n"));
2821 NDIS_DbgPrint(MIN_TRACE
, ("Miniport attribute flags: 0x%x\n", AttributeFlags
));
2823 if (Adapter
->NdisMiniportBlock
.DriverHandle
->MiniportCharacteristics
.AdapterShutdownHandler
)
2825 NDIS_DbgPrint(MAX_TRACE
, ("Miniport set AdapterShutdownHandler in MiniportCharacteristics\n"));
2826 NdisMRegisterAdapterShutdownHandler(Adapter
,
2827 Adapter
->NdisMiniportBlock
.MiniportAdapterContext
,
2828 Adapter
->NdisMiniportBlock
.DriverHandle
->MiniportCharacteristics
.AdapterShutdownHandler
);
2838 IN ULONG MicrosecondsToSleep
)
2840 * FUNCTION: delay the thread's execution for MicrosecondsToSleep
2842 * MicrosecondsToSleep: duh...
2844 * - Because this is a blocking call, current IRQL must be < DISPATCH_LEVEL
2848 LARGE_INTEGER DueTime
;
2852 DueTime
.QuadPart
= (-1) * 10 * MicrosecondsToSleep
;
2854 KeInitializeTimer(&Timer
);
2855 KeSetTimer(&Timer
, DueTime
, 0);
2856 KeWaitForSingleObject(&Timer
, Executive
, KernelMode
, FALSE
, 0);
2864 NdisMSynchronizeWithInterrupt(
2865 IN PNDIS_MINIPORT_INTERRUPT Interrupt
,
2866 IN PVOID SynchronizeFunction
,
2867 IN PVOID SynchronizeContext
)
2869 return(KeSynchronizeExecution(Interrupt
->InterruptObject
,
2870 (PKSYNCHRONIZE_ROUTINE
)SynchronizeFunction
,
2871 SynchronizeContext
));
2880 IN NDIS_HANDLE LogHandle
,
2882 IN UINT LogBufferSize
)
2884 PUCHAR Buffer
= LogBuffer
;
2888 for (i
= 0; i
< LogBufferSize
; i
+= 16)
2890 DbgPrint("%08x |", i
);
2891 for (j
= 0; j
< 16; j
++)
2894 if (idx
< LogBufferSize
)
2895 DbgPrint(" %02x", Buffer
[idx
]);
2900 for (j
= 0; j
< 16; j
++)
2903 if (idx
== LogBufferSize
)
2905 if (Buffer
[idx
] >= ' ') /* FIXME: not portable! replace by if (isprint(Buffer[idx])) ? */
2906 DbgPrint("%c", Buffer
[idx
]);
2913 return NDIS_STATUS_FAILURE
;
2921 NdisTerminateWrapper(
2922 IN NDIS_HANDLE NdisWrapperHandle
,
2923 IN PVOID SystemSpecific
)
2925 * FUNCTION: Releases resources allocated by a call to NdisInitializeWrapper
2927 * NdisWrapperHandle = Handle returned by NdisInitializeWrapper (NDIS_M_DRIVER_BLOCK)
2928 * SystemSpecific = Always NULL
2931 PNDIS_M_DRIVER_BLOCK Miniport
= GET_MINIPORT_DRIVER(NdisWrapperHandle
);
2933 NDIS_DbgPrint(MAX_TRACE
, ("Called.\n"));
2935 ExFreePool(Miniport
->RegistryPath
->Buffer
);
2936 ExFreePool(Miniport
->RegistryPath
);
2937 ExInterlockedRemoveEntryList(&Miniport
->ListEntry
, &MiniportListLock
);
2938 ExFreePool(Miniport
);
2947 NdisMQueryAdapterInstanceName(
2948 OUT PNDIS_STRING AdapterInstanceName
,
2949 IN NDIS_HANDLE MiniportAdapterHandle
)
2957 PLOGICAL_ADAPTER Adapter
= (PLOGICAL_ADAPTER
)MiniportAdapterHandle
;
2958 UNICODE_STRING AdapterName
;
2960 NDIS_DbgPrint(MAX_TRACE
, ("Called.\n"));
2962 AdapterName
.Length
= 0;
2963 AdapterName
.MaximumLength
= Adapter
->NdisMiniportBlock
.MiniportName
.MaximumLength
;
2964 AdapterName
.Buffer
= ExAllocatePool(PagedPool
, AdapterName
.MaximumLength
);
2965 if (!AdapterName
.Buffer
) {
2966 NDIS_DbgPrint(MIN_TRACE
, ("Insufficient resources\n"));
2967 return NDIS_STATUS_RESOURCES
;
2970 RtlCopyUnicodeString(&AdapterName
, &Adapter
->NdisMiniportBlock
.MiniportName
);
2972 *AdapterInstanceName
= AdapterName
;
2974 return NDIS_STATUS_SUCCESS
;
2982 NdisDeregisterAdapterShutdownHandler(
2983 IN NDIS_HANDLE NdisAdapterHandle
)
2991 NdisMDeregisterAdapterShutdownHandler(NdisAdapterHandle
);
3000 NdisRegisterAdapterShutdownHandler(
3001 IN NDIS_HANDLE NdisAdapterHandle
,
3002 IN PVOID ShutdownContext
,
3003 IN ADAPTER_SHUTDOWN_HANDLER ShutdownHandler
)
3011 NdisMRegisterAdapterShutdownHandler(NdisAdapterHandle
,
3021 NdisMGetDeviceProperty(
3022 IN NDIS_HANDLE MiniportAdapterHandle
,
3023 IN OUT PDEVICE_OBJECT
*PhysicalDeviceObject OPTIONAL
,
3024 IN OUT PDEVICE_OBJECT
*FunctionalDeviceObject OPTIONAL
,
3025 IN OUT PDEVICE_OBJECT
*NextDeviceObject OPTIONAL
,
3026 IN OUT PCM_RESOURCE_LIST
*AllocatedResources OPTIONAL
,
3027 IN OUT PCM_RESOURCE_LIST
*AllocatedResourcesTranslated OPTIONAL
)
3035 PLOGICAL_ADAPTER Adapter
= MiniportAdapterHandle
;
3037 NDIS_DbgPrint(MAX_TRACE
, ("Called\n"));
3039 if (PhysicalDeviceObject
!= NULL
)
3040 *PhysicalDeviceObject
= Adapter
->NdisMiniportBlock
.PhysicalDeviceObject
;
3042 if (FunctionalDeviceObject
!= NULL
)
3043 *FunctionalDeviceObject
= Adapter
->NdisMiniportBlock
.DeviceObject
;
3045 if (NextDeviceObject
!= NULL
)
3046 *NextDeviceObject
= Adapter
->NdisMiniportBlock
.NextDeviceObject
;
3048 if (AllocatedResources
!= NULL
)
3049 *AllocatedResources
= Adapter
->NdisMiniportBlock
.AllocatedResources
;
3051 if (AllocatedResourcesTranslated
!= NULL
)
3052 *AllocatedResourcesTranslated
= Adapter
->NdisMiniportBlock
.AllocatedResourcesTranslated
;
3060 NdisMRegisterUnloadHandler(
3061 IN NDIS_HANDLE NdisWrapperHandle
,
3062 IN PDRIVER_UNLOAD UnloadHandler
)
3070 PNDIS_M_DRIVER_BLOCK DriverBlock
= NdisWrapperHandle
;
3072 NDIS_DbgPrint(MAX_TRACE
, ("Miniport registered unload handler\n"));
3074 DriverBlock
->DriverObject
->DriverUnload
= UnloadHandler
;
3082 NdisMRegisterDevice(
3083 IN NDIS_HANDLE NdisWrapperHandle
,
3084 IN PNDIS_STRING DeviceName
,
3085 IN PNDIS_STRING SymbolicName
,
3086 IN PDRIVER_DISPATCH MajorFunctions
[],
3087 OUT PDEVICE_OBJECT
*pDeviceObject
,
3088 OUT NDIS_HANDLE
*NdisDeviceHandle
)
3096 PNDIS_M_DRIVER_BLOCK DriverBlock
= NdisWrapperHandle
;
3097 PNDIS_M_DEVICE_BLOCK DeviceBlock
;
3098 PDEVICE_OBJECT DeviceObject
;
3102 NDIS_DbgPrint(MAX_TRACE
, ("Called\n"));
3104 Status
= IoCreateDevice(DriverBlock
->DriverObject
,
3105 sizeof(NDIS_M_DEVICE_BLOCK
),
3107 FILE_DEVICE_NETWORK
,
3112 if (!NT_SUCCESS(Status
))
3114 NDIS_DbgPrint(MIN_TRACE
, ("IoCreateDevice failed (%x)\n", Status
));
3118 Status
= IoCreateSymbolicLink(SymbolicName
, DeviceName
);
3120 if (!NT_SUCCESS(Status
))
3122 NDIS_DbgPrint(MIN_TRACE
, ("IoCreateSymbolicLink failed (%x)\n", Status
));
3123 IoDeleteDevice(DeviceObject
);
3127 DeviceBlock
= DeviceObject
->DeviceExtension
;
3131 NDIS_DbgPrint(MIN_TRACE
, ("Insufficient resources\n"));
3132 IoDeleteDevice(DeviceObject
);
3133 IoDeleteSymbolicLink(SymbolicName
);
3134 return NDIS_STATUS_RESOURCES
;
3137 for (i
= 0; i
<= IRP_MJ_MAXIMUM_FUNCTION
; i
++)
3138 DeviceBlock
->MajorFunction
[i
] = MajorFunctions
[i
];
3140 DeviceBlock
->DeviceObject
= DeviceObject
;
3141 DeviceBlock
->SymbolicName
= SymbolicName
;
3143 *pDeviceObject
= DeviceObject
;
3144 *NdisDeviceHandle
= DeviceBlock
;
3146 return NDIS_STATUS_SUCCESS
;
3154 NdisMDeregisterDevice(
3155 IN NDIS_HANDLE NdisDeviceHandle
)
3163 PNDIS_M_DEVICE_BLOCK DeviceBlock
= NdisDeviceHandle
;
3165 IoDeleteDevice(DeviceBlock
->DeviceObject
);
3167 IoDeleteSymbolicLink(DeviceBlock
->SymbolicName
);
3169 return NDIS_STATUS_SUCCESS
;
3177 NdisQueryAdapterInstanceName(
3178 OUT PNDIS_STRING AdapterInstanceName
,
3179 IN NDIS_HANDLE NdisBindingHandle
)
3187 PADAPTER_BINDING AdapterBinding
= NdisBindingHandle
;
3188 PLOGICAL_ADAPTER Adapter
= AdapterBinding
->Adapter
;
3190 return NdisMQueryAdapterInstanceName(AdapterInstanceName
,
3199 NdisCompletePnPEvent(
3200 IN NDIS_STATUS Status
,
3201 IN NDIS_HANDLE NdisBindingHandle
,
3202 IN PNET_PNP_EVENT NetPnPEvent
)
3210 PIRP Irp
= (PIRP
)NetPnPEvent
->NdisReserved
[0];
3211 PLIST_ENTRY CurrentEntry
= (PLIST_ENTRY
)NetPnPEvent
->NdisReserved
[1];
3212 PADAPTER_BINDING AdapterBinding
= NdisBindingHandle
;
3213 PLOGICAL_ADAPTER Adapter
= AdapterBinding
->Adapter
;
3214 NDIS_STATUS NdisStatus
;
3216 if (Status
!= NDIS_STATUS_SUCCESS
)
3218 if (NetPnPEvent
->Buffer
) ExFreePool(NetPnPEvent
->Buffer
);
3219 ExFreePool(NetPnPEvent
);
3220 Irp
->IoStatus
.Status
= Status
;
3221 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
3225 while (CurrentEntry
!= &Adapter
->ProtocolListHead
)
3227 AdapterBinding
= CONTAINING_RECORD(CurrentEntry
, ADAPTER_BINDING
, AdapterListEntry
);
3229 NdisStatus
= (*AdapterBinding
->ProtocolBinding
->Chars
.PnPEventHandler
)(
3230 AdapterBinding
->NdisOpenBlock
.ProtocolBindingContext
,
3233 if (NdisStatus
== NDIS_STATUS_PENDING
)
3235 NetPnPEvent
->NdisReserved
[1] = (ULONG_PTR
)CurrentEntry
->Flink
;
3238 else if (NdisStatus
!= NDIS_STATUS_SUCCESS
)
3240 if (NetPnPEvent
->Buffer
) ExFreePool(NetPnPEvent
->Buffer
);
3241 ExFreePool(NetPnPEvent
);
3242 Irp
->IoStatus
.Status
= NdisStatus
;
3243 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
3247 CurrentEntry
= CurrentEntry
->Flink
;
3250 if (NetPnPEvent
->Buffer
) ExFreePool(NetPnPEvent
->Buffer
);
3251 ExFreePool(NetPnPEvent
);
3253 Irp
->IoStatus
.Status
= NDIS_STATUS_SUCCESS
;
3254 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
3262 NdisCancelSendPackets(
3263 IN NDIS_HANDLE NdisBindingHandle
,
3266 PADAPTER_BINDING AdapterBinding
= NdisBindingHandle
;
3267 PLOGICAL_ADAPTER Adapter
= AdapterBinding
->Adapter
;
3269 NDIS_DbgPrint(MAX_TRACE
, ("Called for ID %x.\n", CancelId
));
3271 if (Adapter
->NdisMiniportBlock
.DriverHandle
->MiniportCharacteristics
.CancelSendPacketsHandler
)
3273 (*Adapter
->NdisMiniportBlock
.DriverHandle
->MiniportCharacteristics
.CancelSendPacketsHandler
)(
3274 Adapter
->NdisMiniportBlock
.MiniportAdapterContext
,
3285 NdisIMGetBindingContext(
3286 IN NDIS_HANDLE NdisBindingHandle
)
3294 PADAPTER_BINDING AdapterBinding
= NdisBindingHandle
;
3295 PLOGICAL_ADAPTER Adapter
= AdapterBinding
->Adapter
;
3297 NDIS_DbgPrint(MAX_TRACE
, ("Called.\n"));
3299 return Adapter
->NdisMiniportBlock
.DeviceContext
;
3308 NdisIMGetDeviceContext(
3309 IN NDIS_HANDLE MiniportAdapterHandle
)
3317 PLOGICAL_ADAPTER Adapter
= MiniportAdapterHandle
;
3319 NDIS_DbgPrint(MAX_TRACE
, ("Called.\n"));
3321 return Adapter
->NdisMiniportBlock
.DeviceContext
;