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

📄 xsusb.c

📁 这是一个USB的驱动程序
💻 C
📖 第 1 页 / 共 5 页
字号:
    XsDmaDescriptorElementsT* oldOutP; 
    XsDmaDescriptorElementsT* currentInP = firstDescInVtP;
    PCHAR sourceVirtualAddrP = (PCHAR) firstDescInVtP->sourceVirtualAddr; 
    XsDmaDescriptorElementsT* nextInP;
    INT descrType = 0;
    INT numBytes;

    if (firstDescInVtP == NULL || firstDescOutVtP == NULL) 
      return;

    if (shortPacket)
    {
        do
        {
            oldOutP = currentOutP;
            nextOutP = currentOutP->nextVirtualAddr;
            nextInP = currentInP->nextVirtualAddr;
            if (!(descrType & 0x1))
            {
                numBytes = XsDmaGetNumBytes (currentOutP);
                memcpy (currentInP->sourceVirtualAddr, 
                        currentOutP->targetVirtualAddr, numBytes);
            }
            currentOutP = nextOutP;
            currentInP = nextInP;
            descrType++;
        } while (oldOutP != currentOutP);  // If chain ends by pointing to itself
    }
    else
    {
        do
        {
            oldOutP = currentOutP;
            nextOutP = currentOutP->nextVirtualAddr;
            numBytes = XsDmaGetNumBytes (currentOutP);
/*
            DM_Printf("Num bytes: %x", numBytes); 
            DM_Printf("In: %x", sourceVirtualAddrP); 
            DM_Printf("Out: %x", currentOutP->targetVirtualAddr);
*/            
            memcpy (sourceVirtualAddrP, currentOutP->targetVirtualAddr, numBytes);
            sourceVirtualAddrP = sourceVirtualAddrP + numBytes;
            currentOutP = nextOutP;
        } while (oldOutP != currentOutP);  // If chain ends by pointing to itself
    }


}


UINT32 XsUdcModifyEvenDescriptorsDma (XsDmaDescriptorElementsTPT rootDescriptorP, 
                                      UdcEndpointsT epNum)
{
    UdcContextT * ctxP = &UsbDeviceController;
    UdcRegsT * regsP = (UdcRegsT *)ctxP->regsP;
    UINT32 status = ERR_NONE;
    XsDmaDescriptorElementsT* currentP = rootDescriptorP; // Virtual address!
    XsDmaDescriptorElementsT* nextP ; // Virtual address!
    XsDmaDescriptorElementsT* oldP ; // Virtual address!
    INT descrType = 0;
    PUINT dataP;

    if (rootDescriptorP)
    {
        // Perform specified operation on each descriptor in chain.
        do
        {
            oldP  = currentP;
            nextP = currentP->nextVirtualAddr;
            // Check if this is even decsriptor 
            if (descrType & 0x1)
            {
                // Mark source type as "Byte"
                currentP->sourceDeviceType = XSDMA_DT_BYTE_TYPE;
                // Mark target type as "Cntl"
                currentP->targetDeviceType = XSDMA_DT_CTRL_TYPE;
                // Source is a single byte used to set the control register 
                // to send a short packet.
                // This needs to be 16 bytes alined in the memory
                status = mallocx(1, &currentP->sourceVirtualAddr, (PVOID)&currentP->sourcePhysicalAddr);
                if (status)
                  return status;
                dataP = currentP->sourceVirtualAddr;
                *dataP = UDC_UDCCS_TSP_IN;

                // Modify a command register settings
                currentP->commandRegister = (0x1 << DCMD_LEN_SHIFT // transfer length one byte
                                          & ~DCMD_INCTRGADDR   // do not incr. target
                                          & ~DCMD_INCSRCADDR   // do not incr. source
                                          & ~DCMD_FLOWSRC      // no flow on source
                                          //& ~DCMD_FLOWTRG      // no flow on target
                                          | DCMD_FLOWTRG
                                          | DCMD_SIZE_32       // 32 byte burst
                                          | DCMD_WIDTH_1       // one byte width
                                          );

                // Set the target address to point to the EP's UDCCSx register
                switch (epNum)
                {
                    case Endpoint1:
                        currentP->targetVirtualAddr = (PVOID)&regsP->UDCCS1;
                        currentP->targetPhysicalAddr = (UINT)&regsP->UDCCS1;
                        break;
                    case Endpoint3:
                        currentP->targetVirtualAddr = (PVOID)&regsP->UDCCS3;
                        currentP->targetPhysicalAddr = (UINT)&regsP->UDCCS3;
                        break;
                }
            }                                                               
            descrType++;
            currentP = nextP;
        } while (oldP != currentP);  // If chain ends by pointing to itself
    }

    return (status);
}


XsDmaDescriptorElementsTPT XsUdcCreateDescriptorChainDma (INT channel,
                                                       INT numDescriptors,
                                                       UINT xferByteCount,
                                                       UdcEndpointsT epNum)
{
    UINT32 status = ERR_NONE;
    XsDmaDescriptorElementsTPT rootDescP;

    rootDescP = XsDmaCreateBareDescChain (channel, numDescriptors, xferByteCount);
    if (rootDescP)
    {
        XsUdcModifyEvenDescriptorsDma (rootDescP, epNum);
        status = XsDmaPopulateChainWithBufs (rootDescP);
    }            
    return(rootDescP);
    
}

UINT32 XsUdcConfigureDmaIn (XsDmaChannelPriorityT desiredPriority,
                            XsDmaDeviceNamesT deviceName, 
                            BOOL isTarget,
                            XsDmaDescriptorElementsTPT * firstDescVtP,
                            INT numDescriptors,
                            UINT xferByteCount,
                            PINT returnChannelNumP) 
{
    UINT32  error = FALSE;
    INT channelNum;
    INT epNum;
    XsDmaChannelStatusT status;

    // Request a free channel from DMA service
    channelNum = XsDmaGetFreeChannel (desiredPriority, 
                                      deviceName, 
                                      isTarget,
                                      &status); 

    // Check if the channel has not been given
    if (channelNum == XSDMA_CHANNEL_UNAVAILABLE)
    {
        // Error: no channel has been given
        return (error = XSDMA_CHANNEL_UNAVAILABLE);
    }

    // Check if the requested priority has not been satisfied 
    if (status == XSDMA_CS_NONE_AVAILABLE)
    {
        // Error: no channel has been given
        return (error = XSDMA_CS_NONE_AVAILABLE);
    }

    *returnChannelNumP = channelNum;


    if (deviceName == XSDMA_DN_USB_EP1)
      epNum = Endpoint1;
    else if (deviceName == XSDMA_DN_USB_EP3)
      epNum = Endpoint3;

    // Setup the descriptor chain of N descriptors and get the pointer
    // that points to the beginning of the descriptors chain
    *firstDescVtP = XsUdcCreateDescriptorChainDma (channelNum, 
                                                   numDescriptors,
                                                   xferByteCount,
                                                   epNum);
    if (*firstDescVtP == NULL)
    {
        // Error: in descriptor chain setup
        return (error = -1);
    }

    // Load the first descriptor adderess into the DDADR register
    // for the specified DMA channel.
    error = XsDmaLoadFirstDescriptorAddr (channelNum, *firstDescVtP);
    if (error == ERR_T_ILLPARAM)
    {
        return error;
    }
     
    // Set the Run bit in the DCSR for the specified DMA channel.
/*
    error = XsDmaStart (channelNum);
    if (error != ERR_NONE)
    {
        return error;
    }
*/                        
    return error;
} 

/*
******************************************************************************
*
* FUNCTION:         XsUdcSetupInEndpointDma
*
* DESCRIPTION:      This function will setup DMA to service BULK_IN and ISO-IN Endpoints.
*
* INPUT PARAMETERS: ctxP is a pointer to UDC's context structure
*                   UdcEndpointsT inEpNum
*                   UdcEndpointsT outEpNum
*                   INT numBytes - used to allocate memory
*                   INT maxPacketSize - max. packet size for the endpoint
*
* RETURNS:          0   if successful
*                   UINT32 error   if not
*
* GLOBAL EFFECTS:   The Endpoint's interrupt service request will be disabled and
*					the endpoint uses DMA transfer.
*
* ASSUMPTIONS:      The packet size is equal to the max. packet size for the transfer
*
* CALLS:            
*
* CALLED BY:        
*
* PROTOTYPE:        UINT32 XsUdcSetupInEndpointDma (UdcContextT * ctxP, 
*                                                UdcEndpointsT inEpNum,
*                                                UdcEndpointsT outEpNum,
*                                                numBytes, 
*                                                maxPacketSize)
*
*******************************************************************************
*/
static
UINT32 XsUdcSetupInEndpointDma (UdcContextT * ctxP, 
                              UdcEndpointsT inEpNum, 
                              UdcEndpointsT outEpNum, 
                              INT numBytesXfer, 
                              INT maxPacketSize)
{
    volatile UdcRegsT * regsP = (UdcRegsT *)ctxP->regsP;
    XsDmaDeviceNamesT deviceName;
    INT numDescriptors;
    INT numBytes;
    UINT error = FALSE;
    INT shortPacket;

    // Make sure that the packet size large than 32 bytes
    if (maxPacketSize < 32)
    {
        LOGERROR(ctxP->loggedError, ERR_L_XSUDC,
             ERR_S_XSUDC_DMA_IN, ERR_T_ILLPARAM, 0, 0, 0);
        return (ctxP->loggedError);
    }

    if (inEpNum != 0)
    {
        // Disable endpoint's interrupt service
        XsUdcDisableEndpointInt (ctxP, inEpNum);
        
        switch (inEpNum)
        {
            case Endpoint1:
                // Check for errors
                if (regsP->UDCCS1 & UDC_UDCCS_TPC_IN)
                {
                    // Clear UDCCS-TPC bit
                    regsP->UDCCS1 = (regsP->UDCCS1 & 0x20) | UDC_UDCCS_TPC_IN;
	                XsUdcClearEndpointInt (ctxP, inEpNum);

                    // If STALL is set just return and wait for CLEAR_FEATURE 
                    // to clear the stall bit
                    if (regsP->UDCCS1 & UDC_UDCCS_SST_IN)
                    {
                        LOGERROR(ctxP->loggedError, ERR_L_XSUDC,
                            ERR_S_XSUDC_DMA_IN, ERR_T_UNEXPECTED, 0, 0, 0);
                        return (ctxP->loggedError);
                    }
                    // If underrun bit is set clear it
                    if (regsP->UDCCS1 & UDC_UDCCS_TUR_IN)
                    {
                        regsP->UDCCS1 = (regsP->UDCCS1 & 0x20) | UDC_UDCCS_TUR_IN;
                    }
                }

                deviceName = XSDMA_DN_USB_EP1;
                if (maxPacketSize == BULK_IN_LENGTH)
                {
                    numDescriptors = 2;
                    numBytes = numBytesXfer;
                    shortPacket = FALSE;
                }
                else
                {
                    numDescriptors = (numBytesXfer/maxPacketSize + 
                                             (numBytesXfer % maxPacketSize ? 1 : 0));
                    numBytes = numBytesXfer/numDescriptors;
                    numDescriptors = numDescriptors * 2;
                    shortPacket = TRUE;
                }
                break;
            case Endpoint3:
                // Check for errors
                if (regsP->UDCCS3 & UDC_UDCCS_TPC_IN)
                {
                    // Clear UDCCS-TPC bit
                    regsP->UDCCS3 = (regsP->UDCCS3 & 0x20) | UDC_UDCCS_TPC_IN;
	                XsUdcClearEndpointInt (ctxP, inEpNum);
	
                    // If underrun bit is set clear it
                    if (regsP->UDCCS3 & UDC_UDCCS_TUR_IN)
                    {
                        regsP->UDCCS3 = (regsP->UDCCS3 & 0x20) | UDC_UDCCS_TUR_IN;
                    }
                }

                deviceName = XSDMA_DN_USB_EP3;
                if (maxPacketSize == ISO_IN_LENGTH)
                {
                    numDescriptors = 2;
                    numBytes = numBytesXfer;
                    shortPacket = FALSE;
                }
                else
                {
                    numDescriptors = (numBytesXfer/maxPacketSize + 
                                              (numBytesXfer % maxPacketSize ? 1 : 0));
                    numBytes = numBytesXfer/numDescriptors;
                    numDescriptors = numDescriptors * 2;
                    shortPacket = TRUE;
                }
                break;
        }

        // Configure the DMA channel to be used to service IN Endpoint's FIFO:
        error = XsUdcConfigureDmaIn (XSDMA_CH_PR_LOW,
                                deviceName, 
                                TRUE,
                                &ctxP->EPXferTable[inEpNum].firstDescVtP,
                                numDescriptors,
                                numBytes,
                                (PINT)&ctxP->EPXferTable[inEpNum].dmaChannel);

        if (error != ERR_NONE)
          return (error);

        // if Loopback is enabled, copy the received data to the allocated transmit buffers 
        if (ctxP->EPXferTable[inEpNum].enableLoopback == TRUE)
        {
            XsUdcCopyDataOutToIn (ctxP->EPXferTable[inEpNum].firstDescVtP, 
                                  ctxP->EPXferTable[outEpNum].firstDescVtP,
                                  shortPacket);
        }
        else 
        {
		    // Fill transmit buffers with a known pattern
		    FillTxBufferSerial (ctxP->EPXferTable[inEpNum].firstDescVtP, 
		                        1,
		                        numBytes,
		                        0x56);
        }

        // Set the Run bit in the DCSR for the specified DMA channel.

⌨️ 快捷键说明

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