]> git.kernelconcepts.de Git - karo-tx-uboot.git/blob - drivers/bcm570x_queue.h
Initial revision
[karo-tx-uboot.git] / drivers / bcm570x_queue.h
1
2 /******************************************************************************/
3 /*                                                                            */
4 /* Broadcom BCM5700 Linux Network Driver, Copyright (c) 2000 Broadcom         */
5 /* Corporation.                                                               */
6 /* All rights reserved.                                                       */
7 /*                                                                            */
8 /* This program is free software; you can redistribute it and/or modify       */
9 /* it under the terms of the GNU General Public License as published by       */
10 /* the Free Software Foundation, located in the file LICENSE.                 */
11 /*                                                                            */
12 /* Queue functions.                                                           */
13 /*    void          QQ_InitQueue(PQQ_CONTAINER pQueue)                        */
14 /*    char          QQ_Full(PQQ_CONTAINER pQueue)                             */
15 /*    char          QQ_Empty(PQQ_CONTAINER pQueue)                            */
16 /*    unsigned int QQ_GetSize(PQQ_CONTAINER pQueue)                          */
17 /*    unsigned int QQ_GetEntryCnt(PQQ_CONTAINER pQueue)                      */
18 /*    char          QQ_PushHead(PQQ_CONTAINER pQueue, PQQ_ENTRY pEntry)       */
19 /*    char          QQ_PushTail(PQQ_CONTAINER pQueue, PQQ_ENTRY pEntry)       */
20 /*    PQQ_ENTRY     QQ_PopHead(PQQ_CONTAINER pQueue)                          */
21 /*    PQQ_ENTRY     QQ_PopTail(PQQ_CONTAINER pQueue)                          */
22 /*    PQQ_ENTRY     QQ_GetHead(PQQ_CONTAINER pQueue, unsigned int Idx)       */
23 /*    PQQ_ENTRY     QQ_GetTail(PQQ_CONTAINER pQueue, unsigned int Idx)       */
24 /*                                                                            */
25 /*                                                                            */
26 /* History:                                                                   */
27 /*    02/25/00 Hav Khauv        Initial version.                              */
28 /******************************************************************************/
29
30 #ifndef BCM_QUEUE_H
31 #define BCM_QUEUE_H
32 #ifndef EMBEDDED
33 #define EMBEDDED 1
34 #endif
35
36 /******************************************************************************/
37 /* Queue definitions. */
38 /******************************************************************************/
39
40 /* Entry for queueing. */
41 typedef void *PQQ_ENTRY;
42
43 /* Linux Atomic Ops support */
44 typedef struct { int counter; } atomic_t;
45
46
47 /*
48  * This combination of `inline' and `extern' has almost the effect of a
49  * macro.  The way to use it is to put a function definition in a header
50  * file with these keywords, and put another copy of the definition
51  * (lacking `inline' and `extern') in a library file.  The definition in
52  * the header file will cause most calls to the function to be inlined.
53  * If any uses of the function remain, they will refer to the single copy
54  * in the library.
55  */
56 extern __inline void
57 atomic_set(atomic_t* entry, int val)
58 {
59     entry->counter = val;
60 }
61 extern __inline int
62 atomic_read(atomic_t* entry)
63 {
64     return entry->counter;
65 }
66 extern __inline void
67 atomic_inc(atomic_t* entry)
68 {
69     if(entry)
70         entry->counter++;
71 }
72
73 extern __inline void
74 atomic_dec(atomic_t* entry)
75 {
76     if(entry)
77         entry->counter--;
78 }
79
80 extern __inline void
81 atomic_sub(int a, atomic_t* entry)
82 {
83     if(entry)
84         entry->counter -= a;
85 }
86 extern __inline void
87 atomic_add(int a, atomic_t* entry)
88 {
89     if(entry)
90         entry->counter += a;
91 }
92
93
94 /* Queue header -- base type. */
95 typedef struct {
96     unsigned int Head;
97     unsigned int Tail;
98     unsigned int Size;
99     atomic_t EntryCnt;
100     PQQ_ENTRY Array[1];
101 } QQ_CONTAINER, *PQQ_CONTAINER;
102
103
104 /* Declare queue type macro. */
105 #define DECLARE_QUEUE_TYPE(_QUEUE_TYPE, _QUEUE_SIZE)            \
106                                                                 \
107     typedef struct {                                            \
108         QQ_CONTAINER Container;                                 \
109         PQQ_ENTRY EntryBuffer[_QUEUE_SIZE];                     \
110     } _QUEUE_TYPE, *P##_QUEUE_TYPE
111
112
113
114 /******************************************************************************/
115 /* Compilation switches. */
116 /******************************************************************************/
117
118 #if DBG
119 #undef QQ_NO_OVERFLOW_CHECK
120 #undef QQ_NO_UNDERFLOW_CHECK
121 #endif /* DBG */
122
123 #ifdef QQ_USE_MACROS
124 /* notdone */
125 #else
126
127 #ifdef QQ_NO_INLINE
128 #define __inline
129 #endif /* QQ_NO_INLINE */
130
131 /******************************************************************************/
132 /* Description:                                                               */
133 /*                                                                            */
134 /* Return:                                                                    */
135 /******************************************************************************/
136 extern __inline void
137 QQ_InitQueue(
138 PQQ_CONTAINER pQueue,
139 unsigned int QueueSize) {
140     pQueue->Head = 0;
141     pQueue->Tail = 0;
142     pQueue->Size = QueueSize+1;
143     atomic_set(&pQueue->EntryCnt, 0);
144 } /* QQ_InitQueue */
145
146
147
148 /******************************************************************************/
149 /* Description:                                                               */
150 /*                                                                            */
151 /* Return:                                                                    */
152 /******************************************************************************/
153 extern __inline char
154 QQ_Full(
155 PQQ_CONTAINER pQueue) {
156     unsigned int NewHead;
157
158     NewHead = (pQueue->Head + 1) % pQueue->Size;
159
160     return(NewHead == pQueue->Tail);
161 } /* QQ_Full */
162
163
164
165 /******************************************************************************/
166 /* Description:                                                               */
167 /*                                                                            */
168 /* Return:                                                                    */
169 /******************************************************************************/
170 extern __inline char
171 QQ_Empty(
172 PQQ_CONTAINER pQueue) {
173     return(pQueue->Head == pQueue->Tail);
174 } /* QQ_Empty */
175
176
177
178 /******************************************************************************/
179 /* Description:                                                               */
180 /*                                                                            */
181 /* Return:                                                                    */
182 /******************************************************************************/
183 extern __inline unsigned int
184 QQ_GetSize(
185 PQQ_CONTAINER pQueue) {
186     return pQueue->Size;
187 } /* QQ_GetSize */
188
189
190
191 /******************************************************************************/
192 /* Description:                                                               */
193 /*                                                                            */
194 /* Return:                                                                    */
195 /******************************************************************************/
196 extern __inline unsigned int
197 QQ_GetEntryCnt(
198 PQQ_CONTAINER pQueue) {
199     return atomic_read(&pQueue->EntryCnt);
200 } /* QQ_GetEntryCnt */
201
202
203
204 /******************************************************************************/
205 /* Description:                                                               */
206 /*                                                                            */
207 /* Return:                                                                    */
208 /*    TRUE entry was added successfully.                                      */
209 /*    FALSE queue is full.                                                    */
210 /******************************************************************************/
211 extern __inline char
212 QQ_PushHead(
213 PQQ_CONTAINER pQueue,
214 PQQ_ENTRY pEntry) {
215     unsigned int Head;
216
217     Head = (pQueue->Head + 1) % pQueue->Size;
218
219 #if !defined(QQ_NO_OVERFLOW_CHECK)
220     if(Head == pQueue->Tail) {
221         return 0;
222     } /* if */
223 #endif /* QQ_NO_OVERFLOW_CHECK */
224
225     pQueue->Array[pQueue->Head] = pEntry;
226     wmb();
227     pQueue->Head = Head;
228     atomic_inc(&pQueue->EntryCnt);
229
230     return -1;
231 } /* QQ_PushHead */
232
233
234
235 /******************************************************************************/
236 /* Description:                                                               */
237 /*                                                                            */
238 /* Return:                                                                    */
239 /*    TRUE entry was added successfully.                                      */
240 /*    FALSE queue is full.                                                    */
241 /******************************************************************************/
242 extern __inline char
243 QQ_PushTail(
244 PQQ_CONTAINER pQueue,
245 PQQ_ENTRY pEntry) {
246     unsigned int Tail;
247
248     Tail = pQueue->Tail;
249     if(Tail == 0) {
250         Tail = pQueue->Size;
251     } /* if */
252     Tail--;
253
254 #if !defined(QQ_NO_OVERFLOW_CHECK)
255     if(Tail == pQueue->Head) {
256         return 0;
257     } /* if */
258 #endif /* QQ_NO_OVERFLOW_CHECK */
259
260     pQueue->Array[Tail] = pEntry;
261     wmb();
262     pQueue->Tail = Tail;
263     atomic_inc(&pQueue->EntryCnt);
264
265     return -1;
266 } /* QQ_PushTail */
267
268
269
270 /******************************************************************************/
271 /* Description:                                                               */
272 /*                                                                            */
273 /* Return:                                                                    */
274 /******************************************************************************/
275 extern __inline PQQ_ENTRY
276 QQ_PopHead(
277 PQQ_CONTAINER pQueue) {
278     unsigned int Head;
279     PQQ_ENTRY Entry;
280
281     Head = pQueue->Head;
282
283 #if !defined(QQ_NO_UNDERFLOW_CHECK)
284     if(Head == pQueue->Tail) {
285         return (PQQ_ENTRY) 0;
286     } /* if */
287 #endif /* QQ_NO_UNDERFLOW_CHECK */
288
289     if(Head == 0) {
290         Head = pQueue->Size;
291     } /* if */
292     Head--;
293
294     Entry = pQueue->Array[Head];
295 #ifdef EMBEDDED
296     membar();
297 #else
298     mb();
299 #endif
300     pQueue->Head = Head;
301     atomic_dec(&pQueue->EntryCnt);
302
303     return Entry;
304 } /* QQ_PopHead */
305
306
307
308 /******************************************************************************/
309 /* Description:                                                               */
310 /*                                                                            */
311 /* Return:                                                                    */
312 /******************************************************************************/
313 extern __inline PQQ_ENTRY
314 QQ_PopTail(
315 PQQ_CONTAINER pQueue) {
316     unsigned int Tail;
317     PQQ_ENTRY Entry;
318
319     Tail = pQueue->Tail;
320
321 #if !defined(QQ_NO_UNDERFLOW_CHECK)
322     if(Tail == pQueue->Head) {
323         return (PQQ_ENTRY) 0;
324     } /* if */
325 #endif /* QQ_NO_UNDERFLOW_CHECK */
326
327     Entry = pQueue->Array[Tail];
328 #ifdef EMBEDDED
329     membar();
330 #else
331     mb();
332 #endif
333     pQueue->Tail = (Tail + 1) % pQueue->Size;
334     atomic_dec(&pQueue->EntryCnt);
335
336     return Entry;
337 } /* QQ_PopTail */
338
339
340
341 /******************************************************************************/
342 /* Description:                                                               */
343 /*                                                                            */
344 /* Return:                                                                    */
345 /******************************************************************************/
346 extern __inline PQQ_ENTRY
347 QQ_GetHead(
348     PQQ_CONTAINER pQueue,
349     unsigned int Idx)
350 {
351     if(Idx >= atomic_read(&pQueue->EntryCnt))
352     {
353         return (PQQ_ENTRY) 0;
354     }
355
356     if(pQueue->Head > Idx)
357     {
358         Idx = pQueue->Head - Idx;
359     }
360     else
361     {
362         Idx = pQueue->Size - (Idx - pQueue->Head);
363     }
364     Idx--;
365
366     return pQueue->Array[Idx];
367 }
368
369
370
371 /******************************************************************************/
372 /* Description:                                                               */
373 /*                                                                            */
374 /* Return:                                                                    */
375 /******************************************************************************/
376 extern __inline PQQ_ENTRY
377 QQ_GetTail(
378     PQQ_CONTAINER pQueue,
379     unsigned int Idx)
380 {
381     if(Idx >= atomic_read(&pQueue->EntryCnt))
382     {
383         return (PQQ_ENTRY) 0;
384     }
385
386     Idx += pQueue->Tail;
387     if(Idx >= pQueue->Size)
388     {
389         Idx = Idx - pQueue->Size;
390     }
391
392     return pQueue->Array[Idx];
393 }
394
395 #endif /* QQ_USE_MACROS */
396
397
398
399 #endif /* QUEUE_H */