2 * COPYRIGHT: See COPYING in the top level directory
3 * PROJECT: ReactOS NDIS library
4 * FILE: ndis/miniport.c
5 * PURPOSE: Routines used by NDIS miniport drivers
6 * PROGRAMMERS: Casper S. Hornstrup (chorns@users.sourceforge.net)
7 * Vizzini (vizzini@plasmic.com)
9 * CSH 01/08-2000 Created
10 * 20 Aug 2003 vizzini - DMA support
11 * 3 Oct 2003 vizzini - SendPackets support
20 /* Root of the scm database */
21 #define SERVICES_ROOT L"\\Registry\\Machine\\System\\CurrentControlSet\\Services\\"
24 * Define to 1 to get a debugger breakpoint at the end of NdisInitializeWrapper
25 * for each new miniport starting up
27 #define BREAK_ON_MINIPORT_INIT 0
30 * This has to be big enough to hold the results of querying the Route value
31 * from the Linkage key. Please re-code me to determine this dynamically.
33 #define ROUTE_DATA_SIZE 256
35 /* Number of media we know */
36 #define MEDIA_ARRAY_SIZE 15
38 static NDIS_MEDIUM MediaArray
[MEDIA_ARRAY_SIZE
] =
47 NdisMediumArcnet878_2
,
49 NdisMediumWirelessWan
,
57 /* global list and lock of Miniports NDIS has registered */
58 LIST_ENTRY MiniportListHead
;
59 KSPIN_LOCK MiniportListLock
;
61 /* global list and lock of adapters NDIS has registered */
62 LIST_ENTRY AdapterListHead
;
63 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 someobdy 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
.u4
.ReceiveHandler
)
214 NDIS_DbgPrint(MIN_TRACE
, ("AdapterBinding->ProtocolBinding->Chars.u4.ReceiveHandler was null\n"));
221 ("XXX (%x) %x %x %x %x %x %x %x XXX\n",
222 *AdapterBinding
->ProtocolBinding
->Chars
.u4
.ReceiveHandler
,
223 AdapterBinding
->NdisOpenBlock
.ProtocolBindingContext
,
231 /* call the receive handler */
232 (*AdapterBinding
->ProtocolBinding
->Chars
.u4
.ReceiveHandler
)(
233 AdapterBinding
->NdisOpenBlock
.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);
313 MiniEthReceiveComplete(
314 IN PETH_FILTER Filter
)
316 * FUNCTION: Receive indication complete function for Ethernet devices
318 * Filter = Pointer to Ethernet filter
322 PLIST_ENTRY CurrentEntry
;
323 PLOGICAL_ADAPTER Adapter
;
324 PADAPTER_BINDING AdapterBinding
;
326 NDIS_DbgPrint(DEBUG_MINIPORT
, ("Called.\n"));
328 if( !Filter
) return;
330 Adapter
= (PLOGICAL_ADAPTER
)Filter
->Miniport
;
332 NDIS_DbgPrint(MAX_TRACE
, ("acquiring miniport block lock\n"));
333 KeAcquireSpinLock(&Adapter
->NdisMiniportBlock
.Lock
, &OldIrql
);
335 CurrentEntry
= Adapter
->ProtocolListHead
.Flink
;
337 while (CurrentEntry
!= &Adapter
->ProtocolListHead
)
339 AdapterBinding
= CONTAINING_RECORD(CurrentEntry
, ADAPTER_BINDING
, AdapterListEntry
);
341 /* see comment in MiniIndicateData */
342 /* KeReleaseSpinLock(&Adapter->NdisMiniportBlock.Lock, OldIrql); */
344 (*AdapterBinding
->ProtocolBinding
->Chars
.ReceiveCompleteHandler
)(
345 AdapterBinding
->NdisOpenBlock
.ProtocolBindingContext
);
348 /* KeAcquireSpinLock(&Adapter->NdisMiniportBlock.Lock, &OldIrql); */
350 CurrentEntry
= CurrentEntry
->Flink
;
353 KeReleaseSpinLock(&Adapter
->NdisMiniportBlock
.Lock
, OldIrql
);
358 MiniEthReceiveIndication(
359 IN PETH_FILTER Filter
,
360 IN NDIS_HANDLE MacReceiveContext
,
362 IN PVOID HeaderBuffer
,
363 IN UINT HeaderBufferSize
,
364 IN PVOID LookaheadBuffer
,
365 IN UINT LookaheadBufferSize
,
368 * FUNCTION: Receive indication function for Ethernet devices
370 * MiniportAdapter = Miniport Adapter Handle (PLOGICAL_ADAPTER)
371 * MacReceiveContext = MAC receive context handle
372 * Address = Pointer to destination Ethernet address
373 * HeaderBuffer = Pointer to Ethernet header buffer
374 * HeaderBufferSize = Size of Ethernet header buffer
375 * LookaheadBuffer = Pointer to lookahead buffer
376 * LookaheadBufferSize = Size of lookahead buffer
377 * PacketSize = Total size of received packet
380 MiniIndicateData((PLOGICAL_ADAPTER
)Filter
->Miniport
,
392 IN NDIS_HANDLE MiniportAdapterHandle
,
393 IN NDIS_STATUS Status
,
394 IN BOOLEAN AddressingReset
)
402 IN NDIS_HANDLE MiniportAdapterHandle
,
403 IN PNDIS_PACKET Packet
,
404 IN NDIS_STATUS Status
)
406 * FUNCTION: Forwards a message to the initiating protocol saying
407 * that a packet was handled
409 * NdisAdapterHandle = Handle input to MiniportInitialize
410 * Packet = Pointer to NDIS packet that was sent
411 * Status = Status of send operation
414 PADAPTER_BINDING AdapterBinding
;
416 NDIS_DbgPrint(DEBUG_MINIPORT
, ("Called.\n"));
418 AdapterBinding
= (PADAPTER_BINDING
)Packet
->Reserved
[0];
420 (*AdapterBinding
->ProtocolBinding
->Chars
.u2
.SendCompleteHandler
)(
421 AdapterBinding
->NdisOpenBlock
.ProtocolBindingContext
,
428 MiniSendResourcesAvailable(
429 IN NDIS_HANDLE MiniportAdapterHandle
)
436 MiniTransferDataComplete(
437 IN NDIS_HANDLE MiniportAdapterHandle
,
438 IN PNDIS_PACKET Packet
,
439 IN NDIS_STATUS Status
,
440 IN UINT BytesTransferred
)
442 PLOGICAL_ADAPTER Adapter
= (PLOGICAL_ADAPTER
)MiniportAdapterHandle
;
443 PADAPTER_BINDING AdapterBinding
= Adapter
->MiniportAdapterBinding
;
445 NDIS_DbgPrint(DEBUG_MINIPORT
, ("Called.\n"));
447 (*AdapterBinding
->ProtocolBinding
->Chars
.u3
.TransferDataCompleteHandler
)(
448 AdapterBinding
->NdisOpenBlock
.ProtocolBindingContext
,
456 MiniAdapterHasAddress(
457 PLOGICAL_ADAPTER Adapter
,
460 * FUNCTION: Determines wether a packet has the same destination address as an adapter
462 * Adapter = Pointer to logical adapter object
463 * Packet = Pointer to NDIS packet
465 * TRUE if the destination address is that of the adapter, FALSE if not
471 PNDIS_BUFFER NdisBuffer
;
474 NDIS_DbgPrint(DEBUG_MINIPORT
, ("Called.\n"));
479 NDIS_DbgPrint(MID_TRACE
, ("Adapter object was null\n"));
485 NDIS_DbgPrint(MID_TRACE
, ("Packet was null\n"));
490 NdisQueryPacket(Packet
, NULL
, NULL
, &NdisBuffer
, NULL
);
494 NDIS_DbgPrint(MID_TRACE
, ("Packet contains no buffers.\n"));
498 NdisQueryBuffer(NdisBuffer
, (PVOID
)&Start2
, &BufferLength
);
500 /* FIXME: Should handle fragmented packets */
502 switch (Adapter
->NdisMiniportBlock
.MediaType
)
504 case NdisMedium802_3
:
505 Length
= ETH_LENGTH_OF_ADDRESS
;
506 /* Destination address is the first field */
510 NDIS_DbgPrint(MIN_TRACE
, ("Adapter has unsupported media type (0x%X).\n", Adapter
->NdisMiniportBlock
.MediaType
));
514 if (BufferLength
< Length
)
516 NDIS_DbgPrint(MID_TRACE
, ("Buffer is too small.\n"));
520 Start1
= (PUCHAR
)&Adapter
->Address
;
521 NDIS_DbgPrint(MAX_TRACE
, ("packet address: %x:%x:%x:%x:%x:%x adapter address: %x:%x:%x:%x:%x:%x\n",
522 *((char *)Start1
), *(((char *)Start1
)+1), *(((char *)Start1
)+2), *(((char *)Start1
)+3), *(((char *)Start1
)+4), *(((char *)Start1
)+5),
523 *((char *)Start2
), *(((char *)Start2
)+1), *(((char *)Start2
)+2), *(((char *)Start2
)+3), *(((char *)Start2
)+4), *(((char *)Start2
)+5))
526 return (RtlCompareMemory((PVOID
)Start1
, (PVOID
)Start2
, Length
) == Length
);
532 PNDIS_STRING AdapterName
)
534 * FUNCTION: Finds an adapter object by name
536 * AdapterName = Pointer to name of adapter
538 * Pointer to logical adapter object, or NULL if none was found.
539 * If found, the adapter is referenced for the caller. The caller
540 * is responsible for dereferencing after use
544 PLIST_ENTRY CurrentEntry
;
545 PLOGICAL_ADAPTER Adapter
= 0;
549 NDIS_DbgPrint(DEBUG_MINIPORT
, ("Called.\n"));
551 if(IsListEmpty(&AdapterListHead
))
553 NDIS_DbgPrint(DEBUG_MINIPORT
, ("No registered miniports for protocol to bind to\n"));
557 KeAcquireSpinLock(&AdapterListLock
, &OldIrql
);
561 CurrentEntry
= AdapterListHead
.Flink
;
563 while (CurrentEntry
!= &AdapterListHead
)
565 Adapter
= CONTAINING_RECORD(CurrentEntry
, LOGICAL_ADAPTER
, ListEntry
);
569 NDIS_DbgPrint(DEBUG_MINIPORT
, ("AdapterName = %wZ\n", &AdapterName
));
570 NDIS_DbgPrint(DEBUG_MINIPORT
, ("DeviceName = %wZ\n", &Adapter
->DeviceName
));
572 if (RtlCompareUnicodeString(AdapterName
, &Adapter
->DeviceName
, TRUE
) == 0)
574 ReferenceObject(Adapter
);
578 CurrentEntry
= CurrentEntry
->Flink
;
582 KeReleaseSpinLock(&AdapterListLock
, OldIrql
);
586 NDIS_DbgPrint(DEBUG_MINIPORT
, ("Leaving. Adapter found at 0x%x\n", Adapter
));
590 NDIS_DbgPrint(DEBUG_MINIPORT
, ("Leaving (adapter not found).\n"));
598 MiniQueryInformation(
599 PLOGICAL_ADAPTER Adapter
,
604 * FUNCTION: Queries a logical adapter for properties
606 * Adapter = Pointer to the logical adapter object to query
607 * Oid = Specifies the Object ID to query for
608 * Size = If non-zero overrides the length in the adapter object
609 * BytesWritten = Address of buffer to place number of bytes written
611 * If the specified buffer is too small, a new buffer is allocated,
612 * and the query is attempted again
614 * Status of operation
616 * Is there any way to use the buffer provided by the protocol?
619 NDIS_STATUS NdisStatus
;
622 NDIS_DbgPrint(DEBUG_MINIPORT
, ("Called.\n"));
624 if (Adapter
->QueryBufferLength
== 0)
626 /* XXX is 32 the right number? */
627 Adapter
->QueryBuffer
= ExAllocatePool(NonPagedPool
, (Size
== 0)? 32 : Size
);
629 if (!Adapter
->QueryBuffer
)
631 NDIS_DbgPrint(MIN_TRACE
, ("Insufficient resources.\n"));
632 return NDIS_STATUS_RESOURCES
;
636 Adapter
->QueryBufferLength
= (Size
== 0)? 32 : Size
;
639 /* this is the third time i've seen this conditional */
640 BytesNeeded
= (Size
== 0)? Adapter
->QueryBufferLength
: Size
;
642 /* call the miniport's queryinfo handler */
643 NdisStatus
= (*Adapter
->Miniport
->Chars
.QueryInformationHandler
)(
644 Adapter
->NdisMiniportBlock
.MiniportAdapterContext
,
646 Adapter
->QueryBuffer
,
651 /* XXX is status_pending part of success macro? */
652 if ((NT_SUCCESS(NdisStatus
)) || (NdisStatus
== NDIS_STATUS_PENDING
))
654 NDIS_DbgPrint(DEBUG_MINIPORT
, ("Miniport returned status (0x%X).\n", NdisStatus
));
658 if (NdisStatus
== NDIS_STATUS_INVALID_LENGTH
)
660 ExFreePool(Adapter
->QueryBuffer
);
662 Adapter
->QueryBufferLength
+= BytesNeeded
;
663 Adapter
->QueryBuffer
= ExAllocatePool(NonPagedPool
, Adapter
->QueryBufferLength
);
665 if (!Adapter
->QueryBuffer
)
667 NDIS_DbgPrint(MIN_TRACE
, ("Insufficient resources.\n"));
668 return NDIS_STATUS_RESOURCES
;
671 NdisStatus
= (*Adapter
->Miniport
->Chars
.QueryInformationHandler
)(
672 Adapter
->NdisMiniportBlock
.MiniportAdapterContext
,
674 Adapter
->QueryBuffer
,
687 PLOGICAL_ADAPTER Adapter
,
688 NDIS_WORK_ITEM_TYPE WorkItemType
,
689 PVOID WorkItemContext
,
690 NDIS_HANDLE Initiator
)
692 * FUNCTION: Queues a work item for execution at a later time
694 * Adapter = Pointer to the logical adapter object to queue work item on
695 * WorkItemType = Type of work item to queue
696 * WorkItemContext = Pointer to context information for work item
697 * Initiator = Pointer to ADAPTER_BINDING structure of initiating protocol
699 * Adapter lock must be held when called
701 * Status of operation
704 PNDIS_MINIPORT_WORK_ITEM Item
;
706 NDIS_DbgPrint(MAX_TRACE
, ("Called.\n"));
710 if (Adapter
->WorkQueueLevel
< NDIS_MINIPORT_WORK_QUEUE_SIZE
- 1)
712 Item
= &Adapter
->WorkQueue
[Adapter
->WorkQueueLevel
];
713 Adapter
->WorkQueueLevel
++;
717 Item
= ExAllocatePool(NonPagedPool
, sizeof(NDIS_MINIPORT_WORK_ITEM
));
720 /* Set flag so we know that the buffer should be freed when work item is dequeued */
721 Item
->Allocated
= TRUE
;
725 NDIS_DbgPrint(MIN_TRACE
, ("Insufficient resources.\n"));
726 return NDIS_STATUS_RESOURCES
;
730 Item
->WorkItemType
= WorkItemType
;
731 Item
->WorkItemContext
= WorkItemContext
;
732 Item
->Initiator
= Initiator
;
734 /* safe due to adapter lock held */
735 Item
->Link
.Next
= NULL
;
736 if (!Adapter
->WorkQueueHead
)
738 Adapter
->WorkQueueHead
= Item
;
739 Adapter
->WorkQueueTail
= Item
;
743 Adapter
->WorkQueueTail
->Link
.Next
= (PSINGLE_LIST_ENTRY
)Item
;
744 Adapter
->WorkQueueTail
= Item
;
747 KeInsertQueueDpc(&Adapter
->MiniportDpc
, NULL
, NULL
);
749 return NDIS_STATUS_SUCCESS
;
756 PLOGICAL_ADAPTER Adapter
,
757 NDIS_WORK_ITEM_TYPE
*WorkItemType
,
758 PVOID
*WorkItemContext
,
759 NDIS_HANDLE
*Initiator
)
761 * FUNCTION: Dequeues a work item from the work queue of a logical adapter
763 * Adapter = Pointer to the logical adapter object to dequeue work item from
764 * WorkItemType = Address of buffer for work item type
765 * WorkItemContext = Address of buffer for pointer to context information
766 * Initiator = Address of buffer for initiator of the work (ADAPTER_BINDING)
768 * Adapter lock must be held when called
770 * Status of operation
773 PNDIS_MINIPORT_WORK_ITEM Item
;
775 NDIS_DbgPrint(MAX_TRACE
, ("Called.\n"));
777 Item
= Adapter
->WorkQueueHead
;
781 /* safe due to adapter lock held */
782 Adapter
->WorkQueueHead
= (PNDIS_MINIPORT_WORK_ITEM
)Item
->Link
.Next
;
784 if (Item
== Adapter
->WorkQueueTail
)
785 Adapter
->WorkQueueTail
= NULL
;
787 *WorkItemType
= Item
->WorkItemType
;
788 *WorkItemContext
= Item
->WorkItemContext
;
789 *Initiator
= Item
->Initiator
;
797 Adapter
->WorkQueueLevel
--;
799 if (Adapter
->WorkQueueLevel
< 0)
801 NDIS_DbgPrint(MIN_TRACE
, ("Adapter->WorkQueueLevel is < 0 (should be >= 0).\n"));
806 return NDIS_STATUS_SUCCESS
;
809 return NDIS_STATUS_FAILURE
;
815 PLOGICAL_ADAPTER Adapter
,
816 PNDIS_REQUEST NdisRequest
)
818 * FUNCTION: Sends a request to a miniport
820 * Adapter = Pointer to logical adapter object
821 * NdisRequest = Pointer to NDIS request structure describing request
823 * Status of operation
826 NDIS_DbgPrint(DEBUG_MINIPORT
, ("Called.\n"));
828 Adapter
->NdisMiniportBlock
.MediaRequest
= NdisRequest
;
830 switch (NdisRequest
->RequestType
)
832 case NdisRequestQueryInformation
:
833 return (*Adapter
->Miniport
->Chars
.QueryInformationHandler
)(
834 Adapter
->NdisMiniportBlock
.MiniportAdapterContext
,
835 NdisRequest
->DATA
.QUERY_INFORMATION
.Oid
,
836 NdisRequest
->DATA
.QUERY_INFORMATION
.InformationBuffer
,
837 NdisRequest
->DATA
.QUERY_INFORMATION
.InformationBufferLength
,
838 (PULONG
)&NdisRequest
->DATA
.QUERY_INFORMATION
.BytesWritten
,
839 (PULONG
)&NdisRequest
->DATA
.QUERY_INFORMATION
.BytesNeeded
);
842 case NdisRequestSetInformation
:
843 return (*Adapter
->Miniport
->Chars
.SetInformationHandler
)(
844 Adapter
->NdisMiniportBlock
.MiniportAdapterContext
,
845 NdisRequest
->DATA
.SET_INFORMATION
.Oid
,
846 NdisRequest
->DATA
.SET_INFORMATION
.InformationBuffer
,
847 NdisRequest
->DATA
.SET_INFORMATION
.InformationBufferLength
,
848 (PULONG
)&NdisRequest
->DATA
.SET_INFORMATION
.BytesRead
,
849 (PULONG
)&NdisRequest
->DATA
.SET_INFORMATION
.BytesNeeded
);
853 return NDIS_STATUS_FAILURE
;
858 VOID STDCALL
MiniportDpc(
860 IN PVOID DeferredContext
,
861 IN PVOID SystemArgument1
,
862 IN PVOID SystemArgument2
)
864 * FUNCTION: Deferred routine to handle serialization
866 * Dpc = Pointer to DPC object
867 * DeferredContext = Pointer to context information (LOGICAL_ADAPTER)
868 * SystemArgument1 = Unused
869 * SystemArgument2 = Unused
872 NDIS_STATUS NdisStatus
;
873 PVOID WorkItemContext
;
874 NDIS_WORK_ITEM_TYPE WorkItemType
;
875 PADAPTER_BINDING AdapterBinding
;
876 PLOGICAL_ADAPTER Adapter
= GET_LOGICAL_ADAPTER(DeferredContext
);
878 NDIS_DbgPrint(DEBUG_MINIPORT
, ("Called.\n"));
880 /* XXX is adapter lock held here? should be... */
881 NdisStatus
= MiniDequeueWorkItem(Adapter
, &WorkItemType
, &WorkItemContext
, (PNDIS_HANDLE
)&AdapterBinding
);
883 if (NdisStatus
== NDIS_STATUS_SUCCESS
)
885 Adapter
->MiniportAdapterBinding
= AdapterBinding
;
887 switch (WorkItemType
)
889 case NdisWorkItemSend
:
891 * called by ProSend when protocols want to send packets to the miniport
894 MiniDisplayPacket((PNDIS_PACKET
)WorkItemContext
);
896 if(Adapter
->Miniport
->Chars
.SendPacketsHandler
)
898 NDIS_DbgPrint(MAX_TRACE
, ("Calling miniport's SendPackets handler\n"));
901 * XXX assumes single-packet - prolly OK since we'll call something
902 * different on multi-packet sends
904 (*Adapter
->Miniport
->Chars
.SendPacketsHandler
)(
905 Adapter
->NdisMiniportBlock
.MiniportAdapterContext
, (PPNDIS_PACKET
)&WorkItemContext
, 1);
907 NDIS_DbgPrint(MAX_TRACE
, ("back from miniport's SendPackets handler\n"));
911 NDIS_DbgPrint(MAX_TRACE
, ("Calling miniport's Send handler\n"));
913 NdisStatus
= (*Adapter
->Miniport
->Chars
.u1
.SendHandler
)(
914 Adapter
->NdisMiniportBlock
.MiniportAdapterContext
, (PNDIS_PACKET
)WorkItemContext
, 0);
916 NDIS_DbgPrint(MAX_TRACE
, ("back from miniport's Send handler\n"));
918 if (NdisStatus
!= NDIS_STATUS_PENDING
)
919 MiniSendComplete((NDIS_HANDLE
)Adapter
, (PNDIS_PACKET
)WorkItemContext
, NdisStatus
);
924 case NdisWorkItemSendLoopback
:
926 * called by ProSend when protocols want to send loopback packets
928 /* XXX atm ProIndicatePacket sends a packet up via the loopback adapter only */
929 NdisStatus
= ProIndicatePacket(Adapter
, (PNDIS_PACKET
)WorkItemContext
);
930 MiniSendComplete((NDIS_HANDLE
)Adapter
, (PNDIS_PACKET
)WorkItemContext
, NdisStatus
);
933 case NdisWorkItemReturnPackets
:
936 case NdisWorkItemResetRequested
:
939 case NdisWorkItemResetInProgress
:
942 case NdisWorkItemHalt
:
945 case NdisWorkItemMiniportCallback
:
948 case NdisWorkItemRequest
:
949 NdisStatus
= MiniDoRequest(Adapter
, (PNDIS_REQUEST
)WorkItemContext
);
951 if (NdisStatus
== NDIS_STATUS_PENDING
)
954 switch (((PNDIS_REQUEST
)WorkItemContext
)->RequestType
)
956 case NdisRequestQueryInformation
:
957 NdisMQueryInformationComplete((NDIS_HANDLE
)Adapter
, NdisStatus
);
960 case NdisRequestSetInformation
:
961 NdisMSetInformationComplete((NDIS_HANDLE
)Adapter
, NdisStatus
);
965 NDIS_DbgPrint(MIN_TRACE
, ("Unknown NDIS request type.\n"));
971 NDIS_DbgPrint(MIN_TRACE
, ("Unknown NDIS work item type (%d).\n", WorkItemType
));
984 IN NDIS_HANDLE LogHandle
)
996 IN NDIS_HANDLE MiniportAdapterHandle
,
998 OUT PNDIS_HANDLE LogHandle
)
1002 return NDIS_STATUS_FAILURE
;
1011 NdisMDeregisterAdapterShutdownHandler(
1012 IN NDIS_HANDLE MiniportHandle
)
1014 * FUNCTION: de-registers a shutdown handler
1015 * ARGUMENTS: MiniportHandle: Handle passed into MiniportInitialize
1018 NDIS_DbgPrint(DEBUG_MINIPORT
, ("Called.\n"));
1019 PLOGICAL_ADAPTER Adapter
= (PLOGICAL_ADAPTER
)MiniportHandle
;
1021 if(Adapter
->BugcheckContext
->ShutdownHandler
)
1022 KeDeregisterBugCheckCallback(Adapter
->BugcheckContext
->CallbackRecord
);
1032 IN NDIS_HANDLE LogHandle
)
1043 NdisMIndicateStatus(
1044 IN NDIS_HANDLE MiniportAdapterHandle
,
1045 IN NDIS_STATUS GeneralStatus
,
1046 IN PVOID StatusBuffer
,
1047 IN UINT StatusBufferSize
)
1058 NdisMIndicateStatusComplete(
1059 IN NDIS_HANDLE MiniportAdapterHandle
)
1070 NdisInitializeWrapper(
1071 OUT PNDIS_HANDLE NdisWrapperHandle
,
1072 IN PVOID SystemSpecific1
,
1073 IN PVOID SystemSpecific2
,
1074 IN PVOID SystemSpecific3
)
1076 * FUNCTION: Notifies the NDIS library that a new miniport is initializing
1078 * NdisWrapperHandle = Address of buffer to place NDIS wrapper handle
1079 * SystemSpecific1 = Pointer to the driver's driver object
1080 * SystemSpecific2 = Pointer to the driver's registry path
1081 * SystemSpecific3 = Always NULL
1083 * - SystemSpecific2 goes invalid so we copy it
1086 PMINIPORT_DRIVER Miniport
;
1087 PUNICODE_STRING RegistryPath
;
1088 WCHAR
*RegistryBuffer
;
1090 NDIS_DbgPrint(MAX_TRACE
, ("Called.\n"));
1092 ASSERT(NdisWrapperHandle
);
1094 *NdisWrapperHandle
= NULL
;
1096 #if BREAK_ON_MINIPORT_INIT
1097 __asm__ ("int $3\n");
1100 Miniport
= ExAllocatePool(NonPagedPool
, sizeof(MINIPORT_DRIVER
));
1104 NDIS_DbgPrint(MIN_TRACE
, ("Insufficient resources.\n"));
1108 RtlZeroMemory(Miniport
, sizeof(MINIPORT_DRIVER
));
1110 KeInitializeSpinLock(&Miniport
->Lock
);
1112 Miniport
->RefCount
= 1;
1114 Miniport
->DriverObject
= (PDRIVER_OBJECT
)SystemSpecific1
;
1116 /* set the miniport's driver registry path */
1117 RegistryPath
= ExAllocatePool(PagedPool
, sizeof(UNICODE_STRING
));
1120 NDIS_DbgPrint(MIN_TRACE
, ("Insufficient resources.\n"));
1124 RegistryPath
->Length
= ((PUNICODE_STRING
)SystemSpecific2
)->Length
;
1125 RegistryPath
->MaximumLength
= RegistryPath
->Length
+ sizeof(WCHAR
); /* room for 0-term */
1127 RegistryBuffer
= ExAllocatePool(PagedPool
, RegistryPath
->MaximumLength
);
1130 NDIS_DbgPrint(MIN_TRACE
, ("Insufficient resources.\n"));
1134 RtlCopyMemory(RegistryBuffer
, ((PUNICODE_STRING
)SystemSpecific2
)->Buffer
, RegistryPath
->Length
);
1135 RegistryBuffer
[RegistryPath
->Length
/sizeof(WCHAR
)] = 0;
1137 RegistryPath
->Buffer
= RegistryBuffer
;
1138 Miniport
->RegistryPath
= RegistryPath
;
1140 InitializeListHead(&Miniport
->AdapterListHead
);
1142 /* Put miniport in global miniport list */
1143 ExInterlockedInsertTailList(&MiniportListHead
, &Miniport
->ListEntry
, &MiniportListLock
);
1145 *NdisWrapperHandle
= Miniport
;
1154 NdisMQueryInformationComplete(
1155 IN NDIS_HANDLE MiniportAdapterHandle
,
1156 IN NDIS_STATUS Status
)
1158 PLOGICAL_ADAPTER Adapter
= GET_LOGICAL_ADAPTER(MiniportAdapterHandle
);
1159 PADAPTER_BINDING AdapterBinding
= (PADAPTER_BINDING
)Adapter
->MiniportAdapterBinding
;
1161 NDIS_DbgPrint(MAX_TRACE
, ("Called.\n"));
1163 (*AdapterBinding
->ProtocolBinding
->Chars
.RequestCompleteHandler
)(
1164 AdapterBinding
->NdisOpenBlock
.ProtocolBindingContext
,
1165 Adapter
->NdisMiniportBlock
.MediaRequest
,
1170 VOID STDCALL
NdisIBugcheckCallback(
1174 * FUNCTION: Internal callback for handling bugchecks - calls adapter's shutdown handler
1176 * Buffer: Pointer to a bugcheck callback context
1180 PMINIPORT_BUGCHECK_CONTEXT Context
= (PMINIPORT_BUGCHECK_CONTEXT
)Buffer
;
1181 ADAPTER_SHUTDOWN_HANDLER sh
= (ADAPTER_SHUTDOWN_HANDLER
)Context
->ShutdownHandler
;
1183 NDIS_DbgPrint(DEBUG_MINIPORT
, ("Called.\n"));
1186 sh(Context
->DriverContext
);
1195 NdisMRegisterAdapterShutdownHandler(
1196 IN NDIS_HANDLE MiniportHandle
,
1197 IN PVOID ShutdownContext
,
1198 IN ADAPTER_SHUTDOWN_HANDLER ShutdownHandler
)
1200 * FUNCTION: Register a shutdown handler for an adapter
1202 * MiniportHandle: Handle originally passed into MiniportInitialize
1203 * ShutdownContext: Pre-initialized bugcheck context
1204 * ShutdownHandler: Function to call to handle the bugcheck
1206 * - I'm not sure about ShutdownContext
1207 * - FIXME - memory leak below
1210 PLOGICAL_ADAPTER Adapter
= (PLOGICAL_ADAPTER
)MiniportHandle
;
1211 PMINIPORT_BUGCHECK_CONTEXT BugcheckContext
= Adapter
->BugcheckContext
;
1213 NDIS_DbgPrint(DEBUG_MINIPORT
, ("Called.\n"));
1218 BugcheckContext
= ExAllocatePool(NonPagedPool
, sizeof(MINIPORT_BUGCHECK_CONTEXT
));
1219 if(!BugcheckContext
)
1221 NDIS_DbgPrint(MIN_TRACE
, ("Insufficient resources.\n"));
1225 BugcheckContext
->ShutdownHandler
= ShutdownHandler
;
1226 BugcheckContext
->DriverContext
= ShutdownContext
;
1228 /* not sure if this needs to be initialized or not... oh well, it's a leak. */
1229 BugcheckContext
->CallbackRecord
= ExAllocatePool(NonPagedPool
, sizeof(KBUGCHECK_CALLBACK_RECORD
));
1231 KeRegisterBugCheckCallback(BugcheckContext
->CallbackRecord
, NdisIBugcheckCallback
,
1232 BugcheckContext
, sizeof(BugcheckContext
), "Ndis Miniport");
1238 PLOGICAL_ADAPTER Adapter
,
1239 NDIS_OID AddressOID
)
1241 * FUNCTION: Queries miniport for information
1243 * Adapter = Pointer to logical adapter
1244 * AddressOID = OID to use to query for current address
1246 * Status of operation
1250 NDIS_STATUS NdisStatus
;
1252 NDIS_DbgPrint(MAX_TRACE
, ("Called.\n"));
1254 /* Get MAC options for adapter */
1255 NdisStatus
= MiniQueryInformation(Adapter
, OID_GEN_MAC_OPTIONS
, 0, &BytesWritten
);
1257 if (NdisStatus
!= NDIS_STATUS_SUCCESS
)
1259 NDIS_DbgPrint(MIN_TRACE
, ("OID_GEN_MAC_OPTIONS failed. NdisStatus (0x%X).\n", NdisStatus
));
1263 RtlCopyMemory(&Adapter
->NdisMiniportBlock
.MacOptions
, Adapter
->QueryBuffer
, sizeof(UINT
));
1265 NDIS_DbgPrint(DEBUG_MINIPORT
, ("MacOptions (0x%X).\n", Adapter
->NdisMiniportBlock
.MacOptions
));
1267 /* Get current hardware address of adapter */
1268 NdisStatus
= MiniQueryInformation(Adapter
, AddressOID
, 0, &BytesWritten
);
1270 if (NdisStatus
!= NDIS_STATUS_SUCCESS
)
1272 NDIS_DbgPrint(MIN_TRACE
, ("Address OID (0x%X) failed. NdisStatus (0x%X).\n", AddressOID
, NdisStatus
));
1276 RtlCopyMemory(&Adapter
->Address
, Adapter
->QueryBuffer
, Adapter
->AddressLength
);
1281 PUCHAR A
= (PUCHAR
)&Adapter
->Address
.Type
.Medium802_3
;
1283 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]));
1287 /* Get maximum lookahead buffer size of adapter */
1288 NdisStatus
= MiniQueryInformation(Adapter
, OID_GEN_MAXIMUM_LOOKAHEAD
, 0, &BytesWritten
);
1290 if (NdisStatus
!= NDIS_STATUS_SUCCESS
)
1292 NDIS_DbgPrint(MIN_TRACE
, ("OID_GEN_MAXIMUM_LOOKAHEAD failed. NdisStatus (0x%X).\n", NdisStatus
));
1296 Adapter
->MaxLookaheadLength
= *((PULONG
)Adapter
->QueryBuffer
);
1298 NDIS_DbgPrint(DEBUG_MINIPORT
, ("MaxLookaheadLength (0x%X).\n", Adapter
->MaxLookaheadLength
));
1300 /* Get current lookahead buffer size of adapter */
1301 NdisStatus
= MiniQueryInformation(Adapter
, OID_GEN_CURRENT_LOOKAHEAD
, 0, &BytesWritten
);
1303 if (NdisStatus
!= NDIS_STATUS_SUCCESS
)
1305 NDIS_DbgPrint(MIN_TRACE
, ("OID_GEN_CURRENT_LOOKAHEAD failed. NdisStatus (0x%X).\n", NdisStatus
));
1309 Adapter
->CurLookaheadLength
= *((PULONG
)Adapter
->QueryBuffer
);
1311 NDIS_DbgPrint(DEBUG_MINIPORT
, ("CurLookaheadLength (0x%X).\n", Adapter
->CurLookaheadLength
));
1313 if (Adapter
->MaxLookaheadLength
!= 0)
1315 Adapter
->LookaheadLength
= Adapter
->MaxLookaheadLength
+ Adapter
->MediumHeaderSize
;
1316 Adapter
->LookaheadBuffer
= ExAllocatePool(NonPagedPool
, Adapter
->LookaheadLength
);
1318 if (!Adapter
->LookaheadBuffer
)
1319 return NDIS_STATUS_RESOURCES
;
1322 return STATUS_SUCCESS
;
1328 UNICODE_STRING
*DeviceName
,
1329 PDEVICE_OBJECT PhysicalDeviceObject
,
1330 PMINIPORT_DRIVER Miniport
1333 * FUNCTION: Start an adapter
1335 * DeviceName: Name of device to start
1336 * PhysicalDeviceObject: PDO for our adapter
1339 * - verify that all resources are properly freed on success & failure
1340 * - break up this 250-line function
1343 HANDLE RegKeyHandle
;
1344 NDIS_STATUS NdisStatus
;
1345 NDIS_STATUS OpenErrorStatus
;
1347 UINT SelectedMediumIndex
= 0;
1348 PLOGICAL_ADAPTER Adapter
= 0;
1349 NDIS_OID AddressOID
;
1350 BOOLEAN MemError
= FALSE
;
1354 Adapter
= ExAllocatePool(NonPagedPool
, sizeof(LOGICAL_ADAPTER
));
1357 NDIS_DbgPrint(MIN_TRACE
, ("Insufficient resources.\n"));
1361 /* This is very important */
1362 RtlZeroMemory(Adapter
, sizeof(LOGICAL_ADAPTER
));
1364 Adapter
->DeviceName
.Buffer
= ExAllocatePool(NonPagedPool
, DeviceName
->Length
);
1365 if(!Adapter
->DeviceName
.Buffer
)
1367 NDIS_DbgPrint(MIN_TRACE
,("Insufficient memory\n"));
1368 ExFreePool(Adapter
);
1371 Adapter
->DeviceName
.MaximumLength
= DeviceName
->Length
;
1372 RtlCopyUnicodeString(&Adapter
->DeviceName
, DeviceName
);
1374 NDIS_DbgPrint(MAX_TRACE
, ("creating device %wZ\n", DeviceName
));
1376 Status
= IoCreateDevice(Miniport
->DriverObject
, 0, &Adapter
->DeviceName
, FILE_DEVICE_PHYSICAL_NETCARD
,
1377 0, FALSE
, &Adapter
->NdisMiniportBlock
.DeviceObject
);
1378 if (!NT_SUCCESS(Status
))
1380 NDIS_DbgPrint(MIN_TRACE
, ("Could not create device object.\n"));
1381 ExFreePool(Adapter
);
1385 Status
= IoOpenDeviceRegistryKey(PhysicalDeviceObject
, PLUGPLAY_REGKEY_DRIVER
,
1386 KEY_ALL_ACCESS
, &RegKeyHandle
);
1387 if(Status
!= STATUS_SUCCESS
)
1389 NDIS_DbgPrint(MIN_TRACE
,("failed to open adapter-specific reg key\n"));
1390 ExFreePool(Adapter
);
1394 NDIS_DbgPrint(MAX_TRACE
, ("opened device reg key\n"));
1396 NDIS_DbgPrint(MAX_TRACE
, ("acquiring miniport block lock\n"));
1397 KeInitializeSpinLock(&Adapter
->NdisMiniportBlock
.Lock
);
1398 InitializeListHead(&Adapter
->ProtocolListHead
);
1399 Adapter
->RefCount
= 1;
1400 Adapter
->Miniport
= Miniport
;
1402 /* FIXME: Check return values. */
1403 Size
= sizeof(ULONG
);
1404 IoGetDeviceProperty(PhysicalDeviceObject
, DevicePropertyLegacyBusType
,
1405 Size
, &Adapter
->BusType
, &Size
);
1406 IoGetDeviceProperty(PhysicalDeviceObject
, DevicePropertyBusNumber
,
1407 Size
, &Adapter
->BusNumber
, &Size
);
1408 IoGetDeviceProperty(PhysicalDeviceObject
, DevicePropertyAddress
,
1409 Size
, &Adapter
->SlotNumber
, &Size
);
1411 /* Set handlers (some NDIS macros require these) */
1413 Adapter
->NdisMiniportBlock
.EthRxCompleteHandler
= MiniEthReceiveComplete
;
1414 Adapter
->NdisMiniportBlock
.EthRxIndicateHandler
= MiniEthReceiveIndication
;
1415 Adapter
->NdisMiniportBlock
.SendCompleteHandler
= MiniSendComplete
;
1416 Adapter
->NdisMiniportBlock
.SendResourcesHandler
= MiniSendResourcesAvailable
;
1417 Adapter
->NdisMiniportBlock
.ResetCompleteHandler
= MiniResetComplete
;
1418 Adapter
->NdisMiniportBlock
.TDCompleteHandler
= MiniTransferDataComplete
;
1419 Adapter
->NdisMiniportBlock
.PacketIndicateHandler
= MiniIndicateReceivePacket
;
1421 KeInitializeDpc(&Adapter
->MiniportDpc
, MiniportDpc
, (PVOID
)Adapter
);
1423 /* Put adapter in adapter list for this miniport */
1424 ExInterlockedInsertTailList(&Miniport
->AdapterListHead
, &Adapter
->MiniportListEntry
, &Miniport
->Lock
);
1426 /* Put adapter in global adapter list */
1427 ExInterlockedInsertTailList(&AdapterListHead
, &Adapter
->ListEntry
, &AdapterListLock
);
1429 /* Call MiniportInitialize */
1430 NDIS_DbgPrint(MID_TRACE
, ("calling MiniportInitialize\n"));
1431 NdisStatus
= (*Miniport
->Chars
.InitializeHandler
)( &OpenErrorStatus
, &SelectedMediumIndex
, &MediaArray
[0],
1432 MEDIA_ARRAY_SIZE
, Adapter
, RegKeyHandle
);
1434 ZwClose(RegKeyHandle
);
1436 if ((NdisStatus
== NDIS_STATUS_SUCCESS
) && (SelectedMediumIndex
< MEDIA_ARRAY_SIZE
))
1438 NDIS_DbgPrint(MID_TRACE
,("successful return from MiniportInitialize\n"));
1440 Adapter
->NdisMiniportBlock
.MediaType
= MediaArray
[SelectedMediumIndex
];
1442 switch (Adapter
->NdisMiniportBlock
.MediaType
)
1444 case NdisMedium802_3
:
1445 Adapter
->MediumHeaderSize
= 14; /* XXX figure out what to do about LLC */
1446 AddressOID
= OID_802_3_CURRENT_ADDRESS
;
1447 Adapter
->AddressLength
= ETH_LENGTH_OF_ADDRESS
;
1449 Adapter
->NdisMiniportBlock
.FilterDbs
.u
.EthDB
= ExAllocatePool(NonPagedPool
, sizeof(ETH_FILTER
));
1450 if (Adapter
->NdisMiniportBlock
.FilterDbs
.u
.EthDB
)
1452 RtlZeroMemory(Adapter
->NdisMiniportBlock
.FilterDbs
.u
.EthDB
, sizeof(ETH_FILTER
));
1453 Adapter
->NdisMiniportBlock
.FilterDbs
.u
.EthDB
->Miniport
= (PNDIS_MINIPORT_BLOCK
)Adapter
;
1461 /* FIXME: Support other types of media */
1462 NDIS_DbgPrint(MIN_TRACE
, ("error: unsupported media\n"));
1463 ExFreePool(Adapter
);
1465 KeReleaseSpinLock(&Adapter
->NdisMiniportBlock
.Lock
, OldIrql
);
1469 NdisStatus
= DoQueries(Adapter
, AddressOID
);
1472 if ((MemError
) || (NdisStatus
!= NDIS_STATUS_SUCCESS
) || (SelectedMediumIndex
>= MEDIA_ARRAY_SIZE
))
1474 NDIS_DbgPrint(MAX_TRACE
, ("return from MiniportInitialize: NdisStatus 0x%x, SelectedMediumIndex 0x%x\n",
1475 NdisStatus
, SelectedMediumIndex
));
1477 /* Remove adapter from adapter list for this miniport */
1478 KeAcquireSpinLock(&Miniport
->Lock
, &OldIrql
);
1479 RemoveEntryList(&Adapter
->MiniportListEntry
);
1480 KeReleaseSpinLock(&Miniport
->Lock
, OldIrql
);
1482 /* Remove adapter from global adapter list */
1483 KeAcquireSpinLock(&AdapterListLock
, &OldIrql
);
1484 RemoveEntryList(&Adapter
->ListEntry
);
1485 KeReleaseSpinLock(&AdapterListLock
, OldIrql
);
1487 if (Adapter
->LookaheadBuffer
)
1488 ExFreePool(Adapter
->LookaheadBuffer
);
1490 IoDeleteDevice(Adapter
->NdisMiniportBlock
.DeviceObject
);
1491 ExFreePool(Adapter
);
1492 NDIS_DbgPrint(MIN_TRACE
, ("MiniportInitialize() failed for an adapter.\n"));
1496 IoAttachDeviceToDeviceStack(Adapter
->NdisMiniportBlock
.DeviceObject
,
1497 PhysicalDeviceObject
);
1505 IN PDRIVER_OBJECT DriverObject
,
1506 IN PDEVICE_OBJECT PhysicalDeviceObject
1509 * FUNCTION: Start an adapter found using PnP
1511 * DriverObject = Pointer to the miniport driver object
1512 * PhysicalDeviceObject = Pointer to the PDO for our adapter
1515 static const WCHAR ClassKeyName
[] = {'C','l','a','s','s','\\'};
1516 static const WCHAR LinkageKeyName
[] = {'\\','L','i','n','k','a','g','e',0};
1517 PMINIPORT_DRIVER Miniport
;
1518 PMINIPORT_DRIVER
*MiniportPtr
;
1519 WCHAR
*LinkageKeyBuffer
;
1520 ULONG DriverKeyLength
;
1521 RTL_QUERY_REGISTRY_TABLE QueryTable
[2];
1522 UNICODE_STRING ExportName
;
1526 * Gain the access to the miniport data structure first.
1529 MiniportPtr
= IoGetDriverObjectExtension(DriverObject
, (PVOID
)TAG('D','I','M','N'));
1530 if (MiniportPtr
== NULL
)
1532 NDIS_DbgPrint(DEBUG_MINIPORT
, ("Can't get driver object extension.\n"));
1533 return STATUS_UNSUCCESSFUL
;
1535 Miniport
= *MiniportPtr
;
1538 * Get name of the Linkage registry key for our adapter. It's located under
1539 * the driver key for our driver and so we have basicly two ways to do it.
1540 * Either we can use IoOpenDriverRegistryKey or compose it using information
1541 * gathered by IoGetDeviceProperty. I choosed the second because
1542 * IoOpenDriverRegistryKey wasn't implemented at the time of writing.
1545 Status
= IoGetDeviceProperty(PhysicalDeviceObject
, DevicePropertyDriverKeyName
,
1546 0, NULL
, &DriverKeyLength
);
1547 if (Status
!= STATUS_BUFFER_TOO_SMALL
)
1549 NDIS_DbgPrint(DEBUG_MINIPORT
, ("Can't get miniport driver key length.\n"));
1553 LinkageKeyBuffer
= ExAllocatePool(PagedPool
, DriverKeyLength
+
1554 sizeof(ClassKeyName
) + sizeof(LinkageKeyName
));
1555 if (LinkageKeyBuffer
== NULL
)
1557 NDIS_DbgPrint(DEBUG_MINIPORT
, ("Can't allocate memory for driver key name.\n"));
1558 return STATUS_INSUFFICIENT_RESOURCES
;
1561 Status
= IoGetDeviceProperty(PhysicalDeviceObject
, DevicePropertyDriverKeyName
,
1562 DriverKeyLength
, LinkageKeyBuffer
+
1563 (sizeof(ClassKeyName
) / sizeof(WCHAR
)),
1565 if (!NT_SUCCESS(Status
))
1567 NDIS_DbgPrint(DEBUG_MINIPORT
, ("Can't get miniport driver key.\n"));
1568 ExFreePool(LinkageKeyBuffer
);
1572 /* Compose the linkage key name. */
1573 RtlCopyMemory(LinkageKeyBuffer
, ClassKeyName
, sizeof(ClassKeyName
));
1574 RtlCopyMemory(LinkageKeyBuffer
+ ((sizeof(ClassKeyName
) + DriverKeyLength
) /
1575 sizeof(WCHAR
)) - 1, LinkageKeyName
, sizeof(LinkageKeyName
));
1577 NDIS_DbgPrint(DEBUG_MINIPORT
, ("LinkageKey: %S.\n", LinkageKeyBuffer
));
1580 * Now open the linkage key and read the "Export" and "RootDevice" values
1581 * which contains device name and root service respectively.
1584 RtlZeroMemory(QueryTable
, sizeof(QueryTable
));
1585 RtlInitUnicodeString(&ExportName
, NULL
);
1586 QueryTable
[0].Flags
= RTL_QUERY_REGISTRY_REQUIRED
| RTL_QUERY_REGISTRY_DIRECT
;
1587 QueryTable
[0].Name
= L
"Export";
1588 QueryTable
[0].EntryContext
= &ExportName
;
1590 Status
= RtlQueryRegistryValues(RTL_REGISTRY_CONTROL
, LinkageKeyBuffer
,
1591 QueryTable
, NULL
, NULL
);
1592 if (!NT_SUCCESS(Status
))
1594 NDIS_DbgPrint(DEBUG_MINIPORT
, ("Can't get miniport device name. (%x)\n", Status
));
1595 ExFreePool(LinkageKeyBuffer
);
1598 ExFreePool(LinkageKeyBuffer
);
1600 NdisIStartAdapter(&ExportName
, PhysicalDeviceObject
, Miniport
);
1601 RtlFreeUnicodeString(&ExportName
);
1603 return STATUS_SUCCESS
;
1612 NdisMRegisterMiniport(
1613 IN NDIS_HANDLE NdisWrapperHandle
,
1614 IN PNDIS_MINIPORT_CHARACTERISTICS MiniportCharacteristics
,
1615 IN UINT CharacteristicsLength
)
1617 * FUNCTION: Registers a miniport's MiniportXxx entry points with the NDIS library
1619 * NdisWrapperHandle = Pointer to handle returned by NdisMInitializeWrapper
1620 * MiniportCharacteristics = Pointer to a buffer with miniport characteristics
1621 * CharacteristicsLength = Number of bytes in characteristics buffer
1623 * Status of operation
1627 PMINIPORT_DRIVER Miniport
= GET_MINIPORT_DRIVER(NdisWrapperHandle
);
1628 PMINIPORT_DRIVER
*MiniportPtr
;
1631 NDIS_DbgPrint(MAX_TRACE
, ("Called.\n"));
1633 switch (MiniportCharacteristics
->MajorNdisVersion
)
1636 MinSize
= sizeof(NDIS30_MINIPORT_CHARACTERISTICS_S
);
1640 MinSize
= sizeof(NDIS40_MINIPORT_CHARACTERISTICS_S
);
1644 MinSize
= sizeof(NDIS50_MINIPORT_CHARACTERISTICS_S
);
1648 NDIS_DbgPrint(DEBUG_MINIPORT
, ("Bad miniport characteristics version.\n"));
1649 return NDIS_STATUS_BAD_VERSION
;
1652 if (CharacteristicsLength
< MinSize
)
1654 NDIS_DbgPrint(DEBUG_MINIPORT
, ("Bad miniport characteristics.\n"));
1655 return NDIS_STATUS_BAD_CHARACTERISTICS
;
1658 /* Check if mandatory MiniportXxx functions are specified */
1659 if ((!MiniportCharacteristics
->HaltHandler
) ||
1660 (!MiniportCharacteristics
->InitializeHandler
)||
1661 (!MiniportCharacteristics
->QueryInformationHandler
) ||
1662 (!MiniportCharacteristics
->ResetHandler
) ||
1663 (!MiniportCharacteristics
->SetInformationHandler
))
1665 NDIS_DbgPrint(DEBUG_MINIPORT
, ("Bad miniport characteristics.\n"));
1666 return NDIS_STATUS_BAD_CHARACTERISTICS
;
1669 if (MiniportCharacteristics
->MajorNdisVersion
== 0x03)
1671 if (!MiniportCharacteristics
->u1
.SendHandler
)
1673 NDIS_DbgPrint(DEBUG_MINIPORT
, ("Bad miniport characteristics.\n"));
1674 return NDIS_STATUS_BAD_CHARACTERISTICS
;
1677 else if (MiniportCharacteristics
->MajorNdisVersion
>= 0x04)
1680 if ((!MiniportCharacteristics
->u1
.SendHandler
) &&
1681 (!MiniportCharacteristics
->SendPacketsHandler
))
1683 NDIS_DbgPrint(DEBUG_MINIPORT
, ("Bad miniport characteristics.\n"));
1684 return NDIS_STATUS_BAD_CHARACTERISTICS
;
1688 /* TODO: verify NDIS5 and NDIS5.1 */
1690 RtlCopyMemory(&Miniport
->Chars
, MiniportCharacteristics
, MinSize
);
1693 * NOTE: This is VERY unoptimal! Should we store the MINIPORT_DRIVER
1694 * struture in the driver extension or what?
1697 Status
= IoAllocateDriverObjectExtension(Miniport
->DriverObject
, (PVOID
)TAG('D','I','M','N'),
1698 sizeof(PMINIPORT_DRIVER
), (PVOID
*)&MiniportPtr
);
1699 if (!NT_SUCCESS(Status
))
1701 NDIS_DbgPrint(DEBUG_MINIPORT
, ("Can't allocate driver object extension.\n"));
1702 return NDIS_STATUS_RESOURCES
;
1705 *MiniportPtr
= Miniport
;
1706 Miniport
->DriverObject
->DriverExtension
->AddDevice
= NdisIAddDevice
;
1708 return NDIS_STATUS_SUCCESS
;
1718 IN NDIS_HANDLE MiniportAdapterHandle
,
1719 IN NDIS_STATUS Status
,
1720 IN BOOLEAN AddressingReset
)
1722 MiniResetComplete(MiniportAdapterHandle
, Status
, AddressingReset
);
1732 IN NDIS_HANDLE MiniportAdapterHandle
,
1733 IN PNDIS_PACKET Packet
,
1734 IN NDIS_STATUS Status
)
1736 * FUNCTION: Forwards a message to the initiating protocol saying
1737 * that a packet was handled
1739 * NdisAdapterHandle = Handle input to MiniportInitialize
1740 * Packet = Pointer to NDIS packet that was sent
1741 * Status = Status of send operation
1744 MiniSendComplete(MiniportAdapterHandle
, Packet
, Status
);
1753 NdisMSendResourcesAvailable(
1754 IN NDIS_HANDLE MiniportAdapterHandle
)
1756 MiniSendResourcesAvailable(MiniportAdapterHandle
);
1765 NdisMTransferDataComplete(
1766 IN NDIS_HANDLE MiniportAdapterHandle
,
1767 IN PNDIS_PACKET Packet
,
1768 IN NDIS_STATUS Status
,
1769 IN UINT BytesTransferred
)
1771 MiniTransferDataComplete(MiniportAdapterHandle
, Packet
, Status
, BytesTransferred
);
1780 NdisMSetInformationComplete(
1781 IN NDIS_HANDLE MiniportAdapterHandle
,
1782 IN NDIS_STATUS Status
)
1784 PLOGICAL_ADAPTER Adapter
= GET_LOGICAL_ADAPTER(MiniportAdapterHandle
);
1785 PADAPTER_BINDING AdapterBinding
= (PADAPTER_BINDING
)Adapter
->MiniportAdapterBinding
;
1787 NDIS_DbgPrint(MAX_TRACE
, ("Called.\n"));
1789 (*AdapterBinding
->ProtocolBinding
->Chars
.RequestCompleteHandler
)(
1790 AdapterBinding
->NdisOpenBlock
.ProtocolBindingContext
,
1791 Adapter
->NdisMiniportBlock
.MediaRequest
,
1802 IN NDIS_HANDLE MiniportAdapterHandle
,
1803 IN NDIS_HANDLE MiniportAdapterContext
,
1804 IN BOOLEAN BusMaster
,
1805 IN NDIS_INTERFACE_TYPE AdapterType
)
1807 * FUNCTION: Informs the NDIS library of significant features of the caller's NIC
1809 * MiniportAdapterHandle = Handle input to MiniportInitialize
1810 * MiniportAdapterContext = Pointer to context information
1811 * BusMaster = Specifies TRUE if the caller's NIC is a busmaster DMA device
1812 * AdapterType = Specifies the I/O bus interface of the caller's NIC
1815 PLOGICAL_ADAPTER Adapter
= GET_LOGICAL_ADAPTER(MiniportAdapterHandle
);
1817 NDIS_DbgPrint(MAX_TRACE
, ("Called.\n"));
1819 Adapter
->NdisMiniportBlock
.MiniportAdapterContext
= MiniportAdapterContext
;
1822 Adapter
->NdisMiniportBlock
.Flags
|= NDIS_ATTRIBUTE_BUS_MASTER
;
1824 Adapter
->NdisMiniportBlock
.AdapterType
= AdapterType
;
1825 Adapter
->AttributesSet
= TRUE
;
1834 NdisMSetAttributesEx(
1835 IN NDIS_HANDLE MiniportAdapterHandle
,
1836 IN NDIS_HANDLE MiniportAdapterContext
,
1837 IN UINT CheckForHangTimeInSeconds OPTIONAL
,
1838 IN ULONG AttributeFlags
,
1839 IN NDIS_INTERFACE_TYPE AdapterType
)
1841 * FUNCTION: Informs the NDIS library of significant features of the caller's NIC
1843 * MiniportAdapterHandle = Handle input to MiniportInitialize
1844 * MiniportAdapterContext = Pointer to context information
1845 * CheckForHangTimeInSeconds = Specifies interval in seconds at which
1846 * MiniportCheckForHang should be called
1847 * AttributeFlags = Bitmask that indicates specific attributes
1848 * AdapterType = Specifies the I/O bus interface of the caller's NIC
1851 /* TODO: Take CheckForHandTimeInSeconds into account! */
1853 PLOGICAL_ADAPTER Adapter
= GET_LOGICAL_ADAPTER(MiniportAdapterHandle
);
1855 NDIS_DbgPrint(MAX_TRACE
, ("Called.\n"));
1857 Adapter
->NdisMiniportBlock
.MiniportAdapterContext
= MiniportAdapterContext
;
1858 Adapter
->NdisMiniportBlock
.Flags
= AttributeFlags
;
1859 Adapter
->NdisMiniportBlock
.AdapterType
= AdapterType
;
1860 Adapter
->AttributesSet
= TRUE
;
1861 if (AttributeFlags
& NDIS_ATTRIBUTE_INTERMEDIATE_DRIVER
)
1862 NDIS_DbgPrint(MAX_TRACE
, ("Intermediate drivers not supported yet.\n"));
1872 IN ULONG MicrosecondsToSleep
)
1874 * FUNCTION: delay the thread's execution for MicrosecondsToSleep
1876 * MicrosecondsToSleep: duh...
1878 * - Because this is a blocking call, current IRQL must be < DISPATCH_LEVEL
1882 LARGE_INTEGER DueTime
;
1886 DueTime
.QuadPart
= (-1) * 10 * MicrosecondsToSleep
;
1888 KeInitializeTimer(&Timer
);
1889 KeSetTimer(&Timer
, DueTime
, 0);
1890 KeWaitForSingleObject(&Timer
, Executive
, KernelMode
, FALSE
, 0);
1899 NdisMSynchronizeWithInterrupt(
1900 IN PNDIS_MINIPORT_INTERRUPT Interrupt
,
1901 IN PVOID SynchronizeFunction
,
1902 IN PVOID SynchronizeContext
)
1904 return(KeSynchronizeExecution((PKINTERRUPT
)Interrupt
,
1905 (PKSYNCHRONIZE_ROUTINE
)SynchronizeFunction
,
1906 SynchronizeContext
));
1916 IN NDIS_HANDLE LogHandle
,
1918 IN UINT LogBufferSize
)
1922 return NDIS_STATUS_FAILURE
;
1931 NdisTerminateWrapper(
1932 IN NDIS_HANDLE NdisWrapperHandle
,
1933 IN PVOID SystemSpecific
)
1935 * FUNCTION: Releases resources allocated by a call to NdisInitializeWrapper
1937 * NdisWrapperHandle = Handle returned by NdisInitializeWrapper (MINIPORT_DRIVER)
1938 * SystemSpecific = Always NULL
1941 PMINIPORT_DRIVER Miniport
= GET_MINIPORT_DRIVER(NdisWrapperHandle
);
1943 NDIS_DbgPrint(MAX_TRACE
, ("Called.\n"));
1945 ExFreePool(Miniport
->RegistryPath
->Buffer
);
1946 ExFreePool(Miniport
->RegistryPath
);
1947 ExFreePool(Miniport
);