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

📄 xsmsl.c

📁 优龙YLP270开发板 光盘自带的BIOS和实验例程源码 强烈推荐
💻 C
📖 第 1 页 / 共 5 页
字号:
            LOGERRORX(ctxP->loggedError, ERR_L_MSL, ERR_S_MSL_RECEIVE, 42,
                      ERR_T_TIMEOUT, 0, 0, 0);
            DM_LEAVE(DM_CW_MSL_1);
            return (0);
        }
    } while (status & RXEMPTY);

    DM_CwDbgPrintf(DM_CW_MSL_1, "wordaccess: %d", wordaccess);
    DM_CwDbgPrintf(DM_CW_MSL_1, "byteaccess: %d", byteaccess);

    DM_CwDbgPrintf(DM_CW_MSL_1, "Read FIFO");

    // Drain the number of words in FIFO.
    while(wordaccess-- > 0)
    {
        // Prepare for timeout by getting the initial time interval.
        start = ostCtxP->getTimer_fnp(ostCtxP);
        // Check RXEMPTY before attempting to write to the FIFO
        do
        {
            // Get the channel status.
            status = XsMslChannelStatus(ctxP, channel_offset);

            // Check RXEMPTY status.
            if (status & RXEMPTY)
            {
                // RX FIFO is empty!
                ctxP->rx_empty_count[channel_offset]++;
            }

            // Check RXWAIT state.
            if (status & RXWAIT)
            {
                // In a RXWAIT!
                ctxP->rx_wait_count[channel_offset]++;
            }

            // Get the current time interval.
            if ((ostCtxP->getDelta_fnp(ostCtxP, start)) > timeout)
            {
                DM_CwDbgPrintf(DM_CW_MSL_1, "Receive timeout!");
                // Display the RXEMPTY count.
                DM_CwDbgPrintf(DM_CW_MSL_1, "RXEMPTY count: %d",
                               ctxP->rx_empty_count[channel_offset]);
                // Display the RXWAIT count.
                DM_CwDbgPrintf(DM_CW_MSL_1, "RXWAIT count: %d",
                           ctxP->rx_wait_count[channel_offset]);
                LOGERRORX(ctxP->loggedError, ERR_L_MSL, ERR_S_MSL_RECEIVE, 44,
                          ERR_T_TIMEOUT, 0, 0, 0);
                DM_LEAVE(DM_CW_MSL_1);
                return (0);
            }
        } while (status & RXEMPTY);

       // Get the data.
        *buffer32P++ = RegsP->BBFIFO[channel_offset];
    }

    // Get the pointer to the remaining bytes.
    buffer8P = (PUCHAR)buffer32P;

    DM_CwDbgPrintf(DM_CW_MSL_1, "buffer8P: 0x%08x", buffer8P);

    // Get the remaining bytes.
    while(byteaccess-- > 0)
    {
        // Prepare for timeout by getting the initial time interval.
        start = ostCtxP->getTimer_fnp(ostCtxP);
        // Check RXEMPTY before attempting to write to the FIFO
        do
        {
            // Get the channel status.
            status = XsMslChannelStatus(ctxP, channel_offset);

            // Check RXEMPTY status.
            if (status & RXEMPTY)
            {
                // RX FIFO is empty!
                ctxP->rx_empty_count[channel_offset]++;
            }

            // Check RXWAIT state.
            if (status & RXWAIT)
            {
                // In a RXWAIT!
                ctxP->rx_wait_count[channel_offset]++;
            }

            // Get the current time interval.
            if ((ostCtxP->getDelta_fnp(ostCtxP, start)) > timeout)
            {
                DM_CwDbgPrintf(DM_CW_MSL_1, "Receive timeout!");
                // Display the RXEMPTY count.
                DM_CwDbgPrintf(DM_CW_MSL_1, "RXEMPTY count: %d",
                               ctxP->rx_empty_count[channel_offset]);
                // Display the RXWAIT count.
                DM_CwDbgPrintf(DM_CW_MSL_1, "RXWAIT count: %d",
                               ctxP->rx_wait_count[channel_offset]);
                LOGERRORX(ctxP->loggedError, ERR_L_MSL, ERR_S_MSL_RECEIVE, 46,
                          ERR_T_TIMEOUT, 0, 0, 0);
                DM_LEAVE(DM_CW_MSL_1);
                return (0);
            }
        } while (status & RXEMPTY);

        // Get the data.
        *buffer8P++ = *single_in_fifo;
    }

    DM_CwDbgPrintf(DM_CW_MSL_1, "buffer8P: 0x%08x", buffer8P);

    // Check if the FIFO was empty.
    if (ctxP->rx_empty_count[channel_offset])
    {
        // Display the RXEMPTY count.
        DM_CwDbgPrintf(DM_CW_MSL_1, "RXEMPTY count: %d",
                       ctxP->rx_empty_count[channel_offset]);
    }

    // Check if we had to wait.
    if (ctxP->rx_wait_count[channel_offset])
    {                
        // Display the RXWAIT count.
        DM_CwDbgPrintf(DM_CW_MSL_1, "RXWAIT count: %d",
                       ctxP->rx_wait_count[channel_offset]);
    }

    DM_CwDbgPrintf(DM_CW_MSL_1, "Read %d bytes", fullness);

    DM_LEAVE(DM_CW_MSL_1);
    return (fullness);
}

/*
*******************************************************************************
*
* FUNCTION:
*    XsMslTransmitPacket
*
* DESCRIPTION:
*    Puts LENGTH worth of data from BUFFERP onto channel channel_offset in Polled
*    mode.  In DMA and interrupt mode, the data is put into the transmit queue.
*    The queue's data transmitted by interrupt or dma handler.
*
* INPUT PARAMETERS:
*    XsMslContextT  ctxP            includes RegsP, XsMslChannelStatusFnP
*    UINT32         channel_offset     transmit channel [1:XSMSL_CHANNEL_NUM]
*    PCHAR          bufferP         pointer to transmit data
*    UINT32         length          length of data to send (in bytes)
*
* RETURNS:
*    Success:    0 (ERR_S_MSL_NONE)
*    Failure:    NonZero: Timeout- data did not send successfully.
*
* GLOBAL EFFECTS:
*    None
*
* ASSUMPTIONS:
*    Channel channel_offset has been properly setup to transmit.
*    In POLLED mode, length <= FIFO_LEN.
*
* CALLS:
*    XsMslChannelStatus, malloc, strncpy, XsDmaWaitUntilStopped
*    XsDmaLoadFirstDescriptorAddr
*
* CALLED BY:
*    Tests
*
* PROTOTYPE:
*    UINT32 XsMslTransmitPacket(XsMslContextT *ctxP, UINT32 channel_offset,
*        PCHAR bufferP, UINT32 length);
*
*******************************************************************************
*/
UINT32 XsMslTransmitPacket(XsMslContextT *ctxP, UINT32 channel_offset,
                           PCHAR bufferP, UINT32 length)
{
    volatile XsMslRegsT* RegsP = (XsMslRegsT*) ctxP->RegsP;
    XsMslLLElemTPT current;
    UINT32 status;
    UINT32 i;
    
    DM_FUNC("XsMslTransmitPacket");
    DM_ENTER(DM_CW_MSL_1);

    DM_CwDbgPrintf(DM_CW_MSL_1, "channel_offset: %d", channel_offset);
    DM_CwDbgPrintf(DM_CW_MSL_1, "bufferP: %x", bufferP);
    DM_CwDbgPrintf(DM_CW_MSL_1, "length: %d", length);

    // Check for Valid Channel
    if (channel_offset >= XSMSL_CHANNEL_NUM)
    {

        DM_CwDbgPrintf(DM_CW_MSL_1, "Bad channel number");

        LOGERRORX(ctxP->loggedError, ERR_L_MSL, ERR_S_MSL_TRANSMIT, 
                    11, ERR_T_BADRANGE, 0, 0, 0);
        DM_LEAVE(DM_CW_MSL_1);
        return (ctxP->loggedError);
    }

    DM_CwDbgPrintf(DM_CW_MSL_1, "tx_fifoservice: %x",
                   ctxP->tx_fifoservice[channel_offset]);

    if (ctxP->tx_fifoservice[channel_offset] == TXSERVICE_NONE)
    {
        DM_CwDbgPrintf(DM_CW_MSL_1, "Transmit packet polled");

        // Write to the transmit FIFO.
        status = WriteTxFifo(ctxP, channel_offset, bufferP, length);
        if (status)
        {
            LOGERRORX(ctxP->loggedError, ERR_L_MSL, ERR_S_MSL_TRANSMIT, 
                      47, ERR_T_NO_MEM_AVAIL, 0, 0, 0);
            current->next = NULL;
            DM_LEAVE(DM_CW_MSL_1);
            return (ctxP->loggedError);
        }

        // Write anything to BBEOM to signify EOM
        RegsP->BBEOM[channel_offset] = 0x0;
    }
    else if (ctxP->tx_fifoservice[channel_offset] == TXSERVICE_INT)// INT case
    {
        DM_CwDbgPrintf(DM_CW_MSL_1, "Transmit packet interrupt");

        if (ctxP->tx_llfirst[channel_offset] != NULL)
        {

            DM_CwDbgPrintf(DM_CW_MSL_1, "Create transmit chain");

            // create a LL Elem at then end of the list
            current = ctxP->tx_lllast[channel_offset];
            if ((current->next = (XsMslLLElemTPT) malloc(sizeof(XsMslLLElemT))) == NULL)
            { //FATAL ERROR - unable to setup buffer
                LOGERRORX(ctxP->loggedError, ERR_L_MSL, ERR_S_MSL_TRANSMIT, 
                        12, ERR_T_NO_MEM_AVAIL, 0, 0, 0);
                current->next = NULL;
                DM_LEAVE(DM_CW_MSL_1);
                return (ctxP->loggedError);
            }
            current = current->next;
            current->length = length;
            current->position = 0;
            current->next = NULL;

            DM_CwDbgPrintf(DM_CW_MSL_1, "Create transmit buffer");

            if ((current->buffer = (PCHAR) malloc((length+1)*sizeof(CHAR))) == NULL)
            { //FATAL ERROR - unable to setup buffer
                LOGERRORX(ctxP->loggedError, ERR_L_MSL, ERR_S_MSL_TRANSMIT, 
                        13, ERR_T_NO_MEM_AVAIL, 0, 0, 0);
                free(current);
                ctxP->tx_lllast[channel_offset] = NULL;
                DM_LEAVE(DM_CW_MSL_1);
                return (ctxP->loggedError);
            }
        }
        else
        {
            DM_CwDbgPrintf(DM_CW_MSL_1, "Create first element of list");

            // list is empty, create first LL Elem
            if ((current = (XsMslLLElemTPT) malloc(sizeof(XsMslLLElemT))) == NULL)
            { //FATAL ERROR - unable to setup buffer
                LOGERRORX(ctxP->loggedError, ERR_L_MSL, ERR_S_MSL_TRANSMIT,
                        14, ERR_T_NO_MEM_AVAIL, 0, 0, 0);
                DM_LEAVE(DM_CW_MSL_1);
                return (ctxP->loggedError);
            }
            current->length = length;
            current->position = 0;
            current->next = NULL;

            DM_CwDbgPrintf(DM_CW_MSL_1, "Create transmit buffer");

            if ((current->buffer = (PCHAR) malloc((length+1)*sizeof(CHAR))) == NULL)
            { //FATAL ERROR - unable to setup buffer
                LOGERRORX(ctxP->loggedError, ERR_L_MSL, ERR_S_MSL_TRANSMIT,
                        15, ERR_T_NO_MEM_AVAIL, 0, 0, 0);
                free(current);
                DM_LEAVE(DM_CW_MSL_1);
                return (ctxP->loggedError);
            }
            ctxP->tx_llfirst[channel_offset] = current;
            ctxP->tx_lllast[channel_offset] = current;
        }

        DM_CwDbgPrintf(DM_CW_MSL_1, "Copy transmit buffer");

        // copy data to last elem in LL
        for(i = 0; i < length; ++i)
            current->buffer[i] = bufferP[i];

        DM_CwDbgPrintf(DM_CW_MSL_1, "Calling XsMslEnableTxService");

        if ((RegsP->BBCFG[channel_offset] & TX_SERVICE_MSK) != TXSERVICE_INT)
            XsMslEnableTxService(ctxP, channel_offset);
    }
    else // DMA case
    {
        DM_CwDbgPrintf(DM_CW_MSL_1, "Transmit packet DMA");

        // Setup the memory to memory transfer to copy the user's buffer
        // to the transmit descriptor. Replace the source descriptor buffer
        // with the user's buffer.
        ctxP->tx1_firstDescVtP[channel_offset]->sourceVirtualAddr = bufferP;
        ctxP->tx1_firstDescVtP[channel_offset]->sourcePhysicalAddr = (UINT32) bufferP;

        // Now replace the target descriptor buffer with the transmit descriptor.
        ctxP->tx1_firstDescVtP[channel_offset]->targetVirtualAddr =
            ctxP->tx2_firstDescVtP[channel_offset]->sourceVirtualAddr;
        ctxP->tx1_firstDescVtP[channel_offset]->targetPhysicalAddr =
            ctxP->tx2_firstDescVtP[channel_offset]->sourcePhysicalAddr;
        ctxP->tx_interrupt_channel = 1U << channel_offset;

        DM_CwDbgPrintf(DM_CW_MSL_1, "XsDmaLoadFirstDescriptorAddr");

        // Reload the updated memory to memory descriptor.
        XsDmaLoadFirstDescriptorAddr(ctxP->dma_tx_channel1[channel_offset],
                                     ctxP->tx1_firstDescVtP[channel_offset]); 

        DM_CwDbgPrintf(DM_CW_MSL_1, "Calling XsDmaStart");

        // Start the DMA channel to copy the user's data.
        status = XsDmaStart(ctxP->dma_tx_channel1[channel_offset]);
        if (status != ERR_NONE)
        {
            LOGERRORX(ctxP->loggedError, ERR_L_MSL, ERR_S_MSL_TRANSMIT,
                    16, ERR_T_ILLPARAM, 0, 0, 0);
            DM_LEAVE(DM_CW_MSL_1);
            return (ctxP->loggedError);
        }

        // Need to finish dma transfer before transmitting the data.
        status = XsDmaWaitUntilStopped(ctxP->dma_tx_channel1[channel_offset]);
        if(status)
        {
            LOGERRORX(ctxP->loggedError, ERR_L_MSL, ERR_S_MSL_RECEIVE,
                      41, ERR_T_TIMEOUT, 0, 0, 0);        
            DM_LEAVE(DM_CW_MSL_1);
            return (ctxP->loggedError);
        }

        // Enable the MSL channel to send the packet.
        DM_CwDbgPrintf(DM_CW_MSL_1, "Calling XsMslEnableTxService");
        XsMslEnableTxService(ctxP, channel_offset);

        // Wait for the transmit callback to complete.
        while (!ctxP->xferTxComplete[channel_offset])
        {
            DM_WaitUs(4);
        }

        // Clear the complete flag.
        ctxP->xferTxComplete[channel_offset] = FALSE;
    }
    
    DM_LEAVE(DM_CW_MSL_1);
    return (ERR_S_MSL_NONE);
}

/*
*******************************************************************************
*
* FUNCTION:
*    XsMslReceivePacket
*
* DESCRIPTION:
*    Gets LENGTH worth of data from channel channel_offset and returns in BUFFERP.
*    IN DMA/INT case, if intermediate buffer does not have LENGTH bytes,
*    function will return a NULL char and error message.
*
* INPUT PARAMETERS:
*    XsMslContextT  ctxP            
*    UINT32         channel_offset     receive channel [1:XSMSL_CHANNEL_NUM]
*    PCHAR          bufferP         pointer to buffer
*    UINT32         length          length of data expected (in bytes)
*
* RETURNS:
*    Success:    0 (ERR__S_MSL_NONE)
*    Failure:    NonZero
*                BUFFERP set to NULL.
*
* GLOBAL EFFECTS:
*    None
*
* ASSUMPTIONS:
*    Channel channel_offset has been properly setup to receive.
*    Limit of data transfered in Polled Mode is 1 FIFO_LEN
*
* CALLS:
*    XsMslChannelStatus, XsDmaLoadFirstDescriptorAddr, strncpy, free,
*    XsDmaWaitUntilStopped
*

⌨️ 快捷键说明

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