xref: /illumos-gate/usr/src/uts/common/sys/scsi/adapters/pmcs/pmcs.h (revision 2ac4abe882db38ef90020f7c5ca28586e3d57258)
14c06356bSdh /*
24c06356bSdh  * CDDL HEADER START
34c06356bSdh  *
44c06356bSdh  * The contents of this file are subject to the terms of the
54c06356bSdh  * Common Development and Distribution License (the "License").
64c06356bSdh  * You may not use this file except in compliance with the License.
74c06356bSdh  *
84c06356bSdh  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
94c06356bSdh  * or http://www.opensolaris.org/os/licensing.
104c06356bSdh  * See the License for the specific language governing permissions
114c06356bSdh  * and limitations under the License.
124c06356bSdh  *
134c06356bSdh  * When distributing Covered Code, include this CDDL HEADER in each
144c06356bSdh  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
154c06356bSdh  * If applicable, add the following below this CDDL HEADER, with the
164c06356bSdh  * fields enclosed by brackets "[]" replaced with your own identifying
174c06356bSdh  * information: Portions Copyright [yyyy] [name of copyright owner]
184c06356bSdh  *
194c06356bSdh  * CDDL HEADER END
204c06356bSdh  *
214c06356bSdh  *
2273a3eccdSDavid Hollister  * Copyright 2010 Sun Microsystems, Inc.  All rights reserved.
234c06356bSdh  * Use is subject to license terms.
244c06356bSdh  */
254c06356bSdh /*
264c06356bSdh  * This file is the principle header file for the PMCS driver
274c06356bSdh  */
284c06356bSdh #ifndef _PMCS_H
294c06356bSdh #define	_PMCS_H
304c06356bSdh #ifdef	__cplusplus
314c06356bSdh extern "C" {
324c06356bSdh #endif
334c06356bSdh 
344c06356bSdh 
354c06356bSdh #include <sys/cpuvar.h>
364c06356bSdh #include <sys/ddi.h>
374c06356bSdh #include <sys/sunddi.h>
384c06356bSdh #include <sys/modctl.h>
394c06356bSdh #include <sys/pci.h>
404c06356bSdh #include <sys/pcie.h>
419719310aSDavid Hollister #include <sys/file.h>
424c06356bSdh #include <sys/isa_defs.h>
434c06356bSdh #include <sys/sunmdi.h>
444c06356bSdh #include <sys/mdi_impldefs.h>
454c06356bSdh #include <sys/scsi/scsi.h>
464c06356bSdh #include <sys/scsi/impl/scsi_reset_notify.h>
4796c4a178SChris Horne #include <sys/scsi/impl/scsi_sas.h>
4896c4a178SChris Horne #include <sys/scsi/impl/smp_transport.h>
494c06356bSdh #include <sys/scsi/generic/sas.h>
5096c4a178SChris Horne #include <sys/scsi/generic/smp_frames.h>
514c06356bSdh #include <sys/atomic.h>
524c06356bSdh #include <sys/byteorder.h>
534b456463SDavid Hollister #include <sys/sysmacros.h>
544c06356bSdh #include <sys/bitmap.h>
554c06356bSdh #include <sys/queue.h>
564c06356bSdh #include <sys/sdt.h>
574c06356bSdh #include <sys/ddifm.h>
584c06356bSdh #include <sys/fm/protocol.h>
594c06356bSdh #include <sys/fm/util.h>
604c06356bSdh #include <sys/fm/io/ddi.h>
614c06356bSdh #include <sys/scsi/impl/spc3_types.h>
624c06356bSdh 
634c06356bSdh typedef struct pmcs_hw pmcs_hw_t;
644c06356bSdh typedef struct pmcs_iport pmcs_iport_t;
654c06356bSdh typedef struct pmcs_phy pmcs_phy_t;
664c06356bSdh typedef struct lsas_cmd lsas_cmd_t;
674c06356bSdh typedef struct lsas_result lsas_result_t;
684c06356bSdh typedef struct lsata_cmd lsata_cmd_t;
694c06356bSdh typedef struct lsata_result lsata_result_t;
704c06356bSdh typedef struct pmcwork pmcwork_t;
714c06356bSdh typedef struct pmcs_cmd pmcs_cmd_t;
724c06356bSdh typedef	struct pmcs_xscsi pmcs_xscsi_t;
734c06356bSdh typedef	struct pmcs_lun pmcs_lun_t;
744c06356bSdh typedef struct pmcs_chunk pmcs_chunk_t;
754c06356bSdh 
764c06356bSdh #include <sys/scsi/adapters/pmcs/pmcs_param.h>
774c06356bSdh #include <sys/scsi/adapters/pmcs/pmcs_reg.h>
784c06356bSdh #include <sys/scsi/adapters/pmcs/pmcs_mpi.h>
794c06356bSdh #include <sys/scsi/adapters/pmcs/pmcs_iomb.h>
804c06356bSdh #include <sys/scsi/adapters/pmcs/pmcs_sgl.h>
814c06356bSdh 
824c06356bSdh #include <sys/scsi/adapters/pmcs/ata.h>
834c06356bSdh #include <sys/scsi/adapters/pmcs/pmcs_def.h>
844c06356bSdh #include <sys/scsi/adapters/pmcs/pmcs_proto.h>
854c06356bSdh #include <sys/scsi/adapters/pmcs/pmcs_scsa.h>
864c06356bSdh #include <sys/scsi/adapters/pmcs/pmcs_smhba.h>
874c06356bSdh 
884c06356bSdh #define	PMCS_MAX_UA_SIZE	32
894c06356bSdh 
904c06356bSdh struct pmcs_xscsi {
914c06356bSdh 	uint32_t
924c06356bSdh 		ca		:	1,		/* SATA specific */
934c06356bSdh 		ncq		:	1,		/* SATA specific */
944c06356bSdh 		pio		:	1,		/* SATA specific */
954c06356bSdh 		special_needed	:	1,		/* SATA specific */
964c06356bSdh 		special_running	:	1,		/* SATA specific */
974c06356bSdh 		reset_success	:	1,		/* last reset ok */
984c06356bSdh 		reset_wait	:	1,		/* wait for reset */
994c06356bSdh 		resetting	:	1,		/* now resetting */
1004c06356bSdh 		recover_wait	:	1,		/* wait for recovery */
1014c06356bSdh 		recovering	:	1,		/* now recovering */
1024c06356bSdh 		event_recovery	:	1,		/* event recovery */
1034c06356bSdh 		draining	:	1,
1044c06356bSdh 		new		:	1,
1054c06356bSdh 		assigned	:	1,
1064c06356bSdh 		dev_gone	:	1,
1074c06356bSdh 		phy_addressable	:	1,		/* Direct attach SATA */
1084c06356bSdh 		dev_state	:	4;
1094c06356bSdh 	uint16_t			maxdepth;
1104c06356bSdh 	uint16_t			qdepth;
111601c90f1SSrikanth, Ramana 	uint16_t			actv_cnt;	/* Pkts ON CHIP */
112601c90f1SSrikanth, Ramana 	uint16_t			actv_pkts;	/* Pkts in driver */
1134c06356bSdh 	uint16_t			target_num;
1144c06356bSdh 	/* statlock protects both target stats and the special queue (sq) */
1154c06356bSdh 	kmutex_t			statlock;
1164c06356bSdh 	int32_t				ref_count;
1174c06356bSdh 	dev_info_t 			*dip;	/* Solaris device dip */
1184c06356bSdh 	pmcs_phy_t			*phy;
1194c06356bSdh 	STAILQ_HEAD(wqh, pmcs_cmd)	wq;
1204c06356bSdh 	pmcs_cmd_t			*wq_recovery_tail;	/* See below */
1214c06356bSdh 	kmutex_t			wqlock;
1224c06356bSdh 	STAILQ_HEAD(aqh, pmcs_cmd)	aq;
1234c06356bSdh 	kmutex_t			aqlock;
1244c06356bSdh 	STAILQ_HEAD(sqh, pmcs_cmd)	sq;		/* SATA specific */
1254c06356bSdh 	uint32_t			tagmap;		/* SATA specific */
1264c06356bSdh 	pmcs_hw_t			*pwp;
1274c06356bSdh 	ddi_soft_state_bystr		*lun_sstate;
1284c06356bSdh 	uint64_t			capacity;	/* SATA specific */
1294c06356bSdh 	char				unit_address[PMCS_MAX_UA_SIZE];
1304c06356bSdh 	kcondvar_t			reset_cv;
1314c06356bSdh 	kcondvar_t			abort_cv;
1324c06356bSdh 	char				*ua;
1334c06356bSdh 	pmcs_dtype_t			dtype;
13473a3eccdSDavid Hollister 	list_t				lun_list;	/* list of LUNs */
135499cfd15SDavid Hollister 	struct smp_device		*smpd;		/* Ptr to smp_device */
1364c06356bSdh };
1374c06356bSdh 
1384c06356bSdh /*
1394c06356bSdh  * wq_recovery_tail in the pmcs_xscsi structure is a pointer to a command in
1404c06356bSdh  * the wait queue (wq).  That pointer is the last command in the wait queue
1414c06356bSdh  * that needs to be reissued after device state recovery is complete.  Commands
1424c06356bSdh  * that need to be retried are reinserted into the wq after wq_recovery_tail
1434c06356bSdh  * to maintain the order in which the commands were originally submitted.
1444c06356bSdh  */
1454c06356bSdh 
1464c06356bSdh #define	PMCS_INVALID_TARGET_NUM		(uint16_t)-1
1474c06356bSdh 
1484c06356bSdh #define	PMCS_TGT_WAIT_QUEUE		0x01
1494c06356bSdh #define	PMCS_TGT_ACTIVE_QUEUE		0x02
1504c06356bSdh #define	PMCS_TGT_SPECIAL_QUEUE		0x04
1514c06356bSdh #define	PMCS_TGT_ALL_QUEUES		0xff
1524c06356bSdh 
1534c06356bSdh /*
1544c06356bSdh  * LUN representation.  Just a LUN (number) and pointer to the target
1554c06356bSdh  * structure (pmcs_xscsi).
1564c06356bSdh  */
1574c06356bSdh 
1584c06356bSdh struct pmcs_lun {
15973a3eccdSDavid Hollister 	list_node_t		lun_list_next;
16073a3eccdSDavid Hollister 	pmcs_xscsi_t		*target;
16173a3eccdSDavid Hollister 	struct scsi_device	*sd;
16273a3eccdSDavid Hollister 	uint64_t		lun_num;	/* lun64 */
16373a3eccdSDavid Hollister 	scsi_lun_t		scsi_lun;	/* Wire format */
16473a3eccdSDavid Hollister 	char			unit_address[PMCS_MAX_UA_SIZE];
1654c06356bSdh };
1664c06356bSdh 
1674c06356bSdh /*
1684c06356bSdh  * Interrupt coalescing values
1694c06356bSdh  */
1704c06356bSdh #define	PMCS_MAX_IO_COMPS_PER_INTR	12
1714c06356bSdh #define	PMCS_MAX_IO_COMPS_HIWAT_SHIFT	6
1724c06356bSdh #define	PMCS_MAX_IO_COMPS_LOWAT_SHIFT	10
1734c06356bSdh #define	PMCS_QUANTUM_TIME_USECS		(1000000 / 10)	/* 1/10th sec. */
1744c06356bSdh #define	PMCS_MAX_COAL_TIMER		0x200	/* Don't set > than this */
1754c06356bSdh #define	PMCS_MAX_CQ_THREADS		4
1764c06356bSdh #define	PMCS_COAL_TIMER_GRAN		2	/* Go up/down by 2 usecs */
1774c06356bSdh #define	PMCS_INTR_THRESHOLD(x)		((x) * 6 / 10)
1784c06356bSdh 
1794c06356bSdh /*
1804c06356bSdh  * This structure is used to maintain state with regard to I/O interrupt
1814c06356bSdh  * coalescing.
1824c06356bSdh  */
1834c06356bSdh 
1844c06356bSdh typedef struct pmcs_io_intr_coal_s {
1854c06356bSdh 	hrtime_t	nsecs_between_intrs;
1864c06356bSdh 	hrtime_t	last_io_comp;
1874c06356bSdh 	clock_t		quantum;
1884c06356bSdh 	uint32_t	num_io_completions;
1894c06356bSdh 	uint32_t	num_intrs;
1904c06356bSdh 	uint32_t	max_io_completions;
1914c06356bSdh 	uint32_t	intr_latency;
1924c06356bSdh 	uint32_t	intr_threshold;
1934c06356bSdh 	uint16_t	intr_coal_timer;
1944c06356bSdh 	boolean_t	timer_on;
1954c06356bSdh 	boolean_t	stop_thread;
1964c06356bSdh 	boolean_t	int_cleared;
1974c06356bSdh } pmcs_io_intr_coal_t;
1984c06356bSdh 
1994c06356bSdh typedef struct pmcs_cq_thr_info_s {
2004c06356bSdh 	kthread_t	*cq_thread;
2014c06356bSdh 	kmutex_t	cq_thr_lock;
2024c06356bSdh 	kcondvar_t	cq_cv;
2034c06356bSdh 	pmcs_hw_t	*cq_pwp;
2044c06356bSdh } pmcs_cq_thr_info_t;
2054c06356bSdh 
2064c06356bSdh typedef struct pmcs_cq_info_s {
2074c06356bSdh 	uint32_t		cq_threads;
2084c06356bSdh 	uint32_t		cq_next_disp_thr;
2094c06356bSdh 	boolean_t		cq_stop;
2104c06356bSdh 	pmcs_cq_thr_info_t	*cq_thr_info;
2114c06356bSdh } pmcs_cq_info_t;
2124c06356bSdh 
2134c06356bSdh typedef struct pmcs_iocomp_cb_s {
2144c06356bSdh 	pmcwork_t		*pwrk;
2154c06356bSdh 	char			iomb[PMCS_QENTRY_SIZE << 1];
2164c06356bSdh 	struct pmcs_iocomp_cb_s	*next;
2174c06356bSdh } pmcs_iocomp_cb_t;
2184c06356bSdh 
2194c06356bSdh typedef struct pmcs_iqp_trace_s {
2204c06356bSdh 	char		*head;
2214c06356bSdh 	char		*curpos;
2224c06356bSdh 	uint32_t	size_left;
2234c06356bSdh } pmcs_iqp_trace_t;
2244c06356bSdh 
2254c06356bSdh /*
2264c06356bSdh  * Used by string-based softstate as hint to possible size.
2274c06356bSdh  */
2284c06356bSdh 
2294c06356bSdh #define	PMCS_TGT_SSTATE_SZ		64
2304c06356bSdh #define	PMCS_LUN_SSTATE_SZ		4
2314c06356bSdh 
2324c06356bSdh /*
2334c06356bSdh  * HBA iport node softstate
2344c06356bSdh  */
235601c90f1SSrikanth, Ramana #define	PMCS_IPORT_INVALID_PORT_ID	0xf
2364c06356bSdh 
2374c06356bSdh struct pmcs_iport {
2384c06356bSdh 	kmutex_t	lock;		/* iport lock */
2394c06356bSdh 	list_node_t	list_node;	/* list node for pwp->iports list_t */
2404c06356bSdh 	kmutex_t	refcnt_lock;	/* refcnt lock */
2414c06356bSdh 	kcondvar_t	refcnt_cv;	/* refcnt cv */
2424c06356bSdh 	int		refcnt;		/* refcnt for this iport */
2434c06356bSdh 	dev_info_t	*dip;		/* iport dip */
2444c06356bSdh 	pmcs_hw_t	*pwp;		/* back pointer to HBA state */
2454c06356bSdh 	pmcs_phy_t	*pptr;		/* pointer to this port's primary phy */
2464c06356bSdh 	enum {				/* unit address state in the phymap */
2474c06356bSdh 		UA_INACTIVE,
2484c06356bSdh 		UA_PEND_ACTIVATE,
2494c06356bSdh 		UA_ACTIVE,
2504c06356bSdh 		UA_PEND_DEACTIVATE
2514c06356bSdh 	} ua_state;
2524c06356bSdh 	char		*ua;		/* unit address (phy mask) */
2534c06356bSdh 	int		portid;		/* portid */
2544c06356bSdh 	int		report_skip;	/* skip or report during discovery */
2554c06356bSdh 	list_t		phys;		/* list of phys on this port */
2564c06356bSdh 	int		nphy;		/* number of phys in this port */
2574c06356bSdh 	scsi_hba_tgtmap_t	*iss_tgtmap;	/* tgtmap */
2584c06356bSdh 	ddi_soft_state_bystr	*tgt_sstate;	/* tgt softstate */
2596745c559SJesse Butler 	/* SMP serialization */
2606745c559SJesse Butler 	kmutex_t	smp_lock;
2616745c559SJesse Butler 	kcondvar_t	smp_cv;
2626745c559SJesse Butler 	boolean_t	smp_active;
2636745c559SJesse Butler 	kthread_t	*smp_active_thread;
2644c06356bSdh };
2654c06356bSdh 
2664c06356bSdh struct pmcs_chunk {
2674c06356bSdh 	pmcs_chunk_t		*next;
2684c06356bSdh 	ddi_acc_handle_t	acc_handle;
2694c06356bSdh 	ddi_dma_handle_t	dma_handle;
2704c06356bSdh 	uint8_t			*addrp;
2714c06356bSdh 	uint64_t		dma_addr;
2724c06356bSdh };
2734c06356bSdh 
2744c06356bSdh /*
2754c06356bSdh  * HBA node (i.e. non-iport) softstate
2764c06356bSdh  */
2774c06356bSdh struct pmcs_hw {
2784c06356bSdh 	/*
2794c06356bSdh 	 * Identity
2804c06356bSdh 	 */
2814c06356bSdh 	dev_info_t	*dip;
2824c06356bSdh 
2834c06356bSdh 	/*
2844c06356bSdh 	 * 16 possible initiator PHY WWNs
2854c06356bSdh 	 */
2864c06356bSdh 	uint64_t	sas_wwns[PMCS_MAX_PORTS];
2874c06356bSdh 
2884c06356bSdh 	/*
2894c06356bSdh 	 * Card State
2904c06356bSdh 	 */
2914c06356bSdh 	enum pwpstate {
2924c06356bSdh 		STATE_NIL,
2934c06356bSdh 		STATE_PROBING,
2944c06356bSdh 		STATE_RUNNING,
2954c06356bSdh 		STATE_UNPROBING,
2965c45adf0SJesse Butler 		STATE_IN_RESET,
2974c06356bSdh 		STATE_DEAD
2984c06356bSdh 	} state;
2994c06356bSdh 
3005c45adf0SJesse Butler 	/*
3015c45adf0SJesse Butler 	 * Last reason for a soft reset
3025c45adf0SJesse Butler 	 */
3035c45adf0SJesse Butler 	enum pwp_last_reset_reason {
3045c45adf0SJesse Butler 		PMCS_LAST_RST_UNINIT,
3055c45adf0SJesse Butler 		PMCS_LAST_RST_ATTACH,
3065c45adf0SJesse Butler 		PMCS_LAST_RST_FW_UPGRADE,
3075c45adf0SJesse Butler 		PMCS_LAST_RST_FATAL_ERROR,
3085c45adf0SJesse Butler 		PMCS_LAST_RST_STALL,
3095c45adf0SJesse Butler 		PMCS_LAST_RST_QUIESCE,
3105c45adf0SJesse Butler 		PMCS_LAST_RST_DETACH
3115c45adf0SJesse Butler 	} last_reset_reason;
3125c45adf0SJesse Butler 
3134c06356bSdh 	uint32_t
3144c06356bSdh 		fw_disable_update	: 1,
3154c06356bSdh 		fw_force_update		: 1,
3164c06356bSdh 		blocked			: 1,
3174c06356bSdh 		stuck			: 1,
3184c06356bSdh 		locks_initted		: 1,
3194c06356bSdh 		mpi_table_setup		: 1,
3204c06356bSdh 		hba_attached		: 1,
3214c06356bSdh 		iports_attached		: 1,
3224c06356bSdh 		suspended		: 1,
3234c06356bSdh 		separate_ports		: 1,
3244c06356bSdh 		fwlog			: 4,
3254c06356bSdh 		phymode			: 3,
3264c06356bSdh 		physpeed		: 3,
3274c06356bSdh 		resource_limited	: 1,
3284c06356bSdh 		configuring		: 1,
3295c45adf0SJesse Butler 		ds_err_recovering	: 1,
3309719310aSDavid Hollister 		quiesced		: 1,
331*2ac4abe8SDavid Hollister 		fwlog_file		: 1,
332*2ac4abe8SDavid Hollister 		fw_active_img		: 1;	/* 1='A', 0='B' */
3334c06356bSdh 
3344c06356bSdh 	/*
3354c06356bSdh 	 * This HBA instance's iportmap and list of iport states.
3364c06356bSdh 	 * Note: iports_lock protects iports, iports_attached, and
3374c06356bSdh 	 * num_iports on the HBA softstate.
3384c06356bSdh 	 */
3394c06356bSdh 	krwlock_t		iports_lock;
3404c06356bSdh 	scsi_hba_iportmap_t	*hss_iportmap;
3414c06356bSdh 	list_t			iports;
3424c06356bSdh 	int			num_iports;
3434c06356bSdh 
3444c06356bSdh 	sas_phymap_t		*hss_phymap;
3454c06356bSdh 	int			phymap_active;
3464c06356bSdh 
3474c06356bSdh 	/*
3484c06356bSdh 	 * Locks
3494c06356bSdh 	 */
3504c06356bSdh 	kmutex_t	lock;
3514c06356bSdh 	kmutex_t	dma_lock;
3524c06356bSdh 	kmutex_t	axil_lock;
3534c06356bSdh 	kcondvar_t	drain_cv;
3544c06356bSdh 
3554c06356bSdh 	/*
3564c06356bSdh 	 * FMA Capabilities
3574c06356bSdh 	 */
3584c06356bSdh 	int		fm_capabilities;
3594c06356bSdh 
3604c06356bSdh 	/*
3614c06356bSdh 	 * Register Access Handles
3624c06356bSdh 	 */
3634c06356bSdh 	ddi_device_acc_attr_t 	dev_acc_attr;
3644c06356bSdh 	ddi_device_acc_attr_t	reg_acc_attr;
3654c06356bSdh 	ddi_acc_handle_t 	pci_acc_handle;
3664c06356bSdh 	ddi_acc_handle_t 	msg_acc_handle;
3674c06356bSdh 	ddi_acc_handle_t 	top_acc_handle;
3684c06356bSdh 	ddi_acc_handle_t	mpi_acc_handle;
3694c06356bSdh 	ddi_acc_handle_t	gsm_acc_handle;
3704c06356bSdh 	ddi_acc_handle_t	iqp_acchdls[PMCS_MAX_IQ];
3714c06356bSdh 	ddi_acc_handle_t	oqp_acchdls[PMCS_MAX_IQ];
3724c06356bSdh 	ddi_acc_handle_t	cip_acchdls;
3734c06356bSdh 	ddi_acc_handle_t	fwlog_acchdl;
3744c06356bSdh 	ddi_acc_handle_t	regdump_acchdl;
3754c06356bSdh 
3764c06356bSdh 	/*
3774c06356bSdh 	 * DMA Handles
3784c06356bSdh 	 */
3794c06356bSdh 	ddi_dma_attr_t		iqp_dma_attr;
3804c06356bSdh 	ddi_dma_attr_t		oqp_dma_attr;
3814c06356bSdh 	ddi_dma_attr_t		cip_dma_attr;
3824c06356bSdh 	ddi_dma_attr_t		fwlog_dma_attr;
3834c06356bSdh 	ddi_dma_attr_t		regdump_dma_attr;
3844c06356bSdh 	ddi_dma_handle_t 	iqp_handles[PMCS_MAX_IQ];
3854c06356bSdh 	ddi_dma_handle_t 	oqp_handles[PMCS_MAX_OQ];
3864c06356bSdh 	ddi_dma_handle_t	cip_handles;
3874c06356bSdh 	ddi_dma_handle_t	fwlog_hndl;
3884c06356bSdh 	ddi_dma_handle_t	regdump_hndl;
3894c06356bSdh 
3904c06356bSdh 	/*
3914c06356bSdh 	 * Register Pointers
3924c06356bSdh 	 */
3934c06356bSdh 	uint32_t	*msg_regs;	/* message unit registers */
3944c06356bSdh 	uint32_t	*top_regs;	/* top unit registers */
3954c06356bSdh 	uint32_t	*mpi_regs;	/* message passing unit registers */
3964c06356bSdh 	uint32_t	*gsm_regs;	/* GSM registers */
3974c06356bSdh 
3984c06356bSdh 	/*
3994c06356bSdh 	 * Message Passing and other offsets.
4004c06356bSdh 	 *
4014c06356bSdh 	 * mpi_offset is the offset within the fourth register set (mpi_regs)
4024c06356bSdh 	 * that contains the base of the MPI structures. Since this is actually
4034c06356bSdh 	 * set by the card firmware, it can change from startup to startup.
4044c06356bSdh 	 *
4054c06356bSdh 	 * The other offsets (gst, iqc, oqc) are for similar tables in
4064c06356bSdh 	 * MPI space, typically only accessed during setup.
4074c06356bSdh 	 */
4084c06356bSdh 	uint32_t	mpi_offset;
4094c06356bSdh 	uint32_t	mpi_gst_offset;
4104c06356bSdh 	uint32_t	mpi_iqc_offset;
4114c06356bSdh 	uint32_t	mpi_oqc_offset;
4124c06356bSdh 
4134c06356bSdh 	/*
4144c06356bSdh 	 * Inbound and outbound queue depth
4154c06356bSdh 	 */
4164c06356bSdh 	uint32_t	ioq_depth;
4174c06356bSdh 
4184c06356bSdh 	/*
4194c06356bSdh 	 * Kernel addresses and offsets for Inbound Queue Producer Indices
4204c06356bSdh 	 *
4214c06356bSdh 	 * See comments in pmcs_iomb.h about Inbound Queues. Since it
4224c06356bSdh 	 * is relatively expensive to go across the PCIe bus to read or
4234c06356bSdh 	 * write inside the card, we maintain shadow copies in kernel
4244c06356bSdh 	 * memory and update the card as needed.
4254c06356bSdh 	 */
4264c06356bSdh 	uint32_t	shadow_iqpi[PMCS_MAX_IQ];
4274c06356bSdh 	uint32_t	iqpi_offset[PMCS_MAX_IQ];
428d78a6b7eSJesse Butler 	uint32_t	last_iqci[PMCS_MAX_IQ];
429d78a6b7eSJesse Butler 	uint32_t	last_htag[PMCS_MAX_IQ];
4304c06356bSdh 	uint32_t	*iqp[PMCS_MAX_IQ];
4314c06356bSdh 	kmutex_t	iqp_lock[PMCS_NIQ];
4324c06356bSdh 
4334c06356bSdh 	pmcs_iqp_trace_t	*iqpt;
4344c06356bSdh 
4354c06356bSdh 	/*
4364c06356bSdh 	 * Kernel addresses and offsets for Outbound Queue Consumer Indices
4374c06356bSdh 	 */
4384c06356bSdh 	uint32_t	*oqp[PMCS_MAX_OQ];
4394c06356bSdh 	uint32_t	oqci_offset[PMCS_MAX_OQ];
4404c06356bSdh 
4414c06356bSdh 	/*
4424c06356bSdh 	 * Driver's copy of the outbound queue indices
4434c06356bSdh 	 */
4444c06356bSdh 
4454c06356bSdh 	uint32_t	oqci[PMCS_NOQ];
4464c06356bSdh 	uint32_t	oqpi[PMCS_NOQ];
4474c06356bSdh 
4484c06356bSdh 	/*
4494c06356bSdh 	 * DMA addresses for both Inbound and Outbound queues.
4504c06356bSdh 	 */
4514c06356bSdh 	uint64_t	oqaddr[PMCS_MAX_OQ];
4524c06356bSdh 	uint64_t	iqaddr[PMCS_MAX_IQ];
4534c06356bSdh 
4544c06356bSdh 	/*
4554c06356bSdh 	 * Producer/Queue Host Memory Pointers and scratch areas,
4564c06356bSdh 	 * as well as DMA scatter/gather chunk areas.
4574c06356bSdh 	 *
4584c06356bSdh 	 * See discussion in pmcs_def.h about how this is laid out.
4594c06356bSdh 	 */
4604c06356bSdh 	uint8_t		*cip;
4614c06356bSdh 	uint64_t	ciaddr;
4624c06356bSdh 
4634c06356bSdh 	/*
4644c06356bSdh 	 * Scratch area pointer and DMA addrress for SATA and SMP operations.
4654c06356bSdh 	 */
4664c06356bSdh 	void			*scratch;
4674c06356bSdh 	uint64_t		scratch_dma;
4684c06356bSdh 	volatile uint8_t	scratch_locked;	/* Scratch area ownership */
4694c06356bSdh 
4704c06356bSdh 	/*
4719719310aSDavid Hollister 	 * Firmware info
4729719310aSDavid Hollister 	 *
4739719310aSDavid Hollister 	 * fwlogp: Pointer to block of memory mapped for the event logs
4749719310aSDavid Hollister 	 * fwlogp_aap1: Pointer to the beginning of the AAP1 event log
4759719310aSDavid Hollister 	 * fwlogp_iop: Pointer to the beginning of the IOP event log
4769719310aSDavid Hollister 	 * fwaddr: The physical address of fwlogp
4779719310aSDavid Hollister 	 *
4789719310aSDavid Hollister 	 * fwlogfile_aap1/iop: Path to the saved AAP1/IOP event logs
4799719310aSDavid Hollister 	 * fwlog_max_entries_aap1/iop: Max # of entries in each log
4809719310aSDavid Hollister 	 * fwlog_oldest_idx_aap1/iop: Index of oldest entry in each log
4819719310aSDavid Hollister 	 * fwlog_latest_idx_aap1/iop: Index of newest entry in each log
4829719310aSDavid Hollister 	 * fwlog_threshold_aap1/iop: % full at which we save the event log
4839719310aSDavid Hollister 	 * fwlog_findex_aap1/iop: Suffix to each event log's next filename
4849719310aSDavid Hollister 	 *
4859719310aSDavid Hollister 	 * Firmware event logs are written out to the filenames specified in
4869719310aSDavid Hollister 	 * fwlogp_aap1/iop when the number of entries in the in-memory copy
4879719310aSDavid Hollister 	 * reaches or exceeds the threshold value.  The filenames are suffixed
4889719310aSDavid Hollister 	 * with .X where X is an integer ranging from 0 to 4.  This allows us
4899719310aSDavid Hollister 	 * to save up to 5MB of event log data for each log.
4904c06356bSdh 	 */
4914c06356bSdh 	uint32_t	*fwlogp;
4929719310aSDavid Hollister 	pmcs_fw_event_hdr_t *fwlogp_aap1;
4939719310aSDavid Hollister 	pmcs_fw_event_hdr_t *fwlogp_iop;
4944c06356bSdh 	uint64_t	fwaddr;
4959719310aSDavid Hollister 	char		fwlogfile_aap1[MAXPATHLEN + 1];
4969719310aSDavid Hollister 	uint32_t	fwlog_max_entries_aap1;
4979719310aSDavid Hollister 	uint32_t	fwlog_oldest_idx_aap1;
4989719310aSDavid Hollister 	uint32_t	fwlog_latest_idx_aap1;
4999719310aSDavid Hollister 	uint32_t	fwlog_threshold_aap1;
5009719310aSDavid Hollister 	uint32_t	fwlog_findex_aap1;
5019719310aSDavid Hollister 	char		fwlogfile_iop[MAXPATHLEN + 1];
5029719310aSDavid Hollister 	uint32_t	fwlog_max_entries_iop;
5039719310aSDavid Hollister 	uint32_t	fwlog_oldest_idx_iop;
5049719310aSDavid Hollister 	uint32_t	fwlog_latest_idx_iop;
5059719310aSDavid Hollister 	uint32_t	fwlog_threshold_iop;
5069719310aSDavid Hollister 	uint32_t	fwlog_findex_iop;
5074c06356bSdh 
5084c06356bSdh 	/*
5094c06356bSdh 	 * Internal register dump region and flash chunk DMA info
5104c06356bSdh 	 */
5114c06356bSdh 
5124c06356bSdh 	caddr_t		regdumpp;
5134c06356bSdh 	uint32_t	*flash_chunkp;
5144c06356bSdh 	uint64_t	flash_chunk_addr;
5154c06356bSdh 
5165c45adf0SJesse Butler 	/*
5175c45adf0SJesse Butler 	 * Copies of the last read MSGU and IOP heartbeats.
5185c45adf0SJesse Butler 	 */
5195c45adf0SJesse Butler 	uint32_t	last_msgu_tick;
5205c45adf0SJesse Butler 	uint32_t	last_iop_tick;
5215c45adf0SJesse Butler 
5224c06356bSdh 	/*
5234c06356bSdh 	 * Card information, some determined during MPI setup
5244c06356bSdh 	 */
5254c06356bSdh 	uint32_t	fw;		/* firmware version */
526*2ac4abe8SDavid Hollister 	uint32_t	ila_ver;	/* ILA version */
5274c06356bSdh 	uint8_t		max_iq;		/* maximum inbound queues this card */
5284c06356bSdh 	uint8_t 	max_oq;		/* "" outbound "" */
5294c06356bSdh 	uint8_t		nphy;		/* number of phys this card */
5304c06356bSdh 	uint8_t		chiprev;	/* chip revision */
5314c06356bSdh 	uint16_t	max_cmd;	/* max number of commands supported */
5324c06356bSdh 	uint16_t	max_dev;	/* max number of devices supported */
5334c06356bSdh 	uint16_t	last_wq_dev;	/* last dev whose wq was serviced */
5344c06356bSdh 
5355c45adf0SJesse Butler 	/*
5365c45adf0SJesse Butler 	 * Counter for the number of times watchdog fires.  We can use this
5375c45adf0SJesse Butler 	 * to throttle events which fire off of the watchdog, such as the
5385c45adf0SJesse Butler 	 * forward progress detection routine.
5395c45adf0SJesse Butler 	 */
5405c45adf0SJesse Butler 	uint8_t		watchdog_count;
5414c06356bSdh 
5424c06356bSdh 	/*
5434c06356bSdh 	 * Interrupt Setup stuff.
5444c06356bSdh 	 *
5454c06356bSdh 	 * int_type defines the kind of interrupt we're using with this card.
5464c06356bSdh 	 * oqvec defines the relationship between an Outbound Queue Number and
5474c06356bSdh 	 * a MSI-X vector.
5484c06356bSdh 	 */
5494c06356bSdh 	enum {
5504c06356bSdh 		PMCS_INT_NONE,
5514c06356bSdh 		PMCS_INT_TIMER,
5524c06356bSdh 		PMCS_INT_MSI,
5534c06356bSdh 		PMCS_INT_MSIX,
5544c06356bSdh 		PMCS_INT_FIXED
5554c06356bSdh 	} int_type;
5564c06356bSdh 	uint8_t			oqvec[PMCS_NOQ];
5574c06356bSdh 
5584c06356bSdh 	/*
5594c06356bSdh 	 * Interrupt handle table and size
5604c06356bSdh 	 */
5614c06356bSdh 	ddi_intr_handle_t	*ih_table;
5624c06356bSdh 	size_t			ih_table_size;
5634c06356bSdh 
5644c06356bSdh 	timeout_id_t		wdhandle;
5654c06356bSdh 	uint32_t		intr_mask;
5664c06356bSdh 	int			intr_cnt;
5674c06356bSdh 	int			intr_cap;
5684c06356bSdh 	uint32_t		odb_auto_clear;
5694c06356bSdh 
5704c06356bSdh 	/*
5714c06356bSdh 	 * DMA S/G chunk list
5724c06356bSdh 	 */
5734c06356bSdh 	int		nchunks;
5744c06356bSdh 	pmcs_chunk_t	*dma_chunklist;
5754c06356bSdh 
5764c06356bSdh 	/*
5774c06356bSdh 	 * Front of the DMA S/G chunk freelist
5784c06356bSdh 	 */
5794c06356bSdh 	pmcs_dmachunk_t	*dma_freelist;
5804c06356bSdh 
5814c06356bSdh 	/*
5824c06356bSdh 	 * PHY and Discovery Related Stuff
5834c06356bSdh 	 *
5844c06356bSdh 	 * The PMC chip can have up to 16 local phys. We build a level-first
5854c06356bSdh 	 * traversal tree of phys starting with the physical phys on the
5864c06356bSdh 	 * chip itself (i.e., treating the chip as if it were an expander).
5874c06356bSdh 	 *
5884c06356bSdh 	 * Our discovery process goes through a level and discovers what
5894c06356bSdh 	 * each entity is (and it's phy number within that expander's
5904c06356bSdh 	 * address space). It then configures each non-empty item (SAS,
5914c06356bSdh 	 * SATA/STP, EXPANDER). For expanders, it then performs
5924c06356bSdh 	 * discover on that expander itself via REPORT GENERAL and
5934c06356bSdh 	 * DISCOVERY SMP commands, attaching the discovered entities
5944c06356bSdh 	 * to the next level. Then we step down a level and continue
5954c06356bSdh 	 * (and so on).
5964c06356bSdh 	 *
5974c06356bSdh 	 * The PMC chip maintains an I_T_NEXUS notion based upon our
5984c06356bSdh 	 * registering each new device found (getting back a device handle).
5994c06356bSdh 	 *
6004c06356bSdh 	 * Like with the number of physical PHYS being a maximum of 16,
6014c06356bSdh 	 * there are a maximum number of PORTS also being 16. Some
6024c06356bSdh 	 * events apply to PORTS entirely, so we track PORTS as well.
6034c06356bSdh 	 */
6044c06356bSdh 	pmcs_phy_t		*root_phys;	/* HBA PHYs (level 0) */
6054c06356bSdh 	pmcs_phy_t		*ports[PMCS_MAX_PORTS];
6064c06356bSdh 	kmutex_t		dead_phylist_lock;	/* Protects dead_phys */
6074c06356bSdh 	pmcs_phy_t		*dead_phys;	/* PHYs waiting to be freed */
6084c06356bSdh 
6094c06356bSdh 	kmem_cache_t		*phy_cache;
6104c06356bSdh 
6114c06356bSdh 	/*
6124c06356bSdh 	 * Discovery-related items.
6134c06356bSdh 	 * config_lock: Protects config_changed and should never be held
6144c06356bSdh 	 * outside of getting or setting the value of config_changed.
6154c06356bSdh 	 * config_changed: Boolean indicating whether discovery needs to
6164c06356bSdh 	 * be restarted.
6174c06356bSdh 	 * configuring: 1 = discovery is running, 0 = discovery not running.
6184c06356bSdh 	 * NOTE: configuring is now in the bitfield above.
6199aed1621SDavid Hollister 	 *
6209aed1621SDavid Hollister 	 * config_restart_time is set by the tgtmap_[de]activate callbacks each
6219aed1621SDavid Hollister 	 * time we decide we want SCSA to retry enumeration on some device.
6229aed1621SDavid Hollister 	 * The watchdog timer will not fire discovery unless it has reached
6239aed1621SDavid Hollister 	 * config_restart_time and config_restart is TRUE.  This ensures that
6249aed1621SDavid Hollister 	 * we don't ask SCSA to retry enumerating devices while it is still
6259aed1621SDavid Hollister 	 * running.
6264c06356bSdh 	 */
6274c06356bSdh 	kmutex_t		config_lock;
6284c06356bSdh 	volatile boolean_t	config_changed;
6299aed1621SDavid Hollister 	boolean_t		config_restart;
6309aed1621SDavid Hollister 	clock_t			config_restart_time;
6314c06356bSdh 
6324c06356bSdh 	/*
6334c06356bSdh 	 * Work Related Stuff
6344c06356bSdh 	 *
6354c06356bSdh 	 * Each command given to the PMC chip has an associated work structure.
6364c06356bSdh 	 * See the discussion in pmcs_def.h about work structures.
6374c06356bSdh 	 */
6384c06356bSdh 	pmcwork_t	*work;		/* pool of work structures */
6394c06356bSdh 	STAILQ_HEAD(wfh, pmcwork) wf;	/* current freelist */
6404c06356bSdh 	STAILQ_HEAD(pfh, pmcwork) pf;	/* current pending freelist */
6414c06356bSdh 	uint16_t	wserno;		/* rolling serial number */
6424c06356bSdh 	kmutex_t	wfree_lock;	/* freelist/actvlist/wserno lock */
6434c06356bSdh 	kmutex_t	pfree_lock;	/* freelist/actvlist/wserno lock */
6444c06356bSdh 
6454c06356bSdh 	/*
6464c06356bSdh 	 * Solaris/SCSA items.
6474c06356bSdh 	 */
6484c06356bSdh 	scsi_hba_tran_t		*tran;
64996c4a178SChris Horne 	smp_hba_tran_t		*smp_tran;
6504c06356bSdh 	struct scsi_reset_notify_entry	*reset_notify_listf;
6514c06356bSdh 
6524c06356bSdh 	/*
6534c06356bSdh 	 * Thread Level stuff.
6544c06356bSdh 	 *
6554c06356bSdh 	 * A number of tasks are done off worker thread taskq.
6564c06356bSdh 	 */
6574c06356bSdh 	ddi_taskq_t 		*tq;		/* For the worker thread */
6584c06356bSdh 	volatile ulong_t	work_flags;
6594c06356bSdh 
6604c06356bSdh 	/*
6614c06356bSdh 	 * Solaris target representation.
6624c06356bSdh 	 * targets = array of pointers to xscsi structures
6634c06356bSdh 	 * allocated by ssoftstate.
6644c06356bSdh 	 */
6654c06356bSdh 	pmcs_xscsi_t			**targets;
6664c06356bSdh 
6674c06356bSdh 	STAILQ_HEAD(dqh, pmcs_cmd)	dq;	/* dead commands */
6684c06356bSdh 	STAILQ_HEAD(cqh, pmcs_cmd)	cq;	/* completed commands */
6694c06356bSdh 	kmutex_t			cq_lock;
6704c06356bSdh 	kmem_cache_t			*iocomp_cb_cache;
6714c06356bSdh 	pmcs_iocomp_cb_t		*iocomp_cb_head;
6724c06356bSdh 	pmcs_iocomp_cb_t		*iocomp_cb_tail;
6734c06356bSdh 
6744c06356bSdh 	uint16_t			debug_mask;
6754c06356bSdh 	uint16_t			phyid_block_mask;
6764c06356bSdh 	uint16_t			phys_started;
6774c06356bSdh 	uint32_t			hipri_queue;
6784c06356bSdh 	uint32_t			mpibar;
6794c06356bSdh 	uint32_t			intr_pri;
6804c06356bSdh 
6814c06356bSdh 	pmcs_io_intr_coal_t		io_intr_coal;
6824c06356bSdh 	pmcs_cq_info_t			cq_info;
6834c06356bSdh 	kmutex_t			ict_lock;
6844c06356bSdh 	kcondvar_t			ict_cv;
6854c06356bSdh 	kthread_t			*ict_thread;
6864c06356bSdh 
6874c06356bSdh #ifdef	DEBUG
6884c06356bSdh 	kmutex_t	dbglock;
6894c06356bSdh 	uint32_t	ltags[256];
6904c06356bSdh 	uint32_t	ftags[256];
6914c06356bSdh 	hrtime_t	ltime[256];
6924c06356bSdh 	hrtime_t	ftime[256];
6934c06356bSdh 	uint16_t	ftag_lines[256];
6944c06356bSdh 	uint8_t		lti;			/* last tag index */
6954c06356bSdh 	uint8_t		fti;			/* first tag index */
6964c06356bSdh #endif
6974c06356bSdh };
6984c06356bSdh 
6994c06356bSdh extern void 		*pmcs_softc_state;
7004c06356bSdh extern void 		*pmcs_iport_softstate;
7014c06356bSdh 
7024c06356bSdh /*
7034c06356bSdh  * Some miscellaneous, oft used strings
7044c06356bSdh  */
7054c06356bSdh extern const char pmcs_nowrk[];
7064c06356bSdh extern const char pmcs_nomsg[];
7074c06356bSdh extern const char pmcs_timeo[];
7084c06356bSdh 
70988e8a7f2SDavid Hollister /*
71088e8a7f2SDavid Hollister  * Other externs
71188e8a7f2SDavid Hollister  */
71288e8a7f2SDavid Hollister extern int modrootloaded;
71388e8a7f2SDavid Hollister 
7144c06356bSdh #ifdef	__cplusplus
7154c06356bSdh }
7164c06356bSdh #endif
7174c06356bSdh #endif	/* _PMCS_H */
718