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
));
187 ("XXX (%x) %x %x %x %x %x %x %x XXX\n",
188 *AdapterBinding
->ProtocolBinding
->Chars
.ReceiveHandler
,
189 AdapterBinding
->NdisOpenBlock
.ProtocolBindingContext
,
197 /* call the receive handler */
198 (*AdapterBinding
->ProtocolBinding
->Chars
.ReceiveHandler
)(
199 AdapterBinding
->NdisOpenBlock
.ProtocolBindingContext
,
207 CurrentEntry
= CurrentEntry
->Flink
;
210 KeReleaseSpinLock(&Adapter
->NdisMiniportBlock
.Lock
, OldIrql
);
212 NDIS_DbgPrint(MAX_TRACE
, ("Leaving.\n"));
217 MiniIndicateReceivePacket(
218 IN NDIS_HANDLE MiniportAdapterHandle
,
219 IN PPNDIS_PACKET PacketArray
,
220 IN UINT NumberOfPackets
)
222 * FUNCTION: receives miniport packet array indications
224 * MiniportAdapterHandle: Miniport handle for the adapter
225 * PacketArray: pointer to a list of packet pointers to indicate
226 * NumberOfPackets: number of packets to indicate
230 PLOGICAL_ADAPTER Adapter
= MiniportAdapterHandle
;
231 PLIST_ENTRY CurrentEntry
;
232 PADAPTER_BINDING AdapterBinding
;
236 KeAcquireSpinLock(&Adapter
->NdisMiniportBlock
.Lock
, &OldIrql
);
238 CurrentEntry
= Adapter
->ProtocolListHead
.Flink
;
240 while (CurrentEntry
!= &Adapter
->ProtocolListHead
)
242 AdapterBinding
= CONTAINING_RECORD(CurrentEntry
, ADAPTER_BINDING
, AdapterListEntry
);
244 if (AdapterBinding
->ProtocolBinding
->Chars
.ReceivePacketHandler
)
246 for (i
= 0; i
< NumberOfPackets
; i
++)
248 (*AdapterBinding
->ProtocolBinding
->Chars
.ReceivePacketHandler
)(
249 AdapterBinding
->NdisOpenBlock
.ProtocolBindingContext
,
254 CurrentEntry
= CurrentEntry
->Flink
;
257 KeReleaseSpinLock(&Adapter
->NdisMiniportBlock
.Lock
, OldIrql
);
263 IN NDIS_HANDLE MiniportAdapterHandle
,
264 IN NDIS_STATUS Status
,
265 IN BOOLEAN AddressingReset
)
267 PLOGICAL_ADAPTER Adapter
= MiniportAdapterHandle
;
269 NDIS_DbgPrint(MIN_TRACE
, ("FIXME: MiniResetComplete is partially implemented\n"));
270 NdisMIndicateStatus(Adapter
, NDIS_STATUS_RESET_END
, NULL
, 0);
271 KeAcquireSpinLock(&Adapter
->NdisMiniportBlock
.Lock
, &OldIrql
);
272 Adapter
->MiniportBusy
= FALSE
;
273 KeReleaseSpinLock(&Adapter
->NdisMiniportBlock
.Lock
, OldIrql
);
280 IN PNDIS_HANDLE MiniportAdapterHandle
,
281 IN PNDIS_REQUEST Request
,
282 IN NDIS_STATUS Status
)
284 PLOGICAL_ADAPTER Adapter
= (PLOGICAL_ADAPTER
)MiniportAdapterHandle
;
285 PNDIS_REQUEST_MAC_BLOCK MacBlock
= (PNDIS_REQUEST_MAC_BLOCK
)Request
->MacReserved
;
288 NDIS_DbgPrint(DEBUG_MINIPORT
, ("Called.\n"));
290 KeRaiseIrql(DISPATCH_LEVEL
, &OldIrql
);
291 if( MacBlock
->Binding
->RequestCompleteHandler
) {
292 (*MacBlock
->Binding
->RequestCompleteHandler
)(
293 MacBlock
->Binding
->ProtocolBindingContext
,
297 KeAcquireSpinLockAtDpcLevel(&Adapter
->NdisMiniportBlock
.Lock
);
298 Adapter
->MiniportBusy
= FALSE
;
299 KeReleaseSpinLockFromDpcLevel(&Adapter
->NdisMiniportBlock
.Lock
);
300 KeLowerIrql(OldIrql
);
305 IN NDIS_HANDLE MiniportAdapterHandle
,
306 IN PNDIS_PACKET Packet
,
307 IN NDIS_STATUS Status
)
309 * FUNCTION: Forwards a message to the initiating protocol saying
310 * that a packet was handled
312 * NdisAdapterHandle = Handle input to MiniportInitialize
313 * Packet = Pointer to NDIS packet that was sent
314 * Status = Status of send operation
317 PLOGICAL_ADAPTER Adapter
= MiniportAdapterHandle
;
318 PADAPTER_BINDING AdapterBinding
;
321 NDIS_DbgPrint(DEBUG_MINIPORT
, ("Called.\n"));
323 AdapterBinding
= (PADAPTER_BINDING
)Packet
->Reserved
[0];
325 KeRaiseIrql(DISPATCH_LEVEL
, &OldIrql
);
326 (*AdapterBinding
->ProtocolBinding
->Chars
.SendCompleteHandler
)(
327 AdapterBinding
->NdisOpenBlock
.ProtocolBindingContext
,
330 KeAcquireSpinLockAtDpcLevel(&Adapter
->NdisMiniportBlock
.Lock
);
331 Adapter
->MiniportBusy
= FALSE
;
332 KeReleaseSpinLockFromDpcLevel(&Adapter
->NdisMiniportBlock
.Lock
);
333 KeLowerIrql(OldIrql
);
338 MiniSendResourcesAvailable(
339 IN NDIS_HANDLE MiniportAdapterHandle
)
348 MiniTransferDataComplete(
349 IN NDIS_HANDLE MiniportAdapterHandle
,
350 IN PNDIS_PACKET Packet
,
351 IN NDIS_STATUS Status
,
352 IN UINT BytesTransferred
)
354 PLOGICAL_ADAPTER Adapter
= MiniportAdapterHandle
;
355 PADAPTER_BINDING AdapterBinding
;
358 NDIS_DbgPrint(DEBUG_MINIPORT
, ("Called.\n"));
360 AdapterBinding
= (PADAPTER_BINDING
)Packet
->Reserved
[0];
362 KeRaiseIrql(DISPATCH_LEVEL
, &OldIrql
);
363 (*AdapterBinding
->ProtocolBinding
->Chars
.SendCompleteHandler
)(
364 AdapterBinding
->NdisOpenBlock
.ProtocolBindingContext
,
367 KeAcquireSpinLockAtDpcLevel(&Adapter
->NdisMiniportBlock
.Lock
);
368 Adapter
->MiniportBusy
= FALSE
;
369 KeReleaseSpinLockFromDpcLevel(&Adapter
->NdisMiniportBlock
.Lock
);
370 KeLowerIrql(OldIrql
);
375 MiniAdapterHasAddress(
376 PLOGICAL_ADAPTER Adapter
,
379 * FUNCTION: Determines whether a packet has the same destination address as an adapter
381 * Adapter = Pointer to logical adapter object
382 * Packet = Pointer to NDIS packet
384 * TRUE if the destination address is that of the adapter, FALSE if not
390 PNDIS_BUFFER NdisBuffer
;
393 NDIS_DbgPrint(DEBUG_MINIPORT
, ("Called.\n"));
398 NDIS_DbgPrint(MID_TRACE
, ("Adapter object was null\n"));
404 NDIS_DbgPrint(MID_TRACE
, ("Packet was null\n"));
409 NdisQueryPacket(Packet
, NULL
, NULL
, &NdisBuffer
, NULL
);
413 NDIS_DbgPrint(MID_TRACE
, ("Packet contains no buffers.\n"));
417 NdisQueryBuffer(NdisBuffer
, (PVOID
)&Start2
, &BufferLength
);
419 /* FIXME: Should handle fragmented packets */
421 switch (Adapter
->NdisMiniportBlock
.MediaType
)
423 case NdisMedium802_3
:
424 Length
= ETH_LENGTH_OF_ADDRESS
;
425 /* Destination address is the first field */
429 NDIS_DbgPrint(MIN_TRACE
, ("Adapter has unsupported media type (0x%X).\n", Adapter
->NdisMiniportBlock
.MediaType
));
433 if (BufferLength
< Length
)
435 NDIS_DbgPrint(MID_TRACE
, ("Buffer is too small.\n"));
439 Start1
= (PUCHAR
)&Adapter
->Address
;
440 NDIS_DbgPrint(MAX_TRACE
, ("packet address: %x:%x:%x:%x:%x:%x adapter address: %x:%x:%x:%x:%x:%x\n",
441 *((char *)Start1
), *(((char *)Start1
)+1), *(((char *)Start1
)+2), *(((char *)Start1
)+3), *(((char *)Start1
)+4), *(((char *)Start1
)+5),
442 *((char *)Start2
), *(((char *)Start2
)+1), *(((char *)Start2
)+2), *(((char *)Start2
)+3), *(((char *)Start2
)+4), *(((char *)Start2
)+5))
445 return (RtlCompareMemory((PVOID
)Start1
, (PVOID
)Start2
, Length
) == Length
);
451 PNDIS_STRING AdapterName
)
453 * FUNCTION: Finds an adapter object by name
455 * AdapterName = Pointer to name of adapter
457 * Pointer to logical adapter object, or NULL if none was found.
458 * If found, the adapter is referenced for the caller. The caller
459 * is responsible for dereferencing after use
463 PLIST_ENTRY CurrentEntry
;
464 PLOGICAL_ADAPTER Adapter
= 0;
468 NDIS_DbgPrint(DEBUG_MINIPORT
, ("Called.\n"));
470 if(IsListEmpty(&AdapterListHead
))
472 NDIS_DbgPrint(DEBUG_MINIPORT
, ("No registered miniports for protocol to bind to\n"));
476 KeAcquireSpinLock(&AdapterListLock
, &OldIrql
);
478 CurrentEntry
= AdapterListHead
.Flink
;
480 while (CurrentEntry
!= &AdapterListHead
)
482 Adapter
= CONTAINING_RECORD(CurrentEntry
, LOGICAL_ADAPTER
, ListEntry
);
486 NDIS_DbgPrint(DEBUG_MINIPORT
, ("Examining adapter 0x%lx\n", Adapter
));
487 NDIS_DbgPrint(DEBUG_MINIPORT
, ("AdapterName = %wZ\n", AdapterName
));
488 NDIS_DbgPrint(DEBUG_MINIPORT
, ("DeviceName = %wZ\n", &Adapter
->NdisMiniportBlock
.MiniportName
));
490 if (RtlCompareUnicodeString(AdapterName
, &Adapter
->NdisMiniportBlock
.MiniportName
, TRUE
) == 0)
496 CurrentEntry
= CurrentEntry
->Flink
;
499 KeReleaseSpinLock(&AdapterListLock
, OldIrql
);
503 NDIS_DbgPrint(DEBUG_MINIPORT
, ("Leaving. Adapter found at 0x%x\n", Adapter
));
507 NDIS_DbgPrint(DEBUG_MINIPORT
, ("Leaving (adapter not found).\n"));
515 MiniQueryInformation(
516 PLOGICAL_ADAPTER Adapter
,
522 * FUNCTION: Queries a logical adapter for properties
524 * Adapter = Pointer to the logical adapter object to query
525 * Oid = Specifies the Object ID to query for
526 * Size = Size of the passed buffer
527 * Buffer = Buffer for the output
528 * BytesWritten = Address of buffer to place number of bytes written
530 * If the specified buffer is too small, a new buffer is allocated,
531 * and the query is attempted again
533 * Status of operation
535 * Is there any way to use the buffer provided by the protocol?
538 NDIS_STATUS NdisStatus
;
542 NDIS_DbgPrint(DEBUG_MINIPORT
, ("Called.\n"));
544 /* call the miniport's queryinfo handler */
545 KeRaiseIrql(DISPATCH_LEVEL
, &OldIrql
);
546 NdisStatus
= (*Adapter
->NdisMiniportBlock
.DriverHandle
->MiniportCharacteristics
.QueryInformationHandler
)(
547 Adapter
->NdisMiniportBlock
.MiniportAdapterContext
,
553 KeLowerIrql(OldIrql
);
555 /* FIXME: Wait in pending case! */
561 MiniCheckForHang( PLOGICAL_ADAPTER Adapter
)
563 * FUNCTION: Checks to see if the miniport is hung
565 * Adapter = Pointer to the logical adapter object
567 * TRUE if the miniport is hung
568 * FALSE if the miniport is not hung
574 KeRaiseIrql(DISPATCH_LEVEL
, &OldIrql
);
575 if (Adapter
->NdisMiniportBlock
.DriverHandle
->MiniportCharacteristics
.CheckForHangHandler
)
576 Ret
= (*Adapter
->NdisMiniportBlock
.DriverHandle
->MiniportCharacteristics
.CheckForHangHandler
)(
577 Adapter
->NdisMiniportBlock
.MiniportAdapterContext
);
578 KeLowerIrql(OldIrql
);
585 PLOGICAL_ADAPTER Adapter
,
586 PBOOLEAN AddressingReset
)
588 * FUNCTION: Resets the miniport
590 * Adapter = Pointer to the logical adapter object
591 * AddressingReset = Set to TRUE if we need to call MiniportSetInformation later
593 * Status of the operation
599 if (Adapter
->MiniportBusy
) {
600 KeAcquireSpinLock(&Adapter
->NdisMiniportBlock
.Lock
, &OldIrql
);
601 MiniQueueWorkItem(Adapter
, NdisWorkItemResetRequested
, NULL
);
602 KeReleaseSpinLock(&Adapter
->NdisMiniportBlock
.Lock
, OldIrql
);
603 return NDIS_STATUS_PENDING
;
606 NdisMIndicateStatus(Adapter
, NDIS_STATUS_RESET_START
, NULL
, 0);
607 NdisMIndicateStatusComplete(Adapter
);
609 KeRaiseIrql(DISPATCH_LEVEL
, &OldIrql
);
610 Status
= (*Adapter
->NdisMiniportBlock
.DriverHandle
->MiniportCharacteristics
.ResetHandler
)(
611 Adapter
->NdisMiniportBlock
.MiniportAdapterContext
,
613 KeLowerIrql(OldIrql
);
615 if (Status
!= NDIS_STATUS_PENDING
) {
616 NdisMIndicateStatus(Adapter
, NDIS_STATUS_RESET_END
, NULL
, 0);
617 NdisMIndicateStatusComplete(Adapter
);
619 KeAcquireSpinLock(&Adapter
->NdisMiniportBlock
.Lock
, &OldIrql
);
620 Adapter
->MiniportBusy
= TRUE
;
621 KeReleaseSpinLock(&Adapter
->NdisMiniportBlock
.Lock
, OldIrql
);
630 PVOID DeferredContext
,
631 PVOID SystemArgument1
,
632 PVOID SystemArgument2
)
634 PLOGICAL_ADAPTER Adapter
= DeferredContext
;
635 BOOLEAN AddressingReset
= FALSE
;
638 if (MiniCheckForHang(Adapter
)) {
639 NDIS_DbgPrint(MIN_TRACE
, ("Miniport detected adapter hang\n"));
640 MiniReset(Adapter
, &AddressingReset
);
643 /* FIXME: We should call MiniportSetInformation if AddressingReset is TRUE */
650 PLOGICAL_ADAPTER Adapter
,
651 NDIS_WORK_ITEM_TYPE WorkItemType
,
652 PVOID WorkItemContext
)
654 * FUNCTION: Queues a work item for execution at a later time
656 * Adapter = Pointer to the logical adapter object to queue work item on
657 * WorkItemType = Type of work item to queue
658 * WorkItemContext = Pointer to context information for work item
660 * Adapter lock must be held when called
662 * Status of operation
665 PNDIS_MINIPORT_WORK_ITEM MiniportWorkItem
;
666 PNDIS_WORK_ITEM NdisWorkItem
;
667 PWORK_QUEUE_ITEM WorkQueueItem
;
669 NDIS_DbgPrint(MAX_TRACE
, ("Called.\n"));
672 ASSERT(KeGetCurrentIrql() >= DISPATCH_LEVEL
);
674 MiniportWorkItem
= ExAllocatePool(NonPagedPool
, sizeof(NDIS_MINIPORT_WORK_ITEM
));
675 if (!MiniportWorkItem
)
677 NDIS_DbgPrint(MIN_TRACE
, ("Insufficient resources.\n"));
678 return NDIS_STATUS_RESOURCES
;
681 NdisWorkItem
= ExAllocatePool(NonPagedPool
, sizeof(NDIS_WORK_ITEM
));
684 ExFreePool(MiniportWorkItem
);
685 return NDIS_STATUS_RESOURCES
;
688 MiniportWorkItem
->WorkItemType
= WorkItemType
;
689 MiniportWorkItem
->WorkItemContext
= WorkItemContext
;
691 /* safe due to adapter lock held */
692 MiniportWorkItem
->Link
.Next
= NULL
;
693 if (!Adapter
->WorkQueueHead
)
695 Adapter
->WorkQueueHead
= MiniportWorkItem
;
696 Adapter
->WorkQueueTail
= MiniportWorkItem
;
700 Adapter
->WorkQueueTail
->Link
.Next
= (PSINGLE_LIST_ENTRY
)MiniportWorkItem
;
701 Adapter
->WorkQueueTail
= MiniportWorkItem
;
704 WorkQueueItem
= (PWORK_QUEUE_ITEM
)NdisWorkItem
->WrapperReserved
;
706 NdisWorkItem
->Context
= Adapter
;
708 ExInitializeWorkItem(WorkQueueItem
, MiniportWorker
, NdisWorkItem
);
710 ExQueueWorkItem(WorkQueueItem
, CriticalWorkQueue
);
712 return NDIS_STATUS_SUCCESS
;
719 PLOGICAL_ADAPTER Adapter
,
720 NDIS_WORK_ITEM_TYPE
*WorkItemType
,
721 PVOID
*WorkItemContext
)
723 * FUNCTION: Dequeues a work item from the work queue of a logical adapter
725 * Adapter = Pointer to the logical adapter object to dequeue work item from
726 * AdapterBinding = Address of buffer for adapter binding for this request
727 * WorkItemType = Address of buffer for work item type
728 * WorkItemContext = Address of buffer for pointer to context information
730 * Adapter lock must be held when called
732 * Status of operation
735 PNDIS_MINIPORT_WORK_ITEM MiniportWorkItem
;
736 PNDIS_WORK_ITEM NdisWorkItem
;
737 PWORK_QUEUE_ITEM WorkQueueItem
;
740 NDIS_DbgPrint(MAX_TRACE
, ("Called.\n"));
742 if (Adapter
->MiniportBusy
) {
743 NDIS_DbgPrint(MID_TRACE
, ("Waiting for miniport to become free.\n"));
744 NdisWorkItem
= ExAllocatePool(NonPagedPool
, sizeof(NDIS_WORK_ITEM
));
745 if (!NdisWorkItem
) return NDIS_STATUS_RESOURCES
;
746 WorkQueueItem
= (PWORK_QUEUE_ITEM
)NdisWorkItem
->WrapperReserved
;
747 NdisWorkItem
->Context
= Adapter
;
748 ExInitializeWorkItem(WorkQueueItem
, MiniportWorker
, NdisWorkItem
);
749 ExQueueWorkItem(WorkQueueItem
, CriticalWorkQueue
);
750 return NDIS_STATUS_FAILURE
;
753 MiniportWorkItem
= Adapter
->WorkQueueHead
;
755 if (MiniportWorkItem
)
757 /* safe due to adapter lock held */
758 Adapter
->WorkQueueHead
= (PNDIS_MINIPORT_WORK_ITEM
)MiniportWorkItem
->Link
.Next
;
760 if (MiniportWorkItem
== Adapter
->WorkQueueTail
)
761 Adapter
->WorkQueueTail
= NULL
;
763 *WorkItemType
= MiniportWorkItem
->WorkItemType
;
764 *WorkItemContext
= MiniportWorkItem
->WorkItemContext
;
766 ExFreePool(MiniportWorkItem
);
768 Adapter
->MiniportBusy
= TRUE
;
770 return NDIS_STATUS_SUCCESS
;
773 return NDIS_STATUS_FAILURE
;
779 PLOGICAL_ADAPTER Adapter
,
780 PNDIS_REQUEST NdisRequest
)
782 * FUNCTION: Sends a request to a miniport
784 * AdapterBinding = Pointer to binding used in the request
785 * NdisRequest = Pointer to NDIS request structure describing request
787 * Status of operation
792 NDIS_DbgPrint(DEBUG_MINIPORT
, ("Called.\n"));
794 Adapter
->NdisMiniportBlock
.MediaRequest
= NdisRequest
;
796 KeRaiseIrql(DISPATCH_LEVEL
, &OldIrql
);
797 switch (NdisRequest
->RequestType
)
799 case NdisRequestQueryInformation
:
800 Status
= (*Adapter
->NdisMiniportBlock
.DriverHandle
->MiniportCharacteristics
.QueryInformationHandler
)(
801 Adapter
->NdisMiniportBlock
.MiniportAdapterContext
,
802 NdisRequest
->DATA
.QUERY_INFORMATION
.Oid
,
803 NdisRequest
->DATA
.QUERY_INFORMATION
.InformationBuffer
,
804 NdisRequest
->DATA
.QUERY_INFORMATION
.InformationBufferLength
,
805 (PULONG
)&NdisRequest
->DATA
.QUERY_INFORMATION
.BytesWritten
,
806 (PULONG
)&NdisRequest
->DATA
.QUERY_INFORMATION
.BytesNeeded
);
809 case NdisRequestSetInformation
:
810 Status
= (*Adapter
->NdisMiniportBlock
.DriverHandle
->MiniportCharacteristics
.SetInformationHandler
)(
811 Adapter
->NdisMiniportBlock
.MiniportAdapterContext
,
812 NdisRequest
->DATA
.SET_INFORMATION
.Oid
,
813 NdisRequest
->DATA
.SET_INFORMATION
.InformationBuffer
,
814 NdisRequest
->DATA
.SET_INFORMATION
.InformationBufferLength
,
815 (PULONG
)&NdisRequest
->DATA
.SET_INFORMATION
.BytesRead
,
816 (PULONG
)&NdisRequest
->DATA
.SET_INFORMATION
.BytesNeeded
);
820 Status
= NDIS_STATUS_FAILURE
;
823 if (Status
== NDIS_STATUS_PENDING
) {
824 KeAcquireSpinLockAtDpcLevel(&Adapter
->NdisMiniportBlock
.Lock
);
825 Adapter
->MiniportBusy
= TRUE
;
826 KeReleaseSpinLockFromDpcLevel(&Adapter
->NdisMiniportBlock
.Lock
);
829 KeLowerIrql(OldIrql
);
837 #undef NdisMQueryInformationComplete
840 NdisMQueryInformationComplete(
841 IN NDIS_HANDLE MiniportAdapterHandle
,
842 IN NDIS_STATUS Status
)
844 PLOGICAL_ADAPTER Adapter
=
845 (PLOGICAL_ADAPTER
)MiniportAdapterHandle
;
848 KeRaiseIrql(DISPATCH_LEVEL
, &OldIrql
);
849 if( Adapter
->NdisMiniportBlock
.QueryCompleteHandler
)
850 (Adapter
->NdisMiniportBlock
.QueryCompleteHandler
)(MiniportAdapterHandle
, Status
);
851 KeAcquireSpinLockAtDpcLevel(&Adapter
->NdisMiniportBlock
.Lock
);
852 Adapter
->MiniportBusy
= FALSE
;
853 KeReleaseSpinLockFromDpcLevel(&Adapter
->NdisMiniportBlock
.Lock
);
854 KeLowerIrql(OldIrql
);
857 VOID NTAPI
MiniportWorker(IN PVOID WorkItem
)
859 PNDIS_WORK_ITEM NdisWorkItem
= WorkItem
;
860 PLOGICAL_ADAPTER Adapter
= GET_LOGICAL_ADAPTER(NdisWorkItem
->Context
);
861 KIRQL OldIrql
, RaiseOldIrql
;
862 NDIS_STATUS NdisStatus
;
863 PVOID WorkItemContext
;
864 NDIS_WORK_ITEM_TYPE WorkItemType
;
865 BOOLEAN AddressingReset
;
867 KeAcquireSpinLock(&Adapter
->NdisMiniportBlock
.Lock
, &OldIrql
);
871 (Adapter
, &WorkItemType
, &WorkItemContext
);
873 KeReleaseSpinLock(&Adapter
->NdisMiniportBlock
.Lock
, OldIrql
);
875 if (NdisStatus
== NDIS_STATUS_SUCCESS
)
877 switch (WorkItemType
)
879 case NdisWorkItemSend
:
881 * called by ProSend when protocols want to send packets to the miniport
884 MiniDisplayPacket((PNDIS_PACKET
)WorkItemContext
);
886 if(Adapter
->NdisMiniportBlock
.DriverHandle
->MiniportCharacteristics
.SendPacketsHandler
)
888 if(Adapter
->NdisMiniportBlock
.Flags
& NDIS_ATTRIBUTE_DESERIALIZE
)
890 NDIS_DbgPrint(MAX_TRACE
, ("Calling miniport's SendPackets handler\n"));
891 (*Adapter
->NdisMiniportBlock
.DriverHandle
->MiniportCharacteristics
.SendPacketsHandler
)(
892 Adapter
->NdisMiniportBlock
.MiniportAdapterContext
, (PPNDIS_PACKET
)&WorkItemContext
, 1);
893 NdisStatus
= NDIS_GET_PACKET_STATUS((PNDIS_PACKET
)WorkItemContext
);
897 /* SendPackets is called at DISPATCH_LEVEL for all serialized miniports */
898 KeRaiseIrql(DISPATCH_LEVEL
, &RaiseOldIrql
);
900 NDIS_DbgPrint(MAX_TRACE
, ("Calling miniport's SendPackets handler\n"));
901 (*Adapter
->NdisMiniportBlock
.DriverHandle
->MiniportCharacteristics
.SendPacketsHandler
)(
902 Adapter
->NdisMiniportBlock
.MiniportAdapterContext
, (PPNDIS_PACKET
)&WorkItemContext
, 1);
904 KeLowerIrql(RaiseOldIrql
);
906 NdisStatus
= NDIS_GET_PACKET_STATUS((PNDIS_PACKET
)WorkItemContext
);
907 if( NdisStatus
== NDIS_STATUS_RESOURCES
) {
908 KeAcquireSpinLock(&Adapter
->NdisMiniportBlock
.Lock
, &OldIrql
);
909 MiniQueueWorkItem(Adapter
, WorkItemType
, WorkItemContext
);
910 KeReleaseSpinLock(&Adapter
->NdisMiniportBlock
.Lock
, OldIrql
);
917 if(Adapter
->NdisMiniportBlock
.Flags
& NDIS_ATTRIBUTE_DESERIALIZE
)
919 NDIS_DbgPrint(MAX_TRACE
, ("Calling miniport's Send handler\n"));
920 NdisStatus
= (*Adapter
->NdisMiniportBlock
.DriverHandle
->MiniportCharacteristics
.SendHandler
)(
921 Adapter
->NdisMiniportBlock
.MiniportAdapterContext
, (PNDIS_PACKET
)WorkItemContext
, 0);
922 NDIS_DbgPrint(MAX_TRACE
, ("back from miniport's send handler\n"));
926 /* Send is called at DISPATCH_LEVEL for all serialized miniports */
927 KeRaiseIrql(DISPATCH_LEVEL
, &RaiseOldIrql
);
928 NDIS_DbgPrint(MAX_TRACE
, ("Calling miniport's Send handler\n"));
929 NdisStatus
= (*Adapter
->NdisMiniportBlock
.DriverHandle
->MiniportCharacteristics
.SendHandler
)(
930 Adapter
->NdisMiniportBlock
.MiniportAdapterContext
, (PNDIS_PACKET
)WorkItemContext
, 0);
931 NDIS_DbgPrint(MAX_TRACE
, ("back from miniport's send handler\n"));
932 KeLowerIrql(RaiseOldIrql
);
933 if( NdisStatus
== NDIS_STATUS_RESOURCES
) {
934 KeAcquireSpinLock(&Adapter
->NdisMiniportBlock
.Lock
, &OldIrql
);
935 MiniQueueWorkItem(Adapter
, WorkItemType
, WorkItemContext
);
936 KeReleaseSpinLock(&Adapter
->NdisMiniportBlock
.Lock
, OldIrql
);
942 if( NdisStatus
!= NDIS_STATUS_PENDING
) {
944 ( Adapter
, (PNDIS_PACKET
)WorkItemContext
, NdisStatus
);
948 case NdisWorkItemSendLoopback
:
950 * called by ProSend when protocols want to send loopback packets
952 /* XXX atm ProIndicatePacket sends a packet up via the loopback adapter only */
953 NdisStatus
= ProIndicatePacket(Adapter
, (PNDIS_PACKET
)WorkItemContext
);
955 if( NdisStatus
!= NDIS_STATUS_PENDING
)
956 MiniSendComplete((NDIS_HANDLE
)Adapter
, (PNDIS_PACKET
)WorkItemContext
, NdisStatus
);
959 case NdisWorkItemReturnPackets
:
962 case NdisWorkItemResetRequested
:
963 NdisMIndicateStatus(Adapter
, NDIS_STATUS_RESET_START
, NULL
, 0);
964 NdisMIndicateStatusComplete(Adapter
);
966 KeRaiseIrql(DISPATCH_LEVEL
, &OldIrql
);
967 NdisStatus
= (*Adapter
->NdisMiniportBlock
.DriverHandle
->MiniportCharacteristics
.ResetHandler
)(
968 Adapter
->NdisMiniportBlock
.MiniportAdapterContext
,
970 KeLowerIrql(OldIrql
);
972 if (NdisStatus
== NDIS_STATUS_PENDING
)
975 MiniResetComplete(Adapter
, NdisStatus
, AddressingReset
);
978 case NdisWorkItemResetInProgress
:
981 case NdisWorkItemMiniportCallback
:
984 case NdisWorkItemRequest
:
985 NdisStatus
= MiniDoRequest(Adapter
, (PNDIS_REQUEST
)WorkItemContext
);
987 if (NdisStatus
== NDIS_STATUS_PENDING
)
990 switch (((PNDIS_REQUEST
)WorkItemContext
)->RequestType
)
992 case NdisRequestQueryInformation
:
993 NdisMQueryInformationComplete((NDIS_HANDLE
)Adapter
, NdisStatus
);
994 MiniRequestComplete( (NDIS_HANDLE
)Adapter
, (PNDIS_REQUEST
)WorkItemContext
, NdisStatus
);
997 case NdisRequestSetInformation
:
998 NdisMSetInformationComplete((NDIS_HANDLE
)Adapter
, NdisStatus
);
999 MiniRequestComplete( (NDIS_HANDLE
)Adapter
, (PNDIS_REQUEST
)WorkItemContext
, NdisStatus
);
1003 NDIS_DbgPrint(MIN_TRACE
, ("Unknown NDIS request type.\n"));
1009 NDIS_DbgPrint(MIN_TRACE
, ("Unknown NDIS work item type (%d).\n", WorkItemType
));
1014 if( NdisStatus
!= NDIS_STATUS_PENDING
) {
1015 KeAcquireSpinLock(&Adapter
->NdisMiniportBlock
.Lock
, &OldIrql
);
1016 Adapter
->MiniportBusy
= FALSE
;
1017 KeReleaseSpinLock(&Adapter
->NdisMiniportBlock
.Lock
, OldIrql
);
1020 ExFreePool(WorkItem
);
1028 IN NDIS_HANDLE MiniportHandle
,
1029 IN NDIS_STATUS GeneralStatus
,
1030 IN PVOID StatusBuffer
,
1031 IN UINT StatusBufferSize
)
1033 PLOGICAL_ADAPTER Adapter
= MiniportHandle
;
1034 PLIST_ENTRY CurrentEntry
;
1035 PADAPTER_BINDING AdapterBinding
;
1038 KeAcquireSpinLock(&Adapter
->NdisMiniportBlock
.Lock
, &OldIrql
);
1040 CurrentEntry
= Adapter
->ProtocolListHead
.Flink
;
1042 while (CurrentEntry
!= &Adapter
->ProtocolListHead
)
1044 AdapterBinding
= CONTAINING_RECORD(CurrentEntry
, ADAPTER_BINDING
, AdapterListEntry
);
1046 (*AdapterBinding
->ProtocolBinding
->Chars
.StatusHandler
)(
1047 AdapterBinding
->NdisOpenBlock
.ProtocolBindingContext
,
1052 CurrentEntry
= CurrentEntry
->Flink
;
1055 KeReleaseSpinLock(&Adapter
->NdisMiniportBlock
.Lock
, OldIrql
);
1062 IN NDIS_HANDLE MiniportAdapterHandle
)
1064 PLOGICAL_ADAPTER Adapter
= MiniportAdapterHandle
;
1065 PLIST_ENTRY CurrentEntry
;
1066 PADAPTER_BINDING AdapterBinding
;
1069 KeAcquireSpinLock(&Adapter
->NdisMiniportBlock
.Lock
, &OldIrql
);
1071 CurrentEntry
= Adapter
->ProtocolListHead
.Flink
;
1073 while (CurrentEntry
!= &Adapter
->ProtocolListHead
)
1075 AdapterBinding
= CONTAINING_RECORD(CurrentEntry
, ADAPTER_BINDING
, AdapterListEntry
);
1077 (*AdapterBinding
->ProtocolBinding
->Chars
.StatusCompleteHandler
)(
1078 AdapterBinding
->NdisOpenBlock
.ProtocolBindingContext
);
1080 CurrentEntry
= CurrentEntry
->Flink
;
1083 KeReleaseSpinLock(&Adapter
->NdisMiniportBlock
.Lock
, OldIrql
);
1093 IN NDIS_HANDLE LogHandle
)
1105 IN NDIS_HANDLE MiniportAdapterHandle
,
1107 OUT PNDIS_HANDLE LogHandle
)
1111 return NDIS_STATUS_FAILURE
;
1120 NdisMDeregisterAdapterShutdownHandler(
1121 IN NDIS_HANDLE MiniportHandle
)
1123 * FUNCTION: de-registers a shutdown handler
1124 * ARGUMENTS: MiniportHandle: Handle passed into MiniportInitialize
1127 PLOGICAL_ADAPTER Adapter
= (PLOGICAL_ADAPTER
)MiniportHandle
;
1129 NDIS_DbgPrint(DEBUG_MINIPORT
, ("Called.\n"));
1131 if(Adapter
->BugcheckContext
->ShutdownHandler
) {
1132 KeDeregisterBugCheckCallback(Adapter
->BugcheckContext
->CallbackRecord
);
1133 IoUnregisterShutdownNotification(Adapter
->NdisMiniportBlock
.DeviceObject
);
1144 IN NDIS_HANDLE LogHandle
)
1152 #undef NdisMIndicateStatus
1155 NdisMIndicateStatus(
1156 IN NDIS_HANDLE MiniportAdapterHandle
,
1157 IN NDIS_STATUS GeneralStatus
,
1158 IN PVOID StatusBuffer
,
1159 IN UINT StatusBufferSize
)
1161 MiniStatus(MiniportAdapterHandle
, GeneralStatus
, StatusBuffer
, StatusBufferSize
);
1167 #undef NdisMIndicateStatusComplete
1170 NdisMIndicateStatusComplete(
1171 IN NDIS_HANDLE MiniportAdapterHandle
)
1173 MiniStatusComplete(MiniportAdapterHandle
);
1182 NdisInitializeWrapper(
1183 OUT PNDIS_HANDLE NdisWrapperHandle
,
1184 IN PVOID SystemSpecific1
,
1185 IN PVOID SystemSpecific2
,
1186 IN PVOID SystemSpecific3
)
1188 * FUNCTION: Notifies the NDIS library that a new miniport is initializing
1190 * NdisWrapperHandle = Address of buffer to place NDIS wrapper handle
1191 * SystemSpecific1 = Pointer to the driver's driver object
1192 * SystemSpecific2 = Pointer to the driver's registry path
1193 * SystemSpecific3 = Always NULL
1195 * - SystemSpecific2 goes invalid so we copy it
1198 PNDIS_M_DRIVER_BLOCK Miniport
;
1199 PUNICODE_STRING RegistryPath
;
1200 WCHAR
*RegistryBuffer
;
1202 NDIS_DbgPrint(MAX_TRACE
, ("Called.\n"));
1204 ASSERT(NdisWrapperHandle
);
1206 *NdisWrapperHandle
= NULL
;
1208 #if BREAK_ON_MINIPORT_INIT
1209 __asm__ ("int $3\n");
1212 Miniport
= ExAllocatePool(NonPagedPool
, sizeof(NDIS_M_DRIVER_BLOCK
));
1216 NDIS_DbgPrint(MIN_TRACE
, ("Insufficient resources.\n"));
1220 RtlZeroMemory(Miniport
, sizeof(NDIS_M_DRIVER_BLOCK
));
1222 KeInitializeSpinLock(&Miniport
->Lock
);
1224 Miniport
->DriverObject
= (PDRIVER_OBJECT
)SystemSpecific1
;
1226 /* set the miniport's driver registry path */
1227 RegistryPath
= ExAllocatePool(PagedPool
, sizeof(UNICODE_STRING
));
1230 ExFreePool(Miniport
);
1231 NDIS_DbgPrint(MIN_TRACE
, ("Insufficient resources.\n"));
1235 RegistryPath
->Length
= ((PUNICODE_STRING
)SystemSpecific2
)->Length
;
1236 RegistryPath
->MaximumLength
= RegistryPath
->Length
+ sizeof(WCHAR
); /* room for 0-term */
1238 RegistryBuffer
= ExAllocatePool(PagedPool
, RegistryPath
->MaximumLength
);
1241 NDIS_DbgPrint(MIN_TRACE
, ("Insufficient resources.\n"));
1242 ExFreePool(Miniport
);
1243 ExFreePool(RegistryPath
);
1247 RtlCopyMemory(RegistryBuffer
, ((PUNICODE_STRING
)SystemSpecific2
)->Buffer
, RegistryPath
->Length
);
1248 RegistryBuffer
[RegistryPath
->Length
/sizeof(WCHAR
)] = 0;
1250 RegistryPath
->Buffer
= RegistryBuffer
;
1251 Miniport
->RegistryPath
= RegistryPath
;
1253 InitializeListHead(&Miniport
->DeviceList
);
1255 /* Put miniport in global miniport list */
1256 ExInterlockedInsertTailList(&MiniportListHead
, &Miniport
->ListEntry
, &MiniportListLock
);
1258 *NdisWrapperHandle
= Miniport
;
1262 VOID NTAPI
NdisIBugcheckCallback(
1266 * FUNCTION: Internal callback for handling bugchecks - calls adapter's shutdown handler
1268 * Buffer: Pointer to a bugcheck callback context
1272 PMINIPORT_BUGCHECK_CONTEXT Context
= (PMINIPORT_BUGCHECK_CONTEXT
)Buffer
;
1273 ADAPTER_SHUTDOWN_HANDLER sh
= (ADAPTER_SHUTDOWN_HANDLER
)Context
->ShutdownHandler
;
1275 NDIS_DbgPrint(DEBUG_MINIPORT
, ("Called.\n"));
1278 sh(Context
->DriverContext
);
1287 NdisMRegisterAdapterShutdownHandler(
1288 IN NDIS_HANDLE MiniportHandle
,
1289 IN PVOID ShutdownContext
,
1290 IN ADAPTER_SHUTDOWN_HANDLER ShutdownHandler
)
1292 * FUNCTION: Register a shutdown handler for an adapter
1294 * MiniportHandle: Handle originally passed into MiniportInitialize
1295 * ShutdownContext: Pre-initialized bugcheck context
1296 * ShutdownHandler: Function to call to handle the bugcheck
1298 * - I'm not sure about ShutdownContext
1301 PLOGICAL_ADAPTER Adapter
= (PLOGICAL_ADAPTER
)MiniportHandle
;
1302 PMINIPORT_BUGCHECK_CONTEXT BugcheckContext
;
1304 NDIS_DbgPrint(DEBUG_MINIPORT
, ("Called.\n"));
1306 BugcheckContext
= ExAllocatePool(NonPagedPool
, sizeof(MINIPORT_BUGCHECK_CONTEXT
));
1307 if(!BugcheckContext
)
1309 NDIS_DbgPrint(MIN_TRACE
, ("Insufficient resources.\n"));
1313 BugcheckContext
->ShutdownHandler
= ShutdownHandler
;
1314 BugcheckContext
->DriverContext
= ShutdownContext
;
1316 BugcheckContext
->CallbackRecord
= ExAllocatePool(NonPagedPool
, sizeof(KBUGCHECK_CALLBACK_RECORD
));
1317 if (!BugcheckContext
->CallbackRecord
) {
1318 ExFreePool(BugcheckContext
);
1322 Adapter
->BugcheckContext
= BugcheckContext
;
1324 KeInitializeCallbackRecord(BugcheckContext
->CallbackRecord
);
1326 KeRegisterBugCheckCallback(BugcheckContext
->CallbackRecord
, NdisIBugcheckCallback
,
1327 BugcheckContext
, sizeof(BugcheckContext
), (PUCHAR
)"Ndis Miniport");
1329 IoRegisterShutdownNotification(Adapter
->NdisMiniportBlock
.DeviceObject
);
1335 PLOGICAL_ADAPTER Adapter
,
1336 NDIS_OID AddressOID
)
1338 * FUNCTION: Queries miniport for information
1340 * Adapter = Pointer to logical adapter
1341 * AddressOID = OID to use to query for current address
1343 * Status of operation
1347 NDIS_STATUS NdisStatus
;
1349 NDIS_DbgPrint(MAX_TRACE
, ("Called.\n"));
1351 /* Get MAC options for adapter */
1352 NdisStatus
= MiniQueryInformation(Adapter
, OID_GEN_MAC_OPTIONS
, sizeof(UINT
),
1353 &Adapter
->NdisMiniportBlock
.MacOptions
,
1356 if (NdisStatus
!= NDIS_STATUS_SUCCESS
)
1358 NDIS_DbgPrint(MIN_TRACE
, ("OID_GEN_MAC_OPTIONS failed. NdisStatus (0x%X).\n", NdisStatus
));
1362 NDIS_DbgPrint(DEBUG_MINIPORT
, ("MacOptions (0x%X).\n", Adapter
->NdisMiniportBlock
.MacOptions
));
1364 /* Get current hardware address of adapter */
1365 NdisStatus
= MiniQueryInformation(Adapter
, AddressOID
, Adapter
->AddressLength
,
1366 &Adapter
->Address
, &BytesWritten
);
1368 if (NdisStatus
!= NDIS_STATUS_SUCCESS
)
1370 NDIS_DbgPrint(MIN_TRACE
, ("Address OID (0x%X) failed. NdisStatus (0x%X).\n", AddressOID
, NdisStatus
));
1378 PUCHAR A
= (PUCHAR
)&Adapter
->Address
.Type
.Medium802_3
;
1380 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]));
1384 /* Get maximum lookahead buffer size of adapter */
1385 NdisStatus
= MiniQueryInformation(Adapter
, OID_GEN_MAXIMUM_LOOKAHEAD
, sizeof(ULONG
),
1386 &Adapter
->NdisMiniportBlock
.MaximumLookahead
, &BytesWritten
);
1388 if (NdisStatus
!= NDIS_STATUS_SUCCESS
)
1390 NDIS_DbgPrint(MIN_TRACE
, ("OID_GEN_MAXIMUM_LOOKAHEAD failed. NdisStatus (0x%X).\n", NdisStatus
));
1394 NDIS_DbgPrint(DEBUG_MINIPORT
, ("MaxLookaheadLength (0x%X).\n", Adapter
->NdisMiniportBlock
.MaximumLookahead
));
1396 /* Get current lookahead buffer size of adapter */
1397 NdisStatus
= MiniQueryInformation(Adapter
, OID_GEN_CURRENT_LOOKAHEAD
, sizeof(ULONG
),
1398 &Adapter
->NdisMiniportBlock
.CurrentLookahead
, &BytesWritten
);
1400 if (NdisStatus
!= NDIS_STATUS_SUCCESS
)
1402 NDIS_DbgPrint(MIN_TRACE
, ("OID_GEN_CURRENT_LOOKAHEAD failed. NdisStatus (0x%X).\n", NdisStatus
));
1406 NdisStatus
= MiniQueryInformation(Adapter
, OID_GEN_MAXIMUM_SEND_PACKETS
, sizeof(ULONG
),
1407 &Adapter
->NdisMiniportBlock
.MaxSendPackets
, &BytesWritten
);
1409 if (NdisStatus
!= NDIS_STATUS_SUCCESS
)
1411 NDIS_DbgPrint(MIN_TRACE
, ("OID_GEN_MAXIMUM_SEND_PACKETS failed. NdisStatus (0x%X).\n", NdisStatus
));
1413 /* Set it to 1 if it fails because some drivers don't support this (?)*/
1414 Adapter
->NdisMiniportBlock
.MaxSendPackets
= 1;
1417 NDIS_DbgPrint(DEBUG_MINIPORT
, ("CurLookaheadLength (0x%X).\n", Adapter
->NdisMiniportBlock
.CurrentLookahead
));
1419 if (Adapter
->NdisMiniportBlock
.MaximumLookahead
!= 0)
1421 Adapter
->LookaheadLength
= Adapter
->NdisMiniportBlock
.MaximumLookahead
+ Adapter
->MediumHeaderSize
;
1422 Adapter
->LookaheadBuffer
= ExAllocatePool(NonPagedPool
, Adapter
->LookaheadLength
);
1424 if (!Adapter
->LookaheadBuffer
)
1425 return NDIS_STATUS_RESOURCES
;
1428 return STATUS_SUCCESS
;
1434 NdisIForwardIrpAndWaitCompletionRoutine(
1439 PKEVENT Event
= Context
;
1441 if (Irp
->PendingReturned
)
1442 KeSetEvent(Event
, IO_NO_INCREMENT
, FALSE
);
1444 return STATUS_MORE_PROCESSING_REQUIRED
;
1450 NdisIForwardIrpAndWait(PLOGICAL_ADAPTER Adapter
, PIRP Irp
)
1455 KeInitializeEvent(&Event
, NotificationEvent
, FALSE
);
1456 IoCopyCurrentIrpStackLocationToNext(Irp
);
1457 IoSetCompletionRoutine(Irp
, NdisIForwardIrpAndWaitCompletionRoutine
, &Event
,
1459 Status
= IoCallDriver(Adapter
->NdisMiniportBlock
.NextDeviceObject
, Irp
);
1460 if (Status
== STATUS_PENDING
)
1462 KeWaitForSingleObject(&Event
, Executive
, KernelMode
, FALSE
, NULL
);
1463 Status
= Irp
->IoStatus
.Status
;
1471 NdisIPnPStartDevice(
1472 IN PDEVICE_OBJECT DeviceObject
,
1475 * FUNCTION: Handle the PnP start device event
1477 * DeviceObejct = Functional Device Object
1478 * Irp = IRP_MN_START_DEVICE I/O request packet
1480 * Status of operation
1483 PIO_STACK_LOCATION Stack
= IoGetCurrentIrpStackLocation(Irp
);
1484 PLOGICAL_ADAPTER Adapter
= (PLOGICAL_ADAPTER
)DeviceObject
->DeviceExtension
;
1485 NDIS_WRAPPER_CONTEXT WrapperContext
;
1486 NDIS_STATUS NdisStatus
;
1487 NDIS_STATUS OpenErrorStatus
;
1489 UINT SelectedMediumIndex
= 0;
1490 NDIS_OID AddressOID
;
1491 BOOLEAN Success
= FALSE
;
1492 ULONG ResourceCount
;
1493 ULONG ResourceListSize
;
1494 UNICODE_STRING ParamName
;
1495 PNDIS_CONFIGURATION_PARAMETER ConfigParam
;
1496 NDIS_HANDLE ConfigHandle
;
1498 LARGE_INTEGER Timeout
;
1499 /* FIXME - KIRQL OldIrql; */
1502 * Prepare wrapper context used by HW and configuration routines.
1505 NDIS_DbgPrint(DEBUG_MINIPORT
, ("Start Device %wZ\n", &Adapter
->NdisMiniportBlock
.MiniportName
));
1507 NDIS_DbgPrint(MAX_TRACE
, ("Inserting adapter 0x%x into adapter list\n", Adapter
));
1509 /* Put adapter in global adapter list */
1510 ExInterlockedInsertTailList(&AdapterListHead
, &Adapter
->ListEntry
, &AdapterListLock
);
1512 Status
= IoOpenDeviceRegistryKey(
1513 Adapter
->NdisMiniportBlock
.PhysicalDeviceObject
, PLUGPLAY_REGKEY_DRIVER
,
1514 KEY_ALL_ACCESS
, &WrapperContext
.RegistryHandle
);
1515 if (!NT_SUCCESS(Status
))
1517 NDIS_DbgPrint(MIN_TRACE
,("failed to open adapter-specific reg key\n"));
1518 ExInterlockedRemoveEntryList( &Adapter
->ListEntry
, &AdapterListLock
);
1522 NDIS_DbgPrint(MAX_TRACE
, ("opened device reg key\n"));
1524 WrapperContext
.DeviceObject
= Adapter
->NdisMiniportBlock
.DeviceObject
;
1527 * Store the adapter resources used by HW routines such as
1528 * NdisMQueryAdapterResources.
1531 if (Stack
->Parameters
.StartDevice
.AllocatedResources
!= NULL
)
1533 ResourceCount
= Stack
->Parameters
.StartDevice
.AllocatedResources
->List
[0].
1534 PartialResourceList
.Count
;
1536 FIELD_OFFSET(CM_RESOURCE_LIST
, List
[0].PartialResourceList
.
1537 PartialDescriptors
[ResourceCount
]);
1539 Adapter
->NdisMiniportBlock
.AllocatedResources
=
1540 ExAllocatePool(PagedPool
, ResourceListSize
);
1541 if (Adapter
->NdisMiniportBlock
.AllocatedResources
== NULL
)
1543 ExInterlockedRemoveEntryList( &Adapter
->ListEntry
, &AdapterListLock
);
1544 return STATUS_INSUFFICIENT_RESOURCES
;
1547 RtlCopyMemory(Adapter
->NdisMiniportBlock
.AllocatedResources
,
1548 Stack
->Parameters
.StartDevice
.AllocatedResources
,
1552 if (Stack
->Parameters
.StartDevice
.AllocatedResourcesTranslated
!= NULL
)
1554 ResourceCount
= Stack
->Parameters
.StartDevice
.AllocatedResourcesTranslated
->List
[0].
1555 PartialResourceList
.Count
;
1557 FIELD_OFFSET(CM_RESOURCE_LIST
, List
[0].PartialResourceList
.
1558 PartialDescriptors
[ResourceCount
]);
1560 Adapter
->NdisMiniportBlock
.AllocatedResourcesTranslated
=
1561 ExAllocatePool(PagedPool
, ResourceListSize
);
1562 if (Adapter
->NdisMiniportBlock
.AllocatedResourcesTranslated
== NULL
)
1564 ExInterlockedRemoveEntryList( &Adapter
->ListEntry
, &AdapterListLock
);
1565 return STATUS_INSUFFICIENT_RESOURCES
;
1568 RtlCopyMemory(Adapter
->NdisMiniportBlock
.AllocatedResourcesTranslated
,
1569 Stack
->Parameters
.StartDevice
.AllocatedResourcesTranslated
,
1574 * Store the Bus Type, Bus Number and Slot information. It's used by
1575 * the hardware routines then.
1578 NdisOpenConfiguration(&NdisStatus
, &ConfigHandle
, (NDIS_HANDLE
)&WrapperContext
);
1580 Size
= sizeof(ULONG
);
1581 Status
= IoGetDeviceProperty(Adapter
->NdisMiniportBlock
.PhysicalDeviceObject
,
1582 DevicePropertyLegacyBusType
, Size
,
1583 &Adapter
->NdisMiniportBlock
.BusType
, &Size
);
1584 if (!NT_SUCCESS(Status
) || (INTERFACE_TYPE
)Adapter
->NdisMiniportBlock
.BusType
== InterfaceTypeUndefined
)
1586 NdisInitUnicodeString(&ParamName
, L
"BusType");
1587 NdisReadConfiguration(&NdisStatus
, &ConfigParam
, ConfigHandle
,
1588 &ParamName
, NdisParameterInteger
);
1589 if (NdisStatus
== NDIS_STATUS_SUCCESS
)
1590 Adapter
->NdisMiniportBlock
.BusType
= ConfigParam
->ParameterData
.IntegerData
;
1592 Adapter
->NdisMiniportBlock
.BusType
= Isa
;
1595 Status
= IoGetDeviceProperty(Adapter
->NdisMiniportBlock
.PhysicalDeviceObject
,
1596 DevicePropertyBusNumber
, Size
,
1597 &Adapter
->NdisMiniportBlock
.BusNumber
, &Size
);
1598 if (!NT_SUCCESS(Status
) || Adapter
->NdisMiniportBlock
.BusNumber
== 0xFFFFFFF0)
1600 NdisInitUnicodeString(&ParamName
, L
"BusNumber");
1601 NdisReadConfiguration(&NdisStatus
, &ConfigParam
, ConfigHandle
,
1602 &ParamName
, NdisParameterInteger
);
1603 if (NdisStatus
== NDIS_STATUS_SUCCESS
)
1604 Adapter
->NdisMiniportBlock
.BusNumber
= ConfigParam
->ParameterData
.IntegerData
;
1606 Adapter
->NdisMiniportBlock
.BusNumber
= 0;
1608 WrapperContext
.BusNumber
= Adapter
->NdisMiniportBlock
.BusNumber
;
1610 Status
= IoGetDeviceProperty(Adapter
->NdisMiniportBlock
.PhysicalDeviceObject
,
1611 DevicePropertyAddress
, Size
,
1612 &Adapter
->NdisMiniportBlock
.SlotNumber
, &Size
);
1613 if (!NT_SUCCESS(Status
) || Adapter
->NdisMiniportBlock
.SlotNumber
== (NDIS_INTERFACE_TYPE
)-1)
1615 NdisInitUnicodeString(&ParamName
, L
"SlotNumber");
1616 NdisReadConfiguration(&NdisStatus
, &ConfigParam
, ConfigHandle
,
1617 &ParamName
, NdisParameterInteger
);
1618 if (NdisStatus
== NDIS_STATUS_SUCCESS
)
1619 Adapter
->NdisMiniportBlock
.SlotNumber
= ConfigParam
->ParameterData
.IntegerData
;
1621 Adapter
->NdisMiniportBlock
.SlotNumber
= 0;
1625 /* Convert slotnumber to PCI_SLOT_NUMBER */
1626 ULONG PciSlotNumber
= Adapter
->NdisMiniportBlock
.SlotNumber
;
1627 PCI_SLOT_NUMBER SlotNumber
;
1629 SlotNumber
.u
.AsULONG
= 0;
1630 SlotNumber
.u
.bits
.DeviceNumber
= (PciSlotNumber
>> 16) & 0xFFFF;
1631 SlotNumber
.u
.bits
.FunctionNumber
= PciSlotNumber
& 0xFFFF;
1633 Adapter
->NdisMiniportBlock
.SlotNumber
= SlotNumber
.u
.AsULONG
;
1635 NdisCloseConfiguration(ConfigHandle
);
1637 /* Set handlers (some NDIS macros require these) */
1638 Adapter
->NdisMiniportBlock
.EthRxCompleteHandler
= EthFilterDprIndicateReceiveComplete
;
1639 Adapter
->NdisMiniportBlock
.EthRxIndicateHandler
= EthFilterDprIndicateReceive
;
1640 Adapter
->NdisMiniportBlock
.SendCompleteHandler
= MiniSendComplete
;
1641 Adapter
->NdisMiniportBlock
.SendResourcesHandler
= MiniSendResourcesAvailable
;
1642 Adapter
->NdisMiniportBlock
.ResetCompleteHandler
= MiniResetComplete
;
1643 Adapter
->NdisMiniportBlock
.TDCompleteHandler
= MiniTransferDataComplete
;
1644 Adapter
->NdisMiniportBlock
.PacketIndicateHandler
= MiniIndicateReceivePacket
;
1645 Adapter
->NdisMiniportBlock
.StatusHandler
= MiniStatus
;
1646 Adapter
->NdisMiniportBlock
.StatusCompleteHandler
= MiniStatusComplete
;
1649 * Call MiniportInitialize.
1652 NDIS_DbgPrint(MID_TRACE
, ("calling MiniportInitialize\n"));
1653 NdisStatus
= (*Adapter
->NdisMiniportBlock
.DriverHandle
->MiniportCharacteristics
.InitializeHandler
)(
1654 &OpenErrorStatus
, &SelectedMediumIndex
, &MediaArray
[0],
1655 MEDIA_ARRAY_SIZE
, Adapter
, (NDIS_HANDLE
)&WrapperContext
);
1657 ZwClose(WrapperContext
.RegistryHandle
);
1659 if (NdisStatus
!= NDIS_STATUS_SUCCESS
)
1661 NDIS_DbgPrint(MIN_TRACE
, ("MiniportInitialize() failed for an adapter.\n"));
1662 ExInterlockedRemoveEntryList( &Adapter
->ListEntry
, &AdapterListLock
);
1666 if (SelectedMediumIndex
>= MEDIA_ARRAY_SIZE
)
1668 NDIS_DbgPrint(MIN_TRACE
, ("MiniportInitialize() failed for an adapter\n"));
1669 ExInterlockedRemoveEntryList( &Adapter
->ListEntry
, &AdapterListLock
);
1670 return NDIS_STATUS_UNSUPPORTED_MEDIA
;
1673 Adapter
->NdisMiniportBlock
.MediaType
= MediaArray
[SelectedMediumIndex
];
1675 switch (Adapter
->NdisMiniportBlock
.MediaType
)
1677 case NdisMedium802_3
:
1678 Adapter
->MediumHeaderSize
= 14; /* XXX figure out what to do about LLC */
1679 AddressOID
= OID_802_3_CURRENT_ADDRESS
;
1680 Adapter
->AddressLength
= ETH_LENGTH_OF_ADDRESS
;
1681 NdisStatus
= DoQueries(Adapter
, AddressOID
);
1682 if (NdisStatus
== NDIS_STATUS_SUCCESS
)
1684 Success
= EthCreateFilter(32, /* FIXME: Query this from miniport. */
1685 Adapter
->Address
.Type
.Medium802_3
,
1686 &Adapter
->NdisMiniportBlock
.EthDB
);
1688 ((PETHI_FILTER
)Adapter
->NdisMiniportBlock
.EthDB
)->Miniport
= (PNDIS_MINIPORT_BLOCK
)Adapter
;
1690 NdisStatus
= NDIS_STATUS_RESOURCES
;
1695 /* FIXME: Support other types of media */
1696 NDIS_DbgPrint(MIN_TRACE
, ("error: unsupported media\n"));
1698 /* FIXME - KeReleaseSpinLock(&Adapter->NdisMiniportBlock.Lock, OldIrql); */
1699 ExInterlockedRemoveEntryList( &Adapter
->ListEntry
, &AdapterListLock
);
1700 return STATUS_UNSUCCESSFUL
;
1703 if (NdisStatus
!= NDIS_STATUS_SUCCESS
)
1705 NDIS_DbgPrint(MAX_TRACE
, ("couldn't create filter (%x)\n", NdisStatus
));
1706 if (Adapter
->LookaheadBuffer
)
1708 ExFreePool(Adapter
->LookaheadBuffer
);
1709 Adapter
->LookaheadBuffer
= NULL
;
1711 ExInterlockedRemoveEntryList( &Adapter
->ListEntry
, &AdapterListLock
);
1715 /* Check for a hang every two seconds if it wasn't set in MiniportInitialize */
1716 if (Adapter
->NdisMiniportBlock
.CheckForHangSeconds
== 0)
1717 Adapter
->NdisMiniportBlock
.CheckForHangSeconds
= 2;
1719 Adapter
->NdisMiniportBlock
.OldPnPDeviceState
= Adapter
->NdisMiniportBlock
.PnPDeviceState
;
1720 Adapter
->NdisMiniportBlock
.PnPDeviceState
= NdisPnPDeviceStarted
;
1722 Timeout
.QuadPart
= (LONGLONG
)Adapter
->NdisMiniportBlock
.CheckForHangSeconds
* -1000000;
1723 KeSetTimerEx(&Adapter
->NdisMiniportBlock
.WakeUpDpcTimer
.Timer
, Timeout
,
1724 Adapter
->NdisMiniportBlock
.CheckForHangSeconds
* 1000,
1725 &Adapter
->NdisMiniportBlock
.WakeUpDpcTimer
.Dpc
);
1727 /* Put adapter in adapter list for this miniport */
1728 ExInterlockedInsertTailList(&Adapter
->NdisMiniportBlock
.DriverHandle
->DeviceList
, &Adapter
->MiniportListEntry
, &Adapter
->NdisMiniportBlock
.DriverHandle
->Lock
);
1730 return STATUS_SUCCESS
;
1737 IN PDEVICE_OBJECT DeviceObject
,
1740 * FUNCTION: Handle the PnP stop device event
1742 * DeviceObejct = Functional Device Object
1743 * Irp = IRP_MN_STOP_DEVICE I/O request packet
1745 * Status of operation
1748 PLOGICAL_ADAPTER Adapter
= (PLOGICAL_ADAPTER
)DeviceObject
->DeviceExtension
;
1751 /* Remove adapter from adapter list for this miniport */
1752 KeAcquireSpinLock(&Adapter
->NdisMiniportBlock
.DriverHandle
->Lock
, &OldIrql
);
1753 RemoveEntryList(&Adapter
->MiniportListEntry
);
1754 KeReleaseSpinLock(&Adapter
->NdisMiniportBlock
.DriverHandle
->Lock
, OldIrql
);
1756 /* Remove adapter from global adapter list */
1757 KeAcquireSpinLock(&AdapterListLock
, &OldIrql
);
1758 RemoveEntryList(&Adapter
->ListEntry
);
1759 KeReleaseSpinLock(&AdapterListLock
, OldIrql
);
1761 KeCancelTimer(&Adapter
->NdisMiniportBlock
.WakeUpDpcTimer
.Timer
);
1763 (*Adapter
->NdisMiniportBlock
.DriverHandle
->MiniportCharacteristics
.HaltHandler
)(Adapter
);
1765 if (Adapter
->LookaheadBuffer
)
1767 ExFreePool(Adapter
->LookaheadBuffer
);
1768 Adapter
->LookaheadBuffer
= NULL
;
1770 if (Adapter
->NdisMiniportBlock
.AllocatedResources
)
1772 ExFreePool(Adapter
->NdisMiniportBlock
.AllocatedResources
);
1773 Adapter
->NdisMiniportBlock
.AllocatedResources
= NULL
;
1775 if (Adapter
->NdisMiniportBlock
.AllocatedResourcesTranslated
)
1777 ExFreePool(Adapter
->NdisMiniportBlock
.AllocatedResourcesTranslated
);
1778 Adapter
->NdisMiniportBlock
.AllocatedResourcesTranslated
= NULL
;
1781 Adapter
->NdisMiniportBlock
.OldPnPDeviceState
= Adapter
->NdisMiniportBlock
.PnPDeviceState
;
1782 Adapter
->NdisMiniportBlock
.PnPDeviceState
= NdisPnPDeviceStopped
;
1784 return STATUS_SUCCESS
;
1790 IN PDEVICE_OBJECT DeviceObject
,
1793 PLOGICAL_ADAPTER Adapter
= DeviceObject
->DeviceExtension
;
1794 PMINIPORT_BUGCHECK_CONTEXT Context
= Adapter
->BugcheckContext
;
1795 ADAPTER_SHUTDOWN_HANDLER ShutdownHandler
= Context
->ShutdownHandler
;
1797 ASSERT(ShutdownHandler
);
1799 ShutdownHandler(Context
->DriverContext
);
1801 Irp
->IoStatus
.Status
= STATUS_SUCCESS
;
1802 Irp
->IoStatus
.Information
= 0;
1804 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
1806 return STATUS_SUCCESS
;
1813 IN PDEVICE_OBJECT DeviceObject
,
1816 PIO_STACK_LOCATION Stack
= IoGetCurrentIrpStackLocation(Irp
);
1817 PLOGICAL_ADAPTER Adapter
= (PLOGICAL_ADAPTER
)DeviceObject
->DeviceExtension
;
1820 switch (Stack
->MinorFunction
)
1822 case IRP_MN_START_DEVICE
:
1823 Status
= NdisIForwardIrpAndWait(Adapter
, Irp
);
1824 if (NT_SUCCESS(Status
) && NT_SUCCESS(Irp
->IoStatus
.Status
))
1826 Status
= NdisIPnPStartDevice(DeviceObject
, Irp
);
1828 Irp
->IoStatus
.Status
= Status
;
1829 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
1832 case IRP_MN_STOP_DEVICE
:
1833 Status
= NdisIForwardIrpAndWait(Adapter
, Irp
);
1834 if (NT_SUCCESS(Status
) && NT_SUCCESS(Irp
->IoStatus
.Status
))
1836 Status
= NdisIPnPStopDevice(DeviceObject
, Irp
);
1838 Irp
->IoStatus
.Status
= Status
;
1839 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
1842 case IRP_MN_QUERY_DEVICE_RELATIONS
:
1843 Status
= STATUS_NOT_SUPPORTED
;
1844 Irp
->IoStatus
.Status
= Status
;
1845 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
1849 IoSkipCurrentIrpStackLocation(Irp
);
1850 Status
= IoCallDriver(Adapter
->NdisMiniportBlock
.NextDeviceObject
, Irp
);
1861 IN PDRIVER_OBJECT DriverObject
,
1862 IN PDEVICE_OBJECT PhysicalDeviceObject
)
1864 * FUNCTION: Create a device for an adapter found using PnP
1866 * DriverObject = Pointer to the miniport driver object
1867 * PhysicalDeviceObject = Pointer to the PDO for our adapter
1870 static const WCHAR ClassKeyName
[] = {'C','l','a','s','s','\\'};
1871 static const WCHAR LinkageKeyName
[] = {'\\','L','i','n','k','a','g','e',0};
1872 PNDIS_M_DRIVER_BLOCK Miniport
;
1873 PNDIS_M_DRIVER_BLOCK
*MiniportPtr
;
1874 WCHAR
*LinkageKeyBuffer
;
1875 ULONG DriverKeyLength
;
1876 RTL_QUERY_REGISTRY_TABLE QueryTable
[2];
1877 UNICODE_STRING ExportName
;
1878 PDEVICE_OBJECT DeviceObject
;
1879 PLOGICAL_ADAPTER Adapter
;
1883 * Gain the access to the miniport data structure first.
1886 MiniportPtr
= IoGetDriverObjectExtension(DriverObject
, (PVOID
)TAG('D','I','M','N'));
1887 if (MiniportPtr
== NULL
)
1889 NDIS_DbgPrint(DEBUG_MINIPORT
, ("Can't get driver object extension.\n"));
1890 return STATUS_UNSUCCESSFUL
;
1892 Miniport
= *MiniportPtr
;
1895 * Get name of the Linkage registry key for our adapter. It's located under
1896 * the driver key for our driver and so we have basicly two ways to do it.
1897 * Either we can use IoOpenDriverRegistryKey or compose it using information
1898 * gathered by IoGetDeviceProperty. I choosed the second because
1899 * IoOpenDriverRegistryKey wasn't implemented at the time of writing.
1902 Status
= IoGetDeviceProperty(PhysicalDeviceObject
, DevicePropertyDriverKeyName
,
1903 0, NULL
, &DriverKeyLength
);
1904 if (Status
!= STATUS_BUFFER_TOO_SMALL
&& Status
!= STATUS_BUFFER_OVERFLOW
&& Status
!= STATUS_SUCCESS
)
1906 NDIS_DbgPrint(DEBUG_MINIPORT
, ("Can't get miniport driver key length.\n"));
1910 LinkageKeyBuffer
= ExAllocatePool(PagedPool
, DriverKeyLength
+
1911 sizeof(ClassKeyName
) + sizeof(LinkageKeyName
));
1912 if (LinkageKeyBuffer
== NULL
)
1914 NDIS_DbgPrint(DEBUG_MINIPORT
, ("Can't allocate memory for driver key name.\n"));
1915 return STATUS_INSUFFICIENT_RESOURCES
;
1918 Status
= IoGetDeviceProperty(PhysicalDeviceObject
, DevicePropertyDriverKeyName
,
1919 DriverKeyLength
, LinkageKeyBuffer
+
1920 (sizeof(ClassKeyName
) / sizeof(WCHAR
)),
1922 if (!NT_SUCCESS(Status
))
1924 NDIS_DbgPrint(DEBUG_MINIPORT
, ("Can't get miniport driver key.\n"));
1925 ExFreePool(LinkageKeyBuffer
);
1929 /* Compose the linkage key name. */
1930 RtlCopyMemory(LinkageKeyBuffer
, ClassKeyName
, sizeof(ClassKeyName
));
1931 RtlCopyMemory(LinkageKeyBuffer
+ ((sizeof(ClassKeyName
) + DriverKeyLength
) /
1932 sizeof(WCHAR
)) - 1, LinkageKeyName
, sizeof(LinkageKeyName
));
1934 NDIS_DbgPrint(DEBUG_MINIPORT
, ("LinkageKey: %S.\n", LinkageKeyBuffer
));
1937 * Now open the linkage key and read the "Export" and "RootDevice" values
1938 * which contains device name and root service respectively.
1941 RtlZeroMemory(QueryTable
, sizeof(QueryTable
));
1942 RtlInitUnicodeString(&ExportName
, NULL
);
1943 QueryTable
[0].Flags
= RTL_QUERY_REGISTRY_REQUIRED
| RTL_QUERY_REGISTRY_DIRECT
;
1944 QueryTable
[0].Name
= L
"Export";
1945 QueryTable
[0].EntryContext
= &ExportName
;
1947 Status
= RtlQueryRegistryValues(RTL_REGISTRY_CONTROL
, LinkageKeyBuffer
,
1948 QueryTable
, NULL
, NULL
);
1949 ExFreePool(LinkageKeyBuffer
);
1950 if (!NT_SUCCESS(Status
))
1952 NDIS_DbgPrint(DEBUG_MINIPORT
, ("Can't get miniport device name. (%x)\n", Status
));
1957 * Create the device object.
1960 NDIS_DbgPrint(MAX_TRACE
, ("creating device %wZ\n", &ExportName
));
1962 Status
= IoCreateDevice(Miniport
->DriverObject
, sizeof(LOGICAL_ADAPTER
),
1963 &ExportName
, FILE_DEVICE_PHYSICAL_NETCARD
,
1964 0, FALSE
, &DeviceObject
);
1965 if (!NT_SUCCESS(Status
))
1967 NDIS_DbgPrint(MIN_TRACE
, ("Could not create device object.\n"));
1968 RtlFreeUnicodeString(&ExportName
);
1973 * Initialize the adapter structure.
1976 Adapter
= (PLOGICAL_ADAPTER
)DeviceObject
->DeviceExtension
;
1977 KeInitializeSpinLock(&Adapter
->NdisMiniportBlock
.Lock
);
1978 InitializeListHead(&Adapter
->ProtocolListHead
);
1979 Adapter
->NdisMiniportBlock
.DriverHandle
= Miniport
;
1981 Adapter
->NdisMiniportBlock
.MiniportName
= ExportName
;
1983 Adapter
->NdisMiniportBlock
.DeviceObject
= DeviceObject
;
1984 Adapter
->NdisMiniportBlock
.PhysicalDeviceObject
= PhysicalDeviceObject
;
1985 Adapter
->NdisMiniportBlock
.NextDeviceObject
=
1986 IoAttachDeviceToDeviceStack(Adapter
->NdisMiniportBlock
.DeviceObject
,
1987 PhysicalDeviceObject
);
1989 Adapter
->NdisMiniportBlock
.OldPnPDeviceState
= 0;
1990 Adapter
->NdisMiniportBlock
.PnPDeviceState
= NdisPnPDeviceAdded
;
1992 KeInitializeTimer(&Adapter
->NdisMiniportBlock
.WakeUpDpcTimer
.Timer
);
1993 KeInitializeDpc(&Adapter
->NdisMiniportBlock
.WakeUpDpcTimer
.Dpc
, MiniportHangDpc
, Adapter
);
1995 DeviceObject
->Flags
&= ~DO_DEVICE_INITIALIZING
;
1997 return STATUS_SUCCESS
;
2006 NdisMRegisterMiniport(
2007 IN NDIS_HANDLE NdisWrapperHandle
,
2008 IN PNDIS_MINIPORT_CHARACTERISTICS MiniportCharacteristics
,
2009 IN UINT CharacteristicsLength
)
2011 * FUNCTION: Registers a miniport's MiniportXxx entry points with the NDIS library
2013 * NdisWrapperHandle = Pointer to handle returned by NdisMInitializeWrapper
2014 * MiniportCharacteristics = Pointer to a buffer with miniport characteristics
2015 * CharacteristicsLength = Number of bytes in characteristics buffer
2017 * Status of operation
2021 PNDIS_M_DRIVER_BLOCK Miniport
= GET_MINIPORT_DRIVER(NdisWrapperHandle
);
2022 PNDIS_M_DRIVER_BLOCK
*MiniportPtr
;
2025 NDIS_DbgPrint(MAX_TRACE
, ("Called.\n"));
2027 switch (MiniportCharacteristics
->MajorNdisVersion
)
2030 MinSize
= sizeof(NDIS30_MINIPORT_CHARACTERISTICS
);
2034 MinSize
= sizeof(NDIS40_MINIPORT_CHARACTERISTICS
);
2038 MinSize
= sizeof(NDIS50_MINIPORT_CHARACTERISTICS
);
2042 NDIS_DbgPrint(DEBUG_MINIPORT
, ("Bad miniport characteristics version.\n"));
2043 return NDIS_STATUS_BAD_VERSION
;
2046 if (CharacteristicsLength
< MinSize
)
2048 NDIS_DbgPrint(DEBUG_MINIPORT
, ("Bad miniport characteristics.\n"));
2049 return NDIS_STATUS_BAD_CHARACTERISTICS
;
2052 /* Check if mandatory MiniportXxx functions are specified */
2053 if ((!MiniportCharacteristics
->HaltHandler
) ||
2054 (!MiniportCharacteristics
->InitializeHandler
)||
2055 (!MiniportCharacteristics
->QueryInformationHandler
) ||
2056 (!MiniportCharacteristics
->ResetHandler
) ||
2057 (!MiniportCharacteristics
->SetInformationHandler
))
2059 NDIS_DbgPrint(DEBUG_MINIPORT
, ("Bad miniport characteristics.\n"));
2060 return NDIS_STATUS_BAD_CHARACTERISTICS
;
2063 if (MiniportCharacteristics
->MajorNdisVersion
== 0x03)
2065 if (!MiniportCharacteristics
->SendHandler
)
2067 NDIS_DbgPrint(DEBUG_MINIPORT
, ("Bad miniport characteristics.\n"));
2068 return NDIS_STATUS_BAD_CHARACTERISTICS
;
2071 else if (MiniportCharacteristics
->MajorNdisVersion
>= 0x04)
2074 if ((!MiniportCharacteristics
->SendHandler
) &&
2075 (!MiniportCharacteristics
->SendPacketsHandler
))
2077 NDIS_DbgPrint(DEBUG_MINIPORT
, ("Bad miniport characteristics.\n"));
2078 return NDIS_STATUS_BAD_CHARACTERISTICS
;
2082 /* TODO: verify NDIS5 and NDIS5.1 */
2084 RtlCopyMemory(&Miniport
->MiniportCharacteristics
, MiniportCharacteristics
, MinSize
);
2087 * NOTE: This is VERY unoptimal! Should we store the NDIS_M_DRIVER_BLOCK
2088 * structure in the driver extension or what?
2091 Status
= IoAllocateDriverObjectExtension(Miniport
->DriverObject
, (PVOID
)TAG('D','I','M','N'),
2092 sizeof(PNDIS_M_DRIVER_BLOCK
), (PVOID
*)&MiniportPtr
);
2093 if (!NT_SUCCESS(Status
))
2095 NDIS_DbgPrint(DEBUG_MINIPORT
, ("Can't allocate driver object extension.\n"));
2096 return NDIS_STATUS_RESOURCES
;
2099 *MiniportPtr
= Miniport
;
2101 Miniport
->DriverObject
->MajorFunction
[IRP_MJ_PNP
] = NdisIDispatchPnp
;
2102 Miniport
->DriverObject
->MajorFunction
[IRP_MJ_SHUTDOWN
] = NdisIShutdown
;
2103 Miniport
->DriverObject
->DriverExtension
->AddDevice
= NdisIAddDevice
;
2105 return NDIS_STATUS_SUCCESS
;
2112 #undef NdisMResetComplete
2116 IN NDIS_HANDLE MiniportAdapterHandle
,
2117 IN NDIS_STATUS Status
,
2118 IN BOOLEAN AddressingReset
)
2120 MiniResetComplete(MiniportAdapterHandle
, Status
, AddressingReset
);
2127 #undef NdisMSendComplete
2131 IN NDIS_HANDLE MiniportAdapterHandle
,
2132 IN PNDIS_PACKET Packet
,
2133 IN NDIS_STATUS Status
)
2135 * FUNCTION: Forwards a message to the initiating protocol saying
2136 * that a packet was handled
2138 * NdisAdapterHandle = Handle input to MiniportInitialize
2139 * Packet = Pointer to NDIS packet that was sent
2140 * Status = Status of send operation
2143 MiniSendComplete(MiniportAdapterHandle
, Packet
, Status
);
2150 #undef NdisMSendResourcesAvailable
2153 NdisMSendResourcesAvailable(
2154 IN NDIS_HANDLE MiniportAdapterHandle
)
2156 MiniSendResourcesAvailable(MiniportAdapterHandle
);
2163 #undef NdisMTransferDataComplete
2166 NdisMTransferDataComplete(
2167 IN NDIS_HANDLE MiniportAdapterHandle
,
2168 IN PNDIS_PACKET Packet
,
2169 IN NDIS_STATUS Status
,
2170 IN UINT BytesTransferred
)
2172 MiniTransferDataComplete(MiniportAdapterHandle
, Packet
, Status
, BytesTransferred
);
2179 #undef NdisMSetInformationComplete
2182 NdisMSetInformationComplete(
2183 IN NDIS_HANDLE MiniportAdapterHandle
,
2184 IN NDIS_STATUS Status
)
2186 PLOGICAL_ADAPTER Adapter
=
2187 (PLOGICAL_ADAPTER
)MiniportAdapterHandle
;
2190 KeRaiseIrql(DISPATCH_LEVEL
, &OldIrql
);
2191 (Adapter
->NdisMiniportBlock
.SetCompleteHandler
)(MiniportAdapterHandle
, Status
);
2192 KeAcquireSpinLockAtDpcLevel(&Adapter
->NdisMiniportBlock
.Lock
);
2193 Adapter
->MiniportBusy
= FALSE
;
2194 KeReleaseSpinLockFromDpcLevel(&Adapter
->NdisMiniportBlock
.Lock
);
2195 KeLowerIrql(OldIrql
);
2202 #undef NdisMSetAttributes
2206 IN NDIS_HANDLE MiniportAdapterHandle
,
2207 IN NDIS_HANDLE MiniportAdapterContext
,
2208 IN BOOLEAN BusMaster
,
2209 IN NDIS_INTERFACE_TYPE AdapterType
)
2211 * FUNCTION: Informs the NDIS library of significant features of the caller's NIC
2213 * MiniportAdapterHandle = Handle input to MiniportInitialize
2214 * MiniportAdapterContext = Pointer to context information
2215 * BusMaster = Specifies TRUE if the caller's NIC is a busmaster DMA device
2216 * AdapterType = Specifies the I/O bus interface of the caller's NIC
2219 NDIS_DbgPrint(MAX_TRACE
, ("Called.\n"));
2220 NdisMSetAttributesEx(MiniportAdapterHandle
, MiniportAdapterContext
, 0,
2221 BusMaster
? NDIS_ATTRIBUTE_BUS_MASTER
: 0,
2231 NdisMSetAttributesEx(
2232 IN NDIS_HANDLE MiniportAdapterHandle
,
2233 IN NDIS_HANDLE MiniportAdapterContext
,
2234 IN UINT CheckForHangTimeInSeconds OPTIONAL
,
2235 IN ULONG AttributeFlags
,
2236 IN NDIS_INTERFACE_TYPE AdapterType
)
2238 * FUNCTION: Informs the NDIS library of significant features of the caller's NIC
2240 * MiniportAdapterHandle = Handle input to MiniportInitialize
2241 * MiniportAdapterContext = Pointer to context information
2242 * CheckForHangTimeInSeconds = Specifies interval in seconds at which
2243 * MiniportCheckForHang should be called
2244 * AttributeFlags = Bitmask that indicates specific attributes
2245 * AdapterType = Specifies the I/O bus interface of the caller's NIC
2248 PLOGICAL_ADAPTER Adapter
= GET_LOGICAL_ADAPTER(MiniportAdapterHandle
);
2250 NDIS_DbgPrint(MAX_TRACE
, ("Called.\n"));
2252 Adapter
->NdisMiniportBlock
.MiniportAdapterContext
= MiniportAdapterContext
;
2253 Adapter
->NdisMiniportBlock
.Flags
= AttributeFlags
;
2254 Adapter
->NdisMiniportBlock
.AdapterType
= AdapterType
;
2255 if (CheckForHangTimeInSeconds
> 0)
2256 Adapter
->NdisMiniportBlock
.CheckForHangSeconds
= CheckForHangTimeInSeconds
;
2257 if (AttributeFlags
& NDIS_ATTRIBUTE_INTERMEDIATE_DRIVER
)
2258 NDIS_DbgPrint(MAX_TRACE
, ("Intermediate drivers not supported yet.\n"));
2268 IN ULONG MicrosecondsToSleep
)
2270 * FUNCTION: delay the thread's execution for MicrosecondsToSleep
2272 * MicrosecondsToSleep: duh...
2274 * - Because this is a blocking call, current IRQL must be < DISPATCH_LEVEL
2278 LARGE_INTEGER DueTime
;
2282 DueTime
.QuadPart
= (-1) * 10 * MicrosecondsToSleep
;
2284 KeInitializeTimer(&Timer
);
2285 KeSetTimer(&Timer
, DueTime
, 0);
2286 KeWaitForSingleObject(&Timer
, Executive
, KernelMode
, FALSE
, 0);
2295 NdisMSynchronizeWithInterrupt(
2296 IN PNDIS_MINIPORT_INTERRUPT Interrupt
,
2297 IN PVOID SynchronizeFunction
,
2298 IN PVOID SynchronizeContext
)
2300 return(KeSynchronizeExecution(Interrupt
->InterruptObject
,
2301 (PKSYNCHRONIZE_ROUTINE
)SynchronizeFunction
,
2302 SynchronizeContext
));
2312 IN NDIS_HANDLE LogHandle
,
2314 IN UINT LogBufferSize
)
2316 PUCHAR Buffer
= LogBuffer
;
2320 for (i
= 0; i
< LogBufferSize
; i
+= 16)
2322 DbgPrint("%08x |", i
);
2323 for (j
= 0; j
< 16; j
++)
2326 if (idx
< LogBufferSize
)
2327 DbgPrint(" %02x", Buffer
[idx
]);
2332 for (j
= 0; j
< 16; j
++)
2335 if (idx
== LogBufferSize
)
2337 if (Buffer
[idx
] >= ' ') /* FIXME: not portable! replace by if (isprint(Buffer[idx])) ? */
2338 DbgPrint("%c", Buffer
[idx
]);
2345 return NDIS_STATUS_FAILURE
;
2354 NdisTerminateWrapper(
2355 IN NDIS_HANDLE NdisWrapperHandle
,
2356 IN PVOID SystemSpecific
)
2358 * FUNCTION: Releases resources allocated by a call to NdisInitializeWrapper
2360 * NdisWrapperHandle = Handle returned by NdisInitializeWrapper (NDIS_M_DRIVER_BLOCK)
2361 * SystemSpecific = Always NULL
2364 PNDIS_M_DRIVER_BLOCK Miniport
= GET_MINIPORT_DRIVER(NdisWrapperHandle
);
2366 NDIS_DbgPrint(MAX_TRACE
, ("Called.\n"));
2368 ExFreePool(Miniport
->RegistryPath
->Buffer
);
2369 ExFreePool(Miniport
->RegistryPath
);
2370 ExFreePool(Miniport
);