xref: /illumos-gate/usr/src/uts/common/io/mr_sas/mr_sas_tbolt.c (revision 97ac1f6486eb9b87b187039bec20569f99135a8d)
12ffc8bcaSDan McDonald /*
22ffc8bcaSDan McDonald  * mr_sas_tbolt.c: source for mr_sas driver for New Generation.
32ffc8bcaSDan McDonald  * i.e. Thunderbolt and Invader
42ffc8bcaSDan McDonald  *
52ffc8bcaSDan McDonald  * Solaris MegaRAID device driver for SAS2.0 controllers
62ffc8bcaSDan McDonald  * Copyright (c) 2008-2012, LSI Logic Corporation.
72ffc8bcaSDan McDonald  * All rights reserved.
82ffc8bcaSDan McDonald  *
92ffc8bcaSDan McDonald  * Version:
102ffc8bcaSDan McDonald  * Author:
112ffc8bcaSDan McDonald  *		Swaminathan K S
122ffc8bcaSDan McDonald  *		Arun Chandrashekhar
132ffc8bcaSDan McDonald  *		Manju R
142ffc8bcaSDan McDonald  *		Rasheed
152ffc8bcaSDan McDonald  *		Shakeel Bukhari
162ffc8bcaSDan McDonald  */
172ffc8bcaSDan McDonald 
18a1c36c8bSDan McDonald /*
19d8873b31SJoyce McIntosh  * Copyright 2018 Nexenta Systems, Inc.
20df950592SHummyPkg  * Copyright 2015, 2017 Citrus IT Limited. All rights reserved.
21a1ed883aSGarrett D'Amore  * Copyright 2015 Garrett D'Amore <garrett@damore.org>
22a1c36c8bSDan McDonald  */
23a1c36c8bSDan McDonald 
242ffc8bcaSDan McDonald 
252ffc8bcaSDan McDonald #include <sys/types.h>
262ffc8bcaSDan McDonald #include <sys/file.h>
272ffc8bcaSDan McDonald #include <sys/atomic.h>
282ffc8bcaSDan McDonald #include <sys/scsi/scsi.h>
292ffc8bcaSDan McDonald #include <sys/byteorder.h>
30091932b4SAndy Fiddaman #include <sys/sdt.h>
312ffc8bcaSDan McDonald #include "ld_pd_map.h"
322ffc8bcaSDan McDonald #include "mr_sas.h"
332ffc8bcaSDan McDonald #include "fusion.h"
342ffc8bcaSDan McDonald 
352ffc8bcaSDan McDonald /*
362ffc8bcaSDan McDonald  * FMA header files
372ffc8bcaSDan McDonald  */
382ffc8bcaSDan McDonald #include <sys/ddifm.h>
392ffc8bcaSDan McDonald #include <sys/fm/protocol.h>
402ffc8bcaSDan McDonald #include <sys/fm/util.h>
412ffc8bcaSDan McDonald #include <sys/fm/io/ddi.h>
422ffc8bcaSDan McDonald 
432ffc8bcaSDan McDonald 
442ffc8bcaSDan McDonald /* Pre-TB command size and TB command size. */
452ffc8bcaSDan McDonald #define	MR_COMMAND_SIZE (64*20)	/* 1280 bytes */
462ffc8bcaSDan McDonald MR_LD_RAID *MR_LdRaidGet(U32 ld, MR_FW_RAID_MAP_ALL *map);
472ffc8bcaSDan McDonald U16 MR_TargetIdToLdGet(U32 ldTgtId, MR_FW_RAID_MAP_ALL *map);
482ffc8bcaSDan McDonald U16 MR_GetLDTgtId(U32 ld, MR_FW_RAID_MAP_ALL *map);
492ffc8bcaSDan McDonald U16 get_updated_dev_handle(PLD_LOAD_BALANCE_INFO, struct IO_REQUEST_INFO *);
502ffc8bcaSDan McDonald extern ddi_dma_attr_t mrsas_generic_dma_attr;
512ffc8bcaSDan McDonald extern uint32_t mrsas_tbolt_max_cap_maxxfer;
522ffc8bcaSDan McDonald extern struct ddi_device_acc_attr endian_attr;
532ffc8bcaSDan McDonald extern int	debug_level_g;
542ffc8bcaSDan McDonald extern unsigned int	enable_fp;
55d8873b31SJoyce McIntosh volatile int dump_io_wait_time = 900;
562ffc8bcaSDan McDonald extern volatile int  debug_timeout_g;
572ffc8bcaSDan McDonald extern int	mrsas_issue_pending_cmds(struct mrsas_instance *);
582ffc8bcaSDan McDonald extern int mrsas_complete_pending_cmds(struct mrsas_instance *instance);
592ffc8bcaSDan McDonald extern void	push_pending_mfi_pkt(struct mrsas_instance *,
602ffc8bcaSDan McDonald 			struct mrsas_cmd *);
612ffc8bcaSDan McDonald extern U8 MR_BuildRaidContext(struct mrsas_instance *, struct IO_REQUEST_INFO *,
622ffc8bcaSDan McDonald 	    MPI2_SCSI_IO_VENDOR_UNIQUE *, MR_FW_RAID_MAP_ALL *);
632ffc8bcaSDan McDonald 
642ffc8bcaSDan McDonald /* Local static prototypes. */
652ffc8bcaSDan McDonald static struct mrsas_cmd *mrsas_tbolt_build_cmd(struct mrsas_instance *,
662ffc8bcaSDan McDonald     struct scsi_address *, struct scsi_pkt *, uchar_t *);
673344ffb7SToomas Soome static void mrsas_tbolt_set_pd_lba(U8 *, size_t, uint8_t *, U64, U32);
682ffc8bcaSDan McDonald static int mrsas_tbolt_check_map_info(struct mrsas_instance *);
692ffc8bcaSDan McDonald static int mrsas_tbolt_sync_map_info(struct mrsas_instance *);
702ffc8bcaSDan McDonald static int mrsas_tbolt_prepare_pkt(struct scsa_cmd *);
712ffc8bcaSDan McDonald static int mrsas_tbolt_ioc_init(struct mrsas_instance *, dma_obj_t *);
722ffc8bcaSDan McDonald static void mrsas_tbolt_get_pd_info(struct mrsas_instance *,
732ffc8bcaSDan McDonald     struct mrsas_tbolt_pd_info *, int);
742ffc8bcaSDan McDonald 
75eef6dbdfSAndy Fiddaman static int mrsas_debug_tbolt_fw_faults_after_ocr = 0;
762ffc8bcaSDan McDonald 
772ffc8bcaSDan McDonald /*
782ffc8bcaSDan McDonald  * destroy_mfi_mpi_frame_pool
792ffc8bcaSDan McDonald  */
802ffc8bcaSDan McDonald void
destroy_mfi_mpi_frame_pool(struct mrsas_instance * instance)812ffc8bcaSDan McDonald destroy_mfi_mpi_frame_pool(struct mrsas_instance *instance)
822ffc8bcaSDan McDonald {
832ffc8bcaSDan McDonald 	int	i;
842ffc8bcaSDan McDonald 
852ffc8bcaSDan McDonald 	struct mrsas_cmd	*cmd;
862ffc8bcaSDan McDonald 
872ffc8bcaSDan McDonald 	/* return all mfi frames to pool */
882ffc8bcaSDan McDonald 	for (i = 0; i < MRSAS_APP_RESERVED_CMDS; i++) {
892ffc8bcaSDan McDonald 		cmd = instance->cmd_list[i];
902ffc8bcaSDan McDonald 		if (cmd->frame_dma_obj_status == DMA_OBJ_ALLOCATED) {
912ffc8bcaSDan McDonald 			(void) mrsas_free_dma_obj(instance,
922ffc8bcaSDan McDonald 			    cmd->frame_dma_obj);
932ffc8bcaSDan McDonald 		}
942ffc8bcaSDan McDonald 		cmd->frame_dma_obj_status = DMA_OBJ_FREED;
952ffc8bcaSDan McDonald 	}
962ffc8bcaSDan McDonald }
972ffc8bcaSDan McDonald 
982ffc8bcaSDan McDonald /*
992ffc8bcaSDan McDonald  * destroy_mpi2_frame_pool
1002ffc8bcaSDan McDonald  */
1012ffc8bcaSDan McDonald void
destroy_mpi2_frame_pool(struct mrsas_instance * instance)1022ffc8bcaSDan McDonald destroy_mpi2_frame_pool(struct mrsas_instance *instance)
1032ffc8bcaSDan McDonald {
1042ffc8bcaSDan McDonald 
1052ffc8bcaSDan McDonald 	if (instance->mpi2_frame_pool_dma_obj.status == DMA_OBJ_ALLOCATED) {
1062ffc8bcaSDan McDonald 		(void) mrsas_free_dma_obj(instance,
1072ffc8bcaSDan McDonald 		    instance->mpi2_frame_pool_dma_obj);
1082ffc8bcaSDan McDonald 		instance->mpi2_frame_pool_dma_obj.status |= DMA_OBJ_FREED;
1092ffc8bcaSDan McDonald 	}
1102ffc8bcaSDan McDonald }
1112ffc8bcaSDan McDonald 
1122ffc8bcaSDan McDonald 
1132ffc8bcaSDan McDonald /*
1142ffc8bcaSDan McDonald  * mrsas_tbolt_free_additional_dma_buffer
1152ffc8bcaSDan McDonald  */
1162ffc8bcaSDan McDonald void
mrsas_tbolt_free_additional_dma_buffer(struct mrsas_instance * instance)1172ffc8bcaSDan McDonald mrsas_tbolt_free_additional_dma_buffer(struct mrsas_instance *instance)
1182ffc8bcaSDan McDonald {
1192ffc8bcaSDan McDonald 	int i;
1202ffc8bcaSDan McDonald 
1212ffc8bcaSDan McDonald 	if (instance->mfi_internal_dma_obj.status == DMA_OBJ_ALLOCATED) {
1222ffc8bcaSDan McDonald 		(void) mrsas_free_dma_obj(instance,
1232ffc8bcaSDan McDonald 		    instance->mfi_internal_dma_obj);
1242ffc8bcaSDan McDonald 		instance->mfi_internal_dma_obj.status = DMA_OBJ_FREED;
1252ffc8bcaSDan McDonald 	}
1262ffc8bcaSDan McDonald 	if (instance->mfi_evt_detail_obj.status == DMA_OBJ_ALLOCATED) {
1272ffc8bcaSDan McDonald 		(void) mrsas_free_dma_obj(instance,
1282ffc8bcaSDan McDonald 		    instance->mfi_evt_detail_obj);
1292ffc8bcaSDan McDonald 		instance->mfi_evt_detail_obj.status = DMA_OBJ_FREED;
1302ffc8bcaSDan McDonald 	}
1312ffc8bcaSDan McDonald 
1322ffc8bcaSDan McDonald 	for (i = 0; i < 2; i++) {
1332ffc8bcaSDan McDonald 		if (instance->ld_map_obj[i].status == DMA_OBJ_ALLOCATED) {
1342ffc8bcaSDan McDonald 			(void) mrsas_free_dma_obj(instance,
1352ffc8bcaSDan McDonald 			    instance->ld_map_obj[i]);
1362ffc8bcaSDan McDonald 			instance->ld_map_obj[i].status = DMA_OBJ_FREED;
1372ffc8bcaSDan McDonald 		}
1382ffc8bcaSDan McDonald 	}
1392ffc8bcaSDan McDonald }
1402ffc8bcaSDan McDonald 
1412ffc8bcaSDan McDonald 
1422ffc8bcaSDan McDonald /*
1432ffc8bcaSDan McDonald  * free_req_desc_pool
1442ffc8bcaSDan McDonald  */
1452ffc8bcaSDan McDonald void
free_req_rep_desc_pool(struct mrsas_instance * instance)1462ffc8bcaSDan McDonald free_req_rep_desc_pool(struct mrsas_instance *instance)
1472ffc8bcaSDan McDonald {
1482ffc8bcaSDan McDonald 	if (instance->request_desc_dma_obj.status == DMA_OBJ_ALLOCATED) {
1492ffc8bcaSDan McDonald 		(void) mrsas_free_dma_obj(instance,
1502ffc8bcaSDan McDonald 		    instance->request_desc_dma_obj);
1512ffc8bcaSDan McDonald 		instance->request_desc_dma_obj.status = DMA_OBJ_FREED;
1522ffc8bcaSDan McDonald 	}
1532ffc8bcaSDan McDonald 
1542ffc8bcaSDan McDonald 	if (instance->reply_desc_dma_obj.status == DMA_OBJ_ALLOCATED) {
1552ffc8bcaSDan McDonald 		(void) mrsas_free_dma_obj(instance,
1562ffc8bcaSDan McDonald 		    instance->reply_desc_dma_obj);
1572ffc8bcaSDan McDonald 		instance->reply_desc_dma_obj.status = DMA_OBJ_FREED;
1582ffc8bcaSDan McDonald 	}
1592ffc8bcaSDan McDonald 
1602ffc8bcaSDan McDonald 
1612ffc8bcaSDan McDonald }
1622ffc8bcaSDan McDonald 
1632ffc8bcaSDan McDonald 
1642ffc8bcaSDan McDonald /*
1652ffc8bcaSDan McDonald  * ThunderBolt(TB) Request Message Frame Pool
1662ffc8bcaSDan McDonald  */
1672ffc8bcaSDan McDonald int
create_mpi2_frame_pool(struct mrsas_instance * instance)1682ffc8bcaSDan McDonald create_mpi2_frame_pool(struct mrsas_instance *instance)
1692ffc8bcaSDan McDonald {
1702ffc8bcaSDan McDonald 	int		i = 0;
1712ffc8bcaSDan McDonald 	uint16_t	max_cmd;
1722ffc8bcaSDan McDonald 	uint32_t	sgl_sz;
1732ffc8bcaSDan McDonald 	uint32_t	raid_msg_size;
1742ffc8bcaSDan McDonald 	uint32_t	total_size;
1752ffc8bcaSDan McDonald 	uint32_t	offset;
1762ffc8bcaSDan McDonald 	uint32_t	io_req_base_phys;
1772ffc8bcaSDan McDonald 	uint8_t		*io_req_base;
1782ffc8bcaSDan McDonald 	struct mrsas_cmd	*cmd;
1792ffc8bcaSDan McDonald 
1802ffc8bcaSDan McDonald 	max_cmd = instance->max_fw_cmds;
1812ffc8bcaSDan McDonald 
1822ffc8bcaSDan McDonald 	sgl_sz		= 1024;
1832ffc8bcaSDan McDonald 	raid_msg_size	= MRSAS_THUNDERBOLT_MSG_SIZE;
1842ffc8bcaSDan McDonald 
1852ffc8bcaSDan McDonald 	/* Allocating additional 256 bytes to accomodate SMID 0. */
1862ffc8bcaSDan McDonald 	total_size = MRSAS_THUNDERBOLT_MSG_SIZE + (max_cmd * raid_msg_size) +
1872ffc8bcaSDan McDonald 	    (max_cmd * sgl_sz) + (max_cmd * SENSE_LENGTH);
1882ffc8bcaSDan McDonald 
1892ffc8bcaSDan McDonald 	con_log(CL_ANN1, (CE_NOTE, "create_mpi2_frame_pool: "
1902ffc8bcaSDan McDonald 	    "max_cmd %x", max_cmd));
1912ffc8bcaSDan McDonald 
1922ffc8bcaSDan McDonald 	con_log(CL_DLEVEL3, (CE_NOTE, "create_mpi2_frame_pool: "
1932ffc8bcaSDan McDonald 	    "request message frame pool size %x", total_size));
1942ffc8bcaSDan McDonald 
1952ffc8bcaSDan McDonald 	/*
1962ffc8bcaSDan McDonald 	 * ThunderBolt(TB) We need to create a single chunk of DMA'ble memory
1972ffc8bcaSDan McDonald 	 * and then split the memory to 1024 commands. Each command should be
1982ffc8bcaSDan McDonald 	 * able to contain a RAID MESSAGE FRAME which will embed a MFI_FRAME
1992ffc8bcaSDan McDonald 	 * within it. Further refer the "alloc_req_rep_desc" function where
2002ffc8bcaSDan McDonald 	 * we allocate request/reply descriptors queues for a clue.
2012ffc8bcaSDan McDonald 	 */
2022ffc8bcaSDan McDonald 
2032ffc8bcaSDan McDonald 	instance->mpi2_frame_pool_dma_obj.size = total_size;
2042ffc8bcaSDan McDonald 	instance->mpi2_frame_pool_dma_obj.dma_attr = mrsas_generic_dma_attr;
2052ffc8bcaSDan McDonald 	instance->mpi2_frame_pool_dma_obj.dma_attr.dma_attr_addr_hi =
2062ffc8bcaSDan McDonald 	    0xFFFFFFFFU;
2072ffc8bcaSDan McDonald 	instance->mpi2_frame_pool_dma_obj.dma_attr.dma_attr_count_max =
2082ffc8bcaSDan McDonald 	    0xFFFFFFFFU;
2092ffc8bcaSDan McDonald 	instance->mpi2_frame_pool_dma_obj.dma_attr.dma_attr_sgllen = 1;
2102ffc8bcaSDan McDonald 	instance->mpi2_frame_pool_dma_obj.dma_attr.dma_attr_align = 256;
2112ffc8bcaSDan McDonald 
2122ffc8bcaSDan McDonald 	if (mrsas_alloc_dma_obj(instance, &instance->mpi2_frame_pool_dma_obj,
2132ffc8bcaSDan McDonald 	    (uchar_t)DDI_STRUCTURE_LE_ACC) != 1) {
214ff38cf9dSAndy Fiddaman 		dev_err(instance->dip, CE_WARN,
215ff38cf9dSAndy Fiddaman 		    "could not alloc mpi2 frame pool");
2162ffc8bcaSDan McDonald 		return (DDI_FAILURE);
2172ffc8bcaSDan McDonald 	}
2182ffc8bcaSDan McDonald 
2192ffc8bcaSDan McDonald 	bzero(instance->mpi2_frame_pool_dma_obj.buffer, total_size);
2202ffc8bcaSDan McDonald 	instance->mpi2_frame_pool_dma_obj.status |= DMA_OBJ_ALLOCATED;
2212ffc8bcaSDan McDonald 
2222ffc8bcaSDan McDonald 	instance->io_request_frames =
2232ffc8bcaSDan McDonald 	    (uint8_t *)instance->mpi2_frame_pool_dma_obj.buffer;
2242ffc8bcaSDan McDonald 	instance->io_request_frames_phy =
2252ffc8bcaSDan McDonald 	    (uint32_t)
2262ffc8bcaSDan McDonald 	    instance->mpi2_frame_pool_dma_obj.dma_cookie[0].dmac_address;
2272ffc8bcaSDan McDonald 
2282ffc8bcaSDan McDonald 	con_log(CL_DLEVEL3, (CE_NOTE, "io_request_frames 0x%p",
2292ffc8bcaSDan McDonald 	    (void *)instance->io_request_frames));
2302ffc8bcaSDan McDonald 
2312ffc8bcaSDan McDonald 	con_log(CL_DLEVEL3, (CE_NOTE, "io_request_frames_phy 0x%x",
2322ffc8bcaSDan McDonald 	    instance->io_request_frames_phy));
2332ffc8bcaSDan McDonald 
2342ffc8bcaSDan McDonald 	io_req_base = (uint8_t *)instance->io_request_frames +
2352ffc8bcaSDan McDonald 	    MRSAS_THUNDERBOLT_MSG_SIZE;
2362ffc8bcaSDan McDonald 	io_req_base_phys = instance->io_request_frames_phy +
2372ffc8bcaSDan McDonald 	    MRSAS_THUNDERBOLT_MSG_SIZE;
2382ffc8bcaSDan McDonald 
2392ffc8bcaSDan McDonald 	con_log(CL_DLEVEL3, (CE_NOTE,
2402ffc8bcaSDan McDonald 	    "io req_base_phys 0x%x", io_req_base_phys));
2412ffc8bcaSDan McDonald 
2422ffc8bcaSDan McDonald 	for (i = 0; i < max_cmd; i++) {
2432ffc8bcaSDan McDonald 		cmd = instance->cmd_list[i];
2442ffc8bcaSDan McDonald 
2452ffc8bcaSDan McDonald 		offset = i * MRSAS_THUNDERBOLT_MSG_SIZE;
2462ffc8bcaSDan McDonald 
2472ffc8bcaSDan McDonald 		cmd->scsi_io_request = (Mpi2RaidSCSIIORequest_t *)
2482ffc8bcaSDan McDonald 		    ((uint8_t *)io_req_base + offset);
2492ffc8bcaSDan McDonald 		cmd->scsi_io_request_phys_addr = io_req_base_phys + offset;
2502ffc8bcaSDan McDonald 
2512ffc8bcaSDan McDonald 		cmd->sgl = (Mpi2SGEIOUnion_t *)((uint8_t *)io_req_base +
2522ffc8bcaSDan McDonald 		    (max_cmd * raid_msg_size) + i * sgl_sz);
2532ffc8bcaSDan McDonald 
2542ffc8bcaSDan McDonald 		cmd->sgl_phys_addr = (io_req_base_phys +
2552ffc8bcaSDan McDonald 		    (max_cmd * raid_msg_size) + i * sgl_sz);
2562ffc8bcaSDan McDonald 
2572ffc8bcaSDan McDonald 		cmd->sense1 = (uint8_t *)((uint8_t *)io_req_base +
2582ffc8bcaSDan McDonald 		    (max_cmd * raid_msg_size) + (max_cmd * sgl_sz) +
2592ffc8bcaSDan McDonald 		    (i * SENSE_LENGTH));
2602ffc8bcaSDan McDonald 
2612ffc8bcaSDan McDonald 		cmd->sense_phys_addr1 = (io_req_base_phys +
2622ffc8bcaSDan McDonald 		    (max_cmd * raid_msg_size) + (max_cmd * sgl_sz) +
2632ffc8bcaSDan McDonald 		    (i * SENSE_LENGTH));
2642ffc8bcaSDan McDonald 
2652ffc8bcaSDan McDonald 
2662ffc8bcaSDan McDonald 		cmd->SMID = i + 1;
2672ffc8bcaSDan McDonald 
2682ffc8bcaSDan McDonald 		con_log(CL_DLEVEL3, (CE_NOTE, "Frame Pool Addr [%x]0x%p",
2692ffc8bcaSDan McDonald 		    cmd->index, (void *)cmd->scsi_io_request));
2702ffc8bcaSDan McDonald 
2712ffc8bcaSDan McDonald 		con_log(CL_DLEVEL3, (CE_NOTE, "Frame Pool Phys Addr [%x]0x%x",
2722ffc8bcaSDan McDonald 		    cmd->index, cmd->scsi_io_request_phys_addr));
2732ffc8bcaSDan McDonald 
2742ffc8bcaSDan McDonald 		con_log(CL_DLEVEL3, (CE_NOTE, "Sense Addr [%x]0x%p",
2752ffc8bcaSDan McDonald 		    cmd->index, (void *)cmd->sense1));
2762ffc8bcaSDan McDonald 
2772ffc8bcaSDan McDonald 		con_log(CL_DLEVEL3, (CE_NOTE, "Sense Addr Phys [%x]0x%x",
2782ffc8bcaSDan McDonald 		    cmd->index, cmd->sense_phys_addr1));
2792ffc8bcaSDan McDonald 
2802ffc8bcaSDan McDonald 		con_log(CL_DLEVEL3, (CE_NOTE, "Sgl bufffers [%x]0x%p",
2812ffc8bcaSDan McDonald 		    cmd->index, (void *)cmd->sgl));
2822ffc8bcaSDan McDonald 
2832ffc8bcaSDan McDonald 		con_log(CL_DLEVEL3, (CE_NOTE, "Sgl bufffers phys [%x]0x%x",
2842ffc8bcaSDan McDonald 		    cmd->index, cmd->sgl_phys_addr));
2852ffc8bcaSDan McDonald 	}
2862ffc8bcaSDan McDonald 
2872ffc8bcaSDan McDonald 	return (DDI_SUCCESS);
2882ffc8bcaSDan McDonald 
2892ffc8bcaSDan McDonald }
2902ffc8bcaSDan McDonald 
2912ffc8bcaSDan McDonald 
2922ffc8bcaSDan McDonald /*
2932ffc8bcaSDan McDonald  * alloc_additional_dma_buffer for AEN
2942ffc8bcaSDan McDonald  */
2952ffc8bcaSDan McDonald int
mrsas_tbolt_alloc_additional_dma_buffer(struct mrsas_instance * instance)2962ffc8bcaSDan McDonald mrsas_tbolt_alloc_additional_dma_buffer(struct mrsas_instance *instance)
2972ffc8bcaSDan McDonald {
2982ffc8bcaSDan McDonald 	uint32_t	internal_buf_size = PAGESIZE*2;
2992ffc8bcaSDan McDonald 	int i;
3002ffc8bcaSDan McDonald 
3012ffc8bcaSDan McDonald 	/* Initialize buffer status as free */
3022ffc8bcaSDan McDonald 	instance->mfi_internal_dma_obj.status = DMA_OBJ_FREED;
3032ffc8bcaSDan McDonald 	instance->mfi_evt_detail_obj.status = DMA_OBJ_FREED;
3042ffc8bcaSDan McDonald 	instance->ld_map_obj[0].status = DMA_OBJ_FREED;
3052ffc8bcaSDan McDonald 	instance->ld_map_obj[1].status = DMA_OBJ_FREED;
3062ffc8bcaSDan McDonald 
3072ffc8bcaSDan McDonald 
3082ffc8bcaSDan McDonald 	instance->mfi_internal_dma_obj.size = internal_buf_size;
3092ffc8bcaSDan McDonald 	instance->mfi_internal_dma_obj.dma_attr = mrsas_generic_dma_attr;
3102ffc8bcaSDan McDonald 	instance->mfi_internal_dma_obj.dma_attr.dma_attr_addr_hi = 0xFFFFFFFFU;
3112ffc8bcaSDan McDonald 	instance->mfi_internal_dma_obj.dma_attr.dma_attr_count_max =
3122ffc8bcaSDan McDonald 	    0xFFFFFFFFU;
3132ffc8bcaSDan McDonald 	instance->mfi_internal_dma_obj.dma_attr.dma_attr_sgllen = 1;
3142ffc8bcaSDan McDonald 
3152ffc8bcaSDan McDonald 	if (mrsas_alloc_dma_obj(instance, &instance->mfi_internal_dma_obj,
3162ffc8bcaSDan McDonald 	    (uchar_t)DDI_STRUCTURE_LE_ACC) != 1) {
317ff38cf9dSAndy Fiddaman 		dev_err(instance->dip, CE_WARN,
318ff38cf9dSAndy Fiddaman 		    "could not alloc reply queue");
3192ffc8bcaSDan McDonald 		return (DDI_FAILURE);
3202ffc8bcaSDan McDonald 	}
3212ffc8bcaSDan McDonald 
3222ffc8bcaSDan McDonald 	bzero(instance->mfi_internal_dma_obj.buffer, internal_buf_size);
3232ffc8bcaSDan McDonald 
3242ffc8bcaSDan McDonald 	instance->mfi_internal_dma_obj.status |= DMA_OBJ_ALLOCATED;
3252ffc8bcaSDan McDonald 	instance->internal_buf =
3262ffc8bcaSDan McDonald 	    (caddr_t)(((unsigned long)instance->mfi_internal_dma_obj.buffer));
3272ffc8bcaSDan McDonald 	instance->internal_buf_dmac_add =
3282ffc8bcaSDan McDonald 	    instance->mfi_internal_dma_obj.dma_cookie[0].dmac_address;
3292ffc8bcaSDan McDonald 	instance->internal_buf_size = internal_buf_size;
3302ffc8bcaSDan McDonald 
3312ffc8bcaSDan McDonald 	/* allocate evt_detail */
3322ffc8bcaSDan McDonald 	instance->mfi_evt_detail_obj.size = sizeof (struct mrsas_evt_detail);
3332ffc8bcaSDan McDonald 	instance->mfi_evt_detail_obj.dma_attr = mrsas_generic_dma_attr;
3342ffc8bcaSDan McDonald 	instance->mfi_evt_detail_obj.dma_attr.dma_attr_addr_hi = 0xFFFFFFFFU;
3352ffc8bcaSDan McDonald 	instance->mfi_evt_detail_obj.dma_attr.dma_attr_count_max = 0xFFFFFFFFU;
3362ffc8bcaSDan McDonald 	instance->mfi_evt_detail_obj.dma_attr.dma_attr_sgllen = 1;
3372ffc8bcaSDan McDonald 	instance->mfi_evt_detail_obj.dma_attr.dma_attr_align = 8;
3382ffc8bcaSDan McDonald 
3392ffc8bcaSDan McDonald 	if (mrsas_alloc_dma_obj(instance, &instance->mfi_evt_detail_obj,
3402ffc8bcaSDan McDonald 	    (uchar_t)DDI_STRUCTURE_LE_ACC) != 1) {
341ff38cf9dSAndy Fiddaman 		dev_err(instance->dip, CE_WARN,
342ff38cf9dSAndy Fiddaman 		    "mrsas_tbolt_alloc_additional_dma_buffer: "
3432ffc8bcaSDan McDonald 		    "could not allocate data transfer buffer.");
3442ffc8bcaSDan McDonald 		goto fail_tbolt_additional_buff;
3452ffc8bcaSDan McDonald 	}
3462ffc8bcaSDan McDonald 
3472ffc8bcaSDan McDonald 	bzero(instance->mfi_evt_detail_obj.buffer,
3482ffc8bcaSDan McDonald 	    sizeof (struct mrsas_evt_detail));
3492ffc8bcaSDan McDonald 
3502ffc8bcaSDan McDonald 	instance->mfi_evt_detail_obj.status |= DMA_OBJ_ALLOCATED;
3512ffc8bcaSDan McDonald 
3522ffc8bcaSDan McDonald 	instance->size_map_info = sizeof (MR_FW_RAID_MAP) +
3532ffc8bcaSDan McDonald 	    (sizeof (MR_LD_SPAN_MAP) * (MAX_LOGICAL_DRIVES - 1));
3542ffc8bcaSDan McDonald 
3552ffc8bcaSDan McDonald 	for (i = 0; i < 2; i++) {
3562ffc8bcaSDan McDonald 		/* allocate the data transfer buffer */
3572ffc8bcaSDan McDonald 		instance->ld_map_obj[i].size = instance->size_map_info;
3582ffc8bcaSDan McDonald 		instance->ld_map_obj[i].dma_attr = mrsas_generic_dma_attr;
3592ffc8bcaSDan McDonald 		instance->ld_map_obj[i].dma_attr.dma_attr_addr_hi = 0xFFFFFFFFU;
3602ffc8bcaSDan McDonald 		instance->ld_map_obj[i].dma_attr.dma_attr_count_max =
3612ffc8bcaSDan McDonald 		    0xFFFFFFFFU;
3622ffc8bcaSDan McDonald 		instance->ld_map_obj[i].dma_attr.dma_attr_sgllen = 1;
3632ffc8bcaSDan McDonald 		instance->ld_map_obj[i].dma_attr.dma_attr_align = 1;
3642ffc8bcaSDan McDonald 
3652ffc8bcaSDan McDonald 		if (mrsas_alloc_dma_obj(instance, &instance->ld_map_obj[i],
3662ffc8bcaSDan McDonald 		    (uchar_t)DDI_STRUCTURE_LE_ACC) != 1) {
367ff38cf9dSAndy Fiddaman 			dev_err(instance->dip, CE_WARN,
3682ffc8bcaSDan McDonald 			    "could not allocate data transfer buffer.");
3692ffc8bcaSDan McDonald 			goto fail_tbolt_additional_buff;
3702ffc8bcaSDan McDonald 		}
3712ffc8bcaSDan McDonald 
3722ffc8bcaSDan McDonald 		instance->ld_map_obj[i].status |= DMA_OBJ_ALLOCATED;
3732ffc8bcaSDan McDonald 
3742ffc8bcaSDan McDonald 		bzero(instance->ld_map_obj[i].buffer, instance->size_map_info);
3752ffc8bcaSDan McDonald 
3762ffc8bcaSDan McDonald 		instance->ld_map[i] =
3772ffc8bcaSDan McDonald 		    (MR_FW_RAID_MAP_ALL *)instance->ld_map_obj[i].buffer;
3782ffc8bcaSDan McDonald 		instance->ld_map_phy[i] = (uint32_t)instance->
3792ffc8bcaSDan McDonald 		    ld_map_obj[i].dma_cookie[0].dmac_address;
3802ffc8bcaSDan McDonald 
3812ffc8bcaSDan McDonald 		con_log(CL_DLEVEL3, (CE_NOTE,
3822ffc8bcaSDan McDonald 		    "ld_map Addr Phys 0x%x", instance->ld_map_phy[i]));
3832ffc8bcaSDan McDonald 
3842ffc8bcaSDan McDonald 		con_log(CL_DLEVEL3, (CE_NOTE,
3852ffc8bcaSDan McDonald 		    "size_map_info 0x%x", instance->size_map_info));
3862ffc8bcaSDan McDonald 	}
3872ffc8bcaSDan McDonald 
3882ffc8bcaSDan McDonald 	return (DDI_SUCCESS);
3892ffc8bcaSDan McDonald 
3902ffc8bcaSDan McDonald fail_tbolt_additional_buff:
3912ffc8bcaSDan McDonald 	mrsas_tbolt_free_additional_dma_buffer(instance);
3922ffc8bcaSDan McDonald 
3932ffc8bcaSDan McDonald 	return (DDI_FAILURE);
3942ffc8bcaSDan McDonald }
3952ffc8bcaSDan McDonald 
3962ffc8bcaSDan McDonald MRSAS_REQUEST_DESCRIPTOR_UNION *
mr_sas_get_request_descriptor(struct mrsas_instance * instance,uint16_t index)3972ffc8bcaSDan McDonald mr_sas_get_request_descriptor(struct mrsas_instance *instance, uint16_t index)
3982ffc8bcaSDan McDonald {
3992ffc8bcaSDan McDonald 	MRSAS_REQUEST_DESCRIPTOR_UNION *req_desc;
4002ffc8bcaSDan McDonald 
4012ffc8bcaSDan McDonald 	if (index > instance->max_fw_cmds) {
4022ffc8bcaSDan McDonald 		con_log(CL_ANN1, (CE_NOTE,
4032ffc8bcaSDan McDonald 		    "Invalid SMID 0x%x request for descriptor", index));
4042ffc8bcaSDan McDonald 		con_log(CL_ANN1, (CE_NOTE,
4052ffc8bcaSDan McDonald 		    "max_fw_cmds : 0x%x", instance->max_fw_cmds));
4062ffc8bcaSDan McDonald 		return (NULL);
4072ffc8bcaSDan McDonald 	}
4082ffc8bcaSDan McDonald 
4092ffc8bcaSDan McDonald 	req_desc = (MRSAS_REQUEST_DESCRIPTOR_UNION *)
4102ffc8bcaSDan McDonald 	    ((char *)instance->request_message_pool +
4112ffc8bcaSDan McDonald 	    (sizeof (MRSAS_REQUEST_DESCRIPTOR_UNION) * index));
4122ffc8bcaSDan McDonald 
4132ffc8bcaSDan McDonald 	con_log(CL_ANN1, (CE_NOTE,
4142ffc8bcaSDan McDonald 	    "request descriptor : 0x%08lx", (unsigned long)req_desc));
4152ffc8bcaSDan McDonald 
4162ffc8bcaSDan McDonald 	con_log(CL_ANN1, (CE_NOTE,
4172ffc8bcaSDan McDonald 	    "request descriptor base phy : 0x%08lx",
4182ffc8bcaSDan McDonald 	    (unsigned long)instance->request_message_pool_phy));
4192ffc8bcaSDan McDonald 
4202ffc8bcaSDan McDonald 	return ((MRSAS_REQUEST_DESCRIPTOR_UNION *)req_desc);
4212ffc8bcaSDan McDonald }
4222ffc8bcaSDan McDonald 
4232ffc8bcaSDan McDonald 
4242ffc8bcaSDan McDonald /*
4252ffc8bcaSDan McDonald  * Allocate Request and Reply  Queue Descriptors.
4262ffc8bcaSDan McDonald  */
4272ffc8bcaSDan McDonald int
alloc_req_rep_desc(struct mrsas_instance * instance)4282ffc8bcaSDan McDonald alloc_req_rep_desc(struct mrsas_instance *instance)
4292ffc8bcaSDan McDonald {
4302ffc8bcaSDan McDonald 	uint32_t	request_q_sz, reply_q_sz;
4312ffc8bcaSDan McDonald 	int		i, max_reply_q_sz;
4322ffc8bcaSDan McDonald 	MPI2_REPLY_DESCRIPTORS_UNION *reply_desc;
4332ffc8bcaSDan McDonald 
4342ffc8bcaSDan McDonald 	/*
4352ffc8bcaSDan McDonald 	 * ThunderBolt(TB) There's no longer producer consumer mechanism.
4362ffc8bcaSDan McDonald 	 * Once we have an interrupt we are supposed to scan through the list of
4372ffc8bcaSDan McDonald 	 * reply descriptors and process them accordingly. We would be needing
4382ffc8bcaSDan McDonald 	 * to allocate memory for 1024 reply descriptors
4392ffc8bcaSDan McDonald 	 */
4402ffc8bcaSDan McDonald 
4412ffc8bcaSDan McDonald 	/* Allocate Reply Descriptors */
4422ffc8bcaSDan McDonald 	con_log(CL_ANN1, (CE_NOTE, " reply q desc len = %x",
4432ffc8bcaSDan McDonald 	    (uint_t)sizeof (MPI2_REPLY_DESCRIPTORS_UNION)));
4442ffc8bcaSDan McDonald 
4452ffc8bcaSDan McDonald 	/* reply queue size should be multiple of 16 */
4462ffc8bcaSDan McDonald 	max_reply_q_sz = ((instance->max_fw_cmds + 1 + 15)/16)*16;
4472ffc8bcaSDan McDonald 
4482ffc8bcaSDan McDonald 	reply_q_sz = 8 * max_reply_q_sz;
4492ffc8bcaSDan McDonald 
4502ffc8bcaSDan McDonald 
4512ffc8bcaSDan McDonald 	con_log(CL_ANN1, (CE_NOTE, " reply q desc len = %x",
4522ffc8bcaSDan McDonald 	    (uint_t)sizeof (MPI2_REPLY_DESCRIPTORS_UNION)));
4532ffc8bcaSDan McDonald 
4542ffc8bcaSDan McDonald 	instance->reply_desc_dma_obj.size = reply_q_sz;
4552ffc8bcaSDan McDonald 	instance->reply_desc_dma_obj.dma_attr = mrsas_generic_dma_attr;
4562ffc8bcaSDan McDonald 	instance->reply_desc_dma_obj.dma_attr.dma_attr_addr_hi = 0xFFFFFFFFU;
4572ffc8bcaSDan McDonald 	instance->reply_desc_dma_obj.dma_attr.dma_attr_count_max = 0xFFFFFFFFU;
4582ffc8bcaSDan McDonald 	instance->reply_desc_dma_obj.dma_attr.dma_attr_sgllen = 1;
4592ffc8bcaSDan McDonald 	instance->reply_desc_dma_obj.dma_attr.dma_attr_align = 16;
4602ffc8bcaSDan McDonald 
4612ffc8bcaSDan McDonald 	if (mrsas_alloc_dma_obj(instance, &instance->reply_desc_dma_obj,
4622ffc8bcaSDan McDonald 	    (uchar_t)DDI_STRUCTURE_LE_ACC) != 1) {
463ff38cf9dSAndy Fiddaman 		dev_err(instance->dip, CE_WARN, "could not alloc reply queue");
4642ffc8bcaSDan McDonald 		return (DDI_FAILURE);
4652ffc8bcaSDan McDonald 	}
4662ffc8bcaSDan McDonald 
4672ffc8bcaSDan McDonald 	bzero(instance->reply_desc_dma_obj.buffer, reply_q_sz);
4682ffc8bcaSDan McDonald 	instance->reply_desc_dma_obj.status |= DMA_OBJ_ALLOCATED;
4692ffc8bcaSDan McDonald 
4702ffc8bcaSDan McDonald 	/* virtual address of  reply queue */
4712ffc8bcaSDan McDonald 	instance->reply_frame_pool = (MPI2_REPLY_DESCRIPTORS_UNION *)(
4722ffc8bcaSDan McDonald 	    instance->reply_desc_dma_obj.buffer);
4732ffc8bcaSDan McDonald 
4742ffc8bcaSDan McDonald 	instance->reply_q_depth = max_reply_q_sz;
4752ffc8bcaSDan McDonald 
4762ffc8bcaSDan McDonald 	con_log(CL_ANN1, (CE_NOTE, "[reply queue depth]0x%x",
4772ffc8bcaSDan McDonald 	    instance->reply_q_depth));
4782ffc8bcaSDan McDonald 
4792ffc8bcaSDan McDonald 	con_log(CL_ANN1, (CE_NOTE, "[reply queue virt addr]0x%p",
4802ffc8bcaSDan McDonald 	    (void *)instance->reply_frame_pool));
4812ffc8bcaSDan McDonald 
4822ffc8bcaSDan McDonald 	/* initializing reply address to 0xFFFFFFFF */
4832ffc8bcaSDan McDonald 	reply_desc = instance->reply_frame_pool;
4842ffc8bcaSDan McDonald 
4852ffc8bcaSDan McDonald 	for (i = 0; i < instance->reply_q_depth; i++) {
4862ffc8bcaSDan McDonald 		reply_desc->Words = (uint64_t)~0;
4872ffc8bcaSDan McDonald 		reply_desc++;
4882ffc8bcaSDan McDonald 	}
4892ffc8bcaSDan McDonald 
4902ffc8bcaSDan McDonald 
4912ffc8bcaSDan McDonald 	instance->reply_frame_pool_phy =
4922ffc8bcaSDan McDonald 	    (uint32_t)instance->reply_desc_dma_obj.dma_cookie[0].dmac_address;
4932ffc8bcaSDan McDonald 
4942ffc8bcaSDan McDonald 	con_log(CL_ANN1, (CE_NOTE,
4952ffc8bcaSDan McDonald 	    "[reply queue phys addr]0x%x", instance->reply_frame_pool_phy));
4962ffc8bcaSDan McDonald 
4972ffc8bcaSDan McDonald 
4982ffc8bcaSDan McDonald 	instance->reply_pool_limit_phy = (instance->reply_frame_pool_phy +
4992ffc8bcaSDan McDonald 	    reply_q_sz);
5002ffc8bcaSDan McDonald 
5012ffc8bcaSDan McDonald 	con_log(CL_ANN1, (CE_NOTE, "[reply pool limit phys addr]0x%x",
5022ffc8bcaSDan McDonald 	    instance->reply_pool_limit_phy));
5032ffc8bcaSDan McDonald 
5042ffc8bcaSDan McDonald 
5052ffc8bcaSDan McDonald 	con_log(CL_ANN1, (CE_NOTE, " request q desc len = %x",
5062ffc8bcaSDan McDonald 	    (int)sizeof (MRSAS_REQUEST_DESCRIPTOR_UNION)));
5072ffc8bcaSDan McDonald 
5082ffc8bcaSDan McDonald 	/* Allocate Request Descriptors */
5092ffc8bcaSDan McDonald 	con_log(CL_ANN1, (CE_NOTE, " request q desc len = %x",
5102ffc8bcaSDan McDonald 	    (int)sizeof (MRSAS_REQUEST_DESCRIPTOR_UNION)));
5112ffc8bcaSDan McDonald 
5122ffc8bcaSDan McDonald 	request_q_sz = 8 *
5132ffc8bcaSDan McDonald 	    (instance->max_fw_cmds);
5142ffc8bcaSDan McDonald 
5152ffc8bcaSDan McDonald 	instance->request_desc_dma_obj.size = request_q_sz;
5162ffc8bcaSDan McDonald 	instance->request_desc_dma_obj.dma_attr	= mrsas_generic_dma_attr;
5172ffc8bcaSDan McDonald 	instance->request_desc_dma_obj.dma_attr.dma_attr_addr_hi = 0xFFFFFFFFU;
5182ffc8bcaSDan McDonald 	instance->request_desc_dma_obj.dma_attr.dma_attr_count_max =
5192ffc8bcaSDan McDonald 	    0xFFFFFFFFU;
5202ffc8bcaSDan McDonald 	instance->request_desc_dma_obj.dma_attr.dma_attr_sgllen	= 1;
5212ffc8bcaSDan McDonald 	instance->request_desc_dma_obj.dma_attr.dma_attr_align = 16;
5222ffc8bcaSDan McDonald 
5232ffc8bcaSDan McDonald 	if (mrsas_alloc_dma_obj(instance, &instance->request_desc_dma_obj,
5242ffc8bcaSDan McDonald 	    (uchar_t)DDI_STRUCTURE_LE_ACC) != 1) {
525ff38cf9dSAndy Fiddaman 		dev_err(instance->dip, CE_WARN,
526ff38cf9dSAndy Fiddaman 		    "could not alloc request queue desc");
5272ffc8bcaSDan McDonald 		goto fail_undo_reply_queue;
5282ffc8bcaSDan McDonald 	}
5292ffc8bcaSDan McDonald 
5302ffc8bcaSDan McDonald 	bzero(instance->request_desc_dma_obj.buffer, request_q_sz);
5312ffc8bcaSDan McDonald 	instance->request_desc_dma_obj.status |= DMA_OBJ_ALLOCATED;
5322ffc8bcaSDan McDonald 
5332ffc8bcaSDan McDonald 	/* virtual address of  request queue desc */
5342ffc8bcaSDan McDonald 	instance->request_message_pool = (MRSAS_REQUEST_DESCRIPTOR_UNION *)
5352ffc8bcaSDan McDonald 	    (instance->request_desc_dma_obj.buffer);
5362ffc8bcaSDan McDonald 
5372ffc8bcaSDan McDonald 	instance->request_message_pool_phy =
5382ffc8bcaSDan McDonald 	    (uint32_t)instance->request_desc_dma_obj.dma_cookie[0].dmac_address;
5392ffc8bcaSDan McDonald 
5402ffc8bcaSDan McDonald 	return (DDI_SUCCESS);
5412ffc8bcaSDan McDonald 
5422ffc8bcaSDan McDonald fail_undo_reply_queue:
5432ffc8bcaSDan McDonald 	if (instance->reply_desc_dma_obj.status == DMA_OBJ_ALLOCATED) {
5442ffc8bcaSDan McDonald 		(void) mrsas_free_dma_obj(instance,
5452ffc8bcaSDan McDonald 		    instance->reply_desc_dma_obj);
5462ffc8bcaSDan McDonald 		instance->reply_desc_dma_obj.status = DMA_OBJ_FREED;
5472ffc8bcaSDan McDonald 	}
5482ffc8bcaSDan McDonald 
5492ffc8bcaSDan McDonald 	return (DDI_FAILURE);
5502ffc8bcaSDan McDonald }
5512ffc8bcaSDan McDonald 
5522ffc8bcaSDan McDonald /*
5532ffc8bcaSDan McDonald  * mrsas_alloc_cmd_pool_tbolt
5542ffc8bcaSDan McDonald  *
5552ffc8bcaSDan McDonald  * TODO: merge tbolt-specific code into mrsas_alloc_cmd_pool() to have single
5562ffc8bcaSDan McDonald  * routine
5572ffc8bcaSDan McDonald  */
5582ffc8bcaSDan McDonald int
mrsas_alloc_cmd_pool_tbolt(struct mrsas_instance * instance)5592ffc8bcaSDan McDonald mrsas_alloc_cmd_pool_tbolt(struct mrsas_instance *instance)
5602ffc8bcaSDan McDonald {
5612ffc8bcaSDan McDonald 	int		i;
5622ffc8bcaSDan McDonald 	int		count;
5632ffc8bcaSDan McDonald 	uint32_t	max_cmd;
5642ffc8bcaSDan McDonald 	uint32_t	reserve_cmd;
5652ffc8bcaSDan McDonald 	size_t		sz;
5662ffc8bcaSDan McDonald 
5672ffc8bcaSDan McDonald 	struct mrsas_cmd	*cmd;
5682ffc8bcaSDan McDonald 
5692ffc8bcaSDan McDonald 	max_cmd = instance->max_fw_cmds;
5702ffc8bcaSDan McDonald 	con_log(CL_ANN1, (CE_NOTE, "mrsas_alloc_cmd_pool: "
5712ffc8bcaSDan McDonald 	    "max_cmd %x", max_cmd));
5722ffc8bcaSDan McDonald 
5732ffc8bcaSDan McDonald 
5742ffc8bcaSDan McDonald 	sz = sizeof (struct mrsas_cmd *) * max_cmd;
5752ffc8bcaSDan McDonald 
5762ffc8bcaSDan McDonald 	/*
5772ffc8bcaSDan McDonald 	 * instance->cmd_list is an array of struct mrsas_cmd pointers.
5782ffc8bcaSDan McDonald 	 * Allocate the dynamic array first and then allocate individual
5792ffc8bcaSDan McDonald 	 * commands.
5802ffc8bcaSDan McDonald 	 */
5812ffc8bcaSDan McDonald 	instance->cmd_list = kmem_zalloc(sz, KM_SLEEP);
5822ffc8bcaSDan McDonald 
5832ffc8bcaSDan McDonald 	/* create a frame pool and assign one frame to each cmd */
5842ffc8bcaSDan McDonald 	for (count = 0; count < max_cmd; count++) {
5852ffc8bcaSDan McDonald 		instance->cmd_list[count] =
5862ffc8bcaSDan McDonald 		    kmem_zalloc(sizeof (struct mrsas_cmd), KM_SLEEP);
5872ffc8bcaSDan McDonald 	}
5882ffc8bcaSDan McDonald 
5892ffc8bcaSDan McDonald 	/* add all the commands to command pool */
5902ffc8bcaSDan McDonald 
5912ffc8bcaSDan McDonald 	INIT_LIST_HEAD(&instance->cmd_pool_list);
5922ffc8bcaSDan McDonald 	INIT_LIST_HEAD(&instance->cmd_pend_list);
5932ffc8bcaSDan McDonald 	INIT_LIST_HEAD(&instance->cmd_app_pool_list);
5942ffc8bcaSDan McDonald 
5952ffc8bcaSDan McDonald 	reserve_cmd = MRSAS_APP_RESERVED_CMDS;
5962ffc8bcaSDan McDonald 
5972ffc8bcaSDan McDonald 	/* cmd index 0 reservered for IOC INIT */
5982ffc8bcaSDan McDonald 	for (i = 1; i < reserve_cmd; i++) {
5992ffc8bcaSDan McDonald 		cmd		= instance->cmd_list[i];
6002ffc8bcaSDan McDonald 		cmd->index	= i;
6012ffc8bcaSDan McDonald 		mlist_add_tail(&cmd->list, &instance->cmd_app_pool_list);
6022ffc8bcaSDan McDonald 	}
6032ffc8bcaSDan McDonald 
6042ffc8bcaSDan McDonald 
6052ffc8bcaSDan McDonald 	for (i = reserve_cmd; i < max_cmd; i++) {
6062ffc8bcaSDan McDonald 		cmd		= instance->cmd_list[i];
6072ffc8bcaSDan McDonald 		cmd->index	= i;
6082ffc8bcaSDan McDonald 		mlist_add_tail(&cmd->list, &instance->cmd_pool_list);
6092ffc8bcaSDan McDonald 	}
6102ffc8bcaSDan McDonald 
6112ffc8bcaSDan McDonald 	return (DDI_SUCCESS);
6122ffc8bcaSDan McDonald 
6132ffc8bcaSDan McDonald mrsas_undo_cmds:
6142ffc8bcaSDan McDonald 	if (count > 0) {
6152ffc8bcaSDan McDonald 		/* free each cmd */
6162ffc8bcaSDan McDonald 		for (i = 0; i < count; i++) {
6172ffc8bcaSDan McDonald 			if (instance->cmd_list[i] != NULL) {
6182ffc8bcaSDan McDonald 				kmem_free(instance->cmd_list[i],
6192ffc8bcaSDan McDonald 				    sizeof (struct mrsas_cmd));
6202ffc8bcaSDan McDonald 			}
6212ffc8bcaSDan McDonald 			instance->cmd_list[i] = NULL;
6222ffc8bcaSDan McDonald 		}
6232ffc8bcaSDan McDonald 	}
6242ffc8bcaSDan McDonald 
6252ffc8bcaSDan McDonald mrsas_undo_cmd_list:
6262ffc8bcaSDan McDonald 	if (instance->cmd_list != NULL)
6272ffc8bcaSDan McDonald 		kmem_free(instance->cmd_list, sz);
6282ffc8bcaSDan McDonald 	instance->cmd_list = NULL;
6292ffc8bcaSDan McDonald 
6302ffc8bcaSDan McDonald 	return (DDI_FAILURE);
6312ffc8bcaSDan McDonald }
6322ffc8bcaSDan McDonald 
6332ffc8bcaSDan McDonald 
6342ffc8bcaSDan McDonald /*
6352ffc8bcaSDan McDonald  * free_space_for_mpi2
6362ffc8bcaSDan McDonald  */
6372ffc8bcaSDan McDonald void
free_space_for_mpi2(struct mrsas_instance * instance)6382ffc8bcaSDan McDonald free_space_for_mpi2(struct mrsas_instance *instance)
6392ffc8bcaSDan McDonald {
6402ffc8bcaSDan McDonald 	/* already freed */
6412ffc8bcaSDan McDonald 	if (instance->cmd_list == NULL) {
6422ffc8bcaSDan McDonald 		return;
6432ffc8bcaSDan McDonald 	}
6442ffc8bcaSDan McDonald 
6452ffc8bcaSDan McDonald 	/* First free the additional DMA buffer */
6462ffc8bcaSDan McDonald 	mrsas_tbolt_free_additional_dma_buffer(instance);
6472ffc8bcaSDan McDonald 
6482ffc8bcaSDan McDonald 	/* Free the request/reply descriptor pool */
6492ffc8bcaSDan McDonald 	free_req_rep_desc_pool(instance);
6502ffc8bcaSDan McDonald 
6512ffc8bcaSDan McDonald 	/*  Free the MPI message pool */
6522ffc8bcaSDan McDonald 	destroy_mpi2_frame_pool(instance);
6532ffc8bcaSDan McDonald 
6542ffc8bcaSDan McDonald 	/* Free the MFI frame pool */
6552ffc8bcaSDan McDonald 	destroy_mfi_frame_pool(instance);
6562ffc8bcaSDan McDonald 
6572ffc8bcaSDan McDonald 	/* Free all the commands in the cmd_list */
6582ffc8bcaSDan McDonald 	/* Free the cmd_list buffer itself */
6592ffc8bcaSDan McDonald 	mrsas_free_cmd_pool(instance);
6602ffc8bcaSDan McDonald }
6612ffc8bcaSDan McDonald 
6622ffc8bcaSDan McDonald 
6632ffc8bcaSDan McDonald /*
6642ffc8bcaSDan McDonald  * ThunderBolt(TB) memory allocations for commands/messages/frames.
6652ffc8bcaSDan McDonald  */
6662ffc8bcaSDan McDonald int
alloc_space_for_mpi2(struct mrsas_instance * instance)6672ffc8bcaSDan McDonald alloc_space_for_mpi2(struct mrsas_instance *instance)
6682ffc8bcaSDan McDonald {
6692ffc8bcaSDan McDonald 	/* Allocate command pool (memory for cmd_list & individual commands) */
6702ffc8bcaSDan McDonald 	if (mrsas_alloc_cmd_pool_tbolt(instance)) {
671ff38cf9dSAndy Fiddaman 		dev_err(instance->dip, CE_WARN, "Error creating cmd pool");
6722ffc8bcaSDan McDonald 		return (DDI_FAILURE);
6732ffc8bcaSDan McDonald 	}
6742ffc8bcaSDan McDonald 
6752ffc8bcaSDan McDonald 	/* Initialize single reply size and Message size */
6762ffc8bcaSDan McDonald 	instance->reply_size = MRSAS_THUNDERBOLT_REPLY_SIZE;
6772ffc8bcaSDan McDonald 	instance->raid_io_msg_size = MRSAS_THUNDERBOLT_MSG_SIZE;
6782ffc8bcaSDan McDonald 
6792ffc8bcaSDan McDonald 	instance->max_sge_in_main_msg = (MRSAS_THUNDERBOLT_MSG_SIZE -
6802ffc8bcaSDan McDonald 	    (sizeof (MPI2_RAID_SCSI_IO_REQUEST) -
6812ffc8bcaSDan McDonald 	    sizeof (MPI2_SGE_IO_UNION)))/ sizeof (MPI2_SGE_IO_UNION);
6822ffc8bcaSDan McDonald 	instance->max_sge_in_chain = (MR_COMMAND_SIZE -
6832ffc8bcaSDan McDonald 	    MRSAS_THUNDERBOLT_MSG_SIZE) / sizeof (MPI2_SGE_IO_UNION);
6842ffc8bcaSDan McDonald 
6852ffc8bcaSDan McDonald 	/* Reduce SG count by 1 to take care of group cmds feature in FW */
6862ffc8bcaSDan McDonald 	instance->max_num_sge = (instance->max_sge_in_main_msg +
6872ffc8bcaSDan McDonald 	    instance->max_sge_in_chain - 2);
6882ffc8bcaSDan McDonald 	instance->chain_offset_mpt_msg =
6892ffc8bcaSDan McDonald 	    offsetof(MPI2_RAID_SCSI_IO_REQUEST, SGL) / 16;
6902ffc8bcaSDan McDonald 	instance->chain_offset_io_req = (MRSAS_THUNDERBOLT_MSG_SIZE -
6912ffc8bcaSDan McDonald 	    sizeof (MPI2_SGE_IO_UNION)) / 16;
6922ffc8bcaSDan McDonald 	instance->reply_read_index = 0;
6932ffc8bcaSDan McDonald 
6942ffc8bcaSDan McDonald 
6952ffc8bcaSDan McDonald 	/* Allocate Request and Reply descriptors Array */
6962ffc8bcaSDan McDonald 	/* Make sure the buffer is aligned to 8 for req/rep  descriptor Pool */
6972ffc8bcaSDan McDonald 	if (alloc_req_rep_desc(instance)) {
698ff38cf9dSAndy Fiddaman 		dev_err(instance->dip, CE_WARN,
6992ffc8bcaSDan McDonald 		    "Error, allocating memory for descripter-pool");
7002ffc8bcaSDan McDonald 		goto mpi2_undo_cmd_pool;
7012ffc8bcaSDan McDonald 	}
7022ffc8bcaSDan McDonald 	con_log(CL_ANN1, (CE_NOTE, "[request message pool phys addr]0x%x",
7032ffc8bcaSDan McDonald 	    instance->request_message_pool_phy));
7042ffc8bcaSDan McDonald 
7052ffc8bcaSDan McDonald 
7062ffc8bcaSDan McDonald 	/* Allocate MFI Frame pool - for MPI-MFI passthru commands */
7072ffc8bcaSDan McDonald 	if (create_mfi_frame_pool(instance)) {
708ff38cf9dSAndy Fiddaman 		dev_err(instance->dip, CE_WARN,
7092ffc8bcaSDan McDonald 		    "Error, allocating memory for MFI frame-pool");
7102ffc8bcaSDan McDonald 		goto mpi2_undo_descripter_pool;
7112ffc8bcaSDan McDonald 	}
7122ffc8bcaSDan McDonald 
7132ffc8bcaSDan McDonald 
7142ffc8bcaSDan McDonald 	/* Allocate MPI2 Message pool */
7152ffc8bcaSDan McDonald 	/*
7162ffc8bcaSDan McDonald 	 * Make sure the buffer is alligned to 256 for raid message packet
7172ffc8bcaSDan McDonald 	 * create a io request pool and assign one frame to each cmd
7182ffc8bcaSDan McDonald 	 */
7192ffc8bcaSDan McDonald 
7202ffc8bcaSDan McDonald 	if (create_mpi2_frame_pool(instance)) {
721ff38cf9dSAndy Fiddaman 		dev_err(instance->dip, CE_WARN,
7222ffc8bcaSDan McDonald 		    "Error, allocating memory for MPI2 Message-pool");
7232ffc8bcaSDan McDonald 		goto mpi2_undo_mfi_frame_pool;
7242ffc8bcaSDan McDonald 	}
7252ffc8bcaSDan McDonald 
7262ffc8bcaSDan McDonald #ifdef DEBUG
7272ffc8bcaSDan McDonald 	con_log(CL_ANN1, (CE_CONT, "[max_sge_in_main_msg]0x%x",
7282ffc8bcaSDan McDonald 	    instance->max_sge_in_main_msg));
7292ffc8bcaSDan McDonald 	con_log(CL_ANN1, (CE_CONT, "[max_sge_in_chain]0x%x",
7302ffc8bcaSDan McDonald 	    instance->max_sge_in_chain));
7312ffc8bcaSDan McDonald 	con_log(CL_ANN1, (CE_CONT,
7322ffc8bcaSDan McDonald 	    "[max_sge]0x%x", instance->max_num_sge));
7332ffc8bcaSDan McDonald 	con_log(CL_ANN1, (CE_CONT, "[chain_offset_mpt_msg]0x%x",
7342ffc8bcaSDan McDonald 	    instance->chain_offset_mpt_msg));
7352ffc8bcaSDan McDonald 	con_log(CL_ANN1, (CE_CONT, "[chain_offset_io_req]0x%x",
7362ffc8bcaSDan McDonald 	    instance->chain_offset_io_req));
7372ffc8bcaSDan McDonald #endif
7382ffc8bcaSDan McDonald 
7392ffc8bcaSDan McDonald 
7402ffc8bcaSDan McDonald 	/* Allocate additional dma buffer */
7412ffc8bcaSDan McDonald 	if (mrsas_tbolt_alloc_additional_dma_buffer(instance)) {
742ff38cf9dSAndy Fiddaman 		dev_err(instance->dip, CE_WARN,
7432ffc8bcaSDan McDonald 		    "Error, allocating tbolt additional DMA buffer");
7442ffc8bcaSDan McDonald 		goto mpi2_undo_message_pool;
7452ffc8bcaSDan McDonald 	}
7462ffc8bcaSDan McDonald 
7472ffc8bcaSDan McDonald 	return (DDI_SUCCESS);
7482ffc8bcaSDan McDonald 
7492ffc8bcaSDan McDonald mpi2_undo_message_pool:
7502ffc8bcaSDan McDonald 	destroy_mpi2_frame_pool(instance);
7512ffc8bcaSDan McDonald 
7522ffc8bcaSDan McDonald mpi2_undo_mfi_frame_pool:
7532ffc8bcaSDan McDonald 	destroy_mfi_frame_pool(instance);
7542ffc8bcaSDan McDonald 
7552ffc8bcaSDan McDonald mpi2_undo_descripter_pool:
7562ffc8bcaSDan McDonald 	free_req_rep_desc_pool(instance);
7572ffc8bcaSDan McDonald 
7582ffc8bcaSDan McDonald mpi2_undo_cmd_pool:
7592ffc8bcaSDan McDonald 	mrsas_free_cmd_pool(instance);
7602ffc8bcaSDan McDonald 
7612ffc8bcaSDan McDonald 	return (DDI_FAILURE);
7622ffc8bcaSDan McDonald }
7632ffc8bcaSDan McDonald 
7642ffc8bcaSDan McDonald 
7652ffc8bcaSDan McDonald /*
7662ffc8bcaSDan McDonald  * mrsas_init_adapter_tbolt - Initialize fusion interface adapter.
7672ffc8bcaSDan McDonald  */
7682ffc8bcaSDan McDonald int
mrsas_init_adapter_tbolt(struct mrsas_instance * instance)7692ffc8bcaSDan McDonald mrsas_init_adapter_tbolt(struct mrsas_instance *instance)
7702ffc8bcaSDan McDonald {
7712ffc8bcaSDan McDonald 
7722ffc8bcaSDan McDonald 	/*
7732ffc8bcaSDan McDonald 	 * Reduce the max supported cmds by 1. This is to ensure that the
7742ffc8bcaSDan McDonald 	 * reply_q_sz (1 more than the max cmd that driver may send)
7752ffc8bcaSDan McDonald 	 * does not exceed max cmds that the FW can support
7762ffc8bcaSDan McDonald 	 */
7772ffc8bcaSDan McDonald 
7782ffc8bcaSDan McDonald 	if (instance->max_fw_cmds > 1008) {
7792ffc8bcaSDan McDonald 		instance->max_fw_cmds = 1008;
7802ffc8bcaSDan McDonald 		instance->max_fw_cmds = instance->max_fw_cmds-1;
7812ffc8bcaSDan McDonald 	}
7822ffc8bcaSDan McDonald 
7832ffc8bcaSDan McDonald 	con_log(CL_ANN, (CE_NOTE, "mrsas_init_adapter_tbolt: "
7842ffc8bcaSDan McDonald 	    "instance->max_fw_cmds 0x%X.", instance->max_fw_cmds));
7852ffc8bcaSDan McDonald 
7862ffc8bcaSDan McDonald 
7872ffc8bcaSDan McDonald 	/* create a pool of commands */
7882ffc8bcaSDan McDonald 	if (alloc_space_for_mpi2(instance) != DDI_SUCCESS) {
789ff38cf9dSAndy Fiddaman 		dev_err(instance->dip, CE_WARN,
7902ffc8bcaSDan McDonald 		    "alloc_space_for_mpi2() failed.");
7912ffc8bcaSDan McDonald 
7922ffc8bcaSDan McDonald 		return (DDI_FAILURE);
7932ffc8bcaSDan McDonald 	}
7942ffc8bcaSDan McDonald 
7952ffc8bcaSDan McDonald 	/* Send ioc init message */
7962ffc8bcaSDan McDonald 	/* NOTE: the issue_init call does FMA checking already. */
7972ffc8bcaSDan McDonald 	if (mrsas_issue_init_mpi2(instance) != DDI_SUCCESS) {
798ff38cf9dSAndy Fiddaman 		dev_err(instance->dip, CE_WARN,
7992ffc8bcaSDan McDonald 		    "mrsas_issue_init_mpi2() failed.");
8002ffc8bcaSDan McDonald 
8012ffc8bcaSDan McDonald 		goto fail_init_fusion;
8022ffc8bcaSDan McDonald 	}
8032ffc8bcaSDan McDonald 
8042ffc8bcaSDan McDonald 	instance->unroll.alloc_space_mpi2 = 1;
8052ffc8bcaSDan McDonald 
8062ffc8bcaSDan McDonald 	con_log(CL_ANN, (CE_NOTE,
8072ffc8bcaSDan McDonald 	    "mrsas_init_adapter_tbolt: SUCCESSFUL"));
8082ffc8bcaSDan McDonald 
8092ffc8bcaSDan McDonald 	return (DDI_SUCCESS);
8102ffc8bcaSDan McDonald 
8112ffc8bcaSDan McDonald fail_init_fusion:
8122ffc8bcaSDan McDonald 	free_space_for_mpi2(instance);
8132ffc8bcaSDan McDonald 
8142ffc8bcaSDan McDonald 	return (DDI_FAILURE);
8152ffc8bcaSDan McDonald }
8162ffc8bcaSDan McDonald 
8172ffc8bcaSDan McDonald 
8182ffc8bcaSDan McDonald 
8192ffc8bcaSDan McDonald /*
8202ffc8bcaSDan McDonald  * init_mpi2
8212ffc8bcaSDan McDonald  */
8222ffc8bcaSDan McDonald int
mrsas_issue_init_mpi2(struct mrsas_instance * instance)8232ffc8bcaSDan McDonald mrsas_issue_init_mpi2(struct mrsas_instance *instance)
8242ffc8bcaSDan McDonald {
8252ffc8bcaSDan McDonald 	dma_obj_t init2_dma_obj;
8262ffc8bcaSDan McDonald 	int ret_val = DDI_SUCCESS;
8272ffc8bcaSDan McDonald 
8282ffc8bcaSDan McDonald 	/* allocate DMA buffer for IOC INIT message */
8292ffc8bcaSDan McDonald 	init2_dma_obj.size = sizeof (Mpi2IOCInitRequest_t);
8302ffc8bcaSDan McDonald 	init2_dma_obj.dma_attr = mrsas_generic_dma_attr;
8312ffc8bcaSDan McDonald 	init2_dma_obj.dma_attr.dma_attr_addr_hi = 0xFFFFFFFFU;
8322ffc8bcaSDan McDonald 	init2_dma_obj.dma_attr.dma_attr_count_max = 0xFFFFFFFFU;
8332ffc8bcaSDan McDonald 	init2_dma_obj.dma_attr.dma_attr_sgllen = 1;
8342ffc8bcaSDan McDonald 	init2_dma_obj.dma_attr.dma_attr_align = 256;
8352ffc8bcaSDan McDonald 
8362ffc8bcaSDan McDonald 	if (mrsas_alloc_dma_obj(instance, &init2_dma_obj,
8372ffc8bcaSDan McDonald 	    (uchar_t)DDI_STRUCTURE_LE_ACC) != 1) {
838ff38cf9dSAndy Fiddaman 		dev_err(instance->dip, CE_WARN, "mr_sas_issue_init_mpi2 "
8392ffc8bcaSDan McDonald 		    "could not allocate data transfer buffer.");
8402ffc8bcaSDan McDonald 		return (DDI_FAILURE);
8412ffc8bcaSDan McDonald 	}
8422ffc8bcaSDan McDonald 	(void) memset(init2_dma_obj.buffer, 2, sizeof (Mpi2IOCInitRequest_t));
8432ffc8bcaSDan McDonald 
8442ffc8bcaSDan McDonald 	con_log(CL_ANN1, (CE_NOTE,
8452ffc8bcaSDan McDonald 	    "mrsas_issue_init_mpi2 _phys adr: %x",
8462ffc8bcaSDan McDonald 	    init2_dma_obj.dma_cookie[0].dmac_address));
8472ffc8bcaSDan McDonald 
8482ffc8bcaSDan McDonald 
8492ffc8bcaSDan McDonald 	/* Initialize and send ioc init message */
8502ffc8bcaSDan McDonald 	ret_val = mrsas_tbolt_ioc_init(instance, &init2_dma_obj);
8512ffc8bcaSDan McDonald 	if (ret_val == DDI_FAILURE) {
8522ffc8bcaSDan McDonald 		con_log(CL_ANN1, (CE_WARN,
8532ffc8bcaSDan McDonald 		    "mrsas_issue_init_mpi2: Failed"));
8542ffc8bcaSDan McDonald 		goto fail_init_mpi2;
8552ffc8bcaSDan McDonald 	}
8562ffc8bcaSDan McDonald 
8572ffc8bcaSDan McDonald 	/* free IOC init DMA buffer */
8582ffc8bcaSDan McDonald 	if (mrsas_free_dma_obj(instance, init2_dma_obj)
8592ffc8bcaSDan McDonald 	    != DDI_SUCCESS) {
8602ffc8bcaSDan McDonald 		con_log(CL_ANN1, (CE_WARN,
8612ffc8bcaSDan McDonald 		    "mrsas_issue_init_mpi2: Free Failed"));
8622ffc8bcaSDan McDonald 		return (DDI_FAILURE);
8632ffc8bcaSDan McDonald 	}
8642ffc8bcaSDan McDonald 
8652ffc8bcaSDan McDonald 	/* Get/Check and sync ld_map info */
8662ffc8bcaSDan McDonald 	instance->map_id = 0;
8672ffc8bcaSDan McDonald 	if (mrsas_tbolt_check_map_info(instance) == DDI_SUCCESS)
8682ffc8bcaSDan McDonald 		(void) mrsas_tbolt_sync_map_info(instance);
8692ffc8bcaSDan McDonald 
8702ffc8bcaSDan McDonald 
8712ffc8bcaSDan McDonald 	/* No mrsas_cmd to send, so send NULL. */
8722ffc8bcaSDan McDonald 	if (mrsas_common_check(instance, NULL) != DDI_SUCCESS)
8732ffc8bcaSDan McDonald 		goto fail_init_mpi2;
8742ffc8bcaSDan McDonald 
8752ffc8bcaSDan McDonald 	con_log(CL_ANN, (CE_NOTE,
8762ffc8bcaSDan McDonald 	    "mrsas_issue_init_mpi2: SUCCESSFUL"));
8772ffc8bcaSDan McDonald 
8782ffc8bcaSDan McDonald 	return (DDI_SUCCESS);
8792ffc8bcaSDan McDonald 
8802ffc8bcaSDan McDonald fail_init_mpi2:
8812ffc8bcaSDan McDonald 	(void) mrsas_free_dma_obj(instance, init2_dma_obj);
8822ffc8bcaSDan McDonald 
8832ffc8bcaSDan McDonald 	return (DDI_FAILURE);
8842ffc8bcaSDan McDonald }
8852ffc8bcaSDan McDonald 
8862ffc8bcaSDan McDonald static int
mrsas_tbolt_ioc_init(struct mrsas_instance * instance,dma_obj_t * mpi2_dma_obj)8872ffc8bcaSDan McDonald mrsas_tbolt_ioc_init(struct mrsas_instance *instance, dma_obj_t *mpi2_dma_obj)
8882ffc8bcaSDan McDonald {
8892ffc8bcaSDan McDonald 	int				numbytes;
8902ffc8bcaSDan McDonald 	uint16_t			flags;
8912ffc8bcaSDan McDonald 	struct mrsas_init_frame2	*mfiFrameInit2;
8922ffc8bcaSDan McDonald 	struct mrsas_header		*frame_hdr;
8932ffc8bcaSDan McDonald 	Mpi2IOCInitRequest_t		*init;
8942ffc8bcaSDan McDonald 	struct mrsas_cmd		*cmd = NULL;
8952ffc8bcaSDan McDonald 	struct mrsas_drv_ver		drv_ver_info;
8964bc492d2SAndy Fiddaman 	MRSAS_REQUEST_DESCRIPTOR_UNION	req_desc;
8974bc492d2SAndy Fiddaman 	uint32_t			timeout;
8982ffc8bcaSDan McDonald 
8992ffc8bcaSDan McDonald 	con_log(CL_ANN, (CE_NOTE, "chkpnt:%s:%d", __func__, __LINE__));
9002ffc8bcaSDan McDonald 
9012ffc8bcaSDan McDonald 
9022ffc8bcaSDan McDonald #ifdef DEBUG
9032ffc8bcaSDan McDonald 	con_log(CL_ANN1, (CE_CONT, " mfiFrameInit2 len = %x\n",
9042ffc8bcaSDan McDonald 	    (int)sizeof (*mfiFrameInit2)));
9052ffc8bcaSDan McDonald 	con_log(CL_ANN1, (CE_CONT, " MPI len = %x\n", (int)sizeof (*init)));
9062ffc8bcaSDan McDonald 	con_log(CL_ANN1, (CE_CONT, " mfiFrameInit2 len = %x\n",
9072ffc8bcaSDan McDonald 	    (int)sizeof (struct mrsas_init_frame2)));
9082ffc8bcaSDan McDonald 	con_log(CL_ANN1, (CE_CONT, " MPI len = %x\n",
9092ffc8bcaSDan McDonald 	    (int)sizeof (Mpi2IOCInitRequest_t)));
9102ffc8bcaSDan McDonald #endif
9112ffc8bcaSDan McDonald 
9122ffc8bcaSDan McDonald 	init = (Mpi2IOCInitRequest_t *)mpi2_dma_obj->buffer;
9132ffc8bcaSDan McDonald 	numbytes = sizeof (*init);
9142ffc8bcaSDan McDonald 	bzero(init, numbytes);
9152ffc8bcaSDan McDonald 
9162ffc8bcaSDan McDonald 	ddi_put8(mpi2_dma_obj->acc_handle, &init->Function,
9172ffc8bcaSDan McDonald 	    MPI2_FUNCTION_IOC_INIT);
9182ffc8bcaSDan McDonald 
9192ffc8bcaSDan McDonald 	ddi_put8(mpi2_dma_obj->acc_handle, &init->WhoInit,
9202ffc8bcaSDan McDonald 	    MPI2_WHOINIT_HOST_DRIVER);
9212ffc8bcaSDan McDonald 
9222ffc8bcaSDan McDonald 	/* set MsgVersion and HeaderVersion host driver was built with */
9232ffc8bcaSDan McDonald 	ddi_put16(mpi2_dma_obj->acc_handle, &init->MsgVersion,
9242ffc8bcaSDan McDonald 	    MPI2_VERSION);
9252ffc8bcaSDan McDonald 
9262ffc8bcaSDan McDonald 	ddi_put16(mpi2_dma_obj->acc_handle, &init->HeaderVersion,
9272ffc8bcaSDan McDonald 	    MPI2_HEADER_VERSION);
9282ffc8bcaSDan McDonald 
9292ffc8bcaSDan McDonald 	ddi_put16(mpi2_dma_obj->acc_handle, &init->SystemRequestFrameSize,
9302ffc8bcaSDan McDonald 	    instance->raid_io_msg_size / 4);
9312ffc8bcaSDan McDonald 
9322ffc8bcaSDan McDonald 	ddi_put16(mpi2_dma_obj->acc_handle, &init->ReplyFreeQueueDepth,
9332ffc8bcaSDan McDonald 	    0);
9342ffc8bcaSDan McDonald 
9352ffc8bcaSDan McDonald 	ddi_put16(mpi2_dma_obj->acc_handle,
9362ffc8bcaSDan McDonald 	    &init->ReplyDescriptorPostQueueDepth,
9372ffc8bcaSDan McDonald 	    instance->reply_q_depth);
9382ffc8bcaSDan McDonald 	/*
9392ffc8bcaSDan McDonald 	 * These addresses are set using the DMA cookie addresses from when the
9402ffc8bcaSDan McDonald 	 * memory was allocated.  Sense buffer hi address should be 0.
9412ffc8bcaSDan McDonald 	 * ddi_put32(accessp, &init->SenseBufferAddressHigh, 0);
9422ffc8bcaSDan McDonald 	 */
9432ffc8bcaSDan McDonald 
9442ffc8bcaSDan McDonald 	ddi_put32(mpi2_dma_obj->acc_handle,
9452ffc8bcaSDan McDonald 	    &init->SenseBufferAddressHigh, 0);
9462ffc8bcaSDan McDonald 
9472ffc8bcaSDan McDonald 	ddi_put64(mpi2_dma_obj->acc_handle,
9482ffc8bcaSDan McDonald 	    (uint64_t *)&init->SystemRequestFrameBaseAddress,
9492ffc8bcaSDan McDonald 	    instance->io_request_frames_phy);
9502ffc8bcaSDan McDonald 
9512ffc8bcaSDan McDonald 	ddi_put64(mpi2_dma_obj->acc_handle,
9522ffc8bcaSDan McDonald 	    &init->ReplyDescriptorPostQueueAddress,
9532ffc8bcaSDan McDonald 	    instance->reply_frame_pool_phy);
9542ffc8bcaSDan McDonald 
9552ffc8bcaSDan McDonald 	ddi_put64(mpi2_dma_obj->acc_handle,
9562ffc8bcaSDan McDonald 	    &init->ReplyFreeQueueAddress, 0);
9572ffc8bcaSDan McDonald 
9582ffc8bcaSDan McDonald 	cmd = instance->cmd_list[0];
9592ffc8bcaSDan McDonald 	if (cmd == NULL) {
9602ffc8bcaSDan McDonald 		return (DDI_FAILURE);
9612ffc8bcaSDan McDonald 	}
9622ffc8bcaSDan McDonald 	cmd->retry_count_for_ocr = 0;
9632ffc8bcaSDan McDonald 	cmd->pkt = NULL;
9642ffc8bcaSDan McDonald 	cmd->drv_pkt_time = 0;
9652ffc8bcaSDan McDonald 
9662ffc8bcaSDan McDonald 	mfiFrameInit2 = (struct mrsas_init_frame2 *)cmd->scsi_io_request;
9672ffc8bcaSDan McDonald 	con_log(CL_ANN1, (CE_CONT, "[mfi vaddr]%p", (void *)mfiFrameInit2));
9682ffc8bcaSDan McDonald 
9692ffc8bcaSDan McDonald 	frame_hdr = &cmd->frame->hdr;
9702ffc8bcaSDan McDonald 
9712ffc8bcaSDan McDonald 	ddi_put8(cmd->frame_dma_obj.acc_handle, &frame_hdr->cmd_status,
9722ffc8bcaSDan McDonald 	    MFI_CMD_STATUS_POLL_MODE);
9732ffc8bcaSDan McDonald 
9742ffc8bcaSDan McDonald 	flags = ddi_get16(cmd->frame_dma_obj.acc_handle, &frame_hdr->flags);
9752ffc8bcaSDan McDonald 
9762ffc8bcaSDan McDonald 	flags	|= MFI_FRAME_DONT_POST_IN_REPLY_QUEUE;
9772ffc8bcaSDan McDonald 
9782ffc8bcaSDan McDonald 	ddi_put16(cmd->frame_dma_obj.acc_handle, &frame_hdr->flags, flags);
9792ffc8bcaSDan McDonald 
9802ffc8bcaSDan McDonald 	con_log(CL_ANN, (CE_CONT,
9812ffc8bcaSDan McDonald 	    "mrsas_tbolt_ioc_init: SMID:%x\n", cmd->SMID));
9822ffc8bcaSDan McDonald 
9832ffc8bcaSDan McDonald 	/* Init the MFI Header */
9842ffc8bcaSDan McDonald 	ddi_put8(instance->mpi2_frame_pool_dma_obj.acc_handle,
9852ffc8bcaSDan McDonald 	    &mfiFrameInit2->cmd, MFI_CMD_OP_INIT);
9862ffc8bcaSDan McDonald 
9872ffc8bcaSDan McDonald 	con_log(CL_ANN1, (CE_CONT, "[CMD]%x", mfiFrameInit2->cmd));
9882ffc8bcaSDan McDonald 
9892ffc8bcaSDan McDonald 	ddi_put8(instance->mpi2_frame_pool_dma_obj.acc_handle,
9902ffc8bcaSDan McDonald 	    &mfiFrameInit2->cmd_status,
9912ffc8bcaSDan McDonald 	    MFI_STAT_INVALID_STATUS);
9922ffc8bcaSDan McDonald 
9932ffc8bcaSDan McDonald 	con_log(CL_ANN1, (CE_CONT, "[Status]%x", mfiFrameInit2->cmd_status));
9942ffc8bcaSDan McDonald 
9952ffc8bcaSDan McDonald 	ddi_put32(instance->mpi2_frame_pool_dma_obj.acc_handle,
9962ffc8bcaSDan McDonald 	    &mfiFrameInit2->queue_info_new_phys_addr_lo,
9972ffc8bcaSDan McDonald 	    mpi2_dma_obj->dma_cookie[0].dmac_address);
9982ffc8bcaSDan McDonald 
9992ffc8bcaSDan McDonald 	ddi_put32(instance->mpi2_frame_pool_dma_obj.acc_handle,
10002ffc8bcaSDan McDonald 	    &mfiFrameInit2->data_xfer_len,
10012ffc8bcaSDan McDonald 	    sizeof (Mpi2IOCInitRequest_t));
10022ffc8bcaSDan McDonald 
10032ffc8bcaSDan McDonald 	con_log(CL_ANN1, (CE_CONT, "[reply q desc addr]%x",
10042ffc8bcaSDan McDonald 	    (int)init->ReplyDescriptorPostQueueAddress));
10052ffc8bcaSDan McDonald 
10062ffc8bcaSDan McDonald 	/* fill driver version information */
10072ffc8bcaSDan McDonald 	fill_up_drv_ver(&drv_ver_info);
10082ffc8bcaSDan McDonald 
10092ffc8bcaSDan McDonald 	/* allocate the driver version data transfer buffer */
10102ffc8bcaSDan McDonald 	instance->drv_ver_dma_obj.size = sizeof (drv_ver_info.drv_ver);
10112ffc8bcaSDan McDonald 	instance->drv_ver_dma_obj.dma_attr = mrsas_generic_dma_attr;
10122ffc8bcaSDan McDonald 	instance->drv_ver_dma_obj.dma_attr.dma_attr_addr_hi = 0xFFFFFFFFU;
10132ffc8bcaSDan McDonald 	instance->drv_ver_dma_obj.dma_attr.dma_attr_count_max = 0xFFFFFFFFU;
10142ffc8bcaSDan McDonald 	instance->drv_ver_dma_obj.dma_attr.dma_attr_sgllen = 1;
10152ffc8bcaSDan McDonald 	instance->drv_ver_dma_obj.dma_attr.dma_attr_align = 1;
10162ffc8bcaSDan McDonald 
10172ffc8bcaSDan McDonald 	if (mrsas_alloc_dma_obj(instance, &instance->drv_ver_dma_obj,
10182ffc8bcaSDan McDonald 	    (uchar_t)DDI_STRUCTURE_LE_ACC) != 1) {
1019ff38cf9dSAndy Fiddaman 		dev_err(instance->dip, CE_WARN,
10202ffc8bcaSDan McDonald 		    "fusion init: Could not allocate driver version buffer.");
10212ffc8bcaSDan McDonald 		return (DDI_FAILURE);
10222ffc8bcaSDan McDonald 	}
10232ffc8bcaSDan McDonald 	/* copy driver version to dma buffer */
10242ffc8bcaSDan McDonald 	bzero(instance->drv_ver_dma_obj.buffer, sizeof (drv_ver_info.drv_ver));
10252ffc8bcaSDan McDonald 	ddi_rep_put8(cmd->frame_dma_obj.acc_handle,
10262ffc8bcaSDan McDonald 	    (uint8_t *)drv_ver_info.drv_ver,
10272ffc8bcaSDan McDonald 	    (uint8_t *)instance->drv_ver_dma_obj.buffer,
10282ffc8bcaSDan McDonald 	    sizeof (drv_ver_info.drv_ver), DDI_DEV_AUTOINCR);
10292ffc8bcaSDan McDonald 
10302ffc8bcaSDan McDonald 	/* send driver version physical address to firmware */
10312ffc8bcaSDan McDonald 	ddi_put64(cmd->frame_dma_obj.acc_handle, &mfiFrameInit2->driverversion,
10322ffc8bcaSDan McDonald 	    instance->drv_ver_dma_obj.dma_cookie[0].dmac_address);
10332ffc8bcaSDan McDonald 
10342ffc8bcaSDan McDonald 	con_log(CL_ANN1, (CE_CONT, "[MPIINIT2 frame Phys addr ]0x%x len = %x",
10352ffc8bcaSDan McDonald 	    mfiFrameInit2->queue_info_new_phys_addr_lo,
10362ffc8bcaSDan McDonald 	    (int)sizeof (Mpi2IOCInitRequest_t)));
10372ffc8bcaSDan McDonald 
10382ffc8bcaSDan McDonald 	con_log(CL_ANN1, (CE_CONT, "[Length]%x", mfiFrameInit2->data_xfer_len));
10392ffc8bcaSDan McDonald 
10402ffc8bcaSDan McDonald 	con_log(CL_ANN1, (CE_CONT, "[MFI frame Phys Address]%x len = %x",
10412ffc8bcaSDan McDonald 	    cmd->scsi_io_request_phys_addr,
10422ffc8bcaSDan McDonald 	    (int)sizeof (struct mrsas_init_frame2)));
10432ffc8bcaSDan McDonald 
10442ffc8bcaSDan McDonald 	/* disable interrupts before sending INIT2 frame */
10452ffc8bcaSDan McDonald 	instance->func_ptr->disable_intr(instance);
10462ffc8bcaSDan McDonald 
10474bc492d2SAndy Fiddaman 	req_desc.Words = cmd->scsi_io_request_phys_addr;
10484bc492d2SAndy Fiddaman 	req_desc.MFAIo.RequestFlags =
10492ffc8bcaSDan McDonald 	    (MPI2_REQ_DESCRIPT_FLAGS_MFA << MPI2_REQ_DESCRIPT_FLAGS_TYPE_SHIFT);
10502ffc8bcaSDan McDonald 
10514bc492d2SAndy Fiddaman 	cmd->request_desc = &req_desc;
10522ffc8bcaSDan McDonald 
10532ffc8bcaSDan McDonald 	/* issue the init frame */
10544bc492d2SAndy Fiddaman 
10554bc492d2SAndy Fiddaman 	mutex_enter(&instance->reg_write_mtx);
10564bc492d2SAndy Fiddaman 	WR_IB_LOW_QPORT((uint32_t)(req_desc.Words), instance);
10574bc492d2SAndy Fiddaman 	WR_IB_HIGH_QPORT((uint32_t)(req_desc.Words >> 32), instance);
10584bc492d2SAndy Fiddaman 	mutex_exit(&instance->reg_write_mtx);
10592ffc8bcaSDan McDonald 
10602ffc8bcaSDan McDonald 	con_log(CL_ANN1, (CE_CONT, "[cmd = %d] ", frame_hdr->cmd));
10612ffc8bcaSDan McDonald 	con_log(CL_ANN1, (CE_CONT, "[cmd  Status= %x] ",
10622ffc8bcaSDan McDonald 	    frame_hdr->cmd_status));
10632ffc8bcaSDan McDonald 
10644bc492d2SAndy Fiddaman 	timeout = drv_usectohz(MFI_POLL_TIMEOUT_SECS * MICROSEC);
10654bc492d2SAndy Fiddaman 	do {
10664bc492d2SAndy Fiddaman 		if (ddi_get8(cmd->frame_dma_obj.acc_handle,
10674bc492d2SAndy Fiddaman 		    &mfiFrameInit2->cmd_status) != MFI_CMD_STATUS_POLL_MODE)
10684bc492d2SAndy Fiddaman 			break;
10694bc492d2SAndy Fiddaman 		delay(1);
10704bc492d2SAndy Fiddaman 		timeout--;
10714bc492d2SAndy Fiddaman 	} while (timeout > 0);
10724bc492d2SAndy Fiddaman 
10732ffc8bcaSDan McDonald 	if (ddi_get8(instance->mpi2_frame_pool_dma_obj.acc_handle,
10742ffc8bcaSDan McDonald 	    &mfiFrameInit2->cmd_status) == 0) {
10752ffc8bcaSDan McDonald 		con_log(CL_ANN, (CE_NOTE, "INIT2 Success"));
10762ffc8bcaSDan McDonald 	} else {
10772ffc8bcaSDan McDonald 		con_log(CL_ANN, (CE_WARN, "INIT2 Fail"));
10782ffc8bcaSDan McDonald 		mrsas_dump_reply_desc(instance);
10792ffc8bcaSDan McDonald 		goto fail_ioc_init;
10802ffc8bcaSDan McDonald 	}
10812ffc8bcaSDan McDonald 
10822ffc8bcaSDan McDonald 	mrsas_dump_reply_desc(instance);
10832ffc8bcaSDan McDonald 
10842ffc8bcaSDan McDonald 	instance->unroll.verBuff = 1;
10852ffc8bcaSDan McDonald 
10862ffc8bcaSDan McDonald 	con_log(CL_ANN, (CE_NOTE, "mrsas_tbolt_ioc_init: SUCCESSFUL"));
10872ffc8bcaSDan McDonald 
10882ffc8bcaSDan McDonald 	return (DDI_SUCCESS);
10892ffc8bcaSDan McDonald 
10902ffc8bcaSDan McDonald 
10912ffc8bcaSDan McDonald fail_ioc_init:
10922ffc8bcaSDan McDonald 
10932ffc8bcaSDan McDonald 	(void) mrsas_free_dma_obj(instance, instance->drv_ver_dma_obj);
10942ffc8bcaSDan McDonald 
10952ffc8bcaSDan McDonald 	return (DDI_FAILURE);
10962ffc8bcaSDan McDonald }
10972ffc8bcaSDan McDonald 
10982ffc8bcaSDan McDonald int
wait_for_outstanding_poll_io(struct mrsas_instance * instance)10992ffc8bcaSDan McDonald wait_for_outstanding_poll_io(struct mrsas_instance *instance)
11002ffc8bcaSDan McDonald {
11012ffc8bcaSDan McDonald 	int i;
11022ffc8bcaSDan McDonald 	uint32_t wait_time = dump_io_wait_time;
11032ffc8bcaSDan McDonald 	for (i = 0; i < wait_time; i++) {
11042ffc8bcaSDan McDonald 		/*
11052ffc8bcaSDan McDonald 		 * Check For Outstanding poll Commands
11062ffc8bcaSDan McDonald 		 * except ldsync command and aen command
11072ffc8bcaSDan McDonald 		 */
11082ffc8bcaSDan McDonald 		if (instance->fw_outstanding <= 2) {
11092ffc8bcaSDan McDonald 			break;
11102ffc8bcaSDan McDonald 		}
1111d8873b31SJoyce McIntosh 		drv_usecwait(MILLISEC);
11122ffc8bcaSDan McDonald 		/* complete commands from reply queue */
11132ffc8bcaSDan McDonald 		(void) mr_sas_tbolt_process_outstanding_cmd(instance);
11142ffc8bcaSDan McDonald 	}
11152ffc8bcaSDan McDonald 	if (instance->fw_outstanding > 2) {
11162ffc8bcaSDan McDonald 		return (1);
11172ffc8bcaSDan McDonald 	}
11182ffc8bcaSDan McDonald 	return (0);
11192ffc8bcaSDan McDonald }
11202ffc8bcaSDan McDonald /*
11212ffc8bcaSDan McDonald  * scsi_pkt handling
11222ffc8bcaSDan McDonald  *
11232ffc8bcaSDan McDonald  * Visible to the external world via the transport structure.
11242ffc8bcaSDan McDonald  */
11252ffc8bcaSDan McDonald 
11262ffc8bcaSDan McDonald int
mrsas_tbolt_tran_start(struct scsi_address * ap,struct scsi_pkt * pkt)11272ffc8bcaSDan McDonald mrsas_tbolt_tran_start(struct scsi_address *ap, struct scsi_pkt *pkt)
11282ffc8bcaSDan McDonald {
11292ffc8bcaSDan McDonald 	struct mrsas_instance	*instance = ADDR2MR(ap);
11302ffc8bcaSDan McDonald 	struct scsa_cmd		*acmd = PKT2CMD(pkt);
11312ffc8bcaSDan McDonald 	struct mrsas_cmd	*cmd = NULL;
11322ffc8bcaSDan McDonald 	uchar_t			cmd_done = 0;
11332ffc8bcaSDan McDonald 
11342ffc8bcaSDan McDonald 	con_log(CL_DLEVEL1, (CE_NOTE, "chkpnt:%s:%d", __func__, __LINE__));
11352ffc8bcaSDan McDonald 	if (instance->deadadapter == 1) {
1136ff38cf9dSAndy Fiddaman 		dev_err(instance->dip, CE_WARN,
11372ffc8bcaSDan McDonald 		    "mrsas_tran_start:TBOLT return TRAN_FATAL_ERROR "
11382ffc8bcaSDan McDonald 		    "for IO, as the HBA doesnt take any more IOs");
11392ffc8bcaSDan McDonald 		if (pkt) {
11402ffc8bcaSDan McDonald 			pkt->pkt_reason		= CMD_DEV_GONE;
11412ffc8bcaSDan McDonald 			pkt->pkt_statistics	= STAT_DISCON;
11422ffc8bcaSDan McDonald 		}
11432ffc8bcaSDan McDonald 		return (TRAN_FATAL_ERROR);
11442ffc8bcaSDan McDonald 	}
11452ffc8bcaSDan McDonald 	if (instance->adapterresetinprogress) {
11462ffc8bcaSDan McDonald 		con_log(CL_ANN, (CE_NOTE, "Reset flag set, "
11472ffc8bcaSDan McDonald 		    "returning mfi_pkt and setting TRAN_BUSY\n"));
11482ffc8bcaSDan McDonald 		return (TRAN_BUSY);
11492ffc8bcaSDan McDonald 	}
11502ffc8bcaSDan McDonald 	(void) mrsas_tbolt_prepare_pkt(acmd);
11512ffc8bcaSDan McDonald 
11522ffc8bcaSDan McDonald 	cmd = mrsas_tbolt_build_cmd(instance, ap, pkt, &cmd_done);
11532ffc8bcaSDan McDonald 
11542ffc8bcaSDan McDonald 	/*
11552ffc8bcaSDan McDonald 	 * Check if the command is already completed by the mrsas_build_cmd()
11562ffc8bcaSDan McDonald 	 * routine. In which case the busy_flag would be clear and scb will be
11572ffc8bcaSDan McDonald 	 * NULL and appropriate reason provided in pkt_reason field
11582ffc8bcaSDan McDonald 	 */
11592ffc8bcaSDan McDonald 	if (cmd_done) {
11602ffc8bcaSDan McDonald 		pkt->pkt_reason = CMD_CMPLT;
11612ffc8bcaSDan McDonald 		pkt->pkt_scbp[0] = STATUS_GOOD;
11622ffc8bcaSDan McDonald 		pkt->pkt_state |= STATE_GOT_BUS | STATE_GOT_TARGET
11632ffc8bcaSDan McDonald 		    | STATE_SENT_CMD;
11642ffc8bcaSDan McDonald 		if (((pkt->pkt_flags & FLAG_NOINTR) == 0) && pkt->pkt_comp) {
11652ffc8bcaSDan McDonald 			(*pkt->pkt_comp)(pkt);
11662ffc8bcaSDan McDonald 		}
11672ffc8bcaSDan McDonald 
11682ffc8bcaSDan McDonald 		return (TRAN_ACCEPT);
11692ffc8bcaSDan McDonald 	}
11702ffc8bcaSDan McDonald 
11712ffc8bcaSDan McDonald 	if (cmd == NULL) {
11722ffc8bcaSDan McDonald 		return (TRAN_BUSY);
11732ffc8bcaSDan McDonald 	}
11742ffc8bcaSDan McDonald 
11752ffc8bcaSDan McDonald 
11762ffc8bcaSDan McDonald 	if ((pkt->pkt_flags & FLAG_NOINTR) == 0) {
11772ffc8bcaSDan McDonald 		if (instance->fw_outstanding > instance->max_fw_cmds) {
1178ff38cf9dSAndy Fiddaman 			dev_err(instance->dip, CE_WARN,
11792ffc8bcaSDan McDonald 			    "Command Queue Full... Returning BUSY");
1180091932b4SAndy Fiddaman 			DTRACE_PROBE2(tbolt_start_tran_err,
1181091932b4SAndy Fiddaman 			    uint16_t, instance->fw_outstanding,
1182091932b4SAndy Fiddaman 			    uint16_t, instance->max_fw_cmds);
11832ffc8bcaSDan McDonald 			return_raid_msg_pkt(instance, cmd);
11842ffc8bcaSDan McDonald 			return (TRAN_BUSY);
11852ffc8bcaSDan McDonald 		}
11862ffc8bcaSDan McDonald 
11872ffc8bcaSDan McDonald 		/* Synchronize the Cmd frame for the controller */
11882ffc8bcaSDan McDonald 		(void) ddi_dma_sync(cmd->frame_dma_obj.dma_handle, 0, 0,
11892ffc8bcaSDan McDonald 		    DDI_DMA_SYNC_FORDEV);
11902ffc8bcaSDan McDonald 
11912ffc8bcaSDan McDonald 		con_log(CL_ANN, (CE_CONT, "tbolt_issue_cmd: SCSI CDB[0]=0x%x "
11922ffc8bcaSDan McDonald 		    "cmd->index:0x%x SMID 0x%x\n", pkt->pkt_cdbp[0],
11932ffc8bcaSDan McDonald 		    cmd->index, cmd->SMID));
11942ffc8bcaSDan McDonald 
11952ffc8bcaSDan McDonald 		instance->func_ptr->issue_cmd(cmd, instance);
11962ffc8bcaSDan McDonald 	} else {
11972ffc8bcaSDan McDonald 		instance->func_ptr->issue_cmd(cmd, instance);
11982ffc8bcaSDan McDonald 		(void) wait_for_outstanding_poll_io(instance);
11992ffc8bcaSDan McDonald 		(void) mrsas_common_check(instance, cmd);
1200091932b4SAndy Fiddaman 		DTRACE_PROBE2(tbolt_start_nointr_done,
1201091932b4SAndy Fiddaman 		    uint8_t, cmd->frame->hdr.cmd,
1202091932b4SAndy Fiddaman 		    uint8_t, cmd->frame->hdr.cmd_status);
12032ffc8bcaSDan McDonald 	}
12042ffc8bcaSDan McDonald 
12052ffc8bcaSDan McDonald 	return (TRAN_ACCEPT);
12062ffc8bcaSDan McDonald }
12072ffc8bcaSDan McDonald 
12082ffc8bcaSDan McDonald /*
12092ffc8bcaSDan McDonald  * prepare the pkt:
12102ffc8bcaSDan McDonald  * the pkt may have been resubmitted or just reused so
12112ffc8bcaSDan McDonald  * initialize some fields and do some checks.
12122ffc8bcaSDan McDonald  */
12132ffc8bcaSDan McDonald static int
mrsas_tbolt_prepare_pkt(struct scsa_cmd * acmd)12142ffc8bcaSDan McDonald mrsas_tbolt_prepare_pkt(struct scsa_cmd *acmd)
12152ffc8bcaSDan McDonald {
12162ffc8bcaSDan McDonald 	struct scsi_pkt	*pkt = CMD2PKT(acmd);
12172ffc8bcaSDan McDonald 
12182ffc8bcaSDan McDonald 
12192ffc8bcaSDan McDonald 	/*
12202ffc8bcaSDan McDonald 	 * Reinitialize some fields that need it; the packet may
12212ffc8bcaSDan McDonald 	 * have been resubmitted
12222ffc8bcaSDan McDonald 	 */
12232ffc8bcaSDan McDonald 	pkt->pkt_reason = CMD_CMPLT;
12242ffc8bcaSDan McDonald 	pkt->pkt_state = 0;
12252ffc8bcaSDan McDonald 	pkt->pkt_statistics = 0;
12262ffc8bcaSDan McDonald 	pkt->pkt_resid = 0;
12272ffc8bcaSDan McDonald 
12282ffc8bcaSDan McDonald 	/*
12292ffc8bcaSDan McDonald 	 * zero status byte.
12302ffc8bcaSDan McDonald 	 */
12312ffc8bcaSDan McDonald 	*(pkt->pkt_scbp) = 0;
12322ffc8bcaSDan McDonald 
12332ffc8bcaSDan McDonald 	return (0);
12342ffc8bcaSDan McDonald }
12352ffc8bcaSDan McDonald 
12362ffc8bcaSDan McDonald 
12372ffc8bcaSDan McDonald int
mr_sas_tbolt_build_sgl(struct mrsas_instance * instance,struct scsa_cmd * acmd,struct mrsas_cmd * cmd,Mpi2RaidSCSIIORequest_t * scsi_raid_io,uint32_t * datalen)12382ffc8bcaSDan McDonald mr_sas_tbolt_build_sgl(struct mrsas_instance *instance,
12392ffc8bcaSDan McDonald     struct scsa_cmd *acmd,
12402ffc8bcaSDan McDonald     struct mrsas_cmd *cmd,
12412ffc8bcaSDan McDonald     Mpi2RaidSCSIIORequest_t *scsi_raid_io,
12422ffc8bcaSDan McDonald     uint32_t *datalen)
12432ffc8bcaSDan McDonald {
12442ffc8bcaSDan McDonald 	uint32_t		MaxSGEs;
12452ffc8bcaSDan McDonald 	int			sg_to_process;
12462ffc8bcaSDan McDonald 	uint32_t		i, j;
12472ffc8bcaSDan McDonald 	uint32_t		numElements, endElement;
12482ffc8bcaSDan McDonald 	Mpi25IeeeSgeChain64_t	*ieeeChainElement = NULL;
12492ffc8bcaSDan McDonald 	Mpi25IeeeSgeChain64_t	*scsi_raid_io_sgl_ieee = NULL;
12502ffc8bcaSDan McDonald 	ddi_acc_handle_t acc_handle =
12512ffc8bcaSDan McDonald 	    instance->mpi2_frame_pool_dma_obj.acc_handle;
12522ffc8bcaSDan McDonald 
12532ffc8bcaSDan McDonald 	con_log(CL_ANN1, (CE_NOTE,
12542ffc8bcaSDan McDonald 	    "chkpnt: Building Chained SGL :%d", __LINE__));
12552ffc8bcaSDan McDonald 
12562ffc8bcaSDan McDonald 	/* Calulate SGE size in number of Words(32bit) */
12572ffc8bcaSDan McDonald 	/* Clear the datalen before updating it. */
12582ffc8bcaSDan McDonald 	*datalen = 0;
12592ffc8bcaSDan McDonald 
12602ffc8bcaSDan McDonald 	MaxSGEs = instance->max_sge_in_main_msg;
12612ffc8bcaSDan McDonald 
12622ffc8bcaSDan McDonald 	ddi_put16(acc_handle, &scsi_raid_io->SGLFlags,
12632ffc8bcaSDan McDonald 	    MPI2_SGE_FLAGS_64_BIT_ADDRESSING);
12642ffc8bcaSDan McDonald 
12652ffc8bcaSDan McDonald 	/* set data transfer flag. */
12662ffc8bcaSDan McDonald 	if (acmd->cmd_flags & CFLAG_DMASEND) {
12672ffc8bcaSDan McDonald 		ddi_put32(acc_handle, &scsi_raid_io->Control,
12682ffc8bcaSDan McDonald 		    MPI2_SCSIIO_CONTROL_WRITE);
12692ffc8bcaSDan McDonald 	} else {
12702ffc8bcaSDan McDonald 		ddi_put32(acc_handle, &scsi_raid_io->Control,
12712ffc8bcaSDan McDonald 		    MPI2_SCSIIO_CONTROL_READ);
12722ffc8bcaSDan McDonald 	}
12732ffc8bcaSDan McDonald 
12742ffc8bcaSDan McDonald 
12752ffc8bcaSDan McDonald 	numElements = acmd->cmd_cookiecnt;
12762ffc8bcaSDan McDonald 
12772ffc8bcaSDan McDonald 	con_log(CL_DLEVEL1, (CE_NOTE, "[SGE Count]:%x", numElements));
12782ffc8bcaSDan McDonald 
12792ffc8bcaSDan McDonald 	if (numElements > instance->max_num_sge) {
12802ffc8bcaSDan McDonald 		con_log(CL_ANN, (CE_NOTE,
12812ffc8bcaSDan McDonald 		    "[Max SGE Count Exceeded]:%x", numElements));
12822ffc8bcaSDan McDonald 		return (numElements);
12832ffc8bcaSDan McDonald 	}
12842ffc8bcaSDan McDonald 
12852ffc8bcaSDan McDonald 	ddi_put8(acc_handle, &scsi_raid_io->RaidContext.numSGE,
12862ffc8bcaSDan McDonald 	    (uint8_t)numElements);
12872ffc8bcaSDan McDonald 
12882ffc8bcaSDan McDonald 	/* set end element in main message frame */
12892ffc8bcaSDan McDonald 	endElement = (numElements <= MaxSGEs) ? numElements : (MaxSGEs - 1);
12902ffc8bcaSDan McDonald 
12912ffc8bcaSDan McDonald 	/* prepare the scatter-gather list for the firmware */
12922ffc8bcaSDan McDonald 	scsi_raid_io_sgl_ieee =
12932ffc8bcaSDan McDonald 	    (Mpi25IeeeSgeChain64_t *)&scsi_raid_io->SGL.IeeeChain;
12942ffc8bcaSDan McDonald 
1295df950592SHummyPkg 	if (instance->gen3) {
12962ffc8bcaSDan McDonald 		Mpi25IeeeSgeChain64_t *sgl_ptr_end = scsi_raid_io_sgl_ieee;
12972ffc8bcaSDan McDonald 		sgl_ptr_end += instance->max_sge_in_main_msg - 1;
12982ffc8bcaSDan McDonald 
12992ffc8bcaSDan McDonald 		ddi_put8(acc_handle, &sgl_ptr_end->Flags, 0);
13002ffc8bcaSDan McDonald 	}
13012ffc8bcaSDan McDonald 
13022ffc8bcaSDan McDonald 	for (i = 0; i < endElement; i++, scsi_raid_io_sgl_ieee++) {
13032ffc8bcaSDan McDonald 		ddi_put64(acc_handle, &scsi_raid_io_sgl_ieee->Address,
13042ffc8bcaSDan McDonald 		    acmd->cmd_dmacookies[i].dmac_laddress);
13052ffc8bcaSDan McDonald 
13062ffc8bcaSDan McDonald 		ddi_put32(acc_handle, &scsi_raid_io_sgl_ieee->Length,
13072ffc8bcaSDan McDonald 		    acmd->cmd_dmacookies[i].dmac_size);
13082ffc8bcaSDan McDonald 
13092ffc8bcaSDan McDonald 		ddi_put8(acc_handle, &scsi_raid_io_sgl_ieee->Flags, 0);
13102ffc8bcaSDan McDonald 
1311df950592SHummyPkg 		if (instance->gen3) {
13122ffc8bcaSDan McDonald 			if (i == (numElements - 1)) {
13132ffc8bcaSDan McDonald 				ddi_put8(acc_handle,
13142ffc8bcaSDan McDonald 				    &scsi_raid_io_sgl_ieee->Flags,
13152ffc8bcaSDan McDonald 				    IEEE_SGE_FLAGS_END_OF_LIST);
13162ffc8bcaSDan McDonald 			}
13172ffc8bcaSDan McDonald 		}
13182ffc8bcaSDan McDonald 
13192ffc8bcaSDan McDonald 		*datalen += acmd->cmd_dmacookies[i].dmac_size;
13202ffc8bcaSDan McDonald 
13212ffc8bcaSDan McDonald #ifdef DEBUG
13222ffc8bcaSDan McDonald 		con_log(CL_DLEVEL1, (CE_NOTE, "[SGL Address]: %" PRIx64,
13232ffc8bcaSDan McDonald 		    scsi_raid_io_sgl_ieee->Address));
13242ffc8bcaSDan McDonald 		con_log(CL_DLEVEL1, (CE_NOTE, "[SGL Length]:%x",
13252ffc8bcaSDan McDonald 		    scsi_raid_io_sgl_ieee->Length));
13262ffc8bcaSDan McDonald 		con_log(CL_DLEVEL1, (CE_NOTE, "[SGL Flags]:%x",
13272ffc8bcaSDan McDonald 		    scsi_raid_io_sgl_ieee->Flags));
13282ffc8bcaSDan McDonald #endif
13292ffc8bcaSDan McDonald 
13302ffc8bcaSDan McDonald 	}
13312ffc8bcaSDan McDonald 
13322ffc8bcaSDan McDonald 	ddi_put8(acc_handle, &scsi_raid_io->ChainOffset, 0);
13332ffc8bcaSDan McDonald 
13342ffc8bcaSDan McDonald 	/* check if chained SGL required */
13352ffc8bcaSDan McDonald 	if (i < numElements) {
13362ffc8bcaSDan McDonald 
13372ffc8bcaSDan McDonald 		con_log(CL_ANN1, (CE_NOTE, "[Chain Element index]:%x", i));
13382ffc8bcaSDan McDonald 
1339df950592SHummyPkg 		if (instance->gen3) {
13402ffc8bcaSDan McDonald 			uint16_t ioFlags =
13412ffc8bcaSDan McDonald 			    ddi_get16(acc_handle, &scsi_raid_io->IoFlags);
13422ffc8bcaSDan McDonald 
13432ffc8bcaSDan McDonald 			if ((ioFlags &
13442ffc8bcaSDan McDonald 			    MPI25_SAS_DEVICE0_FLAGS_ENABLED_FAST_PATH) !=
13452ffc8bcaSDan McDonald 			    MPI25_SAS_DEVICE0_FLAGS_ENABLED_FAST_PATH) {
13462ffc8bcaSDan McDonald 				ddi_put8(acc_handle, &scsi_raid_io->ChainOffset,
13472ffc8bcaSDan McDonald 				    (U8)instance->chain_offset_io_req);
13482ffc8bcaSDan McDonald 			} else {
13492ffc8bcaSDan McDonald 				ddi_put8(acc_handle,
13502ffc8bcaSDan McDonald 				    &scsi_raid_io->ChainOffset, 0);
13512ffc8bcaSDan McDonald 			}
13522ffc8bcaSDan McDonald 		} else {
13532ffc8bcaSDan McDonald 			ddi_put8(acc_handle, &scsi_raid_io->ChainOffset,
13542ffc8bcaSDan McDonald 			    (U8)instance->chain_offset_io_req);
13552ffc8bcaSDan McDonald 		}
13562ffc8bcaSDan McDonald 
13572ffc8bcaSDan McDonald 		/* prepare physical chain element */
13582ffc8bcaSDan McDonald 		ieeeChainElement = scsi_raid_io_sgl_ieee;
13592ffc8bcaSDan McDonald 
13602ffc8bcaSDan McDonald 		ddi_put8(acc_handle, &ieeeChainElement->NextChainOffset, 0);
13612ffc8bcaSDan McDonald 
1362df950592SHummyPkg 		if (instance->gen3) {
13632ffc8bcaSDan McDonald 			ddi_put8(acc_handle, &ieeeChainElement->Flags,
13642ffc8bcaSDan McDonald 			    IEEE_SGE_FLAGS_CHAIN_ELEMENT);
13652ffc8bcaSDan McDonald 		} else {
13662ffc8bcaSDan McDonald 			ddi_put8(acc_handle, &ieeeChainElement->Flags,
13672ffc8bcaSDan McDonald 			    (IEEE_SGE_FLAGS_CHAIN_ELEMENT |
13682ffc8bcaSDan McDonald 			    MPI2_IEEE_SGE_FLAGS_IOCPLBNTA_ADDR));
13692ffc8bcaSDan McDonald 		}
13702ffc8bcaSDan McDonald 
13712ffc8bcaSDan McDonald 		ddi_put32(acc_handle, &ieeeChainElement->Length,
13722ffc8bcaSDan McDonald 		    (sizeof (MPI2_SGE_IO_UNION) * (numElements - i)));
13732ffc8bcaSDan McDonald 
13742ffc8bcaSDan McDonald 		ddi_put64(acc_handle, &ieeeChainElement->Address,
13752ffc8bcaSDan McDonald 		    (U64)cmd->sgl_phys_addr);
13762ffc8bcaSDan McDonald 
13772ffc8bcaSDan McDonald 		sg_to_process = numElements - i;
13782ffc8bcaSDan McDonald 
13792ffc8bcaSDan McDonald 		con_log(CL_ANN1, (CE_NOTE,
13802ffc8bcaSDan McDonald 		    "[Additional SGE Count]:%x", endElement));
13812ffc8bcaSDan McDonald 
13822ffc8bcaSDan McDonald 		/* point to the chained SGL buffer */
13832ffc8bcaSDan McDonald 		scsi_raid_io_sgl_ieee = (Mpi25IeeeSgeChain64_t *)cmd->sgl;
13842ffc8bcaSDan McDonald 
13852ffc8bcaSDan McDonald 		/* build rest of the SGL in chained buffer */
13862ffc8bcaSDan McDonald 		for (j = 0; j < sg_to_process; j++, scsi_raid_io_sgl_ieee++) {
13872ffc8bcaSDan McDonald 			con_log(CL_DLEVEL3, (CE_NOTE, "[remaining SGL]:%x", i));
13882ffc8bcaSDan McDonald 
13892ffc8bcaSDan McDonald 			ddi_put64(acc_handle, &scsi_raid_io_sgl_ieee->Address,
13902ffc8bcaSDan McDonald 			    acmd->cmd_dmacookies[i].dmac_laddress);
13912ffc8bcaSDan McDonald 
13922ffc8bcaSDan McDonald 			ddi_put32(acc_handle, &scsi_raid_io_sgl_ieee->Length,
13932ffc8bcaSDan McDonald 			    acmd->cmd_dmacookies[i].dmac_size);
13942ffc8bcaSDan McDonald 
13952ffc8bcaSDan McDonald 			ddi_put8(acc_handle, &scsi_raid_io_sgl_ieee->Flags, 0);
13962ffc8bcaSDan McDonald 
1397df950592SHummyPkg 			if (instance->gen3) {
13982ffc8bcaSDan McDonald 				if (i == (numElements - 1)) {
13992ffc8bcaSDan McDonald 					ddi_put8(acc_handle,
14002ffc8bcaSDan McDonald 					    &scsi_raid_io_sgl_ieee->Flags,
14012ffc8bcaSDan McDonald 					    IEEE_SGE_FLAGS_END_OF_LIST);
14022ffc8bcaSDan McDonald 				}
14032ffc8bcaSDan McDonald 			}
14042ffc8bcaSDan McDonald 
14052ffc8bcaSDan McDonald 			*datalen += acmd->cmd_dmacookies[i].dmac_size;
14062ffc8bcaSDan McDonald 
14072ffc8bcaSDan McDonald #if DEBUG
14082ffc8bcaSDan McDonald 			con_log(CL_DLEVEL1, (CE_NOTE,
14092ffc8bcaSDan McDonald 			    "[SGL Address]: %" PRIx64,
14102ffc8bcaSDan McDonald 			    scsi_raid_io_sgl_ieee->Address));
14112ffc8bcaSDan McDonald 			con_log(CL_DLEVEL1, (CE_NOTE,
14122ffc8bcaSDan McDonald 			    "[SGL Length]:%x", scsi_raid_io_sgl_ieee->Length));
14132ffc8bcaSDan McDonald 			con_log(CL_DLEVEL1, (CE_NOTE,
14142ffc8bcaSDan McDonald 			    "[SGL Flags]:%x", scsi_raid_io_sgl_ieee->Flags));
14152ffc8bcaSDan McDonald #endif
14162ffc8bcaSDan McDonald 
14172ffc8bcaSDan McDonald 			i++;
14182ffc8bcaSDan McDonald 		}
14192ffc8bcaSDan McDonald 	}
14202ffc8bcaSDan McDonald 
14212ffc8bcaSDan McDonald 	return (0);
14222ffc8bcaSDan McDonald } /*end of BuildScatterGather */
14232ffc8bcaSDan McDonald 
14242ffc8bcaSDan McDonald 
14252ffc8bcaSDan McDonald /*
14262ffc8bcaSDan McDonald  * build_cmd
14272ffc8bcaSDan McDonald  */
14282ffc8bcaSDan McDonald static struct mrsas_cmd *
mrsas_tbolt_build_cmd(struct mrsas_instance * instance,struct scsi_address * ap,struct scsi_pkt * pkt,uchar_t * cmd_done)14292ffc8bcaSDan McDonald mrsas_tbolt_build_cmd(struct mrsas_instance *instance, struct scsi_address *ap,
14302ffc8bcaSDan McDonald     struct scsi_pkt *pkt, uchar_t *cmd_done)
14312ffc8bcaSDan McDonald {
14322ffc8bcaSDan McDonald 	uint8_t		fp_possible = 0;
14332ffc8bcaSDan McDonald 	uint32_t	index;
14342ffc8bcaSDan McDonald 	uint32_t	lba_count = 0;
14352ffc8bcaSDan McDonald 	uint32_t	start_lba_hi = 0;
14362ffc8bcaSDan McDonald 	uint32_t	start_lba_lo = 0;
14372ffc8bcaSDan McDonald 	ddi_acc_handle_t acc_handle =
14382ffc8bcaSDan McDonald 	    instance->mpi2_frame_pool_dma_obj.acc_handle;
14392ffc8bcaSDan McDonald 	struct mrsas_cmd		*cmd = NULL;
14402ffc8bcaSDan McDonald 	struct scsa_cmd			*acmd = PKT2CMD(pkt);
14412ffc8bcaSDan McDonald 	MRSAS_REQUEST_DESCRIPTOR_UNION	*ReqDescUnion;
14422ffc8bcaSDan McDonald 	Mpi2RaidSCSIIORequest_t		*scsi_raid_io;
14432ffc8bcaSDan McDonald 	uint32_t			datalen;
14442ffc8bcaSDan McDonald 	struct IO_REQUEST_INFO io_info;
14452ffc8bcaSDan McDonald 	MR_FW_RAID_MAP_ALL *local_map_ptr;
14462ffc8bcaSDan McDonald 	uint16_t pd_cmd_cdblen;
14472ffc8bcaSDan McDonald 
14482ffc8bcaSDan McDonald 	con_log(CL_DLEVEL1, (CE_NOTE,
14492ffc8bcaSDan McDonald 	    "chkpnt: Entered mrsas_tbolt_build_cmd:%d", __LINE__));
14502ffc8bcaSDan McDonald 
14512ffc8bcaSDan McDonald 	/* find out if this is logical or physical drive command.  */
14522ffc8bcaSDan McDonald 	acmd->islogical = MRDRV_IS_LOGICAL(ap);
14532ffc8bcaSDan McDonald 	acmd->device_id = MAP_DEVICE_ID(instance, ap);
14542ffc8bcaSDan McDonald 
14552ffc8bcaSDan McDonald 	*cmd_done = 0;
14562ffc8bcaSDan McDonald 
14572ffc8bcaSDan McDonald 	/* get the command packet */
14582ffc8bcaSDan McDonald 	if (!(cmd = get_raid_msg_pkt(instance))) {
1459091932b4SAndy Fiddaman 		DTRACE_PROBE2(tbolt_build_cmd_mfi_err, uint16_t,
1460091932b4SAndy Fiddaman 		    instance->fw_outstanding, uint16_t, instance->max_fw_cmds);
14612ffc8bcaSDan McDonald 		return (NULL);
14622ffc8bcaSDan McDonald 	}
14632ffc8bcaSDan McDonald 
14642ffc8bcaSDan McDonald 	index = cmd->index;
14652ffc8bcaSDan McDonald 	ReqDescUnion =	mr_sas_get_request_descriptor(instance, index);
14662ffc8bcaSDan McDonald 	ReqDescUnion->Words = 0;
14672ffc8bcaSDan McDonald 	ReqDescUnion->SCSIIO.SMID = cmd->SMID;
14682ffc8bcaSDan McDonald 	ReqDescUnion->SCSIIO.RequestFlags =
14692ffc8bcaSDan McDonald 	    (MPI2_REQ_DESCRIPT_FLAGS_LD_IO <<
14702ffc8bcaSDan McDonald 	    MPI2_REQ_DESCRIPT_FLAGS_TYPE_SHIFT);
14712ffc8bcaSDan McDonald 
14722ffc8bcaSDan McDonald 
14732ffc8bcaSDan McDonald 	cmd->request_desc = ReqDescUnion;
14742ffc8bcaSDan McDonald 	cmd->pkt = pkt;
14752ffc8bcaSDan McDonald 	cmd->cmd = acmd;
14762ffc8bcaSDan McDonald 
1477091932b4SAndy Fiddaman 	DTRACE_PROBE4(tbolt_build_cmd, uint8_t, pkt->pkt_cdbp[0],
1478091932b4SAndy Fiddaman 	    ulong_t, acmd->cmd_dmacount, ulong_t, acmd->cmd_dma_len,
1479091932b4SAndy Fiddaman 	    uint16_t, acmd->device_id);
1480091932b4SAndy Fiddaman 
14812ffc8bcaSDan McDonald 	/* lets get the command directions */
14822ffc8bcaSDan McDonald 	if (acmd->cmd_flags & CFLAG_DMASEND) {
14832ffc8bcaSDan McDonald 		if (acmd->cmd_flags & CFLAG_CONSISTENT) {
14842ffc8bcaSDan McDonald 			(void) ddi_dma_sync(acmd->cmd_dmahandle,
14852ffc8bcaSDan McDonald 			    acmd->cmd_dma_offset, acmd->cmd_dma_len,
14862ffc8bcaSDan McDonald 			    DDI_DMA_SYNC_FORDEV);
14872ffc8bcaSDan McDonald 		}
14882ffc8bcaSDan McDonald 	} else if (acmd->cmd_flags & ~CFLAG_DMASEND) {
14892ffc8bcaSDan McDonald 		if (acmd->cmd_flags & CFLAG_CONSISTENT) {
14902ffc8bcaSDan McDonald 			(void) ddi_dma_sync(acmd->cmd_dmahandle,
14912ffc8bcaSDan McDonald 			    acmd->cmd_dma_offset, acmd->cmd_dma_len,
14922ffc8bcaSDan McDonald 			    DDI_DMA_SYNC_FORCPU);
14932ffc8bcaSDan McDonald 		}
14942ffc8bcaSDan McDonald 	} else {
14952ffc8bcaSDan McDonald 		con_log(CL_ANN, (CE_NOTE, "NO DMA"));
14962ffc8bcaSDan McDonald 	}
14972ffc8bcaSDan McDonald 
14982ffc8bcaSDan McDonald 
14992ffc8bcaSDan McDonald 	/* get SCSI_IO raid message frame pointer */
15002ffc8bcaSDan McDonald 	scsi_raid_io = (Mpi2RaidSCSIIORequest_t *)cmd->scsi_io_request;
15012ffc8bcaSDan McDonald 
15022ffc8bcaSDan McDonald 	/* zero out SCSI_IO raid message frame */
15032ffc8bcaSDan McDonald 	bzero(scsi_raid_io, sizeof (Mpi2RaidSCSIIORequest_t));
15042ffc8bcaSDan McDonald 
15052ffc8bcaSDan McDonald 	/* Set the ldTargetId set by BuildRaidContext() */
15062ffc8bcaSDan McDonald 	ddi_put16(acc_handle, &scsi_raid_io->RaidContext.ldTargetId,
15072ffc8bcaSDan McDonald 	    acmd->device_id);
15082ffc8bcaSDan McDonald 
15092ffc8bcaSDan McDonald 	/*  Copy CDB to scsi_io_request message frame */
15102ffc8bcaSDan McDonald 	ddi_rep_put8(acc_handle,
15112ffc8bcaSDan McDonald 	    (uint8_t *)pkt->pkt_cdbp, (uint8_t *)scsi_raid_io->CDB.CDB32,
15122ffc8bcaSDan McDonald 	    acmd->cmd_cdblen, DDI_DEV_AUTOINCR);
15132ffc8bcaSDan McDonald 
15142ffc8bcaSDan McDonald 	/*
15152ffc8bcaSDan McDonald 	 * Just the CDB length, rest of the Flags are zero
15162ffc8bcaSDan McDonald 	 * This will be modified later.
15172ffc8bcaSDan McDonald 	 */
15182ffc8bcaSDan McDonald 	ddi_put16(acc_handle, &scsi_raid_io->IoFlags, acmd->cmd_cdblen);
15192ffc8bcaSDan McDonald 
15202ffc8bcaSDan McDonald 	pd_cmd_cdblen = acmd->cmd_cdblen;
15212ffc8bcaSDan McDonald 
1522e65bc174SAndy Fiddaman 	if (acmd->islogical) {
1523e65bc174SAndy Fiddaman 
15242ffc8bcaSDan McDonald 		switch (pkt->pkt_cdbp[0]) {
15252ffc8bcaSDan McDonald 		case SCMD_READ:
15262ffc8bcaSDan McDonald 		case SCMD_WRITE:
15272ffc8bcaSDan McDonald 		case SCMD_READ_G1:
15282ffc8bcaSDan McDonald 		case SCMD_WRITE_G1:
15292ffc8bcaSDan McDonald 		case SCMD_READ_G4:
15302ffc8bcaSDan McDonald 		case SCMD_WRITE_G4:
15312ffc8bcaSDan McDonald 		case SCMD_READ_G5:
15322ffc8bcaSDan McDonald 		case SCMD_WRITE_G5:
15332ffc8bcaSDan McDonald 
15342ffc8bcaSDan McDonald 			/* Initialize sense Information */
15352ffc8bcaSDan McDonald 			if (cmd->sense1 == NULL) {
15362ffc8bcaSDan McDonald 				con_log(CL_ANN, (CE_NOTE, "tbolt_build_cmd: "
15372ffc8bcaSDan McDonald 				    "Sense buffer ptr NULL "));
15382ffc8bcaSDan McDonald 			}
15392ffc8bcaSDan McDonald 			bzero(cmd->sense1, SENSE_LENGTH);
15402ffc8bcaSDan McDonald 			con_log(CL_DLEVEL2, (CE_NOTE, "tbolt_build_cmd "
15412ffc8bcaSDan McDonald 			    "CDB[0] = %x\n", pkt->pkt_cdbp[0]));
15422ffc8bcaSDan McDonald 
15432ffc8bcaSDan McDonald 			if (acmd->cmd_cdblen == CDB_GROUP0) {
15442ffc8bcaSDan McDonald 				/* 6-byte cdb */
15452ffc8bcaSDan McDonald 				lba_count = (uint16_t)(pkt->pkt_cdbp[4]);
15462ffc8bcaSDan McDonald 				start_lba_lo = ((uint32_t)(pkt->pkt_cdbp[3]) |
15472ffc8bcaSDan McDonald 				    ((uint32_t)(pkt->pkt_cdbp[2]) << 8) |
15482ffc8bcaSDan McDonald 				    ((uint32_t)((pkt->pkt_cdbp[1]) & 0x1F)
15492ffc8bcaSDan McDonald 				    << 16));
15502ffc8bcaSDan McDonald 			} else if (acmd->cmd_cdblen == CDB_GROUP1) {
15512ffc8bcaSDan McDonald 				/* 10-byte cdb */
15522ffc8bcaSDan McDonald 				lba_count =
15532ffc8bcaSDan McDonald 				    (((uint16_t)(pkt->pkt_cdbp[8])) |
15542ffc8bcaSDan McDonald 				    ((uint16_t)(pkt->pkt_cdbp[7]) << 8));
15552ffc8bcaSDan McDonald 
15562ffc8bcaSDan McDonald 				start_lba_lo =
15572ffc8bcaSDan McDonald 				    (((uint32_t)(pkt->pkt_cdbp[5])) |
15582ffc8bcaSDan McDonald 				    ((uint32_t)(pkt->pkt_cdbp[4]) << 8) |
15592ffc8bcaSDan McDonald 				    ((uint32_t)(pkt->pkt_cdbp[3]) << 16) |
15602ffc8bcaSDan McDonald 				    ((uint32_t)(pkt->pkt_cdbp[2]) << 24));
15612ffc8bcaSDan McDonald 
15622ffc8bcaSDan McDonald 			} else if (acmd->cmd_cdblen == CDB_GROUP5) {
15632ffc8bcaSDan McDonald 				/* 12-byte cdb */
15642ffc8bcaSDan McDonald 				lba_count = (
15652ffc8bcaSDan McDonald 				    ((uint32_t)(pkt->pkt_cdbp[9])) |
15662ffc8bcaSDan McDonald 				    ((uint32_t)(pkt->pkt_cdbp[8]) << 8) |
15672ffc8bcaSDan McDonald 				    ((uint32_t)(pkt->pkt_cdbp[7]) << 16) |
15682ffc8bcaSDan McDonald 				    ((uint32_t)(pkt->pkt_cdbp[6]) << 24));
15692ffc8bcaSDan McDonald 
15702ffc8bcaSDan McDonald 				start_lba_lo =
15712ffc8bcaSDan McDonald 				    (((uint32_t)(pkt->pkt_cdbp[5])) |
15722ffc8bcaSDan McDonald 				    ((uint32_t)(pkt->pkt_cdbp[4]) << 8) |
15732ffc8bcaSDan McDonald 				    ((uint32_t)(pkt->pkt_cdbp[3]) << 16) |
15742ffc8bcaSDan McDonald 				    ((uint32_t)(pkt->pkt_cdbp[2]) << 24));
15752ffc8bcaSDan McDonald 
15762ffc8bcaSDan McDonald 			} else if (acmd->cmd_cdblen == CDB_GROUP4) {
15772ffc8bcaSDan McDonald 				/* 16-byte cdb */
15782ffc8bcaSDan McDonald 				lba_count = (
15792ffc8bcaSDan McDonald 				    ((uint32_t)(pkt->pkt_cdbp[13])) |
15802ffc8bcaSDan McDonald 				    ((uint32_t)(pkt->pkt_cdbp[12]) << 8) |
15812ffc8bcaSDan McDonald 				    ((uint32_t)(pkt->pkt_cdbp[11]) << 16) |
15822ffc8bcaSDan McDonald 				    ((uint32_t)(pkt->pkt_cdbp[10]) << 24));
15832ffc8bcaSDan McDonald 
15842ffc8bcaSDan McDonald 				start_lba_lo = (
15852ffc8bcaSDan McDonald 				    ((uint32_t)(pkt->pkt_cdbp[9])) |
15862ffc8bcaSDan McDonald 				    ((uint32_t)(pkt->pkt_cdbp[8]) << 8) |
15872ffc8bcaSDan McDonald 				    ((uint32_t)(pkt->pkt_cdbp[7]) << 16) |
15882ffc8bcaSDan McDonald 				    ((uint32_t)(pkt->pkt_cdbp[6]) << 24));
15892ffc8bcaSDan McDonald 
15902ffc8bcaSDan McDonald 				start_lba_hi = (
15912ffc8bcaSDan McDonald 				    ((uint32_t)(pkt->pkt_cdbp[5])) |
15922ffc8bcaSDan McDonald 				    ((uint32_t)(pkt->pkt_cdbp[4]) << 8) |
15932ffc8bcaSDan McDonald 				    ((uint32_t)(pkt->pkt_cdbp[3]) << 16) |
15942ffc8bcaSDan McDonald 				    ((uint32_t)(pkt->pkt_cdbp[2]) << 24));
15952ffc8bcaSDan McDonald 			}
15962ffc8bcaSDan McDonald 
15972ffc8bcaSDan McDonald 			if (instance->tbolt &&
15982ffc8bcaSDan McDonald 			    ((lba_count * 512) > mrsas_tbolt_max_cap_maxxfer)) {
1599ff38cf9dSAndy Fiddaman 				dev_err(instance->dip, CE_WARN,
1600ff38cf9dSAndy Fiddaman 				    "IO SECTOR COUNT exceeds "
16012ffc8bcaSDan McDonald 				    "controller limit 0x%x sectors",
16022ffc8bcaSDan McDonald 				    lba_count);
16032ffc8bcaSDan McDonald 			}
16042ffc8bcaSDan McDonald 
16052ffc8bcaSDan McDonald 			bzero(&io_info, sizeof (struct IO_REQUEST_INFO));
16062ffc8bcaSDan McDonald 			io_info.ldStartBlock = ((uint64_t)start_lba_hi << 32) |
16072ffc8bcaSDan McDonald 			    start_lba_lo;
16082ffc8bcaSDan McDonald 			io_info.numBlocks = lba_count;
16092ffc8bcaSDan McDonald 			io_info.ldTgtId = acmd->device_id;
16102ffc8bcaSDan McDonald 
16112ffc8bcaSDan McDonald 			if (acmd->cmd_flags & CFLAG_DMASEND)
16122ffc8bcaSDan McDonald 				io_info.isRead = 0;
16132ffc8bcaSDan McDonald 			else
16142ffc8bcaSDan McDonald 				io_info.isRead = 1;
16152ffc8bcaSDan McDonald 
16162ffc8bcaSDan McDonald 
16172ffc8bcaSDan McDonald 			/* Acquire SYNC MAP UPDATE lock */
16182ffc8bcaSDan McDonald 			mutex_enter(&instance->sync_map_mtx);
16192ffc8bcaSDan McDonald 
16202ffc8bcaSDan McDonald 			local_map_ptr =
16212ffc8bcaSDan McDonald 			    instance->ld_map[(instance->map_id & 1)];
16222ffc8bcaSDan McDonald 
16232ffc8bcaSDan McDonald 			if ((MR_TargetIdToLdGet(
16242ffc8bcaSDan McDonald 			    acmd->device_id, local_map_ptr) >=
16252ffc8bcaSDan McDonald 			    MAX_LOGICAL_DRIVES) || !instance->fast_path_io) {
1626ff38cf9dSAndy Fiddaman 				dev_err(instance->dip, CE_NOTE,
1627ff38cf9dSAndy Fiddaman 				    "Fast Path NOT Possible, "
16282ffc8bcaSDan McDonald 				    "targetId >= MAX_LOGICAL_DRIVES || "
16292ffc8bcaSDan McDonald 				    "!instance->fast_path_io");
16302ffc8bcaSDan McDonald 				fp_possible = 0;
16312ffc8bcaSDan McDonald 				/* Set Regionlock flags to BYPASS */
16322ffc8bcaSDan McDonald 				/* io_request->RaidContext.regLockFlags  = 0; */
16332ffc8bcaSDan McDonald 				ddi_put8(acc_handle,
16342ffc8bcaSDan McDonald 				    &scsi_raid_io->RaidContext.regLockFlags, 0);
16352ffc8bcaSDan McDonald 			} else {
16362ffc8bcaSDan McDonald 				if (MR_BuildRaidContext(instance, &io_info,
16372ffc8bcaSDan McDonald 				    &scsi_raid_io->RaidContext, local_map_ptr))
16382ffc8bcaSDan McDonald 					fp_possible = io_info.fpOkForIo;
16392ffc8bcaSDan McDonald 			}
16402ffc8bcaSDan McDonald 
16412ffc8bcaSDan McDonald 			if (!enable_fp)
16422ffc8bcaSDan McDonald 				fp_possible = 0;
16432ffc8bcaSDan McDonald 
16442ffc8bcaSDan McDonald 			con_log(CL_ANN1, (CE_NOTE, "enable_fp %d  "
16452ffc8bcaSDan McDonald 			    "instance->fast_path_io %d fp_possible %d",
16462ffc8bcaSDan McDonald 			    enable_fp, instance->fast_path_io, fp_possible));
16472ffc8bcaSDan McDonald 
16482ffc8bcaSDan McDonald 		if (fp_possible) {
16492ffc8bcaSDan McDonald 
16502ffc8bcaSDan McDonald 			/* Check for DIF enabled LD */
16512ffc8bcaSDan McDonald 			if (MR_CheckDIF(acmd->device_id, local_map_ptr)) {
16522ffc8bcaSDan McDonald 				/* Prepare 32 Byte CDB for DIF capable Disk */
16532ffc8bcaSDan McDonald 				mrsas_tbolt_prepare_cdb(instance,
16542ffc8bcaSDan McDonald 				    scsi_raid_io->CDB.CDB32,
16552ffc8bcaSDan McDonald 				    &io_info, scsi_raid_io, start_lba_lo);
16562ffc8bcaSDan McDonald 			} else {
16572ffc8bcaSDan McDonald 				mrsas_tbolt_set_pd_lba(scsi_raid_io->CDB.CDB32,
16583344ffb7SToomas Soome 				    sizeof (scsi_raid_io->CDB.CDB32),
16592ffc8bcaSDan McDonald 				    (uint8_t *)&pd_cmd_cdblen,
16602ffc8bcaSDan McDonald 				    io_info.pdBlock, io_info.numBlocks);
16612ffc8bcaSDan McDonald 				ddi_put16(acc_handle,
16622ffc8bcaSDan McDonald 				    &scsi_raid_io->IoFlags, pd_cmd_cdblen);
16632ffc8bcaSDan McDonald 			}
16642ffc8bcaSDan McDonald 
16652ffc8bcaSDan McDonald 			ddi_put8(acc_handle, &scsi_raid_io->Function,
16662ffc8bcaSDan McDonald 			    MPI2_FUNCTION_SCSI_IO_REQUEST);
16672ffc8bcaSDan McDonald 
16682ffc8bcaSDan McDonald 			ReqDescUnion->SCSIIO.RequestFlags =
16692ffc8bcaSDan McDonald 			    (MPI2_REQ_DESCRIPT_FLAGS_HIGH_PRIORITY <<
16702ffc8bcaSDan McDonald 			    MPI2_REQ_DESCRIPT_FLAGS_TYPE_SHIFT);
16712ffc8bcaSDan McDonald 
1672df950592SHummyPkg 			if (instance->gen3) {
16732ffc8bcaSDan McDonald 				uint8_t regLockFlags = ddi_get8(acc_handle,
16742ffc8bcaSDan McDonald 				    &scsi_raid_io->RaidContext.regLockFlags);
16752ffc8bcaSDan McDonald 				uint16_t IoFlags = ddi_get16(acc_handle,
16762ffc8bcaSDan McDonald 				    &scsi_raid_io->IoFlags);
16772ffc8bcaSDan McDonald 
16782ffc8bcaSDan McDonald 				if (regLockFlags == REGION_TYPE_UNUSED)
16792ffc8bcaSDan McDonald 					ReqDescUnion->SCSIIO.RequestFlags =
16802ffc8bcaSDan McDonald 					    (MPI2_REQ_DESCRIPT_FLAGS_NO_LOCK <<
16812ffc8bcaSDan McDonald 					    MPI2_REQ_DESCRIPT_FLAGS_TYPE_SHIFT);
16822ffc8bcaSDan McDonald 
16832ffc8bcaSDan McDonald 				IoFlags |=
16842ffc8bcaSDan McDonald 				    MPI25_SAS_DEVICE0_FLAGS_ENABLED_FAST_PATH;
16852ffc8bcaSDan McDonald 				regLockFlags |=
16862ffc8bcaSDan McDonald 				    (MR_RL_FLAGS_GRANT_DESTINATION_CUDA |
16872ffc8bcaSDan McDonald 				    MR_RL_FLAGS_SEQ_NUM_ENABLE);
16882ffc8bcaSDan McDonald 
16892ffc8bcaSDan McDonald 				ddi_put8(acc_handle,
16902ffc8bcaSDan McDonald 				    &scsi_raid_io->ChainOffset, 0);
16912ffc8bcaSDan McDonald 				ddi_put8(acc_handle,
16922ffc8bcaSDan McDonald 				    &scsi_raid_io->RaidContext.nsegType,
16932ffc8bcaSDan McDonald 				    ((0x01 << MPI2_NSEG_FLAGS_SHIFT) |
16942ffc8bcaSDan McDonald 				    MPI2_TYPE_CUDA));
16952ffc8bcaSDan McDonald 				ddi_put8(acc_handle,
16962ffc8bcaSDan McDonald 				    &scsi_raid_io->RaidContext.regLockFlags,
16972ffc8bcaSDan McDonald 				    regLockFlags);
16982ffc8bcaSDan McDonald 				ddi_put16(acc_handle,
16992ffc8bcaSDan McDonald 				    &scsi_raid_io->IoFlags, IoFlags);
17002ffc8bcaSDan McDonald 			}
17012ffc8bcaSDan McDonald 
17022ffc8bcaSDan McDonald 			if ((instance->load_balance_info[
17032ffc8bcaSDan McDonald 			    acmd->device_id].loadBalanceFlag) &&
17042ffc8bcaSDan McDonald 			    (io_info.isRead)) {
17052ffc8bcaSDan McDonald 				io_info.devHandle =
17062ffc8bcaSDan McDonald 				    get_updated_dev_handle(&instance->
17072ffc8bcaSDan McDonald 				    load_balance_info[acmd->device_id],
17082ffc8bcaSDan McDonald 				    &io_info);
17092ffc8bcaSDan McDonald 				cmd->load_balance_flag |=
17102ffc8bcaSDan McDonald 				    MEGASAS_LOAD_BALANCE_FLAG;
17112ffc8bcaSDan McDonald 			} else {
17122ffc8bcaSDan McDonald 				cmd->load_balance_flag &=
17132ffc8bcaSDan McDonald 				    ~MEGASAS_LOAD_BALANCE_FLAG;
17142ffc8bcaSDan McDonald 			}
17152ffc8bcaSDan McDonald 
17162ffc8bcaSDan McDonald 			ReqDescUnion->SCSIIO.DevHandle = io_info.devHandle;
17172ffc8bcaSDan McDonald 			ddi_put16(acc_handle, &scsi_raid_io->DevHandle,
17182ffc8bcaSDan McDonald 			    io_info.devHandle);
17192ffc8bcaSDan McDonald 
1720e65bc174SAndy Fiddaman 		} else { /* FP Not Possible */
1721e65bc174SAndy Fiddaman 
17222ffc8bcaSDan McDonald 			ddi_put8(acc_handle, &scsi_raid_io->Function,
17232ffc8bcaSDan McDonald 			    MPI2_FUNCTION_LD_IO_REQUEST);
17242ffc8bcaSDan McDonald 
17252ffc8bcaSDan McDonald 			ddi_put16(acc_handle,
17262ffc8bcaSDan McDonald 			    &scsi_raid_io->DevHandle, acmd->device_id);
17272ffc8bcaSDan McDonald 
17282ffc8bcaSDan McDonald 			ReqDescUnion->SCSIIO.RequestFlags =
17292ffc8bcaSDan McDonald 			    (MPI2_REQ_DESCRIPT_FLAGS_LD_IO <<
17302ffc8bcaSDan McDonald 			    MPI2_REQ_DESCRIPT_FLAGS_TYPE_SHIFT);
17312ffc8bcaSDan McDonald 
17322ffc8bcaSDan McDonald 			ddi_put16(acc_handle,
17332ffc8bcaSDan McDonald 			    &scsi_raid_io->RaidContext.timeoutValue,
17342ffc8bcaSDan McDonald 			    local_map_ptr->raidMap.fpPdIoTimeoutSec);
17352ffc8bcaSDan McDonald 
1736df950592SHummyPkg 			if (instance->gen3) {
17372ffc8bcaSDan McDonald 				uint8_t regLockFlags = ddi_get8(acc_handle,
17382ffc8bcaSDan McDonald 				    &scsi_raid_io->RaidContext.regLockFlags);
17392ffc8bcaSDan McDonald 
17402ffc8bcaSDan McDonald 				if (regLockFlags == REGION_TYPE_UNUSED) {
17412ffc8bcaSDan McDonald 					ReqDescUnion->SCSIIO.RequestFlags =
17422ffc8bcaSDan McDonald 					    (MPI2_REQ_DESCRIPT_FLAGS_NO_LOCK <<
17432ffc8bcaSDan McDonald 					    MPI2_REQ_DESCRIPT_FLAGS_TYPE_SHIFT);
17442ffc8bcaSDan McDonald 				}
17452ffc8bcaSDan McDonald 
17462ffc8bcaSDan McDonald 				regLockFlags |=
17472ffc8bcaSDan McDonald 				    (MR_RL_FLAGS_GRANT_DESTINATION_CPU0 |
17482ffc8bcaSDan McDonald 				    MR_RL_FLAGS_SEQ_NUM_ENABLE);
17492ffc8bcaSDan McDonald 
17502ffc8bcaSDan McDonald 				ddi_put8(acc_handle,
17512ffc8bcaSDan McDonald 				    &scsi_raid_io->RaidContext.nsegType,
17522ffc8bcaSDan McDonald 				    ((0x01 << MPI2_NSEG_FLAGS_SHIFT) |
17532ffc8bcaSDan McDonald 				    MPI2_TYPE_CUDA));
17542ffc8bcaSDan McDonald 				ddi_put8(acc_handle,
17552ffc8bcaSDan McDonald 				    &scsi_raid_io->RaidContext.regLockFlags,
17562ffc8bcaSDan McDonald 				    regLockFlags);
17572ffc8bcaSDan McDonald 			}
17582ffc8bcaSDan McDonald 		} /* Not FP */
17592ffc8bcaSDan McDonald 
17602ffc8bcaSDan McDonald 		/* Release SYNC MAP UPDATE lock */
17612ffc8bcaSDan McDonald 		mutex_exit(&instance->sync_map_mtx);
17622ffc8bcaSDan McDonald 
17632ffc8bcaSDan McDonald 		break;
1764e65bc174SAndy Fiddaman 
17652ffc8bcaSDan McDonald 		case 0x35: { /* SCMD_SYNCHRONIZE_CACHE */
17662ffc8bcaSDan McDonald 			return_raid_msg_pkt(instance, cmd);
17672ffc8bcaSDan McDonald 			*cmd_done = 1;
17682ffc8bcaSDan McDonald 			return (NULL);
17692ffc8bcaSDan McDonald 		}
17702ffc8bcaSDan McDonald 
17712ffc8bcaSDan McDonald 		case SCMD_MODE_SENSE:
17722ffc8bcaSDan McDonald 		case SCMD_MODE_SENSE_G1: {
17732ffc8bcaSDan McDonald 			union scsi_cdb	*cdbp;
17742ffc8bcaSDan McDonald 			uint16_t	page_code;
17752ffc8bcaSDan McDonald 
17762ffc8bcaSDan McDonald 			cdbp = (void *)pkt->pkt_cdbp;
17772ffc8bcaSDan McDonald 			page_code = (uint16_t)cdbp->cdb_un.sg.scsi[0];
17782ffc8bcaSDan McDonald 			switch (page_code) {
17792ffc8bcaSDan McDonald 			case 0x3:
17802ffc8bcaSDan McDonald 			case 0x4:
17812ffc8bcaSDan McDonald 				(void) mrsas_mode_sense_build(pkt);
17822ffc8bcaSDan McDonald 				return_raid_msg_pkt(instance, cmd);
17832ffc8bcaSDan McDonald 				*cmd_done = 1;
17842ffc8bcaSDan McDonald 				return (NULL);
17852ffc8bcaSDan McDonald 			}
1786e65bc174SAndy Fiddaman 			return (cmd);
17872ffc8bcaSDan McDonald 		}
17882ffc8bcaSDan McDonald 
1789e65bc174SAndy Fiddaman 		default:
1790e65bc174SAndy Fiddaman 			/* Pass-through command to logical drive */
1791e65bc174SAndy Fiddaman 			ddi_put8(acc_handle, &scsi_raid_io->Function,
1792e65bc174SAndy Fiddaman 			    MPI2_FUNCTION_LD_IO_REQUEST);
1793e65bc174SAndy Fiddaman 			ddi_put8(acc_handle, &scsi_raid_io->LUN[1], acmd->lun);
1794e65bc174SAndy Fiddaman 			ddi_put16(acc_handle, &scsi_raid_io->DevHandle,
1795e65bc174SAndy Fiddaman 			    acmd->device_id);
1796e65bc174SAndy Fiddaman 			ReqDescUnion->SCSIIO.RequestFlags =
1797e65bc174SAndy Fiddaman 			    (MPI2_REQ_DESCRIPT_FLAGS_SCSI_IO <<
1798e65bc174SAndy Fiddaman 			    MPI2_REQ_DESCRIPT_FLAGS_TYPE_SHIFT);
1799e65bc174SAndy Fiddaman 			break;
1800e65bc174SAndy Fiddaman 		}
1801e65bc174SAndy Fiddaman 	} else { /* Physical */
1802e65bc174SAndy Fiddaman 		/* Pass-through command to physical drive */
18032ffc8bcaSDan McDonald 
18042ffc8bcaSDan McDonald 		/* Acquire SYNC MAP UPDATE lock */
18052ffc8bcaSDan McDonald 		mutex_enter(&instance->sync_map_mtx);
18062ffc8bcaSDan McDonald 
1807e65bc174SAndy Fiddaman 		local_map_ptr = instance->ld_map[instance->map_id & 1];
18082ffc8bcaSDan McDonald 
18092ffc8bcaSDan McDonald 		ddi_put8(acc_handle, &scsi_raid_io->Function,
18102ffc8bcaSDan McDonald 		    MPI2_FUNCTION_SCSI_IO_REQUEST);
18112ffc8bcaSDan McDonald 
18122ffc8bcaSDan McDonald 		ReqDescUnion->SCSIIO.RequestFlags =
18132ffc8bcaSDan McDonald 		    (MPI2_REQ_DESCRIPT_FLAGS_HIGH_PRIORITY <<
18142ffc8bcaSDan McDonald 		    MPI2_REQ_DESCRIPT_FLAGS_TYPE_SHIFT);
18152ffc8bcaSDan McDonald 
18162ffc8bcaSDan McDonald 		ddi_put16(acc_handle, &scsi_raid_io->DevHandle,
18172ffc8bcaSDan McDonald 		    local_map_ptr->raidMap.
18182ffc8bcaSDan McDonald 		    devHndlInfo[acmd->device_id].curDevHdl);
18192ffc8bcaSDan McDonald 
18202ffc8bcaSDan McDonald 		/* Set regLockFlasgs to REGION_TYPE_BYPASS */
18212ffc8bcaSDan McDonald 		ddi_put8(acc_handle,
18222ffc8bcaSDan McDonald 		    &scsi_raid_io->RaidContext.regLockFlags, 0);
18232ffc8bcaSDan McDonald 		ddi_put64(acc_handle,
1824e65bc174SAndy Fiddaman 		    &scsi_raid_io->RaidContext.regLockRowLBA, 0);
18252ffc8bcaSDan McDonald 		ddi_put32(acc_handle,
1826e65bc174SAndy Fiddaman 		    &scsi_raid_io->RaidContext.regLockLength, 0);
18272ffc8bcaSDan McDonald 		ddi_put8(acc_handle,
18282ffc8bcaSDan McDonald 		    &scsi_raid_io->RaidContext.RAIDFlags,
18292ffc8bcaSDan McDonald 		    MR_RAID_FLAGS_IO_SUB_TYPE_SYSTEM_PD <<
18302ffc8bcaSDan McDonald 		    MR_RAID_CTX_RAID_FLAGS_IO_SUB_TYPE_SHIFT);
18312ffc8bcaSDan McDonald 		ddi_put16(acc_handle,
18322ffc8bcaSDan McDonald 		    &scsi_raid_io->RaidContext.timeoutValue,
18332ffc8bcaSDan McDonald 		    local_map_ptr->raidMap.fpPdIoTimeoutSec);
18342ffc8bcaSDan McDonald 		ddi_put16(acc_handle,
18352ffc8bcaSDan McDonald 		    &scsi_raid_io->RaidContext.ldTargetId,
18362ffc8bcaSDan McDonald 		    acmd->device_id);
18372ffc8bcaSDan McDonald 		ddi_put8(acc_handle,
18382ffc8bcaSDan McDonald 		    &scsi_raid_io->LUN[1], acmd->lun);
18392ffc8bcaSDan McDonald 
1840df950592SHummyPkg 		if (instance->fast_path_io && instance->gen3) {
1841e65bc174SAndy Fiddaman 			uint16_t IoFlags = ddi_get16(acc_handle,
1842e65bc174SAndy Fiddaman 			    &scsi_raid_io->IoFlags);
1843e65bc174SAndy Fiddaman 			IoFlags |= MPI25_SAS_DEVICE0_FLAGS_ENABLED_FAST_PATH;
1844e65bc174SAndy Fiddaman 			ddi_put16(acc_handle, &scsi_raid_io->IoFlags, IoFlags);
1845e65bc174SAndy Fiddaman 		}
1846e65bc174SAndy Fiddaman 		ddi_put16(acc_handle, &ReqDescUnion->SCSIIO.DevHandle,
1847e65bc174SAndy Fiddaman 		    local_map_ptr->raidMap.
1848e65bc174SAndy Fiddaman 		    devHndlInfo[acmd->device_id].curDevHdl);
1849e65bc174SAndy Fiddaman 
18502ffc8bcaSDan McDonald 		/* Release SYNC MAP UPDATE lock */
18512ffc8bcaSDan McDonald 		mutex_exit(&instance->sync_map_mtx);
18522ffc8bcaSDan McDonald 	}
18532ffc8bcaSDan McDonald 
1854e65bc174SAndy Fiddaman 	/* Set sense buffer physical address/length in scsi_io_request. */
1855e65bc174SAndy Fiddaman 	ddi_put32(acc_handle, &scsi_raid_io->SenseBufferLowAddress,
18562ffc8bcaSDan McDonald 	    cmd->sense_phys_addr1);
1857e65bc174SAndy Fiddaman 	ddi_put8(acc_handle, &scsi_raid_io->SenseBufferLength, SENSE_LENGTH);
18582ffc8bcaSDan McDonald 
18592ffc8bcaSDan McDonald 	/* Construct SGL */
18602ffc8bcaSDan McDonald 	ddi_put8(acc_handle, &scsi_raid_io->SGLOffset0,
18612ffc8bcaSDan McDonald 	    offsetof(MPI2_RAID_SCSI_IO_REQUEST, SGL) / 4);
18622ffc8bcaSDan McDonald 
18632ffc8bcaSDan McDonald 	(void) mr_sas_tbolt_build_sgl(instance, acmd, cmd,
18642ffc8bcaSDan McDonald 	    scsi_raid_io, &datalen);
18652ffc8bcaSDan McDonald 
1866e65bc174SAndy Fiddaman 	ddi_put32(acc_handle, &scsi_raid_io->DataLength, datalen);
18672ffc8bcaSDan McDonald 
18682ffc8bcaSDan McDonald 	con_log(CL_ANN, (CE_CONT,
18692ffc8bcaSDan McDonald 	    "tbolt_build_cmd CDB[0] =%x, TargetID =%x\n",
18702ffc8bcaSDan McDonald 	    pkt->pkt_cdbp[0], acmd->device_id));
18712ffc8bcaSDan McDonald 	con_log(CL_DLEVEL1, (CE_CONT,
18722ffc8bcaSDan McDonald 	    "data length = %x\n",
18732ffc8bcaSDan McDonald 	    scsi_raid_io->DataLength));
18742ffc8bcaSDan McDonald 	con_log(CL_DLEVEL1, (CE_CONT,
18752ffc8bcaSDan McDonald 	    "cdb length = %x\n",
18762ffc8bcaSDan McDonald 	    acmd->cmd_cdblen));
18772ffc8bcaSDan McDonald 
18782ffc8bcaSDan McDonald 	return (cmd);
18792ffc8bcaSDan McDonald }
18802ffc8bcaSDan McDonald 
18812ffc8bcaSDan McDonald uint32_t
tbolt_read_fw_status_reg(struct mrsas_instance * instance)18822ffc8bcaSDan McDonald tbolt_read_fw_status_reg(struct mrsas_instance *instance)
18832ffc8bcaSDan McDonald {
18842ffc8bcaSDan McDonald 	return ((uint32_t)RD_OB_SCRATCH_PAD_0(instance));
18852ffc8bcaSDan McDonald }
18862ffc8bcaSDan McDonald 
18872ffc8bcaSDan McDonald void
tbolt_issue_cmd(struct mrsas_cmd * cmd,struct mrsas_instance * instance)18882ffc8bcaSDan McDonald tbolt_issue_cmd(struct mrsas_cmd *cmd, struct mrsas_instance *instance)
18892ffc8bcaSDan McDonald {
18902ffc8bcaSDan McDonald 	MRSAS_REQUEST_DESCRIPTOR_UNION *req_desc = cmd->request_desc;
18911a5e258fSJosef 'Jeff' Sipek 	atomic_inc_16(&instance->fw_outstanding);
18922ffc8bcaSDan McDonald 
18932ffc8bcaSDan McDonald 	struct scsi_pkt *pkt;
18942ffc8bcaSDan McDonald 
18952ffc8bcaSDan McDonald 	con_log(CL_ANN1,
18962ffc8bcaSDan McDonald 	    (CE_NOTE, "tbolt_issue_cmd: cmd->[SMID]=0x%X", cmd->SMID));
18972ffc8bcaSDan McDonald 
18982ffc8bcaSDan McDonald 	con_log(CL_DLEVEL1, (CE_CONT,
18992ffc8bcaSDan McDonald 	    " [req desc Words] %" PRIx64 " \n", req_desc->Words));
19002ffc8bcaSDan McDonald 	con_log(CL_DLEVEL1, (CE_CONT,
19012ffc8bcaSDan McDonald 	    " [req desc low part] %x \n",
19022ffc8bcaSDan McDonald 	    (uint_t)(req_desc->Words & 0xffffffffff)));
19032ffc8bcaSDan McDonald 	con_log(CL_DLEVEL1, (CE_CONT,
19042ffc8bcaSDan McDonald 	    " [req desc high part] %x \n", (uint_t)(req_desc->Words >> 32)));
19052ffc8bcaSDan McDonald 	pkt = cmd->pkt;
19062ffc8bcaSDan McDonald 
19072ffc8bcaSDan McDonald 	if (pkt) {
19082ffc8bcaSDan McDonald 		con_log(CL_ANN1, (CE_CONT, "%llx :TBOLT issue_cmd_ppc:"
19092ffc8bcaSDan McDonald 		    "ISSUED CMD TO FW : called : cmd:"
19102ffc8bcaSDan McDonald 		    ": %p instance : %p pkt : %p pkt_time : %x\n",
19112ffc8bcaSDan McDonald 		    gethrtime(), (void *)cmd, (void *)instance,
19122ffc8bcaSDan McDonald 		    (void *)pkt, cmd->drv_pkt_time));
19132ffc8bcaSDan McDonald 		if (instance->adapterresetinprogress) {
19142ffc8bcaSDan McDonald 			cmd->drv_pkt_time = (uint16_t)debug_timeout_g;
19152ffc8bcaSDan McDonald 			con_log(CL_ANN, (CE_NOTE,
19162ffc8bcaSDan McDonald 			    "TBOLT Reset the scsi_pkt timer"));
19172ffc8bcaSDan McDonald 		} else {
19182ffc8bcaSDan McDonald 			push_pending_mfi_pkt(instance, cmd);
19192ffc8bcaSDan McDonald 		}
19202ffc8bcaSDan McDonald 
19212ffc8bcaSDan McDonald 	} else {
19222ffc8bcaSDan McDonald 		con_log(CL_ANN1, (CE_CONT, "%llx :TBOLT issue_cmd_ppc:"
19232ffc8bcaSDan McDonald 		    "ISSUED CMD TO FW : called : cmd : %p, instance: %p"
19242ffc8bcaSDan McDonald 		    "(NO PKT)\n", gethrtime(), (void *)cmd, (void *)instance));
19252ffc8bcaSDan McDonald 	}
19262ffc8bcaSDan McDonald 
19272ffc8bcaSDan McDonald 	/* Issue the command to the FW */
19282ffc8bcaSDan McDonald 	mutex_enter(&instance->reg_write_mtx);
19292ffc8bcaSDan McDonald 	WR_IB_LOW_QPORT((uint32_t)(req_desc->Words), instance);
19302ffc8bcaSDan McDonald 	WR_IB_HIGH_QPORT((uint32_t)(req_desc->Words >> 32), instance);
19312ffc8bcaSDan McDonald 	mutex_exit(&instance->reg_write_mtx);
19322ffc8bcaSDan McDonald }
19332ffc8bcaSDan McDonald 
19342ffc8bcaSDan McDonald /*
19352ffc8bcaSDan McDonald  * issue_cmd_in_sync_mode
19362ffc8bcaSDan McDonald  */
19372ffc8bcaSDan McDonald int
tbolt_issue_cmd_in_sync_mode(struct mrsas_instance * instance,struct mrsas_cmd * cmd)19382ffc8bcaSDan McDonald tbolt_issue_cmd_in_sync_mode(struct mrsas_instance *instance,
19392ffc8bcaSDan McDonald     struct mrsas_cmd *cmd)
19402ffc8bcaSDan McDonald {
19412ffc8bcaSDan McDonald 	int		i;
19422ffc8bcaSDan McDonald 	uint32_t	msecs = MFI_POLL_TIMEOUT_SECS * MILLISEC;
19432ffc8bcaSDan McDonald 	MRSAS_REQUEST_DESCRIPTOR_UNION *req_desc = cmd->request_desc;
19442ffc8bcaSDan McDonald 
19452ffc8bcaSDan McDonald 	struct mrsas_header	*hdr;
19462ffc8bcaSDan McDonald 	hdr = (struct mrsas_header *)&cmd->frame->hdr;
19472ffc8bcaSDan McDonald 
19482ffc8bcaSDan McDonald 	con_log(CL_ANN,
19492ffc8bcaSDan McDonald 	    (CE_NOTE, "tbolt_issue_cmd_in_sync_mode: cmd->[SMID]=0x%X",
19502ffc8bcaSDan McDonald 	    cmd->SMID));
19512ffc8bcaSDan McDonald 
19522ffc8bcaSDan McDonald 
19532ffc8bcaSDan McDonald 	if (instance->adapterresetinprogress) {
19542ffc8bcaSDan McDonald 		cmd->drv_pkt_time = ddi_get16
19552ffc8bcaSDan McDonald 		    (cmd->frame_dma_obj.acc_handle, &hdr->timeout);
19562ffc8bcaSDan McDonald 		if (cmd->drv_pkt_time < debug_timeout_g)
19572ffc8bcaSDan McDonald 			cmd->drv_pkt_time = (uint16_t)debug_timeout_g;
19582ffc8bcaSDan McDonald 		con_log(CL_ANN, (CE_NOTE, "tbolt_issue_cmd_in_sync_mode:"
19592ffc8bcaSDan McDonald 		    "RESET-IN-PROGRESS, issue cmd & return."));
19602ffc8bcaSDan McDonald 
19612ffc8bcaSDan McDonald 		mutex_enter(&instance->reg_write_mtx);
19622ffc8bcaSDan McDonald 		WR_IB_LOW_QPORT((uint32_t)(req_desc->Words), instance);
19632ffc8bcaSDan McDonald 		WR_IB_HIGH_QPORT((uint32_t)(req_desc->Words >> 32), instance);
19642ffc8bcaSDan McDonald 		mutex_exit(&instance->reg_write_mtx);
19652ffc8bcaSDan McDonald 
19662ffc8bcaSDan McDonald 		return (DDI_SUCCESS);
19672ffc8bcaSDan McDonald 	} else {
19682ffc8bcaSDan McDonald 		con_log(CL_ANN1, (CE_NOTE,
19692ffc8bcaSDan McDonald 		    "tbolt_issue_cmd_in_sync_mode: pushing the pkt"));
19702ffc8bcaSDan McDonald 		push_pending_mfi_pkt(instance, cmd);
19712ffc8bcaSDan McDonald 	}
19722ffc8bcaSDan McDonald 
19732ffc8bcaSDan McDonald 	con_log(CL_DLEVEL2, (CE_NOTE,
19742ffc8bcaSDan McDonald 	    "HighQport offset :%p",
19752ffc8bcaSDan McDonald 	    (void *)((uintptr_t)(instance)->regmap + IB_HIGH_QPORT)));
19762ffc8bcaSDan McDonald 	con_log(CL_DLEVEL2, (CE_NOTE,
19772ffc8bcaSDan McDonald 	    "LowQport offset :%p",
19782ffc8bcaSDan McDonald 	    (void *)((uintptr_t)(instance)->regmap + IB_LOW_QPORT)));
19792ffc8bcaSDan McDonald 
19802ffc8bcaSDan McDonald 	cmd->sync_cmd = MRSAS_TRUE;
19812ffc8bcaSDan McDonald 	cmd->cmd_status =  ENODATA;
19822ffc8bcaSDan McDonald 
19832ffc8bcaSDan McDonald 
19842ffc8bcaSDan McDonald 	mutex_enter(&instance->reg_write_mtx);
19852ffc8bcaSDan McDonald 	WR_IB_LOW_QPORT((uint32_t)(req_desc->Words), instance);
19862ffc8bcaSDan McDonald 	WR_IB_HIGH_QPORT((uint32_t)(req_desc->Words >> 32), instance);
19872ffc8bcaSDan McDonald 	mutex_exit(&instance->reg_write_mtx);
19882ffc8bcaSDan McDonald 
19892ffc8bcaSDan McDonald 	con_log(CL_ANN1, (CE_NOTE,
19902ffc8bcaSDan McDonald 	    " req desc high part %x", (uint_t)(req_desc->Words >> 32)));
19912ffc8bcaSDan McDonald 	con_log(CL_ANN1, (CE_NOTE, " req desc low part %x",
19922ffc8bcaSDan McDonald 	    (uint_t)(req_desc->Words & 0xffffffff)));
19932ffc8bcaSDan McDonald 
19942ffc8bcaSDan McDonald 	mutex_enter(&instance->int_cmd_mtx);
19952ffc8bcaSDan McDonald 	for (i = 0; i < msecs && (cmd->cmd_status == ENODATA); i++) {
19962ffc8bcaSDan McDonald 		cv_wait(&instance->int_cmd_cv, &instance->int_cmd_mtx);
19972ffc8bcaSDan McDonald 	}
19982ffc8bcaSDan McDonald 	mutex_exit(&instance->int_cmd_mtx);
19992ffc8bcaSDan McDonald 
20002ffc8bcaSDan McDonald 
20012ffc8bcaSDan McDonald 	if (i < (msecs -1)) {
20022ffc8bcaSDan McDonald 		return (DDI_SUCCESS);
20032ffc8bcaSDan McDonald 	} else {
20042ffc8bcaSDan McDonald 		return (DDI_FAILURE);
20052ffc8bcaSDan McDonald 	}
20062ffc8bcaSDan McDonald }
20072ffc8bcaSDan McDonald 
20082ffc8bcaSDan McDonald /*
20092ffc8bcaSDan McDonald  * issue_cmd_in_poll_mode
20102ffc8bcaSDan McDonald  */
20112ffc8bcaSDan McDonald int
tbolt_issue_cmd_in_poll_mode(struct mrsas_instance * instance,struct mrsas_cmd * cmd)20122ffc8bcaSDan McDonald tbolt_issue_cmd_in_poll_mode(struct mrsas_instance *instance,
20132ffc8bcaSDan McDonald     struct mrsas_cmd *cmd)
20142ffc8bcaSDan McDonald {
20152ffc8bcaSDan McDonald 	int		i;
20162ffc8bcaSDan McDonald 	uint16_t	flags;
20172ffc8bcaSDan McDonald 	uint32_t	msecs = MFI_POLL_TIMEOUT_SECS * MILLISEC;
20182ffc8bcaSDan McDonald 	struct mrsas_header *frame_hdr;
20192ffc8bcaSDan McDonald 
20202ffc8bcaSDan McDonald 	con_log(CL_ANN,
20212ffc8bcaSDan McDonald 	    (CE_NOTE, "tbolt_issue_cmd_in_poll_mode: cmd->[SMID]=0x%X",
20222ffc8bcaSDan McDonald 	    cmd->SMID));
20232ffc8bcaSDan McDonald 
20242ffc8bcaSDan McDonald 	MRSAS_REQUEST_DESCRIPTOR_UNION *req_desc = cmd->request_desc;
20252ffc8bcaSDan McDonald 
20262ffc8bcaSDan McDonald 	frame_hdr = (struct mrsas_header *)&cmd->frame->hdr;
20272ffc8bcaSDan McDonald 	ddi_put8(cmd->frame_dma_obj.acc_handle, &frame_hdr->cmd_status,
20282ffc8bcaSDan McDonald 	    MFI_CMD_STATUS_POLL_MODE);
20292ffc8bcaSDan McDonald 	flags = ddi_get16(cmd->frame_dma_obj.acc_handle, &frame_hdr->flags);
20302ffc8bcaSDan McDonald 	flags	|= MFI_FRAME_DONT_POST_IN_REPLY_QUEUE;
20312ffc8bcaSDan McDonald 	ddi_put16(cmd->frame_dma_obj.acc_handle, &frame_hdr->flags, flags);
20322ffc8bcaSDan McDonald 
20332ffc8bcaSDan McDonald 	con_log(CL_ANN1, (CE_NOTE, " req desc low part %x",
20342ffc8bcaSDan McDonald 	    (uint_t)(req_desc->Words & 0xffffffff)));
20352ffc8bcaSDan McDonald 	con_log(CL_ANN1, (CE_NOTE,
20362ffc8bcaSDan McDonald 	    " req desc high part %x", (uint_t)(req_desc->Words >> 32)));
20372ffc8bcaSDan McDonald 
20382ffc8bcaSDan McDonald 	/* issue the frame using inbound queue port */
20392ffc8bcaSDan McDonald 	mutex_enter(&instance->reg_write_mtx);
20402ffc8bcaSDan McDonald 	WR_IB_LOW_QPORT((uint32_t)(req_desc->Words), instance);
20412ffc8bcaSDan McDonald 	WR_IB_HIGH_QPORT((uint32_t)(req_desc->Words >> 32), instance);
20422ffc8bcaSDan McDonald 	mutex_exit(&instance->reg_write_mtx);
20432ffc8bcaSDan McDonald 
20442ffc8bcaSDan McDonald 	for (i = 0; i < msecs && (
20452ffc8bcaSDan McDonald 	    ddi_get8(cmd->frame_dma_obj.acc_handle, &frame_hdr->cmd_status)
20462ffc8bcaSDan McDonald 	    == MFI_CMD_STATUS_POLL_MODE); i++) {
20472ffc8bcaSDan McDonald 		/* wait for cmd_status to change from 0xFF */
20482ffc8bcaSDan McDonald 		drv_usecwait(MILLISEC); /* wait for 1000 usecs */
20492ffc8bcaSDan McDonald 	}
20502ffc8bcaSDan McDonald 
20514bc492d2SAndy Fiddaman 	DTRACE_PROBE1(tbolt_complete_poll_cmd, uint8_t, i);
20524bc492d2SAndy Fiddaman 
20532ffc8bcaSDan McDonald 	if (ddi_get8(cmd->frame_dma_obj.acc_handle,
20542ffc8bcaSDan McDonald 	    &frame_hdr->cmd_status) == MFI_CMD_STATUS_POLL_MODE) {
20552ffc8bcaSDan McDonald 		con_log(CL_ANN1, (CE_NOTE,
20562ffc8bcaSDan McDonald 		    " cmd failed %" PRIx64, (req_desc->Words)));
20572ffc8bcaSDan McDonald 		return (DDI_FAILURE);
20582ffc8bcaSDan McDonald 	}
20592ffc8bcaSDan McDonald 
20602ffc8bcaSDan McDonald 	return (DDI_SUCCESS);
20612ffc8bcaSDan McDonald }
20622ffc8bcaSDan McDonald 
20632ffc8bcaSDan McDonald void
tbolt_enable_intr(struct mrsas_instance * instance)20642ffc8bcaSDan McDonald tbolt_enable_intr(struct mrsas_instance *instance)
20652ffc8bcaSDan McDonald {
20662ffc8bcaSDan McDonald 	/* TODO: For Thunderbolt/Invader also clear intr on enable */
20672ffc8bcaSDan McDonald 	/* writel(~0, &regs->outbound_intr_status); */
20682ffc8bcaSDan McDonald 	/* readl(&regs->outbound_intr_status); */
20692ffc8bcaSDan McDonald 
20702ffc8bcaSDan McDonald 	WR_OB_INTR_MASK(~(MFI_FUSION_ENABLE_INTERRUPT_MASK), instance);
20712ffc8bcaSDan McDonald 
20722ffc8bcaSDan McDonald 	/* dummy read to force PCI flush */
20732ffc8bcaSDan McDonald 	(void) RD_OB_INTR_MASK(instance);
20742ffc8bcaSDan McDonald 
20752ffc8bcaSDan McDonald }
20762ffc8bcaSDan McDonald 
20772ffc8bcaSDan McDonald void
tbolt_disable_intr(struct mrsas_instance * instance)20782ffc8bcaSDan McDonald tbolt_disable_intr(struct mrsas_instance *instance)
20792ffc8bcaSDan McDonald {
20802ffc8bcaSDan McDonald 	uint32_t mask = 0xFFFFFFFF;
20812ffc8bcaSDan McDonald 
20822ffc8bcaSDan McDonald 	WR_OB_INTR_MASK(mask, instance);
20832ffc8bcaSDan McDonald 
20842ffc8bcaSDan McDonald 	/* Dummy readl to force pci flush */
20852ffc8bcaSDan McDonald 
20862ffc8bcaSDan McDonald 	(void) RD_OB_INTR_MASK(instance);
20872ffc8bcaSDan McDonald }
20882ffc8bcaSDan McDonald 
20892ffc8bcaSDan McDonald 
20902ffc8bcaSDan McDonald int
tbolt_intr_ack(struct mrsas_instance * instance)20912ffc8bcaSDan McDonald tbolt_intr_ack(struct mrsas_instance *instance)
20922ffc8bcaSDan McDonald {
20932ffc8bcaSDan McDonald 	uint32_t	status;
20942ffc8bcaSDan McDonald 
20952ffc8bcaSDan McDonald 	/* check if it is our interrupt */
20962ffc8bcaSDan McDonald 	status = RD_OB_INTR_STATUS(instance);
20972ffc8bcaSDan McDonald 	con_log(CL_ANN1, (CE_NOTE,
20982ffc8bcaSDan McDonald 	    "chkpnt: Entered tbolt_intr_ack status = %d", status));
20992ffc8bcaSDan McDonald 
21002ffc8bcaSDan McDonald 	if (!(status & MFI_FUSION_ENABLE_INTERRUPT_MASK)) {
21012ffc8bcaSDan McDonald 		return (DDI_INTR_UNCLAIMED);
21022ffc8bcaSDan McDonald 	}
21032ffc8bcaSDan McDonald 
21042ffc8bcaSDan McDonald 	if (mrsas_check_acc_handle(instance->regmap_handle) != DDI_SUCCESS) {
21052ffc8bcaSDan McDonald 		ddi_fm_service_impact(instance->dip, DDI_SERVICE_LOST);
21062ffc8bcaSDan McDonald 		return (DDI_INTR_UNCLAIMED);
21072ffc8bcaSDan McDonald 	}
21082ffc8bcaSDan McDonald 
21092ffc8bcaSDan McDonald 	if ((status & 1) || (status & MFI_FUSION_ENABLE_INTERRUPT_MASK)) {
21102ffc8bcaSDan McDonald 		/* clear the interrupt by writing back the same value */
21112ffc8bcaSDan McDonald 		WR_OB_INTR_STATUS(status, instance);
21122ffc8bcaSDan McDonald 		/* dummy READ */
21132ffc8bcaSDan McDonald 		(void) RD_OB_INTR_STATUS(instance);
21142ffc8bcaSDan McDonald 	}
21152ffc8bcaSDan McDonald 	return (DDI_INTR_CLAIMED);
21162ffc8bcaSDan McDonald }
21172ffc8bcaSDan McDonald 
21182ffc8bcaSDan McDonald /*
21192ffc8bcaSDan McDonald  * get_raid_msg_pkt : Get a command from the free pool
21202ffc8bcaSDan McDonald  * After successful allocation, the caller of this routine
21212ffc8bcaSDan McDonald  * must clear the frame buffer (memset to zero) before
21222ffc8bcaSDan McDonald  * using the packet further.
21232ffc8bcaSDan McDonald  *
21242ffc8bcaSDan McDonald  * ***** Note *****
21252ffc8bcaSDan McDonald  * After clearing the frame buffer the context id of the
21262ffc8bcaSDan McDonald  * frame buffer SHOULD be restored back.
21272ffc8bcaSDan McDonald  */
21282ffc8bcaSDan McDonald 
21292ffc8bcaSDan McDonald struct mrsas_cmd *
get_raid_msg_pkt(struct mrsas_instance * instance)21302ffc8bcaSDan McDonald get_raid_msg_pkt(struct mrsas_instance *instance)
21312ffc8bcaSDan McDonald {
21322ffc8bcaSDan McDonald 	mlist_t			*head = &instance->cmd_pool_list;
21332ffc8bcaSDan McDonald 	struct mrsas_cmd	*cmd = NULL;
21342ffc8bcaSDan McDonald 
21352ffc8bcaSDan McDonald 	mutex_enter(&instance->cmd_pool_mtx);
21362ffc8bcaSDan McDonald 	ASSERT(mutex_owned(&instance->cmd_pool_mtx));
21372ffc8bcaSDan McDonald 
21382ffc8bcaSDan McDonald 
21392ffc8bcaSDan McDonald 	if (!mlist_empty(head)) {
21402ffc8bcaSDan McDonald 		cmd = mlist_entry(head->next, struct mrsas_cmd, list);
21412ffc8bcaSDan McDonald 		mlist_del_init(head->next);
21422ffc8bcaSDan McDonald 	}
21432ffc8bcaSDan McDonald 	if (cmd != NULL) {
21442ffc8bcaSDan McDonald 		cmd->pkt = NULL;
21452ffc8bcaSDan McDonald 		cmd->retry_count_for_ocr = 0;
21462ffc8bcaSDan McDonald 		cmd->drv_pkt_time = 0;
21472ffc8bcaSDan McDonald 	}
21482ffc8bcaSDan McDonald 	mutex_exit(&instance->cmd_pool_mtx);
21492ffc8bcaSDan McDonald 
21502ffc8bcaSDan McDonald 	if (cmd != NULL)
21512ffc8bcaSDan McDonald 		bzero(cmd->scsi_io_request,
21522ffc8bcaSDan McDonald 		    sizeof (Mpi2RaidSCSIIORequest_t));
21532ffc8bcaSDan McDonald 	return (cmd);
21542ffc8bcaSDan McDonald }
21552ffc8bcaSDan McDonald 
21562ffc8bcaSDan McDonald struct mrsas_cmd *
get_raid_msg_mfi_pkt(struct mrsas_instance * instance)21572ffc8bcaSDan McDonald get_raid_msg_mfi_pkt(struct mrsas_instance *instance)
21582ffc8bcaSDan McDonald {
21592ffc8bcaSDan McDonald 	mlist_t			*head = &instance->cmd_app_pool_list;
21602ffc8bcaSDan McDonald 	struct mrsas_cmd	*cmd = NULL;
21612ffc8bcaSDan McDonald 
21622ffc8bcaSDan McDonald 	mutex_enter(&instance->cmd_app_pool_mtx);
21632ffc8bcaSDan McDonald 	ASSERT(mutex_owned(&instance->cmd_app_pool_mtx));
21642ffc8bcaSDan McDonald 
21652ffc8bcaSDan McDonald 	if (!mlist_empty(head)) {
21662ffc8bcaSDan McDonald 		cmd = mlist_entry(head->next, struct mrsas_cmd, list);
21672ffc8bcaSDan McDonald 		mlist_del_init(head->next);
21682ffc8bcaSDan McDonald 	}
21692ffc8bcaSDan McDonald 	if (cmd != NULL) {
21702ffc8bcaSDan McDonald 		cmd->retry_count_for_ocr = 0;
21712ffc8bcaSDan McDonald 		cmd->drv_pkt_time = 0;
21722ffc8bcaSDan McDonald 		cmd->pkt = NULL;
21732ffc8bcaSDan McDonald 		cmd->request_desc = NULL;
21742ffc8bcaSDan McDonald 
21752ffc8bcaSDan McDonald 	}
21762ffc8bcaSDan McDonald 
21772ffc8bcaSDan McDonald 	mutex_exit(&instance->cmd_app_pool_mtx);
21782ffc8bcaSDan McDonald 
21792ffc8bcaSDan McDonald 	if (cmd != NULL) {
21802ffc8bcaSDan McDonald 		bzero(cmd->scsi_io_request,
21812ffc8bcaSDan McDonald 		    sizeof (Mpi2RaidSCSIIORequest_t));
21822ffc8bcaSDan McDonald 	}
21832ffc8bcaSDan McDonald 
21842ffc8bcaSDan McDonald 	return (cmd);
21852ffc8bcaSDan McDonald }
21862ffc8bcaSDan McDonald 
21872ffc8bcaSDan McDonald /*
21882ffc8bcaSDan McDonald  * return_raid_msg_pkt : Return a cmd to free command pool
21892ffc8bcaSDan McDonald  */
21902ffc8bcaSDan McDonald void
return_raid_msg_pkt(struct mrsas_instance * instance,struct mrsas_cmd * cmd)21912ffc8bcaSDan McDonald return_raid_msg_pkt(struct mrsas_instance *instance, struct mrsas_cmd *cmd)
21922ffc8bcaSDan McDonald {
21932ffc8bcaSDan McDonald 	mutex_enter(&instance->cmd_pool_mtx);
21942ffc8bcaSDan McDonald 	ASSERT(mutex_owned(&instance->cmd_pool_mtx));
21952ffc8bcaSDan McDonald 
21962ffc8bcaSDan McDonald 
21972ffc8bcaSDan McDonald 	mlist_add_tail(&cmd->list, &instance->cmd_pool_list);
21982ffc8bcaSDan McDonald 
21992ffc8bcaSDan McDonald 	mutex_exit(&instance->cmd_pool_mtx);
22002ffc8bcaSDan McDonald }
22012ffc8bcaSDan McDonald 
22022ffc8bcaSDan McDonald void
return_raid_msg_mfi_pkt(struct mrsas_instance * instance,struct mrsas_cmd * cmd)22032ffc8bcaSDan McDonald return_raid_msg_mfi_pkt(struct mrsas_instance *instance, struct mrsas_cmd *cmd)
22042ffc8bcaSDan McDonald {
22052ffc8bcaSDan McDonald 	mutex_enter(&instance->cmd_app_pool_mtx);
22062ffc8bcaSDan McDonald 	ASSERT(mutex_owned(&instance->cmd_app_pool_mtx));
22072ffc8bcaSDan McDonald 
22082ffc8bcaSDan McDonald 	mlist_add_tail(&cmd->list, &instance->cmd_app_pool_list);
22092ffc8bcaSDan McDonald 
22102ffc8bcaSDan McDonald 	mutex_exit(&instance->cmd_app_pool_mtx);
22112ffc8bcaSDan McDonald }
22122ffc8bcaSDan McDonald 
22132ffc8bcaSDan McDonald 
22142ffc8bcaSDan McDonald void
mr_sas_tbolt_build_mfi_cmd(struct mrsas_instance * instance,struct mrsas_cmd * cmd)22152ffc8bcaSDan McDonald mr_sas_tbolt_build_mfi_cmd(struct mrsas_instance *instance,
22162ffc8bcaSDan McDonald     struct mrsas_cmd *cmd)
22172ffc8bcaSDan McDonald {
22182ffc8bcaSDan McDonald 	Mpi2RaidSCSIIORequest_t		*scsi_raid_io;
22192ffc8bcaSDan McDonald 	Mpi25IeeeSgeChain64_t		*scsi_raid_io_sgl_ieee;
22202ffc8bcaSDan McDonald 	MRSAS_REQUEST_DESCRIPTOR_UNION	*ReqDescUnion;
22212ffc8bcaSDan McDonald 	uint32_t			index;
22222ffc8bcaSDan McDonald 	ddi_acc_handle_t acc_handle =
22232ffc8bcaSDan McDonald 	    instance->mpi2_frame_pool_dma_obj.acc_handle;
22242ffc8bcaSDan McDonald 
22252ffc8bcaSDan McDonald 	if (!instance->tbolt) {
22262ffc8bcaSDan McDonald 		con_log(CL_ANN, (CE_NOTE, "Not MFA enabled."));
22272ffc8bcaSDan McDonald 		return;
22282ffc8bcaSDan McDonald 	}
22292ffc8bcaSDan McDonald 
22302ffc8bcaSDan McDonald 	index = cmd->index;
22312ffc8bcaSDan McDonald 
22322ffc8bcaSDan McDonald 	ReqDescUnion = mr_sas_get_request_descriptor(instance, index);
22332ffc8bcaSDan McDonald 
22342ffc8bcaSDan McDonald 	if (!ReqDescUnion) {
22352ffc8bcaSDan McDonald 		con_log(CL_ANN1, (CE_NOTE, "[NULL REQDESC]"));
22362ffc8bcaSDan McDonald 		return;
22372ffc8bcaSDan McDonald 	}
22382ffc8bcaSDan McDonald 
22392ffc8bcaSDan McDonald 	con_log(CL_ANN1, (CE_NOTE, "[SMID]%x", cmd->SMID));
22402ffc8bcaSDan McDonald 
22412ffc8bcaSDan McDonald 	ReqDescUnion->Words = 0;
22422ffc8bcaSDan McDonald 
22432ffc8bcaSDan McDonald 	ReqDescUnion->SCSIIO.RequestFlags =
22442ffc8bcaSDan McDonald 	    (MPI2_REQ_DESCRIPT_FLAGS_SCSI_IO <<
22452ffc8bcaSDan McDonald 	    MPI2_REQ_DESCRIPT_FLAGS_TYPE_SHIFT);
22462ffc8bcaSDan McDonald 
22472ffc8bcaSDan McDonald 	ReqDescUnion->SCSIIO.SMID = cmd->SMID;
22482ffc8bcaSDan McDonald 
22492ffc8bcaSDan McDonald 	cmd->request_desc = ReqDescUnion;
22502ffc8bcaSDan McDonald 
22512ffc8bcaSDan McDonald 	/* get raid message frame pointer */
22522ffc8bcaSDan McDonald 	scsi_raid_io = (Mpi2RaidSCSIIORequest_t *)cmd->scsi_io_request;
22532ffc8bcaSDan McDonald 
2254df950592SHummyPkg 	if (instance->gen3) {
22552ffc8bcaSDan McDonald 		Mpi25IeeeSgeChain64_t *sgl_ptr_end = (Mpi25IeeeSgeChain64_t *)
22562ffc8bcaSDan McDonald 		    &scsi_raid_io->SGL.IeeeChain;
22572ffc8bcaSDan McDonald 		sgl_ptr_end += instance->max_sge_in_main_msg - 1;
22582ffc8bcaSDan McDonald 		ddi_put8(acc_handle, &sgl_ptr_end->Flags, 0);
22592ffc8bcaSDan McDonald 	}
22602ffc8bcaSDan McDonald 
22612ffc8bcaSDan McDonald 	ddi_put8(acc_handle, &scsi_raid_io->Function,
22622ffc8bcaSDan McDonald 	    MPI2_FUNCTION_PASSTHRU_IO_REQUEST);
22632ffc8bcaSDan McDonald 
22642ffc8bcaSDan McDonald 	ddi_put8(acc_handle, &scsi_raid_io->SGLOffset0,
22652ffc8bcaSDan McDonald 	    offsetof(MPI2_RAID_SCSI_IO_REQUEST, SGL) / 4);
22662ffc8bcaSDan McDonald 
22672ffc8bcaSDan McDonald 	ddi_put8(acc_handle, &scsi_raid_io->ChainOffset,
22682ffc8bcaSDan McDonald 	    (U8)offsetof(MPI2_RAID_SCSI_IO_REQUEST, SGL) / 16);
22692ffc8bcaSDan McDonald 
22702ffc8bcaSDan McDonald 	ddi_put32(acc_handle, &scsi_raid_io->SenseBufferLowAddress,
22712ffc8bcaSDan McDonald 	    cmd->sense_phys_addr1);
22722ffc8bcaSDan McDonald 
22732ffc8bcaSDan McDonald 
22742ffc8bcaSDan McDonald 	scsi_raid_io_sgl_ieee =
22752ffc8bcaSDan McDonald 	    (Mpi25IeeeSgeChain64_t *)&scsi_raid_io->SGL.IeeeChain;
22762ffc8bcaSDan McDonald 
22772ffc8bcaSDan McDonald 	ddi_put64(acc_handle, &scsi_raid_io_sgl_ieee->Address,
22782ffc8bcaSDan McDonald 	    (U64)cmd->frame_phys_addr);
22792ffc8bcaSDan McDonald 
22802ffc8bcaSDan McDonald 	ddi_put8(acc_handle,
22812ffc8bcaSDan McDonald 	    &scsi_raid_io_sgl_ieee->Flags, (IEEE_SGE_FLAGS_CHAIN_ELEMENT |
22822ffc8bcaSDan McDonald 	    MPI2_IEEE_SGE_FLAGS_IOCPLBNTA_ADDR));
22832ffc8bcaSDan McDonald 	/* LSI put hardcoded 1024 instead of MEGASAS_MAX_SZ_CHAIN_FRAME. */
22842ffc8bcaSDan McDonald 	ddi_put32(acc_handle, &scsi_raid_io_sgl_ieee->Length, 1024);
22852ffc8bcaSDan McDonald 
22862ffc8bcaSDan McDonald 	con_log(CL_ANN1, (CE_NOTE,
22872ffc8bcaSDan McDonald 	    "[MFI CMD PHY ADDRESS]:%" PRIx64,
22882ffc8bcaSDan McDonald 	    scsi_raid_io_sgl_ieee->Address));
22892ffc8bcaSDan McDonald 	con_log(CL_ANN1, (CE_NOTE,
22902ffc8bcaSDan McDonald 	    "[SGL Length]:%x", scsi_raid_io_sgl_ieee->Length));
22912ffc8bcaSDan McDonald 	con_log(CL_ANN1, (CE_NOTE, "[SGL Flags]:%x",
22922ffc8bcaSDan McDonald 	    scsi_raid_io_sgl_ieee->Flags));
22932ffc8bcaSDan McDonald }
22942ffc8bcaSDan McDonald 
22952ffc8bcaSDan McDonald 
22962ffc8bcaSDan McDonald void
tbolt_complete_cmd(struct mrsas_instance * instance,struct mrsas_cmd * cmd)22972ffc8bcaSDan McDonald tbolt_complete_cmd(struct mrsas_instance *instance,
22982ffc8bcaSDan McDonald     struct mrsas_cmd *cmd)
22992ffc8bcaSDan McDonald {
23002ffc8bcaSDan McDonald 	uint8_t				status;
23012ffc8bcaSDan McDonald 	uint8_t				extStatus;
2302091932b4SAndy Fiddaman 	uint8_t				function;
23032ffc8bcaSDan McDonald 	uint8_t				arm;
23042ffc8bcaSDan McDonald 	struct scsa_cmd			*acmd;
23052ffc8bcaSDan McDonald 	struct scsi_pkt			*pkt;
23062ffc8bcaSDan McDonald 	struct scsi_arq_status		*arqstat;
23072ffc8bcaSDan McDonald 	Mpi2RaidSCSIIORequest_t		*scsi_raid_io;
23082ffc8bcaSDan McDonald 	LD_LOAD_BALANCE_INFO		*lbinfo;
23092ffc8bcaSDan McDonald 	ddi_acc_handle_t acc_handle =
23102ffc8bcaSDan McDonald 	    instance->mpi2_frame_pool_dma_obj.acc_handle;
23112ffc8bcaSDan McDonald 
23122ffc8bcaSDan McDonald 	scsi_raid_io = (Mpi2RaidSCSIIORequest_t *)cmd->scsi_io_request;
23132ffc8bcaSDan McDonald 
23142ffc8bcaSDan McDonald 	status = ddi_get8(acc_handle, &scsi_raid_io->RaidContext.status);
23152ffc8bcaSDan McDonald 	extStatus = ddi_get8(acc_handle, &scsi_raid_io->RaidContext.extStatus);
23162ffc8bcaSDan McDonald 
23172ffc8bcaSDan McDonald 	con_log(CL_DLEVEL3, (CE_NOTE, "status %x", status));
23182ffc8bcaSDan McDonald 	con_log(CL_DLEVEL3, (CE_NOTE, "extStatus %x", extStatus));
23192ffc8bcaSDan McDonald 
23202ffc8bcaSDan McDonald 	if (status != MFI_STAT_OK) {
23212ffc8bcaSDan McDonald 		con_log(CL_ANN, (CE_WARN,
23222ffc8bcaSDan McDonald 		    "IO Cmd Failed SMID %x", cmd->SMID));
23232ffc8bcaSDan McDonald 	} else {
23242ffc8bcaSDan McDonald 		con_log(CL_ANN, (CE_NOTE,
23252ffc8bcaSDan McDonald 		    "IO Cmd Success  SMID %x", cmd->SMID));
23262ffc8bcaSDan McDonald 	}
23272ffc8bcaSDan McDonald 
23282ffc8bcaSDan McDonald 	/* regular commands */
23292ffc8bcaSDan McDonald 
2330091932b4SAndy Fiddaman 	function = ddi_get8(acc_handle, &scsi_raid_io->Function);
2331091932b4SAndy Fiddaman 	DTRACE_PROBE3(tbolt_complete_cmd, uint8_t, function,
2332091932b4SAndy Fiddaman 	    uint8_t, status, uint8_t, extStatus);
2333091932b4SAndy Fiddaman 
2334091932b4SAndy Fiddaman 	switch (function) {
23352ffc8bcaSDan McDonald 
23362ffc8bcaSDan McDonald 	case MPI2_FUNCTION_SCSI_IO_REQUEST :  /* Fast Path IO. */
23372ffc8bcaSDan McDonald 		acmd =	(struct scsa_cmd *)cmd->cmd;
23382ffc8bcaSDan McDonald 		lbinfo = &instance->load_balance_info[acmd->device_id];
23392ffc8bcaSDan McDonald 
23402ffc8bcaSDan McDonald 		if (cmd->load_balance_flag & MEGASAS_LOAD_BALANCE_FLAG) {
23412ffc8bcaSDan McDonald 			arm = lbinfo->raid1DevHandle[0] ==
23422ffc8bcaSDan McDonald 			    scsi_raid_io->DevHandle ? 0 : 1;
23432ffc8bcaSDan McDonald 
23442ffc8bcaSDan McDonald 			lbinfo->scsi_pending_cmds[arm]--;
23452ffc8bcaSDan McDonald 			cmd->load_balance_flag &= ~MEGASAS_LOAD_BALANCE_FLAG;
23462ffc8bcaSDan McDonald 		}
23472ffc8bcaSDan McDonald 		con_log(CL_DLEVEL3, (CE_NOTE,
23482ffc8bcaSDan McDonald 		    "FastPath IO Completion Success "));
23492ffc8bcaSDan McDonald 		/* FALLTHRU */
23502ffc8bcaSDan McDonald 
23512ffc8bcaSDan McDonald 	case MPI2_FUNCTION_LD_IO_REQUEST :   { /* Regular Path IO. */
23522ffc8bcaSDan McDonald 		acmd =	(struct scsa_cmd *)cmd->cmd;
23532ffc8bcaSDan McDonald 		pkt =	(struct scsi_pkt *)CMD2PKT(acmd);
23542ffc8bcaSDan McDonald 
23552ffc8bcaSDan McDonald 		if (acmd->cmd_flags & CFLAG_DMAVALID) {
23562ffc8bcaSDan McDonald 			if (acmd->cmd_flags & CFLAG_CONSISTENT) {
23572ffc8bcaSDan McDonald 				(void) ddi_dma_sync(acmd->cmd_dmahandle,
23582ffc8bcaSDan McDonald 				    acmd->cmd_dma_offset, acmd->cmd_dma_len,
23592ffc8bcaSDan McDonald 				    DDI_DMA_SYNC_FORCPU);
23602ffc8bcaSDan McDonald 			}
23612ffc8bcaSDan McDonald 		}
23622ffc8bcaSDan McDonald 
23632ffc8bcaSDan McDonald 		pkt->pkt_reason		= CMD_CMPLT;
23642ffc8bcaSDan McDonald 		pkt->pkt_statistics	= 0;
23652ffc8bcaSDan McDonald 		pkt->pkt_state = STATE_GOT_BUS | STATE_GOT_TARGET |
23662ffc8bcaSDan McDonald 		    STATE_SENT_CMD | STATE_XFERRED_DATA | STATE_GOT_STATUS;
23672ffc8bcaSDan McDonald 
23682ffc8bcaSDan McDonald 		con_log(CL_ANN, (CE_CONT, " CDB[0] = %x completed for %s: "
23692ffc8bcaSDan McDonald 		    "size %lx SMID %x cmd_status %x", pkt->pkt_cdbp[0],
23702ffc8bcaSDan McDonald 		    ((acmd->islogical) ? "LD" : "PD"),
23712ffc8bcaSDan McDonald 		    acmd->cmd_dmacount, cmd->SMID, status));
23722ffc8bcaSDan McDonald 
23732ffc8bcaSDan McDonald 		if (pkt->pkt_cdbp[0] == SCMD_INQUIRY) {
23742ffc8bcaSDan McDonald 			struct scsi_inquiry	*inq;
23752ffc8bcaSDan McDonald 
23762ffc8bcaSDan McDonald 			if (acmd->cmd_dmacount != 0) {
23772ffc8bcaSDan McDonald 				bp_mapin(acmd->cmd_buf);
23782ffc8bcaSDan McDonald 				inq = (struct scsi_inquiry *)
23792ffc8bcaSDan McDonald 				    acmd->cmd_buf->b_un.b_addr;
23802ffc8bcaSDan McDonald 
23812ffc8bcaSDan McDonald 				/* don't expose physical drives to OS */
23822ffc8bcaSDan McDonald 				if (acmd->islogical &&
23832ffc8bcaSDan McDonald 				    (status == MFI_STAT_OK)) {
23842ffc8bcaSDan McDonald 					display_scsi_inquiry((caddr_t)inq);
23852ffc8bcaSDan McDonald 				} else if ((status == MFI_STAT_OK) &&
23862ffc8bcaSDan McDonald 				    inq->inq_dtype == DTYPE_DIRECT) {
23872ffc8bcaSDan McDonald 					display_scsi_inquiry((caddr_t)inq);
23882ffc8bcaSDan McDonald 				} else {
23892ffc8bcaSDan McDonald 					/* for physical disk */
23902ffc8bcaSDan McDonald 					status = MFI_STAT_DEVICE_NOT_FOUND;
23912ffc8bcaSDan McDonald 				}
23922ffc8bcaSDan McDonald 			}
23932ffc8bcaSDan McDonald 		}
23942ffc8bcaSDan McDonald 
23952ffc8bcaSDan McDonald 		switch (status) {
23962ffc8bcaSDan McDonald 		case MFI_STAT_OK:
23972ffc8bcaSDan McDonald 			pkt->pkt_scbp[0] = STATUS_GOOD;
23982ffc8bcaSDan McDonald 			break;
23992ffc8bcaSDan McDonald 		case MFI_STAT_LD_CC_IN_PROGRESS:
24002ffc8bcaSDan McDonald 		case MFI_STAT_LD_RECON_IN_PROGRESS:
24012ffc8bcaSDan McDonald 			pkt->pkt_scbp[0] = STATUS_GOOD;
24022ffc8bcaSDan McDonald 			break;
24032ffc8bcaSDan McDonald 		case MFI_STAT_LD_INIT_IN_PROGRESS:
24042ffc8bcaSDan McDonald 			pkt->pkt_reason	= CMD_TRAN_ERR;
24052ffc8bcaSDan McDonald 			break;
24062ffc8bcaSDan McDonald 		case MFI_STAT_SCSI_IO_FAILED:
2407ff38cf9dSAndy Fiddaman 			dev_err(instance->dip, CE_WARN,
2408ff38cf9dSAndy Fiddaman 			    "tbolt_complete_cmd: scsi_io failed");
24092ffc8bcaSDan McDonald 			pkt->pkt_reason	= CMD_TRAN_ERR;
24102ffc8bcaSDan McDonald 			break;
24112ffc8bcaSDan McDonald 		case MFI_STAT_SCSI_DONE_WITH_ERROR:
24122ffc8bcaSDan McDonald 			con_log(CL_ANN, (CE_WARN,
24132ffc8bcaSDan McDonald 			    "tbolt_complete_cmd: scsi_done with error"));
24142ffc8bcaSDan McDonald 
24152ffc8bcaSDan McDonald 			pkt->pkt_reason	= CMD_CMPLT;
24162ffc8bcaSDan McDonald 			((struct scsi_status *)pkt->pkt_scbp)->sts_chk = 1;
24172ffc8bcaSDan McDonald 
24182ffc8bcaSDan McDonald 			if (pkt->pkt_cdbp[0] == SCMD_TEST_UNIT_READY) {
24192ffc8bcaSDan McDonald 				con_log(CL_ANN,
24202ffc8bcaSDan McDonald 				    (CE_WARN, "TEST_UNIT_READY fail"));
24212ffc8bcaSDan McDonald 			} else {
24222ffc8bcaSDan McDonald 				pkt->pkt_state |= STATE_ARQ_DONE;
24232ffc8bcaSDan McDonald 				arqstat = (void *)(pkt->pkt_scbp);
24242ffc8bcaSDan McDonald 				arqstat->sts_rqpkt_reason = CMD_CMPLT;
24252ffc8bcaSDan McDonald 				arqstat->sts_rqpkt_resid = 0;
24262ffc8bcaSDan McDonald 				arqstat->sts_rqpkt_state |=
24272ffc8bcaSDan McDonald 				    STATE_GOT_BUS | STATE_GOT_TARGET
24282ffc8bcaSDan McDonald 				    | STATE_SENT_CMD
24292ffc8bcaSDan McDonald 				    | STATE_XFERRED_DATA;
24302ffc8bcaSDan McDonald 				*(uint8_t *)&arqstat->sts_rqpkt_status =
24312ffc8bcaSDan McDonald 				    STATUS_GOOD;
24322ffc8bcaSDan McDonald 				con_log(CL_ANN1,
24332ffc8bcaSDan McDonald 				    (CE_NOTE, "Copying Sense data %x",
24342ffc8bcaSDan McDonald 				    cmd->SMID));
24352ffc8bcaSDan McDonald 
24362ffc8bcaSDan McDonald 				ddi_rep_get8(acc_handle,
24372ffc8bcaSDan McDonald 				    (uint8_t *)&(arqstat->sts_sensedata),
24382ffc8bcaSDan McDonald 				    cmd->sense1,
24392ffc8bcaSDan McDonald 				    sizeof (struct scsi_extended_sense),
24402ffc8bcaSDan McDonald 				    DDI_DEV_AUTOINCR);
24412ffc8bcaSDan McDonald 
24422ffc8bcaSDan McDonald 			}
24432ffc8bcaSDan McDonald 			break;
24442ffc8bcaSDan McDonald 		case MFI_STAT_LD_OFFLINE:
2445ff38cf9dSAndy Fiddaman 			dev_err(instance->dip, CE_WARN,
24462ffc8bcaSDan McDonald 			    "tbolt_complete_cmd: ld offline "
24472ffc8bcaSDan McDonald 			    "CDB[0]=0x%x targetId=0x%x devhandle=0x%x",
24482ffc8bcaSDan McDonald 			    /* UNDO: */
24492ffc8bcaSDan McDonald 			    ddi_get8(acc_handle, &scsi_raid_io->CDB.CDB32[0]),
24502ffc8bcaSDan McDonald 
24512ffc8bcaSDan McDonald 			    ddi_get16(acc_handle,
24522ffc8bcaSDan McDonald 			    &scsi_raid_io->RaidContext.ldTargetId),
24532ffc8bcaSDan McDonald 
24542ffc8bcaSDan McDonald 			    ddi_get16(acc_handle, &scsi_raid_io->DevHandle));
24552ffc8bcaSDan McDonald 
24562ffc8bcaSDan McDonald 			pkt->pkt_reason	= CMD_DEV_GONE;
24572ffc8bcaSDan McDonald 			pkt->pkt_statistics  = STAT_DISCON;
24582ffc8bcaSDan McDonald 			break;
24592ffc8bcaSDan McDonald 		case MFI_STAT_DEVICE_NOT_FOUND:
24602ffc8bcaSDan McDonald 			con_log(CL_ANN, (CE_CONT,
24612ffc8bcaSDan McDonald 			    "tbolt_complete_cmd: device not found error"));
24622ffc8bcaSDan McDonald 			pkt->pkt_reason	= CMD_DEV_GONE;
24632ffc8bcaSDan McDonald 			pkt->pkt_statistics  = STAT_DISCON;
24642ffc8bcaSDan McDonald 			break;
24652ffc8bcaSDan McDonald 
24662ffc8bcaSDan McDonald 		case MFI_STAT_LD_LBA_OUT_OF_RANGE:
24672ffc8bcaSDan McDonald 			pkt->pkt_state |= STATE_ARQ_DONE;
24682ffc8bcaSDan McDonald 			pkt->pkt_reason	= CMD_CMPLT;
24692ffc8bcaSDan McDonald 			((struct scsi_status *)pkt->pkt_scbp)->sts_chk = 1;
24702ffc8bcaSDan McDonald 
24712ffc8bcaSDan McDonald 			arqstat = (void *)(pkt->pkt_scbp);
24722ffc8bcaSDan McDonald 			arqstat->sts_rqpkt_reason = CMD_CMPLT;
24732ffc8bcaSDan McDonald 			arqstat->sts_rqpkt_resid = 0;
24742ffc8bcaSDan McDonald 			arqstat->sts_rqpkt_state |= STATE_GOT_BUS
24752ffc8bcaSDan McDonald 			    | STATE_GOT_TARGET | STATE_SENT_CMD
24762ffc8bcaSDan McDonald 			    | STATE_XFERRED_DATA;
24772ffc8bcaSDan McDonald 			*(uint8_t *)&arqstat->sts_rqpkt_status = STATUS_GOOD;
24782ffc8bcaSDan McDonald 
24792ffc8bcaSDan McDonald 			arqstat->sts_sensedata.es_valid = 1;
24802ffc8bcaSDan McDonald 			arqstat->sts_sensedata.es_key = KEY_ILLEGAL_REQUEST;
24812ffc8bcaSDan McDonald 			arqstat->sts_sensedata.es_class = CLASS_EXTENDED_SENSE;
24822ffc8bcaSDan McDonald 
24832ffc8bcaSDan McDonald 			/*
24842ffc8bcaSDan McDonald 			 * LOGICAL BLOCK ADDRESS OUT OF RANGE:
24852ffc8bcaSDan McDonald 			 * ASC: 0x21h; ASCQ: 0x00h;
24862ffc8bcaSDan McDonald 			 */
24872ffc8bcaSDan McDonald 			arqstat->sts_sensedata.es_add_code = 0x21;
24882ffc8bcaSDan McDonald 			arqstat->sts_sensedata.es_qual_code = 0x00;
24892ffc8bcaSDan McDonald 			break;
24902ffc8bcaSDan McDonald 		case MFI_STAT_INVALID_CMD:
24912ffc8bcaSDan McDonald 		case MFI_STAT_INVALID_DCMD:
24922ffc8bcaSDan McDonald 		case MFI_STAT_INVALID_PARAMETER:
24932ffc8bcaSDan McDonald 		case MFI_STAT_INVALID_SEQUENCE_NUMBER:
24942ffc8bcaSDan McDonald 		default:
2495ff38cf9dSAndy Fiddaman 			dev_err(instance->dip, CE_WARN,
2496ff38cf9dSAndy Fiddaman 			    "tbolt_complete_cmd: Unknown status!");
24972ffc8bcaSDan McDonald 			pkt->pkt_reason	= CMD_TRAN_ERR;
24982ffc8bcaSDan McDonald 
24992ffc8bcaSDan McDonald 			break;
25002ffc8bcaSDan McDonald 		}
25012ffc8bcaSDan McDonald 
25022ffc8bcaSDan McDonald 		atomic_add_16(&instance->fw_outstanding, (-1));
25032ffc8bcaSDan McDonald 
25042ffc8bcaSDan McDonald 		(void) mrsas_common_check(instance, cmd);
25052ffc8bcaSDan McDonald 		if (acmd->cmd_dmahandle) {
25062ffc8bcaSDan McDonald 			if (mrsas_check_dma_handle(acmd->cmd_dmahandle) !=
25072ffc8bcaSDan McDonald 			    DDI_SUCCESS) {
25082ffc8bcaSDan McDonald 				ddi_fm_service_impact(instance->dip,
25092ffc8bcaSDan McDonald 				    DDI_SERVICE_UNAFFECTED);
25102ffc8bcaSDan McDonald 				pkt->pkt_reason = CMD_TRAN_ERR;
25112ffc8bcaSDan McDonald 				pkt->pkt_statistics = 0;
25122ffc8bcaSDan McDonald 			}
25132ffc8bcaSDan McDonald 		}
25142ffc8bcaSDan McDonald 
25152ffc8bcaSDan McDonald 		/* Call the callback routine */
25162ffc8bcaSDan McDonald 		if (((pkt->pkt_flags & FLAG_NOINTR) == 0) && pkt->pkt_comp)
25172ffc8bcaSDan McDonald 			(*pkt->pkt_comp)(pkt);
25182ffc8bcaSDan McDonald 
25192ffc8bcaSDan McDonald 		con_log(CL_ANN1, (CE_NOTE, "Free smid %x", cmd->SMID));
25202ffc8bcaSDan McDonald 
25212ffc8bcaSDan McDonald 		ddi_put8(acc_handle, &scsi_raid_io->RaidContext.status, 0);
25222ffc8bcaSDan McDonald 
25232ffc8bcaSDan McDonald 		ddi_put8(acc_handle, &scsi_raid_io->RaidContext.extStatus, 0);
25242ffc8bcaSDan McDonald 
25252ffc8bcaSDan McDonald 		return_raid_msg_pkt(instance, cmd);
25262ffc8bcaSDan McDonald 		break;
25272ffc8bcaSDan McDonald 	}
25282ffc8bcaSDan McDonald 	case MPI2_FUNCTION_PASSTHRU_IO_REQUEST:	 /* MFA command. */
25292ffc8bcaSDan McDonald 
25302ffc8bcaSDan McDonald 		if (cmd->frame->dcmd.opcode == MR_DCMD_LD_MAP_GET_INFO &&
25312ffc8bcaSDan McDonald 		    cmd->frame->dcmd.mbox.b[1] == 1) {
25322ffc8bcaSDan McDonald 
25332ffc8bcaSDan McDonald 			mutex_enter(&instance->sync_map_mtx);
25342ffc8bcaSDan McDonald 
25352ffc8bcaSDan McDonald 			con_log(CL_ANN, (CE_NOTE,
25362ffc8bcaSDan McDonald 			    "LDMAP sync command	SMID RECEIVED 0x%X",
25372ffc8bcaSDan McDonald 			    cmd->SMID));
25382ffc8bcaSDan McDonald 			if (cmd->frame->hdr.cmd_status != 0) {
2539ff38cf9dSAndy Fiddaman 				dev_err(instance->dip, CE_WARN,
25402ffc8bcaSDan McDonald 				    "map sync failed, status = 0x%x.",
25412ffc8bcaSDan McDonald 				    cmd->frame->hdr.cmd_status);
25422ffc8bcaSDan McDonald 			} else {
25432ffc8bcaSDan McDonald 				instance->map_id++;
2544ff38cf9dSAndy Fiddaman 				con_log(CL_ANN1, (CE_NOTE,
25452ffc8bcaSDan McDonald 				    "map sync received, switched map_id to %"
2546ff38cf9dSAndy Fiddaman 				    PRIu64, instance->map_id));
25472ffc8bcaSDan McDonald 			}
25482ffc8bcaSDan McDonald 
2549e65bc174SAndy Fiddaman 			if (MR_ValidateMapInfo(
2550e65bc174SAndy Fiddaman 			    instance->ld_map[instance->map_id & 1],
25512ffc8bcaSDan McDonald 			    instance->load_balance_info)) {
25522ffc8bcaSDan McDonald 				instance->fast_path_io = 1;
25532ffc8bcaSDan McDonald 			} else {
25542ffc8bcaSDan McDonald 				instance->fast_path_io = 0;
25552ffc8bcaSDan McDonald 			}
25562ffc8bcaSDan McDonald 
25572ffc8bcaSDan McDonald 			con_log(CL_ANN, (CE_NOTE,
25582ffc8bcaSDan McDonald 			    "instance->fast_path_io %d",
25592ffc8bcaSDan McDonald 			    instance->fast_path_io));
25602ffc8bcaSDan McDonald 
25612ffc8bcaSDan McDonald 			instance->unroll.syncCmd = 0;
25622ffc8bcaSDan McDonald 
25632ffc8bcaSDan McDonald 			if (instance->map_update_cmd == cmd) {
25642ffc8bcaSDan McDonald 				return_raid_msg_pkt(instance, cmd);
25652ffc8bcaSDan McDonald 				atomic_add_16(&instance->fw_outstanding, (-1));
25662ffc8bcaSDan McDonald 				(void) mrsas_tbolt_sync_map_info(instance);
25672ffc8bcaSDan McDonald 			}
25682ffc8bcaSDan McDonald 
2569ff38cf9dSAndy Fiddaman 			con_log(CL_ANN1, (CE_NOTE,
2570ff38cf9dSAndy Fiddaman 			    "LDMAP sync completed, ldcount=%d",
2571ff38cf9dSAndy Fiddaman 			    instance->ld_map[instance->map_id & 1]
2572ff38cf9dSAndy Fiddaman 			    ->raidMap.ldCount));
25732ffc8bcaSDan McDonald 			mutex_exit(&instance->sync_map_mtx);
25742ffc8bcaSDan McDonald 			break;
25752ffc8bcaSDan McDonald 		}
25762ffc8bcaSDan McDonald 
25772ffc8bcaSDan McDonald 		if (cmd->frame->dcmd.opcode == MR_DCMD_CTRL_EVENT_WAIT) {
25782ffc8bcaSDan McDonald 			con_log(CL_ANN1, (CE_CONT,
25792ffc8bcaSDan McDonald 			    "AEN command SMID RECEIVED 0x%X",
25802ffc8bcaSDan McDonald 			    cmd->SMID));
25812ffc8bcaSDan McDonald 			if ((instance->aen_cmd == cmd) &&
25822ffc8bcaSDan McDonald 			    (instance->aen_cmd->abort_aen)) {
25832ffc8bcaSDan McDonald 				con_log(CL_ANN, (CE_WARN, "mrsas_softintr: "
25842ffc8bcaSDan McDonald 				    "aborted_aen returned"));
25852ffc8bcaSDan McDonald 			} else {
25862ffc8bcaSDan McDonald 				atomic_add_16(&instance->fw_outstanding, (-1));
25872ffc8bcaSDan McDonald 				service_mfi_aen(instance, cmd);
25882ffc8bcaSDan McDonald 			}
25892ffc8bcaSDan McDonald 		}
25902ffc8bcaSDan McDonald 
25912ffc8bcaSDan McDonald 		if (cmd->sync_cmd == MRSAS_TRUE) {
25922ffc8bcaSDan McDonald 			con_log(CL_ANN1, (CE_CONT,
25932ffc8bcaSDan McDonald 			    "Sync-mode Command Response SMID RECEIVED 0x%X",
25942ffc8bcaSDan McDonald 			    cmd->SMID));
25952ffc8bcaSDan McDonald 
25962ffc8bcaSDan McDonald 			tbolt_complete_cmd_in_sync_mode(instance, cmd);
25972ffc8bcaSDan McDonald 		} else {
25982ffc8bcaSDan McDonald 			con_log(CL_ANN, (CE_CONT,
25992ffc8bcaSDan McDonald 			    "tbolt_complete_cmd: Wrong SMID RECEIVED 0x%X",
26002ffc8bcaSDan McDonald 			    cmd->SMID));
26012ffc8bcaSDan McDonald 		}
26022ffc8bcaSDan McDonald 		break;
26032ffc8bcaSDan McDonald 	default:
26042ffc8bcaSDan McDonald 		mrsas_fm_ereport(instance, DDI_FM_DEVICE_NO_RESPONSE);
26052ffc8bcaSDan McDonald 		ddi_fm_service_impact(instance->dip, DDI_SERVICE_LOST);
26062ffc8bcaSDan McDonald 
26072ffc8bcaSDan McDonald 		/* free message */
26082ffc8bcaSDan McDonald 		con_log(CL_ANN,
26092ffc8bcaSDan McDonald 		    (CE_NOTE, "tbolt_complete_cmd: Unknown Type!!!!!!!!"));
26102ffc8bcaSDan McDonald 		break;
26112ffc8bcaSDan McDonald 	}
26122ffc8bcaSDan McDonald }
26132ffc8bcaSDan McDonald 
26142ffc8bcaSDan McDonald uint_t
mr_sas_tbolt_process_outstanding_cmd(struct mrsas_instance * instance)26152ffc8bcaSDan McDonald mr_sas_tbolt_process_outstanding_cmd(struct mrsas_instance *instance)
26162ffc8bcaSDan McDonald {
26172ffc8bcaSDan McDonald 	uint8_t				replyType;
26182ffc8bcaSDan McDonald 	Mpi2SCSIIOSuccessReplyDescriptor_t *replyDesc;
26192ffc8bcaSDan McDonald 	Mpi2ReplyDescriptorsUnion_t	*desc;
26202ffc8bcaSDan McDonald 	uint16_t			smid;
26212ffc8bcaSDan McDonald 	union desc_value		d_val;
26222ffc8bcaSDan McDonald 	struct mrsas_cmd		*cmd;
26232ffc8bcaSDan McDonald 
26242ffc8bcaSDan McDonald 	struct mrsas_header	*hdr;
26252ffc8bcaSDan McDonald 	struct scsi_pkt		*pkt;
26262ffc8bcaSDan McDonald 
26272ffc8bcaSDan McDonald 	(void) ddi_dma_sync(instance->reply_desc_dma_obj.dma_handle,
26282ffc8bcaSDan McDonald 	    0, 0, DDI_DMA_SYNC_FORDEV);
26292ffc8bcaSDan McDonald 
26302ffc8bcaSDan McDonald 	(void) ddi_dma_sync(instance->reply_desc_dma_obj.dma_handle,
26312ffc8bcaSDan McDonald 	    0, 0, DDI_DMA_SYNC_FORCPU);
26322ffc8bcaSDan McDonald 
26332ffc8bcaSDan McDonald 	desc = instance->reply_frame_pool;
26342ffc8bcaSDan McDonald 	desc += instance->reply_read_index;
26352ffc8bcaSDan McDonald 
26362ffc8bcaSDan McDonald 	replyDesc = (MPI2_SCSI_IO_SUCCESS_REPLY_DESCRIPTOR *)desc;
26372ffc8bcaSDan McDonald 	replyType = replyDesc->ReplyFlags &
26382ffc8bcaSDan McDonald 	    MPI2_RPY_DESCRIPT_FLAGS_TYPE_MASK;
26392ffc8bcaSDan McDonald 
26402ffc8bcaSDan McDonald 	if (replyType == MPI2_RPY_DESCRIPT_FLAGS_UNUSED)
26412ffc8bcaSDan McDonald 		return (DDI_INTR_UNCLAIMED);
26422ffc8bcaSDan McDonald 
26432ffc8bcaSDan McDonald 	if (mrsas_check_dma_handle(instance->mfi_internal_dma_obj.dma_handle)
26442ffc8bcaSDan McDonald 	    != DDI_SUCCESS) {
26452ffc8bcaSDan McDonald 		mrsas_fm_ereport(instance, DDI_FM_DEVICE_NO_RESPONSE);
26462ffc8bcaSDan McDonald 		ddi_fm_service_impact(instance->dip, DDI_SERVICE_LOST);
26472ffc8bcaSDan McDonald 		con_log(CL_ANN1,
26482ffc8bcaSDan McDonald 		    (CE_WARN, "mr_sas_tbolt_process_outstanding_cmd(): "
26492ffc8bcaSDan McDonald 		    "FMA check, returning DDI_INTR_UNCLAIMED"));
26502ffc8bcaSDan McDonald 		return (DDI_INTR_CLAIMED);
26512ffc8bcaSDan McDonald 	}
26522ffc8bcaSDan McDonald 
26532ffc8bcaSDan McDonald 	con_log(CL_ANN1, (CE_NOTE, "Reply Desc	= %p  Words = %" PRIx64,
26542ffc8bcaSDan McDonald 	    (void *)desc, desc->Words));
26552ffc8bcaSDan McDonald 
26562ffc8bcaSDan McDonald 	d_val.word = desc->Words;
26572ffc8bcaSDan McDonald 
26582ffc8bcaSDan McDonald 
26592ffc8bcaSDan McDonald 	/* Read Reply descriptor */
26602ffc8bcaSDan McDonald 	while ((d_val.u1.low != 0xffffffff) &&
26612ffc8bcaSDan McDonald 	    (d_val.u1.high != 0xffffffff)) {
26622ffc8bcaSDan McDonald 
26632ffc8bcaSDan McDonald 		(void) ddi_dma_sync(instance->reply_desc_dma_obj.dma_handle,
26642ffc8bcaSDan McDonald 		    0, 0, DDI_DMA_SYNC_FORCPU);
26652ffc8bcaSDan McDonald 
26662ffc8bcaSDan McDonald 		smid = replyDesc->SMID;
26672ffc8bcaSDan McDonald 
26682ffc8bcaSDan McDonald 		if (!smid || smid > instance->max_fw_cmds + 1) {
26692ffc8bcaSDan McDonald 			con_log(CL_ANN1, (CE_NOTE,
26702ffc8bcaSDan McDonald 			    "Reply Desc at Break  = %p	Words = %" PRIx64,
26712ffc8bcaSDan McDonald 			    (void *)desc, desc->Words));
26722ffc8bcaSDan McDonald 			break;
26732ffc8bcaSDan McDonald 		}
26742ffc8bcaSDan McDonald 
26752ffc8bcaSDan McDonald 		cmd	= instance->cmd_list[smid - 1];
26762ffc8bcaSDan McDonald 		if (!cmd) {
26772ffc8bcaSDan McDonald 			con_log(CL_ANN1, (CE_NOTE, "mr_sas_tbolt_process_"
26782ffc8bcaSDan McDonald 			    "outstanding_cmd: Invalid command "
26792ffc8bcaSDan McDonald 			    " or Poll commad Received in completion path"));
26802ffc8bcaSDan McDonald 		} else {
26812ffc8bcaSDan McDonald 			mutex_enter(&instance->cmd_pend_mtx);
26822ffc8bcaSDan McDonald 			if (cmd->sync_cmd == MRSAS_TRUE) {
26832ffc8bcaSDan McDonald 				hdr = (struct mrsas_header *)&cmd->frame->hdr;
26842ffc8bcaSDan McDonald 				if (hdr) {
26852ffc8bcaSDan McDonald 					con_log(CL_ANN1, (CE_NOTE, "mr_sas_"
26862ffc8bcaSDan McDonald 					    "tbolt_process_outstanding_cmd:"
26872ffc8bcaSDan McDonald 					    " mlist_del_init(&cmd->list)."));
26882ffc8bcaSDan McDonald 					mlist_del_init(&cmd->list);
26892ffc8bcaSDan McDonald 				}
26902ffc8bcaSDan McDonald 			} else {
26912ffc8bcaSDan McDonald 				pkt = cmd->pkt;
26922ffc8bcaSDan McDonald 				if (pkt) {
26932ffc8bcaSDan McDonald 					con_log(CL_ANN1, (CE_NOTE, "mr_sas_"
26942ffc8bcaSDan McDonald 					    "tbolt_process_outstanding_cmd:"
26952ffc8bcaSDan McDonald 					    "mlist_del_init(&cmd->list)."));
26962ffc8bcaSDan McDonald 					mlist_del_init(&cmd->list);
26972ffc8bcaSDan McDonald 				}
26982ffc8bcaSDan McDonald 			}
26992ffc8bcaSDan McDonald 
27002ffc8bcaSDan McDonald 			mutex_exit(&instance->cmd_pend_mtx);
27012ffc8bcaSDan McDonald 
27022ffc8bcaSDan McDonald 			tbolt_complete_cmd(instance, cmd);
27032ffc8bcaSDan McDonald 		}
27042ffc8bcaSDan McDonald 		/* set it back to all 1s. */
27052ffc8bcaSDan McDonald 		desc->Words = -1LL;
27062ffc8bcaSDan McDonald 
27072ffc8bcaSDan McDonald 		instance->reply_read_index++;
27082ffc8bcaSDan McDonald 
27092ffc8bcaSDan McDonald 		if (instance->reply_read_index >= (instance->reply_q_depth)) {
27102ffc8bcaSDan McDonald 			con_log(CL_ANN1, (CE_NOTE, "wrap around"));
27112ffc8bcaSDan McDonald 			instance->reply_read_index = 0;
27122ffc8bcaSDan McDonald 		}
27132ffc8bcaSDan McDonald 
27142ffc8bcaSDan McDonald 		/* Get the next reply descriptor */
27152ffc8bcaSDan McDonald 		if (!instance->reply_read_index)
27162ffc8bcaSDan McDonald 			desc = instance->reply_frame_pool;
27172ffc8bcaSDan McDonald 		else
27182ffc8bcaSDan McDonald 			desc++;
27192ffc8bcaSDan McDonald 
27202ffc8bcaSDan McDonald 		replyDesc = (MPI2_SCSI_IO_SUCCESS_REPLY_DESCRIPTOR *)desc;
27212ffc8bcaSDan McDonald 
27222ffc8bcaSDan McDonald 		d_val.word = desc->Words;
27232ffc8bcaSDan McDonald 
27242ffc8bcaSDan McDonald 		con_log(CL_ANN1, (CE_NOTE,
27252ffc8bcaSDan McDonald 		    "Next Reply Desc  = %p Words = %" PRIx64,
27262ffc8bcaSDan McDonald 		    (void *)desc, desc->Words));
27272ffc8bcaSDan McDonald 
27282ffc8bcaSDan McDonald 		replyType = replyDesc->ReplyFlags &
27292ffc8bcaSDan McDonald 		    MPI2_RPY_DESCRIPT_FLAGS_TYPE_MASK;
27302ffc8bcaSDan McDonald 
27312ffc8bcaSDan McDonald 		if (replyType == MPI2_RPY_DESCRIPT_FLAGS_UNUSED)
27322ffc8bcaSDan McDonald 			break;
27332ffc8bcaSDan McDonald 
27342ffc8bcaSDan McDonald 	} /* End of while loop. */
27352ffc8bcaSDan McDonald 
27362ffc8bcaSDan McDonald 	/* update replyIndex to FW */
27372ffc8bcaSDan McDonald 	WR_MPI2_REPLY_POST_INDEX(instance->reply_read_index, instance);
27382ffc8bcaSDan McDonald 
27392ffc8bcaSDan McDonald 
27402ffc8bcaSDan McDonald 	(void) ddi_dma_sync(instance->reply_desc_dma_obj.dma_handle,
27412ffc8bcaSDan McDonald 	    0, 0, DDI_DMA_SYNC_FORDEV);
27422ffc8bcaSDan McDonald 
27432ffc8bcaSDan McDonald 	(void) ddi_dma_sync(instance->reply_desc_dma_obj.dma_handle,
27442ffc8bcaSDan McDonald 	    0, 0, DDI_DMA_SYNC_FORCPU);
27452ffc8bcaSDan McDonald 	return (DDI_INTR_CLAIMED);
27462ffc8bcaSDan McDonald }
27472ffc8bcaSDan McDonald 
27482ffc8bcaSDan McDonald 
27492ffc8bcaSDan McDonald 
27502ffc8bcaSDan McDonald 
27512ffc8bcaSDan McDonald /*
27522ffc8bcaSDan McDonald  * complete_cmd_in_sync_mode -	Completes an internal command
27532ffc8bcaSDan McDonald  * @instance:			Adapter soft state
27542ffc8bcaSDan McDonald  * @cmd:			Command to be completed
27552ffc8bcaSDan McDonald  *
27562ffc8bcaSDan McDonald  * The issue_cmd_in_sync_mode() function waits for a command to complete
27572ffc8bcaSDan McDonald  * after it issues a command. This function wakes up that waiting routine by
27582ffc8bcaSDan McDonald  * calling wake_up() on the wait queue.
27592ffc8bcaSDan McDonald  */
27602ffc8bcaSDan McDonald void
tbolt_complete_cmd_in_sync_mode(struct mrsas_instance * instance,struct mrsas_cmd * cmd)27612ffc8bcaSDan McDonald tbolt_complete_cmd_in_sync_mode(struct mrsas_instance *instance,
27622ffc8bcaSDan McDonald     struct mrsas_cmd *cmd)
27632ffc8bcaSDan McDonald {
27642ffc8bcaSDan McDonald 
27652ffc8bcaSDan McDonald 	cmd->cmd_status = ddi_get8(cmd->frame_dma_obj.acc_handle,
27662ffc8bcaSDan McDonald 	    &cmd->frame->io.cmd_status);
27672ffc8bcaSDan McDonald 
27682ffc8bcaSDan McDonald 	cmd->sync_cmd = MRSAS_FALSE;
27692ffc8bcaSDan McDonald 
27702ffc8bcaSDan McDonald 	mutex_enter(&instance->int_cmd_mtx);
27712ffc8bcaSDan McDonald 	if (cmd->cmd_status == ENODATA) {
27722ffc8bcaSDan McDonald 		cmd->cmd_status = 0;
27732ffc8bcaSDan McDonald 	}
27742ffc8bcaSDan McDonald 	cv_broadcast(&instance->int_cmd_cv);
27752ffc8bcaSDan McDonald 	mutex_exit(&instance->int_cmd_mtx);
27762ffc8bcaSDan McDonald 
27772ffc8bcaSDan McDonald }
27782ffc8bcaSDan McDonald 
27792ffc8bcaSDan McDonald /*
27802ffc8bcaSDan McDonald  * mrsas_tbolt_get_ld_map_info -	Returns	 ld_map structure
27812ffc8bcaSDan McDonald  * instance:				Adapter soft state
27822ffc8bcaSDan McDonald  *
27832ffc8bcaSDan McDonald  * Issues an internal command (DCMD) to get the FW's controller PD
27842ffc8bcaSDan McDonald  * list structure.  This information is mainly used to find out SYSTEM
27852ffc8bcaSDan McDonald  * supported by the FW.
27862ffc8bcaSDan McDonald  */
27872ffc8bcaSDan McDonald int
mrsas_tbolt_get_ld_map_info(struct mrsas_instance * instance)27882ffc8bcaSDan McDonald mrsas_tbolt_get_ld_map_info(struct mrsas_instance *instance)
27892ffc8bcaSDan McDonald {
27902ffc8bcaSDan McDonald 	int ret = 0;
27912ffc8bcaSDan McDonald 	struct mrsas_cmd	*cmd = NULL;
27922ffc8bcaSDan McDonald 	struct mrsas_dcmd_frame	*dcmd;
27932ffc8bcaSDan McDonald 	MR_FW_RAID_MAP_ALL *ci;
27942ffc8bcaSDan McDonald 	uint32_t ci_h = 0;
27952ffc8bcaSDan McDonald 	U32 size_map_info;
27962ffc8bcaSDan McDonald 
27972ffc8bcaSDan McDonald 	cmd = get_raid_msg_pkt(instance);
27982ffc8bcaSDan McDonald 
27992ffc8bcaSDan McDonald 	if (cmd == NULL) {
2800ff38cf9dSAndy Fiddaman 		dev_err(instance->dip, CE_WARN,
28012ffc8bcaSDan McDonald 		    "Failed to get a cmd from free-pool in get_ld_map_info()");
28022ffc8bcaSDan McDonald 		return (DDI_FAILURE);
28032ffc8bcaSDan McDonald 	}
28042ffc8bcaSDan McDonald 
28052ffc8bcaSDan McDonald 	dcmd = &cmd->frame->dcmd;
28062ffc8bcaSDan McDonald 
28072ffc8bcaSDan McDonald 	size_map_info =	sizeof (MR_FW_RAID_MAP) +
28082ffc8bcaSDan McDonald 	    (sizeof (MR_LD_SPAN_MAP) *
28092ffc8bcaSDan McDonald 	    (MAX_LOGICAL_DRIVES - 1));
28102ffc8bcaSDan McDonald 
28112ffc8bcaSDan McDonald 	con_log(CL_ANN, (CE_NOTE,
28122ffc8bcaSDan McDonald 	    "size_map_info : 0x%x", size_map_info));
28132ffc8bcaSDan McDonald 
2814e65bc174SAndy Fiddaman 	ci = instance->ld_map[instance->map_id & 1];
2815e65bc174SAndy Fiddaman 	ci_h = instance->ld_map_phy[instance->map_id & 1];
28162ffc8bcaSDan McDonald 
28172ffc8bcaSDan McDonald 	if (!ci) {
2818ff38cf9dSAndy Fiddaman 		dev_err(instance->dip, CE_WARN,
2819ff38cf9dSAndy Fiddaman 		    "Failed to alloc mem for ld_map_info");
28202ffc8bcaSDan McDonald 		return_raid_msg_pkt(instance, cmd);
28212ffc8bcaSDan McDonald 		return (-1);
28222ffc8bcaSDan McDonald 	}
28232ffc8bcaSDan McDonald 
28242ffc8bcaSDan McDonald 	bzero(ci, sizeof (*ci));
28252ffc8bcaSDan McDonald 	bzero(dcmd->mbox.b, DCMD_MBOX_SZ);
28262ffc8bcaSDan McDonald 
28272ffc8bcaSDan McDonald 	dcmd->cmd = MFI_CMD_OP_DCMD;
28282ffc8bcaSDan McDonald 	dcmd->cmd_status = 0xFF;
28292ffc8bcaSDan McDonald 	dcmd->sge_count = 1;
28302ffc8bcaSDan McDonald 	dcmd->flags = MFI_FRAME_DIR_READ;
28312ffc8bcaSDan McDonald 	dcmd->timeout = 0;
28322ffc8bcaSDan McDonald 	dcmd->pad_0 = 0;
28332ffc8bcaSDan McDonald 	dcmd->data_xfer_len = size_map_info;
28342ffc8bcaSDan McDonald 	dcmd->opcode = MR_DCMD_LD_MAP_GET_INFO;
28352ffc8bcaSDan McDonald 	dcmd->sgl.sge32[0].phys_addr = ci_h;
28362ffc8bcaSDan McDonald 	dcmd->sgl.sge32[0].length = size_map_info;
28372ffc8bcaSDan McDonald 
28382ffc8bcaSDan McDonald 
28392ffc8bcaSDan McDonald 	mr_sas_tbolt_build_mfi_cmd(instance, cmd);
28402ffc8bcaSDan McDonald 
28412ffc8bcaSDan McDonald 	if (!instance->func_ptr->issue_cmd_in_poll_mode(instance, cmd)) {
28422ffc8bcaSDan McDonald 		ret = 0;
28432ffc8bcaSDan McDonald 		con_log(CL_ANN1, (CE_NOTE, "Get LD Map Info success"));
28442ffc8bcaSDan McDonald 	} else {
2845ff38cf9dSAndy Fiddaman 		dev_err(instance->dip, CE_WARN, "Get LD Map Info failed");
28462ffc8bcaSDan McDonald 		ret = -1;
28472ffc8bcaSDan McDonald 	}
28482ffc8bcaSDan McDonald 
28492ffc8bcaSDan McDonald 	return_raid_msg_pkt(instance, cmd);
28502ffc8bcaSDan McDonald 
28512ffc8bcaSDan McDonald 	return (ret);
28522ffc8bcaSDan McDonald }
28532ffc8bcaSDan McDonald 
28542ffc8bcaSDan McDonald void
mrsas_dump_reply_desc(struct mrsas_instance * instance)28552ffc8bcaSDan McDonald mrsas_dump_reply_desc(struct mrsas_instance *instance)
28562ffc8bcaSDan McDonald {
28572ffc8bcaSDan McDonald 	uint32_t i;
28582ffc8bcaSDan McDonald 	MPI2_REPLY_DESCRIPTORS_UNION *reply_desc;
28592ffc8bcaSDan McDonald 	union desc_value d_val;
28602ffc8bcaSDan McDonald 
28612ffc8bcaSDan McDonald 	reply_desc = instance->reply_frame_pool;
28622ffc8bcaSDan McDonald 
28632ffc8bcaSDan McDonald 	for (i = 0; i < instance->reply_q_depth; i++, reply_desc++) {
28642ffc8bcaSDan McDonald 		d_val.word = reply_desc->Words;
28652ffc8bcaSDan McDonald 		con_log(CL_DLEVEL3, (CE_NOTE,
28662ffc8bcaSDan McDonald 		    "i=%d, %x:%x",
28672ffc8bcaSDan McDonald 		    i, d_val.u1.high, d_val.u1.low));
28682ffc8bcaSDan McDonald 	}
28692ffc8bcaSDan McDonald }
28702ffc8bcaSDan McDonald 
28712ffc8bcaSDan McDonald /*
28722ffc8bcaSDan McDonald  * mrsas_tbolt_command_create -	Create command for fast path.
28732ffc8bcaSDan McDonald  * @io_info:	MegaRAID IO request packet pointer.
28742ffc8bcaSDan McDonald  * @ref_tag:	Reference tag for RD/WRPROTECT
28752ffc8bcaSDan McDonald  *
28762ffc8bcaSDan McDonald  * Create the command for fast path.
28772ffc8bcaSDan McDonald  */
28782ffc8bcaSDan McDonald void
mrsas_tbolt_prepare_cdb(struct mrsas_instance * instance,U8 cdb[],struct IO_REQUEST_INFO * io_info,Mpi2RaidSCSIIORequest_t * scsi_io_request,U32 ref_tag)28792ffc8bcaSDan McDonald mrsas_tbolt_prepare_cdb(struct mrsas_instance *instance, U8 cdb[],
28802ffc8bcaSDan McDonald     struct IO_REQUEST_INFO *io_info, Mpi2RaidSCSIIORequest_t *scsi_io_request,
28812ffc8bcaSDan McDonald     U32 ref_tag)
28822ffc8bcaSDan McDonald {
28832ffc8bcaSDan McDonald 	uint16_t		EEDPFlags;
28842ffc8bcaSDan McDonald 	uint32_t		Control;
28852ffc8bcaSDan McDonald 	ddi_acc_handle_t acc_handle =
28862ffc8bcaSDan McDonald 	    instance->mpi2_frame_pool_dma_obj.acc_handle;
28872ffc8bcaSDan McDonald 
28882ffc8bcaSDan McDonald 	/* Prepare 32-byte CDB if DIF is supported on this device */
28892ffc8bcaSDan McDonald 	con_log(CL_ANN, (CE_NOTE, "Prepare DIF CDB"));
28902ffc8bcaSDan McDonald 
28912ffc8bcaSDan McDonald 	bzero(cdb, 32);
28922ffc8bcaSDan McDonald 
28932ffc8bcaSDan McDonald 	cdb[0] =  MRSAS_SCSI_VARIABLE_LENGTH_CMD;
28942ffc8bcaSDan McDonald 
28952ffc8bcaSDan McDonald 
28962ffc8bcaSDan McDonald 	cdb[7] =  MRSAS_SCSI_ADDL_CDB_LEN;
28972ffc8bcaSDan McDonald 
28982ffc8bcaSDan McDonald 	if (io_info->isRead)
28992ffc8bcaSDan McDonald 		cdb[9] = MRSAS_SCSI_SERVICE_ACTION_READ32;
29002ffc8bcaSDan McDonald 	else
29012ffc8bcaSDan McDonald 		cdb[9] = MRSAS_SCSI_SERVICE_ACTION_WRITE32;
29022ffc8bcaSDan McDonald 
29032ffc8bcaSDan McDonald 	/* Verify within linux driver, set to MEGASAS_RD_WR_PROTECT_CHECK_ALL */
29042ffc8bcaSDan McDonald 	cdb[10] = MRSAS_RD_WR_PROTECT;
29052ffc8bcaSDan McDonald 
29062ffc8bcaSDan McDonald 	/* LOGICAL BLOCK ADDRESS */
29072ffc8bcaSDan McDonald 	cdb[12] = (U8)(((io_info->pdBlock) >> 56) & 0xff);
29082ffc8bcaSDan McDonald 	cdb[13] = (U8)(((io_info->pdBlock) >> 48) & 0xff);
29092ffc8bcaSDan McDonald 	cdb[14] = (U8)(((io_info->pdBlock) >> 40) & 0xff);
29102ffc8bcaSDan McDonald 	cdb[15] = (U8)(((io_info->pdBlock) >> 32) & 0xff);
29112ffc8bcaSDan McDonald 	cdb[16] = (U8)(((io_info->pdBlock) >> 24) & 0xff);
29122ffc8bcaSDan McDonald 	cdb[17] = (U8)(((io_info->pdBlock) >> 16) & 0xff);
29132ffc8bcaSDan McDonald 	cdb[18] = (U8)(((io_info->pdBlock) >> 8) & 0xff);
29142ffc8bcaSDan McDonald 	cdb[19] = (U8)((io_info->pdBlock) & 0xff);
29152ffc8bcaSDan McDonald 
29162ffc8bcaSDan McDonald 	/* Logical block reference tag */
29172ffc8bcaSDan McDonald 	ddi_put32(acc_handle, &scsi_io_request->CDB.EEDP32.PrimaryReferenceTag,
29182ffc8bcaSDan McDonald 	    BE_32(ref_tag));
29192ffc8bcaSDan McDonald 
29202ffc8bcaSDan McDonald 	ddi_put16(acc_handle,
29212ffc8bcaSDan McDonald 	    &scsi_io_request->CDB.EEDP32.PrimaryApplicationTagMask, 0xffff);
29222ffc8bcaSDan McDonald 
29232ffc8bcaSDan McDonald 	ddi_put32(acc_handle, &scsi_io_request->DataLength,
29242ffc8bcaSDan McDonald 	    ((io_info->numBlocks)*512));
29252ffc8bcaSDan McDonald 	/* Specify 32-byte cdb */
29262ffc8bcaSDan McDonald 	ddi_put16(acc_handle, &scsi_io_request->IoFlags, 32);
29272ffc8bcaSDan McDonald 
29282ffc8bcaSDan McDonald 	/* Transfer length */
29292ffc8bcaSDan McDonald 	cdb[28] = (U8)(((io_info->numBlocks) >> 24) & 0xff);
29302ffc8bcaSDan McDonald 	cdb[29] = (U8)(((io_info->numBlocks) >> 16) & 0xff);
29312ffc8bcaSDan McDonald 	cdb[30] = (U8)(((io_info->numBlocks) >> 8) & 0xff);
29322ffc8bcaSDan McDonald 	cdb[31] = (U8)((io_info->numBlocks) & 0xff);
29332ffc8bcaSDan McDonald 
29342ffc8bcaSDan McDonald 	/* set SCSI IO EEDPFlags */
29352ffc8bcaSDan McDonald 	EEDPFlags = ddi_get16(acc_handle, &scsi_io_request->EEDPFlags);
29362ffc8bcaSDan McDonald 	Control = ddi_get32(acc_handle, &scsi_io_request->Control);
29372ffc8bcaSDan McDonald 
29382ffc8bcaSDan McDonald 	/* set SCSI IO EEDPFlags bits */
29392ffc8bcaSDan McDonald 	if (io_info->isRead) {
29402ffc8bcaSDan McDonald 		/*
29412ffc8bcaSDan McDonald 		 * For READ commands, the EEDPFlags shall be set to specify to
29422ffc8bcaSDan McDonald 		 * Increment the Primary Reference Tag, to Check the Reference
29432ffc8bcaSDan McDonald 		 * Tag, and to Check and Remove the Protection Information
29442ffc8bcaSDan McDonald 		 * fields.
29452ffc8bcaSDan McDonald 		 */
29462ffc8bcaSDan McDonald 		EEDPFlags = MPI2_SCSIIO_EEDPFLAGS_INC_PRI_REFTAG	|
29472ffc8bcaSDan McDonald 		    MPI2_SCSIIO_EEDPFLAGS_CHECK_REFTAG	|
29482ffc8bcaSDan McDonald 		    MPI2_SCSIIO_EEDPFLAGS_CHECK_REMOVE_OP	|
29492ffc8bcaSDan McDonald 		    MPI2_SCSIIO_EEDPFLAGS_CHECK_APPTAG	|
29502ffc8bcaSDan McDonald 		    MPI2_SCSIIO_EEDPFLAGS_CHECK_GUARD;
29512ffc8bcaSDan McDonald 	} else {
29522ffc8bcaSDan McDonald 		/*
29532ffc8bcaSDan McDonald 		 * For WRITE commands, the EEDPFlags shall be set to specify to
29542ffc8bcaSDan McDonald 		 * Increment the Primary Reference Tag, and to Insert
29552ffc8bcaSDan McDonald 		 * Protection Information fields.
29562ffc8bcaSDan McDonald 		 */
29572ffc8bcaSDan McDonald 		EEDPFlags = MPI2_SCSIIO_EEDPFLAGS_INC_PRI_REFTAG	|
29582ffc8bcaSDan McDonald 		    MPI2_SCSIIO_EEDPFLAGS_INSERT_OP;
29592ffc8bcaSDan McDonald 	}
29602ffc8bcaSDan McDonald 	Control |= (0x4 << 26);
29612ffc8bcaSDan McDonald 
29622ffc8bcaSDan McDonald 	ddi_put16(acc_handle, &scsi_io_request->EEDPFlags, EEDPFlags);
29632ffc8bcaSDan McDonald 	ddi_put32(acc_handle, &scsi_io_request->Control, Control);
29642ffc8bcaSDan McDonald 	ddi_put32(acc_handle,
29652ffc8bcaSDan McDonald 	    &scsi_io_request->EEDPBlockSize, MRSAS_EEDPBLOCKSIZE);
29662ffc8bcaSDan McDonald }
29672ffc8bcaSDan McDonald 
29682ffc8bcaSDan McDonald 
29692ffc8bcaSDan McDonald /*
29702ffc8bcaSDan McDonald  * mrsas_tbolt_set_pd_lba -	Sets PD LBA
29712ffc8bcaSDan McDonald  * @cdb:		CDB
29723344ffb7SToomas Soome  * @cdb_size:		CDB size
29733344ffb7SToomas Soome  * @cdb_len_ptr:	cdb length
29742ffc8bcaSDan McDonald  * @start_blk:		Start block of IO
29753344ffb7SToomas Soome  * @num_blocks:		Number of blocks
29762ffc8bcaSDan McDonald  *
29772ffc8bcaSDan McDonald  * Used to set the PD LBA in CDB for FP IOs
29782ffc8bcaSDan McDonald  */
29792ffc8bcaSDan McDonald static void
mrsas_tbolt_set_pd_lba(U8 * cdb,size_t cdb_size,uint8_t * cdb_len_ptr,U64 start_blk,U32 num_blocks)29803344ffb7SToomas Soome mrsas_tbolt_set_pd_lba(U8 *cdb, size_t cdb_size, uint8_t *cdb_len_ptr,
29813344ffb7SToomas Soome     U64 start_blk, U32 num_blocks)
29822ffc8bcaSDan McDonald {
29832ffc8bcaSDan McDonald 	U8 cdb_len = *cdb_len_ptr;
29842ffc8bcaSDan McDonald 	U8 flagvals = 0, opcode = 0, groupnum = 0, control = 0;
29852ffc8bcaSDan McDonald 
29862ffc8bcaSDan McDonald 	/* Some drives don't support 16/12 byte CDB's, convert to 10 */
29872ffc8bcaSDan McDonald 	if (((cdb_len == 12) || (cdb_len == 16)) &&
29882ffc8bcaSDan McDonald 	    (start_blk <= 0xffffffff)) {
29892ffc8bcaSDan McDonald 		if (cdb_len == 16) {
29902ffc8bcaSDan McDonald 			con_log(CL_ANN,
29912ffc8bcaSDan McDonald 			    (CE_NOTE, "Converting READ/WRITE(16) to READ10"));
29922ffc8bcaSDan McDonald 			opcode = cdb[0] == READ_16 ? READ_10 : WRITE_10;
29932ffc8bcaSDan McDonald 			flagvals = cdb[1];
29942ffc8bcaSDan McDonald 			groupnum = cdb[14];
29952ffc8bcaSDan McDonald 			control = cdb[15];
29962ffc8bcaSDan McDonald 		} else {
29972ffc8bcaSDan McDonald 			con_log(CL_ANN,
29982ffc8bcaSDan McDonald 			    (CE_NOTE, "Converting READ/WRITE(12) to READ10"));
29992ffc8bcaSDan McDonald 			opcode = cdb[0] == READ_12 ? READ_10 : WRITE_10;
30002ffc8bcaSDan McDonald 			flagvals = cdb[1];
30012ffc8bcaSDan McDonald 			groupnum = cdb[10];
30022ffc8bcaSDan McDonald 			control = cdb[11];
30032ffc8bcaSDan McDonald 		}
30042ffc8bcaSDan McDonald 
30053344ffb7SToomas Soome 		bzero(cdb, cdb_size);
30062ffc8bcaSDan McDonald 
30072ffc8bcaSDan McDonald 		cdb[0] = opcode;
30082ffc8bcaSDan McDonald 		cdb[1] = flagvals;
30092ffc8bcaSDan McDonald 		cdb[6] = groupnum;
30102ffc8bcaSDan McDonald 		cdb[9] = control;
30112ffc8bcaSDan McDonald 		/* Set transfer length */
30122ffc8bcaSDan McDonald 		cdb[8] = (U8)(num_blocks & 0xff);
30132ffc8bcaSDan McDonald 		cdb[7] = (U8)((num_blocks >> 8) & 0xff);
30142ffc8bcaSDan McDonald 		cdb_len = 10;
30152ffc8bcaSDan McDonald 	} else if ((cdb_len < 16) && (start_blk > 0xffffffff)) {
30162ffc8bcaSDan McDonald 		/* Convert to 16 byte CDB for large LBA's */
30172ffc8bcaSDan McDonald 		con_log(CL_ANN,
30182ffc8bcaSDan McDonald 		    (CE_NOTE, "Converting 6/10/12 CDB to 16 byte CDB"));
30192ffc8bcaSDan McDonald 		switch (cdb_len) {
30202ffc8bcaSDan McDonald 		case 6:
30212ffc8bcaSDan McDonald 			opcode = cdb[0] == READ_6 ? READ_16 : WRITE_16;
30222ffc8bcaSDan McDonald 			control = cdb[5];
30232ffc8bcaSDan McDonald 			break;
30242ffc8bcaSDan McDonald 		case 10:
30252ffc8bcaSDan McDonald 			opcode = cdb[0] == READ_10 ? READ_16 : WRITE_16;
30262ffc8bcaSDan McDonald 			flagvals = cdb[1];
30272ffc8bcaSDan McDonald 			groupnum = cdb[6];
30282ffc8bcaSDan McDonald 			control = cdb[9];
30292ffc8bcaSDan McDonald 			break;
30302ffc8bcaSDan McDonald 		case 12:
30312ffc8bcaSDan McDonald 			opcode = cdb[0] == READ_12 ? READ_16 : WRITE_16;
30322ffc8bcaSDan McDonald 			flagvals = cdb[1];
30332ffc8bcaSDan McDonald 			groupnum = cdb[10];
30342ffc8bcaSDan McDonald 			control = cdb[11];
30352ffc8bcaSDan McDonald 			break;
30362ffc8bcaSDan McDonald 		}
30372ffc8bcaSDan McDonald 
30383344ffb7SToomas Soome 		bzero(cdb, cdb_size);
30392ffc8bcaSDan McDonald 
30402ffc8bcaSDan McDonald 		cdb[0] = opcode;
30412ffc8bcaSDan McDonald 		cdb[1] = flagvals;
30422ffc8bcaSDan McDonald 		cdb[14] = groupnum;
30432ffc8bcaSDan McDonald 		cdb[15] = control;
30442ffc8bcaSDan McDonald 
30452ffc8bcaSDan McDonald 		/* Transfer length */
30462ffc8bcaSDan McDonald 		cdb[13] = (U8)(num_blocks & 0xff);
30472ffc8bcaSDan McDonald 		cdb[12] = (U8)((num_blocks >> 8) & 0xff);
30482ffc8bcaSDan McDonald 		cdb[11] = (U8)((num_blocks >> 16) & 0xff);
30492ffc8bcaSDan McDonald 		cdb[10] = (U8)((num_blocks >> 24) & 0xff);
30502ffc8bcaSDan McDonald 
30512ffc8bcaSDan McDonald 		/* Specify 16-byte cdb */
30522ffc8bcaSDan McDonald 		cdb_len = 16;
30532ffc8bcaSDan McDonald 	} else if ((cdb_len == 6) && (start_blk > 0x1fffff)) {
30542ffc8bcaSDan McDonald 		/* convert to 10 byte CDB */
30552ffc8bcaSDan McDonald 		opcode = cdb[0] == READ_6 ? READ_10 : WRITE_10;
30562ffc8bcaSDan McDonald 		control = cdb[5];
30572ffc8bcaSDan McDonald 
30583344ffb7SToomas Soome 		bzero(cdb, cdb_size);
30592ffc8bcaSDan McDonald 		cdb[0] = opcode;
30602ffc8bcaSDan McDonald 		cdb[9] = control;
30612ffc8bcaSDan McDonald 
30622ffc8bcaSDan McDonald 		/* Set transfer length */
30632ffc8bcaSDan McDonald 		cdb[8] = (U8)(num_blocks & 0xff);
30642ffc8bcaSDan McDonald 		cdb[7] = (U8)((num_blocks >> 8) & 0xff);
30652ffc8bcaSDan McDonald 
30662ffc8bcaSDan McDonald 		/* Specify 10-byte cdb */
30672ffc8bcaSDan McDonald 		cdb_len = 10;
30682ffc8bcaSDan McDonald 	}
30692ffc8bcaSDan McDonald 
30702ffc8bcaSDan McDonald 
30712ffc8bcaSDan McDonald 	/* Fall through Normal case, just load LBA here */
30722ffc8bcaSDan McDonald 	switch (cdb_len) {
30732ffc8bcaSDan McDonald 	case 6:
30742ffc8bcaSDan McDonald 	{
30752ffc8bcaSDan McDonald 		U8 val = cdb[1] & 0xE0;
30762ffc8bcaSDan McDonald 		cdb[3] = (U8)(start_blk & 0xff);
30772ffc8bcaSDan McDonald 		cdb[2] = (U8)((start_blk >> 8) & 0xff);
30782ffc8bcaSDan McDonald 		cdb[1] = val | ((U8)(start_blk >> 16) & 0x1f);
30792ffc8bcaSDan McDonald 		break;
30802ffc8bcaSDan McDonald 	}
30812ffc8bcaSDan McDonald 	case 10:
30822ffc8bcaSDan McDonald 		cdb[5] = (U8)(start_blk & 0xff);
30832ffc8bcaSDan McDonald 		cdb[4] = (U8)((start_blk >> 8) & 0xff);
30842ffc8bcaSDan McDonald 		cdb[3] = (U8)((start_blk >> 16) & 0xff);
30852ffc8bcaSDan McDonald 		cdb[2] = (U8)((start_blk >> 24) & 0xff);
30862ffc8bcaSDan McDonald 		break;
30872ffc8bcaSDan McDonald 	case 12:
30882ffc8bcaSDan McDonald 		cdb[5]	  = (U8)(start_blk & 0xff);
30892ffc8bcaSDan McDonald 		cdb[4]	  = (U8)((start_blk >> 8) & 0xff);
30902ffc8bcaSDan McDonald 		cdb[3]	  = (U8)((start_blk >> 16) & 0xff);
30912ffc8bcaSDan McDonald 		cdb[2]	  = (U8)((start_blk >> 24) & 0xff);
30922ffc8bcaSDan McDonald 		break;
30932ffc8bcaSDan McDonald 
30942ffc8bcaSDan McDonald 	case 16:
30952ffc8bcaSDan McDonald 		cdb[9]	= (U8)(start_blk & 0xff);
30962ffc8bcaSDan McDonald 		cdb[8]	= (U8)((start_blk >> 8) & 0xff);
30972ffc8bcaSDan McDonald 		cdb[7]	= (U8)((start_blk >> 16) & 0xff);
30982ffc8bcaSDan McDonald 		cdb[6]	= (U8)((start_blk >> 24) & 0xff);
30992ffc8bcaSDan McDonald 		cdb[5]	= (U8)((start_blk >> 32) & 0xff);
31002ffc8bcaSDan McDonald 		cdb[4]	= (U8)((start_blk >> 40) & 0xff);
31012ffc8bcaSDan McDonald 		cdb[3]	= (U8)((start_blk >> 48) & 0xff);
31022ffc8bcaSDan McDonald 		cdb[2]	= (U8)((start_blk >> 56) & 0xff);
31032ffc8bcaSDan McDonald 		break;
31042ffc8bcaSDan McDonald 	}
31052ffc8bcaSDan McDonald 
31062ffc8bcaSDan McDonald 	*cdb_len_ptr = cdb_len;
31072ffc8bcaSDan McDonald }
31082ffc8bcaSDan McDonald 
31092ffc8bcaSDan McDonald 
31102ffc8bcaSDan McDonald static int
mrsas_tbolt_check_map_info(struct mrsas_instance * instance)31112ffc8bcaSDan McDonald mrsas_tbolt_check_map_info(struct mrsas_instance *instance)
31122ffc8bcaSDan McDonald {
31132ffc8bcaSDan McDonald 	MR_FW_RAID_MAP_ALL *ld_map;
31142ffc8bcaSDan McDonald 
31152ffc8bcaSDan McDonald 	if (!mrsas_tbolt_get_ld_map_info(instance)) {
31162ffc8bcaSDan McDonald 
3117e65bc174SAndy Fiddaman 		ld_map = instance->ld_map[instance->map_id & 1];
31182ffc8bcaSDan McDonald 
31192ffc8bcaSDan McDonald 		con_log(CL_ANN1, (CE_NOTE, "ldCount=%d, map size=%d",
31202ffc8bcaSDan McDonald 		    ld_map->raidMap.ldCount, ld_map->raidMap.totalSize));
31212ffc8bcaSDan McDonald 
3122e65bc174SAndy Fiddaman 		if (MR_ValidateMapInfo(
3123e65bc174SAndy Fiddaman 		    instance->ld_map[instance->map_id & 1],
3124e65bc174SAndy Fiddaman 		    instance->load_balance_info)) {
31252ffc8bcaSDan McDonald 			con_log(CL_ANN,
31262ffc8bcaSDan McDonald 			    (CE_CONT, "MR_ValidateMapInfo success"));
31272ffc8bcaSDan McDonald 
31282ffc8bcaSDan McDonald 			instance->fast_path_io = 1;
31292ffc8bcaSDan McDonald 			con_log(CL_ANN,
31302ffc8bcaSDan McDonald 			    (CE_NOTE, "instance->fast_path_io %d",
31312ffc8bcaSDan McDonald 			    instance->fast_path_io));
31322ffc8bcaSDan McDonald 
31332ffc8bcaSDan McDonald 			return (DDI_SUCCESS);
31342ffc8bcaSDan McDonald 		}
31352ffc8bcaSDan McDonald 
31362ffc8bcaSDan McDonald 	}
31372ffc8bcaSDan McDonald 
31382ffc8bcaSDan McDonald 	instance->fast_path_io = 0;
3139ff38cf9dSAndy Fiddaman 	dev_err(instance->dip, CE_WARN, "MR_ValidateMapInfo failed");
31402ffc8bcaSDan McDonald 	con_log(CL_ANN, (CE_NOTE,
31412ffc8bcaSDan McDonald 	    "instance->fast_path_io %d", instance->fast_path_io));
31422ffc8bcaSDan McDonald 
31432ffc8bcaSDan McDonald 	return (DDI_FAILURE);
31442ffc8bcaSDan McDonald }
31452ffc8bcaSDan McDonald 
31462ffc8bcaSDan McDonald /*
31472ffc8bcaSDan McDonald  * Marks HBA as bad. This will be called either when an
31482ffc8bcaSDan McDonald  * IO packet times out even after 3 FW resets
31492ffc8bcaSDan McDonald  * or FW is found to be fault even after 3 continuous resets.
31502ffc8bcaSDan McDonald  */
31512ffc8bcaSDan McDonald 
31522ffc8bcaSDan McDonald void
mrsas_tbolt_kill_adapter(struct mrsas_instance * instance)31532ffc8bcaSDan McDonald mrsas_tbolt_kill_adapter(struct mrsas_instance *instance)
31542ffc8bcaSDan McDonald {
3155ff38cf9dSAndy Fiddaman 	dev_err(instance->dip, CE_NOTE, "TBOLT Kill adapter called");
31562ffc8bcaSDan McDonald 
31572ffc8bcaSDan McDonald 	if (instance->deadadapter == 1)
31582ffc8bcaSDan McDonald 		return;
31592ffc8bcaSDan McDonald 
31602ffc8bcaSDan McDonald 	con_log(CL_ANN1, (CE_NOTE, "tbolt_kill_adapter: "
31612ffc8bcaSDan McDonald 	    "Writing to doorbell with MFI_STOP_ADP "));
31622ffc8bcaSDan McDonald 	mutex_enter(&instance->ocr_flags_mtx);
31632ffc8bcaSDan McDonald 	instance->deadadapter = 1;
31642ffc8bcaSDan McDonald 	mutex_exit(&instance->ocr_flags_mtx);
31652ffc8bcaSDan McDonald 	instance->func_ptr->disable_intr(instance);
31662ffc8bcaSDan McDonald 	WR_RESERVED0_REGISTER(MFI_STOP_ADP, instance);
31672ffc8bcaSDan McDonald 	/* Flush */
31682ffc8bcaSDan McDonald 	(void) RD_RESERVED0_REGISTER(instance);
31692ffc8bcaSDan McDonald 
31702ffc8bcaSDan McDonald 	(void) mrsas_print_pending_cmds(instance);
31712ffc8bcaSDan McDonald 	(void) mrsas_complete_pending_cmds(instance);
31722ffc8bcaSDan McDonald }
31732ffc8bcaSDan McDonald 
31742ffc8bcaSDan McDonald void
mrsas_reset_reply_desc(struct mrsas_instance * instance)31752ffc8bcaSDan McDonald mrsas_reset_reply_desc(struct mrsas_instance *instance)
31762ffc8bcaSDan McDonald {
31772ffc8bcaSDan McDonald 	int i;
31782ffc8bcaSDan McDonald 	MPI2_REPLY_DESCRIPTORS_UNION *reply_desc;
31792ffc8bcaSDan McDonald 	instance->reply_read_index = 0;
31802ffc8bcaSDan McDonald 
31812ffc8bcaSDan McDonald 	/* initializing reply address to 0xFFFFFFFF */
31822ffc8bcaSDan McDonald 	reply_desc = instance->reply_frame_pool;
31832ffc8bcaSDan McDonald 
31842ffc8bcaSDan McDonald 	for (i = 0; i < instance->reply_q_depth; i++) {
31852ffc8bcaSDan McDonald 		reply_desc->Words = (uint64_t)~0;
31862ffc8bcaSDan McDonald 		reply_desc++;
31872ffc8bcaSDan McDonald 	}
31882ffc8bcaSDan McDonald }
31892ffc8bcaSDan McDonald 
31902ffc8bcaSDan McDonald int
mrsas_tbolt_reset_ppc(struct mrsas_instance * instance)31912ffc8bcaSDan McDonald mrsas_tbolt_reset_ppc(struct mrsas_instance *instance)
31922ffc8bcaSDan McDonald {
31932ffc8bcaSDan McDonald 	uint32_t status = 0x00;
31942ffc8bcaSDan McDonald 	uint32_t retry = 0;
31952ffc8bcaSDan McDonald 	uint32_t cur_abs_reg_val;
31962ffc8bcaSDan McDonald 	uint32_t fw_state;
31972ffc8bcaSDan McDonald 	uint32_t abs_state;
31982ffc8bcaSDan McDonald 	uint32_t i;
31992ffc8bcaSDan McDonald 
32002ffc8bcaSDan McDonald 	if (instance->deadadapter == 1) {
3201ff38cf9dSAndy Fiddaman 		dev_err(instance->dip, CE_WARN, "mrsas_tbolt_reset_ppc: "
32022ffc8bcaSDan McDonald 		    "no more resets as HBA has been marked dead");
32032ffc8bcaSDan McDonald 		return (DDI_FAILURE);
32042ffc8bcaSDan McDonald 	}
32052ffc8bcaSDan McDonald 
32062ffc8bcaSDan McDonald 	mutex_enter(&instance->ocr_flags_mtx);
32072ffc8bcaSDan McDonald 	instance->adapterresetinprogress = 1;
32082ffc8bcaSDan McDonald 	mutex_exit(&instance->ocr_flags_mtx);
32092ffc8bcaSDan McDonald 
32102ffc8bcaSDan McDonald 	instance->func_ptr->disable_intr(instance);
32112ffc8bcaSDan McDonald 
32122ffc8bcaSDan McDonald 	/* Add delay in order to complete the ioctl & io cmds in-flight */
3213eef6dbdfSAndy Fiddaman 	for (i = 0; i < 3000; i++)
32142ffc8bcaSDan McDonald 		drv_usecwait(MILLISEC); /* wait for 1000 usecs */
32152ffc8bcaSDan McDonald 
32162ffc8bcaSDan McDonald 	instance->reply_read_index = 0;
32172ffc8bcaSDan McDonald 
32182ffc8bcaSDan McDonald retry_reset:
3219eef6dbdfSAndy Fiddaman 	con_log(CL_ANN, (CE_NOTE, "mrsas_tbolt_reset_ppc: Resetting TBOLT"));
32202ffc8bcaSDan McDonald 
3221eef6dbdfSAndy Fiddaman 	/* Flush */
3222eef6dbdfSAndy Fiddaman 	WR_TBOLT_IB_WRITE_SEQ(0x0, instance);
3223eef6dbdfSAndy Fiddaman 	/* Write magic number */
32242ffc8bcaSDan McDonald 	WR_TBOLT_IB_WRITE_SEQ(0xF, instance);
3225eef6dbdfSAndy Fiddaman 	WR_TBOLT_IB_WRITE_SEQ(0x4, instance);
32262ffc8bcaSDan McDonald 	WR_TBOLT_IB_WRITE_SEQ(0xb, instance);
3227eef6dbdfSAndy Fiddaman 	WR_TBOLT_IB_WRITE_SEQ(0x2, instance);
3228eef6dbdfSAndy Fiddaman 	WR_TBOLT_IB_WRITE_SEQ(0x7, instance);
32292ffc8bcaSDan McDonald 	WR_TBOLT_IB_WRITE_SEQ(0xd, instance);
3230eef6dbdfSAndy Fiddaman 
32312ffc8bcaSDan McDonald 	con_log(CL_ANN1, (CE_NOTE,
32322ffc8bcaSDan McDonald 	    "mrsas_tbolt_reset_ppc: magic number written "
32332ffc8bcaSDan McDonald 	    "to write sequence register"));
32342ffc8bcaSDan McDonald 
3235eef6dbdfSAndy Fiddaman 	/* Wait for the diag write enable (DRWE) bit to be set */
3236eef6dbdfSAndy Fiddaman 	retry = 0;
3237eef6dbdfSAndy Fiddaman 	status = RD_TBOLT_HOST_DIAG(instance);
3238eef6dbdfSAndy Fiddaman 	while (!(status & DIAG_WRITE_ENABLE)) {
32392ffc8bcaSDan McDonald 		delay(100 * drv_usectohz(MILLISEC));
32402ffc8bcaSDan McDonald 		status = RD_TBOLT_HOST_DIAG(instance);
3241eef6dbdfSAndy Fiddaman 		if (retry++ >= 100) {
3242ff38cf9dSAndy Fiddaman 			dev_err(instance->dip, CE_WARN,
3243eef6dbdfSAndy Fiddaman 			    "%s(): timeout waiting for DRWE.", __func__);
32442ffc8bcaSDan McDonald 			return (DDI_FAILURE);
32452ffc8bcaSDan McDonald 		}
32462ffc8bcaSDan McDonald 	}
32472ffc8bcaSDan McDonald 
3248eef6dbdfSAndy Fiddaman 	/* Send reset command */
32492ffc8bcaSDan McDonald 	WR_TBOLT_HOST_DIAG(status | DIAG_TBOLT_RESET_ADAPTER, instance);
32502ffc8bcaSDan McDonald 	delay(100 * drv_usectohz(MILLISEC));
32512ffc8bcaSDan McDonald 
3252eef6dbdfSAndy Fiddaman 	/* Wait for reset bit to clear */
3253eef6dbdfSAndy Fiddaman 	retry = 0;
3254eef6dbdfSAndy Fiddaman 	status = RD_TBOLT_HOST_DIAG(instance);
32552ffc8bcaSDan McDonald 	while ((status & DIAG_TBOLT_RESET_ADAPTER)) {
32562ffc8bcaSDan McDonald 		delay(100 * drv_usectohz(MILLISEC));
3257eef6dbdfSAndy Fiddaman 		status = RD_TBOLT_HOST_DIAG(instance);
32582ffc8bcaSDan McDonald 		if (retry++ == 100) {
32592ffc8bcaSDan McDonald 			/* Dont call kill adapter here */
32602ffc8bcaSDan McDonald 			/* RESET BIT ADAPTER is cleared by firmare */
32612ffc8bcaSDan McDonald 			/* mrsas_tbolt_kill_adapter(instance); */
3262ff38cf9dSAndy Fiddaman 			dev_err(instance->dip, CE_WARN,
3263ff38cf9dSAndy Fiddaman 			    "%s(): RESET FAILED; return failure!!!", __func__);
32642ffc8bcaSDan McDonald 			return (DDI_FAILURE);
32652ffc8bcaSDan McDonald 		}
32662ffc8bcaSDan McDonald 	}
32672ffc8bcaSDan McDonald 
32682ffc8bcaSDan McDonald 	con_log(CL_ANN,
32692ffc8bcaSDan McDonald 	    (CE_NOTE, "mrsas_tbolt_reset_ppc: Adapter reset complete"));
32702ffc8bcaSDan McDonald 
32712ffc8bcaSDan McDonald 	abs_state = instance->func_ptr->read_fw_status_reg(instance);
32722ffc8bcaSDan McDonald 	retry = 0;
32732ffc8bcaSDan McDonald 	while ((abs_state <= MFI_STATE_FW_INIT) && (retry++ < 1000)) {
32742ffc8bcaSDan McDonald 		delay(100 * drv_usectohz(MILLISEC));
32752ffc8bcaSDan McDonald 		abs_state = instance->func_ptr->read_fw_status_reg(instance);
32762ffc8bcaSDan McDonald 	}
32772ffc8bcaSDan McDonald 	if (abs_state <= MFI_STATE_FW_INIT) {
3278ff38cf9dSAndy Fiddaman 		dev_err(instance->dip, CE_WARN,
32792ffc8bcaSDan McDonald 		    "mrsas_tbolt_reset_ppc: firmware state < MFI_STATE_FW_INIT"
32802ffc8bcaSDan McDonald 		    "state = 0x%x, RETRY RESET.", abs_state);
32812ffc8bcaSDan McDonald 		goto retry_reset;
32822ffc8bcaSDan McDonald 	}
32832ffc8bcaSDan McDonald 
32842ffc8bcaSDan McDonald 	/* Mark HBA as bad, if FW is fault after 3 continuous resets */
32852ffc8bcaSDan McDonald 	if (mfi_state_transition_to_ready(instance) ||
3286eef6dbdfSAndy Fiddaman 	    mrsas_debug_tbolt_fw_faults_after_ocr == 1) {
32872ffc8bcaSDan McDonald 		cur_abs_reg_val =
32882ffc8bcaSDan McDonald 		    instance->func_ptr->read_fw_status_reg(instance);
32892ffc8bcaSDan McDonald 		fw_state	= cur_abs_reg_val & MFI_STATE_MASK;
32902ffc8bcaSDan McDonald 
32912ffc8bcaSDan McDonald 		con_log(CL_ANN1, (CE_NOTE,
32922ffc8bcaSDan McDonald 		    "mrsas_tbolt_reset_ppc :before fake: FW is not ready "
32932ffc8bcaSDan McDonald 		    "FW state = 0x%x", fw_state));
3294eef6dbdfSAndy Fiddaman 		if (mrsas_debug_tbolt_fw_faults_after_ocr == 1)
32952ffc8bcaSDan McDonald 			fw_state = MFI_STATE_FAULT;
32962ffc8bcaSDan McDonald 
32972ffc8bcaSDan McDonald 		con_log(CL_ANN,
32982ffc8bcaSDan McDonald 		    (CE_NOTE,  "mrsas_tbolt_reset_ppc : FW is not ready "
32992ffc8bcaSDan McDonald 		    "FW state = 0x%x", fw_state));
33002ffc8bcaSDan McDonald 
33012ffc8bcaSDan McDonald 		if (fw_state == MFI_STATE_FAULT) {
33022ffc8bcaSDan McDonald 			/* increment the count */
33032ffc8bcaSDan McDonald 			instance->fw_fault_count_after_ocr++;
33042ffc8bcaSDan McDonald 			if (instance->fw_fault_count_after_ocr
33052ffc8bcaSDan McDonald 			    < MAX_FW_RESET_COUNT) {
3306ff38cf9dSAndy Fiddaman 				dev_err(instance->dip, CE_WARN,
3307ff38cf9dSAndy Fiddaman 				    "mrsas_tbolt_reset_ppc: "
33082ffc8bcaSDan McDonald 				    "FW is in fault after OCR count %d "
33092ffc8bcaSDan McDonald 				    "Retry Reset",
33102ffc8bcaSDan McDonald 				    instance->fw_fault_count_after_ocr);
33112ffc8bcaSDan McDonald 				goto retry_reset;
33122ffc8bcaSDan McDonald 
33132ffc8bcaSDan McDonald 			} else {
3314ff38cf9dSAndy Fiddaman 				dev_err(instance->dip, CE_WARN, "%s:"
33152ffc8bcaSDan McDonald 				    "Max Reset Count exceeded >%d"
33162ffc8bcaSDan McDonald 				    "Mark HBA as bad, KILL adapter",
3317ff38cf9dSAndy Fiddaman 				    __func__, MAX_FW_RESET_COUNT);
33182ffc8bcaSDan McDonald 
33192ffc8bcaSDan McDonald 				mrsas_tbolt_kill_adapter(instance);
33202ffc8bcaSDan McDonald 				return (DDI_FAILURE);
33212ffc8bcaSDan McDonald 			}
33222ffc8bcaSDan McDonald 		}
33232ffc8bcaSDan McDonald 	}
33242ffc8bcaSDan McDonald 
33252ffc8bcaSDan McDonald 	/* reset the counter as FW is up after OCR */
33262ffc8bcaSDan McDonald 	instance->fw_fault_count_after_ocr = 0;
33272ffc8bcaSDan McDonald 
33282ffc8bcaSDan McDonald 	mrsas_reset_reply_desc(instance);
33292ffc8bcaSDan McDonald 
33302ffc8bcaSDan McDonald 	abs_state = mrsas_issue_init_mpi2(instance);
33312ffc8bcaSDan McDonald 	if (abs_state == (uint32_t)DDI_FAILURE) {
3332ff38cf9dSAndy Fiddaman 		dev_err(instance->dip, CE_WARN, "mrsas_tbolt_reset_ppc: "
33332ffc8bcaSDan McDonald 		    "INIT failed Retrying Reset");
33342ffc8bcaSDan McDonald 		goto retry_reset;
33352ffc8bcaSDan McDonald 	}
33362ffc8bcaSDan McDonald 
33372ffc8bcaSDan McDonald 	(void) mrsas_print_pending_cmds(instance);
33382ffc8bcaSDan McDonald 
33392ffc8bcaSDan McDonald 	instance->func_ptr->enable_intr(instance);
33402ffc8bcaSDan McDonald 	instance->fw_outstanding = 0;
33412ffc8bcaSDan McDonald 
33422ffc8bcaSDan McDonald 	(void) mrsas_issue_pending_cmds(instance);
33432ffc8bcaSDan McDonald 
33442ffc8bcaSDan McDonald 	instance->aen_cmd->retry_count_for_ocr = 0;
33452ffc8bcaSDan McDonald 	instance->aen_cmd->drv_pkt_time = 0;
33462ffc8bcaSDan McDonald 
33472ffc8bcaSDan McDonald 	instance->func_ptr->issue_cmd(instance->aen_cmd, instance);
33482ffc8bcaSDan McDonald 
33492ffc8bcaSDan McDonald 	mutex_enter(&instance->ocr_flags_mtx);
33502ffc8bcaSDan McDonald 	instance->adapterresetinprogress = 0;
33512ffc8bcaSDan McDonald 	mutex_exit(&instance->ocr_flags_mtx);
33522ffc8bcaSDan McDonald 
3353eef6dbdfSAndy Fiddaman 	dev_err(instance->dip, CE_NOTE, "TBOLT adapter reset successfully");
3354eef6dbdfSAndy Fiddaman 
33552ffc8bcaSDan McDonald 	return (DDI_SUCCESS);
33562ffc8bcaSDan McDonald }
33572ffc8bcaSDan McDonald 
33582ffc8bcaSDan McDonald /*
33592ffc8bcaSDan McDonald  * mrsas_sync_map_info -	Returns FW's ld_map structure
33602ffc8bcaSDan McDonald  * @instance:				Adapter soft state
33612ffc8bcaSDan McDonald  *
33622ffc8bcaSDan McDonald  * Issues an internal command (DCMD) to get the FW's controller PD
33632ffc8bcaSDan McDonald  * list structure.  This information is mainly used to find out SYSTEM
33642ffc8bcaSDan McDonald  * supported by the FW.
33652ffc8bcaSDan McDonald  */
33662ffc8bcaSDan McDonald 
33672ffc8bcaSDan McDonald static int
mrsas_tbolt_sync_map_info(struct mrsas_instance * instance)33682ffc8bcaSDan McDonald mrsas_tbolt_sync_map_info(struct mrsas_instance *instance)
33692ffc8bcaSDan McDonald {
33702ffc8bcaSDan McDonald 	int			ret = 0, i;
33712ffc8bcaSDan McDonald 	struct mrsas_cmd	*cmd = NULL;
33722ffc8bcaSDan McDonald 	struct mrsas_dcmd_frame	*dcmd;
33732ffc8bcaSDan McDonald 	uint32_t size_sync_info, num_lds;
33742ffc8bcaSDan McDonald 	LD_TARGET_SYNC *ci = NULL;
33752ffc8bcaSDan McDonald 	MR_FW_RAID_MAP_ALL *map;
33762ffc8bcaSDan McDonald 	MR_LD_RAID  *raid;
33772ffc8bcaSDan McDonald 	LD_TARGET_SYNC *ld_sync;
33782ffc8bcaSDan McDonald 	uint32_t ci_h = 0;
33792ffc8bcaSDan McDonald 	uint32_t size_map_info;
33802ffc8bcaSDan McDonald 
33812ffc8bcaSDan McDonald 	cmd = get_raid_msg_pkt(instance);
33822ffc8bcaSDan McDonald 
33832ffc8bcaSDan McDonald 	if (cmd == NULL) {
3384ff38cf9dSAndy Fiddaman 		dev_err(instance->dip, CE_WARN,
3385ff38cf9dSAndy Fiddaman 		    "Failed to get a cmd from free-pool in "
33862ffc8bcaSDan McDonald 		    "mrsas_tbolt_sync_map_info().");
33872ffc8bcaSDan McDonald 		return (DDI_FAILURE);
33882ffc8bcaSDan McDonald 	}
33892ffc8bcaSDan McDonald 
33902ffc8bcaSDan McDonald 	/* Clear the frame buffer and assign back the context id */
33912ffc8bcaSDan McDonald 	bzero((char *)&cmd->frame[0], sizeof (union mrsas_frame));
33922ffc8bcaSDan McDonald 	ddi_put32(cmd->frame_dma_obj.acc_handle, &cmd->frame->hdr.context,
33932ffc8bcaSDan McDonald 	    cmd->index);
33942ffc8bcaSDan McDonald 	bzero(cmd->scsi_io_request, sizeof (Mpi2RaidSCSIIORequest_t));
33952ffc8bcaSDan McDonald 
33962ffc8bcaSDan McDonald 
33972ffc8bcaSDan McDonald 	map = instance->ld_map[instance->map_id & 1];
33982ffc8bcaSDan McDonald 
33992ffc8bcaSDan McDonald 	num_lds = map->raidMap.ldCount;
34002ffc8bcaSDan McDonald 
34012ffc8bcaSDan McDonald 	dcmd = &cmd->frame->dcmd;
34022ffc8bcaSDan McDonald 
34032ffc8bcaSDan McDonald 	size_sync_info = sizeof (LD_TARGET_SYNC) * num_lds;
34042ffc8bcaSDan McDonald 
34052ffc8bcaSDan McDonald 	con_log(CL_ANN, (CE_NOTE, "size_sync_info =0x%x ; ld count = 0x%x",
34062ffc8bcaSDan McDonald 	    size_sync_info, num_lds));
34072ffc8bcaSDan McDonald 
34082ffc8bcaSDan McDonald 	ci = (LD_TARGET_SYNC *)instance->ld_map[(instance->map_id - 1) & 1];
34092ffc8bcaSDan McDonald 
34102ffc8bcaSDan McDonald 	bzero(ci, sizeof (MR_FW_RAID_MAP_ALL));
34112ffc8bcaSDan McDonald 	ci_h = instance->ld_map_phy[(instance->map_id - 1) & 1];
34122ffc8bcaSDan McDonald 
34132ffc8bcaSDan McDonald 	bzero(dcmd->mbox.b, DCMD_MBOX_SZ);
34142ffc8bcaSDan McDonald 
34152ffc8bcaSDan McDonald 	ld_sync = (LD_TARGET_SYNC *)ci;
34162ffc8bcaSDan McDonald 
34172ffc8bcaSDan McDonald 	for (i = 0; i < num_lds; i++, ld_sync++) {
34182ffc8bcaSDan McDonald 		raid = MR_LdRaidGet(i, map);
34192ffc8bcaSDan McDonald 
34202ffc8bcaSDan McDonald 		con_log(CL_ANN1,
34212ffc8bcaSDan McDonald 		    (CE_NOTE, "i : 0x%x, Seq Num : 0x%x, Sync Reqd : 0x%x",
34222ffc8bcaSDan McDonald 		    i, raid->seqNum, raid->flags.ldSyncRequired));
34232ffc8bcaSDan McDonald 
34242ffc8bcaSDan McDonald 		ld_sync->ldTargetId = MR_GetLDTgtId(i, map);
34252ffc8bcaSDan McDonald 
34262ffc8bcaSDan McDonald 		con_log(CL_ANN1, (CE_NOTE, "i : 0x%x, tgt : 0x%x",
34272ffc8bcaSDan McDonald 		    i, ld_sync->ldTargetId));
34282ffc8bcaSDan McDonald 
34292ffc8bcaSDan McDonald 		ld_sync->seqNum = raid->seqNum;
34302ffc8bcaSDan McDonald 	}
34312ffc8bcaSDan McDonald 
34322ffc8bcaSDan McDonald 
34332ffc8bcaSDan McDonald 	size_map_info = sizeof (MR_FW_RAID_MAP) +
34342ffc8bcaSDan McDonald 	    (sizeof (MR_LD_SPAN_MAP) * (MAX_LOGICAL_DRIVES - 1));
34352ffc8bcaSDan McDonald 
34362ffc8bcaSDan McDonald 	dcmd->cmd = MFI_CMD_OP_DCMD;
34372ffc8bcaSDan McDonald 	dcmd->cmd_status = 0xFF;
34382ffc8bcaSDan McDonald 	dcmd->sge_count = 1;
34392ffc8bcaSDan McDonald 	dcmd->flags = MFI_FRAME_DIR_WRITE;
34402ffc8bcaSDan McDonald 	dcmd->timeout = 0;
34412ffc8bcaSDan McDonald 	dcmd->pad_0 = 0;
34422ffc8bcaSDan McDonald 	dcmd->data_xfer_len = size_map_info;
34432ffc8bcaSDan McDonald 	ASSERT(num_lds <= 255);
34442ffc8bcaSDan McDonald 	dcmd->mbox.b[0] = (U8)num_lds;
34452ffc8bcaSDan McDonald 	dcmd->mbox.b[1] = 1; /* Pend */
34462ffc8bcaSDan McDonald 	dcmd->opcode = MR_DCMD_LD_MAP_GET_INFO;
34472ffc8bcaSDan McDonald 	dcmd->sgl.sge32[0].phys_addr = ci_h;
34482ffc8bcaSDan McDonald 	dcmd->sgl.sge32[0].length = size_map_info;
34492ffc8bcaSDan McDonald 
34502ffc8bcaSDan McDonald 
34512ffc8bcaSDan McDonald 	instance->map_update_cmd = cmd;
34522ffc8bcaSDan McDonald 	mr_sas_tbolt_build_mfi_cmd(instance, cmd);
34532ffc8bcaSDan McDonald 
34542ffc8bcaSDan McDonald 	instance->func_ptr->issue_cmd(cmd, instance);
34552ffc8bcaSDan McDonald 
34562ffc8bcaSDan McDonald 	instance->unroll.syncCmd = 1;
34572ffc8bcaSDan McDonald 	con_log(CL_ANN1, (CE_NOTE, "sync cmd issued. [SMID]:%x", cmd->SMID));
34582ffc8bcaSDan McDonald 
34592ffc8bcaSDan McDonald 	return (ret);
34602ffc8bcaSDan McDonald }
34612ffc8bcaSDan McDonald 
34622ffc8bcaSDan McDonald /*
34632ffc8bcaSDan McDonald  * abort_syncmap_cmd
34642ffc8bcaSDan McDonald  */
34652ffc8bcaSDan McDonald int
abort_syncmap_cmd(struct mrsas_instance * instance,struct mrsas_cmd * cmd_to_abort)34662ffc8bcaSDan McDonald abort_syncmap_cmd(struct mrsas_instance *instance,
34672ffc8bcaSDan McDonald     struct mrsas_cmd *cmd_to_abort)
34682ffc8bcaSDan McDonald {
34692ffc8bcaSDan McDonald 	int	ret = 0;
34702ffc8bcaSDan McDonald 
34712ffc8bcaSDan McDonald 	struct mrsas_cmd		*cmd;
34722ffc8bcaSDan McDonald 	struct mrsas_abort_frame	*abort_fr;
34732ffc8bcaSDan McDonald 
34742ffc8bcaSDan McDonald 	con_log(CL_ANN1, (CE_NOTE, "chkpnt: abort_ldsync:%d", __LINE__));
34752ffc8bcaSDan McDonald 
34762ffc8bcaSDan McDonald 	cmd = get_raid_msg_mfi_pkt(instance);
34772ffc8bcaSDan McDonald 
34782ffc8bcaSDan McDonald 	if (!cmd) {
3479ff38cf9dSAndy Fiddaman 		dev_err(instance->dip, CE_WARN,
34802ffc8bcaSDan McDonald 		    "Failed to get a cmd from free-pool abort_syncmap_cmd().");
34812ffc8bcaSDan McDonald 		return (DDI_FAILURE);
34822ffc8bcaSDan McDonald 	}
34832ffc8bcaSDan McDonald 	/* Clear the frame buffer and assign back the context id */
34842ffc8bcaSDan McDonald 	bzero((char *)&cmd->frame[0], sizeof (union mrsas_frame));
34852ffc8bcaSDan McDonald 	ddi_put32(cmd->frame_dma_obj.acc_handle, &cmd->frame->hdr.context,
34862ffc8bcaSDan McDonald 	    cmd->index);
34872ffc8bcaSDan McDonald 
34882ffc8bcaSDan McDonald 	abort_fr = &cmd->frame->abort;
34892ffc8bcaSDan McDonald 
34902ffc8bcaSDan McDonald 	/* prepare and issue the abort frame */
34912ffc8bcaSDan McDonald 	ddi_put8(cmd->frame_dma_obj.acc_handle,
34922ffc8bcaSDan McDonald 	    &abort_fr->cmd, MFI_CMD_OP_ABORT);
34932ffc8bcaSDan McDonald 	ddi_put8(cmd->frame_dma_obj.acc_handle, &abort_fr->cmd_status,
34942ffc8bcaSDan McDonald 	    MFI_CMD_STATUS_SYNC_MODE);
34952ffc8bcaSDan McDonald 	ddi_put16(cmd->frame_dma_obj.acc_handle, &abort_fr->flags, 0);
34962ffc8bcaSDan McDonald 	ddi_put32(cmd->frame_dma_obj.acc_handle, &abort_fr->abort_context,
34972ffc8bcaSDan McDonald 	    cmd_to_abort->index);
34982ffc8bcaSDan McDonald 	ddi_put32(cmd->frame_dma_obj.acc_handle,
34992ffc8bcaSDan McDonald 	    &abort_fr->abort_mfi_phys_addr_lo, cmd_to_abort->frame_phys_addr);
35002ffc8bcaSDan McDonald 	ddi_put32(cmd->frame_dma_obj.acc_handle,
35012ffc8bcaSDan McDonald 	    &abort_fr->abort_mfi_phys_addr_hi, 0);
35022ffc8bcaSDan McDonald 
35032ffc8bcaSDan McDonald 	cmd->frame_count = 1;
35042ffc8bcaSDan McDonald 
35052ffc8bcaSDan McDonald 	mr_sas_tbolt_build_mfi_cmd(instance, cmd);
35062ffc8bcaSDan McDonald 
35072ffc8bcaSDan McDonald 	if (instance->func_ptr->issue_cmd_in_poll_mode(instance, cmd)) {
35082ffc8bcaSDan McDonald 		con_log(CL_ANN1, (CE_WARN,
35092ffc8bcaSDan McDonald 		    "abort_ldsync_cmd: issue_cmd_in_poll_mode failed"));
35102ffc8bcaSDan McDonald 		ret = -1;
35112ffc8bcaSDan McDonald 	} else {
35122ffc8bcaSDan McDonald 		ret = 0;
35132ffc8bcaSDan McDonald 	}
35142ffc8bcaSDan McDonald 
35152ffc8bcaSDan McDonald 	return_raid_msg_mfi_pkt(instance, cmd);
35162ffc8bcaSDan McDonald 
35172ffc8bcaSDan McDonald 	atomic_add_16(&instance->fw_outstanding, (-1));
35182ffc8bcaSDan McDonald 
35192ffc8bcaSDan McDonald 	return (ret);
35202ffc8bcaSDan McDonald }
35212ffc8bcaSDan McDonald 
3522a1c36c8bSDan McDonald /*
3523a1c36c8bSDan McDonald  * Even though these functions were originally intended for 2208 only, it
3524a1c36c8bSDan McDonald  * turns out they're useful for "Skinny" support as well.  In a perfect world,
3525a1c36c8bSDan McDonald  * these two functions would be either in mr_sas.c, or in their own new source
3526a1c36c8bSDan McDonald  * file.  Since this driver needs some cleanup anyway, keep this portion in
3527a1c36c8bSDan McDonald  * mind as well.
3528a1c36c8bSDan McDonald  */
3529a1c36c8bSDan McDonald 
35302ffc8bcaSDan McDonald int
mrsas_tbolt_config_pd(struct mrsas_instance * instance,uint16_t tgt,uint8_t lun,dev_info_t ** ldip)35312ffc8bcaSDan McDonald mrsas_tbolt_config_pd(struct mrsas_instance *instance, uint16_t tgt,
35322ffc8bcaSDan McDonald     uint8_t lun, dev_info_t **ldip)
35332ffc8bcaSDan McDonald {
35342ffc8bcaSDan McDonald 	struct scsi_device *sd;
35352ffc8bcaSDan McDonald 	dev_info_t *child;
35362ffc8bcaSDan McDonald 	int rval, dtype;
35372ffc8bcaSDan McDonald 	struct mrsas_tbolt_pd_info *pds = NULL;
35382ffc8bcaSDan McDonald 
35392ffc8bcaSDan McDonald 	con_log(CL_ANN1, (CE_NOTE, "mrsas_tbolt_config_pd: t = %d l = %d",
35402ffc8bcaSDan McDonald 	    tgt, lun));
35412ffc8bcaSDan McDonald 
35422ffc8bcaSDan McDonald 	if ((child = mrsas_find_child(instance, tgt, lun)) != NULL) {
35432ffc8bcaSDan McDonald 		if (ldip) {
35442ffc8bcaSDan McDonald 			*ldip = child;
35452ffc8bcaSDan McDonald 		}
35462ffc8bcaSDan McDonald 		if (instance->mr_tbolt_pd_list[tgt].flag != MRDRV_TGT_VALID) {
35472ffc8bcaSDan McDonald 			rval = mrsas_service_evt(instance, tgt, 1,
3548*97ac1f64SToomas Soome 			    MRSAS_EVT_UNCONFIG_TGT, 0);
35492ffc8bcaSDan McDonald 			con_log(CL_ANN1, (CE_WARN,
35502ffc8bcaSDan McDonald 			    "mr_sas:DELETING STALE ENTRY  rval = %d "
35512ffc8bcaSDan McDonald 			    "tgt id = %d", rval, tgt));
35522ffc8bcaSDan McDonald 			return (NDI_FAILURE);
35532ffc8bcaSDan McDonald 		}
35542ffc8bcaSDan McDonald 		return (NDI_SUCCESS);
35552ffc8bcaSDan McDonald 	}
35562ffc8bcaSDan McDonald 
35572ffc8bcaSDan McDonald 	pds = (struct mrsas_tbolt_pd_info *)
35582ffc8bcaSDan McDonald 	    kmem_zalloc(sizeof (struct mrsas_tbolt_pd_info), KM_SLEEP);
35592ffc8bcaSDan McDonald 	mrsas_tbolt_get_pd_info(instance, pds, tgt);
35602ffc8bcaSDan McDonald 	dtype = pds->scsiDevType;
35612ffc8bcaSDan McDonald 
35622ffc8bcaSDan McDonald 	/* Check for Disk */
35632ffc8bcaSDan McDonald 	if ((dtype == DTYPE_DIRECT)) {
35642ffc8bcaSDan McDonald 		if ((dtype == DTYPE_DIRECT) &&
35652ffc8bcaSDan McDonald 		    (LE_16(pds->fwState) != PD_SYSTEM)) {
35662ffc8bcaSDan McDonald 			kmem_free(pds, sizeof (struct mrsas_tbolt_pd_info));
35672ffc8bcaSDan McDonald 			return (NDI_FAILURE);
35682ffc8bcaSDan McDonald 		}
35692ffc8bcaSDan McDonald 		sd = kmem_zalloc(sizeof (struct scsi_device), KM_SLEEP);
35702ffc8bcaSDan McDonald 		sd->sd_address.a_hba_tran = instance->tran;
35712ffc8bcaSDan McDonald 		sd->sd_address.a_target = (uint16_t)tgt;
35722ffc8bcaSDan McDonald 		sd->sd_address.a_lun = (uint8_t)lun;
35732ffc8bcaSDan McDonald 
35742ffc8bcaSDan McDonald 		if (scsi_hba_probe(sd, NULL) == SCSIPROBE_EXISTS) {
35752ffc8bcaSDan McDonald 			rval = mrsas_config_scsi_device(instance, sd, ldip);
3576ff38cf9dSAndy Fiddaman 			dev_err(instance->dip, CE_CONT,
3577ff38cf9dSAndy Fiddaman 			    "?Phys. device found: tgt %d dtype %d: %s\n",
3578ff38cf9dSAndy Fiddaman 			    tgt, dtype, sd->sd_inq->inq_vid);
35792ffc8bcaSDan McDonald 		} else {
35802ffc8bcaSDan McDonald 			rval = NDI_FAILURE;
35812ffc8bcaSDan McDonald 			con_log(CL_DLEVEL1, (CE_NOTE, "Phys. device Not found "
35822ffc8bcaSDan McDonald 			    "scsi_hba_probe Failed: tgt %d dtype %d: %s",
35832ffc8bcaSDan McDonald 			    tgt, dtype, sd->sd_inq->inq_vid));
35842ffc8bcaSDan McDonald 		}
35852ffc8bcaSDan McDonald 
35862ffc8bcaSDan McDonald 		/* sd_unprobe is blank now. Free buffer manually */
35872ffc8bcaSDan McDonald 		if (sd->sd_inq) {
35882ffc8bcaSDan McDonald 			kmem_free(sd->sd_inq, SUN_INQSIZE);
35892ffc8bcaSDan McDonald 			sd->sd_inq = (struct scsi_inquiry *)NULL;
35902ffc8bcaSDan McDonald 		}
35912ffc8bcaSDan McDonald 		kmem_free(sd, sizeof (struct scsi_device));
35922ffc8bcaSDan McDonald 	} else {
35932ffc8bcaSDan McDonald 		con_log(CL_ANN1, (CE_NOTE,
3594ff38cf9dSAndy Fiddaman 		    "?Device not supported: tgt %d lun %d dtype %d",
35952ffc8bcaSDan McDonald 		    tgt, lun, dtype));
35962ffc8bcaSDan McDonald 		rval = NDI_FAILURE;
35972ffc8bcaSDan McDonald 	}
35982ffc8bcaSDan McDonald 
35992ffc8bcaSDan McDonald 	kmem_free(pds, sizeof (struct mrsas_tbolt_pd_info));
36002ffc8bcaSDan McDonald 	con_log(CL_ANN1, (CE_NOTE, "mrsas_config_pd: return rval = %d",
36012ffc8bcaSDan McDonald 	    rval));
36022ffc8bcaSDan McDonald 	return (rval);
36032ffc8bcaSDan McDonald }
36042ffc8bcaSDan McDonald 
36052ffc8bcaSDan McDonald static void
mrsas_tbolt_get_pd_info(struct mrsas_instance * instance,struct mrsas_tbolt_pd_info * pds,int tgt)36062ffc8bcaSDan McDonald mrsas_tbolt_get_pd_info(struct mrsas_instance *instance,
36072ffc8bcaSDan McDonald     struct mrsas_tbolt_pd_info *pds, int tgt)
36082ffc8bcaSDan McDonald {
36092ffc8bcaSDan McDonald 	struct mrsas_cmd	*cmd;
36102ffc8bcaSDan McDonald 	struct mrsas_dcmd_frame	*dcmd;
36112ffc8bcaSDan McDonald 	dma_obj_t		dcmd_dma_obj;
36122ffc8bcaSDan McDonald 
3613a1c36c8bSDan McDonald 	ASSERT(instance->tbolt || instance->skinny);
3614a1c36c8bSDan McDonald 
3615a1c36c8bSDan McDonald 	if (instance->tbolt)
36162ffc8bcaSDan McDonald 		cmd = get_raid_msg_pkt(instance);
3617a1c36c8bSDan McDonald 	else
3618a1c36c8bSDan McDonald 		cmd = mrsas_get_mfi_pkt(instance);
36192ffc8bcaSDan McDonald 
36202ffc8bcaSDan McDonald 	if (!cmd) {
36212ffc8bcaSDan McDonald 		con_log(CL_ANN1,
36222ffc8bcaSDan McDonald 		    (CE_WARN, "Failed to get a cmd for get pd info"));
36232ffc8bcaSDan McDonald 		return;
36242ffc8bcaSDan McDonald 	}
36252ffc8bcaSDan McDonald 
36262ffc8bcaSDan McDonald 	/* Clear the frame buffer and assign back the context id */
36272ffc8bcaSDan McDonald 	bzero((char *)&cmd->frame[0], sizeof (union mrsas_frame));
36282ffc8bcaSDan McDonald 	ddi_put32(cmd->frame_dma_obj.acc_handle, &cmd->frame->hdr.context,
36292ffc8bcaSDan McDonald 	    cmd->index);
36302ffc8bcaSDan McDonald 
36312ffc8bcaSDan McDonald 
36322ffc8bcaSDan McDonald 	dcmd = &cmd->frame->dcmd;
36332ffc8bcaSDan McDonald 	dcmd_dma_obj.size = sizeof (struct mrsas_tbolt_pd_info);
36342ffc8bcaSDan McDonald 	dcmd_dma_obj.dma_attr = mrsas_generic_dma_attr;
36352ffc8bcaSDan McDonald 	dcmd_dma_obj.dma_attr.dma_attr_addr_hi = 0xffffffff;
36362ffc8bcaSDan McDonald 	dcmd_dma_obj.dma_attr.dma_attr_count_max = 0xffffffff;
36372ffc8bcaSDan McDonald 	dcmd_dma_obj.dma_attr.dma_attr_sgllen = 1;
36382ffc8bcaSDan McDonald 	dcmd_dma_obj.dma_attr.dma_attr_align = 1;
36392ffc8bcaSDan McDonald 
36402ffc8bcaSDan McDonald 	(void) mrsas_alloc_dma_obj(instance, &dcmd_dma_obj,
36412ffc8bcaSDan McDonald 	    DDI_STRUCTURE_LE_ACC);
36422ffc8bcaSDan McDonald 	bzero(dcmd_dma_obj.buffer, sizeof (struct mrsas_tbolt_pd_info));
36432ffc8bcaSDan McDonald 	bzero(dcmd->mbox.b, 12);
36442ffc8bcaSDan McDonald 	ddi_put8(cmd->frame_dma_obj.acc_handle, &dcmd->cmd, MFI_CMD_OP_DCMD);
36452ffc8bcaSDan McDonald 	ddi_put8(cmd->frame_dma_obj.acc_handle, &dcmd->cmd_status, 0);
36462ffc8bcaSDan McDonald 	ddi_put8(cmd->frame_dma_obj.acc_handle, &dcmd->sge_count, 1);
36472ffc8bcaSDan McDonald 	ddi_put16(cmd->frame_dma_obj.acc_handle, &dcmd->flags,
36482ffc8bcaSDan McDonald 	    MFI_FRAME_DIR_READ);
36492ffc8bcaSDan McDonald 	ddi_put16(cmd->frame_dma_obj.acc_handle, &dcmd->timeout, 0);
36502ffc8bcaSDan McDonald 	ddi_put32(cmd->frame_dma_obj.acc_handle, &dcmd->data_xfer_len,
36512ffc8bcaSDan McDonald 	    sizeof (struct mrsas_tbolt_pd_info));
36522ffc8bcaSDan McDonald 	ddi_put32(cmd->frame_dma_obj.acc_handle, &dcmd->opcode,
36532ffc8bcaSDan McDonald 	    MR_DCMD_PD_GET_INFO);
36542ffc8bcaSDan McDonald 	ddi_put32(cmd->frame_dma_obj.acc_handle, &dcmd->mbox.w[0], tgt);
36552ffc8bcaSDan McDonald 	ddi_put32(cmd->frame_dma_obj.acc_handle, &dcmd->sgl.sge32[0].length,
36562ffc8bcaSDan McDonald 	    sizeof (struct mrsas_tbolt_pd_info));
36572ffc8bcaSDan McDonald 	ddi_put32(cmd->frame_dma_obj.acc_handle, &dcmd->sgl.sge32[0].phys_addr,
36582ffc8bcaSDan McDonald 	    dcmd_dma_obj.dma_cookie[0].dmac_address);
36592ffc8bcaSDan McDonald 
36602ffc8bcaSDan McDonald 	cmd->sync_cmd = MRSAS_TRUE;
36612ffc8bcaSDan McDonald 	cmd->frame_count = 1;
36622ffc8bcaSDan McDonald 
3663a1c36c8bSDan McDonald 	if (instance->tbolt)
36642ffc8bcaSDan McDonald 		mr_sas_tbolt_build_mfi_cmd(instance, cmd);
36652ffc8bcaSDan McDonald 
36662ffc8bcaSDan McDonald 	instance->func_ptr->issue_cmd_in_sync_mode(instance, cmd);
36672ffc8bcaSDan McDonald 
36682ffc8bcaSDan McDonald 	ddi_rep_get8(cmd->frame_dma_obj.acc_handle, (uint8_t *)pds,
36692ffc8bcaSDan McDonald 	    (uint8_t *)dcmd_dma_obj.buffer, sizeof (struct mrsas_tbolt_pd_info),
36702ffc8bcaSDan McDonald 	    DDI_DEV_AUTOINCR);
36712ffc8bcaSDan McDonald 	(void) mrsas_free_dma_obj(instance, dcmd_dma_obj);
3672a1c36c8bSDan McDonald 
3673a1c36c8bSDan McDonald 	if (instance->tbolt)
36742ffc8bcaSDan McDonald 		return_raid_msg_pkt(instance, cmd);
3675a1c36c8bSDan McDonald 	else
3676a1c36c8bSDan McDonald 		mrsas_return_mfi_pkt(instance, cmd);
36772ffc8bcaSDan McDonald }
3678