162306a36Sopenharmony_ci/* SPDX-License-Identifier: GPL-2.0-or-later */ 262306a36Sopenharmony_ci/* 362306a36Sopenharmony_ci * Device driver for the SYMBIOS/LSILOGIC 53C8XX and 53C1010 family 462306a36Sopenharmony_ci * of PCI-SCSI IO processors. 562306a36Sopenharmony_ci * 662306a36Sopenharmony_ci * Copyright (C) 1999-2001 Gerard Roudier <groudier@free.fr> 762306a36Sopenharmony_ci * 862306a36Sopenharmony_ci * This driver is derived from the Linux sym53c8xx driver. 962306a36Sopenharmony_ci * Copyright (C) 1998-2000 Gerard Roudier 1062306a36Sopenharmony_ci * 1162306a36Sopenharmony_ci * The sym53c8xx driver is derived from the ncr53c8xx driver that had been 1262306a36Sopenharmony_ci * a port of the FreeBSD ncr driver to Linux-1.2.13. 1362306a36Sopenharmony_ci * 1462306a36Sopenharmony_ci * The original ncr driver has been written for 386bsd and FreeBSD by 1562306a36Sopenharmony_ci * Wolfgang Stanglmeier <wolf@cologne.de> 1662306a36Sopenharmony_ci * Stefan Esser <se@mi.Uni-Koeln.de> 1762306a36Sopenharmony_ci * Copyright (C) 1994 Wolfgang Stanglmeier 1862306a36Sopenharmony_ci * 1962306a36Sopenharmony_ci * Other major contributions: 2062306a36Sopenharmony_ci * 2162306a36Sopenharmony_ci * NVRAM detection and reading. 2262306a36Sopenharmony_ci * Copyright (C) 1997 Richard Waltham <dormouse@farsrobt.demon.co.uk> 2362306a36Sopenharmony_ci * 2462306a36Sopenharmony_ci *----------------------------------------------------------------------------- 2562306a36Sopenharmony_ci */ 2662306a36Sopenharmony_ci 2762306a36Sopenharmony_ci#include <linux/gfp.h> 2862306a36Sopenharmony_ci 2962306a36Sopenharmony_ci#ifndef SYM_HIPD_H 3062306a36Sopenharmony_ci#define SYM_HIPD_H 3162306a36Sopenharmony_ci 3262306a36Sopenharmony_ci/* 3362306a36Sopenharmony_ci * Generic driver options. 3462306a36Sopenharmony_ci * 3562306a36Sopenharmony_ci * They may be defined in platform specific headers, if they 3662306a36Sopenharmony_ci * are useful. 3762306a36Sopenharmony_ci * 3862306a36Sopenharmony_ci * SYM_OPT_HANDLE_DEVICE_QUEUEING 3962306a36Sopenharmony_ci * When this option is set, the driver will use a queue per 4062306a36Sopenharmony_ci * device and handle QUEUE FULL status requeuing internally. 4162306a36Sopenharmony_ci * 4262306a36Sopenharmony_ci * SYM_OPT_LIMIT_COMMAND_REORDERING 4362306a36Sopenharmony_ci * When this option is set, the driver tries to limit tagged 4462306a36Sopenharmony_ci * command reordering to some reasonable value. 4562306a36Sopenharmony_ci * (set for Linux) 4662306a36Sopenharmony_ci */ 4762306a36Sopenharmony_ci#if 0 4862306a36Sopenharmony_ci#define SYM_OPT_HANDLE_DEVICE_QUEUEING 4962306a36Sopenharmony_ci#define SYM_OPT_LIMIT_COMMAND_REORDERING 5062306a36Sopenharmony_ci#endif 5162306a36Sopenharmony_ci 5262306a36Sopenharmony_ci/* 5362306a36Sopenharmony_ci * Active debugging tags and verbosity. 5462306a36Sopenharmony_ci * Both DEBUG_FLAGS and sym_verbose can be redefined 5562306a36Sopenharmony_ci * by the platform specific code to something else. 5662306a36Sopenharmony_ci */ 5762306a36Sopenharmony_ci#define DEBUG_ALLOC (0x0001) 5862306a36Sopenharmony_ci#define DEBUG_PHASE (0x0002) 5962306a36Sopenharmony_ci#define DEBUG_POLL (0x0004) 6062306a36Sopenharmony_ci#define DEBUG_QUEUE (0x0008) 6162306a36Sopenharmony_ci#define DEBUG_RESULT (0x0010) 6262306a36Sopenharmony_ci#define DEBUG_SCATTER (0x0020) 6362306a36Sopenharmony_ci#define DEBUG_SCRIPT (0x0040) 6462306a36Sopenharmony_ci#define DEBUG_TINY (0x0080) 6562306a36Sopenharmony_ci#define DEBUG_TIMING (0x0100) 6662306a36Sopenharmony_ci#define DEBUG_NEGO (0x0200) 6762306a36Sopenharmony_ci#define DEBUG_TAGS (0x0400) 6862306a36Sopenharmony_ci#define DEBUG_POINTER (0x0800) 6962306a36Sopenharmony_ci 7062306a36Sopenharmony_ci#ifndef DEBUG_FLAGS 7162306a36Sopenharmony_ci#define DEBUG_FLAGS (0x0000) 7262306a36Sopenharmony_ci#endif 7362306a36Sopenharmony_ci 7462306a36Sopenharmony_ci#ifndef sym_verbose 7562306a36Sopenharmony_ci#define sym_verbose (np->verbose) 7662306a36Sopenharmony_ci#endif 7762306a36Sopenharmony_ci 7862306a36Sopenharmony_ci/* 7962306a36Sopenharmony_ci * These ones should have been already defined. 8062306a36Sopenharmony_ci */ 8162306a36Sopenharmony_ci#ifndef assert 8262306a36Sopenharmony_ci#define assert(expression) { \ 8362306a36Sopenharmony_ci if (!(expression)) { \ 8462306a36Sopenharmony_ci (void)panic( \ 8562306a36Sopenharmony_ci "assertion \"%s\" failed: file \"%s\", line %d\n", \ 8662306a36Sopenharmony_ci #expression, \ 8762306a36Sopenharmony_ci __FILE__, __LINE__); \ 8862306a36Sopenharmony_ci } \ 8962306a36Sopenharmony_ci} 9062306a36Sopenharmony_ci#endif 9162306a36Sopenharmony_ci 9262306a36Sopenharmony_ci/* 9362306a36Sopenharmony_ci * Number of tasks per device we want to handle. 9462306a36Sopenharmony_ci */ 9562306a36Sopenharmony_ci#if SYM_CONF_MAX_TAG_ORDER > 8 9662306a36Sopenharmony_ci#error "more than 256 tags per logical unit not allowed." 9762306a36Sopenharmony_ci#endif 9862306a36Sopenharmony_ci#define SYM_CONF_MAX_TASK (1<<SYM_CONF_MAX_TAG_ORDER) 9962306a36Sopenharmony_ci 10062306a36Sopenharmony_ci/* 10162306a36Sopenharmony_ci * Donnot use more tasks that we can handle. 10262306a36Sopenharmony_ci */ 10362306a36Sopenharmony_ci#ifndef SYM_CONF_MAX_TAG 10462306a36Sopenharmony_ci#define SYM_CONF_MAX_TAG SYM_CONF_MAX_TASK 10562306a36Sopenharmony_ci#endif 10662306a36Sopenharmony_ci#if SYM_CONF_MAX_TAG > SYM_CONF_MAX_TASK 10762306a36Sopenharmony_ci#undef SYM_CONF_MAX_TAG 10862306a36Sopenharmony_ci#define SYM_CONF_MAX_TAG SYM_CONF_MAX_TASK 10962306a36Sopenharmony_ci#endif 11062306a36Sopenharmony_ci 11162306a36Sopenharmony_ci/* 11262306a36Sopenharmony_ci * This one means 'NO TAG for this job' 11362306a36Sopenharmony_ci */ 11462306a36Sopenharmony_ci#define NO_TAG (256) 11562306a36Sopenharmony_ci 11662306a36Sopenharmony_ci/* 11762306a36Sopenharmony_ci * Number of SCSI targets. 11862306a36Sopenharmony_ci */ 11962306a36Sopenharmony_ci#if SYM_CONF_MAX_TARGET > 16 12062306a36Sopenharmony_ci#error "more than 16 targets not allowed." 12162306a36Sopenharmony_ci#endif 12262306a36Sopenharmony_ci 12362306a36Sopenharmony_ci/* 12462306a36Sopenharmony_ci * Number of logical units per target. 12562306a36Sopenharmony_ci */ 12662306a36Sopenharmony_ci#if SYM_CONF_MAX_LUN > 64 12762306a36Sopenharmony_ci#error "more than 64 logical units per target not allowed." 12862306a36Sopenharmony_ci#endif 12962306a36Sopenharmony_ci 13062306a36Sopenharmony_ci/* 13162306a36Sopenharmony_ci * Asynchronous pre-scaler (ns). Shall be 40 for 13262306a36Sopenharmony_ci * the SCSI timings to be compliant. 13362306a36Sopenharmony_ci */ 13462306a36Sopenharmony_ci#define SYM_CONF_MIN_ASYNC (40) 13562306a36Sopenharmony_ci 13662306a36Sopenharmony_ci 13762306a36Sopenharmony_ci/* 13862306a36Sopenharmony_ci * MEMORY ALLOCATOR. 13962306a36Sopenharmony_ci */ 14062306a36Sopenharmony_ci 14162306a36Sopenharmony_ci#define SYM_MEM_WARN 1 /* Warn on failed operations */ 14262306a36Sopenharmony_ci 14362306a36Sopenharmony_ci#define SYM_MEM_PAGE_ORDER 0 /* 1 PAGE maximum */ 14462306a36Sopenharmony_ci#define SYM_MEM_CLUSTER_SHIFT (PAGE_SHIFT+SYM_MEM_PAGE_ORDER) 14562306a36Sopenharmony_ci#define SYM_MEM_FREE_UNUSED /* Free unused pages immediately */ 14662306a36Sopenharmony_ci/* 14762306a36Sopenharmony_ci * Shortest memory chunk is (1<<SYM_MEM_SHIFT), currently 16. 14862306a36Sopenharmony_ci * Actual allocations happen as SYM_MEM_CLUSTER_SIZE sized. 14962306a36Sopenharmony_ci * (1 PAGE at a time is just fine). 15062306a36Sopenharmony_ci */ 15162306a36Sopenharmony_ci#define SYM_MEM_SHIFT 4 15262306a36Sopenharmony_ci#define SYM_MEM_CLUSTER_SIZE (1UL << SYM_MEM_CLUSTER_SHIFT) 15362306a36Sopenharmony_ci#define SYM_MEM_CLUSTER_MASK (SYM_MEM_CLUSTER_SIZE-1) 15462306a36Sopenharmony_ci 15562306a36Sopenharmony_ci/* 15662306a36Sopenharmony_ci * Number of entries in the START and DONE queues. 15762306a36Sopenharmony_ci * 15862306a36Sopenharmony_ci * We limit to 1 PAGE in order to succeed allocation of 15962306a36Sopenharmony_ci * these queues. Each entry is 8 bytes long (2 DWORDS). 16062306a36Sopenharmony_ci */ 16162306a36Sopenharmony_ci#ifdef SYM_CONF_MAX_START 16262306a36Sopenharmony_ci#define SYM_CONF_MAX_QUEUE (SYM_CONF_MAX_START+2) 16362306a36Sopenharmony_ci#else 16462306a36Sopenharmony_ci#define SYM_CONF_MAX_QUEUE (7*SYM_CONF_MAX_TASK+2) 16562306a36Sopenharmony_ci#define SYM_CONF_MAX_START (SYM_CONF_MAX_QUEUE-2) 16662306a36Sopenharmony_ci#endif 16762306a36Sopenharmony_ci 16862306a36Sopenharmony_ci#if SYM_CONF_MAX_QUEUE > SYM_MEM_CLUSTER_SIZE/8 16962306a36Sopenharmony_ci#undef SYM_CONF_MAX_QUEUE 17062306a36Sopenharmony_ci#define SYM_CONF_MAX_QUEUE (SYM_MEM_CLUSTER_SIZE/8) 17162306a36Sopenharmony_ci#undef SYM_CONF_MAX_START 17262306a36Sopenharmony_ci#define SYM_CONF_MAX_START (SYM_CONF_MAX_QUEUE-2) 17362306a36Sopenharmony_ci#endif 17462306a36Sopenharmony_ci 17562306a36Sopenharmony_ci/* 17662306a36Sopenharmony_ci * For this one, we want a short name :-) 17762306a36Sopenharmony_ci */ 17862306a36Sopenharmony_ci#define MAX_QUEUE SYM_CONF_MAX_QUEUE 17962306a36Sopenharmony_ci 18062306a36Sopenharmony_ci/* 18162306a36Sopenharmony_ci * Common definitions for both bus space based and legacy IO methods. 18262306a36Sopenharmony_ci */ 18362306a36Sopenharmony_ci 18462306a36Sopenharmony_ci#define INB_OFF(np, o) ioread8(np->s.ioaddr + (o)) 18562306a36Sopenharmony_ci#define INW_OFF(np, o) ioread16(np->s.ioaddr + (o)) 18662306a36Sopenharmony_ci#define INL_OFF(np, o) ioread32(np->s.ioaddr + (o)) 18762306a36Sopenharmony_ci 18862306a36Sopenharmony_ci#define OUTB_OFF(np, o, val) iowrite8((val), np->s.ioaddr + (o)) 18962306a36Sopenharmony_ci#define OUTW_OFF(np, o, val) iowrite16((val), np->s.ioaddr + (o)) 19062306a36Sopenharmony_ci#define OUTL_OFF(np, o, val) iowrite32((val), np->s.ioaddr + (o)) 19162306a36Sopenharmony_ci 19262306a36Sopenharmony_ci#define INB(np, r) INB_OFF(np, offsetof(struct sym_reg, r)) 19362306a36Sopenharmony_ci#define INW(np, r) INW_OFF(np, offsetof(struct sym_reg, r)) 19462306a36Sopenharmony_ci#define INL(np, r) INL_OFF(np, offsetof(struct sym_reg, r)) 19562306a36Sopenharmony_ci 19662306a36Sopenharmony_ci#define OUTB(np, r, v) OUTB_OFF(np, offsetof(struct sym_reg, r), (v)) 19762306a36Sopenharmony_ci#define OUTW(np, r, v) OUTW_OFF(np, offsetof(struct sym_reg, r), (v)) 19862306a36Sopenharmony_ci#define OUTL(np, r, v) OUTL_OFF(np, offsetof(struct sym_reg, r), (v)) 19962306a36Sopenharmony_ci 20062306a36Sopenharmony_ci#define OUTONB(np, r, m) OUTB(np, r, INB(np, r) | (m)) 20162306a36Sopenharmony_ci#define OUTOFFB(np, r, m) OUTB(np, r, INB(np, r) & ~(m)) 20262306a36Sopenharmony_ci#define OUTONW(np, r, m) OUTW(np, r, INW(np, r) | (m)) 20362306a36Sopenharmony_ci#define OUTOFFW(np, r, m) OUTW(np, r, INW(np, r) & ~(m)) 20462306a36Sopenharmony_ci#define OUTONL(np, r, m) OUTL(np, r, INL(np, r) | (m)) 20562306a36Sopenharmony_ci#define OUTOFFL(np, r, m) OUTL(np, r, INL(np, r) & ~(m)) 20662306a36Sopenharmony_ci 20762306a36Sopenharmony_ci/* 20862306a36Sopenharmony_ci * We normally want the chip to have a consistent view 20962306a36Sopenharmony_ci * of driver internal data structures when we restart it. 21062306a36Sopenharmony_ci * Thus these macros. 21162306a36Sopenharmony_ci */ 21262306a36Sopenharmony_ci#define OUTL_DSP(np, v) \ 21362306a36Sopenharmony_ci do { \ 21462306a36Sopenharmony_ci MEMORY_WRITE_BARRIER(); \ 21562306a36Sopenharmony_ci OUTL(np, nc_dsp, (v)); \ 21662306a36Sopenharmony_ci } while (0) 21762306a36Sopenharmony_ci 21862306a36Sopenharmony_ci#define OUTONB_STD() \ 21962306a36Sopenharmony_ci do { \ 22062306a36Sopenharmony_ci MEMORY_WRITE_BARRIER(); \ 22162306a36Sopenharmony_ci OUTONB(np, nc_dcntl, (STD|NOCOM)); \ 22262306a36Sopenharmony_ci } while (0) 22362306a36Sopenharmony_ci 22462306a36Sopenharmony_ci/* 22562306a36Sopenharmony_ci * Command control block states. 22662306a36Sopenharmony_ci */ 22762306a36Sopenharmony_ci#define HS_IDLE (0) 22862306a36Sopenharmony_ci#define HS_BUSY (1) 22962306a36Sopenharmony_ci#define HS_NEGOTIATE (2) /* sync/wide data transfer*/ 23062306a36Sopenharmony_ci#define HS_DISCONNECT (3) /* Disconnected by target */ 23162306a36Sopenharmony_ci#define HS_WAIT (4) /* waiting for resource */ 23262306a36Sopenharmony_ci 23362306a36Sopenharmony_ci#define HS_DONEMASK (0x80) 23462306a36Sopenharmony_ci#define HS_COMPLETE (4|HS_DONEMASK) 23562306a36Sopenharmony_ci#define HS_SEL_TIMEOUT (5|HS_DONEMASK) /* Selection timeout */ 23662306a36Sopenharmony_ci#define HS_UNEXPECTED (6|HS_DONEMASK) /* Unexpected disconnect */ 23762306a36Sopenharmony_ci#define HS_COMP_ERR (7|HS_DONEMASK) /* Completed with error */ 23862306a36Sopenharmony_ci 23962306a36Sopenharmony_ci/* 24062306a36Sopenharmony_ci * Software Interrupt Codes 24162306a36Sopenharmony_ci */ 24262306a36Sopenharmony_ci#define SIR_BAD_SCSI_STATUS (1) 24362306a36Sopenharmony_ci#define SIR_SEL_ATN_NO_MSG_OUT (2) 24462306a36Sopenharmony_ci#define SIR_MSG_RECEIVED (3) 24562306a36Sopenharmony_ci#define SIR_MSG_WEIRD (4) 24662306a36Sopenharmony_ci#define SIR_NEGO_FAILED (5) 24762306a36Sopenharmony_ci#define SIR_NEGO_PROTO (6) 24862306a36Sopenharmony_ci#define SIR_SCRIPT_STOPPED (7) 24962306a36Sopenharmony_ci#define SIR_REJECT_TO_SEND (8) 25062306a36Sopenharmony_ci#define SIR_SWIDE_OVERRUN (9) 25162306a36Sopenharmony_ci#define SIR_SODL_UNDERRUN (10) 25262306a36Sopenharmony_ci#define SIR_RESEL_NO_MSG_IN (11) 25362306a36Sopenharmony_ci#define SIR_RESEL_NO_IDENTIFY (12) 25462306a36Sopenharmony_ci#define SIR_RESEL_BAD_LUN (13) 25562306a36Sopenharmony_ci#define SIR_TARGET_SELECTED (14) 25662306a36Sopenharmony_ci#define SIR_RESEL_BAD_I_T_L (15) 25762306a36Sopenharmony_ci#define SIR_RESEL_BAD_I_T_L_Q (16) 25862306a36Sopenharmony_ci#define SIR_ABORT_SENT (17) 25962306a36Sopenharmony_ci#define SIR_RESEL_ABORTED (18) 26062306a36Sopenharmony_ci#define SIR_MSG_OUT_DONE (19) 26162306a36Sopenharmony_ci#define SIR_COMPLETE_ERROR (20) 26262306a36Sopenharmony_ci#define SIR_DATA_OVERRUN (21) 26362306a36Sopenharmony_ci#define SIR_BAD_PHASE (22) 26462306a36Sopenharmony_ci#if SYM_CONF_DMA_ADDRESSING_MODE == 2 26562306a36Sopenharmony_ci#define SIR_DMAP_DIRTY (23) 26662306a36Sopenharmony_ci#define SIR_MAX (23) 26762306a36Sopenharmony_ci#else 26862306a36Sopenharmony_ci#define SIR_MAX (22) 26962306a36Sopenharmony_ci#endif 27062306a36Sopenharmony_ci 27162306a36Sopenharmony_ci/* 27262306a36Sopenharmony_ci * Extended error bit codes. 27362306a36Sopenharmony_ci * xerr_status field of struct sym_ccb. 27462306a36Sopenharmony_ci */ 27562306a36Sopenharmony_ci#define XE_EXTRA_DATA (1) /* unexpected data phase */ 27662306a36Sopenharmony_ci#define XE_BAD_PHASE (1<<1) /* illegal phase (4/5) */ 27762306a36Sopenharmony_ci#define XE_PARITY_ERR (1<<2) /* unrecovered SCSI parity error */ 27862306a36Sopenharmony_ci#define XE_SODL_UNRUN (1<<3) /* ODD transfer in DATA OUT phase */ 27962306a36Sopenharmony_ci#define XE_SWIDE_OVRUN (1<<4) /* ODD transfer in DATA IN phase */ 28062306a36Sopenharmony_ci 28162306a36Sopenharmony_ci/* 28262306a36Sopenharmony_ci * Negotiation status. 28362306a36Sopenharmony_ci * nego_status field of struct sym_ccb. 28462306a36Sopenharmony_ci */ 28562306a36Sopenharmony_ci#define NS_SYNC (1) 28662306a36Sopenharmony_ci#define NS_WIDE (2) 28762306a36Sopenharmony_ci#define NS_PPR (3) 28862306a36Sopenharmony_ci 28962306a36Sopenharmony_ci/* 29062306a36Sopenharmony_ci * A CCB hashed table is used to retrieve CCB address 29162306a36Sopenharmony_ci * from DSA value. 29262306a36Sopenharmony_ci */ 29362306a36Sopenharmony_ci#define CCB_HASH_SHIFT 8 29462306a36Sopenharmony_ci#define CCB_HASH_SIZE (1UL << CCB_HASH_SHIFT) 29562306a36Sopenharmony_ci#define CCB_HASH_MASK (CCB_HASH_SIZE-1) 29662306a36Sopenharmony_ci#if 1 29762306a36Sopenharmony_ci#define CCB_HASH_CODE(dsa) \ 29862306a36Sopenharmony_ci (((dsa) >> (_LGRU16_(sizeof(struct sym_ccb)))) & CCB_HASH_MASK) 29962306a36Sopenharmony_ci#else 30062306a36Sopenharmony_ci#define CCB_HASH_CODE(dsa) (((dsa) >> 9) & CCB_HASH_MASK) 30162306a36Sopenharmony_ci#endif 30262306a36Sopenharmony_ci 30362306a36Sopenharmony_ci#if SYM_CONF_DMA_ADDRESSING_MODE == 2 30462306a36Sopenharmony_ci/* 30562306a36Sopenharmony_ci * We may want to use segment registers for 64 bit DMA. 30662306a36Sopenharmony_ci * 16 segments registers -> up to 64 GB addressable. 30762306a36Sopenharmony_ci */ 30862306a36Sopenharmony_ci#define SYM_DMAP_SHIFT (4) 30962306a36Sopenharmony_ci#define SYM_DMAP_SIZE (1u<<SYM_DMAP_SHIFT) 31062306a36Sopenharmony_ci#define SYM_DMAP_MASK (SYM_DMAP_SIZE-1) 31162306a36Sopenharmony_ci#endif 31262306a36Sopenharmony_ci 31362306a36Sopenharmony_ci/* 31462306a36Sopenharmony_ci * Device flags. 31562306a36Sopenharmony_ci */ 31662306a36Sopenharmony_ci#define SYM_DISC_ENABLED (1) 31762306a36Sopenharmony_ci#define SYM_TAGS_ENABLED (1<<1) 31862306a36Sopenharmony_ci#define SYM_SCAN_BOOT_DISABLED (1<<2) 31962306a36Sopenharmony_ci#define SYM_SCAN_LUNS_DISABLED (1<<3) 32062306a36Sopenharmony_ci 32162306a36Sopenharmony_ci/* 32262306a36Sopenharmony_ci * Host adapter miscellaneous flags. 32362306a36Sopenharmony_ci */ 32462306a36Sopenharmony_ci#define SYM_AVOID_BUS_RESET (1) 32562306a36Sopenharmony_ci 32662306a36Sopenharmony_ci/* 32762306a36Sopenharmony_ci * Misc. 32862306a36Sopenharmony_ci */ 32962306a36Sopenharmony_ci#define SYM_SNOOP_TIMEOUT (10000000) 33062306a36Sopenharmony_ci#define BUS_8_BIT 0 33162306a36Sopenharmony_ci#define BUS_16_BIT 1 33262306a36Sopenharmony_ci 33362306a36Sopenharmony_ci/* 33462306a36Sopenharmony_ci * Gather negotiable parameters value 33562306a36Sopenharmony_ci */ 33662306a36Sopenharmony_cistruct sym_trans { 33762306a36Sopenharmony_ci u8 period; 33862306a36Sopenharmony_ci u8 offset; 33962306a36Sopenharmony_ci unsigned int width:1; 34062306a36Sopenharmony_ci unsigned int iu:1; 34162306a36Sopenharmony_ci unsigned int dt:1; 34262306a36Sopenharmony_ci unsigned int qas:1; 34362306a36Sopenharmony_ci unsigned int check_nego:1; 34462306a36Sopenharmony_ci unsigned int renego:2; 34562306a36Sopenharmony_ci}; 34662306a36Sopenharmony_ci 34762306a36Sopenharmony_ci/* 34862306a36Sopenharmony_ci * Global TCB HEADER. 34962306a36Sopenharmony_ci * 35062306a36Sopenharmony_ci * Due to lack of indirect addressing on earlier NCR chips, 35162306a36Sopenharmony_ci * this substructure is copied from the TCB to a global 35262306a36Sopenharmony_ci * address after selection. 35362306a36Sopenharmony_ci * For SYMBIOS chips that support LOAD/STORE this copy is 35462306a36Sopenharmony_ci * not needed and thus not performed. 35562306a36Sopenharmony_ci */ 35662306a36Sopenharmony_cistruct sym_tcbh { 35762306a36Sopenharmony_ci /* 35862306a36Sopenharmony_ci * Scripts bus addresses of LUN table accessed from scripts. 35962306a36Sopenharmony_ci * LUN #0 is a special case, since multi-lun devices are rare, 36062306a36Sopenharmony_ci * and we we want to speed-up the general case and not waste 36162306a36Sopenharmony_ci * resources. 36262306a36Sopenharmony_ci */ 36362306a36Sopenharmony_ci u32 luntbl_sa; /* bus address of this table */ 36462306a36Sopenharmony_ci u32 lun0_sa; /* bus address of LCB #0 */ 36562306a36Sopenharmony_ci /* 36662306a36Sopenharmony_ci * Actual SYNC/WIDE IO registers value for this target. 36762306a36Sopenharmony_ci * 'sval', 'wval' and 'uval' are read from SCRIPTS and 36862306a36Sopenharmony_ci * so have alignment constraints. 36962306a36Sopenharmony_ci */ 37062306a36Sopenharmony_ci/*0*/ u_char uval; /* -> SCNTL4 register */ 37162306a36Sopenharmony_ci/*1*/ u_char sval; /* -> SXFER io register */ 37262306a36Sopenharmony_ci/*2*/ u_char filler1; 37362306a36Sopenharmony_ci/*3*/ u_char wval; /* -> SCNTL3 io register */ 37462306a36Sopenharmony_ci}; 37562306a36Sopenharmony_ci 37662306a36Sopenharmony_ci/* 37762306a36Sopenharmony_ci * Target Control Block 37862306a36Sopenharmony_ci */ 37962306a36Sopenharmony_cistruct sym_tcb { 38062306a36Sopenharmony_ci /* 38162306a36Sopenharmony_ci * TCB header. 38262306a36Sopenharmony_ci * Assumed at offset 0. 38362306a36Sopenharmony_ci */ 38462306a36Sopenharmony_ci/*0*/ struct sym_tcbh head; 38562306a36Sopenharmony_ci 38662306a36Sopenharmony_ci /* 38762306a36Sopenharmony_ci * LUN table used by the SCRIPTS processor. 38862306a36Sopenharmony_ci * An array of bus addresses is used on reselection. 38962306a36Sopenharmony_ci */ 39062306a36Sopenharmony_ci u32 *luntbl; /* LCBs bus address table */ 39162306a36Sopenharmony_ci int nlcb; /* Number of valid LCBs (including LUN #0) */ 39262306a36Sopenharmony_ci 39362306a36Sopenharmony_ci /* 39462306a36Sopenharmony_ci * LUN table used by the C code. 39562306a36Sopenharmony_ci */ 39662306a36Sopenharmony_ci struct sym_lcb *lun0p; /* LCB of LUN #0 (usual case) */ 39762306a36Sopenharmony_ci#if SYM_CONF_MAX_LUN > 1 39862306a36Sopenharmony_ci struct sym_lcb **lunmp; /* Other LCBs [1..MAX_LUN] */ 39962306a36Sopenharmony_ci#endif 40062306a36Sopenharmony_ci 40162306a36Sopenharmony_ci#ifdef SYM_HAVE_STCB 40262306a36Sopenharmony_ci /* 40362306a36Sopenharmony_ci * O/S specific data structure. 40462306a36Sopenharmony_ci */ 40562306a36Sopenharmony_ci struct sym_stcb s; 40662306a36Sopenharmony_ci#endif 40762306a36Sopenharmony_ci 40862306a36Sopenharmony_ci /* Transfer goal */ 40962306a36Sopenharmony_ci struct sym_trans tgoal; 41062306a36Sopenharmony_ci 41162306a36Sopenharmony_ci /* Last printed transfer speed */ 41262306a36Sopenharmony_ci struct sym_trans tprint; 41362306a36Sopenharmony_ci 41462306a36Sopenharmony_ci /* 41562306a36Sopenharmony_ci * Keep track of the CCB used for the negotiation in order 41662306a36Sopenharmony_ci * to ensure that only 1 negotiation is queued at a time. 41762306a36Sopenharmony_ci */ 41862306a36Sopenharmony_ci struct sym_ccb * nego_cp; /* CCB used for the nego */ 41962306a36Sopenharmony_ci 42062306a36Sopenharmony_ci /* 42162306a36Sopenharmony_ci * Set when we want to reset the device. 42262306a36Sopenharmony_ci */ 42362306a36Sopenharmony_ci u_char to_reset; 42462306a36Sopenharmony_ci 42562306a36Sopenharmony_ci /* 42662306a36Sopenharmony_ci * Other user settable limits and options. 42762306a36Sopenharmony_ci * These limits are read from the NVRAM if present. 42862306a36Sopenharmony_ci */ 42962306a36Sopenharmony_ci unsigned char usrflags; 43062306a36Sopenharmony_ci unsigned char usr_period; 43162306a36Sopenharmony_ci unsigned char usr_width; 43262306a36Sopenharmony_ci unsigned short usrtags; 43362306a36Sopenharmony_ci struct scsi_target *starget; 43462306a36Sopenharmony_ci}; 43562306a36Sopenharmony_ci 43662306a36Sopenharmony_ci/* 43762306a36Sopenharmony_ci * Global LCB HEADER. 43862306a36Sopenharmony_ci * 43962306a36Sopenharmony_ci * Due to lack of indirect addressing on earlier NCR chips, 44062306a36Sopenharmony_ci * this substructure is copied from the LCB to a global 44162306a36Sopenharmony_ci * address after selection. 44262306a36Sopenharmony_ci * For SYMBIOS chips that support LOAD/STORE this copy is 44362306a36Sopenharmony_ci * not needed and thus not performed. 44462306a36Sopenharmony_ci */ 44562306a36Sopenharmony_cistruct sym_lcbh { 44662306a36Sopenharmony_ci /* 44762306a36Sopenharmony_ci * SCRIPTS address jumped by SCRIPTS on reselection. 44862306a36Sopenharmony_ci * For not probed logical units, this address points to 44962306a36Sopenharmony_ci * SCRIPTS that deal with bad LU handling (must be at 45062306a36Sopenharmony_ci * offset zero of the LCB for that reason). 45162306a36Sopenharmony_ci */ 45262306a36Sopenharmony_ci/*0*/ u32 resel_sa; 45362306a36Sopenharmony_ci 45462306a36Sopenharmony_ci /* 45562306a36Sopenharmony_ci * Task (bus address of a CCB) read from SCRIPTS that points 45662306a36Sopenharmony_ci * to the unique ITL nexus allowed to be disconnected. 45762306a36Sopenharmony_ci */ 45862306a36Sopenharmony_ci u32 itl_task_sa; 45962306a36Sopenharmony_ci 46062306a36Sopenharmony_ci /* 46162306a36Sopenharmony_ci * Task table bus address (read from SCRIPTS). 46262306a36Sopenharmony_ci */ 46362306a36Sopenharmony_ci u32 itlq_tbl_sa; 46462306a36Sopenharmony_ci}; 46562306a36Sopenharmony_ci 46662306a36Sopenharmony_ci/* 46762306a36Sopenharmony_ci * Logical Unit Control Block 46862306a36Sopenharmony_ci */ 46962306a36Sopenharmony_cistruct sym_lcb { 47062306a36Sopenharmony_ci /* 47162306a36Sopenharmony_ci * TCB header. 47262306a36Sopenharmony_ci * Assumed at offset 0. 47362306a36Sopenharmony_ci */ 47462306a36Sopenharmony_ci/*0*/ struct sym_lcbh head; 47562306a36Sopenharmony_ci 47662306a36Sopenharmony_ci /* 47762306a36Sopenharmony_ci * Task table read from SCRIPTS that contains pointers to 47862306a36Sopenharmony_ci * ITLQ nexuses. The bus address read from SCRIPTS is 47962306a36Sopenharmony_ci * inside the header. 48062306a36Sopenharmony_ci */ 48162306a36Sopenharmony_ci u32 *itlq_tbl; /* Kernel virtual address */ 48262306a36Sopenharmony_ci 48362306a36Sopenharmony_ci /* 48462306a36Sopenharmony_ci * Busy CCBs management. 48562306a36Sopenharmony_ci */ 48662306a36Sopenharmony_ci u_short busy_itlq; /* Number of busy tagged CCBs */ 48762306a36Sopenharmony_ci u_short busy_itl; /* Number of busy untagged CCBs */ 48862306a36Sopenharmony_ci 48962306a36Sopenharmony_ci /* 49062306a36Sopenharmony_ci * Circular tag allocation buffer. 49162306a36Sopenharmony_ci */ 49262306a36Sopenharmony_ci u_short ia_tag; /* Tag allocation index */ 49362306a36Sopenharmony_ci u_short if_tag; /* Tag release index */ 49462306a36Sopenharmony_ci u_char *cb_tags; /* Circular tags buffer */ 49562306a36Sopenharmony_ci 49662306a36Sopenharmony_ci /* 49762306a36Sopenharmony_ci * O/S specific data structure. 49862306a36Sopenharmony_ci */ 49962306a36Sopenharmony_ci#ifdef SYM_HAVE_SLCB 50062306a36Sopenharmony_ci struct sym_slcb s; 50162306a36Sopenharmony_ci#endif 50262306a36Sopenharmony_ci 50362306a36Sopenharmony_ci#ifdef SYM_OPT_HANDLE_DEVICE_QUEUEING 50462306a36Sopenharmony_ci /* 50562306a36Sopenharmony_ci * Optionnaly the driver can handle device queueing, 50662306a36Sopenharmony_ci * and requeues internally command to redo. 50762306a36Sopenharmony_ci */ 50862306a36Sopenharmony_ci SYM_QUEHEAD waiting_ccbq; 50962306a36Sopenharmony_ci SYM_QUEHEAD started_ccbq; 51062306a36Sopenharmony_ci int num_sgood; 51162306a36Sopenharmony_ci u_short started_tags; 51262306a36Sopenharmony_ci u_short started_no_tag; 51362306a36Sopenharmony_ci u_short started_max; 51462306a36Sopenharmony_ci u_short started_limit; 51562306a36Sopenharmony_ci#endif 51662306a36Sopenharmony_ci 51762306a36Sopenharmony_ci#ifdef SYM_OPT_LIMIT_COMMAND_REORDERING 51862306a36Sopenharmony_ci /* 51962306a36Sopenharmony_ci * Optionally the driver can try to prevent SCSI 52062306a36Sopenharmony_ci * IOs from being reordered too much. 52162306a36Sopenharmony_ci */ 52262306a36Sopenharmony_ci u_char tags_si; /* Current index to tags sum */ 52362306a36Sopenharmony_ci u_short tags_sum[2]; /* Tags sum counters */ 52462306a36Sopenharmony_ci u_short tags_since; /* # of tags since last switch */ 52562306a36Sopenharmony_ci#endif 52662306a36Sopenharmony_ci 52762306a36Sopenharmony_ci /* 52862306a36Sopenharmony_ci * Set when we want to clear all tasks. 52962306a36Sopenharmony_ci */ 53062306a36Sopenharmony_ci u_char to_clear; 53162306a36Sopenharmony_ci 53262306a36Sopenharmony_ci /* 53362306a36Sopenharmony_ci * Capabilities. 53462306a36Sopenharmony_ci */ 53562306a36Sopenharmony_ci u_char user_flags; 53662306a36Sopenharmony_ci u_char curr_flags; 53762306a36Sopenharmony_ci}; 53862306a36Sopenharmony_ci 53962306a36Sopenharmony_ci/* 54062306a36Sopenharmony_ci * Action from SCRIPTS on a task. 54162306a36Sopenharmony_ci * Is part of the CCB, but is also used separately to plug 54262306a36Sopenharmony_ci * error handling action to perform from SCRIPTS. 54362306a36Sopenharmony_ci */ 54462306a36Sopenharmony_cistruct sym_actscr { 54562306a36Sopenharmony_ci u32 start; /* Jumped by SCRIPTS after selection */ 54662306a36Sopenharmony_ci u32 restart; /* Jumped by SCRIPTS on relection */ 54762306a36Sopenharmony_ci}; 54862306a36Sopenharmony_ci 54962306a36Sopenharmony_ci/* 55062306a36Sopenharmony_ci * Phase mismatch context. 55162306a36Sopenharmony_ci * 55262306a36Sopenharmony_ci * It is part of the CCB and is used as parameters for the 55362306a36Sopenharmony_ci * DATA pointer. We need two contexts to handle correctly the 55462306a36Sopenharmony_ci * SAVED DATA POINTER. 55562306a36Sopenharmony_ci */ 55662306a36Sopenharmony_cistruct sym_pmc { 55762306a36Sopenharmony_ci struct sym_tblmove sg; /* Updated interrupted SG block */ 55862306a36Sopenharmony_ci u32 ret; /* SCRIPT return address */ 55962306a36Sopenharmony_ci}; 56062306a36Sopenharmony_ci 56162306a36Sopenharmony_ci/* 56262306a36Sopenharmony_ci * LUN control block lookup. 56362306a36Sopenharmony_ci * We use a direct pointer for LUN #0, and a table of 56462306a36Sopenharmony_ci * pointers which is only allocated for devices that support 56562306a36Sopenharmony_ci * LUN(s) > 0. 56662306a36Sopenharmony_ci */ 56762306a36Sopenharmony_ci#if SYM_CONF_MAX_LUN <= 1 56862306a36Sopenharmony_ci#define sym_lp(tp, lun) (!lun) ? (tp)->lun0p : NULL 56962306a36Sopenharmony_ci#else 57062306a36Sopenharmony_ci#define sym_lp(tp, lun) \ 57162306a36Sopenharmony_ci (!lun) ? (tp)->lun0p : (tp)->lunmp ? (tp)->lunmp[((u8)lun)] : NULL 57262306a36Sopenharmony_ci#endif 57362306a36Sopenharmony_ci 57462306a36Sopenharmony_ci/* 57562306a36Sopenharmony_ci * Status are used by the host and the script processor. 57662306a36Sopenharmony_ci * 57762306a36Sopenharmony_ci * The last four bytes (status[4]) are copied to the 57862306a36Sopenharmony_ci * scratchb register (declared as scr0..scr3) just after the 57962306a36Sopenharmony_ci * select/reselect, and copied back just after disconnecting. 58062306a36Sopenharmony_ci * Inside the script the XX_REG are used. 58162306a36Sopenharmony_ci */ 58262306a36Sopenharmony_ci 58362306a36Sopenharmony_ci/* 58462306a36Sopenharmony_ci * Last four bytes (script) 58562306a36Sopenharmony_ci */ 58662306a36Sopenharmony_ci#define HX_REG scr0 58762306a36Sopenharmony_ci#define HX_PRT nc_scr0 58862306a36Sopenharmony_ci#define HS_REG scr1 58962306a36Sopenharmony_ci#define HS_PRT nc_scr1 59062306a36Sopenharmony_ci#define SS_REG scr2 59162306a36Sopenharmony_ci#define SS_PRT nc_scr2 59262306a36Sopenharmony_ci#define HF_REG scr3 59362306a36Sopenharmony_ci#define HF_PRT nc_scr3 59462306a36Sopenharmony_ci 59562306a36Sopenharmony_ci/* 59662306a36Sopenharmony_ci * Last four bytes (host) 59762306a36Sopenharmony_ci */ 59862306a36Sopenharmony_ci#define host_xflags phys.head.status[0] 59962306a36Sopenharmony_ci#define host_status phys.head.status[1] 60062306a36Sopenharmony_ci#define ssss_status phys.head.status[2] 60162306a36Sopenharmony_ci#define host_flags phys.head.status[3] 60262306a36Sopenharmony_ci 60362306a36Sopenharmony_ci/* 60462306a36Sopenharmony_ci * Host flags 60562306a36Sopenharmony_ci */ 60662306a36Sopenharmony_ci#define HF_IN_PM0 1u 60762306a36Sopenharmony_ci#define HF_IN_PM1 (1u<<1) 60862306a36Sopenharmony_ci#define HF_ACT_PM (1u<<2) 60962306a36Sopenharmony_ci#define HF_DP_SAVED (1u<<3) 61062306a36Sopenharmony_ci#define HF_SENSE (1u<<4) 61162306a36Sopenharmony_ci#define HF_EXT_ERR (1u<<5) 61262306a36Sopenharmony_ci#define HF_DATA_IN (1u<<6) 61362306a36Sopenharmony_ci#ifdef SYM_CONF_IARB_SUPPORT 61462306a36Sopenharmony_ci#define HF_HINT_IARB (1u<<7) 61562306a36Sopenharmony_ci#endif 61662306a36Sopenharmony_ci 61762306a36Sopenharmony_ci/* 61862306a36Sopenharmony_ci * More host flags 61962306a36Sopenharmony_ci */ 62062306a36Sopenharmony_ci#if SYM_CONF_DMA_ADDRESSING_MODE == 2 62162306a36Sopenharmony_ci#define HX_DMAP_DIRTY (1u<<7) 62262306a36Sopenharmony_ci#endif 62362306a36Sopenharmony_ci 62462306a36Sopenharmony_ci/* 62562306a36Sopenharmony_ci * Global CCB HEADER. 62662306a36Sopenharmony_ci * 62762306a36Sopenharmony_ci * Due to lack of indirect addressing on earlier NCR chips, 62862306a36Sopenharmony_ci * this substructure is copied from the ccb to a global 62962306a36Sopenharmony_ci * address after selection (or reselection) and copied back 63062306a36Sopenharmony_ci * before disconnect. 63162306a36Sopenharmony_ci * For SYMBIOS chips that support LOAD/STORE this copy is 63262306a36Sopenharmony_ci * not needed and thus not performed. 63362306a36Sopenharmony_ci */ 63462306a36Sopenharmony_ci 63562306a36Sopenharmony_cistruct sym_ccbh { 63662306a36Sopenharmony_ci /* 63762306a36Sopenharmony_ci * Start and restart SCRIPTS addresses (must be at 0). 63862306a36Sopenharmony_ci */ 63962306a36Sopenharmony_ci/*0*/ struct sym_actscr go; 64062306a36Sopenharmony_ci 64162306a36Sopenharmony_ci /* 64262306a36Sopenharmony_ci * SCRIPTS jump address that deal with data pointers. 64362306a36Sopenharmony_ci * 'savep' points to the position in the script responsible 64462306a36Sopenharmony_ci * for the actual transfer of data. 64562306a36Sopenharmony_ci * It's written on reception of a SAVE_DATA_POINTER message. 64662306a36Sopenharmony_ci */ 64762306a36Sopenharmony_ci u32 savep; /* Jump address to saved data pointer */ 64862306a36Sopenharmony_ci u32 lastp; /* SCRIPTS address at end of data */ 64962306a36Sopenharmony_ci 65062306a36Sopenharmony_ci /* 65162306a36Sopenharmony_ci * Status fields. 65262306a36Sopenharmony_ci */ 65362306a36Sopenharmony_ci u8 status[4]; 65462306a36Sopenharmony_ci}; 65562306a36Sopenharmony_ci 65662306a36Sopenharmony_ci/* 65762306a36Sopenharmony_ci * GET/SET the value of the data pointer used by SCRIPTS. 65862306a36Sopenharmony_ci * 65962306a36Sopenharmony_ci * We must distinguish between the LOAD/STORE-based SCRIPTS 66062306a36Sopenharmony_ci * that use directly the header in the CCB, and the NCR-GENERIC 66162306a36Sopenharmony_ci * SCRIPTS that use the copy of the header in the HCB. 66262306a36Sopenharmony_ci */ 66362306a36Sopenharmony_ci#if SYM_CONF_GENERIC_SUPPORT 66462306a36Sopenharmony_ci#define sym_set_script_dp(np, cp, dp) \ 66562306a36Sopenharmony_ci do { \ 66662306a36Sopenharmony_ci if (np->features & FE_LDSTR) \ 66762306a36Sopenharmony_ci cp->phys.head.lastp = cpu_to_scr(dp); \ 66862306a36Sopenharmony_ci else \ 66962306a36Sopenharmony_ci np->ccb_head.lastp = cpu_to_scr(dp); \ 67062306a36Sopenharmony_ci } while (0) 67162306a36Sopenharmony_ci#define sym_get_script_dp(np, cp) \ 67262306a36Sopenharmony_ci scr_to_cpu((np->features & FE_LDSTR) ? \ 67362306a36Sopenharmony_ci cp->phys.head.lastp : np->ccb_head.lastp) 67462306a36Sopenharmony_ci#else 67562306a36Sopenharmony_ci#define sym_set_script_dp(np, cp, dp) \ 67662306a36Sopenharmony_ci do { \ 67762306a36Sopenharmony_ci cp->phys.head.lastp = cpu_to_scr(dp); \ 67862306a36Sopenharmony_ci } while (0) 67962306a36Sopenharmony_ci 68062306a36Sopenharmony_ci#define sym_get_script_dp(np, cp) (cp->phys.head.lastp) 68162306a36Sopenharmony_ci#endif 68262306a36Sopenharmony_ci 68362306a36Sopenharmony_ci/* 68462306a36Sopenharmony_ci * Data Structure Block 68562306a36Sopenharmony_ci * 68662306a36Sopenharmony_ci * During execution of a ccb by the script processor, the 68762306a36Sopenharmony_ci * DSA (data structure address) register points to this 68862306a36Sopenharmony_ci * substructure of the ccb. 68962306a36Sopenharmony_ci */ 69062306a36Sopenharmony_cistruct sym_dsb { 69162306a36Sopenharmony_ci /* 69262306a36Sopenharmony_ci * CCB header. 69362306a36Sopenharmony_ci * Also assumed at offset 0 of the sym_ccb structure. 69462306a36Sopenharmony_ci */ 69562306a36Sopenharmony_ci/*0*/ struct sym_ccbh head; 69662306a36Sopenharmony_ci 69762306a36Sopenharmony_ci /* 69862306a36Sopenharmony_ci * Phase mismatch contexts. 69962306a36Sopenharmony_ci * We need two to handle correctly the SAVED DATA POINTER. 70062306a36Sopenharmony_ci * MUST BOTH BE AT OFFSET < 256, due to using 8 bit arithmetic 70162306a36Sopenharmony_ci * for address calculation from SCRIPTS. 70262306a36Sopenharmony_ci */ 70362306a36Sopenharmony_ci struct sym_pmc pm0; 70462306a36Sopenharmony_ci struct sym_pmc pm1; 70562306a36Sopenharmony_ci 70662306a36Sopenharmony_ci /* 70762306a36Sopenharmony_ci * Table data for Script 70862306a36Sopenharmony_ci */ 70962306a36Sopenharmony_ci struct sym_tblsel select; 71062306a36Sopenharmony_ci struct sym_tblmove smsg; 71162306a36Sopenharmony_ci struct sym_tblmove smsg_ext; 71262306a36Sopenharmony_ci struct sym_tblmove cmd; 71362306a36Sopenharmony_ci struct sym_tblmove sense; 71462306a36Sopenharmony_ci struct sym_tblmove wresid; 71562306a36Sopenharmony_ci struct sym_tblmove data [SYM_CONF_MAX_SG]; 71662306a36Sopenharmony_ci}; 71762306a36Sopenharmony_ci 71862306a36Sopenharmony_ci/* 71962306a36Sopenharmony_ci * Our Command Control Block 72062306a36Sopenharmony_ci */ 72162306a36Sopenharmony_cistruct sym_ccb { 72262306a36Sopenharmony_ci /* 72362306a36Sopenharmony_ci * This is the data structure which is pointed by the DSA 72462306a36Sopenharmony_ci * register when it is executed by the script processor. 72562306a36Sopenharmony_ci * It must be the first entry. 72662306a36Sopenharmony_ci */ 72762306a36Sopenharmony_ci struct sym_dsb phys; 72862306a36Sopenharmony_ci 72962306a36Sopenharmony_ci /* 73062306a36Sopenharmony_ci * Pointer to CAM ccb and related stuff. 73162306a36Sopenharmony_ci */ 73262306a36Sopenharmony_ci struct scsi_cmnd *cmd; /* CAM scsiio ccb */ 73362306a36Sopenharmony_ci u8 cdb_buf[16]; /* Copy of CDB */ 73462306a36Sopenharmony_ci#define SYM_SNS_BBUF_LEN 32 73562306a36Sopenharmony_ci u8 sns_bbuf[SYM_SNS_BBUF_LEN]; /* Bounce buffer for sense data */ 73662306a36Sopenharmony_ci int data_len; /* Total data length */ 73762306a36Sopenharmony_ci int segments; /* Number of SG segments */ 73862306a36Sopenharmony_ci 73962306a36Sopenharmony_ci u8 order; /* Tag type (if tagged command) */ 74062306a36Sopenharmony_ci unsigned char odd_byte_adjustment; /* odd-sized req on wide bus */ 74162306a36Sopenharmony_ci 74262306a36Sopenharmony_ci u_char nego_status; /* Negotiation status */ 74362306a36Sopenharmony_ci u_char xerr_status; /* Extended error flags */ 74462306a36Sopenharmony_ci u32 extra_bytes; /* Extraneous bytes transferred */ 74562306a36Sopenharmony_ci 74662306a36Sopenharmony_ci /* 74762306a36Sopenharmony_ci * Message areas. 74862306a36Sopenharmony_ci * We prepare a message to be sent after selection. 74962306a36Sopenharmony_ci * We may use a second one if the command is rescheduled 75062306a36Sopenharmony_ci * due to CHECK_CONDITION or COMMAND TERMINATED. 75162306a36Sopenharmony_ci * Contents are IDENTIFY and SIMPLE_TAG. 75262306a36Sopenharmony_ci * While negotiating sync or wide transfer, 75362306a36Sopenharmony_ci * a SDTR or WDTR message is appended. 75462306a36Sopenharmony_ci */ 75562306a36Sopenharmony_ci u_char scsi_smsg [12]; 75662306a36Sopenharmony_ci u_char scsi_smsg2[12]; 75762306a36Sopenharmony_ci 75862306a36Sopenharmony_ci /* 75962306a36Sopenharmony_ci * Auto request sense related fields. 76062306a36Sopenharmony_ci */ 76162306a36Sopenharmony_ci u_char sensecmd[6]; /* Request Sense command */ 76262306a36Sopenharmony_ci u_char sv_scsi_status; /* Saved SCSI status */ 76362306a36Sopenharmony_ci u_char sv_xerr_status; /* Saved extended status */ 76462306a36Sopenharmony_ci int sv_resid; /* Saved residual */ 76562306a36Sopenharmony_ci 76662306a36Sopenharmony_ci /* 76762306a36Sopenharmony_ci * Other fields. 76862306a36Sopenharmony_ci */ 76962306a36Sopenharmony_ci u32 ccb_ba; /* BUS address of this CCB */ 77062306a36Sopenharmony_ci u_short tag; /* Tag for this transfer */ 77162306a36Sopenharmony_ci /* NO_TAG means no tag */ 77262306a36Sopenharmony_ci u_char target; 77362306a36Sopenharmony_ci u_char lun; 77462306a36Sopenharmony_ci struct sym_ccb *link_ccbh; /* Host adapter CCB hash chain */ 77562306a36Sopenharmony_ci SYM_QUEHEAD link_ccbq; /* Link to free/busy CCB queue */ 77662306a36Sopenharmony_ci u32 startp; /* Initial data pointer */ 77762306a36Sopenharmony_ci u32 goalp; /* Expected last data pointer */ 77862306a36Sopenharmony_ci int ext_sg; /* Extreme data pointer, used */ 77962306a36Sopenharmony_ci int ext_ofs; /* to calculate the residual. */ 78062306a36Sopenharmony_ci#ifdef SYM_OPT_HANDLE_DEVICE_QUEUEING 78162306a36Sopenharmony_ci SYM_QUEHEAD link2_ccbq; /* Link for device queueing */ 78262306a36Sopenharmony_ci u_char started; /* CCB queued to the squeue */ 78362306a36Sopenharmony_ci#endif 78462306a36Sopenharmony_ci u_char to_abort; /* Want this IO to be aborted */ 78562306a36Sopenharmony_ci#ifdef SYM_OPT_LIMIT_COMMAND_REORDERING 78662306a36Sopenharmony_ci u_char tags_si; /* Lun tags sum index (0,1) */ 78762306a36Sopenharmony_ci#endif 78862306a36Sopenharmony_ci}; 78962306a36Sopenharmony_ci 79062306a36Sopenharmony_ci#define CCB_BA(cp,lbl) cpu_to_scr(cp->ccb_ba + offsetof(struct sym_ccb, lbl)) 79162306a36Sopenharmony_ci 79262306a36Sopenharmony_citypedef struct device *m_pool_ident_t; 79362306a36Sopenharmony_ci 79462306a36Sopenharmony_ci/* 79562306a36Sopenharmony_ci * Host Control Block 79662306a36Sopenharmony_ci */ 79762306a36Sopenharmony_cistruct sym_hcb { 79862306a36Sopenharmony_ci /* 79962306a36Sopenharmony_ci * Global headers. 80062306a36Sopenharmony_ci * Due to poorness of addressing capabilities, earlier 80162306a36Sopenharmony_ci * chips (810, 815, 825) copy part of the data structures 80262306a36Sopenharmony_ci * (CCB, TCB and LCB) in fixed areas. 80362306a36Sopenharmony_ci */ 80462306a36Sopenharmony_ci#if SYM_CONF_GENERIC_SUPPORT 80562306a36Sopenharmony_ci struct sym_ccbh ccb_head; 80662306a36Sopenharmony_ci struct sym_tcbh tcb_head; 80762306a36Sopenharmony_ci struct sym_lcbh lcb_head; 80862306a36Sopenharmony_ci#endif 80962306a36Sopenharmony_ci /* 81062306a36Sopenharmony_ci * Idle task and invalid task actions and 81162306a36Sopenharmony_ci * their bus addresses. 81262306a36Sopenharmony_ci */ 81362306a36Sopenharmony_ci struct sym_actscr idletask, notask, bad_itl, bad_itlq; 81462306a36Sopenharmony_ci u32 idletask_ba, notask_ba, bad_itl_ba, bad_itlq_ba; 81562306a36Sopenharmony_ci 81662306a36Sopenharmony_ci /* 81762306a36Sopenharmony_ci * Dummy lun table to protect us against target 81862306a36Sopenharmony_ci * returning bad lun number on reselection. 81962306a36Sopenharmony_ci */ 82062306a36Sopenharmony_ci u32 *badluntbl; /* Table physical address */ 82162306a36Sopenharmony_ci u32 badlun_sa; /* SCRIPT handler BUS address */ 82262306a36Sopenharmony_ci 82362306a36Sopenharmony_ci /* 82462306a36Sopenharmony_ci * Bus address of this host control block. 82562306a36Sopenharmony_ci */ 82662306a36Sopenharmony_ci u32 hcb_ba; 82762306a36Sopenharmony_ci 82862306a36Sopenharmony_ci /* 82962306a36Sopenharmony_ci * Bit 32-63 of the on-chip RAM bus address in LE format. 83062306a36Sopenharmony_ci * The START_RAM64 script loads the MMRS and MMWS from this 83162306a36Sopenharmony_ci * field. 83262306a36Sopenharmony_ci */ 83362306a36Sopenharmony_ci u32 scr_ram_seg; 83462306a36Sopenharmony_ci 83562306a36Sopenharmony_ci /* 83662306a36Sopenharmony_ci * Initial value of some IO register bits. 83762306a36Sopenharmony_ci * These values are assumed to have been set by BIOS, and may 83862306a36Sopenharmony_ci * be used to probe adapter implementation differences. 83962306a36Sopenharmony_ci */ 84062306a36Sopenharmony_ci u_char sv_scntl0, sv_scntl3, sv_dmode, sv_dcntl, sv_ctest3, sv_ctest4, 84162306a36Sopenharmony_ci sv_ctest5, sv_gpcntl, sv_stest2, sv_stest4, sv_scntl4, 84262306a36Sopenharmony_ci sv_stest1; 84362306a36Sopenharmony_ci 84462306a36Sopenharmony_ci /* 84562306a36Sopenharmony_ci * Actual initial value of IO register bits used by the 84662306a36Sopenharmony_ci * driver. They are loaded at initialisation according to 84762306a36Sopenharmony_ci * features that are to be enabled/disabled. 84862306a36Sopenharmony_ci */ 84962306a36Sopenharmony_ci u_char rv_scntl0, rv_scntl3, rv_dmode, rv_dcntl, rv_ctest3, rv_ctest4, 85062306a36Sopenharmony_ci rv_ctest5, rv_stest2, rv_ccntl0, rv_ccntl1, rv_scntl4; 85162306a36Sopenharmony_ci 85262306a36Sopenharmony_ci /* 85362306a36Sopenharmony_ci * Target data. 85462306a36Sopenharmony_ci */ 85562306a36Sopenharmony_ci struct sym_tcb target[SYM_CONF_MAX_TARGET]; 85662306a36Sopenharmony_ci 85762306a36Sopenharmony_ci /* 85862306a36Sopenharmony_ci * Target control block bus address array used by the SCRIPT 85962306a36Sopenharmony_ci * on reselection. 86062306a36Sopenharmony_ci */ 86162306a36Sopenharmony_ci u32 *targtbl; 86262306a36Sopenharmony_ci u32 targtbl_ba; 86362306a36Sopenharmony_ci 86462306a36Sopenharmony_ci /* 86562306a36Sopenharmony_ci * DMA pool handle for this HBA. 86662306a36Sopenharmony_ci */ 86762306a36Sopenharmony_ci m_pool_ident_t bus_dmat; 86862306a36Sopenharmony_ci 86962306a36Sopenharmony_ci /* 87062306a36Sopenharmony_ci * O/S specific data structure 87162306a36Sopenharmony_ci */ 87262306a36Sopenharmony_ci struct sym_shcb s; 87362306a36Sopenharmony_ci 87462306a36Sopenharmony_ci /* 87562306a36Sopenharmony_ci * Physical bus addresses of the chip. 87662306a36Sopenharmony_ci */ 87762306a36Sopenharmony_ci u32 mmio_ba; /* MMIO 32 bit BUS address */ 87862306a36Sopenharmony_ci u32 ram_ba; /* RAM 32 bit BUS address */ 87962306a36Sopenharmony_ci 88062306a36Sopenharmony_ci /* 88162306a36Sopenharmony_ci * SCRIPTS virtual and physical bus addresses. 88262306a36Sopenharmony_ci * 'script' is loaded in the on-chip RAM if present. 88362306a36Sopenharmony_ci * 'scripth' stays in main memory for all chips except the 88462306a36Sopenharmony_ci * 53C895A, 53C896 and 53C1010 that provide 8K on-chip RAM. 88562306a36Sopenharmony_ci */ 88662306a36Sopenharmony_ci u_char *scripta0; /* Copy of scripts A, B, Z */ 88762306a36Sopenharmony_ci u_char *scriptb0; 88862306a36Sopenharmony_ci u_char *scriptz0; 88962306a36Sopenharmony_ci u32 scripta_ba; /* Actual scripts A, B, Z */ 89062306a36Sopenharmony_ci u32 scriptb_ba; /* 32 bit bus addresses. */ 89162306a36Sopenharmony_ci u32 scriptz_ba; 89262306a36Sopenharmony_ci u_short scripta_sz; /* Actual size of script A, B, Z*/ 89362306a36Sopenharmony_ci u_short scriptb_sz; 89462306a36Sopenharmony_ci u_short scriptz_sz; 89562306a36Sopenharmony_ci 89662306a36Sopenharmony_ci /* 89762306a36Sopenharmony_ci * Bus addresses, setup and patch methods for 89862306a36Sopenharmony_ci * the selected firmware. 89962306a36Sopenharmony_ci */ 90062306a36Sopenharmony_ci struct sym_fwa_ba fwa_bas; /* Useful SCRIPTA bus addresses */ 90162306a36Sopenharmony_ci struct sym_fwb_ba fwb_bas; /* Useful SCRIPTB bus addresses */ 90262306a36Sopenharmony_ci struct sym_fwz_ba fwz_bas; /* Useful SCRIPTZ bus addresses */ 90362306a36Sopenharmony_ci void (*fw_setup)(struct sym_hcb *np, struct sym_fw *fw); 90462306a36Sopenharmony_ci void (*fw_patch)(struct Scsi_Host *); 90562306a36Sopenharmony_ci char *fw_name; 90662306a36Sopenharmony_ci 90762306a36Sopenharmony_ci /* 90862306a36Sopenharmony_ci * General controller parameters and configuration. 90962306a36Sopenharmony_ci */ 91062306a36Sopenharmony_ci u_int features; /* Chip features map */ 91162306a36Sopenharmony_ci u_char myaddr; /* SCSI id of the adapter */ 91262306a36Sopenharmony_ci u_char maxburst; /* log base 2 of dwords burst */ 91362306a36Sopenharmony_ci u_char maxwide; /* Maximum transfer width */ 91462306a36Sopenharmony_ci u_char minsync; /* Min sync period factor (ST) */ 91562306a36Sopenharmony_ci u_char maxsync; /* Max sync period factor (ST) */ 91662306a36Sopenharmony_ci u_char maxoffs; /* Max scsi offset (ST) */ 91762306a36Sopenharmony_ci u_char minsync_dt; /* Min sync period factor (DT) */ 91862306a36Sopenharmony_ci u_char maxsync_dt; /* Max sync period factor (DT) */ 91962306a36Sopenharmony_ci u_char maxoffs_dt; /* Max scsi offset (DT) */ 92062306a36Sopenharmony_ci u_char multiplier; /* Clock multiplier (1,2,4) */ 92162306a36Sopenharmony_ci u_char clock_divn; /* Number of clock divisors */ 92262306a36Sopenharmony_ci u32 clock_khz; /* SCSI clock frequency in KHz */ 92362306a36Sopenharmony_ci u32 pciclk_khz; /* Estimated PCI clock in KHz */ 92462306a36Sopenharmony_ci /* 92562306a36Sopenharmony_ci * Start queue management. 92662306a36Sopenharmony_ci * It is filled up by the host processor and accessed by the 92762306a36Sopenharmony_ci * SCRIPTS processor in order to start SCSI commands. 92862306a36Sopenharmony_ci */ 92962306a36Sopenharmony_ci volatile /* Prevent code optimizations */ 93062306a36Sopenharmony_ci u32 *squeue; /* Start queue virtual address */ 93162306a36Sopenharmony_ci u32 squeue_ba; /* Start queue BUS address */ 93262306a36Sopenharmony_ci u_short squeueput; /* Next free slot of the queue */ 93362306a36Sopenharmony_ci u_short actccbs; /* Number of allocated CCBs */ 93462306a36Sopenharmony_ci 93562306a36Sopenharmony_ci /* 93662306a36Sopenharmony_ci * Command completion queue. 93762306a36Sopenharmony_ci * It is the same size as the start queue to avoid overflow. 93862306a36Sopenharmony_ci */ 93962306a36Sopenharmony_ci u_short dqueueget; /* Next position to scan */ 94062306a36Sopenharmony_ci volatile /* Prevent code optimizations */ 94162306a36Sopenharmony_ci u32 *dqueue; /* Completion (done) queue */ 94262306a36Sopenharmony_ci u32 dqueue_ba; /* Done queue BUS address */ 94362306a36Sopenharmony_ci 94462306a36Sopenharmony_ci /* 94562306a36Sopenharmony_ci * Miscellaneous buffers accessed by the scripts-processor. 94662306a36Sopenharmony_ci * They shall be DWORD aligned, because they may be read or 94762306a36Sopenharmony_ci * written with a script command. 94862306a36Sopenharmony_ci */ 94962306a36Sopenharmony_ci u_char msgout[8]; /* Buffer for MESSAGE OUT */ 95062306a36Sopenharmony_ci u_char msgin [8]; /* Buffer for MESSAGE IN */ 95162306a36Sopenharmony_ci u32 lastmsg; /* Last SCSI message sent */ 95262306a36Sopenharmony_ci u32 scratch; /* Scratch for SCSI receive */ 95362306a36Sopenharmony_ci /* Also used for cache test */ 95462306a36Sopenharmony_ci /* 95562306a36Sopenharmony_ci * Miscellaneous configuration and status parameters. 95662306a36Sopenharmony_ci */ 95762306a36Sopenharmony_ci u_char usrflags; /* Miscellaneous user flags */ 95862306a36Sopenharmony_ci u_char scsi_mode; /* Current SCSI BUS mode */ 95962306a36Sopenharmony_ci u_char verbose; /* Verbosity for this controller*/ 96062306a36Sopenharmony_ci 96162306a36Sopenharmony_ci /* 96262306a36Sopenharmony_ci * CCB lists and queue. 96362306a36Sopenharmony_ci */ 96462306a36Sopenharmony_ci struct sym_ccb **ccbh; /* CCBs hashed by DSA value */ 96562306a36Sopenharmony_ci /* CCB_HASH_SIZE lists of CCBs */ 96662306a36Sopenharmony_ci SYM_QUEHEAD free_ccbq; /* Queue of available CCBs */ 96762306a36Sopenharmony_ci SYM_QUEHEAD busy_ccbq; /* Queue of busy CCBs */ 96862306a36Sopenharmony_ci 96962306a36Sopenharmony_ci /* 97062306a36Sopenharmony_ci * During error handling and/or recovery, 97162306a36Sopenharmony_ci * active CCBs that are to be completed with 97262306a36Sopenharmony_ci * error or requeued are moved from the busy_ccbq 97362306a36Sopenharmony_ci * to the comp_ccbq prior to completion. 97462306a36Sopenharmony_ci */ 97562306a36Sopenharmony_ci SYM_QUEHEAD comp_ccbq; 97662306a36Sopenharmony_ci 97762306a36Sopenharmony_ci#ifdef SYM_OPT_HANDLE_DEVICE_QUEUEING 97862306a36Sopenharmony_ci SYM_QUEHEAD dummy_ccbq; 97962306a36Sopenharmony_ci#endif 98062306a36Sopenharmony_ci 98162306a36Sopenharmony_ci /* 98262306a36Sopenharmony_ci * IMMEDIATE ARBITRATION (IARB) control. 98362306a36Sopenharmony_ci * 98462306a36Sopenharmony_ci * We keep track in 'last_cp' of the last CCB that has been 98562306a36Sopenharmony_ci * queued to the SCRIPTS processor and clear 'last_cp' when 98662306a36Sopenharmony_ci * this CCB completes. If last_cp is not zero at the moment 98762306a36Sopenharmony_ci * we queue a new CCB, we set a flag in 'last_cp' that is 98862306a36Sopenharmony_ci * used by the SCRIPTS as a hint for setting IARB. 98962306a36Sopenharmony_ci * We donnot set more than 'iarb_max' consecutive hints for 99062306a36Sopenharmony_ci * IARB in order to leave devices a chance to reselect. 99162306a36Sopenharmony_ci * By the way, any non zero value of 'iarb_max' is unfair. :) 99262306a36Sopenharmony_ci */ 99362306a36Sopenharmony_ci#ifdef SYM_CONF_IARB_SUPPORT 99462306a36Sopenharmony_ci u_short iarb_max; /* Max. # consecutive IARB hints*/ 99562306a36Sopenharmony_ci u_short iarb_count; /* Actual # of these hints */ 99662306a36Sopenharmony_ci struct sym_ccb * last_cp; 99762306a36Sopenharmony_ci#endif 99862306a36Sopenharmony_ci 99962306a36Sopenharmony_ci /* 100062306a36Sopenharmony_ci * Command abort handling. 100162306a36Sopenharmony_ci * We need to synchronize tightly with the SCRIPTS 100262306a36Sopenharmony_ci * processor in order to handle things correctly. 100362306a36Sopenharmony_ci */ 100462306a36Sopenharmony_ci u_char abrt_msg[4]; /* Message to send buffer */ 100562306a36Sopenharmony_ci struct sym_tblmove abrt_tbl; /* Table for the MOV of it */ 100662306a36Sopenharmony_ci struct sym_tblsel abrt_sel; /* Sync params for selection */ 100762306a36Sopenharmony_ci u_char istat_sem; /* Tells the chip to stop (SEM) */ 100862306a36Sopenharmony_ci 100962306a36Sopenharmony_ci /* 101062306a36Sopenharmony_ci * 64 bit DMA handling. 101162306a36Sopenharmony_ci */ 101262306a36Sopenharmony_ci#if SYM_CONF_DMA_ADDRESSING_MODE != 0 101362306a36Sopenharmony_ci u_char use_dac; /* Use PCI DAC cycles */ 101462306a36Sopenharmony_ci#if SYM_CONF_DMA_ADDRESSING_MODE == 2 101562306a36Sopenharmony_ci u_char dmap_dirty; /* Dma segments registers dirty */ 101662306a36Sopenharmony_ci u32 dmap_bah[SYM_DMAP_SIZE];/* Segment registers map */ 101762306a36Sopenharmony_ci#endif 101862306a36Sopenharmony_ci#endif 101962306a36Sopenharmony_ci}; 102062306a36Sopenharmony_ci 102162306a36Sopenharmony_ci#if SYM_CONF_DMA_ADDRESSING_MODE == 0 102262306a36Sopenharmony_ci#define use_dac(np) 0 102362306a36Sopenharmony_ci#define set_dac(np) do { } while (0) 102462306a36Sopenharmony_ci#else 102562306a36Sopenharmony_ci#define use_dac(np) (np)->use_dac 102662306a36Sopenharmony_ci#define set_dac(np) (np)->use_dac = 1 102762306a36Sopenharmony_ci#endif 102862306a36Sopenharmony_ci 102962306a36Sopenharmony_ci#define HCB_BA(np, lbl) (np->hcb_ba + offsetof(struct sym_hcb, lbl)) 103062306a36Sopenharmony_ci 103162306a36Sopenharmony_ci 103262306a36Sopenharmony_ci/* 103362306a36Sopenharmony_ci * FIRMWARES (sym_fw.c) 103462306a36Sopenharmony_ci */ 103562306a36Sopenharmony_cistruct sym_fw * sym_find_firmware(struct sym_chip *chip); 103662306a36Sopenharmony_civoid sym_fw_bind_script(struct sym_hcb *np, u32 *start, int len); 103762306a36Sopenharmony_ci 103862306a36Sopenharmony_ci/* 103962306a36Sopenharmony_ci * Driver methods called from O/S specific code. 104062306a36Sopenharmony_ci */ 104162306a36Sopenharmony_cichar *sym_driver_name(void); 104262306a36Sopenharmony_civoid sym_print_xerr(struct scsi_cmnd *cmd, int x_status); 104362306a36Sopenharmony_ciint sym_reset_scsi_bus(struct sym_hcb *np, int enab_int); 104462306a36Sopenharmony_cistruct sym_chip *sym_lookup_chip_table(u_short device_id, u_char revision); 104562306a36Sopenharmony_ci#ifdef SYM_OPT_HANDLE_DEVICE_QUEUEING 104662306a36Sopenharmony_civoid sym_start_next_ccbs(struct sym_hcb *np, struct sym_lcb *lp, int maxn); 104762306a36Sopenharmony_ci#else 104862306a36Sopenharmony_civoid sym_put_start_queue(struct sym_hcb *np, struct sym_ccb *cp); 104962306a36Sopenharmony_ci#endif 105062306a36Sopenharmony_civoid sym_start_up(struct Scsi_Host *, int reason); 105162306a36Sopenharmony_ciirqreturn_t sym_interrupt(struct Scsi_Host *); 105262306a36Sopenharmony_ciint sym_clear_tasks(struct sym_hcb *np, int cam_status, int target, int lun, int task); 105362306a36Sopenharmony_cistruct sym_ccb *sym_get_ccb(struct sym_hcb *np, struct scsi_cmnd *cmd, u_char tag_order); 105462306a36Sopenharmony_civoid sym_free_ccb(struct sym_hcb *np, struct sym_ccb *cp); 105562306a36Sopenharmony_cistruct sym_lcb *sym_alloc_lcb(struct sym_hcb *np, u_char tn, u_char ln); 105662306a36Sopenharmony_ciint sym_free_lcb(struct sym_hcb *np, u_char tn, u_char ln); 105762306a36Sopenharmony_ciint sym_queue_scsiio(struct sym_hcb *np, struct scsi_cmnd *csio, struct sym_ccb *cp); 105862306a36Sopenharmony_ciint sym_abort_scsiio(struct sym_hcb *np, struct scsi_cmnd *ccb, int timed_out); 105962306a36Sopenharmony_ciint sym_reset_scsi_target(struct sym_hcb *np, int target); 106062306a36Sopenharmony_civoid sym_hcb_free(struct sym_hcb *np); 106162306a36Sopenharmony_ciint sym_hcb_attach(struct Scsi_Host *shost, struct sym_fw *fw, struct sym_nvram *nvram); 106262306a36Sopenharmony_ci 106362306a36Sopenharmony_ci/* 106462306a36Sopenharmony_ci * Build a scatter/gather entry. 106562306a36Sopenharmony_ci * 106662306a36Sopenharmony_ci * For 64 bit systems, we use the 8 upper bits of the size field 106762306a36Sopenharmony_ci * to provide bus address bits 32-39 to the SCRIPTS processor. 106862306a36Sopenharmony_ci * This allows the 895A, 896, 1010 to address up to 1 TB of memory. 106962306a36Sopenharmony_ci */ 107062306a36Sopenharmony_ci 107162306a36Sopenharmony_ci#if SYM_CONF_DMA_ADDRESSING_MODE == 0 107262306a36Sopenharmony_ci#define DMA_DAC_MASK DMA_BIT_MASK(32) 107362306a36Sopenharmony_ci#define sym_build_sge(np, data, badd, len) \ 107462306a36Sopenharmony_cido { \ 107562306a36Sopenharmony_ci (data)->addr = cpu_to_scr(badd); \ 107662306a36Sopenharmony_ci (data)->size = cpu_to_scr(len); \ 107762306a36Sopenharmony_ci} while (0) 107862306a36Sopenharmony_ci#elif SYM_CONF_DMA_ADDRESSING_MODE == 1 107962306a36Sopenharmony_ci#define DMA_DAC_MASK DMA_BIT_MASK(40) 108062306a36Sopenharmony_ci#define sym_build_sge(np, data, badd, len) \ 108162306a36Sopenharmony_cido { \ 108262306a36Sopenharmony_ci (data)->addr = cpu_to_scr(badd); \ 108362306a36Sopenharmony_ci (data)->size = cpu_to_scr((((badd) >> 8) & 0xff000000) + len); \ 108462306a36Sopenharmony_ci} while (0) 108562306a36Sopenharmony_ci#elif SYM_CONF_DMA_ADDRESSING_MODE == 2 108662306a36Sopenharmony_ci#define DMA_DAC_MASK DMA_BIT_MASK(64) 108762306a36Sopenharmony_ciint sym_lookup_dmap(struct sym_hcb *np, u32 h, int s); 108862306a36Sopenharmony_cistatic inline void 108962306a36Sopenharmony_cisym_build_sge(struct sym_hcb *np, struct sym_tblmove *data, u64 badd, int len) 109062306a36Sopenharmony_ci{ 109162306a36Sopenharmony_ci u32 h = (badd>>32); 109262306a36Sopenharmony_ci int s = (h&SYM_DMAP_MASK); 109362306a36Sopenharmony_ci 109462306a36Sopenharmony_ci if (h != np->dmap_bah[s]) 109562306a36Sopenharmony_ci goto bad; 109662306a36Sopenharmony_cigood: 109762306a36Sopenharmony_ci (data)->addr = cpu_to_scr(badd); 109862306a36Sopenharmony_ci (data)->size = cpu_to_scr((s<<24) + len); 109962306a36Sopenharmony_ci return; 110062306a36Sopenharmony_cibad: 110162306a36Sopenharmony_ci s = sym_lookup_dmap(np, h, s); 110262306a36Sopenharmony_ci goto good; 110362306a36Sopenharmony_ci} 110462306a36Sopenharmony_ci#else 110562306a36Sopenharmony_ci#error "Unsupported DMA addressing mode" 110662306a36Sopenharmony_ci#endif 110762306a36Sopenharmony_ci 110862306a36Sopenharmony_ci/* 110962306a36Sopenharmony_ci * MEMORY ALLOCATOR. 111062306a36Sopenharmony_ci */ 111162306a36Sopenharmony_ci 111262306a36Sopenharmony_ci#define sym_get_mem_cluster() \ 111362306a36Sopenharmony_ci (void *) __get_free_pages(GFP_ATOMIC, SYM_MEM_PAGE_ORDER) 111462306a36Sopenharmony_ci#define sym_free_mem_cluster(p) \ 111562306a36Sopenharmony_ci free_pages((unsigned long)p, SYM_MEM_PAGE_ORDER) 111662306a36Sopenharmony_ci 111762306a36Sopenharmony_ci/* 111862306a36Sopenharmony_ci * Link between free memory chunks of a given size. 111962306a36Sopenharmony_ci */ 112062306a36Sopenharmony_citypedef struct sym_m_link { 112162306a36Sopenharmony_ci struct sym_m_link *next; 112262306a36Sopenharmony_ci} *m_link_p; 112362306a36Sopenharmony_ci 112462306a36Sopenharmony_ci/* 112562306a36Sopenharmony_ci * Virtual to bus physical translation for a given cluster. 112662306a36Sopenharmony_ci * Such a structure is only useful with DMA abstraction. 112762306a36Sopenharmony_ci */ 112862306a36Sopenharmony_citypedef struct sym_m_vtob { /* Virtual to Bus address translation */ 112962306a36Sopenharmony_ci struct sym_m_vtob *next; 113062306a36Sopenharmony_ci void *vaddr; /* Virtual address */ 113162306a36Sopenharmony_ci dma_addr_t baddr; /* Bus physical address */ 113262306a36Sopenharmony_ci} *m_vtob_p; 113362306a36Sopenharmony_ci 113462306a36Sopenharmony_ci/* Hash this stuff a bit to speed up translations */ 113562306a36Sopenharmony_ci#define VTOB_HASH_SHIFT 5 113662306a36Sopenharmony_ci#define VTOB_HASH_SIZE (1UL << VTOB_HASH_SHIFT) 113762306a36Sopenharmony_ci#define VTOB_HASH_MASK (VTOB_HASH_SIZE-1) 113862306a36Sopenharmony_ci#define VTOB_HASH_CODE(m) \ 113962306a36Sopenharmony_ci ((((unsigned long)(m)) >> SYM_MEM_CLUSTER_SHIFT) & VTOB_HASH_MASK) 114062306a36Sopenharmony_ci 114162306a36Sopenharmony_ci/* 114262306a36Sopenharmony_ci * Memory pool of a given kind. 114362306a36Sopenharmony_ci * Ideally, we want to use: 114462306a36Sopenharmony_ci * 1) 1 pool for memory we donnot need to involve in DMA. 114562306a36Sopenharmony_ci * 2) The same pool for controllers that require same DMA 114662306a36Sopenharmony_ci * constraints and features. 114762306a36Sopenharmony_ci * The OS specific m_pool_id_t thing and the sym_m_pool_match() 114862306a36Sopenharmony_ci * method are expected to tell the driver about. 114962306a36Sopenharmony_ci */ 115062306a36Sopenharmony_citypedef struct sym_m_pool { 115162306a36Sopenharmony_ci m_pool_ident_t dev_dmat; /* Identifies the pool (see above) */ 115262306a36Sopenharmony_ci void * (*get_mem_cluster)(struct sym_m_pool *); 115362306a36Sopenharmony_ci#ifdef SYM_MEM_FREE_UNUSED 115462306a36Sopenharmony_ci void (*free_mem_cluster)(struct sym_m_pool *, void *); 115562306a36Sopenharmony_ci#endif 115662306a36Sopenharmony_ci#define M_GET_MEM_CLUSTER() mp->get_mem_cluster(mp) 115762306a36Sopenharmony_ci#define M_FREE_MEM_CLUSTER(p) mp->free_mem_cluster(mp, p) 115862306a36Sopenharmony_ci int nump; 115962306a36Sopenharmony_ci m_vtob_p vtob[VTOB_HASH_SIZE]; 116062306a36Sopenharmony_ci struct sym_m_pool *next; 116162306a36Sopenharmony_ci struct sym_m_link h[SYM_MEM_CLUSTER_SHIFT - SYM_MEM_SHIFT + 1]; 116262306a36Sopenharmony_ci} *m_pool_p; 116362306a36Sopenharmony_ci 116462306a36Sopenharmony_ci/* 116562306a36Sopenharmony_ci * Alloc, free and translate addresses to bus physical 116662306a36Sopenharmony_ci * for DMAable memory. 116762306a36Sopenharmony_ci */ 116862306a36Sopenharmony_civoid *__sym_calloc_dma(m_pool_ident_t dev_dmat, int size, char *name); 116962306a36Sopenharmony_civoid __sym_mfree_dma(m_pool_ident_t dev_dmat, void *m, int size, char *name); 117062306a36Sopenharmony_cidma_addr_t __vtobus(m_pool_ident_t dev_dmat, void *m); 117162306a36Sopenharmony_ci 117262306a36Sopenharmony_ci/* 117362306a36Sopenharmony_ci * Verbs used by the driver code for DMAable memory handling. 117462306a36Sopenharmony_ci * The _uvptv_ macro avoids a nasty warning about pointer to volatile 117562306a36Sopenharmony_ci * being discarded. 117662306a36Sopenharmony_ci */ 117762306a36Sopenharmony_ci#define _uvptv_(p) ((void *)((u_long)(p))) 117862306a36Sopenharmony_ci 117962306a36Sopenharmony_ci#define _sym_calloc_dma(np, l, n) __sym_calloc_dma(np->bus_dmat, l, n) 118062306a36Sopenharmony_ci#define _sym_mfree_dma(np, p, l, n) \ 118162306a36Sopenharmony_ci __sym_mfree_dma(np->bus_dmat, _uvptv_(p), l, n) 118262306a36Sopenharmony_ci#define sym_calloc_dma(l, n) _sym_calloc_dma(np, l, n) 118362306a36Sopenharmony_ci#define sym_mfree_dma(p, l, n) _sym_mfree_dma(np, p, l, n) 118462306a36Sopenharmony_ci#define vtobus(p) __vtobus(np->bus_dmat, _uvptv_(p)) 118562306a36Sopenharmony_ci 118662306a36Sopenharmony_ci/* 118762306a36Sopenharmony_ci * We have to provide the driver memory allocator with methods for 118862306a36Sopenharmony_ci * it to maintain virtual to bus physical address translations. 118962306a36Sopenharmony_ci */ 119062306a36Sopenharmony_ci 119162306a36Sopenharmony_ci#define sym_m_pool_match(mp_id1, mp_id2) (mp_id1 == mp_id2) 119262306a36Sopenharmony_ci 119362306a36Sopenharmony_cistatic inline void *sym_m_get_dma_mem_cluster(m_pool_p mp, m_vtob_p vbp) 119462306a36Sopenharmony_ci{ 119562306a36Sopenharmony_ci void *vaddr = NULL; 119662306a36Sopenharmony_ci dma_addr_t baddr = 0; 119762306a36Sopenharmony_ci 119862306a36Sopenharmony_ci vaddr = dma_alloc_coherent(mp->dev_dmat, SYM_MEM_CLUSTER_SIZE, &baddr, 119962306a36Sopenharmony_ci GFP_ATOMIC); 120062306a36Sopenharmony_ci if (vaddr) { 120162306a36Sopenharmony_ci vbp->vaddr = vaddr; 120262306a36Sopenharmony_ci vbp->baddr = baddr; 120362306a36Sopenharmony_ci } 120462306a36Sopenharmony_ci return vaddr; 120562306a36Sopenharmony_ci} 120662306a36Sopenharmony_ci 120762306a36Sopenharmony_cistatic inline void sym_m_free_dma_mem_cluster(m_pool_p mp, m_vtob_p vbp) 120862306a36Sopenharmony_ci{ 120962306a36Sopenharmony_ci dma_free_coherent(mp->dev_dmat, SYM_MEM_CLUSTER_SIZE, vbp->vaddr, 121062306a36Sopenharmony_ci vbp->baddr); 121162306a36Sopenharmony_ci} 121262306a36Sopenharmony_ci 121362306a36Sopenharmony_ci#endif /* SYM_HIPD_H */ 1214