ata_da.c revision 198708
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: head/sys/cam/ata/ata_da.c 198708 2009-10-31 10:43:38Z mav $"); 29 30#include <sys/param.h> 31 32#ifdef _KERNEL 33#include <sys/systm.h> 34#include <sys/kernel.h> 35#include <sys/bio.h> 36#include <sys/sysctl.h> 37#include <sys/taskqueue.h> 38#include <sys/lock.h> 39#include <sys/mutex.h> 40#include <sys/conf.h> 41#include <sys/devicestat.h> 42#include <sys/eventhandler.h> 43#include <sys/malloc.h> 44#include <sys/cons.h> 45#include <geom/geom_disk.h> 46#endif /* _KERNEL */ 47 48#ifndef _KERNEL 49#include <stdio.h> 50#include <string.h> 51#endif /* _KERNEL */ 52 53#include <cam/cam.h> 54#include <cam/cam_ccb.h> 55#include <cam/cam_periph.h> 56#include <cam/cam_xpt_periph.h> 57#include <cam/cam_sim.h> 58 59#include <cam/ata/ata_all.h> 60 61#ifdef _KERNEL 62 63#define ATA_MAX_28BIT_LBA 268435455UL 64 65typedef enum { 66 ADA_STATE_NORMAL 67} ada_state; 68 69typedef enum { 70 ADA_FLAG_PACK_INVALID = 0x001, 71 ADA_FLAG_CAN_48BIT = 0x002, 72 ADA_FLAG_CAN_FLUSHCACHE = 0x004, 73 ADA_FLAG_CAN_NCQ = 0x008, 74 ADA_FLAG_CAN_DMA = 0x010, 75 ADA_FLAG_NEED_OTAG = 0x020, 76 ADA_FLAG_WENT_IDLE = 0x040, 77 ADA_FLAG_OPEN = 0x100, 78 ADA_FLAG_SCTX_INIT = 0x200 79} ada_flags; 80 81typedef enum { 82 ADA_Q_NONE = 0x00 83} ada_quirks; 84 85typedef enum { 86 ADA_CCB_BUFFER_IO = 0x03, 87 ADA_CCB_WAITING = 0x04, 88 ADA_CCB_DUMP = 0x05, 89 ADA_CCB_TYPE_MASK = 0x0F, 90} ada_ccb_state; 91 92/* Offsets into our private area for storing information */ 93#define ccb_state ppriv_field0 94#define ccb_bp ppriv_ptr1 95 96struct disk_params { 97 u_int8_t heads; 98 u_int32_t cylinders; 99 u_int8_t secs_per_track; 100 u_int32_t secsize; /* Number of bytes/sector */ 101 u_int64_t sectors; /* total number sectors */ 102}; 103 104struct ada_softc { 105 struct bio_queue_head bio_queue; 106 SLIST_ENTRY(ada_softc) links; 107 LIST_HEAD(, ccb_hdr) pending_ccbs; 108 ada_state state; 109 ada_flags flags; 110 ada_quirks quirks; 111 int ordered_tag_count; 112 int outstanding_cmds; 113 struct disk_params params; 114 struct disk *disk; 115 union ccb saved_ccb; 116 struct task sysctl_task; 117 struct sysctl_ctx_list sysctl_ctx; 118 struct sysctl_oid *sysctl_tree; 119 struct callout sendordered_c; 120}; 121 122struct ada_quirk_entry { 123 struct scsi_inquiry_pattern inq_pat; 124 ada_quirks quirks; 125}; 126 127//static struct ada_quirk_entry ada_quirk_table[] = 128//{ 129//}; 130 131static disk_strategy_t adastrategy; 132static dumper_t adadump; 133static periph_init_t adainit; 134static void adaasync(void *callback_arg, u_int32_t code, 135 struct cam_path *path, void *arg); 136static void adasysctlinit(void *context, int pending); 137static periph_ctor_t adaregister; 138static periph_dtor_t adacleanup; 139static periph_start_t adastart; 140static periph_oninv_t adaoninvalidate; 141static void adadone(struct cam_periph *periph, 142 union ccb *done_ccb); 143static int adaerror(union ccb *ccb, u_int32_t cam_flags, 144 u_int32_t sense_flags); 145static void adasetgeom(struct cam_periph *periph, 146 struct ccb_getdev *cgd); 147static timeout_t adasendorderedtag; 148static void adashutdown(void *arg, int howto); 149 150#ifndef ADA_DEFAULT_TIMEOUT 151#define ADA_DEFAULT_TIMEOUT 30 /* Timeout in seconds */ 152#endif 153 154#ifndef ADA_DEFAULT_RETRY 155#define ADA_DEFAULT_RETRY 4 156#endif 157 158#ifndef ADA_DEFAULT_SEND_ORDERED 159#define ADA_DEFAULT_SEND_ORDERED 1 160#endif 161 162 163static int ada_retry_count = ADA_DEFAULT_RETRY; 164static int ada_default_timeout = ADA_DEFAULT_TIMEOUT; 165static int ada_send_ordered = ADA_DEFAULT_SEND_ORDERED; 166 167SYSCTL_NODE(_kern_cam, OID_AUTO, ada, CTLFLAG_RD, 0, 168 "CAM Direct Access Disk driver"); 169SYSCTL_INT(_kern_cam_ada, OID_AUTO, retry_count, CTLFLAG_RW, 170 &ada_retry_count, 0, "Normal I/O retry count"); 171TUNABLE_INT("kern.cam.ada.retry_count", &ada_retry_count); 172SYSCTL_INT(_kern_cam_ada, OID_AUTO, default_timeout, CTLFLAG_RW, 173 &ada_default_timeout, 0, "Normal I/O timeout (in seconds)"); 174TUNABLE_INT("kern.cam.ada.default_timeout", &ada_default_timeout); 175SYSCTL_INT(_kern_cam_ada, OID_AUTO, ada_send_ordered, CTLFLAG_RW, 176 &ada_send_ordered, 0, "Send Ordered Tags"); 177TUNABLE_INT("kern.cam.ada.ada_send_ordered", &ada_send_ordered); 178 179/* 180 * ADA_ORDEREDTAG_INTERVAL determines how often, relative 181 * to the default timeout, we check to see whether an ordered 182 * tagged transaction is appropriate to prevent simple tag 183 * starvation. Since we'd like to ensure that there is at least 184 * 1/2 of the timeout length left for a starved transaction to 185 * complete after we've sent an ordered tag, we must poll at least 186 * four times in every timeout period. This takes care of the worst 187 * case where a starved transaction starts during an interval that 188 * meets the requirement "don't send an ordered tag" test so it takes 189 * us two intervals to determine that a tag must be sent. 190 */ 191#ifndef ADA_ORDEREDTAG_INTERVAL 192#define ADA_ORDEREDTAG_INTERVAL 4 193#endif 194 195static struct periph_driver adadriver = 196{ 197 adainit, "ada", 198 TAILQ_HEAD_INITIALIZER(adadriver.units), /* generation */ 0 199}; 200 201PERIPHDRIVER_DECLARE(ada, adadriver); 202 203MALLOC_DEFINE(M_ATADA, "ata_da", "ata_da buffers"); 204 205static int 206adaopen(struct disk *dp) 207{ 208 struct cam_periph *periph; 209 struct ada_softc *softc; 210 int unit; 211 int error; 212 213 periph = (struct cam_periph *)dp->d_drv1; 214 if (periph == NULL) { 215 return (ENXIO); 216 } 217 218 if (cam_periph_acquire(periph) != CAM_REQ_CMP) { 219 return(ENXIO); 220 } 221 222 cam_periph_lock(periph); 223 if ((error = cam_periph_hold(periph, PRIBIO|PCATCH)) != 0) { 224 cam_periph_unlock(periph); 225 cam_periph_release(periph); 226 return (error); 227 } 228 229 unit = periph->unit_number; 230 softc = (struct ada_softc *)periph->softc; 231 softc->flags |= ADA_FLAG_OPEN; 232 233 CAM_DEBUG(periph->path, CAM_DEBUG_TRACE, 234 ("adaopen: disk=%s%d (unit %d)\n", dp->d_name, dp->d_unit, 235 unit)); 236 237 if ((softc->flags & ADA_FLAG_PACK_INVALID) != 0) { 238 /* Invalidate our pack information. */ 239 softc->flags &= ~ADA_FLAG_PACK_INVALID; 240 } 241 242 cam_periph_unhold(periph); 243 cam_periph_unlock(periph); 244 return (0); 245} 246 247static int 248adaclose(struct disk *dp) 249{ 250 struct cam_periph *periph; 251 struct ada_softc *softc; 252 union ccb *ccb; 253 int error; 254 255 periph = (struct cam_periph *)dp->d_drv1; 256 if (periph == NULL) 257 return (ENXIO); 258 259 cam_periph_lock(periph); 260 if ((error = cam_periph_hold(periph, PRIBIO)) != 0) { 261 cam_periph_unlock(periph); 262 cam_periph_release(periph); 263 return (error); 264 } 265 266 softc = (struct ada_softc *)periph->softc; 267 /* We only sync the cache if the drive is capable of it. */ 268 if (softc->flags & ADA_FLAG_CAN_FLUSHCACHE) { 269 270 ccb = cam_periph_getccb(periph, CAM_PRIORITY_NORMAL); 271 cam_fill_ataio(&ccb->ataio, 272 1, 273 adadone, 274 CAM_DIR_NONE, 275 0, 276 NULL, 277 0, 278 ada_default_timeout*1000); 279 280 if (softc->flags & ADA_FLAG_CAN_48BIT) 281 ata_48bit_cmd(&ccb->ataio, ATA_FLUSHCACHE48, 0, 0, 0); 282 else 283 ata_28bit_cmd(&ccb->ataio, ATA_FLUSHCACHE, 0, 0, 0); 284 cam_periph_runccb(ccb, /*error_routine*/NULL, /*cam_flags*/0, 285 /*sense_flags*/0, softc->disk->d_devstat); 286 287 if ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) 288 xpt_print(periph->path, "Synchronize cache failed\n"); 289 290 if ((ccb->ccb_h.status & CAM_DEV_QFRZN) != 0) 291 cam_release_devq(ccb->ccb_h.path, 292 /*relsim_flags*/0, 293 /*reduction*/0, 294 /*timeout*/0, 295 /*getcount_only*/0); 296 xpt_release_ccb(ccb); 297 } 298 299 softc->flags &= ~ADA_FLAG_OPEN; 300 cam_periph_unhold(periph); 301 cam_periph_unlock(periph); 302 cam_periph_release(periph); 303 return (0); 304} 305 306/* 307 * Actually translate the requested transfer into one the physical driver 308 * can understand. The transfer is described by a buf and will include 309 * only one physical transfer. 310 */ 311static void 312adastrategy(struct bio *bp) 313{ 314 struct cam_periph *periph; 315 struct ada_softc *softc; 316 317 periph = (struct cam_periph *)bp->bio_disk->d_drv1; 318 if (periph == NULL) { 319 biofinish(bp, NULL, ENXIO); 320 return; 321 } 322 softc = (struct ada_softc *)periph->softc; 323 324 cam_periph_lock(periph); 325 326 /* 327 * If the device has been made invalid, error out 328 */ 329 if ((softc->flags & ADA_FLAG_PACK_INVALID)) { 330 cam_periph_unlock(periph); 331 biofinish(bp, NULL, ENXIO); 332 return; 333 } 334 335 /* 336 * Place it in the queue of disk activities for this disk 337 */ 338 bioq_disksort(&softc->bio_queue, bp); 339 340 /* 341 * Schedule ourselves for performing the work. 342 */ 343 xpt_schedule(periph, CAM_PRIORITY_NORMAL); 344 cam_periph_unlock(periph); 345 346 return; 347} 348 349static int 350adadump(void *arg, void *virtual, vm_offset_t physical, off_t offset, size_t length) 351{ 352 struct cam_periph *periph; 353 struct ada_softc *softc; 354 u_int secsize; 355 union ccb ccb; 356 struct disk *dp; 357 uint64_t lba; 358 uint16_t count; 359 360 dp = arg; 361 periph = dp->d_drv1; 362 if (periph == NULL) 363 return (ENXIO); 364 softc = (struct ada_softc *)periph->softc; 365 cam_periph_lock(periph); 366 secsize = softc->params.secsize; 367 lba = offset / secsize; 368 count = length / secsize; 369 370 if ((softc->flags & ADA_FLAG_PACK_INVALID) != 0) { 371 cam_periph_unlock(periph); 372 return (ENXIO); 373 } 374 375 if (length > 0) { 376 periph->flags |= CAM_PERIPH_POLLED; 377 xpt_setup_ccb(&ccb.ccb_h, periph->path, CAM_PRIORITY_NORMAL); 378 ccb.ccb_h.ccb_state = ADA_CCB_DUMP; 379 cam_fill_ataio(&ccb.ataio, 380 0, 381 adadone, 382 CAM_DIR_OUT, 383 0, 384 (u_int8_t *) virtual, 385 length, 386 ada_default_timeout*1000); 387 if ((softc->flags & ADA_FLAG_CAN_48BIT) && 388 (lba + count >= ATA_MAX_28BIT_LBA || 389 count >= 256)) { 390 ata_48bit_cmd(&ccb.ataio, ATA_WRITE_DMA48, 391 0, lba, count); 392 } else { 393 ata_28bit_cmd(&ccb.ataio, ATA_WRITE_DMA, 394 0, lba, count); 395 } 396 xpt_polled_action(&ccb); 397 398 if ((ccb.ataio.ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) { 399 printf("Aborting dump due to I/O error.\n"); 400 cam_periph_unlock(periph); 401 return(EIO); 402 } 403 cam_periph_unlock(periph); 404 return(0); 405 } 406 407 if (softc->flags & ADA_FLAG_CAN_FLUSHCACHE) { 408 xpt_setup_ccb(&ccb.ccb_h, periph->path, CAM_PRIORITY_NORMAL); 409 410 ccb.ccb_h.ccb_state = ADA_CCB_DUMP; 411 cam_fill_ataio(&ccb.ataio, 412 1, 413 adadone, 414 CAM_DIR_NONE, 415 0, 416 NULL, 417 0, 418 ada_default_timeout*1000); 419 420 if (softc->flags & ADA_FLAG_CAN_48BIT) 421 ata_48bit_cmd(&ccb.ataio, ATA_FLUSHCACHE48, 0, 0, 0); 422 else 423 ata_28bit_cmd(&ccb.ataio, ATA_FLUSHCACHE, 0, 0, 0); 424 xpt_polled_action(&ccb); 425 426 if ((ccb.ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) 427 xpt_print(periph->path, "Synchronize cache failed\n"); 428 429 if ((ccb.ccb_h.status & CAM_DEV_QFRZN) != 0) 430 cam_release_devq(ccb.ccb_h.path, 431 /*relsim_flags*/0, 432 /*reduction*/0, 433 /*timeout*/0, 434 /*getcount_only*/0); 435 } 436 periph->flags &= ~CAM_PERIPH_POLLED; 437 cam_periph_unlock(periph); 438 return (0); 439} 440 441static void 442adainit(void) 443{ 444 cam_status status; 445 446 /* 447 * Install a global async callback. This callback will 448 * receive async callbacks like "new device found". 449 */ 450 status = xpt_register_async(AC_FOUND_DEVICE, adaasync, NULL, NULL); 451 452 if (status != CAM_REQ_CMP) { 453 printf("ada: Failed to attach master async callback " 454 "due to status 0x%x!\n", status); 455 } else if (ada_send_ordered) { 456 457 /* Register our shutdown event handler */ 458 if ((EVENTHANDLER_REGISTER(shutdown_post_sync, adashutdown, 459 NULL, SHUTDOWN_PRI_DEFAULT)) == NULL) 460 printf("adainit: shutdown event registration failed!\n"); 461 } 462} 463 464static void 465adaoninvalidate(struct cam_periph *periph) 466{ 467 struct ada_softc *softc; 468 469 softc = (struct ada_softc *)periph->softc; 470 471 /* 472 * De-register any async callbacks. 473 */ 474 xpt_register_async(0, adaasync, periph, periph->path); 475 476 softc->flags |= ADA_FLAG_PACK_INVALID; 477 478 /* 479 * Return all queued I/O with ENXIO. 480 * XXX Handle any transactions queued to the card 481 * with XPT_ABORT_CCB. 482 */ 483 bioq_flush(&softc->bio_queue, NULL, ENXIO); 484 485 disk_gone(softc->disk); 486 xpt_print(periph->path, "lost device\n"); 487} 488 489static void 490adacleanup(struct cam_periph *periph) 491{ 492 struct ada_softc *softc; 493 494 softc = (struct ada_softc *)periph->softc; 495 496 xpt_print(periph->path, "removing device entry\n"); 497 cam_periph_unlock(periph); 498 499 /* 500 * If we can't free the sysctl tree, oh well... 501 */ 502 if ((softc->flags & ADA_FLAG_SCTX_INIT) != 0 503 && sysctl_ctx_free(&softc->sysctl_ctx) != 0) { 504 xpt_print(periph->path, "can't remove sysctl context\n"); 505 } 506 507 disk_destroy(softc->disk); 508 callout_drain(&softc->sendordered_c); 509 free(softc, M_DEVBUF); 510 cam_periph_lock(periph); 511} 512 513static void 514adaasync(void *callback_arg, u_int32_t code, 515 struct cam_path *path, void *arg) 516{ 517 struct cam_periph *periph; 518 519 periph = (struct cam_periph *)callback_arg; 520 switch (code) { 521 case AC_FOUND_DEVICE: 522 { 523 struct ccb_getdev *cgd; 524 cam_status status; 525 526 cgd = (struct ccb_getdev *)arg; 527 if (cgd == NULL) 528 break; 529 530 if (cgd->protocol != PROTO_ATA) 531 break; 532 533 /* 534 * Allocate a peripheral instance for 535 * this device and start the probe 536 * process. 537 */ 538 status = cam_periph_alloc(adaregister, adaoninvalidate, 539 adacleanup, adastart, 540 "ada", CAM_PERIPH_BIO, 541 cgd->ccb_h.path, adaasync, 542 AC_FOUND_DEVICE, cgd); 543 544 if (status != CAM_REQ_CMP 545 && status != CAM_REQ_INPROG) 546 printf("adaasync: Unable to attach to new device " 547 "due to status 0x%x\n", status); 548 break; 549 } 550 default: 551 cam_periph_async(periph, code, path, arg); 552 break; 553 } 554} 555 556static void 557adasysctlinit(void *context, int pending) 558{ 559 struct cam_periph *periph; 560 struct ada_softc *softc; 561 char tmpstr[80], tmpstr2[80]; 562 563 periph = (struct cam_periph *)context; 564 if (cam_periph_acquire(periph) != CAM_REQ_CMP) 565 return; 566 567 softc = (struct ada_softc *)periph->softc; 568 snprintf(tmpstr, sizeof(tmpstr), "CAM ADA unit %d", periph->unit_number); 569 snprintf(tmpstr2, sizeof(tmpstr2), "%d", periph->unit_number); 570 571 sysctl_ctx_init(&softc->sysctl_ctx); 572 softc->flags |= ADA_FLAG_SCTX_INIT; 573 softc->sysctl_tree = SYSCTL_ADD_NODE(&softc->sysctl_ctx, 574 SYSCTL_STATIC_CHILDREN(_kern_cam_ada), OID_AUTO, tmpstr2, 575 CTLFLAG_RD, 0, tmpstr); 576 if (softc->sysctl_tree == NULL) { 577 printf("adasysctlinit: unable to allocate sysctl tree\n"); 578 cam_periph_release(periph); 579 return; 580 } 581 582 cam_periph_release(periph); 583} 584 585static cam_status 586adaregister(struct cam_periph *periph, void *arg) 587{ 588 struct ada_softc *softc; 589 struct ccb_pathinq cpi; 590 struct ccb_getdev *cgd; 591 char announce_buf[80]; 592 struct disk_params *dp; 593 caddr_t match; 594 u_int maxio; 595 596 cgd = (struct ccb_getdev *)arg; 597 if (periph == NULL) { 598 printf("adaregister: periph was NULL!!\n"); 599 return(CAM_REQ_CMP_ERR); 600 } 601 602 if (cgd == NULL) { 603 printf("adaregister: no getdev CCB, can't register device\n"); 604 return(CAM_REQ_CMP_ERR); 605 } 606 607 softc = (struct ada_softc *)malloc(sizeof(*softc), M_DEVBUF, 608 M_NOWAIT|M_ZERO); 609 610 if (softc == NULL) { 611 printf("adaregister: Unable to probe new device. " 612 "Unable to allocate softc\n"); 613 return(CAM_REQ_CMP_ERR); 614 } 615 616 LIST_INIT(&softc->pending_ccbs); 617 bioq_init(&softc->bio_queue); 618 619 if (cgd->ident_data.capabilities1 & ATA_SUPPORT_DMA) 620 softc->flags |= ADA_FLAG_CAN_DMA; 621 if (cgd->ident_data.support.command2 & ATA_SUPPORT_ADDRESS48) 622 softc->flags |= ADA_FLAG_CAN_48BIT; 623 if (cgd->ident_data.support.command2 & ATA_SUPPORT_FLUSHCACHE) 624 softc->flags |= ADA_FLAG_CAN_FLUSHCACHE; 625 if (cgd->ident_data.satacapabilities & ATA_SUPPORT_NCQ && 626 cgd->ident_data.queue >= 31) 627 softc->flags |= ADA_FLAG_CAN_NCQ; 628 softc->state = ADA_STATE_NORMAL; 629 630 periph->softc = softc; 631 632 /* 633 * See if this device has any quirks. 634 */ 635// match = cam_quirkmatch((caddr_t)&cgd->inq_data, 636// (caddr_t)ada_quirk_table, 637// sizeof(ada_quirk_table)/sizeof(*ada_quirk_table), 638// sizeof(*ada_quirk_table), scsi_inquiry_match); 639 match = NULL; 640 641 if (match != NULL) 642 softc->quirks = ((struct ada_quirk_entry *)match)->quirks; 643 else 644 softc->quirks = ADA_Q_NONE; 645 646 /* Check if the SIM does not want queued commands */ 647 bzero(&cpi, sizeof(cpi)); 648 xpt_setup_ccb(&cpi.ccb_h, periph->path, CAM_PRIORITY_NORMAL); 649 cpi.ccb_h.func_code = XPT_PATH_INQ; 650 xpt_action((union ccb *)&cpi); 651 if (cpi.ccb_h.status != CAM_REQ_CMP || 652 (cpi.hba_inquiry & PI_TAG_ABLE) == 0) 653 softc->flags &= ~ADA_FLAG_CAN_NCQ; 654 655 TASK_INIT(&softc->sysctl_task, 0, adasysctlinit, periph); 656 657 /* 658 * Register this media as a disk 659 */ 660 mtx_unlock(periph->sim->mtx); 661 softc->disk = disk_alloc(); 662 softc->disk->d_open = adaopen; 663 softc->disk->d_close = adaclose; 664 softc->disk->d_strategy = adastrategy; 665 softc->disk->d_dump = adadump; 666 softc->disk->d_name = "ada"; 667 softc->disk->d_drv1 = periph; 668 maxio = cpi.maxio; /* Honor max I/O size of SIM */ 669 if (maxio == 0) 670 maxio = DFLTPHYS; /* traditional default */ 671 else if (maxio > MAXPHYS) 672 maxio = MAXPHYS; /* for safety */ 673 if (cgd->ident_data.support.command2 & ATA_SUPPORT_ADDRESS48) 674 maxio = min(maxio, 65536 * 512); 675 else /* 28bit ATA command limit */ 676 maxio = min(maxio, 256 * 512); 677 softc->disk->d_maxsize = maxio; 678 softc->disk->d_unit = periph->unit_number; 679 softc->disk->d_flags = 0; 680 if (softc->flags & ADA_FLAG_CAN_FLUSHCACHE) 681 softc->disk->d_flags |= DISKFLAG_CANFLUSHCACHE; 682 strlcpy(softc->disk->d_ident, cgd->serial_num, 683 MIN(sizeof(softc->disk->d_ident), cgd->serial_num_len + 1)); 684 685 adasetgeom(periph, cgd); 686 softc->disk->d_sectorsize = softc->params.secsize; 687 softc->disk->d_mediasize = softc->params.secsize * (off_t)softc->params.sectors; 688 /* XXX: these are not actually "firmware" values, so they may be wrong */ 689 softc->disk->d_fwsectors = softc->params.secs_per_track; 690 softc->disk->d_fwheads = softc->params.heads; 691 692 disk_create(softc->disk, DISK_VERSION); 693 mtx_lock(periph->sim->mtx); 694 695 dp = &softc->params; 696 snprintf(announce_buf, sizeof(announce_buf), 697 "%juMB (%ju %u byte sectors: %dH %dS/T %dC)", 698 (uintmax_t)(((uintmax_t)dp->secsize * 699 dp->sectors) / (1024*1024)), 700 (uintmax_t)dp->sectors, 701 dp->secsize, dp->heads, 702 dp->secs_per_track, dp->cylinders); 703 xpt_announce_periph(periph, announce_buf); 704 if (softc->flags & ADA_FLAG_CAN_NCQ) { 705 printf("%s%d: Native Command Queueing enabled\n", 706 periph->periph_name, periph->unit_number); 707 } 708 709 /* 710 * Add async callbacks for bus reset and 711 * bus device reset calls. I don't bother 712 * checking if this fails as, in most cases, 713 * the system will function just fine without 714 * them and the only alternative would be to 715 * not attach the device on failure. 716 */ 717 xpt_register_async(AC_LOST_DEVICE, 718 adaasync, periph, periph->path); 719 720 /* 721 * Schedule a periodic event to occasionally send an 722 * ordered tag to a device. 723 */ 724 callout_init_mtx(&softc->sendordered_c, periph->sim->mtx, 0); 725 callout_reset(&softc->sendordered_c, 726 (ADA_DEFAULT_TIMEOUT * hz) / ADA_ORDEREDTAG_INTERVAL, 727 adasendorderedtag, softc); 728 729 return(CAM_REQ_CMP); 730} 731 732static void 733adastart(struct cam_periph *periph, union ccb *start_ccb) 734{ 735 struct ada_softc *softc = (struct ada_softc *)periph->softc; 736 struct ccb_ataio *ataio = &start_ccb->ataio; 737 738 switch (softc->state) { 739 case ADA_STATE_NORMAL: 740 { 741 /* Pull a buffer from the queue and get going on it */ 742 struct bio *bp; 743 744 /* 745 * See if there is a buf with work for us to do.. 746 */ 747 bp = bioq_first(&softc->bio_queue); 748 if (periph->immediate_priority <= periph->pinfo.priority) { 749 CAM_DEBUG_PRINT(CAM_DEBUG_SUBTRACE, 750 ("queuing for immediate ccb\n")); 751 start_ccb->ccb_h.ccb_state = ADA_CCB_WAITING; 752 SLIST_INSERT_HEAD(&periph->ccb_list, &start_ccb->ccb_h, 753 periph_links.sle); 754 periph->immediate_priority = CAM_PRIORITY_NONE; 755 wakeup(&periph->ccb_list); 756 } else if (bp == NULL) { 757 xpt_release_ccb(start_ccb); 758 } else { 759 u_int8_t tag_code; 760 761 bioq_remove(&softc->bio_queue, bp); 762 763 if ((softc->flags & ADA_FLAG_NEED_OTAG) != 0) { 764 softc->flags &= ~ADA_FLAG_NEED_OTAG; 765 softc->ordered_tag_count++; 766 tag_code = 0; 767 } else { 768 tag_code = 1; 769 } 770 switch (bp->bio_cmd) { 771 case BIO_READ: 772 case BIO_WRITE: 773 { 774 uint64_t lba = bp->bio_pblkno; 775 uint16_t count = bp->bio_bcount / softc->params.secsize; 776 777 cam_fill_ataio(ataio, 778 ada_retry_count, 779 adadone, 780 bp->bio_cmd == BIO_READ ? 781 CAM_DIR_IN : CAM_DIR_OUT, 782 tag_code, 783 bp->bio_data, 784 bp->bio_bcount, 785 ada_default_timeout*1000); 786 787 if ((softc->flags & ADA_FLAG_CAN_NCQ) && tag_code) { 788 if (bp->bio_cmd == BIO_READ) { 789 ata_ncq_cmd(ataio, ATA_READ_FPDMA_QUEUED, 790 lba, count); 791 } else { 792 ata_ncq_cmd(ataio, ATA_WRITE_FPDMA_QUEUED, 793 lba, count); 794 } 795 } else if ((softc->flags & ADA_FLAG_CAN_48BIT) && 796 (lba + count >= ATA_MAX_28BIT_LBA || 797 count > 256)) { 798 if (softc->flags & ADA_FLAG_CAN_DMA) { 799 if (bp->bio_cmd == BIO_READ) { 800 ata_48bit_cmd(ataio, ATA_READ_DMA48, 801 0, lba, count); 802 } else { 803 ata_48bit_cmd(ataio, ATA_WRITE_DMA48, 804 0, lba, count); 805 } 806 } else { 807 if (bp->bio_cmd == BIO_READ) { 808 ata_48bit_cmd(ataio, ATA_READ_MUL48, 809 0, lba, count); 810 } else { 811 ata_48bit_cmd(ataio, ATA_WRITE_MUL48, 812 0, lba, count); 813 } 814 } 815 } else { 816 if (count == 256) 817 count = 0; 818 if (softc->flags & ADA_FLAG_CAN_DMA) { 819 if (bp->bio_cmd == BIO_READ) { 820 ata_28bit_cmd(ataio, ATA_READ_DMA, 821 0, lba, count); 822 } else { 823 ata_28bit_cmd(ataio, ATA_WRITE_DMA, 824 0, lba, count); 825 } 826 } else { 827 if (bp->bio_cmd == BIO_READ) { 828 ata_28bit_cmd(ataio, ATA_READ_MUL, 829 0, lba, count); 830 } else { 831 ata_28bit_cmd(ataio, ATA_WRITE_MUL, 832 0, lba, count); 833 } 834 } 835 } 836 } 837 break; 838 case BIO_FLUSH: 839 cam_fill_ataio(ataio, 840 1, 841 adadone, 842 CAM_DIR_NONE, 843 0, 844 NULL, 845 0, 846 ada_default_timeout*1000); 847 848 if (softc->flags & ADA_FLAG_CAN_48BIT) 849 ata_48bit_cmd(ataio, ATA_FLUSHCACHE48, 0, 0, 0); 850 else 851 ata_28bit_cmd(ataio, ATA_FLUSHCACHE, 0, 0, 0); 852 break; 853 } 854 start_ccb->ccb_h.ccb_state = ADA_CCB_BUFFER_IO; 855 856 /* 857 * Block out any asyncronous callbacks 858 * while we touch the pending ccb list. 859 */ 860 LIST_INSERT_HEAD(&softc->pending_ccbs, 861 &start_ccb->ccb_h, periph_links.le); 862 softc->outstanding_cmds++; 863 864 start_ccb->ccb_h.ccb_bp = bp; 865 bp = bioq_first(&softc->bio_queue); 866 867 xpt_action(start_ccb); 868 } 869 870 if (bp != NULL) { 871 /* Have more work to do, so ensure we stay scheduled */ 872 xpt_schedule(periph, CAM_PRIORITY_NORMAL); 873 } 874 break; 875 } 876 } 877} 878 879static void 880adadone(struct cam_periph *periph, union ccb *done_ccb) 881{ 882 struct ada_softc *softc; 883 struct ccb_ataio *ataio; 884 885 softc = (struct ada_softc *)periph->softc; 886 ataio = &done_ccb->ataio; 887 switch (ataio->ccb_h.ccb_state & ADA_CCB_TYPE_MASK) { 888 case ADA_CCB_BUFFER_IO: 889 { 890 struct bio *bp; 891 892 bp = (struct bio *)done_ccb->ccb_h.ccb_bp; 893 if ((done_ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) { 894 int error; 895 896 error = adaerror(done_ccb, 0, 0); 897 if (error == ERESTART) { 898 /* A retry was scheduled, so just return. */ 899 return; 900 } 901 if (error != 0) { 902 if (error == ENXIO) { 903 /* 904 * Catastrophic error. Mark our pack as 905 * invalid. 906 */ 907 /* 908 * XXX See if this is really a media 909 * XXX change first? 910 */ 911 xpt_print(periph->path, 912 "Invalidating pack\n"); 913 softc->flags |= ADA_FLAG_PACK_INVALID; 914 } 915 916 /* 917 * return all queued I/O with EIO, so that 918 * the client can retry these I/Os in the 919 * proper order should it attempt to recover. 920 */ 921 bioq_flush(&softc->bio_queue, NULL, EIO); 922 bp->bio_error = error; 923 bp->bio_resid = bp->bio_bcount; 924 bp->bio_flags |= BIO_ERROR; 925 } else { 926 bp->bio_resid = ataio->resid; 927 bp->bio_error = 0; 928 if (bp->bio_resid != 0) 929 bp->bio_flags |= BIO_ERROR; 930 } 931 if ((done_ccb->ccb_h.status & CAM_DEV_QFRZN) != 0) 932 cam_release_devq(done_ccb->ccb_h.path, 933 /*relsim_flags*/0, 934 /*reduction*/0, 935 /*timeout*/0, 936 /*getcount_only*/0); 937 } else { 938 if ((done_ccb->ccb_h.status & CAM_DEV_QFRZN) != 0) 939 panic("REQ_CMP with QFRZN"); 940 bp->bio_resid = ataio->resid; 941 if (ataio->resid > 0) 942 bp->bio_flags |= BIO_ERROR; 943 } 944 945 /* 946 * Block out any asyncronous callbacks 947 * while we touch the pending ccb list. 948 */ 949 LIST_REMOVE(&done_ccb->ccb_h, periph_links.le); 950 softc->outstanding_cmds--; 951 if (softc->outstanding_cmds == 0) 952 softc->flags |= ADA_FLAG_WENT_IDLE; 953 954 biodone(bp); 955 break; 956 } 957 case ADA_CCB_WAITING: 958 { 959 /* Caller will release the CCB */ 960 wakeup(&done_ccb->ccb_h.cbfcnp); 961 return; 962 } 963 case ADA_CCB_DUMP: 964 /* No-op. We're polling */ 965 return; 966 default: 967 break; 968 } 969 xpt_release_ccb(done_ccb); 970} 971 972static int 973adaerror(union ccb *ccb, u_int32_t cam_flags, u_int32_t sense_flags) 974{ 975 struct ada_softc *softc; 976 struct cam_periph *periph; 977 978 periph = xpt_path_periph(ccb->ccb_h.path); 979 softc = (struct ada_softc *)periph->softc; 980 981 return(cam_periph_error(ccb, cam_flags, sense_flags, 982 &softc->saved_ccb)); 983} 984 985static void 986adasetgeom(struct cam_periph *periph, struct ccb_getdev *cgd) 987{ 988 struct ada_softc *softc = (struct ada_softc *)periph->softc; 989 struct disk_params *dp = &softc->params; 990 u_int64_t lbasize48; 991 u_int32_t lbasize; 992 993 dp->secsize = 512; 994 if ((cgd->ident_data.atavalid & ATA_FLAG_54_58) && 995 cgd->ident_data.current_heads && cgd->ident_data.current_sectors) { 996 dp->heads = cgd->ident_data.current_heads; 997 dp->secs_per_track = cgd->ident_data.current_sectors; 998 dp->cylinders = cgd->ident_data.cylinders; 999 dp->sectors = (u_int32_t)cgd->ident_data.current_size_1 | 1000 ((u_int32_t)cgd->ident_data.current_size_2 << 16); 1001 } else { 1002 dp->heads = cgd->ident_data.heads; 1003 dp->secs_per_track = cgd->ident_data.sectors; 1004 dp->cylinders = cgd->ident_data.cylinders; 1005 dp->sectors = cgd->ident_data.cylinders * dp->heads * dp->secs_per_track; 1006 } 1007 lbasize = (u_int32_t)cgd->ident_data.lba_size_1 | 1008 ((u_int32_t)cgd->ident_data.lba_size_2 << 16); 1009 1010 /* use the 28bit LBA size if valid or bigger than the CHS mapping */ 1011 if (cgd->ident_data.cylinders == 16383 || dp->sectors < lbasize) 1012 dp->sectors = lbasize; 1013 1014 /* use the 48bit LBA size if valid */ 1015 lbasize48 = ((u_int64_t)cgd->ident_data.lba_size48_1) | 1016 ((u_int64_t)cgd->ident_data.lba_size48_2 << 16) | 1017 ((u_int64_t)cgd->ident_data.lba_size48_3 << 32) | 1018 ((u_int64_t)cgd->ident_data.lba_size48_4 << 48); 1019 if ((cgd->ident_data.support.command2 & ATA_SUPPORT_ADDRESS48) && 1020 lbasize48 > ATA_MAX_28BIT_LBA) 1021 dp->sectors = lbasize48; 1022} 1023 1024static void 1025adasendorderedtag(void *arg) 1026{ 1027 struct ada_softc *softc = arg; 1028 1029 if (ada_send_ordered) { 1030 if ((softc->ordered_tag_count == 0) 1031 && ((softc->flags & ADA_FLAG_WENT_IDLE) == 0)) { 1032 softc->flags |= ADA_FLAG_NEED_OTAG; 1033 } 1034 if (softc->outstanding_cmds > 0) 1035 softc->flags &= ~ADA_FLAG_WENT_IDLE; 1036 1037 softc->ordered_tag_count = 0; 1038 } 1039 /* Queue us up again */ 1040 callout_reset(&softc->sendordered_c, 1041 (ADA_DEFAULT_TIMEOUT * hz) / ADA_ORDEREDTAG_INTERVAL, 1042 adasendorderedtag, softc); 1043} 1044 1045/* 1046 * Step through all ADA peripheral drivers, and if the device is still open, 1047 * sync the disk cache to physical media. 1048 */ 1049static void 1050adashutdown(void * arg, int howto) 1051{ 1052 struct cam_periph *periph; 1053 struct ada_softc *softc; 1054 1055 TAILQ_FOREACH(periph, &adadriver.units, unit_links) { 1056 union ccb ccb; 1057 1058 cam_periph_lock(periph); 1059 softc = (struct ada_softc *)periph->softc; 1060 /* 1061 * We only sync the cache if the drive is still open, and 1062 * if the drive is capable of it.. 1063 */ 1064 if (((softc->flags & ADA_FLAG_OPEN) == 0) || 1065 (softc->flags & ADA_FLAG_CAN_FLUSHCACHE) == 0) { 1066 cam_periph_unlock(periph); 1067 continue; 1068 } 1069 1070 xpt_setup_ccb(&ccb.ccb_h, periph->path, CAM_PRIORITY_NORMAL); 1071 1072 ccb.ccb_h.ccb_state = ADA_CCB_DUMP; 1073 cam_fill_ataio(&ccb.ataio, 1074 1, 1075 adadone, 1076 CAM_DIR_NONE, 1077 0, 1078 NULL, 1079 0, 1080 ada_default_timeout*1000); 1081 1082 if (softc->flags & ADA_FLAG_CAN_48BIT) 1083 ata_48bit_cmd(&ccb.ataio, ATA_FLUSHCACHE48, 0, 0, 0); 1084 else 1085 ata_28bit_cmd(&ccb.ataio, ATA_FLUSHCACHE, 0, 0, 0); 1086 xpt_polled_action(&ccb); 1087 1088 if ((ccb.ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) 1089 xpt_print(periph->path, "Synchronize cache failed\n"); 1090 1091 if ((ccb.ccb_h.status & CAM_DEV_QFRZN) != 0) 1092 cam_release_devq(ccb.ccb_h.path, 1093 /*relsim_flags*/0, 1094 /*reduction*/0, 1095 /*timeout*/0, 1096 /*getcount_only*/0); 1097 cam_periph_unlock(periph); 1098 } 1099} 1100 1101#endif /* _KERNEL */ 1102