cregit-Linux how code gets into the kernel

Release 4.11 drivers/scsi/ncr53c8xx.c

Directory: drivers/scsi
/******************************************************************************
**  Device driver for the PCI-SCSI NCR538XX controller family.
**
**  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.
**
**-----------------------------------------------------------------------------
**
**  This driver has been ported to Linux from the FreeBSD NCR53C8XX driver
**  and is currently maintained 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>
**
**  And has been ported to NetBSD by
**          Charles M. Hannum           <mycroft@gnu.ai.mit.edu>
**
**-----------------------------------------------------------------------------
**
**                     Brief history
**
**  December 10 1995 by Gerard Roudier:
**     Initial port to Linux.
**
**  June 23 1996 by Gerard Roudier:
**     Support for 64 bits architectures (Alpha).
**
**  November 30 1996 by Gerard Roudier:
**     Support for Fast-20 scsi.
**     Support for large DMA fifo and 128 dwords bursting.
**
**  February 27 1997 by Gerard Roudier:
**     Support for Fast-40 scsi.
**     Support for on-Board RAM.
**
**  May 3 1997 by Gerard Roudier:
**     Full support for scsi scripts instructions pre-fetching.
**
**  May 19 1997 by Richard Waltham <dormouse@farsrobt.demon.co.uk>:
**     Support for NvRAM detection and reading.
**
**  August 18 1997 by Cort <cort@cs.nmt.edu>:
**     Support for Power/PC (Big Endian).
**
**  June 20 1998 by Gerard Roudier
**     Support for up to 64 tags per lun.
**     O(1) everywhere (C and SCRIPTS) for normal cases.
**     Low PCI traffic for command handling when on-chip RAM is present.
**     Aggressive SCSI SCRIPTS optimizations.
**
**  2005 by Matthew Wilcox and James Bottomley
**     PCI-ectomy.  This driver now supports only the 720 chip (see the
**     NCR_Q720 and zalon drivers for the bus probe logic).
**
*******************************************************************************
*/

/*
**      Supported SCSI-II features:
**          Synchronous negotiation
**          Wide negotiation        (depends on the NCR Chip)
**          Enable disconnection
**          Tagged command queuing
**          Parity checking
**          Etc...
**
**      Supported NCR/SYMBIOS chips:
**              53C720          (Wide,   Fast SCSI-2, intfly problems)
*/

/* Name and version of the driver */

#define SCSI_NCR_DRIVER_NAME	"ncr53c8xx-3.4.3g"


#define SCSI_NCR_DEBUG_FLAGS	(0)

#include <linux/blkdev.h>
#include <linux/delay.h>
#include <linux/dma-mapping.h>
#include <linux/errno.h>
#include <linux/gfp.h>
#include <linux/init.h>
#include <linux/interrupt.h>
#include <linux/ioport.h>
#include <linux/mm.h>
#include <linux/module.h>
#include <linux/sched.h>
#include <linux/signal.h>
#include <linux/spinlock.h>
#include <linux/stat.h>
#include <linux/string.h>
#include <linux/time.h>
#include <linux/timer.h>
#include <linux/types.h>

#include <asm/dma.h>
#include <asm/io.h>

#include <scsi/scsi.h>
#include <scsi/scsi_cmnd.h>
#include <scsi/scsi_dbg.h>
#include <scsi/scsi_device.h>
#include <scsi/scsi_tcq.h>
#include <scsi/scsi_transport.h>
#include <scsi/scsi_transport_spi.h>

#include "ncr53c8xx.h"


#define NAME53C8XX		"ncr53c8xx"

/*==========================================================
**
**      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; }

Contributors

PersonTokensPropCommitsCommitProp
Matthew Wilcox44100.00%1100.00%
Total44100.00%1100.00%

/*========================================================== ** ** 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 abstraction, 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; }

Contributors

PersonTokensPropCommitsCommitProp
Matthew Wilcox247100.00%1100.00%
Total247100.00%1100.00%


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; } }

Contributors

PersonTokensPropCommitsCommitProp
Matthew Wilcox229100.00%1100.00%
Total229100.00%1100.00%

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; }

Contributors

PersonTokensPropCommitsCommitProp
Matthew Wilcox84100.00%1100.00%
Total84100.00%1100.00%

#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); }

Contributors

PersonTokensPropCommitsCommitProp
Matthew Wilcox47100.00%1100.00%
Total47100.00%1100.00%

/* * 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; }

Contributors

PersonTokensPropCommitsCommitProp
Matthew Wilcox32100.00%1100.00%
Total32100.00%1100.00%


static void ___mp0_freep(m_pool_s *mp, m_addr_t m) { free_pages(m, MEMO_PAGE_ORDER); --mp->nump; }

Contributors

PersonTokensPropCommitsCommitProp
Matthew Wilcox25100.00%1100.00%
Total25100.00%1100.00%

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; }

Contributors

PersonTokensPropCommitsCommitProp
Matthew Wilcox140100.00%1100.00%
Total140100.00%1100.00%


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; } }

Contributors

PersonTokensPropCommitsCommitProp
Matthew Wilcox132100.00%1100.00%
Total132100.00%1100.00%


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; }

Contributors

PersonTokensPropCommitsCommitProp
Matthew Wilcox41100.00%1100.00%
Total41100.00%1100.00%


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; }

Contributors

PersonTokensPropCommitsCommitProp
Matthew Wilcox84100.00%1100.00%
Total84100.00%1100.00%


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"); } }

Contributors

PersonTokensPropCommitsCommitProp
Matthew Wilcox74100.00%1100.00%
Total74100.00%1100.00%


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; }

Contributors

PersonTokensPropCommitsCommitProp
Matthew Wilcox98100.00%1100.00%
Total98100.00%1100.00%


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); }

Contributors

PersonTokensPropCommitsCommitProp
Matthew Wilcox80100.00%1100.00%
Total80100.00%1100.00%


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; }

Contributors

PersonTokensPropCommitsCommitProp
Matthew Wilcox124100.00%1100.00%
Total124100.00%1100.00%

#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: scsi_dma_unmap(cmd); break; } cmd->__data_mapped = 0; }

Contributors

PersonTokensPropCommitsCommitProp
Matthew Wilcox3897.44%150.00%
FUJITA Tomonori12.56%150.00%
Total39100.00%2100.00%


static int __map_scsi_sg_data(struct device *dev, struct scsi_cmnd *cmd) { int use_sg; use_sg = scsi_dma_map(cmd); if (!use_sg) return 0; cmd->__data_mapped = 2; cmd->__data_mapping = use_sg; return use_sg; }

Contributors

PersonTokensPropCommitsCommitProp
Matthew Wilcox4183.67%150.00%
FUJITA Tomonori816.33%150.00%
Total49100.00%2100.00%

#define unmap_scsi_data(np, cmd) __unmap_scsi_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; #ifndef MODULE #ifdef SCSI_NCR_BOOT_COMMAND_LINE_SUPPORT static struct ncr_driver_setup driver_safe_setup __initdata = SCSI_NCR_DRIVER_SAFE_SETUP; #endif #endif /* !MODULE */ #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 #ifdef MODULE #define ARG_SEP ' ' #else #define ARG_SEP ',' #endif #ifndef MODULE 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 ';' */
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; }

Contributors

PersonTokensPropCommitsCommitProp
Matthew Wilcox77100.00%1100.00%
Total77100.00%1100.00%


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)(