Merge branch 'upstream' of git://ftp.linux-mips.org/pub/scm/upstream-linus
[linux-2.6] / drivers / scsi / sym53c8xx_comm.h
1 /******************************************************************************
2 **  High Performance device driver for the Symbios 53C896 controller.
3 **
4 **  Copyright (C) 1998-2001  Gerard Roudier <groudier@free.fr>
5 **
6 **  This driver also supports all the Symbios 53C8XX controller family, 
7 **  except 53C810 revisions < 16, 53C825 revisions < 16 and all 
8 **  revisions of 53C815 controllers.
9 **
10 **  This driver is based on the Linux port of the FreeBSD ncr driver.
11 ** 
12 **  Copyright (C) 1994  Wolfgang Stanglmeier
13 **  
14 **-----------------------------------------------------------------------------
15 **  
16 **  This program is free software; you can redistribute it and/or modify
17 **  it under the terms of the GNU General Public License as published by
18 **  the Free Software Foundation; either version 2 of the License, or
19 **  (at your option) any later version.
20 **
21 **  This program is distributed in the hope that it will be useful,
22 **  but WITHOUT ANY WARRANTY; without even the implied warranty of
23 **  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
24 **  GNU General Public License for more details.
25 **
26 **  You should have received a copy of the GNU General Public License
27 **  along with this program; if not, write to the Free Software
28 **  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
29 **
30 **-----------------------------------------------------------------------------
31 **
32 **  The Linux port of the FreeBSD ncr driver has been achieved in 
33 **  november 1995 by:
34 **
35 **          Gerard Roudier              <groudier@free.fr>
36 **
37 **  Being given that this driver originates from the FreeBSD version, and
38 **  in order to keep synergy on both, any suggested enhancements and corrections
39 **  received on Linux are automatically a potential candidate for the FreeBSD 
40 **  version.
41 **
42 **  The original driver has been written for 386bsd and FreeBSD by
43 **          Wolfgang Stanglmeier        <wolf@cologne.de>
44 **          Stefan Esser                <se@mi.Uni-Koeln.de>
45 **
46 **-----------------------------------------------------------------------------
47 **
48 **  Major contributions:
49 **  --------------------
50 **
51 **  NVRAM detection and reading.
52 **    Copyright (C) 1997 Richard Waltham <dormouse@farsrobt.demon.co.uk>
53 **
54 *******************************************************************************
55 */
56
57 /*==========================================================
58 **
59 **      Debugging tags
60 **
61 **==========================================================
62 */
63
64 #define DEBUG_ALLOC    (0x0001)
65 #define DEBUG_PHASE    (0x0002)
66 #define DEBUG_QUEUE    (0x0008)
67 #define DEBUG_RESULT   (0x0010)
68 #define DEBUG_POINTER  (0x0020)
69 #define DEBUG_SCRIPT   (0x0040)
70 #define DEBUG_TINY     (0x0080)
71 #define DEBUG_TIMING   (0x0100)
72 #define DEBUG_NEGO     (0x0200)
73 #define DEBUG_TAGS     (0x0400)
74 #define DEBUG_SCATTER  (0x0800)
75 #define DEBUG_IC        (0x1000)
76
77 /*
78 **    Enable/Disable debug messages.
79 **    Can be changed at runtime too.
80 */
81
82 #ifdef SCSI_NCR_DEBUG_INFO_SUPPORT
83 static int ncr_debug = SCSI_NCR_DEBUG_FLAGS;
84         #define DEBUG_FLAGS ncr_debug
85 #else
86         #define DEBUG_FLAGS     SCSI_NCR_DEBUG_FLAGS
87 #endif
88
89 static inline struct list_head *ncr_list_pop(struct list_head *head)
90 {
91         if (!list_empty(head)) {
92                 struct list_head *elem = head->next;
93
94                 list_del(elem);
95                 return elem;
96         }
97
98         return NULL;
99 }
100
101 #ifdef __sparc__
102 #include <asm/irq.h>
103 #endif
104
105 /*==========================================================
106 **
107 **      Simple power of two buddy-like allocator.
108 **
109 **      This simple code is not intended to be fast, but to 
110 **      provide power of 2 aligned memory allocations.
111 **      Since the SCRIPTS processor only supplies 8 bit 
112 **      arithmetic, this allocator allows simple and fast 
113 **      address calculations  from the SCRIPTS code.
114 **      In addition, cache line alignment is guaranteed for 
115 **      power of 2 cache line size.
116 **      Enhanced in linux-2.3.44 to provide a memory pool 
117 **      per pcidev to support dynamic dma mapping. (I would 
118 **      have preferred a real bus astraction, btw).
119 **
120 **==========================================================
121 */
122
123 #define MEMO_SHIFT      4       /* 16 bytes minimum memory chunk */
124 #if PAGE_SIZE >= 8192
125 #define MEMO_PAGE_ORDER 0       /* 1 PAGE  maximum */
126 #else
127 #define MEMO_PAGE_ORDER 1       /* 2 PAGES maximum */
128 #endif
129 #define MEMO_FREE_UNUSED        /* Free unused pages immediately */
130 #define MEMO_WARN       1
131 #define MEMO_GFP_FLAGS  GFP_ATOMIC
132 #define MEMO_CLUSTER_SHIFT      (PAGE_SHIFT+MEMO_PAGE_ORDER)
133 #define MEMO_CLUSTER_SIZE       (1UL << MEMO_CLUSTER_SHIFT)
134 #define MEMO_CLUSTER_MASK       (MEMO_CLUSTER_SIZE-1)
135
136 typedef u_long m_addr_t;        /* Enough bits to bit-hack addresses */
137 typedef struct device *m_bush_t;        /* Something that addresses DMAable */
138
139 typedef struct m_link {         /* Link between free memory chunks */
140         struct m_link *next;
141 } m_link_s;
142
143 typedef struct m_vtob {         /* Virtual to Bus address translation */
144         struct m_vtob *next;
145         m_addr_t vaddr;
146         m_addr_t baddr;
147 } m_vtob_s;
148 #define VTOB_HASH_SHIFT         5
149 #define VTOB_HASH_SIZE          (1UL << VTOB_HASH_SHIFT)
150 #define VTOB_HASH_MASK          (VTOB_HASH_SIZE-1)
151 #define VTOB_HASH_CODE(m)       \
152         ((((m_addr_t) (m)) >> MEMO_CLUSTER_SHIFT) & VTOB_HASH_MASK)
153
154 typedef struct m_pool {         /* Memory pool of a given kind */
155         m_bush_t bush;
156         m_addr_t (*getp)(struct m_pool *);
157         void (*freep)(struct m_pool *, m_addr_t);
158         int nump;
159         m_vtob_s *(vtob[VTOB_HASH_SIZE]);
160         struct m_pool *next;
161         struct m_link h[PAGE_SHIFT-MEMO_SHIFT+MEMO_PAGE_ORDER+1];
162 } m_pool_s;
163
164 static void *___m_alloc(m_pool_s *mp, int size)
165 {
166         int i = 0;
167         int s = (1 << MEMO_SHIFT);
168         int j;
169         m_addr_t a;
170         m_link_s *h = mp->h;
171
172         if (size > (PAGE_SIZE << MEMO_PAGE_ORDER))
173                 return NULL;
174
175         while (size > s) {
176                 s <<= 1;
177                 ++i;
178         }
179
180         j = i;
181         while (!h[j].next) {
182                 if (s == (PAGE_SIZE << MEMO_PAGE_ORDER)) {
183                         h[j].next = (m_link_s *)mp->getp(mp);
184                         if (h[j].next)
185                                 h[j].next->next = NULL;
186                         break;
187                 }
188                 ++j;
189                 s <<= 1;
190         }
191         a = (m_addr_t) h[j].next;
192         if (a) {
193                 h[j].next = h[j].next->next;
194                 while (j > i) {
195                         j -= 1;
196                         s >>= 1;
197                         h[j].next = (m_link_s *) (a+s);
198                         h[j].next->next = NULL;
199                 }
200         }
201 #ifdef DEBUG
202         printk("___m_alloc(%d) = %p\n", size, (void *) a);
203 #endif
204         return (void *) a;
205 }
206
207 static void ___m_free(m_pool_s *mp, void *ptr, int size)
208 {
209         int i = 0;
210         int s = (1 << MEMO_SHIFT);
211         m_link_s *q;
212         m_addr_t a, b;
213         m_link_s *h = mp->h;
214
215 #ifdef DEBUG
216         printk("___m_free(%p, %d)\n", ptr, size);
217 #endif
218
219         if (size > (PAGE_SIZE << MEMO_PAGE_ORDER))
220                 return;
221
222         while (size > s) {
223                 s <<= 1;
224                 ++i;
225         }
226
227         a = (m_addr_t) ptr;
228
229         while (1) {
230 #ifdef MEMO_FREE_UNUSED
231                 if (s == (PAGE_SIZE << MEMO_PAGE_ORDER)) {
232                         mp->freep(mp, a);
233                         break;
234                 }
235 #endif
236                 b = a ^ s;
237                 q = &h[i];
238                 while (q->next && q->next != (m_link_s *) b) {
239                         q = q->next;
240                 }
241                 if (!q->next) {
242                         ((m_link_s *) a)->next = h[i].next;
243                         h[i].next = (m_link_s *) a;
244                         break;
245                 }
246                 q->next = q->next->next;
247                 a = a & b;
248                 s <<= 1;
249                 ++i;
250         }
251 }
252
253 static DEFINE_SPINLOCK(ncr53c8xx_lock);
254
255 static void *__m_calloc2(m_pool_s *mp, int size, char *name, int uflags)
256 {
257         void *p;
258
259         p = ___m_alloc(mp, size);
260
261         if (DEBUG_FLAGS & DEBUG_ALLOC)
262                 printk ("new %-10s[%4d] @%p.\n", name, size, p);
263
264         if (p)
265                 memset(p, 0, size);
266         else if (uflags & MEMO_WARN)
267                 printk (NAME53C8XX ": failed to allocate %s[%d]\n", name, size);
268
269         return p;
270 }
271
272 #define __m_calloc(mp, s, n)    __m_calloc2(mp, s, n, MEMO_WARN)
273
274 static void __m_free(m_pool_s *mp, void *ptr, int size, char *name)
275 {
276         if (DEBUG_FLAGS & DEBUG_ALLOC)
277                 printk ("freeing %-10s[%4d] @%p.\n", name, size, ptr);
278
279         ___m_free(mp, ptr, size);
280
281 }
282
283 /*
284  * With pci bus iommu support, we use a default pool of unmapped memory 
285  * for memory we donnot need to DMA from/to and one pool per pcidev for 
286  * memory accessed by the PCI chip. `mp0' is the default not DMAable pool.
287  */
288
289 static m_addr_t ___mp0_getp(m_pool_s *mp)
290 {
291         m_addr_t m = __get_free_pages(MEMO_GFP_FLAGS, MEMO_PAGE_ORDER);
292         if (m)
293                 ++mp->nump;
294         return m;
295 }
296
297 static void ___mp0_freep(m_pool_s *mp, m_addr_t m)
298 {
299         free_pages(m, MEMO_PAGE_ORDER);
300         --mp->nump;
301 }
302
303 static m_pool_s mp0 = {NULL, ___mp0_getp, ___mp0_freep};
304
305 /*
306  * DMAable pools.
307  */
308
309 /*
310  * With pci bus iommu support, we maintain one pool per pcidev and a 
311  * hashed reverse table for virtual to bus physical address translations.
312  */
313 static m_addr_t ___dma_getp(m_pool_s *mp)
314 {
315         m_addr_t vp;
316         m_vtob_s *vbp;
317
318         vbp = __m_calloc(&mp0, sizeof(*vbp), "VTOB");
319         if (vbp) {
320                 dma_addr_t daddr;
321                 vp = (m_addr_t) dma_alloc_coherent(mp->bush,
322                                                 PAGE_SIZE<<MEMO_PAGE_ORDER,
323                                                 &daddr, GFP_ATOMIC);
324                 if (vp) {
325                         int hc = VTOB_HASH_CODE(vp);
326                         vbp->vaddr = vp;
327                         vbp->baddr = daddr;
328                         vbp->next = mp->vtob[hc];
329                         mp->vtob[hc] = vbp;
330                         ++mp->nump;
331                         return vp;
332                 }
333         }
334         if (vbp)
335                 __m_free(&mp0, vbp, sizeof(*vbp), "VTOB");
336         return 0;
337 }
338
339 static void ___dma_freep(m_pool_s *mp, m_addr_t m)
340 {
341         m_vtob_s **vbpp, *vbp;
342         int hc = VTOB_HASH_CODE(m);
343
344         vbpp = &mp->vtob[hc];
345         while (*vbpp && (*vbpp)->vaddr != m)
346                 vbpp = &(*vbpp)->next;
347         if (*vbpp) {
348                 vbp = *vbpp;
349                 *vbpp = (*vbpp)->next;
350                 dma_free_coherent(mp->bush, PAGE_SIZE<<MEMO_PAGE_ORDER,
351                                   (void *)vbp->vaddr, (dma_addr_t)vbp->baddr);
352                 __m_free(&mp0, vbp, sizeof(*vbp), "VTOB");
353                 --mp->nump;
354         }
355 }
356
357 static inline m_pool_s *___get_dma_pool(m_bush_t bush)
358 {
359         m_pool_s *mp;
360         for (mp = mp0.next; mp && mp->bush != bush; mp = mp->next);
361         return mp;
362 }
363
364 static m_pool_s *___cre_dma_pool(m_bush_t bush)
365 {
366         m_pool_s *mp;
367         mp = __m_calloc(&mp0, sizeof(*mp), "MPOOL");
368         if (mp) {
369                 memset(mp, 0, sizeof(*mp));
370                 mp->bush = bush;
371                 mp->getp = ___dma_getp;
372                 mp->freep = ___dma_freep;
373                 mp->next = mp0.next;
374                 mp0.next = mp;
375         }
376         return mp;
377 }
378
379 static void ___del_dma_pool(m_pool_s *p)
380 {
381         struct m_pool **pp = &mp0.next;
382
383         while (*pp && *pp != p)
384                 pp = &(*pp)->next;
385         if (*pp) {
386                 *pp = (*pp)->next;
387                 __m_free(&mp0, p, sizeof(*p), "MPOOL");
388         }
389 }
390
391 static void *__m_calloc_dma(m_bush_t bush, int size, char *name)
392 {
393         u_long flags;
394         struct m_pool *mp;
395         void *m = NULL;
396
397         spin_lock_irqsave(&ncr53c8xx_lock, flags);
398         mp = ___get_dma_pool(bush);
399         if (!mp)
400                 mp = ___cre_dma_pool(bush);
401         if (mp)
402                 m = __m_calloc(mp, size, name);
403         if (mp && !mp->nump)
404                 ___del_dma_pool(mp);
405         spin_unlock_irqrestore(&ncr53c8xx_lock, flags);
406
407         return m;
408 }
409
410 static void __m_free_dma(m_bush_t bush, void *m, int size, char *name)
411 {
412         u_long flags;
413         struct m_pool *mp;
414
415         spin_lock_irqsave(&ncr53c8xx_lock, flags);
416         mp = ___get_dma_pool(bush);
417         if (mp)
418                 __m_free(mp, m, size, name);
419         if (mp && !mp->nump)
420                 ___del_dma_pool(mp);
421         spin_unlock_irqrestore(&ncr53c8xx_lock, flags);
422 }
423
424 static m_addr_t __vtobus(m_bush_t bush, void *m)
425 {
426         u_long flags;
427         m_pool_s *mp;
428         int hc = VTOB_HASH_CODE(m);
429         m_vtob_s *vp = NULL;
430         m_addr_t a = ((m_addr_t) m) & ~MEMO_CLUSTER_MASK;
431
432         spin_lock_irqsave(&ncr53c8xx_lock, flags);
433         mp = ___get_dma_pool(bush);
434         if (mp) {
435                 vp = mp->vtob[hc];
436                 while (vp && (m_addr_t) vp->vaddr != a)
437                         vp = vp->next;
438         }
439         spin_unlock_irqrestore(&ncr53c8xx_lock, flags);
440         return vp ? vp->baddr + (((m_addr_t) m) - a) : 0;
441 }
442
443 #define _m_calloc_dma(np, s, n)         __m_calloc_dma(np->dev, s, n)
444 #define _m_free_dma(np, p, s, n)        __m_free_dma(np->dev, p, s, n)
445 #define m_calloc_dma(s, n)              _m_calloc_dma(np, s, n)
446 #define m_free_dma(p, s, n)             _m_free_dma(np, p, s, n)
447 #define _vtobus(np, p)                  __vtobus(np->dev, p)
448 #define vtobus(p)                       _vtobus(np, p)
449
450 /*
451  *  Deal with DMA mapping/unmapping.
452  */
453
454 /* To keep track of the dma mapping (sg/single) that has been set */
455 #define __data_mapped   SCp.phase
456 #define __data_mapping  SCp.have_data_in
457
458 static void __unmap_scsi_data(struct device *dev, struct scsi_cmnd *cmd)
459 {
460         switch(cmd->__data_mapped) {
461         case 2:
462                 dma_unmap_sg(dev, cmd->buffer, cmd->use_sg,
463                                 cmd->sc_data_direction);
464                 break;
465         case 1:
466                 dma_unmap_single(dev, cmd->__data_mapping,
467                                  cmd->request_bufflen,
468                                  cmd->sc_data_direction);
469                 break;
470         }
471         cmd->__data_mapped = 0;
472 }
473
474 static u_long __map_scsi_single_data(struct device *dev, struct scsi_cmnd *cmd)
475 {
476         dma_addr_t mapping;
477
478         if (cmd->request_bufflen == 0)
479                 return 0;
480
481         mapping = dma_map_single(dev, cmd->request_buffer,
482                                  cmd->request_bufflen,
483                                  cmd->sc_data_direction);
484         cmd->__data_mapped = 1;
485         cmd->__data_mapping = mapping;
486
487         return mapping;
488 }
489
490 static int __map_scsi_sg_data(struct device *dev, struct scsi_cmnd *cmd)
491 {
492         int use_sg;
493
494         if (cmd->use_sg == 0)
495                 return 0;
496
497         use_sg = dma_map_sg(dev, cmd->buffer, cmd->use_sg,
498                         cmd->sc_data_direction);
499         cmd->__data_mapped = 2;
500         cmd->__data_mapping = use_sg;
501
502         return use_sg;
503 }
504
505 #define unmap_scsi_data(np, cmd)        __unmap_scsi_data(np->dev, cmd)
506 #define map_scsi_single_data(np, cmd)   __map_scsi_single_data(np->dev, cmd)
507 #define map_scsi_sg_data(np, cmd)       __map_scsi_sg_data(np->dev, cmd)
508
509 /*==========================================================
510 **
511 **      Driver setup.
512 **
513 **      This structure is initialized from linux config 
514 **      options. It can be overridden at boot-up by the boot 
515 **      command line.
516 **
517 **==========================================================
518 */
519 static struct ncr_driver_setup
520         driver_setup                    = SCSI_NCR_DRIVER_SETUP;
521
522 #ifdef  SCSI_NCR_BOOT_COMMAND_LINE_SUPPORT
523 static struct ncr_driver_setup
524         driver_safe_setup __initdata    = SCSI_NCR_DRIVER_SAFE_SETUP;
525 #endif
526
527 #define initverbose (driver_setup.verbose)
528 #define bootverbose (np->verbose)
529
530
531 /*===================================================================
532 **
533 **      Driver setup from the boot command line
534 **
535 **===================================================================
536 */
537
538 #ifdef MODULE
539 #define ARG_SEP ' '
540 #else
541 #define ARG_SEP ','
542 #endif
543
544 #define OPT_TAGS                1
545 #define OPT_MASTER_PARITY       2
546 #define OPT_SCSI_PARITY         3
547 #define OPT_DISCONNECTION       4
548 #define OPT_SPECIAL_FEATURES    5
549 #define OPT_UNUSED_1            6
550 #define OPT_FORCE_SYNC_NEGO     7
551 #define OPT_REVERSE_PROBE       8
552 #define OPT_DEFAULT_SYNC        9
553 #define OPT_VERBOSE             10
554 #define OPT_DEBUG               11
555 #define OPT_BURST_MAX           12
556 #define OPT_LED_PIN             13
557 #define OPT_MAX_WIDE            14
558 #define OPT_SETTLE_DELAY        15
559 #define OPT_DIFF_SUPPORT        16
560 #define OPT_IRQM                17
561 #define OPT_PCI_FIX_UP          18
562 #define OPT_BUS_CHECK           19
563 #define OPT_OPTIMIZE            20
564 #define OPT_RECOVERY            21
565 #define OPT_SAFE_SETUP          22
566 #define OPT_USE_NVRAM           23
567 #define OPT_EXCLUDE             24
568 #define OPT_HOST_ID             25
569
570 #ifdef SCSI_NCR_IARB_SUPPORT
571 #define OPT_IARB                26
572 #endif
573
574 static char setup_token[] __initdata = 
575         "tags:"   "mpar:"
576         "spar:"   "disc:"
577         "specf:"  "ultra:"
578         "fsn:"    "revprob:"
579         "sync:"   "verb:"
580         "debug:"  "burst:"
581         "led:"    "wide:"
582         "settle:" "diff:"
583         "irqm:"   "pcifix:"
584         "buschk:" "optim:"
585         "recovery:"
586         "safe:"   "nvram:"
587         "excl:"   "hostid:"
588 #ifdef SCSI_NCR_IARB_SUPPORT
589         "iarb:"
590 #endif
591         ;       /* DONNOT REMOVE THIS ';' */
592
593 #ifdef MODULE
594 #define ARG_SEP ' '
595 #else
596 #define ARG_SEP ','
597 #endif
598
599 static int __init get_setup_token(char *p)
600 {
601         char *cur = setup_token;
602         char *pc;
603         int i = 0;
604
605         while (cur != NULL && (pc = strchr(cur, ':')) != NULL) {
606                 ++pc;
607                 ++i;
608                 if (!strncmp(p, cur, pc - cur))
609                         return i;
610                 cur = pc;
611         }
612         return 0;
613 }
614
615
616 static int __init sym53c8xx__setup(char *str)
617 {
618 #ifdef SCSI_NCR_BOOT_COMMAND_LINE_SUPPORT
619         char *cur = str;
620         char *pc, *pv;
621         int i, val, c;
622         int xi = 0;
623
624         while (cur != NULL && (pc = strchr(cur, ':')) != NULL) {
625                 char *pe;
626
627                 val = 0;
628                 pv = pc;
629                 c = *++pv;
630
631                 if      (c == 'n')
632                         val = 0;
633                 else if (c == 'y')
634                         val = 1;
635                 else
636                         val = (int) simple_strtoul(pv, &pe, 0);
637
638                 switch (get_setup_token(cur)) {
639                 case OPT_TAGS:
640                         driver_setup.default_tags = val;
641                         if (pe && *pe == '/') {
642                                 i = 0;
643                                 while (*pe && *pe != ARG_SEP && 
644                                         i < sizeof(driver_setup.tag_ctrl)-1) {
645                                         driver_setup.tag_ctrl[i++] = *pe++;
646                                 }
647                                 driver_setup.tag_ctrl[i] = '\0';
648                         }
649                         break;
650                 case OPT_MASTER_PARITY:
651                         driver_setup.master_parity = val;
652                         break;
653                 case OPT_SCSI_PARITY:
654                         driver_setup.scsi_parity = val;
655                         break;
656                 case OPT_DISCONNECTION:
657                         driver_setup.disconnection = val;
658                         break;
659                 case OPT_SPECIAL_FEATURES:
660                         driver_setup.special_features = val;
661                         break;
662                 case OPT_FORCE_SYNC_NEGO:
663                         driver_setup.force_sync_nego = val;
664                         break;
665                 case OPT_REVERSE_PROBE:
666                         driver_setup.reverse_probe = val;
667                         break;
668                 case OPT_DEFAULT_SYNC:
669                         driver_setup.default_sync = val;
670                         break;
671                 case OPT_VERBOSE:
672                         driver_setup.verbose = val;
673                         break;
674                 case OPT_DEBUG:
675                         driver_setup.debug = val;
676                         break;
677                 case OPT_BURST_MAX:
678                         driver_setup.burst_max = val;
679                         break;
680                 case OPT_LED_PIN:
681                         driver_setup.led_pin = val;
682                         break;
683                 case OPT_MAX_WIDE:
684                         driver_setup.max_wide = val? 1:0;
685                         break;
686                 case OPT_SETTLE_DELAY:
687                         driver_setup.settle_delay = val;
688                         break;
689                 case OPT_DIFF_SUPPORT:
690                         driver_setup.diff_support = val;
691                         break;
692                 case OPT_IRQM:
693                         driver_setup.irqm = val;
694                         break;
695                 case OPT_PCI_FIX_UP:
696                         driver_setup.pci_fix_up = val;
697                         break;
698                 case OPT_BUS_CHECK:
699                         driver_setup.bus_check = val;
700                         break;
701                 case OPT_OPTIMIZE:
702                         driver_setup.optimize = val;
703                         break;
704                 case OPT_RECOVERY:
705                         driver_setup.recovery = val;
706                         break;
707                 case OPT_USE_NVRAM:
708                         driver_setup.use_nvram = val;
709                         break;
710                 case OPT_SAFE_SETUP:
711                         memcpy(&driver_setup, &driver_safe_setup,
712                                 sizeof(driver_setup));
713                         break;
714                 case OPT_EXCLUDE:
715                         if (xi < SCSI_NCR_MAX_EXCLUDES)
716                                 driver_setup.excludes[xi++] = val;
717                         break;
718                 case OPT_HOST_ID:
719                         driver_setup.host_id = val;
720                         break;
721 #ifdef SCSI_NCR_IARB_SUPPORT
722                 case OPT_IARB:
723                         driver_setup.iarb = val;
724                         break;
725 #endif
726                 default:
727                         printk("sym53c8xx_setup: unexpected boot option '%.*s' ignored\n", (int)(pc-cur+1), cur);
728                         break;
729                 }
730
731                 if ((cur = strchr(cur, ARG_SEP)) != NULL)
732                         ++cur;
733         }
734 #endif /* SCSI_NCR_BOOT_COMMAND_LINE_SUPPORT */
735         return 1;
736 }
737
738 /*===================================================================
739 **
740 **      Get device queue depth from boot command line.
741 **
742 **===================================================================
743 */
744 #define DEF_DEPTH       (driver_setup.default_tags)
745 #define ALL_TARGETS     -2
746 #define NO_TARGET       -1
747 #define ALL_LUNS        -2
748 #define NO_LUN          -1
749
750 static int device_queue_depth(int unit, int target, int lun)
751 {
752         int c, h, t, u, v;
753         char *p = driver_setup.tag_ctrl;
754         char *ep;
755
756         h = -1;
757         t = NO_TARGET;
758         u = NO_LUN;
759         while ((c = *p++) != 0) {
760                 v = simple_strtoul(p, &ep, 0);
761                 switch(c) {
762                 case '/':
763                         ++h;
764                         t = ALL_TARGETS;
765                         u = ALL_LUNS;
766                         break;
767                 case 't':
768                         if (t != target)
769                                 t = (target == v) ? v : NO_TARGET;
770                         u = ALL_LUNS;
771                         break;
772                 case 'u':
773                         if (u != lun)
774                                 u = (lun == v) ? v : NO_LUN;
775                         break;
776                 case 'q':
777                         if (h == unit &&
778                                 (t == ALL_TARGETS || t == target) &&
779                                 (u == ALL_LUNS    || u == lun))
780                                 return v;
781                         break;
782                 case '-':
783                         t = ALL_TARGETS;
784                         u = ALL_LUNS;
785                         break;
786                 default:
787                         break;
788                 }
789                 p = ep;
790         }
791         return DEF_DEPTH;
792 }