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

📄 xtemac_fifo.c

📁 xilinx trimode mac driver for linux
💻 C
📖 第 1 页 / 共 3 页
字号:
        Write64_Unaligned(Fptr, BufPtr, PartialBytes);        Write64_Aligned(Fptr, (u32*)((u32)BufPtr + PartialBytes),                        ByteCount - PartialBytes);    }    /* Case 3: No alignment to take advantage of     *     *    1. Read FIFOs using the slower method.     */    else    {        Write64_Unaligned(Fptr, BufPtr, ByteCount);    }    /* If TxBytes is non-zero then the caller wants to transmit data from the     * FIFO     */    if (Eop == XTE_END_OF_PACKET)    {        /* Push the hold to the FIFO if data is present */        if (!mHoldS_IsEmpty(Fptr))        {            mPush64(Fptr);            mHoldS_SetEmpty(Fptr);        }    }    return(XST_SUCCESS);}/******************************************************************************** Algorithm to read from a 64 bit wide receive packet FIFO with through the* holding buffer.** @param Fptr is a pointer to a Temac FIFO instance to worked on.* @param BufPtr is the destination address on any alignment* @param ByteCount is the number of bytes to transfer** @return XST_SUCCESS if transfer completed or XST_NO_DATA if the amount of*         data being buffered by the driver plus the amount of data in the*         packet FIFO is not enough to satisfy the number of bytes requested*         by the ByteCount parameter.*******************************************************************************/static XStatus Read_64(XTemac_PacketFifo *Fptr, void *BufPtr,                       u32 ByteCount, int Eop){    unsigned BufAlignment = (unsigned)BufPtr & 3;    unsigned PartialBytes;    unsigned MaxBytes;    unsigned HoldAlignment = mHold_GetIndex(Fptr);    /* Determine how many bytes can be read from the packet FIFO */    MaxBytes = XPF_V200A_COUNT_MASK & XPF_V200A_GET_COUNT(&Fptr->Fifo);    MaxBytes *= PFIFO_64BIT_WIDTH_BYTES;    /* Case 1: Buffer aligned on 4-byte boundary and Hold is empty     *     *   1. Read all bytes using the fastest transfer method     */    if ((BufAlignment == 0) && (mHoldR_IsEmpty(Fptr)))    {        /* Enough data in fifo? */        if (ByteCount > MaxBytes)        {            return(XST_NO_DATA);        }        Read64_Aligned(Fptr, (u32*)BufPtr, ByteCount);    }    /* Case 2: Buffer and Hold are byte aligned with each other     *     *   1. Transfer enough bytes from the Hold to the buffer to trigger a     *      read from the FIFO.     *     *   2. The state of the buffer and Hold are now as described by Case 1 so     *      read remaining bytes using the fastest transfer method     */    else if (BufAlignment == (HoldAlignment % PFIFO_64BIT_WIDTH_BYTES))    {        PartialBytes = PFIFO_64BIT_WIDTH_BYTES - HoldAlignment;        if (ByteCount < PartialBytes)        {            PartialBytes = ByteCount;        }        /* Enough data in fifo? Must account for the number of bytes the driver         * is currently buffering         */        if (ByteCount > (MaxBytes + PartialBytes))        {            return(XST_NO_DATA);        }        Read64_Unaligned(Fptr, BufPtr, PartialBytes);        Read64_Aligned(Fptr, (u32*)((u32)BufPtr + PartialBytes),                       ByteCount - PartialBytes);    }    /* Case 3: No alignment to take advantage of     *     *    1. Read FIFOs using the slower method.     */    else    {        /* Enough data in fifo? Must account for the number of bytes the driver         * is currently buffering         */        PartialBytes = PFIFO_64BIT_WIDTH_BYTES - HoldAlignment;        if (ByteCount > (MaxBytes + PartialBytes))        {            return(XST_NO_DATA);        }        Read64_Unaligned(Fptr, BufPtr, ByteCount);    }    /* If this marks the end of packet, then dump any remaining data in the     * hold. The dumped data in this context is meaningless.     */    if (Eop == XTE_END_OF_PACKET)    {        mHoldR_SetEmpty(Fptr);    }    return(XST_SUCCESS);}/******************************************************************************** Write to the 64 bit holding buffer. Each time it becomes full, then it is* pushed to the transmit FIFO.** @param F is a pointer to the packet FIFO instance to be worked on.* @param BufPtr is the source buffer address on any alignment* @param ByteCount is the number of bytes to transfer********************************************************************************/static void Write64_Unaligned(XTemac_PacketFifo *F,                              void *BufPtr, u32 ByteCount){    u8* SrcPtr = (u8*)BufPtr;    unsigned FifoTransfersLeft;    unsigned PartialBytes;    unsigned BytesLeft;    unsigned i;    /* Stage 1: The hold may be partially full. Write enough bytes to it to     * cause a push to the FIFO     */    /* Calculate the number of bytes needed to trigger a push, if not enough     * bytes have been specified to cause a push, then adjust accordingly     */    i = mHold_GetIndex(F);    PartialBytes = PFIFO_64BIT_WIDTH_BYTES - i;    if (PartialBytes > ByteCount)    {        PartialBytes = ByteCount;    }    /* Calculate the number of bytes remaining after the first push */    BytesLeft = ByteCount - PartialBytes;    /* Write to the hold and advance its index */    mHold_Advance(F, PartialBytes);    while (PartialBytes--)    {        mHold_CopyIn(F, i, *SrcPtr);        SrcPtr++;        i++;    }    /* Push to fifo if needed */    if (mHoldS_IsFull(F))    {        mPush64(F);        mHoldS_SetEmpty(F);    }    /* No more data to process */    if (!BytesLeft)    {        return;    }    /* Stage 2: The hold is empty now, if any more bytes are left to process, then     * it will begin with nothing in the hold. Use the hold as a temporary storage     * area to contain the data.     *     * The hold is filled then pushed out to the FIFOs a number of times based on     * how many bytes are left to process.     */    /* Calculate the number of times a push will need to occur */    FifoTransfersLeft = BytesLeft / PFIFO_64BIT_WIDTH_BYTES;    /* Calculate the number of partial bytes left after this stage */    PartialBytes = BytesLeft - (FifoTransfersLeft * PFIFO_64BIT_WIDTH_BYTES);    /* Write to the hold and push data to the FIFO */    while (FifoTransfersLeft--)    {        for (i=0; i<PFIFO_64BIT_WIDTH_BYTES; i++)        {            mHold_CopyIn(F, i, *SrcPtr);            SrcPtr++;        }        mPush64(F);    }    /* No more data to process     * HoldIndex was left at 0 by stage 1, at this point, that is     * still the correct value.     */    if (!PartialBytes)    {        return;    }    /* Stage 3: All that is left is to fill the hold with the remaining data     * to be processed. There will be no push to the FIFO because there is not     * enough data left to cause one.     */    /* Write to the hold and push data to the FIFO */    for (i=0; i<PartialBytes; i++)    {        mHold_CopyIn(F, i, *SrcPtr);        SrcPtr++;    }    /* Set the hold's index to its final correct value */    mHold_SetIndex(F, PartialBytes);}/******************************************************************************** Write directly to the 64 bit wide transmit FIFO from an aligned source* buffer. Leftover bytes are written to the holding buffer.** @param F is a pointer to the packet FIFO instance to be worked on.* @param BufPtr is the source buffer address on 32-bit alignment* @param ByteCount is the number of bytes to transfer********************************************************************************/static void Write64_Aligned(XTemac_PacketFifo *F,                            u32 *BufPtr, u32 ByteCount){    unsigned FifoTransfersLeft = ByteCount / PFIFO_64BIT_WIDTH_BYTES;    unsigned PartialBytes      = ByteCount & (PFIFO_64BIT_WIDTH_BYTES - 1);    /* Direct transfer */    while (FifoTransfersLeft--)    {        mWriteFifo64(F, BufPtr);        BufPtr += 2;    }    /* Leftover bytes are left in the holding area */    if (PartialBytes)    {        Write64_Unaligned(F, BufPtr, PartialBytes);    }}/******************************************************************************** Read into the 64 bit holding buffer from the receive packet FIFO.* Each time the holding buffer becomes full, then it is flushed to the* provided buffer.** @param F is a pointer to the packet FIFO instance to be worked on.* @param BufPtr is the destination buffer address on any alignment* @param ByteCount is the number of bytes to transfer********************************************************************************/static void Read64_Unaligned(XTemac_PacketFifo *F,                             void *BufPtr, u32 ByteCount){    u8* DestPtr = (u8*)BufPtr;    unsigned FifoTransfersLeft;    unsigned PartialBytes;    unsigned BytesLeft;    unsigned i;    /* Stage 1: The hold may have some residual bytes that must be flushed     * to the buffer before anything is read from the FIFO     */    /* Calculate the number of bytes to flush to the buffer from the hold.     * If the number of bytes to flush is greater than the "Bytes" requested,     * then adjust accordingly.     */    i = mHold_GetIndex(F);    PartialBytes = PFIFO_64BIT_WIDTH_BYTES - i;    if (PartialBytes > ByteCount)    {        PartialBytes = ByteCount;    }    /* Calculate the number of bytes remaining after flushing to the buffer */    BytesLeft = ByteCount - PartialBytes;    /* Move the hold's index forward */    mHold_Advance(F, PartialBytes);    /* Copy bytes */    while (PartialBytes--)    {        mHold_CopyOut(F, i, *DestPtr);        i++;        DestPtr++;    }    /* No more data to process */    if (!BytesLeft)    {        return;    }    /* Stage 2: The hold is empty now, if any more bytes are left to process, then     * it will begin with nothing in the hold. Use the hold as a temporary storage     * area to contain the data.     *     * The hold is filled with FIFO data, then that data is written to the buffer.     * Do this FifoTransfersLeft times     */    /* Calculate the number of times a push will need to occur */    FifoTransfersLeft = BytesLeft / PFIFO_64BIT_WIDTH_BYTES;    /* Calculate the number of partial bytes left after this stage */    PartialBytes = BytesLeft - (FifoTransfersLeft * PFIFO_64BIT_WIDTH_BYTES);    /* Write to the hold and push data to the FIFO */    while (FifoTransfersLeft--)    {        /* Load the hold with the next data set from the FIFO */        mPop64(F);        /* Write hold to buffer */        for (i=0; i<PFIFO_64BIT_WIDTH_BYTES; i++)        {            mHold_CopyOut(F, i, *DestPtr);            DestPtr++;        }    }    /* No more data to process     * After processing full FIFO chunks of data, the hold is empty at this     * point     */    if (!PartialBytes)    {        return;    }    /* Stage 3: All that is left is to fill the hold one more time with FIFO     * data, then write the remaining requested bytes to the buffer     */    /* Get FIFO data */    mPop64(F);    /* Copy bytes from the hold to the buffer */    for (i=0; i<PartialBytes; i++)    {        mHold_CopyOut(F, i, *DestPtr);        DestPtr++;    }    /* Set the hold's index to its final correct value */    mHold_SetIndex(F, PartialBytes);}/******************************************************************************** Read directly from the 64 bit wide receive FIFO into an aligned destination* buffer. Leftover bytes are written to the holding buffer.** @param F is a pointer to the packet FIFO instance to be worked on.* @param BufPtr is the destination buffer address on 32-bit alignment* @param ByteCount is the number of bytes to transfer********************************************************************************/static void Read64_Aligned(XTemac_PacketFifo *F,                           u32 *BufPtr, u32 ByteCount){    unsigned FifoTransfersLeft = ByteCount / PFIFO_64BIT_WIDTH_BYTES;    unsigned PartialBytes      = ByteCount & (PFIFO_64BIT_WIDTH_BYTES - 1);    /* Direct transfer */    while (FifoTransfersLeft--)    {        mReadFifo64(F, BufPtr);        BufPtr += 2;    }    /* Leftover bytes are left in the holding area */    if (PartialBytes)    {        Read64_Unaligned(F, BufPtr, PartialBytes);    }}

⌨️ 快捷键说明

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