]> git.kernelconcepts.de Git - karo-tx-uboot.git/blob - drivers/net/npe/IxQMgrAqmIf.c
doc: SPI: Add qspi test details on AM43xx
[karo-tx-uboot.git] / drivers / net / npe / IxQMgrAqmIf.c
1 /* 
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.
23  *
24  * @par
25  * SPDX-License-Identifier:     BSD-3-Clause
26  * @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  */
113 UINT32 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  */
118 extern IxQMgrQInlinedReadWriteInfo ixQMgrQInlinedReadWriteInfo[];
119 UINT32 * ixQMgrAqmIfQueAccRegAddr[IX_QMGR_MAX_NUM_QUEUES];
120 UINT32 ixQMgrAqmIfQueLowStatRegAddr[IX_QMGR_MIN_QUEUPP_QID];
121 UINT32 ixQMgrAqmIfQueLowStatBitsOffset[IX_QMGR_MIN_QUEUPP_QID];
122 UINT32 ixQMgrAqmIfQueLowStatBitsMask;
123 UINT32 ixQMgrAqmIfQueUppStat0RegAddr;
124 UINT32 ixQMgrAqmIfQueUppStat1RegAddr;
125 UINT32 ixQMgrAqmIfQueUppStat0BitMask[IX_QMGR_MIN_QUEUPP_QID];
126 UINT32 ixQMgrAqmIfQueUppStat1BitMask[IX_QMGR_MIN_QUEUPP_QID];
127
128 /* 
129  * Fast mutexes, one for each queue, used to protect peek & poke functions
130  */
131 IxOsalFastMutex ixQMgrAqmIfPeekPokeFastMutex[IX_QMGR_MAX_NUM_QUEUES];
132
133 /*
134  * Function prototypes
135  */
136 PRIVATE unsigned
137 watermarkToAqmWatermark (IxQMgrWMLevel watermark );
138
139 PRIVATE unsigned
140 entrySizeToAqmEntrySize (IxQMgrQEntrySizeInWords entrySize);
141
142 PRIVATE unsigned
143 bufferSizeToAqmBufferSize (unsigned bufferSizeInWords);
144
145 PRIVATE void
146 ixQMgrAqmIfRegistersReset (void);
147
148 PRIVATE void
149 ixQMgrAqmIfEntryAddressGet (unsigned int entryIndex,
150                             UINT32 configRegWord,
151                             unsigned int qEntrySizeInwords,
152                             unsigned int qSizeInWords,
153                             UINT32 **address);
154 /*
155  * Function definitions
156  */
157 void
158 ixQMgrAqmIfInit (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 */
188         ixQMgrAqmIfQueAccRegAddr[i] = 
189             (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  */
257 void
258 ixQMgrAqmIfUninit (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  */
270 void
271 ixQMgrAqmIfBaseAddressSet (UINT32 address)
272 {
273     aqmBaseAddress = address;
274 }
275
276 /*
277  * Get the logical base address of AQM
278  */
279 void
280 ixQMgrAqmIfBaseAddressGet (UINT32 *address)
281 {
282     *address = aqmBaseAddress;
283 }
284
285 /*
286  * Get the logical base address of AQM SRAM
287  */
288 void
289 ixQMgrAqmIfSramBaseAddressGet (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  */
299 void
300 ixQMgrAqmIfQRegisterBitsWrite (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  */
364 void
365 ixQMgrAqmIfQStatusCheckValsCalc (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
441 void
442 ixQMgrAqmIfQInterruptEnable (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
463 void
464 ixQMgrAqmIfQInterruptDisable (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
485 void
486 ixQMgrAqmIfQueCfgWrite (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
529 void
530 ixQMgrAqmIfQueCfgRead (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
594 unsigned
595 ixQMgrAqmIfLog2 (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
612 void 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
638 void
639 ixQMgrAqmIfIntSrcSelWrite (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
650 void
651 ixQMgrAqmIfWatermarkSet (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
680 PRIVATE void
681 ixQMgrAqmIfEntryAddressGet (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
731 IX_STATUS
732 ixQMgrAqmIfQPeek (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
785 IX_STATUS
786 ixQMgrAqmIfQPoke (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
840 PRIVATE unsigned
841 watermarkToAqmWatermark (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
854 PRIVATE unsigned
855 entrySizeToAqmEntrySize (IxQMgrQEntrySizeInWords entrySize)
856 {
857     /* entrySize  1("00"),2("01"),4("10") */
858     return (ixQMgrAqmIfLog2 (entrySize));
859 }
860
861 PRIVATE unsigned
862 bufferSizeToAqmBufferSize (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  */
871 PRIVATE void
872 ixQMgrAqmIfRegistersReset (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