📄 xsusb.c
字号:
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, ¤tP->sourceVirtualAddr, (PVOID)¤tP->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)®sP->UDCCS1;
currentP->targetPhysicalAddr = (UINT)®sP->UDCCS1;
break;
case Endpoint3:
currentP->targetVirtualAddr = (PVOID)®sP->UDCCS3;
currentP->targetPhysicalAddr = (UINT)®sP->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 + -