pcirootbridgeio.c

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

C
1,750
字号
Returns:

  EFI_SUCCESS - TODO: Add description for return value

--*/
{
  MAP_INFO  *MapInfo;

  //
  // See if the Map() operation associated with this Unmap() required a mapping buffer.
  // If a mapping buffer was not required, then this function simply returns EFI_SUCCESS.
  //
  if (Mapping != NULL) {
    //
    // Get the MAP_INFO structure from Mapping
    //
    MapInfo = (MAP_INFO *) Mapping;

    //
    // If this is a write operation from the Bus Master's point of view,
    // then copy the contents of the mapped buffer into the real buffer
    // so the processor can read the contents of the real buffer.
    //
    if (MapInfo->Operation == EfiPciOperationBusMasterWrite || MapInfo->Operation == EfiPciOperationBusMasterWrite64) {
      EfiCopyMem (
        (VOID *) (UINTN) MapInfo->HostAddress,
        (VOID *) (UINTN) MapInfo->MappedHostAddress,
        MapInfo->NumberOfBytes
        );
    }

    //
    // Free the mapped buffer and the MAP_INFO structure.
    //
    gBS->FreePages (MapInfo->MappedHostAddress, MapInfo->NumberOfPages);
    gBS->FreePool (Mapping);
  }

  return EFI_SUCCESS;
}

EFI_STATUS
EFIAPI
RootBridgeIoAllocateBuffer (
  IN  EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL  *This,
  IN  EFI_ALLOCATE_TYPE                Type,
  IN  EFI_MEMORY_TYPE                  MemoryType,
  IN  UINTN                            Pages,
  OUT VOID                             **HostAddress,
  IN  UINT64                           Attributes
  )
/*++

Routine Description:

  TODO: Add function description

Arguments:

  This        - TODO: add argument description
  Type        - TODO: add argument description
  MemoryType  - TODO: add argument description
  Pages       - TODO: add argument description
  HostAddress - TODO: add argument description
  Attributes  - TODO: add argument description

Returns:

  EFI_UNSUPPORTED - TODO: Add description for return value
  EFI_INVALID_PARAMETER - TODO: Add description for return value
  EFI_UNSUPPORTED - TODO: Add description for return value
  EFI_INVALID_PARAMETER - TODO: Add description for return value
  EFI_SUCCESS - TODO: Add description for return value

--*/
{
  EFI_STATUS            Status;
  EFI_PHYSICAL_ADDRESS  PhysicalAddress;

  //
  // Validate Attributes
  //
  if (Attributes & EFI_PCI_ATTRIBUTE_INVALID_FOR_ALLOCATE_BUFFER) {
    return EFI_UNSUPPORTED;
  }

  //
  // Check for invalid inputs
  //
  if (HostAddress == NULL) {
    return EFI_INVALID_PARAMETER;
  }

  if ((EFI_PHYSICAL_ADDRESS) (UINTN) (*HostAddress) > 0xffffffff) {
    return EFI_UNSUPPORTED;
  }
  
  //
  // The only valid memory types are EfiBootServicesData and EfiRuntimeServicesData
  //
  if (MemoryType != EfiBootServicesData && MemoryType != EfiRuntimeServicesData) {
    return EFI_INVALID_PARAMETER;
  }

  //
  // Limit allocations to memory below 4GB
  //
  PhysicalAddress = (EFI_PHYSICAL_ADDRESS) (UINTN) (0xffffffff);

  Status          = gBS->AllocatePages (AllocateMaxAddress, MemoryType, Pages, &PhysicalAddress);
  if (EFI_ERROR (Status)) {
    return Status;
  }

  *HostAddress = (VOID *) (UINTN) PhysicalAddress;

  return EFI_SUCCESS;
}

EFI_STATUS
EFIAPI
RootBridgeIoFreeBuffer (
  IN  EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL  *This,
  IN  UINTN                            Pages,
  OUT VOID                             *HostAddress
  )
/*++

Routine Description:

  TODO: Add function description

Arguments:

  This        - TODO: add argument description
  Pages       - TODO: add argument description
  HostAddress - TODO: add argument description

Returns:

  TODO: add return values

--*/
{
  return gBS->FreePages ((EFI_PHYSICAL_ADDRESS) (UINTN) HostAddress, Pages);
}

EFI_STATUS
EFIAPI
RootBridgeIoFlush (
  IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL           *This
  )
/*++

Routine Description:

Arguments:
    
Returns:

--*/
// TODO:    This - add argument and description to function comment
// TODO:    EFI_SUCCESS - add return value to function comment
{
  //
  // not supported yet
  //
  return EFI_SUCCESS;
}

EFI_STATUS
EFIAPI
RootBridgeIoGetAttributes (
  IN  EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL  *This,
  OUT UINT64                           *Supported,
  OUT UINT64                           *Attributes
  )
/*++

Routine Description:

Arguments:
    
Returns:

--*/
// TODO:    This - add argument and description to function comment
// TODO:    Supported - add argument and description to function comment
// TODO:    Attributes - add argument and description to function comment
// TODO:    EFI_INVALID_PARAMETER - add return value to function comment
// TODO:    EFI_SUCCESS - add return value to function comment
{
  PCI_ROOT_BRIDGE_INSTANCE  *PrivateData;

  PrivateData = DRIVER_INSTANCE_FROM_PCI_ROOT_BRIDGE_IO_THIS (This);

  if (Attributes == NULL && Supported == NULL) {
    return EFI_INVALID_PARAMETER;
  }

  //
  // Set the return value for Supported and Attributes
  //
  if (Supported) {
    *Supported = PrivateData->Supports;
  }

  if (Attributes) {
    *Attributes = PrivateData->Attributes;
  }

  return EFI_SUCCESS;
}

EFI_STATUS
EFIAPI
RootBridgeIoSetAttributes (
  IN     EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL  *This,
  IN     UINT64                           Attributes,
  IN OUT UINT64                           *ResourceBase,
  IN OUT UINT64                           *ResourceLength
  )
/*++

Routine Description:

Arguments:
    
Returns:

--*/
// TODO:    This - add argument and description to function comment
// TODO:    Attributes - add argument and description to function comment
// TODO:    ResourceBase - add argument and description to function comment
// TODO:    ResourceLength - add argument and description to function comment
// TODO:    EFI_UNSUPPORTED - add return value to function comment
// TODO:    EFI_SUCCESS - add return value to function comment
// TODO:    EFI_SUCCESS - add return value to function comment
{
  PCI_ROOT_BRIDGE_INSTANCE  *PrivateData;
  UINT64                    Address;
  UINT16                    Data;

  PrivateData = DRIVER_INSTANCE_FROM_PCI_ROOT_BRIDGE_IO_THIS (This);

  if (Attributes) {
    if ((Attributes & (~(PrivateData->Supports))) != 0) {
      return EFI_UNSUPPORTED;
    }
  }

  if (Attributes == PrivateData->Attributes) {
    return EFI_SUCCESS;
  }
  
  //
  // Set IDE primary
  //
  if (Attributes & EFI_PCI_ATTRIBUTE_IDE_PRIMARY_IO) {

    Address = EFI_PCI_ADDRESS (0x0, 0x1f, 0x1, 0x40);

    This->Pci.Read (This, EfiPciWidthUint16, Address, 1, &Data);
    Data |= 0x8000;
    This->Pci.Write (This, EfiPciWidthUint16, Address, 1, &Data);
  }
  
  //
  // Set IDE secondary
  //
  if (Attributes & EFI_PCI_ATTRIBUTE_IDE_SECONDARY_IO) {

    Address = EFI_PCI_ADDRESS (0x0, 0x1f, 0x1, 0x42);

    This->Pci.Read (This, EfiPciWidthUint16, Address, 1, &Data);
    Data |= 0x8000;
    This->Pci.Write (This, EfiPciWidthUint16, Address, 1, &Data);
  }
  
  //
  // It is just a trick for some attribute can only be enabled or disabled
  // otherwise it can impact on other devices
  //
  PrivateData->Attributes = Attributes;

  return EFI_SUCCESS;
}

EFI_STATUS
EFIAPI
RootBridgeIoConfiguration (
  IN     EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL  *This,
  OUT    VOID                             **Resources
  )
/*++

Routine Description:

Arguments:
    
Returns:

--*/
// TODO:    This - add argument and description to function comment
// TODO:    Resources - add argument and description to function comment
// TODO:    EFI_SUCCESS - add return value to function comment
{
  PCI_ROOT_BRIDGE_INSTANCE  *PrivateData;
  UINTN                     Index;

  PrivateData = DRIVER_INSTANCE_FROM_PCI_ROOT_BRIDGE_IO_THIS (This);

  for (Index = 0; Index < TypeMax; Index++) {
    if (PrivateData->ResAllocNode[Index].Status == ResAllocated) {
      mConfiguration.SpaceDesp[Index].AddrRangeMin = PrivateData->ResAllocNode[Index].Base;
      mConfiguration.SpaceDesp[Index].AddrRangeMax =
      PrivateData->ResAllocNode[Index].Base + PrivateData->ResAllocNode[Index].Length - 1;
      mConfiguration.SpaceDesp[Index].AddrLen = PrivateData->ResAllocNode[Index].Length;
    }
  }

  *Resources = &mConfiguration;
  return EFI_SUCCESS;
}

//
// Internal function
//

STATIC
EFI_STATUS
RootBridgeIoPciRW (
  IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL        *This,
  IN BOOLEAN                                Write,
  IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH  Width,
  IN UINT64                                 UserAddress,
  IN UINTN                                  Count,
  IN OUT VOID                               *UserBuffer
  )
/*++

Routine Description:

Arguments:
    
Returns:

--*/
// TODO:    This - add argument and description to function comment
// TODO:    Write - add argument and description to function comment
// TODO:    Width - add argument and description to function comment
// TODO:    UserAddress - add argument and description to function comment
// TODO:    Count - add argument and description to function comment
// TODO:    UserBuffer - add argument and description to function comment
// TODO:    EFI_INVALID_PARAMETER - add return value to function comment
// TODO:    EFI_UNSUPPORTED - add return value to function comment
// TODO:    EFI_SUCCESS - add return value to function comment
{
  PCI_CONFIG_ACCESS_CF8     Pci;
  PCI_CONFIG_ACCESS_CF8     PciAligned;
  UINT32                    InStride;
  UINT32                    OutStride;
  UINTN                     PciData;
  UINTN                     PciDataStride;
  PCI_ROOT_BRIDGE_INSTANCE  *PrivateData;

  if ((Width & 0x03) >= EfiPciWidthUint64) {
    return EFI_INVALID_PARAMETER;
  }

  PrivateData = DRIVER_INSTANCE_FROM_PCI_ROOT_BRIDGE_IO_THIS (This);

  InStride    = 1 << (Width & 0x03);
  OutStride   = InStride;
  if (Width >= EfiCpuIoWidthFifoUint8 && Width <= EfiCpuIoWidthFifoUint64) {
    InStride = 0;
  }

  if (Width >= EfiCpuIoWidthFillUint8 && Width <= EfiCpuIoWidthFillUint64) {
    OutStride = 0;
  }

  if (((EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_PCI_ADDRESS *) &UserAddress)->ExtendedRegister != 0) {
    //
    // For Pci bus driver has made parameter check before calling this function,
    // there is no need to check the parameters again here
    //
    return EFI_UNSUPPORTED;
  } else {
    Pci.Reg = ((EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_PCI_ADDRESS *) &UserAddress)->Register;
  }

  Pci.Func      = ((EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_PCI_ADDRESS *) &UserAddress)->Function;
  Pci.Dev       = ((EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_PCI_ADDRESS *) &UserAddress)->Device;
  Pci.Bus       = ((EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_PCI_ADDRESS *) &UserAddress)->Bus;
  Pci.Reserved  = 0;
  Pci.Enable    = 1;

  //
  // PCI Configure access are all 32-bit aligned, but by accessing the
  //  CONFIG_DATA_REGISTER (0xcfc) with different widths more cycle types
  //  are possible on PCI.
  //
  // To read a byte of PCI configuration space you load 0xcf8 and
  //  read 0xcfc, 0xcfd, 0xcfe, 0xcff
  //
  PciDataStride = ((EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_PCI_ADDRESS *) &UserAddress)->Register & 0x03;

  while (Count) {
    PciAligned = Pci;
    PciAligned.Reg &= 0xfc;
    PciData = PrivateData->PciData + PciDataStride;
    EfiAcquireLock (&PrivateData->PciLock);
    This->Io.Write (
              This,
              EfiPciWidthUint32,
              PrivateData->PciAddress,
              1,
              &PciAligned
              );
    if (Write) {
      This->Io.Write (This, Width, PciData, 1, UserBuffer);
    } else {
      This->Io.Read (This, Width, PciData, 1, UserBuffer);
    }

    EfiReleaseLock (&PrivateData->PciLock);
    UserBuffer    = ((UINT8 *) UserBuffer) + OutStride;
    PciDataStride = (PciDataStride + InStride) % 4;
    Pci.Reg += InStride;
    Count -= 1;
  }

  return EFI_SUCCESS;
}

⌨️ 快捷键说明

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