1 /*
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
5 * 1.0 of the CDDL.
6 *
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.
10 */
11
12 /*
13 * Copyright (C) 2013 Hewlett-Packard Development Company, L.P.
14 */
15
16 #include <sys/sdt.h>
17 #include "cpqary3.h"
18
19 /*
20 * Local Functions Definitions
21 */
22
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)(),
41 caddr_t);
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);
45
46 /*
47 * External Variable Declarations
48 */
49
50 extern ddi_dma_attr_t cpqary3_dma_attr;
51
52 /*
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
58 * Calls : None
59 * Return Values: None
60 */
61 void
cpqary3_init_hbatran(cpqary3_t * ctlr)62 cpqary3_init_hbatran(cpqary3_t *ctlr)
63 {
64 scsi_hba_tran_t *hba_tran;
65
66 ASSERT(ctlr != NULL);
67
68 hba_tran = ctlr->hba_tran;
69
70 /*
71 * Memory for the transport vector has been allocated by now.
72 * initialize all the entry points in this vector
73 */
74
75 hba_tran->tran_hba_private = (void *)ctlr;
76
77 /* Target Driver Instance Initialization */
78 hba_tran->tran_tgt_init = cpqary3_tgt_init;
79 hba_tran->tran_tgt_probe = cpqary3_tgt_probe;
80
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;
86
87 /* Command Transport */
88 hba_tran->tran_start = cpqary3_transport;
89
90 /* Capability Management */
91 hba_tran->tran_getcap = cpqary3_getcap;
92 hba_tran->tran_setcap = cpqary3_setcap;
93
94 /* Abort and Reset */
95 hba_tran->tran_reset = cpqary3_reset;
96 hba_tran->tran_abort = cpqary3_abort;
97 }
98
99 /*
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.
109 */
110 /* ARGSUSED */
111 static int
cpqary3_tgt_init(dev_info_t * hba_dip,dev_info_t * tgt_dip,scsi_hba_tran_t * hba_tran,struct scsi_device * sd)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)
114 {
115 uint32_t tid = SD2TGT(sd);
116 uint32_t lun = SD2LUN(sd);
117 cpqary3_t *ctlr;
118
119 ctlr = (cpqary3_t *)hba_tran->tran_hba_private;
120
121 /* HPQacucli Changes */
122
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);
127 }
128
129 /* HPQacucli Changes */
130 /*
131 * Validate the Target ID
132 * Validate Lun --Ver1.10--
133 * If not a valid target id, return FAILURE.
134 * Derieve the per-controller
135 */
136
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);
141 }
142
143 /*
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
148 */
149
150 mutex_enter(&ctlr->sw_mutex);
151
152 if (!(ctlr->cpqary3_tgtp[tid])) {
153 mutex_exit(&ctlr->sw_mutex);
154 return (DDI_FAILURE);
155 }
156
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;
161
162 mutex_exit(&ctlr->sw_mutex);
163
164 DTRACE_PROBE1(tgt_init_done, uint32_t, tid);
165
166 return (DDI_SUCCESS);
167 }
168
169 /*
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
174 * Calls : None
175 * Return Values: value returned by scsi_hba_probe()
176 */
177 static int
cpqary3_tgt_probe(struct scsi_device * sd,int (* waitfunc)())178 cpqary3_tgt_probe(struct scsi_device *sd, int (*waitfunc)())
179 {
180 #ifdef CPQARY3_DEBUG
181 int status;
182 #endif
183
184 /*
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
187 * driver
188 */
189
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;
194
195 if ((CPQARY3_SUCCESS == cpqary3_probe4targets(ctlr)) &&
196 (ctlr->num_of_targets > 0)) {
197 (void) cpqary3_detect_target_geometry(ctlr);
198 }
199 /* HPQacucli Changes */
200
201 return (scsi_hba_probe(sd, waitfunc));
202
203 #ifdef CPQARY3_DEBUG
204
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",
209 status);
210 cmn_err(CE_CONT, "CPQary3 : _tgt_probe : Leaving \n");
211 return (status);
212
213 #endif
214 }
215
216 /*
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
225 */
226 /* ARGSUSED */
227 static struct scsi_pkt *
cpqary3_init_pkt(struct scsi_address * sa,struct scsi_pkt * scsi_pktp,struct buf * bp,int cmdlen,int statuslen,int tgtlen,int flags,int (* callback)(),caddr_t arg)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)
231 {
232 cpqary3_t *cpqary3p;
233 dev_info_t *dip;
234 cpqary3_pkt_t *cpqary3_pktp;
235 struct scsi_pkt *new_scsi_pktp;
236
237 ASSERT(callback == NULL_FUNC || callback == SLEEP_FUNC);
238
239 cpqary3p = SA2CTLR(sa);
240 dip = cpqary3p->dip;
241
242 /*
243 * If the SCSI packet is NULL, allocate frresh resources to it.
244 * Else, get the next available resources for the same
245 */
246
247 if (!scsi_pktp) {
248 scsi_pktp = scsi_hba_pkt_alloc(dip, sa, cmdlen, statuslen,
249 tgtlen, sizeof (cpqary3_pkt_t), callback, NULL);
250 if (!scsi_pktp)
251 return (NULL);
252
253 cpqary3_pktp = (cpqary3_pkt_t *)scsi_pktp->pkt_ha_private;
254 bzero(cpqary3_pktp, sizeof (cpqary3_pkt_t));
255
256 cpqary3_pktp->scsi_cmd_pkt = scsi_pktp;
257
258 /*
259 * Store the CDB length and sense data length in the
260 * pkt private
261 */
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;
266
267 /*
268 * Initialize to NULL all the fields of scsi_pktp, except
269 * pkt_scbp, pkt_cdbp, pkt_ha_private and pkt_private members.
270 */
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;
279
280 if (flags & PKT_CONSISTENT)
281 cpqary3_pktp->cmd_flags |= DDI_DMA_CONSISTENT;
282
283 if (flags & PKT_DMA_PARTIAL)
284 cpqary3_pktp->cmd_flags |= DDI_DMA_PARTIAL;
285
286 new_scsi_pktp = scsi_pktp;
287 } else {
288 new_scsi_pktp = NULL;
289 cpqary3_pktp = (cpqary3_pkt_t *)scsi_pktp->pkt_ha_private;
290 }
291
292 cpqary3_pktp->bf = bp;
293
294 /*
295 * If any I/O is desired, Allocate/Move DMA resources for the SCSI
296 * packet
297 * If first time allocation for this SCSI packet, allocate fresh DMA
298 * Else, move the already allocated DMA resources
299 */
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) {
304 if (new_scsi_pktp)
305 scsi_hba_pkt_free(sa, new_scsi_pktp);
306 return ((struct scsi_pkt *)NULL);
307 }
308 } else {
309 ASSERT(new_scsi_pktp == NULL);
310 if (CPQARY3_FAILURE ==
311 cpqary3_dma_move(scsi_pktp, bp, cpqary3p)) {
312 return ((struct scsi_pkt *)NULL);
313 }
314 }
315 }
316
317 return (scsi_pktp);
318 }
319
320 /*
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,
326 * callback function
327 * Calls : None
328 * Return Values: SUCCESS / FAILURE
329 */
330 static int
cpqary3_dma_alloc(cpqary3_t * cpqary3p,struct scsi_pkt * scsi_pktp,struct buf * bp,int flags,int (* callback)())331 cpqary3_dma_alloc(cpqary3_t *cpqary3p, struct scsi_pkt *scsi_pktp,
332 struct buf *bp, int flags, int (*callback)())
333 {
334 int32_t (*cb)(caddr_t);
335 int32_t retvalue;
336 uint32_t i = 0;
337 uint32_t dma_flags;
338 cpqary3_pkt_t *cpqary3_pktp;
339 ddi_dma_attr_t tmp_dma_attr;
340
341 cpqary3_pktp = (cpqary3_pkt_t *)scsi_pktp->pkt_ha_private;
342
343 ASSERT(callback == NULL_FUNC || callback == SLEEP_FUNC);
344 /*
345 * Record the direction of the data transfer, so that it
346 * can be used in appropriate synchronization during cpqary3_sync_pkt()
347 */
348 if (bp->b_flags & B_READ) {
349 cpqary3_pktp->cmd_flags &= ~CFLAG_DMASEND;
350 dma_flags = DDI_DMA_READ;
351 } else {
352 cpqary3_pktp->cmd_flags |= CFLAG_DMASEND;
353 dma_flags = DDI_DMA_WRITE;
354 }
355
356 if (flags & PKT_CONSISTENT) {
357 cpqary3_pktp->cmd_flags |= CFLAG_CMDIOPB;
358 dma_flags |= DDI_DMA_CONSISTENT;
359 }
360
361 if (flags & PKT_DMA_PARTIAL) {
362 dma_flags |= DDI_DMA_PARTIAL;
363 }
364
365 tmp_dma_attr = cpqary3_dma_attr;
366
367 /* SG */
368 tmp_dma_attr.dma_attr_sgllen = cpqary3p->sg_cnt;
369 /* SG */
370
371 cb = (callback == NULL_FUNC) ? DDI_DMA_DONTWAIT : DDI_DMA_SLEEP;
372
373 /*
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
378 */
379
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))) {
383 switch (retvalue) {
384 case DDI_DMA_NORESOURCES:
385 /*
386 * No Resources are available to be allocated
387 */
388 bioerror(bp, CPQARY3_BUFFER_ERROR_CLEAR);
389 break;
390
391 case DDI_DMA_BADATTR:
392 /*
393 * The attributes stated in our DMA attribute
394 * structure is such that potential DMA resources can
395 * not be allocated.
396 */
397 cmn_err(CE_CONT, "CPQary3: DmaAlloc: "
398 "AllocHandle Failed BadAttr\n");
399 bioerror(bp, EFAULT);
400 break;
401
402 default:
403 /*
404 * There is no other possible return value
405 */
406 cmn_err(CE_WARN,
407 "CPQary3: dma_alloc: Unexpected Return Value %x "
408 "From call to Allocate DMA Handle \n", retvalue);
409 break;
410 }
411 return (CPQARY3_FAILURE);
412 }
413
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);
417
418 switch (retvalue) {
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");
426 }
427
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");
436 }
437 } else {
438 cpqary3_pktp->cmd_nwin = 1;
439 cpqary3_pktp->cmd_dma_len = 0;
440 cpqary3_pktp->cmd_dma_offset = 0;
441 }
442
443 cpqary3_pktp->cmd_dmacount = 0;
444 i = 0;
445 for (;;) {
446 cpqary3_pktp->cmd_dmacount +=
447 cpqary3_pktp->cmd_dmacookies[i++].dmac_size;
448 /* SG */
449 /* Check Out for Limits */
450 if (i == cpqary3p->sg_cnt ||
451 i == cpqary3_pktp->cmd_ncookies)
452 break;
453 /* SG */
454
455 ddi_dma_nextcookie(cpqary3_pktp->cmd_dmahandle,
456 &cpqary3_pktp->cmd_dmacookies[i]);
457 }
458
459 cpqary3_pktp->cmd_cookie = i;
460 cpqary3_pktp->cmd_cookiecnt = i;
461 cpqary3_pktp->cmd_flags |= CFLAG_DMAVALID;
462
463 scsi_pktp->pkt_resid =
464 bp->b_bcount - cpqary3_pktp->cmd_dmacount;
465
466 return (CPQARY3_SUCCESS);
467
468 case DDI_DMA_NORESOURCES:
469 bioerror(bp, CPQARY3_BUFFER_ERROR_CLEAR);
470 break;
471
472 case DDI_DMA_NOMAPPING:
473 bioerror(bp, EFAULT);
474 break;
475
476 case DDI_DMA_TOOBIG:
477 bioerror(bp, EINVAL);
478 break;
479
480 case DDI_DMA_INUSE:
481 cmn_err(CE_PANIC, "CPQary3: Another I/O transaction "
482 "is using the DMA handle");
483 break;
484
485 default:
486 cmn_err(CE_PANIC, "CPQary3: Unexpected ERROR "
487 "returned from Call to Bind Buffer "
488 "to Handle : 0x%X", retvalue);
489 }
490
491 ddi_dma_free_handle(&cpqary3_pktp->cmd_dmahandle);
492 cpqary3_pktp->cmd_dmahandle = NULL;
493 cpqary3_pktp->cmd_flags &= ~CFLAG_DMAVALID;
494
495 return (CPQARY3_FAILURE);
496
497 }
498
499 /*
500 * Function : cpqary3_dma_move()
501 * Description : This routine gets the next DMA window.
502 * Called By : cpqary3_init_pkt()
503 * Parameters : per-controller, SCSI packet, buffer
504 * Calls : None
505 * Return Values: SUCCESS / FAILURE
506 */
507 static int
cpqary3_dma_move(struct scsi_pkt * scsi_pktp,struct buf * bp,cpqary3_t * cpqary3p)508 cpqary3_dma_move(struct scsi_pkt *scsi_pktp, struct buf *bp,
509 cpqary3_t *cpqary3p)
510 {
511 uint32_t i = 0;
512 cpqary3_pkt_t *cpqary3_pktp;
513
514 cpqary3_pktp = PKT2PVTPKT(scsi_pktp);
515
516 /*
517 * If there are no more cookies remaining in this window,
518 * must move to the next window first.
519 */
520 if (cpqary3_pktp->cmd_cookie == cpqary3_pktp->cmd_ncookies) {
521 /* For small pkts, leave things where they are */
522 if ((cpqary3_pktp->cmd_curwin == cpqary3_pktp->cmd_nwin) &&
523 (cpqary3_pktp->cmd_nwin == 1))
524 return (CPQARY3_SUCCESS);
525
526 /* Shall not be able to move if last window */
527 if (++cpqary3_pktp->cmd_curwin >= cpqary3_pktp->cmd_nwin)
528 return (CPQARY3_FAILURE);
529
530 if (ddi_dma_getwin(cpqary3_pktp->cmd_dmahandle,
531 cpqary3_pktp->cmd_curwin, &cpqary3_pktp->cmd_dma_offset,
532 &cpqary3_pktp->cmd_dma_len,
533 &cpqary3_pktp->cmd_dmacookies[0],
534 &cpqary3_pktp->cmd_ncookies) == DDI_FAILURE)
535 return (CPQARY3_FAILURE);
536
537 cpqary3_pktp->cmd_cookie = 0;
538 } else {
539 /* Still more cookies in this window - get the next one */
540 ddi_dma_nextcookie(cpqary3_pktp->cmd_dmahandle,
541 &cpqary3_pktp->cmd_dmacookies[0]);
542 }
543
544 /* Get remaining cookies in this window, up to our maximum */
545 for (;;) {
546 cpqary3_pktp->cmd_dmacount +=
547 cpqary3_pktp->cmd_dmacookies[i++].dmac_size;
548 cpqary3_pktp->cmd_cookie++;
549 /* SG */
550 /* no. of DATA SEGMENTS */
551 if (i == cpqary3p->sg_cnt ||
552 cpqary3_pktp->cmd_cookie == cpqary3_pktp->cmd_ncookies)
553 break;
554 /* SG */
555
556 ddi_dma_nextcookie(cpqary3_pktp->cmd_dmahandle,
557 &cpqary3_pktp->cmd_dmacookies[i]);
558 }
559
560 cpqary3_pktp->cmd_cookiecnt = i;
561 scsi_pktp->pkt_resid = bp->b_bcount - cpqary3_pktp->cmd_dmacount;
562
563 return (CPQARY3_SUCCESS);
564
565 }
566
567 /*
568 * Function : cpqary3_transport()
569 * Description : This routine services requests from the OS that are
570 * directed towards the targets.(any SCSI command)
571 * Called By : kernel
572 * Parameters : SCSI address, SCSI packet, buffer
573 * Calls : cpqary3_build_iop, cpqary3_add2submitted
574 * Return Values: TRAN_ACCEPT : The driver accepts the command.
575 * TRAN_BUSY : Required resources not available
576 * at the moment.
577 * TRAN_FATAL_ERROR: A target no longer exists.
578 */
579 static int
cpqary3_transport(struct scsi_address * sa,struct scsi_pkt * scsi_pktp)580 cpqary3_transport(struct scsi_address *sa, struct scsi_pkt *scsi_pktp)
581 {
582 cpqary3_t *ctlr;
583 cpqary3_pkt_t *cpqary3_pktp;
584 cpqary3_tgt_t *tgtp;
585 cpqary3_cmdpvt_t *memp;
586
587 ASSERT(sa != NULL);
588 ctlr = SA2CTLR(sa);
589 cpqary3_pktp = PKT2PVTPKT(scsi_pktp);
590 tgtp = ctlr->cpqary3_tgtp[SA2TGT(sa)];
591
592 if (!tgtp)
593 return (TRAN_FATAL_ERROR);
594
595 if (tgtp->type == CPQARY3_TARGET_NONE)
596 return (TRAN_FATAL_ERROR);
597
598 if (cpqary3_additional_cmd(scsi_pktp, ctlr))
599 return (TRAN_ACCEPT);
600
601 /*
602 * Attempt to occupy a free command memory block
603 * If not successful, return TRAN_BUSY
604 * Else, build the Command
605 * Submit it to the controller
606 * If NO_INTR flag is set, wait for the completion of the command and
607 * when the command completes, update packet values appropriately and
608 * return TRAN_ACCEPT.
609 * Make an entry in the submitted Q
610 * return TRAN_ACCEPT
611 */
612
613 if (NULL == (memp = cpqary3_cmdlist_occupy(ctlr)))
614 return (TRAN_BUSY);
615
616 cpqary3_pktp->memp = memp;
617 memp->pvt_pkt = cpqary3_pktp;
618
619 if ((cpqary3_pktp->cmd_flags & DDI_DMA_CONSISTENT) &&
620 cpqary3_pktp->cmd_dmahandle) {
621 (void) ddi_dma_sync(cpqary3_pktp->cmd_dmahandle, 0, 0,
622 DDI_DMA_SYNC_FORDEV);
623 }
624 /* SG */
625 ASSERT(cpqary3_pktp->cmd_cookiecnt <= ctlr->sg_cnt);
626 /* SG */
627
628 /* PERF */
629 memp->complete = cpqary3_oscmd_complete;
630 /* PERF */
631
632 switch (cpqary3_build_cmdlist(memp, SA2TGT(sa))) {
633 case CPQARY3_SUCCESS :
634 if (scsi_pktp->pkt_flags & FLAG_NOINTR) {
635 return (cpqary3_handle_flag_nointr(memp, scsi_pktp));
636 }
637 cpqary3_pktp->cmd_start_time = ddi_get_lbolt();
638 mutex_enter(&ctlr->hw_mutex);
639 /* CONTROLLER_LOCKUP */
640 if (EIO == cpqary3_submit(ctlr, memp->cmdlist_phyaddr)) {
641 mutex_exit(&ctlr->hw_mutex);
642 cpqary3_cmdlist_release(memp, CPQARY3_HOLD_SW_MUTEX);
643 return (TRAN_FATAL_ERROR);
644 }
645 /* CONTROLLER_LOCKUP */
646 mutex_exit(&ctlr->hw_mutex);
647 break;
648 case CPQARY3_FAILURE :
649 cpqary3_cmdlist_release(memp, CPQARY3_HOLD_SW_MUTEX);
650 return (TRAN_FATAL_ERROR);
651 default: /* Never occurs */
652 cmn_err(CE_NOTE, "CPQary3 : Transport : Unexpected Error");
653 return (TRAN_FATAL_ERROR);
654 }
655
656 return (TRAN_ACCEPT);
657 }
658
659 /*
660 * Function : cpqary3_dmafree
661 * Description : This routine de-allocates previously allocated
662 * DMA resources.
663 * Called By : kernel
664 * Parameters : SCSI address, SCSI packet
665 * Calls : None
666 * Return Values: None
667 */
668 /* ARGSUSED */
669 static void
cpqary3_dmafree(struct scsi_address * sa,struct scsi_pkt * scsi_pktp)670 cpqary3_dmafree(struct scsi_address *sa, struct scsi_pkt *scsi_pktp)
671 {
672 cpqary3_pkt_t *cpqary3_pktp;
673
674 cpqary3_pktp = PKT2PVTPKT(scsi_pktp);
675
676 /*
677 * If any DMA was succesfully attempted earlier, free all allocated
678 * resources
679 */
680
681 if (cpqary3_pktp->cmd_flags & CFLAG_DMAVALID) {
682 if (!cpqary3_pktp->cmd_dmahandle) {
683 DTRACE_PROBE(dmafree_null);
684 return;
685 }
686 cpqary3_pktp->cmd_flags &= ~CFLAG_DMAVALID;
687 (void) ddi_dma_unbind_handle(cpqary3_pktp->cmd_dmahandle);
688 ddi_dma_free_handle(&cpqary3_pktp->cmd_dmahandle);
689 cpqary3_pktp->cmd_dmahandle = NULL;
690 }
691 }
692
693 /*
694 * Function : cpqary3_dma_sync
695 * Description : This routine synchronizes the CPU's / HBA's view of
696 * the data associated with the pkt, typically by calling
697 * ddi_dma_sync().
698 * Called By : kernel
699 * Parameters : SCSI address, SCSI packet
700 * Calls : None
701 * Return Values: None
702 */
703 /* ARGSUSED */
704 static void
cpqary3_dma_sync(struct scsi_address * sa,struct scsi_pkt * scsi_pktp)705 cpqary3_dma_sync(struct scsi_address *sa, struct scsi_pkt *scsi_pktp)
706 {
707 cpqary3_pkt_t *cpqary3_pktp = PKT2PVTPKT(scsi_pktp);
708
709 /*
710 * Check whether DMA was attempted successfully earlier
711 * If yes and
712 * if the command flags is write, then synchronise the device else
713 * synchronise the CPU
714 */
715
716 if (cpqary3_pktp->cmd_flags & CFLAG_DMAVALID) {
717 (void) ddi_dma_sync(cpqary3_pktp->cmd_dmahandle,
718 cpqary3_pktp->cmd_dma_offset, cpqary3_pktp->cmd_dma_len,
719 (cpqary3_pktp->cmd_flags & CFLAG_DMASEND) ?
720 DDI_DMA_SYNC_FORDEV : DDI_DMA_SYNC_FORCPU);
721 }
722 }
723
724 /*
725 * Function : cpqary3_destroy_pkt
726 * Description : This routine de-allocates previously allocated
727 * resources for the SCSI packet.
728 * Called By : kernel
729 * Parameters : SCSI address, SCSI packet
730 * Calls : None
731 * Return Values: None
732 */
733 static void
cpqary3_destroy_pkt(struct scsi_address * sa,struct scsi_pkt * scsi_pktp)734 cpqary3_destroy_pkt(struct scsi_address *sa, struct scsi_pkt *scsi_pktp)
735 {
736 cpqary3_pkt_t *cpqary3_pktp;
737
738 cpqary3_pktp = PKT2PVTPKT(scsi_pktp);
739
740 /*
741 * Deallocate DMA Resources, if allocated.
742 * Free the SCSI Packet.
743 */
744
745 if (cpqary3_pktp->cmd_flags & CFLAG_DMAVALID) {
746 if (!cpqary3_pktp->cmd_dmahandle) {
747 DTRACE_PROBE(dmafree_null);
748 } else {
749 cpqary3_pktp->cmd_flags &= ~CFLAG_DMAVALID;
750
751 (void) ddi_dma_unbind_handle(
752 cpqary3_pktp->cmd_dmahandle);
753 ddi_dma_free_handle(&cpqary3_pktp->cmd_dmahandle);
754
755 cpqary3_pktp->cmd_dmahandle = NULL;
756 }
757 }
758
759 scsi_hba_pkt_free(sa, scsi_pktp);
760 }
761
762 /*
763 * Function : cpqary3_reset
764 * Description : This routine resets a SCSI bus/target.
765 * Called By : kernel
766 * Parameters : SCSI address, reset level required
767 * Calls : None
768 * Return Values: SUCCESS
769 */
770 /* ARGSUSED */
771 static int
cpqary3_reset(struct scsi_address * sa,int level)772 cpqary3_reset(struct scsi_address *sa, int level)
773 {
774 /*
775 * Fix for Crash seen during RAID 0 Drive removal -
776 * just return CPQARY3_SUCCESS on reset request
777 */
778 return (CPQARY3_SUCCESS);
779 }
780
781 /*
782 * Function : cpqary3_abort()
783 * Description : This routine aborts a particular command or all commands
784 * directed towards a target.
785 * Called By : kernel
786 * Parameters : SCSI address, SCSI packet
787 * Calls : None
788 * Return Values: SUCCESS / FAILURE
789 * [ abort of concernd command(s) was a success or
790 * a failure. ]
791 */
792 static int
cpqary3_abort(struct scsi_address * sa,struct scsi_pkt * scsi_pktp)793 cpqary3_abort(struct scsi_address *sa, struct scsi_pkt *scsi_pktp)
794 {
795 uint32_t tid;
796 cpqary3_t *ctlr;
797
798 ASSERT(sa != NULL);
799 tid = SA2TGT(sa);
800 ctlr = SA2CTLR(sa);
801
802 /*
803 * If SCSI packet exists, abort that particular command.
804 * Else, abort all existing commands to the target
805 * In either of the cases, we shall have to wait after the abort
806 * functions are called to return the status.
807 */
808
809 if (!scsi_pktp) {
810 return (cpqary3_send_abortcmd(ctlr, tid,
811 (CommandList_t *)NULL));
812 } else {
813 return (cpqary3_send_abortcmd(ctlr, tid, SP2CMD(scsi_pktp)));
814 }
815 }
816
817 /*
818 * Function : cpqary3_getcap
819 * Description : This routine is called to get the current value of a
820 * capability.(SCSI transport capability)
821 * Called By : kernel
822 * Parameters : SCSI address, capability identifier, target(s) affected
823 * Calls : None
824 * Return Values: current value of capability / -1 (if unsupported)
825 */
826 static int
cpqary3_getcap(struct scsi_address * sa,char * capstr,int tgtonly)827 cpqary3_getcap(struct scsi_address *sa, char *capstr, int tgtonly)
828 {
829 int index;
830 cpqary3_t *ctlr = SA2CTLR(sa);
831 cpqary3_tgt_t *tgtp = ctlr->cpqary3_tgtp[SA2TGT(sa)];
832
833 /*
834 * If requested Capability is not supported, return -1.
835 */
836 if (DDI_FAILURE == (index = scsi_hba_lookup_capstr(capstr)))
837 return (CAP_NOT_DEFINED);
838
839 /*
840 * Getting capability for a particulat target is supported
841 * the generic form of tran_getcap() is unsupported(for all targets)
842 * If directed towards a particular target, return current capability.
843 */
844 if (tgtonly == 0) { /* all targets */
845 DTRACE_PROBE1(getcap_alltgt, int, index);
846 return (CAP_NOT_DEFINED);
847 }
848
849 DTRACE_PROBE1(getcap_index, int, index);
850
851 switch (index) {
852 case SCSI_CAP_DMA_MAX:
853 return ((int)cpqary3_dma_attr.dma_attr_maxxfer);
854 case SCSI_CAP_DISCONNECT:
855 return (tgtp->ctlr_flags & CPQARY3_CAP_DISCON_ENABLED);
856 case SCSI_CAP_SYNCHRONOUS:
857 return (tgtp->ctlr_flags & CPQARY3_CAP_SYNC_ENABLED);
858 case SCSI_CAP_WIDE_XFER:
859 return (tgtp->ctlr_flags & CPQARY3_CAP_WIDE_XFER_ENABLED);
860 case SCSI_CAP_ARQ:
861 return ((tgtp->ctlr_flags & CPQARY3_CAP_ARQ_ENABLED) ? 1 : 0);
862 case SCSI_CAP_INITIATOR_ID:
863 return (CTLR_SCSI_ID);
864 case SCSI_CAP_UNTAGGED_QING:
865 return (1);
866 case SCSI_CAP_TAGGED_QING:
867 return (1);
868 case SCSI_CAP_SECTOR_SIZE:
869 return (cpqary3_dma_attr.dma_attr_granular);
870 case SCSI_CAP_TOTAL_SECTORS:
871 return (CAP_NOT_DEFINED);
872 case SCSI_CAP_GEOMETRY:
873 return (cpqary3_target_geometry(sa));
874 case SCSI_CAP_RESET_NOTIFICATION:
875 return (0);
876 default:
877 return (CAP_NOT_DEFINED);
878 }
879 }
880
881 /*
882 * Function : cpqary3_setcap
883 * Description : This routine is called to set the current value of a
884 * capability.(SCSI transport capability)
885 * Called By : kernel
886 * Parameters : SCSI address, capability identifier,
887 * new capability value, target(s) affected
888 * Calls : None
889 * Return Values: SUCCESS / FAILURE / -1 (if capability is unsupported)
890 */
891 /* ARGSUSED */
892 static int
cpqary3_setcap(struct scsi_address * sa,char * capstr,int value,int tgtonly)893 cpqary3_setcap(struct scsi_address *sa, char *capstr, int value, int tgtonly)
894 {
895 int index;
896 int retstatus = CAP_NOT_DEFINED;
897
898 /*
899 * If requested Capability is not supported, return -1.
900 */
901 if ((index = scsi_hba_lookup_capstr(capstr)) == DDI_FAILURE)
902 return (retstatus);
903
904 /*
905 * Setting capability for a particulat target is supported
906 * the generic form of tran_setcap() is unsupported(for all targets)
907 * If directed towards a particular target, set & return current
908 * capability.
909 */
910 if (!tgtonly) {
911 DTRACE_PROBE1(setcap_alltgt, int, index);
912 return (retstatus);
913 }
914
915 DTRACE_PROBE1(setcap_index, int, index);
916
917 switch (index) {
918 case SCSI_CAP_DMA_MAX:
919 return (CAP_CHG_NOT_ALLOWED);
920 case SCSI_CAP_DISCONNECT:
921 return (CAP_CHG_NOT_ALLOWED);
922 case SCSI_CAP_SYNCHRONOUS:
923 return (CAP_CHG_NOT_ALLOWED);
924 case SCSI_CAP_WIDE_XFER:
925 return (CAP_CHG_NOT_ALLOWED);
926 case SCSI_CAP_ARQ:
927 return (1);
928 case SCSI_CAP_INITIATOR_ID:
929 return (CAP_CHG_NOT_ALLOWED);
930 case SCSI_CAP_UNTAGGED_QING:
931 return (1);
932 case SCSI_CAP_TAGGED_QING:
933 return (1);
934 case SCSI_CAP_SECTOR_SIZE:
935 return (CAP_CHG_NOT_ALLOWED);
936 case SCSI_CAP_TOTAL_SECTORS:
937 return (CAP_CHG_NOT_ALLOWED);
938 case SCSI_CAP_GEOMETRY:
939 return (CAP_CHG_NOT_ALLOWED);
940 case SCSI_CAP_RESET_NOTIFICATION:
941 return (CAP_CHG_NOT_ALLOWED);
942 default:
943 return (CAP_NOT_DEFINED);
944 }
945 }
946
947 /*
948 * Function : cpqary3_handle_flag_nointr
949 * Description : This routine is called to handle submission and
950 * subsequently poll for the completion of a command,
951 * when its FLAG_NOINTR bit is set.
952 * Called By : cpqary3_transport()
953 * Parameters : command private structure, SCSI packet
954 * Calls : cpqary3_intr_onoff, cpqary3_retrieve,
955 * cpqary3_submit, cpqary3_poll
956 * Return Values: TRAN_ACCEPT
957 */
958 static int
cpqary3_handle_flag_nointr(cpqary3_cmdpvt_t * memp,struct scsi_pkt * scsi_pktp)959 cpqary3_handle_flag_nointr(cpqary3_cmdpvt_t *memp, struct scsi_pkt *scsi_pktp)
960 {
961 uint32_t tag;
962 uint32_t simple_tag;
963 uint32_t i;
964 cpqary3_t *ctlr;
965 cpqary3_cmdpvt_t *cpqary3_cmdpvtp;
966 uint32_t CmdsOutMax;
967 uint32_t no_cmds;
968
969 RETURN_FAILURE_IF_NULL(memp);
970 tag = memp->tag.tag_value;
971 ctlr = memp->ctlr;
972 ctlr->poll_flag = CPQARY3_FALSE;
973
974 /*
975 * Before sumitting this command, ensure all commands pending
976 * with the controller are completed.
977 */
978
979 cpqary3_intr_onoff(ctlr, CPQARY3_INTR_DISABLE);
980 if (ctlr->host_support & 0x4)
981 cpqary3_lockup_intr_onoff(ctlr, CPQARY3_LOCKUP_INTR_DISABLE);
982
983 no_cmds = (uint32_t)((ctlr->ctlr_maxcmds / 3) * NO_OF_CMDLIST_IN_A_BLK);
984 mutex_enter(&ctlr->sw_mutex);
985
986 for (;;) {
987 ctlr->poll_flag = CPQARY3_FALSE;
988 for (i = 0; i < no_cmds; i++) {
989 cpqary3_cmdpvtp = &ctlr->cmdmemlistp->pool[i];
990 ASSERT(cpqary3_cmdpvtp != NULL);
991
992 if ((tag != cpqary3_cmdpvtp->tag.tag_value) &&
993 (cpqary3_cmdpvtp->occupied == CPQARY3_OCCUPIED)) {
994 if (ctlr->noe_support == 1) {
995 if ((cpqary3_cmdpvtp->cmdlist_memaddr->
996 Header.Tag.drvinfo_n_err ==
997 CPQARY3_NOECMD_SUCCESS) ||
998 (cpqary3_cmdpvtp->cmdpvt_flag ==
999 CPQARY3_TIMEOUT)) {
1000 continue;
1001 }
1002 } else {
1003 if (cpqary3_cmdpvtp->cmdpvt_flag ==
1004 CPQARY3_TIMEOUT) {
1005 continue;
1006 }
1007 }
1008 ctlr->poll_flag = CPQARY3_TRUE;
1009 }
1010 /* NOE */
1011
1012 if (ctlr->poll_flag == CPQARY3_TRUE) {
1013 break;
1014 }
1015 }
1016
1017 if (ctlr->poll_flag == CPQARY3_TRUE) {
1018 if (!(ctlr->bddef->bd_flags & SA_BD_SAS)) {
1019 while ((simple_tag =
1020 ddi_get32(ctlr->opq_handle,
1021 (uint32_t *)ctlr->opq)) != 0xFFFFFFFF) {
1022 CmdsOutMax = ctlr->ctlr_maxcmds;
1023 if ((simple_tag >>
1024 CPQARY3_GET_MEM_TAG) >=
1025 ((CmdsOutMax / 3) * 3)) {
1026 cmn_err(CE_WARN,
1027 "CPQary3 : HBA returned "
1028 "Spurious Tag");
1029 return (CPQARY3_FAILURE);
1030 }
1031
1032 cpqary3_cmdpvtp =
1033 &ctlr->cmdmemlistp->pool[
1034 simple_tag >> CPQARY3_GET_MEM_TAG];
1035 cpqary3_cmdpvtp->cmdlist_memaddr->
1036 Header.Tag.drvinfo_n_err =
1037 (simple_tag & 0xF) >> 1;
1038 cpqary3_cmdpvtp->complete(
1039 cpqary3_cmdpvtp);
1040 }
1041 } else {
1042 mutex_exit(&ctlr->sw_mutex);
1043 if (CPQARY3_SUCCESS != cpqary3_retrieve(ctlr)) {
1044 drv_usecwait(1000);
1045 }
1046 mutex_enter(&ctlr->sw_mutex); /* Changes */
1047 }
1048 } else {
1049 break;
1050 }
1051 }
1052
1053 mutex_enter(&ctlr->hw_mutex);
1054 if (EIO == cpqary3_submit(ctlr, memp->cmdlist_phyaddr)) {
1055 mutex_exit(&ctlr->hw_mutex);
1056 mutex_exit(&ctlr->sw_mutex);
1057 cpqary3_cmdlist_release(memp, CPQARY3_HOLD_SW_MUTEX);
1058 return (TRAN_FATAL_ERROR);
1059 }
1060
1061 if (CPQARY3_FAILURE == cpqary3_poll(ctlr, tag)) {
1062 scsi_pktp->pkt_reason = CMD_TIMEOUT;
1063 scsi_pktp->pkt_statistics = STAT_TIMEOUT;
1064 scsi_pktp->pkt_state = 0;
1065 mutex_exit(&ctlr->hw_mutex);
1066 mutex_exit(&ctlr->sw_mutex);
1067 cpqary3_cmdlist_release(memp, CPQARY3_HOLD_SW_MUTEX);
1068 cpqary3_intr_onoff(ctlr, CPQARY3_INTR_ENABLE);
1069 if (ctlr->host_support & 0x4)
1070 cpqary3_lockup_intr_onoff(ctlr,
1071 CPQARY3_LOCKUP_INTR_ENABLE);
1072 return (TRAN_ACCEPT);
1073 } else {
1074 mutex_exit(&ctlr->hw_mutex);
1075 mutex_exit(&ctlr->sw_mutex);
1076 cpqary3_intr_onoff(ctlr, CPQARY3_INTR_ENABLE);
1077 if (ctlr->host_support & 0x4) {
1078 cpqary3_lockup_intr_onoff(ctlr,
1079 CPQARY3_LOCKUP_INTR_ENABLE);
1080 }
1081 return (TRAN_ACCEPT);
1082 }
1083 }
1084
1085 /*
1086 * Function : cpqary3_poll
1087 * Description : This routine polls for the completion of a command.
1088 * Called By : cpqary3_handle_flag_nointr
1089 * Parameters : per controller, tag of the command to be polled
1090 * Calls : cpqary3_poll_retrieve
1091 * Return Values: TRAN_ACCEPT
1092 */
1093 static int
cpqary3_poll(cpqary3_t * ctlr,uint32_t tag)1094 cpqary3_poll(cpqary3_t *ctlr, uint32_t tag)
1095 {
1096 uint32_t ii = 0;
1097
1098 RETURN_FAILURE_IF_NULL(ctlr);
1099
1100 /*
1101 * POLL for the completion of the said command
1102 * Since, we had ensured that controller is empty, we need not
1103 * check for the complete Retrieved Q.
1104 * However, we just check the Retrieved Q and complete all
1105 * commands in it, inclusive of the polled command.
1106 * if the polled command is completed, send back a success.
1107 */
1108
1109 for (;;) { /* this function is called with both the locks held */
1110 if (CPQARY3_SUCCESS != cpqary3_poll_retrieve(ctlr, tag)) {
1111 ii++;
1112 if (ii > 120000)
1113 return (CPQARY3_FAILURE);
1114 drv_usecwait(500);
1115 continue;
1116 }
1117 break;
1118 }
1119
1120 return (CPQARY3_SUCCESS);
1121 }
1122
1123 static int
cpqary3_additional_cmd(struct scsi_pkt * scsi_pktp,cpqary3_t * ctlr)1124 cpqary3_additional_cmd(struct scsi_pkt *scsi_pktp, cpqary3_t *ctlr)
1125 {
1126 struct scsi_arq_status *arqstat;
1127 /* LINTED: alignment */
1128 arqstat = (struct scsi_arq_status *)(scsi_pktp->pkt_scbp);
1129
1130 switch (scsi_pktp->pkt_cdbp[0]) {
1131 case 0x35: /* Synchronize Cache */
1132
1133 cpqary3_flush_cache(ctlr);
1134
1135 scsi_pktp->pkt_reason = CMD_CMPLT;
1136 scsi_pktp->pkt_statistics = 0;
1137 scsi_pktp->pkt_state = STATE_GOT_BUS | STATE_GOT_TARGET |
1138 STATE_SENT_CMD | STATE_XFERRED_DATA | STATE_GOT_STATUS;
1139
1140 if (scsi_pktp->pkt_comp) {
1141 (*scsi_pktp->pkt_comp)(scsi_pktp);
1142 }
1143
1144 return (1);
1145
1146 case 0x04: /* Format Unit */
1147 cmn_err(CE_NOTE, "The FORMAT UNIT is not supported by this "
1148 "device If this option is selected from the format utility "
1149 "do not continue further. Please refer to cpqary3 driver "
1150 "man pages for details.");
1151
1152 return (0);
1153 case SCSI_LOG_SENSE:
1154 case SCSI_MODE_SELECT:
1155 case SCSI_PERSISTENT_RESERVE_IN:
1156 arqstat->sts_status.sts_chk = 1; /* CHECK CONDITION */
1157 arqstat->sts_rqpkt_reason = CMD_CMPLT;
1158 arqstat->sts_rqpkt_resid = 0;
1159 arqstat->sts_rqpkt_state = STATE_GOT_BUS | STATE_GOT_TARGET |
1160 STATE_SENT_CMD | STATE_XFERRED_DATA;
1161 arqstat->sts_rqpkt_statistics = 0;
1162 arqstat->sts_sensedata.es_valid = 1;
1163 arqstat->sts_sensedata.es_class = CLASS_EXTENDED_SENSE;
1164 arqstat->sts_sensedata.es_key = KEY_ILLEGAL_REQUEST;
1165 scsi_pktp->pkt_state = STATE_GOT_BUS | STATE_GOT_TARGET |
1166 STATE_SENT_CMD | STATE_XFERRED_DATA;
1167
1168 if (scsi_pktp->pkt_comp) {
1169 (*scsi_pktp->pkt_comp)(scsi_pktp);
1170 }
1171 return (1);
1172 }
1173
1174 return (0);
1175 }
1176
1177 /* PERF */
1178 /*
1179 * Function : cpqary3_oscmd_complete
1180 * Description : This routine processes the
1181 * completed OS commands and
1182 * initiates any callback that is needed.
1183 * Called By : cpqary3_transport
1184 * Parameters : per-command
1185 * Calls : cpqary3_ioctl_send_bmiccmd,
1186 * cpqary3_ioctl_send_scsicmd,
1187 * cpqary3_send_abortcmd, cpqary3_flush_cache,
1188 * cpqary3_probe4LVs,
1189 * cpqary3_probe4Tapes, cpqary3_synccmd_complete,
1190 * cpqary3_detect_target_geometry,
1191 * cpqary3_detect_target_geometry
1192 * Return Values: None
1193 */
1194 void
cpqary3_oscmd_complete(cpqary3_cmdpvt_t * cpqary3_cmdpvtp)1195 cpqary3_oscmd_complete(cpqary3_cmdpvt_t *cpqary3_cmdpvtp)
1196 {
1197 cpqary3_t *cpqary3p;
1198 ErrorInfo_t *errorinfop;
1199 CommandList_t *cmdlistp;
1200 struct scsi_pkt *scsi_pktp;
1201
1202 ASSERT(cpqary3_cmdpvtp != NULL);
1203
1204 if (CPQARY3_TIMEOUT == cpqary3_cmdpvtp->cmdpvt_flag) {
1205 cpqary3_cmdlist_release(cpqary3_cmdpvtp,
1206 CPQARY3_NO_MUTEX);
1207 return;
1208 }
1209
1210 cpqary3p = cpqary3_cmdpvtp->ctlr;
1211 cmdlistp = cpqary3_cmdpvtp->cmdlist_memaddr;
1212 errorinfop = cpqary3_cmdpvtp->errorinfop;
1213
1214 if (cmdlistp->Header.Tag.drvinfo_n_err == CPQARY3_OSCMD_SUCCESS) {
1215 scsi_pktp = cpqary3_cmdpvtp->pvt_pkt->scsi_cmd_pkt;
1216 scsi_pktp->pkt_reason = CMD_CMPLT;
1217 scsi_pktp->pkt_statistics = 0;
1218 scsi_pktp->pkt_state = STATE_GOT_BUS |
1219 STATE_GOT_TARGET | STATE_SENT_CMD |
1220 STATE_XFERRED_DATA | STATE_GOT_STATUS;
1221
1222 if (cpqary3_cmdpvtp->pvt_pkt->scsi_cmd_pkt->pkt_flags &
1223 FLAG_NOINTR) {
1224 cpqary3_cmdlist_release(cpqary3_cmdpvtp,
1225 CPQARY3_NO_MUTEX);
1226 } else {
1227 cpqary3_cmdlist_release(cpqary3_cmdpvtp,
1228 CPQARY3_NO_MUTEX);
1229
1230 if (scsi_pktp->pkt_comp) {
1231 mutex_exit(&cpqary3p->sw_mutex);
1232 (*scsi_pktp->pkt_comp)(scsi_pktp);
1233 mutex_enter(&cpqary3p->sw_mutex);
1234 }
1235 }
1236 return;
1237 } else {
1238 scsi_pktp = cpqary3_cmdpvtp->pvt_pkt->scsi_cmd_pkt;
1239 }
1240
1241 switch (errorinfop->CommandStatus) {
1242 case CISS_CMD_DATA_OVERRUN :
1243 scsi_pktp->pkt_reason = CMD_DATA_OVR;
1244 scsi_pktp->pkt_state = STATE_GOT_BUS | STATE_GOT_TARGET |
1245 STATE_SENT_CMD | STATE_XFERRED_DATA | STATE_GOT_STATUS;
1246 break;
1247
1248 case CISS_CMD_INVALID :
1249 DTRACE_PROBE1(invalid_cmd, struct scsi_pkt *, scsi_pktp);
1250 scsi_pktp->pkt_reason = CMD_BADMSG;
1251 scsi_pktp->pkt_state = STATE_GOT_BUS |STATE_GOT_TARGET |
1252 STATE_SENT_CMD | STATE_GOT_STATUS;
1253 break;
1254
1255 case CISS_CMD_PROTOCOL_ERR :
1256 scsi_pktp->pkt_reason = CMD_BADMSG;
1257 scsi_pktp->pkt_state = STATE_GOT_BUS | STATE_GOT_TARGET |
1258 STATE_SENT_CMD | STATE_GOT_STATUS;
1259 break;
1260
1261 case CISS_CMD_HARDWARE_ERR:
1262 case CISS_CMD_CONNECTION_LOST:
1263 scsi_pktp->pkt_reason = CMD_INCOMPLETE;
1264 scsi_pktp->pkt_state = 0;
1265 break;
1266
1267 case CISS_CMD_ABORTED:
1268 case CISS_CMD_UNSOLICITED_ABORT:
1269 scsi_pktp->pkt_reason = CMD_ABORTED;
1270 scsi_pktp->pkt_statistics = STAT_ABORTED;
1271 scsi_pktp->pkt_state = STATE_GOT_BUS | STATE_GOT_TARGET |
1272 STATE_SENT_CMD | STATE_XFERRED_DATA | STATE_GOT_STATUS;
1273 break;
1274
1275 case CISS_CMD_ABORT_FAILED:
1276 break;
1277
1278 case CISS_CMD_TIMEOUT:
1279 scsi_pktp->pkt_reason = CMD_TIMEOUT;
1280 scsi_pktp->pkt_statistics = STAT_TIMEOUT;
1281 scsi_pktp->pkt_state = 0;
1282 break;
1283
1284 case CISS_CMD_DATA_UNDERRUN: /* Significant ONLY for Read & Write */
1285 if (cpqary3_is_scsi_read_write(scsi_pktp)) {
1286 scsi_pktp->pkt_reason = CMD_CMPLT;
1287 scsi_pktp->pkt_statistics = 0;
1288 scsi_pktp->pkt_state =
1289 STATE_GOT_BUS | STATE_GOT_TARGET | STATE_SENT_CMD |
1290 STATE_XFERRED_DATA | STATE_GOT_STATUS;
1291 break;
1292 }
1293 /* FALLTHROUGH */
1294 case CISS_CMD_SUCCESS:
1295 case CISS_CMD_TARGET_STATUS:
1296 scsi_pktp->pkt_reason = CMD_CMPLT;
1297 scsi_pktp->pkt_statistics = 0;
1298 scsi_pktp->pkt_state = STATE_GOT_BUS | STATE_GOT_TARGET |
1299 STATE_SENT_CMD | STATE_XFERRED_DATA | STATE_GOT_STATUS;
1300 break;
1301
1302 default: /* Should never Occur !!! */
1303 scsi_pktp->pkt_reason = CMD_TRAN_ERR;
1304 break;
1305 }
1306
1307
1308 /*
1309 * if ever a command completes with a CHECK CONDITION or a
1310 * COMMAND_TERMINATED SCSI status, Update the sense data.
1311 * NOTE : The CISS_CMD_INVALID command status would always result in a
1312 * CHECK CONDITION and hence reach this part of the code.
1313 */
1314
1315 if ((errorinfop->ScsiStatus == SCSI_CHECK_CONDITION) ||
1316 (errorinfop->ScsiStatus == SCSI_COMMAND_TERMINATED)) {
1317 if (errorinfop->SenseLen) {
1318 struct scsi_arq_status *arq_statusp;
1319 arq_statusp =
1320 /* LINTED: alignment */
1321 (struct scsi_arq_status *)scsi_pktp->pkt_scbp;
1322
1323 if ((errorinfop->ScsiStatus == SCSI_CHECK_CONDITION)) {
1324 arq_statusp->sts_status.sts_chk = (uint8_t)1;
1325 } else {
1326 arq_statusp->sts_status.sts_chk = (uint8_t)1;
1327 arq_statusp->sts_status.sts_scsi2 = (uint8_t)1;
1328 }
1329 bzero((void *)&(arq_statusp->sts_rqpkt_status),
1330 sizeof (struct scsi_status));
1331 arq_statusp->sts_rqpkt_reason = CMD_CMPLT;
1332 arq_statusp->sts_rqpkt_resid = 0;
1333 arq_statusp->sts_rqpkt_state = scsi_pktp->pkt_state;
1334 arq_statusp->sts_rqpkt_statistics =
1335 scsi_pktp->pkt_statistics;
1336 bcopy((caddr_t)&errorinfop->SenseInfo[0],
1337 (caddr_t)(&arq_statusp->sts_sensedata),
1338 CPQARY3_MIN(errorinfop->SenseLen,
1339 cpqary3_cmdpvtp->pvt_pkt->scb_len));
1340 scsi_pktp->pkt_state |= STATE_ARQ_DONE;
1341 }
1342 }
1343
1344 if (cpqary3_cmdpvtp->pvt_pkt->scsi_cmd_pkt->pkt_flags & FLAG_NOINTR) {
1345 cpqary3_cmdlist_release(cpqary3_cmdpvtp, CPQARY3_NO_MUTEX);
1346 } else {
1347 cpqary3_cmdlist_release(cpqary3_cmdpvtp, CPQARY3_NO_MUTEX);
1348
1349 if (scsi_pktp->pkt_comp) {
1350 mutex_exit(&cpqary3p->sw_mutex);
1351 (*scsi_pktp->pkt_comp)(scsi_pktp);
1352 mutex_enter(&cpqary3p->sw_mutex);
1353 }
1354 }
1355 }
1356
1357 static uint8_t
cpqary3_is_scsi_read_write(struct scsi_pkt * scsi_pktp)1358 cpqary3_is_scsi_read_write(struct scsi_pkt *scsi_pktp)
1359 {
1360 /*
1361 * In the scsi packet structure, the first byte is the SCSI Command
1362 * OpCode. We check to see if it is any one of the SCSI Read or Write
1363 * opcodes.
1364 */
1365
1366 switch (scsi_pktp->pkt_cdbp[0]) {
1367 case SCSI_READ_6:
1368 case SCSI_READ_10:
1369 case SCSI_READ_12:
1370 case SCSI_WRITE_6:
1371 case SCSI_WRITE_10:
1372 case SCSI_WRITE_12:
1373 return (1);
1374
1375 default:
1376 return (0);
1377 }
1378 }
1379