| 1 | /*- |
| 2 | * SPDX-License-Identifier: BSD-2-Clause |
| 3 | * |
| 4 | * Copyright (c) 2006 IronPort Systems |
| 5 | * All rights reserved. |
| 6 | * |
| 7 | * Redistribution and use in source and binary forms, with or without |
| 8 | * modification, are permitted provided that the following conditions |
| 9 | * are met: |
| 10 | * 1. Redistributions of source code must retain the above copyright |
| 11 | * notice, this list of conditions and the following disclaimer. |
| 12 | * 2. Redistributions in binary form must reproduce the above copyright |
| 13 | * notice, this list of conditions and the following disclaimer in the |
| 14 | * documentation and/or other materials provided with the distribution. |
| 15 | * |
| 16 | * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND |
| 17 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |
| 18 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE |
| 19 | * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE |
| 20 | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL |
| 21 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS |
| 22 | * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) |
| 23 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT |
| 24 | * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY |
| 25 | * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF |
| 26 | * SUCH DAMAGE. |
| 27 | */ |
| 28 | /*- |
| 29 | * Copyright (c) 2007 LSI Corp. |
| 30 | * Copyright (c) 2007 Rajesh Prabhakaran. |
| 31 | * All rights reserved. |
| 32 | * |
| 33 | * Redistribution and use in source and binary forms, with or without |
| 34 | * modification, are permitted provided that the following conditions |
| 35 | * are met: |
| 36 | * 1. Redistributions of source code must retain the above copyright |
| 37 | * notice, this list of conditions and the following disclaimer. |
| 38 | * 2. Redistributions in binary form must reproduce the above copyright |
| 39 | * notice, this list of conditions and the following disclaimer in the |
| 40 | * documentation and/or other materials provided with the distribution. |
| 41 | * |
| 42 | * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND |
| 43 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |
| 44 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE |
| 45 | * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE |
| 46 | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL |
| 47 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS |
| 48 | * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) |
| 49 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT |
| 50 | * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY |
| 51 | * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF |
| 52 | * SUCH DAMAGE. |
| 53 | */ |
| 54 | |
| 55 | #ifndef _MFIVAR_H |
| 56 | #define _MFIVAR_H |
| 57 | |
| 58 | #include <sys/cdefs.h> |
| 59 | #include <sys/lock.h> |
| 60 | #include <sys/sx.h> |
| 61 | |
| 62 | #include <sys/types.h> |
| 63 | #include <sys/taskqueue.h> |
| 64 | #include "opt_mfi.h" |
| 65 | |
| 66 | /* |
| 67 | * SCSI structures and definitions are used from here, but no linking |
| 68 | * requirements are made to CAM. |
| 69 | */ |
| 70 | #include <cam/scsi/scsi_all.h> |
| 71 | |
| 72 | struct mfi_hwcomms { |
| 73 | 	uint32_t		hw_pi; |
| 74 | 	uint32_t		hw_ci; |
| 75 | 	uint32_t		hw_reply_q[1]; |
| 76 | }; |
| 77 | #define	MEGASAS_MAX_NAME	32 |
| 78 | #define	MEGASAS_VERSION		"4.23" |
| 79 | |
| 80 | struct mfi_softc; |
| 81 | struct disk; |
| 82 | struct ccb_hdr; |
| 83 | |
| 84 | struct mfi_command { |
| 85 | 	TAILQ_ENTRY(mfi_command) cm_link; |
| 86 | 	time_t			cm_timestamp; |
| 87 | 	struct mfi_softc	*cm_sc; |
| 88 | 	union mfi_frame		*cm_frame; |
| 89 | 	bus_addr_t		cm_frame_busaddr; |
| 90 | 	struct mfi_sense	*cm_sense; |
| 91 | 	bus_addr_t		cm_sense_busaddr; |
| 92 | 	bus_dmamap_t		cm_dmamap; |
| 93 | 	union mfi_sgl		*cm_sg; |
| 94 | 	void			*cm_data; |
| 95 | 	int			cm_len; |
| 96 | 	int			cm_stp_len; |
| 97 | 	int			cm_total_frame_size; |
| 98 | 	int			cm_extra_frames; |
| 99 | 	int			cm_flags; |
| 100 | #define MFI_CMD_MAPPED		(1<<0) |
| 101 | #define MFI_CMD_DATAIN		(1<<1) |
| 102 | #define MFI_CMD_DATAOUT		(1<<2) |
| 103 | #define MFI_CMD_COMPLETED	(1<<3) |
| 104 | #define MFI_CMD_POLLED		(1<<4) |
| 105 | #define MFI_CMD_SCSI		(1<<5) |
| 106 | #define MFI_CMD_CCB		(1<<6) |
| 107 | #define	MFI_CMD_BIO		(1<<7) |
| 108 | #define MFI_CMD_TBOLT		(1<<8) |
| 109 | #define MFI_ON_MFIQ_FREE	(1<<9) |
| 110 | #define MFI_ON_MFIQ_READY	(1<<10) |
| 111 | #define MFI_ON_MFIQ_BUSY	(1<<11) |
| 112 | #define MFI_ON_MFIQ_MASK	(MFI_ON_MFIQ_FREE | MFI_ON_MFIQ_READY| \ |
| 113 | MFI_ON_MFIQ_BUSY) |
| 114 | #define MFI_CMD_FLAGS_FMT	"\20" \ |
| 115 | "\1MAPPED" \ |
| 116 | "\2DATAIN" \ |
| 117 | "\3DATAOUT" \ |
| 118 | "\4COMPLETED" \ |
| 119 | "\5POLLED" \ |
| 120 | "\6SCSI" \ |
| 121 | "\7BIO" \ |
| 122 | "\10TBOLT" \ |
| 123 | "\11Q_FREE" \ |
| 124 | "\12Q_READY" \ |
| 125 | "\13Q_BUSY" |
| 126 | 	uint8_t			retry_for_fw_reset; |
| 127 | 	void			(* cm_complete)(struct mfi_command *cm); |
| 128 | 	void			*cm_private; |
| 129 | 	int			cm_index; |
| 130 | 	int			cm_error; |
| 131 | }; |
| 132 | |
| 133 | struct mfi_disk { |
| 134 | 	TAILQ_ENTRY(mfi_disk)	ld_link; |
| 135 | 	device_t	ld_dev; |
| 136 | 	int		ld_id; |
| 137 | 	int		ld_unit; |
| 138 | 	struct mfi_softc *ld_controller; |
| 139 | 	struct mfi_ld_info	*ld_info; |
| 140 | 	struct disk	*ld_disk; |
| 141 | 	int		ld_flags; |
| 142 | #define MFI_DISK_FLAGS_OPEN	0x01 |
| 143 | #define	MFI_DISK_FLAGS_DISABLED	0x02 |
| 144 | }; |
| 145 | |
| 146 | struct mfi_disk_pending { |
| 147 | 	TAILQ_ENTRY(mfi_disk_pending)	ld_link; |
| 148 | 	int		ld_id; |
| 149 | }; |
| 150 | |
| 151 | struct mfi_system_pd { |
| 152 | 	TAILQ_ENTRY(mfi_system_pd) pd_link; |
| 153 | 	device_t	pd_dev; |
| 154 | 	int		pd_id; |
| 155 | 	int		pd_unit; |
| 156 | 	struct mfi_softc *pd_controller; |
| 157 | 	struct mfi_pd_info *pd_info; |
| 158 | 	struct disk	*pd_disk; |
| 159 | 	int		pd_flags; |
| 160 | }; |
| 161 | |
| 162 | struct mfi_system_pending { |
| 163 | 	TAILQ_ENTRY(mfi_system_pending) pd_link; |
| 164 | 	int		pd_id; |
| 165 | }; |
| 166 | |
| 167 | struct mfi_evt_queue_elm { |
| 168 | 	TAILQ_ENTRY(mfi_evt_queue_elm)	link; |
| 169 | 	struct mfi_evt_detail		detail; |
| 170 | }; |
| 171 | |
| 172 | struct mfi_aen { |
| 173 | 	TAILQ_ENTRY(mfi_aen) aen_link; |
| 174 | 	struct proc			*p; |
| 175 | }; |
| 176 | |
| 177 | struct mfi_skinny_dma_info { |
| 178 | 	bus_dma_tag_t			dmat[514]; |
| 179 | 	bus_dmamap_t			dmamap[514]; |
| 180 | 	uint32_t			mem[514]; |
| 181 | 	int				noofmaps; |
| 182 | }; |
| 183 | |
| 184 | struct megasas_sge |
| 185 | { |
| 186 | 	bus_addr_t			phys_addr; |
| 187 | 	uint32_t			length; |
| 188 | }; |
| 189 | |
| 190 | struct mfi_cmd_tbolt; |
| 191 | |
| 192 | struct mfi_softc { |
| 193 | 	device_t			mfi_dev; |
| 194 | 	int				mfi_flags; |
| 195 | #define MFI_FLAGS_SG64		(1<<0) |
| 196 | #define MFI_FLAGS_QFRZN		(1<<1) |
| 197 | #define MFI_FLAGS_OPEN		(1<<2) |
| 198 | #define MFI_FLAGS_STOP		(1<<3) |
| 199 | #define MFI_FLAGS_1064R		(1<<4) |
| 200 | #define MFI_FLAGS_1078		(1<<5) |
| 201 | #define MFI_FLAGS_GEN2		(1<<6) |
| 202 | #define MFI_FLAGS_SKINNY	(1<<7) |
| 203 | #define MFI_FLAGS_TBOLT		(1<<8) |
| 204 | #define MFI_FLAGS_MRSAS		(1<<9) |
| 205 | #define MFI_FLAGS_INVADER	(1<<10) |
| 206 | #define MFI_FLAGS_FURY		(1<<11) |
| 207 | 	// Start: LSIP200113393 |
| 208 | 	bus_dma_tag_t			verbuf_h_dmat; |
| 209 | 	bus_dmamap_t			verbuf_h_dmamap; |
| 210 | 	bus_addr_t			verbuf_h_busaddr; |
| 211 | 	uint32_t			*verbuf; |
| 212 | 	void				*kbuff_arr[MAX_IOCTL_SGE]; |
| 213 | 	bus_dma_tag_t			mfi_kbuff_arr_dmat[2]; |
| 214 | 	bus_dmamap_t			mfi_kbuff_arr_dmamap[2]; |
| 215 | 	bus_addr_t			mfi_kbuff_arr_busaddr[2]; |
| 216 | |
| 217 | 	struct mfi_hwcomms		*mfi_comms; |
| 218 | 	TAILQ_HEAD(,mfi_command)	mfi_free; |
| 219 | 	TAILQ_HEAD(,mfi_command)	mfi_ready; |
| 220 | 	TAILQ_HEAD(BUSYQ,mfi_command)	mfi_busy; |
| 221 | 	struct bio_queue_head		mfi_bioq; |
| 222 | 	struct mfi_qstat		mfi_qstat[MFIQ_COUNT]; |
| 223 | |
| 224 | 	struct resource			*mfi_regs_resource; |
| 225 | 	bus_space_handle_t		mfi_bhandle; |
| 226 | 	bus_space_tag_t			mfi_btag; |
| 227 | 	int				mfi_regs_rid; |
| 228 | |
| 229 | 	bus_dma_tag_t			mfi_parent_dmat; |
| 230 | 	bus_dma_tag_t			mfi_buffer_dmat; |
| 231 | |
| 232 | 	bus_dma_tag_t			mfi_comms_dmat; |
| 233 | 	bus_dmamap_t			mfi_comms_dmamap; |
| 234 | 	bus_addr_t			mfi_comms_busaddr; |
| 235 | |
| 236 | 	bus_dma_tag_t			mfi_frames_dmat; |
| 237 | 	bus_dmamap_t			mfi_frames_dmamap; |
| 238 | 	bus_addr_t			mfi_frames_busaddr; |
| 239 | 	union mfi_frame			*mfi_frames; |
| 240 | |
| 241 | 	bus_dma_tag_t			mfi_tb_init_dmat; |
| 242 | 	bus_dmamap_t			mfi_tb_init_dmamap; |
| 243 | 	bus_addr_t			mfi_tb_init_busaddr; |
| 244 | 	bus_addr_t			mfi_tb_ioc_init_busaddr; |
| 245 | 	union mfi_frame			*mfi_tb_init; |
| 246 | |
| 247 | 	TAILQ_HEAD(,mfi_evt_queue_elm)	mfi_evt_queue; |
| 248 | 	struct task			mfi_evt_task; |
| 249 | 	struct task			mfi_map_sync_task; |
| 250 | 	TAILQ_HEAD(,mfi_aen)		mfi_aen_pids; |
| 251 | 	struct mfi_command		*mfi_aen_cm; |
| 252 | 	struct mfi_command		*mfi_skinny_cm; |
| 253 | 	struct mfi_command		*mfi_map_sync_cm; |
| 254 | 	int				cm_aen_abort; |
| 255 | 	int				cm_map_abort; |
| 256 | 	uint32_t			mfi_aen_triggered; |
| 257 | 	uint32_t			mfi_poll_waiting; |
| 258 | 	uint32_t			mfi_boot_seq_num; |
| 259 | 	struct selinfo			mfi_select; |
| 260 | 	int				mfi_delete_busy_volumes; |
| 261 | 	int				mfi_keep_deleted_volumes; |
| 262 | 	int				mfi_detaching; |
| 263 | |
| 264 | 	bus_dma_tag_t			mfi_sense_dmat; |
| 265 | 	bus_dmamap_t			mfi_sense_dmamap; |
| 266 | 	bus_addr_t			mfi_sense_busaddr; |
| 267 | 	struct mfi_sense		*mfi_sense; |
| 268 | |
| 269 | 	struct resource			*mfi_irq; |
| 270 | 	void				*mfi_intr; |
| 271 | 	int				mfi_irq_rid; |
| 272 | |
| 273 | 	struct intr_config_hook		mfi_ich; |
| 274 | 	eventhandler_tag		eh; |
| 275 | 	/* OCR flags */ |
| 276 | 	uint8_t adpreset; |
| 277 | 	uint8_t issuepend_done; |
| 278 | 	uint8_t disableOnlineCtrlReset; |
| 279 | 	uint32_t mfiStatus; |
| 280 | 	uint32_t last_seq_num; |
| 281 | 	uint32_t volatile hw_crit_error; |
| 282 | |
| 283 | 	/* |
| 284 | 	 * Allocation for the command array. Used as an indexable array to |
| 285 | 	 * recover completed commands. |
| 286 | 	 */ |
| 287 | 	struct mfi_command		*mfi_commands; |
| 288 | 	/* |
| 289 | 	 * How many commands the firmware can handle. Also how big the reply |
| 290 | 	 * queue is, minus 1. |
| 291 | 	 */ |
| 292 | 	int				mfi_max_fw_cmds; |
| 293 | 	/* |
| 294 | 	 * How many S/G elements we'll ever actually use |
| 295 | 	 */ |
| 296 | 	int				mfi_max_sge; |
| 297 | 	/* |
| 298 | 	 * How many bytes a compound frame is, including all of the extra frames |
| 299 | 	 * that are used for S/G elements. |
| 300 | 	 */ |
| 301 | 	int				mfi_cmd_size; |
| 302 | 	/* |
| 303 | 	 * How large an S/G element is. Used to calculate the number of single |
| 304 | 	 * frames in a command. |
| 305 | 	 */ |
| 306 | 	int				mfi_sge_size; |
| 307 | 	/* |
| 308 | 	 * Max number of sectors that the firmware allows |
| 309 | 	 */ |
| 310 | 	uint32_t			mfi_max_io; |
| 311 | |
| 312 | 	TAILQ_HEAD(,mfi_disk)		mfi_ld_tqh; |
| 313 | 	TAILQ_HEAD(,mfi_system_pd)	mfi_syspd_tqh; |
| 314 | 	TAILQ_HEAD(,mfi_disk_pending)	mfi_ld_pend_tqh; |
| 315 | 	TAILQ_HEAD(,mfi_system_pending)	mfi_syspd_pend_tqh; |
| 316 | 	eventhandler_tag		mfi_eh; |
| 317 | 	struct cdev			*mfi_cdev; |
| 318 | |
| 319 | 	TAILQ_HEAD(, ccb_hdr)		mfi_cam_ccbq; |
| 320 | 	struct mfi_command *		(* mfi_cam_start)(void *); |
| 321 | 	void				(*mfi_cam_rescan_cb)(struct mfi_softc *, |
| 322 | 					 uint32_t); |
| 323 | 	struct callout			mfi_watchdog_callout; |
| 324 | 	struct mtx			mfi_io_lock; |
| 325 | 	struct sx			mfi_config_lock; |
| 326 | |
| 327 | 	/* Controller type specific interfaces */ |
| 328 | 	void	(*mfi_enable_intr)(struct mfi_softc *sc); |
| 329 | 	void	(*mfi_disable_intr)(struct mfi_softc *sc); |
| 330 | 	int32_t	(*mfi_read_fw_status)(struct mfi_softc *sc); |
| 331 | 	int	(*mfi_check_clear_intr)(struct mfi_softc *sc); |
| 332 | 	void	(*mfi_issue_cmd)(struct mfi_softc *sc, bus_addr_t bus_add, |
| 333 | 		 uint32_t frame_cnt); |
| 334 | 	int	(*mfi_adp_reset)(struct mfi_softc *sc); |
| 335 | 	int	(*mfi_adp_check_reset)(struct mfi_softc *sc); |
| 336 | 	void				(*mfi_intr_ptr)(void *sc); |
| 337 | |
| 338 | 	/* ThunderBolt */ |
| 339 | 	uint32_t			mfi_tbolt; |
| 340 | 	uint32_t			MFA_enabled; |
| 341 | 	/* Single Reply structure size */ |
| 342 | 	uint16_t			reply_size; |
| 343 | 	/* Singler message size. */ |
| 344 | 	uint16_t			raid_io_msg_size; |
| 345 | 	TAILQ_HEAD(TB, mfi_cmd_tbolt)	mfi_cmd_tbolt_tqh; |
| 346 | 	/* ThunderBolt base contiguous memory mapping. */ |
| 347 | 	bus_dma_tag_t			mfi_tb_dmat; |
| 348 | 	bus_dmamap_t			mfi_tb_dmamap; |
| 349 | 	bus_addr_t			mfi_tb_busaddr; |
| 350 | 	/* ThunderBolt Contiguous DMA memory Mapping */ |
| 351 | 	uint8_t	*			request_message_pool; |
| 352 | 	uint8_t *			request_message_pool_align; |
| 353 | 	uint8_t *			request_desc_pool; |
| 354 | 	bus_addr_t			request_msg_busaddr; |
| 355 | 	bus_addr_t			reply_frame_busaddr; |
| 356 | 	bus_addr_t			sg_frame_busaddr; |
| 357 | 	/* ThunderBolt IOC Init Descriptor */ |
| 358 | 	bus_dma_tag_t			mfi_tb_ioc_init_dmat; |
| 359 | 	bus_dmamap_t			mfi_tb_ioc_init_dmamap; |
| 360 | 	uint8_t *			mfi_tb_ioc_init_desc; |
| 361 | 	struct mfi_cmd_tbolt		**mfi_cmd_pool_tbolt; |
| 362 | 	/* Virtual address of reply Frame Pool */ |
| 363 | 	struct mfi_mpi2_reply_header*	reply_frame_pool; |
| 364 | 	struct mfi_mpi2_reply_header*	reply_frame_pool_align; |
| 365 | |
| 366 | 	/* Last reply frame address */ |
| 367 | 	uint8_t *			reply_pool_limit; |
| 368 | 	uint16_t			last_reply_idx; |
| 369 | 	uint8_t				max_SGEs_in_chain_message; |
| 370 | 	uint8_t				max_SGEs_in_main_message; |
| 371 | 	uint8_t				chain_offset_value_for_main_message; |
| 372 | 	uint8_t				chain_offset_value_for_mpt_ptmsg; |
| 373 | }; |
| 374 | |
| 375 | union desc_value { |
| 376 | 	uint64_t	word; |
| 377 | 	struct { |
| 378 | 		uint32_t	low; |
| 379 | 		uint32_t	high; |
| 380 | 	}u; |
| 381 | }; |
| 382 | |
| 383 | // TODO find the right definition |
| 384 | #define XXX_MFI_CMD_OP_INIT2 0x9 |
| 385 | /* |
| 386 | * Request descriptor types |
| 387 | */ |
| 388 | #define MFI_REQ_DESCRIPT_FLAGS_LD_IO 0x7 |
| 389 | #define MFI_REQ_DESCRIPT_FLAGS_MFA 0x1 |
| 390 | #define MFI_REQ_DESCRIPT_FLAGS_TYPE_SHIFT	0x1 |
| 391 | #define MFI_FUSION_FP_DEFAULT_TIMEOUT		0x14 |
| 392 | #define MFI_LOAD_BALANCE_FLAG			0x1 |
| 393 | #define MFI_DCMD_MBOX_PEND_FLAG			0x1 |
| 394 | |
| 395 | //#define MR_PROT_INFO_TYPE_CONTROLLER	0x08 |
| 396 | #define	MEGASAS_SCSI_VARIABLE_LENGTH_CMD	0x7f |
| 397 | #define MEGASAS_SCSI_SERVICE_ACTION_READ32	0x9 |
| 398 | #define MEGASAS_SCSI_SERVICE_ACTION_WRITE32	0xB |
| 399 | #define	MEGASAS_SCSI_ADDL_CDB_LEN 		0x18 |
| 400 | #define MEGASAS_RD_WR_PROTECT_CHECK_ALL		0x20 |
| 401 | #define MEGASAS_RD_WR_PROTECT_CHECK_NONE	0x60 |
| 402 | #define MEGASAS_EEDPBLOCKSIZE			512 |
| 403 | struct mfi_cmd_tbolt { |
| 404 | 	union mfi_mpi2_request_descriptor *request_desc; |
| 405 | 	struct mfi_mpi2_request_raid_scsi_io *io_request; |
| 406 | 	bus_addr_t		io_request_phys_addr; |
| 407 | 	bus_addr_t		sg_frame_phys_addr; |
| 408 | 	bus_addr_t 		sense_phys_addr; |
| 409 | 	MPI2_SGE_IO_UNION	*sg_frame; |
| 410 | 	uint8_t			*sense; |
| 411 | 	TAILQ_ENTRY(mfi_cmd_tbolt) next; |
| 412 | 	/* |
| 413 | 	 * Context for a MFI frame. |
| 414 | 	 * Used to get the mfi cmd from list when a MFI cmd is completed |
| 415 | 	 */ |
| 416 | 	uint32_t		sync_cmd_idx; |
| 417 | 	uint16_t		index; |
| 418 | 	uint8_t			status; |
| 419 | }; |
| 420 | |
| 421 | extern int mfi_attach(struct mfi_softc *); |
| 422 | extern void mfi_free(struct mfi_softc *); |
| 423 | extern int mfi_shutdown(struct mfi_softc *); |
| 424 | extern void mfi_startio(struct mfi_softc *); |
| 425 | extern void mfi_disk_complete(struct bio *); |
| 426 | extern int mfi_disk_disable(struct mfi_disk *); |
| 427 | extern void mfi_disk_enable(struct mfi_disk *); |
| 428 | extern int mfi_dump_blocks(struct mfi_softc *, int id, uint64_t, void *, int); |
| 429 | extern int mfi_syspd_disable(struct mfi_system_pd *); |
| 430 | extern void mfi_syspd_enable(struct mfi_system_pd *); |
| 431 | extern int mfi_dump_syspd_blocks(struct mfi_softc *, int id, uint64_t, void *, |
| 432 | int); |
| 433 | extern int mfi_transition_firmware(struct mfi_softc *sc); |
| 434 | extern int mfi_aen_setup(struct mfi_softc *sc, uint32_t seq_start); |
| 435 | extern void mfi_complete(struct mfi_softc *sc, struct mfi_command *cm); |
| 436 | extern int mfi_mapcmd(struct mfi_softc *sc,struct mfi_command *cm); |
| 437 | extern int mfi_wait_command(struct mfi_softc *sc, struct mfi_command *cm); |
| 438 | extern void mfi_tbolt_enable_intr_ppc(struct mfi_softc *); |
| 439 | extern void mfi_tbolt_disable_intr_ppc(struct mfi_softc *); |
| 440 | extern int32_t mfi_tbolt_read_fw_status_ppc(struct mfi_softc *); |
| 441 | extern int32_t mfi_tbolt_check_clear_intr_ppc(struct mfi_softc *); |
| 442 | extern void mfi_tbolt_issue_cmd_ppc(struct mfi_softc *, bus_addr_t, uint32_t); |
| 443 | extern void mfi_tbolt_init_globals(struct mfi_softc*); |
| 444 | extern uint32_t mfi_tbolt_get_memory_requirement(struct mfi_softc *); |
| 445 | extern int mfi_tbolt_init_desc_pool(struct mfi_softc *, uint8_t *, uint32_t); |
| 446 | extern int mfi_tbolt_init_MFI_queue(struct mfi_softc *); |
| 447 | extern void mfi_intr_tbolt(void *arg); |
| 448 | extern int mfi_tbolt_alloc_cmd(struct mfi_softc *sc); |
| 449 | extern int mfi_tbolt_send_frame(struct mfi_softc *sc, struct mfi_command *cm); |
| 450 | extern int mfi_tbolt_adp_reset(struct mfi_softc *sc); |
| 451 | extern int mfi_tbolt_reset(struct mfi_softc *sc); |
| 452 | extern void mfi_tbolt_sync_map_info(struct mfi_softc *sc); |
| 453 | extern void mfi_handle_map_sync(void *context, int pending); |
| 454 | extern int mfi_dcmd_command(struct mfi_softc *, struct mfi_command **, |
| 455 | uint32_t, void **, size_t); |
| 456 | extern int mfi_build_cdb(int, uint8_t, u_int64_t, u_int32_t, uint8_t *); |
| 457 | |
| 458 | #define MFIQ_ADD(sc, qname)					\ |
| 459 | 	do {							\ |
| 460 | 		struct mfi_qstat *qs;				\ |
| 461 | 								\ |
| 462 | 		qs = &(sc)->mfi_qstat[qname];			\ |
| 463 | 		qs->q_length++;					\ |
| 464 | 		if (qs->q_length > qs->q_max)			\ |
| 465 | 			qs->q_max = qs->q_length;		\ |
| 466 | 	} while (0) |
| 467 | |
| 468 | #define MFIQ_REMOVE(sc, qname)	(sc)->mfi_qstat[qname].q_length-- |
| 469 | |
| 470 | #define MFIQ_INIT(sc, qname)					\ |
| 471 | 	do {							\ |
| 472 | 		sc->mfi_qstat[qname].q_length = 0;		\ |
| 473 | 		sc->mfi_qstat[qname].q_max = 0;			\ |
| 474 | 	} while (0) |
| 475 | |
| 476 | #define MFIQ_COMMAND_QUEUE(name, index)					\ |
| 477 | 	static __inline void						\ |
| 478 | 	mfi_initq_ ## name (struct mfi_softc *sc)			\ |
| 479 | 	{								\ |
| 480 | 		TAILQ_INIT(&sc->mfi_ ## name);				\ |
| 481 | 		MFIQ_INIT(sc, index);					\ |
| 482 | 	}								\ |
| 483 | 	static __inline void						\ |
| 484 | 	mfi_enqueue_ ## name (struct mfi_command *cm)			\ |
| 485 | 	{								\ |
| 486 | 		if ((cm->cm_flags & MFI_ON_MFIQ_MASK) != 0) {		\ |
| 487 | 			panic("command %p is on another queue, "	\ |
| 488 | 			 "flags = %#x\n", cm, cm->cm_flags);		\ |
| 489 | 		}							\ |
| 490 | 		TAILQ_INSERT_TAIL(&cm->cm_sc->mfi_ ## name, cm, cm_link); \ |
| 491 | 		cm->cm_flags |= MFI_ON_ ## index;			\ |
| 492 | 		MFIQ_ADD(cm->cm_sc, index);				\ |
| 493 | 	}								\ |
| 494 | 	static __inline void						\ |
| 495 | 	mfi_requeue_ ## name (struct mfi_command *cm)			\ |
| 496 | 	{								\ |
| 497 | 		if ((cm->cm_flags & MFI_ON_MFIQ_MASK) != 0) {		\ |
| 498 | 			panic("command %p is on another queue, "	\ |
| 499 | 			 "flags = %#x\n", cm, cm->cm_flags);		\ |
| 500 | 		}							\ |
| 501 | 		TAILQ_INSERT_HEAD(&cm->cm_sc->mfi_ ## name, cm, cm_link); \ |
| 502 | 		cm->cm_flags |= MFI_ON_ ## index;			\ |
| 503 | 		MFIQ_ADD(cm->cm_sc, index);				\ |
| 504 | 	}								\ |
| 505 | 	static __inline struct mfi_command *				\ |
| 506 | 	mfi_dequeue_ ## name (struct mfi_softc *sc)			\ |
| 507 | 	{								\ |
| 508 | 		struct mfi_command *cm;					\ |
| 509 | 									\ |
| 510 | 		if ((cm = TAILQ_FIRST(&sc->mfi_ ## name)) != NULL) {	\ |
| 511 | 			if ((cm->cm_flags & MFI_ON_ ## index) == 0) {	\ |
| 512 | 				panic("command %p not in queue, "	\ |
| 513 | 				 "flags = %#x, bit = %#x\n", cm,	\ |
| 514 | 				 cm->cm_flags, MFI_ON_ ## index);	\ |
| 515 | 			}						\ |
| 516 | 			TAILQ_REMOVE(&sc->mfi_ ## name, cm, cm_link);	\ |
| 517 | 			cm->cm_flags &= ~MFI_ON_ ## index;		\ |
| 518 | 			MFIQ_REMOVE(sc, index);				\ |
| 519 | 		}							\ |
| 520 | 		return (cm);						\ |
| 521 | 	}								\ |
| 522 | 	static __inline void						\ |
| 523 | 	mfi_remove_ ## name (struct mfi_command *cm)			\ |
| 524 | 	{								\ |
| 525 | 		if ((cm->cm_flags & MFI_ON_ ## index) == 0) {		\ |
| 526 | 			panic("command %p not in queue, flags = %#x, " \ |
| 527 | 			 "bit = %#x\n", cm, cm->cm_flags,		\ |
| 528 | 			 MFI_ON_ ## index);				\ |
| 529 | 		}							\ |
| 530 | 		TAILQ_REMOVE(&cm->cm_sc->mfi_ ## name, cm, cm_link);	\ |
| 531 | 		cm->cm_flags &= ~MFI_ON_ ## index;			\ |
| 532 | 		MFIQ_REMOVE(cm->cm_sc, index);				\ |
| 533 | 	}								\ |
| 534 | struct hack |
| 535 | |
| 536 | MFIQ_COMMAND_QUEUE(free, MFIQ_FREE); |
| 537 | MFIQ_COMMAND_QUEUE(ready, MFIQ_READY); |
| 538 | MFIQ_COMMAND_QUEUE(busy, MFIQ_BUSY); |
| 539 | |
| 540 | static __inline void |
| 541 | mfi_initq_bio(struct mfi_softc *sc) |
| 542 | { |
| 543 | 	bioq_init(&sc->mfi_bioq); |
| 544 | 	MFIQ_INIT(sc, MFIQ_BIO); |
| 545 | } |
| 546 | |
| 547 | static __inline void |
| 548 | mfi_enqueue_bio(struct mfi_softc *sc, struct bio *bp) |
| 549 | { |
| 550 | 	bioq_insert_tail(&sc->mfi_bioq, bp); |
| 551 | 	MFIQ_ADD(sc, MFIQ_BIO); |
| 552 | } |
| 553 | |
| 554 | static __inline struct bio * |
| 555 | mfi_dequeue_bio(struct mfi_softc *sc) |
| 556 | { |
| 557 | 	struct bio *bp; |
| 558 | |
| 559 | 	if ((bp = bioq_first(&sc->mfi_bioq)) != NULL) { |
| 560 | 		bioq_remove(&sc->mfi_bioq, bp); |
| 561 | 		MFIQ_REMOVE(sc, MFIQ_BIO); |
| 562 | 	} |
| 563 | 	return (bp); |
| 564 | } |
| 565 | |
| 566 | /* |
| 567 | * This is from the original scsi_extract_sense() in CAM. It's copied |
| 568 | * here because CAM now uses a non-inline version that follows more complex |
| 569 | * additions to the SPC spec, and we don't want to force a dependency on |
| 570 | * the CAM module for such a trivial action. |
| 571 | */ |
| 572 | static __inline void |
| 573 | mfi_extract_sense(struct scsi_sense_data_fixed *sense, |
| 574 | int *error_code, int *sense_key, int *asc, int *ascq) |
| 575 | { |
| 576 | |
| 577 | 	*error_code = sense->error_code & SSD_ERRCODE; |
| 578 | 	*sense_key = sense->flags & SSD_KEY; |
| 579 | 	*asc = (sense->extra_len >= 5) ? sense->add_sense_code : 0; |
| 580 | 	*ascq = (sense->extra_len >= 6) ? sense->add_sense_code_qual : 0; |
| 581 | } |
| 582 | |
| 583 | static __inline void |
| 584 | mfi_print_sense(struct mfi_softc *sc, void *sense) |
| 585 | { |
| 586 | 	int error, key, asc, ascq; |
| 587 | |
| 588 | 	mfi_extract_sense((struct scsi_sense_data_fixed *)sense, |
| 589 | 	 &error, &key, &asc, &ascq); |
| 590 | 	device_printf(sc->mfi_dev, "sense error %d, sense_key %d, " |
| 591 | 	 "asc %d, ascq %d\n", error, key, asc, ascq); |
| 592 | } |
| 593 | |
| 594 | #define MFI_WRITE4(sc, reg, val)	bus_space_write_4((sc)->mfi_btag, \ |
| 595 | 	sc->mfi_bhandle, (reg), (val)) |
| 596 | #define MFI_READ4(sc, reg)		bus_space_read_4((sc)->mfi_btag, \ |
| 597 | 	(sc)->mfi_bhandle, (reg)) |
| 598 | #define MFI_WRITE2(sc, reg, val)	bus_space_write_2((sc)->mfi_btag, \ |
| 599 | 	sc->mfi_bhandle, (reg), (val)) |
| 600 | #define MFI_READ2(sc, reg)		bus_space_read_2((sc)->mfi_btag, \ |
| 601 | 	(sc)->mfi_bhandle, (reg)) |
| 602 | #define MFI_WRITE1(sc, reg, val)	bus_space_write_1((sc)->mfi_btag, \ |
| 603 | 	sc->mfi_bhandle, (reg), (val)) |
| 604 | #define MFI_READ1(sc, reg)		bus_space_read_1((sc)->mfi_btag, \ |
| 605 | 	(sc)->mfi_bhandle, (reg)) |
| 606 | |
| 607 | MALLOC_DECLARE(M_MFIBUF); |
| 608 | SYSCTL_DECL(_hw_mfi); |
| 609 | |
| 610 | #define MFI_RESET_WAIT_TIME 180 |
| 611 | #define MFI_CMD_TIMEOUT 30 |
| 612 | #define MFI_SYS_PD_IO	0 |
| 613 | #define MFI_LD_IO	1 |
| 614 | #define MFI_SKINNY_MEMORY 0x02000000 |
| 615 | #define MFI_MAXPHYS (128 * 1024) |
| 616 | |
| 617 | #ifdef MFI_DEBUG |
| 618 | extern void mfi_print_cmd(struct mfi_command *cm); |
| 619 | extern void mfi_dump_cmds(struct mfi_softc *sc); |
| 620 | extern void mfi_validate_sg(struct mfi_softc *, struct mfi_command *, |
| 621 | const char *, int); |
| 622 | #define MFI_PRINT_CMD(cm)	mfi_print_cmd(cm) |
| 623 | #define MFI_DUMP_CMDS(sc)	mfi_dump_cmds(sc) |
| 624 | #define MFI_VALIDATE_CMD(sc, cm) mfi_validate_sg(sc, cm, __FUNCTION__, __LINE__) |
| 625 | #else |
| 626 | #define MFI_PRINT_CMD(cm) |
| 627 | #define MFI_DUMP_CMDS(sc) |
| 628 | #define MFI_VALIDATE_CMD(sc, cm) |
| 629 | #endif |
| 630 | |
| 631 | extern void mfi_release_command(struct mfi_command *); |
| 632 | extern void mfi_tbolt_return_cmd(struct mfi_softc *, |
| 633 | struct mfi_cmd_tbolt *, struct mfi_command *); |
| 634 | |
| 635 | #endif /* _MFIVAR_H */ |