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
= (MAX_TRACE
+ DEBUG_MINIPORT
);
24 /* Number of media we know */
25 #define MEDIA_ARRAY_SIZE 15
27 static NDIS_MEDIUM MediaArray
[MEDIA_ARRAY_SIZE
] = {
35 NdisMediumArcnet878_2
,
37 NdisMediumWirelessWan
,
46 LIST_ENTRY MiniportListHead
;
47 KSPIN_LOCK MiniportListLock
;
48 LIST_ENTRY AdapterListHead
;
49 KSPIN_LOCK AdapterListLock
;
60 if ((DebugTraceLevel
| DEBUG_PACKET
) > 0) {
61 Length
= CopyPacketToBuffer(
67 DbgPrint("*** PACKET START ***");
69 for (i
= 0; i
< Length
; i
++) {
71 DbgPrint("\n%04X ", i
);
72 DbgPrint("%02X ", Buffer
[i
]);
75 DbgPrint("*** PACKET STOP ***\n");
84 PLOGICAL_ADAPTER Adapter
,
85 NDIS_HANDLE MacReceiveContext
,
87 UINT HeaderBufferSize
,
88 PVOID LookaheadBuffer
,
89 UINT LookaheadBufferSize
,
92 * FUNCTION: Indicate received data to bound protocols
94 * Adapter = Pointer to logical adapter
95 * MacReceiveContext = MAC receive context handle
96 * HeaderBuffer = Pointer to header buffer
97 * HeaderBufferSize = Size of header buffer
98 * LookaheadBuffer = Pointer to lookahead buffer
99 * LookaheadBufferSize = Size of lookahead buffer
100 * PacketSize = Total size of received packet
104 PLIST_ENTRY CurrentEntry
;
105 PADAPTER_BINDING AdapterBinding
;
107 NDIS_DbgPrint(DEBUG_MINIPORT
, ("Called. Adapter (0x%X) HeaderBuffer (0x%X) "
108 "HeaderBufferSize (0x%X) LookaheadBuffer (0x%X) LookaheadBufferSize (0x%X).\n",
109 Adapter
, HeaderBuffer
, HeaderBufferSize
, LookaheadBuffer
, LookaheadBufferSize
));
113 if ((DebugTraceLevel
| DEBUG_PACKET
) > 0) {
117 DbgPrint("*** RECEIVE PACKET START ***\n");
120 for (i
= 0; i
< HeaderBufferSize
; i
++) {
122 DbgPrint("\n%04X ", i
);
123 DbgPrint("%02X ", *p
);
127 DbgPrint("\nFRAME:");
130 Length
= (LookaheadBufferSize
< 64)? LookaheadBufferSize
: 64;
131 for (i
= 0; i
< Length
; i
++) {
133 DbgPrint("\n%04X ", i
);
134 DbgPrint("%02X ", *p
);
138 DbgPrint("\n*** RECEIVE PACKET STOP ***\n");
143 KeAcquireSpinLock(&Adapter
->NdisMiniportBlock
.Lock
, &OldIrql
);
144 CurrentEntry
= Adapter
->ProtocolListHead
.Flink
;
146 if (CurrentEntry
== &Adapter
->ProtocolListHead
) {
147 NDIS_DbgPrint(DEBUG_MINIPORT
, ("WARNING: No upper protocol layer.\n"));
150 while (CurrentEntry
!= &Adapter
->ProtocolListHead
) {
151 AdapterBinding
= CONTAINING_RECORD(CurrentEntry
,
155 KeReleaseSpinLock(&Adapter
->NdisMiniportBlock
.Lock
, OldIrql
);
157 (*AdapterBinding
->ProtocolBinding
->Chars
.u4
.ReceiveHandler
)(
158 AdapterBinding
->NdisOpenBlock
.ProtocolBindingContext
,
166 KeAcquireSpinLock(&Adapter
->NdisMiniportBlock
.Lock
, &OldIrql
);
168 CurrentEntry
= CurrentEntry
->Flink
;
170 KeReleaseSpinLock(&Adapter
->NdisMiniportBlock
.Lock
, OldIrql
);
175 MiniEthReceiveComplete(
176 IN PETH_FILTER Filter
)
178 * FUNCTION: Receive indication complete function for Ethernet devices
180 * Filter = Pointer to Ethernet filter
184 PLIST_ENTRY CurrentEntry
;
185 PLOGICAL_ADAPTER Adapter
;
186 PADAPTER_BINDING AdapterBinding
;
188 NDIS_DbgPrint(DEBUG_MINIPORT
, ("Called.\n"));
190 Adapter
= (PLOGICAL_ADAPTER
)Filter
->Miniport
;
192 KeAcquireSpinLock(&Adapter
->NdisMiniportBlock
.Lock
, &OldIrql
);
193 CurrentEntry
= Adapter
->ProtocolListHead
.Flink
;
194 while (CurrentEntry
!= &Adapter
->ProtocolListHead
) {
195 AdapterBinding
= CONTAINING_RECORD(CurrentEntry
,
199 KeReleaseSpinLock(&Adapter
->NdisMiniportBlock
.Lock
, OldIrql
);
201 (*AdapterBinding
->ProtocolBinding
->Chars
.ReceiveCompleteHandler
)(
202 AdapterBinding
->NdisOpenBlock
.ProtocolBindingContext
);
204 KeAcquireSpinLock(&Adapter
->NdisMiniportBlock
.Lock
, &OldIrql
);
206 CurrentEntry
= CurrentEntry
->Flink
;
208 KeReleaseSpinLock(&Adapter
->NdisMiniportBlock
.Lock
, OldIrql
);
213 MiniEthReceiveIndication(
214 IN PETH_FILTER Filter
,
215 IN NDIS_HANDLE MacReceiveContext
,
217 IN PVOID HeaderBuffer
,
218 IN UINT HeaderBufferSize
,
219 IN PVOID LookaheadBuffer
,
220 IN UINT LookaheadBufferSize
,
223 * FUNCTION: Receive indication function for Ethernet devices
225 * Filter = Pointer to Ethernet filter
226 * MacReceiveContext = MAC receive context handle
227 * Address = Pointer to destination Ethernet address
228 * HeaderBuffer = Pointer to Ethernet header buffer
229 * HeaderBufferSize = Size of Ethernet header buffer
230 * LookaheadBuffer = Pointer to lookahead buffer
231 * LookaheadBufferSize = Size of lookahead buffer
232 * PacketSize = Total size of received packet
235 MiniIndicateData((PLOGICAL_ADAPTER
)Filter
->Miniport
,
247 IN NDIS_HANDLE MiniportAdapterHandle
,
248 IN NDIS_STATUS Status
,
249 IN BOOLEAN AddressingReset
)
257 IN NDIS_HANDLE MiniportAdapterHandle
,
258 IN PNDIS_PACKET Packet
,
259 IN NDIS_STATUS Status
)
261 * FUNCTION: Forwards a message to the initiating protocol saying
262 * that a packet was handled
264 * NdisAdapterHandle = Handle input to MiniportInitialize
265 * Packet = Pointer to NDIS packet that was sent
266 * Status = Status of send operation
269 PADAPTER_BINDING AdapterBinding
;
271 NDIS_DbgPrint(DEBUG_MINIPORT
, ("Called.\n"));
273 AdapterBinding
= (PADAPTER_BINDING
)Packet
->Reserved
[0];
275 (*AdapterBinding
->ProtocolBinding
->Chars
.u2
.SendCompleteHandler
)(
276 AdapterBinding
->NdisOpenBlock
.ProtocolBindingContext
,
283 MiniSendResourcesAvailable(
284 IN NDIS_HANDLE MiniportAdapterHandle
)
291 MiniTransferDataComplete(
292 IN NDIS_HANDLE MiniportAdapterHandle
,
293 IN PNDIS_PACKET Packet
,
294 IN NDIS_STATUS Status
,
295 IN UINT BytesTransferred
)
297 PLOGICAL_ADAPTER Adapter
= (PLOGICAL_ADAPTER
)MiniportAdapterHandle
;
298 PADAPTER_BINDING AdapterBinding
= Adapter
->MiniportAdapterBinding
;
300 NDIS_DbgPrint(DEBUG_MINIPORT
, ("Called.\n"));
302 (*AdapterBinding
->ProtocolBinding
->Chars
.u3
.TransferDataCompleteHandler
)(
303 AdapterBinding
->NdisOpenBlock
.ProtocolBindingContext
,
311 MiniAdapterHasAddress(
312 PLOGICAL_ADAPTER Adapter
,
315 * FUNCTION: Determines wether a packet has the same destination address as an adapter
317 * Adapter = Pointer to logical adapter object
318 * Packet = Pointer to NDIS packet
320 * TRUE if the destination address is that of the adapter, FALSE if not
326 PNDIS_BUFFER NdisBuffer
;
329 Start1
= (PUCHAR
)&Adapter
->Address
;
330 NdisQueryPacket(Packet
, NULL
, NULL
, &NdisBuffer
, NULL
);
332 NDIS_DbgPrint(MID_TRACE
, ("Packet contains no buffers.\n"));
336 NdisQueryBuffer(NdisBuffer
, (PVOID
)&Start2
, &BufferLength
);
338 /* FIXME: Should handle fragmented packets */
340 switch (Adapter
->NdisMiniportBlock
.MediaType
) {
341 case NdisMedium802_3
:
342 Length
= ETH_LENGTH_OF_ADDRESS
;
343 /* Destination address is the first field */
347 NDIS_DbgPrint(MIN_TRACE
, ("Adapter has unsupported media type (0x%X).\n",
348 Adapter
->NdisMiniportBlock
.MediaType
));
352 if (BufferLength
< Length
) {
353 NDIS_DbgPrint(MID_TRACE
, ("Buffer is too small.\n"));
357 return (RtlCompareMemory((PVOID
)Start1
, (PVOID
)Start2
, Length
) == Length
);
363 PNDIS_STRING AdapterName
)
365 * FUNCTION: Returns the logical adapter object for a specific adapter
367 * AdapterName = Pointer to name of adapter
369 * Pointer to logical adapter object, or NULL if none was found.
370 * If found, the adapter is referenced for the caller. The caller
371 * is responsible for dereferencing after use
375 PLIST_ENTRY CurrentEntry
;
376 PLOGICAL_ADAPTER Adapter
;
378 NDIS_DbgPrint(DEBUG_MINIPORT
, ("Called.\n"));
380 KeAcquireSpinLock(&AdapterListLock
, &OldIrql
);
381 CurrentEntry
= AdapterListHead
.Flink
;
382 while (CurrentEntry
!= &AdapterListHead
) {
383 Adapter
= CONTAINING_RECORD(CurrentEntry
, LOGICAL_ADAPTER
, ListEntry
);
385 if (RtlCompareUnicodeString(AdapterName
, &Adapter
->DeviceName
, TRUE
) == 0) {
386 ReferenceObject(Adapter
);
387 KeReleaseSpinLock(&AdapterListLock
, OldIrql
);
389 NDIS_DbgPrint(DEBUG_MINIPORT
, ("Leaving. Adapter found at (0x%X).\n", Adapter
));
394 CurrentEntry
= CurrentEntry
->Flink
;
396 KeReleaseSpinLock(&AdapterListLock
, OldIrql
);
398 NDIS_DbgPrint(DEBUG_MINIPORT
, ("Leaving (adapter not found).\n"));
405 MiniQueryInformation(
406 PLOGICAL_ADAPTER Adapter
,
411 * FUNCTION: Queries a logical adapter for properties
413 * Adapter = Pointer to the logical adapter object to query
414 * Oid = Specifies the Object ID to query for
415 * Size = If non-zero overrides the length in the adapter object
416 * BytesWritten = Address of buffer to place number of bytes written
418 * If the specified buffer is too small, a new buffer is allocated,
419 * and the query is attempted again
421 * Status of operation
424 NDIS_STATUS NdisStatus
;
427 if (Adapter
->QueryBufferLength
== 0) {
428 Adapter
->QueryBuffer
= ExAllocatePool(NonPagedPool
, (Size
== 0)? 32 : Size
);
430 if (!Adapter
->QueryBuffer
) {
431 NDIS_DbgPrint(MIN_TRACE
, ("Insufficient resources.\n"));
432 return NDIS_STATUS_RESOURCES
;
435 Adapter
->QueryBufferLength
= (Size
== 0)? 32 : Size
;
438 BytesNeeded
= (Size
== 0)? Adapter
->QueryBufferLength
: Size
;
440 NdisStatus
= (*Adapter
->Miniport
->Chars
.QueryInformationHandler
)(
441 Adapter
->NdisMiniportBlock
.MiniportAdapterContext
,
443 Adapter
->QueryBuffer
,
448 if ((NT_SUCCESS(NdisStatus
)) || (NdisStatus
== NDIS_STATUS_PENDING
)) {
449 NDIS_DbgPrint(DEBUG_MINIPORT
, ("Miniport returned status (0x%X).\n", NdisStatus
));
453 if (NdisStatus
== NDIS_STATUS_INVALID_LENGTH
) {
454 ExFreePool(Adapter
->QueryBuffer
);
456 Adapter
->QueryBufferLength
+= BytesNeeded
;
457 Adapter
->QueryBuffer
= ExAllocatePool(NonPagedPool
,
458 Adapter
->QueryBufferLength
);
460 if (!Adapter
->QueryBuffer
) {
461 NDIS_DbgPrint(MIN_TRACE
, ("Insufficient resources.\n"));
462 return NDIS_STATUS_RESOURCES
;
465 NdisStatus
= (*Adapter
->Miniport
->Chars
.QueryInformationHandler
)(
466 Adapter
->NdisMiniportBlock
.MiniportAdapterContext
,
468 Adapter
->QueryBuffer
,
481 PLOGICAL_ADAPTER Adapter
,
482 NDIS_WORK_ITEM_TYPE WorkItemType
,
483 PVOID WorkItemContext
,
484 NDIS_HANDLE Initiator
)
486 * FUNCTION: Queues a work item for execution at a later time
488 * Adapter = Pointer to the logical adapter object to queue work item on
489 * WorkItemType = Type of work item to queue
490 * WorkItemContext = Pointer to context information for work item
491 * Initiator = Pointer to ADAPTER_BINDING structure of initiating protocol
493 * Adapter lock must be held when called
495 * Status of operation
498 PNDIS_MINIPORT_WORK_ITEM Item
;
500 NDIS_DbgPrint(MAX_TRACE
, ("Called.\n"));
502 if (Adapter
->WorkQueueLevel
< NDIS_MINIPORT_WORK_QUEUE_SIZE
- 1) {
503 Item
= &Adapter
->WorkQueue
[Adapter
->WorkQueueLevel
];
504 Adapter
->WorkQueueLevel
++;
506 Item
= ExAllocatePool(NonPagedPool
, sizeof(NDIS_MINIPORT_WORK_ITEM
));
508 /* Set flag so we know that the buffer should be freed
509 when work item is dequeued */
510 Item
->Allocated
= TRUE
;
512 NDIS_DbgPrint(MIN_TRACE
, ("Insufficient resources.\n"));
513 return NDIS_STATUS_RESOURCES
;
517 Item
->WorkItemType
= WorkItemType
;
518 Item
->WorkItemContext
= WorkItemContext
;
519 Item
->Initiator
= Initiator
;
521 Item
->Link
.Next
= NULL
;
522 if (!Adapter
->WorkQueueHead
) {
523 Adapter
->WorkQueueHead
= Item
;
525 Adapter
->WorkQueueTail
->Link
.Next
= (PSINGLE_LIST_ENTRY
)Item
;
528 KeInsertQueueDpc(&Adapter
->MiniportDpc
, NULL
, NULL
);
530 return NDIS_STATUS_SUCCESS
;
537 PLOGICAL_ADAPTER Adapter
,
538 NDIS_WORK_ITEM_TYPE
*WorkItemType
,
539 PVOID
*WorkItemContext
,
540 NDIS_HANDLE
*Initiator
)
542 * FUNCTION: Dequeues a work item from the work queue of a logical adapter
544 * Adapter = Pointer to the logical adapter object to dequeue work item from
545 * WorkItemType = Address of buffer for work item type
546 * WorkItemContext = Address of buffer for pointer to context information
547 * Initiator = Address of buffer for initiator of the work (ADAPTER_BINDING)
549 * Adapter lock must be held when called
551 * Status of operation
554 PNDIS_MINIPORT_WORK_ITEM Item
;
556 NDIS_DbgPrint(MAX_TRACE
, ("Called.\n"));
558 Item
= Adapter
->WorkQueueHead
;
560 Adapter
->WorkQueueHead
= (PNDIS_MINIPORT_WORK_ITEM
)Item
->Link
.Next
;
561 if (Item
== Adapter
->WorkQueueTail
)
562 Adapter
->WorkQueueTail
= NULL
;
564 *WorkItemType
= Item
->WorkItemType
;
565 *WorkItemContext
= Item
->WorkItemContext
;
566 *Initiator
= Item
->Initiator
;
568 if (Item
->Allocated
) {
571 Adapter
->WorkQueueLevel
--;
573 if (Adapter
->WorkQueueLevel
< 0) {
574 NDIS_DbgPrint(MIN_TRACE
, ("Adapter->WorkQueueLevel is < 0 (should be >= 0).\n"));
579 return NDIS_STATUS_SUCCESS
;
582 return NDIS_STATUS_FAILURE
;
588 PLOGICAL_ADAPTER Adapter
,
589 PNDIS_REQUEST NdisRequest
)
591 * FUNCTION: Sends a request to a miniport
593 * Adapter = Pointer to logical adapter object
594 * NdisRequest = Pointer to NDIS request structure describing request
596 * Status of operation
599 Adapter
->NdisMiniportBlock
.MediaRequest
= NdisRequest
;
601 switch (NdisRequest
->RequestType
) {
602 case NdisRequestQueryInformation
:
603 return (*Adapter
->Miniport
->Chars
.QueryInformationHandler
)(
604 Adapter
->NdisMiniportBlock
.MiniportAdapterContext
,
605 NdisRequest
->DATA
.QUERY_INFORMATION
.Oid
,
606 NdisRequest
->DATA
.QUERY_INFORMATION
.InformationBuffer
,
607 NdisRequest
->DATA
.QUERY_INFORMATION
.InformationBufferLength
,
608 (PULONG
)&NdisRequest
->DATA
.QUERY_INFORMATION
.BytesWritten
,
609 (PULONG
)&NdisRequest
->DATA
.QUERY_INFORMATION
.BytesNeeded
);
612 case NdisRequestSetInformation
:
613 return (*Adapter
->Miniport
->Chars
.SetInformationHandler
)(
614 Adapter
->NdisMiniportBlock
.MiniportAdapterContext
,
615 NdisRequest
->DATA
.SET_INFORMATION
.Oid
,
616 NdisRequest
->DATA
.SET_INFORMATION
.InformationBuffer
,
617 NdisRequest
->DATA
.SET_INFORMATION
.InformationBufferLength
,
618 (PULONG
)&NdisRequest
->DATA
.SET_INFORMATION
.BytesRead
,
619 (PULONG
)&NdisRequest
->DATA
.SET_INFORMATION
.BytesNeeded
);
623 return NDIS_STATUS_FAILURE
;
628 VOID STDCALL
MiniportDpc(
630 IN PVOID DeferredContext
,
631 IN PVOID SystemArgument1
,
632 IN PVOID SystemArgument2
)
634 * FUNCTION: Deferred routine to handle serialization
636 * Dpc = Pointer to DPC object
637 * DeferredContext = Pointer to context information (LOGICAL_ADAPTER)
638 * SystemArgument1 = Unused
639 * SystemArgument2 = Unused
642 NDIS_STATUS NdisStatus
;
643 PVOID WorkItemContext
;
644 NDIS_WORK_ITEM_TYPE WorkItemType
;
645 PADAPTER_BINDING AdapterBinding
;
646 PLOGICAL_ADAPTER Adapter
= GET_LOGICAL_ADAPTER(DeferredContext
);
648 NDIS_DbgPrint(DEBUG_MINIPORT
, ("Called.\n"));
650 NdisStatus
= MiniDequeueWorkItem(Adapter
,
653 (PNDIS_HANDLE
)&AdapterBinding
);
654 if (NdisStatus
== NDIS_STATUS_SUCCESS
) {
655 Adapter
->MiniportAdapterBinding
= AdapterBinding
;
656 switch (WorkItemType
) {
657 case NdisWorkItemSend
:
659 MiniDisplayPacket((PNDIS_PACKET
)WorkItemContext
);
661 NdisStatus
= (*Adapter
->Miniport
->Chars
.u1
.SendHandler
)(
662 Adapter
->NdisMiniportBlock
.MiniportAdapterContext
,
663 (PNDIS_PACKET
)WorkItemContext
,
665 if (NdisStatus
!= NDIS_STATUS_PENDING
) {
666 MiniSendComplete((NDIS_HANDLE
)Adapter
,
667 (PNDIS_PACKET
)WorkItemContext
,
672 case NdisWorkItemSendLoopback
:
673 NdisStatus
= ProIndicatePacket(Adapter
,
674 (PNDIS_PACKET
)WorkItemContext
);
675 MiniSendComplete((NDIS_HANDLE
)Adapter
,
676 (PNDIS_PACKET
)WorkItemContext
,
680 case NdisWorkItemReturnPackets
:
683 case NdisWorkItemResetRequested
:
686 case NdisWorkItemResetInProgress
:
689 case NdisWorkItemHalt
:
692 case NdisWorkItemMiniportCallback
:
695 case NdisWorkItemRequest
:
696 NdisStatus
= MiniDoRequest(Adapter
, (PNDIS_REQUEST
)WorkItemContext
);
698 if (NdisStatus
== NDIS_STATUS_PENDING
)
701 switch (((PNDIS_REQUEST
)WorkItemContext
)->RequestType
) {
702 case NdisRequestQueryInformation
:
703 NdisMQueryInformationComplete((NDIS_HANDLE
)Adapter
, NdisStatus
);
706 case NdisRequestSetInformation
:
707 NdisMSetInformationComplete((NDIS_HANDLE
)Adapter
, NdisStatus
);
711 NDIS_DbgPrint(MIN_TRACE
, ("Unknown NDIS request type.\n"));
717 NDIS_DbgPrint(MIN_TRACE
, ("Unknown NDIS work item type (%d).\n", WorkItemType
));
730 IN NDIS_HANDLE LogHandle
)
742 IN NDIS_HANDLE MiniportAdapterHandle
,
744 OUT PNDIS_HANDLE LogHandle
)
748 return NDIS_STATUS_FAILURE
;
757 NdisMDeregisterAdapterShutdownHandler(
758 IN NDIS_HANDLE MiniportHandle
)
770 IN NDIS_HANDLE LogHandle
)
782 IN NDIS_HANDLE MiniportAdapterHandle
,
783 IN NDIS_STATUS GeneralStatus
,
784 IN PVOID StatusBuffer
,
785 IN UINT StatusBufferSize
)
796 NdisMIndicateStatusComplete(
797 IN NDIS_HANDLE MiniportAdapterHandle
)
808 NdisInitializeWrapper(
809 OUT PNDIS_HANDLE NdisWrapperHandle
,
810 IN PVOID SystemSpecific1
,
811 IN PVOID SystemSpecific2
,
812 IN PVOID SystemSpecific3
)
814 * FUNCTION: Notifies the NDIS library that a new miniport is initializing
816 * NdisWrapperHandle = Address of buffer to place NDIS wrapper handle
817 * SystemSpecific1 = Pointer to the driver's driver object
818 * SystemSpecific2 = Pointer to the driver's registry path
819 * SystemSpecific3 = Always NULL
822 PMINIPORT_DRIVER Miniport
;
824 NDIS_DbgPrint(MAX_TRACE
, ("Called.\n"));
826 Miniport
= ExAllocatePool(NonPagedPool
, sizeof(MINIPORT_DRIVER
));
828 NDIS_DbgPrint(MIN_TRACE
, ("Insufficient resources.\n"));
829 *NdisWrapperHandle
= NULL
;
833 RtlZeroMemory(Miniport
, sizeof(MINIPORT_DRIVER
));
835 KeInitializeSpinLock(&Miniport
->Lock
);
837 Miniport
->RefCount
= 1;
839 Miniport
->DriverObject
= (PDRIVER_OBJECT
)SystemSpecific1
;
841 InitializeListHead(&Miniport
->AdapterListHead
);
843 /* Put miniport in global miniport list */
844 ExInterlockedInsertTailList(&MiniportListHead
,
845 &Miniport
->ListEntry
,
848 *NdisWrapperHandle
= Miniport
;
857 NdisMQueryInformationComplete(
858 IN NDIS_HANDLE MiniportAdapterHandle
,
859 IN NDIS_STATUS Status
)
861 PLOGICAL_ADAPTER Adapter
= GET_LOGICAL_ADAPTER(MiniportAdapterHandle
);
862 PADAPTER_BINDING AdapterBinding
= (PADAPTER_BINDING
)Adapter
->MiniportAdapterBinding
;
864 NDIS_DbgPrint(MAX_TRACE
, ("Called.\n"));
866 (*AdapterBinding
->ProtocolBinding
->Chars
.RequestCompleteHandler
)(
867 AdapterBinding
->NdisOpenBlock
.ProtocolBindingContext
,
868 Adapter
->NdisMiniportBlock
.MediaRequest
,
878 NdisMRegisterAdapterShutdownHandler(
879 IN NDIS_HANDLE MiniportHandle
,
880 IN PVOID ShutdownContext
,
881 IN ADAPTER_SHUTDOWN_HANDLER ShutdownHandler
)
889 PLOGICAL_ADAPTER Adapter
,
892 * FUNCTION: Queries miniport for information
894 * Adapter = Pointer to logical adapter
895 * AddressOID = OID to use to query for current address
897 * Status of operation
901 NDIS_STATUS NdisStatus
;
903 NDIS_DbgPrint(MAX_TRACE
, ("Called.\n"));
905 /* Get MAC options for adapter */
906 NdisStatus
= MiniQueryInformation(Adapter
,
910 if (NdisStatus
!= NDIS_STATUS_SUCCESS
) {
911 NDIS_DbgPrint(MIN_TRACE
, ("OID_GEN_MAC_OPTIONS failed. NdisStatus (0x%X).\n", NdisStatus
));
915 RtlCopyMemory(&Adapter
->NdisMiniportBlock
.MacOptions
, Adapter
->QueryBuffer
, sizeof(UINT
));
917 NDIS_DbgPrint(DEBUG_MINIPORT
, ("MacOptions (0x%X).\n", Adapter
->NdisMiniportBlock
.MacOptions
));
919 /* Get current hardware address of adapter */
920 NdisStatus
= MiniQueryInformation(Adapter
,
924 if (NdisStatus
!= NDIS_STATUS_SUCCESS
) {
925 NDIS_DbgPrint(MIN_TRACE
, ("Address OID (0x%X) failed. NdisStatus (0x%X).\n",
926 AddressOID
, NdisStatus
));
930 RtlCopyMemory(&Adapter
->Address
, Adapter
->QueryBuffer
, Adapter
->AddressLength
);
935 PUCHAR A
= (PUCHAR
)&Adapter
->Address
.Type
.Medium802_3
;
937 NDIS_DbgPrint(MAX_TRACE
, ("Adapter address is (%02X %02X %02X %02X %02X %02X).\n",
938 A
[0], A
[1], A
[2], A
[3], A
[4], A
[5]));
942 /* Get maximum lookahead buffer size of adapter */
943 NdisStatus
= MiniQueryInformation(Adapter
,
944 OID_GEN_MAXIMUM_LOOKAHEAD
,
947 if (NdisStatus
!= NDIS_STATUS_SUCCESS
) {
948 NDIS_DbgPrint(MIN_TRACE
, ("OID_GEN_MAXIMUM_LOOKAHEAD failed. NdisStatus (0x%X).\n", NdisStatus
));
952 Adapter
->MaxLookaheadLength
= *((PULONG
)Adapter
->QueryBuffer
);
954 NDIS_DbgPrint(DEBUG_MINIPORT
, ("MaxLookaheadLength (0x%X).\n", Adapter
->MaxLookaheadLength
));
956 /* Get current lookahead buffer size of adapter */
957 NdisStatus
= MiniQueryInformation(Adapter
,
958 OID_GEN_CURRENT_LOOKAHEAD
,
961 if (NdisStatus
!= NDIS_STATUS_SUCCESS
) {
962 NDIS_DbgPrint(MIN_TRACE
, ("OID_GEN_CURRENT_LOOKAHEAD failed. NdisStatus (0x%X).\n", NdisStatus
));
966 Adapter
->CurLookaheadLength
= *((PULONG
)Adapter
->QueryBuffer
);
968 NDIS_DbgPrint(DEBUG_MINIPORT
, ("CurLookaheadLength (0x%X).\n", Adapter
->CurLookaheadLength
));
970 if (Adapter
->MaxLookaheadLength
!= 0) {
971 Adapter
->LookaheadLength
= Adapter
->MaxLookaheadLength
+
972 Adapter
->MediumHeaderSize
;
973 Adapter
->LookaheadBuffer
= ExAllocatePool(NonPagedPool
,
974 Adapter
->LookaheadLength
);
975 if (!Adapter
->LookaheadBuffer
)
976 return NDIS_STATUS_RESOURCES
;
979 return STATUS_SUCCESS
;
988 NdisMRegisterMiniport(
989 IN NDIS_HANDLE NdisWrapperHandle
,
990 IN PNDIS_MINIPORT_CHARACTERISTICS MiniportCharacteristics
,
991 IN UINT CharacteristicsLength
)
993 * FUNCTION: Registers a miniport's MiniportXxx entry points with the NDIS library
995 * NdisWrapperHandle = Pointer to handle returned by NdisMInitializeWrapper
996 * MiniportCharacteristics = Pointer to a buffer with miniport characteristics
997 * CharacteristicsLength = Number of bytes in characteristics buffer
999 * Status of operation
1005 NDIS_STATUS NdisStatus
;
1006 NDIS_STATUS OpenErrorStatus
;
1007 UINT SelectedMediumIndex
;
1008 PLOGICAL_ADAPTER Adapter
;
1009 NDIS_OID AddressOID
;
1010 BOOLEAN MemError
= FALSE
;
1011 PMINIPORT_DRIVER Miniport
= GET_MINIPORT_DRIVER(NdisWrapperHandle
);
1013 NDIS_DbgPrint(MAX_TRACE
, ("Called.\n"));
1015 switch (MiniportCharacteristics
->MajorNdisVersion
) {
1017 MinSize
= sizeof(NDIS30_MINIPORT_CHARACTERISTICS_S
);
1021 MinSize
= sizeof(NDIS40_MINIPORT_CHARACTERISTICS_S
);
1025 MinSize
= sizeof(NDIS50_MINIPORT_CHARACTERISTICS_S
);
1029 NDIS_DbgPrint(DEBUG_MINIPORT
, ("Bad miniport characteristics version.\n"));
1030 return NDIS_STATUS_BAD_VERSION
;
1033 if (CharacteristicsLength
< MinSize
) {
1034 NDIS_DbgPrint(DEBUG_MINIPORT
, ("Bad miniport characteristics.\n"));
1035 return NDIS_STATUS_BAD_CHARACTERISTICS
;
1038 /* Check if mandatory MiniportXxx functions are specified */
1039 if ((!MiniportCharacteristics
->HaltHandler
) ||
1040 (!MiniportCharacteristics
->InitializeHandler
)||
1041 (!MiniportCharacteristics
->QueryInformationHandler
) ||
1042 (!MiniportCharacteristics
->ResetHandler
) ||
1043 (!MiniportCharacteristics
->SetInformationHandler
)) {
1044 NDIS_DbgPrint(DEBUG_MINIPORT
, ("Bad miniport characteristics.\n"));
1045 return NDIS_STATUS_BAD_CHARACTERISTICS
;
1048 if (MiniportCharacteristics
->MajorNdisVersion
== 0x03) {
1049 if (!MiniportCharacteristics
->u1
.SendHandler
) {
1050 NDIS_DbgPrint(DEBUG_MINIPORT
, ("Bad miniport characteristics.\n"));
1051 return NDIS_STATUS_BAD_CHARACTERISTICS
;
1053 } else if (MiniportCharacteristics
->MajorNdisVersion
>= 0x04) {
1055 if ((!MiniportCharacteristics
->u1
.SendHandler
) &&
1056 (!MiniportCharacteristics
->SendPacketsHandler
)) {
1057 NDIS_DbgPrint(DEBUG_MINIPORT
, ("Bad miniport characteristics.\n"));
1058 return NDIS_STATUS_BAD_CHARACTERISTICS
;
1062 RtlCopyMemory(&Miniport
->Chars
, MiniportCharacteristics
, MinSize
);
1064 Adapter
= ExAllocatePool(NonPagedPool
, sizeof(LOGICAL_ADAPTER
));
1066 NDIS_DbgPrint(MIN_TRACE
, ("Insufficient resources.\n"));
1067 return NDIS_STATUS_RESOURCES
;
1070 /* This is very important */
1071 RtlZeroMemory(Adapter
, sizeof(LOGICAL_ADAPTER
));
1073 /* Create the device object for this adapter */
1074 /* FIXME: Use GUIDs */
1075 RtlInitUnicodeStringFromLiteral(&Adapter
->DeviceName
, L
"\\Device\\ne2000");
1076 Status
= IoCreateDevice(Miniport
->DriverObject
,
1078 &Adapter
->DeviceName
,
1079 FILE_DEVICE_PHYSICAL_NETCARD
,
1082 &Adapter
->NdisMiniportBlock
.DeviceObject
);
1083 if (!NT_SUCCESS(Status
)) {
1084 NDIS_DbgPrint(MIN_TRACE
, ("Could not create device object.\n"));
1085 ExFreePool(Adapter
);
1086 return NDIS_STATUS_FAILURE
;
1089 /* Initialize adapter object */
1091 KeInitializeSpinLock(&Adapter
->NdisMiniportBlock
.Lock
);
1093 InitializeListHead(&Adapter
->ProtocolListHead
);
1095 Adapter
->RefCount
= 1;
1097 Adapter
->Miniport
= Miniport
;
1099 /* Set handlers (some NDIS macros require these) */
1101 Adapter
->NdisMiniportBlock
.EthRxCompleteHandler
= MiniEthReceiveComplete
;
1102 Adapter
->NdisMiniportBlock
.EthRxIndicateHandler
= MiniEthReceiveIndication
;
1104 Adapter
->NdisMiniportBlock
.SendCompleteHandler
= MiniSendComplete
;
1105 Adapter
->NdisMiniportBlock
.SendResourcesHandler
= MiniSendResourcesAvailable
;
1106 Adapter
->NdisMiniportBlock
.ResetCompleteHandler
= MiniResetComplete
;
1107 Adapter
->NdisMiniportBlock
.TDCompleteHandler
= MiniTransferDataComplete
;
1110 KeInitializeDpc(&Adapter
->MiniportDpc
, MiniportDpc
, (PVOID
)Adapter
);
1112 /* Put adapter in adapter list for this miniport */
1113 ExInterlockedInsertTailList(&Miniport
->AdapterListHead
,
1114 &Adapter
->MiniportListEntry
,
1117 /* Put adapter in global adapter list */
1118 ExInterlockedInsertTailList(&AdapterListHead
,
1119 &Adapter
->ListEntry
,
1122 /* Call MiniportInitialize */
1123 NdisStatus
= (*Miniport
->Chars
.InitializeHandler
)(
1125 &SelectedMediumIndex
,
1129 NULL
/* FIXME: WrapperConfigurationContext */);
1131 if ((NdisStatus
== NDIS_STATUS_SUCCESS
) &&
1132 (SelectedMediumIndex
< MEDIA_ARRAY_SIZE
)) {
1134 Adapter
->NdisMiniportBlock
.MediaType
= MediaArray
[SelectedMediumIndex
];
1136 switch (Adapter
->NdisMiniportBlock
.MediaType
) {
1137 case NdisMedium802_3
:
1138 Adapter
->MediumHeaderSize
= 14;
1139 AddressOID
= OID_802_3_CURRENT_ADDRESS
;
1140 Adapter
->AddressLength
= ETH_LENGTH_OF_ADDRESS
;
1142 Adapter
->NdisMiniportBlock
.FilterDbs
.u
.EthDB
= ExAllocatePool(NonPagedPool
,
1143 sizeof(ETH_FILTER
));
1144 if (Adapter
->NdisMiniportBlock
.FilterDbs
.u
.EthDB
) {
1145 RtlZeroMemory(Adapter
->NdisMiniportBlock
.FilterDbs
.u
.EthDB
, sizeof(ETH_FILTER
));
1146 Adapter
->NdisMiniportBlock
.FilterDbs
.u
.EthDB
->Miniport
= (PNDIS_MINIPORT_BLOCK
)Adapter
;
1152 /* FIXME: Support other types of medias */
1154 return NDIS_STATUS_FAILURE
;
1157 NdisStatus
= DoQueries(Adapter
, AddressOID
);
1161 (NdisStatus
!= NDIS_STATUS_SUCCESS
) ||
1162 (SelectedMediumIndex
>= MEDIA_ARRAY_SIZE
)) {
1164 /* Remove adapter from adapter list for this miniport */
1165 KeAcquireSpinLock(&Miniport
->Lock
, &OldIrql
);
1166 RemoveEntryList(&Adapter
->MiniportListEntry
);
1167 KeReleaseSpinLock(&Miniport
->Lock
, OldIrql
);
1169 /* Remove adapter from global adapter list */
1170 KeAcquireSpinLock(&AdapterListLock
, &OldIrql
);
1171 RemoveEntryList(&Adapter
->ListEntry
);
1172 KeReleaseSpinLock(&AdapterListLock
, OldIrql
);
1174 if (Adapter
->LookaheadBuffer
)
1175 ExFreePool(Adapter
->LookaheadBuffer
);
1177 IoDeleteDevice(Adapter
->NdisMiniportBlock
.DeviceObject
);
1178 ExFreePool(Adapter
);
1179 NDIS_DbgPrint(MIN_TRACE
, ("MiniportInitialize() failed.\n"));
1180 return NDIS_STATUS_FAILURE
;
1183 return NDIS_STATUS_SUCCESS
;
1193 IN NDIS_HANDLE MiniportAdapterHandle
,
1194 IN NDIS_STATUS Status
,
1195 IN BOOLEAN AddressingReset
)
1197 MiniResetComplete(MiniportAdapterHandle
,
1209 IN NDIS_HANDLE MiniportAdapterHandle
,
1210 IN PNDIS_PACKET Packet
,
1211 IN NDIS_STATUS Status
)
1213 * FUNCTION: Forwards a message to the initiating protocol saying
1214 * that a packet was handled
1216 * NdisAdapterHandle = Handle input to MiniportInitialize
1217 * Packet = Pointer to NDIS packet that was sent
1218 * Status = Status of send operation
1221 MiniSendComplete(MiniportAdapterHandle
,
1232 NdisMSendResourcesAvailable(
1233 IN NDIS_HANDLE MiniportAdapterHandle
)
1235 MiniSendResourcesAvailable(MiniportAdapterHandle
);
1244 NdisMTransferDataComplete(
1245 IN NDIS_HANDLE MiniportAdapterHandle
,
1246 IN PNDIS_PACKET Packet
,
1247 IN NDIS_STATUS Status
,
1248 IN UINT BytesTransferred
)
1250 MiniTransferDataComplete(MiniportAdapterHandle
,
1262 NdisMSetInformationComplete(
1263 IN NDIS_HANDLE MiniportAdapterHandle
,
1264 IN NDIS_STATUS Status
)
1266 PLOGICAL_ADAPTER Adapter
= GET_LOGICAL_ADAPTER(MiniportAdapterHandle
);
1267 PADAPTER_BINDING AdapterBinding
= (PADAPTER_BINDING
)Adapter
->MiniportAdapterBinding
;
1269 NDIS_DbgPrint(MAX_TRACE
, ("Called.\n"));
1271 (*AdapterBinding
->ProtocolBinding
->Chars
.RequestCompleteHandler
)(
1272 AdapterBinding
->NdisOpenBlock
.ProtocolBindingContext
,
1273 Adapter
->NdisMiniportBlock
.MediaRequest
,
1284 IN NDIS_HANDLE MiniportAdapterHandle
,
1285 IN NDIS_HANDLE MiniportAdapterContext
,
1286 IN BOOLEAN BusMaster
,
1287 IN NDIS_INTERFACE_TYPE AdapterType
)
1289 * FUNCTION: Informs the NDIS library of significant features of the caller's NIC
1291 * MiniportAdapterHandle = Handle input to MiniportInitialize
1292 * MiniportAdapterContext = Pointer to context information
1293 * BusMaster = Specifies TRUE if the caller's NIC is a busmaster DMA device
1294 * AdapterType = Specifies the I/O bus interface of the caller's NIC
1297 PLOGICAL_ADAPTER Adapter
= GET_LOGICAL_ADAPTER(MiniportAdapterHandle
);
1299 NDIS_DbgPrint(MAX_TRACE
, ("Called.\n"));
1301 Adapter
->NdisMiniportBlock
.MiniportAdapterContext
= MiniportAdapterContext
;
1302 Adapter
->Attributes
= BusMaster
? NDIS_ATTRIBUTE_BUS_MASTER
: 0;
1303 Adapter
->NdisMiniportBlock
.AdapterType
= AdapterType
;
1304 Adapter
->AttributesSet
= TRUE
;
1313 NdisMSetAttributesEx(
1314 IN NDIS_HANDLE MiniportAdapterHandle
,
1315 IN NDIS_HANDLE MiniportAdapterContext
,
1316 IN UINT CheckForHangTimeInSeconds OPTIONAL
,
1317 IN ULONG AttributeFlags
,
1318 IN NDIS_INTERFACE_TYPE AdapterType
)
1320 * FUNCTION: Informs the NDIS library of significant features of the caller's NIC
1322 * MiniportAdapterHandle = Handle input to MiniportInitialize
1323 * MiniportAdapterContext = Pointer to context information
1324 * CheckForHangTimeInSeconds = Specifies interval in seconds at which
1325 * MiniportCheckForHang should be called
1326 * AttributeFlags = Bitmask that indicates specific attributes
1327 * AdapterType = Specifies the I/O bus interface of the caller's NIC
1330 // Currently just like NdisMSetAttributesEx
1331 // TODO: Take CheckForHandTimeInSeconds into account!
1332 PLOGICAL_ADAPTER Adapter
= GET_LOGICAL_ADAPTER(MiniportAdapterHandle
);
1334 NDIS_DbgPrint(MAX_TRACE
, ("Called.\n"));
1335 NDIS_DbgPrint(MIN_TRACE
, ("NdisMSetAttributesEx() is partly-implemented."));
1337 Adapter
->NdisMiniportBlock
.MiniportAdapterContext
= MiniportAdapterContext
;
1338 Adapter
->Attributes
= AttributeFlags
& NDIS_ATTRIBUTE_BUS_MASTER
;
1339 Adapter
->NdisMiniportBlock
.AdapterType
= AdapterType
;
1340 Adapter
->AttributesSet
= TRUE
;
1350 IN ULONG MicrosecondsToSleep
)
1361 NdisMSynchronizeWithInterrupt(
1362 IN PNDIS_MINIPORT_INTERRUPT Interrupt
,
1363 IN PVOID SynchronizeFunction
,
1364 IN PVOID SynchronizeContext
)
1378 IN NDIS_HANDLE LogHandle
,
1380 IN UINT LogBufferSize
)
1384 return NDIS_STATUS_FAILURE
;
1393 NdisTerminateWrapper(
1394 IN NDIS_HANDLE NdisWrapperHandle
,
1395 IN PVOID SystemSpecific
)
1397 * FUNCTION: Releases resources allocated by a call to NdisInitializeWrapper
1399 * NdisWrapperHandle = Handle returned by NdisInitializeWrapper (MINIPORT_DRIVER)
1400 * SystemSpecific = Always NULL
1403 PMINIPORT_DRIVER Miniport
= GET_MINIPORT_DRIVER(NdisWrapperHandle
);
1405 NDIS_DbgPrint(MAX_TRACE
, ("Called.\n"));
1407 ExFreePool(Miniport
);