1 /* 2 * Implementation of SCSI Direct Access Peripheral driver for CAM. 3 * 4 * Copyright (c) 1997 Justin T. Gibbs. 5 * All rights reserved. 6 * 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted provided that the following conditions 9 * are met: 10 * 1. Redistributions of source code must retain the above copyright 11 * notice, this list of conditions, and the following disclaimer, 12 * without modification, immediately at the beginning of the file. 13 * 2. The name of the author may not be used to endorse or promote products 14 * derived from this software without specific prior written permission. 15 * 16 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 17 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 18 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 19 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR 20 * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 21 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 22 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 23 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 24 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 25 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 26 * SUCH DAMAGE. 27 * 28 * $Id: scsi_da.c,v 1.26 1999/05/30 16:51:02 phk Exp $ 29 */ 30 31 #include "opt_hw_wdog.h" 32 33 #include <sys/param.h> 34 #include <sys/systm.h> 35 #include <sys/kernel.h> 36 #include <sys/buf.h> 37 #include <sys/devicestat.h> 38 #include <sys/dkbad.h> 39 #include <sys/disklabel.h> 40 #include <sys/diskslice.h> 41 #include <sys/malloc.h> 42 #include <sys/conf.h> 43 44 #include <machine/cons.h> 45 #include <machine/md_var.h> 46 47 #include <vm/vm.h> 48 #include <vm/vm_prot.h> 49 #include <vm/pmap.h> 50 51 #include <cam/cam.h> 52 #include <cam/cam_ccb.h> 53 #include <cam/cam_extend.h> 54 #include <cam/cam_periph.h> 55 #include <cam/cam_xpt_periph.h> 56 57 #include <cam/scsi/scsi_message.h> 58 59 typedef enum { 60 DA_STATE_PROBE, 61 DA_STATE_NORMAL 62 } da_state; 63 64 typedef enum { 65 DA_FLAG_PACK_INVALID = 0x001, 66 DA_FLAG_NEW_PACK = 0x002, 67 DA_FLAG_PACK_LOCKED = 0x004, 68 DA_FLAG_PACK_REMOVABLE = 0x008, 69 DA_FLAG_TAGGED_QUEUING = 0x010, 70 DA_FLAG_NEED_OTAG = 0x020, 71 DA_FLAG_WENT_IDLE = 0x040, 72 DA_FLAG_RETRY_UA = 0x080, 73 DA_FLAG_OPEN = 0x100 74 } da_flags; 75 76 typedef enum { 77 DA_Q_NONE = 0x00, 78 DA_Q_NO_SYNC_CACHE = 0x01, 79 DA_Q_NO_6_BYTE = 0x02 80 } da_quirks; 81 82 typedef enum { 83 DA_CCB_PROBE = 0x01, 84 DA_CCB_BUFFER_IO = 0x02, 85 DA_CCB_WAITING = 0x03, 86 DA_CCB_DUMP = 0x04, 87 DA_CCB_TYPE_MASK = 0x0F, 88 DA_CCB_RETRY_UA = 0x10 89 } da_ccb_state; 90 91 /* Offsets into our private area for storing information */ 92 #define ccb_state ppriv_field0 93 #define ccb_bp ppriv_ptr1 94 95 struct disk_params { 96 u_int8_t heads; 97 u_int16_t cylinders; 98 u_int8_t secs_per_track; 99 u_int32_t secsize; /* Number of bytes/sector */ 100 u_int32_t sectors; /* total number sectors */ 101 }; 102 103 struct da_softc { 104 struct buf_queue_head buf_queue; 105 struct devstat device_stats; 106 SLIST_ENTRY(da_softc) links; 107 LIST_HEAD(, ccb_hdr) pending_ccbs; 108 da_state state; 109 da_flags flags; 110 da_quirks quirks; 111 int minimum_cmd_size; 112 int ordered_tag_count; 113 struct disk_params params; 114 struct diskslices *dk_slices; /* virtual drives */ 115 union ccb saved_ccb; 116 }; 117 118 struct da_quirk_entry { 119 struct scsi_inquiry_pattern inq_pat; 120 da_quirks quirks; 121 }; 122 123 static struct da_quirk_entry da_quirk_table[] = 124 { 125 { 126 /* 127 * This particular Fujitsu drive doesn't like the 128 * synchronize cache command. 129 * Reported by: Tom Jackson <toj@gorilla.net> 130 */ 131 {T_DIRECT, SIP_MEDIA_FIXED, "FUJITSU", "M2954*", "*"}, 132 /*quirks*/ DA_Q_NO_SYNC_CACHE 133 134 }, 135 { 136 /* 137 * This drive doesn't like the synchronize cache command 138 * either. Reported by: Matthew Jacob <mjacob@feral.com> 139 * in NetBSD PR kern/6027, August 24, 1998. 140 */ 141 {T_DIRECT, SIP_MEDIA_FIXED, "MICROP", "2217*", "*"}, 142 /*quirks*/ DA_Q_NO_SYNC_CACHE 143 }, 144 { 145 /* 146 * This drive doesn't like the synchronize cache command 147 * either. Reported by: Hellmuth Michaelis (hm@kts.org) 148 * (PR 8882). 149 */ 150 {T_DIRECT, SIP_MEDIA_FIXED, "MICROP", "2112*", "*"}, 151 /*quirks*/ DA_Q_NO_SYNC_CACHE 152 }, 153 { 154 /* 155 * Doesn't like the synchronize cache command. 156 * Reported by: Blaz Zupan <blaz@gold.amis.net> 157 */ 158 {T_DIRECT, SIP_MEDIA_FIXED, "NEC", "D3847*", "*"}, 159 /*quirks*/ DA_Q_NO_SYNC_CACHE 160 }, 161 { 162 /* 163 * Doesn't work correctly with 6 byte reads/writes. 164 * Returns illegal request, and points to byte 9 of the 165 * 6-byte CDB. 166 * Reported by: Adam McDougall <bsdx@spawnet.com> 167 */ 168 {T_DIRECT, SIP_MEDIA_FIXED, "QUANTUM", "VIKING 4*", "*"}, 169 /*quirks*/ DA_Q_NO_6_BYTE 170 }, 171 { 172 /* 173 * See above. 174 */ 175 {T_DIRECT, SIP_MEDIA_FIXED, "QUANTUM", "VIKING 2*", "*"}, 176 /*quirks*/ DA_Q_NO_6_BYTE 177 } 178 }; 179 180 static d_open_t daopen; 181 static d_close_t daclose; 182 static d_strategy_t dastrategy; 183 static d_ioctl_t daioctl; 184 static d_dump_t dadump; 185 static d_psize_t dasize; 186 static periph_init_t dainit; 187 static void daasync(void *callback_arg, u_int32_t code, 188 struct cam_path *path, void *arg); 189 static periph_ctor_t daregister; 190 static periph_dtor_t dacleanup; 191 static periph_start_t dastart; 192 static periph_oninv_t daoninvalidate; 193 static void dadone(struct cam_periph *periph, 194 union ccb *done_ccb); 195 static int daerror(union ccb *ccb, u_int32_t cam_flags, 196 u_int32_t sense_flags); 197 static void daprevent(struct cam_periph *periph, int action); 198 static void dasetgeom(struct cam_periph *periph, 199 struct scsi_read_capacity_data * rdcap); 200 static timeout_t dasendorderedtag; 201 static void dashutdown(int howto, void *arg); 202 203 #ifndef DA_DEFAULT_TIMEOUT 204 #define DA_DEFAULT_TIMEOUT 60 /* Timeout in seconds */ 205 #endif 206 207 /* 208 * DA_ORDEREDTAG_INTERVAL determines how often, relative 209 * to the default timeout, we check to see whether an ordered 210 * tagged transaction is appropriate to prevent simple tag 211 * starvation. Since we'd like to ensure that there is at least 212 * 1/2 of the timeout length left for a starved transaction to 213 * complete after we've sent an ordered tag, we must poll at least 214 * four times in every timeout period. This takes care of the worst 215 * case where a starved transaction starts during an interval that 216 * meets the requirement "don't send an ordered tag" test so it takes 217 * us two intervals to determine that a tag must be sent. 218 */ 219 #ifndef DA_ORDEREDTAG_INTERVAL 220 #define DA_ORDEREDTAG_INTERVAL 4 221 #endif 222 223 static struct periph_driver dadriver = 224 { 225 dainit, "da", 226 TAILQ_HEAD_INITIALIZER(dadriver.units), /* generation */ 0 227 }; 228 229 DATA_SET(periphdriver_set, dadriver); 230 231 #define DA_CDEV_MAJOR 13 232 #define DA_BDEV_MAJOR 4 233 234 /* For 2.2-stable support */ 235 #ifndef D_DISK 236 #define D_DISK 0 237 #endif 238 239 static struct cdevsw da_cdevsw = { 240 /* open */ daopen, 241 /* close */ daclose, 242 /* read */ physread, 243 /* write */ physwrite, 244 /* ioctl */ daioctl, 245 /* stop */ nostop, 246 /* reset */ noreset, 247 /* devtotty */ nodevtotty, 248 /* poll */ nopoll, 249 /* mmap */ nommap, 250 /* strategy */ dastrategy, 251 /* name */ "da", 252 /* parms */ noparms, 253 /* maj */ DA_CDEV_MAJOR, 254 /* dump */ dadump, 255 /* psize */ dasize, 256 /* flags */ D_DISK, 257 /* maxio */ 0, 258 /* bmaj */ DA_BDEV_MAJOR 259 }; 260 261 static SLIST_HEAD(,da_softc) softc_list; 262 static struct extend_array *daperiphs; 263 264 static int 265 daopen(dev_t dev, int flags, int fmt, struct proc *p) 266 { 267 struct cam_periph *periph; 268 struct da_softc *softc; 269 struct disklabel label; 270 int unit; 271 int part; 272 int error; 273 int s; 274 275 unit = dkunit(dev); 276 part = dkpart(dev); 277 periph = cam_extend_get(daperiphs, unit); 278 if (periph == NULL) 279 return (ENXIO); 280 281 softc = (struct da_softc *)periph->softc; 282 283 CAM_DEBUG(periph->path, CAM_DEBUG_TRACE, 284 ("daopen: dev=0x%x (unit %d , partition %d)\n", dev, 285 unit, part)); 286 287 if ((error = cam_periph_lock(periph, PRIBIO|PCATCH)) != 0) { 288 return (error); /* error code from tsleep */ 289 } 290 291 if ((softc->flags & DA_FLAG_OPEN) == 0) { 292 if (cam_periph_acquire(periph) != CAM_REQ_CMP) 293 return(ENXIO); 294 softc->flags |= DA_FLAG_OPEN; 295 } 296 297 s = splsoftcam(); 298 if ((softc->flags & DA_FLAG_PACK_INVALID) != 0) { 299 /* 300 * If any partition is open, although the disk has 301 * been invalidated, disallow further opens. 302 */ 303 if (dsisopen(softc->dk_slices)) { 304 splx(s); 305 cam_periph_unlock(periph); 306 return (ENXIO); 307 } 308 309 /* Invalidate our pack information. */ 310 dsgone(&softc->dk_slices); 311 softc->flags &= ~DA_FLAG_PACK_INVALID; 312 } 313 splx(s); 314 315 /* Do a read capacity */ 316 { 317 struct scsi_read_capacity_data *rcap; 318 union ccb *ccb; 319 320 rcap = (struct scsi_read_capacity_data *)malloc(sizeof(*rcap), 321 M_TEMP, 322 M_WAITOK); 323 324 ccb = cam_periph_getccb(periph, /*priority*/1); 325 scsi_read_capacity(&ccb->csio, 326 /*retries*/1, 327 /*cbfncp*/dadone, 328 MSG_SIMPLE_Q_TAG, 329 rcap, 330 SSD_FULL_SIZE, 331 /*timeout*/60000); 332 ccb->ccb_h.ccb_bp = NULL; 333 334 error = cam_periph_runccb(ccb, daerror, /*cam_flags*/0, 335 /*sense_flags*/SF_RETRY_UA | 336 SF_RETRY_SELTO, 337 &softc->device_stats); 338 339 xpt_release_ccb(ccb); 340 341 if (error == 0) { 342 dasetgeom(periph, rcap); 343 } 344 345 free(rcap, M_TEMP); 346 } 347 348 if (error == 0) { 349 struct ccb_getdev cgd; 350 351 /* Build label for whole disk. */ 352 bzero(&label, sizeof(label)); 353 label.d_type = DTYPE_SCSI; 354 355 /* 356 * Grab the inquiry data to get the vendor and product names. 357 * Put them in the typename and packname for the label. 358 */ 359 xpt_setup_ccb(&cgd.ccb_h, periph->path, /*priority*/ 1); 360 cgd.ccb_h.func_code = XPT_GDEV_TYPE; 361 xpt_action((union ccb *)&cgd); 362 363 strncpy(label.d_typename, cgd.inq_data.vendor, 364 min(SID_VENDOR_SIZE, sizeof(label.d_typename))); 365 strncpy(label.d_packname, cgd.inq_data.product, 366 min(SID_PRODUCT_SIZE, sizeof(label.d_packname))); 367 368 label.d_secsize = softc->params.secsize; 369 label.d_nsectors = softc->params.secs_per_track; 370 label.d_ntracks = softc->params.heads; 371 label.d_ncylinders = softc->params.cylinders; 372 label.d_secpercyl = softc->params.heads 373 * softc->params.secs_per_track; 374 label.d_secperunit = softc->params.sectors; 375 376 if ((dsisopen(softc->dk_slices) == 0) 377 && ((softc->flags & DA_FLAG_PACK_REMOVABLE) != 0)) { 378 daprevent(periph, PR_PREVENT); 379 } 380 381 /* Initialize slice tables. */ 382 error = dsopen("da", dev, fmt, 0, &softc->dk_slices, &label, 383 dastrategy, (ds_setgeom_t *)NULL, 384 &da_cdevsw); 385 386 /* 387 * Check to see whether or not the blocksize is set yet. 388 * If it isn't, set it and then clear the blocksize 389 * unavailable flag for the device statistics. 390 */ 391 if ((softc->device_stats.flags & DEVSTAT_BS_UNAVAILABLE) != 0){ 392 softc->device_stats.block_size = softc->params.secsize; 393 softc->device_stats.flags &= ~DEVSTAT_BS_UNAVAILABLE; 394 } 395 } 396 397 if (error != 0) { 398 if ((dsisopen(softc->dk_slices) == 0) 399 && ((softc->flags & DA_FLAG_PACK_REMOVABLE) != 0)) { 400 daprevent(periph, PR_ALLOW); 401 } 402 } 403 cam_periph_unlock(periph); 404 return (error); 405 } 406 407 static int 408 daclose(dev_t dev, int flag, int fmt, struct proc *p) 409 { 410 struct cam_periph *periph; 411 struct da_softc *softc; 412 int unit; 413 int error; 414 415 unit = dkunit(dev); 416 periph = cam_extend_get(daperiphs, unit); 417 if (periph == NULL) 418 return (ENXIO); 419 420 softc = (struct da_softc *)periph->softc; 421 422 if ((error = cam_periph_lock(periph, PRIBIO)) != 0) { 423 return (error); /* error code from tsleep */ 424 } 425 426 dsclose(dev, fmt, softc->dk_slices); 427 if (dsisopen(softc->dk_slices)) { 428 cam_periph_unlock(periph); 429 return (0); 430 } 431 432 if ((softc->quirks & DA_Q_NO_SYNC_CACHE) == 0) { 433 union ccb *ccb; 434 435 ccb = cam_periph_getccb(periph, /*priority*/1); 436 437 scsi_synchronize_cache(&ccb->csio, 438 /*retries*/1, 439 /*cbfcnp*/dadone, 440 MSG_SIMPLE_Q_TAG, 441 /*begin_lba*/0,/* Cover the whole disk */ 442 /*lb_count*/0, 443 SSD_FULL_SIZE, 444 5 * 60 * 1000); 445 446 cam_periph_runccb(ccb, /*error_routine*/NULL, /*cam_flags*/0, 447 /*sense_flags*/SF_RETRY_UA, 448 &softc->device_stats); 449 450 if ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) { 451 if ((ccb->ccb_h.status & CAM_STATUS_MASK) == 452 CAM_SCSI_STATUS_ERROR) { 453 int asc, ascq; 454 int sense_key, error_code; 455 456 scsi_extract_sense(&ccb->csio.sense_data, 457 &error_code, 458 &sense_key, 459 &asc, &ascq); 460 if (sense_key != SSD_KEY_ILLEGAL_REQUEST) 461 scsi_sense_print(&ccb->csio); 462 } else { 463 xpt_print_path(periph->path); 464 printf("Synchronize cache failed, status " 465 "== 0x%x, scsi status == 0x%x\n", 466 ccb->csio.ccb_h.status, 467 ccb->csio.scsi_status); 468 } 469 } 470 471 if ((ccb->ccb_h.status & CAM_DEV_QFRZN) != 0) 472 cam_release_devq(ccb->ccb_h.path, 473 /*relsim_flags*/0, 474 /*reduction*/0, 475 /*timeout*/0, 476 /*getcount_only*/0); 477 478 xpt_release_ccb(ccb); 479 480 } 481 482 if ((softc->flags & DA_FLAG_PACK_REMOVABLE) != 0) { 483 daprevent(periph, PR_ALLOW); 484 /* 485 * If we've got removeable media, mark the blocksize as 486 * unavailable, since it could change when new media is 487 * inserted. 488 */ 489 softc->device_stats.flags |= DEVSTAT_BS_UNAVAILABLE; 490 } 491 492 softc->flags &= ~DA_FLAG_OPEN; 493 cam_periph_unlock(periph); 494 cam_periph_release(periph); 495 return (0); 496 } 497 498 /* 499 * Actually translate the requested transfer into one the physical driver 500 * can understand. The transfer is described by a buf and will include 501 * only one physical transfer. 502 */ 503 static void 504 dastrategy(struct buf *bp) 505 { 506 struct cam_periph *periph; 507 struct da_softc *softc; 508 u_int unit; 509 u_int part; 510 int s; 511 512 unit = dkunit(bp->b_dev); 513 part = dkpart(bp->b_dev); 514 periph = cam_extend_get(daperiphs, unit); 515 if (periph == NULL) { 516 bp->b_error = ENXIO; 517 goto bad; 518 } 519 softc = (struct da_softc *)periph->softc; 520 #if 0 521 /* 522 * check it's not too big a transfer for our adapter 523 */ 524 scsi_minphys(bp,&sd_switch); 525 #endif 526 527 /* 528 * Do bounds checking, adjust transfer, set b_cylin and b_pbklno. 529 */ 530 if (dscheck(bp, softc->dk_slices) <= 0) 531 goto done; 532 533 /* 534 * Mask interrupts so that the pack cannot be invalidated until 535 * after we are in the queue. Otherwise, we might not properly 536 * clean up one of the buffers. 537 */ 538 s = splbio(); 539 540 /* 541 * If the device has been made invalid, error out 542 */ 543 if ((softc->flags & DA_FLAG_PACK_INVALID)) { 544 splx(s); 545 bp->b_error = ENXIO; 546 goto bad; 547 } 548 549 /* 550 * Place it in the queue of disk activities for this disk 551 */ 552 bufqdisksort(&softc->buf_queue, bp); 553 554 splx(s); 555 556 /* 557 * Schedule ourselves for performing the work. 558 */ 559 xpt_schedule(periph, /* XXX priority */1); 560 561 return; 562 bad: 563 bp->b_flags |= B_ERROR; 564 done: 565 566 /* 567 * Correctly set the buf to indicate a completed xfer 568 */ 569 bp->b_resid = bp->b_bcount; 570 biodone(bp); 571 return; 572 } 573 574 /* For 2.2-stable support */ 575 #ifndef ENOIOCTL 576 #define ENOIOCTL -1 577 #endif 578 579 static int 580 daioctl(dev_t dev, u_long cmd, caddr_t addr, int flag, struct proc *p) 581 { 582 struct cam_periph *periph; 583 struct da_softc *softc; 584 int unit; 585 int error; 586 587 unit = dkunit(dev); 588 periph = cam_extend_get(daperiphs, unit); 589 if (periph == NULL) 590 return (ENXIO); 591 592 softc = (struct da_softc *)periph->softc; 593 594 CAM_DEBUG(periph->path, CAM_DEBUG_TRACE, ("daioctl\n")); 595 596 if (cmd == DIOCSBAD) 597 return (EINVAL); /* XXX */ 598 599 if ((error = cam_periph_lock(periph, PRIBIO|PCATCH)) != 0) { 600 return (error); /* error code from tsleep */ 601 } 602 603 error = dsioctl("da", dev, cmd, addr, flag, &softc->dk_slices, 604 dastrategy, (ds_setgeom_t *)NULL); 605 606 if (error == ENOIOCTL) 607 error = cam_periph_ioctl(periph, cmd, addr, daerror); 608 609 cam_periph_unlock(periph); 610 611 return (error); 612 } 613 614 static int 615 dadump(dev_t dev) 616 { 617 struct cam_periph *periph; 618 struct da_softc *softc; 619 struct disklabel *lp; 620 u_int unit; 621 u_int part; 622 long num; /* number of sectors to write */ 623 long blkoff; 624 long blknum; 625 long blkcnt; 626 vm_offset_t addr; 627 static int dadoingadump = 0; 628 struct ccb_scsiio csio; 629 630 /* toss any characters present prior to dump */ 631 while (cncheckc() != -1) 632 ; 633 634 unit = dkunit(dev); 635 part = dkpart(dev); 636 periph = cam_extend_get(daperiphs, unit); 637 if (periph == NULL) { 638 return (ENXIO); 639 } 640 softc = (struct da_softc *)periph->softc; 641 642 if ((softc->flags & DA_FLAG_PACK_INVALID) != 0 643 || (softc->dk_slices == NULL) 644 || (lp = dsgetlabel(dev, softc->dk_slices)) == NULL) 645 return (ENXIO); 646 647 /* Size of memory to dump, in disk sectors. */ 648 /* XXX Fix up for non DEV_BSIZE sectors!!! */ 649 num = (u_long)Maxmem * PAGE_SIZE / softc->params.secsize; 650 651 blkoff = lp->d_partitions[part].p_offset; 652 blkoff += softc->dk_slices->dss_slices[dkslice(dev)].ds_offset; 653 654 /* check transfer bounds against partition size */ 655 if ((dumplo < 0) || ((dumplo + num) > lp->d_partitions[part].p_size)) 656 return (EINVAL); 657 658 if (dadoingadump != 0) 659 return (EFAULT); 660 661 dadoingadump = 1; 662 663 blknum = dumplo + blkoff; 664 blkcnt = PAGE_SIZE / softc->params.secsize; 665 666 addr = 0; /* starting address */ 667 668 while (num > 0) { 669 670 if (is_physical_memory(addr)) { 671 pmap_enter(kernel_pmap, (vm_offset_t)CADDR1, 672 trunc_page(addr), VM_PROT_READ, TRUE); 673 } else { 674 pmap_enter(kernel_pmap, (vm_offset_t)CADDR1, 675 trunc_page(0), VM_PROT_READ, TRUE); 676 } 677 678 xpt_setup_ccb(&csio.ccb_h, periph->path, /*priority*/1); 679 csio.ccb_h.ccb_state = DA_CCB_DUMP; 680 scsi_read_write(&csio, 681 /*retries*/1, 682 dadone, 683 MSG_ORDERED_Q_TAG, 684 /*read*/FALSE, 685 /*byte2*/0, 686 /*minimum_cmd_size*/ softc->minimum_cmd_size, 687 blknum, 688 blkcnt, 689 /*data_ptr*/CADDR1, 690 /*dxfer_len*/blkcnt * softc->params.secsize, 691 /*sense_len*/SSD_FULL_SIZE, 692 DA_DEFAULT_TIMEOUT * 1000); 693 xpt_polled_action((union ccb *)&csio); 694 695 if ((csio.ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) { 696 printf("Aborting dump due to I/O error.\n"); 697 if ((csio.ccb_h.status & CAM_STATUS_MASK) == 698 CAM_SCSI_STATUS_ERROR) 699 scsi_sense_print(&csio); 700 else 701 printf("status == 0x%x, scsi status == 0x%x\n", 702 csio.ccb_h.status, csio.scsi_status); 703 return(EIO); 704 } 705 706 if (addr % (1024 * 1024) == 0) { 707 #ifdef HW_WDOG 708 if (wdog_tickler) 709 (*wdog_tickler)(); 710 #endif /* HW_WDOG */ 711 /* Count in MB of data left to write */ 712 printf("%ld ", (num * softc->params.secsize) 713 / (1024 * 1024)); 714 } 715 716 /* update block count */ 717 num -= blkcnt; 718 blknum += blkcnt; 719 addr += blkcnt * softc->params.secsize; 720 721 /* operator aborting dump? */ 722 if (cncheckc() != -1) 723 return (EINTR); 724 } 725 726 /* 727 * Sync the disk cache contents to the physical media. 728 */ 729 if ((softc->quirks & DA_Q_NO_SYNC_CACHE) == 0) { 730 731 xpt_setup_ccb(&csio.ccb_h, periph->path, /*priority*/1); 732 csio.ccb_h.ccb_state = DA_CCB_DUMP; 733 scsi_synchronize_cache(&csio, 734 /*retries*/1, 735 /*cbfcnp*/dadone, 736 MSG_SIMPLE_Q_TAG, 737 /*begin_lba*/0,/* Cover the whole disk */ 738 /*lb_count*/0, 739 SSD_FULL_SIZE, 740 5 * 60 * 1000); 741 xpt_polled_action((union ccb *)&csio); 742 743 if ((csio.ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) { 744 if ((csio.ccb_h.status & CAM_STATUS_MASK) == 745 CAM_SCSI_STATUS_ERROR) { 746 int asc, ascq; 747 int sense_key, error_code; 748 749 scsi_extract_sense(&csio.sense_data, 750 &error_code, 751 &sense_key, 752 &asc, &ascq); 753 if (sense_key != SSD_KEY_ILLEGAL_REQUEST) 754 scsi_sense_print(&csio); 755 } else { 756 xpt_print_path(periph->path); 757 printf("Synchronize cache failed, status " 758 "== 0x%x, scsi status == 0x%x\n", 759 csio.ccb_h.status, csio.scsi_status); 760 } 761 } 762 } 763 return (0); 764 } 765 766 static int 767 dasize(dev_t dev) 768 { 769 struct cam_periph *periph; 770 struct da_softc *softc; 771 772 periph = cam_extend_get(daperiphs, dkunit(dev)); 773 if (periph == NULL) 774 return (ENXIO); 775 776 softc = (struct da_softc *)periph->softc; 777 778 return (dssize(dev, &softc->dk_slices, daopen, daclose)); 779 } 780 781 static void 782 dainit(void) 783 { 784 cam_status status; 785 struct cam_path *path; 786 787 /* 788 * Create our extend array for storing the devices we attach to. 789 */ 790 daperiphs = cam_extend_new(); 791 SLIST_INIT(&softc_list); 792 if (daperiphs == NULL) { 793 printf("da: Failed to alloc extend array!\n"); 794 return; 795 } 796 797 /* 798 * Install a global async callback. This callback will 799 * receive async callbacks like "new device found". 800 */ 801 status = xpt_create_path(&path, /*periph*/NULL, CAM_XPT_PATH_ID, 802 CAM_TARGET_WILDCARD, CAM_LUN_WILDCARD); 803 804 if (status == CAM_REQ_CMP) { 805 struct ccb_setasync csa; 806 807 xpt_setup_ccb(&csa.ccb_h, path, /*priority*/5); 808 csa.ccb_h.func_code = XPT_SASYNC_CB; 809 csa.event_enable = AC_FOUND_DEVICE; 810 csa.callback = daasync; 811 csa.callback_arg = NULL; 812 xpt_action((union ccb *)&csa); 813 status = csa.ccb_h.status; 814 xpt_free_path(path); 815 } 816 817 if (status != CAM_REQ_CMP) { 818 printf("da: Failed to attach master async callback " 819 "due to status 0x%x!\n", status); 820 } else { 821 int err; 822 823 /* If we were successfull, register our devsw */ 824 cdevsw_add(&da_cdevsw); 825 826 /* 827 * Schedule a periodic event to occasioanly send an 828 * ordered tag to a device. 829 */ 830 timeout(dasendorderedtag, NULL, 831 (DA_DEFAULT_TIMEOUT * hz) / DA_ORDEREDTAG_INTERVAL); 832 833 if ((err = at_shutdown(dashutdown, NULL, 834 SHUTDOWN_POST_SYNC)) != 0) 835 printf("dainit: at_shutdown returned %d!\n", err); 836 } 837 } 838 839 static void 840 daoninvalidate(struct cam_periph *periph) 841 { 842 int s; 843 struct da_softc *softc; 844 struct buf *q_bp; 845 struct ccb_setasync csa; 846 847 softc = (struct da_softc *)periph->softc; 848 849 /* 850 * De-register any async callbacks. 851 */ 852 xpt_setup_ccb(&csa.ccb_h, periph->path, 853 /* priority */ 5); 854 csa.ccb_h.func_code = XPT_SASYNC_CB; 855 csa.event_enable = 0; 856 csa.callback = daasync; 857 csa.callback_arg = periph; 858 xpt_action((union ccb *)&csa); 859 860 softc->flags |= DA_FLAG_PACK_INVALID; 861 862 /* 863 * Although the oninvalidate() routines are always called at 864 * splsoftcam, we need to be at splbio() here to keep the buffer 865 * queue from being modified while we traverse it. 866 */ 867 s = splbio(); 868 869 /* 870 * Return all queued I/O with ENXIO. 871 * XXX Handle any transactions queued to the card 872 * with XPT_ABORT_CCB. 873 */ 874 while ((q_bp = bufq_first(&softc->buf_queue)) != NULL){ 875 bufq_remove(&softc->buf_queue, q_bp); 876 q_bp->b_resid = q_bp->b_bcount; 877 q_bp->b_error = ENXIO; 878 q_bp->b_flags |= B_ERROR; 879 biodone(q_bp); 880 } 881 splx(s); 882 883 SLIST_REMOVE(&softc_list, softc, da_softc, links); 884 885 xpt_print_path(periph->path); 886 printf("lost device\n"); 887 } 888 889 static void 890 dacleanup(struct cam_periph *periph) 891 { 892 struct da_softc *softc; 893 894 softc = (struct da_softc *)periph->softc; 895 896 devstat_remove_entry(&softc->device_stats); 897 cam_extend_release(daperiphs, periph->unit_number); 898 xpt_print_path(periph->path); 899 printf("removing device entry\n"); 900 free(softc, M_DEVBUF); 901 } 902 903 static void 904 daasync(void *callback_arg, u_int32_t code, 905 struct cam_path *path, void *arg) 906 { 907 struct cam_periph *periph; 908 909 periph = (struct cam_periph *)callback_arg; 910 switch (code) { 911 case AC_FOUND_DEVICE: 912 { 913 struct ccb_getdev *cgd; 914 cam_status status; 915 916 cgd = (struct ccb_getdev *)arg; 917 918 if ((cgd->pd_type != T_DIRECT) && (cgd->pd_type != T_OPTICAL)) 919 break; 920 921 /* 922 * Allocate a peripheral instance for 923 * this device and start the probe 924 * process. 925 */ 926 status = cam_periph_alloc(daregister, daoninvalidate, 927 dacleanup, dastart, 928 "da", CAM_PERIPH_BIO, 929 cgd->ccb_h.path, daasync, 930 AC_FOUND_DEVICE, cgd); 931 932 if (status != CAM_REQ_CMP 933 && status != CAM_REQ_INPROG) 934 printf("daasync: Unable to attach to new device " 935 "due to status 0x%x\n", status); 936 break; 937 } 938 case AC_SENT_BDR: 939 case AC_BUS_RESET: 940 { 941 struct da_softc *softc; 942 struct ccb_hdr *ccbh; 943 int s; 944 945 softc = (struct da_softc *)periph->softc; 946 s = splsoftcam(); 947 /* 948 * Don't fail on the expected unit attention 949 * that will occur. 950 */ 951 softc->flags |= DA_FLAG_RETRY_UA; 952 for (ccbh = LIST_FIRST(&softc->pending_ccbs); 953 ccbh != NULL; ccbh = LIST_NEXT(ccbh, periph_links.le)) 954 ccbh->ccb_state |= DA_CCB_RETRY_UA; 955 splx(s); 956 /* FALLTHROUGH*/ 957 } 958 default: 959 cam_periph_async(periph, code, path, arg); 960 break; 961 } 962 } 963 964 static cam_status 965 daregister(struct cam_periph *periph, void *arg) 966 { 967 int s; 968 struct da_softc *softc; 969 struct ccb_setasync csa; 970 struct ccb_getdev *cgd; 971 caddr_t match; 972 973 cgd = (struct ccb_getdev *)arg; 974 if (periph == NULL) { 975 printf("daregister: periph was NULL!!\n"); 976 return(CAM_REQ_CMP_ERR); 977 } 978 979 if (cgd == NULL) { 980 printf("daregister: no getdev CCB, can't register device\n"); 981 return(CAM_REQ_CMP_ERR); 982 } 983 984 softc = (struct da_softc *)malloc(sizeof(*softc),M_DEVBUF,M_NOWAIT); 985 986 if (softc == NULL) { 987 printf("daregister: Unable to probe new device. " 988 "Unable to allocate softc\n"); 989 return(CAM_REQ_CMP_ERR); 990 } 991 992 bzero(softc, sizeof(*softc)); 993 LIST_INIT(&softc->pending_ccbs); 994 softc->state = DA_STATE_PROBE; 995 bufq_init(&softc->buf_queue); 996 if (SID_IS_REMOVABLE(&cgd->inq_data)) 997 softc->flags |= DA_FLAG_PACK_REMOVABLE; 998 if ((cgd->inq_data.flags & SID_CmdQue) != 0) 999 softc->flags |= DA_FLAG_TAGGED_QUEUING; 1000 1001 periph->softc = softc; 1002 1003 cam_extend_set(daperiphs, periph->unit_number, periph); 1004 1005 /* 1006 * See if this device has any quirks. 1007 */ 1008 match = cam_quirkmatch((caddr_t)&cgd->inq_data, 1009 (caddr_t)da_quirk_table, 1010 sizeof(da_quirk_table)/sizeof(*da_quirk_table), 1011 sizeof(*da_quirk_table), scsi_inquiry_match); 1012 1013 if (match != NULL) 1014 softc->quirks = ((struct da_quirk_entry *)match)->quirks; 1015 else 1016 softc->quirks = DA_Q_NONE; 1017 1018 if (softc->quirks & DA_Q_NO_6_BYTE) 1019 softc->minimum_cmd_size = 10; 1020 else 1021 softc->minimum_cmd_size = 6; 1022 1023 /* 1024 * Block our timeout handler while we 1025 * add this softc to the dev list. 1026 */ 1027 s = splsoftclock(); 1028 SLIST_INSERT_HEAD(&softc_list, softc, links); 1029 splx(s); 1030 1031 /* 1032 * The DA driver supports a blocksize, but 1033 * we don't know the blocksize until we do 1034 * a read capacity. So, set a flag to 1035 * indicate that the blocksize is 1036 * unavailable right now. We'll clear the 1037 * flag as soon as we've done a read capacity. 1038 */ 1039 devstat_add_entry(&softc->device_stats, "da", 1040 periph->unit_number, 0, 1041 DEVSTAT_BS_UNAVAILABLE, 1042 cgd->pd_type | DEVSTAT_TYPE_IF_SCSI, 1043 DEVSTAT_PRIORITY_DA); 1044 1045 /* 1046 * Add async callbacks for bus reset and 1047 * bus device reset calls. I don't bother 1048 * checking if this fails as, in most cases, 1049 * the system will function just fine without 1050 * them and the only alternative would be to 1051 * not attach the device on failure. 1052 */ 1053 xpt_setup_ccb(&csa.ccb_h, periph->path, /*priority*/5); 1054 csa.ccb_h.func_code = XPT_SASYNC_CB; 1055 csa.event_enable = AC_SENT_BDR | AC_BUS_RESET | AC_LOST_DEVICE; 1056 csa.callback = daasync; 1057 csa.callback_arg = periph; 1058 xpt_action((union ccb *)&csa); 1059 /* 1060 * Lock this peripheral until we are setup. 1061 * This first call can't block 1062 */ 1063 (void)cam_periph_lock(periph, PRIBIO); 1064 xpt_schedule(periph, /*priority*/5); 1065 1066 return(CAM_REQ_CMP); 1067 } 1068 1069 static void 1070 dastart(struct cam_periph *periph, union ccb *start_ccb) 1071 { 1072 struct da_softc *softc; 1073 1074 softc = (struct da_softc *)periph->softc; 1075 1076 1077 switch (softc->state) { 1078 case DA_STATE_NORMAL: 1079 { 1080 /* Pull a buffer from the queue and get going on it */ 1081 struct buf *bp; 1082 int s; 1083 1084 /* 1085 * See if there is a buf with work for us to do.. 1086 */ 1087 s = splbio(); 1088 bp = bufq_first(&softc->buf_queue); 1089 if (periph->immediate_priority <= periph->pinfo.priority) { 1090 CAM_DEBUG_PRINT(CAM_DEBUG_SUBTRACE, 1091 ("queuing for immediate ccb\n")); 1092 start_ccb->ccb_h.ccb_state = DA_CCB_WAITING; 1093 SLIST_INSERT_HEAD(&periph->ccb_list, &start_ccb->ccb_h, 1094 periph_links.sle); 1095 periph->immediate_priority = CAM_PRIORITY_NONE; 1096 splx(s); 1097 wakeup(&periph->ccb_list); 1098 } else if (bp == NULL) { 1099 splx(s); 1100 xpt_release_ccb(start_ccb); 1101 } else { 1102 int oldspl; 1103 u_int8_t tag_code; 1104 1105 bufq_remove(&softc->buf_queue, bp); 1106 1107 devstat_start_transaction(&softc->device_stats); 1108 1109 if ((bp->b_flags & B_ORDERED) != 0 1110 || (softc->flags & DA_FLAG_NEED_OTAG) != 0) { 1111 softc->flags &= ~DA_FLAG_NEED_OTAG; 1112 softc->ordered_tag_count++; 1113 tag_code = MSG_ORDERED_Q_TAG; 1114 } else { 1115 tag_code = MSG_SIMPLE_Q_TAG; 1116 } 1117 scsi_read_write(&start_ccb->csio, 1118 /*retries*/4, 1119 dadone, 1120 tag_code, 1121 bp->b_flags & B_READ, 1122 /*byte2*/0, 1123 softc->minimum_cmd_size, 1124 bp->b_pblkno, 1125 bp->b_bcount / softc->params.secsize, 1126 bp->b_data, 1127 bp->b_bcount, 1128 /*sense_len*/SSD_FULL_SIZE, 1129 DA_DEFAULT_TIMEOUT * 1000); 1130 start_ccb->ccb_h.ccb_state = DA_CCB_BUFFER_IO; 1131 1132 /* 1133 * Block out any asyncronous callbacks 1134 * while we touch the pending ccb list. 1135 */ 1136 oldspl = splcam(); 1137 LIST_INSERT_HEAD(&softc->pending_ccbs, 1138 &start_ccb->ccb_h, periph_links.le); 1139 splx(oldspl); 1140 1141 /* We expect a unit attention from this device */ 1142 if ((softc->flags & DA_FLAG_RETRY_UA) != 0) { 1143 start_ccb->ccb_h.ccb_state |= DA_CCB_RETRY_UA; 1144 softc->flags &= ~DA_FLAG_RETRY_UA; 1145 } 1146 1147 start_ccb->ccb_h.ccb_bp = bp; 1148 bp = bufq_first(&softc->buf_queue); 1149 splx(s); 1150 1151 xpt_action(start_ccb); 1152 } 1153 1154 if (bp != NULL) { 1155 /* Have more work to do, so ensure we stay scheduled */ 1156 xpt_schedule(periph, /* XXX priority */1); 1157 } 1158 break; 1159 } 1160 case DA_STATE_PROBE: 1161 { 1162 struct ccb_scsiio *csio; 1163 struct scsi_read_capacity_data *rcap; 1164 1165 rcap = (struct scsi_read_capacity_data *)malloc(sizeof(*rcap), 1166 M_TEMP, 1167 M_NOWAIT); 1168 if (rcap == NULL) { 1169 printf("dastart: Couldn't malloc read_capacity data\n"); 1170 /* da_free_periph??? */ 1171 break; 1172 } 1173 csio = &start_ccb->csio; 1174 scsi_read_capacity(csio, 1175 /*retries*/4, 1176 dadone, 1177 MSG_SIMPLE_Q_TAG, 1178 rcap, 1179 SSD_FULL_SIZE, 1180 /*timeout*/5000); 1181 start_ccb->ccb_h.ccb_bp = NULL; 1182 start_ccb->ccb_h.ccb_state = DA_CCB_PROBE; 1183 xpt_action(start_ccb); 1184 break; 1185 } 1186 } 1187 } 1188 1189 1190 static void 1191 dadone(struct cam_periph *periph, union ccb *done_ccb) 1192 { 1193 struct da_softc *softc; 1194 struct ccb_scsiio *csio; 1195 1196 softc = (struct da_softc *)periph->softc; 1197 csio = &done_ccb->csio; 1198 switch (csio->ccb_h.ccb_state & DA_CCB_TYPE_MASK) { 1199 case DA_CCB_BUFFER_IO: 1200 { 1201 struct buf *bp; 1202 int oldspl; 1203 1204 bp = (struct buf *)done_ccb->ccb_h.ccb_bp; 1205 if ((done_ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) { 1206 int error; 1207 int s; 1208 int sf; 1209 1210 if ((csio->ccb_h.ccb_state & DA_CCB_RETRY_UA) != 0) 1211 sf = SF_RETRY_UA; 1212 else 1213 sf = 0; 1214 1215 /* Retry selection timeouts */ 1216 sf |= SF_RETRY_SELTO; 1217 1218 if ((error = daerror(done_ccb, 0, sf)) == ERESTART) { 1219 /* 1220 * A retry was scheuled, so 1221 * just return. 1222 */ 1223 return; 1224 } 1225 if (error != 0) { 1226 struct buf *q_bp; 1227 1228 s = splbio(); 1229 1230 if (error == ENXIO) { 1231 /* 1232 * Catastrophic error. Mark our pack as 1233 * invalid. 1234 */ 1235 /* XXX See if this is really a media 1236 * change first. 1237 */ 1238 xpt_print_path(periph->path); 1239 printf("Invalidating pack\n"); 1240 softc->flags |= DA_FLAG_PACK_INVALID; 1241 } 1242 1243 /* 1244 * return all queued I/O with EIO, so that 1245 * the client can retry these I/Os in the 1246 * proper order should it attempt to recover. 1247 */ 1248 while ((q_bp = bufq_first(&softc->buf_queue)) 1249 != NULL) { 1250 bufq_remove(&softc->buf_queue, q_bp); 1251 q_bp->b_resid = q_bp->b_bcount; 1252 q_bp->b_error = EIO; 1253 q_bp->b_flags |= B_ERROR; 1254 biodone(q_bp); 1255 } 1256 splx(s); 1257 bp->b_error = error; 1258 bp->b_resid = bp->b_bcount; 1259 bp->b_flags |= B_ERROR; 1260 } else { 1261 bp->b_resid = csio->resid; 1262 bp->b_error = 0; 1263 if (bp->b_resid != 0) { 1264 /* Short transfer ??? */ 1265 bp->b_flags |= B_ERROR; 1266 } 1267 } 1268 if ((done_ccb->ccb_h.status & CAM_DEV_QFRZN) != 0) 1269 cam_release_devq(done_ccb->ccb_h.path, 1270 /*relsim_flags*/0, 1271 /*reduction*/0, 1272 /*timeout*/0, 1273 /*getcount_only*/0); 1274 } else { 1275 bp->b_resid = csio->resid; 1276 if (csio->resid > 0) 1277 bp->b_flags |= B_ERROR; 1278 } 1279 1280 /* 1281 * Block out any asyncronous callbacks 1282 * while we touch the pending ccb list. 1283 */ 1284 oldspl = splcam(); 1285 LIST_REMOVE(&done_ccb->ccb_h, periph_links.le); 1286 splx(oldspl); 1287 1288 devstat_end_transaction(&softc->device_stats, 1289 bp->b_bcount - bp->b_resid, 1290 done_ccb->csio.tag_action & 0xf, 1291 (bp->b_flags & B_READ) ? DEVSTAT_READ 1292 : DEVSTAT_WRITE); 1293 1294 if (softc->device_stats.busy_count == 0) 1295 softc->flags |= DA_FLAG_WENT_IDLE; 1296 1297 biodone(bp); 1298 break; 1299 } 1300 case DA_CCB_PROBE: 1301 { 1302 struct scsi_read_capacity_data *rdcap; 1303 char announce_buf[80]; 1304 1305 rdcap = (struct scsi_read_capacity_data *)csio->data_ptr; 1306 1307 if ((csio->ccb_h.status & CAM_STATUS_MASK) == CAM_REQ_CMP) { 1308 struct disk_params *dp; 1309 1310 dasetgeom(periph, rdcap); 1311 dp = &softc->params; 1312 snprintf(announce_buf, sizeof(announce_buf), 1313 "%ldMB (%d %d byte sectors: %dH %dS/T %dC)", 1314 dp->sectors / ((1024L * 1024L) / dp->secsize), 1315 dp->sectors, dp->secsize, dp->heads, 1316 dp->secs_per_track, dp->cylinders); 1317 } else { 1318 int error; 1319 1320 /* 1321 * Retry any UNIT ATTENTION type errors. They 1322 * are expected at boot. 1323 */ 1324 error = daerror(done_ccb, 0, SF_RETRY_UA | 1325 SF_RETRY_SELTO | SF_NO_PRINT); 1326 if (error == ERESTART) { 1327 /* 1328 * A retry was scheuled, so 1329 * just return. 1330 */ 1331 return; 1332 } else if (error != 0) { 1333 struct scsi_sense_data *sense; 1334 int asc, ascq; 1335 int sense_key, error_code; 1336 int have_sense; 1337 cam_status status; 1338 struct ccb_getdev cgd; 1339 1340 /* Don't wedge this device's queue */ 1341 cam_release_devq(done_ccb->ccb_h.path, 1342 /*relsim_flags*/0, 1343 /*reduction*/0, 1344 /*timeout*/0, 1345 /*getcount_only*/0); 1346 1347 status = done_ccb->ccb_h.status; 1348 1349 xpt_setup_ccb(&cgd.ccb_h, 1350 done_ccb->ccb_h.path, 1351 /* priority */ 1); 1352 cgd.ccb_h.func_code = XPT_GDEV_TYPE; 1353 xpt_action((union ccb *)&cgd); 1354 1355 if (((csio->ccb_h.flags & CAM_SENSE_PHYS) != 0) 1356 || ((csio->ccb_h.flags & CAM_SENSE_PTR) != 0) 1357 || ((status & CAM_AUTOSNS_VALID) == 0)) 1358 have_sense = FALSE; 1359 else 1360 have_sense = TRUE; 1361 1362 if (have_sense) { 1363 sense = &csio->sense_data; 1364 scsi_extract_sense(sense, &error_code, 1365 &sense_key, 1366 &asc, &ascq); 1367 } 1368 /* 1369 * Attach to anything that claims to be a 1370 * direct access or optical disk device, 1371 * as long as it doesn't return a "Logical 1372 * unit not supported" (0x25) error. 1373 */ 1374 if ((have_sense) && (asc != 0x25) 1375 && (error_code == SSD_CURRENT_ERROR)) 1376 snprintf(announce_buf, 1377 sizeof(announce_buf), 1378 "Attempt to query device " 1379 "size failed: %s, %s", 1380 scsi_sense_key_text[sense_key], 1381 scsi_sense_desc(asc,ascq, 1382 &cgd.inq_data)); 1383 else { 1384 if (have_sense) 1385 scsi_sense_print( 1386 &done_ccb->csio); 1387 else { 1388 xpt_print_path(periph->path); 1389 printf("got CAM status %#x\n", 1390 done_ccb->ccb_h.status); 1391 } 1392 1393 xpt_print_path(periph->path); 1394 printf("fatal error, failed" 1395 " to attach to device\n"); 1396 1397 /* 1398 * Free up resources. 1399 */ 1400 cam_periph_invalidate(periph); 1401 announce_buf[0] = '\0'; 1402 } 1403 } 1404 } 1405 free(rdcap, M_TEMP); 1406 if (announce_buf[0] != '\0') 1407 xpt_announce_periph(periph, announce_buf); 1408 softc->state = DA_STATE_NORMAL; 1409 /* 1410 * Since our peripheral may be invalidated by an error 1411 * above or an external event, we must release our CCB 1412 * before releasing the probe lock on the peripheral. 1413 * The peripheral will only go away once the last lock 1414 * is removed, and we need it around for the CCB release 1415 * operation. 1416 */ 1417 xpt_release_ccb(done_ccb); 1418 cam_periph_unlock(periph); 1419 return; 1420 } 1421 case DA_CCB_WAITING: 1422 { 1423 /* Caller will release the CCB */ 1424 wakeup(&done_ccb->ccb_h.cbfcnp); 1425 return; 1426 } 1427 case DA_CCB_DUMP: 1428 /* No-op. We're polling */ 1429 return; 1430 default: 1431 break; 1432 } 1433 xpt_release_ccb(done_ccb); 1434 } 1435 1436 static int 1437 daerror(union ccb *ccb, u_int32_t cam_flags, u_int32_t sense_flags) 1438 { 1439 struct da_softc *softc; 1440 struct cam_periph *periph; 1441 1442 periph = xpt_path_periph(ccb->ccb_h.path); 1443 softc = (struct da_softc *)periph->softc; 1444 1445 /* 1446 * XXX 1447 * Until we have a better way of doing pack validation, 1448 * don't treat UAs as errors. 1449 */ 1450 sense_flags |= SF_RETRY_UA; 1451 return(cam_periph_error(ccb, cam_flags, sense_flags, 1452 &softc->saved_ccb)); 1453 } 1454 1455 static void 1456 daprevent(struct cam_periph *periph, int action) 1457 { 1458 struct da_softc *softc; 1459 union ccb *ccb; 1460 int error; 1461 1462 softc = (struct da_softc *)periph->softc; 1463 1464 if (((action == PR_ALLOW) 1465 && (softc->flags & DA_FLAG_PACK_LOCKED) == 0) 1466 || ((action == PR_PREVENT) 1467 && (softc->flags & DA_FLAG_PACK_LOCKED) != 0)) { 1468 return; 1469 } 1470 1471 ccb = cam_periph_getccb(periph, /*priority*/1); 1472 1473 scsi_prevent(&ccb->csio, 1474 /*retries*/1, 1475 /*cbcfp*/dadone, 1476 MSG_SIMPLE_Q_TAG, 1477 action, 1478 SSD_FULL_SIZE, 1479 5000); 1480 1481 error = cam_periph_runccb(ccb, /*error_routine*/NULL, /*cam_flags*/0, 1482 /*sense_flags*/0, &softc->device_stats); 1483 1484 if (error == 0) { 1485 if (action == PR_ALLOW) 1486 softc->flags &= ~DA_FLAG_PACK_LOCKED; 1487 else 1488 softc->flags |= DA_FLAG_PACK_LOCKED; 1489 } 1490 1491 xpt_release_ccb(ccb); 1492 } 1493 1494 static void 1495 dasetgeom(struct cam_periph *periph, struct scsi_read_capacity_data * rdcap) 1496 { 1497 struct ccb_calc_geometry ccg; 1498 struct da_softc *softc; 1499 struct disk_params *dp; 1500 1501 softc = (struct da_softc *)periph->softc; 1502 1503 dp = &softc->params; 1504 dp->secsize = scsi_4btoul(rdcap->length); 1505 dp->sectors = scsi_4btoul(rdcap->addr) + 1; 1506 /* 1507 * Have the controller provide us with a geometry 1508 * for this disk. The only time the geometry 1509 * matters is when we boot and the controller 1510 * is the only one knowledgeable enough to come 1511 * up with something that will make this a bootable 1512 * device. 1513 */ 1514 xpt_setup_ccb(&ccg.ccb_h, periph->path, /*priority*/1); 1515 ccg.ccb_h.func_code = XPT_CALC_GEOMETRY; 1516 ccg.block_size = dp->secsize; 1517 ccg.volume_size = dp->sectors; 1518 ccg.heads = 0; 1519 ccg.secs_per_track = 0; 1520 ccg.cylinders = 0; 1521 xpt_action((union ccb*)&ccg); 1522 dp->heads = ccg.heads; 1523 dp->secs_per_track = ccg.secs_per_track; 1524 dp->cylinders = ccg.cylinders; 1525 } 1526 1527 static void 1528 dasendorderedtag(void *arg) 1529 { 1530 struct da_softc *softc; 1531 int s; 1532 1533 for (softc = SLIST_FIRST(&softc_list); 1534 softc != NULL; 1535 softc = SLIST_NEXT(softc, links)) { 1536 s = splsoftcam(); 1537 if ((softc->ordered_tag_count == 0) 1538 && ((softc->flags & DA_FLAG_WENT_IDLE) == 0)) { 1539 softc->flags |= DA_FLAG_NEED_OTAG; 1540 } 1541 if (softc->device_stats.busy_count > 0) 1542 softc->flags &= ~DA_FLAG_WENT_IDLE; 1543 1544 softc->ordered_tag_count = 0; 1545 splx(s); 1546 } 1547 /* Queue us up again */ 1548 timeout(dasendorderedtag, NULL, 1549 (DA_DEFAULT_TIMEOUT * hz) / DA_ORDEREDTAG_INTERVAL); 1550 } 1551 1552 /* 1553 * Step through all DA peripheral drivers, and if the device is still open, 1554 * sync the disk cache to physical media. 1555 */ 1556 static void 1557 dashutdown(int howto, void *arg) 1558 { 1559 struct cam_periph *periph; 1560 struct da_softc *softc; 1561 1562 for (periph = TAILQ_FIRST(&dadriver.units); periph != NULL; 1563 periph = TAILQ_NEXT(periph, unit_links)) { 1564 union ccb ccb; 1565 softc = (struct da_softc *)periph->softc; 1566 1567 /* 1568 * We only sync the cache if the drive is still open, and 1569 * if the drive is capable of it.. 1570 */ 1571 if (((softc->flags & DA_FLAG_OPEN) == 0) 1572 || (softc->quirks & DA_Q_NO_SYNC_CACHE)) 1573 continue; 1574 1575 xpt_setup_ccb(&ccb.ccb_h, periph->path, /*priority*/1); 1576 1577 ccb.ccb_h.ccb_state = DA_CCB_DUMP; 1578 scsi_synchronize_cache(&ccb.csio, 1579 /*retries*/1, 1580 /*cbfcnp*/dadone, 1581 MSG_SIMPLE_Q_TAG, 1582 /*begin_lba*/0, /* whole disk */ 1583 /*lb_count*/0, 1584 SSD_FULL_SIZE, 1585 5 * 60 * 1000); 1586 1587 xpt_polled_action(&ccb); 1588 1589 if ((ccb.ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) { 1590 if (((ccb.ccb_h.status & CAM_STATUS_MASK) == 1591 CAM_SCSI_STATUS_ERROR) 1592 && (ccb.csio.scsi_status == SCSI_STATUS_CHECK_COND)){ 1593 int error_code, sense_key, asc, ascq; 1594 1595 scsi_extract_sense(&ccb.csio.sense_data, 1596 &error_code, &sense_key, 1597 &asc, &ascq); 1598 1599 if (sense_key != SSD_KEY_ILLEGAL_REQUEST) 1600 scsi_sense_print(&ccb.csio); 1601 } else { 1602 xpt_print_path(periph->path); 1603 printf("Synchronize cache failed, status " 1604 "== 0x%x, scsi status == 0x%x\n", 1605 ccb.ccb_h.status, ccb.csio.scsi_status); 1606 } 1607 } 1608 1609 if ((ccb.ccb_h.status & CAM_DEV_QFRZN) != 0) 1610 cam_release_devq(ccb.ccb_h.path, 1611 /*relsim_flags*/0, 1612 /*reduction*/0, 1613 /*timeout*/0, 1614 /*getcount_only*/0); 1615 1616 } 1617 } 1618