1 /* 2 * Device driver for the SYMBIOS/LSILOGIC 53C8XX and 53C1010 family 3 * of PCI-SCSI IO processors. 4 * 5 * Copyright (C) 1999-2001 Gerard Roudier <groudier@free.fr> 6 * 7 * This driver is derived from the Linux sym53c8xx driver. 8 * Copyright (C) 1998-2000 Gerard Roudier 9 * 10 * The sym53c8xx driver is derived from the ncr53c8xx driver that had been 11 * a port of the FreeBSD ncr driver to Linux-1.2.13. 12 * 13 * The original ncr driver has been written for 386bsd and FreeBSD by 14 * Wolfgang Stanglmeier <wolf@cologne.de> 15 * Stefan Esser <se@mi.Uni-Koeln.de> 16 * Copyright (C) 1994 Wolfgang Stanglmeier 17 * 18 * Other major contributions: 19 * 20 * NVRAM detection and reading. 21 * Copyright (C) 1997 Richard Waltham <dormouse@farsrobt.demon.co.uk> 22 * 23 *----------------------------------------------------------------------------- 24 * 25 * This program is free software; you can redistribute it and/or modify 26 * it under the terms of the GNU General Public License as published by 27 * the Free Software Foundation; either version 2 of the License, or 28 * (at your option) any later version. 29 * 30 * This program is distributed in the hope that it will be useful, 31 * but WITHOUT ANY WARRANTY; without even the implied warranty of 32 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 33 * GNU General Public License for more details. 34 * 35 * You should have received a copy of the GNU General Public License 36 * along with this program; if not, write to the Free Software 37 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 38 */ 39 40 #ifndef SYM_MISC_H 41 #define SYM_MISC_H 42 43 /* 44 * A la VMS/CAM-3 queue management. 45 */ 46 typedef struct sym_quehead { 47 struct sym_quehead *flink; /* Forward pointer */ 48 struct sym_quehead *blink; /* Backward pointer */ 49 } SYM_QUEHEAD; 50 51 #define sym_que_init(ptr) do { \ 52 (ptr)->flink = (ptr); (ptr)->blink = (ptr); \ 53 } while (0) 54 55 static inline struct sym_quehead *sym_que_first(struct sym_quehead *head) 56 { 57 return (head->flink == head) ? 0 : head->flink; 58 } 59 60 static inline struct sym_quehead *sym_que_last(struct sym_quehead *head) 61 { 62 return (head->blink == head) ? 0 : head->blink; 63 } 64 65 static inline void __sym_que_add(struct sym_quehead * new, 66 struct sym_quehead * blink, 67 struct sym_quehead * flink) 68 { 69 flink->blink = new; 70 new->flink = flink; 71 new->blink = blink; 72 blink->flink = new; 73 } 74 75 static inline void __sym_que_del(struct sym_quehead * blink, 76 struct sym_quehead * flink) 77 { 78 flink->blink = blink; 79 blink->flink = flink; 80 } 81 82 static inline int sym_que_empty(struct sym_quehead *head) 83 { 84 return head->flink == head; 85 } 86 87 static inline void sym_que_splice(struct sym_quehead *list, 88 struct sym_quehead *head) 89 { 90 struct sym_quehead *first = list->flink; 91 92 if (first != list) { 93 struct sym_quehead *last = list->blink; 94 struct sym_quehead *at = head->flink; 95 96 first->blink = head; 97 head->flink = first; 98 99 last->flink = at; 100 at->blink = last; 101 } 102 } 103 104 static inline void sym_que_move(struct sym_quehead *orig, 105 struct sym_quehead *dest) 106 { 107 struct sym_quehead *first, *last; 108 109 first = orig->flink; 110 if (first != orig) { 111 first->blink = dest; 112 dest->flink = first; 113 last = orig->blink; 114 last->flink = dest; 115 dest->blink = last; 116 orig->flink = orig; 117 orig->blink = orig; 118 } else { 119 dest->flink = dest; 120 dest->blink = dest; 121 } 122 } 123 124 #define sym_que_entry(ptr, type, member) container_of(ptr, type, member) 125 126 #define sym_insque(new, pos) __sym_que_add(new, pos, (pos)->flink) 127 128 #define sym_remque(el) __sym_que_del((el)->blink, (el)->flink) 129 130 #define sym_insque_head(new, head) __sym_que_add(new, head, (head)->flink) 131 132 static inline struct sym_quehead *sym_remque_head(struct sym_quehead *head) 133 { 134 struct sym_quehead *elem = head->flink; 135 136 if (elem != head) 137 __sym_que_del(head, elem->flink); 138 else 139 elem = NULL; 140 return elem; 141 } 142 143 #define sym_insque_tail(new, head) __sym_que_add(new, (head)->blink, head) 144 145 static inline struct sym_quehead *sym_remque_tail(struct sym_quehead *head) 146 { 147 struct sym_quehead *elem = head->blink; 148 149 if (elem != head) 150 __sym_que_del(elem->blink, head); 151 else 152 elem = 0; 153 return elem; 154 } 155 156 /* 157 * This one may be useful. 158 */ 159 #define FOR_EACH_QUEUED_ELEMENT(head, qp) \ 160 for (qp = (head)->flink; qp != (head); qp = qp->flink) 161 /* 162 * FreeBSD does not offer our kind of queue in the CAM CCB. 163 * So, we have to cast. 164 */ 165 #define sym_qptr(p) ((struct sym_quehead *) (p)) 166 167 /* 168 * Simple bitmap operations. 169 */ 170 #define sym_set_bit(p, n) (((u32 *)(p))[(n)>>5] |= (1<<((n)&0x1f))) 171 #define sym_clr_bit(p, n) (((u32 *)(p))[(n)>>5] &= ~(1<<((n)&0x1f))) 172 #define sym_is_bit(p, n) (((u32 *)(p))[(n)>>5] & (1<<((n)&0x1f))) 173 174 /* 175 * The below round up/down macros are to be used with a constant 176 * as argument (sizeof(...) for example), for the compiler to 177 * optimize the whole thing. 178 */ 179 #define _U_(a,m) (a)<=(1<<m)?m: 180 181 /* 182 * Round up logarithm to base 2 of a 16 bit constant. 183 */ 184 #define _LGRU16_(a) \ 185 ( \ 186 _U_(a, 0)_U_(a, 1)_U_(a, 2)_U_(a, 3)_U_(a, 4)_U_(a, 5)_U_(a, 6)_U_(a, 7) \ 187 _U_(a, 8)_U_(a, 9)_U_(a,10)_U_(a,11)_U_(a,12)_U_(a,13)_U_(a,14)_U_(a,15) \ 188 16) 189 190 #endif /* SYM_MISC_H */ 191