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 Length
= CopyPacketToBuffer(
59 NDIS_DbgPrint(DEBUG_PACKET
, ("*** PACKET START ***"));
61 for (i
= 0; i
< Length
; i
++) {
63 DbgPrint("\n%04X ", i
);
64 DbgPrint("%02X ", Buffer
[i
]);
67 NDIS_DbgPrint(DEBUG_PACKET
, ("*** PACKET STOP ***\n"));
74 PLOGICAL_ADAPTER Adapter
,
75 NDIS_HANDLE MacReceiveContext
,
77 UINT HeaderBufferSize
,
78 PVOID LookaheadBuffer
,
79 UINT LookaheadBufferSize
,
82 * FUNCTION: Indicate received data to bound protocols
84 * Adapter = Pointer to logical adapter
85 * MacReceiveContext = MAC receive context handle
86 * HeaderBuffer = Pointer to header buffer
87 * HeaderBufferSize = Size of header buffer
88 * LookaheadBuffer = Pointer to lookahead buffer
89 * LookaheadBufferSize = Size of lookahead buffer
90 * PacketSize = Total size of received packet
94 PLIST_ENTRY CurrentEntry
;
95 PADAPTER_BINDING AdapterBinding
;
97 NDIS_DbgPrint(DEBUG_MINIPORT
, ("Called. Adapter (0x%X) HeaderBuffer (0x%X) "
98 "HeaderBufferSize (0x%X) LookaheadBuffer (0x%X) LookaheadBufferSize (0x%X).\n",
99 Adapter
, HeaderBuffer
, HeaderBufferSize
, LookaheadBuffer
, LookaheadBufferSize
));
102 if (DebugTraceLevel
| DEBUG_PACKET
) {
106 NDIS_DbgPrint(DEBUG_PACKET
, ("*** RECEIVE PACKET START ***\n"));
107 NDIS_DbgPrint(DEBUG_PACKET
, ("HEADER:"));
109 for (i
= 0; i
< HeaderBufferSize
; i
++) {
111 DbgPrint("\n%04X ", i
);
112 DbgPrint("%02X ", *p
);
116 NDIS_DbgPrint(DEBUG_PACKET
, ("\nFRAME:"));
119 Length
= (LookaheadBufferSize
< 64)? LookaheadBufferSize
: 64;
120 for (i
= 0; i
< Length
; i
++) {
122 DbgPrint("\n%04X ", i
);
123 DbgPrint("%02X ", *p
);
127 NDIS_DbgPrint(DEBUG_PACKET
, ("*** RECEIVE PACKET STOP ***\n"));
131 KeAcquireSpinLock(&Adapter
->Lock
, &OldIrql
);
132 CurrentEntry
= Adapter
->ProtocolListHead
.Flink
;
133 while (CurrentEntry
!= &Adapter
->ProtocolListHead
) {
134 AdapterBinding
= CONTAINING_RECORD(CurrentEntry
,
138 KeReleaseSpinLock(&Adapter
->Lock
, OldIrql
);
140 (*AdapterBinding
->ProtocolBinding
->Chars
.u4
.ReceiveHandler
)(
141 AdapterBinding
->ProtocolBindingContext
,
149 KeAcquireSpinLock(&Adapter
->Lock
, &OldIrql
);
151 CurrentEntry
= CurrentEntry
->Flink
;
153 KeReleaseSpinLock(&Adapter
->Lock
, OldIrql
);
158 MiniEthReceiveComplete(
159 IN PETH_FILTER Filter
)
161 * FUNCTION: Receive indication complete function for Ethernet devices
163 * Filter = Pointer to Ethernet filter
167 PLIST_ENTRY CurrentEntry
;
168 PLOGICAL_ADAPTER Adapter
;
169 PADAPTER_BINDING AdapterBinding
;
171 NDIS_DbgPrint(DEBUG_MINIPORT
, ("Called.\n"));
173 Adapter
= (PLOGICAL_ADAPTER
)Filter
->Miniport
;
175 KeAcquireSpinLock(&Adapter
->Lock
, &OldIrql
);
176 CurrentEntry
= Adapter
->ProtocolListHead
.Flink
;
177 while (CurrentEntry
!= &Adapter
->ProtocolListHead
) {
178 AdapterBinding
= CONTAINING_RECORD(CurrentEntry
,
182 KeReleaseSpinLock(&Adapter
->Lock
, OldIrql
);
184 (*AdapterBinding
->ProtocolBinding
->Chars
.ReceiveCompleteHandler
)(
185 AdapterBinding
->ProtocolBindingContext
);
187 KeAcquireSpinLock(&Adapter
->Lock
, &OldIrql
);
189 CurrentEntry
= CurrentEntry
->Flink
;
191 KeReleaseSpinLock(&Adapter
->Lock
, OldIrql
);
196 MiniEthReceiveIndication(
197 IN PETH_FILTER Filter
,
198 IN NDIS_HANDLE MacReceiveContext
,
200 IN PVOID HeaderBuffer
,
201 IN UINT HeaderBufferSize
,
202 IN PVOID LookaheadBuffer
,
203 IN UINT LookaheadBufferSize
,
206 * FUNCTION: Receive indication function for Ethernet devices
208 * Filter = Pointer to Ethernet filter
209 * MacReceiveContext = MAC receive context handle
210 * Address = Pointer to destination Ethernet address
211 * HeaderBuffer = Pointer to Ethernet header buffer
212 * HeaderBufferSize = Size of Ethernet header buffer
213 * LookaheadBuffer = Pointer to lookahead buffer
214 * LookaheadBufferSize = Size of lookahead buffer
215 * PacketSize = Total size of received packet
218 MiniIndicateData((PLOGICAL_ADAPTER
)Filter
->Miniport
,
230 IN NDIS_HANDLE MiniportAdapterHandle
,
231 IN NDIS_STATUS Status
,
232 IN BOOLEAN AddressingReset
)
240 IN NDIS_HANDLE MiniportAdapterHandle
,
241 IN PNDIS_PACKET Packet
,
242 IN NDIS_STATUS Status
)
244 * FUNCTION: Forwards a message to the initiating protocol saying
245 * that a packet was handled
247 * NdisAdapterHandle = Handle input to MiniportInitialize
248 * Packet = Pointer to NDIS packet that was sent
249 * Status = Status of send operation
252 PADAPTER_BINDING AdapterBinding
;
254 NDIS_DbgPrint(DEBUG_MINIPORT
, ("Called.\n"));
256 AdapterBinding
= (PADAPTER_BINDING
)Packet
->Reserved
[0];
258 (*AdapterBinding
->ProtocolBinding
->Chars
.u2
.SendCompleteHandler
)(
259 AdapterBinding
->ProtocolBindingContext
,
266 MiniSendResourcesAvailable(
267 IN NDIS_HANDLE MiniportAdapterHandle
)
274 MiniTransferDataComplete(
275 IN NDIS_HANDLE MiniportAdapterHandle
,
276 IN PNDIS_PACKET Packet
,
277 IN NDIS_STATUS Status
,
278 IN UINT BytesTransferred
)
280 PLOGICAL_ADAPTER Adapter
= (PLOGICAL_ADAPTER
)MiniportAdapterHandle
;
281 PADAPTER_BINDING AdapterBinding
= Adapter
->MiniportAdapterBinding
;
283 NDIS_DbgPrint(DEBUG_MINIPORT
, ("Called.\n"));
285 (*AdapterBinding
->ProtocolBinding
->Chars
.u3
.TransferDataCompleteHandler
)(
286 AdapterBinding
->ProtocolBindingContext
,
294 MiniAdapterHasAddress(
295 PLOGICAL_ADAPTER Adapter
,
298 * FUNCTION: Determines wether a packet has the same destination address as an adapter
300 * Adapter = Pointer to logical adapter object
301 * Packet = Pointer to NDIS packet
303 * TRUE if the destination address is that of the adapter, FALSE if not
309 PNDIS_BUFFER NdisBuffer
;
312 Start1
= (PUCHAR
)&Adapter
->Address
;
313 NdisQueryPacket(Packet
, NULL
, NULL
, &NdisBuffer
, NULL
);
315 NDIS_DbgPrint(MID_TRACE
, ("Packet contains no buffers.\n"));
319 NdisQueryBuffer(NdisBuffer
, (PVOID
)&Start2
, &BufferLength
);
321 /* FIXME: Should handle fragmented packets */
323 switch (Adapter
->MediaType
) {
324 case NdisMedium802_3
:
325 Length
= ETH_LENGTH_OF_ADDRESS
;
326 /* Destination address is the first field */
330 NDIS_DbgPrint(MIN_TRACE
, ("Adapter has unsupported media type (0x%X).\n", Adapter
->MediaType
));
334 if (BufferLength
< Length
) {
335 NDIS_DbgPrint(MID_TRACE
, ("Buffer is too small.\n"));
339 return (RtlCompareMemory((PVOID
)Start1
, (PVOID
)Start2
, Length
) == Length
);
345 PNDIS_STRING AdapterName
)
347 * FUNCTION: Returns the logical adapter object for a specific adapter
349 * AdapterName = Pointer to name of adapter
351 * Pointer to logical adapter object, or NULL if none was found.
352 * If found, the adapter is referenced for the caller. The caller
353 * is responsible for dereferencing after use
357 PLIST_ENTRY CurrentEntry
;
358 PLOGICAL_ADAPTER Adapter
;
360 NDIS_DbgPrint(DEBUG_MINIPORT
, ("Called.\n"));
362 KeAcquireSpinLock(&AdapterListLock
, &OldIrql
);
363 CurrentEntry
= AdapterListHead
.Flink
;
364 while (CurrentEntry
!= &AdapterListHead
) {
365 Adapter
= CONTAINING_RECORD(CurrentEntry
, LOGICAL_ADAPTER
, ListEntry
);
367 if (RtlCompareUnicodeString(AdapterName
, &Adapter
->DeviceName
, TRUE
) == 0) {
368 ReferenceObject(Adapter
);
369 KeReleaseSpinLock(&AdapterListLock
, OldIrql
);
371 NDIS_DbgPrint(DEBUG_MINIPORT
, ("Leaving. Adapter found at (0x%X).\n", Adapter
));
376 CurrentEntry
= CurrentEntry
->Flink
;
378 KeReleaseSpinLock(&AdapterListLock
, OldIrql
);
380 NDIS_DbgPrint(DEBUG_MINIPORT
, ("Leaving (adapter not found).\n"));
387 MiniQueryInformation(
388 PLOGICAL_ADAPTER Adapter
,
393 * FUNCTION: Queries a logical adapter for properties
395 * Adapter = Pointer to the logical adapter object to query
396 * Oid = Specifies the Object ID to query for
397 * Size = If non-zero overrides the length in the adapter object
398 * BytesWritten = Address of buffer to place number of bytes written
400 * If the specified buffer is too small, a new buffer is allocated,
401 * and the query is attempted again
403 * Status of operation
406 NDIS_STATUS NdisStatus
;
409 if (Adapter
->QueryBufferLength
== 0) {
410 Adapter
->QueryBuffer
= ExAllocatePool(NonPagedPool
, (Size
== 0)? 32 : Size
);
412 if (!Adapter
->QueryBuffer
) {
413 NDIS_DbgPrint(MIN_TRACE
, ("Insufficient resources.\n"));
414 return NDIS_STATUS_RESOURCES
;
417 Adapter
->QueryBufferLength
= (Size
== 0)? 32 : Size
;
420 BytesNeeded
= (Size
== 0)? Adapter
->QueryBufferLength
: Size
;
422 NdisStatus
= (*Adapter
->Miniport
->Chars
.QueryInformationHandler
)(
423 Adapter
->MiniportAdapterContext
,
425 Adapter
->QueryBuffer
,
430 if ((NT_SUCCESS(NdisStatus
)) || (NdisStatus
== NDIS_STATUS_PENDING
)) {
431 NDIS_DbgPrint(DEBUG_MINIPORT
, ("Miniport returned status (0x%X).\n", NdisStatus
));
435 if (NdisStatus
== NDIS_STATUS_INVALID_LENGTH
) {
436 ExFreePool(Adapter
->QueryBuffer
);
438 Adapter
->QueryBufferLength
+= BytesNeeded
;
439 Adapter
->QueryBuffer
= ExAllocatePool(NonPagedPool
,
440 Adapter
->QueryBufferLength
);
442 if (!Adapter
->QueryBuffer
) {
443 NDIS_DbgPrint(MIN_TRACE
, ("Insufficient resources.\n"));
444 return NDIS_STATUS_RESOURCES
;
447 NdisStatus
= (*Adapter
->Miniport
->Chars
.QueryInformationHandler
)(
448 Adapter
->MiniportAdapterContext
,
450 Adapter
->QueryBuffer
,
463 PLOGICAL_ADAPTER Adapter
,
464 NDIS_WORK_ITEM_TYPE WorkItemType
,
465 PVOID WorkItemContext
,
466 NDIS_HANDLE Initiator
)
468 * FUNCTION: Queues a work item for execution at a later time
470 * Adapter = Pointer to the logical adapter object to queue work item on
471 * WorkItemType = Type of work item to queue
472 * WorkItemContext = Pointer to context information for work item
473 * Initiator = Pointer to ADAPTER_BINDING structure of initiating protocol
475 * Adapter lock must be held when called
477 * Status of operation
480 PNDIS_MINIPORT_WORK_ITEM Item
;
482 NDIS_DbgPrint(MAX_TRACE
, ("Called.\n"));
484 if (Adapter
->WorkQueueLevel
< NDIS_MINIPORT_WORK_QUEUE_SIZE
- 1) {
485 Item
= &Adapter
->WorkQueue
[Adapter
->WorkQueueLevel
];
486 Adapter
->WorkQueueLevel
++;
488 Item
= ExAllocatePool(NonPagedPool
, sizeof(NDIS_MINIPORT_WORK_ITEM
));
490 /* Set flag so we know that the buffer should be freed
491 when work item is dequeued */
492 Item
->Allocated
= TRUE
;
494 NDIS_DbgPrint(MIN_TRACE
, ("Insufficient resources.\n"));
495 return NDIS_STATUS_RESOURCES
;
499 Item
->WorkItemType
= WorkItemType
;
500 Item
->WorkItemContext
= WorkItemContext
;
501 Item
->Initiator
= Initiator
;
503 Item
->Link
.Next
= NULL
;
504 if (!Adapter
->WorkQueueHead
) {
505 Adapter
->WorkQueueHead
= Item
;
507 Adapter
->WorkQueueTail
->Link
.Next
= (PSINGLE_LIST_ENTRY
)Item
;
510 KeInsertQueueDpc(&Adapter
->MiniportDpc
, NULL
, NULL
);
512 return NDIS_STATUS_SUCCESS
;
519 PLOGICAL_ADAPTER Adapter
,
520 NDIS_WORK_ITEM_TYPE
*WorkItemType
,
521 PVOID
*WorkItemContext
,
522 NDIS_HANDLE
*Initiator
)
524 * FUNCTION: Dequeues a work item from the work queue of a logical adapter
526 * Adapter = Pointer to the logical adapter object to dequeue work item from
527 * WorkItemType = Address of buffer for work item type
528 * WorkItemContext = Address of buffer for pointer to context information
529 * Initiator = Address of buffer for initiator of the work (ADAPTER_BINDING)
531 * Adapter lock must be held when called
533 * Status of operation
536 PNDIS_MINIPORT_WORK_ITEM Item
;
538 NDIS_DbgPrint(MAX_TRACE
, ("Called.\n"));
540 Item
= Adapter
->WorkQueueHead
;
542 Adapter
->WorkQueueHead
= (PNDIS_MINIPORT_WORK_ITEM
)Item
->Link
.Next
;
543 if (Item
== Adapter
->WorkQueueTail
)
544 Adapter
->WorkQueueTail
= NULL
;
546 *WorkItemType
= Item
->WorkItemType
;
547 *WorkItemContext
= Item
->WorkItemContext
;
548 *Initiator
= Item
->Initiator
;
550 if (Item
->Allocated
) {
553 Adapter
->WorkQueueLevel
--;
555 if (Adapter
->WorkQueueLevel
< 0) {
556 NDIS_DbgPrint(MIN_TRACE
, ("Adapter->WorkQueueLevel is < 0 (should be >= 0).\n"));
561 return NDIS_STATUS_SUCCESS
;
564 return NDIS_STATUS_FAILURE
;
570 PLOGICAL_ADAPTER Adapter
,
571 PNDIS_REQUEST NdisRequest
)
573 * FUNCTION: Sends a request to a miniport
575 * Adapter = Pointer to logical adapter object
576 * NdisRequest = Pointer to NDIS request structure describing request
578 * Status of operation
581 Adapter
->MediaRequest
= NdisRequest
;
583 switch (NdisRequest
->RequestType
) {
584 case NdisRequestQueryInformation
:
585 return (*Adapter
->Miniport
->Chars
.QueryInformationHandler
)(
586 Adapter
->MiniportAdapterContext
,
587 NdisRequest
->DATA
.QUERY_INFORMATION
.Oid
,
588 NdisRequest
->DATA
.QUERY_INFORMATION
.InformationBuffer
,
589 NdisRequest
->DATA
.QUERY_INFORMATION
.InformationBufferLength
,
590 (PULONG
)&NdisRequest
->DATA
.QUERY_INFORMATION
.BytesWritten
,
591 (PULONG
)&NdisRequest
->DATA
.QUERY_INFORMATION
.BytesNeeded
);
594 case NdisRequestSetInformation
:
595 return (*Adapter
->Miniport
->Chars
.SetInformationHandler
)(
596 Adapter
->MiniportAdapterContext
,
597 NdisRequest
->DATA
.SET_INFORMATION
.Oid
,
598 NdisRequest
->DATA
.SET_INFORMATION
.InformationBuffer
,
599 NdisRequest
->DATA
.SET_INFORMATION
.InformationBufferLength
,
600 (PULONG
)&NdisRequest
->DATA
.SET_INFORMATION
.BytesRead
,
601 (PULONG
)&NdisRequest
->DATA
.SET_INFORMATION
.BytesNeeded
);
605 return NDIS_STATUS_FAILURE
;
612 IN PVOID DeferredContext
,
613 IN PVOID SystemArgument1
,
614 IN PVOID SystemArgument2
)
616 * FUNCTION: Deferred routine to handle serialization
618 * Dpc = Pointer to DPC object
619 * DeferredContext = Pointer to context information (LOGICAL_ADAPTER)
620 * SystemArgument1 = Unused
621 * SystemArgument2 = Unused
624 NDIS_STATUS NdisStatus
;
625 PVOID WorkItemContext
;
626 NDIS_WORK_ITEM_TYPE WorkItemType
;
627 PADAPTER_BINDING AdapterBinding
;
628 PLOGICAL_ADAPTER Adapter
= GET_LOGICAL_ADAPTER(DeferredContext
);
630 NDIS_DbgPrint(DEBUG_MINIPORT
, ("Called.\n"));
632 NdisStatus
= MiniDequeueWorkItem(Adapter
,
635 (PNDIS_HANDLE
)&AdapterBinding
);
636 if (NdisStatus
== NDIS_STATUS_SUCCESS
) {
637 Adapter
->MiniportAdapterBinding
= AdapterBinding
;
638 switch (WorkItemType
) {
639 case NdisWorkItemSend
:
641 MiniDisplayPacket((PNDIS_PACKET
)WorkItemContext
);
643 NdisStatus
= (*Adapter
->Miniport
->Chars
.u1
.SendHandler
)(
644 Adapter
->MiniportAdapterContext
,
645 (PNDIS_PACKET
)WorkItemContext
,
647 if (NdisStatus
!= NDIS_STATUS_PENDING
) {
648 MiniSendComplete((NDIS_HANDLE
)Adapter
,
649 (PNDIS_PACKET
)WorkItemContext
,
654 case NdisWorkItemSendLoopback
:
655 NdisStatus
= ProIndicatePacket(Adapter
,
656 (PNDIS_PACKET
)WorkItemContext
);
657 MiniSendComplete((NDIS_HANDLE
)Adapter
,
658 (PNDIS_PACKET
)WorkItemContext
,
662 case NdisWorkItemReturnPackets
:
665 case NdisWorkItemResetRequested
:
668 case NdisWorkItemResetInProgress
:
671 case NdisWorkItemHalt
:
674 case NdisWorkItemMiniportCallback
:
677 case NdisWorkItemRequest
:
678 NdisStatus
= MiniDoRequest(Adapter
, (PNDIS_REQUEST
)WorkItemContext
);
680 if (NdisStatus
== NDIS_STATUS_PENDING
)
683 switch (((PNDIS_REQUEST
)WorkItemContext
)->RequestType
) {
684 case NdisRequestQueryInformation
:
685 NdisMQueryInformationComplete((NDIS_HANDLE
)Adapter
, NdisStatus
);
688 case NdisRequestSetInformation
:
689 NdisMSetInformationComplete((NDIS_HANDLE
)Adapter
, NdisStatus
);
693 NDIS_DbgPrint(MIN_TRACE
, ("Unknown NDIS request type.\n"));
699 NDIS_DbgPrint(MIN_TRACE
, ("Unknown NDIS work item type (%d).\n", WorkItemType
));
709 IN NDIS_HANDLE LogHandle
)
718 IN NDIS_HANDLE MiniportAdapterHandle
,
720 OUT PNDIS_HANDLE LogHandle
)
724 return NDIS_STATUS_FAILURE
;
730 NdisMDeregisterAdapterShutdownHandler(
731 IN NDIS_HANDLE MiniportHandle
)
740 IN NDIS_HANDLE LogHandle
)
749 IN NDIS_HANDLE MiniportAdapterHandle
,
750 IN NDIS_STATUS GeneralStatus
,
751 IN PVOID StatusBuffer
,
752 IN UINT StatusBufferSize
)
760 NdisMIndicateStatusComplete(
761 IN NDIS_HANDLE MiniportAdapterHandle
)
769 NdisInitializeWrapper(
770 OUT PNDIS_HANDLE NdisWrapperHandle
,
771 IN PVOID SystemSpecific1
,
772 IN PVOID SystemSpecific2
,
773 IN PVOID SystemSpecific3
)
775 * FUNCTION: Notifies the NDIS library that a new miniport is initializing
777 * NdisWrapperHandle = Address of buffer to place NDIS wrapper handle
778 * SystemSpecific1 = Pointer to the driver's driver object
779 * SystemSpecific2 = Pointer to the driver's registry path
780 * SystemSpecific3 = Always NULL
783 PMINIPORT_DRIVER Miniport
;
785 NDIS_DbgPrint(MAX_TRACE
, ("Called.\n"));
787 Miniport
= ExAllocatePool(NonPagedPool
, sizeof(MINIPORT_DRIVER
));
789 NDIS_DbgPrint(MIN_TRACE
, ("Insufficient resources.\n"));
790 *NdisWrapperHandle
= NULL
;
794 RtlZeroMemory(Miniport
, sizeof(MINIPORT_DRIVER
));
796 KeInitializeSpinLock(&Miniport
->Lock
);
798 Miniport
->RefCount
= 1;
800 Miniport
->DriverObject
= (PDRIVER_OBJECT
)SystemSpecific1
;
802 InitializeListHead(&Miniport
->AdapterListHead
);
804 /* Put miniport in global miniport list */
805 ExInterlockedInsertTailList(&MiniportListHead
,
806 &Miniport
->ListEntry
,
809 *NdisWrapperHandle
= Miniport
;
815 NdisMQueryInformationComplete(
816 IN NDIS_HANDLE MiniportAdapterHandle
,
817 IN NDIS_STATUS Status
)
819 PLOGICAL_ADAPTER Adapter
= GET_LOGICAL_ADAPTER(MiniportAdapterHandle
);
820 PADAPTER_BINDING AdapterBinding
= (PADAPTER_BINDING
)Adapter
->MiniportAdapterBinding
;
822 NDIS_DbgPrint(MAX_TRACE
, ("Called.\n"));
824 (*AdapterBinding
->ProtocolBinding
->Chars
.RequestCompleteHandler
)(
825 AdapterBinding
->ProtocolBindingContext
,
826 Adapter
->MediaRequest
,
833 NdisMRegisterAdapterShutdownHandler(
834 IN NDIS_HANDLE MiniportHandle
,
835 IN PVOID ShutdownContext
,
836 IN ADAPTER_SHUTDOWN_HANDLER ShutdownHandler
)
844 PLOGICAL_ADAPTER Adapter
,
847 * FUNCTION: Queries miniport for information
849 * Adapter = Pointer to logical adapter
850 * AddressOID = OID to use to query for current address
852 * Status of operation
856 NDIS_STATUS NdisStatus
;
858 NDIS_DbgPrint(MAX_TRACE
, ("Called.\n"));
860 /* Get MAC options for adapter */
861 NdisStatus
= MiniQueryInformation(Adapter
,
865 if (NdisStatus
!= NDIS_STATUS_SUCCESS
) {
866 NDIS_DbgPrint(MIN_TRACE
, ("OID_GEN_MAC_OPTIONS failed. NdisStatus (0x%X).\n", NdisStatus
));
870 RtlCopyMemory(&Adapter
->MacOptions
, Adapter
->QueryBuffer
, sizeof(UINT
));
872 NDIS_DbgPrint(DEBUG_MINIPORT
, ("MacOptions (0x%X).\n", Adapter
->MacOptions
));
874 /* Get current hardware address of adapter */
875 NdisStatus
= MiniQueryInformation(Adapter
,
879 if (NdisStatus
!= NDIS_STATUS_SUCCESS
) {
880 NDIS_DbgPrint(MIN_TRACE
, ("Address OID (0x%X) failed. NdisStatus (0x%X).\n",
881 AddressOID
, NdisStatus
));
885 RtlCopyMemory(&Adapter
->Address
, Adapter
->QueryBuffer
, Adapter
->AddressLength
);
890 PUCHAR A
= (PUCHAR
)&Adapter
->Address
.Type
.Medium802_3
;
892 NDIS_DbgPrint(MAX_TRACE
, ("Adapter address is (%02X %02X %02X %02X %02X %02X).\n",
893 A
[0], A
[1], A
[2], A
[3], A
[4], A
[5]));
897 /* Get maximum lookahead buffer size of adapter */
898 NdisStatus
= MiniQueryInformation(Adapter
,
899 OID_GEN_MAXIMUM_LOOKAHEAD
,
902 if (NdisStatus
!= NDIS_STATUS_SUCCESS
) {
903 NDIS_DbgPrint(MIN_TRACE
, ("OID_GEN_MAXIMUM_LOOKAHEAD failed. NdisStatus (0x%X).\n", NdisStatus
));
907 Adapter
->MaxLookaheadLength
= *((PULONG
)Adapter
->QueryBuffer
);
909 NDIS_DbgPrint(DEBUG_MINIPORT
, ("MaxLookaheadLength (0x%X).\n", Adapter
->MaxLookaheadLength
));
911 /* Get current lookahead buffer size of adapter */
912 NdisStatus
= MiniQueryInformation(Adapter
,
913 OID_GEN_CURRENT_LOOKAHEAD
,
916 if (NdisStatus
!= NDIS_STATUS_SUCCESS
) {
917 NDIS_DbgPrint(MIN_TRACE
, ("OID_GEN_CURRENT_LOOKAHEAD failed. NdisStatus (0x%X).\n", NdisStatus
));
921 Adapter
->CurLookaheadLength
= *((PULONG
)Adapter
->QueryBuffer
);
923 NDIS_DbgPrint(DEBUG_MINIPORT
, ("CurLookaheadLength (0x%X).\n", Adapter
->CurLookaheadLength
));
925 if (Adapter
->MaxLookaheadLength
!= 0) {
926 Adapter
->LookaheadLength
= Adapter
->MaxLookaheadLength
+
927 Adapter
->MediumHeaderSize
;
928 Adapter
->LookaheadBuffer
= ExAllocatePool(NonPagedPool
,
929 Adapter
->LookaheadLength
);
930 if (!Adapter
->LookaheadBuffer
)
931 return NDIS_STATUS_RESOURCES
;
934 return STATUS_SUCCESS
;
940 NdisMRegisterMiniport(
941 IN NDIS_HANDLE NdisWrapperHandle
,
942 IN PNDIS_MINIPORT_CHARACTERISTICS MiniportCharacteristics
,
943 IN UINT CharacteristicsLength
)
945 * FUNCTION: Registers a miniport's MiniportXxx entry points with the NDIS library
947 * NdisWrapperHandle = Pointer to handle returned by NdisMInitializeWrapper
948 * MiniportCharacteristics = Pointer to a buffer with miniport characteristics
949 * CharacteristicsLength = Number of bytes in characteristics buffer
951 * Status of operation
957 NDIS_STATUS NdisStatus
;
958 NDIS_STATUS OpenErrorStatus
;
959 UINT SelectedMediumIndex
;
960 PLOGICAL_ADAPTER Adapter
;
962 BOOLEAN MemError
= FALSE
;
963 PMINIPORT_DRIVER Miniport
= GET_MINIPORT_DRIVER(NdisWrapperHandle
);
965 NDIS_DbgPrint(MAX_TRACE
, ("Called.\n"));
967 switch (MiniportCharacteristics
->MajorNdisVersion
) {
969 MinSize
= sizeof(NDIS30_MINIPORT_CHARACTERISTICS_S
);
973 MinSize
= sizeof(NDIS40_MINIPORT_CHARACTERISTICS_S
);
977 MinSize
= sizeof(NDIS50_MINIPORT_CHARACTERISTICS_S
);
981 NDIS_DbgPrint(DEBUG_MINIPORT
, ("Bad miniport characteristics version.\n"));
982 return NDIS_STATUS_BAD_VERSION
;
985 if (CharacteristicsLength
< MinSize
) {
986 NDIS_DbgPrint(DEBUG_MINIPORT
, ("Bad miniport characteristics.\n"));
987 return NDIS_STATUS_BAD_CHARACTERISTICS
;
990 /* Check if mandatory MiniportXxx functions are specified */
991 if ((!MiniportCharacteristics
->HaltHandler
) ||
992 (!MiniportCharacteristics
->InitializeHandler
)||
993 (!MiniportCharacteristics
->QueryInformationHandler
) ||
994 (!MiniportCharacteristics
->ResetHandler
) ||
995 (!MiniportCharacteristics
->SetInformationHandler
)) {
996 NDIS_DbgPrint(DEBUG_MINIPORT
, ("Bad miniport characteristics.\n"));
997 return NDIS_STATUS_BAD_CHARACTERISTICS
;
1000 if (MiniportCharacteristics
->MajorNdisVersion
== 0x03) {
1001 if (!MiniportCharacteristics
->u1
.SendHandler
) {
1002 NDIS_DbgPrint(DEBUG_MINIPORT
, ("Bad miniport characteristics.\n"));
1003 return NDIS_STATUS_BAD_CHARACTERISTICS
;
1005 } else if (MiniportCharacteristics
->MajorNdisVersion
>= 0x04) {
1007 if ((!MiniportCharacteristics
->u1
.SendHandler
) &&
1008 (!MiniportCharacteristics
->SendPacketsHandler
)) {
1009 NDIS_DbgPrint(DEBUG_MINIPORT
, ("Bad miniport characteristics.\n"));
1010 return NDIS_STATUS_BAD_CHARACTERISTICS
;
1014 RtlCopyMemory(&Miniport
->Chars
, MiniportCharacteristics
, MinSize
);
1016 Adapter
= ExAllocatePool(NonPagedPool
, sizeof(LOGICAL_ADAPTER
));
1018 NDIS_DbgPrint(MIN_TRACE
, ("Insufficient resources.\n"));
1019 return NDIS_STATUS_RESOURCES
;
1022 /* This is very important */
1023 RtlZeroMemory(Adapter
, sizeof(LOGICAL_ADAPTER
));
1025 /* Create the device object for this adapter */
1026 /* FIXME: Use GUIDs */
1027 RtlInitUnicodeString(&Adapter
->DeviceName
, L
"\\Device\\ne2000");
1028 Status
= IoCreateDevice(Miniport
->DriverObject
,
1030 &Adapter
->DeviceName
,
1031 FILE_DEVICE_PHYSICAL_NETCARD
,
1034 &Adapter
->DeviceObject
);
1035 if (!NT_SUCCESS(Status
)) {
1036 NDIS_DbgPrint(MIN_TRACE
, ("Could not create device object.\n"));
1037 ExFreePool(Adapter
);
1038 return NDIS_STATUS_FAILURE
;
1041 /* Initialize adapter object */
1043 KeInitializeSpinLock(&Adapter
->Lock
);
1045 InitializeListHead(&Adapter
->ProtocolListHead
);
1047 Adapter
->RefCount
= 1;
1049 Adapter
->Miniport
= Miniport
;
1051 /* Set handlers (some NDIS macros require these) */
1053 Adapter
->EthRxCompleteHandler
= MiniEthReceiveComplete
;
1054 Adapter
->EthRxIndicateHandler
= MiniEthReceiveIndication
;
1056 Adapter
->SendCompleteHandler
= MiniSendComplete
;
1057 Adapter
->SendResourcesHandler
= MiniSendResourcesAvailable
;
1058 Adapter
->ResetCompleteHandler
= MiniResetComplete
;
1059 Adapter
->TDCompleteHandler
= MiniTransferDataComplete
;
1062 KeInitializeDpc(&Adapter
->MiniportDpc
, MiniportDpc
, (PVOID
)Adapter
);
1064 /* Put adapter in adapter list for this miniport */
1065 ExInterlockedInsertTailList(&Miniport
->AdapterListHead
,
1066 &Adapter
->MiniportListEntry
,
1069 /* Put adapter in global adapter list */
1070 ExInterlockedInsertTailList(&AdapterListHead
,
1071 &Adapter
->ListEntry
,
1074 /* Call MiniportInitialize */
1075 NdisStatus
= (*Miniport
->Chars
.InitializeHandler
)(
1077 &SelectedMediumIndex
,
1081 NULL
/* FIXME: WrapperConfigurationContext */);
1083 if ((NdisStatus
== NDIS_STATUS_SUCCESS
) &&
1084 (SelectedMediumIndex
< MEDIA_ARRAY_SIZE
)) {
1086 Adapter
->MediaType
= MediaArray
[SelectedMediumIndex
];
1088 switch (Adapter
->MediaType
) {
1089 case NdisMedium802_3
:
1090 Adapter
->MediumHeaderSize
= 14;
1091 AddressOID
= OID_802_3_CURRENT_ADDRESS
;
1092 Adapter
->AddressLength
= ETH_LENGTH_OF_ADDRESS
;
1094 Adapter
->FilterDbs
.u
.EthDB
= ExAllocatePool(NonPagedPool
,
1095 sizeof(ETH_FILTER
));
1096 if (Adapter
->FilterDbs
.u
.EthDB
) {
1097 RtlZeroMemory(Adapter
->FilterDbs
.u
.EthDB
, sizeof(ETH_FILTER
));
1098 Adapter
->FilterDbs
.u
.EthDB
->Miniport
= (PNDIS_MINIPORT_BLOCK
)Adapter
;
1104 /* FIXME: Support other types of medias */
1106 return NDIS_STATUS_FAILURE
;
1109 NdisStatus
= DoQueries(Adapter
, AddressOID
);
1113 (NdisStatus
!= NDIS_STATUS_SUCCESS
) ||
1114 (SelectedMediumIndex
>= MEDIA_ARRAY_SIZE
)) {
1116 /* Remove adapter from adapter list for this miniport */
1117 KeAcquireSpinLock(&Miniport
->Lock
, &OldIrql
);
1118 RemoveEntryList(&Adapter
->MiniportListEntry
);
1119 KeReleaseSpinLock(&Miniport
->Lock
, OldIrql
);
1121 /* Remove adapter from global adapter list */
1122 KeAcquireSpinLock(&AdapterListLock
, &OldIrql
);
1123 RemoveEntryList(&Adapter
->ListEntry
);
1124 KeReleaseSpinLock(&AdapterListLock
, OldIrql
);
1126 if (Adapter
->LookaheadBuffer
)
1127 ExFreePool(Adapter
->LookaheadBuffer
);
1129 IoDeleteDevice(Adapter
->DeviceObject
);
1130 ExFreePool(Adapter
);
1131 return NDIS_STATUS_FAILURE
;
1134 return NDIS_STATUS_SUCCESS
;
1141 IN NDIS_HANDLE MiniportAdapterHandle
,
1142 IN NDIS_STATUS Status
,
1143 IN BOOLEAN AddressingReset
)
1145 MiniResetComplete(MiniportAdapterHandle
,
1154 IN NDIS_HANDLE MiniportAdapterHandle
,
1155 IN PNDIS_PACKET Packet
,
1156 IN NDIS_STATUS Status
)
1158 * FUNCTION: Forwards a message to the initiating protocol saying
1159 * that a packet was handled
1161 * NdisAdapterHandle = Handle input to MiniportInitialize
1162 * Packet = Pointer to NDIS packet that was sent
1163 * Status = Status of send operation
1166 MiniSendComplete(MiniportAdapterHandle
,
1174 NdisMSendResourcesAvailable(
1175 IN NDIS_HANDLE MiniportAdapterHandle
)
1177 MiniSendResourcesAvailable(MiniportAdapterHandle
);
1183 NdisMTransferDataComplete(
1184 IN NDIS_HANDLE MiniportAdapterHandle
,
1185 IN PNDIS_PACKET Packet
,
1186 IN NDIS_STATUS Status
,
1187 IN UINT BytesTransferred
)
1189 MiniTransferDataComplete(MiniportAdapterHandle
,
1198 NdisMSetInformationComplete(
1199 IN NDIS_HANDLE MiniportAdapterHandle
,
1200 IN NDIS_STATUS Status
)
1202 PLOGICAL_ADAPTER Adapter
= GET_LOGICAL_ADAPTER(MiniportAdapterHandle
);
1203 PADAPTER_BINDING AdapterBinding
= (PADAPTER_BINDING
)Adapter
->MiniportAdapterBinding
;
1205 NDIS_DbgPrint(MAX_TRACE
, ("Called.\n"));
1207 (*AdapterBinding
->ProtocolBinding
->Chars
.RequestCompleteHandler
)(
1208 AdapterBinding
->ProtocolBindingContext
,
1209 Adapter
->MediaRequest
,
1217 IN NDIS_HANDLE MiniportAdapterHandle
,
1218 IN NDIS_HANDLE MiniportAdapterContext
,
1219 IN BOOLEAN BusMaster
,
1220 IN NDIS_INTERFACE_TYPE AdapterType
)
1222 * FUNCTION: Informs the NDIS library of significant features of the caller's NIC
1224 * MiniportAdapterHandle = Handle input to MiniportInitialize
1225 * MiniportAdapterContext = Pointer to context information
1226 * BusMaster = Specifies TRUE if the caller's NIC is a busmaster DMA device
1227 * AdapterType = Specifies the I/O bus interface of the caller's NIC
1230 PLOGICAL_ADAPTER Adapter
= GET_LOGICAL_ADAPTER(MiniportAdapterHandle
);
1232 NDIS_DbgPrint(MAX_TRACE
, ("Called.\n"));
1234 Adapter
->MiniportAdapterContext
= MiniportAdapterContext
;
1235 Adapter
->Attributes
= BusMaster
? NDIS_ATTRIBUTE_BUS_MASTER
: 0;
1236 Adapter
->AdapterType
= AdapterType
;
1237 Adapter
->AttributesSet
= TRUE
;
1243 NdisMSetAttributesEx(
1244 IN NDIS_HANDLE MiniportAdapterHandle
,
1245 IN NDIS_HANDLE MiniportAdapterContext
,
1246 IN UINT CheckForHangTimeInSeconds OPTIONAL
,
1247 IN ULONG AttributeFlags
,
1248 IN NDIS_INTERFACE_TYPE AdapterType
)
1250 * FUNCTION: Informs the NDIS library of significant features of the caller's NIC
1252 * MiniportAdapterHandle = Handle input to MiniportInitialize
1253 * MiniportAdapterContext = Pointer to context information
1254 * CheckForHangTimeInSeconds = Specifies interval in seconds at which
1255 * MiniportCheckForHang should be called
1256 * AttributeFlags = Bitmask that indicates specific attributes
1257 * AdapterType = Specifies the I/O bus interface of the caller's NIC
1267 IN ULONG MicrosecondsToSleep
)
1275 NdisMSynchronizeWithInterrupt(
1276 IN PNDIS_MINIPORT_INTERRUPT Interrupt
,
1277 IN PVOID SynchronizeFunction
,
1278 IN PVOID SynchronizeContext
)
1289 IN NDIS_HANDLE LogHandle
,
1291 IN UINT LogBufferSize
)
1295 return NDIS_STATUS_FAILURE
;
1301 NdisTerminateWrapper(
1302 IN NDIS_HANDLE NdisWrapperHandle
,
1303 IN PVOID SystemSpecific
)
1305 * FUNCTION: Releases resources allocated by a call to NdisInitializeWrapper
1307 * NdisWrapperHandle = Handle returned by NdisInitializeWrapper (MINIPORT_DRIVER)
1308 * SystemSpecific = Always NULL
1311 PMINIPORT_DRIVER Miniport
= GET_MINIPORT_DRIVER(NdisWrapperHandle
);
1313 NDIS_DbgPrint(MAX_TRACE
, ("Called.\n"));
1315 ExFreePool(Miniport
);