1*1a59d1b8SThomas Gleixner /* SPDX-License-Identifier: GPL-2.0-or-later */
21da177e4SLinus Torvalds /*
31da177e4SLinus Torvalds * Device driver for the SYMBIOS/LSILOGIC 53C8XX and 53C1010 family
41da177e4SLinus Torvalds * of PCI-SCSI IO processors.
51da177e4SLinus Torvalds *
61da177e4SLinus Torvalds * Copyright (C) 1999-2001 Gerard Roudier <groudier@free.fr>
71da177e4SLinus Torvalds *
81da177e4SLinus Torvalds * This driver is derived from the Linux sym53c8xx driver.
91da177e4SLinus Torvalds * Copyright (C) 1998-2000 Gerard Roudier
101da177e4SLinus Torvalds *
111da177e4SLinus Torvalds * The sym53c8xx driver is derived from the ncr53c8xx driver that had been
121da177e4SLinus Torvalds * a port of the FreeBSD ncr driver to Linux-1.2.13.
131da177e4SLinus Torvalds *
141da177e4SLinus Torvalds * The original ncr driver has been written for 386bsd and FreeBSD by
151da177e4SLinus Torvalds * Wolfgang Stanglmeier <wolf@cologne.de>
161da177e4SLinus Torvalds * Stefan Esser <se@mi.Uni-Koeln.de>
171da177e4SLinus Torvalds * Copyright (C) 1994 Wolfgang Stanglmeier
181da177e4SLinus Torvalds *
191da177e4SLinus Torvalds * Other major contributions:
201da177e4SLinus Torvalds *
211da177e4SLinus Torvalds * NVRAM detection and reading.
221da177e4SLinus Torvalds * Copyright (C) 1997 Richard Waltham <dormouse@farsrobt.demon.co.uk>
231da177e4SLinus Torvalds *
241da177e4SLinus Torvalds *-----------------------------------------------------------------------------
251da177e4SLinus Torvalds */
261da177e4SLinus Torvalds
271da177e4SLinus Torvalds #ifndef SYM_MISC_H
281da177e4SLinus Torvalds #define SYM_MISC_H
291da177e4SLinus Torvalds
301da177e4SLinus Torvalds /*
311da177e4SLinus Torvalds * A la VMS/CAM-3 queue management.
321da177e4SLinus Torvalds */
331da177e4SLinus Torvalds typedef struct sym_quehead {
341da177e4SLinus Torvalds struct sym_quehead *flink; /* Forward pointer */
351da177e4SLinus Torvalds struct sym_quehead *blink; /* Backward pointer */
361da177e4SLinus Torvalds } SYM_QUEHEAD;
371da177e4SLinus Torvalds
381da177e4SLinus Torvalds #define sym_que_init(ptr) do { \
391da177e4SLinus Torvalds (ptr)->flink = (ptr); (ptr)->blink = (ptr); \
401da177e4SLinus Torvalds } while (0)
411da177e4SLinus Torvalds
sym_que_first(struct sym_quehead * head)421beb6fa8SHarvey Harrison static inline struct sym_quehead *sym_que_first(struct sym_quehead *head)
431da177e4SLinus Torvalds {
441da177e4SLinus Torvalds return (head->flink == head) ? 0 : head->flink;
451da177e4SLinus Torvalds }
461da177e4SLinus Torvalds
sym_que_last(struct sym_quehead * head)471beb6fa8SHarvey Harrison static inline struct sym_quehead *sym_que_last(struct sym_quehead *head)
481da177e4SLinus Torvalds {
491da177e4SLinus Torvalds return (head->blink == head) ? 0 : head->blink;
501da177e4SLinus Torvalds }
511da177e4SLinus Torvalds
__sym_que_add(struct sym_quehead * new,struct sym_quehead * blink,struct sym_quehead * flink)521beb6fa8SHarvey Harrison static inline void __sym_que_add(struct sym_quehead * new,
531da177e4SLinus Torvalds struct sym_quehead * blink,
541da177e4SLinus Torvalds struct sym_quehead * flink)
551da177e4SLinus Torvalds {
561da177e4SLinus Torvalds flink->blink = new;
571da177e4SLinus Torvalds new->flink = flink;
581da177e4SLinus Torvalds new->blink = blink;
591da177e4SLinus Torvalds blink->flink = new;
601da177e4SLinus Torvalds }
611da177e4SLinus Torvalds
__sym_que_del(struct sym_quehead * blink,struct sym_quehead * flink)621beb6fa8SHarvey Harrison static inline void __sym_que_del(struct sym_quehead * blink,
631da177e4SLinus Torvalds struct sym_quehead * flink)
641da177e4SLinus Torvalds {
651da177e4SLinus Torvalds flink->blink = blink;
661da177e4SLinus Torvalds blink->flink = flink;
671da177e4SLinus Torvalds }
681da177e4SLinus Torvalds
sym_que_empty(struct sym_quehead * head)691beb6fa8SHarvey Harrison static inline int sym_que_empty(struct sym_quehead *head)
701da177e4SLinus Torvalds {
711da177e4SLinus Torvalds return head->flink == head;
721da177e4SLinus Torvalds }
731da177e4SLinus Torvalds
sym_que_splice(struct sym_quehead * list,struct sym_quehead * head)741beb6fa8SHarvey Harrison static inline void sym_que_splice(struct sym_quehead *list,
751da177e4SLinus Torvalds struct sym_quehead *head)
761da177e4SLinus Torvalds {
771da177e4SLinus Torvalds struct sym_quehead *first = list->flink;
781da177e4SLinus Torvalds
791da177e4SLinus Torvalds if (first != list) {
801da177e4SLinus Torvalds struct sym_quehead *last = list->blink;
811da177e4SLinus Torvalds struct sym_quehead *at = head->flink;
821da177e4SLinus Torvalds
831da177e4SLinus Torvalds first->blink = head;
841da177e4SLinus Torvalds head->flink = first;
851da177e4SLinus Torvalds
861da177e4SLinus Torvalds last->flink = at;
871da177e4SLinus Torvalds at->blink = last;
881da177e4SLinus Torvalds }
891da177e4SLinus Torvalds }
901da177e4SLinus Torvalds
sym_que_move(struct sym_quehead * orig,struct sym_quehead * dest)911beb6fa8SHarvey Harrison static inline void sym_que_move(struct sym_quehead *orig,
921da177e4SLinus Torvalds struct sym_quehead *dest)
931da177e4SLinus Torvalds {
941da177e4SLinus Torvalds struct sym_quehead *first, *last;
951da177e4SLinus Torvalds
961da177e4SLinus Torvalds first = orig->flink;
971da177e4SLinus Torvalds if (first != orig) {
981da177e4SLinus Torvalds first->blink = dest;
991da177e4SLinus Torvalds dest->flink = first;
1001da177e4SLinus Torvalds last = orig->blink;
1011da177e4SLinus Torvalds last->flink = dest;
1021da177e4SLinus Torvalds dest->blink = last;
1031da177e4SLinus Torvalds orig->flink = orig;
1041da177e4SLinus Torvalds orig->blink = orig;
1051da177e4SLinus Torvalds } else {
1061da177e4SLinus Torvalds dest->flink = dest;
1071da177e4SLinus Torvalds dest->blink = dest;
1081da177e4SLinus Torvalds }
1091da177e4SLinus Torvalds }
1101da177e4SLinus Torvalds
111d7f305e9SBenjamin Herrenschmidt #define sym_que_entry(ptr, type, member) container_of(ptr, type, member)
1121da177e4SLinus Torvalds
1131da177e4SLinus Torvalds #define sym_insque(new, pos) __sym_que_add(new, pos, (pos)->flink)
1141da177e4SLinus Torvalds
1151da177e4SLinus Torvalds #define sym_remque(el) __sym_que_del((el)->blink, (el)->flink)
1161da177e4SLinus Torvalds
1171da177e4SLinus Torvalds #define sym_insque_head(new, head) __sym_que_add(new, head, (head)->flink)
1181da177e4SLinus Torvalds
sym_remque_head(struct sym_quehead * head)1191beb6fa8SHarvey Harrison static inline struct sym_quehead *sym_remque_head(struct sym_quehead *head)
1201da177e4SLinus Torvalds {
1211da177e4SLinus Torvalds struct sym_quehead *elem = head->flink;
1221da177e4SLinus Torvalds
1231da177e4SLinus Torvalds if (elem != head)
1241da177e4SLinus Torvalds __sym_que_del(head, elem->flink);
1251da177e4SLinus Torvalds else
1261da177e4SLinus Torvalds elem = NULL;
1271da177e4SLinus Torvalds return elem;
1281da177e4SLinus Torvalds }
1291da177e4SLinus Torvalds
1301da177e4SLinus Torvalds #define sym_insque_tail(new, head) __sym_que_add(new, (head)->blink, head)
1311da177e4SLinus Torvalds
sym_remque_tail(struct sym_quehead * head)1321beb6fa8SHarvey Harrison static inline struct sym_quehead *sym_remque_tail(struct sym_quehead *head)
1331da177e4SLinus Torvalds {
1341da177e4SLinus Torvalds struct sym_quehead *elem = head->blink;
1351da177e4SLinus Torvalds
1361da177e4SLinus Torvalds if (elem != head)
1371da177e4SLinus Torvalds __sym_que_del(elem->blink, head);
1381da177e4SLinus Torvalds else
1391da177e4SLinus Torvalds elem = 0;
1401da177e4SLinus Torvalds return elem;
1411da177e4SLinus Torvalds }
1421da177e4SLinus Torvalds
1431da177e4SLinus Torvalds /*
1441da177e4SLinus Torvalds * This one may be useful.
1451da177e4SLinus Torvalds */
1461da177e4SLinus Torvalds #define FOR_EACH_QUEUED_ELEMENT(head, qp) \
1471da177e4SLinus Torvalds for (qp = (head)->flink; qp != (head); qp = qp->flink)
1481da177e4SLinus Torvalds /*
1491da177e4SLinus Torvalds * FreeBSD does not offer our kind of queue in the CAM CCB.
1501da177e4SLinus Torvalds * So, we have to cast.
1511da177e4SLinus Torvalds */
1521da177e4SLinus Torvalds #define sym_qptr(p) ((struct sym_quehead *) (p))
1531da177e4SLinus Torvalds
1541da177e4SLinus Torvalds /*
1551da177e4SLinus Torvalds * Simple bitmap operations.
1561da177e4SLinus Torvalds */
1571da177e4SLinus Torvalds #define sym_set_bit(p, n) (((u32 *)(p))[(n)>>5] |= (1<<((n)&0x1f)))
1581da177e4SLinus Torvalds #define sym_clr_bit(p, n) (((u32 *)(p))[(n)>>5] &= ~(1<<((n)&0x1f)))
1591da177e4SLinus Torvalds #define sym_is_bit(p, n) (((u32 *)(p))[(n)>>5] & (1<<((n)&0x1f)))
1601da177e4SLinus Torvalds
1611da177e4SLinus Torvalds /*
1621da177e4SLinus Torvalds * The below round up/down macros are to be used with a constant
1631da177e4SLinus Torvalds * as argument (sizeof(...) for example), for the compiler to
1641da177e4SLinus Torvalds * optimize the whole thing.
1651da177e4SLinus Torvalds */
1661da177e4SLinus Torvalds #define _U_(a,m) (a)<=(1<<m)?m:
1671da177e4SLinus Torvalds
1681da177e4SLinus Torvalds /*
1691da177e4SLinus Torvalds * Round up logarithm to base 2 of a 16 bit constant.
1701da177e4SLinus Torvalds */
1711da177e4SLinus Torvalds #define _LGRU16_(a) \
1721da177e4SLinus Torvalds ( \
1731da177e4SLinus 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) \
1741da177e4SLinus 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) \
1751da177e4SLinus Torvalds 16)
1761da177e4SLinus Torvalds
1771da177e4SLinus Torvalds #endif /* SYM_MISC_H */
178