scsi_cd.c revision 67928
1/* 2 * Copyright (c) 1997 Justin T. Gibbs. 3 * Copyright (c) 1997, 1998, 1999, 2000 Kenneth D. Merry. 4 * All rights reserved. 5 * 6 * Redistribution and use in source and binary forms, with or without 7 * modification, are permitted provided that the following conditions 8 * are met: 9 * 1. Redistributions of source code must retain the above copyright 10 * notice, this list of conditions, and the following disclaimer, 11 * without modification, immediately at the beginning of the file. 12 * 2. The name of the author may not be used to endorse or promote products 13 * derived from this software without specific prior written permission. 14 * 15 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 16 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 17 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 18 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR 19 * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 20 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 21 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 22 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 23 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 24 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 25 * SUCH DAMAGE. 26 * 27 * $FreeBSD: head/sys/cam/scsi/scsi_cd.c 67928 2000-10-30 07:03:00Z ken $ 28 */ 29/* 30 * Portions of this driver taken from the original FreeBSD cd driver. 31 * Written by Julian Elischer (julian@tfs.com) 32 * for TRW Financial Systems for use under the MACH(2.5) operating system. 33 * 34 * TRW Financial Systems, in accordance with their agreement with Carnegie 35 * Mellon University, makes this software available to CMU to distribute 36 * or use in any manner that they see fit as long as this message is kept with 37 * the software. For this reason TFS also grants any other persons or 38 * organisations permission to use or modify this software. 39 * 40 * TFS supplies this software to be publicly redistributed 41 * on the understanding that TFS is not responsible for the correct 42 * functioning of this software in any circumstances. 43 * 44 * Ported to run under 386BSD by Julian Elischer (julian@tfs.com) Sept 1992 45 * 46 * from: cd.c,v 1.83 1997/05/04 15:24:22 joerg Exp $ 47 */ 48 49#include "opt_cd.h" 50 51#include <sys/param.h> 52#include <sys/systm.h> 53#include <sys/kernel.h> 54#include <sys/bio.h> 55#include <sys/conf.h> 56#include <sys/disk.h> 57#include <sys/malloc.h> 58#include <sys/cdio.h> 59#include <sys/dvdio.h> 60#include <sys/devicestat.h> 61#include <sys/sysctl.h> 62 63#include <cam/cam.h> 64#include <cam/cam_ccb.h> 65#include <cam/cam_extend.h> 66#include <cam/cam_periph.h> 67#include <cam/cam_xpt_periph.h> 68#include <cam/cam_queue.h> 69 70#include <cam/scsi/scsi_message.h> 71#include <cam/scsi/scsi_da.h> 72#include <cam/scsi/scsi_cd.h> 73 74#define LEADOUT 0xaa /* leadout toc entry */ 75 76struct cd_params { 77 u_int32_t blksize; 78 u_long disksize; 79}; 80 81typedef enum { 82 CD_Q_NONE = 0x00, 83 CD_Q_NO_TOUCH = 0x01, 84 CD_Q_BCD_TRACKS = 0x02, 85 CD_Q_NO_CHANGER = 0x04, 86 CD_Q_CHANGER = 0x08 87} cd_quirks; 88 89typedef enum { 90 CD_FLAG_INVALID = 0x001, 91 CD_FLAG_NEW_DISC = 0x002, 92 CD_FLAG_DISC_LOCKED = 0x004, 93 CD_FLAG_DISC_REMOVABLE = 0x008, 94 CD_FLAG_TAGGED_QUEUING = 0x010, 95 CD_FLAG_CHANGER = 0x040, 96 CD_FLAG_ACTIVE = 0x080, 97 CD_FLAG_SCHED_ON_COMP = 0x100, 98 CD_FLAG_RETRY_UA = 0x200 99} cd_flags; 100 101typedef enum { 102 CD_CCB_PROBE = 0x01, 103 CD_CCB_BUFFER_IO = 0x02, 104 CD_CCB_WAITING = 0x03, 105 CD_CCB_TYPE_MASK = 0x0F, 106 CD_CCB_RETRY_UA = 0x10 107} cd_ccb_state; 108 109typedef enum { 110 CHANGER_TIMEOUT_SCHED = 0x01, 111 CHANGER_SHORT_TMOUT_SCHED = 0x02, 112 CHANGER_MANUAL_CALL = 0x04, 113 CHANGER_NEED_TIMEOUT = 0x08 114} cd_changer_flags; 115 116#define ccb_state ppriv_field0 117#define ccb_bp ppriv_ptr1 118 119typedef enum { 120 CD_STATE_PROBE, 121 CD_STATE_NORMAL 122} cd_state; 123 124struct cd_softc { 125 cam_pinfo pinfo; 126 cd_state state; 127 volatile cd_flags flags; 128 struct bio_queue_head bio_queue; 129 LIST_HEAD(, ccb_hdr) pending_ccbs; 130 struct cd_params params; 131 struct disk disk; 132 union ccb saved_ccb; 133 cd_quirks quirks; 134 struct devstat device_stats; 135 STAILQ_ENTRY(cd_softc) changer_links; 136 struct cdchanger *changer; 137 int bufs_left; 138 struct cam_periph *periph; 139}; 140 141struct cd_quirk_entry { 142 struct scsi_inquiry_pattern inq_pat; 143 cd_quirks quirks; 144}; 145 146/* 147 * These quirk entries aren't strictly necessary. Basically, what they do 148 * is tell cdregister() up front that a device is a changer. Otherwise, it 149 * will figure that fact out once it sees a LUN on the device that is 150 * greater than 0. If it is known up front that a device is a changer, all 151 * I/O to the device will go through the changer scheduling routines, as 152 * opposed to the "normal" CD code. 153 */ 154static struct cd_quirk_entry cd_quirk_table[] = 155{ 156 { 157 { T_CDROM, SIP_MEDIA_REMOVABLE, "NRC", "MBR-7", "*"}, 158 /*quirks*/ CD_Q_CHANGER 159 }, 160 { 161 { T_CDROM, SIP_MEDIA_REMOVABLE, "PIONEER", "CD-ROM DRM*", 162 "*"}, /* quirks */ CD_Q_CHANGER 163 }, 164 { 165 { T_CDROM, SIP_MEDIA_REMOVABLE, "NAKAMICH", "MJ-*", "*"}, 166 /* quirks */ CD_Q_CHANGER 167 }, 168 { 169 { T_CDROM, SIP_MEDIA_REMOVABLE, "CHINON", "CD-ROM CDS-535","*"}, 170 /* quirks */ CD_Q_BCD_TRACKS 171 } 172}; 173 174#ifndef MIN 175#define MIN(x,y) ((x<y) ? x : y) 176#endif 177 178#define CD_CDEV_MAJOR 15 179#define CD_BDEV_MAJOR 6 180 181static d_open_t cdopen; 182static d_close_t cdclose; 183static d_ioctl_t cdioctl; 184static d_strategy_t cdstrategy; 185 186static periph_init_t cdinit; 187static periph_ctor_t cdregister; 188static periph_dtor_t cdcleanup; 189static periph_start_t cdstart; 190static periph_oninv_t cdoninvalidate; 191static void cdasync(void *callback_arg, u_int32_t code, 192 struct cam_path *path, void *arg); 193static void cdshorttimeout(void *arg); 194static void cdschedule(struct cam_periph *periph, int priority); 195static void cdrunchangerqueue(void *arg); 196static void cdchangerschedule(struct cd_softc *softc); 197static int cdrunccb(union ccb *ccb, 198 int (*error_routine)(union ccb *ccb, 199 u_int32_t cam_flags, 200 u_int32_t sense_flags), 201 u_int32_t cam_flags, u_int32_t sense_flags); 202static union ccb *cdgetccb(struct cam_periph *periph, 203 u_int32_t priority); 204static void cddone(struct cam_periph *periph, 205 union ccb *start_ccb); 206static int cderror(union ccb *ccb, u_int32_t cam_flags, 207 u_int32_t sense_flags); 208static void cdprevent(struct cam_periph *periph, int action); 209static int cdsize(dev_t dev, u_int32_t *size); 210static int cdreadtoc(struct cam_periph *periph, u_int32_t mode, 211 u_int32_t start, struct cd_toc_entry *data, 212 u_int32_t len); 213static int cdgetmode(struct cam_periph *periph, 214 struct cd_mode_data *data, u_int32_t page); 215static int cdsetmode(struct cam_periph *periph, 216 struct cd_mode_data *data); 217static int cdplay(struct cam_periph *periph, u_int32_t blk, 218 u_int32_t len); 219static int cdreadsubchannel(struct cam_periph *periph, 220 u_int32_t mode, u_int32_t format, 221 int track, 222 struct cd_sub_channel_info *data, 223 u_int32_t len); 224static int cdplaymsf(struct cam_periph *periph, u_int32_t startm, 225 u_int32_t starts, u_int32_t startf, 226 u_int32_t endm, u_int32_t ends, 227 u_int32_t endf); 228static int cdplaytracks(struct cam_periph *periph, 229 u_int32_t strack, u_int32_t sindex, 230 u_int32_t etrack, u_int32_t eindex); 231static int cdpause(struct cam_periph *periph, u_int32_t go); 232static int cdstopunit(struct cam_periph *periph, u_int32_t eject); 233static int cdstartunit(struct cam_periph *periph); 234static int cdreportkey(struct cam_periph *periph, 235 struct dvd_authinfo *authinfo); 236static int cdsendkey(struct cam_periph *periph, 237 struct dvd_authinfo *authinfo); 238static int cdreaddvdstructure(struct cam_periph *periph, 239 struct dvd_struct *dvdstruct); 240 241static struct periph_driver cddriver = 242{ 243 cdinit, "cd", 244 TAILQ_HEAD_INITIALIZER(cddriver.units), /* generation */ 0 245}; 246 247DATA_SET(periphdriver_set, cddriver); 248 249/* For 2.2-stable support */ 250#ifndef D_DISK 251#define D_DISK 0 252#endif 253static struct cdevsw cd_cdevsw = { 254 /* open */ cdopen, 255 /* close */ cdclose, 256 /* read */ physread, 257 /* write */ physwrite, 258 /* ioctl */ cdioctl, 259 /* poll */ nopoll, 260 /* mmap */ nommap, 261 /* strategy */ cdstrategy, 262 /* name */ "cd", 263 /* maj */ CD_CDEV_MAJOR, 264 /* dump */ nodump, 265 /* psize */ nopsize, 266 /* flags */ D_DISK, 267 /* bmaj */ CD_BDEV_MAJOR 268}; 269static struct cdevsw cddisk_cdevsw; 270 271static struct extend_array *cdperiphs; 272static int num_changers; 273 274#ifndef CHANGER_MIN_BUSY_SECONDS 275#define CHANGER_MIN_BUSY_SECONDS 5 276#endif 277#ifndef CHANGER_MAX_BUSY_SECONDS 278#define CHANGER_MAX_BUSY_SECONDS 15 279#endif 280 281static int changer_min_busy_seconds = CHANGER_MIN_BUSY_SECONDS; 282static int changer_max_busy_seconds = CHANGER_MAX_BUSY_SECONDS; 283 284/* 285 * XXX KDM this CAM node should be moved if we ever get more CAM sysctl 286 * variables. 287 */ 288SYSCTL_NODE(_kern, OID_AUTO, cam, CTLFLAG_RD, 0, "CAM Subsystem"); 289SYSCTL_NODE(_kern_cam, OID_AUTO, cd, CTLFLAG_RD, 0, "CAM CDROM driver"); 290SYSCTL_NODE(_kern_cam_cd, OID_AUTO, changer, CTLFLAG_RD, 0, "CD Changer"); 291SYSCTL_INT(_kern_cam_cd_changer, OID_AUTO, min_busy_seconds, CTLFLAG_RW, 292 &changer_min_busy_seconds, 0, "Minimum changer scheduling quantum"); 293SYSCTL_INT(_kern_cam_cd_changer, OID_AUTO, max_busy_seconds, CTLFLAG_RW, 294 &changer_max_busy_seconds, 0, "Maximum changer scheduling quantum"); 295 296struct cdchanger { 297 path_id_t path_id; 298 target_id_t target_id; 299 int num_devices; 300 struct camq devq; 301 struct timeval start_time; 302 struct cd_softc *cur_device; 303 struct callout_handle short_handle; 304 struct callout_handle long_handle; 305 volatile cd_changer_flags flags; 306 STAILQ_ENTRY(cdchanger) changer_links; 307 STAILQ_HEAD(chdevlist, cd_softc) chluns; 308}; 309 310static STAILQ_HEAD(changerlist, cdchanger) changerq; 311 312void 313cdinit(void) 314{ 315 cam_status status; 316 struct cam_path *path; 317 318 /* 319 * Create our extend array for storing the devices we attach to. 320 */ 321 cdperiphs = cam_extend_new(); 322 if (cdperiphs == NULL) { 323 printf("cd: Failed to alloc extend array!\n"); 324 return; 325 } 326 327 /* 328 * Install a global async callback. This callback will 329 * receive async callbacks like "new device found". 330 */ 331 status = xpt_create_path(&path, /*periph*/NULL, CAM_XPT_PATH_ID, 332 CAM_TARGET_WILDCARD, CAM_LUN_WILDCARD); 333 334 if (status == CAM_REQ_CMP) { 335 struct ccb_setasync csa; 336 337 xpt_setup_ccb(&csa.ccb_h, path, /*priority*/5); 338 csa.ccb_h.func_code = XPT_SASYNC_CB; 339 csa.event_enable = AC_FOUND_DEVICE; 340 csa.callback = cdasync; 341 csa.callback_arg = NULL; 342 xpt_action((union ccb *)&csa); 343 status = csa.ccb_h.status; 344 xpt_free_path(path); 345 } 346 347 if (status != CAM_REQ_CMP) { 348 printf("cd: Failed to attach master async callback " 349 "due to status 0x%x!\n", status); 350 } 351} 352 353static void 354cdoninvalidate(struct cam_periph *periph) 355{ 356 int s; 357 struct cd_softc *softc; 358 struct bio *q_bp; 359 struct ccb_setasync csa; 360 361 softc = (struct cd_softc *)periph->softc; 362 363 /* 364 * De-register any async callbacks. 365 */ 366 xpt_setup_ccb(&csa.ccb_h, periph->path, 367 /* priority */ 5); 368 csa.ccb_h.func_code = XPT_SASYNC_CB; 369 csa.event_enable = 0; 370 csa.callback = cdasync; 371 csa.callback_arg = periph; 372 xpt_action((union ccb *)&csa); 373 374 softc->flags |= CD_FLAG_INVALID; 375 376 /* 377 * Although the oninvalidate() routines are always called at 378 * splsoftcam, we need to be at splbio() here to keep the buffer 379 * queue from being modified while we traverse it. 380 */ 381 s = splbio(); 382 383 /* 384 * Return all queued I/O with ENXIO. 385 * XXX Handle any transactions queued to the card 386 * with XPT_ABORT_CCB. 387 */ 388 while ((q_bp = bioq_first(&softc->bio_queue)) != NULL){ 389 bioq_remove(&softc->bio_queue, q_bp); 390 q_bp->bio_resid = q_bp->bio_bcount; 391 q_bp->bio_error = ENXIO; 392 q_bp->bio_flags |= BIO_ERROR; 393 biodone(q_bp); 394 } 395 splx(s); 396 397 /* 398 * If this device is part of a changer, and it was scheduled 399 * to run, remove it from the run queue since we just nuked 400 * all of its scheduled I/O. 401 */ 402 if ((softc->flags & CD_FLAG_CHANGER) 403 && (softc->pinfo.index != CAM_UNQUEUED_INDEX)) 404 camq_remove(&softc->changer->devq, softc->pinfo.index); 405 406 xpt_print_path(periph->path); 407 printf("lost device\n"); 408} 409 410static void 411cdcleanup(struct cam_periph *periph) 412{ 413 struct cd_softc *softc; 414 int s; 415 416 softc = (struct cd_softc *)periph->softc; 417 418 xpt_print_path(periph->path); 419 printf("removing device entry\n"); 420 421 s = splsoftcam(); 422 /* 423 * In the queued, non-active case, the device in question 424 * has already been removed from the changer run queue. Since this 425 * device is active, we need to de-activate it, and schedule 426 * another device to run. (if there is another one to run) 427 */ 428 if ((softc->flags & CD_FLAG_CHANGER) 429 && (softc->flags & CD_FLAG_ACTIVE)) { 430 431 /* 432 * The purpose of the short timeout is soley to determine 433 * whether the current device has finished or not. Well, 434 * since we're removing the active device, we know that it 435 * is finished. So, get rid of the short timeout. 436 * Otherwise, if we're in the time period before the short 437 * timeout fires, and there are no other devices in the 438 * queue to run, there won't be any other device put in the 439 * active slot. i.e., when we call cdrunchangerqueue() 440 * below, it won't do anything. Then, when the short 441 * timeout fires, it'll look at the "current device", which 442 * we are free below, and possibly panic the kernel on a 443 * bogus pointer reference. 444 * 445 * The long timeout doesn't really matter, since we 446 * decrement the qfrozen_cnt to indicate that there is 447 * nothing in the active slot now. Therefore, there won't 448 * be any bogus pointer references there. 449 */ 450 if (softc->changer->flags & CHANGER_SHORT_TMOUT_SCHED) { 451 untimeout(cdshorttimeout, softc->changer, 452 softc->changer->short_handle); 453 softc->changer->flags &= ~CHANGER_SHORT_TMOUT_SCHED; 454 } 455 softc->changer->devq.qfrozen_cnt--; 456 softc->changer->flags |= CHANGER_MANUAL_CALL; 457 cdrunchangerqueue(softc->changer); 458 } 459 460 /* 461 * If we're removing the last device on the changer, go ahead and 462 * remove the changer device structure. 463 */ 464 if ((softc->flags & CD_FLAG_CHANGER) 465 && (--softc->changer->num_devices == 0)) { 466 467 /* 468 * Theoretically, there shouldn't be any timeouts left, but 469 * I'm not completely sure that that will be the case. So, 470 * it won't hurt to check and see if there are any left. 471 */ 472 if (softc->changer->flags & CHANGER_TIMEOUT_SCHED) { 473 untimeout(cdrunchangerqueue, softc->changer, 474 softc->changer->long_handle); 475 softc->changer->flags &= ~CHANGER_TIMEOUT_SCHED; 476 } 477 478 if (softc->changer->flags & CHANGER_SHORT_TMOUT_SCHED) { 479 untimeout(cdshorttimeout, softc->changer, 480 softc->changer->short_handle); 481 softc->changer->flags &= ~CHANGER_SHORT_TMOUT_SCHED; 482 } 483 484 STAILQ_REMOVE(&changerq, softc->changer, cdchanger, 485 changer_links); 486 xpt_print_path(periph->path); 487 printf("removing changer entry\n"); 488 free(softc->changer, M_DEVBUF); 489 num_changers--; 490 } 491 devstat_remove_entry(&softc->device_stats); 492 cam_extend_release(cdperiphs, periph->unit_number); 493 free(softc, M_DEVBUF); 494 splx(s); 495} 496 497static void 498cdasync(void *callback_arg, u_int32_t code, 499 struct cam_path *path, void *arg) 500{ 501 struct cam_periph *periph; 502 503 periph = (struct cam_periph *)callback_arg; 504 switch (code) { 505 case AC_FOUND_DEVICE: 506 { 507 struct ccb_getdev *cgd; 508 cam_status status; 509 510 cgd = (struct ccb_getdev *)arg; 511 512 if (SID_TYPE(&cgd->inq_data) != T_CDROM 513 && SID_TYPE(&cgd->inq_data) != T_WORM) 514 break; 515 516 /* 517 * Allocate a peripheral instance for 518 * this device and start the probe 519 * process. 520 */ 521 status = cam_periph_alloc(cdregister, cdoninvalidate, 522 cdcleanup, cdstart, 523 "cd", CAM_PERIPH_BIO, 524 cgd->ccb_h.path, cdasync, 525 AC_FOUND_DEVICE, cgd); 526 527 if (status != CAM_REQ_CMP 528 && status != CAM_REQ_INPROG) 529 printf("cdasync: Unable to attach new device " 530 "due to status 0x%x\n", status); 531 532 break; 533 } 534 case AC_SENT_BDR: 535 case AC_BUS_RESET: 536 { 537 struct cd_softc *softc; 538 struct ccb_hdr *ccbh; 539 int s; 540 541 softc = (struct cd_softc *)periph->softc; 542 s = splsoftcam(); 543 /* 544 * Don't fail on the expected unit attention 545 * that will occur. 546 */ 547 softc->flags |= CD_FLAG_RETRY_UA; 548 for (ccbh = LIST_FIRST(&softc->pending_ccbs); 549 ccbh != NULL; ccbh = LIST_NEXT(ccbh, periph_links.le)) 550 ccbh->ccb_state |= CD_CCB_RETRY_UA; 551 splx(s); 552 /* FALLTHROUGH */ 553 } 554 default: 555 cam_periph_async(periph, code, path, arg); 556 break; 557 } 558} 559 560static cam_status 561cdregister(struct cam_periph *periph, void *arg) 562{ 563 struct cd_softc *softc; 564 struct ccb_setasync csa; 565 struct ccb_getdev *cgd; 566 caddr_t match; 567 568 cgd = (struct ccb_getdev *)arg; 569 if (periph == NULL) { 570 printf("cdregister: periph was NULL!!\n"); 571 return(CAM_REQ_CMP_ERR); 572 } 573 if (cgd == NULL) { 574 printf("cdregister: no getdev CCB, can't register device\n"); 575 return(CAM_REQ_CMP_ERR); 576 } 577 578 softc = (struct cd_softc *)malloc(sizeof(*softc),M_DEVBUF,M_NOWAIT); 579 580 if (softc == NULL) { 581 printf("cdregister: Unable to probe new device. " 582 "Unable to allocate softc\n"); 583 return(CAM_REQ_CMP_ERR); 584 } 585 586 bzero(softc, sizeof(*softc)); 587 LIST_INIT(&softc->pending_ccbs); 588 softc->state = CD_STATE_PROBE; 589 bioq_init(&softc->bio_queue); 590 if (SID_IS_REMOVABLE(&cgd->inq_data)) 591 softc->flags |= CD_FLAG_DISC_REMOVABLE; 592 if ((cgd->inq_data.flags & SID_CmdQue) != 0) 593 softc->flags |= CD_FLAG_TAGGED_QUEUING; 594 595 periph->softc = softc; 596 softc->periph = periph; 597 598 cam_extend_set(cdperiphs, periph->unit_number, periph); 599 600 /* 601 * See if this device has any quirks. 602 */ 603 match = cam_quirkmatch((caddr_t)&cgd->inq_data, 604 (caddr_t)cd_quirk_table, 605 sizeof(cd_quirk_table)/sizeof(*cd_quirk_table), 606 sizeof(*cd_quirk_table), scsi_inquiry_match); 607 608 if (match != NULL) 609 softc->quirks = ((struct cd_quirk_entry *)match)->quirks; 610 else 611 softc->quirks = CD_Q_NONE; 612 613 /* 614 * We need to register the statistics structure for this device, 615 * but we don't have the blocksize yet for it. So, we register 616 * the structure and indicate that we don't have the blocksize 617 * yet. Unlike other SCSI peripheral drivers, we explicitly set 618 * the device type here to be CDROM, rather than just ORing in 619 * the device type. This is because this driver can attach to either 620 * CDROM or WORM devices, and we want this peripheral driver to 621 * show up in the devstat list as a CD peripheral driver, not a 622 * WORM peripheral driver. WORM drives will also have the WORM 623 * driver attached to them. 624 */ 625 devstat_add_entry(&softc->device_stats, "cd", 626 periph->unit_number, 0, 627 DEVSTAT_BS_UNAVAILABLE, 628 DEVSTAT_TYPE_CDROM | DEVSTAT_TYPE_IF_SCSI, 629 DEVSTAT_PRIORITY_CD); 630 disk_create(periph->unit_number, &softc->disk, 631 DSO_ONESLICE | DSO_COMPATLABEL, 632 &cd_cdevsw, &cddisk_cdevsw); 633 634 /* 635 * Add an async callback so that we get 636 * notified if this device goes away. 637 */ 638 xpt_setup_ccb(&csa.ccb_h, periph->path, 639 /* priority */ 5); 640 csa.ccb_h.func_code = XPT_SASYNC_CB; 641 csa.event_enable = AC_SENT_BDR | AC_BUS_RESET | AC_LOST_DEVICE; 642 csa.callback = cdasync; 643 csa.callback_arg = periph; 644 xpt_action((union ccb *)&csa); 645 646 /* 647 * If the target lun is greater than 0, we most likely have a CD 648 * changer device. Check the quirk entries as well, though, just 649 * in case someone has a CD tower with one lun per drive or 650 * something like that. Also, if we know up front that a 651 * particular device is a changer, we can mark it as such starting 652 * with lun 0, instead of lun 1. It shouldn't be necessary to have 653 * a quirk entry to define something as a changer, however. 654 */ 655 if (((cgd->ccb_h.target_lun > 0) 656 && ((softc->quirks & CD_Q_NO_CHANGER) == 0)) 657 || ((softc->quirks & CD_Q_CHANGER) != 0)) { 658 struct cdchanger *nchanger; 659 struct cam_periph *nperiph; 660 struct cam_path *path; 661 cam_status status; 662 int found; 663 664 /* Set the changer flag in the current device's softc */ 665 softc->flags |= CD_FLAG_CHANGER; 666 667 if (num_changers == 0) 668 STAILQ_INIT(&changerq); 669 670 /* 671 * Now, look around for an existing changer device with the 672 * same path and target ID as the current device. 673 */ 674 for (found = 0, 675 nchanger = (struct cdchanger *)STAILQ_FIRST(&changerq); 676 nchanger != NULL; 677 nchanger = STAILQ_NEXT(nchanger, changer_links)){ 678 if ((nchanger->path_id == cgd->ccb_h.path_id) 679 && (nchanger->target_id == cgd->ccb_h.target_id)) { 680 found = 1; 681 break; 682 } 683 } 684 685 /* 686 * If we found a matching entry, just add this device to 687 * the list of devices on this changer. 688 */ 689 if (found == 1) { 690 struct chdevlist *chlunhead; 691 692 chlunhead = &nchanger->chluns; 693 694 /* 695 * XXX KDM look at consolidating this code with the 696 * code below in a separate function. 697 */ 698 699 /* 700 * Create a path with lun id 0, and see if we can 701 * find a matching device 702 */ 703 status = xpt_create_path(&path, /*periph*/ periph, 704 cgd->ccb_h.path_id, 705 cgd->ccb_h.target_id, 0); 706 707 if ((status == CAM_REQ_CMP) 708 && ((nperiph = cam_periph_find(path, "cd")) != NULL)){ 709 struct cd_softc *nsoftc; 710 711 nsoftc = (struct cd_softc *)nperiph->softc; 712 713 if ((nsoftc->flags & CD_FLAG_CHANGER) == 0){ 714 nsoftc->flags |= CD_FLAG_CHANGER; 715 nchanger->num_devices++; 716 if (camq_resize(&nchanger->devq, 717 nchanger->num_devices)!=CAM_REQ_CMP){ 718 printf("cdregister: " 719 "camq_resize " 720 "failed, changer " 721 "support may " 722 "be messed up\n"); 723 } 724 nsoftc->changer = nchanger; 725 nsoftc->pinfo.index =CAM_UNQUEUED_INDEX; 726 727 STAILQ_INSERT_TAIL(&nchanger->chluns, 728 nsoftc,changer_links); 729 } 730 xpt_free_path(path); 731 } else if (status == CAM_REQ_CMP) 732 xpt_free_path(path); 733 else { 734 printf("cdregister: unable to allocate path\n" 735 "cdregister: changer support may be " 736 "broken\n"); 737 } 738 739 nchanger->num_devices++; 740 741 softc->changer = nchanger; 742 softc->pinfo.index = CAM_UNQUEUED_INDEX; 743 744 if (camq_resize(&nchanger->devq, 745 nchanger->num_devices) != CAM_REQ_CMP) { 746 printf("cdregister: camq_resize " 747 "failed, changer support may " 748 "be messed up\n"); 749 } 750 751 STAILQ_INSERT_TAIL(chlunhead, softc, changer_links); 752 } 753 /* 754 * In this case, we don't already have an entry for this 755 * particular changer, so we need to create one, add it to 756 * the queue, and queue this device on the list for this 757 * changer. Before we queue this device, however, we need 758 * to search for lun id 0 on this target, and add it to the 759 * queue first, if it exists. (and if it hasn't already 760 * been marked as part of the changer.) 761 */ 762 else { 763 nchanger = malloc(sizeof(struct cdchanger), 764 M_DEVBUF, M_NOWAIT); 765 766 if (nchanger == NULL) { 767 softc->flags &= ~CD_FLAG_CHANGER; 768 printf("cdregister: unable to malloc " 769 "changer structure\ncdregister: " 770 "changer support disabled\n"); 771 772 /* 773 * Yes, gotos can be gross but in this case 774 * I think it's justified.. 775 */ 776 goto cdregisterexit; 777 } 778 779 /* zero the structure */ 780 bzero(nchanger, sizeof(struct cdchanger)); 781 782 if (camq_init(&nchanger->devq, 1) != 0) { 783 softc->flags &= ~CD_FLAG_CHANGER; 784 printf("cdregister: changer support " 785 "disabled\n"); 786 goto cdregisterexit; 787 } 788 789 num_changers++; 790 791 nchanger->path_id = cgd->ccb_h.path_id; 792 nchanger->target_id = cgd->ccb_h.target_id; 793 794 /* this is superfluous, but it makes things clearer */ 795 nchanger->num_devices = 0; 796 797 STAILQ_INIT(&nchanger->chluns); 798 799 STAILQ_INSERT_TAIL(&changerq, nchanger, 800 changer_links); 801 802 /* 803 * Create a path with lun id 0, and see if we can 804 * find a matching device 805 */ 806 status = xpt_create_path(&path, /*periph*/ periph, 807 cgd->ccb_h.path_id, 808 cgd->ccb_h.target_id, 0); 809 810 /* 811 * If we were able to allocate the path, and if we 812 * find a matching device and it isn't already 813 * marked as part of a changer, then we add it to 814 * the current changer. 815 */ 816 if ((status == CAM_REQ_CMP) 817 && ((nperiph = cam_periph_find(path, "cd")) != NULL) 818 && ((((struct cd_softc *)periph->softc)->flags & 819 CD_FLAG_CHANGER) == 0)) { 820 struct cd_softc *nsoftc; 821 822 nsoftc = (struct cd_softc *)nperiph->softc; 823 824 nsoftc->flags |= CD_FLAG_CHANGER; 825 nchanger->num_devices++; 826 if (camq_resize(&nchanger->devq, 827 nchanger->num_devices) != CAM_REQ_CMP) { 828 printf("cdregister: camq_resize " 829 "failed, changer support may " 830 "be messed up\n"); 831 } 832 nsoftc->changer = nchanger; 833 nsoftc->pinfo.index = CAM_UNQUEUED_INDEX; 834 835 STAILQ_INSERT_TAIL(&nchanger->chluns, 836 nsoftc, changer_links); 837 xpt_free_path(path); 838 } else if (status == CAM_REQ_CMP) 839 xpt_free_path(path); 840 else { 841 printf("cdregister: unable to allocate path\n" 842 "cdregister: changer support may be " 843 "broken\n"); 844 } 845 846 softc->changer = nchanger; 847 softc->pinfo.index = CAM_UNQUEUED_INDEX; 848 nchanger->num_devices++; 849 if (camq_resize(&nchanger->devq, 850 nchanger->num_devices) != CAM_REQ_CMP) { 851 printf("cdregister: camq_resize " 852 "failed, changer support may " 853 "be messed up\n"); 854 } 855 STAILQ_INSERT_TAIL(&nchanger->chluns, softc, 856 changer_links); 857 } 858 } 859 860cdregisterexit: 861 862 /* Lock this peripheral until we are setup */ 863 /* Can't block */ 864 cam_periph_lock(periph, PRIBIO); 865 866 if ((softc->flags & CD_FLAG_CHANGER) == 0) 867 xpt_schedule(periph, /*priority*/5); 868 else 869 cdschedule(periph, /*priority*/ 5); 870 871 return(CAM_REQ_CMP); 872} 873 874static int 875cdopen(dev_t dev, int flags, int fmt, struct proc *p) 876{ 877 struct disklabel *label; 878 struct cam_periph *periph; 879 struct cd_softc *softc; 880 struct ccb_getdev cgd; 881 u_int32_t size; 882 int unit, error; 883 int s; 884 885 unit = dkunit(dev); 886 periph = cam_extend_get(cdperiphs, unit); 887 888 if (periph == NULL) 889 return (ENXIO); 890 891 softc = (struct cd_softc *)periph->softc; 892 893 /* 894 * Grab splsoftcam and hold it until we lock the peripheral. 895 */ 896 s = splsoftcam(); 897 if (softc->flags & CD_FLAG_INVALID) { 898 splx(s); 899 return(ENXIO); 900 } 901 902 if ((error = cam_periph_lock(periph, PRIBIO | PCATCH)) != 0) { 903 splx(s); 904 return (error); 905 } 906 907 splx(s); 908 909 if (cam_periph_acquire(periph) != CAM_REQ_CMP) 910 return(ENXIO); 911 912 cdprevent(periph, PR_PREVENT); 913 914 /* find out the size */ 915 if ((error = cdsize(dev, &size)) != 0) { 916 cdprevent(periph, PR_ALLOW); 917 cam_periph_unlock(periph); 918 cam_periph_release(periph); 919 return(error); 920 } 921 922 /* 923 * Build prototype label for whole disk. 924 * Should take information about different data tracks from the 925 * TOC and put it in the partition table. 926 */ 927 label = &softc->disk.d_label; 928 bzero(label, sizeof(*label)); 929 label->d_type = DTYPE_SCSI; 930 931 /* 932 * Grab the inquiry data to get the vendor and product names. 933 * Put them in the typename and packname for the label. 934 */ 935 xpt_setup_ccb(&cgd.ccb_h, periph->path, /*priority*/ 1); 936 cgd.ccb_h.func_code = XPT_GDEV_TYPE; 937 xpt_action((union ccb *)&cgd); 938 939 strncpy(label->d_typename, cgd.inq_data.vendor, 940 min(SID_VENDOR_SIZE, sizeof(label->d_typename))); 941 strncpy(label->d_packname, cgd.inq_data.product, 942 min(SID_PRODUCT_SIZE, sizeof(label->d_packname))); 943 944 label->d_secsize = softc->params.blksize; 945 label->d_secperunit = softc->params.disksize; 946 label->d_flags = D_REMOVABLE; 947 /* 948 * Make partition 'a' cover the whole disk. This is a temporary 949 * compatibility hack. The 'a' partition should not exist, so 950 * the slice code won't create it. The slice code will make 951 * partition (RAW_PART + 'a') cover the whole disk and fill in 952 * some more defaults. 953 */ 954 label->d_partitions[0].p_size = label->d_secperunit; 955 label->d_partitions[0].p_fstype = FS_OTHER; 956 957 /* 958 * We unconditionally (re)set the blocksize each time the 959 * CD device is opened. This is because the CD can change, 960 * and therefore the blocksize might change. 961 * XXX problems here if some slice or partition is still 962 * open with the old size? 963 */ 964 if ((softc->device_stats.flags & DEVSTAT_BS_UNAVAILABLE) != 0) 965 softc->device_stats.flags &= ~DEVSTAT_BS_UNAVAILABLE; 966 softc->device_stats.block_size = softc->params.blksize; 967 968 cam_periph_unlock(periph); 969 970 CAM_DEBUG(periph->path, CAM_DEBUG_TRACE, ("leaving cdopen\n")); 971 972 return (error); 973} 974 975static int 976cdclose(dev_t dev, int flag, int fmt, struct proc *p) 977{ 978 struct cam_periph *periph; 979 struct cd_softc *softc; 980 int unit, error; 981 982 unit = dkunit(dev); 983 periph = cam_extend_get(cdperiphs, unit); 984 if (periph == NULL) 985 return (ENXIO); 986 987 softc = (struct cd_softc *)periph->softc; 988 989 if ((error = cam_periph_lock(periph, PRIBIO)) != 0) 990 return (error); 991 992 if ((softc->flags & CD_FLAG_DISC_REMOVABLE) != 0) 993 cdprevent(periph, PR_ALLOW); 994 995 /* 996 * Since we're closing this CD, mark the blocksize as unavailable. 997 * It will be marked as available whence the CD is opened again. 998 */ 999 softc->device_stats.flags |= DEVSTAT_BS_UNAVAILABLE; 1000 1001 cam_periph_unlock(periph); 1002 cam_periph_release(periph); 1003 1004 return (0); 1005} 1006 1007static void 1008cdshorttimeout(void *arg) 1009{ 1010 struct cdchanger *changer; 1011 int s; 1012 1013 s = splsoftcam(); 1014 1015 changer = (struct cdchanger *)arg; 1016 1017 /* Always clear the short timeout flag, since that's what we're in */ 1018 changer->flags &= ~CHANGER_SHORT_TMOUT_SCHED; 1019 1020 /* 1021 * Check to see if there is any more pending or outstanding I/O for 1022 * this device. If not, move it out of the active slot. 1023 */ 1024 if ((bioq_first(&changer->cur_device->bio_queue) == NULL) 1025 && (changer->cur_device->device_stats.busy_count == 0)) { 1026 changer->flags |= CHANGER_MANUAL_CALL; 1027 cdrunchangerqueue(changer); 1028 } 1029 1030 splx(s); 1031} 1032 1033/* 1034 * This is a wrapper for xpt_schedule. It only applies to changers. 1035 */ 1036static void 1037cdschedule(struct cam_periph *periph, int priority) 1038{ 1039 struct cd_softc *softc; 1040 int s; 1041 1042 s = splsoftcam(); 1043 1044 softc = (struct cd_softc *)periph->softc; 1045 1046 /* 1047 * If this device isn't currently queued, and if it isn't 1048 * the active device, then we queue this device and run the 1049 * changer queue if there is no timeout scheduled to do it. 1050 * If this device is the active device, just schedule it 1051 * to run again. If this device is queued, there should be 1052 * a timeout in place already that will make sure it runs. 1053 */ 1054 if ((softc->pinfo.index == CAM_UNQUEUED_INDEX) 1055 && ((softc->flags & CD_FLAG_ACTIVE) == 0)) { 1056 /* 1057 * We don't do anything with the priority here. 1058 * This is strictly a fifo queue. 1059 */ 1060 softc->pinfo.priority = 1; 1061 softc->pinfo.generation = ++softc->changer->devq.generation; 1062 camq_insert(&softc->changer->devq, (cam_pinfo *)softc); 1063 1064 /* 1065 * Since we just put a device in the changer queue, 1066 * check and see if there is a timeout scheduled for 1067 * this changer. If so, let the timeout handle 1068 * switching this device into the active slot. If 1069 * not, manually call the timeout routine to 1070 * bootstrap things. 1071 */ 1072 if (((softc->changer->flags & CHANGER_TIMEOUT_SCHED)==0) 1073 && ((softc->changer->flags & CHANGER_NEED_TIMEOUT)==0) 1074 && ((softc->changer->flags & CHANGER_SHORT_TMOUT_SCHED)==0)){ 1075 softc->changer->flags |= CHANGER_MANUAL_CALL; 1076 cdrunchangerqueue(softc->changer); 1077 } 1078 } else if ((softc->flags & CD_FLAG_ACTIVE) 1079 && ((softc->flags & CD_FLAG_SCHED_ON_COMP) == 0)) 1080 xpt_schedule(periph, priority); 1081 1082 splx(s); 1083 1084} 1085 1086static void 1087cdrunchangerqueue(void *arg) 1088{ 1089 struct cd_softc *softc; 1090 struct cdchanger *changer; 1091 int called_from_timeout; 1092 int s; 1093 1094 s = splsoftcam(); 1095 1096 changer = (struct cdchanger *)arg; 1097 1098 /* 1099 * If we have NOT been called from cdstrategy() or cddone(), and 1100 * instead from a timeout routine, go ahead and clear the 1101 * timeout flag. 1102 */ 1103 if ((changer->flags & CHANGER_MANUAL_CALL) == 0) { 1104 changer->flags &= ~CHANGER_TIMEOUT_SCHED; 1105 called_from_timeout = 1; 1106 } else 1107 called_from_timeout = 0; 1108 1109 /* Always clear the manual call flag */ 1110 changer->flags &= ~CHANGER_MANUAL_CALL; 1111 1112 /* nothing to do if the queue is empty */ 1113 if (changer->devq.entries <= 0) { 1114 splx(s); 1115 return; 1116 } 1117 1118 /* 1119 * If the changer queue is frozen, that means we have an active 1120 * device. 1121 */ 1122 if (changer->devq.qfrozen_cnt > 0) { 1123 1124 if (changer->cur_device->device_stats.busy_count > 0) { 1125 changer->cur_device->flags |= CD_FLAG_SCHED_ON_COMP; 1126 changer->cur_device->bufs_left = 1127 changer->cur_device->device_stats.busy_count; 1128 if (called_from_timeout) { 1129 changer->long_handle = 1130 timeout(cdrunchangerqueue, changer, 1131 changer_max_busy_seconds * hz); 1132 changer->flags |= CHANGER_TIMEOUT_SCHED; 1133 } 1134 splx(s); 1135 return; 1136 } 1137 1138 /* 1139 * We always need to reset the frozen count and clear the 1140 * active flag. 1141 */ 1142 changer->devq.qfrozen_cnt--; 1143 changer->cur_device->flags &= ~CD_FLAG_ACTIVE; 1144 changer->cur_device->flags &= ~CD_FLAG_SCHED_ON_COMP; 1145 1146 /* 1147 * Check to see whether the current device has any I/O left 1148 * to do. If so, requeue it at the end of the queue. If 1149 * not, there is no need to requeue it. 1150 */ 1151 if (bioq_first(&changer->cur_device->bio_queue) != NULL) { 1152 1153 changer->cur_device->pinfo.generation = 1154 ++changer->devq.generation; 1155 camq_insert(&changer->devq, 1156 (cam_pinfo *)changer->cur_device); 1157 } 1158 } 1159 1160 softc = (struct cd_softc *)camq_remove(&changer->devq, CAMQ_HEAD); 1161 1162 changer->cur_device = softc; 1163 1164 changer->devq.qfrozen_cnt++; 1165 softc->flags |= CD_FLAG_ACTIVE; 1166 1167 /* Just in case this device is waiting */ 1168 wakeup(&softc->changer); 1169 xpt_schedule(softc->periph, /*priority*/ 1); 1170 1171 /* 1172 * Get rid of any pending timeouts, and set a flag to schedule new 1173 * ones so this device gets its full time quantum. 1174 */ 1175 if (changer->flags & CHANGER_TIMEOUT_SCHED) { 1176 untimeout(cdrunchangerqueue, changer, changer->long_handle); 1177 changer->flags &= ~CHANGER_TIMEOUT_SCHED; 1178 } 1179 1180 if (changer->flags & CHANGER_SHORT_TMOUT_SCHED) { 1181 untimeout(cdshorttimeout, changer, changer->short_handle); 1182 changer->flags &= ~CHANGER_SHORT_TMOUT_SCHED; 1183 } 1184 1185 /* 1186 * We need to schedule timeouts, but we only do this after the 1187 * first transaction has completed. This eliminates the changer 1188 * switch time. 1189 */ 1190 changer->flags |= CHANGER_NEED_TIMEOUT; 1191 1192 splx(s); 1193} 1194 1195static void 1196cdchangerschedule(struct cd_softc *softc) 1197{ 1198 struct cdchanger *changer; 1199 int s; 1200 1201 s = splsoftcam(); 1202 1203 changer = softc->changer; 1204 1205 /* 1206 * If this is a changer, and this is the current device, 1207 * and this device has at least the minimum time quantum to 1208 * run, see if we can switch it out. 1209 */ 1210 if ((softc->flags & CD_FLAG_ACTIVE) 1211 && ((changer->flags & CHANGER_SHORT_TMOUT_SCHED) == 0) 1212 && ((changer->flags & CHANGER_NEED_TIMEOUT) == 0)) { 1213 /* 1214 * We try three things here. The first is that we 1215 * check to see whether the schedule on completion 1216 * flag is set. If it is, we decrement the number 1217 * of buffers left, and if it's zero, we reschedule. 1218 * Next, we check to see whether the pending buffer 1219 * queue is empty and whether there are no 1220 * outstanding transactions. If so, we reschedule. 1221 * Next, we see if the pending buffer queue is empty. 1222 * If it is, we set the number of buffers left to 1223 * the current active buffer count and set the 1224 * schedule on complete flag. 1225 */ 1226 if (softc->flags & CD_FLAG_SCHED_ON_COMP) { 1227 if (--softc->bufs_left == 0) { 1228 softc->changer->flags |= 1229 CHANGER_MANUAL_CALL; 1230 softc->flags &= ~CD_FLAG_SCHED_ON_COMP; 1231 cdrunchangerqueue(softc->changer); 1232 } 1233 } else if ((bioq_first(&softc->bio_queue) == NULL) 1234 && (softc->device_stats.busy_count == 0)) { 1235 softc->changer->flags |= CHANGER_MANUAL_CALL; 1236 cdrunchangerqueue(softc->changer); 1237 } 1238 } else if ((softc->changer->flags & CHANGER_NEED_TIMEOUT) 1239 && (softc->flags & CD_FLAG_ACTIVE)) { 1240 1241 /* 1242 * Now that the first transaction to this 1243 * particular device has completed, we can go ahead 1244 * and schedule our timeouts. 1245 */ 1246 if ((changer->flags & CHANGER_TIMEOUT_SCHED) == 0) { 1247 changer->long_handle = 1248 timeout(cdrunchangerqueue, changer, 1249 changer_max_busy_seconds * hz); 1250 changer->flags |= CHANGER_TIMEOUT_SCHED; 1251 } else 1252 printf("cdchangerschedule: already have a long" 1253 " timeout!\n"); 1254 1255 if ((changer->flags & CHANGER_SHORT_TMOUT_SCHED) == 0) { 1256 changer->short_handle = 1257 timeout(cdshorttimeout, changer, 1258 changer_min_busy_seconds * hz); 1259 changer->flags |= CHANGER_SHORT_TMOUT_SCHED; 1260 } else 1261 printf("cdchangerschedule: already have a short " 1262 "timeout!\n"); 1263 1264 /* 1265 * We just scheduled timeouts, no need to schedule 1266 * more. 1267 */ 1268 changer->flags &= ~CHANGER_NEED_TIMEOUT; 1269 1270 } 1271 splx(s); 1272} 1273 1274static int 1275cdrunccb(union ccb *ccb, int (*error_routine)(union ccb *ccb, 1276 u_int32_t cam_flags, 1277 u_int32_t sense_flags), 1278 u_int32_t cam_flags, u_int32_t sense_flags) 1279{ 1280 struct cd_softc *softc; 1281 struct cam_periph *periph; 1282 int error; 1283 1284 periph = xpt_path_periph(ccb->ccb_h.path); 1285 softc = (struct cd_softc *)periph->softc; 1286 1287 error = cam_periph_runccb(ccb, error_routine, cam_flags, sense_flags, 1288 &softc->device_stats); 1289 1290 if (softc->flags & CD_FLAG_CHANGER) 1291 cdchangerschedule(softc); 1292 1293 return(error); 1294} 1295 1296static union ccb * 1297cdgetccb(struct cam_periph *periph, u_int32_t priority) 1298{ 1299 struct cd_softc *softc; 1300 int s; 1301 1302 softc = (struct cd_softc *)periph->softc; 1303 1304 if (softc->flags & CD_FLAG_CHANGER) { 1305 1306 s = splsoftcam(); 1307 1308 /* 1309 * This should work the first time this device is woken up, 1310 * but just in case it doesn't, we use a while loop. 1311 */ 1312 while ((softc->flags & CD_FLAG_ACTIVE) == 0) { 1313 /* 1314 * If this changer isn't already queued, queue it up. 1315 */ 1316 if (softc->pinfo.index == CAM_UNQUEUED_INDEX) { 1317 softc->pinfo.priority = 1; 1318 softc->pinfo.generation = 1319 ++softc->changer->devq.generation; 1320 camq_insert(&softc->changer->devq, 1321 (cam_pinfo *)softc); 1322 } 1323 if (((softc->changer->flags & CHANGER_TIMEOUT_SCHED)==0) 1324 && ((softc->changer->flags & CHANGER_NEED_TIMEOUT)==0) 1325 && ((softc->changer->flags 1326 & CHANGER_SHORT_TMOUT_SCHED)==0)) { 1327 softc->changer->flags |= CHANGER_MANUAL_CALL; 1328 cdrunchangerqueue(softc->changer); 1329 } else 1330 tsleep(&softc->changer, PRIBIO, "cgticb", 0); 1331 } 1332 splx(s); 1333 } 1334 return(cam_periph_getccb(periph, priority)); 1335} 1336 1337 1338/* 1339 * Actually translate the requested transfer into one the physical driver 1340 * can understand. The transfer is described by a buf and will include 1341 * only one physical transfer. 1342 */ 1343static void 1344cdstrategy(struct bio *bp) 1345{ 1346 struct cam_periph *periph; 1347 struct cd_softc *softc; 1348 u_int unit, part; 1349 int s; 1350 1351 unit = dkunit(bp->bio_dev); 1352 part = dkpart(bp->bio_dev); 1353 periph = cam_extend_get(cdperiphs, unit); 1354 if (periph == NULL) { 1355 bp->bio_error = ENXIO; 1356 goto bad; 1357 } 1358 1359 CAM_DEBUG(periph->path, CAM_DEBUG_TRACE, ("entering cdstrategy\n")); 1360 1361 softc = (struct cd_softc *)periph->softc; 1362 1363 /* 1364 * Mask interrupts so that the pack cannot be invalidated until 1365 * after we are in the queue. Otherwise, we might not properly 1366 * clean up one of the buffers. 1367 */ 1368 s = splbio(); 1369 1370 /* 1371 * If the device has been made invalid, error out 1372 */ 1373 if ((softc->flags & CD_FLAG_INVALID)) { 1374 splx(s); 1375 bp->bio_error = ENXIO; 1376 goto bad; 1377 } 1378 1379 /* 1380 * Place it in the queue of disk activities for this disk 1381 */ 1382 bioqdisksort(&softc->bio_queue, bp); 1383 1384 splx(s); 1385 1386 /* 1387 * Schedule ourselves for performing the work. We do things 1388 * differently for changers. 1389 */ 1390 if ((softc->flags & CD_FLAG_CHANGER) == 0) 1391 xpt_schedule(periph, /* XXX priority */1); 1392 else 1393 cdschedule(periph, /* priority */ 1); 1394 1395 return; 1396bad: 1397 bp->bio_flags |= BIO_ERROR; 1398 /* 1399 * Correctly set the buf to indicate a completed xfer 1400 */ 1401 bp->bio_resid = bp->bio_bcount; 1402 biodone(bp); 1403 return; 1404} 1405 1406static void 1407cdstart(struct cam_periph *periph, union ccb *start_ccb) 1408{ 1409 struct cd_softc *softc; 1410 struct bio *bp; 1411 struct ccb_scsiio *csio; 1412 struct scsi_read_capacity_data *rcap; 1413 int s; 1414 1415 softc = (struct cd_softc *)periph->softc; 1416 1417 CAM_DEBUG(periph->path, CAM_DEBUG_TRACE, ("entering cdstart\n")); 1418 1419 switch (softc->state) { 1420 case CD_STATE_NORMAL: 1421 { 1422 int oldspl; 1423 1424 s = splbio(); 1425 bp = bioq_first(&softc->bio_queue); 1426 if (periph->immediate_priority <= periph->pinfo.priority) { 1427 start_ccb->ccb_h.ccb_state = CD_CCB_WAITING; 1428 1429 SLIST_INSERT_HEAD(&periph->ccb_list, &start_ccb->ccb_h, 1430 periph_links.sle); 1431 periph->immediate_priority = CAM_PRIORITY_NONE; 1432 splx(s); 1433 wakeup(&periph->ccb_list); 1434 } else if (bp == NULL) { 1435 splx(s); 1436 xpt_release_ccb(start_ccb); 1437 } else { 1438 bioq_remove(&softc->bio_queue, bp); 1439 1440 devstat_start_transaction(&softc->device_stats); 1441 1442 scsi_read_write(&start_ccb->csio, 1443 /*retries*/4, 1444 /* cbfcnp */ cddone, 1445 (bp->bio_flags & BIO_ORDERED) != 0 ? 1446 MSG_ORDERED_Q_TAG : 1447 MSG_SIMPLE_Q_TAG, 1448 /* read */bp->bio_cmd == BIO_READ, 1449 /* byte2 */ 0, 1450 /* minimum_cmd_size */ 10, 1451 /* lba */ bp->bio_pblkno, 1452 bp->bio_bcount / softc->params.blksize, 1453 /* data_ptr */ bp->bio_data, 1454 /* dxfer_len */ bp->bio_bcount, 1455 /* sense_len */ SSD_FULL_SIZE, 1456 /* timeout */ 30000); 1457 start_ccb->ccb_h.ccb_state = CD_CCB_BUFFER_IO; 1458 1459 1460 /* 1461 * Block out any asyncronous callbacks 1462 * while we touch the pending ccb list. 1463 */ 1464 oldspl = splcam(); 1465 LIST_INSERT_HEAD(&softc->pending_ccbs, 1466 &start_ccb->ccb_h, periph_links.le); 1467 splx(oldspl); 1468 1469 /* We expect a unit attention from this device */ 1470 if ((softc->flags & CD_FLAG_RETRY_UA) != 0) { 1471 start_ccb->ccb_h.ccb_state |= CD_CCB_RETRY_UA; 1472 softc->flags &= ~CD_FLAG_RETRY_UA; 1473 } 1474 1475 start_ccb->ccb_h.ccb_bp = bp; 1476 bp = bioq_first(&softc->bio_queue); 1477 splx(s); 1478 1479 xpt_action(start_ccb); 1480 } 1481 if (bp != NULL) { 1482 /* Have more work to do, so ensure we stay scheduled */ 1483 xpt_schedule(periph, /* XXX priority */1); 1484 } 1485 break; 1486 } 1487 case CD_STATE_PROBE: 1488 { 1489 1490 rcap = (struct scsi_read_capacity_data *)malloc(sizeof(*rcap), 1491 M_TEMP, 1492 M_NOWAIT); 1493 if (rcap == NULL) { 1494 xpt_print_path(periph->path); 1495 printf("cdstart: Couldn't malloc read_capacity data\n"); 1496 /* cd_free_periph??? */ 1497 break; 1498 } 1499 csio = &start_ccb->csio; 1500 scsi_read_capacity(csio, 1501 /*retries*/1, 1502 cddone, 1503 MSG_SIMPLE_Q_TAG, 1504 rcap, 1505 SSD_FULL_SIZE, 1506 /*timeout*/20000); 1507 start_ccb->ccb_h.ccb_bp = NULL; 1508 start_ccb->ccb_h.ccb_state = CD_CCB_PROBE; 1509 xpt_action(start_ccb); 1510 break; 1511 } 1512 } 1513} 1514 1515static void 1516cddone(struct cam_periph *periph, union ccb *done_ccb) 1517{ 1518 struct cd_softc *softc; 1519 struct ccb_scsiio *csio; 1520 1521 CAM_DEBUG(periph->path, CAM_DEBUG_TRACE, ("entering cddone\n")); 1522 1523 softc = (struct cd_softc *)periph->softc; 1524 csio = &done_ccb->csio; 1525 1526 switch (csio->ccb_h.ccb_state & CD_CCB_TYPE_MASK) { 1527 case CD_CCB_BUFFER_IO: 1528 { 1529 struct bio *bp; 1530 int error; 1531 int oldspl; 1532 1533 bp = (struct bio *)done_ccb->ccb_h.ccb_bp; 1534 error = 0; 1535 1536 if ((done_ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) { 1537 int sf; 1538 1539 if ((done_ccb->ccb_h.ccb_state & CD_CCB_RETRY_UA) != 0) 1540 sf = SF_RETRY_UA; 1541 else 1542 sf = 0; 1543 1544 /* Retry selection timeouts */ 1545 sf |= SF_RETRY_SELTO; 1546 1547 if ((error = cderror(done_ccb, 0, sf)) == ERESTART) { 1548 /* 1549 * A retry was scheuled, so 1550 * just return. 1551 */ 1552 return; 1553 } 1554 } 1555 1556 if (error != 0) { 1557 int s; 1558 struct bio *q_bp; 1559 1560 xpt_print_path(periph->path); 1561 printf("cddone: got error %#x back\n", error); 1562 s = splbio(); 1563 while ((q_bp = bioq_first(&softc->bio_queue)) != NULL) { 1564 bioq_remove(&softc->bio_queue, q_bp); 1565 q_bp->bio_resid = q_bp->bio_bcount; 1566 q_bp->bio_error = EIO; 1567 q_bp->bio_flags |= BIO_ERROR; 1568 biodone(q_bp); 1569 } 1570 splx(s); 1571 bp->bio_resid = bp->bio_bcount; 1572 bp->bio_error = error; 1573 bp->bio_flags |= BIO_ERROR; 1574 cam_release_devq(done_ccb->ccb_h.path, 1575 /*relsim_flags*/0, 1576 /*reduction*/0, 1577 /*timeout*/0, 1578 /*getcount_only*/0); 1579 1580 } else { 1581 bp->bio_resid = csio->resid; 1582 bp->bio_error = 0; 1583 if (bp->bio_resid != 0) { 1584 /* Short transfer ??? */ 1585 bp->bio_flags |= BIO_ERROR; 1586 } 1587 } 1588 1589 /* 1590 * Block out any asyncronous callbacks 1591 * while we touch the pending ccb list. 1592 */ 1593 oldspl = splcam(); 1594 LIST_REMOVE(&done_ccb->ccb_h, periph_links.le); 1595 splx(oldspl); 1596 1597 if (softc->flags & CD_FLAG_CHANGER) 1598 cdchangerschedule(softc); 1599 1600 devstat_end_transaction_bio(&softc->device_stats, bp); 1601 biodone(bp); 1602 break; 1603 } 1604 case CD_CCB_PROBE: 1605 { 1606 struct scsi_read_capacity_data *rdcap; 1607 char announce_buf[120]; /* 1608 * Currently (9/30/97) the 1609 * longest possible announce 1610 * buffer is 108 bytes, for the 1611 * first error case below. 1612 * That is 39 bytes for the 1613 * basic string, 16 bytes for the 1614 * biggest sense key (hardware 1615 * error), 52 bytes for the 1616 * text of the largest sense 1617 * qualifier valid for a CDROM, 1618 * (0x72, 0x03 or 0x04, 1619 * 0x03), and one byte for the 1620 * null terminating character. 1621 * To allow for longer strings, 1622 * the announce buffer is 120 1623 * bytes. 1624 */ 1625 struct cd_params *cdp; 1626 1627 cdp = &softc->params; 1628 1629 rdcap = (struct scsi_read_capacity_data *)csio->data_ptr; 1630 1631 cdp->disksize = scsi_4btoul (rdcap->addr) + 1; 1632 cdp->blksize = scsi_4btoul (rdcap->length); 1633 1634 if ((csio->ccb_h.status & CAM_STATUS_MASK) == CAM_REQ_CMP) { 1635 1636 snprintf(announce_buf, sizeof(announce_buf), 1637 "cd present [%lu x %lu byte records]", 1638 cdp->disksize, (u_long)cdp->blksize); 1639 1640 } else { 1641 int error; 1642 /* 1643 * Retry any UNIT ATTENTION type errors. They 1644 * are expected at boot. 1645 */ 1646 error = cderror(done_ccb, 0, SF_RETRY_UA | 1647 SF_NO_PRINT | SF_RETRY_SELTO); 1648 if (error == ERESTART) { 1649 /* 1650 * A retry was scheuled, so 1651 * just return. 1652 */ 1653 return; 1654 } else if (error != 0) { 1655 1656 struct scsi_sense_data *sense; 1657 int asc, ascq; 1658 int sense_key, error_code; 1659 int have_sense; 1660 cam_status status; 1661 struct ccb_getdev cgd; 1662 1663 /* Don't wedge this device's queue */ 1664 cam_release_devq(done_ccb->ccb_h.path, 1665 /*relsim_flags*/0, 1666 /*reduction*/0, 1667 /*timeout*/0, 1668 /*getcount_only*/0); 1669 1670 status = done_ccb->ccb_h.status; 1671 1672 xpt_setup_ccb(&cgd.ccb_h, 1673 done_ccb->ccb_h.path, 1674 /* priority */ 1); 1675 cgd.ccb_h.func_code = XPT_GDEV_TYPE; 1676 xpt_action((union ccb *)&cgd); 1677 1678 if (((csio->ccb_h.flags & CAM_SENSE_PHYS) != 0) 1679 || ((csio->ccb_h.flags & CAM_SENSE_PTR) != 0) 1680 || ((status & CAM_AUTOSNS_VALID) == 0)) 1681 have_sense = FALSE; 1682 else 1683 have_sense = TRUE; 1684 1685 if (have_sense) { 1686 sense = &csio->sense_data; 1687 scsi_extract_sense(sense, &error_code, 1688 &sense_key, 1689 &asc, &ascq); 1690 } 1691 /* 1692 * Attach to anything that claims to be a 1693 * CDROM or WORM device, as long as it 1694 * doesn't return a "Logical unit not 1695 * supported" (0x25) error. 1696 */ 1697 if ((have_sense) && (asc != 0x25) 1698 && (error_code == SSD_CURRENT_ERROR)) 1699 snprintf(announce_buf, 1700 sizeof(announce_buf), 1701 "Attempt to query device " 1702 "size failed: %s, %s", 1703 scsi_sense_key_text[sense_key], 1704 scsi_sense_desc(asc,ascq, 1705 &cgd.inq_data)); 1706 else if (SID_TYPE(&cgd.inq_data) == T_CDROM) { 1707 /* 1708 * We only print out an error for 1709 * CDROM type devices. For WORM 1710 * devices, we don't print out an 1711 * error since a few WORM devices 1712 * don't support CDROM commands. 1713 * If we have sense information, go 1714 * ahead and print it out. 1715 * Otherwise, just say that we 1716 * couldn't attach. 1717 */ 1718 1719 /* 1720 * Just print out the error, not 1721 * the full probe message, when we 1722 * don't attach. 1723 */ 1724 if (have_sense) 1725 scsi_sense_print( 1726 &done_ccb->csio); 1727 else { 1728 xpt_print_path(periph->path); 1729 printf("got CAM status %#x\n", 1730 done_ccb->ccb_h.status); 1731 } 1732 xpt_print_path(periph->path); 1733 printf("fatal error, failed" 1734 " to attach to device\n"); 1735 1736 /* 1737 * Invalidate this peripheral. 1738 */ 1739 cam_periph_invalidate(periph); 1740 1741 announce_buf[0] = '\0'; 1742 } else { 1743 1744 /* 1745 * Invalidate this peripheral. 1746 */ 1747 cam_periph_invalidate(periph); 1748 announce_buf[0] = '\0'; 1749 } 1750 } 1751 } 1752 free(rdcap, M_TEMP); 1753 if (announce_buf[0] != '\0') { 1754 xpt_announce_periph(periph, announce_buf); 1755 if (softc->flags & CD_FLAG_CHANGER) 1756 cdchangerschedule(softc); 1757 } 1758 softc->state = CD_STATE_NORMAL; 1759 /* 1760 * Since our peripheral may be invalidated by an error 1761 * above or an external event, we must release our CCB 1762 * before releasing the probe lock on the peripheral. 1763 * The peripheral will only go away once the last lock 1764 * is removed, and we need it around for the CCB release 1765 * operation. 1766 */ 1767 xpt_release_ccb(done_ccb); 1768 cam_periph_unlock(periph); 1769 return; 1770 } 1771 case CD_CCB_WAITING: 1772 { 1773 /* Caller will release the CCB */ 1774 CAM_DEBUG(periph->path, CAM_DEBUG_TRACE, 1775 ("trying to wakeup ccbwait\n")); 1776 1777 wakeup(&done_ccb->ccb_h.cbfcnp); 1778 return; 1779 } 1780 default: 1781 break; 1782 } 1783 xpt_release_ccb(done_ccb); 1784} 1785 1786static int 1787cdioctl(dev_t dev, u_long cmd, caddr_t addr, int flag, struct proc *p) 1788{ 1789 1790 struct cam_periph *periph; 1791 struct cd_softc *softc; 1792 int error, unit; 1793 1794 unit = dkunit(dev); 1795 1796 periph = cam_extend_get(cdperiphs, unit); 1797 if (periph == NULL) 1798 return(ENXIO); 1799 1800 CAM_DEBUG(periph->path, CAM_DEBUG_TRACE, ("entering cdioctl\n")); 1801 1802 softc = (struct cd_softc *)periph->softc; 1803 1804 CAM_DEBUG(periph->path, CAM_DEBUG_TRACE, 1805 ("trying to do ioctl %#lx\n", cmd)); 1806 1807 error = cam_periph_lock(periph, PRIBIO | PCATCH); 1808 1809 if (error != 0) 1810 return(error); 1811 1812 switch (cmd) { 1813 1814 case CDIOCPLAYTRACKS: 1815 { 1816 struct ioc_play_track *args 1817 = (struct ioc_play_track *) addr; 1818 struct cd_mode_data *data; 1819 1820 data = malloc(sizeof(struct cd_mode_data), M_TEMP, 1821 M_WAITOK); 1822 1823 CAM_DEBUG(periph->path, CAM_DEBUG_SUBTRACE, 1824 ("trying to do CDIOCPLAYTRACKS\n")); 1825 1826 error = cdgetmode(periph, data, AUDIO_PAGE); 1827 if (error) { 1828 free(data, M_TEMP); 1829 break; 1830 } 1831 data->page.audio.flags &= ~CD_PA_SOTC; 1832 data->page.audio.flags |= CD_PA_IMMED; 1833 error = cdsetmode(periph, data); 1834 free(data, M_TEMP); 1835 if (error) 1836 break; 1837 if (softc->quirks & CD_Q_BCD_TRACKS) { 1838 args->start_track = bin2bcd(args->start_track); 1839 args->end_track = bin2bcd(args->end_track); 1840 } 1841 error = cdplaytracks(periph, 1842 args->start_track, 1843 args->start_index, 1844 args->end_track, 1845 args->end_index); 1846 } 1847 break; 1848 case CDIOCPLAYMSF: 1849 { 1850 struct ioc_play_msf *args 1851 = (struct ioc_play_msf *) addr; 1852 struct cd_mode_data *data; 1853 1854 data = malloc(sizeof(struct cd_mode_data), M_TEMP, 1855 M_WAITOK); 1856 1857 CAM_DEBUG(periph->path, CAM_DEBUG_SUBTRACE, 1858 ("trying to do CDIOCPLAYMSF\n")); 1859 1860 error = cdgetmode(periph, data, AUDIO_PAGE); 1861 if (error) { 1862 free(data, M_TEMP); 1863 break; 1864 } 1865 data->page.audio.flags &= ~CD_PA_SOTC; 1866 data->page.audio.flags |= CD_PA_IMMED; 1867 error = cdsetmode(periph, data); 1868 free(data, M_TEMP); 1869 if (error) 1870 break; 1871 error = cdplaymsf(periph, 1872 args->start_m, 1873 args->start_s, 1874 args->start_f, 1875 args->end_m, 1876 args->end_s, 1877 args->end_f); 1878 } 1879 break; 1880 case CDIOCPLAYBLOCKS: 1881 { 1882 struct ioc_play_blocks *args 1883 = (struct ioc_play_blocks *) addr; 1884 struct cd_mode_data *data; 1885 1886 CAM_DEBUG(periph->path, CAM_DEBUG_SUBTRACE, 1887 ("trying to do CDIOCPLAYBLOCKS\n")); 1888 1889 data = malloc(sizeof(struct cd_mode_data), M_TEMP, 1890 M_WAITOK); 1891 1892 error = cdgetmode(periph, data, AUDIO_PAGE); 1893 if (error) { 1894 free(data, M_TEMP); 1895 break; 1896 } 1897 data->page.audio.flags &= ~CD_PA_SOTC; 1898 data->page.audio.flags |= CD_PA_IMMED; 1899 error = cdsetmode(periph, data); 1900 free(data, M_TEMP); 1901 if (error) 1902 break; 1903 error = cdplay(periph, args->blk, args->len); 1904 } 1905 break; 1906 case CDIOCREADSUBCHANNEL: 1907 { 1908 struct ioc_read_subchannel *args 1909 = (struct ioc_read_subchannel *) addr; 1910 struct cd_sub_channel_info *data; 1911 u_int32_t len = args->data_len; 1912 1913 CAM_DEBUG(periph->path, CAM_DEBUG_SUBTRACE, 1914 ("trying to do CDIOCREADSUBCHANNEL\n")); 1915 1916 data = malloc(sizeof(struct cd_sub_channel_info), 1917 M_TEMP, M_WAITOK); 1918 1919 if ((len > sizeof(struct cd_sub_channel_info)) || 1920 (len < sizeof(struct cd_sub_channel_header))) { 1921 printf( 1922 "scsi_cd: cdioctl: " 1923 "cdioreadsubchannel: error, len=%d\n", 1924 len); 1925 error = EINVAL; 1926 free(data, M_TEMP); 1927 break; 1928 } 1929 1930 if (softc->quirks & CD_Q_BCD_TRACKS) 1931 args->track = bin2bcd(args->track); 1932 1933 error = cdreadsubchannel(periph, args->address_format, 1934 args->data_format, args->track, data, len); 1935 1936 if (error) { 1937 free(data, M_TEMP); 1938 break; 1939 } 1940 if (softc->quirks & CD_Q_BCD_TRACKS) 1941 data->what.track_info.track_number = 1942 bcd2bin(data->what.track_info.track_number); 1943 len = min(len, ((data->header.data_len[0] << 8) + 1944 data->header.data_len[1] + 1945 sizeof(struct cd_sub_channel_header))); 1946 if (copyout(data, args->data, len) != 0) { 1947 error = EFAULT; 1948 } 1949 free(data, M_TEMP); 1950 } 1951 break; 1952 1953 case CDIOREADTOCHEADER: 1954 { 1955 struct ioc_toc_header *th; 1956 1957 CAM_DEBUG(periph->path, CAM_DEBUG_SUBTRACE, 1958 ("trying to do CDIOREADTOCHEADER\n")); 1959 1960 th = malloc(sizeof(struct ioc_toc_header), M_TEMP, 1961 M_WAITOK); 1962 error = cdreadtoc(periph, 0, 0, 1963 (struct cd_toc_entry *)th, 1964 sizeof (*th)); 1965 if (error) { 1966 free(th, M_TEMP); 1967 break; 1968 } 1969 if (softc->quirks & CD_Q_BCD_TRACKS) { 1970 /* we are going to have to convert the BCD 1971 * encoding on the cd to what is expected 1972 */ 1973 th->starting_track = 1974 bcd2bin(th->starting_track); 1975 th->ending_track = bcd2bin(th->ending_track); 1976 } 1977 NTOHS(th->len); 1978 bcopy(th, addr, sizeof(*th)); 1979 free(th, M_TEMP); 1980 } 1981 break; 1982 case CDIOREADTOCENTRYS: 1983 { 1984 typedef struct { 1985 struct ioc_toc_header header; 1986 struct cd_toc_entry entries[100]; 1987 } data_t; 1988 typedef struct { 1989 struct ioc_toc_header header; 1990 struct cd_toc_entry entry; 1991 } lead_t; 1992 1993 data_t *data; 1994 lead_t *lead; 1995 struct ioc_read_toc_entry *te = 1996 (struct ioc_read_toc_entry *) addr; 1997 struct ioc_toc_header *th; 1998 u_int32_t len, readlen, idx, num; 1999 u_int32_t starting_track = te->starting_track; 2000 2001 CAM_DEBUG(periph->path, CAM_DEBUG_SUBTRACE, 2002 ("trying to do CDIOREADTOCENTRYS\n")); 2003 2004 data = malloc(sizeof(data_t), M_TEMP, M_WAITOK); 2005 lead = malloc(sizeof(lead_t), M_TEMP, M_WAITOK); 2006 2007 if (te->data_len < sizeof(struct cd_toc_entry) 2008 || (te->data_len % sizeof(struct cd_toc_entry)) != 0 2009 || (te->address_format != CD_MSF_FORMAT 2010 && te->address_format != CD_LBA_FORMAT)) { 2011 error = EINVAL; 2012 printf("scsi_cd: error in readtocentries, " 2013 "returning EINVAL\n"); 2014 free(data, M_TEMP); 2015 free(lead, M_TEMP); 2016 break; 2017 } 2018 2019 th = &data->header; 2020 error = cdreadtoc(periph, 0, 0, 2021 (struct cd_toc_entry *)th, 2022 sizeof (*th)); 2023 if (error) { 2024 free(data, M_TEMP); 2025 free(lead, M_TEMP); 2026 break; 2027 } 2028 2029 if (softc->quirks & CD_Q_BCD_TRACKS) { 2030 /* we are going to have to convert the BCD 2031 * encoding on the cd to what is expected 2032 */ 2033 th->starting_track = 2034 bcd2bin(th->starting_track); 2035 th->ending_track = bcd2bin(th->ending_track); 2036 } 2037 2038 if (starting_track == 0) 2039 starting_track = th->starting_track; 2040 else if (starting_track == LEADOUT) 2041 starting_track = th->ending_track + 1; 2042 else if (starting_track < th->starting_track || 2043 starting_track > th->ending_track + 1) { 2044 printf("scsi_cd: error in readtocentries, " 2045 "returning EINVAL\n"); 2046 free(data, M_TEMP); 2047 free(lead, M_TEMP); 2048 error = EINVAL; 2049 break; 2050 } 2051 2052 /* calculate reading length without leadout entry */ 2053 readlen = (th->ending_track - starting_track + 1) * 2054 sizeof(struct cd_toc_entry); 2055 2056 /* and with leadout entry */ 2057 len = readlen + sizeof(struct cd_toc_entry); 2058 if (te->data_len < len) { 2059 len = te->data_len; 2060 if (readlen > len) 2061 readlen = len; 2062 } 2063 if (len > sizeof(data->entries)) { 2064 printf("scsi_cd: error in readtocentries, " 2065 "returning EINVAL\n"); 2066 error = EINVAL; 2067 free(data, M_TEMP); 2068 free(lead, M_TEMP); 2069 break; 2070 } 2071 num = len / sizeof(struct cd_toc_entry); 2072 2073 if (readlen > 0) { 2074 error = cdreadtoc(periph, te->address_format, 2075 starting_track, 2076 (struct cd_toc_entry *)data, 2077 readlen + sizeof (*th)); 2078 if (error) { 2079 free(data, M_TEMP); 2080 free(lead, M_TEMP); 2081 break; 2082 } 2083 } 2084 2085 /* make leadout entry if needed */ 2086 idx = starting_track + num - 1; 2087 if (softc->quirks & CD_Q_BCD_TRACKS) 2088 th->ending_track = bcd2bin(th->ending_track); 2089 if (idx == th->ending_track + 1) { 2090 error = cdreadtoc(periph, te->address_format, 2091 LEADOUT, 2092 (struct cd_toc_entry *)lead, 2093 sizeof(*lead)); 2094 if (error) { 2095 free(data, M_TEMP); 2096 free(lead, M_TEMP); 2097 break; 2098 } 2099 data->entries[idx - starting_track] = 2100 lead->entry; 2101 } 2102 if (softc->quirks & CD_Q_BCD_TRACKS) { 2103 for (idx = 0; idx < num - 1; idx++) { 2104 data->entries[idx].track = 2105 bcd2bin(data->entries[idx].track); 2106 } 2107 } 2108 2109 error = copyout(data->entries, te->data, len); 2110 free(data, M_TEMP); 2111 free(lead, M_TEMP); 2112 } 2113 break; 2114 case CDIOREADTOCENTRY: 2115 { 2116 /* yeah yeah, this is ugly */ 2117 typedef struct { 2118 struct ioc_toc_header header; 2119 struct cd_toc_entry entry; 2120 } data_t; 2121 2122 data_t *data; 2123 struct ioc_read_toc_single_entry *te = 2124 (struct ioc_read_toc_single_entry *) addr; 2125 struct ioc_toc_header *th; 2126 u_int32_t track; 2127 2128 CAM_DEBUG(periph->path, CAM_DEBUG_SUBTRACE, 2129 ("trying to do CDIOREADTOCENTRY\n")); 2130 2131 data = malloc(sizeof(data_t), M_TEMP, M_WAITOK); 2132 2133 if (te->address_format != CD_MSF_FORMAT 2134 && te->address_format != CD_LBA_FORMAT) { 2135 printf("error in readtocentry, " 2136 " returning EINVAL\n"); 2137 free(data, M_TEMP); 2138 error = EINVAL; 2139 break; 2140 } 2141 2142 th = &data->header; 2143 error = cdreadtoc(periph, 0, 0, 2144 (struct cd_toc_entry *)th, 2145 sizeof (*th)); 2146 if (error) { 2147 free(data, M_TEMP); 2148 break; 2149 } 2150 2151 if (softc->quirks & CD_Q_BCD_TRACKS) { 2152 /* we are going to have to convert the BCD 2153 * encoding on the cd to what is expected 2154 */ 2155 th->starting_track = 2156 bcd2bin(th->starting_track); 2157 th->ending_track = bcd2bin(th->ending_track); 2158 } 2159 track = te->track; 2160 if (track == 0) 2161 track = th->starting_track; 2162 else if (track == LEADOUT) 2163 /* OK */; 2164 else if (track < th->starting_track || 2165 track > th->ending_track + 1) { 2166 printf("error in readtocentry, " 2167 " returning EINVAL\n"); 2168 free(data, M_TEMP); 2169 error = EINVAL; 2170 break; 2171 } 2172 2173 error = cdreadtoc(periph, te->address_format, track, 2174 (struct cd_toc_entry *)data, 2175 sizeof(data_t)); 2176 if (error) { 2177 free(data, M_TEMP); 2178 break; 2179 } 2180 2181 if (softc->quirks & CD_Q_BCD_TRACKS) 2182 data->entry.track = bcd2bin(data->entry.track); 2183 bcopy(&data->entry, &te->entry, 2184 sizeof(struct cd_toc_entry)); 2185 free(data, M_TEMP); 2186 } 2187 break; 2188 case CDIOCSETPATCH: 2189 { 2190 struct ioc_patch *arg = (struct ioc_patch *) addr; 2191 struct cd_mode_data *data; 2192 2193 CAM_DEBUG(periph->path, CAM_DEBUG_SUBTRACE, 2194 ("trying to do CDIOCSETPATCH\n")); 2195 2196 data = malloc(sizeof(struct cd_mode_data), M_TEMP, 2197 M_WAITOK); 2198 error = cdgetmode(periph, data, AUDIO_PAGE); 2199 if (error) { 2200 free(data, M_TEMP); 2201 break; 2202 } 2203 data->page.audio.port[LEFT_PORT].channels = 2204 arg->patch[0]; 2205 data->page.audio.port[RIGHT_PORT].channels = 2206 arg->patch[1]; 2207 data->page.audio.port[2].channels = arg->patch[2]; 2208 data->page.audio.port[3].channels = arg->patch[3]; 2209 error = cdsetmode(periph, data); 2210 free(data, M_TEMP); 2211 } 2212 break; 2213 case CDIOCGETVOL: 2214 { 2215 struct ioc_vol *arg = (struct ioc_vol *) addr; 2216 struct cd_mode_data *data; 2217 2218 CAM_DEBUG(periph->path, CAM_DEBUG_SUBTRACE, 2219 ("trying to do CDIOCGETVOL\n")); 2220 2221 data = malloc(sizeof(struct cd_mode_data), M_TEMP, 2222 M_WAITOK); 2223 error = cdgetmode(periph, data, AUDIO_PAGE); 2224 if (error) { 2225 free(data, M_TEMP); 2226 break; 2227 } 2228 arg->vol[LEFT_PORT] = 2229 data->page.audio.port[LEFT_PORT].volume; 2230 arg->vol[RIGHT_PORT] = 2231 data->page.audio.port[RIGHT_PORT].volume; 2232 arg->vol[2] = data->page.audio.port[2].volume; 2233 arg->vol[3] = data->page.audio.port[3].volume; 2234 free(data, M_TEMP); 2235 } 2236 break; 2237 case CDIOCSETVOL: 2238 { 2239 struct ioc_vol *arg = (struct ioc_vol *) addr; 2240 struct cd_mode_data *data; 2241 2242 CAM_DEBUG(periph->path, CAM_DEBUG_SUBTRACE, 2243 ("trying to do CDIOCSETVOL\n")); 2244 2245 data = malloc(sizeof(struct cd_mode_data), M_TEMP, 2246 M_WAITOK); 2247 error = cdgetmode(periph, data, AUDIO_PAGE); 2248 if (error) { 2249 free(data, M_TEMP); 2250 break; 2251 } 2252 data->page.audio.port[LEFT_PORT].channels = CHANNEL_0; 2253 data->page.audio.port[LEFT_PORT].volume = 2254 arg->vol[LEFT_PORT]; 2255 data->page.audio.port[RIGHT_PORT].channels = CHANNEL_1; 2256 data->page.audio.port[RIGHT_PORT].volume = 2257 arg->vol[RIGHT_PORT]; 2258 data->page.audio.port[2].volume = arg->vol[2]; 2259 data->page.audio.port[3].volume = arg->vol[3]; 2260 error = cdsetmode(periph, data); 2261 free(data, M_TEMP); 2262 } 2263 break; 2264 case CDIOCSETMONO: 2265 { 2266 struct cd_mode_data *data; 2267 2268 CAM_DEBUG(periph->path, CAM_DEBUG_SUBTRACE, 2269 ("trying to do CDIOCSETMONO\n")); 2270 2271 data = malloc(sizeof(struct cd_mode_data), 2272 M_TEMP, M_WAITOK); 2273 error = cdgetmode(periph, data, AUDIO_PAGE); 2274 if (error) { 2275 free(data, M_TEMP); 2276 break; 2277 } 2278 data->page.audio.port[LEFT_PORT].channels = 2279 LEFT_CHANNEL | RIGHT_CHANNEL; 2280 data->page.audio.port[RIGHT_PORT].channels = 2281 LEFT_CHANNEL | RIGHT_CHANNEL; 2282 data->page.audio.port[2].channels = 0; 2283 data->page.audio.port[3].channels = 0; 2284 error = cdsetmode(periph, data); 2285 free(data, M_TEMP); 2286 } 2287 break; 2288 case CDIOCSETSTEREO: 2289 { 2290 struct cd_mode_data *data; 2291 2292 CAM_DEBUG(periph->path, CAM_DEBUG_SUBTRACE, 2293 ("trying to do CDIOCSETSTEREO\n")); 2294 2295 data = malloc(sizeof(struct cd_mode_data), M_TEMP, 2296 M_WAITOK); 2297 error = cdgetmode(periph, data, AUDIO_PAGE); 2298 if (error) { 2299 free(data, M_TEMP); 2300 break; 2301 } 2302 data->page.audio.port[LEFT_PORT].channels = 2303 LEFT_CHANNEL; 2304 data->page.audio.port[RIGHT_PORT].channels = 2305 RIGHT_CHANNEL; 2306 data->page.audio.port[2].channels = 0; 2307 data->page.audio.port[3].channels = 0; 2308 error = cdsetmode(periph, data); 2309 free(data, M_TEMP); 2310 } 2311 break; 2312 case CDIOCSETMUTE: 2313 { 2314 struct cd_mode_data *data; 2315 2316 CAM_DEBUG(periph->path, CAM_DEBUG_SUBTRACE, 2317 ("trying to do CDIOCSETMUTE\n")); 2318 2319 data = malloc(sizeof(struct cd_mode_data), M_TEMP, 2320 M_WAITOK); 2321 error = cdgetmode(periph, data, AUDIO_PAGE); 2322 if (error) { 2323 free(data, M_TEMP); 2324 break; 2325 } 2326 data->page.audio.port[LEFT_PORT].channels = 0; 2327 data->page.audio.port[RIGHT_PORT].channels = 0; 2328 data->page.audio.port[2].channels = 0; 2329 data->page.audio.port[3].channels = 0; 2330 error = cdsetmode(periph, data); 2331 free(data, M_TEMP); 2332 } 2333 break; 2334 case CDIOCSETLEFT: 2335 { 2336 struct cd_mode_data *data; 2337 2338 CAM_DEBUG(periph->path, CAM_DEBUG_SUBTRACE, 2339 ("trying to do CDIOCSETLEFT\n")); 2340 2341 data = malloc(sizeof(struct cd_mode_data), M_TEMP, 2342 M_WAITOK); 2343 error = cdgetmode(periph, data, AUDIO_PAGE); 2344 if (error) { 2345 free(data, M_TEMP); 2346 break; 2347 } 2348 data->page.audio.port[LEFT_PORT].channels = 2349 LEFT_CHANNEL; 2350 data->page.audio.port[RIGHT_PORT].channels = 2351 LEFT_CHANNEL; 2352 data->page.audio.port[2].channels = 0; 2353 data->page.audio.port[3].channels = 0; 2354 error = cdsetmode(periph, data); 2355 free(data, M_TEMP); 2356 } 2357 break; 2358 case CDIOCSETRIGHT: 2359 { 2360 struct cd_mode_data *data; 2361 2362 CAM_DEBUG(periph->path, CAM_DEBUG_SUBTRACE, 2363 ("trying to do CDIOCSETRIGHT\n")); 2364 2365 data = malloc(sizeof(struct cd_mode_data), M_TEMP, 2366 M_WAITOK); 2367 error = cdgetmode(periph, data, AUDIO_PAGE); 2368 if (error) { 2369 free(data, M_TEMP); 2370 break; 2371 } 2372 data->page.audio.port[LEFT_PORT].channels = 2373 RIGHT_CHANNEL; 2374 data->page.audio.port[RIGHT_PORT].channels = 2375 RIGHT_CHANNEL; 2376 data->page.audio.port[2].channels = 0; 2377 data->page.audio.port[3].channels = 0; 2378 error = cdsetmode(periph, data); 2379 free(data, M_TEMP); 2380 } 2381 break; 2382 case CDIOCRESUME: 2383 error = cdpause(periph, 1); 2384 break; 2385 case CDIOCPAUSE: 2386 error = cdpause(periph, 0); 2387 break; 2388 case CDIOCSTART: 2389 error = cdstartunit(periph); 2390 break; 2391 case CDIOCSTOP: 2392 error = cdstopunit(periph, 0); 2393 break; 2394 case CDIOCEJECT: 2395 error = cdstopunit(periph, 1); 2396 break; 2397 case CDIOCALLOW: 2398 cdprevent(periph, PR_ALLOW); 2399 break; 2400 case CDIOCPREVENT: 2401 cdprevent(periph, PR_PREVENT); 2402 break; 2403 case CDIOCSETDEBUG: 2404 /* sc_link->flags |= (SDEV_DB1 | SDEV_DB2); */ 2405 error = ENOTTY; 2406 break; 2407 case CDIOCCLRDEBUG: 2408 /* sc_link->flags &= ~(SDEV_DB1 | SDEV_DB2); */ 2409 error = ENOTTY; 2410 break; 2411 case CDIOCRESET: 2412 /* return (cd_reset(periph)); */ 2413 error = ENOTTY; 2414 break; 2415 case DVDIOCSENDKEY: 2416 case DVDIOCREPORTKEY: { 2417 struct dvd_authinfo *authinfo; 2418 2419 authinfo = (struct dvd_authinfo *)addr; 2420 2421 if (cmd == DVDIOCREPORTKEY) 2422 error = cdreportkey(periph, authinfo); 2423 else 2424 error = cdsendkey(periph, authinfo); 2425 break; 2426 } 2427 case DVDIOCREADSTRUCTURE: { 2428 struct dvd_struct *dvdstruct; 2429 2430 dvdstruct = (struct dvd_struct *)addr; 2431 2432 error = cdreaddvdstructure(periph, dvdstruct); 2433 2434 break; 2435 } 2436 default: 2437 error = cam_periph_ioctl(periph, cmd, addr, cderror); 2438 break; 2439 } 2440 2441 cam_periph_unlock(periph); 2442 2443 CAM_DEBUG(periph->path, CAM_DEBUG_TRACE, ("leaving cdioctl\n")); 2444 2445 return (error); 2446} 2447 2448static void 2449cdprevent(struct cam_periph *periph, int action) 2450{ 2451 union ccb *ccb; 2452 struct cd_softc *softc; 2453 int error; 2454 2455 CAM_DEBUG(periph->path, CAM_DEBUG_TRACE, ("entering cdprevent\n")); 2456 2457 softc = (struct cd_softc *)periph->softc; 2458 2459 if (((action == PR_ALLOW) 2460 && (softc->flags & CD_FLAG_DISC_LOCKED) == 0) 2461 || ((action == PR_PREVENT) 2462 && (softc->flags & CD_FLAG_DISC_LOCKED) != 0)) { 2463 return; 2464 } 2465 2466 ccb = cdgetccb(periph, /* priority */ 1); 2467 2468 scsi_prevent(&ccb->csio, 2469 /*retries*/ 1, 2470 cddone, 2471 MSG_SIMPLE_Q_TAG, 2472 action, 2473 SSD_FULL_SIZE, 2474 /* timeout */60000); 2475 2476 error = cdrunccb(ccb, cderror, /*cam_flags*/0, 2477 /*sense_flags*/SF_RETRY_UA|SF_NO_PRINT|SF_RETRY_SELTO); 2478 2479 xpt_release_ccb(ccb); 2480 2481 if (error == 0) { 2482 if (action == PR_ALLOW) 2483 softc->flags &= ~CD_FLAG_DISC_LOCKED; 2484 else 2485 softc->flags |= CD_FLAG_DISC_LOCKED; 2486 } 2487} 2488 2489static int 2490cdsize(dev_t dev, u_int32_t *size) 2491{ 2492 struct cam_periph *periph; 2493 struct cd_softc *softc; 2494 union ccb *ccb; 2495 struct scsi_read_capacity_data *rcap_buf; 2496 int error; 2497 2498 periph = cam_extend_get(cdperiphs, dkunit(dev)); 2499 2500 if (periph == NULL) 2501 return (ENXIO); 2502 2503 CAM_DEBUG(periph->path, CAM_DEBUG_TRACE, ("entering cdsize\n")); 2504 2505 softc = (struct cd_softc *)periph->softc; 2506 2507 ccb = cdgetccb(periph, /* priority */ 1); 2508 2509 rcap_buf = malloc(sizeof(struct scsi_read_capacity_data), 2510 M_TEMP, M_WAITOK); 2511 2512 scsi_read_capacity(&ccb->csio, 2513 /*retries*/ 1, 2514 cddone, 2515 MSG_SIMPLE_Q_TAG, 2516 rcap_buf, 2517 SSD_FULL_SIZE, 2518 /* timeout */20000); 2519 2520 error = cdrunccb(ccb, cderror, /*cam_flags*/0, 2521 /*sense_flags*/SF_RETRY_UA|SF_NO_PRINT|SF_RETRY_SELTO); 2522 2523 xpt_release_ccb(ccb); 2524 2525 softc->params.disksize = scsi_4btoul(rcap_buf->addr) + 1; 2526 softc->params.blksize = scsi_4btoul(rcap_buf->length); 2527 /* 2528 * SCSI-3 mandates that the reported blocksize shall be 2048. 2529 * Older drives sometimes report funny values, trim it down to 2530 * 2048, or other parts of the kernel will get confused. 2531 * 2532 * XXX we leave drives alone that might report 512 bytes, as 2533 * well as drives reporting more weird sizes like perhaps 4K. 2534 */ 2535 if (softc->params.blksize > 2048 && softc->params.blksize <= 2352) 2536 softc->params.blksize = 2048; 2537 2538 free(rcap_buf, M_TEMP); 2539 *size = softc->params.disksize; 2540 2541 return (error); 2542 2543} 2544 2545static int 2546cderror(union ccb *ccb, u_int32_t cam_flags, u_int32_t sense_flags) 2547{ 2548 struct cd_softc *softc; 2549 struct cam_periph *periph; 2550 2551 periph = xpt_path_periph(ccb->ccb_h.path); 2552 softc = (struct cd_softc *)periph->softc; 2553 2554 /* 2555 * XXX 2556 * Until we have a better way of doing pack validation, 2557 * don't treat UAs as errors. 2558 */ 2559 sense_flags |= SF_RETRY_UA; 2560 return (cam_periph_error(ccb, cam_flags, sense_flags, 2561 &softc->saved_ccb)); 2562} 2563 2564/* 2565 * Read table of contents 2566 */ 2567static int 2568cdreadtoc(struct cam_periph *periph, u_int32_t mode, u_int32_t start, 2569 struct cd_toc_entry *data, u_int32_t len) 2570{ 2571 struct scsi_read_toc *scsi_cmd; 2572 u_int32_t ntoc; 2573 struct ccb_scsiio *csio; 2574 union ccb *ccb; 2575 int error; 2576 2577 ntoc = len; 2578 error = 0; 2579 2580 ccb = cdgetccb(periph, /* priority */ 1); 2581 2582 csio = &ccb->csio; 2583 2584 cam_fill_csio(csio, 2585 /* retries */ 1, 2586 /* cbfcnp */ cddone, 2587 /* flags */ CAM_DIR_IN, 2588 /* tag_action */ MSG_SIMPLE_Q_TAG, 2589 /* data_ptr */ (u_int8_t *)data, 2590 /* dxfer_len */ len, 2591 /* sense_len */ SSD_FULL_SIZE, 2592 sizeof(struct scsi_read_toc), 2593 /* timeout */ 50000); 2594 2595 scsi_cmd = (struct scsi_read_toc *)&csio->cdb_io.cdb_bytes; 2596 bzero (scsi_cmd, sizeof(*scsi_cmd)); 2597 2598 if (mode == CD_MSF_FORMAT) 2599 scsi_cmd->byte2 |= CD_MSF; 2600 scsi_cmd->from_track = start; 2601 /* scsi_ulto2b(ntoc, (u_int8_t *)scsi_cmd->data_len); */ 2602 scsi_cmd->data_len[0] = (ntoc) >> 8; 2603 scsi_cmd->data_len[1] = (ntoc) & 0xff; 2604 2605 scsi_cmd->op_code = READ_TOC; 2606 2607 error = cdrunccb(ccb, cderror, /*cam_flags*/0, 2608 /*sense_flags*/SF_RETRY_UA|SF_RETRY_SELTO); 2609 2610 xpt_release_ccb(ccb); 2611 2612 return(error); 2613} 2614 2615static int 2616cdreadsubchannel(struct cam_periph *periph, u_int32_t mode, 2617 u_int32_t format, int track, 2618 struct cd_sub_channel_info *data, u_int32_t len) 2619{ 2620 struct scsi_read_subchannel *scsi_cmd; 2621 struct ccb_scsiio *csio; 2622 union ccb *ccb; 2623 int error; 2624 2625 error = 0; 2626 2627 ccb = cdgetccb(periph, /* priority */ 1); 2628 2629 csio = &ccb->csio; 2630 2631 cam_fill_csio(csio, 2632 /* retries */ 1, 2633 /* cbfcnp */ cddone, 2634 /* flags */ CAM_DIR_IN, 2635 /* tag_action */ MSG_SIMPLE_Q_TAG, 2636 /* data_ptr */ (u_int8_t *)data, 2637 /* dxfer_len */ len, 2638 /* sense_len */ SSD_FULL_SIZE, 2639 sizeof(struct scsi_read_subchannel), 2640 /* timeout */ 50000); 2641 2642 scsi_cmd = (struct scsi_read_subchannel *)&csio->cdb_io.cdb_bytes; 2643 bzero (scsi_cmd, sizeof(*scsi_cmd)); 2644 2645 scsi_cmd->op_code = READ_SUBCHANNEL; 2646 if (mode == CD_MSF_FORMAT) 2647 scsi_cmd->byte1 |= CD_MSF; 2648 scsi_cmd->byte2 = SRS_SUBQ; 2649 scsi_cmd->subchan_format = format; 2650 scsi_cmd->track = track; 2651 scsi_ulto2b(len, (u_int8_t *)scsi_cmd->data_len); 2652 scsi_cmd->control = 0; 2653 2654 error = cdrunccb(ccb, cderror, /*cam_flags*/0, 2655 /*sense_flags*/SF_RETRY_UA|SF_RETRY_SELTO); 2656 2657 xpt_release_ccb(ccb); 2658 2659 return(error); 2660} 2661 2662 2663static int 2664cdgetmode(struct cam_periph *periph, struct cd_mode_data *data, u_int32_t page) 2665{ 2666 struct scsi_mode_sense_6 *scsi_cmd; 2667 struct ccb_scsiio *csio; 2668 union ccb *ccb; 2669 int error; 2670 2671 ccb = cdgetccb(periph, /* priority */ 1); 2672 2673 csio = &ccb->csio; 2674 2675 bzero(data, sizeof(*data)); 2676 cam_fill_csio(csio, 2677 /* retries */ 1, 2678 /* cbfcnp */ cddone, 2679 /* flags */ CAM_DIR_IN, 2680 /* tag_action */ MSG_SIMPLE_Q_TAG, 2681 /* data_ptr */ (u_int8_t *)data, 2682 /* dxfer_len */ sizeof(*data), 2683 /* sense_len */ SSD_FULL_SIZE, 2684 sizeof(struct scsi_mode_sense_6), 2685 /* timeout */ 50000); 2686 2687 scsi_cmd = (struct scsi_mode_sense_6 *)&csio->cdb_io.cdb_bytes; 2688 bzero (scsi_cmd, sizeof(*scsi_cmd)); 2689 2690 scsi_cmd->page = page; 2691 scsi_cmd->length = sizeof(*data) & 0xff; 2692 scsi_cmd->opcode = MODE_SENSE; 2693 2694 error = cdrunccb(ccb, cderror, /*cam_flags*/0, 2695 /*sense_flags*/SF_RETRY_UA|SF_RETRY_SELTO); 2696 2697 xpt_release_ccb(ccb); 2698 2699 return(error); 2700} 2701 2702static int 2703cdsetmode(struct cam_periph *periph, struct cd_mode_data *data) 2704{ 2705 struct scsi_mode_select_6 *scsi_cmd; 2706 struct ccb_scsiio *csio; 2707 union ccb *ccb; 2708 int error; 2709 2710 ccb = cdgetccb(periph, /* priority */ 1); 2711 2712 csio = &ccb->csio; 2713 2714 error = 0; 2715 2716 cam_fill_csio(csio, 2717 /* retries */ 1, 2718 /* cbfcnp */ cddone, 2719 /* flags */ CAM_DIR_OUT, 2720 /* tag_action */ MSG_SIMPLE_Q_TAG, 2721 /* data_ptr */ (u_int8_t *)data, 2722 /* dxfer_len */ sizeof(*data), 2723 /* sense_len */ SSD_FULL_SIZE, 2724 sizeof(struct scsi_mode_select_6), 2725 /* timeout */ 50000); 2726 2727 scsi_cmd = (struct scsi_mode_select_6 *)&csio->cdb_io.cdb_bytes; 2728 2729 bzero(scsi_cmd, sizeof(*scsi_cmd)); 2730 scsi_cmd->opcode = MODE_SELECT; 2731 scsi_cmd->byte2 |= SMS_PF; 2732 scsi_cmd->length = sizeof(*data) & 0xff; 2733 data->header.data_length = 0; 2734 /* 2735 * SONY drives do not allow a mode select with a medium_type 2736 * value that has just been returned by a mode sense; use a 2737 * medium_type of 0 (Default) instead. 2738 */ 2739 data->header.medium_type = 0; 2740 2741 error = cdrunccb(ccb, cderror, /*cam_flags*/0, 2742 /*sense_flags*/SF_RETRY_UA | SF_RETRY_SELTO); 2743 2744 xpt_release_ccb(ccb); 2745 2746 return(error); 2747} 2748 2749 2750static int 2751cdplay(struct cam_periph *periph, u_int32_t blk, u_int32_t len) 2752{ 2753 struct ccb_scsiio *csio; 2754 union ccb *ccb; 2755 int error; 2756 u_int8_t cdb_len; 2757 2758 error = 0; 2759 ccb = cdgetccb(periph, /* priority */ 1); 2760 csio = &ccb->csio; 2761 /* 2762 * Use the smallest possible command to perform the operation. 2763 */ 2764 if ((len & 0xffff0000) == 0) { 2765 /* 2766 * We can fit in a 10 byte cdb. 2767 */ 2768 struct scsi_play_10 *scsi_cmd; 2769 2770 scsi_cmd = (struct scsi_play_10 *)&csio->cdb_io.cdb_bytes; 2771 bzero (scsi_cmd, sizeof(*scsi_cmd)); 2772 scsi_cmd->op_code = PLAY_10; 2773 scsi_ulto4b(blk, (u_int8_t *)scsi_cmd->blk_addr); 2774 scsi_ulto2b(len, (u_int8_t *)scsi_cmd->xfer_len); 2775 cdb_len = sizeof(*scsi_cmd); 2776 } else { 2777 struct scsi_play_12 *scsi_cmd; 2778 2779 scsi_cmd = (struct scsi_play_12 *)&csio->cdb_io.cdb_bytes; 2780 bzero (scsi_cmd, sizeof(*scsi_cmd)); 2781 scsi_cmd->op_code = PLAY_12; 2782 scsi_ulto4b(blk, (u_int8_t *)scsi_cmd->blk_addr); 2783 scsi_ulto4b(len, (u_int8_t *)scsi_cmd->xfer_len); 2784 cdb_len = sizeof(*scsi_cmd); 2785 } 2786 cam_fill_csio(csio, 2787 /*retries*/2, 2788 cddone, 2789 /*flags*/CAM_DIR_NONE, 2790 MSG_SIMPLE_Q_TAG, 2791 /*dataptr*/NULL, 2792 /*datalen*/0, 2793 /*sense_len*/SSD_FULL_SIZE, 2794 cdb_len, 2795 /*timeout*/50 * 1000); 2796 2797 error = cdrunccb(ccb, cderror, /*cam_flags*/0, 2798 /*sense_flags*/SF_RETRY_UA | SF_RETRY_SELTO); 2799 2800 xpt_release_ccb(ccb); 2801 2802 return(error); 2803} 2804 2805static int 2806cdplaymsf(struct cam_periph *periph, u_int32_t startm, u_int32_t starts, 2807 u_int32_t startf, u_int32_t endm, u_int32_t ends, u_int32_t endf) 2808{ 2809 struct scsi_play_msf *scsi_cmd; 2810 struct ccb_scsiio *csio; 2811 union ccb *ccb; 2812 int error; 2813 2814 error = 0; 2815 2816 ccb = cdgetccb(periph, /* priority */ 1); 2817 2818 csio = &ccb->csio; 2819 2820 cam_fill_csio(csio, 2821 /* retries */ 1, 2822 /* cbfcnp */ cddone, 2823 /* flags */ CAM_DIR_NONE, 2824 /* tag_action */ MSG_SIMPLE_Q_TAG, 2825 /* data_ptr */ NULL, 2826 /* dxfer_len */ 0, 2827 /* sense_len */ SSD_FULL_SIZE, 2828 sizeof(struct scsi_play_msf), 2829 /* timeout */ 50000); 2830 2831 scsi_cmd = (struct scsi_play_msf *)&csio->cdb_io.cdb_bytes; 2832 bzero (scsi_cmd, sizeof(*scsi_cmd)); 2833 2834 scsi_cmd->op_code = PLAY_MSF; 2835 scsi_cmd->start_m = startm; 2836 scsi_cmd->start_s = starts; 2837 scsi_cmd->start_f = startf; 2838 scsi_cmd->end_m = endm; 2839 scsi_cmd->end_s = ends; 2840 scsi_cmd->end_f = endf; 2841 2842 error = cdrunccb(ccb, cderror, /*cam_flags*/0, 2843 /*sense_flags*/SF_RETRY_UA | SF_RETRY_SELTO); 2844 2845 xpt_release_ccb(ccb); 2846 2847 return(error); 2848} 2849 2850 2851static int 2852cdplaytracks(struct cam_periph *periph, u_int32_t strack, u_int32_t sindex, 2853 u_int32_t etrack, u_int32_t eindex) 2854{ 2855 struct scsi_play_track *scsi_cmd; 2856 struct ccb_scsiio *csio; 2857 union ccb *ccb; 2858 int error; 2859 2860 error = 0; 2861 2862 ccb = cdgetccb(periph, /* priority */ 1); 2863 2864 csio = &ccb->csio; 2865 2866 cam_fill_csio(csio, 2867 /* retries */ 1, 2868 /* cbfcnp */ cddone, 2869 /* flags */ CAM_DIR_NONE, 2870 /* tag_action */ MSG_SIMPLE_Q_TAG, 2871 /* data_ptr */ NULL, 2872 /* dxfer_len */ 0, 2873 /* sense_len */ SSD_FULL_SIZE, 2874 sizeof(struct scsi_play_track), 2875 /* timeout */ 50000); 2876 2877 scsi_cmd = (struct scsi_play_track *)&csio->cdb_io.cdb_bytes; 2878 bzero (scsi_cmd, sizeof(*scsi_cmd)); 2879 2880 scsi_cmd->op_code = PLAY_TRACK; 2881 scsi_cmd->start_track = strack; 2882 scsi_cmd->start_index = sindex; 2883 scsi_cmd->end_track = etrack; 2884 scsi_cmd->end_index = eindex; 2885 2886 error = cdrunccb(ccb, cderror, /*cam_flags*/0, 2887 /*sense_flags*/SF_RETRY_UA | SF_RETRY_SELTO); 2888 2889 xpt_release_ccb(ccb); 2890 2891 return(error); 2892} 2893 2894static int 2895cdpause(struct cam_periph *periph, u_int32_t go) 2896{ 2897 struct scsi_pause *scsi_cmd; 2898 struct ccb_scsiio *csio; 2899 union ccb *ccb; 2900 int error; 2901 2902 error = 0; 2903 2904 ccb = cdgetccb(periph, /* priority */ 1); 2905 2906 csio = &ccb->csio; 2907 2908 cam_fill_csio(csio, 2909 /* retries */ 1, 2910 /* cbfcnp */ cddone, 2911 /* flags */ CAM_DIR_NONE, 2912 /* tag_action */ MSG_SIMPLE_Q_TAG, 2913 /* data_ptr */ NULL, 2914 /* dxfer_len */ 0, 2915 /* sense_len */ SSD_FULL_SIZE, 2916 sizeof(struct scsi_pause), 2917 /* timeout */ 50000); 2918 2919 scsi_cmd = (struct scsi_pause *)&csio->cdb_io.cdb_bytes; 2920 bzero (scsi_cmd, sizeof(*scsi_cmd)); 2921 2922 scsi_cmd->op_code = PAUSE; 2923 scsi_cmd->resume = go; 2924 2925 error = cdrunccb(ccb, cderror, /*cam_flags*/0, 2926 /*sense_flags*/SF_RETRY_UA |SF_RETRY_SELTO); 2927 2928 xpt_release_ccb(ccb); 2929 2930 return(error); 2931} 2932 2933static int 2934cdstartunit(struct cam_periph *periph) 2935{ 2936 union ccb *ccb; 2937 int error; 2938 2939 error = 0; 2940 2941 ccb = cdgetccb(periph, /* priority */ 1); 2942 2943 scsi_start_stop(&ccb->csio, 2944 /* retries */ 1, 2945 /* cbfcnp */ cddone, 2946 /* tag_action */ MSG_SIMPLE_Q_TAG, 2947 /* start */ TRUE, 2948 /* load_eject */ TRUE, 2949 /* immediate */ FALSE, 2950 /* sense_len */ SSD_FULL_SIZE, 2951 /* timeout */ 50000); 2952 2953 error = cdrunccb(ccb, cderror, /*cam_flags*/0, 2954 /*sense_flags*/SF_RETRY_UA | SF_RETRY_SELTO); 2955 2956 xpt_release_ccb(ccb); 2957 2958 return(error); 2959} 2960 2961static int 2962cdstopunit(struct cam_periph *periph, u_int32_t eject) 2963{ 2964 union ccb *ccb; 2965 int error; 2966 2967 error = 0; 2968 2969 ccb = cdgetccb(periph, /* priority */ 1); 2970 2971 scsi_start_stop(&ccb->csio, 2972 /* retries */ 1, 2973 /* cbfcnp */ cddone, 2974 /* tag_action */ MSG_SIMPLE_Q_TAG, 2975 /* start */ FALSE, 2976 /* load_eject */ eject, 2977 /* immediate */ FALSE, 2978 /* sense_len */ SSD_FULL_SIZE, 2979 /* timeout */ 50000); 2980 2981 error = cdrunccb(ccb, cderror, /*cam_flags*/0, 2982 /*sense_flags*/SF_RETRY_UA | SF_RETRY_SELTO); 2983 2984 xpt_release_ccb(ccb); 2985 2986 return(error); 2987} 2988 2989static int 2990cdreportkey(struct cam_periph *periph, struct dvd_authinfo *authinfo) 2991{ 2992 union ccb *ccb; 2993 u_int8_t *databuf; 2994 u_int32_t lba; 2995 int error; 2996 int length; 2997 2998 error = 0; 2999 databuf = NULL; 3000 lba = 0; 3001 3002 ccb = cdgetccb(periph, /* priority */ 1); 3003 3004 switch (authinfo->format) { 3005 case DVD_REPORT_AGID: 3006 length = sizeof(struct scsi_report_key_data_agid); 3007 break; 3008 case DVD_REPORT_CHALLENGE: 3009 length = sizeof(struct scsi_report_key_data_challenge); 3010 break; 3011 case DVD_REPORT_KEY1: 3012 length = sizeof(struct scsi_report_key_data_key1_key2); 3013 break; 3014 case DVD_REPORT_TITLE_KEY: 3015 length = sizeof(struct scsi_report_key_data_title); 3016 /* The lba field is only set for the title key */ 3017 lba = authinfo->lba; 3018 break; 3019 case DVD_REPORT_ASF: 3020 length = sizeof(struct scsi_report_key_data_asf); 3021 break; 3022 case DVD_REPORT_RPC: 3023 length = sizeof(struct scsi_report_key_data_rpc); 3024 break; 3025 case DVD_INVALIDATE_AGID: 3026 length = 0; 3027 break; 3028 default: 3029 error = EINVAL; 3030 goto bailout; 3031 break; /* NOTREACHED */ 3032 } 3033 3034 if (length != 0) { 3035 databuf = malloc(length, M_DEVBUF, M_WAITOK | M_ZERO); 3036 } else 3037 databuf = NULL; 3038 3039 3040 scsi_report_key(&ccb->csio, 3041 /* retries */ 1, 3042 /* cbfcnp */ cddone, 3043 /* tag_action */ MSG_SIMPLE_Q_TAG, 3044 /* lba */ lba, 3045 /* agid */ authinfo->agid, 3046 /* key_format */ authinfo->format, 3047 /* data_ptr */ databuf, 3048 /* dxfer_len */ length, 3049 /* sense_len */ SSD_FULL_SIZE, 3050 /* timeout */ 50000); 3051 3052 error = cdrunccb(ccb, cderror, /*cam_flags*/0, 3053 /*sense_flags*/SF_RETRY_UA | SF_RETRY_SELTO); 3054 3055 if (error != 0) 3056 goto bailout; 3057 3058 if (ccb->csio.resid != 0) { 3059 xpt_print_path(periph->path); 3060 printf("warning, residual for report key command is %d\n", 3061 ccb->csio.resid); 3062 } 3063 3064 switch(authinfo->format) { 3065 case DVD_REPORT_AGID: { 3066 struct scsi_report_key_data_agid *agid_data; 3067 3068 agid_data = (struct scsi_report_key_data_agid *)databuf; 3069 3070 authinfo->agid = (agid_data->agid & RKD_AGID_MASK) >> 3071 RKD_AGID_SHIFT; 3072 break; 3073 } 3074 case DVD_REPORT_CHALLENGE: { 3075 struct scsi_report_key_data_challenge *chal_data; 3076 3077 chal_data = (struct scsi_report_key_data_challenge *)databuf; 3078 3079 bcopy(chal_data->challenge_key, authinfo->keychal, 3080 min(sizeof(chal_data->challenge_key), 3081 sizeof(authinfo->keychal))); 3082 break; 3083 } 3084 case DVD_REPORT_KEY1: { 3085 struct scsi_report_key_data_key1_key2 *key1_data; 3086 3087 key1_data = (struct scsi_report_key_data_key1_key2 *)databuf; 3088 3089 bcopy(key1_data->key1, authinfo->keychal, 3090 min(sizeof(key1_data->key1), sizeof(authinfo->keychal))); 3091 break; 3092 } 3093 case DVD_REPORT_TITLE_KEY: { 3094 struct scsi_report_key_data_title *title_data; 3095 3096 title_data = (struct scsi_report_key_data_title *)databuf; 3097 3098 authinfo->cpm = (title_data->byte0 & RKD_TITLE_CPM) >> 3099 RKD_TITLE_CPM_SHIFT; 3100 authinfo->cp_sec = (title_data->byte0 & RKD_TITLE_CP_SEC) >> 3101 RKD_TITLE_CP_SEC_SHIFT; 3102 authinfo->cgms = (title_data->byte0 & RKD_TITLE_CMGS_MASK) >> 3103 RKD_TITLE_CMGS_SHIFT; 3104 bcopy(title_data->title_key, authinfo->keychal, 3105 min(sizeof(title_data->title_key), 3106 sizeof(authinfo->keychal))); 3107 break; 3108 } 3109 case DVD_REPORT_ASF: { 3110 struct scsi_report_key_data_asf *asf_data; 3111 3112 asf_data = (struct scsi_report_key_data_asf *)databuf; 3113 3114 authinfo->asf = asf_data->success & RKD_ASF_SUCCESS; 3115 break; 3116 } 3117 case DVD_REPORT_RPC: { 3118 struct scsi_report_key_data_rpc *rpc_data; 3119 3120 rpc_data = (struct scsi_report_key_data_rpc *)databuf; 3121 3122 authinfo->reg_type = (rpc_data->byte4 & RKD_RPC_TYPE_MASK) >> 3123 RKD_RPC_TYPE_SHIFT; 3124 authinfo->vend_rsts = 3125 (rpc_data->byte4 & RKD_RPC_VENDOR_RESET_MASK) >> 3126 RKD_RPC_VENDOR_RESET_SHIFT; 3127 authinfo->user_rsts = rpc_data->byte4 & RKD_RPC_USER_RESET_MASK; 3128 break; 3129 } 3130 case DVD_INVALIDATE_AGID: 3131 break; 3132 default: 3133 /* This should be impossible, since we checked above */ 3134 error = EINVAL; 3135 goto bailout; 3136 break; /* NOTREACHED */ 3137 } 3138bailout: 3139 if (databuf != NULL) 3140 free(databuf, M_DEVBUF); 3141 3142 xpt_release_ccb(ccb); 3143 3144 return(error); 3145} 3146 3147static int 3148cdsendkey(struct cam_periph *periph, struct dvd_authinfo *authinfo) 3149{ 3150 union ccb *ccb; 3151 u_int8_t *databuf; 3152 int length; 3153 int error; 3154 3155 error = 0; 3156 databuf = NULL; 3157 3158 ccb = cdgetccb(periph, /* priority */ 1); 3159 3160 switch(authinfo->format) { 3161 case DVD_SEND_CHALLENGE: { 3162 struct scsi_report_key_data_challenge *challenge_data; 3163 3164 length = sizeof(*challenge_data); 3165 3166 challenge_data = malloc(length, M_DEVBUF, M_WAITOK | M_ZERO); 3167 3168 databuf = (u_int8_t *)challenge_data; 3169 3170 scsi_ulto2b(length - sizeof(challenge_data->data_len), 3171 challenge_data->data_len); 3172 3173 bcopy(authinfo->keychal, challenge_data->challenge_key, 3174 min(sizeof(authinfo->keychal), 3175 sizeof(challenge_data->challenge_key))); 3176 break; 3177 } 3178 case DVD_SEND_KEY2: { 3179 struct scsi_report_key_data_key1_key2 *key2_data; 3180 3181 length = sizeof(*key2_data); 3182 3183 key2_data = malloc(length, M_DEVBUF, M_WAITOK | M_ZERO); 3184 3185 databuf = (u_int8_t *)key2_data; 3186 3187 scsi_ulto2b(length - sizeof(key2_data->data_len), 3188 key2_data->data_len); 3189 3190 bcopy(authinfo->keychal, key2_data->key1, 3191 min(sizeof(authinfo->keychal), sizeof(key2_data->key1))); 3192 3193 break; 3194 } 3195 case DVD_SEND_RPC: { 3196 struct scsi_send_key_data_rpc *rpc_data; 3197 3198 length = sizeof(*rpc_data); 3199 3200 rpc_data = malloc(length, M_DEVBUF, M_WAITOK | M_ZERO); 3201 3202 databuf = (u_int8_t *)rpc_data; 3203 3204 scsi_ulto2b(length - sizeof(rpc_data->data_len), 3205 rpc_data->data_len); 3206 3207 /* 3208 * XXX KDM is this the right field from authinfo to use? 3209 */ 3210 rpc_data->region_code = authinfo->region; 3211 break; 3212 } 3213 default: 3214 error = EINVAL; 3215 goto bailout; 3216 break; /* NOTREACHED */ 3217 } 3218 3219 scsi_send_key(&ccb->csio, 3220 /* retries */ 1, 3221 /* cbfcnp */ cddone, 3222 /* tag_action */ MSG_SIMPLE_Q_TAG, 3223 /* agid */ authinfo->agid, 3224 /* key_format */ authinfo->format, 3225 /* data_ptr */ databuf, 3226 /* dxfer_len */ length, 3227 /* sense_len */ SSD_FULL_SIZE, 3228 /* timeout */ 50000); 3229 3230 error = cdrunccb(ccb, cderror, /*cam_flags*/0, 3231 /*sense_flags*/SF_RETRY_UA | SF_RETRY_SELTO); 3232 3233bailout: 3234 3235 if (databuf != NULL) 3236 free(databuf, M_DEVBUF); 3237 3238 xpt_release_ccb(ccb); 3239 3240 return(error); 3241} 3242 3243static int 3244cdreaddvdstructure(struct cam_periph *periph, struct dvd_struct *dvdstruct) 3245{ 3246 union ccb *ccb; 3247 u_int8_t *databuf; 3248 u_int32_t address; 3249 int error; 3250 int length; 3251 3252 error = 0; 3253 databuf = NULL; 3254 /* The address is reserved for many of the formats */ 3255 address = 0; 3256 3257 ccb = cdgetccb(periph, /* priority */ 1); 3258 3259 switch(dvdstruct->format) { 3260 case DVD_STRUCT_PHYSICAL: 3261 length = sizeof(struct scsi_read_dvd_struct_data_physical); 3262 break; 3263 case DVD_STRUCT_COPYRIGHT: 3264 length = sizeof(struct scsi_read_dvd_struct_data_copyright); 3265 break; 3266 case DVD_STRUCT_DISCKEY: 3267 length = sizeof(struct scsi_read_dvd_struct_data_disc_key); 3268 break; 3269 case DVD_STRUCT_BCA: 3270 length = sizeof(struct scsi_read_dvd_struct_data_bca); 3271 break; 3272 case DVD_STRUCT_MANUFACT: 3273 length = sizeof(struct scsi_read_dvd_struct_data_manufacturer); 3274 break; 3275 case DVD_STRUCT_CMI: 3276 error = ENODEV; 3277 goto bailout; 3278#ifdef notyet 3279 length = sizeof(struct scsi_read_dvd_struct_data_copy_manage); 3280 address = dvdstruct->address; 3281#endif 3282 break; /* NOTREACHED */ 3283 case DVD_STRUCT_PROTDISCID: 3284 length = sizeof(struct scsi_read_dvd_struct_data_prot_discid); 3285 break; 3286 case DVD_STRUCT_DISCKEYBLOCK: 3287 length = sizeof(struct scsi_read_dvd_struct_data_disc_key_blk); 3288 break; 3289 case DVD_STRUCT_DDS: 3290 length = sizeof(struct scsi_read_dvd_struct_data_dds); 3291 break; 3292 case DVD_STRUCT_MEDIUM_STAT: 3293 length = sizeof(struct scsi_read_dvd_struct_data_medium_status); 3294 break; 3295 case DVD_STRUCT_SPARE_AREA: 3296 length = sizeof(struct scsi_read_dvd_struct_data_spare_area); 3297 break; 3298 case DVD_STRUCT_RMD_LAST: 3299 error = ENODEV; 3300 goto bailout; 3301#ifdef notyet 3302 length = sizeof(struct scsi_read_dvd_struct_data_rmd_borderout); 3303 address = dvdstruct->address; 3304#endif 3305 break; /* NOTREACHED */ 3306 case DVD_STRUCT_RMD_RMA: 3307 error = ENODEV; 3308 goto bailout; 3309#ifdef notyet 3310 length = sizeof(struct scsi_read_dvd_struct_data_rmd); 3311 address = dvdstruct->address; 3312#endif 3313 break; /* NOTREACHED */ 3314 case DVD_STRUCT_PRERECORDED: 3315 length = sizeof(struct scsi_read_dvd_struct_data_leadin); 3316 break; 3317 case DVD_STRUCT_UNIQUEID: 3318 length = sizeof(struct scsi_read_dvd_struct_data_disc_id); 3319 break; 3320 case DVD_STRUCT_DCB: 3321 error = ENODEV; 3322 goto bailout; 3323#ifdef notyet 3324 length = sizeof(struct scsi_read_dvd_struct_data_dcb); 3325 address = dvdstruct->address; 3326#endif 3327 break; /* NOTREACHED */ 3328 case DVD_STRUCT_LIST: 3329 /* 3330 * This is the maximum allocation length for the READ DVD 3331 * STRUCTURE command. There's nothing in the MMC3 spec 3332 * that indicates a limit in the amount of data that can 3333 * be returned from this call, other than the limits 3334 * imposed by the 2-byte length variables. 3335 */ 3336 length = 65535; 3337 break; 3338 default: 3339 error = EINVAL; 3340 goto bailout; 3341 break; /* NOTREACHED */ 3342 } 3343 3344 if (length != 0) { 3345 databuf = malloc(length, M_DEVBUF, M_WAITOK | M_ZERO); 3346 } else 3347 databuf = NULL; 3348 3349 scsi_read_dvd_structure(&ccb->csio, 3350 /* retries */ 1, 3351 /* cbfcnp */ cddone, 3352 /* tag_action */ MSG_SIMPLE_Q_TAG, 3353 /* lba */ address, 3354 /* layer_number */ dvdstruct->layer_num, 3355 /* key_format */ dvdstruct->format, 3356 /* agid */ dvdstruct->agid, 3357 /* data_ptr */ databuf, 3358 /* dxfer_len */ length, 3359 /* sense_len */ SSD_FULL_SIZE, 3360 /* timeout */ 50000); 3361 3362 error = cdrunccb(ccb, cderror, /*cam_flags*/0, 3363 /*sense_flags*/SF_RETRY_UA | SF_RETRY_SELTO); 3364 3365 if (error != 0) 3366 goto bailout; 3367 3368 switch(dvdstruct->format) { 3369 case DVD_STRUCT_PHYSICAL: { 3370 struct scsi_read_dvd_struct_data_layer_desc *inlayer; 3371 struct dvd_layer *outlayer; 3372 struct scsi_read_dvd_struct_data_physical *phys_data; 3373 3374 phys_data = 3375 (struct scsi_read_dvd_struct_data_physical *)databuf; 3376 inlayer = &phys_data->layer_desc; 3377 outlayer = (struct dvd_layer *)&dvdstruct->data; 3378 3379 dvdstruct->length = sizeof(*inlayer); 3380 3381 outlayer->book_type = (inlayer->book_type_version & 3382 RDSD_BOOK_TYPE_MASK) >> RDSD_BOOK_TYPE_SHIFT; 3383 outlayer->book_version = (inlayer->book_type_version & 3384 RDSD_BOOK_VERSION_MASK); 3385 outlayer->disc_size = (inlayer->disc_size_max_rate & 3386 RDSD_DISC_SIZE_MASK) >> RDSD_DISC_SIZE_SHIFT; 3387 outlayer->max_rate = (inlayer->disc_size_max_rate & 3388 RDSD_MAX_RATE_MASK); 3389 outlayer->nlayers = (inlayer->layer_info & 3390 RDSD_NUM_LAYERS_MASK) >> RDSD_NUM_LAYERS_SHIFT; 3391 outlayer->track_path = (inlayer->layer_info & 3392 RDSD_TRACK_PATH_MASK) >> RDSD_TRACK_PATH_SHIFT; 3393 outlayer->layer_type = (inlayer->layer_info & 3394 RDSD_LAYER_TYPE_MASK); 3395 outlayer->linear_density = (inlayer->density & 3396 RDSD_LIN_DENSITY_MASK) >> RDSD_LIN_DENSITY_SHIFT; 3397 outlayer->track_density = (inlayer->density & 3398 RDSD_TRACK_DENSITY_MASK); 3399 outlayer->bca = (inlayer->bca & RDSD_BCA_MASK) >> 3400 RDSD_BCA_SHIFT; 3401 outlayer->start_sector = scsi_3btoul(inlayer->main_data_start); 3402 outlayer->end_sector = scsi_3btoul(inlayer->main_data_end); 3403 outlayer->end_sector_l0 = 3404 scsi_3btoul(inlayer->end_sector_layer0); 3405 break; 3406 } 3407 case DVD_STRUCT_COPYRIGHT: { 3408 struct scsi_read_dvd_struct_data_copyright *copy_data; 3409 3410 copy_data = (struct scsi_read_dvd_struct_data_copyright *) 3411 databuf; 3412 3413 dvdstruct->cpst = copy_data->cps_type; 3414 dvdstruct->rmi = copy_data->region_info; 3415 dvdstruct->length = 0; 3416 3417 break; 3418 } 3419 default: 3420 /* 3421 * Tell the user what the overall length is, no matter 3422 * what we can actually fit in the data buffer. 3423 */ 3424 dvdstruct->length = length - ccb->csio.resid - 3425 sizeof(struct scsi_read_dvd_struct_data_header); 3426 3427 /* 3428 * But only actually copy out the smaller of what we read 3429 * in or what the structure can take. 3430 */ 3431 bcopy(databuf + sizeof(struct scsi_read_dvd_struct_data_header), 3432 dvdstruct->data, 3433 min(sizeof(dvdstruct->data), dvdstruct->length)); 3434 break; 3435 } 3436bailout: 3437 3438 if (databuf != NULL) 3439 free(databuf, M_DEVBUF); 3440 3441 xpt_release_ccb(ccb); 3442 3443 return(error); 3444} 3445 3446void 3447scsi_report_key(struct ccb_scsiio *csio, u_int32_t retries, 3448 void (*cbfcnp)(struct cam_periph *, union ccb *), 3449 u_int8_t tag_action, u_int32_t lba, u_int8_t agid, 3450 u_int8_t key_format, u_int8_t *data_ptr, u_int32_t dxfer_len, 3451 u_int8_t sense_len, u_int32_t timeout) 3452{ 3453 struct scsi_report_key *scsi_cmd; 3454 3455 scsi_cmd = (struct scsi_report_key *)&csio->cdb_io.cdb_bytes; 3456 bzero(scsi_cmd, sizeof(*scsi_cmd)); 3457 scsi_cmd->opcode = REPORT_KEY; 3458 scsi_ulto4b(lba, scsi_cmd->lba); 3459 scsi_ulto2b(dxfer_len, scsi_cmd->alloc_len); 3460 scsi_cmd->agid_keyformat = (agid << RK_KF_AGID_SHIFT) | 3461 (key_format & RK_KF_KEYFORMAT_MASK); 3462 3463 cam_fill_csio(csio, 3464 retries, 3465 cbfcnp, 3466 /*flags*/ (dxfer_len == 0) ? CAM_DIR_NONE : CAM_DIR_IN, 3467 tag_action, 3468 /*data_ptr*/ data_ptr, 3469 /*dxfer_len*/ dxfer_len, 3470 sense_len, 3471 sizeof(*scsi_cmd), 3472 timeout); 3473} 3474 3475void 3476scsi_send_key(struct ccb_scsiio *csio, u_int32_t retries, 3477 void (*cbfcnp)(struct cam_periph *, union ccb *), 3478 u_int8_t tag_action, u_int8_t agid, u_int8_t key_format, 3479 u_int8_t *data_ptr, u_int32_t dxfer_len, u_int8_t sense_len, 3480 u_int32_t timeout) 3481{ 3482 struct scsi_send_key *scsi_cmd; 3483 3484 scsi_cmd = (struct scsi_send_key *)&csio->cdb_io.cdb_bytes; 3485 bzero(scsi_cmd, sizeof(*scsi_cmd)); 3486 scsi_cmd->opcode = SEND_KEY; 3487 3488 scsi_ulto2b(dxfer_len, scsi_cmd->param_len); 3489 scsi_cmd->agid_keyformat = (agid << RK_KF_AGID_SHIFT) | 3490 (key_format & RK_KF_KEYFORMAT_MASK); 3491 3492 cam_fill_csio(csio, 3493 retries, 3494 cbfcnp, 3495 /*flags*/ CAM_DIR_OUT, 3496 tag_action, 3497 /*data_ptr*/ data_ptr, 3498 /*dxfer_len*/ dxfer_len, 3499 sense_len, 3500 sizeof(*scsi_cmd), 3501 timeout); 3502} 3503 3504 3505void 3506scsi_read_dvd_structure(struct ccb_scsiio *csio, u_int32_t retries, 3507 void (*cbfcnp)(struct cam_periph *, union ccb *), 3508 u_int8_t tag_action, u_int32_t address, 3509 u_int8_t layer_number, u_int8_t format, u_int8_t agid, 3510 u_int8_t *data_ptr, u_int32_t dxfer_len, 3511 u_int8_t sense_len, u_int32_t timeout) 3512{ 3513 struct scsi_read_dvd_structure *scsi_cmd; 3514 3515 scsi_cmd = (struct scsi_read_dvd_structure *)&csio->cdb_io.cdb_bytes; 3516 bzero(scsi_cmd, sizeof(*scsi_cmd)); 3517 scsi_cmd->opcode = READ_DVD_STRUCTURE; 3518 3519 scsi_ulto4b(address, scsi_cmd->address); 3520 scsi_cmd->layer_number = layer_number; 3521 scsi_cmd->format = format; 3522 scsi_ulto2b(dxfer_len, scsi_cmd->alloc_len); 3523 /* The AGID is the top two bits of this byte */ 3524 scsi_cmd->agid = agid << 6; 3525 3526 cam_fill_csio(csio, 3527 retries, 3528 cbfcnp, 3529 /*flags*/ CAM_DIR_IN, 3530 tag_action, 3531 /*data_ptr*/ data_ptr, 3532 /*dxfer_len*/ dxfer_len, 3533 sense_len, 3534 sizeof(*scsi_cmd), 3535 timeout); 3536} 3537