1 /* 2 * (MPSAFE) 3 * 4 * Copyright (c) 2009 The DragonFly Project. All rights reserved. 5 * 6 * This code is derived from software contributed to The DragonFly Project 7 * by Matthew Dillon <dillon@backplane.com> 8 * 9 * Redistribution and use in source and binary forms, with or without 10 * modification, are permitted provided that the following conditions 11 * are met: 12 * 13 * 1. Redistributions of source code must retain the above copyright 14 * notice, this list of conditions and the following disclaimer. 15 * 2. Redistributions in binary form must reproduce the above copyright 16 * notice, this list of conditions and the following disclaimer in 17 * the documentation and/or other materials provided with the 18 * distribution. 19 * 3. Neither the name of The DragonFly Project nor the names of its 20 * contributors may be used to endorse or promote products derived 21 * from this software without specific, prior written permission. 22 * 23 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 24 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 25 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS 26 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE 27 * COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, 28 * INCIDENTAL, SPECIAL, EXEMPLARY OR CONSEQUENTIAL DAMAGES (INCLUDING, 29 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 30 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED 31 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 32 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT 33 * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 34 * SUCH DAMAGE. 35 */ 36 37 #include "sili.h" 38 39 static void sili_pm_dummy_done(struct ata_xfer *xa); 40 static void sili_pm_empty_done(struct sili_ccb *ccb); 41 42 /* 43 * This is called for PM attachments and hot-plug insertion events, and 44 * typically not called again until after an unplug/replug sequence. 45 * 46 * We just fall through to the hard-reset code, we don't need to 47 * set up any initial conditions. 48 */ 49 int 50 sili_pm_port_init(struct sili_port *ap, struct ata_port *at) 51 { 52 at->at_probe = ATA_PROBE_NEED_HARD_RESET; 53 return (0); 54 } 55 56 /* 57 * This is called from the port hardreset code. 58 */ 59 int 60 sili_pm_port_probe(struct sili_port *ap, int orig_error) 61 { 62 struct ata_port *at; 63 int error; 64 int i; 65 66 /* 67 * Clean up the port state machine 68 */ 69 sili_pwrite(ap, SILI_PREG_CTL_SET, SILI_PREG_CTL_PMA); 70 sili_pwrite(ap, SILI_PREG_CTL_SET, SILI_PREG_CTL_INIT); 71 if (sili_pwait_clr_to(ap, 5000, SILI_PREG_STATUS, SILI_PREG_CTL_INIT)) { 72 kprintf("%s: PM probe: unable to init port\n", 73 PORTNAME(ap)); 74 return (EBUSY); 75 } 76 if (sili_pwait_set(ap, SILI_PREG_STATUS, SILI_PREG_STATUS_READY)) { 77 kprintf("%s: PM probe: port will not come ready\n", 78 PORTNAME(ap)); 79 return (EBUSY); 80 } 81 82 /* 83 * Issue a soft-reset of target 15 84 */ 85 ap->ap_state = AP_S_NORMAL; 86 sili_pwrite(ap, SILI_PREG_SERR, -1); 87 error = sili_pm_softreset(ap, 15); 88 89 if (error == 0) 90 error = sili_pm_identify(ap); 91 92 /* 93 * Finalize. If the softreset failed. Re-init the port 94 * state machine again so the normal non-PM softreset does 95 * not bog down. 96 */ 97 if (error == 0) { 98 for (i = 0; i < SILI_MAX_PMPORTS; ++i) { 99 at = &ap->ap_ata[i]; 100 at->at_probe = ATA_PROBE_NEED_INIT; 101 at->at_features |= ATA_PORT_F_RESCAN; 102 at->at_features &= ~ATA_PORT_F_READLOG; 103 } 104 ap->ap_type = ATA_PORT_T_PM; 105 return (0); 106 } 107 108 sili_pwrite(ap, SILI_PREG_CTL_CLR, SILI_PREG_CTL_PMA); 109 sili_port_init(ap); 110 if (orig_error == 0) { 111 if (sili_pwait_set_to(ap, 5000, SILI_PREG_STATUS, 112 SILI_PREG_STATUS_READY)) { 113 kprintf("%s: PM probe: port will not come ready\n", 114 PORTNAME(ap)); 115 orig_error = EBUSY; 116 } 117 } 118 return (orig_error); 119 120 #if 0 121 sili_pwrite(ap, SILI_PREG_CTL_CLR, SILI_PREG_CTL_RESUME); 122 sili_pwrite(ap, SILI_PREG_CTL_CLR, SILI_PREG_CTL_PMA); 123 sili_pwrite(ap, SILI_PREG_CTL_SET, SILI_PREG_CTL_INIT); 124 if (sili_pwait_clr_to(ap, 5000, SILI_PREG_STATUS, SILI_PREG_CTL_INIT)) { 125 kprintf("%s: PM probe: unable to init port\n", 126 PORTNAME(ap)); 127 orig_error = EBUSY; 128 } 129 if (sili_pwait_set(ap, SILI_PREG_STATUS, SILI_PREG_STATUS_READY)) { 130 kprintf("%s: PM probe: port will not come ready\n", 131 PORTNAME(ap)); 132 orig_error = EBUSY; 133 } 134 kprintf("ORIG ERROR %d\n", orig_error); 135 if (orig_error) 136 return (orig_error); 137 138 /* 139 * If we originally detected a device redo the device reset to 140 * try to clear the mess. 141 */ 142 sili_pwrite(ap, SILI_PREG_CTL_SET, SILI_PREG_CTL_DEVRESET); 143 if (sili_pwait_clr(ap, SILI_PREG_CTL_SET, SILI_PREG_CTL_DEVRESET)) { 144 kprintf("%s: PM probe: unable to reset\n", PORTNAME(ap)); 145 orig_error = EBUSY; 146 } 147 if (sili_pwait_set(ap, SILI_PREG_STATUS, SILI_PREG_STATUS_READY)) { 148 kprintf("%s: PM probe: port will not come ready\n", 149 PORTNAME(ap)); 150 orig_error = EBUSY; 151 } 152 return (orig_error); 153 #endif 154 } 155 156 /* 157 * Identify the port multiplier 158 */ 159 int 160 sili_pm_identify(struct sili_port *ap) 161 { 162 u_int32_t chipid; 163 u_int32_t rev; 164 u_int32_t nports; 165 u_int32_t data1; 166 u_int32_t data2; 167 int has_dummy_port; 168 169 ap->ap_probe = ATA_PROBE_FAILED; 170 if (sili_pm_read(ap, 15, 0, &chipid)) 171 goto err; 172 if (sili_pm_read(ap, 15, 1, &rev)) 173 goto err; 174 if (sili_pm_read(ap, 15, 2, &nports)) 175 goto err; 176 nports &= 0x0000000F; /* only the low 4 bits */ 177 ap->ap_probe = ATA_PROBE_GOOD; 178 179 /* 180 * Ignore fake port on PMs which have it. We can probe it but the 181 * softreset will probably fail. 182 */ 183 switch(chipid) { 184 case 0x37261095: 185 has_dummy_port = 1; 186 break; 187 default: 188 has_dummy_port = 0; 189 break; 190 } 191 if (has_dummy_port) { 192 if (nports > 1) 193 --nports; 194 } 195 196 kprintf("%s: Port multiplier: chip=%08x rev=0x%b nports=%d\n", 197 PORTNAME(ap), 198 chipid, 199 rev, SATA_PFMT_PM_REV, 200 nports); 201 if (has_dummy_port) { 202 kprintf("%s: Port multiplier: Ignoring dummy port #%d\n", 203 PORTNAME(ap), nports); 204 } 205 ap->ap_pmcount = nports; 206 207 if (sili_pm_read(ap, 15, SATA_PMREG_FEA, &data1)) { 208 kprintf("%s: Port multiplier: Warning, " 209 "cannot read feature register\n", PORTNAME(ap)); 210 } else { 211 kprintf("%s: Port multiplier features: 0x%b\n", 212 PORTNAME(ap), 213 data1, 214 SATA_PFMT_PM_FEA); 215 } 216 if (sili_pm_read(ap, 15, SATA_PMREG_FEAEN, &data2) == 0) { 217 kprintf("%s: Port multiplier defaults: 0x%b\n", 218 PORTNAME(ap), 219 data2, 220 SATA_PFMT_PM_FEA); 221 } 222 223 /* 224 * Turn on async notification if we support and the PM supports it. 225 * This allows the PM to forward async notification events to us and 226 * it will also generate an event for target 15 for hot-plug events 227 * (or is supposed to anyway). 228 */ 229 if ((ap->ap_sc->sc_flags & SILI_F_SSNTF) && 230 (data1 & SATA_PMFEA_ASYNCNOTIFY)) { 231 u_int32_t serr_bits = SATA_PM_SERR_DIAG_N | 232 SATA_PM_SERR_DIAG_X; 233 data2 |= SATA_PMFEA_ASYNCNOTIFY; 234 if (sili_pm_write(ap, 15, SATA_PMREG_FEAEN, data2)) { 235 kprintf("%s: Port multiplier: AsyncNotify cannot be " 236 "enabled\n", PORTNAME(ap)); 237 } else if (sili_pm_write(ap, 15, SATA_PMREG_EEENA, serr_bits)) { 238 kprintf("%s: Port mulltiplier: AsyncNotify unable " 239 "to enable error info bits\n", PORTNAME(ap)); 240 } else { 241 kprintf("%s: Port multiplier: AsyncNotify enabled\n", 242 PORTNAME(ap)); 243 } 244 } 245 246 return (0); 247 err: 248 kprintf("%s: Port multiplier cannot be identified\n", PORTNAME(ap)); 249 return (EIO); 250 } 251 252 /* 253 * Do a COMRESET sequence on the target behind a port multiplier. 254 * 255 * If hard is 2 we also cycle the phy on the target. 256 * 257 * This must be done prior to any softreset or probe attempts on 258 * targets behind the port multiplier. 259 * 260 * Returns 0 on success or an error. 261 */ 262 int 263 sili_pm_hardreset(struct sili_port *ap, int target, int hard) 264 { 265 struct ata_port *at; 266 u_int32_t data; 267 int loop; 268 int error = EIO; 269 270 at = &ap->ap_ata[target]; 271 272 /* 273 * Ensure that no other commands are pending. Our HW reset of 274 * the PM target can skewer the port overall! 275 */ 276 sili_exclusive_access(ap); 277 278 /* 279 * Turn off power management and kill the phy on the target 280 * if requested. Hold state for 10ms. 281 */ 282 data = SATA_PM_SCTL_IPM_DISABLED; 283 #if 0 284 if (hard == 2) 285 data |= SATA_PM_SCTL_DET_DISABLE; 286 #endif 287 if (sili_pm_write(ap, target, SATA_PMREG_SERR, -1)) 288 goto err; 289 if (sili_pm_write(ap, target, SATA_PMREG_SCTL, data)) 290 goto err; 291 sili_os_sleep(10); 292 293 /* 294 * Start transmitting COMRESET. COMRESET must be sent for at 295 * least 1ms. 296 * 297 * It takes about 100ms for the DET logic to settle down, 298 * from trial and error testing. If this is too short 299 * the softreset code will fail. 300 * 301 * It is very important to allow the logic to settle before 302 * we issue any additional commands or the target will interfere 303 * with our PM commands. 304 */ 305 at->at_probe = ATA_PROBE_FAILED; 306 at->at_type = ATA_PORT_T_NONE; 307 data = SATA_PM_SCTL_IPM_DISABLED | SATA_PM_SCTL_DET_INIT; 308 if (SiliForceGen1 & (1 << ap->ap_num)) { 309 kprintf("%s.%d: Force 1.5GBits\n", PORTNAME(ap), target); 310 data |= SATA_PM_SCTL_SPD_GEN1; 311 } else { 312 data |= SATA_PM_SCTL_SPD_ANY; 313 } 314 if (sili_pm_write(ap, target, SATA_PMREG_SCTL, data)) 315 goto err; 316 sili_os_sleep(100); 317 318 if (sili_pm_phy_status(ap, target, &data)) { 319 kprintf("%s: (A)Cannot clear phy status\n", 320 ATANAME(ap ,at)); 321 } 322 323 /* 324 * Flush any status, then clear DET to initiate negotiation. 325 * 326 * It is very important to allow the negotiation to settle before 327 * we issue any additional commands or the target will interfere 328 * with our PM commands. 329 */ 330 sili_pm_write(ap, target, SATA_PMREG_SERR, -1); 331 data = SATA_PM_SCTL_IPM_DISABLED | SATA_PM_SCTL_DET_NONE; 332 if (sili_pm_write(ap, target, SATA_PMREG_SCTL, data)) 333 goto err; 334 sili_os_sleep(100); 335 336 /* 337 * Try to determine if there is a device on the port. 338 * 339 * Give the device 3/10 second to at least be detected. 340 * If we fail clear any pending status since we may have 341 * cycled the phy and probably caused another PRCS interrupt. 342 */ 343 for (loop = 3; loop; --loop) { 344 if (sili_pm_read(ap, target, SATA_PMREG_SSTS, &data)) 345 goto err; 346 if (data & SATA_PM_SSTS_DET) 347 break; 348 sili_os_sleep(100); 349 } 350 if (loop == 0) { 351 kprintf("%s.%d: Port appears to be unplugged\n", 352 PORTNAME(ap), target); 353 error = ENODEV; 354 goto err; 355 } 356 357 /* 358 * There is something on the port. Give the device 3 seconds 359 * to fully negotiate. 360 */ 361 for (loop = 30; loop; --loop) { 362 if (sili_pm_read(ap, target, SATA_PMREG_SSTS, &data)) 363 goto err; 364 if ((data & SATA_PM_SSTS_DET) == SATA_PM_SSTS_DET_DEV) 365 break; 366 sili_os_sleep(100); 367 } 368 369 /* 370 * Device not detected 371 */ 372 if (loop == 0) { 373 kprintf("%s: Device may be powered down\n", 374 PORTNAME(ap)); 375 error = ENODEV; 376 goto err; 377 } 378 379 /* 380 * Device detected. 381 * 382 * Wait 200ms to give the device time to send its first D2H FIS. 383 * If we do not wait long enough our softreset sequence can collide 384 * with the end of the device's reset sequence and brick the port. 385 * Some devices may need longer and we handle those cases in the 386 * pm softreset code. 387 * 388 * XXX Looks like we have to wait a lot longer. If the Sili chip's 389 * softreset fails due to a collision with the D2H FIS or the 390 * unbusying it bricks the port. 391 * 392 * XXX how do we poll that particular target's BSY status via the 393 * PM? 394 */ 395 kprintf("%s.%d: PM Device detected ssts=%08x\n", 396 PORTNAME(ap), target, data); 397 sili_os_sleep(5000); 398 399 error = 0; 400 err: 401 at->at_probe = error ? ATA_PROBE_FAILED : ATA_PROBE_NEED_SOFT_RESET; 402 return (error); 403 } 404 405 /* 406 * SILI soft reset through port multiplier. 407 * 408 * This function generates a soft reset through the port multiplier, 409 * keeping port communications intact. 410 * 411 * The SII chip will do the whole mess for us. However, the command 412 * can brick the port if the target is still busy from the previous 413 * COMRESET. 414 */ 415 int 416 sili_pm_softreset(struct sili_port *ap, int target) 417 { 418 struct ata_port *at; 419 struct sili_ccb *ccb; 420 struct sili_prb *prb; 421 int error; 422 u_int32_t data; 423 u_int32_t sig; 424 int timeout; 425 426 error = EIO; 427 at = &ap->ap_ata[target]; 428 429 kprintf("%s: PM softreset\n", ATANAME(ap, at)); 430 431 /* 432 * Prep the special soft-reset SII command. 433 */ 434 ccb = sili_get_err_ccb(ap); 435 ccb->ccb_done = sili_pm_empty_done; 436 ccb->ccb_xa.flags = ATA_F_POLL | ATA_F_EXCLUSIVE | ATA_F_AUTOSENSE; 437 ccb->ccb_xa.complete = sili_pm_dummy_done; 438 ccb->ccb_xa.at = at; 439 440 prb = ccb->ccb_prb; 441 bzero(&prb->prb_h2d, sizeof(prb->prb_h2d)); 442 prb->prb_h2d.flags = at->at_target; 443 prb->prb_control = SILI_PRB_CTRL_SOFTRESET; 444 prb->prb_override = 0; 445 prb->prb_xfer_count = 0; 446 447 ccb->ccb_xa.state = ATA_S_PENDING; 448 449 timeout = (target == 15) ? 1000 : 8000; 450 451 /* 452 * NOTE: Must use sili_quick_timeout() because we hold the err_ccb 453 */ 454 if (sili_poll(ccb, timeout, sili_quick_timeout) != ATA_S_COMPLETE) { 455 if (target != 15) { 456 kprintf("%s: (PM) Softreset FIS failed\n", 457 ATANAME(ap, at)); 458 } 459 sili_put_err_ccb(ccb); 460 goto err; 461 } 462 463 sig = (prb->prb_d2h.lba_high << 24) | 464 (prb->prb_d2h.lba_mid << 16) | 465 (prb->prb_d2h.lba_low << 8) | 466 (prb->prb_d2h.sector_count); 467 kprintf("%s: PM SOFTRESET SIGNATURE %08x\n", ATANAME(ap, at), sig); 468 469 sili_put_err_ccb(ccb); 470 471 /* 472 * Clear the phy status of the target so we can get a new event. 473 * 474 * Target 15 is the PM itself and these registers have 475 * different meanings. 476 */ 477 if (target != 15) { 478 if (sili_pm_phy_status(ap, target, &data)) { 479 kprintf("%s: (C)Cannot clear phy status\n", 480 ATANAME(ap ,at)); 481 } 482 sili_pm_write(ap, target, SATA_PMREG_SERR, -1); 483 } 484 485 /* 486 * If the softreset is trying to clear a BSY condition after a 487 * normal portreset we assign the port type. 488 * 489 * If the softreset is being run first as part of the ccb error 490 * processing code then report if the device signature changed 491 * unexpectedly. 492 */ 493 if (at->at_type == ATA_PORT_T_NONE) { 494 at->at_type = sili_port_signature(ap, at, sig); 495 } else { 496 if (sili_port_signature(ap, at, sig) != at->at_type) { 497 kprintf("%s: device signature unexpectedly " 498 "changed\n", ATANAME(ap, at)); 499 error = EBUSY; /* XXX */ 500 } 501 } 502 error = 0; 503 err: 504 /* 505 * Clear error status so we can detect removal. 506 * 507 * Target 15 is the PM itself and these registers have 508 * different meanings. 509 */ 510 kprintf("%s: PM softreset done error %d\n", ATANAME(ap, at), error); 511 if (error == 0 && target != 15) { 512 if (sili_pm_write(ap, target, SATA_PMREG_SERR, -1)) { 513 kprintf("%s: sili_pm_softreset unable to clear SERR\n", 514 ATANAME(ap, at)); 515 ap->ap_flags &= ~AP_F_IGNORE_IFS; 516 } 517 } 518 519 at->at_probe = error ? ATA_PROBE_FAILED : ATA_PROBE_NEED_IDENT; 520 return (error); 521 } 522 523 524 /* 525 * Return the phy status for a target behind a port multiplier and 526 * reset SATA_PMREG_SERR. 527 * 528 * Returned bits follow SILI_PREG_SSTS bits. The SILI_PREG_SSTS_SPD 529 * bits can be used to determine the link speed and will be 0 if there 530 * is no link. 531 * 532 * 0 is returned if any communications error occurs. 533 */ 534 int 535 sili_pm_phy_status(struct sili_port *ap, int target, u_int32_t *datap) 536 { 537 int error; 538 539 error = sili_pm_read(ap, target, SATA_PMREG_SSTS, datap); 540 if (error == 0) 541 error = sili_pm_write(ap, target, SATA_PMREG_SERR, -1); 542 if (error) 543 *datap = 0; 544 return(error); 545 } 546 547 int 548 sili_pm_set_feature(struct sili_port *ap, int feature, int enable) 549 { 550 struct ata_xfer *xa; 551 int error; 552 553 xa = sili_ata_get_xfer(ap, &ap->ap_ata[15]); 554 555 xa->fis->type = ATA_FIS_TYPE_H2D; 556 xa->fis->flags = ATA_H2D_FLAGS_CMD | 15; 557 xa->fis->command = enable ? ATA_C_SATA_FEATURE_ENA : 558 ATA_C_SATA_FEATURE_DIS; 559 xa->fis->sector_count = feature; 560 xa->fis->control = ATA_FIS_CONTROL_4BIT; 561 562 xa->complete = sili_pm_dummy_done; 563 xa->datalen = 0; 564 xa->flags = ATA_F_POLL | ATA_F_EXCLUSIVE; 565 xa->timeout = 1000; 566 567 if (sili_ata_cmd(xa) == ATA_S_COMPLETE) 568 error = 0; 569 else 570 error = EIO; 571 sili_ata_put_xfer(xa); 572 return(error); 573 } 574 575 /* 576 * Check that a target is still good. 577 */ 578 void 579 sili_pm_check_good(struct sili_port *ap, int target) 580 { 581 struct ata_port *at; 582 u_int32_t data; 583 584 /* 585 * It looks like we might have to read the EINFO register 586 * to allow the PM to generate a new event. 587 */ 588 if (sili_pm_read(ap, 15, SATA_PMREG_EINFO, &data)) { 589 kprintf("%s: Port multiplier EINFO could not be read\n", 590 PORTNAME(ap)); 591 } 592 593 if (sili_pm_write(ap, target, SATA_PMREG_SERR, -1)) { 594 kprintf("%s: Port multiplier: SERR could not be cleared\n", 595 PORTNAME(ap)); 596 } 597 598 if (target == CAM_TARGET_WILDCARD || target >= ap->ap_pmcount) 599 return; 600 at = &ap->ap_ata[target]; 601 602 /* 603 * If the device needs an init or hard reset also make sure the 604 * PHY is turned on. 605 */ 606 if (at->at_probe <= ATA_PROBE_NEED_HARD_RESET) { 607 /*kprintf("%s DOHARD\n", ATANAME(ap, at));*/ 608 sili_pm_hardreset(ap, target, 1); 609 } 610 611 /* 612 * Read the detect status 613 */ 614 if (sili_pm_read(ap, target, SATA_PMREG_SSTS, &data)) { 615 kprintf("%s: Unable to access PM SSTS register target %d\n", 616 PORTNAME(ap), target); 617 return; 618 } 619 if ((data & SATA_PM_SSTS_DET) != SATA_PM_SSTS_DET_DEV) { 620 /*kprintf("%s: DETECT %08x\n", ATANAME(ap, at), data);*/ 621 if (at->at_probe != ATA_PROBE_FAILED) { 622 at->at_probe = ATA_PROBE_FAILED; 623 at->at_type = ATA_PORT_T_NONE; 624 at->at_features |= ATA_PORT_F_RESCAN; 625 kprintf("%s: HOTPLUG (PM) - Device removed\n", 626 ATANAME(ap, at)); 627 } 628 } else { 629 if (at->at_probe == ATA_PROBE_FAILED) { 630 at->at_probe = ATA_PROBE_NEED_HARD_RESET; 631 at->at_features |= ATA_PORT_F_RESCAN; 632 kprintf("%s: HOTPLUG (PM) - Device inserted\n", 633 ATANAME(ap, at)); 634 } 635 } 636 } 637 638 /* 639 * Read a PM register 640 */ 641 int 642 sili_pm_read(struct sili_port *ap, int target, int which, u_int32_t *datap) 643 { 644 struct ata_xfer *xa; 645 int error; 646 647 xa = sili_ata_get_xfer(ap, &ap->ap_ata[15]); 648 649 xa->fis->type = ATA_FIS_TYPE_H2D; 650 xa->fis->flags = ATA_H2D_FLAGS_CMD | 15; 651 xa->fis->command = ATA_C_READ_PM; 652 xa->fis->features = which; 653 xa->fis->device = target | ATA_H2D_DEVICE_LBA; 654 xa->fis->control = ATA_FIS_CONTROL_4BIT; 655 656 xa->complete = sili_pm_dummy_done; 657 xa->datalen = 0; 658 xa->flags = ATA_F_POLL | ATA_F_AUTOSENSE; 659 xa->timeout = 1000; 660 661 if (sili_ata_cmd(xa) == ATA_S_COMPLETE) { 662 *datap = xa->rfis->sector_count | (xa->rfis->lba_low << 8) | 663 (xa->rfis->lba_mid << 16) | (xa->rfis->lba_high << 24); 664 error = 0; 665 } else { 666 kprintf("%s.%d pm_read SCA[%d] failed\n", 667 PORTNAME(ap), target, which); 668 *datap = 0; 669 error = EIO; 670 } 671 sili_ata_put_xfer(xa); 672 return (error); 673 } 674 675 /* 676 * Write a PM register 677 */ 678 int 679 sili_pm_write(struct sili_port *ap, int target, int which, u_int32_t data) 680 { 681 struct ata_xfer *xa; 682 int error; 683 684 xa = sili_ata_get_xfer(ap, &ap->ap_ata[15]); 685 686 xa->fis->type = ATA_FIS_TYPE_H2D; 687 xa->fis->flags = ATA_H2D_FLAGS_CMD | 15; 688 xa->fis->command = ATA_C_WRITE_PM; 689 xa->fis->features = which; 690 xa->fis->device = target | ATA_H2D_DEVICE_LBA; 691 xa->fis->sector_count = (u_int8_t)data; 692 xa->fis->lba_low = (u_int8_t)(data >> 8); 693 xa->fis->lba_mid = (u_int8_t)(data >> 16); 694 xa->fis->lba_high = (u_int8_t)(data >> 24); 695 xa->fis->control = ATA_FIS_CONTROL_4BIT; 696 697 xa->complete = sili_pm_dummy_done; 698 xa->datalen = 0; 699 xa->flags = ATA_F_POLL | ATA_F_EXCLUSIVE; 700 xa->timeout = 1000; 701 702 if (sili_ata_cmd(xa) == ATA_S_COMPLETE) 703 error = 0; 704 else 705 error = EIO; 706 sili_ata_put_xfer(xa); 707 return(error); 708 } 709 710 /* 711 * Dummy done callback for xa. 712 */ 713 static void 714 sili_pm_dummy_done(struct ata_xfer *xa) 715 { 716 } 717 718 static void 719 sili_pm_empty_done(struct sili_ccb *ccb) 720 { 721 } 722