aboutsummaryrefslogtreecommitdiff
path: root/board/xilinx/common/xpacket_fifo_v1_00_b.c
blob: ae2d6d43c54cb8f2778722a8abbb8bf2a76559c5 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
/******************************************************************************
*
*     Author: Xilinx, Inc.
*
*
*     This program is free software; you can redistribute it and/or modify it
*     under the terms of the GNU General Public License as published by the
*     Free Software Foundation; either version 2 of the License, or (at your
*     option) any later version.
*
*
*     XILINX IS PROVIDING THIS DESIGN, CODE, OR INFORMATION "AS IS" AS A
*     COURTESY TO YOU. BY PROVIDING THIS DESIGN, CODE, OR INFORMATION AS
*     ONE POSSIBLE IMPLEMENTATION OF THIS FEATURE, APPLICATION OR STANDARD,
*     XILINX IS MAKING NO REPRESENTATION THAT THIS IMPLEMENTATION IS FREE
*     FROM ANY CLAIMS OF INFRINGEMENT, AND YOU ARE RESPONSIBLE FOR OBTAINING
*     ANY THIRD PARTY RIGHTS YOU MAY REQUIRE FOR YOUR IMPLEMENTATION.
*     XILINX EXPRESSLY DISCLAIMS ANY WARRANTY WHATSOEVER WITH RESPECT TO
*     THE ADEQUACY OF THE IMPLEMENTATION, INCLUDING BUT NOT LIMITED TO ANY
*     WARRANTIES OR REPRESENTATIONS THAT THIS IMPLEMENTATION IS FREE FROM
*     CLAIMS OF INFRINGEMENT, IMPLIED WARRANTIES OF MERCHANTABILITY AND
*     FITNESS FOR A PARTICULAR PURPOSE.
*
*
*     Xilinx hardware products are not intended for use in life support
*     appliances, devices, or systems. Use in such applications is
*     expressly prohibited.
*
*
*     (c) Copyright 2002-2004 Xilinx Inc.
*     All rights reserved.
*
*
*     You should have received a copy of the GNU General Public License along
*     with this program; if not, write to the Free Software Foundation, Inc.,
*     675 Mass Ave, Cambridge, MA 02139, USA.
*
******************************************************************************/
/*****************************************************************************/
/*
*
* @file xpacket_fifo_v1_00_b.c
*
* Contains functions for the XPacketFifoV100b component. See xpacket_fifo_v1_00_b.h
* for more information about the component.
*
* <pre>
* MODIFICATION HISTORY:
*
* Ver   Who  Date     Changes
* ----- ---- -------- -----------------------------------------------
* 1.00b rpm 03/26/02  First release
* </pre>
*
*****************************************************************************/

/***************************** Include Files *********************************/

#include "xbasic_types.h"
#include "xio.h"
#include "xstatus.h"
#include "xpacket_fifo_v1_00_b.h"

/************************** Constant Definitions *****************************/

/* width of a FIFO word */

#define XPF_FIFO_WIDTH_BYTE_COUNT       4UL

/**************************** Type Definitions *******************************/

/***************** Macros (Inline Functions) Definitions *********************/

/************************* Variable Definitions ******************************/

/************************** Function Prototypes ******************************/

/*****************************************************************************/
/*
*
* This function initializes a packet FIFO.  Initialization resets the
* FIFO such that it's empty and ready to use.
*
* @param InstancePtr contains a pointer to the FIFO to operate on.
* @param RegBaseAddress contains the base address of the registers for
*        the packet FIFO.
* @param DataBaseAddress contains the base address of the data for
*        the packet FIFO.
*
* @return
*
* Always returns XST_SUCCESS.
*
* @note
*
* None.
*
******************************************************************************/
XStatus
XPacketFifoV100b_Initialize(XPacketFifoV100b * InstancePtr,
			    u32 RegBaseAddress, u32 DataBaseAddress)
{
	/* assert to verify input argument are valid */

	XASSERT_NONVOID(InstancePtr != NULL);

	/* initialize the component variables to the specified state */

	InstancePtr->RegBaseAddress = RegBaseAddress;
	InstancePtr->DataBaseAddress = DataBaseAddress;
	InstancePtr->IsReady = XCOMPONENT_IS_READY;

	/* reset the FIFO such that it's empty and ready to use and indicate the
	 * initialization was successful, note that the is ready variable must be
	 * set prior to calling the reset function to prevent an assert
	 */
	XPF_V100B_RESET(InstancePtr);

	return XST_SUCCESS;
}

/*****************************************************************************/
/*
*
* This function performs a self-test on the specified packet FIFO.  The self
* test resets the FIFO and reads a register to determine if it is the correct
* reset value.  This test is destructive in that any data in the FIFO will
* be lost.
*
* @param InstancePtr is a pointer to the packet FIFO to be operated on.
*
* @param FifoType specifies the type of FIFO, read or write, for the self test.
*        The FIFO type is specified by the values XPF_READ_FIFO_TYPE or
*        XPF_WRITE_FIFO_TYPE.
*
* @return
*
* XST_SUCCESS is returned if the selftest is successful, or
* XST_PFIFO_BAD_REG_VALUE indicating that the value readback from the
* occupancy/vacancy count register after a reset does not match the
* specified reset value.
*
* @note
*
* None.
*
******************************************************************************/
XStatus
XPacketFifoV100b_SelfTest(XPacketFifoV100b * InstancePtr, u32 FifoType)
{
	u32 Register;

	/* assert to verify valid input arguments */

	XASSERT_NONVOID(InstancePtr != NULL);
	XASSERT_NONVOID((FifoType == XPF_READ_FIFO_TYPE) ||
			(FifoType == XPF_WRITE_FIFO_TYPE));
	XASSERT_NONVOID(InstancePtr->IsReady == XCOMPONENT_IS_READY);

	/* reset the fifo and then check to make sure the occupancy/vacancy
	 * register contents are correct for a reset condition
	 */
	XPF_V100B_RESET(InstancePtr);

	Register = XIo_In32(InstancePtr->RegBaseAddress +
			    XPF_COUNT_STATUS_REG_OFFSET);

	/* check the value of the register to ensure that it's correct for the
	 * specified FIFO type since both FIFO types reset to empty, but a bit
	 * in the register changes definition based upon FIFO type
	 */

	if (FifoType == XPF_READ_FIFO_TYPE) {
		/* check the regiser value for a read FIFO which should be empty */

		if (Register != XPF_EMPTY_FULL_MASK) {
			return XST_PFIFO_BAD_REG_VALUE;
		}
	} else {
		/* check the register value for a write FIFO which should not be full
		 * on reset
		 */
		if ((Register & XPF_EMPTY_FULL_MASK) != 0) {
			return XST_PFIFO_BAD_REG_VALUE;
		}
	}

	/* the test was successful */

	return XST_SUCCESS;
}

/*****************************************************************************/
/*
*
* Read data from a FIFO and puts it into a specified buffer. The packet FIFO is
* currently 32 bits wide such that an input buffer which is a series of bytes
* is filled from the FIFO a word at a time. If the requested byte count is not
* a multiple of 32 bit words, it is necessary for this function to format the
* remaining 32 bit word from the FIFO into a series of bytes in the buffer.
* There may be up to 3 extra bytes which must be extracted from the last word
* of the FIFO and put into the buffer.
*
* @param InstancePtr contains a pointer to the FIFO to operate on.
* @param BufferPtr points to the memory buffer to write the data into. This
*        buffer must be 32 bit aligned or an alignment exception could be
*        generated. Since this buffer is a byte buffer, the data is assumed to
*        be endian independent.
* @param ByteCount contains the number of bytes to read from the FIFO. This
*        number of bytes must be present in the FIFO or an error will be
*        returned.
*
* @return
*
* XST_SUCCESS indicates the operation was successful.  If the number of
* bytes specified by the byte count is not present in the FIFO
* XST_PFIFO_LACK_OF_DATA is returned.
*
* If the function was successful, the specified buffer is modified to contain
* the bytes which were removed from the FIFO.
*
* @note
*
* Note that the exact number of bytes which are present in the FIFO is
* not known by this function.  It can only check for a number of 32 bit
* words such that if the byte count specified is incorrect, but is still
* possible based on the number of words in the FIFO, up to 3 garbage bytes
* may be present at the end of the buffer.
* <br><br>
* This function assumes that if the device consuming data from the FIFO is
* a byte device, the order of the bytes to be consumed is from the most
* significant byte to the least significant byte of a 32 bit word removed
* from the FIFO.
*
******************************************************************************/
XStatus
XPacketFifoV100b_Read(XPacketFifoV100b * InstancePtr,
		      u8 * BufferPtr, u32 ByteCount)
{
	u32 FifoCount;
	u32 WordCount;
	u32 ExtraByteCount;
	u32 *WordBuffer = (u32 *) BufferPtr;

	/* assert to verify valid input arguments including 32 bit alignment of
	 * the buffer pointer
	 */
	XASSERT_NONVOID(InstancePtr != NULL);
	XASSERT_NONVOID(BufferPtr != NULL);
	XASSERT_NONVOID(((u32) BufferPtr &
			 (XPF_FIFO_WIDTH_BYTE_COUNT - 1)) == 0);
	XASSERT_NONVOID(ByteCount != 0);
	XASSERT_NONVOID(InstancePtr->IsReady == XCOMPONENT_IS_READY);

	/* get the count of how many 32 bit words are in the FIFO, if there aren't
	 * enought words to satisfy the request, return an error
	 */

	FifoCount = XIo_In32(InstancePtr->RegBaseAddress +
			     XPF_COUNT_STATUS_REG_OFFSET) & XPF_COUNT_MASK;

	if ((FifoCount * XPF_FIFO_WIDTH_BYTE_COUNT) < ByteCount) {
		return XST_PFIFO_LACK_OF_DATA;
	}

	/* calculate the number of words to read from the FIFO before the word
	 * containing the extra bytes, and calculate the number of extra bytes
	 * the extra bytes are defined as those at the end of the buffer when
	 * the buffer does not end on a 32 bit boundary
	 */
	WordCount = ByteCount / XPF_FIFO_WIDTH_BYTE_COUNT;
	ExtraByteCount = ByteCount % XPF_FIFO_WIDTH_BYTE_COUNT;

	/* Read the 32 bit words from the FIFO for all the buffer except the
	 * last word which contains the extra bytes, the following code assumes
	 * that the buffer is 32 bit aligned, otherwise an alignment exception could
	 * be generated
	 */
	for (FifoCount = 0; FifoCount < WordCount; FifoCount++) {
		WordBuffer[FifoCount] = XIo_In32(InstancePtr->DataBaseAddress);
	}

	/* if there are extra bytes to handle, read the last word from the FIFO
	 * and insert the extra bytes into the buffer
	 */
	if (ExtraByteCount > 0) {
		u32 LastWord;
		u8 *ExtraBytesBuffer = (u8 *) (WordBuffer + WordCount);

		/* get the last word from the FIFO for the extra bytes */

		LastWord = XIo_In32(InstancePtr->DataBaseAddress);

		/* one extra byte in the last word, put the byte into the next location
		 * of the buffer, bytes in a word of the FIFO are ordered from most
		 * significant byte to least
		 */
		if (ExtraByteCount == 1) {
			ExtraBytesBuffer[0] = (u8) (LastWord >> 24);
		}

		/* two extra bytes in the last word, put each byte into the next two
		 * locations of the buffer
		 */
		else if (ExtraByteCount == 2) {
			ExtraBytesBuffer[0] = (u8) (LastWord >> 24);
			ExtraBytesBuffer[1] = (u8) (LastWord >> 16);
		}
		/* three extra bytes in the last word, put each byte into the next three
		 * locations of the buffer
		 */
		else if (ExtraByteCount == 3) {
			ExtraBytesBuffer[0] = (u8) (LastWord >> 24);
			ExtraBytesBuffer[1] = (u8) (LastWord >> 16);
			ExtraBytesBuffer[2] = (u8) (LastWord >> 8);
		}
	}
	return XST_SUCCESS;
}

/*****************************************************************************/
/*
*
* Write data into a packet FIFO. The packet FIFO is currently 32 bits wide
* such that an input buffer which is a series of bytes must be written into the
* FIFO a word at a time. If the buffer is not a multiple of 32 bit words, it is
* necessary for this function to format the remaining bytes into a single 32
* bit word to be inserted into the FIFO. This is necessary to avoid any
* accesses past the end of the buffer.
*
* @param InstancePtr contains a pointer to the FIFO to operate on.
* @param BufferPtr points to the memory buffer that data is to be read from
*        and written into the FIFO. Since this buffer is a byte buffer, the data
*        is assumed to be endian independent. This buffer must be 32 bit aligned
*        or an alignment exception could be generated.
* @param ByteCount contains the number of bytes to read from the buffer and to
*        write to the FIFO.
*
* @return
*
* XST_SUCCESS is returned if the operation succeeded.  If there is not enough
* room in the FIFO to hold the specified bytes, XST_PFIFO_NO_ROOM is
* returned.
*
* @note
*
* This function assumes that if the device inserting data into the FIFO is
* a byte device, the order of the bytes in each 32 bit word is from the most
* significant byte to the least significant byte.
*
******************************************************************************/
XStatus
XPacketFifoV100b_Write(XPacketFifoV100b * InstancePtr,
		       u8 * BufferPtr, u32 ByteCount)
{
	u32 FifoCount;
	u32 WordCount;
	u32 ExtraByteCount;
	u32 *WordBuffer = (u32 *) BufferPtr;

	/* assert to verify valid input arguments including 32 bit alignment of
	 * the buffer pointer
	 */
	XASSERT_NONVOID(InstancePtr != NULL);
	XASSERT_NONVOID(BufferPtr != NULL);
	XASSERT_NONVOID(((u32) BufferPtr &
			 (XPF_FIFO_WIDTH_BYTE_COUNT - 1)) == 0);
	XASSERT_NONVOID(ByteCount != 0);
	XASSERT_NONVOID(InstancePtr->IsReady == XCOMPONENT_IS_READY);

	/* get the count of how many words may be inserted into the FIFO */

	FifoCount = XIo_In32(InstancePtr->RegBaseAddress +
			     XPF_COUNT_STATUS_REG_OFFSET) & XPF_COUNT_MASK;

	/* Calculate the number of 32 bit words required to insert the specified
	 * number of bytes in the FIFO and determine the number of extra bytes
	 * if the buffer length is not a multiple of 32 bit words
	 */

	WordCount = ByteCount / XPF_FIFO_WIDTH_BYTE_COUNT;
	ExtraByteCount = ByteCount % XPF_FIFO_WIDTH_BYTE_COUNT;

	/* take into account the extra bytes in the total word count */

	if (ExtraByteCount > 0) {
		WordCount++;
	}

	/* if there's not enough room in the FIFO to hold the specified
	 * number of bytes, then indicate an error,
	 */
	if (FifoCount < WordCount) {
		return XST_PFIFO_NO_ROOM;
	}

	/* readjust the word count to not take into account the extra bytes */

	if (ExtraByteCount > 0) {
		WordCount--;
	}

	/* Write all the bytes of the buffer which can be written as 32 bit
	 * words into the FIFO, waiting to handle the extra bytes seperately
	 */
	for (FifoCount = 0; FifoCount < WordCount; FifoCount++) {
		XIo_Out32(InstancePtr->DataBaseAddress, WordBuffer[FifoCount]);
	}

	/* if there are extra bytes to handle, extract them from the buffer
	 * and create a 32 bit word and write it to the FIFO
	 */
	if (ExtraByteCount > 0) {
		u32 LastWord = 0;
		u8 *ExtraBytesBuffer = (u8 *) (WordBuffer + WordCount);

		/* one extra byte in the buffer, put the byte into the last word
		 * to be inserted into the FIFO, perform this processing inline rather
		 * than in a loop to help performance
		 */
		if (ExtraByteCount == 1) {
			LastWord = ExtraBytesBuffer[0] << 24;
		}

		/* two extra bytes in the buffer, put each byte into the last word
		 * to be inserted into the FIFO
		 */
		else if (ExtraByteCount == 2) {
			LastWord = ExtraBytesBuffer[0] << 24 |
			    ExtraBytesBuffer[1] << 16;
		}

		/* three extra bytes in the buffer, put each byte into the last word
		 * to be inserted into the FIFO
		 */
		else if (ExtraByteCount == 3) {
			LastWord = ExtraBytesBuffer[0] << 24 |
			    ExtraBytesBuffer[1] << 16 |
			    ExtraBytesBuffer[2] << 8;
		}

		/* write the last 32 bit word to the FIFO and return with no errors */

		XIo_Out32(InstancePtr->DataBaseAddress, LastWord);
	}

	return XST_SUCCESS;
}