linux/drivers/scsi/sym53c8xx_2/sym_hipd.h

/* SPDX-License-Identifier: GPL-2.0-or-later */
/*
 * Device driver for the SYMBIOS/LSILOGIC 53C8XX and 53C1010 family 
 * of PCI-SCSI IO processors.
 *
 * Copyright (C) 1999-2001  Gerard Roudier <[email protected]>
 *
 * This driver is derived from the Linux sym53c8xx driver.
 * Copyright (C) 1998-2000  Gerard Roudier
 *
 * The sym53c8xx driver is derived from the ncr53c8xx driver that had been 
 * a port of the FreeBSD ncr driver to Linux-1.2.13.
 *
 * The original ncr driver has been written for 386bsd and FreeBSD by
 *         Wolfgang Stanglmeier        <[email protected]>
 *         Stefan Esser                <[email protected]>
 * Copyright (C) 1994  Wolfgang Stanglmeier
 *
 * Other major contributions:
 *
 * NVRAM detection and reading.
 * Copyright (C) 1997 Richard Waltham <[email protected]>
 *
 *-----------------------------------------------------------------------------
 */

#include <linux/gfp.h>

#ifndef SYM_HIPD_H
#define SYM_HIPD_H

/*
 *  Generic driver options.
 *
 *  They may be defined in platform specific headers, if they 
 *  are useful.
 *
 *    SYM_OPT_HANDLE_DEVICE_QUEUEING
 *        When this option is set, the driver will use a queue per 
 *        device and handle QUEUE FULL status requeuing internally.
 *
 *    SYM_OPT_LIMIT_COMMAND_REORDERING
 *        When this option is set, the driver tries to limit tagged 
 *        command reordering to some reasonable value.
 *        (set for Linux)
 */
#if 0
#define SYM_OPT_HANDLE_DEVICE_QUEUEING
#define SYM_OPT_LIMIT_COMMAND_REORDERING
#endif

/*
 *  Active debugging tags and verbosity.
 *  Both DEBUG_FLAGS and sym_verbose can be redefined 
 *  by the platform specific code to something else.
 */
#define DEBUG_ALLOC
#define DEBUG_PHASE
#define DEBUG_POLL
#define DEBUG_QUEUE
#define DEBUG_RESULT
#define DEBUG_SCATTER
#define DEBUG_SCRIPT
#define DEBUG_TINY
#define DEBUG_TIMING
#define DEBUG_NEGO
#define DEBUG_TAGS
#define DEBUG_POINTER

#ifndef DEBUG_FLAGS
#define DEBUG_FLAGS
#endif

#ifndef sym_verbose
#define sym_verbose
#endif

/*
 *  These ones should have been already defined.
 */
#ifndef assert
#define assert(expression)
#endif

/*
 *  Number of tasks per device we want to handle.
 */
#if	SYM_CONF_MAX_TAG_ORDER > 8
#error	"more than 256 tags per logical unit not allowed."
#endif
#define SYM_CONF_MAX_TASK

/*
 *  Donnot use more tasks that we can handle.
 */
#ifndef	SYM_CONF_MAX_TAG
#define SYM_CONF_MAX_TAG
#endif
#if	SYM_CONF_MAX_TAG > SYM_CONF_MAX_TASK
#undef	SYM_CONF_MAX_TAG
#define SYM_CONF_MAX_TAG
#endif

/*
 *    This one means 'NO TAG for this job'
 */
#define NO_TAG

/*
 *  Number of SCSI targets.
 */
#if	SYM_CONF_MAX_TARGET > 16
#error	"more than 16 targets not allowed."
#endif

/*
 *  Number of logical units per target.
 */
#if	SYM_CONF_MAX_LUN > 64
#error	"more than 64 logical units per target not allowed."
#endif

/*
 *    Asynchronous pre-scaler (ns). Shall be 40 for 
 *    the SCSI timings to be compliant.
 */
#define SYM_CONF_MIN_ASYNC


/*
 * MEMORY ALLOCATOR.
 */

#define SYM_MEM_WARN

#define SYM_MEM_PAGE_ORDER
#define SYM_MEM_CLUSTER_SHIFT
#define SYM_MEM_FREE_UNUSED
/*
 *  Shortest memory chunk is (1<<SYM_MEM_SHIFT), currently 16.
 *  Actual allocations happen as SYM_MEM_CLUSTER_SIZE sized.
 *  (1 PAGE at a time is just fine).
 */
#define SYM_MEM_SHIFT
#define SYM_MEM_CLUSTER_SIZE
#define SYM_MEM_CLUSTER_MASK

/*
 *  Number of entries in the START and DONE queues.
 *
 *  We limit to 1 PAGE in order to succeed allocation of 
 *  these queues. Each entry is 8 bytes long (2 DWORDS).
 */
#ifdef	SYM_CONF_MAX_START
#define SYM_CONF_MAX_QUEUE
#else
#define SYM_CONF_MAX_QUEUE
#define SYM_CONF_MAX_START
#endif

#if	SYM_CONF_MAX_QUEUE > SYM_MEM_CLUSTER_SIZE/8
#undef	SYM_CONF_MAX_QUEUE
#define SYM_CONF_MAX_QUEUE
#undef	SYM_CONF_MAX_START
#define SYM_CONF_MAX_START
#endif

/*
 *  For this one, we want a short name :-)
 */
#define MAX_QUEUE

/*
 *  Common definitions for both bus space based and legacy IO methods.
 */

#define INB_OFF(np, o)
#define INW_OFF(np, o)
#define INL_OFF(np, o)

#define OUTB_OFF(np, o, val)
#define OUTW_OFF(np, o, val)
#define OUTL_OFF(np, o, val)

#define INB(np, r)
#define INW(np, r)
#define INL(np, r)

#define OUTB(np, r, v)
#define OUTW(np, r, v)
#define OUTL(np, r, v)

#define OUTONB(np, r, m)
#define OUTOFFB(np, r, m)
#define OUTONW(np, r, m)
#define OUTOFFW(np, r, m)
#define OUTONL(np, r, m)
#define OUTOFFL(np, r, m)

/*
 *  We normally want the chip to have a consistent view
 *  of driver internal data structures when we restart it.
 *  Thus these macros.
 */
#define OUTL_DSP(np, v)

#define OUTONB_STD()

/*
 *  Command control block states.
 */
#define HS_IDLE
#define HS_BUSY
#define HS_NEGOTIATE
#define HS_DISCONNECT
#define HS_WAIT

#define HS_DONEMASK
#define HS_COMPLETE
#define HS_SEL_TIMEOUT
#define HS_UNEXPECTED
#define HS_COMP_ERR

/*
 *  Software Interrupt Codes
 */
#define SIR_BAD_SCSI_STATUS
#define SIR_SEL_ATN_NO_MSG_OUT
#define SIR_MSG_RECEIVED
#define SIR_MSG_WEIRD
#define SIR_NEGO_FAILED
#define SIR_NEGO_PROTO
#define SIR_SCRIPT_STOPPED
#define SIR_REJECT_TO_SEND
#define SIR_SWIDE_OVERRUN
#define SIR_SODL_UNDERRUN
#define SIR_RESEL_NO_MSG_IN
#define SIR_RESEL_NO_IDENTIFY
#define SIR_RESEL_BAD_LUN
#define SIR_TARGET_SELECTED
#define SIR_RESEL_BAD_I_T_L
#define SIR_RESEL_BAD_I_T_L_Q
#define SIR_ABORT_SENT
#define SIR_RESEL_ABORTED
#define SIR_MSG_OUT_DONE
#define SIR_COMPLETE_ERROR
#define SIR_DATA_OVERRUN
#define SIR_BAD_PHASE
#if	SYM_CONF_DMA_ADDRESSING_MODE == 2
#define SIR_DMAP_DIRTY
#define SIR_MAX
#else
#define SIR_MAX
#endif

/*
 *  Extended error bit codes.
 *  xerr_status field of struct sym_ccb.
 */
#define XE_EXTRA_DATA
#define XE_BAD_PHASE
#define XE_PARITY_ERR
#define XE_SODL_UNRUN
#define XE_SWIDE_OVRUN

/*
 *  Negotiation status.
 *  nego_status field of struct sym_ccb.
 */
#define NS_SYNC
#define NS_WIDE
#define NS_PPR

/*
 *  A CCB hashed table is used to retrieve CCB address 
 *  from DSA value.
 */
#define CCB_HASH_SHIFT
#define CCB_HASH_SIZE
#define CCB_HASH_MASK
#if 1
#define CCB_HASH_CODE(dsa)
#else
#define CCB_HASH_CODE
#endif

#if	SYM_CONF_DMA_ADDRESSING_MODE == 2
/*
 *  We may want to use segment registers for 64 bit DMA.
 *  16 segments registers -> up to 64 GB addressable.
 */
#define SYM_DMAP_SHIFT
#define SYM_DMAP_SIZE
#define SYM_DMAP_MASK
#endif

/*
 *  Device flags.
 */
#define SYM_DISC_ENABLED
#define SYM_TAGS_ENABLED
#define SYM_SCAN_BOOT_DISABLED
#define SYM_SCAN_LUNS_DISABLED

/*
 *  Host adapter miscellaneous flags.
 */
#define SYM_AVOID_BUS_RESET

/*
 *  Misc.
 */
#define SYM_SNOOP_TIMEOUT
#define BUS_8_BIT
#define BUS_16_BIT

/*
 *  Gather negotiable parameters value
 */
struct sym_trans {};

/*
 *  Global TCB HEADER.
 *
 *  Due to lack of indirect addressing on earlier NCR chips,
 *  this substructure is copied from the TCB to a global 
 *  address after selection.
 *  For SYMBIOS chips that support LOAD/STORE this copy is 
 *  not needed and thus not performed.
 */
struct sym_tcbh {};

/*
 *  Target Control Block
 */
struct sym_tcb {};

/*
 *  Global LCB HEADER.
 *
 *  Due to lack of indirect addressing on earlier NCR chips,
 *  this substructure is copied from the LCB to a global 
 *  address after selection.
 *  For SYMBIOS chips that support LOAD/STORE this copy is 
 *  not needed and thus not performed.
 */
struct sym_lcbh {};

/*
 *  Logical Unit Control Block
 */
struct sym_lcb {};

/*
 *  Action from SCRIPTS on a task.
 *  Is part of the CCB, but is also used separately to plug 
 *  error handling action to perform from SCRIPTS.
 */
struct sym_actscr {};

/*
 *  Phase mismatch context.
 *
 *  It is part of the CCB and is used as parameters for the 
 *  DATA pointer. We need two contexts to handle correctly the 
 *  SAVED DATA POINTER.
 */
struct sym_pmc {};

/*
 *  LUN control block lookup.
 *  We use a direct pointer for LUN #0, and a table of 
 *  pointers which is only allocated for devices that support 
 *  LUN(s) > 0.
 */
#if SYM_CONF_MAX_LUN <= 1
#define sym_lp
#else
#define sym_lp(tp, lun)
#endif

/*
 *  Status are used by the host and the script processor.
 *
 *  The last four bytes (status[4]) are copied to the 
 *  scratchb register (declared as scr0..scr3) just after the 
 *  select/reselect, and copied back just after disconnecting.
 *  Inside the script the XX_REG are used.
 */

/*
 *  Last four bytes (script)
 */
#define HX_REG
#define HX_PRT
#define HS_REG
#define HS_PRT
#define SS_REG
#define SS_PRT
#define HF_REG
#define HF_PRT

/*
 *  Last four bytes (host)
 */
#define host_xflags
#define host_status
#define ssss_status
#define host_flags

/*
 *  Host flags
 */
#define HF_IN_PM0
#define HF_IN_PM1
#define HF_ACT_PM
#define HF_DP_SAVED
#define HF_SENSE
#define HF_EXT_ERR
#define HF_DATA_IN
#ifdef SYM_CONF_IARB_SUPPORT
#define HF_HINT_IARB
#endif

/*
 *  More host flags
 */
#if	SYM_CONF_DMA_ADDRESSING_MODE == 2
#define HX_DMAP_DIRTY
#endif

/*
 *  Global CCB HEADER.
 *
 *  Due to lack of indirect addressing on earlier NCR chips,
 *  this substructure is copied from the ccb to a global 
 *  address after selection (or reselection) and copied back 
 *  before disconnect.
 *  For SYMBIOS chips that support LOAD/STORE this copy is 
 *  not needed and thus not performed.
 */

struct sym_ccbh {};

/*
 *  GET/SET the value of the data pointer used by SCRIPTS.
 *
 *  We must distinguish between the LOAD/STORE-based SCRIPTS 
 *  that use directly the header in the CCB, and the NCR-GENERIC 
 *  SCRIPTS that use the copy of the header in the HCB.
 */
#if	SYM_CONF_GENERIC_SUPPORT
#define sym_set_script_dp(np, cp, dp)
#define sym_get_script_dp(np, cp)
#else
#define sym_set_script_dp

#define sym_get_script_dp
#endif

/*
 *  Data Structure Block
 *
 *  During execution of a ccb by the script processor, the 
 *  DSA (data structure address) register points to this 
 *  substructure of the ccb.
 */
struct sym_dsb {};

/*
 *  Our Command Control Block
 */
struct sym_ccb {};

#define CCB_BA(cp,lbl)

m_pool_ident_t;

/*
 *  Host Control Block
 */
struct sym_hcb {};

#if SYM_CONF_DMA_ADDRESSING_MODE == 0
#define use_dac
#define set_dac
#else
#define use_dac(np)
#define set_dac(np)
#endif

#define HCB_BA(np, lbl)


/*
 *  FIRMWARES (sym_fw.c)
 */
struct sym_fw * sym_find_firmware(struct sym_chip *chip);
void sym_fw_bind_script(struct sym_hcb *np, u32 *start, int len);

/*
 *  Driver methods called from O/S specific code.
 */
char *sym_driver_name(void);
void sym_print_xerr(struct scsi_cmnd *cmd, int x_status);
int sym_reset_scsi_bus(struct sym_hcb *np, int enab_int);
struct sym_chip *sym_lookup_chip_table(u_short device_id, u_char revision);
#ifdef SYM_OPT_HANDLE_DEVICE_QUEUEING
void sym_start_next_ccbs(struct sym_hcb *np, struct sym_lcb *lp, int maxn);
#else
void sym_put_start_queue(struct sym_hcb *np, struct sym_ccb *cp);
#endif
void sym_start_up(struct Scsi_Host *, int reason);
irqreturn_t sym_interrupt(struct Scsi_Host *);
int sym_clear_tasks(struct sym_hcb *np, int cam_status, int target, int lun, int task);
struct sym_ccb *sym_get_ccb(struct sym_hcb *np, struct scsi_cmnd *cmd, u_char tag_order);
void sym_free_ccb(struct sym_hcb *np, struct sym_ccb *cp);
struct sym_lcb *sym_alloc_lcb(struct sym_hcb *np, u_char tn, u_char ln);
int sym_free_lcb(struct sym_hcb *np, u_char tn, u_char ln);
int sym_queue_scsiio(struct sym_hcb *np, struct scsi_cmnd *csio, struct sym_ccb *cp);
int sym_abort_scsiio(struct sym_hcb *np, struct scsi_cmnd *ccb, int timed_out);
int sym_reset_scsi_target(struct sym_hcb *np, int target);
void sym_hcb_free(struct sym_hcb *np);
int sym_hcb_attach(struct Scsi_Host *shost, struct sym_fw *fw, struct sym_nvram *nvram);

/*
 *  Build a scatter/gather entry.
 *
 *  For 64 bit systems, we use the 8 upper bits of the size field 
 *  to provide bus address bits 32-39 to the SCRIPTS processor.
 *  This allows the 895A, 896, 1010 to address up to 1 TB of memory.
 */

#if   SYM_CONF_DMA_ADDRESSING_MODE == 0
#define DMA_DAC_MASK
#define sym_build_sge
#elif SYM_CONF_DMA_ADDRESSING_MODE == 1
#define DMA_DAC_MASK
#define sym_build_sge(np, data, badd, len)
#elif SYM_CONF_DMA_ADDRESSING_MODE == 2
#define DMA_DAC_MASK
int sym_lookup_dmap(struct sym_hcb *np, u32 h, int s);
static inline void
sym_build_sge(struct sym_hcb *np, struct sym_tblmove *data, u64 badd, int len)
{
	u32 h = (badd>>32);
	int s = (h&SYM_DMAP_MASK);

	if (h != np->dmap_bah[s])
		goto bad;
good:
	(data)->addr = cpu_to_scr(badd);
	(data)->size = cpu_to_scr((s<<24) + len);
	return;
bad:
	s = sym_lookup_dmap(np, h, s);
	goto good;
}
#else
#error "Unsupported DMA addressing mode"
#endif

/*
 *  MEMORY ALLOCATOR.
 */

#define sym_get_mem_cluster()
#define sym_free_mem_cluster(p)

/*
 *  Link between free memory chunks of a given size.
 */
m_link_p;

/*
 *  Virtual to bus physical translation for a given cluster.
 *  Such a structure is only useful with DMA abstraction.
 */
m_vtob_p;

/* Hash this stuff a bit to speed up translations */
#define VTOB_HASH_SHIFT
#define VTOB_HASH_SIZE
#define VTOB_HASH_MASK
#define VTOB_HASH_CODE(m)

/*
 *  Memory pool of a given kind.
 *  Ideally, we want to use:
 *  1) 1 pool for memory we donnot need to involve in DMA.
 *  2) The same pool for controllers that require same DMA 
 *     constraints and features.
 *     The OS specific m_pool_id_t thing and the sym_m_pool_match() 
 *     method are expected to tell the driver about.
 */
m_pool_p;

/*
 *  Alloc, free and translate addresses to bus physical 
 *  for DMAable memory.
 */
void *__sym_calloc_dma(m_pool_ident_t dev_dmat, int size, char *name);
void __sym_mfree_dma(m_pool_ident_t dev_dmat, void *m, int size, char *name);
dma_addr_t __vtobus(m_pool_ident_t dev_dmat, void *m);

/*
 * Verbs used by the driver code for DMAable memory handling.
 * The _uvptv_ macro avoids a nasty warning about pointer to volatile 
 * being discarded.
 */
#define _uvptv_(p)

#define _sym_calloc_dma(np, l, n)
#define _sym_mfree_dma(np, p, l, n)
#define sym_calloc_dma(l, n)
#define sym_mfree_dma(p, l, n)
#define vtobus(p)

/*
 *  We have to provide the driver memory allocator with methods for 
 *  it to maintain virtual to bus physical address translations.
 */

#define sym_m_pool_match(mp_id1, mp_id2)

static inline void *sym_m_get_dma_mem_cluster(m_pool_p mp, m_vtob_p vbp)
{}

static inline void sym_m_free_dma_mem_cluster(m_pool_p mp, m_vtob_p vbp)
{}

#endif /* SYM_HIPD_H */