pcirootbridgeio.c

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

C
1,750
字号
        return EFI_SUCCESS;
      }

      NumberOfTicks -= 1;
    }
  }

  return EFI_TIMEOUT;
}

EFI_STATUS
EFIAPI
RootBridgeIoPollIo (
  IN  EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL        *This,
  IN  EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH  Width,
  IN  UINT64                                 Address,
  IN  UINT64                                 Mask,
  IN  UINT64                                 Value,
  IN  UINT64                                 Delay,
  OUT UINT64                                 *Result
  )
/*++

Routine Description:
  Io Poll
  
Arguments:
    
Returns:

--*/
// TODO:    This - add argument and description to function comment
// TODO:    Width - add argument and description to function comment
// TODO:    Address - add argument and description to function comment
// TODO:    Mask - add argument and description to function comment
// TODO:    Value - add argument and description to function comment
// TODO:    Delay - add argument and description to function comment
// TODO:    Result - add argument and description to function comment
// TODO:    EFI_INVALID_PARAMETER - add return value to function comment
// TODO:    EFI_INVALID_PARAMETER - add return value to function comment
// TODO:    EFI_SUCCESS - add return value to function comment
// TODO:    EFI_SUCCESS - add return value to function comment
// TODO:    EFI_SUCCESS - add return value to function comment
// TODO:    EFI_TIMEOUT - add return value to function comment
{
  EFI_STATUS  Status;
  UINT64      NumberOfTicks;
  UINTN       Remainder;

  //
  // No matter what, always do a single poll.
  //

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

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

  Status = This->Io.Read (This, Width, Address, 1, Result);
  if (EFI_ERROR (Status)) {
    return Status;
  }

  if ((*Result & Mask) == Value) {
    return EFI_SUCCESS;
  }

  if (Delay == 0) {
    return EFI_SUCCESS;

  } else {

    //
    // Determine the proper # of metronome ticks to wait for polling the
    // location.  The number of ticks is Roundup (Delay / mMetronome->TickPeriod)+1
    // The "+1" to account for the possibility of the first tick being short
    // because we started in the middle of a tick.
    //
    NumberOfTicks = DivU64x32 (Delay, (UINT32) mMetronome->TickPeriod, &Remainder);
    if (Remainder != 0) {
      NumberOfTicks += 1;
    }

    NumberOfTicks += 1;

    while (NumberOfTicks) {

      mMetronome->WaitForTick (mMetronome, 1);

      Status = This->Io.Read (This, Width, Address, 1, Result);
      if (EFI_ERROR (Status)) {
        return Status;
      }

      if ((*Result & Mask) == Value) {
        return EFI_SUCCESS;
      }

      NumberOfTicks -= 1;
    }
  }

  return EFI_TIMEOUT;
}

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:

--*/
// TODO:    This - add argument and description to function comment
// TODO:    Width - add argument and description to function comment
// TODO:    Address - add argument and description to function comment
// TODO:    Count - add argument and description to function comment
// TODO:    Buffer - add argument and description to function comment
// TODO:    EFI_INVALID_PARAMETER - add return value to function comment
// TODO:    EFI_INVALID_PARAMETER - add return value to function comment
// TODO:    EFI_INVALID_PARAMETER - add return value to function comment
// TODO:    EFI_INVALID_PARAMETER - add return value to function comment
{
  PCI_ROOT_BRIDGE_INSTANCE              *PrivateData;
  EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH OldWidth;
  UINTN                                 OldCount;
  UINTN                                 AlignMask;
  VOID                                  *Buf;
  VOID                                  *ptr;
  EFI_STATUS                            Status;

  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 &= 0x03;

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

  AlignMask = (1 << Width) - 1;
  if ((UINTN) Buffer & AlignMask) {
    Status = gBS->AllocatePool (
                    EfiBootServicesData,
                    (1 << Width) * (OldCount + 1),
                    &Buf
                    );
    ptr = (VOID *) (((UINTN) (((UINTN) Buf) &~(AlignMask))) + (1 << Width));
    Status = mCpuIo->Mem.Read (
                          mCpuIo,
                          (EFI_CPU_IO_PROTOCOL_WIDTH) OldWidth,
                          Address,
                          OldCount,
                          ptr
                          );
    EfiCopyMem (Buffer, ptr, (1 << Width) * OldCount);
    gBS->FreePool (Buf);
  } else {
    Status = mCpuIo->Mem.Read (
                          mCpuIo,
                          (EFI_CPU_IO_PROTOCOL_WIDTH) OldWidth,
                          Address,
                          OldCount,
                          Buffer
                          );
  }

  return Status;
}

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:
  Memory write
  
Arguments:
    
Returns:

--*/
// TODO:    This - add argument and description to function comment
// TODO:    Width - add argument and description to function comment
// TODO:    Address - add argument and description to function comment
// TODO:    Count - add argument and description to function comment
// TODO:    Buffer - add argument and description to function comment
// TODO:    EFI_INVALID_PARAMETER - add return value to function comment
// TODO:    EFI_INVALID_PARAMETER - add return value to function comment
// TODO:    EFI_INVALID_PARAMETER - add return value to function comment
// TODO:    EFI_INVALID_PARAMETER - add return value to function comment
{
  PCI_ROOT_BRIDGE_INSTANCE              *PrivateData;
  EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH OldWidth;
  UINTN                                 OldCount;
  UINTN                                 AlignMask;
  VOID                                  *Buf;
  VOID                                  *ptr;
  EFI_STATUS                            Status;

  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 &= 0x03;

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

  AlignMask = (1 << Width) - 1;
  if ((UINTN) Buffer & AlignMask) {
    Status = gBS->AllocatePool (
                    EfiBootServicesData,
                    (1 << Width) * (OldCount + 1),
                    &Buf
                    );
    ptr = (VOID *) (((UINTN) (((UINTN) Buf) &~(AlignMask))) + (1 << Width));
    EfiCopyMem (ptr, Buffer, (1 << Width) * OldCount);
    Status = mCpuIo->Mem.Write (
                          mCpuIo,
                          (EFI_CPU_IO_PROTOCOL_WIDTH) OldWidth,
                          Address,
                          OldCount,
                          ptr
                          );
    gBS->FreePool (Buf);
  } else {
    Status = mCpuIo->Mem.Write (
                          mCpuIo,
                          (EFI_CPU_IO_PROTOCOL_WIDTH) OldWidth,
                          Address,
                          OldCount,
                          Buffer
                          );
  }

  return Status;
}

EFI_STATUS
EFIAPI
RootBridgeIoIoRead (
  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 read
  
Arguments:
    
Returns:

--*/
// TODO:    This - add argument and description to function comment
// TODO:    Width - add argument and description to function comment
// TODO:    Address - add argument and description to function comment
// TODO:    Count - add argument and description to function comment
// TODO:    Buffer - add argument and description to function comment
// TODO:    EFI_INVALID_PARAMETER - add return value to function comment
// TODO:    EFI_INVALID_PARAMETER - add return value to function comment
// TODO:    EFI_INVALID_PARAMETER - add return value to function comment
// TODO:    EFI_INVALID_PARAMETER - add return value to function comment
// TODO:    EFI_INVALID_PARAMETER - add return value to function comment
{

  UINTN                                 AlignMask;
  PCI_ROOT_BRIDGE_INSTANCE              *PrivateData;
  EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH OldWidth;
  UINTN                                 OldCount;
  UINTN                                 Counter;
  UINTN                                 InStride;
  UINTN                                 OutStride;
  CHAR8                                 Buf[16];
  CHAR8                                 *Ptr;
  CHAR8                                 *TempBuf;
  EFI_STATUS                            Status;

  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 & 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 &= 0x03;

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

  if (Address & AlignMask) {
    return EFI_INVALID_PARAMETER;
  }

  Counter = OldCount;
  TempBuf = (CHAR8 *) Buffer;
  Status  = EFI_SUCCESS;
  if ((UINTN) Buffer & AlignMask) {
    Ptr = (CHAR8 *) (((UINTN) (((UINTN) Buf) &~(AlignMask))) + (1 << Width));
    while (Counter > 0) {
      InStride  = (OldCount - Counter) << Width;
      OutStride = (OldCount - Counter) << Width;
      if (Width >= EfiCpuIoWidthFifoUint8 && Width <= EfiCpuIoWidthFifoUint64) {
        InStride = 0;
      }

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

      Status = mCpuIo->Io.Read (
                            mCpuIo,
                            (EFI_CPU_IO_PROTOCOL_WIDTH) OldWidth,
                            Address + InStride,
                            1,
                            (VOID *) Ptr
                            );
      if (EFI_ERROR (Status)) {
        return Status;
      }

      EfiCopyMem (TempBuf + OutStride, Ptr, (1 << Width));
      Counter--;
    };

  } else {
    Status = mCpuIo->Io.Read (
                          mCpuIo,
                          (EFI_CPU_IO_PROTOCOL_WIDTH) OldWidth,
                          Address,
                          OldCount,
                          Buffer
                          );
  }

  return Status;

}

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:

⌨️ 快捷键说明

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