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"
66 USB_REG(HostID)->USBSTS_H = 0xFFFFFFFF;
67 USB_REG(HostID)->PORTSC1_H &= ~(1 << 12);
68 USB_REG(HostID)->USBMODE_H = (1 << 0);
106 return USB_REG(HostID)->FRINDEX_H;
126 uint16_t MaxPacketSize,
129 uint8_t HSHubDevAddr,
130 uint8_t HSHubPortNum,
141 #if !INTERRUPT_LIST_ENABLE
149 TransferDir, MaxPacketSize, Interval, Mult) );
151 EndpointNumber &= 0xF;
152 MaxPacketSize &= 0x3FF;
154 switch (TransferType) {
158 MaxPacketSize, Interval, Mult, HSHubDevAddr, HSHubPortNum, &HeadIdx) );
166 MaxPacketSize, Interval, Mult, HSHubDevAddr, HSHubPortNum, &HeadIdx) );
177 "Highspeed ISO and ISO IN is not supported yet, due to lack of testing");
181 MaxPacketSize, Interval, Mult, HSHubDevAddr, HSHubPortNum, &HeadIdx) );
192 uint8_t HostID, HeadIdx;
216 uint8_t HostID, HeadIdx;
233 if (HeadIdx == pItd->IhdIdx) {
235 pNextPointer->
Link = pItd->Horizontal.Link;
243 if (HeadIdx == pSItd->IhdIdx) {
245 pNextPointer->
Link = pSItd->Horizontal.Link;
259 PHCD_QTD pQtd = (PHCD_QTD) Align32(TdLink);
260 TdLink = pQtd->NextQtd;
263 pQtd->IntOnComplete = 0;
277 uint8_t HostID, QhdIdx;
279 uint32_t SetupTdIdx, DataTdIdx, StatusTdIdx;
283 if ((pDeviceRequest ==
NULL) || (buffer ==
NULL)) {
289 Datalength = pDeviceRequest->wLength;
290 direction = pDeviceRequest->bmRequestType & 0x80;
300 DataTdIdx = SetupTdIdx;
323 uint8_t *
const buffer,
325 uint16_t *
const pActualTransferred)
327 uint8_t HostID, HeadIdx;
332 if ((buffer ==
NULL) || (length == 0)) {
366 HcdQHD(HostID, HeadIdx)->pActualTransferCount = pActualTransferred;
368 *(
HcdQHD(HostID, HeadIdx)->pActualTransferCount) = ExpectedLength;
376 uint8_t HostID, HeadIdx;
384 static void FreeQhd(uint8_t HostID, uint8_t QhdIdx)
388 HcdQHD(HostID, QhdIdx)->inUse = 0;
394 uint8_t EndpointNumber,
397 uint16_t MaxPacketSize,
400 uint8_t HSHubDevAddr,
401 uint8_t HSHubPortNum,
405 for ( (*pQhdIdx) = 0; (*pQhdIdx) <
HCD_MAX_QTD &&
HcdQHD(HostID, *pQhdIdx)->inUse; (*pQhdIdx)++) {}
411 memset(
HcdQHD(HostID, *pQhdIdx), 0,
sizeof(HCD_QHD) );
414 HcdQHD(HostID, *pQhdIdx)->inUse = 1;
421 HcdQHD(HostID, *pQhdIdx)->DeviceAddress = DeviceAddr;
423 HcdQHD(HostID, *pQhdIdx)->InActiveOnNextTransaction = 0;
427 HcdQHD(HostID, *pQhdIdx)->HeadReclamationFlag = 0;
428 HcdQHD(HostID, *pQhdIdx)->MaxPackageSize = MaxPacketSize;
431 HcdQHD(HostID, *pQhdIdx)->NakCountReload = 0;
436 *pQhdIdx)->uFrameSMask =
440 HcdQHD(HostID, *pQhdIdx)->HubAddress = HSHubDevAddr;
441 HcdQHD(HostID, *pQhdIdx)->PortNumber = HSHubPortNum;
449 *pQhdIdx)->Overlay.PingState_Err =
468 Align32(pQhd->Horizontal.Link) != (
uint32_t)
HcdQHD(HostID, QhdIdx) &&
470 pQhd = (
PHCD_QHD) Align32(pQhd->Horizontal.Link);
472 if ( Align32(pQhd->Horizontal.Link) != (
uint32_t)
HcdQHD(HostID, QhdIdx) ) {
477 pQhd->Horizontal.Link =
HcdQHD(HostID, QhdIdx)->Horizontal.Link;
483 static void FreeQtd(PHCD_QTD pQtd)
498 for ((*pTdIdx) = 0; (*pTdIdx) <
HCD_MAX_QTD &&
HcdQTD(HostID, *pTdIdx)->inUse; (*pTdIdx)++) {}
506 HcdQTD(HostID, *pTdIdx)->NextQtd = 1;
509 HcdQTD(HostID, *pTdIdx)->inUse = 1;
511 HcdQTD(HostID, *pTdIdx)->Active = 1;
513 HcdQTD(HostID, *pTdIdx)->TotalBytesToTransfer = xferLen;
515 HcdQTD(HostID, *pTdIdx)->IntOnComplete = IOC;
517 HcdQTD(HostID, *pTdIdx)->BufferPointer[0] = (
uint32_t) BufferPointer;
518 BytesInPage = 0x1000 - Offset4k((
uint32_t) BufferPointer);
519 xferLen -=
MIN(xferLen, BytesInPage);
521 for (idx = 1; idx <= 4 && xferLen > 0; idx++) {
523 *pTdIdx)->BufferPointer[idx] = Align4k(
HcdQTD(HostID, (*pTdIdx))->BufferPointer[idx - 1]) + 0x1000;
524 xferLen -=
MIN(xferLen, 0x1000);
547 if(PipeStreaming[HostID].PacketSize > 0)
548 TdLen =
MIN(xferLen, PipeStreaming[HostID].PacketSize);
550 TdLen =
MIN(xferLen, MaxTDLen);
553 if (TailTdIdx == 0xFFFFFFFF)
561 if(
HCD_STATUS_OK ==
AllocQTD(HostID, &NewTdIDx, dataBuff, TdLen, PIDCode, DataToggle, (xferLen==0) ? 1 : 0))
564 TailTdIdx = NewTdIDx;
568 PipeStreaming[HostID].BufferAddress = (
uint32_t)dataBuff;
569 PipeStreaming[HostID].RemainBytes = xferLen + TdLen;
570 PipeStreaming[HostID].DataToggle =
DataToggle;
575 if(DataToggle == 1) DataToggle = 0;
603 uint8_t XactStep = 8 / XactPerITD;
606 memset(
HcdHsITD(HostID, *pTdIdx), 0,
sizeof(HCD_HS_ITD));
608 HcdHsITD(HostID, *pTdIdx)->inUse = 1;
612 for (i = 0; TDLen > 0 && i < 8; i += XactStep) {
616 HcdHsITD(HostID, *pTdIdx)->BufferPointer[i] = Align4k( (
uint32_t) dataBuff);
618 HcdHsITD(HostID, *pTdIdx)->Transaction[i].Offset = ( (
uint32_t) dataBuff ) & 4095;
619 HcdHsITD(HostID, *pTdIdx)->Transaction[i].PageSelect = i;
620 HcdHsITD(HostID, *pTdIdx)->Transaction[i].IntOnComplete = (IntOnComplete && TDLen == 0) ? 1 : 0;
621 HcdHsITD(HostID, *pTdIdx)->Transaction[i].Length = XactLen;
622 HcdHsITD(HostID, *pTdIdx)->Transaction[i].Active = 1;
627 HcdHsITD(HostID, *pTdIdx)->BufferPointer[0] |= (
HcdQHD(HostID, IhdIdx)->EndpointNumber << 8) |
HcdQHD(HostID,
631 *pTdIdx)->BufferPointer[1] |=
632 (
HcdQHD(HostID, IhdIdx)->Direction << 1) |
HcdQHD(HostID, IhdIdx)->MaxPackageSize;
633 HcdHsITD(HostID, *pTdIdx)->BufferPointer[2] |=
HcdQHD(HostID, IhdIdx)->Mult;
650 if (
HcdQHD(IhdIdx)->Interval < 4) {
651 XactPerITD = 1 << ( 4 -
HcdQHD(IhdIdx)->Interval );
656 FramePeriod = 1 << (
HcdQHD(IhdIdx)->Interval - 4 );
660 #define FramePeriod 1
663 MaxTDLen = XactPerITD *
HcdQHD(HostID, IhdIdx)->MaxPackageSize *
HcdQHD(HostID, IhdIdx)->Mult;
664 FrameIdx =
USB_REG(HostID)->FRINDEX_H >> 3;
666 if (xferLen > MaxTDLen * FRAME_LIST_SIZE) {
669 "ISO data length overflows the Period Frame List size, Please increase size by FRAMELIST_SIZE_BITS or reduce data length");
672 while (xferLen > 0) {
676 TDLen =
MIN(xferLen, MaxTDLen);
681 FrameIdx = (FrameIdx + FramePeriod) % FRAME_LIST_SIZE;
701 uint8_t IntOnComplete)
706 for ((*pTdIdx) = 0; (*pTdIdx) <
HCD_MAX_SITD &&
HcdSITD(HostID, *pTdIdx)->inUse; (*pTdIdx)++) {}
711 memset(
HcdSITD(HostID, *pTdIdx), 0,
sizeof(HCD_SITD) );
713 HcdSITD(HostID, *pTdIdx)->inUse = 1;
714 HcdSITD(HostID, *pTdIdx)->IhdIdx = HeadIdx;
719 HcdSITD(HostID, *pTdIdx)->DeviceAddress =
HcdQHD(HostID, HeadIdx)->DeviceAddress;
720 HcdSITD(HostID, *pTdIdx)->EndpointNumber =
HcdQHD(HostID, HeadIdx)->EndpointNumber;
721 HcdSITD(HostID, *pTdIdx)->HubAddress =
HcdQHD(HostID, HeadIdx)->HubAddress;
722 HcdSITD(HostID, *pTdIdx)->PortNumber =
HcdQHD(HostID, HeadIdx)->PortNumber;
723 HcdSITD(HostID, *pTdIdx)->Direction =
HcdQHD(HostID, HeadIdx)->Direction;
725 HcdSITD(HostID, *pTdIdx)->uFrameSMask = (1 << TCount) - 1;
726 HcdSITD(HostID, *pTdIdx)->uFrameCMask = 0;
728 HcdSITD(HostID, *pTdIdx)->Active = 1;
729 HcdSITD(HostID, *pTdIdx)->TotalBytesToTransfer = TDLen;
734 HcdSITD(HostID, *pTdIdx)->BufferPointer[1] = Align4k( ((
uint32_t) dataBuff) + TDLen);
736 HcdSITD(HostID, *pTdIdx)->BufferPointer[1] |= TCount << TCount_Pos;
737 HcdSITD(HostID, *pTdIdx)->BufferPointer[1] |= (TCount > 1 ? 1 : 0 ) << TPos_Pos;
759 if (
HcdQHD(IhdIdx)->Interval < 4) {
763 FramePeriod = 1 << (
HcdQHD(IhdIdx)->Interval - 4 );
766 #define FramePeriod 1
772 "ISO data length overflows the Period Frame List size, Please increase size by FRAMELIST_SIZE_BITS or reduce data length");
775 FrameIdx =
USB_REG(HostID)->FRINDEX_H >> 3;
785 FrameIdx = (FrameIdx + FramePeriod) % FRAME_LIST_SIZE;
811 if ((pHandle->
HostId >= MAX_USB_CORE) ||
819 *pHostID = pHandle->
HostId;
822 *pIdx = pHandle->
Idx;
838 pHandle->
Type = (uint8_t) XferType;
861 static __INLINE PHCD_QTD
HcdQTD(uint8_t HostID, uint8_t idx)
884 static __INLINE
bool IsInterruptQhd(uint8_t HostID, uint8_t QhdIdx)
886 return HcdQHD(HostID, QhdIdx)->uFrameSMask;
893 IntStatus =
USB_REG(HostID)->USBSTS_H & t;
895 if (IntStatus == 0) {
939 static void RemoveCompletedQTD(uint8_t HostID,
PHCD_QHD pQhd)
943 bool is_data_remain =
false;
946 while( (
isValidLink(TdLink), pQtd = (PHCD_QTD) Align32(TdLink) ) &&
949 TdLink = pQtd->NextQtd;
951 if(pQhd->pActualTransferCount)
952 *(pQhd->pActualTransferCount) -= pQtd->TotalBytesToTransfer;
954 if (pQtd->IntOnComplete)
956 if(PipeStreaming[HostID].RemainBytes > 0)
957 is_data_remain =
true;
967 pQhd->FirstQtd = TdLink;
971 QueueQTDs(HostID, &pQtd,(uint8_t*)PipeStreaming[HostID].BufferAddress,
972 PipeStreaming[HostID].RemainBytes,
974 PipeStreaming[HostID].DataToggle);
980 static void RemoveErrorQTD(
PHCD_QHD pQhd)
984 bool errorfound =
false;
987 while ( (
isValidLink(TdLink), pQtd = (PHCD_QTD) Align32(TdLink) ) &&
989 TdLink = pQtd->NextQtd;
998 TdLink = pQhd->FirstQtd;
1000 pQtd = (PHCD_QTD) Align32(TdLink);
1001 TdLink = pQtd->NextQtd;
1003 pQtd->IntOnComplete = 0;
1007 pQhd->Overlay.Halted = 0;
1019 pQhd = (
PHCD_QHD) Align32(pQhd->Horizontal.Link);
1020 RemoveCompletedQTD(HostID,pQhd);
1037 if ((pItd->Transaction[0].Active == 0) && (pItd->Transaction[1].Active == 0) &&
1038 ( pItd->Transaction[2].Active == 0) && ( pItd->Transaction[3].Active == 0) &&
1039 ( pItd->Transaction[4].Active == 0) && ( pItd->Transaction[5].Active == 0) &&
1040 ( pItd->Transaction[6].Active == 0) && ( pItd->Transaction[7].Active == 0) ) {
1041 if ((pItd->Transaction[0].IntOnComplete == 1) || (pItd->Transaction[1].IntOnComplete == 1) ||
1042 ( pItd->Transaction[2].IntOnComplete == 1) || ( pItd->Transaction[3].IntOnComplete == 1) ||
1043 ( pItd->Transaction[4].IntOnComplete == 1) || ( pItd->Transaction[5].IntOnComplete == 1) ||
1044 ( pItd->Transaction[6].IntOnComplete == 1) || ( pItd->Transaction[7].IntOnComplete == 1) ) {
1049 pNextPointer->
Link = pItd->Horizontal.Link;
1057 if (pSItd->Active == 0) {
1058 if (pSItd->IntOnComplete) {
1064 pNextPointer->
Link = pSItd->Horizontal.Link;
1080 pQhd = (
PHCD_QHD) Align32(pQhd->Horizontal.Link);
1081 RemoveCompletedQTD(HostID,pQhd);
1093 pQhd = (
PHCD_QHD) Align32(pQhd->Horizontal.Link);
1094 RemoveErrorQTD(pQhd);
1100 if (deviceConnect) {
1143 USB_REG(HostID)->USBMODE_H = 0x23;
1203 static __INLINE
void DisableSchedule(uint8_t HostID, uint8_t isPeriod)
1208 if (
USB_REG(HostID)->USBSTS_H & statusMask) {
1209 USB_REG(HostID)->USBCMD_H &= ~cmdMask;
1210 while (
USB_REG(HostID)->USBSTS_H & statusMask) {}
1214 static __INLINE
void EnableSchedule(uint8_t HostID, uint8_t isPeriod)
1219 if (!(
USB_REG(HostID)->USBSTS_H & statusMask)) {
1220 USB_REG(HostID)->USBCMD_H |= cmdMask;
1221 while (!(
USB_REG(HostID)->USBSTS_H & statusMask)) {}
1247 uint8_t HostID = 0, HeadIdx;
1252 PipeStreaming[HostID].PacketSize = packetsize;
1255 #endif // __LPC_EHCI__