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