ReactOS Fundraising Campaign 2012
 
€ 4,410 / € 30,000

Information | Donate

Home | Info | Community | Development | myReactOS | Contact Us

  1. Home
  2. Community
  3. Development
  4. myReactOS
  5. Fundraiser 2012

  1. Main Page
  2. Alphabetical List
  3. Data Structures
  4. Directories
  5. File List
  6. Data Fields
  7. Globals
  8. Related Pages

ReactOS Development > Doxygen

protocol.c
Go to the documentation of this file.
00001 /*
00002  * COPYRIGHT:   See COPYING in the top level directory
00003  * PROJECT:     ReactOS NDIS library
00004  * FILE:        ndis/protocol.c
00005  * PURPOSE:     Routines used by NDIS protocol drivers
00006  * PROGRAMMERS: Casper S. Hornstrup (chorns@users.sourceforge.net)
00007  *              Vizzini (vizzini@plasmic.com)
00008  * REVISIONS:
00009  *   CSH 01/08-2000 Created
00010  *   09-13-2003 Vizzini Updates for SendPackets support
00011  */
00012 
00013 #include "ndissys.h"
00014 
00015 #define SERVICES_KEY L"\\Registry\\Machine\\System\\CurrentControlSet\\Services\\"
00016 #define LINKAGE_KEY  L"\\Linkage"
00017 #define PARAMETERS_KEY L"\\Parameters\\"
00018 
00019 LIST_ENTRY ProtocolListHead;
00020 KSPIN_LOCK ProtocolListLock;
00021 
00022 #define WORKER_TEST 0
00023 
00024 typedef struct _DMA_CONTEXT {
00025     PLOGICAL_ADAPTER Adapter;
00026     PNDIS_PACKET Packet;
00027 } DMA_CONTEXT, *PDMA_CONTEXT;
00028 
00029 PNET_PNP_EVENT
00030 ProSetupPnPEvent(
00031     NET_PNP_EVENT_CODE EventCode,
00032     PVOID              EventBuffer,
00033     ULONG              EventBufferLength)
00034 {
00035     PNET_PNP_EVENT PnPEvent;
00036 
00037     PnPEvent = ExAllocatePool(PagedPool, sizeof(NET_PNP_EVENT));
00038     if (!PnPEvent) {
00039         NDIS_DbgPrint(MIN_TRACE, ("Insufficient resources\n"));
00040         return NULL;
00041     }
00042 
00043     RtlZeroMemory(PnPEvent, sizeof(NET_PNP_EVENT));
00044 
00045     PnPEvent->NetEvent = EventCode;
00046 
00047     if (EventBuffer != NULL)
00048     {
00049         PnPEvent->Buffer = ExAllocatePool(PagedPool, EventBufferLength);
00050         if (!PnPEvent->Buffer)
00051         {
00052             NDIS_DbgPrint(MIN_TRACE, ("Insufficient resources\n"));
00053             ExFreePool(PnPEvent);
00054             return NULL;
00055         }
00056 
00057         PnPEvent->BufferLength = EventBufferLength;
00058 
00059         RtlCopyMemory(PnPEvent->Buffer, EventBuffer, PnPEvent->BufferLength);
00060     }
00061 
00062     return PnPEvent;
00063 }
00064 
00065 NDIS_STATUS
00066 ProSendAndFreePnPEvent(
00067    PLOGICAL_ADAPTER Adapter,
00068    PNET_PNP_EVENT   PnPEvent,
00069    PIRP             Irp)
00070 {
00071   PLIST_ENTRY CurrentEntry;
00072   NDIS_STATUS Status;
00073   PADAPTER_BINDING AdapterBinding;
00074 
00075   CurrentEntry = Adapter->ProtocolListHead.Flink;
00076 
00077   while (CurrentEntry != &Adapter->ProtocolListHead)
00078   {
00079      AdapterBinding = CONTAINING_RECORD(CurrentEntry, ADAPTER_BINDING, AdapterListEntry);
00080 
00081      Status = (*AdapterBinding->ProtocolBinding->Chars.PnPEventHandler)(
00082       AdapterBinding->NdisOpenBlock.ProtocolBindingContext,
00083       PnPEvent);
00084 
00085      if (Status == NDIS_STATUS_PENDING)
00086      {
00087          IoMarkIrpPending(Irp);
00088          /* Yes, I know this is stupid */
00089          PnPEvent->NdisReserved[0] = (ULONG_PTR)Irp;
00090          PnPEvent->NdisReserved[1] = (ULONG_PTR)CurrentEntry->Flink;
00091          return NDIS_STATUS_PENDING;
00092      }
00093      else if (Status != NDIS_STATUS_SUCCESS)
00094      {
00095          if (PnPEvent->Buffer) ExFreePool(PnPEvent->Buffer);
00096          ExFreePool(PnPEvent);
00097          return Status;
00098      }
00099 
00100      CurrentEntry = CurrentEntry->Flink;
00101   }
00102 
00103   if (PnPEvent->Buffer) ExFreePool(PnPEvent->Buffer);
00104   ExFreePool(PnPEvent);
00105 
00106   return NDIS_STATUS_SUCCESS;
00107 }
00108 
00109 NTSTATUS
00110 NTAPI
00111 NdisIPwrSetPower(
00112     IN PDEVICE_OBJECT DeviceObject,
00113     PIRP Irp)
00114 {
00115   PLOGICAL_ADAPTER Adapter = (PLOGICAL_ADAPTER)DeviceObject->DeviceExtension;
00116   PNET_PNP_EVENT PnPEvent;
00117   PIO_STACK_LOCATION Stack = IoGetCurrentIrpStackLocation(Irp);
00118 
00119   ASSERT(Stack->Parameters.Power.Type == DevicePowerState);
00120 
00121   PnPEvent = ProSetupPnPEvent(NetEventSetPower, &Stack->Parameters.Power.State, sizeof(NDIS_DEVICE_POWER_STATE));
00122   if (!PnPEvent) {
00123       NDIS_DbgPrint(MIN_TRACE, ("Insufficient resources\n"));
00124       return NDIS_STATUS_RESOURCES;
00125   }
00126 
00127   return ProSendAndFreePnPEvent(Adapter, PnPEvent, Irp);
00128 }
00129 
00130 NTSTATUS
00131 NTAPI
00132 NdisIPwrQueryPower(
00133     IN PDEVICE_OBJECT DeviceObject,
00134     PIRP Irp)
00135 {
00136   PLOGICAL_ADAPTER Adapter = (PLOGICAL_ADAPTER)DeviceObject->DeviceExtension;
00137   PNET_PNP_EVENT PnPEvent;
00138   PIO_STACK_LOCATION Stack = IoGetCurrentIrpStackLocation(Irp);
00139 
00140   ASSERT(Stack->Parameters.Power.Type == DevicePowerState);
00141 
00142   PnPEvent = ProSetupPnPEvent(NetEventQueryPower, &Stack->Parameters.Power.State, sizeof(NDIS_DEVICE_POWER_STATE));
00143   if (!PnPEvent) {
00144       NDIS_DbgPrint(MIN_TRACE, ("Insufficient resources\n"));
00145       return NDIS_STATUS_RESOURCES;
00146   }
00147 
00148   return ProSendAndFreePnPEvent(Adapter, PnPEvent, Irp);
00149 }
00150 
00151 
00152 NTSTATUS
00153 NTAPI
00154 NdisIPnPQueryStopDevice(
00155     IN PDEVICE_OBJECT DeviceObject,
00156     PIRP Irp)
00157 {
00158   PLOGICAL_ADAPTER Adapter = (PLOGICAL_ADAPTER)DeviceObject->DeviceExtension;
00159   PNET_PNP_EVENT PnPEvent;
00160 
00161   PnPEvent = ProSetupPnPEvent(NetEventQueryRemoveDevice, NULL, 0);
00162   if (!PnPEvent) {
00163       NDIS_DbgPrint(MIN_TRACE, ("Insufficient resources\n"));
00164       return NDIS_STATUS_RESOURCES;
00165   }
00166 
00167   return ProSendAndFreePnPEvent(Adapter, PnPEvent, Irp);
00168 }
00169 
00170 NTSTATUS
00171 NTAPI
00172 NdisIPnPCancelStopDevice(
00173     IN PDEVICE_OBJECT DeviceObject,
00174     PIRP Irp)
00175 {
00176   PLOGICAL_ADAPTER Adapter = (PLOGICAL_ADAPTER)DeviceObject->DeviceExtension;
00177   PNET_PNP_EVENT PnPEvent;
00178 
00179   PnPEvent = ProSetupPnPEvent(NetEventCancelRemoveDevice, NULL, 0);
00180   if (!PnPEvent) {
00181       NDIS_DbgPrint(MIN_TRACE, ("Insufficient resources\n"));
00182       return NDIS_STATUS_RESOURCES;
00183   }
00184 
00185   return ProSendAndFreePnPEvent(Adapter, PnPEvent, Irp);
00186 }
00187 
00188 
00189 /*
00190  * @implemented
00191  */
00192 VOID
00193 EXPORT
00194 NdisCompleteBindAdapter(
00195     IN  NDIS_HANDLE BindAdapterContext,
00196     IN  NDIS_STATUS Status,
00197     IN  NDIS_STATUS OpenStatus)
00198 /*
00199  * FUNCTION: Indicates a packet to bound protocols
00200  * ARGUMENTS:
00201  *     Adapter = Pointer to logical adapter
00202  *     Packet  = Pointer to packet to indicate
00203  * RETURNS:
00204  *     Status of operation
00205  * NOTES:
00206  *     - FIXME: partially-implemented
00207  */
00208 {
00209   PROTOCOL_BINDING *Protocol = (PROTOCOL_BINDING *)BindAdapterContext;
00210 
00211   if (!NT_SUCCESS(Status)) {
00212       NDIS_DbgPrint(MIN_TRACE, ("Binding failed (%x)\n", Status));
00213       return;
00214   }
00215 
00216   /* Put protocol binding struct on global list */
00217   ExInterlockedInsertTailList(&ProtocolListHead, &Protocol->ListEntry, &ProtocolListLock);
00218 }
00219 
00220 /*
00221  * @implemented
00222  */
00223 VOID
00224 EXPORT
00225 NdisCompleteUnbindAdapter(
00226     IN  NDIS_HANDLE UnbindAdapterContext,
00227     IN  NDIS_STATUS Status)
00228 {
00229   /* We probably need to do more here but for now we just do
00230    * the opposite of what NdisCompleteBindAdapter does
00231    */
00232 
00233   PROTOCOL_BINDING *Protocol = (PROTOCOL_BINDING *)UnbindAdapterContext;
00234 
00235   if (!NT_SUCCESS(Status)) {
00236       NDIS_DbgPrint(MIN_TRACE, ("Unbinding failed (%x)\n", Status));
00237       return;
00238   }
00239 
00240   ExInterlockedRemoveEntryList(&Protocol->ListEntry, &ProtocolListLock);
00241 }
00242 
00243 
00244 NDIS_STATUS
00245 ProIndicatePacket(
00246     PLOGICAL_ADAPTER Adapter,
00247     PNDIS_PACKET Packet)
00248 /*
00249  * FUNCTION: Indicates a packet to bound protocols
00250  * ARGUMENTS:
00251  *     Adapter = Pointer to logical adapter
00252  *     Packet  = Pointer to packet to indicate
00253  * RETURNS:
00254  *     STATUS_SUCCESS in all cases
00255  * NOTES:
00256  *     - XXX ATM, this only handles loopback packets - is that its designed function?
00257  */
00258 {
00259   UINT BufferedLength;
00260   UINT PacketLength;
00261   KIRQL OldIrql;
00262   PUCHAR LookaheadBuffer;
00263 
00264   NDIS_DbgPrint(MAX_TRACE, ("Called.\n"));
00265 
00266 #if DBG
00267   MiniDisplayPacket(Packet);
00268 #endif
00269 
00270   NdisQueryPacket(Packet, NULL, NULL, NULL, &PacketLength);
00271 
00272   LookaheadBuffer = ExAllocatePool(NonPagedPool, PacketLength);
00273   if (!LookaheadBuffer) {
00274       NDIS_DbgPrint(MIN_TRACE, ("Insufficient resources\n"));
00275       return NDIS_STATUS_RESOURCES;
00276   }
00277 
00278   NDIS_DbgPrint(MAX_TRACE, ("acquiring miniport block lock\n"));
00279   KeAcquireSpinLock(&Adapter->NdisMiniportBlock.Lock, &OldIrql);
00280     {
00281       BufferedLength = CopyPacketToBuffer(LookaheadBuffer, Packet, 0, PacketLength);
00282       Adapter->NdisMiniportBlock.IndicatedPacket[KeGetCurrentProcessorNumber()] = Packet;
00283     }
00284   KeReleaseSpinLock(&Adapter->NdisMiniportBlock.Lock, OldIrql);
00285 
00286   if (BufferedLength > Adapter->MediumHeaderSize)
00287     {
00288       /* XXX Change this to call SendPackets so we don't have to duplicate this wacky logic */
00289       MiniIndicateData(Adapter, NULL, LookaheadBuffer, Adapter->MediumHeaderSize,
00290           &LookaheadBuffer[Adapter->MediumHeaderSize], BufferedLength - Adapter->MediumHeaderSize,
00291           PacketLength - Adapter->MediumHeaderSize);
00292     }
00293   else
00294     {
00295       MiniIndicateData(Adapter, NULL, LookaheadBuffer, Adapter->MediumHeaderSize, NULL, 0, 0);
00296     }
00297 
00298   ExFreePool(LookaheadBuffer);
00299 
00300   KeAcquireSpinLock(&Adapter->NdisMiniportBlock.Lock, &OldIrql);
00301     {
00302       Adapter->NdisMiniportBlock.IndicatedPacket[KeGetCurrentProcessorNumber()] = NULL;
00303     }
00304   KeReleaseSpinLock(&Adapter->NdisMiniportBlock.Lock, OldIrql);
00305 
00306   return NDIS_STATUS_SUCCESS;
00307 }
00308 
00309 
00310 NDIS_STATUS NTAPI
00311 ProRequest(
00312     IN  NDIS_HANDLE     MacBindingHandle,
00313     IN  PNDIS_REQUEST   NdisRequest)
00314 /*
00315  * FUNCTION: Forwards a request to an NDIS miniport
00316  * ARGUMENTS:
00317  *     MacBindingHandle = Adapter binding handle
00318  *     NdisRequest      = Pointer to request to perform
00319  * RETURNS:
00320  *     Status of operation
00321  */
00322 {
00323   PADAPTER_BINDING AdapterBinding;
00324   PLOGICAL_ADAPTER Adapter;
00325   PNDIS_REQUEST_MAC_BLOCK MacBlock = (PNDIS_REQUEST_MAC_BLOCK)NdisRequest->MacReserved;
00326 
00327   NDIS_DbgPrint(MAX_TRACE, ("Called.\n"));
00328 
00329   ASSERT(MacBindingHandle);
00330   AdapterBinding = GET_ADAPTER_BINDING(MacBindingHandle);
00331 
00332   ASSERT(AdapterBinding->Adapter);
00333   Adapter = AdapterBinding->Adapter;
00334 
00335   MacBlock->Binding = &AdapterBinding->NdisOpenBlock;
00336 
00337 #if WORKER_TEST
00338   MiniQueueWorkItem(Adapter, NdisWorkItemRequest, NdisRequest, FALSE);
00339   return NDIS_STATUS_PENDING;
00340 #else
00341   if (MiniIsBusy(Adapter, NdisWorkItemRequest)) {
00342       MiniQueueWorkItem(Adapter, NdisWorkItemRequest, NdisRequest, FALSE);
00343       return NDIS_STATUS_PENDING;
00344   }
00345 
00346   return MiniDoRequest(Adapter, NdisRequest);
00347 #endif
00348 }
00349 
00350 
00351 NDIS_STATUS NTAPI
00352 ProReset(
00353     IN  NDIS_HANDLE MacBindingHandle)
00354 {
00355     PADAPTER_BINDING AdapterBinding = MacBindingHandle;
00356 
00357     /* FIXME: Wait for all packets to be sent */
00358 
00359     return MiniReset(AdapterBinding->Adapter);
00360 }
00361 
00362 VOID NTAPI
00363 ScatterGatherSendPacket(
00364    IN PDEVICE_OBJECT DeviceObject,
00365    IN PIRP Irp,
00366    IN PSCATTER_GATHER_LIST ScatterGather,
00367    IN PVOID Context)
00368 {
00369    PDMA_CONTEXT DmaContext = Context;
00370    PLOGICAL_ADAPTER Adapter = DmaContext->Adapter;
00371    PNDIS_PACKET Packet = DmaContext->Packet;
00372    NDIS_STATUS Status;
00373 
00374    NDIS_DbgPrint(MAX_TRACE, ("Called.\n"));
00375 
00376    NDIS_PER_PACKET_INFO_FROM_PACKET(Packet,
00377                                     ScatterGatherListPacketInfo) = ScatterGather;
00378 
00379    Status = proSendPacketToMiniport(Adapter, Packet);
00380 
00381    if (Status != NDIS_STATUS_PENDING) {
00382        NDIS_DbgPrint(MAX_TRACE, ("Completing packet.\n"));
00383        MiniSendComplete(Adapter,
00384                         Packet,
00385                         Status);
00386    }
00387 
00388    ExFreePool(DmaContext);
00389 }
00390 
00391 NDIS_STATUS
00392 proSendPacketToMiniport(PLOGICAL_ADAPTER Adapter, PNDIS_PACKET Packet)
00393 {
00394 #if WORKER_TEST
00395    MiniQueueWorkItem(Adapter, NdisWorkItemSend, Packet, FALSE);
00396    return NDIS_STATUS_PENDING;
00397 #else
00398    KIRQL RaiseOldIrql;
00399    NDIS_STATUS NdisStatus;
00400 
00401    if(MiniIsBusy(Adapter, NdisWorkItemSend)) {
00402       MiniQueueWorkItem(Adapter, NdisWorkItemSend, Packet, FALSE);
00403       return NDIS_STATUS_PENDING;
00404    }
00405 
00406    if(Adapter->NdisMiniportBlock.DriverHandle->MiniportCharacteristics.SendPacketsHandler)
00407    {
00408         if(Adapter->NdisMiniportBlock.Flags & NDIS_ATTRIBUTE_DESERIALIZE)
00409         {
00410             NDIS_DbgPrint(MAX_TRACE, ("Calling miniport's SendPackets handler\n"));
00411             (*Adapter->NdisMiniportBlock.DriverHandle->MiniportCharacteristics.SendPacketsHandler)(
00412              Adapter->NdisMiniportBlock.MiniportAdapterContext, &Packet, 1);
00413              NdisStatus = NDIS_STATUS_PENDING;
00414         } else {
00415             /* SendPackets is called at DISPATCH_LEVEL for all serialized miniports */
00416             KeRaiseIrql(DISPATCH_LEVEL, &RaiseOldIrql);
00417             {
00418                NDIS_DbgPrint(MAX_TRACE, ("Calling miniport's SendPackets handler\n"));
00419                (*Adapter->NdisMiniportBlock.DriverHandle->MiniportCharacteristics.SendPacketsHandler)(
00420                 Adapter->NdisMiniportBlock.MiniportAdapterContext, &Packet, 1);
00421             }
00422             KeLowerIrql(RaiseOldIrql);
00423 
00424             NdisStatus = NDIS_GET_PACKET_STATUS(Packet);
00425             if (NdisStatus == NDIS_STATUS_RESOURCES) {
00426                 MiniQueueWorkItem(Adapter, NdisWorkItemSend, Packet, TRUE);
00427                 NdisStatus = NDIS_STATUS_PENDING;
00428             }
00429         }
00430 
00431         return NdisStatus;
00432    } else {
00433         if(Adapter->NdisMiniportBlock.Flags & NDIS_ATTRIBUTE_DESERIALIZE)
00434         {
00435             NDIS_DbgPrint(MAX_TRACE, ("Calling miniport's Send handler\n"));
00436             NdisStatus = (*Adapter->NdisMiniportBlock.DriverHandle->MiniportCharacteristics.SendHandler)(
00437                           Adapter->NdisMiniportBlock.MiniportAdapterContext, Packet, Packet->Private.Flags);
00438             NDIS_DbgPrint(MAX_TRACE, ("back from miniport's send handler\n"));
00439         } else {
00440             /* Send is called at DISPATCH_LEVEL for all serialized miniports */
00441             KeRaiseIrql(DISPATCH_LEVEL, &RaiseOldIrql);
00442             NDIS_DbgPrint(MAX_TRACE, ("Calling miniport's Send handler\n"));
00443             NdisStatus = (*Adapter->NdisMiniportBlock.DriverHandle->MiniportCharacteristics.SendHandler)(
00444                           Adapter->NdisMiniportBlock.MiniportAdapterContext, Packet, Packet->Private.Flags);
00445             NDIS_DbgPrint(MAX_TRACE, ("back from miniport's send handler\n"));
00446             KeLowerIrql(RaiseOldIrql);
00447 
00448             if (NdisStatus == NDIS_STATUS_RESOURCES) {
00449                 MiniQueueWorkItem(Adapter, NdisWorkItemSend, Packet, TRUE);
00450                 NdisStatus = NDIS_STATUS_PENDING;
00451             }
00452         }
00453 
00454         return NdisStatus;
00455    }
00456 #endif
00457 }
00458 
00459 
00460 NDIS_STATUS NTAPI
00461 ProSend(
00462     IN  NDIS_HANDLE     MacBindingHandle,
00463     IN  PNDIS_PACKET    Packet)
00464 /*
00465  * FUNCTION: Forwards a request to send a packet to an NDIS miniport
00466  * ARGUMENTS:
00467  *     MacBindingHandle = Adapter binding handle
00468  *     Packet           = Pointer to NDIS packet descriptor
00469  * RETURNS:
00470  *     NDIS_STATUS_SUCCESS if the packet was successfully sent
00471  *     NDIS_STATUS_PENDING if the miniport was busy or a serialized miniport returned NDIS_STATUS_RESOURCES
00472  */
00473 {
00474   PADAPTER_BINDING AdapterBinding;
00475   PLOGICAL_ADAPTER Adapter;
00476   PNDIS_BUFFER NdisBuffer;
00477   PDMA_CONTEXT Context;
00478   NDIS_STATUS NdisStatus;
00479   UINT PacketLength;
00480   KIRQL OldIrql;
00481 
00482   NDIS_DbgPrint(MAX_TRACE, ("Called.\n"));
00483 
00484   ASSERT(MacBindingHandle);
00485   AdapterBinding = GET_ADAPTER_BINDING(MacBindingHandle);
00486 
00487   ASSERT(AdapterBinding);
00488   Adapter = AdapterBinding->Adapter;
00489 
00490   ASSERT(Adapter);
00491 
00492   /* if the following is not true, KeRaiseIrql() below will break */
00493   ASSERT(KeGetCurrentIrql() <= DISPATCH_LEVEL);
00494 
00495   /* XXX what is this crazy black magic? */
00496   Packet->Reserved[1] = (ULONG_PTR)MacBindingHandle;
00497 
00498   /*
00499    * Test the packet to see if it is a MAC loopback.
00500    *
00501    * We may have to loop this packet if miniport cannot.
00502    * If dest MAC address of packet == MAC address of adapter,
00503    * this is a loopback frame.
00504    */
00505 
00506   if ((Adapter->NdisMiniportBlock.MacOptions & NDIS_MAC_OPTION_NO_LOOPBACK) &&
00507       MiniAdapterHasAddress(Adapter, Packet))
00508     {
00509 #if WORKER_TEST
00510         MiniQueueWorkItem(Adapter, NdisWorkItemSendLoopback, Packet, FALSE);
00511         return NDIS_STATUS_PENDING;
00512 #else
00513         return ProIndicatePacket(Adapter, Packet);
00514 #endif
00515     } else {
00516         if (Adapter->NdisMiniportBlock.ScatterGatherListSize != 0)
00517         {
00518             NDIS_DbgPrint(MID_TRACE, ("Using Scatter/Gather DMA\n"));
00519 
00520             NdisQueryPacket(Packet,
00521                             NULL,
00522                             NULL,
00523                             &NdisBuffer,
00524                             &PacketLength);
00525 
00526             Context = ExAllocatePool(NonPagedPool, sizeof(DMA_CONTEXT));
00527             if (!Context) {
00528                 NDIS_DbgPrint(MIN_TRACE, ("Insufficient resources\n"));
00529                 return NDIS_STATUS_RESOURCES;
00530             }
00531 
00532             Context->Adapter = Adapter;
00533             Context->Packet = Packet;
00534 
00535             KeRaiseIrql(DISPATCH_LEVEL, &OldIrql);
00536 
00537             KeFlushIoBuffers(NdisBuffer, FALSE, TRUE);
00538 
00539             NdisStatus = Adapter->NdisMiniportBlock.SystemAdapterObject->DmaOperations->GetScatterGatherList(
00540                           Adapter->NdisMiniportBlock.SystemAdapterObject,
00541                           Adapter->NdisMiniportBlock.PhysicalDeviceObject,
00542                           NdisBuffer,
00543                           MmGetMdlVirtualAddress(NdisBuffer),
00544                           PacketLength,
00545                           ScatterGatherSendPacket,
00546                           Context,
00547                           TRUE);
00548 
00549             KeLowerIrql(OldIrql);
00550 
00551             if (!NT_SUCCESS(NdisStatus)) {
00552                 NDIS_DbgPrint(MIN_TRACE, ("GetScatterGatherList failed! (%x)\n", NdisStatus));
00553                 return NdisStatus;
00554             }
00555 
00556             return NDIS_STATUS_PENDING;
00557         }
00558 
00559 
00560         return proSendPacketToMiniport(Adapter, Packet);
00561     }
00562 }
00563 
00564 
00565 VOID NTAPI
00566 ProSendPackets(
00567     IN  NDIS_HANDLE     NdisBindingHandle,
00568     IN  PPNDIS_PACKET   PacketArray,
00569     IN  UINT            NumberOfPackets)
00570 {
00571     PADAPTER_BINDING AdapterBinding = NdisBindingHandle;
00572     PLOGICAL_ADAPTER Adapter = AdapterBinding->Adapter;
00573     KIRQL RaiseOldIrql;
00574     NDIS_STATUS NdisStatus;
00575     UINT i;
00576 
00577     if(Adapter->NdisMiniportBlock.DriverHandle->MiniportCharacteristics.SendPacketsHandler)
00578     {
00579        if(Adapter->NdisMiniportBlock.Flags & NDIS_ATTRIBUTE_DESERIALIZE)
00580        {
00581           (*Adapter->NdisMiniportBlock.DriverHandle->MiniportCharacteristics.SendPacketsHandler)(
00582            Adapter->NdisMiniportBlock.MiniportAdapterContext, PacketArray, NumberOfPackets);
00583        }
00584        else
00585        {
00586           /* SendPackets is called at DISPATCH_LEVEL for all serialized miniports */
00587           KeRaiseIrql(DISPATCH_LEVEL, &RaiseOldIrql);
00588           (*Adapter->NdisMiniportBlock.DriverHandle->MiniportCharacteristics.SendPacketsHandler)(
00589            Adapter->NdisMiniportBlock.MiniportAdapterContext, PacketArray, NumberOfPackets);
00590           KeLowerIrql(RaiseOldIrql);
00591           for (i = 0; i < NumberOfPackets; i++)
00592           {
00593              NdisStatus = NDIS_GET_PACKET_STATUS(PacketArray[i]);
00594              if (NdisStatus != NDIS_STATUS_PENDING)
00595                  MiniSendComplete(Adapter, PacketArray[i], NdisStatus);
00596           }
00597        }
00598      }
00599      else
00600      {
00601        if(Adapter->NdisMiniportBlock.Flags & NDIS_ATTRIBUTE_DESERIALIZE)
00602        {  
00603           for (i = 0; i < NumberOfPackets; i++)
00604           {
00605              NdisStatus = (*Adapter->NdisMiniportBlock.DriverHandle->MiniportCharacteristics.SendHandler)(
00606                            Adapter->NdisMiniportBlock.MiniportAdapterContext, PacketArray[i], PacketArray[i]->Private.Flags);
00607              if (NdisStatus != NDIS_STATUS_PENDING)
00608                  MiniSendComplete(Adapter, PacketArray[i], NdisStatus);
00609           }
00610        }
00611        else
00612        {
00613          /* Send is called at DISPATCH_LEVEL for all serialized miniports */
00614          KeRaiseIrql(DISPATCH_LEVEL, &RaiseOldIrql);
00615          for (i = 0; i < NumberOfPackets; i++)
00616          {
00617             NdisStatus = (*Adapter->NdisMiniportBlock.DriverHandle->MiniportCharacteristics.SendHandler)(
00618                            Adapter->NdisMiniportBlock.MiniportAdapterContext, PacketArray[i], PacketArray[i]->Private.Flags);
00619             if (NdisStatus != NDIS_STATUS_PENDING)
00620                 MiniSendComplete(Adapter, PacketArray[i], NdisStatus);
00621          }
00622          KeLowerIrql(RaiseOldIrql);
00623        }
00624      }
00625 }
00626 
00627 
00628 NDIS_STATUS NTAPI
00629 ProTransferData(
00630     IN  NDIS_HANDLE         MacBindingHandle,
00631     IN  NDIS_HANDLE         MacReceiveContext,
00632     IN  UINT                ByteOffset,
00633     IN  UINT                BytesToTransfer,
00634     IN  OUT PNDIS_PACKET    Packet,
00635     OUT PUINT               BytesTransferred)
00636 /*
00637  * FUNCTION: Forwards a request to copy received data into a protocol-supplied packet
00638  * ARGUMENTS:
00639  *     MacBindingHandle  = Adapter binding handle
00640  *     MacReceiveContext = MAC receive context
00641  *     ByteOffset        = Offset in packet to place data
00642  *     BytesToTransfer   = Number of bytes to copy into packet
00643  *     Packet            = Pointer to NDIS packet descriptor
00644  *     BytesTransferred  = Address of buffer to place number of bytes copied
00645  */
00646 {
00647     PADAPTER_BINDING AdapterBinding = GET_ADAPTER_BINDING(MacBindingHandle);
00648     PLOGICAL_ADAPTER Adapter        = AdapterBinding->Adapter;
00649     NDIS_STATUS Status;
00650     KIRQL OldIrql;
00651 
00652     NDIS_DbgPrint(MAX_TRACE, ("Called.\n"));
00653 
00654     /* FIXME: Interrupts must be disabled for adapter */
00655     /* XXX sd - why is that true? */
00656 
00657     if (Adapter->NdisMiniportBlock.IndicatedPacket[KeGetCurrentProcessorNumber()]) {
00658     NDIS_DbgPrint(MAX_TRACE, ("LoopPacket\n"));
00659         /* NDIS is responsible for looping this packet */
00660         NdisCopyFromPacketToPacket(Packet,
00661                                    ByteOffset + Adapter->MediumHeaderSize,
00662                                    BytesToTransfer + Adapter->MediumHeaderSize,
00663                                    Adapter->NdisMiniportBlock.IndicatedPacket[KeGetCurrentProcessorNumber()],
00664                                    0,
00665                                    BytesTransferred);
00666         return NDIS_STATUS_SUCCESS;
00667     }
00668 
00669     ASSERT(Adapter->NdisMiniportBlock.DriverHandle->MiniportCharacteristics.TransferDataHandler);
00670 
00671     KeRaiseIrql(DISPATCH_LEVEL, &OldIrql);
00672 
00673     Status = (*Adapter->NdisMiniportBlock.DriverHandle->MiniportCharacteristics.TransferDataHandler)(
00674         Packet,
00675         BytesTransferred,
00676         Adapter->NdisMiniportBlock.MiniportAdapterContext,
00677         MacReceiveContext,
00678         ByteOffset,
00679         BytesToTransfer);
00680 
00681     KeLowerIrql(OldIrql);
00682 
00683     return Status;
00684 }
00685 
00686 
00687 
00688 /*
00689  * @implemented
00690  */
00691 VOID
00692 EXPORT
00693 NdisCloseAdapter(
00694     OUT PNDIS_STATUS    Status,
00695     IN  NDIS_HANDLE     NdisBindingHandle)
00696 /*
00697  * FUNCTION: Closes an adapter opened with NdisOpenAdapter
00698  * ARGUMENTS:
00699  *     Status            = Address of buffer for status information
00700  *     NdisBindingHandle = Handle returned by NdisOpenAdapter
00701  */
00702 {
00703     PADAPTER_BINDING AdapterBinding = GET_ADAPTER_BINDING(NdisBindingHandle);
00704 
00705     NDIS_DbgPrint(MAX_TRACE, ("Called.\n"));
00706 
00707     /* Remove from protocol's bound adapters list */
00708     ExInterlockedRemoveEntryList(&AdapterBinding->ProtocolListEntry, &AdapterBinding->ProtocolBinding->Lock);
00709 
00710     /* Remove protocol from adapter's bound protocols list */
00711     ExInterlockedRemoveEntryList(&AdapterBinding->AdapterListEntry, &AdapterBinding->Adapter->NdisMiniportBlock.Lock);
00712 
00713     ExFreePool(AdapterBinding);
00714 
00715     *Status = NDIS_STATUS_SUCCESS;
00716 }
00717 
00718 
00719 /*
00720  * @implemented
00721  */
00722 VOID
00723 EXPORT
00724 NdisDeregisterProtocol(
00725     OUT PNDIS_STATUS    Status,
00726     IN NDIS_HANDLE      NdisProtocolHandle)
00727 /*
00728  * FUNCTION: Releases the resources allocated by NdisRegisterProtocol
00729  * ARGUMENTS:
00730  *     Status             = Address of buffer for status information
00731  *     NdisProtocolHandle = Handle returned by NdisRegisterProtocol
00732  */
00733 {
00734     PPROTOCOL_BINDING Protocol = GET_PROTOCOL_BINDING(NdisProtocolHandle);
00735 
00736     NDIS_DbgPrint(MAX_TRACE, ("Called.\n"));
00737 
00738     /* FIXME: Make sure no adapter bindings exist */
00739 
00740     /* Remove protocol from global list */
00741     ExInterlockedRemoveEntryList(&Protocol->ListEntry, &ProtocolListLock);
00742 
00743     ExFreePool(Protocol);
00744 
00745     *Status = NDIS_STATUS_SUCCESS;
00746 }
00747 
00748 
00749 /*
00750  * @implemented
00751  */
00752 VOID
00753 EXPORT
00754 NdisOpenAdapter(
00755     OUT PNDIS_STATUS    Status,
00756     OUT PNDIS_STATUS    OpenErrorStatus,
00757     OUT PNDIS_HANDLE    NdisBindingHandle,
00758     OUT PUINT           SelectedMediumIndex,
00759     IN  PNDIS_MEDIUM    MediumArray,
00760     IN  UINT            MediumArraySize,
00761     IN  NDIS_HANDLE     NdisProtocolHandle,
00762     IN  NDIS_HANDLE     ProtocolBindingContext,
00763     IN  PNDIS_STRING    AdapterName,
00764     IN  UINT            OpenOptions,
00765     IN  PSTRING         AddressingInformation   OPTIONAL)
00766 /*
00767  * FUNCTION: Opens an adapter for communication
00768  * ARGUMENTS:
00769  *     Status                 = Address of buffer for status information
00770  *     OpenErrorStatus        = Address of buffer for secondary error code
00771  *     NdisBindingHandle      = Address of buffer for adapter binding handle
00772  *     SelectedMediumIndex    = Address of buffer for selected medium
00773  *     MediumArray            = Pointer to an array of NDIS_MEDIUMs called can support
00774  *     MediumArraySize        = Number of elements in MediumArray
00775  *     NdisProtocolHandle     = Handle returned by NdisRegisterProtocol
00776  *     ProtocolBindingContext = Pointer to caller suplied context area
00777  *     AdapterName            = Pointer to buffer with name of adapter
00778  *     OpenOptions            = Bitmask with flags passed to next-lower driver
00779  *     AddressingInformation  = Optional pointer to buffer with NIC specific information
00780  */
00781 {
00782   UINT i;
00783   BOOLEAN Found;
00784   PLOGICAL_ADAPTER Adapter;
00785   PADAPTER_BINDING AdapterBinding;
00786   PPROTOCOL_BINDING Protocol = GET_PROTOCOL_BINDING(NdisProtocolHandle);
00787 
00788   NDIS_DbgPrint(MAX_TRACE, ("Called.\n"));
00789 
00790   if(!NdisProtocolHandle)
00791     {
00792       NDIS_DbgPrint(MIN_TRACE, ("NdisProtocolHandle is NULL\n"));
00793       *OpenErrorStatus = *Status = NDIS_STATUS_FAILURE;
00794       return;
00795     }
00796 
00797   Adapter = MiniLocateDevice(AdapterName);
00798   if (!Adapter)
00799     {
00800       NDIS_DbgPrint(MIN_TRACE, ("Adapter not found.\n"));
00801       *Status = NDIS_STATUS_ADAPTER_NOT_FOUND;
00802       return;
00803     }
00804 
00805   /* Find the media type in the list provided by the protocol driver */
00806   Found = FALSE;
00807   for (i = 0; i < MediumArraySize; i++)
00808     {
00809       if (Adapter->NdisMiniportBlock.MediaType == MediumArray[i])
00810         {
00811           *SelectedMediumIndex = i;
00812           Found = TRUE;
00813           break;
00814         }
00815     }
00816 
00817   if (!Found)
00818     {
00819       NDIS_DbgPrint(MIN_TRACE, ("Medium is not supported.\n"));
00820       *Status = NDIS_STATUS_UNSUPPORTED_MEDIA;
00821       return;
00822     }
00823 
00824   /* Now that we have confirmed that the adapter can be opened, create a binding */
00825 
00826   AdapterBinding = ExAllocatePool(NonPagedPool, sizeof(ADAPTER_BINDING));
00827   if (!AdapterBinding)
00828     {
00829       NDIS_DbgPrint(MIN_TRACE, ("Insufficient resources.\n"));
00830       *Status = NDIS_STATUS_RESOURCES;
00831       return;
00832     }
00833 
00834   RtlZeroMemory(AdapterBinding, sizeof(ADAPTER_BINDING));
00835 
00836   AdapterBinding->ProtocolBinding        = Protocol;
00837   AdapterBinding->Adapter                = Adapter;
00838   AdapterBinding->NdisOpenBlock.ProtocolBindingContext = ProtocolBindingContext;
00839 
00840   /* Set fields required by some NDIS macros */
00841   AdapterBinding->NdisOpenBlock.BindingHandle = (NDIS_HANDLE)AdapterBinding;
00842 
00843   /* Set handlers (some NDIS macros require these) */
00844 
00845   AdapterBinding->NdisOpenBlock.RequestHandler      = ProRequest;
00846   AdapterBinding->NdisOpenBlock.ResetHandler        = ProReset;
00847   AdapterBinding->NdisOpenBlock.SendHandler         = ProSend;
00848   AdapterBinding->NdisOpenBlock.SendPacketsHandler  = ProSendPackets;
00849   AdapterBinding->NdisOpenBlock.TransferDataHandler = ProTransferData;
00850 
00851   AdapterBinding->NdisOpenBlock.RequestCompleteHandler =
00852     Protocol->Chars.RequestCompleteHandler;
00853 
00854   /* Put on protocol's bound adapters list */
00855   ExInterlockedInsertTailList(&Protocol->AdapterListHead, &AdapterBinding->ProtocolListEntry, &Protocol->Lock);
00856 
00857   /* Put protocol on adapter's bound protocols list */
00858   NDIS_DbgPrint(MAX_TRACE, ("acquiring miniport block lock\n"));
00859   ExInterlockedInsertTailList(&Adapter->ProtocolListHead, &AdapterBinding->AdapterListEntry, &Adapter->NdisMiniportBlock.Lock);
00860 
00861   *NdisBindingHandle = (NDIS_HANDLE)AdapterBinding;
00862 
00863   *Status = NDIS_STATUS_SUCCESS;
00864 }
00865 
00866 PADAPTER_BINDING
00867 NTAPI
00868 LocateAdapterBindingByName(IN PPROTOCOL_BINDING ProtocolBinding, IN PNDIS_STRING AdapterName)
00869 {
00870     PLIST_ENTRY CurrentEntry;
00871     PADAPTER_BINDING AdapterBinding;
00872     KIRQL OldIrql;
00873 
00874     KeAcquireSpinLock(&ProtocolBinding->Lock, &OldIrql);
00875 
00876     CurrentEntry = ProtocolBinding->AdapterListHead.Flink;
00877 
00878     while (CurrentEntry != &ProtocolBinding->AdapterListHead)
00879     {
00880          AdapterBinding = CONTAINING_RECORD(CurrentEntry, ADAPTER_BINDING, ProtocolListEntry);
00881 
00882          if (RtlCompareUnicodeString(AdapterName, &AdapterBinding->Adapter->NdisMiniportBlock.MiniportName, TRUE) == 0)
00883          {
00884              KeReleaseSpinLock(&ProtocolBinding->Lock, OldIrql);
00885              return AdapterBinding;
00886          }
00887 
00888          CurrentEntry = CurrentEntry->Flink;
00889     }
00890 
00891     KeReleaseSpinLock(&ProtocolBinding->Lock, OldIrql);
00892 
00893     return NULL;
00894 }
00895 
00896 VOID
00897 NTAPI
00898 ndisBindMiniportsToProtocol(OUT PNDIS_STATUS Status, IN PPROTOCOL_BINDING Protocol)
00899 {
00900   /*
00901    * bind the protocol to all of its miniports
00902    *
00903    * open registry path
00904    * get list of devices from Bind key
00905    * call BindAdapterHandler for each
00906    */
00907     OBJECT_ATTRIBUTES ObjectAttributes;
00908     UNICODE_STRING RegistryPath;
00909     WCHAR *RegistryPathStr, *DataPtr = NULL;
00910     NTSTATUS NtStatus;
00911     HANDLE DriverKeyHandle = NULL;
00912     PKEY_VALUE_PARTIAL_INFORMATION KeyInformation = NULL;
00913     PNDIS_PROTOCOL_CHARACTERISTICS ProtocolCharacteristics = &Protocol->Chars;
00914     UNICODE_STRING ValueName;
00915     ULONG ResultLength;
00916     PLIST_ENTRY CurrentEntry = NULL;
00917 
00918     RegistryPathStr = ExAllocatePoolWithTag(PagedPool, sizeof(SERVICES_KEY) + ProtocolCharacteristics->Name.Length + sizeof(LINKAGE_KEY), NDIS_TAG + __LINE__);
00919     if(!RegistryPathStr)
00920     {
00921         NDIS_DbgPrint(MIN_TRACE, ("Insufficient resources.\n"));
00922         *Status = NDIS_STATUS_RESOURCES;
00923         return;
00924     }
00925 
00926     wcscpy(RegistryPathStr, SERVICES_KEY);
00927     wcsncat(RegistryPathStr, ((WCHAR *)ProtocolCharacteristics->Name.Buffer), ProtocolCharacteristics->Name.Length / sizeof(WCHAR));
00928     RegistryPathStr[wcslen(SERVICES_KEY)+ProtocolCharacteristics->Name.Length/sizeof(WCHAR)] = 0;
00929     wcscat(RegistryPathStr, LINKAGE_KEY);
00930 
00931     RtlInitUnicodeString(&RegistryPath, RegistryPathStr);
00932     NDIS_DbgPrint(MAX_TRACE, ("Opening configuration key: %wZ\n", &RegistryPath));
00933 
00934     InitializeObjectAttributes(&ObjectAttributes, &RegistryPath, OBJ_CASE_INSENSITIVE, NULL, NULL);
00935     NtStatus = ZwOpenKey(&DriverKeyHandle, KEY_READ, &ObjectAttributes);
00936 
00937     ExFreePool(RegistryPathStr);
00938 
00939     if(NT_SUCCESS(NtStatus))
00940     {
00941         NDIS_DbgPrint(MAX_TRACE, ("Successfully opened the registry configuration\n"));
00942 
00943         RtlInitUnicodeString(&ValueName, L"Bind");
00944 
00945         NtStatus = ZwQueryValueKey(DriverKeyHandle, &ValueName, KeyValuePartialInformation, NULL, 0, &ResultLength);
00946         if(NtStatus != STATUS_BUFFER_OVERFLOW && NtStatus != STATUS_BUFFER_TOO_SMALL && NtStatus != STATUS_SUCCESS)
00947         {
00948             NDIS_DbgPrint(MIN_TRACE, ("Unable to query the Bind value for size\n"));
00949             ZwClose(DriverKeyHandle);
00950         }
00951         else
00952         {
00953             KeyInformation = ExAllocatePoolWithTag(PagedPool, sizeof(KEY_VALUE_PARTIAL_INFORMATION) + ResultLength, NDIS_TAG + __LINE__);
00954             if(!KeyInformation)
00955             {
00956                 NDIS_DbgPrint(MIN_TRACE, ("Insufficient resources.\n"));
00957                 ZwClose(DriverKeyHandle);
00958                 NtStatus = STATUS_NO_MEMORY;
00959             }
00960             else
00961             {
00962                 NtStatus = ZwQueryValueKey(DriverKeyHandle, &ValueName, KeyValuePartialInformation, KeyInformation,
00963                                            sizeof(KEY_VALUE_PARTIAL_INFORMATION) + ResultLength, &ResultLength);
00964 
00965                 ZwClose(DriverKeyHandle);
00966 
00967                 if(!NT_SUCCESS(NtStatus))
00968                 {
00969                     NDIS_DbgPrint(MIN_TRACE, ("Unable to query the Bind value\n"));
00970                     ExFreePool(KeyInformation);
00971                     KeyInformation = NULL;
00972                 }
00973             }
00974         }
00975     }
00976 
00977     if (!NT_SUCCESS(NtStatus))
00978     {
00979         NDIS_DbgPrint(MIN_TRACE, ("Performing global bind for protocol '%wZ'\n", &ProtocolCharacteristics->Name));
00980         KeyInformation = NULL;
00981 
00982         CurrentEntry = AdapterListHead.Flink;
00983     }
00984     else
00985     {
00986         NDIS_DbgPrint(MIN_TRACE, ("Performing standard bind for protocol '%wZ'\n", &ProtocolCharacteristics->Name));
00987 
00988         DataPtr = (WCHAR*)KeyInformation->Data;
00989     }
00990 
00991     /* Assume success for now */
00992     *Status = NDIS_STATUS_SUCCESS;
00993 
00994     while (TRUE)
00995     {
00996         /* BindContext is for tracking pending binding operations */
00997         VOID *BindContext = 0;
00998         NDIS_STRING DeviceName;
00999         NDIS_STRING RegistryPath;
01000         WCHAR *RegistryPathStr = NULL;
01001         ULONG PathLength = 0;
01002         PLOGICAL_ADAPTER Adapter;
01003 
01004         if (KeyInformation)
01005         {
01006             /* Parse the REG_MULTI_SZ entry for device names */
01007             if (!(*DataPtr))
01008                 break;
01009 
01010             RtlInitUnicodeString(&DeviceName, DataPtr);
01011         }
01012         else
01013         {
01014             /* Use the device name from the global adapter list */
01015             if (CurrentEntry == &AdapterListHead)
01016                 break;
01017 
01018             Adapter = CONTAINING_RECORD(CurrentEntry, LOGICAL_ADAPTER, ListEntry);
01019 
01020             DeviceName = Adapter->NdisMiniportBlock.MiniportName;
01021         }
01022 
01023         /* Make sure the adapter has started */
01024         if (!MiniLocateDevice(&DeviceName))
01025         {
01026             /* It wasn't in the global miniport list, so skip the bind entry */
01027             goto next;
01028         }
01029         
01030         /* Make sure this device isn't already bound to this protocol */
01031         if (LocateAdapterBindingByName(Protocol, &DeviceName))
01032         {
01033             /* It was already in this protocol's bound adapter list, so skip the bind entry */
01034             goto next;
01035         }
01036 
01037         /*
01038          * RegistryPath should be:
01039          *     \Registry\Machine\System\CurrentControlSet\Services\Nic1\Parameters\Tcpip
01040          *
01041          *  This is constructed as follows:
01042          *      SERVICES_KEY + extracted device name + Protocol name from characteristics
01043          */
01044 
01045         PathLength = sizeof(SERVICES_KEY) +                               /* \Registry\Machine\System\CurrentControlSet\Services\ */
01046         wcslen( DeviceName.Buffer + 8 ) * sizeof(WCHAR) + /* Adapter1  (extracted from \Device\Adapter1)          */
01047         sizeof(PARAMETERS_KEY) +                                      /* \Parameters\                                         */
01048         ProtocolCharacteristics->Name.Length + sizeof(WCHAR);                         /* Tcpip                                                */
01049 
01050         RegistryPathStr = ExAllocatePool(PagedPool, PathLength);
01051         if(!RegistryPathStr)
01052         {
01053             NDIS_DbgPrint(MIN_TRACE, ("insufficient resources.\n"));
01054             *Status = NDIS_STATUS_RESOURCES;
01055             break;
01056         }
01057 
01058         wcscpy(RegistryPathStr, SERVICES_KEY);
01059         wcscat(RegistryPathStr, DeviceName.Buffer + 8 );
01060         wcscat(RegistryPathStr, PARAMETERS_KEY);
01061         wcsncat(RegistryPathStr, ProtocolCharacteristics->Name.Buffer, ProtocolCharacteristics->Name.Length / sizeof(WCHAR) );
01062 
01063         RegistryPathStr[PathLength/sizeof(WCHAR) - 1] = 0;
01064 
01065         RtlInitUnicodeString(&RegistryPath, RegistryPathStr);
01066 
01067         NDIS_DbgPrint(MAX_TRACE, ("Calling protocol's BindAdapter handler with DeviceName %wZ and RegistryPath %wZ\n",
01068                                   &DeviceName, &RegistryPath));
01069 
01070         {
01071             BIND_HANDLER BindHandler = ProtocolCharacteristics->BindAdapterHandler;
01072             if(BindHandler)
01073             {
01074                 BindHandler(Status, BindContext, &DeviceName, &RegistryPath, 0);
01075                 NDIS_DbgPrint(MIN_TRACE, ("%wZ's BindAdapter handler returned 0x%x for %wZ\n", &ProtocolCharacteristics->Name, *Status, &DeviceName));
01076             }
01077             else
01078                 NDIS_DbgPrint(MIN_TRACE, ("No protocol bind handler specified\n"));
01079         }
01080 
01081     next:
01082         if (KeyInformation)
01083         {
01084             /* Advance to the next adapter in the REG_MULTI_SZ */
01085             DataPtr += (DeviceName.Length / sizeof(WCHAR)) + 1;
01086         }
01087         else
01088         {
01089             /* Advance to the next adapter in the global list */
01090             CurrentEntry = CurrentEntry->Flink;
01091         }
01092     }
01093 
01094     if (KeyInformation)
01095     {
01096         ExFreePool(KeyInformation);
01097     }
01098 }
01099 
01100 /*
01101  * @implemented
01102  */
01103 VOID
01104 EXPORT
01105 NdisRegisterProtocol(
01106     OUT PNDIS_STATUS                    Status,
01107     OUT PNDIS_HANDLE                    NdisProtocolHandle,
01108     IN  PNDIS_PROTOCOL_CHARACTERISTICS  ProtocolCharacteristics,
01109     IN  UINT                            CharacteristicsLength)
01110 /*
01111  * FUNCTION: Registers an NDIS driver's ProtocolXxx entry points
01112  * ARGUMENTS:
01113  *     Status                  = Address of buffer for status information
01114  *     NdisProtocolHandle      = Address of buffer for handle used to identify the driver
01115  *     ProtocolCharacteristics = Pointer to NDIS_PROTOCOL_CHARACTERISTICS structure
01116  *     CharacteristicsLength   = Size of structure which ProtocolCharacteristics targets
01117  * NOTES:
01118  *     - you *must* set NdisProtocolHandle before doing anything that could wind up
01119  *       getting BindAdapterHandler, as it will probably call OpenAdapter with this handle
01120  *     - the above implies that the initialization of the protocol block must be complete
01121  *       by then
01122  * TODO:
01123  *     - break this function up - probably do a 'ndisRefreshProtocolBindings' function
01124  *     - make this thing able to handle >1 protocol
01125  */
01126 {
01127   PPROTOCOL_BINDING Protocol;
01128   NTSTATUS NtStatus;
01129   UINT MinSize;
01130   PNET_PNP_EVENT PnPEvent;
01131 
01132   NDIS_DbgPrint(MAX_TRACE, ("Called.\n"));
01133 
01134   *NdisProtocolHandle = NULL;
01135 
01136   /* first validate the PROTOCOL_CHARACTERISTICS */
01137   switch (ProtocolCharacteristics->MajorNdisVersion)
01138     {
01139     case 0x03:
01140       /* we don't really want to support ndis3 drivers - so we complain for now */
01141       NDIS_DbgPrint(MID_TRACE, ("NDIS 3 protocol attempting to register\n"));
01142       MinSize = sizeof(NDIS30_PROTOCOL_CHARACTERISTICS);
01143       break;
01144 
01145     case 0x04:
01146       MinSize = sizeof(NDIS40_PROTOCOL_CHARACTERISTICS);
01147       break;
01148 
01149     case 0x05:
01150       MinSize = sizeof(NDIS50_PROTOCOL_CHARACTERISTICS);
01151       break;
01152 
01153     default:
01154       *Status = NDIS_STATUS_BAD_VERSION;
01155       NDIS_DbgPrint(MIN_TRACE, ("Incorrect characteristics size\n"));
01156       return;
01157     }
01158 
01159   if (CharacteristicsLength < MinSize)
01160     {
01161       NDIS_DbgPrint(MIN_TRACE, ("Bad protocol characteristics.\n"));
01162       *Status = NDIS_STATUS_BAD_CHARACTERISTICS;
01163       return;
01164     }
01165 
01166   /* set up the protocol block */
01167   Protocol = ExAllocatePool(NonPagedPool, sizeof(PROTOCOL_BINDING));
01168   if (!Protocol)
01169     {
01170       NDIS_DbgPrint(MIN_TRACE, ("Insufficient resources.\n"));
01171       *Status = NDIS_STATUS_RESOURCES;
01172       return;
01173     }
01174 
01175   RtlZeroMemory(Protocol, sizeof(PROTOCOL_BINDING));
01176   RtlCopyMemory(&Protocol->Chars, ProtocolCharacteristics, MinSize);
01177 
01178   NtStatus = RtlUpcaseUnicodeString(&Protocol->Chars.Name, &ProtocolCharacteristics->Name, TRUE);
01179   if (!NT_SUCCESS(NtStatus))
01180     {
01181       NDIS_DbgPrint(MIN_TRACE, ("Insufficient resources.\n"));
01182       ExFreePool(Protocol);
01183       *Status = NDIS_STATUS_RESOURCES;
01184       return;
01185     }
01186 
01187   KeInitializeSpinLock(&Protocol->Lock);
01188 
01189   InitializeListHead(&Protocol->AdapterListHead);
01190 
01191   /* We must set this before the call to ndisBindMiniportsToProtocol because the protocol's 
01192    * BindAdapter handler might need it */
01193 
01194   *NdisProtocolHandle = Protocol;
01195 
01196   ndisBindMiniportsToProtocol(Status, Protocol);
01197 
01198   /* Should we only send this if ndisBindMiniportsToProtocol succeeds? */
01199   PnPEvent = ProSetupPnPEvent(NetEventBindsComplete, NULL, 0);
01200   if (PnPEvent)
01201   {
01202       if (Protocol->Chars.PnPEventHandler)
01203       {
01204           /* We call this with a NULL binding context because it affects all bindings */
01205           NtStatus = (*Protocol->Chars.PnPEventHandler)(NULL,
01206                                                         PnPEvent);
01207 
01208           /* FIXME: We don't support this yet */
01209           ASSERT(NtStatus != NDIS_STATUS_PENDING);
01210       }
01211 
01212       ExFreePool(PnPEvent);
01213   }
01214 
01215   if (*Status == NDIS_STATUS_SUCCESS) {
01216       ExInterlockedInsertTailList(&ProtocolListHead, &Protocol->ListEntry, &ProtocolListLock);
01217   } else {
01218       NDIS_DbgPrint(MIN_TRACE, ("Binding failed (%x)\n", *Status));
01219       ExFreePool(Protocol);
01220       *NdisProtocolHandle = NULL;
01221   }
01222 }
01223 
01224 
01225 /*
01226  * @implemented
01227  */
01228 VOID
01229 EXPORT
01230 NdisRequest(
01231     OUT PNDIS_STATUS    Status,
01232     IN  NDIS_HANDLE     NdisBindingHandle,
01233     IN  PNDIS_REQUEST   NdisRequest)
01234 /*
01235  * FUNCTION: Forwards a request to an NDIS driver
01236  * ARGUMENTS:
01237  *     Status            = Address of buffer for status information
01238  *     NdisBindingHandle = Adapter binding handle
01239  *     NdisRequest       = Pointer to request to perform
01240  */
01241 {
01242     *Status = ProRequest(NdisBindingHandle, NdisRequest);
01243 }
01244 
01245 
01246 /*
01247  * @implemented
01248  */
01249 VOID
01250 EXPORT
01251 NdisReset(
01252     OUT PNDIS_STATUS    Status,
01253     IN  NDIS_HANDLE     NdisBindingHandle)
01254 {
01255     *Status = ProReset(NdisBindingHandle);
01256 }
01257 
01258 
01259 /*
01260  * @implemented
01261  */
01262 #undef NdisSend
01263 VOID
01264 EXPORT
01265 NdisSend(
01266     OUT PNDIS_STATUS    Status,
01267     IN  NDIS_HANDLE     NdisBindingHandle,
01268     IN  PNDIS_PACKET    Packet)
01269 /*
01270  * FUNCTION: Forwards a request to send a packet
01271  * ARGUMENTS:
01272  *     Status             = Address of buffer for status information
01273  *     NdisBindingHandle  = Adapter binding handle
01274  *     Packet             = Pointer to NDIS packet descriptor
01275  */
01276 {
01277     *Status = ProSend(NdisBindingHandle, Packet);
01278 }
01279 
01280 
01281 /*
01282  * @implemented
01283  */
01284 #undef NdisSendPackets
01285 VOID
01286 EXPORT
01287 NdisSendPackets(
01288     IN  NDIS_HANDLE     NdisBindingHandle,
01289     IN  PPNDIS_PACKET   PacketArray,
01290     IN  UINT            NumberOfPackets)
01291 {
01292     ProSendPackets(NdisBindingHandle, PacketArray, NumberOfPackets);
01293 }
01294 
01295 
01296 /*
01297  * @implemented
01298  */
01299 #undef NdisTransferData
01300 VOID
01301 EXPORT
01302 NdisTransferData(
01303     OUT     PNDIS_STATUS    Status,
01304     IN      NDIS_HANDLE     NdisBindingHandle,
01305     IN      NDIS_HANDLE     MacReceiveContext,
01306     IN      UINT            ByteOffset,
01307     IN      UINT            BytesToTransfer,
01308     IN OUT  PNDIS_PACKET    Packet,
01309     OUT     PUINT           BytesTransferred)
01310 /*
01311  * FUNCTION: Forwards a request to copy received data into a protocol-supplied packet
01312  * ARGUMENTS:
01313  *     Status            = Address of buffer for status information
01314  *     NdisBindingHandle = Adapter binding handle
01315  *     MacReceiveContext = MAC receive context
01316  *     ByteOffset        = Offset in packet to place data
01317  *     BytesToTransfer   = Number of bytes to copy into packet
01318  *     Packet            = Pointer to NDIS packet descriptor
01319  *     BytesTransferred  = Address of buffer to place number of bytes copied
01320  */
01321 {
01322     *Status = ProTransferData(NdisBindingHandle,
01323                               MacReceiveContext,
01324                               ByteOffset,
01325                               BytesToTransfer,
01326                               Packet,
01327                               BytesTransferred);
01328 }
01329 
01330 /*
01331  * @implemented
01332  */
01333 VOID
01334 NTAPI
01335 NdisReEnumerateProtocolBindings(IN NDIS_HANDLE NdisProtocolHandle)
01336 {
01337     NDIS_STATUS NdisStatus;
01338 
01339     ndisBindMiniportsToProtocol(&NdisStatus, NdisProtocolHandle);
01340 }
01341 
01342 
01343 /*
01344  * @implemented
01345  */
01346 VOID
01347 EXPORT
01348 NdisGetDriverHandle(
01349     IN  PNDIS_HANDLE    NdisBindingHandle,
01350     OUT PNDIS_HANDLE    NdisDriverHandle)
01351 /*
01352  * FUNCTION:
01353  * ARGUMENTS:
01354  * NOTES:
01355  *    NDIS 5.0
01356  */
01357 {
01358     PADAPTER_BINDING Binding = (PADAPTER_BINDING)NdisBindingHandle;
01359 
01360     if (!Binding)
01361     {
01362         NDIS_DbgPrint(MIN_TRACE, ("Bad binding handle\n"));
01363         *NdisDriverHandle = NULL;
01364         return;
01365     }
01366 
01367     *NdisDriverHandle = Binding->Adapter->NdisMiniportBlock.DriverHandle;
01368 }
01369 
01370 /* EOF */

Generated on Fri May 25 2012 04:22:11 for ReactOS by doxygen 1.7.6.1

ReactOS is a registered trademark or a trademark of ReactOS Foundation in the United States and other countries.