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
);
115 DbgPrint("\nFRAME:");
118 Length
= (LookaheadBufferSize
< 64)? LookaheadBufferSize
: 64;
119 for (i
= 0; i
< Length
; i
++) {
121 DbgPrint("\n%04X ", i
);
122 DbgPrint("%02X ", *p
);
126 DbgPrint("\n*** RECEIVE PACKET STOP ***\n");
134 PLOGICAL_ADAPTER Adapter
,
135 NDIS_HANDLE MacReceiveContext
,
137 UINT HeaderBufferSize
,
138 PVOID LookaheadBuffer
,
139 UINT LookaheadBufferSize
,
142 * FUNCTION: Indicate received data to bound protocols
144 * Adapter = Pointer to logical adapter
145 * MacReceiveContext = MAC receive context handle
146 * HeaderBuffer = Pointer to header buffer
147 * HeaderBufferSize = Size of header buffer
148 * LookaheadBuffer = Pointer to lookahead buffer
149 * LookaheadBufferSize = Size of lookahead buffer
150 * PacketSize = Total size of received packet
154 PLIST_ENTRY CurrentEntry
;
155 PADAPTER_BINDING AdapterBinding
;
157 NDIS_DbgPrint(DEBUG_MINIPORT
, ("Called. Adapter (0x%X) HeaderBuffer (0x%X) "
158 "HeaderBufferSize (0x%X) LookaheadBuffer (0x%X) LookaheadBufferSize (0x%X).\n",
159 Adapter
, HeaderBuffer
, HeaderBufferSize
, LookaheadBuffer
, LookaheadBufferSize
));
161 MiniDisplayPacket2(HeaderBuffer
, HeaderBufferSize
, LookaheadBuffer
, LookaheadBufferSize
);
164 * XXX Think about this. This is probably broken. Spinlocks are
165 * taken out for now until i comprehend the Right Way to do this.
167 * This used to acquire the MiniportBlock spinlock and hold it until
168 * just before the call to ReceiveHandler. It would then release and
169 * subsequently re-acquire the lock.
171 * I don't see how this does any good, as it would seem he's just
172 * trying to protect the packet list. If someobdy else dequeues
173 * a packet, we are in fact in bad shape, but we don't want to
174 * necessarily call the receive handler at elevated irql either.
176 * therefore: We *are* going to call the receive handler at high irql
177 * (due to holding the lock) for now, and eventually we have to
178 * figure out another way to protect this packet list.
180 * UPDATE: this is busted; this results in a recursive lock acquisition.
182 //NDIS_DbgPrint(MAX_TRACE, ("acquiring miniport block lock\n"));
183 //KeAcquireSpinLock(&Adapter->NdisMiniportBlock.Lock, &OldIrql);
185 CurrentEntry
= Adapter
->ProtocolListHead
.Flink
;
186 NDIS_DbgPrint(DEBUG_MINIPORT
, ("CurrentEntry = %x\n", CurrentEntry
));
188 if (CurrentEntry
== &Adapter
->ProtocolListHead
)
190 NDIS_DbgPrint(DEBUG_MINIPORT
, ("WARNING: No upper protocol layer.\n"));
193 while (CurrentEntry
!= &Adapter
->ProtocolListHead
)
195 AdapterBinding
= CONTAINING_RECORD(CurrentEntry
, ADAPTER_BINDING
, AdapterListEntry
);
196 NDIS_DbgPrint(DEBUG_MINIPORT
, ("AdapterBinding = %x\n", AdapterBinding
));
199 /* KeReleaseSpinLock(&Adapter->NdisMiniportBlock.Lock, OldIrql); */
204 NDIS_DbgPrint(MIN_TRACE
, ("AdapterBinding was null\n"));
208 if(!AdapterBinding
->ProtocolBinding
)
210 NDIS_DbgPrint(MIN_TRACE
, ("AdapterBinding->ProtocolBinding was null\n"));
214 if(!AdapterBinding
->ProtocolBinding
->Chars
.u4
.ReceiveHandler
)
216 NDIS_DbgPrint(MIN_TRACE
, ("AdapterBinding->ProtocolBinding->Chars.u4.ReceiveHandler was null\n"));
223 ("XXX (%x) %x %x %x %x %x %x %x XXX\n",
224 *AdapterBinding
->ProtocolBinding
->Chars
.u4
.ReceiveHandler
,
225 AdapterBinding
->NdisOpenBlock
.ProtocolBindingContext
,
233 /* call the receive handler */
234 (*AdapterBinding
->ProtocolBinding
->Chars
.u4
.ReceiveHandler
)(
235 AdapterBinding
->NdisOpenBlock
.ProtocolBindingContext
,
244 /* KeAcquireSpinLock(&Adapter->NdisMiniportBlock.Lock, &OldIrql); */
246 CurrentEntry
= CurrentEntry
->Flink
;
249 //KeReleaseSpinLock(&Adapter->NdisMiniportBlock.Lock, OldIrql);
251 NDIS_DbgPrint(MAX_TRACE
, ("Leaving.\n"));
256 MiniIndicateReceivePacket(
257 IN NDIS_HANDLE Miniport
,
258 IN PPNDIS_PACKET PacketArray
,
259 IN UINT NumberOfPackets
)
261 * FUNCTION: receives miniport packet array indications
263 * Miniport: Miniport handle for the adapter
264 * PacketArray: pointer to a list of packet pointers to indicate
265 * NumberOfPackets: number of packets to indicate
267 * - This currently is a big temporary hack. In the future this should
268 * call ProtocolReceivePacket() on each bound protocol if it exists.
269 * For now it just mimics NdisMEthIndicateReceive.
274 for(i
= 0; i
< NumberOfPackets
; i
++)
276 PCHAR PacketBuffer
= 0;
277 UINT PacketLength
= 0;
278 PNDIS_BUFFER NdisBuffer
= 0;
280 #define PACKET_TAG (('k' << 24) + ('P' << 16) + ('D' << 8) + 'N')
282 NdisAllocateMemoryWithTag((PVOID
)&PacketBuffer
, 1518, PACKET_TAG
);
285 NDIS_DbgPrint(MIN_TRACE
, ("insufficient resources\n"));
289 NdisQueryPacket(PacketArray
[i
], NULL
, NULL
, &NdisBuffer
, NULL
);
293 PNDIS_BUFFER CurrentBuffer
;
297 NdisQueryBuffer(NdisBuffer
, &BufferVa
, &BufferLen
);
298 memcpy(PacketBuffer
+ PacketLength
, BufferVa
, BufferLen
);
299 PacketLength
+= BufferLen
;
301 CurrentBuffer
= NdisBuffer
;
302 NdisGetNextBuffer(CurrentBuffer
, &NdisBuffer
);
305 NDIS_DbgPrint(MID_TRACE
, ("indicating a %d-byte packet\n", PacketLength
));
307 MiniIndicateData(Miniport
, NULL
, PacketBuffer
, 14, PacketBuffer
+14, PacketLength
-14, PacketLength
-14);
309 NdisFreeMemory(PacketBuffer
, 0, 0);
315 MiniEthReceiveComplete(
316 IN PETH_FILTER Filter
)
318 * FUNCTION: Receive indication complete function for Ethernet devices
320 * Filter = Pointer to Ethernet filter
324 PLIST_ENTRY CurrentEntry
;
325 PLOGICAL_ADAPTER Adapter
;
326 PADAPTER_BINDING AdapterBinding
;
328 NDIS_DbgPrint(DEBUG_MINIPORT
, ("Called.\n"));
330 if( !Filter
) return;
332 Adapter
= (PLOGICAL_ADAPTER
)Filter
->Miniport
;
334 NDIS_DbgPrint(MAX_TRACE
, ("acquiring miniport block lock\n"));
335 KeAcquireSpinLock(&Adapter
->NdisMiniportBlock
.Lock
, &OldIrql
);
337 CurrentEntry
= Adapter
->ProtocolListHead
.Flink
;
339 while (CurrentEntry
!= &Adapter
->ProtocolListHead
)
341 AdapterBinding
= CONTAINING_RECORD(CurrentEntry
, ADAPTER_BINDING
, AdapterListEntry
);
343 /* see comment in MiniIndicateData */
344 /* KeReleaseSpinLock(&Adapter->NdisMiniportBlock.Lock, OldIrql); */
346 (*AdapterBinding
->ProtocolBinding
->Chars
.ReceiveCompleteHandler
)(
347 AdapterBinding
->NdisOpenBlock
.ProtocolBindingContext
);
350 /* KeAcquireSpinLock(&Adapter->NdisMiniportBlock.Lock, &OldIrql); */
352 CurrentEntry
= CurrentEntry
->Flink
;
355 KeReleaseSpinLock(&Adapter
->NdisMiniportBlock
.Lock
, OldIrql
);
360 MiniEthReceiveIndication(
361 IN PETH_FILTER Filter
,
362 IN NDIS_HANDLE MacReceiveContext
,
364 IN PVOID HeaderBuffer
,
365 IN UINT HeaderBufferSize
,
366 IN PVOID LookaheadBuffer
,
367 IN UINT LookaheadBufferSize
,
370 * FUNCTION: Receive indication function for Ethernet devices
372 * MiniportAdapter = Miniport Adapter Handle (PLOGICAL_ADAPTER)
373 * MacReceiveContext = MAC receive context handle
374 * Address = Pointer to destination Ethernet address
375 * HeaderBuffer = Pointer to Ethernet header buffer
376 * HeaderBufferSize = Size of Ethernet header buffer
377 * LookaheadBuffer = Pointer to lookahead buffer
378 * LookaheadBufferSize = Size of lookahead buffer
379 * PacketSize = Total size of received packet
382 MiniIndicateData((PLOGICAL_ADAPTER
)Filter
->Miniport
,
394 IN NDIS_HANDLE MiniportAdapterHandle
,
395 IN NDIS_STATUS Status
,
396 IN BOOLEAN AddressingReset
)
404 IN NDIS_HANDLE MiniportAdapterHandle
,
405 IN PNDIS_PACKET Packet
,
406 IN NDIS_STATUS Status
)
408 * FUNCTION: Forwards a message to the initiating protocol saying
409 * that a packet was handled
411 * NdisAdapterHandle = Handle input to MiniportInitialize
412 * Packet = Pointer to NDIS packet that was sent
413 * Status = Status of send operation
416 PADAPTER_BINDING AdapterBinding
;
418 NDIS_DbgPrint(DEBUG_MINIPORT
, ("Called.\n"));
420 AdapterBinding
= (PADAPTER_BINDING
)Packet
->Reserved
[0];
422 (*AdapterBinding
->ProtocolBinding
->Chars
.u2
.SendCompleteHandler
)(
423 AdapterBinding
->NdisOpenBlock
.ProtocolBindingContext
,
430 MiniSendResourcesAvailable(
431 IN NDIS_HANDLE MiniportAdapterHandle
)
438 MiniTransferDataComplete(
439 IN NDIS_HANDLE MiniportAdapterHandle
,
440 IN PNDIS_PACKET Packet
,
441 IN NDIS_STATUS Status
,
442 IN UINT BytesTransferred
)
444 PLOGICAL_ADAPTER Adapter
= (PLOGICAL_ADAPTER
)MiniportAdapterHandle
;
445 PADAPTER_BINDING AdapterBinding
= Adapter
->MiniportAdapterBinding
;
447 NDIS_DbgPrint(DEBUG_MINIPORT
, ("Called.\n"));
449 (*AdapterBinding
->ProtocolBinding
->Chars
.u3
.TransferDataCompleteHandler
)(
450 AdapterBinding
->NdisOpenBlock
.ProtocolBindingContext
,
458 MiniAdapterHasAddress(
459 PLOGICAL_ADAPTER Adapter
,
462 * FUNCTION: Determines wether a packet has the same destination address as an adapter
464 * Adapter = Pointer to logical adapter object
465 * Packet = Pointer to NDIS packet
467 * TRUE if the destination address is that of the adapter, FALSE if not
473 PNDIS_BUFFER NdisBuffer
;
476 NDIS_DbgPrint(DEBUG_MINIPORT
, ("Called.\n"));
481 NDIS_DbgPrint(MID_TRACE
, ("Adapter object was null\n"));
487 NDIS_DbgPrint(MID_TRACE
, ("Packet was null\n"));
492 NdisQueryPacket(Packet
, NULL
, NULL
, &NdisBuffer
, NULL
);
496 NDIS_DbgPrint(MID_TRACE
, ("Packet contains no buffers.\n"));
500 NdisQueryBuffer(NdisBuffer
, (PVOID
)&Start2
, &BufferLength
);
502 /* FIXME: Should handle fragmented packets */
504 switch (Adapter
->NdisMiniportBlock
.MediaType
)
506 case NdisMedium802_3
:
507 Length
= ETH_LENGTH_OF_ADDRESS
;
508 /* Destination address is the first field */
512 NDIS_DbgPrint(MIN_TRACE
, ("Adapter has unsupported media type (0x%X).\n", Adapter
->NdisMiniportBlock
.MediaType
));
516 if (BufferLength
< Length
)
518 NDIS_DbgPrint(MID_TRACE
, ("Buffer is too small.\n"));
522 Start1
= (PUCHAR
)&Adapter
->Address
;
523 NDIS_DbgPrint(MAX_TRACE
, ("packet address: %x:%x:%x:%x:%x:%x adapter address: %x:%x:%x:%x:%x:%x\n",
524 *((char *)Start1
), *(((char *)Start1
)+1), *(((char *)Start1
)+2), *(((char *)Start1
)+3), *(((char *)Start1
)+4), *(((char *)Start1
)+5),
525 *((char *)Start2
), *(((char *)Start2
)+1), *(((char *)Start2
)+2), *(((char *)Start2
)+3), *(((char *)Start2
)+4), *(((char *)Start2
)+5))
528 return (RtlCompareMemory((PVOID
)Start1
, (PVOID
)Start2
, Length
) == Length
);
534 PNDIS_STRING AdapterName
)
536 * FUNCTION: Finds an adapter object by name
538 * AdapterName = Pointer to name of adapter
540 * Pointer to logical adapter object, or NULL if none was found.
541 * If found, the adapter is referenced for the caller. The caller
542 * is responsible for dereferencing after use
546 PLIST_ENTRY CurrentEntry
;
547 PLOGICAL_ADAPTER Adapter
= 0;
551 NDIS_DbgPrint(DEBUG_MINIPORT
, ("Called.\n"));
553 if(IsListEmpty(&AdapterListHead
))
555 NDIS_DbgPrint(DEBUG_MINIPORT
, ("No registered miniports for protocol to bind to\n"));
559 KeAcquireSpinLock(&AdapterListLock
, &OldIrql
);
563 CurrentEntry
= AdapterListHead
.Flink
;
565 while (CurrentEntry
!= &AdapterListHead
)
567 Adapter
= CONTAINING_RECORD(CurrentEntry
, LOGICAL_ADAPTER
, ListEntry
);
571 NDIS_DbgPrint(DEBUG_MINIPORT
, ("AdapterName = %wZ\n", &AdapterName
));
572 NDIS_DbgPrint(DEBUG_MINIPORT
, ("DeviceName = %wZ\n", &Adapter
->DeviceName
));
574 if (RtlCompareUnicodeString(AdapterName
, &Adapter
->DeviceName
, TRUE
) == 0)
576 ReferenceObject(Adapter
);
580 CurrentEntry
= CurrentEntry
->Flink
;
584 KeReleaseSpinLock(&AdapterListLock
, OldIrql
);
588 NDIS_DbgPrint(DEBUG_MINIPORT
, ("Leaving. Adapter found at 0x%x\n", Adapter
));
592 NDIS_DbgPrint(DEBUG_MINIPORT
, ("Leaving (adapter not found).\n"));
600 MiniQueryInformation(
601 PLOGICAL_ADAPTER Adapter
,
606 * FUNCTION: Queries a logical adapter for properties
608 * Adapter = Pointer to the logical adapter object to query
609 * Oid = Specifies the Object ID to query for
610 * Size = If non-zero overrides the length in the adapter object
611 * BytesWritten = Address of buffer to place number of bytes written
613 * If the specified buffer is too small, a new buffer is allocated,
614 * and the query is attempted again
616 * Status of operation
618 * Is there any way to use the buffer provided by the protocol?
621 NDIS_STATUS NdisStatus
;
624 NDIS_DbgPrint(DEBUG_MINIPORT
, ("Called.\n"));
626 if (Adapter
->QueryBufferLength
== 0)
628 /* XXX is 32 the right number? */
629 Adapter
->QueryBuffer
= ExAllocatePool(NonPagedPool
, (Size
== 0)? 32 : Size
);
631 if (!Adapter
->QueryBuffer
)
633 NDIS_DbgPrint(MIN_TRACE
, ("Insufficient resources.\n"));
634 return NDIS_STATUS_RESOURCES
;
638 Adapter
->QueryBufferLength
= (Size
== 0)? 32 : Size
;
641 /* this is the third time i've seen this conditional */
642 BytesNeeded
= (Size
== 0)? Adapter
->QueryBufferLength
: Size
;
644 /* call the miniport's queryinfo handler */
645 NdisStatus
= (*Adapter
->Miniport
->Chars
.QueryInformationHandler
)(
646 Adapter
->NdisMiniportBlock
.MiniportAdapterContext
,
648 Adapter
->QueryBuffer
,
653 /* XXX is status_pending part of success macro? */
654 if ((NT_SUCCESS(NdisStatus
)) || (NdisStatus
== NDIS_STATUS_PENDING
))
656 NDIS_DbgPrint(DEBUG_MINIPORT
, ("Miniport returned status (0x%X).\n", NdisStatus
));
660 if (NdisStatus
== NDIS_STATUS_INVALID_LENGTH
)
662 ExFreePool(Adapter
->QueryBuffer
);
664 Adapter
->QueryBufferLength
+= BytesNeeded
;
665 Adapter
->QueryBuffer
= ExAllocatePool(NonPagedPool
, Adapter
->QueryBufferLength
);
667 if (!Adapter
->QueryBuffer
)
669 NDIS_DbgPrint(MIN_TRACE
, ("Insufficient resources.\n"));
670 return NDIS_STATUS_RESOURCES
;
673 NdisStatus
= (*Adapter
->Miniport
->Chars
.QueryInformationHandler
)(
674 Adapter
->NdisMiniportBlock
.MiniportAdapterContext
,
676 Adapter
->QueryBuffer
,
689 PLOGICAL_ADAPTER Adapter
,
690 NDIS_WORK_ITEM_TYPE WorkItemType
,
691 PVOID WorkItemContext
,
692 NDIS_HANDLE Initiator
)
694 * FUNCTION: Queues a work item for execution at a later time
696 * Adapter = Pointer to the logical adapter object to queue work item on
697 * WorkItemType = Type of work item to queue
698 * WorkItemContext = Pointer to context information for work item
699 * Initiator = Pointer to ADAPTER_BINDING structure of initiating protocol
701 * Adapter lock must be held when called
703 * Status of operation
706 PNDIS_MINIPORT_WORK_ITEM Item
;
708 NDIS_DbgPrint(MAX_TRACE
, ("Called.\n"));
712 if (Adapter
->WorkQueueLevel
< NDIS_MINIPORT_WORK_QUEUE_SIZE
- 1)
714 Item
= &Adapter
->WorkQueue
[Adapter
->WorkQueueLevel
];
715 Adapter
->WorkQueueLevel
++;
719 Item
= ExAllocatePool(NonPagedPool
, sizeof(NDIS_MINIPORT_WORK_ITEM
));
722 /* Set flag so we know that the buffer should be freed when work item is dequeued */
723 Item
->Allocated
= TRUE
;
727 NDIS_DbgPrint(MIN_TRACE
, ("Insufficient resources.\n"));
728 return NDIS_STATUS_RESOURCES
;
732 Item
->WorkItemType
= WorkItemType
;
733 Item
->WorkItemContext
= WorkItemContext
;
734 Item
->Initiator
= Initiator
;
736 /* safe due to adapter lock held */
737 Item
->Link
.Next
= NULL
;
738 if (!Adapter
->WorkQueueHead
)
740 Adapter
->WorkQueueHead
= Item
;
741 Adapter
->WorkQueueTail
= Item
;
745 Adapter
->WorkQueueTail
->Link
.Next
= (PSINGLE_LIST_ENTRY
)Item
;
746 Adapter
->WorkQueueTail
= Item
;
749 KeInsertQueueDpc(&Adapter
->MiniportDpc
, NULL
, NULL
);
751 return NDIS_STATUS_SUCCESS
;
758 PLOGICAL_ADAPTER Adapter
,
759 NDIS_WORK_ITEM_TYPE
*WorkItemType
,
760 PVOID
*WorkItemContext
,
761 NDIS_HANDLE
*Initiator
)
763 * FUNCTION: Dequeues a work item from the work queue of a logical adapter
765 * Adapter = Pointer to the logical adapter object to dequeue work item from
766 * WorkItemType = Address of buffer for work item type
767 * WorkItemContext = Address of buffer for pointer to context information
768 * Initiator = Address of buffer for initiator of the work (ADAPTER_BINDING)
770 * Adapter lock must be held when called
772 * Status of operation
775 PNDIS_MINIPORT_WORK_ITEM Item
;
777 NDIS_DbgPrint(MAX_TRACE
, ("Called.\n"));
779 Item
= Adapter
->WorkQueueHead
;
783 /* safe due to adapter lock held */
784 Adapter
->WorkQueueHead
= (PNDIS_MINIPORT_WORK_ITEM
)Item
->Link
.Next
;
786 if (Item
== Adapter
->WorkQueueTail
)
787 Adapter
->WorkQueueTail
= NULL
;
789 *WorkItemType
= Item
->WorkItemType
;
790 *WorkItemContext
= Item
->WorkItemContext
;
791 *Initiator
= Item
->Initiator
;
799 Adapter
->WorkQueueLevel
--;
801 if (Adapter
->WorkQueueLevel
< 0)
803 NDIS_DbgPrint(MIN_TRACE
, ("Adapter->WorkQueueLevel is < 0 (should be >= 0).\n"));
808 return NDIS_STATUS_SUCCESS
;
811 return NDIS_STATUS_FAILURE
;
817 PLOGICAL_ADAPTER Adapter
,
818 PNDIS_REQUEST NdisRequest
)
820 * FUNCTION: Sends a request to a miniport
822 * Adapter = Pointer to logical adapter object
823 * NdisRequest = Pointer to NDIS request structure describing request
825 * Status of operation
828 NDIS_DbgPrint(DEBUG_MINIPORT
, ("Called.\n"));
830 Adapter
->NdisMiniportBlock
.MediaRequest
= NdisRequest
;
832 switch (NdisRequest
->RequestType
)
834 case NdisRequestQueryInformation
:
835 return (*Adapter
->Miniport
->Chars
.QueryInformationHandler
)(
836 Adapter
->NdisMiniportBlock
.MiniportAdapterContext
,
837 NdisRequest
->DATA
.QUERY_INFORMATION
.Oid
,
838 NdisRequest
->DATA
.QUERY_INFORMATION
.InformationBuffer
,
839 NdisRequest
->DATA
.QUERY_INFORMATION
.InformationBufferLength
,
840 (PULONG
)&NdisRequest
->DATA
.QUERY_INFORMATION
.BytesWritten
,
841 (PULONG
)&NdisRequest
->DATA
.QUERY_INFORMATION
.BytesNeeded
);
844 case NdisRequestSetInformation
:
845 return (*Adapter
->Miniport
->Chars
.SetInformationHandler
)(
846 Adapter
->NdisMiniportBlock
.MiniportAdapterContext
,
847 NdisRequest
->DATA
.SET_INFORMATION
.Oid
,
848 NdisRequest
->DATA
.SET_INFORMATION
.InformationBuffer
,
849 NdisRequest
->DATA
.SET_INFORMATION
.InformationBufferLength
,
850 (PULONG
)&NdisRequest
->DATA
.SET_INFORMATION
.BytesRead
,
851 (PULONG
)&NdisRequest
->DATA
.SET_INFORMATION
.BytesNeeded
);
855 return NDIS_STATUS_FAILURE
;
860 VOID STDCALL
MiniportDpc(
862 IN PVOID DeferredContext
,
863 IN PVOID SystemArgument1
,
864 IN PVOID SystemArgument2
)
866 * FUNCTION: Deferred routine to handle serialization
868 * Dpc = Pointer to DPC object
869 * DeferredContext = Pointer to context information (LOGICAL_ADAPTER)
870 * SystemArgument1 = Unused
871 * SystemArgument2 = Unused
874 NDIS_STATUS NdisStatus
;
875 PVOID WorkItemContext
;
876 NDIS_WORK_ITEM_TYPE WorkItemType
;
877 PADAPTER_BINDING AdapterBinding
;
878 PLOGICAL_ADAPTER Adapter
= GET_LOGICAL_ADAPTER(DeferredContext
);
880 NDIS_DbgPrint(DEBUG_MINIPORT
, ("Called.\n"));
882 /* XXX is adapter lock held here? should be... */
883 NdisStatus
= MiniDequeueWorkItem(Adapter
, &WorkItemType
, &WorkItemContext
, (PNDIS_HANDLE
)&AdapterBinding
);
885 if (NdisStatus
== NDIS_STATUS_SUCCESS
)
887 Adapter
->MiniportAdapterBinding
= AdapterBinding
;
889 switch (WorkItemType
)
891 case NdisWorkItemSend
:
893 * called by ProSend when protocols want to send packets to the miniport
896 MiniDisplayPacket((PNDIS_PACKET
)WorkItemContext
);
898 if(Adapter
->Miniport
->Chars
.SendPacketsHandler
)
900 NDIS_DbgPrint(MAX_TRACE
, ("Calling miniport's SendPackets handler\n"));
903 * XXX assumes single-packet - prolly OK since we'll call something
904 * different on multi-packet sends
906 (*Adapter
->Miniport
->Chars
.SendPacketsHandler
)(
907 Adapter
->NdisMiniportBlock
.MiniportAdapterContext
, (PPNDIS_PACKET
)&WorkItemContext
, 1);
909 NDIS_DbgPrint(MAX_TRACE
, ("back from miniport's SendPackets handler\n"));
913 NDIS_DbgPrint(MAX_TRACE
, ("Calling miniport's Send handler\n"));
915 NdisStatus
= (*Adapter
->Miniport
->Chars
.u1
.SendHandler
)(
916 Adapter
->NdisMiniportBlock
.MiniportAdapterContext
, (PNDIS_PACKET
)WorkItemContext
, 0);
918 NDIS_DbgPrint(MAX_TRACE
, ("back from miniport's Send handler\n"));
920 if (NdisStatus
!= NDIS_STATUS_PENDING
)
921 MiniSendComplete((NDIS_HANDLE
)Adapter
, (PNDIS_PACKET
)WorkItemContext
, NdisStatus
);
926 case NdisWorkItemSendLoopback
:
928 * called by ProSend when protocols want to send loopback packets
930 /* XXX atm ProIndicatePacket sends a packet up via the loopback adapter only */
931 NdisStatus
= ProIndicatePacket(Adapter
, (PNDIS_PACKET
)WorkItemContext
);
932 MiniSendComplete((NDIS_HANDLE
)Adapter
, (PNDIS_PACKET
)WorkItemContext
, NdisStatus
);
935 case NdisWorkItemReturnPackets
:
938 case NdisWorkItemResetRequested
:
941 case NdisWorkItemResetInProgress
:
944 case NdisWorkItemHalt
:
947 case NdisWorkItemMiniportCallback
:
950 case NdisWorkItemRequest
:
951 NdisStatus
= MiniDoRequest(Adapter
, (PNDIS_REQUEST
)WorkItemContext
);
953 if (NdisStatus
== NDIS_STATUS_PENDING
)
956 switch (((PNDIS_REQUEST
)WorkItemContext
)->RequestType
)
958 case NdisRequestQueryInformation
:
959 NdisMQueryInformationComplete((NDIS_HANDLE
)Adapter
, NdisStatus
);
962 case NdisRequestSetInformation
:
963 NdisMSetInformationComplete((NDIS_HANDLE
)Adapter
, NdisStatus
);
967 NDIS_DbgPrint(MIN_TRACE
, ("Unknown NDIS request type.\n"));
973 NDIS_DbgPrint(MIN_TRACE
, ("Unknown NDIS work item type (%d).\n", WorkItemType
));
986 IN NDIS_HANDLE LogHandle
)
998 IN NDIS_HANDLE MiniportAdapterHandle
,
1000 OUT PNDIS_HANDLE LogHandle
)
1004 return NDIS_STATUS_FAILURE
;
1013 NdisMDeregisterAdapterShutdownHandler(
1014 IN NDIS_HANDLE MiniportHandle
)
1016 * FUNCTION: de-registers a shutdown handler
1017 * ARGUMENTS: MiniportHandle: Handle passed into MiniportInitialize
1020 NDIS_DbgPrint(DEBUG_MINIPORT
, ("Called.\n"));
1021 PLOGICAL_ADAPTER Adapter
= (PLOGICAL_ADAPTER
)MiniportHandle
;
1023 if(Adapter
->BugcheckContext
->ShutdownHandler
)
1024 KeDeregisterBugCheckCallback(Adapter
->BugcheckContext
->CallbackRecord
);
1034 IN NDIS_HANDLE LogHandle
)
1045 NdisMIndicateStatus(
1046 IN NDIS_HANDLE MiniportAdapterHandle
,
1047 IN NDIS_STATUS GeneralStatus
,
1048 IN PVOID StatusBuffer
,
1049 IN UINT StatusBufferSize
)
1060 NdisMIndicateStatusComplete(
1061 IN NDIS_HANDLE MiniportAdapterHandle
)
1072 NdisInitializeWrapper(
1073 OUT PNDIS_HANDLE NdisWrapperHandle
,
1074 IN PVOID SystemSpecific1
,
1075 IN PVOID SystemSpecific2
,
1076 IN PVOID SystemSpecific3
)
1078 * FUNCTION: Notifies the NDIS library that a new miniport is initializing
1080 * NdisWrapperHandle = Address of buffer to place NDIS wrapper handle
1081 * SystemSpecific1 = Pointer to the driver's driver object
1082 * SystemSpecific2 = Pointer to the driver's registry path
1083 * SystemSpecific3 = Always NULL
1085 * - SystemSpecific2 goes invalid so we copy it
1088 PMINIPORT_DRIVER Miniport
;
1089 PUNICODE_STRING RegistryPath
;
1090 WCHAR
*RegistryBuffer
;
1092 NDIS_DbgPrint(MAX_TRACE
, ("Called.\n"));
1094 ASSERT(NdisWrapperHandle
);
1096 *NdisWrapperHandle
= NULL
;
1098 #if BREAK_ON_MINIPORT_INIT
1099 __asm__ ("int $3\n");
1102 Miniport
= ExAllocatePool(NonPagedPool
, sizeof(MINIPORT_DRIVER
));
1106 NDIS_DbgPrint(MIN_TRACE
, ("Insufficient resources.\n"));
1110 RtlZeroMemory(Miniport
, sizeof(MINIPORT_DRIVER
));
1112 KeInitializeSpinLock(&Miniport
->Lock
);
1114 Miniport
->RefCount
= 1;
1116 Miniport
->DriverObject
= (PDRIVER_OBJECT
)SystemSpecific1
;
1118 /* set the miniport's driver registry path */
1119 RegistryPath
= ExAllocatePool(PagedPool
, sizeof(UNICODE_STRING
));
1122 NDIS_DbgPrint(MIN_TRACE
, ("Insufficient resources.\n"));
1126 RegistryPath
->Length
= ((PUNICODE_STRING
)SystemSpecific2
)->Length
;
1127 RegistryPath
->MaximumLength
= RegistryPath
->Length
+ sizeof(WCHAR
); /* room for 0-term */
1129 RegistryBuffer
= ExAllocatePool(PagedPool
, RegistryPath
->MaximumLength
);
1132 NDIS_DbgPrint(MIN_TRACE
, ("Insufficient resources.\n"));
1136 RtlCopyMemory(RegistryBuffer
, ((PUNICODE_STRING
)SystemSpecific2
)->Buffer
, RegistryPath
->Length
);
1137 RegistryBuffer
[RegistryPath
->Length
/sizeof(WCHAR
)] = 0;
1139 RegistryPath
->Buffer
= RegistryBuffer
;
1140 Miniport
->RegistryPath
= RegistryPath
;
1142 InitializeListHead(&Miniport
->AdapterListHead
);
1144 /* Put miniport in global miniport list */
1145 ExInterlockedInsertTailList(&MiniportListHead
, &Miniport
->ListEntry
, &MiniportListLock
);
1147 *NdisWrapperHandle
= Miniport
;
1156 NdisMQueryInformationComplete(
1157 IN NDIS_HANDLE MiniportAdapterHandle
,
1158 IN NDIS_STATUS Status
)
1160 PLOGICAL_ADAPTER Adapter
= GET_LOGICAL_ADAPTER(MiniportAdapterHandle
);
1161 PADAPTER_BINDING AdapterBinding
= (PADAPTER_BINDING
)Adapter
->MiniportAdapterBinding
;
1163 NDIS_DbgPrint(MAX_TRACE
, ("Called.\n"));
1165 (*AdapterBinding
->ProtocolBinding
->Chars
.RequestCompleteHandler
)(
1166 AdapterBinding
->NdisOpenBlock
.ProtocolBindingContext
,
1167 Adapter
->NdisMiniportBlock
.MediaRequest
,
1172 VOID STDCALL
NdisIBugcheckCallback(
1176 * FUNCTION: Internal callback for handling bugchecks - calls adapter's shutdown handler
1178 * Buffer: Pointer to a bugcheck callback context
1182 PMINIPORT_BUGCHECK_CONTEXT Context
= (PMINIPORT_BUGCHECK_CONTEXT
)Buffer
;
1183 ADAPTER_SHUTDOWN_HANDLER sh
= (ADAPTER_SHUTDOWN_HANDLER
)Context
->ShutdownHandler
;
1185 NDIS_DbgPrint(DEBUG_MINIPORT
, ("Called.\n"));
1188 sh(Context
->DriverContext
);
1197 NdisMRegisterAdapterShutdownHandler(
1198 IN NDIS_HANDLE MiniportHandle
,
1199 IN PVOID ShutdownContext
,
1200 IN ADAPTER_SHUTDOWN_HANDLER ShutdownHandler
)
1202 * FUNCTION: Register a shutdown handler for an adapter
1204 * MiniportHandle: Handle originally passed into MiniportInitialize
1205 * ShutdownContext: Pre-initialized bugcheck context
1206 * ShutdownHandler: Function to call to handle the bugcheck
1208 * - I'm not sure about ShutdownContext
1209 * - FIXME - memory leak below
1212 PLOGICAL_ADAPTER Adapter
= (PLOGICAL_ADAPTER
)MiniportHandle
;
1213 PMINIPORT_BUGCHECK_CONTEXT BugcheckContext
= Adapter
->BugcheckContext
;
1215 NDIS_DbgPrint(DEBUG_MINIPORT
, ("Called.\n"));
1220 BugcheckContext
= ExAllocatePool(NonPagedPool
, sizeof(MINIPORT_BUGCHECK_CONTEXT
));
1221 if(!BugcheckContext
)
1223 NDIS_DbgPrint(MIN_TRACE
, ("Insufficient resources.\n"));
1227 BugcheckContext
->ShutdownHandler
= ShutdownHandler
;
1228 BugcheckContext
->DriverContext
= ShutdownContext
;
1230 /* not sure if this needs to be initialized or not... oh well, it's a leak. */
1231 BugcheckContext
->CallbackRecord
= ExAllocatePool(NonPagedPool
, sizeof(KBUGCHECK_CALLBACK_RECORD
));
1233 KeRegisterBugCheckCallback(BugcheckContext
->CallbackRecord
, NdisIBugcheckCallback
,
1234 BugcheckContext
, sizeof(BugcheckContext
), "Ndis Miniport");
1240 PLOGICAL_ADAPTER Adapter
,
1241 NDIS_OID AddressOID
)
1243 * FUNCTION: Queries miniport for information
1245 * Adapter = Pointer to logical adapter
1246 * AddressOID = OID to use to query for current address
1248 * Status of operation
1252 NDIS_STATUS NdisStatus
;
1254 NDIS_DbgPrint(MAX_TRACE
, ("Called.\n"));
1256 /* Get MAC options for adapter */
1257 NdisStatus
= MiniQueryInformation(Adapter
, OID_GEN_MAC_OPTIONS
, 0, &BytesWritten
);
1259 if (NdisStatus
!= NDIS_STATUS_SUCCESS
)
1261 NDIS_DbgPrint(MIN_TRACE
, ("OID_GEN_MAC_OPTIONS failed. NdisStatus (0x%X).\n", NdisStatus
));
1265 RtlCopyMemory(&Adapter
->NdisMiniportBlock
.MacOptions
, Adapter
->QueryBuffer
, sizeof(UINT
));
1267 NDIS_DbgPrint(DEBUG_MINIPORT
, ("MacOptions (0x%X).\n", Adapter
->NdisMiniportBlock
.MacOptions
));
1269 /* Get current hardware address of adapter */
1270 NdisStatus
= MiniQueryInformation(Adapter
, AddressOID
, 0, &BytesWritten
);
1272 if (NdisStatus
!= NDIS_STATUS_SUCCESS
)
1274 NDIS_DbgPrint(MIN_TRACE
, ("Address OID (0x%X) failed. NdisStatus (0x%X).\n", AddressOID
, NdisStatus
));
1278 RtlCopyMemory(&Adapter
->Address
, Adapter
->QueryBuffer
, Adapter
->AddressLength
);
1283 PUCHAR A
= (PUCHAR
)&Adapter
->Address
.Type
.Medium802_3
;
1285 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]));
1289 /* Get maximum lookahead buffer size of adapter */
1290 NdisStatus
= MiniQueryInformation(Adapter
, OID_GEN_MAXIMUM_LOOKAHEAD
, 0, &BytesWritten
);
1292 if (NdisStatus
!= NDIS_STATUS_SUCCESS
)
1294 NDIS_DbgPrint(MIN_TRACE
, ("OID_GEN_MAXIMUM_LOOKAHEAD failed. NdisStatus (0x%X).\n", NdisStatus
));
1298 Adapter
->MaxLookaheadLength
= *((PULONG
)Adapter
->QueryBuffer
);
1300 NDIS_DbgPrint(DEBUG_MINIPORT
, ("MaxLookaheadLength (0x%X).\n", Adapter
->MaxLookaheadLength
));
1302 /* Get current lookahead buffer size of adapter */
1303 NdisStatus
= MiniQueryInformation(Adapter
, OID_GEN_CURRENT_LOOKAHEAD
, 0, &BytesWritten
);
1305 if (NdisStatus
!= NDIS_STATUS_SUCCESS
)
1307 NDIS_DbgPrint(MIN_TRACE
, ("OID_GEN_CURRENT_LOOKAHEAD failed. NdisStatus (0x%X).\n", NdisStatus
));
1311 Adapter
->CurLookaheadLength
= *((PULONG
)Adapter
->QueryBuffer
);
1313 NDIS_DbgPrint(DEBUG_MINIPORT
, ("CurLookaheadLength (0x%X).\n", Adapter
->CurLookaheadLength
));
1315 if (Adapter
->MaxLookaheadLength
!= 0)
1317 Adapter
->LookaheadLength
= Adapter
->MaxLookaheadLength
+ Adapter
->MediumHeaderSize
;
1318 Adapter
->LookaheadBuffer
= ExAllocatePool(NonPagedPool
, Adapter
->LookaheadLength
);
1320 if (!Adapter
->LookaheadBuffer
)
1321 return NDIS_STATUS_RESOURCES
;
1324 return STATUS_SUCCESS
;
1330 UNICODE_STRING
*DeviceName
,
1331 PDEVICE_OBJECT PhysicalDeviceObject
,
1332 PMINIPORT_DRIVER Miniport
1335 * FUNCTION: Start an adapter
1337 * DeviceName: Name of device to start
1338 * PhysicalDeviceObject: PDO for our adapter
1341 * - verify that all resources are properly freed on success & failure
1342 * - break up this 250-line function
1345 HANDLE RegKeyHandle
;
1346 NDIS_STATUS NdisStatus
;
1347 NDIS_STATUS OpenErrorStatus
;
1349 UINT SelectedMediumIndex
= 0;
1350 PLOGICAL_ADAPTER Adapter
= 0;
1351 NDIS_OID AddressOID
;
1352 BOOLEAN MemError
= FALSE
;
1356 Adapter
= ExAllocatePool(NonPagedPool
, sizeof(LOGICAL_ADAPTER
));
1359 NDIS_DbgPrint(MIN_TRACE
, ("Insufficient resources.\n"));
1363 /* This is very important */
1364 RtlZeroMemory(Adapter
, sizeof(LOGICAL_ADAPTER
));
1366 Adapter
->DeviceName
.Buffer
= ExAllocatePool(NonPagedPool
, DeviceName
->Length
);
1367 if(!Adapter
->DeviceName
.Buffer
)
1369 NDIS_DbgPrint(MIN_TRACE
,("Insufficient memory\n"));
1370 ExFreePool(Adapter
);
1373 Adapter
->DeviceName
.MaximumLength
= DeviceName
->Length
;
1374 RtlCopyUnicodeString(&Adapter
->DeviceName
, DeviceName
);
1376 NDIS_DbgPrint(MAX_TRACE
, ("creating device %wZ\n", DeviceName
));
1378 Status
= IoCreateDevice(Miniport
->DriverObject
, 0, &Adapter
->DeviceName
, FILE_DEVICE_PHYSICAL_NETCARD
,
1379 0, FALSE
, &Adapter
->NdisMiniportBlock
.DeviceObject
);
1380 if (!NT_SUCCESS(Status
))
1382 NDIS_DbgPrint(MIN_TRACE
, ("Could not create device object.\n"));
1383 ExFreePool(Adapter
);
1387 Status
= IoOpenDeviceRegistryKey(PhysicalDeviceObject
, PLUGPLAY_REGKEY_DRIVER
,
1388 KEY_ALL_ACCESS
, &RegKeyHandle
);
1389 if(Status
!= STATUS_SUCCESS
)
1391 NDIS_DbgPrint(MIN_TRACE
,("failed to open adapter-specific reg key\n"));
1392 ExFreePool(Adapter
);
1396 NDIS_DbgPrint(MAX_TRACE
, ("opened device reg key\n"));
1398 NDIS_DbgPrint(MAX_TRACE
, ("acquiring miniport block lock\n"));
1399 KeInitializeSpinLock(&Adapter
->NdisMiniportBlock
.Lock
);
1400 InitializeListHead(&Adapter
->ProtocolListHead
);
1401 Adapter
->RefCount
= 1;
1402 Adapter
->Miniport
= Miniport
;
1404 /* FIXME: Check return values. */
1405 Size
= sizeof(ULONG
);
1406 IoGetDeviceProperty(PhysicalDeviceObject
, DevicePropertyLegacyBusType
,
1407 Size
, &Adapter
->BusType
, &Size
);
1408 IoGetDeviceProperty(PhysicalDeviceObject
, DevicePropertyBusNumber
,
1409 Size
, &Adapter
->BusNumber
, &Size
);
1410 IoGetDeviceProperty(PhysicalDeviceObject
, DevicePropertyAddress
,
1411 Size
, &Adapter
->SlotNumber
, &Size
);
1413 /* Set handlers (some NDIS macros require these) */
1415 Adapter
->NdisMiniportBlock
.EthRxCompleteHandler
= MiniEthReceiveComplete
;
1416 Adapter
->NdisMiniportBlock
.EthRxIndicateHandler
= MiniEthReceiveIndication
;
1417 Adapter
->NdisMiniportBlock
.SendCompleteHandler
= MiniSendComplete
;
1418 Adapter
->NdisMiniportBlock
.SendResourcesHandler
= MiniSendResourcesAvailable
;
1419 Adapter
->NdisMiniportBlock
.ResetCompleteHandler
= MiniResetComplete
;
1420 Adapter
->NdisMiniportBlock
.TDCompleteHandler
= MiniTransferDataComplete
;
1421 Adapter
->NdisMiniportBlock
.PacketIndicateHandler
= MiniIndicateReceivePacket
;
1423 KeInitializeDpc(&Adapter
->MiniportDpc
, MiniportDpc
, (PVOID
)Adapter
);
1425 /* Put adapter in adapter list for this miniport */
1426 ExInterlockedInsertTailList(&Miniport
->AdapterListHead
, &Adapter
->MiniportListEntry
, &Miniport
->Lock
);
1428 /* Put adapter in global adapter list */
1429 ExInterlockedInsertTailList(&AdapterListHead
, &Adapter
->ListEntry
, &AdapterListLock
);
1431 /* Call MiniportInitialize */
1432 NDIS_DbgPrint(MID_TRACE
, ("calling MiniportInitialize\n"));
1433 NdisStatus
= (*Miniport
->Chars
.InitializeHandler
)( &OpenErrorStatus
, &SelectedMediumIndex
, &MediaArray
[0],
1434 MEDIA_ARRAY_SIZE
, Adapter
, RegKeyHandle
);
1436 ZwClose(RegKeyHandle
);
1438 if ((NdisStatus
== NDIS_STATUS_SUCCESS
) && (SelectedMediumIndex
< MEDIA_ARRAY_SIZE
))
1440 NDIS_DbgPrint(MID_TRACE
,("successful return from MiniportInitialize\n"));
1442 Adapter
->NdisMiniportBlock
.MediaType
= MediaArray
[SelectedMediumIndex
];
1444 switch (Adapter
->NdisMiniportBlock
.MediaType
)
1446 case NdisMedium802_3
:
1447 Adapter
->MediumHeaderSize
= 14; /* XXX figure out what to do about LLC */
1448 AddressOID
= OID_802_3_CURRENT_ADDRESS
;
1449 Adapter
->AddressLength
= ETH_LENGTH_OF_ADDRESS
;
1451 Adapter
->NdisMiniportBlock
.FilterDbs
.u
.EthDB
= ExAllocatePool(NonPagedPool
, sizeof(ETH_FILTER
));
1452 if (Adapter
->NdisMiniportBlock
.FilterDbs
.u
.EthDB
)
1454 RtlZeroMemory(Adapter
->NdisMiniportBlock
.FilterDbs
.u
.EthDB
, sizeof(ETH_FILTER
));
1455 Adapter
->NdisMiniportBlock
.FilterDbs
.u
.EthDB
->Miniport
= (PNDIS_MINIPORT_BLOCK
)Adapter
;
1463 /* FIXME: Support other types of media */
1464 NDIS_DbgPrint(MIN_TRACE
, ("error: unsupported media\n"));
1465 ExFreePool(Adapter
);
1467 KeReleaseSpinLock(&Adapter
->NdisMiniportBlock
.Lock
, OldIrql
);
1471 NdisStatus
= DoQueries(Adapter
, AddressOID
);
1474 if ((MemError
) || (NdisStatus
!= NDIS_STATUS_SUCCESS
) || (SelectedMediumIndex
>= MEDIA_ARRAY_SIZE
))
1476 NDIS_DbgPrint(MAX_TRACE
, ("return from MiniportInitialize: NdisStatus 0x%x, SelectedMediumIndex 0x%x\n",
1477 NdisStatus
, SelectedMediumIndex
));
1479 /* Remove adapter from adapter list for this miniport */
1480 KeAcquireSpinLock(&Miniport
->Lock
, &OldIrql
);
1481 RemoveEntryList(&Adapter
->MiniportListEntry
);
1482 KeReleaseSpinLock(&Miniport
->Lock
, OldIrql
);
1484 /* Remove adapter from global adapter list */
1485 KeAcquireSpinLock(&AdapterListLock
, &OldIrql
);
1486 RemoveEntryList(&Adapter
->ListEntry
);
1487 KeReleaseSpinLock(&AdapterListLock
, OldIrql
);
1489 if (Adapter
->LookaheadBuffer
)
1490 ExFreePool(Adapter
->LookaheadBuffer
);
1492 IoDeleteDevice(Adapter
->NdisMiniportBlock
.DeviceObject
);
1493 ExFreePool(Adapter
);
1494 NDIS_DbgPrint(MIN_TRACE
, ("MiniportInitialize() failed for an adapter.\n"));
1498 IoAttachDeviceToDeviceStack(Adapter
->NdisMiniportBlock
.DeviceObject
,
1499 PhysicalDeviceObject
);
1507 IN PDRIVER_OBJECT DriverObject
,
1508 IN PDEVICE_OBJECT PhysicalDeviceObject
1511 * FUNCTION: Start an adapter found using PnP
1513 * DriverObject = Pointer to the miniport driver object
1514 * PhysicalDeviceObject = Pointer to the PDO for our adapter
1517 static const WCHAR ClassKeyName
[] = {'C','l','a','s','s','\\'};
1518 static const WCHAR LinkageKeyName
[] = {'\\','L','i','n','k','a','g','e',0};
1519 PMINIPORT_DRIVER Miniport
;
1520 PMINIPORT_DRIVER
*MiniportPtr
;
1521 WCHAR
*LinkageKeyBuffer
;
1522 ULONG DriverKeyLength
;
1523 RTL_QUERY_REGISTRY_TABLE QueryTable
[2];
1524 UNICODE_STRING ExportName
;
1528 * Gain the access to the miniport data structure first.
1531 MiniportPtr
= IoGetDriverObjectExtension(DriverObject
, (PVOID
)TAG('D','I','M','N'));
1532 if (MiniportPtr
== NULL
)
1534 NDIS_DbgPrint(DEBUG_MINIPORT
, ("Can't get driver object extension.\n"));
1535 return STATUS_UNSUCCESSFUL
;
1537 Miniport
= *MiniportPtr
;
1540 * Get name of the Linkage registry key for our adapter. It's located under
1541 * the driver key for our driver and so we have basicly two ways to do it.
1542 * Either we can use IoOpenDriverRegistryKey or compose it using information
1543 * gathered by IoGetDeviceProperty. I choosed the second because
1544 * IoOpenDriverRegistryKey wasn't implemented at the time of writing.
1547 Status
= IoGetDeviceProperty(PhysicalDeviceObject
, DevicePropertyDriverKeyName
,
1548 0, NULL
, &DriverKeyLength
);
1549 if (Status
!= STATUS_BUFFER_TOO_SMALL
)
1551 NDIS_DbgPrint(DEBUG_MINIPORT
, ("Can't get miniport driver key length.\n"));
1555 LinkageKeyBuffer
= ExAllocatePool(PagedPool
, DriverKeyLength
+
1556 sizeof(ClassKeyName
) + sizeof(LinkageKeyName
));
1557 if (LinkageKeyBuffer
== NULL
)
1559 NDIS_DbgPrint(DEBUG_MINIPORT
, ("Can't allocate memory for driver key name.\n"));
1560 return STATUS_INSUFFICIENT_RESOURCES
;
1563 Status
= IoGetDeviceProperty(PhysicalDeviceObject
, DevicePropertyDriverKeyName
,
1564 DriverKeyLength
, LinkageKeyBuffer
+
1565 (sizeof(ClassKeyName
) / sizeof(WCHAR
)),
1567 if (!NT_SUCCESS(Status
))
1569 NDIS_DbgPrint(DEBUG_MINIPORT
, ("Can't get miniport driver key.\n"));
1570 ExFreePool(LinkageKeyBuffer
);
1574 /* Compose the linkage key name. */
1575 RtlCopyMemory(LinkageKeyBuffer
, ClassKeyName
, sizeof(ClassKeyName
));
1576 RtlCopyMemory(LinkageKeyBuffer
+ ((sizeof(ClassKeyName
) + DriverKeyLength
) /
1577 sizeof(WCHAR
)) - 1, LinkageKeyName
, sizeof(LinkageKeyName
));
1579 NDIS_DbgPrint(DEBUG_MINIPORT
, ("LinkageKey: %S.\n", LinkageKeyBuffer
));
1582 * Now open the linkage key and read the "Export" and "RootDevice" values
1583 * which contains device name and root service respectively.
1586 RtlZeroMemory(QueryTable
, sizeof(QueryTable
));
1587 RtlInitUnicodeString(&ExportName
, NULL
);
1588 QueryTable
[0].Flags
= RTL_QUERY_REGISTRY_REQUIRED
| RTL_QUERY_REGISTRY_DIRECT
;
1589 QueryTable
[0].Name
= L
"Export";
1590 QueryTable
[0].EntryContext
= &ExportName
;
1592 Status
= RtlQueryRegistryValues(RTL_REGISTRY_CONTROL
, LinkageKeyBuffer
,
1593 QueryTable
, NULL
, NULL
);
1594 if (!NT_SUCCESS(Status
))
1596 NDIS_DbgPrint(DEBUG_MINIPORT
, ("Can't get miniport device name. (%x)\n", Status
));
1597 ExFreePool(LinkageKeyBuffer
);
1600 ExFreePool(LinkageKeyBuffer
);
1602 NdisIStartAdapter(&ExportName
, PhysicalDeviceObject
, Miniport
);
1603 RtlFreeUnicodeString(&ExportName
);
1605 return STATUS_SUCCESS
;
1614 NdisMRegisterMiniport(
1615 IN NDIS_HANDLE NdisWrapperHandle
,
1616 IN PNDIS_MINIPORT_CHARACTERISTICS MiniportCharacteristics
,
1617 IN UINT CharacteristicsLength
)
1619 * FUNCTION: Registers a miniport's MiniportXxx entry points with the NDIS library
1621 * NdisWrapperHandle = Pointer to handle returned by NdisMInitializeWrapper
1622 * MiniportCharacteristics = Pointer to a buffer with miniport characteristics
1623 * CharacteristicsLength = Number of bytes in characteristics buffer
1625 * Status of operation
1629 PMINIPORT_DRIVER Miniport
= GET_MINIPORT_DRIVER(NdisWrapperHandle
);
1630 PMINIPORT_DRIVER
*MiniportPtr
;
1633 NDIS_DbgPrint(MAX_TRACE
, ("Called.\n"));
1635 switch (MiniportCharacteristics
->MajorNdisVersion
)
1638 MinSize
= sizeof(NDIS30_MINIPORT_CHARACTERISTICS_S
);
1642 MinSize
= sizeof(NDIS40_MINIPORT_CHARACTERISTICS_S
);
1646 MinSize
= sizeof(NDIS50_MINIPORT_CHARACTERISTICS_S
);
1650 NDIS_DbgPrint(DEBUG_MINIPORT
, ("Bad miniport characteristics version.\n"));
1651 return NDIS_STATUS_BAD_VERSION
;
1654 if (CharacteristicsLength
< MinSize
)
1656 NDIS_DbgPrint(DEBUG_MINIPORT
, ("Bad miniport characteristics.\n"));
1657 return NDIS_STATUS_BAD_CHARACTERISTICS
;
1660 /* Check if mandatory MiniportXxx functions are specified */
1661 if ((!MiniportCharacteristics
->HaltHandler
) ||
1662 (!MiniportCharacteristics
->InitializeHandler
)||
1663 (!MiniportCharacteristics
->QueryInformationHandler
) ||
1664 (!MiniportCharacteristics
->ResetHandler
) ||
1665 (!MiniportCharacteristics
->SetInformationHandler
))
1667 NDIS_DbgPrint(DEBUG_MINIPORT
, ("Bad miniport characteristics.\n"));
1668 return NDIS_STATUS_BAD_CHARACTERISTICS
;
1671 if (MiniportCharacteristics
->MajorNdisVersion
== 0x03)
1673 if (!MiniportCharacteristics
->u1
.SendHandler
)
1675 NDIS_DbgPrint(DEBUG_MINIPORT
, ("Bad miniport characteristics.\n"));
1676 return NDIS_STATUS_BAD_CHARACTERISTICS
;
1679 else if (MiniportCharacteristics
->MajorNdisVersion
>= 0x04)
1682 if ((!MiniportCharacteristics
->u1
.SendHandler
) &&
1683 (!MiniportCharacteristics
->SendPacketsHandler
))
1685 NDIS_DbgPrint(DEBUG_MINIPORT
, ("Bad miniport characteristics.\n"));
1686 return NDIS_STATUS_BAD_CHARACTERISTICS
;
1690 /* TODO: verify NDIS5 and NDIS5.1 */
1692 RtlCopyMemory(&Miniport
->Chars
, MiniportCharacteristics
, MinSize
);
1695 * NOTE: This is VERY unoptimal! Should we store the MINIPORT_DRIVER
1696 * struture in the driver extension or what?
1699 Status
= IoAllocateDriverObjectExtension(Miniport
->DriverObject
, (PVOID
)TAG('D','I','M','N'),
1700 sizeof(PMINIPORT_DRIVER
), (PVOID
*)&MiniportPtr
);
1701 if (!NT_SUCCESS(Status
))
1703 NDIS_DbgPrint(DEBUG_MINIPORT
, ("Can't allocate driver object extension.\n"));
1704 return NDIS_STATUS_RESOURCES
;
1707 *MiniportPtr
= Miniport
;
1708 Miniport
->DriverObject
->DriverExtension
->AddDevice
= NdisIAddDevice
;
1710 return NDIS_STATUS_SUCCESS
;
1720 IN NDIS_HANDLE MiniportAdapterHandle
,
1721 IN NDIS_STATUS Status
,
1722 IN BOOLEAN AddressingReset
)
1724 MiniResetComplete(MiniportAdapterHandle
, Status
, AddressingReset
);
1734 IN NDIS_HANDLE MiniportAdapterHandle
,
1735 IN PNDIS_PACKET Packet
,
1736 IN NDIS_STATUS Status
)
1738 * FUNCTION: Forwards a message to the initiating protocol saying
1739 * that a packet was handled
1741 * NdisAdapterHandle = Handle input to MiniportInitialize
1742 * Packet = Pointer to NDIS packet that was sent
1743 * Status = Status of send operation
1746 MiniSendComplete(MiniportAdapterHandle
, Packet
, Status
);
1755 NdisMSendResourcesAvailable(
1756 IN NDIS_HANDLE MiniportAdapterHandle
)
1758 MiniSendResourcesAvailable(MiniportAdapterHandle
);
1767 NdisMTransferDataComplete(
1768 IN NDIS_HANDLE MiniportAdapterHandle
,
1769 IN PNDIS_PACKET Packet
,
1770 IN NDIS_STATUS Status
,
1771 IN UINT BytesTransferred
)
1773 MiniTransferDataComplete(MiniportAdapterHandle
, Packet
, Status
, BytesTransferred
);
1782 NdisMSetInformationComplete(
1783 IN NDIS_HANDLE MiniportAdapterHandle
,
1784 IN NDIS_STATUS Status
)
1786 PLOGICAL_ADAPTER Adapter
= GET_LOGICAL_ADAPTER(MiniportAdapterHandle
);
1787 PADAPTER_BINDING AdapterBinding
= (PADAPTER_BINDING
)Adapter
->MiniportAdapterBinding
;
1789 NDIS_DbgPrint(MAX_TRACE
, ("Called.\n"));
1791 (*AdapterBinding
->ProtocolBinding
->Chars
.RequestCompleteHandler
)(
1792 AdapterBinding
->NdisOpenBlock
.ProtocolBindingContext
,
1793 Adapter
->NdisMiniportBlock
.MediaRequest
,
1804 IN NDIS_HANDLE MiniportAdapterHandle
,
1805 IN NDIS_HANDLE MiniportAdapterContext
,
1806 IN BOOLEAN BusMaster
,
1807 IN NDIS_INTERFACE_TYPE AdapterType
)
1809 * FUNCTION: Informs the NDIS library of significant features of the caller's NIC
1811 * MiniportAdapterHandle = Handle input to MiniportInitialize
1812 * MiniportAdapterContext = Pointer to context information
1813 * BusMaster = Specifies TRUE if the caller's NIC is a busmaster DMA device
1814 * AdapterType = Specifies the I/O bus interface of the caller's NIC
1817 PLOGICAL_ADAPTER Adapter
= GET_LOGICAL_ADAPTER(MiniportAdapterHandle
);
1819 NDIS_DbgPrint(MAX_TRACE
, ("Called.\n"));
1821 Adapter
->NdisMiniportBlock
.MiniportAdapterContext
= MiniportAdapterContext
;
1824 Adapter
->NdisMiniportBlock
.Flags
|= NDIS_ATTRIBUTE_BUS_MASTER
;
1826 Adapter
->NdisMiniportBlock
.AdapterType
= AdapterType
;
1827 Adapter
->AttributesSet
= TRUE
;
1836 NdisMSetAttributesEx(
1837 IN NDIS_HANDLE MiniportAdapterHandle
,
1838 IN NDIS_HANDLE MiniportAdapterContext
,
1839 IN UINT CheckForHangTimeInSeconds OPTIONAL
,
1840 IN ULONG AttributeFlags
,
1841 IN NDIS_INTERFACE_TYPE AdapterType
)
1843 * FUNCTION: Informs the NDIS library of significant features of the caller's NIC
1845 * MiniportAdapterHandle = Handle input to MiniportInitialize
1846 * MiniportAdapterContext = Pointer to context information
1847 * CheckForHangTimeInSeconds = Specifies interval in seconds at which
1848 * MiniportCheckForHang should be called
1849 * AttributeFlags = Bitmask that indicates specific attributes
1850 * AdapterType = Specifies the I/O bus interface of the caller's NIC
1853 /* TODO: Take CheckForHandTimeInSeconds into account! */
1855 PLOGICAL_ADAPTER Adapter
= GET_LOGICAL_ADAPTER(MiniportAdapterHandle
);
1857 NDIS_DbgPrint(MAX_TRACE
, ("Called.\n"));
1859 Adapter
->NdisMiniportBlock
.MiniportAdapterContext
= MiniportAdapterContext
;
1860 Adapter
->NdisMiniportBlock
.Flags
= AttributeFlags
;
1861 Adapter
->NdisMiniportBlock
.AdapterType
= AdapterType
;
1862 Adapter
->AttributesSet
= TRUE
;
1863 if (AttributeFlags
& NDIS_ATTRIBUTE_INTERMEDIATE_DRIVER
)
1864 NDIS_DbgPrint(MAX_TRACE
, ("Intermediate drivers not supported yet.\n"));
1874 IN ULONG MicrosecondsToSleep
)
1876 * FUNCTION: delay the thread's execution for MicrosecondsToSleep
1878 * MicrosecondsToSleep: duh...
1880 * - Because this is a blocking call, current IRQL must be < DISPATCH_LEVEL
1884 LARGE_INTEGER DueTime
;
1888 DueTime
.QuadPart
= (-1) * 10 * MicrosecondsToSleep
;
1890 KeInitializeTimer(&Timer
);
1891 KeSetTimer(&Timer
, DueTime
, 0);
1892 KeWaitForSingleObject(&Timer
, Executive
, KernelMode
, FALSE
, 0);
1901 NdisMSynchronizeWithInterrupt(
1902 IN PNDIS_MINIPORT_INTERRUPT Interrupt
,
1903 IN PVOID SynchronizeFunction
,
1904 IN PVOID SynchronizeContext
)
1906 return(KeSynchronizeExecution((PKINTERRUPT
)Interrupt
,
1907 (PKSYNCHRONIZE_ROUTINE
)SynchronizeFunction
,
1908 SynchronizeContext
));
1918 IN NDIS_HANDLE LogHandle
,
1920 IN UINT LogBufferSize
)
1924 return NDIS_STATUS_FAILURE
;
1933 NdisTerminateWrapper(
1934 IN NDIS_HANDLE NdisWrapperHandle
,
1935 IN PVOID SystemSpecific
)
1937 * FUNCTION: Releases resources allocated by a call to NdisInitializeWrapper
1939 * NdisWrapperHandle = Handle returned by NdisInitializeWrapper (MINIPORT_DRIVER)
1940 * SystemSpecific = Always NULL
1943 PMINIPORT_DRIVER Miniport
= GET_MINIPORT_DRIVER(NdisWrapperHandle
);
1945 NDIS_DbgPrint(MAX_TRACE
, ("Called.\n"));
1947 ExFreePool(Miniport
->RegistryPath
->Buffer
);
1948 ExFreePool(Miniport
->RegistryPath
);
1949 ExFreePool(Miniport
);