11e091e43SHans Rosenfeld /*
21e091e43SHans Rosenfeld  * This file and its contents are supplied under the terms of the
31e091e43SHans Rosenfeld  * Common Development and Distribution License ("CDDL"), version 1.0.
41e091e43SHans Rosenfeld  * You may only use this file in accordance with the terms of version
51e091e43SHans Rosenfeld  * 1.0 of the CDDL.
61e091e43SHans Rosenfeld  *
71e091e43SHans Rosenfeld  * A full copy of the text of the CDDL should have accompanied this
81e091e43SHans Rosenfeld  * source.  A copy of the CDDL is also available via the Internet at
91e091e43SHans Rosenfeld  * http://www.illumos.org/license/CDDL.
101e091e43SHans Rosenfeld  */
111e091e43SHans Rosenfeld 
121e091e43SHans Rosenfeld /*
13d39213d9SHans Rosenfeld  * Copyright 2024 Racktop Systems, Inc.
141e091e43SHans Rosenfeld  */
151e091e43SHans Rosenfeld #ifndef _LMRC_H
161e091e43SHans Rosenfeld #define	_LMRC_H
171e091e43SHans Rosenfeld 
181e091e43SHans Rosenfeld #include <sys/list.h>
191e091e43SHans Rosenfeld #include <sys/types.h>
201e091e43SHans Rosenfeld 
211e091e43SHans Rosenfeld #include <sys/scsi/scsi.h>
22*98f0a994SHans Rosenfeld #include <sys/scsi/adapters/mfi/mfi_pd.h>
23*98f0a994SHans Rosenfeld 
241e091e43SHans Rosenfeld #include <sys/taskq_impl.h>
251e091e43SHans Rosenfeld 
261e091e43SHans Rosenfeld #if !defined(_LITTLE_ENDIAN) || !defined(_BIT_FIELDS_LTOH)
271e091e43SHans Rosenfeld #error "lmrc only works on little endian systems"
281e091e43SHans Rosenfeld #endif
291e091e43SHans Rosenfeld 
301e091e43SHans Rosenfeld typedef enum lmrc_adapter_class	lmrc_adapter_class_t;
311e091e43SHans Rosenfeld typedef enum lmrc_init_level	lmrc_init_level_t;
321e091e43SHans Rosenfeld typedef struct lmrc_dma		lmrc_dma_t;
331e091e43SHans Rosenfeld typedef struct lmrc_mpt_cmd	lmrc_mpt_cmd_t;
341e091e43SHans Rosenfeld typedef struct lmrc_mfi_cmd	lmrc_mfi_cmd_t;
351e091e43SHans Rosenfeld typedef struct lmrc_scsa_cmd	lmrc_scsa_cmd_t;
361e091e43SHans Rosenfeld typedef struct lmrc_pd		lmrc_pd_t;
371e091e43SHans Rosenfeld typedef struct lmrc_tgt		lmrc_tgt_t;
381e091e43SHans Rosenfeld typedef struct lmrc		lmrc_t;
391e091e43SHans Rosenfeld 
401e091e43SHans Rosenfeld #include "lmrc_reg.h"
411e091e43SHans Rosenfeld #include "lmrc_phys.h"
421e091e43SHans Rosenfeld 
431e091e43SHans Rosenfeld extern void *lmrc_state;
441e091e43SHans Rosenfeld 
451e091e43SHans Rosenfeld enum lmrc_adapter_class {
461e091e43SHans Rosenfeld 	LMRC_ACLASS_OTHER,
471e091e43SHans Rosenfeld 	LMRC_ACLASS_GEN3,
481e091e43SHans Rosenfeld 	LMRC_ACLASS_VENTURA,
491e091e43SHans Rosenfeld 	LMRC_ACLASS_AERO,
501e091e43SHans Rosenfeld };
511e091e43SHans Rosenfeld 
521e091e43SHans Rosenfeld /* iports for RAID and physical targets */
531e091e43SHans Rosenfeld #define	LMRC_IPORT_RAID		"v0"
541e091e43SHans Rosenfeld #define	LMRC_IPORT_PHYS		"p0"
551e091e43SHans Rosenfeld 
561e091e43SHans Rosenfeld /* in seconds */
571e091e43SHans Rosenfeld #define	LMRC_IO_TIMEOUT				10
581e091e43SHans Rosenfeld #define	LMRC_RESET_TIMEOUT			180
591e091e43SHans Rosenfeld #define	LMRC_RESET_WAIT_TIME			3
601e091e43SHans Rosenfeld #define	LMRC_INTERNAL_CMD_WAIT_TIME		180
611e091e43SHans Rosenfeld 
621e091e43SHans Rosenfeld #define	LMRC_MAX_RESET_TRIES			3
631e091e43SHans Rosenfeld 
641e091e43SHans Rosenfeld enum lmrc_init_level {
651e091e43SHans Rosenfeld 	LMRC_INITLEVEL_BASIC =		(1 << 0),
661e091e43SHans Rosenfeld 	LMRC_INITLEVEL_THREAD =		(1 << 1),
671e091e43SHans Rosenfeld 	LMRC_INITLEVEL_FM =		(1 << 2),
681e091e43SHans Rosenfeld 	LMRC_INITLEVEL_REGS =		(1 << 3),
691e091e43SHans Rosenfeld 	LMRC_INITLEVEL_INTR =		(1 << 4),
701e091e43SHans Rosenfeld 	LMRC_INITLEVEL_SYNC =		(1 << 5),
711e091e43SHans Rosenfeld 	LMRC_INITLEVEL_HBA =		(1 << 6),
721e091e43SHans Rosenfeld 	LMRC_INITLEVEL_NODE =		(1 << 7),
731e091e43SHans Rosenfeld 	LMRC_INITLEVEL_TASKQ =		(1 << 8),
741e091e43SHans Rosenfeld 	LMRC_INITLEVEL_AEN =		(1 << 9),
751e091e43SHans Rosenfeld 	LMRC_INITLEVEL_MFICMDS =	(1 << 10),
761e091e43SHans Rosenfeld 	LMRC_INITLEVEL_MPTCMDS =	(1 << 11),
771e091e43SHans Rosenfeld 	LMRC_INITLEVEL_FW =		(1 << 12),
78d39213d9SHans Rosenfeld 	LMRC_INITLEVEL_RAID =		(1 << 13),
79d39213d9SHans Rosenfeld 	LMRC_INITLEVEL_PHYS =		(1 << 14),
801e091e43SHans Rosenfeld };
811e091e43SHans Rosenfeld 
821e091e43SHans Rosenfeld #define	INITLEVEL_SET(_lmrc, name)				\
831e091e43SHans Rosenfeld 	do {							\
841e091e43SHans Rosenfeld 		VERIFY(!((_lmrc)->l_init_level & (name)));	\
851e091e43SHans Rosenfeld 		(_lmrc)->l_init_level |= (name);		\
861e091e43SHans Rosenfeld 	} while (0)
871e091e43SHans Rosenfeld 
881e091e43SHans Rosenfeld #define	INITLEVEL_CLEAR(_lmrc, name)				\
891e091e43SHans Rosenfeld 	do {							\
901e091e43SHans Rosenfeld 		VERIFY((_lmrc)->l_init_level & (name));	\
911e091e43SHans Rosenfeld 		(_lmrc)->l_init_level &= ~(name);		\
921e091e43SHans Rosenfeld 	} while (0)
931e091e43SHans Rosenfeld 
941e091e43SHans Rosenfeld #define	INITLEVEL_ACTIVE(_lmrc, name)				\
951e091e43SHans Rosenfeld 	(((_lmrc)->l_init_level & (name)) != 0)
961e091e43SHans Rosenfeld 
971e091e43SHans Rosenfeld struct lmrc_dma {
981e091e43SHans Rosenfeld 	ddi_dma_handle_t	ld_hdl;
991e091e43SHans Rosenfeld 	ddi_acc_handle_t	ld_acc;
1001e091e43SHans Rosenfeld 	void			*ld_buf;
1011e091e43SHans Rosenfeld 	size_t			ld_len;
1021e091e43SHans Rosenfeld };
1031e091e43SHans Rosenfeld 
1041e091e43SHans Rosenfeld typedef	void (lmrc_mpt_cmd_cb_t)(lmrc_t *, lmrc_mpt_cmd_t *);
1051e091e43SHans Rosenfeld 
1061e091e43SHans Rosenfeld struct lmrc_mpt_cmd {
1071e091e43SHans Rosenfeld 	list_node_t		mpt_node;
1081e091e43SHans Rosenfeld 	lmrc_dma_t		mpt_chain_dma;
1091e091e43SHans Rosenfeld 	lmrc_dma_t		mpt_sense_dma;
1101e091e43SHans Rosenfeld 	uint16_t		mpt_smid;
1111e091e43SHans Rosenfeld 	uint16_t		mpt_queue;
1121e091e43SHans Rosenfeld 
1131e091e43SHans Rosenfeld 	lmrc_mfi_cmd_t		*mpt_mfi;
1141e091e43SHans Rosenfeld 	struct scsi_pkt		*mpt_pkt;
1151e091e43SHans Rosenfeld 
1161e091e43SHans Rosenfeld 	void			*mpt_io_frame;
1171e091e43SHans Rosenfeld 	Mpi25IeeeSgeChain64_t	*mpt_chain;
1181e091e43SHans Rosenfeld 	uint8_t			*mpt_sense;
1191e091e43SHans Rosenfeld 
1201e091e43SHans Rosenfeld 	kmutex_t		mpt_lock;
1211e091e43SHans Rosenfeld 	kcondvar_t		mpt_cv;
1221e091e43SHans Rosenfeld 	boolean_t		mpt_complete;
1231e091e43SHans Rosenfeld 	hrtime_t		mpt_timeout;
1241e091e43SHans Rosenfeld 
1251e091e43SHans Rosenfeld 	taskq_ent_t		mpt_tqent;
1261e091e43SHans Rosenfeld 
1271e091e43SHans Rosenfeld 	lmrc_t			*mpt_lmrc;
1281e091e43SHans Rosenfeld };
1291e091e43SHans Rosenfeld 
1301e091e43SHans Rosenfeld typedef	void (lmrc_mfi_cmd_cb_t)(lmrc_t *, lmrc_mfi_cmd_t *);
1311e091e43SHans Rosenfeld 
1321e091e43SHans Rosenfeld struct lmrc_mfi_cmd {
1331e091e43SHans Rosenfeld 	list_node_t		mfi_node;
1341e091e43SHans Rosenfeld 	lmrc_dma_t		mfi_frame_dma;
1351e091e43SHans Rosenfeld 
136*98f0a994SHans Rosenfeld 	mfi_frame_t		*mfi_frame;
1371e091e43SHans Rosenfeld 	uint32_t		mfi_idx;
1381e091e43SHans Rosenfeld 	uint16_t		mfi_smid;
1391e091e43SHans Rosenfeld 
1401e091e43SHans Rosenfeld 	kmutex_t		mfi_lock;
1411e091e43SHans Rosenfeld 	kcondvar_t		mfi_cv;
1421e091e43SHans Rosenfeld 	lmrc_dma_t		mfi_data_dma;
1431e091e43SHans Rosenfeld 
1441e091e43SHans Rosenfeld 	lmrc_mfi_cmd_cb_t	*mfi_callback;
1451e091e43SHans Rosenfeld 	taskq_ent_t		mfi_tqent;
1461e091e43SHans Rosenfeld 	lmrc_mpt_cmd_t		*mfi_mpt;
1471e091e43SHans Rosenfeld 
1481e091e43SHans Rosenfeld 	lmrc_t			*mfi_lmrc;
1491e091e43SHans Rosenfeld };
1501e091e43SHans Rosenfeld 
1511e091e43SHans Rosenfeld struct lmrc_scsa_cmd {
1521e091e43SHans Rosenfeld 	lmrc_mpt_cmd_t		*sc_mpt;
1531e091e43SHans Rosenfeld 	lmrc_tgt_t		*sc_tgt;
1541e091e43SHans Rosenfeld };
1551e091e43SHans Rosenfeld 
1561e091e43SHans Rosenfeld struct lmrc_tgt {
1571e091e43SHans Rosenfeld 	krwlock_t		tgt_lock;
1581e091e43SHans Rosenfeld 	kmutex_t		tgt_mpt_active_lock;
1591e091e43SHans Rosenfeld 	list_t			tgt_mpt_active;
1601e091e43SHans Rosenfeld 	lmrc_t			*tgt_lmrc;
1611e091e43SHans Rosenfeld 	uint16_t		tgt_dev_id;
1621e091e43SHans Rosenfeld 	uint8_t			tgt_type;
1631e091e43SHans Rosenfeld 	uint8_t			tgt_interconnect_type;
1641e091e43SHans Rosenfeld 	uint64_t		tgt_wwn;
165*98f0a994SHans Rosenfeld 	mfi_pd_info_t		*tgt_pd_info;
1661e091e43SHans Rosenfeld 	char			tgt_wwnstr[SCSI_WWN_BUFLEN];
1671e091e43SHans Rosenfeld };
1681e091e43SHans Rosenfeld 
1691e091e43SHans Rosenfeld struct lmrc {
1701e091e43SHans Rosenfeld 	dev_info_t		*l_dip;
1711e091e43SHans Rosenfeld 	dev_info_t		*l_raid_dip;
1721e091e43SHans Rosenfeld 	dev_info_t		*l_phys_dip;
1731e091e43SHans Rosenfeld 
1741e091e43SHans Rosenfeld 	char			l_iocname[16];
1751e091e43SHans Rosenfeld 
1761e091e43SHans Rosenfeld 	lmrc_init_level_t	l_init_level;
1771e091e43SHans Rosenfeld 	lmrc_adapter_class_t	l_class;
1781e091e43SHans Rosenfeld 
1791e091e43SHans Rosenfeld 	kmutex_t		l_mpt_cmd_lock;
1801e091e43SHans Rosenfeld 	list_t			l_mpt_cmd_list;
1811e091e43SHans Rosenfeld 	lmrc_mpt_cmd_t		**l_mpt_cmds;
1821e091e43SHans Rosenfeld 
1831e091e43SHans Rosenfeld 	kmutex_t		l_mfi_cmd_lock;
1841e091e43SHans Rosenfeld 	list_t			l_mfi_cmd_list;
1851e091e43SHans Rosenfeld 	lmrc_mfi_cmd_t		**l_mfi_cmds;
1861e091e43SHans Rosenfeld 
1871e091e43SHans Rosenfeld 	lmrc_dma_t		l_ioreq_dma;
1881e091e43SHans Rosenfeld 	lmrc_dma_t		l_reply_dma;
1891e091e43SHans Rosenfeld 
1901e091e43SHans Rosenfeld 	ksema_t			l_ioctl_sema;
1911e091e43SHans Rosenfeld 
1921e091e43SHans Rosenfeld 	kthread_t		*l_thread;
1931e091e43SHans Rosenfeld 	kmutex_t		l_thread_lock;
1941e091e43SHans Rosenfeld 	kcondvar_t		l_thread_cv;
1951e091e43SHans Rosenfeld 	boolean_t		l_thread_stop;
1961e091e43SHans Rosenfeld 
197*98f0a994SHans Rosenfeld 	mfi_ctrl_info_t		*l_ctrl_info;
1981e091e43SHans Rosenfeld 
1991e091e43SHans Rosenfeld 	ddi_intr_handle_t	*l_intr_htable;
2001e091e43SHans Rosenfeld 	size_t			l_intr_htable_size;
2011e091e43SHans Rosenfeld 	int			l_intr_types;
2021e091e43SHans Rosenfeld 	int			l_intr_type;
2031e091e43SHans Rosenfeld 	int			l_intr_count;
2041e091e43SHans Rosenfeld 	uint_t			l_intr_pri;
2051e091e43SHans Rosenfeld 	int			l_intr_cap;
2061e091e43SHans Rosenfeld 
2071e091e43SHans Rosenfeld 	uint16_t		*l_last_reply_idx;
2081e091e43SHans Rosenfeld 	uint32_t		l_rphi[LMRC_MAX_REPLY_POST_HOST_INDEX];
2091e091e43SHans Rosenfeld 
2101e091e43SHans Rosenfeld 	int			l_fm_capabilities;
2111e091e43SHans Rosenfeld 
2121e091e43SHans Rosenfeld 	/* Controller HW/FW properties */
2131e091e43SHans Rosenfeld 	boolean_t		l_disable_online_ctrl_reset;
2141e091e43SHans Rosenfeld 	boolean_t		l_fw_fault;
2151e091e43SHans Rosenfeld 	boolean_t		l_fw_msix_enabled;
2161e091e43SHans Rosenfeld 	boolean_t		l_fw_sync_cache_support;
2171e091e43SHans Rosenfeld 	size_t			l_fw_supported_vd_count;
2181e091e43SHans Rosenfeld 	size_t			l_fw_supported_pd_count;
2191e091e43SHans Rosenfeld 
2201e091e43SHans Rosenfeld 	boolean_t		l_msix_combined;
2211e091e43SHans Rosenfeld 	boolean_t		l_atomic_desc_support;
2221e091e43SHans Rosenfeld 	boolean_t		l_64bit_dma_support;
2231e091e43SHans Rosenfeld 	boolean_t		l_max_256_vd_support;
2241e091e43SHans Rosenfeld 	boolean_t		l_use_seqnum_jbod_fp;
2251e091e43SHans Rosenfeld 	boolean_t		l_pdmap_tgtid_support;
2261e091e43SHans Rosenfeld 
2271e091e43SHans Rosenfeld 	size_t			l_max_reply_queues;
2281e091e43SHans Rosenfeld 	size_t			l_max_num_sge;
2291e091e43SHans Rosenfeld 	size_t			l_max_sge_in_main_msg;
2301e091e43SHans Rosenfeld 	size_t			l_max_sge_in_chain;
2311e091e43SHans Rosenfeld 
2321e091e43SHans Rosenfeld 	uint32_t		l_fw_outstanding_cmds;
2331e091e43SHans Rosenfeld 	uint32_t		l_max_fw_cmds;
2341e091e43SHans Rosenfeld 	uint32_t		l_max_scsi_cmds;
2351e091e43SHans Rosenfeld 	size_t			l_reply_q_depth;
2361e091e43SHans Rosenfeld 
2371e091e43SHans Rosenfeld 	size_t			l_reply_alloc_sz;
2381e091e43SHans Rosenfeld 	size_t			l_io_frames_alloc_sz;
2391e091e43SHans Rosenfeld 	size_t			l_max_chain_frame_sz;
2401e091e43SHans Rosenfeld 	size_t			l_chain_offset_mfi_pthru;
2411e091e43SHans Rosenfeld 	size_t			l_chain_offset_io_request;
2421e091e43SHans Rosenfeld 
2431e091e43SHans Rosenfeld 	size_t			l_max_raid_map_sz;
2441e091e43SHans Rosenfeld 	size_t			l_max_map_sz;
2451e091e43SHans Rosenfeld 	size_t			l_current_map_sz;
2461e091e43SHans Rosenfeld 
2471e091e43SHans Rosenfeld 	size_t			l_nvme_page_sz;
2481e091e43SHans Rosenfeld 
2491e091e43SHans Rosenfeld 	scsi_hba_tran_t		*l_hba_tran;
2501e091e43SHans Rosenfeld 	dev_info_t		*l_iport;
2511e091e43SHans Rosenfeld 	taskq_t			*l_taskq;
2521e091e43SHans Rosenfeld 
2531e091e43SHans Rosenfeld 	ddi_dma_attr_t		l_dma_attr;
2541e091e43SHans Rosenfeld 	ddi_dma_attr_t		l_dma_attr_32;
2551e091e43SHans Rosenfeld 	ddi_device_acc_attr_t	l_acc_attr;
2561e091e43SHans Rosenfeld 	caddr_t			l_regmap;
2571e091e43SHans Rosenfeld 	ddi_acc_handle_t	l_reghandle;
2581e091e43SHans Rosenfeld 	kmutex_t		l_reg_lock;
2591e091e43SHans Rosenfeld 
2601e091e43SHans Rosenfeld 	krwlock_t		l_raidmap_lock;
2611e091e43SHans Rosenfeld 	lmrc_fw_raid_map_t	*l_raidmap;
2621e091e43SHans Rosenfeld 
2631e091e43SHans Rosenfeld 	krwlock_t		l_pdmap_lock;
264*98f0a994SHans Rosenfeld 	mfi_pd_map_t		*l_pdmap;
2651e091e43SHans Rosenfeld 
2661e091e43SHans Rosenfeld 	lmrc_tgt_t		l_targets[LMRC_MAX_LD + LMRC_MAX_PD];
2671e091e43SHans Rosenfeld 
2681e091e43SHans Rosenfeld 	scsi_hba_tgtmap_t	*l_raid_tgtmap;
2691e091e43SHans Rosenfeld 	scsi_hba_tgtmap_t	*l_phys_tgtmap;
2701e091e43SHans Rosenfeld 
2711e091e43SHans Rosenfeld };
2721e091e43SHans Rosenfeld 
2731e091e43SHans Rosenfeld int lmrc_check_acc_handle(ddi_acc_handle_t);
2741e091e43SHans Rosenfeld int lmrc_check_dma_handle(ddi_dma_handle_t);
2751e091e43SHans Rosenfeld 
2761e091e43SHans Rosenfeld void lmrc_dma_build_sgl(lmrc_t *, lmrc_mpt_cmd_t *, const ddi_dma_cookie_t *,
2771e091e43SHans Rosenfeld     uint_t);
2781e091e43SHans Rosenfeld size_t lmrc_dma_get_size(lmrc_dma_t *);
2791e091e43SHans Rosenfeld void lmrc_dma_set_addr64(lmrc_dma_t *, uint64_t *);
2801e091e43SHans Rosenfeld void lmrc_dma_set_addr32(lmrc_dma_t *, uint32_t *);
2811e091e43SHans Rosenfeld int lmrc_dma_alloc(lmrc_t *, ddi_dma_attr_t, lmrc_dma_t *, size_t, uint64_t,
2821e091e43SHans Rosenfeld     uint_t);
2831e091e43SHans Rosenfeld void lmrc_dma_free(lmrc_dma_t *);
2841e091e43SHans Rosenfeld 
2851e091e43SHans Rosenfeld void lmrc_disable_intr(lmrc_t *);
2861e091e43SHans Rosenfeld void lmrc_enable_intr(lmrc_t *);
2871e091e43SHans Rosenfeld uint_t lmrc_intr_ack(lmrc_t *);
2881e091e43SHans Rosenfeld 
2891e091e43SHans Rosenfeld void lmrc_send_atomic_request(lmrc_t *, lmrc_atomic_req_desc_t);
2901e091e43SHans Rosenfeld void lmrc_send_request(lmrc_t *, lmrc_req_desc_t);
2911e091e43SHans Rosenfeld lmrc_atomic_req_desc_t lmrc_build_atomic_request(lmrc_t *, lmrc_mpt_cmd_t *,
2921e091e43SHans Rosenfeld     uint8_t);
2931e091e43SHans Rosenfeld 
2941e091e43SHans Rosenfeld void lmrc_fm_ereport(lmrc_t *, const char *);
2951e091e43SHans Rosenfeld 
2961e091e43SHans Rosenfeld int lmrc_hba_attach(lmrc_t *);
2971e091e43SHans Rosenfeld void lmrc_hba_detach(lmrc_t *);
2981e091e43SHans Rosenfeld 
2991e091e43SHans Rosenfeld void lmrc_thread(void *);
3001e091e43SHans Rosenfeld int lmrc_adapter_init(lmrc_t *);
3011e091e43SHans Rosenfeld int lmrc_ioc_init(lmrc_t *);
3021e091e43SHans Rosenfeld int lmrc_fw_init(lmrc_t *);
3031e091e43SHans Rosenfeld 
304*98f0a994SHans Rosenfeld void lmrc_tgt_init(lmrc_tgt_t *, uint16_t, char *, mfi_pd_info_t *);
3051e091e43SHans Rosenfeld void lmrc_tgt_clear(lmrc_tgt_t *);
3061e091e43SHans Rosenfeld lmrc_tgt_t *lmrc_tgt_find(lmrc_t *, struct scsi_device *);
3071e091e43SHans Rosenfeld 
3081e091e43SHans Rosenfeld void lmrc_wakeup_mfi(lmrc_t *, lmrc_mfi_cmd_t *);
3091e091e43SHans Rosenfeld void lmrc_issue_mfi(lmrc_t *, lmrc_mfi_cmd_t *, lmrc_mfi_cmd_cb_t *);
3101e091e43SHans Rosenfeld int lmrc_wait_mfi(lmrc_t *, lmrc_mfi_cmd_t *, uint8_t);
3111e091e43SHans Rosenfeld int lmrc_issue_blocked_mfi(lmrc_t *, lmrc_mfi_cmd_t *);
3121e091e43SHans Rosenfeld 
3131e091e43SHans Rosenfeld int lmrc_poll_for_reply(lmrc_t *, lmrc_mpt_cmd_t *);
3141e091e43SHans Rosenfeld int lmrc_process_replies(lmrc_t *, uint8_t);
3151e091e43SHans Rosenfeld 
3161e091e43SHans Rosenfeld int lmrc_abort_mpt(lmrc_t *, lmrc_tgt_t *, lmrc_mpt_cmd_t *);
3171e091e43SHans Rosenfeld lmrc_mpt_cmd_t *lmrc_get_mpt(lmrc_t *);
3181e091e43SHans Rosenfeld void lmrc_put_mpt(lmrc_mpt_cmd_t *);
3191e091e43SHans Rosenfeld 
3201e091e43SHans Rosenfeld lmrc_mfi_cmd_t *lmrc_get_dcmd(lmrc_t *, uint16_t, uint32_t, uint32_t, uint_t);
3211e091e43SHans Rosenfeld void lmrc_put_dcmd(lmrc_t *, lmrc_mfi_cmd_t *);
3221e091e43SHans Rosenfeld 
3231e091e43SHans Rosenfeld lmrc_mfi_cmd_t *lmrc_get_mfi(lmrc_t *);
3241e091e43SHans Rosenfeld void lmrc_put_mfi(lmrc_mfi_cmd_t *);
3251e091e43SHans Rosenfeld int lmrc_abort_outstanding_mfi(lmrc_t *, const size_t);
326d8b83e34SHans Rosenfeld int lmrc_build_mptmfi_passthru(lmrc_t *, lmrc_mfi_cmd_t *);
3271e091e43SHans Rosenfeld 
3281e091e43SHans Rosenfeld int lmrc_start_aen(lmrc_t *);
3291e091e43SHans Rosenfeld 
3301e091e43SHans Rosenfeld int lmrc_ctrl_shutdown(lmrc_t *);
3311e091e43SHans Rosenfeld 
3321e091e43SHans Rosenfeld /*
3331e091e43SHans Rosenfeld  * per-target active MPT command list functions
3341e091e43SHans Rosenfeld  */
3351e091e43SHans Rosenfeld 
3361e091e43SHans Rosenfeld /*
3371e091e43SHans Rosenfeld  * lmrc_tgt_first_active_mpt
3381e091e43SHans Rosenfeld  *
3391e091e43SHans Rosenfeld  * Returns the first active MPT command of a target. The MPT command is returned
3401e091e43SHans Rosenfeld  * locked.
3411e091e43SHans Rosenfeld  */
3421e091e43SHans Rosenfeld static inline lmrc_mpt_cmd_t *
lmrc_tgt_first_active_mpt(lmrc_tgt_t * tgt)3431e091e43SHans Rosenfeld lmrc_tgt_first_active_mpt(lmrc_tgt_t *tgt)
3441e091e43SHans Rosenfeld {
3451e091e43SHans Rosenfeld 	lmrc_mpt_cmd_t *mpt = list_head(&tgt->tgt_mpt_active);
3461e091e43SHans Rosenfeld 
3471e091e43SHans Rosenfeld 	ASSERT(mutex_owned(&tgt->tgt_mpt_active_lock));
3481e091e43SHans Rosenfeld 
3491e091e43SHans Rosenfeld 	if (mpt != NULL)
3501e091e43SHans Rosenfeld 		mutex_enter(&mpt->mpt_lock);
3511e091e43SHans Rosenfeld 
3521e091e43SHans Rosenfeld 	return (mpt);
3531e091e43SHans Rosenfeld }
3541e091e43SHans Rosenfeld 
3551e091e43SHans Rosenfeld /*
3561e091e43SHans Rosenfeld  * lmrc_tgt_next_active_mpt
3571e091e43SHans Rosenfeld  *
3581e091e43SHans Rosenfeld  * Given a MPT command on the active list of a target, returns the next active
3591e091e43SHans Rosenfeld  * MPT command on that target. The given MPT command is unlocked, and the next
3601e091e43SHans Rosenfeld  * command is returned locked.
3611e091e43SHans Rosenfeld  */
3621e091e43SHans Rosenfeld static inline lmrc_mpt_cmd_t *
lmrc_tgt_next_active_mpt(lmrc_tgt_t * tgt,lmrc_mpt_cmd_t * mpt)3631e091e43SHans Rosenfeld lmrc_tgt_next_active_mpt(lmrc_tgt_t *tgt, lmrc_mpt_cmd_t *mpt)
3641e091e43SHans Rosenfeld {
3651e091e43SHans Rosenfeld 	lmrc_mpt_cmd_t *nextmpt;
3661e091e43SHans Rosenfeld 
3671e091e43SHans Rosenfeld 	ASSERT(mutex_owned(&tgt->tgt_mpt_active_lock));
3681e091e43SHans Rosenfeld 
3691e091e43SHans Rosenfeld 	nextmpt = list_next(&tgt->tgt_mpt_active, mpt);
3701e091e43SHans Rosenfeld 	mutex_exit(&mpt->mpt_lock);
3711e091e43SHans Rosenfeld 
3721e091e43SHans Rosenfeld 	if (nextmpt != NULL)
3731e091e43SHans Rosenfeld 		mutex_enter(&nextmpt->mpt_lock);
3741e091e43SHans Rosenfeld 
3751e091e43SHans Rosenfeld 	return (nextmpt);
3761e091e43SHans Rosenfeld }
3771e091e43SHans Rosenfeld 
3781e091e43SHans Rosenfeld /*
3791e091e43SHans Rosenfeld  * lmrc_tgt_add_active_mpt
3801e091e43SHans Rosenfeld  *
3811e091e43SHans Rosenfeld  * Adds a MPT command to the active command list of a target. The command
3821e091e43SHans Rosenfeld  * mutex must be held. There's no risk for a deadlock against the iterator
3831e091e43SHans Rosenfeld  * functions.
3841e091e43SHans Rosenfeld  */
3851e091e43SHans Rosenfeld static inline void
lmrc_tgt_add_active_mpt(lmrc_tgt_t * tgt,lmrc_mpt_cmd_t * mpt)3861e091e43SHans Rosenfeld lmrc_tgt_add_active_mpt(lmrc_tgt_t *tgt, lmrc_mpt_cmd_t *mpt)
3871e091e43SHans Rosenfeld {
3881e091e43SHans Rosenfeld 	ASSERT(mutex_owned(&mpt->mpt_lock));
3891e091e43SHans Rosenfeld 
3901e091e43SHans Rosenfeld 	mutex_enter(&tgt->tgt_mpt_active_lock);
3911e091e43SHans Rosenfeld 	list_insert_head(&tgt->tgt_mpt_active, mpt);
3921e091e43SHans Rosenfeld 	mutex_exit(&tgt->tgt_mpt_active_lock);
3931e091e43SHans Rosenfeld }
3941e091e43SHans Rosenfeld 
3951e091e43SHans Rosenfeld /*
3961e091e43SHans Rosenfeld  * lmrc_tgt_rem_active_mpt
3971e091e43SHans Rosenfeld  *
3981e091e43SHans Rosenfeld  * Removes a MPT command from the active command list of a target. The command
3991e091e43SHans Rosenfeld  * must not be locked to avoid a deadlock with against the iterator functions.
4001e091e43SHans Rosenfeld  */
4011e091e43SHans Rosenfeld static inline void
lmrc_tgt_rem_active_mpt(lmrc_tgt_t * tgt,lmrc_mpt_cmd_t * mpt)4021e091e43SHans Rosenfeld lmrc_tgt_rem_active_mpt(lmrc_tgt_t *tgt, lmrc_mpt_cmd_t *mpt)
4031e091e43SHans Rosenfeld {
4041e091e43SHans Rosenfeld 	ASSERT(!mutex_owned(&mpt->mpt_lock));
4051e091e43SHans Rosenfeld 
4061e091e43SHans Rosenfeld 	mutex_enter(&tgt->tgt_mpt_active_lock);
4071e091e43SHans Rosenfeld 	list_remove(&tgt->tgt_mpt_active, mpt);
4081e091e43SHans Rosenfeld 	mutex_exit(&tgt->tgt_mpt_active_lock);
4091e091e43SHans Rosenfeld }
4101e091e43SHans Rosenfeld 
4111e091e43SHans Rosenfeld /*
4121e091e43SHans Rosenfeld  * Number of replies to be processed before the Reply Post Host register
4131e091e43SHans Rosenfeld  * is updated.
4141e091e43SHans Rosenfeld  */
4151e091e43SHans Rosenfeld #define	LMRC_THRESHOLD_REPLY_COUNT		50
4161e091e43SHans Rosenfeld 
4171e091e43SHans Rosenfeld #endif /* _LMRC_H */
418