xref: /titanic_44/usr/src/uts/common/io/cpqary3/cpqary3_scsi.c (revision 80c94ecd7a524eb933a4bb221a9618b9dc490e76)
1*80c94ecdSKeith M Wesolowski /*
2*80c94ecdSKeith M Wesolowski  * This file and its contents are supplied under the terms of the
3*80c94ecdSKeith M Wesolowski  * Common Development and Distribution License ("CDDL"), version 1.0.
4*80c94ecdSKeith M Wesolowski  * You may only use this file in accordance with the terms of version
5*80c94ecdSKeith M Wesolowski  * 1.0 of the CDDL.
6*80c94ecdSKeith M Wesolowski  *
7*80c94ecdSKeith M Wesolowski  * A full copy of the text of the CDDL should have accompanied this
8*80c94ecdSKeith M Wesolowski  * source.  A copy of the CDDL is also available via the Internet at
9*80c94ecdSKeith M Wesolowski  * http://www.illumos.org/license/CDDL.
10*80c94ecdSKeith M Wesolowski  */
11*80c94ecdSKeith M Wesolowski 
12*80c94ecdSKeith M Wesolowski /*
13*80c94ecdSKeith M Wesolowski  * Copyright (C) 2013 Hewlett-Packard Development Company, L.P.
14*80c94ecdSKeith M Wesolowski  */
15*80c94ecdSKeith M Wesolowski 
16*80c94ecdSKeith M Wesolowski #include <sys/sdt.h>
17*80c94ecdSKeith M Wesolowski #include "cpqary3.h"
18*80c94ecdSKeith M Wesolowski 
19*80c94ecdSKeith M Wesolowski /*
20*80c94ecdSKeith M Wesolowski  * Local Functions Definitions
21*80c94ecdSKeith M Wesolowski  */
22*80c94ecdSKeith M Wesolowski 
23*80c94ecdSKeith M Wesolowski uint8_t cpqary3_format_unit(cpqary3_cmdpvt_t *);
24*80c94ecdSKeith M Wesolowski 
25*80c94ecdSKeith M Wesolowski static uint8_t cpqary3_probe4LVs(cpqary3_t *);
26*80c94ecdSKeith M Wesolowski static uint8_t cpqary3_probe4Tapes(cpqary3_t *);
27*80c94ecdSKeith M Wesolowski 
28*80c94ecdSKeith M Wesolowski 
29*80c94ecdSKeith M Wesolowski /*
30*80c94ecdSKeith M Wesolowski  * Function	:	cpqary3_probe4targets
31*80c94ecdSKeith M Wesolowski  * Description	: 	This routine detects all existing logical drives
32*80c94ecdSKeith M Wesolowski  *			and updates per target structure.
33*80c94ecdSKeith M Wesolowski  * Called By	:  	cpqary3_tgt_init()
34*80c94ecdSKeith M Wesolowski  * Parameters	: 	per-controller
35*80c94ecdSKeith M Wesolowski  * Calls	:  	cpqary3_probe4LVs(), cpqary3_probe4Tapes()
36*80c94ecdSKeith M Wesolowski  * Return Values: 	SUCCESS/ FAILURE
37*80c94ecdSKeith M Wesolowski  *			[Shall fail only if Memory Constraints exist, the
38*80c94ecdSKeith M Wesolowski  *			controller is defective/does not respond]
39*80c94ecdSKeith M Wesolowski  */
40*80c94ecdSKeith M Wesolowski uint8_t
cpqary3_probe4targets(cpqary3_t * cpqary3p)41*80c94ecdSKeith M Wesolowski cpqary3_probe4targets(cpqary3_t *cpqary3p)
42*80c94ecdSKeith M Wesolowski {
43*80c94ecdSKeith M Wesolowski 	uint8_t rv;
44*80c94ecdSKeith M Wesolowski 
45*80c94ecdSKeith M Wesolowski 	rv = cpqary3_probe4LVs(cpqary3p);
46*80c94ecdSKeith M Wesolowski 
47*80c94ecdSKeith M Wesolowski 	if (CPQARY3_FAILURE == rv) {
48*80c94ecdSKeith M Wesolowski 		return (rv);
49*80c94ecdSKeith M Wesolowski 	}
50*80c94ecdSKeith M Wesolowski 
51*80c94ecdSKeith M Wesolowski 	rv = cpqary3_probe4Tapes(cpqary3p);
52*80c94ecdSKeith M Wesolowski 
53*80c94ecdSKeith M Wesolowski 	if (CPQARY3_FAILURE == rv) {
54*80c94ecdSKeith M Wesolowski 		return (rv);
55*80c94ecdSKeith M Wesolowski 	}
56*80c94ecdSKeith M Wesolowski 
57*80c94ecdSKeith M Wesolowski 	return (CPQARY3_SUCCESS);
58*80c94ecdSKeith M Wesolowski 
59*80c94ecdSKeith M Wesolowski }
60*80c94ecdSKeith M Wesolowski 
61*80c94ecdSKeith M Wesolowski /*
62*80c94ecdSKeith M Wesolowski  * Function	:	cpqary3_build_cmdlist
63*80c94ecdSKeith M Wesolowski  * Description	: 	This routine builds the command list for the specific
64*80c94ecdSKeith M Wesolowski  *			opcode.
65*80c94ecdSKeith M Wesolowski  * Called By	: 	cpqary3_transport()
66*80c94ecdSKeith M Wesolowski  * Parameters	: 	cmdlist pvt struct, target id as received by SA.
67*80c94ecdSKeith M Wesolowski  * Calls	: 	None
68*80c94ecdSKeith M Wesolowski  * Return Values: 	SUCCESS		: 	Build is successful
69*80c94ecdSKeith M Wesolowski  *			FAILURE		: 	Build has Failed
70*80c94ecdSKeith M Wesolowski  */
71*80c94ecdSKeith M Wesolowski uint8_t
cpqary3_build_cmdlist(cpqary3_cmdpvt_t * cpqary3_cmdpvtp,uint32_t tid)72*80c94ecdSKeith M Wesolowski cpqary3_build_cmdlist(cpqary3_cmdpvt_t *cpqary3_cmdpvtp, uint32_t tid)
73*80c94ecdSKeith M Wesolowski {
74*80c94ecdSKeith M Wesolowski 	int		cntr;
75*80c94ecdSKeith M Wesolowski 	cpqary3_t	*cpqary3p;
76*80c94ecdSKeith M Wesolowski 	struct buf	*bfp;
77*80c94ecdSKeith M Wesolowski 	cpqary3_tgt_t	*tgtp;
78*80c94ecdSKeith M Wesolowski 	CommandList_t	*cmdlistp;
79*80c94ecdSKeith M Wesolowski 
80*80c94ecdSKeith M Wesolowski 	RETURN_FAILURE_IF_NULL(cpqary3_cmdpvtp);
81*80c94ecdSKeith M Wesolowski 
82*80c94ecdSKeith M Wesolowski 	if (NULL == (cpqary3p = cpqary3_cmdpvtp->ctlr))
83*80c94ecdSKeith M Wesolowski 		return (CPQARY3_FAILURE);
84*80c94ecdSKeith M Wesolowski 
85*80c94ecdSKeith M Wesolowski 	bfp = (struct buf *)cpqary3_cmdpvtp->pvt_pkt->bf;
86*80c94ecdSKeith M Wesolowski 
87*80c94ecdSKeith M Wesolowski 	tgtp = cpqary3p->cpqary3_tgtp[tid];
88*80c94ecdSKeith M Wesolowski 
89*80c94ecdSKeith M Wesolowski 	if (!tgtp) {
90*80c94ecdSKeith M Wesolowski 		return (CPQARY3_FAILURE);
91*80c94ecdSKeith M Wesolowski 	}
92*80c94ecdSKeith M Wesolowski 
93*80c94ecdSKeith M Wesolowski 	cmdlistp = cpqary3_cmdpvtp->cmdlist_memaddr;
94*80c94ecdSKeith M Wesolowski 
95*80c94ecdSKeith M Wesolowski 	/* Update Cmd Header */
96*80c94ecdSKeith M Wesolowski 	cmdlistp->Header.SGList = cpqary3_cmdpvtp->pvt_pkt->cmd_cookiecnt;
97*80c94ecdSKeith M Wesolowski 	cmdlistp->Header.SGTotal = cpqary3_cmdpvtp->pvt_pkt->cmd_cookiecnt;
98*80c94ecdSKeith M Wesolowski 	cmdlistp->Header.Tag.drvinfo_n_err = CPQARY3_OSCMD_SUCCESS;
99*80c94ecdSKeith M Wesolowski 
100*80c94ecdSKeith M Wesolowski 	if (tgtp->type == CPQARY3_TARGET_CTLR) {
101*80c94ecdSKeith M Wesolowski 		cmdlistp->Header.LUN.PhysDev.TargetId = 0;
102*80c94ecdSKeith M Wesolowski 		cmdlistp->Header.LUN.PhysDev.Bus = 0;
103*80c94ecdSKeith M Wesolowski 		cmdlistp->Header.LUN.PhysDev.Mode = MASK_PERIPHERIAL_DEV_ADDR;
104*80c94ecdSKeith M Wesolowski 	} else if (tgtp->type == CPQARY3_TARGET_LOG_VOL) {
105*80c94ecdSKeith M Wesolowski 		cmdlistp->Header.LUN.LogDev.VolId = tgtp->logical_id;
106*80c94ecdSKeith M Wesolowski 		cmdlistp->Header.LUN.LogDev.Mode = LOGICAL_VOL_ADDR;
107*80c94ecdSKeith M Wesolowski 	} else if (tgtp->type == CPQARY3_TARGET_TAPE) {
108*80c94ecdSKeith M Wesolowski 		bcopy(&(tgtp->PhysID), &(cmdlistp->Header.LUN.PhysDev),
109*80c94ecdSKeith M Wesolowski 		    sizeof (PhysDevAddr_t));
110*80c94ecdSKeith M Wesolowski 
111*80c94ecdSKeith M Wesolowski 		DTRACE_PROBE1(build_cmdlist_tape, CommandList_t *, cmdlistp);
112*80c94ecdSKeith M Wesolowski 	}
113*80c94ecdSKeith M Wesolowski 
114*80c94ecdSKeith M Wesolowski 	/* Cmd Request */
115*80c94ecdSKeith M Wesolowski 	cmdlistp->Request.CDBLen = cpqary3_cmdpvtp->pvt_pkt->cdb_len;
116*80c94ecdSKeith M Wesolowski 
117*80c94ecdSKeith M Wesolowski 	bcopy((caddr_t)cpqary3_cmdpvtp->pvt_pkt->scsi_cmd_pkt->pkt_cdbp,
118*80c94ecdSKeith M Wesolowski 	    (caddr_t)cmdlistp->Request.CDB, cpqary3_cmdpvtp->pvt_pkt->cdb_len);
119*80c94ecdSKeith M Wesolowski 
120*80c94ecdSKeith M Wesolowski 
121*80c94ecdSKeith M Wesolowski 	cmdlistp->Request.Type.Type = CISS_TYPE_CMD;
122*80c94ecdSKeith M Wesolowski 	cmdlistp->Request.Type.Attribute = CISS_ATTR_ORDERED;
123*80c94ecdSKeith M Wesolowski 
124*80c94ecdSKeith M Wesolowski 	DTRACE_PROBE2(build_cmdlist_buf, struct buf *, bfp,
125*80c94ecdSKeith M Wesolowski 	    CommandList_t *, cmdlistp);
126*80c94ecdSKeith M Wesolowski 
127*80c94ecdSKeith M Wesolowski 	if (bfp && (bfp->b_flags & B_READ))
128*80c94ecdSKeith M Wesolowski 		cmdlistp->Request.Type.Direction = CISS_XFER_READ;
129*80c94ecdSKeith M Wesolowski 	else if (bfp && (bfp->b_flags & B_WRITE))
130*80c94ecdSKeith M Wesolowski 		cmdlistp->Request.Type.Direction = CISS_XFER_WRITE;
131*80c94ecdSKeith M Wesolowski 	else
132*80c94ecdSKeith M Wesolowski 		cmdlistp->Request.Type.Direction = CISS_XFER_NONE;
133*80c94ecdSKeith M Wesolowski 	/*
134*80c94ecdSKeith M Wesolowski 	 * Looks like the above Direction is going for a toss in case of
135*80c94ecdSKeith M Wesolowski 	 * MSA20(perticularly for 0x0a-write) connected to SMART Array.
136*80c94ecdSKeith M Wesolowski 	 * If the above check fails, the below switch should take care.
137*80c94ecdSKeith M Wesolowski 	 */
138*80c94ecdSKeith M Wesolowski 
139*80c94ecdSKeith M Wesolowski 	switch (cmdlistp->Request.CDB[0]) {
140*80c94ecdSKeith M Wesolowski 		case 0x08:
141*80c94ecdSKeith M Wesolowski 		case 0x28:
142*80c94ecdSKeith M Wesolowski 			cmdlistp->Request.Type.Direction = CISS_XFER_READ;
143*80c94ecdSKeith M Wesolowski 			break;
144*80c94ecdSKeith M Wesolowski 		case 0x0A:
145*80c94ecdSKeith M Wesolowski 		case 0x2A:
146*80c94ecdSKeith M Wesolowski 			cmdlistp->Request.Type.Direction = CISS_XFER_WRITE;
147*80c94ecdSKeith M Wesolowski 			break;
148*80c94ecdSKeith M Wesolowski 	}
149*80c94ecdSKeith M Wesolowski 	/*
150*80c94ecdSKeith M Wesolowski 	 * NEED to increase this TimeOut value when the concerned
151*80c94ecdSKeith M Wesolowski 	 * targets are tape devices(i.e., we need to do it here manually).
152*80c94ecdSKeith M Wesolowski 	 */
153*80c94ecdSKeith M Wesolowski 	cmdlistp->Request.Timeout = 2 *
154*80c94ecdSKeith M Wesolowski 	    (cpqary3_cmdpvtp->pvt_pkt->scsi_cmd_pkt->pkt_time);
155*80c94ecdSKeith M Wesolowski 
156*80c94ecdSKeith M Wesolowski 	for (cntr = 0; cntr < cpqary3_cmdpvtp->pvt_pkt->cmd_cookiecnt; cntr++) {
157*80c94ecdSKeith M Wesolowski 		cmdlistp->SG[cntr].Addr =
158*80c94ecdSKeith M Wesolowski 		    cpqary3_cmdpvtp->pvt_pkt->
159*80c94ecdSKeith M Wesolowski 		    cmd_dmacookies[cntr].dmac_laddress;
160*80c94ecdSKeith M Wesolowski 		cmdlistp->SG[cntr].Len = (uint32_t)
161*80c94ecdSKeith M Wesolowski 		    cpqary3_cmdpvtp->pvt_pkt->cmd_dmacookies[cntr].dmac_size;
162*80c94ecdSKeith M Wesolowski 	}
163*80c94ecdSKeith M Wesolowski 
164*80c94ecdSKeith M Wesolowski 	return (CPQARY3_SUCCESS);
165*80c94ecdSKeith M Wesolowski }
166*80c94ecdSKeith M Wesolowski 
167*80c94ecdSKeith M Wesolowski 
168*80c94ecdSKeith M Wesolowski /*
169*80c94ecdSKeith M Wesolowski  * Function	: 	cpqary3_send_abortcmd
170*80c94ecdSKeith M Wesolowski  * Description	: 	Sends the Abort command to abort
171*80c94ecdSKeith M Wesolowski  *			a set of cmds(on a target) or a cmdlist.
172*80c94ecdSKeith M Wesolowski  * Called By	: 	cpqary3_abort
173*80c94ecdSKeith M Wesolowski  * Parameters	: 	per controller, target_id, cmdlist to abort
174*80c94ecdSKeith M Wesolowski  * Calls	:  	cpqary3_synccmd_alloc(), cpqary3_synccmd_send(),
175*80c94ecdSKeith M Wesolowski  *			cpqary3_synccmd_free()
176*80c94ecdSKeith M Wesolowski  * Return Values: 	SUCCESS - abort cmd submit is successful.
177*80c94ecdSKeith M Wesolowski  *			FAILURE - Could not submit the abort cmd.
178*80c94ecdSKeith M Wesolowski  */
179*80c94ecdSKeith M Wesolowski uint8_t
cpqary3_send_abortcmd(cpqary3_t * cpqary3p,uint16_t target_id,CommandList_t * cmdlist2abortp)180*80c94ecdSKeith M Wesolowski cpqary3_send_abortcmd(cpqary3_t *cpqary3p, uint16_t target_id,
181*80c94ecdSKeith M Wesolowski     CommandList_t *cmdlist2abortp)
182*80c94ecdSKeith M Wesolowski {
183*80c94ecdSKeith M Wesolowski 	CommandList_t		*cmdlistp;
184*80c94ecdSKeith M Wesolowski 	cpqary3_tgt_t		*cpqtgtp;
185*80c94ecdSKeith M Wesolowski 	cpqary3_tag_t		*cpqary3_tagp;
186*80c94ecdSKeith M Wesolowski 	cpqary3_cmdpvt_t	*cpqary3_cmdpvtp;
187*80c94ecdSKeith M Wesolowski 
188*80c94ecdSKeith M Wesolowski 	/*
189*80c94ecdSKeith M Wesolowski 	 * NOTE : DO NOT perform this operation for cmdlist2abortp.
190*80c94ecdSKeith M Wesolowski 	 * It may be NULL
191*80c94ecdSKeith M Wesolowski 	 */
192*80c94ecdSKeith M Wesolowski 	RETURN_FAILURE_IF_NULL(cpqary3p);
193*80c94ecdSKeith M Wesolowski 
194*80c94ecdSKeith M Wesolowski 	if (target_id == CTLR_SCSI_ID)
195*80c94ecdSKeith M Wesolowski 		return (CPQARY3_FAILURE);
196*80c94ecdSKeith M Wesolowski 
197*80c94ecdSKeith M Wesolowski 	cpqtgtp = cpqary3p->cpqary3_tgtp[target_id];
198*80c94ecdSKeith M Wesolowski 
199*80c94ecdSKeith M Wesolowski 	if (!cpqtgtp) {
200*80c94ecdSKeith M Wesolowski 		return (CPQARY3_FAILURE);
201*80c94ecdSKeith M Wesolowski 	}
202*80c94ecdSKeith M Wesolowski 
203*80c94ecdSKeith M Wesolowski 	/*
204*80c94ecdSKeith M Wesolowski 	 * Occupy the Command List
205*80c94ecdSKeith M Wesolowski 	 * Update the Command List accordingly
206*80c94ecdSKeith M Wesolowski 	 * Submit the command and wait for a signal
207*80c94ecdSKeith M Wesolowski 	 */
208*80c94ecdSKeith M Wesolowski 
209*80c94ecdSKeith M Wesolowski 	/* BGB: CVFIX -> Introduced the call to cpqary3_synccmd_alloc */
210*80c94ecdSKeith M Wesolowski 	cpqary3_cmdpvtp = cpqary3_synccmd_alloc(cpqary3p, 0);
211*80c94ecdSKeith M Wesolowski 	if (cpqary3_cmdpvtp == NULL)
212*80c94ecdSKeith M Wesolowski 		return (CPQARY3_FAILURE);
213*80c94ecdSKeith M Wesolowski 
214*80c94ecdSKeith M Wesolowski 	cmdlistp = cpqary3_cmdpvtp->cmdlist_memaddr;
215*80c94ecdSKeith M Wesolowski 
216*80c94ecdSKeith M Wesolowski 	cmdlistp->Header.SGList = 0;
217*80c94ecdSKeith M Wesolowski 	cmdlistp->Header.SGTotal = 0;
218*80c94ecdSKeith M Wesolowski 	cmdlistp->Header.Tag.drvinfo_n_err = CPQARY3_SYNCCMD_SUCCESS;
219*80c94ecdSKeith M Wesolowski 	cmdlistp->Header.LUN.PhysDev.TargetId = 0;
220*80c94ecdSKeith M Wesolowski 	cmdlistp->Header.LUN.PhysDev.Bus = 0;
221*80c94ecdSKeith M Wesolowski 	cmdlistp->Header.LUN.PhysDev.Mode = PERIPHERIAL_DEV_ADDR;
222*80c94ecdSKeith M Wesolowski 
223*80c94ecdSKeith M Wesolowski 	cmdlistp->Request.Type.Type = CISS_TYPE_MSG;
224*80c94ecdSKeith M Wesolowski 	cmdlistp->Request.Type.Attribute = CISS_ATTR_HEADOFQUEUE;
225*80c94ecdSKeith M Wesolowski 	cmdlistp->Request.Type.Direction = CISS_XFER_NONE;
226*80c94ecdSKeith M Wesolowski 	cmdlistp->Request.Timeout = CISS_NO_TIMEOUT;
227*80c94ecdSKeith M Wesolowski 	cmdlistp->Request.CDBLen = CPQARY3_CDBLEN_16;
228*80c94ecdSKeith M Wesolowski 	cmdlistp->Request.CDB[0] = CISS_MSG_ABORT;
229*80c94ecdSKeith M Wesolowski 
230*80c94ecdSKeith M Wesolowski 	if (cmdlist2abortp) { /* Abort this Particular Task */
231*80c94ecdSKeith M Wesolowski 		cmdlistp->Request.CDB[1] = CISS_ABORT_TASK;
232*80c94ecdSKeith M Wesolowski 		cpqary3_tagp = (cpqary3_tag_t *)&cmdlistp->Request.CDB[4];
233*80c94ecdSKeith M Wesolowski 		cpqary3_tagp->drvinfo_n_err =
234*80c94ecdSKeith M Wesolowski 		    cmdlist2abortp->Header.Tag.drvinfo_n_err;
235*80c94ecdSKeith M Wesolowski 		cpqary3_tagp->tag_value = cmdlist2abortp->Header.Tag.tag_value;
236*80c94ecdSKeith M Wesolowski 	} else { /* Abort all tasks for this Target */
237*80c94ecdSKeith M Wesolowski 		cmdlistp->Request.CDB[1] = CISS_ABORT_TASKSET;
238*80c94ecdSKeith M Wesolowski 
239*80c94ecdSKeith M Wesolowski 		switch (cpqtgtp->type) {
240*80c94ecdSKeith M Wesolowski 		case CPQARY3_TARGET_LOG_VOL:
241*80c94ecdSKeith M Wesolowski 			cmdlistp->Header.LUN.LogDev.Mode = LOGICAL_VOL_ADDR;
242*80c94ecdSKeith M Wesolowski 			cmdlistp->Header.LUN.LogDev.VolId = cpqtgtp->logical_id;
243*80c94ecdSKeith M Wesolowski 			break;
244*80c94ecdSKeith M Wesolowski 		case CPQARY3_TARGET_TAPE:
245*80c94ecdSKeith M Wesolowski 			bcopy(&(cpqtgtp->PhysID),
246*80c94ecdSKeith M Wesolowski 			    &(cmdlistp->Header.LUN.PhysDev),
247*80c94ecdSKeith M Wesolowski 			    sizeof (PhysDevAddr_t));
248*80c94ecdSKeith M Wesolowski 		}
249*80c94ecdSKeith M Wesolowski 	}
250*80c94ecdSKeith M Wesolowski 
251*80c94ecdSKeith M Wesolowski 	/* PERF */
252*80c94ecdSKeith M Wesolowski 
253*80c94ecdSKeith M Wesolowski 	cpqary3_cmdpvtp->complete = cpqary3_synccmd_complete;
254*80c94ecdSKeith M Wesolowski 
255*80c94ecdSKeith M Wesolowski 	/* PERF */
256*80c94ecdSKeith M Wesolowski 
257*80c94ecdSKeith M Wesolowski 	/* BGB: CVFIX -> Introduced a call to cpqary3_synccmd_send */
258*80c94ecdSKeith M Wesolowski 	if (cpqary3_synccmd_send(cpqary3p, cpqary3_cmdpvtp, 30000,
259*80c94ecdSKeith M Wesolowski 	    CPQARY3_SYNCCMD_SEND_WAITSIG) != 0) {
260*80c94ecdSKeith M Wesolowski 		cpqary3_synccmd_free(cpqary3p, cpqary3_cmdpvtp);
261*80c94ecdSKeith M Wesolowski 		return (CPQARY3_FAILURE);
262*80c94ecdSKeith M Wesolowski 	}
263*80c94ecdSKeith M Wesolowski 
264*80c94ecdSKeith M Wesolowski 	if (cpqary3_cmdpvtp->cmdlist_memaddr->Header.Tag.drvinfo_n_err ==
265*80c94ecdSKeith M Wesolowski 	    CPQARY3_SYNCCMD_FAILURE) {
266*80c94ecdSKeith M Wesolowski 		cpqary3_synccmd_free(cpqary3p, cpqary3_cmdpvtp);
267*80c94ecdSKeith M Wesolowski 		return (CPQARY3_FAILURE);
268*80c94ecdSKeith M Wesolowski 	}
269*80c94ecdSKeith M Wesolowski 
270*80c94ecdSKeith M Wesolowski 	cpqary3_synccmd_free(cpqary3p, cpqary3_cmdpvtp);
271*80c94ecdSKeith M Wesolowski 
272*80c94ecdSKeith M Wesolowski 	return (CPQARY3_SUCCESS);
273*80c94ecdSKeith M Wesolowski 
274*80c94ecdSKeith M Wesolowski }
275*80c94ecdSKeith M Wesolowski 
276*80c94ecdSKeith M Wesolowski 
277*80c94ecdSKeith M Wesolowski /*
278*80c94ecdSKeith M Wesolowski  * Function	: 	cpqary3_fulsh_cache
279*80c94ecdSKeith M Wesolowski  * Description	: 	This routine flushes the controller cache.
280*80c94ecdSKeith M Wesolowski  * Called By	: 	cpqary3_detach(), cpqary3_additional_cmd()
281*80c94ecdSKeith M Wesolowski  * Parameters	: 	per controller
282*80c94ecdSKeith M Wesolowski  * Calls	:  	cpqary3_synccmd_alloc(), cpqary3_synccmd_send()
283*80c94ecdSKeith M Wesolowski  *			cpqary3_synccmd_free()
284*80c94ecdSKeith M Wesolowski  * Return Values:	None
285*80c94ecdSKeith M Wesolowski  */
286*80c94ecdSKeith M Wesolowski void
cpqary3_flush_cache(cpqary3_t * cpqary3p)287*80c94ecdSKeith M Wesolowski cpqary3_flush_cache(cpqary3_t *cpqary3p)
288*80c94ecdSKeith M Wesolowski {
289*80c94ecdSKeith M Wesolowski 	CommandList_t		*cmdlistp;
290*80c94ecdSKeith M Wesolowski 	cpqary3_cmdpvt_t	*cpqary3_cmdpvtp;
291*80c94ecdSKeith M Wesolowski 
292*80c94ecdSKeith M Wesolowski 	/*
293*80c94ecdSKeith M Wesolowski 	 * Occupy the Command List
294*80c94ecdSKeith M Wesolowski 	 * Allocate Physically Contigous Memory for the FLUSH CACHE buffer
295*80c94ecdSKeith M Wesolowski 	 * Update the Command List accordingly
296*80c94ecdSKeith M Wesolowski 	 * Submit the command and wait for a signal
297*80c94ecdSKeith M Wesolowski 	 */
298*80c94ecdSKeith M Wesolowski 
299*80c94ecdSKeith M Wesolowski 	ASSERT(cpqary3p != NULL);
300*80c94ecdSKeith M Wesolowski 
301*80c94ecdSKeith M Wesolowski 	/* grab a command and allocate a dma buffer */
302*80c94ecdSKeith M Wesolowski 	cpqary3_cmdpvtp = cpqary3_synccmd_alloc(cpqary3p,
303*80c94ecdSKeith M Wesolowski 	    sizeof (flushcache_buf_t));
304*80c94ecdSKeith M Wesolowski 	if (cpqary3_cmdpvtp == NULL)
305*80c94ecdSKeith M Wesolowski 		return;
306*80c94ecdSKeith M Wesolowski 
307*80c94ecdSKeith M Wesolowski 	cmdlistp = cpqary3_cmdpvtp->cmdlist_memaddr;
308*80c94ecdSKeith M Wesolowski 	cmdlistp->Header.SGList = 1;
309*80c94ecdSKeith M Wesolowski 	cmdlistp->Header.SGTotal = 1;
310*80c94ecdSKeith M Wesolowski 	cmdlistp->Header.Tag.drvinfo_n_err = CPQARY3_SYNCCMD_SUCCESS;
311*80c94ecdSKeith M Wesolowski 	cmdlistp->Header.LUN.PhysDev.TargetId = 0;
312*80c94ecdSKeith M Wesolowski 	cmdlistp->Header.LUN.PhysDev.Bus = 0;
313*80c94ecdSKeith M Wesolowski 	cmdlistp->Header.LUN.PhysDev.Mode = PERIPHERIAL_DEV_ADDR;
314*80c94ecdSKeith M Wesolowski 
315*80c94ecdSKeith M Wesolowski 	cmdlistp->Request.CDBLen = CPQARY3_CDBLEN_16;
316*80c94ecdSKeith M Wesolowski 	cmdlistp->Request.Type.Type = CISS_TYPE_CMD;
317*80c94ecdSKeith M Wesolowski 	cmdlistp->Request.Type.Attribute = CISS_ATTR_HEADOFQUEUE;
318*80c94ecdSKeith M Wesolowski 	cmdlistp->Request.Type.Direction = CISS_XFER_WRITE;
319*80c94ecdSKeith M Wesolowski 	cmdlistp->Request.Timeout = CISS_NO_TIMEOUT;
320*80c94ecdSKeith M Wesolowski 	cmdlistp->Request.CDB[0] = ARRAY_WRITE;
321*80c94ecdSKeith M Wesolowski 	cmdlistp->Request.CDB[6] = CISS_FLUSH_CACHE; /* 0xC2 */
322*80c94ecdSKeith M Wesolowski 	cmdlistp->Request.CDB[8] = 0x02;
323*80c94ecdSKeith M Wesolowski 
324*80c94ecdSKeith M Wesolowski 	/* PERF */
325*80c94ecdSKeith M Wesolowski 
326*80c94ecdSKeith M Wesolowski 	cpqary3_cmdpvtp->complete = cpqary3_synccmd_complete;
327*80c94ecdSKeith M Wesolowski 
328*80c94ecdSKeith M Wesolowski 	/* PERF */
329*80c94ecdSKeith M Wesolowski 
330*80c94ecdSKeith M Wesolowski 	if (cpqary3_synccmd_send(cpqary3p, cpqary3_cmdpvtp, 90000,
331*80c94ecdSKeith M Wesolowski 	    CPQARY3_SYNCCMD_SEND_WAITSIG) != 0) {
332*80c94ecdSKeith M Wesolowski 		cpqary3_synccmd_free(cpqary3p, cpqary3_cmdpvtp);
333*80c94ecdSKeith M Wesolowski 		cmn_err(CE_WARN, "CPQary3  %s : Flush Cache Operation"
334*80c94ecdSKeith M Wesolowski 		    "Failed, Timeout", cpqary3p->hba_name);
335*80c94ecdSKeith M Wesolowski 		return;
336*80c94ecdSKeith M Wesolowski 	}
337*80c94ecdSKeith M Wesolowski 
338*80c94ecdSKeith M Wesolowski 	cpqary3_synccmd_free(cpqary3p, cpqary3_cmdpvtp);
339*80c94ecdSKeith M Wesolowski }
340*80c94ecdSKeith M Wesolowski 
341*80c94ecdSKeith M Wesolowski /*
342*80c94ecdSKeith M Wesolowski  * Function	:  	cpqary3_probe4LVs
343*80c94ecdSKeith M Wesolowski  * Description	:  	This routine probes for the logical drives
344*80c94ecdSKeith M Wesolowski  *			configured on the HP Smart Array controllers
345*80c94ecdSKeith M Wesolowski  * Called By	:  	cpqary3_probe4targets()
346*80c94ecdSKeith M Wesolowski  * Parameters	:  	per controller
347*80c94ecdSKeith M Wesolowski  * Calls	:  	cpqary3_synccmd_alloc(), cpqary3_synccmd_send()
348*80c94ecdSKeith M Wesolowski  *			cpqary3_synccmd_free()
349*80c94ecdSKeith M Wesolowski  * Return Values:  	None
350*80c94ecdSKeith M Wesolowski  */
351*80c94ecdSKeith M Wesolowski uint8_t
cpqary3_probe4LVs(cpqary3_t * cpqary3p)352*80c94ecdSKeith M Wesolowski cpqary3_probe4LVs(cpqary3_t *cpqary3p)
353*80c94ecdSKeith M Wesolowski {
354*80c94ecdSKeith M Wesolowski 	ulong_t			log_lun_no = 0;
355*80c94ecdSKeith M Wesolowski 	ulong_t			lun_id = 0;
356*80c94ecdSKeith M Wesolowski 	ulong_t			ld_count = 0;
357*80c94ecdSKeith M Wesolowski 	ulong_t			i = 0;
358*80c94ecdSKeith M Wesolowski 	ulong_t			cntr = 0;
359*80c94ecdSKeith M Wesolowski 	uint32_t		data_addr_len;
360*80c94ecdSKeith M Wesolowski 	rll_data_t		*rllp;
361*80c94ecdSKeith M Wesolowski 	CommandList_t		*cmdlistp;
362*80c94ecdSKeith M Wesolowski 	cpqary3_cmdpvt_t	*cpqary3_cmdpvtp;
363*80c94ecdSKeith M Wesolowski 
364*80c94ecdSKeith M Wesolowski 	/*
365*80c94ecdSKeith M Wesolowski 	 * Occupy the Command List
366*80c94ecdSKeith M Wesolowski 	 * Allocate Physically Contigous Memory
367*80c94ecdSKeith M Wesolowski 	 * Update the Command List for Report Logical LUNS (rll) Command
368*80c94ecdSKeith M Wesolowski 	 * This command detects all existing logical drives.
369*80c94ecdSKeith M Wesolowski 	 * Submit and Poll for completion
370*80c94ecdSKeith M Wesolowski 	 */
371*80c94ecdSKeith M Wesolowski 
372*80c94ecdSKeith M Wesolowski 	RETURN_FAILURE_IF_NULL(cpqary3p);
373*80c94ecdSKeith M Wesolowski 
374*80c94ecdSKeith M Wesolowski 	/* Sync Changes */
375*80c94ecdSKeith M Wesolowski 	cpqary3_cmdpvtp = cpqary3_synccmd_alloc(cpqary3p, sizeof (rll_data_t));
376*80c94ecdSKeith M Wesolowski 	if (cpqary3_cmdpvtp == NULL)
377*80c94ecdSKeith M Wesolowski 		return (CPQARY3_FAILURE);
378*80c94ecdSKeith M Wesolowski 
379*80c94ecdSKeith M Wesolowski 	cmdlistp = cpqary3_cmdpvtp->cmdlist_memaddr;
380*80c94ecdSKeith M Wesolowski 	rllp = (rll_data_t *)cpqary3_cmdpvtp->driverdata->sg;
381*80c94ecdSKeith M Wesolowski 
382*80c94ecdSKeith M Wesolowski 	cmdlistp->Header.SGList = 1;
383*80c94ecdSKeith M Wesolowski 	cmdlistp->Header.SGTotal = 1;
384*80c94ecdSKeith M Wesolowski 	cmdlistp->Header.Tag.drvinfo_n_err = CPQARY3_SYNCCMD_SUCCESS;
385*80c94ecdSKeith M Wesolowski 	cmdlistp->Header.LUN.PhysDev.Mode = MASK_PERIPHERIAL_DEV_ADDR;
386*80c94ecdSKeith M Wesolowski 
387*80c94ecdSKeith M Wesolowski 	cmdlistp->Request.CDBLen = CPQARY3_CDBLEN_12;
388*80c94ecdSKeith M Wesolowski 	cmdlistp->Request.Timeout = CISS_NO_TIMEOUT;
389*80c94ecdSKeith M Wesolowski 	cmdlistp->Request.Type.Type = CISS_TYPE_CMD;
390*80c94ecdSKeith M Wesolowski 	cmdlistp->Request.Type.Attribute = CISS_ATTR_ORDERED;
391*80c94ecdSKeith M Wesolowski 	cmdlistp->Request.Type.Direction = CISS_XFER_READ;
392*80c94ecdSKeith M Wesolowski 	cmdlistp->Request.CDB[0] = CISS_OPCODE_RLL;
393*80c94ecdSKeith M Wesolowski 
394*80c94ecdSKeith M Wesolowski 	data_addr_len = sizeof (rll_data_t);
395*80c94ecdSKeith M Wesolowski 
396*80c94ecdSKeith M Wesolowski 	cmdlistp->Request.CDB[6] = (data_addr_len >> 24) & 0xff;
397*80c94ecdSKeith M Wesolowski 	cmdlistp->Request.CDB[7] = (data_addr_len >> 16) & 0xff;
398*80c94ecdSKeith M Wesolowski 	cmdlistp->Request.CDB[8] = (data_addr_len >> 8) & 0xff;
399*80c94ecdSKeith M Wesolowski 	cmdlistp->Request.CDB[9] = (data_addr_len) & 0xff;
400*80c94ecdSKeith M Wesolowski 
401*80c94ecdSKeith M Wesolowski 	DTRACE_PROBE2(rll_cmd_send, CommandList_t *, cmdlistp,
402*80c94ecdSKeith M Wesolowski 	    cpqary3_cmdpvt_t *, cpqary3_cmdpvtp);
403*80c94ecdSKeith M Wesolowski 
404*80c94ecdSKeith M Wesolowski 	/* PERF */
405*80c94ecdSKeith M Wesolowski 	cpqary3_cmdpvtp->complete = cpqary3_synccmd_complete;
406*80c94ecdSKeith M Wesolowski 	/* PERF */
407*80c94ecdSKeith M Wesolowski 
408*80c94ecdSKeith M Wesolowski 	if (cpqary3_synccmd_send(cpqary3p, cpqary3_cmdpvtp, 90000,
409*80c94ecdSKeith M Wesolowski 	    CPQARY3_SYNCCMD_SEND_WAITSIG) != 0) {
410*80c94ecdSKeith M Wesolowski 		cpqary3_synccmd_free(cpqary3p, cpqary3_cmdpvtp);
411*80c94ecdSKeith M Wesolowski 		return (CPQARY3_FAILURE);
412*80c94ecdSKeith M Wesolowski 	}
413*80c94ecdSKeith M Wesolowski 
414*80c94ecdSKeith M Wesolowski 	if ((cpqary3_cmdpvtp->cmdlist_memaddr->Header.Tag.drvinfo_n_err ==
415*80c94ecdSKeith M Wesolowski 	    CPQARY3_SYNCCMD_FAILURE) &&
416*80c94ecdSKeith M Wesolowski 	    (cpqary3_cmdpvtp->errorinfop->CommandStatus !=
417*80c94ecdSKeith M Wesolowski 	    CISS_CMD_DATA_UNDERRUN)) {
418*80c94ecdSKeith M Wesolowski 		cmn_err(CE_WARN, "CPQary3 : Probe for logical targets "
419*80c94ecdSKeith M Wesolowski 		    "returned ERROR !");
420*80c94ecdSKeith M Wesolowski 		DTRACE_PROBE1(rll_cmd_fail,
421*80c94ecdSKeith M Wesolowski 		    ErrorInfo_t *, cpqary3_cmdpvtp->errorinfop);
422*80c94ecdSKeith M Wesolowski 		cpqary3_synccmd_free(cpqary3p, cpqary3_cmdpvtp);
423*80c94ecdSKeith M Wesolowski 		return (CPQARY3_FAILURE);
424*80c94ecdSKeith M Wesolowski 	}
425*80c94ecdSKeith M Wesolowski 	/* Sync Changes */
426*80c94ecdSKeith M Wesolowski 
427*80c94ecdSKeith M Wesolowski 	log_lun_no = ((rllp->lunlist_byte0 + (rllp->lunlist_byte1 << 8) +
428*80c94ecdSKeith M Wesolowski 	    (rllp->lunlist_byte2 << 16) + (rllp->lunlist_byte3 << 24)) / 8);
429*80c94ecdSKeith M Wesolowski 
430*80c94ecdSKeith M Wesolowski 	DTRACE_PROBE2(rll_cmd_result, rll_data_t *, rllp, ulong_t, log_lun_no);
431*80c94ecdSKeith M Wesolowski 
432*80c94ecdSKeith M Wesolowski 	/*
433*80c94ecdSKeith M Wesolowski 	 * The following is to restrict the maximum number of supported logical
434*80c94ecdSKeith M Wesolowski 	 * volumes to 32. This is very important as controller support upto 128
435*80c94ecdSKeith M Wesolowski 	 * logical volumes and this driver implementation supports only 32.
436*80c94ecdSKeith M Wesolowski 	 */
437*80c94ecdSKeith M Wesolowski 
438*80c94ecdSKeith M Wesolowski 	if (log_lun_no > MAX_LOGDRV) {
439*80c94ecdSKeith M Wesolowski 		log_lun_no = MAX_LOGDRV;
440*80c94ecdSKeith M Wesolowski 	}
441*80c94ecdSKeith M Wesolowski 
442*80c94ecdSKeith M Wesolowski 	cpqary3p->num_of_targets = log_lun_no;
443*80c94ecdSKeith M Wesolowski 	DTRACE_PROBE1(update_lvlun_count, ulong_t, log_lun_no);
444*80c94ecdSKeith M Wesolowski 
445*80c94ecdSKeith M Wesolowski 	/*
446*80c94ecdSKeith M Wesolowski 	 * Update per target structure with relevant information
447*80c94ecdSKeith M Wesolowski 	 * CPQARY#_TGT_ALLIGNMENT is 1 because of the following mapping:
448*80c94ecdSKeith M Wesolowski 	 * Target IDs 0-6 	in the OS = Logical Drives 0 - 6 in the HBA
449*80c94ecdSKeith M Wesolowski 	 * Target ID  7 	in the OS = none in the HBA
450*80c94ecdSKeith M Wesolowski 	 * Target IDs 8-32 	in the OS = Logical Drives 7 - 31 in the HBA
451*80c94ecdSKeith M Wesolowski 	 * Everytime we reference a logical drive with ID > 6, we shall use
452*80c94ecdSKeith M Wesolowski 	 * the alignment.
453*80c94ecdSKeith M Wesolowski 	 */
454*80c94ecdSKeith M Wesolowski 
455*80c94ecdSKeith M Wesolowski 
456*80c94ecdSKeith M Wesolowski 	/*
457*80c94ecdSKeith M Wesolowski 	 * Depending upon the value of the variable legacy_mapping set in
458*80c94ecdSKeith M Wesolowski 	 * cpqary3_attach(),
459*80c94ecdSKeith M Wesolowski 	 * the target mapping algorithm to be used by the driver is decided.
460*80c94ecdSKeith M Wesolowski 	 *
461*80c94ecdSKeith M Wesolowski 	 * If the value of legacy_mapping is set to one, in the case of
462*80c94ecdSKeith M Wesolowski 	 * Logical Drives with holes,
463*80c94ecdSKeith M Wesolowski 	 * Targets will be renumbered by the driver as shown below
464*80c94ecdSKeith M Wesolowski 	 * Below example makes the mapping logic clear.
465*80c94ecdSKeith M Wesolowski 	 *
466*80c94ecdSKeith M Wesolowski 	 * Logical Drive 0 in the HBA -> Target  ID 0 i.e., cXt0dXsx
467*80c94ecdSKeith M Wesolowski 	 * Logical Drive 2 in the HBA ->  Target ID 1 i.e., cXt1dXsX
468*80c94ecdSKeith M Wesolowski 	 * Logical Drive 3 in the HBA ->  Target ID 2 i.e., cXt2dXsX
469*80c94ecdSKeith M Wesolowski 	 *
470*80c94ecdSKeith M Wesolowski 	 * If the value of legacy_mapping is not one, then the Logical
471*80c94ecdSKeith M Wesolowski 	 * Drive numbers will
472*80c94ecdSKeith M Wesolowski 	 * not be renumbered in the case of holes, and the mapping
473*80c94ecdSKeith M Wesolowski 	 * will be done as shown below
474*80c94ecdSKeith M Wesolowski 	 * This will be the default mapping from 1.80 cpqary3 driver.
475*80c94ecdSKeith M Wesolowski 	 *
476*80c94ecdSKeith M Wesolowski 	 * Logical Drive 0  in the HBA -> Target ID 0 i.e. cXt0dXsx
477*80c94ecdSKeith M Wesolowski 	 * Logical Drive 2 in the HBA ->  Target ID 2 i.e. cXt2dXsX
478*80c94ecdSKeith M Wesolowski 	 * Logical Drive 3 in the HBA ->  Target ID 3 i.e. cXt3dXsX
479*80c94ecdSKeith M Wesolowski 	 */
480*80c94ecdSKeith M Wesolowski 
481*80c94ecdSKeith M Wesolowski 
482*80c94ecdSKeith M Wesolowski 	if (cpqary3p->legacy_mapping == 1) {
483*80c94ecdSKeith M Wesolowski 		for (cntr = 0; cntr < log_lun_no; cntr++) {
484*80c94ecdSKeith M Wesolowski 			i = ((cntr < CTLR_SCSI_ID) ?
485*80c94ecdSKeith M Wesolowski 			    cntr : cntr + CPQARY3_TGT_ALIGNMENT);
486*80c94ecdSKeith M Wesolowski 			if (!(cpqary3p->cpqary3_tgtp[i] = (cpqary3_tgt_t *)
487*80c94ecdSKeith M Wesolowski 			    MEM_ZALLOC(sizeof (cpqary3_tgt_t)))) {
488*80c94ecdSKeith M Wesolowski 				cmn_err(CE_WARN, "CPQary3 : Failed to Detect "
489*80c94ecdSKeith M Wesolowski 				    "targets, Memory Allocation Failure");
490*80c94ecdSKeith M Wesolowski 				cpqary3_synccmd_free(cpqary3p, cpqary3_cmdpvtp);
491*80c94ecdSKeith M Wesolowski 				return (CPQARY3_FAILURE);
492*80c94ecdSKeith M Wesolowski 			}
493*80c94ecdSKeith M Wesolowski 
494*80c94ecdSKeith M Wesolowski 			cpqary3p->cpqary3_tgtp[i]->logical_id =
495*80c94ecdSKeith M Wesolowski 			    rllp->ll_data[cntr].logical_id;
496*80c94ecdSKeith M Wesolowski 
497*80c94ecdSKeith M Wesolowski 			cpqary3p->cpqary3_tgtp[i]->type =
498*80c94ecdSKeith M Wesolowski 			    CPQARY3_TARGET_LOG_VOL;
499*80c94ecdSKeith M Wesolowski 
500*80c94ecdSKeith M Wesolowski 			DTRACE_PROBE2(lvlun_remapped,
501*80c94ecdSKeith M Wesolowski 			    cpqary3_tgt_t *, cpqary3p->cpqary3_tgtp[i],
502*80c94ecdSKeith M Wesolowski 			    rpl_data_t *, &rllp->ll_data[cntr]);
503*80c94ecdSKeith M Wesolowski 		}
504*80c94ecdSKeith M Wesolowski 	} else {
505*80c94ecdSKeith M Wesolowski 		/*
506*80c94ecdSKeith M Wesolowski 		 * Fix for QXCR1000446657: Logical drives are re numbered after
507*80c94ecdSKeith M Wesolowski 		 * deleting a Logical drive.
508*80c94ecdSKeith M Wesolowski 		 * We are using new indexing mechanism to fill the
509*80c94ecdSKeith M Wesolowski 		 * cpqary3_tgtp[],
510*80c94ecdSKeith M Wesolowski 		 * Check given during memory allocation of cpqary3_tgtp
511*80c94ecdSKeith M Wesolowski 		 * elements, so that memory is not re-allocated each time the
512*80c94ecdSKeith M Wesolowski 		 * cpqary3_probe4LVs() is called.
513*80c94ecdSKeith M Wesolowski 		 * Check given while freeing the memory of the cpqary3_tgtp[]
514*80c94ecdSKeith M Wesolowski 		 * elements, when a hole is found in the Logical Drives
515*80c94ecdSKeith M Wesolowski 		 * configured.
516*80c94ecdSKeith M Wesolowski 		 */
517*80c94ecdSKeith M Wesolowski 
518*80c94ecdSKeith M Wesolowski 		/* ensure that the loop will break for cntr = 32 in any case */
519*80c94ecdSKeith M Wesolowski 		for (cntr = 0; ((ld_count < log_lun_no) && (cntr < MAX_LOGDRV));
520*80c94ecdSKeith M Wesolowski 		    cntr++) {
521*80c94ecdSKeith M Wesolowski 			i = ((cntr < CTLR_SCSI_ID) ?
522*80c94ecdSKeith M Wesolowski 			    cntr : cntr + CPQARY3_TGT_ALIGNMENT);
523*80c94ecdSKeith M Wesolowski 			lun_id = (rllp->ll_data[ld_count].logical_id & 0xFFFF);
524*80c94ecdSKeith M Wesolowski 			if (cntr != lun_id) {
525*80c94ecdSKeith M Wesolowski 				if (cpqary3p->cpqary3_tgtp[i]) {
526*80c94ecdSKeith M Wesolowski 					MEM_SFREE(cpqary3p->cpqary3_tgtp[i],
527*80c94ecdSKeith M Wesolowski 					    sizeof (cpqary3_tgt_t));
528*80c94ecdSKeith M Wesolowski 					cpqary3p->cpqary3_tgtp[i] = NULL;
529*80c94ecdSKeith M Wesolowski 				}
530*80c94ecdSKeith M Wesolowski 			} else {
531*80c94ecdSKeith M Wesolowski 				if (cpqary3p->cpqary3_tgtp[i] == NULL &&
532*80c94ecdSKeith M Wesolowski 				    !(cpqary3p->cpqary3_tgtp[i] =
533*80c94ecdSKeith M Wesolowski 				    (cpqary3_tgt_t *)MEM_ZALLOC(
534*80c94ecdSKeith M Wesolowski 				    sizeof (cpqary3_tgt_t)))) {
535*80c94ecdSKeith M Wesolowski 					cmn_err(CE_WARN,
536*80c94ecdSKeith M Wesolowski 					    "CPQary3 : Failed to Detect "
537*80c94ecdSKeith M Wesolowski 					    "targets, Memory Allocation "
538*80c94ecdSKeith M Wesolowski 					    "Failure");
539*80c94ecdSKeith M Wesolowski 					/* Sync Changes */
540*80c94ecdSKeith M Wesolowski 					cpqary3_synccmd_free(cpqary3p,
541*80c94ecdSKeith M Wesolowski 					    cpqary3_cmdpvtp);
542*80c94ecdSKeith M Wesolowski 					/* Sync Changes */
543*80c94ecdSKeith M Wesolowski 					return (CPQARY3_FAILURE);
544*80c94ecdSKeith M Wesolowski 				}
545*80c94ecdSKeith M Wesolowski 				cpqary3p->cpqary3_tgtp[i]->logical_id =
546*80c94ecdSKeith M Wesolowski 				    rllp->ll_data[ld_count].logical_id;
547*80c94ecdSKeith M Wesolowski 				cpqary3p->cpqary3_tgtp[i]->type =
548*80c94ecdSKeith M Wesolowski 				    CPQARY3_TARGET_LOG_VOL;
549*80c94ecdSKeith M Wesolowski 
550*80c94ecdSKeith M Wesolowski 				/*
551*80c94ecdSKeith M Wesolowski 				 * Send "BMIC sense logical drive status
552*80c94ecdSKeith M Wesolowski 				 * command to set the target type to
553*80c94ecdSKeith M Wesolowski 				 * CPQARY3_TARGET_NONE in case of logical
554*80c94ecdSKeith M Wesolowski 				 * drive failure
555*80c94ecdSKeith M Wesolowski 				 */
556*80c94ecdSKeith M Wesolowski 
557*80c94ecdSKeith M Wesolowski 				ld_count++;
558*80c94ecdSKeith M Wesolowski 			}
559*80c94ecdSKeith M Wesolowski 		}
560*80c94ecdSKeith M Wesolowski 
561*80c94ecdSKeith M Wesolowski 	}
562*80c94ecdSKeith M Wesolowski 
563*80c94ecdSKeith M Wesolowski 	/* HPQacucli Changes */
564*80c94ecdSKeith M Wesolowski 	for (; cntr < MAX_LOGDRV; cntr++) {
565*80c94ecdSKeith M Wesolowski 		cpqary3_tgt_t *t;
566*80c94ecdSKeith M Wesolowski 		i = ((cntr < CTLR_SCSI_ID) ?
567*80c94ecdSKeith M Wesolowski 		    cntr : cntr + CPQARY3_TGT_ALIGNMENT);
568*80c94ecdSKeith M Wesolowski 		t = cpqary3p->cpqary3_tgtp[i];
569*80c94ecdSKeith M Wesolowski 		cpqary3p->cpqary3_tgtp[i] = NULL;
570*80c94ecdSKeith M Wesolowski 		if (t) {
571*80c94ecdSKeith M Wesolowski 			MEM_SFREE(t, sizeof (*t));
572*80c94ecdSKeith M Wesolowski 		}
573*80c94ecdSKeith M Wesolowski 	}
574*80c94ecdSKeith M Wesolowski 	/* HPQacucli Changes */
575*80c94ecdSKeith M Wesolowski 
576*80c94ecdSKeith M Wesolowski 	/* Sync Changes */
577*80c94ecdSKeith M Wesolowski 	cpqary3_synccmd_free(cpqary3p, cpqary3_cmdpvtp);
578*80c94ecdSKeith M Wesolowski 	/* Sync Changes */
579*80c94ecdSKeith M Wesolowski 
580*80c94ecdSKeith M Wesolowski 	return (CPQARY3_SUCCESS);
581*80c94ecdSKeith M Wesolowski }
582*80c94ecdSKeith M Wesolowski 
583*80c94ecdSKeith M Wesolowski /*
584*80c94ecdSKeith M Wesolowski  * Function	:  	cpqary3_probe4Tapes
585*80c94ecdSKeith M Wesolowski  * Description	:  	This routine probes for the logical drives
586*80c94ecdSKeith M Wesolowski  *			configured on the HP Smart Array controllers
587*80c94ecdSKeith M Wesolowski  * Called By	:  	cpqary3_probe4targets()
588*80c94ecdSKeith M Wesolowski  * Parameters	:  	per controller
589*80c94ecdSKeith M Wesolowski  * Calls	:  	cpqary3_synccmd_alloc(), cpqary3_synccmd_send()
590*80c94ecdSKeith M Wesolowski  *			cpqary3_synccmd_free()
591*80c94ecdSKeith M Wesolowski  * Return Values:  	None
592*80c94ecdSKeith M Wesolowski  */
593*80c94ecdSKeith M Wesolowski uint8_t
cpqary3_probe4Tapes(cpqary3_t * cpqary3p)594*80c94ecdSKeith M Wesolowski cpqary3_probe4Tapes(cpqary3_t *cpqary3p)
595*80c94ecdSKeith M Wesolowski {
596*80c94ecdSKeith M Wesolowski 	uint8_t			phy_lun_no;
597*80c94ecdSKeith M Wesolowski 	uint32_t		ii = 0;
598*80c94ecdSKeith M Wesolowski 	uint8_t			cntr = 0;
599*80c94ecdSKeith M Wesolowski 	uint32_t		data_addr_len;
600*80c94ecdSKeith M Wesolowski 	rpl_data_t		*rplp;
601*80c94ecdSKeith M Wesolowski 	CommandList_t		*cmdlistp;
602*80c94ecdSKeith M Wesolowski 	cpqary3_cmdpvt_t	*cpqary3_cmdpvtp;
603*80c94ecdSKeith M Wesolowski 
604*80c94ecdSKeith M Wesolowski 	/*
605*80c94ecdSKeith M Wesolowski 	 * Occupy the Command List
606*80c94ecdSKeith M Wesolowski 	 * Allocate Physically Contigous Memory
607*80c94ecdSKeith M Wesolowski 	 * Update the Command List for Report Logical LUNS (rll) Command
608*80c94ecdSKeith M Wesolowski 	 * This command detects all existing logical drives.
609*80c94ecdSKeith M Wesolowski 	 * Submit and Poll for completion
610*80c94ecdSKeith M Wesolowski 	 */
611*80c94ecdSKeith M Wesolowski 
612*80c94ecdSKeith M Wesolowski 	RETURN_FAILURE_IF_NULL(cpqary3p);
613*80c94ecdSKeith M Wesolowski 
614*80c94ecdSKeith M Wesolowski 	/* Sync Changes */
615*80c94ecdSKeith M Wesolowski 	cpqary3_cmdpvtp = cpqary3_synccmd_alloc(cpqary3p, sizeof (rpl_data_t));
616*80c94ecdSKeith M Wesolowski 	if (cpqary3_cmdpvtp == NULL)
617*80c94ecdSKeith M Wesolowski 		return (CPQARY3_FAILURE);
618*80c94ecdSKeith M Wesolowski 
619*80c94ecdSKeith M Wesolowski 	cmdlistp = cpqary3_cmdpvtp->cmdlist_memaddr;
620*80c94ecdSKeith M Wesolowski 	rplp = (rpl_data_t *)cpqary3_cmdpvtp->driverdata->sg;
621*80c94ecdSKeith M Wesolowski 
622*80c94ecdSKeith M Wesolowski 	/* Sync Changes */
623*80c94ecdSKeith M Wesolowski 
624*80c94ecdSKeith M Wesolowski 	cmdlistp->Header.SGList = 1;
625*80c94ecdSKeith M Wesolowski 	cmdlistp->Header.SGTotal = 1;
626*80c94ecdSKeith M Wesolowski 	cmdlistp->Header.Tag.drvinfo_n_err = CPQARY3_SYNCCMD_SUCCESS;
627*80c94ecdSKeith M Wesolowski 	cmdlistp->Header.LUN.PhysDev.TargetId = 0;
628*80c94ecdSKeith M Wesolowski 	cmdlistp->Header.LUN.PhysDev.Bus = 0;
629*80c94ecdSKeith M Wesolowski 	cmdlistp->Header.LUN.PhysDev.Mode = MASK_PERIPHERIAL_DEV_ADDR;
630*80c94ecdSKeith M Wesolowski 
631*80c94ecdSKeith M Wesolowski 	cmdlistp->Request.CDBLen = CPQARY3_CDBLEN_12;
632*80c94ecdSKeith M Wesolowski 	cmdlistp->Request.Timeout = CISS_NO_TIMEOUT;
633*80c94ecdSKeith M Wesolowski 	cmdlistp->Request.Type.Type = CISS_TYPE_CMD;
634*80c94ecdSKeith M Wesolowski 	cmdlistp->Request.Type.Attribute = CISS_ATTR_ORDERED;
635*80c94ecdSKeith M Wesolowski 	cmdlistp->Request.Type.Direction = CISS_XFER_READ;
636*80c94ecdSKeith M Wesolowski 	cmdlistp->Request.CDB[0] = CISS_OPCODE_RPL;
637*80c94ecdSKeith M Wesolowski 
638*80c94ecdSKeith M Wesolowski 	data_addr_len = sizeof (rpl_data_t);
639*80c94ecdSKeith M Wesolowski 
640*80c94ecdSKeith M Wesolowski 	cmdlistp->Request.CDB[6] = (data_addr_len >> 24) & 0xff;
641*80c94ecdSKeith M Wesolowski 	cmdlistp->Request.CDB[7] = (data_addr_len >> 16) & 0xff;
642*80c94ecdSKeith M Wesolowski 	cmdlistp->Request.CDB[8] = (data_addr_len >> 8) & 0xff;
643*80c94ecdSKeith M Wesolowski 	cmdlistp->Request.CDB[9] = (data_addr_len) & 0xff;
644*80c94ecdSKeith M Wesolowski 
645*80c94ecdSKeith M Wesolowski 	DTRACE_PROBE2(tape_probe_cmd_send,
646*80c94ecdSKeith M Wesolowski 	    CommandList_t *, cmdlistp, cpqary3_cmdpvt_t *, cpqary3_cmdpvtp);
647*80c94ecdSKeith M Wesolowski 
648*80c94ecdSKeith M Wesolowski 	/* PERF */
649*80c94ecdSKeith M Wesolowski 	cpqary3_cmdpvtp->complete = cpqary3_synccmd_complete;
650*80c94ecdSKeith M Wesolowski 	/* PERF */
651*80c94ecdSKeith M Wesolowski 
652*80c94ecdSKeith M Wesolowski 	/* Sync Changes */
653*80c94ecdSKeith M Wesolowski 
654*80c94ecdSKeith M Wesolowski 	if (cpqary3_synccmd_send(cpqary3p, cpqary3_cmdpvtp, 90000,
655*80c94ecdSKeith M Wesolowski 	    CPQARY3_SYNCCMD_SEND_WAITSIG) != 0) {
656*80c94ecdSKeith M Wesolowski 		cpqary3_synccmd_free(cpqary3p, cpqary3_cmdpvtp);
657*80c94ecdSKeith M Wesolowski 		return (CPQARY3_FAILURE);
658*80c94ecdSKeith M Wesolowski 	}
659*80c94ecdSKeith M Wesolowski 
660*80c94ecdSKeith M Wesolowski 	if ((cpqary3_cmdpvtp->cmdlist_memaddr->Header.Tag.drvinfo_n_err ==
661*80c94ecdSKeith M Wesolowski 	    CPQARY3_SYNCCMD_FAILURE) &&
662*80c94ecdSKeith M Wesolowski 	    (cpqary3_cmdpvtp->errorinfop->CommandStatus !=
663*80c94ecdSKeith M Wesolowski 	    CISS_CMD_DATA_UNDERRUN)) {
664*80c94ecdSKeith M Wesolowski 		cmn_err(CE_WARN, "CPQary3 : Probe for physical targets "
665*80c94ecdSKeith M Wesolowski 		    "returned ERROR !");
666*80c94ecdSKeith M Wesolowski 		DTRACE_PROBE1(tape_probe_cmdfail,
667*80c94ecdSKeith M Wesolowski 		    ErrorInfo_t *, cpqary3_cmdpvtp->errorinfop);
668*80c94ecdSKeith M Wesolowski 		cpqary3_synccmd_free(cpqary3p, cpqary3_cmdpvtp);
669*80c94ecdSKeith M Wesolowski 		return (CPQARY3_FAILURE);
670*80c94ecdSKeith M Wesolowski 	}
671*80c94ecdSKeith M Wesolowski 	/* Sync Changes */
672*80c94ecdSKeith M Wesolowski 
673*80c94ecdSKeith M Wesolowski 	phy_lun_no = ((rplp->lunlist_byte0 +
674*80c94ecdSKeith M Wesolowski 	    (rplp->lunlist_byte1 << 8) +
675*80c94ecdSKeith M Wesolowski 	    (rplp->lunlist_byte2 << 16) +
676*80c94ecdSKeith M Wesolowski 	    (rplp->lunlist_byte3 << 24)) / 8);
677*80c94ecdSKeith M Wesolowski 
678*80c94ecdSKeith M Wesolowski 	/*
679*80c94ecdSKeith M Wesolowski 	 *	Update per target structure with relevant information
680*80c94ecdSKeith M Wesolowski 	 * CPQARY3_TAPE_BASE is 33 because of the following mapping:
681*80c94ecdSKeith M Wesolowski 	 * Target IDs 0-6 	in the OS = Logical Drives 0 - 6 in the HBA
682*80c94ecdSKeith M Wesolowski 	 * Target ID  7 	in the OS = none in the HBA
683*80c94ecdSKeith M Wesolowski 	 * Target IDs 8-32 	in the OS = Logical Drives 7 - 31 in the HBA
684*80c94ecdSKeith M Wesolowski 	 * Target IDs 33 and above are reserved for Tapes and hence we need
685*80c94ecdSKeith M Wesolowski 	 * the alignment.
686*80c94ecdSKeith M Wesolowski 	 */
687*80c94ecdSKeith M Wesolowski 
688*80c94ecdSKeith M Wesolowski 
689*80c94ecdSKeith M Wesolowski 	/*
690*80c94ecdSKeith M Wesolowski 	 * HP Smart Array SAS controllers with Firmware revsion 5.14 or
691*80c94ecdSKeith M Wesolowski 	 * later support
692*80c94ecdSKeith M Wesolowski 	 * 64 Logical drives. So we are checking
693*80c94ecdSKeith M Wesolowski 	 * if the controller is SAS or CISS and then assigning the value of the
694*80c94ecdSKeith M Wesolowski 	 * TAPE BASE accordingly
695*80c94ecdSKeith M Wesolowski 	 */
696*80c94ecdSKeith M Wesolowski 
697*80c94ecdSKeith M Wesolowski 	if (cpqary3p->bddef->bd_flags & SA_BD_SAS) {
698*80c94ecdSKeith M Wesolowski 		ii = 0x41;	/* MAX_LOGDRV + 1 - 64 + 1 */
699*80c94ecdSKeith M Wesolowski 	} else {
700*80c94ecdSKeith M Wesolowski 		ii = 0x21;	/* MAX_LOGDRV + 1 - 32 + 1 */
701*80c94ecdSKeith M Wesolowski 	}
702*80c94ecdSKeith M Wesolowski 
703*80c94ecdSKeith M Wesolowski 	for (cntr = 0; cntr < phy_lun_no; cntr++) {
704*80c94ecdSKeith M Wesolowski 		if (rplp->pl_data[cntr].Mode == CISS_PHYS_MODE) {
705*80c94ecdSKeith M Wesolowski 			if (cpqary3p->cpqary3_tgtp[ii] == NULL &&
706*80c94ecdSKeith M Wesolowski 			    !(cpqary3p->cpqary3_tgtp[ii] =
707*80c94ecdSKeith M Wesolowski 			    (cpqary3_tgt_t *)
708*80c94ecdSKeith M Wesolowski 			    MEM_ZALLOC(sizeof (cpqary3_tgt_t)))) {
709*80c94ecdSKeith M Wesolowski 				cmn_err(CE_WARN, "CPQary3 : Failed to Detect "
710*80c94ecdSKeith M Wesolowski 				    "targets, Memory Allocation Failure");
711*80c94ecdSKeith M Wesolowski 				cpqary3_synccmd_free(cpqary3p,
712*80c94ecdSKeith M Wesolowski 				    cpqary3_cmdpvtp);
713*80c94ecdSKeith M Wesolowski 				return (CPQARY3_FAILURE);
714*80c94ecdSKeith M Wesolowski 			}
715*80c94ecdSKeith M Wesolowski 
716*80c94ecdSKeith M Wesolowski 			bcopy(&(rplp->pl_data[cntr]),
717*80c94ecdSKeith M Wesolowski 			    &(cpqary3p->cpqary3_tgtp[ii]->PhysID),
718*80c94ecdSKeith M Wesolowski 			    sizeof (PhysDevAddr_t));
719*80c94ecdSKeith M Wesolowski 
720*80c94ecdSKeith M Wesolowski 			cpqary3p->cpqary3_tgtp[ii]->type = CPQARY3_TARGET_TAPE;
721*80c94ecdSKeith M Wesolowski 
722*80c94ecdSKeith M Wesolowski 			DTRACE_PROBE1(tape_discovered,
723*80c94ecdSKeith M Wesolowski 			    cpqary3_tgt_t *, cpqary3p->cpqary3_tgtp[ii]);
724*80c94ecdSKeith M Wesolowski 
725*80c94ecdSKeith M Wesolowski 			ii++;
726*80c94ecdSKeith M Wesolowski 		}
727*80c94ecdSKeith M Wesolowski 	}
728*80c94ecdSKeith M Wesolowski 
729*80c94ecdSKeith M Wesolowski 	/* Sync Changes */
730*80c94ecdSKeith M Wesolowski 	cpqary3_synccmd_free(cpqary3p, cpqary3_cmdpvtp);
731*80c94ecdSKeith M Wesolowski 	/* Sync Changes */
732*80c94ecdSKeith M Wesolowski 
733*80c94ecdSKeith M Wesolowski 	return (CPQARY3_SUCCESS);
734*80c94ecdSKeith M Wesolowski 
735*80c94ecdSKeith M Wesolowski }
736*80c94ecdSKeith M Wesolowski 
737*80c94ecdSKeith M Wesolowski /*
738*80c94ecdSKeith M Wesolowski  * Function	:    cpqary3_synccmd_complete
739*80c94ecdSKeith M Wesolowski  * Description	:    This routine processes the completed commands
740*80c94ecdSKeith M Wesolowski  *			using the sync interface and
741*80c94ecdSKeith M Wesolowski  *			initiates any callback that is needed.
742*80c94ecdSKeith M Wesolowski  * Called By	:    cpqary3_transport
743*80c94ecdSKeith M Wesolowski  * Parameters	:    per-command
744*80c94ecdSKeith M Wesolowski  * Calls	:    cpqary3_cmdlist_release, cpqary3_synccmd_cleanup
745*80c94ecdSKeith M Wesolowski  * Return Values:    None
746*80c94ecdSKeith M Wesolowski  */
747*80c94ecdSKeith M Wesolowski void
cpqary3_synccmd_complete(cpqary3_cmdpvt_t * cpqary3_cmdpvtp)748*80c94ecdSKeith M Wesolowski cpqary3_synccmd_complete(cpqary3_cmdpvt_t *cpqary3_cmdpvtp)
749*80c94ecdSKeith M Wesolowski {
750*80c94ecdSKeith M Wesolowski 	cpqary3_t	*cpqary3p;
751*80c94ecdSKeith M Wesolowski 
752*80c94ecdSKeith M Wesolowski 	ASSERT(cpqary3_cmdpvtp != NULL);
753*80c94ecdSKeith M Wesolowski 
754*80c94ecdSKeith M Wesolowski 	if (CPQARY3_TIMEOUT == cpqary3_cmdpvtp->cmdpvt_flag) {
755*80c94ecdSKeith M Wesolowski 		cpqary3_cmdlist_release(cpqary3_cmdpvtp, CPQARY3_NO_MUTEX);
756*80c94ecdSKeith M Wesolowski 		return;
757*80c94ecdSKeith M Wesolowski 	}
758*80c94ecdSKeith M Wesolowski 
759*80c94ecdSKeith M Wesolowski 	cpqary3p = cpqary3_cmdpvtp->ctlr;
760*80c94ecdSKeith M Wesolowski 
761*80c94ecdSKeith M Wesolowski 	if (cpqary3_cmdpvtp->cmdpvt_flag == CPQARY3_SYNC_TIMEOUT) {
762*80c94ecdSKeith M Wesolowski 		/*
763*80c94ecdSKeith M Wesolowski 		 * The submitter has abandoned this command, so we
764*80c94ecdSKeith M Wesolowski 		 * have to free the resources here.
765*80c94ecdSKeith M Wesolowski 		 */
766*80c94ecdSKeith M Wesolowski 		mutex_exit(&(cpqary3p->sw_mutex));
767*80c94ecdSKeith M Wesolowski 		cpqary3_synccmd_cleanup(cpqary3_cmdpvtp);
768*80c94ecdSKeith M Wesolowski 		mutex_enter(&(cpqary3p->sw_mutex));
769*80c94ecdSKeith M Wesolowski 	} else {
770*80c94ecdSKeith M Wesolowski 		/* submitter is waiting; wake him up */
771*80c94ecdSKeith M Wesolowski 		cpqary3_cmdpvtp->cmdpvt_flag = 0;
772*80c94ecdSKeith M Wesolowski 
773*80c94ecdSKeith M Wesolowski 		/*
774*80c94ecdSKeith M Wesolowski 		 * Fix for Flush Cache Operation Timed out issue:
775*80c94ecdSKeith M Wesolowski 		 * cv_signal() wakes up only one blocked thread.
776*80c94ecdSKeith M Wesolowski 		 * We need to use cv_broadcast which unblocks
777*80c94ecdSKeith M Wesolowski 		 * all the blocked threads()
778*80c94ecdSKeith M Wesolowski 		 */
779*80c94ecdSKeith M Wesolowski 		cv_broadcast(&(cpqary3p->cv_ioctl_wait));
780*80c94ecdSKeith M Wesolowski 	}
781*80c94ecdSKeith M Wesolowski }
782