/******************************************************************************//* *//* Broadcom BCM5700 Linux Network Driver, Copyright (c) 2000 - 2003 Broadcom *//* Corporation. *//* All rights reserved. *//* *//* This program is free software; you can redistribute it and/or modify *//* it under the terms of the GNU General Public License as published by *//* the Free Software Foundation, located in the file LICENSE. *//* *//* Queue functions. *//* void QQ_InitQueue(PQQ_CONTAINER pQueue) *//* char QQ_Full(PQQ_CONTAINER pQueue) *//* char QQ_Empty(PQQ_CONTAINER pQueue) *//* unsigned int QQ_GetSize(PQQ_CONTAINER pQueue) *//* unsigned int QQ_GetEntryCnt(PQQ_CONTAINER pQueue) *//* char QQ_PushHead(PQQ_CONTAINER pQueue, PQQ_ENTRY pEntry) *//* char QQ_PushTail(PQQ_CONTAINER pQueue, PQQ_ENTRY pEntry) *//* PQQ_ENTRY QQ_PopHead(PQQ_CONTAINER pQueue) *//* PQQ_ENTRY QQ_PopTail(PQQ_CONTAINER pQueue) *//* PQQ_ENTRY QQ_GetHead(PQQ_CONTAINER pQueue, unsigned int Idx) *//* PQQ_ENTRY QQ_GetTail(PQQ_CONTAINER pQueue, unsigned int Idx) *//* *//* *//* History: *//* 02/25/00 Hav Khauv Initial version. *//******************************************************************************/#ifndef BCM_QUEUE_H#define BCM_QUEUE_H/******************************************************************************//* Queue definitions. *//******************************************************************************//* Entry for queueing. */typedef void *PQQ_ENTRY;/* Queue header -- base type. */typedef struct {unsigned int Head;unsigned int Tail;unsigned int Size;MM_ATOMIC_T EntryCnt;PQQ_ENTRY Array[1];} QQ_CONTAINER, *PQQ_CONTAINER;/* Declare queue type macro. */#define DECLARE_QUEUE_TYPE(_QUEUE_TYPE, _QUEUE_SIZE) \\typedef struct { \QQ_CONTAINER Container; \PQQ_ENTRY EntryBuffer[_QUEUE_SIZE]; \} _QUEUE_TYPE, *P##_QUEUE_TYPE/******************************************************************************//* Compilation switches. *//******************************************************************************/#if DBG#undef QQ_NO_OVERFLOW_CHECK#undef QQ_NO_UNDERFLOW_CHECK#endif /* DBG */#ifdef QQ_USE_MACROS/* notdone */#else#ifdef QQ_NO_INLINE#define __inline#endif /* QQ_NO_INLINE *//******************************************************************************//* Description: *//* *//* Return: *//******************************************************************************/__inline static voidQQ_InitQueue(PQQ_CONTAINER pQueue,unsigned int QueueSize) {pQueue->Head = 0;pQueue->Tail = 0;pQueue->Size = QueueSize+1;MM_ATOMIC_SET(&pQueue->EntryCnt, 0);} /* QQ_InitQueue *//******************************************************************************//* Description: *//* *//* Return: *//******************************************************************************/__inline static charQQ_Full(PQQ_CONTAINER pQueue) {unsigned int NewHead;NewHead = (pQueue->Head + 1) % pQueue->Size;return(NewHead == pQueue->Tail);} /* QQ_Full *//******************************************************************************//* Description: *//* *//* Return: *//******************************************************************************/__inline static charQQ_Empty(PQQ_CONTAINER pQueue) {return(pQueue->Head == pQueue->Tail);} /* QQ_Empty *//******************************************************************************//* Description: *//* *//* Return: *//******************************************************************************/__inline static unsigned intQQ_GetSize(PQQ_CONTAINER pQueue) {return pQueue->Size;} /* QQ_GetSize *//******************************************************************************//* Description: *//* *//* Return: *//******************************************************************************/__inline static unsigned intQQ_GetEntryCnt(PQQ_CONTAINER pQueue) {return MM_ATOMIC_READ(&pQueue->EntryCnt);} /* QQ_GetEntryCnt *//******************************************************************************//* Description: *//* *//* Return: *//* TRUE entry was added successfully. *//* FALSE queue is full. *//******************************************************************************/__inline static charQQ_PushHead(PQQ_CONTAINER pQueue,PQQ_ENTRY pEntry) {unsigned int Head;Head = (pQueue->Head + 1) % pQueue->Size;#if !defined(QQ_NO_OVERFLOW_CHECK)if(Head == pQueue->Tail) {return 0;} /* if */#endif /* QQ_NO_OVERFLOW_CHECK */pQueue->Array[pQueue->Head] = pEntry;MM_WMB();pQueue->Head = Head;MM_ATOMIC_INC(&pQueue->EntryCnt);return -1;} /* QQ_PushHead *//******************************************************************************//* Description: *//* *//* Return: *//* TRUE entry was added successfully. *//* FALSE queue is full. *//******************************************************************************/__inline static charQQ_PushTail(PQQ_CONTAINER pQueue,PQQ_ENTRY pEntry) {unsigned int Tail;Tail = pQueue->Tail;if(Tail == 0) {Tail = pQueue->Size;} /* if */Tail--;#if !defined(QQ_NO_OVERFLOW_CHECK)if(Tail == pQueue->Head) {return 0;} /* if */#endif /* QQ_NO_OVERFLOW_CHECK */pQueue->Array[Tail] = pEntry;MM_WMB();pQueue->Tail = Tail;MM_ATOMIC_INC(&pQueue->EntryCnt);return -1;} /* QQ_PushTail *//******************************************************************************//* Description: *//* *//* Return: *//******************************************************************************/__inline static PQQ_ENTRYQQ_PopHead(PQQ_CONTAINER pQueue) {unsigned int Head;unsigned int Tail;PQQ_ENTRY Entry;Head = pQueue->Head;Tail = pQueue->Tail;MM_MB();#if !defined(QQ_NO_UNDERFLOW_CHECK)if(Head == Tail) {return (PQQ_ENTRY) 0;} /* if */#endif /* QQ_NO_UNDERFLOW_CHECK */if(Head == 0) {Head = pQueue->Size;} /* if */Head--;Entry = pQueue->Array[Head];MM_MB();pQueue->Head = Head;MM_ATOMIC_DEC(&pQueue->EntryCnt);return Entry;} /* QQ_PopHead *//******************************************************************************//* Description: *//* *//* Return: *//******************************************************************************/__inline static PQQ_ENTRYQQ_PopTail(PQQ_CONTAINER pQueue) {unsigned int Head;unsigned int Tail;PQQ_ENTRY Entry;Head = pQueue->Head;Tail = pQueue->Tail;MM_MB();#if !defined(QQ_NO_UNDERFLOW_CHECK)if(Tail == Head) {return (PQQ_ENTRY) 0;} /* if */#endif /* QQ_NO_UNDERFLOW_CHECK */Entry = pQueue->Array[Tail];MM_MB();pQueue->Tail = (Tail + 1) % pQueue->Size;MM_ATOMIC_DEC(&pQueue->EntryCnt);return Entry;} /* QQ_PopTail *//******************************************************************************//* Description: *//* *//* Return: *//******************************************************************************/__inline static PQQ_ENTRYQQ_GetHead(PQQ_CONTAINER pQueue,unsigned int Idx){if(Idx >= (unsigned int) MM_ATOMIC_READ(&pQueue->EntryCnt)){return (PQQ_ENTRY) 0;}if(pQueue->Head > Idx){Idx = pQueue->Head - Idx;}else{Idx = pQueue->Size - (Idx - pQueue->Head);}Idx--;return pQueue->Array[Idx];}/******************************************************************************//* Description: *//* *//* Return: *//******************************************************************************/__inline static PQQ_ENTRYQQ_GetTail(PQQ_CONTAINER pQueue,unsigned int Idx){if(Idx >= (unsigned int) MM_ATOMIC_READ(&pQueue->EntryCnt)){return (PQQ_ENTRY) 0;}Idx += pQueue->Tail;if(Idx >= pQueue->Size){Idx = Idx - pQueue->Size;}return pQueue->Array[Idx];}#endif /* QQ_USE_MACROS */#endif /* QUEUE_H */