ehcisched.c

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

C
2,975
字号
Returns:

  EFI_SUCCESS       Success
  EFI_DEVICE_ERROR  Fail

--*/
{
  EFI_STATUS  Status;

  Status = EFI_SUCCESS;

  ASSERT (HcDev);
  ASSERT (QhPtr);

  
  HcDev->NULLQH->Next = HcDev->NULLQH;
  HcDev->NULLQH->Prev = HcDev->NULLQH;


  QhPtr->Next = QhPtr;
  QhPtr->Prev = QhPtr;
  
  HcDev->NULLQH->Qh.QhHorizontalPointer = (UINT32) (GET_0B_TO_31B (&(HcDev->NULLQH->Qh) >> 5));
  
  
  SetAndWaitDoorBell (HcDev, 2 * EHCI_GENERIC_TIMEOUT);

  QhPtr->Qh.QhTerminate         = 1;
  QhPtr->Qh.QhHorizontalPointer = 0;


  Status = DisableAsynchronousSchedule (HcDev);
  if (EFI_ERROR (Status)) {
    Status = EFI_DEVICE_ERROR;
    goto exit;
  }

  Status = WaitForAsyncScheduleDisable (HcDev, EHCI_GENERIC_TIMEOUT);
  if (EFI_ERROR (Status)) {
    DEBUG ((gEHCErrorLevel, "EHCI: WaitForAsyncScheduleDisable TimeOut\n"));
    Status = EFI_TIMEOUT;
    goto exit;
  }


exit:
  return Status;
}

VOID
LinkQhToPeriodicList (
  IN USB2_HC_DEV        *HcDev,
  IN EHCI_QH_ENTITY     *QhPtr
  )
/*++

Routine Description:

  Link Qh to Periodic Schedule List

Arguments:

  HcDev  - USB2_HC_DEV
  QhPtr  - A pointer to Qh

Returns:

  VOID

--*/
{
  FRAME_LIST_ENTRY  *FrameEntryPtr;
  EHCI_QH_ENTITY    *FindQhPtr;
  EHCI_QH_HW        *FindQhHwPtr;
  UINTN             FrameIndex;

  ASSERT (HcDev);
  ASSERT (QhPtr);

  FindQhPtr                     = NULL;
  FindQhHwPtr                   = NULL;
  FrameIndex                    = 0;
  FrameEntryPtr                 = (FRAME_LIST_ENTRY *) HcDev->PeriodicFrameListBuffer;

  QhPtr->Qh.HeadReclamationFlag = FALSE;

  if (QhPtr->TransferType == ASYNC_INTERRUPT_TRANSFER) {

    //
    // AsyncInterruptTransfer Qh
    //

    //
    // Link to Frame[0] List
    //
    if (!FrameEntryPtr->LinkTerminate) {
      //
      // Not Null FrameList
      //
      FindQhHwPtr = (EHCI_QH_HW *) GET_0B_TO_31B (FrameEntryPtr->LinkPointer << 5);
      FindQhPtr   = (EHCI_QH_ENTITY *) GET_QH_ENTITY_ADDR (FindQhHwPtr);
      //
      // FindQh is Left/Right to Qh
      //
      while ((NULL != FindQhPtr->Next) && (FindQhPtr->Interval > QhPtr->Interval)) {
        FindQhPtr = FindQhPtr->Next;
      }

      if (FindQhPtr->Interval == QhPtr->Interval) {
        //
        // Link Qh after FindQh
        //
        if (NULL != FindQhPtr->Next) {
          FindQhPtr->Next->Prev         = QhPtr;
          QhPtr->Qh.QhHorizontalPointer = (UINT32) GET_0B_TO_31B (&(FindQhPtr->Next->Qh) >> 5);
          QhPtr->Qh.SelectType          = QH_SELECT_TYPE;
          QhPtr->Qh.QhTerminate         = FALSE;
        }

        FindQhPtr->Qh.QhHorizontalPointer = (UINT32) GET_0B_TO_31B (&(QhPtr->Qh) >> 5);
        FindQhPtr->Qh.SelectType          = QH_SELECT_TYPE;
        FindQhPtr->Qh.QhTerminate         = FALSE;

        QhPtr->Prev                       = FindQhPtr;
        QhPtr->Next                       = FindQhPtr->Next;
        FindQhPtr->Next                   = QhPtr;
      } else if (FindQhPtr->Interval < QhPtr->Interval) {
        //
        // Link Qh before FindQh
        //
        if (NULL == FindQhPtr->Prev) {
          //
          // Qh is the First one in Frame[0] List
          //
          FrameEntryPtr->LinkPointer    = (UINT32) GET_0B_TO_31B (&(QhPtr->Qh) >> 5);
          FrameEntryPtr->SelectType     = QH_SELECT_TYPE;
          FrameEntryPtr->LinkTerminate  = FALSE;
        } else {
          //
          // Qh is not the First one in Frame[0] List
          //
          FindQhPtr->Prev->Next                   = QhPtr;
          FindQhPtr->Prev->Qh.QhHorizontalPointer = (UINT32) GET_0B_TO_31B (&(QhPtr->Qh) >> 5);
          FindQhPtr->Prev->Qh.SelectType          = QH_SELECT_TYPE;
          FindQhPtr->Prev->Qh.QhTerminate         = FALSE;
        }

        QhPtr->Qh.QhHorizontalPointer = (UINT32) GET_0B_TO_31B (&(FindQhPtr->Qh) >> 5);
        QhPtr->Qh.SelectType          = QH_SELECT_TYPE;
        QhPtr->Qh.QhTerminate         = FALSE;

        QhPtr->Next                   = FindQhPtr;
        QhPtr->Prev                   = FindQhPtr->Prev;
        FindQhPtr->Prev               = QhPtr;
      } else {
        //
        // Link Qh after FindQh, Qh is the Last one
        //
        FindQhPtr->Qh.QhHorizontalPointer = (UINT32) GET_0B_TO_31B (&(QhPtr->Qh) >> 5);
        FindQhPtr->Prev->Qh.SelectType    = QH_SELECT_TYPE;
        FindQhPtr->Qh.QhTerminate         = FALSE;

        QhPtr->Prev                       = FindQhPtr;
        QhPtr->Next                       = NULL;
        FindQhPtr->Next                   = QhPtr;
      }
    } else {
      //
      // Null FrameList
      //
      FrameEntryPtr->LinkPointer    = (UINT32) GET_0B_TO_31B (&(QhPtr->Qh) >> 5);
      FrameEntryPtr->SelectType     = QH_SELECT_TYPE;
      FrameEntryPtr->LinkTerminate  = FALSE;
    }
    //
    // Other Frame[X]
    //
    if (NULL == QhPtr->Prev) {
      //
      // Qh is the First one in Frame[0] List
      //
      FrameIndex += QhPtr->Interval;
      while (FrameIndex < HcDev->PeriodicFrameListLength) {
        FrameEntryPtr                 = (FRAME_LIST_ENTRY *) (FrameEntryPtr + QhPtr->Interval);
        FrameEntryPtr->LinkPointer    = (UINT32) GET_0B_TO_31B (&(QhPtr->Qh) >> 5);
        FrameEntryPtr->SelectType     = QH_SELECT_TYPE;
        FrameEntryPtr->LinkTerminate  = FALSE;
        FrameIndex += QhPtr->Interval;
      }
    } else if (QhPtr->Interval < QhPtr->Prev->Interval) {
      //
      // Qh is not the First one in Frame[0] List, and Prev.interval > Qh.interval
      //
      FrameIndex += QhPtr->Interval;
      while (FrameIndex < HcDev->PeriodicFrameListLength) {
        FrameEntryPtr = (FRAME_LIST_ENTRY *) (FrameEntryPtr + QhPtr->Interval);
        if ((FrameIndex % QhPtr->Prev->Interval) != 0) {
          FrameEntryPtr->LinkPointer    = (UINT32) GET_0B_TO_31B (&(QhPtr->Qh) >> 5);
          FrameEntryPtr->SelectType     = QH_SELECT_TYPE;
          FrameEntryPtr->LinkTerminate  = FALSE;
        }

        FrameIndex += QhPtr->Interval;
      }
    }
  } else {

    //
    // SyncInterruptTransfer Qh
    //

    if (!FrameEntryPtr->LinkTerminate) {
      //
      // Not Null FrameList
      //
      FindQhHwPtr = (EHCI_QH_HW *) GET_0B_TO_31B (FrameEntryPtr->LinkPointer << 5);
      FindQhPtr   = (EHCI_QH_ENTITY *) GET_QH_ENTITY_ADDR (FindQhHwPtr);
      //
      // FindQh is Last Qh in the Asynchronous List, Link Qh after FindQh
      //
      while (NULL != FindQhPtr->Next) {
        FindQhPtr = FindQhPtr->Next;
      }

      FindQhPtr->Qh.QhHorizontalPointer = (UINT32) GET_0B_TO_31B (&(QhPtr->Qh) >> 5);
      FindQhPtr->Qh.SelectType          = QH_SELECT_TYPE;
      FindQhPtr->Qh.QhTerminate         = FALSE;

      FindQhPtr->Next                   = QhPtr;
      QhPtr->Prev                       = FindQhPtr;
    } else {
      //
      // Null FrameList
      //
      FrameEntryPtr->LinkPointer    = (UINT32) GET_0B_TO_31B (&(QhPtr->Qh) >> 5);
      FrameEntryPtr->SelectType     = QH_SELECT_TYPE;
      FrameEntryPtr->LinkTerminate  = FALSE;
    }
  }

  return ;
}

VOID
UnlinkQhFromPeriodicList (
  IN USB2_HC_DEV        *HcDev,
  IN EHCI_QH_ENTITY     *QhPtr,
  IN UINTN              Interval
  )
/*++

Routine Description:

  Unlink Qh from Periodic Schedule List

Arguments:

  HcDev     - USB2_HC_DEV
  QhPtr     - A pointer to Qh
  Interval  - Interval of this periodic transfer

Returns:

  VOID

--*/
{
  FRAME_LIST_ENTRY  *FrameEntryPtr;
  UINTN             FrameIndex;

  FrameIndex = 0;

  ASSERT (HcDev);
  ASSERT (QhPtr);

  FrameIndex    = 0;
  FrameEntryPtr = (FRAME_LIST_ENTRY *) HcDev->PeriodicFrameListBuffer;

  if (QhPtr->TransferType == ASYNC_INTERRUPT_TRANSFER) {

    //
    // AsyncInterruptTransfer Qh
    //

    if (NULL == QhPtr->Prev) {
      //
      // Qh is the First one on  Frame[0] List
      //
      if (NULL == QhPtr->Next) {
        //
        // Only one on  Frame[0] List
        //
        while (FrameIndex < HcDev->PeriodicFrameListLength) {
          FrameEntryPtr->LinkPointer    = 0;
          FrameEntryPtr->SelectType     = 0;
          FrameEntryPtr->LinkTerminate  = TRUE;
          FrameEntryPtr                += Interval;
          FrameIndex                   += Interval;
        }
      } else {
        while (FrameIndex < HcDev->PeriodicFrameListLength) {
          FrameEntryPtr->LinkPointer    = (UINT32) GET_0B_TO_31B (&(QhPtr->Next->Qh) >> 5);
          FrameEntryPtr->SelectType     = QH_SELECT_TYPE;
          FrameEntryPtr->LinkTerminate  = FALSE;
          FrameEntryPtr += Interval;
          FrameIndex += Interval;
        }
      }
    } else {

      //
      // Not First one on  Frame[0] List
      //
      if (NULL == QhPtr->Next) {
        //
        // Qh is the Last one on  Frame[0] List
        //
        QhPtr->Prev->Qh.QhHorizontalPointer = 0;
        QhPtr->Prev->Qh.SelectType          = 0;
        QhPtr->Prev->Qh.QhTerminate         = TRUE;
      } else {
        QhPtr->Prev->Qh.QhHorizontalPointer = (UINT32) GET_0B_TO_31B (&(QhPtr->Next->Qh) >> 5);
        QhPtr->Prev->Qh.SelectType          = QH_SELECT_TYPE;
        QhPtr->Prev->Qh.QhTerminate         = FALSE;
      }

      if (Interval == QhPtr->Prev->Interval) {
        //
        // Interval is the same as Prev
        // Not involed Frame[X]
        //
      } else {
        //
        // Other Frame[X]
        //
        while (FrameIndex < HcDev->PeriodicFrameListLength) {
          if ((FrameIndex % QhPtr->Prev->Interval) != 0) {
            FrameEntryPtr->LinkPointer    = QhPtr->Prev->Qh.QhHorizontalPointer;
            FrameEntryPtr->SelectType     = QhPtr->Prev->Qh.SelectType;
            FrameEntryPtr->LinkTerminate  = QhPtr->Prev->Qh.QhTerminate;
          }
          FrameEntryPtr += Interval;
          FrameIndex += Interval;
        }
      }
    }

    if (NULL != QhPtr->Next) {
      QhPtr->Next->Prev = QhPtr->Prev;
    }

    if (NULL != QhPtr->Prev) {
      QhPtr->Prev->Next = QhPtr->Next;
    }
  } else {
    //
    // SyncInterruptTransfer Qh
    //
    if (NULL == QhPtr->Prev) {
      //
      // Qh is the only one Qh on  Frame[0] List
      //
      FrameEntryPtr->LinkPointer    = 0;
      FrameEntryPtr->SelectType     = 0;
      FrameEntryPtr->LinkTerminate  = TRUE;
    } else {
      QhPtr->Prev->Qh.QhHorizontalPointer = 0;
      QhPtr->Prev->Qh.SelectType          = 0;
      QhPtr->Prev->Qh.QhTerminate         = TRUE;
    }

    if (NULL != QhPtr->Prev) {
      QhPtr->Prev->Next = NULL;
    }
  }

  return ;
}

VOID
LinkToAsyncReqeust (
  IN  USB2_HC_DEV        *HcDev,
  IN  EHCI_ASYNC_REQUEST *AsyncRequestPtr
  )
/*++

Routine Description:

  Llink AsyncRequest Entry to Async Request List

Arguments:

  HcDev             - USB2_HC_DEV
  AsyncRequestPtr   - A pointer to Async Request Entry

Returns:

  VOID

--*/
{
  EHCI_ASYNC_REQUEST  *CurrentPtr;

  CurrentPtr              = HcDev->AsyncRequestList;
  HcDev->AsyncRequestList = AsyncRequestPtr;
  AsyncRequestPtr->Prev   = NULL;
  AsyncRequestPtr->Next   = CurrentPtr;

  if (NULL != CurrentPtr) {
    CurrentPtr->Prev = AsyncRequestPtr;
  }

  return ;
}

VOID
UnlinkFromAsyncReqeust (
  IN  USB2_HC_DEV        *HcDev,
  IN  EHCI_ASYNC_REQUEST *AsyncRequestPtr
  )
/*++

Routine Description:

  Unlink AsyncRequest Entry from Async Request List

Arguments:

  HcDev            - USB2_HC_DEV
  AsyncRequestPtr  - A pointer to Async Request Entry

Returns:

  VOID

--*/
{
  if (NULL == AsyncRequestPtr->Prev) {
    HcDev->AsyncRequestList = AsyncRequestPtr->Next;
    if (NULL != AsyncRequestPtr->Next) {
      AsyncRequestPtr->Next->Prev = NULL;
    }
  } else {
    AsyncRequestPtr->Prev->Next = AsyncRequestPtr->Next;
    if (NULL != AsyncRequestPtr->Next) {
      AsyncRequestPtr->Next->Prev = AsyncRequestPtr->Prev;
    }
  }

  return ;
}

VOID
SetQtdBufferPointer (
  IN EHCI_QTD_HW  *QtdHwPtr,
  IN VOID         *DataPtr,
  IN UINTN        DataLen
  )
/*++

Routine Description:

  Set data buffer pointers in Qtd

Arguments:

  QtdHwPtr  - A pointer to Qtd hardware structure
  DataPtr   - A pointer to user data buffer
  DataLen   - Length of the user data buffer

Returns:

  VOID

--*/
{
  UINTN     RemainLen;

  ASSERT (QtdHwPtr);
  ASSERT (DataLen <= 5 * EFI_PAGE_SIZE);

  RemainLen = DataLen;
  //
  // Allow buffer address range across 4G.
  // But EFI_USB_MAX_BULK_BUFFER_NUM = 1, so don't allow
  // seperate buffer array.
  //
  //
  // Set BufferPointer0, ExtBufferPointer0 and Offset
  //
  QtdHwPtr->BufferPointer0    = (UINT32) (GET_0B_TO_31B (DataPtr) >> EFI_PAGE_SHIFT);
  QtdHwPtr->CurrentOffset     = (UINT32) (GET_0B_TO_31B (DataPtr) & EFI_PAGE_MASK);

  //
  // Set BufferPointer1 and ExtBufferPointer1
  //
  RemainLen = RemainLen > (EFI_PAGE_SIZE - QtdHwPtr->CurrentOffset) ? (RemainLen - (EFI_PAGE_SIZE - QtdHwPtr->CurrentOffset)) : 0;
  if (RemainLen == 0) {
    goto exit;
  }

  QtdHwPtr->BufferPointer1    = QtdHwPtr->BufferPointer0 + 1;

  //
  // Set BufferPointer2 and ExtBufferPointer2
  //
  RemainLen = RemainLen > EFI_PAGE_SIZE ? (RemainLen - EFI_PAGE_SIZE) : 0;
  if (RemainLen == 0) {
    goto exit;
  }

  QtdHwPtr->BufferPointer2    = QtdHwPtr->BufferPointer1 + 1;

  //
  // Set BufferPointer3 and ExtBufferPointer3
  //
  RemainLen = RemainLen > EFI_PAGE_SIZE ? (RemainLen - EFI_PAGE_SIZE) : 0;
  if (RemainLen == 0) {
    goto exit;
  }

  QtdHwPtr->BufferPointer3    = QtdHwPtr->BufferPointer2 + 1;

  //
  // Set BufferPointer4 and ExtBufferPointer4
  //
  RemainLen = RemainLen > EFI_PAGE_SIZE ? (RemainLen - EFI_PAGE_SIZE) : 0;
  if (RemainLen == 0) {
    goto exit;
  }

  QtdHwPtr->BufferPointer4    = QtdHwPtr->BufferPointer3 + 1;

exit:
  return ;
}

BOOLEAN
IsQtdStatusActive (
  IN EHCI_QTD_HW  *HwQtdPtr
  )
/*++

Routine Description:

  Whether Qtd status is active or not

Arguments:

  HwQtdPtr - A pointer to hardware Qtd structure

Returns:

  TRUE    Active
  FALSE   Inactive

--*/
{
  UINT8   QtdStatus;
  BOOLEAN Value;

  QtdStatus = (UINT8) (HwQtdPtr->Status);
  Value     = (BOOLEAN) (QtdStatus & QTD_STATUS_ACTIVE);

  return Value;
}

BOOLEAN
IsQtdStatusHalted (
  IN EHCI_QTD_HW  *HwQtdPtr
  )
/*++

Routine Description:

  Whether Qtd status is halted or not

Arguments:

  HwQtdPtr - A pointer to hardware Qtd structure

Returns:

  TRUE    Halted
  FALSE   Not halted

--*/
{
  UINT8   QtdStatus;
  BOOLEAN Value;

  QtdStatus = (UINT8) (HwQtdPtr->Status);
  Value     = (BOOLEAN) (QtdStatus & QTD_STATUS_HALTED);

  return Value;

⌨️ 快捷键说明

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