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 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 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 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 * 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 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 484 default: 485 cmn_err(CE_PANIC, "CPQary3: Unexpected ERROR " 486 "returned from Call to Bind Buffer " 487 "to Handle : 0x%X", i); 488 } 489 490 ddi_dma_free_handle(&cpqary3_pktp->cmd_dmahandle); 491 cpqary3_pktp->cmd_dmahandle = NULL; 492 cpqary3_pktp->cmd_flags &= ~CFLAG_DMAVALID; 493 494 return (CPQARY3_FAILURE); 495 496 } 497 498 /* 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 503 * Calls : None 504 * Return Values: SUCCESS / FAILURE 505 */ 506 static int 507 cpqary3_dma_move(struct scsi_pkt *scsi_pktp, struct buf *bp, 508 cpqary3_t *cpqary3p) 509 { 510 uint32_t i = 0; 511 cpqary3_pkt_t *cpqary3_pktp; 512 513 cpqary3_pktp = PKT2PVTPKT(scsi_pktp); 514 515 /* 516 * If there are no more cookies remaining in this window, 517 * must move to the next window first. 518 */ 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); 524 525 /* Shall not be able to move if last window */ 526 if (++cpqary3_pktp->cmd_curwin >= cpqary3_pktp->cmd_nwin) 527 return (CPQARY3_FAILURE); 528 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); 535 536 cpqary3_pktp->cmd_cookie = 0; 537 } else { 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]); 541 } 542 543 /* Get remaining cookies in this window, up to our maximum */ 544 for (;;) { 545 cpqary3_pktp->cmd_dmacount += 546 cpqary3_pktp->cmd_dmacookies[i++].dmac_size; 547 cpqary3_pktp->cmd_cookie++; 548 /* SG */ 549 /* no. of DATA SEGMENTS */ 550 if (i == cpqary3p->sg_cnt || 551 cpqary3_pktp->cmd_cookie == cpqary3_pktp->cmd_ncookies) 552 break; 553 /* SG */ 554 555 ddi_dma_nextcookie(cpqary3_pktp->cmd_dmahandle, 556 &cpqary3_pktp->cmd_dmacookies[i]); 557 } 558 559 cpqary3_pktp->cmd_cookiecnt = i; 560 scsi_pktp->pkt_resid = bp->b_bcount - cpqary3_pktp->cmd_dmacount; 561 562 return (CPQARY3_SUCCESS); 563 564 } 565 566 /* 567 * Function : cpqary3_transport() 568 * Description : This routine services requests from the OS that are 569 * directed towards the targets.(any SCSI command) 570 * Called By : kernel 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 575 * at the moment. 576 * TRAN_FATAL_ERROR: A target no longer exists. 577 */ 578 static int 579 cpqary3_transport(struct scsi_address *sa, struct scsi_pkt *scsi_pktp) 580 { 581 cpqary3_t *ctlr; 582 cpqary3_pkt_t *cpqary3_pktp; 583 cpqary3_tgt_t *tgtp; 584 cpqary3_cmdpvt_t *memp; 585 586 ASSERT(sa != NULL); 587 ctlr = SA2CTLR(sa); 588 cpqary3_pktp = PKT2PVTPKT(scsi_pktp); 589 tgtp = ctlr->cpqary3_tgtp[SA2TGT(sa)]; 590 591 if (!tgtp) 592 return (TRAN_FATAL_ERROR); 593 594 if (tgtp->type == CPQARY3_TARGET_NONE) 595 return (TRAN_FATAL_ERROR); 596 597 if (cpqary3_additional_cmd(scsi_pktp, ctlr)) 598 return (TRAN_ACCEPT); 599 600 /* 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 609 * return TRAN_ACCEPT 610 */ 611 612 if (NULL == (memp = cpqary3_cmdlist_occupy(ctlr))) 613 return (TRAN_BUSY); 614 615 cpqary3_pktp->memp = memp; 616 memp->pvt_pkt = cpqary3_pktp; 617 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); 622 } 623 /* SG */ 624 ASSERT(cpqary3_pktp->cmd_cookiecnt <= ctlr->sg_cnt); 625 /* SG */ 626 627 /* PERF */ 628 memp->complete = cpqary3_oscmd_complete; 629 /* PERF */ 630 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)); 635 } 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); 643 } 644 /* CONTROLLER_LOCKUP */ 645 mutex_exit(&ctlr->hw_mutex); 646 break; 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); 653 } 654 655 return (TRAN_ACCEPT); 656 } 657 658 /* 659 * Function : cpqary3_dmafree 660 * Description : This routine de-allocates previously allocated 661 * DMA resources. 662 * Called By : kernel 663 * Parameters : SCSI address, SCSI packet 664 * Calls : None 665 * Return Values: None 666 */ 667 /* ARGSUSED */ 668 static void 669 cpqary3_dmafree(struct scsi_address *sa, struct scsi_pkt *scsi_pktp) 670 { 671 cpqary3_pkt_t *cpqary3_pktp; 672 673 cpqary3_pktp = PKT2PVTPKT(scsi_pktp); 674 675 /* 676 * If any DMA was succesfully attempted earlier, free all allocated 677 * resources 678 */ 679 680 if (cpqary3_pktp->cmd_flags & CFLAG_DMAVALID) { 681 if (!cpqary3_pktp->cmd_dmahandle) { 682 DTRACE_PROBE(dmafree_null); 683 return; 684 } 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; 689 } 690 } 691 692 /* 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 696 * ddi_dma_sync(). 697 * Called By : kernel 698 * Parameters : SCSI address, SCSI packet 699 * Calls : None 700 * Return Values: None 701 */ 702 /* ARGSUSED */ 703 static void 704 cpqary3_dma_sync(struct scsi_address *sa, struct scsi_pkt *scsi_pktp) 705 { 706 cpqary3_pkt_t *cpqary3_pktp = PKT2PVTPKT(scsi_pktp); 707 708 /* 709 * Check whether DMA was attempted successfully earlier 710 * If yes and 711 * if the command flags is write, then synchronise the device else 712 * synchronise the CPU 713 */ 714 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); 720 } 721 } 722 723 /* 724 * Function : cpqary3_destroy_pkt 725 * Description : This routine de-allocates previously allocated 726 * resources for the SCSI packet. 727 * Called By : kernel 728 * Parameters : SCSI address, SCSI packet 729 * Calls : None 730 * Return Values: None 731 */ 732 static void 733 cpqary3_destroy_pkt(struct scsi_address *sa, struct scsi_pkt *scsi_pktp) 734 { 735 cpqary3_pkt_t *cpqary3_pktp; 736 737 cpqary3_pktp = PKT2PVTPKT(scsi_pktp); 738 739 /* 740 * Deallocate DMA Resources, if allocated. 741 * Free the SCSI Packet. 742 */ 743 744 if (cpqary3_pktp->cmd_flags & CFLAG_DMAVALID) { 745 if (!cpqary3_pktp->cmd_dmahandle) { 746 DTRACE_PROBE(dmafree_null); 747 } else { 748 cpqary3_pktp->cmd_flags &= ~CFLAG_DMAVALID; 749 750 (void) ddi_dma_unbind_handle( 751 cpqary3_pktp->cmd_dmahandle); 752 ddi_dma_free_handle(&cpqary3_pktp->cmd_dmahandle); 753 754 cpqary3_pktp->cmd_dmahandle = NULL; 755 } 756 } 757 758 scsi_hba_pkt_free(sa, scsi_pktp); 759 } 760 761 /* 762 * Function : cpqary3_reset 763 * Description : This routine resets a SCSI bus/target. 764 * Called By : kernel 765 * Parameters : SCSI address, reset level required 766 * Calls : None 767 * Return Values: SUCCESS 768 */ 769 /* ARGSUSED */ 770 static int 771 cpqary3_reset(struct scsi_address *sa, int level) 772 { 773 /* 774 * Fix for Crash seen during RAID 0 Drive removal - 775 * just return CPQARY3_SUCCESS on reset request 776 */ 777 return (CPQARY3_SUCCESS); 778 } 779 780 /* 781 * Function : cpqary3_abort() 782 * Description : This routine aborts a particular command or all commands 783 * directed towards a target. 784 * Called By : kernel 785 * Parameters : SCSI address, SCSI packet 786 * Calls : None 787 * Return Values: SUCCESS / FAILURE 788 * [ abort of concernd command(s) was a success or 789 * a failure. ] 790 */ 791 static int 792 cpqary3_abort(struct scsi_address *sa, struct scsi_pkt *scsi_pktp) 793 { 794 uint32_t tid; 795 cpqary3_t *ctlr; 796 797 ASSERT(sa != NULL); 798 tid = SA2TGT(sa); 799 ctlr = SA2CTLR(sa); 800 801 /* 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. 806 */ 807 808 if (!scsi_pktp) { 809 return (cpqary3_send_abortcmd(ctlr, tid, 810 (CommandList_t *)NULL)); 811 } else { 812 return (cpqary3_send_abortcmd(ctlr, tid, SP2CMD(scsi_pktp))); 813 } 814 } 815 816 /* 817 * Function : cpqary3_getcap 818 * Description : This routine is called to get the current value of a 819 * capability.(SCSI transport capability) 820 * Called By : kernel 821 * Parameters : SCSI address, capability identifier, target(s) affected 822 * Calls : None 823 * Return Values: current value of capability / -1 (if unsupported) 824 */ 825 static int 826 cpqary3_getcap(struct scsi_address *sa, char *capstr, int tgtonly) 827 { 828 int index; 829 cpqary3_t *ctlr = SA2CTLR(sa); 830 cpqary3_tgt_t *tgtp = ctlr->cpqary3_tgtp[SA2TGT(sa)]; 831 832 /* 833 * If requested Capability is not supported, return -1. 834 */ 835 if (DDI_FAILURE == (index = scsi_hba_lookup_capstr(capstr))) 836 return (CAP_NOT_DEFINED); 837 838 /* 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. 842 */ 843 if (tgtonly == 0) { /* all targets */ 844 DTRACE_PROBE1(getcap_alltgt, int, index); 845 return (CAP_NOT_DEFINED); 846 } 847 848 DTRACE_PROBE1(getcap_index, int, index); 849 850 switch (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); 859 case SCSI_CAP_ARQ: 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: 864 return (1); 865 case SCSI_CAP_TAGGED_QING: 866 return (1); 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: 874 return (0); 875 default: 876 return (CAP_NOT_DEFINED); 877 } 878 } 879 880 /* 881 * Function : cpqary3_setcap 882 * Description : This routine is called to set the current value of a 883 * capability.(SCSI transport capability) 884 * Called By : kernel 885 * Parameters : SCSI address, capability identifier, 886 * new capability value, target(s) affected 887 * Calls : None 888 * Return Values: SUCCESS / FAILURE / -1 (if capability is unsupported) 889 */ 890 /* ARGSUSED */ 891 static int 892 cpqary3_setcap(struct scsi_address *sa, char *capstr, int value, int tgtonly) 893 { 894 int index; 895 int retstatus = CAP_NOT_DEFINED; 896 897 /* 898 * If requested Capability is not supported, return -1. 899 */ 900 if ((index = scsi_hba_lookup_capstr(capstr)) == DDI_FAILURE) 901 return (retstatus); 902 903 /* 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 907 * capability. 908 */ 909 if (!tgtonly) { 910 DTRACE_PROBE1(setcap_alltgt, int, index); 911 return (retstatus); 912 } 913 914 DTRACE_PROBE1(setcap_index, int, index); 915 916 switch (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); 925 case SCSI_CAP_ARQ: 926 return (1); 927 case SCSI_CAP_INITIATOR_ID: 928 return (CAP_CHG_NOT_ALLOWED); 929 case SCSI_CAP_UNTAGGED_QING: 930 return (1); 931 case SCSI_CAP_TAGGED_QING: 932 return (1); 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); 941 default: 942 return (CAP_NOT_DEFINED); 943 } 944 } 945 946 /* 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 956 */ 957 static int 958 cpqary3_handle_flag_nointr(cpqary3_cmdpvt_t *memp, struct scsi_pkt *scsi_pktp) 959 { 960 uint32_t tag; 961 uint32_t simple_tag; 962 uint32_t i; 963 cpqary3_t *ctlr; 964 cpqary3_cmdpvt_t *cpqary3_cmdpvtp; 965 uint32_t CmdsOutMax; 966 uint32_t no_cmds; 967 968 RETURN_FAILURE_IF_NULL(memp); 969 tag = memp->tag.tag_value; 970 ctlr = memp->ctlr; 971 ctlr->poll_flag = CPQARY3_FALSE; 972 973 /* 974 * Before sumitting this command, ensure all commands pending 975 * with the controller are completed. 976 */ 977 978 cpqary3_intr_onoff(ctlr, CPQARY3_INTR_DISABLE); 979 if (ctlr->host_support & 0x4) 980 cpqary3_lockup_intr_onoff(ctlr, CPQARY3_LOCKUP_INTR_DISABLE); 981 982 no_cmds = (uint32_t)((ctlr->ctlr_maxcmds / 3) * NO_OF_CMDLIST_IN_A_BLK); 983 mutex_enter(&ctlr->sw_mutex); 984 985 for (;;) { 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); 990 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 == 998 CPQARY3_TIMEOUT)) { 999 continue; 1000 } 1001 } else { 1002 if (cpqary3_cmdpvtp->cmdpvt_flag == 1003 CPQARY3_TIMEOUT) { 1004 continue; 1005 } 1006 } 1007 ctlr->poll_flag = CPQARY3_TRUE; 1008 } 1009 /* NOE */ 1010 1011 if (ctlr->poll_flag == CPQARY3_TRUE) { 1012 break; 1013 } 1014 } 1015 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; 1022 if ((simple_tag >> 1023 CPQARY3_GET_MEM_TAG) >= 1024 ((CmdsOutMax / 3) * 3)) { 1025 cmn_err(CE_WARN, 1026 "CPQary3 : HBA returned " 1027 "Spurious Tag"); 1028 return (CPQARY3_FAILURE); 1029 } 1030 1031 cpqary3_cmdpvtp = 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( 1038 cpqary3_cmdpvtp); 1039 } 1040 } else { 1041 mutex_exit(&ctlr->sw_mutex); 1042 if (CPQARY3_SUCCESS != cpqary3_retrieve(ctlr)) { 1043 drv_usecwait(1000); 1044 } 1045 mutex_enter(&ctlr->sw_mutex); /* Changes */ 1046 } 1047 } else { 1048 break; 1049 } 1050 } 1051 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); 1058 } 1059 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); 1072 } else { 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); 1079 } 1080 return (TRAN_ACCEPT); 1081 } 1082 } 1083 1084 /* 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 1091 */ 1092 static int 1093 cpqary3_poll(cpqary3_t *ctlr, uint32_t tag) 1094 { 1095 uint32_t ii = 0; 1096 1097 RETURN_FAILURE_IF_NULL(ctlr); 1098 1099 /* 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. 1106 */ 1107 1108 for (;;) { /* this function is called with both the locks held */ 1109 if (CPQARY3_SUCCESS != cpqary3_poll_retrieve(ctlr, tag)) { 1110 ii++; 1111 if (ii > 120000) 1112 return (CPQARY3_FAILURE); 1113 drv_usecwait(500); 1114 continue; 1115 } 1116 break; 1117 } 1118 1119 return (CPQARY3_SUCCESS); 1120 } 1121 1122 static int 1123 cpqary3_additional_cmd(struct scsi_pkt *scsi_pktp, cpqary3_t *ctlr) 1124 { 1125 struct scsi_arq_status *arqstat; 1126 /* LINTED: alignment */ 1127 arqstat = (struct scsi_arq_status *)(scsi_pktp->pkt_scbp); 1128 1129 switch (scsi_pktp->pkt_cdbp[0]) { 1130 case 0x35: /* Synchronize Cache */ 1131 1132 cpqary3_flush_cache(ctlr); 1133 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; 1138 1139 if (scsi_pktp->pkt_comp) { 1140 (*scsi_pktp->pkt_comp)(scsi_pktp); 1141 } 1142 1143 return (1); 1144 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."); 1150 1151 return (0); 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; 1166 1167 if (scsi_pktp->pkt_comp) { 1168 (*scsi_pktp->pkt_comp)(scsi_pktp); 1169 } 1170 return (1); 1171 } 1172 1173 return (0); 1174 } 1175 1176 /* PERF */ 1177 /* 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 1192 */ 1193 void 1194 cpqary3_oscmd_complete(cpqary3_cmdpvt_t *cpqary3_cmdpvtp) 1195 { 1196 cpqary3_t *cpqary3p; 1197 ErrorInfo_t *errorinfop; 1198 CommandList_t *cmdlistp; 1199 struct scsi_pkt *scsi_pktp; 1200 1201 ASSERT(cpqary3_cmdpvtp != NULL); 1202 1203 if (CPQARY3_TIMEOUT == cpqary3_cmdpvtp->cmdpvt_flag) { 1204 cpqary3_cmdlist_release(cpqary3_cmdpvtp, 1205 CPQARY3_NO_MUTEX); 1206 return; 1207 } 1208 1209 cpqary3p = cpqary3_cmdpvtp->ctlr; 1210 cmdlistp = cpqary3_cmdpvtp->cmdlist_memaddr; 1211 errorinfop = cpqary3_cmdpvtp->errorinfop; 1212 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; 1220 1221 if (cpqary3_cmdpvtp->pvt_pkt->scsi_cmd_pkt->pkt_flags & 1222 FLAG_NOINTR) { 1223 cpqary3_cmdlist_release(cpqary3_cmdpvtp, 1224 CPQARY3_NO_MUTEX); 1225 } else { 1226 cpqary3_cmdlist_release(cpqary3_cmdpvtp, 1227 CPQARY3_NO_MUTEX); 1228 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); 1233 } 1234 } 1235 return; 1236 } else { 1237 scsi_pktp = cpqary3_cmdpvtp->pvt_pkt->scsi_cmd_pkt; 1238 } 1239 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; 1245 break; 1246 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; 1252 break; 1253 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; 1258 break; 1259 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; 1264 break; 1265 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; 1272 break; 1273 1274 case CISS_CMD_ABORT_FAILED: 1275 break; 1276 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; 1281 break; 1282 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; 1290 break; 1291 } 1292 /* FALLTHROUGH */ 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; 1299 break; 1300 1301 default: /* Should never Occur !!! */ 1302 scsi_pktp->pkt_reason = CMD_TRAN_ERR; 1303 break; 1304 } 1305 1306 1307 /* 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. 1312 */ 1313 1314 if ((errorinfop->ScsiStatus == SCSI_CHECK_CONDITION) || 1315 (errorinfop->ScsiStatus == SCSI_COMMAND_TERMINATED)) { 1316 if (errorinfop->SenseLen) { 1317 struct scsi_arq_status *arq_statusp; 1318 arq_statusp = 1319 /* LINTED: alignment */ 1320 (struct scsi_arq_status *)scsi_pktp->pkt_scbp; 1321 1322 if ((errorinfop->ScsiStatus == SCSI_CHECK_CONDITION)) { 1323 arq_statusp->sts_status.sts_chk = (uint8_t)1; 1324 } else { 1325 arq_statusp->sts_status.sts_chk = (uint8_t)1; 1326 arq_statusp->sts_status.sts_scsi2 = (uint8_t)1; 1327 } 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; 1340 } 1341 } 1342 1343 if (cpqary3_cmdpvtp->pvt_pkt->scsi_cmd_pkt->pkt_flags & FLAG_NOINTR) { 1344 cpqary3_cmdlist_release(cpqary3_cmdpvtp, CPQARY3_NO_MUTEX); 1345 } else { 1346 cpqary3_cmdlist_release(cpqary3_cmdpvtp, CPQARY3_NO_MUTEX); 1347 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); 1352 } 1353 } 1354 } 1355 1356 static uint8_t 1357 cpqary3_is_scsi_read_write(struct scsi_pkt *scsi_pktp) 1358 { 1359 /* 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 1362 * opcodes. 1363 */ 1364 1365 switch (scsi_pktp->pkt_cdbp[0]) { 1366 case SCSI_READ_6: 1367 case SCSI_READ_10: 1368 case SCSI_READ_12: 1369 case SCSI_WRITE_6: 1370 case SCSI_WRITE_10: 1371 case SCSI_WRITE_12: 1372 return (1); 1373 1374 default: 1375 return (0); 1376 } 1377 } 1378