pciio.c

来自「EFI BIOS是Intel提出的下一代的BIOS标准。这里上传的Edk源代码是」· C语言 代码 · 共 1,868 行 · 第 1/4 页

C
1,868
字号
      }
    }

    //
    // Check to see if an VGA related attributes are being set.
    //
    if ((NewAttributes & EFI_PCI_IO_ATTRIBUTE_VGA_PALETTE_IO) ^ (PciIoDevice->Attributes & EFI_PCI_IO_ATTRIBUTE_VGA_PALETTE_IO)) {

      if (NewAttributes & EFI_PCI_IO_ATTRIBUTE_VGA_PALETTE_IO) {
        EnableCommand  |= EFI_PCI_COMMAND_VGA_PALETTE_SNOOP;
      } else {
        DisableCommand  |= EFI_PCI_COMMAND_VGA_PALETTE_SNOOP;
      }
    }

  } else {

    if ((NewAttributes & EFI_PCI_IO_ATTRIBUTE_VGA_IO) ^ (PciIoDevice->Attributes & EFI_PCI_IO_ATTRIBUTE_VGA_IO)) {

      if (NewAttributes & EFI_PCI_IO_ATTRIBUTE_VGA_IO) {

        //
        //Check if there have been an active VGA device on the same segment
        //
        Temp = ActiveVGADeviceOnTheSameSegment (PciIoDevice);

        if (Temp && Temp != PciIoDevice) {
          return EFI_UNSUPPORTED;
        }
      }
    }

    if ((NewAttributes & EFI_PCI_IO_ATTRIBUTE_VGA_PALETTE_IO) ^ (PciIoDevice->Attributes & EFI_PCI_IO_ATTRIBUTE_VGA_PALETTE_IO)) {
      if (IS_PCI_GFX(&PciIoDevice->Pci)) {

        //
        //Get the boot VGA on the same segement
        //
        Temp = ActiveVGADeviceOnTheSameSegment (PciIoDevice);

        if (!Temp) {

          //
          // If there is no VGA device on the segement, set
          // this graphics card to decode the palette range
          //
          DisableCommand  |= EFI_PCI_COMMAND_VGA_PALETTE_SNOOP;
        } else {

          //
          // Check these two agents are on the same path
          //
          if (PciDevicesOnTheSamePath(Temp, PciIoDevice)) {

            //
            // Check if they are on the same bus
            //
            if (Temp->Parent == PciIoDevice->Parent) {

              PciReadCommandRegister (Temp, &Command);

              //
              // If they are on the same bus, either one can
              // be set to snoop, the other set to decode
              //
              if (Command & EFI_PCI_COMMAND_VGA_PALETTE_SNOOP) {
                DisableCommand  |= EFI_PCI_COMMAND_VGA_PALETTE_SNOOP;
              } else {
                EnableCommand  |= EFI_PCI_COMMAND_VGA_PALETTE_SNOOP;
              }
            } else {

              //
              // If they are on  the same path but on the different bus
              // The first agent is set to snoop, the second one set to
              // decode
              //
              if (Temp->BusNumber > PciIoDevice->BusNumber) {
                PciEnableCommandRegister(Temp,EFI_PCI_COMMAND_VGA_PALETTE_SNOOP);
                DisableCommand  |= EFI_PCI_COMMAND_VGA_PALETTE_SNOOP;
              } else {
                PciDisableCommandRegister(Temp,EFI_PCI_COMMAND_VGA_PALETTE_SNOOP);
                EnableCommand  |= EFI_PCI_COMMAND_VGA_PALETTE_SNOOP;
              }
            }
          } else {

            EnableCommand  |= EFI_PCI_COMMAND_VGA_PALETTE_SNOOP;
          }
        }
      }
    }
  }

  //
  // Check to see of the I/O enable is being modified
  //
  if ((NewAttributes & EFI_PCI_IO_ATTRIBUTE_IO) ^ (PciIoDevice->Attributes & EFI_PCI_IO_ATTRIBUTE_IO)) {
    if (NewAttributes & EFI_PCI_IO_ATTRIBUTE_IO) {
      EnableCommand |= EFI_PCI_COMMAND_IO_SPACE;
    } else {
      DisableCommand |= EFI_PCI_COMMAND_IO_SPACE;
    }
  }

  //
  // Check to see of the Memory enable is being modified
  //
  if ((NewAttributes & EFI_PCI_IO_ATTRIBUTE_MEMORY) ^ (PciIoDevice->Attributes & EFI_PCI_IO_ATTRIBUTE_MEMORY)) {
    if (NewAttributes & EFI_PCI_IO_ATTRIBUTE_MEMORY) {
      EnableCommand |= EFI_PCI_COMMAND_MEMORY_SPACE;
    } else {
      DisableCommand |= EFI_PCI_COMMAND_MEMORY_SPACE;
    }
  }

  //
  // Check to see of the Bus Master enable is being modified
  //
  if ((NewAttributes & EFI_PCI_IO_ATTRIBUTE_BUS_MASTER) ^ (PciIoDevice->Attributes & EFI_PCI_IO_ATTRIBUTE_BUS_MASTER)) {
    if (NewAttributes & EFI_PCI_IO_ATTRIBUTE_BUS_MASTER) {
      EnableCommand  |= EFI_PCI_COMMAND_BUS_MASTER;
    } else {
      DisableCommand |= EFI_PCI_COMMAND_BUS_MASTER;
    }
  }

  Status = EFI_SUCCESS;
  if (EnableCommand) {
    Status = PciEnableCommandRegister(PciIoDevice, EnableCommand);
  } 

  if (DisableCommand) {
    Status = PciDisableCommandRegister(PciIoDevice, DisableCommand);
  }

  if (EFI_ERROR(Status)) {
    return EFI_UNSUPPORTED;
  }

  if (EnableBridge) {
    Status = PciEnableBridgeControlRegister(PciIoDevice, EnableBridge);
  }

  if (DisableBridge) {
    Status = PciDisableBridgeControlRegister(PciIoDevice, DisableBridge);
  }
   
  if (EFI_ERROR(Status)) {
    return EFI_UNSUPPORTED;
  }

  //
  // Set the upstream bridge attributes
  //
  if (Operation != EfiPciIoAttributeOperationGet && Operation != EfiPciIoAttributeOperationSupported) {

    //
    // EFI_PCI_IO_ATTRIBUTE_MEMORY, EFI_PCI_IO_ATTRIBUTE_IO, EFI_PCI_IO_ATTRIBUTE_BUS_MASTER
    // EFI_PCI_IO_ATTRIBUTE_MEMORY_WRITE_COMBINE, EFI_PCI_IO_ATTRIBUTE_MEMORY_CACHED
    // EFI_PCI_IO_ATTRIBUTE_DUAL_ADDRESS_CYCLE will not effect to upstream bridge
    // 
    NewUpStreamBridgeAttributes = Attributes & \
                                (~(EFI_PCI_IO_ATTRIBUTE_IO | \
                                EFI_PCI_IO_ATTRIBUTE_MEMORY | \
                                EFI_PCI_IO_ATTRIBUTE_BUS_MASTER | \
                                EFI_PCI_IO_ATTRIBUTE_MEMORY_WRITE_COMBINE | \
                                EFI_PCI_IO_ATTRIBUTE_MEMORY_CACHED | \
                                EFI_PCI_IO_ATTRIBUTE_DUAL_ADDRESS_CYCLE));

    if (NewUpStreamBridgeAttributes){
      UpStreamBridgesAttributes(PciIoDevice, Operation, NewUpStreamBridgeAttributes);
    }
  }
  
  PciIoDevice->Attributes = NewAttributes;

  return Status;
}

EFI_STATUS
EFIAPI
PciIoGetBarAttributes (
  IN EFI_PCI_IO_PROTOCOL             * This,
  IN  UINT8                          BarIndex,
  OUT UINT64                         *Supports, OPTIONAL
  OUT VOID                           **Resources OPTIONAL
  )
/*++

Routine Description:


Arguments:

Returns:

  None

--*/
{

  UINT8                             *Configuration;
  UINT8                             NumConfig;
  PCI_IO_DEVICE                     *PciIoDevice;
  EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *Ptr;
  EFI_ACPI_END_TAG_DESCRIPTOR       *PtrEnd;

  NumConfig   = 0;

  PciIoDevice = PCI_IO_DEVICE_FROM_PCI_IO_THIS (This);

  if (Supports == NULL && Resources == NULL) {
    return EFI_INVALID_PARAMETER;
  }

  if (BarIndex >= PCI_MAX_BAR) {
    return EFI_UNSUPPORTED;
  }

  //
  // This driver does not support modifications to the WRITE_COMBINE or
  // CACHED attributes for BAR ranges.
  //
  if (Supports != NULL) {
    *Supports = PciIoDevice->Supports & EFI_PCI_IO_ATTRIBUTE_MEMORY_CACHED & EFI_PCI_IO_ATTRIBUTE_MEMORY_WRITE_COMBINE;
  }

  if (Resources != NULL) {

    if (PciIoDevice->PciBar[BarIndex].BarType != PciBarTypeUnknown) {
      NumConfig = 1;
    }

    Configuration = EfiLibAllocatePool (sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR) * NumConfig + sizeof (EFI_ACPI_END_TAG_DESCRIPTOR));
    if (Configuration == NULL) {
      return EFI_OUT_OF_RESOURCES;
    }

    EfiZeroMem (
      Configuration,
      sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR) * NumConfig + sizeof (EFI_ACPI_END_TAG_DESCRIPTOR)
      );

    Ptr = (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *) Configuration;

    if (NumConfig == 1) {
      Ptr->Desc         = ACPI_ADDRESS_SPACE_DESCRIPTOR;
      Ptr->Len          = sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR) - 3;

      Ptr->AddrRangeMin = PciIoDevice->PciBar[BarIndex].BaseAddress;
      Ptr->AddrLen      = PciIoDevice->PciBar[BarIndex].Length;
      Ptr->AddrRangeMax = PciIoDevice->PciBar[BarIndex].Alignment;

      switch (PciIoDevice->PciBar[BarIndex].BarType) {
      case PciBarTypeIo16:
      case PciBarTypeIo32:
        //
        // Io
        //
        Ptr->ResType = ACPI_ADDRESS_SPACE_TYPE_IO;
        break;

      case PciBarTypeMem32:
        //
        // Mem
        //
        Ptr->ResType = ACPI_ADDRESS_SPACE_TYPE_MEM;
        //
        // 32 bit
        //
        Ptr->AddrSpaceGranularity = 32;
        break;

      case PciBarTypePMem32:
        //
        // Mem
        //
        Ptr->ResType = ACPI_ADDRESS_SPACE_TYPE_MEM;
        //
        // prefechable
        //
        Ptr->SpecificFlag = 0x6;
        //
        // 32 bit
        //
        Ptr->AddrSpaceGranularity = 32;
        break;

      case PciBarTypeMem64:
        //
        // Mem
        //
        Ptr->ResType = ACPI_ADDRESS_SPACE_TYPE_MEM;
        //
        // 64 bit
        //
        Ptr->AddrSpaceGranularity = 64;
        break;

      case PciBarTypePMem64:
        //
        // Mem
        //
        Ptr->ResType = ACPI_ADDRESS_SPACE_TYPE_MEM;
        //
        // prefechable
        //
        Ptr->SpecificFlag = 0x6;
        //
        // 64 bit
        //
        Ptr->AddrSpaceGranularity = 64;
        break;
      }

      Ptr = (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *) ((UINT8 *) Ptr + sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR));
    }
    
    //
    // put the checksum
    //
    PtrEnd            = (EFI_ACPI_END_TAG_DESCRIPTOR *) ((UINT8 *) Ptr);
    PtrEnd->Desc      = ACPI_END_TAG_DESCRIPTOR;
    PtrEnd->Checksum  = 0;

    *Resources        = Configuration;
  }

  return EFI_SUCCESS;
}

EFI_STATUS
EFIAPI
PciIoSetBarAttributes (
  IN EFI_PCI_IO_PROTOCOL              *This,
  IN     UINT64                       Attributes,
  IN     UINT8                        BarIndex,
  IN OUT UINT64                       *Offset,
  IN OUT UINT64                       *Length
  )
/*++

Routine Description:


Arguments:

Returns:

  None

--*/
{
  EFI_STATUS    Status;
  PCI_IO_DEVICE *PciIoDevice;
  UINT64        NonRelativeOffset;
  UINT64        Supports;

  PciIoDevice = PCI_IO_DEVICE_FROM_PCI_IO_THIS (This);

  //
  // Make sure Offset and Length are not NULL
  //
  if (Offset == NULL || Length == NULL) {
    return EFI_INVALID_PARAMETER;
  }

  if (PciIoDevice->PciBar[BarIndex].BarType == PciBarTypeUnknown) {
    return EFI_UNSUPPORTED;
  }
  //
  // This driver does not support setting the WRITE_COMBINE or the CACHED attributes.
  // If Attributes is not 0, then return EFI_UNSUPPORTED.
  //
  Supports = PciIoDevice->Supports & EFI_PCI_IO_ATTRIBUTE_MEMORY_CACHED & EFI_PCI_IO_ATTRIBUTE_MEMORY_WRITE_COMBINE;

  if (Attributes != (Attributes & Supports)) {
    return EFI_UNSUPPORTED;
  }
  //
  // Attributes must be supported.  Make sure the BAR range describd by BarIndex, Offset, and
  // Length are valid for this PCI device.
  //
  NonRelativeOffset = *Offset;
  Status = PciIoVerifyBarAccess (
            PciIoDevice,
            BarIndex,
            PciBarTypeMem,
            EfiPciIoWidthUint8,
            (UINT32) *Length,
            &NonRelativeOffset
            );
  if (EFI_ERROR (Status)) {
    return EFI_UNSUPPORTED;
  }

  return EFI_SUCCESS;
}

EFI_STATUS
UpStreamBridgesAttributes (
  IN  PCI_IO_DEVICE                            *PciIoDevice,
  IN  EFI_PCI_IO_PROTOCOL_ATTRIBUTE_OPERATION  Operation,
  IN  UINT64                                   Attributes
  )
/*++

Routine Description:

Arguments:

Returns:

  None

--*/
{
  PCI_IO_DEVICE       *Parent;
  EFI_PCI_IO_PROTOCOL *PciIo;

  Parent = PciIoDevice->Parent;

  while (Parent && IS_PCI_BRIDGE (&Parent->Pci)) {

    //
    // Get the PciIo Protocol
    //
    PciIo = &Parent->PciIo;

    PciIo->Attributes (PciIo, Operation, Attributes, NULL);

    Parent = Parent->Parent;
  }

  return EFI_SUCCESS;
}

BOOLEAN
PciDevicesOnTheSamePath (
  IN PCI_IO_DEVICE        *PciDevice1,
  IN PCI_IO_DEVICE        *PciDevice2
  )
/*++

Routine Description:

Arguments:

  PciDevice1  -  The pointer to the first PCI_IO_DEVICE.
  PciDevice2  -  The pointer to the second PCI_IO_DEVICE.

Returns:

  TRUE   -  The two Pci devices are on the same path.
  FALSE  -  The two Pci devices are not on the same path.

--*/
{

  if (PciDevice1->Parent == PciDevice2->Parent) {
    return TRUE;
  }

  return (PciDeviceExisted (PciDevice1->Parent, PciDevice2)|| PciDeviceExisted (PciDevice2->Parent, PciDevice1));
}

⌨️ 快捷键说明

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