Exemple #1
0
HCD_STATUS HcdCancelTransfer(uint32_t PipeHandle)
{
    uint8_t HostID, EdIdx;

    ASSERT_STATUS_OK(PipehandleParse(PipeHandle, &HostID, &EdIdx) );

    HcdED(EdIdx)->hcED.Skip = 1;

    /* Clear SOF and wait for the next frame */
    USB_REG(HostID)->InterruptStatus = HC_INTERRUPT_StartofFrame;
    while ( !(USB_REG(HostID)->InterruptStatus & HC_INTERRUPT_StartofFrame) )/* TODO Should have timeout */

        /* ISO TD & General TD have the same offset for nextTD, we can use GTD as pointer to travel on TD list */
        while ( Align16(HcdED(EdIdx)->hcED.HeadP.HeadTD) != Align16(HcdED(EdIdx)->hcED.TailP) ) {
            uint32_t HeadTD = Align16(HcdED(EdIdx)->hcED.HeadP.HeadTD);
            if ( IsIsoEndpoint(EdIdx) ) {
                HcdED(EdIdx)->hcED.HeadP.HeadTD = ((PHCD_IsoTransferDescriptor) HeadTD)->NextTD;
                FreeItd( (PHCD_IsoTransferDescriptor) HeadTD);
            }
            else {
                HcdED(EdIdx)->hcED.HeadP.HeadTD = ((PHCD_GeneralTransferDescriptor) HeadTD)->hcGTD.NextTD;
                FreeGtd((PHCD_GeneralTransferDescriptor) HeadTD);
            }
        }
    HcdED(EdIdx)->hcED.HeadP.HeadTD = Align16(HcdED(EdIdx)->hcED.TailP);/*-- Toggle Carry/Halted are also set to 0 --*/
    HcdED(EdIdx)->hcED.HeadP.ToggleCarry = 0;

    HcdED(EdIdx)->hcED.Skip = 0;
    return HCD_STATUS_OK;
}
Exemple #2
0
HCD_STATUS HcdDataTransfer(uint32_t PipeHandle,
                           uint8_t *const buffer,
                           uint32_t const length,
                           uint16_t *const pActualTransferred)
{
    uint8_t HostID, EdIdx;
    uint32_t ExpectedLength;

    if ((buffer == NULL) || (length == 0)) {
        ASSERT_STATUS_OK_MESSAGE(HCD_STATUS_PARAMETER_INVALID, "Data Buffer is NULL or Transfer Length is 0");
    }

    ASSERT_STATUS_OK(PipehandleParse(PipeHandle, &HostID, &EdIdx) );
    ASSERT_STATUS_OK(HcdED(EdIdx)->hcED.HeadP.Halted ? HCD_STATUS_TRANSFER_Stall : HCD_STATUS_OK);

    ExpectedLength = (length != HCD_ENDPOINT_MAXPACKET_XFER_LEN) ? length : HcdED(EdIdx)->hcED.MaxPackageSize;

    if ( IsIsoEndpoint(EdIdx) ) {	/* Iso Transfer */
        ASSERT_STATUS_OK(QueueITDs(EdIdx, buffer, ExpectedLength) );
    }
    else {
        ASSERT_STATUS_OK(QueueGTDs(EdIdx, buffer, ExpectedLength, 0) );
        if (HcdED(EdIdx)->ListIndex == BULK_LIST_HEAD) {
            USB_REG(HostID)->CommandStatus |= HC_COMMAND_STATUS_BulkListFilled;
        }
    }

    HcdED(EdIdx)->status = HCD_STATUS_TRANSFER_QUEUED;
    HcdED(EdIdx)->pActualTransferCount = pActualTransferred;/* TODO refractor Actual length transfer */

    return HCD_STATUS_OK;
}
Exemple #3
0
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;
}
Exemple #4
0
static HCD_STATUS WaitForTransferComplete(uint8_t EdIdx)
{
#ifndef __TEST__
    while ( HcdED(EdIdx)->status == HCD_STATUS_TRANSFER_QUEUED ) {}
    return (HCD_STATUS) HcdED(EdIdx)->status;
#else
    return HCD_STATUS_OK;
#endif
}
Exemple #5
0
HCD_STATUS HcdClearEndpointHalt(uint32_t PipeHandle)
{
    uint8_t HostID, EdIdx;
    ASSERT_STATUS_OK(PipehandleParse(PipeHandle, &HostID, &EdIdx) );
    /* TODO should we call HcdCancelTrnasfer ? */
    HcdED(EdIdx)->hcED.HeadP.Halted = 0;
    HcdED(EdIdx)->hcED.HeadP.ToggleCarry = 0;

    HcdED(EdIdx)->status = HCD_STATUS_OK;

    return HCD_STATUS_OK;
}
Exemple #6
0
static __INLINE HCD_STATUS InsertEndpoint(uint8_t HostID, uint32_t EdIdx, uint8_t ListIndex)
{
    PHC_ED list_head;
    list_head = &(ohci_data[HostID].staticEDs[ListIndex]);

    HcdED(EdIdx)->hcED.NextED = list_head->NextED;
    list_head->NextED = (uint32_t) HcdED(EdIdx);

    //  if ( IsInterruptEndpoint(EdIdx) )
    //  {
    //      OHCI_HOST_DATA->staticEDs[ListIndex].TailP += HcdED(EdIdx)->hcED.MaxPackageSize;	/* increase the bandwidth for the found list */
    //  }

    return HCD_STATUS_OK;
}
Exemple #7
0
HCD_STATUS HcdGetPipeStatus(uint32_t PipeHandle)
{
    uint8_t HostID, EdIdx;

    ASSERT_STATUS_OK(PipehandleParse(PipeHandle, &HostID, &EdIdx) );

    return (HCD_STATUS)HcdED(EdIdx)->status;
}
Exemple #8
0
static __INLINE HCD_STATUS RemoveEndpoint(uint8_t HostID, uint32_t EdIdx)
{
    PHCD_EndpointDescriptor prevED;

    prevED = (PHCD_EndpointDescriptor) & (ohci_data[HostID].staticEDs[HcdED(EdIdx)->ListIndex]);
    while (prevED->hcED.NextED != (uint32_t) HcdED(EdIdx) ) {
        prevED = (PHCD_EndpointDescriptor) (prevED->hcED.NextED);
    }

    //  if ( IsInterruptEndpoint(EdIdx) )
    //  {
    //      OHCI_HOST_DATA->staticEDs[HcdED(EdIdx)->ListIndex].TailP -= HcdED(EdIdx)->hcED.MaxPackageSize;	/* decrease the bandwidth for the removed list */
    //  }
    prevED->hcED.NextED = HcdED(EdIdx)->hcED.NextED;

    return HCD_STATUS_OK;
}
Exemple #9
0
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;
}
Exemple #10
0
HCD_STATUS HcdClosePipe(uint32_t PipeHandle)
{
    uint8_t HostID, EdIdx;

    ASSERT_STATUS_OK(PipehandleParse(PipeHandle, &HostID, &EdIdx) );

    ASSERT_STATUS_OK(HcdCancelTransfer(PipeHandle) );

    HcdED(EdIdx)->hcED.Skip = 1;/* no need for delay, it is already delayed in cancel transfer */
    RemoveEndpoint(HostID, EdIdx);

    FreeED(EdIdx);

    return HCD_STATUS_OK;
}
Exemple #11
0
/** Direction, DataToggle parameter only has meaning for control transfer, for other transfer use 0 for these paras */
static HCD_STATUS QueueOneGTD (uint32_t EdIdx, uint8_t* const CurrentBufferPointer, uint32_t xferLen, uint8_t DirectionPID, uint8_t DataToggle, uint8_t IOC)
{
	PHCD_GeneralTransferDescriptor TailP;

	TailP = ( (PHCD_GeneralTransferDescriptor) HcdED(EdIdx)->hcED.TailP ) ;
	TailP->hcGTD.DirectionPID = DirectionPID;
	TailP->hcGTD.DataToggle = DataToggle;
	TailP->hcGTD.CurrentBufferPointer = CurrentBufferPointer;
	TailP->hcGTD.BufferEnd = (xferLen) ? (CurrentBufferPointer+xferLen-1) : NULL;
	TailP->TransferCount = xferLen;
	if (!IOC)
	{
		TailP->hcGTD.DelayInterrupt = TD_NoInterruptOnComplete; /* Delay Interrupt with  */
	}

	/* Create a new place holder TD & link setup TD to the new place holder */
	ASSERT_STATUS_OK ( AllocGtdForEd(EdIdx) );

	return HCD_STATUS_OK;
}
Exemple #12
0
HCD_STATUS HcdControlTransfer(uint32_t PipeHandle,
                              const USB_Request_Header_t *const pDeviceRequest,
                              uint8_t *const buffer)
{
    uint8_t HostID, EdIdx;

    if ((pDeviceRequest == NULL) || (buffer == NULL)) {
        ASSERT_STATUS_OK_MESSAGE(HCD_STATUS_PARAMETER_INVALID, "Device Request or Data Buffer is NULL");
    }

    ASSERT_STATUS_OK(PipehandleParse(PipeHandle, &HostID, &EdIdx) );

    /************************************************************************/
    /* Setup Stage                                                          */
    /************************************************************************/
    ASSERT_STATUS_OK(QueueOneGTD(EdIdx, (uint8_t *) pDeviceRequest, 8, 0, 2, 0) );			/* Setup TD: DirectionPID=00 - DataToggle=10b (always DATA0) */

    /************************************************************************/
    /* Data Stage                                                           */
    /************************************************************************/
    if (pDeviceRequest->wLength) {	/* Could have problem if the wLength is larger than pipe size */
        ASSERT_STATUS_OK(QueueOneGTD(EdIdx, buffer, pDeviceRequest->wLength,
                                     (pDeviceRequest->bmRequestType & 0x80) ? 2 : 1, 3, 0) );											/* DataToggle=11b (always DATA1) */
    }
    /************************************************************************/
    /* Status Stage                                                                     */
    /************************************************************************/
    ASSERT_STATUS_OK(QueueOneGTD(EdIdx, NULL, 0, (pDeviceRequest->bmRequestType & 0x80) ? 1 : 2, 3, 1) );	/* Status TD: Direction=opposite of data direction - DataToggle=11b (always DATA1) */

    /* set control list filled */
    USB_REG(HostID)->CommandStatus |= HC_COMMAND_STATUS_ControlListFilled;

    HcdED(EdIdx)->status = HCD_STATUS_TRANSFER_QUEUED;

    /* wait for semaphore compete TDs */
    ASSERT_STATUS_OK(WaitForTransferComplete(EdIdx) );

    return HCD_STATUS_OK;
}
Exemple #13
0
static __INLINE Bool IsInterruptEndpoint(uint8_t EdIdx)
{
    return (HcdED(EdIdx)->ListIndex < CONTROL_LIST_HEAD) && !IsIsoEndpoint(EdIdx);
}
Exemple #14
0
static __INLINE Bool IsIsoEndpoint(uint8_t EdIdx)
{
    return (HcdED(EdIdx)->hcED.Format ==0 ? FALSE : TRUE);
}
Exemple #15
0
static __INLINE Bool IsIsoEndpoint( uint8_t EdIdx )
{
	return HcdED(EdIdx)->hcED.Format ;
}
Exemple #16
0
HCD_STATUS HcdOpenPipe(uint8_t HostID,
                       uint8_t DeviceAddr,
                       HCD_USB_SPEED DeviceSpeed,
                       uint8_t EndpointNumber,
                       HCD_TRANSFER_TYPE TransferType,
                       HCD_TRANSFER_DIR TransferDir,
                       uint16_t MaxPacketSize,
                       uint8_t Interval,
                       uint8_t Mult,
                       uint8_t HSHubDevAddr,
                       uint8_t HSHubPortNum,
                       uint32_t *const PipeHandle)
{
    uint32_t EdIdx;
    uint8_t ListIdx;

    (void) Mult;
    (void) HSHubDevAddr;
    (void) HSHubPortNum;	/* Disable compiler warnings */

#if !ISO_LIST_ENABLE
    if ( TransferType == ISOCHRONOUS_TRANSFER ) {
        ASSERT_STATUS_OK_MESSAGE(HCD_STATUS_TRANSFER_TYPE_NOT_SUPPORTED, "Please set ISO_LIST_ENABLE to YES");
    }
#endif

#if !INTERRUPT_LIST_ENABLE
    if ( TransferType == INTERRUPT_TRANSFER ) {
        ASSERT_STATUS_OK_MESSAGE(HCD_STATUS_TRANSFER_TYPE_NOT_SUPPORTED, "Please set INTERRUPT_LIST_ENABLE to YES");
    }
#endif

    /********************************* Parameters Verify *********************************/
    ASSERT_STATUS_OK(OpenPipe_VerifyParameters(HostID, DeviceAddr, DeviceSpeed, EndpointNumber, TransferType,
                     TransferDir, MaxPacketSize, Interval, 0) );

    EndpointNumber &= 0xF;	/* Endpoint number is in range 0-15 */
    MaxPacketSize &= 0x3FF;	/* Max Packet Size is in range 0-1024 */

    switch (TransferType) {
    case CONTROL_TRANSFER:
        ListIdx = CONTROL_LIST_HEAD;
        break;

    case BULK_TRANSFER:
        ListIdx = BULK_LIST_HEAD;
        break;

    case INTERRUPT_TRANSFER:
        // ListIdx = FindInterruptTransferListIndex(Interval);
        ListIdx = INTERRUPT_1ms_LIST_HEAD;
        break;

    case ISOCHRONOUS_TRANSFER:
        ListIdx = ISO_LIST_HEAD;
        break;
    default :							// just to clear warning
        ListIdx = 0xFF;
        break;
    }

    if(ListIdx == 0xFF) return HCD_STATUS_PARAMETER_INVALID;

    ASSERT_STATUS_OK(AllocEd(DeviceAddr, DeviceSpeed, EndpointNumber, TransferType, TransferDir, MaxPacketSize,
                             Interval, &EdIdx) );

    /* Add new ED to the EDs List */
    HcdED(EdIdx)->ListIndex  = ListIdx;
    InsertEndpoint(HostID, EdIdx, ListIdx);

    PipehandleCreate(PipeHandle, HostID, EdIdx);
    return HCD_STATUS_OK;
}
Exemple #17
0
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 */
    }
}