\r
EHCI transfer scheduling routines.\r
\r
-Copyright (c) 2007 - 2009, Intel Corporation\r
+Copyright (c) 2007 - 2010, Intel Corporation\r
All rights reserved. This program and the accompanying materials\r
are licensed and made available under the terms and conditions of the BSD License\r
which accompanies this distribution. The full text of the license may be found at\r
QhHw->HorizonLink = QH_LINK (PciAddr + OFFSET_OF(EHC_QH, QhHw), EHC_TYPE_QH, FALSE);\r
QhHw->Status = QTD_STAT_HALTED;\r
QhHw->ReclaimHead = 1;\r
+ Qh->NextQh = Qh;\r
Ehc->ReclaimHead = Qh;\r
\r
//\r
UINTN Pages;\r
UINTN Bytes;\r
UINTN Index;\r
- UINT32 *Desc;\r
EFI_STATUS Status;\r
EFI_PHYSICAL_ADDRESS PciAddr;\r
\r
return EFI_OUT_OF_RESOURCES;\r
}\r
\r
- Ehc->PeriodFrameHost = Buf;\r
- Ehc->PeriodFrame = (VOID *) ((UINTN) PhyAddr);\r
+ Ehc->PeriodFrame = Buf;\r
Ehc->PeriodFrameMap = Map;\r
- Ehc->High32bitAddr = EHC_HIGH_32BIT (PhyAddr);\r
+\r
+ //\r
+ // Program the FRAMELISTBASE register with the low 32 bit addr\r
+ //\r
+ EhcWriteOpReg (Ehc, EHC_FRAME_BASE_OFFSET, EHC_LOW_32BIT (PhyAddr));\r
+ //\r
+ // Program the CTRLDSSEGMENT register with the high 32 bit addr\r
+ //\r
+ EhcWriteOpReg (Ehc, EHC_CTRLDSSEG_OFFSET, EHC_HIGH_32BIT (PhyAddr));\r
\r
//\r
// Init memory pool management then create the helper\r
Ehc->MemPool = UsbHcInitMemPool (\r
PciIo,\r
EHC_BIT_IS_SET (Ehc->HcCapParams, HCCP_64BIT),\r
- Ehc->High32bitAddr\r
+ EHC_HIGH_32BIT (PhyAddr)\r
);\r
\r
if (Ehc->MemPool == NULL) {\r
- return EFI_OUT_OF_RESOURCES;\r
+ Status = EFI_OUT_OF_RESOURCES;\r
+ goto ErrorExit1;\r
}\r
\r
Status = EhcCreateHelpQ (Ehc);\r
\r
if (EFI_ERROR (Status)) {\r
- return Status;\r
+ goto ErrorExit;\r
}\r
\r
//\r
// Initialize the frame list entries then set the registers\r
//\r
- Desc = (UINT32 *) Ehc->PeriodFrameHost;\r
+ Ehc->PeriodFrameHost = AllocateZeroPool (EHC_FRAME_LEN * sizeof (UINTN));\r
+ if (Ehc->PeriodFrameHost == NULL) {\r
+ Status = EFI_OUT_OF_RESOURCES;\r
+ goto ErrorExit;\r
+ }\r
+\r
+ PciAddr = UsbHcGetPciAddressForHostMem (Ehc->MemPool, Ehc->PeriodOne, sizeof (EHC_QH));\r
\r
for (Index = 0; Index < EHC_FRAME_LEN; Index++) {\r
- PciAddr = UsbHcGetPciAddressForHostMem (Ehc->MemPool, Ehc->PeriodOne, sizeof (EHC_QH));\r
- Desc[Index] = QH_LINK (PciAddr, EHC_TYPE_QH, FALSE);\r
+ //\r
+ // Store the pci bus address of the QH in period frame list which will be accessed by pci bus master.\r
+ //\r
+ ((UINT32 *)(Ehc->PeriodFrame))[Index] = QH_LINK (PciAddr, EHC_TYPE_QH, FALSE);\r
+ //\r
+ // Store the host address of the QH in period frame list which will be accessed by host.\r
+ //\r
+ ((UINTN *)(Ehc->PeriodFrameHost))[Index] = (UINTN)Ehc->PeriodOne;\r
}\r
\r
- EhcWriteOpReg (Ehc, EHC_FRAME_BASE_OFFSET, EHC_LOW_32BIT (Ehc->PeriodFrame));\r
-\r
//\r
// Second initialize the asynchronous schedule:\r
// Only need to set the AsynListAddr register to\r
PciAddr = UsbHcGetPciAddressForHostMem (Ehc->MemPool, Ehc->ReclaimHead, sizeof (EHC_QH));\r
EhcWriteOpReg (Ehc, EHC_ASYNC_HEAD_OFFSET, EHC_LOW_32BIT (PciAddr));\r
return EFI_SUCCESS;\r
+\r
+ErrorExit:\r
+ if (Ehc->PeriodOne != NULL) {\r
+ UsbHcFreeMem (Ehc->MemPool, Ehc->PeriodOne, sizeof (EHC_QH));\r
+ Ehc->PeriodOne = NULL;\r
+ }\r
+\r
+ if (Ehc->ReclaimHead != NULL) {\r
+ UsbHcFreeMem (Ehc->MemPool, Ehc->ReclaimHead, sizeof (EHC_QH));\r
+ Ehc->ReclaimHead = NULL;\r
+ }\r
+\r
+ if (Ehc->ShortReadStop != NULL) {\r
+ UsbHcFreeMem (Ehc->MemPool, Ehc->ShortReadStop, sizeof (EHC_QTD));\r
+ Ehc->ShortReadStop = NULL;\r
+ }\r
+\r
+ErrorExit1:\r
+ PciIo->FreeBuffer (PciIo, Pages, Buf);\r
+ PciIo->Unmap (PciIo, Map);\r
+\r
+ return Status;\r
}\r
\r
\r
Ehc->MemPool = NULL;\r
}\r
\r
- if (Ehc->PeriodFrameHost != NULL) {\r
+ if (Ehc->PeriodFrame != NULL) {\r
PciIo = Ehc->PciIo;\r
ASSERT (PciIo != NULL);\r
\r
PciIo->FreeBuffer (\r
PciIo,\r
EFI_SIZE_TO_PAGES (EFI_PAGE_SIZE),\r
- Ehc->PeriodFrameHost\r
+ Ehc->PeriodFrame\r
);\r
\r
+ Ehc->PeriodFrame = NULL;\r
+ }\r
+\r
+ if (Ehc->PeriodFrameHost != NULL) {\r
+ FreePool (Ehc->PeriodFrameHost);\r
Ehc->PeriodFrameHost = NULL;\r
- Ehc->PeriodFrame = NULL;\r
}\r
}\r
\r
Qh->NextQh = Head->NextQh;\r
Head->NextQh = Qh;\r
\r
- PciAddr = UsbHcGetPciAddressForHostMem (Ehc->MemPool, Head, sizeof (EHC_QH));\r
- Qh->QhHw.HorizonLink = QH_LINK (PciAddr, EHC_TYPE_QH, FALSE);;\r
- PciAddr = UsbHcGetPciAddressForHostMem (Ehc->MemPool, Qh, sizeof (EHC_QH));\r
+ PciAddr = UsbHcGetPciAddressForHostMem (Ehc->MemPool, Qh->NextQh, sizeof (EHC_QH));\r
+ Qh->QhHw.HorizonLink = QH_LINK (PciAddr, EHC_TYPE_QH, FALSE);\r
+ PciAddr = UsbHcGetPciAddressForHostMem (Ehc->MemPool, Head->NextQh, sizeof (EHC_QH));\r
Head->QhHw.HorizonLink = QH_LINK (PciAddr, EHC_TYPE_QH, FALSE);\r
}\r
\r
Head->NextQh = Qh->NextQh;\r
Qh->NextQh = NULL;\r
\r
- PciAddr = UsbHcGetPciAddressForHostMem (Ehc->MemPool, Head, sizeof (EHC_QH));\r
+ PciAddr = UsbHcGetPciAddressForHostMem (Ehc->MemPool, Head->NextQh, sizeof (EHC_QH));\r
Head->QhHw.HorizonLink = QH_LINK (PciAddr, EHC_TYPE_QH, FALSE);\r
\r
//\r
IN EHC_QH *Qh\r
)\r
{\r
- UINT32 *Frames;\r
UINTN Index;\r
EHC_QH *Prev;\r
EHC_QH *Next;\r
EFI_PHYSICAL_ADDRESS PciAddr;\r
\r
- Frames = Ehc->PeriodFrameHost;\r
-\r
for (Index = 0; Index < EHC_FRAME_LEN; Index += Qh->Interval) {\r
//\r
// First QH can't be NULL because we always keep PeriodOne\r
// heads on the frame list\r
//\r
- ASSERT (!EHC_LINK_TERMINATED (Frames[Index]));\r
- Next = EHC_ADDR (Ehc->High32bitAddr, Frames[Index]);\r
+ ASSERT (!EHC_LINK_TERMINATED (((UINT32*)Ehc->PeriodFrame)[Index]));\r
+ Next = (EHC_QH*)((UINTN*)Ehc->PeriodFrameHost)[Index];\r
Prev = NULL;\r
\r
//\r
PciAddr = UsbHcGetPciAddressForHostMem (Ehc->MemPool, Qh, sizeof (EHC_QH));\r
\r
if (Prev == NULL) {\r
- Frames[Index] = QH_LINK (PciAddr, EHC_TYPE_QH, FALSE);\r
+ ((UINT32*)Ehc->PeriodFrame)[Index] = QH_LINK (PciAddr, EHC_TYPE_QH, FALSE);\r
+ ((UINTN*)Ehc->PeriodFrameHost)[Index] = (UINTN)Qh;\r
} else {\r
Prev->NextQh = Qh;\r
Prev->QhHw.HorizonLink = QH_LINK (PciAddr, EHC_TYPE_QH, FALSE);\r
IN EHC_QH *Qh\r
)\r
{\r
- UINT32 *Frames;\r
UINTN Index;\r
EHC_QH *Prev;\r
EHC_QH *This;\r
\r
- Frames = Ehc->PeriodFrameHost;\r
-\r
for (Index = 0; Index < EHC_FRAME_LEN; Index += Qh->Interval) {\r
//\r
// Frame link can't be NULL because we always keep PeroidOne\r
// on the frame list\r
//\r
- ASSERT (!EHC_LINK_TERMINATED (Frames[Index]));\r
- This = EHC_ADDR (Ehc->High32bitAddr, Frames[Index]);\r
+ ASSERT (!EHC_LINK_TERMINATED (((UINT32*)Ehc->PeriodFrame)[Index]));\r
+ This = (EHC_QH*)((UINTN*)Ehc->PeriodFrameHost)[Index];\r
Prev = NULL;\r
\r
//\r
//\r
// Qh is the first entry in the frame\r
//\r
- Frames[Index] = Qh->QhHw.HorizonLink;\r
+ ((UINT32*)Ehc->PeriodFrame)[Index] = Qh->QhHw.HorizonLink;\r
+ ((UINTN*)Ehc->PeriodFrameHost)[Index] = (UINTN)Qh->NextQh;\r
} else {\r
Prev->NextQh = Qh->NextQh;\r
Prev->QhHw.HorizonLink = Qh->QhHw.HorizonLink;\r
QhHw->Pid = 0;\r
QhHw->ErrCnt = 0;\r
QhHw->CurPage = 0;\r
- QhHw->IOC = 0;\r
+ QhHw->Ioc = 0;\r
QhHw->TotalBytes = 0;\r
\r
for (Index = 0; Index < 5; Index++) {\r