xref: /onnv-gate/usr/src/uts/common/sys/emul64var.h (revision 1144:30b0bd5f7fdb)
185Scth /*
285Scth  * CDDL HEADER START
385Scth  *
485Scth  * The contents of this file are subject to the terms of the
585Scth  * Common Development and Distribution License, Version 1.0 only
685Scth  * (the "License").  You may not use this file except in compliance
785Scth  * with the License.
885Scth  *
985Scth  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
1085Scth  * or http://www.opensolaris.org/os/licensing.
1185Scth  * See the License for the specific language governing permissions
1285Scth  * and limitations under the License.
1385Scth  *
1485Scth  * When distributing Covered Code, include this CDDL HEADER in each
1585Scth  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
1685Scth  * If applicable, add the following below this CDDL HEADER, with the
1785Scth  * fields enclosed by brackets "[]" replaced with your own identifying
1885Scth  * information: Portions Copyright [yyyy] [name of copyright owner]
1985Scth  *
2085Scth  * CDDL HEADER END
2185Scth  */
2285Scth /*
2385Scth  * Copyright 2005 Sun Microsystems, Inc.  All rights reserved.
2485Scth  * Use is subject to license terms.
2585Scth  */
2685Scth 
2785Scth #ifndef _SYS_SCSI_ADAPTERS_EMUL64VAR_H
2885Scth #define	_SYS_SCSI_ADAPTERS_EMUL64VAR_H
2985Scth 
3085Scth #pragma ident	"%Z%%M%	%I%	%E% SMI"
3185Scth 
3285Scth #include <sys/avl.h>
3385Scth #include <sys/note.h>
3485Scth #include <sys/emul64.h>
3585Scth 
3685Scth #ifdef	__cplusplus
3785Scth extern "C" {
3885Scth #endif
3985Scth 
4085Scth /*
4185Scth  * Convenient short hand defines
4285Scth  */
4385Scth #define	TRUE			 1
4485Scth #define	FALSE			 0
4585Scth #define	UNDEFINED		-1
4685Scth 
4785Scth #define	CNUM(emul64)		(ddi_get_instance(emul64->emul64_tran.tran_dev))
4885Scth 
4985Scth #define	EMUL64_RETRY_DELAY		5
5085Scth #define	EMUL64_RETRIES		0	/* retry of selections */
5185Scth #define	EMUL64_INITIAL_SOFT_SPACE	5 /* Used for the softstate_init func */
5285Scth 
5385Scth #define	MSW(x)			(int16_t)(((int32_t)x >> 16) & 0xFFFF)
5485Scth #define	LSW(x)			(int16_t)((int32_t)x & 0xFFFF)
5585Scth 
5685Scth #define	TGT(sp)			(CMD2PKT(sp)->pkt_address.a_target)
5785Scth #define	LUN(sp)			(CMD2PKT(sp)->pkt_address.a_lun)
5885Scth 
5985Scth #define	HW_REV(val)		(((val) >>8) & 0xff)
6085Scth #define	FW_REV(val)		((val) & 0xff)
6185Scth 
6285Scth /*
6385Scth  * max number of LUNs per target
6485Scth  */
6585Scth #define	EMUL64_NLUNS_PER_TARGET	32
6685Scth 
6785Scth /*
6885Scth  * Default emul64 scsi-options
6985Scth  */
7085Scth #define	EMUL64_DEFAULT_SCSI_OPTIONS					\
7185Scth 					SCSI_OPTIONS_PARITY	|	\
7285Scth 					SCSI_OPTIONS_DR		|	\
7385Scth 					SCSI_OPTIONS_SYNC	|	\
7485Scth 					SCSI_OPTIONS_TAG	|	\
7585Scth 					SCSI_OPTIONS_FAST	|	\
7685Scth 					SCSI_OPTIONS_WIDE
7785Scth 
7885Scth /*
7985Scth  *	Tag reject
8085Scth  */
8185Scth #define	TAG_REJECT	28
8285Scth /*
8385Scth  * Interrupt actions returned by emul64_i_flag_event()
8485Scth  */
8585Scth #define	ACTION_CONTINUE		0	/* Continue */
8685Scth #define	ACTION_RETURN		1	/* Exit */
8785Scth #define	ACTION_IGNORE		2	/* Ignore */
8885Scth 
8985Scth /*
9085Scth  * Reset actions for emul64_i_reset_interface()
9185Scth  */
9285Scth #define	EMUL64_RESET_BUS_IF_BUSY	0x01 /* reset scsi bus if it is busy */
9385Scth #define	EMUL64_FORCE_RESET_BUS	0x02	/* reset scsi bus on error reco */
9485Scth 
9585Scth 
9685Scth /*
9785Scth  * extracting period and offset from emul64_synch
9885Scth  */
9985Scth #define	PERIOD_MASK(val)	((val) & 0xff)
10085Scth #define	OFFSET_MASK(val)	(((val) >>8) & 0xff)
10185Scth 
10285Scth /*
10385Scth  * timeout values
10485Scth  */
10585Scth #define	EMUL64_GRACE		10	/* Timeout margin (sec.) */
10685Scth #define	EMUL64_TIMEOUT_DELAY(secs, delay)	(secs * (1000000 / delay))
10785Scth 
10885Scth /*
10985Scth  * delay time for polling loops
11085Scth  */
11185Scth #define	EMUL64_NOINTR_POLL_DELAY_TIME		1000	/* usecs */
11285Scth 
11385Scth /*
11485Scth  * busy wait delay time after chip reset
11585Scth  */
11685Scth #define	EMUL64_CHIP_RESET_BUSY_WAIT_TIME		100	/* usecs */
11785Scth 
11885Scth /*
11985Scth  * timeout for EMUL64 coming out of reset
12085Scth  */
12185Scth #define	EMUL64_RESET_WAIT				1000	/* ms */
12285Scth #define	EMUL64_SOFT_RESET_TIME			1	/* second */
12385Scth 
12485Scth /*
12585Scth  * emul64_softstate flags for introducing hot plug
12685Scth  */
12785Scth #define	EMUL64_SS_OPEN		0x01
12885Scth #define	EMUL64_SS_DRAINING		0x02
12985Scth #define	EMUL64_SS_QUIESCED		0x04
13085Scth #define	EMUL64_SS_DRAIN_ERROR	0x08
13185Scth 
13285Scth /*
13385Scth  * ioctl command definitions
13485Scth  */
13585Scth #ifndef	EMUL64_RESET_TARGET
13685Scth #define	EMUL64_RESET_TARGET		(('i' << 8) | 0x03)
13785Scth #endif
13885Scth 
13985Scth 
14085Scth /*
14185Scth  * Debugging macros
14285Scth  */
14385Scth #define	EMUL64_DEBUG	if (emul64debug) emul64_i_log
14485Scth #define	EMUL64_DEBUG2	if (emul64debug > 1) emul64_i_log
14585Scth 
14685Scth 
14785Scth #define	REQ_TGT_LUN(tgt, lun)			(((tgt) << 8) | (lun))
14885Scth 
14985Scth 
15085Scth #define	RESP_CQ_FLAGS(resp)	((resp->resp_header.cq_flags_seq) & 0xff)
15185Scth 
15285Scth 
15385Scth #define	EMUL64_NDATASEGS		4
15485Scth 
15585Scth 
15685Scth /*
15785Scth  * translate scsi_pkt flags into EMUL64 request packet flags
15885Scth  * It would be illegal if two flags are set; the driver does not
15985Scth  * check for this. Setting NODISCON and a tag flag is harmless.
16085Scth  */
16185Scth #define	EMUL64_SET_PKT_FLAGS(scsa_flags, emul64_flags) {		\
16285Scth 	emul64_flags = (scsa_flags >> 11) & 0xe; /* tags */		\
16385Scth 	emul64_flags |= (scsa_flags >> 1) & 0x1; /* no disconnect */	\
16485Scth }
16585Scth 
16685Scth /*
16785Scth  * throttle values for EMUL64 request queue
16885Scth  */
16985Scth #define	SHUTDOWN_THROTTLE	-1	/* do not submit any requests */
17085Scth #define	CLEAR_THROTTLE		(EMUL64_MAX_REQUESTS -1)
17185Scth 
17285Scth 
17385Scth #define	EMUL64_GET_PKT_STATE(state)	((uint32_t)(state >> 8))
17485Scth #define	EMUL64_GET_PKT_STATS(stats)	((uint32_t)(stats))
17585Scth 
17685Scth #define	EMUL64_STAT_NEGOTIATE	0x0080
17785Scth 
17885Scth #define	EMUL64_SET_REASON(sp, reason) { \
17985Scth 	if ((sp) && CMD2PKT(sp)->pkt_reason == CMD_CMPLT) \
18085Scth 		CMD2PKT(sp)->pkt_reason = (reason); \
18185Scth }
18285Scth 
18385Scth /*
18485Scth  * mutex short hands
18585Scth  */
18685Scth #define	EMUL64_REQ_MUTEX(emul64)	(&emul64->emul64_request_mutex)
18785Scth #define	EMUL64_RESP_MUTEX(emul64)	(&emul64->emul64_response_mutex)
18885Scth #define	EMUL64_HOTPLUG_MUTEX(emul64)	(&emul64->emul64_hotplug_mutex)
18985Scth 
19085Scth 
19185Scth #define	EMUL64_MUTEX_ENTER(emul64) mutex_enter(EMUL64_RESP_MUTEX(emul64)), \
19285Scth 				mutex_enter(EMUL64_REQ_MUTEX(emul64))
19385Scth #define	EMUL64_MUTEX_EXIT(emul64)	mutex_exit(EMUL64_RESP_MUTEX(emul64)), \
19485Scth 				mutex_exit(EMUL64_REQ_MUTEX(emul64))
19585Scth 
19685Scth #define	EMUL64_CV(emul64)			(&(emul64)->emul64_cv)
19785Scth 
19885Scth /*
19985Scth  * HBA interface macros
20085Scth  */
20185Scth #define	SDEV2TRAN(sd)		((sd)->sd_address.a_hba_tran)
20285Scth #define	SDEV2ADDR(sd)		(&((sd)->sd_address))
20385Scth #define	PKT2TRAN(pkt)		((pkt)->pkt_address.a_hba_tran)
20485Scth #define	ADDR2TRAN(ap)		((ap)->a_hba_tran)
20585Scth 
20685Scth #define	TRAN2EMUL64(tran)	((struct emul64 *)(tran)->tran_hba_private)
20785Scth #define	SDEV2EMUL64(sd)		(TRAN2EMUL64(SDEV2TRAN(sd)))
20885Scth #define	PKT2EMUL64(pkt)		(TRAN2EMUL64(PKT2TRAN(pkt)))
20985Scth #define	ADDR2EMUL64(ap)		(TRAN2EMUL64(ADDR2TRAN(ap)))
21085Scth 
21185Scth #define	CMD2ADDR(cmd)		(&CMD2PKT(cmd)->pkt_address)
21285Scth #define	CMD2TRAN(cmd)		(CMD2PKT(cmd)->pkt_address.a_hba_tran)
21385Scth #define	CMD2EMUL64(cmd)		(TRAN2EMUL64(CMD2TRAN(cmd)))
21485Scth 
21585Scth /*
21685Scth  * Results of checking for range overlap.
21785Scth  */
21885Scth typedef enum emul64_rng_overlap {
21985Scth 	O_NONE,			/* No overlap */
22085Scth 	O_SAME,			/* Ranges are identical */
22185Scth 	O_SUBSET,		/* Blocks are contained in range */
22285Scth 	O_OVERLAP		/* Ranges overlap. */
22385Scth } emul64_rng_overlap_t;
22485Scth 
22585Scth /*
22685Scth  * Rather than keep the entire image of the disk, we only keep
22785Scth  * the blocks which have been written with non-zeros.  As the
22885Scth  * purpose of this driver is to exercise format and perhaps other
22985Scth  * large-disk management tools, only recording the label for
23085Scth  * i/o is sufficient
23185Scth  */
23285Scth typedef struct blklist {
23385Scth 	diskaddr_t	bl_blkno;	/* Disk address of the data */
23485Scth 	uchar_t		*bl_data;	/* Pointer to the data */
23585Scth 	avl_node_t	bl_node;	/* Our linkage in AVL tree */
23685Scth } blklist_t;
23785Scth 
23885Scth /*
23985Scth  * Structure to track a range of blocks where writes are to be ignored.
24085Scth  */
24185Scth typedef struct emul64_nowrite {
24285Scth 	struct emul64_nowrite	*emul64_nwnext;	/* next item in list */
24385Scth 	emul64_range_t		emul64_blocked;	/* range to ignore writes */
24485Scth } emul64_nowrite_t;
24585Scth 
24685Scth typedef struct emul64_tgt {
24785Scth 	struct scsi_address	emul64_tgt_saddr;
24885Scth 	struct emul64_tgt	*emul64_tgt_next;	/* Next tgt on ctlr */
24985Scth 	emul64_nowrite_t	*emul64_tgt_nowrite;	/* List of regions to */
25085Scth 							/* skip writes */
25185Scth 	diskaddr_t		emul64_tgt_sectors;	/* # sectors in dev */
25285Scth 	char 			emul64_tgt_inq[8+16];
25385Scth 	uint_t			emul64_tgt_dtype;
25485Scth 	uint_t			emul64_tgt_ncyls;	/* # cylinders in dev */
25585Scth 	uint_t			emul64_tgt_nheads;	/* # disk heads */
25685Scth 	uint_t			emul64_tgt_nsect;	/* # sectors */
25785Scth 	uint64_t		emul64_list_length;	/* # data blks */
25885Scth 	avl_tree_t		emul64_tgt_data;	/* Tree of data blks */
25985Scth 	kmutex_t		emul64_tgt_blk_lock;	/* Protect data blks */
26085Scth 	krwlock_t		emul64_tgt_nw_lock;	/* Guard tgt_nowrite */
261*1144Spd144616 	/* Fields for error injection */
262*1144Spd144616 	ushort_t		emul64_einj_state;
263*1144Spd144616 	ushort_t		emul64_einj_sense_length;
264*1144Spd144616 	uint_t			emul64_einj_pkt_state;
265*1144Spd144616 	uint_t			emul64_einj_pkt_reason;
266*1144Spd144616 	struct scsi_status	emul64_einj_scsi_status;
267*1144Spd144616 	uint8_t			*emul64_einj_sense_data;
26885Scth } emul64_tgt_t;
26985Scth 
27085Scth /*
27185Scth  * emul64 softstate structure
27285Scth  */
27385Scth 
27485Scth /*
27585Scth  * deadline slot structure for timeout handling
27685Scth  */
27785Scth struct emul64_slot {
27885Scth 	struct emul64_cmd	*slot_cmd;
27985Scth 	clock_t		slot_deadline;
28085Scth };
28185Scth 
28285Scth 
28385Scth /*
28485Scth  * Record the reset notification requests from target drivers.
28585Scth  */
28685Scth struct emul64_reset_notify_entry {
28785Scth 	struct scsi_address		*ap;
28885Scth 	void				(*callback)(caddr_t);
28985Scth 	caddr_t				arg;
29085Scth 	struct emul64_reset_notify_entry	*next;
29185Scth };
29285Scth 
29385Scth 
29485Scth struct emul64 {
29585Scth 
29685Scth 	/*
29785Scth 	 * Transport structure for this instance of the hba
29885Scth 	 */
29985Scth 	scsi_hba_tran_t		*emul64_tran;
30085Scth 
30185Scth 	/*
30285Scth 	 * dev_info_t reference can be found in the transport structure
30385Scth 	 */
30485Scth 	dev_info_t		*emul64_dip;
30585Scth 
30685Scth 	/*
30785Scth 	 * Interrupt block cookie
30885Scth 	 */
30985Scth 	ddi_iblock_cookie_t	emul64_iblock;
31085Scth 
31185Scth 	/*
31285Scth 	 * Firmware revision number
31385Scth 	 */
31485Scth 	uint16_t		emul64_major_rev;
31585Scth 	uint16_t		emul64_minor_rev;
31685Scth 
31785Scth 	/*
31885Scth 	 * timeout id
31985Scth 	 */
32085Scth 	timeout_id_t		emul64_timeout_id;
32185Scth 
32285Scth 	/*
32385Scth 	 * scsi options, scsi_tag_age_limit  per emul64
32485Scth 	 */
32585Scth 	int			emul64_scsi_options;
32685Scth 	int			emul64_target_scsi_options[NTARGETS_WIDE];
32785Scth 	int			emul64_scsi_tag_age_limit;
32885Scth 
32985Scth 	/*
33085Scth 	 * scsi_reset_delay per emul64
33185Scth 	 */
33285Scth 	clock_t			emul64_scsi_reset_delay;
33385Scth 
33485Scth 	/*
33585Scth 	 * current host ID
33685Scth 	 */
33785Scth 	uint8_t			emul64_initiator_id;
33885Scth 
33985Scth 	/*
34085Scth 	 * suspended flag for power management
34185Scth 	 */
34285Scth 	uint8_t			emul64_suspended;
34385Scth 
34485Scth 	/*
34585Scth 	 * Host adapter capabilities and offset/period values per target
34685Scth 	 */
34785Scth 	uint16_t		emul64_cap[NTARGETS_WIDE];
34885Scth 	int16_t			emul64_synch[NTARGETS_WIDE];
34985Scth 
35085Scth 	/*
35185Scth 	 * EMUL64 Hardware register pointer.
35285Scth 	 */
35385Scth 	struct emul64regs		*emul64_reg;
35485Scth 
35585Scth 
35685Scth 	kmutex_t		emul64_request_mutex;
35785Scth 	kmutex_t		emul64_response_mutex;
35885Scth 
35985Scth 	/*
36085Scth 	 * for keeping track of the max LUNs per target on this bus
36185Scth 	 */
36285Scth 	uchar_t			emul64_max_lun[NTARGETS_WIDE];
36385Scth 
36485Scth 	/*
36585Scth 	 * for keeping track of each target/lun
36685Scth 	 */
36785Scth 	int	nt_total_sectors[NTARGETS_WIDE][EMUL64_NLUNS_PER_TARGET];
36885Scth 
36985Scth 	struct emul64_reset_notify_entry	*emul64_reset_notify_listf;
37085Scth 
37185Scth 	ushort_t		emul64_backoff;
37285Scth 	uint_t			emul64_softstate; /* flags for hotplug */
37385Scth 	int			emul64_hotplug_waiting;
37485Scth 	kcondvar_t		emul64_cv; /* cv for bus quiesce/unquiesce */
37585Scth 	kmutex_t		emul64_hotplug_mutex; /* Mutex for hotplug */
37685Scth 	taskq_t			*emul64_taskq;
37785Scth 	emul64_tgt_t		*emul64_tgt;
37885Scth };
37985Scth 
38085Scth _NOTE(MUTEX_PROTECTS_DATA(emul64::emul64_request_mutex,
38185Scth 				emul64::emul64_queue_space))
38285Scth _NOTE(MUTEX_PROTECTS_DATA(emul64::emul64_request_mutex,
38385Scth 				emul64::emul64_request_in))
38485Scth _NOTE(MUTEX_PROTECTS_DATA(emul64::emul64_request_mutex,
38585Scth 				emul64::emul64_request_out))
38685Scth _NOTE(MUTEX_PROTECTS_DATA(emul64::emul64_request_mutex,
38785Scth 				emul64::emul64_request_ptr))
38885Scth _NOTE(MUTEX_PROTECTS_DATA(emul64::emul64_request_mutex,
38985Scth 				emul64::emul64_mbox))
39085Scth _NOTE(MUTEX_PROTECTS_DATA(emul64::emul64_request_mutex,
39185Scth 				emul64::emul64_slots))
39285Scth 
39385Scth _NOTE(MUTEX_PROTECTS_DATA(emul64::emul64_response_mutex,
39485Scth 				emul64::emul64_response_in))
39585Scth _NOTE(MUTEX_PROTECTS_DATA(emul64::emul64_response_mutex,
39685Scth 				emul64::emul64_response_out))
39785Scth _NOTE(MUTEX_PROTECTS_DATA(emul64::emul64_response_mutex,
39885Scth 				emul64::emul64_response_ptr))
39985Scth 
40085Scth extern void emul64_bsd_init();
40185Scth extern void emul64_bsd_fini();
40285Scth extern void emul64_bsd_get_props(dev_info_t *);
40385Scth 
40485Scth extern emul64_rng_overlap_t emul64_overlap(emul64_range_t *,
40585Scth 						diskaddr_t, size_t);
40685Scth extern int emul64_bsd_blkcompare(const void *, const void *);
40785Scth extern int emul64debug;
40885Scth extern long emul64_nowrite_count;
40985Scth extern kmutex_t emul64_stats_mutex;
41085Scth extern int emul64_collect_stats;
41185Scth extern uint64_t emul64_taskq_max;
41285Scth extern int emul64_max_task;
41385Scth extern int emul64_task_nthreads;
41485Scth 
41585Scth #ifdef	__cplusplus
41685Scth }
41785Scth #endif
41885Scth 
41985Scth #endif	/* _SYS_SCSI_ADAPTERS_EMUL64VAR_H */
420