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)
8 * CSH 01/08-2000 Created
18 /* See debug.h for debug/trace constants */
19 //ULONG DebugTraceLevel = MIN_TRACE;
20 //ULONG DebugTraceLevel = -1
23 #define SERVICES_ROOT L"\\Registry\\Machine\\System\\CurrentControlSet\\Services\\"
24 #define DEVICE_ROOT L"\\Device\\"
25 #define ROUTE_DATA_SIZE 256 /* adjust as necessary */
28 /* Number of media we know */
29 #define MEDIA_ARRAY_SIZE 15
31 static NDIS_MEDIUM MediaArray
[MEDIA_ARRAY_SIZE
] = {
39 NdisMediumArcnet878_2
,
41 NdisMediumWirelessWan
,
50 LIST_ENTRY MiniportListHead
;
51 KSPIN_LOCK MiniportListLock
;
52 LIST_ENTRY AdapterListHead
;
53 KSPIN_LOCK AdapterListLock
;
54 LIST_ENTRY OrphanAdapterListHead
;
55 KSPIN_LOCK OrphanAdapterListLock
;
65 if ((DebugTraceLevel
| DEBUG_PACKET
) > 0) {
66 Length
= CopyPacketToBuffer(
72 DbgPrint("*** PACKET START ***");
74 for (i
= 0; i
< Length
; i
++) {
76 DbgPrint("\n%04X ", i
);
77 DbgPrint("%02X ", Buffer
[i
]);
80 DbgPrint("*** PACKET STOP ***\n");
89 PLOGICAL_ADAPTER Adapter
,
90 NDIS_HANDLE MacReceiveContext
,
92 UINT HeaderBufferSize
,
93 PVOID LookaheadBuffer
,
94 UINT LookaheadBufferSize
,
97 * FUNCTION: Indicate received data to bound protocols
99 * Adapter = Pointer to logical adapter
100 * MacReceiveContext = MAC receive context handle
101 * HeaderBuffer = Pointer to header buffer
102 * HeaderBufferSize = Size of header buffer
103 * LookaheadBuffer = Pointer to lookahead buffer
104 * LookaheadBufferSize = Size of lookahead buffer
105 * PacketSize = Total size of received packet
109 PLIST_ENTRY CurrentEntry
;
110 PADAPTER_BINDING AdapterBinding
;
112 NDIS_DbgPrint(DEBUG_MINIPORT
, ("Called. Adapter (0x%X) HeaderBuffer (0x%X) "
113 "HeaderBufferSize (0x%X) LookaheadBuffer (0x%X) LookaheadBufferSize (0x%X).\n",
114 Adapter
, HeaderBuffer
, HeaderBufferSize
, LookaheadBuffer
, LookaheadBufferSize
));
118 if ((DebugTraceLevel
| DEBUG_PACKET
) > 0) {
122 DbgPrint("*** RECEIVE PACKET START ***\n");
125 for (i
= 0; i
< HeaderBufferSize
; i
++) {
127 DbgPrint("\n%04X ", i
);
128 DbgPrint("%02X ", *p
);
132 DbgPrint("\nFRAME:");
135 Length
= (LookaheadBufferSize
< 64)? LookaheadBufferSize
: 64;
136 for (i
= 0; i
< Length
; i
++) {
138 DbgPrint("\n%04X ", i
);
139 DbgPrint("%02X ", *p
);
143 DbgPrint("\n*** RECEIVE PACKET STOP ***\n");
148 KeAcquireSpinLock(&Adapter
->NdisMiniportBlock
.Lock
, &OldIrql
);
149 CurrentEntry
= Adapter
->ProtocolListHead
.Flink
;
151 if (CurrentEntry
== &Adapter
->ProtocolListHead
) {
152 NDIS_DbgPrint(DEBUG_MINIPORT
, ("WARNING: No upper protocol layer.\n"));
155 while (CurrentEntry
!= &Adapter
->ProtocolListHead
) {
156 AdapterBinding
= CONTAINING_RECORD(CurrentEntry
,
160 KeReleaseSpinLock(&Adapter
->NdisMiniportBlock
.Lock
, OldIrql
);
162 (*AdapterBinding
->ProtocolBinding
->Chars
.u4
.ReceiveHandler
)(
163 AdapterBinding
->NdisOpenBlock
.ProtocolBindingContext
,
171 KeAcquireSpinLock(&Adapter
->NdisMiniportBlock
.Lock
, &OldIrql
);
173 CurrentEntry
= CurrentEntry
->Flink
;
175 KeReleaseSpinLock(&Adapter
->NdisMiniportBlock
.Lock
, OldIrql
);
180 MiniEthReceiveComplete(
181 IN PETH_FILTER Filter
)
183 * FUNCTION: Receive indication complete function for Ethernet devices
185 * Filter = Pointer to Ethernet filter
189 PLIST_ENTRY CurrentEntry
;
190 PLOGICAL_ADAPTER Adapter
;
191 PADAPTER_BINDING AdapterBinding
;
193 NDIS_DbgPrint(DEBUG_MINIPORT
, ("Called.\n"));
195 Adapter
= (PLOGICAL_ADAPTER
)Filter
->Miniport
;
197 KeAcquireSpinLock(&Adapter
->NdisMiniportBlock
.Lock
, &OldIrql
);
198 CurrentEntry
= Adapter
->ProtocolListHead
.Flink
;
199 while (CurrentEntry
!= &Adapter
->ProtocolListHead
) {
200 AdapterBinding
= CONTAINING_RECORD(CurrentEntry
,
204 KeReleaseSpinLock(&Adapter
->NdisMiniportBlock
.Lock
, OldIrql
);
206 (*AdapterBinding
->ProtocolBinding
->Chars
.ReceiveCompleteHandler
)(
207 AdapterBinding
->NdisOpenBlock
.ProtocolBindingContext
);
209 KeAcquireSpinLock(&Adapter
->NdisMiniportBlock
.Lock
, &OldIrql
);
211 CurrentEntry
= CurrentEntry
->Flink
;
213 KeReleaseSpinLock(&Adapter
->NdisMiniportBlock
.Lock
, OldIrql
);
218 MiniEthReceiveIndication(
219 IN PETH_FILTER Filter
,
220 IN NDIS_HANDLE MacReceiveContext
,
222 IN PVOID HeaderBuffer
,
223 IN UINT HeaderBufferSize
,
224 IN PVOID LookaheadBuffer
,
225 IN UINT LookaheadBufferSize
,
228 * FUNCTION: Receive indication function for Ethernet devices
230 * Filter = Pointer to Ethernet filter
231 * MacReceiveContext = MAC receive context handle
232 * Address = Pointer to destination Ethernet address
233 * HeaderBuffer = Pointer to Ethernet header buffer
234 * HeaderBufferSize = Size of Ethernet header buffer
235 * LookaheadBuffer = Pointer to lookahead buffer
236 * LookaheadBufferSize = Size of lookahead buffer
237 * PacketSize = Total size of received packet
240 MiniIndicateData((PLOGICAL_ADAPTER
)Filter
->Miniport
,
252 IN NDIS_HANDLE MiniportAdapterHandle
,
253 IN NDIS_STATUS Status
,
254 IN BOOLEAN AddressingReset
)
262 IN NDIS_HANDLE MiniportAdapterHandle
,
263 IN PNDIS_PACKET Packet
,
264 IN NDIS_STATUS Status
)
266 * FUNCTION: Forwards a message to the initiating protocol saying
267 * that a packet was handled
269 * NdisAdapterHandle = Handle input to MiniportInitialize
270 * Packet = Pointer to NDIS packet that was sent
271 * Status = Status of send operation
274 PADAPTER_BINDING AdapterBinding
;
276 NDIS_DbgPrint(DEBUG_MINIPORT
, ("Called.\n"));
278 AdapterBinding
= (PADAPTER_BINDING
)Packet
->Reserved
[0];
280 (*AdapterBinding
->ProtocolBinding
->Chars
.u2
.SendCompleteHandler
)(
281 AdapterBinding
->NdisOpenBlock
.ProtocolBindingContext
,
288 MiniSendResourcesAvailable(
289 IN NDIS_HANDLE MiniportAdapterHandle
)
296 MiniTransferDataComplete(
297 IN NDIS_HANDLE MiniportAdapterHandle
,
298 IN PNDIS_PACKET Packet
,
299 IN NDIS_STATUS Status
,
300 IN UINT BytesTransferred
)
302 PLOGICAL_ADAPTER Adapter
= (PLOGICAL_ADAPTER
)MiniportAdapterHandle
;
303 PADAPTER_BINDING AdapterBinding
= Adapter
->MiniportAdapterBinding
;
305 NDIS_DbgPrint(DEBUG_MINIPORT
, ("Called.\n"));
307 (*AdapterBinding
->ProtocolBinding
->Chars
.u3
.TransferDataCompleteHandler
)(
308 AdapterBinding
->NdisOpenBlock
.ProtocolBindingContext
,
316 MiniAdapterHasAddress(
317 PLOGICAL_ADAPTER Adapter
,
320 * FUNCTION: Determines wether a packet has the same destination address as an adapter
322 * Adapter = Pointer to logical adapter object
323 * Packet = Pointer to NDIS packet
325 * TRUE if the destination address is that of the adapter, FALSE if not
331 PNDIS_BUFFER NdisBuffer
;
334 Start1
= (PUCHAR
)&Adapter
->Address
;
335 NdisQueryPacket(Packet
, NULL
, NULL
, &NdisBuffer
, NULL
);
337 NDIS_DbgPrint(MID_TRACE
, ("Packet contains no buffers.\n"));
341 NdisQueryBuffer(NdisBuffer
, (PVOID
)&Start2
, &BufferLength
);
343 /* FIXME: Should handle fragmented packets */
345 switch (Adapter
->NdisMiniportBlock
.MediaType
) {
346 case NdisMedium802_3
:
347 Length
= ETH_LENGTH_OF_ADDRESS
;
348 /* Destination address is the first field */
352 NDIS_DbgPrint(MIN_TRACE
, ("Adapter has unsupported media type (0x%X).\n",
353 Adapter
->NdisMiniportBlock
.MediaType
));
357 if (BufferLength
< Length
) {
358 NDIS_DbgPrint(MID_TRACE
, ("Buffer is too small.\n"));
362 return (RtlCompareMemory((PVOID
)Start1
, (PVOID
)Start2
, Length
) == Length
);
368 PNDIS_STRING AdapterName
)
370 * FUNCTION: Returns the logical adapter object for a specific adapter
372 * AdapterName = Pointer to name of adapter
374 * Pointer to logical adapter object, or NULL if none was found.
375 * If found, the adapter is referenced for the caller. The caller
376 * is responsible for dereferencing after use
380 PLIST_ENTRY CurrentEntry
;
381 PLOGICAL_ADAPTER Adapter
;
383 NDIS_DbgPrint(DEBUG_MINIPORT
, ("Called.\n"));
385 KeAcquireSpinLock(&AdapterListLock
, &OldIrql
);
386 CurrentEntry
= AdapterListHead
.Flink
;
387 while (CurrentEntry
!= &AdapterListHead
) {
388 Adapter
= CONTAINING_RECORD(CurrentEntry
, LOGICAL_ADAPTER
, ListEntry
);
390 if (RtlCompareUnicodeString(AdapterName
, &Adapter
->DeviceName
, TRUE
) == 0) {
391 ReferenceObject(Adapter
);
392 KeReleaseSpinLock(&AdapterListLock
, OldIrql
);
394 NDIS_DbgPrint(DEBUG_MINIPORT
, ("Leaving. Adapter found at (0x%X).\n", Adapter
));
399 CurrentEntry
= CurrentEntry
->Flink
;
401 KeReleaseSpinLock(&AdapterListLock
, OldIrql
);
403 NDIS_DbgPrint(DEBUG_MINIPORT
, ("Leaving (adapter not found).\n"));
410 MiniQueryInformation(
411 PLOGICAL_ADAPTER Adapter
,
416 * FUNCTION: Queries a logical adapter for properties
418 * Adapter = Pointer to the logical adapter object to query
419 * Oid = Specifies the Object ID to query for
420 * Size = If non-zero overrides the length in the adapter object
421 * BytesWritten = Address of buffer to place number of bytes written
423 * If the specified buffer is too small, a new buffer is allocated,
424 * and the query is attempted again
426 * Status of operation
429 NDIS_STATUS NdisStatus
;
432 if (Adapter
->QueryBufferLength
== 0) {
433 Adapter
->QueryBuffer
= ExAllocatePool(NonPagedPool
, (Size
== 0)? 32 : Size
);
435 if (!Adapter
->QueryBuffer
) {
436 NDIS_DbgPrint(MIN_TRACE
, ("Insufficient resources.\n"));
437 return NDIS_STATUS_RESOURCES
;
440 Adapter
->QueryBufferLength
= (Size
== 0)? 32 : Size
;
443 BytesNeeded
= (Size
== 0)? Adapter
->QueryBufferLength
: Size
;
445 NdisStatus
= (*Adapter
->Miniport
->Chars
.QueryInformationHandler
)(
446 Adapter
->NdisMiniportBlock
.MiniportAdapterContext
,
448 Adapter
->QueryBuffer
,
453 if ((NT_SUCCESS(NdisStatus
)) || (NdisStatus
== NDIS_STATUS_PENDING
)) {
454 NDIS_DbgPrint(DEBUG_MINIPORT
, ("Miniport returned status (0x%X).\n", NdisStatus
));
458 if (NdisStatus
== NDIS_STATUS_INVALID_LENGTH
) {
459 ExFreePool(Adapter
->QueryBuffer
);
461 Adapter
->QueryBufferLength
+= BytesNeeded
;
462 Adapter
->QueryBuffer
= ExAllocatePool(NonPagedPool
,
463 Adapter
->QueryBufferLength
);
465 if (!Adapter
->QueryBuffer
) {
466 NDIS_DbgPrint(MIN_TRACE
, ("Insufficient resources.\n"));
467 return NDIS_STATUS_RESOURCES
;
470 NdisStatus
= (*Adapter
->Miniport
->Chars
.QueryInformationHandler
)(
471 Adapter
->NdisMiniportBlock
.MiniportAdapterContext
,
473 Adapter
->QueryBuffer
,
486 PLOGICAL_ADAPTER Adapter
,
487 NDIS_WORK_ITEM_TYPE WorkItemType
,
488 PVOID WorkItemContext
,
489 NDIS_HANDLE Initiator
)
491 * FUNCTION: Queues a work item for execution at a later time
493 * Adapter = Pointer to the logical adapter object to queue work item on
494 * WorkItemType = Type of work item to queue
495 * WorkItemContext = Pointer to context information for work item
496 * Initiator = Pointer to ADAPTER_BINDING structure of initiating protocol
498 * Adapter lock must be held when called
500 * Status of operation
503 PNDIS_MINIPORT_WORK_ITEM Item
;
505 NDIS_DbgPrint(MAX_TRACE
, ("Called.\n"));
507 if (Adapter
->WorkQueueLevel
< NDIS_MINIPORT_WORK_QUEUE_SIZE
- 1) {
508 Item
= &Adapter
->WorkQueue
[Adapter
->WorkQueueLevel
];
509 Adapter
->WorkQueueLevel
++;
511 Item
= ExAllocatePool(NonPagedPool
, sizeof(NDIS_MINIPORT_WORK_ITEM
));
513 /* Set flag so we know that the buffer should be freed
514 when work item is dequeued */
515 Item
->Allocated
= TRUE
;
517 NDIS_DbgPrint(MIN_TRACE
, ("Insufficient resources.\n"));
518 return NDIS_STATUS_RESOURCES
;
522 Item
->WorkItemType
= WorkItemType
;
523 Item
->WorkItemContext
= WorkItemContext
;
524 Item
->Initiator
= Initiator
;
526 Item
->Link
.Next
= NULL
;
527 if (!Adapter
->WorkQueueHead
) {
528 Adapter
->WorkQueueHead
= Item
;
530 Adapter
->WorkQueueTail
->Link
.Next
= (PSINGLE_LIST_ENTRY
)Item
;
533 KeInsertQueueDpc(&Adapter
->MiniportDpc
, NULL
, NULL
);
535 return NDIS_STATUS_SUCCESS
;
542 PLOGICAL_ADAPTER Adapter
,
543 NDIS_WORK_ITEM_TYPE
*WorkItemType
,
544 PVOID
*WorkItemContext
,
545 NDIS_HANDLE
*Initiator
)
547 * FUNCTION: Dequeues a work item from the work queue of a logical adapter
549 * Adapter = Pointer to the logical adapter object to dequeue work item from
550 * WorkItemType = Address of buffer for work item type
551 * WorkItemContext = Address of buffer for pointer to context information
552 * Initiator = Address of buffer for initiator of the work (ADAPTER_BINDING)
554 * Adapter lock must be held when called
556 * Status of operation
559 PNDIS_MINIPORT_WORK_ITEM Item
;
561 NDIS_DbgPrint(MAX_TRACE
, ("Called.\n"));
563 Item
= Adapter
->WorkQueueHead
;
565 Adapter
->WorkQueueHead
= (PNDIS_MINIPORT_WORK_ITEM
)Item
->Link
.Next
;
566 if (Item
== Adapter
->WorkQueueTail
)
567 Adapter
->WorkQueueTail
= NULL
;
569 *WorkItemType
= Item
->WorkItemType
;
570 *WorkItemContext
= Item
->WorkItemContext
;
571 *Initiator
= Item
->Initiator
;
573 if (Item
->Allocated
) {
576 Adapter
->WorkQueueLevel
--;
578 if (Adapter
->WorkQueueLevel
< 0) {
579 NDIS_DbgPrint(MIN_TRACE
, ("Adapter->WorkQueueLevel is < 0 (should be >= 0).\n"));
584 return NDIS_STATUS_SUCCESS
;
587 return NDIS_STATUS_FAILURE
;
593 PLOGICAL_ADAPTER Adapter
,
594 PNDIS_REQUEST NdisRequest
)
596 * FUNCTION: Sends a request to a miniport
598 * Adapter = Pointer to logical adapter object
599 * NdisRequest = Pointer to NDIS request structure describing request
601 * Status of operation
604 Adapter
->NdisMiniportBlock
.MediaRequest
= NdisRequest
;
606 switch (NdisRequest
->RequestType
) {
607 case NdisRequestQueryInformation
:
608 return (*Adapter
->Miniport
->Chars
.QueryInformationHandler
)(
609 Adapter
->NdisMiniportBlock
.MiniportAdapterContext
,
610 NdisRequest
->DATA
.QUERY_INFORMATION
.Oid
,
611 NdisRequest
->DATA
.QUERY_INFORMATION
.InformationBuffer
,
612 NdisRequest
->DATA
.QUERY_INFORMATION
.InformationBufferLength
,
613 (PULONG
)&NdisRequest
->DATA
.QUERY_INFORMATION
.BytesWritten
,
614 (PULONG
)&NdisRequest
->DATA
.QUERY_INFORMATION
.BytesNeeded
);
617 case NdisRequestSetInformation
:
618 return (*Adapter
->Miniport
->Chars
.SetInformationHandler
)(
619 Adapter
->NdisMiniportBlock
.MiniportAdapterContext
,
620 NdisRequest
->DATA
.SET_INFORMATION
.Oid
,
621 NdisRequest
->DATA
.SET_INFORMATION
.InformationBuffer
,
622 NdisRequest
->DATA
.SET_INFORMATION
.InformationBufferLength
,
623 (PULONG
)&NdisRequest
->DATA
.SET_INFORMATION
.BytesRead
,
624 (PULONG
)&NdisRequest
->DATA
.SET_INFORMATION
.BytesNeeded
);
628 return NDIS_STATUS_FAILURE
;
633 VOID STDCALL
MiniportDpc(
635 IN PVOID DeferredContext
,
636 IN PVOID SystemArgument1
,
637 IN PVOID SystemArgument2
)
639 * FUNCTION: Deferred routine to handle serialization
641 * Dpc = Pointer to DPC object
642 * DeferredContext = Pointer to context information (LOGICAL_ADAPTER)
643 * SystemArgument1 = Unused
644 * SystemArgument2 = Unused
647 NDIS_STATUS NdisStatus
;
648 PVOID WorkItemContext
;
649 NDIS_WORK_ITEM_TYPE WorkItemType
;
650 PADAPTER_BINDING AdapterBinding
;
651 PLOGICAL_ADAPTER Adapter
= GET_LOGICAL_ADAPTER(DeferredContext
);
653 NDIS_DbgPrint(DEBUG_MINIPORT
, ("Called.\n"));
655 NdisStatus
= MiniDequeueWorkItem(Adapter
,
658 (PNDIS_HANDLE
)&AdapterBinding
);
659 if (NdisStatus
== NDIS_STATUS_SUCCESS
) {
660 Adapter
->MiniportAdapterBinding
= AdapterBinding
;
661 switch (WorkItemType
) {
662 case NdisWorkItemSend
:
664 MiniDisplayPacket((PNDIS_PACKET
)WorkItemContext
);
666 NdisStatus
= (*Adapter
->Miniport
->Chars
.u1
.SendHandler
)(
667 Adapter
->NdisMiniportBlock
.MiniportAdapterContext
,
668 (PNDIS_PACKET
)WorkItemContext
,
670 if (NdisStatus
!= NDIS_STATUS_PENDING
) {
671 MiniSendComplete((NDIS_HANDLE
)Adapter
,
672 (PNDIS_PACKET
)WorkItemContext
,
677 case NdisWorkItemSendLoopback
:
678 NdisStatus
= ProIndicatePacket(Adapter
,
679 (PNDIS_PACKET
)WorkItemContext
);
680 MiniSendComplete((NDIS_HANDLE
)Adapter
,
681 (PNDIS_PACKET
)WorkItemContext
,
685 case NdisWorkItemReturnPackets
:
688 case NdisWorkItemResetRequested
:
691 case NdisWorkItemResetInProgress
:
694 case NdisWorkItemHalt
:
697 case NdisWorkItemMiniportCallback
:
700 case NdisWorkItemRequest
:
701 NdisStatus
= MiniDoRequest(Adapter
, (PNDIS_REQUEST
)WorkItemContext
);
703 if (NdisStatus
== NDIS_STATUS_PENDING
)
706 switch (((PNDIS_REQUEST
)WorkItemContext
)->RequestType
) {
707 case NdisRequestQueryInformation
:
708 NdisMQueryInformationComplete((NDIS_HANDLE
)Adapter
, NdisStatus
);
711 case NdisRequestSetInformation
:
712 NdisMSetInformationComplete((NDIS_HANDLE
)Adapter
, NdisStatus
);
716 NDIS_DbgPrint(MIN_TRACE
, ("Unknown NDIS request type.\n"));
722 NDIS_DbgPrint(MIN_TRACE
, ("Unknown NDIS work item type (%d).\n", WorkItemType
));
735 IN NDIS_HANDLE LogHandle
)
747 IN NDIS_HANDLE MiniportAdapterHandle
,
749 OUT PNDIS_HANDLE LogHandle
)
753 return NDIS_STATUS_FAILURE
;
762 NdisMDeregisterAdapterShutdownHandler(
763 IN NDIS_HANDLE MiniportHandle
)
765 PLOGICAL_ADAPTER Adapter
= (PLOGICAL_ADAPTER
)MiniportHandle
;
767 if(Adapter
->BugcheckContext
->ShutdownHandler
)
768 KeDeregisterBugCheckCallback(Adapter
->BugcheckContext
->CallbackRecord
);
778 IN NDIS_HANDLE LogHandle
)
790 IN NDIS_HANDLE MiniportAdapterHandle
,
791 IN NDIS_STATUS GeneralStatus
,
792 IN PVOID StatusBuffer
,
793 IN UINT StatusBufferSize
)
804 NdisMIndicateStatusComplete(
805 IN NDIS_HANDLE MiniportAdapterHandle
)
816 NdisInitializeWrapper(
817 OUT PNDIS_HANDLE NdisWrapperHandle
,
818 IN PVOID SystemSpecific1
,
819 IN PVOID SystemSpecific2
,
820 IN PVOID SystemSpecific3
)
822 * FUNCTION: Notifies the NDIS library that a new miniport is initializing
824 * NdisWrapperHandle = Address of buffer to place NDIS wrapper handle
825 * SystemSpecific1 = Pointer to the driver's driver object
826 * SystemSpecific2 = Pointer to the driver's registry path
827 * SystemSpecific3 = Always NULL
829 * - SystemSpecific2 goes invalid so we copy it
830 * - Registry key is 0-terminated for safety
833 PMINIPORT_DRIVER Miniport
;
834 PUNICODE_STRING RegistryPath
;
835 WCHAR
*RegistryBuffer
;
837 NDIS_DbgPrint(MAX_TRACE
, ("Called.\n"));
839 Miniport
= ExAllocatePool(NonPagedPool
, sizeof(MINIPORT_DRIVER
));
841 NDIS_DbgPrint(MIN_TRACE
, ("Insufficient resources.\n"));
842 *NdisWrapperHandle
= NULL
;
846 RtlZeroMemory(Miniport
, sizeof(MINIPORT_DRIVER
));
848 KeInitializeSpinLock(&Miniport
->Lock
);
850 Miniport
->RefCount
= 1;
852 Miniport
->DriverObject
= (PDRIVER_OBJECT
)SystemSpecific1
;
854 /* set the miniport's driver registry path */
855 RegistryPath
= ExAllocatePool(PagedPool
, sizeof(UNICODE_STRING
));
858 NDIS_DbgPrint(MIN_TRACE
, ("Insufficient resources.\n"));
862 RegistryPath
->Length
= ((PUNICODE_STRING
)SystemSpecific2
)->Length
;
863 RegistryPath
->MaximumLength
= RegistryPath
->Length
+ 1; /* room for 0-term */
865 RegistryBuffer
= ExAllocatePool(PagedPool
, RegistryPath
->Length
+ sizeof(WCHAR
));
868 NDIS_DbgPrint(MIN_TRACE
, ("Insufficient resources.\n"));
872 RtlCopyMemory(RegistryBuffer
, ((PUNICODE_STRING
)SystemSpecific2
)->Buffer
, RegistryPath
->Length
);
873 RegistryBuffer
[RegistryPath
->Length
] = 0;
875 RegistryPath
->Buffer
= RegistryBuffer
;
876 Miniport
->RegistryPath
= RegistryPath
;
878 InitializeListHead(&Miniport
->AdapterListHead
);
880 /* Put miniport in global miniport list */
881 ExInterlockedInsertTailList(&MiniportListHead
,
882 &Miniport
->ListEntry
,
885 *NdisWrapperHandle
= Miniport
;
894 NdisMQueryInformationComplete(
895 IN NDIS_HANDLE MiniportAdapterHandle
,
896 IN NDIS_STATUS Status
)
898 PLOGICAL_ADAPTER Adapter
= GET_LOGICAL_ADAPTER(MiniportAdapterHandle
);
899 PADAPTER_BINDING AdapterBinding
= (PADAPTER_BINDING
)Adapter
->MiniportAdapterBinding
;
901 NDIS_DbgPrint(MAX_TRACE
, ("Called.\n"));
903 (*AdapterBinding
->ProtocolBinding
->Chars
.RequestCompleteHandler
)(
904 AdapterBinding
->NdisOpenBlock
.ProtocolBindingContext
,
905 Adapter
->NdisMiniportBlock
.MediaRequest
,
909 VOID
NdisIBugcheckCallback(
913 PMINIPORT_BUGCHECK_CONTEXT Context
= (PMINIPORT_BUGCHECK_CONTEXT
)Buffer
;
914 ADAPTER_SHUTDOWN_HANDLER sh
= (ADAPTER_SHUTDOWN_HANDLER
)Context
->ShutdownHandler
;
917 sh(Context
->DriverContext
);
925 NdisMRegisterAdapterShutdownHandler(
926 IN NDIS_HANDLE MiniportHandle
,
927 IN PVOID ShutdownContext
,
928 IN ADAPTER_SHUTDOWN_HANDLER ShutdownHandler
)
930 PLOGICAL_ADAPTER Adapter
= (PLOGICAL_ADAPTER
)MiniportHandle
;
931 PMINIPORT_BUGCHECK_CONTEXT BugcheckContext
= Adapter
->BugcheckContext
;
933 if(BugcheckContext
->ShutdownHandler
)
936 BugcheckContext
->ShutdownHandler
= ShutdownHandler
;
937 BugcheckContext
->DriverContext
= ShutdownContext
;
939 /* not sure if this needs to be initialized or not... oh well, it's a leak. */
940 BugcheckContext
->CallbackRecord
= ExAllocatePool(NonPagedPool
, sizeof(KBUGCHECK_CALLBACK_RECORD
));
942 KeRegisterBugCheckCallback(BugcheckContext
->CallbackRecord
, NdisIBugcheckCallback
,
943 BugcheckContext
, sizeof(BugcheckContext
), "Ndis Miniport");
949 PLOGICAL_ADAPTER Adapter
,
952 * FUNCTION: Queries miniport for information
954 * Adapter = Pointer to logical adapter
955 * AddressOID = OID to use to query for current address
957 * Status of operation
961 NDIS_STATUS NdisStatus
;
963 NDIS_DbgPrint(MAX_TRACE
, ("Called.\n"));
965 /* Get MAC options for adapter */
966 NdisStatus
= MiniQueryInformation(Adapter
,
970 if (NdisStatus
!= NDIS_STATUS_SUCCESS
) {
971 NDIS_DbgPrint(MIN_TRACE
, ("OID_GEN_MAC_OPTIONS failed. NdisStatus (0x%X).\n", NdisStatus
));
975 RtlCopyMemory(&Adapter
->NdisMiniportBlock
.MacOptions
, Adapter
->QueryBuffer
, sizeof(UINT
));
977 NDIS_DbgPrint(DEBUG_MINIPORT
, ("MacOptions (0x%X).\n", Adapter
->NdisMiniportBlock
.MacOptions
));
979 /* Get current hardware address of adapter */
980 NdisStatus
= MiniQueryInformation(Adapter
,
984 if (NdisStatus
!= NDIS_STATUS_SUCCESS
) {
985 NDIS_DbgPrint(MIN_TRACE
, ("Address OID (0x%X) failed. NdisStatus (0x%X).\n",
986 AddressOID
, NdisStatus
));
990 RtlCopyMemory(&Adapter
->Address
, Adapter
->QueryBuffer
, Adapter
->AddressLength
);
995 PUCHAR A
= (PUCHAR
)&Adapter
->Address
.Type
.Medium802_3
;
997 NDIS_DbgPrint(MAX_TRACE
, ("Adapter address is (%02X %02X %02X %02X %02X %02X).\n",
998 A
[0], A
[1], A
[2], A
[3], A
[4], A
[5]));
1002 /* Get maximum lookahead buffer size of adapter */
1003 NdisStatus
= MiniQueryInformation(Adapter
,
1004 OID_GEN_MAXIMUM_LOOKAHEAD
,
1007 if (NdisStatus
!= NDIS_STATUS_SUCCESS
) {
1008 NDIS_DbgPrint(MIN_TRACE
, ("OID_GEN_MAXIMUM_LOOKAHEAD failed. NdisStatus (0x%X).\n", NdisStatus
));
1012 Adapter
->MaxLookaheadLength
= *((PULONG
)Adapter
->QueryBuffer
);
1014 NDIS_DbgPrint(DEBUG_MINIPORT
, ("MaxLookaheadLength (0x%X).\n", Adapter
->MaxLookaheadLength
));
1016 /* Get current lookahead buffer size of adapter */
1017 NdisStatus
= MiniQueryInformation(Adapter
,
1018 OID_GEN_CURRENT_LOOKAHEAD
,
1021 if (NdisStatus
!= NDIS_STATUS_SUCCESS
) {
1022 NDIS_DbgPrint(MIN_TRACE
, ("OID_GEN_CURRENT_LOOKAHEAD failed. NdisStatus (0x%X).\n", NdisStatus
));
1026 Adapter
->CurLookaheadLength
= *((PULONG
)Adapter
->QueryBuffer
);
1028 NDIS_DbgPrint(DEBUG_MINIPORT
, ("CurLookaheadLength (0x%X).\n", Adapter
->CurLookaheadLength
));
1030 if (Adapter
->MaxLookaheadLength
!= 0) {
1031 Adapter
->LookaheadLength
= Adapter
->MaxLookaheadLength
+
1032 Adapter
->MediumHeaderSize
;
1033 Adapter
->LookaheadBuffer
= ExAllocatePool(NonPagedPool
,
1034 Adapter
->LookaheadLength
);
1035 if (!Adapter
->LookaheadBuffer
)
1036 return NDIS_STATUS_RESOURCES
;
1039 return STATUS_SUCCESS
;
1048 NdisMRegisterMiniport(
1049 IN NDIS_HANDLE NdisWrapperHandle
,
1050 IN PNDIS_MINIPORT_CHARACTERISTICS MiniportCharacteristics
,
1051 IN UINT CharacteristicsLength
)
1053 * FUNCTION: Registers a miniport's MiniportXxx entry points with the NDIS library
1055 * NdisWrapperHandle = Pointer to handle returned by NdisMInitializeWrapper
1056 * MiniportCharacteristics = Pointer to a buffer with miniport characteristics
1057 * CharacteristicsLength = Number of bytes in characteristics buffer
1059 * Status of operation
1061 * - To create device objects for the miniport, the Route value under Linkage is
1062 * parsed. I don't know if this is the way Microsoft does it or not.
1064 * verify this algorithm by playing with nt
1065 * break this function up
1071 NDIS_STATUS NdisStatus
;
1072 NDIS_STATUS OpenErrorStatus
;
1073 UINT SelectedMediumIndex
;
1074 PLOGICAL_ADAPTER Adapter
;
1075 NDIS_OID AddressOID
;
1076 BOOLEAN MemError
= FALSE
;
1077 PMINIPORT_DRIVER Miniport
= GET_MINIPORT_DRIVER(NdisWrapperHandle
);
1078 OBJECT_ATTRIBUTES DeviceKeyAttributes
;
1079 OBJECT_ATTRIBUTES LinkageKeyAttributes
;
1080 HANDLE DeviceKeyHandle
;
1081 HANDLE LinkageKeyHandle
;
1082 UNICODE_STRING RouteVal
;
1083 UNICODE_STRING LinkageKeyName
;
1084 KEY_VALUE_PARTIAL_INFORMATION
*RouteData
;
1085 ULONG RouteDataLength
;
1086 UINT NextRouteOffset
= 0;
1088 NDIS_DbgPrint(MAX_TRACE
, ("Called.\n"));
1090 switch (MiniportCharacteristics
->MajorNdisVersion
) {
1092 MinSize
= sizeof(NDIS30_MINIPORT_CHARACTERISTICS_S
);
1096 MinSize
= sizeof(NDIS40_MINIPORT_CHARACTERISTICS_S
);
1100 MinSize
= sizeof(NDIS50_MINIPORT_CHARACTERISTICS_S
);
1104 NDIS_DbgPrint(DEBUG_MINIPORT
, ("Bad miniport characteristics version.\n"));
1105 return NDIS_STATUS_BAD_VERSION
;
1108 if (CharacteristicsLength
< MinSize
) {
1109 NDIS_DbgPrint(DEBUG_MINIPORT
, ("Bad miniport characteristics.\n"));
1110 return NDIS_STATUS_BAD_CHARACTERISTICS
;
1113 /* Check if mandatory MiniportXxx functions are specified */
1114 if ((!MiniportCharacteristics
->HaltHandler
) ||
1115 (!MiniportCharacteristics
->InitializeHandler
)||
1116 (!MiniportCharacteristics
->QueryInformationHandler
) ||
1117 (!MiniportCharacteristics
->ResetHandler
) ||
1118 (!MiniportCharacteristics
->SetInformationHandler
)) {
1119 NDIS_DbgPrint(DEBUG_MINIPORT
, ("Bad miniport characteristics.\n"));
1120 return NDIS_STATUS_BAD_CHARACTERISTICS
;
1123 if (MiniportCharacteristics
->MajorNdisVersion
== 0x03) {
1124 if (!MiniportCharacteristics
->u1
.SendHandler
) {
1125 NDIS_DbgPrint(DEBUG_MINIPORT
, ("Bad miniport characteristics.\n"));
1126 return NDIS_STATUS_BAD_CHARACTERISTICS
;
1128 } else if (MiniportCharacteristics
->MajorNdisVersion
>= 0x04) {
1130 if ((!MiniportCharacteristics
->u1
.SendHandler
) &&
1131 (!MiniportCharacteristics
->SendPacketsHandler
)) {
1132 NDIS_DbgPrint(DEBUG_MINIPORT
, ("Bad miniport characteristics.\n"));
1133 return NDIS_STATUS_BAD_CHARACTERISTICS
;
1137 RtlCopyMemory(&Miniport
->Chars
, MiniportCharacteristics
, MinSize
);
1139 /* Read the miniport config from the registry */
1140 InitializeObjectAttributes(&DeviceKeyAttributes
, Miniport
->RegistryPath
, OBJ_CASE_INSENSITIVE
, NULL
, NULL
);
1142 Status
= ZwOpenKey(&DeviceKeyHandle
, KEY_READ
, &DeviceKeyAttributes
);
1143 if(!NT_SUCCESS(Status
))
1145 NDIS_DbgPrint(MIN_TRACE
,("Failed to open driver key: 0x%x\n", Status
));
1146 return NDIS_STATUS_FAILURE
;
1149 RtlInitUnicodeString(&LinkageKeyName
, L
"Linkage");
1150 InitializeObjectAttributes(&LinkageKeyAttributes
, &LinkageKeyName
, OBJ_CASE_INSENSITIVE
, DeviceKeyHandle
, NULL
);
1152 Status
= ZwOpenKey(&LinkageKeyHandle
, KEY_READ
, &LinkageKeyAttributes
);
1153 if(!NT_SUCCESS(Status
))
1155 NDIS_DbgPrint(MIN_TRACE
,("Failed to open Linkage key: 0x%x\n", Status
));
1156 ZwClose(DeviceKeyHandle
);
1157 return NDIS_STATUS_FAILURE
;
1160 RouteData
= ExAllocatePool(PagedPool
, ROUTE_DATA_SIZE
);
1163 NDIS_DbgPrint(MIN_TRACE
,("Insufficient resources\n"));
1164 ZwClose(LinkageKeyHandle
);
1165 ZwClose(DeviceKeyHandle
);
1166 return NDIS_STATUS_RESOURCES
;
1169 RtlInitUnicodeString(&RouteVal
, L
"Route");
1171 Status
= ZwQueryValueKey(LinkageKeyHandle
, &RouteVal
, KeyValuePartialInformation
, RouteData
, ROUTE_DATA_SIZE
, &RouteDataLength
);
1172 if(!NT_SUCCESS(Status
))
1174 NDIS_DbgPrint(MIN_TRACE
,("Failed to query Route value\n"));
1175 ZwClose(LinkageKeyHandle
);
1176 ZwClose(DeviceKeyHandle
);
1177 ExFreePool(RouteData
);
1178 return NDIS_STATUS_FAILURE
;
1181 ZwClose(LinkageKeyHandle
);
1182 ZwClose(DeviceKeyHandle
);
1184 /* route is a REG_MULTI_SZ with each nic object created by NDI - create an adapter for each */
1185 while((RouteData
->Data
)[NextRouteOffset
])
1188 HANDLE RegKeyHandle
;
1190 UNICODE_STRING RegKeyPathU
;
1191 OBJECT_ATTRIBUTES RegKeyAttributes
;
1193 Adapter
= ExAllocatePool(NonPagedPool
, sizeof(LOGICAL_ADAPTER
));
1195 NDIS_DbgPrint(MIN_TRACE
, ("Insufficient resources.\n"));
1196 ExFreePool(RouteData
);
1197 return NDIS_STATUS_RESOURCES
;
1200 /* This is very important */
1201 RtlZeroMemory(Adapter
, sizeof(LOGICAL_ADAPTER
));
1203 DeviceName
= ExAllocatePool(NonPagedPool
, sizeof(DEVICE_ROOT
) + RouteData
->DataLength
);
1206 NDIS_DbgPrint(MIN_TRACE
,("Insufficient memory\n"));
1207 ExFreePool(Adapter
);
1208 ExFreePool(RouteData
);
1209 return NDIS_STATUS_RESOURCES
;
1212 wcscpy(DeviceName
, DEVICE_ROOT
);
1213 wcsncat(DeviceName
, (WCHAR
*)RouteData
->Data
, RouteData
->DataLength
); /* reg_sz is 0-term by def */
1214 RtlInitUnicodeString(&Adapter
->DeviceName
, DeviceName
);
1216 NDIS_DbgPrint(MAX_TRACE
, ("creating device %ws\n", DeviceName
));
1218 Status
= IoCreateDevice(Miniport
->DriverObject
, 0, &Adapter
->DeviceName
, FILE_DEVICE_PHYSICAL_NETCARD
,
1219 0, FALSE
, &Adapter
->NdisMiniportBlock
.DeviceObject
);
1220 if (!NT_SUCCESS(Status
)) {
1221 NDIS_DbgPrint(MIN_TRACE
, ("Could not create device object.\n"));
1222 ExFreePool(Adapter
);
1223 ExFreePool(RouteData
);
1224 return NDIS_STATUS_FAILURE
;
1227 RegKeyPath
= ExAllocatePool(PagedPool
, sizeof(SERVICES_ROOT
)+RouteData
->DataLength
); /* includes room for a 0-term */
1230 NDIS_DbgPrint(MIN_TRACE
,("Insufficient resources\n"));
1231 ExFreePool(Adapter
);
1232 ExFreePool(RouteData
);
1233 return NDIS_STATUS_FAILURE
;
1236 wcscpy(RegKeyPath
, SERVICES_ROOT
);
1237 wcsncat(RegKeyPath
, (WCHAR
*)RouteData
->Data
, RouteData
->DataLength
);
1238 RegKeyPath
[sizeof(SERVICES_ROOT
)+RouteData
->DataLength
-1] = 0;
1240 RtlInitUnicodeString(&RegKeyPathU
, RegKeyPath
);
1241 InitializeObjectAttributes(&RegKeyAttributes
, &RegKeyPathU
, OBJ_CASE_INSENSITIVE
, NULL
, NULL
);
1243 Status
= ZwOpenKey(&RegKeyHandle
, KEY_ALL_ACCESS
, &RegKeyAttributes
);
1244 if(Status
!= STATUS_SUCCESS
)
1246 NDIS_DbgPrint(MIN_TRACE
,("ndis!NdisMRegisterMiniport: failed to open adapter-specific reg key %ws\n", RegKeyPath
));
1247 ExFreePool(Adapter
);
1248 ExFreePool(RouteData
);
1249 return NDIS_STATUS_FAILURE
;
1252 KeInitializeSpinLock(&Adapter
->NdisMiniportBlock
.Lock
);
1253 InitializeListHead(&Adapter
->ProtocolListHead
);
1254 Adapter
->RefCount
= 1;
1255 Adapter
->Miniport
= Miniport
;
1257 /* Set handlers (some NDIS macros require these) */
1259 Adapter
->NdisMiniportBlock
.EthRxCompleteHandler
= MiniEthReceiveComplete
;
1260 Adapter
->NdisMiniportBlock
.EthRxIndicateHandler
= MiniEthReceiveIndication
;
1261 Adapter
->NdisMiniportBlock
.SendCompleteHandler
= MiniSendComplete
;
1262 Adapter
->NdisMiniportBlock
.SendResourcesHandler
= MiniSendResourcesAvailable
;
1263 Adapter
->NdisMiniportBlock
.ResetCompleteHandler
= MiniResetComplete
;
1264 Adapter
->NdisMiniportBlock
.TDCompleteHandler
= MiniTransferDataComplete
;
1266 KeInitializeDpc(&Adapter
->MiniportDpc
, MiniportDpc
, (PVOID
)Adapter
);
1268 /* Put adapter in adapter list for this miniport */
1269 ExInterlockedInsertTailList(&Miniport
->AdapterListHead
, &Adapter
->MiniportListEntry
, &Miniport
->Lock
);
1271 /* Put adapter in global adapter list */
1272 ExInterlockedInsertTailList(&AdapterListHead
, &Adapter
->ListEntry
, &AdapterListLock
);
1274 /* Call MiniportInitialize */
1275 NDIS_DbgPrint(MID_TRACE
, ("calling MiniportInitialize\n"));
1276 NdisStatus
= (*Miniport
->Chars
.InitializeHandler
)( &OpenErrorStatus
, &SelectedMediumIndex
, &MediaArray
[0],
1277 MEDIA_ARRAY_SIZE
, Adapter
, RegKeyHandle
);
1279 ZwClose(RegKeyHandle
);
1281 if ((NdisStatus
== NDIS_STATUS_SUCCESS
) && (SelectedMediumIndex
< MEDIA_ARRAY_SIZE
)) {
1283 NDIS_DbgPrint(MID_TRACE
,("successful return from MiniportInitialize\n"));
1285 Adapter
->NdisMiniportBlock
.MediaType
= MediaArray
[SelectedMediumIndex
];
1287 switch (Adapter
->NdisMiniportBlock
.MediaType
) {
1288 case NdisMedium802_3
:
1289 Adapter
->MediumHeaderSize
= 14;
1290 AddressOID
= OID_802_3_CURRENT_ADDRESS
;
1291 Adapter
->AddressLength
= ETH_LENGTH_OF_ADDRESS
;
1293 Adapter
->NdisMiniportBlock
.FilterDbs
.u
.EthDB
= ExAllocatePool(NonPagedPool
, sizeof(ETH_FILTER
));
1294 if (Adapter
->NdisMiniportBlock
.FilterDbs
.u
.EthDB
) {
1295 RtlZeroMemory(Adapter
->NdisMiniportBlock
.FilterDbs
.u
.EthDB
, sizeof(ETH_FILTER
));
1296 Adapter
->NdisMiniportBlock
.FilterDbs
.u
.EthDB
->Miniport
= (PNDIS_MINIPORT_BLOCK
)Adapter
;
1302 /* FIXME: Support other types of media */
1303 ExFreePool(Adapter
);
1304 ExFreePool(RouteData
);
1306 return NDIS_STATUS_FAILURE
;
1309 NdisStatus
= DoQueries(Adapter
, AddressOID
);
1312 if ((MemError
) || (NdisStatus
!= NDIS_STATUS_SUCCESS
) || (SelectedMediumIndex
>= MEDIA_ARRAY_SIZE
)) {
1314 /* Remove adapter from adapter list for this miniport */
1315 KeAcquireSpinLock(&Miniport
->Lock
, &OldIrql
);
1316 RemoveEntryList(&Adapter
->MiniportListEntry
);
1317 KeReleaseSpinLock(&Miniport
->Lock
, OldIrql
);
1319 /* Remove adapter from global adapter list */
1320 KeAcquireSpinLock(&AdapterListLock
, &OldIrql
);
1321 RemoveEntryList(&Adapter
->ListEntry
);
1322 KeReleaseSpinLock(&AdapterListLock
, OldIrql
);
1324 if (Adapter
->LookaheadBuffer
)
1325 ExFreePool(Adapter
->LookaheadBuffer
);
1327 IoDeleteDevice(Adapter
->NdisMiniportBlock
.DeviceObject
);
1328 ExFreePool(Adapter
);
1329 NDIS_DbgPrint(MIN_TRACE
, ("MiniportInitialize() failed for an adapter.\n"));
1332 NextRouteOffset
+= wcslen((WCHAR
*)RouteData
->Data
);
1335 ExFreePool(RouteData
);
1336 return NDIS_STATUS_SUCCESS
;
1346 IN NDIS_HANDLE MiniportAdapterHandle
,
1347 IN NDIS_STATUS Status
,
1348 IN BOOLEAN AddressingReset
)
1350 MiniResetComplete(MiniportAdapterHandle
,
1362 IN NDIS_HANDLE MiniportAdapterHandle
,
1363 IN PNDIS_PACKET Packet
,
1364 IN NDIS_STATUS Status
)
1366 * FUNCTION: Forwards a message to the initiating protocol saying
1367 * that a packet was handled
1369 * NdisAdapterHandle = Handle input to MiniportInitialize
1370 * Packet = Pointer to NDIS packet that was sent
1371 * Status = Status of send operation
1374 MiniSendComplete(MiniportAdapterHandle
,
1385 NdisMSendResourcesAvailable(
1386 IN NDIS_HANDLE MiniportAdapterHandle
)
1388 MiniSendResourcesAvailable(MiniportAdapterHandle
);
1397 NdisMTransferDataComplete(
1398 IN NDIS_HANDLE MiniportAdapterHandle
,
1399 IN PNDIS_PACKET Packet
,
1400 IN NDIS_STATUS Status
,
1401 IN UINT BytesTransferred
)
1403 MiniTransferDataComplete(MiniportAdapterHandle
,
1415 NdisMSetInformationComplete(
1416 IN NDIS_HANDLE MiniportAdapterHandle
,
1417 IN NDIS_STATUS Status
)
1419 PLOGICAL_ADAPTER Adapter
= GET_LOGICAL_ADAPTER(MiniportAdapterHandle
);
1420 PADAPTER_BINDING AdapterBinding
= (PADAPTER_BINDING
)Adapter
->MiniportAdapterBinding
;
1422 NDIS_DbgPrint(MAX_TRACE
, ("Called.\n"));
1424 (*AdapterBinding
->ProtocolBinding
->Chars
.RequestCompleteHandler
)(
1425 AdapterBinding
->NdisOpenBlock
.ProtocolBindingContext
,
1426 Adapter
->NdisMiniportBlock
.MediaRequest
,
1437 IN NDIS_HANDLE MiniportAdapterHandle
,
1438 IN NDIS_HANDLE MiniportAdapterContext
,
1439 IN BOOLEAN BusMaster
,
1440 IN NDIS_INTERFACE_TYPE AdapterType
)
1442 * FUNCTION: Informs the NDIS library of significant features of the caller's NIC
1444 * MiniportAdapterHandle = Handle input to MiniportInitialize
1445 * MiniportAdapterContext = Pointer to context information
1446 * BusMaster = Specifies TRUE if the caller's NIC is a busmaster DMA device
1447 * AdapterType = Specifies the I/O bus interface of the caller's NIC
1450 PLOGICAL_ADAPTER Adapter
= GET_LOGICAL_ADAPTER(MiniportAdapterHandle
);
1452 NDIS_DbgPrint(MAX_TRACE
, ("Called.\n"));
1454 Adapter
->NdisMiniportBlock
.MiniportAdapterContext
= MiniportAdapterContext
;
1455 Adapter
->Attributes
= BusMaster
? NDIS_ATTRIBUTE_BUS_MASTER
: 0;
1456 Adapter
->NdisMiniportBlock
.AdapterType
= AdapterType
;
1457 Adapter
->AttributesSet
= TRUE
;
1466 NdisMSetAttributesEx(
1467 IN NDIS_HANDLE MiniportAdapterHandle
,
1468 IN NDIS_HANDLE MiniportAdapterContext
,
1469 IN UINT CheckForHangTimeInSeconds OPTIONAL
,
1470 IN ULONG AttributeFlags
,
1471 IN NDIS_INTERFACE_TYPE AdapterType
)
1473 * FUNCTION: Informs the NDIS library of significant features of the caller's NIC
1475 * MiniportAdapterHandle = Handle input to MiniportInitialize
1476 * MiniportAdapterContext = Pointer to context information
1477 * CheckForHangTimeInSeconds = Specifies interval in seconds at which
1478 * MiniportCheckForHang should be called
1479 * AttributeFlags = Bitmask that indicates specific attributes
1480 * AdapterType = Specifies the I/O bus interface of the caller's NIC
1483 // Currently just like NdisMSetAttributesEx
1484 // TODO: Take CheckForHandTimeInSeconds into account!
1485 PLOGICAL_ADAPTER Adapter
= GET_LOGICAL_ADAPTER(MiniportAdapterHandle
);
1487 NDIS_DbgPrint(MAX_TRACE
, ("Called.\n"));
1488 NDIS_DbgPrint(MIN_TRACE
, ("NdisMSetAttributesEx() is partly-implemented."));
1490 Adapter
->NdisMiniportBlock
.MiniportAdapterContext
= MiniportAdapterContext
;
1491 Adapter
->Attributes
= AttributeFlags
& NDIS_ATTRIBUTE_BUS_MASTER
;
1492 Adapter
->NdisMiniportBlock
.AdapterType
= AdapterType
;
1493 Adapter
->AttributesSet
= TRUE
;
1503 IN ULONG MicrosecondsToSleep
)
1514 NdisMSynchronizeWithInterrupt(
1515 IN PNDIS_MINIPORT_INTERRUPT Interrupt
,
1516 IN PVOID SynchronizeFunction
,
1517 IN PVOID SynchronizeContext
)
1531 IN NDIS_HANDLE LogHandle
,
1533 IN UINT LogBufferSize
)
1537 return NDIS_STATUS_FAILURE
;
1546 NdisTerminateWrapper(
1547 IN NDIS_HANDLE NdisWrapperHandle
,
1548 IN PVOID SystemSpecific
)
1550 * FUNCTION: Releases resources allocated by a call to NdisInitializeWrapper
1552 * NdisWrapperHandle = Handle returned by NdisInitializeWrapper (MINIPORT_DRIVER)
1553 * SystemSpecific = Always NULL
1556 PMINIPORT_DRIVER Miniport
= GET_MINIPORT_DRIVER(NdisWrapperHandle
);
1558 NDIS_DbgPrint(MAX_TRACE
, ("Called.\n"));
1560 ExFreePool(Miniport
->RegistryPath
->Buffer
);
1561 ExFreePool(Miniport
->RegistryPath
);
1562 ExFreePool(Miniport
);
1569 ULONG KeyInformationSize;
1570 KEY_BASIC_INFORMATION *KeyInformation;
1573 KeyInformation = ExAllocatePool(PagedPool, 1024);
1574 ASSERT(KeyInformation);
1576 RtlInitUnicodeString(&LinkageKeyName, L"\\Registry\\Machine\\System\\CurrentControlSet\\Services\\NE2000");
1577 InitializeObjectAttributes(&LinkageKeyAttributes, &LinkageKeyName, OBJ_CASE_INSENSITIVE|OBJ_KERNEL_HANDLE, NULL, NULL);
1579 Status = ZwOpenKey(&LinkageKeyHandle, KEY_READ, &LinkageKeyAttributes);
1580 if(!NT_SUCCESS(Status))
1582 DbgPrint("ndis!NdisMRegisterMiniport: Failed to open Linkage key: 0x%x\n", Status);
1589 Status = ZwEnumerateKey(LinkageKeyHandle, i, KeyBasicInformation, KeyInformation, 1024, &KeyInformationSize);
1590 if(!NT_SUCCESS(Status))
1592 DbgPrint("ndis!NdisMRegisterMiniport: Failed to enumerate: 0x%x\n", Status);
1596 KeyInformation->Name[KeyInformation->NameLength] = 0;
1597 DbgPrint("ndis!NdisMRegisterMiniport: enumerated key %ws\n", KeyInformation->Name);
1600 ExFreePool(KeyInformation);