⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 ohcd.cpp

📁 WinCE 3.0 BSP, 包含Inter SA1110, Intel_815E, Advantech_PCM9574 等
💻 CPP
📖 第 1 页 / 共 5 页
字号:
            aszRequestStrings[bRequest] : TEXT("Invalid"));
}
inline const TCHAR *DecodePortFeatureString(USHORT wValue)
{
    return ((wValue < NUM_ELEMENTS(aszPortFeatureStrings)) ?
            aszPortFeatureStrings[wValue]:TEXT("Invalid"));
}
inline const TCHAR *DecodeHubFeatureString(USHORT wValue)
{
    return ((wValue < NUM_ELEMENTS(aszHubFeatureStrings)) ?
            aszHubFeatureStrings[wValue]:TEXT("Invalid"));
}

// Routine to decode control transfers - somewhat incomplete, add further decoding
// as necessary...
void
COhcd::DecodeControlTransfer(SEndpoint * pEndpt, PUSB_DEVICE_REQUEST pDr)
{
    SDevice *pDev;
	USB_DEVICE_REQUEST tempDeviceReq;
	PDWORD pSrc;
	PDWORD pDest;

    EnterCriticalSection(&m_csDeviceListLock);
    pDev = m_ppDevices[pEndpt->pEd->bfFunctionAddress];
    LeaveCriticalSection(&m_csDeviceListLock);
    if (!pDev)
        return;

	// Make a local copy of the device request so we can access by char and short
	pDest = (PDWORD) &tempDeviceReq;
	pSrc = (PDWORD) pDr;
	*pDest++ = *pSrc++;
	*pDest = *pSrc;

    // We only care about EP 0 transfers
    if (pEndpt->endptArrayNum == gcEndpoint0Addr) 
    {
        if (tempDeviceReq.bmRequestType & USB_REQUEST_CLASS)
        {
            if (pDev->pHubPorts)
            {
                // Treat this as a hub request
                switch (tempDeviceReq.bRequest) {
                    case USB_REQUEST_SET_FEATURE:
                    case USB_REQUEST_CLEAR_FEATURE:
                        // Port 0 == hub command, else port command
                        DEBUGMSG(1,(TEXT("OHCD::Control (HUB %X): %s_FEATURE, %s, port:%u\r\n"),pDev,
                                    (tempDeviceReq.bRequest == USB_REQUEST_SET_FEATURE)? TEXT("SET") : TEXT("CLEAR"),
                                    (tempDeviceReq.wIndex == 0) ?  DecodeHubFeatureString(tempDeviceReq.wValue) : DecodePortFeatureString(tempDeviceReq.wValue), 
                                    tempDeviceReq.wIndex)); 
                        break;
                    default:
                        DEBUGMSG(1,(TEXT("OHCD::Control (HUB %X): %s Val: %u, Idx: %u, Len: %u\r\n"),pDev,
                                    DecodeRequestString(tempDeviceReq.bRequest),tempDeviceReq.wValue, tempDeviceReq.wIndex,tempDeviceReq.wLength));
                        break;
                }
            }
            else
			{
                DEBUGMSG(1,(TEXT("OHCD::Control (CLASS %X): %s Val: %u, Idx: %u, Len: %u\r\n"),pDev,
                            DecodeRequestString(tempDeviceReq.bRequest),tempDeviceReq.wValue, tempDeviceReq.wIndex,tempDeviceReq.wLength));
			}
		}
        else 
        {
            // Device request
                    DEBUGMSG(1,(TEXT("OHCD:Control (DEV %X): %s Val: %u, Idx: %u, Len: %u\r\n"),pDev,
                                DecodeRequestString(tempDeviceReq.bRequest),tempDeviceReq.wValue, tempDeviceReq.wIndex,tempDeviceReq.wLength));
        }
    }
}
#endif // DEBUG


EError COhcd::InitializeSchedule(void)
{
    PBYTE virtAddr;
    ULONG physAddr;
    EError errorCode;
    UINT numTds;
    UINT td;
    ULONG paEd;
    REGISTER regBase = m_regBase;
    SGeneralTransferDescriptor *pTd;
    SIsochTransferDescriptor *pITd;
    SEndpointDescriptor *pEd, *pPrevEd;
    SDevice *pDev;
    SEndpoint *pEndpt;
    PBYTE pSetupBuffer;
    ULONG paSetupBuffer;
    STransfer *pTransfer;

    DEBUGMSG(ZONE_FUNCTION,(TEXT("+OHCD::InitializeSchedule\r\n")));
    
    // We're going to first get a good page aligned chunk of memory and divy
    // it up between the HCCA and some ED/TDs

    errorCode = ALLOC_PHYS_MEM(m_pobMem, USBPAGESIZE, &virtAddr,
            &physAddr, USBALLOCF_SPECIAL, NULL);

//    errorCode = m_pobMem->AllocateMemory(USBPAGESIZE, &virtAddr,
//            &physAddr, USBALLOCF_SPECIAL);
    if (errorCode != successful)
    {
        DEBUGMSG(ZONE_ERROR,
            (TEXT("OHCD: Couldn't allocate memory for the HCCA and TDs\r\n")));
        return(errorCode);
    }
    m_pHcca = virtAddr;
    virtAddr += gcHccaByteSize;
    physAddr += gcHccaByteSize;


    // This isn't strictly necessary as obviously no one has used the TD Lists
    // yet.  But grabbing an unheld CS is practically free, so this can't hurt.
    EnterCriticalSection(&m_csTdListsLock);

    // That's 256 bytes out of 4K.  Split the remaining memory between EDs, TDs
    // and Isoch TDs.  EDs and TDs are the same size, which is half that of
    // IsochTDs, so just split the remaining memory in half and allocate as
    // many of both kinds of TDs as each will allow.  Note that we can make
    // Tds into Eds and vice versa, so we'll just make TDs, not both.
    numTds = gcNumExtraGeneralTds + (USBPAGESIZE - gcHccaByteSize) /
        (sizeof(SGeneralTransferDescriptor) * 2);

    m_pFreeTdList = (SGeneralTransferDescriptor *)virtAddr;

    for (td = 0; td < numTds - 1; td++)
    {
        pTd = (SGeneralTransferDescriptor *)(virtAddr +
            td * sizeof(SGeneralTransferDescriptor));
        pTd->paNextTd = physAddr +
            (td + 1) * sizeof(SGeneralTransferDescriptor);
    }
    pTd = (SGeneralTransferDescriptor *)(virtAddr +
            (numTds - 1) * sizeof(SGeneralTransferDescriptor));
    pTd->paNextTd = 0;

    virtAddr += numTds * sizeof(SGeneralTransferDescriptor);
    physAddr += numTds * sizeof(SGeneralTransferDescriptor);

    // That did the general tds,  Now finish off the page with isoch ones.
    numTds = (USBPAGESIZE - (virtAddr - m_pHcca)) /
        sizeof(SIsochTransferDescriptor);

    m_pFreeITdList = (SIsochTransferDescriptor *)virtAddr;

    for (td = 0; td < numTds - 1; td++)
    {
        pITd = (SIsochTransferDescriptor *)(virtAddr +
            td * sizeof(SIsochTransferDescriptor));
        pITd->paNextTd = physAddr +
            (td + 1) * sizeof(SIsochTransferDescriptor);
    }
    pITd = (SIsochTransferDescriptor *)(virtAddr +
        (td + 1) * sizeof(SIsochTransferDescriptor));
    pITd->paNextTd = 0;

    // Now that we've got storage set aside for a bunch of descriptors, let's
    // set up the necessary list heads.
    errorCode = InitializeInterruptEds();
    if (errorCode != successful)
    {
        DEBUGMSG(ZONE_ERROR, (TEXT("OHCD: Error setting up InterruptEds\r\n")));
        return(errorCode);
    }

    // Our scheduling lives will be made considerably easier if we put dummy
    // Eds at the  start of the bulk and control Lists.  I've also seen
    // comments in the NT code that suggests this is necessary for CMD parts.
    pEd = (SEndpointDescriptor *)m_pFreeTdList;
    m_pFreeTdList = (SGeneralTransferDescriptor *)
        (m_pobMem->PaToVa(m_pFreeTdList->paNextTd));

    // In the static Eds, the tail pointer points to itself and the
    // head points to null.  This is illegal for OHCI, but since the
    // SKIP bit is set, the HC will never notice.
    pEd->paTdQueueTail = paEd = m_pobMem->VaToPa((PBYTE)pEd);
    pEd->paTdQueueHead = gcStaticEdIdentifier;
    pEd->bfSkip = TRUE;
    pEd->paNextEd = 0;
    WRITE_REGISTER_ULONG(HcBulkHeadEd(regBase), paEd);
    WRITE_REGISTER_ULONG(HcBulkCurrentEd(regBase), paEd);

    pEd = (SEndpointDescriptor *)m_pFreeTdList;
    m_pFreeTdList = (SGeneralTransferDescriptor *)
        (m_pobMem->PaToVa(m_pFreeTdList->paNextTd));
    pEd->paTdQueueTail = paEd = m_pobMem->VaToPa((PBYTE)pEd);
    pEd->paTdQueueHead = gcStaticEdIdentifier;
    pEd->bfSkip = TRUE;
    pEd->paNextEd = 0;
    WRITE_REGISTER_ULONG(HcControlHeadEd(regBase), paEd);
    WRITE_REGISTER_ULONG(HcControlCurrentEd(regBase), paEd);
    pPrevEd = pEd;

    LeaveCriticalSection(&m_csTdListsLock);

    // Now set up the Addr0 device and control endpoint.
    pDev = AddDevice(0, 0, TRUE);
    if (pDev == NULL)
        return(error);
    pEndpt = pDev->ppEndpts[gcEndpoint0Addr];

    errorCode = ALLOC_PHYS_MEM(m_pobMem, sizeof(USB_DEVICE_REQUEST),
                &pSetupBuffer, &paSetupBuffer, 0, NULL);

//    errorCode = m_pobMem->AllocateMemory(sizeof(USB_DEVICE_REQUEST),
//                &pSetupBuffer, &paSetupBuffer);
    if (errorCode != successful)
    {
        DEBUGMSG(ZONE_ERROR,
        (TEXT("OHCD: Couldn't allocate memory for the control queue\r\n")));
        return(errorCode);
    }

    EnterCriticalSection(&m_csOtherListsLock);
    if (m_pFreeTransferHead != NULL)
    {
        pTransfer = m_pFreeTransferHead;
        m_pFreeTransferHead = pTransfer->pNext;
    }
    else
    {
        pTransfer = new STransfer;
    }
    LeaveCriticalSection(&m_csOtherListsLock);

    pTransfer->lpbClientBuffer = NULL;
    pTransfer->dwClientBufferPerms = 0;
    pTransfer->lpCompletionParameter = NULL;
    pTransfer->lpCompletionStartAddress = NULL;
    pTransfer->lpCancelParameter = NULL;
    pTransfer->lpCancelStartAddress = NULL;
    pTransfer->lpvCancelId = NULL;
    pTransfer->pfComplete = NULL;
    pTransfer->pdwBytesTransfered = NULL;
    pTransfer->pdwError = NULL;
    pTransfer->adwIsochErrors = NULL;
    pTransfer->adwIsochLengths = NULL;
    pTransfer->pSetupBuffer = pSetupBuffer;
    pTransfer->cbBuffer1 = 0;
    pTransfer->pDataBuffer1 = NULL;
    pTransfer->paDataBuffer1 = 0;
    pTransfer->cbBuffer2 = 0;
    pTransfer->pDataBuffer2 = NULL;
    pTransfer->paDataBuffer2 = 0;
    pTransfer->aCopyLengths = NULL;
    pTransfer->pCopyLength = NULL;
#ifdef USE_CRITICAL_THREAD
    pTransfer->cCriticalTds = 0;
#endif
    pTransfer->cNormalTds = 0;
    pTransfer->fCanceled = FALSE;
    pTransfer->fActiveCanceled = FALSE;
    pTransfer->fIn = FALSE;
    pTransfer->fCompress = FALSE;
    pTransfer->bufType = gcBufTypeUnused;
    pTransfer->paLastTD = 0;
    pTransfer->pNext = NULL;

    pEndpt->pTransferHead = pTransfer;
    DEBUGMSG(ZONE_FUNCTION,(TEXT("-OHCD::InitializeSchedule\r\n")));
    return(successful);
}



// Don't even try to understand this without first reading the portion of
// the OHCI spec that describes the Interrupt Ed structure.
EError COhcd::InitializeInterruptEds(void)
{
    SEndpointDescriptor * pEd;
    SEndpointDescriptor * pStaticEds[gcIntrNumStaticEds];
    PULONG pEdListHead;
    UINT ed;
    UINT balanceEd = 0;
    UINT extra = 0;
    UINT balance[] =
        { 0, 16, 8, 24, 4, 20, 12, 28, 2, 18, 10, 26, 6, 22, 14, 30 };

    ASSERT(m_pHcca != NULL);

    DEBUGMSG(ZONE_FUNCTION,(TEXT("+OHCD::InitializeInterruptEds\r\n")));
    
    for (ed = 0; ed < gcIntrNumStaticEds; ed++)
    {
        pEd = (SEndpointDescriptor *)m_pFreeTdList;
        m_pFreeTdList = (SGeneralTransferDescriptor *)
            (m_pobMem->PaToVa(m_pFreeTdList->paNextTd));
        // In the static intr eds, the tail pointer points to itself and the
        // head points to null.  This is illegal for OHCI, but since the
        // SKIP bit is set, the HC will never notice.
        pEd->paTdQueueTail = m_pobMem->VaToPa((PBYTE)pEd);
        pEd->paTdQueueHead = gcStaticEdIdentifier;
        pEd->bfSkip = TRUE;
        pStaticEds[ed] = pEd;
        if (ed != 0)
        {
            // Remember, this sets pEd->paNextEd to the Phys Addr of
            // pStaticEds[(ed - 1)/2];
            pEd->paNextEd = pStaticEds[(ed - 1) / 2]->paTdQueueTail;
        }
        else
        {
            // This is the last Interrupt Descriptor.  Isoch descriptors
            // go after these.
            pEd->paNextEd = 0;
            m_paLastIntrEd = m_pobMem->VaToPa((PBYTE)pEd);
        }

        if (ed >= gcIntrNumStaticEds - gcIntrNumListHeads)
        {
            // The final 32 go in the HCCA in a wierd order as defined by
            // the balance array above.
            // To save space, I used a balance array that is 1/2 as big as
            // necessary.  The second set of 16 values are equal to the first
            // set with each being + 1 bigger.
            pEdListHead = (PULONG)(m_pHcca +
                4 * (balance[balanceEd] + extra));
            *pEdListHead = pEd->paTdQueueTail;  //pEd's PhysAddr
            balanceEd++;
            if (balanceEd > 15)
            {
                balanceEd = 0;
                extra = 1;
            }
        }
    }
    DEBUGMSG(ZONE_FUNCTION,(TEXT("-OHCD::InitializeInterruptEds\r\n")));
    return(successful);
}

// Reset and initialize the HC hardware. Will leave the HC in RESET state, call
// EnterOperationalState() to actually start sending SOFs.  
// Note: This function may be called within the context of a power handler routine,
// so cannot make any system calls if m_bPoweredUpAfterPowerDown is set!
EError COhcd::InitializeHardware(void)
{
    REGISTER regBase = m_regBase;
    ULONG physAddr;
    ULONG ulValue;

    // if there was a previous driver changing the frame length then
    // we want to clear this condition when the device goes through
    // a warm reboot.
    DEBUGMSG(ZONE_FUNCTION && !m_bPoweredUpAfterPowerDown,
             (TEXT("+OHCD::InitializeHardware\r\n")));

    m_nAdjustFrame = 0;
    m_fAdjust = FALSE;
    m_hAdjustmentEvent = NULL;

    // These registers need to be saved before we reset the HC
    // because a software reset will zero them.
    // They were already saved by the PowerManagementCallback if this is a warm boot.
    if (!m_bPoweredUpAfterPowerDown) {
        m_paHcBulkHeadEdSave = READ_REGISTER_ULONG(HcBulkHeadEd(regBase));
        m_paHcControlHeadEdSave = READ_REGISTER_ULONG(HcControlHeadEd(regBase));
    }

    // Reset the chip
    ulValue = READ_REGISTER_ULONG(HcCommandStatus(regBase));
    ulValue |= gcHcCommandStatusHCRmask;
    WRITE_REGISTER_ULONG(HcCommandStatus(regBase), ulValue);

    // Wait for HC to complete reset (max 10us)
    while (READ_REGISTER_ULONG(HcCommandStatus(regBase)) & gcHcCommandStatusHCRmask) 
       ;

    // Put the HC into the USB_RESET state (must do this within 1ms of the above)
    ulValue = READ_REGISTER_ULONG(HcControl(regBase));
    ulValue &= ~gcHcControlHCFSmask;
    ulValue |= gcHcControlFSReset;
    WRITE_REGISTER_ULONG(HcControl(regBase), ulValue);

    // Restore the registers we just saved.
    // They will be restored by PowerManagementCallback if this is a warm boot.
    if (!m_bPoweredUpAfterPowerDown) {
        WRITE_REGISTER_ULONG(HcBulkHeadEd(regBase), m_paHcBulkHeadEdSave);
        WRITE_REGISTER_ULONG(HcControlHeadEd(regBase), m_paHcControlHeadEdSave);

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -