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 /* Root of the scm database */
22 #define SERVICES_ROOT L"\\Registry\\Machine\\System\\CurrentControlSet\\Services\\"
25 * Define to 1 to get a debugger breakpoint at the end of NdisInitializeWrapper
26 * for each new miniport starting up
28 #define BREAK_ON_MINIPORT_INIT 0
31 * This has to be big enough to hold the results of querying the Route value
32 * from the Linkage key. Please re-code me to determine this dynamically.
34 #define ROUTE_DATA_SIZE 256
36 /* Number of media we know */
37 #define MEDIA_ARRAY_SIZE 15
39 static NDIS_MEDIUM MediaArray
[MEDIA_ARRAY_SIZE
] =
48 NdisMediumArcnet878_2
,
50 NdisMediumWirelessWan
,
58 /* global list and lock of Miniports NDIS has registered */
59 LIST_ENTRY MiniportListHead
;
60 KSPIN_LOCK MiniportListLock
;
62 /* global list and lock of adapters NDIS has registered */
63 LIST_ENTRY AdapterListHead
;
64 KSPIN_LOCK AdapterListLock
;
73 if ((DebugTraceLevel
& DEBUG_PACKET
) > 0) {
74 Length
= CopyPacketToBuffer(
80 DbgPrint("*** PACKET START ***");
82 for (i
= 0; i
< Length
; i
++) {
84 DbgPrint("\n%04X ", i
);
85 DbgPrint("%02X ", Buffer
[i
]);
88 DbgPrint("*** PACKET STOP ***\n");
96 UINT HeaderBufferSize
,
97 PVOID LookaheadBuffer
,
98 UINT LookaheadBufferSize
)
101 if ((DebugTraceLevel
& DEBUG_PACKET
) > 0) {
105 DbgPrint("*** RECEIVE PACKET START ***\n");
108 for (i
= 0; i
< HeaderBufferSize
; i
++) {
110 DbgPrint("\n%04X ", i
);
111 DbgPrint("%02X ", *p
++);
114 DbgPrint("\nFRAME:");
117 Length
= (LookaheadBufferSize
< 64)? LookaheadBufferSize
: 64;
118 for (i
= 0; i
< Length
; i
++) {
120 DbgPrint("\n%04X ", i
);
121 DbgPrint("%02X ", *p
++);
124 DbgPrint("\n*** RECEIVE PACKET STOP ***\n");
132 PLOGICAL_ADAPTER Adapter
,
133 NDIS_HANDLE MacReceiveContext
,
135 UINT HeaderBufferSize
,
136 PVOID LookaheadBuffer
,
137 UINT LookaheadBufferSize
,
140 * FUNCTION: Indicate received data to bound protocols
142 * Adapter = Pointer to logical adapter
143 * MacReceiveContext = MAC receive context handle
144 * HeaderBuffer = Pointer to header buffer
145 * HeaderBufferSize = Size of header buffer
146 * LookaheadBuffer = Pointer to lookahead buffer
147 * LookaheadBufferSize = Size of lookahead buffer
148 * PacketSize = Total size of received packet
152 PLIST_ENTRY CurrentEntry
;
153 PADAPTER_BINDING AdapterBinding
;
155 NDIS_DbgPrint(DEBUG_MINIPORT
, ("Called. Adapter (0x%X) HeaderBuffer (0x%X) "
156 "HeaderBufferSize (0x%X) LookaheadBuffer (0x%X) LookaheadBufferSize (0x%X).\n",
157 Adapter
, HeaderBuffer
, HeaderBufferSize
, LookaheadBuffer
, LookaheadBufferSize
));
159 MiniDisplayPacket2(HeaderBuffer
, HeaderBufferSize
, LookaheadBuffer
, LookaheadBufferSize
);
162 * XXX Think about this. This is probably broken. Spinlocks are
163 * taken out for now until i comprehend the Right Way to do this.
165 * This used to acquire the MiniportBlock spinlock and hold it until
166 * just before the call to ReceiveHandler. It would then release and
167 * subsequently re-acquire the lock.
169 * I don't see how this does any good, as it would seem he's just
170 * trying to protect the packet list. If somebody else dequeues
171 * a packet, we are in fact in bad shape, but we don't want to
172 * necessarily call the receive handler at elevated irql either.
174 * therefore: We *are* going to call the receive handler at high irql
175 * (due to holding the lock) for now, and eventually we have to
176 * figure out another way to protect this packet list.
178 * UPDATE: this is busted; this results in a recursive lock acquisition.
180 //NDIS_DbgPrint(MAX_TRACE, ("acquiring miniport block lock\n"));
181 //KeAcquireSpinLock(&Adapter->NdisMiniportBlock.Lock, &OldIrql);
183 CurrentEntry
= Adapter
->ProtocolListHead
.Flink
;
184 NDIS_DbgPrint(DEBUG_MINIPORT
, ("CurrentEntry = %x\n", CurrentEntry
));
186 if (CurrentEntry
== &Adapter
->ProtocolListHead
)
188 NDIS_DbgPrint(DEBUG_MINIPORT
, ("WARNING: No upper protocol layer.\n"));
191 while (CurrentEntry
!= &Adapter
->ProtocolListHead
)
193 AdapterBinding
= CONTAINING_RECORD(CurrentEntry
, ADAPTER_BINDING
, AdapterListEntry
);
194 NDIS_DbgPrint(DEBUG_MINIPORT
, ("AdapterBinding = %x\n", AdapterBinding
));
197 /* KeReleaseSpinLock(&Adapter->NdisMiniportBlock.Lock, OldIrql); */
202 NDIS_DbgPrint(MIN_TRACE
, ("AdapterBinding was null\n"));
206 if(!AdapterBinding
->ProtocolBinding
)
208 NDIS_DbgPrint(MIN_TRACE
, ("AdapterBinding->ProtocolBinding was null\n"));
212 if(!AdapterBinding
->ProtocolBinding
->Chars
.ReceiveHandler
)
214 NDIS_DbgPrint(MIN_TRACE
, ("AdapterBinding->ProtocolBinding->Chars.ReceiveHandler was null\n"));
221 ("XXX (%x) %x %x %x %x %x %x %x XXX\n",
222 *AdapterBinding
->ProtocolBinding
->Chars
.ReceiveHandler
,
223 AdapterBinding
->NdisOpenBlock
.NdisCommonOpenBlock
.ProtocolBindingContext
,
231 /* call the receive handler */
232 (*AdapterBinding
->ProtocolBinding
->Chars
.ReceiveHandler
)(
233 AdapterBinding
->NdisOpenBlock
.NdisCommonOpenBlock
.ProtocolBindingContext
,
242 /* KeAcquireSpinLock(&Adapter->NdisMiniportBlock.Lock, &OldIrql); */
244 CurrentEntry
= CurrentEntry
->Flink
;
247 //KeReleaseSpinLock(&Adapter->NdisMiniportBlock.Lock, OldIrql);
249 NDIS_DbgPrint(MAX_TRACE
, ("Leaving.\n"));
254 MiniIndicateReceivePacket(
255 IN NDIS_HANDLE Miniport
,
256 IN PPNDIS_PACKET PacketArray
,
257 IN UINT NumberOfPackets
)
259 * FUNCTION: receives miniport packet array indications
261 * Miniport: Miniport handle for the adapter
262 * PacketArray: pointer to a list of packet pointers to indicate
263 * NumberOfPackets: number of packets to indicate
265 * - This currently is a big temporary hack. In the future this should
266 * call ProtocolReceivePacket() on each bound protocol if it exists.
267 * For now it just mimics NdisMEthIndicateReceive.
272 for(i
= 0; i
< NumberOfPackets
; i
++)
274 PCHAR PacketBuffer
= 0;
275 UINT PacketLength
= 0;
276 PNDIS_BUFFER NdisBuffer
= 0;
278 #define PACKET_TAG (('k' << 24) + ('P' << 16) + ('D' << 8) + 'N')
280 NdisAllocateMemoryWithTag((PVOID
)&PacketBuffer
, 1518, PACKET_TAG
);
283 NDIS_DbgPrint(MIN_TRACE
, ("insufficient resources\n"));
287 NdisQueryPacket(PacketArray
[i
], NULL
, NULL
, &NdisBuffer
, NULL
);
291 PNDIS_BUFFER CurrentBuffer
;
295 NdisQueryBuffer(NdisBuffer
, &BufferVa
, &BufferLen
);
296 memcpy(PacketBuffer
+ PacketLength
, BufferVa
, BufferLen
);
297 PacketLength
+= BufferLen
;
299 CurrentBuffer
= NdisBuffer
;
300 NdisGetNextBuffer(CurrentBuffer
, &NdisBuffer
);
303 NDIS_DbgPrint(MID_TRACE
, ("indicating a %d-byte packet\n", PacketLength
));
305 MiniIndicateData(Miniport
, NULL
, PacketBuffer
, 14, PacketBuffer
+14, PacketLength
-14, PacketLength
-14);
307 NdisFreeMemory(PacketBuffer
, 0, 0);
314 IN NDIS_HANDLE MiniportAdapterHandle
,
315 IN NDIS_STATUS Status
,
316 IN BOOLEAN AddressingReset
)
324 IN NDIS_HANDLE MiniportAdapterHandle
,
325 IN PNDIS_PACKET Packet
,
326 IN NDIS_STATUS Status
)
328 * FUNCTION: Forwards a message to the initiating protocol saying
329 * that a packet was handled
331 * NdisAdapterHandle = Handle input to MiniportInitialize
332 * Packet = Pointer to NDIS packet that was sent
333 * Status = Status of send operation
336 PADAPTER_BINDING AdapterBinding
;
338 NDIS_DbgPrint(DEBUG_MINIPORT
, ("Called.\n"));
340 AdapterBinding
= (PADAPTER_BINDING
)Packet
->Reserved
[0];
342 (*AdapterBinding
->ProtocolBinding
->Chars
.SendCompleteHandler
)(
343 AdapterBinding
->NdisOpenBlock
.NdisCommonOpenBlock
.ProtocolBindingContext
,
350 MiniSendResourcesAvailable(
351 IN NDIS_HANDLE MiniportAdapterHandle
)
358 MiniTransferDataComplete(
359 IN NDIS_HANDLE MiniportAdapterHandle
,
360 IN PNDIS_PACKET Packet
,
361 IN NDIS_STATUS Status
,
362 IN UINT BytesTransferred
)
364 PADAPTER_BINDING AdapterBinding
;
366 NDIS_DbgPrint(DEBUG_MINIPORT
, ("Called.\n"));
368 AdapterBinding
= (PADAPTER_BINDING
)Packet
->Reserved
[0];
370 (*AdapterBinding
->ProtocolBinding
->Chars
.SendCompleteHandler
)(
371 AdapterBinding
->NdisOpenBlock
.NdisCommonOpenBlock
.ProtocolBindingContext
,
378 MiniAdapterHasAddress(
379 PLOGICAL_ADAPTER Adapter
,
382 * FUNCTION: Determines whether a packet has the same destination address as an adapter
384 * Adapter = Pointer to logical adapter object
385 * Packet = Pointer to NDIS packet
387 * TRUE if the destination address is that of the adapter, FALSE if not
393 PNDIS_BUFFER NdisBuffer
;
396 NDIS_DbgPrint(DEBUG_MINIPORT
, ("Called.\n"));
401 NDIS_DbgPrint(MID_TRACE
, ("Adapter object was null\n"));
407 NDIS_DbgPrint(MID_TRACE
, ("Packet was null\n"));
412 NdisQueryPacket(Packet
, NULL
, NULL
, &NdisBuffer
, NULL
);
416 NDIS_DbgPrint(MID_TRACE
, ("Packet contains no buffers.\n"));
420 NdisQueryBuffer(NdisBuffer
, (PVOID
)&Start2
, &BufferLength
);
422 /* FIXME: Should handle fragmented packets */
424 switch (Adapter
->NdisMiniportBlock
.MediaType
)
426 case NdisMedium802_3
:
427 Length
= ETH_LENGTH_OF_ADDRESS
;
428 /* Destination address is the first field */
432 NDIS_DbgPrint(MIN_TRACE
, ("Adapter has unsupported media type (0x%X).\n", Adapter
->NdisMiniportBlock
.MediaType
));
436 if (BufferLength
< Length
)
438 NDIS_DbgPrint(MID_TRACE
, ("Buffer is too small.\n"));
442 Start1
= (PUCHAR
)&Adapter
->Address
;
443 NDIS_DbgPrint(MAX_TRACE
, ("packet address: %x:%x:%x:%x:%x:%x adapter address: %x:%x:%x:%x:%x:%x\n",
444 *((char *)Start1
), *(((char *)Start1
)+1), *(((char *)Start1
)+2), *(((char *)Start1
)+3), *(((char *)Start1
)+4), *(((char *)Start1
)+5),
445 *((char *)Start2
), *(((char *)Start2
)+1), *(((char *)Start2
)+2), *(((char *)Start2
)+3), *(((char *)Start2
)+4), *(((char *)Start2
)+5))
448 return (RtlCompareMemory((PVOID
)Start1
, (PVOID
)Start2
, Length
) == Length
);
454 PNDIS_STRING AdapterName
)
456 * FUNCTION: Finds an adapter object by name
458 * AdapterName = Pointer to name of adapter
460 * Pointer to logical adapter object, or NULL if none was found.
461 * If found, the adapter is referenced for the caller. The caller
462 * is responsible for dereferencing after use
466 PLIST_ENTRY CurrentEntry
;
467 PLOGICAL_ADAPTER Adapter
= 0;
471 NDIS_DbgPrint(DEBUG_MINIPORT
, ("Called.\n"));
473 if(IsListEmpty(&AdapterListHead
))
475 NDIS_DbgPrint(DEBUG_MINIPORT
, ("No registered miniports for protocol to bind to\n"));
479 KeAcquireSpinLock(&AdapterListLock
, &OldIrql
);
483 CurrentEntry
= AdapterListHead
.Flink
;
485 while (CurrentEntry
!= &AdapterListHead
)
487 Adapter
= CONTAINING_RECORD(CurrentEntry
, LOGICAL_ADAPTER
, ListEntry
);
491 NDIS_DbgPrint(DEBUG_MINIPORT
, ("AdapterName = %wZ\n", AdapterName
));
492 NDIS_DbgPrint(DEBUG_MINIPORT
, ("DeviceName = %wZ\n", &Adapter
->NdisMiniportBlock
.MiniportName
));
494 if (RtlCompareUnicodeString(AdapterName
, &Adapter
->NdisMiniportBlock
.MiniportName
, TRUE
) == 0)
496 ReferenceObject(Adapter
);
501 CurrentEntry
= CurrentEntry
->Flink
;
505 KeReleaseSpinLock(&AdapterListLock
, OldIrql
);
509 NDIS_DbgPrint(DEBUG_MINIPORT
, ("Leaving. Adapter found at 0x%x\n", Adapter
));
513 NDIS_DbgPrint(DEBUG_MINIPORT
, ("Leaving (adapter not found).\n"));
521 MiniQueryInformation(
522 PLOGICAL_ADAPTER Adapter
,
527 * FUNCTION: Queries a logical adapter for properties
529 * Adapter = Pointer to the logical adapter object to query
530 * Oid = Specifies the Object ID to query for
531 * Size = If non-zero overrides the length in the adapter object
532 * BytesWritten = Address of buffer to place number of bytes written
534 * If the specified buffer is too small, a new buffer is allocated,
535 * and the query is attempted again
537 * Status of operation
539 * Is there any way to use the buffer provided by the protocol?
542 NDIS_STATUS NdisStatus
;
545 NDIS_DbgPrint(DEBUG_MINIPORT
, ("Called.\n"));
547 if (Adapter
->QueryBufferLength
== 0)
549 /* XXX is 32 the right number? */
550 Adapter
->QueryBuffer
= ExAllocatePool(NonPagedPool
, (Size
== 0)? 32 : Size
);
552 if (!Adapter
->QueryBuffer
)
554 NDIS_DbgPrint(MIN_TRACE
, ("Insufficient resources.\n"));
555 return NDIS_STATUS_RESOURCES
;
559 Adapter
->QueryBufferLength
= (Size
== 0)? 32 : Size
;
562 /* this is the third time i've seen this conditional */
563 BytesNeeded
= (Size
== 0)? Adapter
->QueryBufferLength
: Size
;
565 /* call the miniport's queryinfo handler */
566 NdisStatus
= (*Adapter
->Miniport
->Chars
.QueryInformationHandler
)(
567 Adapter
->NdisMiniportBlock
.MiniportAdapterContext
,
569 Adapter
->QueryBuffer
,
574 /* XXX is status_pending part of success macro? */
575 if ((NT_SUCCESS(NdisStatus
)) || (NdisStatus
== NDIS_STATUS_PENDING
))
577 NDIS_DbgPrint(DEBUG_MINIPORT
, ("Miniport returned status (0x%X).\n", NdisStatus
));
581 if (NdisStatus
== NDIS_STATUS_INVALID_LENGTH
)
583 ExFreePool(Adapter
->QueryBuffer
);
585 Adapter
->QueryBufferLength
+= BytesNeeded
;
586 Adapter
->QueryBuffer
= ExAllocatePool(NonPagedPool
, Adapter
->QueryBufferLength
);
588 if (!Adapter
->QueryBuffer
)
590 NDIS_DbgPrint(MIN_TRACE
, ("Insufficient resources.\n"));
591 return NDIS_STATUS_RESOURCES
;
594 NdisStatus
= (*Adapter
->Miniport
->Chars
.QueryInformationHandler
)(
595 Adapter
->NdisMiniportBlock
.MiniportAdapterContext
,
597 Adapter
->QueryBuffer
,
610 PLOGICAL_ADAPTER Adapter
,
611 NDIS_WORK_ITEM_TYPE WorkItemType
,
612 PVOID WorkItemContext
)
614 * FUNCTION: Queues a work item for execution at a later time
616 * Adapter = Pointer to the logical adapter object to queue work item on
617 * WorkItemType = Type of work item to queue
618 * WorkItemContext = Pointer to context information for work item
620 * Adapter lock must be held when called
622 * Status of operation
625 PNDIS_MINIPORT_WORK_ITEM Item
;
627 NDIS_DbgPrint(MAX_TRACE
, ("Called.\n"));
630 ASSERT(KeGetCurrentIrql() >= DISPATCH_LEVEL
);
633 if (Adapter
->WorkQueueLevel
< NDIS_MINIPORT_WORK_QUEUE_SIZE
- 1)
635 Item
= &Adapter
->WorkQueue
[Adapter
->WorkQueueLevel
];
636 Adapter
->WorkQueueLevel
++;
641 Item
= ExAllocatePool(NonPagedPool
, sizeof(NDIS_MINIPORT_WORK_ITEM
));
644 NDIS_DbgPrint(MIN_TRACE
, ("Insufficient resources.\n"));
645 return NDIS_STATUS_RESOURCES
;
649 Item
->WorkItemType
= WorkItemType
;
650 Item
->WorkItemContext
= WorkItemContext
;
652 /* safe due to adapter lock held */
653 Item
->Link
.Next
= NULL
;
654 if (!Adapter
->WorkQueueHead
)
656 Adapter
->WorkQueueHead
= Item
;
657 Adapter
->WorkQueueTail
= Item
;
661 Adapter
->WorkQueueTail
->Link
.Next
= (PSINGLE_LIST_ENTRY
)Item
;
662 Adapter
->WorkQueueTail
= Item
;
665 KeInsertQueueDpc(&Adapter
->MiniportDpc
, NULL
, NULL
);
667 return NDIS_STATUS_SUCCESS
;
674 PLOGICAL_ADAPTER Adapter
,
675 NDIS_WORK_ITEM_TYPE
*WorkItemType
,
676 PVOID
*WorkItemContext
)
678 * FUNCTION: Dequeues a work item from the work queue of a logical adapter
680 * Adapter = Pointer to the logical adapter object to dequeue work item from
681 * WorkItemType = Address of buffer for work item type
682 * WorkItemContext = Address of buffer for pointer to context information
684 * Adapter lock must be held when called
686 * Status of operation
689 PNDIS_MINIPORT_WORK_ITEM Item
;
691 NDIS_DbgPrint(MAX_TRACE
, ("Called.\n"));
693 Item
= Adapter
->WorkQueueHead
;
697 /* safe due to adapter lock held */
698 Adapter
->WorkQueueHead
= (PNDIS_MINIPORT_WORK_ITEM
)Item
->Link
.Next
;
700 if (Item
== Adapter
->WorkQueueTail
)
701 Adapter
->WorkQueueTail
= NULL
;
703 *WorkItemType
= Item
->WorkItemType
;
704 *WorkItemContext
= Item
->WorkItemContext
;
708 return NDIS_STATUS_SUCCESS
;
711 return NDIS_STATUS_FAILURE
;
717 PLOGICAL_ADAPTER Adapter
,
718 PNDIS_REQUEST NdisRequest
)
720 * FUNCTION: Sends a request to a miniport
722 * Adapter = Pointer to logical adapter object
723 * NdisRequest = Pointer to NDIS request structure describing request
725 * Status of operation
728 NDIS_DbgPrint(DEBUG_MINIPORT
, ("Called.\n"));
730 Adapter
->NdisMiniportBlock
.MediaRequest
= NdisRequest
;
732 switch (NdisRequest
->RequestType
)
734 case NdisRequestQueryInformation
:
735 return (*Adapter
->Miniport
->Chars
.QueryInformationHandler
)(
736 Adapter
->NdisMiniportBlock
.MiniportAdapterContext
,
737 NdisRequest
->DATA
.QUERY_INFORMATION
.Oid
,
738 NdisRequest
->DATA
.QUERY_INFORMATION
.InformationBuffer
,
739 NdisRequest
->DATA
.QUERY_INFORMATION
.InformationBufferLength
,
740 (PULONG
)&NdisRequest
->DATA
.QUERY_INFORMATION
.BytesWritten
,
741 (PULONG
)&NdisRequest
->DATA
.QUERY_INFORMATION
.BytesNeeded
);
744 case NdisRequestSetInformation
:
745 return (*Adapter
->Miniport
->Chars
.SetInformationHandler
)(
746 Adapter
->NdisMiniportBlock
.MiniportAdapterContext
,
747 NdisRequest
->DATA
.SET_INFORMATION
.Oid
,
748 NdisRequest
->DATA
.SET_INFORMATION
.InformationBuffer
,
749 NdisRequest
->DATA
.SET_INFORMATION
.InformationBufferLength
,
750 (PULONG
)&NdisRequest
->DATA
.SET_INFORMATION
.BytesRead
,
751 (PULONG
)&NdisRequest
->DATA
.SET_INFORMATION
.BytesNeeded
);
755 return NDIS_STATUS_FAILURE
;
760 #undef NdisMQueryInformationComplete
766 NdisMQueryInformationComplete(
767 IN NDIS_HANDLE MiniportAdapterHandle
,
768 IN NDIS_STATUS Status
)
770 PNDIS_MINIPORT_BLOCK MiniportBlock
=
771 (PNDIS_MINIPORT_BLOCK
)MiniportAdapterHandle
;
772 ASSERT(MiniportBlock
);
773 if( MiniportBlock
->QueryCompleteHandler
)
774 (MiniportBlock
->QueryCompleteHandler
)(MiniportAdapterHandle
, Status
);
778 VOID STDCALL
MiniportDpc(
780 IN PVOID DeferredContext
,
781 IN PVOID SystemArgument1
,
782 IN PVOID SystemArgument2
)
784 * FUNCTION: Deferred routine to handle serialization
786 * Dpc = Pointer to DPC object
787 * DeferredContext = Pointer to context information (LOGICAL_ADAPTER)
788 * SystemArgument1 = Unused
789 * SystemArgument2 = Unused
792 NDIS_STATUS NdisStatus
;
793 PVOID WorkItemContext
;
794 NDIS_WORK_ITEM_TYPE WorkItemType
;
795 PLOGICAL_ADAPTER Adapter
= GET_LOGICAL_ADAPTER(DeferredContext
);
797 NDIS_DbgPrint(DEBUG_MINIPORT
, ("Called.\n"));
799 NdisStatus
= MiniDequeueWorkItem(Adapter
, &WorkItemType
, &WorkItemContext
);
801 if (NdisStatus
== NDIS_STATUS_SUCCESS
)
803 switch (WorkItemType
)
805 case NdisWorkItemSend
:
807 * called by ProSend when protocols want to send packets to the miniport
810 MiniDisplayPacket((PNDIS_PACKET
)WorkItemContext
);
812 if(Adapter
->Miniport
->Chars
.SendPacketsHandler
)
814 NDIS_DbgPrint(MAX_TRACE
, ("Calling miniport's SendPackets handler\n"));
817 * XXX assumes single-packet - prolly OK since we'll call something
818 * different on multi-packet sends
820 (*Adapter
->Miniport
->Chars
.SendPacketsHandler
)(
821 Adapter
->NdisMiniportBlock
.MiniportAdapterContext
, (PPNDIS_PACKET
)&WorkItemContext
, 1);
823 NDIS_DbgPrint(MAX_TRACE
, ("back from miniport's SendPackets handler\n"));
827 NDIS_DbgPrint(MAX_TRACE
, ("Calling miniport's Send handler\n"));
829 NdisStatus
= (*Adapter
->Miniport
->Chars
.SendHandler
)(
830 Adapter
->NdisMiniportBlock
.MiniportAdapterContext
, (PNDIS_PACKET
)WorkItemContext
, 0);
832 NDIS_DbgPrint(MAX_TRACE
, ("back from miniport's Send handler\n"));
837 case NdisWorkItemSendLoopback
:
839 * called by ProSend when protocols want to send loopback packets
841 /* XXX atm ProIndicatePacket sends a packet up via the loopback adapter only */
842 NdisStatus
= ProIndicatePacket(Adapter
, (PNDIS_PACKET
)WorkItemContext
);
843 MiniSendComplete((NDIS_HANDLE
)Adapter
, (PNDIS_PACKET
)WorkItemContext
, NdisStatus
);
846 case NdisWorkItemReturnPackets
:
849 case NdisWorkItemResetRequested
:
852 case NdisWorkItemResetInProgress
:
855 case NdisWorkItemHalt
:
858 case NdisWorkItemMiniportCallback
:
861 case NdisWorkItemRequest
:
862 NdisStatus
= MiniDoRequest(Adapter
, (PNDIS_REQUEST
)WorkItemContext
);
864 if (NdisStatus
== NDIS_STATUS_PENDING
)
867 switch (((PNDIS_REQUEST
)WorkItemContext
)->RequestType
)
869 case NdisRequestQueryInformation
:
870 NdisMQueryInformationComplete((NDIS_HANDLE
)Adapter
, NdisStatus
);
873 case NdisRequestSetInformation
:
874 NdisMSetInformationComplete((NDIS_HANDLE
)Adapter
, NdisStatus
);
878 NDIS_DbgPrint(MIN_TRACE
, ("Unknown NDIS request type.\n"));
884 NDIS_DbgPrint(MIN_TRACE
, ("Unknown NDIS work item type (%d).\n", WorkItemType
));
897 IN NDIS_HANDLE LogHandle
)
909 IN NDIS_HANDLE MiniportAdapterHandle
,
911 OUT PNDIS_HANDLE LogHandle
)
915 return NDIS_STATUS_FAILURE
;
924 NdisMDeregisterAdapterShutdownHandler(
925 IN NDIS_HANDLE MiniportHandle
)
927 * FUNCTION: de-registers a shutdown handler
928 * ARGUMENTS: MiniportHandle: Handle passed into MiniportInitialize
931 NDIS_DbgPrint(DEBUG_MINIPORT
, ("Called.\n"));
932 PLOGICAL_ADAPTER Adapter
= (PLOGICAL_ADAPTER
)MiniportHandle
;
934 if(Adapter
->BugcheckContext
->ShutdownHandler
)
935 KeDeregisterBugCheckCallback(Adapter
->BugcheckContext
->CallbackRecord
);
945 IN NDIS_HANDLE LogHandle
)
950 #undef NdisMIndicateStatus
958 IN NDIS_HANDLE MiniportAdapterHandle
,
959 IN NDIS_STATUS GeneralStatus
,
960 IN PVOID StatusBuffer
,
961 IN UINT StatusBufferSize
)
966 #undef NdisMIndicateStatusComplete
973 NdisMIndicateStatusComplete(
974 IN NDIS_HANDLE MiniportAdapterHandle
)
985 NdisInitializeWrapper(
986 OUT PNDIS_HANDLE NdisWrapperHandle
,
987 IN PVOID SystemSpecific1
,
988 IN PVOID SystemSpecific2
,
989 IN PVOID SystemSpecific3
)
991 * FUNCTION: Notifies the NDIS library that a new miniport is initializing
993 * NdisWrapperHandle = Address of buffer to place NDIS wrapper handle
994 * SystemSpecific1 = Pointer to the driver's driver object
995 * SystemSpecific2 = Pointer to the driver's registry path
996 * SystemSpecific3 = Always NULL
998 * - SystemSpecific2 goes invalid so we copy it
1001 PMINIPORT_DRIVER Miniport
;
1002 PUNICODE_STRING RegistryPath
;
1003 WCHAR
*RegistryBuffer
;
1005 NDIS_DbgPrint(MAX_TRACE
, ("Called.\n"));
1007 ASSERT(NdisWrapperHandle
);
1009 *NdisWrapperHandle
= NULL
;
1011 #if BREAK_ON_MINIPORT_INIT
1012 __asm__ ("int $3\n");
1015 Miniport
= ExAllocatePool(NonPagedPool
, sizeof(MINIPORT_DRIVER
));
1019 NDIS_DbgPrint(MIN_TRACE
, ("Insufficient resources.\n"));
1023 RtlZeroMemory(Miniport
, sizeof(MINIPORT_DRIVER
));
1025 KeInitializeSpinLock(&Miniport
->Lock
);
1027 Miniport
->RefCount
= 1;
1029 Miniport
->DriverObject
= (PDRIVER_OBJECT
)SystemSpecific1
;
1031 /* set the miniport's driver registry path */
1032 RegistryPath
= ExAllocatePool(PagedPool
, sizeof(UNICODE_STRING
));
1035 NDIS_DbgPrint(MIN_TRACE
, ("Insufficient resources.\n"));
1039 RegistryPath
->Length
= ((PUNICODE_STRING
)SystemSpecific2
)->Length
;
1040 RegistryPath
->MaximumLength
= RegistryPath
->Length
+ sizeof(WCHAR
); /* room for 0-term */
1042 RegistryBuffer
= ExAllocatePool(PagedPool
, RegistryPath
->MaximumLength
);
1045 NDIS_DbgPrint(MIN_TRACE
, ("Insufficient resources.\n"));
1049 RtlCopyMemory(RegistryBuffer
, ((PUNICODE_STRING
)SystemSpecific2
)->Buffer
, RegistryPath
->Length
);
1050 RegistryBuffer
[RegistryPath
->Length
/sizeof(WCHAR
)] = 0;
1052 RegistryPath
->Buffer
= RegistryBuffer
;
1053 Miniport
->RegistryPath
= RegistryPath
;
1055 InitializeListHead(&Miniport
->AdapterListHead
);
1057 /* Put miniport in global miniport list */
1058 ExInterlockedInsertTailList(&MiniportListHead
, &Miniport
->ListEntry
, &MiniportListLock
);
1060 *NdisWrapperHandle
= Miniport
;
1064 VOID STDCALL
NdisIBugcheckCallback(
1068 * FUNCTION: Internal callback for handling bugchecks - calls adapter's shutdown handler
1070 * Buffer: Pointer to a bugcheck callback context
1074 PMINIPORT_BUGCHECK_CONTEXT Context
= (PMINIPORT_BUGCHECK_CONTEXT
)Buffer
;
1075 ADAPTER_SHUTDOWN_HANDLER sh
= (ADAPTER_SHUTDOWN_HANDLER
)Context
->ShutdownHandler
;
1077 NDIS_DbgPrint(DEBUG_MINIPORT
, ("Called.\n"));
1080 sh(Context
->DriverContext
);
1089 NdisMRegisterAdapterShutdownHandler(
1090 IN NDIS_HANDLE MiniportHandle
,
1091 IN PVOID ShutdownContext
,
1092 IN ADAPTER_SHUTDOWN_HANDLER ShutdownHandler
)
1094 * FUNCTION: Register a shutdown handler for an adapter
1096 * MiniportHandle: Handle originally passed into MiniportInitialize
1097 * ShutdownContext: Pre-initialized bugcheck context
1098 * ShutdownHandler: Function to call to handle the bugcheck
1100 * - I'm not sure about ShutdownContext
1101 * - FIXME - memory leak below
1104 PLOGICAL_ADAPTER Adapter
= (PLOGICAL_ADAPTER
)MiniportHandle
;
1105 PMINIPORT_BUGCHECK_CONTEXT BugcheckContext
= Adapter
->BugcheckContext
;
1107 NDIS_DbgPrint(DEBUG_MINIPORT
, ("Called.\n"));
1112 BugcheckContext
= ExAllocatePool(NonPagedPool
, sizeof(MINIPORT_BUGCHECK_CONTEXT
));
1113 if(!BugcheckContext
)
1115 NDIS_DbgPrint(MIN_TRACE
, ("Insufficient resources.\n"));
1119 BugcheckContext
->ShutdownHandler
= ShutdownHandler
;
1120 BugcheckContext
->DriverContext
= ShutdownContext
;
1122 /* not sure if this needs to be initialized or not... oh well, it's a leak. */
1123 BugcheckContext
->CallbackRecord
= ExAllocatePool(NonPagedPool
, sizeof(KBUGCHECK_CALLBACK_RECORD
));
1125 KeRegisterBugCheckCallback(BugcheckContext
->CallbackRecord
, NdisIBugcheckCallback
,
1126 BugcheckContext
, sizeof(BugcheckContext
), (PUCHAR
)"Ndis Miniport");
1132 PLOGICAL_ADAPTER Adapter
,
1133 NDIS_OID AddressOID
)
1135 * FUNCTION: Queries miniport for information
1137 * Adapter = Pointer to logical adapter
1138 * AddressOID = OID to use to query for current address
1140 * Status of operation
1144 NDIS_STATUS NdisStatus
;
1146 NDIS_DbgPrint(MAX_TRACE
, ("Called.\n"));
1148 /* Get MAC options for adapter */
1149 NdisStatus
= MiniQueryInformation(Adapter
, OID_GEN_MAC_OPTIONS
, 0, &BytesWritten
);
1151 if (NdisStatus
!= NDIS_STATUS_SUCCESS
)
1153 NDIS_DbgPrint(MIN_TRACE
, ("OID_GEN_MAC_OPTIONS failed. NdisStatus (0x%X).\n", NdisStatus
));
1157 RtlCopyMemory(&Adapter
->NdisMiniportBlock
.MacOptions
, Adapter
->QueryBuffer
, sizeof(UINT
));
1159 NDIS_DbgPrint(DEBUG_MINIPORT
, ("MacOptions (0x%X).\n", Adapter
->NdisMiniportBlock
.MacOptions
));
1161 /* Get current hardware address of adapter */
1162 NdisStatus
= MiniQueryInformation(Adapter
, AddressOID
, 0, &BytesWritten
);
1164 if (NdisStatus
!= NDIS_STATUS_SUCCESS
)
1166 NDIS_DbgPrint(MIN_TRACE
, ("Address OID (0x%X) failed. NdisStatus (0x%X).\n", AddressOID
, NdisStatus
));
1170 RtlCopyMemory(&Adapter
->Address
, Adapter
->QueryBuffer
, Adapter
->AddressLength
);
1175 PUCHAR A
= (PUCHAR
)&Adapter
->Address
.Type
.Medium802_3
;
1177 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]));
1181 /* Get maximum lookahead buffer size of adapter */
1182 NdisStatus
= MiniQueryInformation(Adapter
, OID_GEN_MAXIMUM_LOOKAHEAD
, 0, &BytesWritten
);
1184 if (NdisStatus
!= NDIS_STATUS_SUCCESS
)
1186 NDIS_DbgPrint(MIN_TRACE
, ("OID_GEN_MAXIMUM_LOOKAHEAD failed. NdisStatus (0x%X).\n", NdisStatus
));
1190 Adapter
->NdisMiniportBlock
.MaximumLookahead
= *((PULONG
)Adapter
->QueryBuffer
);
1192 NDIS_DbgPrint(DEBUG_MINIPORT
, ("MaxLookaheadLength (0x%X).\n", Adapter
->NdisMiniportBlock
.MaximumLookahead
));
1194 /* Get current lookahead buffer size of adapter */
1195 NdisStatus
= MiniQueryInformation(Adapter
, OID_GEN_CURRENT_LOOKAHEAD
, 0, &BytesWritten
);
1197 if (NdisStatus
!= NDIS_STATUS_SUCCESS
)
1199 NDIS_DbgPrint(MIN_TRACE
, ("OID_GEN_CURRENT_LOOKAHEAD failed. NdisStatus (0x%X).\n", NdisStatus
));
1203 Adapter
->NdisMiniportBlock
.CurrentLookahead
= *((PULONG
)Adapter
->QueryBuffer
);
1205 NDIS_DbgPrint(DEBUG_MINIPORT
, ("CurLookaheadLength (0x%X).\n", Adapter
->NdisMiniportBlock
.CurrentLookahead
));
1207 if (Adapter
->NdisMiniportBlock
.MaximumLookahead
!= 0)
1209 Adapter
->LookaheadLength
= Adapter
->NdisMiniportBlock
.MaximumLookahead
+ Adapter
->MediumHeaderSize
;
1210 Adapter
->LookaheadBuffer
= ExAllocatePool(NonPagedPool
, Adapter
->LookaheadLength
);
1212 if (!Adapter
->LookaheadBuffer
)
1213 return NDIS_STATUS_RESOURCES
;
1216 return STATUS_SUCCESS
;
1222 NdisIForwardIrpAndWaitCompletionRoutine(
1227 PKEVENT Event
= Context
;
1229 if (Irp
->PendingReturned
)
1230 KeSetEvent(Event
, IO_NO_INCREMENT
, FALSE
);
1232 return STATUS_MORE_PROCESSING_REQUIRED
;
1238 NdisIForwardIrpAndWait(PLOGICAL_ADAPTER Adapter
, PIRP Irp
)
1243 KeInitializeEvent(&Event
, NotificationEvent
, FALSE
);
1244 IoCopyCurrentIrpStackLocationToNext(Irp
);
1245 IoSetCompletionRoutine(Irp
, NdisIForwardIrpAndWaitCompletionRoutine
, &Event
, TRUE
, TRUE
, TRUE
);
1246 Status
= IoCallDriver(Adapter
->NdisMiniportBlock
.NextDeviceObject
, Irp
);
1247 if (Status
== STATUS_PENDING
)
1249 KeWaitForSingleObject(&Event
, Executive
, KernelMode
, FALSE
, NULL
);
1250 Status
= Irp
->IoStatus
.Status
;
1258 NdisIPnPStartDevice(
1259 IN PDEVICE_OBJECT DeviceObject
,
1262 * FUNCTION: Handle the PnP start device event
1264 * DeviceObejct = Functional Device Object
1265 * Irp = IRP_MN_START_DEVICE I/O request packet
1267 * Status of operation
1270 PIO_STACK_LOCATION Stack
= IoGetCurrentIrpStackLocation(Irp
);
1271 PLOGICAL_ADAPTER Adapter
= (PLOGICAL_ADAPTER
)DeviceObject
->DeviceExtension
;
1272 NDIS_WRAPPER_CONTEXT WrapperContext
;
1273 NDIS_STATUS NdisStatus
;
1274 NDIS_STATUS OpenErrorStatus
;
1276 UINT SelectedMediumIndex
= 0;
1277 NDIS_OID AddressOID
;
1279 ULONG ResourceCount
;
1280 ULONG ResourceListSize
;
1281 UNICODE_STRING ParamName
;
1282 PNDIS_CONFIGURATION_PARAMETER ConfigParam
;
1283 NDIS_HANDLE ConfigHandle
;
1288 * Prepare wrapper context used by HW and configuration routines.
1291 Status
= IoOpenDeviceRegistryKey(
1292 Adapter
->NdisMiniportBlock
.PhysicalDeviceObject
, PLUGPLAY_REGKEY_DRIVER
,
1293 KEY_ALL_ACCESS
, &WrapperContext
.RegistryHandle
);
1294 if (!NT_SUCCESS(Status
))
1296 NDIS_DbgPrint(MIN_TRACE
,("failed to open adapter-specific reg key\n"));
1300 NDIS_DbgPrint(MAX_TRACE
, ("opened device reg key\n"));
1302 WrapperContext
.DeviceObject
= Adapter
->NdisMiniportBlock
.DeviceObject
;
1305 * Store the adapter resources used by HW routines such as
1306 * NdisMQueryAdapterResources.
1309 if (Stack
->Parameters
.StartDevice
.AllocatedResources
!= NULL
&&
1310 Stack
->Parameters
.StartDevice
.AllocatedResourcesTranslated
!= NULL
)
1312 ResourceCount
= Stack
->Parameters
.StartDevice
.AllocatedResources
->List
[0].
1313 PartialResourceList
.Count
;
1315 FIELD_OFFSET(CM_RESOURCE_LIST
, List
[0].PartialResourceList
.
1316 PartialDescriptors
[ResourceCount
]);
1318 Adapter
->NdisMiniportBlock
.AllocatedResources
=
1319 ExAllocatePool(PagedPool
, ResourceListSize
);
1320 if (Adapter
->NdisMiniportBlock
.AllocatedResources
== NULL
)
1322 return STATUS_INSUFFICIENT_RESOURCES
;
1325 Adapter
->NdisMiniportBlock
.AllocatedResourcesTranslated
=
1326 ExAllocatePool(PagedPool
, ResourceListSize
);
1327 if (Adapter
->NdisMiniportBlock
.AllocatedResourcesTranslated
== NULL
)
1329 ExFreePool(Adapter
->NdisMiniportBlock
.AllocatedResources
);
1330 Adapter
->NdisMiniportBlock
.AllocatedResources
= NULL
;
1331 return STATUS_INSUFFICIENT_RESOURCES
;
1334 RtlCopyMemory(Adapter
->NdisMiniportBlock
.AllocatedResources
,
1335 Stack
->Parameters
.StartDevice
.AllocatedResources
,
1338 RtlCopyMemory(Adapter
->NdisMiniportBlock
.AllocatedResourcesTranslated
,
1339 Stack
->Parameters
.StartDevice
.AllocatedResourcesTranslated
,
1344 * Store the Bus Type, Bus Number and Slot information. It's used by
1345 * the hardware routines then.
1348 NdisOpenConfiguration(&NdisStatus
, &ConfigHandle
, (NDIS_HANDLE
)&WrapperContext
);
1350 Size
= sizeof(ULONG
);
1351 Status
= IoGetDeviceProperty(Adapter
->NdisMiniportBlock
.PhysicalDeviceObject
,
1352 DevicePropertyLegacyBusType
, Size
,
1353 &Adapter
->NdisMiniportBlock
.BusType
, &Size
);
1354 if (!NT_SUCCESS(Status
) || Adapter
->NdisMiniportBlock
.BusType
== -1)
1356 NdisInitUnicodeString(&ParamName
, L
"BusType");
1357 NdisReadConfiguration(&NdisStatus
, &ConfigParam
, ConfigHandle
,
1358 &ParamName
, NdisParameterInteger
);
1359 if (NdisStatus
== NDIS_STATUS_SUCCESS
)
1360 Adapter
->NdisMiniportBlock
.BusType
= ConfigParam
->ParameterData
.IntegerData
;
1362 Adapter
->NdisMiniportBlock
.BusType
= Isa
;
1365 Status
= IoGetDeviceProperty(Adapter
->NdisMiniportBlock
.PhysicalDeviceObject
,
1366 DevicePropertyBusNumber
, Size
,
1367 &Adapter
->NdisMiniportBlock
.BusNumber
, &Size
);
1368 if (!NT_SUCCESS(Status
) || Adapter
->NdisMiniportBlock
.BusNumber
== -1)
1370 NdisInitUnicodeString(&ParamName
, L
"BusNumber");
1371 NdisReadConfiguration(&NdisStatus
, &ConfigParam
, ConfigHandle
,
1372 &ParamName
, NdisParameterInteger
);
1373 if (NdisStatus
== NDIS_STATUS_SUCCESS
)
1374 Adapter
->NdisMiniportBlock
.BusNumber
= ConfigParam
->ParameterData
.IntegerData
;
1376 Adapter
->NdisMiniportBlock
.BusNumber
= 0;
1378 WrapperContext
.BusNumber
= Adapter
->NdisMiniportBlock
.BusNumber
;
1380 Status
= IoGetDeviceProperty(Adapter
->NdisMiniportBlock
.PhysicalDeviceObject
,
1381 DevicePropertyAddress
, Size
,
1382 &Adapter
->NdisMiniportBlock
.SlotNumber
, &Size
);
1383 if (!NT_SUCCESS(Status
) || Adapter
->NdisMiniportBlock
.SlotNumber
== -1)
1385 NdisInitUnicodeString(&ParamName
, L
"SlotNumber");
1386 NdisReadConfiguration(&NdisStatus
, &ConfigParam
, ConfigHandle
,
1387 &ParamName
, NdisParameterInteger
);
1388 if (NdisStatus
== NDIS_STATUS_SUCCESS
)
1389 Adapter
->NdisMiniportBlock
.SlotNumber
= ConfigParam
->ParameterData
.IntegerData
;
1391 Adapter
->NdisMiniportBlock
.SlotNumber
= 0;
1394 NdisCloseConfiguration(ConfigHandle
);
1397 * Call MiniportInitialize.
1400 NDIS_DbgPrint(MID_TRACE
, ("calling MiniportInitialize\n"));
1401 NdisStatus
= (*Adapter
->Miniport
->Chars
.InitializeHandler
)(
1402 &OpenErrorStatus
, &SelectedMediumIndex
, &MediaArray
[0],
1403 MEDIA_ARRAY_SIZE
, Adapter
, (NDIS_HANDLE
)&WrapperContext
);
1405 ZwClose(WrapperContext
.RegistryHandle
);
1407 if (NdisStatus
!= NDIS_STATUS_SUCCESS
||
1408 SelectedMediumIndex
>= MEDIA_ARRAY_SIZE
)
1410 NDIS_DbgPrint(MIN_TRACE
, ("MiniportInitialize() failed for an adapter.\n"));
1411 return (NTSTATUS
)NdisStatus
;
1414 /* Set handlers (some NDIS macros require these) */
1416 Adapter
->NdisMiniportBlock
.EthRxCompleteHandler
= EthFilterDprIndicateReceiveComplete
;
1417 Adapter
->NdisMiniportBlock
.EthRxIndicateHandler
= EthFilterDprIndicateReceive
;
1418 Adapter
->NdisMiniportBlock
.SendCompleteHandler
= MiniSendComplete
;
1419 Adapter
->NdisMiniportBlock
.SendResourcesHandler
= MiniSendResourcesAvailable
;
1420 Adapter
->NdisMiniportBlock
.ResetCompleteHandler
= MiniResetComplete
;
1421 Adapter
->NdisMiniportBlock
.TDCompleteHandler
= MiniTransferDataComplete
;
1422 Adapter
->NdisMiniportBlock
.PacketIndicateHandler
= MiniIndicateReceivePacket
;
1424 Adapter
->NdisMiniportBlock
.MediaType
= MediaArray
[SelectedMediumIndex
];
1426 switch (Adapter
->NdisMiniportBlock
.MediaType
)
1428 case NdisMedium802_3
:
1429 Adapter
->MediumHeaderSize
= 14; /* XXX figure out what to do about LLC */
1430 AddressOID
= OID_802_3_CURRENT_ADDRESS
;
1431 Adapter
->AddressLength
= ETH_LENGTH_OF_ADDRESS
;
1432 NdisStatus
= DoQueries(Adapter
, AddressOID
);
1433 if (NdisStatus
== NDIS_STATUS_SUCCESS
)
1435 Success
= EthCreateFilter(32, /* FIXME: Query this from miniport. */
1436 Adapter
->Address
.Type
.Medium802_3
,
1437 &Adapter
->NdisMiniportBlock
.FilterDbs
.EthDB
);
1439 Adapter
->NdisMiniportBlock
.FilterDbs
.EthDB
->Miniport
= (PNDIS_MINIPORT_BLOCK
)Adapter
;
1441 NdisStatus
= NDIS_STATUS_RESOURCES
;
1446 /* FIXME: Support other types of media */
1447 NDIS_DbgPrint(MIN_TRACE
, ("error: unsupported media\n"));
1449 KeReleaseSpinLock(&Adapter
->NdisMiniportBlock
.Lock
, OldIrql
);
1450 return STATUS_UNSUCCESSFUL
;
1453 if (!Success
|| NdisStatus
!= NDIS_STATUS_SUCCESS
)
1455 NDIS_DbgPrint(MAX_TRACE
, ("couldn't create filter (%x)\n", NdisStatus
));
1456 if (Adapter
->LookaheadBuffer
)
1458 ExFreePool(Adapter
->LookaheadBuffer
);
1459 Adapter
->LookaheadBuffer
= NULL
;
1461 return (NTSTATUS
)NdisStatus
;
1464 Adapter
->NdisMiniportBlock
.OldPnPDeviceState
= Adapter
->NdisMiniportBlock
.PnPDeviceState
;
1465 Adapter
->NdisMiniportBlock
.PnPDeviceState
= NdisPnPDeviceStarted
;
1467 /* Put adapter in adapter list for this miniport */
1468 ExInterlockedInsertTailList(&Adapter
->Miniport
->AdapterListHead
, &Adapter
->MiniportListEntry
, &Adapter
->Miniport
->Lock
);
1470 /* Put adapter in global adapter list */
1471 ExInterlockedInsertTailList(&AdapterListHead
, &Adapter
->ListEntry
, &AdapterListLock
);
1473 return STATUS_SUCCESS
;
1480 IN PDEVICE_OBJECT DeviceObject
,
1483 * FUNCTION: Handle the PnP stop device event
1485 * DeviceObejct = Functional Device Object
1486 * Irp = IRP_MN_STOP_DEVICE I/O request packet
1488 * Status of operation
1491 PLOGICAL_ADAPTER Adapter
= (PLOGICAL_ADAPTER
)DeviceObject
->DeviceExtension
;
1494 /* Remove adapter from adapter list for this miniport */
1495 KeAcquireSpinLock(&Adapter
->Miniport
->Lock
, &OldIrql
);
1496 RemoveEntryList(&Adapter
->MiniportListEntry
);
1497 KeReleaseSpinLock(&Adapter
->Miniport
->Lock
, OldIrql
);
1499 /* Remove adapter from global adapter list */
1500 KeAcquireSpinLock(&AdapterListLock
, &OldIrql
);
1501 RemoveEntryList(&Adapter
->ListEntry
);
1502 KeReleaseSpinLock(&AdapterListLock
, OldIrql
);
1504 (*Adapter
->Miniport
->Chars
.HaltHandler
)(Adapter
);
1506 if (Adapter
->LookaheadBuffer
)
1508 ExFreePool(Adapter
->LookaheadBuffer
);
1509 Adapter
->LookaheadBuffer
= NULL
;
1511 if (Adapter
->NdisMiniportBlock
.AllocatedResources
)
1513 ExFreePool(Adapter
->NdisMiniportBlock
.AllocatedResources
);
1514 Adapter
->NdisMiniportBlock
.AllocatedResources
= NULL
;
1516 if (Adapter
->NdisMiniportBlock
.AllocatedResourcesTranslated
)
1518 ExFreePool(Adapter
->NdisMiniportBlock
.AllocatedResourcesTranslated
);
1519 Adapter
->NdisMiniportBlock
.AllocatedResourcesTranslated
= NULL
;
1522 Adapter
->NdisMiniportBlock
.OldPnPDeviceState
= Adapter
->NdisMiniportBlock
.PnPDeviceState
;
1523 Adapter
->NdisMiniportBlock
.PnPDeviceState
= NdisPnPDeviceStopped
;
1525 return STATUS_SUCCESS
;
1532 IN PDEVICE_OBJECT DeviceObject
,
1535 PIO_STACK_LOCATION Stack
= IoGetCurrentIrpStackLocation(Irp
);
1536 PLOGICAL_ADAPTER Adapter
= (PLOGICAL_ADAPTER
)DeviceObject
->DeviceExtension
;
1539 switch (Stack
->MinorFunction
)
1541 case IRP_MN_START_DEVICE
:
1542 Status
= NdisIForwardIrpAndWait(Adapter
, Irp
);
1543 if (NT_SUCCESS(Status
) && NT_SUCCESS(Irp
->IoStatus
.Status
))
1545 Status
= NdisIPnPStartDevice(DeviceObject
, Irp
);
1547 Irp
->IoStatus
.Status
= Status
;
1548 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
1551 case IRP_MN_STOP_DEVICE
:
1553 Status
= NdisIForwardIrpAndWait(Adapter
, Irp
);
1554 if (NT_SUCCESS(Status
) && NT_SUCCESS(Irp
->IoStatus
.Status
))
1556 Status
= NdisIPnPStopDevice(DeviceObject
, Irp
);
1558 Irp
->IoStatus
.Status
= Status
;
1559 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
1563 IoSkipCurrentIrpStackLocation(Irp
);
1564 return IoCallDriver(Adapter
->NdisMiniportBlock
.NextDeviceObject
, Irp
);
1574 IN PDRIVER_OBJECT DriverObject
,
1575 IN PDEVICE_OBJECT PhysicalDeviceObject
)
1577 * FUNCTION: Create a device for an adapter found using PnP
1579 * DriverObject = Pointer to the miniport driver object
1580 * PhysicalDeviceObject = Pointer to the PDO for our adapter
1583 static const WCHAR ClassKeyName
[] = {'C','l','a','s','s','\\'};
1584 static const WCHAR LinkageKeyName
[] = {'\\','L','i','n','k','a','g','e',0};
1585 PMINIPORT_DRIVER Miniport
;
1586 PMINIPORT_DRIVER
*MiniportPtr
;
1587 WCHAR
*LinkageKeyBuffer
;
1588 ULONG DriverKeyLength
;
1589 RTL_QUERY_REGISTRY_TABLE QueryTable
[2];
1590 UNICODE_STRING ExportName
;
1591 PDEVICE_OBJECT DeviceObject
;
1592 PLOGICAL_ADAPTER Adapter
;
1596 * Gain the access to the miniport data structure first.
1599 MiniportPtr
= IoGetDriverObjectExtension(DriverObject
, (PVOID
)TAG('D','I','M','N'));
1600 if (MiniportPtr
== NULL
)
1602 NDIS_DbgPrint(DEBUG_MINIPORT
, ("Can't get driver object extension.\n"));
1603 return STATUS_UNSUCCESSFUL
;
1605 Miniport
= *MiniportPtr
;
1608 * Get name of the Linkage registry key for our adapter. It's located under
1609 * the driver key for our driver and so we have basicly two ways to do it.
1610 * Either we can use IoOpenDriverRegistryKey or compose it using information
1611 * gathered by IoGetDeviceProperty. I choosed the second because
1612 * IoOpenDriverRegistryKey wasn't implemented at the time of writing.
1615 Status
= IoGetDeviceProperty(PhysicalDeviceObject
, DevicePropertyDriverKeyName
,
1616 0, NULL
, &DriverKeyLength
);
1617 if (Status
!= STATUS_BUFFER_TOO_SMALL
)
1619 NDIS_DbgPrint(DEBUG_MINIPORT
, ("Can't get miniport driver key length.\n"));
1623 LinkageKeyBuffer
= ExAllocatePool(PagedPool
, DriverKeyLength
+
1624 sizeof(ClassKeyName
) + sizeof(LinkageKeyName
));
1625 if (LinkageKeyBuffer
== NULL
)
1627 NDIS_DbgPrint(DEBUG_MINIPORT
, ("Can't allocate memory for driver key name.\n"));
1628 return STATUS_INSUFFICIENT_RESOURCES
;
1631 Status
= IoGetDeviceProperty(PhysicalDeviceObject
, DevicePropertyDriverKeyName
,
1632 DriverKeyLength
, LinkageKeyBuffer
+
1633 (sizeof(ClassKeyName
) / sizeof(WCHAR
)),
1635 if (!NT_SUCCESS(Status
))
1637 NDIS_DbgPrint(DEBUG_MINIPORT
, ("Can't get miniport driver key.\n"));
1638 ExFreePool(LinkageKeyBuffer
);
1642 /* Compose the linkage key name. */
1643 RtlCopyMemory(LinkageKeyBuffer
, ClassKeyName
, sizeof(ClassKeyName
));
1644 RtlCopyMemory(LinkageKeyBuffer
+ ((sizeof(ClassKeyName
) + DriverKeyLength
) /
1645 sizeof(WCHAR
)) - 1, LinkageKeyName
, sizeof(LinkageKeyName
));
1647 NDIS_DbgPrint(DEBUG_MINIPORT
, ("LinkageKey: %S.\n", LinkageKeyBuffer
));
1650 * Now open the linkage key and read the "Export" and "RootDevice" values
1651 * which contains device name and root service respectively.
1654 RtlZeroMemory(QueryTable
, sizeof(QueryTable
));
1655 RtlInitUnicodeString(&ExportName
, NULL
);
1656 QueryTable
[0].Flags
= RTL_QUERY_REGISTRY_REQUIRED
| RTL_QUERY_REGISTRY_DIRECT
;
1657 QueryTable
[0].Name
= L
"Export";
1658 QueryTable
[0].EntryContext
= &ExportName
;
1660 Status
= RtlQueryRegistryValues(RTL_REGISTRY_CONTROL
, LinkageKeyBuffer
,
1661 QueryTable
, NULL
, NULL
);
1662 ExFreePool(LinkageKeyBuffer
);
1663 if (!NT_SUCCESS(Status
))
1665 NDIS_DbgPrint(DEBUG_MINIPORT
, ("Can't get miniport device name. (%x)\n", Status
));
1670 * Create the device object.
1673 NDIS_DbgPrint(MAX_TRACE
, ("creating device %wZ\n", &ExportName
));
1675 Status
= IoCreateDevice(Miniport
->DriverObject
, sizeof(LOGICAL_ADAPTER
),
1676 &ExportName
, FILE_DEVICE_PHYSICAL_NETCARD
,
1677 0, FALSE
, &DeviceObject
);
1678 if (!NT_SUCCESS(Status
))
1680 NDIS_DbgPrint(MIN_TRACE
, ("Could not create device object.\n"));
1681 RtlFreeUnicodeString(&ExportName
);
1686 * Initialize the adapter structure.
1689 Adapter
= (PLOGICAL_ADAPTER
)DeviceObject
->DeviceExtension
;
1690 KeInitializeSpinLock(&Adapter
->NdisMiniportBlock
.Lock
);
1691 InitializeListHead(&Adapter
->ProtocolListHead
);
1692 Adapter
->RefCount
= 1;
1693 Adapter
->Miniport
= Miniport
;
1695 Adapter
->NdisMiniportBlock
.MiniportName
= ExportName
;
1697 Adapter
->NdisMiniportBlock
.DeviceObject
= DeviceObject
;
1698 Adapter
->NdisMiniportBlock
.PhysicalDeviceObject
= PhysicalDeviceObject
;
1699 Adapter
->NdisMiniportBlock
.NextDeviceObject
=
1700 IoAttachDeviceToDeviceStack(Adapter
->NdisMiniportBlock
.DeviceObject
,
1701 PhysicalDeviceObject
);
1703 Adapter
->NdisMiniportBlock
.OldPnPDeviceState
= 0;
1704 Adapter
->NdisMiniportBlock
.PnPDeviceState
= NdisPnPDeviceAdded
;
1706 KeInitializeDpc(&Adapter
->MiniportDpc
, MiniportDpc
, (PVOID
)Adapter
);
1708 DeviceObject
->Flags
&= ~DO_DEVICE_INITIALIZING
;
1710 return STATUS_SUCCESS
;
1719 NdisMRegisterMiniport(
1720 IN NDIS_HANDLE NdisWrapperHandle
,
1721 IN PNDIS_MINIPORT_CHARACTERISTICS MiniportCharacteristics
,
1722 IN UINT CharacteristicsLength
)
1724 * FUNCTION: Registers a miniport's MiniportXxx entry points with the NDIS library
1726 * NdisWrapperHandle = Pointer to handle returned by NdisMInitializeWrapper
1727 * MiniportCharacteristics = Pointer to a buffer with miniport characteristics
1728 * CharacteristicsLength = Number of bytes in characteristics buffer
1730 * Status of operation
1734 PMINIPORT_DRIVER Miniport
= GET_MINIPORT_DRIVER(NdisWrapperHandle
);
1735 PMINIPORT_DRIVER
*MiniportPtr
;
1738 NDIS_DbgPrint(MAX_TRACE
, ("Called.\n"));
1740 switch (MiniportCharacteristics
->MajorNdisVersion
)
1743 MinSize
= sizeof(NDIS30_MINIPORT_CHARACTERISTICS
);
1747 MinSize
= sizeof(NDIS40_MINIPORT_CHARACTERISTICS
);
1751 MinSize
= sizeof(NDIS50_MINIPORT_CHARACTERISTICS
);
1755 NDIS_DbgPrint(DEBUG_MINIPORT
, ("Bad miniport characteristics version.\n"));
1756 return NDIS_STATUS_BAD_VERSION
;
1759 if (CharacteristicsLength
< MinSize
)
1761 NDIS_DbgPrint(DEBUG_MINIPORT
, ("Bad miniport characteristics.\n"));
1762 return NDIS_STATUS_BAD_CHARACTERISTICS
;
1765 /* Check if mandatory MiniportXxx functions are specified */
1766 if ((!MiniportCharacteristics
->HaltHandler
) ||
1767 (!MiniportCharacteristics
->InitializeHandler
)||
1768 (!MiniportCharacteristics
->QueryInformationHandler
) ||
1769 (!MiniportCharacteristics
->ResetHandler
) ||
1770 (!MiniportCharacteristics
->SetInformationHandler
))
1772 NDIS_DbgPrint(DEBUG_MINIPORT
, ("Bad miniport characteristics.\n"));
1773 return NDIS_STATUS_BAD_CHARACTERISTICS
;
1776 if (MiniportCharacteristics
->MajorNdisVersion
== 0x03)
1778 if (!MiniportCharacteristics
->SendHandler
)
1780 NDIS_DbgPrint(DEBUG_MINIPORT
, ("Bad miniport characteristics.\n"));
1781 return NDIS_STATUS_BAD_CHARACTERISTICS
;
1784 else if (MiniportCharacteristics
->MajorNdisVersion
>= 0x04)
1787 if ((!MiniportCharacteristics
->SendHandler
) &&
1788 (!MiniportCharacteristics
->SendPacketsHandler
))
1790 NDIS_DbgPrint(DEBUG_MINIPORT
, ("Bad miniport characteristics.\n"));
1791 return NDIS_STATUS_BAD_CHARACTERISTICS
;
1795 /* TODO: verify NDIS5 and NDIS5.1 */
1797 RtlCopyMemory(&Miniport
->Chars
, MiniportCharacteristics
, MinSize
);
1800 * NOTE: This is VERY unoptimal! Should we store the MINIPORT_DRIVER
1801 * struture in the driver extension or what?
1804 Status
= IoAllocateDriverObjectExtension(Miniport
->DriverObject
, (PVOID
)TAG('D','I','M','N'),
1805 sizeof(PMINIPORT_DRIVER
), (PVOID
*)&MiniportPtr
);
1806 if (!NT_SUCCESS(Status
))
1808 NDIS_DbgPrint(DEBUG_MINIPORT
, ("Can't allocate driver object extension.\n"));
1809 return NDIS_STATUS_RESOURCES
;
1812 *MiniportPtr
= Miniport
;
1814 Miniport
->DriverObject
->MajorFunction
[IRP_MJ_PNP
] = NdisIDispatchPnp
;
1815 Miniport
->DriverObject
->DriverExtension
->AddDevice
= NdisIAddDevice
;
1817 return NDIS_STATUS_SUCCESS
;
1827 IN NDIS_HANDLE MiniportAdapterHandle
,
1828 IN NDIS_STATUS Status
,
1829 IN BOOLEAN AddressingReset
)
1831 MiniResetComplete(MiniportAdapterHandle
, Status
, AddressingReset
);
1834 #undef NdisMSendComplete
1843 IN NDIS_HANDLE MiniportAdapterHandle
,
1844 IN PNDIS_PACKET Packet
,
1845 IN NDIS_STATUS Status
)
1847 * FUNCTION: Forwards a message to the initiating protocol saying
1848 * that a packet was handled
1850 * NdisAdapterHandle = Handle input to MiniportInitialize
1851 * Packet = Pointer to NDIS packet that was sent
1852 * Status = Status of send operation
1855 MiniSendComplete(MiniportAdapterHandle
, Packet
, Status
);
1864 NdisMSendResourcesAvailable(
1865 IN NDIS_HANDLE MiniportAdapterHandle
)
1867 MiniSendResourcesAvailable(MiniportAdapterHandle
);
1876 NdisMTransferDataComplete(
1877 IN NDIS_HANDLE MiniportAdapterHandle
,
1878 IN PNDIS_PACKET Packet
,
1879 IN NDIS_STATUS Status
,
1880 IN UINT BytesTransferred
)
1882 MiniTransferDataComplete(MiniportAdapterHandle
, Packet
, Status
, BytesTransferred
);
1885 #undef NdisMSetInformationComplete
1893 NdisMSetInformationComplete(
1894 IN NDIS_HANDLE MiniportAdapterHandle
,
1895 IN NDIS_STATUS Status
)
1897 (*((PNDIS_MINIPORT_BLOCK
)(MiniportAdapterHandle
))->SetCompleteHandler
)(MiniportAdapterHandle
, Status
);
1900 #undef NdisMSetAttributes
1909 IN NDIS_HANDLE MiniportAdapterHandle
,
1910 IN NDIS_HANDLE MiniportAdapterContext
,
1911 IN BOOLEAN BusMaster
,
1912 IN NDIS_INTERFACE_TYPE AdapterType
)
1914 * FUNCTION: Informs the NDIS library of significant features of the caller's NIC
1916 * MiniportAdapterHandle = Handle input to MiniportInitialize
1917 * MiniportAdapterContext = Pointer to context information
1918 * BusMaster = Specifies TRUE if the caller's NIC is a busmaster DMA device
1919 * AdapterType = Specifies the I/O bus interface of the caller's NIC
1922 NDIS_DbgPrint(MAX_TRACE
, ("Called.\n"));
1923 NdisMSetAttributesEx(MiniportAdapterContext
, MiniportAdapterContext
, 0,
1924 BusMaster
? NDIS_ATTRIBUTE_BUS_MASTER
: 0,
1934 NdisMSetAttributesEx(
1935 IN NDIS_HANDLE MiniportAdapterHandle
,
1936 IN NDIS_HANDLE MiniportAdapterContext
,
1937 IN UINT CheckForHangTimeInSeconds OPTIONAL
,
1938 IN ULONG AttributeFlags
,
1939 IN NDIS_INTERFACE_TYPE AdapterType
)
1941 * FUNCTION: Informs the NDIS library of significant features of the caller's NIC
1943 * MiniportAdapterHandle = Handle input to MiniportInitialize
1944 * MiniportAdapterContext = Pointer to context information
1945 * CheckForHangTimeInSeconds = Specifies interval in seconds at which
1946 * MiniportCheckForHang should be called
1947 * AttributeFlags = Bitmask that indicates specific attributes
1948 * AdapterType = Specifies the I/O bus interface of the caller's NIC
1951 /* TODO: Take CheckForHandTimeInSeconds into account! */
1953 PLOGICAL_ADAPTER Adapter
= GET_LOGICAL_ADAPTER(MiniportAdapterHandle
);
1955 NDIS_DbgPrint(MAX_TRACE
, ("Called.\n"));
1957 Adapter
->NdisMiniportBlock
.MiniportAdapterContext
= MiniportAdapterContext
;
1958 Adapter
->NdisMiniportBlock
.Flags
= AttributeFlags
;
1959 Adapter
->NdisMiniportBlock
.AdapterType
= AdapterType
;
1960 Adapter
->AttributesSet
= TRUE
;
1961 if (AttributeFlags
& NDIS_ATTRIBUTE_INTERMEDIATE_DRIVER
)
1962 NDIS_DbgPrint(MAX_TRACE
, ("Intermediate drivers not supported yet.\n"));
1972 IN ULONG MicrosecondsToSleep
)
1974 * FUNCTION: delay the thread's execution for MicrosecondsToSleep
1976 * MicrosecondsToSleep: duh...
1978 * - Because this is a blocking call, current IRQL must be < DISPATCH_LEVEL
1982 LARGE_INTEGER DueTime
;
1986 DueTime
.QuadPart
= (-1) * 10 * MicrosecondsToSleep
;
1988 KeInitializeTimer(&Timer
);
1989 KeSetTimer(&Timer
, DueTime
, 0);
1990 KeWaitForSingleObject(&Timer
, Executive
, KernelMode
, FALSE
, 0);
1999 NdisMSynchronizeWithInterrupt(
2000 IN PNDIS_MINIPORT_INTERRUPT Interrupt
,
2001 IN PVOID SynchronizeFunction
,
2002 IN PVOID SynchronizeContext
)
2004 return(KeSynchronizeExecution(Interrupt
->InterruptObject
,
2005 (PKSYNCHRONIZE_ROUTINE
)SynchronizeFunction
,
2006 SynchronizeContext
));
2016 IN NDIS_HANDLE LogHandle
,
2018 IN UINT LogBufferSize
)
2022 return NDIS_STATUS_FAILURE
;
2031 NdisTerminateWrapper(
2032 IN NDIS_HANDLE NdisWrapperHandle
,
2033 IN PVOID SystemSpecific
)
2035 * FUNCTION: Releases resources allocated by a call to NdisInitializeWrapper
2037 * NdisWrapperHandle = Handle returned by NdisInitializeWrapper (MINIPORT_DRIVER)
2038 * SystemSpecific = Always NULL
2041 PMINIPORT_DRIVER Miniport
= GET_MINIPORT_DRIVER(NdisWrapperHandle
);
2043 NDIS_DbgPrint(MAX_TRACE
, ("Called.\n"));
2045 ExFreePool(Miniport
->RegistryPath
->Buffer
);
2046 ExFreePool(Miniport
->RegistryPath
);
2047 ExFreePool(Miniport
);