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
);
169 NDIS_DbgPrint(MAX_TRACE
, ("acquiring miniport block lock\n"));
170 KeAcquireSpinLock(&Adapter
->NdisMiniportBlock
.Lock
, &OldIrql
);
172 CurrentEntry
= Adapter
->ProtocolListHead
.Flink
;
173 NDIS_DbgPrint(DEBUG_MINIPORT
, ("CurrentEntry = %x\n", CurrentEntry
));
175 if (CurrentEntry
== &Adapter
->ProtocolListHead
)
177 NDIS_DbgPrint(DEBUG_MINIPORT
, ("WARNING: No upper protocol layer.\n"));
180 while (CurrentEntry
!= &Adapter
->ProtocolListHead
)
182 AdapterBinding
= CONTAINING_RECORD(CurrentEntry
, ADAPTER_BINDING
, AdapterListEntry
);
183 NDIS_DbgPrint(DEBUG_MINIPORT
, ("AdapterBinding = %x\n", AdapterBinding
));
188 NDIS_DbgPrint(MIN_TRACE
, ("AdapterBinding was null\n"));
192 if(!AdapterBinding
->ProtocolBinding
)
194 NDIS_DbgPrint(MIN_TRACE
, ("AdapterBinding->ProtocolBinding was null\n"));
198 if(!AdapterBinding
->ProtocolBinding
->Chars
.ReceiveHandler
)
200 NDIS_DbgPrint(MIN_TRACE
, ("AdapterBinding->ProtocolBinding->Chars.ReceiveHandler was null\n"));
207 ("XXX (%x) %x %x %x %x %x %x %x XXX\n",
208 *AdapterBinding
->ProtocolBinding
->Chars
.ReceiveHandler
,
209 AdapterBinding
->NdisOpenBlock
.ProtocolBindingContext
,
217 /* call the receive handler */
218 (*AdapterBinding
->ProtocolBinding
->Chars
.ReceiveHandler
)(
219 AdapterBinding
->NdisOpenBlock
.ProtocolBindingContext
,
227 CurrentEntry
= CurrentEntry
->Flink
;
230 KeReleaseSpinLock(&Adapter
->NdisMiniportBlock
.Lock
, OldIrql
);
232 NDIS_DbgPrint(MAX_TRACE
, ("Leaving.\n"));
237 MiniIndicateReceivePacket(
238 IN NDIS_HANDLE Miniport
,
239 IN PPNDIS_PACKET PacketArray
,
240 IN UINT NumberOfPackets
)
242 * FUNCTION: receives miniport packet array indications
244 * Miniport: Miniport handle for the adapter
245 * PacketArray: pointer to a list of packet pointers to indicate
246 * NumberOfPackets: number of packets to indicate
248 * - This currently is a big temporary hack. In the future this should
249 * call ProtocolReceivePacket() on each bound protocol if it exists.
250 * For now it just mimics NdisMEthIndicateReceive.
255 for(i
= 0; i
< NumberOfPackets
; i
++)
257 PCHAR PacketBuffer
= 0;
258 UINT PacketLength
= 0;
259 PNDIS_BUFFER NdisBuffer
= 0;
261 #define PACKET_TAG (('k' << 24) + ('P' << 16) + ('D' << 8) + 'N')
263 NdisAllocateMemoryWithTag((PVOID
)&PacketBuffer
, 1518, PACKET_TAG
);
266 NDIS_DbgPrint(MIN_TRACE
, ("insufficient resources\n"));
270 NdisQueryPacket(PacketArray
[i
], NULL
, NULL
, &NdisBuffer
, NULL
);
274 PNDIS_BUFFER CurrentBuffer
;
278 NdisQueryBuffer(NdisBuffer
, &BufferVa
, &BufferLen
);
279 memcpy(PacketBuffer
+ PacketLength
, BufferVa
, BufferLen
);
280 PacketLength
+= BufferLen
;
282 CurrentBuffer
= NdisBuffer
;
283 NdisGetNextBuffer(CurrentBuffer
, &NdisBuffer
);
286 NDIS_DbgPrint(MID_TRACE
, ("indicating a %d-byte packet\n", PacketLength
));
288 MiniIndicateData(Miniport
, NULL
, PacketBuffer
, 14, PacketBuffer
+14, PacketLength
-14, PacketLength
-14);
290 NdisFreeMemory(PacketBuffer
, 0, 0);
297 IN NDIS_HANDLE MiniportAdapterHandle
,
298 IN NDIS_STATUS Status
,
299 IN BOOLEAN AddressingReset
)
308 IN PNDIS_HANDLE MiniportAdapterHandle
,
309 IN PNDIS_REQUEST Request
,
310 IN NDIS_STATUS Status
)
312 PLOGICAL_ADAPTER Adapter
= (PLOGICAL_ADAPTER
)MiniportAdapterHandle
;
313 PNDIS_REQUEST_MAC_BLOCK MacBlock
= (PNDIS_REQUEST_MAC_BLOCK
)Request
->MacReserved
;
316 NDIS_DbgPrint(DEBUG_MINIPORT
, ("Called.\n"));
318 KeRaiseIrql(DISPATCH_LEVEL
, &OldIrql
);
319 if( MacBlock
->Binding
->RequestCompleteHandler
) {
320 (*MacBlock
->Binding
->RequestCompleteHandler
)(
321 MacBlock
->Binding
->ProtocolBindingContext
,
325 KeAcquireSpinLockAtDpcLevel(&Adapter
->NdisMiniportBlock
.Lock
);
326 Adapter
->MiniportBusy
= FALSE
;
327 KeReleaseSpinLockFromDpcLevel(&Adapter
->NdisMiniportBlock
.Lock
);
328 KeLowerIrql(OldIrql
);
333 IN NDIS_HANDLE MiniportAdapterHandle
,
334 IN PNDIS_PACKET Packet
,
335 IN NDIS_STATUS Status
)
337 * FUNCTION: Forwards a message to the initiating protocol saying
338 * that a packet was handled
340 * NdisAdapterHandle = Handle input to MiniportInitialize
341 * Packet = Pointer to NDIS packet that was sent
342 * Status = Status of send operation
345 PLOGICAL_ADAPTER Adapter
= MiniportAdapterHandle
;
346 PADAPTER_BINDING AdapterBinding
;
349 NDIS_DbgPrint(DEBUG_MINIPORT
, ("Called.\n"));
351 AdapterBinding
= (PADAPTER_BINDING
)Packet
->Reserved
[0];
353 KeRaiseIrql(DISPATCH_LEVEL
, &OldIrql
);
354 (*AdapterBinding
->ProtocolBinding
->Chars
.SendCompleteHandler
)(
355 AdapterBinding
->NdisOpenBlock
.ProtocolBindingContext
,
358 KeAcquireSpinLockAtDpcLevel(&Adapter
->NdisMiniportBlock
.Lock
);
359 Adapter
->MiniportBusy
= FALSE
;
360 KeReleaseSpinLockFromDpcLevel(&Adapter
->NdisMiniportBlock
.Lock
);
361 KeLowerIrql(OldIrql
);
366 MiniSendResourcesAvailable(
367 IN NDIS_HANDLE MiniportAdapterHandle
)
376 MiniTransferDataComplete(
377 IN NDIS_HANDLE MiniportAdapterHandle
,
378 IN PNDIS_PACKET Packet
,
379 IN NDIS_STATUS Status
,
380 IN UINT BytesTransferred
)
382 PLOGICAL_ADAPTER Adapter
= MiniportAdapterHandle
;
383 PADAPTER_BINDING AdapterBinding
;
386 NDIS_DbgPrint(DEBUG_MINIPORT
, ("Called.\n"));
388 AdapterBinding
= (PADAPTER_BINDING
)Packet
->Reserved
[0];
390 KeRaiseIrql(DISPATCH_LEVEL
, &OldIrql
);
391 (*AdapterBinding
->ProtocolBinding
->Chars
.SendCompleteHandler
)(
392 AdapterBinding
->NdisOpenBlock
.ProtocolBindingContext
,
395 KeAcquireSpinLockAtDpcLevel(&Adapter
->NdisMiniportBlock
.Lock
);
396 Adapter
->MiniportBusy
= FALSE
;
397 KeReleaseSpinLockFromDpcLevel(&Adapter
->NdisMiniportBlock
.Lock
);
398 KeLowerIrql(OldIrql
);
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
);
506 CurrentEntry
= AdapterListHead
.Flink
;
508 while (CurrentEntry
!= &AdapterListHead
)
510 Adapter
= CONTAINING_RECORD(CurrentEntry
, LOGICAL_ADAPTER
, ListEntry
);
514 NDIS_DbgPrint(DEBUG_MINIPORT
, ("Examining adapter 0x%lx\n", Adapter
));
515 NDIS_DbgPrint(DEBUG_MINIPORT
, ("AdapterName = %wZ\n", AdapterName
));
516 NDIS_DbgPrint(DEBUG_MINIPORT
, ("DeviceName = %wZ\n", &Adapter
->NdisMiniportBlock
.MiniportName
));
518 if (RtlCompareUnicodeString(AdapterName
, &Adapter
->NdisMiniportBlock
.MiniportName
, TRUE
) == 0)
524 CurrentEntry
= CurrentEntry
->Flink
;
527 KeReleaseSpinLock(&AdapterListLock
, OldIrql
);
531 NDIS_DbgPrint(DEBUG_MINIPORT
, ("Leaving. Adapter found at 0x%x\n", Adapter
));
535 NDIS_DbgPrint(DEBUG_MINIPORT
, ("Leaving (adapter not found).\n"));
543 MiniQueryInformation(
544 PLOGICAL_ADAPTER Adapter
,
550 * FUNCTION: Queries a logical adapter for properties
552 * Adapter = Pointer to the logical adapter object to query
553 * Oid = Specifies the Object ID to query for
554 * Size = Size of the passed buffer
555 * Buffer = Buffer for the output
556 * BytesWritten = Address of buffer to place number of bytes written
558 * If the specified buffer is too small, a new buffer is allocated,
559 * and the query is attempted again
561 * Status of operation
563 * Is there any way to use the buffer provided by the protocol?
566 NDIS_STATUS NdisStatus
;
570 NDIS_DbgPrint(DEBUG_MINIPORT
, ("Called.\n"));
572 /* call the miniport's queryinfo handler */
573 KeRaiseIrql(DISPATCH_LEVEL
, &OldIrql
);
574 NdisStatus
= (*Adapter
->NdisMiniportBlock
.DriverHandle
->MiniportCharacteristics
.QueryInformationHandler
)(
575 Adapter
->NdisMiniportBlock
.MiniportAdapterContext
,
581 KeLowerIrql(OldIrql
);
583 /* FIXME: Wait in pending case! */
589 MiniCheckForHang( PLOGICAL_ADAPTER Adapter
)
591 * FUNCTION: Checks to see if the miniport is hung
593 * Adapter = Pointer to the logical adapter object
595 * TRUE if the miniport is hung
596 * FALSE if the miniport is not hung
602 KeRaiseIrql(DISPATCH_LEVEL
, &OldIrql
);
603 if (Adapter
->NdisMiniportBlock
.DriverHandle
->MiniportCharacteristics
.CheckForHangHandler
)
604 Ret
= (*Adapter
->NdisMiniportBlock
.DriverHandle
->MiniportCharacteristics
.CheckForHangHandler
)(
605 Adapter
->NdisMiniportBlock
.MiniportAdapterContext
);
606 KeLowerIrql(OldIrql
);
613 PLOGICAL_ADAPTER Adapter
,
614 PBOOLEAN AddressingReset
)
616 * FUNCTION: Resets the miniport
618 * Adapter = Pointer to the logical adapter object
619 * AddressingReset = Set to TRUE if we need to call MiniportSetInformation later
621 * Status of the operation
627 if (Adapter
->MiniportBusy
) {
628 KeAcquireSpinLock(&Adapter
->NdisMiniportBlock
.Lock
, &OldIrql
);
629 MiniQueueWorkItem(Adapter
, NdisWorkItemResetRequested
, NULL
);
630 KeReleaseSpinLock(&Adapter
->NdisMiniportBlock
.Lock
, OldIrql
);
631 return NDIS_STATUS_PENDING
;
634 KeRaiseIrql(DISPATCH_LEVEL
, &OldIrql
);
635 Status
= (*Adapter
->NdisMiniportBlock
.DriverHandle
->MiniportCharacteristics
.ResetHandler
)(
636 Adapter
->NdisMiniportBlock
.MiniportAdapterContext
,
638 KeLowerIrql(OldIrql
);
646 PVOID DeferredContext
,
647 PVOID SystemArgument1
,
648 PVOID SystemArgument2
)
650 PLOGICAL_ADAPTER Adapter
= DeferredContext
;
651 BOOLEAN AddressingReset
= FALSE
;
654 if (MiniCheckForHang(Adapter
)) {
655 NDIS_DbgPrint(MIN_TRACE
, ("Miniport detected adapter hang\n"));
656 MiniReset(Adapter
, &AddressingReset
);
659 /* FIXME: We should call MiniportSetInformation if AddressingReset is TRUE */
666 PLOGICAL_ADAPTER Adapter
,
667 NDIS_WORK_ITEM_TYPE WorkItemType
,
668 PVOID WorkItemContext
)
670 * FUNCTION: Queues a work item for execution at a later time
672 * Adapter = Pointer to the logical adapter object to queue work item on
673 * WorkItemType = Type of work item to queue
674 * WorkItemContext = Pointer to context information for work item
676 * Adapter lock must be held when called
678 * Status of operation
681 PNDIS_MINIPORT_WORK_ITEM Item
;
683 NDIS_DbgPrint(MAX_TRACE
, ("Called.\n"));
686 ASSERT(KeGetCurrentIrql() >= DISPATCH_LEVEL
);
688 Item
= ExAllocatePool(NonPagedPool
, sizeof(NDIS_MINIPORT_WORK_ITEM
));
691 NDIS_DbgPrint(MIN_TRACE
, ("Insufficient resources.\n"));
692 return NDIS_STATUS_RESOURCES
;
695 Item
->WorkItemType
= WorkItemType
;
696 Item
->WorkItemContext
= WorkItemContext
;
698 /* safe due to adapter lock held */
699 Item
->Link
.Next
= NULL
;
700 if (!Adapter
->WorkQueueHead
)
702 Adapter
->WorkQueueHead
= Item
;
703 Adapter
->WorkQueueTail
= Item
;
707 Adapter
->WorkQueueTail
->Link
.Next
= (PSINGLE_LIST_ENTRY
)Item
;
708 Adapter
->WorkQueueTail
= Item
;
711 KeInsertQueueDpc(&Adapter
->NdisMiniportBlock
.DeferredDpc
, NULL
, NULL
);
713 return NDIS_STATUS_SUCCESS
;
720 PLOGICAL_ADAPTER Adapter
,
721 NDIS_WORK_ITEM_TYPE
*WorkItemType
,
722 PVOID
*WorkItemContext
)
724 * FUNCTION: Dequeues a work item from the work queue of a logical adapter
726 * Adapter = Pointer to the logical adapter object to dequeue work item from
727 * AdapterBinding = Address of buffer for adapter binding for this request
728 * WorkItemType = Address of buffer for work item type
729 * WorkItemContext = Address of buffer for pointer to context information
731 * Adapter lock must be held when called
733 * Status of operation
736 PNDIS_MINIPORT_WORK_ITEM Item
;
738 NDIS_DbgPrint(MAX_TRACE
, ("Called.\n"));
740 if (Adapter
->MiniportBusy
) {
741 NDIS_DbgPrint(MID_TRACE
, ("Waiting for miniport to become free.\n"));
742 KeInsertQueueDpc(&Adapter
->NdisMiniportBlock
.DeferredDpc
, NULL
, NULL
);
743 return NDIS_STATUS_FAILURE
;
746 Item
= Adapter
->WorkQueueHead
;
750 /* safe due to adapter lock held */
751 Adapter
->WorkQueueHead
= (PNDIS_MINIPORT_WORK_ITEM
)Item
->Link
.Next
;
753 if (Item
== Adapter
->WorkQueueTail
)
754 Adapter
->WorkQueueTail
= NULL
;
756 *WorkItemType
= Item
->WorkItemType
;
757 *WorkItemContext
= Item
->WorkItemContext
;
761 Adapter
->MiniportBusy
= TRUE
;
763 return NDIS_STATUS_SUCCESS
;
766 return NDIS_STATUS_FAILURE
;
772 PLOGICAL_ADAPTER Adapter
,
773 PNDIS_REQUEST NdisRequest
)
775 * FUNCTION: Sends a request to a miniport
777 * AdapterBinding = Pointer to binding used in the request
778 * NdisRequest = Pointer to NDIS request structure describing request
780 * Status of operation
785 NDIS_DbgPrint(DEBUG_MINIPORT
, ("Called.\n"));
787 Adapter
->NdisMiniportBlock
.MediaRequest
= NdisRequest
;
789 KeRaiseIrql(DISPATCH_LEVEL
, &OldIrql
);
790 switch (NdisRequest
->RequestType
)
792 case NdisRequestQueryInformation
:
793 Status
= (*Adapter
->NdisMiniportBlock
.DriverHandle
->MiniportCharacteristics
.QueryInformationHandler
)(
794 Adapter
->NdisMiniportBlock
.MiniportAdapterContext
,
795 NdisRequest
->DATA
.QUERY_INFORMATION
.Oid
,
796 NdisRequest
->DATA
.QUERY_INFORMATION
.InformationBuffer
,
797 NdisRequest
->DATA
.QUERY_INFORMATION
.InformationBufferLength
,
798 (PULONG
)&NdisRequest
->DATA
.QUERY_INFORMATION
.BytesWritten
,
799 (PULONG
)&NdisRequest
->DATA
.QUERY_INFORMATION
.BytesNeeded
);
802 case NdisRequestSetInformation
:
803 Status
= (*Adapter
->NdisMiniportBlock
.DriverHandle
->MiniportCharacteristics
.SetInformationHandler
)(
804 Adapter
->NdisMiniportBlock
.MiniportAdapterContext
,
805 NdisRequest
->DATA
.SET_INFORMATION
.Oid
,
806 NdisRequest
->DATA
.SET_INFORMATION
.InformationBuffer
,
807 NdisRequest
->DATA
.SET_INFORMATION
.InformationBufferLength
,
808 (PULONG
)&NdisRequest
->DATA
.SET_INFORMATION
.BytesRead
,
809 (PULONG
)&NdisRequest
->DATA
.SET_INFORMATION
.BytesNeeded
);
813 Status
= NDIS_STATUS_FAILURE
;
816 if (Status
== NDIS_STATUS_PENDING
) {
817 KeAcquireSpinLockAtDpcLevel(&Adapter
->NdisMiniportBlock
.Lock
);
818 Adapter
->MiniportBusy
= TRUE
;
819 KeReleaseSpinLockFromDpcLevel(&Adapter
->NdisMiniportBlock
.Lock
);
822 KeLowerIrql(OldIrql
);
830 #undef NdisMQueryInformationComplete
833 NdisMQueryInformationComplete(
834 IN NDIS_HANDLE MiniportAdapterHandle
,
835 IN NDIS_STATUS Status
)
837 PLOGICAL_ADAPTER Adapter
=
838 (PLOGICAL_ADAPTER
)MiniportAdapterHandle
;
841 KeRaiseIrql(DISPATCH_LEVEL
, &OldIrql
);
842 if( Adapter
->NdisMiniportBlock
.QueryCompleteHandler
)
843 (Adapter
->NdisMiniportBlock
.QueryCompleteHandler
)(MiniportAdapterHandle
, Status
);
844 KeAcquireSpinLockAtDpcLevel(&Adapter
->NdisMiniportBlock
.Lock
);
845 Adapter
->MiniportBusy
= FALSE
;
846 KeReleaseSpinLockFromDpcLevel(&Adapter
->NdisMiniportBlock
.Lock
);
847 KeLowerIrql(OldIrql
);
850 VOID NTAPI
MiniportWorker(IN PVOID WorkItem
)
852 PNDIS_WORK_ITEM NdisWorkItem
= WorkItem
;
853 PLOGICAL_ADAPTER Adapter
= GET_LOGICAL_ADAPTER(NdisWorkItem
->Context
);
854 KIRQL OldIrql
, RaiseOldIrql
;
855 NDIS_STATUS NdisStatus
;
856 PVOID WorkItemContext
;
857 NDIS_WORK_ITEM_TYPE WorkItemType
;
858 BOOLEAN AddressingReset
;
860 KeAcquireSpinLock(&Adapter
->NdisMiniportBlock
.Lock
, &OldIrql
);
864 (Adapter
, &WorkItemType
, &WorkItemContext
);
866 KeReleaseSpinLock(&Adapter
->NdisMiniportBlock
.Lock
, OldIrql
);
868 if (NdisStatus
== NDIS_STATUS_SUCCESS
)
870 switch (WorkItemType
)
872 case NdisWorkItemSend
:
874 * called by ProSend when protocols want to send packets to the miniport
877 MiniDisplayPacket((PNDIS_PACKET
)WorkItemContext
);
879 if(Adapter
->NdisMiniportBlock
.DriverHandle
->MiniportCharacteristics
.SendPacketsHandler
)
881 if(Adapter
->NdisMiniportBlock
.Flags
& NDIS_ATTRIBUTE_DESERIALIZE
)
883 NDIS_DbgPrint(MAX_TRACE
, ("Calling miniport's SendPackets handler\n"));
884 (*Adapter
->NdisMiniportBlock
.DriverHandle
->MiniportCharacteristics
.SendPacketsHandler
)(
885 Adapter
->NdisMiniportBlock
.MiniportAdapterContext
, (PPNDIS_PACKET
)&WorkItemContext
, 1);
886 NdisStatus
= NDIS_GET_PACKET_STATUS((PNDIS_PACKET
)WorkItemContext
);
890 /* SendPackets is called at DISPATCH_LEVEL for all serialized miniports */
891 KeRaiseIrql(DISPATCH_LEVEL
, &RaiseOldIrql
);
893 NDIS_DbgPrint(MAX_TRACE
, ("Calling miniport's SendPackets handler\n"));
894 (*Adapter
->NdisMiniportBlock
.DriverHandle
->MiniportCharacteristics
.SendPacketsHandler
)(
895 Adapter
->NdisMiniportBlock
.MiniportAdapterContext
, (PPNDIS_PACKET
)&WorkItemContext
, 1);
897 KeLowerIrql(RaiseOldIrql
);
899 NdisStatus
= NDIS_GET_PACKET_STATUS((PNDIS_PACKET
)WorkItemContext
);
900 if( NdisStatus
== NDIS_STATUS_RESOURCES
) {
901 KeAcquireSpinLock(&Adapter
->NdisMiniportBlock
.Lock
, &OldIrql
);
902 MiniQueueWorkItem(Adapter
, WorkItemType
, WorkItemContext
);
903 KeReleaseSpinLock(&Adapter
->NdisMiniportBlock
.Lock
, OldIrql
);
910 if(Adapter
->NdisMiniportBlock
.Flags
& NDIS_ATTRIBUTE_DESERIALIZE
)
912 NDIS_DbgPrint(MAX_TRACE
, ("Calling miniport's Send handler\n"));
913 NdisStatus
= (*Adapter
->NdisMiniportBlock
.DriverHandle
->MiniportCharacteristics
.SendHandler
)(
914 Adapter
->NdisMiniportBlock
.MiniportAdapterContext
, (PNDIS_PACKET
)WorkItemContext
, 0);
915 NDIS_DbgPrint(MAX_TRACE
, ("back from miniport's send handler\n"));
919 /* Send is called at DISPATCH_LEVEL for all serialized miniports */
920 KeRaiseIrql(DISPATCH_LEVEL
, &RaiseOldIrql
);
921 NDIS_DbgPrint(MAX_TRACE
, ("Calling miniport's Send handler\n"));
922 NdisStatus
= (*Adapter
->NdisMiniportBlock
.DriverHandle
->MiniportCharacteristics
.SendHandler
)(
923 Adapter
->NdisMiniportBlock
.MiniportAdapterContext
, (PNDIS_PACKET
)WorkItemContext
, 0);
924 NDIS_DbgPrint(MAX_TRACE
, ("back from miniport's send handler\n"));
925 KeLowerIrql(RaiseOldIrql
);
926 if( NdisStatus
== NDIS_STATUS_RESOURCES
) {
927 KeAcquireSpinLock(&Adapter
->NdisMiniportBlock
.Lock
, &OldIrql
);
928 MiniQueueWorkItem(Adapter
, WorkItemType
, WorkItemContext
);
929 KeReleaseSpinLock(&Adapter
->NdisMiniportBlock
.Lock
, OldIrql
);
935 if( NdisStatus
!= NDIS_STATUS_PENDING
) {
937 ( Adapter
, (PNDIS_PACKET
)WorkItemContext
, NdisStatus
);
941 case NdisWorkItemSendLoopback
:
943 * called by ProSend when protocols want to send loopback packets
945 /* XXX atm ProIndicatePacket sends a packet up via the loopback adapter only */
946 NdisStatus
= ProIndicatePacket(Adapter
, (PNDIS_PACKET
)WorkItemContext
);
948 if( NdisStatus
!= NDIS_STATUS_PENDING
)
949 MiniSendComplete((NDIS_HANDLE
)Adapter
, (PNDIS_PACKET
)WorkItemContext
, NdisStatus
);
952 case NdisWorkItemReturnPackets
:
955 case NdisWorkItemResetRequested
:
956 KeRaiseIrql(DISPATCH_LEVEL
, &OldIrql
);
957 NdisStatus
= (*Adapter
->NdisMiniportBlock
.DriverHandle
->MiniportCharacteristics
.ResetHandler
)(
958 Adapter
->NdisMiniportBlock
.MiniportAdapterContext
,
960 KeLowerIrql(OldIrql
);
962 if (NdisStatus
== NDIS_STATUS_PENDING
)
965 MiniResetComplete(Adapter
, NdisStatus
, AddressingReset
);
968 case NdisWorkItemResetInProgress
:
971 case NdisWorkItemMiniportCallback
:
974 case NdisWorkItemRequest
:
975 NdisStatus
= MiniDoRequest(Adapter
, (PNDIS_REQUEST
)WorkItemContext
);
977 if (NdisStatus
== NDIS_STATUS_PENDING
)
980 switch (((PNDIS_REQUEST
)WorkItemContext
)->RequestType
)
982 case NdisRequestQueryInformation
:
983 NdisMQueryInformationComplete((NDIS_HANDLE
)Adapter
, NdisStatus
);
984 MiniRequestComplete( (NDIS_HANDLE
)Adapter
, (PNDIS_REQUEST
)WorkItemContext
, NdisStatus
);
987 case NdisRequestSetInformation
:
988 NdisMSetInformationComplete((NDIS_HANDLE
)Adapter
, NdisStatus
);
989 MiniRequestComplete( (NDIS_HANDLE
)Adapter
, (PNDIS_REQUEST
)WorkItemContext
, NdisStatus
);
993 NDIS_DbgPrint(MIN_TRACE
, ("Unknown NDIS request type.\n"));
999 NDIS_DbgPrint(MIN_TRACE
, ("Unknown NDIS work item type (%d).\n", WorkItemType
));
1004 if( NdisStatus
!= NDIS_STATUS_PENDING
) {
1005 KeAcquireSpinLock(&Adapter
->NdisMiniportBlock
.Lock
, &OldIrql
);
1006 Adapter
->MiniportBusy
= FALSE
;
1007 KeReleaseSpinLock(&Adapter
->NdisMiniportBlock
.Lock
, OldIrql
);
1010 ExFreePool(WorkItem
);
1015 VOID NTAPI
MiniportDpc(
1017 IN PVOID DeferredContext
,
1018 IN PVOID SystemArgument1
,
1019 IN PVOID SystemArgument2
)
1021 * FUNCTION: Deferred routine to handle serialization
1023 * Dpc = Pointer to DPC object
1024 * DeferredContext = Pointer to context information (LOGICAL_ADAPTER)
1025 * SystemArgument1 = Unused
1026 * SystemArgument2 = Unused
1029 PNDIS_WORK_ITEM NdisWorkItem
;
1030 PWORK_QUEUE_ITEM WorkItem
;
1032 NDIS_DbgPrint(DEBUG_MINIPORT
, ("Called.\n"));
1034 NdisWorkItem
= ExAllocatePool(NonPagedPool
, sizeof(NDIS_WORK_ITEM
));
1035 if (!NdisWorkItem
) return;
1037 WorkItem
= (PWORK_QUEUE_ITEM
)NdisWorkItem
->WrapperReserved
;
1039 NdisWorkItem
->Context
= DeferredContext
;
1041 ExInitializeWorkItem(WorkItem
, MiniportWorker
, NdisWorkItem
);
1043 ExQueueWorkItem(WorkItem
, CriticalWorkQueue
);
1050 IN NDIS_HANDLE MiniportHandle
,
1051 IN NDIS_STATUS GeneralStatus
,
1052 IN PVOID StatusBuffer
,
1053 IN UINT StatusBufferSize
)
1062 IN NDIS_HANDLE MiniportAdapterHandle
)
1074 IN NDIS_HANDLE LogHandle
)
1086 IN NDIS_HANDLE MiniportAdapterHandle
,
1088 OUT PNDIS_HANDLE LogHandle
)
1092 return NDIS_STATUS_FAILURE
;
1101 NdisMDeregisterAdapterShutdownHandler(
1102 IN NDIS_HANDLE MiniportHandle
)
1104 * FUNCTION: de-registers a shutdown handler
1105 * ARGUMENTS: MiniportHandle: Handle passed into MiniportInitialize
1108 PLOGICAL_ADAPTER Adapter
= (PLOGICAL_ADAPTER
)MiniportHandle
;
1110 NDIS_DbgPrint(DEBUG_MINIPORT
, ("Called.\n"));
1112 if(Adapter
->BugcheckContext
->ShutdownHandler
)
1113 KeDeregisterBugCheckCallback(Adapter
->BugcheckContext
->CallbackRecord
);
1123 IN NDIS_HANDLE LogHandle
)
1131 #undef NdisMIndicateStatus
1134 NdisMIndicateStatus(
1135 IN NDIS_HANDLE MiniportAdapterHandle
,
1136 IN NDIS_STATUS GeneralStatus
,
1137 IN PVOID StatusBuffer
,
1138 IN UINT StatusBufferSize
)
1146 #undef NdisMIndicateStatusComplete
1149 NdisMIndicateStatusComplete(
1150 IN NDIS_HANDLE MiniportAdapterHandle
)
1161 NdisInitializeWrapper(
1162 OUT PNDIS_HANDLE NdisWrapperHandle
,
1163 IN PVOID SystemSpecific1
,
1164 IN PVOID SystemSpecific2
,
1165 IN PVOID SystemSpecific3
)
1167 * FUNCTION: Notifies the NDIS library that a new miniport is initializing
1169 * NdisWrapperHandle = Address of buffer to place NDIS wrapper handle
1170 * SystemSpecific1 = Pointer to the driver's driver object
1171 * SystemSpecific2 = Pointer to the driver's registry path
1172 * SystemSpecific3 = Always NULL
1174 * - SystemSpecific2 goes invalid so we copy it
1177 PNDIS_M_DRIVER_BLOCK Miniport
;
1178 PUNICODE_STRING RegistryPath
;
1179 WCHAR
*RegistryBuffer
;
1181 NDIS_DbgPrint(MAX_TRACE
, ("Called.\n"));
1183 ASSERT(NdisWrapperHandle
);
1185 *NdisWrapperHandle
= NULL
;
1187 #if BREAK_ON_MINIPORT_INIT
1188 __asm__ ("int $3\n");
1191 Miniport
= ExAllocatePool(NonPagedPool
, sizeof(NDIS_M_DRIVER_BLOCK
));
1195 NDIS_DbgPrint(MIN_TRACE
, ("Insufficient resources.\n"));
1199 RtlZeroMemory(Miniport
, sizeof(NDIS_M_DRIVER_BLOCK
));
1201 KeInitializeSpinLock(&Miniport
->Lock
);
1203 Miniport
->DriverObject
= (PDRIVER_OBJECT
)SystemSpecific1
;
1205 /* set the miniport's driver registry path */
1206 RegistryPath
= ExAllocatePool(PagedPool
, sizeof(UNICODE_STRING
));
1209 ExFreePool(Miniport
);
1210 NDIS_DbgPrint(MIN_TRACE
, ("Insufficient resources.\n"));
1214 RegistryPath
->Length
= ((PUNICODE_STRING
)SystemSpecific2
)->Length
;
1215 RegistryPath
->MaximumLength
= RegistryPath
->Length
+ sizeof(WCHAR
); /* room for 0-term */
1217 RegistryBuffer
= ExAllocatePool(PagedPool
, RegistryPath
->MaximumLength
);
1220 NDIS_DbgPrint(MIN_TRACE
, ("Insufficient resources.\n"));
1221 ExFreePool(Miniport
);
1222 ExFreePool(RegistryPath
);
1226 RtlCopyMemory(RegistryBuffer
, ((PUNICODE_STRING
)SystemSpecific2
)->Buffer
, RegistryPath
->Length
);
1227 RegistryBuffer
[RegistryPath
->Length
/sizeof(WCHAR
)] = 0;
1229 RegistryPath
->Buffer
= RegistryBuffer
;
1230 Miniport
->RegistryPath
= RegistryPath
;
1232 InitializeListHead(&Miniport
->DeviceList
);
1234 /* Put miniport in global miniport list */
1235 ExInterlockedInsertTailList(&MiniportListHead
, &Miniport
->ListEntry
, &MiniportListLock
);
1237 *NdisWrapperHandle
= Miniport
;
1241 VOID NTAPI
NdisIBugcheckCallback(
1245 * FUNCTION: Internal callback for handling bugchecks - calls adapter's shutdown handler
1247 * Buffer: Pointer to a bugcheck callback context
1251 PMINIPORT_BUGCHECK_CONTEXT Context
= (PMINIPORT_BUGCHECK_CONTEXT
)Buffer
;
1252 ADAPTER_SHUTDOWN_HANDLER sh
= (ADAPTER_SHUTDOWN_HANDLER
)Context
->ShutdownHandler
;
1254 NDIS_DbgPrint(DEBUG_MINIPORT
, ("Called.\n"));
1257 sh(Context
->DriverContext
);
1266 NdisMRegisterAdapterShutdownHandler(
1267 IN NDIS_HANDLE MiniportHandle
,
1268 IN PVOID ShutdownContext
,
1269 IN ADAPTER_SHUTDOWN_HANDLER ShutdownHandler
)
1271 * FUNCTION: Register a shutdown handler for an adapter
1273 * MiniportHandle: Handle originally passed into MiniportInitialize
1274 * ShutdownContext: Pre-initialized bugcheck context
1275 * ShutdownHandler: Function to call to handle the bugcheck
1277 * - I'm not sure about ShutdownContext
1280 PLOGICAL_ADAPTER Adapter
= (PLOGICAL_ADAPTER
)MiniportHandle
;
1281 PMINIPORT_BUGCHECK_CONTEXT BugcheckContext
= Adapter
->BugcheckContext
;
1283 NDIS_DbgPrint(DEBUG_MINIPORT
, ("Called.\n"));
1288 BugcheckContext
= ExAllocatePool(NonPagedPool
, sizeof(MINIPORT_BUGCHECK_CONTEXT
));
1289 if(!BugcheckContext
)
1291 NDIS_DbgPrint(MIN_TRACE
, ("Insufficient resources.\n"));
1295 BugcheckContext
->ShutdownHandler
= ShutdownHandler
;
1296 BugcheckContext
->DriverContext
= ShutdownContext
;
1298 BugcheckContext
->CallbackRecord
= ExAllocatePool(NonPagedPool
, sizeof(KBUGCHECK_CALLBACK_RECORD
));
1300 KeInitializeCallbackRecord(BugcheckContext
->CallbackRecord
);
1302 KeRegisterBugCheckCallback(BugcheckContext
->CallbackRecord
, NdisIBugcheckCallback
,
1303 BugcheckContext
, sizeof(BugcheckContext
), (PUCHAR
)"Ndis Miniport");
1309 PLOGICAL_ADAPTER Adapter
,
1310 NDIS_OID AddressOID
)
1312 * FUNCTION: Queries miniport for information
1314 * Adapter = Pointer to logical adapter
1315 * AddressOID = OID to use to query for current address
1317 * Status of operation
1321 NDIS_STATUS NdisStatus
;
1323 NDIS_DbgPrint(MAX_TRACE
, ("Called.\n"));
1325 /* Get MAC options for adapter */
1326 NdisStatus
= MiniQueryInformation(Adapter
, OID_GEN_MAC_OPTIONS
, sizeof(UINT
),
1327 &Adapter
->NdisMiniportBlock
.MacOptions
,
1330 if (NdisStatus
!= NDIS_STATUS_SUCCESS
)
1332 NDIS_DbgPrint(MIN_TRACE
, ("OID_GEN_MAC_OPTIONS failed. NdisStatus (0x%X).\n", NdisStatus
));
1336 NDIS_DbgPrint(DEBUG_MINIPORT
, ("MacOptions (0x%X).\n", Adapter
->NdisMiniportBlock
.MacOptions
));
1338 /* Get current hardware address of adapter */
1339 NdisStatus
= MiniQueryInformation(Adapter
, AddressOID
, Adapter
->AddressLength
,
1340 &Adapter
->Address
, &BytesWritten
);
1342 if (NdisStatus
!= NDIS_STATUS_SUCCESS
)
1344 NDIS_DbgPrint(MIN_TRACE
, ("Address OID (0x%X) failed. NdisStatus (0x%X).\n", AddressOID
, NdisStatus
));
1352 PUCHAR A
= (PUCHAR
)&Adapter
->Address
.Type
.Medium802_3
;
1354 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]));
1358 /* Get maximum lookahead buffer size of adapter */
1359 NdisStatus
= MiniQueryInformation(Adapter
, OID_GEN_MAXIMUM_LOOKAHEAD
, sizeof(ULONG
),
1360 &Adapter
->NdisMiniportBlock
.MaximumLookahead
, &BytesWritten
);
1362 if (NdisStatus
!= NDIS_STATUS_SUCCESS
)
1364 NDIS_DbgPrint(MIN_TRACE
, ("OID_GEN_MAXIMUM_LOOKAHEAD failed. NdisStatus (0x%X).\n", NdisStatus
));
1368 NDIS_DbgPrint(DEBUG_MINIPORT
, ("MaxLookaheadLength (0x%X).\n", Adapter
->NdisMiniportBlock
.MaximumLookahead
));
1370 /* Get current lookahead buffer size of adapter */
1371 NdisStatus
= MiniQueryInformation(Adapter
, OID_GEN_CURRENT_LOOKAHEAD
, sizeof(ULONG
),
1372 &Adapter
->NdisMiniportBlock
.CurrentLookahead
, &BytesWritten
);
1374 if (NdisStatus
!= NDIS_STATUS_SUCCESS
)
1376 NDIS_DbgPrint(MIN_TRACE
, ("OID_GEN_CURRENT_LOOKAHEAD failed. NdisStatus (0x%X).\n", NdisStatus
));
1380 NdisStatus
= MiniQueryInformation(Adapter
, OID_GEN_MAXIMUM_SEND_PACKETS
, sizeof(ULONG
),
1381 &Adapter
->NdisMiniportBlock
.MaxSendPackets
, &BytesWritten
);
1383 if (NdisStatus
!= NDIS_STATUS_SUCCESS
)
1385 NDIS_DbgPrint(MIN_TRACE
, ("OID_GEN_MAXIMUM_SEND_PACKETS failed. NdisStatus (0x%X).\n", NdisStatus
));
1387 /* Set it to 1 if it fails because some drivers don't support this (?)*/
1388 Adapter
->NdisMiniportBlock
.MaxSendPackets
= 1;
1391 NDIS_DbgPrint(DEBUG_MINIPORT
, ("CurLookaheadLength (0x%X).\n", Adapter
->NdisMiniportBlock
.CurrentLookahead
));
1393 if (Adapter
->NdisMiniportBlock
.MaximumLookahead
!= 0)
1395 Adapter
->LookaheadLength
= Adapter
->NdisMiniportBlock
.MaximumLookahead
+ Adapter
->MediumHeaderSize
;
1396 Adapter
->LookaheadBuffer
= ExAllocatePool(NonPagedPool
, Adapter
->LookaheadLength
);
1398 if (!Adapter
->LookaheadBuffer
)
1399 return NDIS_STATUS_RESOURCES
;
1402 return STATUS_SUCCESS
;
1408 NdisIForwardIrpAndWaitCompletionRoutine(
1413 PKEVENT Event
= Context
;
1415 if (Irp
->PendingReturned
)
1416 KeSetEvent(Event
, IO_NO_INCREMENT
, FALSE
);
1418 return STATUS_MORE_PROCESSING_REQUIRED
;
1424 NdisIForwardIrpAndWait(PLOGICAL_ADAPTER Adapter
, PIRP Irp
)
1429 KeInitializeEvent(&Event
, NotificationEvent
, FALSE
);
1430 IoCopyCurrentIrpStackLocationToNext(Irp
);
1431 IoSetCompletionRoutine(Irp
, NdisIForwardIrpAndWaitCompletionRoutine
, &Event
,
1433 Status
= IoCallDriver(Adapter
->NdisMiniportBlock
.NextDeviceObject
, Irp
);
1434 if (Status
== STATUS_PENDING
)
1436 KeWaitForSingleObject(&Event
, Executive
, KernelMode
, FALSE
, NULL
);
1437 Status
= Irp
->IoStatus
.Status
;
1445 NdisIPnPStartDevice(
1446 IN PDEVICE_OBJECT DeviceObject
,
1449 * FUNCTION: Handle the PnP start device event
1451 * DeviceObejct = Functional Device Object
1452 * Irp = IRP_MN_START_DEVICE I/O request packet
1454 * Status of operation
1457 PIO_STACK_LOCATION Stack
= IoGetCurrentIrpStackLocation(Irp
);
1458 PLOGICAL_ADAPTER Adapter
= (PLOGICAL_ADAPTER
)DeviceObject
->DeviceExtension
;
1459 NDIS_WRAPPER_CONTEXT WrapperContext
;
1460 NDIS_STATUS NdisStatus
;
1461 NDIS_STATUS OpenErrorStatus
;
1463 UINT SelectedMediumIndex
= 0;
1464 NDIS_OID AddressOID
;
1465 BOOLEAN Success
= FALSE
;
1466 ULONG ResourceCount
;
1467 ULONG ResourceListSize
;
1468 UNICODE_STRING ParamName
;
1469 PNDIS_CONFIGURATION_PARAMETER ConfigParam
;
1470 NDIS_HANDLE ConfigHandle
;
1472 LARGE_INTEGER Timeout
;
1473 /* FIXME - KIRQL OldIrql; */
1476 * Prepare wrapper context used by HW and configuration routines.
1479 NDIS_DbgPrint(DEBUG_MINIPORT
, ("Start Device %wZ\n", &Adapter
->NdisMiniportBlock
.MiniportName
));
1481 NDIS_DbgPrint(MAX_TRACE
, ("Inserting adapter 0x%x into adapter list\n", Adapter
));
1483 /* Put adapter in global adapter list */
1484 ExInterlockedInsertTailList(&AdapterListHead
, &Adapter
->ListEntry
, &AdapterListLock
);
1486 Status
= IoOpenDeviceRegistryKey(
1487 Adapter
->NdisMiniportBlock
.PhysicalDeviceObject
, PLUGPLAY_REGKEY_DRIVER
,
1488 KEY_ALL_ACCESS
, &WrapperContext
.RegistryHandle
);
1489 if (!NT_SUCCESS(Status
))
1491 NDIS_DbgPrint(MIN_TRACE
,("failed to open adapter-specific reg key\n"));
1492 ExInterlockedRemoveEntryList( &Adapter
->ListEntry
, &AdapterListLock
);
1496 NDIS_DbgPrint(MAX_TRACE
, ("opened device reg key\n"));
1498 WrapperContext
.DeviceObject
= Adapter
->NdisMiniportBlock
.DeviceObject
;
1501 * Store the adapter resources used by HW routines such as
1502 * NdisMQueryAdapterResources.
1505 if (Stack
->Parameters
.StartDevice
.AllocatedResources
!= NULL
)
1507 ResourceCount
= Stack
->Parameters
.StartDevice
.AllocatedResources
->List
[0].
1508 PartialResourceList
.Count
;
1510 FIELD_OFFSET(CM_RESOURCE_LIST
, List
[0].PartialResourceList
.
1511 PartialDescriptors
[ResourceCount
]);
1513 Adapter
->NdisMiniportBlock
.AllocatedResources
=
1514 ExAllocatePool(PagedPool
, ResourceListSize
);
1515 if (Adapter
->NdisMiniportBlock
.AllocatedResources
== NULL
)
1517 ExInterlockedRemoveEntryList( &Adapter
->ListEntry
, &AdapterListLock
);
1518 return STATUS_INSUFFICIENT_RESOURCES
;
1521 RtlCopyMemory(Adapter
->NdisMiniportBlock
.AllocatedResources
,
1522 Stack
->Parameters
.StartDevice
.AllocatedResources
,
1526 if (Stack
->Parameters
.StartDevice
.AllocatedResourcesTranslated
!= NULL
)
1528 ResourceCount
= Stack
->Parameters
.StartDevice
.AllocatedResourcesTranslated
->List
[0].
1529 PartialResourceList
.Count
;
1531 FIELD_OFFSET(CM_RESOURCE_LIST
, List
[0].PartialResourceList
.
1532 PartialDescriptors
[ResourceCount
]);
1534 Adapter
->NdisMiniportBlock
.AllocatedResourcesTranslated
=
1535 ExAllocatePool(PagedPool
, ResourceListSize
);
1536 if (Adapter
->NdisMiniportBlock
.AllocatedResourcesTranslated
== NULL
)
1538 ExInterlockedRemoveEntryList( &Adapter
->ListEntry
, &AdapterListLock
);
1539 return STATUS_INSUFFICIENT_RESOURCES
;
1542 RtlCopyMemory(Adapter
->NdisMiniportBlock
.AllocatedResourcesTranslated
,
1543 Stack
->Parameters
.StartDevice
.AllocatedResourcesTranslated
,
1548 * Store the Bus Type, Bus Number and Slot information. It's used by
1549 * the hardware routines then.
1552 NdisOpenConfiguration(&NdisStatus
, &ConfigHandle
, (NDIS_HANDLE
)&WrapperContext
);
1554 Size
= sizeof(ULONG
);
1555 Status
= IoGetDeviceProperty(Adapter
->NdisMiniportBlock
.PhysicalDeviceObject
,
1556 DevicePropertyLegacyBusType
, Size
,
1557 &Adapter
->NdisMiniportBlock
.BusType
, &Size
);
1558 if (!NT_SUCCESS(Status
) || (INTERFACE_TYPE
)Adapter
->NdisMiniportBlock
.BusType
== InterfaceTypeUndefined
)
1560 NdisInitUnicodeString(&ParamName
, L
"BusType");
1561 NdisReadConfiguration(&NdisStatus
, &ConfigParam
, ConfigHandle
,
1562 &ParamName
, NdisParameterInteger
);
1563 if (NdisStatus
== NDIS_STATUS_SUCCESS
)
1564 Adapter
->NdisMiniportBlock
.BusType
= ConfigParam
->ParameterData
.IntegerData
;
1566 Adapter
->NdisMiniportBlock
.BusType
= Isa
;
1569 Status
= IoGetDeviceProperty(Adapter
->NdisMiniportBlock
.PhysicalDeviceObject
,
1570 DevicePropertyBusNumber
, Size
,
1571 &Adapter
->NdisMiniportBlock
.BusNumber
, &Size
);
1572 if (!NT_SUCCESS(Status
) || Adapter
->NdisMiniportBlock
.BusNumber
== 0xFFFFFFF0)
1574 NdisInitUnicodeString(&ParamName
, L
"BusNumber");
1575 NdisReadConfiguration(&NdisStatus
, &ConfigParam
, ConfigHandle
,
1576 &ParamName
, NdisParameterInteger
);
1577 if (NdisStatus
== NDIS_STATUS_SUCCESS
)
1578 Adapter
->NdisMiniportBlock
.BusNumber
= ConfigParam
->ParameterData
.IntegerData
;
1580 Adapter
->NdisMiniportBlock
.BusNumber
= 0;
1582 WrapperContext
.BusNumber
= Adapter
->NdisMiniportBlock
.BusNumber
;
1584 Status
= IoGetDeviceProperty(Adapter
->NdisMiniportBlock
.PhysicalDeviceObject
,
1585 DevicePropertyAddress
, Size
,
1586 &Adapter
->NdisMiniportBlock
.SlotNumber
, &Size
);
1587 if (!NT_SUCCESS(Status
) || Adapter
->NdisMiniportBlock
.SlotNumber
== (NDIS_INTERFACE_TYPE
)-1)
1589 NdisInitUnicodeString(&ParamName
, L
"SlotNumber");
1590 NdisReadConfiguration(&NdisStatus
, &ConfigParam
, ConfigHandle
,
1591 &ParamName
, NdisParameterInteger
);
1592 if (NdisStatus
== NDIS_STATUS_SUCCESS
)
1593 Adapter
->NdisMiniportBlock
.SlotNumber
= ConfigParam
->ParameterData
.IntegerData
;
1595 Adapter
->NdisMiniportBlock
.SlotNumber
= 0;
1599 /* Convert slotnumber to PCI_SLOT_NUMBER */
1600 ULONG PciSlotNumber
= Adapter
->NdisMiniportBlock
.SlotNumber
;
1601 PCI_SLOT_NUMBER SlotNumber
;
1603 SlotNumber
.u
.AsULONG
= 0;
1604 SlotNumber
.u
.bits
.DeviceNumber
= (PciSlotNumber
>> 16) & 0xFFFF;
1605 SlotNumber
.u
.bits
.FunctionNumber
= PciSlotNumber
& 0xFFFF;
1607 Adapter
->NdisMiniportBlock
.SlotNumber
= SlotNumber
.u
.AsULONG
;
1609 NdisCloseConfiguration(ConfigHandle
);
1611 /* Set handlers (some NDIS macros require these) */
1612 Adapter
->NdisMiniportBlock
.EthRxCompleteHandler
= EthFilterDprIndicateReceiveComplete
;
1613 Adapter
->NdisMiniportBlock
.EthRxIndicateHandler
= EthFilterDprIndicateReceive
;
1614 Adapter
->NdisMiniportBlock
.SendCompleteHandler
= MiniSendComplete
;
1615 Adapter
->NdisMiniportBlock
.SendResourcesHandler
= MiniSendResourcesAvailable
;
1616 Adapter
->NdisMiniportBlock
.ResetCompleteHandler
= MiniResetComplete
;
1617 Adapter
->NdisMiniportBlock
.TDCompleteHandler
= MiniTransferDataComplete
;
1618 Adapter
->NdisMiniportBlock
.PacketIndicateHandler
= MiniIndicateReceivePacket
;
1619 Adapter
->NdisMiniportBlock
.StatusHandler
= MiniStatus
;
1620 Adapter
->NdisMiniportBlock
.StatusCompleteHandler
= MiniStatusComplete
;
1623 * Call MiniportInitialize.
1626 NDIS_DbgPrint(MID_TRACE
, ("calling MiniportInitialize\n"));
1627 NdisStatus
= (*Adapter
->NdisMiniportBlock
.DriverHandle
->MiniportCharacteristics
.InitializeHandler
)(
1628 &OpenErrorStatus
, &SelectedMediumIndex
, &MediaArray
[0],
1629 MEDIA_ARRAY_SIZE
, Adapter
, (NDIS_HANDLE
)&WrapperContext
);
1631 ZwClose(WrapperContext
.RegistryHandle
);
1633 if (NdisStatus
!= NDIS_STATUS_SUCCESS
||
1634 SelectedMediumIndex
>= MEDIA_ARRAY_SIZE
)
1636 NDIS_DbgPrint(MIN_TRACE
, ("MiniportInitialize() failed for an adapter.\n"));
1637 ExInterlockedRemoveEntryList( &Adapter
->ListEntry
, &AdapterListLock
);
1638 if (NdisStatus
== NDIS_STATUS_SUCCESS
) NdisStatus
= NDIS_STATUS_FAILURE
;
1639 return (NTSTATUS
)NdisStatus
;
1642 Adapter
->NdisMiniportBlock
.MediaType
= MediaArray
[SelectedMediumIndex
];
1644 switch (Adapter
->NdisMiniportBlock
.MediaType
)
1646 case NdisMedium802_3
:
1647 Adapter
->MediumHeaderSize
= 14; /* XXX figure out what to do about LLC */
1648 AddressOID
= OID_802_3_CURRENT_ADDRESS
;
1649 Adapter
->AddressLength
= ETH_LENGTH_OF_ADDRESS
;
1650 NdisStatus
= DoQueries(Adapter
, AddressOID
);
1651 if (NdisStatus
== NDIS_STATUS_SUCCESS
)
1653 Success
= EthCreateFilter(32, /* FIXME: Query this from miniport. */
1654 Adapter
->Address
.Type
.Medium802_3
,
1655 &Adapter
->NdisMiniportBlock
.EthDB
);
1657 ((PETHI_FILTER
)Adapter
->NdisMiniportBlock
.EthDB
)->Miniport
= (PNDIS_MINIPORT_BLOCK
)Adapter
;
1659 NdisStatus
= NDIS_STATUS_RESOURCES
;
1664 /* FIXME: Support other types of media */
1665 NDIS_DbgPrint(MIN_TRACE
, ("error: unsupported media\n"));
1667 /* FIXME - KeReleaseSpinLock(&Adapter->NdisMiniportBlock.Lock, OldIrql); */
1668 ExInterlockedRemoveEntryList( &Adapter
->ListEntry
, &AdapterListLock
);
1669 return STATUS_UNSUCCESSFUL
;
1672 if (!Success
|| NdisStatus
!= NDIS_STATUS_SUCCESS
)
1674 NDIS_DbgPrint(MAX_TRACE
, ("couldn't create filter (%x)\n", NdisStatus
));
1675 if (Adapter
->LookaheadBuffer
)
1677 ExFreePool(Adapter
->LookaheadBuffer
);
1678 Adapter
->LookaheadBuffer
= NULL
;
1680 ExInterlockedRemoveEntryList( &Adapter
->ListEntry
, &AdapterListLock
);
1681 if (NdisStatus
== NDIS_STATUS_SUCCESS
) NdisStatus
= NDIS_STATUS_FAILURE
;
1682 return (NTSTATUS
)NdisStatus
;
1685 /* Check for a hang every two seconds if it wasn't set in MiniportInitialize */
1686 if (Adapter
->NdisMiniportBlock
.CheckForHangSeconds
== 0)
1687 Adapter
->NdisMiniportBlock
.CheckForHangSeconds
= 2;
1689 Adapter
->NdisMiniportBlock
.OldPnPDeviceState
= Adapter
->NdisMiniportBlock
.PnPDeviceState
;
1690 Adapter
->NdisMiniportBlock
.PnPDeviceState
= NdisPnPDeviceStarted
;
1692 Timeout
.QuadPart
= (LONGLONG
)Adapter
->NdisMiniportBlock
.CheckForHangSeconds
* -1000000;
1693 KeSetTimerEx(&Adapter
->NdisMiniportBlock
.WakeUpDpcTimer
.Timer
, Timeout
,
1694 Adapter
->NdisMiniportBlock
.CheckForHangSeconds
* 1000,
1695 &Adapter
->NdisMiniportBlock
.WakeUpDpcTimer
.Dpc
);
1697 /* Put adapter in adapter list for this miniport */
1698 ExInterlockedInsertTailList(&Adapter
->NdisMiniportBlock
.DriverHandle
->DeviceList
, &Adapter
->MiniportListEntry
, &Adapter
->NdisMiniportBlock
.DriverHandle
->Lock
);
1700 return STATUS_SUCCESS
;
1707 IN PDEVICE_OBJECT DeviceObject
,
1710 * FUNCTION: Handle the PnP stop device event
1712 * DeviceObejct = Functional Device Object
1713 * Irp = IRP_MN_STOP_DEVICE I/O request packet
1715 * Status of operation
1718 PLOGICAL_ADAPTER Adapter
= (PLOGICAL_ADAPTER
)DeviceObject
->DeviceExtension
;
1721 /* Remove adapter from adapter list for this miniport */
1722 KeAcquireSpinLock(&Adapter
->NdisMiniportBlock
.DriverHandle
->Lock
, &OldIrql
);
1723 RemoveEntryList(&Adapter
->MiniportListEntry
);
1724 KeReleaseSpinLock(&Adapter
->NdisMiniportBlock
.DriverHandle
->Lock
, OldIrql
);
1726 /* Remove adapter from global adapter list */
1727 KeAcquireSpinLock(&AdapterListLock
, &OldIrql
);
1728 RemoveEntryList(&Adapter
->ListEntry
);
1729 KeReleaseSpinLock(&AdapterListLock
, OldIrql
);
1731 (*Adapter
->NdisMiniportBlock
.DriverHandle
->MiniportCharacteristics
.HaltHandler
)(Adapter
);
1733 if (Adapter
->LookaheadBuffer
)
1735 ExFreePool(Adapter
->LookaheadBuffer
);
1736 Adapter
->LookaheadBuffer
= NULL
;
1738 if (Adapter
->NdisMiniportBlock
.AllocatedResources
)
1740 ExFreePool(Adapter
->NdisMiniportBlock
.AllocatedResources
);
1741 Adapter
->NdisMiniportBlock
.AllocatedResources
= NULL
;
1743 if (Adapter
->NdisMiniportBlock
.AllocatedResourcesTranslated
)
1745 ExFreePool(Adapter
->NdisMiniportBlock
.AllocatedResourcesTranslated
);
1746 Adapter
->NdisMiniportBlock
.AllocatedResourcesTranslated
= NULL
;
1749 Adapter
->NdisMiniportBlock
.OldPnPDeviceState
= Adapter
->NdisMiniportBlock
.PnPDeviceState
;
1750 Adapter
->NdisMiniportBlock
.PnPDeviceState
= NdisPnPDeviceStopped
;
1752 KeCancelTimer(&Adapter
->NdisMiniportBlock
.WakeUpDpcTimer
.Timer
);
1754 return STATUS_SUCCESS
;
1761 IN PDEVICE_OBJECT DeviceObject
,
1764 PIO_STACK_LOCATION Stack
= IoGetCurrentIrpStackLocation(Irp
);
1765 PLOGICAL_ADAPTER Adapter
= (PLOGICAL_ADAPTER
)DeviceObject
->DeviceExtension
;
1768 switch (Stack
->MinorFunction
)
1770 case IRP_MN_START_DEVICE
:
1771 Status
= NdisIForwardIrpAndWait(Adapter
, Irp
);
1772 if (NT_SUCCESS(Status
) && NT_SUCCESS(Irp
->IoStatus
.Status
))
1774 Status
= NdisIPnPStartDevice(DeviceObject
, Irp
);
1776 Irp
->IoStatus
.Status
= Status
;
1777 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
1780 case IRP_MN_STOP_DEVICE
:
1781 Status
= NdisIForwardIrpAndWait(Adapter
, Irp
);
1782 if (NT_SUCCESS(Status
) && NT_SUCCESS(Irp
->IoStatus
.Status
))
1784 Status
= NdisIPnPStopDevice(DeviceObject
, Irp
);
1786 Irp
->IoStatus
.Status
= Status
;
1787 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
1790 case IRP_MN_QUERY_DEVICE_RELATIONS
:
1791 Status
= STATUS_NOT_SUPPORTED
;
1792 Irp
->IoStatus
.Status
= Status
;
1793 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
1797 IoSkipCurrentIrpStackLocation(Irp
);
1798 Status
= IoCallDriver(Adapter
->NdisMiniportBlock
.NextDeviceObject
, Irp
);
1809 IN PDRIVER_OBJECT DriverObject
,
1810 IN PDEVICE_OBJECT PhysicalDeviceObject
)
1812 * FUNCTION: Create a device for an adapter found using PnP
1814 * DriverObject = Pointer to the miniport driver object
1815 * PhysicalDeviceObject = Pointer to the PDO for our adapter
1818 static const WCHAR ClassKeyName
[] = {'C','l','a','s','s','\\'};
1819 static const WCHAR LinkageKeyName
[] = {'\\','L','i','n','k','a','g','e',0};
1820 PNDIS_M_DRIVER_BLOCK Miniport
;
1821 PNDIS_M_DRIVER_BLOCK
*MiniportPtr
;
1822 WCHAR
*LinkageKeyBuffer
;
1823 ULONG DriverKeyLength
;
1824 RTL_QUERY_REGISTRY_TABLE QueryTable
[2];
1825 UNICODE_STRING ExportName
;
1826 PDEVICE_OBJECT DeviceObject
;
1827 PLOGICAL_ADAPTER Adapter
;
1831 * Gain the access to the miniport data structure first.
1834 MiniportPtr
= IoGetDriverObjectExtension(DriverObject
, (PVOID
)TAG('D','I','M','N'));
1835 if (MiniportPtr
== NULL
)
1837 NDIS_DbgPrint(DEBUG_MINIPORT
, ("Can't get driver object extension.\n"));
1838 return STATUS_UNSUCCESSFUL
;
1840 Miniport
= *MiniportPtr
;
1843 * Get name of the Linkage registry key for our adapter. It's located under
1844 * the driver key for our driver and so we have basicly two ways to do it.
1845 * Either we can use IoOpenDriverRegistryKey or compose it using information
1846 * gathered by IoGetDeviceProperty. I choosed the second because
1847 * IoOpenDriverRegistryKey wasn't implemented at the time of writing.
1850 Status
= IoGetDeviceProperty(PhysicalDeviceObject
, DevicePropertyDriverKeyName
,
1851 0, NULL
, &DriverKeyLength
);
1852 if (Status
!= STATUS_BUFFER_TOO_SMALL
&& Status
!= STATUS_BUFFER_OVERFLOW
&& Status
!= STATUS_SUCCESS
)
1854 NDIS_DbgPrint(DEBUG_MINIPORT
, ("Can't get miniport driver key length.\n"));
1858 LinkageKeyBuffer
= ExAllocatePool(PagedPool
, DriverKeyLength
+
1859 sizeof(ClassKeyName
) + sizeof(LinkageKeyName
));
1860 if (LinkageKeyBuffer
== NULL
)
1862 NDIS_DbgPrint(DEBUG_MINIPORT
, ("Can't allocate memory for driver key name.\n"));
1863 return STATUS_INSUFFICIENT_RESOURCES
;
1866 Status
= IoGetDeviceProperty(PhysicalDeviceObject
, DevicePropertyDriverKeyName
,
1867 DriverKeyLength
, LinkageKeyBuffer
+
1868 (sizeof(ClassKeyName
) / sizeof(WCHAR
)),
1870 if (!NT_SUCCESS(Status
))
1872 NDIS_DbgPrint(DEBUG_MINIPORT
, ("Can't get miniport driver key.\n"));
1873 ExFreePool(LinkageKeyBuffer
);
1877 /* Compose the linkage key name. */
1878 RtlCopyMemory(LinkageKeyBuffer
, ClassKeyName
, sizeof(ClassKeyName
));
1879 RtlCopyMemory(LinkageKeyBuffer
+ ((sizeof(ClassKeyName
) + DriverKeyLength
) /
1880 sizeof(WCHAR
)) - 1, LinkageKeyName
, sizeof(LinkageKeyName
));
1882 NDIS_DbgPrint(DEBUG_MINIPORT
, ("LinkageKey: %S.\n", LinkageKeyBuffer
));
1885 * Now open the linkage key and read the "Export" and "RootDevice" values
1886 * which contains device name and root service respectively.
1889 RtlZeroMemory(QueryTable
, sizeof(QueryTable
));
1890 RtlInitUnicodeString(&ExportName
, NULL
);
1891 QueryTable
[0].Flags
= RTL_QUERY_REGISTRY_REQUIRED
| RTL_QUERY_REGISTRY_DIRECT
;
1892 QueryTable
[0].Name
= L
"Export";
1893 QueryTable
[0].EntryContext
= &ExportName
;
1895 Status
= RtlQueryRegistryValues(RTL_REGISTRY_CONTROL
, LinkageKeyBuffer
,
1896 QueryTable
, NULL
, NULL
);
1897 ExFreePool(LinkageKeyBuffer
);
1898 if (!NT_SUCCESS(Status
))
1900 NDIS_DbgPrint(DEBUG_MINIPORT
, ("Can't get miniport device name. (%x)\n", Status
));
1905 * Create the device object.
1908 NDIS_DbgPrint(MAX_TRACE
, ("creating device %wZ\n", &ExportName
));
1910 Status
= IoCreateDevice(Miniport
->DriverObject
, sizeof(LOGICAL_ADAPTER
),
1911 &ExportName
, FILE_DEVICE_PHYSICAL_NETCARD
,
1912 0, FALSE
, &DeviceObject
);
1913 if (!NT_SUCCESS(Status
))
1915 NDIS_DbgPrint(MIN_TRACE
, ("Could not create device object.\n"));
1916 RtlFreeUnicodeString(&ExportName
);
1921 * Initialize the adapter structure.
1924 Adapter
= (PLOGICAL_ADAPTER
)DeviceObject
->DeviceExtension
;
1925 KeInitializeSpinLock(&Adapter
->NdisMiniportBlock
.Lock
);
1926 InitializeListHead(&Adapter
->ProtocolListHead
);
1927 Adapter
->NdisMiniportBlock
.DriverHandle
= Miniport
;
1929 Adapter
->NdisMiniportBlock
.MiniportName
= ExportName
;
1931 Adapter
->NdisMiniportBlock
.DeviceObject
= DeviceObject
;
1932 Adapter
->NdisMiniportBlock
.PhysicalDeviceObject
= PhysicalDeviceObject
;
1933 Adapter
->NdisMiniportBlock
.NextDeviceObject
=
1934 IoAttachDeviceToDeviceStack(Adapter
->NdisMiniportBlock
.DeviceObject
,
1935 PhysicalDeviceObject
);
1937 Adapter
->NdisMiniportBlock
.OldPnPDeviceState
= 0;
1938 Adapter
->NdisMiniportBlock
.PnPDeviceState
= NdisPnPDeviceAdded
;
1940 KeInitializeTimer(&Adapter
->NdisMiniportBlock
.WakeUpDpcTimer
.Timer
);
1941 KeInitializeDpc(&Adapter
->NdisMiniportBlock
.WakeUpDpcTimer
.Dpc
, MiniportHangDpc
, Adapter
);
1942 KeInitializeDpc(&Adapter
->NdisMiniportBlock
.DeferredDpc
, MiniportDpc
, Adapter
);
1944 DeviceObject
->Flags
&= ~DO_DEVICE_INITIALIZING
;
1946 return STATUS_SUCCESS
;
1955 NdisMRegisterMiniport(
1956 IN NDIS_HANDLE NdisWrapperHandle
,
1957 IN PNDIS_MINIPORT_CHARACTERISTICS MiniportCharacteristics
,
1958 IN UINT CharacteristicsLength
)
1960 * FUNCTION: Registers a miniport's MiniportXxx entry points with the NDIS library
1962 * NdisWrapperHandle = Pointer to handle returned by NdisMInitializeWrapper
1963 * MiniportCharacteristics = Pointer to a buffer with miniport characteristics
1964 * CharacteristicsLength = Number of bytes in characteristics buffer
1966 * Status of operation
1970 PNDIS_M_DRIVER_BLOCK Miniport
= GET_MINIPORT_DRIVER(NdisWrapperHandle
);
1971 PNDIS_M_DRIVER_BLOCK
*MiniportPtr
;
1974 NDIS_DbgPrint(MAX_TRACE
, ("Called.\n"));
1976 switch (MiniportCharacteristics
->MajorNdisVersion
)
1979 MinSize
= sizeof(NDIS30_MINIPORT_CHARACTERISTICS
);
1983 MinSize
= sizeof(NDIS40_MINIPORT_CHARACTERISTICS
);
1987 MinSize
= sizeof(NDIS50_MINIPORT_CHARACTERISTICS
);
1991 NDIS_DbgPrint(DEBUG_MINIPORT
, ("Bad miniport characteristics version.\n"));
1992 return NDIS_STATUS_BAD_VERSION
;
1995 if (CharacteristicsLength
< MinSize
)
1997 NDIS_DbgPrint(DEBUG_MINIPORT
, ("Bad miniport characteristics.\n"));
1998 return NDIS_STATUS_BAD_CHARACTERISTICS
;
2001 /* Check if mandatory MiniportXxx functions are specified */
2002 if ((!MiniportCharacteristics
->HaltHandler
) ||
2003 (!MiniportCharacteristics
->InitializeHandler
)||
2004 (!MiniportCharacteristics
->QueryInformationHandler
) ||
2005 (!MiniportCharacteristics
->ResetHandler
) ||
2006 (!MiniportCharacteristics
->SetInformationHandler
))
2008 NDIS_DbgPrint(DEBUG_MINIPORT
, ("Bad miniport characteristics.\n"));
2009 return NDIS_STATUS_BAD_CHARACTERISTICS
;
2012 if (MiniportCharacteristics
->MajorNdisVersion
== 0x03)
2014 if (!MiniportCharacteristics
->SendHandler
)
2016 NDIS_DbgPrint(DEBUG_MINIPORT
, ("Bad miniport characteristics.\n"));
2017 return NDIS_STATUS_BAD_CHARACTERISTICS
;
2020 else if (MiniportCharacteristics
->MajorNdisVersion
>= 0x04)
2023 if ((!MiniportCharacteristics
->SendHandler
) &&
2024 (!MiniportCharacteristics
->SendPacketsHandler
))
2026 NDIS_DbgPrint(DEBUG_MINIPORT
, ("Bad miniport characteristics.\n"));
2027 return NDIS_STATUS_BAD_CHARACTERISTICS
;
2031 /* TODO: verify NDIS5 and NDIS5.1 */
2033 RtlCopyMemory(&Miniport
->MiniportCharacteristics
, MiniportCharacteristics
, MinSize
);
2036 * NOTE: This is VERY unoptimal! Should we store the NDIS_M_DRIVER_BLOCK
2037 * structure in the driver extension or what?
2040 Status
= IoAllocateDriverObjectExtension(Miniport
->DriverObject
, (PVOID
)TAG('D','I','M','N'),
2041 sizeof(PNDIS_M_DRIVER_BLOCK
), (PVOID
*)&MiniportPtr
);
2042 if (!NT_SUCCESS(Status
))
2044 NDIS_DbgPrint(DEBUG_MINIPORT
, ("Can't allocate driver object extension.\n"));
2045 return NDIS_STATUS_RESOURCES
;
2048 *MiniportPtr
= Miniport
;
2050 Miniport
->DriverObject
->MajorFunction
[IRP_MJ_PNP
] = NdisIDispatchPnp
;
2051 Miniport
->DriverObject
->DriverExtension
->AddDevice
= NdisIAddDevice
;
2053 return NDIS_STATUS_SUCCESS
;
2060 #undef NdisMResetComplete
2064 IN NDIS_HANDLE MiniportAdapterHandle
,
2065 IN NDIS_STATUS Status
,
2066 IN BOOLEAN AddressingReset
)
2068 MiniResetComplete(MiniportAdapterHandle
, Status
, AddressingReset
);
2075 #undef NdisMSendComplete
2079 IN NDIS_HANDLE MiniportAdapterHandle
,
2080 IN PNDIS_PACKET Packet
,
2081 IN NDIS_STATUS Status
)
2083 * FUNCTION: Forwards a message to the initiating protocol saying
2084 * that a packet was handled
2086 * NdisAdapterHandle = Handle input to MiniportInitialize
2087 * Packet = Pointer to NDIS packet that was sent
2088 * Status = Status of send operation
2091 MiniSendComplete(MiniportAdapterHandle
, Packet
, Status
);
2098 #undef NdisMSendResourcesAvailable
2101 NdisMSendResourcesAvailable(
2102 IN NDIS_HANDLE MiniportAdapterHandle
)
2104 MiniSendResourcesAvailable(MiniportAdapterHandle
);
2111 #undef NdisMTransferDataComplete
2114 NdisMTransferDataComplete(
2115 IN NDIS_HANDLE MiniportAdapterHandle
,
2116 IN PNDIS_PACKET Packet
,
2117 IN NDIS_STATUS Status
,
2118 IN UINT BytesTransferred
)
2120 MiniTransferDataComplete(MiniportAdapterHandle
, Packet
, Status
, BytesTransferred
);
2127 #undef NdisMSetInformationComplete
2130 NdisMSetInformationComplete(
2131 IN NDIS_HANDLE MiniportAdapterHandle
,
2132 IN NDIS_STATUS Status
)
2134 PLOGICAL_ADAPTER Adapter
=
2135 (PLOGICAL_ADAPTER
)MiniportAdapterHandle
;
2138 KeRaiseIrql(DISPATCH_LEVEL
, &OldIrql
);
2139 (Adapter
->NdisMiniportBlock
.SetCompleteHandler
)(MiniportAdapterHandle
, Status
);
2140 KeAcquireSpinLockAtDpcLevel(&Adapter
->NdisMiniportBlock
.Lock
);
2141 Adapter
->MiniportBusy
= FALSE
;
2142 KeReleaseSpinLockFromDpcLevel(&Adapter
->NdisMiniportBlock
.Lock
);
2143 KeLowerIrql(OldIrql
);
2150 #undef NdisMSetAttributes
2154 IN NDIS_HANDLE MiniportAdapterHandle
,
2155 IN NDIS_HANDLE MiniportAdapterContext
,
2156 IN BOOLEAN BusMaster
,
2157 IN NDIS_INTERFACE_TYPE AdapterType
)
2159 * FUNCTION: Informs the NDIS library of significant features of the caller's NIC
2161 * MiniportAdapterHandle = Handle input to MiniportInitialize
2162 * MiniportAdapterContext = Pointer to context information
2163 * BusMaster = Specifies TRUE if the caller's NIC is a busmaster DMA device
2164 * AdapterType = Specifies the I/O bus interface of the caller's NIC
2167 NDIS_DbgPrint(MAX_TRACE
, ("Called.\n"));
2168 NdisMSetAttributesEx(MiniportAdapterHandle
, MiniportAdapterContext
, 0,
2169 BusMaster
? NDIS_ATTRIBUTE_BUS_MASTER
: 0,
2179 NdisMSetAttributesEx(
2180 IN NDIS_HANDLE MiniportAdapterHandle
,
2181 IN NDIS_HANDLE MiniportAdapterContext
,
2182 IN UINT CheckForHangTimeInSeconds OPTIONAL
,
2183 IN ULONG AttributeFlags
,
2184 IN NDIS_INTERFACE_TYPE AdapterType
)
2186 * FUNCTION: Informs the NDIS library of significant features of the caller's NIC
2188 * MiniportAdapterHandle = Handle input to MiniportInitialize
2189 * MiniportAdapterContext = Pointer to context information
2190 * CheckForHangTimeInSeconds = Specifies interval in seconds at which
2191 * MiniportCheckForHang should be called
2192 * AttributeFlags = Bitmask that indicates specific attributes
2193 * AdapterType = Specifies the I/O bus interface of the caller's NIC
2196 PLOGICAL_ADAPTER Adapter
= GET_LOGICAL_ADAPTER(MiniportAdapterHandle
);
2198 NDIS_DbgPrint(MAX_TRACE
, ("Called.\n"));
2200 Adapter
->NdisMiniportBlock
.MiniportAdapterContext
= MiniportAdapterContext
;
2201 Adapter
->NdisMiniportBlock
.Flags
= AttributeFlags
;
2202 Adapter
->NdisMiniportBlock
.AdapterType
= AdapterType
;
2203 if (CheckForHangTimeInSeconds
> 0)
2204 Adapter
->NdisMiniportBlock
.CheckForHangSeconds
= CheckForHangTimeInSeconds
;
2205 if (AttributeFlags
& NDIS_ATTRIBUTE_INTERMEDIATE_DRIVER
)
2206 NDIS_DbgPrint(MAX_TRACE
, ("Intermediate drivers not supported yet.\n"));
2216 IN ULONG MicrosecondsToSleep
)
2218 * FUNCTION: delay the thread's execution for MicrosecondsToSleep
2220 * MicrosecondsToSleep: duh...
2222 * - Because this is a blocking call, current IRQL must be < DISPATCH_LEVEL
2226 LARGE_INTEGER DueTime
;
2230 DueTime
.QuadPart
= (-1) * 10 * MicrosecondsToSleep
;
2232 KeInitializeTimer(&Timer
);
2233 KeSetTimer(&Timer
, DueTime
, 0);
2234 KeWaitForSingleObject(&Timer
, Executive
, KernelMode
, FALSE
, 0);
2243 NdisMSynchronizeWithInterrupt(
2244 IN PNDIS_MINIPORT_INTERRUPT Interrupt
,
2245 IN PVOID SynchronizeFunction
,
2246 IN PVOID SynchronizeContext
)
2248 return(KeSynchronizeExecution(Interrupt
->InterruptObject
,
2249 (PKSYNCHRONIZE_ROUTINE
)SynchronizeFunction
,
2250 SynchronizeContext
));
2260 IN NDIS_HANDLE LogHandle
,
2262 IN UINT LogBufferSize
)
2264 PUCHAR Buffer
= LogBuffer
;
2268 for (i
= 0; i
< LogBufferSize
; i
+= 16)
2270 DbgPrint("%08x |", i
);
2271 for (j
= 0; j
< 16; j
++)
2274 if (idx
< LogBufferSize
)
2275 DbgPrint(" %02x", Buffer
[idx
]);
2280 for (j
= 0; j
< 16; j
++)
2283 if (idx
== LogBufferSize
)
2285 if (Buffer
[idx
] >= ' ') /* FIXME: not portable! replace by if (isprint(Buffer[idx])) ? */
2286 DbgPrint("%c", Buffer
[idx
]);
2293 return NDIS_STATUS_FAILURE
;
2302 NdisTerminateWrapper(
2303 IN NDIS_HANDLE NdisWrapperHandle
,
2304 IN PVOID SystemSpecific
)
2306 * FUNCTION: Releases resources allocated by a call to NdisInitializeWrapper
2308 * NdisWrapperHandle = Handle returned by NdisInitializeWrapper (NDIS_M_DRIVER_BLOCK)
2309 * SystemSpecific = Always NULL
2312 PNDIS_M_DRIVER_BLOCK Miniport
= GET_MINIPORT_DRIVER(NdisWrapperHandle
);
2314 NDIS_DbgPrint(MAX_TRACE
, ("Called.\n"));
2316 ExFreePool(Miniport
->RegistryPath
->Buffer
);
2317 ExFreePool(Miniport
->RegistryPath
);
2318 ExFreePool(Miniport
);