ata_da.c revision 237305
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: stable/9/sys/cam/ata/ata_da.c 237305 2012-06-20 13:59:25Z mav $"); 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 71typedef enum { 72 ADA_STATE_RAHEAD, 73 ADA_STATE_WCACHE, 74 ADA_STATE_NORMAL 75} ada_state; 76 77typedef 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 92typedef enum { 93 ADA_Q_NONE = 0x00, 94 ADA_Q_4K = 0x01, 95} ada_quirks; 96 97typedef 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 111struct 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) 122struct trim_request { 123 uint8_t data[TRIM_MAX_RANGES * 8]; 124 struct bio *bps[TRIM_MAX_BIOS]; 125}; 126 127struct 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 154struct ada_quirk_entry { 155 struct scsi_inquiry_pattern inq_pat; 156 ada_quirks quirks; 157}; 158 159static 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 281static disk_strategy_t adastrategy; 282static dumper_t adadump; 283static periph_init_t adainit; 284static void adaasync(void *callback_arg, u_int32_t code, 285 struct cam_path *path, void *arg); 286static void adasysctlinit(void *context, int pending); 287static periph_ctor_t adaregister; 288static periph_dtor_t adacleanup; 289static periph_start_t adastart; 290static periph_oninv_t adaoninvalidate; 291static void adadone(struct cam_periph *periph, 292 union ccb *done_ccb); 293static int adaerror(union ccb *ccb, u_int32_t cam_flags, 294 u_int32_t sense_flags); 295static void adagetparams(struct cam_periph *periph, 296 struct ccb_getdev *cgd); 297static timeout_t adasendorderedtag; 298static void adashutdown(void *arg, int howto); 299static void adasuspend(void *arg); 300static 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 351static int ada_legacy_aliases = ADA_DEFAULT_LEGACY_ALIASES; 352static int ada_retry_count = ADA_DEFAULT_RETRY; 353static int ada_default_timeout = ADA_DEFAULT_TIMEOUT; 354static int ada_send_ordered = ADA_DEFAULT_SEND_ORDERED; 355static int ada_spindown_shutdown = ADA_DEFAULT_SPINDOWN_SHUTDOWN; 356static int ada_spindown_suspend = ADA_DEFAULT_SPINDOWN_SUSPEND; 357static int ada_read_ahead = ADA_DEFAULT_READ_AHEAD; 358static int ada_write_cache = ADA_DEFAULT_WRITE_CACHE; 359 360SYSCTL_NODE(_kern_cam, OID_AUTO, ada, CTLFLAG_RD, 0, 361 "CAM Direct Access Disk driver"); 362SYSCTL_INT(_kern_cam_ada, OID_AUTO, legacy_aliases, CTLFLAG_RW, 363 &ada_legacy_aliases, 0, "Create legacy-like device aliases"); 364TUNABLE_INT("kern.cam.ada.legacy_aliases", &ada_legacy_aliases); 365SYSCTL_INT(_kern_cam_ada, OID_AUTO, retry_count, CTLFLAG_RW, 366 &ada_retry_count, 0, "Normal I/O retry count"); 367TUNABLE_INT("kern.cam.ada.retry_count", &ada_retry_count); 368SYSCTL_INT(_kern_cam_ada, OID_AUTO, default_timeout, CTLFLAG_RW, 369 &ada_default_timeout, 0, "Normal I/O timeout (in seconds)"); 370TUNABLE_INT("kern.cam.ada.default_timeout", &ada_default_timeout); 371SYSCTL_INT(_kern_cam_ada, OID_AUTO, ada_send_ordered, CTLFLAG_RW, 372 &ada_send_ordered, 0, "Send Ordered Tags"); 373TUNABLE_INT("kern.cam.ada.ada_send_ordered", &ada_send_ordered); 374SYSCTL_INT(_kern_cam_ada, OID_AUTO, spindown_shutdown, CTLFLAG_RW, 375 &ada_spindown_shutdown, 0, "Spin down upon shutdown"); 376TUNABLE_INT("kern.cam.ada.spindown_shutdown", &ada_spindown_shutdown); 377SYSCTL_INT(_kern_cam_ada, OID_AUTO, spindown_suspend, CTLFLAG_RW, 378 &ada_spindown_suspend, 0, "Spin down upon suspend"); 379TUNABLE_INT("kern.cam.ada.spindown_suspend", &ada_spindown_suspend); 380SYSCTL_INT(_kern_cam_ada, OID_AUTO, read_ahead, CTLFLAG_RW, 381 &ada_read_ahead, 0, "Enable disk read-ahead"); 382TUNABLE_INT("kern.cam.ada.read_ahead", &ada_read_ahead); 383SYSCTL_INT(_kern_cam_ada, OID_AUTO, write_cache, CTLFLAG_RW, 384 &ada_write_cache, 0, "Enable disk write cache"); 385TUNABLE_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 403static struct periph_driver adadriver = 404{ 405 adainit, "ada", 406 TAILQ_HEAD_INITIALIZER(adadriver.units), /* generation */ 0 407}; 408 409PERIPHDRIVER_DECLARE(ada, adadriver); 410 411MALLOC_DEFINE(M_ATADA, "ata_da", "ata_da buffers"); 412 413static int 414adaopen(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 | CAM_DEBUG_PERIPH, 440 ("adaopen\n")); 441 442 if ((softc->flags & ADA_FLAG_PACK_INVALID) != 0) { 443 /* Invalidate our pack information. */ 444 softc->flags &= ~ADA_FLAG_PACK_INVALID; 445 } 446 447 cam_periph_unhold(periph); 448 cam_periph_unlock(periph); 449 return (0); 450} 451 452static int 453adaclose(struct disk *dp) 454{ 455 struct cam_periph *periph; 456 struct ada_softc *softc; 457 union ccb *ccb; 458 459 periph = (struct cam_periph *)dp->d_drv1; 460 if (periph == NULL) 461 return (ENXIO); 462 463 cam_periph_lock(periph); 464 if (cam_periph_hold(periph, PRIBIO) != 0) { 465 cam_periph_unlock(periph); 466 cam_periph_release(periph); 467 return (0); 468 } 469 470 softc = (struct ada_softc *)periph->softc; 471 472 CAM_DEBUG(periph->path, CAM_DEBUG_TRACE | CAM_DEBUG_PERIPH, 473 ("adaclose\n")); 474 475 /* We only sync the cache if the drive is capable of it. */ 476 if ((softc->flags & ADA_FLAG_CAN_FLUSHCACHE) != 0 && 477 (softc->flags & ADA_FLAG_PACK_INVALID) == 0) { 478 479 ccb = cam_periph_getccb(periph, CAM_PRIORITY_NORMAL); 480 cam_fill_ataio(&ccb->ataio, 481 1, 482 adadone, 483 CAM_DIR_NONE, 484 0, 485 NULL, 486 0, 487 ada_default_timeout*1000); 488 489 if (softc->flags & ADA_FLAG_CAN_48BIT) 490 ata_48bit_cmd(&ccb->ataio, ATA_FLUSHCACHE48, 0, 0, 0); 491 else 492 ata_28bit_cmd(&ccb->ataio, ATA_FLUSHCACHE, 0, 0, 0); 493 cam_periph_runccb(ccb, /*error_routine*/NULL, /*cam_flags*/0, 494 /*sense_flags*/0, softc->disk->d_devstat); 495 496 if ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) 497 xpt_print(periph->path, "Synchronize cache failed\n"); 498 xpt_release_ccb(ccb); 499 } 500 501 softc->flags &= ~ADA_FLAG_OPEN; 502 cam_periph_unhold(periph); 503 cam_periph_unlock(periph); 504 cam_periph_release(periph); 505 return (0); 506} 507 508static void 509adaschedule(struct cam_periph *periph) 510{ 511 struct ada_softc *softc = (struct ada_softc *)periph->softc; 512 uint32_t prio; 513 514 /* Check if cam_periph_getccb() was called. */ 515 prio = periph->immediate_priority; 516 517 /* Check if we have more work to do. */ 518 if (bioq_first(&softc->bio_queue) || 519 (!softc->trim_running && bioq_first(&softc->trim_queue))) { 520 prio = CAM_PRIORITY_NORMAL; 521 } 522 523 /* Schedule CCB if any of above is true. */ 524 if (prio != CAM_PRIORITY_NONE) 525 xpt_schedule(periph, prio); 526} 527 528/* 529 * Actually translate the requested transfer into one the physical driver 530 * can understand. The transfer is described by a buf and will include 531 * only one physical transfer. 532 */ 533static void 534adastrategy(struct bio *bp) 535{ 536 struct cam_periph *periph; 537 struct ada_softc *softc; 538 539 periph = (struct cam_periph *)bp->bio_disk->d_drv1; 540 if (periph == NULL) { 541 biofinish(bp, NULL, ENXIO); 542 return; 543 } 544 softc = (struct ada_softc *)periph->softc; 545 546 cam_periph_lock(periph); 547 548 CAM_DEBUG(periph->path, CAM_DEBUG_TRACE, ("adastrategy(%p)\n", bp)); 549 550 /* 551 * If the device has been made invalid, error out 552 */ 553 if ((softc->flags & ADA_FLAG_PACK_INVALID)) { 554 cam_periph_unlock(periph); 555 biofinish(bp, NULL, ENXIO); 556 return; 557 } 558 559 /* 560 * Place it in the queue of disk activities for this disk 561 */ 562 if (bp->bio_cmd == BIO_DELETE && 563 (softc->flags & ADA_FLAG_CAN_TRIM)) 564 bioq_disksort(&softc->trim_queue, bp); 565 else 566 bioq_disksort(&softc->bio_queue, bp); 567 568 /* 569 * Schedule ourselves for performing the work. 570 */ 571 adaschedule(periph); 572 cam_periph_unlock(periph); 573 574 return; 575} 576 577static int 578adadump(void *arg, void *virtual, vm_offset_t physical, off_t offset, size_t length) 579{ 580 struct cam_periph *periph; 581 struct ada_softc *softc; 582 u_int secsize; 583 union ccb ccb; 584 struct disk *dp; 585 uint64_t lba; 586 uint16_t count; 587 588 dp = arg; 589 periph = dp->d_drv1; 590 if (periph == NULL) 591 return (ENXIO); 592 softc = (struct ada_softc *)periph->softc; 593 cam_periph_lock(periph); 594 secsize = softc->params.secsize; 595 lba = offset / secsize; 596 count = length / secsize; 597 598 if ((softc->flags & ADA_FLAG_PACK_INVALID) != 0) { 599 cam_periph_unlock(periph); 600 return (ENXIO); 601 } 602 603 if (length > 0) { 604 xpt_setup_ccb(&ccb.ccb_h, periph->path, CAM_PRIORITY_NORMAL); 605 ccb.ccb_h.ccb_state = ADA_CCB_DUMP; 606 cam_fill_ataio(&ccb.ataio, 607 0, 608 adadone, 609 CAM_DIR_OUT, 610 0, 611 (u_int8_t *) virtual, 612 length, 613 ada_default_timeout*1000); 614 if ((softc->flags & ADA_FLAG_CAN_48BIT) && 615 (lba + count >= ATA_MAX_28BIT_LBA || 616 count >= 256)) { 617 ata_48bit_cmd(&ccb.ataio, ATA_WRITE_DMA48, 618 0, lba, count); 619 } else { 620 ata_28bit_cmd(&ccb.ataio, ATA_WRITE_DMA, 621 0, lba, count); 622 } 623 xpt_polled_action(&ccb); 624 625 if ((ccb.ataio.ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) { 626 printf("Aborting dump due to I/O error.\n"); 627 cam_periph_unlock(periph); 628 return(EIO); 629 } 630 cam_periph_unlock(periph); 631 return(0); 632 } 633 634 if (softc->flags & ADA_FLAG_CAN_FLUSHCACHE) { 635 xpt_setup_ccb(&ccb.ccb_h, periph->path, CAM_PRIORITY_NORMAL); 636 637 ccb.ccb_h.ccb_state = ADA_CCB_DUMP; 638 cam_fill_ataio(&ccb.ataio, 639 1, 640 adadone, 641 CAM_DIR_NONE, 642 0, 643 NULL, 644 0, 645 ada_default_timeout*1000); 646 647 if (softc->flags & ADA_FLAG_CAN_48BIT) 648 ata_48bit_cmd(&ccb.ataio, ATA_FLUSHCACHE48, 0, 0, 0); 649 else 650 ata_28bit_cmd(&ccb.ataio, ATA_FLUSHCACHE, 0, 0, 0); 651 xpt_polled_action(&ccb); 652 653 if ((ccb.ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) 654 xpt_print(periph->path, "Synchronize cache failed\n"); 655 656 if ((ccb.ccb_h.status & CAM_DEV_QFRZN) != 0) 657 cam_release_devq(ccb.ccb_h.path, 658 /*relsim_flags*/0, 659 /*reduction*/0, 660 /*timeout*/0, 661 /*getcount_only*/0); 662 } 663 cam_periph_unlock(periph); 664 return (0); 665} 666 667static void 668adainit(void) 669{ 670 cam_status status; 671 672 /* 673 * Install a global async callback. This callback will 674 * receive async callbacks like "new device found". 675 */ 676 status = xpt_register_async(AC_FOUND_DEVICE, adaasync, NULL, NULL); 677 678 if (status != CAM_REQ_CMP) { 679 printf("ada: Failed to attach master async callback " 680 "due to status 0x%x!\n", status); 681 } else if (ada_send_ordered) { 682 683 /* Register our event handlers */ 684 if ((EVENTHANDLER_REGISTER(power_suspend, adasuspend, 685 NULL, EVENTHANDLER_PRI_LAST)) == NULL) 686 printf("adainit: power event registration failed!\n"); 687 if ((EVENTHANDLER_REGISTER(power_resume, adaresume, 688 NULL, EVENTHANDLER_PRI_LAST)) == NULL) 689 printf("adainit: power event registration failed!\n"); 690 if ((EVENTHANDLER_REGISTER(shutdown_post_sync, adashutdown, 691 NULL, SHUTDOWN_PRI_DEFAULT)) == NULL) 692 printf("adainit: shutdown event registration failed!\n"); 693 } 694} 695 696static void 697adaoninvalidate(struct cam_periph *periph) 698{ 699 struct ada_softc *softc; 700 701 softc = (struct ada_softc *)periph->softc; 702 703 /* 704 * De-register any async callbacks. 705 */ 706 xpt_register_async(0, adaasync, periph, periph->path); 707 708 softc->flags |= ADA_FLAG_PACK_INVALID; 709 710 /* 711 * Return all queued I/O with ENXIO. 712 * XXX Handle any transactions queued to the card 713 * with XPT_ABORT_CCB. 714 */ 715 bioq_flush(&softc->bio_queue, NULL, ENXIO); 716 bioq_flush(&softc->trim_queue, NULL, ENXIO); 717 718 disk_gone(softc->disk); 719 xpt_print(periph->path, "lost device\n"); 720} 721 722static void 723adacleanup(struct cam_periph *periph) 724{ 725 struct ada_softc *softc; 726 727 softc = (struct ada_softc *)periph->softc; 728 729 xpt_print(periph->path, "removing device entry\n"); 730 cam_periph_unlock(periph); 731 732 /* 733 * If we can't free the sysctl tree, oh well... 734 */ 735 if ((softc->flags & ADA_FLAG_SCTX_INIT) != 0 736 && sysctl_ctx_free(&softc->sysctl_ctx) != 0) { 737 xpt_print(periph->path, "can't remove sysctl context\n"); 738 } 739 740 disk_destroy(softc->disk); 741 callout_drain(&softc->sendordered_c); 742 free(softc, M_DEVBUF); 743 cam_periph_lock(periph); 744} 745 746static void 747adaasync(void *callback_arg, u_int32_t code, 748 struct cam_path *path, void *arg) 749{ 750 struct ccb_getdev cgd; 751 struct cam_periph *periph; 752 struct ada_softc *softc; 753 754 periph = (struct cam_periph *)callback_arg; 755 switch (code) { 756 case AC_FOUND_DEVICE: 757 { 758 struct ccb_getdev *cgd; 759 cam_status status; 760 761 cgd = (struct ccb_getdev *)arg; 762 if (cgd == NULL) 763 break; 764 765 if (cgd->protocol != PROTO_ATA) 766 break; 767 768 /* 769 * Allocate a peripheral instance for 770 * this device and start the probe 771 * process. 772 */ 773 status = cam_periph_alloc(adaregister, adaoninvalidate, 774 adacleanup, adastart, 775 "ada", CAM_PERIPH_BIO, 776 cgd->ccb_h.path, adaasync, 777 AC_FOUND_DEVICE, cgd); 778 779 if (status != CAM_REQ_CMP 780 && status != CAM_REQ_INPROG) 781 printf("adaasync: Unable to attach to new device " 782 "due to status 0x%x\n", status); 783 break; 784 } 785 case AC_GETDEV_CHANGED: 786 { 787 softc = (struct ada_softc *)periph->softc; 788 xpt_setup_ccb(&cgd.ccb_h, periph->path, CAM_PRIORITY_NORMAL); 789 cgd.ccb_h.func_code = XPT_GDEV_TYPE; 790 xpt_action((union ccb *)&cgd); 791 792 if ((cgd.ident_data.capabilities1 & ATA_SUPPORT_DMA) && 793 (cgd.inq_flags & SID_DMA)) 794 softc->flags |= ADA_FLAG_CAN_DMA; 795 else 796 softc->flags &= ~ADA_FLAG_CAN_DMA; 797 if ((cgd.ident_data.satacapabilities & ATA_SUPPORT_NCQ) && 798 (cgd.inq_flags & SID_DMA) && (cgd.inq_flags & SID_CmdQue)) 799 softc->flags |= ADA_FLAG_CAN_NCQ; 800 else 801 softc->flags &= ~ADA_FLAG_CAN_NCQ; 802 if ((cgd.ident_data.support_dsm & ATA_SUPPORT_DSM_TRIM) && 803 (cgd.inq_flags & SID_DMA)) 804 softc->flags |= ADA_FLAG_CAN_TRIM; 805 else 806 softc->flags &= ~ADA_FLAG_CAN_TRIM; 807 808 cam_periph_async(periph, code, path, arg); 809 break; 810 } 811 case AC_ADVINFO_CHANGED: 812 { 813 uintptr_t buftype; 814 815 buftype = (uintptr_t)arg; 816 if (buftype == CDAI_TYPE_PHYS_PATH) { 817 struct ada_softc *softc; 818 819 softc = periph->softc; 820 disk_attr_changed(softc->disk, "GEOM::physpath", 821 M_NOWAIT); 822 } 823 break; 824 } 825 case AC_SENT_BDR: 826 case AC_BUS_RESET: 827 { 828 softc = (struct ada_softc *)periph->softc; 829 cam_periph_async(periph, code, path, arg); 830 if (softc->state != ADA_STATE_NORMAL) 831 break; 832 xpt_setup_ccb(&cgd.ccb_h, periph->path, CAM_PRIORITY_NORMAL); 833 cgd.ccb_h.func_code = XPT_GDEV_TYPE; 834 xpt_action((union ccb *)&cgd); 835 if (ADA_RA >= 0 && 836 cgd.ident_data.support.command1 & ATA_SUPPORT_LOOKAHEAD) 837 softc->state = ADA_STATE_RAHEAD; 838 else if (ADA_WC >= 0 && 839 cgd.ident_data.support.command1 & ATA_SUPPORT_WRITECACHE) 840 softc->state = ADA_STATE_WCACHE; 841 else 842 break; 843 cam_periph_acquire(periph); 844 cam_freeze_devq_arg(periph->path, 845 RELSIM_RELEASE_RUNLEVEL, CAM_RL_DEV + 1); 846 xpt_schedule(periph, CAM_PRIORITY_DEV); 847 } 848 default: 849 cam_periph_async(periph, code, path, arg); 850 break; 851 } 852} 853 854static void 855adasysctlinit(void *context, int pending) 856{ 857 struct cam_periph *periph; 858 struct ada_softc *softc; 859 char tmpstr[80], tmpstr2[80]; 860 861 periph = (struct cam_periph *)context; 862 863 /* periph was held for us when this task was enqueued */ 864 if (periph->flags & CAM_PERIPH_INVALID) { 865 cam_periph_release(periph); 866 return; 867 } 868 869 softc = (struct ada_softc *)periph->softc; 870 snprintf(tmpstr, sizeof(tmpstr), "CAM ADA unit %d", periph->unit_number); 871 snprintf(tmpstr2, sizeof(tmpstr2), "%d", periph->unit_number); 872 873 sysctl_ctx_init(&softc->sysctl_ctx); 874 softc->flags |= ADA_FLAG_SCTX_INIT; 875 softc->sysctl_tree = SYSCTL_ADD_NODE(&softc->sysctl_ctx, 876 SYSCTL_STATIC_CHILDREN(_kern_cam_ada), OID_AUTO, tmpstr2, 877 CTLFLAG_RD, 0, tmpstr); 878 if (softc->sysctl_tree == NULL) { 879 printf("adasysctlinit: unable to allocate sysctl tree\n"); 880 cam_periph_release(periph); 881 return; 882 } 883 884 SYSCTL_ADD_INT(&softc->sysctl_ctx, SYSCTL_CHILDREN(softc->sysctl_tree), 885 OID_AUTO, "read_ahead", CTLFLAG_RW | CTLFLAG_MPSAFE, 886 &softc->read_ahead, 0, "Enable disk read ahead."); 887 SYSCTL_ADD_INT(&softc->sysctl_ctx, SYSCTL_CHILDREN(softc->sysctl_tree), 888 OID_AUTO, "write_cache", CTLFLAG_RW | CTLFLAG_MPSAFE, 889 &softc->write_cache, 0, "Enable disk write cache."); 890#ifdef ADA_TEST_FAILURE 891 /* 892 * Add a 'door bell' sysctl which allows one to set it from userland 893 * and cause something bad to happen. For the moment, we only allow 894 * whacking the next read or write. 895 */ 896 SYSCTL_ADD_INT(&softc->sysctl_ctx, SYSCTL_CHILDREN(softc->sysctl_tree), 897 OID_AUTO, "force_read_error", CTLFLAG_RW | CTLFLAG_MPSAFE, 898 &softc->force_read_error, 0, 899 "Force a read error for the next N reads."); 900 SYSCTL_ADD_INT(&softc->sysctl_ctx, SYSCTL_CHILDREN(softc->sysctl_tree), 901 OID_AUTO, "force_write_error", CTLFLAG_RW | CTLFLAG_MPSAFE, 902 &softc->force_write_error, 0, 903 "Force a write error for the next N writes."); 904 SYSCTL_ADD_INT(&softc->sysctl_ctx, SYSCTL_CHILDREN(softc->sysctl_tree), 905 OID_AUTO, "periodic_read_error", CTLFLAG_RW | CTLFLAG_MPSAFE, 906 &softc->periodic_read_error, 0, 907 "Force a read error every N reads (don't set too low)."); 908#endif 909 cam_periph_release(periph); 910} 911 912static int 913adagetattr(struct bio *bp) 914{ 915 int ret = -1; 916 struct cam_periph *periph; 917 918 if (bp->bio_disk == NULL || bp->bio_disk->d_drv1 == NULL) 919 return ENXIO; 920 periph = (struct cam_periph *)bp->bio_disk->d_drv1; 921 if (periph->path == NULL) 922 return ENXIO; 923 924 ret = xpt_getattr(bp->bio_data, bp->bio_length, bp->bio_attribute, 925 periph->path); 926 if (ret == 0) 927 bp->bio_completed = bp->bio_length; 928 return ret; 929} 930 931static cam_status 932adaregister(struct cam_periph *periph, void *arg) 933{ 934 struct ada_softc *softc; 935 struct ccb_pathinq cpi; 936 struct ccb_getdev *cgd; 937 char announce_buf[80], buf1[32]; 938 struct disk_params *dp; 939 caddr_t match; 940 u_int maxio; 941 int legacy_id, quirks; 942 943 cgd = (struct ccb_getdev *)arg; 944 if (periph == NULL) { 945 printf("adaregister: periph was NULL!!\n"); 946 return(CAM_REQ_CMP_ERR); 947 } 948 949 if (cgd == NULL) { 950 printf("adaregister: no getdev CCB, can't register device\n"); 951 return(CAM_REQ_CMP_ERR); 952 } 953 954 softc = (struct ada_softc *)malloc(sizeof(*softc), M_DEVBUF, 955 M_NOWAIT|M_ZERO); 956 957 if (softc == NULL) { 958 printf("adaregister: Unable to probe new device. " 959 "Unable to allocate softc\n"); 960 return(CAM_REQ_CMP_ERR); 961 } 962 963 bioq_init(&softc->bio_queue); 964 bioq_init(&softc->trim_queue); 965 966 if ((cgd->ident_data.capabilities1 & ATA_SUPPORT_DMA) && 967 (cgd->inq_flags & SID_DMA)) 968 softc->flags |= ADA_FLAG_CAN_DMA; 969 if (cgd->ident_data.support.command2 & ATA_SUPPORT_ADDRESS48) 970 softc->flags |= ADA_FLAG_CAN_48BIT; 971 if (cgd->ident_data.support.command2 & ATA_SUPPORT_FLUSHCACHE) 972 softc->flags |= ADA_FLAG_CAN_FLUSHCACHE; 973 if (cgd->ident_data.support.command1 & ATA_SUPPORT_POWERMGT) 974 softc->flags |= ADA_FLAG_CAN_POWERMGT; 975 if ((cgd->ident_data.satacapabilities & ATA_SUPPORT_NCQ) && 976 (cgd->inq_flags & SID_DMA) && (cgd->inq_flags & SID_CmdQue)) 977 softc->flags |= ADA_FLAG_CAN_NCQ; 978 if ((cgd->ident_data.support_dsm & ATA_SUPPORT_DSM_TRIM) && 979 (cgd->inq_flags & SID_DMA)) { 980 softc->flags |= ADA_FLAG_CAN_TRIM; 981 softc->trim_max_ranges = TRIM_MAX_RANGES; 982 if (cgd->ident_data.max_dsm_blocks != 0) { 983 softc->trim_max_ranges = 984 min(cgd->ident_data.max_dsm_blocks * 64, 985 softc->trim_max_ranges); 986 } 987 } 988 if (cgd->ident_data.support.command2 & ATA_SUPPORT_CFA) 989 softc->flags |= ADA_FLAG_CAN_CFA; 990 991 periph->softc = softc; 992 993 /* 994 * See if this device has any quirks. 995 */ 996 match = cam_quirkmatch((caddr_t)&cgd->ident_data, 997 (caddr_t)ada_quirk_table, 998 sizeof(ada_quirk_table)/sizeof(*ada_quirk_table), 999 sizeof(*ada_quirk_table), ata_identify_match); 1000 if (match != NULL) 1001 softc->quirks = ((struct ada_quirk_entry *)match)->quirks; 1002 else 1003 softc->quirks = ADA_Q_NONE; 1004 1005 bzero(&cpi, sizeof(cpi)); 1006 xpt_setup_ccb(&cpi.ccb_h, periph->path, CAM_PRIORITY_NONE); 1007 cpi.ccb_h.func_code = XPT_PATH_INQ; 1008 xpt_action((union ccb *)&cpi); 1009 1010 TASK_INIT(&softc->sysctl_task, 0, adasysctlinit, periph); 1011 1012 /* 1013 * Register this media as a disk 1014 */ 1015 (void)cam_periph_hold(periph, PRIBIO); 1016 mtx_unlock(periph->sim->mtx); 1017 snprintf(announce_buf, sizeof(announce_buf), 1018 "kern.cam.ada.%d.quirks", periph->unit_number); 1019 quirks = softc->quirks; 1020 TUNABLE_INT_FETCH(announce_buf, &quirks); 1021 softc->quirks = quirks; 1022 softc->read_ahead = -1; 1023 snprintf(announce_buf, sizeof(announce_buf), 1024 "kern.cam.ada.%d.read_ahead", periph->unit_number); 1025 TUNABLE_INT_FETCH(announce_buf, &softc->read_ahead); 1026 softc->write_cache = -1; 1027 snprintf(announce_buf, sizeof(announce_buf), 1028 "kern.cam.ada.%d.write_cache", periph->unit_number); 1029 TUNABLE_INT_FETCH(announce_buf, &softc->write_cache); 1030 adagetparams(periph, cgd); 1031 softc->disk = disk_alloc(); 1032 softc->disk->d_devstat = devstat_new_entry(periph->periph_name, 1033 periph->unit_number, softc->params.secsize, 1034 DEVSTAT_ALL_SUPPORTED, 1035 DEVSTAT_TYPE_DIRECT | 1036 XPORT_DEVSTAT_TYPE(cpi.transport), 1037 DEVSTAT_PRIORITY_DISK); 1038 softc->disk->d_open = adaopen; 1039 softc->disk->d_close = adaclose; 1040 softc->disk->d_strategy = adastrategy; 1041 softc->disk->d_getattr = adagetattr; 1042 softc->disk->d_dump = adadump; 1043 softc->disk->d_name = "ada"; 1044 softc->disk->d_drv1 = periph; 1045 maxio = cpi.maxio; /* Honor max I/O size of SIM */ 1046 if (maxio == 0) 1047 maxio = DFLTPHYS; /* traditional default */ 1048 else if (maxio > MAXPHYS) 1049 maxio = MAXPHYS; /* for safety */ 1050 if (softc->flags & ADA_FLAG_CAN_48BIT) 1051 maxio = min(maxio, 65536 * softc->params.secsize); 1052 else /* 28bit ATA command limit */ 1053 maxio = min(maxio, 256 * softc->params.secsize); 1054 softc->disk->d_maxsize = maxio; 1055 softc->disk->d_unit = periph->unit_number; 1056 softc->disk->d_flags = 0; 1057 if (softc->flags & ADA_FLAG_CAN_FLUSHCACHE) 1058 softc->disk->d_flags |= DISKFLAG_CANFLUSHCACHE; 1059 if ((softc->flags & ADA_FLAG_CAN_TRIM) || 1060 ((softc->flags & ADA_FLAG_CAN_CFA) && 1061 !(softc->flags & ADA_FLAG_CAN_48BIT))) 1062 softc->disk->d_flags |= DISKFLAG_CANDELETE; 1063 strlcpy(softc->disk->d_descr, cgd->ident_data.model, 1064 MIN(sizeof(softc->disk->d_descr), sizeof(cgd->ident_data.model))); 1065 softc->disk->d_hba_vendor = cpi.hba_vendor; 1066 softc->disk->d_hba_device = cpi.hba_device; 1067 softc->disk->d_hba_subvendor = cpi.hba_subvendor; 1068 softc->disk->d_hba_subdevice = cpi.hba_subdevice; 1069 1070 softc->disk->d_sectorsize = softc->params.secsize; 1071 softc->disk->d_mediasize = (off_t)softc->params.sectors * 1072 softc->params.secsize; 1073 if (ata_physical_sector_size(&cgd->ident_data) != 1074 softc->params.secsize) { 1075 softc->disk->d_stripesize = 1076 ata_physical_sector_size(&cgd->ident_data); 1077 softc->disk->d_stripeoffset = (softc->disk->d_stripesize - 1078 ata_logical_sector_offset(&cgd->ident_data)) % 1079 softc->disk->d_stripesize; 1080 } else if (softc->quirks & ADA_Q_4K) { 1081 softc->disk->d_stripesize = 4096; 1082 softc->disk->d_stripeoffset = 0; 1083 } 1084 softc->disk->d_fwsectors = softc->params.secs_per_track; 1085 softc->disk->d_fwheads = softc->params.heads; 1086 ata_disk_firmware_geom_adjust(softc->disk); 1087 1088 if (ada_legacy_aliases) { 1089#ifdef ATA_STATIC_ID 1090 legacy_id = xpt_path_legacy_ata_id(periph->path); 1091#else 1092 legacy_id = softc->disk->d_unit; 1093#endif 1094 if (legacy_id >= 0) { 1095 snprintf(announce_buf, sizeof(announce_buf), 1096 "kern.devalias.%s%d", 1097 softc->disk->d_name, softc->disk->d_unit); 1098 snprintf(buf1, sizeof(buf1), 1099 "ad%d", legacy_id); 1100 setenv(announce_buf, buf1); 1101 } 1102 } else 1103 legacy_id = -1; 1104 disk_create(softc->disk, DISK_VERSION); 1105 mtx_lock(periph->sim->mtx); 1106 cam_periph_unhold(periph); 1107 1108 dp = &softc->params; 1109 snprintf(announce_buf, sizeof(announce_buf), 1110 "%juMB (%ju %u byte sectors: %dH %dS/T %dC)", 1111 (uintmax_t)(((uintmax_t)dp->secsize * 1112 dp->sectors) / (1024*1024)), 1113 (uintmax_t)dp->sectors, 1114 dp->secsize, dp->heads, 1115 dp->secs_per_track, dp->cylinders); 1116 xpt_announce_periph(periph, announce_buf); 1117 if (legacy_id >= 0) 1118 printf("%s%d: Previously was known as ad%d\n", 1119 periph->periph_name, periph->unit_number, legacy_id); 1120 1121 /* 1122 * Create our sysctl variables, now that we know 1123 * we have successfully attached. 1124 */ 1125 cam_periph_acquire(periph); 1126 taskqueue_enqueue(taskqueue_thread, &softc->sysctl_task); 1127 1128 /* 1129 * Add async callbacks for bus reset and 1130 * bus device reset calls. I don't bother 1131 * checking if this fails as, in most cases, 1132 * the system will function just fine without 1133 * them and the only alternative would be to 1134 * not attach the device on failure. 1135 */ 1136 xpt_register_async(AC_SENT_BDR | AC_BUS_RESET | AC_LOST_DEVICE | 1137 AC_GETDEV_CHANGED | AC_ADVINFO_CHANGED, 1138 adaasync, periph, periph->path); 1139 1140 /* 1141 * Schedule a periodic event to occasionally send an 1142 * ordered tag to a device. 1143 */ 1144 callout_init_mtx(&softc->sendordered_c, periph->sim->mtx, 0); 1145 callout_reset(&softc->sendordered_c, 1146 (ada_default_timeout * hz) / ADA_ORDEREDTAG_INTERVAL, 1147 adasendorderedtag, softc); 1148 1149 if (ADA_RA >= 0 && 1150 cgd->ident_data.support.command1 & ATA_SUPPORT_LOOKAHEAD) { 1151 softc->state = ADA_STATE_RAHEAD; 1152 cam_periph_acquire(periph); 1153 cam_freeze_devq_arg(periph->path, 1154 RELSIM_RELEASE_RUNLEVEL, CAM_RL_DEV + 1); 1155 xpt_schedule(periph, CAM_PRIORITY_DEV); 1156 } else if (ADA_WC >= 0 && 1157 cgd->ident_data.support.command1 & ATA_SUPPORT_WRITECACHE) { 1158 softc->state = ADA_STATE_WCACHE; 1159 cam_periph_acquire(periph); 1160 cam_freeze_devq_arg(periph->path, 1161 RELSIM_RELEASE_RUNLEVEL, CAM_RL_DEV + 1); 1162 xpt_schedule(periph, CAM_PRIORITY_DEV); 1163 } else 1164 softc->state = ADA_STATE_NORMAL; 1165 1166 return(CAM_REQ_CMP); 1167} 1168 1169static void 1170adastart(struct cam_periph *periph, union ccb *start_ccb) 1171{ 1172 struct ada_softc *softc = (struct ada_softc *)periph->softc; 1173 struct ccb_ataio *ataio = &start_ccb->ataio; 1174 1175 CAM_DEBUG(periph->path, CAM_DEBUG_TRACE, ("adastart\n")); 1176 1177 switch (softc->state) { 1178 case ADA_STATE_NORMAL: 1179 { 1180 struct bio *bp; 1181 u_int8_t tag_code; 1182 1183 /* Execute immediate CCB if waiting. */ 1184 if (periph->immediate_priority <= periph->pinfo.priority) { 1185 CAM_DEBUG(periph->path, CAM_DEBUG_SUBTRACE, 1186 ("queuing for immediate ccb\n")); 1187 start_ccb->ccb_h.ccb_state = ADA_CCB_WAITING; 1188 SLIST_INSERT_HEAD(&periph->ccb_list, &start_ccb->ccb_h, 1189 periph_links.sle); 1190 periph->immediate_priority = CAM_PRIORITY_NONE; 1191 wakeup(&periph->ccb_list); 1192 /* Have more work to do, so ensure we stay scheduled */ 1193 adaschedule(periph); 1194 break; 1195 } 1196 /* Run TRIM if not running yet. */ 1197 if (!softc->trim_running && 1198 (bp = bioq_first(&softc->trim_queue)) != 0) { 1199 struct trim_request *req = &softc->trim_req; 1200 struct bio *bp1; 1201 uint64_t lastlba = (uint64_t)-1; 1202 int bps = 0, c, lastcount = 0, off, ranges = 0; 1203 1204 softc->trim_running = 1; 1205 bzero(req, sizeof(*req)); 1206 bp1 = bp; 1207 do { 1208 uint64_t lba = bp1->bio_pblkno; 1209 int count = bp1->bio_bcount / 1210 softc->params.secsize; 1211 1212 bioq_remove(&softc->trim_queue, bp1); 1213 1214 /* Try to extend the previous range. */ 1215 if (lba == lastlba) { 1216 c = min(count, 0xffff - lastcount); 1217 lastcount += c; 1218 off = (ranges - 1) * 8; 1219 req->data[off + 6] = lastcount & 0xff; 1220 req->data[off + 7] = 1221 (lastcount >> 8) & 0xff; 1222 count -= c; 1223 lba += c; 1224 } 1225 1226 while (count > 0) { 1227 c = min(count, 0xffff); 1228 off = ranges * 8; 1229 req->data[off + 0] = lba & 0xff; 1230 req->data[off + 1] = (lba >> 8) & 0xff; 1231 req->data[off + 2] = (lba >> 16) & 0xff; 1232 req->data[off + 3] = (lba >> 24) & 0xff; 1233 req->data[off + 4] = (lba >> 32) & 0xff; 1234 req->data[off + 5] = (lba >> 40) & 0xff; 1235 req->data[off + 6] = c & 0xff; 1236 req->data[off + 7] = (c >> 8) & 0xff; 1237 lba += c; 1238 count -= c; 1239 lastcount = c; 1240 ranges++; 1241 } 1242 lastlba = lba; 1243 req->bps[bps++] = bp1; 1244 bp1 = bioq_first(&softc->trim_queue); 1245 if (bps >= TRIM_MAX_BIOS || 1246 bp1 == NULL || 1247 bp1->bio_bcount / softc->params.secsize > 1248 (softc->trim_max_ranges - ranges) * 0xffff) 1249 break; 1250 } while (1); 1251 cam_fill_ataio(ataio, 1252 ada_retry_count, 1253 adadone, 1254 CAM_DIR_OUT, 1255 0, 1256 req->data, 1257 ((ranges + 63) / 64) * 512, 1258 ada_default_timeout * 1000); 1259 ata_48bit_cmd(ataio, ATA_DATA_SET_MANAGEMENT, 1260 ATA_DSM_TRIM, 0, (ranges + 63) / 64); 1261 start_ccb->ccb_h.ccb_state = ADA_CCB_TRIM; 1262 goto out; 1263 } 1264 /* Run regular command. */ 1265 bp = bioq_first(&softc->bio_queue); 1266 if (bp == NULL) { 1267 xpt_release_ccb(start_ccb); 1268 break; 1269 } 1270 bioq_remove(&softc->bio_queue, bp); 1271 1272 if ((bp->bio_flags & BIO_ORDERED) != 0 1273 || (softc->flags & ADA_FLAG_NEED_OTAG) != 0) { 1274 softc->flags &= ~ADA_FLAG_NEED_OTAG; 1275 softc->ordered_tag_count++; 1276 tag_code = 0; 1277 } else { 1278 tag_code = 1; 1279 } 1280 switch (bp->bio_cmd) { 1281 case BIO_READ: 1282 case BIO_WRITE: 1283 { 1284 uint64_t lba = bp->bio_pblkno; 1285 uint16_t count = bp->bio_bcount / softc->params.secsize; 1286#ifdef ADA_TEST_FAILURE 1287 int fail = 0; 1288 1289 /* 1290 * Support the failure ioctls. If the command is a 1291 * read, and there are pending forced read errors, or 1292 * if a write and pending write errors, then fail this 1293 * operation with EIO. This is useful for testing 1294 * purposes. Also, support having every Nth read fail. 1295 * 1296 * This is a rather blunt tool. 1297 */ 1298 if (bp->bio_cmd == BIO_READ) { 1299 if (softc->force_read_error) { 1300 softc->force_read_error--; 1301 fail = 1; 1302 } 1303 if (softc->periodic_read_error > 0) { 1304 if (++softc->periodic_read_count >= 1305 softc->periodic_read_error) { 1306 softc->periodic_read_count = 0; 1307 fail = 1; 1308 } 1309 } 1310 } else { 1311 if (softc->force_write_error) { 1312 softc->force_write_error--; 1313 fail = 1; 1314 } 1315 } 1316 if (fail) { 1317 bp->bio_error = EIO; 1318 bp->bio_flags |= BIO_ERROR; 1319 biodone(bp); 1320 xpt_release_ccb(start_ccb); 1321 adaschedule(periph); 1322 return; 1323 } 1324#endif 1325 cam_fill_ataio(ataio, 1326 ada_retry_count, 1327 adadone, 1328 bp->bio_cmd == BIO_READ ? 1329 CAM_DIR_IN : CAM_DIR_OUT, 1330 tag_code, 1331 bp->bio_data, 1332 bp->bio_bcount, 1333 ada_default_timeout*1000); 1334 1335 if ((softc->flags & ADA_FLAG_CAN_NCQ) && tag_code) { 1336 if (bp->bio_cmd == BIO_READ) { 1337 ata_ncq_cmd(ataio, ATA_READ_FPDMA_QUEUED, 1338 lba, count); 1339 } else { 1340 ata_ncq_cmd(ataio, ATA_WRITE_FPDMA_QUEUED, 1341 lba, count); 1342 } 1343 } else if ((softc->flags & ADA_FLAG_CAN_48BIT) && 1344 (lba + count >= ATA_MAX_28BIT_LBA || 1345 count > 256)) { 1346 if (softc->flags & ADA_FLAG_CAN_DMA) { 1347 if (bp->bio_cmd == BIO_READ) { 1348 ata_48bit_cmd(ataio, ATA_READ_DMA48, 1349 0, lba, count); 1350 } else { 1351 ata_48bit_cmd(ataio, ATA_WRITE_DMA48, 1352 0, lba, count); 1353 } 1354 } else { 1355 if (bp->bio_cmd == BIO_READ) { 1356 ata_48bit_cmd(ataio, ATA_READ_MUL48, 1357 0, lba, count); 1358 } else { 1359 ata_48bit_cmd(ataio, ATA_WRITE_MUL48, 1360 0, lba, count); 1361 } 1362 } 1363 } else { 1364 if (count == 256) 1365 count = 0; 1366 if (softc->flags & ADA_FLAG_CAN_DMA) { 1367 if (bp->bio_cmd == BIO_READ) { 1368 ata_28bit_cmd(ataio, ATA_READ_DMA, 1369 0, lba, count); 1370 } else { 1371 ata_28bit_cmd(ataio, ATA_WRITE_DMA, 1372 0, lba, count); 1373 } 1374 } else { 1375 if (bp->bio_cmd == BIO_READ) { 1376 ata_28bit_cmd(ataio, ATA_READ_MUL, 1377 0, lba, count); 1378 } else { 1379 ata_28bit_cmd(ataio, ATA_WRITE_MUL, 1380 0, lba, count); 1381 } 1382 } 1383 } 1384 break; 1385 } 1386 case BIO_DELETE: 1387 { 1388 uint64_t lba = bp->bio_pblkno; 1389 uint16_t count = bp->bio_bcount / softc->params.secsize; 1390 1391 cam_fill_ataio(ataio, 1392 ada_retry_count, 1393 adadone, 1394 CAM_DIR_NONE, 1395 0, 1396 NULL, 1397 0, 1398 ada_default_timeout*1000); 1399 1400 if (count >= 256) 1401 count = 0; 1402 ata_28bit_cmd(ataio, ATA_CFA_ERASE, 0, lba, count); 1403 break; 1404 } 1405 case BIO_FLUSH: 1406 cam_fill_ataio(ataio, 1407 1, 1408 adadone, 1409 CAM_DIR_NONE, 1410 0, 1411 NULL, 1412 0, 1413 ada_default_timeout*1000); 1414 1415 if (softc->flags & ADA_FLAG_CAN_48BIT) 1416 ata_48bit_cmd(ataio, ATA_FLUSHCACHE48, 0, 0, 0); 1417 else 1418 ata_28bit_cmd(ataio, ATA_FLUSHCACHE, 0, 0, 0); 1419 break; 1420 } 1421 start_ccb->ccb_h.ccb_state = ADA_CCB_BUFFER_IO; 1422out: 1423 start_ccb->ccb_h.ccb_bp = bp; 1424 softc->outstanding_cmds++; 1425 xpt_action(start_ccb); 1426 1427 /* May have more work to do, so ensure we stay scheduled */ 1428 adaschedule(periph); 1429 break; 1430 } 1431 case ADA_STATE_RAHEAD: 1432 case ADA_STATE_WCACHE: 1433 { 1434 if (softc->flags & ADA_FLAG_PACK_INVALID) { 1435 softc->state = ADA_STATE_NORMAL; 1436 xpt_release_ccb(start_ccb); 1437 cam_release_devq(periph->path, 1438 RELSIM_RELEASE_RUNLEVEL, 0, CAM_RL_DEV + 1, FALSE); 1439 adaschedule(periph); 1440 cam_periph_release_locked(periph); 1441 return; 1442 } 1443 1444 cam_fill_ataio(ataio, 1445 1, 1446 adadone, 1447 CAM_DIR_NONE, 1448 0, 1449 NULL, 1450 0, 1451 ada_default_timeout*1000); 1452 1453 if (softc->state == ADA_STATE_RAHEAD) { 1454 ata_28bit_cmd(ataio, ATA_SETFEATURES, ADA_RA ? 1455 ATA_SF_ENAB_RCACHE : ATA_SF_DIS_RCACHE, 0, 0); 1456 start_ccb->ccb_h.ccb_state = ADA_CCB_RAHEAD; 1457 } else { 1458 ata_28bit_cmd(ataio, ATA_SETFEATURES, ADA_WC ? 1459 ATA_SF_ENAB_WCACHE : ATA_SF_DIS_WCACHE, 0, 0); 1460 start_ccb->ccb_h.ccb_state = ADA_CCB_WCACHE; 1461 } 1462 xpt_action(start_ccb); 1463 break; 1464 } 1465 } 1466} 1467 1468static void 1469adadone(struct cam_periph *periph, union ccb *done_ccb) 1470{ 1471 struct ada_softc *softc; 1472 struct ccb_ataio *ataio; 1473 struct ccb_getdev *cgd; 1474 1475 softc = (struct ada_softc *)periph->softc; 1476 ataio = &done_ccb->ataio; 1477 1478 CAM_DEBUG(periph->path, CAM_DEBUG_TRACE, ("adadone\n")); 1479 1480 switch (ataio->ccb_h.ccb_state & ADA_CCB_TYPE_MASK) { 1481 case ADA_CCB_BUFFER_IO: 1482 case ADA_CCB_TRIM: 1483 { 1484 struct bio *bp; 1485 1486 bp = (struct bio *)done_ccb->ccb_h.ccb_bp; 1487 if ((done_ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) { 1488 int error; 1489 1490 error = adaerror(done_ccb, 0, 0); 1491 if (error == ERESTART) { 1492 /* A retry was scheduled, so just return. */ 1493 return; 1494 } 1495 if (error != 0) { 1496 if (error == ENXIO && 1497 (softc->flags & ADA_FLAG_PACK_INVALID) == 0) { 1498 /* 1499 * Catastrophic error. Mark our pack as 1500 * invalid. 1501 */ 1502 /* 1503 * XXX See if this is really a media 1504 * XXX change first? 1505 */ 1506 xpt_print(periph->path, 1507 "Invalidating pack\n"); 1508 softc->flags |= ADA_FLAG_PACK_INVALID; 1509 } 1510 bp->bio_error = error; 1511 bp->bio_resid = bp->bio_bcount; 1512 bp->bio_flags |= BIO_ERROR; 1513 } else { 1514 bp->bio_resid = ataio->resid; 1515 bp->bio_error = 0; 1516 if (bp->bio_resid != 0) 1517 bp->bio_flags |= BIO_ERROR; 1518 } 1519 if ((done_ccb->ccb_h.status & CAM_DEV_QFRZN) != 0) 1520 cam_release_devq(done_ccb->ccb_h.path, 1521 /*relsim_flags*/0, 1522 /*reduction*/0, 1523 /*timeout*/0, 1524 /*getcount_only*/0); 1525 } else { 1526 if ((done_ccb->ccb_h.status & CAM_DEV_QFRZN) != 0) 1527 panic("REQ_CMP with QFRZN"); 1528 bp->bio_resid = ataio->resid; 1529 if (ataio->resid > 0) 1530 bp->bio_flags |= BIO_ERROR; 1531 } 1532 softc->outstanding_cmds--; 1533 if (softc->outstanding_cmds == 0) 1534 softc->flags |= ADA_FLAG_WENT_IDLE; 1535 if ((ataio->ccb_h.ccb_state & ADA_CCB_TYPE_MASK) == 1536 ADA_CCB_TRIM) { 1537 struct trim_request *req = 1538 (struct trim_request *)ataio->data_ptr; 1539 int i; 1540 1541 for (i = 1; i < TRIM_MAX_BIOS && req->bps[i]; i++) { 1542 struct bio *bp1 = req->bps[i]; 1543 1544 bp1->bio_resid = bp->bio_resid; 1545 bp1->bio_error = bp->bio_error; 1546 if (bp->bio_flags & BIO_ERROR) 1547 bp1->bio_flags |= BIO_ERROR; 1548 biodone(bp1); 1549 } 1550 softc->trim_running = 0; 1551 biodone(bp); 1552 adaschedule(periph); 1553 } else 1554 biodone(bp); 1555 break; 1556 } 1557 case ADA_CCB_RAHEAD: 1558 { 1559 if ((done_ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) { 1560 if (adaerror(done_ccb, 0, 0) == ERESTART) { 1561 return; 1562 } else if ((done_ccb->ccb_h.status & CAM_DEV_QFRZN) != 0) { 1563 cam_release_devq(done_ccb->ccb_h.path, 1564 /*relsim_flags*/0, 1565 /*reduction*/0, 1566 /*timeout*/0, 1567 /*getcount_only*/0); 1568 } 1569 } 1570 1571 /* 1572 * Since our peripheral may be invalidated by an error 1573 * above or an external event, we must release our CCB 1574 * before releasing the reference on the peripheral. 1575 * The peripheral will only go away once the last reference 1576 * is removed, and we need it around for the CCB release 1577 * operation. 1578 */ 1579 cgd = (struct ccb_getdev *)done_ccb; 1580 xpt_setup_ccb(&cgd->ccb_h, periph->path, CAM_PRIORITY_NORMAL); 1581 cgd->ccb_h.func_code = XPT_GDEV_TYPE; 1582 xpt_action((union ccb *)cgd); 1583 if (ADA_WC >= 0 && 1584 cgd->ident_data.support.command1 & ATA_SUPPORT_WRITECACHE) { 1585 softc->state = ADA_STATE_WCACHE; 1586 xpt_release_ccb(done_ccb); 1587 xpt_schedule(periph, CAM_PRIORITY_DEV); 1588 return; 1589 } 1590 softc->state = ADA_STATE_NORMAL; 1591 xpt_release_ccb(done_ccb); 1592 cam_release_devq(periph->path, 1593 RELSIM_RELEASE_RUNLEVEL, 0, CAM_RL_DEV + 1, FALSE); 1594 adaschedule(periph); 1595 cam_periph_release_locked(periph); 1596 return; 1597 } 1598 case ADA_CCB_WCACHE: 1599 { 1600 if ((done_ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) { 1601 if (adaerror(done_ccb, 0, 0) == ERESTART) { 1602 return; 1603 } else if ((done_ccb->ccb_h.status & CAM_DEV_QFRZN) != 0) { 1604 cam_release_devq(done_ccb->ccb_h.path, 1605 /*relsim_flags*/0, 1606 /*reduction*/0, 1607 /*timeout*/0, 1608 /*getcount_only*/0); 1609 } 1610 } 1611 1612 softc->state = ADA_STATE_NORMAL; 1613 /* 1614 * Since our peripheral may be invalidated by an error 1615 * above or an external event, we must release our CCB 1616 * before releasing the reference on the peripheral. 1617 * The peripheral will only go away once the last reference 1618 * is removed, and we need it around for the CCB release 1619 * operation. 1620 */ 1621 xpt_release_ccb(done_ccb); 1622 cam_release_devq(periph->path, 1623 RELSIM_RELEASE_RUNLEVEL, 0, CAM_RL_DEV + 1, FALSE); 1624 adaschedule(periph); 1625 cam_periph_release_locked(periph); 1626 return; 1627 } 1628 case ADA_CCB_WAITING: 1629 { 1630 /* Caller will release the CCB */ 1631 wakeup(&done_ccb->ccb_h.cbfcnp); 1632 return; 1633 } 1634 case ADA_CCB_DUMP: 1635 /* No-op. We're polling */ 1636 return; 1637 default: 1638 break; 1639 } 1640 xpt_release_ccb(done_ccb); 1641} 1642 1643static int 1644adaerror(union ccb *ccb, u_int32_t cam_flags, u_int32_t sense_flags) 1645{ 1646 1647 return(cam_periph_error(ccb, cam_flags, sense_flags, NULL)); 1648} 1649 1650static void 1651adagetparams(struct cam_periph *periph, struct ccb_getdev *cgd) 1652{ 1653 struct ada_softc *softc = (struct ada_softc *)periph->softc; 1654 struct disk_params *dp = &softc->params; 1655 u_int64_t lbasize48; 1656 u_int32_t lbasize; 1657 1658 dp->secsize = ata_logical_sector_size(&cgd->ident_data); 1659 if ((cgd->ident_data.atavalid & ATA_FLAG_54_58) && 1660 cgd->ident_data.current_heads && cgd->ident_data.current_sectors) { 1661 dp->heads = cgd->ident_data.current_heads; 1662 dp->secs_per_track = cgd->ident_data.current_sectors; 1663 dp->cylinders = cgd->ident_data.cylinders; 1664 dp->sectors = (u_int32_t)cgd->ident_data.current_size_1 | 1665 ((u_int32_t)cgd->ident_data.current_size_2 << 16); 1666 } else { 1667 dp->heads = cgd->ident_data.heads; 1668 dp->secs_per_track = cgd->ident_data.sectors; 1669 dp->cylinders = cgd->ident_data.cylinders; 1670 dp->sectors = cgd->ident_data.cylinders * dp->heads * dp->secs_per_track; 1671 } 1672 lbasize = (u_int32_t)cgd->ident_data.lba_size_1 | 1673 ((u_int32_t)cgd->ident_data.lba_size_2 << 16); 1674 1675 /* use the 28bit LBA size if valid or bigger than the CHS mapping */ 1676 if (cgd->ident_data.cylinders == 16383 || dp->sectors < lbasize) 1677 dp->sectors = lbasize; 1678 1679 /* use the 48bit LBA size if valid */ 1680 lbasize48 = ((u_int64_t)cgd->ident_data.lba_size48_1) | 1681 ((u_int64_t)cgd->ident_data.lba_size48_2 << 16) | 1682 ((u_int64_t)cgd->ident_data.lba_size48_3 << 32) | 1683 ((u_int64_t)cgd->ident_data.lba_size48_4 << 48); 1684 if ((cgd->ident_data.support.command2 & ATA_SUPPORT_ADDRESS48) && 1685 lbasize48 > ATA_MAX_28BIT_LBA) 1686 dp->sectors = lbasize48; 1687} 1688 1689static void 1690adasendorderedtag(void *arg) 1691{ 1692 struct ada_softc *softc = arg; 1693 1694 if (ada_send_ordered) { 1695 if ((softc->ordered_tag_count == 0) 1696 && ((softc->flags & ADA_FLAG_WENT_IDLE) == 0)) { 1697 softc->flags |= ADA_FLAG_NEED_OTAG; 1698 } 1699 if (softc->outstanding_cmds > 0) 1700 softc->flags &= ~ADA_FLAG_WENT_IDLE; 1701 1702 softc->ordered_tag_count = 0; 1703 } 1704 /* Queue us up again */ 1705 callout_reset(&softc->sendordered_c, 1706 (ada_default_timeout * hz) / ADA_ORDEREDTAG_INTERVAL, 1707 adasendorderedtag, softc); 1708} 1709 1710/* 1711 * Step through all ADA peripheral drivers, and if the device is still open, 1712 * sync the disk cache to physical media. 1713 */ 1714static void 1715adaflush(void) 1716{ 1717 struct cam_periph *periph; 1718 struct ada_softc *softc; 1719 1720 TAILQ_FOREACH(periph, &adadriver.units, unit_links) { 1721 union ccb ccb; 1722 1723 /* If we paniced with lock held - not recurse here. */ 1724 if (cam_periph_owned(periph)) 1725 continue; 1726 cam_periph_lock(periph); 1727 softc = (struct ada_softc *)periph->softc; 1728 /* 1729 * We only sync the cache if the drive is still open, and 1730 * if the drive is capable of it.. 1731 */ 1732 if (((softc->flags & ADA_FLAG_OPEN) == 0) || 1733 (softc->flags & ADA_FLAG_CAN_FLUSHCACHE) == 0) { 1734 cam_periph_unlock(periph); 1735 continue; 1736 } 1737 1738 xpt_setup_ccb(&ccb.ccb_h, periph->path, CAM_PRIORITY_NORMAL); 1739 1740 ccb.ccb_h.ccb_state = ADA_CCB_DUMP; 1741 cam_fill_ataio(&ccb.ataio, 1742 1, 1743 adadone, 1744 CAM_DIR_NONE, 1745 0, 1746 NULL, 1747 0, 1748 ada_default_timeout*1000); 1749 1750 if (softc->flags & ADA_FLAG_CAN_48BIT) 1751 ata_48bit_cmd(&ccb.ataio, ATA_FLUSHCACHE48, 0, 0, 0); 1752 else 1753 ata_28bit_cmd(&ccb.ataio, ATA_FLUSHCACHE, 0, 0, 0); 1754 xpt_polled_action(&ccb); 1755 1756 if ((ccb.ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) 1757 xpt_print(periph->path, "Synchronize cache failed\n"); 1758 1759 if ((ccb.ccb_h.status & CAM_DEV_QFRZN) != 0) 1760 cam_release_devq(ccb.ccb_h.path, 1761 /*relsim_flags*/0, 1762 /*reduction*/0, 1763 /*timeout*/0, 1764 /*getcount_only*/0); 1765 cam_periph_unlock(periph); 1766 } 1767} 1768 1769static void 1770adaspindown(uint8_t cmd, int flags) 1771{ 1772 struct cam_periph *periph; 1773 struct ada_softc *softc; 1774 1775 TAILQ_FOREACH(periph, &adadriver.units, unit_links) { 1776 union ccb ccb; 1777 1778 /* If we paniced with lock held - not recurse here. */ 1779 if (cam_periph_owned(periph)) 1780 continue; 1781 cam_periph_lock(periph); 1782 softc = (struct ada_softc *)periph->softc; 1783 /* 1784 * We only spin-down the drive if it is capable of it.. 1785 */ 1786 if ((softc->flags & ADA_FLAG_CAN_POWERMGT) == 0) { 1787 cam_periph_unlock(periph); 1788 continue; 1789 } 1790 1791 if (bootverbose) 1792 xpt_print(periph->path, "spin-down\n"); 1793 1794 xpt_setup_ccb(&ccb.ccb_h, periph->path, CAM_PRIORITY_NORMAL); 1795 1796 ccb.ccb_h.ccb_state = ADA_CCB_DUMP; 1797 cam_fill_ataio(&ccb.ataio, 1798 1, 1799 adadone, 1800 CAM_DIR_NONE | flags, 1801 0, 1802 NULL, 1803 0, 1804 ada_default_timeout*1000); 1805 1806 ata_28bit_cmd(&ccb.ataio, cmd, 0, 0, 0); 1807 xpt_polled_action(&ccb); 1808 1809 if ((ccb.ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) 1810 xpt_print(periph->path, "Spin-down disk failed\n"); 1811 1812 if ((ccb.ccb_h.status & CAM_DEV_QFRZN) != 0) 1813 cam_release_devq(ccb.ccb_h.path, 1814 /*relsim_flags*/0, 1815 /*reduction*/0, 1816 /*timeout*/0, 1817 /*getcount_only*/0); 1818 cam_periph_unlock(periph); 1819 } 1820} 1821 1822static void 1823adashutdown(void *arg, int howto) 1824{ 1825 1826 adaflush(); 1827 if (ada_spindown_shutdown != 0 && 1828 (howto & (RB_HALT | RB_POWEROFF)) != 0) 1829 adaspindown(ATA_STANDBY_IMMEDIATE, 0); 1830} 1831 1832static void 1833adasuspend(void *arg) 1834{ 1835 1836 adaflush(); 1837 if (ada_spindown_suspend != 0) 1838 adaspindown(ATA_SLEEP, CAM_DEV_QFREEZE); 1839} 1840 1841static void 1842adaresume(void *arg) 1843{ 1844 struct cam_periph *periph; 1845 struct ada_softc *softc; 1846 1847 if (ada_spindown_suspend == 0) 1848 return; 1849 1850 TAILQ_FOREACH(periph, &adadriver.units, unit_links) { 1851 cam_periph_lock(periph); 1852 softc = (struct ada_softc *)periph->softc; 1853 /* 1854 * We only spin-down the drive if it is capable of it.. 1855 */ 1856 if ((softc->flags & ADA_FLAG_CAN_POWERMGT) == 0) { 1857 cam_periph_unlock(periph); 1858 continue; 1859 } 1860 1861 if (bootverbose) 1862 xpt_print(periph->path, "resume\n"); 1863 1864 /* 1865 * Drop freeze taken due to CAM_DEV_QFREEZE flag set on 1866 * sleep request. 1867 */ 1868 cam_release_devq(periph->path, 1869 /*relsim_flags*/0, 1870 /*openings*/0, 1871 /*timeout*/0, 1872 /*getcount_only*/0); 1873 1874 cam_periph_unlock(periph); 1875 } 1876} 1877 1878#endif /* _KERNEL */ 1879