[PATCH] ppc32: add watchdog & RTC support for Marvell EV64360BP board
[linux/fpc-iii.git] / drivers / scsi / sym53c8xx_comm.h
blob20ae2b17df5862c166cc6b91f453567a7e08a749
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.
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.
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.
30 **-----------------------------------------------------------------------------
32 ** The Linux port of the FreeBSD ncr driver has been achieved in
33 ** november 1995 by:
35 ** Gerard Roudier <groudier@free.fr>
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.
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>
46 **-----------------------------------------------------------------------------
48 ** Major contributions:
49 ** --------------------
51 ** NVRAM detection and reading.
52 ** Copyright (C) 1997 Richard Waltham <dormouse@farsrobt.demon.co.uk>
54 *******************************************************************************
57 /*==========================================================
59 ** Debugging tags
61 **==========================================================
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)
78 ** Enable/Disable debug messages.
79 ** Can be changed at runtime too.
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
89 static inline struct list_head *ncr_list_pop(struct list_head *head)
91 if (!list_empty(head)) {
92 struct list_head *elem = head->next;
94 list_del(elem);
95 return elem;
98 return NULL;
101 #ifdef __sparc__
102 #include <asm/irq.h>
103 #endif
105 /*==========================================================
107 ** Simple power of two buddy-like allocator.
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).
120 **==========================================================
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)
136 typedef u_long m_addr_t; /* Enough bits to bit-hack addresses */
137 typedef struct device *m_bush_t; /* Something that addresses DMAable */
139 typedef struct m_link { /* Link between free memory chunks */
140 struct m_link *next;
141 } m_link_s;
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)
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;
164 static void *___m_alloc(m_pool_s *mp, int size)
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;
172 if (size > (PAGE_SIZE << MEMO_PAGE_ORDER))
173 return NULL;
175 while (size > s) {
176 s <<= 1;
177 ++i;
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;
188 ++j;
189 s <<= 1;
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;
201 #ifdef DEBUG
202 printk("___m_alloc(%d) = %p\n", size, (void *) a);
203 #endif
204 return (void *) a;
207 static void ___m_free(m_pool_s *mp, void *ptr, int size)
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;
215 #ifdef DEBUG
216 printk("___m_free(%p, %d)\n", ptr, size);
217 #endif
219 if (size > (PAGE_SIZE << MEMO_PAGE_ORDER))
220 return;
222 while (size > s) {
223 s <<= 1;
224 ++i;
227 a = (m_addr_t) ptr;
229 while (1) {
230 #ifdef MEMO_FREE_UNUSED
231 if (s == (PAGE_SIZE << MEMO_PAGE_ORDER)) {
232 mp->freep(mp, a);
233 break;
235 #endif
236 b = a ^ s;
237 q = &h[i];
238 while (q->next && q->next != (m_link_s *) b) {
239 q = q->next;
241 if (!q->next) {
242 ((m_link_s *) a)->next = h[i].next;
243 h[i].next = (m_link_s *) a;
244 break;
246 q->next = q->next->next;
247 a = a & b;
248 s <<= 1;
249 ++i;
253 static DEFINE_SPINLOCK(ncr53c8xx_lock);
255 static void *__m_calloc2(m_pool_s *mp, int size, char *name, int uflags)
257 void *p;
259 p = ___m_alloc(mp, size);
261 if (DEBUG_FLAGS & DEBUG_ALLOC)
262 printk ("new %-10s[%4d] @%p.\n", name, size, p);
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);
269 return p;
272 #define __m_calloc(mp, s, n) __m_calloc2(mp, s, n, MEMO_WARN)
274 static void __m_free(m_pool_s *mp, void *ptr, int size, char *name)
276 if (DEBUG_FLAGS & DEBUG_ALLOC)
277 printk ("freeing %-10s[%4d] @%p.\n", name, size, ptr);
279 ___m_free(mp, ptr, size);
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.
289 static m_addr_t ___mp0_getp(m_pool_s *mp)
291 m_addr_t m = __get_free_pages(MEMO_GFP_FLAGS, MEMO_PAGE_ORDER);
292 if (m)
293 ++mp->nump;
294 return m;
297 static void ___mp0_freep(m_pool_s *mp, m_addr_t m)
299 free_pages(m, MEMO_PAGE_ORDER);
300 --mp->nump;
303 static m_pool_s mp0 = {NULL, ___mp0_getp, ___mp0_freep};
306 * DMAable pools.
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.
313 static m_addr_t ___dma_getp(m_pool_s *mp)
315 m_addr_t vp;
316 m_vtob_s *vbp;
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;
334 if (vbp)
335 __m_free(&mp0, vbp, sizeof(*vbp), "VTOB");
336 return 0;
339 static void ___dma_freep(m_pool_s *mp, m_addr_t m)
341 m_vtob_s **vbpp, *vbp;
342 int hc = VTOB_HASH_CODE(m);
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;
357 static inline m_pool_s *___get_dma_pool(m_bush_t bush)
359 m_pool_s *mp;
360 for (mp = mp0.next; mp && mp->bush != bush; mp = mp->next);
361 return mp;
364 static m_pool_s *___cre_dma_pool(m_bush_t bush)
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;
376 return mp;
379 static void ___del_dma_pool(m_pool_s *p)
381 struct m_pool **pp = &mp0.next;
383 while (*pp && *pp != p)
384 pp = &(*pp)->next;
385 if (*pp) {
386 *pp = (*pp)->next;
387 __m_free(&mp0, p, sizeof(*p), "MPOOL");
391 static void *__m_calloc_dma(m_bush_t bush, int size, char *name)
393 u_long flags;
394 struct m_pool *mp;
395 void *m = NULL;
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);
407 return m;
410 static void __m_free_dma(m_bush_t bush, void *m, int size, char *name)
412 u_long flags;
413 struct m_pool *mp;
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);
424 static m_addr_t __vtobus(m_bush_t bush, void *m)
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;
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;
439 spin_unlock_irqrestore(&ncr53c8xx_lock, flags);
440 return vp ? vp->baddr + (((m_addr_t) m) - a) : 0;
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)
451 * Deal with DMA mapping/unmapping.
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
458 static void __unmap_scsi_data(struct device *dev, struct scsi_cmnd *cmd)
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;
471 cmd->__data_mapped = 0;
474 static u_long __map_scsi_single_data(struct device *dev, struct scsi_cmnd *cmd)
476 dma_addr_t mapping;
478 if (cmd->request_bufflen == 0)
479 return 0;
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;
487 return mapping;
490 static int __map_scsi_sg_data(struct device *dev, struct scsi_cmnd *cmd)
492 int use_sg;
494 if (cmd->use_sg == 0)
495 return 0;
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;
502 return use_sg;
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)
509 /*==========================================================
511 ** Driver setup.
513 ** This structure is initialized from linux config
514 ** options. It can be overridden at boot-up by the boot
515 ** command line.
517 **==========================================================
519 static struct ncr_driver_setup
520 driver_setup = SCSI_NCR_DRIVER_SETUP;
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
527 #define initverbose (driver_setup.verbose)
528 #define bootverbose (np->verbose)
531 /*===================================================================
533 ** Driver setup from the boot command line
535 **===================================================================
538 #ifdef MODULE
539 #define ARG_SEP ' '
540 #else
541 #define ARG_SEP ','
542 #endif
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
570 #ifdef SCSI_NCR_IARB_SUPPORT
571 #define OPT_IARB 26
572 #endif
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 ';' */
593 #ifdef MODULE
594 #define ARG_SEP ' '
595 #else
596 #define ARG_SEP ','
597 #endif
599 static int __init get_setup_token(char *p)
601 char *cur = setup_token;
602 char *pc;
603 int i = 0;
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;
612 return 0;
616 static int __init sym53c8xx__setup(char *str)
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;
624 while (cur != NULL && (pc = strchr(cur, ':')) != NULL) {
625 char *pe;
627 val = 0;
628 pv = pc;
629 c = *++pv;
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);
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++;
647 driver_setup.tag_ctrl[i] = '\0';
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;
731 if ((cur = strchr(cur, ARG_SEP)) != NULL)
732 ++cur;
734 #endif /* SCSI_NCR_BOOT_COMMAND_LINE_SUPPORT */
735 return 1;
738 /*===================================================================
740 ** Get device queue depth from boot command line.
742 **===================================================================
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
750 static int device_queue_depth(int unit, int target, int lun)
752 int c, h, t, u, v;
753 char *p = driver_setup.tag_ctrl;
754 char *ep;
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;
789 p = ep;
791 return DEF_DEPTH;