static HCD_STATUS QueueOneITD(uint32_t EdIdx, uint8_t *dataBuff, uint32_t TDLen, uint16_t StartingFrame) { uint32_t i; PHCD_IsoTransferDescriptor pItd = (PHCD_IsoTransferDescriptor) Align16(HcdED(EdIdx)->hcED.TailP); pItd->StartingFrame = StartingFrame; pItd->FrameCount = (TDLen / HcdED(EdIdx)->hcED.MaxPackageSize) + (TDLen % HcdED(EdIdx)->hcED.MaxPackageSize ? 1 : 0) - 1; pItd->BufferPage0 = Align4k( (uint32_t) dataBuff); pItd->BufferEnd = (uint32_t) (dataBuff + TDLen - 1); for (i = 0; TDLen > 0 && i < 8; i++) { uint32_t XactLen = MIN(TDLen, HcdED(EdIdx)->hcED.MaxPackageSize); pItd->OffsetPSW[i] = (HCD_STATUS_TRANSFER_NotAccessed << 12) | (Align4k((uint32_t) dataBuff) != Align4k(pItd->BufferPage0) ? _BIT(12) : 0) | Offset4k((uint32_t) dataBuff); /*-- FIXME take into cross page account later 15-12: ConditionCode, 11-0: offset --*/ TDLen -= XactLen; dataBuff += XactLen; } /* Create a new place holder TD & link setup TD to the new place holder */ ASSERT_STATUS_OK(AllocItdForEd(EdIdx) ); return HCD_STATUS_OK; }
static HCD_STATUS QueueGTDs(uint32_t EdIdx, uint8_t *dataBuff, uint32_t xferLen, uint8_t Direction) { while (xferLen > 0) { uint16_t TdLen; uint32_t MaxTDLen = TD_MAX_XFER_LENGTH - Offset4k((uint32_t) dataBuff); TdLen = MIN(xferLen, MaxTDLen); xferLen -= TdLen; ASSERT_STATUS_OK(QueueOneGTD(EdIdx, dataBuff, TdLen, Direction, 0, (xferLen ? 0 : 1)) ); dataBuff += TdLen; } return HCD_STATUS_OK; }
static HCD_STATUS QueueITDs(uint32_t EdIdx, uint8_t* dataBuff, uint32_t xferLen) { uint32_t FrameIdx; uint32_t MaxDataSize; #if 0 /* Maximum bandwidth (Interval = 1) regardless of Interval value */ uint8_t MaxXactPerITD, FramePeriod; if (HcdED(EdIdx)->Interval < 4) /*-- Period < 8 --*/ { MaxXactPerITD = 1 << ( 4 - HcdED(EdIdx)->Interval ) ; /*-- Interval 1 => 8, 2 => 4, 3 => 2 --*/ FramePeriod = 1; }else { MaxXactPerITD = 1; FramePeriod = 1 << ( HcdED(EdIdx)->Interval - 4 ); /*-- Frame step 4 => 1, 5 => 2, 6 => 3 --*/ } #else #define MaxXactPerITD 8 #define FramePeriod 1 #endif MaxDataSize = MaxXactPerITD * HcdED(EdIdx)->hcED.MaxPackageSize; FrameIdx = HcdGetFrameNumber(0)+1; /* FIXME dual controller */ while (xferLen > 0) { uint16_t TdLen; uint32_t MaxTDLen = TD_MAX_XFER_LENGTH - Offset4k((uint32_t)dataBuff); MaxTDLen = MIN(MaxDataSize, MaxTDLen); TdLen = MIN(xferLen, MaxTDLen); xferLen -= TdLen; /*---------- Fill data to Place hodler TD ----------*/ ASSERT_STATUS_OK ( QueueOneITD(EdIdx, dataBuff, TdLen, FrameIdx) ); FrameIdx = (FrameIdx + FramePeriod) % (1<<16); dataBuff += TdLen; } return HCD_STATUS_OK; }
static void ProcessDoneQueue(uint8_t HostID, uint32_t donehead) { PHC_GTD pCurTD = (PHC_GTD) donehead; PHC_GTD pTDList = NULL; /* do nothing if done queue is empty */ if (!donehead) { return; } /* reverse done queue order */ do { uint32_t nextTD = pCurTD->NextTD; pCurTD->NextTD = (uint32_t) pTDList; pTDList = pCurTD; pCurTD = (PHC_GTD) nextTD; } while (pCurTD); while (pTDList != NULL) { uint32_t EdIdx; pCurTD = pTDList; pTDList = (PHC_GTD) pTDList->NextTD; /* TODO Cannot determine EdIdx because GTD and ITD have different offsets for EdIdx */ if ( ((uint32_t) pCurTD) <= ((uint32_t) HcdITD(MAX_ITD - 1)) ) { /* ISO TD address range */ PHCD_IsoTransferDescriptor pItd = (PHCD_IsoTransferDescriptor) pCurTD; EdIdx = pItd->EdIdx; } else { /* GTD */ PHCD_GeneralTransferDescriptor pGtd = (PHCD_GeneralTransferDescriptor) pCurTD; EdIdx = pGtd->EdIdx; if (pGtd->hcGTD.CurrentBufferPointer) { pGtd->TransferCount -= ( Align4k( ((uint32_t) pGtd->hcGTD.BufferEnd) ^ ((uint32_t) pGtd->hcGTD.CurrentBufferPointer) ) ? 0x00001000 : 0 ) + Offset4k((uint32_t) pGtd->hcGTD.BufferEnd) - Offset4k( (uint32_t) pGtd->hcGTD.CurrentBufferPointer) + 1; } if (HcdED(EdIdx)->pActualTransferCount) { *(HcdED(EdIdx)->pActualTransferCount) = pGtd->TransferCount;/* increase usb request transfer count */ } } if (pCurTD->DelayInterrupt != TD_NoInterruptOnComplete) { /* Update ED status if Interrupt on Complete is set */ HcdED(EdIdx)->status = pCurTD->ConditionCode; } if ( pCurTD->ConditionCode ) { /* also update ED status if TD complete with error */ HcdED(EdIdx)->status = (HcdED(EdIdx)->hcED.HeadP.Halted == 1) ? HCD_STATUS_TRANSFER_Stall : pCurTD->ConditionCode; HcdED(EdIdx)->hcED.HeadP.Halted = 0; hcd_printf("Error on Endpoint 0x%X has HCD_STATUS code %d\r\n", HcdED(EdIdx)->hcED.FunctionAddr | (HcdED(EdIdx)->hcED.Direction == 2 ? 0x80 : 0x00), pCurTD->ConditionCode); } /* remove completed TD from usb request list, if request list is now empty complete usb request */ if (IsIsoEndpoint(EdIdx)) { FreeItd( (PHCD_IsoTransferDescriptor) pCurTD); } else { FreeGtd( (PHCD_GeneralTransferDescriptor) pCurTD); } /* Post Semaphore to signal TDs are transfer */ } }