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

📄 pdo.c

📁 ReactOS是一些高手根据Windows XP的内核编写出的类XP。内核实现机理和API函数调用几乎相同。甚至可以兼容XP的程序。喜欢研究系统内核的人可以看一看。
💻 C
📖 第 1 页 / 共 3 页
字号:
/*
 * PROJECT:         ReactOS PCI bus driver
 * FILE:            pdo.c
 * PURPOSE:         Child device object dispatch routines
 * PROGRAMMERS:     Casper S. Hornstrup (chorns@users.sourceforge.net)
 * UPDATE HISTORY:
 *      10-09-2001  CSH  Created
 */

#include "pci.h"

#ifndef NDEBUG
#define NDEBUG
#endif
#include <debug.h>

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

static NTSTATUS
PdoQueryDeviceText(
  IN PDEVICE_OBJECT DeviceObject,
  IN PIRP Irp,
  PIO_STACK_LOCATION IrpSp)
{
  PPDO_DEVICE_EXTENSION DeviceExtension;
  NTSTATUS Status;

  DPRINT("Called\n");

  DeviceExtension = (PPDO_DEVICE_EXTENSION)DeviceObject->DeviceExtension;

  Status = STATUS_SUCCESS;

  switch (IrpSp->Parameters.QueryDeviceText.DeviceTextType)
  {
    case DeviceTextDescription:
      DPRINT("DeviceTextDescription\n");
      Irp->IoStatus.Information = (ULONG_PTR)DeviceExtension->DeviceDescription.Buffer;
      break;

    case DeviceTextLocationInformation:
      DPRINT("DeviceTextLocationInformation\n");
      Irp->IoStatus.Information = (ULONG_PTR)DeviceExtension->DeviceLocation.Buffer;
      break;

    default:
      Irp->IoStatus.Information = 0;
      Status = STATUS_INVALID_PARAMETER;
  }

  return Status;
}


static NTSTATUS
PdoQueryId(
  IN PDEVICE_OBJECT DeviceObject,
  IN PIRP Irp,
  PIO_STACK_LOCATION IrpSp)
{
  PPDO_DEVICE_EXTENSION DeviceExtension;
  UNICODE_STRING String;
  NTSTATUS Status;

  DPRINT("Called\n");

  DeviceExtension = (PPDO_DEVICE_EXTENSION)DeviceObject->DeviceExtension;

//  Irp->IoStatus.Information = 0;

  Status = STATUS_SUCCESS;

  RtlInitUnicodeString(&String, NULL);

  switch (IrpSp->Parameters.QueryId.IdType) {
    case BusQueryDeviceID:
      Status = PciDuplicateUnicodeString(
        RTL_DUPLICATE_UNICODE_STRING_NULL_TERMINATE,
        &DeviceExtension->DeviceID,
        &String);

      DPRINT("DeviceID: %S\n", String.Buffer);

      Irp->IoStatus.Information = (ULONG_PTR)String.Buffer;
      break;

    case BusQueryHardwareIDs:
      Status = PciDuplicateUnicodeString(
        RTL_DUPLICATE_UNICODE_STRING_NULL_TERMINATE,
        &DeviceExtension->HardwareIDs,
        &String);

      Irp->IoStatus.Information = (ULONG_PTR)String.Buffer;
      break;

    case BusQueryCompatibleIDs:
      Status = PciDuplicateUnicodeString(
        RTL_DUPLICATE_UNICODE_STRING_NULL_TERMINATE,
        &DeviceExtension->CompatibleIDs,
        &String);

      Irp->IoStatus.Information = (ULONG_PTR)String.Buffer;
      break;

    case BusQueryInstanceID:
      Status = PciDuplicateUnicodeString(
        RTL_DUPLICATE_UNICODE_STRING_NULL_TERMINATE,
        &DeviceExtension->InstanceID,
        &String);

      DPRINT("InstanceID: %S\n", String.Buffer);

      Irp->IoStatus.Information = (ULONG_PTR)String.Buffer;
      break;

    case BusQueryDeviceSerialNumber:
    default:
      Status = STATUS_NOT_IMPLEMENTED;
  }

  return Status;
}


static NTSTATUS
PdoQueryBusInformation(
  IN PDEVICE_OBJECT DeviceObject,
  IN PIRP Irp,
  PIO_STACK_LOCATION IrpSp)
{
  PPDO_DEVICE_EXTENSION DeviceExtension;
  PFDO_DEVICE_EXTENSION FdoDeviceExtension;
  PPNP_BUS_INFORMATION BusInformation;

  DPRINT("Called\n");

  DeviceExtension = (PPDO_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
  FdoDeviceExtension = (PFDO_DEVICE_EXTENSION)DeviceExtension->Fdo->DeviceExtension;
  BusInformation = ExAllocatePoolWithTag(PagedPool, sizeof(PNP_BUS_INFORMATION), TAG_PCI);
  Irp->IoStatus.Information = (ULONG_PTR)BusInformation;
  if (BusInformation != NULL)
  {
    BusInformation->BusTypeGuid = GUID_BUS_TYPE_PCI;
    BusInformation->LegacyBusType = PCIBus;
    BusInformation->BusNumber = DeviceExtension->PciDevice->BusNumber;

    return STATUS_SUCCESS;
  }

  return STATUS_INSUFFICIENT_RESOURCES;
}


static NTSTATUS
PdoQueryCapabilities(
  IN PDEVICE_OBJECT DeviceObject,
  IN PIRP Irp,
  PIO_STACK_LOCATION IrpSp)
{
  PPDO_DEVICE_EXTENSION DeviceExtension;
  PDEVICE_CAPABILITIES DeviceCapabilities;
  ULONG DeviceNumber, FunctionNumber;

  DPRINT("Called\n");

  DeviceExtension = (PPDO_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
  DeviceCapabilities = IrpSp->Parameters.DeviceCapabilities.Capabilities;

  if (DeviceCapabilities->Version != 1)
    return STATUS_UNSUCCESSFUL;

  DeviceNumber = DeviceExtension->PciDevice->SlotNumber.u.bits.DeviceNumber;
  FunctionNumber = DeviceExtension->PciDevice->SlotNumber.u.bits.FunctionNumber;

  DeviceCapabilities->UniqueID = FALSE;
  DeviceCapabilities->Address = ((DeviceNumber << 16) & 0xFFFF0000) + (FunctionNumber & 0xFFFF);
  DeviceCapabilities->UINumber = (ULONG)-1; /* FIXME */

  return STATUS_SUCCESS;
}


static BOOLEAN
PdoGetRangeLength(PPDO_DEVICE_EXTENSION DeviceExtension,
                  ULONG Offset,
                  PULONG Base,
                  PULONG Length,
                  PULONG Flags)
{
  ULONG OrigValue;
  ULONG BaseValue;
  ULONG NewValue;
  ULONG Size;
  ULONG XLength;

  /* Save original value */
  Size= HalGetBusDataByOffset(PCIConfiguration,
                              DeviceExtension->PciDevice->BusNumber,
                              DeviceExtension->PciDevice->SlotNumber.u.AsULONG,
                              &OrigValue,
                              Offset,
                              sizeof(ULONG));
  if (Size != sizeof(ULONG))
  {
    DPRINT1("Wrong size %lu\n", Size);
    return FALSE;
  }

  BaseValue = (OrigValue & 0x00000001) ? (OrigValue & ~0x3) : (OrigValue & ~0xF);

  *Base = BaseValue;

  /* Set magic value */
  NewValue = (ULONG)-1;
  Size= HalSetBusDataByOffset(PCIConfiguration,
                              DeviceExtension->PciDevice->BusNumber,
                              DeviceExtension->PciDevice->SlotNumber.u.AsULONG,
                              &NewValue,
                              Offset,
                              sizeof(ULONG));
  if (Size != sizeof(ULONG))
  {
    DPRINT1("Wrong size %lu\n", Size);
    return FALSE;
  }

  /* Get the range length */
  Size= HalGetBusDataByOffset(PCIConfiguration,
                              DeviceExtension->PciDevice->BusNumber,
                              DeviceExtension->PciDevice->SlotNumber.u.AsULONG,
                              &NewValue,
                              Offset,
                              sizeof(ULONG));
  if (Size != sizeof(ULONG))
  {
    DPRINT1("Wrong size %lu\n", Size);
    return FALSE;
  }

  /* Restore original value */
  Size= HalSetBusDataByOffset(PCIConfiguration,
                              DeviceExtension->PciDevice->BusNumber,
                              DeviceExtension->PciDevice->SlotNumber.u.AsULONG,
                              &OrigValue,
                              Offset,
                              sizeof(ULONG));
  if (Size != sizeof(ULONG))
  {
    DPRINT1("Wrong size %lu\n", Size);
    return FALSE;
  }

  if (NewValue == 0)
  {
    DPRINT("Unused address register\n");
    *Base = 0;
    *Length = 0;
    *Flags = 0;
     return TRUE;
  }

  XLength = ~((NewValue & 0x00000001) ? (NewValue & ~0x3) : (NewValue & ~0xF)) + 1;

#if 0
  DbgPrint("BaseAddress 0x%08lx  Length 0x%08lx",
           BaseValue, XLength);

  if (NewValue & 0x00000001)
  {
    DbgPrint("  IO range");
  }
  else
  {
    DbgPrint("  Memory range");
    if ((NewValue & 0x00000006) == 0)
    {
      DbgPrint(" in 32-Bit address space");
    }
    else if ((NewValue & 0x00000006) == 2)
    {
      DbgPrint(" below 1BM ");
    }
    else if ((NewValue & 0x00000006) == 4)
    {
      DbgPrint(" in 64-Bit address space");
    }

    if (NewValue & 0x00000008)
    {
      DbgPrint(" prefetchable");
    }
  }

  DbgPrint("\n");
#endif

  *Length = XLength;
  *Flags = (NewValue & 0x00000001) ? (NewValue & 0x3) : (NewValue & 0xF);

  return TRUE;
}


static NTSTATUS
PdoQueryResourceRequirements(
  IN PDEVICE_OBJECT DeviceObject,
  IN PIRP Irp,
  PIO_STACK_LOCATION IrpSp)
{
  PPDO_DEVICE_EXTENSION DeviceExtension;
  PCI_COMMON_CONFIG PciConfig;
  PIO_RESOURCE_REQUIREMENTS_LIST ResourceList;
  PIO_RESOURCE_DESCRIPTOR Descriptor;
  ULONG Size;
  ULONG ResCount = 0;
  ULONG ListSize;
  ULONG i;
  ULONG Base;
  ULONG Length;
  ULONG Flags;

  DPRINT("PdoQueryResourceRequirements() called\n");

  DeviceExtension = (PPDO_DEVICE_EXTENSION)DeviceObject->DeviceExtension;

  /* Get PCI configuration space */
  Size= HalGetBusData(PCIConfiguration,
                      DeviceExtension->PciDevice->BusNumber,
                      DeviceExtension->PciDevice->SlotNumber.u.AsULONG,
                      &PciConfig,
                      PCI_COMMON_HDR_LENGTH);
  DPRINT("Size %lu\n", Size);
  if (Size < PCI_COMMON_HDR_LENGTH)
  {
    Irp->IoStatus.Information = 0;
    return STATUS_UNSUCCESSFUL;
  }

  DPRINT("Command register: 0x%04hx\n", PciConfig.Command);

  /* Count required resource descriptors */
  ResCount = 0;
  if (PCI_CONFIGURATION_TYPE(&PciConfig) == PCI_DEVICE_TYPE)
  {
    for (i = 0; i < PCI_TYPE0_ADDRESSES; i++)
    {
      if (!PdoGetRangeLength(DeviceExtension,
			     0x10 + i * 4,
			     &Base,
			     &Length,
			     &Flags))
	break;

      if (Length != 0)
        ResCount += 2;
    }

    /* FIXME: Check ROM address */

    if (PciConfig.u.type0.InterruptPin != 0)
      ResCount++;
  }
  else if (PCI_CONFIGURATION_TYPE(&PciConfig) == PCI_BRIDGE_TYPE)
  {
    for (i = 0; i < PCI_TYPE1_ADDRESSES; i++)
    {
      if (!PdoGetRangeLength(DeviceExtension,
			     0x10 + i * 4,
			     &Base,
			     &Length,
			     &Flags))
	break;

      if (Length != 0)
        ResCount += 2;
    }
    if (DeviceExtension->PciDevice->PciConfig.BaseClass == PCI_CLASS_BRIDGE_DEV)
      ResCount++;
  }
  else if (PCI_CONFIGURATION_TYPE(&PciConfig) == PCI_CARDBUS_BRIDGE_TYPE)
  {
    /* FIXME: Count Cardbus bridge resources */
  }
  else
  {
    DPRINT1("Unsupported header type %u\n", PCI_CONFIGURATION_TYPE(&PciConfig));
  }

  if (ResCount == 0)
  {
    Irp->IoStatus.Information = 0;
    return STATUS_SUCCESS;
  }

  /* Calculate the resource list size */
  ListSize = FIELD_OFFSET(IO_RESOURCE_REQUIREMENTS_LIST, List->Descriptors)
    + ResCount * sizeof(IO_RESOURCE_DESCRIPTOR);

  DPRINT("ListSize %lu (0x%lx)\n", ListSize, ListSize);

  /* Allocate the resource requirements list */
  ResourceList = ExAllocatePoolWithTag(PagedPool,
                                ListSize, TAG_PCI);
  if (ResourceList == NULL)
  {
    Irp->IoStatus.Information = 0;
    return STATUS_INSUFFICIENT_RESOURCES;
  }

  RtlZeroMemory(ResourceList, ListSize);
  ResourceList->ListSize = ListSize;
  ResourceList->InterfaceType = PCIBus;
  ResourceList->BusNumber = DeviceExtension->PciDevice->BusNumber;
  ResourceList->SlotNumber = DeviceExtension->PciDevice->SlotNumber.u.AsULONG;
  ResourceList->AlternativeLists = 1;

  ResourceList->List[0].Version = 1;
  ResourceList->List[0].Revision = 1;
  ResourceList->List[0].Count = ResCount;

  Descriptor = &ResourceList->List[0].Descriptors[0];
  if (PCI_CONFIGURATION_TYPE(&PciConfig) == PCI_DEVICE_TYPE)
  {
    for (i = 0; i < PCI_TYPE0_ADDRESSES; i++)
    {
      if (!PdoGetRangeLength(DeviceExtension,
			     0x10 + i * 4,
			     &Base,
			     &Length,
			     &Flags))
      {
        DPRINT1("PdoGetRangeLength() failed\n");
        break;
      }

      if (Length == 0)
      {
        DPRINT("Unused address register\n");
        continue;
      }

      /* Set preferred descriptor */
      Descriptor->Option = IO_RESOURCE_PREFERRED;
      if (Flags & PCI_ADDRESS_IO_SPACE)
      {
        Descriptor->Type = CmResourceTypePort;
        Descriptor->ShareDisposition = CmResourceShareDeviceExclusive;
        Descriptor->Flags = CM_RESOURCE_PORT_IO |
                            CM_RESOURCE_PORT_16_BIT_DECODE |
                            CM_RESOURCE_PORT_POSITIVE_DECODE;

        Descriptor->u.Port.Length = Length;
        Descriptor->u.Port.Alignment = 1;
        Descriptor->u.Port.MinimumAddress.QuadPart = (ULONGLONG)Base;
        Descriptor->u.Port.MaximumAddress.QuadPart = (ULONGLONG)(Base + Length - 1);
      }
      else
      {
        Descriptor->Type = CmResourceTypeMemory;
        Descriptor->ShareDisposition = CmResourceShareDeviceExclusive;
        Descriptor->Flags = CM_RESOURCE_MEMORY_READ_WRITE;

        Descriptor->u.Memory.Length = Length;
        Descriptor->u.Memory.Alignment = 1;
        Descriptor->u.Memory.MinimumAddress.QuadPart = (ULONGLONG)Base;
        Descriptor->u.Memory.MaximumAddress.QuadPart = (ULONGLONG)(Base + Length - 1);
      }
      Descriptor++;

      /* Set alternative descriptor */
      Descriptor->Option = IO_RESOURCE_ALTERNATIVE;
      if (Flags & PCI_ADDRESS_IO_SPACE)
      {
        Descriptor->Type = CmResourceTypePort;
        Descriptor->ShareDisposition = CmResourceShareDeviceExclusive;
        Descriptor->Flags = CM_RESOURCE_PORT_IO |
                            CM_RESOURCE_PORT_16_BIT_DECODE |
                            CM_RESOURCE_PORT_POSITIVE_DECODE;

⌨️ 快捷键说明

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