コード例 #1
0
ファイル: UhciSched.c プロジェクト: SunnyKi/bareBoot
/**
  Free an asynchronous request's resource such as memory.

  @param  Uhc                    The UHCI device.
  @param  AsyncReq               The asynchronous request to free.

**/
VOID
UhciFreeAsyncReq (
  IN USB_HC_DEV           *Uhc,
  IN UHCI_ASYNC_REQUEST   *AsyncReq
  )
{
  ASSERT ((Uhc != NULL) && (AsyncReq != NULL));

  UhciDestoryTds (Uhc, AsyncReq->FirstTd);
  UsbHcFreeMem (Uhc->MemPool, AsyncReq->QhSw, sizeof (UHCI_QH_SW));

  if (AsyncReq->Data != NULL) {
    UsbHcFreeMem (Uhc->MemPool, AsyncReq->Data, AsyncReq->DataLen);
  }

  gBS->FreePool (AsyncReq);
}
コード例 #2
0
ファイル: UhciSched.c プロジェクト: SunnyKi/bareBoot
/**
  Destory FrameList buffer.

  @param  Uhc                    The UHCI device.

**/
VOID
UhciDestoryFrameList (
  IN USB_HC_DEV           *Uhc
  )
{
  //
  // Unmap the common buffer for framelist entry,
  // and free the common buffer.
  // Uhci's frame list occupy 4k memory.
  //
  Uhc->PciIo->Unmap (Uhc->PciIo, Uhc->FrameMapping);

  Uhc->PciIo->FreeBuffer (
                Uhc->PciIo,
                EFI_SIZE_TO_PAGES (4096),
                (VOID *) Uhc->FrameBase
                );

  if (Uhc->FrameBaseHostAddr != NULL) {
    FreePool (Uhc->FrameBaseHostAddr);
  }

  if (Uhc->SyncIntQh != NULL) {
    UsbHcFreeMem (Uhc->MemPool, Uhc->SyncIntQh, sizeof (UHCI_QH_SW));
  }

  if (Uhc->CtrlQh != NULL) {
    UsbHcFreeMem (Uhc->MemPool, Uhc->CtrlQh, sizeof (UHCI_QH_SW));
  }

  if (Uhc->BulkQh != NULL) {
    UsbHcFreeMem (Uhc->MemPool, Uhc->BulkQh, sizeof (UHCI_QH_SW));
  }

  Uhc->FrameBase           = NULL;
  Uhc->FrameBaseHostAddr   = NULL;
  Uhc->SyncIntQh           = NULL;
  Uhc->CtrlQh              = NULL;
  Uhc->BulkQh              = NULL;
}
コード例 #3
0
ファイル: OhciUrb.c プロジェクト: SunnyKi/bareBoot
EFI_STATUS
OhciFreeED (
  IN USB_OHCI_HC_DEV      *Ohc,
  IN ED_DESCRIPTOR        *Ed
  )
{
  if (Ed == NULL) {
    return EFI_SUCCESS;
  }
  UsbHcFreeMem(Ohc->MemPool, Ed, sizeof(ED_DESCRIPTOR));

  return EFI_SUCCESS;
}
コード例 #4
0
ファイル: OhciUrb.c プロジェクト: SunnyKi/bareBoot
/**

  Free a TD

  @Param  Ohc                   UHC private data
  @Param  Td                    Pointer to a TD to free

  @retval  EFI_SUCCESS          TD freed

**/
EFI_STATUS
OhciFreeTD (
  IN USB_OHCI_HC_DEV      *Ohc,
  IN TD_DESCRIPTOR        *Td
  )
{
  if (Td == NULL) {
    return EFI_SUCCESS;
  }
  UsbHcFreeMem(Ohc->MemPool, Td, sizeof(TD_DESCRIPTOR));

  return EFI_SUCCESS;
}
コード例 #5
0
ファイル: EhciUrb.c プロジェクト: AshleyDeSimone/edk2
/**
  Free a list of QTDs.
  
  @param  Ehc         The EHCI device.
  @param  Qtds        The list head of the QTD.

**/
VOID
EhcFreeQtds (
  IN PEI_USB2_HC_DEV      *Ehc,
  IN EFI_LIST_ENTRY       *Qtds
  )
{
  EFI_LIST_ENTRY          *Entry;
  EFI_LIST_ENTRY          *Next;
  PEI_EHC_QTD             *Qtd;

  EFI_LIST_FOR_EACH_SAFE (Entry, Next, Qtds) {
    Qtd = EFI_LIST_CONTAINER (Entry, PEI_EHC_QTD, QtdList);

    RemoveEntryList (&Qtd->QtdList);
    UsbHcFreeMem (Ehc->MemPool, Qtd, sizeof (PEI_EHC_QTD));
  }
コード例 #6
0
ファイル: OhciUrb.c プロジェクト: SunnyKi/bareBoot
/**

  Free the Ed that were initilized during driver was starting,
  those memory were used as interrupt ED head

  @Param  Ohc                   Device private data


**/
VOID
OhciFreeFixedIntMemory (
  IN USB_OHCI_HC_DEV      *Ohc
  )
{
  static UINT32           Leaf[] = {32,16,8,4,2,1};
  UINTN                   Index;
  UINTN                   Level;

  for (Level = 0; Level < 6; Level++) {
    for (Index = 0; Index < Leaf[Level]; Index++) {
      if (Ohc->IntervalList[Level][Index] != NULL) {
        UsbHcFreeMem(Ohc->MemPool, Ohc->IntervalList[Level][Index], sizeof(ED_DESCRIPTOR));
      }
    }
  }
}
コード例 #7
0
ファイル: UhciQueue.c プロジェクト: SunnyKi/bareBoot
/**
  Delete a list of TDs.

  @param  Uhc         The UHCI device.
  @param  FirstTd     TD link list head.

  @return None.

**/
VOID
UhciDestoryTds (
  IN USB_HC_DEV           *Uhc,
  IN UHCI_TD_SW           *FirstTd
  )
{
  UHCI_TD_SW            *NextTd;
  UHCI_TD_SW            *ThisTd;

  NextTd = FirstTd;

  while (NextTd != NULL) {
    ThisTd  = NextTd;
    NextTd  = ThisTd->NextTd;
    UsbHcFreeMem (Uhc->MemPool, ThisTd, sizeof (UHCI_TD_SW));
  }
}
コード例 #8
0
ファイル: OhciSched.c プロジェクト: shijunjing/edk2
/**

  Free a interrupt context entry

  @param  Ohc                   UHC private data
  @param  Entry                 Pointer to an interrupt context entry

  @retval EFI_SUCCESS           Entry freed
  @retval EFI_INVALID_PARAMETER Entry is NULL

**/
EFI_STATUS
OhciFreeInterruptContextEntry (
  IN USB_OHCI_HC_DEV          *Ohc,
  IN INTERRUPT_CONTEXT_ENTRY  *Entry
  )
{
  TD_DESCRIPTOR           *Td;
  if (Entry == NULL) {
    return EFI_INVALID_PARAMETER;
  }
  if (Entry->UCBufferMapping != NULL) {
    Ohc->PciIo->Unmap(Ohc->PciIo, Entry->UCBufferMapping);
  }
  if (Entry->UCBuffer != NULL) {
    FreePool(Entry->UCBuffer);
  }
  while (Entry->DataTd) {
    Td = Entry->DataTd;
    Entry->DataTd = (TD_DESCRIPTOR *)(UINTN)(Entry->DataTd->NextTDPointer);
    UsbHcFreeMem(Ohc->MemPool, Td, sizeof(TD_DESCRIPTOR));
  }
  FreePool(Entry);
  return EFI_SUCCESS;
}
コード例 #9
0
ファイル: UhciSched.c プロジェクト: SunnyKi/bareBoot
/**
  Create Frame List Structure.

  @param  Uhc                    UHCI device.

  @retval EFI_OUT_OF_RESOURCES   Can't allocate memory resources.
  @retval EFI_UNSUPPORTED        Map memory fail.
  @retval EFI_SUCCESS            Success.

**/
EFI_STATUS
UhciInitFrameList (
  IN USB_HC_DEV         *Uhc
  )
{
  EFI_PHYSICAL_ADDRESS  MappedAddr;
  EFI_STATUS            Status;
  VOID                  *Buffer;
  VOID                  *Mapping;
  UINTN                 Pages;
  UINTN                 Bytes;
  UINTN                 Index;
  EFI_PHYSICAL_ADDRESS  PhyAddr;

  //
  // The Frame List is a common buffer that will be
  // accessed by both the cpu and the usb bus master
  // at the same time. The Frame List ocupies 4K bytes,
  // and must be aligned on 4-Kbyte boundaries.
  //
  Bytes = 4096;
  Pages = EFI_SIZE_TO_PAGES (Bytes);

  Status = Uhc->PciIo->AllocateBuffer (
                         Uhc->PciIo,
                         AllocateAnyPages,
                         EfiBootServicesData,
                         Pages,
                         &Buffer,
                         0
                         );

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

  Status = Uhc->PciIo->Map (
                         Uhc->PciIo,
                         EfiPciIoOperationBusMasterCommonBuffer,
                         Buffer,
                         &Bytes,
                         &MappedAddr,
                         &Mapping
                         );

  if (EFI_ERROR (Status) || (Bytes != 4096)) {
    Status = EFI_UNSUPPORTED;
    goto ON_ERROR;
  }

  Uhc->FrameBase           = (UINT32 *) (UINTN) Buffer;
  Uhc->FrameMapping        = Mapping;

  //
  // Tell the Host Controller where the Frame List lies,
  // by set the Frame List Base Address Register.
  //
  UhciSetFrameListBaseAddr (Uhc->PciIo, (VOID *) (UINTN) MappedAddr);

  //
  // Allocate the QH used by sync interrupt/control/bulk transfer.
  // FS ctrl/bulk queue head is set to loopback so additional BW
  // can be reclaimed. Notice, LS don't support bulk transfer and
  // also doesn't support BW reclamation.
  //
  Uhc->SyncIntQh  = UhciCreateQh (Uhc, 1);
  Uhc->CtrlQh     = UhciCreateQh (Uhc, 1);
  Uhc->BulkQh     = UhciCreateQh (Uhc, 1);

  if ((Uhc->SyncIntQh == NULL) || (Uhc->CtrlQh == NULL) || (Uhc->BulkQh == NULL)) {
    Uhc->PciIo->Unmap (Uhc->PciIo, Mapping);
    Status = EFI_OUT_OF_RESOURCES;
    goto ON_ERROR;
  }

  //
  //                                                +-------------+
  //                                                |             |
  // Link the three together: SyncIntQh->CtrlQh->BulkQh <---------+
  // Each frame entry is linked to this sequence of QH. These QH
  // will remain on the schedul, never got removed
  //
  PhyAddr = UsbHcGetPciAddressForHostMem (Uhc->MemPool, Uhc->CtrlQh, sizeof (UHCI_QH_HW));
  Uhc->SyncIntQh->QhHw.HorizonLink  = QH_HLINK (PhyAddr, FALSE);
  Uhc->SyncIntQh->NextQh            = Uhc->CtrlQh;

  PhyAddr = UsbHcGetPciAddressForHostMem (Uhc->MemPool, Uhc->BulkQh, sizeof (UHCI_QH_HW));
  Uhc->CtrlQh->QhHw.HorizonLink     = QH_HLINK (PhyAddr, FALSE);
  Uhc->CtrlQh->NextQh               = Uhc->BulkQh;

  //
  // Some old platform such as Intel's Tiger 4 has a difficult time
  // in supporting the full speed bandwidth reclamation in the previous
  // mentioned form. Most new platforms don't suffer it.
  //
  Uhc->BulkQh->QhHw.HorizonLink     = QH_HLINK (PhyAddr, FALSE);

  Uhc->BulkQh->NextQh               = NULL;

  Uhc->FrameBaseHostAddr = AllocateZeroPool (4096);
  if (Uhc->FrameBaseHostAddr == NULL) {
    Status = EFI_OUT_OF_RESOURCES;
    goto ON_ERROR;
  }

  PhyAddr = UsbHcGetPciAddressForHostMem (Uhc->MemPool, Uhc->SyncIntQh, sizeof (UHCI_QH_HW));
  for (Index = 0; Index < UHCI_FRAME_NUM; Index++) {
    Uhc->FrameBase[Index] = QH_HLINK (PhyAddr, FALSE);
    Uhc->FrameBaseHostAddr[Index] = (UINT32)(UINTN)Uhc->SyncIntQh;
  }

  return EFI_SUCCESS;

ON_ERROR:
  if (Uhc->SyncIntQh != NULL) {
    UsbHcFreeMem (Uhc->MemPool, Uhc->SyncIntQh, sizeof (UHCI_QH_SW));
  }

  if (Uhc->CtrlQh != NULL) {
    UsbHcFreeMem (Uhc->MemPool, Uhc->CtrlQh, sizeof (UHCI_QH_SW));
  }

  if (Uhc->BulkQh != NULL) {
    UsbHcFreeMem (Uhc->MemPool, Uhc->BulkQh, sizeof (UHCI_QH_SW));
  }

  Uhc->PciIo->FreeBuffer (Uhc->PciIo, Pages, Buffer);
  return Status;
}
コード例 #10
0
ファイル: OhcPeim.c プロジェクト: shijunjing/edk2
/**
  Submits control transfer to a target USB device.

  @param  PeiServices            The pointer of EFI_PEI_SERVICES.
  @param  This                   The pointer of PEI_USB_HOST_CONTROLLER_PPI.
  @param  DeviceAddress          The target device address.
  @param  DeviceSpeed            Target device speed.
  @param  MaximumPacketLength    Maximum packet size the default control transfer
                                 endpoint is capable of sending or receiving.
  @param  Request                USB device request to send.
  @param  TransferDirection      Specifies the data direction for the data stage.
  @param  Data                   Data buffer to be transmitted or received from USB device.
  @param  DataLength             The size (in bytes) of the data buffer.
  @param  TimeOut                Indicates the maximum timeout, in millisecond.
  @param  TransferResult         Return the result of this control transfer.

  @retval EFI_SUCCESS            Transfer was completed successfully.
  @retval EFI_OUT_OF_RESOURCES   The transfer failed due to lack of resources.
  @retval EFI_INVALID_PARAMETER  Some parameters are invalid.
  @retval EFI_TIMEOUT            Transfer failed due to timeout.
  @retval EFI_DEVICE_ERROR       Transfer failed due to host controller or device error.

**/
EFI_STATUS
EFIAPI
OhciControlTransfer (
  IN  EFI_PEI_SERVICES             **PeiServices,
  IN  PEI_USB_HOST_CONTROLLER_PPI  *This,
  IN  UINT8                        DeviceAddress,
  IN  UINT8                        DeviceSpeed,
  IN  UINT8                        MaxPacketLength,
  IN  EFI_USB_DEVICE_REQUEST       *Request,
  IN  EFI_USB_DATA_DIRECTION       TransferDirection,
  IN  OUT VOID                     *Data,
  IN  OUT UINTN                    *DataLength,
  IN  UINTN                        TimeOut,
  OUT UINT32                       *TransferResult
  )
{
  USB_OHCI_HC_DEV               *Ohc;
  ED_DESCRIPTOR                 *Ed;
  TD_DESCRIPTOR                 *HeadTd;
  TD_DESCRIPTOR                 *SetupTd;
  TD_DESCRIPTOR                 *DataTd;
  TD_DESCRIPTOR                 *StatusTd;
  TD_DESCRIPTOR                 *EmptyTd;
  EFI_STATUS                    Status;
  UINT32                        DataPidDir;
  UINT32                        StatusPidDir;
  UINTN                         TimeCount;
  UINT32                        ErrorCode;

  UINTN                         ActualSendLength;
  UINTN                         LeftLength;
  UINT8                         DataToggle;

  EFI_PHYSICAL_ADDRESS          ReqMapPhyAddr = 0;

  UINTN                         DataMapLength = 0;
  EFI_PHYSICAL_ADDRESS          DataMapPhyAddr = 0;

  HeadTd = NULL;
  DataTd = NULL;

  if ((TransferDirection != EfiUsbDataOut && TransferDirection != EfiUsbDataIn &&
       TransferDirection != EfiUsbNoData) ||
      Request == NULL || DataLength == NULL || TransferResult == NULL ||
      (TransferDirection == EfiUsbNoData && (*DataLength != 0 || Data != NULL)) ||
      (TransferDirection != EfiUsbNoData && (*DataLength == 0 || Data == NULL)) ||
      (DeviceSpeed != EFI_USB_SPEED_LOW && DeviceSpeed != EFI_USB_SPEED_FULL) ||
      (MaxPacketLength != 8 && MaxPacketLength != 16 &&
       MaxPacketLength != 32 && MaxPacketLength != 64)) {
    DEBUG ((EFI_D_INFO, "OhciControlTransfer: EFI_INVALID_PARAMETER\n"));
    return EFI_INVALID_PARAMETER;
  }

  if (*DataLength > MAX_BYTES_PER_TD) {
    DEBUG ((EFI_D_ERROR, "OhciControlTransfer: Request data size is too large\n"));
    return EFI_INVALID_PARAMETER;
  }

  Ohc = PEI_RECOVERY_USB_OHC_DEV_FROM_EHCI_THIS(This);

  if (TransferDirection == EfiUsbDataIn) {
    DataPidDir = TD_IN_PID;
    StatusPidDir = TD_OUT_PID;
  } else {
    DataPidDir = TD_OUT_PID;
    StatusPidDir = TD_IN_PID;
  }

  OhciSetHcControl (Ohc, CONTROL_ENABLE, 0);
  if (OhciGetHcControl (Ohc, CONTROL_ENABLE) != 0) {
    MicroSecondDelay (HC_1_MILLISECOND);
    if (OhciGetHcControl (Ohc, CONTROL_ENABLE) != 0) {
      *TransferResult = EFI_USB_ERR_SYSTEM;
      DEBUG ((EFI_D_INFO, "OhciControlTransfer: Fail to disable CONTROL transfer\n"));
      return EFI_DEVICE_ERROR;
    }
  }
  OhciSetMemoryPointer (Ohc, HC_CONTROL_HEAD, NULL);
  Ed = OhciCreateED (Ohc);
  if (Ed == NULL) {
    DEBUG ((EFI_D_INFO, "OhciControlTransfer: Fail to allocate ED buffer\n"));
    return EFI_OUT_OF_RESOURCES;
  }
  OhciSetEDField (Ed, ED_SKIP, 1);
  OhciSetEDField (Ed, ED_FUNC_ADD, DeviceAddress);
  OhciSetEDField (Ed, ED_ENDPT_NUM, 0);
  OhciSetEDField (Ed, ED_DIR, ED_FROM_TD_DIR);
  OhciSetEDField (Ed, ED_SPEED, DeviceSpeed);
  OhciSetEDField (Ed, ED_FORMAT | ED_HALTED | ED_DTTOGGLE, 0);
  OhciSetEDField (Ed, ED_MAX_PACKET, MaxPacketLength);
  OhciSetEDField (Ed, ED_PDATA, 0);
  OhciSetEDField (Ed, ED_ZERO, 0);
  OhciSetEDField (Ed, ED_TDHEAD_PTR, (UINT32) NULL);
  OhciSetEDField (Ed, ED_TDTAIL_PTR, (UINT32) NULL);
  OhciSetEDField (Ed, ED_NEXT_EDPTR, (UINT32) NULL);
  OhciAttachEDToList (Ohc, CONTROL_LIST, Ed, NULL);
  //
  // Setup Stage
  //
  if(Request != NULL) {
    ReqMapPhyAddr = (EFI_PHYSICAL_ADDRESS)(UINTN)Request;
  }
  SetupTd = OhciCreateTD (Ohc);
  if (SetupTd == NULL) {
    Status = EFI_OUT_OF_RESOURCES;
    DEBUG ((EFI_D_INFO, "OhciControlTransfer: Fail to allocate Setup TD buffer\n"));
    goto FREE_ED_BUFF;
  }
  HeadTd = SetupTd;
  OhciSetTDField (SetupTd, TD_PDATA, 0);
  OhciSetTDField (SetupTd, TD_BUFFER_ROUND, 1);
  OhciSetTDField (SetupTd, TD_DIR_PID, TD_SETUP_PID);
  OhciSetTDField (SetupTd, TD_DELAY_INT, TD_NO_DELAY);
  OhciSetTDField (SetupTd, TD_DT_TOGGLE, 2);
  OhciSetTDField (SetupTd, TD_ERROR_CNT, 0);
  OhciSetTDField (SetupTd, TD_COND_CODE, TD_TOBE_PROCESSED);
  OhciSetTDField (SetupTd, TD_CURR_BUFFER_PTR, (UINTN)ReqMapPhyAddr);
  OhciSetTDField (SetupTd, TD_NEXT_PTR, (UINT32) NULL);
  OhciSetTDField (SetupTd, TD_BUFFER_END_PTR, (UINTN)ReqMapPhyAddr + sizeof (EFI_USB_DEVICE_REQUEST) - 1);
  SetupTd->ActualSendLength = 0;
  SetupTd->DataBuffer = NULL;
  SetupTd->NextTDPointer = NULL;

  DataMapLength = *DataLength;
  if ((Data != NULL) && (DataMapLength != 0)) {
    DataMapPhyAddr = (EFI_PHYSICAL_ADDRESS)(UINTN)Data;
  }
  //
  //Data Stage
  //
  LeftLength = DataMapLength;
  ActualSendLength = DataMapLength;
  DataToggle = 1;
  while (LeftLength > 0) {
    ActualSendLength = LeftLength;
    if (LeftLength > MaxPacketLength) {
      ActualSendLength = MaxPacketLength;
    }
    DataTd = OhciCreateTD (Ohc);
    if (DataTd == NULL) {
      DEBUG ((EFI_D_INFO, "OhciControlTransfer: Fail to allocate Data TD buffer\n"));
      Status = EFI_OUT_OF_RESOURCES;
      goto FREE_TD_BUFF;
    }
    OhciSetTDField (DataTd, TD_PDATA, 0);
    OhciSetTDField (DataTd, TD_BUFFER_ROUND, 1);
    OhciSetTDField (DataTd, TD_DIR_PID, DataPidDir);
    OhciSetTDField (DataTd, TD_DELAY_INT, TD_NO_DELAY);
    OhciSetTDField (DataTd, TD_DT_TOGGLE, DataToggle);
    OhciSetTDField (DataTd, TD_ERROR_CNT, 0);
    OhciSetTDField (DataTd, TD_COND_CODE, TD_TOBE_PROCESSED);
    OhciSetTDField (DataTd, TD_CURR_BUFFER_PTR, (UINT32) DataMapPhyAddr);
    OhciSetTDField (DataTd, TD_BUFFER_END_PTR, (UINT32) DataMapPhyAddr + ActualSendLength - 1);
    OhciSetTDField (DataTd, TD_NEXT_PTR, (UINT32) NULL);
    DataTd->ActualSendLength = ActualSendLength;
    DataTd->DataBuffer = (UINT8 *)(UINTN)DataMapPhyAddr;
    DataTd->NextTDPointer = 0;
    OhciLinkTD (HeadTd, DataTd);
    DataToggle ^= 1;
    DataMapPhyAddr += ActualSendLength;
    LeftLength -= ActualSendLength;
  }
  //
  // Status Stage
  //
  StatusTd = OhciCreateTD (Ohc);
  if (StatusTd == NULL) {
    DEBUG ((EFI_D_INFO, "OhciControlTransfer: Fail to allocate Status TD buffer\n"));
    Status = EFI_OUT_OF_RESOURCES;
    goto FREE_TD_BUFF;
  }
  OhciSetTDField (StatusTd, TD_PDATA, 0);
  OhciSetTDField (StatusTd, TD_BUFFER_ROUND, 1);
  OhciSetTDField (StatusTd, TD_DIR_PID, StatusPidDir);
  OhciSetTDField (StatusTd, TD_DELAY_INT, 7);
  OhciSetTDField (StatusTd, TD_DT_TOGGLE, 3);
  OhciSetTDField (StatusTd, TD_ERROR_CNT, 0);
  OhciSetTDField (StatusTd, TD_COND_CODE, TD_TOBE_PROCESSED);
  OhciSetTDField (StatusTd, TD_CURR_BUFFER_PTR, (UINT32) NULL);
  OhciSetTDField (StatusTd, TD_NEXT_PTR, (UINT32) NULL);
  OhciSetTDField (StatusTd, TD_BUFFER_END_PTR, (UINT32) NULL);
  StatusTd->ActualSendLength = 0;
  StatusTd->DataBuffer = NULL;
  StatusTd->NextTDPointer = NULL;
  OhciLinkTD (HeadTd, StatusTd);
  //
  // Empty Stage
  //
  EmptyTd = OhciCreateTD (Ohc);
  if (EmptyTd == NULL) {
    Status = EFI_OUT_OF_RESOURCES;
    DEBUG ((EFI_D_INFO, "OhciControlTransfer: Fail to allocate Empty TD buffer\n"));
    goto FREE_TD_BUFF;
  }
  OhciSetTDField (EmptyTd, TD_PDATA, 0);
  OhciSetTDField (EmptyTd, TD_BUFFER_ROUND, 0);
  OhciSetTDField (EmptyTd, TD_DIR_PID, 0);
  OhciSetTDField (EmptyTd, TD_DELAY_INT, 0);
  //OhciSetTDField (EmptyTd, TD_DT_TOGGLE, CurrentToggle);
  EmptyTd->Word0.DataToggle = 0;
  OhciSetTDField (EmptyTd, TD_ERROR_CNT, 0);
  OhciSetTDField (EmptyTd, TD_COND_CODE, 0);
  OhciSetTDField (EmptyTd, TD_CURR_BUFFER_PTR, 0);
  OhciSetTDField (EmptyTd, TD_BUFFER_END_PTR, 0);
  OhciSetTDField (EmptyTd, TD_NEXT_PTR, 0);
  EmptyTd->ActualSendLength = 0;
  EmptyTd->DataBuffer = NULL;
  EmptyTd->NextTDPointer = NULL;
  OhciLinkTD (HeadTd, EmptyTd);
  Ed->TdTailPointer = EmptyTd;
  OhciAttachTDListToED (Ed, HeadTd);
  //
  OhciSetEDField (Ed, ED_SKIP, 0);
  MicroSecondDelay (20 * HC_1_MILLISECOND);
  OhciSetHcCommandStatus (Ohc, CONTROL_LIST_FILLED, 1);
  OhciSetHcControl (Ohc, CONTROL_ENABLE, 1);
  MicroSecondDelay (20 * HC_1_MILLISECOND);
  if (OhciGetHcControl (Ohc, CONTROL_ENABLE) != 1) {
  MicroSecondDelay (HC_1_MILLISECOND);
    if (OhciGetHcControl (Ohc, CONTROL_ENABLE) != 1) {
      *TransferResult = EFI_USB_ERR_SYSTEM;
      Status = EFI_DEVICE_ERROR;
      DEBUG ((EFI_D_INFO, "OhciControlTransfer: Fail to enable CONTROL transfer\n"));
      goto FREE_TD_BUFF;
    }
  }

  TimeCount = 0;
  Status = CheckIfDone (Ohc, CONTROL_LIST, Ed, HeadTd, &ErrorCode);

  while (Status == EFI_NOT_READY && TimeCount <= TimeOut) {
    MicroSecondDelay (HC_1_MILLISECOND);
    TimeCount++;
    Status = CheckIfDone (Ohc, CONTROL_LIST, Ed, HeadTd, &ErrorCode);
  }
  //
  *TransferResult = ConvertErrorCode (ErrorCode);

  if (ErrorCode != TD_NO_ERROR) {
    if (ErrorCode == TD_TOBE_PROCESSED) {
      DEBUG ((EFI_D_INFO, "Control pipe timeout, > %d mS\r\n", TimeOut));
    } else {
      DEBUG ((EFI_D_INFO, "Control pipe broken\r\n"));
    }

    *DataLength = 0;
  }

  OhciSetHcControl (Ohc, CONTROL_ENABLE, 0);
  if (OhciGetHcControl (Ohc, CONTROL_ENABLE) != 0) {
  MicroSecondDelay (HC_1_MILLISECOND);
    if (OhciGetHcControl (Ohc, CONTROL_ENABLE) != 0) {
      *TransferResult = EFI_USB_ERR_SYSTEM;
      DEBUG ((EFI_D_INFO, "OhciControlTransfer: Cannot disable CONTROL_ENABLE transfer\n"));
      goto FREE_TD_BUFF;
    }
  }

FREE_TD_BUFF:
  while (HeadTd) {
    DataTd = HeadTd;
    HeadTd = HeadTd->NextTDPointer;
    UsbHcFreeMem(Ohc->MemPool, DataTd, sizeof(TD_DESCRIPTOR));
  }

FREE_ED_BUFF:
  UsbHcFreeMem(Ohc->MemPool, Ed, sizeof(ED_DESCRIPTOR));

  return Status;
}
コード例 #11
0
ファイル: OhcPeim.c プロジェクト: shijunjing/edk2
/**
  Submits bulk transfer to a bulk endpoint of a USB device.

  @param  PeiServices           The pointer of EFI_PEI_SERVICES.
  @param  This                  The pointer of PEI_USB_HOST_CONTROLLER_PPI.
  @param  DeviceAddress         Target device address.
  @param  EndPointAddress       Endpoint number and its direction in bit 7.
  @param  MaxiPacketLength      Maximum packet size the endpoint is capable of
                                sending or receiving.
  @param  Data                  A pointers to the buffers of data to transmit
                                from or receive into.
  @param  DataLength            The lenght of the data buffer.
  @param  DataToggle            On input, the initial data toggle for the transfer;
                                On output, it is updated to to next data toggle to use of
                                the subsequent bulk transfer.
  @param  TimeOut               Indicates the maximum time, in millisecond, which the
                                transfer is allowed to complete.
  @param  TransferResult        A pointer to the detailed result information of the
                                bulk transfer.

  @retval EFI_SUCCESS           The transfer was completed successfully.
  @retval EFI_OUT_OF_RESOURCES  The transfer failed due to lack of resource.
  @retval EFI_INVALID_PARAMETER Parameters are invalid.
  @retval EFI_TIMEOUT           The transfer failed due to timeout.
  @retval EFI_DEVICE_ERROR      The transfer failed due to host controller error.

**/
EFI_STATUS
EFIAPI
OhciBulkTransfer (
  IN EFI_PEI_SERVICES             **PeiServices,
  IN PEI_USB_HOST_CONTROLLER_PPI  *This,
  IN  UINT8                       DeviceAddress,
  IN  UINT8                       EndPointAddress,
  IN  UINT8                       MaxPacketLength,
  IN  OUT VOID                    *Data,
  IN  OUT UINTN                   *DataLength,
  IN  OUT UINT8                   *DataToggle,
  IN  UINTN                       TimeOut,
  OUT UINT32                      *TransferResult
  )
{
  USB_OHCI_HC_DEV                *Ohc;
  ED_DESCRIPTOR                  *Ed;
  UINT32                         DataPidDir;
  TD_DESCRIPTOR                  *HeadTd;
  TD_DESCRIPTOR                  *DataTd;
  TD_DESCRIPTOR                  *EmptyTd;
  EFI_STATUS                     Status;
  UINT8                          EndPointNum;
  UINTN                          TimeCount;
  UINT32                         ErrorCode;

  UINT8                          CurrentToggle;
  UINTN                          MapLength;
  EFI_PHYSICAL_ADDRESS           MapPyhAddr;
  UINTN                          LeftLength;
  UINTN                          ActualSendLength;
  BOOLEAN                        FirstTD;

  MapLength = 0;
  MapPyhAddr = 0;
  LeftLength = 0;
  Status = EFI_SUCCESS;

  if (Data == NULL || DataLength == NULL || DataToggle == NULL || TransferResult == NULL ||
      *DataLength == 0 || (*DataToggle != 0 && *DataToggle != 1) ||
      (MaxPacketLength != 8 && MaxPacketLength != 16 &&
       MaxPacketLength != 32 && MaxPacketLength != 64)) {
    return EFI_INVALID_PARAMETER;
  }

  Ohc = PEI_RECOVERY_USB_OHC_DEV_FROM_EHCI_THIS (This);

  if ((EndPointAddress & 0x80) != 0) {
    DataPidDir = TD_IN_PID;
  } else {
    DataPidDir = TD_OUT_PID;
  }

  EndPointNum = (EndPointAddress & 0xF);

  OhciSetHcControl (Ohc, BULK_ENABLE, 0);
  if (OhciGetHcControl (Ohc, BULK_ENABLE) != 0) {
    MicroSecondDelay (HC_1_MILLISECOND);
    if (OhciGetHcControl (Ohc, BULK_ENABLE) != 0) {
      *TransferResult = EFI_USB_ERR_SYSTEM;
      return EFI_DEVICE_ERROR;
    }
  }

  OhciSetMemoryPointer (Ohc, HC_BULK_HEAD, NULL);

  Ed = OhciCreateED (Ohc);
  if (Ed == NULL) {
    DEBUG ((EFI_D_INFO, "OhcBulkTransfer: Fail to allocate ED buffer\r\n"));
    return EFI_OUT_OF_RESOURCES;
  }
  OhciSetEDField (Ed, ED_SKIP, 1);
  OhciSetEDField (Ed, ED_FUNC_ADD, DeviceAddress);
  OhciSetEDField (Ed, ED_ENDPT_NUM, EndPointNum);
  OhciSetEDField (Ed, ED_DIR, ED_FROM_TD_DIR);
  OhciSetEDField (Ed, ED_SPEED, HI_SPEED);
  OhciSetEDField (Ed, ED_FORMAT | ED_HALTED | ED_DTTOGGLE, 0);
  OhciSetEDField (Ed, ED_MAX_PACKET, MaxPacketLength);
  OhciSetEDField (Ed, ED_PDATA, 0);
  OhciSetEDField (Ed, ED_ZERO, 0);
  OhciSetEDField (Ed, ED_TDHEAD_PTR, (UINT32) NULL);
  OhciSetEDField (Ed, ED_TDTAIL_PTR, (UINT32) NULL);
  OhciSetEDField (Ed, ED_NEXT_EDPTR, (UINT32) NULL);
  OhciAttachEDToList (Ohc, BULK_LIST, Ed, NULL);

  if(Data != NULL) {
    MapLength = *DataLength;
    MapPyhAddr = (EFI_PHYSICAL_ADDRESS)(UINTN)Data;
  }
  //
  //Data Stage
  //
  LeftLength = MapLength;
  ActualSendLength = MapLength;
  CurrentToggle = *DataToggle;
  HeadTd = NULL;
  FirstTD = TRUE;
  while (LeftLength > 0) {
    ActualSendLength = LeftLength;
    if (LeftLength > MaxPacketLength) {
      ActualSendLength = MaxPacketLength;
    }
    DataTd = OhciCreateTD (Ohc);
    if (DataTd == NULL) {
      DEBUG ((EFI_D_INFO, "OhcBulkTransfer: Fail to allocate Data TD buffer\r\n"));
      Status = EFI_OUT_OF_RESOURCES;
      goto FREE_TD_BUFF;
    }
    OhciSetTDField (DataTd, TD_PDATA, 0);
    OhciSetTDField (DataTd, TD_BUFFER_ROUND, 1);
    OhciSetTDField (DataTd, TD_DIR_PID, DataPidDir);
    OhciSetTDField (DataTd, TD_DELAY_INT, TD_NO_DELAY);
    OhciSetTDField (DataTd, TD_DT_TOGGLE, CurrentToggle);
    OhciSetTDField (DataTd, TD_ERROR_CNT, 0);
    OhciSetTDField (DataTd, TD_COND_CODE, TD_TOBE_PROCESSED);
    OhciSetTDField (DataTd, TD_CURR_BUFFER_PTR, (UINT32) MapPyhAddr);
    OhciSetTDField (DataTd, TD_BUFFER_END_PTR, (UINT32) MapPyhAddr + ActualSendLength - 1);
    OhciSetTDField (DataTd, TD_NEXT_PTR, (UINT32) NULL);
    DataTd->ActualSendLength = ActualSendLength;
    DataTd->DataBuffer = (UINT8 *)(UINTN)MapPyhAddr;
    DataTd->NextTDPointer = 0;
    if (FirstTD) {
      HeadTd = DataTd;
      FirstTD = FALSE;
    } else {
      OhciLinkTD (HeadTd, DataTd);
    }
    CurrentToggle ^= 1;
    MapPyhAddr += ActualSendLength;
    LeftLength -= ActualSendLength;
  }
  //
  // Empty Stage
  //
  EmptyTd = OhciCreateTD (Ohc);
  if (EmptyTd == NULL) {
    Status = EFI_OUT_OF_RESOURCES;
      DEBUG ((EFI_D_INFO, "OhcBulkTransfer: Fail to allocate Empty TD buffer\r\n"));
    goto FREE_TD_BUFF;
  }
  OhciSetTDField (EmptyTd, TD_PDATA, 0);
  OhciSetTDField (EmptyTd, TD_BUFFER_ROUND, 0);
  OhciSetTDField (EmptyTd, TD_DIR_PID, 0);
  OhciSetTDField (EmptyTd, TD_DELAY_INT, 0);
  //OhciSetTDField (EmptyTd, TD_DT_TOGGLE, CurrentToggle);
  EmptyTd->Word0.DataToggle = 0;
  OhciSetTDField (EmptyTd, TD_ERROR_CNT, 0);
  OhciSetTDField (EmptyTd, TD_COND_CODE, 0);
  OhciSetTDField (EmptyTd, TD_CURR_BUFFER_PTR, 0);
  OhciSetTDField (EmptyTd, TD_BUFFER_END_PTR, 0);
  OhciSetTDField (EmptyTd, TD_NEXT_PTR, 0);
  EmptyTd->ActualSendLength = 0;
  EmptyTd->DataBuffer = NULL;
  EmptyTd->NextTDPointer = NULL;
  OhciLinkTD (HeadTd, EmptyTd);
  Ed->TdTailPointer = EmptyTd;
  OhciAttachTDListToED (Ed, HeadTd);

  OhciSetEDField (Ed, ED_SKIP, 0);
  OhciSetHcCommandStatus (Ohc, BULK_LIST_FILLED, 1);
  OhciSetHcControl (Ohc, BULK_ENABLE, 1);
  if (OhciGetHcControl (Ohc, BULK_ENABLE) != 1) {
    MicroSecondDelay (HC_1_MILLISECOND);
    if (OhciGetHcControl (Ohc, BULK_ENABLE) != 1) {
      *TransferResult = EFI_USB_ERR_SYSTEM;
      goto FREE_TD_BUFF;
    }
  }

  TimeCount = 0;
  Status = CheckIfDone (Ohc, BULK_LIST, Ed, HeadTd, &ErrorCode);

  while (Status == EFI_NOT_READY && TimeCount <= TimeOut) {
    MicroSecondDelay (HC_1_MILLISECOND);
    TimeCount++;
    Status = CheckIfDone (Ohc, BULK_LIST, Ed, HeadTd, &ErrorCode);
  }

  *TransferResult = ConvertErrorCode (ErrorCode);

  if (ErrorCode != TD_NO_ERROR) {
    if (ErrorCode == TD_TOBE_PROCESSED) {
      DEBUG ((EFI_D_INFO, "Bulk pipe timeout, > %d mS\r\n", TimeOut));
    } else {
      DEBUG ((EFI_D_INFO, "Bulk pipe broken\r\n"));
    }
    *DataLength = 0;
  }
    *DataToggle = (UINT8) OhciGetEDField (Ed, ED_DTTOGGLE);

FREE_TD_BUFF:
  while (HeadTd) {
    DataTd = HeadTd;
    HeadTd = HeadTd->NextTDPointer;
    UsbHcFreeMem(Ohc->MemPool, DataTd, sizeof(TD_DESCRIPTOR));
  }
  UsbHcFreeMem(Ohc->MemPool, Ed, sizeof(ED_DESCRIPTOR));

  return Status;
}