35 #define __INCLUDE_FROM_USB_DRIVER
36 #include "../../../USBMode.h"
38 #if (defined(USB_CAN_BE_HOST) && defined(__LPC_EHCI__))
40 #define __LPC_EHCI_C__
41 #include "../../../../../../Common/Common.h"
42 #include "../../../USBTask.h"
65 USB_REG(HostID)->USBSTS_H = 0xFFFFFFFF;
66 USB_REG(HostID)->PORTSC1_H &= ~(1 << 12);
67 USB_REG(HostID)->USBMODE_H = (1 << 0);
105 return USB_REG(HostID)->FRINDEX_H;
125 uint16_t MaxPacketSize,
128 uint8_t HSHubDevAddr,
129 uint8_t HSHubPortNum,
140 #if !INTERRUPT_LIST_ENABLE
148 TransferDir, MaxPacketSize, Interval, Mult) );
150 EndpointNumber &= 0xF;
151 MaxPacketSize &= 0x3FF;
153 switch (TransferType) {
157 MaxPacketSize, Interval, Mult, HSHubDevAddr, HSHubPortNum, &HeadIdx) );
165 MaxPacketSize, Interval, Mult, HSHubDevAddr, HSHubPortNum, &HeadIdx) );
175 "Highspeed ISO and ISO IN is not supported yet, due to lack of testing");
179 MaxPacketSize, Interval, Mult, HSHubDevAddr, HSHubPortNum, &HeadIdx) );
189 uint8_t HostID, HeadIdx;
212 uint8_t HostID, HeadIdx;
229 if (HeadIdx == pItd->IhdIdx) {
231 pNextPointer->
Link = pItd->Horizontal.Link;
239 if (HeadIdx == pSItd->IhdIdx) {
241 pNextPointer->
Link = pSItd->Horizontal.Link;
255 PHCD_QTD pQtd = (PHCD_QTD) Align32(TdLink);
256 TdLink = pQtd->NextQtd;
259 pQtd->IntOnComplete = 0;
271 uint8_t *
const buffer)
273 uint8_t HostID, QhdIdx;
275 uint32_t SetupTdIdx, DataTdIdx, StatusTdIdx;
279 if ((pDeviceRequest ==
NULL) || (buffer ==
NULL)) {
285 Datalength = pDeviceRequest->wLength;
286 direction = pDeviceRequest->bmRequestType & 0x80;
296 DataTdIdx = SetupTdIdx;
319 uint8_t *
const buffer,
321 uint16_t *
const pActualTransferred)
323 uint8_t HostID, HeadIdx;
328 if ((buffer ==
NULL) || (length == 0)) {
356 HcdQHD(HostID, HeadIdx)->pActualTransferCount = pActualTransferred;
358 *(
HcdQHD(HostID, HeadIdx)->pActualTransferCount) = ExpectedLength;
366 uint8_t HostID, HeadIdx;
374 static void FreeQhd(uint8_t HostID, uint8_t QhdIdx)
378 HcdQHD(HostID, QhdIdx)->inUse = 0;
384 uint8_t EndpointNumber,
387 uint16_t MaxPacketSize,
390 uint8_t HSHubDevAddr,
391 uint8_t HSHubPortNum,
395 for ( (*pQhdIdx) = 0; (*pQhdIdx) <
HCD_MAX_QTD &&
HcdQHD(HostID, *pQhdIdx)->inUse; (*pQhdIdx)++) {}
401 memset(
HcdQHD(HostID, *pQhdIdx), 0,
sizeof(HCD_QHD) );
404 HcdQHD(HostID, *pQhdIdx)->inUse = 1;
411 HcdQHD(HostID, *pQhdIdx)->DeviceAddress = DeviceAddr;
413 HcdQHD(HostID, *pQhdIdx)->InActiveOnNextTransaction = 0;
417 HcdQHD(HostID, *pQhdIdx)->HeadReclamationFlag = 0;
418 HcdQHD(HostID, *pQhdIdx)->MaxPackageSize = MaxPacketSize;
421 HcdQHD(HostID, *pQhdIdx)->NakCountReload = 0;
426 *pQhdIdx)->uFrameSMask =
430 HcdQHD(HostID, *pQhdIdx)->HubAddress = HSHubDevAddr;
431 HcdQHD(HostID, *pQhdIdx)->PortNumber = HSHubPortNum;
439 *pQhdIdx)->Overlay.PingState_Err =
458 Align32(pQhd->Horizontal.Link) != (
uint32_t)
HcdQHD(HostID, QhdIdx) &&
460 pQhd = (
PHCD_QHD) Align32(pQhd->Horizontal.Link);
462 if ( Align32(pQhd->Horizontal.Link) != (
uint32_t)
HcdQHD(HostID, QhdIdx) ) {
467 pQhd->Horizontal.Link =
HcdQHD(HostID, QhdIdx)->Horizontal.Link;
473 static void FreeQtd(PHCD_QTD pQtd)
488 for ((*pTdIdx) = 0; (*pTdIdx) <
HCD_MAX_QTD &&
HcdQTD(HostID, *pTdIdx)->inUse; (*pTdIdx)++) {}
496 HcdQTD(HostID, *pTdIdx)->NextQtd = 1;
499 HcdQTD(HostID, *pTdIdx)->inUse = 1;
501 HcdQTD(HostID, *pTdIdx)->Active = 1;
503 HcdQTD(HostID, *pTdIdx)->TotalBytesToTransfer = xferLen;
505 HcdQTD(HostID, *pTdIdx)->IntOnComplete = IOC;
507 HcdQTD(HostID, *pTdIdx)->BufferPointer[0] = (
uint32_t) BufferPointer;
508 BytesInPage = 0x1000 - Offset4k((
uint32_t) BufferPointer);
509 xferLen -=
MIN(xferLen, BytesInPage);
511 for (idx = 1; idx <= 4 && xferLen > 0; idx++) {
513 *pTdIdx)->BufferPointer[idx] = Align4k(
HcdQTD(HostID, (*pTdIdx))->BufferPointer[idx - 1]) + 0x1000;
514 xferLen -=
MIN(xferLen, 0x1000);
533 while (xferLen > 0) {
537 TdLen =
MIN(xferLen, MaxTDLen);
540 if (TailTdIdx == 0xFFFFFFFF) {
548 TailTdIdx = NewTdIDx;
575 uint8_t XactStep = 8 / XactPerITD;
578 memset(
HcdHsITD(HostID, *pTdIdx), 0,
sizeof(HCD_HS_ITD));
580 HcdHsITD(HostID, *pTdIdx)->inUse = 1;
584 for (i = 0; TDLen > 0 && i < 8; i += XactStep) {
588 HcdHsITD(HostID, *pTdIdx)->BufferPointer[i] = Align4k( (
uint32_t) dataBuff);
590 HcdHsITD(HostID, *pTdIdx)->Transaction[i].Offset = ( (
uint32_t) dataBuff ) & 4095;
591 HcdHsITD(HostID, *pTdIdx)->Transaction[i].PageSelect = i;
592 HcdHsITD(HostID, *pTdIdx)->Transaction[i].IntOnComplete = (IntOnComplete && TDLen == 0) ? 1 : 0;
593 HcdHsITD(HostID, *pTdIdx)->Transaction[i].Length = XactLen;
594 HcdHsITD(HostID, *pTdIdx)->Transaction[i].Active = 1;
599 HcdHsITD(HostID, *pTdIdx)->BufferPointer[0] |= (
HcdQHD(HostID, IhdIdx)->EndpointNumber << 8) |
HcdQHD(HostID,
603 *pTdIdx)->BufferPointer[1] |=
604 (
HcdQHD(HostID, IhdIdx)->Direction << 1) |
HcdQHD(HostID, IhdIdx)->MaxPackageSize;
605 HcdHsITD(HostID, *pTdIdx)->BufferPointer[2] |=
HcdQHD(HostID, IhdIdx)->Mult;
622 if (
HcdQHD(IhdIdx)->Interval < 4) {
623 XactPerITD = 1 << ( 4 -
HcdQHD(IhdIdx)->Interval );
628 FramePeriod = 1 << (
HcdQHD(IhdIdx)->Interval - 4 );
632 #define FramePeriod 1
635 MaxTDLen = XactPerITD *
HcdQHD(HostID, IhdIdx)->MaxPackageSize *
HcdQHD(HostID, IhdIdx)->Mult;
636 FrameIdx =
USB_REG(HostID)->FRINDEX_H >> 3;
638 if (xferLen > MaxTDLen * FRAME_LIST_SIZE) {
641 "ISO data length overflows the Period Frame List size, Please increase size by FRAMELIST_SIZE_BITS or reduce data length");
644 while (xferLen > 0) {
648 TDLen =
MIN(xferLen, MaxTDLen);
653 FrameIdx = (FrameIdx + FramePeriod) % FRAME_LIST_SIZE;
673 uint8_t IntOnComplete)
678 for ((*pTdIdx) = 0; (*pTdIdx) <
HCD_MAX_SITD &&
HcdSITD(HostID, *pTdIdx)->inUse; (*pTdIdx)++) {}
683 memset(
HcdSITD(HostID, *pTdIdx), 0,
sizeof(HCD_SITD) );
685 HcdSITD(HostID, *pTdIdx)->inUse = 1;
686 HcdSITD(HostID, *pTdIdx)->IhdIdx = HeadIdx;
691 HcdSITD(HostID, *pTdIdx)->DeviceAddress =
HcdQHD(HostID, HeadIdx)->DeviceAddress;
692 HcdSITD(HostID, *pTdIdx)->EndpointNumber =
HcdQHD(HostID, HeadIdx)->EndpointNumber;
693 HcdSITD(HostID, *pTdIdx)->HubAddress =
HcdQHD(HostID, HeadIdx)->HubAddress;
694 HcdSITD(HostID, *pTdIdx)->PortNumber =
HcdQHD(HostID, HeadIdx)->PortNumber;
695 HcdSITD(HostID, *pTdIdx)->Direction =
HcdQHD(HostID, HeadIdx)->Direction;
697 HcdSITD(HostID, *pTdIdx)->uFrameSMask = (1 << TCount) - 1;
698 HcdSITD(HostID, *pTdIdx)->uFrameCMask = 0;
700 HcdSITD(HostID, *pTdIdx)->Active = 1;
701 HcdSITD(HostID, *pTdIdx)->TotalBytesToTransfer = TDLen;
706 HcdSITD(HostID, *pTdIdx)->BufferPointer[1] = Align4k( ((
uint32_t) dataBuff) + TDLen);
708 HcdSITD(HostID, *pTdIdx)->BufferPointer[1] |= TCount << TCount_Pos;
709 HcdSITD(HostID, *pTdIdx)->BufferPointer[1] |= (TCount > 1 ? 1 : 0 ) << TPos_Pos;
731 if (
HcdQHD(IhdIdx)->Interval < 4) {
735 FramePeriod = 1 << (
HcdQHD(IhdIdx)->Interval - 4 );
738 #define FramePeriod 1
744 "ISO data length overflows the Period Frame List size, Please increase size by FRAMELIST_SIZE_BITS or reduce data length");
747 FrameIdx =
USB_REG(HostID)->FRINDEX_H >> 3;
757 FrameIdx = (FrameIdx + FramePeriod) % FRAME_LIST_SIZE;
783 if ((pHandle->
HostId >= MAX_USB_CORE) ||
791 *pHostID = pHandle->
HostId;
794 *pIdx = pHandle->
Idx;
810 pHandle->
Type = (uint8_t) XferType;
833 static __INLINE PHCD_QTD
HcdQTD(uint8_t HostID, uint8_t idx)
856 static __INLINE
bool IsInterruptQhd(uint8_t HostID, uint8_t QhdIdx)
858 return HcdQHD(HostID, QhdIdx)->uFrameSMask;
865 IntStatus =
USB_REG(HostID)->USBSTS_H & t;
867 if (IntStatus == 0) {
911 static void RemoveCompletedQTD(
PHCD_QHD pQhd)
917 while ( (
isValidLink(TdLink), pQtd = (PHCD_QTD) Align32(TdLink) ) &&
919 TdLink = pQtd->NextQtd;
921 if (pQhd->pActualTransferCount) {
922 *(pQhd->pActualTransferCount) -= pQtd->TotalBytesToTransfer;
925 if (pQtd->IntOnComplete) {
933 pQhd->FirstQtd = TdLink;
936 static void RemoveErrorQTD(
PHCD_QHD pQhd)
940 bool errorfound =
false;
943 while ( (
isValidLink(TdLink), pQtd = (PHCD_QTD) Align32(TdLink) ) &&
945 TdLink = pQtd->NextQtd;
954 TdLink = pQhd->FirstQtd;
956 pQtd = (PHCD_QTD) Align32(TdLink);
957 TdLink = pQtd->NextQtd;
959 pQtd->IntOnComplete = 0;
963 pQhd->Overlay.Halted = 0;
975 pQhd = (
PHCD_QHD) Align32(pQhd->Horizontal.Link);
976 RemoveCompletedQTD(pQhd);
993 if ((pItd->Transaction[0].Active == 0) && (pItd->Transaction[1].Active == 0) &&
994 ( pItd->Transaction[2].Active == 0) && ( pItd->Transaction[3].Active == 0) &&
995 ( pItd->Transaction[4].Active == 0) && ( pItd->Transaction[5].Active == 0) &&
996 ( pItd->Transaction[6].Active == 0) && ( pItd->Transaction[7].Active == 0) ) {
997 if ((pItd->Transaction[0].IntOnComplete == 1) || (pItd->Transaction[1].IntOnComplete == 1) ||
998 ( pItd->Transaction[2].IntOnComplete == 1) || ( pItd->Transaction[3].IntOnComplete == 1) ||
999 ( pItd->Transaction[4].IntOnComplete == 1) || ( pItd->Transaction[5].IntOnComplete == 1) ||
1000 ( pItd->Transaction[6].IntOnComplete == 1) || ( pItd->Transaction[7].IntOnComplete == 1) ) {
1005 pNextPointer->
Link = pItd->Horizontal.Link;
1013 if (pSItd->Active == 0) {
1014 if (pSItd->IntOnComplete) {
1020 pNextPointer->
Link = pSItd->Horizontal.Link;
1036 pQhd = (
PHCD_QHD) Align32(pQhd->Horizontal.Link);
1037 RemoveCompletedQTD(pQhd);
1049 pQhd = (
PHCD_QHD) Align32(pQhd->Horizontal.Link);
1050 RemoveErrorQTD(pQhd);
1056 if (deviceConnect) {
1099 USB_REG(HostID)->USBMODE_H = 0x23;
1159 static __INLINE
void DisableSchedule(uint8_t HostID, uint8_t isPeriod)
1164 if (
USB_REG(HostID)->USBSTS_H & statusMask) {
1165 USB_REG(HostID)->USBCMD_H &= ~cmdMask;
1166 while (
USB_REG(HostID)->USBSTS_H & statusMask) {}
1170 static __INLINE
void EnableSchedule(uint8_t HostID, uint8_t isPeriod)
1175 if (!(
USB_REG(HostID)->USBSTS_H & statusMask)) {
1176 USB_REG(HostID)->USBCMD_H |= cmdMask;
1177 while (!(
USB_REG(HostID)->USBSTS_H & statusMask)) {}
1201 #endif // __LPC_EHCI__