uboot/drivers/net/bcm570x_queue.h
<<
>>
Prefs
   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. */
  41typedef void *PQQ_ENTRY;
  42
  43/* Linux Atomic Ops support */
  44typedef 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 */
  56extern __inline void
  57atomic_set(atomic_t* entry, int val)
  58{
  59    entry->counter = val;
  60}
  61extern __inline int
  62atomic_read(atomic_t* entry)
  63{
  64    return entry->counter;
  65}
  66extern __inline void
  67atomic_inc(atomic_t* entry)
  68{
  69    if(entry)
  70        entry->counter++;
  71}
  72
  73extern __inline void
  74atomic_dec(atomic_t* entry)
  75{
  76    if(entry)
  77        entry->counter--;
  78}
  79
  80extern __inline void
  81atomic_sub(int a, atomic_t* entry)
  82{
  83    if(entry)
  84        entry->counter -= a;
  85}
  86extern __inline void
  87atomic_add(int a, atomic_t* entry)
  88{
  89    if(entry)
  90        entry->counter += a;
  91}
  92
  93
  94/* Queue header -- base type. */
  95typedef 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/* Compilation switches. */
 115/******************************************************************************/
 116
 117#if DBG
 118#undef QQ_NO_OVERFLOW_CHECK
 119#undef QQ_NO_UNDERFLOW_CHECK
 120#endif /* DBG */
 121
 122#ifdef QQ_USE_MACROS
 123/* notdone */
 124#else
 125
 126#ifdef QQ_NO_INLINE
 127#define __inline
 128#endif /* QQ_NO_INLINE */
 129
 130/******************************************************************************/
 131/* Description:                                                               */
 132/*                                                                            */
 133/* Return:                                                                    */
 134/******************************************************************************/
 135extern __inline void
 136QQ_InitQueue(
 137PQQ_CONTAINER pQueue,
 138unsigned int QueueSize) {
 139    pQueue->Head = 0;
 140    pQueue->Tail = 0;
 141    pQueue->Size = QueueSize+1;
 142    atomic_set(&pQueue->EntryCnt, 0);
 143} /* QQ_InitQueue */
 144
 145
 146/******************************************************************************/
 147/* Description:                                                               */
 148/*                                                                            */
 149/* Return:                                                                    */
 150/******************************************************************************/
 151extern __inline char
 152QQ_Full(
 153PQQ_CONTAINER pQueue) {
 154    unsigned int NewHead;
 155
 156    NewHead = (pQueue->Head + 1) % pQueue->Size;
 157
 158    return(NewHead == pQueue->Tail);
 159} /* QQ_Full */
 160
 161
 162/******************************************************************************/
 163/* Description:                                                               */
 164/*                                                                            */
 165/* Return:                                                                    */
 166/******************************************************************************/
 167extern __inline char
 168QQ_Empty(
 169PQQ_CONTAINER pQueue) {
 170    return(pQueue->Head == pQueue->Tail);
 171} /* QQ_Empty */
 172
 173
 174/******************************************************************************/
 175/* Description:                                                               */
 176/*                                                                            */
 177/* Return:                                                                    */
 178/******************************************************************************/
 179extern __inline unsigned int
 180QQ_GetSize(
 181PQQ_CONTAINER pQueue) {
 182    return pQueue->Size;
 183} /* QQ_GetSize */
 184
 185
 186/******************************************************************************/
 187/* Description:                                                               */
 188/*                                                                            */
 189/* Return:                                                                    */
 190/******************************************************************************/
 191extern __inline unsigned int
 192QQ_GetEntryCnt(
 193PQQ_CONTAINER pQueue) {
 194    return atomic_read(&pQueue->EntryCnt);
 195} /* QQ_GetEntryCnt */
 196
 197
 198/******************************************************************************/
 199/* Description:                                                               */
 200/*                                                                            */
 201/* Return:                                                                    */
 202/*    TRUE entry was added successfully.                                      */
 203/*    FALSE queue is full.                                                    */
 204/******************************************************************************/
 205extern __inline char
 206QQ_PushHead(
 207PQQ_CONTAINER pQueue,
 208PQQ_ENTRY pEntry) {
 209    unsigned int Head;
 210
 211    Head = (pQueue->Head + 1) % pQueue->Size;
 212
 213#if !defined(QQ_NO_OVERFLOW_CHECK)
 214    if(Head == pQueue->Tail) {
 215        return 0;
 216    } /* if */
 217#endif /* QQ_NO_OVERFLOW_CHECK */
 218
 219    pQueue->Array[pQueue->Head] = pEntry;
 220    wmb();
 221    pQueue->Head = Head;
 222    atomic_inc(&pQueue->EntryCnt);
 223
 224    return -1;
 225} /* QQ_PushHead */
 226
 227
 228/******************************************************************************/
 229/* Description:                                                               */
 230/*                                                                            */
 231/* Return:                                                                    */
 232/*    TRUE entry was added successfully.                                      */
 233/*    FALSE queue is full.                                                    */
 234/******************************************************************************/
 235extern __inline char
 236QQ_PushTail(
 237PQQ_CONTAINER pQueue,
 238PQQ_ENTRY pEntry) {
 239    unsigned int Tail;
 240
 241    Tail = pQueue->Tail;
 242    if(Tail == 0) {
 243        Tail = pQueue->Size;
 244    } /* if */
 245    Tail--;
 246
 247#if !defined(QQ_NO_OVERFLOW_CHECK)
 248    if(Tail == pQueue->Head) {
 249        return 0;
 250    } /* if */
 251#endif /* QQ_NO_OVERFLOW_CHECK */
 252
 253    pQueue->Array[Tail] = pEntry;
 254    wmb();
 255    pQueue->Tail = Tail;
 256    atomic_inc(&pQueue->EntryCnt);
 257
 258    return -1;
 259} /* QQ_PushTail */
 260
 261
 262/******************************************************************************/
 263/* Description:                                                               */
 264/*                                                                            */
 265/* Return:                                                                    */
 266/******************************************************************************/
 267extern __inline PQQ_ENTRY
 268QQ_PopHead(
 269PQQ_CONTAINER pQueue) {
 270    unsigned int Head;
 271    PQQ_ENTRY Entry;
 272
 273    Head = pQueue->Head;
 274
 275#if !defined(QQ_NO_UNDERFLOW_CHECK)
 276    if(Head == pQueue->Tail) {
 277        return (PQQ_ENTRY) 0;
 278    } /* if */
 279#endif /* QQ_NO_UNDERFLOW_CHECK */
 280
 281    if(Head == 0) {
 282        Head = pQueue->Size;
 283    } /* if */
 284    Head--;
 285
 286    Entry = pQueue->Array[Head];
 287#ifdef EMBEDDED
 288    membar();
 289#else
 290    mb();
 291#endif
 292    pQueue->Head = Head;
 293    atomic_dec(&pQueue->EntryCnt);
 294
 295    return Entry;
 296} /* QQ_PopHead */
 297
 298
 299/******************************************************************************/
 300/* Description:                                                               */
 301/*                                                                            */
 302/* Return:                                                                    */
 303/******************************************************************************/
 304extern __inline PQQ_ENTRY
 305QQ_PopTail(
 306PQQ_CONTAINER pQueue) {
 307    unsigned int Tail;
 308    PQQ_ENTRY Entry;
 309
 310    Tail = pQueue->Tail;
 311
 312#if !defined(QQ_NO_UNDERFLOW_CHECK)
 313    if(Tail == pQueue->Head) {
 314        return (PQQ_ENTRY) 0;
 315    } /* if */
 316#endif /* QQ_NO_UNDERFLOW_CHECK */
 317
 318    Entry = pQueue->Array[Tail];
 319#ifdef EMBEDDED
 320    membar();
 321#else
 322    mb();
 323#endif
 324    pQueue->Tail = (Tail + 1) % pQueue->Size;
 325    atomic_dec(&pQueue->EntryCnt);
 326
 327    return Entry;
 328} /* QQ_PopTail */
 329
 330
 331/******************************************************************************/
 332/* Description:                                                               */
 333/*                                                                            */
 334/* Return:                                                                    */
 335/******************************************************************************/
 336extern __inline PQQ_ENTRY
 337QQ_GetHead(
 338    PQQ_CONTAINER pQueue,
 339    unsigned int Idx)
 340{
 341    if(Idx >= atomic_read(&pQueue->EntryCnt))
 342    {
 343        return (PQQ_ENTRY) 0;
 344    }
 345
 346    if(pQueue->Head > Idx)
 347    {
 348        Idx = pQueue->Head - Idx;
 349    }
 350    else
 351    {
 352        Idx = pQueue->Size - (Idx - pQueue->Head);
 353    }
 354    Idx--;
 355
 356    return pQueue->Array[Idx];
 357}
 358
 359
 360/******************************************************************************/
 361/* Description:                                                               */
 362/*                                                                            */
 363/* Return:                                                                    */
 364/******************************************************************************/
 365extern __inline PQQ_ENTRY
 366QQ_GetTail(
 367    PQQ_CONTAINER pQueue,
 368    unsigned int Idx)
 369{
 370    if(Idx >= atomic_read(&pQueue->EntryCnt))
 371    {
 372        return (PQQ_ENTRY) 0;
 373    }
 374
 375    Idx += pQueue->Tail;
 376    if(Idx >= pQueue->Size)
 377    {
 378        Idx = Idx - pQueue->Size;
 379    }
 380
 381    return pQueue->Array[Idx];
 382}
 383
 384#endif /* QQ_USE_MACROS */
 385
 386
 387#endif /* QUEUE_H */
 388