c73be5e881b70e3f8d9eb0072f6ea295baadbb41
[linux-2.6.git] / drivers / net / bcm5700 / queue.h
1 /******************************************************************************/
2 /*                                                                            */
3 /* Broadcom BCM5700 Linux Network Driver, Copyright (c) 2000 - 2004 Broadcom  */
4 /* Corporation.                                                               */
5 /* All rights reserved.                                                       */
6 /*                                                                            */
7 /* This program is free software; you can redistribute it and/or modify       */
8 /* it under the terms of the GNU General Public License as published by       */
9 /* the Free Software Foundation, located in the file LICENSE.                 */
10 /*                                                                            */
11 /* Queue functions.                                                           */
12 /*    void          QQ_InitQueue(PQQ_CONTAINER pQueue)                        */
13 /*    char          QQ_Full(PQQ_CONTAINER pQueue)                             */
14 /*    char          QQ_Empty(PQQ_CONTAINER pQueue)                            */
15 /*    unsigned int QQ_GetSize(PQQ_CONTAINER pQueue)                          */
16 /*    unsigned int QQ_GetEntryCnt(PQQ_CONTAINER pQueue)                      */
17 /*    char          QQ_PushHead(PQQ_CONTAINER pQueue, PQQ_ENTRY pEntry)       */
18 /*    char          QQ_PushTail(PQQ_CONTAINER pQueue, PQQ_ENTRY pEntry)       */
19 /*    PQQ_ENTRY     QQ_PopHead(PQQ_CONTAINER pQueue)                          */
20 /*    PQQ_ENTRY     QQ_PopTail(PQQ_CONTAINER pQueue)                          */
21 /*    PQQ_ENTRY     QQ_GetHead(PQQ_CONTAINER pQueue, unsigned int Idx)       */
22 /*    PQQ_ENTRY     QQ_GetTail(PQQ_CONTAINER pQueue, unsigned int Idx)       */
23 /*                                                                            */
24 /*                                                                            */
25 /* History:                                                                   */
26 /*    02/25/00 Hav Khauv        Initial version.                              */
27 /******************************************************************************/
28
29 #ifndef BCM_QUEUE_H
30 #define BCM_QUEUE_H
31
32
33
34 /******************************************************************************/
35 /* Queue definitions. */
36 /******************************************************************************/
37
38 /* Entry for queueing. */
39 typedef void *PQQ_ENTRY;
40
41
42 /* Queue header -- base type. */
43 typedef struct {
44     unsigned int Head;
45     unsigned int Tail;
46     unsigned int Size;
47     MM_ATOMIC_T EntryCnt;
48     PQQ_ENTRY Array[1];
49 } QQ_CONTAINER, *PQQ_CONTAINER;
50
51
52 /* Declare queue type macro. */
53 #define DECLARE_QUEUE_TYPE(_QUEUE_TYPE, _QUEUE_SIZE)            \
54                                                                 \
55     typedef struct {                                            \
56         QQ_CONTAINER Container;                                 \
57         PQQ_ENTRY EntryBuffer[_QUEUE_SIZE];                     \
58     } _QUEUE_TYPE, *P##_QUEUE_TYPE
59
60
61
62 /******************************************************************************/
63 /* Compilation switches. */
64 /******************************************************************************/
65
66 #if DBG
67 #undef QQ_NO_OVERFLOW_CHECK
68 #undef QQ_NO_UNDERFLOW_CHECK
69 #endif /* DBG */
70
71 #ifdef QQ_USE_MACROS
72 /* notdone */
73 #else
74
75 #ifdef QQ_NO_INLINE
76 #define __inline
77 #endif /* QQ_NO_INLINE */
78
79
80
81 /******************************************************************************/
82 /* Description:                                                               */
83 /*                                                                            */
84 /* Return:                                                                    */
85 /******************************************************************************/
86 __inline static void 
87 QQ_InitQueue(
88 PQQ_CONTAINER pQueue,
89 unsigned int QueueSize) {
90     pQueue->Head = 0;
91     pQueue->Tail = 0;
92     pQueue->Size = QueueSize+1;
93     MM_ATOMIC_SET(&pQueue->EntryCnt, 0);
94 } /* QQ_InitQueue */
95
96
97
98 /******************************************************************************/
99 /* Description:                                                               */
100 /*                                                                            */
101 /* Return:                                                                    */
102 /******************************************************************************/
103 __inline static char 
104 QQ_Full(
105 PQQ_CONTAINER pQueue) {
106     unsigned int NewHead;
107
108     NewHead = (pQueue->Head + 1) % pQueue->Size;
109
110     return(NewHead == pQueue->Tail);
111 } /* QQ_Full */
112
113
114
115 /******************************************************************************/
116 /* Description:                                                               */
117 /*                                                                            */
118 /* Return:                                                                    */
119 /******************************************************************************/
120 __inline static char 
121 QQ_Empty(
122 PQQ_CONTAINER pQueue) {
123     return(pQueue->Head == pQueue->Tail);
124 } /* QQ_Empty */
125
126
127
128 /******************************************************************************/
129 /* Description:                                                               */
130 /*                                                                            */
131 /* Return:                                                                    */
132 /******************************************************************************/
133 __inline static unsigned int 
134 QQ_GetSize(
135 PQQ_CONTAINER pQueue) {
136     return pQueue->Size;
137 } /* QQ_GetSize */
138
139
140
141 /******************************************************************************/
142 /* Description:                                                               */
143 /*                                                                            */
144 /* Return:                                                                    */
145 /******************************************************************************/
146 __inline static unsigned int 
147 QQ_GetEntryCnt(
148 PQQ_CONTAINER pQueue) {
149     return MM_ATOMIC_READ(&pQueue->EntryCnt);
150 } /* QQ_GetEntryCnt */
151
152
153
154 /******************************************************************************/
155 /* Description:                                                               */
156 /*                                                                            */
157 /* Return:                                                                    */
158 /*    TRUE entry was added successfully.                                      */
159 /*    FALSE queue is full.                                                    */
160 /******************************************************************************/
161 __inline static char 
162 QQ_PushHead(
163 PQQ_CONTAINER pQueue, 
164 PQQ_ENTRY pEntry) {
165     unsigned int Head;
166
167     Head = (pQueue->Head + 1) % pQueue->Size;
168
169 #if !defined(QQ_NO_OVERFLOW_CHECK)
170     if(Head == pQueue->Tail) {
171         return 0;
172     } /* if */
173 #endif /* QQ_NO_OVERFLOW_CHECK */
174
175     pQueue->Array[pQueue->Head] = pEntry;
176     MM_WMB();
177     pQueue->Head = Head;
178     MM_ATOMIC_INC(&pQueue->EntryCnt);
179
180     return -1;
181 } /* QQ_PushHead */
182
183
184
185 /******************************************************************************/
186 /* Description:                                                               */
187 /*                                                                            */
188 /* Return:                                                                    */
189 /*    TRUE entry was added successfully.                                      */
190 /*    FALSE queue is full.                                                    */
191 /******************************************************************************/
192 __inline static char 
193 QQ_PushTail(
194 PQQ_CONTAINER pQueue,
195 PQQ_ENTRY pEntry) {
196     unsigned int Tail;
197
198     Tail = pQueue->Tail;
199     if(Tail == 0) {
200         Tail = pQueue->Size;
201     } /* if */
202     Tail--;
203
204 #if !defined(QQ_NO_OVERFLOW_CHECK)
205     if(Tail == pQueue->Head) {
206         return 0;
207     } /* if */
208 #endif /* QQ_NO_OVERFLOW_CHECK */
209
210     pQueue->Array[Tail] = pEntry;
211     MM_WMB();
212     pQueue->Tail = Tail;
213     MM_ATOMIC_INC(&pQueue->EntryCnt);
214
215     return -1;
216 } /* QQ_PushTail */
217
218
219
220 /******************************************************************************/
221 /* Description:                                                               */
222 /*                                                                            */
223 /* Return:                                                                    */
224 /******************************************************************************/
225 __inline static PQQ_ENTRY
226 QQ_PopHead(
227 PQQ_CONTAINER pQueue) {
228     unsigned int Head;
229     unsigned int Tail;
230     PQQ_ENTRY Entry;
231
232     Head = pQueue->Head;
233     Tail = pQueue->Tail;
234
235     MM_MB();
236 #if !defined(QQ_NO_UNDERFLOW_CHECK)
237     if(Head == Tail) {
238         return (PQQ_ENTRY) 0;
239     } /* if */
240 #endif /* QQ_NO_UNDERFLOW_CHECK */
241
242     if(Head == 0) {
243         Head = pQueue->Size;
244     } /* if */
245     Head--;
246
247     Entry = pQueue->Array[Head];
248     MM_MB();
249     pQueue->Head = Head;
250     MM_ATOMIC_DEC(&pQueue->EntryCnt);
251
252     return Entry;
253 } /* QQ_PopHead */
254
255
256
257 /******************************************************************************/
258 /* Description:                                                               */
259 /*                                                                            */
260 /* Return:                                                                    */
261 /******************************************************************************/
262 __inline static PQQ_ENTRY
263 QQ_PopTail(
264 PQQ_CONTAINER pQueue) {
265     unsigned int Head;
266     unsigned int Tail;
267     PQQ_ENTRY Entry;
268
269     Head = pQueue->Head;
270     Tail = pQueue->Tail;
271
272     MM_MB();
273 #if !defined(QQ_NO_UNDERFLOW_CHECK)
274     if(Tail == Head) {
275         return (PQQ_ENTRY) 0;
276     } /* if */
277 #endif /* QQ_NO_UNDERFLOW_CHECK */
278
279     Entry = pQueue->Array[Tail];
280     MM_MB();
281     pQueue->Tail = (Tail + 1) % pQueue->Size;
282     MM_ATOMIC_DEC(&pQueue->EntryCnt);
283
284     return Entry;
285 } /* QQ_PopTail */
286
287
288
289 /******************************************************************************/
290 /* Description:                                                               */
291 /*                                                                            */
292 /* Return:                                                                    */
293 /******************************************************************************/
294 __inline static PQQ_ENTRY
295 QQ_GetHead(
296     PQQ_CONTAINER pQueue,
297     unsigned int Idx)
298 {
299     if(Idx >= (unsigned int) MM_ATOMIC_READ(&pQueue->EntryCnt))
300     {
301         return (PQQ_ENTRY) 0;
302     }
303
304     if(pQueue->Head > Idx)
305     {
306         Idx = pQueue->Head - Idx;
307     }
308     else
309     {
310         Idx = pQueue->Size - (Idx - pQueue->Head);
311     }
312     Idx--;
313
314     return pQueue->Array[Idx];
315 }
316
317
318
319 /******************************************************************************/
320 /* Description:                                                               */
321 /*                                                                            */
322 /* Return:                                                                    */
323 /******************************************************************************/
324 __inline static PQQ_ENTRY
325 QQ_GetTail(
326     PQQ_CONTAINER pQueue,
327     unsigned int Idx)
328 {
329     if(Idx >= (unsigned int) MM_ATOMIC_READ(&pQueue->EntryCnt))
330     {
331         return (PQQ_ENTRY) 0;
332     }
333
334     Idx += pQueue->Tail;
335     if(Idx >= pQueue->Size)
336     {
337         Idx = Idx - pQueue->Size;
338     }
339
340     return pQueue->Array[Idx];
341 }
342
343 #endif /* QQ_USE_MACROS */
344
345
346
347 #endif /* QUEUE_H */