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