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