1 /*- 2 * SPDX-License-Identifier: BSD-2-Clause 3 * 4 * Copyright (c) 2009 Alexander Motin <mav@FreeBSD.org> 5 * All rights reserved. 6 * 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted provided that the following conditions 9 * are met: 10 * 1. Redistributions of source code must retain the above copyright 11 * notice, this list of conditions and the following disclaimer, 12 * without modification, immediately at the beginning of the file. 13 * 2. Redistributions in binary form must reproduce the above copyright 14 * notice, this list of conditions and the following disclaimer in the 15 * documentation and/or other materials provided with the distribution. 16 * 17 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 18 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 19 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 20 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 21 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 22 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 23 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 24 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 26 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 27 */ 28 29 #include <sys/param.h> 30 31 #ifdef _KERNEL 32 #include <sys/systm.h> 33 #include <sys/kernel.h> 34 #include <sys/bio.h> 35 #include <sys/sysctl.h> 36 #include <sys/taskqueue.h> 37 #include <sys/lock.h> 38 #include <sys/mutex.h> 39 #include <sys/conf.h> 40 #include <sys/devicestat.h> 41 #include <sys/eventhandler.h> 42 #include <sys/malloc.h> 43 #include <sys/cons.h> 44 #include <geom/geom_disk.h> 45 #endif /* _KERNEL */ 46 47 #ifndef _KERNEL 48 #include <stdio.h> 49 #include <string.h> 50 #endif /* _KERNEL */ 51 52 #include <cam/cam.h> 53 #include <cam/cam_ccb.h> 54 #include <cam/cam_periph.h> 55 #include <cam/cam_xpt_periph.h> 56 #include <cam/cam_xpt_internal.h> 57 #include <cam/cam_sim.h> 58 59 #include <cam/ata/ata_all.h> 60 61 #ifdef _KERNEL 62 63 typedef enum { 64 PMP_STATE_NORMAL, 65 PMP_STATE_PORTS, 66 PMP_STATE_PM_QUIRKS_1, 67 PMP_STATE_PM_QUIRKS_2, 68 PMP_STATE_PM_QUIRKS_3, 69 PMP_STATE_PRECONFIG, 70 PMP_STATE_RESET, 71 PMP_STATE_CONNECT, 72 PMP_STATE_CHECK, 73 PMP_STATE_CLEAR, 74 PMP_STATE_CONFIG, 75 PMP_STATE_SCAN 76 } pmp_state; 77 78 typedef enum { 79 PMP_FLAG_SCTX_INIT = 0x200 80 } pmp_flags; 81 82 typedef enum { 83 PMP_CCB_PROBE = 0x01, 84 } pmp_ccb_state; 85 86 /* Offsets into our private area for storing information */ 87 #define ccb_state ppriv_field0 88 #define ccb_bp ppriv_ptr1 89 90 struct pmp_softc { 91 SLIST_ENTRY(pmp_softc) links; 92 pmp_state state; 93 pmp_flags flags; 94 uint32_t pm_pid; 95 uint32_t pm_prv; 96 int pm_ports; 97 int pm_step; 98 int pm_try; 99 int found; 100 int reset; 101 int frozen; 102 int restart; 103 int events; 104 #define PMP_EV_RESET 1 105 #define PMP_EV_RESCAN 2 106 u_int caps; 107 struct task sysctl_task; 108 struct sysctl_ctx_list sysctl_ctx; 109 struct sysctl_oid *sysctl_tree; 110 }; 111 112 static periph_init_t pmpinit; 113 static void pmpasync(void *callback_arg, uint32_t code, 114 struct cam_path *path, void *arg); 115 static void pmpsysctlinit(void *context, int pending); 116 static periph_ctor_t pmpregister; 117 static periph_dtor_t pmpcleanup; 118 static periph_start_t pmpstart; 119 static periph_oninv_t pmponinvalidate; 120 static void pmpdone(struct cam_periph *periph, 121 union ccb *done_ccb); 122 123 #ifndef PMP_DEFAULT_TIMEOUT 124 #define PMP_DEFAULT_TIMEOUT 30 /* Timeout in seconds */ 125 #endif 126 127 #ifndef PMP_DEFAULT_RETRY 128 #define PMP_DEFAULT_RETRY 1 129 #endif 130 131 #ifndef PMP_DEFAULT_HIDE_SPECIAL 132 #define PMP_DEFAULT_HIDE_SPECIAL 1 133 #endif 134 135 static int pmp_retry_count = PMP_DEFAULT_RETRY; 136 static int pmp_default_timeout = PMP_DEFAULT_TIMEOUT; 137 static int pmp_hide_special = PMP_DEFAULT_HIDE_SPECIAL; 138 139 static SYSCTL_NODE(_kern_cam, OID_AUTO, pmp, CTLFLAG_RD | CTLFLAG_MPSAFE, 0, 140 "CAM Direct Access Disk driver"); 141 SYSCTL_INT(_kern_cam_pmp, OID_AUTO, retry_count, CTLFLAG_RWTUN, 142 &pmp_retry_count, 0, "Normal I/O retry count"); 143 SYSCTL_INT(_kern_cam_pmp, OID_AUTO, default_timeout, CTLFLAG_RWTUN, 144 &pmp_default_timeout, 0, "Normal I/O timeout (in seconds)"); 145 SYSCTL_INT(_kern_cam_pmp, OID_AUTO, hide_special, CTLFLAG_RWTUN, 146 &pmp_hide_special, 0, "Hide extra ports"); 147 148 static struct periph_driver pmpdriver = 149 { 150 pmpinit, "pmp", 151 TAILQ_HEAD_INITIALIZER(pmpdriver.units), /* generation */ 0, 152 CAM_PERIPH_DRV_EARLY 153 }; 154 155 PERIPHDRIVER_DECLARE(pmp, pmpdriver); 156 157 static void 158 pmpinit(void) 159 { 160 cam_status status; 161 162 /* 163 * Install a global async callback. This callback will 164 * receive async callbacks like "new device found". 165 */ 166 status = xpt_register_async(AC_FOUND_DEVICE, pmpasync, NULL, NULL); 167 168 if (status != CAM_REQ_CMP) { 169 printf("pmp: Failed to attach master async callback " 170 "due to status 0x%x!\n", status); 171 } 172 } 173 174 static void 175 pmpfreeze(struct cam_periph *periph, int mask) 176 { 177 struct pmp_softc *softc = (struct pmp_softc *)periph->softc; 178 struct cam_path *dpath; 179 int i; 180 181 mask &= ~softc->frozen; 182 for (i = 0; i < 15; i++) { 183 if ((mask & (1 << i)) == 0) 184 continue; 185 if (xpt_create_path(&dpath, periph, 186 xpt_path_path_id(periph->path), 187 i, 0) == CAM_REQ_CMP) { 188 softc->frozen |= (1 << i); 189 xpt_acquire_device(dpath->device); 190 cam_freeze_devq(dpath); 191 xpt_free_path(dpath); 192 } 193 } 194 } 195 196 static void 197 pmprelease(struct cam_periph *periph, int mask) 198 { 199 struct pmp_softc *softc = (struct pmp_softc *)periph->softc; 200 struct cam_path *dpath; 201 int i; 202 203 mask &= softc->frozen; 204 for (i = 0; i < 15; i++) { 205 if ((mask & (1 << i)) == 0) 206 continue; 207 if (xpt_create_path(&dpath, periph, 208 xpt_path_path_id(periph->path), 209 i, 0) == CAM_REQ_CMP) { 210 softc->frozen &= ~(1 << i); 211 cam_release_devq(dpath, 0, 0, 0, FALSE); 212 xpt_release_device(dpath->device); 213 xpt_free_path(dpath); 214 } 215 } 216 } 217 218 static void 219 pmponinvalidate(struct cam_periph *periph) 220 { 221 struct cam_path *dpath; 222 int i; 223 224 /* 225 * De-register any async callbacks. 226 */ 227 xpt_register_async(0, pmpasync, periph, periph->path); 228 229 for (i = 0; i < 15; i++) { 230 if (xpt_create_path(&dpath, periph, 231 xpt_path_path_id(periph->path), 232 i, 0) == CAM_REQ_CMP) { 233 xpt_async(AC_LOST_DEVICE, dpath, NULL); 234 xpt_free_path(dpath); 235 } 236 } 237 pmprelease(periph, -1); 238 } 239 240 static void 241 pmpcleanup(struct cam_periph *periph) 242 { 243 struct pmp_softc *softc; 244 245 softc = (struct pmp_softc *)periph->softc; 246 247 cam_periph_unlock(periph); 248 249 /* 250 * If we can't free the sysctl tree, oh well... 251 */ 252 if ((softc->flags & PMP_FLAG_SCTX_INIT) != 0 253 && sysctl_ctx_free(&softc->sysctl_ctx) != 0) { 254 xpt_print(periph->path, "can't remove sysctl context\n"); 255 } 256 257 free(softc, M_DEVBUF); 258 cam_periph_lock(periph); 259 } 260 261 static void 262 pmpasync(void *callback_arg, uint32_t code, 263 struct cam_path *path, void *arg) 264 { 265 struct cam_periph *periph; 266 struct pmp_softc *softc; 267 268 periph = (struct cam_periph *)callback_arg; 269 switch (code) { 270 case AC_FOUND_DEVICE: 271 { 272 struct ccb_getdev *cgd; 273 cam_status status; 274 275 cgd = (struct ccb_getdev *)arg; 276 if (cgd == NULL) 277 break; 278 279 if (cgd->protocol != PROTO_SATAPM) 280 break; 281 282 /* 283 * Allocate a peripheral instance for 284 * this device and start the probe 285 * process. 286 */ 287 status = cam_periph_alloc(pmpregister, pmponinvalidate, 288 pmpcleanup, pmpstart, 289 "pmp", CAM_PERIPH_BIO, 290 path, pmpasync, 291 AC_FOUND_DEVICE, cgd); 292 293 if (status != CAM_REQ_CMP 294 && status != CAM_REQ_INPROG) 295 printf("pmpasync: Unable to attach to new device " 296 "due to status 0x%x\n", status); 297 break; 298 } 299 case AC_SCSI_AEN: 300 case AC_SENT_BDR: 301 case AC_BUS_RESET: 302 softc = (struct pmp_softc *)periph->softc; 303 cam_periph_async(periph, code, path, arg); 304 if (code == AC_SCSI_AEN) 305 softc->events |= PMP_EV_RESCAN; 306 else 307 softc->events |= PMP_EV_RESET; 308 if (code == AC_SCSI_AEN && softc->state != PMP_STATE_NORMAL) 309 break; 310 xpt_hold_boot(); 311 pmpfreeze(periph, softc->found); 312 if (code == AC_SENT_BDR || code == AC_BUS_RESET) 313 softc->found = 0; /* We have to reset everything. */ 314 if (softc->state == PMP_STATE_NORMAL) { 315 if (cam_periph_acquire(periph) == 0) { 316 if (softc->pm_pid == 0x37261095 || 317 softc->pm_pid == 0x38261095) 318 softc->state = PMP_STATE_PM_QUIRKS_1; 319 else 320 softc->state = PMP_STATE_PRECONFIG; 321 xpt_schedule(periph, CAM_PRIORITY_DEV); 322 } else { 323 pmprelease(periph, softc->found); 324 xpt_release_boot(); 325 } 326 } else 327 softc->restart = 1; 328 break; 329 default: 330 cam_periph_async(periph, code, path, arg); 331 break; 332 } 333 } 334 335 static void 336 pmpsysctlinit(void *context, int pending) 337 { 338 struct cam_periph *periph; 339 struct pmp_softc *softc; 340 char tmpstr[32], tmpstr2[16]; 341 342 periph = (struct cam_periph *)context; 343 if (cam_periph_acquire(periph) != 0) 344 return; 345 346 softc = (struct pmp_softc *)periph->softc; 347 snprintf(tmpstr, sizeof(tmpstr), "CAM PMP unit %d", periph->unit_number); 348 snprintf(tmpstr2, sizeof(tmpstr2), "%d", periph->unit_number); 349 350 sysctl_ctx_init(&softc->sysctl_ctx); 351 softc->flags |= PMP_FLAG_SCTX_INIT; 352 softc->sysctl_tree = SYSCTL_ADD_NODE_WITH_LABEL(&softc->sysctl_ctx, 353 SYSCTL_STATIC_CHILDREN(_kern_cam_pmp), OID_AUTO, tmpstr2, 354 CTLFLAG_RD | CTLFLAG_MPSAFE, 0, tmpstr, "device_index"); 355 if (softc->sysctl_tree == NULL) { 356 printf("pmpsysctlinit: unable to allocate sysctl tree\n"); 357 cam_periph_release(periph); 358 return; 359 } 360 361 cam_periph_release(periph); 362 } 363 364 static cam_status 365 pmpregister(struct cam_periph *periph, void *arg) 366 { 367 struct pmp_softc *softc; 368 struct ccb_getdev *cgd; 369 370 cgd = (struct ccb_getdev *)arg; 371 if (cgd == NULL) { 372 printf("pmpregister: no getdev CCB, can't register device\n"); 373 return(CAM_REQ_CMP_ERR); 374 } 375 376 softc = (struct pmp_softc *)malloc(sizeof(*softc), M_DEVBUF, 377 M_NOWAIT|M_ZERO); 378 379 if (softc == NULL) { 380 printf("pmpregister: Unable to probe new device. " 381 "Unable to allocate softc\n"); 382 return(CAM_REQ_CMP_ERR); 383 } 384 periph->softc = softc; 385 386 softc->pm_pid = ((uint32_t *)&cgd->ident_data)[0]; 387 softc->pm_prv = ((uint32_t *)&cgd->ident_data)[1]; 388 TASK_INIT(&softc->sysctl_task, 0, pmpsysctlinit, periph); 389 390 xpt_announce_periph(periph, NULL); 391 392 /* 393 * Add async callbacks for bus reset and 394 * bus device reset calls. I don't bother 395 * checking if this fails as, in most cases, 396 * the system will function just fine without 397 * them and the only alternative would be to 398 * not attach the device on failure. 399 */ 400 xpt_register_async(AC_SENT_BDR | AC_BUS_RESET | AC_LOST_DEVICE | 401 AC_SCSI_AEN, pmpasync, periph, periph->path); 402 403 /* 404 * Take an exclusive refcount on the periph while pmpstart is called 405 * to finish the probe. The reference will be dropped in pmpdone at 406 * the end of probe. 407 */ 408 (void)cam_periph_acquire(periph); 409 xpt_hold_boot(); 410 softc->state = PMP_STATE_PORTS; 411 softc->events = PMP_EV_RESCAN; 412 xpt_schedule(periph, CAM_PRIORITY_DEV); 413 414 return(CAM_REQ_CMP); 415 } 416 417 static void 418 pmpstart(struct cam_periph *periph, union ccb *start_ccb) 419 { 420 struct ccb_trans_settings cts; 421 struct ccb_ataio *ataio; 422 struct pmp_softc *softc; 423 struct cam_path *dpath; 424 int revision = 0; 425 426 softc = (struct pmp_softc *)periph->softc; 427 ataio = &start_ccb->ataio; 428 429 CAM_DEBUG(periph->path, CAM_DEBUG_TRACE, ("pmpstart\n")); 430 431 if (softc->restart) { 432 softc->restart = 0; 433 if (softc->pm_pid == 0x37261095 || softc->pm_pid == 0x38261095) 434 softc->state = min(softc->state, PMP_STATE_PM_QUIRKS_1); 435 else 436 softc->state = min(softc->state, PMP_STATE_PRECONFIG); 437 } 438 /* Fetch user wanted device speed. */ 439 if (softc->state == PMP_STATE_RESET || 440 softc->state == PMP_STATE_CONNECT) { 441 if (xpt_create_path(&dpath, periph, 442 xpt_path_path_id(periph->path), 443 softc->pm_step, 0) == CAM_REQ_CMP) { 444 bzero(&cts, sizeof(cts)); 445 xpt_setup_ccb(&cts.ccb_h, dpath, CAM_PRIORITY_NONE); 446 cts.ccb_h.func_code = XPT_GET_TRAN_SETTINGS; 447 cts.type = CTS_TYPE_USER_SETTINGS; 448 xpt_action((union ccb *)&cts); 449 if (cts.xport_specific.sata.valid & CTS_SATA_VALID_REVISION) 450 revision = cts.xport_specific.sata.revision; 451 xpt_free_path(dpath); 452 } 453 } 454 switch (softc->state) { 455 case PMP_STATE_PORTS: 456 cam_fill_ataio(ataio, 457 pmp_retry_count, 458 pmpdone, 459 /*flags*/CAM_DIR_NONE, 460 0, 461 /*data_ptr*/NULL, 462 /*dxfer_len*/0, 463 pmp_default_timeout * 1000); 464 ata_pm_read_cmd(ataio, 2, 15); 465 break; 466 467 case PMP_STATE_PM_QUIRKS_1: 468 case PMP_STATE_PM_QUIRKS_3: 469 cam_fill_ataio(ataio, 470 pmp_retry_count, 471 pmpdone, 472 /*flags*/CAM_DIR_NONE, 473 0, 474 /*data_ptr*/NULL, 475 /*dxfer_len*/0, 476 pmp_default_timeout * 1000); 477 ata_pm_read_cmd(ataio, 129, 15); 478 break; 479 480 case PMP_STATE_PM_QUIRKS_2: 481 cam_fill_ataio(ataio, 482 pmp_retry_count, 483 pmpdone, 484 /*flags*/CAM_DIR_NONE, 485 0, 486 /*data_ptr*/NULL, 487 /*dxfer_len*/0, 488 pmp_default_timeout * 1000); 489 ata_pm_write_cmd(ataio, 129, 15, softc->caps & ~0x1); 490 break; 491 492 case PMP_STATE_PRECONFIG: 493 /* Get/update host SATA capabilities. */ 494 bzero(&cts, sizeof(cts)); 495 xpt_setup_ccb(&cts.ccb_h, periph->path, CAM_PRIORITY_NONE); 496 cts.ccb_h.func_code = XPT_GET_TRAN_SETTINGS; 497 cts.type = CTS_TYPE_CURRENT_SETTINGS; 498 xpt_action((union ccb *)&cts); 499 if (cts.xport_specific.sata.valid & CTS_SATA_VALID_CAPS) 500 softc->caps = cts.xport_specific.sata.caps; 501 else 502 softc->caps = 0; 503 cam_fill_ataio(ataio, 504 pmp_retry_count, 505 pmpdone, 506 /*flags*/CAM_DIR_NONE, 507 0, 508 /*data_ptr*/NULL, 509 /*dxfer_len*/0, 510 pmp_default_timeout * 1000); 511 ata_pm_write_cmd(ataio, 0x60, 15, 0x0); 512 break; 513 case PMP_STATE_RESET: 514 cam_fill_ataio(ataio, 515 pmp_retry_count, 516 pmpdone, 517 /*flags*/CAM_DIR_NONE, 518 0, 519 /*data_ptr*/NULL, 520 /*dxfer_len*/0, 521 pmp_default_timeout * 1000); 522 ata_pm_write_cmd(ataio, 2, softc->pm_step, 523 (revision << 4) | 524 ((softc->found & (1 << softc->pm_step)) ? 0 : 1)); 525 break; 526 case PMP_STATE_CONNECT: 527 cam_fill_ataio(ataio, 528 pmp_retry_count, 529 pmpdone, 530 /*flags*/CAM_DIR_NONE, 531 0, 532 /*data_ptr*/NULL, 533 /*dxfer_len*/0, 534 pmp_default_timeout * 1000); 535 ata_pm_write_cmd(ataio, 2, softc->pm_step, 536 (revision << 4)); 537 break; 538 case PMP_STATE_CHECK: 539 cam_fill_ataio(ataio, 540 pmp_retry_count, 541 pmpdone, 542 /*flags*/CAM_DIR_NONE, 543 0, 544 /*data_ptr*/NULL, 545 /*dxfer_len*/0, 546 pmp_default_timeout * 1000); 547 ata_pm_read_cmd(ataio, 0, softc->pm_step); 548 break; 549 case PMP_STATE_CLEAR: 550 softc->reset = 0; 551 cam_fill_ataio(ataio, 552 pmp_retry_count, 553 pmpdone, 554 /*flags*/CAM_DIR_NONE, 555 0, 556 /*data_ptr*/NULL, 557 /*dxfer_len*/0, 558 pmp_default_timeout * 1000); 559 ata_pm_write_cmd(ataio, 1, softc->pm_step, 0xFFFFFFFF); 560 break; 561 case PMP_STATE_CONFIG: 562 cam_fill_ataio(ataio, 563 pmp_retry_count, 564 pmpdone, 565 /*flags*/CAM_DIR_NONE, 566 0, 567 /*data_ptr*/NULL, 568 /*dxfer_len*/0, 569 pmp_default_timeout * 1000); 570 ata_pm_write_cmd(ataio, 0x60, 15, 0x07 | 571 ((softc->caps & CTS_SATA_CAPS_H_AN) ? 0x08 : 0)); 572 break; 573 default: 574 break; 575 } 576 xpt_action(start_ccb); 577 } 578 579 static void 580 pmpdone(struct cam_periph *periph, union ccb *done_ccb) 581 { 582 struct ccb_trans_settings cts; 583 struct pmp_softc *softc; 584 struct ccb_ataio *ataio; 585 struct cam_path *dpath; 586 uint32_t priority, res; 587 int i; 588 589 softc = (struct pmp_softc *)periph->softc; 590 ataio = &done_ccb->ataio; 591 592 CAM_DEBUG(periph->path, CAM_DEBUG_TRACE, ("pmpdone\n")); 593 594 priority = done_ccb->ccb_h.pinfo.priority; 595 596 if ((done_ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) { 597 if (cam_periph_error(done_ccb, 0, 0) == ERESTART) { 598 return; 599 } else if ((done_ccb->ccb_h.status & CAM_DEV_QFRZN) != 0) { 600 cam_release_devq(done_ccb->ccb_h.path, 601 /*relsim_flags*/0, 602 /*reduction*/0, 603 /*timeout*/0, 604 /*getcount_only*/0); 605 } 606 goto done; 607 } 608 609 if (softc->restart) { 610 softc->restart = 0; 611 xpt_release_ccb(done_ccb); 612 if (softc->pm_pid == 0x37261095 || softc->pm_pid == 0x38261095) 613 softc->state = min(softc->state, PMP_STATE_PM_QUIRKS_1); 614 else 615 softc->state = min(softc->state, PMP_STATE_PRECONFIG); 616 xpt_schedule(periph, priority); 617 return; 618 } 619 620 switch (softc->state) { 621 case PMP_STATE_PORTS: 622 softc->pm_ports = (ataio->res.lba_high << 24) + 623 (ataio->res.lba_mid << 16) + 624 (ataio->res.lba_low << 8) + 625 ataio->res.sector_count; 626 if (pmp_hide_special) { 627 /* 628 * This PMP declares 6 ports, while only 5 of them 629 * are real. Port 5 is a SEMB port, probing which 630 * causes timeouts if external SEP is not connected 631 * to PMP over I2C. 632 */ 633 if ((softc->pm_pid == 0x37261095 || 634 softc->pm_pid == 0x38261095) && 635 softc->pm_ports == 6) 636 softc->pm_ports = 5; 637 638 /* 639 * This PMP declares 7 ports, while only 5 of them 640 * are real. Port 5 is a fake "Config Disk" with 641 * 640 sectors size. Port 6 is a SEMB port. 642 */ 643 if (softc->pm_pid == 0x47261095 && softc->pm_ports == 7) 644 softc->pm_ports = 5; 645 646 /* 647 * These PMPs have extra configuration port. 648 */ 649 if (softc->pm_pid == 0x57231095 || 650 softc->pm_pid == 0x57331095 || 651 softc->pm_pid == 0x57341095 || 652 softc->pm_pid == 0x57441095) 653 softc->pm_ports--; 654 } 655 printf("%s%d: %d fan-out ports\n", 656 periph->periph_name, periph->unit_number, 657 softc->pm_ports); 658 if (softc->pm_pid == 0x37261095 || softc->pm_pid == 0x38261095) 659 softc->state = PMP_STATE_PM_QUIRKS_1; 660 else 661 softc->state = PMP_STATE_PRECONFIG; 662 xpt_release_ccb(done_ccb); 663 xpt_schedule(periph, priority); 664 return; 665 666 case PMP_STATE_PM_QUIRKS_1: 667 softc->caps = (ataio->res.lba_high << 24) + 668 (ataio->res.lba_mid << 16) + 669 (ataio->res.lba_low << 8) + 670 ataio->res.sector_count; 671 if (softc->caps & 0x1) 672 softc->state = PMP_STATE_PM_QUIRKS_2; 673 else 674 softc->state = PMP_STATE_PRECONFIG; 675 xpt_release_ccb(done_ccb); 676 xpt_schedule(periph, priority); 677 return; 678 679 case PMP_STATE_PM_QUIRKS_2: 680 if (bootverbose) 681 softc->state = PMP_STATE_PM_QUIRKS_3; 682 else 683 softc->state = PMP_STATE_PRECONFIG; 684 xpt_release_ccb(done_ccb); 685 xpt_schedule(periph, priority); 686 return; 687 688 case PMP_STATE_PM_QUIRKS_3: 689 res = (ataio->res.lba_high << 24) + 690 (ataio->res.lba_mid << 16) + 691 (ataio->res.lba_low << 8) + 692 ataio->res.sector_count; 693 printf("%s%d: Disabling SiI3x26 R_OK in GSCR_POLL: %x->%x\n", 694 periph->periph_name, periph->unit_number, softc->caps, res); 695 softc->state = PMP_STATE_PRECONFIG; 696 xpt_release_ccb(done_ccb); 697 xpt_schedule(periph, priority); 698 return; 699 700 case PMP_STATE_PRECONFIG: 701 softc->pm_step = 0; 702 softc->state = PMP_STATE_RESET; 703 softc->reset |= ~softc->found; 704 xpt_release_ccb(done_ccb); 705 xpt_schedule(periph, priority); 706 return; 707 case PMP_STATE_RESET: 708 softc->pm_step++; 709 if (softc->pm_step >= softc->pm_ports) { 710 softc->pm_step = 0; 711 cam_freeze_devq(periph->path); 712 cam_release_devq(periph->path, 713 RELSIM_RELEASE_AFTER_TIMEOUT, 714 /*reduction*/0, 715 /*timeout*/5, 716 /*getcount_only*/0); 717 softc->state = PMP_STATE_CONNECT; 718 } 719 xpt_release_ccb(done_ccb); 720 xpt_schedule(periph, priority); 721 return; 722 case PMP_STATE_CONNECT: 723 softc->pm_step++; 724 if (softc->pm_step >= softc->pm_ports) { 725 softc->pm_step = 0; 726 softc->pm_try = 0; 727 cam_freeze_devq(periph->path); 728 cam_release_devq(periph->path, 729 RELSIM_RELEASE_AFTER_TIMEOUT, 730 /*reduction*/0, 731 /*timeout*/10, 732 /*getcount_only*/0); 733 softc->state = PMP_STATE_CHECK; 734 } 735 xpt_release_ccb(done_ccb); 736 xpt_schedule(periph, priority); 737 return; 738 case PMP_STATE_CHECK: 739 res = (ataio->res.lba_high << 24) + 740 (ataio->res.lba_mid << 16) + 741 (ataio->res.lba_low << 8) + 742 ataio->res.sector_count; 743 if (((res & 0xf0f) == 0x103 && (res & 0x0f0) != 0) || 744 (res & 0x600) != 0) { 745 if (bootverbose) { 746 printf("%s%d: port %d status: %08x\n", 747 periph->periph_name, periph->unit_number, 748 softc->pm_step, res); 749 } 750 /* Report device speed if it is online. */ 751 if ((res & 0xf0f) == 0x103 && 752 xpt_create_path(&dpath, periph, 753 xpt_path_path_id(periph->path), 754 softc->pm_step, 0) == CAM_REQ_CMP) { 755 bzero(&cts, sizeof(cts)); 756 xpt_setup_ccb(&cts.ccb_h, dpath, CAM_PRIORITY_NONE); 757 cts.ccb_h.func_code = XPT_SET_TRAN_SETTINGS; 758 cts.type = CTS_TYPE_CURRENT_SETTINGS; 759 cts.xport_specific.sata.revision = (res & 0x0f0) >> 4; 760 cts.xport_specific.sata.valid = CTS_SATA_VALID_REVISION; 761 cts.xport_specific.sata.caps = softc->caps & 762 (CTS_SATA_CAPS_H_PMREQ | 763 CTS_SATA_CAPS_H_DMAAA | 764 CTS_SATA_CAPS_H_AN); 765 cts.xport_specific.sata.valid |= CTS_SATA_VALID_CAPS; 766 xpt_action((union ccb *)&cts); 767 xpt_free_path(dpath); 768 } 769 softc->found |= (1 << softc->pm_step); 770 softc->pm_step++; 771 } else { 772 if (softc->pm_try < 10) { 773 cam_freeze_devq(periph->path); 774 cam_release_devq(periph->path, 775 RELSIM_RELEASE_AFTER_TIMEOUT, 776 /*reduction*/0, 777 /*timeout*/10, 778 /*getcount_only*/0); 779 softc->pm_try++; 780 } else { 781 if (bootverbose) { 782 printf("%s%d: port %d status: %08x\n", 783 periph->periph_name, periph->unit_number, 784 softc->pm_step, res); 785 } 786 softc->found &= ~(1 << softc->pm_step); 787 if (xpt_create_path(&dpath, periph, 788 done_ccb->ccb_h.path_id, 789 softc->pm_step, 0) == CAM_REQ_CMP) { 790 xpt_async(AC_LOST_DEVICE, dpath, NULL); 791 xpt_free_path(dpath); 792 } 793 softc->pm_step++; 794 } 795 } 796 if (softc->pm_step >= softc->pm_ports) { 797 if (softc->reset & softc->found) { 798 cam_freeze_devq(periph->path); 799 cam_release_devq(periph->path, 800 RELSIM_RELEASE_AFTER_TIMEOUT, 801 /*reduction*/0, 802 /*timeout*/1000, 803 /*getcount_only*/0); 804 } 805 softc->state = PMP_STATE_CLEAR; 806 softc->pm_step = 0; 807 } 808 xpt_release_ccb(done_ccb); 809 xpt_schedule(periph, priority); 810 return; 811 case PMP_STATE_CLEAR: 812 softc->pm_step++; 813 if (softc->pm_step >= softc->pm_ports) { 814 softc->state = PMP_STATE_CONFIG; 815 softc->pm_step = 0; 816 } 817 xpt_release_ccb(done_ccb); 818 xpt_schedule(periph, priority); 819 return; 820 case PMP_STATE_CONFIG: 821 for (i = 0; i < softc->pm_ports; i++) { 822 union ccb *ccb; 823 824 if ((softc->found & (1 << i)) == 0) 825 continue; 826 if (xpt_create_path(&dpath, periph, 827 xpt_path_path_id(periph->path), 828 i, 0) != CAM_REQ_CMP) { 829 printf("pmpdone: xpt_create_path failed\n"); 830 continue; 831 } 832 /* If we did hard reset to this device, inform XPT. */ 833 if ((softc->reset & softc->found & (1 << i)) != 0) 834 xpt_async(AC_SENT_BDR, dpath, NULL); 835 /* If rescan requested, scan this device. */ 836 if (softc->events & PMP_EV_RESCAN) { 837 ccb = xpt_alloc_ccb_nowait(); 838 if (ccb == NULL) { 839 xpt_free_path(dpath); 840 goto done; 841 } 842 xpt_setup_ccb(&ccb->ccb_h, dpath, CAM_PRIORITY_XPT); 843 xpt_rescan(ccb); 844 } else 845 xpt_free_path(dpath); 846 } 847 break; 848 default: 849 break; 850 } 851 done: 852 xpt_release_ccb(done_ccb); 853 softc->state = PMP_STATE_NORMAL; 854 softc->events = 0; 855 xpt_release_boot(); 856 pmprelease(periph, -1); 857 cam_periph_release_locked(periph); 858 } 859 860 #endif /* _KERNEL */ 861