コード例 #1
0
/**
  Clear all the interrutp status bits, these bits
  are Write-Clean.

  @param  Uhc          The UHCI device.

**/
VOID
UhciAckAllInterrupt (
  IN  USB_HC_DEV          *Uhc
  )
{
  UhciWriteReg (Uhc->PciIo, USBSTS_OFFSET, 0x3F);

  //
  // If current HC is halted, re-enable it. Host Controller Process Error
  // is a temporary error status.
  //
  if (!UhciIsHcWorking (Uhc->PciIo)) {
    DEBUG ((EFI_D_ERROR, "UhciAckAllInterrupt: re-enable the UHCI from system error\n"));
    Uhc->Usb2Hc.SetState (&Uhc->Usb2Hc, EfiUsbHcStateOperational);
  }
}
コード例 #2
0
ファイル: UhciSched.c プロジェクト: SunnyKi/bareBoot
/**
  Check TDs Results.

  @param  Uhc                    This UHCI device.
  @param  Td                     UHCI_TD_SW to check.
  @param  IsLow                  Is Low Speed Device.
  @param  QhResult               Return the result of this TD list.

  @return Whether the TD's result is finialized.

**/
BOOLEAN
UhciCheckTdStatus (
  IN  USB_HC_DEV          *Uhc,
  IN  UHCI_TD_SW          *Td,
  IN  BOOLEAN             IsLow,
  OUT UHCI_QH_RESULT      *QhResult
  )
{
  UINTN                   Len;
  UINT8                   State;
  UHCI_TD_HW              *TdHw;
  BOOLEAN                 Finished;

  Finished             = TRUE;

  //
  // Initialize the data toggle to that of the first
  // TD. The next toggle to use is either:
  // 1. first TD's toggle if no TD is executed OK
  // 2. the next toggle of last executed-OK TD
  //
  QhResult->Result     = EFI_USB_NOERROR;
  QhResult->NextToggle = (UINT8)Td->TdHw.DataToggle;
  QhResult->Complete   = 0;

  while (Td != NULL) {
    TdHw  = &Td->TdHw;
    State = (UINT8)TdHw->Status;

    //
    // UHCI will set STALLED bit when it abort the execution
    // of TD list. There are several reasons:
    //   1. BABBLE error happened
    //   2. Received a STALL response
    //   3. Error count decreased to zero.
    //
    // It also set CRC/Timeout/NAK/Buffer Error/BitStuff Error
    // bits when corresponding conditions happen. But these
    // conditions are not deadly, that is a TD can successfully
    // completes even these bits are set. But it is likely that
    // upper layer won't distinguish these condtions. So, only
    // set these bits when TD is actually halted.
    //
    if ((State & USBTD_STALLED) != 0) {
      if ((State & USBTD_BABBLE) != 0) {
        QhResult->Result |= EFI_USB_ERR_BABBLE;

      } else if (TdHw->ErrorCount != 0) {
        QhResult->Result |= EFI_USB_ERR_STALL;
      }

      if ((State & USBTD_CRC) != 0) {
        QhResult->Result |= EFI_USB_ERR_CRC;
      }

      if ((State & USBTD_BUFFERR) != 0) {
        QhResult->Result |= EFI_USB_ERR_BUFFER;
      }

      if ((Td->TdHw.Status & USBTD_BITSTUFF) != 0) {
        QhResult->Result |= EFI_USB_ERR_BITSTUFF;
      }

      if (TdHw->ErrorCount == 0) {
        QhResult->Result |= EFI_USB_ERR_TIMEOUT;
      }

      Finished = TRUE;
      goto ON_EXIT;

    } else if ((State & USBTD_ACTIVE) != 0) {
      //
      // The TD is still active, no need to check further.
      //
      QhResult->Result |= EFI_USB_ERR_NOTEXECUTE;

      Finished = FALSE;
      goto ON_EXIT;

    } else {
      //
      // Update the next data toggle, it is always the
      // next to the last known-good TD's data toggle if
      // any TD is executed OK
      //
      QhResult->NextToggle = (UINT8) (1 - (UINT8)TdHw->DataToggle);

      //
      // This TD is finished OK or met short packet read. Update the
      // transfer length if it isn't a SETUP.
      //
      Len = (TdHw->ActualLen + 1) & 0x7FF;

      if (TdHw->PidCode != SETUP_PACKET_ID) {
        QhResult->Complete += Len;
      }

      //
      // Short packet condition for full speed input TD, also
      // terminate the transfer
      //
      if (!IsLow && (TdHw->ShortPacket == 1) && (Len < Td->DataLen)) {
        DEBUG ((EFI_D_VERBOSE, "UhciCheckTdStatus: short packet read occured\n"));

        Finished = TRUE;
        goto ON_EXIT;
      }
    }

    Td = Td->NextTd;
  }

ON_EXIT:
  //
  // Check whether HC is halted. Don't move this up. It must be
  // called after data toggle is successfully updated.
  //
  if (!UhciIsHcWorking (Uhc->PciIo)) {
    QhResult->Result |= EFI_USB_ERR_SYSTEM;
    Finished  = TRUE;
  }

  if (Finished) {
    Uhc->PciIo->Flush (Uhc->PciIo);
  }

  UhciAckAllInterrupt (Uhc);
  return Finished;
}