Get rid of NdisWorkItemHalt.
[reactos.git] / reactos / drivers / net / ndis / ndis / miniport.c
index c39aafa..a46668c 100644 (file)
  *   20 Aug 2003 vizzini - DMA support
  *   3  Oct 2003 vizzini - SendPackets support
  */
-#include <roscfg.h>
-#include <miniport.h>
-#include <protocol.h>
+
+#include "ndissys.h"
+#include "efilter.h"
 
 #ifdef DBG
 #include <buffer.h>
 #endif /* DBG */
 
+#undef NdisMSendComplete
+VOID
+EXPORT
+NdisMSendComplete(
+    IN  NDIS_HANDLE     MiniportAdapterHandle,
+    IN  PNDIS_PACKET    Packet,
+    IN  NDIS_STATUS     Status);
+
 /* Root of the scm database */
 #define SERVICES_ROOT L"\\Registry\\Machine\\System\\CurrentControlSet\\Services\\"
 
-/* prefix for device object registration */
-#define DEVICE_ROOT L"\\Device\\"
-
 /*
  * Define to 1 to get a debugger breakpoint at the end of NdisInitializeWrapper
  * for each new miniport starting up
  */
 #define BREAK_ON_MINIPORT_INIT 0
 
-/* 
+/*
  * This has to be big enough to hold the results of querying the Route value
  * from the Linkage key.  Please re-code me to determine this dynamically.
  */
@@ -39,7 +44,7 @@
 /* Number of media we know */
 #define MEDIA_ARRAY_SIZE    15
 
-static NDIS_MEDIUM MediaArray[MEDIA_ARRAY_SIZE] = 
+static NDIS_MEDIUM MediaArray[MEDIA_ARRAY_SIZE] =
 {
     NdisMedium802_3,
     NdisMedium802_5,
@@ -66,20 +71,14 @@ KSPIN_LOCK MiniportListLock;
 LIST_ENTRY AdapterListHead;
 KSPIN_LOCK AdapterListLock;
 
-/* global list and lock of orphan adapters waiting to be claimed by a miniport */
-LIST_ENTRY OrphanAdapterListHead;
-KSPIN_LOCK OrphanAdapterListLock;
-
-
 VOID
 MiniDisplayPacket(
     PNDIS_PACKET Packet)
 {
-//#ifdef DBG
-#if 0
+#ifdef DBG
     ULONG i, Length;
     UCHAR Buffer[64];
-    if ((DebugTraceLevel | DEBUG_PACKET) > 0) {
+    if ((DebugTraceLevel & DEBUG_PACKET) > 0) {
         Length = CopyPacketToBuffer(
             (PUCHAR)&Buffer,
             Packet,
@@ -107,7 +106,7 @@ MiniDisplayPacket2(
     UINT   LookaheadBufferSize)
 {
 #ifdef DBG
-    if ((DebugTraceLevel | DEBUG_PACKET) > 0) {
+    if ((DebugTraceLevel & DEBUG_PACKET) > 0) {
         ULONG i, Length;
         PUCHAR p;
 
@@ -117,8 +116,7 @@ MiniDisplayPacket2(
         for (i = 0; i < HeaderBufferSize; i++) {
             if (i % 16 == 0)
                 DbgPrint("\n%04X ", i);
-            DbgPrint("%02X ", *p);
-            *(ULONG_PTR*)p += 1;
+            DbgPrint("%02X ", *p++);
         }
 
         DbgPrint("\nFRAME:");
@@ -128,8 +126,7 @@ MiniDisplayPacket2(
         for (i = 0; i < Length; i++) {
             if (i % 16 == 0)
                 DbgPrint("\n%04X ", i);
-            DbgPrint("%02X ", *p);
-            *(ULONG_PTR*)p += 1;
+            DbgPrint("%02X ", *p++);
         }
 
         DbgPrint("\n*** RECEIVE PACKET STOP ***\n");
@@ -162,7 +159,7 @@ MiniIndicateData(
   /* KIRQL OldIrql; */
   PLIST_ENTRY CurrentEntry;
   PADAPTER_BINDING AdapterBinding;
-  
+
   NDIS_DbgPrint(DEBUG_MINIPORT, ("Called. Adapter (0x%X)  HeaderBuffer (0x%X)  "
       "HeaderBufferSize (0x%X)  LookaheadBuffer (0x%X)  LookaheadBufferSize (0x%X).\n",
       Adapter, HeaderBuffer, HeaderBufferSize, LookaheadBuffer, LookaheadBufferSize));
@@ -178,7 +175,7 @@ MiniIndicateData(
    * subsequently re-acquire the lock.
    *
    * I don't see how this does any good, as it would seem he's just
-   * trying to protect the packet list.  If someobdy else dequeues
+   * trying to protect the packet list.  If somebody else dequeues
    * a packet, we are in fact in bad shape, but we don't want to
    * necessarily call the receive handler at elevated irql either.
    *
@@ -194,12 +191,12 @@ MiniIndicateData(
       CurrentEntry = Adapter->ProtocolListHead.Flink;
       NDIS_DbgPrint(DEBUG_MINIPORT, ("CurrentEntry = %x\n", CurrentEntry));
 
-      if (CurrentEntry == &Adapter->ProtocolListHead) 
+      if (CurrentEntry == &Adapter->ProtocolListHead)
         {
           NDIS_DbgPrint(DEBUG_MINIPORT, ("WARNING: No upper protocol layer.\n"));
         }
 
-      while (CurrentEntry != &Adapter->ProtocolListHead) 
+      while (CurrentEntry != &Adapter->ProtocolListHead)
         {
           AdapterBinding = CONTAINING_RECORD(CurrentEntry, ADAPTER_BINDING, AdapterListEntry);
          NDIS_DbgPrint(DEBUG_MINIPORT, ("AdapterBinding = %x\n", AdapterBinding));
@@ -220,17 +217,17 @@ MiniIndicateData(
               break;
             }
 
-          if(!AdapterBinding->ProtocolBinding->Chars.u4.ReceiveHandler)
+          if(!AdapterBinding->ProtocolBinding->Chars.ReceiveHandler)
             {
-              NDIS_DbgPrint(MIN_TRACE, ("AdapterBinding->ProtocolBinding->Chars.u4.ReceiveHandler was null\n"));
+              NDIS_DbgPrint(MIN_TRACE, ("AdapterBinding->ProtocolBinding->Chars.ReceiveHandler was null\n"));
               break;
             }
 #endif
 
          NDIS_DbgPrint
-             (MID_TRACE, 
+             (MID_TRACE,
               ("XXX (%x) %x %x %x %x %x %x %x XXX\n",
-               *AdapterBinding->ProtocolBinding->Chars.u4.ReceiveHandler,
+               *AdapterBinding->ProtocolBinding->Chars.ReceiveHandler,
                AdapterBinding->NdisOpenBlock.ProtocolBindingContext,
                MacReceiveContext,
                HeaderBuffer,
@@ -240,7 +237,7 @@ MiniIndicateData(
                PacketSize));
 
           /* call the receive handler */
-          (*AdapterBinding->ProtocolBinding->Chars.u4.ReceiveHandler)(
+          (*AdapterBinding->ProtocolBinding->Chars.ReceiveHandler)(
               AdapterBinding->NdisOpenBlock.ProtocolBindingContext,
               MacReceiveContext,
               HeaderBuffer,
@@ -261,7 +258,7 @@ MiniIndicateData(
 }
 
 \f
-VOID STDCALL
+VOID NTAPI
 MiniIndicateReceivePacket(
     IN  NDIS_HANDLE    Miniport,
     IN  PPNDIS_PACKET  PacketArray,
@@ -320,85 +317,7 @@ MiniIndicateReceivePacket(
 }
 
 \f
-VOID STDCALL
-MiniEthReceiveComplete(
-    IN  PETH_FILTER Filter)
-/*
- * FUNCTION: Receive indication complete function for Ethernet devices
- * ARGUMENTS:
- *     Filter = Pointer to Ethernet filter
- */
-{
-  KIRQL OldIrql;
-  PLIST_ENTRY CurrentEntry;
-  PLOGICAL_ADAPTER Adapter;
-  PADAPTER_BINDING AdapterBinding;
-
-  NDIS_DbgPrint(DEBUG_MINIPORT, ("Called.\n"));
-
-  if( !Filter ) return;
-
-  Adapter = (PLOGICAL_ADAPTER)Filter->Miniport;
-
-  NDIS_DbgPrint(MAX_TRACE, ("acquiring miniport block lock\n"));
-  KeAcquireSpinLock(&Adapter->NdisMiniportBlock.Lock, &OldIrql);
-    {
-      CurrentEntry = Adapter->ProtocolListHead.Flink;
-
-      while (CurrentEntry != &Adapter->ProtocolListHead) 
-        {
-          AdapterBinding = CONTAINING_RECORD(CurrentEntry, ADAPTER_BINDING, AdapterListEntry);
-
-          /* see comment in MiniIndicateData */
-          /* KeReleaseSpinLock(&Adapter->NdisMiniportBlock.Lock, OldIrql); */
-
-          (*AdapterBinding->ProtocolBinding->Chars.ReceiveCompleteHandler)(
-              AdapterBinding->NdisOpenBlock.ProtocolBindingContext);
-
-          /* see above */
-          /* KeAcquireSpinLock(&Adapter->NdisMiniportBlock.Lock, &OldIrql); */
-
-          CurrentEntry = CurrentEntry->Flink;
-        }
-    }
-  KeReleaseSpinLock(&Adapter->NdisMiniportBlock.Lock, OldIrql);
-}
-
-\f
-VOID STDCALL
-MiniEthReceiveIndication(
-    IN  NDIS_HANDLE MiniportAdapter,
-    IN  NDIS_HANDLE MacReceiveContext,
-    IN  PCHAR       Address,
-    IN  PVOID       HeaderBuffer,
-    IN  UINT        HeaderBufferSize,
-    IN  PVOID       LookaheadBuffer,
-    IN  UINT        LookaheadBufferSize,
-    IN  UINT        PacketSize)
-/*
- * FUNCTION: Receive indication function for Ethernet devices
- * ARGUMENTS:
- *     MiniportAdapter     = Miniport Adapter Handle (PLOGICAL_ADAPTER)
- *     MacReceiveContext   = MAC receive context handle
- *     Address             = Pointer to destination Ethernet address
- *     HeaderBuffer        = Pointer to Ethernet header buffer
- *     HeaderBufferSize    = Size of Ethernet header buffer
- *     LookaheadBuffer     = Pointer to lookahead buffer
- *     LookaheadBufferSize = Size of lookahead buffer
- *     PacketSize          = Total size of received packet
- */
-{
-    MiniIndicateData(MiniportAdapter,
-                    MacReceiveContext,
-                    HeaderBuffer,
-                    HeaderBufferSize,
-                    LookaheadBuffer,
-                    LookaheadBufferSize,
-                    PacketSize);
-}
-
-\f
-VOID STDCALL
+VOID NTAPI
 MiniResetComplete(
     IN  NDIS_HANDLE MiniportAdapterHandle,
     IN  NDIS_STATUS Status,
@@ -408,7 +327,24 @@ MiniResetComplete(
 }
 
 
-VOID STDCALL
+\f
+VOID NTAPI
+MiniRequestComplete(
+    IN PADAPTER_BINDING AdapterBinding,
+    IN PNDIS_REQUEST Request,
+    IN  NDIS_STATUS Status)
+{
+    NDIS_DbgPrint(DEBUG_MINIPORT, ("Called.\n"));
+
+    if( AdapterBinding->ProtocolBinding->Chars.RequestCompleteHandler ) {
+        (*AdapterBinding->ProtocolBinding->Chars.RequestCompleteHandler)(
+            AdapterBinding->NdisOpenBlock.ProtocolBindingContext,
+            Request,
+            Status);
+    }
+}
+
+VOID NTAPI
 MiniSendComplete(
     IN  NDIS_HANDLE     MiniportAdapterHandle,
     IN  PNDIS_PACKET    Packet,
@@ -428,14 +364,14 @@ MiniSendComplete(
 
     AdapterBinding = (PADAPTER_BINDING)Packet->Reserved[0];
 
-    (*AdapterBinding->ProtocolBinding->Chars.u2.SendCompleteHandler)(
+    (*AdapterBinding->ProtocolBinding->Chars.SendCompleteHandler)(
         AdapterBinding->NdisOpenBlock.ProtocolBindingContext,
         Packet,
         Status);
 }
 
 
-VOID STDCALL
+VOID NTAPI
 MiniSendResourcesAvailable(
     IN  NDIS_HANDLE MiniportAdapterHandle)
 {
@@ -443,23 +379,23 @@ MiniSendResourcesAvailable(
 }
 
 
-VOID STDCALL
+VOID NTAPI
 MiniTransferDataComplete(
     IN  NDIS_HANDLE     MiniportAdapterHandle,
     IN  PNDIS_PACKET    Packet,
     IN  NDIS_STATUS     Status,
     IN  UINT            BytesTransferred)
 {
-    PLOGICAL_ADAPTER Adapter        = (PLOGICAL_ADAPTER)MiniportAdapterHandle;
-    PADAPTER_BINDING AdapterBinding = Adapter->MiniportAdapterBinding;
+    PADAPTER_BINDING AdapterBinding;
 
     NDIS_DbgPrint(DEBUG_MINIPORT, ("Called.\n"));
 
-    (*AdapterBinding->ProtocolBinding->Chars.u3.TransferDataCompleteHandler)(
+    AdapterBinding = (PADAPTER_BINDING)Packet->Reserved[0];
+
+    (*AdapterBinding->ProtocolBinding->Chars.SendCompleteHandler)(
         AdapterBinding->NdisOpenBlock.ProtocolBindingContext,
         Packet,
-        Status,
-        BytesTransferred);
+        Status);
 }
 
 \f
@@ -468,7 +404,7 @@ MiniAdapterHasAddress(
     PLOGICAL_ADAPTER Adapter,
     PNDIS_PACKET Packet)
 /*
- * FUNCTION: Determines wether a packet has the same destination address as an adapter
+ * FUNCTION: Determines whether a packet has the same destination address as an adapter
  * ARGUMENTS:
  *     Adapter = Pointer to logical adapter object
  *     Packet  = Pointer to NDIS packet
@@ -500,7 +436,7 @@ MiniAdapterHasAddress(
 
   NdisQueryPacket(Packet, NULL, NULL, &NdisBuffer, NULL);
 
-  if (!NdisBuffer) 
+  if (!NdisBuffer)
     {
       NDIS_DbgPrint(MID_TRACE, ("Packet contains no buffers.\n"));
       return FALSE;
@@ -510,7 +446,7 @@ MiniAdapterHasAddress(
 
   /* FIXME: Should handle fragmented packets */
 
-  switch (Adapter->NdisMiniportBlock.MediaType) 
+  switch (Adapter->NdisMiniportBlock.MediaType)
     {
       case NdisMedium802_3:
         Length = ETH_LENGTH_OF_ADDRESS;
@@ -522,7 +458,7 @@ MiniAdapterHasAddress(
         return FALSE;
     }
 
-  if (BufferLength < Length) 
+  if (BufferLength < Length)
     {
         NDIS_DbgPrint(MID_TRACE, ("Buffer is too small.\n"));
         return FALSE;
@@ -571,21 +507,22 @@ MiniLocateDevice(
         {
           CurrentEntry = AdapterListHead.Flink;
 
-          while (CurrentEntry != &AdapterListHead) 
+          while (CurrentEntry != &AdapterListHead)
             {
               Adapter = CONTAINING_RECORD(CurrentEntry, LOGICAL_ADAPTER, ListEntry);
 
               ASSERT(Adapter);
 
-              NDIS_DbgPrint(DEBUG_MINIPORT, ("AdapterName = %wZ\n", &AdapterName));
-              NDIS_DbgPrint(DEBUG_MINIPORT, ("DeviceName = %wZ\n", &Adapter->DeviceName));
+              NDIS_DbgPrint(DEBUG_MINIPORT, ("AdapterName = %wZ\n", AdapterName));
+              NDIS_DbgPrint(DEBUG_MINIPORT, ("DeviceName = %wZ\n", &Adapter->NdisMiniportBlock.MiniportName));
 
-              if (RtlCompareUnicodeString(AdapterName, &Adapter->DeviceName, TRUE) == 0) 
+              if (RtlCompareUnicodeString(AdapterName, &Adapter->NdisMiniportBlock.MiniportName, TRUE) == 0)
                 {
                   ReferenceObject(Adapter);
                   break;
                 }
 
+              Adapter = NULL;
               CurrentEntry = CurrentEntry->Flink;
             }
         } while (0);
@@ -594,7 +531,7 @@ MiniLocateDevice(
 
   if(Adapter)
     {
-      NDIS_DbgPrint(DEBUG_MINIPORT, ("Leaving. Adapter found at 0x%x\n", Adapter)); 
+      NDIS_DbgPrint(DEBUG_MINIPORT, ("Leaving. Adapter found at 0x%x\n", Adapter));
     }
   else
     {
@@ -632,12 +569,12 @@ MiniQueryInformation(
 
   NDIS_DbgPrint(DEBUG_MINIPORT, ("Called.\n"));
 
-  if (Adapter->QueryBufferLength == 0) 
+  if (Adapter->QueryBufferLength == 0)
     {
       /* XXX is 32 the right number? */
       Adapter->QueryBuffer = ExAllocatePool(NonPagedPool, (Size == 0)? 32 : Size);
 
-      if (!Adapter->QueryBuffer) 
+      if (!Adapter->QueryBuffer)
         {
           NDIS_DbgPrint(MIN_TRACE, ("Insufficient resources.\n"));
           return NDIS_STATUS_RESOURCES;
@@ -660,20 +597,20 @@ MiniQueryInformation(
       &BytesNeeded);
 
   /* XXX is status_pending part of success macro? */
-  if ((NT_SUCCESS(NdisStatus)) || (NdisStatus == NDIS_STATUS_PENDING)) 
+  if ((NT_SUCCESS(NdisStatus)) || (NdisStatus == NDIS_STATUS_PENDING))
     {
       NDIS_DbgPrint(DEBUG_MINIPORT, ("Miniport returned status (0x%X).\n", NdisStatus));
       return NdisStatus;
     }
 
-  if (NdisStatus == NDIS_STATUS_INVALID_LENGTH) 
+  if (NdisStatus == NDIS_STATUS_INVALID_LENGTH)
     {
       ExFreePool(Adapter->QueryBuffer);
 
       Adapter->QueryBufferLength += BytesNeeded;
       Adapter->QueryBuffer = ExAllocatePool(NonPagedPool, Adapter->QueryBufferLength);
 
-      if (!Adapter->QueryBuffer) 
+      if (!Adapter->QueryBuffer)
         {
           NDIS_DbgPrint(MIN_TRACE, ("Insufficient resources.\n"));
           return NDIS_STATUS_RESOURCES;
@@ -683,7 +620,7 @@ MiniQueryInformation(
           Adapter->NdisMiniportBlock.MiniportAdapterContext,
           Oid,
           Adapter->QueryBuffer,
-          Size,
+          Adapter->QueryBufferLength,
           BytesWritten,
           &BytesNeeded);
     }
@@ -695,69 +632,66 @@ MiniQueryInformation(
 NDIS_STATUS
 FASTCALL
 MiniQueueWorkItem(
-    PLOGICAL_ADAPTER    Adapter,
+    PADAPTER_BINDING    AdapterBinding,
     NDIS_WORK_ITEM_TYPE WorkItemType,
-    PVOID               WorkItemContext,
-    NDIS_HANDLE         Initiator)
+    PVOID               WorkItemContext)
 /*
  * FUNCTION: Queues a work item for execution at a later time
  * ARGUMENTS:
  *     Adapter         = Pointer to the logical adapter object to queue work item on
  *     WorkItemType    = Type of work item to queue
  *     WorkItemContext = Pointer to context information for work item
- *     Initiator       = Pointer to ADAPTER_BINDING structure of initiating protocol
  * NOTES:
  *     Adapter lock must be held when called
  * RETURNS:
  *     Status of operation
  */
 {
-  PNDIS_MINIPORT_WORK_ITEM Item;
-
-  NDIS_DbgPrint(MAX_TRACE, ("Called.\n"));
-
-  ASSERT(Adapter);
-
-  if (Adapter->WorkQueueLevel < NDIS_MINIPORT_WORK_QUEUE_SIZE - 1) 
+    PINTERNAL_NDIS_MINIPORT_WORK_ITEM Item;
+    PLOGICAL_ADAPTER Adapter = AdapterBinding->Adapter;
+
+    NDIS_DbgPrint(MAX_TRACE, ("Called.\n"));
+    
+    ASSERT(Adapter);
+    ASSERT(KeGetCurrentIrql() >= DISPATCH_LEVEL);
+    
+#if 0
+    if (Adapter->WorkQueueLevel < NDIS_MINIPORT_WORK_QUEUE_SIZE - 1)
     {
-      Item = &Adapter->WorkQueue[Adapter->WorkQueueLevel];
-      Adapter->WorkQueueLevel++;
-    } 
-  else 
+        Item = &Adapter->WorkQueue[Adapter->WorkQueueLevel];
+        Adapter->WorkQueueLevel++;
+    }
+    else
+#endif
     {
-      Item = ExAllocatePool(NonPagedPool, sizeof(NDIS_MINIPORT_WORK_ITEM));
-      if (Item) 
-        {
-          /* Set flag so we know that the buffer should be freed when work item is dequeued */
-          Item->Allocated = TRUE;
-        } 
-      else 
+        Item = ExAllocatePool(NonPagedPool, sizeof(INTERNAL_NDIS_MINIPORT_WORK_ITEM));
+        if (Item == NULL)
         {
-          NDIS_DbgPrint(MIN_TRACE, ("Insufficient resources.\n"));
-          return NDIS_STATUS_RESOURCES;
+            NDIS_DbgPrint(MIN_TRACE, ("Insufficient resources.\n"));
+            return NDIS_STATUS_RESOURCES;
         }
     }
-
-  Item->WorkItemType    = WorkItemType;
-  Item->WorkItemContext = WorkItemContext;
-  Item->Initiator       = Initiator;
-
-  /* safe due to adapter lock held */
-  Item->Link.Next = NULL;
-  if (!Adapter->WorkQueueHead) 
+    
+    Item->AdapterBinding = AdapterBinding;
+    Item->RealWorkItem.WorkItemType    = WorkItemType;
+    Item->RealWorkItem.WorkItemContext = WorkItemContext;
+    
+    /* safe due to adapter lock held */
+    Item->Link.Next = NULL;
+    if (!Adapter->WorkQueueHead)
     {
-      Adapter->WorkQueueHead = Item;
-      Adapter->WorkQueueTail = Item;
-    } 
-  else 
+        Adapter->WorkQueueHead = Item;
+        Adapter->WorkQueueTail = Item;
+    }
+    else
     {
-      Adapter->WorkQueueTail->Link.Next = (PSINGLE_LIST_ENTRY)Item;
-      Adapter->WorkQueueTail = Item;
+        Adapter->WorkQueueTail->Link.Next = (PSINGLE_LIST_ENTRY)Item;
+        Adapter->WorkQueueTail = Item;
     }
-
-  KeInsertQueueDpc(&Adapter->MiniportDpc, NULL, NULL);
-
-  return NDIS_STATUS_SUCCESS;
+    
+    KeInsertQueueDpc(&Adapter->MiniportDpc, NULL, NULL);
+    
+    return NDIS_STATUS_SUCCESS;
 }
 
 \f
@@ -765,82 +699,71 @@ NDIS_STATUS
 FASTCALL
 MiniDequeueWorkItem(
     PLOGICAL_ADAPTER    Adapter,
+    PADAPTER_BINDING    *AdapterBinding,
     NDIS_WORK_ITEM_TYPE *WorkItemType,
-    PVOID               *WorkItemContext,
-    NDIS_HANDLE         *Initiator)
+    PVOID               *WorkItemContext)
 /*
  * FUNCTION: Dequeues a work item from the work queue of a logical adapter
  * ARGUMENTS:
  *     Adapter         = Pointer to the logical adapter object to dequeue work item from
+ *     AdapterBinding  = Address of buffer for adapter binding for this request
  *     WorkItemType    = Address of buffer for work item type
  *     WorkItemContext = Address of buffer for pointer to context information
- *     Initiator       = Address of buffer for initiator of the work (ADAPTER_BINDING)
  * NOTES:
  *     Adapter lock must be held when called
  * RETURNS:
  *     Status of operation
  */
 {
-  PNDIS_MINIPORT_WORK_ITEM Item;
-
-  NDIS_DbgPrint(MAX_TRACE, ("Called.\n"));
-
-  Item = Adapter->WorkQueueHead;
-
-  if (Item) 
+    PINTERNAL_NDIS_MINIPORT_WORK_ITEM Item;
+    
+    NDIS_DbgPrint(MAX_TRACE, ("Called.\n"));
+    
+    Item = Adapter->WorkQueueHead;
+    
+    if (Item)
     {
-      /* safe due to adapter lock held */
-      Adapter->WorkQueueHead = (PNDIS_MINIPORT_WORK_ITEM)Item->Link.Next;
-
-      if (Item == Adapter->WorkQueueTail)
-        Adapter->WorkQueueTail = NULL;
-
-      *WorkItemType    = Item->WorkItemType;
-      *WorkItemContext = Item->WorkItemContext;
-      *Initiator       = Item->Initiator;
-
-      if (Item->Allocated) 
-        {
-            ExFreePool(Item);
-        } 
-      else 
-        {
-          Adapter->WorkQueueLevel--;
-#ifdef DBG
-          if (Adapter->WorkQueueLevel < 0) 
-            {
-              NDIS_DbgPrint(MIN_TRACE, ("Adapter->WorkQueueLevel is < 0 (should be >= 0).\n"));
-            }
-#endif
-        }
-
-      return NDIS_STATUS_SUCCESS;
+        /* safe due to adapter lock held */
+        Adapter->WorkQueueHead = (PINTERNAL_NDIS_MINIPORT_WORK_ITEM)Item->Link.Next;
+        
+        if (Item == Adapter->WorkQueueTail)
+            Adapter->WorkQueueTail = NULL;
+        
+        *AdapterBinding  = Item->AdapterBinding;
+        *WorkItemType    = Item->RealWorkItem.WorkItemType;
+        *WorkItemContext = Item->RealWorkItem.WorkItemContext;
+        
+        ExFreePool(Item);
+        
+        return NDIS_STATUS_SUCCESS;
     }
-
-  return NDIS_STATUS_FAILURE;
+    
+    return NDIS_STATUS_FAILURE;
 }
 
 \f
 NDIS_STATUS
 MiniDoRequest(
-    PLOGICAL_ADAPTER Adapter,
+    PADAPTER_BINDING AdapterBinding,
     PNDIS_REQUEST NdisRequest)
 /*
  * FUNCTION: Sends a request to a miniport
  * ARGUMENTS:
- *     Adapter     = Pointer to logical adapter object
- *     NdisRequest = Pointer to NDIS request structure describing request
+ *     AdapterBinding = Pointer to binding used in the request
+ *     NdisRequest    = Pointer to NDIS request structure describing request
  * RETURNS:
  *     Status of operation
  */
 {
-  NDIS_DbgPrint(DEBUG_MINIPORT, ("Called.\n"));
-
-  Adapter->NdisMiniportBlock.MediaRequest = NdisRequest;
+    PLOGICAL_ADAPTER Adapter = AdapterBinding->Adapter;
 
-  switch (NdisRequest->RequestType) 
+    NDIS_DbgPrint(DEBUG_MINIPORT, ("Called.\n"));
+    
+    Adapter->NdisMiniportBlock.MediaRequest = NdisRequest;
+    
+    switch (NdisRequest->RequestType)
     {
-      case NdisRequestQueryInformation:
+    case NdisRequestQueryInformation:
         return (*Adapter->Miniport->Chars.QueryInformationHandler)(
             Adapter->NdisMiniportBlock.MiniportAdapterContext,
             NdisRequest->DATA.QUERY_INFORMATION.Oid,
@@ -849,8 +772,8 @@ MiniDoRequest(
             (PULONG)&NdisRequest->DATA.QUERY_INFORMATION.BytesWritten,
             (PULONG)&NdisRequest->DATA.QUERY_INFORMATION.BytesNeeded);
         break;
-
-      case NdisRequestSetInformation:
+        
+    case NdisRequestSetInformation:
         return (*Adapter->Miniport->Chars.SetInformationHandler)(
             Adapter->NdisMiniportBlock.MiniportAdapterContext,
             NdisRequest->DATA.SET_INFORMATION.Oid,
@@ -859,14 +782,32 @@ MiniDoRequest(
             (PULONG)&NdisRequest->DATA.SET_INFORMATION.BytesRead,
             (PULONG)&NdisRequest->DATA.SET_INFORMATION.BytesNeeded);
         break;
-
-      default:
+        
+    default:
         return NDIS_STATUS_FAILURE;
     }
 }
 
 \f
-VOID STDCALL MiniportDpc(
+/*
+ * @implemented
+ */
+#undef NdisMQueryInformationComplete
+VOID
+EXPORT
+NdisMQueryInformationComplete(
+    IN  NDIS_HANDLE MiniportAdapterHandle,
+    IN  NDIS_STATUS Status)
+{
+    PNDIS_MINIPORT_BLOCK MiniportBlock =
+       (PNDIS_MINIPORT_BLOCK)MiniportAdapterHandle;
+    ASSERT(MiniportBlock);
+    if( MiniportBlock->QueryCompleteHandler )
+       (MiniportBlock->QueryCompleteHandler)(MiniportAdapterHandle, Status);
+}
+
+\f
+VOID NTAPI MiniportDpc(
     IN PKDPC Dpc,
     IN PVOID DeferredContext,
     IN PVOID SystemArgument1,
@@ -888,14 +829,13 @@ VOID STDCALL MiniportDpc(
 
   NDIS_DbgPrint(DEBUG_MINIPORT, ("Called.\n"));
 
-  /* XXX is adapter lock held here?  should be... */
-  NdisStatus = MiniDequeueWorkItem(Adapter, &WorkItemType, &WorkItemContext, (PNDIS_HANDLE)&AdapterBinding);
+  NdisStatus = 
+      MiniDequeueWorkItem
+      (Adapter, &AdapterBinding, &WorkItemType, &WorkItemContext);
 
-  if (NdisStatus == NDIS_STATUS_SUCCESS) 
+  if (NdisStatus == NDIS_STATUS_SUCCESS)
     {
-      Adapter->MiniportAdapterBinding = AdapterBinding;
-
-      switch (WorkItemType) 
+      switch (WorkItemType)
         {
           case NdisWorkItemSend:
             /*
@@ -914,6 +854,8 @@ VOID STDCALL MiniportDpc(
                  */
                 (*Adapter->Miniport->Chars.SendPacketsHandler)(
                     Adapter->NdisMiniportBlock.MiniportAdapterContext, (PPNDIS_PACKET)&WorkItemContext, 1);
+               NdisStatus =
+                   NDIS_GET_PACKET_STATUS((PNDIS_PACKET)WorkItemContext);
 
                 NDIS_DbgPrint(MAX_TRACE, ("back from miniport's SendPackets handler\n"));
               }
@@ -921,15 +863,16 @@ VOID STDCALL MiniportDpc(
               {
                 NDIS_DbgPrint(MAX_TRACE, ("Calling miniport's Send handler\n"));
 
-                NdisStatus = (*Adapter->Miniport->Chars.u1.SendHandler)(
+                NdisStatus = (*Adapter->Miniport->Chars.SendHandler)(
                     Adapter->NdisMiniportBlock.MiniportAdapterContext, (PNDIS_PACKET)WorkItemContext, 0);
 
                 NDIS_DbgPrint(MAX_TRACE, ("back from miniport's Send handler\n"));
-
-                if (NdisStatus != NDIS_STATUS_PENDING) 
-                    MiniSendComplete((NDIS_HANDLE)Adapter, (PNDIS_PACKET)WorkItemContext, NdisStatus);
               }
-
+           if( NdisStatus != NDIS_STATUS_PENDING ) {
+               NdisMSendComplete
+                   ( Adapter, (PNDIS_PACKET)WorkItemContext, NdisStatus );
+               Adapter->MiniportBusy = FALSE;
+           }
             break;
 
           case NdisWorkItemSendLoopback:
@@ -950,26 +893,25 @@ VOID STDCALL MiniportDpc(
           case NdisWorkItemResetInProgress:
             break;
 
-          case NdisWorkItemHalt:
-            break;
-
           case NdisWorkItemMiniportCallback:
             break;
 
           case NdisWorkItemRequest:
-            NdisStatus = MiniDoRequest(Adapter, (PNDIS_REQUEST)WorkItemContext);
+            NdisStatus = MiniDoRequest(AdapterBinding, (PNDIS_REQUEST)WorkItemContext);
 
             if (NdisStatus == NDIS_STATUS_PENDING)
               break;
 
-            switch (((PNDIS_REQUEST)WorkItemContext)->RequestType) 
+            switch (((PNDIS_REQUEST)WorkItemContext)->RequestType)
               {
                 case NdisRequestQueryInformation:
-                  NdisMQueryInformationComplete((NDIS_HANDLE)Adapter, NdisStatus);
+                 NdisMQueryInformationComplete((NDIS_HANDLE)Adapter, NdisStatus);
+                  MiniRequestComplete( AdapterBinding, (PNDIS_REQUEST)WorkItemContext, NdisStatus );
                   break;
 
                 case NdisRequestSetInformation:
                   NdisMSetInformationComplete((NDIS_HANDLE)Adapter, NdisStatus);
+                  MiniRequestComplete( AdapterBinding, (PNDIS_REQUEST)WorkItemContext, NdisStatus );
                   break;
 
                 default:
@@ -1026,9 +968,10 @@ NdisMDeregisterAdapterShutdownHandler(
  * ARGUMENTS:  MiniportHandle:  Handle passed into MiniportInitialize
  */
 {
-  NDIS_DbgPrint(DEBUG_MINIPORT, ("Called.\n"));
   PLOGICAL_ADAPTER  Adapter = (PLOGICAL_ADAPTER)MiniportHandle;
 
+  NDIS_DbgPrint(DEBUG_MINIPORT, ("Called.\n"));
+
   if(Adapter->BugcheckContext->ShutdownHandler)
     KeDeregisterBugCheckCallback(Adapter->BugcheckContext->CallbackRecord);
 }
@@ -1045,10 +988,10 @@ NdisMFlushLog(
     UNIMPLEMENTED
 }
 
-
 /*
  * @unimplemented
  */
+#undef NdisMIndicateStatus
 VOID
 EXPORT
 NdisMIndicateStatus(
@@ -1060,10 +1003,10 @@ NdisMIndicateStatus(
     UNIMPLEMENTED
 }
 
-
 /*
  * @unimplemented
  */
+#undef NdisMIndicateStatusComplete
 VOID
 EXPORT
 NdisMIndicateStatusComplete(
@@ -1110,7 +1053,7 @@ NdisInitializeWrapper(
 
   Miniport = ExAllocatePool(NonPagedPool, sizeof(MINIPORT_DRIVER));
 
-  if (!Miniport) 
+  if (!Miniport)
     {
       NDIS_DbgPrint(MIN_TRACE, ("Insufficient resources.\n"));
       return;
@@ -1157,28 +1100,7 @@ NdisInitializeWrapper(
 }
 
 \f
-/*
- * @implemented
- */
-VOID
-EXPORT
-NdisMQueryInformationComplete(
-    IN  NDIS_HANDLE MiniportAdapterHandle,
-    IN  NDIS_STATUS Status)
-{
-  PLOGICAL_ADAPTER Adapter        = GET_LOGICAL_ADAPTER(MiniportAdapterHandle);
-  PADAPTER_BINDING AdapterBinding = (PADAPTER_BINDING)Adapter->MiniportAdapterBinding;
-
-  NDIS_DbgPrint(MAX_TRACE, ("Called.\n"));
-
-  (*AdapterBinding->ProtocolBinding->Chars.RequestCompleteHandler)(
-      AdapterBinding->NdisOpenBlock.ProtocolBindingContext,
-      Adapter->NdisMiniportBlock.MediaRequest,
-      Status);
-}
-
-\f
-VOID STDCALL NdisIBugcheckCallback(
+VOID NTAPI NdisIBugcheckCallback(
     IN PVOID   Buffer,
     IN ULONG   Length)
 /*
@@ -1195,7 +1117,7 @@ VOID STDCALL NdisIBugcheckCallback(
 
   if(sh)
     sh(Context->DriverContext);
-} 
+}
 
 \f
 /*
@@ -1223,7 +1145,7 @@ NdisMRegisterAdapterShutdownHandler(
 
   NDIS_DbgPrint(DEBUG_MINIPORT, ("Called.\n"));
 
-  if(BugcheckContext) 
+  if(BugcheckContext)
     return;
 
   BugcheckContext = ExAllocatePool(NonPagedPool, sizeof(MINIPORT_BUGCHECK_CONTEXT));
@@ -1239,8 +1161,8 @@ NdisMRegisterAdapterShutdownHandler(
   /* not sure if this needs to be initialized or not... oh well, it's a leak. */
   BugcheckContext->CallbackRecord = ExAllocatePool(NonPagedPool, sizeof(KBUGCHECK_CALLBACK_RECORD));
 
-  KeRegisterBugCheckCallback(BugcheckContext->CallbackRecord, NdisIBugcheckCallback, 
-      BugcheckContext, sizeof(BugcheckContext), "Ndis Miniport");
+  KeRegisterBugCheckCallback(BugcheckContext->CallbackRecord, NdisIBugcheckCallback,
+      BugcheckContext, sizeof(BugcheckContext), (PUCHAR)"Ndis Miniport");
 }
 
 \f
@@ -1265,7 +1187,7 @@ DoQueries(
   /* Get MAC options for adapter */
   NdisStatus = MiniQueryInformation(Adapter, OID_GEN_MAC_OPTIONS, 0, &BytesWritten);
 
-  if (NdisStatus != NDIS_STATUS_SUCCESS) 
+  if (NdisStatus != NDIS_STATUS_SUCCESS)
     {
       NDIS_DbgPrint(MIN_TRACE, ("OID_GEN_MAC_OPTIONS failed. NdisStatus (0x%X).\n", NdisStatus));
       return NdisStatus;
@@ -1278,7 +1200,7 @@ DoQueries(
   /* Get current hardware address of adapter */
   NdisStatus = MiniQueryInformation(Adapter, AddressOID, 0, &BytesWritten);
 
-  if (NdisStatus != NDIS_STATUS_SUCCESS) 
+  if (NdisStatus != NDIS_STATUS_SUCCESS)
     {
       NDIS_DbgPrint(MIN_TRACE, ("Address OID (0x%X) failed. NdisStatus (0x%X).\n", AddressOID, NdisStatus));
       return NdisStatus;
@@ -1298,32 +1220,32 @@ DoQueries(
   /* Get maximum lookahead buffer size of adapter */
   NdisStatus = MiniQueryInformation(Adapter, OID_GEN_MAXIMUM_LOOKAHEAD, 0, &BytesWritten);
 
-  if (NdisStatus != NDIS_STATUS_SUCCESS) 
+  if (NdisStatus != NDIS_STATUS_SUCCESS)
     {
       NDIS_DbgPrint(MIN_TRACE, ("OID_GEN_MAXIMUM_LOOKAHEAD failed. NdisStatus (0x%X).\n", NdisStatus));
       return NdisStatus;
     }
 
-  Adapter->MaxLookaheadLength = *((PULONG)Adapter->QueryBuffer);
+  Adapter->NdisMiniportBlock.MaximumLookahead = *((PULONG)Adapter->QueryBuffer);
 
-  NDIS_DbgPrint(DEBUG_MINIPORT, ("MaxLookaheadLength (0x%X).\n", Adapter->MaxLookaheadLength));
+  NDIS_DbgPrint(DEBUG_MINIPORT, ("MaxLookaheadLength (0x%X).\n", Adapter->NdisMiniportBlock.MaximumLookahead));
 
   /* Get current lookahead buffer size of adapter */
   NdisStatus = MiniQueryInformation(Adapter, OID_GEN_CURRENT_LOOKAHEAD, 0, &BytesWritten);
 
-  if (NdisStatus != NDIS_STATUS_SUCCESS) 
+  if (NdisStatus != NDIS_STATUS_SUCCESS)
     {
       NDIS_DbgPrint(MIN_TRACE, ("OID_GEN_CURRENT_LOOKAHEAD failed. NdisStatus (0x%X).\n", NdisStatus));
       return NdisStatus;
     }
 
-  Adapter->CurLookaheadLength = *((PULONG)Adapter->QueryBuffer);
+  Adapter->NdisMiniportBlock.CurrentLookahead = *((PULONG)Adapter->QueryBuffer);
 
-  NDIS_DbgPrint(DEBUG_MINIPORT, ("CurLookaheadLength (0x%X).\n", Adapter->CurLookaheadLength));
+  NDIS_DbgPrint(DEBUG_MINIPORT, ("CurLookaheadLength (0x%X).\n", Adapter->NdisMiniportBlock.CurrentLookahead));
 
-  if (Adapter->MaxLookaheadLength != 0) 
+  if (Adapter->NdisMiniportBlock.MaximumLookahead != 0)
     {
-      Adapter->LookaheadLength = Adapter->MaxLookaheadLength + Adapter->MediumHeaderSize;
+      Adapter->LookaheadLength = Adapter->NdisMiniportBlock.MaximumLookahead + Adapter->MediumHeaderSize;
       Adapter->LookaheadBuffer = ExAllocatePool(NonPagedPool, Adapter->LookaheadLength);
 
       if (!Adapter->LookaheadBuffer)
@@ -1334,272 +1256,501 @@ DoQueries(
 }
 
 \f
-VOID
-NdisIStartAdapter(
-    WCHAR *DeviceNameStr,
-    UINT DeviceNameStrLength,
-    PMINIPORT_DRIVER Miniport
-)
+NTSTATUS
+NTAPI
+NdisIForwardIrpAndWaitCompletionRoutine(
+    PDEVICE_OBJECT Fdo,
+    PIRP Irp,
+    PVOID Context)
+{
+  PKEVENT Event = Context;
+
+  if (Irp->PendingReturned)
+    KeSetEvent(Event, IO_NO_INCREMENT, FALSE);
+
+  return STATUS_MORE_PROCESSING_REQUIRED;
+}
+
+\f
+NTSTATUS
+NTAPI
+NdisIForwardIrpAndWait(PLOGICAL_ADAPTER Adapter, PIRP Irp)
+{
+  KEVENT Event;
+  NTSTATUS Status;
+
+  KeInitializeEvent(&Event, NotificationEvent, FALSE);
+  IoCopyCurrentIrpStackLocationToNext(Irp);
+  IoSetCompletionRoutine(Irp, NdisIForwardIrpAndWaitCompletionRoutine, &Event,
+                         TRUE, TRUE, TRUE);
+  Status = IoCallDriver(Adapter->NdisMiniportBlock.NextDeviceObject, Irp);
+  if (Status == STATUS_PENDING)
+    {
+      KeWaitForSingleObject(&Event, Executive, KernelMode, FALSE, NULL);
+      Status = Irp->IoStatus.Status;
+    }
+  return Status;
+}
+
+\f
+NTSTATUS
+NTAPI
+NdisIPnPStartDevice(
+    IN PDEVICE_OBJECT DeviceObject,
+    PIRP Irp)
 /*
- * FUNCTION: Start an adapter
+ * FUNCTION: Handle the PnP start device event
  * ARGUMENTS:
- *     DeviceNameStr: 0-terminated wide char string of name of device to start
- *     DeviceNameStrLength: length of DeviceNameStr *IN WCHARs*
- * NOTES:
- * TODO:
- *     - verify that all resources are properly freed on success & failure
- *     - break up this 250-line function
+ *     DeviceObejct = Functional Device Object
+ *     Irp          = IRP_MN_START_DEVICE I/O request packet
+ * RETURNS:
+ *     Status of operation
  */
 {
-  WCHAR *DeviceName;
-  HANDLE RegKeyHandle;
-  WCHAR *RegKeyPath;
-  UNICODE_STRING RegKeyPathU;
-  OBJECT_ATTRIBUTES RegKeyAttributes;
+  PIO_STACK_LOCATION Stack = IoGetCurrentIrpStackLocation(Irp);
+  PLOGICAL_ADAPTER Adapter = (PLOGICAL_ADAPTER)DeviceObject->DeviceExtension;
+  NDIS_WRAPPER_CONTEXT WrapperContext;
   NDIS_STATUS NdisStatus;
   NDIS_STATUS OpenErrorStatus;
   NTSTATUS Status;
   UINT SelectedMediumIndex = 0;
-  PLOGICAL_ADAPTER Adapter = 0;
   NDIS_OID AddressOID;
-  BOOLEAN MemError = FALSE;
-  KIRQL OldIrql;
-  PORPHAN_ADAPTER OrphanAdapter = 0;
+  BOOLEAN Success = FALSE;
+  ULONG ResourceCount;
+  ULONG ResourceListSize;
+  UNICODE_STRING ParamName;
+  PNDIS_CONFIGURATION_PARAMETER ConfigParam;
+  NDIS_HANDLE ConfigHandle;
+  ULONG Size;
+/* FIXME - KIRQL OldIrql; */
+
+  /*
+   * Prepare wrapper context used by HW and configuration routines.
+   */
 
-  NDIS_DbgPrint(MAX_TRACE, ("Called with %ws\n", DeviceNameStr));
-  Adapter = ExAllocatePool(NonPagedPool, sizeof(LOGICAL_ADAPTER));
-  if (!Adapter) 
+  Status = IoOpenDeviceRegistryKey(
+    Adapter->NdisMiniportBlock.PhysicalDeviceObject, PLUGPLAY_REGKEY_DRIVER,
+    KEY_ALL_ACCESS, &WrapperContext.RegistryHandle);
+  if (!NT_SUCCESS(Status))
     {
-      NDIS_DbgPrint(MIN_TRACE, ("Insufficient resources.\n"));
-      return
+      NDIS_DbgPrint(MIN_TRACE,("failed to open adapter-specific reg key\n"));
+      return Status;
     }
 
-  /* This is very important */
-  RtlZeroMemory(Adapter, sizeof(LOGICAL_ADAPTER));
+  NDIS_DbgPrint(MAX_TRACE, ("opened device reg key\n"));
+
+  WrapperContext.DeviceObject = Adapter->NdisMiniportBlock.DeviceObject;
+
+  /*
+   * Store the adapter resources used by HW routines such as
+   * NdisMQueryAdapterResources.
+   */
 
-  DeviceName = ExAllocatePool(NonPagedPool, sizeof(DEVICE_ROOT) + DeviceNameStrLength * sizeof(WCHAR));
-  if(!DeviceName)
+  if (Stack->Parameters.StartDevice.AllocatedResources != NULL &&
+      Stack->Parameters.StartDevice.AllocatedResourcesTranslated != NULL)
     {
-      NDIS_DbgPrint(MIN_TRACE,("Insufficient memory\n"));
-      ExFreePool(Adapter);
-      return;
+      ResourceCount = Stack->Parameters.StartDevice.AllocatedResources->List[0].
+                      PartialResourceList.Count;
+      ResourceListSize =
+        FIELD_OFFSET(CM_RESOURCE_LIST, List[0].PartialResourceList.
+                     PartialDescriptors[ResourceCount]);
+
+      Adapter->NdisMiniportBlock.AllocatedResources =
+        ExAllocatePool(PagedPool, ResourceListSize);
+      if (Adapter->NdisMiniportBlock.AllocatedResources == NULL)
+        {
+          return STATUS_INSUFFICIENT_RESOURCES;
+        }
+
+      Adapter->NdisMiniportBlock.AllocatedResourcesTranslated =
+        ExAllocatePool(PagedPool, ResourceListSize);
+      if (Adapter->NdisMiniportBlock.AllocatedResourcesTranslated == NULL)
+        {
+          ExFreePool(Adapter->NdisMiniportBlock.AllocatedResources);
+          Adapter->NdisMiniportBlock.AllocatedResources = NULL;
+          return STATUS_INSUFFICIENT_RESOURCES;
+        }
+
+      RtlCopyMemory(Adapter->NdisMiniportBlock.AllocatedResources,
+                    Stack->Parameters.StartDevice.AllocatedResources,
+                    ResourceListSize);
+
+      RtlCopyMemory(Adapter->NdisMiniportBlock.AllocatedResourcesTranslated,
+                    Stack->Parameters.StartDevice.AllocatedResourcesTranslated,
+                    ResourceListSize);
     }
 
-  /* DEVICE_ROOT is a constant string defined above, incl. 0-term */
-  wcscpy(DeviceName, DEVICE_ROOT);
+  /*
+   * Store the Bus Type, Bus Number and Slot information. It's used by
+   * the hardware routines then.
+   */
 
-  /* reg_sz is 0-term by def */
-  wcsncat(DeviceName, DeviceNameStr, DeviceNameStrLength); 
-  RtlInitUnicodeString(&Adapter->DeviceName, DeviceName);
+  NdisOpenConfiguration(&NdisStatus, &ConfigHandle, (NDIS_HANDLE)&WrapperContext);
 
-  NDIS_DbgPrint(MAX_TRACE, ("creating device %ws\n", DeviceName));
+  Size = sizeof(ULONG);
+  Status = IoGetDeviceProperty(Adapter->NdisMiniportBlock.PhysicalDeviceObject,
+                               DevicePropertyLegacyBusType, Size,
+                               &Adapter->NdisMiniportBlock.BusType, &Size);
+  if (!NT_SUCCESS(Status) || Adapter->NdisMiniportBlock.BusType == (NDIS_INTERFACE_TYPE)-1)
+    {
+      NdisInitUnicodeString(&ParamName, L"BusType");
+      NdisReadConfiguration(&NdisStatus, &ConfigParam, ConfigHandle,
+                            &ParamName, NdisParameterInteger);
+      if (NdisStatus == NDIS_STATUS_SUCCESS)
+        Adapter->NdisMiniportBlock.BusType = ConfigParam->ParameterData.IntegerData;
+      else
+        Adapter->NdisMiniportBlock.BusType = Isa;
+    }
 
-  Status = IoCreateDevice(Miniport->DriverObject, 0, &Adapter->DeviceName, FILE_DEVICE_PHYSICAL_NETCARD,
-      0, FALSE, &Adapter->NdisMiniportBlock.DeviceObject);
-  if (!NT_SUCCESS(Status)) 
+  Status = IoGetDeviceProperty(Adapter->NdisMiniportBlock.PhysicalDeviceObject,
+                               DevicePropertyBusNumber, Size,
+                               &Adapter->NdisMiniportBlock.BusNumber, &Size);
+  if (!NT_SUCCESS(Status) || Adapter->NdisMiniportBlock.BusNumber == (NDIS_INTERFACE_TYPE)-1)
     {
-      NDIS_DbgPrint(MIN_TRACE, ("Could not create device object.\n"));
-      ExFreePool(Adapter);
-      return;
+      NdisInitUnicodeString(&ParamName, L"BusNumber");
+      NdisReadConfiguration(&NdisStatus, &ConfigParam, ConfigHandle,
+                            &ParamName, NdisParameterInteger);
+      if (NdisStatus == NDIS_STATUS_SUCCESS)
+        Adapter->NdisMiniportBlock.BusNumber = ConfigParam->ParameterData.IntegerData;
+      else
+        Adapter->NdisMiniportBlock.BusNumber = 0;
     }
+  WrapperContext.BusNumber = Adapter->NdisMiniportBlock.BusNumber;
 
-  /* find out if there are any adapters in the orphans list and reserve resources */
-  KeAcquireSpinLock(&OrphanAdapterListLock, &OldIrql);
-  OrphanAdapter = (PORPHAN_ADAPTER)OrphanAdapterListHead.Flink;
-  while(&OrphanAdapter->ListEntry != &OrphanAdapterListHead)
+  Status = IoGetDeviceProperty(Adapter->NdisMiniportBlock.PhysicalDeviceObject,
+                               DevicePropertyAddress, Size,
+                               &Adapter->NdisMiniportBlock.SlotNumber, &Size);
+  if (!NT_SUCCESS(Status) || Adapter->NdisMiniportBlock.SlotNumber == (NDIS_INTERFACE_TYPE)-1)
     {
-      PORPHAN_ADAPTER TempAdapter;
-      PCM_RESOURCE_LIST ResourceList;
-      UINT i;
+      NdisInitUnicodeString(&ParamName, L"SlotNumber");
+      NdisReadConfiguration(&NdisStatus, &ConfigParam, ConfigHandle,
+                            &ParamName, NdisParameterInteger);
+      if (NdisStatus == NDIS_STATUS_SUCCESS)
+        Adapter->NdisMiniportBlock.SlotNumber = ConfigParam->ParameterData.IntegerData;
+      else
+        Adapter->NdisMiniportBlock.SlotNumber = 0;
+    }
 
-      if(!RtlCompareUnicodeString(&OrphanAdapter->RegistryPath, Miniport->RegistryPath, TRUE))
-        {
-          OrphanAdapter = (PORPHAN_ADAPTER)OrphanAdapter->ListEntry.Flink;
-          continue;
-        }
+  NdisCloseConfiguration(ConfigHandle);
 
-      NDIS_DbgPrint(MAX_TRACE, ("Found an orphan adapter for RegistryPath %wZ\n", Miniport->RegistryPath));
+  /*
+   * Call MiniportInitialize.
+   */
 
-      /* there is an orphan adapter for us */
-      Adapter->SlotNumber = OrphanAdapter->SlotNumber;
-      Adapter->BusNumber  = OrphanAdapter->BusNumber;
-      Adapter->BusType    = OrphanAdapter->BusType;
+  NDIS_DbgPrint(MID_TRACE, ("calling MiniportInitialize\n"));
+  NdisStatus = (*Adapter->Miniport->Chars.InitializeHandler)(
+    &OpenErrorStatus, &SelectedMediumIndex, &MediaArray[0],
+    MEDIA_ARRAY_SIZE, Adapter, (NDIS_HANDLE)&WrapperContext);
 
-      Status = HalAssignSlotResources(Miniport->RegistryPath, 0, Miniport->DriverObject,
-          Adapter->NdisMiniportBlock.DeviceObject, Adapter->BusType, Adapter->BusNumber, 
-          Adapter->SlotNumber, &ResourceList);
+  ZwClose(WrapperContext.RegistryHandle);
 
-      if(!NT_SUCCESS(Status))
-        {
-          NDIS_DbgPrint(MIN_TRACE, ("HalAssignSlotResources broke: 0x%x\n", Status));
-          ASSERT(0);
+  if (NdisStatus != NDIS_STATUS_SUCCESS ||
+      SelectedMediumIndex >= MEDIA_ARRAY_SIZE)
+    {
+      NDIS_DbgPrint(MIN_TRACE, ("MiniportInitialize() failed for an adapter.\n"));
+      return (NTSTATUS)NdisStatus;
+    }
 
-          /* i guess we should just give up on this adapter */
-          break;
-        }
+  /* Set handlers (some NDIS macros require these) */
+
+  Adapter->NdisMiniportBlock.EthRxCompleteHandler = EthFilterDprIndicateReceiveComplete;
+  Adapter->NdisMiniportBlock.EthRxIndicateHandler = EthFilterDprIndicateReceive;
+  Adapter->NdisMiniportBlock.SendCompleteHandler  = MiniSendComplete;
+  Adapter->NdisMiniportBlock.SendResourcesHandler = MiniSendResourcesAvailable;
+  Adapter->NdisMiniportBlock.ResetCompleteHandler = MiniResetComplete;
+  Adapter->NdisMiniportBlock.TDCompleteHandler    = MiniTransferDataComplete;
+  Adapter->NdisMiniportBlock.PacketIndicateHandler= MiniIndicateReceivePacket;
+
+  Adapter->NdisMiniportBlock.MediaType = MediaArray[SelectedMediumIndex];
+
+  switch (Adapter->NdisMiniportBlock.MediaType)
+    {
+      case NdisMedium802_3:
+        Adapter->MediumHeaderSize = 14;       /* XXX figure out what to do about LLC */
+        AddressOID = OID_802_3_CURRENT_ADDRESS;
+        Adapter->AddressLength = ETH_LENGTH_OF_ADDRESS;
+        NdisStatus = DoQueries(Adapter, AddressOID);
+        if (NdisStatus == NDIS_STATUS_SUCCESS)
+          {
+            Success = EthCreateFilter(32, /* FIXME: Query this from miniport. */
+                                      Adapter->Address.Type.Medium802_3,
+                                      &Adapter->NdisMiniportBlock.EthDB);
+            if (Success)
+              ((PETHI_FILTER)Adapter->NdisMiniportBlock.EthDB)->Miniport = (PNDIS_MINIPORT_BLOCK)Adapter;
+            else
+              NdisStatus = NDIS_STATUS_RESOURCES;
+          }
+        break;
+
+      default:
+        /* FIXME: Support other types of media */
+        NDIS_DbgPrint(MIN_TRACE, ("error: unsupported media\n"));
+        ASSERT(FALSE);
+/* FIXME - KeReleaseSpinLock(&Adapter->NdisMiniportBlock.Lock, OldIrql); */
+        return STATUS_UNSUCCESSFUL;
+    }
 
-      /* go through the returned resource list and populate the Adapter */
-      for(i = 0; i<ResourceList->Count; i++)
+  if (!Success || NdisStatus != NDIS_STATUS_SUCCESS)
+    {
+      NDIS_DbgPrint(MAX_TRACE, ("couldn't create filter (%x)\n", NdisStatus));
+      if (Adapter->LookaheadBuffer)
         {
-          int j;
+          ExFreePool(Adapter->LookaheadBuffer);
+          Adapter->LookaheadBuffer = NULL;
+        }
+      return (NTSTATUS)NdisStatus;
+    }
 
-          PCM_FULL_RESOURCE_DESCRIPTOR ResourceDescriptor = &ResourceList->List[i];
+  Adapter->NdisMiniportBlock.OldPnPDeviceState = Adapter->NdisMiniportBlock.PnPDeviceState;
+  Adapter->NdisMiniportBlock.PnPDeviceState = NdisPnPDeviceStarted;
 
-          for(j=0; j<ResourceDescriptor->PartialResourceList.Count; j++)
-            {
-              PCM_PARTIAL_RESOURCE_DESCRIPTOR PartialResourceDescriptor = 
-                  &ResourceDescriptor->PartialResourceList.PartialDescriptors[i];
+  /* Put adapter in adapter list for this miniport */
+  ExInterlockedInsertTailList(&Adapter->Miniport->AdapterListHead, &Adapter->MiniportListEntry, &Adapter->Miniport->Lock);
 
-              switch(PartialResourceDescriptor->Type)
-                {
-                case CmResourceTypeInterrupt:
-                  Adapter->Irql = PartialResourceDescriptor->u.Interrupt.Level;
-                  Adapter->Vector = PartialResourceDescriptor->u.Interrupt.Vector;
-                  Adapter->Affinity = PartialResourceDescriptor->u.Interrupt.Affinity;
-                  break;
+  /* Put adapter in global adapter list */
+  ExInterlockedInsertTailList(&AdapterListHead, &Adapter->ListEntry, &AdapterListLock);
 
-                case CmResourceTypePort:
-                  Adapter->BaseIoAddress = PartialResourceDescriptor->u.Port.Start;
-                  break;
+  return STATUS_SUCCESS;
+}
 
-                case CmResourceTypeMemory:
-                  Adapter->BaseMemoryAddress = PartialResourceDescriptor->u.Memory.Start;
-                  break;
+\f
+NTSTATUS
+NTAPI
+NdisIPnPStopDevice(
+    IN PDEVICE_OBJECT DeviceObject,
+    PIRP Irp)
+/*
+ * FUNCTION: Handle the PnP stop device event
+ * ARGUMENTS:
+ *     DeviceObejct = Functional Device Object
+ *     Irp          = IRP_MN_STOP_DEVICE I/O request packet
+ * RETURNS:
+ *     Status of operation
+ */
+{
+  PLOGICAL_ADAPTER Adapter = (PLOGICAL_ADAPTER)DeviceObject->DeviceExtension;
+  KIRQL OldIrql;
 
-                case CmResourceTypeDma:
-                  Adapter->DmaPort = PartialResourceDescriptor->u.Dma.Port;
-                  Adapter->DmaChannel = PartialResourceDescriptor->u.Dma.Channel;
-                  break;
+  /* Remove adapter from adapter list for this miniport */
+  KeAcquireSpinLock(&Adapter->Miniport->Lock, &OldIrql);
+  RemoveEntryList(&Adapter->MiniportListEntry);
+  KeReleaseSpinLock(&Adapter->Miniport->Lock, OldIrql);
 
-                case CmResourceTypeDeviceSpecific:
-                default:
-                  break;
-                }
-            }
-        }
+  /* Remove adapter from global adapter list */
+  KeAcquireSpinLock(&AdapterListLock, &OldIrql);
+  RemoveEntryList(&Adapter->ListEntry);
+  KeReleaseSpinLock(&AdapterListLock, OldIrql);
 
-      /* remove the adapter from the list */
-      TempAdapter = (PORPHAN_ADAPTER)OrphanAdapter->ListEntry.Flink;
-      RemoveEntryList(&OrphanAdapter->ListEntry);
-      OrphanAdapter = TempAdapter;
-    }
-  KeReleaseSpinLock(&OrphanAdapterListLock, OldIrql);
+  (*Adapter->Miniport->Chars.HaltHandler)(Adapter);
 
-  /* includes room for a 0-term */
-  RegKeyPath = ExAllocatePool(PagedPool, (wcslen(SERVICES_ROOT) + wcslen(DeviceNameStr) + 1) * sizeof(WCHAR));
-  if(!RegKeyPath)
+  if (Adapter->LookaheadBuffer)
     {
-      NDIS_DbgPrint(MIN_TRACE,("Insufficient resources\n"));
-      ExFreePool(Adapter);
-      return; 
+      ExFreePool(Adapter->LookaheadBuffer);
+      Adapter->LookaheadBuffer = NULL;
+    }
+  if (Adapter->NdisMiniportBlock.AllocatedResources)
+    {
+      ExFreePool(Adapter->NdisMiniportBlock.AllocatedResources);
+      Adapter->NdisMiniportBlock.AllocatedResources = NULL;
+    }
+  if (Adapter->NdisMiniportBlock.AllocatedResourcesTranslated)
+    {
+      ExFreePool(Adapter->NdisMiniportBlock.AllocatedResourcesTranslated);
+      Adapter->NdisMiniportBlock.AllocatedResourcesTranslated = NULL;
     }
 
-  wcscpy(RegKeyPath, SERVICES_ROOT);
-  wcscat(RegKeyPath, DeviceNameStr);
-  RegKeyPath[wcslen(SERVICES_ROOT) + wcslen(DeviceNameStr)] = 0;
+  Adapter->NdisMiniportBlock.OldPnPDeviceState = Adapter->NdisMiniportBlock.PnPDeviceState;
+  Adapter->NdisMiniportBlock.PnPDeviceState = NdisPnPDeviceStopped;
 
-  RtlInitUnicodeString(&RegKeyPathU, RegKeyPath);
-  InitializeObjectAttributes(&RegKeyAttributes, &RegKeyPathU, OBJ_CASE_INSENSITIVE, NULL, NULL);
+  return STATUS_SUCCESS;
+}
 
-  Status = ZwOpenKey(&RegKeyHandle, KEY_ALL_ACCESS, &RegKeyAttributes);
-  if(Status != STATUS_SUCCESS)
+\f
+NTSTATUS
+NTAPI
+NdisIDispatchPnp(
+    IN PDEVICE_OBJECT DeviceObject,
+    PIRP Irp)
+{
+  PIO_STACK_LOCATION Stack = IoGetCurrentIrpStackLocation(Irp);
+  PLOGICAL_ADAPTER Adapter = (PLOGICAL_ADAPTER)DeviceObject->DeviceExtension;
+  NTSTATUS Status;
+
+  switch (Stack->MinorFunction)
     {
-      NDIS_DbgPrint(MIN_TRACE,("failed to open adapter-specific reg key %wZ\n", &RegKeyPathU));
-      ExFreePool(Adapter);
-      return;
-    }
+      case IRP_MN_START_DEVICE:
+        Status = NdisIForwardIrpAndWait(Adapter, Irp);
+        if (NT_SUCCESS(Status) && NT_SUCCESS(Irp->IoStatus.Status))
+          {
+             Status = NdisIPnPStartDevice(DeviceObject, Irp);
+          }
+        Irp->IoStatus.Status = Status;
+        IoCompleteRequest(Irp, IO_NO_INCREMENT);
+        break;
 
-  NDIS_DbgPrint(MAX_TRACE, ("opened device reg key: %wZ\n", &RegKeyPathU));
+      case IRP_MN_STOP_DEVICE:
+        /* FIXME */
+        Status = STATUS_UNSUCCESSFUL;
+        break;
+        Status = NdisIForwardIrpAndWait(Adapter, Irp);
+        if (NT_SUCCESS(Status) && NT_SUCCESS(Irp->IoStatus.Status))
+          {
+            Status = NdisIPnPStopDevice(DeviceObject, Irp);
+          }
+        Irp->IoStatus.Status = Status;
+        IoCompleteRequest(Irp, IO_NO_INCREMENT);
+        break;
 
-  NDIS_DbgPrint(MAX_TRACE, ("acquiring miniport block lock\n"));
-  KeInitializeSpinLock(&Adapter->NdisMiniportBlock.Lock);
-  InitializeListHead(&Adapter->ProtocolListHead);
-  Adapter->RefCount = 1;
-  Adapter->Miniport = Miniport;
+      default:
+        IoSkipCurrentIrpStackLocation(Irp);
+        Status = IoCallDriver(Adapter->NdisMiniportBlock.NextDeviceObject, Irp);
+        break;
+    }
 
-  /* Set handlers (some NDIS macros require these) */
+  return Status;
+}
 
-  Adapter->NdisMiniportBlock.EthRxCompleteHandler = MiniEthReceiveComplete;
-  Adapter->NdisMiniportBlock.EthRxIndicateHandler = MiniEthReceiveIndication;
-  Adapter->NdisMiniportBlock.SendCompleteHandler  = MiniSendComplete;
-  Adapter->NdisMiniportBlock.SendResourcesHandler = MiniSendResourcesAvailable;
-  Adapter->NdisMiniportBlock.ResetCompleteHandler = MiniResetComplete;
-  Adapter->NdisMiniportBlock.TDCompleteHandler    = MiniTransferDataComplete;
-  Adapter->NdisMiniportBlock.PacketIndicateHandler= MiniIndicateReceivePacket;
+\f
+NTSTATUS
+NTAPI
+NdisIAddDevice(
+    IN PDRIVER_OBJECT DriverObject,
+    IN PDEVICE_OBJECT PhysicalDeviceObject)
+/*
+ * FUNCTION: Create a device for an adapter found using PnP
+ * ARGUMENTS:
+ *     DriverObject         = Pointer to the miniport driver object
+ *     PhysicalDeviceObject = Pointer to the PDO for our adapter
+ */
+{
+  static const WCHAR ClassKeyName[] = {'C','l','a','s','s','\\'};
+  static const WCHAR LinkageKeyName[] = {'\\','L','i','n','k','a','g','e',0};
+  PMINIPORT_DRIVER Miniport;
+  PMINIPORT_DRIVER *MiniportPtr;
+  WCHAR *LinkageKeyBuffer;
+  ULONG DriverKeyLength;
+  RTL_QUERY_REGISTRY_TABLE QueryTable[2];
+  UNICODE_STRING ExportName;
+  PDEVICE_OBJECT DeviceObject;
+  PLOGICAL_ADAPTER Adapter;
+  NTSTATUS Status;
 
-  KeInitializeDpc(&Adapter->MiniportDpc, MiniportDpc, (PVOID)Adapter);
+  /*
+   * Gain the access to the miniport data structure first.
+   */
 
-  /* Put adapter in adapter list for this miniport */
-  ExInterlockedInsertTailList(&Miniport->AdapterListHead, &Adapter->MiniportListEntry, &Miniport->Lock);
+  MiniportPtr = IoGetDriverObjectExtension(DriverObject, (PVOID)TAG('D','I','M','N'));
+  if (MiniportPtr == NULL)
+    {
+      NDIS_DbgPrint(DEBUG_MINIPORT, ("Can't get driver object extension.\n"));
+      return STATUS_UNSUCCESSFUL;
+    }
+  Miniport = *MiniportPtr;
 
-  /* Put adapter in global adapter list */
-  ExInterlockedInsertTailList(&AdapterListHead, &Adapter->ListEntry, &AdapterListLock);
+  /*
+   * Get name of the Linkage registry key for our adapter. It's located under
+   * the driver key for our driver and so we have basicly two ways to do it.
+   * Either we can use IoOpenDriverRegistryKey or compose it using information
+   * gathered by IoGetDeviceProperty. I choosed the second because
+   * IoOpenDriverRegistryKey wasn't implemented at the time of writing.
+   */
 
-  /* Call MiniportInitialize */
-  NDIS_DbgPrint(MID_TRACE, ("calling MiniportInitialize\n"));
-  NdisStatus = (*Miniport->Chars.InitializeHandler)( &OpenErrorStatus, &SelectedMediumIndex, &MediaArray[0],
-      MEDIA_ARRAY_SIZE, Adapter, RegKeyHandle);
+  Status = IoGetDeviceProperty(PhysicalDeviceObject, DevicePropertyDriverKeyName,
+                               0, NULL, &DriverKeyLength);
+  if (Status != STATUS_BUFFER_TOO_SMALL)
+    {
+      NDIS_DbgPrint(DEBUG_MINIPORT, ("Can't get miniport driver key length.\n"));
+      return Status;
+    }
 
-  ZwClose(RegKeyHandle);
+  LinkageKeyBuffer = ExAllocatePool(PagedPool, DriverKeyLength +
+                                    sizeof(ClassKeyName) + sizeof(LinkageKeyName));
+  if (LinkageKeyBuffer == NULL)
+    {
+      NDIS_DbgPrint(DEBUG_MINIPORT, ("Can't allocate memory for driver key name.\n"));
+      return STATUS_INSUFFICIENT_RESOURCES;
+    }
 
-  if ((NdisStatus == NDIS_STATUS_SUCCESS) && (SelectedMediumIndex < MEDIA_ARRAY_SIZE)) 
+  Status = IoGetDeviceProperty(PhysicalDeviceObject, DevicePropertyDriverKeyName,
+                               DriverKeyLength, LinkageKeyBuffer +
+                               (sizeof(ClassKeyName) / sizeof(WCHAR)),
+                               &DriverKeyLength);
+  if (!NT_SUCCESS(Status))
     {
-      NDIS_DbgPrint(MID_TRACE,("successful return from MiniportInitialize\n"));
+      NDIS_DbgPrint(DEBUG_MINIPORT, ("Can't get miniport driver key.\n"));
+      ExFreePool(LinkageKeyBuffer);
+      return Status;
+    }
 
-      Adapter->NdisMiniportBlock.MediaType = MediaArray[SelectedMediumIndex];
+  /* Compose the linkage key name. */
+  RtlCopyMemory(LinkageKeyBuffer, ClassKeyName, sizeof(ClassKeyName));
+  RtlCopyMemory(LinkageKeyBuffer + ((sizeof(ClassKeyName) + DriverKeyLength) /
+                sizeof(WCHAR)) - 1, LinkageKeyName, sizeof(LinkageKeyName));
 
-      switch (Adapter->NdisMiniportBlock.MediaType) 
-        {
-        case NdisMedium802_3:
-          Adapter->MediumHeaderSize = 14;       /* XXX figure out what to do about LLC */
-          AddressOID = OID_802_3_CURRENT_ADDRESS;
-          Adapter->AddressLength = ETH_LENGTH_OF_ADDRESS;
+  NDIS_DbgPrint(DEBUG_MINIPORT, ("LinkageKey: %S.\n", LinkageKeyBuffer));
 
-          Adapter->NdisMiniportBlock.FilterDbs.u.EthDB = ExAllocatePool(NonPagedPool, sizeof(ETH_FILTER));
-          if (Adapter->NdisMiniportBlock.FilterDbs.u.EthDB) 
-            {
-              RtlZeroMemory(Adapter->NdisMiniportBlock.FilterDbs.u.EthDB, sizeof(ETH_FILTER));
-              Adapter->NdisMiniportBlock.FilterDbs.u.EthDB->Miniport = (PNDIS_MINIPORT_BLOCK)Adapter;
-            } 
-          else
-            MemError = TRUE;
-
-          break;
-
-        default:
-          /* FIXME: Support other types of media */
-          NDIS_DbgPrint(MIN_TRACE, ("error: unsupported media\n"));
-          ExFreePool(Adapter);
-          ASSERT(FALSE);
-         KeReleaseSpinLock(&Adapter->NdisMiniportBlock.Lock, OldIrql);
-          return;
-        }
+  /*
+   * Now open the linkage key and read the "Export" and "RootDevice" values
+   * which contains device name and root service respectively.
+   */
+
+  RtlZeroMemory(QueryTable, sizeof(QueryTable));
+  RtlInitUnicodeString(&ExportName, NULL);
+  QueryTable[0].Flags = RTL_QUERY_REGISTRY_REQUIRED | RTL_QUERY_REGISTRY_DIRECT;
+  QueryTable[0].Name = L"Export";
+  QueryTable[0].EntryContext = &ExportName;
 
-      NdisStatus = DoQueries(Adapter, AddressOID);
+  Status = RtlQueryRegistryValues(RTL_REGISTRY_CONTROL, LinkageKeyBuffer,
+                                  QueryTable, NULL, NULL);
+  ExFreePool(LinkageKeyBuffer);
+  if (!NT_SUCCESS(Status))
+    {
+      NDIS_DbgPrint(DEBUG_MINIPORT, ("Can't get miniport device name. (%x)\n", Status));
+      return Status;
     }
 
-  if ((MemError) || (NdisStatus != NDIS_STATUS_SUCCESS) || (SelectedMediumIndex >= MEDIA_ARRAY_SIZE)) 
+  /*
+   * Create the device object.
+   */
+
+  NDIS_DbgPrint(MAX_TRACE, ("creating device %wZ\n", &ExportName));
+
+  Status = IoCreateDevice(Miniport->DriverObject, sizeof(LOGICAL_ADAPTER),
+    &ExportName, FILE_DEVICE_PHYSICAL_NETCARD,
+    0, FALSE, &DeviceObject);
+  if (!NT_SUCCESS(Status))
     {
-      NDIS_DbgPrint(MAX_TRACE, ("return from MiniportInitialize: NdisStatus 0x%x, SelectedMediumIndex 0x%x\n",
-          NdisStatus, SelectedMediumIndex));
+      NDIS_DbgPrint(MIN_TRACE, ("Could not create device object.\n"));
+      RtlFreeUnicodeString(&ExportName);
+      return Status;
+    }
 
-      /* Remove adapter from adapter list for this miniport */
-      KeAcquireSpinLock(&Miniport->Lock, &OldIrql);
-      RemoveEntryList(&Adapter->MiniportListEntry);
-      KeReleaseSpinLock(&Miniport->Lock, OldIrql);
+  /*
+   * Initialize the adapter structure.
+   */
 
-      /* Remove adapter from global adapter list */
-      KeAcquireSpinLock(&AdapterListLock, &OldIrql);
-      RemoveEntryList(&Adapter->ListEntry);
-      KeReleaseSpinLock(&AdapterListLock, OldIrql);
+  Adapter = (PLOGICAL_ADAPTER)DeviceObject->DeviceExtension;
+  KeInitializeSpinLock(&Adapter->NdisMiniportBlock.Lock);
+  InitializeListHead(&Adapter->ProtocolListHead);
+  Adapter->RefCount = 1;
+  Adapter->Miniport = Miniport;
 
-      if (Adapter->LookaheadBuffer)
-        ExFreePool(Adapter->LookaheadBuffer);
+  Adapter->NdisMiniportBlock.MiniportName = ExportName;
 
-      IoDeleteDevice(Adapter->NdisMiniportBlock.DeviceObject);
-      ExFreePool(Adapter);
-      NDIS_DbgPrint(MIN_TRACE, ("MiniportInitialize() failed for an adapter.\n"));
-    }
+  Adapter->NdisMiniportBlock.DeviceObject = DeviceObject;
+  Adapter->NdisMiniportBlock.PhysicalDeviceObject = PhysicalDeviceObject;
+  Adapter->NdisMiniportBlock.NextDeviceObject =
+    IoAttachDeviceToDeviceStack(Adapter->NdisMiniportBlock.DeviceObject,
+                                PhysicalDeviceObject);
+
+  Adapter->NdisMiniportBlock.OldPnPDeviceState = 0;
+  Adapter->NdisMiniportBlock.PnPDeviceState = NdisPnPDeviceAdded;
+
+  KeInitializeDpc(&Adapter->MiniportDpc, MiniportDpc, (PVOID)Adapter);
+
+  DeviceObject->Flags &= ~DO_DEVICE_INITIALIZING;
+
+  return STATUS_SUCCESS;
 }
 
 \f
@@ -1619,41 +1770,28 @@ NdisMRegisterMiniport(
  *     MiniportCharacteristics = Pointer to a buffer with miniport characteristics
  *     CharacteristicsLength   = Number of bytes in characteristics buffer
  * RETURNS:
- *     Status of operation      
- * NOTES:
- *     - To create device objects for the miniport, the Route value under Linkage is
- *       parsed.  I don't know if this is the way Microsoft does it or not.
- * TODO: 
- *     verify this algorithm by playing with nt
+ *     Status of operation
  */
 {
   UINT MinSize;
-  NTSTATUS Status;
   PMINIPORT_DRIVER Miniport = GET_MINIPORT_DRIVER(NdisWrapperHandle);
-  OBJECT_ATTRIBUTES DeviceKeyAttributes;
-  OBJECT_ATTRIBUTES LinkageKeyAttributes;
-  HANDLE DeviceKeyHandle;
-  HANDLE LinkageKeyHandle;
-  UNICODE_STRING RouteVal;
-  UNICODE_STRING LinkageKeyName;
-  KEY_VALUE_PARTIAL_INFORMATION *RouteData;
-  ULONG RouteDataLength;
-  UINT NextRouteOffset = 0;
+  PMINIPORT_DRIVER *MiniportPtr;
+  NTSTATUS Status;
 
   NDIS_DbgPrint(MAX_TRACE, ("Called.\n"));
 
-  switch (MiniportCharacteristics->MajorNdisVersion) 
+  switch (MiniportCharacteristics->MajorNdisVersion)
     {
       case 0x03:
-        MinSize = sizeof(NDIS30_MINIPORT_CHARACTERISTICS_S);
+        MinSize = sizeof(NDIS30_MINIPORT_CHARACTERISTICS);
         break;
 
       case 0x04:
-        MinSize = sizeof(NDIS40_MINIPORT_CHARACTERISTICS_S);
+        MinSize = sizeof(NDIS40_MINIPORT_CHARACTERISTICS);
         break;
 
       case 0x05:
-        MinSize = sizeof(NDIS50_MINIPORT_CHARACTERISTICS_S);
+        MinSize = sizeof(NDIS50_MINIPORT_CHARACTERISTICS);
         break;
 
       default:
@@ -1661,7 +1799,7 @@ NdisMRegisterMiniport(
         return NDIS_STATUS_BAD_VERSION;
     }
 
-  if (CharacteristicsLength < MinSize) 
+  if (CharacteristicsLength < MinSize)
     {
         NDIS_DbgPrint(DEBUG_MINIPORT, ("Bad miniport characteristics.\n"));
         return NDIS_STATUS_BAD_CHARACTERISTICS;
@@ -1672,25 +1810,25 @@ NdisMRegisterMiniport(
       (!MiniportCharacteristics->InitializeHandler)||
       (!MiniportCharacteristics->QueryInformationHandler) ||
       (!MiniportCharacteristics->ResetHandler) ||
-      (!MiniportCharacteristics->SetInformationHandler)) 
+      (!MiniportCharacteristics->SetInformationHandler))
     {
       NDIS_DbgPrint(DEBUG_MINIPORT, ("Bad miniport characteristics.\n"));
       return NDIS_STATUS_BAD_CHARACTERISTICS;
     }
 
-  if (MiniportCharacteristics->MajorNdisVersion == 0x03) 
+  if (MiniportCharacteristics->MajorNdisVersion == 0x03)
     {
-      if (!MiniportCharacteristics->u1.SendHandler) 
+      if (!MiniportCharacteristics->SendHandler)
         {
           NDIS_DbgPrint(DEBUG_MINIPORT, ("Bad miniport characteristics.\n"));
           return NDIS_STATUS_BAD_CHARACTERISTICS;
         }
-    } 
-  else if (MiniportCharacteristics->MajorNdisVersion >= 0x04) 
+    }
+  else if (MiniportCharacteristics->MajorNdisVersion >= 0x04)
     {
       /* NDIS 4.0+ */
-      if ((!MiniportCharacteristics->u1.SendHandler) &&
-          (!MiniportCharacteristics->SendPacketsHandler)) 
+      if ((!MiniportCharacteristics->SendHandler) &&
+          (!MiniportCharacteristics->SendPacketsHandler))
         {
           NDIS_DbgPrint(DEBUG_MINIPORT, ("Bad miniport characteristics.\n"));
           return NDIS_STATUS_BAD_CHARACTERISTICS;
@@ -1702,72 +1840,23 @@ NdisMRegisterMiniport(
   RtlCopyMemory(&Miniport->Chars, MiniportCharacteristics, MinSize);
 
   /*
-   * extract the list of bound adapters from the registry's Route value
-   * for this adapter.  It seems under WinNT that the Route value in the
-   * Linkage subkey holds an entry for each miniport instance we know about.
-   * This surely isn't how Windows does it, but it's better than nothing.
-   *
-   * FIXME: this is documented in the ddk, believe it or not - read & do
+   * NOTE: This is VERY unoptimal! Should we store the MINIPORT_DRIVER
+   * struture in the driver extension or what?
    */
 
-  /* Read the miniport config from the registry */
-  InitializeObjectAttributes(&DeviceKeyAttributes, Miniport->RegistryPath, OBJ_CASE_INSENSITIVE, NULL, NULL);
-
-  Status = ZwOpenKey(&DeviceKeyHandle, KEY_READ, &DeviceKeyAttributes);
-  if(!NT_SUCCESS(Status))
+  Status = IoAllocateDriverObjectExtension(Miniport->DriverObject, (PVOID)TAG('D','I','M','N'),
+                                           sizeof(PMINIPORT_DRIVER), (PVOID*)&MiniportPtr);
+  if (!NT_SUCCESS(Status))
     {
-      NDIS_DbgPrint(MIN_TRACE,("Failed to open driver key: 0x%x\n", Status));
-      return NDIS_STATUS_FAILURE;
-    }
-
-  RtlInitUnicodeString(&LinkageKeyName, L"Linkage");
-  InitializeObjectAttributes(&LinkageKeyAttributes, &LinkageKeyName, OBJ_CASE_INSENSITIVE, DeviceKeyHandle, NULL);
-
-  Status = ZwOpenKey(&LinkageKeyHandle, KEY_READ, &LinkageKeyAttributes);
-  if(!NT_SUCCESS(Status))
-    {
-      NDIS_DbgPrint(MIN_TRACE,("Failed to open Linkage key: 0x%x\n", Status));
-      ZwClose(DeviceKeyHandle);
-      return NDIS_STATUS_FAILURE;
-    }
-
-  RouteData = ExAllocatePool(PagedPool, ROUTE_DATA_SIZE);
-  if(!RouteData)
-    {
-      NDIS_DbgPrint(MIN_TRACE,("Insufficient resources\n"));
-      ZwClose(LinkageKeyHandle);
-      ZwClose(DeviceKeyHandle);
+      NDIS_DbgPrint(DEBUG_MINIPORT, ("Can't allocate driver object extension.\n"));
       return NDIS_STATUS_RESOURCES;
     }
 
-  RtlInitUnicodeString(&RouteVal, L"Route");
-
-  Status = ZwQueryValueKey(LinkageKeyHandle, &RouteVal, KeyValuePartialInformation, RouteData, ROUTE_DATA_SIZE, &RouteDataLength);
-  if(!NT_SUCCESS(Status))
-    {
-      NDIS_DbgPrint(MIN_TRACE,("Failed to query Route value\n"));
-      ZwClose(LinkageKeyHandle);
-      ZwClose(DeviceKeyHandle);
-      ExFreePool(RouteData);
-      return NDIS_STATUS_FAILURE;
-    }
+  *MiniportPtr = Miniport;
 
-  ZwClose(LinkageKeyHandle);
-  ZwClose(DeviceKeyHandle);
+  Miniport->DriverObject->MajorFunction[IRP_MJ_PNP] = NdisIDispatchPnp;
+  Miniport->DriverObject->DriverExtension->AddDevice = NdisIAddDevice;
 
-  /* route is a REG_MULTI_SZ with each nic object created by NDI - create an adapter for each */
-  while(*(RouteData->Data + NextRouteOffset))
-    {
-      NDIS_DbgPrint(MID_TRACE, ("Starting adapter %ws\n", (WCHAR *)(RouteData->Data + NextRouteOffset)));
-
-      NdisIStartAdapter((WCHAR *)(RouteData->Data + NextRouteOffset), 
-          wcslen((WCHAR *)(RouteData->Data + NextRouteOffset)), Miniport);
-
-      /* NextRouteOffset is in bytes, not WCHARs */
-      NextRouteOffset += wcslen((WCHAR *)(RouteData->Data + NextRouteOffset)) * sizeof(WCHAR); 
-    }
-
-  ExFreePool(RouteData);
   return NDIS_STATUS_SUCCESS;
 }
 
@@ -1775,6 +1864,7 @@ NdisMRegisterMiniport(
 /*
  * @implemented
  */
+#undef NdisMResetComplete
 VOID
 EXPORT
 NdisMResetComplete(
@@ -1789,6 +1879,7 @@ NdisMResetComplete(
 /*
  * @implemented
  */
+#undef NdisMSendComplete
 VOID
 EXPORT
 NdisMSendComplete(
@@ -1811,6 +1902,7 @@ NdisMSendComplete(
 /*
  * @implemented
  */
+#undef NdisMSendResourcesAvailable
 VOID
 EXPORT
 NdisMSendResourcesAvailable(
@@ -1823,6 +1915,7 @@ NdisMSendResourcesAvailable(
 /*
  * @implemented
  */
+#undef NdisMTransferDataComplete
 VOID
 EXPORT
 NdisMTransferDataComplete(
@@ -1838,27 +1931,21 @@ NdisMTransferDataComplete(
 /*
  * @implemented
  */
+#undef NdisMSetInformationComplete
 VOID
 EXPORT
 NdisMSetInformationComplete(
     IN  NDIS_HANDLE MiniportAdapterHandle,
     IN  NDIS_STATUS Status)
 {
-  PLOGICAL_ADAPTER Adapter        = GET_LOGICAL_ADAPTER(MiniportAdapterHandle);
-  PADAPTER_BINDING AdapterBinding = (PADAPTER_BINDING)Adapter->MiniportAdapterBinding;
-
-  NDIS_DbgPrint(MAX_TRACE, ("Called.\n"));
-
-  (*AdapterBinding->ProtocolBinding->Chars.RequestCompleteHandler)(
-      AdapterBinding->NdisOpenBlock.ProtocolBindingContext,
-      Adapter->NdisMiniportBlock.MediaRequest,
-      Status);
+  (*((PNDIS_MINIPORT_BLOCK)(MiniportAdapterHandle))->SetCompleteHandler)(MiniportAdapterHandle, Status);
 }
 
 \f
 /*
  * @implemented
  */
+#undef NdisMSetAttributes
 VOID
 EXPORT
 NdisMSetAttributes(
@@ -1875,17 +1962,10 @@ NdisMSetAttributes(
  *     AdapterType            = Specifies the I/O bus interface of the caller's NIC
  */
 {
-  PLOGICAL_ADAPTER Adapter = GET_LOGICAL_ADAPTER(MiniportAdapterHandle);
-
   NDIS_DbgPrint(MAX_TRACE, ("Called.\n"));
-
-  Adapter->NdisMiniportBlock.MiniportAdapterContext = MiniportAdapterContext;
-  
-  if(BusMaster)
-    Adapter->NdisMiniportBlock.Flags |= NDIS_ATTRIBUTE_BUS_MASTER;
-
-  Adapter->NdisMiniportBlock.AdapterType   = AdapterType;
-  Adapter->AttributesSet = TRUE;
+  NdisMSetAttributesEx(MiniportAdapterHandle, MiniportAdapterContext, 0,
+                       BusMaster ? NDIS_ATTRIBUTE_BUS_MASTER : 0,
+                       AdapterType);
 }
 
 \f
@@ -1915,15 +1995,14 @@ NdisMSetAttributesEx(
 
   PLOGICAL_ADAPTER Adapter = GET_LOGICAL_ADAPTER(MiniportAdapterHandle);
 
-  NDIS_DbgPrint(MAX_TRACE, ("Called - NdisMSetAttributesEx() is partly-implemented.\n"));
+  NDIS_DbgPrint(MAX_TRACE, ("Called.\n"));
 
   Adapter->NdisMiniportBlock.MiniportAdapterContext = MiniportAdapterContext;
-
-  /* don't know why this is here - anybody? */
-  Adapter->NdisMiniportBlock.Flags  = AttributeFlags;
-
+  Adapter->NdisMiniportBlock.Flags = AttributeFlags;
   Adapter->NdisMiniportBlock.AdapterType = AdapterType;
   Adapter->AttributesSet = TRUE;
+  if (AttributeFlags & NDIS_ATTRIBUTE_INTERMEDIATE_DRIVER)
+    NDIS_DbgPrint(MAX_TRACE, ("Intermediate drivers not supported yet.\n"));
 }
 
 \f
@@ -1965,7 +2044,7 @@ NdisMSynchronizeWithInterrupt(
     IN  PVOID                       SynchronizeFunction,
     IN  PVOID                       SynchronizeContext)
 {
-  return(KeSynchronizeExecution((PKINTERRUPT)Interrupt,
+  return(KeSynchronizeExecution(Interrupt->InterruptObject,
                                (PKSYNCHRONIZE_ROUTINE)SynchronizeFunction,
                                SynchronizeContext));
 }