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\\"
24 /* prefix for device object registration */
25 #define DEVICE_ROOT L"\\Device\\"
28 * Define to 1 to get a debugger breakpoint at the end of NdisInitializeWrapper
29 * for each new miniport starting up
31 #define BREAK_ON_MINIPORT_INIT 0
34 * This has to be big enough to hold the results of querying the Route value
35 * from the Linkage key. Please re-code me to determine this dynamically.
37 #define ROUTE_DATA_SIZE 256
39 /* Number of media we know */
40 #define MEDIA_ARRAY_SIZE 15
42 static NDIS_MEDIUM MediaArray
[MEDIA_ARRAY_SIZE
] =
51 NdisMediumArcnet878_2
,
53 NdisMediumWirelessWan
,
61 /* global list and lock of Miniports NDIS has registered */
62 LIST_ENTRY MiniportListHead
;
63 KSPIN_LOCK MiniportListLock
;
65 /* global list and lock of adapters NDIS has registered */
66 LIST_ENTRY AdapterListHead
;
67 KSPIN_LOCK AdapterListLock
;
69 /* global list and lock of orphan adapters waiting to be claimed by a miniport */
70 LIST_ENTRY OrphanAdapterListHead
;
71 KSPIN_LOCK OrphanAdapterListLock
;
82 if ((DebugTraceLevel
| DEBUG_PACKET
) > 0) {
83 Length
= CopyPacketToBuffer(
89 DbgPrint("*** PACKET START ***");
91 for (i
= 0; i
< Length
; i
++) {
93 DbgPrint("\n%04X ", i
);
94 DbgPrint("%02X ", Buffer
[i
]);
97 DbgPrint("*** PACKET STOP ***\n");
105 UINT HeaderBufferSize
,
106 PVOID LookaheadBuffer
,
107 UINT LookaheadBufferSize
)
110 if ((DebugTraceLevel
| DEBUG_PACKET
) > 0) {
114 DbgPrint("*** RECEIVE PACKET START ***\n");
117 for (i
= 0; i
< HeaderBufferSize
; i
++) {
119 DbgPrint("\n%04X ", i
);
120 DbgPrint("%02X ", *p
);
124 DbgPrint("\nFRAME:");
127 Length
= (LookaheadBufferSize
< 64)? LookaheadBufferSize
: 64;
128 for (i
= 0; i
< Length
; i
++) {
130 DbgPrint("\n%04X ", i
);
131 DbgPrint("%02X ", *p
);
135 DbgPrint("\n*** RECEIVE PACKET STOP ***\n");
143 PLOGICAL_ADAPTER Adapter
,
144 NDIS_HANDLE MacReceiveContext
,
146 UINT HeaderBufferSize
,
147 PVOID LookaheadBuffer
,
148 UINT LookaheadBufferSize
,
151 * FUNCTION: Indicate received data to bound protocols
153 * Adapter = Pointer to logical adapter
154 * MacReceiveContext = MAC receive context handle
155 * HeaderBuffer = Pointer to header buffer
156 * HeaderBufferSize = Size of header buffer
157 * LookaheadBuffer = Pointer to lookahead buffer
158 * LookaheadBufferSize = Size of lookahead buffer
159 * PacketSize = Total size of received packet
163 PLIST_ENTRY CurrentEntry
;
164 PADAPTER_BINDING AdapterBinding
;
166 NDIS_DbgPrint(DEBUG_MINIPORT
, ("Called. Adapter (0x%X) HeaderBuffer (0x%X) "
167 "HeaderBufferSize (0x%X) LookaheadBuffer (0x%X) LookaheadBufferSize (0x%X).\n",
168 Adapter
, HeaderBuffer
, HeaderBufferSize
, LookaheadBuffer
, LookaheadBufferSize
));
170 MiniDisplayPacket2(HeaderBuffer
, HeaderBufferSize
, LookaheadBuffer
, LookaheadBufferSize
);
173 * XXX Think about this. This is probably broken. Spinlocks are
174 * taken out for now until i comprehend the Right Way to do this.
176 * This used to acquire the MiniportBlock spinlock and hold it until
177 * just before the call to ReceiveHandler. It would then release and
178 * subsequently re-acquire the lock.
180 * I don't see how this does any good, as it would seem he's just
181 * trying to protect the packet list. If someobdy else dequeues
182 * a packet, we are in fact in bad shape, but we don't want to
183 * necessarily call the receive handler at elevated irql either.
185 * therefore: We *are* going to call the receive handler at high irql
186 * (due to holding the lock) for now, and eventually we have to
187 * figure out another way to protect this packet list.
189 * UPDATE: this is busted; this results in a recursive lock acquisition.
191 //NDIS_DbgPrint(MAX_TRACE, ("acquiring miniport block lock\n"));
192 //KeAcquireSpinLock(&Adapter->NdisMiniportBlock.Lock, &OldIrql);
194 CurrentEntry
= Adapter
->ProtocolListHead
.Flink
;
195 NDIS_DbgPrint(DEBUG_MINIPORT
, ("CurrentEntry = %x\n", CurrentEntry
));
197 if (CurrentEntry
== &Adapter
->ProtocolListHead
)
199 NDIS_DbgPrint(DEBUG_MINIPORT
, ("WARNING: No upper protocol layer.\n"));
202 while (CurrentEntry
!= &Adapter
->ProtocolListHead
)
204 AdapterBinding
= CONTAINING_RECORD(CurrentEntry
, ADAPTER_BINDING
, AdapterListEntry
);
205 NDIS_DbgPrint(DEBUG_MINIPORT
, ("AdapterBinding = %x\n", AdapterBinding
));
208 /* KeReleaseSpinLock(&Adapter->NdisMiniportBlock.Lock, OldIrql); */
213 NDIS_DbgPrint(MIN_TRACE
, ("AdapterBinding was null\n"));
217 if(!AdapterBinding
->ProtocolBinding
)
219 NDIS_DbgPrint(MIN_TRACE
, ("AdapterBinding->ProtocolBinding was null\n"));
223 if(!AdapterBinding
->ProtocolBinding
->Chars
.u4
.ReceiveHandler
)
225 NDIS_DbgPrint(MIN_TRACE
, ("AdapterBinding->ProtocolBinding->Chars.u4.ReceiveHandler was null\n"));
232 ("XXX (%x) %x %x %x %x %x %x %x XXX\n",
233 *AdapterBinding
->ProtocolBinding
->Chars
.u4
.ReceiveHandler
,
234 AdapterBinding
->NdisOpenBlock
.ProtocolBindingContext
,
242 /* call the receive handler */
243 (*AdapterBinding
->ProtocolBinding
->Chars
.u4
.ReceiveHandler
)(
244 AdapterBinding
->NdisOpenBlock
.ProtocolBindingContext
,
253 /* KeAcquireSpinLock(&Adapter->NdisMiniportBlock.Lock, &OldIrql); */
255 CurrentEntry
= CurrentEntry
->Flink
;
258 //KeReleaseSpinLock(&Adapter->NdisMiniportBlock.Lock, OldIrql);
260 NDIS_DbgPrint(MAX_TRACE
, ("Leaving.\n"));
265 MiniIndicateReceivePacket(
266 IN NDIS_HANDLE Miniport
,
267 IN PPNDIS_PACKET PacketArray
,
268 IN UINT NumberOfPackets
)
270 * FUNCTION: receives miniport packet array indications
272 * Miniport: Miniport handle for the adapter
273 * PacketArray: pointer to a list of packet pointers to indicate
274 * NumberOfPackets: number of packets to indicate
276 * - This currently is a big temporary hack. In the future this should
277 * call ProtocolReceivePacket() on each bound protocol if it exists.
278 * For now it just mimics NdisMEthIndicateReceive.
283 for(i
= 0; i
< NumberOfPackets
; i
++)
285 PCHAR PacketBuffer
= 0;
286 UINT PacketLength
= 0;
287 PNDIS_BUFFER NdisBuffer
= 0;
289 #define PACKET_TAG (('k' << 24) + ('P' << 16) + ('D' << 8) + 'N')
291 NdisAllocateMemoryWithTag((PVOID
)&PacketBuffer
, 1518, PACKET_TAG
);
294 NDIS_DbgPrint(MIN_TRACE
, ("insufficient resources\n"));
298 NdisQueryPacket(PacketArray
[i
], NULL
, NULL
, &NdisBuffer
, NULL
);
302 PNDIS_BUFFER CurrentBuffer
;
306 NdisQueryBuffer(NdisBuffer
, &BufferVa
, &BufferLen
);
307 memcpy(PacketBuffer
+ PacketLength
, BufferVa
, BufferLen
);
308 PacketLength
+= BufferLen
;
310 CurrentBuffer
= NdisBuffer
;
311 NdisGetNextBuffer(CurrentBuffer
, &NdisBuffer
);
314 NDIS_DbgPrint(MID_TRACE
, ("indicating a %d-byte packet\n", PacketLength
));
316 MiniIndicateData(Miniport
, NULL
, PacketBuffer
, 14, PacketBuffer
+14, PacketLength
-14, PacketLength
-14);
318 NdisFreeMemory(PacketBuffer
, 0, 0);
324 MiniEthReceiveComplete(
325 IN PETH_FILTER Filter
)
327 * FUNCTION: Receive indication complete function for Ethernet devices
329 * Filter = Pointer to Ethernet filter
333 PLIST_ENTRY CurrentEntry
;
334 PLOGICAL_ADAPTER Adapter
;
335 PADAPTER_BINDING AdapterBinding
;
337 NDIS_DbgPrint(DEBUG_MINIPORT
, ("Called.\n"));
339 if( !Filter
) return;
341 Adapter
= (PLOGICAL_ADAPTER
)Filter
->Miniport
;
343 NDIS_DbgPrint(MAX_TRACE
, ("acquiring miniport block lock\n"));
344 KeAcquireSpinLock(&Adapter
->NdisMiniportBlock
.Lock
, &OldIrql
);
346 CurrentEntry
= Adapter
->ProtocolListHead
.Flink
;
348 while (CurrentEntry
!= &Adapter
->ProtocolListHead
)
350 AdapterBinding
= CONTAINING_RECORD(CurrentEntry
, ADAPTER_BINDING
, AdapterListEntry
);
352 /* see comment in MiniIndicateData */
353 /* KeReleaseSpinLock(&Adapter->NdisMiniportBlock.Lock, OldIrql); */
355 (*AdapterBinding
->ProtocolBinding
->Chars
.ReceiveCompleteHandler
)(
356 AdapterBinding
->NdisOpenBlock
.ProtocolBindingContext
);
359 /* KeAcquireSpinLock(&Adapter->NdisMiniportBlock.Lock, &OldIrql); */
361 CurrentEntry
= CurrentEntry
->Flink
;
364 KeReleaseSpinLock(&Adapter
->NdisMiniportBlock
.Lock
, OldIrql
);
369 MiniEthReceiveIndication(
370 IN NDIS_HANDLE MiniportAdapter
,
371 IN NDIS_HANDLE MacReceiveContext
,
373 IN PVOID HeaderBuffer
,
374 IN UINT HeaderBufferSize
,
375 IN PVOID LookaheadBuffer
,
376 IN UINT LookaheadBufferSize
,
379 * FUNCTION: Receive indication function for Ethernet devices
381 * MiniportAdapter = Miniport Adapter Handle (PLOGICAL_ADAPTER)
382 * MacReceiveContext = MAC receive context handle
383 * Address = Pointer to destination Ethernet address
384 * HeaderBuffer = Pointer to Ethernet header buffer
385 * HeaderBufferSize = Size of Ethernet header buffer
386 * LookaheadBuffer = Pointer to lookahead buffer
387 * LookaheadBufferSize = Size of lookahead buffer
388 * PacketSize = Total size of received packet
391 MiniIndicateData(MiniportAdapter
,
403 IN NDIS_HANDLE MiniportAdapterHandle
,
404 IN NDIS_STATUS Status
,
405 IN BOOLEAN AddressingReset
)
413 IN NDIS_HANDLE MiniportAdapterHandle
,
414 IN PNDIS_PACKET Packet
,
415 IN NDIS_STATUS Status
)
417 * FUNCTION: Forwards a message to the initiating protocol saying
418 * that a packet was handled
420 * NdisAdapterHandle = Handle input to MiniportInitialize
421 * Packet = Pointer to NDIS packet that was sent
422 * Status = Status of send operation
425 PADAPTER_BINDING AdapterBinding
;
427 NDIS_DbgPrint(DEBUG_MINIPORT
, ("Called.\n"));
429 AdapterBinding
= (PADAPTER_BINDING
)Packet
->Reserved
[0];
431 (*AdapterBinding
->ProtocolBinding
->Chars
.u2
.SendCompleteHandler
)(
432 AdapterBinding
->NdisOpenBlock
.ProtocolBindingContext
,
439 MiniSendResourcesAvailable(
440 IN NDIS_HANDLE MiniportAdapterHandle
)
447 MiniTransferDataComplete(
448 IN NDIS_HANDLE MiniportAdapterHandle
,
449 IN PNDIS_PACKET Packet
,
450 IN NDIS_STATUS Status
,
451 IN UINT BytesTransferred
)
453 PLOGICAL_ADAPTER Adapter
= (PLOGICAL_ADAPTER
)MiniportAdapterHandle
;
454 PADAPTER_BINDING AdapterBinding
= Adapter
->MiniportAdapterBinding
;
456 NDIS_DbgPrint(DEBUG_MINIPORT
, ("Called.\n"));
458 (*AdapterBinding
->ProtocolBinding
->Chars
.u3
.TransferDataCompleteHandler
)(
459 AdapterBinding
->NdisOpenBlock
.ProtocolBindingContext
,
467 MiniAdapterHasAddress(
468 PLOGICAL_ADAPTER Adapter
,
471 * FUNCTION: Determines wether a packet has the same destination address as an adapter
473 * Adapter = Pointer to logical adapter object
474 * Packet = Pointer to NDIS packet
476 * TRUE if the destination address is that of the adapter, FALSE if not
482 PNDIS_BUFFER NdisBuffer
;
485 NDIS_DbgPrint(DEBUG_MINIPORT
, ("Called.\n"));
490 NDIS_DbgPrint(MID_TRACE
, ("Adapter object was null\n"));
496 NDIS_DbgPrint(MID_TRACE
, ("Packet was null\n"));
501 NdisQueryPacket(Packet
, NULL
, NULL
, &NdisBuffer
, NULL
);
505 NDIS_DbgPrint(MID_TRACE
, ("Packet contains no buffers.\n"));
509 NdisQueryBuffer(NdisBuffer
, (PVOID
)&Start2
, &BufferLength
);
511 /* FIXME: Should handle fragmented packets */
513 switch (Adapter
->NdisMiniportBlock
.MediaType
)
515 case NdisMedium802_3
:
516 Length
= ETH_LENGTH_OF_ADDRESS
;
517 /* Destination address is the first field */
521 NDIS_DbgPrint(MIN_TRACE
, ("Adapter has unsupported media type (0x%X).\n", Adapter
->NdisMiniportBlock
.MediaType
));
525 if (BufferLength
< Length
)
527 NDIS_DbgPrint(MID_TRACE
, ("Buffer is too small.\n"));
531 Start1
= (PUCHAR
)&Adapter
->Address
;
532 NDIS_DbgPrint(MAX_TRACE
, ("packet address: %x:%x:%x:%x:%x:%x adapter address: %x:%x:%x:%x:%x:%x\n",
533 *((char *)Start1
), *(((char *)Start1
)+1), *(((char *)Start1
)+2), *(((char *)Start1
)+3), *(((char *)Start1
)+4), *(((char *)Start1
)+5),
534 *((char *)Start2
), *(((char *)Start2
)+1), *(((char *)Start2
)+2), *(((char *)Start2
)+3), *(((char *)Start2
)+4), *(((char *)Start2
)+5))
537 return (RtlCompareMemory((PVOID
)Start1
, (PVOID
)Start2
, Length
) == Length
);
543 PNDIS_STRING AdapterName
)
545 * FUNCTION: Finds an adapter object by name
547 * AdapterName = Pointer to name of adapter
549 * Pointer to logical adapter object, or NULL if none was found.
550 * If found, the adapter is referenced for the caller. The caller
551 * is responsible for dereferencing after use
555 PLIST_ENTRY CurrentEntry
;
556 PLOGICAL_ADAPTER Adapter
= 0;
560 NDIS_DbgPrint(DEBUG_MINIPORT
, ("Called.\n"));
562 if(IsListEmpty(&AdapterListHead
))
564 NDIS_DbgPrint(DEBUG_MINIPORT
, ("No registered miniports for protocol to bind to\n"));
568 KeAcquireSpinLock(&AdapterListLock
, &OldIrql
);
572 CurrentEntry
= AdapterListHead
.Flink
;
574 while (CurrentEntry
!= &AdapterListHead
)
576 Adapter
= CONTAINING_RECORD(CurrentEntry
, LOGICAL_ADAPTER
, ListEntry
);
580 NDIS_DbgPrint(DEBUG_MINIPORT
, ("AdapterName = %wZ\n", &AdapterName
));
581 NDIS_DbgPrint(DEBUG_MINIPORT
, ("DeviceName = %wZ\n", &Adapter
->DeviceName
));
583 if (RtlCompareUnicodeString(AdapterName
, &Adapter
->DeviceName
, TRUE
) == 0)
585 ReferenceObject(Adapter
);
589 CurrentEntry
= CurrentEntry
->Flink
;
593 KeReleaseSpinLock(&AdapterListLock
, OldIrql
);
597 NDIS_DbgPrint(DEBUG_MINIPORT
, ("Leaving. Adapter found at 0x%x\n", Adapter
));
601 NDIS_DbgPrint(DEBUG_MINIPORT
, ("Leaving (adapter not found).\n"));
609 MiniQueryInformation(
610 PLOGICAL_ADAPTER Adapter
,
615 * FUNCTION: Queries a logical adapter for properties
617 * Adapter = Pointer to the logical adapter object to query
618 * Oid = Specifies the Object ID to query for
619 * Size = If non-zero overrides the length in the adapter object
620 * BytesWritten = Address of buffer to place number of bytes written
622 * If the specified buffer is too small, a new buffer is allocated,
623 * and the query is attempted again
625 * Status of operation
627 * Is there any way to use the buffer provided by the protocol?
630 NDIS_STATUS NdisStatus
;
633 NDIS_DbgPrint(DEBUG_MINIPORT
, ("Called.\n"));
635 if (Adapter
->QueryBufferLength
== 0)
637 /* XXX is 32 the right number? */
638 Adapter
->QueryBuffer
= ExAllocatePool(NonPagedPool
, (Size
== 0)? 32 : Size
);
640 if (!Adapter
->QueryBuffer
)
642 NDIS_DbgPrint(MIN_TRACE
, ("Insufficient resources.\n"));
643 return NDIS_STATUS_RESOURCES
;
647 Adapter
->QueryBufferLength
= (Size
== 0)? 32 : Size
;
650 /* this is the third time i've seen this conditional */
651 BytesNeeded
= (Size
== 0)? Adapter
->QueryBufferLength
: Size
;
653 /* call the miniport's queryinfo handler */
654 NdisStatus
= (*Adapter
->Miniport
->Chars
.QueryInformationHandler
)(
655 Adapter
->NdisMiniportBlock
.MiniportAdapterContext
,
657 Adapter
->QueryBuffer
,
662 /* XXX is status_pending part of success macro? */
663 if ((NT_SUCCESS(NdisStatus
)) || (NdisStatus
== NDIS_STATUS_PENDING
))
665 NDIS_DbgPrint(DEBUG_MINIPORT
, ("Miniport returned status (0x%X).\n", NdisStatus
));
669 if (NdisStatus
== NDIS_STATUS_INVALID_LENGTH
)
671 ExFreePool(Adapter
->QueryBuffer
);
673 Adapter
->QueryBufferLength
+= BytesNeeded
;
674 Adapter
->QueryBuffer
= ExAllocatePool(NonPagedPool
, Adapter
->QueryBufferLength
);
676 if (!Adapter
->QueryBuffer
)
678 NDIS_DbgPrint(MIN_TRACE
, ("Insufficient resources.\n"));
679 return NDIS_STATUS_RESOURCES
;
682 NdisStatus
= (*Adapter
->Miniport
->Chars
.QueryInformationHandler
)(
683 Adapter
->NdisMiniportBlock
.MiniportAdapterContext
,
685 Adapter
->QueryBuffer
,
698 PLOGICAL_ADAPTER Adapter
,
699 NDIS_WORK_ITEM_TYPE WorkItemType
,
700 PVOID WorkItemContext
,
701 NDIS_HANDLE Initiator
)
703 * FUNCTION: Queues a work item for execution at a later time
705 * Adapter = Pointer to the logical adapter object to queue work item on
706 * WorkItemType = Type of work item to queue
707 * WorkItemContext = Pointer to context information for work item
708 * Initiator = Pointer to ADAPTER_BINDING structure of initiating protocol
710 * Adapter lock must be held when called
712 * Status of operation
715 PNDIS_MINIPORT_WORK_ITEM Item
;
717 NDIS_DbgPrint(MAX_TRACE
, ("Called.\n"));
721 if (Adapter
->WorkQueueLevel
< NDIS_MINIPORT_WORK_QUEUE_SIZE
- 1)
723 Item
= &Adapter
->WorkQueue
[Adapter
->WorkQueueLevel
];
724 Adapter
->WorkQueueLevel
++;
728 Item
= ExAllocatePool(NonPagedPool
, sizeof(NDIS_MINIPORT_WORK_ITEM
));
731 /* Set flag so we know that the buffer should be freed when work item is dequeued */
732 Item
->Allocated
= TRUE
;
736 NDIS_DbgPrint(MIN_TRACE
, ("Insufficient resources.\n"));
737 return NDIS_STATUS_RESOURCES
;
741 Item
->WorkItemType
= WorkItemType
;
742 Item
->WorkItemContext
= WorkItemContext
;
743 Item
->Initiator
= Initiator
;
745 /* safe due to adapter lock held */
746 Item
->Link
.Next
= NULL
;
747 if (!Adapter
->WorkQueueHead
)
749 Adapter
->WorkQueueHead
= Item
;
750 Adapter
->WorkQueueTail
= Item
;
754 Adapter
->WorkQueueTail
->Link
.Next
= (PSINGLE_LIST_ENTRY
)Item
;
755 Adapter
->WorkQueueTail
= Item
;
758 KeInsertQueueDpc(&Adapter
->MiniportDpc
, NULL
, NULL
);
760 return NDIS_STATUS_SUCCESS
;
767 PLOGICAL_ADAPTER Adapter
,
768 NDIS_WORK_ITEM_TYPE
*WorkItemType
,
769 PVOID
*WorkItemContext
,
770 NDIS_HANDLE
*Initiator
)
772 * FUNCTION: Dequeues a work item from the work queue of a logical adapter
774 * Adapter = Pointer to the logical adapter object to dequeue work item from
775 * WorkItemType = Address of buffer for work item type
776 * WorkItemContext = Address of buffer for pointer to context information
777 * Initiator = Address of buffer for initiator of the work (ADAPTER_BINDING)
779 * Adapter lock must be held when called
781 * Status of operation
784 PNDIS_MINIPORT_WORK_ITEM Item
;
786 NDIS_DbgPrint(MAX_TRACE
, ("Called.\n"));
788 Item
= Adapter
->WorkQueueHead
;
792 /* safe due to adapter lock held */
793 Adapter
->WorkQueueHead
= (PNDIS_MINIPORT_WORK_ITEM
)Item
->Link
.Next
;
795 if (Item
== Adapter
->WorkQueueTail
)
796 Adapter
->WorkQueueTail
= NULL
;
798 *WorkItemType
= Item
->WorkItemType
;
799 *WorkItemContext
= Item
->WorkItemContext
;
800 *Initiator
= Item
->Initiator
;
808 Adapter
->WorkQueueLevel
--;
810 if (Adapter
->WorkQueueLevel
< 0)
812 NDIS_DbgPrint(MIN_TRACE
, ("Adapter->WorkQueueLevel is < 0 (should be >= 0).\n"));
817 return NDIS_STATUS_SUCCESS
;
820 return NDIS_STATUS_FAILURE
;
826 PLOGICAL_ADAPTER Adapter
,
827 PNDIS_REQUEST NdisRequest
)
829 * FUNCTION: Sends a request to a miniport
831 * Adapter = Pointer to logical adapter object
832 * NdisRequest = Pointer to NDIS request structure describing request
834 * Status of operation
837 NDIS_DbgPrint(DEBUG_MINIPORT
, ("Called.\n"));
839 Adapter
->NdisMiniportBlock
.MediaRequest
= NdisRequest
;
841 switch (NdisRequest
->RequestType
)
843 case NdisRequestQueryInformation
:
844 return (*Adapter
->Miniport
->Chars
.QueryInformationHandler
)(
845 Adapter
->NdisMiniportBlock
.MiniportAdapterContext
,
846 NdisRequest
->DATA
.QUERY_INFORMATION
.Oid
,
847 NdisRequest
->DATA
.QUERY_INFORMATION
.InformationBuffer
,
848 NdisRequest
->DATA
.QUERY_INFORMATION
.InformationBufferLength
,
849 (PULONG
)&NdisRequest
->DATA
.QUERY_INFORMATION
.BytesWritten
,
850 (PULONG
)&NdisRequest
->DATA
.QUERY_INFORMATION
.BytesNeeded
);
853 case NdisRequestSetInformation
:
854 return (*Adapter
->Miniport
->Chars
.SetInformationHandler
)(
855 Adapter
->NdisMiniportBlock
.MiniportAdapterContext
,
856 NdisRequest
->DATA
.SET_INFORMATION
.Oid
,
857 NdisRequest
->DATA
.SET_INFORMATION
.InformationBuffer
,
858 NdisRequest
->DATA
.SET_INFORMATION
.InformationBufferLength
,
859 (PULONG
)&NdisRequest
->DATA
.SET_INFORMATION
.BytesRead
,
860 (PULONG
)&NdisRequest
->DATA
.SET_INFORMATION
.BytesNeeded
);
864 return NDIS_STATUS_FAILURE
;
869 VOID STDCALL
MiniportDpc(
871 IN PVOID DeferredContext
,
872 IN PVOID SystemArgument1
,
873 IN PVOID SystemArgument2
)
875 * FUNCTION: Deferred routine to handle serialization
877 * Dpc = Pointer to DPC object
878 * DeferredContext = Pointer to context information (LOGICAL_ADAPTER)
879 * SystemArgument1 = Unused
880 * SystemArgument2 = Unused
883 NDIS_STATUS NdisStatus
;
884 PVOID WorkItemContext
;
885 NDIS_WORK_ITEM_TYPE WorkItemType
;
886 PADAPTER_BINDING AdapterBinding
;
887 PLOGICAL_ADAPTER Adapter
= GET_LOGICAL_ADAPTER(DeferredContext
);
889 NDIS_DbgPrint(DEBUG_MINIPORT
, ("Called.\n"));
891 /* XXX is adapter lock held here? should be... */
892 NdisStatus
= MiniDequeueWorkItem(Adapter
, &WorkItemType
, &WorkItemContext
, (PNDIS_HANDLE
)&AdapterBinding
);
894 if (NdisStatus
== NDIS_STATUS_SUCCESS
)
896 Adapter
->MiniportAdapterBinding
= AdapterBinding
;
898 switch (WorkItemType
)
900 case NdisWorkItemSend
:
902 * called by ProSend when protocols want to send packets to the miniport
905 MiniDisplayPacket((PNDIS_PACKET
)WorkItemContext
);
907 if(Adapter
->Miniport
->Chars
.SendPacketsHandler
)
909 NDIS_DbgPrint(MAX_TRACE
, ("Calling miniport's SendPackets handler\n"));
912 * XXX assumes single-packet - prolly OK since we'll call something
913 * different on multi-packet sends
915 (*Adapter
->Miniport
->Chars
.SendPacketsHandler
)(
916 Adapter
->NdisMiniportBlock
.MiniportAdapterContext
, (PPNDIS_PACKET
)&WorkItemContext
, 1);
918 NDIS_DbgPrint(MAX_TRACE
, ("back from miniport's SendPackets handler\n"));
922 NDIS_DbgPrint(MAX_TRACE
, ("Calling miniport's Send handler\n"));
924 NdisStatus
= (*Adapter
->Miniport
->Chars
.u1
.SendHandler
)(
925 Adapter
->NdisMiniportBlock
.MiniportAdapterContext
, (PNDIS_PACKET
)WorkItemContext
, 0);
927 NDIS_DbgPrint(MAX_TRACE
, ("back from miniport's Send handler\n"));
929 if (NdisStatus
!= NDIS_STATUS_PENDING
)
930 MiniSendComplete((NDIS_HANDLE
)Adapter
, (PNDIS_PACKET
)WorkItemContext
, NdisStatus
);
935 case NdisWorkItemSendLoopback
:
937 * called by ProSend when protocols want to send loopback packets
939 /* XXX atm ProIndicatePacket sends a packet up via the loopback adapter only */
940 NdisStatus
= ProIndicatePacket(Adapter
, (PNDIS_PACKET
)WorkItemContext
);
941 MiniSendComplete((NDIS_HANDLE
)Adapter
, (PNDIS_PACKET
)WorkItemContext
, NdisStatus
);
944 case NdisWorkItemReturnPackets
:
947 case NdisWorkItemResetRequested
:
950 case NdisWorkItemResetInProgress
:
953 case NdisWorkItemHalt
:
956 case NdisWorkItemMiniportCallback
:
959 case NdisWorkItemRequest
:
960 NdisStatus
= MiniDoRequest(Adapter
, (PNDIS_REQUEST
)WorkItemContext
);
962 if (NdisStatus
== NDIS_STATUS_PENDING
)
965 switch (((PNDIS_REQUEST
)WorkItemContext
)->RequestType
)
967 case NdisRequestQueryInformation
:
968 NdisMQueryInformationComplete((NDIS_HANDLE
)Adapter
, NdisStatus
);
971 case NdisRequestSetInformation
:
972 NdisMSetInformationComplete((NDIS_HANDLE
)Adapter
, NdisStatus
);
976 NDIS_DbgPrint(MIN_TRACE
, ("Unknown NDIS request type.\n"));
982 NDIS_DbgPrint(MIN_TRACE
, ("Unknown NDIS work item type (%d).\n", WorkItemType
));
995 IN NDIS_HANDLE LogHandle
)
1007 IN NDIS_HANDLE MiniportAdapterHandle
,
1009 OUT PNDIS_HANDLE LogHandle
)
1013 return NDIS_STATUS_FAILURE
;
1022 NdisMDeregisterAdapterShutdownHandler(
1023 IN NDIS_HANDLE MiniportHandle
)
1025 * FUNCTION: de-registers a shutdown handler
1026 * ARGUMENTS: MiniportHandle: Handle passed into MiniportInitialize
1029 NDIS_DbgPrint(DEBUG_MINIPORT
, ("Called.\n"));
1030 PLOGICAL_ADAPTER Adapter
= (PLOGICAL_ADAPTER
)MiniportHandle
;
1032 if(Adapter
->BugcheckContext
->ShutdownHandler
)
1033 KeDeregisterBugCheckCallback(Adapter
->BugcheckContext
->CallbackRecord
);
1043 IN NDIS_HANDLE LogHandle
)
1054 NdisMIndicateStatus(
1055 IN NDIS_HANDLE MiniportAdapterHandle
,
1056 IN NDIS_STATUS GeneralStatus
,
1057 IN PVOID StatusBuffer
,
1058 IN UINT StatusBufferSize
)
1069 NdisMIndicateStatusComplete(
1070 IN NDIS_HANDLE MiniportAdapterHandle
)
1081 NdisInitializeWrapper(
1082 OUT PNDIS_HANDLE NdisWrapperHandle
,
1083 IN PVOID SystemSpecific1
,
1084 IN PVOID SystemSpecific2
,
1085 IN PVOID SystemSpecific3
)
1087 * FUNCTION: Notifies the NDIS library that a new miniport is initializing
1089 * NdisWrapperHandle = Address of buffer to place NDIS wrapper handle
1090 * SystemSpecific1 = Pointer to the driver's driver object
1091 * SystemSpecific2 = Pointer to the driver's registry path
1092 * SystemSpecific3 = Always NULL
1094 * - SystemSpecific2 goes invalid so we copy it
1097 PMINIPORT_DRIVER Miniport
;
1098 PUNICODE_STRING RegistryPath
;
1099 WCHAR
*RegistryBuffer
;
1101 NDIS_DbgPrint(MAX_TRACE
, ("Called.\n"));
1103 ASSERT(NdisWrapperHandle
);
1105 *NdisWrapperHandle
= NULL
;
1107 #if BREAK_ON_MINIPORT_INIT
1108 __asm__ ("int $3\n");
1111 Miniport
= ExAllocatePool(NonPagedPool
, sizeof(MINIPORT_DRIVER
));
1115 NDIS_DbgPrint(MIN_TRACE
, ("Insufficient resources.\n"));
1119 RtlZeroMemory(Miniport
, sizeof(MINIPORT_DRIVER
));
1121 KeInitializeSpinLock(&Miniport
->Lock
);
1123 Miniport
->RefCount
= 1;
1125 Miniport
->DriverObject
= (PDRIVER_OBJECT
)SystemSpecific1
;
1127 /* set the miniport's driver registry path */
1128 RegistryPath
= ExAllocatePool(PagedPool
, sizeof(UNICODE_STRING
));
1131 NDIS_DbgPrint(MIN_TRACE
, ("Insufficient resources.\n"));
1135 RegistryPath
->Length
= ((PUNICODE_STRING
)SystemSpecific2
)->Length
;
1136 RegistryPath
->MaximumLength
= RegistryPath
->Length
+ sizeof(WCHAR
); /* room for 0-term */
1138 RegistryBuffer
= ExAllocatePool(PagedPool
, RegistryPath
->MaximumLength
);
1141 NDIS_DbgPrint(MIN_TRACE
, ("Insufficient resources.\n"));
1145 RtlCopyMemory(RegistryBuffer
, ((PUNICODE_STRING
)SystemSpecific2
)->Buffer
, RegistryPath
->Length
);
1146 RegistryBuffer
[RegistryPath
->Length
/sizeof(WCHAR
)] = 0;
1148 RegistryPath
->Buffer
= RegistryBuffer
;
1149 Miniport
->RegistryPath
= RegistryPath
;
1151 InitializeListHead(&Miniport
->AdapterListHead
);
1153 /* Put miniport in global miniport list */
1154 ExInterlockedInsertTailList(&MiniportListHead
, &Miniport
->ListEntry
, &MiniportListLock
);
1156 *NdisWrapperHandle
= Miniport
;
1165 NdisMQueryInformationComplete(
1166 IN NDIS_HANDLE MiniportAdapterHandle
,
1167 IN NDIS_STATUS Status
)
1169 PLOGICAL_ADAPTER Adapter
= GET_LOGICAL_ADAPTER(MiniportAdapterHandle
);
1170 PADAPTER_BINDING AdapterBinding
= (PADAPTER_BINDING
)Adapter
->MiniportAdapterBinding
;
1172 NDIS_DbgPrint(MAX_TRACE
, ("Called.\n"));
1174 (*AdapterBinding
->ProtocolBinding
->Chars
.RequestCompleteHandler
)(
1175 AdapterBinding
->NdisOpenBlock
.ProtocolBindingContext
,
1176 Adapter
->NdisMiniportBlock
.MediaRequest
,
1181 VOID STDCALL
NdisIBugcheckCallback(
1185 * FUNCTION: Internal callback for handling bugchecks - calls adapter's shutdown handler
1187 * Buffer: Pointer to a bugcheck callback context
1191 PMINIPORT_BUGCHECK_CONTEXT Context
= (PMINIPORT_BUGCHECK_CONTEXT
)Buffer
;
1192 ADAPTER_SHUTDOWN_HANDLER sh
= (ADAPTER_SHUTDOWN_HANDLER
)Context
->ShutdownHandler
;
1194 NDIS_DbgPrint(DEBUG_MINIPORT
, ("Called.\n"));
1197 sh(Context
->DriverContext
);
1206 NdisMRegisterAdapterShutdownHandler(
1207 IN NDIS_HANDLE MiniportHandle
,
1208 IN PVOID ShutdownContext
,
1209 IN ADAPTER_SHUTDOWN_HANDLER ShutdownHandler
)
1211 * FUNCTION: Register a shutdown handler for an adapter
1213 * MiniportHandle: Handle originally passed into MiniportInitialize
1214 * ShutdownContext: Pre-initialized bugcheck context
1215 * ShutdownHandler: Function to call to handle the bugcheck
1217 * - I'm not sure about ShutdownContext
1218 * - FIXME - memory leak below
1221 PLOGICAL_ADAPTER Adapter
= (PLOGICAL_ADAPTER
)MiniportHandle
;
1222 PMINIPORT_BUGCHECK_CONTEXT BugcheckContext
= Adapter
->BugcheckContext
;
1224 NDIS_DbgPrint(DEBUG_MINIPORT
, ("Called.\n"));
1229 BugcheckContext
= ExAllocatePool(NonPagedPool
, sizeof(MINIPORT_BUGCHECK_CONTEXT
));
1230 if(!BugcheckContext
)
1232 NDIS_DbgPrint(MIN_TRACE
, ("Insufficient resources.\n"));
1236 BugcheckContext
->ShutdownHandler
= ShutdownHandler
;
1237 BugcheckContext
->DriverContext
= ShutdownContext
;
1239 /* not sure if this needs to be initialized or not... oh well, it's a leak. */
1240 BugcheckContext
->CallbackRecord
= ExAllocatePool(NonPagedPool
, sizeof(KBUGCHECK_CALLBACK_RECORD
));
1242 KeRegisterBugCheckCallback(BugcheckContext
->CallbackRecord
, NdisIBugcheckCallback
,
1243 BugcheckContext
, sizeof(BugcheckContext
), "Ndis Miniport");
1249 PLOGICAL_ADAPTER Adapter
,
1250 NDIS_OID AddressOID
)
1252 * FUNCTION: Queries miniport for information
1254 * Adapter = Pointer to logical adapter
1255 * AddressOID = OID to use to query for current address
1257 * Status of operation
1261 NDIS_STATUS NdisStatus
;
1263 NDIS_DbgPrint(MAX_TRACE
, ("Called.\n"));
1265 /* Get MAC options for adapter */
1266 NdisStatus
= MiniQueryInformation(Adapter
, OID_GEN_MAC_OPTIONS
, 0, &BytesWritten
);
1268 if (NdisStatus
!= NDIS_STATUS_SUCCESS
)
1270 NDIS_DbgPrint(MIN_TRACE
, ("OID_GEN_MAC_OPTIONS failed. NdisStatus (0x%X).\n", NdisStatus
));
1274 RtlCopyMemory(&Adapter
->NdisMiniportBlock
.MacOptions
, Adapter
->QueryBuffer
, sizeof(UINT
));
1276 NDIS_DbgPrint(DEBUG_MINIPORT
, ("MacOptions (0x%X).\n", Adapter
->NdisMiniportBlock
.MacOptions
));
1278 /* Get current hardware address of adapter */
1279 NdisStatus
= MiniQueryInformation(Adapter
, AddressOID
, 0, &BytesWritten
);
1281 if (NdisStatus
!= NDIS_STATUS_SUCCESS
)
1283 NDIS_DbgPrint(MIN_TRACE
, ("Address OID (0x%X) failed. NdisStatus (0x%X).\n", AddressOID
, NdisStatus
));
1287 RtlCopyMemory(&Adapter
->Address
, Adapter
->QueryBuffer
, Adapter
->AddressLength
);
1292 PUCHAR A
= (PUCHAR
)&Adapter
->Address
.Type
.Medium802_3
;
1294 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]));
1298 /* Get maximum lookahead buffer size of adapter */
1299 NdisStatus
= MiniQueryInformation(Adapter
, OID_GEN_MAXIMUM_LOOKAHEAD
, 0, &BytesWritten
);
1301 if (NdisStatus
!= NDIS_STATUS_SUCCESS
)
1303 NDIS_DbgPrint(MIN_TRACE
, ("OID_GEN_MAXIMUM_LOOKAHEAD failed. NdisStatus (0x%X).\n", NdisStatus
));
1307 Adapter
->MaxLookaheadLength
= *((PULONG
)Adapter
->QueryBuffer
);
1309 NDIS_DbgPrint(DEBUG_MINIPORT
, ("MaxLookaheadLength (0x%X).\n", Adapter
->MaxLookaheadLength
));
1311 /* Get current lookahead buffer size of adapter */
1312 NdisStatus
= MiniQueryInformation(Adapter
, OID_GEN_CURRENT_LOOKAHEAD
, 0, &BytesWritten
);
1314 if (NdisStatus
!= NDIS_STATUS_SUCCESS
)
1316 NDIS_DbgPrint(MIN_TRACE
, ("OID_GEN_CURRENT_LOOKAHEAD failed. NdisStatus (0x%X).\n", NdisStatus
));
1320 Adapter
->CurLookaheadLength
= *((PULONG
)Adapter
->QueryBuffer
);
1322 NDIS_DbgPrint(DEBUG_MINIPORT
, ("CurLookaheadLength (0x%X).\n", Adapter
->CurLookaheadLength
));
1324 if (Adapter
->MaxLookaheadLength
!= 0)
1326 Adapter
->LookaheadLength
= Adapter
->MaxLookaheadLength
+ Adapter
->MediumHeaderSize
;
1327 Adapter
->LookaheadBuffer
= ExAllocatePool(NonPagedPool
, Adapter
->LookaheadLength
);
1329 if (!Adapter
->LookaheadBuffer
)
1330 return NDIS_STATUS_RESOURCES
;
1333 return STATUS_SUCCESS
;
1339 WCHAR
*DeviceNameStr
,
1340 UINT DeviceNameStrLength
,
1341 PMINIPORT_DRIVER Miniport
1344 * FUNCTION: Start an adapter
1346 * DeviceNameStr: 0-terminated wide char string of name of device to start
1347 * DeviceNameStrLength: length of DeviceNameStr *IN WCHARs*
1350 * - verify that all resources are properly freed on success & failure
1351 * - break up this 250-line function
1355 HANDLE RegKeyHandle
;
1357 UNICODE_STRING RegKeyPathU
;
1358 OBJECT_ATTRIBUTES RegKeyAttributes
;
1359 NDIS_STATUS NdisStatus
;
1360 NDIS_STATUS OpenErrorStatus
;
1362 UINT SelectedMediumIndex
= 0;
1363 PLOGICAL_ADAPTER Adapter
= 0;
1364 NDIS_OID AddressOID
;
1365 BOOLEAN MemError
= FALSE
;
1367 PORPHAN_ADAPTER OrphanAdapter
= 0;
1369 NDIS_DbgPrint(MAX_TRACE
, ("Called with %ws\n", DeviceNameStr
));
1370 Adapter
= ExAllocatePool(NonPagedPool
, sizeof(LOGICAL_ADAPTER
));
1373 NDIS_DbgPrint(MIN_TRACE
, ("Insufficient resources.\n"));
1377 /* This is very important */
1378 RtlZeroMemory(Adapter
, sizeof(LOGICAL_ADAPTER
));
1380 DeviceName
= ExAllocatePool(NonPagedPool
, sizeof(DEVICE_ROOT
) + DeviceNameStrLength
* sizeof(WCHAR
));
1383 NDIS_DbgPrint(MIN_TRACE
,("Insufficient memory\n"));
1384 ExFreePool(Adapter
);
1388 /* DEVICE_ROOT is a constant string defined above, incl. 0-term */
1389 wcscpy(DeviceName
, DEVICE_ROOT
);
1391 /* reg_sz is 0-term by def */
1392 wcsncat(DeviceName
, DeviceNameStr
, DeviceNameStrLength
);
1393 RtlInitUnicodeString(&Adapter
->DeviceName
, DeviceName
);
1395 NDIS_DbgPrint(MAX_TRACE
, ("creating device %ws\n", DeviceName
));
1397 Status
= IoCreateDevice(Miniport
->DriverObject
, 0, &Adapter
->DeviceName
, FILE_DEVICE_PHYSICAL_NETCARD
,
1398 0, FALSE
, &Adapter
->NdisMiniportBlock
.DeviceObject
);
1399 if (!NT_SUCCESS(Status
))
1401 NDIS_DbgPrint(MIN_TRACE
, ("Could not create device object.\n"));
1402 ExFreePool(Adapter
);
1406 /* find out if there are any adapters in the orphans list and reserve resources */
1407 KeAcquireSpinLock(&OrphanAdapterListLock
, &OldIrql
);
1408 OrphanAdapter
= (PORPHAN_ADAPTER
)OrphanAdapterListHead
.Flink
;
1409 while(&OrphanAdapter
->ListEntry
!= &OrphanAdapterListHead
)
1411 PORPHAN_ADAPTER TempAdapter
;
1412 PCM_RESOURCE_LIST ResourceList
;
1415 if(!RtlCompareUnicodeString(&OrphanAdapter
->RegistryPath
, Miniport
->RegistryPath
, TRUE
))
1417 OrphanAdapter
= (PORPHAN_ADAPTER
)OrphanAdapter
->ListEntry
.Flink
;
1421 NDIS_DbgPrint(MAX_TRACE
, ("Found an orphan adapter for RegistryPath %wZ\n", Miniport
->RegistryPath
));
1423 /* there is an orphan adapter for us */
1424 Adapter
->SlotNumber
= OrphanAdapter
->SlotNumber
;
1425 Adapter
->BusNumber
= OrphanAdapter
->BusNumber
;
1426 Adapter
->BusType
= OrphanAdapter
->BusType
;
1428 Status
= HalAssignSlotResources(Miniport
->RegistryPath
, 0, Miniport
->DriverObject
,
1429 Adapter
->NdisMiniportBlock
.DeviceObject
, Adapter
->BusType
, Adapter
->BusNumber
,
1430 Adapter
->SlotNumber
, &ResourceList
);
1432 if(!NT_SUCCESS(Status
))
1434 NDIS_DbgPrint(MIN_TRACE
, ("HalAssignSlotResources broke: 0x%x\n", Status
));
1437 /* i guess we should just give up on this adapter */
1441 /* go through the returned resource list and populate the Adapter */
1442 for(i
= 0; i
<ResourceList
->Count
; i
++)
1446 PCM_FULL_RESOURCE_DESCRIPTOR ResourceDescriptor
= &ResourceList
->List
[i
];
1448 for(j
=0; j
<ResourceDescriptor
->PartialResourceList
.Count
; j
++)
1450 PCM_PARTIAL_RESOURCE_DESCRIPTOR PartialResourceDescriptor
=
1451 &ResourceDescriptor
->PartialResourceList
.PartialDescriptors
[i
];
1453 switch(PartialResourceDescriptor
->Type
)
1455 case CmResourceTypeInterrupt
:
1456 Adapter
->Irql
= PartialResourceDescriptor
->u
.Interrupt
.Level
;
1457 Adapter
->Vector
= PartialResourceDescriptor
->u
.Interrupt
.Vector
;
1458 Adapter
->Affinity
= PartialResourceDescriptor
->u
.Interrupt
.Affinity
;
1461 case CmResourceTypePort
:
1462 Adapter
->BaseIoAddress
= PartialResourceDescriptor
->u
.Port
.Start
;
1465 case CmResourceTypeMemory
:
1466 Adapter
->BaseMemoryAddress
= PartialResourceDescriptor
->u
.Memory
.Start
;
1469 case CmResourceTypeDma
:
1470 Adapter
->DmaPort
= PartialResourceDescriptor
->u
.Dma
.Port
;
1471 Adapter
->DmaChannel
= PartialResourceDescriptor
->u
.Dma
.Channel
;
1474 case CmResourceTypeDeviceSpecific
:
1481 /* remove the adapter from the list */
1482 TempAdapter
= (PORPHAN_ADAPTER
)OrphanAdapter
->ListEntry
.Flink
;
1483 RemoveEntryList(&OrphanAdapter
->ListEntry
);
1484 OrphanAdapter
= TempAdapter
;
1486 KeReleaseSpinLock(&OrphanAdapterListLock
, OldIrql
);
1488 /* includes room for a 0-term */
1489 RegKeyPath
= ExAllocatePool(PagedPool
, (wcslen(SERVICES_ROOT
) + wcslen(DeviceNameStr
) + 1) * sizeof(WCHAR
));
1492 NDIS_DbgPrint(MIN_TRACE
,("Insufficient resources\n"));
1493 ExFreePool(Adapter
);
1497 wcscpy(RegKeyPath
, SERVICES_ROOT
);
1498 wcscat(RegKeyPath
, DeviceNameStr
);
1499 RegKeyPath
[wcslen(SERVICES_ROOT
) + wcslen(DeviceNameStr
)] = 0;
1501 RtlInitUnicodeString(&RegKeyPathU
, RegKeyPath
);
1502 InitializeObjectAttributes(&RegKeyAttributes
, &RegKeyPathU
, OBJ_CASE_INSENSITIVE
, NULL
, NULL
);
1504 Status
= ZwOpenKey(&RegKeyHandle
, KEY_ALL_ACCESS
, &RegKeyAttributes
);
1505 if(Status
!= STATUS_SUCCESS
)
1507 NDIS_DbgPrint(MIN_TRACE
,("failed to open adapter-specific reg key %wZ\n", &RegKeyPathU
));
1508 ExFreePool(Adapter
);
1512 NDIS_DbgPrint(MAX_TRACE
, ("opened device reg key: %wZ\n", &RegKeyPathU
));
1514 NDIS_DbgPrint(MAX_TRACE
, ("acquiring miniport block lock\n"));
1515 KeInitializeSpinLock(&Adapter
->NdisMiniportBlock
.Lock
);
1516 InitializeListHead(&Adapter
->ProtocolListHead
);
1517 Adapter
->RefCount
= 1;
1518 Adapter
->Miniport
= Miniport
;
1520 /* Set handlers (some NDIS macros require these) */
1522 Adapter
->NdisMiniportBlock
.EthRxCompleteHandler
= MiniEthReceiveComplete
;
1523 Adapter
->NdisMiniportBlock
.EthRxIndicateHandler
= MiniEthReceiveIndication
;
1524 Adapter
->NdisMiniportBlock
.SendCompleteHandler
= MiniSendComplete
;
1525 Adapter
->NdisMiniportBlock
.SendResourcesHandler
= MiniSendResourcesAvailable
;
1526 Adapter
->NdisMiniportBlock
.ResetCompleteHandler
= MiniResetComplete
;
1527 Adapter
->NdisMiniportBlock
.TDCompleteHandler
= MiniTransferDataComplete
;
1528 Adapter
->NdisMiniportBlock
.PacketIndicateHandler
= MiniIndicateReceivePacket
;
1530 KeInitializeDpc(&Adapter
->MiniportDpc
, MiniportDpc
, (PVOID
)Adapter
);
1532 /* Put adapter in adapter list for this miniport */
1533 ExInterlockedInsertTailList(&Miniport
->AdapterListHead
, &Adapter
->MiniportListEntry
, &Miniport
->Lock
);
1535 /* Put adapter in global adapter list */
1536 ExInterlockedInsertTailList(&AdapterListHead
, &Adapter
->ListEntry
, &AdapterListLock
);
1538 /* Call MiniportInitialize */
1539 NDIS_DbgPrint(MID_TRACE
, ("calling MiniportInitialize\n"));
1540 NdisStatus
= (*Miniport
->Chars
.InitializeHandler
)( &OpenErrorStatus
, &SelectedMediumIndex
, &MediaArray
[0],
1541 MEDIA_ARRAY_SIZE
, Adapter
, RegKeyHandle
);
1543 ZwClose(RegKeyHandle
);
1545 if ((NdisStatus
== NDIS_STATUS_SUCCESS
) && (SelectedMediumIndex
< MEDIA_ARRAY_SIZE
))
1547 NDIS_DbgPrint(MID_TRACE
,("successful return from MiniportInitialize\n"));
1549 Adapter
->NdisMiniportBlock
.MediaType
= MediaArray
[SelectedMediumIndex
];
1551 switch (Adapter
->NdisMiniportBlock
.MediaType
)
1553 case NdisMedium802_3
:
1554 Adapter
->MediumHeaderSize
= 14; /* XXX figure out what to do about LLC */
1555 AddressOID
= OID_802_3_CURRENT_ADDRESS
;
1556 Adapter
->AddressLength
= ETH_LENGTH_OF_ADDRESS
;
1558 Adapter
->NdisMiniportBlock
.FilterDbs
.u
.EthDB
= ExAllocatePool(NonPagedPool
, sizeof(ETH_FILTER
));
1559 if (Adapter
->NdisMiniportBlock
.FilterDbs
.u
.EthDB
)
1561 RtlZeroMemory(Adapter
->NdisMiniportBlock
.FilterDbs
.u
.EthDB
, sizeof(ETH_FILTER
));
1562 Adapter
->NdisMiniportBlock
.FilterDbs
.u
.EthDB
->Miniport
= (PNDIS_MINIPORT_BLOCK
)Adapter
;
1570 /* FIXME: Support other types of media */
1571 NDIS_DbgPrint(MIN_TRACE
, ("error: unsupported media\n"));
1572 ExFreePool(Adapter
);
1574 KeReleaseSpinLock(&Adapter
->NdisMiniportBlock
.Lock
, OldIrql
);
1578 NdisStatus
= DoQueries(Adapter
, AddressOID
);
1581 if ((MemError
) || (NdisStatus
!= NDIS_STATUS_SUCCESS
) || (SelectedMediumIndex
>= MEDIA_ARRAY_SIZE
))
1583 NDIS_DbgPrint(MAX_TRACE
, ("return from MiniportInitialize: NdisStatus 0x%x, SelectedMediumIndex 0x%x\n",
1584 NdisStatus
, SelectedMediumIndex
));
1586 /* Remove adapter from adapter list for this miniport */
1587 KeAcquireSpinLock(&Miniport
->Lock
, &OldIrql
);
1588 RemoveEntryList(&Adapter
->MiniportListEntry
);
1589 KeReleaseSpinLock(&Miniport
->Lock
, OldIrql
);
1591 /* Remove adapter from global adapter list */
1592 KeAcquireSpinLock(&AdapterListLock
, &OldIrql
);
1593 RemoveEntryList(&Adapter
->ListEntry
);
1594 KeReleaseSpinLock(&AdapterListLock
, OldIrql
);
1596 if (Adapter
->LookaheadBuffer
)
1597 ExFreePool(Adapter
->LookaheadBuffer
);
1599 IoDeleteDevice(Adapter
->NdisMiniportBlock
.DeviceObject
);
1600 ExFreePool(Adapter
);
1601 NDIS_DbgPrint(MIN_TRACE
, ("MiniportInitialize() failed for an adapter.\n"));
1611 NdisMRegisterMiniport(
1612 IN NDIS_HANDLE NdisWrapperHandle
,
1613 IN PNDIS_MINIPORT_CHARACTERISTICS MiniportCharacteristics
,
1614 IN UINT CharacteristicsLength
)
1616 * FUNCTION: Registers a miniport's MiniportXxx entry points with the NDIS library
1618 * NdisWrapperHandle = Pointer to handle returned by NdisMInitializeWrapper
1619 * MiniportCharacteristics = Pointer to a buffer with miniport characteristics
1620 * CharacteristicsLength = Number of bytes in characteristics buffer
1622 * Status of operation
1624 * - To create device objects for the miniport, the Route value under Linkage is
1625 * parsed. I don't know if this is the way Microsoft does it or not.
1627 * verify this algorithm by playing with nt
1632 PMINIPORT_DRIVER Miniport
= GET_MINIPORT_DRIVER(NdisWrapperHandle
);
1633 OBJECT_ATTRIBUTES DeviceKeyAttributes
;
1634 OBJECT_ATTRIBUTES LinkageKeyAttributes
;
1635 HANDLE DeviceKeyHandle
;
1636 HANDLE LinkageKeyHandle
;
1637 UNICODE_STRING RouteVal
;
1638 UNICODE_STRING LinkageKeyName
;
1639 KEY_VALUE_PARTIAL_INFORMATION
*RouteData
;
1640 ULONG RouteDataLength
;
1641 UINT NextRouteOffset
= 0;
1643 NDIS_DbgPrint(MAX_TRACE
, ("Called.\n"));
1645 switch (MiniportCharacteristics
->MajorNdisVersion
)
1648 MinSize
= sizeof(NDIS30_MINIPORT_CHARACTERISTICS_S
);
1652 MinSize
= sizeof(NDIS40_MINIPORT_CHARACTERISTICS_S
);
1656 MinSize
= sizeof(NDIS50_MINIPORT_CHARACTERISTICS_S
);
1660 NDIS_DbgPrint(DEBUG_MINIPORT
, ("Bad miniport characteristics version.\n"));
1661 return NDIS_STATUS_BAD_VERSION
;
1664 if (CharacteristicsLength
< MinSize
)
1666 NDIS_DbgPrint(DEBUG_MINIPORT
, ("Bad miniport characteristics.\n"));
1667 return NDIS_STATUS_BAD_CHARACTERISTICS
;
1670 /* Check if mandatory MiniportXxx functions are specified */
1671 if ((!MiniportCharacteristics
->HaltHandler
) ||
1672 (!MiniportCharacteristics
->InitializeHandler
)||
1673 (!MiniportCharacteristics
->QueryInformationHandler
) ||
1674 (!MiniportCharacteristics
->ResetHandler
) ||
1675 (!MiniportCharacteristics
->SetInformationHandler
))
1677 NDIS_DbgPrint(DEBUG_MINIPORT
, ("Bad miniport characteristics.\n"));
1678 return NDIS_STATUS_BAD_CHARACTERISTICS
;
1681 if (MiniportCharacteristics
->MajorNdisVersion
== 0x03)
1683 if (!MiniportCharacteristics
->u1
.SendHandler
)
1685 NDIS_DbgPrint(DEBUG_MINIPORT
, ("Bad miniport characteristics.\n"));
1686 return NDIS_STATUS_BAD_CHARACTERISTICS
;
1689 else if (MiniportCharacteristics
->MajorNdisVersion
>= 0x04)
1692 if ((!MiniportCharacteristics
->u1
.SendHandler
) &&
1693 (!MiniportCharacteristics
->SendPacketsHandler
))
1695 NDIS_DbgPrint(DEBUG_MINIPORT
, ("Bad miniport characteristics.\n"));
1696 return NDIS_STATUS_BAD_CHARACTERISTICS
;
1700 /* TODO: verify NDIS5 and NDIS5.1 */
1702 RtlCopyMemory(&Miniport
->Chars
, MiniportCharacteristics
, MinSize
);
1705 * extract the list of bound adapters from the registry's Route value
1706 * for this adapter. It seems under WinNT that the Route value in the
1707 * Linkage subkey holds an entry for each miniport instance we know about.
1708 * This surely isn't how Windows does it, but it's better than nothing.
1710 * FIXME: this is documented in the ddk, believe it or not - read & do
1713 /* Read the miniport config from the registry */
1714 InitializeObjectAttributes(&DeviceKeyAttributes
, Miniport
->RegistryPath
, OBJ_CASE_INSENSITIVE
, NULL
, NULL
);
1716 Status
= ZwOpenKey(&DeviceKeyHandle
, KEY_READ
, &DeviceKeyAttributes
);
1717 if(!NT_SUCCESS(Status
))
1719 NDIS_DbgPrint(MIN_TRACE
,("Failed to open driver key: 0x%x\n", Status
));
1720 return NDIS_STATUS_FAILURE
;
1723 RtlInitUnicodeString(&LinkageKeyName
, L
"Linkage");
1724 InitializeObjectAttributes(&LinkageKeyAttributes
, &LinkageKeyName
, OBJ_CASE_INSENSITIVE
, DeviceKeyHandle
, NULL
);
1726 Status
= ZwOpenKey(&LinkageKeyHandle
, KEY_READ
, &LinkageKeyAttributes
);
1727 if(!NT_SUCCESS(Status
))
1729 NDIS_DbgPrint(MIN_TRACE
,("Failed to open Linkage key: 0x%x\n", Status
));
1730 ZwClose(DeviceKeyHandle
);
1731 return NDIS_STATUS_FAILURE
;
1734 RouteData
= ExAllocatePool(PagedPool
, ROUTE_DATA_SIZE
);
1737 NDIS_DbgPrint(MIN_TRACE
,("Insufficient resources\n"));
1738 ZwClose(LinkageKeyHandle
);
1739 ZwClose(DeviceKeyHandle
);
1740 return NDIS_STATUS_RESOURCES
;
1743 RtlInitUnicodeString(&RouteVal
, L
"Route");
1745 Status
= ZwQueryValueKey(LinkageKeyHandle
, &RouteVal
, KeyValuePartialInformation
, RouteData
, ROUTE_DATA_SIZE
, &RouteDataLength
);
1746 if(!NT_SUCCESS(Status
))
1748 NDIS_DbgPrint(MIN_TRACE
,("Failed to query Route value\n"));
1749 ZwClose(LinkageKeyHandle
);
1750 ZwClose(DeviceKeyHandle
);
1751 ExFreePool(RouteData
);
1752 return NDIS_STATUS_FAILURE
;
1755 ZwClose(LinkageKeyHandle
);
1756 ZwClose(DeviceKeyHandle
);
1758 /* route is a REG_MULTI_SZ with each nic object created by NDI - create an adapter for each */
1759 while(*(RouteData
->Data
+ NextRouteOffset
))
1761 NDIS_DbgPrint(MID_TRACE
, ("Starting adapter %ws\n", (WCHAR
*)(RouteData
->Data
+ NextRouteOffset
)));
1763 NdisIStartAdapter((WCHAR
*)(RouteData
->Data
+ NextRouteOffset
),
1764 wcslen((WCHAR
*)(RouteData
->Data
+ NextRouteOffset
)), Miniport
);
1766 /* NextRouteOffset is in bytes, not WCHARs */
1767 NextRouteOffset
+= wcslen((WCHAR
*)(RouteData
->Data
+ NextRouteOffset
)) * sizeof(WCHAR
);
1770 ExFreePool(RouteData
);
1771 return NDIS_STATUS_SUCCESS
;
1781 IN NDIS_HANDLE MiniportAdapterHandle
,
1782 IN NDIS_STATUS Status
,
1783 IN BOOLEAN AddressingReset
)
1785 MiniResetComplete(MiniportAdapterHandle
, Status
, AddressingReset
);
1795 IN NDIS_HANDLE MiniportAdapterHandle
,
1796 IN PNDIS_PACKET Packet
,
1797 IN NDIS_STATUS Status
)
1799 * FUNCTION: Forwards a message to the initiating protocol saying
1800 * that a packet was handled
1802 * NdisAdapterHandle = Handle input to MiniportInitialize
1803 * Packet = Pointer to NDIS packet that was sent
1804 * Status = Status of send operation
1807 MiniSendComplete(MiniportAdapterHandle
, Packet
, Status
);
1816 NdisMSendResourcesAvailable(
1817 IN NDIS_HANDLE MiniportAdapterHandle
)
1819 MiniSendResourcesAvailable(MiniportAdapterHandle
);
1828 NdisMTransferDataComplete(
1829 IN NDIS_HANDLE MiniportAdapterHandle
,
1830 IN PNDIS_PACKET Packet
,
1831 IN NDIS_STATUS Status
,
1832 IN UINT BytesTransferred
)
1834 MiniTransferDataComplete(MiniportAdapterHandle
, Packet
, Status
, BytesTransferred
);
1843 NdisMSetInformationComplete(
1844 IN NDIS_HANDLE MiniportAdapterHandle
,
1845 IN NDIS_STATUS Status
)
1847 PLOGICAL_ADAPTER Adapter
= GET_LOGICAL_ADAPTER(MiniportAdapterHandle
);
1848 PADAPTER_BINDING AdapterBinding
= (PADAPTER_BINDING
)Adapter
->MiniportAdapterBinding
;
1850 NDIS_DbgPrint(MAX_TRACE
, ("Called.\n"));
1852 (*AdapterBinding
->ProtocolBinding
->Chars
.RequestCompleteHandler
)(
1853 AdapterBinding
->NdisOpenBlock
.ProtocolBindingContext
,
1854 Adapter
->NdisMiniportBlock
.MediaRequest
,
1865 IN NDIS_HANDLE MiniportAdapterHandle
,
1866 IN NDIS_HANDLE MiniportAdapterContext
,
1867 IN BOOLEAN BusMaster
,
1868 IN NDIS_INTERFACE_TYPE AdapterType
)
1870 * FUNCTION: Informs the NDIS library of significant features of the caller's NIC
1872 * MiniportAdapterHandle = Handle input to MiniportInitialize
1873 * MiniportAdapterContext = Pointer to context information
1874 * BusMaster = Specifies TRUE if the caller's NIC is a busmaster DMA device
1875 * AdapterType = Specifies the I/O bus interface of the caller's NIC
1878 PLOGICAL_ADAPTER Adapter
= GET_LOGICAL_ADAPTER(MiniportAdapterHandle
);
1880 NDIS_DbgPrint(MAX_TRACE
, ("Called.\n"));
1882 Adapter
->NdisMiniportBlock
.MiniportAdapterContext
= MiniportAdapterContext
;
1885 Adapter
->NdisMiniportBlock
.Flags
|= NDIS_ATTRIBUTE_BUS_MASTER
;
1887 Adapter
->NdisMiniportBlock
.AdapterType
= AdapterType
;
1888 Adapter
->AttributesSet
= TRUE
;
1897 NdisMSetAttributesEx(
1898 IN NDIS_HANDLE MiniportAdapterHandle
,
1899 IN NDIS_HANDLE MiniportAdapterContext
,
1900 IN UINT CheckForHangTimeInSeconds OPTIONAL
,
1901 IN ULONG AttributeFlags
,
1902 IN NDIS_INTERFACE_TYPE AdapterType
)
1904 * FUNCTION: Informs the NDIS library of significant features of the caller's NIC
1906 * MiniportAdapterHandle = Handle input to MiniportInitialize
1907 * MiniportAdapterContext = Pointer to context information
1908 * CheckForHangTimeInSeconds = Specifies interval in seconds at which
1909 * MiniportCheckForHang should be called
1910 * AttributeFlags = Bitmask that indicates specific attributes
1911 * AdapterType = Specifies the I/O bus interface of the caller's NIC
1914 /* TODO: Take CheckForHandTimeInSeconds into account! */
1916 PLOGICAL_ADAPTER Adapter
= GET_LOGICAL_ADAPTER(MiniportAdapterHandle
);
1918 NDIS_DbgPrint(MAX_TRACE
, ("Called - NdisMSetAttributesEx() is partly-implemented.\n"));
1920 Adapter
->NdisMiniportBlock
.MiniportAdapterContext
= MiniportAdapterContext
;
1922 /* don't know why this is here - anybody? */
1923 Adapter
->NdisMiniportBlock
.Flags
= AttributeFlags
;
1925 Adapter
->NdisMiniportBlock
.AdapterType
= AdapterType
;
1926 Adapter
->AttributesSet
= TRUE
;
1936 IN ULONG MicrosecondsToSleep
)
1938 * FUNCTION: delay the thread's execution for MicrosecondsToSleep
1940 * MicrosecondsToSleep: duh...
1942 * - Because this is a blocking call, current IRQL must be < DISPATCH_LEVEL
1946 LARGE_INTEGER DueTime
;
1950 DueTime
.QuadPart
= (-1) * 10 * MicrosecondsToSleep
;
1952 KeInitializeTimer(&Timer
);
1953 KeSetTimer(&Timer
, DueTime
, 0);
1954 KeWaitForSingleObject(&Timer
, Executive
, KernelMode
, FALSE
, 0);
1963 NdisMSynchronizeWithInterrupt(
1964 IN PNDIS_MINIPORT_INTERRUPT Interrupt
,
1965 IN PVOID SynchronizeFunction
,
1966 IN PVOID SynchronizeContext
)
1968 return(KeSynchronizeExecution((PKINTERRUPT
)Interrupt
,
1969 (PKSYNCHRONIZE_ROUTINE
)SynchronizeFunction
,
1970 SynchronizeContext
));
1980 IN NDIS_HANDLE LogHandle
,
1982 IN UINT LogBufferSize
)
1986 return NDIS_STATUS_FAILURE
;
1995 NdisTerminateWrapper(
1996 IN NDIS_HANDLE NdisWrapperHandle
,
1997 IN PVOID SystemSpecific
)
1999 * FUNCTION: Releases resources allocated by a call to NdisInitializeWrapper
2001 * NdisWrapperHandle = Handle returned by NdisInitializeWrapper (MINIPORT_DRIVER)
2002 * SystemSpecific = Always NULL
2005 PMINIPORT_DRIVER Miniport
= GET_MINIPORT_DRIVER(NdisWrapperHandle
);
2007 NDIS_DbgPrint(MAX_TRACE
, ("Called.\n"));
2009 ExFreePool(Miniport
->RegistryPath
->Buffer
);
2010 ExFreePool(Miniport
->RegistryPath
);
2011 ExFreePool(Miniport
);