1 /*- 2 * Copyright (c) 2009 Alexander Motin <mav@FreeBSD.org> 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 1. Redistributions of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer, 10 * without modification, immediately at the beginning of the file. 11 * 2. Redistributions in binary form must reproduce the above copyright 12 * notice, this list of conditions and the following disclaimer in the 13 * documentation and/or other materials provided with the distribution. 14 * 15 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 16 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 17 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 18 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 19 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 20 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 21 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 22 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 23 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 24 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 25 */ 26 27 #include <sys/cdefs.h> 28 __FBSDID("$FreeBSD$"); 29 30 #include "opt_ada.h" 31 #include "opt_ata.h" 32 33 #include <sys/param.h> 34 35 #ifdef _KERNEL 36 #include <sys/systm.h> 37 #include <sys/kernel.h> 38 #include <sys/bio.h> 39 #include <sys/sysctl.h> 40 #include <sys/taskqueue.h> 41 #include <sys/lock.h> 42 #include <sys/mutex.h> 43 #include <sys/conf.h> 44 #include <sys/devicestat.h> 45 #include <sys/eventhandler.h> 46 #include <sys/malloc.h> 47 #include <sys/cons.h> 48 #include <sys/reboot.h> 49 #include <geom/geom_disk.h> 50 #endif /* _KERNEL */ 51 52 #ifndef _KERNEL 53 #include <stdio.h> 54 #include <string.h> 55 #endif /* _KERNEL */ 56 57 #include <cam/cam.h> 58 #include <cam/cam_ccb.h> 59 #include <cam/cam_periph.h> 60 #include <cam/cam_xpt_periph.h> 61 #include <cam/cam_sim.h> 62 63 #include <cam/ata/ata_all.h> 64 65 #include <machine/md_var.h> /* geometry translation */ 66 67 #ifdef _KERNEL 68 69 #define ATA_MAX_28BIT_LBA 268435455UL 70 71 typedef enum { 72 ADA_STATE_RAHEAD, 73 ADA_STATE_WCACHE, 74 ADA_STATE_NORMAL 75 } ada_state; 76 77 typedef enum { 78 ADA_FLAG_PACK_INVALID = 0x001, 79 ADA_FLAG_CAN_48BIT = 0x002, 80 ADA_FLAG_CAN_FLUSHCACHE = 0x004, 81 ADA_FLAG_CAN_NCQ = 0x008, 82 ADA_FLAG_CAN_DMA = 0x010, 83 ADA_FLAG_NEED_OTAG = 0x020, 84 ADA_FLAG_WENT_IDLE = 0x040, 85 ADA_FLAG_CAN_TRIM = 0x080, 86 ADA_FLAG_OPEN = 0x100, 87 ADA_FLAG_SCTX_INIT = 0x200, 88 ADA_FLAG_CAN_CFA = 0x400, 89 ADA_FLAG_CAN_POWERMGT = 0x800 90 } ada_flags; 91 92 typedef enum { 93 ADA_Q_NONE = 0x00, 94 ADA_Q_4K = 0x01, 95 } ada_quirks; 96 97 typedef enum { 98 ADA_CCB_RAHEAD = 0x01, 99 ADA_CCB_WCACHE = 0x02, 100 ADA_CCB_BUFFER_IO = 0x03, 101 ADA_CCB_WAITING = 0x04, 102 ADA_CCB_DUMP = 0x05, 103 ADA_CCB_TRIM = 0x06, 104 ADA_CCB_TYPE_MASK = 0x0F, 105 } ada_ccb_state; 106 107 /* Offsets into our private area for storing information */ 108 #define ccb_state ppriv_field0 109 #define ccb_bp ppriv_ptr1 110 111 struct disk_params { 112 u_int8_t heads; 113 u_int8_t secs_per_track; 114 u_int32_t cylinders; 115 u_int32_t secsize; /* Number of bytes/logical sector */ 116 u_int64_t sectors; /* Total number sectors */ 117 }; 118 119 #define TRIM_MAX_BLOCKS 8 120 #define TRIM_MAX_RANGES (TRIM_MAX_BLOCKS * 64) 121 #define TRIM_MAX_BIOS (TRIM_MAX_RANGES * 4) 122 struct trim_request { 123 uint8_t data[TRIM_MAX_RANGES * 8]; 124 struct bio *bps[TRIM_MAX_BIOS]; 125 }; 126 127 struct ada_softc { 128 struct bio_queue_head bio_queue; 129 struct bio_queue_head trim_queue; 130 ada_state state; 131 ada_flags flags; 132 ada_quirks quirks; 133 int ordered_tag_count; 134 int outstanding_cmds; 135 int trim_max_ranges; 136 int trim_running; 137 int read_ahead; 138 int write_cache; 139 #ifdef ADA_TEST_FAILURE 140 int force_read_error; 141 int force_write_error; 142 int periodic_read_error; 143 int periodic_read_count; 144 #endif 145 struct disk_params params; 146 struct disk *disk; 147 struct task sysctl_task; 148 struct sysctl_ctx_list sysctl_ctx; 149 struct sysctl_oid *sysctl_tree; 150 struct callout sendordered_c; 151 struct trim_request trim_req; 152 }; 153 154 struct ada_quirk_entry { 155 struct scsi_inquiry_pattern inq_pat; 156 ada_quirks quirks; 157 }; 158 159 static struct ada_quirk_entry ada_quirk_table[] = 160 { 161 { 162 /* Hitachi Advanced Format (4k) drives */ 163 { T_DIRECT, SIP_MEDIA_FIXED, "*", "Hitachi H??????????E3*", "*" }, 164 /*quirks*/ADA_Q_4K 165 }, 166 { 167 /* Samsung Advanced Format (4k) drives */ 168 { T_DIRECT, SIP_MEDIA_FIXED, "*", "SAMSUNG HD155UI*", "*" }, 169 /*quirks*/ADA_Q_4K 170 }, 171 { 172 /* Samsung Advanced Format (4k) drives */ 173 { T_DIRECT, SIP_MEDIA_FIXED, "*", "SAMSUNG HD204UI*", "*" }, 174 /*quirks*/ADA_Q_4K 175 }, 176 { 177 /* Seagate Barracuda Green Advanced Format (4k) drives */ 178 { T_DIRECT, SIP_MEDIA_FIXED, "*", "ST????DL*", "*" }, 179 /*quirks*/ADA_Q_4K 180 }, 181 { 182 /* Seagate Barracuda Advanced Format (4k) drives */ 183 { T_DIRECT, SIP_MEDIA_FIXED, "*", "ST???DM*", "*" }, 184 /*quirks*/ADA_Q_4K 185 }, 186 { 187 /* Seagate Barracuda Advanced Format (4k) drives */ 188 { T_DIRECT, SIP_MEDIA_FIXED, "*", "ST????DM*", "*" }, 189 /*quirks*/ADA_Q_4K 190 }, 191 { 192 /* Seagate Momentus Advanced Format (4k) drives */ 193 { T_DIRECT, SIP_MEDIA_FIXED, "*", "ST9500423AS*", "*" }, 194 /*quirks*/ADA_Q_4K 195 }, 196 { 197 /* Seagate Momentus Advanced Format (4k) drives */ 198 { T_DIRECT, SIP_MEDIA_FIXED, "*", "ST9500424AS*", "*" }, 199 /*quirks*/ADA_Q_4K 200 }, 201 { 202 /* Seagate Momentus Advanced Format (4k) drives */ 203 { T_DIRECT, SIP_MEDIA_FIXED, "*", "ST9640423AS*", "*" }, 204 /*quirks*/ADA_Q_4K 205 }, 206 { 207 /* Seagate Momentus Advanced Format (4k) drives */ 208 { T_DIRECT, SIP_MEDIA_FIXED, "*", "ST9640424AS*", "*" }, 209 /*quirks*/ADA_Q_4K 210 }, 211 { 212 /* Seagate Momentus Advanced Format (4k) drives */ 213 { T_DIRECT, SIP_MEDIA_FIXED, "*", "ST9750420AS*", "*" }, 214 /*quirks*/ADA_Q_4K 215 }, 216 { 217 /* Seagate Momentus Advanced Format (4k) drives */ 218 { T_DIRECT, SIP_MEDIA_FIXED, "*", "ST9750422AS*", "*" }, 219 /*quirks*/ADA_Q_4K 220 }, 221 { 222 /* Seagate Momentus Advanced Format (4k) drives */ 223 { T_DIRECT, SIP_MEDIA_FIXED, "*", "ST9750423AS*", "*" }, 224 /*quirks*/ADA_Q_4K 225 }, 226 { 227 /* Seagate Momentus Thin Advanced Format (4k) drives */ 228 { T_DIRECT, SIP_MEDIA_FIXED, "*", "ST???LT*", "*" }, 229 /*quirks*/ADA_Q_4K 230 }, 231 { 232 /* WDC Caviar Green Advanced Format (4k) drives */ 233 { T_DIRECT, SIP_MEDIA_FIXED, "*", "WDC WD????RS*", "*" }, 234 /*quirks*/ADA_Q_4K 235 }, 236 { 237 /* WDC Caviar Green Advanced Format (4k) drives */ 238 { T_DIRECT, SIP_MEDIA_FIXED, "*", "WDC WD????RX*", "*" }, 239 /*quirks*/ADA_Q_4K 240 }, 241 { 242 /* WDC Caviar Green Advanced Format (4k) drives */ 243 { T_DIRECT, SIP_MEDIA_FIXED, "*", "WDC WD??????RS*", "*" }, 244 /*quirks*/ADA_Q_4K 245 }, 246 { 247 /* WDC Caviar Green Advanced Format (4k) drives */ 248 { T_DIRECT, SIP_MEDIA_FIXED, "*", "WDC WD??????RX*", "*" }, 249 /*quirks*/ADA_Q_4K 250 }, 251 { 252 /* WDC Scorpio Black Advanced Format (4k) drives */ 253 { T_DIRECT, SIP_MEDIA_FIXED, "*", "WDC WD???PKT*", "*" }, 254 /*quirks*/ADA_Q_4K 255 }, 256 { 257 /* WDC Scorpio Black Advanced Format (4k) drives */ 258 { T_DIRECT, SIP_MEDIA_FIXED, "*", "WDC WD?????PKT*", "*" }, 259 /*quirks*/ADA_Q_4K 260 }, 261 { 262 /* WDC Scorpio Blue Advanced Format (4k) drives */ 263 { T_DIRECT, SIP_MEDIA_FIXED, "*", "WDC WD???PVT*", "*" }, 264 /*quirks*/ADA_Q_4K 265 }, 266 { 267 /* WDC Scorpio Blue Advanced Format (4k) drives */ 268 { T_DIRECT, SIP_MEDIA_FIXED, "*", "WDC WD?????PVT*", "*" }, 269 /*quirks*/ADA_Q_4K 270 }, 271 { 272 /* Default */ 273 { 274 T_ANY, SIP_MEDIA_REMOVABLE|SIP_MEDIA_FIXED, 275 /*vendor*/"*", /*product*/"*", /*revision*/"*" 276 }, 277 /*quirks*/0 278 }, 279 }; 280 281 static disk_strategy_t adastrategy; 282 static dumper_t adadump; 283 static periph_init_t adainit; 284 static void adaasync(void *callback_arg, u_int32_t code, 285 struct cam_path *path, void *arg); 286 static void adasysctlinit(void *context, int pending); 287 static periph_ctor_t adaregister; 288 static periph_dtor_t adacleanup; 289 static periph_start_t adastart; 290 static periph_oninv_t adaoninvalidate; 291 static void adadone(struct cam_periph *periph, 292 union ccb *done_ccb); 293 static int adaerror(union ccb *ccb, u_int32_t cam_flags, 294 u_int32_t sense_flags); 295 static void adagetparams(struct cam_periph *periph, 296 struct ccb_getdev *cgd); 297 static timeout_t adasendorderedtag; 298 static void adashutdown(void *arg, int howto); 299 static void adasuspend(void *arg); 300 static void adaresume(void *arg); 301 302 #ifndef ADA_DEFAULT_LEGACY_ALIASES 303 #ifdef ATA_CAM 304 #define ADA_DEFAULT_LEGACY_ALIASES 1 305 #else 306 #define ADA_DEFAULT_LEGACY_ALIASES 0 307 #endif 308 #endif 309 310 #ifndef ADA_DEFAULT_TIMEOUT 311 #define ADA_DEFAULT_TIMEOUT 30 /* Timeout in seconds */ 312 #endif 313 314 #ifndef ADA_DEFAULT_RETRY 315 #define ADA_DEFAULT_RETRY 4 316 #endif 317 318 #ifndef ADA_DEFAULT_SEND_ORDERED 319 #define ADA_DEFAULT_SEND_ORDERED 1 320 #endif 321 322 #ifndef ADA_DEFAULT_SPINDOWN_SHUTDOWN 323 #define ADA_DEFAULT_SPINDOWN_SHUTDOWN 1 324 #endif 325 326 #ifndef ADA_DEFAULT_SPINDOWN_SUSPEND 327 #define ADA_DEFAULT_SPINDOWN_SUSPEND 1 328 #endif 329 330 #ifndef ADA_DEFAULT_READ_AHEAD 331 #define ADA_DEFAULT_READ_AHEAD 1 332 #endif 333 334 #ifndef ADA_DEFAULT_WRITE_CACHE 335 #define ADA_DEFAULT_WRITE_CACHE 1 336 #endif 337 338 #define ADA_RA (softc->read_ahead >= 0 ? \ 339 softc->read_ahead : ada_read_ahead) 340 #define ADA_WC (softc->write_cache >= 0 ? \ 341 softc->write_cache : ada_write_cache) 342 343 /* 344 * Most platforms map firmware geometry to actual, but some don't. If 345 * not overridden, default to nothing. 346 */ 347 #ifndef ata_disk_firmware_geom_adjust 348 #define ata_disk_firmware_geom_adjust(disk) 349 #endif 350 351 static int ada_legacy_aliases = ADA_DEFAULT_LEGACY_ALIASES; 352 static int ada_retry_count = ADA_DEFAULT_RETRY; 353 static int ada_default_timeout = ADA_DEFAULT_TIMEOUT; 354 static int ada_send_ordered = ADA_DEFAULT_SEND_ORDERED; 355 static int ada_spindown_shutdown = ADA_DEFAULT_SPINDOWN_SHUTDOWN; 356 static int ada_spindown_suspend = ADA_DEFAULT_SPINDOWN_SUSPEND; 357 static int ada_read_ahead = ADA_DEFAULT_READ_AHEAD; 358 static int ada_write_cache = ADA_DEFAULT_WRITE_CACHE; 359 360 static SYSCTL_NODE(_kern_cam, OID_AUTO, ada, CTLFLAG_RD, 0, 361 "CAM Direct Access Disk driver"); 362 SYSCTL_INT(_kern_cam_ada, OID_AUTO, legacy_aliases, CTLFLAG_RW, 363 &ada_legacy_aliases, 0, "Create legacy-like device aliases"); 364 TUNABLE_INT("kern.cam.ada.legacy_aliases", &ada_legacy_aliases); 365 SYSCTL_INT(_kern_cam_ada, OID_AUTO, retry_count, CTLFLAG_RW, 366 &ada_retry_count, 0, "Normal I/O retry count"); 367 TUNABLE_INT("kern.cam.ada.retry_count", &ada_retry_count); 368 SYSCTL_INT(_kern_cam_ada, OID_AUTO, default_timeout, CTLFLAG_RW, 369 &ada_default_timeout, 0, "Normal I/O timeout (in seconds)"); 370 TUNABLE_INT("kern.cam.ada.default_timeout", &ada_default_timeout); 371 SYSCTL_INT(_kern_cam_ada, OID_AUTO, ada_send_ordered, CTLFLAG_RW, 372 &ada_send_ordered, 0, "Send Ordered Tags"); 373 TUNABLE_INT("kern.cam.ada.ada_send_ordered", &ada_send_ordered); 374 SYSCTL_INT(_kern_cam_ada, OID_AUTO, spindown_shutdown, CTLFLAG_RW, 375 &ada_spindown_shutdown, 0, "Spin down upon shutdown"); 376 TUNABLE_INT("kern.cam.ada.spindown_shutdown", &ada_spindown_shutdown); 377 SYSCTL_INT(_kern_cam_ada, OID_AUTO, spindown_suspend, CTLFLAG_RW, 378 &ada_spindown_suspend, 0, "Spin down upon suspend"); 379 TUNABLE_INT("kern.cam.ada.spindown_suspend", &ada_spindown_suspend); 380 SYSCTL_INT(_kern_cam_ada, OID_AUTO, read_ahead, CTLFLAG_RW, 381 &ada_read_ahead, 0, "Enable disk read-ahead"); 382 TUNABLE_INT("kern.cam.ada.read_ahead", &ada_read_ahead); 383 SYSCTL_INT(_kern_cam_ada, OID_AUTO, write_cache, CTLFLAG_RW, 384 &ada_write_cache, 0, "Enable disk write cache"); 385 TUNABLE_INT("kern.cam.ada.write_cache", &ada_write_cache); 386 387 /* 388 * ADA_ORDEREDTAG_INTERVAL determines how often, relative 389 * to the default timeout, we check to see whether an ordered 390 * tagged transaction is appropriate to prevent simple tag 391 * starvation. Since we'd like to ensure that there is at least 392 * 1/2 of the timeout length left for a starved transaction to 393 * complete after we've sent an ordered tag, we must poll at least 394 * four times in every timeout period. This takes care of the worst 395 * case where a starved transaction starts during an interval that 396 * meets the requirement "don't send an ordered tag" test so it takes 397 * us two intervals to determine that a tag must be sent. 398 */ 399 #ifndef ADA_ORDEREDTAG_INTERVAL 400 #define ADA_ORDEREDTAG_INTERVAL 4 401 #endif 402 403 static struct periph_driver adadriver = 404 { 405 adainit, "ada", 406 TAILQ_HEAD_INITIALIZER(adadriver.units), /* generation */ 0 407 }; 408 409 PERIPHDRIVER_DECLARE(ada, adadriver); 410 411 static MALLOC_DEFINE(M_ATADA, "ata_da", "ata_da buffers"); 412 413 static int 414 adaopen(struct disk *dp) 415 { 416 struct cam_periph *periph; 417 struct ada_softc *softc; 418 int error; 419 420 periph = (struct cam_periph *)dp->d_drv1; 421 if (periph == NULL) { 422 return (ENXIO); 423 } 424 425 if (cam_periph_acquire(periph) != CAM_REQ_CMP) { 426 return(ENXIO); 427 } 428 429 cam_periph_lock(periph); 430 if ((error = cam_periph_hold(periph, PRIBIO|PCATCH)) != 0) { 431 cam_periph_unlock(periph); 432 cam_periph_release(periph); 433 return (error); 434 } 435 436 softc = (struct ada_softc *)periph->softc; 437 softc->flags |= ADA_FLAG_OPEN; 438 439 CAM_DEBUG(periph->path, CAM_DEBUG_TRACE, 440 ("adaopen: disk=%s%d (unit %d)\n", dp->d_name, dp->d_unit, 441 periph->unit_number)); 442 443 if ((softc->flags & ADA_FLAG_PACK_INVALID) != 0) { 444 /* Invalidate our pack information. */ 445 softc->flags &= ~ADA_FLAG_PACK_INVALID; 446 } 447 448 cam_periph_unhold(periph); 449 cam_periph_unlock(periph); 450 return (0); 451 } 452 453 static int 454 adaclose(struct disk *dp) 455 { 456 struct cam_periph *periph; 457 struct ada_softc *softc; 458 union ccb *ccb; 459 460 periph = (struct cam_periph *)dp->d_drv1; 461 if (periph == NULL) 462 return (ENXIO); 463 464 cam_periph_lock(periph); 465 if (cam_periph_hold(periph, PRIBIO) != 0) { 466 cam_periph_unlock(periph); 467 cam_periph_release(periph); 468 return (0); 469 } 470 471 softc = (struct ada_softc *)periph->softc; 472 /* We only sync the cache if the drive is capable of it. */ 473 if ((softc->flags & ADA_FLAG_CAN_FLUSHCACHE) != 0 && 474 (softc->flags & ADA_FLAG_PACK_INVALID) == 0) { 475 476 ccb = cam_periph_getccb(periph, CAM_PRIORITY_NORMAL); 477 cam_fill_ataio(&ccb->ataio, 478 1, 479 adadone, 480 CAM_DIR_NONE, 481 0, 482 NULL, 483 0, 484 ada_default_timeout*1000); 485 486 if (softc->flags & ADA_FLAG_CAN_48BIT) 487 ata_48bit_cmd(&ccb->ataio, ATA_FLUSHCACHE48, 0, 0, 0); 488 else 489 ata_28bit_cmd(&ccb->ataio, ATA_FLUSHCACHE, 0, 0, 0); 490 cam_periph_runccb(ccb, /*error_routine*/NULL, /*cam_flags*/0, 491 /*sense_flags*/0, softc->disk->d_devstat); 492 493 if ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) 494 xpt_print(periph->path, "Synchronize cache failed\n"); 495 xpt_release_ccb(ccb); 496 } 497 498 softc->flags &= ~ADA_FLAG_OPEN; 499 cam_periph_unhold(periph); 500 cam_periph_unlock(periph); 501 cam_periph_release(periph); 502 return (0); 503 } 504 505 static void 506 adaschedule(struct cam_periph *periph) 507 { 508 struct ada_softc *softc = (struct ada_softc *)periph->softc; 509 uint32_t prio; 510 511 /* Check if cam_periph_getccb() was called. */ 512 prio = periph->immediate_priority; 513 514 /* Check if we have more work to do. */ 515 if (bioq_first(&softc->bio_queue) || 516 (!softc->trim_running && bioq_first(&softc->trim_queue))) { 517 prio = CAM_PRIORITY_NORMAL; 518 } 519 520 /* Schedule CCB if any of above is true. */ 521 if (prio != CAM_PRIORITY_NONE) 522 xpt_schedule(periph, prio); 523 } 524 525 /* 526 * Actually translate the requested transfer into one the physical driver 527 * can understand. The transfer is described by a buf and will include 528 * only one physical transfer. 529 */ 530 static void 531 adastrategy(struct bio *bp) 532 { 533 struct cam_periph *periph; 534 struct ada_softc *softc; 535 536 periph = (struct cam_periph *)bp->bio_disk->d_drv1; 537 if (periph == NULL) { 538 biofinish(bp, NULL, ENXIO); 539 return; 540 } 541 softc = (struct ada_softc *)periph->softc; 542 543 cam_periph_lock(periph); 544 545 /* 546 * If the device has been made invalid, error out 547 */ 548 if ((softc->flags & ADA_FLAG_PACK_INVALID)) { 549 cam_periph_unlock(periph); 550 biofinish(bp, NULL, ENXIO); 551 return; 552 } 553 554 /* 555 * Place it in the queue of disk activities for this disk 556 */ 557 if (bp->bio_cmd == BIO_DELETE && 558 (softc->flags & ADA_FLAG_CAN_TRIM)) 559 bioq_disksort(&softc->trim_queue, bp); 560 else 561 bioq_disksort(&softc->bio_queue, bp); 562 563 /* 564 * Schedule ourselves for performing the work. 565 */ 566 adaschedule(periph); 567 cam_periph_unlock(periph); 568 569 return; 570 } 571 572 static int 573 adadump(void *arg, void *virtual, vm_offset_t physical, off_t offset, size_t length) 574 { 575 struct cam_periph *periph; 576 struct ada_softc *softc; 577 u_int secsize; 578 union ccb ccb; 579 struct disk *dp; 580 uint64_t lba; 581 uint16_t count; 582 583 dp = arg; 584 periph = dp->d_drv1; 585 if (periph == NULL) 586 return (ENXIO); 587 softc = (struct ada_softc *)periph->softc; 588 cam_periph_lock(periph); 589 secsize = softc->params.secsize; 590 lba = offset / secsize; 591 count = length / secsize; 592 593 if ((softc->flags & ADA_FLAG_PACK_INVALID) != 0) { 594 cam_periph_unlock(periph); 595 return (ENXIO); 596 } 597 598 if (length > 0) { 599 xpt_setup_ccb(&ccb.ccb_h, periph->path, CAM_PRIORITY_NORMAL); 600 ccb.ccb_h.ccb_state = ADA_CCB_DUMP; 601 cam_fill_ataio(&ccb.ataio, 602 0, 603 adadone, 604 CAM_DIR_OUT, 605 0, 606 (u_int8_t *) virtual, 607 length, 608 ada_default_timeout*1000); 609 if ((softc->flags & ADA_FLAG_CAN_48BIT) && 610 (lba + count >= ATA_MAX_28BIT_LBA || 611 count >= 256)) { 612 ata_48bit_cmd(&ccb.ataio, ATA_WRITE_DMA48, 613 0, lba, count); 614 } else { 615 ata_28bit_cmd(&ccb.ataio, ATA_WRITE_DMA, 616 0, lba, count); 617 } 618 xpt_polled_action(&ccb); 619 620 if ((ccb.ataio.ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) { 621 printf("Aborting dump due to I/O error.\n"); 622 cam_periph_unlock(periph); 623 return(EIO); 624 } 625 cam_periph_unlock(periph); 626 return(0); 627 } 628 629 if (softc->flags & ADA_FLAG_CAN_FLUSHCACHE) { 630 xpt_setup_ccb(&ccb.ccb_h, periph->path, CAM_PRIORITY_NORMAL); 631 632 ccb.ccb_h.ccb_state = ADA_CCB_DUMP; 633 cam_fill_ataio(&ccb.ataio, 634 1, 635 adadone, 636 CAM_DIR_NONE, 637 0, 638 NULL, 639 0, 640 ada_default_timeout*1000); 641 642 if (softc->flags & ADA_FLAG_CAN_48BIT) 643 ata_48bit_cmd(&ccb.ataio, ATA_FLUSHCACHE48, 0, 0, 0); 644 else 645 ata_28bit_cmd(&ccb.ataio, ATA_FLUSHCACHE, 0, 0, 0); 646 xpt_polled_action(&ccb); 647 648 if ((ccb.ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) 649 xpt_print(periph->path, "Synchronize cache failed\n"); 650 651 if ((ccb.ccb_h.status & CAM_DEV_QFRZN) != 0) 652 cam_release_devq(ccb.ccb_h.path, 653 /*relsim_flags*/0, 654 /*reduction*/0, 655 /*timeout*/0, 656 /*getcount_only*/0); 657 } 658 cam_periph_unlock(periph); 659 return (0); 660 } 661 662 static void 663 adainit(void) 664 { 665 cam_status status; 666 667 /* 668 * Install a global async callback. This callback will 669 * receive async callbacks like "new device found". 670 */ 671 status = xpt_register_async(AC_FOUND_DEVICE, adaasync, NULL, NULL); 672 673 if (status != CAM_REQ_CMP) { 674 printf("ada: Failed to attach master async callback " 675 "due to status 0x%x!\n", status); 676 } else if (ada_send_ordered) { 677 678 /* Register our event handlers */ 679 if ((EVENTHANDLER_REGISTER(power_suspend, adasuspend, 680 NULL, EVENTHANDLER_PRI_LAST)) == NULL) 681 printf("adainit: power event registration failed!\n"); 682 if ((EVENTHANDLER_REGISTER(power_resume, adaresume, 683 NULL, EVENTHANDLER_PRI_LAST)) == NULL) 684 printf("adainit: power event registration failed!\n"); 685 if ((EVENTHANDLER_REGISTER(shutdown_post_sync, adashutdown, 686 NULL, SHUTDOWN_PRI_DEFAULT)) == NULL) 687 printf("adainit: shutdown event registration failed!\n"); 688 } 689 } 690 691 static void 692 adaoninvalidate(struct cam_periph *periph) 693 { 694 struct ada_softc *softc; 695 696 softc = (struct ada_softc *)periph->softc; 697 698 /* 699 * De-register any async callbacks. 700 */ 701 xpt_register_async(0, adaasync, periph, periph->path); 702 703 softc->flags |= ADA_FLAG_PACK_INVALID; 704 705 /* 706 * Return all queued I/O with ENXIO. 707 * XXX Handle any transactions queued to the card 708 * with XPT_ABORT_CCB. 709 */ 710 bioq_flush(&softc->bio_queue, NULL, ENXIO); 711 bioq_flush(&softc->trim_queue, NULL, ENXIO); 712 713 disk_gone(softc->disk); 714 xpt_print(periph->path, "lost device\n"); 715 } 716 717 static void 718 adacleanup(struct cam_periph *periph) 719 { 720 struct ada_softc *softc; 721 722 softc = (struct ada_softc *)periph->softc; 723 724 xpt_print(periph->path, "removing device entry\n"); 725 cam_periph_unlock(periph); 726 727 /* 728 * If we can't free the sysctl tree, oh well... 729 */ 730 if ((softc->flags & ADA_FLAG_SCTX_INIT) != 0 731 && sysctl_ctx_free(&softc->sysctl_ctx) != 0) { 732 xpt_print(periph->path, "can't remove sysctl context\n"); 733 } 734 735 disk_destroy(softc->disk); 736 callout_drain(&softc->sendordered_c); 737 free(softc, M_DEVBUF); 738 cam_periph_lock(periph); 739 } 740 741 static void 742 adaasync(void *callback_arg, u_int32_t code, 743 struct cam_path *path, void *arg) 744 { 745 struct ccb_getdev cgd; 746 struct cam_periph *periph; 747 struct ada_softc *softc; 748 749 periph = (struct cam_periph *)callback_arg; 750 switch (code) { 751 case AC_FOUND_DEVICE: 752 { 753 struct ccb_getdev *cgd; 754 cam_status status; 755 756 cgd = (struct ccb_getdev *)arg; 757 if (cgd == NULL) 758 break; 759 760 if (cgd->protocol != PROTO_ATA) 761 break; 762 763 /* 764 * Allocate a peripheral instance for 765 * this device and start the probe 766 * process. 767 */ 768 status = cam_periph_alloc(adaregister, adaoninvalidate, 769 adacleanup, adastart, 770 "ada", CAM_PERIPH_BIO, 771 cgd->ccb_h.path, adaasync, 772 AC_FOUND_DEVICE, cgd); 773 774 if (status != CAM_REQ_CMP 775 && status != CAM_REQ_INPROG) 776 printf("adaasync: Unable to attach to new device " 777 "due to status 0x%x\n", status); 778 break; 779 } 780 case AC_GETDEV_CHANGED: 781 { 782 softc = (struct ada_softc *)periph->softc; 783 xpt_setup_ccb(&cgd.ccb_h, periph->path, CAM_PRIORITY_NORMAL); 784 cgd.ccb_h.func_code = XPT_GDEV_TYPE; 785 xpt_action((union ccb *)&cgd); 786 787 if ((cgd.ident_data.capabilities1 & ATA_SUPPORT_DMA) && 788 (cgd.inq_flags & SID_DMA)) 789 softc->flags |= ADA_FLAG_CAN_DMA; 790 else 791 softc->flags &= ~ADA_FLAG_CAN_DMA; 792 if ((cgd.ident_data.satacapabilities & ATA_SUPPORT_NCQ) && 793 (cgd.inq_flags & SID_DMA) && (cgd.inq_flags & SID_CmdQue)) 794 softc->flags |= ADA_FLAG_CAN_NCQ; 795 else 796 softc->flags &= ~ADA_FLAG_CAN_NCQ; 797 if ((cgd.ident_data.support_dsm & ATA_SUPPORT_DSM_TRIM) && 798 (cgd.inq_flags & SID_DMA)) 799 softc->flags |= ADA_FLAG_CAN_TRIM; 800 else 801 softc->flags &= ~ADA_FLAG_CAN_TRIM; 802 803 cam_periph_async(periph, code, path, arg); 804 break; 805 } 806 case AC_ADVINFO_CHANGED: 807 { 808 uintptr_t buftype; 809 810 buftype = (uintptr_t)arg; 811 if (buftype == CDAI_TYPE_PHYS_PATH) { 812 struct ada_softc *softc; 813 814 softc = periph->softc; 815 disk_attr_changed(softc->disk, "GEOM::physpath", 816 M_NOWAIT); 817 } 818 break; 819 } 820 case AC_SENT_BDR: 821 case AC_BUS_RESET: 822 { 823 softc = (struct ada_softc *)periph->softc; 824 cam_periph_async(periph, code, path, arg); 825 if (softc->state != ADA_STATE_NORMAL) 826 break; 827 xpt_setup_ccb(&cgd.ccb_h, periph->path, CAM_PRIORITY_NORMAL); 828 cgd.ccb_h.func_code = XPT_GDEV_TYPE; 829 xpt_action((union ccb *)&cgd); 830 if (ADA_RA >= 0 && 831 cgd.ident_data.support.command1 & ATA_SUPPORT_LOOKAHEAD) 832 softc->state = ADA_STATE_RAHEAD; 833 else if (ADA_WC >= 0 && 834 cgd.ident_data.support.command1 & ATA_SUPPORT_WRITECACHE) 835 softc->state = ADA_STATE_WCACHE; 836 else 837 break; 838 cam_periph_acquire(periph); 839 cam_freeze_devq_arg(periph->path, 840 RELSIM_RELEASE_RUNLEVEL, CAM_RL_DEV + 1); 841 xpt_schedule(periph, CAM_PRIORITY_DEV); 842 } 843 default: 844 cam_periph_async(periph, code, path, arg); 845 break; 846 } 847 } 848 849 static void 850 adasysctlinit(void *context, int pending) 851 { 852 struct cam_periph *periph; 853 struct ada_softc *softc; 854 char tmpstr[80], tmpstr2[80]; 855 856 periph = (struct cam_periph *)context; 857 858 /* periph was held for us when this task was enqueued */ 859 if (periph->flags & CAM_PERIPH_INVALID) { 860 cam_periph_release(periph); 861 return; 862 } 863 864 softc = (struct ada_softc *)periph->softc; 865 snprintf(tmpstr, sizeof(tmpstr), "CAM ADA unit %d", periph->unit_number); 866 snprintf(tmpstr2, sizeof(tmpstr2), "%d", periph->unit_number); 867 868 sysctl_ctx_init(&softc->sysctl_ctx); 869 softc->flags |= ADA_FLAG_SCTX_INIT; 870 softc->sysctl_tree = SYSCTL_ADD_NODE(&softc->sysctl_ctx, 871 SYSCTL_STATIC_CHILDREN(_kern_cam_ada), OID_AUTO, tmpstr2, 872 CTLFLAG_RD, 0, tmpstr); 873 if (softc->sysctl_tree == NULL) { 874 printf("adasysctlinit: unable to allocate sysctl tree\n"); 875 cam_periph_release(periph); 876 return; 877 } 878 879 SYSCTL_ADD_INT(&softc->sysctl_ctx, SYSCTL_CHILDREN(softc->sysctl_tree), 880 OID_AUTO, "read_ahead", CTLFLAG_RW | CTLFLAG_MPSAFE, 881 &softc->read_ahead, 0, "Enable disk read ahead."); 882 SYSCTL_ADD_INT(&softc->sysctl_ctx, SYSCTL_CHILDREN(softc->sysctl_tree), 883 OID_AUTO, "write_cache", CTLFLAG_RW | CTLFLAG_MPSAFE, 884 &softc->write_cache, 0, "Enable disk write cache."); 885 #ifdef ADA_TEST_FAILURE 886 /* 887 * Add a 'door bell' sysctl which allows one to set it from userland 888 * and cause something bad to happen. For the moment, we only allow 889 * whacking the next read or write. 890 */ 891 SYSCTL_ADD_INT(&softc->sysctl_ctx, SYSCTL_CHILDREN(softc->sysctl_tree), 892 OID_AUTO, "force_read_error", CTLFLAG_RW | CTLFLAG_MPSAFE, 893 &softc->force_read_error, 0, 894 "Force a read error for the next N reads."); 895 SYSCTL_ADD_INT(&softc->sysctl_ctx, SYSCTL_CHILDREN(softc->sysctl_tree), 896 OID_AUTO, "force_write_error", CTLFLAG_RW | CTLFLAG_MPSAFE, 897 &softc->force_write_error, 0, 898 "Force a write error for the next N writes."); 899 SYSCTL_ADD_INT(&softc->sysctl_ctx, SYSCTL_CHILDREN(softc->sysctl_tree), 900 OID_AUTO, "periodic_read_error", CTLFLAG_RW | CTLFLAG_MPSAFE, 901 &softc->periodic_read_error, 0, 902 "Force a read error every N reads (don't set too low)."); 903 #endif 904 cam_periph_release(periph); 905 } 906 907 static int 908 adagetattr(struct bio *bp) 909 { 910 int ret = -1; 911 struct cam_periph *periph; 912 913 if (bp->bio_disk == NULL || bp->bio_disk->d_drv1 == NULL) 914 return ENXIO; 915 periph = (struct cam_periph *)bp->bio_disk->d_drv1; 916 if (periph->path == NULL) 917 return ENXIO; 918 919 ret = xpt_getattr(bp->bio_data, bp->bio_length, bp->bio_attribute, 920 periph->path); 921 if (ret == 0) 922 bp->bio_completed = bp->bio_length; 923 return ret; 924 } 925 926 static cam_status 927 adaregister(struct cam_periph *periph, void *arg) 928 { 929 struct ada_softc *softc; 930 struct ccb_pathinq cpi; 931 struct ccb_getdev *cgd; 932 char announce_buf[80], buf1[32]; 933 struct disk_params *dp; 934 caddr_t match; 935 u_int maxio; 936 int legacy_id, quirks; 937 938 cgd = (struct ccb_getdev *)arg; 939 if (periph == NULL) { 940 printf("adaregister: periph was NULL!!\n"); 941 return(CAM_REQ_CMP_ERR); 942 } 943 944 if (cgd == NULL) { 945 printf("adaregister: no getdev CCB, can't register device\n"); 946 return(CAM_REQ_CMP_ERR); 947 } 948 949 softc = (struct ada_softc *)malloc(sizeof(*softc), M_DEVBUF, 950 M_NOWAIT|M_ZERO); 951 952 if (softc == NULL) { 953 printf("adaregister: Unable to probe new device. " 954 "Unable to allocate softc\n"); 955 return(CAM_REQ_CMP_ERR); 956 } 957 958 bioq_init(&softc->bio_queue); 959 bioq_init(&softc->trim_queue); 960 961 if ((cgd->ident_data.capabilities1 & ATA_SUPPORT_DMA) && 962 (cgd->inq_flags & SID_DMA)) 963 softc->flags |= ADA_FLAG_CAN_DMA; 964 if (cgd->ident_data.support.command2 & ATA_SUPPORT_ADDRESS48) 965 softc->flags |= ADA_FLAG_CAN_48BIT; 966 if (cgd->ident_data.support.command2 & ATA_SUPPORT_FLUSHCACHE) 967 softc->flags |= ADA_FLAG_CAN_FLUSHCACHE; 968 if (cgd->ident_data.support.command1 & ATA_SUPPORT_POWERMGT) 969 softc->flags |= ADA_FLAG_CAN_POWERMGT; 970 if ((cgd->ident_data.satacapabilities & ATA_SUPPORT_NCQ) && 971 (cgd->inq_flags & SID_DMA) && (cgd->inq_flags & SID_CmdQue)) 972 softc->flags |= ADA_FLAG_CAN_NCQ; 973 if ((cgd->ident_data.support_dsm & ATA_SUPPORT_DSM_TRIM) && 974 (cgd->inq_flags & SID_DMA)) { 975 softc->flags |= ADA_FLAG_CAN_TRIM; 976 softc->trim_max_ranges = TRIM_MAX_RANGES; 977 if (cgd->ident_data.max_dsm_blocks != 0) { 978 softc->trim_max_ranges = 979 min(cgd->ident_data.max_dsm_blocks * 64, 980 softc->trim_max_ranges); 981 } 982 } 983 if (cgd->ident_data.support.command2 & ATA_SUPPORT_CFA) 984 softc->flags |= ADA_FLAG_CAN_CFA; 985 986 periph->softc = softc; 987 988 /* 989 * See if this device has any quirks. 990 */ 991 match = cam_quirkmatch((caddr_t)&cgd->ident_data, 992 (caddr_t)ada_quirk_table, 993 sizeof(ada_quirk_table)/sizeof(*ada_quirk_table), 994 sizeof(*ada_quirk_table), ata_identify_match); 995 if (match != NULL) 996 softc->quirks = ((struct ada_quirk_entry *)match)->quirks; 997 else 998 softc->quirks = ADA_Q_NONE; 999 1000 bzero(&cpi, sizeof(cpi)); 1001 xpt_setup_ccb(&cpi.ccb_h, periph->path, CAM_PRIORITY_NONE); 1002 cpi.ccb_h.func_code = XPT_PATH_INQ; 1003 xpt_action((union ccb *)&cpi); 1004 1005 TASK_INIT(&softc->sysctl_task, 0, adasysctlinit, periph); 1006 1007 /* 1008 * Register this media as a disk 1009 */ 1010 (void)cam_periph_hold(periph, PRIBIO); 1011 mtx_unlock(periph->sim->mtx); 1012 snprintf(announce_buf, sizeof(announce_buf), 1013 "kern.cam.ada.%d.quirks", periph->unit_number); 1014 quirks = softc->quirks; 1015 TUNABLE_INT_FETCH(announce_buf, &quirks); 1016 softc->quirks = quirks; 1017 softc->read_ahead = -1; 1018 snprintf(announce_buf, sizeof(announce_buf), 1019 "kern.cam.ada.%d.read_ahead", periph->unit_number); 1020 TUNABLE_INT_FETCH(announce_buf, &softc->read_ahead); 1021 softc->write_cache = -1; 1022 snprintf(announce_buf, sizeof(announce_buf), 1023 "kern.cam.ada.%d.write_cache", periph->unit_number); 1024 TUNABLE_INT_FETCH(announce_buf, &softc->write_cache); 1025 adagetparams(periph, cgd); 1026 softc->disk = disk_alloc(); 1027 softc->disk->d_devstat = devstat_new_entry(periph->periph_name, 1028 periph->unit_number, softc->params.secsize, 1029 DEVSTAT_ALL_SUPPORTED, 1030 DEVSTAT_TYPE_DIRECT | 1031 XPORT_DEVSTAT_TYPE(cpi.transport), 1032 DEVSTAT_PRIORITY_DISK); 1033 softc->disk->d_open = adaopen; 1034 softc->disk->d_close = adaclose; 1035 softc->disk->d_strategy = adastrategy; 1036 softc->disk->d_getattr = adagetattr; 1037 softc->disk->d_dump = adadump; 1038 softc->disk->d_name = "ada"; 1039 softc->disk->d_drv1 = periph; 1040 maxio = cpi.maxio; /* Honor max I/O size of SIM */ 1041 if (maxio == 0) 1042 maxio = DFLTPHYS; /* traditional default */ 1043 else if (maxio > MAXPHYS) 1044 maxio = MAXPHYS; /* for safety */ 1045 if (softc->flags & ADA_FLAG_CAN_48BIT) 1046 maxio = min(maxio, 65536 * softc->params.secsize); 1047 else /* 28bit ATA command limit */ 1048 maxio = min(maxio, 256 * softc->params.secsize); 1049 softc->disk->d_maxsize = maxio; 1050 softc->disk->d_unit = periph->unit_number; 1051 softc->disk->d_flags = 0; 1052 if (softc->flags & ADA_FLAG_CAN_FLUSHCACHE) 1053 softc->disk->d_flags |= DISKFLAG_CANFLUSHCACHE; 1054 if ((softc->flags & ADA_FLAG_CAN_TRIM) || 1055 ((softc->flags & ADA_FLAG_CAN_CFA) && 1056 !(softc->flags & ADA_FLAG_CAN_48BIT))) 1057 softc->disk->d_flags |= DISKFLAG_CANDELETE; 1058 strlcpy(softc->disk->d_descr, cgd->ident_data.model, 1059 MIN(sizeof(softc->disk->d_descr), sizeof(cgd->ident_data.model))); 1060 softc->disk->d_hba_vendor = cpi.hba_vendor; 1061 softc->disk->d_hba_device = cpi.hba_device; 1062 softc->disk->d_hba_subvendor = cpi.hba_subvendor; 1063 softc->disk->d_hba_subdevice = cpi.hba_subdevice; 1064 1065 softc->disk->d_sectorsize = softc->params.secsize; 1066 softc->disk->d_mediasize = (off_t)softc->params.sectors * 1067 softc->params.secsize; 1068 if (ata_physical_sector_size(&cgd->ident_data) != 1069 softc->params.secsize) { 1070 softc->disk->d_stripesize = 1071 ata_physical_sector_size(&cgd->ident_data); 1072 softc->disk->d_stripeoffset = (softc->disk->d_stripesize - 1073 ata_logical_sector_offset(&cgd->ident_data)) % 1074 softc->disk->d_stripesize; 1075 } else if (softc->quirks & ADA_Q_4K) { 1076 softc->disk->d_stripesize = 4096; 1077 softc->disk->d_stripeoffset = 0; 1078 } 1079 softc->disk->d_fwsectors = softc->params.secs_per_track; 1080 softc->disk->d_fwheads = softc->params.heads; 1081 ata_disk_firmware_geom_adjust(softc->disk); 1082 1083 if (ada_legacy_aliases) { 1084 #ifdef ATA_STATIC_ID 1085 legacy_id = xpt_path_legacy_ata_id(periph->path); 1086 #else 1087 legacy_id = softc->disk->d_unit; 1088 #endif 1089 if (legacy_id >= 0) { 1090 snprintf(announce_buf, sizeof(announce_buf), 1091 "kern.devalias.%s%d", 1092 softc->disk->d_name, softc->disk->d_unit); 1093 snprintf(buf1, sizeof(buf1), 1094 "ad%d", legacy_id); 1095 setenv(announce_buf, buf1); 1096 } 1097 } else 1098 legacy_id = -1; 1099 disk_create(softc->disk, DISK_VERSION); 1100 mtx_lock(periph->sim->mtx); 1101 cam_periph_unhold(periph); 1102 1103 dp = &softc->params; 1104 snprintf(announce_buf, sizeof(announce_buf), 1105 "%juMB (%ju %u byte sectors: %dH %dS/T %dC)", 1106 (uintmax_t)(((uintmax_t)dp->secsize * 1107 dp->sectors) / (1024*1024)), 1108 (uintmax_t)dp->sectors, 1109 dp->secsize, dp->heads, 1110 dp->secs_per_track, dp->cylinders); 1111 xpt_announce_periph(periph, announce_buf); 1112 if (legacy_id >= 0) 1113 printf("%s%d: Previously was known as ad%d\n", 1114 periph->periph_name, periph->unit_number, legacy_id); 1115 1116 /* 1117 * Create our sysctl variables, now that we know 1118 * we have successfully attached. 1119 */ 1120 cam_periph_acquire(periph); 1121 taskqueue_enqueue(taskqueue_thread, &softc->sysctl_task); 1122 1123 /* 1124 * Add async callbacks for bus reset and 1125 * bus device reset calls. I don't bother 1126 * checking if this fails as, in most cases, 1127 * the system will function just fine without 1128 * them and the only alternative would be to 1129 * not attach the device on failure. 1130 */ 1131 xpt_register_async(AC_SENT_BDR | AC_BUS_RESET | AC_LOST_DEVICE | 1132 AC_GETDEV_CHANGED | AC_ADVINFO_CHANGED, 1133 adaasync, periph, periph->path); 1134 1135 /* 1136 * Schedule a periodic event to occasionally send an 1137 * ordered tag to a device. 1138 */ 1139 callout_init_mtx(&softc->sendordered_c, periph->sim->mtx, 0); 1140 callout_reset(&softc->sendordered_c, 1141 (ada_default_timeout * hz) / ADA_ORDEREDTAG_INTERVAL, 1142 adasendorderedtag, softc); 1143 1144 if (ADA_RA >= 0 && 1145 cgd->ident_data.support.command1 & ATA_SUPPORT_LOOKAHEAD) { 1146 softc->state = ADA_STATE_RAHEAD; 1147 cam_periph_acquire(periph); 1148 cam_freeze_devq_arg(periph->path, 1149 RELSIM_RELEASE_RUNLEVEL, CAM_RL_DEV + 1); 1150 xpt_schedule(periph, CAM_PRIORITY_DEV); 1151 } else if (ADA_WC >= 0 && 1152 cgd->ident_data.support.command1 & ATA_SUPPORT_WRITECACHE) { 1153 softc->state = ADA_STATE_WCACHE; 1154 cam_periph_acquire(periph); 1155 cam_freeze_devq_arg(periph->path, 1156 RELSIM_RELEASE_RUNLEVEL, CAM_RL_DEV + 1); 1157 xpt_schedule(periph, CAM_PRIORITY_DEV); 1158 } else 1159 softc->state = ADA_STATE_NORMAL; 1160 1161 return(CAM_REQ_CMP); 1162 } 1163 1164 static void 1165 adastart(struct cam_periph *periph, union ccb *start_ccb) 1166 { 1167 struct ada_softc *softc = (struct ada_softc *)periph->softc; 1168 struct ccb_ataio *ataio = &start_ccb->ataio; 1169 1170 switch (softc->state) { 1171 case ADA_STATE_NORMAL: 1172 { 1173 struct bio *bp; 1174 u_int8_t tag_code; 1175 1176 /* Execute immediate CCB if waiting. */ 1177 if (periph->immediate_priority <= periph->pinfo.priority) { 1178 CAM_DEBUG_PRINT(CAM_DEBUG_SUBTRACE, 1179 ("queuing for immediate ccb\n")); 1180 start_ccb->ccb_h.ccb_state = ADA_CCB_WAITING; 1181 SLIST_INSERT_HEAD(&periph->ccb_list, &start_ccb->ccb_h, 1182 periph_links.sle); 1183 periph->immediate_priority = CAM_PRIORITY_NONE; 1184 wakeup(&periph->ccb_list); 1185 /* Have more work to do, so ensure we stay scheduled */ 1186 adaschedule(periph); 1187 break; 1188 } 1189 /* Run TRIM if not running yet. */ 1190 if (!softc->trim_running && 1191 (bp = bioq_first(&softc->trim_queue)) != 0) { 1192 struct trim_request *req = &softc->trim_req; 1193 struct bio *bp1; 1194 uint64_t lastlba = (uint64_t)-1; 1195 int bps = 0, c, lastcount = 0, off, ranges = 0; 1196 1197 softc->trim_running = 1; 1198 bzero(req, sizeof(*req)); 1199 bp1 = bp; 1200 do { 1201 uint64_t lba = bp1->bio_pblkno; 1202 int count = bp1->bio_bcount / 1203 softc->params.secsize; 1204 1205 bioq_remove(&softc->trim_queue, bp1); 1206 1207 /* Try to extend the previous range. */ 1208 if (lba == lastlba) { 1209 c = min(count, 0xffff - lastcount); 1210 lastcount += c; 1211 off = (ranges - 1) * 8; 1212 req->data[off + 6] = lastcount & 0xff; 1213 req->data[off + 7] = 1214 (lastcount >> 8) & 0xff; 1215 count -= c; 1216 lba += c; 1217 } 1218 1219 while (count > 0) { 1220 c = min(count, 0xffff); 1221 off = ranges * 8; 1222 req->data[off + 0] = lba & 0xff; 1223 req->data[off + 1] = (lba >> 8) & 0xff; 1224 req->data[off + 2] = (lba >> 16) & 0xff; 1225 req->data[off + 3] = (lba >> 24) & 0xff; 1226 req->data[off + 4] = (lba >> 32) & 0xff; 1227 req->data[off + 5] = (lba >> 40) & 0xff; 1228 req->data[off + 6] = c & 0xff; 1229 req->data[off + 7] = (c >> 8) & 0xff; 1230 lba += c; 1231 count -= c; 1232 lastcount = c; 1233 ranges++; 1234 } 1235 lastlba = lba; 1236 req->bps[bps++] = bp1; 1237 bp1 = bioq_first(&softc->trim_queue); 1238 if (bps >= TRIM_MAX_BIOS || 1239 bp1 == NULL || 1240 bp1->bio_bcount / softc->params.secsize > 1241 (softc->trim_max_ranges - ranges) * 0xffff) 1242 break; 1243 } while (1); 1244 cam_fill_ataio(ataio, 1245 ada_retry_count, 1246 adadone, 1247 CAM_DIR_OUT, 1248 0, 1249 req->data, 1250 ((ranges + 63) / 64) * 512, 1251 ada_default_timeout * 1000); 1252 ata_48bit_cmd(ataio, ATA_DATA_SET_MANAGEMENT, 1253 ATA_DSM_TRIM, 0, (ranges + 63) / 64); 1254 start_ccb->ccb_h.ccb_state = ADA_CCB_TRIM; 1255 goto out; 1256 } 1257 /* Run regular command. */ 1258 bp = bioq_first(&softc->bio_queue); 1259 if (bp == NULL) { 1260 xpt_release_ccb(start_ccb); 1261 break; 1262 } 1263 bioq_remove(&softc->bio_queue, bp); 1264 1265 if ((bp->bio_flags & BIO_ORDERED) != 0 1266 || (softc->flags & ADA_FLAG_NEED_OTAG) != 0) { 1267 softc->flags &= ~ADA_FLAG_NEED_OTAG; 1268 softc->ordered_tag_count++; 1269 tag_code = 0; 1270 } else { 1271 tag_code = 1; 1272 } 1273 switch (bp->bio_cmd) { 1274 case BIO_READ: 1275 case BIO_WRITE: 1276 { 1277 uint64_t lba = bp->bio_pblkno; 1278 uint16_t count = bp->bio_bcount / softc->params.secsize; 1279 #ifdef ADA_TEST_FAILURE 1280 int fail = 0; 1281 1282 /* 1283 * Support the failure ioctls. If the command is a 1284 * read, and there are pending forced read errors, or 1285 * if a write and pending write errors, then fail this 1286 * operation with EIO. This is useful for testing 1287 * purposes. Also, support having every Nth read fail. 1288 * 1289 * This is a rather blunt tool. 1290 */ 1291 if (bp->bio_cmd == BIO_READ) { 1292 if (softc->force_read_error) { 1293 softc->force_read_error--; 1294 fail = 1; 1295 } 1296 if (softc->periodic_read_error > 0) { 1297 if (++softc->periodic_read_count >= 1298 softc->periodic_read_error) { 1299 softc->periodic_read_count = 0; 1300 fail = 1; 1301 } 1302 } 1303 } else { 1304 if (softc->force_write_error) { 1305 softc->force_write_error--; 1306 fail = 1; 1307 } 1308 } 1309 if (fail) { 1310 bp->bio_error = EIO; 1311 bp->bio_flags |= BIO_ERROR; 1312 biodone(bp); 1313 xpt_release_ccb(start_ccb); 1314 adaschedule(periph); 1315 return; 1316 } 1317 #endif 1318 cam_fill_ataio(ataio, 1319 ada_retry_count, 1320 adadone, 1321 bp->bio_cmd == BIO_READ ? 1322 CAM_DIR_IN : CAM_DIR_OUT, 1323 tag_code, 1324 bp->bio_data, 1325 bp->bio_bcount, 1326 ada_default_timeout*1000); 1327 1328 if ((softc->flags & ADA_FLAG_CAN_NCQ) && tag_code) { 1329 if (bp->bio_cmd == BIO_READ) { 1330 ata_ncq_cmd(ataio, ATA_READ_FPDMA_QUEUED, 1331 lba, count); 1332 } else { 1333 ata_ncq_cmd(ataio, ATA_WRITE_FPDMA_QUEUED, 1334 lba, count); 1335 } 1336 } else if ((softc->flags & ADA_FLAG_CAN_48BIT) && 1337 (lba + count >= ATA_MAX_28BIT_LBA || 1338 count > 256)) { 1339 if (softc->flags & ADA_FLAG_CAN_DMA) { 1340 if (bp->bio_cmd == BIO_READ) { 1341 ata_48bit_cmd(ataio, ATA_READ_DMA48, 1342 0, lba, count); 1343 } else { 1344 ata_48bit_cmd(ataio, ATA_WRITE_DMA48, 1345 0, lba, count); 1346 } 1347 } else { 1348 if (bp->bio_cmd == BIO_READ) { 1349 ata_48bit_cmd(ataio, ATA_READ_MUL48, 1350 0, lba, count); 1351 } else { 1352 ata_48bit_cmd(ataio, ATA_WRITE_MUL48, 1353 0, lba, count); 1354 } 1355 } 1356 } else { 1357 if (count == 256) 1358 count = 0; 1359 if (softc->flags & ADA_FLAG_CAN_DMA) { 1360 if (bp->bio_cmd == BIO_READ) { 1361 ata_28bit_cmd(ataio, ATA_READ_DMA, 1362 0, lba, count); 1363 } else { 1364 ata_28bit_cmd(ataio, ATA_WRITE_DMA, 1365 0, lba, count); 1366 } 1367 } else { 1368 if (bp->bio_cmd == BIO_READ) { 1369 ata_28bit_cmd(ataio, ATA_READ_MUL, 1370 0, lba, count); 1371 } else { 1372 ata_28bit_cmd(ataio, ATA_WRITE_MUL, 1373 0, lba, count); 1374 } 1375 } 1376 } 1377 break; 1378 } 1379 case BIO_DELETE: 1380 { 1381 uint64_t lba = bp->bio_pblkno; 1382 uint16_t count = bp->bio_bcount / softc->params.secsize; 1383 1384 cam_fill_ataio(ataio, 1385 ada_retry_count, 1386 adadone, 1387 CAM_DIR_NONE, 1388 0, 1389 NULL, 1390 0, 1391 ada_default_timeout*1000); 1392 1393 if (count >= 256) 1394 count = 0; 1395 ata_28bit_cmd(ataio, ATA_CFA_ERASE, 0, lba, count); 1396 break; 1397 } 1398 case BIO_FLUSH: 1399 cam_fill_ataio(ataio, 1400 1, 1401 adadone, 1402 CAM_DIR_NONE, 1403 0, 1404 NULL, 1405 0, 1406 ada_default_timeout*1000); 1407 1408 if (softc->flags & ADA_FLAG_CAN_48BIT) 1409 ata_48bit_cmd(ataio, ATA_FLUSHCACHE48, 0, 0, 0); 1410 else 1411 ata_28bit_cmd(ataio, ATA_FLUSHCACHE, 0, 0, 0); 1412 break; 1413 } 1414 start_ccb->ccb_h.ccb_state = ADA_CCB_BUFFER_IO; 1415 out: 1416 start_ccb->ccb_h.ccb_bp = bp; 1417 softc->outstanding_cmds++; 1418 xpt_action(start_ccb); 1419 1420 /* May have more work to do, so ensure we stay scheduled */ 1421 adaschedule(periph); 1422 break; 1423 } 1424 case ADA_STATE_RAHEAD: 1425 case ADA_STATE_WCACHE: 1426 { 1427 if (softc->flags & ADA_FLAG_PACK_INVALID) { 1428 softc->state = ADA_STATE_NORMAL; 1429 xpt_release_ccb(start_ccb); 1430 cam_release_devq(periph->path, 1431 RELSIM_RELEASE_RUNLEVEL, 0, CAM_RL_DEV + 1, FALSE); 1432 adaschedule(periph); 1433 cam_periph_release_locked(periph); 1434 return; 1435 } 1436 1437 cam_fill_ataio(ataio, 1438 1, 1439 adadone, 1440 CAM_DIR_NONE, 1441 0, 1442 NULL, 1443 0, 1444 ada_default_timeout*1000); 1445 1446 if (softc->state == ADA_STATE_RAHEAD) { 1447 ata_28bit_cmd(ataio, ATA_SETFEATURES, ADA_RA ? 1448 ATA_SF_ENAB_RCACHE : ATA_SF_DIS_RCACHE, 0, 0); 1449 start_ccb->ccb_h.ccb_state = ADA_CCB_RAHEAD; 1450 } else { 1451 ata_28bit_cmd(ataio, ATA_SETFEATURES, ADA_WC ? 1452 ATA_SF_ENAB_WCACHE : ATA_SF_DIS_WCACHE, 0, 0); 1453 start_ccb->ccb_h.ccb_state = ADA_CCB_WCACHE; 1454 } 1455 xpt_action(start_ccb); 1456 break; 1457 } 1458 } 1459 } 1460 1461 static void 1462 adadone(struct cam_periph *periph, union ccb *done_ccb) 1463 { 1464 struct ada_softc *softc; 1465 struct ccb_ataio *ataio; 1466 struct ccb_getdev *cgd; 1467 1468 softc = (struct ada_softc *)periph->softc; 1469 ataio = &done_ccb->ataio; 1470 switch (ataio->ccb_h.ccb_state & ADA_CCB_TYPE_MASK) { 1471 case ADA_CCB_BUFFER_IO: 1472 case ADA_CCB_TRIM: 1473 { 1474 struct bio *bp; 1475 1476 bp = (struct bio *)done_ccb->ccb_h.ccb_bp; 1477 if ((done_ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) { 1478 int error; 1479 1480 error = adaerror(done_ccb, 0, 0); 1481 if (error == ERESTART) { 1482 /* A retry was scheduled, so just return. */ 1483 return; 1484 } 1485 if (error != 0) { 1486 if (error == ENXIO && 1487 (softc->flags & ADA_FLAG_PACK_INVALID) == 0) { 1488 /* 1489 * Catastrophic error. Mark our pack as 1490 * invalid. 1491 */ 1492 /* 1493 * XXX See if this is really a media 1494 * XXX change first? 1495 */ 1496 xpt_print(periph->path, 1497 "Invalidating pack\n"); 1498 softc->flags |= ADA_FLAG_PACK_INVALID; 1499 } 1500 bp->bio_error = error; 1501 bp->bio_resid = bp->bio_bcount; 1502 bp->bio_flags |= BIO_ERROR; 1503 } else { 1504 bp->bio_resid = ataio->resid; 1505 bp->bio_error = 0; 1506 if (bp->bio_resid != 0) 1507 bp->bio_flags |= BIO_ERROR; 1508 } 1509 if ((done_ccb->ccb_h.status & CAM_DEV_QFRZN) != 0) 1510 cam_release_devq(done_ccb->ccb_h.path, 1511 /*relsim_flags*/0, 1512 /*reduction*/0, 1513 /*timeout*/0, 1514 /*getcount_only*/0); 1515 } else { 1516 if ((done_ccb->ccb_h.status & CAM_DEV_QFRZN) != 0) 1517 panic("REQ_CMP with QFRZN"); 1518 bp->bio_resid = ataio->resid; 1519 if (ataio->resid > 0) 1520 bp->bio_flags |= BIO_ERROR; 1521 } 1522 softc->outstanding_cmds--; 1523 if (softc->outstanding_cmds == 0) 1524 softc->flags |= ADA_FLAG_WENT_IDLE; 1525 if ((ataio->ccb_h.ccb_state & ADA_CCB_TYPE_MASK) == 1526 ADA_CCB_TRIM) { 1527 struct trim_request *req = 1528 (struct trim_request *)ataio->data_ptr; 1529 int i; 1530 1531 for (i = 1; i < TRIM_MAX_BIOS && req->bps[i]; i++) { 1532 struct bio *bp1 = req->bps[i]; 1533 1534 bp1->bio_resid = bp->bio_resid; 1535 bp1->bio_error = bp->bio_error; 1536 if (bp->bio_flags & BIO_ERROR) 1537 bp1->bio_flags |= BIO_ERROR; 1538 biodone(bp1); 1539 } 1540 softc->trim_running = 0; 1541 biodone(bp); 1542 adaschedule(periph); 1543 } else 1544 biodone(bp); 1545 break; 1546 } 1547 case ADA_CCB_RAHEAD: 1548 { 1549 if ((done_ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) { 1550 if (adaerror(done_ccb, 0, 0) == ERESTART) { 1551 return; 1552 } else if ((done_ccb->ccb_h.status & CAM_DEV_QFRZN) != 0) { 1553 cam_release_devq(done_ccb->ccb_h.path, 1554 /*relsim_flags*/0, 1555 /*reduction*/0, 1556 /*timeout*/0, 1557 /*getcount_only*/0); 1558 } 1559 } 1560 1561 /* 1562 * Since our peripheral may be invalidated by an error 1563 * above or an external event, we must release our CCB 1564 * before releasing the reference on the peripheral. 1565 * The peripheral will only go away once the last reference 1566 * is removed, and we need it around for the CCB release 1567 * operation. 1568 */ 1569 cgd = (struct ccb_getdev *)done_ccb; 1570 xpt_setup_ccb(&cgd->ccb_h, periph->path, CAM_PRIORITY_NORMAL); 1571 cgd->ccb_h.func_code = XPT_GDEV_TYPE; 1572 xpt_action((union ccb *)cgd); 1573 if (ADA_WC >= 0 && 1574 cgd->ident_data.support.command1 & ATA_SUPPORT_WRITECACHE) { 1575 softc->state = ADA_STATE_WCACHE; 1576 xpt_release_ccb(done_ccb); 1577 xpt_schedule(periph, CAM_PRIORITY_DEV); 1578 return; 1579 } 1580 softc->state = ADA_STATE_NORMAL; 1581 xpt_release_ccb(done_ccb); 1582 cam_release_devq(periph->path, 1583 RELSIM_RELEASE_RUNLEVEL, 0, CAM_RL_DEV + 1, FALSE); 1584 adaschedule(periph); 1585 cam_periph_release_locked(periph); 1586 return; 1587 } 1588 case ADA_CCB_WCACHE: 1589 { 1590 if ((done_ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) { 1591 if (adaerror(done_ccb, 0, 0) == ERESTART) { 1592 return; 1593 } else if ((done_ccb->ccb_h.status & CAM_DEV_QFRZN) != 0) { 1594 cam_release_devq(done_ccb->ccb_h.path, 1595 /*relsim_flags*/0, 1596 /*reduction*/0, 1597 /*timeout*/0, 1598 /*getcount_only*/0); 1599 } 1600 } 1601 1602 softc->state = ADA_STATE_NORMAL; 1603 /* 1604 * Since our peripheral may be invalidated by an error 1605 * above or an external event, we must release our CCB 1606 * before releasing the reference on the peripheral. 1607 * The peripheral will only go away once the last reference 1608 * is removed, and we need it around for the CCB release 1609 * operation. 1610 */ 1611 xpt_release_ccb(done_ccb); 1612 cam_release_devq(periph->path, 1613 RELSIM_RELEASE_RUNLEVEL, 0, CAM_RL_DEV + 1, FALSE); 1614 adaschedule(periph); 1615 cam_periph_release_locked(periph); 1616 return; 1617 } 1618 case ADA_CCB_WAITING: 1619 { 1620 /* Caller will release the CCB */ 1621 wakeup(&done_ccb->ccb_h.cbfcnp); 1622 return; 1623 } 1624 case ADA_CCB_DUMP: 1625 /* No-op. We're polling */ 1626 return; 1627 default: 1628 break; 1629 } 1630 xpt_release_ccb(done_ccb); 1631 } 1632 1633 static int 1634 adaerror(union ccb *ccb, u_int32_t cam_flags, u_int32_t sense_flags) 1635 { 1636 1637 return(cam_periph_error(ccb, cam_flags, sense_flags, NULL)); 1638 } 1639 1640 static void 1641 adagetparams(struct cam_periph *periph, struct ccb_getdev *cgd) 1642 { 1643 struct ada_softc *softc = (struct ada_softc *)periph->softc; 1644 struct disk_params *dp = &softc->params; 1645 u_int64_t lbasize48; 1646 u_int32_t lbasize; 1647 1648 dp->secsize = ata_logical_sector_size(&cgd->ident_data); 1649 if ((cgd->ident_data.atavalid & ATA_FLAG_54_58) && 1650 cgd->ident_data.current_heads && cgd->ident_data.current_sectors) { 1651 dp->heads = cgd->ident_data.current_heads; 1652 dp->secs_per_track = cgd->ident_data.current_sectors; 1653 dp->cylinders = cgd->ident_data.cylinders; 1654 dp->sectors = (u_int32_t)cgd->ident_data.current_size_1 | 1655 ((u_int32_t)cgd->ident_data.current_size_2 << 16); 1656 } else { 1657 dp->heads = cgd->ident_data.heads; 1658 dp->secs_per_track = cgd->ident_data.sectors; 1659 dp->cylinders = cgd->ident_data.cylinders; 1660 dp->sectors = cgd->ident_data.cylinders * dp->heads * dp->secs_per_track; 1661 } 1662 lbasize = (u_int32_t)cgd->ident_data.lba_size_1 | 1663 ((u_int32_t)cgd->ident_data.lba_size_2 << 16); 1664 1665 /* use the 28bit LBA size if valid or bigger than the CHS mapping */ 1666 if (cgd->ident_data.cylinders == 16383 || dp->sectors < lbasize) 1667 dp->sectors = lbasize; 1668 1669 /* use the 48bit LBA size if valid */ 1670 lbasize48 = ((u_int64_t)cgd->ident_data.lba_size48_1) | 1671 ((u_int64_t)cgd->ident_data.lba_size48_2 << 16) | 1672 ((u_int64_t)cgd->ident_data.lba_size48_3 << 32) | 1673 ((u_int64_t)cgd->ident_data.lba_size48_4 << 48); 1674 if ((cgd->ident_data.support.command2 & ATA_SUPPORT_ADDRESS48) && 1675 lbasize48 > ATA_MAX_28BIT_LBA) 1676 dp->sectors = lbasize48; 1677 } 1678 1679 static void 1680 adasendorderedtag(void *arg) 1681 { 1682 struct ada_softc *softc = arg; 1683 1684 if (ada_send_ordered) { 1685 if ((softc->ordered_tag_count == 0) 1686 && ((softc->flags & ADA_FLAG_WENT_IDLE) == 0)) { 1687 softc->flags |= ADA_FLAG_NEED_OTAG; 1688 } 1689 if (softc->outstanding_cmds > 0) 1690 softc->flags &= ~ADA_FLAG_WENT_IDLE; 1691 1692 softc->ordered_tag_count = 0; 1693 } 1694 /* Queue us up again */ 1695 callout_reset(&softc->sendordered_c, 1696 (ada_default_timeout * hz) / ADA_ORDEREDTAG_INTERVAL, 1697 adasendorderedtag, softc); 1698 } 1699 1700 /* 1701 * Step through all ADA peripheral drivers, and if the device is still open, 1702 * sync the disk cache to physical media. 1703 */ 1704 static void 1705 adaflush(void) 1706 { 1707 struct cam_periph *periph; 1708 struct ada_softc *softc; 1709 1710 TAILQ_FOREACH(periph, &adadriver.units, unit_links) { 1711 union ccb ccb; 1712 1713 /* If we paniced with lock held - not recurse here. */ 1714 if (cam_periph_owned(periph)) 1715 continue; 1716 cam_periph_lock(periph); 1717 softc = (struct ada_softc *)periph->softc; 1718 /* 1719 * We only sync the cache if the drive is still open, and 1720 * if the drive is capable of it.. 1721 */ 1722 if (((softc->flags & ADA_FLAG_OPEN) == 0) || 1723 (softc->flags & ADA_FLAG_CAN_FLUSHCACHE) == 0) { 1724 cam_periph_unlock(periph); 1725 continue; 1726 } 1727 1728 xpt_setup_ccb(&ccb.ccb_h, periph->path, CAM_PRIORITY_NORMAL); 1729 1730 ccb.ccb_h.ccb_state = ADA_CCB_DUMP; 1731 cam_fill_ataio(&ccb.ataio, 1732 1, 1733 adadone, 1734 CAM_DIR_NONE, 1735 0, 1736 NULL, 1737 0, 1738 ada_default_timeout*1000); 1739 1740 if (softc->flags & ADA_FLAG_CAN_48BIT) 1741 ata_48bit_cmd(&ccb.ataio, ATA_FLUSHCACHE48, 0, 0, 0); 1742 else 1743 ata_28bit_cmd(&ccb.ataio, ATA_FLUSHCACHE, 0, 0, 0); 1744 xpt_polled_action(&ccb); 1745 1746 if ((ccb.ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) 1747 xpt_print(periph->path, "Synchronize cache failed\n"); 1748 1749 if ((ccb.ccb_h.status & CAM_DEV_QFRZN) != 0) 1750 cam_release_devq(ccb.ccb_h.path, 1751 /*relsim_flags*/0, 1752 /*reduction*/0, 1753 /*timeout*/0, 1754 /*getcount_only*/0); 1755 cam_periph_unlock(periph); 1756 } 1757 } 1758 1759 static void 1760 adaspindown(uint8_t cmd, int flags) 1761 { 1762 struct cam_periph *periph; 1763 struct ada_softc *softc; 1764 1765 TAILQ_FOREACH(periph, &adadriver.units, unit_links) { 1766 union ccb ccb; 1767 1768 /* If we paniced with lock held - not recurse here. */ 1769 if (cam_periph_owned(periph)) 1770 continue; 1771 cam_periph_lock(periph); 1772 softc = (struct ada_softc *)periph->softc; 1773 /* 1774 * We only spin-down the drive if it is capable of it.. 1775 */ 1776 if ((softc->flags & ADA_FLAG_CAN_POWERMGT) == 0) { 1777 cam_periph_unlock(periph); 1778 continue; 1779 } 1780 1781 if (bootverbose) 1782 xpt_print(periph->path, "spin-down\n"); 1783 1784 xpt_setup_ccb(&ccb.ccb_h, periph->path, CAM_PRIORITY_NORMAL); 1785 1786 ccb.ccb_h.ccb_state = ADA_CCB_DUMP; 1787 cam_fill_ataio(&ccb.ataio, 1788 1, 1789 adadone, 1790 CAM_DIR_NONE | flags, 1791 0, 1792 NULL, 1793 0, 1794 ada_default_timeout*1000); 1795 1796 ata_28bit_cmd(&ccb.ataio, cmd, 0, 0, 0); 1797 xpt_polled_action(&ccb); 1798 1799 if ((ccb.ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) 1800 xpt_print(periph->path, "Spin-down disk failed\n"); 1801 1802 if ((ccb.ccb_h.status & CAM_DEV_QFRZN) != 0) 1803 cam_release_devq(ccb.ccb_h.path, 1804 /*relsim_flags*/0, 1805 /*reduction*/0, 1806 /*timeout*/0, 1807 /*getcount_only*/0); 1808 cam_periph_unlock(periph); 1809 } 1810 } 1811 1812 static void 1813 adashutdown(void *arg, int howto) 1814 { 1815 1816 adaflush(); 1817 if (ada_spindown_shutdown != 0 && 1818 (howto & (RB_HALT | RB_POWEROFF)) != 0) 1819 adaspindown(ATA_STANDBY_IMMEDIATE, 0); 1820 } 1821 1822 static void 1823 adasuspend(void *arg) 1824 { 1825 1826 adaflush(); 1827 if (ada_spindown_suspend != 0) 1828 adaspindown(ATA_SLEEP, CAM_DEV_QFREEZE); 1829 } 1830 1831 static void 1832 adaresume(void *arg) 1833 { 1834 struct cam_periph *periph; 1835 struct ada_softc *softc; 1836 1837 if (ada_spindown_suspend == 0) 1838 return; 1839 1840 TAILQ_FOREACH(periph, &adadriver.units, unit_links) { 1841 cam_periph_lock(periph); 1842 softc = (struct ada_softc *)periph->softc; 1843 /* 1844 * We only spin-down the drive if it is capable of it.. 1845 */ 1846 if ((softc->flags & ADA_FLAG_CAN_POWERMGT) == 0) { 1847 cam_periph_unlock(periph); 1848 continue; 1849 } 1850 1851 if (bootverbose) 1852 xpt_print(periph->path, "resume\n"); 1853 1854 /* 1855 * Drop freeze taken due to CAM_DEV_QFREEZE flag set on 1856 * sleep request. 1857 */ 1858 cam_release_devq(periph->path, 1859 /*relsim_flags*/0, 1860 /*openings*/0, 1861 /*timeout*/0, 1862 /*getcount_only*/0); 1863 1864 cam_periph_unlock(periph); 1865 } 1866 } 1867 1868 #endif /* _KERNEL */ 1869