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

📄 pcnet.c

📁 winNT技术操作系统,国外开放的原代码和LIUX一样
💻 C
📖 第 1 页 / 共 3 页
字号:
      Status =  NDIS_STATUS_RESOURCES;
      DPRINT1("Insufficient resources\n");
      BREAKPOINT;
      *OpenErrorStatus = Status;
      return Status;
    }

  RtlZeroMemory(Adapter, sizeof(ADAPTER));

  Adapter->MiniportAdapterHandle = MiniportAdapterHandle;

  /* register our adapter structwith ndis */
  NdisMSetAttributesEx(Adapter->MiniportAdapterHandle, Adapter, 0, NDIS_ATTRIBUTE_BUS_MASTER, NdisInterfacePci);

  do
    {
      /* Card-specific detection and setup */
      Status = MiQueryCard(Adapter);
      if(Status != NDIS_STATUS_SUCCESS)
        {
          DPRINT1("MiQueryCard failed\n");
          Status = NDIS_STATUS_ADAPTER_NOT_FOUND;
          BREAKPOINT;
          break;
        }

      /* register an IO port range */
      Status = NdisMRegisterIoPortRange((PVOID*)&Adapter->PortOffset, Adapter->MiniportAdapterHandle,
          (UINT)Adapter->IoBaseAddress, NUMBER_OF_PORTS);
      if(Status != NDIS_STATUS_SUCCESS)
        {
          DPRINT1("NdisMRegisterIoPortRange failed: 0x%x\n", Status);
          BREAKPOINT
          break;
        }

      /* Allocate map registers */
      Status = NdisMAllocateMapRegisters(Adapter->MiniportAdapterHandle, 0,
          NDIS_DMA_32BITS, 8, BUFFER_SIZE);
      if(Status != NDIS_STATUS_SUCCESS)
        {
          DPRINT1("NdisMAllocateMapRegisters failed: 0x%x\n", Status);
          BREAKPOINT
          break;
        }

      /* set up the interrupt */
      Status = NdisMRegisterInterrupt(&Adapter->InterruptObject, Adapter->MiniportAdapterHandle, Adapter->InterruptVector,
          Adapter->InterruptVector, TRUE, TRUE, NdisInterruptLevelSensitive);
      if(Status != NDIS_STATUS_SUCCESS)
        {
          DPRINT("NdisMRegisterInterrupt failed: 0x%x\n", Status);
          BREAKPOINT
          break;
        }

      InterruptRegistered = TRUE;

      /* Allocate and initialize shared data structures */
      Status = MiAllocateSharedMemory(Adapter);
      if(Status != NDIS_STATUS_SUCCESS)
        {
          Status = NDIS_STATUS_RESOURCES;
          DPRINT("MiAllocateSharedMemory failed", Status);
          BREAKPOINT
          break;
        }

      /* set up the initialization block */
      MiPrepareInitializationBlock(Adapter);

      DPRINT("Interrupt registered successfully\n");

      /* Initialize and start the chip */
      MiInitChip(Adapter);

      NdisAllocateSpinLock(&Adapter->Lock);

      Status = NDIS_STATUS_SUCCESS;
    }
  while(0);

  if(Status != NDIS_STATUS_SUCCESS && Adapter)
    {
      DPRINT("Error; freeing stuff\n");

      NdisMFreeMapRegisters(Adapter->MiniportAdapterHandle); /* doesn't hurt to free if we never alloc'd? */

      if(Adapter->PortOffset)
        NdisMDeregisterIoPortRange(Adapter->MiniportAdapterHandle, Adapter->IoBaseAddress, NUMBER_OF_PORTS, (PVOID)Adapter->PortOffset);

      if(InterruptRegistered)
        NdisMDeregisterInterrupt(&Adapter->InterruptObject);

      MiFreeSharedMemory(Adapter);

      NdisFreeMemory(Adapter, 0, 0);
    }

  if(Status == NDIS_STATUS_SUCCESS)
    {
      NdisMInitializeTimer(&Adapter->MediaDetectionTimer,
                           Adapter->MiniportAdapterHandle,
                           MiniportMediaDetectionTimer,
                           Adapter);
      NdisMSetPeriodicTimer(&Adapter->MediaDetectionTimer,
                            MEDIA_DETECTION_INTERVAL);
    }

#if DBG
  if(!MiTestCard(Adapter))
    ASSERT(0);
#endif

  DPRINT("returning 0x%x\n", Status);
  *OpenErrorStatus = Status;
  return Status;
}

static VOID
STDCALL
MiniportISR(
    OUT PBOOLEAN InterruptRecognized,
    OUT PBOOLEAN QueueMiniportHandleInterrupt,
    IN NDIS_HANDLE MiniportAdapterContext)
/*
 * FUNCTION: Miniport interrupt service routine
 * ARGUMENTS:
 *     InterruptRecognized: the interrupt was ours
 *     QueueMiniportHandleInterrupt: whether to queue a DPC to handle this interrupt
 *     MiniportAdapterContext: the context originally passed to NdisMSetAttributes
 * NOTES:
 *     - called by NDIS at DIRQL
 *     - by setting QueueMiniportHandleInterrupt to TRUE, MiniportHandleInterrupt
 *       will be called
 */
{
  USHORT Data;
  USHORT Rap;
  PADAPTER Adapter = (PADAPTER)MiniportAdapterContext;

  DPRINT("Called\n");

  /* save the old RAP value */
  NdisRawReadPortUshort(Adapter->PortOffset + RAP, &Rap);

  /* is this ours? */
  NdisRawWritePortUshort(Adapter->PortOffset + RAP, CSR0);
  NdisRawReadPortUshort(Adapter->PortOffset + RDP, &Data);

  if(!(Data & CSR0_INTR))
    {
      DPRINT("not our interrupt.\n");
      *InterruptRecognized = FALSE;
      *QueueMiniportHandleInterrupt = FALSE;
    }
  else
    {
      DPRINT("detected our interrupt\n");

      /* disable interrupts */
      NdisRawWritePortUshort(Adapter->PortOffset + RAP, CSR0);
      NdisRawWritePortUshort(Adapter->PortOffset + RDP, 0);

      *InterruptRecognized = TRUE;
      *QueueMiniportHandleInterrupt = TRUE;
    }

  /* restore the rap */
  NdisRawWritePortUshort(Adapter->PortOffset + RAP, Rap);
}

static NDIS_STATUS
STDCALL
MiniportReset(
    OUT PBOOLEAN AddressingReset,
    IN NDIS_HANDLE MiniportAdapterContext)
/*
 * FUNCTION: Reset the miniport
 * ARGUMENTS:
 *     AddressingReset: Whether or not we want NDIS to subsequently call MiniportSetInformation
 *                      to reset our addresses and filters
 *     MiniportAdapterContext: context originally passed to NdisMSetAttributes
 * RETURNS:
 *     NDIS_STATUS_SUCCESS on all requests
 * Notes:
 *     - Called by NDIS at PASSIVE_LEVEL when it thinks we need a reset
 */
{
  DPRINT("Called\n");

  /* MiniportReset doesn't do anything at the moment... perhaps this should be fixed. */

  *AddressingReset = FALSE;
  return NDIS_STATUS_SUCCESS;
}

static BOOLEAN
STDCALL
MiSyncStartTransmit(
    IN PVOID SynchronizeContext)
/*
 * FUNCTION: Stop the adapter
 * ARGUMENTS:
 *     SynchronizeContext: Adapter context
 */
{
  PADAPTER Adapter = (PADAPTER)SynchronizeContext;
  NdisRawWritePortUshort(Adapter->PortOffset + RAP, CSR0);
  NdisRawWritePortUshort(Adapter->PortOffset + RDP, CSR0_IENA | CSR0_TDMD);
  return TRUE;
}

static NDIS_STATUS
STDCALL
MiniportSend(
    IN NDIS_HANDLE MiniportAdapterContext,
    IN PNDIS_PACKET Packet,
    IN UINT Flags)
/*
 * FUNCTION: Called by NDIS when it has a packet for the NIC to send out
 * ARGUMENTS:
 *     MiniportAdapterContext: context originally input to NdisMSetAttributes
 *     Packet: The NDIS_PACKET to be sent
 *     Flags: Flags associated with Packet
 * RETURNS:
 *     NDIS_STATUS_SUCCESS on processed requests
 *     NDIS_STATUS_RESOURCES if there's no place in buffer ring
 * NOTES:
 *     - Called by NDIS at DISPATCH_LEVEL
 */
{
  PADAPTER Adapter = (PADAPTER)MiniportAdapterContext;
  PTRANSMIT_DESCRIPTOR Desc;
  PNDIS_BUFFER NdisBuffer;
  PVOID SourceBuffer;
  UINT TotalPacketLength, SourceLength, Position = 0;

  DPRINT("Called\n");

  NdisDprAcquireSpinLock(&Adapter->Lock);

  /* Check if we have free entry in our circular buffer. */
  if ((Adapter->CurrentTransmitEndIndex + 1 ==
       Adapter->CurrentTransmitStartIndex) ||
      (Adapter->CurrentTransmitEndIndex == NUMBER_OF_BUFFERS - 1 &&
       Adapter->CurrentTransmitStartIndex == 0))
    {
      DPRINT1("No free space in circular buffer\n");
      NdisDprReleaseSpinLock(&Adapter->Lock);
      return NDIS_STATUS_RESOURCES;
    }

  Desc = Adapter->TransmitDescriptorRingVirt + Adapter->CurrentTransmitEndIndex;

  NdisQueryPacket(Packet, NULL, NULL, &NdisBuffer, &TotalPacketLength);
  ASSERT(TotalPacketLength <= BUFFER_SIZE);

  DPRINT("TotalPacketLength: %x\n", TotalPacketLength);

  while (NdisBuffer)
    {
      NdisQueryBuffer(NdisBuffer, &SourceBuffer, &SourceLength);

      DPRINT("Buffer: %x Length: %x\n", SourceBuffer, SourceLength);

      RtlCopyMemory(Adapter->TransmitBufferPtrVirt +
                    Adapter->CurrentTransmitEndIndex * BUFFER_SIZE + Position,
                    SourceBuffer, SourceLength);

      Position += SourceLength;

      NdisGetNextBuffer(NdisBuffer, &NdisBuffer);
    }

#if DBG && 0
  {
    PUCHAR Ptr = Adapter->TransmitBufferPtrVirt +
                 Adapter->CurrentTransmitEndIndex * BUFFER_SIZE;
    for (Position = 0; Position < TotalPacketLength; Position++)
      {
        if (Position % 16 == 0)
          DbgPrint("\n");
        DbgPrint("%x ", *Ptr++);
      }
  }
  DbgPrint("\n");
#endif

  Adapter->CurrentTransmitEndIndex++;
  Adapter->CurrentTransmitEndIndex %= NUMBER_OF_BUFFERS;

  Desc->FLAGS = TD1_OWN | TD1_STP | TD1_ENP;
  Desc->BCNT = 0xf000 | -TotalPacketLength;

  NdisMSynchronizeWithInterrupt(&Adapter->InterruptObject, MiSyncStartTransmit, Adapter);

  NdisDprReleaseSpinLock(&Adapter->Lock);

  return NDIS_STATUS_SUCCESS;
}

static ULONG
STDCALL
MiEthernetCrc(UCHAR *Address)
/*
 * FUNCTION: Calculate Ethernet CRC32
 * ARGUMENTS:
 *     Address: 6-byte ethernet address
 * RETURNS:
 *     The calculated CRC32 value.
 */
{
  UINT Counter, Length;
  ULONG Value = ~0;

  for (Length = 0; Length < 6; Length++)
    {
      Value ^= *Address++;
      for (Counter = 0; Counter < 8; Counter++)
        {
          Value >>= 1;
          Value ^= (Value & 1) * 0xedb88320;
        }
    }

  return Value;
}

NDIS_STATUS
STDCALL
MiSetMulticast(
    PADAPTER Adapter,
    UCHAR *Addresses,
    UINT AddressCount)
{
  UINT Index;
  ULONG CrcIndex;

  NdisZeroMemory(Adapter->InitializationBlockVirt->LADR, 8);
  for (Index = 0; Index < AddressCount; Index++)
    {
      CrcIndex = MiEthernetCrc(Addresses) >> 26;
      Adapter->InitializationBlockVirt->LADR[CrcIndex >> 3] |= 1 << (CrcIndex & 15);
      Addresses += 6;
    }

  /* FIXME: The specification mentions we need to reload the init block here. */

  return NDIS_STATUS_SUCCESS;
}

NDIS_MEDIA_STATE
STDCALL
MiGetMediaState(PADAPTER Adapter)
/*
 * FUNCTION: Determine the link state
 * ARGUMENTS:
 *     Adapter: Adapter context
 * RETURNS:
 *     NdisMediaStateConnected if the cable is connected
 *     NdisMediaStateDisconnected if the cable is disconnected
 */
{
  ULONG Data;
  NdisRawWritePortUshort(Adapter->PortOffset + RAP, BCR4);
  NdisRawReadPortUshort(Adapter->PortOffset + BDP, &Data);
  return Data & BCR4_LEDOUT ? NdisMediaStateConnected : NdisMediaStateDisconnected;
}

NTSTATUS
STDCALL
DriverEntry(
    IN PDRIVER_OBJECT DriverObject,
    IN PUNICODE_STRING RegistryPath)
/*
 * FUNCTION: Start this driver
 * ARGUMENTS:
 *     DriverObject: Pointer to the system-allocated driver object
 *     RegistryPath: Pointer to our SCM database entry
 * RETURNS:
 *     NDIS_STATUS_SUCCESS on success
 *     NDIS_STATUS_FAILURE on failure
 * NOTES:
 *     - Called by the I/O manager when the driver starts at PASSIVE_LEVEL
 *     - TODO: convert this to NTSTATUS return values
 */
{
  NDIS_HANDLE WrapperHandle;
  NDIS_MINIPORT_CHARACTERISTICS Characteristics;
  NDIS_STATUS Status;

  RtlZeroMemory(&Characteristics, sizeof(Characteristics));
  Characteristics.MajorNdisVersion = NDIS_MINIPORT_MAJOR_VERSION;
  Characteristics.MinorNdisVersion = NDIS_MINIPORT_MINOR_VERSION;
  Characteristics.HaltHandler = MiniportHalt;
  Characteristics.HandleInterruptHandler = MiniportHandleInterrupt;
  Characteristics.InitializeHandler = MiniportInitialize;
  Characteristics.ISRHandler = MiniportISR;
  Characteristics.QueryInformationHandler = MiniportQueryInformation;
  Characteristics.ResetHandler = MiniportReset;
  Characteristics.SetInformationHandler = MiniportSetInformation;
  Characteristics.SendHandler = MiniportSend;

  NdisMInitializeWrapper(&WrapperHandle, DriverObject, RegistryPath, 0);

  Status = NdisMRegisterMiniport(WrapperHandle, &Characteristics, sizeof(Characteristics));
  if(Status != NDIS_STATUS_SUCCESS)
    {
      NdisTerminateWrapper(WrapperHandle, 0);
      return NDIS_STATUS_FAILURE;
    }

  return NDIS_STATUS_SUCCESS;
}

⌨️ 快捷键说明

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