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
17 /* Number of media we know */
18 #define MEDIA_ARRAY_SIZE 15
20 static NDIS_MEDIUM MediaArray
[MEDIA_ARRAY_SIZE
] = {
28 NdisMediumArcnet878_2
,
30 NdisMediumWirelessWan
,
39 LIST_ENTRY MiniportListHead
;
40 KSPIN_LOCK MiniportListLock
;
41 LIST_ENTRY AdapterListHead
;
42 KSPIN_LOCK AdapterListLock
;
53 if ((DebugTraceLevel
| DEBUG_PACKET
) > 0) {
54 Length
= CopyPacketToBuffer(
60 DbgPrint("*** PACKET START ***");
62 for (i
= 0; i
< Length
; i
++) {
64 DbgPrint("\n%04X ", i
);
65 DbgPrint("%02X ", Buffer
[i
]);
68 DbgPrint("*** PACKET STOP ***\n");
77 PLOGICAL_ADAPTER Adapter
,
78 NDIS_HANDLE MacReceiveContext
,
80 UINT HeaderBufferSize
,
81 PVOID LookaheadBuffer
,
82 UINT LookaheadBufferSize
,
85 * FUNCTION: Indicate received data to bound protocols
87 * Adapter = Pointer to logical adapter
88 * MacReceiveContext = MAC receive context handle
89 * HeaderBuffer = Pointer to header buffer
90 * HeaderBufferSize = Size of header buffer
91 * LookaheadBuffer = Pointer to lookahead buffer
92 * LookaheadBufferSize = Size of lookahead buffer
93 * PacketSize = Total size of received packet
97 PLIST_ENTRY CurrentEntry
;
98 PADAPTER_BINDING AdapterBinding
;
100 NDIS_DbgPrint(DEBUG_MINIPORT
, ("Called. Adapter (0x%X) HeaderBuffer (0x%X) "
101 "HeaderBufferSize (0x%X) LookaheadBuffer (0x%X) LookaheadBufferSize (0x%X).\n",
102 Adapter
, HeaderBuffer
, HeaderBufferSize
, LookaheadBuffer
, LookaheadBufferSize
));
106 if ((DebugTraceLevel
| DEBUG_PACKET
) > 0) {
110 DbgPrint("*** RECEIVE PACKET START ***\n");
113 for (i
= 0; i
< HeaderBufferSize
; i
++) {
115 DbgPrint("\n%04X ", i
);
116 DbgPrint("%02X ", *p
);
120 DbgPrint("\nFRAME:\n");
123 Length
= (LookaheadBufferSize
< 64)? LookaheadBufferSize
: 64;
124 for (i
= 0; i
< Length
; i
++) {
126 DbgPrint("\n%04X ", i
);
127 DbgPrint("%02X ", *p
);
131 DbgPrint("\n*** RECEIVE PACKET STOP ***\n");
136 KeAcquireSpinLock(&Adapter
->NdisMiniportBlock
.Lock
, &OldIrql
);
137 CurrentEntry
= Adapter
->ProtocolListHead
.Flink
;
138 while (CurrentEntry
!= &Adapter
->ProtocolListHead
) {
139 AdapterBinding
= CONTAINING_RECORD(CurrentEntry
,
143 KeReleaseSpinLock(&Adapter
->NdisMiniportBlock
.Lock
, OldIrql
);
145 (*AdapterBinding
->ProtocolBinding
->Chars
.u4
.ReceiveHandler
)(
146 AdapterBinding
->NdisOpenBlock
.ProtocolBindingContext
,
154 KeAcquireSpinLock(&Adapter
->NdisMiniportBlock
.Lock
, &OldIrql
);
156 CurrentEntry
= CurrentEntry
->Flink
;
158 KeReleaseSpinLock(&Adapter
->NdisMiniportBlock
.Lock
, OldIrql
);
163 MiniEthReceiveComplete(
164 IN PETH_FILTER Filter
)
166 * FUNCTION: Receive indication complete function for Ethernet devices
168 * Filter = Pointer to Ethernet filter
172 PLIST_ENTRY CurrentEntry
;
173 PLOGICAL_ADAPTER Adapter
;
174 PADAPTER_BINDING AdapterBinding
;
176 NDIS_DbgPrint(DEBUG_MINIPORT
, ("Called.\n"));
178 Adapter
= (PLOGICAL_ADAPTER
)Filter
->Miniport
;
180 KeAcquireSpinLock(&Adapter
->NdisMiniportBlock
.Lock
, &OldIrql
);
181 CurrentEntry
= Adapter
->ProtocolListHead
.Flink
;
182 while (CurrentEntry
!= &Adapter
->ProtocolListHead
) {
183 AdapterBinding
= CONTAINING_RECORD(CurrentEntry
,
187 KeReleaseSpinLock(&Adapter
->NdisMiniportBlock
.Lock
, OldIrql
);
189 (*AdapterBinding
->ProtocolBinding
->Chars
.ReceiveCompleteHandler
)(
190 AdapterBinding
->NdisOpenBlock
.ProtocolBindingContext
);
192 KeAcquireSpinLock(&Adapter
->NdisMiniportBlock
.Lock
, &OldIrql
);
194 CurrentEntry
= CurrentEntry
->Flink
;
196 KeReleaseSpinLock(&Adapter
->NdisMiniportBlock
.Lock
, OldIrql
);
201 MiniEthReceiveIndication(
202 IN PETH_FILTER Filter
,
203 IN NDIS_HANDLE MacReceiveContext
,
205 IN PVOID HeaderBuffer
,
206 IN UINT HeaderBufferSize
,
207 IN PVOID LookaheadBuffer
,
208 IN UINT LookaheadBufferSize
,
211 * FUNCTION: Receive indication function for Ethernet devices
213 * Filter = Pointer to Ethernet filter
214 * MacReceiveContext = MAC receive context handle
215 * Address = Pointer to destination Ethernet address
216 * HeaderBuffer = Pointer to Ethernet header buffer
217 * HeaderBufferSize = Size of Ethernet header buffer
218 * LookaheadBuffer = Pointer to lookahead buffer
219 * LookaheadBufferSize = Size of lookahead buffer
220 * PacketSize = Total size of received packet
223 MiniIndicateData((PLOGICAL_ADAPTER
)Filter
->Miniport
,
235 IN NDIS_HANDLE MiniportAdapterHandle
,
236 IN NDIS_STATUS Status
,
237 IN BOOLEAN AddressingReset
)
245 IN NDIS_HANDLE MiniportAdapterHandle
,
246 IN PNDIS_PACKET Packet
,
247 IN NDIS_STATUS Status
)
249 * FUNCTION: Forwards a message to the initiating protocol saying
250 * that a packet was handled
252 * NdisAdapterHandle = Handle input to MiniportInitialize
253 * Packet = Pointer to NDIS packet that was sent
254 * Status = Status of send operation
257 PADAPTER_BINDING AdapterBinding
;
259 NDIS_DbgPrint(DEBUG_MINIPORT
, ("Called.\n"));
261 AdapterBinding
= (PADAPTER_BINDING
)Packet
->Reserved
[0];
263 (*AdapterBinding
->ProtocolBinding
->Chars
.u2
.SendCompleteHandler
)(
264 AdapterBinding
->NdisOpenBlock
.ProtocolBindingContext
,
271 MiniSendResourcesAvailable(
272 IN NDIS_HANDLE MiniportAdapterHandle
)
279 MiniTransferDataComplete(
280 IN NDIS_HANDLE MiniportAdapterHandle
,
281 IN PNDIS_PACKET Packet
,
282 IN NDIS_STATUS Status
,
283 IN UINT BytesTransferred
)
285 PLOGICAL_ADAPTER Adapter
= (PLOGICAL_ADAPTER
)MiniportAdapterHandle
;
286 PADAPTER_BINDING AdapterBinding
= Adapter
->MiniportAdapterBinding
;
288 NDIS_DbgPrint(DEBUG_MINIPORT
, ("Called.\n"));
290 (*AdapterBinding
->ProtocolBinding
->Chars
.u3
.TransferDataCompleteHandler
)(
291 AdapterBinding
->NdisOpenBlock
.ProtocolBindingContext
,
299 MiniAdapterHasAddress(
300 PLOGICAL_ADAPTER Adapter
,
303 * FUNCTION: Determines wether a packet has the same destination address as an adapter
305 * Adapter = Pointer to logical adapter object
306 * Packet = Pointer to NDIS packet
308 * TRUE if the destination address is that of the adapter, FALSE if not
314 PNDIS_BUFFER NdisBuffer
;
317 Start1
= (PUCHAR
)&Adapter
->Address
;
318 NdisQueryPacket(Packet
, NULL
, NULL
, &NdisBuffer
, NULL
);
320 NDIS_DbgPrint(MID_TRACE
, ("Packet contains no buffers.\n"));
324 NdisQueryBuffer(NdisBuffer
, (PVOID
)&Start2
, &BufferLength
);
326 /* FIXME: Should handle fragmented packets */
328 switch (Adapter
->NdisMiniportBlock
.MediaType
) {
329 case NdisMedium802_3
:
330 Length
= ETH_LENGTH_OF_ADDRESS
;
331 /* Destination address is the first field */
335 NDIS_DbgPrint(MIN_TRACE
, ("Adapter has unsupported media type (0x%X).\n",
336 Adapter
->NdisMiniportBlock
.MediaType
));
340 if (BufferLength
< Length
) {
341 NDIS_DbgPrint(MID_TRACE
, ("Buffer is too small.\n"));
345 return (RtlCompareMemory((PVOID
)Start1
, (PVOID
)Start2
, Length
) == Length
);
351 PNDIS_STRING AdapterName
)
353 * FUNCTION: Returns the logical adapter object for a specific adapter
355 * AdapterName = Pointer to name of adapter
357 * Pointer to logical adapter object, or NULL if none was found.
358 * If found, the adapter is referenced for the caller. The caller
359 * is responsible for dereferencing after use
363 PLIST_ENTRY CurrentEntry
;
364 PLOGICAL_ADAPTER Adapter
;
366 NDIS_DbgPrint(DEBUG_MINIPORT
, ("Called.\n"));
368 KeAcquireSpinLock(&AdapterListLock
, &OldIrql
);
369 CurrentEntry
= AdapterListHead
.Flink
;
370 while (CurrentEntry
!= &AdapterListHead
) {
371 Adapter
= CONTAINING_RECORD(CurrentEntry
, LOGICAL_ADAPTER
, ListEntry
);
373 if (RtlCompareUnicodeString(AdapterName
, &Adapter
->DeviceName
, TRUE
) == 0) {
374 ReferenceObject(Adapter
);
375 KeReleaseSpinLock(&AdapterListLock
, OldIrql
);
377 NDIS_DbgPrint(DEBUG_MINIPORT
, ("Leaving. Adapter found at (0x%X).\n", Adapter
));
382 CurrentEntry
= CurrentEntry
->Flink
;
384 KeReleaseSpinLock(&AdapterListLock
, OldIrql
);
386 NDIS_DbgPrint(DEBUG_MINIPORT
, ("Leaving (adapter not found).\n"));
393 MiniQueryInformation(
394 PLOGICAL_ADAPTER Adapter
,
399 * FUNCTION: Queries a logical adapter for properties
401 * Adapter = Pointer to the logical adapter object to query
402 * Oid = Specifies the Object ID to query for
403 * Size = If non-zero overrides the length in the adapter object
404 * BytesWritten = Address of buffer to place number of bytes written
406 * If the specified buffer is too small, a new buffer is allocated,
407 * and the query is attempted again
409 * Status of operation
412 NDIS_STATUS NdisStatus
;
415 if (Adapter
->QueryBufferLength
== 0) {
416 Adapter
->QueryBuffer
= ExAllocatePool(NonPagedPool
, (Size
== 0)? 32 : Size
);
418 if (!Adapter
->QueryBuffer
) {
419 NDIS_DbgPrint(MIN_TRACE
, ("Insufficient resources.\n"));
420 return NDIS_STATUS_RESOURCES
;
423 Adapter
->QueryBufferLength
= (Size
== 0)? 32 : Size
;
426 BytesNeeded
= (Size
== 0)? Adapter
->QueryBufferLength
: Size
;
428 NdisStatus
= (*Adapter
->Miniport
->Chars
.QueryInformationHandler
)(
429 Adapter
->NdisMiniportBlock
.MiniportAdapterContext
,
431 Adapter
->QueryBuffer
,
436 if ((NT_SUCCESS(NdisStatus
)) || (NdisStatus
== NDIS_STATUS_PENDING
)) {
437 NDIS_DbgPrint(DEBUG_MINIPORT
, ("Miniport returned status (0x%X).\n", NdisStatus
));
441 if (NdisStatus
== NDIS_STATUS_INVALID_LENGTH
) {
442 ExFreePool(Adapter
->QueryBuffer
);
444 Adapter
->QueryBufferLength
+= BytesNeeded
;
445 Adapter
->QueryBuffer
= ExAllocatePool(NonPagedPool
,
446 Adapter
->QueryBufferLength
);
448 if (!Adapter
->QueryBuffer
) {
449 NDIS_DbgPrint(MIN_TRACE
, ("Insufficient resources.\n"));
450 return NDIS_STATUS_RESOURCES
;
453 NdisStatus
= (*Adapter
->Miniport
->Chars
.QueryInformationHandler
)(
454 Adapter
->NdisMiniportBlock
.MiniportAdapterContext
,
456 Adapter
->QueryBuffer
,
469 PLOGICAL_ADAPTER Adapter
,
470 NDIS_WORK_ITEM_TYPE WorkItemType
,
471 PVOID WorkItemContext
,
472 NDIS_HANDLE Initiator
)
474 * FUNCTION: Queues a work item for execution at a later time
476 * Adapter = Pointer to the logical adapter object to queue work item on
477 * WorkItemType = Type of work item to queue
478 * WorkItemContext = Pointer to context information for work item
479 * Initiator = Pointer to ADAPTER_BINDING structure of initiating protocol
481 * Adapter lock must be held when called
483 * Status of operation
486 PNDIS_MINIPORT_WORK_ITEM Item
;
488 NDIS_DbgPrint(MAX_TRACE
, ("Called.\n"));
490 if (Adapter
->WorkQueueLevel
< NDIS_MINIPORT_WORK_QUEUE_SIZE
- 1) {
491 Item
= &Adapter
->WorkQueue
[Adapter
->WorkQueueLevel
];
492 Adapter
->WorkQueueLevel
++;
494 Item
= ExAllocatePool(NonPagedPool
, sizeof(NDIS_MINIPORT_WORK_ITEM
));
496 /* Set flag so we know that the buffer should be freed
497 when work item is dequeued */
498 Item
->Allocated
= TRUE
;
500 NDIS_DbgPrint(MIN_TRACE
, ("Insufficient resources.\n"));
501 return NDIS_STATUS_RESOURCES
;
505 Item
->WorkItemType
= WorkItemType
;
506 Item
->WorkItemContext
= WorkItemContext
;
507 Item
->Initiator
= Initiator
;
509 Item
->Link
.Next
= NULL
;
510 if (!Adapter
->WorkQueueHead
) {
511 Adapter
->WorkQueueHead
= Item
;
513 Adapter
->WorkQueueTail
->Link
.Next
= (PSINGLE_LIST_ENTRY
)Item
;
516 KeInsertQueueDpc(&Adapter
->MiniportDpc
, NULL
, NULL
);
518 return NDIS_STATUS_SUCCESS
;
525 PLOGICAL_ADAPTER Adapter
,
526 NDIS_WORK_ITEM_TYPE
*WorkItemType
,
527 PVOID
*WorkItemContext
,
528 NDIS_HANDLE
*Initiator
)
530 * FUNCTION: Dequeues a work item from the work queue of a logical adapter
532 * Adapter = Pointer to the logical adapter object to dequeue work item from
533 * WorkItemType = Address of buffer for work item type
534 * WorkItemContext = Address of buffer for pointer to context information
535 * Initiator = Address of buffer for initiator of the work (ADAPTER_BINDING)
537 * Adapter lock must be held when called
539 * Status of operation
542 PNDIS_MINIPORT_WORK_ITEM Item
;
544 NDIS_DbgPrint(MAX_TRACE
, ("Called.\n"));
546 Item
= Adapter
->WorkQueueHead
;
548 Adapter
->WorkQueueHead
= (PNDIS_MINIPORT_WORK_ITEM
)Item
->Link
.Next
;
549 if (Item
== Adapter
->WorkQueueTail
)
550 Adapter
->WorkQueueTail
= NULL
;
552 *WorkItemType
= Item
->WorkItemType
;
553 *WorkItemContext
= Item
->WorkItemContext
;
554 *Initiator
= Item
->Initiator
;
556 if (Item
->Allocated
) {
559 Adapter
->WorkQueueLevel
--;
561 if (Adapter
->WorkQueueLevel
< 0) {
562 NDIS_DbgPrint(MIN_TRACE
, ("Adapter->WorkQueueLevel is < 0 (should be >= 0).\n"));
567 return NDIS_STATUS_SUCCESS
;
570 return NDIS_STATUS_FAILURE
;
576 PLOGICAL_ADAPTER Adapter
,
577 PNDIS_REQUEST NdisRequest
)
579 * FUNCTION: Sends a request to a miniport
581 * Adapter = Pointer to logical adapter object
582 * NdisRequest = Pointer to NDIS request structure describing request
584 * Status of operation
587 Adapter
->NdisMiniportBlock
.MediaRequest
= NdisRequest
;
589 switch (NdisRequest
->RequestType
) {
590 case NdisRequestQueryInformation
:
591 return (*Adapter
->Miniport
->Chars
.QueryInformationHandler
)(
592 Adapter
->NdisMiniportBlock
.MiniportAdapterContext
,
593 NdisRequest
->DATA
.QUERY_INFORMATION
.Oid
,
594 NdisRequest
->DATA
.QUERY_INFORMATION
.InformationBuffer
,
595 NdisRequest
->DATA
.QUERY_INFORMATION
.InformationBufferLength
,
596 (PULONG
)&NdisRequest
->DATA
.QUERY_INFORMATION
.BytesWritten
,
597 (PULONG
)&NdisRequest
->DATA
.QUERY_INFORMATION
.BytesNeeded
);
600 case NdisRequestSetInformation
:
601 return (*Adapter
->Miniport
->Chars
.SetInformationHandler
)(
602 Adapter
->NdisMiniportBlock
.MiniportAdapterContext
,
603 NdisRequest
->DATA
.SET_INFORMATION
.Oid
,
604 NdisRequest
->DATA
.SET_INFORMATION
.InformationBuffer
,
605 NdisRequest
->DATA
.SET_INFORMATION
.InformationBufferLength
,
606 (PULONG
)&NdisRequest
->DATA
.SET_INFORMATION
.BytesRead
,
607 (PULONG
)&NdisRequest
->DATA
.SET_INFORMATION
.BytesNeeded
);
611 return NDIS_STATUS_FAILURE
;
616 VOID STDCALL
MiniportDpc(
618 IN PVOID DeferredContext
,
619 IN PVOID SystemArgument1
,
620 IN PVOID SystemArgument2
)
622 * FUNCTION: Deferred routine to handle serialization
624 * Dpc = Pointer to DPC object
625 * DeferredContext = Pointer to context information (LOGICAL_ADAPTER)
626 * SystemArgument1 = Unused
627 * SystemArgument2 = Unused
630 NDIS_STATUS NdisStatus
;
631 PVOID WorkItemContext
;
632 NDIS_WORK_ITEM_TYPE WorkItemType
;
633 PADAPTER_BINDING AdapterBinding
;
634 PLOGICAL_ADAPTER Adapter
= GET_LOGICAL_ADAPTER(DeferredContext
);
636 NDIS_DbgPrint(DEBUG_MINIPORT
, ("Called.\n"));
638 NdisStatus
= MiniDequeueWorkItem(Adapter
,
641 (PNDIS_HANDLE
)&AdapterBinding
);
642 if (NdisStatus
== NDIS_STATUS_SUCCESS
) {
643 Adapter
->MiniportAdapterBinding
= AdapterBinding
;
644 switch (WorkItemType
) {
645 case NdisWorkItemSend
:
647 MiniDisplayPacket((PNDIS_PACKET
)WorkItemContext
);
649 NdisStatus
= (*Adapter
->Miniport
->Chars
.u1
.SendHandler
)(
650 Adapter
->NdisMiniportBlock
.MiniportAdapterContext
,
651 (PNDIS_PACKET
)WorkItemContext
,
653 if (NdisStatus
!= NDIS_STATUS_PENDING
) {
654 MiniSendComplete((NDIS_HANDLE
)Adapter
,
655 (PNDIS_PACKET
)WorkItemContext
,
660 case NdisWorkItemSendLoopback
:
661 NdisStatus
= ProIndicatePacket(Adapter
,
662 (PNDIS_PACKET
)WorkItemContext
);
663 MiniSendComplete((NDIS_HANDLE
)Adapter
,
664 (PNDIS_PACKET
)WorkItemContext
,
668 case NdisWorkItemReturnPackets
:
671 case NdisWorkItemResetRequested
:
674 case NdisWorkItemResetInProgress
:
677 case NdisWorkItemHalt
:
680 case NdisWorkItemMiniportCallback
:
683 case NdisWorkItemRequest
:
684 NdisStatus
= MiniDoRequest(Adapter
, (PNDIS_REQUEST
)WorkItemContext
);
686 if (NdisStatus
== NDIS_STATUS_PENDING
)
689 switch (((PNDIS_REQUEST
)WorkItemContext
)->RequestType
) {
690 case NdisRequestQueryInformation
:
691 NdisMQueryInformationComplete((NDIS_HANDLE
)Adapter
, NdisStatus
);
694 case NdisRequestSetInformation
:
695 NdisMSetInformationComplete((NDIS_HANDLE
)Adapter
, NdisStatus
);
699 NDIS_DbgPrint(MIN_TRACE
, ("Unknown NDIS request type.\n"));
705 NDIS_DbgPrint(MIN_TRACE
, ("Unknown NDIS work item type (%d).\n", WorkItemType
));
715 IN NDIS_HANDLE LogHandle
)
724 IN NDIS_HANDLE MiniportAdapterHandle
,
726 OUT PNDIS_HANDLE LogHandle
)
730 return NDIS_STATUS_FAILURE
;
736 NdisMDeregisterAdapterShutdownHandler(
737 IN NDIS_HANDLE MiniportHandle
)
746 IN NDIS_HANDLE LogHandle
)
755 IN NDIS_HANDLE MiniportAdapterHandle
,
756 IN NDIS_STATUS GeneralStatus
,
757 IN PVOID StatusBuffer
,
758 IN UINT StatusBufferSize
)
766 NdisMIndicateStatusComplete(
767 IN NDIS_HANDLE MiniportAdapterHandle
)
775 NdisInitializeWrapper(
776 OUT PNDIS_HANDLE NdisWrapperHandle
,
777 IN PVOID SystemSpecific1
,
778 IN PVOID SystemSpecific2
,
779 IN PVOID SystemSpecific3
)
781 * FUNCTION: Notifies the NDIS library that a new miniport is initializing
783 * NdisWrapperHandle = Address of buffer to place NDIS wrapper handle
784 * SystemSpecific1 = Pointer to the driver's driver object
785 * SystemSpecific2 = Pointer to the driver's registry path
786 * SystemSpecific3 = Always NULL
789 PMINIPORT_DRIVER Miniport
;
791 NDIS_DbgPrint(MAX_TRACE
, ("Called.\n"));
793 Miniport
= ExAllocatePool(NonPagedPool
, sizeof(MINIPORT_DRIVER
));
795 NDIS_DbgPrint(MIN_TRACE
, ("Insufficient resources.\n"));
796 *NdisWrapperHandle
= NULL
;
800 RtlZeroMemory(Miniport
, sizeof(MINIPORT_DRIVER
));
802 KeInitializeSpinLock(&Miniport
->Lock
);
804 Miniport
->RefCount
= 1;
806 Miniport
->DriverObject
= (PDRIVER_OBJECT
)SystemSpecific1
;
808 InitializeListHead(&Miniport
->AdapterListHead
);
810 /* Put miniport in global miniport list */
811 ExInterlockedInsertTailList(&MiniportListHead
,
812 &Miniport
->ListEntry
,
815 *NdisWrapperHandle
= Miniport
;
821 NdisMQueryInformationComplete(
822 IN NDIS_HANDLE MiniportAdapterHandle
,
823 IN NDIS_STATUS Status
)
825 PLOGICAL_ADAPTER Adapter
= GET_LOGICAL_ADAPTER(MiniportAdapterHandle
);
826 PADAPTER_BINDING AdapterBinding
= (PADAPTER_BINDING
)Adapter
->MiniportAdapterBinding
;
828 NDIS_DbgPrint(MAX_TRACE
, ("Called.\n"));
830 (*AdapterBinding
->ProtocolBinding
->Chars
.RequestCompleteHandler
)(
831 AdapterBinding
->NdisOpenBlock
.ProtocolBindingContext
,
832 Adapter
->NdisMiniportBlock
.MediaRequest
,
839 NdisMRegisterAdapterShutdownHandler(
840 IN NDIS_HANDLE MiniportHandle
,
841 IN PVOID ShutdownContext
,
842 IN ADAPTER_SHUTDOWN_HANDLER ShutdownHandler
)
850 PLOGICAL_ADAPTER Adapter
,
853 * FUNCTION: Queries miniport for information
855 * Adapter = Pointer to logical adapter
856 * AddressOID = OID to use to query for current address
858 * Status of operation
862 NDIS_STATUS NdisStatus
;
864 NDIS_DbgPrint(MAX_TRACE
, ("Called.\n"));
866 /* Get MAC options for adapter */
867 NdisStatus
= MiniQueryInformation(Adapter
,
871 if (NdisStatus
!= NDIS_STATUS_SUCCESS
) {
872 NDIS_DbgPrint(MIN_TRACE
, ("OID_GEN_MAC_OPTIONS failed. NdisStatus (0x%X).\n", NdisStatus
));
876 RtlCopyMemory(&Adapter
->NdisMiniportBlock
.MacOptions
, Adapter
->QueryBuffer
, sizeof(UINT
));
878 NDIS_DbgPrint(DEBUG_MINIPORT
, ("MacOptions (0x%X).\n", Adapter
->NdisMiniportBlock
.MacOptions
));
880 /* Get current hardware address of adapter */
881 NdisStatus
= MiniQueryInformation(Adapter
,
885 if (NdisStatus
!= NDIS_STATUS_SUCCESS
) {
886 NDIS_DbgPrint(MIN_TRACE
, ("Address OID (0x%X) failed. NdisStatus (0x%X).\n",
887 AddressOID
, NdisStatus
));
891 RtlCopyMemory(&Adapter
->Address
, Adapter
->QueryBuffer
, Adapter
->AddressLength
);
896 PUCHAR A
= (PUCHAR
)&Adapter
->Address
.Type
.Medium802_3
;
898 NDIS_DbgPrint(MAX_TRACE
, ("Adapter address is (%02X %02X %02X %02X %02X %02X).\n",
899 A
[0], A
[1], A
[2], A
[3], A
[4], A
[5]));
903 /* Get maximum lookahead buffer size of adapter */
904 NdisStatus
= MiniQueryInformation(Adapter
,
905 OID_GEN_MAXIMUM_LOOKAHEAD
,
908 if (NdisStatus
!= NDIS_STATUS_SUCCESS
) {
909 NDIS_DbgPrint(MIN_TRACE
, ("OID_GEN_MAXIMUM_LOOKAHEAD failed. NdisStatus (0x%X).\n", NdisStatus
));
913 Adapter
->MaxLookaheadLength
= *((PULONG
)Adapter
->QueryBuffer
);
915 NDIS_DbgPrint(DEBUG_MINIPORT
, ("MaxLookaheadLength (0x%X).\n", Adapter
->MaxLookaheadLength
));
917 /* Get current lookahead buffer size of adapter */
918 NdisStatus
= MiniQueryInformation(Adapter
,
919 OID_GEN_CURRENT_LOOKAHEAD
,
922 if (NdisStatus
!= NDIS_STATUS_SUCCESS
) {
923 NDIS_DbgPrint(MIN_TRACE
, ("OID_GEN_CURRENT_LOOKAHEAD failed. NdisStatus (0x%X).\n", NdisStatus
));
927 Adapter
->CurLookaheadLength
= *((PULONG
)Adapter
->QueryBuffer
);
929 NDIS_DbgPrint(DEBUG_MINIPORT
, ("CurLookaheadLength (0x%X).\n", Adapter
->CurLookaheadLength
));
931 if (Adapter
->MaxLookaheadLength
!= 0) {
932 Adapter
->LookaheadLength
= Adapter
->MaxLookaheadLength
+
933 Adapter
->MediumHeaderSize
;
934 Adapter
->LookaheadBuffer
= ExAllocatePool(NonPagedPool
,
935 Adapter
->LookaheadLength
);
936 if (!Adapter
->LookaheadBuffer
)
937 return NDIS_STATUS_RESOURCES
;
940 return STATUS_SUCCESS
;
946 NdisMRegisterMiniport(
947 IN NDIS_HANDLE NdisWrapperHandle
,
948 IN PNDIS_MINIPORT_CHARACTERISTICS MiniportCharacteristics
,
949 IN UINT CharacteristicsLength
)
951 * FUNCTION: Registers a miniport's MiniportXxx entry points with the NDIS library
953 * NdisWrapperHandle = Pointer to handle returned by NdisMInitializeWrapper
954 * MiniportCharacteristics = Pointer to a buffer with miniport characteristics
955 * CharacteristicsLength = Number of bytes in characteristics buffer
957 * Status of operation
963 NDIS_STATUS NdisStatus
;
964 NDIS_STATUS OpenErrorStatus
;
965 UINT SelectedMediumIndex
;
966 PLOGICAL_ADAPTER Adapter
;
968 BOOLEAN MemError
= FALSE
;
969 PMINIPORT_DRIVER Miniport
= GET_MINIPORT_DRIVER(NdisWrapperHandle
);
971 NDIS_DbgPrint(MAX_TRACE
, ("Called.\n"));
973 switch (MiniportCharacteristics
->MajorNdisVersion
) {
975 MinSize
= sizeof(NDIS30_MINIPORT_CHARACTERISTICS_S
);
979 MinSize
= sizeof(NDIS40_MINIPORT_CHARACTERISTICS_S
);
983 MinSize
= sizeof(NDIS50_MINIPORT_CHARACTERISTICS_S
);
987 NDIS_DbgPrint(DEBUG_MINIPORT
, ("Bad miniport characteristics version.\n"));
988 return NDIS_STATUS_BAD_VERSION
;
991 if (CharacteristicsLength
< MinSize
) {
992 NDIS_DbgPrint(DEBUG_MINIPORT
, ("Bad miniport characteristics.\n"));
993 return NDIS_STATUS_BAD_CHARACTERISTICS
;
996 /* Check if mandatory MiniportXxx functions are specified */
997 if ((!MiniportCharacteristics
->HaltHandler
) ||
998 (!MiniportCharacteristics
->InitializeHandler
)||
999 (!MiniportCharacteristics
->QueryInformationHandler
) ||
1000 (!MiniportCharacteristics
->ResetHandler
) ||
1001 (!MiniportCharacteristics
->SetInformationHandler
)) {
1002 NDIS_DbgPrint(DEBUG_MINIPORT
, ("Bad miniport characteristics.\n"));
1003 return NDIS_STATUS_BAD_CHARACTERISTICS
;
1006 if (MiniportCharacteristics
->MajorNdisVersion
== 0x03) {
1007 if (!MiniportCharacteristics
->u1
.SendHandler
) {
1008 NDIS_DbgPrint(DEBUG_MINIPORT
, ("Bad miniport characteristics.\n"));
1009 return NDIS_STATUS_BAD_CHARACTERISTICS
;
1011 } else if (MiniportCharacteristics
->MajorNdisVersion
>= 0x04) {
1013 if ((!MiniportCharacteristics
->u1
.SendHandler
) &&
1014 (!MiniportCharacteristics
->SendPacketsHandler
)) {
1015 NDIS_DbgPrint(DEBUG_MINIPORT
, ("Bad miniport characteristics.\n"));
1016 return NDIS_STATUS_BAD_CHARACTERISTICS
;
1020 RtlCopyMemory(&Miniport
->Chars
, MiniportCharacteristics
, MinSize
);
1022 Adapter
= ExAllocatePool(NonPagedPool
, sizeof(LOGICAL_ADAPTER
));
1024 NDIS_DbgPrint(MIN_TRACE
, ("Insufficient resources.\n"));
1025 return NDIS_STATUS_RESOURCES
;
1028 /* This is very important */
1029 RtlZeroMemory(Adapter
, sizeof(LOGICAL_ADAPTER
));
1031 /* Create the device object for this adapter */
1032 /* FIXME: Use GUIDs */
1033 RtlInitUnicodeStringFromLiteral(&Adapter
->DeviceName
, L
"\\Device\\ne2000");
1034 Status
= IoCreateDevice(Miniport
->DriverObject
,
1036 &Adapter
->DeviceName
,
1037 FILE_DEVICE_PHYSICAL_NETCARD
,
1040 &Adapter
->NdisMiniportBlock
.DeviceObject
);
1041 if (!NT_SUCCESS(Status
)) {
1042 NDIS_DbgPrint(MIN_TRACE
, ("Could not create device object.\n"));
1043 ExFreePool(Adapter
);
1044 return NDIS_STATUS_FAILURE
;
1047 /* Initialize adapter object */
1049 KeInitializeSpinLock(&Adapter
->NdisMiniportBlock
.Lock
);
1051 InitializeListHead(&Adapter
->ProtocolListHead
);
1053 Adapter
->RefCount
= 1;
1055 Adapter
->Miniport
= Miniport
;
1057 /* Set handlers (some NDIS macros require these) */
1059 Adapter
->NdisMiniportBlock
.EthRxCompleteHandler
= MiniEthReceiveComplete
;
1060 Adapter
->NdisMiniportBlock
.EthRxIndicateHandler
= MiniEthReceiveIndication
;
1062 Adapter
->NdisMiniportBlock
.SendCompleteHandler
= MiniSendComplete
;
1063 Adapter
->NdisMiniportBlock
.SendResourcesHandler
= MiniSendResourcesAvailable
;
1064 Adapter
->NdisMiniportBlock
.ResetCompleteHandler
= MiniResetComplete
;
1065 Adapter
->NdisMiniportBlock
.TDCompleteHandler
= MiniTransferDataComplete
;
1068 KeInitializeDpc(&Adapter
->MiniportDpc
, MiniportDpc
, (PVOID
)Adapter
);
1070 /* Put adapter in adapter list for this miniport */
1071 ExInterlockedInsertTailList(&Miniport
->AdapterListHead
,
1072 &Adapter
->MiniportListEntry
,
1075 /* Put adapter in global adapter list */
1076 ExInterlockedInsertTailList(&AdapterListHead
,
1077 &Adapter
->ListEntry
,
1080 /* Call MiniportInitialize */
1081 NdisStatus
= (*Miniport
->Chars
.InitializeHandler
)(
1083 &SelectedMediumIndex
,
1087 NULL
/* FIXME: WrapperConfigurationContext */);
1089 if ((NdisStatus
== NDIS_STATUS_SUCCESS
) &&
1090 (SelectedMediumIndex
< MEDIA_ARRAY_SIZE
)) {
1092 Adapter
->NdisMiniportBlock
.MediaType
= MediaArray
[SelectedMediumIndex
];
1094 switch (Adapter
->NdisMiniportBlock
.MediaType
) {
1095 case NdisMedium802_3
:
1096 Adapter
->MediumHeaderSize
= 14;
1097 AddressOID
= OID_802_3_CURRENT_ADDRESS
;
1098 Adapter
->AddressLength
= ETH_LENGTH_OF_ADDRESS
;
1100 Adapter
->NdisMiniportBlock
.FilterDbs
.u
.EthDB
= ExAllocatePool(NonPagedPool
,
1101 sizeof(ETH_FILTER
));
1102 if (Adapter
->NdisMiniportBlock
.FilterDbs
.u
.EthDB
) {
1103 RtlZeroMemory(Adapter
->NdisMiniportBlock
.FilterDbs
.u
.EthDB
, sizeof(ETH_FILTER
));
1104 Adapter
->NdisMiniportBlock
.FilterDbs
.u
.EthDB
->Miniport
= (PNDIS_MINIPORT_BLOCK
)Adapter
;
1110 /* FIXME: Support other types of medias */
1112 return NDIS_STATUS_FAILURE
;
1115 NdisStatus
= DoQueries(Adapter
, AddressOID
);
1119 (NdisStatus
!= NDIS_STATUS_SUCCESS
) ||
1120 (SelectedMediumIndex
>= MEDIA_ARRAY_SIZE
)) {
1122 /* Remove adapter from adapter list for this miniport */
1123 KeAcquireSpinLock(&Miniport
->Lock
, &OldIrql
);
1124 RemoveEntryList(&Adapter
->MiniportListEntry
);
1125 KeReleaseSpinLock(&Miniport
->Lock
, OldIrql
);
1127 /* Remove adapter from global adapter list */
1128 KeAcquireSpinLock(&AdapterListLock
, &OldIrql
);
1129 RemoveEntryList(&Adapter
->ListEntry
);
1130 KeReleaseSpinLock(&AdapterListLock
, OldIrql
);
1132 if (Adapter
->LookaheadBuffer
)
1133 ExFreePool(Adapter
->LookaheadBuffer
);
1135 IoDeleteDevice(Adapter
->NdisMiniportBlock
.DeviceObject
);
1136 ExFreePool(Adapter
);
1137 return NDIS_STATUS_FAILURE
;
1140 return NDIS_STATUS_SUCCESS
;
1147 IN NDIS_HANDLE MiniportAdapterHandle
,
1148 IN NDIS_STATUS Status
,
1149 IN BOOLEAN AddressingReset
)
1151 MiniResetComplete(MiniportAdapterHandle
,
1160 IN NDIS_HANDLE MiniportAdapterHandle
,
1161 IN PNDIS_PACKET Packet
,
1162 IN NDIS_STATUS Status
)
1164 * FUNCTION: Forwards a message to the initiating protocol saying
1165 * that a packet was handled
1167 * NdisAdapterHandle = Handle input to MiniportInitialize
1168 * Packet = Pointer to NDIS packet that was sent
1169 * Status = Status of send operation
1172 MiniSendComplete(MiniportAdapterHandle
,
1180 NdisMSendResourcesAvailable(
1181 IN NDIS_HANDLE MiniportAdapterHandle
)
1183 MiniSendResourcesAvailable(MiniportAdapterHandle
);
1189 NdisMTransferDataComplete(
1190 IN NDIS_HANDLE MiniportAdapterHandle
,
1191 IN PNDIS_PACKET Packet
,
1192 IN NDIS_STATUS Status
,
1193 IN UINT BytesTransferred
)
1195 MiniTransferDataComplete(MiniportAdapterHandle
,
1204 NdisMSetInformationComplete(
1205 IN NDIS_HANDLE MiniportAdapterHandle
,
1206 IN NDIS_STATUS Status
)
1208 PLOGICAL_ADAPTER Adapter
= GET_LOGICAL_ADAPTER(MiniportAdapterHandle
);
1209 PADAPTER_BINDING AdapterBinding
= (PADAPTER_BINDING
)Adapter
->MiniportAdapterBinding
;
1211 NDIS_DbgPrint(MAX_TRACE
, ("Called.\n"));
1213 (*AdapterBinding
->ProtocolBinding
->Chars
.RequestCompleteHandler
)(
1214 AdapterBinding
->NdisOpenBlock
.ProtocolBindingContext
,
1215 Adapter
->NdisMiniportBlock
.MediaRequest
,
1223 IN NDIS_HANDLE MiniportAdapterHandle
,
1224 IN NDIS_HANDLE MiniportAdapterContext
,
1225 IN BOOLEAN BusMaster
,
1226 IN NDIS_INTERFACE_TYPE AdapterType
)
1228 * FUNCTION: Informs the NDIS library of significant features of the caller's NIC
1230 * MiniportAdapterHandle = Handle input to MiniportInitialize
1231 * MiniportAdapterContext = Pointer to context information
1232 * BusMaster = Specifies TRUE if the caller's NIC is a busmaster DMA device
1233 * AdapterType = Specifies the I/O bus interface of the caller's NIC
1236 PLOGICAL_ADAPTER Adapter
= GET_LOGICAL_ADAPTER(MiniportAdapterHandle
);
1238 NDIS_DbgPrint(MAX_TRACE
, ("Called.\n"));
1240 Adapter
->NdisMiniportBlock
.MiniportAdapterContext
= MiniportAdapterContext
;
1241 Adapter
->Attributes
= BusMaster
? NDIS_ATTRIBUTE_BUS_MASTER
: 0;
1242 Adapter
->NdisMiniportBlock
.AdapterType
= AdapterType
;
1243 Adapter
->AttributesSet
= TRUE
;
1249 NdisMSetAttributesEx(
1250 IN NDIS_HANDLE MiniportAdapterHandle
,
1251 IN NDIS_HANDLE MiniportAdapterContext
,
1252 IN UINT CheckForHangTimeInSeconds OPTIONAL
,
1253 IN ULONG AttributeFlags
,
1254 IN NDIS_INTERFACE_TYPE AdapterType
)
1256 * FUNCTION: Informs the NDIS library of significant features of the caller's NIC
1258 * MiniportAdapterHandle = Handle input to MiniportInitialize
1259 * MiniportAdapterContext = Pointer to context information
1260 * CheckForHangTimeInSeconds = Specifies interval in seconds at which
1261 * MiniportCheckForHang should be called
1262 * AttributeFlags = Bitmask that indicates specific attributes
1263 * AdapterType = Specifies the I/O bus interface of the caller's NIC
1273 IN ULONG MicrosecondsToSleep
)
1281 NdisMSynchronizeWithInterrupt(
1282 IN PNDIS_MINIPORT_INTERRUPT Interrupt
,
1283 IN PVOID SynchronizeFunction
,
1284 IN PVOID SynchronizeContext
)
1295 IN NDIS_HANDLE LogHandle
,
1297 IN UINT LogBufferSize
)
1301 return NDIS_STATUS_FAILURE
;
1307 NdisTerminateWrapper(
1308 IN NDIS_HANDLE NdisWrapperHandle
,
1309 IN PVOID SystemSpecific
)
1311 * FUNCTION: Releases resources allocated by a call to NdisInitializeWrapper
1313 * NdisWrapperHandle = Handle returned by NdisInitializeWrapper (MINIPORT_DRIVER)
1314 * SystemSpecific = Always NULL
1317 PMINIPORT_DRIVER Miniport
= GET_MINIPORT_DRIVER(NdisWrapperHandle
);
1319 NDIS_DbgPrint(MAX_TRACE
, ("Called.\n"));
1321 ExFreePool(Miniport
);