Пример #1
0
EFI_STATUS
EFIAPI
PcatRootBridgeIoSetAttributes (
  IN     EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL  *This,
  IN     UINT64                           Attributes,
  IN OUT UINT64                           *ResourceBase,
  IN OUT UINT64                           *ResourceLength 
  )

{
  PCAT_PCI_ROOT_BRIDGE_INSTANCE   *PrivateData;
  
  PrivateData = DRIVER_INSTANCE_FROM_PCI_ROOT_BRIDGE_IO_THIS(This);

  //
  // This is a generic driver for a PC-AT class system.  It does not have any
  // chipset specific knowlegde, so none of the attributes can be set or 
  // cleared.  Any attempt to set attribute that are already set will succeed, 
  // and any attempt to set an attribute that is not supported will fail.
  //
  if (Attributes & (~PrivateData->Attributes)) {
    return EFI_UNSUPPORTED;
  }

  return EFI_SUCCESS;
}
Пример #2
0
EFI_STATUS
EFIAPI
RootBridgeIoConfiguration (
  IN  EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL     *This,
  OUT VOID                                **Resources
  )
/*++

Routine Description:

Arguments:
    
Returns:

--*/
{
  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) {
      Configuration.SpaceDesp[Index].AddrRangeMin = PrivateData->ResAllocNode[Index].Base;
      Configuration.SpaceDesp[Index].AddrRangeMax = PrivateData->ResAllocNode[Index].Base + PrivateData->ResAllocNode[Index].Length - 1;
      Configuration.SpaceDesp[Index].AddrLen      = PrivateData->ResAllocNode[Index].Length;
    }  
  }  
    
  *Resources = &Configuration;      
  return EFI_SUCCESS;
}
Пример #3
0
EFI_STATUS
EFIAPI
RootBridgeIoMemRead (
  IN     EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL        *This,
  IN     EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH  Width,
  IN     UINT64                                 Address,
  IN     UINTN                                  Count,
  IN OUT VOID                                   *Buffer
  )
/*++

Routine Description:
  Memory read
  
Arguments:
    
Returns:

--*/  
{
  PCI_ROOT_BRIDGE_INSTANCE                 *PrivateData;
  EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH    OldWidth;
  UINTN                                    OldCount;
  
  if (Buffer == NULL) {
    return EFI_INVALID_PARAMETER;
  }

  if (Width < 0 || Width >= EfiPciWidthMaximum) {
    return EFI_INVALID_PARAMETER;
  }

  PrivateData = DRIVER_INSTANCE_FROM_PCI_ROOT_BRIDGE_IO_THIS(This);

  //
  // Check memory access limit
  //
  if (Address < PrivateData->MemBase) {
    return EFI_INVALID_PARAMETER;
  }

  OldWidth = Width;
  OldCount = Count;

  if (Width >= EfiPciWidthFifoUint8 && Width <= EfiPciWidthFifoUint64) {
    Count = 1;
  }

  Width = (EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH)(Width & 0x03);

  if (Address + (((UINTN)1 << Width) * Count) - 1 > PrivateData->MemLimit) {
    return EFI_INVALID_PARAMETER;
  }

  return mCpuIo->Mem.Read (mCpuIo, (EFI_CPU_IO_PROTOCOL_WIDTH) OldWidth, 
                       Address, OldCount, Buffer);
}
Пример #4
0
EFI_STATUS
EFIAPI
RootBridgeIoGetAttributes (
  IN  EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL  *This,
  OUT UINT64                           *Supported,
  OUT UINT64                           *Attributes
  )
/*++

Routine Description:

  Get the attributes that a PCI root bridge supports and 
  the attributes the PCI root bridge is currently using.
  
Arguments:

  This        -  Pointer to EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL
                 instance.
  Supports    -  A pointer to the mask of attributes that 
                 this PCI root bridge supports.
  Attributes  -  A pointer to the mask of attributes that 
                 this PCI root bridge is currently using.
Returns:

  EFI_SUCCESS            -  Success.
  EFI_INVALID_PARAMETER  -  Invalid parameter found.
  
--*/

// GC_TODO:    Supported - add argument and description to function comment
//
// GC_TODO:    Supported - add argument and description to function comment
//
// GC_TODO:    Supported - add argument and description 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;
}
Пример #5
0
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:

  Sets the attributes for a resource range on a PCI root bridge.
  
Arguments:

  This            -  Pointer to EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL instance.
  Attributes      -  The mask of attributes to set.
  ResourceBase    -  Pointer to the base address of the resource range 
                     to be modified by the attributes specified by Attributes.
  ResourceLength  -  Pointer to the length of the resource range to be modified.
  
Returns:
  EFI_SUCCESS            -  Success.
  EFI_INVALID_PARAMETER  -  Invalid parameter found.
  EFI_OUT_OF_RESOURCES   -  Not enough resources to set the attributes upon.

--*/

//
// GC_TODO:    EFI_UNSUPPORTED - add return value to function comment
//
{
  PCI_ROOT_BRIDGE_INSTANCE  *PrivateData;

  PrivateData = DRIVER_INSTANCE_FROM_PCI_ROOT_BRIDGE_IO_THIS (This);

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

  if (Attributes == PrivateData->Attributes) {
    return EFI_SUCCESS;
  }
  //
  // 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;
}
Пример #6
0
EFI_STATUS
EFIAPI
PcatRootBridgeIoConfiguration (
  IN  EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL  *This,
  OUT VOID                             **Resources
  )

{
  PCAT_PCI_ROOT_BRIDGE_INSTANCE   *PrivateData;
  
  PrivateData = DRIVER_INSTANCE_FROM_PCI_ROOT_BRIDGE_IO_THIS(This);

  *Resources = PrivateData->Configuration;

  return EFI_SUCCESS;
}
Пример #7
0
EFI_STATUS
EFIAPI
PcatRootBridgeIoMemWrite (
  IN     EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL        *This,
  IN     EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH  Width,
  IN     UINT64                                 Address,
  IN     UINTN                                  Count,
  IN OUT VOID                                   *Buffer
  )
{
  PCAT_PCI_ROOT_BRIDGE_INSTANCE *PrivateData;
  UINTN  AlignMask;
  PTR    In;
  PTR    Out;

  if ( Buffer == NULL ) {
    return EFI_INVALID_PARAMETER;
  }
  
  PrivateData = DRIVER_INSTANCE_FROM_PCI_ROOT_BRIDGE_IO_THIS(This);

  if (!PcatRootBridgeMemAddressValid (PrivateData, Address)) {
    return EFI_INVALID_PARAMETER;
  }

  AlignMask = (1 << (Width & 0x03)) - 1;
  if (Address & AlignMask) {
    return EFI_INVALID_PARAMETER;
  }

  Address += PrivateData->PhysicalMemoryBase;

  In.buf  = (VOID *)(UINTN) Address;
  Out.buf = Buffer;
  if ((UINT32)Width <= EfiPciWidthUint64) {
    return PcatRootBridgeIoMemRW (Width, Count, TRUE, In, TRUE, Out);
  }
  if (Width >= EfiPciWidthFifoUint8 && Width <= EfiPciWidthFifoUint64) {
    return PcatRootBridgeIoMemRW (Width, Count, FALSE, In, TRUE, Out);
  }
  if (Width >= EfiPciWidthFillUint8 && Width <= EfiPciWidthFillUint64) {
    return PcatRootBridgeIoMemRW (Width, Count, TRUE, In, FALSE, Out);
  }

  return EFI_INVALID_PARAMETER;
}
Пример #8
0
EFI_STATUS
EFIAPI
PcatRootBridgeIoGetAttributes (
  IN  EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL  *This,
  OUT UINT64                           *Supported,  OPTIONAL
  OUT UINT64                           *Attributes
  )

{
  PCAT_PCI_ROOT_BRIDGE_INSTANCE *PrivateData;

  PrivateData = DRIVER_INSTANCE_FROM_PCI_ROOT_BRIDGE_IO_THIS(This);

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

  //
  // Supported is an OPTIONAL parameter.  See if it is NULL
  //
  if (Supported) {
    //
    // This is a generic driver for a PC-AT class system.  It does not have any
    // chipset specific knowlegde, so none of the attributes can be set or 
    // cleared.  Any attempt to set attribute that are already set will succeed, 
    // and any attempt to set an attribute that is not supported will fail.
    //
    *Supported = PrivateData->Attributes;
  }

  //
  // Set Attrbutes to the attributes detected when the PCI Root Bridge was initialized
  //
  
  if (Attributes) {
    *Attributes = PrivateData->Attributes;
  }
  
   
  return EFI_SUCCESS;
}
Пример #9
0
EFI_STATUS
EFIAPI
RootBridgeIoGetAttributes (
  IN  EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL  *This,
  OUT UINT64                           *Supported,
  OUT UINT64                           *Attributes
  )
/*++

Routine Description:

Arguments:
    
Returns:

--*/
{
  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;
}
Пример #10
0
EFI_STATUS
EFIAPI
RootBridgeIoIoWrite (
  IN     EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL          *This,
  IN     EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH    Width,
  IN     UINT64                                   Address,
  IN     UINTN                                    Count,
  IN OUT VOID                                     *Buffer
  )
/*++

Routine Description:

  Enable a PCI driver to write to PCI controller registers in the 
  PCI root bridge I/O space.
  
Arguments:

  This     -  A pointer to EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL
  Width    -  Signifies the width of the memory operation.
  Address  -  The base address of the I/O operation.
  Count    -  The number of I/O operations to perform.
  Buffer   -  The source buffer to write data from.
              
Returns:

  EFI_SUCCESS            -  The data was written to the PCI root bridge.
  EFI_INVALID_PARAMETER  -  Invalid parameters found.
  EFI_OUT_OF_RESOURCES   -  The request could not be completed due to a lack of 
                            resources.
--*/
{
  UINTN                     AlignMask;
  PCI_ROOT_BRIDGE_INSTANCE  *PrivateData;

  if (Buffer == NULL) {
    return EFI_INVALID_PARAMETER;
  }

  if (Width < 0 ||
      Width == EfiPciWidthUint64 ||
      Width == EfiPciWidthFifoUint64 ||
      Width == EfiPciWidthFillUint64 ||
      Width >= EfiPciWidthMaximum
      ) {
    return EFI_INVALID_PARAMETER;
  }

  PrivateData = DRIVER_INSTANCE_FROM_PCI_ROOT_BRIDGE_IO_THIS (This);

  //
  // AlignMask = (1 << Width) - 1;
  //
  AlignMask = (1 << (Width & 0x03)) - 1;

  //
  // Check Io access limit
  //
  if (Address > PrivateData->Aperture.IoLimit) {
    return EFI_INVALID_PARAMETER;
  }

  if (Address & AlignMask) {
    return EFI_INVALID_PARAMETER;
  }

  return mCpuIo->Io.Write (
                      mCpuIo,
                      (EFI_CPU_IO_PROTOCOL_WIDTH) Width,
                      Address,
                      Count,
                      Buffer
                      );

}
Пример #11
0
EFI_STATUS
SimpleIioRootBridgeConstructor (
  IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL       *Protocol,
  IN EFI_HANDLE                            HostBridgeHandle,
  IN PCI_ROOT_BRIDGE_RESOURCE_APERTURE     *ResAperture,
  UINT64                                   AllocAttributes

  )
/*++

Routine Description:

  Construct the Pci Root Bridge Io protocol.

Arguments:

  Protocol          -  Protocol to initialize.
  HostBridgeHandle  -  Handle to the HostBridge.
  ResAperture       -  Resource apperture of the root bridge.
  AllocAttributes   -  Attribute of resouce allocated.
    
Returns:

  EFI_SUCCESS  -  Success.
  Others       -  Fail.

--*/
{
  EFI_STATUS                Status;
  PCI_ROOT_BRIDGE_INSTANCE  *PrivateData;
  PCI_RESOURCE_TYPE         Index;
  UINT32                    HecBase;
  UINT32                    HecSize;

  PrivateData = DRIVER_INSTANCE_FROM_PCI_ROOT_BRIDGE_IO_THIS (Protocol);

  //
  // Initialize the apertures with default values
  //
  CopyMem (
    &PrivateData->Aperture,
    ResAperture,
    sizeof (PCI_ROOT_BRIDGE_RESOURCE_APERTURE)
    );

  for (Index = TypeIo; Index < TypeMax; Index++) {
    PrivateData->ResAllocNode[Index].Type   = Index;
    PrivateData->ResAllocNode[Index].Base   = 0;
    PrivateData->ResAllocNode[Index].Length = 0;
    PrivateData->ResAllocNode[Index].Status = ResNone;
  }

  EfiInitializeLock (&PrivateData->PciLock, TPL_HIGH_LEVEL);
  PrivateData->PciAddress             = 0xCF8;
  PrivateData->PciData                = 0xCFC;

  PrivateData->RootBridgeAllocAttrib  = AllocAttributes;
  PrivateData->Attributes             = 0;
  PrivateData->Supports = EFI_PCI_ATTRIBUTE_IDE_PRIMARY_IO |
    EFI_PCI_ATTRIBUTE_IDE_SECONDARY_IO |
    EFI_PCI_ATTRIBUTE_ISA_IO_16         |
    EFI_PCI_ATTRIBUTE_VGA_PALETTE_IO_16 |
    EFI_PCI_ATTRIBUTE_VGA_MEMORY |
    EFI_PCI_ATTRIBUTE_VGA_IO_16;

  //
  // Don't support BASE above 4GB currently
  // Position to bit 39:28
  //
  HecBase = (UINT32) mIioUds->IioUdsPtr->PlatformData.PciExpressBase;
  HecSize = (UINT32) mIioUds->IioUdsPtr->PlatformData.PciExpressSize;

  ASSERT ((HecBase & (HecSize - 1)) == 0);    
  ASSERT (HecBase != 0);

  PrivateData->HecBase            = HecBase;
  PrivateData->HecLen             = HecSize;

  PrivateData->BusNumberAssigned  = FALSE;
  PrivateData->BusScanCount       = 0;

  Protocol->ParentHandle          = HostBridgeHandle;

  Protocol->PollMem               = RootBridgeIoPollMem;
  Protocol->PollIo                = RootBridgeIoPollIo;

  Protocol->Mem.Read              = RootBridgeIoMemRead;
  Protocol->Mem.Write             = RootBridgeIoMemWrite;

  Protocol->Io.Read               = RootBridgeIoIoRead;
  Protocol->Io.Write              = RootBridgeIoIoWrite;

  Protocol->CopyMem               = RootBridgeIoCopyMem;

  Protocol->Pci.Read              = RootBridgeIoPciRead;
  Protocol->Pci.Write             = RootBridgeIoPciWrite;

  Protocol->Map                   = RootBridgeIoMap;
  Protocol->Unmap                 = RootBridgeIoUnmap;

  Protocol->AllocateBuffer        = RootBridgeIoAllocateBuffer;
  Protocol->FreeBuffer            = RootBridgeIoFreeBuffer;

  Protocol->Flush                 = RootBridgeIoFlush;

  Protocol->GetAttributes         = RootBridgeIoGetAttributes;
  Protocol->SetAttributes         = RootBridgeIoSetAttributes;

  Protocol->Configuration         = RootBridgeIoConfiguration;

  Protocol->SegmentNumber         = 0;

  Status                          = gBS->LocateProtocol (&gEfiMetronomeArchProtocolGuid, NULL, &mMetronome);
  ASSERT_EFI_ERROR (Status);

  Status = gBS->LocateProtocol (
                  &gEfiCpuIoProtocolGuid,
                  NULL,
                  &mCpuIo
                  );
  ASSERT_EFI_ERROR (Status);

  return EFI_SUCCESS;
}
Пример #12
0
EFI_STATUS
EFIAPI
RootBridgeIoMemWrite (
  IN     EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL        *This,
  IN     EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH  Width,
  IN     UINT64                                 Address,
  IN     UINTN                                  Count,
  IN OUT VOID                                   *Buffer
  )
/*++

Routine Description:

  Allow write to memory mapped I/O space.
  
Arguments:

  This     -  Pointer to EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL instance.
  Width    -  The width of memory operation.
  Address  -  Base address of the memory operation.
  Count    -  Number of memory opeartion to perform.
  Buffer   -  The source buffer to write data from.
  
Returns:

  EFI_SUCCESS            -  Success.
  EFI_INVALID_PARAMETER  -  Invalid parameter found.
  EFI_OUT_OF_RESOURCES   -  Fail due to lack of resources.
  
--*/
{
  PCI_ROOT_BRIDGE_INSTANCE  *PrivateData;

  if (Buffer == NULL) {
    return EFI_INVALID_PARAMETER;
  }

  if (Width < 0 ||
      Width == EfiPciWidthUint64 ||
      Width == EfiPciWidthFifoUint64 ||
      Width == EfiPciWidthFillUint64 ||
      Width >= EfiPciWidthMaximum
      ) {
    return EFI_INVALID_PARAMETER;
  }

  PrivateData = DRIVER_INSTANCE_FROM_PCI_ROOT_BRIDGE_IO_THIS (This);

  //
  // Check memory access limit
  //
  if (PrivateData->Aperture.Mem64Limit > PrivateData->Aperture.Mem64Base) {
      if (Address > PrivateData->Aperture.Mem64Limit) {
        return EFI_INVALID_PARAMETER;
      }
  } else {
      if (Address > PrivateData->Aperture.Mem32Limit) {
        return EFI_INVALID_PARAMETER;
      }
  }

  return mCpuIo->Mem.Write (
                      mCpuIo,
                      (EFI_CPU_IO_PROTOCOL_WIDTH) Width,
                      Address,
                      Count,
                      Buffer
                      );
}
Пример #13
0
EFI_STATUS
EFIAPI
RootBridgeIoConfiguration (
  IN  EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL  *This,
  OUT VOID                             **Resources
  )
/*++

Routine Description:

  Retrieves the current resource settings of this PCI root bridge
  in the form of a set of ACPI 2.0 resource descriptor.
  
Arguments:

  This       -  Pointer to the EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL instance.
  Resources  -  Pointer to the ACPI 2.0 resource descriptor that
                describe the current configuration of this PCI root
                bridge.
                
Returns:

  EFI_SUCCESS      -  Success.
  EFI_UNSUPPORTED  -  Current configuration of the PCI root bridge
                      could not be retrieved.
                      
--*/

//
// GC_TODO:    EFI_OUT_OF_RESOURCES - add return value to function comment
//
{
  EFI_STATUS                        Status;
  UINTN                             Idx;

  PCI_ROOT_BRIDGE_INSTANCE          *RbPrivateData;
  PCI_RES_NODE                      *ResAllocNode;
  EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *Config;

  //
  // Get this instance of the Root Bridge.
  //
  RbPrivateData = DRIVER_INSTANCE_FROM_PCI_ROOT_BRIDGE_IO_THIS (This);

  //
  // If the pointer is not NULL, it points to a buffer already allocated.
  //
  if (RbPrivateData->ConfigBuffer == NULL) {
    Status = gBS->AllocatePool (
                    EfiBootServicesData,
                    TypeMax * sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR) + sizeof (EFI_ACPI_END_TAG_DESCRIPTOR),
                    &RbPrivateData->ConfigBuffer
                    );
    if (EFI_ERROR (Status)) {
      return EFI_OUT_OF_RESOURCES;
    }
  }

  Config = RbPrivateData->ConfigBuffer;

  ZeroMem (Config, TypeMax * sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR) + sizeof (EFI_ACPI_END_TAG_DESCRIPTOR));

  for (Idx = 0; Idx < TypeMax; Idx++) {

    ResAllocNode = &RbPrivateData->ResAllocNode[Idx];

    if (ResAllocNode->Status != ResAllocated) {
      continue;
    }

    switch (ResAllocNode->Type) {

    case TypeIo:
      Config->Desc          = ACPI_ADDRESS_SPACE_DESCRIPTOR;
      Config->Len           = sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR) - 3;
      Config->ResType       = ACPI_ADDRESS_SPACE_TYPE_IO;
      Config->AddrRangeMin  = ResAllocNode->Base;
      Config->AddrRangeMax  = ResAllocNode->Base + ResAllocNode->Length - 1;
      Config->AddrLen       = ResAllocNode->Length;
      break;

    case TypeMem32:
      Config->Desc                  = ACPI_ADDRESS_SPACE_DESCRIPTOR;
      Config->Len                   = sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR) - 3;
      Config->ResType               = ACPI_ADDRESS_SPACE_TYPE_MEM;
      Config->AddrSpaceGranularity  = 32;
      Config->AddrRangeMin          = ResAllocNode->Base;
      Config->AddrRangeMax          = ResAllocNode->Base + ResAllocNode->Length - 1;
      Config->AddrLen               = ResAllocNode->Length;
      break;

    case TypePMem32:
      Config->Desc                  = ACPI_ADDRESS_SPACE_DESCRIPTOR;
      Config->Len                   = sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR) - 3;
      Config->ResType               = ACPI_ADDRESS_SPACE_TYPE_MEM;
      Config->SpecificFlag          = 6;
      Config->AddrSpaceGranularity  = 32;
      Config->AddrRangeMin          = ResAllocNode->Base;
      Config->AddrRangeMax          = ResAllocNode->Base + ResAllocNode->Length - 1;
      Config->AddrLen               = ResAllocNode->Length;
      break;

    case TypeMem64:
      Config->Desc                  = ACPI_ADDRESS_SPACE_DESCRIPTOR;
      Config->Len                   = sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR) - 3;
      Config->ResType               = ACPI_ADDRESS_SPACE_TYPE_MEM;
      Config->SpecificFlag          = 6;
      Config->AddrSpaceGranularity  = 64;
      Config->AddrRangeMin          = ResAllocNode->Base;
      Config->AddrRangeMax          = ResAllocNode->Base + ResAllocNode->Length - 1;
      Config->AddrLen               = ResAllocNode->Length;
      break;

    case TypePMem64:
      Config->Desc                  = ACPI_ADDRESS_SPACE_DESCRIPTOR;
      Config->Len                   = sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR) - 3;
      Config->ResType               = ACPI_ADDRESS_SPACE_TYPE_MEM;
      Config->SpecificFlag          = 6;
      Config->AddrSpaceGranularity  = 64;
      Config->AddrRangeMin          = ResAllocNode->Base;
      Config->AddrRangeMax          = ResAllocNode->Base + ResAllocNode->Length - 1;
      Config->AddrLen               = ResAllocNode->Length;
      break;

    case TypeBus:
      Config->Desc          = ACPI_ADDRESS_SPACE_DESCRIPTOR;
      Config->Len           = sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR) - 3;
      Config->ResType       = ACPI_ADDRESS_SPACE_TYPE_BUS;
      Config->AddrRangeMin  = ResAllocNode->Base;
      Config->AddrRangeMax  = ResAllocNode->Base + ResAllocNode->Length - 1;
      Config->AddrLen       = ResAllocNode->Length;
      break;

    default:
      break;
    }

    Config++;
  }
  //
  // Terminate the entries.
  //
  ((EFI_ACPI_END_TAG_DESCRIPTOR *) Config)->Desc      = ACPI_END_TAG_DESCRIPTOR;
  ((EFI_ACPI_END_TAG_DESCRIPTOR *) Config)->Checksum  = 0x0;

  *Resources = RbPrivateData->ConfigBuffer;
  return EFI_SUCCESS;
}
Пример #14
0
EFI_STATUS
EFIAPI
PcatRootBridgeIoUnmap (
  IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL  *This,
  IN VOID                             *Mapping
  )

{
  MAP_INFO    *MapInfo;
  PCAT_PCI_ROOT_BRIDGE_INSTANCE *PrivateData;
  LIST_ENTRY *Link;

  //
  // Perform a fence operation to make sure all memory operations are flushed
  //
  MemoryFence();

  PrivateData = DRIVER_INSTANCE_FROM_PCI_ROOT_BRIDGE_IO_THIS(This);
  //
  // 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;

  for (Link = PrivateData->MapInfo.ForwardLink; Link != &PrivateData->MapInfo; Link = Link->ForwardLink) {
      if (((MAP_INFO_INSTANCE*)Link)->Map == MapInfo)
        break;
    }

    if (Link == &PrivateData->MapInfo) {
      return EFI_INVALID_PARAMETER;
  }

    RemoveEntryList(Link);
    ((MAP_INFO_INSTANCE*)Link)->Map = NULL;
    gBS->FreePool((MAP_INFO_INSTANCE*)Link);

    //
    // 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) {
      CopyMem (
        (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);
  }

  //
  // Perform a fence operation to make sure all memory operations are flushed
  //
  MemoryFence();

  return EFI_SUCCESS;
}
Пример #15
0
EFI_STATUS
PcatRootBridgeIoIoRead (
  IN     EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL        *This,
  IN     EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH  Width,
  IN     UINT64                                 UserAddress,
  IN     UINTN                                  Count,
  IN OUT VOID                                   *UserBuffer
  )
{
  PCAT_PCI_ROOT_BRIDGE_INSTANCE *PrivateData;
  UINTN                         InStride;
  UINTN                         OutStride;
  UINTN                         AlignMask;
  UINTN                         Address;
  PTR                           Buffer;
  UINT16                        Data16;
  UINT32                        Data32;
  
 
  if ( UserBuffer == NULL ) {
    return EFI_INVALID_PARAMETER;
  }
  
  PrivateData = DRIVER_INSTANCE_FROM_PCI_ROOT_BRIDGE_IO_THIS(This);

  Address    = (UINTN)  UserAddress;
  Buffer.buf = (UINT8 *)UserBuffer;

  if ( Address < PrivateData->IoBase || Address > PrivateData->IoLimit ) {
    return EFI_INVALID_PARAMETER;
  }
    
  if ((UINT32)Width >= EfiPciWidthMaximum) {
    return EFI_INVALID_PARAMETER;
  }

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

  AlignMask = (1 << (Width & 0x03)) - 1;
  if ( Address & AlignMask ) {
    return EFI_INVALID_PARAMETER;
  }

  InStride  = 1 << (Width & 0x03);
  OutStride = InStride;
  if (Width >=EfiPciWidthFifoUint8 && Width <= EfiPciWidthFifoUint64) {
    InStride = 0;
  }
  if (Width >=EfiPciWidthFillUint8 && Width <= EfiPciWidthFillUint64) {
    OutStride = 0;
  }
  Width = Width & 0x03;

  Address += PrivateData->PhysicalIoBase;

  //
  // Loop for each iteration and move the data
  //

  switch (Width) {
  case EfiPciWidthUint8:
    for (; Count > 0; Count--, Buffer.buf += OutStride, Address += InStride) {
      MEMORY_FENCE();
      *Buffer.ui8 = PORT_TO_MEM8(Address);
      MEMORY_FENCE();
    }
    break;

  case EfiPciWidthUint16:
    for (; Count > 0; Count--, Buffer.buf += OutStride, Address += InStride) {
      MEMORY_FENCE();
      if (Buffer.ui & 0x1) {
        Data16 = PORT_TO_MEM16(Address);
        *Buffer.ui8     = (UINT8)(Data16 & 0xff);
        *(Buffer.ui8+1) = (UINT8)((Data16 >> 8) & 0xff);
      } else {
        *Buffer.ui16 = PORT_TO_MEM16(Address);
      }
      MEMORY_FENCE();
    }
Пример #16
0
EFI_STATUS
PcatRootBridgeIoPciRW (
  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
  )
{
  PCI_CONFIG_ACCESS_CF8             Pci;
  PCI_CONFIG_ACCESS_CF8             PciAligned;
  UINT32                            InStride;
  UINT32                            OutStride;
  UINTN                             PciData;
  UINTN                             PciDataStride;
  PCAT_PCI_ROOT_BRIDGE_INSTANCE     *PrivateData;
  EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_PCI_ADDRESS  PciAddress;
  UINT64                            PciExpressRegAddr;
  BOOLEAN                           UsePciExpressAccess;

  if (Width < 0 || Width >= EfiPciWidthMaximum) {
    return EFI_INVALID_PARAMETER;
  }
  
  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 >= EfiPciWidthFifoUint8 && Width <= EfiPciWidthFifoUint64) {
    InStride = 0;
  }

  if (Width >= EfiPciWidthFillUint8 && Width <= EfiPciWidthFillUint64) {
    OutStride = 0;
  }

  UsePciExpressAccess = FALSE;

  CopyMem (&PciAddress, &UserAddress, sizeof(UINT64));

  if (PciAddress.ExtendedRegister > 0xFF) {
    //
    // Check PciExpressBaseAddress
    //
    if ((PrivateData->PciExpressBaseAddress == 0) ||
        (PrivateData->PciExpressBaseAddress >= MAX_ADDRESS)) {
      return EFI_UNSUPPORTED;
    } else {
      UsePciExpressAccess = TRUE;
    }
  } else {
    if (PciAddress.ExtendedRegister != 0) {
      Pci.Bits.Reg = PciAddress.ExtendedRegister & 0xFF;
    } else {
      Pci.Bits.Reg = PciAddress.Register;
    }
    //
    // Note: We can also use PciExpress access here, if wanted.
    //
  }

  if (!UsePciExpressAccess) {
    Pci.Bits.Func     = PciAddress.Function;
    Pci.Bits.Dev      = PciAddress.Device;
    Pci.Bits.Bus      = PciAddress.Bus;
    Pci.Bits.Reserved = 0;
    Pci.Bits.Enable   = 1;

    //
    // PCI Config access are all 32-bit alligned, but by accessing the
    //  CONFIG_DATA_REGISTER (0xcfc) with different widths more cycle types
    //  are possible on PCI.
    //
    // To read a byte of PCI config space you load 0xcf8 and 
    //  read 0xcfc, 0xcfd, 0xcfe, 0xcff
    //
    PciDataStride = Pci.Bits.Reg & 0x03;

    while (Count) {
      PciAligned = Pci;
      PciAligned.Bits.Reg &= 0xfc;
      PciData = (UINTN)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.Bits.Reg += InStride;
      Count -= 1;
    }
  } else {
    //
    // Access PCI-Express space by using memory mapped method.
    //
    PciExpressRegAddr = (PrivateData->PciExpressBaseAddress) |
                        (PciAddress.Bus      << 20) |
                        (PciAddress.Device   << 15) |
                        (PciAddress.Function << 12);
    if (PciAddress.ExtendedRegister != 0) {
      PciExpressRegAddr += PciAddress.ExtendedRegister;
    } else {
      PciExpressRegAddr += PciAddress.Register;
    }
    while (Count) {
      if (Write) {
        This->Mem.Write (This, Width, (UINTN) PciExpressRegAddr, 1, UserBuffer);
      } else {
        This->Mem.Read (This, Width, (UINTN) PciExpressRegAddr, 1, UserBuffer);
      }

      UserBuffer = ((UINT8 *) UserBuffer) + OutStride;
      PciExpressRegAddr += InStride;
      Count -= 1;
    }
  }
  
  return EFI_SUCCESS;
}
Пример #17
0
EFI_STATUS
EFIAPI
PcatRootBridgeIoMap (
  IN     EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL            *This,
  IN     EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_OPERATION  Operation,
  IN     VOID                                       *HostAddress,
  IN OUT UINTN                                      *NumberOfBytes,
  OUT    EFI_PHYSICAL_ADDRESS                       *DeviceAddress,
  OUT    VOID                                       **Mapping
  )

{
  EFI_STATUS            Status;
  EFI_PHYSICAL_ADDRESS  PhysicalAddress;
  MAP_INFO              *MapInfo;
  MAP_INFO_INSTANCE    *MapInstance;
  PCAT_PCI_ROOT_BRIDGE_INSTANCE *PrivateData;

  if ( HostAddress == NULL || NumberOfBytes == NULL || 
       DeviceAddress == NULL || Mapping == NULL ) {
    
    return EFI_INVALID_PARAMETER;
  }

  //
  // Perform a fence operation to make sure all memory operations are flushed
  //
  MemoryFence();

  //
  // Initialize the return values to their defaults
  //
  *Mapping = NULL;

  //
  // Make sure that Operation is valid
  //
  if ((UINT32)Operation >= EfiPciOperationMaximum) {
    return EFI_INVALID_PARAMETER;
  }

  //
  // Most PCAT like chipsets can not handle performing DMA above 4GB.
  // If any part of the DMA transfer being mapped is above 4GB, then
  // map the DMA transfer to a buffer below 4GB.
  //
  PhysicalAddress = (EFI_PHYSICAL_ADDRESS)(UINTN)HostAddress;
  if ((PhysicalAddress + *NumberOfBytes) > 0x100000000ULL) {

    //
    // Common Buffer operations can not be remapped.  If the common buffer
    // if above 4GB, then it is not possible to generate a mapping, so return 
    // an error.
    //
    if (Operation == EfiPciOperationBusMasterCommonBuffer || Operation == EfiPciOperationBusMasterCommonBuffer64) {
      return EFI_UNSUPPORTED;
    }

    //
    // Allocate a MAP_INFO structure to remember the mapping when Unmap() is
    // called later.
    //
    Status = gBS->AllocatePool (
                    EfiBootServicesData, 
                    sizeof(MAP_INFO), 
                    (VOID **)&MapInfo
                    );
    if (EFI_ERROR (Status)) {
      *NumberOfBytes = 0;
      return Status;
    }

    //
    // Return a pointer to the MAP_INFO structure in Mapping
    //
    *Mapping = MapInfo;

    //
    // Initialize the MAP_INFO structure
    //
    MapInfo->Operation         = Operation;
    MapInfo->NumberOfBytes     = *NumberOfBytes;
    MapInfo->NumberOfPages     = EFI_SIZE_TO_PAGES(*NumberOfBytes);
    MapInfo->HostAddress       = PhysicalAddress;
    MapInfo->MappedHostAddress = 0x00000000ffffffff;

    //
    // Allocate a buffer below 4GB to map the transfer to.
    //
    Status = gBS->AllocatePages (
                    AllocateMaxAddress, 
                    EfiBootServicesData, 
                    MapInfo->NumberOfPages,
                    &MapInfo->MappedHostAddress
                    );
    if (EFI_ERROR(Status)) {
      gBS->FreePool (MapInfo);
      *NumberOfBytes = 0;
      return Status;
    }

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


  Status =gBS->AllocatePool (
                    EfiBootServicesData, 
                    sizeof(MAP_INFO_INSTANCE), 
                    (VOID **)&MapInstance
                    );                    
    if (EFI_ERROR(Status)) {
      gBS->FreePages (MapInfo->MappedHostAddress,MapInfo->NumberOfPages);
      gBS->FreePool (MapInfo);
      *NumberOfBytes = 0;
      return Status;
    }

    MapInstance->Map=MapInfo;
    PrivateData = DRIVER_INSTANCE_FROM_PCI_ROOT_BRIDGE_IO_THIS(This);
    InsertTailList(&PrivateData->MapInfo,&MapInstance->Link);
    
  //
    // The DeviceAddress is the address of the maped buffer below 4GB
    //
    *DeviceAddress = MapInfo->MappedHostAddress;
  } else {
    //
    // The transfer is below 4GB, so the DeviceAddress is simply the HostAddress
    //
    *DeviceAddress = PhysicalAddress;
  }

  //
  // Perform a fence operation to make sure all memory operations are flushed
  //
  MemoryFence();

  return EFI_SUCCESS;
}
Пример #18
0
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:

--*/   
{
  PCI_CONFIG_ACCESS_CF8             Pci;
  PCI_CONFIG_ACCESS_CF8             PciAligned;
  UINT32                            Stride;
  UINTN                             PciData;
  UINTN                             PciDataStride;
  PCI_ROOT_BRIDGE_INSTANCE         *PrivateData;

  if (Width >= EfiPciWidthMaximum) {
    return EFI_INVALID_PARAMETER;
  }

  PrivateData = DRIVER_INSTANCE_FROM_PCI_ROOT_BRIDGE_IO_THIS(This);

  ASSERT (((EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_PCI_ADDRESS*)&UserAddress)->ExtendedRegister == 0x00);

  Stride = 1 << Width;

  Pci.Bits.Reg = ((EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_PCI_ADDRESS*) &UserAddress)->Register;
  Pci.Bits.Func = ((EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_PCI_ADDRESS*) &UserAddress)->Function;
  Pci.Bits.Dev = ((EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_PCI_ADDRESS*) &UserAddress)->Device;
  Pci.Bits.Bus = ((EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_PCI_ADDRESS*) &UserAddress)->Bus;
  Pci.Bits.Reserved = 0;
  Pci.Bits.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.Bits.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) + Stride;
    PciDataStride = (PciDataStride + Stride) % 4;
    Count -= 1;

    //
    // Only increment the PCI address if Width is not a FIFO.
    //
    if (Width >= EfiPciWidthUint8 && Width <= EfiPciWidthUint64) {
      Pci.Bits.Reg += Stride;
    }
  }
  return EFI_SUCCESS;
}
Пример #19
0
EFI_STATUS
RootBridgeConstructor (
  IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL    *Protocol,
  IN EFI_HANDLE                         HostBridgeHandle,
  IN UINT64                             Attri,
  IN PCI_ROOT_BRIDGE_RESOURCE_APPETURE  *ResAppeture
  )
/*++

Routine Description:

    Construct the Pci Root Bridge Io protocol

Arguments:

    Protocol - protocol to initialize
    
Returns:

    None

--*/
{
  EFI_STATUS                        Status;
  PCI_ROOT_BRIDGE_INSTANCE          *PrivateData;
  PCI_RESOURCE_TYPE                 Index;

  PrivateData = DRIVER_INSTANCE_FROM_PCI_ROOT_BRIDGE_IO_THIS (Protocol);

  //
  // The host to pci bridge, the host memory and io addresses are
  // direct mapped to pci addresses, so no need translate, set bases to 0.
  //
  PrivateData->MemBase = ResAppeture->MemBase;
  PrivateData->IoBase  = ResAppeture->IoBase;

  //
  // The host bridge only supports 32bit addressing for memory
  // and standard IA32 16bit io
  //
  PrivateData->MemLimit = ResAppeture->MemLimit;
  PrivateData->IoLimit  = ResAppeture->IoLimit;

  //
  // Bus Appeture for this Root Bridge (Possible Range)
  //
  PrivateData->BusBase  = ResAppeture->BusBase;
  PrivateData->BusLimit = ResAppeture->BusLimit;
  
  //
  // Specific for this chipset
  //
  for (Index = TypeIo; Index < TypeMax; Index++) {
    PrivateData->ResAllocNode[Index].Type      = Index;
    PrivateData->ResAllocNode[Index].Base      = 0;
    PrivateData->ResAllocNode[Index].Length    = 0;
    PrivateData->ResAllocNode[Index].Status    = ResNone;
  }
  

  EfiInitializeLock (&PrivateData->PciLock, TPL_HIGH_LEVEL);
  PrivateData->PciAddress = 0xCF8;
  PrivateData->PciData    = 0xCFC;

  PrivateData->RootBridgeAttrib = Attri;
  
  PrivateData->Attributes  = 0;
  PrivateData->Supports    = 0;

  Protocol->ParentHandle   = HostBridgeHandle;
  
  Protocol->PollMem        = RootBridgeIoPollMem;
  Protocol->PollIo         = RootBridgeIoPollIo;

  Protocol->Mem.Read       = RootBridgeIoMemRead;
  Protocol->Mem.Write      = RootBridgeIoMemWrite;

  Protocol->Io.Read        = RootBridgeIoIoRead;
  Protocol->Io.Write       = RootBridgeIoIoWrite;

  Protocol->CopyMem        = RootBridgeIoCopyMem;

  Protocol->Pci.Read       = RootBridgeIoPciRead;
  Protocol->Pci.Write      = RootBridgeIoPciWrite;

  Protocol->Map            = RootBridgeIoMap;
  Protocol->Unmap          = RootBridgeIoUnmap;

  Protocol->AllocateBuffer = RootBridgeIoAllocateBuffer;
  Protocol->FreeBuffer     = RootBridgeIoFreeBuffer;

  Protocol->Flush          = RootBridgeIoFlush;

  Protocol->GetAttributes  = RootBridgeIoGetAttributes;
  Protocol->SetAttributes  = RootBridgeIoSetAttributes;

  Protocol->Configuration  = RootBridgeIoConfiguration;

  Protocol->SegmentNumber  = 0;

  Status = gBS->LocateProtocol (&gEfiCpuIo2ProtocolGuid, NULL, (VOID **)&mCpuIo);
  ASSERT_EFI_ERROR (Status);

  Status = gBS->LocateProtocol (&gEfiMetronomeArchProtocolGuid, NULL, (VOID **)&mMetronome);
  ASSERT_EFI_ERROR (Status);

  return EFI_SUCCESS;
}
Пример #20
0
//
// Internal function
//
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
  )
{
  PCI_CONFIG_ACCESS_CF8             Pci;
  PCI_CONFIG_ACCESS_CF8             PciAligned;
  UINT32                            InStride;
  UINT32                            OutStride;
  UINTN                             PciData;
  UINTN                             PciDataStride;
  PCI_ROOT_BRIDGE_INSTANCE     *PrivateData;
  EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_PCI_ADDRESS  PciAddress;

  if (Width < 0 || Width >= EfiPciWidthMaximum) {
    return EFI_INVALID_PARAMETER;
  }
  
  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;
  }

  CopyMem (&PciAddress, &UserAddress, sizeof(UINT64));

  if (PciAddress.ExtendedRegister > 0xFF) {
    return EFI_UNSUPPORTED;
  }

  if (PciAddress.ExtendedRegister != 0) {
    Pci.Bits.Reg = PciAddress.ExtendedRegister & 0xFF;
  } else {
    Pci.Bits.Reg = PciAddress.Register;
  }

  Pci.Bits.Func     = PciAddress.Function;
  Pci.Bits.Dev      = PciAddress.Device;
  Pci.Bits.Bus      = PciAddress.Bus;
  Pci.Bits.Reserved = 0;
  Pci.Bits.Enable   = 1;

  //
  // PCI Config access are all 32-bit alligned, but by accessing the
  //  CONFIG_DATA_REGISTER (0xcfc) with different widths more cycle types
  //  are possible on PCI.
  //
  // To read a byte of PCI config space you load 0xcf8 and 
  //  read 0xcfc, 0xcfd, 0xcfe, 0xcff
  //
  PciDataStride = Pci.Bits.Reg & 0x03;

  while (Count) {
    CopyMem (&PciAligned, &Pci, sizeof (PciAligned));
    PciAligned.Bits.Reg &= 0xfc;
    PciData = (UINTN)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.Bits.Reg += InStride;
    Count -= 1;
  }
  
  return EFI_SUCCESS;
}
Пример #21
0
EFI_STATUS
EFIAPI
RootBridgeIoPciWrite (
  IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL          *This,
  IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH    Width,
  IN UINT64                                   Address,
  IN UINTN                                    Count,
  IN OUT VOID                                 *Buffer
  )
/*++

Routine Description:

  Allows write to PCI configuration space.
  
Arguments:

  This     -  A pointer to EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL
  Width    -  Signifies the width of the memory operation.
  Address  -  The address within the PCI configuration space
              for the PCI controller.
  Count    -  The number of PCI configuration operations 
              to perform.
  Buffer   -  The source buffer to get the results.
              
Returns:

  EFI_SUCCESS            -  The data was written to the PCI root bridge.
  EFI_INVALID_PARAMETER  -  Invalid parameters found.
  EFI_OUT_OF_RESOURCES   -  The request could not be completed due to a lack of 
                            resources.
--*/
{
  PCI_ROOT_BRIDGE_INSTANCE  *PrivateData;
  UINT32                    PciBus;
  UINT32                    PciDev;
  UINT32                    PciFn;
  UINT32                    PciExtReg;
  UINT64                    ExtConfigAdd;

  if (Buffer == NULL) {
    return EFI_INVALID_PARAMETER;
  }

  if (Width < 0 || Width >= EfiPciWidthMaximum) {
    return EFI_INVALID_PARAMETER;
  }

  //
  // Write Pci configuration space
  //
  PrivateData = DRIVER_INSTANCE_FROM_PCI_ROOT_BRIDGE_IO_THIS (This);

  if (PrivateData->HecBase == 0) {
    return RootBridgeIoPciRW (This, TRUE, Width, Address, Count, Buffer);
  }

  if (!((EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_PCI_ADDRESS *) &Address)->ExtendedRegister) {
    PciExtReg = ((EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_PCI_ADDRESS *) &Address)->Register;
  } else {
    PciExtReg = ((EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_PCI_ADDRESS *) &Address)->ExtendedRegister & 0x0FFF;
  }

  PciBus        = ((EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_PCI_ADDRESS *) &Address)->Bus;
  PciDev        = ((EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_PCI_ADDRESS *) &Address)->Device;
  PciFn         = ((EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_PCI_ADDRESS *) &Address)->Function;

  ExtConfigAdd  = (UINT64) PrivateData->HecBase + PCIE_OFF (PciBus, PciDev, PciFn, PciExtReg);

  return mCpuIo->Mem.Write (
                      mCpuIo,
                      (EFI_CPU_IO_PROTOCOL_WIDTH) Width,
                      ExtConfigAdd,
                      Count,
                      Buffer
                      );
}
Пример #22
0
EFI_STATUS
EFIAPI
RootBridgeIoIoWrite (
  IN       EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL         *This,
  IN       EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH   Width,
  IN       UINT64                                  Address,
  IN       UINTN                                   Count,
  IN OUT   VOID                                    *Buffer
  )
/*++

Routine Description:
  Io write
  
Arguments:
    
Returns:

--*/  
{
  UINTN                                         AlignMask;
  PCI_ROOT_BRIDGE_INSTANCE                      *PrivateData;
  EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH         OldWidth;
  UINTN                                         OldCount;

  if (Buffer == NULL) {
    return EFI_INVALID_PARAMETER;
  }

  if (Width < 0 || Width >= EfiPciWidthMaximum) {
    return EFI_INVALID_PARAMETER;
  }

  PrivateData = DRIVER_INSTANCE_FROM_PCI_ROOT_BRIDGE_IO_THIS(This);

  //AlignMask = (1 << Width) - 1;
  AlignMask = (1 << (Width & 0x03)) - 1;

  //
  // Check Io access limit
  //
  if (Address < PrivateData->IoBase) {
    return EFI_INVALID_PARAMETER;
  }

  OldWidth = Width;
  OldCount = Count;
  if (Width >= EfiPciWidthFifoUint8 && Width <= EfiPciWidthFifoUint64) {
    Count = 1;
  }

  Width = (EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH)(Width & 0x03);
  
  if (Address + (((UINTN)1 << Width) * Count) - 1 >= PrivateData->IoLimit) {
    return EFI_INVALID_PARAMETER;
  }

  if (Address & AlignMask) {
    return EFI_INVALID_PARAMETER;
  }

  return mCpuIo->Io.Write (mCpuIo, (EFI_CPU_IO_PROTOCOL_WIDTH) OldWidth, 
                      Address, OldCount, Buffer);

}