1/*******************************************************************************
2*Copyright (c) 2014 PMC-Sierra, Inc.  All rights reserved.
3*
4*Redistribution and use in source and binary forms, with or without modification, are permitted provided
5*that the following conditions are met:
6*1. Redistributions of source code must retain the above copyright notice, this list of conditions and the
7*following disclaimer.
8*2. Redistributions in binary form must reproduce the above copyright notice,
9*this list of conditions and the following disclaimer in the documentation and/or other materials provided
10*with the distribution.
11*
12*THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED
13*WARRANTIES,INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
14*FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
15*FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
16*NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
17*BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
18*LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
19*SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE
20*
21* $FreeBSD$
22*
23********************************************************************************/
24/*******************************************************************************/
25/** \file
26 *
27 * The file defines list data structures for SAS/SATA TD layer
28 *
29 */
30
31#ifndef __TDLIST_H__
32#define __TDLIST_H__
33
34
35typedef struct tdList_s tdList_t;
36
37struct tdList_s {
38  tdList_t  *flink;
39  tdList_t  *blink;
40};
41
42#define TDLIST_NEXT_ENTRY(ptr, type, member)        \
43  container_of((ptr)->flink, type, member)
44
45#define TDLIST_INIT_HDR(hdr)                        \
46  do {                                              \
47    ((tdList_t *)(hdr))->flink = (tdList_t *)(hdr); \
48    ((tdList_t *)(hdr))->blink = (tdList_t *)(hdr); \
49  } while (0)
50
51#define TDLIST_INIT_ELEMENT(hdr)                     \
52  do {                                               \
53    ((tdList_t *)(hdr))->flink = (tdList_t *)agNULL; \
54    ((tdList_t *)(hdr))->blink = (tdList_t *)agNULL; \
55  } while (0)
56
57#define TDLIST_ENQUEUE_AT_HEAD(toAddHdr,listHdr)                                \
58  do {                                                                          \
59    ((tdList_t *)(toAddHdr))->flink           = ((tdList_t *)(listHdr))->flink; \
60    ((tdList_t *)(toAddHdr))->blink           = (tdList_t *)(listHdr) ;         \
61    ((tdList_t *)(listHdr))->flink->blink     = (tdList_t *)(toAddHdr);         \
62    ((tdList_t *)(listHdr))->flink            = (tdList_t *)(toAddHdr);         \
63  } while (0)
64
65#define TDLIST_ENQUEUE_AT_TAIL(toAddHdr,listHdr)                                \
66  do {                                                                          \
67    ((tdList_t *)(toAddHdr))->flink           = (tdList_t *)(listHdr);          \
68    ((tdList_t *)(toAddHdr))->blink           = ((tdList_t *)(listHdr))->blink; \
69    ((tdList_t *)(listHdr))->blink->flink     = (tdList_t *)(toAddHdr);         \
70    ((tdList_t *)(listHdr))->blink            = (tdList_t *)(toAddHdr);         \
71  } while (0)
72
73#define TDLIST_EMPTY(listHdr) \
74  (((tdList_t *)(listHdr))->flink == ((tdList_t *)(listHdr)))
75
76#define TDLIST_NOT_EMPTY(listHdr) \
77  (!TDLIST_EMPTY(listHdr))
78
79#define TDLIST_DEQUEUE_THIS(hdr)                                      \
80  do {                                                                \
81    ((tdList_t *)(hdr))->blink->flink = ((tdList_t *)(hdr))->flink;   \
82    ((tdList_t *)(hdr))->flink->blink = ((tdList_t *)(hdr))->blink;   \
83    ((tdList_t *)(hdr))->flink = ((tdList_t *)(hdr))->blink = agNULL; \
84  } while (0)
85
86#define TDLIST_DEQUEUE_FROM_HEAD_FAST(atHeadHdr,listHdr)                              \
87  do {                                                                                \
88    *((tdList_t **)(atHeadHdr))                 = ((tdList_t *)(listHdr))->flink;     \
89    (*((tdList_t **)(atHeadHdr)))->flink->blink = (tdList_t *)(listHdr);              \
90    ((tdList_t *)(listHdr))->flink              = (*(tdList_t **)(atHeadHdr))->flink; \
91  } while (0)
92
93#define TDLIST_DEQUEUE_FROM_HEAD(atHeadHdr,listHdr)             \
94do {                                                            \
95  if (TDLIST_NOT_EMPTY((listHdr)))                              \
96  {                                                             \
97    TDLIST_DEQUEUE_FROM_HEAD_FAST(atHeadHdr,listHdr);           \
98  }                                                             \
99  else                                                          \
100  {                                                             \
101    (*((tdList_t **)(atHeadHdr))) = (tdList_t *)agNULL;         \
102  }                                                             \
103} while (0)
104
105#define TDLIST_DEQUEUE_FROM_TAIL_FAST(atTailHdr,listHdr)                                \
106  do {                                                                                  \
107    (*((tdList_t **)(atTailHdr)))               = ((tdList_t *)(listHdr))->blink;       \
108    (*((tdList_t **)(atTailHdr)))->blink->flink = (tdList_t *)(listHdr);                \
109    ((tdList_t *)(listHdr))->blink              = (*((tdList_t **)(atTailHdr)))->blink; \
110  } while (0)
111
112#define TDLIST_DEQUEUE_FROM_TAIL(atTailHdr,listHdr)               \
113  do {                                                            \
114    if (TDLIST_NOT_EMPTY((listHdr)))                              \
115    {                                                             \
116      TDLIST_DEQUEUE_FROM_TAIL_FAST(atTailHdr,listHdr);           \
117    }                                                             \
118    else                                                          \
119    {                                                             \
120      (*((tdList_t **)(atTailHdr))) = (tdList_t *)agNULL;         \
121    }                                                             \
122  } while (0)
123
124#define TDLIST_ENQUEUE_LIST_AT_TAIL_FAST(toAddListHdr, listHdr)               \
125  do {                                                                        \
126    ((tdList_t *)toAddListHdr)->blink->flink = ((tdList_t *)listHdr);         \
127    ((tdList_t *)toAddListHdr)->flink->blink = ((tdList_t *)listHdr)->blink;  \
128    ((tdList_t *)listHdr)->blink->flink = ((tdList_t *)toAddListHdr)->flink;  \
129    ((tdList_t *)listHdr)->blink = ((tdList_t *)toAddListHdr)->blink;         \
130    TDLIST_INIT_HDR(toAddListHdr);                                            \
131  } while (0)
132
133#define TDLIST_ENQUEUE_LIST_AT_TAIL(toAddListHdr, listHdr)                    \
134  do {                                                                        \
135    if (TDLIST_NOT_EMPTY(toAddListHdr))                                       \
136    {                                                                         \
137      TDLIST_ENQUEUE_LIST_AT_TAIL_FAST(toAddListHdr, listHdr);                \
138    }                                                                         \
139  } while (0)
140
141#define TDLIST_ENQUEUE_LIST_AT_HEAD_FAST(toAddListHdr, listHdr)               \
142  do {                                                                        \
143    ((tdList_t *)toAddListHdr)->blink->flink = ((tdList_t *)listHdr)->flink;  \
144    ((tdList_t *)toAddListHdr)->flink->blink = ((tdList_t *)listHdr);         \
145    ((tdList_t *)listHdr)->flink->blink = ((tdList_t *)toAddListHdr)->blink;  \
146    ((tdList_t *)listHdr)->flink = ((tdList_t *)toAddListHdr)->flink;         \
147    TDLIST_INIT_HDR(toAddListHdr);                                            \
148  } while (0)
149
150#define TDLIST_ENQUEUE_LIST_AT_HEAD(toAddListHdr, listHdr)                    \
151  do {                                                                        \
152    if (TDLIST_NOT_EMPTY(toAddListHdr))                                       \
153    {                                                                         \
154      TDLIST_ENQUEUE_LIST_AT_HEAD_FAST(toAddListHdr, listHdr);                \
155    }                                                                         \
156  } while (0)
157
158#define TD_FIELD_OFFSET(baseType,fieldName) \
159                    ((bit32)((bitptr)(&(((baseType *)0)->fieldName))))
160
161#define TDLIST_OBJECT_BASE(baseType,fieldName,fieldPtr)         \
162                    (void *)fieldPtr == (void *)0 ? (baseType *)0 :             \
163                    ((baseType *)((bit8 *)(fieldPtr) - ((bitptr)(&(((baseType *)0)->fieldName)))))
164
165
166
167#endif /* __TDLIST_H__ */
168
169