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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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