180c94ecdSKeith M Wesolowski /*
280c94ecdSKeith M Wesolowski  * This file and its contents are supplied under the terms of the
380c94ecdSKeith M Wesolowski  * Common Development and Distribution License ("CDDL"), version 1.0.
480c94ecdSKeith M Wesolowski  * You may only use this file in accordance with the terms of version
580c94ecdSKeith M Wesolowski  * 1.0 of the CDDL.
680c94ecdSKeith M Wesolowski  *
780c94ecdSKeith M Wesolowski  * A full copy of the text of the CDDL should have accompanied this
880c94ecdSKeith M Wesolowski  * source.  A copy of the CDDL is also available via the Internet at
980c94ecdSKeith M Wesolowski  * http://www.illumos.org/license/CDDL.
1080c94ecdSKeith M Wesolowski  */
1180c94ecdSKeith M Wesolowski 
1280c94ecdSKeith M Wesolowski /*
1380c94ecdSKeith M Wesolowski  * Copyright (C) 2013 Hewlett-Packard Development Company, L.P.
14*48bbca81SDaniel Hoffman  * Copyright (c) 2016 by Delphix. All rights reserved.
1580c94ecdSKeith M Wesolowski  */
1680c94ecdSKeith M Wesolowski 
1780c94ecdSKeith M Wesolowski #include <sys/sdt.h>
1880c94ecdSKeith M Wesolowski #include "cpqary3.h"
1980c94ecdSKeith M Wesolowski 
2080c94ecdSKeith M Wesolowski /*
2180c94ecdSKeith M Wesolowski  * Local Functions Definitions
2280c94ecdSKeith M Wesolowski  */
2380c94ecdSKeith M Wesolowski 
2480c94ecdSKeith M Wesolowski uint8_t cpqary3_format_unit(cpqary3_cmdpvt_t *);
2580c94ecdSKeith M Wesolowski 
2680c94ecdSKeith M Wesolowski static uint8_t cpqary3_probe4LVs(cpqary3_t *);
2780c94ecdSKeith M Wesolowski static uint8_t cpqary3_probe4Tapes(cpqary3_t *);
2880c94ecdSKeith M Wesolowski 
2980c94ecdSKeith M Wesolowski 
3080c94ecdSKeith M Wesolowski /*
3180c94ecdSKeith M Wesolowski  * Function	:	cpqary3_probe4targets
3280c94ecdSKeith M Wesolowski  * Description	: 	This routine detects all existing logical drives
3380c94ecdSKeith M Wesolowski  *			and updates per target structure.
3480c94ecdSKeith M Wesolowski  * Called By	:  	cpqary3_tgt_init()
3580c94ecdSKeith M Wesolowski  * Parameters	: 	per-controller
3680c94ecdSKeith M Wesolowski  * Calls	:  	cpqary3_probe4LVs(), cpqary3_probe4Tapes()
3780c94ecdSKeith M Wesolowski  * Return Values: 	SUCCESS/ FAILURE
3880c94ecdSKeith M Wesolowski  *			[Shall fail only if Memory Constraints exist, the
3980c94ecdSKeith M Wesolowski  *			controller is defective/does not respond]
4080c94ecdSKeith M Wesolowski  */
4180c94ecdSKeith M Wesolowski uint8_t
cpqary3_probe4targets(cpqary3_t * cpqary3p)4280c94ecdSKeith M Wesolowski cpqary3_probe4targets(cpqary3_t *cpqary3p)
4380c94ecdSKeith M Wesolowski {
4480c94ecdSKeith M Wesolowski 	uint8_t rv;
4580c94ecdSKeith M Wesolowski 
4680c94ecdSKeith M Wesolowski 	rv = cpqary3_probe4LVs(cpqary3p);
4780c94ecdSKeith M Wesolowski 
4880c94ecdSKeith M Wesolowski 	if (CPQARY3_FAILURE == rv) {
4980c94ecdSKeith M Wesolowski 		return (rv);
5080c94ecdSKeith M Wesolowski 	}
5180c94ecdSKeith M Wesolowski 
5280c94ecdSKeith M Wesolowski 	rv = cpqary3_probe4Tapes(cpqary3p);
5380c94ecdSKeith M Wesolowski 
5480c94ecdSKeith M Wesolowski 	if (CPQARY3_FAILURE == rv) {
5580c94ecdSKeith M Wesolowski 		return (rv);
5680c94ecdSKeith M Wesolowski 	}
5780c94ecdSKeith M Wesolowski 
5880c94ecdSKeith M Wesolowski 	return (CPQARY3_SUCCESS);
5980c94ecdSKeith M Wesolowski 
6080c94ecdSKeith M Wesolowski }
6180c94ecdSKeith M Wesolowski 
6280c94ecdSKeith M Wesolowski /*
6380c94ecdSKeith M Wesolowski  * Function	:	cpqary3_build_cmdlist
6480c94ecdSKeith M Wesolowski  * Description	: 	This routine builds the command list for the specific
6580c94ecdSKeith M Wesolowski  *			opcode.
6680c94ecdSKeith M Wesolowski  * Called By	: 	cpqary3_transport()
6780c94ecdSKeith M Wesolowski  * Parameters	: 	cmdlist pvt struct, target id as received by SA.
6880c94ecdSKeith M Wesolowski  * Calls	: 	None
6980c94ecdSKeith M Wesolowski  * Return Values: 	SUCCESS		: 	Build is successful
7080c94ecdSKeith M Wesolowski  *			FAILURE		: 	Build has Failed
7180c94ecdSKeith M Wesolowski  */
7280c94ecdSKeith M Wesolowski uint8_t
cpqary3_build_cmdlist(cpqary3_cmdpvt_t * cpqary3_cmdpvtp,uint32_t tid)7380c94ecdSKeith M Wesolowski cpqary3_build_cmdlist(cpqary3_cmdpvt_t *cpqary3_cmdpvtp, uint32_t tid)
7480c94ecdSKeith M Wesolowski {
7580c94ecdSKeith M Wesolowski 	int		cntr;
7680c94ecdSKeith M Wesolowski 	cpqary3_t	*cpqary3p;
7780c94ecdSKeith M Wesolowski 	struct buf	*bfp;
7880c94ecdSKeith M Wesolowski 	cpqary3_tgt_t	*tgtp;
7980c94ecdSKeith M Wesolowski 	CommandList_t	*cmdlistp;
8080c94ecdSKeith M Wesolowski 
8180c94ecdSKeith M Wesolowski 	RETURN_FAILURE_IF_NULL(cpqary3_cmdpvtp);
8280c94ecdSKeith M Wesolowski 
8380c94ecdSKeith M Wesolowski 	if (NULL == (cpqary3p = cpqary3_cmdpvtp->ctlr))
8480c94ecdSKeith M Wesolowski 		return (CPQARY3_FAILURE);
8580c94ecdSKeith M Wesolowski 
8680c94ecdSKeith M Wesolowski 	bfp = (struct buf *)cpqary3_cmdpvtp->pvt_pkt->bf;
8780c94ecdSKeith M Wesolowski 
8880c94ecdSKeith M Wesolowski 	tgtp = cpqary3p->cpqary3_tgtp[tid];
8980c94ecdSKeith M Wesolowski 
9080c94ecdSKeith M Wesolowski 	if (!tgtp) {
9180c94ecdSKeith M Wesolowski 		return (CPQARY3_FAILURE);
9280c94ecdSKeith M Wesolowski 	}
9380c94ecdSKeith M Wesolowski 
9480c94ecdSKeith M Wesolowski 	cmdlistp = cpqary3_cmdpvtp->cmdlist_memaddr;
9580c94ecdSKeith M Wesolowski 
9680c94ecdSKeith M Wesolowski 	/* Update Cmd Header */
9780c94ecdSKeith M Wesolowski 	cmdlistp->Header.SGList = cpqary3_cmdpvtp->pvt_pkt->cmd_cookiecnt;
9880c94ecdSKeith M Wesolowski 	cmdlistp->Header.SGTotal = cpqary3_cmdpvtp->pvt_pkt->cmd_cookiecnt;
9980c94ecdSKeith M Wesolowski 	cmdlistp->Header.Tag.drvinfo_n_err = CPQARY3_OSCMD_SUCCESS;
10080c94ecdSKeith M Wesolowski 
10180c94ecdSKeith M Wesolowski 	if (tgtp->type == CPQARY3_TARGET_CTLR) {
10280c94ecdSKeith M Wesolowski 		cmdlistp->Header.LUN.PhysDev.TargetId = 0;
10380c94ecdSKeith M Wesolowski 		cmdlistp->Header.LUN.PhysDev.Bus = 0;
10480c94ecdSKeith M Wesolowski 		cmdlistp->Header.LUN.PhysDev.Mode = MASK_PERIPHERIAL_DEV_ADDR;
10580c94ecdSKeith M Wesolowski 	} else if (tgtp->type == CPQARY3_TARGET_LOG_VOL) {
10680c94ecdSKeith M Wesolowski 		cmdlistp->Header.LUN.LogDev.VolId = tgtp->logical_id;
10780c94ecdSKeith M Wesolowski 		cmdlistp->Header.LUN.LogDev.Mode = LOGICAL_VOL_ADDR;
10880c94ecdSKeith M Wesolowski 	} else if (tgtp->type == CPQARY3_TARGET_TAPE) {
10980c94ecdSKeith M Wesolowski 		bcopy(&(tgtp->PhysID), &(cmdlistp->Header.LUN.PhysDev),
11080c94ecdSKeith M Wesolowski 		    sizeof (PhysDevAddr_t));
11180c94ecdSKeith M Wesolowski 
11280c94ecdSKeith M Wesolowski 		DTRACE_PROBE1(build_cmdlist_tape, CommandList_t *, cmdlistp);
11380c94ecdSKeith M Wesolowski 	}
11480c94ecdSKeith M Wesolowski 
11580c94ecdSKeith M Wesolowski 	/* Cmd Request */
11680c94ecdSKeith M Wesolowski 	cmdlistp->Request.CDBLen = cpqary3_cmdpvtp->pvt_pkt->cdb_len;
11780c94ecdSKeith M Wesolowski 
11880c94ecdSKeith M Wesolowski 	bcopy((caddr_t)cpqary3_cmdpvtp->pvt_pkt->scsi_cmd_pkt->pkt_cdbp,
11980c94ecdSKeith M Wesolowski 	    (caddr_t)cmdlistp->Request.CDB, cpqary3_cmdpvtp->pvt_pkt->cdb_len);
12080c94ecdSKeith M Wesolowski 
12180c94ecdSKeith M Wesolowski 
12280c94ecdSKeith M Wesolowski 	cmdlistp->Request.Type.Type = CISS_TYPE_CMD;
12380c94ecdSKeith M Wesolowski 	cmdlistp->Request.Type.Attribute = CISS_ATTR_ORDERED;
12480c94ecdSKeith M Wesolowski 
12580c94ecdSKeith M Wesolowski 	DTRACE_PROBE2(build_cmdlist_buf, struct buf *, bfp,
12680c94ecdSKeith M Wesolowski 	    CommandList_t *, cmdlistp);
12780c94ecdSKeith M Wesolowski 
12880c94ecdSKeith M Wesolowski 	if (bfp && (bfp->b_flags & B_READ))
12980c94ecdSKeith M Wesolowski 		cmdlistp->Request.Type.Direction = CISS_XFER_READ;
13080c94ecdSKeith M Wesolowski 	else if (bfp && (bfp->b_flags & B_WRITE))
13180c94ecdSKeith M Wesolowski 		cmdlistp->Request.Type.Direction = CISS_XFER_WRITE;
13280c94ecdSKeith M Wesolowski 	else
13380c94ecdSKeith M Wesolowski 		cmdlistp->Request.Type.Direction = CISS_XFER_NONE;
13480c94ecdSKeith M Wesolowski 	/*
13580c94ecdSKeith M Wesolowski 	 * Looks like the above Direction is going for a toss in case of
13680c94ecdSKeith M Wesolowski 	 * MSA20(perticularly for 0x0a-write) connected to SMART Array.
13780c94ecdSKeith M Wesolowski 	 * If the above check fails, the below switch should take care.
13880c94ecdSKeith M Wesolowski 	 */
13980c94ecdSKeith M Wesolowski 
14080c94ecdSKeith M Wesolowski 	switch (cmdlistp->Request.CDB[0]) {
14180c94ecdSKeith M Wesolowski 		case 0x08:
14280c94ecdSKeith M Wesolowski 		case 0x28:
14380c94ecdSKeith M Wesolowski 			cmdlistp->Request.Type.Direction = CISS_XFER_READ;
14480c94ecdSKeith M Wesolowski 			break;
14580c94ecdSKeith M Wesolowski 		case 0x0A:
14680c94ecdSKeith M Wesolowski 		case 0x2A:
14780c94ecdSKeith M Wesolowski 			cmdlistp->Request.Type.Direction = CISS_XFER_WRITE;
14880c94ecdSKeith M Wesolowski 			break;
14980c94ecdSKeith M Wesolowski 	}
15080c94ecdSKeith M Wesolowski 	/*
15180c94ecdSKeith M Wesolowski 	 * NEED to increase this TimeOut value when the concerned
15280c94ecdSKeith M Wesolowski 	 * targets are tape devices(i.e., we need to do it here manually).
15380c94ecdSKeith M Wesolowski 	 */
15480c94ecdSKeith M Wesolowski 	cmdlistp->Request.Timeout = 2 *
15580c94ecdSKeith M Wesolowski 	    (cpqary3_cmdpvtp->pvt_pkt->scsi_cmd_pkt->pkt_time);
15680c94ecdSKeith M Wesolowski 
15780c94ecdSKeith M Wesolowski 	for (cntr = 0; cntr < cpqary3_cmdpvtp->pvt_pkt->cmd_cookiecnt; cntr++) {
15880c94ecdSKeith M Wesolowski 		cmdlistp->SG[cntr].Addr =
15980c94ecdSKeith M Wesolowski 		    cpqary3_cmdpvtp->pvt_pkt->
16080c94ecdSKeith M Wesolowski 		    cmd_dmacookies[cntr].dmac_laddress;
16180c94ecdSKeith M Wesolowski 		cmdlistp->SG[cntr].Len = (uint32_t)
16280c94ecdSKeith M Wesolowski 		    cpqary3_cmdpvtp->pvt_pkt->cmd_dmacookies[cntr].dmac_size;
16380c94ecdSKeith M Wesolowski 	}
16480c94ecdSKeith M Wesolowski 
16580c94ecdSKeith M Wesolowski 	return (CPQARY3_SUCCESS);
16680c94ecdSKeith M Wesolowski }
16780c94ecdSKeith M Wesolowski 
16880c94ecdSKeith M Wesolowski 
16980c94ecdSKeith M Wesolowski /*
17080c94ecdSKeith M Wesolowski  * Function	: 	cpqary3_send_abortcmd
17180c94ecdSKeith M Wesolowski  * Description	: 	Sends the Abort command to abort
17280c94ecdSKeith M Wesolowski  *			a set of cmds(on a target) or a cmdlist.
17380c94ecdSKeith M Wesolowski  * Called By	: 	cpqary3_abort
17480c94ecdSKeith M Wesolowski  * Parameters	: 	per controller, target_id, cmdlist to abort
17580c94ecdSKeith M Wesolowski  * Calls	:  	cpqary3_synccmd_alloc(), cpqary3_synccmd_send(),
17680c94ecdSKeith M Wesolowski  *			cpqary3_synccmd_free()
17780c94ecdSKeith M Wesolowski  * Return Values: 	SUCCESS - abort cmd submit is successful.
17880c94ecdSKeith M Wesolowski  *			FAILURE - Could not submit the abort cmd.
17980c94ecdSKeith M Wesolowski  */
18080c94ecdSKeith M Wesolowski uint8_t
cpqary3_send_abortcmd(cpqary3_t * cpqary3p,uint16_t target_id,CommandList_t * cmdlist2abortp)18180c94ecdSKeith M Wesolowski cpqary3_send_abortcmd(cpqary3_t *cpqary3p, uint16_t target_id,
18280c94ecdSKeith M Wesolowski     CommandList_t *cmdlist2abortp)
18380c94ecdSKeith M Wesolowski {
18480c94ecdSKeith M Wesolowski 	CommandList_t		*cmdlistp;
18580c94ecdSKeith M Wesolowski 	cpqary3_tgt_t		*cpqtgtp;
18680c94ecdSKeith M Wesolowski 	cpqary3_tag_t		*cpqary3_tagp;
18780c94ecdSKeith M Wesolowski 	cpqary3_cmdpvt_t	*cpqary3_cmdpvtp;
18880c94ecdSKeith M Wesolowski 
18980c94ecdSKeith M Wesolowski 	/*
19080c94ecdSKeith M Wesolowski 	 * NOTE : DO NOT perform this operation for cmdlist2abortp.
19180c94ecdSKeith M Wesolowski 	 * It may be NULL
19280c94ecdSKeith M Wesolowski 	 */
19380c94ecdSKeith M Wesolowski 	RETURN_FAILURE_IF_NULL(cpqary3p);
19480c94ecdSKeith M Wesolowski 
19580c94ecdSKeith M Wesolowski 	if (target_id == CTLR_SCSI_ID)
19680c94ecdSKeith M Wesolowski 		return (CPQARY3_FAILURE);
19780c94ecdSKeith M Wesolowski 
19880c94ecdSKeith M Wesolowski 	cpqtgtp = cpqary3p->cpqary3_tgtp[target_id];
19980c94ecdSKeith M Wesolowski 
20080c94ecdSKeith M Wesolowski 	if (!cpqtgtp) {
20180c94ecdSKeith M Wesolowski 		return (CPQARY3_FAILURE);
20280c94ecdSKeith M Wesolowski 	}
20380c94ecdSKeith M Wesolowski 
20480c94ecdSKeith M Wesolowski 	/*
20580c94ecdSKeith M Wesolowski 	 * Occupy the Command List
20680c94ecdSKeith M Wesolowski 	 * Update the Command List accordingly
20780c94ecdSKeith M Wesolowski 	 * Submit the command and wait for a signal
20880c94ecdSKeith M Wesolowski 	 */
20980c94ecdSKeith M Wesolowski 
21080c94ecdSKeith M Wesolowski 	/* BGB: CVFIX -> Introduced the call to cpqary3_synccmd_alloc */
21180c94ecdSKeith M Wesolowski 	cpqary3_cmdpvtp = cpqary3_synccmd_alloc(cpqary3p, 0);
21280c94ecdSKeith M Wesolowski 	if (cpqary3_cmdpvtp == NULL)
21380c94ecdSKeith M Wesolowski 		return (CPQARY3_FAILURE);
21480c94ecdSKeith M Wesolowski 
21580c94ecdSKeith M Wesolowski 	cmdlistp = cpqary3_cmdpvtp->cmdlist_memaddr;
21680c94ecdSKeith M Wesolowski 
21780c94ecdSKeith M Wesolowski 	cmdlistp->Header.SGList = 0;
21880c94ecdSKeith M Wesolowski 	cmdlistp->Header.SGTotal = 0;
21980c94ecdSKeith M Wesolowski 	cmdlistp->Header.Tag.drvinfo_n_err = CPQARY3_SYNCCMD_SUCCESS;
22080c94ecdSKeith M Wesolowski 	cmdlistp->Header.LUN.PhysDev.TargetId = 0;
22180c94ecdSKeith M Wesolowski 	cmdlistp->Header.LUN.PhysDev.Bus = 0;
22280c94ecdSKeith M Wesolowski 	cmdlistp->Header.LUN.PhysDev.Mode = PERIPHERIAL_DEV_ADDR;
22380c94ecdSKeith M Wesolowski 
22480c94ecdSKeith M Wesolowski 	cmdlistp->Request.Type.Type = CISS_TYPE_MSG;
22580c94ecdSKeith M Wesolowski 	cmdlistp->Request.Type.Attribute = CISS_ATTR_HEADOFQUEUE;
22680c94ecdSKeith M Wesolowski 	cmdlistp->Request.Type.Direction = CISS_XFER_NONE;
22780c94ecdSKeith M Wesolowski 	cmdlistp->Request.Timeout = CISS_NO_TIMEOUT;
22880c94ecdSKeith M Wesolowski 	cmdlistp->Request.CDBLen = CPQARY3_CDBLEN_16;
22980c94ecdSKeith M Wesolowski 	cmdlistp->Request.CDB[0] = CISS_MSG_ABORT;
23080c94ecdSKeith M Wesolowski 
23180c94ecdSKeith M Wesolowski 	if (cmdlist2abortp) { /* Abort this Particular Task */
23280c94ecdSKeith M Wesolowski 		cmdlistp->Request.CDB[1] = CISS_ABORT_TASK;
23380c94ecdSKeith M Wesolowski 		cpqary3_tagp = (cpqary3_tag_t *)&cmdlistp->Request.CDB[4];
23480c94ecdSKeith M Wesolowski 		cpqary3_tagp->drvinfo_n_err =
23580c94ecdSKeith M Wesolowski 		    cmdlist2abortp->Header.Tag.drvinfo_n_err;
23680c94ecdSKeith M Wesolowski 		cpqary3_tagp->tag_value = cmdlist2abortp->Header.Tag.tag_value;
23780c94ecdSKeith M Wesolowski 	} else { /* Abort all tasks for this Target */
23880c94ecdSKeith M Wesolowski 		cmdlistp->Request.CDB[1] = CISS_ABORT_TASKSET;
23980c94ecdSKeith M Wesolowski 
24080c94ecdSKeith M Wesolowski 		switch (cpqtgtp->type) {
24180c94ecdSKeith M Wesolowski 		case CPQARY3_TARGET_LOG_VOL:
24280c94ecdSKeith M Wesolowski 			cmdlistp->Header.LUN.LogDev.Mode = LOGICAL_VOL_ADDR;
24380c94ecdSKeith M Wesolowski 			cmdlistp->Header.LUN.LogDev.VolId = cpqtgtp->logical_id;
24480c94ecdSKeith M Wesolowski 			break;
24580c94ecdSKeith M Wesolowski 		case CPQARY3_TARGET_TAPE:
24680c94ecdSKeith M Wesolowski 			bcopy(&(cpqtgtp->PhysID),
24780c94ecdSKeith M Wesolowski 			    &(cmdlistp->Header.LUN.PhysDev),
24880c94ecdSKeith M Wesolowski 			    sizeof (PhysDevAddr_t));
24980c94ecdSKeith M Wesolowski 		}
25080c94ecdSKeith M Wesolowski 	}
25180c94ecdSKeith M Wesolowski 
25280c94ecdSKeith M Wesolowski 	/* PERF */
25380c94ecdSKeith M Wesolowski 
25480c94ecdSKeith M Wesolowski 	cpqary3_cmdpvtp->complete = cpqary3_synccmd_complete;
25580c94ecdSKeith M Wesolowski 
25680c94ecdSKeith M Wesolowski 	/* PERF */
25780c94ecdSKeith M Wesolowski 
25880c94ecdSKeith M Wesolowski 	/* BGB: CVFIX -> Introduced a call to cpqary3_synccmd_send */
25980c94ecdSKeith M Wesolowski 	if (cpqary3_synccmd_send(cpqary3p, cpqary3_cmdpvtp, 30000,
26080c94ecdSKeith M Wesolowski 	    CPQARY3_SYNCCMD_SEND_WAITSIG) != 0) {
26180c94ecdSKeith M Wesolowski 		cpqary3_synccmd_free(cpqary3p, cpqary3_cmdpvtp);
26280c94ecdSKeith M Wesolowski 		return (CPQARY3_FAILURE);
26380c94ecdSKeith M Wesolowski 	}
26480c94ecdSKeith M Wesolowski 
26580c94ecdSKeith M Wesolowski 	if (cpqary3_cmdpvtp->cmdlist_memaddr->Header.Tag.drvinfo_n_err ==
26680c94ecdSKeith M Wesolowski 	    CPQARY3_SYNCCMD_FAILURE) {
26780c94ecdSKeith M Wesolowski 		cpqary3_synccmd_free(cpqary3p, cpqary3_cmdpvtp);
26880c94ecdSKeith M Wesolowski 		return (CPQARY3_FAILURE);
26980c94ecdSKeith M Wesolowski 	}
27080c94ecdSKeith M Wesolowski 
27180c94ecdSKeith M Wesolowski 	cpqary3_synccmd_free(cpqary3p, cpqary3_cmdpvtp);
27280c94ecdSKeith M Wesolowski 
27380c94ecdSKeith M Wesolowski 	return (CPQARY3_SUCCESS);
27480c94ecdSKeith M Wesolowski 
27580c94ecdSKeith M Wesolowski }
27680c94ecdSKeith M Wesolowski 
27780c94ecdSKeith M Wesolowski 
27880c94ecdSKeith M Wesolowski /*
27980c94ecdSKeith M Wesolowski  * Function	: 	cpqary3_fulsh_cache
28080c94ecdSKeith M Wesolowski  * Description	: 	This routine flushes the controller cache.
28180c94ecdSKeith M Wesolowski  * Called By	: 	cpqary3_detach(), cpqary3_additional_cmd()
28280c94ecdSKeith M Wesolowski  * Parameters	: 	per controller
28380c94ecdSKeith M Wesolowski  * Calls	:  	cpqary3_synccmd_alloc(), cpqary3_synccmd_send()
28480c94ecdSKeith M Wesolowski  *			cpqary3_synccmd_free()
28580c94ecdSKeith M Wesolowski  * Return Values:	None
28680c94ecdSKeith M Wesolowski  */
28780c94ecdSKeith M Wesolowski void
cpqary3_flush_cache(cpqary3_t * cpqary3p)28880c94ecdSKeith M Wesolowski cpqary3_flush_cache(cpqary3_t *cpqary3p)
28980c94ecdSKeith M Wesolowski {
29080c94ecdSKeith M Wesolowski 	CommandList_t		*cmdlistp;
29180c94ecdSKeith M Wesolowski 	cpqary3_cmdpvt_t	*cpqary3_cmdpvtp;
29280c94ecdSKeith M Wesolowski 
29380c94ecdSKeith M Wesolowski 	/*
29480c94ecdSKeith M Wesolowski 	 * Occupy the Command List
29580c94ecdSKeith M Wesolowski 	 * Allocate Physically Contigous Memory for the FLUSH CACHE buffer
29680c94ecdSKeith M Wesolowski 	 * Update the Command List accordingly
29780c94ecdSKeith M Wesolowski 	 * Submit the command and wait for a signal
29880c94ecdSKeith M Wesolowski 	 */
29980c94ecdSKeith M Wesolowski 
30080c94ecdSKeith M Wesolowski 	ASSERT(cpqary3p != NULL);
30180c94ecdSKeith M Wesolowski 
30280c94ecdSKeith M Wesolowski 	/* grab a command and allocate a dma buffer */
30380c94ecdSKeith M Wesolowski 	cpqary3_cmdpvtp = cpqary3_synccmd_alloc(cpqary3p,
30480c94ecdSKeith M Wesolowski 	    sizeof (flushcache_buf_t));
30580c94ecdSKeith M Wesolowski 	if (cpqary3_cmdpvtp == NULL)
30680c94ecdSKeith M Wesolowski 		return;
30780c94ecdSKeith M Wesolowski 
30880c94ecdSKeith M Wesolowski 	cmdlistp = cpqary3_cmdpvtp->cmdlist_memaddr;
30980c94ecdSKeith M Wesolowski 	cmdlistp->Header.SGList = 1;
31080c94ecdSKeith M Wesolowski 	cmdlistp->Header.SGTotal = 1;
31180c94ecdSKeith M Wesolowski 	cmdlistp->Header.Tag.drvinfo_n_err = CPQARY3_SYNCCMD_SUCCESS;
31280c94ecdSKeith M Wesolowski 	cmdlistp->Header.LUN.PhysDev.TargetId = 0;
31380c94ecdSKeith M Wesolowski 	cmdlistp->Header.LUN.PhysDev.Bus = 0;
31480c94ecdSKeith M Wesolowski 	cmdlistp->Header.LUN.PhysDev.Mode = PERIPHERIAL_DEV_ADDR;
31580c94ecdSKeith M Wesolowski 
31680c94ecdSKeith M Wesolowski 	cmdlistp->Request.CDBLen = CPQARY3_CDBLEN_16;
31780c94ecdSKeith M Wesolowski 	cmdlistp->Request.Type.Type = CISS_TYPE_CMD;
31880c94ecdSKeith M Wesolowski 	cmdlistp->Request.Type.Attribute = CISS_ATTR_HEADOFQUEUE;
31980c94ecdSKeith M Wesolowski 	cmdlistp->Request.Type.Direction = CISS_XFER_WRITE;
32080c94ecdSKeith M Wesolowski 	cmdlistp->Request.Timeout = CISS_NO_TIMEOUT;
32180c94ecdSKeith M Wesolowski 	cmdlistp->Request.CDB[0] = ARRAY_WRITE;
32280c94ecdSKeith M Wesolowski 	cmdlistp->Request.CDB[6] = CISS_FLUSH_CACHE; /* 0xC2 */
32380c94ecdSKeith M Wesolowski 	cmdlistp->Request.CDB[8] = 0x02;
32480c94ecdSKeith M Wesolowski 
32580c94ecdSKeith M Wesolowski 	/* PERF */
32680c94ecdSKeith M Wesolowski 
32780c94ecdSKeith M Wesolowski 	cpqary3_cmdpvtp->complete = cpqary3_synccmd_complete;
32880c94ecdSKeith M Wesolowski 
32980c94ecdSKeith M Wesolowski 	/* PERF */
33080c94ecdSKeith M Wesolowski 
33180c94ecdSKeith M Wesolowski 	if (cpqary3_synccmd_send(cpqary3p, cpqary3_cmdpvtp, 90000,
33280c94ecdSKeith M Wesolowski 	    CPQARY3_SYNCCMD_SEND_WAITSIG) != 0) {
33380c94ecdSKeith M Wesolowski 		cpqary3_synccmd_free(cpqary3p, cpqary3_cmdpvtp);
33480c94ecdSKeith M Wesolowski 		cmn_err(CE_WARN, "CPQary3  %s : Flush Cache Operation"
33580c94ecdSKeith M Wesolowski 		    "Failed, Timeout", cpqary3p->hba_name);
33680c94ecdSKeith M Wesolowski 		return;
33780c94ecdSKeith M Wesolowski 	}
33880c94ecdSKeith M Wesolowski 
33980c94ecdSKeith M Wesolowski 	cpqary3_synccmd_free(cpqary3p, cpqary3_cmdpvtp);
34080c94ecdSKeith M Wesolowski }
34180c94ecdSKeith M Wesolowski 
34280c94ecdSKeith M Wesolowski /*
34380c94ecdSKeith M Wesolowski  * Function	:  	cpqary3_probe4LVs
34480c94ecdSKeith M Wesolowski  * Description	:  	This routine probes for the logical drives
34580c94ecdSKeith M Wesolowski  *			configured on the HP Smart Array controllers
34680c94ecdSKeith M Wesolowski  * Called By	:  	cpqary3_probe4targets()
34780c94ecdSKeith M Wesolowski  * Parameters	:  	per controller
34880c94ecdSKeith M Wesolowski  * Calls	:  	cpqary3_synccmd_alloc(), cpqary3_synccmd_send()
34980c94ecdSKeith M Wesolowski  *			cpqary3_synccmd_free()
35080c94ecdSKeith M Wesolowski  * Return Values:  	None
35180c94ecdSKeith M Wesolowski  */
35280c94ecdSKeith M Wesolowski uint8_t
cpqary3_probe4LVs(cpqary3_t * cpqary3p)35380c94ecdSKeith M Wesolowski cpqary3_probe4LVs(cpqary3_t *cpqary3p)
35480c94ecdSKeith M Wesolowski {
35580c94ecdSKeith M Wesolowski 	ulong_t			log_lun_no = 0;
35680c94ecdSKeith M Wesolowski 	ulong_t			lun_id = 0;
35780c94ecdSKeith M Wesolowski 	ulong_t			ld_count = 0;
35880c94ecdSKeith M Wesolowski 	ulong_t			i = 0;
35980c94ecdSKeith M Wesolowski 	ulong_t			cntr = 0;
36080c94ecdSKeith M Wesolowski 	uint32_t		data_addr_len;
36180c94ecdSKeith M Wesolowski 	rll_data_t		*rllp;
36280c94ecdSKeith M Wesolowski 	CommandList_t		*cmdlistp;
36380c94ecdSKeith M Wesolowski 	cpqary3_cmdpvt_t	*cpqary3_cmdpvtp;
36480c94ecdSKeith M Wesolowski 
36580c94ecdSKeith M Wesolowski 	/*
36680c94ecdSKeith M Wesolowski 	 * Occupy the Command List
36780c94ecdSKeith M Wesolowski 	 * Allocate Physically Contigous Memory
36880c94ecdSKeith M Wesolowski 	 * Update the Command List for Report Logical LUNS (rll) Command
36980c94ecdSKeith M Wesolowski 	 * This command detects all existing logical drives.
37080c94ecdSKeith M Wesolowski 	 * Submit and Poll for completion
37180c94ecdSKeith M Wesolowski 	 */
37280c94ecdSKeith M Wesolowski 
37380c94ecdSKeith M Wesolowski 	RETURN_FAILURE_IF_NULL(cpqary3p);
37480c94ecdSKeith M Wesolowski 
37580c94ecdSKeith M Wesolowski 	/* Sync Changes */
37680c94ecdSKeith M Wesolowski 	cpqary3_cmdpvtp = cpqary3_synccmd_alloc(cpqary3p, sizeof (rll_data_t));
37780c94ecdSKeith M Wesolowski 	if (cpqary3_cmdpvtp == NULL)
37880c94ecdSKeith M Wesolowski 		return (CPQARY3_FAILURE);
37980c94ecdSKeith M Wesolowski 
38080c94ecdSKeith M Wesolowski 	cmdlistp = cpqary3_cmdpvtp->cmdlist_memaddr;
38180c94ecdSKeith M Wesolowski 	rllp = (rll_data_t *)cpqary3_cmdpvtp->driverdata->sg;
38280c94ecdSKeith M Wesolowski 
38380c94ecdSKeith M Wesolowski 	cmdlistp->Header.SGList = 1;
38480c94ecdSKeith M Wesolowski 	cmdlistp->Header.SGTotal = 1;
38580c94ecdSKeith M Wesolowski 	cmdlistp->Header.Tag.drvinfo_n_err = CPQARY3_SYNCCMD_SUCCESS;
38680c94ecdSKeith M Wesolowski 	cmdlistp->Header.LUN.PhysDev.Mode = MASK_PERIPHERIAL_DEV_ADDR;
38780c94ecdSKeith M Wesolowski 
38880c94ecdSKeith M Wesolowski 	cmdlistp->Request.CDBLen = CPQARY3_CDBLEN_12;
38980c94ecdSKeith M Wesolowski 	cmdlistp->Request.Timeout = CISS_NO_TIMEOUT;
39080c94ecdSKeith M Wesolowski 	cmdlistp->Request.Type.Type = CISS_TYPE_CMD;
39180c94ecdSKeith M Wesolowski 	cmdlistp->Request.Type.Attribute = CISS_ATTR_ORDERED;
39280c94ecdSKeith M Wesolowski 	cmdlistp->Request.Type.Direction = CISS_XFER_READ;
39380c94ecdSKeith M Wesolowski 	cmdlistp->Request.CDB[0] = CISS_OPCODE_RLL;
39480c94ecdSKeith M Wesolowski 
39580c94ecdSKeith M Wesolowski 	data_addr_len = sizeof (rll_data_t);
39680c94ecdSKeith M Wesolowski 
39780c94ecdSKeith M Wesolowski 	cmdlistp->Request.CDB[6] = (data_addr_len >> 24) & 0xff;
39880c94ecdSKeith M Wesolowski 	cmdlistp->Request.CDB[7] = (data_addr_len >> 16) & 0xff;
39980c94ecdSKeith M Wesolowski 	cmdlistp->Request.CDB[8] = (data_addr_len >> 8) & 0xff;
40080c94ecdSKeith M Wesolowski 	cmdlistp->Request.CDB[9] = (data_addr_len) & 0xff;
40180c94ecdSKeith M Wesolowski 
40280c94ecdSKeith M Wesolowski 	DTRACE_PROBE2(rll_cmd_send, CommandList_t *, cmdlistp,
40380c94ecdSKeith M Wesolowski 	    cpqary3_cmdpvt_t *, cpqary3_cmdpvtp);
40480c94ecdSKeith M Wesolowski 
40580c94ecdSKeith M Wesolowski 	/* PERF */
40680c94ecdSKeith M Wesolowski 	cpqary3_cmdpvtp->complete = cpqary3_synccmd_complete;
40780c94ecdSKeith M Wesolowski 	/* PERF */
40880c94ecdSKeith M Wesolowski 
40980c94ecdSKeith M Wesolowski 	if (cpqary3_synccmd_send(cpqary3p, cpqary3_cmdpvtp, 90000,
41080c94ecdSKeith M Wesolowski 	    CPQARY3_SYNCCMD_SEND_WAITSIG) != 0) {
41180c94ecdSKeith M Wesolowski 		cpqary3_synccmd_free(cpqary3p, cpqary3_cmdpvtp);
41280c94ecdSKeith M Wesolowski 		return (CPQARY3_FAILURE);
41380c94ecdSKeith M Wesolowski 	}
41480c94ecdSKeith M Wesolowski 
41580c94ecdSKeith M Wesolowski 	if ((cpqary3_cmdpvtp->cmdlist_memaddr->Header.Tag.drvinfo_n_err ==
41680c94ecdSKeith M Wesolowski 	    CPQARY3_SYNCCMD_FAILURE) &&
41780c94ecdSKeith M Wesolowski 	    (cpqary3_cmdpvtp->errorinfop->CommandStatus !=
41880c94ecdSKeith M Wesolowski 	    CISS_CMD_DATA_UNDERRUN)) {
41980c94ecdSKeith M Wesolowski 		cmn_err(CE_WARN, "CPQary3 : Probe for logical targets "
42080c94ecdSKeith M Wesolowski 		    "returned ERROR !");
42180c94ecdSKeith M Wesolowski 		DTRACE_PROBE1(rll_cmd_fail,
42280c94ecdSKeith M Wesolowski 		    ErrorInfo_t *, cpqary3_cmdpvtp->errorinfop);
42380c94ecdSKeith M Wesolowski 		cpqary3_synccmd_free(cpqary3p, cpqary3_cmdpvtp);
42480c94ecdSKeith M Wesolowski 		return (CPQARY3_FAILURE);
42580c94ecdSKeith M Wesolowski 	}
42680c94ecdSKeith M Wesolowski 	/* Sync Changes */
42780c94ecdSKeith M Wesolowski 
42880c94ecdSKeith M Wesolowski 	log_lun_no = ((rllp->lunlist_byte0 + (rllp->lunlist_byte1 << 8) +
42980c94ecdSKeith M Wesolowski 	    (rllp->lunlist_byte2 << 16) + (rllp->lunlist_byte3 << 24)) / 8);
43080c94ecdSKeith M Wesolowski 
43180c94ecdSKeith M Wesolowski 	DTRACE_PROBE2(rll_cmd_result, rll_data_t *, rllp, ulong_t, log_lun_no);
43280c94ecdSKeith M Wesolowski 
43380c94ecdSKeith M Wesolowski 	/*
43480c94ecdSKeith M Wesolowski 	 * The following is to restrict the maximum number of supported logical
43580c94ecdSKeith M Wesolowski 	 * volumes to 32. This is very important as controller support upto 128
43680c94ecdSKeith M Wesolowski 	 * logical volumes and this driver implementation supports only 32.
43780c94ecdSKeith M Wesolowski 	 */
43880c94ecdSKeith M Wesolowski 
43980c94ecdSKeith M Wesolowski 	if (log_lun_no > MAX_LOGDRV) {
44080c94ecdSKeith M Wesolowski 		log_lun_no = MAX_LOGDRV;
44180c94ecdSKeith M Wesolowski 	}
44280c94ecdSKeith M Wesolowski 
44380c94ecdSKeith M Wesolowski 	cpqary3p->num_of_targets = log_lun_no;
44480c94ecdSKeith M Wesolowski 	DTRACE_PROBE1(update_lvlun_count, ulong_t, log_lun_no);
44580c94ecdSKeith M Wesolowski 
44680c94ecdSKeith M Wesolowski 	/*
44780c94ecdSKeith M Wesolowski 	 * Update per target structure with relevant information
44880c94ecdSKeith M Wesolowski 	 * CPQARY#_TGT_ALLIGNMENT is 1 because of the following mapping:
44980c94ecdSKeith M Wesolowski 	 * Target IDs 0-6 	in the OS = Logical Drives 0 - 6 in the HBA
45080c94ecdSKeith M Wesolowski 	 * Target ID  7 	in the OS = none in the HBA
45180c94ecdSKeith M Wesolowski 	 * Target IDs 8-32 	in the OS = Logical Drives 7 - 31 in the HBA
45280c94ecdSKeith M Wesolowski 	 * Everytime we reference a logical drive with ID > 6, we shall use
45380c94ecdSKeith M Wesolowski 	 * the alignment.
45480c94ecdSKeith M Wesolowski 	 */
45580c94ecdSKeith M Wesolowski 
45680c94ecdSKeith M Wesolowski 
45780c94ecdSKeith M Wesolowski 	/*
45880c94ecdSKeith M Wesolowski 	 * Depending upon the value of the variable legacy_mapping set in
45980c94ecdSKeith M Wesolowski 	 * cpqary3_attach(),
46080c94ecdSKeith M Wesolowski 	 * the target mapping algorithm to be used by the driver is decided.
46180c94ecdSKeith M Wesolowski 	 *
46280c94ecdSKeith M Wesolowski 	 * If the value of legacy_mapping is set to one, in the case of
46380c94ecdSKeith M Wesolowski 	 * Logical Drives with holes,
46480c94ecdSKeith M Wesolowski 	 * Targets will be renumbered by the driver as shown below
46580c94ecdSKeith M Wesolowski 	 * Below example makes the mapping logic clear.
46680c94ecdSKeith M Wesolowski 	 *
46780c94ecdSKeith M Wesolowski 	 * Logical Drive 0 in the HBA -> Target  ID 0 i.e., cXt0dXsx
46880c94ecdSKeith M Wesolowski 	 * Logical Drive 2 in the HBA ->  Target ID 1 i.e., cXt1dXsX
46980c94ecdSKeith M Wesolowski 	 * Logical Drive 3 in the HBA ->  Target ID 2 i.e., cXt2dXsX
47080c94ecdSKeith M Wesolowski 	 *
47180c94ecdSKeith M Wesolowski 	 * If the value of legacy_mapping is not one, then the Logical
47280c94ecdSKeith M Wesolowski 	 * Drive numbers will
47380c94ecdSKeith M Wesolowski 	 * not be renumbered in the case of holes, and the mapping
47480c94ecdSKeith M Wesolowski 	 * will be done as shown below
47580c94ecdSKeith M Wesolowski 	 * This will be the default mapping from 1.80 cpqary3 driver.
47680c94ecdSKeith M Wesolowski 	 *
47780c94ecdSKeith M Wesolowski 	 * Logical Drive 0  in the HBA -> Target ID 0 i.e. cXt0dXsx
47880c94ecdSKeith M Wesolowski 	 * Logical Drive 2 in the HBA ->  Target ID 2 i.e. cXt2dXsX
47980c94ecdSKeith M Wesolowski 	 * Logical Drive 3 in the HBA ->  Target ID 3 i.e. cXt3dXsX
48080c94ecdSKeith M Wesolowski 	 */
48180c94ecdSKeith M Wesolowski 
48280c94ecdSKeith M Wesolowski 
48380c94ecdSKeith M Wesolowski 	if (cpqary3p->legacy_mapping == 1) {
48480c94ecdSKeith M Wesolowski 		for (cntr = 0; cntr < log_lun_no; cntr++) {
48580c94ecdSKeith M Wesolowski 			i = ((cntr < CTLR_SCSI_ID) ?
48680c94ecdSKeith M Wesolowski 			    cntr : cntr + CPQARY3_TGT_ALIGNMENT);
48780c94ecdSKeith M Wesolowski 			if (!(cpqary3p->cpqary3_tgtp[i] = (cpqary3_tgt_t *)
48880c94ecdSKeith M Wesolowski 			    MEM_ZALLOC(sizeof (cpqary3_tgt_t)))) {
48980c94ecdSKeith M Wesolowski 				cmn_err(CE_WARN, "CPQary3 : Failed to Detect "
49080c94ecdSKeith M Wesolowski 				    "targets, Memory Allocation Failure");
49180c94ecdSKeith M Wesolowski 				cpqary3_synccmd_free(cpqary3p, cpqary3_cmdpvtp);
49280c94ecdSKeith M Wesolowski 				return (CPQARY3_FAILURE);
49380c94ecdSKeith M Wesolowski 			}
49480c94ecdSKeith M Wesolowski 
49580c94ecdSKeith M Wesolowski 			cpqary3p->cpqary3_tgtp[i]->logical_id =
49680c94ecdSKeith M Wesolowski 			    rllp->ll_data[cntr].logical_id;
49780c94ecdSKeith M Wesolowski 
49880c94ecdSKeith M Wesolowski 			cpqary3p->cpqary3_tgtp[i]->type =
49980c94ecdSKeith M Wesolowski 			    CPQARY3_TARGET_LOG_VOL;
50080c94ecdSKeith M Wesolowski 
50180c94ecdSKeith M Wesolowski 			DTRACE_PROBE2(lvlun_remapped,
50280c94ecdSKeith M Wesolowski 			    cpqary3_tgt_t *, cpqary3p->cpqary3_tgtp[i],
50380c94ecdSKeith M Wesolowski 			    rpl_data_t *, &rllp->ll_data[cntr]);
50480c94ecdSKeith M Wesolowski 		}
50580c94ecdSKeith M Wesolowski 	} else {
50680c94ecdSKeith M Wesolowski 		/*
50780c94ecdSKeith M Wesolowski 		 * Fix for QXCR1000446657: Logical drives are re numbered after
50880c94ecdSKeith M Wesolowski 		 * deleting a Logical drive.
50980c94ecdSKeith M Wesolowski 		 * We are using new indexing mechanism to fill the
51080c94ecdSKeith M Wesolowski 		 * cpqary3_tgtp[],
51180c94ecdSKeith M Wesolowski 		 * Check given during memory allocation of cpqary3_tgtp
51280c94ecdSKeith M Wesolowski 		 * elements, so that memory is not re-allocated each time the
51380c94ecdSKeith M Wesolowski 		 * cpqary3_probe4LVs() is called.
51480c94ecdSKeith M Wesolowski 		 * Check given while freeing the memory of the cpqary3_tgtp[]
51580c94ecdSKeith M Wesolowski 		 * elements, when a hole is found in the Logical Drives
51680c94ecdSKeith M Wesolowski 		 * configured.
51780c94ecdSKeith M Wesolowski 		 */
51880c94ecdSKeith M Wesolowski 
51980c94ecdSKeith M Wesolowski 		/* ensure that the loop will break for cntr = 32 in any case */
52080c94ecdSKeith M Wesolowski 		for (cntr = 0; ((ld_count < log_lun_no) && (cntr < MAX_LOGDRV));
52180c94ecdSKeith M Wesolowski 		    cntr++) {
52280c94ecdSKeith M Wesolowski 			i = ((cntr < CTLR_SCSI_ID) ?
52380c94ecdSKeith M Wesolowski 			    cntr : cntr + CPQARY3_TGT_ALIGNMENT);
52480c94ecdSKeith M Wesolowski 			lun_id = (rllp->ll_data[ld_count].logical_id & 0xFFFF);
52580c94ecdSKeith M Wesolowski 			if (cntr != lun_id) {
52680c94ecdSKeith M Wesolowski 				if (cpqary3p->cpqary3_tgtp[i]) {
52780c94ecdSKeith M Wesolowski 					MEM_SFREE(cpqary3p->cpqary3_tgtp[i],
52880c94ecdSKeith M Wesolowski 					    sizeof (cpqary3_tgt_t));
52980c94ecdSKeith M Wesolowski 					cpqary3p->cpqary3_tgtp[i] = NULL;
53080c94ecdSKeith M Wesolowski 				}
53180c94ecdSKeith M Wesolowski 			} else {
53280c94ecdSKeith M Wesolowski 				if (cpqary3p->cpqary3_tgtp[i] == NULL &&
53380c94ecdSKeith M Wesolowski 				    !(cpqary3p->cpqary3_tgtp[i] =
53480c94ecdSKeith M Wesolowski 				    (cpqary3_tgt_t *)MEM_ZALLOC(
53580c94ecdSKeith M Wesolowski 				    sizeof (cpqary3_tgt_t)))) {
53680c94ecdSKeith M Wesolowski 					cmn_err(CE_WARN,
53780c94ecdSKeith M Wesolowski 					    "CPQary3 : Failed to Detect "
53880c94ecdSKeith M Wesolowski 					    "targets, Memory Allocation "
53980c94ecdSKeith M Wesolowski 					    "Failure");
54080c94ecdSKeith M Wesolowski 					/* Sync Changes */
54180c94ecdSKeith M Wesolowski 					cpqary3_synccmd_free(cpqary3p,
54280c94ecdSKeith M Wesolowski 					    cpqary3_cmdpvtp);
54380c94ecdSKeith M Wesolowski 					/* Sync Changes */
54480c94ecdSKeith M Wesolowski 					return (CPQARY3_FAILURE);
54580c94ecdSKeith M Wesolowski 				}
54680c94ecdSKeith M Wesolowski 				cpqary3p->cpqary3_tgtp[i]->logical_id =
54780c94ecdSKeith M Wesolowski 				    rllp->ll_data[ld_count].logical_id;
54880c94ecdSKeith M Wesolowski 				cpqary3p->cpqary3_tgtp[i]->type =
54980c94ecdSKeith M Wesolowski 				    CPQARY3_TARGET_LOG_VOL;
55080c94ecdSKeith M Wesolowski 
55180c94ecdSKeith M Wesolowski 				/*
55280c94ecdSKeith M Wesolowski 				 * Send "BMIC sense logical drive status
55380c94ecdSKeith M Wesolowski 				 * command to set the target type to
55480c94ecdSKeith M Wesolowski 				 * CPQARY3_TARGET_NONE in case of logical
55580c94ecdSKeith M Wesolowski 				 * drive failure
55680c94ecdSKeith M Wesolowski 				 */
55780c94ecdSKeith M Wesolowski 
55880c94ecdSKeith M Wesolowski 				ld_count++;
55980c94ecdSKeith M Wesolowski 			}
56080c94ecdSKeith M Wesolowski 		}
56180c94ecdSKeith M Wesolowski 
56280c94ecdSKeith M Wesolowski 	}
56380c94ecdSKeith M Wesolowski 
56480c94ecdSKeith M Wesolowski 	/* HPQacucli Changes */
56580c94ecdSKeith M Wesolowski 	for (; cntr < MAX_LOGDRV; cntr++) {
56680c94ecdSKeith M Wesolowski 		cpqary3_tgt_t *t;
56780c94ecdSKeith M Wesolowski 		i = ((cntr < CTLR_SCSI_ID) ?
56880c94ecdSKeith M Wesolowski 		    cntr : cntr + CPQARY3_TGT_ALIGNMENT);
56980c94ecdSKeith M Wesolowski 		t = cpqary3p->cpqary3_tgtp[i];
57080c94ecdSKeith M Wesolowski 		cpqary3p->cpqary3_tgtp[i] = NULL;
57180c94ecdSKeith M Wesolowski 		if (t) {
57280c94ecdSKeith M Wesolowski 			MEM_SFREE(t, sizeof (*t));
57380c94ecdSKeith M Wesolowski 		}
57480c94ecdSKeith M Wesolowski 	}
57580c94ecdSKeith M Wesolowski 	/* HPQacucli Changes */
57680c94ecdSKeith M Wesolowski 
57780c94ecdSKeith M Wesolowski 	/* Sync Changes */
57880c94ecdSKeith M Wesolowski 	cpqary3_synccmd_free(cpqary3p, cpqary3_cmdpvtp);
57980c94ecdSKeith M Wesolowski 	/* Sync Changes */
58080c94ecdSKeith M Wesolowski 
58180c94ecdSKeith M Wesolowski 	return (CPQARY3_SUCCESS);
58280c94ecdSKeith M Wesolowski }
58380c94ecdSKeith M Wesolowski 
58480c94ecdSKeith M Wesolowski /*
58580c94ecdSKeith M Wesolowski  * Function	:  	cpqary3_probe4Tapes
58680c94ecdSKeith M Wesolowski  * Description	:  	This routine probes for the logical drives
58780c94ecdSKeith M Wesolowski  *			configured on the HP Smart Array controllers
58880c94ecdSKeith M Wesolowski  * Called By	:  	cpqary3_probe4targets()
58980c94ecdSKeith M Wesolowski  * Parameters	:  	per controller
59080c94ecdSKeith M Wesolowski  * Calls	:  	cpqary3_synccmd_alloc(), cpqary3_synccmd_send()
59180c94ecdSKeith M Wesolowski  *			cpqary3_synccmd_free()
59280c94ecdSKeith M Wesolowski  * Return Values:  	None
59380c94ecdSKeith M Wesolowski  */
59480c94ecdSKeith M Wesolowski uint8_t
cpqary3_probe4Tapes(cpqary3_t * cpqary3p)59580c94ecdSKeith M Wesolowski cpqary3_probe4Tapes(cpqary3_t *cpqary3p)
59680c94ecdSKeith M Wesolowski {
59780c94ecdSKeith M Wesolowski 	uint8_t			phy_lun_no;
59880c94ecdSKeith M Wesolowski 	uint32_t		ii = 0;
59980c94ecdSKeith M Wesolowski 	uint8_t			cntr = 0;
60080c94ecdSKeith M Wesolowski 	uint32_t		data_addr_len;
60180c94ecdSKeith M Wesolowski 	rpl_data_t		*rplp;
60280c94ecdSKeith M Wesolowski 	CommandList_t		*cmdlistp;
60380c94ecdSKeith M Wesolowski 	cpqary3_cmdpvt_t	*cpqary3_cmdpvtp;
60480c94ecdSKeith M Wesolowski 
60580c94ecdSKeith M Wesolowski 	/*
60680c94ecdSKeith M Wesolowski 	 * Occupy the Command List
60780c94ecdSKeith M Wesolowski 	 * Allocate Physically Contigous Memory
60880c94ecdSKeith M Wesolowski 	 * Update the Command List for Report Logical LUNS (rll) Command
60980c94ecdSKeith M Wesolowski 	 * This command detects all existing logical drives.
61080c94ecdSKeith M Wesolowski 	 * Submit and Poll for completion
61180c94ecdSKeith M Wesolowski 	 */
61280c94ecdSKeith M Wesolowski 
61380c94ecdSKeith M Wesolowski 	RETURN_FAILURE_IF_NULL(cpqary3p);
61480c94ecdSKeith M Wesolowski 
61580c94ecdSKeith M Wesolowski 	/* Sync Changes */
61680c94ecdSKeith M Wesolowski 	cpqary3_cmdpvtp = cpqary3_synccmd_alloc(cpqary3p, sizeof (rpl_data_t));
61780c94ecdSKeith M Wesolowski 	if (cpqary3_cmdpvtp == NULL)
61880c94ecdSKeith M Wesolowski 		return (CPQARY3_FAILURE);
61980c94ecdSKeith M Wesolowski 
62080c94ecdSKeith M Wesolowski 	cmdlistp = cpqary3_cmdpvtp->cmdlist_memaddr;
62180c94ecdSKeith M Wesolowski 	rplp = (rpl_data_t *)cpqary3_cmdpvtp->driverdata->sg;
62280c94ecdSKeith M Wesolowski 
62380c94ecdSKeith M Wesolowski 	/* Sync Changes */
62480c94ecdSKeith M Wesolowski 
62580c94ecdSKeith M Wesolowski 	cmdlistp->Header.SGList = 1;
62680c94ecdSKeith M Wesolowski 	cmdlistp->Header.SGTotal = 1;
62780c94ecdSKeith M Wesolowski 	cmdlistp->Header.Tag.drvinfo_n_err = CPQARY3_SYNCCMD_SUCCESS;
62880c94ecdSKeith M Wesolowski 	cmdlistp->Header.LUN.PhysDev.TargetId = 0;
62980c94ecdSKeith M Wesolowski 	cmdlistp->Header.LUN.PhysDev.Bus = 0;
63080c94ecdSKeith M Wesolowski 	cmdlistp->Header.LUN.PhysDev.Mode = MASK_PERIPHERIAL_DEV_ADDR;
63180c94ecdSKeith M Wesolowski 
63280c94ecdSKeith M Wesolowski 	cmdlistp->Request.CDBLen = CPQARY3_CDBLEN_12;
63380c94ecdSKeith M Wesolowski 	cmdlistp->Request.Timeout = CISS_NO_TIMEOUT;
63480c94ecdSKeith M Wesolowski 	cmdlistp->Request.Type.Type = CISS_TYPE_CMD;
63580c94ecdSKeith M Wesolowski 	cmdlistp->Request.Type.Attribute = CISS_ATTR_ORDERED;
63680c94ecdSKeith M Wesolowski 	cmdlistp->Request.Type.Direction = CISS_XFER_READ;
63780c94ecdSKeith M Wesolowski 	cmdlistp->Request.CDB[0] = CISS_OPCODE_RPL;
63880c94ecdSKeith M Wesolowski 
63980c94ecdSKeith M Wesolowski 	data_addr_len = sizeof (rpl_data_t);
64080c94ecdSKeith M Wesolowski 
64180c94ecdSKeith M Wesolowski 	cmdlistp->Request.CDB[6] = (data_addr_len >> 24) & 0xff;
64280c94ecdSKeith M Wesolowski 	cmdlistp->Request.CDB[7] = (data_addr_len >> 16) & 0xff;
64380c94ecdSKeith M Wesolowski 	cmdlistp->Request.CDB[8] = (data_addr_len >> 8) & 0xff;
64480c94ecdSKeith M Wesolowski 	cmdlistp->Request.CDB[9] = (data_addr_len) & 0xff;
64580c94ecdSKeith M Wesolowski 
64680c94ecdSKeith M Wesolowski 	DTRACE_PROBE2(tape_probe_cmd_send,
64780c94ecdSKeith M Wesolowski 	    CommandList_t *, cmdlistp, cpqary3_cmdpvt_t *, cpqary3_cmdpvtp);
64880c94ecdSKeith M Wesolowski 
64980c94ecdSKeith M Wesolowski 	/* PERF */
65080c94ecdSKeith M Wesolowski 	cpqary3_cmdpvtp->complete = cpqary3_synccmd_complete;
65180c94ecdSKeith M Wesolowski 	/* PERF */
65280c94ecdSKeith M Wesolowski 
65380c94ecdSKeith M Wesolowski 	/* Sync Changes */
65480c94ecdSKeith M Wesolowski 
65580c94ecdSKeith M Wesolowski 	if (cpqary3_synccmd_send(cpqary3p, cpqary3_cmdpvtp, 90000,
65680c94ecdSKeith M Wesolowski 	    CPQARY3_SYNCCMD_SEND_WAITSIG) != 0) {
65780c94ecdSKeith M Wesolowski 		cpqary3_synccmd_free(cpqary3p, cpqary3_cmdpvtp);
65880c94ecdSKeith M Wesolowski 		return (CPQARY3_FAILURE);
65980c94ecdSKeith M Wesolowski 	}
66080c94ecdSKeith M Wesolowski 
66180c94ecdSKeith M Wesolowski 	if ((cpqary3_cmdpvtp->cmdlist_memaddr->Header.Tag.drvinfo_n_err ==
66280c94ecdSKeith M Wesolowski 	    CPQARY3_SYNCCMD_FAILURE) &&
66380c94ecdSKeith M Wesolowski 	    (cpqary3_cmdpvtp->errorinfop->CommandStatus !=
66480c94ecdSKeith M Wesolowski 	    CISS_CMD_DATA_UNDERRUN)) {
66580c94ecdSKeith M Wesolowski 		cmn_err(CE_WARN, "CPQary3 : Probe for physical targets "
66680c94ecdSKeith M Wesolowski 		    "returned ERROR !");
66780c94ecdSKeith M Wesolowski 		DTRACE_PROBE1(tape_probe_cmdfail,
66880c94ecdSKeith M Wesolowski 		    ErrorInfo_t *, cpqary3_cmdpvtp->errorinfop);
66980c94ecdSKeith M Wesolowski 		cpqary3_synccmd_free(cpqary3p, cpqary3_cmdpvtp);
67080c94ecdSKeith M Wesolowski 		return (CPQARY3_FAILURE);
67180c94ecdSKeith M Wesolowski 	}
67280c94ecdSKeith M Wesolowski 	/* Sync Changes */
67380c94ecdSKeith M Wesolowski 
67480c94ecdSKeith M Wesolowski 	phy_lun_no = ((rplp->lunlist_byte0 +
67580c94ecdSKeith M Wesolowski 	    (rplp->lunlist_byte1 << 8) +
67680c94ecdSKeith M Wesolowski 	    (rplp->lunlist_byte2 << 16) +
67780c94ecdSKeith M Wesolowski 	    (rplp->lunlist_byte3 << 24)) / 8);
67880c94ecdSKeith M Wesolowski 
67980c94ecdSKeith M Wesolowski 	/*
68080c94ecdSKeith M Wesolowski 	 *	Update per target structure with relevant information
68180c94ecdSKeith M Wesolowski 	 * CPQARY3_TAPE_BASE is 33 because of the following mapping:
68280c94ecdSKeith M Wesolowski 	 * Target IDs 0-6 	in the OS = Logical Drives 0 - 6 in the HBA
68380c94ecdSKeith M Wesolowski 	 * Target ID  7 	in the OS = none in the HBA
68480c94ecdSKeith M Wesolowski 	 * Target IDs 8-32 	in the OS = Logical Drives 7 - 31 in the HBA
68580c94ecdSKeith M Wesolowski 	 * Target IDs 33 and above are reserved for Tapes and hence we need
68680c94ecdSKeith M Wesolowski 	 * the alignment.
68780c94ecdSKeith M Wesolowski 	 */
68880c94ecdSKeith M Wesolowski 
68980c94ecdSKeith M Wesolowski 
69080c94ecdSKeith M Wesolowski 	/*
69180c94ecdSKeith M Wesolowski 	 * HP Smart Array SAS controllers with Firmware revsion 5.14 or
69280c94ecdSKeith M Wesolowski 	 * later support
69380c94ecdSKeith M Wesolowski 	 * 64 Logical drives. So we are checking
69480c94ecdSKeith M Wesolowski 	 * if the controller is SAS or CISS and then assigning the value of the
69580c94ecdSKeith M Wesolowski 	 * TAPE BASE accordingly
69680c94ecdSKeith M Wesolowski 	 */
69780c94ecdSKeith M Wesolowski 
69880c94ecdSKeith M Wesolowski 	if (cpqary3p->bddef->bd_flags & SA_BD_SAS) {
69980c94ecdSKeith M Wesolowski 		ii = 0x41;	/* MAX_LOGDRV + 1 - 64 + 1 */
70080c94ecdSKeith M Wesolowski 	} else {
70180c94ecdSKeith M Wesolowski 		ii = 0x21;	/* MAX_LOGDRV + 1 - 32 + 1 */
70280c94ecdSKeith M Wesolowski 	}
70380c94ecdSKeith M Wesolowski 
70480c94ecdSKeith M Wesolowski 	for (cntr = 0; cntr < phy_lun_no; cntr++) {
70580c94ecdSKeith M Wesolowski 		if (rplp->pl_data[cntr].Mode == CISS_PHYS_MODE) {
70680c94ecdSKeith M Wesolowski 			if (cpqary3p->cpqary3_tgtp[ii] == NULL &&
70780c94ecdSKeith M Wesolowski 			    !(cpqary3p->cpqary3_tgtp[ii] =
70880c94ecdSKeith M Wesolowski 			    (cpqary3_tgt_t *)
70980c94ecdSKeith M Wesolowski 			    MEM_ZALLOC(sizeof (cpqary3_tgt_t)))) {
71080c94ecdSKeith M Wesolowski 				cmn_err(CE_WARN, "CPQary3 : Failed to Detect "
71180c94ecdSKeith M Wesolowski 				    "targets, Memory Allocation Failure");
71280c94ecdSKeith M Wesolowski 				cpqary3_synccmd_free(cpqary3p,
71380c94ecdSKeith M Wesolowski 				    cpqary3_cmdpvtp);
71480c94ecdSKeith M Wesolowski 				return (CPQARY3_FAILURE);
71580c94ecdSKeith M Wesolowski 			}
71680c94ecdSKeith M Wesolowski 
71780c94ecdSKeith M Wesolowski 			bcopy(&(rplp->pl_data[cntr]),
71880c94ecdSKeith M Wesolowski 			    &(cpqary3p->cpqary3_tgtp[ii]->PhysID),
71980c94ecdSKeith M Wesolowski 			    sizeof (PhysDevAddr_t));
72080c94ecdSKeith M Wesolowski 
72180c94ecdSKeith M Wesolowski 			cpqary3p->cpqary3_tgtp[ii]->type = CPQARY3_TARGET_TAPE;
72280c94ecdSKeith M Wesolowski 
72380c94ecdSKeith M Wesolowski 			DTRACE_PROBE1(tape_discovered,
72480c94ecdSKeith M Wesolowski 			    cpqary3_tgt_t *, cpqary3p->cpqary3_tgtp[ii]);
72580c94ecdSKeith M Wesolowski 
72680c94ecdSKeith M Wesolowski 			ii++;
72780c94ecdSKeith M Wesolowski 		}
72880c94ecdSKeith M Wesolowski 	}
72980c94ecdSKeith M Wesolowski 
73080c94ecdSKeith M Wesolowski 	/* Sync Changes */
73180c94ecdSKeith M Wesolowski 	cpqary3_synccmd_free(cpqary3p, cpqary3_cmdpvtp);
73280c94ecdSKeith M Wesolowski 	/* Sync Changes */
73380c94ecdSKeith M Wesolowski 
73480c94ecdSKeith M Wesolowski 	return (CPQARY3_SUCCESS);
73580c94ecdSKeith M Wesolowski 
73680c94ecdSKeith M Wesolowski }
73780c94ecdSKeith M Wesolowski 
73880c94ecdSKeith M Wesolowski /*
73980c94ecdSKeith M Wesolowski  * Function	:    cpqary3_synccmd_complete
74080c94ecdSKeith M Wesolowski  * Description	:    This routine processes the completed commands
74180c94ecdSKeith M Wesolowski  *			using the sync interface and
74280c94ecdSKeith M Wesolowski  *			initiates any callback that is needed.
74380c94ecdSKeith M Wesolowski  * Called By	:    cpqary3_transport
74480c94ecdSKeith M Wesolowski  * Parameters	:    per-command
74580c94ecdSKeith M Wesolowski  * Calls	:    cpqary3_cmdlist_release, cpqary3_synccmd_cleanup
74680c94ecdSKeith M Wesolowski  * Return Values:    None
74780c94ecdSKeith M Wesolowski  */
74880c94ecdSKeith M Wesolowski void
cpqary3_synccmd_complete(cpqary3_cmdpvt_t * cpqary3_cmdpvtp)74980c94ecdSKeith M Wesolowski cpqary3_synccmd_complete(cpqary3_cmdpvt_t *cpqary3_cmdpvtp)
75080c94ecdSKeith M Wesolowski {
75180c94ecdSKeith M Wesolowski 	cpqary3_t	*cpqary3p;
75280c94ecdSKeith M Wesolowski 
75380c94ecdSKeith M Wesolowski 	ASSERT(cpqary3_cmdpvtp != NULL);
75480c94ecdSKeith M Wesolowski 
75580c94ecdSKeith M Wesolowski 	if (CPQARY3_TIMEOUT == cpqary3_cmdpvtp->cmdpvt_flag) {
75680c94ecdSKeith M Wesolowski 		cpqary3_cmdlist_release(cpqary3_cmdpvtp, CPQARY3_NO_MUTEX);
75780c94ecdSKeith M Wesolowski 		return;
75880c94ecdSKeith M Wesolowski 	}
75980c94ecdSKeith M Wesolowski 
76080c94ecdSKeith M Wesolowski 	cpqary3p = cpqary3_cmdpvtp->ctlr;
76180c94ecdSKeith M Wesolowski 
76280c94ecdSKeith M Wesolowski 	if (cpqary3_cmdpvtp->cmdpvt_flag == CPQARY3_SYNC_TIMEOUT) {
76380c94ecdSKeith M Wesolowski 		/*
76480c94ecdSKeith M Wesolowski 		 * The submitter has abandoned this command, so we
76580c94ecdSKeith M Wesolowski 		 * have to free the resources here.
76680c94ecdSKeith M Wesolowski 		 */
76780c94ecdSKeith M Wesolowski 		mutex_exit(&(cpqary3p->sw_mutex));
76880c94ecdSKeith M Wesolowski 		cpqary3_synccmd_cleanup(cpqary3_cmdpvtp);
76980c94ecdSKeith M Wesolowski 		mutex_enter(&(cpqary3p->sw_mutex));
77080c94ecdSKeith M Wesolowski 	} else {
771*48bbca81SDaniel Hoffman 		/* submitter is waiting; wake it up */
77280c94ecdSKeith M Wesolowski 		cpqary3_cmdpvtp->cmdpvt_flag = 0;
77380c94ecdSKeith M Wesolowski 
77480c94ecdSKeith M Wesolowski 		/*
77580c94ecdSKeith M Wesolowski 		 * Fix for Flush Cache Operation Timed out issue:
77680c94ecdSKeith M Wesolowski 		 * cv_signal() wakes up only one blocked thread.
77780c94ecdSKeith M Wesolowski 		 * We need to use cv_broadcast which unblocks
77880c94ecdSKeith M Wesolowski 		 * all the blocked threads()
77980c94ecdSKeith M Wesolowski 		 */
78080c94ecdSKeith M Wesolowski 		cv_broadcast(&(cpqary3p->cv_ioctl_wait));
78180c94ecdSKeith M Wesolowski 	}
78280c94ecdSKeith M Wesolowski }
783