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
21 #undef NdisMSendComplete
25 IN NDIS_HANDLE MiniportAdapterHandle
,
26 IN PNDIS_PACKET Packet
,
27 IN NDIS_STATUS Status
);
29 /* Root of the scm database */
30 #define SERVICES_ROOT L"\\Registry\\Machine\\System\\CurrentControlSet\\Services\\"
33 * Define to 1 to get a debugger breakpoint at the end of NdisInitializeWrapper
34 * for each new miniport starting up
36 #define BREAK_ON_MINIPORT_INIT 0
39 * This has to be big enough to hold the results of querying the Route value
40 * from the Linkage key. Please re-code me to determine this dynamically.
42 #define ROUTE_DATA_SIZE 256
44 /* Number of media we know */
45 #define MEDIA_ARRAY_SIZE 15
47 static NDIS_MEDIUM MediaArray
[MEDIA_ARRAY_SIZE
] =
56 NdisMediumArcnet878_2
,
58 NdisMediumWirelessWan
,
66 /* global list and lock of Miniports NDIS has registered */
67 LIST_ENTRY MiniportListHead
;
68 KSPIN_LOCK MiniportListLock
;
70 /* global list and lock of adapters NDIS has registered */
71 LIST_ENTRY AdapterListHead
;
72 KSPIN_LOCK AdapterListLock
;
81 if ((DebugTraceLevel
& DEBUG_PACKET
) > 0) {
82 Length
= CopyPacketToBuffer(
88 DbgPrint("*** PACKET START ***");
90 for (i
= 0; i
< Length
; i
++) {
92 DbgPrint("\n%04X ", i
);
93 DbgPrint("%02X ", Buffer
[i
]);
96 DbgPrint("*** PACKET STOP ***\n");
104 UINT HeaderBufferSize
,
105 PVOID LookaheadBuffer
,
106 UINT LookaheadBufferSize
)
109 if ((DebugTraceLevel
& DEBUG_PACKET
) > 0) {
113 DbgPrint("*** RECEIVE PACKET START ***\n");
116 for (i
= 0; i
< HeaderBufferSize
; i
++) {
118 DbgPrint("\n%04X ", i
);
119 DbgPrint("%02X ", *p
++);
122 DbgPrint("\nFRAME:");
125 Length
= (LookaheadBufferSize
< 64)? LookaheadBufferSize
: 64;
126 for (i
= 0; i
< Length
; i
++) {
128 DbgPrint("\n%04X ", i
);
129 DbgPrint("%02X ", *p
++);
132 DbgPrint("\n*** RECEIVE PACKET STOP ***\n");
140 PLOGICAL_ADAPTER Adapter
,
141 NDIS_HANDLE MacReceiveContext
,
143 UINT HeaderBufferSize
,
144 PVOID LookaheadBuffer
,
145 UINT LookaheadBufferSize
,
148 * FUNCTION: Indicate received data to bound protocols
150 * Adapter = Pointer to logical adapter
151 * MacReceiveContext = MAC receive context handle
152 * HeaderBuffer = Pointer to header buffer
153 * HeaderBufferSize = Size of header buffer
154 * LookaheadBuffer = Pointer to lookahead buffer
155 * LookaheadBufferSize = Size of lookahead buffer
156 * PacketSize = Total size of received packet
160 PLIST_ENTRY CurrentEntry
;
161 PADAPTER_BINDING AdapterBinding
;
163 NDIS_DbgPrint(DEBUG_MINIPORT
, ("Called. Adapter (0x%X) HeaderBuffer (0x%X) "
164 "HeaderBufferSize (0x%X) LookaheadBuffer (0x%X) LookaheadBufferSize (0x%X).\n",
165 Adapter
, HeaderBuffer
, HeaderBufferSize
, LookaheadBuffer
, LookaheadBufferSize
));
167 MiniDisplayPacket2(HeaderBuffer
, HeaderBufferSize
, LookaheadBuffer
, LookaheadBufferSize
);
169 NDIS_DbgPrint(MAX_TRACE
, ("acquiring miniport block lock\n"));
170 KeAcquireSpinLock(&Adapter
->NdisMiniportBlock
.Lock
, &OldIrql
);
172 CurrentEntry
= Adapter
->ProtocolListHead
.Flink
;
173 NDIS_DbgPrint(DEBUG_MINIPORT
, ("CurrentEntry = %x\n", CurrentEntry
));
175 if (CurrentEntry
== &Adapter
->ProtocolListHead
)
177 NDIS_DbgPrint(DEBUG_MINIPORT
, ("WARNING: No upper protocol layer.\n"));
180 while (CurrentEntry
!= &Adapter
->ProtocolListHead
)
182 AdapterBinding
= CONTAINING_RECORD(CurrentEntry
, ADAPTER_BINDING
, AdapterListEntry
);
183 NDIS_DbgPrint(DEBUG_MINIPORT
, ("AdapterBinding = %x\n", AdapterBinding
));
188 NDIS_DbgPrint(MIN_TRACE
, ("AdapterBinding was null\n"));
192 if(!AdapterBinding
->ProtocolBinding
)
194 NDIS_DbgPrint(MIN_TRACE
, ("AdapterBinding->ProtocolBinding was null\n"));
198 if(!AdapterBinding
->ProtocolBinding
->Chars
.ReceiveHandler
)
200 NDIS_DbgPrint(MIN_TRACE
, ("AdapterBinding->ProtocolBinding->Chars.ReceiveHandler was null\n"));
207 ("XXX (%x) %x %x %x %x %x %x %x XXX\n",
208 *AdapterBinding
->ProtocolBinding
->Chars
.ReceiveHandler
,
209 AdapterBinding
->NdisOpenBlock
.ProtocolBindingContext
,
217 /* call the receive handler */
218 (*AdapterBinding
->ProtocolBinding
->Chars
.ReceiveHandler
)(
219 AdapterBinding
->NdisOpenBlock
.ProtocolBindingContext
,
227 CurrentEntry
= CurrentEntry
->Flink
;
230 KeReleaseSpinLock(&Adapter
->NdisMiniportBlock
.Lock
, OldIrql
);
232 NDIS_DbgPrint(MAX_TRACE
, ("Leaving.\n"));
237 MiniIndicateReceivePacket(
238 IN NDIS_HANDLE MiniportAdapterHandle
,
239 IN PPNDIS_PACKET PacketArray
,
240 IN UINT NumberOfPackets
)
242 * FUNCTION: receives miniport packet array indications
244 * MiniportAdapterHandle: Miniport handle for the adapter
245 * PacketArray: pointer to a list of packet pointers to indicate
246 * NumberOfPackets: number of packets to indicate
250 PLOGICAL_ADAPTER Adapter
= MiniportAdapterHandle
;
251 PLIST_ENTRY CurrentEntry
;
252 PADAPTER_BINDING AdapterBinding
;
256 KeAcquireSpinLock(&Adapter
->NdisMiniportBlock
.Lock
, &OldIrql
);
258 CurrentEntry
= Adapter
->ProtocolListHead
.Flink
;
260 while (CurrentEntry
!= &Adapter
->ProtocolListHead
)
262 AdapterBinding
= CONTAINING_RECORD(CurrentEntry
, ADAPTER_BINDING
, AdapterListEntry
);
264 for (i
= 0; i
< NumberOfPackets
; i
++)
266 (*AdapterBinding
->ProtocolBinding
->Chars
.ReceivePacketHandler
)(
267 AdapterBinding
->NdisOpenBlock
.ProtocolBindingContext
,
271 CurrentEntry
= CurrentEntry
->Flink
;
274 KeReleaseSpinLock(&Adapter
->NdisMiniportBlock
.Lock
, OldIrql
);
280 IN NDIS_HANDLE MiniportAdapterHandle
,
281 IN NDIS_STATUS Status
,
282 IN BOOLEAN AddressingReset
)
284 PLOGICAL_ADAPTER Adapter
= MiniportAdapterHandle
;
286 NDIS_DbgPrint(MIN_TRACE
, ("FIXME: MiniResetComplete is partially implemented\n"));
287 NdisMIndicateStatus(Adapter
, NDIS_STATUS_RESET_END
, NULL
, 0);
288 KeAcquireSpinLock(&Adapter
->NdisMiniportBlock
.Lock
, &OldIrql
);
289 Adapter
->MiniportBusy
= FALSE
;
290 KeReleaseSpinLock(&Adapter
->NdisMiniportBlock
.Lock
, OldIrql
);
297 IN PNDIS_HANDLE MiniportAdapterHandle
,
298 IN PNDIS_REQUEST Request
,
299 IN NDIS_STATUS Status
)
301 PLOGICAL_ADAPTER Adapter
= (PLOGICAL_ADAPTER
)MiniportAdapterHandle
;
302 PNDIS_REQUEST_MAC_BLOCK MacBlock
= (PNDIS_REQUEST_MAC_BLOCK
)Request
->MacReserved
;
305 NDIS_DbgPrint(DEBUG_MINIPORT
, ("Called.\n"));
307 KeRaiseIrql(DISPATCH_LEVEL
, &OldIrql
);
308 if( MacBlock
->Binding
->RequestCompleteHandler
) {
309 (*MacBlock
->Binding
->RequestCompleteHandler
)(
310 MacBlock
->Binding
->ProtocolBindingContext
,
314 KeAcquireSpinLockAtDpcLevel(&Adapter
->NdisMiniportBlock
.Lock
);
315 Adapter
->MiniportBusy
= FALSE
;
316 KeReleaseSpinLockFromDpcLevel(&Adapter
->NdisMiniportBlock
.Lock
);
317 KeLowerIrql(OldIrql
);
322 IN NDIS_HANDLE MiniportAdapterHandle
,
323 IN PNDIS_PACKET Packet
,
324 IN NDIS_STATUS Status
)
326 * FUNCTION: Forwards a message to the initiating protocol saying
327 * that a packet was handled
329 * NdisAdapterHandle = Handle input to MiniportInitialize
330 * Packet = Pointer to NDIS packet that was sent
331 * Status = Status of send operation
334 PLOGICAL_ADAPTER Adapter
= MiniportAdapterHandle
;
335 PADAPTER_BINDING AdapterBinding
;
338 NDIS_DbgPrint(DEBUG_MINIPORT
, ("Called.\n"));
340 AdapterBinding
= (PADAPTER_BINDING
)Packet
->Reserved
[0];
342 KeRaiseIrql(DISPATCH_LEVEL
, &OldIrql
);
343 (*AdapterBinding
->ProtocolBinding
->Chars
.SendCompleteHandler
)(
344 AdapterBinding
->NdisOpenBlock
.ProtocolBindingContext
,
347 KeAcquireSpinLockAtDpcLevel(&Adapter
->NdisMiniportBlock
.Lock
);
348 Adapter
->MiniportBusy
= FALSE
;
349 KeReleaseSpinLockFromDpcLevel(&Adapter
->NdisMiniportBlock
.Lock
);
350 KeLowerIrql(OldIrql
);
355 MiniSendResourcesAvailable(
356 IN NDIS_HANDLE MiniportAdapterHandle
)
365 MiniTransferDataComplete(
366 IN NDIS_HANDLE MiniportAdapterHandle
,
367 IN PNDIS_PACKET Packet
,
368 IN NDIS_STATUS Status
,
369 IN UINT BytesTransferred
)
371 PLOGICAL_ADAPTER Adapter
= MiniportAdapterHandle
;
372 PADAPTER_BINDING AdapterBinding
;
375 NDIS_DbgPrint(DEBUG_MINIPORT
, ("Called.\n"));
377 AdapterBinding
= (PADAPTER_BINDING
)Packet
->Reserved
[0];
379 KeRaiseIrql(DISPATCH_LEVEL
, &OldIrql
);
380 (*AdapterBinding
->ProtocolBinding
->Chars
.SendCompleteHandler
)(
381 AdapterBinding
->NdisOpenBlock
.ProtocolBindingContext
,
384 KeAcquireSpinLockAtDpcLevel(&Adapter
->NdisMiniportBlock
.Lock
);
385 Adapter
->MiniportBusy
= FALSE
;
386 KeReleaseSpinLockFromDpcLevel(&Adapter
->NdisMiniportBlock
.Lock
);
387 KeLowerIrql(OldIrql
);
392 MiniAdapterHasAddress(
393 PLOGICAL_ADAPTER Adapter
,
396 * FUNCTION: Determines whether a packet has the same destination address as an adapter
398 * Adapter = Pointer to logical adapter object
399 * Packet = Pointer to NDIS packet
401 * TRUE if the destination address is that of the adapter, FALSE if not
407 PNDIS_BUFFER NdisBuffer
;
410 NDIS_DbgPrint(DEBUG_MINIPORT
, ("Called.\n"));
415 NDIS_DbgPrint(MID_TRACE
, ("Adapter object was null\n"));
421 NDIS_DbgPrint(MID_TRACE
, ("Packet was null\n"));
426 NdisQueryPacket(Packet
, NULL
, NULL
, &NdisBuffer
, NULL
);
430 NDIS_DbgPrint(MID_TRACE
, ("Packet contains no buffers.\n"));
434 NdisQueryBuffer(NdisBuffer
, (PVOID
)&Start2
, &BufferLength
);
436 /* FIXME: Should handle fragmented packets */
438 switch (Adapter
->NdisMiniportBlock
.MediaType
)
440 case NdisMedium802_3
:
441 Length
= ETH_LENGTH_OF_ADDRESS
;
442 /* Destination address is the first field */
446 NDIS_DbgPrint(MIN_TRACE
, ("Adapter has unsupported media type (0x%X).\n", Adapter
->NdisMiniportBlock
.MediaType
));
450 if (BufferLength
< Length
)
452 NDIS_DbgPrint(MID_TRACE
, ("Buffer is too small.\n"));
456 Start1
= (PUCHAR
)&Adapter
->Address
;
457 NDIS_DbgPrint(MAX_TRACE
, ("packet address: %x:%x:%x:%x:%x:%x adapter address: %x:%x:%x:%x:%x:%x\n",
458 *((char *)Start1
), *(((char *)Start1
)+1), *(((char *)Start1
)+2), *(((char *)Start1
)+3), *(((char *)Start1
)+4), *(((char *)Start1
)+5),
459 *((char *)Start2
), *(((char *)Start2
)+1), *(((char *)Start2
)+2), *(((char *)Start2
)+3), *(((char *)Start2
)+4), *(((char *)Start2
)+5))
462 return (RtlCompareMemory((PVOID
)Start1
, (PVOID
)Start2
, Length
) == Length
);
468 PNDIS_STRING AdapterName
)
470 * FUNCTION: Finds an adapter object by name
472 * AdapterName = Pointer to name of adapter
474 * Pointer to logical adapter object, or NULL if none was found.
475 * If found, the adapter is referenced for the caller. The caller
476 * is responsible for dereferencing after use
480 PLIST_ENTRY CurrentEntry
;
481 PLOGICAL_ADAPTER Adapter
= 0;
485 NDIS_DbgPrint(DEBUG_MINIPORT
, ("Called.\n"));
487 if(IsListEmpty(&AdapterListHead
))
489 NDIS_DbgPrint(DEBUG_MINIPORT
, ("No registered miniports for protocol to bind to\n"));
493 KeAcquireSpinLock(&AdapterListLock
, &OldIrql
);
495 CurrentEntry
= AdapterListHead
.Flink
;
497 while (CurrentEntry
!= &AdapterListHead
)
499 Adapter
= CONTAINING_RECORD(CurrentEntry
, LOGICAL_ADAPTER
, ListEntry
);
503 NDIS_DbgPrint(DEBUG_MINIPORT
, ("Examining adapter 0x%lx\n", Adapter
));
504 NDIS_DbgPrint(DEBUG_MINIPORT
, ("AdapterName = %wZ\n", AdapterName
));
505 NDIS_DbgPrint(DEBUG_MINIPORT
, ("DeviceName = %wZ\n", &Adapter
->NdisMiniportBlock
.MiniportName
));
507 if (RtlCompareUnicodeString(AdapterName
, &Adapter
->NdisMiniportBlock
.MiniportName
, TRUE
) == 0)
513 CurrentEntry
= CurrentEntry
->Flink
;
516 KeReleaseSpinLock(&AdapterListLock
, OldIrql
);
520 NDIS_DbgPrint(DEBUG_MINIPORT
, ("Leaving. Adapter found at 0x%x\n", Adapter
));
524 NDIS_DbgPrint(DEBUG_MINIPORT
, ("Leaving (adapter not found).\n"));
532 MiniQueryInformation(
533 PLOGICAL_ADAPTER Adapter
,
539 * FUNCTION: Queries a logical adapter for properties
541 * Adapter = Pointer to the logical adapter object to query
542 * Oid = Specifies the Object ID to query for
543 * Size = Size of the passed buffer
544 * Buffer = Buffer for the output
545 * BytesWritten = Address of buffer to place number of bytes written
547 * If the specified buffer is too small, a new buffer is allocated,
548 * and the query is attempted again
550 * Status of operation
552 * Is there any way to use the buffer provided by the protocol?
555 NDIS_STATUS NdisStatus
;
559 NDIS_DbgPrint(DEBUG_MINIPORT
, ("Called.\n"));
561 /* call the miniport's queryinfo handler */
562 KeRaiseIrql(DISPATCH_LEVEL
, &OldIrql
);
563 NdisStatus
= (*Adapter
->NdisMiniportBlock
.DriverHandle
->MiniportCharacteristics
.QueryInformationHandler
)(
564 Adapter
->NdisMiniportBlock
.MiniportAdapterContext
,
570 KeLowerIrql(OldIrql
);
572 /* FIXME: Wait in pending case! */
578 MiniCheckForHang( PLOGICAL_ADAPTER Adapter
)
580 * FUNCTION: Checks to see if the miniport is hung
582 * Adapter = Pointer to the logical adapter object
584 * TRUE if the miniport is hung
585 * FALSE if the miniport is not hung
591 KeRaiseIrql(DISPATCH_LEVEL
, &OldIrql
);
592 if (Adapter
->NdisMiniportBlock
.DriverHandle
->MiniportCharacteristics
.CheckForHangHandler
)
593 Ret
= (*Adapter
->NdisMiniportBlock
.DriverHandle
->MiniportCharacteristics
.CheckForHangHandler
)(
594 Adapter
->NdisMiniportBlock
.MiniportAdapterContext
);
595 KeLowerIrql(OldIrql
);
602 PLOGICAL_ADAPTER Adapter
,
603 PBOOLEAN AddressingReset
)
605 * FUNCTION: Resets the miniport
607 * Adapter = Pointer to the logical adapter object
608 * AddressingReset = Set to TRUE if we need to call MiniportSetInformation later
610 * Status of the operation
616 if (Adapter
->MiniportBusy
) {
617 KeAcquireSpinLock(&Adapter
->NdisMiniportBlock
.Lock
, &OldIrql
);
618 MiniQueueWorkItem(Adapter
, NdisWorkItemResetRequested
, NULL
);
619 KeReleaseSpinLock(&Adapter
->NdisMiniportBlock
.Lock
, OldIrql
);
620 return NDIS_STATUS_PENDING
;
623 NdisMIndicateStatus(Adapter
, NDIS_STATUS_RESET_START
, NULL
, 0);
624 NdisMIndicateStatusComplete(Adapter
);
626 KeRaiseIrql(DISPATCH_LEVEL
, &OldIrql
);
627 Status
= (*Adapter
->NdisMiniportBlock
.DriverHandle
->MiniportCharacteristics
.ResetHandler
)(
628 Adapter
->NdisMiniportBlock
.MiniportAdapterContext
,
630 KeLowerIrql(OldIrql
);
632 if (Status
!= NDIS_STATUS_PENDING
) {
633 NdisMIndicateStatus(Adapter
, NDIS_STATUS_RESET_END
, NULL
, 0);
634 NdisMIndicateStatusComplete(Adapter
);
636 KeAcquireSpinLock(&Adapter
->NdisMiniportBlock
.Lock
, &OldIrql
);
637 Adapter
->MiniportBusy
= TRUE
;
638 KeReleaseSpinLock(&Adapter
->NdisMiniportBlock
.Lock
, OldIrql
);
647 PVOID DeferredContext
,
648 PVOID SystemArgument1
,
649 PVOID SystemArgument2
)
651 PLOGICAL_ADAPTER Adapter
= DeferredContext
;
652 BOOLEAN AddressingReset
= FALSE
;
655 if (MiniCheckForHang(Adapter
)) {
656 NDIS_DbgPrint(MIN_TRACE
, ("Miniport detected adapter hang\n"));
657 MiniReset(Adapter
, &AddressingReset
);
660 /* FIXME: We should call MiniportSetInformation if AddressingReset is TRUE */
667 PLOGICAL_ADAPTER Adapter
,
668 NDIS_WORK_ITEM_TYPE WorkItemType
,
669 PVOID WorkItemContext
)
671 * FUNCTION: Queues a work item for execution at a later time
673 * Adapter = Pointer to the logical adapter object to queue work item on
674 * WorkItemType = Type of work item to queue
675 * WorkItemContext = Pointer to context information for work item
677 * Adapter lock must be held when called
679 * Status of operation
682 PNDIS_MINIPORT_WORK_ITEM Item
;
684 NDIS_DbgPrint(MAX_TRACE
, ("Called.\n"));
687 ASSERT(KeGetCurrentIrql() >= DISPATCH_LEVEL
);
689 Item
= ExAllocatePool(NonPagedPool
, sizeof(NDIS_MINIPORT_WORK_ITEM
));
692 NDIS_DbgPrint(MIN_TRACE
, ("Insufficient resources.\n"));
693 return NDIS_STATUS_RESOURCES
;
696 Item
->WorkItemType
= WorkItemType
;
697 Item
->WorkItemContext
= WorkItemContext
;
699 /* safe due to adapter lock held */
700 Item
->Link
.Next
= NULL
;
701 if (!Adapter
->WorkQueueHead
)
703 Adapter
->WorkQueueHead
= Item
;
704 Adapter
->WorkQueueTail
= Item
;
708 Adapter
->WorkQueueTail
->Link
.Next
= (PSINGLE_LIST_ENTRY
)Item
;
709 Adapter
->WorkQueueTail
= Item
;
712 KeInsertQueueDpc(&Adapter
->NdisMiniportBlock
.DeferredDpc
, NULL
, NULL
);
714 return NDIS_STATUS_SUCCESS
;
721 PLOGICAL_ADAPTER Adapter
,
722 NDIS_WORK_ITEM_TYPE
*WorkItemType
,
723 PVOID
*WorkItemContext
)
725 * FUNCTION: Dequeues a work item from the work queue of a logical adapter
727 * Adapter = Pointer to the logical adapter object to dequeue work item from
728 * AdapterBinding = Address of buffer for adapter binding for this request
729 * WorkItemType = Address of buffer for work item type
730 * WorkItemContext = Address of buffer for pointer to context information
732 * Adapter lock must be held when called
734 * Status of operation
737 PNDIS_MINIPORT_WORK_ITEM Item
;
739 NDIS_DbgPrint(MAX_TRACE
, ("Called.\n"));
741 if (Adapter
->MiniportBusy
) {
742 NDIS_DbgPrint(MID_TRACE
, ("Waiting for miniport to become free.\n"));
743 KeInsertQueueDpc(&Adapter
->NdisMiniportBlock
.DeferredDpc
, NULL
, NULL
);
744 return NDIS_STATUS_FAILURE
;
747 Item
= Adapter
->WorkQueueHead
;
751 /* safe due to adapter lock held */
752 Adapter
->WorkQueueHead
= (PNDIS_MINIPORT_WORK_ITEM
)Item
->Link
.Next
;
754 if (Item
== Adapter
->WorkQueueTail
)
755 Adapter
->WorkQueueTail
= NULL
;
757 *WorkItemType
= Item
->WorkItemType
;
758 *WorkItemContext
= Item
->WorkItemContext
;
762 Adapter
->MiniportBusy
= TRUE
;
764 return NDIS_STATUS_SUCCESS
;
767 return NDIS_STATUS_FAILURE
;
773 PLOGICAL_ADAPTER Adapter
,
774 PNDIS_REQUEST NdisRequest
)
776 * FUNCTION: Sends a request to a miniport
778 * AdapterBinding = Pointer to binding used in the request
779 * NdisRequest = Pointer to NDIS request structure describing request
781 * Status of operation
786 NDIS_DbgPrint(DEBUG_MINIPORT
, ("Called.\n"));
788 Adapter
->NdisMiniportBlock
.MediaRequest
= NdisRequest
;
790 KeRaiseIrql(DISPATCH_LEVEL
, &OldIrql
);
791 switch (NdisRequest
->RequestType
)
793 case NdisRequestQueryInformation
:
794 Status
= (*Adapter
->NdisMiniportBlock
.DriverHandle
->MiniportCharacteristics
.QueryInformationHandler
)(
795 Adapter
->NdisMiniportBlock
.MiniportAdapterContext
,
796 NdisRequest
->DATA
.QUERY_INFORMATION
.Oid
,
797 NdisRequest
->DATA
.QUERY_INFORMATION
.InformationBuffer
,
798 NdisRequest
->DATA
.QUERY_INFORMATION
.InformationBufferLength
,
799 (PULONG
)&NdisRequest
->DATA
.QUERY_INFORMATION
.BytesWritten
,
800 (PULONG
)&NdisRequest
->DATA
.QUERY_INFORMATION
.BytesNeeded
);
803 case NdisRequestSetInformation
:
804 Status
= (*Adapter
->NdisMiniportBlock
.DriverHandle
->MiniportCharacteristics
.SetInformationHandler
)(
805 Adapter
->NdisMiniportBlock
.MiniportAdapterContext
,
806 NdisRequest
->DATA
.SET_INFORMATION
.Oid
,
807 NdisRequest
->DATA
.SET_INFORMATION
.InformationBuffer
,
808 NdisRequest
->DATA
.SET_INFORMATION
.InformationBufferLength
,
809 (PULONG
)&NdisRequest
->DATA
.SET_INFORMATION
.BytesRead
,
810 (PULONG
)&NdisRequest
->DATA
.SET_INFORMATION
.BytesNeeded
);
814 Status
= NDIS_STATUS_FAILURE
;
817 if (Status
== NDIS_STATUS_PENDING
) {
818 KeAcquireSpinLockAtDpcLevel(&Adapter
->NdisMiniportBlock
.Lock
);
819 Adapter
->MiniportBusy
= TRUE
;
820 KeReleaseSpinLockFromDpcLevel(&Adapter
->NdisMiniportBlock
.Lock
);
823 KeLowerIrql(OldIrql
);
831 #undef NdisMQueryInformationComplete
834 NdisMQueryInformationComplete(
835 IN NDIS_HANDLE MiniportAdapterHandle
,
836 IN NDIS_STATUS Status
)
838 PLOGICAL_ADAPTER Adapter
=
839 (PLOGICAL_ADAPTER
)MiniportAdapterHandle
;
842 KeRaiseIrql(DISPATCH_LEVEL
, &OldIrql
);
843 if( Adapter
->NdisMiniportBlock
.QueryCompleteHandler
)
844 (Adapter
->NdisMiniportBlock
.QueryCompleteHandler
)(MiniportAdapterHandle
, Status
);
845 KeAcquireSpinLockAtDpcLevel(&Adapter
->NdisMiniportBlock
.Lock
);
846 Adapter
->MiniportBusy
= FALSE
;
847 KeReleaseSpinLockFromDpcLevel(&Adapter
->NdisMiniportBlock
.Lock
);
848 KeLowerIrql(OldIrql
);
851 VOID NTAPI
MiniportWorker(IN PVOID WorkItem
)
853 PNDIS_WORK_ITEM NdisWorkItem
= WorkItem
;
854 PLOGICAL_ADAPTER Adapter
= GET_LOGICAL_ADAPTER(NdisWorkItem
->Context
);
855 KIRQL OldIrql
, RaiseOldIrql
;
856 NDIS_STATUS NdisStatus
;
857 PVOID WorkItemContext
;
858 NDIS_WORK_ITEM_TYPE WorkItemType
;
859 BOOLEAN AddressingReset
;
861 KeAcquireSpinLock(&Adapter
->NdisMiniportBlock
.Lock
, &OldIrql
);
865 (Adapter
, &WorkItemType
, &WorkItemContext
);
867 KeReleaseSpinLock(&Adapter
->NdisMiniportBlock
.Lock
, OldIrql
);
869 if (NdisStatus
== NDIS_STATUS_SUCCESS
)
871 switch (WorkItemType
)
873 case NdisWorkItemSend
:
875 * called by ProSend when protocols want to send packets to the miniport
878 MiniDisplayPacket((PNDIS_PACKET
)WorkItemContext
);
880 if(Adapter
->NdisMiniportBlock
.DriverHandle
->MiniportCharacteristics
.SendPacketsHandler
)
882 if(Adapter
->NdisMiniportBlock
.Flags
& NDIS_ATTRIBUTE_DESERIALIZE
)
884 NDIS_DbgPrint(MAX_TRACE
, ("Calling miniport's SendPackets handler\n"));
885 (*Adapter
->NdisMiniportBlock
.DriverHandle
->MiniportCharacteristics
.SendPacketsHandler
)(
886 Adapter
->NdisMiniportBlock
.MiniportAdapterContext
, (PPNDIS_PACKET
)&WorkItemContext
, 1);
887 NdisStatus
= NDIS_GET_PACKET_STATUS((PNDIS_PACKET
)WorkItemContext
);
891 /* SendPackets is called at DISPATCH_LEVEL for all serialized miniports */
892 KeRaiseIrql(DISPATCH_LEVEL
, &RaiseOldIrql
);
894 NDIS_DbgPrint(MAX_TRACE
, ("Calling miniport's SendPackets handler\n"));
895 (*Adapter
->NdisMiniportBlock
.DriverHandle
->MiniportCharacteristics
.SendPacketsHandler
)(
896 Adapter
->NdisMiniportBlock
.MiniportAdapterContext
, (PPNDIS_PACKET
)&WorkItemContext
, 1);
898 KeLowerIrql(RaiseOldIrql
);
900 NdisStatus
= NDIS_GET_PACKET_STATUS((PNDIS_PACKET
)WorkItemContext
);
901 if( NdisStatus
== NDIS_STATUS_RESOURCES
) {
902 KeAcquireSpinLock(&Adapter
->NdisMiniportBlock
.Lock
, &OldIrql
);
903 MiniQueueWorkItem(Adapter
, WorkItemType
, WorkItemContext
);
904 KeReleaseSpinLock(&Adapter
->NdisMiniportBlock
.Lock
, OldIrql
);
911 if(Adapter
->NdisMiniportBlock
.Flags
& NDIS_ATTRIBUTE_DESERIALIZE
)
913 NDIS_DbgPrint(MAX_TRACE
, ("Calling miniport's Send handler\n"));
914 NdisStatus
= (*Adapter
->NdisMiniportBlock
.DriverHandle
->MiniportCharacteristics
.SendHandler
)(
915 Adapter
->NdisMiniportBlock
.MiniportAdapterContext
, (PNDIS_PACKET
)WorkItemContext
, 0);
916 NDIS_DbgPrint(MAX_TRACE
, ("back from miniport's send handler\n"));
920 /* Send is called at DISPATCH_LEVEL for all serialized miniports */
921 KeRaiseIrql(DISPATCH_LEVEL
, &RaiseOldIrql
);
922 NDIS_DbgPrint(MAX_TRACE
, ("Calling miniport's Send handler\n"));
923 NdisStatus
= (*Adapter
->NdisMiniportBlock
.DriverHandle
->MiniportCharacteristics
.SendHandler
)(
924 Adapter
->NdisMiniportBlock
.MiniportAdapterContext
, (PNDIS_PACKET
)WorkItemContext
, 0);
925 NDIS_DbgPrint(MAX_TRACE
, ("back from miniport's send handler\n"));
926 KeLowerIrql(RaiseOldIrql
);
927 if( NdisStatus
== NDIS_STATUS_RESOURCES
) {
928 KeAcquireSpinLock(&Adapter
->NdisMiniportBlock
.Lock
, &OldIrql
);
929 MiniQueueWorkItem(Adapter
, WorkItemType
, WorkItemContext
);
930 KeReleaseSpinLock(&Adapter
->NdisMiniportBlock
.Lock
, OldIrql
);
936 if( NdisStatus
!= NDIS_STATUS_PENDING
) {
938 ( Adapter
, (PNDIS_PACKET
)WorkItemContext
, NdisStatus
);
942 case NdisWorkItemSendLoopback
:
944 * called by ProSend when protocols want to send loopback packets
946 /* XXX atm ProIndicatePacket sends a packet up via the loopback adapter only */
947 NdisStatus
= ProIndicatePacket(Adapter
, (PNDIS_PACKET
)WorkItemContext
);
949 if( NdisStatus
!= NDIS_STATUS_PENDING
)
950 MiniSendComplete((NDIS_HANDLE
)Adapter
, (PNDIS_PACKET
)WorkItemContext
, NdisStatus
);
953 case NdisWorkItemReturnPackets
:
956 case NdisWorkItemResetRequested
:
957 NdisMIndicateStatus(Adapter
, NDIS_STATUS_RESET_START
, NULL
, 0);
958 NdisMIndicateStatusComplete(Adapter
);
960 KeRaiseIrql(DISPATCH_LEVEL
, &OldIrql
);
961 NdisStatus
= (*Adapter
->NdisMiniportBlock
.DriverHandle
->MiniportCharacteristics
.ResetHandler
)(
962 Adapter
->NdisMiniportBlock
.MiniportAdapterContext
,
964 KeLowerIrql(OldIrql
);
966 if (NdisStatus
== NDIS_STATUS_PENDING
)
969 MiniResetComplete(Adapter
, NdisStatus
, AddressingReset
);
972 case NdisWorkItemResetInProgress
:
975 case NdisWorkItemMiniportCallback
:
978 case NdisWorkItemRequest
:
979 NdisStatus
= MiniDoRequest(Adapter
, (PNDIS_REQUEST
)WorkItemContext
);
981 if (NdisStatus
== NDIS_STATUS_PENDING
)
984 switch (((PNDIS_REQUEST
)WorkItemContext
)->RequestType
)
986 case NdisRequestQueryInformation
:
987 NdisMQueryInformationComplete((NDIS_HANDLE
)Adapter
, NdisStatus
);
988 MiniRequestComplete( (NDIS_HANDLE
)Adapter
, (PNDIS_REQUEST
)WorkItemContext
, NdisStatus
);
991 case NdisRequestSetInformation
:
992 NdisMSetInformationComplete((NDIS_HANDLE
)Adapter
, NdisStatus
);
993 MiniRequestComplete( (NDIS_HANDLE
)Adapter
, (PNDIS_REQUEST
)WorkItemContext
, NdisStatus
);
997 NDIS_DbgPrint(MIN_TRACE
, ("Unknown NDIS request type.\n"));
1003 NDIS_DbgPrint(MIN_TRACE
, ("Unknown NDIS work item type (%d).\n", WorkItemType
));
1008 if( NdisStatus
!= NDIS_STATUS_PENDING
) {
1009 KeAcquireSpinLock(&Adapter
->NdisMiniportBlock
.Lock
, &OldIrql
);
1010 Adapter
->MiniportBusy
= FALSE
;
1011 KeReleaseSpinLock(&Adapter
->NdisMiniportBlock
.Lock
, OldIrql
);
1014 ExFreePool(WorkItem
);
1019 VOID NTAPI
MiniportDpc(
1021 IN PVOID DeferredContext
,
1022 IN PVOID SystemArgument1
,
1023 IN PVOID SystemArgument2
)
1025 * FUNCTION: Deferred routine to handle serialization
1027 * Dpc = Pointer to DPC object
1028 * DeferredContext = Pointer to context information (LOGICAL_ADAPTER)
1029 * SystemArgument1 = Unused
1030 * SystemArgument2 = Unused
1033 PNDIS_WORK_ITEM NdisWorkItem
;
1034 PWORK_QUEUE_ITEM WorkItem
;
1036 NDIS_DbgPrint(DEBUG_MINIPORT
, ("Called.\n"));
1038 NdisWorkItem
= ExAllocatePool(NonPagedPool
, sizeof(NDIS_WORK_ITEM
));
1039 if (!NdisWorkItem
) return;
1041 WorkItem
= (PWORK_QUEUE_ITEM
)NdisWorkItem
->WrapperReserved
;
1043 NdisWorkItem
->Context
= DeferredContext
;
1045 ExInitializeWorkItem(WorkItem
, MiniportWorker
, NdisWorkItem
);
1047 ExQueueWorkItem(WorkItem
, CriticalWorkQueue
);
1054 IN NDIS_HANDLE MiniportHandle
,
1055 IN NDIS_STATUS GeneralStatus
,
1056 IN PVOID StatusBuffer
,
1057 IN UINT StatusBufferSize
)
1059 PLOGICAL_ADAPTER Adapter
= MiniportHandle
;
1060 PLIST_ENTRY CurrentEntry
;
1061 PADAPTER_BINDING AdapterBinding
;
1064 KeAcquireSpinLock(&Adapter
->NdisMiniportBlock
.Lock
, &OldIrql
);
1066 CurrentEntry
= Adapter
->ProtocolListHead
.Flink
;
1068 while (CurrentEntry
!= &Adapter
->ProtocolListHead
)
1070 AdapterBinding
= CONTAINING_RECORD(CurrentEntry
, ADAPTER_BINDING
, AdapterListEntry
);
1072 (*AdapterBinding
->ProtocolBinding
->Chars
.StatusHandler
)(
1073 AdapterBinding
->NdisOpenBlock
.ProtocolBindingContext
,
1078 CurrentEntry
= CurrentEntry
->Flink
;
1081 KeReleaseSpinLock(&Adapter
->NdisMiniportBlock
.Lock
, OldIrql
);
1088 IN NDIS_HANDLE MiniportAdapterHandle
)
1090 PLOGICAL_ADAPTER Adapter
= MiniportAdapterHandle
;
1091 PLIST_ENTRY CurrentEntry
;
1092 PADAPTER_BINDING AdapterBinding
;
1095 KeAcquireSpinLock(&Adapter
->NdisMiniportBlock
.Lock
, &OldIrql
);
1097 CurrentEntry
= Adapter
->ProtocolListHead
.Flink
;
1099 while (CurrentEntry
!= &Adapter
->ProtocolListHead
)
1101 AdapterBinding
= CONTAINING_RECORD(CurrentEntry
, ADAPTER_BINDING
, AdapterListEntry
);
1103 (*AdapterBinding
->ProtocolBinding
->Chars
.StatusCompleteHandler
)(
1104 AdapterBinding
->NdisOpenBlock
.ProtocolBindingContext
);
1106 CurrentEntry
= CurrentEntry
->Flink
;
1109 KeReleaseSpinLock(&Adapter
->NdisMiniportBlock
.Lock
, OldIrql
);
1119 IN NDIS_HANDLE LogHandle
)
1131 IN NDIS_HANDLE MiniportAdapterHandle
,
1133 OUT PNDIS_HANDLE LogHandle
)
1137 return NDIS_STATUS_FAILURE
;
1146 NdisMDeregisterAdapterShutdownHandler(
1147 IN NDIS_HANDLE MiniportHandle
)
1149 * FUNCTION: de-registers a shutdown handler
1150 * ARGUMENTS: MiniportHandle: Handle passed into MiniportInitialize
1153 PLOGICAL_ADAPTER Adapter
= (PLOGICAL_ADAPTER
)MiniportHandle
;
1155 NDIS_DbgPrint(DEBUG_MINIPORT
, ("Called.\n"));
1157 if(Adapter
->BugcheckContext
->ShutdownHandler
)
1158 KeDeregisterBugCheckCallback(Adapter
->BugcheckContext
->CallbackRecord
);
1168 IN NDIS_HANDLE LogHandle
)
1176 #undef NdisMIndicateStatus
1179 NdisMIndicateStatus(
1180 IN NDIS_HANDLE MiniportAdapterHandle
,
1181 IN NDIS_STATUS GeneralStatus
,
1182 IN PVOID StatusBuffer
,
1183 IN UINT StatusBufferSize
)
1185 MiniStatus(MiniportAdapterHandle
, GeneralStatus
, StatusBuffer
, StatusBufferSize
);
1191 #undef NdisMIndicateStatusComplete
1194 NdisMIndicateStatusComplete(
1195 IN NDIS_HANDLE MiniportAdapterHandle
)
1197 MiniStatusComplete(MiniportAdapterHandle
);
1206 NdisInitializeWrapper(
1207 OUT PNDIS_HANDLE NdisWrapperHandle
,
1208 IN PVOID SystemSpecific1
,
1209 IN PVOID SystemSpecific2
,
1210 IN PVOID SystemSpecific3
)
1212 * FUNCTION: Notifies the NDIS library that a new miniport is initializing
1214 * NdisWrapperHandle = Address of buffer to place NDIS wrapper handle
1215 * SystemSpecific1 = Pointer to the driver's driver object
1216 * SystemSpecific2 = Pointer to the driver's registry path
1217 * SystemSpecific3 = Always NULL
1219 * - SystemSpecific2 goes invalid so we copy it
1222 PNDIS_M_DRIVER_BLOCK Miniport
;
1223 PUNICODE_STRING RegistryPath
;
1224 WCHAR
*RegistryBuffer
;
1226 NDIS_DbgPrint(MAX_TRACE
, ("Called.\n"));
1228 ASSERT(NdisWrapperHandle
);
1230 *NdisWrapperHandle
= NULL
;
1232 #if BREAK_ON_MINIPORT_INIT
1233 __asm__ ("int $3\n");
1236 Miniport
= ExAllocatePool(NonPagedPool
, sizeof(NDIS_M_DRIVER_BLOCK
));
1240 NDIS_DbgPrint(MIN_TRACE
, ("Insufficient resources.\n"));
1244 RtlZeroMemory(Miniport
, sizeof(NDIS_M_DRIVER_BLOCK
));
1246 KeInitializeSpinLock(&Miniport
->Lock
);
1248 Miniport
->DriverObject
= (PDRIVER_OBJECT
)SystemSpecific1
;
1250 /* set the miniport's driver registry path */
1251 RegistryPath
= ExAllocatePool(PagedPool
, sizeof(UNICODE_STRING
));
1254 ExFreePool(Miniport
);
1255 NDIS_DbgPrint(MIN_TRACE
, ("Insufficient resources.\n"));
1259 RegistryPath
->Length
= ((PUNICODE_STRING
)SystemSpecific2
)->Length
;
1260 RegistryPath
->MaximumLength
= RegistryPath
->Length
+ sizeof(WCHAR
); /* room for 0-term */
1262 RegistryBuffer
= ExAllocatePool(PagedPool
, RegistryPath
->MaximumLength
);
1265 NDIS_DbgPrint(MIN_TRACE
, ("Insufficient resources.\n"));
1266 ExFreePool(Miniport
);
1267 ExFreePool(RegistryPath
);
1271 RtlCopyMemory(RegistryBuffer
, ((PUNICODE_STRING
)SystemSpecific2
)->Buffer
, RegistryPath
->Length
);
1272 RegistryBuffer
[RegistryPath
->Length
/sizeof(WCHAR
)] = 0;
1274 RegistryPath
->Buffer
= RegistryBuffer
;
1275 Miniport
->RegistryPath
= RegistryPath
;
1277 InitializeListHead(&Miniport
->DeviceList
);
1279 /* Put miniport in global miniport list */
1280 ExInterlockedInsertTailList(&MiniportListHead
, &Miniport
->ListEntry
, &MiniportListLock
);
1282 *NdisWrapperHandle
= Miniport
;
1286 VOID NTAPI
NdisIBugcheckCallback(
1290 * FUNCTION: Internal callback for handling bugchecks - calls adapter's shutdown handler
1292 * Buffer: Pointer to a bugcheck callback context
1296 PMINIPORT_BUGCHECK_CONTEXT Context
= (PMINIPORT_BUGCHECK_CONTEXT
)Buffer
;
1297 ADAPTER_SHUTDOWN_HANDLER sh
= (ADAPTER_SHUTDOWN_HANDLER
)Context
->ShutdownHandler
;
1299 NDIS_DbgPrint(DEBUG_MINIPORT
, ("Called.\n"));
1302 sh(Context
->DriverContext
);
1311 NdisMRegisterAdapterShutdownHandler(
1312 IN NDIS_HANDLE MiniportHandle
,
1313 IN PVOID ShutdownContext
,
1314 IN ADAPTER_SHUTDOWN_HANDLER ShutdownHandler
)
1316 * FUNCTION: Register a shutdown handler for an adapter
1318 * MiniportHandle: Handle originally passed into MiniportInitialize
1319 * ShutdownContext: Pre-initialized bugcheck context
1320 * ShutdownHandler: Function to call to handle the bugcheck
1322 * - I'm not sure about ShutdownContext
1325 PLOGICAL_ADAPTER Adapter
= (PLOGICAL_ADAPTER
)MiniportHandle
;
1326 PMINIPORT_BUGCHECK_CONTEXT BugcheckContext
= Adapter
->BugcheckContext
;
1328 NDIS_DbgPrint(DEBUG_MINIPORT
, ("Called.\n"));
1333 BugcheckContext
= ExAllocatePool(NonPagedPool
, sizeof(MINIPORT_BUGCHECK_CONTEXT
));
1334 if(!BugcheckContext
)
1336 NDIS_DbgPrint(MIN_TRACE
, ("Insufficient resources.\n"));
1340 BugcheckContext
->ShutdownHandler
= ShutdownHandler
;
1341 BugcheckContext
->DriverContext
= ShutdownContext
;
1343 BugcheckContext
->CallbackRecord
= ExAllocatePool(NonPagedPool
, sizeof(KBUGCHECK_CALLBACK_RECORD
));
1345 KeInitializeCallbackRecord(BugcheckContext
->CallbackRecord
);
1347 KeRegisterBugCheckCallback(BugcheckContext
->CallbackRecord
, NdisIBugcheckCallback
,
1348 BugcheckContext
, sizeof(BugcheckContext
), (PUCHAR
)"Ndis Miniport");
1354 PLOGICAL_ADAPTER Adapter
,
1355 NDIS_OID AddressOID
)
1357 * FUNCTION: Queries miniport for information
1359 * Adapter = Pointer to logical adapter
1360 * AddressOID = OID to use to query for current address
1362 * Status of operation
1366 NDIS_STATUS NdisStatus
;
1368 NDIS_DbgPrint(MAX_TRACE
, ("Called.\n"));
1370 /* Get MAC options for adapter */
1371 NdisStatus
= MiniQueryInformation(Adapter
, OID_GEN_MAC_OPTIONS
, sizeof(UINT
),
1372 &Adapter
->NdisMiniportBlock
.MacOptions
,
1375 if (NdisStatus
!= NDIS_STATUS_SUCCESS
)
1377 NDIS_DbgPrint(MIN_TRACE
, ("OID_GEN_MAC_OPTIONS failed. NdisStatus (0x%X).\n", NdisStatus
));
1381 NDIS_DbgPrint(DEBUG_MINIPORT
, ("MacOptions (0x%X).\n", Adapter
->NdisMiniportBlock
.MacOptions
));
1383 /* Get current hardware address of adapter */
1384 NdisStatus
= MiniQueryInformation(Adapter
, AddressOID
, Adapter
->AddressLength
,
1385 &Adapter
->Address
, &BytesWritten
);
1387 if (NdisStatus
!= NDIS_STATUS_SUCCESS
)
1389 NDIS_DbgPrint(MIN_TRACE
, ("Address OID (0x%X) failed. NdisStatus (0x%X).\n", AddressOID
, NdisStatus
));
1397 PUCHAR A
= (PUCHAR
)&Adapter
->Address
.Type
.Medium802_3
;
1399 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]));
1403 /* Get maximum lookahead buffer size of adapter */
1404 NdisStatus
= MiniQueryInformation(Adapter
, OID_GEN_MAXIMUM_LOOKAHEAD
, sizeof(ULONG
),
1405 &Adapter
->NdisMiniportBlock
.MaximumLookahead
, &BytesWritten
);
1407 if (NdisStatus
!= NDIS_STATUS_SUCCESS
)
1409 NDIS_DbgPrint(MIN_TRACE
, ("OID_GEN_MAXIMUM_LOOKAHEAD failed. NdisStatus (0x%X).\n", NdisStatus
));
1413 NDIS_DbgPrint(DEBUG_MINIPORT
, ("MaxLookaheadLength (0x%X).\n", Adapter
->NdisMiniportBlock
.MaximumLookahead
));
1415 /* Get current lookahead buffer size of adapter */
1416 NdisStatus
= MiniQueryInformation(Adapter
, OID_GEN_CURRENT_LOOKAHEAD
, sizeof(ULONG
),
1417 &Adapter
->NdisMiniportBlock
.CurrentLookahead
, &BytesWritten
);
1419 if (NdisStatus
!= NDIS_STATUS_SUCCESS
)
1421 NDIS_DbgPrint(MIN_TRACE
, ("OID_GEN_CURRENT_LOOKAHEAD failed. NdisStatus (0x%X).\n", NdisStatus
));
1425 NdisStatus
= MiniQueryInformation(Adapter
, OID_GEN_MAXIMUM_SEND_PACKETS
, sizeof(ULONG
),
1426 &Adapter
->NdisMiniportBlock
.MaxSendPackets
, &BytesWritten
);
1428 if (NdisStatus
!= NDIS_STATUS_SUCCESS
)
1430 NDIS_DbgPrint(MIN_TRACE
, ("OID_GEN_MAXIMUM_SEND_PACKETS failed. NdisStatus (0x%X).\n", NdisStatus
));
1432 /* Set it to 1 if it fails because some drivers don't support this (?)*/
1433 Adapter
->NdisMiniportBlock
.MaxSendPackets
= 1;
1436 NDIS_DbgPrint(DEBUG_MINIPORT
, ("CurLookaheadLength (0x%X).\n", Adapter
->NdisMiniportBlock
.CurrentLookahead
));
1438 if (Adapter
->NdisMiniportBlock
.MaximumLookahead
!= 0)
1440 Adapter
->LookaheadLength
= Adapter
->NdisMiniportBlock
.MaximumLookahead
+ Adapter
->MediumHeaderSize
;
1441 Adapter
->LookaheadBuffer
= ExAllocatePool(NonPagedPool
, Adapter
->LookaheadLength
);
1443 if (!Adapter
->LookaheadBuffer
)
1444 return NDIS_STATUS_RESOURCES
;
1447 return STATUS_SUCCESS
;
1453 NdisIForwardIrpAndWaitCompletionRoutine(
1458 PKEVENT Event
= Context
;
1460 if (Irp
->PendingReturned
)
1461 KeSetEvent(Event
, IO_NO_INCREMENT
, FALSE
);
1463 return STATUS_MORE_PROCESSING_REQUIRED
;
1469 NdisIForwardIrpAndWait(PLOGICAL_ADAPTER Adapter
, PIRP Irp
)
1474 KeInitializeEvent(&Event
, NotificationEvent
, FALSE
);
1475 IoCopyCurrentIrpStackLocationToNext(Irp
);
1476 IoSetCompletionRoutine(Irp
, NdisIForwardIrpAndWaitCompletionRoutine
, &Event
,
1478 Status
= IoCallDriver(Adapter
->NdisMiniportBlock
.NextDeviceObject
, Irp
);
1479 if (Status
== STATUS_PENDING
)
1481 KeWaitForSingleObject(&Event
, Executive
, KernelMode
, FALSE
, NULL
);
1482 Status
= Irp
->IoStatus
.Status
;
1490 NdisIPnPStartDevice(
1491 IN PDEVICE_OBJECT DeviceObject
,
1494 * FUNCTION: Handle the PnP start device event
1496 * DeviceObejct = Functional Device Object
1497 * Irp = IRP_MN_START_DEVICE I/O request packet
1499 * Status of operation
1502 PIO_STACK_LOCATION Stack
= IoGetCurrentIrpStackLocation(Irp
);
1503 PLOGICAL_ADAPTER Adapter
= (PLOGICAL_ADAPTER
)DeviceObject
->DeviceExtension
;
1504 NDIS_WRAPPER_CONTEXT WrapperContext
;
1505 NDIS_STATUS NdisStatus
;
1506 NDIS_STATUS OpenErrorStatus
;
1508 UINT SelectedMediumIndex
= 0;
1509 NDIS_OID AddressOID
;
1510 BOOLEAN Success
= FALSE
;
1511 ULONG ResourceCount
;
1512 ULONG ResourceListSize
;
1513 UNICODE_STRING ParamName
;
1514 PNDIS_CONFIGURATION_PARAMETER ConfigParam
;
1515 NDIS_HANDLE ConfigHandle
;
1517 LARGE_INTEGER Timeout
;
1518 /* FIXME - KIRQL OldIrql; */
1521 * Prepare wrapper context used by HW and configuration routines.
1524 NDIS_DbgPrint(DEBUG_MINIPORT
, ("Start Device %wZ\n", &Adapter
->NdisMiniportBlock
.MiniportName
));
1526 NDIS_DbgPrint(MAX_TRACE
, ("Inserting adapter 0x%x into adapter list\n", Adapter
));
1528 /* Put adapter in global adapter list */
1529 ExInterlockedInsertTailList(&AdapterListHead
, &Adapter
->ListEntry
, &AdapterListLock
);
1531 Status
= IoOpenDeviceRegistryKey(
1532 Adapter
->NdisMiniportBlock
.PhysicalDeviceObject
, PLUGPLAY_REGKEY_DRIVER
,
1533 KEY_ALL_ACCESS
, &WrapperContext
.RegistryHandle
);
1534 if (!NT_SUCCESS(Status
))
1536 NDIS_DbgPrint(MIN_TRACE
,("failed to open adapter-specific reg key\n"));
1537 ExInterlockedRemoveEntryList( &Adapter
->ListEntry
, &AdapterListLock
);
1541 NDIS_DbgPrint(MAX_TRACE
, ("opened device reg key\n"));
1543 WrapperContext
.DeviceObject
= Adapter
->NdisMiniportBlock
.DeviceObject
;
1546 * Store the adapter resources used by HW routines such as
1547 * NdisMQueryAdapterResources.
1550 if (Stack
->Parameters
.StartDevice
.AllocatedResources
!= NULL
)
1552 ResourceCount
= Stack
->Parameters
.StartDevice
.AllocatedResources
->List
[0].
1553 PartialResourceList
.Count
;
1555 FIELD_OFFSET(CM_RESOURCE_LIST
, List
[0].PartialResourceList
.
1556 PartialDescriptors
[ResourceCount
]);
1558 Adapter
->NdisMiniportBlock
.AllocatedResources
=
1559 ExAllocatePool(PagedPool
, ResourceListSize
);
1560 if (Adapter
->NdisMiniportBlock
.AllocatedResources
== NULL
)
1562 ExInterlockedRemoveEntryList( &Adapter
->ListEntry
, &AdapterListLock
);
1563 return STATUS_INSUFFICIENT_RESOURCES
;
1566 RtlCopyMemory(Adapter
->NdisMiniportBlock
.AllocatedResources
,
1567 Stack
->Parameters
.StartDevice
.AllocatedResources
,
1571 if (Stack
->Parameters
.StartDevice
.AllocatedResourcesTranslated
!= NULL
)
1573 ResourceCount
= Stack
->Parameters
.StartDevice
.AllocatedResourcesTranslated
->List
[0].
1574 PartialResourceList
.Count
;
1576 FIELD_OFFSET(CM_RESOURCE_LIST
, List
[0].PartialResourceList
.
1577 PartialDescriptors
[ResourceCount
]);
1579 Adapter
->NdisMiniportBlock
.AllocatedResourcesTranslated
=
1580 ExAllocatePool(PagedPool
, ResourceListSize
);
1581 if (Adapter
->NdisMiniportBlock
.AllocatedResourcesTranslated
== NULL
)
1583 ExInterlockedRemoveEntryList( &Adapter
->ListEntry
, &AdapterListLock
);
1584 return STATUS_INSUFFICIENT_RESOURCES
;
1587 RtlCopyMemory(Adapter
->NdisMiniportBlock
.AllocatedResourcesTranslated
,
1588 Stack
->Parameters
.StartDevice
.AllocatedResourcesTranslated
,
1593 * Store the Bus Type, Bus Number and Slot information. It's used by
1594 * the hardware routines then.
1597 NdisOpenConfiguration(&NdisStatus
, &ConfigHandle
, (NDIS_HANDLE
)&WrapperContext
);
1599 Size
= sizeof(ULONG
);
1600 Status
= IoGetDeviceProperty(Adapter
->NdisMiniportBlock
.PhysicalDeviceObject
,
1601 DevicePropertyLegacyBusType
, Size
,
1602 &Adapter
->NdisMiniportBlock
.BusType
, &Size
);
1603 if (!NT_SUCCESS(Status
) || (INTERFACE_TYPE
)Adapter
->NdisMiniportBlock
.BusType
== InterfaceTypeUndefined
)
1605 NdisInitUnicodeString(&ParamName
, L
"BusType");
1606 NdisReadConfiguration(&NdisStatus
, &ConfigParam
, ConfigHandle
,
1607 &ParamName
, NdisParameterInteger
);
1608 if (NdisStatus
== NDIS_STATUS_SUCCESS
)
1609 Adapter
->NdisMiniportBlock
.BusType
= ConfigParam
->ParameterData
.IntegerData
;
1611 Adapter
->NdisMiniportBlock
.BusType
= Isa
;
1614 Status
= IoGetDeviceProperty(Adapter
->NdisMiniportBlock
.PhysicalDeviceObject
,
1615 DevicePropertyBusNumber
, Size
,
1616 &Adapter
->NdisMiniportBlock
.BusNumber
, &Size
);
1617 if (!NT_SUCCESS(Status
) || Adapter
->NdisMiniportBlock
.BusNumber
== 0xFFFFFFF0)
1619 NdisInitUnicodeString(&ParamName
, L
"BusNumber");
1620 NdisReadConfiguration(&NdisStatus
, &ConfigParam
, ConfigHandle
,
1621 &ParamName
, NdisParameterInteger
);
1622 if (NdisStatus
== NDIS_STATUS_SUCCESS
)
1623 Adapter
->NdisMiniportBlock
.BusNumber
= ConfigParam
->ParameterData
.IntegerData
;
1625 Adapter
->NdisMiniportBlock
.BusNumber
= 0;
1627 WrapperContext
.BusNumber
= Adapter
->NdisMiniportBlock
.BusNumber
;
1629 Status
= IoGetDeviceProperty(Adapter
->NdisMiniportBlock
.PhysicalDeviceObject
,
1630 DevicePropertyAddress
, Size
,
1631 &Adapter
->NdisMiniportBlock
.SlotNumber
, &Size
);
1632 if (!NT_SUCCESS(Status
) || Adapter
->NdisMiniportBlock
.SlotNumber
== (NDIS_INTERFACE_TYPE
)-1)
1634 NdisInitUnicodeString(&ParamName
, L
"SlotNumber");
1635 NdisReadConfiguration(&NdisStatus
, &ConfigParam
, ConfigHandle
,
1636 &ParamName
, NdisParameterInteger
);
1637 if (NdisStatus
== NDIS_STATUS_SUCCESS
)
1638 Adapter
->NdisMiniportBlock
.SlotNumber
= ConfigParam
->ParameterData
.IntegerData
;
1640 Adapter
->NdisMiniportBlock
.SlotNumber
= 0;
1644 /* Convert slotnumber to PCI_SLOT_NUMBER */
1645 ULONG PciSlotNumber
= Adapter
->NdisMiniportBlock
.SlotNumber
;
1646 PCI_SLOT_NUMBER SlotNumber
;
1648 SlotNumber
.u
.AsULONG
= 0;
1649 SlotNumber
.u
.bits
.DeviceNumber
= (PciSlotNumber
>> 16) & 0xFFFF;
1650 SlotNumber
.u
.bits
.FunctionNumber
= PciSlotNumber
& 0xFFFF;
1652 Adapter
->NdisMiniportBlock
.SlotNumber
= SlotNumber
.u
.AsULONG
;
1654 NdisCloseConfiguration(ConfigHandle
);
1656 /* Set handlers (some NDIS macros require these) */
1657 Adapter
->NdisMiniportBlock
.EthRxCompleteHandler
= EthFilterDprIndicateReceiveComplete
;
1658 Adapter
->NdisMiniportBlock
.EthRxIndicateHandler
= EthFilterDprIndicateReceive
;
1659 Adapter
->NdisMiniportBlock
.SendCompleteHandler
= MiniSendComplete
;
1660 Adapter
->NdisMiniportBlock
.SendResourcesHandler
= MiniSendResourcesAvailable
;
1661 Adapter
->NdisMiniportBlock
.ResetCompleteHandler
= MiniResetComplete
;
1662 Adapter
->NdisMiniportBlock
.TDCompleteHandler
= MiniTransferDataComplete
;
1663 Adapter
->NdisMiniportBlock
.PacketIndicateHandler
= MiniIndicateReceivePacket
;
1664 Adapter
->NdisMiniportBlock
.StatusHandler
= MiniStatus
;
1665 Adapter
->NdisMiniportBlock
.StatusCompleteHandler
= MiniStatusComplete
;
1668 * Call MiniportInitialize.
1671 NDIS_DbgPrint(MID_TRACE
, ("calling MiniportInitialize\n"));
1672 NdisStatus
= (*Adapter
->NdisMiniportBlock
.DriverHandle
->MiniportCharacteristics
.InitializeHandler
)(
1673 &OpenErrorStatus
, &SelectedMediumIndex
, &MediaArray
[0],
1674 MEDIA_ARRAY_SIZE
, Adapter
, (NDIS_HANDLE
)&WrapperContext
);
1676 ZwClose(WrapperContext
.RegistryHandle
);
1678 if (NdisStatus
!= NDIS_STATUS_SUCCESS
||
1679 SelectedMediumIndex
>= MEDIA_ARRAY_SIZE
)
1681 NDIS_DbgPrint(MIN_TRACE
, ("MiniportInitialize() failed for an adapter.\n"));
1682 ExInterlockedRemoveEntryList( &Adapter
->ListEntry
, &AdapterListLock
);
1683 if (NdisStatus
== NDIS_STATUS_SUCCESS
) NdisStatus
= NDIS_STATUS_FAILURE
;
1687 Adapter
->NdisMiniportBlock
.MediaType
= MediaArray
[SelectedMediumIndex
];
1689 switch (Adapter
->NdisMiniportBlock
.MediaType
)
1691 case NdisMedium802_3
:
1692 Adapter
->MediumHeaderSize
= 14; /* XXX figure out what to do about LLC */
1693 AddressOID
= OID_802_3_CURRENT_ADDRESS
;
1694 Adapter
->AddressLength
= ETH_LENGTH_OF_ADDRESS
;
1695 NdisStatus
= DoQueries(Adapter
, AddressOID
);
1696 if (NdisStatus
== NDIS_STATUS_SUCCESS
)
1698 Success
= EthCreateFilter(32, /* FIXME: Query this from miniport. */
1699 Adapter
->Address
.Type
.Medium802_3
,
1700 &Adapter
->NdisMiniportBlock
.EthDB
);
1702 ((PETHI_FILTER
)Adapter
->NdisMiniportBlock
.EthDB
)->Miniport
= (PNDIS_MINIPORT_BLOCK
)Adapter
;
1704 NdisStatus
= NDIS_STATUS_RESOURCES
;
1709 /* FIXME: Support other types of media */
1710 NDIS_DbgPrint(MIN_TRACE
, ("error: unsupported media\n"));
1712 /* FIXME - KeReleaseSpinLock(&Adapter->NdisMiniportBlock.Lock, OldIrql); */
1713 ExInterlockedRemoveEntryList( &Adapter
->ListEntry
, &AdapterListLock
);
1714 return STATUS_UNSUCCESSFUL
;
1717 if (NdisStatus
!= NDIS_STATUS_SUCCESS
)
1719 NDIS_DbgPrint(MAX_TRACE
, ("couldn't create filter (%x)\n", NdisStatus
));
1720 if (Adapter
->LookaheadBuffer
)
1722 ExFreePool(Adapter
->LookaheadBuffer
);
1723 Adapter
->LookaheadBuffer
= NULL
;
1725 ExInterlockedRemoveEntryList( &Adapter
->ListEntry
, &AdapterListLock
);
1729 /* Check for a hang every two seconds if it wasn't set in MiniportInitialize */
1730 if (Adapter
->NdisMiniportBlock
.CheckForHangSeconds
== 0)
1731 Adapter
->NdisMiniportBlock
.CheckForHangSeconds
= 2;
1733 Adapter
->NdisMiniportBlock
.OldPnPDeviceState
= Adapter
->NdisMiniportBlock
.PnPDeviceState
;
1734 Adapter
->NdisMiniportBlock
.PnPDeviceState
= NdisPnPDeviceStarted
;
1736 Timeout
.QuadPart
= (LONGLONG
)Adapter
->NdisMiniportBlock
.CheckForHangSeconds
* -1000000;
1737 KeSetTimerEx(&Adapter
->NdisMiniportBlock
.WakeUpDpcTimer
.Timer
, Timeout
,
1738 Adapter
->NdisMiniportBlock
.CheckForHangSeconds
* 1000,
1739 &Adapter
->NdisMiniportBlock
.WakeUpDpcTimer
.Dpc
);
1741 /* Put adapter in adapter list for this miniport */
1742 ExInterlockedInsertTailList(&Adapter
->NdisMiniportBlock
.DriverHandle
->DeviceList
, &Adapter
->MiniportListEntry
, &Adapter
->NdisMiniportBlock
.DriverHandle
->Lock
);
1744 return STATUS_SUCCESS
;
1751 IN PDEVICE_OBJECT DeviceObject
,
1754 * FUNCTION: Handle the PnP stop device event
1756 * DeviceObejct = Functional Device Object
1757 * Irp = IRP_MN_STOP_DEVICE I/O request packet
1759 * Status of operation
1762 PLOGICAL_ADAPTER Adapter
= (PLOGICAL_ADAPTER
)DeviceObject
->DeviceExtension
;
1765 /* Remove adapter from adapter list for this miniport */
1766 KeAcquireSpinLock(&Adapter
->NdisMiniportBlock
.DriverHandle
->Lock
, &OldIrql
);
1767 RemoveEntryList(&Adapter
->MiniportListEntry
);
1768 KeReleaseSpinLock(&Adapter
->NdisMiniportBlock
.DriverHandle
->Lock
, OldIrql
);
1770 /* Remove adapter from global adapter list */
1771 KeAcquireSpinLock(&AdapterListLock
, &OldIrql
);
1772 RemoveEntryList(&Adapter
->ListEntry
);
1773 KeReleaseSpinLock(&AdapterListLock
, OldIrql
);
1775 (*Adapter
->NdisMiniportBlock
.DriverHandle
->MiniportCharacteristics
.HaltHandler
)(Adapter
);
1777 if (Adapter
->LookaheadBuffer
)
1779 ExFreePool(Adapter
->LookaheadBuffer
);
1780 Adapter
->LookaheadBuffer
= NULL
;
1782 if (Adapter
->NdisMiniportBlock
.AllocatedResources
)
1784 ExFreePool(Adapter
->NdisMiniportBlock
.AllocatedResources
);
1785 Adapter
->NdisMiniportBlock
.AllocatedResources
= NULL
;
1787 if (Adapter
->NdisMiniportBlock
.AllocatedResourcesTranslated
)
1789 ExFreePool(Adapter
->NdisMiniportBlock
.AllocatedResourcesTranslated
);
1790 Adapter
->NdisMiniportBlock
.AllocatedResourcesTranslated
= NULL
;
1793 Adapter
->NdisMiniportBlock
.OldPnPDeviceState
= Adapter
->NdisMiniportBlock
.PnPDeviceState
;
1794 Adapter
->NdisMiniportBlock
.PnPDeviceState
= NdisPnPDeviceStopped
;
1796 KeCancelTimer(&Adapter
->NdisMiniportBlock
.WakeUpDpcTimer
.Timer
);
1798 return STATUS_SUCCESS
;
1805 IN PDEVICE_OBJECT DeviceObject
,
1808 PIO_STACK_LOCATION Stack
= IoGetCurrentIrpStackLocation(Irp
);
1809 PLOGICAL_ADAPTER Adapter
= (PLOGICAL_ADAPTER
)DeviceObject
->DeviceExtension
;
1812 switch (Stack
->MinorFunction
)
1814 case IRP_MN_START_DEVICE
:
1815 Status
= NdisIForwardIrpAndWait(Adapter
, Irp
);
1816 if (NT_SUCCESS(Status
) && NT_SUCCESS(Irp
->IoStatus
.Status
))
1818 Status
= NdisIPnPStartDevice(DeviceObject
, Irp
);
1820 Irp
->IoStatus
.Status
= Status
;
1821 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
1824 case IRP_MN_STOP_DEVICE
:
1825 Status
= NdisIForwardIrpAndWait(Adapter
, Irp
);
1826 if (NT_SUCCESS(Status
) && NT_SUCCESS(Irp
->IoStatus
.Status
))
1828 Status
= NdisIPnPStopDevice(DeviceObject
, Irp
);
1830 Irp
->IoStatus
.Status
= Status
;
1831 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
1834 case IRP_MN_QUERY_DEVICE_RELATIONS
:
1835 Status
= STATUS_NOT_SUPPORTED
;
1836 Irp
->IoStatus
.Status
= Status
;
1837 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
1841 IoSkipCurrentIrpStackLocation(Irp
);
1842 Status
= IoCallDriver(Adapter
->NdisMiniportBlock
.NextDeviceObject
, Irp
);
1853 IN PDRIVER_OBJECT DriverObject
,
1854 IN PDEVICE_OBJECT PhysicalDeviceObject
)
1856 * FUNCTION: Create a device for an adapter found using PnP
1858 * DriverObject = Pointer to the miniport driver object
1859 * PhysicalDeviceObject = Pointer to the PDO for our adapter
1862 static const WCHAR ClassKeyName
[] = {'C','l','a','s','s','\\'};
1863 static const WCHAR LinkageKeyName
[] = {'\\','L','i','n','k','a','g','e',0};
1864 PNDIS_M_DRIVER_BLOCK Miniport
;
1865 PNDIS_M_DRIVER_BLOCK
*MiniportPtr
;
1866 WCHAR
*LinkageKeyBuffer
;
1867 ULONG DriverKeyLength
;
1868 RTL_QUERY_REGISTRY_TABLE QueryTable
[2];
1869 UNICODE_STRING ExportName
;
1870 PDEVICE_OBJECT DeviceObject
;
1871 PLOGICAL_ADAPTER Adapter
;
1875 * Gain the access to the miniport data structure first.
1878 MiniportPtr
= IoGetDriverObjectExtension(DriverObject
, (PVOID
)TAG('D','I','M','N'));
1879 if (MiniportPtr
== NULL
)
1881 NDIS_DbgPrint(DEBUG_MINIPORT
, ("Can't get driver object extension.\n"));
1882 return STATUS_UNSUCCESSFUL
;
1884 Miniport
= *MiniportPtr
;
1887 * Get name of the Linkage registry key for our adapter. It's located under
1888 * the driver key for our driver and so we have basicly two ways to do it.
1889 * Either we can use IoOpenDriverRegistryKey or compose it using information
1890 * gathered by IoGetDeviceProperty. I choosed the second because
1891 * IoOpenDriverRegistryKey wasn't implemented at the time of writing.
1894 Status
= IoGetDeviceProperty(PhysicalDeviceObject
, DevicePropertyDriverKeyName
,
1895 0, NULL
, &DriverKeyLength
);
1896 if (Status
!= STATUS_BUFFER_TOO_SMALL
&& Status
!= STATUS_BUFFER_OVERFLOW
&& Status
!= STATUS_SUCCESS
)
1898 NDIS_DbgPrint(DEBUG_MINIPORT
, ("Can't get miniport driver key length.\n"));
1902 LinkageKeyBuffer
= ExAllocatePool(PagedPool
, DriverKeyLength
+
1903 sizeof(ClassKeyName
) + sizeof(LinkageKeyName
));
1904 if (LinkageKeyBuffer
== NULL
)
1906 NDIS_DbgPrint(DEBUG_MINIPORT
, ("Can't allocate memory for driver key name.\n"));
1907 return STATUS_INSUFFICIENT_RESOURCES
;
1910 Status
= IoGetDeviceProperty(PhysicalDeviceObject
, DevicePropertyDriverKeyName
,
1911 DriverKeyLength
, LinkageKeyBuffer
+
1912 (sizeof(ClassKeyName
) / sizeof(WCHAR
)),
1914 if (!NT_SUCCESS(Status
))
1916 NDIS_DbgPrint(DEBUG_MINIPORT
, ("Can't get miniport driver key.\n"));
1917 ExFreePool(LinkageKeyBuffer
);
1921 /* Compose the linkage key name. */
1922 RtlCopyMemory(LinkageKeyBuffer
, ClassKeyName
, sizeof(ClassKeyName
));
1923 RtlCopyMemory(LinkageKeyBuffer
+ ((sizeof(ClassKeyName
) + DriverKeyLength
) /
1924 sizeof(WCHAR
)) - 1, LinkageKeyName
, sizeof(LinkageKeyName
));
1926 NDIS_DbgPrint(DEBUG_MINIPORT
, ("LinkageKey: %S.\n", LinkageKeyBuffer
));
1929 * Now open the linkage key and read the "Export" and "RootDevice" values
1930 * which contains device name and root service respectively.
1933 RtlZeroMemory(QueryTable
, sizeof(QueryTable
));
1934 RtlInitUnicodeString(&ExportName
, NULL
);
1935 QueryTable
[0].Flags
= RTL_QUERY_REGISTRY_REQUIRED
| RTL_QUERY_REGISTRY_DIRECT
;
1936 QueryTable
[0].Name
= L
"Export";
1937 QueryTable
[0].EntryContext
= &ExportName
;
1939 Status
= RtlQueryRegistryValues(RTL_REGISTRY_CONTROL
, LinkageKeyBuffer
,
1940 QueryTable
, NULL
, NULL
);
1941 ExFreePool(LinkageKeyBuffer
);
1942 if (!NT_SUCCESS(Status
))
1944 NDIS_DbgPrint(DEBUG_MINIPORT
, ("Can't get miniport device name. (%x)\n", Status
));
1949 * Create the device object.
1952 NDIS_DbgPrint(MAX_TRACE
, ("creating device %wZ\n", &ExportName
));
1954 Status
= IoCreateDevice(Miniport
->DriverObject
, sizeof(LOGICAL_ADAPTER
),
1955 &ExportName
, FILE_DEVICE_PHYSICAL_NETCARD
,
1956 0, FALSE
, &DeviceObject
);
1957 if (!NT_SUCCESS(Status
))
1959 NDIS_DbgPrint(MIN_TRACE
, ("Could not create device object.\n"));
1960 RtlFreeUnicodeString(&ExportName
);
1965 * Initialize the adapter structure.
1968 Adapter
= (PLOGICAL_ADAPTER
)DeviceObject
->DeviceExtension
;
1969 KeInitializeSpinLock(&Adapter
->NdisMiniportBlock
.Lock
);
1970 InitializeListHead(&Adapter
->ProtocolListHead
);
1971 Adapter
->NdisMiniportBlock
.DriverHandle
= Miniport
;
1973 Adapter
->NdisMiniportBlock
.MiniportName
= ExportName
;
1975 Adapter
->NdisMiniportBlock
.DeviceObject
= DeviceObject
;
1976 Adapter
->NdisMiniportBlock
.PhysicalDeviceObject
= PhysicalDeviceObject
;
1977 Adapter
->NdisMiniportBlock
.NextDeviceObject
=
1978 IoAttachDeviceToDeviceStack(Adapter
->NdisMiniportBlock
.DeviceObject
,
1979 PhysicalDeviceObject
);
1981 Adapter
->NdisMiniportBlock
.OldPnPDeviceState
= 0;
1982 Adapter
->NdisMiniportBlock
.PnPDeviceState
= NdisPnPDeviceAdded
;
1984 KeInitializeTimer(&Adapter
->NdisMiniportBlock
.WakeUpDpcTimer
.Timer
);
1985 KeInitializeDpc(&Adapter
->NdisMiniportBlock
.WakeUpDpcTimer
.Dpc
, MiniportHangDpc
, Adapter
);
1986 KeInitializeDpc(&Adapter
->NdisMiniportBlock
.DeferredDpc
, MiniportDpc
, Adapter
);
1988 DeviceObject
->Flags
&= ~DO_DEVICE_INITIALIZING
;
1990 return STATUS_SUCCESS
;
1999 NdisMRegisterMiniport(
2000 IN NDIS_HANDLE NdisWrapperHandle
,
2001 IN PNDIS_MINIPORT_CHARACTERISTICS MiniportCharacteristics
,
2002 IN UINT CharacteristicsLength
)
2004 * FUNCTION: Registers a miniport's MiniportXxx entry points with the NDIS library
2006 * NdisWrapperHandle = Pointer to handle returned by NdisMInitializeWrapper
2007 * MiniportCharacteristics = Pointer to a buffer with miniport characteristics
2008 * CharacteristicsLength = Number of bytes in characteristics buffer
2010 * Status of operation
2014 PNDIS_M_DRIVER_BLOCK Miniport
= GET_MINIPORT_DRIVER(NdisWrapperHandle
);
2015 PNDIS_M_DRIVER_BLOCK
*MiniportPtr
;
2018 NDIS_DbgPrint(MAX_TRACE
, ("Called.\n"));
2020 switch (MiniportCharacteristics
->MajorNdisVersion
)
2023 MinSize
= sizeof(NDIS30_MINIPORT_CHARACTERISTICS
);
2027 MinSize
= sizeof(NDIS40_MINIPORT_CHARACTERISTICS
);
2031 MinSize
= sizeof(NDIS50_MINIPORT_CHARACTERISTICS
);
2035 NDIS_DbgPrint(DEBUG_MINIPORT
, ("Bad miniport characteristics version.\n"));
2036 return NDIS_STATUS_BAD_VERSION
;
2039 if (CharacteristicsLength
< MinSize
)
2041 NDIS_DbgPrint(DEBUG_MINIPORT
, ("Bad miniport characteristics.\n"));
2042 return NDIS_STATUS_BAD_CHARACTERISTICS
;
2045 /* Check if mandatory MiniportXxx functions are specified */
2046 if ((!MiniportCharacteristics
->HaltHandler
) ||
2047 (!MiniportCharacteristics
->InitializeHandler
)||
2048 (!MiniportCharacteristics
->QueryInformationHandler
) ||
2049 (!MiniportCharacteristics
->ResetHandler
) ||
2050 (!MiniportCharacteristics
->SetInformationHandler
))
2052 NDIS_DbgPrint(DEBUG_MINIPORT
, ("Bad miniport characteristics.\n"));
2053 return NDIS_STATUS_BAD_CHARACTERISTICS
;
2056 if (MiniportCharacteristics
->MajorNdisVersion
== 0x03)
2058 if (!MiniportCharacteristics
->SendHandler
)
2060 NDIS_DbgPrint(DEBUG_MINIPORT
, ("Bad miniport characteristics.\n"));
2061 return NDIS_STATUS_BAD_CHARACTERISTICS
;
2064 else if (MiniportCharacteristics
->MajorNdisVersion
>= 0x04)
2067 if ((!MiniportCharacteristics
->SendHandler
) &&
2068 (!MiniportCharacteristics
->SendPacketsHandler
))
2070 NDIS_DbgPrint(DEBUG_MINIPORT
, ("Bad miniport characteristics.\n"));
2071 return NDIS_STATUS_BAD_CHARACTERISTICS
;
2075 /* TODO: verify NDIS5 and NDIS5.1 */
2077 RtlCopyMemory(&Miniport
->MiniportCharacteristics
, MiniportCharacteristics
, MinSize
);
2080 * NOTE: This is VERY unoptimal! Should we store the NDIS_M_DRIVER_BLOCK
2081 * structure in the driver extension or what?
2084 Status
= IoAllocateDriverObjectExtension(Miniport
->DriverObject
, (PVOID
)TAG('D','I','M','N'),
2085 sizeof(PNDIS_M_DRIVER_BLOCK
), (PVOID
*)&MiniportPtr
);
2086 if (!NT_SUCCESS(Status
))
2088 NDIS_DbgPrint(DEBUG_MINIPORT
, ("Can't allocate driver object extension.\n"));
2089 return NDIS_STATUS_RESOURCES
;
2092 *MiniportPtr
= Miniport
;
2094 Miniport
->DriverObject
->MajorFunction
[IRP_MJ_PNP
] = NdisIDispatchPnp
;
2095 Miniport
->DriverObject
->DriverExtension
->AddDevice
= NdisIAddDevice
;
2097 return NDIS_STATUS_SUCCESS
;
2104 #undef NdisMResetComplete
2108 IN NDIS_HANDLE MiniportAdapterHandle
,
2109 IN NDIS_STATUS Status
,
2110 IN BOOLEAN AddressingReset
)
2112 MiniResetComplete(MiniportAdapterHandle
, Status
, AddressingReset
);
2119 #undef NdisMSendComplete
2123 IN NDIS_HANDLE MiniportAdapterHandle
,
2124 IN PNDIS_PACKET Packet
,
2125 IN NDIS_STATUS Status
)
2127 * FUNCTION: Forwards a message to the initiating protocol saying
2128 * that a packet was handled
2130 * NdisAdapterHandle = Handle input to MiniportInitialize
2131 * Packet = Pointer to NDIS packet that was sent
2132 * Status = Status of send operation
2135 MiniSendComplete(MiniportAdapterHandle
, Packet
, Status
);
2142 #undef NdisMSendResourcesAvailable
2145 NdisMSendResourcesAvailable(
2146 IN NDIS_HANDLE MiniportAdapterHandle
)
2148 MiniSendResourcesAvailable(MiniportAdapterHandle
);
2155 #undef NdisMTransferDataComplete
2158 NdisMTransferDataComplete(
2159 IN NDIS_HANDLE MiniportAdapterHandle
,
2160 IN PNDIS_PACKET Packet
,
2161 IN NDIS_STATUS Status
,
2162 IN UINT BytesTransferred
)
2164 MiniTransferDataComplete(MiniportAdapterHandle
, Packet
, Status
, BytesTransferred
);
2171 #undef NdisMSetInformationComplete
2174 NdisMSetInformationComplete(
2175 IN NDIS_HANDLE MiniportAdapterHandle
,
2176 IN NDIS_STATUS Status
)
2178 PLOGICAL_ADAPTER Adapter
=
2179 (PLOGICAL_ADAPTER
)MiniportAdapterHandle
;
2182 KeRaiseIrql(DISPATCH_LEVEL
, &OldIrql
);
2183 (Adapter
->NdisMiniportBlock
.SetCompleteHandler
)(MiniportAdapterHandle
, Status
);
2184 KeAcquireSpinLockAtDpcLevel(&Adapter
->NdisMiniportBlock
.Lock
);
2185 Adapter
->MiniportBusy
= FALSE
;
2186 KeReleaseSpinLockFromDpcLevel(&Adapter
->NdisMiniportBlock
.Lock
);
2187 KeLowerIrql(OldIrql
);
2194 #undef NdisMSetAttributes
2198 IN NDIS_HANDLE MiniportAdapterHandle
,
2199 IN NDIS_HANDLE MiniportAdapterContext
,
2200 IN BOOLEAN BusMaster
,
2201 IN NDIS_INTERFACE_TYPE AdapterType
)
2203 * FUNCTION: Informs the NDIS library of significant features of the caller's NIC
2205 * MiniportAdapterHandle = Handle input to MiniportInitialize
2206 * MiniportAdapterContext = Pointer to context information
2207 * BusMaster = Specifies TRUE if the caller's NIC is a busmaster DMA device
2208 * AdapterType = Specifies the I/O bus interface of the caller's NIC
2211 NDIS_DbgPrint(MAX_TRACE
, ("Called.\n"));
2212 NdisMSetAttributesEx(MiniportAdapterHandle
, MiniportAdapterContext
, 0,
2213 BusMaster
? NDIS_ATTRIBUTE_BUS_MASTER
: 0,
2223 NdisMSetAttributesEx(
2224 IN NDIS_HANDLE MiniportAdapterHandle
,
2225 IN NDIS_HANDLE MiniportAdapterContext
,
2226 IN UINT CheckForHangTimeInSeconds OPTIONAL
,
2227 IN ULONG AttributeFlags
,
2228 IN NDIS_INTERFACE_TYPE AdapterType
)
2230 * FUNCTION: Informs the NDIS library of significant features of the caller's NIC
2232 * MiniportAdapterHandle = Handle input to MiniportInitialize
2233 * MiniportAdapterContext = Pointer to context information
2234 * CheckForHangTimeInSeconds = Specifies interval in seconds at which
2235 * MiniportCheckForHang should be called
2236 * AttributeFlags = Bitmask that indicates specific attributes
2237 * AdapterType = Specifies the I/O bus interface of the caller's NIC
2240 PLOGICAL_ADAPTER Adapter
= GET_LOGICAL_ADAPTER(MiniportAdapterHandle
);
2242 NDIS_DbgPrint(MAX_TRACE
, ("Called.\n"));
2244 Adapter
->NdisMiniportBlock
.MiniportAdapterContext
= MiniportAdapterContext
;
2245 Adapter
->NdisMiniportBlock
.Flags
= AttributeFlags
;
2246 Adapter
->NdisMiniportBlock
.AdapterType
= AdapterType
;
2247 if (CheckForHangTimeInSeconds
> 0)
2248 Adapter
->NdisMiniportBlock
.CheckForHangSeconds
= CheckForHangTimeInSeconds
;
2249 if (AttributeFlags
& NDIS_ATTRIBUTE_INTERMEDIATE_DRIVER
)
2250 NDIS_DbgPrint(MAX_TRACE
, ("Intermediate drivers not supported yet.\n"));
2260 IN ULONG MicrosecondsToSleep
)
2262 * FUNCTION: delay the thread's execution for MicrosecondsToSleep
2264 * MicrosecondsToSleep: duh...
2266 * - Because this is a blocking call, current IRQL must be < DISPATCH_LEVEL
2270 LARGE_INTEGER DueTime
;
2274 DueTime
.QuadPart
= (-1) * 10 * MicrosecondsToSleep
;
2276 KeInitializeTimer(&Timer
);
2277 KeSetTimer(&Timer
, DueTime
, 0);
2278 KeWaitForSingleObject(&Timer
, Executive
, KernelMode
, FALSE
, 0);
2287 NdisMSynchronizeWithInterrupt(
2288 IN PNDIS_MINIPORT_INTERRUPT Interrupt
,
2289 IN PVOID SynchronizeFunction
,
2290 IN PVOID SynchronizeContext
)
2292 return(KeSynchronizeExecution(Interrupt
->InterruptObject
,
2293 (PKSYNCHRONIZE_ROUTINE
)SynchronizeFunction
,
2294 SynchronizeContext
));
2304 IN NDIS_HANDLE LogHandle
,
2306 IN UINT LogBufferSize
)
2308 PUCHAR Buffer
= LogBuffer
;
2312 for (i
= 0; i
< LogBufferSize
; i
+= 16)
2314 DbgPrint("%08x |", i
);
2315 for (j
= 0; j
< 16; j
++)
2318 if (idx
< LogBufferSize
)
2319 DbgPrint(" %02x", Buffer
[idx
]);
2324 for (j
= 0; j
< 16; j
++)
2327 if (idx
== LogBufferSize
)
2329 if (Buffer
[idx
] >= ' ') /* FIXME: not portable! replace by if (isprint(Buffer[idx])) ? */
2330 DbgPrint("%c", Buffer
[idx
]);
2337 return NDIS_STATUS_FAILURE
;
2346 NdisTerminateWrapper(
2347 IN NDIS_HANDLE NdisWrapperHandle
,
2348 IN PVOID SystemSpecific
)
2350 * FUNCTION: Releases resources allocated by a call to NdisInitializeWrapper
2352 * NdisWrapperHandle = Handle returned by NdisInitializeWrapper (NDIS_M_DRIVER_BLOCK)
2353 * SystemSpecific = Always NULL
2356 PNDIS_M_DRIVER_BLOCK Miniport
= GET_MINIPORT_DRIVER(NdisWrapperHandle
);
2358 NDIS_DbgPrint(MAX_TRACE
, ("Called.\n"));
2360 ExFreePool(Miniport
->RegistryPath
->Buffer
);
2361 ExFreePool(Miniport
->RegistryPath
);
2362 ExFreePool(Miniport
);