⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 uhchlp.c

📁 Next BIOS Source code : Extensible Firmware Interface
💻 C
📖 第 1 页 / 共 5 页
字号:
SetCurFrameListQHorTD(
  IN  FRAMELIST_ENTRY    *pCurEntry,
  IN  BOOLEAN            IsQH
  )
{
  //
  // This bit indicates to the hardware whether the item referenced by the
  // link pointer is a TD or a QH.
  //
  pCurEntry-> FrameListPtrQSelect = (IsQH ? 1 : 0) ;
}


BOOLEAN
IsCurFrameListQHorTD(
  IN  FRAMELIST_ENTRY    *pCurEntry
  )  
{
  //
  //TRUE is QH
  //FALSE is TD
  //
  return (BOOLEAN)(pCurEntry->FrameListPtrQSelect);
}

BOOLEAN
GetCurFrameListTerminate(
  IN  FRAMELIST_ENTRY    *pCurEntry
  )
{
  //
  // TRUE means the frame is empty,
  // FALSE means the link pointer field is valid.
  //
  return (BOOLEAN)(pCurEntry->FrameListPtrTerminate) ;
}

VOID
SetCurFrameListPointer(
  IN  FRAMELIST_ENTRY   *pCurEntry,
  IN  UINT8             *ptr
  )
{
  //
  // Set the pointer field of the frame.
  //
  pCurEntry-> FrameListPtr = (UINT32)((UINTN)ptr >> 4);
}

VOID*
GetCurFrameListPointer(
  IN  FRAMELIST_ENTRY    *pCurEntry
  )
{
  VOID     *ptr ;
  //
  // Get the link pointer of the frame.
  //
  ptr = (VOID*)((UINTN)(pCurEntry-> FrameListPtr << 4));
  return ptr;
}

VOID
LinkQHToFrameList(
  IN  FRAMELIST_ENTRY   *pEntry,
  IN  UINT16            FrameListIndex,
  IN  QH_STRUCT         *ptrQH
  ) 
{
  FRAMELIST_ENTRY     *pCurFrame ;
  QH_STRUCT           *TempQH;
  QH_STRUCT           *NextTempQH;
  TD_STRUCT           *TempTD;
  BOOLEAN             LINK;
  
  //
  // Get frame list entry that the link process will begin from.
  //
  pCurFrame = pEntry + FrameListIndex ; 

  //
  // if current frame is empty 
  // then link the specified QH directly to the Frame List.
  // 
  if (GetCurFrameListTerminate (pCurFrame)) {  
    
    //
    // Link new QH to the frame list entry.
    //
    SetCurFrameListQHorTD (pCurFrame, TRUE) ;
    
    SetCurFrameListPointer (pCurFrame, (UINT8 *)ptrQH) ;
    
    //
    // clear T bit in the Frame List, indicating that the frame list entry 
    // is no longer empty.
    //
    SetorClearCurFrameListTerminate(pCurFrame, FALSE) ;
    
    return;
    
  } else {        
    //
    // current frame list has link pointer
    //
    if (!IsCurFrameListQHorTD (pCurFrame)) {
    //  
    //  a TD is linked to the framelist entry
    //
      TempTD = (TD_STRUCT*)GetCurFrameListPointer (pCurFrame);
      
      while (GetTDLinkPtrValidorInvalid (TempTD)) {
        
        if (IsTDLinkPtrQHOrTD (TempTD)) { // QH linked next to the TD
          break;
        }
        
        TempTD = (TD_STRUCT*)GetTDLinkPtr (TempTD);
      }
      
      //
      // either no ptr linked next to the TD or QH is linked next to the TD
      //
      if (!GetTDLinkPtrValidorInvalid (TempTD)) {
        
        //
        // no ptr linked next to the TD
        //
        TempTD->ptrNextQH = ptrQH;        
        SetTDLinkPtrQHorTDSelect (TempTD,TRUE);
        SetTDLinkPtr (TempTD,ptrQH);
        SetTDLinkPtrValidorInvalid(TempTD,TRUE) ;
        //ptrQH->ptrNext = NULL; 
        
        return;
        
      } else {
        //
        //  QH is linked next to the TD
        //
        TempQH = (QH_STRUCT*)GetTDLinkPtr (TempTD) ;
      }
    
    } else {  
    //
    // a QH is linked to the framelist entry
    //
      TempQH = (QH_STRUCT*)GetCurFrameListPointer(pCurFrame) ;
    }
    
    //
    // Set up Flag
    //
    LINK = TRUE;
    
    //
    // avoid the same qh repeated linking in one frame entry
    //
    if (TempQH == ptrQH) {
      LINK = FALSE;
    }
    //
    // if current QH has next QH connected
    //
    while (GetQHHorizontalValidorInvalid (TempQH)) { 

      //
      // Get next QH pointer
      //
      NextTempQH = (QH_STRUCT*)GetQHHorizontalLinkPtr (TempQH);
      
      //
      // Bulk transfer qh may be self-linked,
      // so, the code below is to avoid dead-loop when meeting self-linked qh
      //
      if (NextTempQH == TempQH) {
        LINK = FALSE;
        break;
      }
      
      TempQH = NextTempQH;
      
      //
      // avoid the same qh repeated linking in one frame entry
      //
      if (TempQH == ptrQH) {
        LINK = FALSE;
      }
    }
     
    if (LINK) {
       // Link
      TempQH->ptrNext = ptrQH;
      SetQHHorizontalQHorTDSelect(TempQH,TRUE) ;
      SetQHHorizontalLinkPtr(TempQH,ptrQH) ;
      SetQHHorizontalValidorInvalid(TempQH,TRUE) ;
      //ptrQH->ptrNext = NULL;
    }   
    
    return;
      
  }

}

EFI_STATUS
ExecuteControlTransfer (
  IN  USB_HC_DEV  *HcDev,
  IN  TD_STRUCT   *ptrTD,
  IN  UINT32      wIndex,
  OUT UINTN       *ActualLen,
  IN  UINTN       TimeOut,
  OUT UINT32      *TransferResult
  )
{
  UINTN               ErrTDPos;
  UINTN               Delay;
  
  ErrTDPos          = 0 ;
  *TransferResult   = EFI_USB_NOERROR;  
  *ActualLen        = 0;
  
  Delay = (TimeOut * STALL_1_MILLI_SECOND / 50) + 1;
        
  do {
      
    CheckTDsResults(ptrTD,TransferResult,&ErrTDPos,ActualLen);
    
    //
    // TD is inactive, means the control transfer is end.
    //
    if ((*TransferResult & EFI_USB_ERR_NOTEXECUTE) != EFI_USB_ERR_NOTEXECUTE) {
      break;
    }
    gBS->Stall(50);
      
  } while(Delay--);
    
    
  if(*TransferResult != EFI_USB_NOERROR) {
    return EFI_DEVICE_ERROR;
  }
    
  return EFI_SUCCESS;
}    


EFI_STATUS
ExecBulkorSyncInterruptTransfer (
  IN  USB_HC_DEV  *HcDev,
  IN  TD_STRUCT   *ptrTD,
  IN  UINT32      wIndex,
  OUT UINTN       *ActualLen,
  OUT UINT8       *DataToggle,
  IN  UINTN       TimeOut,
  OUT UINT32      *TransferResult
  )
{
  UINTN               ErrTDPos;
  UINTN               ScrollNum;
  UINTN               Delay;

  ErrTDPos          = 0;
  *TransferResult   = EFI_USB_NOERROR;
  *ActualLen        = 0;

  Delay = (TimeOut * STALL_1_MILLI_SECOND / 50) + 1;
    
  do {

    CheckTDsResults (ptrTD,TransferResult,&ErrTDPos,ActualLen);
    //
    // TD is inactive, thus meaning bulk transfer's end.
    //    
    if ((*TransferResult & EFI_USB_ERR_NOTEXECUTE) != EFI_USB_ERR_NOTEXECUTE) {
      break;
    }  
    gBS->Stall(50);   // Stall for 50 us

  } while (Delay--);
  
  //
  // has error
  //
  if(*TransferResult != EFI_USB_NOERROR) {
  
    //
    // scroll the Data Toggle back to the last success TD
    //
    ScrollNum = CountTDsNumber(ptrTD) - ErrTDPos;
    if(ScrollNum % 2) {
      *DataToggle ^= 1 ;
    }
    
    return EFI_DEVICE_ERROR ;
  }

  return EFI_SUCCESS;
} 

VOID
DelLinkSingleQH (
  IN  USB_HC_DEV      *HcDev,
  IN  QH_STRUCT       *ptrQH,
  IN  UINT16          FrameListIndex,
  IN  BOOLEAN         SearchOther,
  IN  BOOLEAN         Delete
  )
{
  FRAMELIST_ENTRY   *pCurFrame;
  UINTN             i;
  UINTN             BeginFrame;
  UINTN             EndFrame;
  QH_STRUCT         *CurrentQH;
  QH_STRUCT         *NextQH;
  QH_STRUCT         *LastLoopQH;
  TD_STRUCT         *CurrentTD;
  VOID              *PtrPreQH;
  BOOLEAN           Found;
  
  NextQH    = NULL;
  PtrPreQH  = NULL;
  Found     = FALSE;
  
  if (ptrQH == NULL) {
    return;
  }
  
  if (SearchOther) {
    BeginFrame = 0;
    EndFrame = 1024;
  } else {
    BeginFrame = FrameListIndex;
    EndFrame = FrameListIndex + 1;
  }
  
  for ( i = BeginFrame; i < EndFrame; i ++) {
    
    pCurFrame = HcDev->FrameListEntry + (i % 1024);
    
    if (GetCurFrameListTerminate (pCurFrame)) {
      //
      // current frame list is empty,search next frame list entry
      //
      continue;
    }
    
    if (!IsCurFrameListQHorTD (pCurFrame)) {  
    //
    // TD linked to current framelist
    //  
      CurrentTD = (TD_STRUCT*)GetCurFrameListPointer (pCurFrame);
      
      while (GetTDLinkPtrValidorInvalid (CurrentTD)) {
        
        if (IsTDLinkPtrQHOrTD (CurrentTD)) { 
        //
        // QH linked next to the TD,break while()
        //
          break;
        }
        
        CurrentTD = (TD_STRUCT*)GetTDLinkPtr (CurrentTD);
      }
      
      if (!GetTDLinkPtrValidorInvalid (CurrentTD)) {
      //
      // no QH linked next to the last TD,
      // search next frame list
      //
        continue;
      }
      
      //
      // a QH linked next to the last TD
      //
      CurrentQH = (QH_STRUCT*)GetTDLinkPtr (CurrentTD);
      
      PtrPreQH = CurrentTD;
    
    } else {  
    //
    // a QH linked to current framelist
    //      
      CurrentQH = (QH_STRUCT*)GetCurFrameListPointer (pCurFrame);
      
      PtrPreQH = NULL;
    }
    
    if (CurrentQH == ptrQH) {
      
      //
      // tell whether CurrentQH is in QH loop and is one of the ends of the 
      // loop,
      // if yes, break the QH loop.
      //
      if (IsQHsLooped (CurrentQH,&LastLoopQH)) {
        
        if ((CurrentQH == LastLoopQH) || (CurrentQH == LastLoopQH->LoopPtr)) {
        
          LastLoopQH->LoopPtr = NULL;
          SetQHHorizontalValidorInvalid(LastLoopQH,FALSE);
          SetQHHorizontalLinkPtr(LastLoopQH,NULL);
          LastLoopQH->ptrNext = NULL;
        }
      }
      
      if(GetQHHorizontalValidorInvalid (ptrQH)) {
      //
      // there is QH connected after the QH found
      //
        //
        // retrieve nex qh pointer of the qh found.
        //
        NextQH = GetQHHorizontalLinkPtr (ptrQH);
      } else {
        NextQH = NULL;
      }
      
      if (PtrPreQH) {  // QH linked to a TD struct
        
        CurrentTD = (TD_STRUCT*)PtrPreQH;
                
        SetTDLinkPtrValidorInvalid (CurrentTD,(BOOLEAN)((NextQH == NULL) ? FALSE : TRUE));
        SetTDLinkPtr (CurrentTD,NextQH);
        CurrentTD->ptrNextQH = NextQH;
        
      } else {  // QH linked directly to current framelist entry
        
        SetorClearCurFrameListTerminate (pCurFrame,(BOOLEAN)((NextQH == NULL) ? TRUE : FALSE));
        SetCurFrameListPointer (pCurFrame,(UINT8*)NextQH);
      }
      
      Found = TRUE;
      //
      // search next framelist entry
      //
      continue;
    }
    
    //
    // retrieve the Last QH in the Loop,
    // if no Loop, LastLoopQH = NULL
    //
    IsQHsLooped (CurrentQH,&LastLoopQH);
    
    while (CurrentQH != LastLoopQH) {
      
      PtrPreQH = CurrentQH;
      //
      // Get next horizontal linked QH
      //
      CurrentQH = (QH_STRUCT*)GetQHHorizontalLinkPtr (CurrentQH);
      
      //
      // the qh is found
      //
      if (CurrentQH == ptrQH) {
        break;
      }
    }
    
    if (CurrentQH != ptrQH) {
      //
      // search next frame list entry
      //
      continue;
    }   
    
    // 
    // find the specified qh, then delink it from
    // the horizontal QH list in the frame entry.
    //
    
    if (LastLoopQH != NULL) {
      //
      // break the qh loop 
      // if exists and the specified qh is one of the ends of the loop 
      //
      if ((CurrentQH == LastLoopQH) || (CurrentQH == LastLoopQH->LoopPtr)) {
        LastLoopQH->LoopPtr = NULL;
        SetQHHorizontalValidorInvalid(LastLoopQH,FALSE);
        SetQHHorizontalLinkPtr(LastLoopQH,NULL);
        LastLoopQH->ptrNext = NULL;
      }
    }
    
    if(GetQHHorizontalValidorInvalid (ptrQH)) {
    //
    // there is QH connected after the QH found
    //
      //
      // retrieve nex qh pointer of the qh found.
      //
      NextQH = GetQHHorizontalLinkPtr (ptrQH);

    } else {
    //
    // NO QH connected after the QH found
    //
      NextQH = NULL;
      //
      // NULL the previous QH's link ptr and set Terminate field.
      //
      SetQHHorizontalValidorInvalid((QH_STRUCT*)PtrPreQH,FALSE);
    }
    
    SetQHHorizontalLinkPtr((QH_STRUCT*)PtrPreQH,NextQH);
    ((QH_STRUCT*)PtrPreQH)->ptrNext = NextQH;

    Found = TRUE;
  }
  
  if (Found && Delete) {
    //
    // free memory once used by the specific QH
    //
    UhciFreePool(HcDev,(UINT8*)ptrQH,sizeof(QH_STRUCT));
  }

  return;
}


VOID
DeleteQueuedTDs(
  IN  USB_HC_DEV      *HcDev,
  IN  TD_STRUCT       *ptrFirstTD
  )
/*
  The last TD in the queue may be linked to itself.
  Must take this condition into account.
*/
{
  TD_STRUCT         *Tptr1;
  TD_STRUCT         *Tptr2;
  
  Tptr1 = ptrFirstTD;
  //
  // Delete all the TDs in a queue.
  //  
  while(Tptr1) {
    
    Tptr2 = Tptr1;
    
    if(!GetTDLinkPtrValidorInvalid (Tptr2)) {
      Tptr1 = NULL ;
    } else  {
      
      Tptr1 = GetTDLinkPtr(Tptr2);
      
      //
      // TD link to itself
      //
      if (Tptr1 == Tptr2) {
        Tptr1 = NULL;
      }
    }

    UhciFreePool(HcDev,(UINT8*)Tptr2,sizeof(TD_STRUCT));
  }

  return;
}    


VOID
InsertQHTDToINTList(
  IN  USB_HC_DEV                      *HcDev,
  IN  QH_STRUCT                       *ptrQH,
  IN  TD_STRUCT                       *ptrFirstTD,
  IN  UINT8                           DeviceAddress,
  IN  UINT8                           EndPointAddress,
  IN  UINT8                           DataToggle,
  IN  UINTN                           DataLength,
  IN  UINTN                           PollingInterval,
  IN  VOID                            *Mapping,
  IN  UINT8                           *DataBuffer,
  IN  EFI_ASYNC_USB_TRANSFER_CALLBACK CallBackFunction,
  IN  VOID                            *Context
  )
{
  EFI_STATUS        Status;
  INTERRUPT_LIST    *Node ;

  Status = gBS->AllocatePool (EfiBootServicesData,sizeof(INTERRUPT_LIST),&Node);
  if(EFI_ERROR(Status)) {
    return;
  }   
  
  //
  // Fill Node field
  //
  Node->Signature         = INTERRUPT_LIST_SIGNATURE;
  Node->DevAddr           = DeviceAddress;
  Node->EndPoint          = EndPointAddress;
  Node->ptrQH             = ptrQH;
  Node->ptrFirstTD        = ptrFirstTD;
  Node->DataToggle        = DataToggle ;
  Node->DataLen           = DataLength;
  Node->PollInterval      = PollingInterval;
  Node->Mapping           = Mapping;

⌨️ 快捷键说明

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