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