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
);
173 PLOGICAL_ADAPTER Adapter
,
174 NDIS_HANDLE MacReceiveContext
,
176 UINT HeaderBufferSize
,
177 PVOID LookaheadBuffer
,
178 UINT LookaheadBufferSize
,
181 * FUNCTION: Indicate received data to bound protocols
183 * Adapter = Pointer to logical adapter
184 * MacReceiveContext = MAC receive context handle
185 * HeaderBuffer = Pointer to header buffer
186 * HeaderBufferSize = Size of header buffer
187 * LookaheadBuffer = Pointer to lookahead buffer
188 * LookaheadBufferSize = Size of lookahead buffer
189 * PacketSize = Total size of received packet
193 PLIST_ENTRY CurrentEntry
;
194 PADAPTER_BINDING AdapterBinding
;
196 NDIS_DbgPrint(DEBUG_MINIPORT
, ("Called. Adapter (0x%X) HeaderBuffer (0x%X) "
197 "HeaderBufferSize (0x%X) LookaheadBuffer (0x%X) LookaheadBufferSize (0x%X).\n",
198 Adapter
, HeaderBuffer
, HeaderBufferSize
, LookaheadBuffer
, LookaheadBufferSize
));
200 MiniDisplayPacket2(HeaderBuffer
, HeaderBufferSize
, LookaheadBuffer
, LookaheadBufferSize
);
202 NDIS_DbgPrint(MAX_TRACE
, ("acquiring miniport block lock\n"));
203 KeAcquireSpinLock(&Adapter
->NdisMiniportBlock
.Lock
, &OldIrql
);
205 CurrentEntry
= Adapter
->ProtocolListHead
.Flink
;
206 NDIS_DbgPrint(DEBUG_MINIPORT
, ("CurrentEntry = %x\n", CurrentEntry
));
208 if (CurrentEntry
== &Adapter
->ProtocolListHead
)
210 NDIS_DbgPrint(MIN_TRACE
, ("WARNING: No upper protocol layer.\n"));
213 while (CurrentEntry
!= &Adapter
->ProtocolListHead
)
215 AdapterBinding
= CONTAINING_RECORD(CurrentEntry
, ADAPTER_BINDING
, AdapterListEntry
);
216 NDIS_DbgPrint(DEBUG_MINIPORT
, ("AdapterBinding = %x\n", AdapterBinding
));
220 ("XXX (%x) %x %x %x %x %x %x %x XXX\n",
221 *AdapterBinding
->ProtocolBinding
->Chars
.ReceiveHandler
,
222 AdapterBinding
->NdisOpenBlock
.ProtocolBindingContext
,
230 /* call the receive handler */
231 (*AdapterBinding
->ProtocolBinding
->Chars
.ReceiveHandler
)(
232 AdapterBinding
->NdisOpenBlock
.ProtocolBindingContext
,
240 CurrentEntry
= CurrentEntry
->Flink
;
243 KeReleaseSpinLock(&Adapter
->NdisMiniportBlock
.Lock
, OldIrql
);
245 NDIS_DbgPrint(MAX_TRACE
, ("Leaving.\n"));
254 IN PNDIS_PACKET
*PacketsToReturn
,
255 IN UINT NumberOfPackets
)
257 * FUNCTION: Releases ownership of one or more packets
259 * PacketsToReturn = Pointer to an array of pointers to packet descriptors
260 * NumberOfPackets = Number of pointers in descriptor pointer array
264 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 Adapter
->NdisMiniportBlock
.DriverHandle
->MiniportCharacteristics
.ReturnPacketHandler(
278 Adapter
->NdisMiniportBlock
.MiniportAdapterContext
,
284 MiniIndicateReceivePacket(
285 IN NDIS_HANDLE MiniportAdapterHandle
,
286 IN PPNDIS_PACKET PacketArray
,
287 IN UINT NumberOfPackets
)
289 * FUNCTION: receives miniport packet array indications
291 * MiniportAdapterHandle: Miniport handle for the adapter
292 * PacketArray: pointer to a list of packet pointers to indicate
293 * NumberOfPackets: number of packets to indicate
297 PLOGICAL_ADAPTER Adapter
= MiniportAdapterHandle
;
298 PLIST_ENTRY CurrentEntry
;
299 PADAPTER_BINDING AdapterBinding
;
303 KeAcquireSpinLock(&Adapter
->NdisMiniportBlock
.Lock
, &OldIrql
);
305 CurrentEntry
= Adapter
->ProtocolListHead
.Flink
;
307 while (CurrentEntry
!= &Adapter
->ProtocolListHead
)
309 AdapterBinding
= CONTAINING_RECORD(CurrentEntry
, ADAPTER_BINDING
, AdapterListEntry
);
311 for (i
= 0; i
< NumberOfPackets
; i
++)
313 /* Store the indicating miniport in the packet */
314 PacketArray
[i
]->Reserved
[1] = (ULONG_PTR
)Adapter
;
316 if (AdapterBinding
->ProtocolBinding
->Chars
.ReceivePacketHandler
&&
317 NDIS_GET_PACKET_STATUS(PacketArray
[i
]) != NDIS_STATUS_RESOURCES
)
319 NDIS_DbgPrint(MID_TRACE
, ("Indicating packet to protocol's ReceivePacket handler\n"));
320 PacketArray
[i
]->WrapperReserved
[0] += (*AdapterBinding
->ProtocolBinding
->Chars
.ReceivePacketHandler
)(
321 AdapterBinding
->NdisOpenBlock
.ProtocolBindingContext
,
323 NDIS_DbgPrint(MID_TRACE
, ("Protocol is holding %d references to the packet\n", PacketArray
[i
]->WrapperReserved
[0]));
327 UINT FirstBufferLength
, TotalBufferLength
, LookAheadSize
, HeaderSize
;
328 PNDIS_BUFFER NdisBuffer
;
329 PVOID NdisBufferVA
, LookAheadBuffer
;
331 NdisGetFirstBufferFromPacket(PacketArray
[i
],
337 HeaderSize
= NDIS_GET_PACKET_HEADER_SIZE(PacketArray
[i
]);
339 if (Adapter
->NdisMiniportBlock
.CurrentLookahead
< (TotalBufferLength
- HeaderSize
))
341 LookAheadSize
= Adapter
->NdisMiniportBlock
.CurrentLookahead
;
345 LookAheadSize
= TotalBufferLength
- HeaderSize
;
348 LookAheadBuffer
= ExAllocatePool(NonPagedPool
, LookAheadSize
);
349 if (!LookAheadBuffer
)
351 NDIS_DbgPrint(MIN_TRACE
, ("Failed to allocate lookahead buffer!\n"));
352 KeReleaseSpinLock(&Adapter
->NdisMiniportBlock
.Lock
, OldIrql
);
356 CopyBufferChainToBuffer(LookAheadBuffer
,
361 NDIS_DbgPrint(MID_TRACE
, ("Indicating packet to protocol's legacy Receive handler\n"));
362 (*AdapterBinding
->ProtocolBinding
->Chars
.ReceiveHandler
)(
363 AdapterBinding
->NdisOpenBlock
.ProtocolBindingContext
,
364 AdapterBinding
->NdisOpenBlock
.MacHandle
,
369 TotalBufferLength
- HeaderSize
);
371 ExFreePool(LookAheadBuffer
);
375 CurrentEntry
= CurrentEntry
->Flink
;
378 /* Loop the packet array to get everything
379 * set up for return the packets to the miniport */
380 for (i
= 0; i
< NumberOfPackets
; i
++)
382 /* First, check the initial packet status */
383 if (NDIS_GET_PACKET_STATUS(PacketArray
[i
]) == NDIS_STATUS_RESOURCES
)
385 /* The miniport driver gets it back immediately so nothing to do here */
386 NDIS_DbgPrint(MID_TRACE
, ("Miniport needs the packet back immediately\n"));
390 /* Different behavior depending on whether it's serialized or not */
391 if (Adapter
->NdisMiniportBlock
.Flags
& NDIS_ATTRIBUTE_DESERIALIZE
)
393 /* We need to check the reference count */
394 if (PacketArray
[i
]->WrapperReserved
[0] == 0)
396 /* NOTE: Unlike serialized miniports, this is REQUIRED to be called for each
397 * packet received that can be reused immediately, it is not implied! */
398 Adapter
->NdisMiniportBlock
.DriverHandle
->MiniportCharacteristics
.ReturnPacketHandler(
399 Adapter
->NdisMiniportBlock
.MiniportAdapterContext
,
401 NDIS_DbgPrint(MID_TRACE
, ("Packet has been returned to miniport (Deserialized)\n"));
405 /* Packet will be returned by the protocol's call to NdisReturnPackets */
406 NDIS_DbgPrint(MID_TRACE
, ("Packet will be returned to miniport later (Deserialized)\n"));
411 /* Check the reference count */
412 if (PacketArray
[i
]->WrapperReserved
[0] == 0)
414 /* NDIS_STATUS_SUCCESS means the miniport can have the packet back immediately */
415 NDIS_SET_PACKET_STATUS(PacketArray
[i
], NDIS_STATUS_SUCCESS
);
417 NDIS_DbgPrint(MID_TRACE
, ("Packet has been returned to miniport (Serialized)\n"));
421 /* NDIS_STATUS_PENDING means the miniport needs to wait for MiniportReturnPacket */
422 NDIS_SET_PACKET_STATUS(PacketArray
[i
], NDIS_STATUS_PENDING
);
424 NDIS_DbgPrint(MID_TRACE
, ("Packet will be returned to miniport later (Serialized)\n"));
429 KeReleaseSpinLock(&Adapter
->NdisMiniportBlock
.Lock
, OldIrql
);
435 IN NDIS_HANDLE MiniportAdapterHandle
,
436 IN NDIS_STATUS Status
,
437 IN BOOLEAN AddressingReset
)
439 PLOGICAL_ADAPTER Adapter
= MiniportAdapterHandle
;
440 PLIST_ENTRY CurrentEntry
;
441 PADAPTER_BINDING AdapterBinding
;
445 MiniDoAddressingReset(Adapter
);
447 NdisMIndicateStatus(Adapter
, NDIS_STATUS_RESET_END
, NULL
, 0);
448 NdisMIndicateStatusComplete(Adapter
);
450 KeAcquireSpinLock(&Adapter
->NdisMiniportBlock
.Lock
, &OldIrql
);
452 if (Adapter
->NdisMiniportBlock
.ResetStatus
!= NDIS_STATUS_PENDING
)
454 KeBugCheckEx(BUGCODE_ID_DRIVER
,
455 (ULONG_PTR
)MiniportAdapterHandle
,
457 (ULONG_PTR
)AddressingReset
,
461 Adapter
->NdisMiniportBlock
.ResetStatus
= Status
;
463 CurrentEntry
= Adapter
->ProtocolListHead
.Flink
;
465 while (CurrentEntry
!= &Adapter
->ProtocolListHead
)
467 AdapterBinding
= CONTAINING_RECORD(CurrentEntry
, ADAPTER_BINDING
, AdapterListEntry
);
469 (*AdapterBinding
->ProtocolBinding
->Chars
.ResetCompleteHandler
)(
470 AdapterBinding
->NdisOpenBlock
.ProtocolBindingContext
,
473 CurrentEntry
= CurrentEntry
->Flink
;
476 KeReleaseSpinLock(&Adapter
->NdisMiniportBlock
.Lock
, OldIrql
);
481 IN NDIS_HANDLE MiniportAdapterHandle
,
482 IN NDIS_STATUS Status
)
484 PLOGICAL_ADAPTER Adapter
= (PLOGICAL_ADAPTER
)MiniportAdapterHandle
;
485 PNDIS_REQUEST Request
;
486 PNDIS_REQUEST_MAC_BLOCK MacBlock
;
489 NDIS_DbgPrint(DEBUG_MINIPORT
, ("Called.\n"));
491 KeRaiseIrql(DISPATCH_LEVEL
, &OldIrql
);
493 KeAcquireSpinLockAtDpcLevel(&Adapter
->NdisMiniportBlock
.Lock
);
494 Request
= Adapter
->NdisMiniportBlock
.PendingRequest
;
495 KeReleaseSpinLockFromDpcLevel(&Adapter
->NdisMiniportBlock
.Lock
);
497 MacBlock
= (PNDIS_REQUEST_MAC_BLOCK
)Request
->MacReserved
;
499 if( MacBlock
->Binding
->RequestCompleteHandler
) {
500 (*MacBlock
->Binding
->RequestCompleteHandler
)(
501 MacBlock
->Binding
->ProtocolBindingContext
,
506 KeAcquireSpinLockAtDpcLevel(&Adapter
->NdisMiniportBlock
.Lock
);
507 Adapter
->NdisMiniportBlock
.PendingRequest
= NULL
;
508 KeReleaseSpinLockFromDpcLevel(&Adapter
->NdisMiniportBlock
.Lock
);
510 KeLowerIrql(OldIrql
);
515 IN NDIS_HANDLE MiniportAdapterHandle
,
516 IN PNDIS_PACKET Packet
,
517 IN NDIS_STATUS Status
)
519 * FUNCTION: Forwards a message to the initiating protocol saying
520 * that a packet was handled
522 * NdisAdapterHandle = Handle input to MiniportInitialize
523 * Packet = Pointer to NDIS packet that was sent
524 * Status = Status of send operation
527 PLOGICAL_ADAPTER Adapter
= MiniportAdapterHandle
;
528 PADAPTER_BINDING AdapterBinding
;
530 PSCATTER_GATHER_LIST SGList
;
532 NDIS_DbgPrint(DEBUG_MINIPORT
, ("Called.\n"));
534 AdapterBinding
= (PADAPTER_BINDING
)Packet
->Reserved
[1];
536 KeRaiseIrql(DISPATCH_LEVEL
, &OldIrql
);
538 if (Adapter
->NdisMiniportBlock
.ScatterGatherListSize
!= 0)
540 NDIS_DbgPrint(MAX_TRACE
, ("Freeing Scatter/Gather list\n"));
542 SGList
= NDIS_PER_PACKET_INFO_FROM_PACKET(Packet
,
543 ScatterGatherListPacketInfo
);
545 Adapter
->NdisMiniportBlock
.SystemAdapterObject
->
546 DmaOperations
->PutScatterGatherList(
547 Adapter
->NdisMiniportBlock
.SystemAdapterObject
,
551 NDIS_PER_PACKET_INFO_FROM_PACKET(Packet
,
552 ScatterGatherListPacketInfo
) = NULL
;
555 (*AdapterBinding
->ProtocolBinding
->Chars
.SendCompleteHandler
)(
556 AdapterBinding
->NdisOpenBlock
.ProtocolBindingContext
,
560 KeLowerIrql(OldIrql
);
565 MiniSendResourcesAvailable(
566 IN NDIS_HANDLE MiniportAdapterHandle
)
575 MiniTransferDataComplete(
576 IN NDIS_HANDLE MiniportAdapterHandle
,
577 IN PNDIS_PACKET Packet
,
578 IN NDIS_STATUS Status
,
579 IN UINT BytesTransferred
)
581 PADAPTER_BINDING AdapterBinding
;
584 NDIS_DbgPrint(DEBUG_MINIPORT
, ("Called.\n"));
586 AdapterBinding
= (PADAPTER_BINDING
)Packet
->Reserved
[1];
588 KeRaiseIrql(DISPATCH_LEVEL
, &OldIrql
);
589 (*AdapterBinding
->ProtocolBinding
->Chars
.TransferDataCompleteHandler
)(
590 AdapterBinding
->NdisOpenBlock
.ProtocolBindingContext
,
594 KeLowerIrql(OldIrql
);
599 MiniAdapterHasAddress(
600 PLOGICAL_ADAPTER Adapter
,
603 * FUNCTION: Determines whether a packet has the same destination address as an adapter
605 * Adapter = Pointer to logical adapter object
606 * Packet = Pointer to NDIS packet
608 * TRUE if the destination address is that of the adapter, FALSE if not
614 PNDIS_BUFFER NdisBuffer
;
617 NDIS_DbgPrint(DEBUG_MINIPORT
, ("Called.\n"));
622 NDIS_DbgPrint(MIN_TRACE
, ("Adapter object was null\n"));
628 NDIS_DbgPrint(MIN_TRACE
, ("Packet was null\n"));
633 NdisQueryPacket(Packet
, NULL
, NULL
, &NdisBuffer
, NULL
);
637 NDIS_DbgPrint(MIN_TRACE
, ("Packet contains no buffers.\n"));
641 NdisQueryBuffer(NdisBuffer
, (PVOID
)&Start2
, &BufferLength
);
643 /* FIXME: Should handle fragmented packets */
645 switch (Adapter
->NdisMiniportBlock
.MediaType
)
647 case NdisMedium802_3
:
648 Length
= ETH_LENGTH_OF_ADDRESS
;
649 /* Destination address is the first field */
653 NDIS_DbgPrint(MIN_TRACE
, ("Adapter has unsupported media type (0x%X).\n", Adapter
->NdisMiniportBlock
.MediaType
));
657 if (BufferLength
< Length
)
659 NDIS_DbgPrint(MIN_TRACE
, ("Buffer is too small.\n"));
663 Start1
= (PUCHAR
)&Adapter
->Address
;
664 NDIS_DbgPrint(MAX_TRACE
, ("packet address: %x:%x:%x:%x:%x:%x adapter address: %x:%x:%x:%x:%x:%x\n",
665 *((char *)Start1
), *(((char *)Start1
)+1), *(((char *)Start1
)+2), *(((char *)Start1
)+3), *(((char *)Start1
)+4), *(((char *)Start1
)+5),
666 *((char *)Start2
), *(((char *)Start2
)+1), *(((char *)Start2
)+2), *(((char *)Start2
)+3), *(((char *)Start2
)+4), *(((char *)Start2
)+5)));
668 return (RtlCompareMemory((PVOID
)Start1
, (PVOID
)Start2
, Length
) == Length
);
674 PNDIS_STRING AdapterName
)
676 * FUNCTION: Finds an adapter object by name
678 * AdapterName = Pointer to name of adapter
680 * Pointer to logical adapter object, or NULL if none was found.
681 * If found, the adapter is referenced for the caller. The caller
682 * is responsible for dereferencing after use
686 PLIST_ENTRY CurrentEntry
;
687 PLOGICAL_ADAPTER Adapter
= 0;
691 NDIS_DbgPrint(DEBUG_MINIPORT
, ("Called.\n"));
693 if(IsListEmpty(&AdapterListHead
))
695 NDIS_DbgPrint(MIN_TRACE
, ("No registered miniports for protocol to bind to\n"));
699 NDIS_DbgPrint(DEBUG_MINIPORT
, ("AdapterName = %wZ\n", AdapterName
));
701 KeAcquireSpinLock(&AdapterListLock
, &OldIrql
);
703 CurrentEntry
= AdapterListHead
.Flink
;
705 while (CurrentEntry
!= &AdapterListHead
)
707 Adapter
= CONTAINING_RECORD(CurrentEntry
, LOGICAL_ADAPTER
, ListEntry
);
711 NDIS_DbgPrint(DEBUG_MINIPORT
, ("Examining adapter 0x%lx\n", Adapter
));
713 /* We're technically not allowed to call this above PASSIVE_LEVEL, but it doesn't break
714 * right now and I'd rather use a working API than reimplement it here */
715 if (RtlCompareUnicodeString(AdapterName
, &Adapter
->NdisMiniportBlock
.MiniportName
, TRUE
) == 0)
721 CurrentEntry
= CurrentEntry
->Flink
;
724 KeReleaseSpinLock(&AdapterListLock
, OldIrql
);
728 NDIS_DbgPrint(DEBUG_MINIPORT
, ("Leaving. Adapter found at 0x%x\n", Adapter
));
732 NDIS_DbgPrint(MIN_TRACE
, ("Leaving (adapter not found for %wZ).\n", AdapterName
));
740 PLOGICAL_ADAPTER Adapter
,
746 NDIS_STATUS NdisStatus
;
747 PNDIS_REQUEST NdisRequest
;
749 NDIS_DbgPrint(DEBUG_MINIPORT
, ("Called.\n"));
751 NdisRequest
= ExAllocatePool(NonPagedPool
, sizeof(NDIS_REQUEST
));
753 NDIS_DbgPrint(MIN_TRACE
, ("Insufficient resources\n"));
754 return NDIS_STATUS_RESOURCES
;
757 RtlZeroMemory(NdisRequest
, sizeof(NDIS_REQUEST
));
759 NdisRequest
->RequestType
= NdisRequestSetInformation
;
760 NdisRequest
->DATA
.SET_INFORMATION
.Oid
= Oid
;
761 NdisRequest
->DATA
.SET_INFORMATION
.InformationBuffer
= Buffer
;
762 NdisRequest
->DATA
.SET_INFORMATION
.InformationBufferLength
= Size
;
764 NdisStatus
= MiniDoRequest(Adapter
, NdisRequest
);
766 /* FIXME: Wait in pending case! */
768 ASSERT(NdisStatus
!= NDIS_STATUS_PENDING
);
770 *BytesRead
= NdisRequest
->DATA
.SET_INFORMATION
.BytesRead
;
772 ExFreePool(NdisRequest
);
778 MiniQueryInformation(
779 PLOGICAL_ADAPTER Adapter
,
785 * FUNCTION: Queries a logical adapter for properties
787 * Adapter = Pointer to the logical adapter object to query
788 * Oid = Specifies the Object ID to query for
789 * Size = Size of the passed buffer
790 * Buffer = Buffer for the output
791 * BytesWritten = Address of buffer to place number of bytes written
793 * Status of operation
796 NDIS_STATUS NdisStatus
;
797 PNDIS_REQUEST NdisRequest
;
799 NDIS_DbgPrint(DEBUG_MINIPORT
, ("Called.\n"));
801 NdisRequest
= ExAllocatePool(NonPagedPool
, sizeof(NDIS_REQUEST
));
803 NDIS_DbgPrint(MIN_TRACE
, ("Insufficient resources\n"));
804 return NDIS_STATUS_RESOURCES
;
807 RtlZeroMemory(NdisRequest
, sizeof(NDIS_REQUEST
));
809 NdisRequest
->RequestType
= NdisRequestQueryInformation
;
810 NdisRequest
->DATA
.QUERY_INFORMATION
.Oid
= Oid
;
811 NdisRequest
->DATA
.QUERY_INFORMATION
.InformationBuffer
= Buffer
;
812 NdisRequest
->DATA
.QUERY_INFORMATION
.InformationBufferLength
= Size
;
814 NdisStatus
= MiniDoRequest(Adapter
, NdisRequest
);
816 /* FIXME: Wait in pending case! */
818 ASSERT(NdisStatus
!= NDIS_STATUS_PENDING
);
820 *BytesWritten
= NdisRequest
->DATA
.QUERY_INFORMATION
.BytesWritten
;
822 ExFreePool(NdisRequest
);
828 MiniCheckForHang( PLOGICAL_ADAPTER Adapter
)
830 * FUNCTION: Checks to see if the miniport is hung
832 * Adapter = Pointer to the logical adapter object
834 * TRUE if the miniport is hung
835 * FALSE if the miniport is not hung
841 KeRaiseIrql(DISPATCH_LEVEL
, &OldIrql
);
842 if (Adapter
->NdisMiniportBlock
.DriverHandle
->MiniportCharacteristics
.CheckForHangHandler
)
843 Ret
= (*Adapter
->NdisMiniportBlock
.DriverHandle
->MiniportCharacteristics
.CheckForHangHandler
)(
844 Adapter
->NdisMiniportBlock
.MiniportAdapterContext
);
845 KeLowerIrql(OldIrql
);
851 MiniDoAddressingReset(PLOGICAL_ADAPTER Adapter
)
855 MiniSetInformation(Adapter
,
856 OID_GEN_CURRENT_LOOKAHEAD
,
858 &Adapter
->NdisMiniportBlock
.CurrentLookahead
,
861 /* FIXME: Set more stuff */
866 PLOGICAL_ADAPTER Adapter
)
868 * FUNCTION: Resets the miniport
870 * Adapter = Pointer to the logical adapter object
872 * Status of the operation
877 BOOLEAN AddressingReset
= TRUE
;
879 if (MiniIsBusy(Adapter
, NdisWorkItemResetRequested
)) {
880 MiniQueueWorkItem(Adapter
, NdisWorkItemResetRequested
, NULL
, FALSE
);
881 return NDIS_STATUS_PENDING
;
884 NdisMIndicateStatus(Adapter
, NDIS_STATUS_RESET_START
, NULL
, 0);
885 NdisMIndicateStatusComplete(Adapter
);
887 KeRaiseIrql(DISPATCH_LEVEL
, &OldIrql
);
888 Status
= (*Adapter
->NdisMiniportBlock
.DriverHandle
->MiniportCharacteristics
.ResetHandler
)(
889 Adapter
->NdisMiniportBlock
.MiniportAdapterContext
,
892 KeAcquireSpinLockAtDpcLevel(&Adapter
->NdisMiniportBlock
.Lock
);
893 Adapter
->NdisMiniportBlock
.ResetStatus
= Status
;
894 KeReleaseSpinLockFromDpcLevel(&Adapter
->NdisMiniportBlock
.Lock
);
896 KeLowerIrql(OldIrql
);
898 if (Status
!= NDIS_STATUS_PENDING
) {
900 MiniDoAddressingReset(Adapter
);
902 NdisMIndicateStatus(Adapter
, NDIS_STATUS_RESET_END
, NULL
, 0);
903 NdisMIndicateStatusComplete(Adapter
);
912 PVOID DeferredContext
,
913 PVOID SystemArgument1
,
914 PVOID SystemArgument2
)
916 PLOGICAL_ADAPTER Adapter
= DeferredContext
;
918 if (MiniCheckForHang(Adapter
)) {
919 NDIS_DbgPrint(MIN_TRACE
, ("Miniport detected adapter hang\n"));
928 PLOGICAL_ADAPTER Adapter
,
929 NDIS_WORK_ITEM_TYPE WorkItemType
,
930 PVOID WorkItemContext
,
933 * FUNCTION: Queues a work item for execution at a later time
935 * Adapter = Pointer to the logical adapter object to queue work item on
936 * WorkItemType = Type of work item to queue
937 * WorkItemContext = Pointer to context information for work item
939 * Status of operation
942 PNDIS_MINIPORT_WORK_ITEM MiniportWorkItem
;
943 PIO_WORKITEM IoWorkItem
;
946 NDIS_DbgPrint(MAX_TRACE
, ("Called.\n"));
950 KeAcquireSpinLock(&Adapter
->NdisMiniportBlock
.Lock
, &OldIrql
);
953 if (WorkItemType
== NdisWorkItemSend
)
955 NDIS_DbgPrint(MIN_TRACE
, ("Requeuing failed packet (%x).\n", WorkItemContext
));
956 Adapter
->NdisMiniportBlock
.FirstPendingPacket
= WorkItemContext
;
960 //This should never happen
966 MiniportWorkItem
= ExAllocatePool(NonPagedPool
, sizeof(NDIS_MINIPORT_WORK_ITEM
));
967 if (!MiniportWorkItem
)
969 KeReleaseSpinLock(&Adapter
->NdisMiniportBlock
.Lock
, OldIrql
);
970 NDIS_DbgPrint(MIN_TRACE
, ("Insufficient resources.\n"));
974 MiniportWorkItem
->WorkItemType
= WorkItemType
;
975 MiniportWorkItem
->WorkItemContext
= WorkItemContext
;
977 /* safe due to adapter lock held */
978 MiniportWorkItem
->Link
.Next
= NULL
;
979 if (!Adapter
->WorkQueueHead
)
981 Adapter
->WorkQueueHead
= MiniportWorkItem
;
982 Adapter
->WorkQueueTail
= MiniportWorkItem
;
986 Adapter
->WorkQueueTail
->Link
.Next
= (PSINGLE_LIST_ENTRY
)MiniportWorkItem
;
987 Adapter
->WorkQueueTail
= MiniportWorkItem
;
991 IoWorkItem
= IoAllocateWorkItem(Adapter
->NdisMiniportBlock
.DeviceObject
);
993 IoQueueWorkItem(IoWorkItem
, MiniportWorker
, DelayedWorkQueue
, IoWorkItem
);
995 KeReleaseSpinLock(&Adapter
->NdisMiniportBlock
.Lock
, OldIrql
);
1001 MiniDequeueWorkItem(
1002 PLOGICAL_ADAPTER Adapter
,
1003 NDIS_WORK_ITEM_TYPE
*WorkItemType
,
1004 PVOID
*WorkItemContext
)
1006 * FUNCTION: Dequeues a work item from the work queue of a logical adapter
1008 * Adapter = Pointer to the logical adapter object to dequeue work item from
1009 * AdapterBinding = Address of buffer for adapter binding for this request
1010 * WorkItemType = Address of buffer for work item type
1011 * WorkItemContext = Address of buffer for pointer to context information
1013 * Adapter lock must be held when called
1015 * Status of operation
1018 PNDIS_MINIPORT_WORK_ITEM MiniportWorkItem
;
1019 PNDIS_PACKET Packet
;
1021 NDIS_DbgPrint(MAX_TRACE
, ("Called.\n"));
1023 MiniportWorkItem
= Adapter
->WorkQueueHead
;
1025 if ((Packet
= Adapter
->NdisMiniportBlock
.FirstPendingPacket
))
1027 Adapter
->NdisMiniportBlock
.FirstPendingPacket
= NULL
;
1029 *WorkItemType
= NdisWorkItemSend
;
1030 *WorkItemContext
= Packet
;
1032 return NDIS_STATUS_SUCCESS
;
1034 else if (MiniportWorkItem
)
1036 /* safe due to adapter lock held */
1037 Adapter
->WorkQueueHead
= (PNDIS_MINIPORT_WORK_ITEM
)MiniportWorkItem
->Link
.Next
;
1039 if (MiniportWorkItem
== Adapter
->WorkQueueTail
)
1040 Adapter
->WorkQueueTail
= NULL
;
1042 *WorkItemType
= MiniportWorkItem
->WorkItemType
;
1043 *WorkItemContext
= MiniportWorkItem
->WorkItemContext
;
1045 ExFreePool(MiniportWorkItem
);
1047 return NDIS_STATUS_SUCCESS
;
1051 NDIS_DbgPrint(MIN_TRACE
, ("No work item to dequeue\n"));
1053 return NDIS_STATUS_FAILURE
;
1060 PLOGICAL_ADAPTER Adapter
,
1061 PNDIS_REQUEST NdisRequest
)
1063 * FUNCTION: Sends a request to a miniport
1065 * AdapterBinding = Pointer to binding used in the request
1066 * NdisRequest = Pointer to NDIS request structure describing request
1068 * Status of operation
1073 NDIS_DbgPrint(DEBUG_MINIPORT
, ("Called.\n"));
1075 KeRaiseIrql(DISPATCH_LEVEL
, &OldIrql
);
1077 KeAcquireSpinLockAtDpcLevel(&Adapter
->NdisMiniportBlock
.Lock
);
1078 Adapter
->NdisMiniportBlock
.PendingRequest
= NdisRequest
;
1079 KeReleaseSpinLockFromDpcLevel(&Adapter
->NdisMiniportBlock
.Lock
);
1081 if (!Adapter
->NdisMiniportBlock
.DriverHandle
->MiniportCharacteristics
.CoRequestHandler
)
1083 switch (NdisRequest
->RequestType
)
1085 case NdisRequestQueryInformation
:
1086 Status
= (*Adapter
->NdisMiniportBlock
.DriverHandle
->MiniportCharacteristics
.QueryInformationHandler
)(
1087 Adapter
->NdisMiniportBlock
.MiniportAdapterContext
,
1088 NdisRequest
->DATA
.QUERY_INFORMATION
.Oid
,
1089 NdisRequest
->DATA
.QUERY_INFORMATION
.InformationBuffer
,
1090 NdisRequest
->DATA
.QUERY_INFORMATION
.InformationBufferLength
,
1091 (PULONG
)&NdisRequest
->DATA
.QUERY_INFORMATION
.BytesWritten
,
1092 (PULONG
)&NdisRequest
->DATA
.QUERY_INFORMATION
.BytesNeeded
);
1095 case NdisRequestSetInformation
:
1096 Status
= (*Adapter
->NdisMiniportBlock
.DriverHandle
->MiniportCharacteristics
.SetInformationHandler
)(
1097 Adapter
->NdisMiniportBlock
.MiniportAdapterContext
,
1098 NdisRequest
->DATA
.SET_INFORMATION
.Oid
,
1099 NdisRequest
->DATA
.SET_INFORMATION
.InformationBuffer
,
1100 NdisRequest
->DATA
.SET_INFORMATION
.InformationBufferLength
,
1101 (PULONG
)&NdisRequest
->DATA
.SET_INFORMATION
.BytesRead
,
1102 (PULONG
)&NdisRequest
->DATA
.SET_INFORMATION
.BytesNeeded
);
1106 NDIS_DbgPrint(MIN_TRACE
, ("Bad request type\n"));
1107 Status
= NDIS_STATUS_FAILURE
;
1112 Status
= (*Adapter
->NdisMiniportBlock
.DriverHandle
->MiniportCharacteristics
.CoRequestHandler
)(
1113 Adapter
->NdisMiniportBlock
.MiniportAdapterContext
,
1118 if (Status
!= NDIS_STATUS_PENDING
) {
1119 KeAcquireSpinLockAtDpcLevel(&Adapter
->NdisMiniportBlock
.Lock
);
1120 Adapter
->NdisMiniportBlock
.PendingRequest
= NULL
;
1121 KeReleaseSpinLockFromDpcLevel(&Adapter
->NdisMiniportBlock
.Lock
);
1124 KeLowerIrql(OldIrql
);
1132 #undef NdisMSetInformationComplete
1135 NdisMSetInformationComplete(
1136 IN NDIS_HANDLE MiniportAdapterHandle
,
1137 IN NDIS_STATUS Status
)
1139 PLOGICAL_ADAPTER Adapter
=
1140 (PLOGICAL_ADAPTER
)MiniportAdapterHandle
;
1143 KeRaiseIrql(DISPATCH_LEVEL
, &OldIrql
);
1144 if (Adapter
->NdisMiniportBlock
.SetCompleteHandler
)
1145 (Adapter
->NdisMiniportBlock
.SetCompleteHandler
)(MiniportAdapterHandle
, Status
);
1146 KeLowerIrql(OldIrql
);
1153 #undef NdisMQueryInformationComplete
1156 NdisMQueryInformationComplete(
1157 IN NDIS_HANDLE MiniportAdapterHandle
,
1158 IN NDIS_STATUS Status
)
1160 PLOGICAL_ADAPTER Adapter
=
1161 (PLOGICAL_ADAPTER
)MiniportAdapterHandle
;
1164 KeRaiseIrql(DISPATCH_LEVEL
, &OldIrql
);
1165 if( Adapter
->NdisMiniportBlock
.QueryCompleteHandler
)
1166 (Adapter
->NdisMiniportBlock
.QueryCompleteHandler
)(MiniportAdapterHandle
, Status
);
1167 KeLowerIrql(OldIrql
);
1172 MiniportWorker(IN PDEVICE_OBJECT DeviceObject
, IN PVOID Context
)
1174 PLOGICAL_ADAPTER Adapter
= DeviceObject
->DeviceExtension
;
1175 KIRQL OldIrql
, RaiseOldIrql
;
1176 NDIS_STATUS NdisStatus
;
1177 PVOID WorkItemContext
;
1178 NDIS_WORK_ITEM_TYPE WorkItemType
;
1179 BOOLEAN AddressingReset
;
1181 IoFreeWorkItem((PIO_WORKITEM
)Context
);
1183 KeAcquireSpinLock(&Adapter
->NdisMiniportBlock
.Lock
, &OldIrql
);
1187 (Adapter
, &WorkItemType
, &WorkItemContext
);
1189 KeReleaseSpinLock(&Adapter
->NdisMiniportBlock
.Lock
, OldIrql
);
1191 if (NdisStatus
== NDIS_STATUS_SUCCESS
)
1193 switch (WorkItemType
)
1195 case NdisWorkItemSend
:
1197 * called by ProSend when protocols want to send packets to the miniport
1200 if(Adapter
->NdisMiniportBlock
.DriverHandle
->MiniportCharacteristics
.SendPacketsHandler
)
1202 if(Adapter
->NdisMiniportBlock
.Flags
& NDIS_ATTRIBUTE_DESERIALIZE
)
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);
1207 NdisStatus
= NDIS_STATUS_PENDING
;
1211 /* SendPackets is called at DISPATCH_LEVEL for all serialized miniports */
1212 KeRaiseIrql(DISPATCH_LEVEL
, &RaiseOldIrql
);
1214 NDIS_DbgPrint(MAX_TRACE
, ("Calling miniport's SendPackets handler\n"));
1215 (*Adapter
->NdisMiniportBlock
.DriverHandle
->MiniportCharacteristics
.SendPacketsHandler
)(
1216 Adapter
->NdisMiniportBlock
.MiniportAdapterContext
, (PPNDIS_PACKET
)&WorkItemContext
, 1);
1218 KeLowerIrql(RaiseOldIrql
);
1220 NdisStatus
= NDIS_GET_PACKET_STATUS((PNDIS_PACKET
)WorkItemContext
);
1221 if( NdisStatus
== NDIS_STATUS_RESOURCES
) {
1222 MiniQueueWorkItem(Adapter
, WorkItemType
, WorkItemContext
, TRUE
);
1229 if(Adapter
->NdisMiniportBlock
.Flags
& NDIS_ATTRIBUTE_DESERIALIZE
)
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"));
1239 /* Send is called at DISPATCH_LEVEL for all serialized miniports */
1240 KeRaiseIrql(DISPATCH_LEVEL
, &RaiseOldIrql
);
1241 NDIS_DbgPrint(MAX_TRACE
, ("Calling miniport's Send handler\n"));
1242 NdisStatus
= (*Adapter
->NdisMiniportBlock
.DriverHandle
->MiniportCharacteristics
.SendHandler
)(
1243 Adapter
->NdisMiniportBlock
.MiniportAdapterContext
, (PNDIS_PACKET
)WorkItemContext
,
1244 ((PNDIS_PACKET
)WorkItemContext
)->Private
.Flags
);
1245 NDIS_DbgPrint(MAX_TRACE
, ("back from miniport's send handler\n"));
1246 KeLowerIrql(RaiseOldIrql
);
1247 if( NdisStatus
== NDIS_STATUS_RESOURCES
) {
1248 MiniQueueWorkItem(Adapter
, WorkItemType
, WorkItemContext
, TRUE
);
1254 if( NdisStatus
!= NDIS_STATUS_PENDING
) {
1256 ( Adapter
, (PNDIS_PACKET
)WorkItemContext
, NdisStatus
);
1260 case NdisWorkItemSendLoopback
:
1262 * called by ProSend when protocols want to send loopback packets
1264 /* XXX atm ProIndicatePacket sends a packet up via the loopback adapter only */
1265 NdisStatus
= ProIndicatePacket(Adapter
, (PNDIS_PACKET
)WorkItemContext
);
1267 if( NdisStatus
!= NDIS_STATUS_PENDING
)
1268 MiniSendComplete((NDIS_HANDLE
)Adapter
, (PNDIS_PACKET
)WorkItemContext
, NdisStatus
);
1271 case NdisWorkItemReturnPackets
:
1274 case NdisWorkItemResetRequested
:
1275 NdisMIndicateStatus(Adapter
, NDIS_STATUS_RESET_START
, NULL
, 0);
1276 NdisMIndicateStatusComplete(Adapter
);
1278 KeRaiseIrql(DISPATCH_LEVEL
, &OldIrql
);
1279 NdisStatus
= (*Adapter
->NdisMiniportBlock
.DriverHandle
->MiniportCharacteristics
.ResetHandler
)(
1280 Adapter
->NdisMiniportBlock
.MiniportAdapterContext
,
1283 KeAcquireSpinLockAtDpcLevel(&Adapter
->NdisMiniportBlock
.Lock
);
1284 Adapter
->NdisMiniportBlock
.ResetStatus
= NdisStatus
;
1285 KeReleaseSpinLockFromDpcLevel(&Adapter
->NdisMiniportBlock
.Lock
);
1287 KeLowerIrql(OldIrql
);
1289 if (NdisStatus
!= NDIS_STATUS_PENDING
)
1290 MiniResetComplete(Adapter
, NdisStatus
, AddressingReset
);
1293 case NdisWorkItemResetInProgress
:
1296 case NdisWorkItemMiniportCallback
:
1299 case NdisWorkItemRequest
:
1300 NdisStatus
= MiniDoRequest(Adapter
, (PNDIS_REQUEST
)WorkItemContext
);
1302 if (NdisStatus
== NDIS_STATUS_PENDING
)
1305 switch (((PNDIS_REQUEST
)WorkItemContext
)->RequestType
)
1307 case NdisRequestQueryInformation
:
1308 NdisMQueryInformationComplete((NDIS_HANDLE
)Adapter
, NdisStatus
);
1311 case NdisRequestSetInformation
:
1312 NdisMSetInformationComplete((NDIS_HANDLE
)Adapter
, NdisStatus
);
1316 NDIS_DbgPrint(MIN_TRACE
, ("Unknown NDIS request type.\n"));
1322 NDIS_DbgPrint(MIN_TRACE
, ("Unknown NDIS work item type (%d).\n", WorkItemType
));
1333 IN NDIS_HANDLE MiniportHandle
,
1334 IN NDIS_STATUS GeneralStatus
,
1335 IN PVOID StatusBuffer
,
1336 IN UINT StatusBufferSize
)
1338 PLOGICAL_ADAPTER Adapter
= MiniportHandle
;
1339 PLIST_ENTRY CurrentEntry
;
1340 PADAPTER_BINDING AdapterBinding
;
1343 KeAcquireSpinLock(&Adapter
->NdisMiniportBlock
.Lock
, &OldIrql
);
1345 CurrentEntry
= Adapter
->ProtocolListHead
.Flink
;
1347 while (CurrentEntry
!= &Adapter
->ProtocolListHead
)
1349 AdapterBinding
= CONTAINING_RECORD(CurrentEntry
, ADAPTER_BINDING
, AdapterListEntry
);
1351 (*AdapterBinding
->ProtocolBinding
->Chars
.StatusHandler
)(
1352 AdapterBinding
->NdisOpenBlock
.ProtocolBindingContext
,
1357 CurrentEntry
= CurrentEntry
->Flink
;
1360 KeReleaseSpinLock(&Adapter
->NdisMiniportBlock
.Lock
, OldIrql
);
1367 IN NDIS_HANDLE MiniportAdapterHandle
)
1369 PLOGICAL_ADAPTER Adapter
= MiniportAdapterHandle
;
1370 PLIST_ENTRY CurrentEntry
;
1371 PADAPTER_BINDING AdapterBinding
;
1374 KeAcquireSpinLock(&Adapter
->NdisMiniportBlock
.Lock
, &OldIrql
);
1376 CurrentEntry
= Adapter
->ProtocolListHead
.Flink
;
1378 while (CurrentEntry
!= &Adapter
->ProtocolListHead
)
1380 AdapterBinding
= CONTAINING_RECORD(CurrentEntry
, ADAPTER_BINDING
, AdapterListEntry
);
1382 (*AdapterBinding
->ProtocolBinding
->Chars
.StatusCompleteHandler
)(
1383 AdapterBinding
->NdisOpenBlock
.ProtocolBindingContext
);
1385 CurrentEntry
= CurrentEntry
->Flink
;
1388 KeReleaseSpinLock(&Adapter
->NdisMiniportBlock
.Lock
, OldIrql
);
1398 IN NDIS_HANDLE LogHandle
)
1400 PNDIS_LOG Log
= (PNDIS_LOG
)LogHandle
;
1401 PNDIS_MINIPORT_BLOCK Miniport
= Log
->Miniport
;
1404 NDIS_DbgPrint(MAX_TRACE
, ("called: LogHandle 0x%x\n", LogHandle
));
1406 KeAcquireSpinLock(&(Miniport
)->Lock
, &OldIrql
);
1407 Miniport
->Log
= NULL
;
1408 KeReleaseSpinLock(&(Miniport
)->Lock
, OldIrql
);
1419 IN NDIS_HANDLE MiniportAdapterHandle
,
1421 OUT PNDIS_HANDLE LogHandle
)
1423 PLOGICAL_ADAPTER Adapter
= MiniportAdapterHandle
;
1427 NDIS_DbgPrint(MAX_TRACE
, ("called: MiniportAdapterHandle 0x%x, Size %ld\n", MiniportAdapterHandle
, Size
));
1429 KeAcquireSpinLock(&Adapter
->NdisMiniportBlock
.Lock
, &OldIrql
);
1431 if (Adapter
->NdisMiniportBlock
.Log
)
1434 return NDIS_STATUS_FAILURE
;
1437 Log
= ExAllocatePool(NonPagedPool
, Size
+ sizeof(NDIS_LOG
));
1441 return NDIS_STATUS_RESOURCES
;
1444 Adapter
->NdisMiniportBlock
.Log
= Log
;
1446 KeInitializeSpinLock(&Log
->LogLock
);
1448 Log
->Miniport
= &Adapter
->NdisMiniportBlock
;
1449 Log
->TotalSize
= Size
;
1450 Log
->CurrentSize
= 0;
1457 KeReleaseSpinLock(&Adapter
->NdisMiniportBlock
.Lock
, OldIrql
);
1459 return NDIS_STATUS_SUCCESS
;
1467 NdisMDeregisterAdapterShutdownHandler(
1468 IN NDIS_HANDLE MiniportHandle
)
1470 * FUNCTION: de-registers a shutdown handler
1471 * ARGUMENTS: MiniportHandle: Handle passed into MiniportInitialize
1474 PLOGICAL_ADAPTER Adapter
= (PLOGICAL_ADAPTER
)MiniportHandle
;
1476 NDIS_DbgPrint(DEBUG_MINIPORT
, ("Called.\n"));
1478 if(Adapter
->BugcheckContext
->ShutdownHandler
) {
1479 KeDeregisterBugCheckCallback(Adapter
->BugcheckContext
->CallbackRecord
);
1480 IoUnregisterShutdownNotification(Adapter
->NdisMiniportBlock
.DeviceObject
);
1490 IN NDIS_HANDLE LogHandle
)
1492 PNDIS_LOG Log
= (PNDIS_LOG
) LogHandle
;
1495 NDIS_DbgPrint(MAX_TRACE
, ("called: LogHandle 0x%x\n", LogHandle
));
1498 KeAcquireSpinLock(&Log
->LogLock
, &OldIrql
);
1500 /* Set buffers size */
1501 Log
->CurrentSize
= 0;
1506 KeReleaseSpinLock(&Log
->LogLock
, OldIrql
);
1512 #undef NdisMIndicateStatus
1515 NdisMIndicateStatus(
1516 IN NDIS_HANDLE MiniportAdapterHandle
,
1517 IN NDIS_STATUS GeneralStatus
,
1518 IN PVOID StatusBuffer
,
1519 IN UINT StatusBufferSize
)
1521 MiniStatus(MiniportAdapterHandle
, GeneralStatus
, StatusBuffer
, StatusBufferSize
);
1527 #undef NdisMIndicateStatusComplete
1530 NdisMIndicateStatusComplete(
1531 IN NDIS_HANDLE MiniportAdapterHandle
)
1533 MiniStatusComplete(MiniportAdapterHandle
);
1542 NdisInitializeWrapper(
1543 OUT PNDIS_HANDLE NdisWrapperHandle
,
1544 IN PVOID SystemSpecific1
,
1545 IN PVOID SystemSpecific2
,
1546 IN PVOID SystemSpecific3
)
1548 * FUNCTION: Notifies the NDIS library that a new miniport is initializing
1550 * NdisWrapperHandle = Address of buffer to place NDIS wrapper handle
1551 * SystemSpecific1 = Pointer to the driver's driver object
1552 * SystemSpecific2 = Pointer to the driver's registry path
1553 * SystemSpecific3 = Always NULL
1555 * - SystemSpecific2 goes invalid so we copy it
1558 PNDIS_M_DRIVER_BLOCK Miniport
;
1559 PUNICODE_STRING RegistryPath
;
1560 WCHAR
*RegistryBuffer
;
1562 NDIS_DbgPrint(MAX_TRACE
, ("Called.\n"));
1564 ASSERT(NdisWrapperHandle
);
1566 *NdisWrapperHandle
= NULL
;
1568 #if BREAK_ON_MINIPORT_INIT
1572 Miniport
= ExAllocatePool(NonPagedPool
, sizeof(NDIS_M_DRIVER_BLOCK
));
1576 NDIS_DbgPrint(MIN_TRACE
, ("Insufficient resources.\n"));
1580 RtlZeroMemory(Miniport
, sizeof(NDIS_M_DRIVER_BLOCK
));
1582 KeInitializeSpinLock(&Miniport
->Lock
);
1584 Miniport
->DriverObject
= (PDRIVER_OBJECT
)SystemSpecific1
;
1586 /* set the miniport's driver registry path */
1587 RegistryPath
= ExAllocatePool(PagedPool
, sizeof(UNICODE_STRING
));
1590 ExFreePool(Miniport
);
1591 NDIS_DbgPrint(MIN_TRACE
, ("Insufficient resources.\n"));
1595 RegistryPath
->Length
= ((PUNICODE_STRING
)SystemSpecific2
)->Length
;
1596 RegistryPath
->MaximumLength
= RegistryPath
->Length
+ sizeof(WCHAR
); /* room for 0-term */
1598 RegistryBuffer
= ExAllocatePool(PagedPool
, RegistryPath
->MaximumLength
);
1601 NDIS_DbgPrint(MIN_TRACE
, ("Insufficient resources.\n"));
1602 ExFreePool(Miniport
);
1603 ExFreePool(RegistryPath
);
1607 RtlCopyMemory(RegistryBuffer
, ((PUNICODE_STRING
)SystemSpecific2
)->Buffer
, RegistryPath
->Length
);
1608 RegistryBuffer
[RegistryPath
->Length
/sizeof(WCHAR
)] = 0;
1610 RegistryPath
->Buffer
= RegistryBuffer
;
1611 Miniport
->RegistryPath
= RegistryPath
;
1613 InitializeListHead(&Miniport
->DeviceList
);
1615 /* Put miniport in global miniport list */
1616 ExInterlockedInsertTailList(&MiniportListHead
, &Miniport
->ListEntry
, &MiniportListLock
);
1618 *NdisWrapperHandle
= Miniport
;
1622 VOID NTAPI
NdisIBugcheckCallback(
1626 * FUNCTION: Internal callback for handling bugchecks - calls adapter's shutdown handler
1628 * Buffer: Pointer to a bugcheck callback context
1632 PMINIPORT_BUGCHECK_CONTEXT Context
= (PMINIPORT_BUGCHECK_CONTEXT
)Buffer
;
1633 ADAPTER_SHUTDOWN_HANDLER sh
= (ADAPTER_SHUTDOWN_HANDLER
)Context
->ShutdownHandler
;
1635 NDIS_DbgPrint(DEBUG_MINIPORT
, ("Called.\n"));
1638 sh(Context
->DriverContext
);
1647 NdisMRegisterAdapterShutdownHandler(
1648 IN NDIS_HANDLE MiniportHandle
,
1649 IN PVOID ShutdownContext
,
1650 IN ADAPTER_SHUTDOWN_HANDLER ShutdownHandler
)
1652 * FUNCTION: Register a shutdown handler for an adapter
1654 * MiniportHandle: Handle originally passed into MiniportInitialize
1655 * ShutdownContext: Pre-initialized bugcheck context
1656 * ShutdownHandler: Function to call to handle the bugcheck
1658 * - I'm not sure about ShutdownContext
1661 PLOGICAL_ADAPTER Adapter
= (PLOGICAL_ADAPTER
)MiniportHandle
;
1662 PMINIPORT_BUGCHECK_CONTEXT BugcheckContext
;
1664 NDIS_DbgPrint(DEBUG_MINIPORT
, ("Called.\n"));
1666 BugcheckContext
= ExAllocatePool(NonPagedPool
, sizeof(MINIPORT_BUGCHECK_CONTEXT
));
1667 if(!BugcheckContext
)
1669 NDIS_DbgPrint(MIN_TRACE
, ("Insufficient resources.\n"));
1673 BugcheckContext
->ShutdownHandler
= ShutdownHandler
;
1674 BugcheckContext
->DriverContext
= ShutdownContext
;
1676 BugcheckContext
->CallbackRecord
= ExAllocatePool(NonPagedPool
, sizeof(KBUGCHECK_CALLBACK_RECORD
));
1677 if (!BugcheckContext
->CallbackRecord
) {
1678 ExFreePool(BugcheckContext
);
1682 Adapter
->BugcheckContext
= BugcheckContext
;
1684 KeInitializeCallbackRecord(BugcheckContext
->CallbackRecord
);
1686 KeRegisterBugCheckCallback(BugcheckContext
->CallbackRecord
, NdisIBugcheckCallback
,
1687 BugcheckContext
, sizeof(*BugcheckContext
), (PUCHAR
)"Ndis Miniport");
1689 IoRegisterShutdownNotification(Adapter
->NdisMiniportBlock
.DeviceObject
);
1695 PLOGICAL_ADAPTER Adapter
,
1696 NDIS_OID AddressOID
)
1698 * FUNCTION: Queries miniport for information
1700 * Adapter = Pointer to logical adapter
1701 * AddressOID = OID to use to query for current address
1703 * Status of operation
1707 NDIS_STATUS NdisStatus
;
1709 NDIS_DbgPrint(MAX_TRACE
, ("Called.\n"));
1711 /* Get MAC options for adapter */
1712 NdisStatus
= MiniQueryInformation(Adapter
, OID_GEN_MAC_OPTIONS
, sizeof(UINT
),
1713 &Adapter
->NdisMiniportBlock
.MacOptions
,
1716 if (NdisStatus
!= NDIS_STATUS_SUCCESS
)
1718 NDIS_DbgPrint(MIN_TRACE
, ("OID_GEN_MAC_OPTIONS failed. NdisStatus (0x%X).\n", NdisStatus
));
1722 NDIS_DbgPrint(DEBUG_MINIPORT
, ("MacOptions (0x%X).\n", Adapter
->NdisMiniportBlock
.MacOptions
));
1724 /* Get current hardware address of adapter */
1725 NdisStatus
= MiniQueryInformation(Adapter
, AddressOID
, Adapter
->AddressLength
,
1726 &Adapter
->Address
, &BytesWritten
);
1728 if (NdisStatus
!= NDIS_STATUS_SUCCESS
)
1730 NDIS_DbgPrint(MIN_TRACE
, ("Address OID (0x%X) failed. NdisStatus (0x%X).\n", AddressOID
, NdisStatus
));
1738 PUCHAR A
= (PUCHAR
)&Adapter
->Address
.Type
.Medium802_3
;
1740 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]));
1744 /* Get maximum lookahead buffer size of adapter */
1745 NdisStatus
= MiniQueryInformation(Adapter
, OID_GEN_MAXIMUM_LOOKAHEAD
, sizeof(ULONG
),
1746 &Adapter
->NdisMiniportBlock
.MaximumLookahead
, &BytesWritten
);
1748 if (NdisStatus
!= NDIS_STATUS_SUCCESS
)
1750 NDIS_DbgPrint(MIN_TRACE
, ("OID_GEN_MAXIMUM_LOOKAHEAD failed. NdisStatus (0x%X).\n", NdisStatus
));
1754 NDIS_DbgPrint(DEBUG_MINIPORT
, ("MaxLookaheadLength (0x%X).\n", Adapter
->NdisMiniportBlock
.MaximumLookahead
));
1756 /* Get current lookahead buffer size of adapter */
1757 NdisStatus
= MiniQueryInformation(Adapter
, OID_GEN_CURRENT_LOOKAHEAD
, sizeof(ULONG
),
1758 &Adapter
->NdisMiniportBlock
.CurrentLookahead
, &BytesWritten
);
1760 if (NdisStatus
!= NDIS_STATUS_SUCCESS
)
1762 NDIS_DbgPrint(MIN_TRACE
, ("OID_GEN_CURRENT_LOOKAHEAD failed. NdisStatus (0x%X).\n", NdisStatus
));
1766 NdisStatus
= MiniQueryInformation(Adapter
, OID_GEN_MAXIMUM_SEND_PACKETS
, sizeof(ULONG
),
1767 &Adapter
->NdisMiniportBlock
.MaxSendPackets
, &BytesWritten
);
1769 if (NdisStatus
!= NDIS_STATUS_SUCCESS
)
1771 NDIS_DbgPrint(MIN_TRACE
, ("OID_GEN_MAXIMUM_SEND_PACKETS failed. NdisStatus (0x%X).\n", NdisStatus
));
1773 /* Set it to 1 if it fails because some drivers don't support this (?)*/
1774 Adapter
->NdisMiniportBlock
.MaxSendPackets
= 1;
1777 NDIS_DbgPrint(DEBUG_MINIPORT
, ("CurLookaheadLength (0x%X).\n", Adapter
->NdisMiniportBlock
.CurrentLookahead
));
1779 return STATUS_SUCCESS
;
1785 NdisIForwardIrpAndWaitCompletionRoutine(
1790 PKEVENT Event
= Context
;
1792 if (Irp
->PendingReturned
)
1793 KeSetEvent(Event
, IO_NO_INCREMENT
, FALSE
);
1795 return STATUS_MORE_PROCESSING_REQUIRED
;
1801 NdisIForwardIrpAndWait(PLOGICAL_ADAPTER Adapter
, PIRP Irp
)
1806 KeInitializeEvent(&Event
, NotificationEvent
, FALSE
);
1807 IoCopyCurrentIrpStackLocationToNext(Irp
);
1808 IoSetCompletionRoutine(Irp
, NdisIForwardIrpAndWaitCompletionRoutine
, &Event
,
1810 Status
= IoCallDriver(Adapter
->NdisMiniportBlock
.NextDeviceObject
, Irp
);
1811 if (Status
== STATUS_PENDING
)
1813 KeWaitForSingleObject(&Event
, Executive
, KernelMode
, FALSE
, NULL
);
1814 Status
= Irp
->IoStatus
.Status
;
1822 IN PDEVICE_OBJECT DeviceObject
,
1825 Irp
->IoStatus
.Status
= STATUS_SUCCESS
;
1826 Irp
->IoStatus
.Information
= 0;
1828 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
1830 return STATUS_SUCCESS
;
1836 NdisIPnPStartDevice(
1837 IN PDEVICE_OBJECT DeviceObject
,
1840 * FUNCTION: Handle the PnP start device event
1842 * DeviceObejct = Functional Device Object
1843 * Irp = IRP_MN_START_DEVICE I/O request packet
1845 * Status of operation
1848 PIO_STACK_LOCATION Stack
= IoGetCurrentIrpStackLocation(Irp
);
1849 PLOGICAL_ADAPTER Adapter
= (PLOGICAL_ADAPTER
)DeviceObject
->DeviceExtension
;
1850 NDIS_WRAPPER_CONTEXT WrapperContext
;
1851 NDIS_STATUS NdisStatus
;
1852 NDIS_STATUS OpenErrorStatus
;
1854 UINT SelectedMediumIndex
= 0;
1855 NDIS_OID AddressOID
;
1856 BOOLEAN Success
= FALSE
;
1857 ULONG ResourceCount
;
1858 ULONG ResourceListSize
;
1859 UNICODE_STRING ParamName
;
1860 PNDIS_CONFIGURATION_PARAMETER ConfigParam
;
1861 NDIS_HANDLE ConfigHandle
;
1863 LARGE_INTEGER Timeout
;
1864 UINT MaxMulticastAddresses
;
1866 PLIST_ENTRY CurrentEntry
;
1867 PPROTOCOL_BINDING ProtocolBinding
;
1870 * Prepare wrapper context used by HW and configuration routines.
1873 NDIS_DbgPrint(DEBUG_MINIPORT
, ("Start Device %wZ\n", &Adapter
->NdisMiniportBlock
.MiniportName
));
1875 NDIS_DbgPrint(MAX_TRACE
, ("Inserting adapter 0x%x into adapter list\n", Adapter
));
1877 /* Put adapter in global adapter list */
1878 ExInterlockedInsertTailList(&AdapterListHead
, &Adapter
->ListEntry
, &AdapterListLock
);
1880 Status
= IoOpenDeviceRegistryKey(
1881 Adapter
->NdisMiniportBlock
.PhysicalDeviceObject
, PLUGPLAY_REGKEY_DRIVER
,
1882 KEY_ALL_ACCESS
, &WrapperContext
.RegistryHandle
);
1883 if (!NT_SUCCESS(Status
))
1885 NDIS_DbgPrint(MIN_TRACE
,("failed to open adapter-specific reg key\n"));
1886 ExInterlockedRemoveEntryList( &Adapter
->ListEntry
, &AdapterListLock
);
1890 NDIS_DbgPrint(MAX_TRACE
, ("opened device reg key\n"));
1892 WrapperContext
.DeviceObject
= Adapter
->NdisMiniportBlock
.DeviceObject
;
1895 * Store the adapter resources used by HW routines such as
1896 * NdisMQueryAdapterResources.
1899 if (Stack
->Parameters
.StartDevice
.AllocatedResources
!= NULL
)
1901 ResourceCount
= Stack
->Parameters
.StartDevice
.AllocatedResources
->List
[0].
1902 PartialResourceList
.Count
;
1904 FIELD_OFFSET(CM_RESOURCE_LIST
, List
[0].PartialResourceList
.
1905 PartialDescriptors
[ResourceCount
]);
1907 Adapter
->NdisMiniportBlock
.AllocatedResources
=
1908 ExAllocatePool(PagedPool
, ResourceListSize
);
1909 if (Adapter
->NdisMiniportBlock
.AllocatedResources
== NULL
)
1911 NDIS_DbgPrint(MIN_TRACE
, ("Insufficient resources\n"));
1912 ExInterlockedRemoveEntryList( &Adapter
->ListEntry
, &AdapterListLock
);
1913 return STATUS_INSUFFICIENT_RESOURCES
;
1916 Adapter
->NdisMiniportBlock
.Resources
=
1917 ExAllocatePool(PagedPool
, ResourceListSize
);
1918 if (!Adapter
->NdisMiniportBlock
.Resources
)
1920 NDIS_DbgPrint(MIN_TRACE
, ("Insufficient resources\n"));
1921 ExFreePool(Adapter
->NdisMiniportBlock
.AllocatedResources
);
1922 ExInterlockedRemoveEntryList(&Adapter
->ListEntry
, &AdapterListLock
);
1923 return STATUS_INSUFFICIENT_RESOURCES
;
1926 RtlCopyMemory(Adapter
->NdisMiniportBlock
.Resources
,
1927 Stack
->Parameters
.StartDevice
.AllocatedResources
,
1930 RtlCopyMemory(Adapter
->NdisMiniportBlock
.AllocatedResources
,
1931 Stack
->Parameters
.StartDevice
.AllocatedResources
,
1935 if (Stack
->Parameters
.StartDevice
.AllocatedResourcesTranslated
!= NULL
)
1937 ResourceCount
= Stack
->Parameters
.StartDevice
.AllocatedResourcesTranslated
->List
[0].
1938 PartialResourceList
.Count
;
1940 FIELD_OFFSET(CM_RESOURCE_LIST
, List
[0].PartialResourceList
.
1941 PartialDescriptors
[ResourceCount
]);
1943 Adapter
->NdisMiniportBlock
.AllocatedResourcesTranslated
=
1944 ExAllocatePool(PagedPool
, ResourceListSize
);
1945 if (Adapter
->NdisMiniportBlock
.AllocatedResourcesTranslated
== NULL
)
1947 NDIS_DbgPrint(MIN_TRACE
, ("Insufficient resources\n"));
1948 ExInterlockedRemoveEntryList( &Adapter
->ListEntry
, &AdapterListLock
);
1949 return STATUS_INSUFFICIENT_RESOURCES
;
1952 RtlCopyMemory(Adapter
->NdisMiniportBlock
.AllocatedResourcesTranslated
,
1953 Stack
->Parameters
.StartDevice
.AllocatedResourcesTranslated
,
1958 * Store the Bus Type, Bus Number and Slot information. It's used by
1959 * the hardware routines then.
1962 NdisOpenConfiguration(&NdisStatus
, &ConfigHandle
, (NDIS_HANDLE
)&WrapperContext
);
1963 if (NdisStatus
!= NDIS_STATUS_SUCCESS
)
1965 NDIS_DbgPrint(MIN_TRACE
, ("Failed to open configuration key\n"));
1966 ExInterlockedRemoveEntryList( &Adapter
->ListEntry
, &AdapterListLock
);
1970 Size
= sizeof(ULONG
);
1971 Status
= IoGetDeviceProperty(Adapter
->NdisMiniportBlock
.PhysicalDeviceObject
,
1972 DevicePropertyLegacyBusType
, Size
,
1973 &Adapter
->NdisMiniportBlock
.BusType
, &Size
);
1974 if (!NT_SUCCESS(Status
) || (INTERFACE_TYPE
)Adapter
->NdisMiniportBlock
.BusType
== InterfaceTypeUndefined
)
1976 NdisInitUnicodeString(&ParamName
, L
"BusType");
1977 NdisReadConfiguration(&NdisStatus
, &ConfigParam
, ConfigHandle
,
1978 &ParamName
, NdisParameterInteger
);
1979 if (NdisStatus
== NDIS_STATUS_SUCCESS
)
1980 Adapter
->NdisMiniportBlock
.BusType
= ConfigParam
->ParameterData
.IntegerData
;
1982 Adapter
->NdisMiniportBlock
.BusType
= Isa
;
1985 Status
= IoGetDeviceProperty(Adapter
->NdisMiniportBlock
.PhysicalDeviceObject
,
1986 DevicePropertyBusNumber
, Size
,
1987 &Adapter
->NdisMiniportBlock
.BusNumber
, &Size
);
1988 if (!NT_SUCCESS(Status
) || Adapter
->NdisMiniportBlock
.BusNumber
== 0xFFFFFFF0)
1990 NdisInitUnicodeString(&ParamName
, L
"BusNumber");
1991 NdisReadConfiguration(&NdisStatus
, &ConfigParam
, ConfigHandle
,
1992 &ParamName
, NdisParameterInteger
);
1993 if (NdisStatus
== NDIS_STATUS_SUCCESS
)
1994 Adapter
->NdisMiniportBlock
.BusNumber
= ConfigParam
->ParameterData
.IntegerData
;
1996 Adapter
->NdisMiniportBlock
.BusNumber
= 0;
1998 WrapperContext
.BusNumber
= Adapter
->NdisMiniportBlock
.BusNumber
;
2000 Status
= IoGetDeviceProperty(Adapter
->NdisMiniportBlock
.PhysicalDeviceObject
,
2001 DevicePropertyAddress
, Size
,
2002 &Adapter
->NdisMiniportBlock
.SlotNumber
, &Size
);
2003 if (!NT_SUCCESS(Status
) || Adapter
->NdisMiniportBlock
.SlotNumber
== (NDIS_INTERFACE_TYPE
)-1)
2005 NdisInitUnicodeString(&ParamName
, L
"SlotNumber");
2006 NdisReadConfiguration(&NdisStatus
, &ConfigParam
, ConfigHandle
,
2007 &ParamName
, NdisParameterInteger
);
2008 if (NdisStatus
== NDIS_STATUS_SUCCESS
)
2009 Adapter
->NdisMiniportBlock
.SlotNumber
= ConfigParam
->ParameterData
.IntegerData
;
2011 Adapter
->NdisMiniportBlock
.SlotNumber
= 0;
2015 /* Convert slotnumber to PCI_SLOT_NUMBER */
2016 ULONG PciSlotNumber
= Adapter
->NdisMiniportBlock
.SlotNumber
;
2017 PCI_SLOT_NUMBER SlotNumber
;
2019 SlotNumber
.u
.AsULONG
= 0;
2020 SlotNumber
.u
.bits
.DeviceNumber
= (PciSlotNumber
>> 16) & 0xFFFF;
2021 SlotNumber
.u
.bits
.FunctionNumber
= PciSlotNumber
& 0xFFFF;
2023 Adapter
->NdisMiniportBlock
.SlotNumber
= SlotNumber
.u
.AsULONG
;
2025 WrapperContext
.SlotNumber
= Adapter
->NdisMiniportBlock
.SlotNumber
;
2027 NdisCloseConfiguration(ConfigHandle
);
2029 /* Set handlers (some NDIS macros require these) */
2030 Adapter
->NdisMiniportBlock
.EthRxCompleteHandler
= EthFilterDprIndicateReceiveComplete
;
2031 Adapter
->NdisMiniportBlock
.EthRxIndicateHandler
= EthFilterDprIndicateReceive
;
2032 Adapter
->NdisMiniportBlock
.SendCompleteHandler
= MiniSendComplete
;
2033 Adapter
->NdisMiniportBlock
.SendResourcesHandler
= MiniSendResourcesAvailable
;
2034 Adapter
->NdisMiniportBlock
.ResetCompleteHandler
= MiniResetComplete
;
2035 Adapter
->NdisMiniportBlock
.TDCompleteHandler
= MiniTransferDataComplete
;
2036 Adapter
->NdisMiniportBlock
.PacketIndicateHandler
= MiniIndicateReceivePacket
;
2037 Adapter
->NdisMiniportBlock
.StatusHandler
= MiniStatus
;
2038 Adapter
->NdisMiniportBlock
.StatusCompleteHandler
= MiniStatusComplete
;
2039 Adapter
->NdisMiniportBlock
.SendPacketsHandler
= ProSendPackets
;
2040 Adapter
->NdisMiniportBlock
.QueryCompleteHandler
= MiniRequestComplete
;
2041 Adapter
->NdisMiniportBlock
.SetCompleteHandler
= MiniRequestComplete
;
2044 * Call MiniportInitialize.
2047 NDIS_DbgPrint(MID_TRACE
, ("calling MiniportInitialize\n"));
2048 NdisStatus
= (*Adapter
->NdisMiniportBlock
.DriverHandle
->MiniportCharacteristics
.InitializeHandler
)(
2049 &OpenErrorStatus
, &SelectedMediumIndex
, &MediaArray
[0],
2050 MEDIA_ARRAY_SIZE
, Adapter
, (NDIS_HANDLE
)&WrapperContext
);
2052 ZwClose(WrapperContext
.RegistryHandle
);
2054 if (NdisStatus
!= NDIS_STATUS_SUCCESS
)
2056 NDIS_DbgPrint(MIN_TRACE
, ("MiniportInitialize() failed for an adapter.\n"));
2057 ExInterlockedRemoveEntryList( &Adapter
->ListEntry
, &AdapterListLock
);
2058 if (Adapter
->NdisMiniportBlock
.Interrupt
)
2060 KeBugCheckEx(BUGCODE_ID_DRIVER
,
2062 (ULONG_PTR
)Adapter
->NdisMiniportBlock
.Interrupt
,
2063 (ULONG_PTR
)Adapter
->NdisMiniportBlock
.TimerQueue
,
2066 if (Adapter
->NdisMiniportBlock
.TimerQueue
)
2068 KeBugCheckEx(BUGCODE_ID_DRIVER
,
2070 (ULONG_PTR
)Adapter
->NdisMiniportBlock
.Interrupt
,
2071 (ULONG_PTR
)Adapter
->NdisMiniportBlock
.TimerQueue
,
2077 if (SelectedMediumIndex
>= MEDIA_ARRAY_SIZE
)
2079 NDIS_DbgPrint(MIN_TRACE
, ("MiniportInitialize() selected a bad index\n"));
2080 ExInterlockedRemoveEntryList( &Adapter
->ListEntry
, &AdapterListLock
);
2081 return NDIS_STATUS_UNSUPPORTED_MEDIA
;
2084 Adapter
->NdisMiniportBlock
.MediaType
= MediaArray
[SelectedMediumIndex
];
2086 switch (Adapter
->NdisMiniportBlock
.MediaType
)
2088 case NdisMedium802_3
:
2089 Adapter
->MediumHeaderSize
= 14; /* XXX figure out what to do about LLC */
2090 AddressOID
= OID_802_3_CURRENT_ADDRESS
;
2091 Adapter
->AddressLength
= ETH_LENGTH_OF_ADDRESS
;
2092 NdisStatus
= DoQueries(Adapter
, AddressOID
);
2093 if (NdisStatus
== NDIS_STATUS_SUCCESS
)
2095 NdisStatus
= MiniQueryInformation(Adapter
, OID_802_3_MAXIMUM_LIST_SIZE
, sizeof(UINT
),
2096 &MaxMulticastAddresses
, &BytesWritten
);
2098 if (NdisStatus
!= NDIS_STATUS_SUCCESS
)
2100 ExInterlockedRemoveEntryList( &Adapter
->ListEntry
, &AdapterListLock
);
2101 NDIS_DbgPrint(MIN_TRACE
, ("MiniQueryInformation failed (%x)\n", NdisStatus
));
2105 Success
= EthCreateFilter(MaxMulticastAddresses
,
2106 Adapter
->Address
.Type
.Medium802_3
,
2107 &Adapter
->NdisMiniportBlock
.EthDB
);
2109 ((PETHI_FILTER
)Adapter
->NdisMiniportBlock
.EthDB
)->Miniport
= (PNDIS_MINIPORT_BLOCK
)Adapter
;
2111 NdisStatus
= NDIS_STATUS_RESOURCES
;
2116 /* FIXME: Support other types of media */
2117 NDIS_DbgPrint(MIN_TRACE
, ("error: unsupported media\n"));
2119 ExInterlockedRemoveEntryList( &Adapter
->ListEntry
, &AdapterListLock
);
2120 return STATUS_UNSUCCESSFUL
;
2123 if (NdisStatus
!= NDIS_STATUS_SUCCESS
)
2125 NDIS_DbgPrint(MIN_TRACE
, ("couldn't create filter (%x)\n", NdisStatus
));
2129 /* Check for a hang every two seconds if it wasn't set in MiniportInitialize */
2130 if (Adapter
->NdisMiniportBlock
.CheckForHangSeconds
== 0)
2131 Adapter
->NdisMiniportBlock
.CheckForHangSeconds
= 2;
2133 Adapter
->NdisMiniportBlock
.OldPnPDeviceState
= Adapter
->NdisMiniportBlock
.PnPDeviceState
;
2134 Adapter
->NdisMiniportBlock
.PnPDeviceState
= NdisPnPDeviceStarted
;
2136 IoSetDeviceInterfaceState(&Adapter
->NdisMiniportBlock
.SymbolicLinkName
, TRUE
);
2138 Timeout
.QuadPart
= Int32x32To64(Adapter
->NdisMiniportBlock
.CheckForHangSeconds
, -1000000);
2139 KeSetTimerEx(&Adapter
->NdisMiniportBlock
.WakeUpDpcTimer
.Timer
, Timeout
,
2140 Adapter
->NdisMiniportBlock
.CheckForHangSeconds
* 1000,
2141 &Adapter
->NdisMiniportBlock
.WakeUpDpcTimer
.Dpc
);
2143 /* Put adapter in adapter list for this miniport */
2144 ExInterlockedInsertTailList(&Adapter
->NdisMiniportBlock
.DriverHandle
->DeviceList
, &Adapter
->MiniportListEntry
, &Adapter
->NdisMiniportBlock
.DriverHandle
->Lock
);
2146 /* Refresh bindings for all protocols */
2147 CurrentEntry
= ProtocolListHead
.Flink
;
2148 while (CurrentEntry
!= &ProtocolListHead
)
2150 ProtocolBinding
= CONTAINING_RECORD(CurrentEntry
, PROTOCOL_BINDING
, ListEntry
);
2152 ndisBindMiniportsToProtocol(&NdisStatus
, ProtocolBinding
);
2154 CurrentEntry
= CurrentEntry
->Flink
;
2157 return STATUS_SUCCESS
;
2164 IN PDEVICE_OBJECT DeviceObject
,
2167 * FUNCTION: Handle the PnP stop device event
2169 * DeviceObejct = Functional Device Object
2170 * Irp = IRP_MN_STOP_DEVICE I/O request packet
2172 * Status of operation
2175 PLOGICAL_ADAPTER Adapter
= (PLOGICAL_ADAPTER
)DeviceObject
->DeviceExtension
;
2177 /* Remove adapter from adapter list for this miniport */
2178 ExInterlockedRemoveEntryList(&Adapter
->MiniportListEntry
, &Adapter
->NdisMiniportBlock
.DriverHandle
->Lock
);
2180 /* Remove adapter from global adapter list */
2181 ExInterlockedRemoveEntryList(&Adapter
->ListEntry
, &AdapterListLock
);
2183 KeCancelTimer(&Adapter
->NdisMiniportBlock
.WakeUpDpcTimer
.Timer
);
2185 (*Adapter
->NdisMiniportBlock
.DriverHandle
->MiniportCharacteristics
.HaltHandler
)(Adapter
);
2187 IoSetDeviceInterfaceState(&Adapter
->NdisMiniportBlock
.SymbolicLinkName
, FALSE
);
2189 if (Adapter
->NdisMiniportBlock
.AllocatedResources
)
2191 ExFreePool(Adapter
->NdisMiniportBlock
.AllocatedResources
);
2192 Adapter
->NdisMiniportBlock
.AllocatedResources
= NULL
;
2194 if (Adapter
->NdisMiniportBlock
.AllocatedResourcesTranslated
)
2196 ExFreePool(Adapter
->NdisMiniportBlock
.AllocatedResourcesTranslated
);
2197 Adapter
->NdisMiniportBlock
.AllocatedResourcesTranslated
= NULL
;
2200 if (Adapter
->NdisMiniportBlock
.Resources
)
2202 ExFreePool(Adapter
->NdisMiniportBlock
.Resources
);
2203 Adapter
->NdisMiniportBlock
.Resources
= NULL
;
2206 if (Adapter
->NdisMiniportBlock
.EthDB
)
2208 EthDeleteFilter(Adapter
->NdisMiniportBlock
.EthDB
);
2209 Adapter
->NdisMiniportBlock
.EthDB
= NULL
;
2212 Adapter
->NdisMiniportBlock
.OldPnPDeviceState
= Adapter
->NdisMiniportBlock
.PnPDeviceState
;
2213 Adapter
->NdisMiniportBlock
.PnPDeviceState
= NdisPnPDeviceStopped
;
2215 return STATUS_SUCCESS
;
2221 IN PDEVICE_OBJECT DeviceObject
,
2224 PLOGICAL_ADAPTER Adapter
= DeviceObject
->DeviceExtension
;
2225 PMINIPORT_BUGCHECK_CONTEXT Context
= Adapter
->BugcheckContext
;
2226 ADAPTER_SHUTDOWN_HANDLER ShutdownHandler
= Context
->ShutdownHandler
;
2228 ASSERT(ShutdownHandler
);
2230 ShutdownHandler(Context
->DriverContext
);
2232 Irp
->IoStatus
.Status
= STATUS_SUCCESS
;
2233 Irp
->IoStatus
.Information
= 0;
2235 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
2237 return STATUS_SUCCESS
;
2242 NdisIDeviceIoControl(
2243 IN PDEVICE_OBJECT DeviceObject
,
2246 PLOGICAL_ADAPTER Adapter
= (PLOGICAL_ADAPTER
)DeviceObject
->DeviceExtension
;
2247 PIO_STACK_LOCATION Stack
= IoGetCurrentIrpStackLocation(Irp
);
2248 NDIS_STATUS Status
= STATUS_NOT_SUPPORTED
;
2251 Irp
->IoStatus
.Information
= 0;
2255 switch (Stack
->Parameters
.DeviceIoControl
.IoControlCode
)
2257 case IOCTL_NDIS_QUERY_GLOBAL_STATS
:
2258 Status
= MiniQueryInformation(Adapter
,
2259 *(PNDIS_OID
)Irp
->AssociatedIrp
.SystemBuffer
,
2260 Stack
->Parameters
.DeviceIoControl
.OutputBufferLength
,
2261 MmGetSystemAddressForMdl(Irp
->MdlAddress
),
2263 Irp
->IoStatus
.Information
= Written
;
2271 if (Status
!= NDIS_STATUS_PENDING
)
2273 Irp
->IoStatus
.Status
= Status
;
2274 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
2277 IoMarkIrpPending(Irp
);
2286 IN PDEVICE_OBJECT DeviceObject
,
2289 PIO_STACK_LOCATION Stack
= IoGetCurrentIrpStackLocation(Irp
);
2290 PLOGICAL_ADAPTER Adapter
= (PLOGICAL_ADAPTER
)DeviceObject
->DeviceExtension
;
2293 switch (Stack
->MinorFunction
)
2295 case IRP_MN_START_DEVICE
:
2296 Status
= NdisIForwardIrpAndWait(Adapter
, Irp
);
2297 if (NT_SUCCESS(Status
) && NT_SUCCESS(Irp
->IoStatus
.Status
))
2299 Status
= NdisIPnPStartDevice(DeviceObject
, Irp
);
2302 NDIS_DbgPrint(MIN_TRACE
, ("Lower driver failed device start\n"));
2303 Irp
->IoStatus
.Status
= Status
;
2304 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
2307 case IRP_MN_STOP_DEVICE
:
2308 Status
= NdisIPnPStopDevice(DeviceObject
, Irp
);
2309 if (!NT_SUCCESS(Status
))
2310 NDIS_DbgPrint(MIN_TRACE
, ("WARNING: Ignoring halt device failure! Passing the IRP down anyway\n"));
2311 Irp
->IoStatus
.Status
= STATUS_SUCCESS
;
2314 case IRP_MN_QUERY_REMOVE_DEVICE
:
2315 case IRP_MN_QUERY_STOP_DEVICE
:
2316 Status
= NdisIPnPQueryStopDevice(DeviceObject
, Irp
);
2317 Irp
->IoStatus
.Status
= Status
;
2318 if (Status
!= STATUS_SUCCESS
)
2320 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
2321 NDIS_DbgPrint(MIN_TRACE
, ("Failing miniport halt request\n"));
2326 case IRP_MN_CANCEL_REMOVE_DEVICE
:
2327 case IRP_MN_CANCEL_STOP_DEVICE
:
2328 Status
= NdisIForwardIrpAndWait(Adapter
, Irp
);
2329 if (NT_SUCCESS(Status
) && NT_SUCCESS(Irp
->IoStatus
.Status
))
2331 Status
= NdisIPnPCancelStopDevice(DeviceObject
, Irp
);
2335 NDIS_DbgPrint(MIN_TRACE
, ("Lower driver failed cancel stop/remove request\n"));
2337 Irp
->IoStatus
.Status
= Status
;
2338 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
2341 case IRP_MN_QUERY_PNP_DEVICE_STATE
:
2342 Status
= NDIS_STATUS_SUCCESS
;
2343 Irp
->IoStatus
.Status
= Status
;
2344 Irp
->IoStatus
.Information
|= Adapter
->NdisMiniportBlock
.PnPFlags
;
2351 IoSkipCurrentIrpStackLocation(Irp
);
2352 return IoCallDriver(Adapter
->NdisMiniportBlock
.NextDeviceObject
, Irp
);
2359 IN PDRIVER_OBJECT DriverObject
,
2360 IN PDEVICE_OBJECT PhysicalDeviceObject
)
2362 * FUNCTION: Create a device for an adapter found using PnP
2364 * DriverObject = Pointer to the miniport driver object
2365 * PhysicalDeviceObject = Pointer to the PDO for our adapter
2368 static const WCHAR ClassKeyName
[] = {'C','l','a','s','s','\\'};
2369 static const WCHAR LinkageKeyName
[] = {'\\','L','i','n','k','a','g','e',0};
2370 PNDIS_M_DRIVER_BLOCK Miniport
;
2371 PNDIS_M_DRIVER_BLOCK
*MiniportPtr
;
2372 WCHAR
*LinkageKeyBuffer
;
2373 ULONG DriverKeyLength
;
2374 RTL_QUERY_REGISTRY_TABLE QueryTable
[2];
2375 UNICODE_STRING ExportName
;
2376 PDEVICE_OBJECT DeviceObject
;
2377 PLOGICAL_ADAPTER Adapter
;
2381 * Gain the access to the miniport data structure first.
2384 MiniportPtr
= IoGetDriverObjectExtension(DriverObject
, (PVOID
)'NMID');
2385 if (MiniportPtr
== NULL
)
2387 NDIS_DbgPrint(MIN_TRACE
, ("Can't get driver object extension.\n"));
2388 return NDIS_STATUS_FAILURE
;
2390 Miniport
= *MiniportPtr
;
2393 * Get name of the Linkage registry key for our adapter. It's located under
2394 * the driver key for our driver and so we have basicly two ways to do it.
2395 * Either we can use IoOpenDriverRegistryKey or compose it using information
2396 * gathered by IoGetDeviceProperty. I choosed the second because
2397 * IoOpenDriverRegistryKey wasn't implemented at the time of writing.
2400 Status
= IoGetDeviceProperty(PhysicalDeviceObject
, DevicePropertyDriverKeyName
,
2401 0, NULL
, &DriverKeyLength
);
2402 if (Status
!= STATUS_BUFFER_TOO_SMALL
&& Status
!= STATUS_BUFFER_OVERFLOW
&& Status
!= STATUS_SUCCESS
)
2404 NDIS_DbgPrint(MIN_TRACE
, ("Can't get miniport driver key length.\n"));
2408 LinkageKeyBuffer
= ExAllocatePool(PagedPool
, DriverKeyLength
+
2409 sizeof(ClassKeyName
) + sizeof(LinkageKeyName
));
2410 if (LinkageKeyBuffer
== NULL
)
2412 NDIS_DbgPrint(MIN_TRACE
, ("Can't allocate memory for driver key name.\n"));
2413 return STATUS_INSUFFICIENT_RESOURCES
;
2416 Status
= IoGetDeviceProperty(PhysicalDeviceObject
, DevicePropertyDriverKeyName
,
2417 DriverKeyLength
, LinkageKeyBuffer
+
2418 (sizeof(ClassKeyName
) / sizeof(WCHAR
)),
2420 if (!NT_SUCCESS(Status
))
2422 NDIS_DbgPrint(MIN_TRACE
, ("Can't get miniport driver key.\n"));
2423 ExFreePool(LinkageKeyBuffer
);
2427 /* Compose the linkage key name. */
2428 RtlCopyMemory(LinkageKeyBuffer
, ClassKeyName
, sizeof(ClassKeyName
));
2429 RtlCopyMemory(LinkageKeyBuffer
+ ((sizeof(ClassKeyName
) + DriverKeyLength
) /
2430 sizeof(WCHAR
)) - 1, LinkageKeyName
, sizeof(LinkageKeyName
));
2432 NDIS_DbgPrint(DEBUG_MINIPORT
, ("LinkageKey: %S.\n", LinkageKeyBuffer
));
2435 * Now open the linkage key and read the "Export" and "RootDevice" values
2436 * which contains device name and root service respectively.
2439 RtlZeroMemory(QueryTable
, sizeof(QueryTable
));
2440 RtlInitUnicodeString(&ExportName
, NULL
);
2441 QueryTable
[0].Flags
= RTL_QUERY_REGISTRY_REQUIRED
| RTL_QUERY_REGISTRY_DIRECT
;
2442 QueryTable
[0].Name
= L
"Export";
2443 QueryTable
[0].EntryContext
= &ExportName
;
2445 Status
= RtlQueryRegistryValues(RTL_REGISTRY_CONTROL
, LinkageKeyBuffer
,
2446 QueryTable
, NULL
, NULL
);
2447 ExFreePool(LinkageKeyBuffer
);
2448 if (!NT_SUCCESS(Status
))
2450 NDIS_DbgPrint(MIN_TRACE
, ("Can't get miniport device name. (%x)\n", Status
));
2455 * Create the device object.
2458 NDIS_DbgPrint(MAX_TRACE
, ("creating device %wZ\n", &ExportName
));
2460 Status
= IoCreateDevice(Miniport
->DriverObject
, sizeof(LOGICAL_ADAPTER
),
2461 &ExportName
, FILE_DEVICE_PHYSICAL_NETCARD
,
2462 0, FALSE
, &DeviceObject
);
2463 if (!NT_SUCCESS(Status
))
2465 NDIS_DbgPrint(MIN_TRACE
, ("Could not create device object.\n"));
2466 RtlFreeUnicodeString(&ExportName
);
2471 * Initialize the adapter structure.
2474 Adapter
= (PLOGICAL_ADAPTER
)DeviceObject
->DeviceExtension
;
2475 KeInitializeSpinLock(&Adapter
->NdisMiniportBlock
.Lock
);
2476 InitializeListHead(&Adapter
->ProtocolListHead
);
2478 Status
= IoRegisterDeviceInterface(PhysicalDeviceObject
,
2479 &GUID_DEVINTERFACE_NET
,
2481 &Adapter
->NdisMiniportBlock
.SymbolicLinkName
);
2483 if (!NT_SUCCESS(Status
))
2485 NDIS_DbgPrint(MIN_TRACE
, ("Could not create device interface.\n"));
2486 IoDeleteDevice(DeviceObject
);
2487 RtlFreeUnicodeString(&ExportName
);
2491 Adapter
->NdisMiniportBlock
.DriverHandle
= Miniport
;
2492 Adapter
->NdisMiniportBlock
.MiniportName
= ExportName
;
2493 Adapter
->NdisMiniportBlock
.DeviceObject
= DeviceObject
;
2494 Adapter
->NdisMiniportBlock
.PhysicalDeviceObject
= PhysicalDeviceObject
;
2495 Adapter
->NdisMiniportBlock
.NextDeviceObject
=
2496 IoAttachDeviceToDeviceStack(Adapter
->NdisMiniportBlock
.DeviceObject
,
2497 PhysicalDeviceObject
);
2499 Adapter
->NdisMiniportBlock
.OldPnPDeviceState
= 0;
2500 Adapter
->NdisMiniportBlock
.PnPDeviceState
= NdisPnPDeviceAdded
;
2502 KeInitializeTimer(&Adapter
->NdisMiniportBlock
.WakeUpDpcTimer
.Timer
);
2503 KeInitializeDpc(&Adapter
->NdisMiniportBlock
.WakeUpDpcTimer
.Dpc
, MiniportHangDpc
, Adapter
);
2505 DeviceObject
->Flags
&= ~DO_DEVICE_INITIALIZING
;
2507 return STATUS_SUCCESS
;
2516 NdisMRegisterMiniport(
2517 IN NDIS_HANDLE NdisWrapperHandle
,
2518 IN PNDIS_MINIPORT_CHARACTERISTICS MiniportCharacteristics
,
2519 IN UINT CharacteristicsLength
)
2521 * FUNCTION: Registers a miniport's MiniportXxx entry points with the NDIS library
2523 * NdisWrapperHandle = Pointer to handle returned by NdisMInitializeWrapper
2524 * MiniportCharacteristics = Pointer to a buffer with miniport characteristics
2525 * CharacteristicsLength = Number of bytes in characteristics buffer
2527 * Status of operation
2531 PNDIS_M_DRIVER_BLOCK Miniport
= GET_MINIPORT_DRIVER(NdisWrapperHandle
);
2532 PNDIS_M_DRIVER_BLOCK
*MiniportPtr
;
2535 NDIS_DbgPrint(MAX_TRACE
, ("Called.\n"));
2537 switch (MiniportCharacteristics
->MajorNdisVersion
)
2540 MinSize
= sizeof(NDIS30_MINIPORT_CHARACTERISTICS
);
2544 MinSize
= sizeof(NDIS40_MINIPORT_CHARACTERISTICS
);
2548 switch (MiniportCharacteristics
->MinorNdisVersion
)
2551 MinSize
= sizeof(NDIS50_MINIPORT_CHARACTERISTICS
);
2555 MinSize
= sizeof(NDIS51_MINIPORT_CHARACTERISTICS
);
2559 NDIS_DbgPrint(MIN_TRACE
, ("Bad 5.x minor characteristics version.\n"));
2560 return NDIS_STATUS_BAD_VERSION
;
2565 NDIS_DbgPrint(MIN_TRACE
, ("Bad miniport characteristics version.\n"));
2566 return NDIS_STATUS_BAD_VERSION
;
2569 NDIS_DbgPrint(MIN_TRACE
, ("Initializing an NDIS %u.%u miniport\n",
2570 MiniportCharacteristics
->MajorNdisVersion
,
2571 MiniportCharacteristics
->MinorNdisVersion
));
2573 if (CharacteristicsLength
< MinSize
)
2575 NDIS_DbgPrint(MIN_TRACE
, ("Bad miniport characteristics length.\n"));
2576 return NDIS_STATUS_BAD_CHARACTERISTICS
;
2579 /* Check if mandatory MiniportXxx functions are specified */
2580 if ((!MiniportCharacteristics
->HaltHandler
) ||
2581 (!MiniportCharacteristics
->InitializeHandler
)||
2582 (!MiniportCharacteristics
->ResetHandler
))
2584 NDIS_DbgPrint(MIN_TRACE
, ("Bad miniport characteristics.\n"));
2585 return NDIS_STATUS_BAD_CHARACTERISTICS
;
2588 if (MiniportCharacteristics
->MajorNdisVersion
< 0x05)
2590 if ((!MiniportCharacteristics
->QueryInformationHandler
) ||
2591 (!MiniportCharacteristics
->SetInformationHandler
))
2593 NDIS_DbgPrint(MIN_TRACE
, ("Bad miniport characteristics. (Set/Query)\n"));
2594 return NDIS_STATUS_BAD_CHARACTERISTICS
;
2599 if (((!MiniportCharacteristics
->QueryInformationHandler
) ||
2600 (!MiniportCharacteristics
->SetInformationHandler
)) &&
2601 (!MiniportCharacteristics
->CoRequestHandler
))
2603 NDIS_DbgPrint(MIN_TRACE
, ("Bad miniport characteristics. (Set/Query)\n"));
2604 return NDIS_STATUS_BAD_CHARACTERISTICS
;
2608 if (MiniportCharacteristics
->MajorNdisVersion
== 0x03)
2610 if (!MiniportCharacteristics
->SendHandler
)
2612 NDIS_DbgPrint(MIN_TRACE
, ("Bad miniport characteristics. (NDIS 3.0)\n"));
2613 return NDIS_STATUS_BAD_CHARACTERISTICS
;
2616 else if (MiniportCharacteristics
->MajorNdisVersion
== 0x04)
2619 if ((!MiniportCharacteristics
->SendHandler
) &&
2620 (!MiniportCharacteristics
->SendPacketsHandler
))
2622 NDIS_DbgPrint(MIN_TRACE
, ("Bad miniport characteristics. (NDIS 4.0)\n"));
2623 return NDIS_STATUS_BAD_CHARACTERISTICS
;
2626 else if (MiniportCharacteristics
->MajorNdisVersion
== 0x05)
2628 /* TODO: Add more checks here */
2630 if ((!MiniportCharacteristics
->SendHandler
) &&
2631 (!MiniportCharacteristics
->SendPacketsHandler
) &&
2632 (!MiniportCharacteristics
->CoSendPacketsHandler
))
2634 NDIS_DbgPrint(MIN_TRACE
, ("Bad miniport characteristics. (NDIS 5.0)\n"));
2635 return NDIS_STATUS_BAD_CHARACTERISTICS
;
2639 RtlCopyMemory(&Miniport
->MiniportCharacteristics
, MiniportCharacteristics
, MinSize
);
2642 * NOTE: This is VERY unoptimal! Should we store the NDIS_M_DRIVER_BLOCK
2643 * structure in the driver extension or what?
2646 Status
= IoAllocateDriverObjectExtension(Miniport
->DriverObject
, (PVOID
)'NMID',
2647 sizeof(PNDIS_M_DRIVER_BLOCK
), (PVOID
*)&MiniportPtr
);
2648 if (!NT_SUCCESS(Status
))
2650 NDIS_DbgPrint(MIN_TRACE
, ("Can't allocate driver object extension.\n"));
2651 return NDIS_STATUS_RESOURCES
;
2654 *MiniportPtr
= Miniport
;
2656 Miniport
->DriverObject
->MajorFunction
[IRP_MJ_CREATE
] = NdisICreateClose
;
2657 Miniport
->DriverObject
->MajorFunction
[IRP_MJ_CLOSE
] = NdisICreateClose
;
2658 Miniport
->DriverObject
->MajorFunction
[IRP_MJ_PNP
] = NdisIDispatchPnp
;
2659 Miniport
->DriverObject
->MajorFunction
[IRP_MJ_SHUTDOWN
] = NdisIShutdown
;
2660 Miniport
->DriverObject
->MajorFunction
[IRP_MJ_DEVICE_CONTROL
] = NdisIDeviceIoControl
;
2661 Miniport
->DriverObject
->DriverExtension
->AddDevice
= NdisIAddDevice
;
2663 return NDIS_STATUS_SUCCESS
;
2670 #undef NdisMResetComplete
2674 IN NDIS_HANDLE MiniportAdapterHandle
,
2675 IN NDIS_STATUS Status
,
2676 IN BOOLEAN AddressingReset
)
2678 MiniResetComplete(MiniportAdapterHandle
, Status
, AddressingReset
);
2685 #undef NdisMSendComplete
2689 IN NDIS_HANDLE MiniportAdapterHandle
,
2690 IN PNDIS_PACKET Packet
,
2691 IN NDIS_STATUS Status
)
2693 * FUNCTION: Forwards a message to the initiating protocol saying
2694 * that a packet was handled
2696 * NdisAdapterHandle = Handle input to MiniportInitialize
2697 * Packet = Pointer to NDIS packet that was sent
2698 * Status = Status of send operation
2701 MiniSendComplete(MiniportAdapterHandle
, Packet
, Status
);
2708 #undef NdisMSendResourcesAvailable
2711 NdisMSendResourcesAvailable(
2712 IN NDIS_HANDLE MiniportAdapterHandle
)
2714 MiniSendResourcesAvailable(MiniportAdapterHandle
);
2721 #undef NdisMTransferDataComplete
2724 NdisMTransferDataComplete(
2725 IN NDIS_HANDLE MiniportAdapterHandle
,
2726 IN PNDIS_PACKET Packet
,
2727 IN NDIS_STATUS Status
,
2728 IN UINT BytesTransferred
)
2730 MiniTransferDataComplete(MiniportAdapterHandle
, Packet
, Status
, BytesTransferred
);
2737 #undef NdisMSetAttributes
2741 IN NDIS_HANDLE MiniportAdapterHandle
,
2742 IN NDIS_HANDLE MiniportAdapterContext
,
2743 IN BOOLEAN BusMaster
,
2744 IN NDIS_INTERFACE_TYPE AdapterType
)
2746 * FUNCTION: Informs the NDIS library of significant features of the caller's NIC
2748 * MiniportAdapterHandle = Handle input to MiniportInitialize
2749 * MiniportAdapterContext = Pointer to context information
2750 * BusMaster = Specifies TRUE if the caller's NIC is a busmaster DMA device
2751 * AdapterType = Specifies the I/O bus interface of the caller's NIC
2754 NDIS_DbgPrint(MAX_TRACE
, ("Called.\n"));
2755 NdisMSetAttributesEx(MiniportAdapterHandle
, MiniportAdapterContext
, 0,
2756 BusMaster
? NDIS_ATTRIBUTE_BUS_MASTER
: 0,
2766 NdisMSetAttributesEx(
2767 IN NDIS_HANDLE MiniportAdapterHandle
,
2768 IN NDIS_HANDLE MiniportAdapterContext
,
2769 IN UINT CheckForHangTimeInSeconds OPTIONAL
,
2770 IN ULONG AttributeFlags
,
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 * CheckForHangTimeInSeconds = Specifies interval in seconds at which
2778 * MiniportCheckForHang should be called
2779 * AttributeFlags = Bitmask that indicates specific attributes
2780 * AdapterType = Specifies the I/O bus interface of the caller's NIC
2783 PLOGICAL_ADAPTER Adapter
= GET_LOGICAL_ADAPTER(MiniportAdapterHandle
);
2785 NDIS_DbgPrint(MAX_TRACE
, ("Called.\n"));
2787 Adapter
->NdisMiniportBlock
.MiniportAdapterContext
= MiniportAdapterContext
;
2788 Adapter
->NdisMiniportBlock
.Flags
= AttributeFlags
;
2789 Adapter
->NdisMiniportBlock
.AdapterType
= AdapterType
;
2790 if (CheckForHangTimeInSeconds
> 0)
2791 Adapter
->NdisMiniportBlock
.CheckForHangSeconds
= CheckForHangTimeInSeconds
;
2792 if (AttributeFlags
& NDIS_ATTRIBUTE_INTERMEDIATE_DRIVER
)
2793 NDIS_DbgPrint(MAX_TRACE
, ("Intermediate drivers not supported yet.\n"));
2796 if (Adapter
->NdisMiniportBlock
.DriverHandle
->MiniportCharacteristics
.AdapterShutdownHandler
)
2798 NDIS_DbgPrint(MAX_TRACE
, ("Miniport set AdapterShutdownHandler in MiniportCharacteristics\n"));
2799 NdisMRegisterAdapterShutdownHandler(Adapter
,
2800 Adapter
->NdisMiniportBlock
.MiniportAdapterContext
,
2801 Adapter
->NdisMiniportBlock
.DriverHandle
->MiniportCharacteristics
.AdapterShutdownHandler
);
2812 IN ULONG MicrosecondsToSleep
)
2814 * FUNCTION: delay the thread's execution for MicrosecondsToSleep
2816 * MicrosecondsToSleep: duh...
2818 * - Because this is a blocking call, current IRQL must be < DISPATCH_LEVEL
2822 LARGE_INTEGER DueTime
;
2826 DueTime
.QuadPart
= (-1) * 10 * MicrosecondsToSleep
;
2828 KeInitializeTimer(&Timer
);
2829 KeSetTimer(&Timer
, DueTime
, 0);
2830 KeWaitForSingleObject(&Timer
, Executive
, KernelMode
, FALSE
, 0);
2839 NdisMSynchronizeWithInterrupt(
2840 IN PNDIS_MINIPORT_INTERRUPT Interrupt
,
2841 IN PVOID SynchronizeFunction
,
2842 IN PVOID SynchronizeContext
)
2844 return(KeSynchronizeExecution(Interrupt
->InterruptObject
,
2845 (PKSYNCHRONIZE_ROUTINE
)SynchronizeFunction
,
2846 SynchronizeContext
));
2856 IN NDIS_HANDLE LogHandle
,
2858 IN UINT LogBufferSize
)
2860 PUCHAR Buffer
= LogBuffer
;
2864 for (i
= 0; i
< LogBufferSize
; i
+= 16)
2866 DbgPrint("%08x |", i
);
2867 for (j
= 0; j
< 16; j
++)
2870 if (idx
< LogBufferSize
)
2871 DbgPrint(" %02x", Buffer
[idx
]);
2876 for (j
= 0; j
< 16; j
++)
2879 if (idx
== LogBufferSize
)
2881 if (Buffer
[idx
] >= ' ') /* FIXME: not portable! replace by if (isprint(Buffer[idx])) ? */
2882 DbgPrint("%c", Buffer
[idx
]);
2889 return NDIS_STATUS_FAILURE
;
2898 NdisTerminateWrapper(
2899 IN NDIS_HANDLE NdisWrapperHandle
,
2900 IN PVOID SystemSpecific
)
2902 * FUNCTION: Releases resources allocated by a call to NdisInitializeWrapper
2904 * NdisWrapperHandle = Handle returned by NdisInitializeWrapper (NDIS_M_DRIVER_BLOCK)
2905 * SystemSpecific = Always NULL
2908 PNDIS_M_DRIVER_BLOCK Miniport
= GET_MINIPORT_DRIVER(NdisWrapperHandle
);
2910 NDIS_DbgPrint(MAX_TRACE
, ("Called.\n"));
2912 ExFreePool(Miniport
->RegistryPath
->Buffer
);
2913 ExFreePool(Miniport
->RegistryPath
);
2914 ExInterlockedRemoveEntryList(&Miniport
->ListEntry
, &MiniportListLock
);
2915 ExFreePool(Miniport
);
2924 NdisMQueryAdapterInstanceName(
2925 OUT PNDIS_STRING AdapterInstanceName
,
2926 IN NDIS_HANDLE MiniportAdapterHandle
)
2934 PLOGICAL_ADAPTER Adapter
= (PLOGICAL_ADAPTER
)MiniportAdapterHandle
;
2935 UNICODE_STRING AdapterName
;
2937 NDIS_DbgPrint(MAX_TRACE
, ("Called.\n"));
2939 AdapterName
.Length
= 0;
2940 AdapterName
.MaximumLength
= Adapter
->NdisMiniportBlock
.MiniportName
.MaximumLength
;
2941 AdapterName
.Buffer
= ExAllocatePool(PagedPool
, AdapterName
.MaximumLength
);
2942 if (!AdapterName
.Buffer
) {
2943 NDIS_DbgPrint(MIN_TRACE
, ("Insufficient resources\n"));
2944 return NDIS_STATUS_RESOURCES
;
2947 RtlCopyUnicodeString(&AdapterName
, &Adapter
->NdisMiniportBlock
.MiniportName
);
2949 *AdapterInstanceName
= AdapterName
;
2951 return NDIS_STATUS_SUCCESS
;
2959 NdisDeregisterAdapterShutdownHandler(
2960 IN NDIS_HANDLE NdisAdapterHandle
)
2968 NdisMDeregisterAdapterShutdownHandler(NdisAdapterHandle
);
2977 NdisRegisterAdapterShutdownHandler(
2978 IN NDIS_HANDLE NdisAdapterHandle
,
2979 IN PVOID ShutdownContext
,
2980 IN ADAPTER_SHUTDOWN_HANDLER ShutdownHandler
)
2988 NdisMRegisterAdapterShutdownHandler(NdisAdapterHandle
,
2998 NdisMGetDeviceProperty(
2999 IN NDIS_HANDLE MiniportAdapterHandle
,
3000 IN OUT PDEVICE_OBJECT
*PhysicalDeviceObject OPTIONAL
,
3001 IN OUT PDEVICE_OBJECT
*FunctionalDeviceObject OPTIONAL
,
3002 IN OUT PDEVICE_OBJECT
*NextDeviceObject OPTIONAL
,
3003 IN OUT PCM_RESOURCE_LIST
*AllocatedResources OPTIONAL
,
3004 IN OUT PCM_RESOURCE_LIST
*AllocatedResourcesTranslated OPTIONAL
)
3012 PLOGICAL_ADAPTER Adapter
= MiniportAdapterHandle
;
3014 NDIS_DbgPrint(MAX_TRACE
, ("Called\n"));
3016 if (PhysicalDeviceObject
!= NULL
)
3017 *PhysicalDeviceObject
= Adapter
->NdisMiniportBlock
.PhysicalDeviceObject
;
3019 if (FunctionalDeviceObject
!= NULL
)
3020 *FunctionalDeviceObject
= Adapter
->NdisMiniportBlock
.DeviceObject
;
3022 if (NextDeviceObject
!= NULL
)
3023 *NextDeviceObject
= Adapter
->NdisMiniportBlock
.NextDeviceObject
;
3025 if (AllocatedResources
!= NULL
)
3026 *AllocatedResources
= Adapter
->NdisMiniportBlock
.AllocatedResources
;
3028 if (AllocatedResourcesTranslated
!= NULL
)
3029 *AllocatedResourcesTranslated
= Adapter
->NdisMiniportBlock
.AllocatedResourcesTranslated
;
3037 NdisMRegisterUnloadHandler(
3038 IN NDIS_HANDLE NdisWrapperHandle
,
3039 IN PDRIVER_UNLOAD UnloadHandler
)
3047 PNDIS_M_DRIVER_BLOCK DriverBlock
= NdisWrapperHandle
;
3049 NDIS_DbgPrint(MAX_TRACE
, ("Miniport registered unload handler\n"));
3051 DriverBlock
->DriverObject
->DriverUnload
= UnloadHandler
;
3059 NdisMRegisterDevice(
3060 IN NDIS_HANDLE NdisWrapperHandle
,
3061 IN PNDIS_STRING DeviceName
,
3062 IN PNDIS_STRING SymbolicName
,
3063 IN PDRIVER_DISPATCH MajorFunctions
[],
3064 OUT PDEVICE_OBJECT
*pDeviceObject
,
3065 OUT NDIS_HANDLE
*NdisDeviceHandle
)
3073 PNDIS_M_DRIVER_BLOCK DriverBlock
= NdisWrapperHandle
;
3074 PNDIS_M_DEVICE_BLOCK DeviceBlock
;
3075 PDEVICE_OBJECT DeviceObject
;
3079 NDIS_DbgPrint(MAX_TRACE
, ("Called\n"));
3081 Status
= IoCreateDevice(DriverBlock
->DriverObject
,
3082 0, /* This space is reserved for us. Should we use it? */
3084 FILE_DEVICE_NETWORK
,
3089 if (!NT_SUCCESS(Status
))
3091 NDIS_DbgPrint(MIN_TRACE
, ("IoCreateDevice failed (%x)\n", Status
));
3095 Status
= IoCreateSymbolicLink(SymbolicName
, DeviceName
);
3097 if (!NT_SUCCESS(Status
))
3099 NDIS_DbgPrint(MIN_TRACE
, ("IoCreateSymbolicLink failed (%x)\n", Status
));
3100 IoDeleteDevice(DeviceObject
);
3104 DeviceBlock
= ExAllocatePool(NonPagedPool
, sizeof(NDIS_M_DEVICE_BLOCK
));
3108 NDIS_DbgPrint(MIN_TRACE
, ("Insufficient resources\n"));
3109 IoDeleteDevice(DeviceObject
);
3110 IoDeleteSymbolicLink(SymbolicName
);
3111 return NDIS_STATUS_RESOURCES
;
3114 for (i
= 0; i
<= IRP_MJ_MAXIMUM_FUNCTION
; i
++)
3115 DriverBlock
->DriverObject
->MajorFunction
[i
] = MajorFunctions
[i
];
3117 DriverBlock
->DriverObject
->MajorFunction
[IRP_MJ_PNP
] = NdisIDispatchPnp
;
3119 if (!DriverBlock
->DriverObject
->MajorFunction
[IRP_MJ_CREATE
])
3120 DriverBlock
->DriverObject
->MajorFunction
[IRP_MJ_CREATE
] = NdisICreateClose
;
3122 if (!DriverBlock
->DriverObject
->MajorFunction
[IRP_MJ_CLOSE
])
3123 DriverBlock
->DriverObject
->MajorFunction
[IRP_MJ_CLOSE
] = NdisICreateClose
;
3125 DeviceBlock
->DeviceObject
= DeviceObject
;
3126 DeviceBlock
->SymbolicName
= SymbolicName
;
3128 *pDeviceObject
= DeviceObject
;
3129 *NdisDeviceHandle
= DeviceBlock
;
3131 return NDIS_STATUS_SUCCESS
;
3139 NdisMDeregisterDevice(
3140 IN NDIS_HANDLE NdisDeviceHandle
)
3148 PNDIS_M_DEVICE_BLOCK DeviceBlock
= NdisDeviceHandle
;
3150 IoDeleteDevice(DeviceBlock
->DeviceObject
);
3152 IoDeleteSymbolicLink(DeviceBlock
->SymbolicName
);
3154 ExFreePool(DeviceBlock
);
3156 return NDIS_STATUS_SUCCESS
;
3164 NdisQueryAdapterInstanceName(
3165 OUT PNDIS_STRING AdapterInstanceName
,
3166 IN NDIS_HANDLE NdisBindingHandle
)
3174 PADAPTER_BINDING AdapterBinding
= NdisBindingHandle
;
3175 PLOGICAL_ADAPTER Adapter
= AdapterBinding
->Adapter
;
3177 return NdisMQueryAdapterInstanceName(AdapterInstanceName
,
3186 NdisCompletePnPEvent(
3187 IN NDIS_STATUS Status
,
3188 IN NDIS_HANDLE NdisBindingHandle
,
3189 IN PNET_PNP_EVENT NetPnPEvent
)
3197 PIRP Irp
= (PIRP
)NetPnPEvent
->NdisReserved
[0];
3198 PLIST_ENTRY CurrentEntry
= (PLIST_ENTRY
)NetPnPEvent
->NdisReserved
[1];
3199 PADAPTER_BINDING AdapterBinding
= NdisBindingHandle
;
3200 PLOGICAL_ADAPTER Adapter
= AdapterBinding
->Adapter
;
3201 NDIS_STATUS NdisStatus
;
3203 if (Status
!= NDIS_STATUS_SUCCESS
)
3205 if (NetPnPEvent
->Buffer
) ExFreePool(NetPnPEvent
->Buffer
);
3206 ExFreePool(NetPnPEvent
);
3207 Irp
->IoStatus
.Status
= Status
;
3208 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
3212 while (CurrentEntry
!= &Adapter
->ProtocolListHead
)
3214 AdapterBinding
= CONTAINING_RECORD(CurrentEntry
, ADAPTER_BINDING
, AdapterListEntry
);
3216 NdisStatus
= (*AdapterBinding
->ProtocolBinding
->Chars
.PnPEventHandler
)(
3217 AdapterBinding
->NdisOpenBlock
.ProtocolBindingContext
,
3220 if (NdisStatus
== NDIS_STATUS_PENDING
)
3222 NetPnPEvent
->NdisReserved
[1] = (ULONG_PTR
)CurrentEntry
->Flink
;
3225 else if (NdisStatus
!= NDIS_STATUS_SUCCESS
)
3227 if (NetPnPEvent
->Buffer
) ExFreePool(NetPnPEvent
->Buffer
);
3228 ExFreePool(NetPnPEvent
);
3229 Irp
->IoStatus
.Status
= NdisStatus
;
3230 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
3234 CurrentEntry
= CurrentEntry
->Flink
;
3237 if (NetPnPEvent
->Buffer
) ExFreePool(NetPnPEvent
->Buffer
);
3238 ExFreePool(NetPnPEvent
);
3240 Irp
->IoStatus
.Status
= NDIS_STATUS_SUCCESS
;
3241 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
3249 NdisCancelSendPackets(
3250 IN NDIS_HANDLE NdisBindingHandle
,
3253 PADAPTER_BINDING AdapterBinding
= NdisBindingHandle
;
3254 PLOGICAL_ADAPTER Adapter
= AdapterBinding
->Adapter
;
3256 NDIS_DbgPrint(MAX_TRACE
, ("Called for ID %x.\n", CancelId
));
3258 if (Adapter
->NdisMiniportBlock
.DriverHandle
->MiniportCharacteristics
.CancelSendPacketsHandler
)
3260 (*Adapter
->NdisMiniportBlock
.DriverHandle
->MiniportCharacteristics
.CancelSendPacketsHandler
)(
3261 Adapter
->NdisMiniportBlock
.MiniportAdapterContext
,
3272 NdisIMGetBindingContext(
3273 IN NDIS_HANDLE NdisBindingHandle
)
3281 PADAPTER_BINDING AdapterBinding
= NdisBindingHandle
;
3282 PLOGICAL_ADAPTER Adapter
= AdapterBinding
->Adapter
;
3284 NDIS_DbgPrint(MAX_TRACE
, ("Called.\n"));
3286 return Adapter
->NdisMiniportBlock
.DeviceContext
;
3295 NdisIMGetDeviceContext(
3296 IN NDIS_HANDLE MiniportAdapterHandle
)
3304 PLOGICAL_ADAPTER Adapter
= MiniportAdapterHandle
;
3306 NDIS_DbgPrint(MAX_TRACE
, ("Called.\n"));
3308 return Adapter
->NdisMiniportBlock
.DeviceContext
;