2 * COPYRIGHT: See COPYING in the top level directory
3 * PROJECT: ReactOS NDIS library
4 * FILE: ndis/miniport.c
5 * PURPOSE: Routines used by NDIS miniport drivers
6 * PROGRAMMERS: Casper S. Hornstrup (chorns@users.sourceforge.net)
7 * Vizzini (vizzini@plasmic.com)
9 * CSH 01/08-2000 Created
10 * 20 Aug 2003 vizzini - DMA support
11 * 3 Oct 2003 vizzini - SendPackets support
21 #undef NdisMSendComplete
25 IN NDIS_HANDLE MiniportAdapterHandle
,
26 IN PNDIS_PACKET Packet
,
27 IN NDIS_STATUS Status
);
29 /* Root of the scm database */
30 #define SERVICES_ROOT L"\\Registry\\Machine\\System\\CurrentControlSet\\Services\\"
33 * Define to 1 to get a debugger breakpoint at the end of NdisInitializeWrapper
34 * for each new miniport starting up
36 #define BREAK_ON_MINIPORT_INIT 0
39 * This has to be big enough to hold the results of querying the Route value
40 * from the Linkage key. Please re-code me to determine this dynamically.
42 #define ROUTE_DATA_SIZE 256
44 /* Number of media we know */
45 #define MEDIA_ARRAY_SIZE 15
47 static NDIS_MEDIUM MediaArray
[MEDIA_ARRAY_SIZE
] =
56 NdisMediumArcnet878_2
,
58 NdisMediumWirelessWan
,
66 /* global list and lock of Miniports NDIS has registered */
67 LIST_ENTRY MiniportListHead
;
68 KSPIN_LOCK MiniportListLock
;
70 /* global list and lock of adapters NDIS has registered */
71 LIST_ENTRY AdapterListHead
;
72 KSPIN_LOCK AdapterListLock
;
81 if ((DebugTraceLevel
& DEBUG_PACKET
) > 0) {
82 Length
= CopyPacketToBuffer(
88 DbgPrint("*** PACKET START ***");
90 for (i
= 0; i
< Length
; i
++) {
92 DbgPrint("\n%04X ", i
);
93 DbgPrint("%02X ", Buffer
[i
]);
96 DbgPrint("*** PACKET STOP ***\n");
104 UINT HeaderBufferSize
,
105 PVOID LookaheadBuffer
,
106 UINT LookaheadBufferSize
)
109 if ((DebugTraceLevel
& DEBUG_PACKET
) > 0) {
113 DbgPrint("*** RECEIVE PACKET START ***\n");
116 for (i
= 0; i
< HeaderBufferSize
; i
++) {
118 DbgPrint("\n%04X ", i
);
119 DbgPrint("%02X ", *p
++);
122 DbgPrint("\nFRAME:");
125 Length
= (LookaheadBufferSize
< 64)? LookaheadBufferSize
: 64;
126 for (i
= 0; i
< Length
; i
++) {
128 DbgPrint("\n%04X ", i
);
129 DbgPrint("%02X ", *p
++);
132 DbgPrint("\n*** RECEIVE PACKET STOP ***\n");
140 PLOGICAL_ADAPTER Adapter
,
141 NDIS_HANDLE MacReceiveContext
,
143 UINT HeaderBufferSize
,
144 PVOID LookaheadBuffer
,
145 UINT LookaheadBufferSize
,
148 * FUNCTION: Indicate received data to bound protocols
150 * Adapter = Pointer to logical adapter
151 * MacReceiveContext = MAC receive context handle
152 * HeaderBuffer = Pointer to header buffer
153 * HeaderBufferSize = Size of header buffer
154 * LookaheadBuffer = Pointer to lookahead buffer
155 * LookaheadBufferSize = Size of lookahead buffer
156 * PacketSize = Total size of received packet
160 PLIST_ENTRY CurrentEntry
;
161 PADAPTER_BINDING AdapterBinding
;
163 NDIS_DbgPrint(DEBUG_MINIPORT
, ("Called. Adapter (0x%X) HeaderBuffer (0x%X) "
164 "HeaderBufferSize (0x%X) LookaheadBuffer (0x%X) LookaheadBufferSize (0x%X).\n",
165 Adapter
, HeaderBuffer
, HeaderBufferSize
, LookaheadBuffer
, LookaheadBufferSize
));
167 MiniDisplayPacket2(HeaderBuffer
, HeaderBufferSize
, LookaheadBuffer
, LookaheadBufferSize
);
170 * XXX Think about this. This is probably broken. Spinlocks are
171 * taken out for now until i comprehend the Right Way to do this.
173 * This used to acquire the MiniportBlock spinlock and hold it until
174 * just before the call to ReceiveHandler. It would then release and
175 * subsequently re-acquire the lock.
177 * I don't see how this does any good, as it would seem he's just
178 * trying to protect the packet list. If somebody else dequeues
179 * a packet, we are in fact in bad shape, but we don't want to
180 * necessarily call the receive handler at elevated irql either.
182 * therefore: We *are* going to call the receive handler at high irql
183 * (due to holding the lock) for now, and eventually we have to
184 * figure out another way to protect this packet list.
186 * UPDATE: this is busted; this results in a recursive lock acquisition.
188 //NDIS_DbgPrint(MAX_TRACE, ("acquiring miniport block lock\n"));
189 //KeAcquireSpinLock(&Adapter->NdisMiniportBlock.Lock, &OldIrql);
191 CurrentEntry
= Adapter
->ProtocolListHead
.Flink
;
192 NDIS_DbgPrint(DEBUG_MINIPORT
, ("CurrentEntry = %x\n", CurrentEntry
));
194 if (CurrentEntry
== &Adapter
->ProtocolListHead
)
196 NDIS_DbgPrint(DEBUG_MINIPORT
, ("WARNING: No upper protocol layer.\n"));
199 while (CurrentEntry
!= &Adapter
->ProtocolListHead
)
201 AdapterBinding
= CONTAINING_RECORD(CurrentEntry
, ADAPTER_BINDING
, AdapterListEntry
);
202 NDIS_DbgPrint(DEBUG_MINIPORT
, ("AdapterBinding = %x\n", AdapterBinding
));
205 /* KeReleaseSpinLock(&Adapter->NdisMiniportBlock.Lock, OldIrql); */
210 NDIS_DbgPrint(MIN_TRACE
, ("AdapterBinding was null\n"));
214 if(!AdapterBinding
->ProtocolBinding
)
216 NDIS_DbgPrint(MIN_TRACE
, ("AdapterBinding->ProtocolBinding was null\n"));
220 if(!AdapterBinding
->ProtocolBinding
->Chars
.ReceiveHandler
)
222 NDIS_DbgPrint(MIN_TRACE
, ("AdapterBinding->ProtocolBinding->Chars.ReceiveHandler was null\n"));
229 ("XXX (%x) %x %x %x %x %x %x %x XXX\n",
230 *AdapterBinding
->ProtocolBinding
->Chars
.ReceiveHandler
,
231 AdapterBinding
->NdisOpenBlock
.ProtocolBindingContext
,
239 /* call the receive handler */
240 (*AdapterBinding
->ProtocolBinding
->Chars
.ReceiveHandler
)(
241 AdapterBinding
->NdisOpenBlock
.ProtocolBindingContext
,
250 /* KeAcquireSpinLock(&Adapter->NdisMiniportBlock.Lock, &OldIrql); */
252 CurrentEntry
= CurrentEntry
->Flink
;
255 //KeReleaseSpinLock(&Adapter->NdisMiniportBlock.Lock, OldIrql);
257 NDIS_DbgPrint(MAX_TRACE
, ("Leaving.\n"));
262 MiniIndicateReceivePacket(
263 IN NDIS_HANDLE Miniport
,
264 IN PPNDIS_PACKET PacketArray
,
265 IN UINT NumberOfPackets
)
267 * FUNCTION: receives miniport packet array indications
269 * Miniport: Miniport handle for the adapter
270 * PacketArray: pointer to a list of packet pointers to indicate
271 * NumberOfPackets: number of packets to indicate
273 * - This currently is a big temporary hack. In the future this should
274 * call ProtocolReceivePacket() on each bound protocol if it exists.
275 * For now it just mimics NdisMEthIndicateReceive.
280 for(i
= 0; i
< NumberOfPackets
; i
++)
282 PCHAR PacketBuffer
= 0;
283 UINT PacketLength
= 0;
284 PNDIS_BUFFER NdisBuffer
= 0;
286 #define PACKET_TAG (('k' << 24) + ('P' << 16) + ('D' << 8) + 'N')
288 NdisAllocateMemoryWithTag((PVOID
)&PacketBuffer
, 1518, PACKET_TAG
);
291 NDIS_DbgPrint(MIN_TRACE
, ("insufficient resources\n"));
295 NdisQueryPacket(PacketArray
[i
], NULL
, NULL
, &NdisBuffer
, NULL
);
299 PNDIS_BUFFER CurrentBuffer
;
303 NdisQueryBuffer(NdisBuffer
, &BufferVa
, &BufferLen
);
304 memcpy(PacketBuffer
+ PacketLength
, BufferVa
, BufferLen
);
305 PacketLength
+= BufferLen
;
307 CurrentBuffer
= NdisBuffer
;
308 NdisGetNextBuffer(CurrentBuffer
, &NdisBuffer
);
311 NDIS_DbgPrint(MID_TRACE
, ("indicating a %d-byte packet\n", PacketLength
));
313 MiniIndicateData(Miniport
, NULL
, PacketBuffer
, 14, PacketBuffer
+14, PacketLength
-14, PacketLength
-14);
315 NdisFreeMemory(PacketBuffer
, 0, 0);
322 IN NDIS_HANDLE MiniportAdapterHandle
,
323 IN NDIS_STATUS Status
,
324 IN BOOLEAN AddressingReset
)
333 IN PADAPTER_BINDING AdapterBinding
,
334 IN PNDIS_REQUEST Request
,
335 IN NDIS_STATUS Status
)
337 NDIS_DbgPrint(DEBUG_MINIPORT
, ("Called.\n"));
339 if( AdapterBinding
->ProtocolBinding
->Chars
.RequestCompleteHandler
) {
340 (*AdapterBinding
->ProtocolBinding
->Chars
.RequestCompleteHandler
)(
341 AdapterBinding
->NdisOpenBlock
.ProtocolBindingContext
,
349 IN NDIS_HANDLE MiniportAdapterHandle
,
350 IN PNDIS_PACKET Packet
,
351 IN NDIS_STATUS Status
)
353 * FUNCTION: Forwards a message to the initiating protocol saying
354 * that a packet was handled
356 * NdisAdapterHandle = Handle input to MiniportInitialize
357 * Packet = Pointer to NDIS packet that was sent
358 * Status = Status of send operation
361 PADAPTER_BINDING AdapterBinding
;
363 NDIS_DbgPrint(DEBUG_MINIPORT
, ("Called.\n"));
365 AdapterBinding
= (PADAPTER_BINDING
)Packet
->Reserved
[0];
367 (*AdapterBinding
->ProtocolBinding
->Chars
.SendCompleteHandler
)(
368 AdapterBinding
->NdisOpenBlock
.ProtocolBindingContext
,
375 MiniSendResourcesAvailable(
376 IN NDIS_HANDLE MiniportAdapterHandle
)
383 MiniTransferDataComplete(
384 IN NDIS_HANDLE MiniportAdapterHandle
,
385 IN PNDIS_PACKET Packet
,
386 IN NDIS_STATUS Status
,
387 IN UINT BytesTransferred
)
389 PADAPTER_BINDING AdapterBinding
;
391 NDIS_DbgPrint(DEBUG_MINIPORT
, ("Called.\n"));
393 AdapterBinding
= (PADAPTER_BINDING
)Packet
->Reserved
[0];
395 (*AdapterBinding
->ProtocolBinding
->Chars
.SendCompleteHandler
)(
396 AdapterBinding
->NdisOpenBlock
.ProtocolBindingContext
,
403 MiniAdapterHasAddress(
404 PLOGICAL_ADAPTER Adapter
,
407 * FUNCTION: Determines whether a packet has the same destination address as an adapter
409 * Adapter = Pointer to logical adapter object
410 * Packet = Pointer to NDIS packet
412 * TRUE if the destination address is that of the adapter, FALSE if not
418 PNDIS_BUFFER NdisBuffer
;
421 NDIS_DbgPrint(DEBUG_MINIPORT
, ("Called.\n"));
426 NDIS_DbgPrint(MID_TRACE
, ("Adapter object was null\n"));
432 NDIS_DbgPrint(MID_TRACE
, ("Packet was null\n"));
437 NdisQueryPacket(Packet
, NULL
, NULL
, &NdisBuffer
, NULL
);
441 NDIS_DbgPrint(MID_TRACE
, ("Packet contains no buffers.\n"));
445 NdisQueryBuffer(NdisBuffer
, (PVOID
)&Start2
, &BufferLength
);
447 /* FIXME: Should handle fragmented packets */
449 switch (Adapter
->NdisMiniportBlock
.MediaType
)
451 case NdisMedium802_3
:
452 Length
= ETH_LENGTH_OF_ADDRESS
;
453 /* Destination address is the first field */
457 NDIS_DbgPrint(MIN_TRACE
, ("Adapter has unsupported media type (0x%X).\n", Adapter
->NdisMiniportBlock
.MediaType
));
461 if (BufferLength
< Length
)
463 NDIS_DbgPrint(MID_TRACE
, ("Buffer is too small.\n"));
467 Start1
= (PUCHAR
)&Adapter
->Address
;
468 NDIS_DbgPrint(MAX_TRACE
, ("packet address: %x:%x:%x:%x:%x:%x adapter address: %x:%x:%x:%x:%x:%x\n",
469 *((char *)Start1
), *(((char *)Start1
)+1), *(((char *)Start1
)+2), *(((char *)Start1
)+3), *(((char *)Start1
)+4), *(((char *)Start1
)+5),
470 *((char *)Start2
), *(((char *)Start2
)+1), *(((char *)Start2
)+2), *(((char *)Start2
)+3), *(((char *)Start2
)+4), *(((char *)Start2
)+5))
473 return (RtlCompareMemory((PVOID
)Start1
, (PVOID
)Start2
, Length
) == Length
);
479 PNDIS_STRING AdapterName
)
481 * FUNCTION: Finds an adapter object by name
483 * AdapterName = Pointer to name of adapter
485 * Pointer to logical adapter object, or NULL if none was found.
486 * If found, the adapter is referenced for the caller. The caller
487 * is responsible for dereferencing after use
491 PLIST_ENTRY CurrentEntry
;
492 PLOGICAL_ADAPTER Adapter
= 0;
496 NDIS_DbgPrint(DEBUG_MINIPORT
, ("Called.\n"));
498 if(IsListEmpty(&AdapterListHead
))
500 NDIS_DbgPrint(DEBUG_MINIPORT
, ("No registered miniports for protocol to bind to\n"));
504 KeAcquireSpinLock(&AdapterListLock
, &OldIrql
);
508 CurrentEntry
= AdapterListHead
.Flink
;
510 while (CurrentEntry
!= &AdapterListHead
)
512 Adapter
= CONTAINING_RECORD(CurrentEntry
, LOGICAL_ADAPTER
, ListEntry
);
516 NDIS_DbgPrint(DEBUG_MINIPORT
, ("AdapterName = %wZ\n", AdapterName
));
517 NDIS_DbgPrint(DEBUG_MINIPORT
, ("DeviceName = %wZ\n", &Adapter
->NdisMiniportBlock
.MiniportName
));
519 if (RtlCompareUnicodeString(AdapterName
, &Adapter
->NdisMiniportBlock
.MiniportName
, TRUE
) == 0)
521 ReferenceObject(Adapter
);
526 CurrentEntry
= CurrentEntry
->Flink
;
530 KeReleaseSpinLock(&AdapterListLock
, OldIrql
);
534 NDIS_DbgPrint(DEBUG_MINIPORT
, ("Leaving. Adapter found at 0x%x\n", Adapter
));
538 NDIS_DbgPrint(DEBUG_MINIPORT
, ("Leaving (adapter not found).\n"));
546 MiniQueryInformation(
547 PLOGICAL_ADAPTER Adapter
,
552 * FUNCTION: Queries a logical adapter for properties
554 * Adapter = Pointer to the logical adapter object to query
555 * Oid = Specifies the Object ID to query for
556 * Size = If non-zero overrides the length in the adapter object
557 * BytesWritten = Address of buffer to place number of bytes written
559 * If the specified buffer is too small, a new buffer is allocated,
560 * and the query is attempted again
562 * Status of operation
564 * Is there any way to use the buffer provided by the protocol?
567 NDIS_STATUS NdisStatus
;
570 NDIS_DbgPrint(DEBUG_MINIPORT
, ("Called.\n"));
572 if (Adapter
->QueryBufferLength
== 0)
574 /* XXX is 32 the right number? */
575 Adapter
->QueryBuffer
= ExAllocatePool(NonPagedPool
, (Size
== 0)? 32 : Size
);
577 if (!Adapter
->QueryBuffer
)
579 NDIS_DbgPrint(MIN_TRACE
, ("Insufficient resources.\n"));
580 return NDIS_STATUS_RESOURCES
;
584 Adapter
->QueryBufferLength
= (Size
== 0)? 32 : Size
;
587 /* this is the third time i've seen this conditional */
588 BytesNeeded
= (Size
== 0)? Adapter
->QueryBufferLength
: Size
;
590 /* call the miniport's queryinfo handler */
591 NdisStatus
= (*Adapter
->Miniport
->Chars
.QueryInformationHandler
)(
592 Adapter
->NdisMiniportBlock
.MiniportAdapterContext
,
594 Adapter
->QueryBuffer
,
599 /* XXX is status_pending part of success macro? */
600 if ((NT_SUCCESS(NdisStatus
)) || (NdisStatus
== NDIS_STATUS_PENDING
))
602 NDIS_DbgPrint(DEBUG_MINIPORT
, ("Miniport returned status (0x%X).\n", NdisStatus
));
606 if (NdisStatus
== NDIS_STATUS_INVALID_LENGTH
)
608 ExFreePool(Adapter
->QueryBuffer
);
610 Adapter
->QueryBufferLength
+= BytesNeeded
;
611 Adapter
->QueryBuffer
= ExAllocatePool(NonPagedPool
, Adapter
->QueryBufferLength
);
613 if (!Adapter
->QueryBuffer
)
615 NDIS_DbgPrint(MIN_TRACE
, ("Insufficient resources.\n"));
616 return NDIS_STATUS_RESOURCES
;
619 NdisStatus
= (*Adapter
->Miniport
->Chars
.QueryInformationHandler
)(
620 Adapter
->NdisMiniportBlock
.MiniportAdapterContext
,
622 Adapter
->QueryBuffer
,
623 Adapter
->QueryBufferLength
,
635 PADAPTER_BINDING AdapterBinding
,
636 NDIS_WORK_ITEM_TYPE WorkItemType
,
637 PVOID WorkItemContext
)
639 * FUNCTION: Queues a work item for execution at a later time
641 * Adapter = Pointer to the logical adapter object to queue work item on
642 * WorkItemType = Type of work item to queue
643 * WorkItemContext = Pointer to context information for work item
645 * Adapter lock must be held when called
647 * Status of operation
650 PINTERNAL_NDIS_MINIPORT_WORK_ITEM Item
;
651 PLOGICAL_ADAPTER Adapter
= AdapterBinding
->Adapter
;
653 NDIS_DbgPrint(MAX_TRACE
, ("Called.\n"));
656 ASSERT(KeGetCurrentIrql() >= DISPATCH_LEVEL
);
659 if (Adapter
->WorkQueueLevel
< NDIS_MINIPORT_WORK_QUEUE_SIZE
- 1)
661 Item
= &Adapter
->WorkQueue
[Adapter
->WorkQueueLevel
];
662 Adapter
->WorkQueueLevel
++;
667 Item
= ExAllocatePool(NonPagedPool
, sizeof(INTERNAL_NDIS_MINIPORT_WORK_ITEM
));
670 NDIS_DbgPrint(MIN_TRACE
, ("Insufficient resources.\n"));
671 return NDIS_STATUS_RESOURCES
;
675 Item
->AdapterBinding
= AdapterBinding
;
676 Item
->RealWorkItem
.WorkItemType
= WorkItemType
;
677 Item
->RealWorkItem
.WorkItemContext
= WorkItemContext
;
679 /* safe due to adapter lock held */
680 Item
->Link
.Next
= NULL
;
681 if (!Adapter
->WorkQueueHead
)
683 Adapter
->WorkQueueHead
= Item
;
684 Adapter
->WorkQueueTail
= Item
;
688 Adapter
->WorkQueueTail
->Link
.Next
= (PSINGLE_LIST_ENTRY
)Item
;
689 Adapter
->WorkQueueTail
= Item
;
692 KeInsertQueueDpc(&Adapter
->MiniportDpc
, NULL
, NULL
);
694 return NDIS_STATUS_SUCCESS
;
701 PLOGICAL_ADAPTER Adapter
,
702 PADAPTER_BINDING
*AdapterBinding
,
703 NDIS_WORK_ITEM_TYPE
*WorkItemType
,
704 PVOID
*WorkItemContext
)
706 * FUNCTION: Dequeues a work item from the work queue of a logical adapter
708 * Adapter = Pointer to the logical adapter object to dequeue work item from
709 * AdapterBinding = Address of buffer for adapter binding for this request
710 * WorkItemType = Address of buffer for work item type
711 * WorkItemContext = Address of buffer for pointer to context information
713 * Adapter lock must be held when called
715 * Status of operation
718 PINTERNAL_NDIS_MINIPORT_WORK_ITEM Item
;
720 NDIS_DbgPrint(MAX_TRACE
, ("Called.\n"));
722 Item
= Adapter
->WorkQueueHead
;
726 /* safe due to adapter lock held */
727 Adapter
->WorkQueueHead
= (PINTERNAL_NDIS_MINIPORT_WORK_ITEM
)Item
->Link
.Next
;
729 if (Item
== Adapter
->WorkQueueTail
)
730 Adapter
->WorkQueueTail
= NULL
;
732 *AdapterBinding
= Item
->AdapterBinding
;
733 *WorkItemType
= Item
->RealWorkItem
.WorkItemType
;
734 *WorkItemContext
= Item
->RealWorkItem
.WorkItemContext
;
738 return NDIS_STATUS_SUCCESS
;
741 return NDIS_STATUS_FAILURE
;
747 PADAPTER_BINDING AdapterBinding
,
748 PNDIS_REQUEST NdisRequest
)
750 * FUNCTION: Sends a request to a miniport
752 * AdapterBinding = Pointer to binding used in the request
753 * NdisRequest = Pointer to NDIS request structure describing request
755 * Status of operation
758 PLOGICAL_ADAPTER Adapter
= AdapterBinding
->Adapter
;
760 NDIS_DbgPrint(DEBUG_MINIPORT
, ("Called.\n"));
762 Adapter
->NdisMiniportBlock
.MediaRequest
= NdisRequest
;
764 switch (NdisRequest
->RequestType
)
766 case NdisRequestQueryInformation
:
767 return (*Adapter
->Miniport
->Chars
.QueryInformationHandler
)(
768 Adapter
->NdisMiniportBlock
.MiniportAdapterContext
,
769 NdisRequest
->DATA
.QUERY_INFORMATION
.Oid
,
770 NdisRequest
->DATA
.QUERY_INFORMATION
.InformationBuffer
,
771 NdisRequest
->DATA
.QUERY_INFORMATION
.InformationBufferLength
,
772 (PULONG
)&NdisRequest
->DATA
.QUERY_INFORMATION
.BytesWritten
,
773 (PULONG
)&NdisRequest
->DATA
.QUERY_INFORMATION
.BytesNeeded
);
776 case NdisRequestSetInformation
:
777 return (*Adapter
->Miniport
->Chars
.SetInformationHandler
)(
778 Adapter
->NdisMiniportBlock
.MiniportAdapterContext
,
779 NdisRequest
->DATA
.SET_INFORMATION
.Oid
,
780 NdisRequest
->DATA
.SET_INFORMATION
.InformationBuffer
,
781 NdisRequest
->DATA
.SET_INFORMATION
.InformationBufferLength
,
782 (PULONG
)&NdisRequest
->DATA
.SET_INFORMATION
.BytesRead
,
783 (PULONG
)&NdisRequest
->DATA
.SET_INFORMATION
.BytesNeeded
);
787 return NDIS_STATUS_FAILURE
;
795 #undef NdisMQueryInformationComplete
798 NdisMQueryInformationComplete(
799 IN NDIS_HANDLE MiniportAdapterHandle
,
800 IN NDIS_STATUS Status
)
802 PNDIS_MINIPORT_BLOCK MiniportBlock
=
803 (PNDIS_MINIPORT_BLOCK
)MiniportAdapterHandle
;
804 ASSERT(MiniportBlock
);
805 if( MiniportBlock
->QueryCompleteHandler
)
806 (MiniportBlock
->QueryCompleteHandler
)(MiniportAdapterHandle
, Status
);
810 VOID NTAPI
MiniportDpc(
812 IN PVOID DeferredContext
,
813 IN PVOID SystemArgument1
,
814 IN PVOID SystemArgument2
)
816 * FUNCTION: Deferred routine to handle serialization
818 * Dpc = Pointer to DPC object
819 * DeferredContext = Pointer to context information (LOGICAL_ADAPTER)
820 * SystemArgument1 = Unused
821 * SystemArgument2 = Unused
824 NDIS_STATUS NdisStatus
;
825 PVOID WorkItemContext
;
826 NDIS_WORK_ITEM_TYPE WorkItemType
;
827 PADAPTER_BINDING AdapterBinding
;
828 PLOGICAL_ADAPTER Adapter
= GET_LOGICAL_ADAPTER(DeferredContext
);
830 NDIS_DbgPrint(DEBUG_MINIPORT
, ("Called.\n"));
834 (Adapter
, &AdapterBinding
, &WorkItemType
, &WorkItemContext
);
836 if (NdisStatus
== NDIS_STATUS_SUCCESS
)
838 switch (WorkItemType
)
840 case NdisWorkItemSend
:
842 * called by ProSend when protocols want to send packets to the miniport
845 MiniDisplayPacket((PNDIS_PACKET
)WorkItemContext
);
847 if(Adapter
->Miniport
->Chars
.SendPacketsHandler
)
849 NDIS_DbgPrint(MAX_TRACE
, ("Calling miniport's SendPackets handler\n"));
852 * XXX assumes single-packet - prolly OK since we'll call something
853 * different on multi-packet sends
855 (*Adapter
->Miniport
->Chars
.SendPacketsHandler
)(
856 Adapter
->NdisMiniportBlock
.MiniportAdapterContext
, (PPNDIS_PACKET
)&WorkItemContext
, 1);
858 NDIS_GET_PACKET_STATUS((PNDIS_PACKET
)WorkItemContext
);
860 NDIS_DbgPrint(MAX_TRACE
, ("back from miniport's SendPackets handler\n"));
864 NDIS_DbgPrint(MAX_TRACE
, ("Calling miniport's Send handler\n"));
866 NdisStatus
= (*Adapter
->Miniport
->Chars
.SendHandler
)(
867 Adapter
->NdisMiniportBlock
.MiniportAdapterContext
, (PNDIS_PACKET
)WorkItemContext
, 0);
869 NDIS_DbgPrint(MAX_TRACE
, ("back from miniport's Send handler\n"));
871 if( NdisStatus
!= NDIS_STATUS_PENDING
) {
873 ( Adapter
, (PNDIS_PACKET
)WorkItemContext
, NdisStatus
);
874 Adapter
->MiniportBusy
= FALSE
;
878 case NdisWorkItemSendLoopback
:
880 * called by ProSend when protocols want to send loopback packets
882 /* XXX atm ProIndicatePacket sends a packet up via the loopback adapter only */
883 NdisStatus
= ProIndicatePacket(Adapter
, (PNDIS_PACKET
)WorkItemContext
);
884 MiniSendComplete((NDIS_HANDLE
)Adapter
, (PNDIS_PACKET
)WorkItemContext
, NdisStatus
);
887 case NdisWorkItemReturnPackets
:
890 case NdisWorkItemResetRequested
:
893 case NdisWorkItemResetInProgress
:
896 case NdisWorkItemHalt
:
899 case NdisWorkItemMiniportCallback
:
902 case NdisWorkItemRequest
:
903 NdisStatus
= MiniDoRequest(AdapterBinding
, (PNDIS_REQUEST
)WorkItemContext
);
905 if (NdisStatus
== NDIS_STATUS_PENDING
)
908 switch (((PNDIS_REQUEST
)WorkItemContext
)->RequestType
)
910 case NdisRequestQueryInformation
:
911 NdisMQueryInformationComplete((NDIS_HANDLE
)Adapter
, NdisStatus
);
912 MiniRequestComplete( AdapterBinding
, (PNDIS_REQUEST
)WorkItemContext
, NdisStatus
);
915 case NdisRequestSetInformation
:
916 NdisMSetInformationComplete((NDIS_HANDLE
)Adapter
, NdisStatus
);
917 MiniRequestComplete( AdapterBinding
, (PNDIS_REQUEST
)WorkItemContext
, NdisStatus
);
921 NDIS_DbgPrint(MIN_TRACE
, ("Unknown NDIS request type.\n"));
927 NDIS_DbgPrint(MIN_TRACE
, ("Unknown NDIS work item type (%d).\n", WorkItemType
));
940 IN NDIS_HANDLE LogHandle
)
952 IN NDIS_HANDLE MiniportAdapterHandle
,
954 OUT PNDIS_HANDLE LogHandle
)
958 return NDIS_STATUS_FAILURE
;
967 NdisMDeregisterAdapterShutdownHandler(
968 IN NDIS_HANDLE MiniportHandle
)
970 * FUNCTION: de-registers a shutdown handler
971 * ARGUMENTS: MiniportHandle: Handle passed into MiniportInitialize
974 PLOGICAL_ADAPTER Adapter
= (PLOGICAL_ADAPTER
)MiniportHandle
;
976 NDIS_DbgPrint(DEBUG_MINIPORT
, ("Called.\n"));
978 if(Adapter
->BugcheckContext
->ShutdownHandler
)
979 KeDeregisterBugCheckCallback(Adapter
->BugcheckContext
->CallbackRecord
);
989 IN NDIS_HANDLE LogHandle
)
997 #undef NdisMIndicateStatus
1000 NdisMIndicateStatus(
1001 IN NDIS_HANDLE MiniportAdapterHandle
,
1002 IN NDIS_STATUS GeneralStatus
,
1003 IN PVOID StatusBuffer
,
1004 IN UINT StatusBufferSize
)
1012 #undef NdisMIndicateStatusComplete
1015 NdisMIndicateStatusComplete(
1016 IN NDIS_HANDLE MiniportAdapterHandle
)
1027 NdisInitializeWrapper(
1028 OUT PNDIS_HANDLE NdisWrapperHandle
,
1029 IN PVOID SystemSpecific1
,
1030 IN PVOID SystemSpecific2
,
1031 IN PVOID SystemSpecific3
)
1033 * FUNCTION: Notifies the NDIS library that a new miniport is initializing
1035 * NdisWrapperHandle = Address of buffer to place NDIS wrapper handle
1036 * SystemSpecific1 = Pointer to the driver's driver object
1037 * SystemSpecific2 = Pointer to the driver's registry path
1038 * SystemSpecific3 = Always NULL
1040 * - SystemSpecific2 goes invalid so we copy it
1043 PMINIPORT_DRIVER Miniport
;
1044 PUNICODE_STRING RegistryPath
;
1045 WCHAR
*RegistryBuffer
;
1047 NDIS_DbgPrint(MAX_TRACE
, ("Called.\n"));
1049 ASSERT(NdisWrapperHandle
);
1051 *NdisWrapperHandle
= NULL
;
1053 #if BREAK_ON_MINIPORT_INIT
1054 __asm__ ("int $3\n");
1057 Miniport
= ExAllocatePool(NonPagedPool
, sizeof(MINIPORT_DRIVER
));
1061 NDIS_DbgPrint(MIN_TRACE
, ("Insufficient resources.\n"));
1065 RtlZeroMemory(Miniport
, sizeof(MINIPORT_DRIVER
));
1067 KeInitializeSpinLock(&Miniport
->Lock
);
1069 Miniport
->RefCount
= 1;
1071 Miniport
->DriverObject
= (PDRIVER_OBJECT
)SystemSpecific1
;
1073 /* set the miniport's driver registry path */
1074 RegistryPath
= ExAllocatePool(PagedPool
, sizeof(UNICODE_STRING
));
1077 NDIS_DbgPrint(MIN_TRACE
, ("Insufficient resources.\n"));
1081 RegistryPath
->Length
= ((PUNICODE_STRING
)SystemSpecific2
)->Length
;
1082 RegistryPath
->MaximumLength
= RegistryPath
->Length
+ sizeof(WCHAR
); /* room for 0-term */
1084 RegistryBuffer
= ExAllocatePool(PagedPool
, RegistryPath
->MaximumLength
);
1087 NDIS_DbgPrint(MIN_TRACE
, ("Insufficient resources.\n"));
1091 RtlCopyMemory(RegistryBuffer
, ((PUNICODE_STRING
)SystemSpecific2
)->Buffer
, RegistryPath
->Length
);
1092 RegistryBuffer
[RegistryPath
->Length
/sizeof(WCHAR
)] = 0;
1094 RegistryPath
->Buffer
= RegistryBuffer
;
1095 Miniport
->RegistryPath
= RegistryPath
;
1097 InitializeListHead(&Miniport
->AdapterListHead
);
1099 /* Put miniport in global miniport list */
1100 ExInterlockedInsertTailList(&MiniportListHead
, &Miniport
->ListEntry
, &MiniportListLock
);
1102 *NdisWrapperHandle
= Miniport
;
1106 VOID NTAPI
NdisIBugcheckCallback(
1110 * FUNCTION: Internal callback for handling bugchecks - calls adapter's shutdown handler
1112 * Buffer: Pointer to a bugcheck callback context
1116 PMINIPORT_BUGCHECK_CONTEXT Context
= (PMINIPORT_BUGCHECK_CONTEXT
)Buffer
;
1117 ADAPTER_SHUTDOWN_HANDLER sh
= (ADAPTER_SHUTDOWN_HANDLER
)Context
->ShutdownHandler
;
1119 NDIS_DbgPrint(DEBUG_MINIPORT
, ("Called.\n"));
1122 sh(Context
->DriverContext
);
1131 NdisMRegisterAdapterShutdownHandler(
1132 IN NDIS_HANDLE MiniportHandle
,
1133 IN PVOID ShutdownContext
,
1134 IN ADAPTER_SHUTDOWN_HANDLER ShutdownHandler
)
1136 * FUNCTION: Register a shutdown handler for an adapter
1138 * MiniportHandle: Handle originally passed into MiniportInitialize
1139 * ShutdownContext: Pre-initialized bugcheck context
1140 * ShutdownHandler: Function to call to handle the bugcheck
1142 * - I'm not sure about ShutdownContext
1143 * - FIXME - memory leak below
1146 PLOGICAL_ADAPTER Adapter
= (PLOGICAL_ADAPTER
)MiniportHandle
;
1147 PMINIPORT_BUGCHECK_CONTEXT BugcheckContext
= Adapter
->BugcheckContext
;
1149 NDIS_DbgPrint(DEBUG_MINIPORT
, ("Called.\n"));
1154 BugcheckContext
= ExAllocatePool(NonPagedPool
, sizeof(MINIPORT_BUGCHECK_CONTEXT
));
1155 if(!BugcheckContext
)
1157 NDIS_DbgPrint(MIN_TRACE
, ("Insufficient resources.\n"));
1161 BugcheckContext
->ShutdownHandler
= ShutdownHandler
;
1162 BugcheckContext
->DriverContext
= ShutdownContext
;
1164 /* not sure if this needs to be initialized or not... oh well, it's a leak. */
1165 BugcheckContext
->CallbackRecord
= ExAllocatePool(NonPagedPool
, sizeof(KBUGCHECK_CALLBACK_RECORD
));
1167 KeRegisterBugCheckCallback(BugcheckContext
->CallbackRecord
, NdisIBugcheckCallback
,
1168 BugcheckContext
, sizeof(BugcheckContext
), (PUCHAR
)"Ndis Miniport");
1174 PLOGICAL_ADAPTER Adapter
,
1175 NDIS_OID AddressOID
)
1177 * FUNCTION: Queries miniport for information
1179 * Adapter = Pointer to logical adapter
1180 * AddressOID = OID to use to query for current address
1182 * Status of operation
1186 NDIS_STATUS NdisStatus
;
1188 NDIS_DbgPrint(MAX_TRACE
, ("Called.\n"));
1190 /* Get MAC options for adapter */
1191 NdisStatus
= MiniQueryInformation(Adapter
, OID_GEN_MAC_OPTIONS
, 0, &BytesWritten
);
1193 if (NdisStatus
!= NDIS_STATUS_SUCCESS
)
1195 NDIS_DbgPrint(MIN_TRACE
, ("OID_GEN_MAC_OPTIONS failed. NdisStatus (0x%X).\n", NdisStatus
));
1199 RtlCopyMemory(&Adapter
->NdisMiniportBlock
.MacOptions
, Adapter
->QueryBuffer
, sizeof(UINT
));
1201 NDIS_DbgPrint(DEBUG_MINIPORT
, ("MacOptions (0x%X).\n", Adapter
->NdisMiniportBlock
.MacOptions
));
1203 /* Get current hardware address of adapter */
1204 NdisStatus
= MiniQueryInformation(Adapter
, AddressOID
, 0, &BytesWritten
);
1206 if (NdisStatus
!= NDIS_STATUS_SUCCESS
)
1208 NDIS_DbgPrint(MIN_TRACE
, ("Address OID (0x%X) failed. NdisStatus (0x%X).\n", AddressOID
, NdisStatus
));
1212 RtlCopyMemory(&Adapter
->Address
, Adapter
->QueryBuffer
, Adapter
->AddressLength
);
1217 PUCHAR A
= (PUCHAR
)&Adapter
->Address
.Type
.Medium802_3
;
1219 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]));
1223 /* Get maximum lookahead buffer size of adapter */
1224 NdisStatus
= MiniQueryInformation(Adapter
, OID_GEN_MAXIMUM_LOOKAHEAD
, 0, &BytesWritten
);
1226 if (NdisStatus
!= NDIS_STATUS_SUCCESS
)
1228 NDIS_DbgPrint(MIN_TRACE
, ("OID_GEN_MAXIMUM_LOOKAHEAD failed. NdisStatus (0x%X).\n", NdisStatus
));
1232 Adapter
->NdisMiniportBlock
.MaximumLookahead
= *((PULONG
)Adapter
->QueryBuffer
);
1234 NDIS_DbgPrint(DEBUG_MINIPORT
, ("MaxLookaheadLength (0x%X).\n", Adapter
->NdisMiniportBlock
.MaximumLookahead
));
1236 /* Get current lookahead buffer size of adapter */
1237 NdisStatus
= MiniQueryInformation(Adapter
, OID_GEN_CURRENT_LOOKAHEAD
, 0, &BytesWritten
);
1239 if (NdisStatus
!= NDIS_STATUS_SUCCESS
)
1241 NDIS_DbgPrint(MIN_TRACE
, ("OID_GEN_CURRENT_LOOKAHEAD failed. NdisStatus (0x%X).\n", NdisStatus
));
1245 Adapter
->NdisMiniportBlock
.CurrentLookahead
= *((PULONG
)Adapter
->QueryBuffer
);
1247 NDIS_DbgPrint(DEBUG_MINIPORT
, ("CurLookaheadLength (0x%X).\n", Adapter
->NdisMiniportBlock
.CurrentLookahead
));
1249 if (Adapter
->NdisMiniportBlock
.MaximumLookahead
!= 0)
1251 Adapter
->LookaheadLength
= Adapter
->NdisMiniportBlock
.MaximumLookahead
+ Adapter
->MediumHeaderSize
;
1252 Adapter
->LookaheadBuffer
= ExAllocatePool(NonPagedPool
, Adapter
->LookaheadLength
);
1254 if (!Adapter
->LookaheadBuffer
)
1255 return NDIS_STATUS_RESOURCES
;
1258 return STATUS_SUCCESS
;
1264 NdisIForwardIrpAndWaitCompletionRoutine(
1269 PKEVENT Event
= Context
;
1271 if (Irp
->PendingReturned
)
1272 KeSetEvent(Event
, IO_NO_INCREMENT
, FALSE
);
1274 return STATUS_MORE_PROCESSING_REQUIRED
;
1280 NdisIForwardIrpAndWait(PLOGICAL_ADAPTER Adapter
, PIRP Irp
)
1285 KeInitializeEvent(&Event
, NotificationEvent
, FALSE
);
1286 IoCopyCurrentIrpStackLocationToNext(Irp
);
1287 IoSetCompletionRoutine(Irp
, NdisIForwardIrpAndWaitCompletionRoutine
, &Event
,
1289 Status
= IoCallDriver(Adapter
->NdisMiniportBlock
.NextDeviceObject
, Irp
);
1290 if (Status
== STATUS_PENDING
)
1292 KeWaitForSingleObject(&Event
, Executive
, KernelMode
, FALSE
, NULL
);
1293 Status
= Irp
->IoStatus
.Status
;
1301 NdisIPnPStartDevice(
1302 IN PDEVICE_OBJECT DeviceObject
,
1305 * FUNCTION: Handle the PnP start device event
1307 * DeviceObejct = Functional Device Object
1308 * Irp = IRP_MN_START_DEVICE I/O request packet
1310 * Status of operation
1313 PIO_STACK_LOCATION Stack
= IoGetCurrentIrpStackLocation(Irp
);
1314 PLOGICAL_ADAPTER Adapter
= (PLOGICAL_ADAPTER
)DeviceObject
->DeviceExtension
;
1315 NDIS_WRAPPER_CONTEXT WrapperContext
;
1316 NDIS_STATUS NdisStatus
;
1317 NDIS_STATUS OpenErrorStatus
;
1319 UINT SelectedMediumIndex
= 0;
1320 NDIS_OID AddressOID
;
1321 BOOLEAN Success
= FALSE
;
1322 ULONG ResourceCount
;
1323 ULONG ResourceListSize
;
1324 UNICODE_STRING ParamName
;
1325 PNDIS_CONFIGURATION_PARAMETER ConfigParam
;
1326 NDIS_HANDLE ConfigHandle
;
1328 /* FIXME - KIRQL OldIrql; */
1331 * Prepare wrapper context used by HW and configuration routines.
1334 Status
= IoOpenDeviceRegistryKey(
1335 Adapter
->NdisMiniportBlock
.PhysicalDeviceObject
, PLUGPLAY_REGKEY_DRIVER
,
1336 KEY_ALL_ACCESS
, &WrapperContext
.RegistryHandle
);
1337 if (!NT_SUCCESS(Status
))
1339 NDIS_DbgPrint(MIN_TRACE
,("failed to open adapter-specific reg key\n"));
1343 NDIS_DbgPrint(MAX_TRACE
, ("opened device reg key\n"));
1345 WrapperContext
.DeviceObject
= Adapter
->NdisMiniportBlock
.DeviceObject
;
1348 * Store the adapter resources used by HW routines such as
1349 * NdisMQueryAdapterResources.
1352 if (Stack
->Parameters
.StartDevice
.AllocatedResources
!= NULL
&&
1353 Stack
->Parameters
.StartDevice
.AllocatedResourcesTranslated
!= NULL
)
1355 ResourceCount
= Stack
->Parameters
.StartDevice
.AllocatedResources
->List
[0].
1356 PartialResourceList
.Count
;
1358 FIELD_OFFSET(CM_RESOURCE_LIST
, List
[0].PartialResourceList
.
1359 PartialDescriptors
[ResourceCount
]);
1361 Adapter
->NdisMiniportBlock
.AllocatedResources
=
1362 ExAllocatePool(PagedPool
, ResourceListSize
);
1363 if (Adapter
->NdisMiniportBlock
.AllocatedResources
== NULL
)
1365 return STATUS_INSUFFICIENT_RESOURCES
;
1368 Adapter
->NdisMiniportBlock
.AllocatedResourcesTranslated
=
1369 ExAllocatePool(PagedPool
, ResourceListSize
);
1370 if (Adapter
->NdisMiniportBlock
.AllocatedResourcesTranslated
== NULL
)
1372 ExFreePool(Adapter
->NdisMiniportBlock
.AllocatedResources
);
1373 Adapter
->NdisMiniportBlock
.AllocatedResources
= NULL
;
1374 return STATUS_INSUFFICIENT_RESOURCES
;
1377 RtlCopyMemory(Adapter
->NdisMiniportBlock
.AllocatedResources
,
1378 Stack
->Parameters
.StartDevice
.AllocatedResources
,
1381 RtlCopyMemory(Adapter
->NdisMiniportBlock
.AllocatedResourcesTranslated
,
1382 Stack
->Parameters
.StartDevice
.AllocatedResourcesTranslated
,
1387 * Store the Bus Type, Bus Number and Slot information. It's used by
1388 * the hardware routines then.
1391 NdisOpenConfiguration(&NdisStatus
, &ConfigHandle
, (NDIS_HANDLE
)&WrapperContext
);
1393 Size
= sizeof(ULONG
);
1394 Status
= IoGetDeviceProperty(Adapter
->NdisMiniportBlock
.PhysicalDeviceObject
,
1395 DevicePropertyLegacyBusType
, Size
,
1396 &Adapter
->NdisMiniportBlock
.BusType
, &Size
);
1397 if (!NT_SUCCESS(Status
) || Adapter
->NdisMiniportBlock
.BusType
== (NDIS_INTERFACE_TYPE
)-1)
1399 NdisInitUnicodeString(&ParamName
, L
"BusType");
1400 NdisReadConfiguration(&NdisStatus
, &ConfigParam
, ConfigHandle
,
1401 &ParamName
, NdisParameterInteger
);
1402 if (NdisStatus
== NDIS_STATUS_SUCCESS
)
1403 Adapter
->NdisMiniportBlock
.BusType
= ConfigParam
->ParameterData
.IntegerData
;
1405 Adapter
->NdisMiniportBlock
.BusType
= Isa
;
1408 Status
= IoGetDeviceProperty(Adapter
->NdisMiniportBlock
.PhysicalDeviceObject
,
1409 DevicePropertyBusNumber
, Size
,
1410 &Adapter
->NdisMiniportBlock
.BusNumber
, &Size
);
1411 if (!NT_SUCCESS(Status
) || Adapter
->NdisMiniportBlock
.BusNumber
== (NDIS_INTERFACE_TYPE
)-1)
1413 NdisInitUnicodeString(&ParamName
, L
"BusNumber");
1414 NdisReadConfiguration(&NdisStatus
, &ConfigParam
, ConfigHandle
,
1415 &ParamName
, NdisParameterInteger
);
1416 if (NdisStatus
== NDIS_STATUS_SUCCESS
)
1417 Adapter
->NdisMiniportBlock
.BusNumber
= ConfigParam
->ParameterData
.IntegerData
;
1419 Adapter
->NdisMiniportBlock
.BusNumber
= 0;
1421 WrapperContext
.BusNumber
= Adapter
->NdisMiniportBlock
.BusNumber
;
1423 Status
= IoGetDeviceProperty(Adapter
->NdisMiniportBlock
.PhysicalDeviceObject
,
1424 DevicePropertyAddress
, Size
,
1425 &Adapter
->NdisMiniportBlock
.SlotNumber
, &Size
);
1426 if (!NT_SUCCESS(Status
) || Adapter
->NdisMiniportBlock
.SlotNumber
== (NDIS_INTERFACE_TYPE
)-1)
1428 NdisInitUnicodeString(&ParamName
, L
"SlotNumber");
1429 NdisReadConfiguration(&NdisStatus
, &ConfigParam
, ConfigHandle
,
1430 &ParamName
, NdisParameterInteger
);
1431 if (NdisStatus
== NDIS_STATUS_SUCCESS
)
1432 Adapter
->NdisMiniportBlock
.SlotNumber
= ConfigParam
->ParameterData
.IntegerData
;
1434 Adapter
->NdisMiniportBlock
.SlotNumber
= 0;
1437 NdisCloseConfiguration(ConfigHandle
);
1440 * Call MiniportInitialize.
1443 NDIS_DbgPrint(MID_TRACE
, ("calling MiniportInitialize\n"));
1444 NdisStatus
= (*Adapter
->Miniport
->Chars
.InitializeHandler
)(
1445 &OpenErrorStatus
, &SelectedMediumIndex
, &MediaArray
[0],
1446 MEDIA_ARRAY_SIZE
, Adapter
, (NDIS_HANDLE
)&WrapperContext
);
1448 ZwClose(WrapperContext
.RegistryHandle
);
1450 if (NdisStatus
!= NDIS_STATUS_SUCCESS
||
1451 SelectedMediumIndex
>= MEDIA_ARRAY_SIZE
)
1453 NDIS_DbgPrint(MIN_TRACE
, ("MiniportInitialize() failed for an adapter.\n"));
1454 return (NTSTATUS
)NdisStatus
;
1457 /* Set handlers (some NDIS macros require these) */
1459 Adapter
->NdisMiniportBlock
.EthRxCompleteHandler
= EthFilterDprIndicateReceiveComplete
;
1460 Adapter
->NdisMiniportBlock
.EthRxIndicateHandler
= EthFilterDprIndicateReceive
;
1461 Adapter
->NdisMiniportBlock
.SendCompleteHandler
= MiniSendComplete
;
1462 Adapter
->NdisMiniportBlock
.SendResourcesHandler
= MiniSendResourcesAvailable
;
1463 Adapter
->NdisMiniportBlock
.ResetCompleteHandler
= MiniResetComplete
;
1464 Adapter
->NdisMiniportBlock
.TDCompleteHandler
= MiniTransferDataComplete
;
1465 Adapter
->NdisMiniportBlock
.PacketIndicateHandler
= MiniIndicateReceivePacket
;
1467 Adapter
->NdisMiniportBlock
.MediaType
= MediaArray
[SelectedMediumIndex
];
1469 switch (Adapter
->NdisMiniportBlock
.MediaType
)
1471 case NdisMedium802_3
:
1472 Adapter
->MediumHeaderSize
= 14; /* XXX figure out what to do about LLC */
1473 AddressOID
= OID_802_3_CURRENT_ADDRESS
;
1474 Adapter
->AddressLength
= ETH_LENGTH_OF_ADDRESS
;
1475 NdisStatus
= DoQueries(Adapter
, AddressOID
);
1476 if (NdisStatus
== NDIS_STATUS_SUCCESS
)
1478 Success
= EthCreateFilter(32, /* FIXME: Query this from miniport. */
1479 Adapter
->Address
.Type
.Medium802_3
,
1480 &Adapter
->NdisMiniportBlock
.EthDB
);
1482 ((PETHI_FILTER
)Adapter
->NdisMiniportBlock
.EthDB
)->Miniport
= (PNDIS_MINIPORT_BLOCK
)Adapter
;
1484 NdisStatus
= NDIS_STATUS_RESOURCES
;
1489 /* FIXME: Support other types of media */
1490 NDIS_DbgPrint(MIN_TRACE
, ("error: unsupported media\n"));
1492 /* FIXME - KeReleaseSpinLock(&Adapter->NdisMiniportBlock.Lock, OldIrql); */
1493 return STATUS_UNSUCCESSFUL
;
1496 if (!Success
|| NdisStatus
!= NDIS_STATUS_SUCCESS
)
1498 NDIS_DbgPrint(MAX_TRACE
, ("couldn't create filter (%x)\n", NdisStatus
));
1499 if (Adapter
->LookaheadBuffer
)
1501 ExFreePool(Adapter
->LookaheadBuffer
);
1502 Adapter
->LookaheadBuffer
= NULL
;
1504 return (NTSTATUS
)NdisStatus
;
1507 Adapter
->NdisMiniportBlock
.OldPnPDeviceState
= Adapter
->NdisMiniportBlock
.PnPDeviceState
;
1508 Adapter
->NdisMiniportBlock
.PnPDeviceState
= NdisPnPDeviceStarted
;
1510 /* Put adapter in adapter list for this miniport */
1511 ExInterlockedInsertTailList(&Adapter
->Miniport
->AdapterListHead
, &Adapter
->MiniportListEntry
, &Adapter
->Miniport
->Lock
);
1513 /* Put adapter in global adapter list */
1514 ExInterlockedInsertTailList(&AdapterListHead
, &Adapter
->ListEntry
, &AdapterListLock
);
1516 return STATUS_SUCCESS
;
1523 IN PDEVICE_OBJECT DeviceObject
,
1526 * FUNCTION: Handle the PnP stop device event
1528 * DeviceObejct = Functional Device Object
1529 * Irp = IRP_MN_STOP_DEVICE I/O request packet
1531 * Status of operation
1534 PLOGICAL_ADAPTER Adapter
= (PLOGICAL_ADAPTER
)DeviceObject
->DeviceExtension
;
1537 /* Remove adapter from adapter list for this miniport */
1538 KeAcquireSpinLock(&Adapter
->Miniport
->Lock
, &OldIrql
);
1539 RemoveEntryList(&Adapter
->MiniportListEntry
);
1540 KeReleaseSpinLock(&Adapter
->Miniport
->Lock
, OldIrql
);
1542 /* Remove adapter from global adapter list */
1543 KeAcquireSpinLock(&AdapterListLock
, &OldIrql
);
1544 RemoveEntryList(&Adapter
->ListEntry
);
1545 KeReleaseSpinLock(&AdapterListLock
, OldIrql
);
1547 (*Adapter
->Miniport
->Chars
.HaltHandler
)(Adapter
);
1549 if (Adapter
->LookaheadBuffer
)
1551 ExFreePool(Adapter
->LookaheadBuffer
);
1552 Adapter
->LookaheadBuffer
= NULL
;
1554 if (Adapter
->NdisMiniportBlock
.AllocatedResources
)
1556 ExFreePool(Adapter
->NdisMiniportBlock
.AllocatedResources
);
1557 Adapter
->NdisMiniportBlock
.AllocatedResources
= NULL
;
1559 if (Adapter
->NdisMiniportBlock
.AllocatedResourcesTranslated
)
1561 ExFreePool(Adapter
->NdisMiniportBlock
.AllocatedResourcesTranslated
);
1562 Adapter
->NdisMiniportBlock
.AllocatedResourcesTranslated
= NULL
;
1565 Adapter
->NdisMiniportBlock
.OldPnPDeviceState
= Adapter
->NdisMiniportBlock
.PnPDeviceState
;
1566 Adapter
->NdisMiniportBlock
.PnPDeviceState
= NdisPnPDeviceStopped
;
1568 return STATUS_SUCCESS
;
1575 IN PDEVICE_OBJECT DeviceObject
,
1578 PIO_STACK_LOCATION Stack
= IoGetCurrentIrpStackLocation(Irp
);
1579 PLOGICAL_ADAPTER Adapter
= (PLOGICAL_ADAPTER
)DeviceObject
->DeviceExtension
;
1582 switch (Stack
->MinorFunction
)
1584 case IRP_MN_START_DEVICE
:
1585 Status
= NdisIForwardIrpAndWait(Adapter
, Irp
);
1586 if (NT_SUCCESS(Status
) && NT_SUCCESS(Irp
->IoStatus
.Status
))
1588 Status
= NdisIPnPStartDevice(DeviceObject
, Irp
);
1590 Irp
->IoStatus
.Status
= Status
;
1591 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
1594 case IRP_MN_STOP_DEVICE
:
1596 Status
= STATUS_UNSUCCESSFUL
;
1598 Status
= NdisIForwardIrpAndWait(Adapter
, Irp
);
1599 if (NT_SUCCESS(Status
) && NT_SUCCESS(Irp
->IoStatus
.Status
))
1601 Status
= NdisIPnPStopDevice(DeviceObject
, Irp
);
1603 Irp
->IoStatus
.Status
= Status
;
1604 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
1608 IoSkipCurrentIrpStackLocation(Irp
);
1609 Status
= IoCallDriver(Adapter
->NdisMiniportBlock
.NextDeviceObject
, Irp
);
1620 IN PDRIVER_OBJECT DriverObject
,
1621 IN PDEVICE_OBJECT PhysicalDeviceObject
)
1623 * FUNCTION: Create a device for an adapter found using PnP
1625 * DriverObject = Pointer to the miniport driver object
1626 * PhysicalDeviceObject = Pointer to the PDO for our adapter
1629 static const WCHAR ClassKeyName
[] = {'C','l','a','s','s','\\'};
1630 static const WCHAR LinkageKeyName
[] = {'\\','L','i','n','k','a','g','e',0};
1631 PMINIPORT_DRIVER Miniport
;
1632 PMINIPORT_DRIVER
*MiniportPtr
;
1633 WCHAR
*LinkageKeyBuffer
;
1634 ULONG DriverKeyLength
;
1635 RTL_QUERY_REGISTRY_TABLE QueryTable
[2];
1636 UNICODE_STRING ExportName
;
1637 PDEVICE_OBJECT DeviceObject
;
1638 PLOGICAL_ADAPTER Adapter
;
1642 * Gain the access to the miniport data structure first.
1645 MiniportPtr
= IoGetDriverObjectExtension(DriverObject
, (PVOID
)TAG('D','I','M','N'));
1646 if (MiniportPtr
== NULL
)
1648 NDIS_DbgPrint(DEBUG_MINIPORT
, ("Can't get driver object extension.\n"));
1649 return STATUS_UNSUCCESSFUL
;
1651 Miniport
= *MiniportPtr
;
1654 * Get name of the Linkage registry key for our adapter. It's located under
1655 * the driver key for our driver and so we have basicly two ways to do it.
1656 * Either we can use IoOpenDriverRegistryKey or compose it using information
1657 * gathered by IoGetDeviceProperty. I choosed the second because
1658 * IoOpenDriverRegistryKey wasn't implemented at the time of writing.
1661 Status
= IoGetDeviceProperty(PhysicalDeviceObject
, DevicePropertyDriverKeyName
,
1662 0, NULL
, &DriverKeyLength
);
1663 if (Status
!= STATUS_BUFFER_TOO_SMALL
)
1665 NDIS_DbgPrint(DEBUG_MINIPORT
, ("Can't get miniport driver key length.\n"));
1669 LinkageKeyBuffer
= ExAllocatePool(PagedPool
, DriverKeyLength
+
1670 sizeof(ClassKeyName
) + sizeof(LinkageKeyName
));
1671 if (LinkageKeyBuffer
== NULL
)
1673 NDIS_DbgPrint(DEBUG_MINIPORT
, ("Can't allocate memory for driver key name.\n"));
1674 return STATUS_INSUFFICIENT_RESOURCES
;
1677 Status
= IoGetDeviceProperty(PhysicalDeviceObject
, DevicePropertyDriverKeyName
,
1678 DriverKeyLength
, LinkageKeyBuffer
+
1679 (sizeof(ClassKeyName
) / sizeof(WCHAR
)),
1681 if (!NT_SUCCESS(Status
))
1683 NDIS_DbgPrint(DEBUG_MINIPORT
, ("Can't get miniport driver key.\n"));
1684 ExFreePool(LinkageKeyBuffer
);
1688 /* Compose the linkage key name. */
1689 RtlCopyMemory(LinkageKeyBuffer
, ClassKeyName
, sizeof(ClassKeyName
));
1690 RtlCopyMemory(LinkageKeyBuffer
+ ((sizeof(ClassKeyName
) + DriverKeyLength
) /
1691 sizeof(WCHAR
)) - 1, LinkageKeyName
, sizeof(LinkageKeyName
));
1693 NDIS_DbgPrint(DEBUG_MINIPORT
, ("LinkageKey: %S.\n", LinkageKeyBuffer
));
1696 * Now open the linkage key and read the "Export" and "RootDevice" values
1697 * which contains device name and root service respectively.
1700 RtlZeroMemory(QueryTable
, sizeof(QueryTable
));
1701 RtlInitUnicodeString(&ExportName
, NULL
);
1702 QueryTable
[0].Flags
= RTL_QUERY_REGISTRY_REQUIRED
| RTL_QUERY_REGISTRY_DIRECT
;
1703 QueryTable
[0].Name
= L
"Export";
1704 QueryTable
[0].EntryContext
= &ExportName
;
1706 Status
= RtlQueryRegistryValues(RTL_REGISTRY_CONTROL
, LinkageKeyBuffer
,
1707 QueryTable
, NULL
, NULL
);
1708 ExFreePool(LinkageKeyBuffer
);
1709 if (!NT_SUCCESS(Status
))
1711 NDIS_DbgPrint(DEBUG_MINIPORT
, ("Can't get miniport device name. (%x)\n", Status
));
1716 * Create the device object.
1719 NDIS_DbgPrint(MAX_TRACE
, ("creating device %wZ\n", &ExportName
));
1721 Status
= IoCreateDevice(Miniport
->DriverObject
, sizeof(LOGICAL_ADAPTER
),
1722 &ExportName
, FILE_DEVICE_PHYSICAL_NETCARD
,
1723 0, FALSE
, &DeviceObject
);
1724 if (!NT_SUCCESS(Status
))
1726 NDIS_DbgPrint(MIN_TRACE
, ("Could not create device object.\n"));
1727 RtlFreeUnicodeString(&ExportName
);
1732 * Initialize the adapter structure.
1735 Adapter
= (PLOGICAL_ADAPTER
)DeviceObject
->DeviceExtension
;
1736 KeInitializeSpinLock(&Adapter
->NdisMiniportBlock
.Lock
);
1737 InitializeListHead(&Adapter
->ProtocolListHead
);
1738 Adapter
->RefCount
= 1;
1739 Adapter
->Miniport
= Miniport
;
1741 Adapter
->NdisMiniportBlock
.MiniportName
= ExportName
;
1743 Adapter
->NdisMiniportBlock
.DeviceObject
= DeviceObject
;
1744 Adapter
->NdisMiniportBlock
.PhysicalDeviceObject
= PhysicalDeviceObject
;
1745 Adapter
->NdisMiniportBlock
.NextDeviceObject
=
1746 IoAttachDeviceToDeviceStack(Adapter
->NdisMiniportBlock
.DeviceObject
,
1747 PhysicalDeviceObject
);
1749 Adapter
->NdisMiniportBlock
.OldPnPDeviceState
= 0;
1750 Adapter
->NdisMiniportBlock
.PnPDeviceState
= NdisPnPDeviceAdded
;
1752 KeInitializeDpc(&Adapter
->MiniportDpc
, MiniportDpc
, (PVOID
)Adapter
);
1754 DeviceObject
->Flags
&= ~DO_DEVICE_INITIALIZING
;
1756 return STATUS_SUCCESS
;
1765 NdisMRegisterMiniport(
1766 IN NDIS_HANDLE NdisWrapperHandle
,
1767 IN PNDIS_MINIPORT_CHARACTERISTICS MiniportCharacteristics
,
1768 IN UINT CharacteristicsLength
)
1770 * FUNCTION: Registers a miniport's MiniportXxx entry points with the NDIS library
1772 * NdisWrapperHandle = Pointer to handle returned by NdisMInitializeWrapper
1773 * MiniportCharacteristics = Pointer to a buffer with miniport characteristics
1774 * CharacteristicsLength = Number of bytes in characteristics buffer
1776 * Status of operation
1780 PMINIPORT_DRIVER Miniport
= GET_MINIPORT_DRIVER(NdisWrapperHandle
);
1781 PMINIPORT_DRIVER
*MiniportPtr
;
1784 NDIS_DbgPrint(MAX_TRACE
, ("Called.\n"));
1786 switch (MiniportCharacteristics
->MajorNdisVersion
)
1789 MinSize
= sizeof(NDIS30_MINIPORT_CHARACTERISTICS
);
1793 MinSize
= sizeof(NDIS40_MINIPORT_CHARACTERISTICS
);
1797 MinSize
= sizeof(NDIS50_MINIPORT_CHARACTERISTICS
);
1801 NDIS_DbgPrint(DEBUG_MINIPORT
, ("Bad miniport characteristics version.\n"));
1802 return NDIS_STATUS_BAD_VERSION
;
1805 if (CharacteristicsLength
< MinSize
)
1807 NDIS_DbgPrint(DEBUG_MINIPORT
, ("Bad miniport characteristics.\n"));
1808 return NDIS_STATUS_BAD_CHARACTERISTICS
;
1811 /* Check if mandatory MiniportXxx functions are specified */
1812 if ((!MiniportCharacteristics
->HaltHandler
) ||
1813 (!MiniportCharacteristics
->InitializeHandler
)||
1814 (!MiniportCharacteristics
->QueryInformationHandler
) ||
1815 (!MiniportCharacteristics
->ResetHandler
) ||
1816 (!MiniportCharacteristics
->SetInformationHandler
))
1818 NDIS_DbgPrint(DEBUG_MINIPORT
, ("Bad miniport characteristics.\n"));
1819 return NDIS_STATUS_BAD_CHARACTERISTICS
;
1822 if (MiniportCharacteristics
->MajorNdisVersion
== 0x03)
1824 if (!MiniportCharacteristics
->SendHandler
)
1826 NDIS_DbgPrint(DEBUG_MINIPORT
, ("Bad miniport characteristics.\n"));
1827 return NDIS_STATUS_BAD_CHARACTERISTICS
;
1830 else if (MiniportCharacteristics
->MajorNdisVersion
>= 0x04)
1833 if ((!MiniportCharacteristics
->SendHandler
) &&
1834 (!MiniportCharacteristics
->SendPacketsHandler
))
1836 NDIS_DbgPrint(DEBUG_MINIPORT
, ("Bad miniport characteristics.\n"));
1837 return NDIS_STATUS_BAD_CHARACTERISTICS
;
1841 /* TODO: verify NDIS5 and NDIS5.1 */
1843 RtlCopyMemory(&Miniport
->Chars
, MiniportCharacteristics
, MinSize
);
1846 * NOTE: This is VERY unoptimal! Should we store the MINIPORT_DRIVER
1847 * struture in the driver extension or what?
1850 Status
= IoAllocateDriverObjectExtension(Miniport
->DriverObject
, (PVOID
)TAG('D','I','M','N'),
1851 sizeof(PMINIPORT_DRIVER
), (PVOID
*)&MiniportPtr
);
1852 if (!NT_SUCCESS(Status
))
1854 NDIS_DbgPrint(DEBUG_MINIPORT
, ("Can't allocate driver object extension.\n"));
1855 return NDIS_STATUS_RESOURCES
;
1858 *MiniportPtr
= Miniport
;
1860 Miniport
->DriverObject
->MajorFunction
[IRP_MJ_PNP
] = NdisIDispatchPnp
;
1861 Miniport
->DriverObject
->DriverExtension
->AddDevice
= NdisIAddDevice
;
1863 return NDIS_STATUS_SUCCESS
;
1870 #undef NdisMResetComplete
1874 IN NDIS_HANDLE MiniportAdapterHandle
,
1875 IN NDIS_STATUS Status
,
1876 IN BOOLEAN AddressingReset
)
1878 MiniResetComplete(MiniportAdapterHandle
, Status
, AddressingReset
);
1885 #undef NdisMSendComplete
1889 IN NDIS_HANDLE MiniportAdapterHandle
,
1890 IN PNDIS_PACKET Packet
,
1891 IN NDIS_STATUS Status
)
1893 * FUNCTION: Forwards a message to the initiating protocol saying
1894 * that a packet was handled
1896 * NdisAdapterHandle = Handle input to MiniportInitialize
1897 * Packet = Pointer to NDIS packet that was sent
1898 * Status = Status of send operation
1901 MiniSendComplete(MiniportAdapterHandle
, Packet
, Status
);
1908 #undef NdisMSendResourcesAvailable
1911 NdisMSendResourcesAvailable(
1912 IN NDIS_HANDLE MiniportAdapterHandle
)
1914 MiniSendResourcesAvailable(MiniportAdapterHandle
);
1921 #undef NdisMTransferDataComplete
1924 NdisMTransferDataComplete(
1925 IN NDIS_HANDLE MiniportAdapterHandle
,
1926 IN PNDIS_PACKET Packet
,
1927 IN NDIS_STATUS Status
,
1928 IN UINT BytesTransferred
)
1930 MiniTransferDataComplete(MiniportAdapterHandle
, Packet
, Status
, BytesTransferred
);
1937 #undef NdisMSetInformationComplete
1940 NdisMSetInformationComplete(
1941 IN NDIS_HANDLE MiniportAdapterHandle
,
1942 IN NDIS_STATUS Status
)
1944 (*((PNDIS_MINIPORT_BLOCK
)(MiniportAdapterHandle
))->SetCompleteHandler
)(MiniportAdapterHandle
, Status
);
1951 #undef NdisMSetAttributes
1955 IN NDIS_HANDLE MiniportAdapterHandle
,
1956 IN NDIS_HANDLE MiniportAdapterContext
,
1957 IN BOOLEAN BusMaster
,
1958 IN NDIS_INTERFACE_TYPE AdapterType
)
1960 * FUNCTION: Informs the NDIS library of significant features of the caller's NIC
1962 * MiniportAdapterHandle = Handle input to MiniportInitialize
1963 * MiniportAdapterContext = Pointer to context information
1964 * BusMaster = Specifies TRUE if the caller's NIC is a busmaster DMA device
1965 * AdapterType = Specifies the I/O bus interface of the caller's NIC
1968 NDIS_DbgPrint(MAX_TRACE
, ("Called.\n"));
1969 NdisMSetAttributesEx(MiniportAdapterHandle
, MiniportAdapterContext
, 0,
1970 BusMaster
? NDIS_ATTRIBUTE_BUS_MASTER
: 0,
1980 NdisMSetAttributesEx(
1981 IN NDIS_HANDLE MiniportAdapterHandle
,
1982 IN NDIS_HANDLE MiniportAdapterContext
,
1983 IN UINT CheckForHangTimeInSeconds OPTIONAL
,
1984 IN ULONG AttributeFlags
,
1985 IN NDIS_INTERFACE_TYPE AdapterType
)
1987 * FUNCTION: Informs the NDIS library of significant features of the caller's NIC
1989 * MiniportAdapterHandle = Handle input to MiniportInitialize
1990 * MiniportAdapterContext = Pointer to context information
1991 * CheckForHangTimeInSeconds = Specifies interval in seconds at which
1992 * MiniportCheckForHang should be called
1993 * AttributeFlags = Bitmask that indicates specific attributes
1994 * AdapterType = Specifies the I/O bus interface of the caller's NIC
1997 /* TODO: Take CheckForHandTimeInSeconds into account! */
1999 PLOGICAL_ADAPTER Adapter
= GET_LOGICAL_ADAPTER(MiniportAdapterHandle
);
2001 NDIS_DbgPrint(MAX_TRACE
, ("Called.\n"));
2003 Adapter
->NdisMiniportBlock
.MiniportAdapterContext
= MiniportAdapterContext
;
2004 Adapter
->NdisMiniportBlock
.Flags
= AttributeFlags
;
2005 Adapter
->NdisMiniportBlock
.AdapterType
= AdapterType
;
2006 Adapter
->AttributesSet
= TRUE
;
2007 if (AttributeFlags
& NDIS_ATTRIBUTE_INTERMEDIATE_DRIVER
)
2008 NDIS_DbgPrint(MAX_TRACE
, ("Intermediate drivers not supported yet.\n"));
2018 IN ULONG MicrosecondsToSleep
)
2020 * FUNCTION: delay the thread's execution for MicrosecondsToSleep
2022 * MicrosecondsToSleep: duh...
2024 * - Because this is a blocking call, current IRQL must be < DISPATCH_LEVEL
2028 LARGE_INTEGER DueTime
;
2032 DueTime
.QuadPart
= (-1) * 10 * MicrosecondsToSleep
;
2034 KeInitializeTimer(&Timer
);
2035 KeSetTimer(&Timer
, DueTime
, 0);
2036 KeWaitForSingleObject(&Timer
, Executive
, KernelMode
, FALSE
, 0);
2045 NdisMSynchronizeWithInterrupt(
2046 IN PNDIS_MINIPORT_INTERRUPT Interrupt
,
2047 IN PVOID SynchronizeFunction
,
2048 IN PVOID SynchronizeContext
)
2050 return(KeSynchronizeExecution(Interrupt
->InterruptObject
,
2051 (PKSYNCHRONIZE_ROUTINE
)SynchronizeFunction
,
2052 SynchronizeContext
));
2062 IN NDIS_HANDLE LogHandle
,
2064 IN UINT LogBufferSize
)
2068 return NDIS_STATUS_FAILURE
;
2077 NdisTerminateWrapper(
2078 IN NDIS_HANDLE NdisWrapperHandle
,
2079 IN PVOID SystemSpecific
)
2081 * FUNCTION: Releases resources allocated by a call to NdisInitializeWrapper
2083 * NdisWrapperHandle = Handle returned by NdisInitializeWrapper (MINIPORT_DRIVER)
2084 * SystemSpecific = Always NULL
2087 PMINIPORT_DRIVER Miniport
= GET_MINIPORT_DRIVER(NdisWrapperHandle
);
2089 NDIS_DbgPrint(MAX_TRACE
, ("Called.\n"));
2091 ExFreePool(Miniport
->RegistryPath
->Buffer
);
2092 ExFreePool(Miniport
->RegistryPath
);
2093 ExFreePool(Miniport
);