Ejemplo n.º 1
0
UINT32
CheckEDStatus (
  IN  ED_DESCRIPTOR       *Ed,
  IN  TD_DESCRIPTOR       *HeadTd
  )
{
  while(HeadTd != NULL) {
    if (HeadTd->Word0.ConditionCode != 0) {
      return HeadTd->Word0.ConditionCode;
    }
    HeadTd = HeadTd->NextTDPointer;
  }

  if (OhciGetEDField (Ed, ED_TDHEAD_PTR) != OhciGetEDField (Ed, ED_TDTAIL_PTR)) {
    return TD_TOBE_PROCESSED;
  }

  return TD_NO_ERROR;
}
Ejemplo n.º 2
0
UINT32
CheckEDStatus (
  IN  ED_DESCRIPTOR       *Ed,
  IN  TD_DESCRIPTOR       *HeadTd,
  OUT OHCI_ED_RESULT      *EdResult
  )
{
  while(HeadTd != NULL) {
    if (HeadTd->NextTDPointer == 0) {
      return TD_NO_ERROR;
    }
    if (HeadTd->Word0.ConditionCode != 0) {
      return HeadTd->Word0.ConditionCode;
    }
    EdResult->NextToggle = ((UINT8)(HeadTd->Word0.DataToggle) & BIT0) ^ BIT0;
    HeadTd = (TD_DESCRIPTOR *)(UINTN)(HeadTd->NextTDPointer);
  }
  if (OhciGetEDField (Ed, ED_TDHEAD_PTR) != OhciGetEDField (Ed, ED_TDTAIL_PTR)) {
    return TD_TOBE_PROCESSED;
  }
  return TD_NO_ERROR;
}
Ejemplo n.º 3
0
VOID
EFIAPI
OhciHouseKeeper (
  IN  EFI_EVENT           Event,
  IN  VOID                *Context
  )
{

  USB_OHCI_HC_DEV          *Ohc;
  INTERRUPT_CONTEXT_ENTRY  *Entry;
  INTERRUPT_CONTEXT_ENTRY  *PreEntry;
  ED_DESCRIPTOR            *Ed;
  TD_DESCRIPTOR            *DataTd;
  TD_DESCRIPTOR            *HeadTd;

  UINT8                    Toggle;
  EFI_TPL                  OriginalTPL;
  UINT32                   Result;

  Ohc = (USB_OHCI_HC_DEV *) Context;
  OriginalTPL = gBS->RaiseTPL(TPL_NOTIFY);

  Entry = Ohc->InterruptContextList;
  PreEntry = NULL;

  while(Entry != NULL) {

    OhciCheckTDsResults(Ohc, Entry->DataTd, &Result );
    if (((Result & EFI_USB_ERR_STALL) == EFI_USB_ERR_STALL) ||
      ((Result & EFI_USB_ERR_NOTEXECUTE) == EFI_USB_ERR_NOTEXECUTE)) {
      PreEntry = Entry;
      Entry = Entry->NextEntry;
      continue;
    }

    if (Entry->CallBackFunction != NULL) {
      OhciInvokeInterruptCallBack (Entry, Result);
      if (Ohc->InterruptContextList == NULL) {
        gBS->RestoreTPL (OriginalTPL);
        return;
      }
    }
    if (Entry->IsPeriodic) {

      Ed = Entry->Ed;
      HeadTd = Entry->DataTd;
      DataTd = HeadTd;
      Toggle = 0;
      if (Result == EFI_USB_NOERROR) {
        //
        // Update toggle if there is no error, and re-submit the interrupt Ed&Tds
        //
        if ((Ed != NULL) && (DataTd != NULL)) {
          Ed->Word0.Skip = 1;
        }
        //
        // From hcir1_0a.pdf 4.2.2
        // ToggleCarry:This bit is the data toggle carry bit,
        // Whenever a TD is retired, this bit is written to
        // contain the last data toggle value(LSb of data Toggel
        // file) from the retired TD.
        // This field is not used for Isochronous Endpoints
        //
        if (Ed == NULL) {
          return;
        }
        Toggle = (UINT8) OhciGetEDField (Ed, ED_DTTOGGLE);
        while(DataTd != NULL) {
          if (DataTd->NextTDPointer == 0) {
            DataTd->Word0.DataToggle = 0;
            break;
          } else {
            OhciSetTDField (DataTd, TD_DT_TOGGLE, Toggle);
          }
          DataTd = (TD_DESCRIPTOR *)(UINTN)(DataTd->NextTDPointer);
          Toggle ^= 1;
        }
        //
        // HC will only update DataToggle, ErrorCount, ConditionCode
        // CurrentBufferPointer & NextTD, so we only need to update
        // them once we want to active them again
        //
        DataTd = HeadTd;
        while (DataTd != NULL) {
          if (DataTd->NextTDPointer == 0) {
            OhciSetTDField (DataTd, TD_ERROR_CNT | TD_COND_CODE | TD_CURR_BUFFER_PTR | TD_NEXT_PTR, 0);
            break;
          }
          OhciSetTDField (DataTd, TD_ERROR_CNT, 0);
          OhciSetTDField (DataTd, TD_COND_CODE, TD_TOBE_PROCESSED);
          DataTd->NextTD = DataTd->NextTDPointer;
          DataTd->CurrBufferPointer = DataTd->DataBuffer;
          DataTd = (TD_DESCRIPTOR *)(UINTN)(DataTd->NextTDPointer);
        }
        //
        // Active current Ed,Td
        //
        // HC will only update Halted, ToggleCarry & TDQueueHeadPointer,
        // So we only need to update them once we want to active them again.
        //
        if ((Ed != NULL) && (DataTd != NULL)) {
          Ed->Word2.TdHeadPointer = (UINT32)((UINTN)HeadTd>>4);
          OhciSetEDField (Ed, ED_HALTED | ED_DTTOGGLE, 0);
          Ed->Word0.Skip = 0;
        }
      }
    } else {
Ejemplo n.º 4
0
/**
  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;
}