123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792 |
- /******************************************************************************
- ** High Performance device driver for the Symbios 53C896 controller.
- **
- ** Copyright (C) 1998-2001 Gerard Roudier <groudier@free.fr>
- **
- ** This driver also supports all the Symbios 53C8XX controller family,
- ** except 53C810 revisions < 16, 53C825 revisions < 16 and all
- ** revisions of 53C815 controllers.
- **
- ** This driver is based on the Linux port of the FreeBSD ncr driver.
- **
- ** Copyright (C) 1994 Wolfgang Stanglmeier
- **
- **-----------------------------------------------------------------------------
- **
- ** This program is free software; you can redistribute it and/or modify
- ** it under the terms of the GNU General Public License as published by
- ** the Free Software Foundation; either version 2 of the License, or
- ** (at your option) any later version.
- **
- ** This program is distributed in the hope that it will be useful,
- ** but WITHOUT ANY WARRANTY; without even the implied warranty of
- ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- ** GNU General Public License for more details.
- **
- ** You should have received a copy of the GNU General Public License
- ** along with this program; if not, write to the Free Software
- ** Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- **
- **-----------------------------------------------------------------------------
- **
- ** The Linux port of the FreeBSD ncr driver has been achieved in
- ** november 1995 by:
- **
- ** Gerard Roudier <groudier@free.fr>
- **
- ** Being given that this driver originates from the FreeBSD version, and
- ** in order to keep synergy on both, any suggested enhancements and corrections
- ** received on Linux are automatically a potential candidate for the FreeBSD
- ** version.
- **
- ** The original driver has been written for 386bsd and FreeBSD by
- ** Wolfgang Stanglmeier <wolf@cologne.de>
- ** Stefan Esser <se@mi.Uni-Koeln.de>
- **
- **-----------------------------------------------------------------------------
- **
- ** Major contributions:
- ** --------------------
- **
- ** NVRAM detection and reading.
- ** Copyright (C) 1997 Richard Waltham <dormouse@farsrobt.demon.co.uk>
- **
- *******************************************************************************
- */
- /*==========================================================
- **
- ** Debugging tags
- **
- **==========================================================
- */
- #define DEBUG_ALLOC (0x0001)
- #define DEBUG_PHASE (0x0002)
- #define DEBUG_QUEUE (0x0008)
- #define DEBUG_RESULT (0x0010)
- #define DEBUG_POINTER (0x0020)
- #define DEBUG_SCRIPT (0x0040)
- #define DEBUG_TINY (0x0080)
- #define DEBUG_TIMING (0x0100)
- #define DEBUG_NEGO (0x0200)
- #define DEBUG_TAGS (0x0400)
- #define DEBUG_SCATTER (0x0800)
- #define DEBUG_IC (0x1000)
- /*
- ** Enable/Disable debug messages.
- ** Can be changed at runtime too.
- */
- #ifdef SCSI_NCR_DEBUG_INFO_SUPPORT
- static int ncr_debug = SCSI_NCR_DEBUG_FLAGS;
- #define DEBUG_FLAGS ncr_debug
- #else
- #define DEBUG_FLAGS SCSI_NCR_DEBUG_FLAGS
- #endif
- static inline struct list_head *ncr_list_pop(struct list_head *head)
- {
- if (!list_empty(head)) {
- struct list_head *elem = head->next;
- list_del(elem);
- return elem;
- }
- return NULL;
- }
- #ifdef __sparc__
- #include <asm/irq.h>
- #endif
- /*==========================================================
- **
- ** Simple power of two buddy-like allocator.
- **
- ** This simple code is not intended to be fast, but to
- ** provide power of 2 aligned memory allocations.
- ** Since the SCRIPTS processor only supplies 8 bit
- ** arithmetic, this allocator allows simple and fast
- ** address calculations from the SCRIPTS code.
- ** In addition, cache line alignment is guaranteed for
- ** power of 2 cache line size.
- ** Enhanced in linux-2.3.44 to provide a memory pool
- ** per pcidev to support dynamic dma mapping. (I would
- ** have preferred a real bus astraction, btw).
- **
- **==========================================================
- */
- #define MEMO_SHIFT 4 /* 16 bytes minimum memory chunk */
- #if PAGE_SIZE >= 8192
- #define MEMO_PAGE_ORDER 0 /* 1 PAGE maximum */
- #else
- #define MEMO_PAGE_ORDER 1 /* 2 PAGES maximum */
- #endif
- #define MEMO_FREE_UNUSED /* Free unused pages immediately */
- #define MEMO_WARN 1
- #define MEMO_GFP_FLAGS GFP_ATOMIC
- #define MEMO_CLUSTER_SHIFT (PAGE_SHIFT+MEMO_PAGE_ORDER)
- #define MEMO_CLUSTER_SIZE (1UL << MEMO_CLUSTER_SHIFT)
- #define MEMO_CLUSTER_MASK (MEMO_CLUSTER_SIZE-1)
- typedef u_long m_addr_t; /* Enough bits to bit-hack addresses */
- typedef struct device *m_bush_t; /* Something that addresses DMAable */
- typedef struct m_link { /* Link between free memory chunks */
- struct m_link *next;
- } m_link_s;
- typedef struct m_vtob { /* Virtual to Bus address translation */
- struct m_vtob *next;
- m_addr_t vaddr;
- m_addr_t baddr;
- } m_vtob_s;
- #define VTOB_HASH_SHIFT 5
- #define VTOB_HASH_SIZE (1UL << VTOB_HASH_SHIFT)
- #define VTOB_HASH_MASK (VTOB_HASH_SIZE-1)
- #define VTOB_HASH_CODE(m) \
- ((((m_addr_t) (m)) >> MEMO_CLUSTER_SHIFT) & VTOB_HASH_MASK)
- typedef struct m_pool { /* Memory pool of a given kind */
- m_bush_t bush;
- m_addr_t (*getp)(struct m_pool *);
- void (*freep)(struct m_pool *, m_addr_t);
- int nump;
- m_vtob_s *(vtob[VTOB_HASH_SIZE]);
- struct m_pool *next;
- struct m_link h[PAGE_SHIFT-MEMO_SHIFT+MEMO_PAGE_ORDER+1];
- } m_pool_s;
- static void *___m_alloc(m_pool_s *mp, int size)
- {
- int i = 0;
- int s = (1 << MEMO_SHIFT);
- int j;
- m_addr_t a;
- m_link_s *h = mp->h;
- if (size > (PAGE_SIZE << MEMO_PAGE_ORDER))
- return NULL;
- while (size > s) {
- s <<= 1;
- ++i;
- }
- j = i;
- while (!h[j].next) {
- if (s == (PAGE_SIZE << MEMO_PAGE_ORDER)) {
- h[j].next = (m_link_s *)mp->getp(mp);
- if (h[j].next)
- h[j].next->next = NULL;
- break;
- }
- ++j;
- s <<= 1;
- }
- a = (m_addr_t) h[j].next;
- if (a) {
- h[j].next = h[j].next->next;
- while (j > i) {
- j -= 1;
- s >>= 1;
- h[j].next = (m_link_s *) (a+s);
- h[j].next->next = NULL;
- }
- }
- #ifdef DEBUG
- printk("___m_alloc(%d) = %p\n", size, (void *) a);
- #endif
- return (void *) a;
- }
- static void ___m_free(m_pool_s *mp, void *ptr, int size)
- {
- int i = 0;
- int s = (1 << MEMO_SHIFT);
- m_link_s *q;
- m_addr_t a, b;
- m_link_s *h = mp->h;
- #ifdef DEBUG
- printk("___m_free(%p, %d)\n", ptr, size);
- #endif
- if (size > (PAGE_SIZE << MEMO_PAGE_ORDER))
- return;
- while (size > s) {
- s <<= 1;
- ++i;
- }
- a = (m_addr_t) ptr;
- while (1) {
- #ifdef MEMO_FREE_UNUSED
- if (s == (PAGE_SIZE << MEMO_PAGE_ORDER)) {
- mp->freep(mp, a);
- break;
- }
- #endif
- b = a ^ s;
- q = &h[i];
- while (q->next && q->next != (m_link_s *) b) {
- q = q->next;
- }
- if (!q->next) {
- ((m_link_s *) a)->next = h[i].next;
- h[i].next = (m_link_s *) a;
- break;
- }
- q->next = q->next->next;
- a = a & b;
- s <<= 1;
- ++i;
- }
- }
- static DEFINE_SPINLOCK(ncr53c8xx_lock);
- static void *__m_calloc2(m_pool_s *mp, int size, char *name, int uflags)
- {
- void *p;
- p = ___m_alloc(mp, size);
- if (DEBUG_FLAGS & DEBUG_ALLOC)
- printk ("new %-10s[%4d] @%p.\n", name, size, p);
- if (p)
- memset(p, 0, size);
- else if (uflags & MEMO_WARN)
- printk (NAME53C8XX ": failed to allocate %s[%d]\n", name, size);
- return p;
- }
- #define __m_calloc(mp, s, n) __m_calloc2(mp, s, n, MEMO_WARN)
- static void __m_free(m_pool_s *mp, void *ptr, int size, char *name)
- {
- if (DEBUG_FLAGS & DEBUG_ALLOC)
- printk ("freeing %-10s[%4d] @%p.\n", name, size, ptr);
- ___m_free(mp, ptr, size);
- }
- /*
- * With pci bus iommu support, we use a default pool of unmapped memory
- * for memory we donnot need to DMA from/to and one pool per pcidev for
- * memory accessed by the PCI chip. `mp0' is the default not DMAable pool.
- */
- static m_addr_t ___mp0_getp(m_pool_s *mp)
- {
- m_addr_t m = __get_free_pages(MEMO_GFP_FLAGS, MEMO_PAGE_ORDER);
- if (m)
- ++mp->nump;
- return m;
- }
- static void ___mp0_freep(m_pool_s *mp, m_addr_t m)
- {
- free_pages(m, MEMO_PAGE_ORDER);
- --mp->nump;
- }
- static m_pool_s mp0 = {NULL, ___mp0_getp, ___mp0_freep};
- /*
- * DMAable pools.
- */
- /*
- * With pci bus iommu support, we maintain one pool per pcidev and a
- * hashed reverse table for virtual to bus physical address translations.
- */
- static m_addr_t ___dma_getp(m_pool_s *mp)
- {
- m_addr_t vp;
- m_vtob_s *vbp;
- vbp = __m_calloc(&mp0, sizeof(*vbp), "VTOB");
- if (vbp) {
- dma_addr_t daddr;
- vp = (m_addr_t) dma_alloc_coherent(mp->bush,
- PAGE_SIZE<<MEMO_PAGE_ORDER,
- &daddr, GFP_ATOMIC);
- if (vp) {
- int hc = VTOB_HASH_CODE(vp);
- vbp->vaddr = vp;
- vbp->baddr = daddr;
- vbp->next = mp->vtob[hc];
- mp->vtob[hc] = vbp;
- ++mp->nump;
- return vp;
- }
- }
- if (vbp)
- __m_free(&mp0, vbp, sizeof(*vbp), "VTOB");
- return 0;
- }
- static void ___dma_freep(m_pool_s *mp, m_addr_t m)
- {
- m_vtob_s **vbpp, *vbp;
- int hc = VTOB_HASH_CODE(m);
- vbpp = &mp->vtob[hc];
- while (*vbpp && (*vbpp)->vaddr != m)
- vbpp = &(*vbpp)->next;
- if (*vbpp) {
- vbp = *vbpp;
- *vbpp = (*vbpp)->next;
- dma_free_coherent(mp->bush, PAGE_SIZE<<MEMO_PAGE_ORDER,
- (void *)vbp->vaddr, (dma_addr_t)vbp->baddr);
- __m_free(&mp0, vbp, sizeof(*vbp), "VTOB");
- --mp->nump;
- }
- }
- static inline m_pool_s *___get_dma_pool(m_bush_t bush)
- {
- m_pool_s *mp;
- for (mp = mp0.next; mp && mp->bush != bush; mp = mp->next);
- return mp;
- }
- static m_pool_s *___cre_dma_pool(m_bush_t bush)
- {
- m_pool_s *mp;
- mp = __m_calloc(&mp0, sizeof(*mp), "MPOOL");
- if (mp) {
- memset(mp, 0, sizeof(*mp));
- mp->bush = bush;
- mp->getp = ___dma_getp;
- mp->freep = ___dma_freep;
- mp->next = mp0.next;
- mp0.next = mp;
- }
- return mp;
- }
- static void ___del_dma_pool(m_pool_s *p)
- {
- struct m_pool **pp = &mp0.next;
- while (*pp && *pp != p)
- pp = &(*pp)->next;
- if (*pp) {
- *pp = (*pp)->next;
- __m_free(&mp0, p, sizeof(*p), "MPOOL");
- }
- }
- static void *__m_calloc_dma(m_bush_t bush, int size, char *name)
- {
- u_long flags;
- struct m_pool *mp;
- void *m = NULL;
- spin_lock_irqsave(&ncr53c8xx_lock, flags);
- mp = ___get_dma_pool(bush);
- if (!mp)
- mp = ___cre_dma_pool(bush);
- if (mp)
- m = __m_calloc(mp, size, name);
- if (mp && !mp->nump)
- ___del_dma_pool(mp);
- spin_unlock_irqrestore(&ncr53c8xx_lock, flags);
- return m;
- }
- static void __m_free_dma(m_bush_t bush, void *m, int size, char *name)
- {
- u_long flags;
- struct m_pool *mp;
- spin_lock_irqsave(&ncr53c8xx_lock, flags);
- mp = ___get_dma_pool(bush);
- if (mp)
- __m_free(mp, m, size, name);
- if (mp && !mp->nump)
- ___del_dma_pool(mp);
- spin_unlock_irqrestore(&ncr53c8xx_lock, flags);
- }
- static m_addr_t __vtobus(m_bush_t bush, void *m)
- {
- u_long flags;
- m_pool_s *mp;
- int hc = VTOB_HASH_CODE(m);
- m_vtob_s *vp = NULL;
- m_addr_t a = ((m_addr_t) m) & ~MEMO_CLUSTER_MASK;
- spin_lock_irqsave(&ncr53c8xx_lock, flags);
- mp = ___get_dma_pool(bush);
- if (mp) {
- vp = mp->vtob[hc];
- while (vp && (m_addr_t) vp->vaddr != a)
- vp = vp->next;
- }
- spin_unlock_irqrestore(&ncr53c8xx_lock, flags);
- return vp ? vp->baddr + (((m_addr_t) m) - a) : 0;
- }
- #define _m_calloc_dma(np, s, n) __m_calloc_dma(np->dev, s, n)
- #define _m_free_dma(np, p, s, n) __m_free_dma(np->dev, p, s, n)
- #define m_calloc_dma(s, n) _m_calloc_dma(np, s, n)
- #define m_free_dma(p, s, n) _m_free_dma(np, p, s, n)
- #define _vtobus(np, p) __vtobus(np->dev, p)
- #define vtobus(p) _vtobus(np, p)
- /*
- * Deal with DMA mapping/unmapping.
- */
- /* To keep track of the dma mapping (sg/single) that has been set */
- #define __data_mapped SCp.phase
- #define __data_mapping SCp.have_data_in
- static void __unmap_scsi_data(struct device *dev, struct scsi_cmnd *cmd)
- {
- switch(cmd->__data_mapped) {
- case 2:
- dma_unmap_sg(dev, cmd->buffer, cmd->use_sg,
- cmd->sc_data_direction);
- break;
- case 1:
- dma_unmap_single(dev, cmd->__data_mapping,
- cmd->request_bufflen,
- cmd->sc_data_direction);
- break;
- }
- cmd->__data_mapped = 0;
- }
- static u_long __map_scsi_single_data(struct device *dev, struct scsi_cmnd *cmd)
- {
- dma_addr_t mapping;
- if (cmd->request_bufflen == 0)
- return 0;
- mapping = dma_map_single(dev, cmd->request_buffer,
- cmd->request_bufflen,
- cmd->sc_data_direction);
- cmd->__data_mapped = 1;
- cmd->__data_mapping = mapping;
- return mapping;
- }
- static int __map_scsi_sg_data(struct device *dev, struct scsi_cmnd *cmd)
- {
- int use_sg;
- if (cmd->use_sg == 0)
- return 0;
- use_sg = dma_map_sg(dev, cmd->buffer, cmd->use_sg,
- cmd->sc_data_direction);
- cmd->__data_mapped = 2;
- cmd->__data_mapping = use_sg;
- return use_sg;
- }
- #define unmap_scsi_data(np, cmd) __unmap_scsi_data(np->dev, cmd)
- #define map_scsi_single_data(np, cmd) __map_scsi_single_data(np->dev, cmd)
- #define map_scsi_sg_data(np, cmd) __map_scsi_sg_data(np->dev, cmd)
- /*==========================================================
- **
- ** Driver setup.
- **
- ** This structure is initialized from linux config
- ** options. It can be overridden at boot-up by the boot
- ** command line.
- **
- **==========================================================
- */
- static struct ncr_driver_setup
- driver_setup = SCSI_NCR_DRIVER_SETUP;
- #ifdef SCSI_NCR_BOOT_COMMAND_LINE_SUPPORT
- static struct ncr_driver_setup
- driver_safe_setup __initdata = SCSI_NCR_DRIVER_SAFE_SETUP;
- #endif
- #define initverbose (driver_setup.verbose)
- #define bootverbose (np->verbose)
- /*===================================================================
- **
- ** Driver setup from the boot command line
- **
- **===================================================================
- */
- #ifdef MODULE
- #define ARG_SEP ' '
- #else
- #define ARG_SEP ','
- #endif
- #define OPT_TAGS 1
- #define OPT_MASTER_PARITY 2
- #define OPT_SCSI_PARITY 3
- #define OPT_DISCONNECTION 4
- #define OPT_SPECIAL_FEATURES 5
- #define OPT_UNUSED_1 6
- #define OPT_FORCE_SYNC_NEGO 7
- #define OPT_REVERSE_PROBE 8
- #define OPT_DEFAULT_SYNC 9
- #define OPT_VERBOSE 10
- #define OPT_DEBUG 11
- #define OPT_BURST_MAX 12
- #define OPT_LED_PIN 13
- #define OPT_MAX_WIDE 14
- #define OPT_SETTLE_DELAY 15
- #define OPT_DIFF_SUPPORT 16
- #define OPT_IRQM 17
- #define OPT_PCI_FIX_UP 18
- #define OPT_BUS_CHECK 19
- #define OPT_OPTIMIZE 20
- #define OPT_RECOVERY 21
- #define OPT_SAFE_SETUP 22
- #define OPT_USE_NVRAM 23
- #define OPT_EXCLUDE 24
- #define OPT_HOST_ID 25
- #ifdef SCSI_NCR_IARB_SUPPORT
- #define OPT_IARB 26
- #endif
- static char setup_token[] __initdata =
- "tags:" "mpar:"
- "spar:" "disc:"
- "specf:" "ultra:"
- "fsn:" "revprob:"
- "sync:" "verb:"
- "debug:" "burst:"
- "led:" "wide:"
- "settle:" "diff:"
- "irqm:" "pcifix:"
- "buschk:" "optim:"
- "recovery:"
- "safe:" "nvram:"
- "excl:" "hostid:"
- #ifdef SCSI_NCR_IARB_SUPPORT
- "iarb:"
- #endif
- ; /* DONNOT REMOVE THIS ';' */
- #ifdef MODULE
- #define ARG_SEP ' '
- #else
- #define ARG_SEP ','
- #endif
- static int __init get_setup_token(char *p)
- {
- char *cur = setup_token;
- char *pc;
- int i = 0;
- while (cur != NULL && (pc = strchr(cur, ':')) != NULL) {
- ++pc;
- ++i;
- if (!strncmp(p, cur, pc - cur))
- return i;
- cur = pc;
- }
- return 0;
- }
- static int __init sym53c8xx__setup(char *str)
- {
- #ifdef SCSI_NCR_BOOT_COMMAND_LINE_SUPPORT
- char *cur = str;
- char *pc, *pv;
- int i, val, c;
- int xi = 0;
- while (cur != NULL && (pc = strchr(cur, ':')) != NULL) {
- char *pe;
- val = 0;
- pv = pc;
- c = *++pv;
- if (c == 'n')
- val = 0;
- else if (c == 'y')
- val = 1;
- else
- val = (int) simple_strtoul(pv, &pe, 0);
- switch (get_setup_token(cur)) {
- case OPT_TAGS:
- driver_setup.default_tags = val;
- if (pe && *pe == '/') {
- i = 0;
- while (*pe && *pe != ARG_SEP &&
- i < sizeof(driver_setup.tag_ctrl)-1) {
- driver_setup.tag_ctrl[i++] = *pe++;
- }
- driver_setup.tag_ctrl[i] = '\0';
- }
- break;
- case OPT_MASTER_PARITY:
- driver_setup.master_parity = val;
- break;
- case OPT_SCSI_PARITY:
- driver_setup.scsi_parity = val;
- break;
- case OPT_DISCONNECTION:
- driver_setup.disconnection = val;
- break;
- case OPT_SPECIAL_FEATURES:
- driver_setup.special_features = val;
- break;
- case OPT_FORCE_SYNC_NEGO:
- driver_setup.force_sync_nego = val;
- break;
- case OPT_REVERSE_PROBE:
- driver_setup.reverse_probe = val;
- break;
- case OPT_DEFAULT_SYNC:
- driver_setup.default_sync = val;
- break;
- case OPT_VERBOSE:
- driver_setup.verbose = val;
- break;
- case OPT_DEBUG:
- driver_setup.debug = val;
- break;
- case OPT_BURST_MAX:
- driver_setup.burst_max = val;
- break;
- case OPT_LED_PIN:
- driver_setup.led_pin = val;
- break;
- case OPT_MAX_WIDE:
- driver_setup.max_wide = val? 1:0;
- break;
- case OPT_SETTLE_DELAY:
- driver_setup.settle_delay = val;
- break;
- case OPT_DIFF_SUPPORT:
- driver_setup.diff_support = val;
- break;
- case OPT_IRQM:
- driver_setup.irqm = val;
- break;
- case OPT_PCI_FIX_UP:
- driver_setup.pci_fix_up = val;
- break;
- case OPT_BUS_CHECK:
- driver_setup.bus_check = val;
- break;
- case OPT_OPTIMIZE:
- driver_setup.optimize = val;
- break;
- case OPT_RECOVERY:
- driver_setup.recovery = val;
- break;
- case OPT_USE_NVRAM:
- driver_setup.use_nvram = val;
- break;
- case OPT_SAFE_SETUP:
- memcpy(&driver_setup, &driver_safe_setup,
- sizeof(driver_setup));
- break;
- case OPT_EXCLUDE:
- if (xi < SCSI_NCR_MAX_EXCLUDES)
- driver_setup.excludes[xi++] = val;
- break;
- case OPT_HOST_ID:
- driver_setup.host_id = val;
- break;
- #ifdef SCSI_NCR_IARB_SUPPORT
- case OPT_IARB:
- driver_setup.iarb = val;
- break;
- #endif
- default:
- printk("sym53c8xx_setup: unexpected boot option '%.*s' ignored\n", (int)(pc-cur+1), cur);
- break;
- }
- if ((cur = strchr(cur, ARG_SEP)) != NULL)
- ++cur;
- }
- #endif /* SCSI_NCR_BOOT_COMMAND_LINE_SUPPORT */
- return 1;
- }
- /*===================================================================
- **
- ** Get device queue depth from boot command line.
- **
- **===================================================================
- */
- #define DEF_DEPTH (driver_setup.default_tags)
- #define ALL_TARGETS -2
- #define NO_TARGET -1
- #define ALL_LUNS -2
- #define NO_LUN -1
- static int device_queue_depth(int unit, int target, int lun)
- {
- int c, h, t, u, v;
- char *p = driver_setup.tag_ctrl;
- char *ep;
- h = -1;
- t = NO_TARGET;
- u = NO_LUN;
- while ((c = *p++) != 0) {
- v = simple_strtoul(p, &ep, 0);
- switch(c) {
- case '/':
- ++h;
- t = ALL_TARGETS;
- u = ALL_LUNS;
- break;
- case 't':
- if (t != target)
- t = (target == v) ? v : NO_TARGET;
- u = ALL_LUNS;
- break;
- case 'u':
- if (u != lun)
- u = (lun == v) ? v : NO_LUN;
- break;
- case 'q':
- if (h == unit &&
- (t == ALL_TARGETS || t == target) &&
- (u == ALL_LUNS || u == lun))
- return v;
- break;
- case '-':
- t = ALL_TARGETS;
- u = ALL_LUNS;
- break;
- default:
- break;
- }
- p = ep;
- }
- return DEF_DEPTH;
- }
|