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

📄 uhchlp.c

📁 Next BIOS Source code : Extensible Firmware Interface
💻 C
📖 第 1 页 / 共 5 页
字号:
  }

  return;
}

VOID
SelfLinkBulkTransferQH (
  IN  QH_STRUCT *ptrQH
  )
{
  if (ptrQH == NULL) {
    return;
  }
  
  //
  // Make the QH's horizontal link pointer pointing to itself.
  //
  ptrQH->ptrNext = ptrQH;
  SetQHHorizontalQHorTDSelect(ptrQH,TRUE);
  SetQHHorizontalLinkPtr(ptrQH,ptrQH);
  SetQHHorizontalValidorInvalid(ptrQH,TRUE);
  
  return;
}    

EFI_STATUS
CreateFrameList (
  USB_HC_DEV                *HcDev,
  UINT32                    FlBaseAddrReg
  )
{
  EFI_STATUS              Status ;
  VOID                    *CommonBuffer;
  EFI_PHYSICAL_ADDRESS    MappedAddress;
  VOID                    *Mapping;
  UINTN                   BufferSizeInPages;
  UINTN                   BufferSizeInBytes;
  
  //
  // 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.
  //
  BufferSizeInBytes = 4096;
  BufferSizeInPages = EFI_SIZE_TO_PAGES(BufferSizeInBytes);
  Status = HcDev->PciIo->AllocateBuffer (HcDev->PciIo,
                                         AllocateAnyPages,
                                         EfiBootServicesData,
                                         BufferSizeInPages,
                                         &CommonBuffer,
                                         0
                                         );
  if(EFI_ERROR(Status)) {
    return EFI_OUT_OF_RESOURCES;
  }
  
  Status = HcDev->PciIo->Map (HcDev->PciIo,
                              EfiPciIoOperationBusMasterCommonBuffer,
                              CommonBuffer,
                              &BufferSizeInBytes,
                              &MappedAddress,
                              &Mapping
                              );
  if (EFI_ERROR(Status) || (BufferSizeInBytes != 4096)) {
    HcDev->PciIo->FreeBuffer (HcDev->PciIo,BufferSizeInPages,CommonBuffer);
    return EFI_UNSUPPORTED;
  }
  
  HcDev->FrameListEntry = (FRAMELIST_ENTRY*)((UINTN)MappedAddress);
  
  HcDev->FrameListMapping = Mapping;

  InitFrameList (HcDev);
  
  //
  // Tell the Host Controller where the Frame List lies,
  // by set the Frame List Base Address Register.
  //  
  SetFrameListBaseAddress(
    HcDev->PciIo,
    FlBaseAddrReg,
    (UINT32)((UINTN)HcDev->FrameListEntry)
  );


  return EFI_SUCCESS;
}

EFI_STATUS
FreeFrameListEntry(
  USB_HC_DEV        *HcDev
  )
{
  //
  // Unmap the common buffer for framelist entry,
  // and free the common buffer.
  // Uhci's frame list occupy 4k memory.
  //
  HcDev->PciIo->Unmap (HcDev->PciIo,HcDev->FrameListMapping);
  HcDev->PciIo->FreeBuffer (
                      HcDev->PciIo,
                      EFI_SIZE_TO_PAGES(4096),
                      (VOID*)(HcDev->FrameListEntry)
                      );
  return EFI_SUCCESS;
}    

VOID
InitFrameList (
  USB_HC_DEV    *HcDev
  )
{
  FRAMELIST_ENTRY     *FrameListPtr;
  UINTN               Index;
  
  //
  // Validate each Frame List Entry
  //
  FrameListPtr = HcDev->FrameListEntry;
  for(Index = 0 ; Index < 1024 ; Index ++) {
    FrameListPtr->FrameListPtrTerminate = 1 ;
    FrameListPtr->FrameListPtr = 0;
    FrameListPtr->FrameListPtrQSelect = 0;
    FrameListPtr->FrameListRsvd = 0;
    FrameListPtr++;
  }
}

////////////////////////////////////////////////////////////////
//
// QH TD related Helper Functions
//
////////////////////////////////////////////////////////////////

//
// functions for QH
//

EFI_STATUS
AllocateQHStruct(
  USB_HC_DEV            *HcDev,
  OUT QH_STRUCT         **ppQHStruct
)
{
  EFI_STATUS  Status;
  
  *ppQHStruct = NULL;
  
  //
  // QH must align on 16 bytes alignment,
  // since the memory allocated by UhciAllocatePool ()
  // is aligned on 32 bytes, it is no need to adjust
  // the allocated memory returned.
  //
  Status = UhciAllocatePool (HcDev,(UINT8**)ppQHStruct,sizeof(QH_STRUCT));
   
  if(EFI_ERROR(Status)) {
    return Status;
  }    
  
  EfiZeroMem(*ppQHStruct, sizeof(QH_STRUCT));
  
  return EFI_SUCCESS;
}

VOID
InitQH(
  IN  QH_STRUCT *ptrQH
)
{
  //
  // Make QH ready
  //
  SetQHHorizontalValidorInvalid(ptrQH, FALSE);
  SetQHVerticalValidorInvalid(ptrQH, FALSE);
  ptrQH->LoopPtr = NULL;
}

EFI_STATUS
CreateQH(
  USB_HC_DEV          *HcDev,
  QH_STRUCT           **pptrQH
  )
{
  EFI_STATUS    Status;

  //
  // allocate align memory for QH_STRUCT
  //
  Status = AllocateQHStruct(HcDev,pptrQH) ;
  if(EFI_ERROR(Status)) {
    return EFI_OUT_OF_RESOURCES ;
  }

  //
  // init each field of the QH_STRUCT
  //
  InitQH(*pptrQH) ;

  return EFI_SUCCESS ;
}

void
SetQHHorizontalLinkPtr(
  IN QH_STRUCT  *ptrQH,
  IN VOID       *ptrNext
)
{
  //
  // Since the QH_STRUCT is aligned on 16-byte boundaries,
  // Only the highest 28bit of the address is valid 
  // (take 32bit address as an example).
  //
  ptrQH->QH.QHHorizontalPtr = (UINT32)((UINTN)ptrNext >> 4);
}

VOID*
GetQHHorizontalLinkPtr(
  IN QH_STRUCT  *ptrQH
)
{
  //
  // Restore the 28bit address to 32bit address 
  //(take 32bit address as an example)
  //
  return ((VOID*)((UINTN)(ptrQH->QH.QHHorizontalPtr << 4)));
}

VOID
SetQHHorizontalQHorTDSelect(
  IN QH_STRUCT  *ptrQH,
  IN BOOLEAN    bQH
)
{
  //
  // if QH is connected, the specified bit is set,
  // if TD is connected, the specified bit is cleared.
  //
  ptrQH->QH.QHHorizontalQSelect = bQH ? 1 : 0;
}


VOID
SetQHHorizontalValidorInvalid(
  IN QH_STRUCT  *ptrQH,
  IN BOOLEAN    bValid
)
{
  //
  // Valid means the horizontal link pointer is valid,
  // else, it's invalid.
  //
  ptrQH->QH.QHHorizontalTerminate = bValid ? 0 : 1;
}

VOID
SetQHVerticalLinkPtr(
  IN QH_STRUCT  *ptrQH,
  IN VOID     *ptrNext
)
{
  //
  // Since the QH_STRUCT is aligned on 16-byte boundaries,
  // Only the highest 28bit of the address is valid 
  // (take 32bit address as an example).
  //
  ptrQH->QH.QHVerticalPtr = (UINT32)((UINTN)ptrNext >> 4);
}

VOID*
GetQHVerticalLinkPtr(
  IN QH_STRUCT  *ptrQH
)
{
  //
  // Restore the 28bit address to 32bit address 
  //(take 32bit address as an example)
  //
  return ((VOID*)((UINTN)(ptrQH->QH.QHVerticalPtr << 4)));
}

VOID
SetQHVerticalQHorTDSelect(
  IN QH_STRUCT  *ptrQH,
  IN BOOLEAN    bQH
)
{
  //
  // Set the specified bit if the Vertical Link Pointer pointing to a QH,
  // Clear the specified bit if the Vertical Link Pointer pointing to a TD.
  //
  ptrQH->QH.QHVerticalQSelect = bQH ? 1 : 0;
}

BOOLEAN
IsQHHorizontalQHSelect(
  IN QH_STRUCT  *ptrQH
)
{
  //
  // Retrieve the information about whether the Horizontal Link Pointer
  // pointing to a QH or TD.
  //
  return (BOOLEAN)(ptrQH->QH.QHHorizontalQSelect? TRUE : FALSE);
}

VOID
SetQHVerticalValidorInvalid(
  IN QH_STRUCT  *ptrQH,
  IN BOOLEAN    IsValid
)
{
  //
  // If TRUE, indicates the Vertical Link Pointer field is valid,
  // else, the field is invalid.
  //
  ptrQH->QH.QHVerticalTerminate = IsValid ? 0 : 1;
}


BOOLEAN
GetQHVerticalValidorInvalid(
  IN QH_STRUCT  *ptrQH
)
{
  //
  // If TRUE, indicates the Vertical Link Pointer field is valid,
  // else, the field is invalid.
  //
  return (BOOLEAN)(!(ptrQH->QH.QHVerticalTerminate));
}

BOOLEAN
GetQHHorizontalValidorInvalid(
  IN QH_STRUCT  *ptrQH
)
{
  //
  // If TRUE, meaning the Horizontal Link Pointer field is valid,
  // else, the field is invalid.
  //
  return (BOOLEAN)(!(ptrQH->QH.QHHorizontalTerminate));
}

//
// functions for TD
//
EFI_STATUS
AllocateTDStruct(
  USB_HC_DEV        *HcDev,
  TD_STRUCT         **ppTDStruct
  )
{
  EFI_STATUS  Status;
  
  *ppTDStruct = NULL;
  
  //
  // TD must align on 16 bytes alignment,
  // since the memory allocated by UhciAllocatePool ()
  // is aligned on 32 bytes, it is no need to adjust
  // the allocated memory returned.
  //
  Status = UhciAllocatePool (HcDev,
                           (UINT8**)ppTDStruct,
                           sizeof(TD_STRUCT)
                           );   
  if(EFI_ERROR(Status)) {
    return Status;
  }
  
  EfiZeroMem(*ppTDStruct, sizeof (TD_STRUCT));
  
  return EFI_SUCCESS;
}

VOID
InitTD(
  IN  TD_STRUCT *ptrTD
)
{
  //
  // Make TD ready.
  //
  SetTDLinkPtrValidorInvalid(ptrTD, FALSE);
}

EFI_STATUS
CreateTD(
  USB_HC_DEV      *HcDev,
  TD_STRUCT       **pptrTD
  )
{
  EFI_STATUS      Status;
  //
  // create memory for TD_STRUCT, and align the memory.
  //
  Status = AllocateTDStruct(HcDev,pptrTD) ;
  if(EFI_ERROR(Status)) {
    return EFI_OUT_OF_RESOURCES;
  }

  InitTD(*pptrTD);

  return EFI_SUCCESS ;
}

EFI_STATUS
GenSetupStageTD(
  IN  USB_HC_DEV          *HcDev,
  IN  UINT8               DevAddr,
  IN  UINT8               Endpoint,
  IN  BOOLEAN             bSlow,
  IN  UINT8               *pDevReq,
  IN  UINT8               RequestLen,
  OUT TD_STRUCT           **ppTD
)
{
  EFI_STATUS      Status;
  TD_STRUCT       *pTDStruct;

  Status = CreateTD(HcDev,&pTDStruct);
  if(EFI_ERROR(Status)) {
    return EFI_OUT_OF_RESOURCES;
  }

  SetTDLinkPtr(pTDStruct,NULL);

  //
  // Depth first fashion
  //
  SetTDLinkPtrDepthorBreadth(pTDStruct, TRUE);

  //SetTDLinkPtrQHorTDSelect(pTDStruct,FALSE) ;

  //
  // initialize as the last TD in the QH context,
  // this field will be updated in the TD linkage process.
  //
  SetTDLinkPtrValidorInvalid(pTDStruct, FALSE);
  
  //
  // Disable Short Packet Detection by default
  //
  EnableorDisableTDShortPacket (pTDStruct, FALSE) ;

  //
  // Max error counter is 3, retry 3 times when error encountered.
  //
  SetTDControlErrorCounter(pTDStruct, 3);

  //
  // set device speed attribute 
  // (TRUE - Slow Device; FALSE - Full Speed Device)
  //
  SetTDLoworFullSpeedDevice (pTDStruct, bSlow);

  //
  // Non isochronous transfer TD
  //
  SetTDControlIsochronousorNot(pTDStruct,FALSE) ;

  //
  // Interrupt On Complete bit be set to zero,
  // Disable IOC interrupt.
  //
  SetorClearTDControlIOC(pTDStruct,FALSE) ;

  //
  // Set TD Active bit
  //
  SetTDStatusActiveorInactive(pTDStruct, TRUE);
  
  SetTDTokenMaxLength(pTDStruct, RequestLen) ;
  
  SetTDTokenDataToggle0(pTDStruct);

  SetTDTokenEndPoint(pTDStruct, Endpoint);

  SetTDTokenDeviceAddress (pTDStruct, DevAddr);

  SetTDTokenPacketID(pTDStruct, SETUP_PACKET_ID);
  
  pTDStruct->pTDBuffer = (UINT8*)pDevReq;
  pTDStruct->TDBufferLength = RequestLen;
  SetTDDataBuffer(pTDStruct);

  *ppTD = pTDStruct;

  return EFI_SUCCESS;
}

EFI_STATUS
GenDataTD(
  IN  USB_HC_DEV          *HcDev,
  IN  UINT8               DevAddr,
  IN  UINT8               Endpoint,
  IN  UINT8               *pData,
  IN  UINT8               Len,
  IN  UINT8               PktID,
  IN  UINT8               Toggle,
  IN  BOOLEAN             bSlow,
  OUT TD_STRUCT           **ppTD
  )
{
  TD_STRUCT   *pTDStruct;
  EFI_STATUS  Status;

  Status = CreateTD(HcDev,&pTDStruct);
  if(EFI_ERROR(Status)) {
    return EFI_OUT_OF_RESOURCES;
  }

  SetTDLinkPtr(pTDStruct,NULL) ;

  //
  // Depth first fashion
  //
  SetTDLinkPtrDepthorBreadth(pTDStruct,TRUE);

  //
  // Link pointer pointing to TD struct
  //
  SetTDLinkPtrQHorTDSelect(pTDStruct,FALSE);

  //
  // initialize as the last TD in the QH context,
  // this field will be updated in the TD linkage process.
  //
  SetTDLinkPtrValidorInvalid(pTDStruct, FALSE);

  //
  // Disable short packet detect
  //
  EnableorDisableTDShortPacket (pTDStruct, FALSE) ;
  //
  // Max error counter is 3
  //
  SetTDControlErrorCounter(pTDStruct, 3);

  //
  // set device speed attribute
  // (TRUE - Slow Device; FALSE - Full Speed Device)
  //
  SetTDLoworFullSpeedDevice (pTDStruct, bSlow);

  //
  // Non isochronous transfer TD
  //
  SetTDControlIsochronousorNot(pTDStruct,FALSE) ;

  //
  // Disable Interrupt On Complete
  // Disable IOC interrupt.
  //
  SetorClearTDControlIOC(pTDStruct,FALSE) ;

  //
  // Set Active bit
  //
  SetTDStatusActiveorInactive(pTDStruct, TRUE);
  
  SetTDTokenMaxLength(pTDStruct, Len) ;
  
  if(Toggle) {
    SetTDTokenDataToggle1(pTDStruct);
  } else {
    SetTDTokenDataToggle0(pTDStruct);
  }
  
  SetTDTokenEndPoint(pTDStruct, Endpoint);

  SetTDTokenDeviceAddress(pTDStruct, DevAddr);

  SetTDTokenPacketID(pTDStruct, PktID);
  
  pTDStruct->pTDBuffer = (UINT8*)pData;
  pTDStruct->TDBufferLength = Len;
  SetTDDataBuffer(pTDStruct);
  *ppTD = pTDStruct;

  return EFI_SUCCESS;
}


EFI_STATUS
CreateStatusTD(
  IN  USB_HC_DEV          *HcDev,
  IN  UINT8               DevAddr,
  IN  UINT8               Endpoint,
  IN  UINT8               PktID,
  IN  BOOLEAN             bSlow,
  OUT TD_STRUCT           **ppTD
)
{
  TD_STRUCT   *ptrTDStruct;
  EFI_STATUS  Status;

  Status = CreateTD(HcDev,&ptrTDStruct);
  if(EFI_ERROR(Status)) {

⌨️ 快捷键说明

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