bcm570x_queue.h 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387
  1. /******************************************************************************/
  2. /* */
  3. /* Broadcom BCM5700 Linux Network Driver, Copyright (c) 2000 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. #ifndef BCM_QUEUE_H
  29. #define BCM_QUEUE_H
  30. #ifndef EMBEDDED
  31. #define EMBEDDED 1
  32. #endif
  33. /******************************************************************************/
  34. /* Queue definitions. */
  35. /******************************************************************************/
  36. /* Entry for queueing. */
  37. typedef void *PQQ_ENTRY;
  38. /* Linux Atomic Ops support */
  39. typedef struct { int counter; } atomic_t;
  40. /*
  41. * This combination of `inline' and `extern' has almost the effect of a
  42. * macro. The way to use it is to put a function definition in a header
  43. * file with these keywords, and put another copy of the definition
  44. * (lacking `inline' and `extern') in a library file. The definition in
  45. * the header file will cause most calls to the function to be inlined.
  46. * If any uses of the function remain, they will refer to the single copy
  47. * in the library.
  48. */
  49. extern __inline void
  50. atomic_set(atomic_t* entry, int val)
  51. {
  52. entry->counter = val;
  53. }
  54. extern __inline int
  55. atomic_read(atomic_t* entry)
  56. {
  57. return entry->counter;
  58. }
  59. extern __inline void
  60. atomic_inc(atomic_t* entry)
  61. {
  62. if(entry)
  63. entry->counter++;
  64. }
  65. extern __inline void
  66. atomic_dec(atomic_t* entry)
  67. {
  68. if(entry)
  69. entry->counter--;
  70. }
  71. extern __inline void
  72. atomic_sub(int a, atomic_t* entry)
  73. {
  74. if(entry)
  75. entry->counter -= a;
  76. }
  77. extern __inline void
  78. atomic_add(int a, atomic_t* entry)
  79. {
  80. if(entry)
  81. entry->counter += a;
  82. }
  83. /* Queue header -- base type. */
  84. typedef struct {
  85. unsigned int Head;
  86. unsigned int Tail;
  87. unsigned int Size;
  88. atomic_t EntryCnt;
  89. PQQ_ENTRY Array[1];
  90. } QQ_CONTAINER, *PQQ_CONTAINER;
  91. /* Declare queue type macro. */
  92. #define DECLARE_QUEUE_TYPE(_QUEUE_TYPE, _QUEUE_SIZE) \
  93. \
  94. typedef struct { \
  95. QQ_CONTAINER Container; \
  96. PQQ_ENTRY EntryBuffer[_QUEUE_SIZE]; \
  97. } _QUEUE_TYPE, *P##_QUEUE_TYPE
  98. /******************************************************************************/
  99. /* Compilation switches. */
  100. /******************************************************************************/
  101. #if DBG
  102. #undef QQ_NO_OVERFLOW_CHECK
  103. #undef QQ_NO_UNDERFLOW_CHECK
  104. #endif /* DBG */
  105. #ifdef QQ_USE_MACROS
  106. /* notdone */
  107. #else
  108. #ifdef QQ_NO_INLINE
  109. #define __inline
  110. #endif /* QQ_NO_INLINE */
  111. /******************************************************************************/
  112. /* Description: */
  113. /* */
  114. /* Return: */
  115. /******************************************************************************/
  116. extern __inline void
  117. QQ_InitQueue(
  118. PQQ_CONTAINER pQueue,
  119. unsigned int QueueSize) {
  120. pQueue->Head = 0;
  121. pQueue->Tail = 0;
  122. pQueue->Size = QueueSize+1;
  123. atomic_set(&pQueue->EntryCnt, 0);
  124. } /* QQ_InitQueue */
  125. /******************************************************************************/
  126. /* Description: */
  127. /* */
  128. /* Return: */
  129. /******************************************************************************/
  130. extern __inline char
  131. QQ_Full(
  132. PQQ_CONTAINER pQueue) {
  133. unsigned int NewHead;
  134. NewHead = (pQueue->Head + 1) % pQueue->Size;
  135. return(NewHead == pQueue->Tail);
  136. } /* QQ_Full */
  137. /******************************************************************************/
  138. /* Description: */
  139. /* */
  140. /* Return: */
  141. /******************************************************************************/
  142. extern __inline char
  143. QQ_Empty(
  144. PQQ_CONTAINER pQueue) {
  145. return(pQueue->Head == pQueue->Tail);
  146. } /* QQ_Empty */
  147. /******************************************************************************/
  148. /* Description: */
  149. /* */
  150. /* Return: */
  151. /******************************************************************************/
  152. extern __inline unsigned int
  153. QQ_GetSize(
  154. PQQ_CONTAINER pQueue) {
  155. return pQueue->Size;
  156. } /* QQ_GetSize */
  157. /******************************************************************************/
  158. /* Description: */
  159. /* */
  160. /* Return: */
  161. /******************************************************************************/
  162. extern __inline unsigned int
  163. QQ_GetEntryCnt(
  164. PQQ_CONTAINER pQueue) {
  165. return atomic_read(&pQueue->EntryCnt);
  166. } /* QQ_GetEntryCnt */
  167. /******************************************************************************/
  168. /* Description: */
  169. /* */
  170. /* Return: */
  171. /* TRUE entry was added successfully. */
  172. /* FALSE queue is full. */
  173. /******************************************************************************/
  174. extern __inline char
  175. QQ_PushHead(
  176. PQQ_CONTAINER pQueue,
  177. PQQ_ENTRY pEntry) {
  178. unsigned int Head;
  179. Head = (pQueue->Head + 1) % pQueue->Size;
  180. #if !defined(QQ_NO_OVERFLOW_CHECK)
  181. if(Head == pQueue->Tail) {
  182. return 0;
  183. } /* if */
  184. #endif /* QQ_NO_OVERFLOW_CHECK */
  185. pQueue->Array[pQueue->Head] = pEntry;
  186. wmb();
  187. pQueue->Head = Head;
  188. atomic_inc(&pQueue->EntryCnt);
  189. return -1;
  190. } /* QQ_PushHead */
  191. /******************************************************************************/
  192. /* Description: */
  193. /* */
  194. /* Return: */
  195. /* TRUE entry was added successfully. */
  196. /* FALSE queue is full. */
  197. /******************************************************************************/
  198. extern __inline char
  199. QQ_PushTail(
  200. PQQ_CONTAINER pQueue,
  201. PQQ_ENTRY pEntry) {
  202. unsigned int Tail;
  203. Tail = pQueue->Tail;
  204. if(Tail == 0) {
  205. Tail = pQueue->Size;
  206. } /* if */
  207. Tail--;
  208. #if !defined(QQ_NO_OVERFLOW_CHECK)
  209. if(Tail == pQueue->Head) {
  210. return 0;
  211. } /* if */
  212. #endif /* QQ_NO_OVERFLOW_CHECK */
  213. pQueue->Array[Tail] = pEntry;
  214. wmb();
  215. pQueue->Tail = Tail;
  216. atomic_inc(&pQueue->EntryCnt);
  217. return -1;
  218. } /* QQ_PushTail */
  219. /******************************************************************************/
  220. /* Description: */
  221. /* */
  222. /* Return: */
  223. /******************************************************************************/
  224. extern __inline PQQ_ENTRY
  225. QQ_PopHead(
  226. PQQ_CONTAINER pQueue) {
  227. unsigned int Head;
  228. PQQ_ENTRY Entry;
  229. Head = pQueue->Head;
  230. #if !defined(QQ_NO_UNDERFLOW_CHECK)
  231. if(Head == pQueue->Tail) {
  232. return (PQQ_ENTRY) 0;
  233. } /* if */
  234. #endif /* QQ_NO_UNDERFLOW_CHECK */
  235. if(Head == 0) {
  236. Head = pQueue->Size;
  237. } /* if */
  238. Head--;
  239. Entry = pQueue->Array[Head];
  240. #ifdef EMBEDDED
  241. membar();
  242. #else
  243. mb();
  244. #endif
  245. pQueue->Head = Head;
  246. atomic_dec(&pQueue->EntryCnt);
  247. return Entry;
  248. } /* QQ_PopHead */
  249. /******************************************************************************/
  250. /* Description: */
  251. /* */
  252. /* Return: */
  253. /******************************************************************************/
  254. extern __inline PQQ_ENTRY
  255. QQ_PopTail(
  256. PQQ_CONTAINER pQueue) {
  257. unsigned int Tail;
  258. PQQ_ENTRY Entry;
  259. Tail = pQueue->Tail;
  260. #if !defined(QQ_NO_UNDERFLOW_CHECK)
  261. if(Tail == pQueue->Head) {
  262. return (PQQ_ENTRY) 0;
  263. } /* if */
  264. #endif /* QQ_NO_UNDERFLOW_CHECK */
  265. Entry = pQueue->Array[Tail];
  266. #ifdef EMBEDDED
  267. membar();
  268. #else
  269. mb();
  270. #endif
  271. pQueue->Tail = (Tail + 1) % pQueue->Size;
  272. atomic_dec(&pQueue->EntryCnt);
  273. return Entry;
  274. } /* QQ_PopTail */
  275. /******************************************************************************/
  276. /* Description: */
  277. /* */
  278. /* Return: */
  279. /******************************************************************************/
  280. extern __inline PQQ_ENTRY
  281. QQ_GetHead(
  282. PQQ_CONTAINER pQueue,
  283. unsigned int Idx)
  284. {
  285. if(Idx >= atomic_read(&pQueue->EntryCnt))
  286. {
  287. return (PQQ_ENTRY) 0;
  288. }
  289. if(pQueue->Head > Idx)
  290. {
  291. Idx = pQueue->Head - Idx;
  292. }
  293. else
  294. {
  295. Idx = pQueue->Size - (Idx - pQueue->Head);
  296. }
  297. Idx--;
  298. return pQueue->Array[Idx];
  299. }
  300. /******************************************************************************/
  301. /* Description: */
  302. /* */
  303. /* Return: */
  304. /******************************************************************************/
  305. extern __inline PQQ_ENTRY
  306. QQ_GetTail(
  307. PQQ_CONTAINER pQueue,
  308. unsigned int Idx)
  309. {
  310. if(Idx >= atomic_read(&pQueue->EntryCnt))
  311. {
  312. return (PQQ_ENTRY) 0;
  313. }
  314. Idx += pQueue->Tail;
  315. if(Idx >= pQueue->Size)
  316. {
  317. Idx = Idx - pQueue->Size;
  318. }
  319. return pQueue->Array[Idx];
  320. }
  321. #endif /* QQ_USE_MACROS */
  322. #endif /* QUEUE_H */