📄 xtemac_fifo.c
字号:
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 + -