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.
20 * Local Functions Definitions
23 static int cpqary3_tgt_init(dev_info_t
*, dev_info_t
*, scsi_hba_tran_t
*,
24 struct scsi_device
*);
25 static int cpqary3_tgt_probe(struct scsi_device
*, int (*)());
26 static int cpqary3_transport(struct scsi_address
*, struct scsi_pkt
*);
27 static int cpqary3_reset(struct scsi_address
*, int);
28 static int cpqary3_abort(struct scsi_address
*, struct scsi_pkt
*);
29 static int cpqary3_getcap(struct scsi_address
*, char *, int);
30 static int cpqary3_setcap(struct scsi_address
*, char *, int, int);
31 static int cpqary3_dma_alloc(cpqary3_t
*, struct scsi_pkt
*,
32 struct buf
*, int, int (*)());
33 static int cpqary3_dma_move(struct scsi_pkt
*, struct buf
*, cpqary3_t
*);
34 static int cpqary3_handle_flag_nointr(cpqary3_cmdpvt_t
*, struct scsi_pkt
*);
35 static int cpqary3_poll(cpqary3_t
*, uint32_t);
36 static void cpqary3_dmafree(struct scsi_address
*, struct scsi_pkt
*);
37 static void cpqary3_dma_sync(struct scsi_address
*, struct scsi_pkt
*);
38 static void cpqary3_destroy_pkt(struct scsi_address
*, struct scsi_pkt
*);
39 static struct scsi_pkt
*cpqary3_init_pkt(struct scsi_address
*,
40 struct scsi_pkt
*, struct buf
*, int, int, int, int, int (*callback
)(),
42 static int cpqary3_additional_cmd(struct scsi_pkt
*scsi_pktp
, cpqary3_t
*);
43 void cpqary3_oscmd_complete(cpqary3_cmdpvt_t
*);
44 static uint8_t cpqary3_is_scsi_read_write(struct scsi_pkt
*scsi_pktp
);
47 * External Variable Declarations
50 extern ddi_dma_attr_t cpqary3_dma_attr
;
53 * Function : cpqary3_init_hbatran
54 * Description : This routine initializes the transport vector in the
55 * SCSA architecture for entry ponts in this driver.
56 * Called By : cpqary3_attach()
57 * Parameters : per_controller
62 cpqary3_init_hbatran(cpqary3_t
*ctlr
)
64 scsi_hba_tran_t
*hba_tran
;
68 hba_tran
= ctlr
->hba_tran
;
71 * Memory for the transport vector has been allocated by now.
72 * initialize all the entry points in this vector
75 hba_tran
->tran_hba_private
= (void *)ctlr
;
77 /* Target Driver Instance Initialization */
78 hba_tran
->tran_tgt_init
= cpqary3_tgt_init
;
79 hba_tran
->tran_tgt_probe
= cpqary3_tgt_probe
;
81 /* Resource Allocation */
82 hba_tran
->tran_init_pkt
= cpqary3_init_pkt
;
83 hba_tran
->tran_destroy_pkt
= cpqary3_destroy_pkt
;
84 hba_tran
->tran_sync_pkt
= cpqary3_dma_sync
;
85 hba_tran
->tran_dmafree
= cpqary3_dmafree
;
87 /* Command Transport */
88 hba_tran
->tran_start
= cpqary3_transport
;
90 /* Capability Management */
91 hba_tran
->tran_getcap
= cpqary3_getcap
;
92 hba_tran
->tran_setcap
= cpqary3_setcap
;
95 hba_tran
->tran_reset
= cpqary3_reset
;
96 hba_tran
->tran_abort
= cpqary3_abort
;
100 * Function : cpqary3_tgt_init ()
101 * Description : This routine validates the target ID.
102 * Called By : cpqary3_init_hbatran()
103 * Parameters : HBA-instance, target instance, transport vector,
104 * scsi-device structure
105 * Calls : cpqary3_detect_target_geometry(),
106 * cpqary3_probe4targets()
107 * Return Values: DDI_SUCCESS : A Target exists at this ID.
108 * DDI_FAILURE : No such target exists.
112 cpqary3_tgt_init(dev_info_t
*hba_dip
, dev_info_t
*tgt_dip
,
113 scsi_hba_tran_t
*hba_tran
, struct scsi_device
*sd
)
115 uint32_t tid
= SD2TGT(sd
);
116 uint32_t lun
= SD2LUN(sd
);
119 ctlr
= (cpqary3_t
*)hba_tran
->tran_hba_private
;
121 /* HPQacucli Changes */
123 extern int8_t cpqary3_detect_target_geometry(cpqary3_t
*);
124 if ((CPQARY3_SUCCESS
== cpqary3_probe4targets(ctlr
)) &&
125 (ctlr
->num_of_targets
> 0)) {
126 (void) cpqary3_detect_target_geometry(ctlr
);
129 /* HPQacucli Changes */
131 * Validate the Target ID
132 * Validate Lun --Ver1.10--
133 * If not a valid target id, return FAILURE.
134 * Derieve the per-controller
137 if ((tid
>= CPQARY3_MAX_TGT
) || (lun
!= 0)) {
138 DTRACE_PROBE2(tgt_init_notsup
,
139 cpqary3_t
*, ctlr
, uint32_t, tid
);
140 return (DDI_FAILURE
);
144 * Check to see if a target structure corrresponding to this
145 * target Id exists.(support only for Logical Drives and Controller)
146 * if target exists, update target flags, return SUCCESS
147 * is target does not exist, return FAILURE
150 mutex_enter(&ctlr
->sw_mutex
);
152 if (!(ctlr
->cpqary3_tgtp
[tid
])) {
153 mutex_exit(&ctlr
->sw_mutex
);
154 return (DDI_FAILURE
);
157 ctlr
->cpqary3_tgtp
[tid
]->tgt_dip
= tgt_dip
;
158 ctlr
->cpqary3_tgtp
[tid
]->ctlr_flags
= CPQARY3_CAP_DISCON_ENABLED
|
159 CPQARY3_CAP_SYNC_ENABLED
| CPQARY3_CAP_WIDE_XFER_ENABLED
|
160 CPQARY3_CAP_ARQ_ENABLED
;
162 mutex_exit(&ctlr
->sw_mutex
);
164 DTRACE_PROBE1(tgt_init_done
, uint32_t, tid
);
166 return (DDI_SUCCESS
);
170 * Function : cpqary3_tgt_probe()
171 * Description : This routine probes into the Target Details.
172 * Called By : cpqary3_init_hbatran()
173 * Parameters : scsi-device structure, calling function if any
175 * Return Values: value returned by scsi_hba_probe()
178 cpqary3_tgt_probe(struct scsi_device
*sd
, int (*waitfunc
)())
185 * Probe for the presence of the target, using the scsi_hba_probe().
186 * It inturn issues the SCSI inquiry command that is serviced by our
190 /* HPQacucli Changes */
191 extern int8_t cpqary3_detect_target_geometry(cpqary3_t
*);
192 struct scsi_hba_tran
*hba_tran
= sd
->sd_address
.a_hba_tran
;
193 cpqary3_t
*ctlr
= hba_tran
->tran_hba_private
;
195 if ((CPQARY3_SUCCESS
== cpqary3_probe4targets(ctlr
)) &&
196 (ctlr
->num_of_targets
> 0)) {
197 (void) cpqary3_detect_target_geometry(ctlr
);
199 /* HPQacucli Changes */
201 return (scsi_hba_probe(sd
, waitfunc
));
205 /* Comment the previous line of code */
206 status
= scsi_hba_probe(sd
, waitfunc
);
207 cmn_err(CE_CONT
, "CPQary3 : _tgt_probe : target = %d \n", SD2TGT(sd
));
208 cmn_err(CE_CONT
, "CPQary3 : _tgt_probe : scsi_hba_probe returned %d \n",
210 cmn_err(CE_CONT
, "CPQary3 : _tgt_probe : Leaving \n");
217 * Function : cpqary3_init_pkt
218 * Description : This routine allocates resources for a SCSI packet.
219 * Called By : cpqary3_init_pkt()
220 * Parameters : SCSI address, SCSI packet, buffer, CDB length,
221 * SCB length, driver private length, flags modifier,
222 * callback function, arguement for the callback function
223 * Calls : cpqary3_dma_alloc(), cpqary3_dma_move()
224 * Return Values: allocated SCSI packet / NULL
227 static struct scsi_pkt
*
228 cpqary3_init_pkt(struct scsi_address
*sa
, struct scsi_pkt
*scsi_pktp
,
229 struct buf
*bp
, int cmdlen
, int statuslen
, int tgtlen
,
230 int flags
, int (*callback
)(), caddr_t arg
)
234 cpqary3_pkt_t
*cpqary3_pktp
;
235 struct scsi_pkt
*new_scsi_pktp
;
237 ASSERT(callback
== NULL_FUNC
|| callback
== SLEEP_FUNC
);
239 cpqary3p
= SA2CTLR(sa
);
243 * If the SCSI packet is NULL, allocate frresh resources to it.
244 * Else, get the next available resources for the same
248 scsi_pktp
= scsi_hba_pkt_alloc(dip
, sa
, cmdlen
, statuslen
,
249 tgtlen
, sizeof (cpqary3_pkt_t
), callback
, NULL
);
253 cpqary3_pktp
= (cpqary3_pkt_t
*)scsi_pktp
->pkt_ha_private
;
254 bzero(cpqary3_pktp
, sizeof (cpqary3_pkt_t
));
256 cpqary3_pktp
->scsi_cmd_pkt
= scsi_pktp
;
259 * Store the CDB length and sense data length in the
262 cpqary3_pktp
->cdb_len
= cmdlen
;
263 cpqary3_pktp
->scb_len
= statuslen
;
264 cpqary3_pktp
->cmd_dmahandle
= NULL
;
265 cpqary3_pktp
->memp
= (cpqary3_cmdpvt_t
*)NULL
;
268 * Initialize to NULL all the fields of scsi_pktp, except
269 * pkt_scbp, pkt_cdbp, pkt_ha_private and pkt_private members.
271 scsi_pktp
->pkt_address
= *sa
;
272 scsi_pktp
->pkt_comp
= (void (*) ())NULL
;
273 scsi_pktp
->pkt_flags
= 0;
274 scsi_pktp
->pkt_time
= 0;
275 scsi_pktp
->pkt_resid
= 0;
276 scsi_pktp
->pkt_statistics
= 0;
277 scsi_pktp
->pkt_state
= 0;
278 scsi_pktp
->pkt_reason
= 0;
280 if (flags
& PKT_CONSISTENT
)
281 cpqary3_pktp
->cmd_flags
|= DDI_DMA_CONSISTENT
;
283 if (flags
& PKT_DMA_PARTIAL
)
284 cpqary3_pktp
->cmd_flags
|= DDI_DMA_PARTIAL
;
286 new_scsi_pktp
= scsi_pktp
;
288 new_scsi_pktp
= NULL
;
289 cpqary3_pktp
= (cpqary3_pkt_t
*)scsi_pktp
->pkt_ha_private
;
292 cpqary3_pktp
->bf
= bp
;
295 * If any I/O is desired, Allocate/Move DMA resources for the SCSI
297 * If first time allocation for this SCSI packet, allocate fresh DMA
298 * Else, move the already allocated DMA resources
300 if (bp
&& bp
->b_bcount
!= 0) { /* I/O is desired */
301 if (!cpqary3_pktp
->cmd_dmahandle
) { /* First time allocation */
302 if (cpqary3_dma_alloc(cpqary3p
, scsi_pktp
,
303 bp
, flags
, callback
) == CPQARY3_FAILURE
) {
305 scsi_hba_pkt_free(sa
, new_scsi_pktp
);
309 ASSERT(new_scsi_pktp
== NULL
);
310 if (CPQARY3_FAILURE
==
311 cpqary3_dma_move(scsi_pktp
, bp
, cpqary3p
)) {
321 * Function : cpqary3_dma_alloc()
322 * Description : This routine services requests for memory (dynamic)
323 * as and when required by the OS.
324 * Called By : cpqary3_init_pkt()
325 * Parameters : per-controller, SCSI packet, buffer, flag modifier,
328 * Return Values: SUCCESS / FAILURE
331 cpqary3_dma_alloc(cpqary3_t
*cpqary3p
, struct scsi_pkt
*scsi_pktp
,
332 struct buf
*bp
, int flags
, int (*callback
)())
334 int32_t (*cb
)(caddr_t
);
338 cpqary3_pkt_t
*cpqary3_pktp
;
339 ddi_dma_attr_t tmp_dma_attr
;
341 cpqary3_pktp
= (cpqary3_pkt_t
*)scsi_pktp
->pkt_ha_private
;
343 ASSERT(callback
== NULL_FUNC
|| callback
== SLEEP_FUNC
);
345 * Record the direction of the data transfer, so that it
346 * can be used in appropriate synchronization during cpqary3_sync_pkt()
348 if (bp
->b_flags
& B_READ
) {
349 cpqary3_pktp
->cmd_flags
&= ~CFLAG_DMASEND
;
350 dma_flags
= DDI_DMA_READ
;
352 cpqary3_pktp
->cmd_flags
|= CFLAG_DMASEND
;
353 dma_flags
= DDI_DMA_WRITE
;
356 if (flags
& PKT_CONSISTENT
) {
357 cpqary3_pktp
->cmd_flags
|= CFLAG_CMDIOPB
;
358 dma_flags
|= DDI_DMA_CONSISTENT
;
361 if (flags
& PKT_DMA_PARTIAL
) {
362 dma_flags
|= DDI_DMA_PARTIAL
;
365 tmp_dma_attr
= cpqary3_dma_attr
;
368 tmp_dma_attr
.dma_attr_sgllen
= cpqary3p
->sg_cnt
;
371 cb
= (callback
== NULL_FUNC
) ? DDI_DMA_DONTWAIT
: DDI_DMA_SLEEP
;
374 * DMA resources are allocated thru a 2 step protocol :
375 * - allocate a DMA handle
376 * - bind the buffer to the handle
377 * If both the steps succeed, we have succeeded in allocating resources
380 if (DDI_SUCCESS
!= (retvalue
= ddi_dma_alloc_handle(cpqary3p
->dip
,
381 &tmp_dma_attr
, cb
, CPQARY3_DMA_NO_CALLBACK
,
382 &cpqary3_pktp
->cmd_dmahandle
))) {
384 case DDI_DMA_NORESOURCES
:
386 * No Resources are available to be allocated
388 bioerror(bp
, CPQARY3_BUFFER_ERROR_CLEAR
);
391 case DDI_DMA_BADATTR
:
393 * The attributes stated in our DMA attribute
394 * structure is such that potential DMA resources can
397 cmn_err(CE_CONT
, "CPQary3: DmaAlloc: "
398 "AllocHandle Failed BadAttr\n");
399 bioerror(bp
, EFAULT
);
404 * There is no other possible return value
407 "CPQary3: dma_alloc: Unexpected Return Value %x "
408 "From call to Allocate DMA Handle \n", retvalue
);
411 return (CPQARY3_FAILURE
);
414 retvalue
= ddi_dma_buf_bind_handle(cpqary3_pktp
->cmd_dmahandle
, bp
,
415 dma_flags
, cb
, CPQARY3_DMA_NO_CALLBACK
,
416 &cpqary3_pktp
->cmd_dmacookies
[0], &cpqary3_pktp
->cmd_ncookies
);
419 case DDI_DMA_PARTIAL_MAP
:
420 case DDI_DMA_MAPPED
:
421 if (DDI_DMA_PARTIAL_MAP
== retvalue
) {
422 if (ddi_dma_numwin(cpqary3_pktp
->cmd_dmahandle
,
423 &cpqary3_pktp
->cmd_nwin
) == DDI_FAILURE
) {
424 cmn_err(CE_PANIC
, "CPQary3: Retrieval of DMA "
425 "windows number failed");
428 if (ddi_dma_getwin(cpqary3_pktp
->cmd_dmahandle
,
429 cpqary3_pktp
->cmd_curwin
,
430 &cpqary3_pktp
->cmd_dma_offset
,
431 &cpqary3_pktp
->cmd_dma_len
,
432 &cpqary3_pktp
->cmd_dmacookies
[0],
433 &cpqary3_pktp
->cmd_ncookies
) == DDI_FAILURE
) {
434 cmn_err(CE_PANIC
, "CPQary3: Activation of New "
435 "DMA Window Failed");
438 cpqary3_pktp
->cmd_nwin
= 1;
439 cpqary3_pktp
->cmd_dma_len
= 0;
440 cpqary3_pktp
->cmd_dma_offset
= 0;
443 cpqary3_pktp
->cmd_dmacount
= 0;
446 cpqary3_pktp
->cmd_dmacount
+=
447 cpqary3_pktp
->cmd_dmacookies
[i
++].dmac_size
;
449 /* Check Out for Limits */
450 if (i
== cpqary3p
->sg_cnt
||
451 i
== cpqary3_pktp
->cmd_ncookies
)
455 ddi_dma_nextcookie(cpqary3_pktp
->cmd_dmahandle
,
456 &cpqary3_pktp
->cmd_dmacookies
[i
]);
459 cpqary3_pktp
->cmd_cookie
= i
;
460 cpqary3_pktp
->cmd_cookiecnt
= i
;
461 cpqary3_pktp
->cmd_flags
|= CFLAG_DMAVALID
;
463 scsi_pktp
->pkt_resid
=
464 bp
->b_bcount
- cpqary3_pktp
->cmd_dmacount
;
466 return (CPQARY3_SUCCESS
);
468 case DDI_DMA_NORESOURCES
:
469 bioerror(bp
, CPQARY3_BUFFER_ERROR_CLEAR
);
472 case DDI_DMA_NOMAPPING
:
473 bioerror(bp
, EFAULT
);
477 bioerror(bp
, EINVAL
);
481 cmn_err(CE_PANIC
, "CPQary3: Another I/O transaction "
482 "is using the DMA handle");
485 cmn_err(CE_PANIC
, "CPQary3: Unexpected ERROR "
486 "returned from Call to Bind Buffer "
487 "to Handle : 0x%X", i
);
490 ddi_dma_free_handle(&cpqary3_pktp
->cmd_dmahandle
);
491 cpqary3_pktp
->cmd_dmahandle
= NULL
;
492 cpqary3_pktp
->cmd_flags
&= ~CFLAG_DMAVALID
;
494 return (CPQARY3_FAILURE
);
499 * Function : cpqary3_dma_move()
500 * Description : This routine gets the next DMA window.
501 * Called By : cpqary3_init_pkt()
502 * Parameters : per-controller, SCSI packet, buffer
504 * Return Values: SUCCESS / FAILURE
507 cpqary3_dma_move(struct scsi_pkt
*scsi_pktp
, struct buf
*bp
,
511 cpqary3_pkt_t
*cpqary3_pktp
;
513 cpqary3_pktp
= PKT2PVTPKT(scsi_pktp
);
516 * If there are no more cookies remaining in this window,
517 * must move to the next window first.
519 if (cpqary3_pktp
->cmd_cookie
== cpqary3_pktp
->cmd_ncookies
) {
520 /* For small pkts, leave things where they are */
521 if ((cpqary3_pktp
->cmd_curwin
== cpqary3_pktp
->cmd_nwin
) &&
522 (cpqary3_pktp
->cmd_nwin
== 1))
523 return (CPQARY3_SUCCESS
);
525 /* Shall not be able to move if last window */
526 if (++cpqary3_pktp
->cmd_curwin
>= cpqary3_pktp
->cmd_nwin
)
527 return (CPQARY3_FAILURE
);
529 if (ddi_dma_getwin(cpqary3_pktp
->cmd_dmahandle
,
530 cpqary3_pktp
->cmd_curwin
, &cpqary3_pktp
->cmd_dma_offset
,
531 &cpqary3_pktp
->cmd_dma_len
,
532 &cpqary3_pktp
->cmd_dmacookies
[0],
533 &cpqary3_pktp
->cmd_ncookies
) == DDI_FAILURE
)
534 return (CPQARY3_FAILURE
);
536 cpqary3_pktp
->cmd_cookie
= 0;
538 /* Still more cookies in this window - get the next one */
539 ddi_dma_nextcookie(cpqary3_pktp
->cmd_dmahandle
,
540 &cpqary3_pktp
->cmd_dmacookies
[0]);
543 /* Get remaining cookies in this window, up to our maximum */
545 cpqary3_pktp
->cmd_dmacount
+=
546 cpqary3_pktp
->cmd_dmacookies
[i
++].dmac_size
;
547 cpqary3_pktp
->cmd_cookie
++;
549 /* no. of DATA SEGMENTS */
550 if (i
== cpqary3p
->sg_cnt
||
551 cpqary3_pktp
->cmd_cookie
== cpqary3_pktp
->cmd_ncookies
)
555 ddi_dma_nextcookie(cpqary3_pktp
->cmd_dmahandle
,
556 &cpqary3_pktp
->cmd_dmacookies
[i
]);
559 cpqary3_pktp
->cmd_cookiecnt
= i
;
560 scsi_pktp
->pkt_resid
= bp
->b_bcount
- cpqary3_pktp
->cmd_dmacount
;
562 return (CPQARY3_SUCCESS
);
567 * Function : cpqary3_transport()
568 * Description : This routine services requests from the OS that are
569 * directed towards the targets.(any SCSI command)
571 * Parameters : SCSI address, SCSI packet, buffer
572 * Calls : cpqary3_build_iop, cpqary3_add2submitted
573 * Return Values: TRAN_ACCEPT : The driver accepts the command.
574 * TRAN_BUSY : Required resources not available
576 * TRAN_FATAL_ERROR: A target no longer exists.
579 cpqary3_transport(struct scsi_address
*sa
, struct scsi_pkt
*scsi_pktp
)
582 cpqary3_pkt_t
*cpqary3_pktp
;
584 cpqary3_cmdpvt_t
*memp
;
588 cpqary3_pktp
= PKT2PVTPKT(scsi_pktp
);
589 tgtp
= ctlr
->cpqary3_tgtp
[SA2TGT(sa
)];
592 return (TRAN_FATAL_ERROR
);
594 if (tgtp
->type
== CPQARY3_TARGET_NONE
)
595 return (TRAN_FATAL_ERROR
);
597 if (cpqary3_additional_cmd(scsi_pktp
, ctlr
))
598 return (TRAN_ACCEPT
);
601 * Attempt to occupy a free command memory block
602 * If not successful, return TRAN_BUSY
603 * Else, build the Command
604 * Submit it to the controller
605 * If NO_INTR flag is set, wait for the completion of the command and
606 * when the command completes, update packet values appropriately and
607 * return TRAN_ACCEPT.
608 * Make an entry in the submitted Q
612 if (NULL
== (memp
= cpqary3_cmdlist_occupy(ctlr
)))
615 cpqary3_pktp
->memp
= memp
;
616 memp
->pvt_pkt
= cpqary3_pktp
;
618 if ((cpqary3_pktp
->cmd_flags
& DDI_DMA_CONSISTENT
) &&
619 cpqary3_pktp
->cmd_dmahandle
) {
620 (void) ddi_dma_sync(cpqary3_pktp
->cmd_dmahandle
, 0, 0,
621 DDI_DMA_SYNC_FORDEV
);
624 ASSERT(cpqary3_pktp
->cmd_cookiecnt
<= ctlr
->sg_cnt
);
628 memp
->complete
= cpqary3_oscmd_complete
;
631 switch (cpqary3_build_cmdlist(memp
, SA2TGT(sa
))) {
632 case CPQARY3_SUCCESS
:
633 if (scsi_pktp
->pkt_flags
& FLAG_NOINTR
) {
634 return (cpqary3_handle_flag_nointr(memp
, scsi_pktp
));
636 cpqary3_pktp
->cmd_start_time
= ddi_get_lbolt();
637 mutex_enter(&ctlr
->hw_mutex
);
638 /* CONTROLLER_LOCKUP */
639 if (EIO
== cpqary3_submit(ctlr
, memp
->cmdlist_phyaddr
)) {
640 mutex_exit(&ctlr
->hw_mutex
);
641 cpqary3_cmdlist_release(memp
, CPQARY3_HOLD_SW_MUTEX
);
642 return (TRAN_FATAL_ERROR
);
644 /* CONTROLLER_LOCKUP */
645 mutex_exit(&ctlr
->hw_mutex
);
647 case CPQARY3_FAILURE
:
648 cpqary3_cmdlist_release(memp
, CPQARY3_HOLD_SW_MUTEX
);
649 return (TRAN_FATAL_ERROR
);
650 default: /* Never occurs */
651 cmn_err(CE_NOTE
, "CPQary3 : Transport : Unexpected Error");
652 return (TRAN_FATAL_ERROR
);
655 return (TRAN_ACCEPT
);
659 * Function : cpqary3_dmafree
660 * Description : This routine de-allocates previously allocated
663 * Parameters : SCSI address, SCSI packet
665 * Return Values: None
669 cpqary3_dmafree(struct scsi_address
*sa
, struct scsi_pkt
*scsi_pktp
)
671 cpqary3_pkt_t
*cpqary3_pktp
;
673 cpqary3_pktp
= PKT2PVTPKT(scsi_pktp
);
676 * If any DMA was succesfully attempted earlier, free all allocated
680 if (cpqary3_pktp
->cmd_flags
& CFLAG_DMAVALID
) {
681 if (!cpqary3_pktp
->cmd_dmahandle
) {
682 DTRACE_PROBE(dmafree_null
);
685 cpqary3_pktp
->cmd_flags
&= ~CFLAG_DMAVALID
;
686 (void) ddi_dma_unbind_handle(cpqary3_pktp
->cmd_dmahandle
);
687 ddi_dma_free_handle(&cpqary3_pktp
->cmd_dmahandle
);
688 cpqary3_pktp
->cmd_dmahandle
= NULL
;
693 * Function : cpqary3_dma_sync
694 * Description : This routine synchronizes the CPU's / HBA's view of
695 * the data associated with the pkt, typically by calling
698 * Parameters : SCSI address, SCSI packet
700 * Return Values: None
704 cpqary3_dma_sync(struct scsi_address
*sa
, struct scsi_pkt
*scsi_pktp
)
706 cpqary3_pkt_t
*cpqary3_pktp
= PKT2PVTPKT(scsi_pktp
);
709 * Check whether DMA was attempted successfully earlier
711 * if the command flags is write, then synchronise the device else
712 * synchronise the CPU
715 if (cpqary3_pktp
->cmd_flags
& CFLAG_DMAVALID
) {
716 (void) ddi_dma_sync(cpqary3_pktp
->cmd_dmahandle
,
717 cpqary3_pktp
->cmd_dma_offset
, cpqary3_pktp
->cmd_dma_len
,
718 (cpqary3_pktp
->cmd_flags
& CFLAG_DMASEND
) ?
719 DDI_DMA_SYNC_FORDEV
: DDI_DMA_SYNC_FORCPU
);
724 * Function : cpqary3_destroy_pkt
725 * Description : This routine de-allocates previously allocated
726 * resources for the SCSI packet.
728 * Parameters : SCSI address, SCSI packet
730 * Return Values: None
733 cpqary3_destroy_pkt(struct scsi_address
*sa
, struct scsi_pkt
*scsi_pktp
)
735 cpqary3_pkt_t
*cpqary3_pktp
;
737 cpqary3_pktp
= PKT2PVTPKT(scsi_pktp
);
740 * Deallocate DMA Resources, if allocated.
741 * Free the SCSI Packet.
744 if (cpqary3_pktp
->cmd_flags
& CFLAG_DMAVALID
) {
745 if (!cpqary3_pktp
->cmd_dmahandle
) {
746 DTRACE_PROBE(dmafree_null
);
748 cpqary3_pktp
->cmd_flags
&= ~CFLAG_DMAVALID
;
750 (void) ddi_dma_unbind_handle(
751 cpqary3_pktp
->cmd_dmahandle
);
752 ddi_dma_free_handle(&cpqary3_pktp
->cmd_dmahandle
);
754 cpqary3_pktp
->cmd_dmahandle
= NULL
;
758 scsi_hba_pkt_free(sa
, scsi_pktp
);
762 * Function : cpqary3_reset
763 * Description : This routine resets a SCSI bus/target.
765 * Parameters : SCSI address, reset level required
767 * Return Values: SUCCESS
771 cpqary3_reset(struct scsi_address
*sa
, int level
)
774 * Fix for Crash seen during RAID 0 Drive removal -
775 * just return CPQARY3_SUCCESS on reset request
777 return (CPQARY3_SUCCESS
);
781 * Function : cpqary3_abort()
782 * Description : This routine aborts a particular command or all commands
783 * directed towards a target.
785 * Parameters : SCSI address, SCSI packet
787 * Return Values: SUCCESS / FAILURE
788 * [ abort of concernd command(s) was a success or
792 cpqary3_abort(struct scsi_address
*sa
, struct scsi_pkt
*scsi_pktp
)
802 * If SCSI packet exists, abort that particular command.
803 * Else, abort all existing commands to the target
804 * In either of the cases, we shall have to wait after the abort
805 * functions are called to return the status.
809 return (cpqary3_send_abortcmd(ctlr
, tid
,
810 (CommandList_t
*)NULL
));
812 return (cpqary3_send_abortcmd(ctlr
, tid
, SP2CMD(scsi_pktp
)));
817 * Function : cpqary3_getcap
818 * Description : This routine is called to get the current value of a
819 * capability.(SCSI transport capability)
821 * Parameters : SCSI address, capability identifier, target(s) affected
823 * Return Values: current value of capability / -1 (if unsupported)
826 cpqary3_getcap(struct scsi_address
*sa
, char *capstr
, int tgtonly
)
829 cpqary3_t
*ctlr
= SA2CTLR(sa
);
830 cpqary3_tgt_t
*tgtp
= ctlr
->cpqary3_tgtp
[SA2TGT(sa
)];
833 * If requested Capability is not supported, return -1.
835 if (DDI_FAILURE
== (index
= scsi_hba_lookup_capstr(capstr
)))
836 return (CAP_NOT_DEFINED
);
839 * Getting capability for a particulat target is supported
840 * the generic form of tran_getcap() is unsupported(for all targets)
841 * If directed towards a particular target, return current capability.
843 if (tgtonly
== 0) { /* all targets */
844 DTRACE_PROBE1(getcap_alltgt
, int, index
);
845 return (CAP_NOT_DEFINED
);
848 DTRACE_PROBE1(getcap_index
, int, index
);
851 case SCSI_CAP_DMA_MAX
:
852 return ((int)cpqary3_dma_attr
.dma_attr_maxxfer
);
853 case SCSI_CAP_DISCONNECT
:
854 return (tgtp
->ctlr_flags
& CPQARY3_CAP_DISCON_ENABLED
);
855 case SCSI_CAP_SYNCHRONOUS
:
856 return (tgtp
->ctlr_flags
& CPQARY3_CAP_SYNC_ENABLED
);
857 case SCSI_CAP_WIDE_XFER
:
858 return (tgtp
->ctlr_flags
& CPQARY3_CAP_WIDE_XFER_ENABLED
);
860 return ((tgtp
->ctlr_flags
& CPQARY3_CAP_ARQ_ENABLED
) ? 1 : 0);
861 case SCSI_CAP_INITIATOR_ID
:
862 return (CTLR_SCSI_ID
);
863 case SCSI_CAP_UNTAGGED_QING
:
865 case SCSI_CAP_TAGGED_QING
:
867 case SCSI_CAP_SECTOR_SIZE
:
868 return (cpqary3_dma_attr
.dma_attr_granular
);
869 case SCSI_CAP_TOTAL_SECTORS
:
870 return (CAP_NOT_DEFINED
);
871 case SCSI_CAP_GEOMETRY
:
872 return (cpqary3_target_geometry(sa
));
873 case SCSI_CAP_RESET_NOTIFICATION
:
876 return (CAP_NOT_DEFINED
);
881 * Function : cpqary3_setcap
882 * Description : This routine is called to set the current value of a
883 * capability.(SCSI transport capability)
885 * Parameters : SCSI address, capability identifier,
886 * new capability value, target(s) affected
888 * Return Values: SUCCESS / FAILURE / -1 (if capability is unsupported)
892 cpqary3_setcap(struct scsi_address
*sa
, char *capstr
, int value
, int tgtonly
)
895 int retstatus
= CAP_NOT_DEFINED
;
898 * If requested Capability is not supported, return -1.
900 if ((index
= scsi_hba_lookup_capstr(capstr
)) == DDI_FAILURE
)
904 * Setting capability for a particulat target is supported
905 * the generic form of tran_setcap() is unsupported(for all targets)
906 * If directed towards a particular target, set & return current
910 DTRACE_PROBE1(setcap_alltgt
, int, index
);
914 DTRACE_PROBE1(setcap_index
, int, index
);
917 case SCSI_CAP_DMA_MAX
:
918 return (CAP_CHG_NOT_ALLOWED
);
919 case SCSI_CAP_DISCONNECT
:
920 return (CAP_CHG_NOT_ALLOWED
);
921 case SCSI_CAP_SYNCHRONOUS
:
922 return (CAP_CHG_NOT_ALLOWED
);
923 case SCSI_CAP_WIDE_XFER
:
924 return (CAP_CHG_NOT_ALLOWED
);
927 case SCSI_CAP_INITIATOR_ID
:
928 return (CAP_CHG_NOT_ALLOWED
);
929 case SCSI_CAP_UNTAGGED_QING
:
931 case SCSI_CAP_TAGGED_QING
:
933 case SCSI_CAP_SECTOR_SIZE
:
934 return (CAP_CHG_NOT_ALLOWED
);
935 case SCSI_CAP_TOTAL_SECTORS
:
936 return (CAP_CHG_NOT_ALLOWED
);
937 case SCSI_CAP_GEOMETRY
:
938 return (CAP_CHG_NOT_ALLOWED
);
939 case SCSI_CAP_RESET_NOTIFICATION
:
940 return (CAP_CHG_NOT_ALLOWED
);
942 return (CAP_NOT_DEFINED
);
947 * Function : cpqary3_handle_flag_nointr
948 * Description : This routine is called to handle submission and
949 * subsequently poll for the completion of a command,
950 * when its FLAG_NOINTR bit is set.
951 * Called By : cpqary3_transport()
952 * Parameters : command private structure, SCSI packet
953 * Calls : cpqary3_intr_onoff, cpqary3_retrieve,
954 * cpqary3_submit, cpqary3_poll
955 * Return Values: TRAN_ACCEPT
958 cpqary3_handle_flag_nointr(cpqary3_cmdpvt_t
*memp
, struct scsi_pkt
*scsi_pktp
)
964 cpqary3_cmdpvt_t
*cpqary3_cmdpvtp
;
968 RETURN_FAILURE_IF_NULL(memp
);
969 tag
= memp
->tag
.tag_value
;
971 ctlr
->poll_flag
= CPQARY3_FALSE
;
974 * Before sumitting this command, ensure all commands pending
975 * with the controller are completed.
978 cpqary3_intr_onoff(ctlr
, CPQARY3_INTR_DISABLE
);
979 if (ctlr
->host_support
& 0x4)
980 cpqary3_lockup_intr_onoff(ctlr
, CPQARY3_LOCKUP_INTR_DISABLE
);
982 no_cmds
= (uint32_t)((ctlr
->ctlr_maxcmds
/ 3) * NO_OF_CMDLIST_IN_A_BLK
);
983 mutex_enter(&ctlr
->sw_mutex
);
986 ctlr
->poll_flag
= CPQARY3_FALSE
;
987 for (i
= 0; i
< no_cmds
; i
++) {
988 cpqary3_cmdpvtp
= &ctlr
->cmdmemlistp
->pool
[i
];
989 ASSERT(cpqary3_cmdpvtp
!= NULL
);
991 if ((tag
!= cpqary3_cmdpvtp
->tag
.tag_value
) &&
992 (cpqary3_cmdpvtp
->occupied
== CPQARY3_OCCUPIED
)) {
993 if (ctlr
->noe_support
== 1) {
994 if ((cpqary3_cmdpvtp
->cmdlist_memaddr
->
995 Header
.Tag
.drvinfo_n_err
==
996 CPQARY3_NOECMD_SUCCESS
) ||
997 (cpqary3_cmdpvtp
->cmdpvt_flag
==
1002 if (cpqary3_cmdpvtp
->cmdpvt_flag
==
1007 ctlr
->poll_flag
= CPQARY3_TRUE
;
1011 if (ctlr
->poll_flag
== CPQARY3_TRUE
) {
1016 if (ctlr
->poll_flag
== CPQARY3_TRUE
) {
1017 if (!(ctlr
->bddef
->bd_flags
& SA_BD_SAS
)) {
1018 while ((simple_tag
=
1019 ddi_get32(ctlr
->opq_handle
,
1020 (uint32_t *)ctlr
->opq
)) != 0xFFFFFFFF) {
1021 CmdsOutMax
= ctlr
->ctlr_maxcmds
;
1023 CPQARY3_GET_MEM_TAG
) >=
1024 ((CmdsOutMax
/ 3) * 3)) {
1026 "CPQary3 : HBA returned "
1028 return (CPQARY3_FAILURE
);
1032 &ctlr
->cmdmemlistp
->pool
[
1033 simple_tag
>> CPQARY3_GET_MEM_TAG
];
1034 cpqary3_cmdpvtp
->cmdlist_memaddr
->
1035 Header
.Tag
.drvinfo_n_err
=
1036 (simple_tag
& 0xF) >> 1;
1037 cpqary3_cmdpvtp
->complete(
1041 mutex_exit(&ctlr
->sw_mutex
);
1042 if (CPQARY3_SUCCESS
!= cpqary3_retrieve(ctlr
)) {
1045 mutex_enter(&ctlr
->sw_mutex
); /* Changes */
1052 mutex_enter(&ctlr
->hw_mutex
);
1053 if (EIO
== cpqary3_submit(ctlr
, memp
->cmdlist_phyaddr
)) {
1054 mutex_exit(&ctlr
->hw_mutex
);
1055 mutex_exit(&ctlr
->sw_mutex
);
1056 cpqary3_cmdlist_release(memp
, CPQARY3_HOLD_SW_MUTEX
);
1057 return (TRAN_FATAL_ERROR
);
1060 if (CPQARY3_FAILURE
== cpqary3_poll(ctlr
, tag
)) {
1061 scsi_pktp
->pkt_reason
= CMD_TIMEOUT
;
1062 scsi_pktp
->pkt_statistics
= STAT_TIMEOUT
;
1063 scsi_pktp
->pkt_state
= 0;
1064 mutex_exit(&ctlr
->hw_mutex
);
1065 mutex_exit(&ctlr
->sw_mutex
);
1066 cpqary3_cmdlist_release(memp
, CPQARY3_HOLD_SW_MUTEX
);
1067 cpqary3_intr_onoff(ctlr
, CPQARY3_INTR_ENABLE
);
1068 if (ctlr
->host_support
& 0x4)
1069 cpqary3_lockup_intr_onoff(ctlr
,
1070 CPQARY3_LOCKUP_INTR_ENABLE
);
1071 return (TRAN_ACCEPT
);
1073 mutex_exit(&ctlr
->hw_mutex
);
1074 mutex_exit(&ctlr
->sw_mutex
);
1075 cpqary3_intr_onoff(ctlr
, CPQARY3_INTR_ENABLE
);
1076 if (ctlr
->host_support
& 0x4) {
1077 cpqary3_lockup_intr_onoff(ctlr
,
1078 CPQARY3_LOCKUP_INTR_ENABLE
);
1080 return (TRAN_ACCEPT
);
1085 * Function : cpqary3_poll
1086 * Description : This routine polls for the completion of a command.
1087 * Called By : cpqary3_handle_flag_nointr
1088 * Parameters : per controller, tag of the command to be polled
1089 * Calls : cpqary3_poll_retrieve
1090 * Return Values: TRAN_ACCEPT
1093 cpqary3_poll(cpqary3_t
*ctlr
, uint32_t tag
)
1097 RETURN_FAILURE_IF_NULL(ctlr
);
1100 * POLL for the completion of the said command
1101 * Since, we had ensured that controller is empty, we need not
1102 * check for the complete Retrieved Q.
1103 * However, we just check the Retrieved Q and complete all
1104 * commands in it, inclusive of the polled command.
1105 * if the polled command is completed, send back a success.
1108 for (;;) { /* this function is called with both the locks held */
1109 if (CPQARY3_SUCCESS
!= cpqary3_poll_retrieve(ctlr
, tag
)) {
1112 return (CPQARY3_FAILURE
);
1119 return (CPQARY3_SUCCESS
);
1123 cpqary3_additional_cmd(struct scsi_pkt
*scsi_pktp
, cpqary3_t
*ctlr
)
1125 struct scsi_arq_status
*arqstat
;
1126 /* LINTED: alignment */
1127 arqstat
= (struct scsi_arq_status
*)(scsi_pktp
->pkt_scbp
);
1129 switch (scsi_pktp
->pkt_cdbp
[0]) {
1130 case 0x35: /* Synchronize Cache */
1132 cpqary3_flush_cache(ctlr
);
1134 scsi_pktp
->pkt_reason
= CMD_CMPLT
;
1135 scsi_pktp
->pkt_statistics
= 0;
1136 scsi_pktp
->pkt_state
= STATE_GOT_BUS
| STATE_GOT_TARGET
|
1137 STATE_SENT_CMD
| STATE_XFERRED_DATA
| STATE_GOT_STATUS
;
1139 if (scsi_pktp
->pkt_comp
) {
1140 (*scsi_pktp
->pkt_comp
)(scsi_pktp
);
1145 case 0x04: /* Format Unit */
1146 cmn_err(CE_NOTE
, "The FORMAT UNIT is not supported by this "
1147 "device If this option is selected from the format utility "
1148 "do not continue further. Please refer to cpqary3 driver "
1149 "man pages for details.");
1152 case SCSI_LOG_SENSE
:
1153 case SCSI_MODE_SELECT
:
1154 case SCSI_PERSISTENT_RESERVE_IN
:
1155 arqstat
->sts_status
.sts_chk
= 1; /* CHECK CONDITION */
1156 arqstat
->sts_rqpkt_reason
= CMD_CMPLT
;
1157 arqstat
->sts_rqpkt_resid
= 0;
1158 arqstat
->sts_rqpkt_state
= STATE_GOT_BUS
| STATE_GOT_TARGET
|
1159 STATE_SENT_CMD
| STATE_XFERRED_DATA
;
1160 arqstat
->sts_rqpkt_statistics
= 0;
1161 arqstat
->sts_sensedata
.es_valid
= 1;
1162 arqstat
->sts_sensedata
.es_class
= CLASS_EXTENDED_SENSE
;
1163 arqstat
->sts_sensedata
.es_key
= KEY_ILLEGAL_REQUEST
;
1164 scsi_pktp
->pkt_state
= STATE_GOT_BUS
| STATE_GOT_TARGET
|
1165 STATE_SENT_CMD
| STATE_XFERRED_DATA
;
1167 if (scsi_pktp
->pkt_comp
) {
1168 (*scsi_pktp
->pkt_comp
)(scsi_pktp
);
1178 * Function : cpqary3_oscmd_complete
1179 * Description : This routine processes the
1180 * completed OS commands and
1181 * initiates any callback that is needed.
1182 * Called By : cpqary3_transport
1183 * Parameters : per-command
1184 * Calls : cpqary3_ioctl_send_bmiccmd,
1185 * cpqary3_ioctl_send_scsicmd,
1186 * cpqary3_send_abortcmd, cpqary3_flush_cache,
1187 * cpqary3_probe4LVs,
1188 * cpqary3_probe4Tapes, cpqary3_synccmd_complete,
1189 * cpqary3_detect_target_geometry,
1190 * cpqary3_detect_target_geometry
1191 * Return Values: None
1194 cpqary3_oscmd_complete(cpqary3_cmdpvt_t
*cpqary3_cmdpvtp
)
1196 cpqary3_t
*cpqary3p
;
1197 ErrorInfo_t
*errorinfop
;
1198 CommandList_t
*cmdlistp
;
1199 struct scsi_pkt
*scsi_pktp
;
1201 ASSERT(cpqary3_cmdpvtp
!= NULL
);
1203 if (CPQARY3_TIMEOUT
== cpqary3_cmdpvtp
->cmdpvt_flag
) {
1204 cpqary3_cmdlist_release(cpqary3_cmdpvtp
,
1209 cpqary3p
= cpqary3_cmdpvtp
->ctlr
;
1210 cmdlistp
= cpqary3_cmdpvtp
->cmdlist_memaddr
;
1211 errorinfop
= cpqary3_cmdpvtp
->errorinfop
;
1213 if (cmdlistp
->Header
.Tag
.drvinfo_n_err
== CPQARY3_OSCMD_SUCCESS
) {
1214 scsi_pktp
= cpqary3_cmdpvtp
->pvt_pkt
->scsi_cmd_pkt
;
1215 scsi_pktp
->pkt_reason
= CMD_CMPLT
;
1216 scsi_pktp
->pkt_statistics
= 0;
1217 scsi_pktp
->pkt_state
= STATE_GOT_BUS
|
1218 STATE_GOT_TARGET
| STATE_SENT_CMD
|
1219 STATE_XFERRED_DATA
| STATE_GOT_STATUS
;
1221 if (cpqary3_cmdpvtp
->pvt_pkt
->scsi_cmd_pkt
->pkt_flags
&
1223 cpqary3_cmdlist_release(cpqary3_cmdpvtp
,
1226 cpqary3_cmdlist_release(cpqary3_cmdpvtp
,
1229 if (scsi_pktp
->pkt_comp
) {
1230 mutex_exit(&cpqary3p
->sw_mutex
);
1231 (*scsi_pktp
->pkt_comp
)(scsi_pktp
);
1232 mutex_enter(&cpqary3p
->sw_mutex
);
1237 scsi_pktp
= cpqary3_cmdpvtp
->pvt_pkt
->scsi_cmd_pkt
;
1240 switch (errorinfop
->CommandStatus
) {
1241 case CISS_CMD_DATA_OVERRUN
:
1242 scsi_pktp
->pkt_reason
= CMD_DATA_OVR
;
1243 scsi_pktp
->pkt_state
= STATE_GOT_BUS
| STATE_GOT_TARGET
|
1244 STATE_SENT_CMD
| STATE_XFERRED_DATA
| STATE_GOT_STATUS
;
1247 case CISS_CMD_INVALID
:
1248 DTRACE_PROBE1(invalid_cmd
, struct scsi_pkt
*, scsi_pktp
);
1249 scsi_pktp
->pkt_reason
= CMD_BADMSG
;
1250 scsi_pktp
->pkt_state
= STATE_GOT_BUS
|STATE_GOT_TARGET
|
1251 STATE_SENT_CMD
| STATE_GOT_STATUS
;
1254 case CISS_CMD_PROTOCOL_ERR
:
1255 scsi_pktp
->pkt_reason
= CMD_BADMSG
;
1256 scsi_pktp
->pkt_state
= STATE_GOT_BUS
| STATE_GOT_TARGET
|
1257 STATE_SENT_CMD
| STATE_GOT_STATUS
;
1260 case CISS_CMD_HARDWARE_ERR
:
1261 case CISS_CMD_CONNECTION_LOST
:
1262 scsi_pktp
->pkt_reason
= CMD_INCOMPLETE
;
1263 scsi_pktp
->pkt_state
= 0;
1266 case CISS_CMD_ABORTED
:
1267 case CISS_CMD_UNSOLICITED_ABORT
:
1268 scsi_pktp
->pkt_reason
= CMD_ABORTED
;
1269 scsi_pktp
->pkt_statistics
= STAT_ABORTED
;
1270 scsi_pktp
->pkt_state
= STATE_GOT_BUS
| STATE_GOT_TARGET
|
1271 STATE_SENT_CMD
| STATE_XFERRED_DATA
| STATE_GOT_STATUS
;
1274 case CISS_CMD_ABORT_FAILED
:
1277 case CISS_CMD_TIMEOUT
:
1278 scsi_pktp
->pkt_reason
= CMD_TIMEOUT
;
1279 scsi_pktp
->pkt_statistics
= STAT_TIMEOUT
;
1280 scsi_pktp
->pkt_state
= 0;
1283 case CISS_CMD_DATA_UNDERRUN
: /* Significant ONLY for Read & Write */
1284 if (cpqary3_is_scsi_read_write(scsi_pktp
)) {
1285 scsi_pktp
->pkt_reason
= CMD_CMPLT
;
1286 scsi_pktp
->pkt_statistics
= 0;
1287 scsi_pktp
->pkt_state
=
1288 STATE_GOT_BUS
| STATE_GOT_TARGET
| STATE_SENT_CMD
|
1289 STATE_XFERRED_DATA
| STATE_GOT_STATUS
;
1293 case CISS_CMD_SUCCESS
:
1294 case CISS_CMD_TARGET_STATUS
:
1295 scsi_pktp
->pkt_reason
= CMD_CMPLT
;
1296 scsi_pktp
->pkt_statistics
= 0;
1297 scsi_pktp
->pkt_state
= STATE_GOT_BUS
| STATE_GOT_TARGET
|
1298 STATE_SENT_CMD
| STATE_XFERRED_DATA
| STATE_GOT_STATUS
;
1301 default: /* Should never Occur !!! */
1302 scsi_pktp
->pkt_reason
= CMD_TRAN_ERR
;
1308 * if ever a command completes with a CHECK CONDITION or a
1309 * COMMAND_TERMINATED SCSI status, Update the sense data.
1310 * NOTE : The CISS_CMD_INVALID command status would always result in a
1311 * CHECK CONDITION and hence reach this part of the code.
1314 if ((errorinfop
->ScsiStatus
== SCSI_CHECK_CONDITION
) ||
1315 (errorinfop
->ScsiStatus
== SCSI_COMMAND_TERMINATED
)) {
1316 if (errorinfop
->SenseLen
) {
1317 struct scsi_arq_status
*arq_statusp
;
1319 /* LINTED: alignment */
1320 (struct scsi_arq_status
*)scsi_pktp
->pkt_scbp
;
1322 if ((errorinfop
->ScsiStatus
== SCSI_CHECK_CONDITION
)) {
1323 arq_statusp
->sts_status
.sts_chk
= (uint8_t)1;
1325 arq_statusp
->sts_status
.sts_chk
= (uint8_t)1;
1326 arq_statusp
->sts_status
.sts_scsi2
= (uint8_t)1;
1328 bzero((void *)&(arq_statusp
->sts_rqpkt_status
),
1329 sizeof (struct scsi_status
));
1330 arq_statusp
->sts_rqpkt_reason
= CMD_CMPLT
;
1331 arq_statusp
->sts_rqpkt_resid
= 0;
1332 arq_statusp
->sts_rqpkt_state
= scsi_pktp
->pkt_state
;
1333 arq_statusp
->sts_rqpkt_statistics
=
1334 scsi_pktp
->pkt_statistics
;
1335 bcopy((caddr_t
)&errorinfop
->SenseInfo
[0],
1336 (caddr_t
)(&arq_statusp
->sts_sensedata
),
1337 CPQARY3_MIN(errorinfop
->SenseLen
,
1338 cpqary3_cmdpvtp
->pvt_pkt
->scb_len
));
1339 scsi_pktp
->pkt_state
|= STATE_ARQ_DONE
;
1343 if (cpqary3_cmdpvtp
->pvt_pkt
->scsi_cmd_pkt
->pkt_flags
& FLAG_NOINTR
) {
1344 cpqary3_cmdlist_release(cpqary3_cmdpvtp
, CPQARY3_NO_MUTEX
);
1346 cpqary3_cmdlist_release(cpqary3_cmdpvtp
, CPQARY3_NO_MUTEX
);
1348 if (scsi_pktp
->pkt_comp
) {
1349 mutex_exit(&cpqary3p
->sw_mutex
);
1350 (*scsi_pktp
->pkt_comp
)(scsi_pktp
);
1351 mutex_enter(&cpqary3p
->sw_mutex
);
1357 cpqary3_is_scsi_read_write(struct scsi_pkt
*scsi_pktp
)
1360 * In the scsi packet structure, the first byte is the SCSI Command
1361 * OpCode. We check to see if it is any one of the SCSI Read or Write
1365 switch (scsi_pktp
->pkt_cdbp
[0]) {