1*8226594fSRick McNeal /*
2*8226594fSRick McNeal  * This file and its contents are supplied under the terms of the
3*8226594fSRick McNeal  * Common Development and Distribution License ("CDDL"), version 1.0.
4*8226594fSRick McNeal  * You may only use this file in accordance with the terms of version
5*8226594fSRick McNeal  * 1.0 of the CDDL.
6*8226594fSRick McNeal  *
7*8226594fSRick McNeal  * A full copy of the text of the CDDL should have accompanied this
8*8226594fSRick McNeal  * source.  A copy of the CDDL is also available via the Internet at
9*8226594fSRick McNeal  * http://www.illumos.org/license/CDDL.
10*8226594fSRick McNeal  */
11*8226594fSRick McNeal 
12*8226594fSRick McNeal /*
13*8226594fSRick McNeal  * Copyright 2023 Tintri by DDN, Inc. All rights reserved.
14*8226594fSRick McNeal  * Copyright 2021 RackTop Systems, Inc.
15*8226594fSRick McNeal  */
16*8226594fSRick McNeal 
17*8226594fSRick McNeal #ifndef _SMARTPQI_H
18*8226594fSRick McNeal #define	_SMARTPQI_H
19*8226594fSRick McNeal 
20*8226594fSRick McNeal #ifdef __cplusplus
21*8226594fSRick McNeal extern "C" {
22*8226594fSRick McNeal #endif
23*8226594fSRick McNeal 
24*8226594fSRick McNeal /* ---- Standard header files. ---- */
25*8226594fSRick McNeal #include <sys/note.h>
26*8226594fSRick McNeal #include <sys/byteorder.h>
27*8226594fSRick McNeal #include <sys/scsi/scsi.h>
28*8226594fSRick McNeal #include <sys/pci.h>
29*8226594fSRick McNeal #include <sys/file.h>
30*8226594fSRick McNeal #include <sys/policy.h>
31*8226594fSRick McNeal #include <sys/model.h>
32*8226594fSRick McNeal #include <sys/sysevent.h>
33*8226594fSRick McNeal #include <sys/sysevent/eventdefs.h>
34*8226594fSRick McNeal #include <sys/sysevent/dr.h>
35*8226594fSRick McNeal #include <sys/sata/sata_defs.h>
36*8226594fSRick McNeal #include <sys/sata/sata_hba.h>
37*8226594fSRick McNeal #include <sys/scsi/generic/sas.h>
38*8226594fSRick McNeal #include <sys/scsi/impl/scsi_sas.h>
39*8226594fSRick McNeal #include <sys/scsi/impl/scsi_reset_notify.h>
40*8226594fSRick McNeal #include <sys/sdt.h>
41*8226594fSRick McNeal #include <sys/mdi_impldefs.h>
42*8226594fSRick McNeal #include <sys/fs/dv_node.h>
43*8226594fSRick McNeal #include <sys/sysmacros.h>
44*8226594fSRick McNeal #include <sys/systm.h>
45*8226594fSRick McNeal #include <smartpqi_hw.h>
46*8226594fSRick McNeal 
47*8226594fSRick McNeal /* ---- Hint for ddi_soft_state_init() on amount of structs to alloc ---- */
48*8226594fSRick McNeal #define	SMARTPQI_INITIAL_SOFT_SPACE	1
49*8226594fSRick McNeal 
50*8226594fSRick McNeal #define	SMARTPQI_MOD_STRING	"smartpqi RT-20210716"
51*8226594fSRick McNeal 
52*8226594fSRick McNeal /* ---- Handy constants ---- */
53*8226594fSRick McNeal #define	UNDEFINED				-1
54*8226594fSRick McNeal #define	MAX_NAME_PROP_SIZE			256
55*8226594fSRick McNeal #define	LUN_PROP				"lun"
56*8226594fSRick McNeal #define	LUN64_PROP				"lun64"
57*8226594fSRick McNeal #define	MDI_GUID				"wwn"
58*8226594fSRick McNeal #define	NDI_GUID				"guid"
59*8226594fSRick McNeal #define	TARGET_PROP				"target"
60*8226594fSRick McNeal #define	LUN_PROP				"lun"
61*8226594fSRick McNeal #define	COMPAT_PROP				"compatible"
62*8226594fSRick McNeal #define	NAME_DISK				"disk"
63*8226594fSRick McNeal #define	NAME_ENCLOSURE				"enclosure"
64*8226594fSRick McNeal 
65*8226594fSRick McNeal #define	CMD_TIMEOUT_SCAN_SECS			10
66*8226594fSRick McNeal #define	SYNC_CMDS_TIMEOUT_SECS			5
67*8226594fSRick McNeal #define	IO_SPACE				1
68*8226594fSRick McNeal #define	PQI_MAXTGTS				256
69*8226594fSRick McNeal 
70*8226594fSRick McNeal #define	PQI_MIN_MSIX_VECTORS			1
71*8226594fSRick McNeal #define	PQI_MAX_MSIX_VECTORS			16
72*8226594fSRick McNeal #define	PQI_DEFAULT_QUEUE_GROUP			0
73*8226594fSRick McNeal #define	PQI_MAX_QUEUE_GROUPS			PQI_MAX_MSIX_VECTORS
74*8226594fSRick McNeal #define	PQI_MIN_OPERATIONAL_QUEUE_ID		1
75*8226594fSRick McNeal #define	PQI_NGENS				16
76*8226594fSRick McNeal #define	PQI_MAX_IO_SLOTS			(1 << 12)
77*8226594fSRick McNeal #define	PQI_SLOT_INDEX_MASK			0xfff
78*8226594fSRick McNeal #define	PQI_GENSHIFT				12
79*8226594fSRick McNeal /*
80*8226594fSRick McNeal  * Generate and extract fields from a 16 bit io request id.
81*8226594fSRick McNeal  * We generate a request id by combining a 12 bit slot index with a
82*8226594fSRick McNeal  * 4 bit generation count.
83*8226594fSRick McNeal  */
84*8226594fSRick McNeal #define	PQI_MAKE_REQID(index, gen) (((gen) << PQI_GENSHIFT) | (index))
85*8226594fSRick McNeal #define	PQI_REQID_GEN(id)	((id) >> PQI_GENSHIFT)
86*8226594fSRick McNeal #define	PQI_REQID_INDEX(id)	((id) & PQI_SLOT_INDEX_MASK)
87*8226594fSRick McNeal 
88*8226594fSRick McNeal /* ---- Size of structure scsi_arq_status without sense data. ---- */
89*8226594fSRick McNeal #define	PQI_ARQ_STATUS_NOSENSE_LEN	(sizeof (struct scsi_arq_status) - \
90*8226594fSRick McNeal     sizeof (struct scsi_extended_sense))
91*8226594fSRick McNeal 
92*8226594fSRick McNeal /* ---- macros to return various addresses ---- */
93*8226594fSRick McNeal #define	ADDR2TRAN(ap)	((ap)->a_hba_tran)
94*8226594fSRick McNeal #define	TRAN2PQI(hba)	((pqi_state_t *)(hba)->tran_hba_private)
95*8226594fSRick McNeal #define	ADDR2PQI(ap)	(TRAN2PQI(ADDR2TRAN(ap)))
96*8226594fSRick McNeal #define	PKT2CMD(pkt)	((pqi_cmd_t *)(pkt)->pkt_ha_private)
97*8226594fSRick McNeal #define	CMD2PKT(cmd)	((struct scsi_pkt *)(cmd)->pc_pkt)
98*8226594fSRick McNeal 
99*8226594fSRick McNeal /* ---- PQI configuration ---- */
100*8226594fSRick McNeal #define	PQI_MAX_OUTSTANDING_REQUESTS		32
101*8226594fSRick McNeal #define	PQI_ERROR_BUFFER_ELEMENT_LENGTH sizeof (struct pqi_raid_error_info)
102*8226594fSRick McNeal #define	PQI_CREATE_ADMIN_QUEUE_PAIR		1
103*8226594fSRick McNeal #define	PQI_DELETE_ADMIN_QUEUE_PAIR		2
104*8226594fSRick McNeal #define	PQI_MAX_TRANSFER_SIZE			(4 * 1024U * 1024U)
105*8226594fSRick McNeal #define	PQI_MAX_RESET_XFER_SIZE			(512 * 1024)
106*8226594fSRick McNeal #define	PQI_NUM_SUPPORTED_EVENTS		7
107*8226594fSRick McNeal #define	PQI_RESERVED_IO_SLOTS_LUN_RESET		1
108*8226594fSRick McNeal #define	PQI_RESERVED_IO_SLOTS_EVENT_ACK	PQI_NUM_SUPPORTED_EVENTS
109*8226594fSRick McNeal #define	PQI_RESERVED_IO_SLOTS_SYNCHRONOUS_REQUESTS	3
110*8226594fSRick McNeal #define	PQI_RESERVED_IO_SLOTS \
111*8226594fSRick McNeal 	(PQI_RESERVED_IO_SLOTS_LUN_RESET + PQI_RESERVED_IO_SLOTS_EVENT_ACK + \
112*8226594fSRick McNeal 	PQI_RESERVED_IO_SLOTS_SYNCHRONOUS_REQUESTS)
113*8226594fSRick McNeal #define	PQI_MAX_SCATTER_GATHER			0x200
114*8226594fSRick McNeal 
115*8226594fSRick McNeal /* ---- SIS constants ---- */
116*8226594fSRick McNeal #define	SIS_BASE_STRUCT_ALIGNMENT		16
117*8226594fSRick McNeal 
118*8226594fSRick McNeal /* ---- Once every 10 seconds ---- */
119*8226594fSRick McNeal #define	WATCHDOG (10 * MICROSEC)
120*8226594fSRick McNeal 
121*8226594fSRick McNeal /* ---- Update HBA time of day clock once a day ---- */
122*8226594fSRick McNeal #define	MINUTE		60
123*8226594fSRick McNeal #define	HOUR		(60 * MINUTE)
124*8226594fSRick McNeal #define	DAY		(24 * HOUR)
125*8226594fSRick McNeal 
126*8226594fSRick McNeal #define	HBA_IS_QUIESCED(s)	(((s)->s_flags & PQI_HBA_QUIESCED) != 0)
127*8226594fSRick McNeal #define	HBA_QUIESCED_PENDING(s)	\
128*8226594fSRick McNeal 	(((s)->s_flags & PQI_HBA_QUIESCED_PENDING) != 0 && \
129*8226594fSRick McNeal 	((s)->s_cmd_queue_len == 0))
130*8226594fSRick McNeal 
131*8226594fSRick McNeal /*
132*8226594fSRick McNeal  * The PQIALIGN_TYPED() does round up to produce aligned value,
133*8226594fSRick McNeal  * and is built to support pointers.
134*8226594fSRick McNeal  * We could use P2ROUNDUP_TYPED from sysmacros.h, but unfortunately,
135*8226594fSRick McNeal  * P2ROUNDUP_TYPED does not work with pointer types.
136*8226594fSRick McNeal  */
137*8226594fSRick McNeal #define	PQIALIGN_TYPED(addr, align, type) \
138*8226594fSRick McNeal 	(type)(((uintptr_t)(addr) + align - 1) & ~(align - 1))
139*8226594fSRick McNeal 
140*8226594fSRick McNeal /* ---- Handy macros to get/set device registers ---- */
141*8226594fSRick McNeal #define	G8(state, __reg__) \
142*8226594fSRick McNeal     ddi_get8(state->s_datap, &state->s_reg->__reg__)
143*8226594fSRick McNeal #define	G16(state, __reg__) \
144*8226594fSRick McNeal     ddi_get16(state->s_datap, &state->s_reg->__reg__)
145*8226594fSRick McNeal #define	G32(state, __reg__) \
146*8226594fSRick McNeal     ddi_get32(state->s_datap, &state->s_reg->__reg__)
147*8226594fSRick McNeal #define	S8(state, __reg__, val) \
148*8226594fSRick McNeal     ddi_put8(state->s_datap, &state->s_reg->__reg__, val)
149*8226594fSRick McNeal #define	S32(state, __reg__, val) \
150*8226594fSRick McNeal     ddi_put32(state->s_datap, &state->s_reg->__reg__, val)
151*8226594fSRick McNeal #define	S64(state, __reg__, val) \
152*8226594fSRick McNeal     ddi_put64(state->s_datap, &state->s_reg->__reg__, val)
153*8226594fSRick McNeal #define	G64(state, __reg__) \
154*8226594fSRick McNeal     ddi_get64(state->s_datap, &state->s_reg->__reg__)
155*8226594fSRick McNeal 
156*8226594fSRick McNeal /*
157*8226594fSRick McNeal  * Yuck! Internal knowledge of MPxIO, but since this variable is required
158*8226594fSRick McNeal  * to use MPxIO and there's no public API it must be declared here. Both
159*8226594fSRick McNeal  * the iSCSI Initiator and MPT SAS drivers do the same thing.
160*8226594fSRick McNeal  */
161*8226594fSRick McNeal extern dev_info_t *scsi_vhci_dip;
162*8226594fSRick McNeal 
163*8226594fSRick McNeal typedef enum pqi_io_path {
164*8226594fSRick McNeal 	RAID_PATH = 0,
165*8226594fSRick McNeal 	AIO_PATH = 1
166*8226594fSRick McNeal } pqi_path_t;
167*8226594fSRick McNeal 
168*8226594fSRick McNeal typedef struct dma_overhead {
169*8226594fSRick McNeal 	ddi_dma_handle_t	handle;
170*8226594fSRick McNeal 	ddi_acc_handle_t	acc;
171*8226594fSRick McNeal 	caddr_t			alloc_memory;
172*8226594fSRick McNeal 	size_t			len_to_alloc;
173*8226594fSRick McNeal 	size_t			allocated_len;
174*8226594fSRick McNeal 	uint64_t		dma_addr;
175*8226594fSRick McNeal 	uint_t			cookie_count;
176*8226594fSRick McNeal 	ddi_dma_cookie_t	second;
177*8226594fSRick McNeal } pqi_dma_overhead_t;
178*8226594fSRick McNeal 
179*8226594fSRick McNeal typedef struct pqi_admin_queues {
180*8226594fSRick McNeal 	caddr_t			iq_element_array;
181*8226594fSRick McNeal 	caddr_t			oq_element_array;
182*8226594fSRick McNeal 	volatile pqi_index_t	*iq_ci;
183*8226594fSRick McNeal 	pqi_index_t		*oq_pi;
184*8226594fSRick McNeal 	uint64_t		iq_element_array_bus_addr;
185*8226594fSRick McNeal 	uint64_t		oq_element_array_bus_addr;
186*8226594fSRick McNeal 	uint64_t		iq_ci_bus_addr;
187*8226594fSRick McNeal 	uint64_t		oq_pi_bus_addr;
188*8226594fSRick McNeal 	uint32_t		*iq_pi;
189*8226594fSRick McNeal 	pqi_index_t		iq_pi_copy;
190*8226594fSRick McNeal 	uint32_t		*oq_ci;
191*8226594fSRick McNeal 	pqi_index_t		oq_ci_copy;
192*8226594fSRick McNeal 	struct task_struct	*task;
193*8226594fSRick McNeal 	uint16_t		int_msg_num;
194*8226594fSRick McNeal } pqi_admin_queues_t;
195*8226594fSRick McNeal 
196*8226594fSRick McNeal typedef struct pqi_event_queue {
197*8226594fSRick McNeal 	uint16_t		oq_id;
198*8226594fSRick McNeal 	uint16_t		int_msg_num;
199*8226594fSRick McNeal 	void			*oq_element_array;
200*8226594fSRick McNeal 	pqi_index_t		*oq_pi;		/* In s_queue_dma space */
201*8226594fSRick McNeal 	uint64_t		oq_element_array_bus_addr;
202*8226594fSRick McNeal 	uint64_t		oq_pi_bus_addr;
203*8226594fSRick McNeal 	uint32_t		*oq_ci;		/* In s_reg space */
204*8226594fSRick McNeal 	pqi_index_t		oq_ci_copy;
205*8226594fSRick McNeal } pqi_event_queue_t;
206*8226594fSRick McNeal 
207*8226594fSRick McNeal typedef struct pqi_queue_group {
208*8226594fSRick McNeal 	struct pqi_state	*qg_softc;	/* backpointer */
209*8226594fSRick McNeal 	uint16_t		iq_id[2];
210*8226594fSRick McNeal 	uint16_t		oq_id;
211*8226594fSRick McNeal 	uint16_t		int_msg_num;
212*8226594fSRick McNeal 	caddr_t			iq_element_array[2];
213*8226594fSRick McNeal 	caddr_t			oq_element_array;
214*8226594fSRick McNeal 	uint64_t		iq_element_array_bus_addr[2];
215*8226594fSRick McNeal 	uint64_t		oq_element_array_bus_addr;
216*8226594fSRick McNeal 	pqi_index_t		iq_pi_copy[2];
217*8226594fSRick McNeal 	pqi_index_t		oq_ci_copy;
218*8226594fSRick McNeal 	/* ---- In s_reg space ---- */
219*8226594fSRick McNeal 	uint32_t		*iq_pi[2];
220*8226594fSRick McNeal 	uint32_t		*oq_ci;
221*8226594fSRick McNeal 
222*8226594fSRick McNeal 	/* ---- In s_queue_dma space ---- */
223*8226594fSRick McNeal 	pqi_index_t		*iq_ci[2];
224*8226594fSRick McNeal 	pqi_index_t		*oq_pi;
225*8226594fSRick McNeal 
226*8226594fSRick McNeal 	uint64_t		iq_ci_bus_addr[2];
227*8226594fSRick McNeal 	uint64_t		oq_pi_bus_addr;
228*8226594fSRick McNeal 
229*8226594fSRick McNeal 	kmutex_t		submit_lock[2]; /* protect submission queue */
230*8226594fSRick McNeal 	list_t			request_list[2];
231*8226594fSRick McNeal 	int			submit_count;
232*8226594fSRick McNeal 	int			cmplt_count;
233*8226594fSRick McNeal 	boolean_t		qg_active;
234*8226594fSRick McNeal } pqi_queue_group_t;
235*8226594fSRick McNeal 
236*8226594fSRick McNeal typedef struct pqi_io_request {
237*8226594fSRick McNeal 	kmutex_t		io_lock; /* protect generation/serviced flag */
238*8226594fSRick McNeal 	uint32_t		io_refcount;
239*8226594fSRick McNeal 	uint16_t		io_index;
240*8226594fSRick McNeal 	void			(*io_cb)(struct pqi_io_request *, void *);
241*8226594fSRick McNeal 	void			*io_context;
242*8226594fSRick McNeal 	uint8_t			io_raid_bypass : 1;
243*8226594fSRick McNeal 	uint8_t			io_gen;
244*8226594fSRick McNeal 	boolean_t		io_serviced;
245*8226594fSRick McNeal 	int			io_status;
246*8226594fSRick McNeal 	pqi_queue_group_t	*io_queue_group;
247*8226594fSRick McNeal 	int			io_queue_path;
248*8226594fSRick McNeal 	struct pqi_cmd		*io_cmd;
249*8226594fSRick McNeal 	void			*io_error_info;
250*8226594fSRick McNeal 	pqi_dma_overhead_t	*io_sg_chain_dma;
251*8226594fSRick McNeal 	void			*io_iu;
252*8226594fSRick McNeal 	list_node_t		io_list_node;
253*8226594fSRick McNeal 
254*8226594fSRick McNeal 	/* ---- Debug aids ---- */
255*8226594fSRick McNeal 	pqi_index_t		io_pi;
256*8226594fSRick McNeal 	int			io_iu_type;
257*8226594fSRick McNeal 
258*8226594fSRick McNeal 	struct pqi_state	*io_softc;
259*8226594fSRick McNeal } pqi_io_request_t;
260*8226594fSRick McNeal 
261*8226594fSRick McNeal typedef struct pqi_event {
262*8226594fSRick McNeal 	boolean_t		ev_pending;
263*8226594fSRick McNeal 	uint8_t			ev_type;
264*8226594fSRick McNeal 	uint16_t		ev_id;
265*8226594fSRick McNeal 	uint32_t		ev_additional;
266*8226594fSRick McNeal } pqi_event_t;
267*8226594fSRick McNeal 
268*8226594fSRick McNeal /* ---- Flags used in pqi_state ---- */
269*8226594fSRick McNeal #define	PQI_HBA_DRIVER_SHUTDOWN			0x0001
270*8226594fSRick McNeal #define	PQI_HBA_QUIESCED			0x0002
271*8226594fSRick McNeal #define	PQI_HBA_QUIESCED_PENDING		0x0004
272*8226594fSRick McNeal #define	PQI_HBA_AUTO_REQUEST_SENSE		0x0008
273*8226594fSRick McNeal #define	PQI_HBA_LUN_RESET_CAP			0x0010
274*8226594fSRick McNeal 
275*8226594fSRick McNeal /* ---- Debug flags, example debug=0x10; in .conf file ---- */
276*8226594fSRick McNeal #define	DBG_LVL_CDB				0x0001
277*8226594fSRick McNeal #define	DBG_LVL_RQST				0x0002
278*8226594fSRick McNeal #define	DBG_LVL_STATE				0x0004
279*8226594fSRick McNeal #define	DBG_LVL_RAW_RQST			0x0008
280*8226594fSRick McNeal 
281*8226594fSRick McNeal typedef struct pqi_device {
282*8226594fSRick McNeal 	list_node_t		pd_list;
283*8226594fSRick McNeal 	kmutex_t		pd_mutex;
284*8226594fSRick McNeal 
285*8226594fSRick McNeal 	/* ---- Protected by pd_mutex ---- */
286*8226594fSRick McNeal 	list_t			pd_cmd_list;
287*8226594fSRick McNeal 	int			pd_flags;
288*8226594fSRick McNeal 
289*8226594fSRick McNeal 	int			pd_active_cmds;
290*8226594fSRick McNeal 	int			pd_target;
291*8226594fSRick McNeal 	int			pd_lun;
292*8226594fSRick McNeal 
293*8226594fSRick McNeal 	/* ---- Only one will be valid, MPxIO uses s_pip ---- */
294*8226594fSRick McNeal 	dev_info_t		*pd_dip;
295*8226594fSRick McNeal 	mdi_pathinfo_t		*pd_pip;
296*8226594fSRick McNeal 	mdi_pathinfo_t		*pd_pip_offlined;
297*8226594fSRick McNeal 
298*8226594fSRick McNeal 	dev_info_t		*pd_parent;
299*8226594fSRick McNeal 	int			pd_devtype;
300*8226594fSRick McNeal 	int			pd_online : 1;
301*8226594fSRick McNeal 	int			pd_scanned : 1;
302*8226594fSRick McNeal 	int			pd_phys_dev : 1;
303*8226594fSRick McNeal 	int			pd_external_raid : 1;
304*8226594fSRick McNeal 	int			pd_aio_enabled : 1;
305*8226594fSRick McNeal 	uint32_t		pd_aio_handle;
306*8226594fSRick McNeal 	char			pd_scsi3addr[8];
307*8226594fSRick McNeal 	uint64_t		pd_wwid;
308*8226594fSRick McNeal 	char			*pd_guid;
309*8226594fSRick McNeal 	uint8_t			pd_volume_id[16];
310*8226594fSRick McNeal 	char			pd_vendor[8];	/* From INQUIRY */
311*8226594fSRick McNeal 	char			pd_model[16];	/* From INQUIRY */
312*8226594fSRick McNeal 	char			pd_unit_address[32];
313*8226594fSRick McNeal 
314*8226594fSRick McNeal 	/* ---- Debug stats ---- */
315*8226594fSRick McNeal 	uint32_t		pd_killed;
316*8226594fSRick McNeal 	uint32_t		pd_posted;
317*8226594fSRick McNeal 	uint32_t		pd_timedout;
318*8226594fSRick McNeal 	uint32_t		pd_sense_errors;
319*8226594fSRick McNeal } pqi_device_t;
320*8226594fSRick McNeal 
321*8226594fSRick McNeal typedef struct pqi_state {
322*8226594fSRick McNeal 	int			s_instance;
323*8226594fSRick McNeal 	dev_info_t		*s_dip;
324*8226594fSRick McNeal 	int			s_flags;
325*8226594fSRick McNeal 	kmutex_t		s_mutex;
326*8226594fSRick McNeal 	kmutex_t		s_intr_mutex;
327*8226594fSRick McNeal 	kcondvar_t		s_quiescedvar;
328*8226594fSRick McNeal 	uint32_t		s_next_target;
329*8226594fSRick McNeal 
330*8226594fSRick McNeal 	/* ---- Used for serialized commands through driver ---- */
331*8226594fSRick McNeal 	struct pqi_device	s_special_device;
332*8226594fSRick McNeal 
333*8226594fSRick McNeal 	boolean_t		s_intr_ready;
334*8226594fSRick McNeal 	boolean_t		s_offline;
335*8226594fSRick McNeal 	boolean_t		s_disable_mpxio;
336*8226594fSRick McNeal 	kmem_cache_t		*s_cmd_cache;
337*8226594fSRick McNeal 	ddi_taskq_t		*s_events_taskq;
338*8226594fSRick McNeal 	ddi_taskq_t		*s_complete_taskq;
339*8226594fSRick McNeal 	timeout_id_t		s_time_of_day;
340*8226594fSRick McNeal 	timeout_id_t		s_cmd_timeout;
341*8226594fSRick McNeal 
342*8226594fSRick McNeal 	/* ---- Debug related state ---- */
343*8226594fSRick McNeal 	int			s_debug_level;
344*8226594fSRick McNeal 
345*8226594fSRick McNeal 	/* ---- State for watchdog ---- */
346*8226594fSRick McNeal 	timeout_id_t		s_watchdog;
347*8226594fSRick McNeal 	uint32_t		s_last_intr_count;
348*8226594fSRick McNeal 	uint32_t		s_last_heartbeat_count;
349*8226594fSRick McNeal 	uint32_t		s_intr_count;
350*8226594fSRick McNeal 
351*8226594fSRick McNeal 	/* ---- Interrupt related fields ---- */
352*8226594fSRick McNeal 	int			s_intr_type;	/* Type of interrupt used */
353*8226594fSRick McNeal 	int			s_intr_cnt;	/* # of interrupts */
354*8226594fSRick McNeal 	uint_t			s_intr_pri;	/* Interrupt priority */
355*8226594fSRick McNeal 	int			s_intr_cap;	/* Interrupt capabilities */
356*8226594fSRick McNeal 	int			s_intr_size;	/* Size of s_htable */
357*8226594fSRick McNeal 	ddi_intr_handle_t	*s_itable;	/* Interrupt table */
358*8226594fSRick McNeal 
359*8226594fSRick McNeal 	scsi_hba_tran_t		*s_tran;
360*8226594fSRick McNeal 	ddi_dma_attr_t		s_msg_dma_attr;	/* Used for message frames */
361*8226594fSRick McNeal 
362*8226594fSRick McNeal 	/* ---- list of reset notification requests ---- */
363*8226594fSRick McNeal 	struct scsi_reset_notify_entry	*s_reset_notify_listf;
364*8226594fSRick McNeal 
365*8226594fSRick McNeal 	pqi_ctrl_regs_t		*s_reg;
366*8226594fSRick McNeal 	ddi_device_acc_attr_t	s_reg_acc_attr;
367*8226594fSRick McNeal 	/* ---- operating regs data access handle ---- */
368*8226594fSRick McNeal 	ddi_acc_handle_t	s_datap;
369*8226594fSRick McNeal 
370*8226594fSRick McNeal 	list_t			s_devnodes;
371*8226594fSRick McNeal 	volatile uint32_t	s_cmd_queue_len;
372*8226594fSRick McNeal 
373*8226594fSRick McNeal 	/* ---- SIS capabilities from controller ---- */
374*8226594fSRick McNeal 	uint32_t		s_max_sg_entries;
375*8226594fSRick McNeal 	uint32_t		s_max_xfer_size;
376*8226594fSRick McNeal 	uint32_t		s_max_outstanding_requests;
377*8226594fSRick McNeal 	uint32_t		s_config_table_offset;
378*8226594fSRick McNeal 	uint32_t		s_config_table_len;
379*8226594fSRick McNeal 
380*8226594fSRick McNeal 	/* ---- PQI capabilities from controller ---- */
381*8226594fSRick McNeal 	uint32_t		*s_heartbeat_counter;
382*8226594fSRick McNeal 	uint16_t		s_max_inbound_queues;
383*8226594fSRick McNeal 	uint16_t		s_max_elements_per_iq;
384*8226594fSRick McNeal 	uint16_t		s_max_iq_element_length;
385*8226594fSRick McNeal 	uint16_t		s_max_outbound_queues;
386*8226594fSRick McNeal 	uint16_t		s_max_elements_per_oq;
387*8226594fSRick McNeal 	uint16_t		s_max_oq_element_length;
388*8226594fSRick McNeal 	uint16_t		s_max_inbound_iu_length_per_firmware;
389*8226594fSRick McNeal 	uint8_t			s_inbound_spanning_supported : 1,
390*8226594fSRick McNeal 				s_outbound_spanning_supported:1,
391*8226594fSRick McNeal 				s_pqi_mode_enabled : 1;
392*8226594fSRick McNeal 	char			s_firmware_version[11];
393*8226594fSRick McNeal 
394*8226594fSRick McNeal 	/* ---- Computed values from config ---- */
395*8226594fSRick McNeal 	uint32_t		s_max_sg_per_iu;
396*8226594fSRick McNeal 	uint32_t		s_num_elements_per_iq;
397*8226594fSRick McNeal 	uint32_t		s_num_elements_per_oq;
398*8226594fSRick McNeal 	uint32_t		s_max_inbound_iu_length;
399*8226594fSRick McNeal 	uint32_t		s_num_queue_groups;
400*8226594fSRick McNeal 	uint32_t		s_max_io_slots;
401*8226594fSRick McNeal 	uint32_t		s_sg_chain_buf_length;
402*8226594fSRick McNeal 	uint32_t		s_max_sectors;
403*8226594fSRick McNeal 
404*8226594fSRick McNeal 	/* ---- allocation/free is protected by s_io_mutex ---- */
405*8226594fSRick McNeal 	kmutex_t		s_io_mutex;
406*8226594fSRick McNeal 	kcondvar_t		s_io_condvar;
407*8226594fSRick McNeal 	pqi_io_request_t	*s_io_rqst_pool;
408*8226594fSRick McNeal 	int			s_io_wait_cnt;
409*8226594fSRick McNeal 	int			s_next_io_slot;
410*8226594fSRick McNeal 	uint32_t		s_io_need;
411*8226594fSRick McNeal 	uint32_t		s_io_had2wait;
412*8226594fSRick McNeal 	uint32_t		s_io_sig;
413*8226594fSRick McNeal 
414*8226594fSRick McNeal 	pqi_dma_overhead_t	*s_error_dma;
415*8226594fSRick McNeal 	pqi_dma_overhead_t	*s_adminq_dma;
416*8226594fSRick McNeal 	pqi_admin_queues_t	s_admin_queues;
417*8226594fSRick McNeal 	pqi_dma_overhead_t	*s_queue_dma;
418*8226594fSRick McNeal 	pqi_queue_group_t	s_queue_groups[PQI_MAX_QUEUE_GROUPS];
419*8226594fSRick McNeal 	pqi_event_queue_t	s_event_queue;
420*8226594fSRick McNeal 	struct pqi_event	s_events[PQI_NUM_SUPPORTED_EVENTS];
421*8226594fSRick McNeal } pqi_state_t;
422*8226594fSRick McNeal 
423*8226594fSRick McNeal /* ---- Flags used in pqi_cmd_t ---- */
424*8226594fSRick McNeal #define	PQI_FLAG_ABORTED	0x0001
425*8226594fSRick McNeal #define	PQI_FLAG_TIMED_OUT	0x0002
426*8226594fSRick McNeal #define	PQI_FLAG_RESET		0x0004
427*8226594fSRick McNeal #define	PQI_FLAG_IO_IOPB	0x0040
428*8226594fSRick McNeal #define	PQI_FLAG_DMA_VALID	0x0100
429*8226594fSRick McNeal #define	PQI_FLAG_CDB_EXT	0x0200
430*8226594fSRick McNeal #define	PQI_FLAG_SCB_EXT	0x0400
431*8226594fSRick McNeal #define	PQI_FLAG_PRIV_EXT	0x0800
432*8226594fSRick McNeal #define	PQI_FLAG_IO_READ	0x1000
433*8226594fSRick McNeal #define	PQI_FLAG_IO_BOUNCE	0x2000
434*8226594fSRick McNeal #define	PQI_FLAG_FINISHING	0x4000
435*8226594fSRick McNeal 
436*8226594fSRick McNeal typedef enum pqi_cmd_action {
437*8226594fSRick McNeal 	PQI_CMD_UNINIT,
438*8226594fSRick McNeal 	PQI_CMD_QUEUE,
439*8226594fSRick McNeal 	PQI_CMD_START,
440*8226594fSRick McNeal 	PQI_CMD_CMPLT,
441*8226594fSRick McNeal 	PQI_CMD_TIMEOUT,
442*8226594fSRick McNeal 	PQI_CMD_FAIL
443*8226594fSRick McNeal } pqi_cmd_action_t;
444*8226594fSRick McNeal 
445*8226594fSRick McNeal #define	PQI_FLAGS_PERSISTENT	\
446*8226594fSRick McNeal 	(PQI_FLAG_DMA_VALID	|\
447*8226594fSRick McNeal 	PQI_FLAG_IO_IOPB)
448*8226594fSRick McNeal 
449*8226594fSRick McNeal #define	PQI_FLAGS_NON_HW_COMPLETION \
450*8226594fSRick McNeal 	(PQI_FLAG_ABORTED	|\
451*8226594fSRick McNeal 	PQI_FLAG_TIMED_OUT	|\
452*8226594fSRick McNeal 	PQI_FLAG_RESET)
453*8226594fSRick McNeal 
454*8226594fSRick McNeal typedef struct pqi_cmd {
455*8226594fSRick McNeal 	list_node_t		pc_list;
456*8226594fSRick McNeal 	kmutex_t		pc_mutex;	// protects pc_cmd_state
457*8226594fSRick McNeal 
458*8226594fSRick McNeal 	pqi_cmd_action_t	pc_cur_action;
459*8226594fSRick McNeal 	pqi_cmd_action_t	pc_last_action;
460*8226594fSRick McNeal 
461*8226594fSRick McNeal 	struct scsi_pkt		*pc_pkt;
462*8226594fSRick McNeal 	pqi_state_t		*pc_softc;
463*8226594fSRick McNeal 	pqi_device_t		*pc_device;
464*8226594fSRick McNeal 	ksema_t			*pc_poll;
465*8226594fSRick McNeal 	uint8_t			pc_cdb[SCSI_CDB_SIZE];
466*8226594fSRick McNeal 	struct scsi_arq_status	pc_cmd_scb;
467*8226594fSRick McNeal 
468*8226594fSRick McNeal 	uint64_t		pc_tgt_priv[2];
469*8226594fSRick McNeal 	int			pc_dma_count;	/* bytes to transfer */
470*8226594fSRick McNeal 
471*8226594fSRick McNeal 	/*
472*8226594fSRick McNeal 	 * Setting/clearing/testing of ABORT and FINISHING are
473*8226594fSRick McNeal 	 * protected by pqi_device->pd_mutex. The other bits in
474*8226594fSRick McNeal 	 * this flag are set during init_pkt and read only during
475*8226594fSRick McNeal 	 * cleanup.
476*8226594fSRick McNeal 	 */
477*8226594fSRick McNeal 	int			pc_flags;
478*8226594fSRick McNeal 
479*8226594fSRick McNeal 	int			pc_tgtlen;
480*8226594fSRick McNeal 	int			pc_statuslen;
481*8226594fSRick McNeal 	int			pc_cmdlen;
482*8226594fSRick McNeal 	hrtime_t		pc_expiration;
483*8226594fSRick McNeal 	hrtime_t		pc_start_time;
484*8226594fSRick McNeal 
485*8226594fSRick McNeal 	/* ---- For partial DMA transfers ---- */
486*8226594fSRick McNeal 	uint_t			pc_nwin;
487*8226594fSRick McNeal 	uint_t			pc_winidx;
488*8226594fSRick McNeal 	off_t			pc_dma_offset;
489*8226594fSRick McNeal 	size_t			pc_dma_len;
490*8226594fSRick McNeal 
491*8226594fSRick McNeal 	/* ---- Valid after call to pqi_transport_command ---- */
492*8226594fSRick McNeal 	pqi_io_request_t	*pc_io_rqst;
493*8226594fSRick McNeal 
494*8226594fSRick McNeal 	ddi_dma_handle_t	pc_dmahdl;
495*8226594fSRick McNeal 	ddi_dma_cookie_t	pc_dmac;
496*8226594fSRick McNeal 	uint_t			pc_dmaccount;	/* cookie count */
497*8226594fSRick McNeal 	struct scsi_pkt		pc_cached_pkt;
498*8226594fSRick McNeal 	ddi_dma_cookie_t	pc_cached_cookies[PQI_MAX_SCATTER_GATHER];
499*8226594fSRick McNeal } pqi_cmd_t;
500*8226594fSRick McNeal 
501*8226594fSRick McNeal /* ---- configuration table section IDs ---- */
502*8226594fSRick McNeal #define	PQI_CONFIG_TABLE_SECTION_GENERAL_INFO		0
503*8226594fSRick McNeal #define	PQI_CONFIG_TABLE_SECTION_FIRMWARE_FEATURES	1
504*8226594fSRick McNeal #define	PQI_CONFIG_TABLE_SECTION_FIRMWARE_ERRATA	2
505*8226594fSRick McNeal #define	PQI_CONFIG_TABLE_SECTION_DEBUG			3
506*8226594fSRick McNeal #define	PQI_CONFIG_TABLE_SECTION_HEARTBEAT		4
507*8226594fSRick McNeal 
508*8226594fSRick McNeal /* ---- manifest constants for the flags field of pqi_sg_descriptor ---- */
509*8226594fSRick McNeal #define	CISS_SG_NORMAL				0x00000000
510*8226594fSRick McNeal #define	CISS_SG_LAST				0x40000000
511*8226594fSRick McNeal #define	CISS_SG_CHAIN				0x80000000
512*8226594fSRick McNeal 
513*8226594fSRick McNeal /*
514*8226594fSRick McNeal  * According to the PQI spec, the IU header is only the first 4 bytes of our
515*8226594fSRick McNeal  * pqi_iu_header structure.
516*8226594fSRick McNeal  */
517*8226594fSRick McNeal #define	PQI_REQUEST_HEADER_LENGTH			4
518*8226594fSRick McNeal #define	PQI_REQUEST_IU_TASK_MANAGEMENT			0x13
519*8226594fSRick McNeal #define	PQI_REQUEST_IU_RAID_PATH_IO			0x14
520*8226594fSRick McNeal #define	PQI_REQUEST_IU_AIO_PATH_IO			0x15
521*8226594fSRick McNeal #define	PQI_REQUEST_IU_GENERAL_ADMIN			0x60
522*8226594fSRick McNeal #define	PQI_REQUEST_IU_REPORT_VENDOR_EVENT_CONFIG	0x72
523*8226594fSRick McNeal #define	PQI_REQUEST_IU_SET_VENDOR_EVENT_CONFIG		0x73
524*8226594fSRick McNeal #define	PQI_REQUEST_IU_ACKNOWLEDGE_VENDOR_EVENT		0xf6
525*8226594fSRick McNeal 
526*8226594fSRick McNeal #define	MASKED_DEVICE(lunid)				((lunid)[3] & 0xc0)
527*8226594fSRick McNeal 
528*8226594fSRick McNeal #define	MEMP(args...) (void) snprintf(m.mem + strlen(m.mem), \
529*8226594fSRick McNeal 	m.len - strlen(m.mem), args)
530*8226594fSRick McNeal 
531*8226594fSRick McNeal typedef struct mem_len_pair {
532*8226594fSRick McNeal 	caddr_t	mem;
533*8226594fSRick McNeal 	int	len;
534*8226594fSRick McNeal } mem_len_pair_t;
535*8226594fSRick McNeal 
536*8226594fSRick McNeal /* ---- Defines for PQI mode ---- */
537*8226594fSRick McNeal #define	IRQ_MODE_NONE			0x00
538*8226594fSRick McNeal #define	VPD_PAGE			(1 << 8)
539*8226594fSRick McNeal 
540*8226594fSRick McNeal /* ---- Defines for use in Legacy mode ---- */
541*8226594fSRick McNeal #define	SIS_CTRL_KERNEL_UP		0x080
542*8226594fSRick McNeal #define	SIS_CTRL_KERNEL_PANIC		0x100
543*8226594fSRick McNeal #define	SIS_MODE			0x0
544*8226594fSRick McNeal #define	PQI_MODE			0x1
545*8226594fSRick McNeal 
546*8226594fSRick McNeal /* ---- smartpqi_main.c ---- */
547*8226594fSRick McNeal extern void *pqi_state;
548*8226594fSRick McNeal extern int pqi_do_scan;
549*8226594fSRick McNeal extern int pqi_do_ctrl;
550*8226594fSRick McNeal 
551*8226594fSRick McNeal /* ---- smartpqi_intr.c ---- */
552*8226594fSRick McNeal int smartpqi_register_intrs(pqi_state_t *);
553*8226594fSRick McNeal void smartpqi_unregister_intrs(pqi_state_t *);
554*8226594fSRick McNeal void pqi_process_io_intr(pqi_state_t *s, pqi_queue_group_t *qg);
555*8226594fSRick McNeal 
556*8226594fSRick McNeal /* ---- smartpqi_sis.c ---- */
557*8226594fSRick McNeal boolean_t sis_reenable_mode(pqi_state_t *s);
558*8226594fSRick McNeal void sis_write_scratch(pqi_state_t *s, int mode);
559*8226594fSRick McNeal uint32_t sis_read_scratch(pqi_state_t *s);
560*8226594fSRick McNeal boolean_t sis_wait_for_ctrl_ready(pqi_state_t *s);
561*8226594fSRick McNeal boolean_t sis_get_ctrl_props(pqi_state_t *s);
562*8226594fSRick McNeal boolean_t sis_init_base_struct_addr(pqi_state_t *s);
563*8226594fSRick McNeal boolean_t sis_get_pqi_capabilities(pqi_state_t *s);
564*8226594fSRick McNeal 
565*8226594fSRick McNeal /* ---- smartpqi_init.c ---- */
566*8226594fSRick McNeal void pqi_free_io_resource(pqi_state_t *s);
567*8226594fSRick McNeal boolean_t pqi_scsi_inquiry(pqi_state_t *s, pqi_device_t *dev, int vpd,
568*8226594fSRick McNeal     struct scsi_inquiry *inq, int len);
569*8226594fSRick McNeal void pqi_rescan_devices(pqi_state_t *s);
570*8226594fSRick McNeal boolean_t pqi_check_firmware(pqi_state_t *s);
571*8226594fSRick McNeal boolean_t pqi_prep_full(pqi_state_t *s);
572*8226594fSRick McNeal boolean_t pqi_reset_ctl(pqi_state_t *s);
573*8226594fSRick McNeal boolean_t pqi_hba_reset(pqi_state_t *s);
574*8226594fSRick McNeal 
575*8226594fSRick McNeal /* ---- smartpqi_hba.c ---- */
576*8226594fSRick McNeal boolean_t smartpqi_register_hba(pqi_state_t *);
577*8226594fSRick McNeal void smartpqi_unregister_hba(pqi_state_t *);
578*8226594fSRick McNeal pqi_device_t *pqi_find_target_ua(pqi_state_t *s, char *);
579*8226594fSRick McNeal int pqi_cache_constructor(void *buf, void *un, int flags);
580*8226594fSRick McNeal void pqi_cache_destructor(void *buf, void *un);
581*8226594fSRick McNeal int pqi_config_all(dev_info_t *pdip, pqi_state_t *s);
582*8226594fSRick McNeal void pqi_quiesced_notify(pqi_state_t *s);
583*8226594fSRick McNeal 
584*8226594fSRick McNeal /* ---- smartpqi_hw.c ---- */
585*8226594fSRick McNeal void pqi_start_io(pqi_state_t *s, pqi_queue_group_t *qg, pqi_path_t path,
586*8226594fSRick McNeal     pqi_io_request_t *io);
587*8226594fSRick McNeal int pqi_transport_command(pqi_state_t *s, pqi_cmd_t *cmd);
588*8226594fSRick McNeal pqi_cmd_action_t pqi_fail_cmd(pqi_cmd_t *cmd, uchar_t reason, uint_t stats);
589*8226594fSRick McNeal void pqi_fail_drive_cmds(pqi_device_t *devp, uchar_t reason);
590*8226594fSRick McNeal void pqi_watchdog(void *v);
591*8226594fSRick McNeal void pqi_do_rescan(void *v);
592*8226594fSRick McNeal void pqi_event_worker(void *v);
593*8226594fSRick McNeal uint32_t pqi_disable_intr(pqi_state_t *s);
594*8226594fSRick McNeal void pqi_enable_intr(pqi_state_t *s, uint32_t old_state);
595*8226594fSRick McNeal void pqi_lun_reset(pqi_state_t *s, pqi_device_t *d);
596*8226594fSRick McNeal 
597*8226594fSRick McNeal /* ---- smartpqi_util.c ---- */
598*8226594fSRick McNeal pqi_dma_overhead_t *pqi_alloc_single(pqi_state_t *s, size_t len);
599*8226594fSRick McNeal void pqi_free_single(pqi_state_t *s, pqi_dma_overhead_t *d);
600*8226594fSRick McNeal pqi_io_request_t *pqi_alloc_io(pqi_state_t *s);
601*8226594fSRick McNeal void pqi_free_io(pqi_io_request_t *io);
602*8226594fSRick McNeal boolean_t pqi_timeout_io(pqi_io_request_t *io);
603*8226594fSRick McNeal boolean_t pqi_service_io(pqi_io_request_t *io, uint8_t generation);
604*8226594fSRick McNeal void pqi_dump_io(pqi_io_request_t *io);
605*8226594fSRick McNeal pqi_cmd_action_t pqi_cmd_action(pqi_cmd_t *cmd, pqi_cmd_action_t a);
606*8226594fSRick McNeal pqi_cmd_action_t pqi_cmd_action_nolock(pqi_cmd_t *cmd, pqi_cmd_action_t a);
607*8226594fSRick McNeal char *pqi_event_to_str(uint8_t event);
608*8226594fSRick McNeal int pqi_map_event(uint8_t event);
609*8226594fSRick McNeal boolean_t pqi_supported_event(uint8_t event_type);
610*8226594fSRick McNeal char *bool_to_str(int v);
611*8226594fSRick McNeal char *dtype_to_str(int t);
612*8226594fSRick McNeal void pqi_free_mem_len(mem_len_pair_t *m);
613*8226594fSRick McNeal mem_len_pair_t pqi_alloc_mem_len(int len);
614*8226594fSRick McNeal mem_len_pair_t build_cdb_str(uint8_t *cdb);
615*8226594fSRick McNeal boolean_t pqi_is_offline(pqi_state_t *s);
616*8226594fSRick McNeal void pqi_show_dev_state(pqi_state_t *s);
617*8226594fSRick McNeal char *cdb_to_str(uint8_t scsi_cmd);
618*8226594fSRick McNeal char *io_status_to_str(int val);
619*8226594fSRick McNeal char *scsi_status_to_str(uint8_t val);
620*8226594fSRick McNeal char *iu_type_to_str(int val);
621*8226594fSRick McNeal 
622*8226594fSRick McNeal #ifdef __cplusplus
623*8226594fSRick McNeal }
624*8226594fSRick McNeal #endif
625*8226594fSRick McNeal 
626*8226594fSRick McNeal #endif /* _SMARTPQI_H */
627