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));
727 IN NDIS_HANDLE LogHandle)
736 IN NDIS_HANDLE MiniportAdapterHandle,
738 OUT PNDIS_HANDLE LogHandle)
742 return NDIS_STATUS_FAILURE;
748 NdisMDeregisterAdapterShutdownHandler(
749 IN NDIS_HANDLE MiniportHandle)
758 IN NDIS_HANDLE LogHandle)
767 IN NDIS_HANDLE MiniportAdapterHandle,
768 IN NDIS_STATUS GeneralStatus,
769 IN PVOID StatusBuffer,
770 IN UINT StatusBufferSize)
778 NdisMIndicateStatusComplete(
779 IN NDIS_HANDLE MiniportAdapterHandle)
787 NdisInitializeWrapper(
788 OUT PNDIS_HANDLE NdisWrapperHandle,
789 IN PVOID SystemSpecific1,
790 IN PVOID SystemSpecific2,
791 IN PVOID SystemSpecific3)
793 * FUNCTION: Notifies the NDIS library that a new miniport is initializing
795 * NdisWrapperHandle = Address of buffer to place NDIS wrapper handle
796 * SystemSpecific1 = Pointer to the driver's driver object
797 * SystemSpecific2 = Pointer to the driver's registry path
798 * SystemSpecific3 = Always NULL
801 PMINIPORT_DRIVER Miniport;
803 NDIS_DbgPrint(MAX_TRACE, ("Called.\n"));
805 Miniport = ExAllocatePool(NonPagedPool, sizeof(MINIPORT_DRIVER));
807 NDIS_DbgPrint(MIN_TRACE, ("Insufficient resources.\n"));
808 *NdisWrapperHandle = NULL;
812 RtlZeroMemory(Miniport, sizeof(MINIPORT_DRIVER));
814 KeInitializeSpinLock(&Miniport->Lock);
816 Miniport->RefCount = 1;
818 Miniport->DriverObject = (PDRIVER_OBJECT)SystemSpecific1;
820 InitializeListHead(&Miniport->AdapterListHead);
822 /* Put miniport in global miniport list */
823 ExInterlockedInsertTailList(&MiniportListHead,
824 &Miniport->ListEntry,
827 *NdisWrapperHandle = Miniport;
833 NdisMQueryInformationComplete(
834 IN NDIS_HANDLE MiniportAdapterHandle,
835 IN NDIS_STATUS Status)
837 PLOGICAL_ADAPTER Adapter = GET_LOGICAL_ADAPTER(MiniportAdapterHandle);
838 PADAPTER_BINDING AdapterBinding = (PADAPTER_BINDING)Adapter->MiniportAdapterBinding;
840 NDIS_DbgPrint(MAX_TRACE, ("Called.\n"));
842 (*AdapterBinding->ProtocolBinding->Chars.RequestCompleteHandler)(
843 AdapterBinding->NdisOpenBlock.ProtocolBindingContext,
844 Adapter->NdisMiniportBlock.MediaRequest,
851 NdisMRegisterAdapterShutdownHandler(
852 IN NDIS_HANDLE MiniportHandle,
853 IN PVOID ShutdownContext,
854 IN ADAPTER_SHUTDOWN_HANDLER ShutdownHandler)
862 PLOGICAL_ADAPTER Adapter,
865 * FUNCTION: Queries miniport for information
867 * Adapter = Pointer to logical adapter
868 * AddressOID = OID to use to query for current address
870 * Status of operation
874 NDIS_STATUS NdisStatus;
876 NDIS_DbgPrint(MAX_TRACE, ("Called.\n"));
878 /* Get MAC options for adapter */
879 NdisStatus = MiniQueryInformation(Adapter,
883 if (NdisStatus != NDIS_STATUS_SUCCESS) {
884 NDIS_DbgPrint(MIN_TRACE, ("OID_GEN_MAC_OPTIONS failed. NdisStatus (0x%X).\n", NdisStatus));
888 RtlCopyMemory(&Adapter->NdisMiniportBlock.MacOptions, Adapter->QueryBuffer, sizeof(UINT));
890 NDIS_DbgPrint(DEBUG_MINIPORT, ("MacOptions (0x%X).\n", Adapter->NdisMiniportBlock.MacOptions));
892 /* Get current hardware address of adapter */
893 NdisStatus = MiniQueryInformation(Adapter,
897 if (NdisStatus != NDIS_STATUS_SUCCESS) {
898 NDIS_DbgPrint(MIN_TRACE, ("Address OID (0x%X) failed. NdisStatus (0x%X).\n",
899 AddressOID, NdisStatus));
903 RtlCopyMemory(&Adapter->Address, Adapter->QueryBuffer, Adapter->AddressLength);
908 PUCHAR A = (PUCHAR)&Adapter->Address.Type.Medium802_3;
910 NDIS_DbgPrint(MAX_TRACE, ("Adapter address is (%02X %02X %02X %02X %02X %02X).\n",
911 A[0], A[1], A[2], A[3], A[4], A[5]));
915 /* Get maximum lookahead buffer size of adapter */
916 NdisStatus = MiniQueryInformation(Adapter,
917 OID_GEN_MAXIMUM_LOOKAHEAD,
920 if (NdisStatus != NDIS_STATUS_SUCCESS) {
921 NDIS_DbgPrint(MIN_TRACE, ("OID_GEN_MAXIMUM_LOOKAHEAD failed. NdisStatus (0x%X).\n", NdisStatus));
925 Adapter->MaxLookaheadLength = *((PULONG)Adapter->QueryBuffer);
927 NDIS_DbgPrint(DEBUG_MINIPORT, ("MaxLookaheadLength (0x%X).\n", Adapter->MaxLookaheadLength));
929 /* Get current lookahead buffer size of adapter */
930 NdisStatus = MiniQueryInformation(Adapter,
931 OID_GEN_CURRENT_LOOKAHEAD,
934 if (NdisStatus != NDIS_STATUS_SUCCESS) {
935 NDIS_DbgPrint(MIN_TRACE, ("OID_GEN_CURRENT_LOOKAHEAD failed. NdisStatus (0x%X).\n", NdisStatus));
939 Adapter->CurLookaheadLength = *((PULONG)Adapter->QueryBuffer);
941 NDIS_DbgPrint(DEBUG_MINIPORT, ("CurLookaheadLength (0x%X).\n", Adapter->CurLookaheadLength));
943 if (Adapter->MaxLookaheadLength != 0) {
944 Adapter->LookaheadLength = Adapter->MaxLookaheadLength +
945 Adapter->MediumHeaderSize;
946 Adapter->LookaheadBuffer = ExAllocatePool(NonPagedPool,
947 Adapter->LookaheadLength);
948 if (!Adapter->LookaheadBuffer)
949 return NDIS_STATUS_RESOURCES;
952 return STATUS_SUCCESS;
958 NdisMRegisterMiniport(
959 IN NDIS_HANDLE NdisWrapperHandle,
960 IN PNDIS_MINIPORT_CHARACTERISTICS MiniportCharacteristics,
961 IN UINT CharacteristicsLength)
963 * FUNCTION: Registers a miniport's MiniportXxx entry points with the NDIS library
965 * NdisWrapperHandle = Pointer to handle returned by NdisMInitializeWrapper
966 * MiniportCharacteristics = Pointer to a buffer with miniport characteristics
967 * CharacteristicsLength = Number of bytes in characteristics buffer
969 * Status of operation
975 NDIS_STATUS NdisStatus;
976 NDIS_STATUS OpenErrorStatus;
977 UINT SelectedMediumIndex;
978 PLOGICAL_ADAPTER Adapter;
980 BOOLEAN MemError = FALSE;
981 PMINIPORT_DRIVER Miniport = GET_MINIPORT_DRIVER(NdisWrapperHandle);
983 NDIS_DbgPrint(MAX_TRACE, ("Called.\n"));
985 switch (MiniportCharacteristics->MajorNdisVersion) {
987 MinSize = sizeof(NDIS30_MINIPORT_CHARACTERISTICS_S);
991 MinSize = sizeof(NDIS40_MINIPORT_CHARACTERISTICS_S);
995 MinSize = sizeof(NDIS50_MINIPORT_CHARACTERISTICS_S);
999 NDIS_DbgPrint(DEBUG_MINIPORT, ("Bad miniport characteristics version.\n"));
1000 return NDIS_STATUS_BAD_VERSION;
1003 if (CharacteristicsLength < MinSize) {
1004 NDIS_DbgPrint(DEBUG_MINIPORT, ("Bad miniport characteristics.\n"));
1005 return NDIS_STATUS_BAD_CHARACTERISTICS;
1008 /* Check if mandatory MiniportXxx functions are specified */
1009 if ((!MiniportCharacteristics->HaltHandler) ||
1010 (!MiniportCharacteristics->InitializeHandler)||
1011 (!MiniportCharacteristics->QueryInformationHandler) ||
1012 (!MiniportCharacteristics->ResetHandler) ||
1013 (!MiniportCharacteristics->SetInformationHandler)) {
1014 NDIS_DbgPrint(DEBUG_MINIPORT, ("Bad miniport characteristics.\n"));
1015 return NDIS_STATUS_BAD_CHARACTERISTICS;
1018 if (MiniportCharacteristics->MajorNdisVersion == 0x03) {
1019 if (!MiniportCharacteristics->u1.SendHandler) {
1020 NDIS_DbgPrint(DEBUG_MINIPORT, ("Bad miniport characteristics.\n"));
1021 return NDIS_STATUS_BAD_CHARACTERISTICS;
1023 } else if (MiniportCharacteristics->MajorNdisVersion >= 0x04) {
1025 if ((!MiniportCharacteristics->u1.SendHandler) &&
1026 (!MiniportCharacteristics->SendPacketsHandler)) {
1027 NDIS_DbgPrint(DEBUG_MINIPORT, ("Bad miniport characteristics.\n"));
1028 return NDIS_STATUS_BAD_CHARACTERISTICS;
1032 RtlCopyMemory(&Miniport->Chars, MiniportCharacteristics, MinSize);
1034 Adapter = ExAllocatePool(NonPagedPool, sizeof(LOGICAL_ADAPTER));
1036 NDIS_DbgPrint(MIN_TRACE, ("Insufficient resources.\n"));
1037 return NDIS_STATUS_RESOURCES;
1040 /* This is very important */
1041 RtlZeroMemory(Adapter, sizeof(LOGICAL_ADAPTER));
1043 /* Create the device object for this adapter */
1044 /* FIXME: Use GUIDs */
1045 RtlInitUnicodeStringFromLiteral(&Adapter->DeviceName, L"\\Device\\ne2000");
1046 Status = IoCreateDevice(Miniport->DriverObject,
1048 &Adapter->DeviceName,
1049 FILE_DEVICE_PHYSICAL_NETCARD,
1052 &Adapter->NdisMiniportBlock.DeviceObject);
1053 if (!NT_SUCCESS(Status)) {
1054 NDIS_DbgPrint(MIN_TRACE, ("Could not create device object.\n"));
1055 ExFreePool(Adapter);
1056 return NDIS_STATUS_FAILURE;
1059 /* Initialize adapter object */
1061 KeInitializeSpinLock(&Adapter->NdisMiniportBlock.Lock);
1063 InitializeListHead(&Adapter->ProtocolListHead);
1065 Adapter->RefCount = 1;
1067 Adapter->Miniport = Miniport;
1069 /* Set handlers (some NDIS macros require these) */
1071 Adapter->NdisMiniportBlock.EthRxCompleteHandler = MiniEthReceiveComplete;
1072 Adapter->NdisMiniportBlock.EthRxIndicateHandler = MiniEthReceiveIndication;
1074 Adapter->NdisMiniportBlock.SendCompleteHandler = MiniSendComplete;
1075 Adapter->NdisMiniportBlock.SendResourcesHandler = MiniSendResourcesAvailable;
1076 Adapter->NdisMiniportBlock.ResetCompleteHandler = MiniResetComplete;
1077 Adapter->NdisMiniportBlock.TDCompleteHandler = MiniTransferDataComplete;
1080 KeInitializeDpc(&Adapter->MiniportDpc, MiniportDpc, (PVOID)Adapter);
1082 /* Put adapter in adapter list for this miniport */
1083 ExInterlockedInsertTailList(&Miniport->AdapterListHead,
1084 &Adapter->MiniportListEntry,
1087 /* Put adapter in global adapter list */
1088 ExInterlockedInsertTailList(&AdapterListHead,
1089 &Adapter->ListEntry,
1092 /* Call MiniportInitialize */
1093 NdisStatus = (*Miniport->Chars.InitializeHandler)(
1095 &SelectedMediumIndex,
1099 NULL /* FIXME: WrapperConfigurationContext */);
1101 if ((NdisStatus == NDIS_STATUS_SUCCESS) &&
1102 (SelectedMediumIndex < MEDIA_ARRAY_SIZE)) {
1104 Adapter->NdisMiniportBlock.MediaType = MediaArray[SelectedMediumIndex];
1106 switch (Adapter->NdisMiniportBlock.MediaType) {
1107 case NdisMedium802_3:
1108 Adapter->MediumHeaderSize = 14;
1109 AddressOID = OID_802_3_CURRENT_ADDRESS;
1110 Adapter->AddressLength = ETH_LENGTH_OF_ADDRESS;
1112 Adapter->NdisMiniportBlock.FilterDbs.u.EthDB = ExAllocatePool(NonPagedPool,
1113 sizeof(ETH_FILTER));
1114 if (Adapter->NdisMiniportBlock.FilterDbs.u.EthDB) {
1115 RtlZeroMemory(Adapter->NdisMiniportBlock.FilterDbs.u.EthDB, sizeof(ETH_FILTER));
1116 Adapter->NdisMiniportBlock.FilterDbs.u.EthDB->Miniport = (PNDIS_MINIPORT_BLOCK)Adapter;
1122 /* FIXME: Support other types of medias */
1124 return NDIS_STATUS_FAILURE;
1127 NdisStatus = DoQueries(Adapter, AddressOID);
1131 (NdisStatus != NDIS_STATUS_SUCCESS) ||
1132 (SelectedMediumIndex >= MEDIA_ARRAY_SIZE)) {
1134 /* Remove adapter from adapter list for this miniport */
1135 KeAcquireSpinLock(&Miniport->Lock, &OldIrql);
1136 RemoveEntryList(&Adapter->MiniportListEntry);
1137 KeReleaseSpinLock(&Miniport->Lock, OldIrql);
1139 /* Remove adapter from global adapter list */
1140 KeAcquireSpinLock(&AdapterListLock, &OldIrql);
1141 RemoveEntryList(&Adapter->ListEntry);
1142 KeReleaseSpinLock(&AdapterListLock, OldIrql);
1144 if (Adapter->LookaheadBuffer)
1145 ExFreePool(Adapter->LookaheadBuffer);
1147 IoDeleteDevice(Adapter->NdisMiniportBlock.DeviceObject);
1148 ExFreePool(Adapter);
1149 return NDIS_STATUS_FAILURE;
1152 return NDIS_STATUS_SUCCESS;
1159 IN NDIS_HANDLE MiniportAdapterHandle,
1160 IN NDIS_STATUS Status,
1161 IN BOOLEAN AddressingReset)
1163 MiniResetComplete(MiniportAdapterHandle,
1172 IN NDIS_HANDLE MiniportAdapterHandle,
1173 IN PNDIS_PACKET Packet,
1174 IN NDIS_STATUS Status)
1176 * FUNCTION: Forwards a message to the initiating protocol saying
1177 * that a packet was handled
1179 * NdisAdapterHandle = Handle input to MiniportInitialize
1180 * Packet = Pointer to NDIS packet that was sent
1181 * Status = Status of send operation
1184 MiniSendComplete(MiniportAdapterHandle,
1192 NdisMSendResourcesAvailable(
1193 IN NDIS_HANDLE MiniportAdapterHandle)
1195 MiniSendResourcesAvailable(MiniportAdapterHandle);
1201 NdisMTransferDataComplete(
1202 IN NDIS_HANDLE MiniportAdapterHandle,
1203 IN PNDIS_PACKET Packet,
1204 IN NDIS_STATUS Status,
1205 IN UINT BytesTransferred)
1207 MiniTransferDataComplete(MiniportAdapterHandle,
1216 NdisMSetInformationComplete(
1217 IN NDIS_HANDLE MiniportAdapterHandle,
1218 IN NDIS_STATUS Status)
1220 PLOGICAL_ADAPTER Adapter = GET_LOGICAL_ADAPTER(MiniportAdapterHandle);
1221 PADAPTER_BINDING AdapterBinding = (PADAPTER_BINDING)Adapter->MiniportAdapterBinding;
1223 NDIS_DbgPrint(MAX_TRACE, ("Called.\n"));
1225 (*AdapterBinding->ProtocolBinding->Chars.RequestCompleteHandler)(
1226 AdapterBinding->NdisOpenBlock.ProtocolBindingContext,
1227 Adapter->NdisMiniportBlock.MediaRequest,
1235 IN NDIS_HANDLE MiniportAdapterHandle,
1236 IN NDIS_HANDLE MiniportAdapterContext,
1237 IN BOOLEAN BusMaster,
1238 IN NDIS_INTERFACE_TYPE AdapterType)
1240 * FUNCTION: Informs the NDIS library of significant features of the caller's NIC
1242 * MiniportAdapterHandle = Handle input to MiniportInitialize
1243 * MiniportAdapterContext = Pointer to context information
1244 * BusMaster = Specifies TRUE if the caller's NIC is a busmaster DMA device
1245 * AdapterType = Specifies the I/O bus interface of the caller's NIC
1248 PLOGICAL_ADAPTER Adapter = GET_LOGICAL_ADAPTER(MiniportAdapterHandle);
1250 NDIS_DbgPrint(MAX_TRACE, ("Called.\n"));
1252 Adapter->NdisMiniportBlock.MiniportAdapterContext = MiniportAdapterContext;
1253 Adapter->Attributes = BusMaster? NDIS_ATTRIBUTE_BUS_MASTER : 0;
1254 Adapter->NdisMiniportBlock.AdapterType = AdapterType;
1255 Adapter->AttributesSet = TRUE;
1261 NdisMSetAttributesEx(
1262 IN NDIS_HANDLE MiniportAdapterHandle,
1263 IN NDIS_HANDLE MiniportAdapterContext,
1264 IN UINT CheckForHangTimeInSeconds OPTIONAL,
1265 IN ULONG AttributeFlags,
1266 IN NDIS_INTERFACE_TYPE AdapterType)
1268 * FUNCTION: Informs the NDIS library of significant features of the caller's NIC
1270 * MiniportAdapterHandle = Handle input to MiniportInitialize
1271 * MiniportAdapterContext = Pointer to context information
1272 * CheckForHangTimeInSeconds = Specifies interval in seconds at which
1273 * MiniportCheckForHang should be called
1274 * AttributeFlags = Bitmask that indicates specific attributes
1275 * AdapterType = Specifies the I/O bus interface of the caller's NIC
1278 // Currently just like NdisMSetAttributesEx
1279 // TODO: Take CheckForHandTimeInSeconds into account!
1280 PLOGICAL_ADAPTER Adapter = GET_LOGICAL_ADAPTER(MiniportAdapterHandle);
1282 NDIS_DbgPrint(MAX_TRACE, ("Called.\n"));
1283 NDIS_DbgPrint(MIN_TRACE, ("NdisMSetAttributesEx() is partly-implemented."));
1285 Adapter->NdisMiniportBlock.MiniportAdapterContext = MiniportAdapterContext;
1286 Adapter->Attributes = AttributeFlags & NDIS_ATTRIBUTE_BUS_MASTER;
1287 Adapter->NdisMiniportBlock.AdapterType = AdapterType;
1288 Adapter->AttributesSet = TRUE;
1295 IN ULONG MicrosecondsToSleep)
1303 NdisMSynchronizeWithInterrupt(
1304 IN PNDIS_MINIPORT_INTERRUPT Interrupt,
1305 IN PVOID SynchronizeFunction,
1306 IN PVOID SynchronizeContext)
1317 IN NDIS_HANDLE LogHandle,
1319 IN UINT LogBufferSize)
1323 return NDIS_STATUS_FAILURE;
1329 NdisTerminateWrapper(
1330 IN NDIS_HANDLE NdisWrapperHandle,
1331 IN PVOID SystemSpecific)
1333 * FUNCTION: Releases resources allocated by a call to NdisInitializeWrapper
1335 * NdisWrapperHandle = Handle returned by NdisInitializeWrapper (MINIPORT_DRIVER)
1336 * SystemSpecific = Always NULL
1339 PMINIPORT_DRIVER Miniport = GET_MINIPORT_DRIVER(NdisWrapperHandle);
1341 NDIS_DbgPrint(MAX_TRACE, ("Called.\n"));
1343 ExFreePool(Miniport);