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

📄 phcd.cpp

📁 ISP1161 USB Driver under WinCE for StrongARM processor implementation
💻 CPP
📖 第 1 页 / 共 5 页
字号:
    TEXT("GET_DESCRIPTOR"),
    TEXT("SET_DESCRIPTOR"),
    TEXT("GET_CONFIGURATION"),
    TEXT("SET_CONFIGURATION"),
    TEXT("GET_INTERFACE"),
    TEXT("SET_INTERFACE"),
    TEXT("SYNC_FRAME")
};

static const TCHAR *aszPortFeatureStrings[] =
{
    TEXT("PORT_CONNECTION"),
    TEXT("PORT_ENABLE"),
    TEXT("PORT_SUSPEND"),
    TEXT("PORT_OVER_CURRENT"),
    TEXT("PORT_RESET"),
    TEXT("RSVD (5)"),
    TEXT("RSVD (6)"),
    TEXT("RSVD (7)"),
    TEXT("PORT_POWER"),
    TEXT("PORT_LOW_SPEED"),
    TEXT("RSVD (10)"),
    TEXT("RSVD (11)"),
    TEXT("RSVD (12)"),
    TEXT("RSVD (13)"),
    TEXT("RSVD (14)"),
    TEXT("RSVD (15)"),
    TEXT("C_PORT_CONNECTION"),
    TEXT("C_PORT_ENABLE"),
    TEXT("C_PORT_SUSPEND"),
    TEXT("C_PORT_OVER_CURRENT"),
    TEXT("C_PORT_RESET"),
};

static const TCHAR *aszHubFeatureStrings[] =
{
    TEXT("LOCAL_POWER"),
    TEXT("OVER_CURRENT")
};

inline const TCHAR *DecodeRequestString(UCHAR bRequest)
{
    return ((bRequest < NUM_ELEMENTS(aszRequestStrings)) ? 
            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
CPhcd::DecodeControlTransfer(SEndpoint * pEndpt, PUSB_DEVICE_REQUEST pDr)
{
    SDevice *pDev;
    EnterCriticalSection(&m_csDeviceListLock);
    pDev = m_ppDevices[pEndpt->pEd->bfFunctionAddress];
    LeaveCriticalSection(&m_csDeviceListLock);
    if (!pDev)
        return;

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


EError CPhcd::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;

    RETAILMSG(ISPDBG,(TEXT("+PHCD::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("PHCD: 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("PHCD: 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 PHCI, 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("PHCD: 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;
    RETAILMSG(ISPDBG,(TEXT("-PHCD::InitializeSchedule\r\n")));

    return(successful);
}



// Don't even try to understand this without first reading the portion of
// the PHCI spec that describes the Interrupt Ed structure.
EError CPhcd::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(ISPDBG,(TEXT("+PHCD::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 PHCI, 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(ISPDBG,(TEXT("-PHCD::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 CPhcd::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_INIT && !m_bPoweredUpAfterPowerDown,
             (TEXT("+PHCD::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));

⌨️ 快捷键说明

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