/* @(#)espreg.h 1.1 94/10/31 */

#ifndef _scsi_adapters_espreg_h
#define	_scsi_adapters_espreg_h

/*
 * Copyright (c) 1988-1991 by Sun Microsystems, Inc.
 */

/*
 * Hardware definitions for ESP (Enhanced SCSI Processor) generation chips.
 */

/*
 * Include definition of DMA, DMA+, and ESC gate arrays
 */

#include <sundev/dmaga.h>

/*
 * ESP register definitions.
 */

/*
 * All current Sun implementations use the following layout.
 * That is, the ESP registers are always byte-wide, but are
 * accessed longwords apart. Notice also that the byte-ordering
 * is big-endian.
 */

struct espreg {
	u_char	esp_xcnt_lo;		/* RW: transfer counter (low byte) */
					u_char _pad1, _pad2, _pad3;

	u_char	esp_xcnt_mid;		/* RW: transfer counter (mid byte) */
					u_char _pad5, _pad6, _pad7;

	u_char	esp_fifo_data;		/* RW: fifo data buffer */
					u_char _pad9, _pad10, _pad11;

	u_char	esp_cmd;		/* RW: command register */
					u_char _pad13, _pad14, _pad15;

	u_char	esp_stat;		/* R: status register */
#define	esp_busid	esp_stat	/* W: bus id for sel/resel */
					u_char _pad17, _pad18, _pad19;


	u_char	esp_intr;		/* R: interrupt status register */
#define	esp_timeout	esp_intr	/* W: sel/resel timeout */
					u_char _pad21, _pad22, _pad23;


	u_char	esp_step;		/* R: sequence step register */
#define	esp_sync_period esp_step	/* W: synchronous period */
					u_char _pad25, _pad26, _pad27;


	u_char	esp_fifo_flag;		/* R: fifo flag register */
#define	esp_sync_offset esp_fifo_flag	/* W: synchronous offset */
					u_char _pad29, _pad30, _pad31;


	u_char	esp_conf;		/* RW: configuration register */
					u_char _pad33, _pad34, _pad35;


	u_char	esp_clock_conv;		/* W: clock conversion register */
					u_char _pad37, _pad38, _pad39;


	u_char	esp_test;		/* RW: test register */
					u_char _pad41, _pad42, _pad43;


	u_char	esp_conf2;		/* ESP-II configuration register */
					u_char _pad45, _pad46, _pad47;

	u_char	esp_conf3;		/* ESP-III configuration register */
					u_char _pad49, _pad50, _pad51;

					u_char _pad52, _pad53, _pad54, _pad55;

	u_char	esp_xcnt_hi;		/* RW: transfer counter (hi byte) */
#define	esp_id_code esp_xcnt_hi		/* R: part-unique id code */
					u_char _pad57, _pad58, _pad59;

	u_char	esp_fifo_bottom;	/* RW: fifo data bottom */
					u_char _pad61, _pad62, _pad63;
};


/*
 * ESP command register definitions
 */

/*
 * These commands may be used at any time with the ESP chip.
 * None generate an interrupt, per se, although if you have
 * enabled detection of SCSI reset in setting the configuration
 * register, a CMD_RESET_SCSI will generate an interrupt.
 * Therefore, it is recommended that if you use the CMD_RESET_SCSI
 * command, you at least temporarily disable recognition of
 * SCSI reset in the configuration register.
 */

#define	CMD_NOP		0x0
#define	CMD_FLUSH	0x1
#define	CMD_RESET_ESP	0x2
#define	CMD_RESET_SCSI	0x3

/*
 * These commands will only work if the ESP is in the
 * 'disconnected' state:
 */

#define	CMD_RESEL_SEQ	0x40
#define	CMD_SEL_NOATN	0x41
#define	CMD_SEL_ATN	0x42
#define	CMD_SEL_STOP	0x43
#define	CMD_EN_RESEL	0x44	/* (no interrupt generated) */
#define	CMD_DIS_RESEL	0x45
#define	CMD_SEL_ATN3	0x46	/* (ESP100A/200, ESP236 only) */

/*
 * These commands will only work if the ESP is connected as
 * an initiator to a target:
 */

#define	CMD_TRAN_INFO	0x10
#define	CMD_COMP_SEQ	0x11
#define	CMD_MSG_ACPT	0x12
#define	CMD_TRAN_PAD	0x18
#define	CMD_SET_ATN	0x1a	/* (no interrupt generated) */
#define	CMD_CLR_ATN	0x1b	/* (no interrupt generated) (ESP236 only) */

/*
 * DMA enable bit
 */

#define	CMD_DMA		0x80

/*
 * ESP fifo register definitions (read only)
 *
 * The first four bits are the count of bytes
 * in the fifo.
 *
 * Bit 5 is a 'offset counter not zero' flag for
 * the ESP100 only. On the ESP100A, the top 3 bits
 * of the fifo register are the 3 bits of the Sequence
 * Step register (if the ESP100A is not in TEST mode.
 * If the ESP100A is in TEST mode, then bit 5 has
 * the 'offset counter not zero' function). At least,
 * so states the documentation.
 *
 */

#define	FIFOSIZE		16
#define	MAX_FIFO_FLAG		(FIFOSIZE-1)
#define	ESP_FIFO_ONZ		0x20


/*
 * ESP status register definitions (read only)
 */

#define	ESP_STAT_RES	0x80	/* reserved (ESP100, ESP100A) */
#define	ESP_STAT_IPEND	0x80	/* interrupt pending (ESP-236 only) */
#define	ESP_STAT_GERR	0x40	/* gross error */
#define	ESP_STAT_PERR	0x20	/* parity error */
#define	ESP_STAT_XZERO	0x10	/* transfer counter zero */
#define	ESP_STAT_XCMP	0x8	/* transfer completed (target mode only) */
#define	ESP_STAT_MSG	0x4	/* scsi phase bit: MSG */
#define	ESP_STAT_CD	0x2	/* scsi phase bit: CD */
#define	ESP_STAT_IO	0x1	/* scsi phase bit: IO */

#define	ESP_STAT_BITS	\
	"\20\10IPND\07GERR\06PERR\05XZERO\04XCMP\03MSG\02CD\01IO"

/*
 * settings of status to reflect different information transfer phases
 */

#define	ESP_PHASE_MASK		(ESP_STAT_MSG | ESP_STAT_CD | ESP_STAT_IO)
#define	ESP_PHASE_DATA_OUT	0
#define	ESP_PHASE_DATA_IN	(ESP_STAT_IO)
#define	ESP_PHASE_COMMAND	(ESP_STAT_CD)
#define	ESP_PHASE_STATUS	(ESP_STAT_CD | ESP_STAT_IO)
#define	ESP_PHASE_MSG_OUT	(ESP_STAT_MSG | ESP_STAT_CD)
#define	ESP_PHASE_MSG_IN	(ESP_STAT_MSG | ESP_STAT_CD | ESP_STAT_IO)

/*
 * ESP interrupt status register definitions (read only)
 */

#define	ESP_INT_RESET	0x80	/* SCSI reset detected */
#define	ESP_INT_ILLEGAL 0x40	/* illegal cmd */
#define	ESP_INT_DISCON	0x20	/* disconnect */
#define	ESP_INT_BUS	0x10	/* bus service */
#define	ESP_INT_FCMP	0x8	/* function completed */
#define	ESP_INT_RESEL	0x4	/* reselected */
#define	ESP_INT_SELATN	0x2	/* selected with ATN */
#define	ESP_INT_SEL	0x1	/* selected without ATN */

#define	ESP_INT_BITS	\
	"\20\10RST\07ILL\06DISC\05BUS\04FCMP\03RESEL\02SATN\01SEL"

/*
 * ESP step register- only the least significant 3 bits are valid
 */

#define	ESP_STEP_MASK	0x7

#define	ESP_STEP_ARBSEL 0	/*
				 * Arbitration and select completed.
				 * Not MESSAGE OUT phase. ATN* asserted.
				 */

#define	ESP_STEP_SENTID 1	/*
				 * Sent one message byte. ATN* asserted.
				 * (SELECT AND STOP command only).
				 */

#define	ESP_STEP_NOTCMD 2	/*
				 * For SELECT WITH ATN command:
				 *	Sent one message byte. ATN* off.
				 *	Not COMMAND phase.
				 *
				 * For SELECT WITHOUT ATN command:
				 *
				 *	Not COMMAND phase.
				 *
				 * For SELECT WITH ATN3 command:
				 *	Sent one to three message bytes.
				 *	Stopped due to unexpected phase
				 *	change. If third message byte
				 *	not sent, ATN* asserted.
				 */

#define	ESP_STEP_PCMD	3	/*
				 * Not all of command bytes transferred
				 * due to premature phase change.
				 */

#define	ESP_STEP_DONE	4	/*
				 * Complete sequence.
				 */

/*
 * ESP configuration register definitions (read/write)
 */

#define	ESP_CONF_SLOWMODE	0x80	/* slow cable mode */
#define	ESP_CONF_DISRINT	0x40	/* disable reset int */
#define	ESP_CONF_PARTEST	0x20	/* parity test mode */
#define	ESP_CONF_PAREN		0x10	/* enable parity */
#define	ESP_CONF_CHIPTEST	0x8	/* chip test mode */
#define	ESP_CONF_BUSID		0x7	/* last 3 bits to be host id */

#define	DEFAULT_HOSTID		7

/*
 * ESP test register definitions (read/write)
 */

#define	ESP_TEST_TGT		0x1	/* target test mode */
#define	ESP_TEST_INI		0x2	/* initiator test mode */
#define	ESP_TEST_TRI		0x4	/* tristate test mode */

/*
 * ESP configuration register #2 definitions (read/write)
 * (ESP100A, ESP200, or ESP236 only)
 */

#define	ESP_CONF2_RESETF	0x80	/* Reserve FIFO byte (ESP-236 only) */

#define	ESP_CONF2_FENABLE	0x40	/* Features Enable (FAS100,216 only) */

#define	ESP_CONF2_STATPL	0x40	/*
					 * Enable Status Phase Latch
					 * (ESP-236 only)
					 */

#define	ESP_CONF2_BYTECM	0x20	/*
					 * Enable Byte Control Mode
					 * (ESP-236 only)
					 */

#define	ESP_CONF2_TRIDMA	0x10	/* Tristate DMA REQ */
#define	ESP_CONF2_SCSI2		0x8	/* SCSI-2 mode (target mode only) */
#define	ESP_CONF2_TBADPAR	0x4	/* Target Bad Parity Abort */

#define	ESP_CONF2_REGPAR	0x2	/*
					 * Register Parity Enable
					 * (ESP200, ESP236 only)
					 */

#define	ESP_CONF2_DMAPAR	0x1	/*
					 * DMA parity enable
					 * (ESP200, ESP236 only)
					 */

/*
 * ESP configuration #3 register definitions (read/write)
 * (ESP236, FAS236, and FAS100A)
 */

#define	ESP_CONF3_236_IDRESCHK	0x80	/* ID message checking */
#define	ESP_CONF3_236_QUENB		0x40	/* 3-byte msg support */
#define	ESP_CONF3_236_CDB10		0x20	/* group 2 scsi-2 support */
#define	ESP_CONF3_236_FASTSCSI	0x10	/* 10 MB/S fast scsi mode */
#define	ESP_CONF3_236_FASTCLK	0x8	/* fast clock mode */
#define	ESP_CONF3_236_SAVERESB	0x4	/* save residual byte */
#define	ESP_CONF3_236_ALTDMA	0x2	/* enable alternate DMA mode */
#define	ESP_CONF3_236_THRESH8	0x1	/* enable threshold-8 mode */

#define	ESP_CONF3_100A_IDRESCHK 0x10	/* ID message checking */
#define	ESP_CONF3_100A_QUENB		0x8	/* 3-byte msg support */
#define	ESP_CONF3_100A_CDB10		0x4	/* group 2 scsi-2 support */
#define	ESP_CONF3_100A_FASTSCSI 0x2	/* 10 MB/S fast scsi mode */
#define	ESP_CONF3_100A_FASTCLK	0x1	/* fast clock mode */

/*
 * ESP part-unique id code definitions (read only)
 * (FAS236 and FAS100A only)
 */

#define	ESP_FAS100A		0x0	/* chip family code 0 */
#define	ESP_FAS236		0x2	/* chip family code 2 */
#define	ESP_REV_MASK		0x7	/* revision level mask */
#define	ESP_FCODE_MASK		0xf8	/* revision family code mask */

/*
 * Macros to get/set an integer (long or short) word into the 2 or 3  8-bit
 * registers that constitute the ESP's counter register.
 */

#define	SET_ESP_COUNT_16(ep, val)	\
	(ep)->esp_xcnt_lo = (val), (ep)->esp_xcnt_mid = ((val) >> 8)
#define	GET_ESP_COUNT_16(ep, val)	\
	(val) = (u_long) (ep)->esp_xcnt_lo |\
	(((u_long) (ep)->esp_xcnt_mid) << 8)
#define	SET_ESP_COUNT_24(ep, val)	\
	(ep)->esp_xcnt_lo = (val), (ep)->esp_xcnt_mid = ((val) >> 8), \
	(ep)->esp_xcnt_hi = ((val) >> 16)
#define	GET_ESP_COUNT_24(ep, val)	\
	(val) = (u_long) (ep)->esp_xcnt_lo | \
	(((u_long) (ep)->esp_xcnt_mid) << 8) | \
	(((u_long) (ep)->esp_xcnt_hi) << 16)

#define	GET_ESP_COUNT(ep, val)	\
	if (esp->e_espconf2 & 0x40) \
		GET_ESP_COUNT_24(ep, val); \
	else \
		GET_ESP_COUNT_16(ep, val);

#define	SET_ESP_COUNT(ep, val)	\
	if (esp->e_espconf2 & 0x40) \
		SET_ESP_COUNT_24(ep, val); \
	else \
		SET_ESP_COUNT_16(ep, val);



/*
 * The counter is a 16 bit counter only for the ESP.
 * If loaded with zero, it will do the full 64kb. If
 * we define maxcount to be 64kb, then the low order
 * 16 bits will be zero, and the register will be
 * properly loaded.
 */

#define	ESP_MAX_DMACOUNT	(64<<10)

/*
 * ESP Clock constants
 */

/*
 * The probe routine will select amongst these values
 * and stuff it into the tag e_clock_conv in the private host
 * adapter structure (see below) (as well as the the register esp_clock_conv
 * on the chip)
 */

#define	CLOCK_10MHZ		2
#define	CLOCK_15MHZ		3
#define	CLOCK_20MHZ		4
#define	CLOCK_25MHZ		5
#define	CLOCK_30MHZ		6
#define	CLOCK_35MHZ		7
#define	CLOCK_40MHZ		8	/* really 0 */
#define	CLOCK_MASK		0x7

/*
 * This yields nanoseconds per input clock tick
 */

#define	CLOCK_PERIOD(mhz)	(1000 * MEG) /(mhz / 1000)
#define	CONVERT_PERIOD(time)	((time)+3) >>2

/*
 * Formula to compute the select/reselect timeout register value:
 *
 *	Time_unit = 7682 * CCF * Input_Clock_Period
 *
 * where Time_unit && Input_Clock_Period should be in the same units.
 * CCF = Clock Conversion Factor from CLOCK_XMHZ above.
 * Desired_Timeout_Period = 250 ms.
 *
 */

#define	ESP_CLOCK_DELAY 7682
#define	ESP_CLOCK_TICK(esp)	\
	(ESP_CLOCK_DELAY * (esp)->e_clock_conv * (esp)->e_clock_cycle) / 1000
#define	ESP_SEL_TIMEOUT (250 * MEG)
#define	ESP_CLOCK_TIMEOUT(tick) \
	(ESP_SEL_TIMEOUT + (tick) - 1) / (tick)

/*
 * Max/Min number of clock cycles for synchronous period
 */

#define	MIN_SYNC_FAST(esp)	4
#define	MIN_SYNC_SLOW(esp)	\
	(((esp)->e_espconf & ESP_CONF_SLOWMODE)? 6: 5)
#define	MIN_SYNC(esp)	\
	((((esp)->e_type == FAS236) || ((esp)->e_type == FAS100A)) ? \
	MIN_SYNC_FAST(esp) : MIN_SYNC_SLOW(esp))
#define	MAX_SYNC(esp)		35
#define	SYNC_PERIOD_MASK	0x1F
#define FASTSCSI_THRESHOLD	50		/* 5 MB/s */

/*
 * Max/Min time (in nanoseconds) between successive Req/Ack
 */

#define	MIN_SYNC_TIME(esp)	(MIN_SYNC((esp))*(esp)->e_clock_cycle) / 1000
#define	MAX_SYNC_TIME(esp)	(MAX_SYNC((esp))*(esp)->e_clock_cycle) / 1000

/*
 * Max/Min Period values (appropriate for SYNCHRONOUS message).
 * We round up here to make sure that we are always slower
 * (longer time period).
 */

#define	MIN_SYNC_PERIOD(esp)	(CONVERT_PERIOD(MIN_SYNC_TIME((esp))))
#define	MAX_SYNC_PERIOD(esp)	(CONVERT_PERIOD(MAX_SYNC_TIME((esp))))

/*
 * According to the Emulex application notes for this part,
 * the ability to receive synchronous data is independent
 * of the ESP chip's input clock rate, and is fixed at
 * a maximum 5.6 mb/s (180 ns/byte).
 *
 * Therefore, we can tell targets that we can *receive*
 * synchronous data this fast.
 */

#define	DEFAULT_SYNC_PERIOD		180		/* 5.6 MB/s */
#define	DEFAULT_FASTSYNC_PERIOD		100		/* 10.0 MB/s */


/*
 * Short hand macro convert parameter in
 * nanoseconds/byte into k-bytes/second.
 */

#define	ESP_SYNC_KBPS(ns)	((((1000*MEG)/(ns))+999)/1000)


/*
 * Default Synchronous offset.
 * (max # of allowable outstanding REQ)
 */

#define	DEFAULT_OFFSET	15

/*
 * Chip type defines && macros
 */

#define	ESP100		0
#define	NCR53C90	0
#define	ESP100A		1
#define	NCR53C90A	1
#define	ESP236		2
#define	FAS236		3
#define	FAS100A		4
#define	FAST		5

#define	IS_53C90(esp)	((esp)->e_type == NCR53C90)

/*
 * Compatibility hacks
 */

#ifndef OPENPROMS

#define	ESP_SIZE		0x2000		/*
						 * ESP and DVMA space
						 */

#define	DMAGA_OFFSET		0x1000		/*
						 * Offset of DMA registers
						 * for STINGRAY && HYDRA.
						 */

#define	STINGRAY_DMA_OFFSET	DMAGA_OFFSET
#define	HYDRA_DMA_OFFSET	DMAGA_OFFSET

#endif	/* !OPENPROMS */

#endif	/* !_scsi_adapters_espreg_h */
