pciio.c

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

C
1,868
字号

  None

--*/
{
  EFI_STATUS    Status;
  PCI_IO_DEVICE *PciIoDevice;

  PciIoDevice = PCI_IO_DEVICE_FROM_PCI_IO_THIS (This);

  if (Operation < 0 || Operation >= EfiPciIoOperationMaximum) {
    return EFI_INVALID_PARAMETER;
  }

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

  if (PciIoDevice->Attributes & EFI_PCI_IO_ATTRIBUTE_DUAL_ADDRESS_CYCLE) {
    Operation = Operation + EfiPciOperationBusMasterRead64;
  }

  Status = PciIoDevice->PciRootBridgeIo->Map (
                                          PciIoDevice->PciRootBridgeIo,
                                          (EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_OPERATION) Operation,
                                          HostAddress,
                                          NumberOfBytes,
                                          DeviceAddress,
                                          Mapping
                                          );

  return Status;
}

EFI_STATUS
EFIAPI
PciIoUnmap (
  IN  EFI_PCI_IO_PROTOCOL  *This,
  IN  VOID                 *Mapping
  )
/*++

Routine Description:

  Unmaps a memory region for DMA

Arguments:

Returns:

  None

--*/
{
  EFI_STATUS    Status;
  PCI_IO_DEVICE *PciIoDevice;

  PciIoDevice = PCI_IO_DEVICE_FROM_PCI_IO_THIS (This);

  Status = PciIoDevice->PciRootBridgeIo->Unmap (
                                          PciIoDevice->PciRootBridgeIo,
                                          Mapping
                                          );

  return Status;
}

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

Routine Description:

  Allocates a common buffer for DMA

Arguments:

Returns:

  None

--*/
{
  EFI_STATUS    Status;
  PCI_IO_DEVICE *PciIoDevice;

  if (Attributes &
      (~(EFI_PCI_ATTRIBUTE_MEMORY_WRITE_COMBINE | EFI_PCI_ATTRIBUTE_MEMORY_CACHED))) {
    return EFI_UNSUPPORTED;
  }

  PciIoDevice = PCI_IO_DEVICE_FROM_PCI_IO_THIS (This);

  if (PciIoDevice->Attributes & EFI_PCI_IO_ATTRIBUTE_DUAL_ADDRESS_CYCLE) {
    Attributes |= EFI_PCI_ATTRIBUTE_DUAL_ADDRESS_CYCLE;
  }

  Status = PciIoDevice->PciRootBridgeIo->AllocateBuffer (
                                          PciIoDevice->PciRootBridgeIo,
                                          Type,
                                          MemoryType,
                                          Pages,
                                          HostAddress,
                                          Attributes
                                          );

  return Status;
}

EFI_STATUS
EFIAPI
PciIoFreeBuffer (
  IN  EFI_PCI_IO_PROTOCOL   *This,
  IN  UINTN                 Pages,
  IN  VOID                  *HostAddress
  )
/*++

Routine Description:

  Frees a common buffer 

Arguments:

Returns:

  None

--*/
{
  EFI_STATUS    Status;
  PCI_IO_DEVICE *PciIoDevice;
  
  if( HostAddress == NULL ){
  	 return EFI_INVALID_PARAMETER;
  } 

  PciIoDevice = PCI_IO_DEVICE_FROM_PCI_IO_THIS (This);

  Status = PciIoDevice->PciRootBridgeIo->FreeBuffer (
                                          PciIoDevice->PciRootBridgeIo,
                                          Pages,
                                          HostAddress
                                          );

  return Status;
}

EFI_STATUS
EFIAPI
PciIoFlush (
  IN  EFI_PCI_IO_PROTOCOL  *This
  )
/*++

Routine Description:

  Flushes a DMA buffer

Arguments:

Returns:

  None

--*/

{
  EFI_STATUS    Status;
  UINT32         Register;
  PCI_IO_DEVICE  *PciIoDevice;

  PciIoDevice = PCI_IO_DEVICE_FROM_PCI_IO_THIS (This);

  //
  // If the device is behind a PCI-PCI Bridge, then perform a read cycles to the device to 
  // flush the posted write cycles through the PCI-PCI bridges
  //
  if (PciIoDevice->Parent != NULL) {
    Status = This->Pci.Read (This, EfiPciIoWidthUint32, 0, 1, &Register);
  }

  //
  // Call the PCI Root Bridge I/O Protocol to flush the posted write cycles through the chipset
  //
  Status = PciIoDevice->PciRootBridgeIo->Flush (
                                           PciIoDevice->PciRootBridgeIo
                                           );

  return Status;
}

EFI_STATUS
EFIAPI
PciIoGetLocation (
  IN  EFI_PCI_IO_PROTOCOL  *This,
  OUT UINTN                *Segment,
  OUT UINTN                *Bus,
  OUT UINTN                *Device,
  OUT UINTN                *Function
  )
/*++

Routine Description:

  Gets a PCI device's current bus number, device number, and function number.

Arguments:

Returns:

  None

--*/
{
  PCI_IO_DEVICE *PciIoDevice;

  PciIoDevice = PCI_IO_DEVICE_FROM_PCI_IO_THIS (This);

  if (Segment == NULL || Bus == NULL || Device == NULL || Function == NULL) {
    return EFI_INVALID_PARAMETER;
  }

  *Segment  = PciIoDevice->PciRootBridgeIo->SegmentNumber;
  *Bus      = PciIoDevice->BusNumber;
  *Device   = PciIoDevice->DeviceNumber;
  *Function = PciIoDevice->FunctionNumber;

  return EFI_SUCCESS;
}

BOOLEAN
CheckBarType (
  IN PCI_IO_DEVICE       *PciIoDevice,
  UINT8                  BarIndex,
  PCI_BAR_TYPE           BarType
  )
/*++

Routine Description:

  Sets a PCI controllers attributes on a resource range

Arguments:

Returns:

  None

--*/
{
  switch (BarType) {

  case PciBarTypeMem:

    if (PciIoDevice->PciBar[BarIndex].BarType != PciBarTypeMem32  &&
        PciIoDevice->PciBar[BarIndex].BarType != PciBarTypePMem32 &&
        PciIoDevice->PciBar[BarIndex].BarType != PciBarTypePMem64 &&
        PciIoDevice->PciBar[BarIndex].BarType != PciBarTypeMem64    ) {
      return FALSE;
    }

    return TRUE;

  case PciBarTypeIo:
    if (PciIoDevice->PciBar[BarIndex].BarType != PciBarTypeIo32 &&
        PciIoDevice->PciBar[BarIndex].BarType != PciBarTypeIo16){
      return FALSE;
    }

    return TRUE;

  default:
    break;
  }

  return FALSE;
}

EFI_STATUS
EFIAPI
PciIoAttributes (
  IN EFI_PCI_IO_PROTOCOL                       * This,
  IN  EFI_PCI_IO_PROTOCOL_ATTRIBUTE_OPERATION  Operation,
  IN  UINT64                                   Attributes,
  OUT UINT64                                   *Result OPTIONAL
  )
/*++

Routine Description:


Arguments:

Returns:

  None

--*/
{
  EFI_STATUS    Status;

  PCI_IO_DEVICE *PciIoDevice;
  PCI_IO_DEVICE *Temp;
  UINT64         NewAttributes;
  UINT64         PciRootBridgeSupports;
  UINT64         PciRootBridgeAttributes;
  UINT64         NewPciRootBridgeAttributes;
  UINT64         NewUpStreamBridgeAttributes;
  UINT64         ModifiedPciRootBridgeAttributes;
  UINT16         EnableCommand;
  UINT16         DisableCommand;
  UINT16         EnableBridge;
  UINT16         DisableBridge;
  UINT16         Command;

  PciIoDevice = PCI_IO_DEVICE_FROM_PCI_IO_THIS (This);
  NewUpStreamBridgeAttributes = 0;

  EnableCommand   = 0;
  DisableCommand  = 0;
  EnableBridge    = 0;
  DisableBridge   = 0;

  switch (Operation) {
  case EfiPciIoAttributeOperationGet:
    if (Result == NULL) {
      return EFI_INVALID_PARAMETER;
    }

    *Result = PciIoDevice->Attributes;
    return EFI_SUCCESS;

  case EfiPciIoAttributeOperationSupported:
    if (Result == NULL) {
      return EFI_INVALID_PARAMETER;
    }

    *Result = PciIoDevice->Supports;
    return EFI_SUCCESS;

  case EfiPciIoAttributeOperationEnable:
	  if(Attributes & ~(PciIoDevice->Supports)) {
		  return EFI_UNSUPPORTED;
	  }
	  NewAttributes = PciIoDevice->Attributes | Attributes;
    break;
  case EfiPciIoAttributeOperationDisable:
	  if(Attributes & ~(PciIoDevice->Supports)) {
		  return EFI_UNSUPPORTED;
	  }
    NewAttributes = PciIoDevice->Attributes & (~Attributes);
    break;
  case EfiPciIoAttributeOperationSet:
	  if(Attributes & ~(PciIoDevice->Supports)) {
		  return EFI_UNSUPPORTED;
	  }
    NewAttributes = Attributes;
    break;
  default:
    return EFI_INVALID_PARAMETER;
  }

  //
  // If VGA_IO is set, then set VGA_MEMORY too.  This driver can not enable them seperately.
  //
  if (NewAttributes & EFI_PCI_IO_ATTRIBUTE_VGA_IO) {
    NewAttributes |= EFI_PCI_IO_ATTRIBUTE_VGA_MEMORY;
  }

  //
  // If VGA_MEMORY is set, then set VGA_IO too.  This driver can not enable them seperately.
  //
  if (NewAttributes & EFI_PCI_IO_ATTRIBUTE_VGA_MEMORY) {
    NewAttributes |= EFI_PCI_IO_ATTRIBUTE_VGA_IO;
  }

  //
  // If the attributes are already set correctly, then just return EFI_SUCCESS;
  //
  if ((NewAttributes ^ PciIoDevice->Attributes) == 0) {
    return EFI_SUCCESS;
  }

  //
  // This driver takes care of EFI_PCI_IO_ATTRIBUTE_IO, EFI_PCI_IO_ATTRIBUTE_MEMORY, and
  // EFI_PCI_IO_ATTRIBUTE_BUS_MASTER.  Strip these 3 bits off the new attribute mask so
  // a call to the PCI Root Bridge I/O Protocol can be made
  //

  if (!IS_PCI_BRIDGE(&PciIoDevice->Pci)) {
    NewPciRootBridgeAttributes = NewAttributes & (~(EFI_PCI_IO_ATTRIBUTE_IO | EFI_PCI_IO_ATTRIBUTE_MEMORY | EFI_PCI_IO_ATTRIBUTE_BUS_MASTER | EFI_PCI_IO_ATTRIBUTE_DUAL_ADDRESS_CYCLE));

    //  
    // Get the current attributes of this PCI device's PCI Root Bridge
    //
    Status = PciIoDevice->PciRootBridgeIo->GetAttributes (
                                            PciIoDevice->PciRootBridgeIo,
                                            &PciRootBridgeSupports,
                                            &PciRootBridgeAttributes
                                            );

    //
    // Check to see if any of the PCI Root Bridge attributes are being modified
    //
    ModifiedPciRootBridgeAttributes = NewPciRootBridgeAttributes ^ PciRootBridgeAttributes;
    if (ModifiedPciRootBridgeAttributes) {

      //
      // Check to see if the PCI Root Bridge supports modifiying the attributes that are changing
      //
      if ((ModifiedPciRootBridgeAttributes & PciRootBridgeSupports) != ModifiedPciRootBridgeAttributes) {
  //     return EFI_UNSUPPORTED;
      }
      //
      // Call the PCI Root Bridge to attempt to modify the attributes
      //
      Status = PciIoDevice->PciRootBridgeIo->SetAttributes (
                                             PciIoDevice->PciRootBridgeIo,
                                             NewPciRootBridgeAttributes,
                                             NULL,
                                             NULL
                                             );
      if (EFI_ERROR (Status)) {
      //
      // The PCI Root Bridge could not modify the attributes, so return the error.
      //
        return Status;
      }
    }
  }


  if (IS_PCI_BRIDGE(&PciIoDevice->Pci)) {


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

      if (NewAttributes & EFI_PCI_IO_ATTRIBUTE_VGA_IO) {
        EnableBridge  |= EFI_PCI_BRIDGE_CONTROL_VGA;
      } else {
        DisableBridge  |= EFI_PCI_BRIDGE_CONTROL_VGA;
      }
    }

    //
    // Check to see if an VGA related attributes are being set.
    // If ISA Enable on the PPB is set, the PPB will block the
    // 0x100-0x3FF for each 1KB block in the first 64K I/O block
    //
    if ((NewAttributes & EFI_PCI_IO_ATTRIBUTE_ISA_IO) ^ (PciIoDevice->Attributes & EFI_PCI_IO_ATTRIBUTE_ISA_IO)) {

      if (NewAttributes & EFI_PCI_IO_ATTRIBUTE_ISA_IO) {
        DisableBridge  |= EFI_PCI_BRIDGE_CONTROL_ISA;
      } else {
        EnableBridge  |= EFI_PCI_BRIDGE_CONTROL_ISA;

⌨️ 快捷键说明

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