X-Git-Url: http://git.onelab.eu/?a=blobdiff_plain;f=drivers%2Fscsi%2Fncr53c8xx.c;h=bbf521cbc55d135747965d5390d17d70c312343b;hb=refs%2Fheads%2Fvserver;hp=ce2e1ac7932ed18686a2b23980b83cf469500265;hpb=5273a3df6485dc2ad6aa7ddd441b9a21970f003b;p=linux-2.6.git diff --git a/drivers/scsi/ncr53c8xx.c b/drivers/scsi/ncr53c8xx.c index ce2e1ac79..bbf521cbc 100644 --- a/drivers/scsi/ncr53c8xx.c +++ b/drivers/scsi/ncr53c8xx.c @@ -69,6 +69,10 @@ ** 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). +** ******************************************************************************* */ @@ -83,38 +87,13 @@ ** ** Supported NCR/SYMBIOS chips: ** 53C720 (Wide, Fast SCSI-2, intfly problems) -** 53C810 (8 bits, Fast SCSI-2, no rom BIOS) -** 53C815 (8 bits, Fast SCSI-2, on board rom BIOS) -** 53C820 (Wide, Fast SCSI-2, no rom BIOS) -** 53C825 (Wide, Fast SCSI-2, on board rom BIOS) -** 53C860 (8 bits, Fast 20, no rom BIOS) -** 53C875 (Wide, Fast 20, on board rom BIOS) -** 53C895 (Wide, Fast 40, on board rom BIOS) -** 53C895A (Wide, Fast 40, on board rom BIOS) -** 53C896 (Wide, Fast 40, on board rom BIOS) -** 53C897 (Wide, Fast 40, on board rom BIOS) -** 53C1510D (Wide, Fast 40, on board rom BIOS) -** -** Other features: -** Memory mapped IO (linux-1.3.X and above only) -** Module -** Shared IRQ (since linux-1.3.72) */ -/* -** Name and version of the driver -*/ -#define SCSI_NCR_DRIVER_NAME "ncr53c8xx-3.4.3b-20010512" +/* Name and version of the driver */ +#define SCSI_NCR_DRIVER_NAME "ncr53c8xx-3.4.3g" #define SCSI_NCR_DEBUG_FLAGS (0) -/*========================================================== -** -** Include files -** -**========================================================== -*/ - #include #include #include @@ -137,30 +116,753 @@ #include #include -#include "scsi.h" -#include "hosts.h" +#include +#include +#include +#include +#include +#include +#include #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) + /* -** Donnot compile integrity checking code for Linux-2.3.0 -** and above since SCSI data structures are not ready yet. +** Enable/Disable debug messages. +** Can be changed at runtime too. */ -/* #if LINUX_VERSION_CODE < KERNEL_VERSION(2,3,0) */ -#if 0 -#define SCSI_NCR_INTEGRITY_CHECKING + +#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 -#define NAME53C "ncr53c" -#define NAME53C8XX "ncr53c8xx" -#define DRIVER_SMP_LOCK ncr53c8xx_lock +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; +} + +/*========================================================== +** +** 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; +} + +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<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<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) -#include "sym53c8xx_comm.h" +/* + * 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->request_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->request_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; + +#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; +} + +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; +} +#endif /* !MODULE */ + +/*=================================================================== +** +** 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 -int ncr53c8xx_slave_configure(Scsi_Device *device); -int ncr53c8xx_bus_reset(Scsi_Cmnd *cmd); -int ncr53c8xx_queue_command (Scsi_Cmnd *cmd, void (* done)(Scsi_Cmnd *)); -const char *ncr53c8xx_info (struct Scsi_Host *host); +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; +} /*========================================================== @@ -307,7 +1009,7 @@ typedef u32 tagmap_t; ** The maximum number of segments a transfer is split into. ** We support up to 127 segments for both read and write. ** The data scripts are broken into 2 sub-scripts. -** 80 (MAX_SCATTERL) segments are moved from a sub-script +** 80 (MAX_SCATTERL) segments are moved from a sub-script ** in on-chip RAM. This makes data transfers shorter than ** 80k (assuming 1k fs) as fast as possible. */ @@ -334,18 +1036,9 @@ typedef u32 tagmap_t; #define ScsiResult(host_code, scsi_code) (((host_code) << 16) + ((scsi_code) & 0x7f)) -static void ncr53c8xx_timeout(unsigned long np); -static int ncr53c8xx_proc_info(struct Scsi_Host *host, char *buffer, char **start, off_t offset, - int length, int func); - #define initverbose (driver_setup.verbose) #define bootverbose (np->verbose) -#ifdef SCSI_NCR_NVRAM_SUPPORT -static u_char Tekram_sync[16] __initdata = - {25,31,37,43, 50,62,75,125, 12,15,18,21, 6,7,9,10}; -#endif /* SCSI_NCR_NVRAM_SUPPORT */ - /*========================================================== ** ** Command control block states. @@ -438,44 +1131,21 @@ static u_char Tekram_sync[16] __initdata = /*========================================================== ** -** "Special features" of targets. -** quirks field of struct tcb. -** actualquirks field of struct ccb. -** -**========================================================== -*/ - -#define QUIRK_AUTOSAVE (0x01) -#define QUIRK_NOMSG (0x02) -#define QUIRK_NOSYNC (0x10) -#define QUIRK_NOWIDE16 (0x20) - -/*========================================================== -** -** Capability bits in Inquire response byte 7. +** Misc. ** **========================================================== */ -#define INQ7_QUEUE (0x02) -#define INQ7_SYNC (0x10) -#define INQ7_WIDE16 (0x20) +#define CCB_MAGIC (0xf2691ad2) /*========================================================== ** -** Misc. +** Declaration of structs. ** **========================================================== */ -#define CCB_MAGIC (0xf2691ad2) - -/*========================================================== -** -** Declaration of structs. -** -**========================================================== -*/ +static struct scsi_transport_template *ncr53c8xx_transport_template = NULL; struct tcb; struct lcb; @@ -483,11 +1153,6 @@ struct ccb; struct ncb; struct script; -typedef struct ncb * ncb_p; -typedef struct tcb * tcb_p; -typedef struct lcb * lcb_p; -typedef struct ccb * ccb_p; - struct link { ncrcmd l_cmd; ncrcmd l_paddr; @@ -558,9 +1223,7 @@ struct tcb { **---------------------------------------------------------------- */ struct link jump_lcb[4]; /* JUMPs for reselection */ - lcb_p lp[MAX_LUN]; /* The lcb's of this tcb */ - u_char inq_done; /* Target capabilities received */ - u_char inq_byte7; /* Contains these capabilities */ + struct lcb * lp[MAX_LUN]; /* The lcb's of this tcb */ /*---------------------------------------------------------------- ** Pointer to the ccb used for negotiation. @@ -568,7 +1231,7 @@ struct tcb { ** when tagged command queuing is enabled. **---------------------------------------------------------------- */ - ccb_p nego_cp; + struct ccb * nego_cp; /*---------------------------------------------------------------- ** statistical data @@ -582,7 +1245,7 @@ struct tcb { **---------------------------------------------------------------- */ #ifdef SCSI_NCR_BIG_ENDIAN -/*0*/ u_short period; +/*0*/ u16 period; /*2*/ u_char sval; /*3*/ u_char minsync; /*0*/ u_char wval; @@ -592,29 +1255,19 @@ struct tcb { #else /*0*/ u_char minsync; /*1*/ u_char sval; -/*2*/ u_short period; +/*2*/ u16 period; /*0*/ u_char maxoffs; /*1*/ u_char quirks; /*2*/ u_char widedone; /*3*/ u_char wval; #endif -#ifdef SCSI_NCR_INTEGRITY_CHECKING - u_char ic_min_sync; - u_char ic_max_width; - u_char ic_maximums_set; - u_char ic_done; -#endif - - /*---------------------------------------------------------------- - ** User settable limits and options. - ** These limits are read from the NVRAM if present. - **---------------------------------------------------------------- - */ + /* User settable limits and options. */ u_char usrsync; u_char usrwide; u_char usrtags; u_char usrflag; + struct scsi_target *starget; }; /*======================================================================== @@ -658,10 +1311,10 @@ struct lcb { ** CCB queue management. **---------------------------------------------------------------- */ - XPT_QUEHEAD free_ccbq; /* Queue of available CCBs */ - XPT_QUEHEAD busy_ccbq; /* Queue of busy CCBs */ - XPT_QUEHEAD wait_ccbq; /* Queue of waiting for IO CCBs */ - XPT_QUEHEAD skip_ccbq; /* Queue of skipped CCBs */ + struct list_head free_ccbq; /* Queue of available CCBs */ + struct list_head busy_ccbq; /* Queue of busy CCBs */ + struct list_head wait_ccbq; /* Queue of waiting for IO CCBs */ + struct list_head skip_ccbq; /* Queue of skipped CCBs */ u_char actccbs; /* Number of allocated CCBs */ u_char busyccbs; /* CCBs busy for this lun */ u_char queuedccbs; /* CCBs queued to the controller*/ @@ -681,7 +1334,6 @@ struct lcb { u_char usetags; /* Command queuing is active */ u_char maxtags; /* Max nr of tags asked by user */ u_char numtags; /* Current number of tags */ - u_char inq_byte7; /* Store unit CmdQ capabitility */ /*---------------------------------------------------------------- ** QUEUE FULL control and ORDERED tag control. @@ -691,11 +1343,11 @@ struct lcb { ** QUEUE FULL and ORDERED tag control. **---------------------------------------------------------------- */ - u_short num_good; /* Nr of GOOD since QUEUE FULL */ + u16 num_good; /* Nr of GOOD since QUEUE FULL */ tagmap_t tags_umap; /* Used tags bitmap */ tagmap_t tags_smap; /* Tags in use at 'tag_stime' */ u_long tags_stime; /* Last time we set smap=umap */ - ccb_p held_ccb; /* CCB held for QUEUE FULL */ + struct ccb * held_ccb; /* CCB held for QUEUE FULL */ }; /*======================================================================== @@ -761,7 +1413,7 @@ struct head { ** The virtual address of the ccb containing this header. **---------------------------------------------------------------- */ - ccb_p cp; + struct ccb * cp; /*---------------------------------------------------------------- ** Status fields. @@ -789,7 +1441,7 @@ struct head { ** The first four bytes (scr_st[4]) are used inside the script by ** "COPY" commands. ** Because source and destination must have the same alignment -** in a DWORD, the fields HAVE to be at the choosen offsets. +** in a DWORD, the fields HAVE to be at the chosen offsets. ** xerr_st 0 (0x34) scratcha ** sync_st 1 (0x05) sxfer ** wide_st 3 (0x03) scntl3 @@ -849,7 +1501,7 @@ struct head { ** the DSA (data structure address) register points ** to this substructure of the ccb. ** This substructure contains the header with -** the script-processor-changable data and +** the script-processor-changeable data and ** data blocks for the indirect move commands. ** **---------------------------------------------------------- @@ -871,7 +1523,7 @@ struct dsb { struct scr_tblmove smsg ; struct scr_tblmove cmd ; struct scr_tblmove sense ; - struct scr_tblmove data [MAX_SCATTER]; + struct scr_tblmove data[MAX_SCATTER]; }; @@ -921,7 +1573,7 @@ struct ccb { ** pointer to a control block. **---------------------------------------------------------------- */ - Scsi_Cmnd *cmd; /* SCSI command */ + struct scsi_cmnd *cmd; /* SCSI command */ u_char cdb_buf[16]; /* Copy of CDB */ u_char sense_buf[64]; int data_len; /* Total data length */ @@ -951,8 +1603,8 @@ struct ccb { u_char lun; u_char queued; u_char auto_sense; - ccb_p link_ccb; /* Host adapter CCB chain */ - XPT_QUEHEAD link_ccbq; /* Link to unit CCB queue */ + struct ccb * link_ccb; /* Host adapter CCB chain */ + struct list_head link_ccbq; /* Link to unit CCB queue */ u32 startp; /* Initial data pointer */ u_long magic; /* Free / busy CCB flag */ }; @@ -980,9 +1632,9 @@ struct ncb { ** CCBs management queues. **---------------------------------------------------------------- */ - Scsi_Cmnd *waiting_list; /* Commands waiting for a CCB */ + struct scsi_cmnd *waiting_list; /* Commands waiting for a CCB */ /* when lcb is not allocated. */ - Scsi_Cmnd *done_list; /* Commands waiting for done() */ + struct scsi_cmnd *done_list; /* Commands waiting for done() */ /* callback to be invoked. */ spinlock_t smp_lock; /* Lock for SMP threading */ @@ -991,7 +1643,6 @@ struct ncb { **---------------------------------------------------------------- */ int unit; /* Unit number */ - char chip_name[8]; /* Chip name */ char inst_name[16]; /* ncb instance name */ /*---------------------------------------------------------------- @@ -1030,11 +1681,11 @@ struct ncb { ** Virtual and physical bus addresses of the chip. **---------------------------------------------------------------- */ - vm_offset_t vaddr; /* Virtual and bus address of */ - vm_offset_t paddr; /* chip's IO registers. */ - vm_offset_t paddr2; /* On-chip RAM bus address. */ + void __iomem *vaddr; /* Virtual and bus address of */ + unsigned long paddr; /* chip's IO registers. */ + unsigned long paddr2; /* On-chip RAM bus address. */ volatile /* Pointer to volatile for */ - struct ncr_reg *reg; /* memory mapped IO. */ + struct ncr_reg __iomem *reg; /* memory mapped IO. */ /*---------------------------------------------------------------- ** SCRIPTS virtual and physical bus addresses. @@ -1053,13 +1704,9 @@ struct ncb { **---------------------------------------------------------------- */ struct device *dev; - u_short device_id; /* PCI device id */ u_char revision_id; /* PCI device revision id */ - u_char bus; /* PCI BUS number */ - u_char device_fn; /* PCI BUS device and function */ - u_long base_io; /* IO space base address */ - u_int irq; /* IRQ level */ - u_int features; /* Chip features map */ + u32 irq; /* IRQ level */ + u32 features; /* Chip features map */ u_char myaddr; /* SCSI id of the adapter */ u_char maxburst; /* log base 2 of dwords burst */ u_char maxwide; /* Maximum transfer width */ @@ -1076,10 +1723,10 @@ struct ncb { ** SCRIPTS processor in order to start SCSI commands. **---------------------------------------------------------------- */ - u_short squeueput; /* Next free slot of the queue */ - u_short actccbs; /* Number of allocated CCBs */ - u_short queuedccbs; /* Number of CCBs in start queue*/ - u_short queuedepth; /* Start queue depth */ + u16 squeueput; /* Next free slot of the queue */ + u16 actccbs; /* Number of allocated CCBs */ + u16 queuedccbs; /* Number of CCBs in start queue*/ + u16 queuedepth; /* Start queue depth */ /*---------------------------------------------------------------- ** Timeout handler. @@ -1133,17 +1780,6 @@ struct ncb { struct ccb *ccb; /* Global CCB */ struct usrcmd user; /* Command from user */ volatile u_char release_stage; /* Synchronisation stage on release */ - -#ifdef SCSI_NCR_INTEGRITY_CHECKING - /*---------------------------------------------------------------- - ** Fields that are used for integrity check - **---------------------------------------------------------------- - */ - unsigned char check_integrity; /* Enable midlayer integ.check on - * bus scan. */ - unsigned char check_integ_par; /* Set if par or Init. Det. error - * used only during integ check */ -#endif }; #define NCB_SCRIPT_PHYS(np,lbl) (np->p_script + offsetof (struct script, lbl)) @@ -1223,7 +1859,7 @@ struct script { #endif ncrcmd save_dp [ 7]; ncrcmd restore_dp [ 5]; - ncrcmd disconnect [ 17]; + ncrcmd disconnect [ 10]; ncrcmd msg_out [ 9]; ncrcmd msg_out_done [ 7]; ncrcmd idle [ 2]; @@ -1304,65 +1940,52 @@ struct scripth { **========================================================== */ -static void ncr_alloc_ccb (ncb_p np, u_char tn, u_char ln); -static void ncr_complete (ncb_p np, ccb_p cp); -static void ncr_exception (ncb_p np); -static void ncr_free_ccb (ncb_p np, ccb_p cp); -static void ncr_init_ccb (ncb_p np, ccb_p cp); -static void ncr_init_tcb (ncb_p np, u_char tn); -static lcb_p ncr_alloc_lcb (ncb_p np, u_char tn, u_char ln); -static lcb_p ncr_setup_lcb (ncb_p np, u_char tn, u_char ln, - u_char *inq_data); -static void ncr_getclock (ncb_p np, int mult); -static void ncr_selectclock (ncb_p np, u_char scntl3); -static ccb_p ncr_get_ccb (ncb_p np, u_char tn, u_char ln); -static void ncr_chip_reset (ncb_p np, int delay); -static void ncr_init (ncb_p np, int reset, char * msg, u_long code); -static int ncr_int_sbmc (ncb_p np); -static int ncr_int_par (ncb_p np); -static void ncr_int_ma (ncb_p np); -static void ncr_int_sir (ncb_p np); -static void ncr_int_sto (ncb_p np); -static u_long ncr_lookup (char* id); +static void ncr_alloc_ccb (struct ncb *np, u_char tn, u_char ln); +static void ncr_complete (struct ncb *np, struct ccb *cp); +static void ncr_exception (struct ncb *np); +static void ncr_free_ccb (struct ncb *np, struct ccb *cp); +static void ncr_init_ccb (struct ncb *np, struct ccb *cp); +static void ncr_init_tcb (struct ncb *np, u_char tn); +static struct lcb * ncr_alloc_lcb (struct ncb *np, u_char tn, u_char ln); +static struct lcb * ncr_setup_lcb (struct ncb *np, struct scsi_device *sdev); +static void ncr_getclock (struct ncb *np, int mult); +static void ncr_selectclock (struct ncb *np, u_char scntl3); +static struct ccb *ncr_get_ccb (struct ncb *np, struct scsi_cmnd *cmd); +static void ncr_chip_reset (struct ncb *np, int delay); +static void ncr_init (struct ncb *np, int reset, char * msg, u_long code); +static int ncr_int_sbmc (struct ncb *np); +static int ncr_int_par (struct ncb *np); +static void ncr_int_ma (struct ncb *np); +static void ncr_int_sir (struct ncb *np); +static void ncr_int_sto (struct ncb *np); static void ncr_negotiate (struct ncb* np, struct tcb* tp); -static int ncr_prepare_nego(ncb_p np, ccb_p cp, u_char *msgptr); -#ifdef SCSI_NCR_INTEGRITY_CHECKING -static int ncr_ic_nego(ncb_p np, ccb_p cp, Scsi_Cmnd *cmd, u_char *msgptr); -#endif +static int ncr_prepare_nego(struct ncb *np, struct ccb *cp, u_char *msgptr); static void ncr_script_copy_and_bind - (ncb_p np, ncrcmd *src, ncrcmd *dst, int len); + (struct ncb *np, ncrcmd *src, ncrcmd *dst, int len); static void ncr_script_fill (struct script * scr, struct scripth * scripth); -static int ncr_scatter (ncb_p np, ccb_p cp, Scsi_Cmnd *cmd); -static void ncr_getsync (ncb_p np, u_char sfac, u_char *fakp, u_char *scntl3p); -static void ncr_setsync (ncb_p np, ccb_p cp, u_char scntl3, u_char sxfer); -static void ncr_setup_tags (ncb_p np, u_char tn, u_char ln); -static void ncr_setwide (ncb_p np, ccb_p cp, u_char wide, u_char ack); -static int ncr_show_msg (u_char * msg); -static void ncr_print_msg (ccb_p cp, char *label, u_char *msg); -static int ncr_snooptest (ncb_p np); -static void ncr_timeout (ncb_p np); -static void ncr_wakeup (ncb_p np, u_long code); -static void ncr_wakeup_done (ncb_p np); -static void ncr_start_next_ccb (ncb_p np, lcb_p lp, int maxn); -static void ncr_put_start_queue(ncb_p np, ccb_p cp); -static void ncr_start_reset (ncb_p np); -static int ncr_reset_scsi_bus (ncb_p np, int enab_int, int settle_delay); - -#ifdef SCSI_NCR_USER_COMMAND_SUPPORT -static void ncr_usercmd (ncb_p np); -#endif - -static void insert_into_waiting_list(ncb_p np, Scsi_Cmnd *cmd); -static Scsi_Cmnd *retrieve_from_waiting_list(int to_remove, ncb_p np, Scsi_Cmnd *cmd); -static void process_waiting_list(ncb_p np, int sts); +static int ncr_scatter (struct ncb *np, struct ccb *cp, struct scsi_cmnd *cmd); +static void ncr_getsync (struct ncb *np, u_char sfac, u_char *fakp, u_char *scntl3p); +static void ncr_setsync (struct ncb *np, struct ccb *cp, u_char scntl3, u_char sxfer); +static void ncr_setup_tags (struct ncb *np, struct scsi_device *sdev); +static void ncr_setwide (struct ncb *np, struct ccb *cp, u_char wide, u_char ack); +static int ncr_snooptest (struct ncb *np); +static void ncr_timeout (struct ncb *np); +static void ncr_wakeup (struct ncb *np, u_long code); +static void ncr_wakeup_done (struct ncb *np); +static void ncr_start_next_ccb (struct ncb *np, struct lcb * lp, int maxn); +static void ncr_put_start_queue(struct ncb *np, struct ccb *cp); + +static void insert_into_waiting_list(struct ncb *np, struct scsi_cmnd *cmd); +static struct scsi_cmnd *retrieve_from_waiting_list(int to_remove, struct ncb *np, struct scsi_cmnd *cmd); +static void process_waiting_list(struct ncb *np, int sts); #define remove_from_waiting_list(np, cmd) \ retrieve_from_waiting_list(1, (np), (cmd)) #define requeue_waiting_list(np) process_waiting_list((np), DID_OK) #define reset_waiting_list(np) process_waiting_list((np), DID_RESET) -static inline char *ncr_name (ncb_p np) +static inline char *ncr_name (struct ncb *np) { return np->inst_name; } @@ -1487,7 +2110,7 @@ static struct script script0 __initdata = { */ /* - ** The M_REJECT problem seems to be due to a selection + ** The MESSAGE_REJECT problem seems to be due to a selection ** timing problem. ** Wait immediately for the selection to complete. ** (2.5x behaves so) @@ -1538,7 +2161,7 @@ static struct script script0 __initdata = { /* ** Selection complete. ** Send the IDENTIFY and SIMPLE_TAG messages - ** (and the M_X_SYNC_REQ message) + ** (and the EXTENDED_SDTR message) */ SCR_MOVE_TBL ^ SCR_MSG_OUT, offsetof (struct dsb, smsg), @@ -1567,7 +2190,7 @@ static struct script script0 __initdata = { /* ** Initialize the msgout buffer with a NOOP message. */ - SCR_LOAD_REG (scratcha, M_NOOP), + SCR_LOAD_REG (scratcha, NOP), 0, SCR_COPY (1), RADDR (scratcha), @@ -1719,21 +2342,21 @@ static struct script script0 __initdata = { /* ** Handle this message. */ - SCR_JUMP ^ IFTRUE (DATA (M_COMPLETE)), + SCR_JUMP ^ IFTRUE (DATA (COMMAND_COMPLETE)), PADDR (complete), - SCR_JUMP ^ IFTRUE (DATA (M_DISCONNECT)), + SCR_JUMP ^ IFTRUE (DATA (DISCONNECT)), PADDR (disconnect), - SCR_JUMP ^ IFTRUE (DATA (M_SAVE_DP)), + SCR_JUMP ^ IFTRUE (DATA (SAVE_POINTERS)), PADDR (save_dp), - SCR_JUMP ^ IFTRUE (DATA (M_RESTORE_DP)), + SCR_JUMP ^ IFTRUE (DATA (RESTORE_POINTERS)), PADDR (restore_dp), - SCR_JUMP ^ IFTRUE (DATA (M_EXTENDED)), + SCR_JUMP ^ IFTRUE (DATA (EXTENDED_MESSAGE)), PADDRH (msg_extended), - SCR_JUMP ^ IFTRUE (DATA (M_NOOP)), + SCR_JUMP ^ IFTRUE (DATA (NOP)), PADDR (clrack), - SCR_JUMP ^ IFTRUE (DATA (M_REJECT)), + SCR_JUMP ^ IFTRUE (DATA (MESSAGE_REJECT)), PADDRH (msg_reject), - SCR_JUMP ^ IFTRUE (DATA (M_IGN_RESIDUE)), + SCR_JUMP ^ IFTRUE (DATA (IGNORE_WIDE_RESIDUE)), PADDRH (msg_ign_residue), /* ** Rest of the messages left as @@ -1748,7 +2371,7 @@ static struct script script0 __initdata = { */ SCR_INT, SIR_REJECT_SENT, - SCR_LOAD_REG (scratcha, M_REJECT), + SCR_LOAD_REG (scratcha, MESSAGE_REJECT), 0, }/*-------------------------< SETMSG >----------------------*/,{ SCR_COPY (1), @@ -1851,13 +2474,8 @@ static struct script script0 __initdata = { /* ** ... signal completion to the host */ -#ifdef SIMULATED_INTFLY SCR_INT, SIR_INTFLY, -#else - SCR_INT_FLY, - 0, -#endif /* ** Auf zu neuen Schandtaten! */ @@ -1876,13 +2494,8 @@ static struct script script0 __initdata = { SCR_INT, SIR_DONE_OVERFLOW, }/*------------------------< DONE_END >---------------------*/,{ -#ifdef SIMULATED_INTFLY SCR_INT, SIR_INTFLY, -#else - SCR_INT_FLY, - 0, -#endif SCR_COPY (4), RADDR (temp), PADDR (done_pos), @@ -1935,21 +2548,6 @@ static struct script script0 __initdata = { */ SCR_LOAD_REG (HS_REG, HS_DISCONNECT), 0, - /* - ** If QUIRK_AUTOSAVE is set, - ** do an "save pointer" operation. - */ - SCR_FROM_REG (QU_REG), - 0, - SCR_JUMP ^ IFFALSE (MASK (QUIRK_AUTOSAVE, QUIRK_AUTOSAVE)), - PADDR (cleanup_ok), - /* - ** like SAVE_DP message: - ** Copy TEMP register to SAVEP in header. - */ - SCR_COPY (4), - RADDR (temp), - NADDR (header.savep), SCR_JUMP, PADDR (cleanup_ok), @@ -1965,7 +2563,7 @@ static struct script script0 __initdata = { /* ** If it was no ABORT message ... */ - SCR_JUMP ^ IFTRUE (DATA (M_ABORT)), + SCR_JUMP ^ IFTRUE (DATA (ABORT_TASK_SET)), PADDRH (msg_out_abort), /* ** ... wait for the next phase @@ -1977,7 +2575,7 @@ static struct script script0 __initdata = { /* ** ... else clear the message ... */ - SCR_LOAD_REG (scratcha, M_NOOP), + SCR_LOAD_REG (scratcha, NOP), 0, SCR_COPY (4), RADDR (scratcha), @@ -2226,7 +2824,7 @@ static struct scripth scripth0 __initdata = { **----------------------------------------------------------- ** ** ##===========< I=0; i=========== -** || SCR_COPY (sizeof(ccb_p)), +** || SCR_COPY (sizeof(struct ccb *), ** || NADDR (header.cp), ** || NADDR (ccb_done[i]), ** || SCR_CALL, @@ -2436,7 +3034,7 @@ static struct scripth scripth0 __initdata = { */ SCR_MOVE_ABS (1) ^ SCR_MSG_IN, NADDR (msgin[2]), - SCR_JUMP ^ IFTRUE (DATA (M_X_WIDE_REQ)), + SCR_JUMP ^ IFTRUE (DATA (EXTENDED_WDTR)), PADDRH (msg_wdtr), /* ** unknown extended message @@ -2470,7 +3068,7 @@ static struct scripth scripth0 __initdata = { }/*-------------------------< SEND_WDTR >----------------*/,{ /* - ** Send the M_X_WIDE_REQ + ** Send the EXTENDED_WDTR */ SCR_MOVE_ABS (4) ^ SCR_MSG_OUT, NADDR (msgout), @@ -2490,7 +3088,7 @@ static struct scripth scripth0 __initdata = { */ SCR_MOVE_ABS (1) ^ SCR_MSG_IN, NADDR (msgin[2]), - SCR_JUMP ^ IFTRUE (DATA (M_X_SYNC_REQ)), + SCR_JUMP ^ IFTRUE (DATA (EXTENDED_SDTR)), PADDRH (msg_sdtr), /* ** unknown extended message @@ -2525,7 +3123,7 @@ static struct scripth scripth0 __initdata = { }/*-------------------------< SEND_SDTR >-------------*/,{ /* - ** Send the M_X_SYNC_REQ + ** Send the EXTENDED_SDTR */ SCR_MOVE_ABS (5) ^ SCR_MSG_OUT, NADDR (msgout), @@ -2603,10 +3201,10 @@ static struct scripth scripth0 __initdata = { }/*-------------------------< RESET >----------------------*/,{ /* - ** Send a M_RESET message if bad IDENTIFY + ** Send a TARGET_RESET message if bad IDENTIFY ** received on reselection. */ - SCR_LOAD_REG (scratcha, M_ABORT_TAG), + SCR_LOAD_REG (scratcha, ABORT_TASK), 0, SCR_JUMP, PADDRH (abort_resel), @@ -2614,7 +3212,7 @@ static struct scripth scripth0 __initdata = { /* ** Abort a wrong tag received on reselection. */ - SCR_LOAD_REG (scratcha, M_ABORT_TAG), + SCR_LOAD_REG (scratcha, ABORT_TASK), 0, SCR_JUMP, PADDRH (abort_resel), @@ -2622,7 +3220,7 @@ static struct scripth scripth0 __initdata = { /* ** Abort a reselection when no active CCB. */ - SCR_LOAD_REG (scratcha, M_ABORT), + SCR_LOAD_REG (scratcha, ABORT_TASK_SET), 0, }/*-------------------------< ABORT_RESEL >----------------*/,{ SCR_COPY (1), @@ -2734,7 +3332,7 @@ static struct scripth scripth0 __initdata = { ** Read the message, since we got it directly ** from the SCSI BUS data lines. ** Signal problem to C code for logging the event. - ** Send a M_ABORT to clear all pending tasks. + ** Send an ABORT_TASK_SET to clear all pending tasks. */ SCR_INT, SIR_RESEL_BAD_LUN, @@ -2746,7 +3344,7 @@ static struct scripth scripth0 __initdata = { /* ** We donnot have a task for that I_T_L. ** Signal problem to C code for logging the event. - ** Send a M_ABORT message. + ** Send an ABORT_TASK_SET message. */ SCR_INT, SIR_RESEL_BAD_I_T_L, @@ -2756,7 +3354,7 @@ static struct scripth scripth0 __initdata = { /* ** We donnot have a task that matches the tag. ** Signal problem to C code for logging the event. - ** Send a M_ABORTTAG message. + ** Send an ABORT_TASK message. */ SCR_INT, SIR_RESEL_BAD_I_T_L_Q, @@ -2767,7 +3365,7 @@ static struct scripth scripth0 __initdata = { ** We donnot know the target that reselected us. ** Grab the first message if any (IDENTIFY). ** Signal problem to C code for logging the event. - ** M_RESET message. + ** TARGET_RESET message. */ SCR_INT, SIR_RESEL_BAD_TARGET, @@ -2877,22 +3475,22 @@ void __init ncr_script_fill (struct script * scr, struct scripth * scrh) for (i=0; itryloop + sizeof (scrh->tryloop)); + BUG_ON((u_long)p != (u_long)&scrh->tryloop + sizeof (scrh->tryloop)); #ifdef SCSI_NCR_CCB_DONE_SUPPORT p = scrh->done_queue; for (i = 0; idone_queue+sizeof(scrh->done_queue)); + BUG_ON((u_long)p != (u_long)&scrh->done_queue+sizeof(scrh->done_queue)); #endif /* SCSI_NCR_CCB_DONE_SUPPORT */ @@ -2902,8 +3500,9 @@ void __init ncr_script_fill (struct script * scr, struct scripth * scrh) *p++ =PADDR (dispatch); *p++ =SCR_MOVE_TBL ^ SCR_DATA_IN; *p++ =offsetof (struct dsb, data[i]); - }; - assert ((u_long)p == (u_long)&scrh->hdata_in + sizeof (scrh->hdata_in)); + } + + BUG_ON((u_long)p != (u_long)&scrh->hdata_in + sizeof (scrh->hdata_in)); p = scr->data_in; for (i=MAX_SCATTERH; idata_in + sizeof (scr->data_in)); + } + + BUG_ON((u_long)p != (u_long)&scr->data_in + sizeof (scr->data_in)); p = scrh->hdata_out; for (i=0; ihdata_out + sizeof (scrh->hdata_out)); + } + + BUG_ON((u_long)p != (u_long)&scrh->hdata_out + sizeof (scrh->hdata_out)); p = scr->data_out; for (i=MAX_SCATTERH; idata_out + sizeof (scr->data_out)); + BUG_ON((u_long) p != (u_long)&scr->data_out + sizeof (scr->data_out)); } /*========================================================== @@ -2944,7 +3545,7 @@ void __init ncr_script_fill (struct script * scr, struct scripth * scrh) */ static void __init -ncr_script_copy_and_bind (ncb_p np, ncrcmd *src, ncrcmd *dst, int len) +ncr_script_copy_and_bind (struct ncb *np, ncrcmd *src, ncrcmd *dst, int len) { ncrcmd opcode, new, old, tmp1, tmp2; ncrcmd *start, *end; @@ -2969,8 +3570,8 @@ ncr_script_copy_and_bind (ncb_p np, ncrcmd *src, ncrcmd *dst, int len) if (opcode == 0) { printk (KERN_ERR "%s: ERROR0 IN SCRIPT at %d.\n", ncr_name(np), (int) (src-start-1)); - MDELAY (1000); - }; + mdelay(1000); + } if (DEBUG_FLAGS & DEBUG_SCRIPT) printk (KERN_DEBUG "%p: <%x>\n", @@ -2999,7 +3600,7 @@ ncr_script_copy_and_bind (ncb_p np, ncrcmd *src, ncrcmd *dst, int len) if ((tmp1 ^ tmp2) & 3) { printk (KERN_ERR"%s: ERROR1 IN SCRIPT at %d.\n", ncr_name(np), (int) (src-start-1)); - MDELAY (1000); + mdelay(1000); } /* ** If PREFETCH feature not enabled, remove @@ -3039,7 +3640,7 @@ ncr_script_copy_and_bind (ncb_p np, ncrcmd *src, ncrcmd *dst, int len) default: relocs = 0; break; - }; + } if (relocs) { while (relocs--) { @@ -3086,49 +3687,25 @@ ncr_script_copy_and_bind (ncb_p np, ncrcmd *src, ncrcmd *dst, int len) } else *dst++ = cpu_to_scr(*src++); - }; + } } -/*========================================================== -** -** -** Auto configuration: attach and init a host adapter. -** -** -**========================================================== -*/ - /* ** Linux host data structure -** -** The script area is allocated in the host data structure -** because kmalloc() returns NULL during scsi initialisations -** with Linux 1.2.X */ struct host_data { struct ncb *ncb; }; -/* -** Print something which allows to retrieve the controller type, unit, -** target, lun concerned by a kernel message. -*/ - -static void PRINT_TARGET(ncb_p np, int target) -{ - printk(KERN_INFO "%s-<%d,*>: ", ncr_name(np), target); -} +#define PRINT_ADDR(cmd, arg...) dev_info(&cmd->device->sdev_gendev , ## arg) -static void PRINT_LUN(ncb_p np, int target, int lun) +static void ncr_print_msg(struct ccb *cp, char *label, u_char *msg) { - printk(KERN_INFO "%s-<%d,%d>: ", ncr_name(np), target, lun); -} + PRINT_ADDR(cp->cmd, "%s: ", label); -static void PRINT_ADDR(Scsi_Cmnd *cmd) -{ - struct host_data *host_data = (struct host_data *) cmd->device->host->hostdata; - PRINT_LUN(host_data->ncb, cmd->device->id, cmd->device->lun); + spi_print_msg(msg); + printk("\n"); } /*========================================================== @@ -3164,90 +3741,31 @@ static u_long div_10M[] = #define burst_length(bc) (!(bc))? 0 : 1 << (bc) /* - * Burst code from io register bits. Burst enable is ctest0 for c720, - * ctest4 for others. + * Burst code from io register bits. Burst enable is ctest0 for c720 */ -#define burst_code(dmode, ctest0, ctest4, ctest5) \ - (np->device_id == PSEUDO_720_ID) ? \ - (ctest0) & 0x80? 0 : (((dmode) & 0xc0) >> 6) + 1 : \ - (ctest4) & 0x80? 0 : (((dmode) & 0xc0) >> 6) + ((ctest5) & 0x04) + 1 +#define burst_code(dmode, ctest0) \ + (ctest0) & 0x80 ? 0 : (((dmode) & 0xc0) >> 6) + 1 /* * Set initial io register bits from burst code. */ -static inline void ncr_init_burst(ncb_p np, u_char bc) +static inline void ncr_init_burst(struct ncb *np, u_char bc) { - u_char *be = (np->device_id == PSEUDO_720_ID) ? - &np->rv_ctest0 : &np->rv_ctest4; + u_char *be = &np->rv_ctest0; *be &= ~0x80; np->rv_dmode &= ~(0x3 << 6); np->rv_ctest5 &= ~0x4; if (!bc) { *be |= 0x80; - } - else { + } else { --bc; np->rv_dmode |= ((bc & 0x3) << 6); np->rv_ctest5 |= (bc & 0x4); } } -#ifdef SCSI_NCR_NVRAM_SUPPORT - -/* -** Get target set-up from Symbios format NVRAM. -*/ - -static void __init -ncr_Symbios_setup_target(ncb_p np, int target, Symbios_nvram *nvram) -{ - tcb_p tp = &np->target[target]; - Symbios_target *tn = &nvram->target[target]; - - tp->usrsync = tn->sync_period ? (tn->sync_period + 3) / 4 : 255; - tp->usrwide = tn->bus_width == 0x10 ? 1 : 0; - tp->usrtags = - (tn->flags & SYMBIOS_QUEUE_TAGS_ENABLED)? MAX_TAGS : 0; - - if (!(tn->flags & SYMBIOS_DISCONNECT_ENABLE)) - tp->usrflag |= UF_NODISC; - if (!(tn->flags & SYMBIOS_SCAN_AT_BOOT_TIME)) - tp->usrflag |= UF_NOSCAN; -} - -/* -** Get target set-up from Tekram format NVRAM. -*/ - -static void __init -ncr_Tekram_setup_target(ncb_p np, int target, Tekram_nvram *nvram) -{ - tcb_p tp = &np->target[target]; - struct Tekram_target *tn = &nvram->target[target]; - int i; - - if (tn->flags & TEKRAM_SYNC_NEGO) { - i = tn->sync_index & 0xf; - tp->usrsync = Tekram_sync[i]; - } - - tp->usrwide = (tn->flags & TEKRAM_WIDE_NEGO) ? 1 : 0; - - if (tn->flags & TEKRAM_TAGGED_COMMANDS) { - tp->usrtags = 2 << nvram->max_tags_index; - } - - if (!(tn->flags & TEKRAM_DISCONNECT_ENABLE)) - tp->usrflag = UF_NODISC; - - /* If any device does not support parity, we will not use this option */ - if (!(tn->flags & TEKRAM_PARITY_CHECK)) - np->rv_scntl0 &= ~0x0a; /* SCSI parity checking disabled */ -} -#endif /* SCSI_NCR_NVRAM_SUPPORT */ - -static int __init ncr_prepare_setting(ncb_p np, ncr_nvram *nvram) +static void __init ncr_prepare_setting(struct ncb *np) { u_char burst_max; u_long period; @@ -3278,9 +3796,7 @@ static int __init ncr_prepare_setting(ncb_p np, ncr_nvram *nvram) /* * Guess the frequency of the chip's clock. */ - if (np->features & (FE_ULTRA3 | FE_ULTRA2)) - np->clock_khz = 160000; - else if (np->features & FE_ULTRA) + if (np->features & FE_ULTRA) np->clock_khz = 80000; else np->clock_khz = 40000; @@ -3329,10 +3845,8 @@ static int __init ncr_prepare_setting(ncb_p np, ncr_nvram *nvram) * Check against chip SCSI standard support (SCSI-2,ULTRA,ULTRA2). */ - if (np->minsync < 25 && !(np->features & (FE_ULTRA|FE_ULTRA2))) + if (np->minsync < 25 && !(np->features & FE_ULTRA)) np->minsync = 25; - else if (np->minsync < 12 && !(np->features & FE_ULTRA2)) - np->minsync = 12; /* * Maximum synchronous period factor supported by the chip. @@ -3352,7 +3866,7 @@ static int __init ncr_prepare_setting(ncb_p np, ncr_nvram *nvram) np->rv_ctest3 = np->sv_ctest3; np->rv_ctest4 = np->sv_ctest4; np->rv_ctest5 = np->sv_ctest5; - burst_max = burst_code(np->sv_dmode, np->sv_ctest0, np->sv_ctest4, np->sv_ctest5); + burst_max = burst_code(np->sv_dmode, np->sv_ctest0); #else /* @@ -3360,7 +3874,7 @@ static int __init ncr_prepare_setting(ncb_p np, ncr_nvram *nvram) */ burst_max = driver_setup.burst_max; if (burst_max == 255) - burst_max = burst_code(np->sv_dmode, np->sv_ctest0, np->sv_ctest4, np->sv_ctest5); + burst_max = burst_code(np->sv_dmode, np->sv_ctest0); if (burst_max > 7) burst_max = 7; if (burst_max > np->maxburst) @@ -3398,25 +3912,6 @@ static int __init ncr_prepare_setting(ncb_p np, ncr_nvram *nvram) if (driver_setup.scsi_parity) np->rv_scntl0 |= 0x0a; /* full arb., ena parity, par->ATN */ -#ifdef SCSI_NCR_NVRAM_SUPPORT - /* - ** Get parity checking, host ID and verbose mode from NVRAM - **/ - if (nvram) { - switch(nvram->type) { - case SCSI_NCR_TEKRAM_NVRAM: - np->myaddr = nvram->data.Tekram.host_id & 0x0f; - break; - case SCSI_NCR_SYMBIOS_NVRAM: - if (!(nvram->data.Symbios.flags & SYMBIOS_PARITY_ENABLE)) - np->rv_scntl0 &= ~0x0a; - np->myaddr = nvram->data.Symbios.host_id & 0x0f; - if (nvram->data.Symbios.flags & SYMBIOS_VERBOSE_MSGS) - np->verbose += 1; - break; - } - } -#endif /* ** Get SCSI addr of host adapter (set by bios?). */ @@ -3443,9 +3938,7 @@ static int __init ncr_prepare_setting(ncb_p np, ncr_nvram *nvram) ** since a 100% safe algorithm is not possible. */ np->scsi_mode = SMODE_SE; - if (np->features & FE_ULTRA2) - np->scsi_mode = (np->sv_stest4 & SMODE); - else if (np->features & FE_DIFF) { + if (np->features & FE_DIFF) { switch(driver_setup.diff_support) { case 4: /* Trust previous settings if present, then GPIO3 */ if (np->sv_scntl3) { @@ -3454,8 +3947,6 @@ static int __init ncr_prepare_setting(ncb_p np, ncr_nvram *nvram) break; } case 3: /* SYMBIOS controllers report HVD through GPIO3 */ - if (nvram && nvram->type != SCSI_NCR_SYMBIOS_NVRAM) - break; if (INB(nc_gpreg) & 0x08) break; case 2: /* Set HVD unconditionally */ @@ -3478,8 +3969,7 @@ static int __init ncr_prepare_setting(ncb_p np, ncr_nvram *nvram) ** that drive the LED directly. ** Also probe initial setting of GPIO0 as output. */ - if ((driver_setup.led_pin || - (nvram && nvram->type == SCSI_NCR_SYMBIOS_NVRAM)) && + if ((driver_setup.led_pin) && !(np->features & FE_LEDC) && !(np->sv_gpcntl & 0x01)) np->features |= FE_LED0; @@ -3499,51 +3989,25 @@ static int __init ncr_prepare_setting(ncb_p np, ncr_nvram *nvram) /* ** Configure targets according to driver setup. - ** If NVRAM present get targets setup from NVRAM. ** Allow to override sync, wide and NOSCAN from ** boot command line. */ for (i = 0 ; i < MAX_TARGET ; i++) { - tcb_p tp = &np->target[i]; - - tp->usrsync = 255; -#ifdef SCSI_NCR_NVRAM_SUPPORT - if (nvram) { - switch(nvram->type) { - case SCSI_NCR_TEKRAM_NVRAM: - ncr_Tekram_setup_target(np, i, &nvram->data.Tekram); - break; - case SCSI_NCR_SYMBIOS_NVRAM: - ncr_Symbios_setup_target(np, i, &nvram->data.Symbios); - break; - } - if (driver_setup.use_nvram & 0x2) - tp->usrsync = driver_setup.default_sync; - if (driver_setup.use_nvram & 0x4) - tp->usrwide = driver_setup.max_wide; - if (driver_setup.use_nvram & 0x8) - tp->usrflag &= ~UF_NOSCAN; - } - else { -#else - if (1) { -#endif - tp->usrsync = driver_setup.default_sync; - tp->usrwide = driver_setup.max_wide; - tp->usrtags = MAX_TAGS; - if (!driver_setup.disconnection) - np->target[i].usrflag = UF_NODISC; - } + struct tcb *tp = &np->target[i]; + + tp->usrsync = driver_setup.default_sync; + tp->usrwide = driver_setup.max_wide; + tp->usrtags = MAX_TAGS; + tp->period = 0xffff; + if (!driver_setup.disconnection) + np->target[i].usrflag = UF_NODISC; } /* ** Announce all that stuff to user. */ - i = nvram ? nvram->type : 0; - printk(KERN_INFO "%s: %sID %d, Fast-%d%s%s\n", ncr_name(np), - i == SCSI_NCR_SYMBIOS_NVRAM ? "Symbios format NVRAM, " : - (i == SCSI_NCR_TEKRAM_NVRAM ? "Tekram format NVRAM, " : ""), + printk(KERN_INFO "%s: ID %d, Fast-%d%s%s\n", ncr_name(np), np->myaddr, np->minsync < 12 ? 40 : (np->minsync < 25 ? 20 : 10), (np->rv_scntl0 & 0xa) ? ", Parity Checking" : ", NO Parity", @@ -3564,677 +4028,130 @@ static int __init ncr_prepare_setting(ncb_p np, ncr_nvram *nvram) if (bootverbose && np->paddr2) printk (KERN_INFO "%s: on-chip RAM at 0x%lx\n", ncr_name(np), np->paddr2); - - return 0; } -/* -** Host attach and initialisations. +/*========================================================== +** +** +** Done SCSI commands list management. +** +** We donnot enter the scsi_done() callback immediately +** after a command has been seen as completed but we +** insert it into a list which is flushed outside any kind +** of driver critical section. +** This allows to do minimal stuff under interrupt and +** inside critical sections and to also avoid locking up +** on recursive calls to driver entry points under SMP. +** In fact, the only kernel point which is entered by the +** driver with a driver lock set is kmalloc(GFP_ATOMIC) +** that shall not reenter the driver under any circumstances, +** AFAIK. ** -** Allocate host data and ncb structure. -** Request IO region and remap MMIO region. -** Do chip initialization. -** If all is OK, install interrupt handling and -** start the timer daemon. +**========================================================== */ - -struct Scsi_Host * __init -ncr_attach (Scsi_Host_Template *tpnt, int unit, struct ncr_device *device) +static inline void ncr_queue_done_cmd(struct ncb *np, struct scsi_cmnd *cmd) { - struct host_data *host_data; - ncb_p np = 0; - struct Scsi_Host *instance = 0; - u_long flags = 0; - ncr_nvram *nvram = device->nvram; - int i; - -#ifdef SCSI_NCR_PROC_INFO_SUPPORT - tpnt->proc_info = ncr53c8xx_proc_info, -#endif - tpnt->info = ncr53c8xx_info; - tpnt->queuecommand = ncr53c8xx_queue_command; - tpnt->slave_configure = ncr53c8xx_slave_configure; - tpnt->eh_bus_reset_handler = ncr53c8xx_bus_reset; - tpnt->can_queue = SCSI_NCR_CAN_QUEUE; - tpnt->this_id = 7; - tpnt->sg_tablesize = SCSI_NCR_SG_TABLESIZE; - tpnt->cmd_per_lun = SCSI_NCR_CMD_PER_LUN; - tpnt->use_clustering = DISABLE_CLUSTERING; - - if(device->differential) - driver_setup.diff_support = device->differential; - - printk(KERN_INFO "ncr53c%s-%d: rev 0x%x on bus %d device %d function %d irq %d\n", - device->chip.name, unit, device->chip.revision_id, - device->slot.bus, (device->slot.device_fn & 0xf8) >> 3, - device->slot.device_fn & 7, - device->slot.irq); + unmap_scsi_data(np, cmd); + cmd->host_scribble = (char *) np->done_list; + np->done_list = cmd; +} - /* - ** Allocate host_data structure - */ - if (!(instance = scsi_host_alloc(tpnt, sizeof(*host_data)))) - goto attach_error; - host_data = (struct host_data *) instance->hostdata; +static inline void ncr_flush_done_cmds(struct scsi_cmnd *lcmd) +{ + struct scsi_cmnd *cmd; - /* - ** Allocate the host control block. - */ - np = __m_calloc_dma(device->dev, sizeof(struct ncb), "NCB"); - if (!np) - goto attach_error; - NCR_INIT_LOCK_NCB(np); - np->dev = device->dev; - np->p_ncb = vtobus(np); - host_data->ncb = np; + while (lcmd) { + cmd = lcmd; + lcmd = (struct scsi_cmnd *) cmd->host_scribble; + cmd->scsi_done(cmd); + } +} - /* - ** Allocate the default CCB. - */ - np->ccb = (ccb_p) m_calloc_dma(sizeof(struct ccb), "CCB"); - if (!np->ccb) - goto attach_error; +/*========================================================== +** +** +** Prepare the next negotiation message if needed. +** +** Fill in the part of message buffer that contains the +** negotiation and the nego_status field of the CCB. +** Returns the size of the message in bytes. +** +** +**========================================================== +*/ - /* - ** Store input informations in the host data structure. - */ - strlcpy(np->chip_name, device->chip.name, sizeof(np->chip_name)); - np->unit = unit; - np->verbose = driver_setup.verbose; - sprintf(np->inst_name, "ncr53c%s-%d", np->chip_name, np->unit); - np->device_id = device->chip.device_id; - np->revision_id = device->chip.revision_id; - np->bus = device->slot.bus; - np->device_fn = device->slot.device_fn; - np->features = device->chip.features; - np->clock_divn = device->chip.nr_divisor; - np->maxoffs = device->chip.offset_max; - np->maxburst = device->chip.burst_max; - np->myaddr = device->host_id; - /* - ** Allocate SCRIPTS areas. - */ - np->script0 = (struct script *) - m_calloc_dma(sizeof(struct script), "SCRIPT"); - if (!np->script0) - goto attach_error; - np->scripth0 = (struct scripth *) - m_calloc_dma(sizeof(struct scripth), "SCRIPTH"); - if (!np->scripth0) - goto attach_error; +static int ncr_prepare_nego(struct ncb *np, struct ccb *cp, u_char *msgptr) +{ + struct tcb *tp = &np->target[cp->target]; + int msglen = 0; + int nego = 0; + struct scsi_target *starget = tp->starget; - /* - ** Initialize timer structure - ** - */ - init_timer(&np->timer); - np->timer.data = (unsigned long) np; - np->timer.function = ncr53c8xx_timeout; + /* negotiate wide transfers ? */ + if (!tp->widedone) { + if (spi_support_wide(starget)) { + nego = NS_WIDE; + } else + tp->widedone=1; + } - /* - ** Try to map the controller chip to - ** virtual and physical memory. - */ + /* negotiate synchronous transfers? */ + if (!nego && !tp->period) { + if (spi_support_sync(starget)) { + nego = NS_SYNC; + } else { + tp->period =0xffff; + dev_info(&starget->dev, "target did not report SYNC.\n"); + } + } - np->paddr = device->slot.base; - np->paddr2 = (np->features & FE_RAM)? device->slot.base_2 : 0; + switch (nego) { + case NS_SYNC: + msglen += spi_populate_sync_msg(msgptr + msglen, + tp->maxoffs ? tp->minsync : 0, tp->maxoffs); + break; + case NS_WIDE: + msglen += spi_populate_width_msg(msgptr + msglen, tp->usrwide); + break; + } -#ifndef SCSI_NCR_IOMAPPED - if(device->slot.base_v) - np->vaddr = device->slot.base_v; - else - np->vaddr = (unsigned long)ioremap(device->slot.base_c, 128); + cp->nego_status = nego; - if (!np->vaddr) { - printk(KERN_ERR - "%s: can't map memory mapped IO region\n",ncr_name(np)); - goto attach_error; + if (nego) { + tp->nego_cp = cp; + if (DEBUG_FLAGS & DEBUG_NEGO) { + ncr_print_msg(cp, nego == NS_WIDE ? + "wide msgout":"sync_msgout", msgptr); + } } - else - if (bootverbose > 1) - printk(KERN_INFO - "%s: using memory mapped IO at virtual address 0x%lx\n", ncr_name(np), (u_long) np->vaddr); - /* - ** Make the controller's registers available. - ** Now the INB INW INL OUTB OUTW OUTL macros - ** can be used safely. - */ + return msglen; +} - np->reg = (struct ncr_reg*) np->vaddr; -#else - /* - ** Try to map the controller chip into iospace. - */ +/*========================================================== +** +** +** Start execution of a SCSI command. +** This is called from the generic SCSI driver. +** +** +**========================================================== +*/ +static int ncr_queue_command (struct ncb *np, struct scsi_cmnd *cmd) +{ + struct scsi_device *sdev = cmd->device; + struct tcb *tp = &np->target[sdev->id]; + struct lcb *lp = tp->lp[sdev->lun]; + struct ccb *cp; - np->base_io = device->slot.io_port; -#endif /* !defined SCSI_NCR_IOMAPPED */ - -#ifdef SCSI_NCR_NVRAM_SUPPORT - if (nvram) { - switch(nvram->type) { - case SCSI_NCR_SYMBIOS_NVRAM: -#ifdef SCSI_NCR_DEBUG_NVRAM - ncr_display_Symbios_nvram(&nvram->data.Symbios); -#endif - break; - case SCSI_NCR_TEKRAM_NVRAM: -#ifdef SCSI_NCR_DEBUG_NVRAM - ncr_display_Tekram_nvram(&nvram->data.Tekram); -#endif - break; - default: - nvram = 0; -#ifdef SCSI_NCR_DEBUG_NVRAM - printk(KERN_DEBUG "%s: NVRAM: None or invalid data.\n", ncr_name(np)); -#endif - } - } -#endif - - /* - ** Do chip dependent initialization. - */ - (void)ncr_prepare_setting(np, nvram); - - if (np->paddr2 && sizeof(struct script) > 4096) { - np->paddr2 = 0; - printk(KERN_WARNING "%s: script too large, NOT using on chip RAM.\n", - ncr_name(np)); - } - - /* - ** Fill Linux host instance structure - */ - instance->max_channel = 0; - instance->this_id = np->myaddr; - instance->max_id = np->maxwide ? 16 : 8; - instance->max_lun = SCSI_NCR_MAX_LUN; -#ifndef SCSI_NCR_IOMAPPED - instance->base = (unsigned long) np->reg; -#endif - instance->irq = device->slot.irq; - instance->unique_id = device->slot.io_port; - instance->io_port = device->slot.io_port; - instance->n_io_port = 128; - instance->dma_channel = 0; - instance->cmd_per_lun = MAX_TAGS; - instance->can_queue = (MAX_START-4); - scsi_set_device(instance, device->dev); - -#ifdef SCSI_NCR_INTEGRITY_CHECKING - np->check_integrity = 0; - instance->check_integrity = 0; - -#ifdef SCSI_NCR_ENABLE_INTEGRITY_CHECK - if ( !(driver_setup.bus_check & 0x04) ) { - np->check_integrity = 1; - instance->check_integrity = 1; - } -#endif -#endif - /* - ** Patch script to physical addresses - */ - ncr_script_fill (&script0, &scripth0); - - np->scripth = np->scripth0; - np->p_scripth = vtobus(np->scripth); - - np->p_script = (np->paddr2) ? np->paddr2 : vtobus(np->script0); - - ncr_script_copy_and_bind (np, (ncrcmd *) &script0, (ncrcmd *) np->script0, sizeof(struct script)); - ncr_script_copy_and_bind (np, (ncrcmd *) &scripth0, (ncrcmd *) np->scripth0, sizeof(struct scripth)); - np->ccb->p_ccb = vtobus (np->ccb); - - /* - ** Patch the script for LED support. - */ - - if (np->features & FE_LED0) { - np->script0->idle[0] = - cpu_to_scr(SCR_REG_REG(gpreg, SCR_OR, 0x01)); - np->script0->reselected[0] = - cpu_to_scr(SCR_REG_REG(gpreg, SCR_AND, 0xfe)); - np->script0->start[0] = - cpu_to_scr(SCR_REG_REG(gpreg, SCR_AND, 0xfe)); - } - - /* - ** Look for the target control block of this nexus. - ** For i = 0 to 3 - ** JUMP ^ IFTRUE (MASK (i, 3)), @(next_lcb) - */ - for (i = 0 ; i < 4 ; i++) { - np->jump_tcb[i].l_cmd = - cpu_to_scr((SCR_JUMP ^ IFTRUE (MASK (i, 3)))); - np->jump_tcb[i].l_paddr = - cpu_to_scr(NCB_SCRIPTH_PHYS (np, bad_target)); - } - - /* - ** Reset chip. - */ - ncr_chip_reset(np, 100); - - /* - ** Now check the cache handling of the chipset. - */ - - if (ncr_snooptest (np)) { - printk (KERN_ERR "CACHE INCORRECTLY CONFIGURED.\n"); - goto attach_error; - }; - - /* - ** Install the interrupt handler. - */ - - np->irq = device->slot.irq; - - /* - ** Initialize the fixed part of the default ccb. - */ - ncr_init_ccb(np, np->ccb); - - /* - ** After SCSI devices have been opened, we cannot - ** reset the bus safely, so we do it here. - ** Interrupt handler does the real work. - ** Process the reset exception, - ** if interrupts are not enabled yet. - ** Then enable disconnects. - */ - NCR_LOCK_NCB(np, flags); - if (ncr_reset_scsi_bus(np, 0, driver_setup.settle_delay) != 0) { - printk(KERN_ERR "%s: FATAL ERROR: CHECK SCSI BUS - CABLES, TERMINATION, DEVICE POWER etc.!\n", ncr_name(np)); - - NCR_UNLOCK_NCB(np, flags); - goto attach_error; - } - ncr_exception (np); - - np->disc = 1; - - /* - ** The middle-level SCSI driver does not - ** wait for devices to settle. - ** Wait synchronously if more than 2 seconds. - */ - if (driver_setup.settle_delay > 2) { - printk(KERN_INFO "%s: waiting %d seconds for scsi devices to settle...\n", - ncr_name(np), driver_setup.settle_delay); - MDELAY (1000 * driver_setup.settle_delay); - } - - /* - ** Now let the generic SCSI driver - ** look for the SCSI devices on the bus .. - */ - - /* - ** start the timeout daemon - */ - np->lasttime=0; - ncr_timeout (np); - - /* - ** use SIMPLE TAG messages by default - */ -#ifdef SCSI_NCR_ALWAYS_SIMPLE_TAG - np->order = M_SIMPLE_TAG; -#endif - - NCR_UNLOCK_NCB(np, flags); - - return instance; - -attach_error: - if (!instance) return NULL; - printk(KERN_INFO "%s: detaching...\n", ncr_name(np)); - if (!np) - goto unregister; - if (np->scripth0) - m_free_dma(np->scripth0, sizeof(struct scripth), "SCRIPTH"); - if (np->script0) - m_free_dma(np->script0, sizeof(struct script), "SCRIPT"); - if (np->ccb) - m_free_dma(np->ccb, sizeof(struct ccb), "CCB"); - m_free_dma(np, sizeof(struct ncb), "NCB"); - -unregister: - scsi_host_put(instance); - - return NULL; -} - - -/*========================================================== -** -** -** Done SCSI commands list management. -** -** We donnot enter the scsi_done() callback immediately -** after a command has been seen as completed but we -** insert it into a list which is flushed outside any kind -** of driver critical section. -** This allows to do minimal stuff under interrupt and -** inside critical sections and to also avoid locking up -** on recursive calls to driver entry points under SMP. -** In fact, the only kernel point which is entered by the -** driver with a driver lock set is kmalloc(GFP_ATOMIC) -** that shall not reenter the driver under any circumstances, -** AFAIK. -** -**========================================================== -*/ -static inline void ncr_queue_done_cmd(ncb_p np, Scsi_Cmnd *cmd) -{ - unmap_scsi_data(np, cmd); - cmd->host_scribble = (char *) np->done_list; - np->done_list = cmd; -} - -static inline void ncr_flush_done_cmds(Scsi_Cmnd *lcmd) -{ - Scsi_Cmnd *cmd; - - while (lcmd) { - cmd = lcmd; - lcmd = (Scsi_Cmnd *) cmd->host_scribble; - cmd->scsi_done(cmd); - } -} - -/*========================================================== -** -** -** Prepare the next negotiation message for integrity check, -** if needed. -** -** Fill in the part of message buffer that contains the -** negotiation and the nego_status field of the CCB. -** Returns the size of the message in bytes. -** -** -**========================================================== -*/ - -#ifdef SCSI_NCR_INTEGRITY_CHECKING -static int ncr_ic_nego(ncb_p np, ccb_p cp, Scsi_Cmnd *cmd, u_char *msgptr) -{ - tcb_p tp = &np->target[cp->target]; - int msglen = 0; - int nego = 0; - u_char no_increase; - - if (tp->inq_done) { - - if (!tp->ic_maximums_set) { - tp->ic_maximums_set = 1; - - /* check target and host adapter capabilities */ - if ( (tp->inq_byte7 & INQ7_WIDE16) && - np->maxwide && tp->usrwide ) - tp->ic_max_width = 1; - else - tp->ic_max_width = 0; - - if ((tp->inq_byte7 & INQ7_SYNC) && tp->maxoffs) { - tp->ic_min_sync = (tp->minsync < np->minsync) ? - np->minsync : tp->minsync; - } - else - tp->ic_min_sync = 255; - - tp->period = 1; - tp->widedone = 1; - } - - if (DEBUG_FLAGS & DEBUG_IC) { - printk("%s: cmd->ic_nego %d, 1st byte 0x%2X\n", - ncr_name(np), cmd->ic_nego, cmd->cmnd[0]); - } - - /* First command from integrity check routine will request - * a PPR message. Disable. - */ - if ((cmd->ic_nego & NS_PPR) == NS_PPR) - cmd->ic_nego &= ~NS_PPR; - /* Previous command recorded a parity or an initiator - * detected error condition. Force bus to narrow for this - * target. Clear flag. Negotation on request sense. - * Note: kernel forces 2 bus resets :o( but clears itself out. - * Minor bug? in scsi_obsolete.c (ugly) - */ - if (np->check_integ_par) { - printk("%s: Parity Error. Target set to narrow.\n", - ncr_name(np)); - tp->ic_max_width = 0; - tp->widedone = tp->period = 0; - } - - /* In case of a bus reset, ncr_negotiate will reset - * the flags tp->widedone and tp->period to 0, forcing - * a new negotiation. - */ - no_increase = 0; - if (tp->widedone == 0) { - cmd->ic_nego = NS_WIDE; - tp->widedone = 1; - no_increase = 1; - } - else if (tp->period == 0) { - cmd->ic_nego = NS_SYNC; - tp->period = 1; - no_increase = 1; - } - - switch (cmd->ic_nego) { - case NS_WIDE: - /* - ** negotiate wide transfers ? - ** Do NOT negotiate if device only supports - ** narrow. - */ - if (tp->ic_max_width | np->check_integ_par) { - nego = NS_WIDE; - - msgptr[msglen++] = M_EXTENDED; - msgptr[msglen++] = 2; - msgptr[msglen++] = M_X_WIDE_REQ; - msgptr[msglen++] = cmd->ic_nego_width & tp->ic_max_width; - } - else - cmd->ic_nego_width &= tp->ic_max_width; - - break; - - case NS_SYNC: - /* - ** negotiate synchronous transfers? - ** Target must support sync transfers. - ** - ** If period becomes longer than max, reset to async - */ - - if (tp->inq_byte7 & INQ7_SYNC) { - - nego = NS_SYNC; - - msgptr[msglen++] = M_EXTENDED; - msgptr[msglen++] = 3; - msgptr[msglen++] = M_X_SYNC_REQ; - - switch (cmd->ic_nego_sync) { - case 2: /* increase the period */ - if (!no_increase) { - if (tp->ic_min_sync <= 0x0A) - tp->ic_min_sync = 0x0C; - else if (tp->ic_min_sync <= 0x0C) - tp->ic_min_sync = 0x19; - else if (tp->ic_min_sync <= 0x19) - tp->ic_min_sync *= 2; - else { - tp->ic_min_sync = 255; - cmd->ic_nego_sync = 0; - tp->maxoffs = 0; - } - } - msgptr[msglen++] = tp->maxoffs?tp->ic_min_sync:0; - msgptr[msglen++] = tp->maxoffs; - break; - - case 1: /* nego. to maximum */ - msgptr[msglen++] = tp->maxoffs?tp->ic_min_sync:0; - msgptr[msglen++] = tp->maxoffs; - break; - - case 0: /* nego to async */ - default: - msgptr[msglen++] = 0; - msgptr[msglen++] = 0; - break; - }; - } - else - cmd->ic_nego_sync = 0; - break; - - case NS_NOCHANGE: - default: - break; - }; - }; - - cp->nego_status = nego; - np->check_integ_par = 0; - - if (nego) { - tp->nego_cp = cp; - if (DEBUG_FLAGS & DEBUG_NEGO) { - ncr_print_msg(cp, nego == NS_WIDE ? - "wide/narrow msgout": "sync/async msgout", msgptr); - }; - }; - - return msglen; -} -#endif /* SCSI_NCR_INTEGRITY_CHECKING */ - -/*========================================================== -** -** -** Prepare the next negotiation message if needed. -** -** Fill in the part of message buffer that contains the -** negotiation and the nego_status field of the CCB. -** Returns the size of the message in bytes. -** -** -**========================================================== -*/ - - -static int ncr_prepare_nego(ncb_p np, ccb_p cp, u_char *msgptr) -{ - tcb_p tp = &np->target[cp->target]; - int msglen = 0; - int nego = 0; - - if (tp->inq_done) { - - /* - ** negotiate wide transfers ? - */ - - if (!tp->widedone) { - if (tp->inq_byte7 & INQ7_WIDE16) { - nego = NS_WIDE; -#ifdef SCSI_NCR_INTEGRITY_CHECKING - if (tp->ic_done) - tp->usrwide &= tp->ic_max_width; -#endif - } else - tp->widedone=1; - - }; - - /* - ** negotiate synchronous transfers? - */ - - if (!nego && !tp->period) { - if (tp->inq_byte7 & INQ7_SYNC) { - nego = NS_SYNC; -#ifdef SCSI_NCR_INTEGRITY_CHECKING - if ((tp->ic_done) && - (tp->minsync < tp->ic_min_sync)) - tp->minsync = tp->ic_min_sync; -#endif - } else { - tp->period =0xffff; - PRINT_TARGET(np, cp->target); - printk ("target did not report SYNC.\n"); - }; - }; - }; - - switch (nego) { - case NS_SYNC: - msgptr[msglen++] = M_EXTENDED; - msgptr[msglen++] = 3; - msgptr[msglen++] = M_X_SYNC_REQ; - msgptr[msglen++] = tp->maxoffs ? tp->minsync : 0; - msgptr[msglen++] = tp->maxoffs; - break; - case NS_WIDE: - msgptr[msglen++] = M_EXTENDED; - msgptr[msglen++] = 2; - msgptr[msglen++] = M_X_WIDE_REQ; - msgptr[msglen++] = tp->usrwide; - break; - }; - - cp->nego_status = nego; - - if (nego) { - tp->nego_cp = cp; - if (DEBUG_FLAGS & DEBUG_NEGO) { - ncr_print_msg(cp, nego == NS_WIDE ? - "wide msgout":"sync_msgout", msgptr); - }; - }; - - return msglen; -} - - - -/*========================================================== -** -** -** Start execution of a SCSI command. -** This is called from the generic SCSI driver. -** -** -**========================================================== -*/ -static int ncr_queue_command (ncb_p np, Scsi_Cmnd *cmd) -{ -/* Scsi_Device *device = cmd->device; */ - tcb_p tp = &np->target[cmd->device->id]; - lcb_p lp = tp->lp[cmd->device->lun]; - ccb_p cp; - - int segments; - u_char idmsg, *msgptr; - u_int msglen; - int direction; - u32 lastp, goalp; + int segments; + u_char idmsg, *msgptr; + u32 msglen; + int direction; + u32 lastp, goalp; /*--------------------------------------------- ** @@ -4242,11 +4159,11 @@ static int ncr_queue_command (ncb_p np, Scsi_Cmnd *cmd) ** **--------------------------------------------- */ - if ((cmd->device->id == np->myaddr ) || - (cmd->device->id >= MAX_TARGET) || - (cmd->device->lun >= MAX_LUN )) { + if ((sdev->id == np->myaddr ) || + (sdev->id >= MAX_TARGET) || + (sdev->lun >= MAX_LUN )) { return(DID_BAD_TARGET); - } + } /*--------------------------------------------- ** @@ -4264,8 +4181,7 @@ static int ncr_queue_command (ncb_p np, Scsi_Cmnd *cmd) } if (DEBUG_FLAGS & DEBUG_TINY) { - PRINT_ADDR(cmd); - printk ("CMD=%x ", cmd->cmnd[0]); + PRINT_ADDR(cmd, "CMD=%x ", cmd->cmnd[0]); } /*--------------------------------------------------- @@ -4279,12 +4195,12 @@ static int ncr_queue_command (ncb_p np, Scsi_Cmnd *cmd) **---------------------------------------------------- */ if (np->settle_time && cmd->timeout_per_command >= HZ) { - u_long tlimit = ktime_get(cmd->timeout_per_command - HZ); - if (ktime_dif(np->settle_time, tlimit) > 0) + u_long tlimit = jiffies + cmd->timeout_per_command - HZ; + if (time_after(np->settle_time, tlimit)) np->settle_time = tlimit; } - if (np->settle_time || !(cp=ncr_get_ccb (np, cmd->device->id, cmd->device->lun))) { + if (np->settle_time || !(cp=ncr_get_ccb (np, cmd))) { insert_into_waiting_list(np, cmd); return(DID_OK); } @@ -4297,7 +4213,7 @@ static int ncr_queue_command (ncb_p np, Scsi_Cmnd *cmd) **---------------------------------------------------- */ - idmsg = M_IDENTIFY | cmd->device->lun; + idmsg = IDENTIFY(0, sdev->lun); if (cp ->tag != NO_TAG || (cp != np->ccb && np->disc && !(tp->usrflag & UF_NODISC))) @@ -4314,15 +4230,15 @@ static int ncr_queue_command (ncb_p np, Scsi_Cmnd *cmd) ** Force ordered tag if necessary to avoid timeouts ** and to preserve interactivity. */ - if (lp && ktime_exp(lp->tags_stime)) { + if (lp && time_after(jiffies, lp->tags_stime)) { if (lp->tags_smap) { - order = M_ORDERED_TAG; + order = ORDERED_QUEUE_TAG; if ((DEBUG_FLAGS & DEBUG_TAGS)||bootverbose>2){ - PRINT_ADDR(cmd); - printk("ordered tag forced.\n"); + PRINT_ADDR(cmd, + "ordered tag forced.\n"); } } - lp->tags_stime = ktime_get(3*HZ); + lp->tags_stime = jiffies + 3*HZ; lp->tags_smap = lp->tags_umap; } @@ -4334,10 +4250,10 @@ static int ncr_queue_command (ncb_p np, Scsi_Cmnd *cmd) case 0x08: /* READ_SMALL (6) */ case 0x28: /* READ_BIG (10) */ case 0xa8: /* READ_HUGE (12) */ - order = M_SIMPLE_TAG; + order = SIMPLE_QUEUE_TAG; break; default: - order = M_ORDERED_TAG; + order = ORDERED_QUEUE_TAG; } } msgptr[msglen++] = order; @@ -4356,9 +4272,9 @@ static int ncr_queue_command (ncb_p np, Scsi_Cmnd *cmd) **---------------------------------------------------- */ - direction = scsi_data_direction(cmd); - if (direction != SCSI_DATA_NONE) { - segments = ncr_scatter (np, cp, cp->cmd); + direction = cmd->sc_data_direction; + if (direction != DMA_NONE) { + segments = ncr_scatter(np, cp, cp->cmd); if (segments < 0) { ncr_free_ccb(np, cp); return(DID_ERROR); @@ -4380,72 +4296,9 @@ static int ncr_queue_command (ncb_p np, Scsi_Cmnd *cmd) cp->nego_status = 0; -#ifdef SCSI_NCR_INTEGRITY_CHECKING - if ((np->check_integrity && tp->ic_done) || !np->check_integrity) { - if ((!tp->widedone || !tp->period) && !tp->nego_cp && lp) { - msglen += ncr_prepare_nego (np, cp, msgptr + msglen); - } - } - else if (np->check_integrity && (cmd->ic_in_progress)) { - msglen += ncr_ic_nego (np, cp, cmd, msgptr + msglen); - } - else if (np->check_integrity && cmd->ic_complete) { - /* - * Midlayer signal to the driver that all of the scsi commands - * for the integrity check have completed. Save the negotiated - * parameters (extracted from sval and wval). - */ - - { - u_char idiv; - idiv = (tp->wval>>4) & 0x07; - if ((tp->sval&0x1f) && idiv ) - tp->period = (((tp->sval>>5)+4) - *div_10M[idiv-1])/np->clock_khz; - else - tp->period = 0xffff; - } - /* - * tp->period contains 10 times the transfer period, - * which itself is 4 * the requested negotiation rate. - */ - if (tp->period <= 250) tp->ic_min_sync = 10; - else if (tp->period <= 303) tp->ic_min_sync = 11; - else if (tp->period <= 500) tp->ic_min_sync = 12; - else - tp->ic_min_sync = (tp->period + 40 - 1) / 40; - - - /* - * Negotiation for this target it complete. - */ - tp->ic_max_width = (tp->wval & EWS) ? 1: 0; - tp->ic_done = 1; - tp->widedone = 1; - - printk("%s: Integrity Check Complete: \n", ncr_name(np)); - - printk("%s: %s %s SCSI", ncr_name(np), - (tp->sval&0x1f)?"SYNC":"ASYNC", - tp->ic_max_width?"WIDE":"NARROW"); - - if (tp->sval&0x1f) { - u_long mbs = 10000 * (tp->ic_max_width + 1); - - printk(" %d.%d MB/s", - (int) (mbs / tp->period), (int) (mbs % tp->period)); - - printk(" (%d ns, %d offset)\n", - tp->period/10, tp->sval&0x1f); - } - else - printk(" %d MB/s. \n ", (tp->ic_max_width+1)*5); - } -#else if ((!tp->widedone || !tp->period) && !tp->nego_cp && lp) { msglen += ncr_prepare_nego (np, cp, msgptr + msglen); } -#endif /* SCSI_NCR_INTEGRITY_CHECKING */ /*---------------------------------------------------- ** @@ -4454,17 +4307,17 @@ static int ncr_queue_command (ncb_p np, Scsi_Cmnd *cmd) **---------------------------------------------------- */ if (!cp->data_len) - direction = SCSI_DATA_NONE; + direction = DMA_NONE; /* - ** If data direction is UNKNOWN, speculate DATA_READ - ** but prepare alternate pointers for WRITE in case + ** If data direction is BIDIRECTIONAL, speculate FROM_DEVICE + ** but prepare alternate pointers for TO_DEVICE in case ** of our speculation will be just wrong. ** SCRIPTS will swap values if needed. */ switch(direction) { - case SCSI_DATA_UNKNOWN: - case SCSI_DATA_WRITE: + case DMA_BIDIRECTIONAL: + case DMA_TO_DEVICE: goalp = NCB_SCRIPT_PHYS (np, data_out2) + 8; if (segments <= MAX_SCATTERL) lastp = goalp - 8 - (segments * 16); @@ -4472,12 +4325,12 @@ static int ncr_queue_command (ncb_p np, Scsi_Cmnd *cmd) lastp = NCB_SCRIPTH_PHYS (np, hdata_out2); lastp -= (segments - MAX_SCATTERL) * 16; } - if (direction != SCSI_DATA_UNKNOWN) + if (direction != DMA_BIDIRECTIONAL) break; cp->phys.header.wgoalp = cpu_to_scr(goalp); cp->phys.header.wlastp = cpu_to_scr(lastp); /* fall through */ - case SCSI_DATA_READ: + case DMA_FROM_DEVICE: goalp = NCB_SCRIPT_PHYS (np, data_in2) + 8; if (segments <= MAX_SCATTERL) lastp = goalp - 8 - (segments * 16); @@ -4487,7 +4340,7 @@ static int ncr_queue_command (ncb_p np, Scsi_Cmnd *cmd) } break; default: - case SCSI_DATA_NONE: + case DMA_NONE: lastp = goalp = NCB_SCRIPT_PHYS (np, no_data); break; } @@ -4499,7 +4352,7 @@ static int ncr_queue_command (ncb_p np, Scsi_Cmnd *cmd) cp->phys.header.lastp = cpu_to_scr(lastp); cp->phys.header.goalp = cpu_to_scr(goalp); - if (direction == SCSI_DATA_UNKNOWN) + if (direction == DMA_BIDIRECTIONAL) cp->phys.header.savep = cpu_to_scr(NCB_SCRIPTH_PHYS (np, data_io)); else @@ -4530,7 +4383,7 @@ static int ncr_queue_command (ncb_p np, Scsi_Cmnd *cmd) /* ** select */ - cp->phys.select.sel_id = cmd->device->id; + cp->phys.select.sel_id = sdev_id(sdev); cp->phys.select.sel_scntl3 = tp->wval; cp->phys.select.sel_sxfer = tp->sval; /* @@ -4542,14 +4395,14 @@ static int ncr_queue_command (ncb_p np, Scsi_Cmnd *cmd) /* ** command */ - memcpy(cp->cdb_buf, cmd->cmnd, MIN(cmd->cmd_len, sizeof(cp->cdb_buf))); + memcpy(cp->cdb_buf, cmd->cmnd, min_t(int, cmd->cmd_len, sizeof(cp->cdb_buf))); cp->phys.cmd.addr = cpu_to_scr(CCB_PHYS (cp, cdb_buf[0])); cp->phys.cmd.size = cpu_to_scr(cmd->cmd_len); /* ** status */ - cp->actualquirks = tp->quirks; + cp->actualquirks = 0; cp->host_status = cp->nego_status ? HS_NEGOTIATE : HS_BUSY; cp->scsi_status = S_ILLEGAL; cp->parity_status = 0; @@ -4567,9 +4420,7 @@ static int ncr_queue_command (ncb_p np, Scsi_Cmnd *cmd) **---------------------------------------------------- */ - /* - ** activate this job. - */ + /* activate this job. */ cp->magic = CCB_MAGIC; /* @@ -4582,11 +4433,9 @@ static int ncr_queue_command (ncb_p np, Scsi_Cmnd *cmd) else ncr_put_start_queue(np, cp); - /* - ** Command is successfully queued. - */ + /* Command is successfully queued. */ - return(DID_OK); + return DID_OK; } @@ -4600,30 +4449,30 @@ static int ncr_queue_command (ncb_p np, Scsi_Cmnd *cmd) **========================================================== */ -static void ncr_start_next_ccb(ncb_p np, lcb_p lp, int maxn) +static void ncr_start_next_ccb(struct ncb *np, struct lcb *lp, int maxn) { - XPT_QUEHEAD *qp; - ccb_p cp; + struct list_head *qp; + struct ccb *cp; if (lp->held_ccb) return; while (maxn-- && lp->queuedccbs < lp->queuedepth) { - qp = xpt_remque_head(&lp->wait_ccbq); + qp = ncr_list_pop(&lp->wait_ccbq); if (!qp) break; ++lp->queuedccbs; - cp = xpt_que_entry(qp, struct ccb, link_ccbq); - xpt_insque_tail(qp, &lp->busy_ccbq); + cp = list_entry(qp, struct ccb, link_ccbq); + list_add_tail(qp, &lp->busy_ccbq); lp->jump_ccb[cp->tag == NO_TAG ? 0 : cp->tag] = cpu_to_scr(CCB_PHYS (cp, restart)); ncr_put_start_queue(np, cp); } } -static void ncr_put_start_queue(ncb_p np, ccb_p cp) +static void ncr_put_start_queue(struct ncb *np, struct ccb *cp) { - u_short qidx; + u16 qidx; /* ** insert into start queue. @@ -4651,32 +4500,13 @@ static void ncr_put_start_queue(ncb_p np, ccb_p cp) OUTB (nc_istat, SIGP); } - -/*========================================================== -** -** -** Start reset process. -** If reset in progress do nothing. -** The interrupt handler will reinitialize the chip. -** The timeout handler will wait for settle_time before -** clearing it and so resuming command processing. -** -** -**========================================================== -*/ -static void ncr_start_reset(ncb_p np) -{ - if (!np->settle_time) { - (void) ncr_reset_scsi_bus(np, 1, driver_setup.settle_delay); - } - } - -static int ncr_reset_scsi_bus(ncb_p np, int enab_int, int settle_delay) + +static int ncr_reset_scsi_bus(struct ncb *np, int enab_int, int settle_delay) { u32 term; int retv = 0; - np->settle_time = ktime_get(settle_delay * HZ); + np->settle_time = jiffies + settle_delay * HZ; if (bootverbose > 1) printk("%s: resetting, " @@ -4684,7 +4514,7 @@ static int ncr_reset_scsi_bus(ncb_p np, int enab_int, int settle_delay) ncr_name(np), settle_delay); ncr_chip_reset(np, 100); - UDELAY (2000); /* The 895 needs time for the bus mode to settle */ + udelay(2000); /* The 895 needs time for the bus mode to settle */ if (enab_int) OUTW (nc_sien, RST); /* @@ -4692,10 +4522,8 @@ static int ncr_reset_scsi_bus(ncb_p np, int enab_int, int settle_delay) ** properly set IRQ mode, prior to resetting the bus. */ OUTB (nc_stest3, TE); - if (np->device_id != PSEUDO_720_ID) - OUTB (nc_dcntl, (np->rv_dcntl & IRQM)); OUTB (nc_scntl1, CRST); - UDELAY (200); + udelay(200); if (!driver_setup.bus_check) goto out; @@ -4732,6 +4560,20 @@ out: return retv; } +/* + * Start reset process. + * If reset in progress do nothing. + * The interrupt handler will reinitialize the chip. + * The timeout handler will wait for settle_time before + * clearing it and so resuming command processing. + */ +static void ncr_start_reset(struct ncb *np) +{ + if (!np->settle_time) { + ncr_reset_scsi_bus(np, 1, driver_setup.settle_delay); + } +} + /*========================================================== ** ** @@ -4741,10 +4583,10 @@ out: ** **========================================================== */ -static int ncr_reset_bus (ncb_p np, Scsi_Cmnd *cmd, int sync_reset) +static int ncr_reset_bus (struct ncb *np, struct scsi_cmnd *cmd, int sync_reset) { -/* Scsi_Device *device = cmd->device; */ - ccb_p cp; +/* struct scsi_device *device = cmd->device; */ + struct ccb *cp; int found; /* @@ -4800,6 +4642,7 @@ static int ncr_reset_bus (ncb_p np, Scsi_Cmnd *cmd, int sync_reset) return SUCCESS; } +#if 0 /* unused and broken.. */ /*========================================================== ** ** @@ -4809,10 +4652,10 @@ static int ncr_reset_bus (ncb_p np, Scsi_Cmnd *cmd, int sync_reset) ** **========================================================== */ -static int ncr_abort_command (ncb_p np, Scsi_Cmnd *cmd) +static int ncr_abort_command (struct ncb *np, struct scsi_cmnd *cmd) { -/* Scsi_Device *device = cmd->device; */ - ccb_p cp; +/* struct scsi_device *device = cmd->device; */ + struct ccb *cp; int found; int retv; @@ -4880,23 +4723,13 @@ static int ncr_abort_command (ncb_p np, Scsi_Cmnd *cmd) return retv; } +#endif -/*========================================================== -** -** Linux release module stuff. -** -** Called before unloading the module -** Detach the host. -** We have to free resources and halt the NCR chip -** -**========================================================== -*/ - -static int ncr_detach(ncb_p np) +static void ncr_detach(struct ncb *np) { - ccb_p cp; - tcb_p tp; - lcb_p lp; + struct ccb *cp; + struct tcb *tp; + struct lcb *lp; int target, lun; int i; char inst_name[16]; @@ -4915,7 +4748,8 @@ static int ncr_detach(ncb_p np) printk("%s: stopping the timer\n", ncr_name(np)); #endif np->release_stage = 1; - for (i = 50 ; i && np->release_stage != 2 ; i--) MDELAY (100); + for (i = 50 ; i && np->release_stage != 2 ; i--) + mdelay(100); if (np->release_stage != 2) printk("%s: the timer seems to be already stopped\n", ncr_name(np)); else np->release_stage = 2; @@ -4965,9 +4799,7 @@ static int ncr_detach(ncb_p np) m_free_dma(cp, sizeof(*cp), "CCB"); } - /* - ** Free allocated tp(s) - */ + /* Free allocated tp(s) */ for (target = 0; target < MAX_TARGET ; target++) { tp=&np->target[target]; @@ -4993,8 +4825,6 @@ static int ncr_detach(ncb_p np) m_free_dma(np, sizeof(struct ncb), "NCB"); printk("%s: host resources successfully released\n", inst_name); - - return 1; } /*========================================================== @@ -5007,11 +4837,11 @@ static int ncr_detach(ncb_p np) **========================================================== */ -void ncr_complete (ncb_p np, ccb_p cp) +void ncr_complete (struct ncb *np, struct ccb *cp) { - Scsi_Cmnd *cmd; - tcb_p tp; - lcb_p lp; + struct scsi_cmnd *cmd; + struct tcb *tp; + struct lcb *lp; /* ** Sanity check @@ -5044,7 +4874,7 @@ void ncr_complete (ncb_p np, ccb_p cp) */ if (cp == tp->nego_cp) - tp->nego_cp = 0; + tp->nego_cp = NULL; /* ** If auto-sense performed, change scsi status. @@ -5060,9 +4890,8 @@ void ncr_complete (ncb_p np, ccb_p cp) if (lp && lp->held_ccb) { if (cp == lp->held_ccb) { - xpt_que_splice(&lp->skip_ccbq, &lp->wait_ccbq); - xpt_que_init(&lp->skip_ccbq); - lp->held_ccb = 0; + list_splice_init(&lp->skip_ccbq, &lp->wait_ccbq); + lp->held_ccb = NULL; } } @@ -5071,8 +4900,7 @@ void ncr_complete (ncb_p np, ccb_p cp) */ if (cp->parity_status > 1) { - PRINT_ADDR(cmd); - printk ("%d parity error(s).\n",cp->parity_status); + PRINT_ADDR(cmd, "%d parity error(s).\n",cp->parity_status); } /* @@ -5080,16 +4908,16 @@ void ncr_complete (ncb_p np, ccb_p cp) */ if (cp->xerr_status != XE_OK) { - PRINT_ADDR(cmd); switch (cp->xerr_status) { case XE_EXTRA_DATA: - printk ("extraneous data discarded.\n"); + PRINT_ADDR(cmd, "extraneous data discarded.\n"); break; case XE_BAD_PHASE: - printk ("invalid scsi phase (4/5).\n"); + PRINT_ADDR(cmd, "invalid scsi phase (4/5).\n"); break; default: - printk ("extended error %d.\n", cp->xerr_status); + PRINT_ADDR(cmd, "extended error %d.\n", + cp->xerr_status); break; } if (cp->host_status==HS_COMPLETE) @@ -5101,9 +4929,9 @@ void ncr_complete (ncb_p np, ccb_p cp) */ if (DEBUG_FLAGS & (DEBUG_RESULT|DEBUG_TINY)) { if (cp->host_status!=HS_COMPLETE || cp->scsi_status!=S_GOOD) { - PRINT_ADDR(cmd); - printk ("ERROR: cmd=%x host_status=%x scsi_status=%x\n", - cmd->cmnd[0], cp->host_status, cp->scsi_status); + PRINT_ADDR(cmd, "ERROR: cmd=%x host_status=%x " + "scsi_status=%x\n", cmd->cmnd[0], + cp->host_status, cp->scsi_status); } } @@ -5113,11 +4941,11 @@ void ncr_complete (ncb_p np, ccb_p cp) if ( (cp->host_status == HS_COMPLETE) && (cp->scsi_status == S_GOOD || cp->scsi_status == S_COND_MET)) { - /* - ** All went well (GOOD status). - ** CONDITION MET status is returned on - ** `Pre-Fetch' or `Search data' success. - */ + /* + * All went well (GOOD status). + * CONDITION MET status is returned on + * `Pre-Fetch' or `Search data' success. + */ cmd->result = ScsiResult(DID_OK, cp->scsi_status); /* @@ -5133,19 +4961,6 @@ void ncr_complete (ncb_p np, ccb_p cp) if (!lp) ncr_alloc_lcb (np, cmd->device->id, cmd->device->lun); - /* - ** On standard INQUIRY response (EVPD and CmDt - ** not set), setup logical unit according to - ** announced capabilities (we need the 1rst 7 bytes). - */ - if (cmd->cmnd[0] == 0x12 && !(cmd->cmnd[1] & 0x3) && - cmd->cmnd[4] >= 7 && !cmd->use_sg) { - sync_scsi_data_for_cpu(np, cmd); /* SYNC the data */ - ncr_setup_lcb (np, cmd->device->id, cmd->device->lun, - (char *) cmd->request_buffer); - sync_scsi_data_for_device(np, cmd); /* SYNC the data */ - } - tp->bytes += cp->data_len; tp->transfers ++; @@ -5158,7 +4973,7 @@ void ncr_complete (ncb_p np, ccb_p cp) if (lp->num_good >= 1000) { lp->num_good = 0; ++lp->numtags; - ncr_setup_tags (np, cmd->device->id, cmd->device->lun); + ncr_setup_tags (np, cmd->device); } } } else if ((cp->host_status == HS_COMPLETE) @@ -5172,13 +4987,12 @@ void ncr_complete (ncb_p np, ccb_p cp) ** Copy back sense data to caller's buffer. */ memcpy(cmd->sense_buffer, cp->sense_buf, - MIN(sizeof(cmd->sense_buffer), sizeof(cp->sense_buf))); + min(sizeof(cmd->sense_buffer), sizeof(cp->sense_buf))); if (DEBUG_FLAGS & (DEBUG_RESULT|DEBUG_TINY)) { u_char * p = (u_char*) & cmd->sense_buffer; int i; - PRINT_ADDR(cmd); - printk ("sense data:"); + PRINT_ADDR(cmd, "sense data:"); for (i=0; i<14; i++) printk (" %x", *p++); printk (".\n"); } @@ -5225,8 +5039,7 @@ void ncr_complete (ncb_p np, ccb_p cp) /* ** Other protocol messes */ - PRINT_ADDR(cmd); - printk ("COMMAND FAILED (%x %x) @%p.\n", + PRINT_ADDR(cmd, "COMMAND FAILED (%x %x) @%p.\n", cp->host_status, cp->scsi_status, cp); cmd->result = ScsiResult(DID_ERROR, cp->scsi_status); @@ -5239,8 +5052,7 @@ void ncr_complete (ncb_p np, ccb_p cp) if (tp->usrflag & UF_TRACE) { u_char * p; int i; - PRINT_ADDR(cmd); - printk (" CMD:"); + PRINT_ADDR(cmd, " CMD:"); p = (u_char*) &cmd->cmnd[0]; for (i=0; icmd_len; i++) printk (" %x", *p++); @@ -5272,7 +5084,7 @@ void ncr_complete (ncb_p np, ccb_p cp) ** requeue awaiting scsi commands for this lun. */ if (lp && lp->queuedccbs < lp->queuedepth && - !xpt_que_empty(&lp->wait_ccbq)) + !list_empty(&lp->wait_ccbq)) ncr_start_next_ccb(np, lp, 2); /* @@ -5298,19 +5110,18 @@ void ncr_complete (ncb_p np, ccb_p cp) /* ** This CCB has been skipped by the NCR. -** Queue it in the correponding unit queue. +** Queue it in the corresponding unit queue. */ -static void ncr_ccb_skipped(ncb_p np, ccb_p cp) +static void ncr_ccb_skipped(struct ncb *np, struct ccb *cp) { - tcb_p tp = &np->target[cp->target]; - lcb_p lp = tp->lp[cp->lun]; + struct tcb *tp = &np->target[cp->target]; + struct lcb *lp = tp->lp[cp->lun]; if (lp && cp != np->ccb) { cp->host_status &= ~HS_SKIPMASK; cp->start.schedule.l_paddr = cpu_to_scr(NCB_SCRIPT_PHYS (np, select)); - xpt_remque(&cp->link_ccbq); - xpt_insque_tail(&cp->link_ccbq, &lp->skip_ccbq); + list_move_tail(&cp->link_ccbq, &lp->skip_ccbq); if (cp->queued) { --lp->queuedccbs; } @@ -5325,9 +5136,9 @@ static void ncr_ccb_skipped(ncb_p np, ccb_p cp) ** The NCR has completed CCBs. ** Look at the DONE QUEUE if enabled, otherwise scan all CCBs */ -void ncr_wakeup_done (ncb_p np) +void ncr_wakeup_done (struct ncb *np) { - ccb_p cp; + struct ccb *cp; #ifdef SCSI_NCR_CCB_DONE_SUPPORT int i, j; @@ -5341,7 +5152,7 @@ void ncr_wakeup_done (ncb_p np) if (!CCB_DONE_VALID(cp)) break; - np->ccb_done[j] = (ccb_p) CCB_DONE_EMPTY; + np->ccb_done[j] = (struct ccb *)CCB_DONE_EMPTY; np->scripth->done_queue[5*j + 4] = cpu_to_scr(NCB_SCRIPT_PHYS (np, done_plug)); MEMORY_BARRIER(); @@ -5371,9 +5182,9 @@ void ncr_wakeup_done (ncb_p np) /* ** Complete all active CCBs. */ -void ncr_wakeup (ncb_p np, u_long code) +void ncr_wakeup (struct ncb *np, u_long code) { - ccb_p cp = np->ccb; + struct ccb *cp = np->ccb; while (cp) { if (cp->host_status != HS_IDLE) { @@ -5392,10 +5203,10 @@ void ncr_wakeup (ncb_p np, u_long code) * at least. EA (dcntl bit 5) isn't set here as it is set once only in * the _detect function. */ -static void ncr_chip_reset(ncb_p np, int delay) +static void ncr_chip_reset(struct ncb *np, int delay) { OUTB (nc_istat, SRST); - UDELAY (delay); + udelay(delay); OUTB (nc_istat, 0 ); if (np->features & FE_EHP) @@ -5414,7 +5225,7 @@ static void ncr_chip_reset(ncb_p np, int delay) **========================================================== */ -void ncr_init (ncb_p np, int reset, char * msg, u_long code) +void ncr_init (struct ncb *np, int reset, char * msg, u_long code) { int i; @@ -5424,7 +5235,7 @@ void ncr_init (ncb_p np, int reset, char * msg, u_long code) if (reset) { OUTB (nc_istat, SRST); - UDELAY (100); + udelay(100); } else { OUTB (nc_stest3, TE|CSF); @@ -5456,7 +5267,7 @@ void ncr_init (ncb_p np, int reset, char * msg, u_long code) ** Clear Done Queue */ for (i = 0; i < MAX_DONE; i++) { - np->ccb_done[i] = (ccb_p) CCB_DONE_EMPTY; + np->ccb_done[i] = (struct ccb *)CCB_DONE_EMPTY; np->scripth0->done_queue[5*i + 4] = cpu_to_scr(NCB_SCRIPT_PHYS (np, done_end)); } @@ -5527,24 +5338,6 @@ void ncr_init (ncb_p np, int reset, char * msg, u_long code) OUTW (nc_sien , STO|HTH|MA|SGE|UDC|RST|PAR); OUTB (nc_dien , MDPE|BF|ABRT|SSI|SIR|IID); - /* - ** For 895/6 enable SBMC interrupt and save current SCSI bus mode. - */ - if (np->features & FE_ULTRA2) { - OUTONW (nc_sien, SBMC); - np->scsi_mode = INB (nc_stest4) & SMODE; - } - - /* - ** DEL 441 - 53C876 Rev 5 - Part Number 609-0392787/2788 - ITEM 2. - ** Disable overlapped arbitration. - ** All 896 chips are also affected by this errata. - */ - if (np->device_id == PCI_DEVICE_ID_NCR_53C875) - OUTB (nc_ctest0, (1<<5)); - else if (np->device_id == PCI_DEVICE_ID_NCR_53C896) - OUTB (nc_ccntl0, DPR); - /* ** Fill in target structure. ** Reinitialize usrsync. @@ -5553,7 +5346,7 @@ void ncr_init (ncb_p np, int reset, char * msg, u_long code) */ for (i=0;itarget[i]; + struct tcb *tp = &np->target[i]; tp->sval = 0; tp->wval = np->rv_scntl3; @@ -5566,12 +5359,11 @@ void ncr_init (ncb_p np, int reset, char * msg, u_long code) } else tp->usrsync = 255; - }; + } if (tp->usrwide > np->maxwide) tp->usrwide = np->maxwide; - ncr_negotiate (np, tp); } /* @@ -5626,8 +5418,11 @@ static void ncr_negotiate (struct ncb* np, struct tcb* tp) if (minsync > np->maxsync) minsync = 255; + if (tp->maxoffs > np->maxoffs) + tp->maxoffs = np->maxoffs; + tp->minsync = minsync; - tp->maxoffs = (minsync<255 ? np->maxoffs : 0); + tp->maxoffs = (minsync<255 ? tp->maxoffs : 0); /* ** period=0: has to negotiate sync transfer @@ -5651,7 +5446,7 @@ static void ncr_negotiate (struct ncb* np, struct tcb* tp) **========================================================== */ -static void ncr_getsync(ncb_p np, u_char sfac, u_char *fakp, u_char *scntl3p) +static void ncr_getsync(struct ncb *np, u_char sfac, u_char *fakp, u_char *scntl3p) { u_long clk = np->clock_khz; /* SCSI clock frequency in kHz */ int div = np->clock_divn; /* Number of divisors supported */ @@ -5720,10 +5515,10 @@ static void ncr_getsync(ncb_p np, u_char sfac, u_char *fakp, u_char *scntl3p) **========================================================== */ -static void ncr_set_sync_wide_status (ncb_p np, u_char target) +static void ncr_set_sync_wide_status (struct ncb *np, u_char target) { - ccb_p cp; - tcb_p tp = &np->target[target]; + struct ccb *cp; + struct tcb *tp = &np->target[target]; /* ** set actual value and sync_status @@ -5738,14 +5533,14 @@ static void ncr_set_sync_wide_status (ncb_p np, u_char target) */ for (cp = np->ccb; cp; cp = cp->link_ccb) { if (!cp->cmd) continue; - if (cp->cmd->device->id != target) continue; + if (scmd_id(cp->cmd) != target) continue; #if 0 cp->sync_status = tp->sval; cp->wide_status = tp->wval; #endif cp->phys.select.sel_scntl3 = tp->wval; cp->phys.select.sel_sxfer = tp->sval; - }; + } } /*========================================================== @@ -5755,20 +5550,14 @@ static void ncr_set_sync_wide_status (ncb_p np, u_char target) **========================================================== */ -static void ncr_setsync (ncb_p np, ccb_p cp, u_char scntl3, u_char sxfer) +static void ncr_setsync (struct ncb *np, struct ccb *cp, u_char scntl3, u_char sxfer) { - Scsi_Cmnd *cmd; - tcb_p tp; + struct scsi_cmnd *cmd = cp->cmd; + struct tcb *tp; u_char target = INB (nc_sdid) & 0x0f; u_char idiv; - assert (cp && cp->cmd); - if (!cp) return; - - cmd = cp->cmd; - if (!cmd) return; - - assert (target == (cmd->device->id & 0xf)); + BUG_ON(target != (scmd_id(cmd) & 0xf)); tp = &np->target[target]; @@ -5787,40 +5576,19 @@ static void ncr_setsync (ncb_p np, ccb_p cp, u_char scntl3, u_char sxfer) else tp->period = 0xffff; - /* - ** Stop there if sync parameters are unchanged - */ - if (tp->sval == sxfer && tp->wval == scntl3) return; + /* Stop there if sync parameters are unchanged */ + if (tp->sval == sxfer && tp->wval == scntl3) + return; tp->sval = sxfer; tp->wval = scntl3; - /* - ** Bells and whistles ;-) - */ - PRINT_TARGET(np, target); if (sxfer & 0x01f) { - unsigned f10 = 100000 << (tp->widedone ? tp->widedone -1 : 0); - unsigned mb10 = (f10 + tp->period/2) / tp->period; - char *scsi; - - /* - ** Disable extended Sreq/Sack filtering - */ - if (tp->period <= 2000) OUTOFFB (nc_stest2, EXT); - - /* - ** Bells and whistles ;-) - */ - if (tp->period < 500) scsi = "FAST-40"; - else if (tp->period < 1000) scsi = "FAST-20"; - else if (tp->period < 2000) scsi = "FAST-10"; - else scsi = "FAST-5"; - - printk ("%s %sSCSI %d.%d MB/s (%d ns, offset %d)\n", scsi, - tp->widedone > 1 ? "WIDE " : "", - mb10 / 10, mb10 % 10, tp->period / 10, sxfer & 0x1f); - } else - printk ("%sasynchronous.\n", tp->widedone > 1 ? "wide " : ""); + /* Disable extended Sreq/Sack filtering */ + if (tp->period <= 2000) + OUTOFFB(nc_stest2, EXT); + } + + spi_display_xfer_agreement(tp->starget); /* ** set actual value and sync_status @@ -5839,21 +5607,15 @@ static void ncr_setsync (ncb_p np, ccb_p cp, u_char scntl3, u_char sxfer) **========================================================== */ -static void ncr_setwide (ncb_p np, ccb_p cp, u_char wide, u_char ack) +static void ncr_setwide (struct ncb *np, struct ccb *cp, u_char wide, u_char ack) { - Scsi_Cmnd *cmd; - u_short target = INB (nc_sdid) & 0x0f; - tcb_p tp; + struct scsi_cmnd *cmd = cp->cmd; + u16 target = INB (nc_sdid) & 0x0f; + struct tcb *tp; u_char scntl3; u_char sxfer; - assert (cp && cp->cmd); - if (!cp) return; - - cmd = cp->cmd; - if (!cmd) return; - - assert (target == (cmd->device->id & 0xf)); + BUG_ON(target != (scmd_id(cmd) & 0xf)); tp = &np->target[target]; tp->widedone = wide+1; @@ -5872,11 +5634,8 @@ static void ncr_setwide (ncb_p np, ccb_p cp, u_char wide, u_char ack) ** Bells and whistles ;-) */ if (bootverbose >= 2) { - PRINT_TARGET(np, target); - if (scntl3 & EWS) - printk ("WIDE SCSI (16 bit) enabled.\n"); - else - printk ("WIDE SCSI disabled.\n"); + dev_info(&cmd->device->sdev_target->dev, "WIDE SCSI %sabled.\n", + (scntl3 & EWS) ? "en" : "dis"); } /* @@ -5893,16 +5652,17 @@ static void ncr_setwide (ncb_p np, ccb_p cp, u_char wide, u_char ack) **========================================================== */ -static void ncr_setup_tags (ncb_p np, u_char tn, u_char ln) +static void ncr_setup_tags (struct ncb *np, struct scsi_device *sdev) { - tcb_p tp = &np->target[tn]; - lcb_p lp = tp->lp[ln]; + unsigned char tn = sdev->id, ln = sdev->lun; + struct tcb *tp = &np->target[tn]; + struct lcb *lp = tp->lp[ln]; u_char reqtags, maxdepth; /* ** Just in case ... */ - if ((!tp) || (!lp)) + if ((!tp) || (!lp) || !sdev) return; /* @@ -5926,11 +5686,11 @@ static void ncr_setup_tags (ncb_p np, u_char tn, u_char ln) ** only devices capable of tagged commands ** only if enabled by user .. */ - if ((lp->inq_byte7 & INQ7_QUEUE) && lp->numtags > 1) { + if (sdev->tagged_supported && lp->numtags > 1) { reqtags = lp->numtags; } else { reqtags = 1; - }; + } /* ** Update max number of tags @@ -5970,96 +5730,17 @@ static void ncr_setup_tags (ncb_p np, u_char tn, u_char ln) ** Announce change to user. */ if (bootverbose) { - PRINT_LUN(np, tn, ln); if (lp->usetags) { - printk("tagged command queue depth set to %d\n", reqtags); - } - else { - printk("tagged command queueing disabled\n"); + dev_info(&sdev->sdev_gendev, + "tagged command queue depth set to %d\n", + reqtags); + } else { + dev_info(&sdev->sdev_gendev, + "tagged command queueing disabled\n"); } } } -/*---------------------------------------------------- -** -** handle user commands -** -**---------------------------------------------------- -*/ - -#ifdef SCSI_NCR_USER_COMMAND_SUPPORT - -static void ncr_usercmd (ncb_p np) -{ - u_char t; - tcb_p tp; - - switch (np->user.cmd) { - - case 0: return; - - case UC_SETSYNC: - for (t=0; tuser.target>>t)&1)) continue; - tp = &np->target[t]; - tp->usrsync = np->user.data; - ncr_negotiate (np, tp); - }; - break; - - case UC_SETTAGS: - for (t=0; tuser.target>>t)&1)) continue; - np->target[t].usrtags = np->user.data; - for (ln = 0; ln < MAX_LUN; ln++) { - lcb_p lp = np->target[t].lp[ln]; - if (!lp) - continue; - lp->maxtags = lp->numtags = np->user.data; - ncr_setup_tags (np, t, ln); - } - }; - break; - - case UC_SETDEBUG: -#ifdef SCSI_NCR_DEBUG_INFO_SUPPORT - ncr_debug = np->user.data; -#endif - break; - - case UC_SETORDER: - np->order = np->user.data; - break; - - case UC_SETVERBOSE: - np->verbose = np->user.data; - break; - - case UC_SETWIDE: - for (t=0; tuser.target>>t)&1)) continue; - tp = &np->target[t]; - size = np->user.data; - if (size > np->maxwide) size=np->maxwide; - tp->usrwide = size; - ncr_negotiate (np, tp); - }; - break; - - case UC_SETFLAG: - for (t=0; tuser.target>>t)&1)) continue; - tp = &np->target[t]; - tp->usrflag = np->user.data; - }; - break; - } - np->user.cmd=0; -} -#endif - /*========================================================== ** ** @@ -6074,9 +5755,9 @@ static void ncr_usercmd (ncb_p np) **---------------------------------------------------------- */ -static void ncr_timeout (ncb_p np) +static void ncr_timeout (struct ncb *np) { - u_long thistime = ktime_get(0); + u_long thistime = jiffies; /* ** If release process in progress, let's go @@ -6089,7 +5770,7 @@ static void ncr_timeout (ncb_p np) return; } - np->timer.expires = ktime_get(SCSI_NCR_TIMER_INTERVAL); + np->timer.expires = jiffies + SCSI_NCR_TIMER_INTERVAL; add_timer(&np->timer); /* @@ -6162,7 +5843,7 @@ static void ncr_timeout (ncb_p np) **========================================================== */ -static void ncr_log_hard_error(ncb_p np, u_short sist, u_char dstat) +static void ncr_log_hard_error(struct ncb *np, u16 sist, u_char dstat) { u32 dsp; int script_ofs; @@ -6188,7 +5869,7 @@ static void ncr_log_hard_error(ncb_p np, u_short sist, u_char dstat) } else { script_ofs = dsp; script_size = 0; - script_base = 0; + script_base = NULL; script_name = "mem"; } @@ -6204,10 +5885,10 @@ static void ncr_log_hard_error(ncb_p np, u_short sist, u_char dstat) scr_to_cpu((int) *(ncrcmd *)(script_base + script_ofs))); } - printk ("%s: regdump:", ncr_name(np)); - for (i=0; i<16;i++) + printk ("%s: regdump:", ncr_name(np)); + for (i=0; i<16;i++) printk (" %02x", (unsigned)INB_OFF(i)); - printk (".\n"); + printk (".\n"); } /*============================================================ @@ -6218,8 +5899,8 @@ static void ncr_log_hard_error(ncb_p np, u_short sist, u_char dstat) ** ** In normal cases, interrupt conditions occur one at a ** time. The ncr is able to stack in some extra registers -** other interrupts that will occurs after the first one. -** But severall interrupts may occur at the same time. +** other interrupts that will occur after the first one. +** But, several interrupts may occur at the same time. ** ** We probably should only try to deal with the normal ** case, but it seems that multiple interrupts occur in @@ -6242,10 +5923,10 @@ static void ncr_log_hard_error(ncb_p np, u_short sist, u_char dstat) **============================================================ */ -void ncr_exception (ncb_p np) +void ncr_exception (struct ncb *np) { u_char istat, dstat; - u_short sist; + u16 sist; int i; /* @@ -6261,7 +5942,7 @@ void ncr_exception (ncb_p np) istat = INB (nc_istat); if (DEBUG_FLAGS & DEBUG_TINY) printk ("F "); ncr_wakeup_done (np); - }; + } if (!(istat & (SIP|DIP))) return; @@ -6322,7 +6003,7 @@ void ncr_exception (ncb_p np) } OUTONB_STD (); return; - }; + } /*======================================================== ** Now, interrupts that need some fixing up. @@ -6342,7 +6023,7 @@ void ncr_exception (ncb_p np) if (sist & RST) { ncr_init (np, 1, bootverbose ? "scsi reset" : NULL, HS_RESET); return; - }; + } if ((sist & STO) && !(dstat & (MDPE|BF|ABRT))) { @@ -6353,7 +6034,7 @@ void ncr_exception (ncb_p np) ncr_int_sto (np); return; - }; + } /*========================================================= ** Now, interrupts we are not able to recover cleanly. @@ -6368,13 +6049,13 @@ void ncr_exception (ncb_p np) **========================================================= */ - if (ktime_exp(np->regtime)) { - np->regtime = ktime_get(10*HZ); + if (time_after(jiffies, np->regtime)) { + np->regtime = jiffies + 10*HZ; for (i = 0; iregdump); i++) ((char*)&np->regdump)[i] = INB_OFF(i); np->regdump.nc_dstat = dstat; np->regdump.nc_sist = sist; - }; + } ncr_log_hard_error(np, sist, dstat); @@ -6386,20 +6067,20 @@ void ncr_exception (ncb_p np) (dstat & (MDPE|BF|ABRT|IID))) { ncr_start_reset(np); return; - }; + } if (sist & HTH) { printk ("%s: handshake timeout\n", ncr_name(np)); ncr_start_reset(np); return; - }; + } if (sist & UDC) { printk ("%s: unexpected disconnect\n", ncr_name(np)); OUTB (HS_PRT, HS_UNEXPECTED); OUTL_DSP (NCB_SCRIPT_PHYS (np, cleanup)); return; - }; + } /*========================================================= ** We just miss the cause of the interrupt. :( @@ -6425,10 +6106,10 @@ void ncr_exception (ncb_p np) **---------------------------------------------------------- */ -void ncr_int_sto (ncb_p np) +void ncr_int_sto (struct ncb *np) { u_long dsa; - ccb_p cp; + struct ccb *cp; if (DEBUG_FLAGS & DEBUG_TINY) printk ("T"); /* @@ -6443,7 +6124,7 @@ void ncr_int_sto (ncb_p np) if (cp) { cp-> host_status = HS_SEL_TIMEOUT; ncr_complete (np, cp); - }; + } /* ** repair start queue and jump to start point. @@ -6470,7 +6151,7 @@ void ncr_int_sto (ncb_p np) **---------------------------------------------------------- */ -static int ncr_int_sbmc (ncb_p np) +static int ncr_int_sbmc (struct ncb *np) { u_char scsi_mode = INB (nc_stest4) & SMODE; @@ -6485,7 +6166,7 @@ static int ncr_int_sbmc (ncb_p np) ** Suspend command processing for 1 second and ** reinitialize all except the chip. */ - np->settle_time = ktime_get(1*HZ); + np->settle_time = jiffies + HZ; ncr_init (np, 0, bootverbose ? "scsi mode change" : NULL, HS_RESET); return 1; } @@ -6502,7 +6183,7 @@ static int ncr_int_sbmc (ncb_p np) **---------------------------------------------------------- */ -static int ncr_int_par (ncb_p np) +static int ncr_int_par (struct ncb *np) { u_char hsts = INB (HS_PRT); u32 dbc = INL (nc_dbc); @@ -6540,17 +6221,10 @@ static int ncr_int_par (ncb_p np) if (!(dbc & 0xc0000000)) phase = (dbc >> 24) & 7; if (phase == 7) - msg = M_PARITY; + msg = MSG_PARITY_ERROR; else - msg = M_ID_ERROR; + msg = INITIATOR_ERROR; -#ifdef SCSI_NCR_INTEGRITY_CHECKING - /* - ** Save error message. For integrity check use only. - */ - if (np->check_integrity) - np->check_integ_par = msg; -#endif /* * If the NCR stopped on a MOVE ^ DATA_IN, we jump to a @@ -6589,7 +6263,7 @@ reset_all: **---------------------------------------------------------- */ -static void ncr_int_ma (ncb_p np) +static void ncr_int_ma (struct ncb *np) { u32 dbc; u32 rest; @@ -6600,9 +6274,9 @@ static void ncr_int_ma (ncb_p np) u32 *vdsp; u32 oadr, olen; u32 *tblp; - ncrcmd *newcmd; + ncrcmd *newcmd; u_char cmd, sbcl; - ccb_p cp; + struct ccb *cp; dsp = INL (nc_dsp); dbc = INL (nc_dbc); @@ -6618,7 +6292,7 @@ static void ncr_int_ma (ncb_p np) if ((cmd & 1) == 0) { u_char ctest5, ss0, ss2; - u_short delta; + u16 delta; ctest5 = (np->rv_ctest5 & DFS) ? INB (nc_ctest5) : 0; if (ctest5 & DFS) @@ -6641,7 +6315,7 @@ static void ncr_int_ma (ncb_p np) ss2 = INB (nc_sstat2); if (ss2 & OLF1) rest++; if (ss2 & ORF1) rest++; - }; + } if (DEBUG_FLAGS & (DEBUG_TINY|DEBUG_PHASE)) printk ("P%x%x RL=%d D=%d SS0=%x ", cmd&7, sbcl&7, @@ -6667,7 +6341,7 @@ static void ncr_int_ma (ncb_p np) if (!(cmd & 6)) { cp = np->header.cp; if (CCB_PHYS(cp, phys) != dsa) - cp = 0; + cp = NULL; } else { cp = np->ccb; while (cp && (CCB_PHYS (cp, phys) != dsa)) @@ -6678,7 +6352,7 @@ static void ncr_int_ma (ncb_p np) ** try to find the interrupted script command, ** and the address at which to continue. */ - vdsp = 0; + vdsp = NULL; nxtdsp = 0; if (dsp > np->p_script && dsp <= np->p_script + sizeof(struct script)) { @@ -6710,7 +6384,7 @@ static void ncr_int_ma (ncb_p np) cp, np->header.cp, (unsigned)dsp, (unsigned)nxtdsp, vdsp, cmd); - }; + } /* ** cp=0 means that the DSA does not point to a valid control @@ -6738,7 +6412,7 @@ static void ncr_int_ma (ncb_p np) } else { tblp = (u32 *) 0; olen = scr_to_cpu(vdsp[0]) & 0xffffff; - }; + } if (DEBUG_FLAGS & DEBUG_PHASE) { printk ("OCMD=%x\nTBLP=%p OLEN=%x OADR=%x\n", @@ -6746,16 +6420,15 @@ static void ncr_int_ma (ncb_p np) tblp, (unsigned) olen, (unsigned) oadr); - }; + } /* ** check cmd against assumed interrupted script command. */ if (cmd != (scr_to_cpu(vdsp[0]) >> 24)) { - PRINT_ADDR(cp->cmd); - printk ("internal error: cmd=%02x != %02x=(vdsp[0] >> 24)\n", - (unsigned)cmd, (unsigned)scr_to_cpu(vdsp[0]) >> 24); + PRINT_ADDR(cp->cmd, "internal error: cmd=%02x != %02x=(vdsp[0] " + ">> 24)\n", cmd, scr_to_cpu(vdsp[0]) >> 24); goto reset_all; } @@ -6777,12 +6450,11 @@ static void ncr_int_ma (ncb_p np) */ if (cmd & 0x06) { - PRINT_ADDR(cp->cmd); - printk ("phase change %x-%x %d@%08x resid=%d.\n", + PRINT_ADDR(cp->cmd, "phase change %x-%x %d@%08x resid=%d.\n", cmd&7, sbcl&7, (unsigned)olen, (unsigned)oadr, (unsigned)rest); goto unexpected_phase; - }; + } /* ** choose the correct patch area. @@ -6806,8 +6478,7 @@ static void ncr_int_ma (ncb_p np) newcmd[3] = cpu_to_scr(nxtdsp); if (DEBUG_FLAGS & DEBUG_PHASE) { - PRINT_ADDR(cp->cmd); - printk ("newcmd[%d] %x %x %x %x.\n", + PRINT_ADDR(cp->cmd, "newcmd[%d] %x %x %x %x.\n", (int) (newcmd - cp->patch), (unsigned)scr_to_cpu(newcmd[0]), (unsigned)scr_to_cpu(newcmd[1]), @@ -6890,13 +6561,13 @@ reset_all: } -static void ncr_sir_to_redo(ncb_p np, int num, ccb_p cp) +static void ncr_sir_to_redo(struct ncb *np, int num, struct ccb *cp) { - Scsi_Cmnd *cmd = cp->cmd; - tcb_p tp = &np->target[cmd->device->id]; - lcb_p lp = tp->lp[cmd->device->lun]; - XPT_QUEHEAD *qp; - ccb_p cp2; + struct scsi_cmnd *cmd = cp->cmd; + struct tcb *tp = &np->target[cmd->device->id]; + struct lcb *lp = tp->lp[cmd->device->lun]; + struct list_head *qp; + struct ccb * cp2; int disc_cnt = 0; int busy_cnt = 0; u32 startp; @@ -6909,10 +6580,10 @@ static void ncr_sir_to_redo(ncb_p np, int num, ccb_p cp) ** are before cp and busy ones after. */ if (lp) { - qp = lp->busy_ccbq.blink; + qp = lp->busy_ccbq.prev; while (qp != &lp->busy_ccbq) { - cp2 = xpt_que_entry(qp, struct ccb, link_ccbq); - qp = qp->blink; + cp2 = list_entry(qp, struct ccb, link_ccbq); + qp = qp->prev; ++busy_cnt; if (cp2 == cp) break; @@ -6933,14 +6604,13 @@ static void ncr_sir_to_redo(ncb_p np, int num, ccb_p cp) if (!lp) goto out; if (bootverbose >= 1) { - PRINT_ADDR(cmd); - printk ("QUEUE FULL! %d busy, %d disconnected CCBs\n", - busy_cnt, disc_cnt); + PRINT_ADDR(cmd, "QUEUE FULL! %d busy, %d disconnected " + "CCBs\n", busy_cnt, disc_cnt); } if (disc_cnt < lp->numtags) { lp->numtags = disc_cnt > 2 ? disc_cnt : 2; lp->num_good = 0; - ncr_setup_tags (np, cmd->device->id, cmd->device->lun); + ncr_setup_tags (np, cmd->device); } /* ** Requeue the command to the start queue. @@ -6972,7 +6642,7 @@ static void ncr_sir_to_redo(ncb_p np, int num, ccb_p cp) ** ** identify message */ - cp->scsi_smsg2[0] = M_IDENTIFY | cmd->device->lun; + cp->scsi_smsg2[0] = IDENTIFY(0, cmd->device->lun); cp->phys.smsg.addr = cpu_to_scr(CCB_PHYS (cp, scsi_smsg2)); cp->phys.smsg.size = cpu_to_scr(1); @@ -6992,7 +6662,7 @@ static void ncr_sir_to_redo(ncb_p np, int num, ccb_p cp) /* ** sense data */ - bzero(cp->sense_buf, sizeof(cp->sense_buf)); + memset(cp->sense_buf, 0, sizeof(cp->sense_buf)); cp->phys.sense.addr = cpu_to_scr(CCB_PHYS(cp,sense_buf[0])); cp->phys.sense.size = cpu_to_scr(sizeof(cp->sense_buf)); @@ -7017,7 +6687,7 @@ static void ncr_sir_to_redo(ncb_p np, int num, ccb_p cp) /* ** Select without ATN for quirky devices. */ - if (tp->quirks & QUIRK_NOMSG) + if (cmd->device->select_no_atn) cp->start.schedule.l_paddr = cpu_to_scr(NCB_SCRIPTH_PHYS (np, select_no_atn)); @@ -7042,43 +6712,16 @@ out: **========================================================== */ -static int ncr_show_msg (u_char * msg) -{ - u_char i; - printk ("%x",*msg); - if (*msg==M_EXTENDED) { - for (i=1;i<8;i++) { - if (i-1>msg[1]) break; - printk ("-%x",msg[i]); - }; - return (i+1); - } else if ((*msg & 0xf0) == 0x20) { - printk ("-%x",msg[1]); - return (2); - }; - return (1); -} - -static void ncr_print_msg ( ccb_p cp, char *label, u_char *msg) -{ - if (cp) - PRINT_ADDR(cp->cmd); - if (label) - printk("%s: ", label); - - (void) ncr_show_msg (msg); - printk(".\n"); -} - -void ncr_int_sir (ncb_p np) +void ncr_int_sir (struct ncb *np) { u_char scntl3; u_char chg, ofs, per, fak, wide; u_char num = INB (nc_dsps); - ccb_p cp=0; + struct ccb *cp=NULL; u_long dsa = INL (nc_dsa); u_char target = INB (nc_sdid) & 0x0f; - tcb_p tp = &np->target[target]; + struct tcb *tp = &np->target[target]; + struct scsi_target *starget = tp->starget; if (DEBUG_FLAGS & DEBUG_TINY) printk ("I#%d", num); @@ -7133,7 +6776,8 @@ void ncr_int_sir (ncb_p np) while (cp && (CCB_PHYS (cp, phys) != dsa)) cp = cp->link_ccb; - assert (cp && cp == np->header.cp); + BUG_ON(!cp); + BUG_ON(cp != np->header.cp); if (!cp || cp != np->header.cp) goto out; @@ -7143,6 +6787,8 @@ void ncr_int_sir (ncb_p np) /*----------------------------------------------------------------------------- ** ** Was Sie schon immer ueber transfermode negotiation wissen wollten ... +** ("Everything you've always wanted to know about transfer mode +** negotiation") ** ** We try to negotiate sync and wide transfer only after ** a successful inquire command. We look at byte 7 of the @@ -7153,7 +6799,7 @@ void ncr_int_sir (ncb_p np) ** The host status field is set to HS_NEGOTIATE to mark this ** situation. ** -** If the target doesn't answer this message immidiately +** If the target doesn't answer this message immediately ** (as required by the standard), the SIR_NEGO_FAIL interrupt ** will be raised eventually. ** The handler removes the HS_NEGOTIATE status, and sets the @@ -7222,10 +6868,9 @@ void ncr_int_sir (ncb_p np) */ if (DEBUG_FLAGS & DEBUG_NEGO) { - PRINT_ADDR(cp->cmd); - printk ("negotiation failed sir=%x status=%x.\n", - num, cp->nego_status); - }; + PRINT_ADDR(cp->cmd, "negotiation failed sir=%x " + "status=%x.\n", num, cp->nego_status); + } /* ** any error in negotiation: @@ -7234,34 +6879,26 @@ void ncr_int_sir (ncb_p np) switch (cp->nego_status) { case NS_SYNC: + spi_period(starget) = 0; + spi_offset(starget) = 0; ncr_setsync (np, cp, 0, 0xe0); break; case NS_WIDE: + spi_width(starget) = 0; ncr_setwide (np, cp, 0, 0); break; - }; - np->msgin [0] = M_NOOP; - np->msgout[0] = M_NOOP; + } + np->msgin [0] = NOP; + np->msgout[0] = NOP; cp->nego_status = 0; break; case SIR_NEGO_SYNC: - /* - ** Synchronous request message received. - */ - if (DEBUG_FLAGS & DEBUG_NEGO) { - PRINT_ADDR(cp->cmd); - printk ("sync msgin: "); - (void) ncr_show_msg (np->msgin); - printk (".\n"); - }; - - /* - ** get requested values. - */ + ncr_print_msg(cp, "sync msgin", np->msgin); + } chg = 0; per = np->msgin[3]; @@ -7273,8 +6910,8 @@ void ncr_int_sir (ncb_p np) ** it CAN transfer synch. */ - if (ofs) - tp->inq_byte7 |= INQ7_SYNC; + if (ofs && starget) + spi_support_sync(starget) = 1; /* ** check values against driver limits. @@ -7307,9 +6944,8 @@ void ncr_int_sir (ncb_p np) } if (DEBUG_FLAGS & DEBUG_NEGO) { - PRINT_ADDR(cp->cmd); - printk ("sync: per=%d scntl3=0x%x ofs=%d fak=%d chg=%d.\n", - per, scntl3, ofs, fak, chg); + PRINT_ADDR(cp->cmd, "sync: per=%d scntl3=0x%x ofs=%d " + "fak=%d chg=%d.\n", per, scntl3, ofs, fak, chg); } if (INB (HS_PRT) == HS_NEGOTIATE) { @@ -7317,57 +6953,50 @@ void ncr_int_sir (ncb_p np) switch (cp->nego_status) { case NS_SYNC: - /* - ** This was an answer message - */ + /* This was an answer message */ if (chg) { - /* - ** Answer wasn't acceptable. - */ - ncr_setsync (np, cp, 0, 0xe0); - OUTL_DSP (NCB_SCRIPT_PHYS (np, msg_bad)); + /* Answer wasn't acceptable. */ + spi_period(starget) = 0; + spi_offset(starget) = 0; + ncr_setsync(np, cp, 0, 0xe0); + OUTL_DSP(NCB_SCRIPT_PHYS (np, msg_bad)); } else { - /* - ** Answer is ok. - */ - ncr_setsync (np, cp, scntl3, (fak<<5)|ofs); - OUTL_DSP (NCB_SCRIPT_PHYS (np, clrack)); - }; + /* Answer is ok. */ + spi_period(starget) = per; + spi_offset(starget) = ofs; + ncr_setsync(np, cp, scntl3, (fak<<5)|ofs); + OUTL_DSP(NCB_SCRIPT_PHYS (np, clrack)); + } return; case NS_WIDE: - ncr_setwide (np, cp, 0, 0); + spi_width(starget) = 0; + ncr_setwide(np, cp, 0, 0); break; - }; - }; + } + } /* ** It was a request. Set value and ** prepare an answer message */ - ncr_setsync (np, cp, scntl3, (fak<<5)|ofs); - - np->msgout[0] = M_EXTENDED; - np->msgout[1] = 3; - np->msgout[2] = M_X_SYNC_REQ; - np->msgout[3] = per; - np->msgout[4] = ofs; + spi_period(starget) = per; + spi_offset(starget) = ofs; + ncr_setsync(np, cp, scntl3, (fak<<5)|ofs); + spi_populate_sync_msg(np->msgout, per, ofs); cp->nego_status = NS_SYNC; if (DEBUG_FLAGS & DEBUG_NEGO) { - PRINT_ADDR(cp->cmd); - printk ("sync msgout: "); - (void) ncr_show_msg (np->msgout); - printk (".\n"); + ncr_print_msg(cp, "sync msgout", np->msgout); } if (!ofs) { OUTL_DSP (NCB_SCRIPT_PHYS (np, msg_bad)); return; } - np->msgin [0] = M_NOOP; + np->msgin [0] = NOP; break; @@ -7376,11 +7005,8 @@ void ncr_int_sir (ncb_p np) ** Wide request message received. */ if (DEBUG_FLAGS & DEBUG_NEGO) { - PRINT_ADDR(cp->cmd); - printk ("wide msgin: "); - (void) ncr_show_msg (np->msgin); - printk (".\n"); - }; + ncr_print_msg(cp, "wide msgin", np->msgin); + } /* ** get requested values. @@ -7394,8 +7020,8 @@ void ncr_int_sir (ncb_p np) ** it CAN transfer wide. */ - if (wide) - tp->inq_byte7 |= INQ7_WIDE16; + if (wide && starget) + spi_support_wide(starget) = 1; /* ** check values against driver limits. @@ -7405,8 +7031,8 @@ void ncr_int_sir (ncb_p np) {chg = 1; wide = tp->usrwide;} if (DEBUG_FLAGS & DEBUG_NEGO) { - PRINT_ADDR(cp->cmd); - printk ("wide: wide=%d chg=%d.\n", wide, chg); + PRINT_ADDR(cp->cmd, "wide: wide=%d chg=%d.\n", wide, + chg); } if (INB (HS_PRT) == HS_NEGOTIATE) { @@ -7418,47 +7044,41 @@ void ncr_int_sir (ncb_p np) ** This was an answer message */ if (chg) { - /* - ** Answer wasn't acceptable. - */ - ncr_setwide (np, cp, 0, 1); + /* Answer wasn't acceptable. */ + spi_width(starget) = 0; + ncr_setwide(np, cp, 0, 1); OUTL_DSP (NCB_SCRIPT_PHYS (np, msg_bad)); } else { - /* - ** Answer is ok. - */ - ncr_setwide (np, cp, wide, 1); + /* Answer is ok. */ + spi_width(starget) = wide; + ncr_setwide(np, cp, wide, 1); OUTL_DSP (NCB_SCRIPT_PHYS (np, clrack)); - }; + } return; case NS_SYNC: - ncr_setsync (np, cp, 0, 0xe0); + spi_period(starget) = 0; + spi_offset(starget) = 0; + ncr_setsync(np, cp, 0, 0xe0); break; - }; - }; + } + } /* ** It was a request, set value and ** prepare an answer message */ - ncr_setwide (np, cp, wide, 1); + spi_width(starget) = wide; + ncr_setwide(np, cp, wide, 1); + spi_populate_width_msg(np->msgout, wide); - np->msgout[0] = M_EXTENDED; - np->msgout[1] = 2; - np->msgout[2] = M_X_WIDE_REQ; - np->msgout[3] = wide; - - np->msgin [0] = M_NOOP; + np->msgin [0] = NOP; cp->nego_status = NS_WIDE; if (DEBUG_FLAGS & DEBUG_NEGO) { - PRINT_ADDR(cp->cmd); - printk ("wide msgout: "); - (void) ncr_show_msg (np->msgin); - printk (".\n"); + ncr_print_msg(cp, "wide msgout", np->msgin); } break; @@ -7472,13 +7092,12 @@ void ncr_int_sir (ncb_p np) case SIR_REJECT_RECEIVED: /*----------------------------------------------- ** - ** We received a M_REJECT message. + ** We received a MESSAGE_REJECT. ** **----------------------------------------------- */ - PRINT_ADDR(cp->cmd); - printk ("M_REJECT received (%x:%x).\n", + PRINT_ADDR(cp->cmd, "MESSAGE_REJECT received (%x:%x).\n", (unsigned)scr_to_cpu(np->lastmsg), np->msgout[0]); break; @@ -7490,10 +7109,7 @@ void ncr_int_sir (ncb_p np) **----------------------------------------------- */ - PRINT_ADDR(cp->cmd); - printk ("M_REJECT sent for "); - (void) ncr_show_msg (np->msgin); - printk (".\n"); + ncr_print_msg(cp, "MESSAGE_REJECT sent for", np->msgin); break; /*-------------------------------------------------------------------- @@ -7512,8 +7128,8 @@ void ncr_int_sir (ncb_p np) **----------------------------------------------- */ - PRINT_ADDR(cp->cmd); - printk ("M_IGN_RESIDUE received, but not yet implemented.\n"); + PRINT_ADDR(cp->cmd, "IGNORE_WIDE_RESIDUE received, but not yet " + "implemented.\n"); break; #if 0 case SIR_MISSING_SAVE: @@ -7525,15 +7141,14 @@ void ncr_int_sir (ncb_p np) **----------------------------------------------- */ - PRINT_ADDR(cp->cmd); - printk ("M_DISCONNECT received, but datapointer not saved: " - "data=%x save=%x goal=%x.\n", + PRINT_ADDR(cp->cmd, "DISCONNECT received, but datapointer " + "not saved: data=%x save=%x goal=%x.\n", (unsigned) INL (nc_temp), (unsigned) scr_to_cpu(np->header.savep), (unsigned) scr_to_cpu(np->header.goalp)); break; #endif - }; + } out: OUTONB_STD (); @@ -7548,50 +7163,44 @@ out: **========================================================== */ -static ccb_p ncr_get_ccb (ncb_p np, u_char tn, u_char ln) +static struct ccb *ncr_get_ccb(struct ncb *np, struct scsi_cmnd *cmd) { - tcb_p tp = &np->target[tn]; - lcb_p lp = tp->lp[ln]; + u_char tn = cmd->device->id; + u_char ln = cmd->device->lun; + struct tcb *tp = &np->target[tn]; + struct lcb *lp = tp->lp[ln]; u_char tag = NO_TAG; - ccb_p cp = (ccb_p) 0; + struct ccb *cp = NULL; /* ** Lun structure available ? */ if (lp) { - XPT_QUEHEAD *qp; + struct list_head *qp; /* ** Keep from using more tags than we can handle. */ if (lp->usetags && lp->busyccbs >= lp->maxnxs) - return (ccb_p) 0; + return NULL; /* ** Allocate a new CCB if needed. */ - if (xpt_que_empty(&lp->free_ccbq)) + if (list_empty(&lp->free_ccbq)) ncr_alloc_ccb(np, tn, ln); - /* - ** Tune tag mode if asked by user. - */ - if (lp->queuedepth != lp->numtags) { - ncr_setup_tags(np, tn, ln); - } - /* ** Look for free CCB */ - qp = xpt_remque_head(&lp->free_ccbq); + qp = ncr_list_pop(&lp->free_ccbq); if (qp) { - cp = xpt_que_entry(qp, struct ccb, link_ccbq); + cp = list_entry(qp, struct ccb, link_ccbq); if (cp->magic) { - PRINT_LUN(np, tn, ln); - printk ("ccb free list corrupted (@%p)\n", cp); - cp = 0; - } - else { - xpt_insque_tail(qp, &lp->wait_ccbq); + PRINT_ADDR(cmd, "ccb free list corrupted " + "(@%p)\n", cp); + cp = NULL; + } else { + list_add_tail(qp, &lp->wait_ccbq); ++lp->busyccbs; } } @@ -7605,7 +7214,7 @@ static ccb_p ncr_get_ccb (ncb_p np, u_char tn, u_char ln) tag = lp->cb_tags[lp->ia_tag]; } else if (lp->actccbs > 0) - return (ccb_p) 0; + return NULL; } /* @@ -7622,11 +7231,11 @@ static ccb_p ncr_get_ccb (ncb_p np, u_char tn, u_char ln) if (flags & SCSI_NOSLEEP) break; if (tsleep ((caddr_t)cp, PRIBIO|PCATCH, "ncr", 0)) break; - }; + } #endif if (cp->magic) - return ((ccb_p) 0); + return NULL; cp->magic = 1; @@ -7650,8 +7259,7 @@ static ccb_p ncr_get_ccb (ncb_p np, u_char tn, u_char ln) cp->lun = ln; if (DEBUG_FLAGS & DEBUG_TAGS) { - PRINT_LUN(np, tn, ln); - printk ("ccb @%p using tag %d.\n", cp, tag); + PRINT_ADDR(cmd, "ccb @%p using tag %d.\n", cp, tag); } return cp; @@ -7666,14 +7274,13 @@ static ccb_p ncr_get_ccb (ncb_p np, u_char tn, u_char ln) **========================================================== */ -static void ncr_free_ccb (ncb_p np, ccb_p cp) +static void ncr_free_ccb (struct ncb *np, struct ccb *cp) { - tcb_p tp = &np->target[cp->target]; - lcb_p lp = tp->lp[cp->lun]; + struct tcb *tp = &np->target[cp->target]; + struct lcb *lp = tp->lp[cp->lun]; if (DEBUG_FLAGS & DEBUG_TAGS) { - PRINT_LUN(np, cp->target, cp->lun); - printk ("ccb @%p freeing tag %d.\n", cp, cp->tag); + PRINT_ADDR(cp->cmd, "ccb @%p freeing tag %d.\n", cp, cp->tag); } /* @@ -7701,10 +7308,8 @@ static void ncr_free_ccb (ncb_p np, ccb_p cp) */ if (lp) { - if (cp != np->ccb) { - xpt_remque(&cp->link_ccbq); - xpt_insque_head(&cp->link_ccbq, &lp->free_ccbq); - } + if (cp != np->ccb) + list_move(&cp->link_ccbq, &lp->free_ccbq); --lp->busyccbs; if (cp->queued) { --lp->queuedccbs; @@ -7731,7 +7336,7 @@ static void ncr_free_ccb (ncb_p np, ccb_p cp) **------------------------------------------------------------------------ **------------------------------------------------------------------------ */ -static void ncr_init_ccb(ncb_p np, ccb_p cp) +static void ncr_init_ccb(struct ncb *np, struct ccb *cp) { ncrcmd copy_4 = np->features & FE_PFEN ? SCR_COPY(4) : SCR_COPY_F(4); @@ -7742,9 +7347,9 @@ static void ncr_init_ccb(ncb_p np, ccb_p cp) cp->phys.header.cp = cp; /* - ** This allows xpt_remque to work for the default ccb. + ** This allows list_del to work for the default ccb. */ - xpt_que_init(&cp->link_ccbq); + INIT_LIST_HEAD(&cp->link_ccbq); /* ** Initialyze the start and restart launch script. @@ -7770,11 +7375,11 @@ static void ncr_init_ccb(ncb_p np, ccb_p cp) **------------------------------------------------------------------------ **------------------------------------------------------------------------ */ -static void ncr_alloc_ccb(ncb_p np, u_char tn, u_char ln) +static void ncr_alloc_ccb(struct ncb *np, u_char tn, u_char ln) { - tcb_p tp = &np->target[tn]; - lcb_p lp = tp->lp[ln]; - ccb_p cp = 0; + struct tcb *tp = &np->target[tn]; + struct lcb *lp = tp->lp[ln]; + struct ccb *cp = NULL; /* ** Allocate memory for this CCB. @@ -7788,7 +7393,7 @@ static void ncr_alloc_ccb(ncb_p np, u_char tn, u_char ln) */ lp->actccbs++; np->actccbs++; - bzero (cp, sizeof (*cp)); + memset(cp, 0, sizeof (*cp)); ncr_init_ccb(np, cp); /* @@ -7798,8 +7403,7 @@ static void ncr_alloc_ccb(ncb_p np, u_char tn, u_char ln) cp->link_ccb = np->ccb->link_ccb; np->ccb->link_ccb = cp; - xpt_insque_head(&cp->link_ccbq, &lp->free_ccbq); - ncr_setup_tags (np, tn, ln); + list_add(&cp->link_ccbq, &lp->free_ccbq); } /*========================================================== @@ -7820,9 +7424,9 @@ static void ncr_alloc_ccb(ncb_p np, u_char tn, u_char ln) ** It contains a SCRIPT that is called on target reselection. **------------------------------------------------------------------------ */ -static void ncr_init_tcb (ncb_p np, u_char tn) +static void ncr_init_tcb (struct ncb *np, u_char tn) { - tcb_p tp = &np->target[tn]; + struct tcb *tp = &np->target[tn]; ncrcmd copy_1 = np->features & FE_PFEN ? SCR_COPY(1) : SCR_COPY_F(1); int th = tn & 3; int i; @@ -7887,15 +7491,15 @@ static void ncr_init_tcb (ncb_p np, u_char tn) ** These assert's should be moved at driver initialisations. */ #ifdef SCSI_NCR_BIG_ENDIAN - assert (( (offsetof(struct ncr_reg, nc_sxfer) ^ - offsetof(struct tcb , sval )) &3) == 3); - assert (( (offsetof(struct ncr_reg, nc_scntl3) ^ - offsetof(struct tcb , wval )) &3) == 3); + BUG_ON(((offsetof(struct ncr_reg, nc_sxfer) ^ + offsetof(struct tcb , sval )) &3) != 3); + BUG_ON(((offsetof(struct ncr_reg, nc_scntl3) ^ + offsetof(struct tcb , wval )) &3) != 3); #else - assert (( (offsetof(struct ncr_reg, nc_sxfer) ^ - offsetof(struct tcb , sval )) &3) == 0); - assert (( (offsetof(struct ncr_reg, nc_scntl3) ^ - offsetof(struct tcb , wval )) &3) == 0); + BUG_ON(((offsetof(struct ncr_reg, nc_sxfer) ^ + offsetof(struct tcb , sval )) &3) != 0); + BUG_ON(((offsetof(struct ncr_reg, nc_scntl3) ^ + offsetof(struct tcb , wval )) &3) != 0); #endif } @@ -7907,10 +7511,10 @@ static void ncr_init_tcb (ncb_p np, u_char tn) ** command has been successfully completed for this target/lun. **------------------------------------------------------------------------ */ -static lcb_p ncr_alloc_lcb (ncb_p np, u_char tn, u_char ln) +static struct lcb *ncr_alloc_lcb (struct ncb *np, u_char tn, u_char ln) { - tcb_p tp = &np->target[tn]; - lcb_p lp = tp->lp[ln]; + struct tcb *tp = &np->target[tn]; + struct lcb *lp = tp->lp[ln]; ncrcmd copy_4 = np->features & FE_PFEN ? SCR_COPY(4) : SCR_COPY_F(4); int lh = ln & 3; @@ -7926,7 +7530,7 @@ static lcb_p ncr_alloc_lcb (ncb_p np, u_char tn, u_char ln) lp = m_calloc_dma(sizeof(struct lcb), "LCB"); if (!lp) goto fail; - bzero(lp, sizeof(*lp)); + memset(lp, 0, sizeof(*lp)); tp->lp[ln] = lp; /* @@ -7938,10 +7542,10 @@ static lcb_p ncr_alloc_lcb (ncb_p np, u_char tn, u_char ln) /* ** Initialize the CCB queue headers. */ - xpt_que_init(&lp->free_ccbq); - xpt_que_init(&lp->busy_ccbq); - xpt_que_init(&lp->wait_ccbq); - xpt_que_init(&lp->skip_ccbq); + INIT_LIST_HEAD(&lp->free_ccbq); + INIT_LIST_HEAD(&lp->busy_ccbq); + INIT_LIST_HEAD(&lp->wait_ccbq); + INIT_LIST_HEAD(&lp->skip_ccbq); /* ** Set max CCBs to 1 and use the default 1 entry @@ -7997,68 +7601,21 @@ fail: ** will play with CHANGE DEFINITION commands. :-) **------------------------------------------------------------------------ */ -static lcb_p ncr_setup_lcb (ncb_p np, u_char tn, u_char ln, u_char *inq_data) +static struct lcb *ncr_setup_lcb (struct ncb *np, struct scsi_device *sdev) { - tcb_p tp = &np->target[tn]; - lcb_p lp = tp->lp[ln]; - u_char inq_byte7; + unsigned char tn = sdev->id, ln = sdev->lun; + struct tcb *tp = &np->target[tn]; + struct lcb *lp = tp->lp[ln]; - /* - ** If no lcb, try to allocate it. - */ + /* If no lcb, try to allocate it. */ if (!lp && !(lp = ncr_alloc_lcb(np, tn, ln))) goto fail; - /* - ** Get device quirks from a speciality table. - */ - tp->quirks = ncr_lookup (inq_data); - if (tp->quirks && bootverbose) { - PRINT_LUN(np, tn, ln); - printk ("quirks=%x.\n", tp->quirks); - } - - /* - ** Evaluate trustable target/unit capabilities. - ** We only believe device version >= SCSI-2 that - ** use appropriate response data format (2). - ** But it seems that some CCS devices also - ** support SYNC and I donnot want to frustrate - ** anybody. ;-) - */ - inq_byte7 = 0; - if ((inq_data[2] & 0x7) >= 2 && (inq_data[3] & 0xf) == 2) - inq_byte7 = inq_data[7]; - else if ((inq_data[2] & 0x7) == 1 && (inq_data[3] & 0xf) == 1) - inq_byte7 = INQ7_SYNC; - - /* - ** Throw away announced LUN capabilities if we are told - ** that there is no real device supported by the logical unit. - */ - if ((inq_data[0] & 0xe0) > 0x20 || (inq_data[0] & 0x1f) == 0x1f) - inq_byte7 &= (INQ7_SYNC | INQ7_WIDE16); - - /* - ** If user is wanting SYNC, force this feature. - */ - if (driver_setup.force_sync_nego) - inq_byte7 |= INQ7_SYNC; - - /* - ** Prepare negotiation if SIP capabilities have changed. - */ - tp->inq_done = 1; - if ((inq_byte7 ^ tp->inq_byte7) & (INQ7_SYNC | INQ7_WIDE16)) { - tp->inq_byte7 = inq_byte7; - ncr_negotiate(np, tp); - } - /* ** If unit supports tagged commands, allocate the ** CCB JUMP table if not yet. */ - if ((inq_byte7 & INQ7_QUEUE) && lp->jump_ccb == &lp->jump_ccb_0) { + if (sdev->tagged_supported && lp->jump_ccb == &lp->jump_ccb_0) { int i; lp->jump_ccb = m_calloc_dma(256, "JUMP_CCB"); if (!lp->jump_ccb) { @@ -8072,17 +7629,10 @@ static lcb_p ncr_setup_lcb (ncb_p np, u_char tn, u_char ln, u_char *inq_data) for (i = 0 ; i < MAX_TAGS ; i++) lp->cb_tags[i] = i; lp->maxnxs = MAX_TAGS; - lp->tags_stime = ktime_get(3*HZ); + lp->tags_stime = jiffies + 3*HZ; + ncr_setup_tags (np, sdev); } - /* - ** Adjust tagged queueing status if needed. - */ - if ((inq_byte7 ^ lp->inq_byte7) & INQ7_QUEUE) { - lp->inq_byte7 = inq_byte7; - lp->numtags = lp->maxtags; - ncr_setup_tags (np, tn, ln); - } fail: return lp; @@ -8117,44 +7667,57 @@ fail: ** sizes to the data segment array. */ -static int ncr_scatter(ncb_p np, ccb_p cp, Scsi_Cmnd *cmd) +static int ncr_scatter_no_sglist(struct ncb *np, struct ccb *cp, struct scsi_cmnd *cmd) +{ + struct scr_tblmove *data = &cp->phys.data[MAX_SCATTER - 1]; + int segment; + + cp->data_len = cmd->request_bufflen; + + if (cmd->request_bufflen) { + dma_addr_t baddr = map_scsi_single_data(np, cmd); + if (baddr) { + ncr_build_sge(np, data, baddr, cmd->request_bufflen); + segment = 1; + } else { + segment = -2; + } + } else { + segment = 0; + } + + return segment; +} + +static int ncr_scatter(struct ncb *np, struct ccb *cp, struct scsi_cmnd *cmd) { - struct scr_tblmove *data; int segment = 0; int use_sg = (int) cmd->use_sg; - data = cp->phys.data; cp->data_len = 0; - if (!use_sg) { - if (cmd->request_bufflen) { - u_long baddr = map_scsi_single_data(np, cmd); + if (!use_sg) + segment = ncr_scatter_no_sglist(np, cp, cmd); + else if ((use_sg = map_scsi_sg_data(np, cmd)) > 0) { + struct scatterlist *scatter = (struct scatterlist *)cmd->request_buffer; + struct scr_tblmove *data; - data = &data[MAX_SCATTER - 1]; - data[0].addr = cpu_to_scr(baddr); - data[0].size = cpu_to_scr(cmd->request_bufflen); - cp->data_len = cmd->request_bufflen; - segment = 1; + if (use_sg > MAX_SCATTER) { + unmap_scsi_data(np, cmd); + return -1; } - } - else if (use_sg <= MAX_SCATTER) { - struct scatterlist *scatter = (struct scatterlist *)cmd->buffer; - use_sg = map_scsi_sg_data(np, cmd); - data = &data[MAX_SCATTER - use_sg]; + data = &cp->phys.data[MAX_SCATTER - use_sg]; - while (segment < use_sg) { - u_long baddr = scsi_sg_dma_address(&scatter[segment]); - unsigned int len = scsi_sg_dma_len(&scatter[segment]); + for (segment = 0; segment < use_sg; segment++) { + dma_addr_t baddr = sg_dma_address(&scatter[segment]); + unsigned int len = sg_dma_len(&scatter[segment]); - data[segment].addr = cpu_to_scr(baddr); - data[segment].size = cpu_to_scr(len); - cp->data_len += len; - ++segment; + ncr_build_sge(np, &data[segment], baddr, len); + cp->data_len += len; } - } - else { - return -1; + } else { + segment = -2; } return segment; @@ -8171,7 +7734,6 @@ static int ncr_scatter(ncb_p np, ccb_p cp, Scsi_Cmnd *cmd) **========================================================== */ -#ifndef SCSI_NCR_IOMAPPED static int __init ncr_regtest (struct ncb* np) { register volatile u32 data; @@ -8191,24 +7753,21 @@ static int __init ncr_regtest (struct ncb* np) printk ("CACHE TEST FAILED: reg dstat-sstat2 readback %x.\n", (unsigned) data); return (0x10); - }; + } return (0); } -#endif static int __init ncr_snooptest (struct ncb* np) { u32 ncr_rd, ncr_wr, ncr_bk, host_rd, host_wr, pc; int i, err=0; -#ifndef SCSI_NCR_IOMAPPED if (np->reg) { - err |= ncr_regtest (np); - if (err) return (err); + err |= ncr_regtest (np); + if (err) + return (err); } -#endif - /* - ** init - */ + + /* init */ pc = NCB_SCRIPTH_PHYS (np, snooptest); host_wr = 1; ncr_wr = 2; @@ -8247,7 +7806,7 @@ static int __init ncr_snooptest (struct ncb* np) if (i>=NCR_SNOOP_TIMEOUT) { printk ("CACHE TEST FAILED: timeout.\n"); return (0x20); - }; + } /* ** Check termination position. */ @@ -8257,7 +7816,7 @@ static int __init ncr_snooptest (struct ncb* np) (u_long) NCB_SCRIPTH_PHYS (np, snooptest), (u_long) pc, (u_long) NCB_SCRIPTH_PHYS (np, snoopend) +8); return (0x40); - }; + } /* ** Show results. */ @@ -8265,74 +7824,18 @@ static int __init ncr_snooptest (struct ncb* np) printk ("CACHE TEST FAILED: host wrote %d, ncr read %d.\n", (int) host_wr, (int) ncr_rd); err |= 1; - }; + } if (host_rd != ncr_wr) { printk ("CACHE TEST FAILED: ncr wrote %d, host read %d.\n", (int) ncr_wr, (int) host_rd); err |= 2; - }; + } if (ncr_bk != ncr_wr) { printk ("CACHE TEST FAILED: ncr wrote %d, read back %d.\n", (int) ncr_wr, (int) ncr_bk); err |= 4; - }; - return (err); -} - -/*========================================================== -** -** -** Device lookup. -** -** @GENSCSI@ should be integrated to scsiconf.c -** -** -**========================================================== -*/ - -struct table_entry { - char * manufacturer; - char * model; - char * version; - u_long info; -}; - -static struct table_entry device_tab[] = -{ -#if 0 - {"", "", "", QUIRK_NOMSG}, -#endif - {"SONY", "SDT-5000", "3.17", QUIRK_NOMSG}, - {"WangDAT", "Model 2600", "01.7", QUIRK_NOMSG}, - {"WangDAT", "Model 3200", "02.2", QUIRK_NOMSG}, - {"WangDAT", "Model 1300", "02.4", QUIRK_NOMSG}, - {"", "", "", 0} /* catch all: must be last entry. */ -}; - -static u_long ncr_lookup(char * id) -{ - struct table_entry * p = device_tab; - char *d, *r, c; - - for (;;p++) { - - d = id+8; - r = p->manufacturer; - while ((c=*r++)) if (c!=*d++) break; - if (c) continue; - - d = id+16; - r = p->model; - while ((c=*r++)) if (c!=*d++) break; - if (c) continue; - - d = id+32; - r = p->version; - while ((c=*r++)) if (c!=*d++) break; - if (c) continue; - - return (p->info); } + return (err); } /*========================================================== @@ -8344,7 +7847,7 @@ static u_long ncr_lookup(char * id) **========================================================== ** ** Note: we have to return the correct value. -** THERE IS NO SAVE DEFAULT VALUE. +** THERE IS NO SAFE DEFAULT VALUE. ** ** Most NCR/SYMBIOS boards are delivered with a 40 Mhz clock. ** 53C860 and 53C875 rev. 1 support fast20 transfers but @@ -8361,7 +7864,7 @@ static u_long ncr_lookup(char * id) /* * Select NCR SCSI clock frequency */ -static void ncr_selectclock(ncb_p np, u_char scntl3) +static void ncr_selectclock(struct ncb *np, u_char scntl3) { if (np->multiplier < 2) { OUTB(nc_scntl3, scntl3); @@ -8375,11 +7878,11 @@ static void ncr_selectclock(ncb_p np, u_char scntl3) if (np->multiplier > 2) { /* Poll bit 5 of stest4 for quadrupler */ int i = 20; while (!(INB(nc_stest4) & LCKFRQ) && --i > 0) - UDELAY (20); + udelay(20); if (!i) printk("%s: the chip cannot lock the frequency\n", ncr_name(np)); } else /* Wait 20 micro-seconds for doubler */ - UDELAY (20); + udelay(20); OUTB(nc_stest3, HSC); /* Halt the scsi clock */ OUTB(nc_scntl3, scntl3); OUTB(nc_stest1, (DBLEN|DBLSEL));/* Select clock multiplier */ @@ -8390,7 +7893,7 @@ static void ncr_selectclock(ncb_p np, u_char scntl3) /* * calculate NCR SCSI clock frequency (in KHz) */ -static unsigned __init ncrgetfreq (ncb_p np, int gen) +static unsigned __init ncrgetfreq (struct ncb *np, int gen) { unsigned ms = 0; char count = 0; @@ -8420,7 +7923,7 @@ static unsigned __init ncrgetfreq (ncb_p np, int gen) OUTB (nc_stime1, gen); /* set to nominal delay of 1<host; + struct ncb *np = ((struct host_data *) host->hostdata)->ncb; + struct tcb *tp = &np->target[device->id]; + tp->starget = device->sdev_target; + + return 0; +} -int ncr53c8xx_slave_configure(Scsi_Device *device) +static int ncr53c8xx_slave_configure(struct scsi_device *device) { struct Scsi_Host *host = device->host; - ncb_p np; - tcb_p tp; - lcb_p lp; + struct ncb *np = ((struct host_data *) host->hostdata)->ncb; + struct tcb *tp = &np->target[device->id]; + struct lcb *lp = tp->lp[device->lun]; int numtags, depth_to_use; - np = ((struct host_data *) host->hostdata)->ncb; - tp = &np->target[device->id]; - lp = tp->lp[device->lun]; + ncr_setup_lcb(np, device); /* ** Select queue depth from driver setup. @@ -8546,28 +8053,31 @@ int ncr53c8xx_slave_configure(Scsi_Device *device) ** Since the queue depth is not tunable under Linux, ** we need to know this value in order not to ** announce stupid things to user. + ** + ** XXX(hch): As of Linux 2.6 it certainly _is_ tunable.. + ** In fact we just tuned it, or did I miss + ** something important? :) */ if (lp) { lp->numtags = lp->maxtags = numtags; lp->scdev_depth = depth_to_use; } - ncr_setup_tags (np, device->id, device->lun); + ncr_setup_tags (np, device); #ifdef DEBUG_NCR53C8XX printk("ncr53c8xx_select_queue_depth: host=%d, id=%d, lun=%d, depth=%d\n", np->unit, device->id, device->lun, depth_to_use); #endif + if (spi_support_sync(device->sdev_target) && + !spi_initial_dv(device->sdev_target)) + spi_dv_device(device); return 0; } -/* -** Linux entry point of queuecommand() function -*/ - -int ncr53c8xx_queue_command (Scsi_Cmnd *cmd, void (* done)(Scsi_Cmnd *)) +static int ncr53c8xx_queue_command (struct scsi_cmnd *cmd, void (* done)(struct scsi_cmnd *)) { - ncb_p np = ((struct host_data *) cmd->device->host->hostdata)->ncb; + struct ncb *np = ((struct host_data *) cmd->device->host->hostdata)->ncb; unsigned long flags; int sts; @@ -8577,12 +8087,10 @@ printk("ncr53c8xx_queue_command\n"); cmd->scsi_done = done; cmd->host_scribble = NULL; -#ifdef SCSI_NCR_DYNAMIC_DMA_MAPPING cmd->__data_mapped = 0; cmd->__data_mapping = 0; -#endif - NCR_LOCK_NCB(np, flags); + spin_lock_irqsave(&np->smp_lock, flags); if ((sts = ncr_queue_command(np, cmd)) != DID_OK) { cmd->result = ScsiResult(sts, 0); @@ -8595,31 +8103,24 @@ printk("ncr53c8xx : command not queued - result=%d\n", sts); printk("ncr53c8xx : command successfully queued\n"); #endif - NCR_UNLOCK_NCB(np, flags); + spin_unlock_irqrestore(&np->smp_lock, flags); if (sts != DID_OK) { unmap_scsi_data(np, cmd); done(cmd); + sts = 0; } return sts; } -/* -** Linux entry point of the interrupt handler. -** Since linux versions > 1.3.70, we trust the kernel for -** passing the internal host descriptor as 'dev_id'. -** Otherwise, we scan the host list and call the interrupt -** routine for each host that uses this IRQ. -*/ - -irqreturn_t ncr53c8xx_intr(int irq, void *dev_id, struct pt_regs * regs) +irqreturn_t ncr53c8xx_intr(int irq, void *dev_id) { unsigned long flags; struct Scsi_Host *shost = (struct Scsi_Host *)dev_id; struct host_data *host_data = (struct host_data *)shost->hostdata; - ncb_p np = host_data->ncb; - Scsi_Cmnd *done_list; + struct ncb *np = host_data->ncb; + struct scsi_cmnd *done_list; #ifdef DEBUG_NCR53C8XX printk("ncr53c8xx : interrupt received\n"); @@ -8627,57 +8128,41 @@ irqreturn_t ncr53c8xx_intr(int irq, void *dev_id, struct pt_regs * regs) if (DEBUG_FLAGS & DEBUG_TINY) printk ("["); - NCR_LOCK_NCB(np, flags); + spin_lock_irqsave(&np->smp_lock, flags); ncr_exception(np); done_list = np->done_list; - np->done_list = 0; - NCR_UNLOCK_NCB(np, flags); + np->done_list = NULL; + spin_unlock_irqrestore(&np->smp_lock, flags); if (DEBUG_FLAGS & DEBUG_TINY) printk ("]\n"); - if (done_list) { - NCR_LOCK_SCSI_DONE(done_list->device->host, flags); - ncr_flush_done_cmds(done_list); - NCR_UNLOCK_SCSI_DONE(done_list->device->host, flags); - } + if (done_list) + ncr_flush_done_cmds(done_list); return IRQ_HANDLED; } -/* -** Linux entry point of the timer handler -*/ - static void ncr53c8xx_timeout(unsigned long npref) { - ncb_p np = (ncb_p) npref; - unsigned long flags; - Scsi_Cmnd *done_list; + struct ncb *np = (struct ncb *) npref; + unsigned long flags; + struct scsi_cmnd *done_list; - NCR_LOCK_NCB(np, flags); - ncr_timeout((ncb_p) np); - done_list = np->done_list; - np->done_list = 0; - NCR_UNLOCK_NCB(np, flags); + spin_lock_irqsave(&np->smp_lock, flags); + ncr_timeout(np); + done_list = np->done_list; + np->done_list = NULL; + spin_unlock_irqrestore(&np->smp_lock, flags); - if (done_list) { - NCR_LOCK_SCSI_DONE(done_list->device->host, flags); - ncr_flush_done_cmds(done_list); - NCR_UNLOCK_SCSI_DONE(done_list->device->host, flags); - } + if (done_list) + ncr_flush_done_cmds(done_list); } -/* -** Linux entry point of reset() function -*/ - -int ncr53c8xx_bus_reset(Scsi_Cmnd *cmd) +static int ncr53c8xx_bus_reset(struct scsi_cmnd *cmd) { - ncb_p np = ((struct host_data *) cmd->device->host->hostdata)->ncb; + struct ncb *np = ((struct host_data *) cmd->device->host->hostdata)->ncb; int sts; unsigned long flags; - Scsi_Cmnd *done_list; - - NCR_LOCK_NCB(np, flags); + struct scsi_cmnd *done_list; /* * If the mid-level driver told us reset is synchronous, it seems @@ -8686,68 +8171,46 @@ int ncr53c8xx_bus_reset(Scsi_Cmnd *cmd) * before returning SUCCESS. */ + spin_lock_irqsave(&np->smp_lock, flags); sts = ncr_reset_bus(np, cmd, 1); done_list = np->done_list; - np->done_list = 0; - NCR_UNLOCK_NCB(np, flags); + np->done_list = NULL; + spin_unlock_irqrestore(&np->smp_lock, flags); ncr_flush_done_cmds(done_list); return sts; } -/* -** Linux entry point of abort() function -*/ - -int ncr53c8xx_abort(Scsi_Cmnd *cmd) +#if 0 /* unused and broken */ +static int ncr53c8xx_abort(struct scsi_cmnd *cmd) { - ncb_p np = ((struct host_data *) cmd->device->host->hostdata)->ncb; + struct ncb *np = ((struct host_data *) cmd->device->host->hostdata)->ncb; int sts; unsigned long flags; - Scsi_Cmnd *done_list; + struct scsi_cmnd *done_list; #if defined SCSI_RESET_SYNCHRONOUS && defined SCSI_RESET_ASYNCHRONOUS - printk("ncr53c8xx_abort: pid=%lu serial_number=%ld serial_number_at_timeout=%ld\n", - cmd->pid, cmd->serial_number, cmd->serial_number_at_timeout); + printk("ncr53c8xx_abort: pid=%lu serial_number=%ld\n", + cmd->pid, cmd->serial_number); #else printk("ncr53c8xx_abort: command pid %lu\n", cmd->pid); #endif NCR_LOCK_NCB(np, flags); -#if defined SCSI_RESET_SYNCHRONOUS && defined SCSI_RESET_ASYNCHRONOUS - /* - * We have to just ignore abort requests in some situations. - */ - if (cmd->serial_number != cmd->serial_number_at_timeout) { - sts = SCSI_ABORT_NOT_RUNNING; - goto out; - } -#endif - sts = ncr_abort_command(np, cmd); out: done_list = np->done_list; - np->done_list = 0; + np->done_list = NULL; NCR_UNLOCK_NCB(np, flags); ncr_flush_done_cmds(done_list); return sts; } - - -int ncr53c8xx_release(struct Scsi_Host *host) -{ -#ifdef DEBUG_NCR53C8XX -printk("ncr53c8xx : release\n"); #endif - ncr_detach(((struct host_data *) host->hostdata)->ncb); - - return 1; -} /* @@ -8765,55 +8228,55 @@ printk("ncr53c8xx : release\n"); #define next_wcmd host_scribble -static void insert_into_waiting_list(ncb_p np, Scsi_Cmnd *cmd) +static void insert_into_waiting_list(struct ncb *np, struct scsi_cmnd *cmd) { - Scsi_Cmnd *wcmd; + struct scsi_cmnd *wcmd; #ifdef DEBUG_WAITING_LIST printk("%s: cmd %lx inserted into waiting list\n", ncr_name(np), (u_long) cmd); #endif - cmd->next_wcmd = 0; + cmd->next_wcmd = NULL; if (!(wcmd = np->waiting_list)) np->waiting_list = cmd; else { while ((wcmd->next_wcmd) != 0) - wcmd = (Scsi_Cmnd *) wcmd->next_wcmd; + wcmd = (struct scsi_cmnd *) wcmd->next_wcmd; wcmd->next_wcmd = (char *) cmd; } } -static Scsi_Cmnd *retrieve_from_waiting_list(int to_remove, ncb_p np, Scsi_Cmnd *cmd) +static struct scsi_cmnd *retrieve_from_waiting_list(int to_remove, struct ncb *np, struct scsi_cmnd *cmd) { - Scsi_Cmnd **pcmd = &np->waiting_list; + struct scsi_cmnd **pcmd = &np->waiting_list; while (*pcmd) { if (cmd == *pcmd) { if (to_remove) { - *pcmd = (Scsi_Cmnd *) cmd->next_wcmd; - cmd->next_wcmd = 0; + *pcmd = (struct scsi_cmnd *) cmd->next_wcmd; + cmd->next_wcmd = NULL; } #ifdef DEBUG_WAITING_LIST printk("%s: cmd %lx retrieved from waiting list\n", ncr_name(np), (u_long) cmd); #endif return cmd; } - pcmd = (Scsi_Cmnd **) &(*pcmd)->next_wcmd; + pcmd = (struct scsi_cmnd **) &(*pcmd)->next_wcmd; } - return 0; + return NULL; } -static void process_waiting_list(ncb_p np, int sts) +static void process_waiting_list(struct ncb *np, int sts) { - Scsi_Cmnd *waiting_list, *wcmd; + struct scsi_cmnd *waiting_list, *wcmd; waiting_list = np->waiting_list; - np->waiting_list = 0; + np->waiting_list = NULL; #ifdef DEBUG_WAITING_LIST if (waiting_list) printk("%s: waiting_list=%lx processing sts=%d\n", ncr_name(np), (u_long) waiting_list, sts); #endif while ((wcmd = waiting_list) != 0) { - waiting_list = (Scsi_Cmnd *) wcmd->next_wcmd; - wcmd->next_wcmd = 0; + waiting_list = (struct scsi_cmnd *) wcmd->next_wcmd; + wcmd->next_wcmd = NULL; if (sts == DID_OK) { #ifdef DEBUG_WAITING_LIST printk("%s: cmd %lx trying to requeue\n", ncr_name(np), (u_long) wcmd); @@ -8832,323 +8295,387 @@ static void process_waiting_list(ncb_p np, int sts) #undef next_wcmd -#ifdef SCSI_NCR_PROC_INFO_SUPPORT +static ssize_t show_ncr53c8xx_revision(struct class_device *dev, char *buf) +{ + struct Scsi_Host *host = class_to_shost(dev); + struct host_data *host_data = (struct host_data *)host->hostdata; + + return snprintf(buf, 20, "0x%x\n", host_data->ncb->revision_id); +} + +static struct class_device_attribute ncr53c8xx_revision_attr = { + .attr = { .name = "revision", .mode = S_IRUGO, }, + .show = show_ncr53c8xx_revision, +}; + +static struct class_device_attribute *ncr53c8xx_host_attrs[] = { + &ncr53c8xx_revision_attr, + NULL +}; -/*========================================================================= -** Proc file system stuff +/*========================================================== ** -** A read operation returns profile information. -** A write operation is a control command. -** The string is parsed in the driver code and the command is passed -** to the ncr_usercmd() function. -**========================================================================= +** Boot command line. +** +**========================================================== */ +#ifdef MODULE +char *ncr53c8xx; /* command line passed by insmod */ +module_param(ncr53c8xx, charp, 0); +#endif + +#ifndef MODULE +static int __init ncr53c8xx_setup(char *str) +{ + return sym53c8xx__setup(str); +} -#ifdef SCSI_NCR_USER_COMMAND_SUPPORT +__setup("ncr53c8xx=", ncr53c8xx_setup); +#endif -#define is_digit(c) ((c) >= '0' && (c) <= '9') -#define digit_to_bin(c) ((c) - '0') -#define is_space(c) ((c) == ' ' || (c) == '\t') -static int skip_spaces(char *ptr, int len) +/* + * Host attach and initialisations. + * + * Allocate host data and ncb structure. + * Request IO region and remap MMIO region. + * Do chip initialization. + * If all is OK, install interrupt handling and + * start the timer daemon. + */ +struct Scsi_Host * __init ncr_attach(struct scsi_host_template *tpnt, + int unit, struct ncr_device *device) { - int cnt, c; + struct host_data *host_data; + struct ncb *np = NULL; + struct Scsi_Host *instance = NULL; + u_long flags = 0; + int i; - for (cnt = len; cnt > 0 && (c = *ptr++) && is_space(c); cnt--); + if (!tpnt->name) + tpnt->name = SCSI_NCR_DRIVER_NAME; + if (!tpnt->shost_attrs) + tpnt->shost_attrs = ncr53c8xx_host_attrs; - return (len - cnt); -} + tpnt->queuecommand = ncr53c8xx_queue_command; + tpnt->slave_configure = ncr53c8xx_slave_configure; + tpnt->slave_alloc = ncr53c8xx_slave_alloc; + tpnt->eh_bus_reset_handler = ncr53c8xx_bus_reset; + tpnt->can_queue = SCSI_NCR_CAN_QUEUE; + tpnt->this_id = 7; + tpnt->sg_tablesize = SCSI_NCR_SG_TABLESIZE; + tpnt->cmd_per_lun = SCSI_NCR_CMD_PER_LUN; + tpnt->use_clustering = ENABLE_CLUSTERING; -static int get_int_arg(char *ptr, int len, u_long *pv) -{ - int cnt, c; - u_long v; + if (device->differential) + driver_setup.diff_support = device->differential; - for (v = 0, cnt = len; cnt > 0 && (c = *ptr++) && is_digit(c); cnt--) { - v = (v * 10) + digit_to_bin(c); - } + printk(KERN_INFO "ncr53c720-%d: rev 0x%x irq %d\n", + unit, device->chip.revision_id, device->slot.irq); - if (pv) - *pv = v; + instance = scsi_host_alloc(tpnt, sizeof(*host_data)); + if (!instance) + goto attach_error; + host_data = (struct host_data *) instance->hostdata; - return (len - cnt); -} + np = __m_calloc_dma(device->dev, sizeof(struct ncb), "NCB"); + if (!np) + goto attach_error; + spin_lock_init(&np->smp_lock); + np->dev = device->dev; + np->p_ncb = vtobus(np); + host_data->ncb = np; -static int is_keyword(char *ptr, int len, char *verb) -{ - int verb_len = strlen(verb); + np->ccb = m_calloc_dma(sizeof(struct ccb), "CCB"); + if (!np->ccb) + goto attach_error; + + /* Store input information in the host data structure. */ + np->unit = unit; + np->verbose = driver_setup.verbose; + sprintf(np->inst_name, "ncr53c720-%d", np->unit); + np->revision_id = device->chip.revision_id; + np->features = device->chip.features; + np->clock_divn = device->chip.nr_divisor; + np->maxoffs = device->chip.offset_max; + np->maxburst = device->chip.burst_max; + np->myaddr = device->host_id; + + /* Allocate SCRIPTS areas. */ + np->script0 = m_calloc_dma(sizeof(struct script), "SCRIPT"); + if (!np->script0) + goto attach_error; + np->scripth0 = m_calloc_dma(sizeof(struct scripth), "SCRIPTH"); + if (!np->scripth0) + goto attach_error; + + init_timer(&np->timer); + np->timer.data = (unsigned long) np; + np->timer.function = ncr53c8xx_timeout; - if (len >= strlen(verb) && !memcmp(verb, ptr, verb_len)) - return verb_len; + /* Try to map the controller chip to virtual and physical memory. */ + + np->paddr = device->slot.base; + np->paddr2 = (np->features & FE_RAM) ? device->slot.base_2 : 0; + + if (device->slot.base_v) + np->vaddr = device->slot.base_v; else - return 0; + np->vaddr = ioremap(device->slot.base_c, 128); -} + if (!np->vaddr) { + printk(KERN_ERR + "%s: can't map memory mapped IO region\n",ncr_name(np)); + goto attach_error; + } else { + if (bootverbose > 1) + printk(KERN_INFO + "%s: using memory mapped IO at virtual address 0x%lx\n", ncr_name(np), (u_long) np->vaddr); + } + + /* Make the controller's registers available. Now the INB INW INL + * OUTB OUTW OUTL macros can be used safely. + */ -#define SKIP_SPACES(min_spaces) \ - if ((arg_len = skip_spaces(ptr, len)) < (min_spaces)) \ - return -EINVAL; \ - ptr += arg_len; len -= arg_len; + np->reg = (struct ncr_reg __iomem *)np->vaddr; -#define GET_INT_ARG(v) \ - if (!(arg_len = get_int_arg(ptr, len, &(v)))) \ - return -EINVAL; \ - ptr += arg_len; len -= arg_len; + /* Do chip dependent initialization. */ + ncr_prepare_setting(np); + if (np->paddr2 && sizeof(struct script) > 4096) { + np->paddr2 = 0; + printk(KERN_WARNING "%s: script too large, NOT using on chip RAM.\n", + ncr_name(np)); + } -/* -** Parse a control command -*/ + instance->max_channel = 0; + instance->this_id = np->myaddr; + instance->max_id = np->maxwide ? 16 : 8; + instance->max_lun = SCSI_NCR_MAX_LUN; + instance->base = (unsigned long) np->reg; + instance->irq = device->slot.irq; + instance->unique_id = device->slot.base; + instance->dma_channel = 0; + instance->cmd_per_lun = MAX_TAGS; + instance->can_queue = (MAX_START-4); + /* This can happen if you forget to call ncr53c8xx_init from + * your module_init */ + BUG_ON(!ncr53c8xx_transport_template); + instance->transportt = ncr53c8xx_transport_template; -static int ncr_user_command(ncb_p np, char *buffer, int length) -{ - char *ptr = buffer; - int len = length; - struct usrcmd *uc = &np->user; - int arg_len; - u_long target; - - bzero(uc, sizeof(*uc)); - - if (len > 0 && ptr[len-1] == '\n') - --len; - - if ((arg_len = is_keyword(ptr, len, "setsync")) != 0) - uc->cmd = UC_SETSYNC; - else if ((arg_len = is_keyword(ptr, len, "settags")) != 0) - uc->cmd = UC_SETTAGS; - else if ((arg_len = is_keyword(ptr, len, "setorder")) != 0) - uc->cmd = UC_SETORDER; - else if ((arg_len = is_keyword(ptr, len, "setverbose")) != 0) - uc->cmd = UC_SETVERBOSE; - else if ((arg_len = is_keyword(ptr, len, "setwide")) != 0) - uc->cmd = UC_SETWIDE; - else if ((arg_len = is_keyword(ptr, len, "setdebug")) != 0) - uc->cmd = UC_SETDEBUG; - else if ((arg_len = is_keyword(ptr, len, "setflag")) != 0) - uc->cmd = UC_SETFLAG; - else - arg_len = 0; + /* Patch script to physical addresses */ + ncr_script_fill(&script0, &scripth0); -#ifdef DEBUG_PROC_INFO -printk("ncr_user_command: arg_len=%d, cmd=%ld\n", arg_len, uc->cmd); -#endif + np->scripth = np->scripth0; + np->p_scripth = vtobus(np->scripth); + np->p_script = (np->paddr2) ? np->paddr2 : vtobus(np->script0); - if (!arg_len) - return -EINVAL; - ptr += arg_len; len -= arg_len; - - switch(uc->cmd) { - case UC_SETSYNC: - case UC_SETTAGS: - case UC_SETWIDE: - case UC_SETFLAG: - SKIP_SPACES(1); - if ((arg_len = is_keyword(ptr, len, "all")) != 0) { - ptr += arg_len; len -= arg_len; - uc->target = ~0; - } else { - GET_INT_ARG(target); - uc->target = (1<script0, sizeof(struct script)); + ncr_script_copy_and_bind(np, (ncrcmd *) &scripth0, + (ncrcmd *) np->scripth0, sizeof(struct scripth)); + np->ccb->p_ccb = vtobus (np->ccb); + + /* Patch the script for LED support. */ + + if (np->features & FE_LED0) { + np->script0->idle[0] = + cpu_to_scr(SCR_REG_REG(gpreg, SCR_OR, 0x01)); + np->script0->reselected[0] = + cpu_to_scr(SCR_REG_REG(gpreg, SCR_AND, 0xfe)); + np->script0->start[0] = + cpu_to_scr(SCR_REG_REG(gpreg, SCR_AND, 0xfe)); } - switch(uc->cmd) { - case UC_SETVERBOSE: - case UC_SETSYNC: - case UC_SETTAGS: - case UC_SETWIDE: - SKIP_SPACES(1); - GET_INT_ARG(uc->data); -#ifdef DEBUG_PROC_INFO -printk("ncr_user_command: data=%ld\n", uc->data); -#endif - break; - case UC_SETORDER: - SKIP_SPACES(1); - if ((arg_len = is_keyword(ptr, len, "simple"))) - uc->data = M_SIMPLE_TAG; - else if ((arg_len = is_keyword(ptr, len, "ordered"))) - uc->data = M_ORDERED_TAG; - else if ((arg_len = is_keyword(ptr, len, "default"))) - uc->data = 0; - else - return -EINVAL; - break; - case UC_SETDEBUG: - while (len > 0) { - SKIP_SPACES(1); - if ((arg_len = is_keyword(ptr, len, "alloc"))) - uc->data |= DEBUG_ALLOC; - else if ((arg_len = is_keyword(ptr, len, "phase"))) - uc->data |= DEBUG_PHASE; - else if ((arg_len = is_keyword(ptr, len, "queue"))) - uc->data |= DEBUG_QUEUE; - else if ((arg_len = is_keyword(ptr, len, "result"))) - uc->data |= DEBUG_RESULT; - else if ((arg_len = is_keyword(ptr, len, "scatter"))) - uc->data |= DEBUG_SCATTER; - else if ((arg_len = is_keyword(ptr, len, "script"))) - uc->data |= DEBUG_SCRIPT; - else if ((arg_len = is_keyword(ptr, len, "tiny"))) - uc->data |= DEBUG_TINY; - else if ((arg_len = is_keyword(ptr, len, "timing"))) - uc->data |= DEBUG_TIMING; - else if ((arg_len = is_keyword(ptr, len, "nego"))) - uc->data |= DEBUG_NEGO; - else if ((arg_len = is_keyword(ptr, len, "tags"))) - uc->data |= DEBUG_TAGS; - else - return -EINVAL; - ptr += arg_len; len -= arg_len; - } -#ifdef DEBUG_PROC_INFO -printk("ncr_user_command: data=%ld\n", uc->data); -#endif - break; - case UC_SETFLAG: - while (len > 0) { - SKIP_SPACES(1); - if ((arg_len = is_keyword(ptr, len, "trace"))) - uc->data |= UF_TRACE; - else if ((arg_len = is_keyword(ptr, len, "no_disc"))) - uc->data |= UF_NODISC; - else - return -EINVAL; - ptr += arg_len; len -= arg_len; - } - break; - default: - break; + /* + * Look for the target control block of this nexus. + * For i = 0 to 3 + * JUMP ^ IFTRUE (MASK (i, 3)), @(next_lcb) + */ + for (i = 0 ; i < 4 ; i++) { + np->jump_tcb[i].l_cmd = + cpu_to_scr((SCR_JUMP ^ IFTRUE (MASK (i, 3)))); + np->jump_tcb[i].l_paddr = + cpu_to_scr(NCB_SCRIPTH_PHYS (np, bad_target)); } - if (len) - return -EINVAL; - else { - unsigned long flags; + ncr_chip_reset(np, 100); - NCR_LOCK_NCB(np, flags); - ncr_usercmd (np); - NCR_UNLOCK_NCB(np, flags); - } - return length; -} + /* Now check the cache handling of the chipset. */ -#endif /* SCSI_NCR_USER_COMMAND_SUPPORT */ + if (ncr_snooptest(np)) { + printk(KERN_ERR "CACHE INCORRECTLY CONFIGURED.\n"); + goto attach_error; + } + /* Install the interrupt handler. */ + np->irq = device->slot.irq; -#ifdef SCSI_NCR_USER_INFO_SUPPORT -/* -** Copy formatted information into the input buffer. -*/ + /* Initialize the fixed part of the default ccb. */ + ncr_init_ccb(np, np->ccb); -static int ncr_host_info(ncb_p np, char *ptr, off_t offset, int len) -{ - struct info_str info; + /* + * After SCSI devices have been opened, we cannot reset the bus + * safely, so we do it here. Interrupt handler does the real work. + * Process the reset exception if interrupts are not enabled yet. + * Then enable disconnects. + */ + spin_lock_irqsave(&np->smp_lock, flags); + if (ncr_reset_scsi_bus(np, 0, driver_setup.settle_delay) != 0) { + printk(KERN_ERR "%s: FATAL ERROR: CHECK SCSI BUS - CABLES, TERMINATION, DEVICE POWER etc.!\n", ncr_name(np)); - info.buffer = ptr; - info.length = len; - info.offset = offset; - info.pos = 0; + spin_unlock_irqrestore(&np->smp_lock, flags); + goto attach_error; + } + ncr_exception(np); - copy_info(&info, " Chip NCR53C%s, device id 0x%x, " - "revision id 0x%x\n", - np->chip_name, np->device_id, np->revision_id); - copy_info(&info, " On PCI bus %d, device %d, function %d, IRQ %d\n", - np->bus, (np->device_fn & 0xf8) >> 3, np->device_fn & 7, - (int) np->irq); - copy_info(&info, " Synchronous period factor %d, " - "max commands per lun %d\n", - (int) np->minsync, MAX_TAGS); + np->disc = 1; - if (driver_setup.debug || driver_setup.verbose > 1) { - copy_info(&info, " Debug flags 0x%x, verbosity level %d\n", - driver_setup.debug, driver_setup.verbose); + /* + * The middle-level SCSI driver does not wait for devices to settle. + * Wait synchronously if more than 2 seconds. + */ + if (driver_setup.settle_delay > 2) { + printk(KERN_INFO "%s: waiting %d seconds for scsi devices to settle...\n", + ncr_name(np), driver_setup.settle_delay); + mdelay(1000 * driver_setup.settle_delay); } - return info.pos > info.offset? info.pos - info.offset : 0; -} + /* start the timeout daemon */ + np->lasttime=0; + ncr_timeout (np); + + /* use SIMPLE TAG messages by default */ +#ifdef SCSI_NCR_ALWAYS_SIMPLE_TAG + np->order = SIMPLE_QUEUE_TAG; +#endif -#endif /* SCSI_NCR_USER_INFO_SUPPORT */ + spin_unlock_irqrestore(&np->smp_lock, flags); + + return instance; + + attach_error: + if (!instance) + return NULL; + printk(KERN_INFO "%s: detaching...\n", ncr_name(np)); + if (!np) + goto unregister; + if (np->scripth0) + m_free_dma(np->scripth0, sizeof(struct scripth), "SCRIPTH"); + if (np->script0) + m_free_dma(np->script0, sizeof(struct script), "SCRIPT"); + if (np->ccb) + m_free_dma(np->ccb, sizeof(struct ccb), "CCB"); + m_free_dma(np, sizeof(struct ncb), "NCB"); + host_data->ncb = NULL; + + unregister: + scsi_host_put(instance); + + return NULL; +} -/* -** Entry point of the scsi proc fs of the driver. -** - func = 0 means read (returns profile data) -** - func = 1 means write (parse user control command) -*/ -static int ncr53c8xx_proc_info(struct Scsi_Host *host, char *buffer, char **start, off_t offset, - int length, int func) +int ncr53c8xx_release(struct Scsi_Host *host) { struct host_data *host_data; - ncb_p ncb = 0; - int retv; - -#ifdef DEBUG_PROC_INFO -printk("ncr53c8xx_proc_info: hostno=%d, func=%d\n", host->host_no, func); +#ifdef DEBUG_NCR53C8XX + printk("ncr53c8xx: release\n"); #endif + if (!host) + return 1; + host_data = (struct host_data *)host->hostdata; + if (host_data && host_data->ncb) + ncr_detach(host_data->ncb); + return 1; +} + +static void ncr53c8xx_set_period(struct scsi_target *starget, int period) +{ + struct Scsi_Host *shost = dev_to_shost(starget->dev.parent); + struct ncb *np = ((struct host_data *)shost->hostdata)->ncb; + struct tcb *tp = &np->target[starget->id]; - host_data = (struct host_data *) host->hostdata; - ncb = host_data->ncb; + if (period > np->maxsync) + period = np->maxsync; + else if (period < np->minsync) + period = np->minsync; - if (func) { -#ifdef SCSI_NCR_USER_COMMAND_SUPPORT - retv = ncr_user_command(ncb, buffer, length); -#else - retv = -EINVAL; -#endif - } - else { - if (start) - *start = buffer; -#ifdef SCSI_NCR_USER_INFO_SUPPORT - retv = ncr_host_info(ncb, buffer, offset, length); -#else - retv = -EINVAL; -#endif - } + tp->usrsync = period; - return retv; + ncr_negotiate(np, tp); } -/*========================================================================= -** End of proc file system stuff -**========================================================================= -*/ -#endif +static void ncr53c8xx_set_offset(struct scsi_target *starget, int offset) +{ + struct Scsi_Host *shost = dev_to_shost(starget->dev.parent); + struct ncb *np = ((struct host_data *)shost->hostdata)->ncb; + struct tcb *tp = &np->target[starget->id]; + if (offset > np->maxoffs) + offset = np->maxoffs; + else if (offset < 0) + offset = 0; -/*========================================================== -** -** Boot command line. -** -**========================================================== -*/ -#ifdef MODULE -char *ncr53c8xx = 0; /* command line passed by insmod */ -MODULE_PARM(ncr53c8xx, "s"); -#endif + tp->maxoffs = offset; -int __init ncr53c8xx_setup(char *str) + ncr_negotiate(np, tp); +} + +static void ncr53c8xx_set_width(struct scsi_target *starget, int width) { - return sym53c8xx__setup(str); + struct Scsi_Host *shost = dev_to_shost(starget->dev.parent); + struct ncb *np = ((struct host_data *)shost->hostdata)->ncb; + struct tcb *tp = &np->target[starget->id]; + + if (width > np->maxwide) + width = np->maxwide; + else if (width < 0) + width = 0; + + tp->usrwide = width; + + ncr_negotiate(np, tp); } -#ifndef MODULE -__setup("ncr53c8xx=", ncr53c8xx_setup); -#endif +static void ncr53c8xx_get_signalling(struct Scsi_Host *shost) +{ + struct ncb *np = ((struct host_data *)shost->hostdata)->ncb; + enum spi_signal_type type; -/*========================================================== -** -** Entry point for info() function -** -**========================================================== -*/ -const char *ncr53c8xx_info (struct Scsi_Host *host) + switch (np->scsi_mode) { + case SMODE_SE: + type = SPI_SIGNAL_SE; + break; + case SMODE_HVD: + type = SPI_SIGNAL_HVD; + break; + default: + type = SPI_SIGNAL_UNKNOWN; + break; + } + spi_signalling(shost) = type; +} + +static struct spi_function_template ncr53c8xx_transport_functions = { + .set_period = ncr53c8xx_set_period, + .show_period = 1, + .set_offset = ncr53c8xx_set_offset, + .show_offset = 1, + .set_width = ncr53c8xx_set_width, + .show_width = 1, + .get_signalling = ncr53c8xx_get_signalling, +}; + +int __init ncr53c8xx_init(void) +{ + ncr53c8xx_transport_template = spi_attach_transport(&ncr53c8xx_transport_functions); + if (!ncr53c8xx_transport_template) + return -ENODEV; + return 0; +} + +void ncr53c8xx_exit(void) { - return SCSI_NCR_DRIVER_NAME; + spi_release_transport(ncr53c8xx_transport_template); }