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)
7 * Vizzini (vizzini@plasmic.com)
9 * CSH 01/08-2000 Created
10 * 8/20/2003 vizzini - DMA support
18 /* Root of the scm database */
19 #define SERVICES_ROOT L"\\Registry\\Machine\\System\\CurrentControlSet\\Services\\"
21 /* prefix for device object registration */
22 #define DEVICE_ROOT L"\\Device\\"
25 * Define to 1 to get a debugger breakpoint at the end of NdisInitializeWrapper
26 * for each new miniport starting up
28 #define BREAK_ON_MINIPORT_INIT 0
31 * This has to be big enough to hold the results of querying the Route value
32 * from the Linkage key. Please re-code me to determine this dynamically.
34 #define ROUTE_DATA_SIZE 256
36 /* Number of media we know */
37 #define MEDIA_ARRAY_SIZE 15
39 static NDIS_MEDIUM MediaArray[MEDIA_ARRAY_SIZE] = {
47 NdisMediumArcnet878_2,
49 NdisMediumWirelessWan,
57 /* global list and lock of Miniports NDIS has registered */
58 LIST_ENTRY MiniportListHead;
59 KSPIN_LOCK MiniportListLock;
61 /* global list and lock of adapters NDIS has registered */
62 LIST_ENTRY AdapterListHead;
63 KSPIN_LOCK AdapterListLock;
65 /* global list and lock of orphan adapters waiting to be claimed by a miniport */
66 LIST_ENTRY OrphanAdapterListHead;
67 KSPIN_LOCK OrphanAdapterListLock;
78 if ((DebugTraceLevel | DEBUG_PACKET) > 0) {
79 Length = CopyPacketToBuffer(
85 DbgPrint("*** PACKET START ***");
87 for (i = 0; i < Length; i++) {
89 DbgPrint("\n%04X ", i);
90 DbgPrint("%02X ", Buffer[i]);
93 DbgPrint("*** PACKET STOP ***\n");
102 PLOGICAL_ADAPTER Adapter,
103 NDIS_HANDLE MacReceiveContext,
105 UINT HeaderBufferSize,
106 PVOID LookaheadBuffer,
107 UINT LookaheadBufferSize,
110 * FUNCTION: Indicate received data to bound protocols
112 * Adapter = Pointer to logical adapter
113 * MacReceiveContext = MAC receive context handle
114 * HeaderBuffer = Pointer to header buffer
115 * HeaderBufferSize = Size of header buffer
116 * LookaheadBuffer = Pointer to lookahead buffer
117 * LookaheadBufferSize = Size of lookahead buffer
118 * PacketSize = Total size of received packet
122 PLIST_ENTRY CurrentEntry;
123 PADAPTER_BINDING AdapterBinding;
125 NDIS_DbgPrint(DEBUG_MINIPORT, ("Called. Adapter (0x%X) HeaderBuffer (0x%X) "
126 "HeaderBufferSize (0x%X) LookaheadBuffer (0x%X) LookaheadBufferSize (0x%X).\n",
127 Adapter, HeaderBuffer, HeaderBufferSize, LookaheadBuffer, LookaheadBufferSize));
131 if ((DebugTraceLevel | DEBUG_PACKET) > 0) {
135 DbgPrint("*** RECEIVE PACKET START ***\n");
138 for (i = 0; i < HeaderBufferSize; i++) {
140 DbgPrint("\n%04X ", i);
141 DbgPrint("%02X ", *p);
145 DbgPrint("\nFRAME:");
148 Length = (LookaheadBufferSize < 64)? LookaheadBufferSize : 64;
149 for (i = 0; i < Length; i++) {
151 DbgPrint("\n%04X ", i);
152 DbgPrint("%02X ", *p);
156 DbgPrint("\n*** RECEIVE PACKET STOP ***\n");
161 KeAcquireSpinLock(&Adapter->NdisMiniportBlock.Lock, &OldIrql);
162 CurrentEntry = Adapter->ProtocolListHead.Flink;
164 if (CurrentEntry == &Adapter->ProtocolListHead) {
165 NDIS_DbgPrint(DEBUG_MINIPORT, ("WARNING: No upper protocol layer.\n"));
168 while (CurrentEntry != &Adapter->ProtocolListHead) {
169 AdapterBinding = CONTAINING_RECORD(CurrentEntry,
173 KeReleaseSpinLock(&Adapter->NdisMiniportBlock.Lock, OldIrql);
175 (*AdapterBinding->ProtocolBinding->Chars.u4.ReceiveHandler)(
176 AdapterBinding->NdisOpenBlock.ProtocolBindingContext,
184 KeAcquireSpinLock(&Adapter->NdisMiniportBlock.Lock, &OldIrql);
186 CurrentEntry = CurrentEntry->Flink;
188 KeReleaseSpinLock(&Adapter->NdisMiniportBlock.Lock, OldIrql);
193 MiniIndicateReceivePacket(
194 IN NDIS_HANDLE Miniport,
195 IN PPNDIS_PACKET PacketArray,
196 IN UINT NumberOfPackets)
198 * FUNCTION: receives miniport packet array indications
200 * Miniport: Miniport handle for the adapter
201 * PacketArray: pointer to a list of packet pointers to indicate
202 * NumberOfPackets: number of packets to indicate
205 NDIS_DbgPrint(MAX_TRACE, ("Called.\n"));
210 MiniEthReceiveComplete(
211 IN PETH_FILTER Filter)
213 * FUNCTION: Receive indication complete function for Ethernet devices
215 * Filter = Pointer to Ethernet filter
219 PLIST_ENTRY CurrentEntry;
220 PLOGICAL_ADAPTER Adapter;
221 PADAPTER_BINDING AdapterBinding;
223 NDIS_DbgPrint(DEBUG_MINIPORT, ("Called.\n"));
225 Adapter = (PLOGICAL_ADAPTER)Filter->Miniport;
227 KeAcquireSpinLock(&Adapter->NdisMiniportBlock.Lock, &OldIrql);
228 CurrentEntry = Adapter->ProtocolListHead.Flink;
229 while (CurrentEntry != &Adapter->ProtocolListHead) {
230 AdapterBinding = CONTAINING_RECORD(CurrentEntry,
234 KeReleaseSpinLock(&Adapter->NdisMiniportBlock.Lock, OldIrql);
236 (*AdapterBinding->ProtocolBinding->Chars.ReceiveCompleteHandler)(
237 AdapterBinding->NdisOpenBlock.ProtocolBindingContext);
239 KeAcquireSpinLock(&Adapter->NdisMiniportBlock.Lock, &OldIrql);
241 CurrentEntry = CurrentEntry->Flink;
243 KeReleaseSpinLock(&Adapter->NdisMiniportBlock.Lock, OldIrql);
248 MiniEthReceiveIndication(
249 IN PETH_FILTER Filter,
250 IN NDIS_HANDLE MacReceiveContext,
252 IN PVOID HeaderBuffer,
253 IN UINT HeaderBufferSize,
254 IN PVOID LookaheadBuffer,
255 IN UINT LookaheadBufferSize,
258 * FUNCTION: Receive indication function for Ethernet devices
260 * Filter = Pointer to Ethernet filter
261 * MacReceiveContext = MAC receive context handle
262 * Address = Pointer to destination Ethernet address
263 * HeaderBuffer = Pointer to Ethernet header buffer
264 * HeaderBufferSize = Size of Ethernet header buffer
265 * LookaheadBuffer = Pointer to lookahead buffer
266 * LookaheadBufferSize = Size of lookahead buffer
267 * PacketSize = Total size of received packet
270 MiniIndicateData((PLOGICAL_ADAPTER)Filter->Miniport,
282 IN NDIS_HANDLE MiniportAdapterHandle,
283 IN NDIS_STATUS Status,
284 IN BOOLEAN AddressingReset)
292 IN NDIS_HANDLE MiniportAdapterHandle,
293 IN PNDIS_PACKET Packet,
294 IN NDIS_STATUS Status)
296 * FUNCTION: Forwards a message to the initiating protocol saying
297 * that a packet was handled
299 * NdisAdapterHandle = Handle input to MiniportInitialize
300 * Packet = Pointer to NDIS packet that was sent
301 * Status = Status of send operation
304 PADAPTER_BINDING AdapterBinding;
306 NDIS_DbgPrint(DEBUG_MINIPORT, ("Called.\n"));
308 AdapterBinding = (PADAPTER_BINDING)Packet->Reserved[0];
310 (*AdapterBinding->ProtocolBinding->Chars.u2.SendCompleteHandler)(
311 AdapterBinding->NdisOpenBlock.ProtocolBindingContext,
318 MiniSendResourcesAvailable(
319 IN NDIS_HANDLE MiniportAdapterHandle)
326 MiniTransferDataComplete(
327 IN NDIS_HANDLE MiniportAdapterHandle,
328 IN PNDIS_PACKET Packet,
329 IN NDIS_STATUS Status,
330 IN UINT BytesTransferred)
332 PLOGICAL_ADAPTER Adapter = (PLOGICAL_ADAPTER)MiniportAdapterHandle;
333 PADAPTER_BINDING AdapterBinding = Adapter->MiniportAdapterBinding;
335 NDIS_DbgPrint(DEBUG_MINIPORT, ("Called.\n"));
337 (*AdapterBinding->ProtocolBinding->Chars.u3.TransferDataCompleteHandler)(
338 AdapterBinding->NdisOpenBlock.ProtocolBindingContext,
346 MiniAdapterHasAddress(
347 PLOGICAL_ADAPTER Adapter,
350 * FUNCTION: Determines wether a packet has the same destination address as an adapter
352 * Adapter = Pointer to logical adapter object
353 * Packet = Pointer to NDIS packet
355 * TRUE if the destination address is that of the adapter, FALSE if not
361 PNDIS_BUFFER NdisBuffer;
364 NDIS_DbgPrint(DEBUG_MINIPORT, ("Called.\n"));
366 Start1 = (PUCHAR)&Adapter->Address;
367 NdisQueryPacket(Packet, NULL, NULL, &NdisBuffer, NULL);
369 NDIS_DbgPrint(MID_TRACE, ("Packet contains no buffers.\n"));
373 NdisQueryBuffer(NdisBuffer, (PVOID)&Start2, &BufferLength);
375 /* FIXME: Should handle fragmented packets */
377 switch (Adapter->NdisMiniportBlock.MediaType) {
378 case NdisMedium802_3:
379 Length = ETH_LENGTH_OF_ADDRESS;
380 /* Destination address is the first field */
384 NDIS_DbgPrint(MIN_TRACE, ("Adapter has unsupported media type (0x%X).\n",
385 Adapter->NdisMiniportBlock.MediaType));
389 if (BufferLength < Length) {
390 NDIS_DbgPrint(MID_TRACE, ("Buffer is too small.\n"));
394 return (RtlCompareMemory((PVOID)Start1, (PVOID)Start2, Length) == Length);
400 PNDIS_STRING AdapterName)
402 * FUNCTION: Returns the logical adapter object for a specific adapter
404 * AdapterName = Pointer to name of adapter
406 * Pointer to logical adapter object, or NULL if none was found.
407 * If found, the adapter is referenced for the caller. The caller
408 * is responsible for dereferencing after use
412 PLIST_ENTRY CurrentEntry;
413 PLOGICAL_ADAPTER Adapter;
415 NDIS_DbgPrint(DEBUG_MINIPORT, ("Called.\n"));
417 KeAcquireSpinLock(&AdapterListLock, &OldIrql);
418 CurrentEntry = AdapterListHead.Flink;
419 while (CurrentEntry != &AdapterListHead) {
420 Adapter = CONTAINING_RECORD(CurrentEntry, LOGICAL_ADAPTER, ListEntry);
422 if (RtlCompareUnicodeString(AdapterName, &Adapter->DeviceName, TRUE) == 0) {
423 ReferenceObject(Adapter);
424 KeReleaseSpinLock(&AdapterListLock, OldIrql);
426 NDIS_DbgPrint(DEBUG_MINIPORT, ("Leaving. Adapter found at (0x%X).\n", Adapter));
431 CurrentEntry = CurrentEntry->Flink;
433 KeReleaseSpinLock(&AdapterListLock, OldIrql);
435 NDIS_DbgPrint(DEBUG_MINIPORT, ("Leaving (adapter not found).\n"));
442 MiniQueryInformation(
443 PLOGICAL_ADAPTER Adapter,
448 * FUNCTION: Queries a logical adapter for properties
450 * Adapter = Pointer to the logical adapter object to query
451 * Oid = Specifies the Object ID to query for
452 * Size = If non-zero overrides the length in the adapter object
453 * BytesWritten = Address of buffer to place number of bytes written
455 * If the specified buffer is too small, a new buffer is allocated,
456 * and the query is attempted again
458 * Status of operation
461 NDIS_STATUS NdisStatus;
464 NDIS_DbgPrint(DEBUG_MINIPORT, ("Called.\n"));
466 if (Adapter->QueryBufferLength == 0) {
467 Adapter->QueryBuffer = ExAllocatePool(NonPagedPool, (Size == 0)? 32 : Size);
469 if (!Adapter->QueryBuffer) {
470 NDIS_DbgPrint(MIN_TRACE, ("Insufficient resources.\n"));
471 return NDIS_STATUS_RESOURCES;
474 Adapter->QueryBufferLength = (Size == 0)? 32 : Size;
477 BytesNeeded = (Size == 0)? Adapter->QueryBufferLength : Size;
479 NdisStatus = (*Adapter->Miniport->Chars.QueryInformationHandler)(
480 Adapter->NdisMiniportBlock.MiniportAdapterContext,
482 Adapter->QueryBuffer,
487 if ((NT_SUCCESS(NdisStatus)) || (NdisStatus == NDIS_STATUS_PENDING)) {
488 NDIS_DbgPrint(DEBUG_MINIPORT, ("Miniport returned status (0x%X).\n", NdisStatus));
492 if (NdisStatus == NDIS_STATUS_INVALID_LENGTH) {
493 ExFreePool(Adapter->QueryBuffer);
495 Adapter->QueryBufferLength += BytesNeeded;
496 Adapter->QueryBuffer = ExAllocatePool(NonPagedPool,
497 Adapter->QueryBufferLength);
499 if (!Adapter->QueryBuffer) {
500 NDIS_DbgPrint(MIN_TRACE, ("Insufficient resources.\n"));
501 return NDIS_STATUS_RESOURCES;
504 NdisStatus = (*Adapter->Miniport->Chars.QueryInformationHandler)(
505 Adapter->NdisMiniportBlock.MiniportAdapterContext,
507 Adapter->QueryBuffer,
520 PLOGICAL_ADAPTER Adapter,
521 NDIS_WORK_ITEM_TYPE WorkItemType,
522 PVOID WorkItemContext,
523 NDIS_HANDLE Initiator)
525 * FUNCTION: Queues a work item for execution at a later time
527 * Adapter = Pointer to the logical adapter object to queue work item on
528 * WorkItemType = Type of work item to queue
529 * WorkItemContext = Pointer to context information for work item
530 * Initiator = Pointer to ADAPTER_BINDING structure of initiating protocol
532 * Adapter lock must be held when called
534 * Status of operation
537 PNDIS_MINIPORT_WORK_ITEM Item;
539 NDIS_DbgPrint(MAX_TRACE, ("Called.\n"));
541 if (Adapter->WorkQueueLevel < NDIS_MINIPORT_WORK_QUEUE_SIZE - 1) {
542 Item = &Adapter->WorkQueue[Adapter->WorkQueueLevel];
543 Adapter->WorkQueueLevel++;
545 Item = ExAllocatePool(NonPagedPool, sizeof(NDIS_MINIPORT_WORK_ITEM));
547 /* Set flag so we know that the buffer should be freed
548 when work item is dequeued */
549 Item->Allocated = TRUE;
551 NDIS_DbgPrint(MIN_TRACE, ("Insufficient resources.\n"));
552 return NDIS_STATUS_RESOURCES;
556 Item->WorkItemType = WorkItemType;
557 Item->WorkItemContext = WorkItemContext;
558 Item->Initiator = Initiator;
560 Item->Link.Next = NULL;
561 if (!Adapter->WorkQueueHead) {
562 Adapter->WorkQueueHead = Item;
564 Adapter->WorkQueueTail->Link.Next = (PSINGLE_LIST_ENTRY)Item;
567 KeInsertQueueDpc(&Adapter->MiniportDpc, NULL, NULL);
569 return NDIS_STATUS_SUCCESS;
576 PLOGICAL_ADAPTER Adapter,
577 NDIS_WORK_ITEM_TYPE *WorkItemType,
578 PVOID *WorkItemContext,
579 NDIS_HANDLE *Initiator)
581 * FUNCTION: Dequeues a work item from the work queue of a logical adapter
583 * Adapter = Pointer to the logical adapter object to dequeue work item from
584 * WorkItemType = Address of buffer for work item type
585 * WorkItemContext = Address of buffer for pointer to context information
586 * Initiator = Address of buffer for initiator of the work (ADAPTER_BINDING)
588 * Adapter lock must be held when called
590 * Status of operation
593 PNDIS_MINIPORT_WORK_ITEM Item;
595 NDIS_DbgPrint(MAX_TRACE, ("Called.\n"));
597 Item = Adapter->WorkQueueHead;
599 Adapter->WorkQueueHead = (PNDIS_MINIPORT_WORK_ITEM)Item->Link.Next;
600 if (Item == Adapter->WorkQueueTail)
601 Adapter->WorkQueueTail = NULL;
603 *WorkItemType = Item->WorkItemType;
604 *WorkItemContext = Item->WorkItemContext;
605 *Initiator = Item->Initiator;
607 if (Item->Allocated) {
610 Adapter->WorkQueueLevel--;
612 if (Adapter->WorkQueueLevel < 0) {
613 NDIS_DbgPrint(MIN_TRACE, ("Adapter->WorkQueueLevel is < 0 (should be >= 0).\n"));
618 return NDIS_STATUS_SUCCESS;
621 return NDIS_STATUS_FAILURE;
627 PLOGICAL_ADAPTER Adapter,
628 PNDIS_REQUEST NdisRequest)
630 * FUNCTION: Sends a request to a miniport
632 * Adapter = Pointer to logical adapter object
633 * NdisRequest = Pointer to NDIS request structure describing request
635 * Status of operation
638 NDIS_DbgPrint(DEBUG_MINIPORT, ("Called.\n"));
640 Adapter->NdisMiniportBlock.MediaRequest = NdisRequest;
642 switch (NdisRequest->RequestType) {
643 case NdisRequestQueryInformation:
644 return (*Adapter->Miniport->Chars.QueryInformationHandler)(
645 Adapter->NdisMiniportBlock.MiniportAdapterContext,
646 NdisRequest->DATA.QUERY_INFORMATION.Oid,
647 NdisRequest->DATA.QUERY_INFORMATION.InformationBuffer,
648 NdisRequest->DATA.QUERY_INFORMATION.InformationBufferLength,
649 (PULONG)&NdisRequest->DATA.QUERY_INFORMATION.BytesWritten,
650 (PULONG)&NdisRequest->DATA.QUERY_INFORMATION.BytesNeeded);
653 case NdisRequestSetInformation:
654 return (*Adapter->Miniport->Chars.SetInformationHandler)(
655 Adapter->NdisMiniportBlock.MiniportAdapterContext,
656 NdisRequest->DATA.SET_INFORMATION.Oid,
657 NdisRequest->DATA.SET_INFORMATION.InformationBuffer,
658 NdisRequest->DATA.SET_INFORMATION.InformationBufferLength,
659 (PULONG)&NdisRequest->DATA.SET_INFORMATION.BytesRead,
660 (PULONG)&NdisRequest->DATA.SET_INFORMATION.BytesNeeded);
664 return NDIS_STATUS_FAILURE;
669 VOID STDCALL MiniportDpc(
671 IN PVOID DeferredContext,
672 IN PVOID SystemArgument1,
673 IN PVOID SystemArgument2)
675 * FUNCTION: Deferred routine to handle serialization
677 * Dpc = Pointer to DPC object
678 * DeferredContext = Pointer to context information (LOGICAL_ADAPTER)
679 * SystemArgument1 = Unused
680 * SystemArgument2 = Unused
683 NDIS_STATUS NdisStatus;
684 PVOID WorkItemContext;
685 NDIS_WORK_ITEM_TYPE WorkItemType;
686 PADAPTER_BINDING AdapterBinding;
687 PLOGICAL_ADAPTER Adapter = GET_LOGICAL_ADAPTER(DeferredContext);
689 NDIS_DbgPrint(DEBUG_MINIPORT, ("Called.\n"));
691 NdisStatus = MiniDequeueWorkItem(Adapter,
694 (PNDIS_HANDLE)&AdapterBinding);
695 if (NdisStatus == NDIS_STATUS_SUCCESS) {
696 Adapter->MiniportAdapterBinding = AdapterBinding;
697 switch (WorkItemType) {
698 case NdisWorkItemSend:
700 MiniDisplayPacket((PNDIS_PACKET)WorkItemContext);
702 NdisStatus = (*Adapter->Miniport->Chars.u1.SendHandler)(
703 Adapter->NdisMiniportBlock.MiniportAdapterContext,
704 (PNDIS_PACKET)WorkItemContext,
706 if (NdisStatus != NDIS_STATUS_PENDING) {
707 MiniSendComplete((NDIS_HANDLE)Adapter,
708 (PNDIS_PACKET)WorkItemContext,
713 case NdisWorkItemSendLoopback:
714 NdisStatus = ProIndicatePacket(Adapter,
715 (PNDIS_PACKET)WorkItemContext);
716 MiniSendComplete((NDIS_HANDLE)Adapter,
717 (PNDIS_PACKET)WorkItemContext,
721 case NdisWorkItemReturnPackets:
724 case NdisWorkItemResetRequested:
727 case NdisWorkItemResetInProgress:
730 case NdisWorkItemHalt:
733 case NdisWorkItemMiniportCallback:
736 case NdisWorkItemRequest:
737 NdisStatus = MiniDoRequest(Adapter, (PNDIS_REQUEST)WorkItemContext);
739 if (NdisStatus == NDIS_STATUS_PENDING)
742 switch (((PNDIS_REQUEST)WorkItemContext)->RequestType) {
743 case NdisRequestQueryInformation:
744 NdisMQueryInformationComplete((NDIS_HANDLE)Adapter, NdisStatus);
747 case NdisRequestSetInformation:
748 NdisMSetInformationComplete((NDIS_HANDLE)Adapter, NdisStatus);
752 NDIS_DbgPrint(MIN_TRACE, ("Unknown NDIS request type.\n"));
758 NDIS_DbgPrint(MIN_TRACE, ("Unknown NDIS work item type (%d).\n", WorkItemType));
771 IN NDIS_HANDLE LogHandle)
783 IN NDIS_HANDLE MiniportAdapterHandle,
785 OUT PNDIS_HANDLE LogHandle)
789 return NDIS_STATUS_FAILURE;
798 NdisMDeregisterAdapterShutdownHandler(
799 IN NDIS_HANDLE MiniportHandle)
801 * FUNCTION: de-registers a shutdown handler
802 * ARGUMENTS: MiniportHandle: Handle passed into MiniportInitialize
805 NDIS_DbgPrint(DEBUG_MINIPORT, ("Called.\n"));
806 PLOGICAL_ADAPTER Adapter = (PLOGICAL_ADAPTER)MiniportHandle;
808 if(Adapter->BugcheckContext->ShutdownHandler)
809 KeDeregisterBugCheckCallback(Adapter->BugcheckContext->CallbackRecord);
819 IN NDIS_HANDLE LogHandle)
831 IN NDIS_HANDLE MiniportAdapterHandle,
832 IN NDIS_STATUS GeneralStatus,
833 IN PVOID StatusBuffer,
834 IN UINT StatusBufferSize)
845 NdisMIndicateStatusComplete(
846 IN NDIS_HANDLE MiniportAdapterHandle)
857 NdisInitializeWrapper(
858 OUT PNDIS_HANDLE NdisWrapperHandle,
859 IN PVOID SystemSpecific1,
860 IN PVOID SystemSpecific2,
861 IN PVOID SystemSpecific3)
863 * FUNCTION: Notifies the NDIS library that a new miniport is initializing
865 * NdisWrapperHandle = Address of buffer to place NDIS wrapper handle
866 * SystemSpecific1 = Pointer to the driver's driver object
867 * SystemSpecific2 = Pointer to the driver's registry path
868 * SystemSpecific3 = Always NULL
870 * - SystemSpecific2 goes invalid so we copy it
873 PMINIPORT_DRIVER Miniport;
874 PUNICODE_STRING RegistryPath;
875 WCHAR *RegistryBuffer;
877 NDIS_DbgPrint(MAX_TRACE, ("Called.\n"));
879 #if BREAK_ON_MINIPORT_INIT
880 __asm__ ("int $3\n");
883 Miniport = ExAllocatePool(NonPagedPool, sizeof(MINIPORT_DRIVER));
885 NDIS_DbgPrint(MIN_TRACE, ("Insufficient resources.\n"));
886 *NdisWrapperHandle = NULL;
890 RtlZeroMemory(Miniport, sizeof(MINIPORT_DRIVER));
892 KeInitializeSpinLock(&Miniport->Lock);
894 Miniport->RefCount = 1;
896 Miniport->DriverObject = (PDRIVER_OBJECT)SystemSpecific1;
898 /* set the miniport's driver registry path */
899 RegistryPath = ExAllocatePool(PagedPool, sizeof(UNICODE_STRING));
902 NDIS_DbgPrint(MIN_TRACE, ("Insufficient resources.\n"));
906 RegistryPath->Length = ((PUNICODE_STRING)SystemSpecific2)->Length;
907 RegistryPath->MaximumLength = RegistryPath->Length + sizeof(WCHAR); /* room for 0-term */
909 RegistryBuffer = ExAllocatePool(PagedPool, RegistryPath->Length + sizeof(WCHAR));
912 NDIS_DbgPrint(MIN_TRACE, ("Insufficient resources.\n"));
916 RtlCopyMemory(RegistryBuffer, ((PUNICODE_STRING)SystemSpecific2)->Buffer, RegistryPath->Length);
917 RegistryBuffer[RegistryPath->Length/sizeof(WCHAR)] = 0;
919 RegistryPath->Buffer = RegistryBuffer;
920 Miniport->RegistryPath = RegistryPath;
922 InitializeListHead(&Miniport->AdapterListHead);
924 /* Put miniport in global miniport list */
925 ExInterlockedInsertTailList(&MiniportListHead,
926 &Miniport->ListEntry,
929 *NdisWrapperHandle = Miniport;
939 NdisMQueryInformationComplete(
940 IN NDIS_HANDLE MiniportAdapterHandle,
941 IN NDIS_STATUS Status)
943 PLOGICAL_ADAPTER Adapter = GET_LOGICAL_ADAPTER(MiniportAdapterHandle);
944 PADAPTER_BINDING AdapterBinding = (PADAPTER_BINDING)Adapter->MiniportAdapterBinding;
946 NDIS_DbgPrint(MAX_TRACE, ("Called.\n"));
948 (*AdapterBinding->ProtocolBinding->Chars.RequestCompleteHandler)(
949 AdapterBinding->NdisOpenBlock.ProtocolBindingContext,
950 Adapter->NdisMiniportBlock.MediaRequest,
955 VOID NdisIBugcheckCallback(
959 * FUNCTION: Internal callback for handling bugchecks - calls adapter's shutdown handler
961 * Buffer: Pointer to a bugcheck callback context
965 PMINIPORT_BUGCHECK_CONTEXT Context = (PMINIPORT_BUGCHECK_CONTEXT)Buffer;
966 ADAPTER_SHUTDOWN_HANDLER sh = (ADAPTER_SHUTDOWN_HANDLER)Context->ShutdownHandler;
968 NDIS_DbgPrint(DEBUG_MINIPORT, ("Called.\n"));
971 sh(Context->DriverContext);
980 NdisMRegisterAdapterShutdownHandler(
981 IN NDIS_HANDLE MiniportHandle,
982 IN PVOID ShutdownContext,
983 IN ADAPTER_SHUTDOWN_HANDLER ShutdownHandler)
985 * FUNCTION: Register a shutdown handler for an adapter
987 * MiniportHandle: Handle originally passed into MiniportInitialize
988 * ShutdownContext: Pre-initialized bugcheck context
989 * ShutdownHandler: Function to call to handle the bugcheck
991 * - I'm not sure about ShutdownContext
992 * - FIXME - memory leak below
995 PLOGICAL_ADAPTER Adapter = (PLOGICAL_ADAPTER)MiniportHandle;
996 PMINIPORT_BUGCHECK_CONTEXT BugcheckContext = Adapter->BugcheckContext;
998 NDIS_DbgPrint(DEBUG_MINIPORT, ("Called.\n"));
1003 BugcheckContext = ExAllocatePool(NonPagedPool, sizeof(MINIPORT_BUGCHECK_CONTEXT));
1004 if(!BugcheckContext)
1006 NDIS_DbgPrint(MIN_TRACE, ("Insufficient resources.\n"));
1010 BugcheckContext->ShutdownHandler = ShutdownHandler;
1011 BugcheckContext->DriverContext = ShutdownContext;
1013 /* not sure if this needs to be initialized or not... oh well, it's a leak. */
1014 BugcheckContext->CallbackRecord = ExAllocatePool(NonPagedPool, sizeof(KBUGCHECK_CALLBACK_RECORD));
1016 KeRegisterBugCheckCallback(BugcheckContext->CallbackRecord, NdisIBugcheckCallback,
1017 BugcheckContext, sizeof(BugcheckContext), "Ndis Miniport");
1023 PLOGICAL_ADAPTER Adapter,
1024 NDIS_OID AddressOID)
1026 * FUNCTION: Queries miniport for information
1028 * Adapter = Pointer to logical adapter
1029 * AddressOID = OID to use to query for current address
1031 * Status of operation
1035 NDIS_STATUS NdisStatus;
1037 NDIS_DbgPrint(MAX_TRACE, ("Called.\n"));
1039 /* Get MAC options for adapter */
1040 NdisStatus = MiniQueryInformation(Adapter,
1041 OID_GEN_MAC_OPTIONS,
1044 if (NdisStatus != NDIS_STATUS_SUCCESS) {
1045 NDIS_DbgPrint(MIN_TRACE, ("OID_GEN_MAC_OPTIONS failed. NdisStatus (0x%X).\n", NdisStatus));
1049 RtlCopyMemory(&Adapter->NdisMiniportBlock.MacOptions, Adapter->QueryBuffer, sizeof(UINT));
1051 NDIS_DbgPrint(DEBUG_MINIPORT, ("MacOptions (0x%X).\n", Adapter->NdisMiniportBlock.MacOptions));
1053 /* Get current hardware address of adapter */
1054 NdisStatus = MiniQueryInformation(Adapter,
1058 if (NdisStatus != NDIS_STATUS_SUCCESS) {
1059 NDIS_DbgPrint(MIN_TRACE, ("Address OID (0x%X) failed. NdisStatus (0x%X).\n",
1060 AddressOID, NdisStatus));
1064 RtlCopyMemory(&Adapter->Address, Adapter->QueryBuffer, Adapter->AddressLength);
1069 PUCHAR A = (PUCHAR)&Adapter->Address.Type.Medium802_3;
1071 NDIS_DbgPrint(MAX_TRACE, ("Adapter address is (%02X %02X %02X %02X %02X %02X).\n",
1072 A[0], A[1], A[2], A[3], A[4], A[5]));
1076 /* Get maximum lookahead buffer size of adapter */
1077 NdisStatus = MiniQueryInformation(Adapter,
1078 OID_GEN_MAXIMUM_LOOKAHEAD,
1081 if (NdisStatus != NDIS_STATUS_SUCCESS) {
1082 NDIS_DbgPrint(MIN_TRACE, ("OID_GEN_MAXIMUM_LOOKAHEAD failed. NdisStatus (0x%X).\n", NdisStatus));
1086 Adapter->MaxLookaheadLength = *((PULONG)Adapter->QueryBuffer);
1088 NDIS_DbgPrint(DEBUG_MINIPORT, ("MaxLookaheadLength (0x%X).\n", Adapter->MaxLookaheadLength));
1090 /* Get current lookahead buffer size of adapter */
1091 NdisStatus = MiniQueryInformation(Adapter,
1092 OID_GEN_CURRENT_LOOKAHEAD,
1095 if (NdisStatus != NDIS_STATUS_SUCCESS) {
1096 NDIS_DbgPrint(MIN_TRACE, ("OID_GEN_CURRENT_LOOKAHEAD failed. NdisStatus (0x%X).\n", NdisStatus));
1100 Adapter->CurLookaheadLength = *((PULONG)Adapter->QueryBuffer);
1102 NDIS_DbgPrint(DEBUG_MINIPORT, ("CurLookaheadLength (0x%X).\n", Adapter->CurLookaheadLength));
1104 if (Adapter->MaxLookaheadLength != 0) {
1105 Adapter->LookaheadLength = Adapter->MaxLookaheadLength +
1106 Adapter->MediumHeaderSize;
1107 Adapter->LookaheadBuffer = ExAllocatePool(NonPagedPool,
1108 Adapter->LookaheadLength);
1109 if (!Adapter->LookaheadBuffer)
1110 return NDIS_STATUS_RESOURCES;
1113 return STATUS_SUCCESS;
1119 WCHAR *DeviceNameStr,
1120 UINT DeviceNameStrLength,
1121 PMINIPORT_DRIVER Miniport
1124 * FUNCTION: Start an adapter
1126 * DeviceNameStr: 0-terminated wide char string of name of device to start
1127 * DeviceNameStrLength: length of DeviceNameStr *IN WCHARs*
1130 * - verify that all resources are properly freed on success & failure
1134 HANDLE RegKeyHandle;
1136 UNICODE_STRING RegKeyPathU;
1137 OBJECT_ATTRIBUTES RegKeyAttributes;
1138 NDIS_STATUS NdisStatus;
1139 NDIS_STATUS OpenErrorStatus;
1141 UINT SelectedMediumIndex = 0;
1142 PLOGICAL_ADAPTER Adapter = 0;
1143 NDIS_OID AddressOID;
1144 BOOLEAN MemError = FALSE;
1146 PORPHAN_ADAPTER OrphanAdapter = 0;
1148 NDIS_DbgPrint(MAX_TRACE, ("Called with %ws\n", DeviceNameStr));
1149 Adapter = ExAllocatePool(NonPagedPool, sizeof(LOGICAL_ADAPTER));
1152 NDIS_DbgPrint(MIN_TRACE, ("Insufficient resources.\n"));
1156 /* This is very important */
1157 RtlZeroMemory(Adapter, sizeof(LOGICAL_ADAPTER));
1159 DeviceName = ExAllocatePool(NonPagedPool, sizeof(DEVICE_ROOT) + DeviceNameStrLength * sizeof(WCHAR));
1162 NDIS_DbgPrint(MIN_TRACE,("Insufficient memory\n"));
1163 ExFreePool(Adapter);
1167 /* DEVICE_ROOT is a constant string defined above, incl. 0-term */
1168 wcscpy(DeviceName, DEVICE_ROOT);
1170 /* reg_sz is 0-term by def */
1171 wcsncat(DeviceName, DeviceNameStr, DeviceNameStrLength);
1172 RtlInitUnicodeString(&Adapter->DeviceName, DeviceName);
1174 NDIS_DbgPrint(MAX_TRACE, ("creating device %ws\n", DeviceName));
1176 Status = IoCreateDevice(Miniport->DriverObject, 0, &Adapter->DeviceName, FILE_DEVICE_PHYSICAL_NETCARD,
1177 0, FALSE, &Adapter->NdisMiniportBlock.DeviceObject);
1178 if (!NT_SUCCESS(Status))
1180 NDIS_DbgPrint(MIN_TRACE, ("Could not create device object.\n"));
1181 ExFreePool(Adapter);
1185 /* find out if there are any adapters in the orphans list and reserve resources */
1186 KeAcquireSpinLock(&OrphanAdapterListLock, &OldIrql);
1187 OrphanAdapter = (PORPHAN_ADAPTER)OrphanAdapterListHead.Flink;
1188 while(&OrphanAdapter->ListEntry != &OrphanAdapterListHead)
1190 PORPHAN_ADAPTER TempAdapter;
1191 PCM_RESOURCE_LIST ResourceList;
1194 if(!RtlCompareUnicodeString(&OrphanAdapter->RegistryPath, Miniport->RegistryPath, TRUE))
1196 OrphanAdapter = (PORPHAN_ADAPTER)OrphanAdapter->ListEntry.Flink;
1200 NDIS_DbgPrint(MAX_TRACE, ("Found an orphan adapter for RegistryPath %wZ\n", Miniport->RegistryPath));
1202 /* there is an orphan adapter for us */
1203 Adapter->SlotNumber = OrphanAdapter->SlotNumber;
1204 Adapter->BusNumber = OrphanAdapter->BusNumber;
1205 Adapter->BusType = OrphanAdapter->BusType;
1207 Status = HalAssignSlotResources(Miniport->RegistryPath, 0, Miniport->DriverObject,
1208 Adapter->NdisMiniportBlock.DeviceObject, Adapter->BusType, Adapter->BusNumber,
1209 Adapter->SlotNumber, &ResourceList);
1211 if(!NT_SUCCESS(Status))
1213 NDIS_DbgPrint(MIN_TRACE, ("HalAssignSlotResources broke: 0x%x\n", Status));
1215 __asm__ ("int $3\n");
1217 /* i guess we should just give up on this adapter */
1221 /* go through the returned resource list and populate the Adapter */
1222 for(i = 0; i<ResourceList->Count; i++)
1226 PCM_FULL_RESOURCE_DESCRIPTOR ResourceDescriptor = &ResourceList->List[i];
1228 for(j=0; j<ResourceDescriptor->PartialResourceList.Count; j++)
1230 PCM_PARTIAL_RESOURCE_DESCRIPTOR PartialResourceDescriptor =
1231 &ResourceDescriptor->PartialResourceList.PartialDescriptors[i];
1233 switch(PartialResourceDescriptor->Type)
1235 case CmResourceTypeInterrupt:
1236 Adapter->Irql = PartialResourceDescriptor->u.Interrupt.Level;
1237 Adapter->Vector = PartialResourceDescriptor->u.Interrupt.Vector;
1238 Adapter->Affinity = PartialResourceDescriptor->u.Interrupt.Affinity;
1241 case CmResourceTypePort:
1242 Adapter->BaseIoAddress = PartialResourceDescriptor->u.Port.Start;
1245 case CmResourceTypeMemory:
1246 Adapter->BaseMemoryAddress = PartialResourceDescriptor->u.Memory.Start;
1249 case CmResourceTypeDma:
1250 Adapter->DmaPort = PartialResourceDescriptor->u.Dma.Port;
1251 Adapter->DmaChannel = PartialResourceDescriptor->u.Dma.Channel;
1254 case CmResourceTypeDeviceSpecific:
1261 /* remove the adapter from the list */
1262 TempAdapter = (PORPHAN_ADAPTER)OrphanAdapter->ListEntry.Flink;
1263 RemoveEntryList(&OrphanAdapter->ListEntry);
1264 OrphanAdapter = TempAdapter;
1266 KeReleaseSpinLock(&OrphanAdapterListLock, OldIrql);
1268 /* includes room for a 0-term */
1269 RegKeyPath = ExAllocatePool(PagedPool, (wcslen(SERVICES_ROOT) + wcslen(DeviceNameStr) + 1) * sizeof(WCHAR));
1272 NDIS_DbgPrint(MIN_TRACE,("Insufficient resources\n"));
1273 ExFreePool(Adapter);
1277 wcscpy(RegKeyPath, SERVICES_ROOT);
1278 wcscat(RegKeyPath, DeviceNameStr);
1279 RegKeyPath[wcslen(SERVICES_ROOT) + wcslen(DeviceNameStr)] = 0;
1281 RtlInitUnicodeString(&RegKeyPathU, RegKeyPath);
1282 InitializeObjectAttributes(&RegKeyAttributes, &RegKeyPathU, OBJ_CASE_INSENSITIVE, NULL, NULL);
1284 Status = ZwOpenKey(&RegKeyHandle, KEY_ALL_ACCESS, &RegKeyAttributes);
1285 if(Status != STATUS_SUCCESS)
1287 NDIS_DbgPrint(MIN_TRACE,("failed to open adapter-specific reg key %ws\n", RegKeyPath));
1288 ExFreePool(Adapter);
1292 NDIS_DbgPrint(MAX_TRACE, ("opened device reg key: %wZ\n", &RegKeyPathU));
1294 KeInitializeSpinLock(&Adapter->NdisMiniportBlock.Lock);
1295 InitializeListHead(&Adapter->ProtocolListHead);
1296 Adapter->RefCount = 1;
1297 Adapter->Miniport = Miniport;
1299 /* Set handlers (some NDIS macros require these) */
1301 Adapter->NdisMiniportBlock.EthRxCompleteHandler = MiniEthReceiveComplete;
1302 Adapter->NdisMiniportBlock.EthRxIndicateHandler = MiniEthReceiveIndication;
1303 Adapter->NdisMiniportBlock.SendCompleteHandler = MiniSendComplete;
1304 Adapter->NdisMiniportBlock.SendResourcesHandler = MiniSendResourcesAvailable;
1305 Adapter->NdisMiniportBlock.ResetCompleteHandler = MiniResetComplete;
1306 Adapter->NdisMiniportBlock.TDCompleteHandler = MiniTransferDataComplete;
1307 Adapter->NdisMiniportBlock.PacketIndicateHandler= MiniIndicateReceivePacket;
1309 KeInitializeDpc(&Adapter->MiniportDpc, MiniportDpc, (PVOID)Adapter);
1311 /* Put adapter in adapter list for this miniport */
1312 ExInterlockedInsertTailList(&Miniport->AdapterListHead, &Adapter->MiniportListEntry, &Miniport->Lock);
1314 /* Put adapter in global adapter list */
1315 ExInterlockedInsertTailList(&AdapterListHead, &Adapter->ListEntry, &AdapterListLock);
1317 /* Call MiniportInitialize */
1318 NDIS_DbgPrint(MID_TRACE, ("calling MiniportInitialize\n"));
1319 NdisStatus = (*Miniport->Chars.InitializeHandler)( &OpenErrorStatus, &SelectedMediumIndex, &MediaArray[0],
1320 MEDIA_ARRAY_SIZE, Adapter, RegKeyHandle);
1322 ZwClose(RegKeyHandle);
1324 if ((NdisStatus == NDIS_STATUS_SUCCESS) && (SelectedMediumIndex < MEDIA_ARRAY_SIZE))
1326 NDIS_DbgPrint(MID_TRACE,("successful return from MiniportInitialize\n"));
1328 Adapter->NdisMiniportBlock.MediaType = MediaArray[SelectedMediumIndex];
1330 switch (Adapter->NdisMiniportBlock.MediaType)
1332 case NdisMedium802_3:
1333 Adapter->MediumHeaderSize = 14; /* XXX figure out what to do about LLC */
1334 AddressOID = OID_802_3_CURRENT_ADDRESS;
1335 Adapter->AddressLength = ETH_LENGTH_OF_ADDRESS;
1337 Adapter->NdisMiniportBlock.FilterDbs.u.EthDB = ExAllocatePool(NonPagedPool, sizeof(ETH_FILTER));
1338 if (Adapter->NdisMiniportBlock.FilterDbs.u.EthDB)
1340 RtlZeroMemory(Adapter->NdisMiniportBlock.FilterDbs.u.EthDB, sizeof(ETH_FILTER));
1341 Adapter->NdisMiniportBlock.FilterDbs.u.EthDB->Miniport = (PNDIS_MINIPORT_BLOCK)Adapter;
1349 /* FIXME: Support other types of media */
1350 ExFreePool(Adapter);
1355 NdisStatus = DoQueries(Adapter, AddressOID);
1358 if ((MemError) || (NdisStatus != NDIS_STATUS_SUCCESS) || (SelectedMediumIndex >= MEDIA_ARRAY_SIZE))
1360 NDIS_DbgPrint(MAX_TRACE, ("return from MiniportInitialize: NdisStatus 0x%x, SelectedMediumIndex 0x%x\n",
1361 NdisStatus, SelectedMediumIndex));
1363 /* Remove adapter from adapter list for this miniport */
1364 KeAcquireSpinLock(&Miniport->Lock, &OldIrql);
1365 RemoveEntryList(&Adapter->MiniportListEntry);
1366 KeReleaseSpinLock(&Miniport->Lock, OldIrql);
1368 /* Remove adapter from global adapter list */
1369 KeAcquireSpinLock(&AdapterListLock, &OldIrql);
1370 RemoveEntryList(&Adapter->ListEntry);
1371 KeReleaseSpinLock(&AdapterListLock, OldIrql);
1373 if (Adapter->LookaheadBuffer)
1374 ExFreePool(Adapter->LookaheadBuffer);
1376 IoDeleteDevice(Adapter->NdisMiniportBlock.DeviceObject);
1377 ExFreePool(Adapter);
1378 NDIS_DbgPrint(MIN_TRACE, ("MiniportInitialize() failed for an adapter.\n"));
1387 NdisMRegisterMiniport(
1388 IN NDIS_HANDLE NdisWrapperHandle,
1389 IN PNDIS_MINIPORT_CHARACTERISTICS MiniportCharacteristics,
1390 IN UINT CharacteristicsLength)
1392 * FUNCTION: Registers a miniport's MiniportXxx entry points with the NDIS library
1394 * NdisWrapperHandle = Pointer to handle returned by NdisMInitializeWrapper
1395 * MiniportCharacteristics = Pointer to a buffer with miniport characteristics
1396 * CharacteristicsLength = Number of bytes in characteristics buffer
1398 * Status of operation
1400 * - To create device objects for the miniport, the Route value under Linkage is
1401 * parsed. I don't know if this is the way Microsoft does it or not.
1403 * verify this algorithm by playing with nt
1408 PMINIPORT_DRIVER Miniport = GET_MINIPORT_DRIVER(NdisWrapperHandle);
1409 OBJECT_ATTRIBUTES DeviceKeyAttributes;
1410 OBJECT_ATTRIBUTES LinkageKeyAttributes;
1411 HANDLE DeviceKeyHandle;
1412 HANDLE LinkageKeyHandle;
1413 UNICODE_STRING RouteVal;
1414 UNICODE_STRING LinkageKeyName;
1415 KEY_VALUE_PARTIAL_INFORMATION *RouteData;
1416 ULONG RouteDataLength;
1417 UINT NextRouteOffset = 0;
1419 NDIS_DbgPrint(MAX_TRACE, ("Called.\n"));
1421 switch (MiniportCharacteristics->MajorNdisVersion) {
1423 MinSize = sizeof(NDIS30_MINIPORT_CHARACTERISTICS_S);
1427 MinSize = sizeof(NDIS40_MINIPORT_CHARACTERISTICS_S);
1431 MinSize = sizeof(NDIS50_MINIPORT_CHARACTERISTICS_S);
1435 NDIS_DbgPrint(DEBUG_MINIPORT, ("Bad miniport characteristics version.\n"));
1436 return NDIS_STATUS_BAD_VERSION;
1439 if (CharacteristicsLength < MinSize) {
1440 NDIS_DbgPrint(DEBUG_MINIPORT, ("Bad miniport characteristics.\n"));
1441 return NDIS_STATUS_BAD_CHARACTERISTICS;
1444 /* Check if mandatory MiniportXxx functions are specified */
1445 if ((!MiniportCharacteristics->HaltHandler) ||
1446 (!MiniportCharacteristics->InitializeHandler)||
1447 (!MiniportCharacteristics->QueryInformationHandler) ||
1448 (!MiniportCharacteristics->ResetHandler) ||
1449 (!MiniportCharacteristics->SetInformationHandler)) {
1450 NDIS_DbgPrint(DEBUG_MINIPORT, ("Bad miniport characteristics.\n"));
1451 return NDIS_STATUS_BAD_CHARACTERISTICS;
1454 if (MiniportCharacteristics->MajorNdisVersion == 0x03) {
1455 if (!MiniportCharacteristics->u1.SendHandler) {
1456 NDIS_DbgPrint(DEBUG_MINIPORT, ("Bad miniport characteristics.\n"));
1457 return NDIS_STATUS_BAD_CHARACTERISTICS;
1459 } else if (MiniportCharacteristics->MajorNdisVersion >= 0x04) {
1461 if ((!MiniportCharacteristics->u1.SendHandler) &&
1462 (!MiniportCharacteristics->SendPacketsHandler)) {
1463 NDIS_DbgPrint(DEBUG_MINIPORT, ("Bad miniport characteristics.\n"));
1464 return NDIS_STATUS_BAD_CHARACTERISTICS;
1468 /* TODO: verify NDIS5 and NDIS5.1 */
1470 RtlCopyMemory(&Miniport->Chars, MiniportCharacteristics, MinSize);
1473 * extract the list of bound adapters from the registry's Route value
1474 * for this adapter. It seems under WinNT that the Route value in the
1475 * Linkage subkey holds an entry for each miniport instance we know about.
1476 * This surely isn't how Windows does it, but it's better than nothing.
1479 /* Read the miniport config from the registry */
1480 InitializeObjectAttributes(&DeviceKeyAttributes, Miniport->RegistryPath, OBJ_CASE_INSENSITIVE, NULL, NULL);
1482 Status = ZwOpenKey(&DeviceKeyHandle, KEY_READ, &DeviceKeyAttributes);
1483 if(!NT_SUCCESS(Status))
1485 NDIS_DbgPrint(MIN_TRACE,("Failed to open driver key: 0x%x\n", Status));
1486 return NDIS_STATUS_FAILURE;
1489 RtlInitUnicodeString(&LinkageKeyName, L"Linkage");
1490 InitializeObjectAttributes(&LinkageKeyAttributes, &LinkageKeyName, OBJ_CASE_INSENSITIVE, DeviceKeyHandle, NULL);
1492 Status = ZwOpenKey(&LinkageKeyHandle, KEY_READ, &LinkageKeyAttributes);
1493 if(!NT_SUCCESS(Status))
1495 NDIS_DbgPrint(MIN_TRACE,("Failed to open Linkage key: 0x%x\n", Status));
1496 ZwClose(DeviceKeyHandle);
1497 return NDIS_STATUS_FAILURE;
1500 RouteData = ExAllocatePool(PagedPool, ROUTE_DATA_SIZE);
1503 NDIS_DbgPrint(MIN_TRACE,("Insufficient resources\n"));
1504 ZwClose(LinkageKeyHandle);
1505 ZwClose(DeviceKeyHandle);
1506 return NDIS_STATUS_RESOURCES;
1509 RtlInitUnicodeString(&RouteVal, L"Route");
1511 Status = ZwQueryValueKey(LinkageKeyHandle, &RouteVal, KeyValuePartialInformation, RouteData, ROUTE_DATA_SIZE, &RouteDataLength);
1512 if(!NT_SUCCESS(Status))
1514 NDIS_DbgPrint(MIN_TRACE,("Failed to query Route value\n"));
1515 ZwClose(LinkageKeyHandle);
1516 ZwClose(DeviceKeyHandle);
1517 ExFreePool(RouteData);
1518 return NDIS_STATUS_FAILURE;
1521 ZwClose(LinkageKeyHandle);
1522 ZwClose(DeviceKeyHandle);
1524 /* route is a REG_MULTI_SZ with each nic object created by NDI - create an adapter for each */
1525 while(*(RouteData->Data + NextRouteOffset))
1527 NDIS_DbgPrint(MID_TRACE, ("Starting adapter %ws\n", (WCHAR *)(RouteData->Data + NextRouteOffset)));
1529 NdisIStartAdapter((WCHAR *)(RouteData->Data + NextRouteOffset),
1530 wcslen((WCHAR *)(RouteData->Data + NextRouteOffset)), Miniport);
1532 NextRouteOffset += wcslen((WCHAR *)(RouteData->Data + NextRouteOffset));
1535 ExFreePool(RouteData);
1536 return NDIS_STATUS_SUCCESS;
1546 IN NDIS_HANDLE MiniportAdapterHandle,
1547 IN NDIS_STATUS Status,
1548 IN BOOLEAN AddressingReset)
1550 MiniResetComplete(MiniportAdapterHandle,
1562 IN NDIS_HANDLE MiniportAdapterHandle,
1563 IN PNDIS_PACKET Packet,
1564 IN NDIS_STATUS Status)
1566 * FUNCTION: Forwards a message to the initiating protocol saying
1567 * that a packet was handled
1569 * NdisAdapterHandle = Handle input to MiniportInitialize
1570 * Packet = Pointer to NDIS packet that was sent
1571 * Status = Status of send operation
1574 MiniSendComplete(MiniportAdapterHandle,
1585 NdisMSendResourcesAvailable(
1586 IN NDIS_HANDLE MiniportAdapterHandle)
1588 MiniSendResourcesAvailable(MiniportAdapterHandle);
1597 NdisMTransferDataComplete(
1598 IN NDIS_HANDLE MiniportAdapterHandle,
1599 IN PNDIS_PACKET Packet,
1600 IN NDIS_STATUS Status,
1601 IN UINT BytesTransferred)
1603 MiniTransferDataComplete(MiniportAdapterHandle,
1615 NdisMSetInformationComplete(
1616 IN NDIS_HANDLE MiniportAdapterHandle,
1617 IN NDIS_STATUS Status)
1619 PLOGICAL_ADAPTER Adapter = GET_LOGICAL_ADAPTER(MiniportAdapterHandle);
1620 PADAPTER_BINDING AdapterBinding = (PADAPTER_BINDING)Adapter->MiniportAdapterBinding;
1622 NDIS_DbgPrint(MAX_TRACE, ("Called.\n"));
1624 (*AdapterBinding->ProtocolBinding->Chars.RequestCompleteHandler)(
1625 AdapterBinding->NdisOpenBlock.ProtocolBindingContext,
1626 Adapter->NdisMiniportBlock.MediaRequest,
1637 IN NDIS_HANDLE MiniportAdapterHandle,
1638 IN NDIS_HANDLE MiniportAdapterContext,
1639 IN BOOLEAN BusMaster,
1640 IN NDIS_INTERFACE_TYPE AdapterType)
1642 * FUNCTION: Informs the NDIS library of significant features of the caller's NIC
1644 * MiniportAdapterHandle = Handle input to MiniportInitialize
1645 * MiniportAdapterContext = Pointer to context information
1646 * BusMaster = Specifies TRUE if the caller's NIC is a busmaster DMA device
1647 * AdapterType = Specifies the I/O bus interface of the caller's NIC
1650 PLOGICAL_ADAPTER Adapter = GET_LOGICAL_ADAPTER(MiniportAdapterHandle);
1652 NDIS_DbgPrint(MAX_TRACE, ("Called.\n"));
1654 Adapter->NdisMiniportBlock.MiniportAdapterContext = MiniportAdapterContext;
1655 Adapter->Attributes = BusMaster? NDIS_ATTRIBUTE_BUS_MASTER : 0;
1656 Adapter->NdisMiniportBlock.AdapterType = AdapterType;
1657 Adapter->AttributesSet = TRUE;
1666 NdisMSetAttributesEx(
1667 IN NDIS_HANDLE MiniportAdapterHandle,
1668 IN NDIS_HANDLE MiniportAdapterContext,
1669 IN UINT CheckForHangTimeInSeconds OPTIONAL,
1670 IN ULONG AttributeFlags,
1671 IN NDIS_INTERFACE_TYPE AdapterType)
1673 * FUNCTION: Informs the NDIS library of significant features of the caller's NIC
1675 * MiniportAdapterHandle = Handle input to MiniportInitialize
1676 * MiniportAdapterContext = Pointer to context information
1677 * CheckForHangTimeInSeconds = Specifies interval in seconds at which
1678 * MiniportCheckForHang should be called
1679 * AttributeFlags = Bitmask that indicates specific attributes
1680 * AdapterType = Specifies the I/O bus interface of the caller's NIC
1683 // Currently just like NdisMSetAttributesEx
1684 // TODO: Take CheckForHandTimeInSeconds into account!
1685 PLOGICAL_ADAPTER Adapter = GET_LOGICAL_ADAPTER(MiniportAdapterHandle);
1687 NDIS_DbgPrint(MAX_TRACE, ("Called.\n"));
1688 NDIS_DbgPrint(MAX_TRACE, ("NdisMSetAttributesEx() is partly-implemented.\n"));
1690 Adapter->NdisMiniportBlock.MiniportAdapterContext = MiniportAdapterContext;
1692 /* don't know why this is here - anybody? */
1693 Adapter->Attributes = AttributeFlags & NDIS_ATTRIBUTE_BUS_MASTER;
1694 Adapter->NdisMiniportBlock.AdapterType = AdapterType;
1695 Adapter->AttributesSet = TRUE;
1697 if(AttributeFlags & NDIS_ATTRIBUTE_DESERIALIZE)
1699 NDIS_DbgPrint(MIN_TRACE, ("Deserialized miniport - UNIMPLEMENTED\n"));
1701 __asm__("int $3\n");
1713 IN ULONG MicrosecondsToSleep)
1724 NdisMSynchronizeWithInterrupt(
1725 IN PNDIS_MINIPORT_INTERRUPT Interrupt,
1726 IN PVOID SynchronizeFunction,
1727 IN PVOID SynchronizeContext)
1741 IN NDIS_HANDLE LogHandle,
1743 IN UINT LogBufferSize)
1747 return NDIS_STATUS_FAILURE;
1756 NdisTerminateWrapper(
1757 IN NDIS_HANDLE NdisWrapperHandle,
1758 IN PVOID SystemSpecific)
1760 * FUNCTION: Releases resources allocated by a call to NdisInitializeWrapper
1762 * NdisWrapperHandle = Handle returned by NdisInitializeWrapper (MINIPORT_DRIVER)
1763 * SystemSpecific = Always NULL
1766 PMINIPORT_DRIVER Miniport = GET_MINIPORT_DRIVER(NdisWrapperHandle);
1768 NDIS_DbgPrint(MAX_TRACE, ("Called.\n"));
1770 ExFreePool(Miniport->RegistryPath->Buffer);
1771 ExFreePool(Miniport->RegistryPath);
1772 ExFreePool(Miniport);
1779 ULONG KeyInformationSize;
1780 KEY_BASIC_INFORMATION *KeyInformation;
1783 KeyInformation = ExAllocatePool(PagedPool, 1024);
1784 ASSERT(KeyInformation);
1786 RtlInitUnicodeString(&LinkageKeyName, L"\\Registry\\Machine\\System\\CurrentControlSet\\Services\\NE2000");
1787 InitializeObjectAttributes(&LinkageKeyAttributes, &LinkageKeyName, OBJ_CASE_INSENSITIVE|OBJ_KERNEL_HANDLE, NULL, NULL);
1789 Status = ZwOpenKey(&LinkageKeyHandle, KEY_READ, &LinkageKeyAttributes);
1790 if(!NT_SUCCESS(Status))
1792 DbgPrint("ndis!NdisMRegisterMiniport: Failed to open Linkage key: 0x%x\n", Status);
1799 Status = ZwEnumerateKey(LinkageKeyHandle, i, KeyBasicInformation, KeyInformation, 1024, &KeyInformationSize);
1800 if(!NT_SUCCESS(Status))
1802 DbgPrint("ndis!NdisMRegisterMiniport: Failed to enumerate: 0x%x\n", Status);
1806 KeyInformation->Name[KeyInformation->NameLength/sizeof(WCHAR)] = 0;
1807 DbgPrint("ndis!NdisMRegisterMiniport: enumerated key %ws\n", KeyInformation->Name);
1810 ExFreePool(KeyInformation);