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