1 /* 2 * CDDL HEADER START 3 * 4 * The contents of this file are subject to the terms of the 5 * Common Development and Distribution License (the "License"). 6 * You may not use this file except in compliance with the License. 7 * 8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9 * or http://www.opensolaris.org/os/licensing. 10 * See the License for the specific language governing permissions 11 * and limitations under the License. 12 * 13 * When distributing Covered Code, include this CDDL HEADER in each 14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15 * If applicable, add the following below this CDDL HEADER, with the 16 * fields enclosed by brackets "[]" replaced with your own identifying 17 * information: Portions Copyright [yyyy] [name of copyright owner] 18 * 19 * CDDL HEADER END 20 * 21 * 22 * Copyright 2009 Sun Microsystems, Inc. All rights reserved. 23 * Use is subject to license terms. 24 */ 25 /* 26 * SATA midlayer interface for PMC driver. 27 */ 28 29 #include <sys/scsi/adapters/pmcs/pmcs.h> 30 31 static void 32 SATAcopy(pmcs_cmd_t *sp, void *kbuf, uint32_t amt) 33 { 34 struct buf *bp = scsi_pkt2bp(CMD2PKT(sp)); 35 36 bp_mapin(scsi_pkt2bp(CMD2PKT(sp))); 37 /* There is only one direction currently */ 38 (void) memcpy(bp->b_un.b_addr, kbuf, amt); 39 CMD2PKT(sp)->pkt_resid -= amt; 40 CMD2PKT(sp)->pkt_state |= STATE_XFERRED_DATA; 41 bp_mapout(scsi_pkt2bp(CMD2PKT(sp))); 42 } 43 44 /* 45 * Run a non block-io command. Some commands are interpreted 46 * out of extant data. Some imply actually running a SATA command. 47 * 48 * Returns zero if we were able to run. 49 * 50 * Returns -1 only if other commands are active, either another 51 * command here or regular I/O active. 52 * 53 * Called with PHY lock and xp statlock held. 54 */ 55 #define SRESPSZ 132 56 CTASSERT(SRESPSZ == sizeof (struct scsi_inquiry)); 57 58 static int 59 pmcs_sata_special_work(pmcs_hw_t *pwp, pmcs_xscsi_t *xp) 60 { 61 int i; 62 int saq; 63 pmcs_cmd_t *sp; 64 struct scsi_pkt *pkt; 65 pmcs_phy_t *pptr; 66 uint8_t rp[SRESPSZ]; 67 ata_identify_t *id; 68 uint32_t amt = 0; 69 uint8_t key = 0x05; /* illegal command */ 70 uint8_t asc = 0; 71 uint8_t ascq = 0; 72 uint8_t status = STATUS_GOOD; 73 74 if (xp->actv_cnt) { 75 pmcs_prt(pwp, PMCS_PRT_DEBUG1, NULL, xp, 76 "%s: target %p actv count %u", 77 __func__, (void *)xp, xp->actv_cnt); 78 return (-1); 79 } 80 if (xp->special_running) { 81 pmcs_prt(pwp, PMCS_PRT_DEBUG, NULL, xp, 82 "%s: target %p special running already", 83 __func__, (void *)xp); 84 return (-1); 85 } 86 xp->special_needed = 0; 87 88 /* 89 * We're now running special. 90 */ 91 xp->special_running = 1; 92 pptr = xp->phy; 93 94 sp = STAILQ_FIRST(&xp->sq); 95 if (sp == NULL) { 96 xp->special_running = 0; 97 return (0); 98 } 99 100 pkt = CMD2PKT(sp); 101 pmcs_prt(pwp, PMCS_PRT_DEBUG2, pptr, xp, 102 "%s: target %p cmd %p cdb0 %x with actv_cnt %u", 103 __func__, (void *)xp, (void *)sp, pkt->pkt_cdbp[0], xp->actv_cnt); 104 105 if (pkt->pkt_cdbp[0] == SCMD_INQUIRY || 106 pkt->pkt_cdbp[0] == SCMD_READ_CAPACITY) { 107 int retval; 108 109 if (pmcs_acquire_scratch(pwp, B_FALSE)) { 110 xp->special_running = 0; 111 return (-1); 112 } 113 saq = 1; 114 115 mutex_exit(&xp->statlock); 116 retval = pmcs_sata_identify(pwp, pptr); 117 mutex_enter(&xp->statlock); 118 119 if (retval) { 120 pmcs_release_scratch(pwp); 121 xp->special_running = 0; 122 123 pmcs_prt(pwp, PMCS_PRT_DEBUG2, pptr, xp, 124 "%s: target %p identify failed %x", 125 __func__, (void *)xp, retval); 126 /* 127 * If the failure is due to not being 128 * able to get resources, return such 129 * that we'll try later. Otherwise, 130 * fail current command. 131 */ 132 if (retval == ENOMEM) { 133 pmcs_prt(pwp, PMCS_PRT_DEBUG, pptr, xp, 134 "%s: sata identify failed (ENOMEM) for " 135 "cmd %p", __func__, (void *)sp); 136 return (-1); 137 } 138 pkt->pkt_state = STATE_GOT_BUS | STATE_GOT_TARGET | 139 STATE_SENT_CMD; 140 if (retval == ETIMEDOUT) { 141 pkt->pkt_reason = CMD_TIMEOUT; 142 pkt->pkt_statistics |= STAT_TIMEOUT; 143 } else { 144 pkt->pkt_reason = CMD_TRAN_ERR; 145 } 146 goto out; 147 } 148 149 id = pwp->scratch; 150 151 /* 152 * Check to see if this device is an NCQ capable device. 153 * Yes, we'll end up doing this check for every INQUIRY 154 * if indeed we *are* only a pio device, but this is so 155 * infrequent that it's not really worth an extra bitfield. 156 * 157 * Note that PIO mode here means that the PMCS firmware 158 * performs PIO- not us. 159 */ 160 if (xp->ncq == 0) { 161 /* 162 * Reset existing stuff. 163 */ 164 xp->pio = 0; 165 xp->qdepth = 1; 166 xp->tagmap = 0; 167 168 if (id->word76 != 0 && id->word76 != 0xffff && 169 (LE_16(id->word76) & (1 << 8))) { 170 xp->ncq = 1; 171 xp->qdepth = (LE_16(id->word75) & 0x1f) + 1; 172 pmcs_prt(pwp, PMCS_PRT_DEBUG_CONFIG, pptr, xp, 173 "%s: device %s supports NCQ %u deep", 174 __func__, xp->phy->path, xp->qdepth); 175 } else { 176 /* 177 * Default back to PIO. 178 * 179 * Note that non-FPDMA would still be possible, 180 * but for this specific configuration, if it's 181 * not NCQ it's safest to assume PIO. 182 */ 183 xp->pio = 1; 184 pmcs_prt(pwp, PMCS_PRT_DEBUG_CONFIG, pptr, xp, 185 "%s: device %s assumed PIO", 186 __func__, xp->phy->path); 187 } 188 } 189 } else { 190 saq = 0; 191 id = NULL; 192 } 193 194 bzero(rp, SRESPSZ); 195 196 switch (pkt->pkt_cdbp[0]) { 197 case SCMD_INQUIRY: 198 { 199 struct scsi_inquiry *inqp; 200 uint16_t *a, *b; 201 202 /* Check for illegal bits */ 203 if ((pkt->pkt_cdbp[1] & 0xfc) || pkt->pkt_cdbp[5]) { 204 status = STATUS_CHECK; 205 asc = 0x24; /* invalid field in cdb */ 206 break; 207 } 208 if (pkt->pkt_cdbp[1] & 0x1) { 209 switch (pkt->pkt_cdbp[2]) { 210 case 0x0: 211 rp[3] = 3; 212 rp[5] = 0x80; 213 rp[6] = 0x83; 214 amt = 7; 215 break; 216 case 0x80: 217 rp[1] = 0x80; 218 rp[3] = 0x14; 219 a = (void *) &rp[4]; 220 b = id->model_number; 221 for (i = 0; i < 5; i++) { 222 *a = ddi_swap16(*b); 223 a++; 224 b++; 225 } 226 amt = 24; 227 break; 228 case 0x83: 229 rp[1] = 0x83; 230 if ((LE_16(id->word87) & 0x100) && 231 (LE_16(id->word108) >> 12) == 5) { 232 rp[3] = 12; 233 rp[4] = 1; 234 rp[5] = 3; 235 rp[7] = 8; 236 rp[8] = LE_16(id->word108) >> 8; 237 rp[9] = LE_16(id->word108); 238 rp[10] = LE_16(id->word109) >> 8; 239 rp[11] = LE_16(id->word109); 240 rp[12] = LE_16(id->word110) >> 8; 241 rp[13] = LE_16(id->word110); 242 rp[14] = LE_16(id->word111) >> 8; 243 rp[15] = LE_16(id->word111); 244 amt = 16; 245 } else { 246 rp[3] = 64; 247 rp[4] = 2; 248 rp[5] = 1; 249 rp[7] = 60; 250 rp[8] = 'A'; 251 rp[9] = 'T'; 252 rp[10] = 'A'; 253 rp[11] = ' '; 254 rp[12] = ' '; 255 rp[13] = ' '; 256 rp[14] = ' '; 257 rp[15] = ' '; 258 a = (void *) &rp[16]; 259 b = id->model_number; 260 for (i = 0; i < 20; i++) { 261 *a = ddi_swap16(*b); 262 a++; 263 b++; 264 } 265 a = (void *) &rp[40]; 266 b = id->serial_number; 267 for (i = 0; i < 10; i++) { 268 *a = ddi_swap16(*b); 269 a++; 270 b++; 271 } 272 amt = 68; 273 } 274 break; 275 default: 276 status = STATUS_CHECK; 277 asc = 0x24; /* invalid field in cdb */ 278 break; 279 } 280 } else { 281 inqp = (struct scsi_inquiry *)rp; 282 inqp->inq_qual = 0; 283 inqp->inq_ansi = 5; /* spc3 */ 284 inqp->inq_rdf = 2; /* response format 2 */ 285 inqp->inq_len = 32; 286 287 if (xp->ncq && (xp->qdepth > 1)) { 288 inqp->inq_cmdque = 1; 289 } 290 291 (void) memcpy(inqp->inq_vid, "ATA ", 8); 292 293 a = (void *)inqp->inq_pid; 294 b = id->model_number; 295 for (i = 0; i < 8; i++) { 296 *a = ddi_swap16(*b); 297 a++; 298 b++; 299 } 300 if (id->firmware_revision[2] == 0x2020 && 301 id->firmware_revision[3] == 0x2020) { 302 inqp->inq_revision[0] = 303 ddi_swap16(id->firmware_revision[0]) >> 8; 304 inqp->inq_revision[1] = 305 ddi_swap16(id->firmware_revision[0]); 306 inqp->inq_revision[2] = 307 ddi_swap16(id->firmware_revision[1]) >> 8; 308 inqp->inq_revision[3] = 309 ddi_swap16(id->firmware_revision[1]); 310 } else { 311 inqp->inq_revision[0] = 312 ddi_swap16(id->firmware_revision[2]) >> 8; 313 inqp->inq_revision[1] = 314 ddi_swap16(id->firmware_revision[2]); 315 inqp->inq_revision[2] = 316 ddi_swap16(id->firmware_revision[3]) >> 8; 317 inqp->inq_revision[3] = 318 ddi_swap16(id->firmware_revision[3]); 319 } 320 amt = 36; 321 } 322 amt = pmcs_set_resid(pkt, amt, pkt->pkt_cdbp[4]); 323 if (amt) { 324 if (xp->actv_cnt) { 325 xp->special_needed = 1; 326 xp->special_running = 0; 327 pmcs_prt(pwp, PMCS_PRT_DEBUG, pptr, xp, 328 "%s: @ line %d", __func__, __LINE__); 329 if (saq) { 330 pmcs_release_scratch(pwp); 331 } 332 return (-1); 333 } 334 SATAcopy(sp, rp, amt); 335 } 336 break; 337 } 338 case SCMD_READ_CAPACITY: 339 { 340 uint64_t last_block; 341 uint32_t block_size = 512; /* XXXX */ 342 343 xp->capacity = LBA_CAPACITY(id); 344 last_block = xp->capacity - 1; 345 /* Check for illegal bits */ 346 if ((pkt->pkt_cdbp[1] & 0xfe) || pkt->pkt_cdbp[6] || 347 (pkt->pkt_cdbp[8] & 0xfe) || pkt->pkt_cdbp[7] || 348 pkt->pkt_cdbp[9]) { 349 status = STATUS_CHECK; 350 asc = 0x24; /* invalid field in cdb */ 351 break; 352 } 353 for (i = 1; i < 10; i++) { 354 if (pkt->pkt_cdbp[i]) { 355 status = STATUS_CHECK; 356 asc = 0x24; /* invalid field in cdb */ 357 break; 358 } 359 } 360 if (status != STATUS_GOOD) { 361 break; 362 } 363 if (last_block > 0xffffffffULL) { 364 last_block = 0xffffffffULL; 365 } 366 rp[0] = (last_block >> 24) & 0xff; 367 rp[1] = (last_block >> 16) & 0xff; 368 rp[2] = (last_block >> 8) & 0xff; 369 rp[3] = (last_block) & 0xff; 370 rp[4] = (block_size >> 24) & 0xff; 371 rp[5] = (block_size >> 16) & 0xff; 372 rp[6] = (block_size >> 8) & 0xff; 373 rp[7] = (block_size) & 0xff; 374 amt = 8; 375 amt = pmcs_set_resid(pkt, amt, 8); 376 if (amt) { 377 if (xp->actv_cnt) { 378 xp->special_needed = 1; 379 xp->special_running = 0; 380 pmcs_prt(pwp, PMCS_PRT_DEBUG, pptr, xp, 381 "%s: @ line %d", __func__, __LINE__); 382 if (saq) { 383 pmcs_release_scratch(pwp); 384 } 385 return (-1); 386 } 387 SATAcopy(sp, rp, amt); 388 } 389 break; 390 } 391 case SCMD_REPORT_LUNS: { 392 int rl_len; 393 394 /* Check for illegal bits */ 395 if (pkt->pkt_cdbp[1] || pkt->pkt_cdbp[3] || pkt->pkt_cdbp[4] || 396 pkt->pkt_cdbp[5] || pkt->pkt_cdbp[10] || 397 pkt->pkt_cdbp[11]) { 398 status = STATUS_CHECK; 399 asc = 0x24; /* invalid field in cdb */ 400 break; 401 } 402 403 rp[3] = 8; 404 rl_len = 16; /* list length (4) + reserved (4) + 1 LUN (8) */ 405 amt = rl_len; 406 amt = pmcs_set_resid(pkt, amt, rl_len); 407 408 if (amt) { 409 if (xp->actv_cnt) { 410 xp->special_needed = 1; 411 xp->special_running = 0; 412 pmcs_prt(pwp, PMCS_PRT_DEBUG, pptr, xp, 413 "%s: @ line %d", __func__, __LINE__); 414 if (saq) { 415 pmcs_release_scratch(pwp); 416 } 417 return (-1); 418 } 419 SATAcopy(sp, rp, rl_len); 420 } 421 break; 422 } 423 424 case SCMD_REQUEST_SENSE: 425 /* Check for illegal bits */ 426 if ((pkt->pkt_cdbp[1] & 0xfe) || pkt->pkt_cdbp[2] || 427 pkt->pkt_cdbp[3] || pkt->pkt_cdbp[5]) { 428 status = STATUS_CHECK; 429 asc = 0x24; /* invalid field in cdb */ 430 break; 431 } 432 rp[0] = 0xf0; 433 amt = 18; 434 amt = pmcs_set_resid(pkt, amt, pkt->pkt_cdbp[4]); 435 if (amt) { 436 if (xp->actv_cnt) { 437 xp->special_needed = 1; 438 xp->special_running = 0; 439 pmcs_prt(pwp, PMCS_PRT_DEBUG, pptr, xp, 440 "%s: @ line %d", __func__, __LINE__); 441 if (saq) { 442 pmcs_release_scratch(pwp); 443 } 444 return (-1); 445 } 446 SATAcopy(sp, rp, 18); 447 } 448 break; 449 case SCMD_START_STOP: 450 /* Check for illegal bits */ 451 if ((pkt->pkt_cdbp[1] & 0xfe) || pkt->pkt_cdbp[2] || 452 (pkt->pkt_cdbp[3] & 0xf0) || (pkt->pkt_cdbp[4] & 0x08) || 453 pkt->pkt_cdbp[5]) { 454 status = STATUS_CHECK; 455 asc = 0x24; /* invalid field in cdb */ 456 break; 457 } 458 break; 459 case SCMD_SYNCHRONIZE_CACHE: 460 /* Check for illegal bits */ 461 if ((pkt->pkt_cdbp[1] & 0xf8) || (pkt->pkt_cdbp[6] & 0xe0) || 462 pkt->pkt_cdbp[9]) { 463 status = STATUS_CHECK; 464 asc = 0x24; /* invalid field in cdb */ 465 break; 466 } 467 break; 468 case SCMD_TEST_UNIT_READY: 469 /* Check for illegal bits */ 470 if (pkt->pkt_cdbp[1] || pkt->pkt_cdbp[2] || pkt->pkt_cdbp[3] || 471 pkt->pkt_cdbp[4] || pkt->pkt_cdbp[5]) { 472 status = STATUS_CHECK; 473 asc = 0x24; /* invalid field in cdb */ 474 break; 475 } 476 if (xp->ca) { 477 status = STATUS_CHECK; 478 key = 0x6; 479 asc = 0x28; 480 xp->ca = 0; 481 } 482 break; 483 default: 484 asc = 0x20; /* invalid operation command code */ 485 status = STATUS_CHECK; 486 break; 487 } 488 if (status != STATUS_GOOD) { 489 bzero(rp, 18); 490 rp[0] = 0xf0; 491 rp[2] = key; 492 rp[12] = asc; 493 rp[13] = ascq; 494 pmcs_latch_status(pwp, sp, status, rp, 18, pptr->path); 495 } else { 496 pmcs_latch_status(pwp, sp, status, NULL, 0, pptr->path); 497 } 498 499 out: 500 STAILQ_REMOVE_HEAD(&xp->sq, cmd_next); 501 pmcs_prt(pwp, PMCS_PRT_DEBUG2, pptr, xp, 502 "%s: pkt %p tgt %u done reason=%x state=%x resid=%ld status=%x", 503 __func__, (void *)pkt, xp->target_num, pkt->pkt_reason, 504 pkt->pkt_state, pkt->pkt_resid, status); 505 506 if (saq) { 507 pmcs_release_scratch(pwp); 508 } 509 510 if (xp->draining) { 511 pmcs_prt(pwp, PMCS_PRT_DEBUG, pptr, xp, 512 "%s: waking up drain waiters", __func__); 513 cv_signal(&pwp->drain_cv); 514 } 515 516 mutex_exit(&xp->statlock); 517 mutex_enter(&pwp->cq_lock); 518 STAILQ_INSERT_TAIL(&pwp->cq, sp, cmd_next); 519 PMCS_CQ_RUN_LOCKED(pwp); 520 mutex_exit(&pwp->cq_lock); 521 mutex_enter(&xp->statlock); 522 xp->special_running = 0; 523 return (0); 524 } 525 526 /* 527 * Run all special commands queued up for a SATA device. 528 * We're only called if the caller knows we have work to do. 529 * 530 * We can't run them if things are still active for the device, 531 * return saying we didn't run anything. 532 * 533 * When we finish, wake up anyone waiting for active commands 534 * to go to zero. 535 * 536 * Called with PHY lock and xp statlock held. 537 */ 538 int 539 pmcs_run_sata_special(pmcs_hw_t *pwp, pmcs_xscsi_t *xp) 540 { 541 while (!STAILQ_EMPTY(&xp->sq)) { 542 if (pmcs_sata_special_work(pwp, xp)) { 543 return (-1); 544 } 545 } 546 return (0); 547 } 548 549 /* 550 * Search for SATA special commands to run and run them. 551 * If we succeed in running the special command(s), kick 552 * the normal commands into operation again. Call completion 553 * for any commands that were completed while we were here. 554 * 555 * Called unlocked. 556 */ 557 void 558 pmcs_sata_work(pmcs_hw_t *pwp) 559 { 560 pmcs_xscsi_t *xp; 561 int spinagain = 0; 562 uint16_t target; 563 564 for (target = 0; target < pwp->max_dev; target++) { 565 xp = pwp->targets[target]; 566 if ((xp == NULL) || (xp->phy == NULL)) { 567 continue; 568 } 569 pmcs_lock_phy(xp->phy); 570 mutex_enter(&xp->statlock); 571 if (STAILQ_EMPTY(&xp->sq)) { 572 mutex_exit(&xp->statlock); 573 pmcs_unlock_phy(xp->phy); 574 continue; 575 } 576 if (xp->actv_cnt) { 577 xp->special_needed = 1; 578 pmcs_prt(pwp, PMCS_PRT_DEBUG1, NULL, xp, 579 "%s: deferring until drained", __func__); 580 spinagain++; 581 } else { 582 if (pmcs_run_sata_special(pwp, xp)) { 583 spinagain++; 584 } 585 } 586 mutex_exit(&xp->statlock); 587 pmcs_unlock_phy(xp->phy); 588 } 589 590 if (spinagain) { 591 SCHEDULE_WORK(pwp, PMCS_WORK_SATA_RUN); 592 } else { 593 SCHEDULE_WORK(pwp, PMCS_WORK_RUN_QUEUES); 594 } 595 596 /* 597 * Run completion on any commands ready for it. 598 */ 599 PMCS_CQ_RUN(pwp); 600 } 601 602 /* 603 * Called with PHY lock held and scratch acquired 604 */ 605 int 606 pmcs_sata_identify(pmcs_hw_t *pwp, pmcs_phy_t *pptr) 607 { 608 fis_t fis; 609 fis[0] = (IDENTIFY_DEVICE << 16) | (1 << 15) | FIS_REG_H2DEV; 610 fis[1] = 0; 611 fis[2] = 0; 612 fis[3] = 0; 613 fis[4] = 0; 614 return (pmcs_run_sata_cmd(pwp, pptr, fis, SATA_PROTOCOL_PIO, 615 PMCIN_DATADIR_2_INI, sizeof (ata_identify_t))); 616 } 617 618 /* 619 * Called with PHY lock held and scratch held 620 */ 621 int 622 pmcs_run_sata_cmd(pmcs_hw_t *pwp, pmcs_phy_t *pptr, fis_t fis, uint32_t mode, 623 uint32_t ddir, uint32_t dlen) 624 { 625 struct pmcwork *pwrk; 626 uint32_t *ptr, msg[PMCS_MSG_SIZE]; 627 uint32_t iq, htag, status; 628 int i, result = 0; 629 630 pwrk = pmcs_gwork(pwp, PMCS_TAG_TYPE_WAIT, pptr); 631 if (pwrk == NULL) { 632 return (ENOMEM); 633 } 634 635 msg[0] = LE_32(PMCS_IOMB_IN_SAS(PMCS_OQ_IODONE, 636 PMCIN_SATA_HOST_IO_START)); 637 htag = pwrk->htag; 638 pwrk->arg = msg; 639 pwrk->dtype = SATA; 640 msg[1] = LE_32(pwrk->htag); 641 msg[2] = LE_32(pptr->device_id); 642 msg[3] = LE_32(dlen); 643 msg[4] = LE_32(mode | ddir); 644 if (dlen) { 645 if (ddir == PMCIN_DATADIR_2_DEV) { 646 if (ddi_dma_sync(pwp->cip_handles, 0, 0, 647 DDI_DMA_SYNC_FORDEV) != DDI_SUCCESS) { 648 pmcs_prt(pwp, PMCS_PRT_DEBUG, pptr, NULL, 649 "Condition check failed at %s():%d", 650 __func__, __LINE__); 651 } 652 } 653 msg[12] = LE_32(DWORD0(pwp->scratch_dma)); 654 msg[13] = LE_32(DWORD1(pwp->scratch_dma)); 655 msg[14] = LE_32(dlen); 656 msg[15] = 0; 657 } else { 658 msg[12] = 0; 659 msg[13] = 0; 660 msg[14] = 0; 661 msg[15] = 0; 662 } 663 for (i = 0; i < 5; i++) { 664 msg[5+i] = LE_32(fis[i]); 665 } 666 msg[10] = 0; 667 msg[11] = 0; 668 GET_IO_IQ_ENTRY(pwp, ptr, pptr->device_id, iq); 669 if (ptr == NULL) { 670 pmcs_pwork(pwp, pwrk); 671 return (ENOMEM); 672 } 673 COPY_MESSAGE(ptr, msg, PMCS_MSG_SIZE); 674 pwrk->state = PMCS_WORK_STATE_ONCHIP; 675 INC_IQ_ENTRY(pwp, iq); 676 677 pmcs_unlock_phy(pptr); 678 WAIT_FOR(pwrk, 1000, result); 679 pmcs_pwork(pwp, pwrk); 680 pmcs_lock_phy(pptr); 681 682 if (result) { 683 pmcs_timed_out(pwp, htag, __func__); 684 if (pmcs_abort(pwp, pptr, htag, 0, 1)) { 685 pptr->abort_pending = 1; 686 SCHEDULE_WORK(pwp, PMCS_WORK_ABORT_HANDLE); 687 } 688 return (ETIMEDOUT); 689 } 690 691 status = LE_32(msg[2]); 692 693 if (status != PMCOUT_STATUS_OK) { 694 if (status == PMCOUT_STATUS_OPEN_CNX_ERROR_STP_RESOURCES_BUSY) { 695 pmcs_prt(pwp, PMCS_PRT_DEBUG, pptr, pptr->target, 696 "%s: Potential affiliation active on 0x%" PRIx64, 697 __func__, pmcs_barray2wwn(pptr->sas_address)); 698 } else { 699 pmcs_prt(pwp, PMCS_PRT_DEBUG2, pptr, pptr->target, 700 "%s: SATA I/O returned with IOMB status 0x%x", 701 __func__, status); 702 } 703 return (EIO); 704 } 705 706 if (LE_32(ptr[3]) != 0) { 707 size_t j, amt = LE_32(ptr[3]); 708 if (amt > sizeof (fis_t)) { 709 amt = sizeof (fis_t); 710 } 711 amt >>= 2; 712 for (j = 0; j < amt; j++) { 713 fis[j] = LE_32(msg[4 + j]); 714 } 715 } 716 if (dlen && ddir == PMCIN_DATADIR_2_INI) { 717 if (ddi_dma_sync(pwp->cip_handles, 0, 0, 718 DDI_DMA_SYNC_FORKERNEL) != DDI_SUCCESS) { 719 pmcs_prt(pwp, PMCS_PRT_DEBUG, pptr, NULL, 720 "Condition check failed at %s():%d", 721 __func__, __LINE__); 722 } 723 } 724 return (0); 725 } 726