fdo.c

来自「一个类似windows」· C语言 代码 · 共 591 行 · 第 1/2 页

C
591
字号
/*
 * PROJECT:         ReactOS PCI bus driver
 * FILE:            fdo.c
 * PURPOSE:         PCI device object dispatch routines
 * PROGRAMMERS:     Casper S. Hornstrup (chorns@users.sourceforge.net)
 * UPDATE HISTORY:
 *      10-09-2001  CSH  Created
 */

#include "pci.h"

#define NDEBUG
#include <debug.h>

/*** PRIVATE *****************************************************************/

static NTSTATUS
FdoLocateChildDevice(
  PPCI_DEVICE *Device,
  PFDO_DEVICE_EXTENSION DeviceExtension,
  PCI_SLOT_NUMBER SlotNumber,
  PPCI_COMMON_CONFIG PciConfig)
{
  PLIST_ENTRY CurrentEntry;
  PPCI_DEVICE CurrentDevice;

  DPRINT("Called\n");

  CurrentEntry = DeviceExtension->DeviceListHead.Flink;
  while (CurrentEntry != &DeviceExtension->DeviceListHead) {
    CurrentDevice = CONTAINING_RECORD(CurrentEntry, PCI_DEVICE, ListEntry);

    /* If both vendor ID and device ID match, it is the same device */
    if ((PciConfig->VendorID == CurrentDevice->PciConfig.VendorID) &&
        (PciConfig->DeviceID == CurrentDevice->PciConfig.DeviceID) &&
        (SlotNumber.u.AsULONG == CurrentDevice->SlotNumber.u.AsULONG)) {
      *Device = CurrentDevice;
      DPRINT("Done\n");
      return STATUS_SUCCESS;
    }

    CurrentEntry = CurrentEntry->Flink;
  }

  *Device = NULL;
  DPRINT("Done\n");
  return STATUS_UNSUCCESSFUL;
}


static NTSTATUS
FdoEnumerateDevices(
  PDEVICE_OBJECT DeviceObject)
{
  PFDO_DEVICE_EXTENSION DeviceExtension;
  PCI_COMMON_CONFIG PciConfig;
  PLIST_ENTRY CurrentEntry;
  PPCI_DEVICE Device;
  PCI_SLOT_NUMBER SlotNumber;
  ULONG DeviceNumber;
  ULONG FunctionNumber;
  ULONG Size;
  NTSTATUS Status;

  DPRINT("Called\n");

  DeviceExtension = (PFDO_DEVICE_EXTENSION)DeviceObject->DeviceExtension;

  /* Mark all devices to be removed. If we don't discover them again during
     enumeration, assume that they have been surprise removed */
  CurrentEntry = DeviceExtension->DeviceListHead.Flink;
  while (CurrentEntry != &DeviceExtension->DeviceListHead) {
    Device = CONTAINING_RECORD(CurrentEntry, PCI_DEVICE, ListEntry);
    Device->RemovePending = TRUE;
    CurrentEntry = CurrentEntry->Flink;
  }

  DeviceExtension->DeviceListCount = 0;

  /* Enumerate devices on the PCI bus */
  SlotNumber.u.AsULONG = 0;
  for (DeviceNumber = 0; DeviceNumber < PCI_MAX_DEVICES; DeviceNumber++)
  {
    SlotNumber.u.bits.DeviceNumber = DeviceNumber;
    for (FunctionNumber = 0; FunctionNumber < PCI_MAX_FUNCTION; FunctionNumber++)
    {
      SlotNumber.u.bits.FunctionNumber = FunctionNumber;

      DPRINT("Bus %1lu  Device %2lu  Func %1lu\n",
        DeviceExtension->BusNumber,
        DeviceNumber,
        FunctionNumber);

      RtlZeroMemory(&PciConfig,
                    sizeof(PCI_COMMON_CONFIG));

      Size = HalGetBusData(PCIConfiguration,
                           DeviceExtension->BusNumber,
                           SlotNumber.u.AsULONG,
                           &PciConfig,
                           PCI_COMMON_HDR_LENGTH);
      DPRINT("Size %lu\n", Size);
      if (Size < PCI_COMMON_HDR_LENGTH)
      {
        if (FunctionNumber == 0)
        {
          break;
        }
        else
        {
          continue;
        }
      }

      DPRINT("Bus %1lu  Device %2lu  Func %1lu  VenID 0x%04hx  DevID 0x%04hx\n",
        DeviceExtension->BusNumber,
        DeviceNumber,
        FunctionNumber,
        PciConfig.VendorID,
        PciConfig.DeviceID);

      Status = FdoLocateChildDevice(&Device, DeviceExtension, SlotNumber, &PciConfig);
      if (!NT_SUCCESS(Status))
      {
        Device = (PPCI_DEVICE)ExAllocatePool(NonPagedPool, sizeof(PCI_DEVICE));
        if (!Device)
        {
          /* FIXME: Cleanup resources for already discovered devices */
          return STATUS_INSUFFICIENT_RESOURCES;
        }

        RtlZeroMemory(Device,
                      sizeof(PCI_DEVICE));

        Device->BusNumber = DeviceExtension->BusNumber;

        RtlCopyMemory(&Device->SlotNumber,
                      &SlotNumber,
                      sizeof(PCI_SLOT_NUMBER));

        RtlCopyMemory(&Device->PciConfig,
                      &PciConfig,
                      sizeof(PCI_COMMON_CONFIG));

        ExInterlockedInsertTailList(
          &DeviceExtension->DeviceListHead,
          &Device->ListEntry,
          &DeviceExtension->DeviceListLock);
      }

      /* Don't remove this device */
      Device->RemovePending = FALSE;

      DeviceExtension->DeviceListCount++;

      /* Skip to next device if the current one is not a multifunction device */
      if ((FunctionNumber == 0) &&
          ((PciConfig.HeaderType & 0x80) == 0))
      {
        break;
      }
    }
  }

  DPRINT("Done\n");

  return STATUS_SUCCESS;
}


static NTSTATUS
FdoQueryBusRelations(
  IN PDEVICE_OBJECT DeviceObject,
  IN PIRP Irp,
  PIO_STACK_LOCATION IrpSp)
{
  PPDO_DEVICE_EXTENSION PdoDeviceExtension;
  PFDO_DEVICE_EXTENSION DeviceExtension;
  PDEVICE_RELATIONS Relations;
  PLIST_ENTRY CurrentEntry;
  PPCI_DEVICE Device;
  NTSTATUS Status;
  BOOLEAN ErrorOccurred;
  NTSTATUS ErrorStatus;
  ULONG Size;
  ULONG i;

  DPRINT("Called\n");

  ErrorStatus = STATUS_INSUFFICIENT_RESOURCES;

  Status = STATUS_SUCCESS;

  ErrorOccurred = FALSE;

  FdoEnumerateDevices(DeviceObject);

  DeviceExtension = (PFDO_DEVICE_EXTENSION)DeviceObject->DeviceExtension;

  if (Irp->IoStatus.Information) {
    /* FIXME: Another bus driver has already created a DEVICE_RELATIONS
              structure so we must merge this structure with our own */
  }

  Size = sizeof(DEVICE_RELATIONS) + sizeof(Relations->Objects) *
    (DeviceExtension->DeviceListCount - 1);
  Relations = (PDEVICE_RELATIONS)ExAllocatePool(PagedPool, Size);
  if (!Relations)
    return STATUS_INSUFFICIENT_RESOURCES;

  Relations->Count = DeviceExtension->DeviceListCount;

  i = 0;
  CurrentEntry = DeviceExtension->DeviceListHead.Flink;
  while (CurrentEntry != &DeviceExtension->DeviceListHead) {
    Device = CONTAINING_RECORD(CurrentEntry, PCI_DEVICE, ListEntry);

    PdoDeviceExtension = NULL;

    if (!Device->Pdo) {
      /* Create a physical device object for the
         device as it does not already have one */
      Status = IoCreateDevice(
        DeviceObject->DriverObject,
        sizeof(PDO_DEVICE_EXTENSION),
        NULL,
        FILE_DEVICE_CONTROLLER,
        FILE_AUTOGENERATED_DEVICE_NAME,
        FALSE,
        &Device->Pdo);
      if (!NT_SUCCESS(Status)) {
        DPRINT("IoCreateDevice() failed with status 0x%X\n", Status);
        ErrorStatus = Status;
        ErrorOccurred = TRUE;
        break;
      }

      Device->Pdo->Flags |= DO_BUS_ENUMERATED_DEVICE;

      Device->Pdo->Flags &= ~DO_DEVICE_INITIALIZING;

      //Device->Pdo->Flags |= DO_POWER_PAGABLE;

      PdoDeviceExtension = (PPDO_DEVICE_EXTENSION)Device->Pdo->DeviceExtension;

      RtlZeroMemory(PdoDeviceExtension, sizeof(PDO_DEVICE_EXTENSION));

      PdoDeviceExtension->Common.IsFDO = FALSE;

      PdoDeviceExtension->Common.DeviceObject = Device->Pdo;

      PdoDeviceExtension->Common.DevicePowerState = PowerDeviceD0;

      PdoDeviceExtension->Fdo = DeviceObject;

      PdoDeviceExtension->PciDevice = Device;

      /* Add Device ID string */
      Status = PciCreateDeviceIDString(&PdoDeviceExtension->DeviceID, Device);
      if (!NT_SUCCESS(Status))
      {
        ErrorStatus = Status;
        ErrorOccurred = TRUE;
        break;
      }

      DPRINT("DeviceID: %S\n", PdoDeviceExtension->DeviceID.Buffer);

      /* Add Instance ID string */
      Status = PciCreateInstanceIDString(&PdoDeviceExtension->InstanceID, Device);
      if (!NT_SUCCESS(Status))
      {
        ErrorStatus = Status;
        ErrorOccurred = TRUE;
        break;
      }

      /* Add Hardware IDs string */
      Status = PciCreateHardwareIDsString(&PdoDeviceExtension->HardwareIDs, Device);
      if (!NT_SUCCESS(Status))
      {
        ErrorStatus = Status;
        ErrorOccurred = TRUE;
        break;
      }

      /* Add Compatible IDs string */
      Status = PciCreateCompatibleIDsString(&PdoDeviceExtension->CompatibleIDs, Device);
      if (!NT_SUCCESS(Status))
      {
        ErrorStatus = Status;
        ErrorOccurred = TRUE;
        break;
      }

      /* Add device description string */

⌨️ 快捷键说明

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