2 * This file and its contents are supplied under the terms of the
3 * Common Development and Distribution License ("CDDL"), version 1.0.
4 * You may only use this file in accordance with the terms of version
7 * A full copy of the text of the CDDL should have accompanied this
8 * source. A copy of the CDDL is also available via the Internet at
9 * http://www.illumos.org/license/CDDL.
13 * Copyright (C) 2013 Hewlett-Packard Development Company, L.P.
14 * Copyright (c) 2016 by Delphix. All rights reserved.
21 * Local Functions Definitions
24 uint8_t cpqary3_format_unit(cpqary3_cmdpvt_t
*);
26 static uint8_t cpqary3_probe4LVs(cpqary3_t
*);
27 static uint8_t cpqary3_probe4Tapes(cpqary3_t
*);
31 * Function : cpqary3_probe4targets
32 * Description : This routine detects all existing logical drives
33 * and updates per target structure.
34 * Called By : cpqary3_tgt_init()
35 * Parameters : per-controller
36 * Calls : cpqary3_probe4LVs(), cpqary3_probe4Tapes()
37 * Return Values: SUCCESS/ FAILURE
38 * [Shall fail only if Memory Constraints exist, the
39 * controller is defective/does not respond]
42 cpqary3_probe4targets(cpqary3_t
*cpqary3p
)
46 rv
= cpqary3_probe4LVs(cpqary3p
);
48 if (CPQARY3_FAILURE
== rv
) {
52 rv
= cpqary3_probe4Tapes(cpqary3p
);
54 if (CPQARY3_FAILURE
== rv
) {
58 return (CPQARY3_SUCCESS
);
63 * Function : cpqary3_build_cmdlist
64 * Description : This routine builds the command list for the specific
66 * Called By : cpqary3_transport()
67 * Parameters : cmdlist pvt struct, target id as received by SA.
69 * Return Values: SUCCESS : Build is successful
70 * FAILURE : Build has Failed
73 cpqary3_build_cmdlist(cpqary3_cmdpvt_t
*cpqary3_cmdpvtp
, uint32_t tid
)
79 CommandList_t
*cmdlistp
;
81 RETURN_FAILURE_IF_NULL(cpqary3_cmdpvtp
);
83 if (NULL
== (cpqary3p
= cpqary3_cmdpvtp
->ctlr
))
84 return (CPQARY3_FAILURE
);
86 bfp
= (struct buf
*)cpqary3_cmdpvtp
->pvt_pkt
->bf
;
88 tgtp
= cpqary3p
->cpqary3_tgtp
[tid
];
91 return (CPQARY3_FAILURE
);
94 cmdlistp
= cpqary3_cmdpvtp
->cmdlist_memaddr
;
96 /* Update Cmd Header */
97 cmdlistp
->Header
.SGList
= cpqary3_cmdpvtp
->pvt_pkt
->cmd_cookiecnt
;
98 cmdlistp
->Header
.SGTotal
= cpqary3_cmdpvtp
->pvt_pkt
->cmd_cookiecnt
;
99 cmdlistp
->Header
.Tag
.drvinfo_n_err
= CPQARY3_OSCMD_SUCCESS
;
101 if (tgtp
->type
== CPQARY3_TARGET_CTLR
) {
102 cmdlistp
->Header
.LUN
.PhysDev
.TargetId
= 0;
103 cmdlistp
->Header
.LUN
.PhysDev
.Bus
= 0;
104 cmdlistp
->Header
.LUN
.PhysDev
.Mode
= MASK_PERIPHERIAL_DEV_ADDR
;
105 } else if (tgtp
->type
== CPQARY3_TARGET_LOG_VOL
) {
106 cmdlistp
->Header
.LUN
.LogDev
.VolId
= tgtp
->logical_id
;
107 cmdlistp
->Header
.LUN
.LogDev
.Mode
= LOGICAL_VOL_ADDR
;
108 } else if (tgtp
->type
== CPQARY3_TARGET_TAPE
) {
109 bcopy(&(tgtp
->PhysID
), &(cmdlistp
->Header
.LUN
.PhysDev
),
110 sizeof (PhysDevAddr_t
));
112 DTRACE_PROBE1(build_cmdlist_tape
, CommandList_t
*, cmdlistp
);
116 cmdlistp
->Request
.CDBLen
= cpqary3_cmdpvtp
->pvt_pkt
->cdb_len
;
118 bcopy((caddr_t
)cpqary3_cmdpvtp
->pvt_pkt
->scsi_cmd_pkt
->pkt_cdbp
,
119 (caddr_t
)cmdlistp
->Request
.CDB
, cpqary3_cmdpvtp
->pvt_pkt
->cdb_len
);
122 cmdlistp
->Request
.Type
.Type
= CISS_TYPE_CMD
;
123 cmdlistp
->Request
.Type
.Attribute
= CISS_ATTR_ORDERED
;
125 DTRACE_PROBE2(build_cmdlist_buf
, struct buf
*, bfp
,
126 CommandList_t
*, cmdlistp
);
128 if (bfp
&& (bfp
->b_flags
& B_READ
))
129 cmdlistp
->Request
.Type
.Direction
= CISS_XFER_READ
;
130 else if (bfp
&& (bfp
->b_flags
& B_WRITE
))
131 cmdlistp
->Request
.Type
.Direction
= CISS_XFER_WRITE
;
133 cmdlistp
->Request
.Type
.Direction
= CISS_XFER_NONE
;
135 * Looks like the above Direction is going for a toss in case of
136 * MSA20(perticularly for 0x0a-write) connected to SMART Array.
137 * If the above check fails, the below switch should take care.
140 switch (cmdlistp
->Request
.CDB
[0]) {
143 cmdlistp
->Request
.Type
.Direction
= CISS_XFER_READ
;
147 cmdlistp
->Request
.Type
.Direction
= CISS_XFER_WRITE
;
151 * NEED to increase this TimeOut value when the concerned
152 * targets are tape devices(i.e., we need to do it here manually).
154 cmdlistp
->Request
.Timeout
= 2 *
155 (cpqary3_cmdpvtp
->pvt_pkt
->scsi_cmd_pkt
->pkt_time
);
157 for (cntr
= 0; cntr
< cpqary3_cmdpvtp
->pvt_pkt
->cmd_cookiecnt
; cntr
++) {
158 cmdlistp
->SG
[cntr
].Addr
=
159 cpqary3_cmdpvtp
->pvt_pkt
->
160 cmd_dmacookies
[cntr
].dmac_laddress
;
161 cmdlistp
->SG
[cntr
].Len
= (uint32_t)
162 cpqary3_cmdpvtp
->pvt_pkt
->cmd_dmacookies
[cntr
].dmac_size
;
165 return (CPQARY3_SUCCESS
);
170 * Function : cpqary3_send_abortcmd
171 * Description : Sends the Abort command to abort
172 * a set of cmds(on a target) or a cmdlist.
173 * Called By : cpqary3_abort
174 * Parameters : per controller, target_id, cmdlist to abort
175 * Calls : cpqary3_synccmd_alloc(), cpqary3_synccmd_send(),
176 * cpqary3_synccmd_free()
177 * Return Values: SUCCESS - abort cmd submit is successful.
178 * FAILURE - Could not submit the abort cmd.
181 cpqary3_send_abortcmd(cpqary3_t
*cpqary3p
, uint16_t target_id
,
182 CommandList_t
*cmdlist2abortp
)
184 CommandList_t
*cmdlistp
;
185 cpqary3_tgt_t
*cpqtgtp
;
186 cpqary3_tag_t
*cpqary3_tagp
;
187 cpqary3_cmdpvt_t
*cpqary3_cmdpvtp
;
190 * NOTE : DO NOT perform this operation for cmdlist2abortp.
193 RETURN_FAILURE_IF_NULL(cpqary3p
);
195 if (target_id
== CTLR_SCSI_ID
)
196 return (CPQARY3_FAILURE
);
198 cpqtgtp
= cpqary3p
->cpqary3_tgtp
[target_id
];
201 return (CPQARY3_FAILURE
);
205 * Occupy the Command List
206 * Update the Command List accordingly
207 * Submit the command and wait for a signal
210 /* BGB: CVFIX -> Introduced the call to cpqary3_synccmd_alloc */
211 cpqary3_cmdpvtp
= cpqary3_synccmd_alloc(cpqary3p
, 0);
212 if (cpqary3_cmdpvtp
== NULL
)
213 return (CPQARY3_FAILURE
);
215 cmdlistp
= cpqary3_cmdpvtp
->cmdlist_memaddr
;
217 cmdlistp
->Header
.SGList
= 0;
218 cmdlistp
->Header
.SGTotal
= 0;
219 cmdlistp
->Header
.Tag
.drvinfo_n_err
= CPQARY3_SYNCCMD_SUCCESS
;
220 cmdlistp
->Header
.LUN
.PhysDev
.TargetId
= 0;
221 cmdlistp
->Header
.LUN
.PhysDev
.Bus
= 0;
222 cmdlistp
->Header
.LUN
.PhysDev
.Mode
= PERIPHERIAL_DEV_ADDR
;
224 cmdlistp
->Request
.Type
.Type
= CISS_TYPE_MSG
;
225 cmdlistp
->Request
.Type
.Attribute
= CISS_ATTR_HEADOFQUEUE
;
226 cmdlistp
->Request
.Type
.Direction
= CISS_XFER_NONE
;
227 cmdlistp
->Request
.Timeout
= CISS_NO_TIMEOUT
;
228 cmdlistp
->Request
.CDBLen
= CPQARY3_CDBLEN_16
;
229 cmdlistp
->Request
.CDB
[0] = CISS_MSG_ABORT
;
231 if (cmdlist2abortp
) { /* Abort this Particular Task */
232 cmdlistp
->Request
.CDB
[1] = CISS_ABORT_TASK
;
233 cpqary3_tagp
= (cpqary3_tag_t
*)&cmdlistp
->Request
.CDB
[4];
234 cpqary3_tagp
->drvinfo_n_err
=
235 cmdlist2abortp
->Header
.Tag
.drvinfo_n_err
;
236 cpqary3_tagp
->tag_value
= cmdlist2abortp
->Header
.Tag
.tag_value
;
237 } else { /* Abort all tasks for this Target */
238 cmdlistp
->Request
.CDB
[1] = CISS_ABORT_TASKSET
;
240 switch (cpqtgtp
->type
) {
241 case CPQARY3_TARGET_LOG_VOL
:
242 cmdlistp
->Header
.LUN
.LogDev
.Mode
= LOGICAL_VOL_ADDR
;
243 cmdlistp
->Header
.LUN
.LogDev
.VolId
= cpqtgtp
->logical_id
;
245 case CPQARY3_TARGET_TAPE
:
246 bcopy(&(cpqtgtp
->PhysID
),
247 &(cmdlistp
->Header
.LUN
.PhysDev
),
248 sizeof (PhysDevAddr_t
));
254 cpqary3_cmdpvtp
->complete
= cpqary3_synccmd_complete
;
258 /* BGB: CVFIX -> Introduced a call to cpqary3_synccmd_send */
259 if (cpqary3_synccmd_send(cpqary3p
, cpqary3_cmdpvtp
, 30000,
260 CPQARY3_SYNCCMD_SEND_WAITSIG
) != 0) {
261 cpqary3_synccmd_free(cpqary3p
, cpqary3_cmdpvtp
);
262 return (CPQARY3_FAILURE
);
265 if (cpqary3_cmdpvtp
->cmdlist_memaddr
->Header
.Tag
.drvinfo_n_err
==
266 CPQARY3_SYNCCMD_FAILURE
) {
267 cpqary3_synccmd_free(cpqary3p
, cpqary3_cmdpvtp
);
268 return (CPQARY3_FAILURE
);
271 cpqary3_synccmd_free(cpqary3p
, cpqary3_cmdpvtp
);
273 return (CPQARY3_SUCCESS
);
279 * Function : cpqary3_fulsh_cache
280 * Description : This routine flushes the controller cache.
281 * Called By : cpqary3_detach(), cpqary3_additional_cmd()
282 * Parameters : per controller
283 * Calls : cpqary3_synccmd_alloc(), cpqary3_synccmd_send()
284 * cpqary3_synccmd_free()
285 * Return Values: None
288 cpqary3_flush_cache(cpqary3_t
*cpqary3p
)
290 CommandList_t
*cmdlistp
;
291 cpqary3_cmdpvt_t
*cpqary3_cmdpvtp
;
294 * Occupy the Command List
295 * Allocate Physically Contigous Memory for the FLUSH CACHE buffer
296 * Update the Command List accordingly
297 * Submit the command and wait for a signal
300 ASSERT(cpqary3p
!= NULL
);
302 /* grab a command and allocate a dma buffer */
303 cpqary3_cmdpvtp
= cpqary3_synccmd_alloc(cpqary3p
,
304 sizeof (flushcache_buf_t
));
305 if (cpqary3_cmdpvtp
== NULL
)
308 cmdlistp
= cpqary3_cmdpvtp
->cmdlist_memaddr
;
309 cmdlistp
->Header
.SGList
= 1;
310 cmdlistp
->Header
.SGTotal
= 1;
311 cmdlistp
->Header
.Tag
.drvinfo_n_err
= CPQARY3_SYNCCMD_SUCCESS
;
312 cmdlistp
->Header
.LUN
.PhysDev
.TargetId
= 0;
313 cmdlistp
->Header
.LUN
.PhysDev
.Bus
= 0;
314 cmdlistp
->Header
.LUN
.PhysDev
.Mode
= PERIPHERIAL_DEV_ADDR
;
316 cmdlistp
->Request
.CDBLen
= CPQARY3_CDBLEN_16
;
317 cmdlistp
->Request
.Type
.Type
= CISS_TYPE_CMD
;
318 cmdlistp
->Request
.Type
.Attribute
= CISS_ATTR_HEADOFQUEUE
;
319 cmdlistp
->Request
.Type
.Direction
= CISS_XFER_WRITE
;
320 cmdlistp
->Request
.Timeout
= CISS_NO_TIMEOUT
;
321 cmdlistp
->Request
.CDB
[0] = ARRAY_WRITE
;
322 cmdlistp
->Request
.CDB
[6] = CISS_FLUSH_CACHE
; /* 0xC2 */
323 cmdlistp
->Request
.CDB
[8] = 0x02;
327 cpqary3_cmdpvtp
->complete
= cpqary3_synccmd_complete
;
331 if (cpqary3_synccmd_send(cpqary3p
, cpqary3_cmdpvtp
, 90000,
332 CPQARY3_SYNCCMD_SEND_WAITSIG
) != 0) {
333 cpqary3_synccmd_free(cpqary3p
, cpqary3_cmdpvtp
);
334 cmn_err(CE_WARN
, "CPQary3 %s : Flush Cache Operation"
335 "Failed, Timeout", cpqary3p
->hba_name
);
339 cpqary3_synccmd_free(cpqary3p
, cpqary3_cmdpvtp
);
343 * Function : cpqary3_probe4LVs
344 * Description : This routine probes for the logical drives
345 * configured on the HP Smart Array controllers
346 * Called By : cpqary3_probe4targets()
347 * Parameters : per controller
348 * Calls : cpqary3_synccmd_alloc(), cpqary3_synccmd_send()
349 * cpqary3_synccmd_free()
350 * Return Values: None
353 cpqary3_probe4LVs(cpqary3_t
*cpqary3p
)
355 ulong_t log_lun_no
= 0;
357 ulong_t ld_count
= 0;
360 uint32_t data_addr_len
;
362 CommandList_t
*cmdlistp
;
363 cpqary3_cmdpvt_t
*cpqary3_cmdpvtp
;
366 * Occupy the Command List
367 * Allocate Physically Contigous Memory
368 * Update the Command List for Report Logical LUNS (rll) Command
369 * This command detects all existing logical drives.
370 * Submit and Poll for completion
373 RETURN_FAILURE_IF_NULL(cpqary3p
);
376 cpqary3_cmdpvtp
= cpqary3_synccmd_alloc(cpqary3p
, sizeof (rll_data_t
));
377 if (cpqary3_cmdpvtp
== NULL
)
378 return (CPQARY3_FAILURE
);
380 cmdlistp
= cpqary3_cmdpvtp
->cmdlist_memaddr
;
381 rllp
= (rll_data_t
*)cpqary3_cmdpvtp
->driverdata
->sg
;
383 cmdlistp
->Header
.SGList
= 1;
384 cmdlistp
->Header
.SGTotal
= 1;
385 cmdlistp
->Header
.Tag
.drvinfo_n_err
= CPQARY3_SYNCCMD_SUCCESS
;
386 cmdlistp
->Header
.LUN
.PhysDev
.Mode
= MASK_PERIPHERIAL_DEV_ADDR
;
388 cmdlistp
->Request
.CDBLen
= CPQARY3_CDBLEN_12
;
389 cmdlistp
->Request
.Timeout
= CISS_NO_TIMEOUT
;
390 cmdlistp
->Request
.Type
.Type
= CISS_TYPE_CMD
;
391 cmdlistp
->Request
.Type
.Attribute
= CISS_ATTR_ORDERED
;
392 cmdlistp
->Request
.Type
.Direction
= CISS_XFER_READ
;
393 cmdlistp
->Request
.CDB
[0] = CISS_OPCODE_RLL
;
395 data_addr_len
= sizeof (rll_data_t
);
397 cmdlistp
->Request
.CDB
[6] = (data_addr_len
>> 24) & 0xff;
398 cmdlistp
->Request
.CDB
[7] = (data_addr_len
>> 16) & 0xff;
399 cmdlistp
->Request
.CDB
[8] = (data_addr_len
>> 8) & 0xff;
400 cmdlistp
->Request
.CDB
[9] = (data_addr_len
) & 0xff;
402 DTRACE_PROBE2(rll_cmd_send
, CommandList_t
*, cmdlistp
,
403 cpqary3_cmdpvt_t
*, cpqary3_cmdpvtp
);
406 cpqary3_cmdpvtp
->complete
= cpqary3_synccmd_complete
;
409 if (cpqary3_synccmd_send(cpqary3p
, cpqary3_cmdpvtp
, 90000,
410 CPQARY3_SYNCCMD_SEND_WAITSIG
) != 0) {
411 cpqary3_synccmd_free(cpqary3p
, cpqary3_cmdpvtp
);
412 return (CPQARY3_FAILURE
);
415 if ((cpqary3_cmdpvtp
->cmdlist_memaddr
->Header
.Tag
.drvinfo_n_err
==
416 CPQARY3_SYNCCMD_FAILURE
) &&
417 (cpqary3_cmdpvtp
->errorinfop
->CommandStatus
!=
418 CISS_CMD_DATA_UNDERRUN
)) {
419 cmn_err(CE_WARN
, "CPQary3 : Probe for logical targets "
421 DTRACE_PROBE1(rll_cmd_fail
,
422 ErrorInfo_t
*, cpqary3_cmdpvtp
->errorinfop
);
423 cpqary3_synccmd_free(cpqary3p
, cpqary3_cmdpvtp
);
424 return (CPQARY3_FAILURE
);
428 log_lun_no
= ((rllp
->lunlist_byte0
+ (rllp
->lunlist_byte1
<< 8) +
429 (rllp
->lunlist_byte2
<< 16) + (rllp
->lunlist_byte3
<< 24)) / 8);
431 DTRACE_PROBE2(rll_cmd_result
, rll_data_t
*, rllp
, ulong_t
, log_lun_no
);
434 * The following is to restrict the maximum number of supported logical
435 * volumes to 32. This is very important as controller support upto 128
436 * logical volumes and this driver implementation supports only 32.
439 if (log_lun_no
> MAX_LOGDRV
) {
440 log_lun_no
= MAX_LOGDRV
;
443 cpqary3p
->num_of_targets
= log_lun_no
;
444 DTRACE_PROBE1(update_lvlun_count
, ulong_t
, log_lun_no
);
447 * Update per target structure with relevant information
448 * CPQARY#_TGT_ALLIGNMENT is 1 because of the following mapping:
449 * Target IDs 0-6 in the OS = Logical Drives 0 - 6 in the HBA
450 * Target ID 7 in the OS = none in the HBA
451 * Target IDs 8-32 in the OS = Logical Drives 7 - 31 in the HBA
452 * Everytime we reference a logical drive with ID > 6, we shall use
458 * Depending upon the value of the variable legacy_mapping set in
460 * the target mapping algorithm to be used by the driver is decided.
462 * If the value of legacy_mapping is set to one, in the case of
463 * Logical Drives with holes,
464 * Targets will be renumbered by the driver as shown below
465 * Below example makes the mapping logic clear.
467 * Logical Drive 0 in the HBA -> Target ID 0 i.e., cXt0dXsx
468 * Logical Drive 2 in the HBA -> Target ID 1 i.e., cXt1dXsX
469 * Logical Drive 3 in the HBA -> Target ID 2 i.e., cXt2dXsX
471 * If the value of legacy_mapping is not one, then the Logical
473 * not be renumbered in the case of holes, and the mapping
474 * will be done as shown below
475 * This will be the default mapping from 1.80 cpqary3 driver.
477 * Logical Drive 0 in the HBA -> Target ID 0 i.e. cXt0dXsx
478 * Logical Drive 2 in the HBA -> Target ID 2 i.e. cXt2dXsX
479 * Logical Drive 3 in the HBA -> Target ID 3 i.e. cXt3dXsX
483 if (cpqary3p
->legacy_mapping
== 1) {
484 for (cntr
= 0; cntr
< log_lun_no
; cntr
++) {
485 i
= ((cntr
< CTLR_SCSI_ID
) ?
486 cntr
: cntr
+ CPQARY3_TGT_ALIGNMENT
);
487 if (!(cpqary3p
->cpqary3_tgtp
[i
] = (cpqary3_tgt_t
*)
488 MEM_ZALLOC(sizeof (cpqary3_tgt_t
)))) {
489 cmn_err(CE_WARN
, "CPQary3 : Failed to Detect "
490 "targets, Memory Allocation Failure");
491 cpqary3_synccmd_free(cpqary3p
, cpqary3_cmdpvtp
);
492 return (CPQARY3_FAILURE
);
495 cpqary3p
->cpqary3_tgtp
[i
]->logical_id
=
496 rllp
->ll_data
[cntr
].logical_id
;
498 cpqary3p
->cpqary3_tgtp
[i
]->type
=
499 CPQARY3_TARGET_LOG_VOL
;
501 DTRACE_PROBE2(lvlun_remapped
,
502 cpqary3_tgt_t
*, cpqary3p
->cpqary3_tgtp
[i
],
503 rpl_data_t
*, &rllp
->ll_data
[cntr
]);
507 * Fix for QXCR1000446657: Logical drives are re numbered after
508 * deleting a Logical drive.
509 * We are using new indexing mechanism to fill the
511 * Check given during memory allocation of cpqary3_tgtp
512 * elements, so that memory is not re-allocated each time the
513 * cpqary3_probe4LVs() is called.
514 * Check given while freeing the memory of the cpqary3_tgtp[]
515 * elements, when a hole is found in the Logical Drives
519 /* ensure that the loop will break for cntr = 32 in any case */
520 for (cntr
= 0; ((ld_count
< log_lun_no
) && (cntr
< MAX_LOGDRV
));
522 i
= ((cntr
< CTLR_SCSI_ID
) ?
523 cntr
: cntr
+ CPQARY3_TGT_ALIGNMENT
);
524 lun_id
= (rllp
->ll_data
[ld_count
].logical_id
& 0xFFFF);
525 if (cntr
!= lun_id
) {
526 if (cpqary3p
->cpqary3_tgtp
[i
]) {
527 MEM_SFREE(cpqary3p
->cpqary3_tgtp
[i
],
528 sizeof (cpqary3_tgt_t
));
529 cpqary3p
->cpqary3_tgtp
[i
] = NULL
;
532 if (cpqary3p
->cpqary3_tgtp
[i
] == NULL
&&
533 !(cpqary3p
->cpqary3_tgtp
[i
] =
534 (cpqary3_tgt_t
*)MEM_ZALLOC(
535 sizeof (cpqary3_tgt_t
)))) {
537 "CPQary3 : Failed to Detect "
538 "targets, Memory Allocation "
541 cpqary3_synccmd_free(cpqary3p
,
544 return (CPQARY3_FAILURE
);
546 cpqary3p
->cpqary3_tgtp
[i
]->logical_id
=
547 rllp
->ll_data
[ld_count
].logical_id
;
548 cpqary3p
->cpqary3_tgtp
[i
]->type
=
549 CPQARY3_TARGET_LOG_VOL
;
552 * Send "BMIC sense logical drive status
553 * command to set the target type to
554 * CPQARY3_TARGET_NONE in case of logical
564 /* HPQacucli Changes */
565 for (; cntr
< MAX_LOGDRV
; cntr
++) {
567 i
= ((cntr
< CTLR_SCSI_ID
) ?
568 cntr
: cntr
+ CPQARY3_TGT_ALIGNMENT
);
569 t
= cpqary3p
->cpqary3_tgtp
[i
];
570 cpqary3p
->cpqary3_tgtp
[i
] = NULL
;
572 MEM_SFREE(t
, sizeof (*t
));
575 /* HPQacucli Changes */
578 cpqary3_synccmd_free(cpqary3p
, cpqary3_cmdpvtp
);
581 return (CPQARY3_SUCCESS
);
585 * Function : cpqary3_probe4Tapes
586 * Description : This routine probes for the logical drives
587 * configured on the HP Smart Array controllers
588 * Called By : cpqary3_probe4targets()
589 * Parameters : per controller
590 * Calls : cpqary3_synccmd_alloc(), cpqary3_synccmd_send()
591 * cpqary3_synccmd_free()
592 * Return Values: None
595 cpqary3_probe4Tapes(cpqary3_t
*cpqary3p
)
600 uint32_t data_addr_len
;
602 CommandList_t
*cmdlistp
;
603 cpqary3_cmdpvt_t
*cpqary3_cmdpvtp
;
606 * Occupy the Command List
607 * Allocate Physically Contigous Memory
608 * Update the Command List for Report Logical LUNS (rll) Command
609 * This command detects all existing logical drives.
610 * Submit and Poll for completion
613 RETURN_FAILURE_IF_NULL(cpqary3p
);
616 cpqary3_cmdpvtp
= cpqary3_synccmd_alloc(cpqary3p
, sizeof (rpl_data_t
));
617 if (cpqary3_cmdpvtp
== NULL
)
618 return (CPQARY3_FAILURE
);
620 cmdlistp
= cpqary3_cmdpvtp
->cmdlist_memaddr
;
621 rplp
= (rpl_data_t
*)cpqary3_cmdpvtp
->driverdata
->sg
;
625 cmdlistp
->Header
.SGList
= 1;
626 cmdlistp
->Header
.SGTotal
= 1;
627 cmdlistp
->Header
.Tag
.drvinfo_n_err
= CPQARY3_SYNCCMD_SUCCESS
;
628 cmdlistp
->Header
.LUN
.PhysDev
.TargetId
= 0;
629 cmdlistp
->Header
.LUN
.PhysDev
.Bus
= 0;
630 cmdlistp
->Header
.LUN
.PhysDev
.Mode
= MASK_PERIPHERIAL_DEV_ADDR
;
632 cmdlistp
->Request
.CDBLen
= CPQARY3_CDBLEN_12
;
633 cmdlistp
->Request
.Timeout
= CISS_NO_TIMEOUT
;
634 cmdlistp
->Request
.Type
.Type
= CISS_TYPE_CMD
;
635 cmdlistp
->Request
.Type
.Attribute
= CISS_ATTR_ORDERED
;
636 cmdlistp
->Request
.Type
.Direction
= CISS_XFER_READ
;
637 cmdlistp
->Request
.CDB
[0] = CISS_OPCODE_RPL
;
639 data_addr_len
= sizeof (rpl_data_t
);
641 cmdlistp
->Request
.CDB
[6] = (data_addr_len
>> 24) & 0xff;
642 cmdlistp
->Request
.CDB
[7] = (data_addr_len
>> 16) & 0xff;
643 cmdlistp
->Request
.CDB
[8] = (data_addr_len
>> 8) & 0xff;
644 cmdlistp
->Request
.CDB
[9] = (data_addr_len
) & 0xff;
646 DTRACE_PROBE2(tape_probe_cmd_send
,
647 CommandList_t
*, cmdlistp
, cpqary3_cmdpvt_t
*, cpqary3_cmdpvtp
);
650 cpqary3_cmdpvtp
->complete
= cpqary3_synccmd_complete
;
655 if (cpqary3_synccmd_send(cpqary3p
, cpqary3_cmdpvtp
, 90000,
656 CPQARY3_SYNCCMD_SEND_WAITSIG
) != 0) {
657 cpqary3_synccmd_free(cpqary3p
, cpqary3_cmdpvtp
);
658 return (CPQARY3_FAILURE
);
661 if ((cpqary3_cmdpvtp
->cmdlist_memaddr
->Header
.Tag
.drvinfo_n_err
==
662 CPQARY3_SYNCCMD_FAILURE
) &&
663 (cpqary3_cmdpvtp
->errorinfop
->CommandStatus
!=
664 CISS_CMD_DATA_UNDERRUN
)) {
665 cmn_err(CE_WARN
, "CPQary3 : Probe for physical targets "
667 DTRACE_PROBE1(tape_probe_cmdfail
,
668 ErrorInfo_t
*, cpqary3_cmdpvtp
->errorinfop
);
669 cpqary3_synccmd_free(cpqary3p
, cpqary3_cmdpvtp
);
670 return (CPQARY3_FAILURE
);
674 phy_lun_no
= ((rplp
->lunlist_byte0
+
675 (rplp
->lunlist_byte1
<< 8) +
676 (rplp
->lunlist_byte2
<< 16) +
677 (rplp
->lunlist_byte3
<< 24)) / 8);
680 * Update per target structure with relevant information
681 * CPQARY3_TAPE_BASE is 33 because of the following mapping:
682 * Target IDs 0-6 in the OS = Logical Drives 0 - 6 in the HBA
683 * Target ID 7 in the OS = none in the HBA
684 * Target IDs 8-32 in the OS = Logical Drives 7 - 31 in the HBA
685 * Target IDs 33 and above are reserved for Tapes and hence we need
691 * HP Smart Array SAS controllers with Firmware revsion 5.14 or
693 * 64 Logical drives. So we are checking
694 * if the controller is SAS or CISS and then assigning the value of the
695 * TAPE BASE accordingly
698 if (cpqary3p
->bddef
->bd_flags
& SA_BD_SAS
) {
699 ii
= 0x41; /* MAX_LOGDRV + 1 - 64 + 1 */
701 ii
= 0x21; /* MAX_LOGDRV + 1 - 32 + 1 */
704 for (cntr
= 0; cntr
< phy_lun_no
; cntr
++) {
705 if (rplp
->pl_data
[cntr
].Mode
== CISS_PHYS_MODE
) {
706 if (cpqary3p
->cpqary3_tgtp
[ii
] == NULL
&&
707 !(cpqary3p
->cpqary3_tgtp
[ii
] =
709 MEM_ZALLOC(sizeof (cpqary3_tgt_t
)))) {
710 cmn_err(CE_WARN
, "CPQary3 : Failed to Detect "
711 "targets, Memory Allocation Failure");
712 cpqary3_synccmd_free(cpqary3p
,
714 return (CPQARY3_FAILURE
);
717 bcopy(&(rplp
->pl_data
[cntr
]),
718 &(cpqary3p
->cpqary3_tgtp
[ii
]->PhysID
),
719 sizeof (PhysDevAddr_t
));
721 cpqary3p
->cpqary3_tgtp
[ii
]->type
= CPQARY3_TARGET_TAPE
;
723 DTRACE_PROBE1(tape_discovered
,
724 cpqary3_tgt_t
*, cpqary3p
->cpqary3_tgtp
[ii
]);
731 cpqary3_synccmd_free(cpqary3p
, cpqary3_cmdpvtp
);
734 return (CPQARY3_SUCCESS
);
739 * Function : cpqary3_synccmd_complete
740 * Description : This routine processes the completed commands
741 * using the sync interface and
742 * initiates any callback that is needed.
743 * Called By : cpqary3_transport
744 * Parameters : per-command
745 * Calls : cpqary3_cmdlist_release, cpqary3_synccmd_cleanup
746 * Return Values: None
749 cpqary3_synccmd_complete(cpqary3_cmdpvt_t
*cpqary3_cmdpvtp
)
753 ASSERT(cpqary3_cmdpvtp
!= NULL
);
755 if (CPQARY3_TIMEOUT
== cpqary3_cmdpvtp
->cmdpvt_flag
) {
756 cpqary3_cmdlist_release(cpqary3_cmdpvtp
, CPQARY3_NO_MUTEX
);
760 cpqary3p
= cpqary3_cmdpvtp
->ctlr
;
762 if (cpqary3_cmdpvtp
->cmdpvt_flag
== CPQARY3_SYNC_TIMEOUT
) {
764 * The submitter has abandoned this command, so we
765 * have to free the resources here.
767 mutex_exit(&(cpqary3p
->sw_mutex
));
768 cpqary3_synccmd_cleanup(cpqary3_cmdpvtp
);
769 mutex_enter(&(cpqary3p
->sw_mutex
));
771 /* submitter is waiting; wake it up */
772 cpqary3_cmdpvtp
->cmdpvt_flag
= 0;
775 * Fix for Flush Cache Operation Timed out issue:
776 * cv_signal() wakes up only one blocked thread.
777 * We need to use cv_broadcast which unblocks
778 * all the blocked threads()
780 cv_broadcast(&(cpqary3p
->cv_ioctl_wait
));