⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 protocol.c

📁 ReactOS是一些高手根据Windows XP的内核编写出的类XP。内核实现机理和API函数调用几乎相同。甚至可以兼容XP的程序。喜欢研究系统内核的人可以看一看。
💻 C
📖 第 1 页 / 共 3 页
字号:
/*
 * COPYRIGHT:   See COPYING in the top level directory
 * PROJECT:     ReactOS NDIS library
 * FILE:        ndis/protocol.c
 * PURPOSE:     Routines used by NDIS protocol drivers
 * PROGRAMMERS: Casper S. Hornstrup (chorns@users.sourceforge.net)
 *              Vizzini (vizzini@plasmic.com)
 * REVISIONS:
 *   CSH 01/08-2000 Created
 *   09-13-2003 Vizzini Updates for SendPackets support
 */

#include "ndissys.h"
#include <buffer.h>

#define SERVICES_KEY L"\\Registry\\Machine\\System\\CurrentControlSet\\Services\\"
#define LINKAGE_KEY  L"\\Linkage"
#define PARAMETERS_KEY L"\\Parameters\\"

LIST_ENTRY ProtocolListHead;
KSPIN_LOCK ProtocolListLock;


/*
 * @implemented
 */
VOID
EXPORT
NdisCompleteBindAdapter(
    IN  NDIS_HANDLE BindAdapterContext,
    IN  NDIS_STATUS Status,
    IN  NDIS_STATUS OpenStatus)
/*
 * FUNCTION: Indicates a packet to bound protocols
 * ARGUMENTS:
 *     Adapter = Pointer to logical adapter
 *     Packet  = Pointer to packet to indicate
 * RETURNS:
 *     Status of operation
 * NOTES:
 *     - FIXME: partially-implemented
 */
{
  PROTOCOL_BINDING *Protocol = (PROTOCOL_BINDING *)BindAdapterContext;

  /* Put protocol binding struct on global list */
  ExInterlockedInsertTailList(&ProtocolListHead, &Protocol->ListEntry, &ProtocolListLock);
}


NDIS_STATUS
ProIndicatePacket(
    PLOGICAL_ADAPTER Adapter,
    PNDIS_PACKET Packet)
/*
 * FUNCTION: Indicates a packet to bound protocols
 * ARGUMENTS:
 *     Adapter = Pointer to logical adapter
 *     Packet  = Pointer to packet to indicate
 * RETURNS:
 *     STATUS_SUCCESS in all cases
 * NOTES:
 *     - XXX ATM, this only handles loopback packets - is that its designed function?
 */
{
  KIRQL OldIrql;
  UINT BufferedLength;
  UINT PacketLength;

  NDIS_DbgPrint(MAX_TRACE, ("Called.\n"));

#ifdef DBG
  MiniDisplayPacket(Packet);
#endif

  NdisQueryPacket(Packet, NULL, NULL, NULL, &PacketLength);

  NDIS_DbgPrint(MAX_TRACE, ("acquiring miniport block lock\n"));
  KeAcquireSpinLock(&Adapter->NdisMiniportBlock.Lock, &OldIrql);
    {
      Adapter->NdisMiniportBlock.IndicatedPacket[KeGetCurrentProcessorNumber()] = Packet;
      BufferedLength = CopyPacketToBuffer(Adapter->LookaheadBuffer, Packet, 0, Adapter->NdisMiniportBlock.CurrentLookahead);
    }
  KeReleaseSpinLock(&Adapter->NdisMiniportBlock.Lock, OldIrql);

  if (BufferedLength > Adapter->MediumHeaderSize)
    {
      /* XXX Change this to call SendPackets so we don't have to duplicate this wacky logic */
      MiniIndicateData(Adapter, NULL, Adapter->LookaheadBuffer, Adapter->MediumHeaderSize,
          &Adapter->LookaheadBuffer[Adapter->MediumHeaderSize], BufferedLength - Adapter->MediumHeaderSize,
          PacketLength - Adapter->MediumHeaderSize);
    }
  else
    {
      MiniIndicateData(Adapter, NULL, Adapter->LookaheadBuffer, Adapter->MediumHeaderSize, NULL, 0, 0);
    }

  NDIS_DbgPrint(MAX_TRACE, ("acquiring miniport block lock\n"));
  KeAcquireSpinLock(&Adapter->NdisMiniportBlock.Lock, &OldIrql);
    {
      Adapter->NdisMiniportBlock.IndicatedPacket[KeGetCurrentProcessorNumber()] = NULL;
    }
  KeReleaseSpinLock(&Adapter->NdisMiniportBlock.Lock, OldIrql);

  return STATUS_SUCCESS;
}


NDIS_STATUS NTAPI
ProRequest(
    IN  NDIS_HANDLE     MacBindingHandle,
    IN  PNDIS_REQUEST   NdisRequest)
/*
 * FUNCTION: Forwards a request to an NDIS miniport
 * ARGUMENTS:
 *     MacBindingHandle = Adapter binding handle
 *     NdisRequest      = Pointer to request to perform
 * RETURNS:
 *     Status of operation
 */
{
  KIRQL OldIrql;
  BOOLEAN QueueWorkItem = FALSE;
  NDIS_STATUS NdisStatus;
  PADAPTER_BINDING AdapterBinding;
  PLOGICAL_ADAPTER Adapter;
  PNDIS_REQUEST_MAC_BLOCK MacBlock = (PNDIS_REQUEST_MAC_BLOCK)NdisRequest->MacReserved;

  NDIS_DbgPrint(MAX_TRACE, ("Called.\n"));

  ASSERT(MacBindingHandle);
  AdapterBinding = GET_ADAPTER_BINDING(MacBindingHandle);

  ASSERT(AdapterBinding->Adapter);
  Adapter = AdapterBinding->Adapter;

  MacBlock->Binding = &AdapterBinding->NdisOpenBlock;

  /*
   * If the miniport is already busy, queue a workitem
   */
  NDIS_DbgPrint(MAX_TRACE, ("acquiring miniport block lock\n"));
  KeAcquireSpinLock(&Adapter->NdisMiniportBlock.Lock, &OldIrql);
    {
      if(Adapter->MiniportBusy)
        QueueWorkItem = TRUE;
      else
        {
          NDIS_DbgPrint(MAX_TRACE, ("Setting adapter 0x%x to busy\n"));
          Adapter->MiniportBusy = TRUE;
        }
    }

  /* MiniQueueWorkItem must be called at IRQL >= DISPATCH_LEVEL */
  if (QueueWorkItem)
    {
      MiniQueueWorkItem(Adapter, NdisWorkItemRequest, (PVOID)NdisRequest);
      KeReleaseSpinLock(&Adapter->NdisMiniportBlock.Lock, OldIrql);
      return NDIS_STATUS_PENDING;
    }

  KeReleaseSpinLock(&Adapter->NdisMiniportBlock.Lock, OldIrql);

  /* MiniportQueryInformation (called by MiniDoRequest) runs at DISPATCH_LEVEL */
  /* TODO (?): move the irql raise into MiniDoRequest */
  KeRaiseIrql(DISPATCH_LEVEL, &OldIrql);
    {
      NdisStatus = MiniDoRequest(&Adapter->NdisMiniportBlock, NdisRequest);

      NDIS_DbgPrint(MAX_TRACE, ("acquiring miniport block lock\n"));
      KeAcquireSpinLockAtDpcLevel(&Adapter->NdisMiniportBlock.Lock);
        {
          NDIS_DbgPrint(MAX_TRACE, ("Setting adapter 0x%x to free\n"));
          Adapter->MiniportBusy = FALSE;

          if (Adapter->WorkQueueHead)
            KeInsertQueueDpc(&Adapter->NdisMiniportBlock.DeferredDpc, NULL, NULL);
        }
      KeReleaseSpinLockFromDpcLevel(&Adapter->NdisMiniportBlock.Lock);
    }
  KeLowerIrql(OldIrql);

  return NdisStatus;
}


NDIS_STATUS NTAPI
ProReset(
    IN  NDIS_HANDLE MacBindingHandle)
{
    UNIMPLEMENTED

    return NDIS_STATUS_FAILURE;
}


NDIS_STATUS NTAPI
ProSend(
    IN  NDIS_HANDLE     MacBindingHandle,
    IN  PNDIS_PACKET    Packet)
/*
 * FUNCTION: Forwards a request to send a packet to an NDIS miniport
 * ARGUMENTS:
 *     MacBindingHandle = Adapter binding handle
 *     Packet           = Pointer to NDIS packet descriptor
 * RETURNS:
 *     NDIS_STATUS_SUCCESS always
 * NOTES:
 * TODO:
 *     - Fix return values
 *     - Should queue packet if miniport returns NDIS_STATUS_RESOURCES
 *     - Queue packets directly on the adapters when possible (i.e.
 *       when miniports not busy)
 *     - Break this up
 */
{
  KIRQL RaiseOldIrql, SpinOldIrql;
  BOOLEAN QueueWorkItem = FALSE;
  NDIS_STATUS NdisStatus;
  PADAPTER_BINDING AdapterBinding;
  PLOGICAL_ADAPTER Adapter;

  NDIS_DbgPrint(MAX_TRACE, ("Called.\n"));

  ASSERT(MacBindingHandle);
  AdapterBinding = GET_ADAPTER_BINDING(MacBindingHandle);

  ASSERT(AdapterBinding);
  Adapter = AdapterBinding->Adapter;

  ASSERT(Adapter);

  /* if the following is not true, KeRaiseIrql() below will break */
  ASSERT(KeGetCurrentIrql() <= DISPATCH_LEVEL);

  /* XXX what is this crazy black magic? */
  Packet->Reserved[0] = (ULONG_PTR)MacBindingHandle;

  /*
   * Acquire this lock in order to see if the miniport is busy.
   * If it is not busy, we mark it as busy and release the lock.
   * Else we don't do anything because we have to queue a workitem
   * anyway.
   */
  NDIS_DbgPrint(MAX_TRACE, ("acquiring miniport block lock\n"));
  KeAcquireSpinLock(&Adapter->NdisMiniportBlock.Lock, &SpinOldIrql);
    {
      /*
       * if the miniport is marked as busy, we queue the packet as a work item,
       * else we send the packet directly to the miniport.  Sending to the miniport
       * makes it busy.
       */
      if (Adapter->MiniportBusy)
        QueueWorkItem = TRUE;
      else
        {
          NDIS_DbgPrint(MAX_TRACE, ("Setting adapter 0x%x to busy\n"));
          Adapter->MiniportBusy = TRUE;
        }
    }
  KeReleaseSpinLock(&Adapter->NdisMiniportBlock.Lock, SpinOldIrql);

  /*
   * Test the packet to see if it is a MAC loopback.
   *
   * We may have to loop this packet if miniport cannot.
   * If dest MAC address of packet == MAC address of adapter,
   * this is a loopback frame.
   */
  if ((Adapter->NdisMiniportBlock.MacOptions & NDIS_MAC_OPTION_NO_LOOPBACK) &&
      MiniAdapterHasAddress(Adapter, Packet))
    {
      NDIS_DbgPrint(MIN_TRACE, ("Looping packet.\n"));

      if (QueueWorkItem)
        {
          MiniQueueWorkItem(Adapter, NdisWorkItemSendLoopback, (PVOID)Packet);
          return NDIS_STATUS_PENDING;
        }

      KeRaiseIrql(DISPATCH_LEVEL, &RaiseOldIrql);
        {
          /*
           * atm this *only* handles loopback packets - it calls MiniIndicateData to
           * send back to the protocol.  FIXME: this will need to be adjusted a bit.
           * Also, I'm not sure you really have to be at dispatch level for this.  It
           * might use a ReceivePackets handler, which can run <= DISPATCH_LEVEL.
           */
          NdisStatus = ProIndicatePacket(Adapter, Packet);

          NDIS_DbgPrint(MAX_TRACE, ("acquiring miniport block lock\n"));
          KeAcquireSpinLockAtDpcLevel(&Adapter->NdisMiniportBlock.Lock);
            {
              NDIS_DbgPrint(MAX_TRACE, ("Setting adapter 0x%x to free\n"));
              Adapter->MiniportBusy = FALSE;

              if (Adapter->WorkQueueHead)
                KeInsertQueueDpc(&Adapter->NdisMiniportBlock.DeferredDpc, NULL, NULL);
              else
                NDIS_DbgPrint(MID_TRACE,("Failed to insert packet into work queue\n"));
            }
          KeReleaseSpinLockFromDpcLevel(&Adapter->NdisMiniportBlock.Lock);
        }
      KeLowerIrql(RaiseOldIrql);

      return NdisStatus;
    }
  else
    NDIS_DbgPrint(MID_TRACE,("Not a loopback packet\n"));

  /* This is a normal send packet, not a loopback packet. */
  if (QueueWorkItem)
    {
      MiniQueueWorkItem(Adapter, NdisWorkItemSend, (PVOID)Packet);
      NDIS_DbgPrint(MAX_TRACE, ("Queued a work item and returning\n"));
      return NDIS_STATUS_PENDING;
    }

  ASSERT(Adapter->NdisMiniportBlock.DriverHandle);

  /*
   * Call the appropriate send handler
   *
   * If a miniport provides a SendPackets handler, we always call it.  If not, we call the
   * Send handler.
   */
  if(Adapter->NdisMiniportBlock.DriverHandle->MiniportCharacteristics.SendPacketsHandler)
    {
      if(Adapter->NdisMiniportBlock.Flags & NDIS_ATTRIBUTE_DESERIALIZE)
        {
          NDIS_DbgPrint(MAX_TRACE, ("Calling miniport's SendPackets handler\n"));
          (*Adapter->NdisMiniportBlock.DriverHandle->MiniportCharacteristics.SendPacketsHandler)(
            Adapter->NdisMiniportBlock.MiniportAdapterContext, &Packet, 1);
        }
      else
        {
          /* SendPackets is called at DISPATCH_LEVEL for all serialized miniports */

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -