blob: 69138ccded9b81495fb3cda76f1b01f566988ff1 [file] [log] [blame]
Wolfgang Denkba94a1b2006-05-30 15:56:48 +02001/*
2 * @file: IxQMgrAqmIf.c
3 *
4 * @author Intel Corporation
5 * @date 30-Oct-2001
6 *
7 * @brief This component provides a set of functions for
8 * perfoming I/O on the AQM hardware.
9 *
10 * Design Notes:
11 * These functions are intended to be as fast as possible
12 * and as a result perform NO PARAMETER CHECKING.
13 *
14 *
15 * @par
16 * IXP400 SW Release version 2.0
17 *
18 * -- Copyright Notice --
19 *
20 * @par
21 * Copyright 2001-2005, Intel Corporation.
22 * All rights reserved.
Wolfgang Denkcb3761e2013-07-28 22:12:47 +020023 *
Wolfgang Denkba94a1b2006-05-30 15:56:48 +020024 * @par
Wolfgang Denkcb3761e2013-07-28 22:12:47 +020025 * SPDX-License-Identifier: BSD-3-Clause
Wolfgang Denkba94a1b2006-05-30 15:56:48 +020026 * @par
27 * -- End of Copyright Notice --
28*/
29
30/*
31 * Inlines are compiled as function when this is defined.
32 * N.B. Must be placed before #include of "IxQMgrAqmIf_p.h
33 */
34#ifndef IXQMGRAQMIF_P_H
35# define IXQMGRAQMIF_C
36#else
37# error
38#endif
39
40/*
41 * User defined include files.
42 */
43#include "IxOsal.h"
44#include "IxQMgr.h"
45#include "IxQMgrAqmIf_p.h"
46#include "IxQMgrLog_p.h"
47
48
49/*
50 * #defines and macros used in this file.
51 */
52
53/* These defines are the bit offsets of the various fields of
54 * the queue configuration register
55 */
56#define IX_QMGR_Q_CONFIG_WRPTR_OFFSET 0x00
57#define IX_QMGR_Q_CONFIG_RDPTR_OFFSET 0x07
58#define IX_QMGR_Q_CONFIG_BADDR_OFFSET 0x0E
59#define IX_QMGR_Q_CONFIG_ESIZE_OFFSET 0x16
60#define IX_QMGR_Q_CONFIG_BSIZE_OFFSET 0x18
61#define IX_QMGR_Q_CONFIG_NE_OFFSET 0x1A
62#define IX_QMGR_Q_CONFIG_NF_OFFSET 0x1D
63
64#define IX_QMGR_BASE_ADDR_16_WORD_ALIGN 0x40
65#define IX_QMGR_BASE_ADDR_16_WORD_SHIFT 0x6
66
67#define IX_QMGR_NE_NF_CLEAR_MASK 0x03FFFFFF
68#define IX_QMGR_NE_MASK 0x7
69#define IX_QMGR_NF_MASK 0x7
70#define IX_QMGR_SIZE_MASK 0x3
71#define IX_QMGR_ENTRY_SIZE_MASK 0x3
72#define IX_QMGR_BADDR_MASK 0x003FC000
73#define IX_QMGR_RDPTR_MASK 0x7F
74#define IX_QMGR_WRPTR_MASK 0x7F
75#define IX_QMGR_RDWRPTR_MASK 0x00003FFF
76
77#define IX_QMGR_AQM_ADDRESS_SPACE_SIZE_IN_WORDS 0x1000
78
79/* Base address of AQM SRAM */
80#define IX_QMGR_AQM_SRAM_BASE_ADDRESS_OFFSET \
81((IX_QMGR_QUECONFIG_BASE_OFFSET) + (IX_QMGR_QUECONFIG_SIZE))
82
83/* Min buffer size used for generating buffer size in QUECONFIG */
84#define IX_QMGR_MIN_BUFFER_SIZE 16
85
86/* Reset values of QMgr hardware registers */
87#define IX_QMGR_QUELOWSTAT_RESET_VALUE 0x33333333
88#define IX_QMGR_QUEUOSTAT_RESET_VALUE 0x00000000
89#define IX_QMGR_QUEUPPSTAT0_RESET_VALUE 0xFFFFFFFF
90#define IX_QMGR_QUEUPPSTAT1_RESET_VALUE 0x00000000
91#define IX_QMGR_INT0SRCSELREG_RESET_VALUE 0x00000000
92#define IX_QMGR_QUEIEREG_RESET_VALUE 0x00000000
93#define IX_QMGR_QINTREG_RESET_VALUE 0xFFFFFFFF
94#define IX_QMGR_QUECONFIG_RESET_VALUE 0x00000000
95
96#define IX_QMGR_PHYSICAL_AQM_BASE_ADDRESS IX_OSAL_IXP400_QMGR_PHYS_BASE
97
98#define IX_QMGR_QUELOWSTAT_BITS_PER_Q (BITS_PER_WORD/IX_QMGR_QUELOWSTAT_NUM_QUE_PER_WORD)
99
100#define IX_QMGR_QUELOWSTAT_QID_MASK 0x7
101#define IX_QMGR_Q_CONFIG_ADDR_GET(qId)\
102 (((qId) * IX_QMGR_NUM_BYTES_PER_WORD) +\
103 IX_QMGR_QUECONFIG_BASE_OFFSET)
104
105#define IX_QMGR_ENTRY1_OFFSET 0
106#define IX_QMGR_ENTRY2_OFFSET 1
107#define IX_QMGR_ENTRY4_OFFSET 3
108
109/*
110 * Variable declarations global to this file. Externs are followed by
111 * statics.
112 */
113UINT32 aqmBaseAddress = 0;
114/* Store addresses and bit-masks for certain queue access and status registers.
115 * This is to facilitate inlining of QRead, QWrite and QStatusGet functions
116 * in IxQMgr,h
117 */
118extern IxQMgrQInlinedReadWriteInfo ixQMgrQInlinedReadWriteInfo[];
119UINT32 * ixQMgrAqmIfQueAccRegAddr[IX_QMGR_MAX_NUM_QUEUES];
120UINT32 ixQMgrAqmIfQueLowStatRegAddr[IX_QMGR_MIN_QUEUPP_QID];
121UINT32 ixQMgrAqmIfQueLowStatBitsOffset[IX_QMGR_MIN_QUEUPP_QID];
122UINT32 ixQMgrAqmIfQueLowStatBitsMask;
123UINT32 ixQMgrAqmIfQueUppStat0RegAddr;
124UINT32 ixQMgrAqmIfQueUppStat1RegAddr;
125UINT32 ixQMgrAqmIfQueUppStat0BitMask[IX_QMGR_MIN_QUEUPP_QID];
126UINT32 ixQMgrAqmIfQueUppStat1BitMask[IX_QMGR_MIN_QUEUPP_QID];
127
128/*
129 * Fast mutexes, one for each queue, used to protect peek & poke functions
130 */
131IxOsalFastMutex ixQMgrAqmIfPeekPokeFastMutex[IX_QMGR_MAX_NUM_QUEUES];
132
133/*
134 * Function prototypes
135 */
136PRIVATE unsigned
137watermarkToAqmWatermark (IxQMgrWMLevel watermark );
138
139PRIVATE unsigned
140entrySizeToAqmEntrySize (IxQMgrQEntrySizeInWords entrySize);
141
142PRIVATE unsigned
143bufferSizeToAqmBufferSize (unsigned bufferSizeInWords);
144
145PRIVATE void
146ixQMgrAqmIfRegistersReset (void);
147
148PRIVATE void
149ixQMgrAqmIfEntryAddressGet (unsigned int entryIndex,
150 UINT32 configRegWord,
151 unsigned int qEntrySizeInwords,
152 unsigned int qSizeInWords,
153 UINT32 **address);
154/*
155 * Function definitions
156 */
157void
158ixQMgrAqmIfInit (void)
159{
160 UINT32 aqmVirtualAddr;
161 int i;
162
163 /* The value of aqmBaseAddress depends on the logical address
164 * assigned by the MMU.
165 */
166 aqmVirtualAddr =
167 (UINT32) IX_OSAL_MEM_MAP(IX_QMGR_PHYSICAL_AQM_BASE_ADDRESS,
168 IX_OSAL_IXP400_QMGR_MAP_SIZE);
169 IX_OSAL_ASSERT (aqmVirtualAddr);
170
171 ixQMgrAqmIfBaseAddressSet (aqmVirtualAddr);
172
173 ixQMgrAqmIfRegistersReset ();
174
175 for (i = 0; i< IX_QMGR_MAX_NUM_QUEUES; i++)
176 {
177 ixOsalFastMutexInit(&ixQMgrAqmIfPeekPokeFastMutex[i]);
178
179 /********************************************************************
180 * Register addresses and bit masks are calculated and stored here to
181 * facilitate inlining of QRead, QWrite and QStatusGet functions in
182 * IxQMgr.h.
183 * These calculations are normally performed dynamically in inlined
184 * functions in IxQMgrAqmIf_p.h, and their semantics are reused here.
185 */
186
187 /* AQM Queue access reg addresses, per queue */
Wolfgang Denk53677ef2008-05-20 16:00:29 +0200188 ixQMgrAqmIfQueAccRegAddr[i] =
Wolfgang Denkba94a1b2006-05-30 15:56:48 +0200189 (UINT32 *)(aqmBaseAddress + IX_QMGR_Q_ACCESS_ADDR_GET(i));
190 ixQMgrQInlinedReadWriteInfo[i].qAccRegAddr =
191 (volatile UINT32 *)(aqmBaseAddress + IX_QMGR_Q_ACCESS_ADDR_GET(i));
192
193
194 ixQMgrQInlinedReadWriteInfo[i].qConfigRegAddr =
195 (volatile UINT32 *)(aqmBaseAddress + IX_QMGR_Q_CONFIG_ADDR_GET(i));
196
197 /* AQM Queue lower-group (0-31), only */
198 if (i < IX_QMGR_MIN_QUEUPP_QID)
199 {
200 /* AQM Q underflow/overflow status register addresses, per queue */
201 ixQMgrQInlinedReadWriteInfo[i].qUOStatRegAddr =
202 (volatile UINT32 *)(aqmBaseAddress +
203 IX_QMGR_QUEUOSTAT0_OFFSET +
204 ((i / IX_QMGR_QUEUOSTAT_NUM_QUE_PER_WORD) *
205 IX_QMGR_NUM_BYTES_PER_WORD));
206
207 /* AQM Q underflow status bit masks for status register per queue */
208 ixQMgrQInlinedReadWriteInfo[i].qUflowStatBitMask =
209 (IX_QMGR_UNDERFLOW_BIT_OFFSET + 1) <<
210 ((i & (IX_QMGR_QUEUOSTAT_NUM_QUE_PER_WORD - 1)) *
211 (BITS_PER_WORD / IX_QMGR_QUEUOSTAT_NUM_QUE_PER_WORD));
212
213 /* AQM Q overflow status bit masks for status register, per queue */
214 ixQMgrQInlinedReadWriteInfo[i].qOflowStatBitMask =
215 (IX_QMGR_OVERFLOW_BIT_OFFSET + 1) <<
216 ((i & (IX_QMGR_QUEUOSTAT_NUM_QUE_PER_WORD - 1)) *
217 (BITS_PER_WORD / IX_QMGR_QUEUOSTAT_NUM_QUE_PER_WORD));
218
219 /* AQM Q lower-group (0-31) status register addresses, per queue */
220 ixQMgrAqmIfQueLowStatRegAddr[i] = aqmBaseAddress +
221 IX_QMGR_QUELOWSTAT0_OFFSET +
222 ((i / IX_QMGR_QUELOWSTAT_NUM_QUE_PER_WORD) *
223 IX_QMGR_NUM_BYTES_PER_WORD);
224
225 /* AQM Q lower-group (0-31) status register bit offset */
226 ixQMgrAqmIfQueLowStatBitsOffset[i] =
227 (i & (IX_QMGR_QUELOWSTAT_NUM_QUE_PER_WORD - 1)) *
228 (BITS_PER_WORD / IX_QMGR_QUELOWSTAT_NUM_QUE_PER_WORD);
229 }
230 else /* AQM Q upper-group (32-63), only */
231 {
232 /* AQM Q upper-group (32-63) Nearly Empty status reg bit masks */
233 ixQMgrAqmIfQueUppStat0BitMask[i - IX_QMGR_MIN_QUEUPP_QID] =
234 (1 << (i - IX_QMGR_MIN_QUEUPP_QID));
235
236 /* AQM Q upper-group (32-63) Full status register bit masks */
237 ixQMgrAqmIfQueUppStat1BitMask[i - IX_QMGR_MIN_QUEUPP_QID] =
238 (1 << (i - IX_QMGR_MIN_QUEUPP_QID));
239 }
240 }
241
242 /* AQM Q lower-group (0-31) status register bit mask */
243 ixQMgrAqmIfQueLowStatBitsMask = (1 <<
244 (BITS_PER_WORD /
245 IX_QMGR_QUELOWSTAT_NUM_QUE_PER_WORD)) - 1;
246
247 /* AQM Q upper-group (32-63) Nearly Empty status register address */
248 ixQMgrAqmIfQueUppStat0RegAddr = aqmBaseAddress + IX_QMGR_QUEUPPSTAT0_OFFSET;
249
250 /* AQM Q upper-group (32-63) Full status register address */
251 ixQMgrAqmIfQueUppStat1RegAddr = aqmBaseAddress + IX_QMGR_QUEUPPSTAT1_OFFSET;
252}
253
254/*
255 * Uninitialise the AqmIf module by unmapping memory, etc
256 */
257void
258ixQMgrAqmIfUninit (void)
259{
260 UINT32 virtAddr;
261
262 ixQMgrAqmIfBaseAddressGet (&virtAddr);
263 IX_OSAL_MEM_UNMAP (virtAddr);
264 ixQMgrAqmIfBaseAddressSet (0);
265}
266
267/*
268 * Set the the logical base address of AQM
269 */
270void
271ixQMgrAqmIfBaseAddressSet (UINT32 address)
272{
273 aqmBaseAddress = address;
274}
275
276/*
277 * Get the logical base address of AQM
278 */
279void
280ixQMgrAqmIfBaseAddressGet (UINT32 *address)
281{
282 *address = aqmBaseAddress;
283}
284
285/*
286 * Get the logical base address of AQM SRAM
287 */
288void
289ixQMgrAqmIfSramBaseAddressGet (UINT32 *address)
290{
291 *address = aqmBaseAddress +
292 IX_QMGR_AQM_SRAM_BASE_ADDRESS_OFFSET;
293}
294
295/*
296 * This function will write the status bits of a queue
297 * specified by qId.
298 */
299void
300ixQMgrAqmIfQRegisterBitsWrite (IxQMgrQId qId,
301 UINT32 registerBaseAddrOffset,
302 unsigned queuesPerRegWord,
303 UINT32 value)
304{
305 volatile UINT32 *registerAddress;
306 UINT32 registerWord;
307 UINT32 statusBitsMask;
308 UINT32 bitsPerQueue;
309
310 bitsPerQueue = BITS_PER_WORD / queuesPerRegWord;
311
312 /*
313 * Calculate the registerAddress
314 * multiple queues split accross registers
315 */
316 registerAddress = (UINT32*)(aqmBaseAddress +
317 registerBaseAddrOffset +
318 ((qId / queuesPerRegWord) *
319 IX_QMGR_NUM_BYTES_PER_WORD));
320
321 /* Read the current data */
322 ixQMgrAqmIfWordRead (registerAddress, &registerWord);
323
324
325 if( (registerBaseAddrOffset == IX_QMGR_INT0SRCSELREG0_OFFSET) &&
326 (qId == IX_QMGR_QUEUE_0) )
327 {
328 statusBitsMask = 0x7 ;
329
330 /* Queue 0 at INT0SRCSELREG should not corrupt the value bit-3 */
331 value &= 0x7 ;
332 }
333 else
334 {
335 /* Calculate the mask for the status bits for this queue. */
336 statusBitsMask = ((1 << bitsPerQueue) - 1);
337 statusBitsMask <<= ((qId & (queuesPerRegWord - 1)) * bitsPerQueue);
338
339 /* Mask out bits in value that would overwrite other q data */
340 value <<= ((qId & (queuesPerRegWord - 1)) * bitsPerQueue);
341 value &= statusBitsMask;
342 }
343
344 /* Mask out bits to write to */
345 registerWord &= ~statusBitsMask;
346
347
348 /* Set the write bits */
349 registerWord |= value;
350
351 /*
352 * Write the data
353 */
354 ixQMgrAqmIfWordWrite (registerAddress, registerWord);
355}
356
357/*
358 * This function generates the parameters that can be used to
359 * check if a Qs status matches the specified source select.
360 * It calculates which status word to check (statusWordOffset),
361 * the value to check the status against (checkValue) and the
362 * mask (mask) to mask out all but the bits to check in the status word.
363 */
364void
365ixQMgrAqmIfQStatusCheckValsCalc (IxQMgrQId qId,
366 IxQMgrSourceId srcSel,
367 unsigned int *statusWordOffset,
368 UINT32 *checkValue,
369 UINT32 *mask)
370{
371 UINT32 shiftVal;
372
373 if (qId < IX_QMGR_MIN_QUEUPP_QID)
374 {
375 switch (srcSel)
376 {
377 case IX_QMGR_Q_SOURCE_ID_E:
378 *checkValue = IX_QMGR_Q_STATUS_E_BIT_MASK;
379 *mask = IX_QMGR_Q_STATUS_E_BIT_MASK;
380 break;
381 case IX_QMGR_Q_SOURCE_ID_NE:
382 *checkValue = IX_QMGR_Q_STATUS_NE_BIT_MASK;
383 *mask = IX_QMGR_Q_STATUS_NE_BIT_MASK;
384 break;
385 case IX_QMGR_Q_SOURCE_ID_NF:
386 *checkValue = IX_QMGR_Q_STATUS_NF_BIT_MASK;
387 *mask = IX_QMGR_Q_STATUS_NF_BIT_MASK;
388 break;
389 case IX_QMGR_Q_SOURCE_ID_F:
390 *checkValue = IX_QMGR_Q_STATUS_F_BIT_MASK;
391 *mask = IX_QMGR_Q_STATUS_F_BIT_MASK;
392 break;
393 case IX_QMGR_Q_SOURCE_ID_NOT_E:
394 *checkValue = 0;
395 *mask = IX_QMGR_Q_STATUS_E_BIT_MASK;
396 break;
397 case IX_QMGR_Q_SOURCE_ID_NOT_NE:
398 *checkValue = 0;
399 *mask = IX_QMGR_Q_STATUS_NE_BIT_MASK;
400 break;
401 case IX_QMGR_Q_SOURCE_ID_NOT_NF:
402 *checkValue = 0;
403 *mask = IX_QMGR_Q_STATUS_NF_BIT_MASK;
404 break;
405 case IX_QMGR_Q_SOURCE_ID_NOT_F:
406 *checkValue = 0;
407 *mask = IX_QMGR_Q_STATUS_F_BIT_MASK;
408 break;
409 default:
410 /* Should never hit */
411 IX_OSAL_ASSERT(0);
412 break;
413 }
414
415 /* One nibble of status per queue so need to shift the
416 * check value and mask out to the correct position.
417 */
418 shiftVal = (qId % IX_QMGR_QUELOWSTAT_NUM_QUE_PER_WORD) *
419 IX_QMGR_QUELOWSTAT_BITS_PER_Q;
420
421 /* Calculate the which status word to check from the qId,
422 * 8 Qs status per word
423 */
424 *statusWordOffset = qId / IX_QMGR_QUELOWSTAT_NUM_QUE_PER_WORD;
425
426 *checkValue <<= shiftVal;
427 *mask <<= shiftVal;
428 }
429 else
430 {
431 /* One status word */
432 *statusWordOffset = 0;
433 /* Single bits per queue and int source bit hardwired NE,
434 * Qs start at 32.
435 */
436 *mask = 1 << (qId - IX_QMGR_MIN_QUEUPP_QID);
437 *checkValue = *mask;
438 }
439}
440
441void
442ixQMgrAqmIfQInterruptEnable (IxQMgrQId qId)
443{
444 volatile UINT32 *registerAddress;
445 UINT32 registerWord;
446 UINT32 actualBitOffset;
447
448 if (qId < IX_QMGR_MIN_QUEUPP_QID)
449 {
450 registerAddress = (UINT32*)(aqmBaseAddress + IX_QMGR_QUEIEREG0_OFFSET);
451 }
452 else
453 {
454 registerAddress = (UINT32*)(aqmBaseAddress + IX_QMGR_QUEIEREG1_OFFSET);
455 }
456
457 actualBitOffset = 1 << (qId % IX_QMGR_MIN_QUEUPP_QID);
458
459 ixQMgrAqmIfWordRead (registerAddress, &registerWord);
460 ixQMgrAqmIfWordWrite (registerAddress, (registerWord | actualBitOffset));
461}
462
463void
464ixQMgrAqmIfQInterruptDisable (IxQMgrQId qId)
465{
466 volatile UINT32 *registerAddress;
467 UINT32 registerWord;
468 UINT32 actualBitOffset;
469
470 if (qId < IX_QMGR_MIN_QUEUPP_QID)
471 {
472 registerAddress = (UINT32*)(aqmBaseAddress + IX_QMGR_QUEIEREG0_OFFSET);
473 }
474 else
475 {
476 registerAddress = (UINT32*)(aqmBaseAddress + IX_QMGR_QUEIEREG1_OFFSET);
477 }
478
479 actualBitOffset = 1 << (qId % IX_QMGR_MIN_QUEUPP_QID);
480
481 ixQMgrAqmIfWordRead (registerAddress, &registerWord);
482 ixQMgrAqmIfWordWrite (registerAddress, registerWord & (~actualBitOffset));
483}
484
485void
486ixQMgrAqmIfQueCfgWrite (IxQMgrQId qId,
487 IxQMgrQSizeInWords qSizeInWords,
488 IxQMgrQEntrySizeInWords entrySizeInWords,
489 UINT32 freeSRAMAddress)
490{
491 volatile UINT32 *cfgAddress = NULL;
492 UINT32 qCfg = 0;
493 UINT32 baseAddress = 0;
494 unsigned aqmEntrySize = 0;
495 unsigned aqmBufferSize = 0;
496
497 /* Build config register */
498 aqmEntrySize = entrySizeToAqmEntrySize (entrySizeInWords);
499 qCfg |= (aqmEntrySize&IX_QMGR_ENTRY_SIZE_MASK) <<
500 IX_QMGR_Q_CONFIG_ESIZE_OFFSET;
501
502 aqmBufferSize = bufferSizeToAqmBufferSize (qSizeInWords);
503 qCfg |= (aqmBufferSize&IX_QMGR_SIZE_MASK) << IX_QMGR_Q_CONFIG_BSIZE_OFFSET;
504
505 /* baseAddress, calculated relative to aqmBaseAddress and start address */
506 baseAddress = freeSRAMAddress -
507 (aqmBaseAddress + IX_QMGR_QUECONFIG_BASE_OFFSET);
508
509 /* Verify base address aligned to a 16 word boundary */
510 if ((baseAddress % IX_QMGR_BASE_ADDR_16_WORD_ALIGN) != 0)
511 {
512 IX_QMGR_LOG_ERROR0("ixQMgrAqmIfQueCfgWrite () address is not on 16 word boundary\n");
513 }
514 /* Now convert it to a 16 word pointer as required by QUECONFIG register */
515 baseAddress >>= IX_QMGR_BASE_ADDR_16_WORD_SHIFT;
516
517
518 qCfg |= (baseAddress << IX_QMGR_Q_CONFIG_BADDR_OFFSET);
519
520
521 cfgAddress = (UINT32*)(aqmBaseAddress +
522 IX_QMGR_Q_CONFIG_ADDR_GET(qId));
523
524
525 /* NOTE: High and Low watermarks are set to zero */
526 ixQMgrAqmIfWordWrite (cfgAddress, qCfg);
527}
528
529void
530ixQMgrAqmIfQueCfgRead (IxQMgrQId qId,
531 unsigned int numEntries,
532 UINT32 *baseAddress,
533 unsigned int *ne,
534 unsigned int *nf,
535 UINT32 *readPtr,
536 UINT32 *writePtr)
537{
538 UINT32 qcfg;
539 UINT32 *cfgAddress = (UINT32*)(aqmBaseAddress + IX_QMGR_Q_CONFIG_ADDR_GET(qId));
540 unsigned int qEntrySizeInwords;
541 unsigned int qSizeInWords;
542 UINT32 *readPtr_ = NULL;
543
544 /* Read the queue configuration register */
545 ixQMgrAqmIfWordRead (cfgAddress, &qcfg);
546
547 /* Extract the base address */
548 *baseAddress = (UINT32)((qcfg & IX_QMGR_BADDR_MASK) >>
549 (IX_QMGR_Q_CONFIG_BADDR_OFFSET));
550
551 /* Base address is a 16 word pointer from the start of AQM SRAM.
552 * Convert to absolute word address.
553 */
554 *baseAddress <<= IX_QMGR_BASE_ADDR_16_WORD_SHIFT;
555 *baseAddress += (UINT32)IX_QMGR_QUECONFIG_BASE_OFFSET;
556
557 /*
558 * Extract the watermarks. 0->0 entries, 1->1 entries, 2->2 entries, 3->4 entries......
559 * If ne > 0 ==> neInEntries = 2^(ne - 1)
560 * If ne == 0 ==> neInEntries = 0
561 * The same applies.
562 */
563 *ne = ((qcfg) >> (IX_QMGR_Q_CONFIG_NE_OFFSET)) & IX_QMGR_NE_MASK;
564 *nf = ((qcfg) >> (IX_QMGR_Q_CONFIG_NF_OFFSET)) & IX_QMGR_NF_MASK;
565
566 if (0 != *ne)
567 {
568 *ne = 1 << (*ne - 1);
569 }
570 if (0 != *nf)
571 {
572 *nf = 1 << (*nf - 1);
573 }
574
575 /* Get the queue entry size in words */
576 qEntrySizeInwords = ixQMgrQEntrySizeInWordsGet (qId);
577
578 /* Get the queue size in words */
579 qSizeInWords = ixQMgrQSizeInWordsGet (qId);
580
581 ixQMgrAqmIfEntryAddressGet (0/* Entry 0. i.e the readPtr*/,
582 qcfg,
583 qEntrySizeInwords,
584 qSizeInWords,
585 &readPtr_);
586 *readPtr = (UINT32)readPtr_;
587 *readPtr -= (UINT32)aqmBaseAddress;/* Offset, not absolute address */
588
589 *writePtr = (qcfg >> IX_QMGR_Q_CONFIG_WRPTR_OFFSET) & IX_QMGR_WRPTR_MASK;
590 *writePtr = *baseAddress + (*writePtr * (IX_QMGR_NUM_BYTES_PER_WORD));
591 return;
592}
593
594unsigned
595ixQMgrAqmIfLog2 (unsigned number)
596{
597 unsigned count = 0;
598
599 /*
600 * N.B. this function will return 0
601 * for ixQMgrAqmIfLog2 (0)
602 */
603 while (number/2)
604 {
605 number /=2;
606 count++;
607 }
608
609 return count;
610}
611
612void ixQMgrAqmIfIntSrcSelReg0Bit3Set (void)
613{
614
615 volatile UINT32 *registerAddress;
616 UINT32 registerWord;
617
618 /*
619 * Calculate the registerAddress
620 * multiple queues split accross registers
621 */
622 registerAddress = (UINT32*)(aqmBaseAddress +
623 IX_QMGR_INT0SRCSELREG0_OFFSET);
624
625 /* Read the current data */
626 ixQMgrAqmIfWordRead (registerAddress, &registerWord);
627
628 /* Set the write bits */
629 registerWord |= (1<<IX_QMGR_INT0SRCSELREG0_BIT3) ;
630
631 /*
632 * Write the data
633 */
634 ixQMgrAqmIfWordWrite (registerAddress, registerWord);
635}
636
637
638void
639ixQMgrAqmIfIntSrcSelWrite (IxQMgrQId qId,
640 IxQMgrSourceId sourceId)
641{
642 ixQMgrAqmIfQRegisterBitsWrite (qId,
643 IX_QMGR_INT0SRCSELREG0_OFFSET,
644 IX_QMGR_INTSRC_NUM_QUE_PER_WORD,
645 sourceId);
646}
647
648
649
650void
651ixQMgrAqmIfWatermarkSet (IxQMgrQId qId,
652 unsigned ne,
653 unsigned nf)
654{
655 volatile UINT32 *address = 0;
656 UINT32 value = 0;
657 unsigned aqmNeWatermark = 0;
658 unsigned aqmNfWatermark = 0;
659
660 address = (UINT32*)(aqmBaseAddress +
661 IX_QMGR_Q_CONFIG_ADDR_GET(qId));
662
663 aqmNeWatermark = watermarkToAqmWatermark (ne);
664 aqmNfWatermark = watermarkToAqmWatermark (nf);
665
666 /* Read the current watermarks */
667 ixQMgrAqmIfWordRead (address, &value);
668
669 /* Clear out the old watermarks */
670 value &= IX_QMGR_NE_NF_CLEAR_MASK;
671
672 /* Generate the value to write */
673 value |= (aqmNeWatermark << IX_QMGR_Q_CONFIG_NE_OFFSET) |
674 (aqmNfWatermark << IX_QMGR_Q_CONFIG_NF_OFFSET);
675
676 ixQMgrAqmIfWordWrite (address, value);
677
678}
679
680PRIVATE void
681ixQMgrAqmIfEntryAddressGet (unsigned int entryIndex,
682 UINT32 configRegWord,
683 unsigned int qEntrySizeInwords,
684 unsigned int qSizeInWords,
685 UINT32 **address)
686{
687 UINT32 readPtr;
688 UINT32 baseAddress;
689 UINT32 *topOfAqmSram;
690
691 topOfAqmSram = ((UINT32 *)aqmBaseAddress + IX_QMGR_AQM_ADDRESS_SPACE_SIZE_IN_WORDS);
692
693 /* Extract the base address */
694 baseAddress = (UINT32)((configRegWord & IX_QMGR_BADDR_MASK) >>
695 (IX_QMGR_Q_CONFIG_BADDR_OFFSET));
696
697 /* Base address is a 16 word pointer from the start of AQM SRAM.
698 * Convert to absolute word address.
699 */
700 baseAddress <<= IX_QMGR_BASE_ADDR_16_WORD_SHIFT;
701 baseAddress += ((UINT32)aqmBaseAddress + (UINT32)IX_QMGR_QUECONFIG_BASE_OFFSET);
702
703 /* Extract the read pointer. Read pointer is a word pointer */
704 readPtr = (UINT32)((configRegWord >>
705 IX_QMGR_Q_CONFIG_RDPTR_OFFSET)&IX_QMGR_RDPTR_MASK);
706
707 /* Read/Write pointers(word pointers) are offsets from the queue buffer space base address.
708 * Calculate the absolute read pointer address. NOTE: Queues are circular buffers.
709 */
710 readPtr = (readPtr + (entryIndex * qEntrySizeInwords)) & (qSizeInWords - 1); /* Mask by queue size */
711 *address = (UINT32 *)(baseAddress + (readPtr * (IX_QMGR_NUM_BYTES_PER_WORD)));
712
713 switch (qEntrySizeInwords)
714 {
715 case IX_QMGR_Q_ENTRY_SIZE1:
716 IX_OSAL_ASSERT((*address + IX_QMGR_ENTRY1_OFFSET) < topOfAqmSram);
717 break;
718 case IX_QMGR_Q_ENTRY_SIZE2:
719 IX_OSAL_ASSERT((*address + IX_QMGR_ENTRY2_OFFSET) < topOfAqmSram);
720 break;
721 case IX_QMGR_Q_ENTRY_SIZE4:
722 IX_OSAL_ASSERT((*address + IX_QMGR_ENTRY4_OFFSET) < topOfAqmSram);
723 break;
724 default:
725 IX_QMGR_LOG_ERROR0("Invalid Q Entry size passed to ixQMgrAqmIfEntryAddressGet");
726 break;
727 }
728
729}
730
731IX_STATUS
732ixQMgrAqmIfQPeek (IxQMgrQId qId,
733 unsigned int entryIndex,
734 unsigned int *entry)
735{
736 UINT32 *cfgRegAddress = (UINT32*)(aqmBaseAddress + IX_QMGR_Q_CONFIG_ADDR_GET(qId));
737 UINT32 *entryAddress = NULL;
738 UINT32 configRegWordOnEntry;
739 UINT32 configRegWordOnExit;
740 unsigned int qEntrySizeInwords;
741 unsigned int qSizeInWords;
742
743 /* Get the queue entry size in words */
744 qEntrySizeInwords = ixQMgrQEntrySizeInWordsGet (qId);
745
746 /* Get the queue size in words */
747 qSizeInWords = ixQMgrQSizeInWordsGet (qId);
748
749 /* Read the config register */
750 ixQMgrAqmIfWordRead (cfgRegAddress, &configRegWordOnEntry);
751
752 /* Get the entry address */
753 ixQMgrAqmIfEntryAddressGet (entryIndex,
754 configRegWordOnEntry,
755 qEntrySizeInwords,
756 qSizeInWords,
757 &entryAddress);
758
759 /* Get the lock or return busy */
760 if (IX_SUCCESS != ixOsalFastMutexTryLock(&ixQMgrAqmIfPeekPokeFastMutex[qId]))
761 {
762 return IX_FAIL;
763 }
764
765 while(qEntrySizeInwords--)
766 {
767 ixQMgrAqmIfWordRead (entryAddress++, entry++);
768 }
769
770 /* Release the lock */
771 ixOsalFastMutexUnlock(&ixQMgrAqmIfPeekPokeFastMutex[qId]);
772
773 /* Read the config register */
774 ixQMgrAqmIfWordRead (cfgRegAddress, &configRegWordOnExit);
775
776 /* Check that the read and write pointers have not changed */
777 if (configRegWordOnEntry != configRegWordOnExit)
778 {
779 return IX_FAIL;
780 }
781
782 return IX_SUCCESS;
783}
784
785IX_STATUS
786ixQMgrAqmIfQPoke (IxQMgrQId qId,
787 unsigned entryIndex,
788 unsigned int *entry)
789{
790 UINT32 *cfgRegAddress = (UINT32*)(aqmBaseAddress + IX_QMGR_Q_CONFIG_ADDR_GET(qId));
791 UINT32 *entryAddress = NULL;
792 UINT32 configRegWordOnEntry;
793 UINT32 configRegWordOnExit;
794 unsigned int qEntrySizeInwords;
795 unsigned int qSizeInWords;
796
797 /* Get the queue entry size in words */
798 qEntrySizeInwords = ixQMgrQEntrySizeInWordsGet (qId);
799
800 /* Get the queue size in words */
801 qSizeInWords = ixQMgrQSizeInWordsGet (qId);
802
803 /* Read the config register */
804 ixQMgrAqmIfWordRead (cfgRegAddress, &configRegWordOnEntry);
805
806 /* Get the entry address */
807 ixQMgrAqmIfEntryAddressGet (entryIndex,
808 configRegWordOnEntry,
809 qEntrySizeInwords,
810 qSizeInWords,
811 &entryAddress);
812
813 /* Get the lock or return busy */
814 if (IX_SUCCESS != ixOsalFastMutexTryLock(&ixQMgrAqmIfPeekPokeFastMutex[qId]))
815 {
816 return IX_FAIL;
817 }
818
819 /* Else read the entry directly from SRAM. This will not move the read pointer */
820 while(qEntrySizeInwords--)
821 {
822 ixQMgrAqmIfWordWrite (entryAddress++, *entry++);
823 }
824
825 /* Release the lock */
826 ixOsalFastMutexUnlock(&ixQMgrAqmIfPeekPokeFastMutex[qId]);
827
828 /* Read the config register */
829 ixQMgrAqmIfWordRead (cfgRegAddress, &configRegWordOnExit);
830
831 /* Check that the read and write pointers have not changed */
832 if (configRegWordOnEntry != configRegWordOnExit)
833 {
834 return IX_FAIL;
835 }
836
837 return IX_SUCCESS;
838}
839
840PRIVATE unsigned
841watermarkToAqmWatermark (IxQMgrWMLevel watermark )
842{
843 unsigned aqmWatermark = 0;
844
845 /*
846 * Watermarks 0("000"),1("001"),2("010"),4("011"),
847 * 8("100"),16("101"),32("110"),64("111")
848 */
849 aqmWatermark = ixQMgrAqmIfLog2 (watermark * 2);
850
851 return aqmWatermark;
852}
853
854PRIVATE unsigned
855entrySizeToAqmEntrySize (IxQMgrQEntrySizeInWords entrySize)
856{
857 /* entrySize 1("00"),2("01"),4("10") */
858 return (ixQMgrAqmIfLog2 (entrySize));
859}
860
861PRIVATE unsigned
862bufferSizeToAqmBufferSize (unsigned bufferSizeInWords)
863{
864 /* bufferSize 16("00"),32("01),64("10"),128("11") */
865 return (ixQMgrAqmIfLog2 (bufferSizeInWords / IX_QMGR_MIN_BUFFER_SIZE));
866}
867
868/*
869 * Reset AQM registers to default values.
870 */
871PRIVATE void
872ixQMgrAqmIfRegistersReset (void)
873{
874 volatile UINT32 *qConfigWordAddress = NULL;
875 unsigned int i;
876
877 /*
878 * Need to initialize AQM hardware registers to an initial
879 * value as init may have been called as a result of a soft
880 * reset. i.e. soft reset does not reset hardware registers.
881 */
882
883 /* Reset queues 0..31 status registers 0..3 */
884 ixQMgrAqmIfWordWrite((UINT32 *)(aqmBaseAddress + IX_QMGR_QUELOWSTAT0_OFFSET),
885 IX_QMGR_QUELOWSTAT_RESET_VALUE);
886 ixQMgrAqmIfWordWrite((UINT32 *)(aqmBaseAddress + IX_QMGR_QUELOWSTAT1_OFFSET),
887 IX_QMGR_QUELOWSTAT_RESET_VALUE);
888 ixQMgrAqmIfWordWrite((UINT32 *)(aqmBaseAddress + IX_QMGR_QUELOWSTAT2_OFFSET),
889 IX_QMGR_QUELOWSTAT_RESET_VALUE);
890 ixQMgrAqmIfWordWrite((UINT32 *)(aqmBaseAddress + IX_QMGR_QUELOWSTAT3_OFFSET),
891 IX_QMGR_QUELOWSTAT_RESET_VALUE);
892
893 /* Reset underflow/overflow status registers 0..1 */
894 ixQMgrAqmIfWordWrite((UINT32 *)(aqmBaseAddress + IX_QMGR_QUEUOSTAT0_OFFSET),
895 IX_QMGR_QUEUOSTAT_RESET_VALUE);
896 ixQMgrAqmIfWordWrite((UINT32 *)(aqmBaseAddress + IX_QMGR_QUEUOSTAT1_OFFSET),
897 IX_QMGR_QUEUOSTAT_RESET_VALUE);
898
899 /* Reset queues 32..63 nearly empty status registers */
900 ixQMgrAqmIfWordWrite((UINT32 *)(aqmBaseAddress + IX_QMGR_QUEUPPSTAT0_OFFSET),
901 IX_QMGR_QUEUPPSTAT0_RESET_VALUE);
902
903 /* Reset queues 32..63 full status registers */
904 ixQMgrAqmIfWordWrite((UINT32 *)(aqmBaseAddress + IX_QMGR_QUEUPPSTAT1_OFFSET),
905 IX_QMGR_QUEUPPSTAT1_RESET_VALUE);
906
907 /* Reset int0 status flag source select registers 0..3 */
908 ixQMgrAqmIfWordWrite((UINT32 *)(aqmBaseAddress + IX_QMGR_INT0SRCSELREG0_OFFSET),
909 IX_QMGR_INT0SRCSELREG_RESET_VALUE);
910 ixQMgrAqmIfWordWrite((UINT32 *)(aqmBaseAddress + IX_QMGR_INT0SRCSELREG1_OFFSET),
911 IX_QMGR_INT0SRCSELREG_RESET_VALUE);
912 ixQMgrAqmIfWordWrite((UINT32 *)(aqmBaseAddress + IX_QMGR_INT0SRCSELREG2_OFFSET),
913 IX_QMGR_INT0SRCSELREG_RESET_VALUE);
914 ixQMgrAqmIfWordWrite((UINT32 *)(aqmBaseAddress + IX_QMGR_INT0SRCSELREG3_OFFSET),
915 IX_QMGR_INT0SRCSELREG_RESET_VALUE);
916
917 /* Reset queue interrupt enable register 0..1 */
918 ixQMgrAqmIfWordWrite((UINT32 *)(aqmBaseAddress + IX_QMGR_QUEIEREG0_OFFSET),
919 IX_QMGR_QUEIEREG_RESET_VALUE);
920 ixQMgrAqmIfWordWrite((UINT32 *)(aqmBaseAddress + IX_QMGR_QUEIEREG1_OFFSET),
921 IX_QMGR_QUEIEREG_RESET_VALUE);
922
923 /* Reset queue interrupt register 0..1 */
924 ixQMgrAqmIfWordWrite((UINT32 *)(aqmBaseAddress + IX_QMGR_QINTREG0_OFFSET),
925 IX_QMGR_QINTREG_RESET_VALUE);
926 ixQMgrAqmIfWordWrite((UINT32 *)(aqmBaseAddress + IX_QMGR_QINTREG1_OFFSET),
927 IX_QMGR_QINTREG_RESET_VALUE);
928
929 /* Reset queue configuration words 0..63 */
930 qConfigWordAddress = (UINT32 *)(aqmBaseAddress + IX_QMGR_QUECONFIG_BASE_OFFSET);
931 for (i = 0; i < (IX_QMGR_QUECONFIG_SIZE / sizeof(UINT32)); i++)
932 {
933 ixQMgrAqmIfWordWrite(qConfigWordAddress,
934 IX_QMGR_QUECONFIG_RESET_VALUE);
935 /* Next word */
936 qConfigWordAddress++;
937 }
938}
939