scsi_cd.c revision 119708
1/* 2 * Copyright (c) 1997 Justin T. Gibbs. 3 * Copyright (c) 1997, 1998, 1999, 2000, 2001, 2002, 2003 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 28/* 29 * Portions of this driver taken from the original FreeBSD cd driver. 30 * Written by Julian Elischer (julian@tfs.com) 31 * for TRW Financial Systems for use under the MACH(2.5) operating system. 32 * 33 * TRW Financial Systems, in accordance with their agreement with Carnegie 34 * Mellon University, makes this software available to CMU to distribute 35 * or use in any manner that they see fit as long as this message is kept with 36 * the software. For this reason TFS also grants any other persons or 37 * organisations permission to use or modify this software. 38 * 39 * TFS supplies this software to be publicly redistributed 40 * on the understanding that TFS is not responsible for the correct 41 * functioning of this software in any circumstances. 42 * 43 * Ported to run under 386BSD by Julian Elischer (julian@tfs.com) Sept 1992 44 * 45 * from: cd.c,v 1.83 1997/05/04 15:24:22 joerg Exp $ 46 */ 47 48#include <sys/cdefs.h> 49__FBSDID("$FreeBSD: head/sys/cam/scsi/scsi_cd.c 119708 2003-09-03 04:46:28Z ken $"); 50 51#include "opt_cd.h" 52 53#include <sys/param.h> 54#include <sys/systm.h> 55#include <sys/kernel.h> 56#include <sys/bio.h> 57#include <sys/conf.h> 58#include <sys/disk.h> 59#include <sys/malloc.h> 60#include <sys/cdio.h> 61#include <sys/cdrio.h> 62#include <sys/dvdio.h> 63#include <sys/devicestat.h> 64#include <sys/sysctl.h> 65#include <sys/taskqueue.h> 66 67#include <cam/cam.h> 68#include <cam/cam_ccb.h> 69#include <cam/cam_periph.h> 70#include <cam/cam_xpt_periph.h> 71#include <cam/cam_queue.h> 72 73#include <cam/scsi/scsi_message.h> 74#include <cam/scsi/scsi_da.h> 75#include <cam/scsi/scsi_cd.h> 76 77#define LEADOUT 0xaa /* leadout toc entry */ 78 79struct cd_params { 80 u_int32_t blksize; 81 u_long disksize; 82}; 83 84typedef enum { 85 CD_Q_NONE = 0x00, 86 CD_Q_NO_TOUCH = 0x01, 87 CD_Q_BCD_TRACKS = 0x02, 88 CD_Q_NO_CHANGER = 0x04, 89 CD_Q_CHANGER = 0x08, 90 CD_Q_10_BYTE_ONLY = 0x10 91} cd_quirks; 92 93typedef enum { 94 CD_FLAG_INVALID = 0x001, 95 CD_FLAG_NEW_DISC = 0x002, 96 CD_FLAG_DISC_LOCKED = 0x004, 97 CD_FLAG_DISC_REMOVABLE = 0x008, 98 CD_FLAG_TAGGED_QUEUING = 0x010, 99 CD_FLAG_CHANGER = 0x040, 100 CD_FLAG_ACTIVE = 0x080, 101 CD_FLAG_SCHED_ON_COMP = 0x100, 102 CD_FLAG_RETRY_UA = 0x200, 103 CD_FLAG_VALID_MEDIA = 0x400, 104 CD_FLAG_VALID_TOC = 0x800 105} cd_flags; 106 107typedef enum { 108 CD_CCB_PROBE = 0x01, 109 CD_CCB_BUFFER_IO = 0x02, 110 CD_CCB_WAITING = 0x03, 111 CD_CCB_TYPE_MASK = 0x0F, 112 CD_CCB_RETRY_UA = 0x10 113} cd_ccb_state; 114 115typedef enum { 116 CHANGER_TIMEOUT_SCHED = 0x01, 117 CHANGER_SHORT_TMOUT_SCHED = 0x02, 118 CHANGER_MANUAL_CALL = 0x04, 119 CHANGER_NEED_TIMEOUT = 0x08 120} cd_changer_flags; 121 122#define ccb_state ppriv_field0 123#define ccb_bp ppriv_ptr1 124 125struct cd_tocdata { 126 struct ioc_toc_header header; 127 struct cd_toc_entry entries[100]; 128}; 129 130struct cd_toc_single { 131 struct ioc_toc_header header; 132 struct cd_toc_entry entry; 133}; 134 135typedef enum { 136 CD_STATE_PROBE, 137 CD_STATE_NORMAL 138} cd_state; 139 140struct cd_softc { 141 cam_pinfo pinfo; 142 cd_state state; 143 volatile cd_flags flags; 144 struct bio_queue_head bio_queue; 145 LIST_HEAD(, ccb_hdr) pending_ccbs; 146 struct cd_params params; 147 union ccb saved_ccb; 148 cd_quirks quirks; 149 struct devstat *device_stats; 150 STAILQ_ENTRY(cd_softc) changer_links; 151 struct cdchanger *changer; 152 int bufs_left; 153 struct cam_periph *periph; 154 dev_t dev; 155 eventhandler_tag clonetag; 156 int minimum_command_size; 157 int outstanding_cmds; 158 struct task sysctl_task; 159 struct sysctl_ctx_list sysctl_ctx; 160 struct sysctl_oid *sysctl_tree; 161 STAILQ_HEAD(, cd_mode_params) mode_queue; 162 struct cd_tocdata toc; 163}; 164 165struct cd_page_sizes { 166 int page; 167 int page_size; 168}; 169 170static struct cd_page_sizes cd_page_size_table[] = 171{ 172 { AUDIO_PAGE, sizeof(struct cd_audio_page)} 173}; 174 175struct cd_quirk_entry { 176 struct scsi_inquiry_pattern inq_pat; 177 cd_quirks quirks; 178}; 179 180/* 181 * The changer quirk entries aren't strictly necessary. Basically, what 182 * they do is tell cdregister() up front that a device is a changer. 183 * Otherwise, it will figure that fact out once it sees a LUN on the device 184 * that is greater than 0. If it is known up front that a device is a changer, 185 * all I/O to the device will go through the changer scheduling routines, as 186 * opposed to the "normal" CD code. 187 * 188 * NOTE ON 10_BYTE_ONLY quirks: Any 10_BYTE_ONLY quirks MUST be because 189 * your device hangs when it gets a 10 byte command. Adding a quirk just 190 * to get rid of the informative diagnostic message is not acceptable. All 191 * 10_BYTE_ONLY quirks must be documented in full in a PR (which should be 192 * referenced in a comment along with the quirk) , and must be approved by 193 * ken@FreeBSD.org. Any quirks added that don't adhere to this policy may 194 * be removed until the submitter can explain why they are needed. 195 * 10_BYTE_ONLY quirks will be removed (as they will no longer be necessary) 196 * when the CAM_NEW_TRAN_CODE work is done. 197 */ 198static struct cd_quirk_entry cd_quirk_table[] = 199{ 200 { 201 { T_CDROM, SIP_MEDIA_REMOVABLE, "NRC", "MBR-7", "*"}, 202 /*quirks*/ CD_Q_CHANGER 203 }, 204 { 205 { T_CDROM, SIP_MEDIA_REMOVABLE, "PIONEER", "CD-ROM DRM*", 206 "*"}, /* quirks */ CD_Q_CHANGER 207 }, 208 { 209 { T_CDROM, SIP_MEDIA_REMOVABLE, "NAKAMICH", "MJ-*", "*"}, 210 /* quirks */ CD_Q_CHANGER 211 }, 212 { 213 { T_CDROM, SIP_MEDIA_REMOVABLE, "CHINON", "CD-ROM CDS-535","*"}, 214 /* quirks */ CD_Q_BCD_TRACKS 215 } 216}; 217 218#define CD_CDEV_MAJOR 15 219 220static d_open_t cdopen; 221static d_close_t cdclose; 222static d_ioctl_t cdioctl; 223static d_strategy_t cdstrategy; 224 225static periph_init_t cdinit; 226static periph_ctor_t cdregister; 227static periph_dtor_t cdcleanup; 228static periph_start_t cdstart; 229static periph_oninv_t cdoninvalidate; 230static void cdasync(void *callback_arg, u_int32_t code, 231 struct cam_path *path, void *arg); 232static int cdcmdsizesysctl(SYSCTL_HANDLER_ARGS); 233static void cdshorttimeout(void *arg); 234static void cdschedule(struct cam_periph *periph, int priority); 235static void cdrunchangerqueue(void *arg); 236static void cdchangerschedule(struct cd_softc *softc); 237static int cdrunccb(union ccb *ccb, 238 int (*error_routine)(union ccb *ccb, 239 u_int32_t cam_flags, 240 u_int32_t sense_flags), 241 u_int32_t cam_flags, u_int32_t sense_flags); 242static union ccb *cdgetccb(struct cam_periph *periph, 243 u_int32_t priority); 244static void cddone(struct cam_periph *periph, 245 union ccb *start_ccb); 246static union cd_pages *cdgetpage(struct cd_mode_params *mode_params); 247static int cdgetpagesize(int page_num); 248static void cdprevent(struct cam_periph *periph, int action); 249static int cdcheckmedia(struct cam_periph *periph); 250static int cdsize(struct cam_periph *periph, u_int32_t *size); 251static int cd6byteworkaround(union ccb *ccb); 252static int cderror(union ccb *ccb, u_int32_t cam_flags, 253 u_int32_t sense_flags); 254static int cdreadtoc(struct cam_periph *periph, u_int32_t mode, 255 u_int32_t start, u_int8_t *data, 256 u_int32_t len, u_int32_t sense_flags); 257static int cdgetmode(struct cam_periph *periph, 258 struct cd_mode_params *data, u_int32_t page); 259static int cdsetmode(struct cam_periph *periph, 260 struct cd_mode_params *data); 261static int cdplay(struct cam_periph *periph, u_int32_t blk, 262 u_int32_t len); 263static int cdreadsubchannel(struct cam_periph *periph, 264 u_int32_t mode, u_int32_t format, 265 int track, 266 struct cd_sub_channel_info *data, 267 u_int32_t len); 268static int cdplaymsf(struct cam_periph *periph, u_int32_t startm, 269 u_int32_t starts, u_int32_t startf, 270 u_int32_t endm, u_int32_t ends, 271 u_int32_t endf); 272static int cdplaytracks(struct cam_periph *periph, 273 u_int32_t strack, u_int32_t sindex, 274 u_int32_t etrack, u_int32_t eindex); 275static int cdpause(struct cam_periph *periph, u_int32_t go); 276static int cdstopunit(struct cam_periph *periph, u_int32_t eject); 277static int cdstartunit(struct cam_periph *periph, int load); 278static int cdsetspeed(struct cam_periph *periph, 279 u_int32_t rdspeed, u_int32_t wrspeed); 280static int cdreportkey(struct cam_periph *periph, 281 struct dvd_authinfo *authinfo); 282static int cdsendkey(struct cam_periph *periph, 283 struct dvd_authinfo *authinfo); 284static int cdreaddvdstructure(struct cam_periph *periph, 285 struct dvd_struct *dvdstruct); 286 287static struct periph_driver cddriver = 288{ 289 cdinit, "cd", 290 TAILQ_HEAD_INITIALIZER(cddriver.units), /* generation */ 0 291}; 292 293PERIPHDRIVER_DECLARE(cd, cddriver); 294 295static struct cdevsw cd_cdevsw = { 296 .d_open = cdopen, 297 .d_close = cdclose, 298 .d_read = physread, 299 .d_write = physwrite, 300 .d_ioctl = cdioctl, 301 .d_strategy = cdstrategy, 302 .d_name = "cd", 303 .d_maj = CD_CDEV_MAJOR, 304 .d_flags = D_DISK, 305}; 306 307static int num_changers; 308 309#ifndef CHANGER_MIN_BUSY_SECONDS 310#define CHANGER_MIN_BUSY_SECONDS 5 311#endif 312#ifndef CHANGER_MAX_BUSY_SECONDS 313#define CHANGER_MAX_BUSY_SECONDS 15 314#endif 315 316static int changer_min_busy_seconds = CHANGER_MIN_BUSY_SECONDS; 317static int changer_max_busy_seconds = CHANGER_MAX_BUSY_SECONDS; 318 319SYSCTL_NODE(_kern_cam, OID_AUTO, cd, CTLFLAG_RD, 0, "CAM CDROM driver"); 320SYSCTL_NODE(_kern_cam_cd, OID_AUTO, changer, CTLFLAG_RD, 0, "CD Changer"); 321SYSCTL_INT(_kern_cam_cd_changer, OID_AUTO, min_busy_seconds, CTLFLAG_RW, 322 &changer_min_busy_seconds, 0, "Minimum changer scheduling quantum"); 323TUNABLE_INT("kern.cam.cd.changer.min_busy_seconds", &changer_min_busy_seconds); 324SYSCTL_INT(_kern_cam_cd_changer, OID_AUTO, max_busy_seconds, CTLFLAG_RW, 325 &changer_max_busy_seconds, 0, "Maximum changer scheduling quantum"); 326TUNABLE_INT("kern.cam.cd.changer.max_busy_seconds", &changer_max_busy_seconds); 327 328struct cdchanger { 329 path_id_t path_id; 330 target_id_t target_id; 331 int num_devices; 332 struct camq devq; 333 struct timeval start_time; 334 struct cd_softc *cur_device; 335 struct callout_handle short_handle; 336 struct callout_handle long_handle; 337 volatile cd_changer_flags flags; 338 STAILQ_ENTRY(cdchanger) changer_links; 339 STAILQ_HEAD(chdevlist, cd_softc) chluns; 340}; 341 342static STAILQ_HEAD(changerlist, cdchanger) changerq; 343 344static void 345cdclone(void *arg, char *name, int namelen, dev_t *dev) 346{ 347 struct cd_softc *softc; 348 const char *p; 349 int l; 350 351 softc = arg; 352 p = devtoname(softc->dev); 353 l = strlen(p); 354 if (bcmp(name, p, l)) 355 return; 356 if (name[l] != 'a' && name[l] != 'c') 357 return; 358 if (name[l + 1] != '\0') 359 return; 360 *dev = softc->dev; 361 return; 362} 363 364static void 365cdinit(void) 366{ 367 cam_status status; 368 struct cam_path *path; 369 370 /* 371 * Install a global async callback. This callback will 372 * receive async callbacks like "new device found". 373 */ 374 status = xpt_create_path(&path, /*periph*/NULL, CAM_XPT_PATH_ID, 375 CAM_TARGET_WILDCARD, CAM_LUN_WILDCARD); 376 377 if (status == CAM_REQ_CMP) { 378 struct ccb_setasync csa; 379 380 xpt_setup_ccb(&csa.ccb_h, path, /*priority*/5); 381 csa.ccb_h.func_code = XPT_SASYNC_CB; 382 csa.event_enable = AC_FOUND_DEVICE; 383 csa.callback = cdasync; 384 csa.callback_arg = NULL; 385 xpt_action((union ccb *)&csa); 386 status = csa.ccb_h.status; 387 xpt_free_path(path); 388 } 389 390 if (status != CAM_REQ_CMP) { 391 printf("cd: Failed to attach master async callback " 392 "due to status 0x%x!\n", status); 393 } 394} 395 396static void 397cdoninvalidate(struct cam_periph *periph) 398{ 399 int s; 400 struct cd_softc *softc; 401 struct ccb_setasync csa; 402 403 softc = (struct cd_softc *)periph->softc; 404 405 /* 406 * De-register any async callbacks. 407 */ 408 xpt_setup_ccb(&csa.ccb_h, periph->path, 409 /* priority */ 5); 410 csa.ccb_h.func_code = XPT_SASYNC_CB; 411 csa.event_enable = 0; 412 csa.callback = cdasync; 413 csa.callback_arg = periph; 414 xpt_action((union ccb *)&csa); 415 416 softc->flags |= CD_FLAG_INVALID; 417 418 /* 419 * Although the oninvalidate() routines are always called at 420 * splsoftcam, we need to be at splbio() here to keep the buffer 421 * queue from being modified while we traverse it. 422 */ 423 s = splbio(); 424 425 /* 426 * Return all queued I/O with ENXIO. 427 * XXX Handle any transactions queued to the card 428 * with XPT_ABORT_CCB. 429 */ 430 bioq_flush(&softc->bio_queue, NULL, ENXIO); 431 splx(s); 432 433 /* 434 * If this device is part of a changer, and it was scheduled 435 * to run, remove it from the run queue since we just nuked 436 * all of its scheduled I/O. 437 */ 438 if ((softc->flags & CD_FLAG_CHANGER) 439 && (softc->pinfo.index != CAM_UNQUEUED_INDEX)) 440 camq_remove(&softc->changer->devq, softc->pinfo.index); 441 442 xpt_print_path(periph->path); 443 printf("lost device\n"); 444} 445 446static void 447cdcleanup(struct cam_periph *periph) 448{ 449 struct cd_softc *softc; 450 int s; 451 452 softc = (struct cd_softc *)periph->softc; 453 454 xpt_print_path(periph->path); 455 printf("removing device entry\n"); 456 457 if (sysctl_ctx_free(&softc->sysctl_ctx) != 0) { 458 xpt_print_path(periph->path); 459 printf("can't remove sysctl context\n"); 460 } 461 462 s = splsoftcam(); 463 /* 464 * In the queued, non-active case, the device in question 465 * has already been removed from the changer run queue. Since this 466 * device is active, we need to de-activate it, and schedule 467 * another device to run. (if there is another one to run) 468 */ 469 if ((softc->flags & CD_FLAG_CHANGER) 470 && (softc->flags & CD_FLAG_ACTIVE)) { 471 472 /* 473 * The purpose of the short timeout is soley to determine 474 * whether the current device has finished or not. Well, 475 * since we're removing the active device, we know that it 476 * is finished. So, get rid of the short timeout. 477 * Otherwise, if we're in the time period before the short 478 * timeout fires, and there are no other devices in the 479 * queue to run, there won't be any other device put in the 480 * active slot. i.e., when we call cdrunchangerqueue() 481 * below, it won't do anything. Then, when the short 482 * timeout fires, it'll look at the "current device", which 483 * we are free below, and possibly panic the kernel on a 484 * bogus pointer reference. 485 * 486 * The long timeout doesn't really matter, since we 487 * decrement the qfrozen_cnt to indicate that there is 488 * nothing in the active slot now. Therefore, there won't 489 * be any bogus pointer references there. 490 */ 491 if (softc->changer->flags & CHANGER_SHORT_TMOUT_SCHED) { 492 untimeout(cdshorttimeout, softc->changer, 493 softc->changer->short_handle); 494 softc->changer->flags &= ~CHANGER_SHORT_TMOUT_SCHED; 495 } 496 softc->changer->devq.qfrozen_cnt--; 497 softc->changer->flags |= CHANGER_MANUAL_CALL; 498 cdrunchangerqueue(softc->changer); 499 } 500 501 /* 502 * If we're removing the last device on the changer, go ahead and 503 * remove the changer device structure. 504 */ 505 if ((softc->flags & CD_FLAG_CHANGER) 506 && (--softc->changer->num_devices == 0)) { 507 508 /* 509 * Theoretically, there shouldn't be any timeouts left, but 510 * I'm not completely sure that that will be the case. So, 511 * it won't hurt to check and see if there are any left. 512 */ 513 if (softc->changer->flags & CHANGER_TIMEOUT_SCHED) { 514 untimeout(cdrunchangerqueue, softc->changer, 515 softc->changer->long_handle); 516 softc->changer->flags &= ~CHANGER_TIMEOUT_SCHED; 517 } 518 519 if (softc->changer->flags & CHANGER_SHORT_TMOUT_SCHED) { 520 untimeout(cdshorttimeout, softc->changer, 521 softc->changer->short_handle); 522 softc->changer->flags &= ~CHANGER_SHORT_TMOUT_SCHED; 523 } 524 525 STAILQ_REMOVE(&changerq, softc->changer, cdchanger, 526 changer_links); 527 xpt_print_path(periph->path); 528 printf("removing changer entry\n"); 529 free(softc->changer, M_DEVBUF); 530 num_changers--; 531 } 532 devstat_remove_entry(softc->device_stats); 533 destroy_dev(softc->dev); 534 EVENTHANDLER_DEREGISTER(dev_clone, softc->clonetag); 535 free(softc, M_DEVBUF); 536 splx(s); 537} 538 539static void 540cdasync(void *callback_arg, u_int32_t code, 541 struct cam_path *path, void *arg) 542{ 543 struct cam_periph *periph; 544 545 periph = (struct cam_periph *)callback_arg; 546 switch (code) { 547 case AC_FOUND_DEVICE: 548 { 549 struct ccb_getdev *cgd; 550 cam_status status; 551 552 cgd = (struct ccb_getdev *)arg; 553 if (cgd == NULL) 554 break; 555 556 if (SID_TYPE(&cgd->inq_data) != T_CDROM 557 && SID_TYPE(&cgd->inq_data) != T_WORM) 558 break; 559 560 /* 561 * Allocate a peripheral instance for 562 * this device and start the probe 563 * process. 564 */ 565 status = cam_periph_alloc(cdregister, cdoninvalidate, 566 cdcleanup, cdstart, 567 "cd", CAM_PERIPH_BIO, 568 cgd->ccb_h.path, cdasync, 569 AC_FOUND_DEVICE, cgd); 570 571 if (status != CAM_REQ_CMP 572 && status != CAM_REQ_INPROG) 573 printf("cdasync: Unable to attach new device " 574 "due to status 0x%x\n", status); 575 576 break; 577 } 578 case AC_SENT_BDR: 579 case AC_BUS_RESET: 580 { 581 struct cd_softc *softc; 582 struct ccb_hdr *ccbh; 583 int s; 584 585 softc = (struct cd_softc *)periph->softc; 586 s = splsoftcam(); 587 /* 588 * Don't fail on the expected unit attention 589 * that will occur. 590 */ 591 softc->flags |= CD_FLAG_RETRY_UA; 592 LIST_FOREACH(ccbh, &softc->pending_ccbs, periph_links.le) 593 ccbh->ccb_state |= CD_CCB_RETRY_UA; 594 splx(s); 595 /* FALLTHROUGH */ 596 } 597 default: 598 cam_periph_async(periph, code, path, arg); 599 break; 600 } 601} 602 603static void 604cdsysctlinit(void *context, int pending) 605{ 606 struct cam_periph *periph; 607 struct cd_softc *softc; 608 char tmpstr[80], tmpstr2[80]; 609 610 periph = (struct cam_periph *)context; 611 softc = (struct cd_softc *)periph->softc; 612 613 snprintf(tmpstr, sizeof(tmpstr), "CAM CD unit %d", periph->unit_number); 614 snprintf(tmpstr2, sizeof(tmpstr2), "%d", periph->unit_number); 615 616 mtx_lock(&Giant); 617 618 sysctl_ctx_init(&softc->sysctl_ctx); 619 softc->sysctl_tree = SYSCTL_ADD_NODE(&softc->sysctl_ctx, 620 SYSCTL_STATIC_CHILDREN(_kern_cam_cd), OID_AUTO, 621 tmpstr2, CTLFLAG_RD, 0, tmpstr); 622 623 if (softc->sysctl_tree == NULL) { 624 printf("cdsysctlinit: unable to allocate sysctl tree\n"); 625 return; 626 } 627 628 /* 629 * Now register the sysctl handler, so the user can the value on 630 * the fly. 631 */ 632 SYSCTL_ADD_PROC(&softc->sysctl_ctx,SYSCTL_CHILDREN(softc->sysctl_tree), 633 OID_AUTO, "minimum_cmd_size", CTLTYPE_INT | CTLFLAG_RW, 634 &softc->minimum_command_size, 0, cdcmdsizesysctl, "I", 635 "Minimum CDB size"); 636 637 mtx_unlock(&Giant); 638} 639 640/* 641 * We have a handler function for this so we can check the values when the 642 * user sets them, instead of every time we look at them. 643 */ 644static int 645cdcmdsizesysctl(SYSCTL_HANDLER_ARGS) 646{ 647 int error, value; 648 649 value = *(int *)arg1; 650 651 error = sysctl_handle_int(oidp, &value, 0, req); 652 653 if ((error != 0) 654 || (req->newptr == NULL)) 655 return (error); 656 657 /* 658 * The only real values we can have here are 6 or 10. I don't 659 * really forsee having 12 be an option at any time in the future. 660 * So if the user sets something less than or equal to 6, we'll set 661 * it to 6. If he sets something greater than 6, we'll set it to 10. 662 * 663 * I suppose we could just return an error here for the wrong values, 664 * but I don't think it's necessary to do so, as long as we can 665 * determine the user's intent without too much trouble. 666 */ 667 if (value < 6) 668 value = 6; 669 else if (value > 6) 670 value = 10; 671 672 *(int *)arg1 = value; 673 674 return (0); 675} 676 677static cam_status 678cdregister(struct cam_periph *periph, void *arg) 679{ 680 struct cd_softc *softc; 681 struct ccb_setasync csa; 682 struct ccb_pathinq cpi; 683 struct ccb_getdev *cgd; 684 char tmpstr[80]; 685 caddr_t match; 686 687 cgd = (struct ccb_getdev *)arg; 688 if (periph == NULL) { 689 printf("cdregister: periph was NULL!!\n"); 690 return(CAM_REQ_CMP_ERR); 691 } 692 if (cgd == NULL) { 693 printf("cdregister: no getdev CCB, can't register device\n"); 694 return(CAM_REQ_CMP_ERR); 695 } 696 697 softc = (struct cd_softc *)malloc(sizeof(*softc),M_DEVBUF,M_NOWAIT); 698 699 if (softc == NULL) { 700 printf("cdregister: Unable to probe new device. " 701 "Unable to allocate softc\n"); 702 return(CAM_REQ_CMP_ERR); 703 } 704 705 bzero(softc, sizeof(*softc)); 706 LIST_INIT(&softc->pending_ccbs); 707 STAILQ_INIT(&softc->mode_queue); 708 softc->state = CD_STATE_PROBE; 709 bioq_init(&softc->bio_queue); 710 if (SID_IS_REMOVABLE(&cgd->inq_data)) 711 softc->flags |= CD_FLAG_DISC_REMOVABLE; 712 if ((cgd->inq_data.flags & SID_CmdQue) != 0) 713 softc->flags |= CD_FLAG_TAGGED_QUEUING; 714 715 periph->softc = softc; 716 softc->periph = periph; 717 718 /* 719 * See if this device has any quirks. 720 */ 721 match = cam_quirkmatch((caddr_t)&cgd->inq_data, 722 (caddr_t)cd_quirk_table, 723 sizeof(cd_quirk_table)/sizeof(*cd_quirk_table), 724 sizeof(*cd_quirk_table), scsi_inquiry_match); 725 726 if (match != NULL) 727 softc->quirks = ((struct cd_quirk_entry *)match)->quirks; 728 else 729 softc->quirks = CD_Q_NONE; 730 731 /* Check if the SIM does not want 6 byte commands */ 732 xpt_setup_ccb(&cpi.ccb_h, periph->path, /*priority*/1); 733 cpi.ccb_h.func_code = XPT_PATH_INQ; 734 xpt_action((union ccb *)&cpi); 735 if (cpi.ccb_h.status == CAM_REQ_CMP && (cpi.hba_misc & PIM_NO_6_BYTE)) 736 softc->quirks |= CD_Q_10_BYTE_ONLY; 737 738 TASK_INIT(&softc->sysctl_task, 0, cdsysctlinit, periph); 739 740 /* The default is 6 byte commands, unless quirked otherwise */ 741 if (softc->quirks & CD_Q_10_BYTE_ONLY) 742 softc->minimum_command_size = 10; 743 else 744 softc->minimum_command_size = 6; 745 746 /* 747 * Load the user's default, if any. 748 */ 749 snprintf(tmpstr, sizeof(tmpstr), "kern.cam.cd.%d.minimum_cmd_size", 750 periph->unit_number); 751 TUNABLE_INT_FETCH(tmpstr, &softc->minimum_command_size); 752 753 /* 6 and 10 are the only permissible values here. */ 754 if (softc->minimum_command_size < 6) 755 softc->minimum_command_size = 6; 756 else if (softc->minimum_command_size > 6) 757 softc->minimum_command_size = 10; 758 759 /* 760 * We need to register the statistics structure for this device, 761 * but we don't have the blocksize yet for it. So, we register 762 * the structure and indicate that we don't have the blocksize 763 * yet. Unlike other SCSI peripheral drivers, we explicitly set 764 * the device type here to be CDROM, rather than just ORing in 765 * the device type. This is because this driver can attach to either 766 * CDROM or WORM devices, and we want this peripheral driver to 767 * show up in the devstat list as a CD peripheral driver, not a 768 * WORM peripheral driver. WORM drives will also have the WORM 769 * driver attached to them. 770 */ 771 softc->device_stats = devstat_new_entry("cd", 772 periph->unit_number, 0, 773 DEVSTAT_BS_UNAVAILABLE, 774 DEVSTAT_TYPE_CDROM | DEVSTAT_TYPE_IF_SCSI, 775 DEVSTAT_PRIORITY_CD); 776 softc->dev = make_dev(&cd_cdevsw, periph->unit_number, 777 UID_ROOT, GID_OPERATOR, 0640, "cd%d", periph->unit_number); 778 softc->dev->si_drv1 = periph; 779 softc->clonetag = 780 EVENTHANDLER_REGISTER(dev_clone, cdclone, softc, 1000); 781 782 /* 783 * Add an async callback so that we get 784 * notified if this device goes away. 785 */ 786 xpt_setup_ccb(&csa.ccb_h, periph->path, 787 /* priority */ 5); 788 csa.ccb_h.func_code = XPT_SASYNC_CB; 789 csa.event_enable = AC_SENT_BDR | AC_BUS_RESET | AC_LOST_DEVICE; 790 csa.callback = cdasync; 791 csa.callback_arg = periph; 792 xpt_action((union ccb *)&csa); 793 794 /* 795 * If the target lun is greater than 0, we most likely have a CD 796 * changer device. Check the quirk entries as well, though, just 797 * in case someone has a CD tower with one lun per drive or 798 * something like that. Also, if we know up front that a 799 * particular device is a changer, we can mark it as such starting 800 * with lun 0, instead of lun 1. It shouldn't be necessary to have 801 * a quirk entry to define something as a changer, however. 802 */ 803 if (((cgd->ccb_h.target_lun > 0) 804 && ((softc->quirks & CD_Q_NO_CHANGER) == 0)) 805 || ((softc->quirks & CD_Q_CHANGER) != 0)) { 806 struct cdchanger *nchanger; 807 struct cam_periph *nperiph; 808 struct cam_path *path; 809 cam_status status; 810 int found; 811 812 /* Set the changer flag in the current device's softc */ 813 softc->flags |= CD_FLAG_CHANGER; 814 815 if (num_changers == 0) 816 STAILQ_INIT(&changerq); 817 818 /* 819 * Now, look around for an existing changer device with the 820 * same path and target ID as the current device. 821 */ 822 for (found = 0, 823 nchanger = (struct cdchanger *)STAILQ_FIRST(&changerq); 824 nchanger != NULL; 825 nchanger = STAILQ_NEXT(nchanger, changer_links)){ 826 if ((nchanger->path_id == cgd->ccb_h.path_id) 827 && (nchanger->target_id == cgd->ccb_h.target_id)) { 828 found = 1; 829 break; 830 } 831 } 832 833 /* 834 * If we found a matching entry, just add this device to 835 * the list of devices on this changer. 836 */ 837 if (found == 1) { 838 struct chdevlist *chlunhead; 839 840 chlunhead = &nchanger->chluns; 841 842 /* 843 * XXX KDM look at consolidating this code with the 844 * code below in a separate function. 845 */ 846 847 /* 848 * Create a path with lun id 0, and see if we can 849 * find a matching device 850 */ 851 status = xpt_create_path(&path, /*periph*/ periph, 852 cgd->ccb_h.path_id, 853 cgd->ccb_h.target_id, 0); 854 855 if ((status == CAM_REQ_CMP) 856 && ((nperiph = cam_periph_find(path, "cd")) != NULL)){ 857 struct cd_softc *nsoftc; 858 859 nsoftc = (struct cd_softc *)nperiph->softc; 860 861 if ((nsoftc->flags & CD_FLAG_CHANGER) == 0){ 862 nsoftc->flags |= CD_FLAG_CHANGER; 863 nchanger->num_devices++; 864 if (camq_resize(&nchanger->devq, 865 nchanger->num_devices)!=CAM_REQ_CMP){ 866 printf("cdregister: " 867 "camq_resize " 868 "failed, changer " 869 "support may " 870 "be messed up\n"); 871 } 872 nsoftc->changer = nchanger; 873 nsoftc->pinfo.index =CAM_UNQUEUED_INDEX; 874 875 STAILQ_INSERT_TAIL(&nchanger->chluns, 876 nsoftc,changer_links); 877 } 878 xpt_free_path(path); 879 } else if (status == CAM_REQ_CMP) 880 xpt_free_path(path); 881 else { 882 printf("cdregister: unable to allocate path\n" 883 "cdregister: changer support may be " 884 "broken\n"); 885 } 886 887 nchanger->num_devices++; 888 889 softc->changer = nchanger; 890 softc->pinfo.index = CAM_UNQUEUED_INDEX; 891 892 if (camq_resize(&nchanger->devq, 893 nchanger->num_devices) != CAM_REQ_CMP) { 894 printf("cdregister: camq_resize " 895 "failed, changer support may " 896 "be messed up\n"); 897 } 898 899 STAILQ_INSERT_TAIL(chlunhead, softc, changer_links); 900 } 901 /* 902 * In this case, we don't already have an entry for this 903 * particular changer, so we need to create one, add it to 904 * the queue, and queue this device on the list for this 905 * changer. Before we queue this device, however, we need 906 * to search for lun id 0 on this target, and add it to the 907 * queue first, if it exists. (and if it hasn't already 908 * been marked as part of the changer.) 909 */ 910 else { 911 nchanger = malloc(sizeof(struct cdchanger), 912 M_DEVBUF, M_NOWAIT); 913 914 if (nchanger == NULL) { 915 softc->flags &= ~CD_FLAG_CHANGER; 916 printf("cdregister: unable to malloc " 917 "changer structure\ncdregister: " 918 "changer support disabled\n"); 919 920 /* 921 * Yes, gotos can be gross but in this case 922 * I think it's justified.. 923 */ 924 goto cdregisterexit; 925 } 926 927 /* zero the structure */ 928 bzero(nchanger, sizeof(struct cdchanger)); 929 930 if (camq_init(&nchanger->devq, 1) != 0) { 931 softc->flags &= ~CD_FLAG_CHANGER; 932 printf("cdregister: changer support " 933 "disabled\n"); 934 goto cdregisterexit; 935 } 936 937 num_changers++; 938 939 nchanger->path_id = cgd->ccb_h.path_id; 940 nchanger->target_id = cgd->ccb_h.target_id; 941 942 /* this is superfluous, but it makes things clearer */ 943 nchanger->num_devices = 0; 944 945 STAILQ_INIT(&nchanger->chluns); 946 947 STAILQ_INSERT_TAIL(&changerq, nchanger, 948 changer_links); 949 950 /* 951 * Create a path with lun id 0, and see if we can 952 * find a matching device 953 */ 954 status = xpt_create_path(&path, /*periph*/ periph, 955 cgd->ccb_h.path_id, 956 cgd->ccb_h.target_id, 0); 957 958 /* 959 * If we were able to allocate the path, and if we 960 * find a matching device and it isn't already 961 * marked as part of a changer, then we add it to 962 * the current changer. 963 */ 964 if ((status == CAM_REQ_CMP) 965 && ((nperiph = cam_periph_find(path, "cd")) != NULL) 966 && ((((struct cd_softc *)periph->softc)->flags & 967 CD_FLAG_CHANGER) == 0)) { 968 struct cd_softc *nsoftc; 969 970 nsoftc = (struct cd_softc *)nperiph->softc; 971 972 nsoftc->flags |= CD_FLAG_CHANGER; 973 nchanger->num_devices++; 974 if (camq_resize(&nchanger->devq, 975 nchanger->num_devices) != CAM_REQ_CMP) { 976 printf("cdregister: camq_resize " 977 "failed, changer support may " 978 "be messed up\n"); 979 } 980 nsoftc->changer = nchanger; 981 nsoftc->pinfo.index = CAM_UNQUEUED_INDEX; 982 983 STAILQ_INSERT_TAIL(&nchanger->chluns, 984 nsoftc, changer_links); 985 xpt_free_path(path); 986 } else if (status == CAM_REQ_CMP) 987 xpt_free_path(path); 988 else { 989 printf("cdregister: unable to allocate path\n" 990 "cdregister: changer support may be " 991 "broken\n"); 992 } 993 994 softc->changer = nchanger; 995 softc->pinfo.index = CAM_UNQUEUED_INDEX; 996 nchanger->num_devices++; 997 if (camq_resize(&nchanger->devq, 998 nchanger->num_devices) != CAM_REQ_CMP) { 999 printf("cdregister: camq_resize " 1000 "failed, changer support may " 1001 "be messed up\n"); 1002 } 1003 STAILQ_INSERT_TAIL(&nchanger->chluns, softc, 1004 changer_links); 1005 } 1006 } 1007 1008cdregisterexit: 1009 1010 /* Lock this peripheral until we are setup */ 1011 /* Can't block */ 1012 cam_periph_lock(periph, PRIBIO); 1013 1014 if ((softc->flags & CD_FLAG_CHANGER) == 0) 1015 xpt_schedule(periph, /*priority*/5); 1016 else 1017 cdschedule(periph, /*priority*/ 5); 1018 1019 return(CAM_REQ_CMP); 1020} 1021 1022static int 1023cdopen(dev_t dev, int flags, int fmt, struct thread *td) 1024{ 1025 struct cam_periph *periph; 1026 struct cd_softc *softc; 1027 int error; 1028 int s; 1029 1030 periph = (struct cam_periph *)dev->si_drv1; 1031 if (periph == NULL) 1032 return (ENXIO); 1033 1034 softc = (struct cd_softc *)periph->softc; 1035 1036 /* 1037 * Grab splsoftcam and hold it until we lock the peripheral. 1038 */ 1039 s = splsoftcam(); 1040 if (softc->flags & CD_FLAG_INVALID) { 1041 splx(s); 1042 return(ENXIO); 1043 } 1044 1045 if ((error = cam_periph_lock(periph, PRIBIO | PCATCH)) != 0) { 1046 splx(s); 1047 return (error); 1048 } 1049 1050 splx(s); 1051 1052 if (cam_periph_acquire(periph) != CAM_REQ_CMP) 1053 return(ENXIO); 1054 1055 /* 1056 * Check for media, and set the appropriate flags. We don't bail 1057 * if we don't have media, but then we don't allow anything but the 1058 * CDIOCEJECT/CDIOCCLOSE ioctls if there is no media. 1059 */ 1060 cdcheckmedia(periph); 1061 1062 cam_periph_unlock(periph); 1063 1064 CAM_DEBUG(periph->path, CAM_DEBUG_TRACE, ("leaving cdopen\n")); 1065 1066 return (error); 1067} 1068 1069static int 1070cdclose(dev_t dev, int flag, int fmt, struct thread *td) 1071{ 1072 struct cam_periph *periph; 1073 struct cd_softc *softc; 1074 int error; 1075 1076 periph = (struct cam_periph *)dev->si_drv1; 1077 if (periph == NULL) 1078 return (ENXIO); 1079 1080 softc = (struct cd_softc *)periph->softc; 1081 1082 if ((error = cam_periph_lock(periph, PRIBIO)) != 0) 1083 return (error); 1084 1085 if ((softc->flags & CD_FLAG_DISC_REMOVABLE) != 0) 1086 cdprevent(periph, PR_ALLOW); 1087 1088 /* 1089 * Since we're closing this CD, mark the blocksize as unavailable. 1090 * It will be marked as available when the CD is opened again. 1091 */ 1092 softc->device_stats->flags |= DEVSTAT_BS_UNAVAILABLE; 1093 1094 /* 1095 * We'll check the media and toc again at the next open(). 1096 */ 1097 softc->flags &= ~(CD_FLAG_VALID_MEDIA|CD_FLAG_VALID_TOC); 1098 1099 cam_periph_unlock(periph); 1100 cam_periph_release(periph); 1101 1102 return (0); 1103} 1104 1105static void 1106cdshorttimeout(void *arg) 1107{ 1108 struct cdchanger *changer; 1109 int s; 1110 1111 s = splsoftcam(); 1112 1113 changer = (struct cdchanger *)arg; 1114 1115 /* Always clear the short timeout flag, since that's what we're in */ 1116 changer->flags &= ~CHANGER_SHORT_TMOUT_SCHED; 1117 1118 /* 1119 * Check to see if there is any more pending or outstanding I/O for 1120 * this device. If not, move it out of the active slot. 1121 */ 1122 if ((bioq_first(&changer->cur_device->bio_queue) == NULL) 1123 && (changer->cur_device->outstanding_cmds == 0)) { 1124 changer->flags |= CHANGER_MANUAL_CALL; 1125 cdrunchangerqueue(changer); 1126 } 1127 1128 splx(s); 1129} 1130 1131/* 1132 * This is a wrapper for xpt_schedule. It only applies to changers. 1133 */ 1134static void 1135cdschedule(struct cam_periph *periph, int priority) 1136{ 1137 struct cd_softc *softc; 1138 int s; 1139 1140 s = splsoftcam(); 1141 1142 softc = (struct cd_softc *)periph->softc; 1143 1144 /* 1145 * If this device isn't currently queued, and if it isn't 1146 * the active device, then we queue this device and run the 1147 * changer queue if there is no timeout scheduled to do it. 1148 * If this device is the active device, just schedule it 1149 * to run again. If this device is queued, there should be 1150 * a timeout in place already that will make sure it runs. 1151 */ 1152 if ((softc->pinfo.index == CAM_UNQUEUED_INDEX) 1153 && ((softc->flags & CD_FLAG_ACTIVE) == 0)) { 1154 /* 1155 * We don't do anything with the priority here. 1156 * This is strictly a fifo queue. 1157 */ 1158 softc->pinfo.priority = 1; 1159 softc->pinfo.generation = ++softc->changer->devq.generation; 1160 camq_insert(&softc->changer->devq, (cam_pinfo *)softc); 1161 1162 /* 1163 * Since we just put a device in the changer queue, 1164 * check and see if there is a timeout scheduled for 1165 * this changer. If so, let the timeout handle 1166 * switching this device into the active slot. If 1167 * not, manually call the timeout routine to 1168 * bootstrap things. 1169 */ 1170 if (((softc->changer->flags & CHANGER_TIMEOUT_SCHED)==0) 1171 && ((softc->changer->flags & CHANGER_NEED_TIMEOUT)==0) 1172 && ((softc->changer->flags & CHANGER_SHORT_TMOUT_SCHED)==0)){ 1173 softc->changer->flags |= CHANGER_MANUAL_CALL; 1174 cdrunchangerqueue(softc->changer); 1175 } 1176 } else if ((softc->flags & CD_FLAG_ACTIVE) 1177 && ((softc->flags & CD_FLAG_SCHED_ON_COMP) == 0)) 1178 xpt_schedule(periph, priority); 1179 1180 splx(s); 1181 1182} 1183 1184static void 1185cdrunchangerqueue(void *arg) 1186{ 1187 struct cd_softc *softc; 1188 struct cdchanger *changer; 1189 int called_from_timeout; 1190 int s; 1191 1192 s = splsoftcam(); 1193 1194 changer = (struct cdchanger *)arg; 1195 1196 /* 1197 * If we have NOT been called from cdstrategy() or cddone(), and 1198 * instead from a timeout routine, go ahead and clear the 1199 * timeout flag. 1200 */ 1201 if ((changer->flags & CHANGER_MANUAL_CALL) == 0) { 1202 changer->flags &= ~CHANGER_TIMEOUT_SCHED; 1203 called_from_timeout = 1; 1204 } else 1205 called_from_timeout = 0; 1206 1207 /* Always clear the manual call flag */ 1208 changer->flags &= ~CHANGER_MANUAL_CALL; 1209 1210 /* nothing to do if the queue is empty */ 1211 if (changer->devq.entries <= 0) { 1212 splx(s); 1213 return; 1214 } 1215 1216 /* 1217 * If the changer queue is frozen, that means we have an active 1218 * device. 1219 */ 1220 if (changer->devq.qfrozen_cnt > 0) { 1221 1222 if (changer->cur_device->outstanding_cmds > 0) { 1223 changer->cur_device->flags |= CD_FLAG_SCHED_ON_COMP; 1224 changer->cur_device->bufs_left = 1225 changer->cur_device->outstanding_cmds; 1226 if (called_from_timeout) { 1227 changer->long_handle = 1228 timeout(cdrunchangerqueue, changer, 1229 changer_max_busy_seconds * hz); 1230 changer->flags |= CHANGER_TIMEOUT_SCHED; 1231 } 1232 splx(s); 1233 return; 1234 } 1235 1236 /* 1237 * We always need to reset the frozen count and clear the 1238 * active flag. 1239 */ 1240 changer->devq.qfrozen_cnt--; 1241 changer->cur_device->flags &= ~CD_FLAG_ACTIVE; 1242 changer->cur_device->flags &= ~CD_FLAG_SCHED_ON_COMP; 1243 1244 /* 1245 * Check to see whether the current device has any I/O left 1246 * to do. If so, requeue it at the end of the queue. If 1247 * not, there is no need to requeue it. 1248 */ 1249 if (bioq_first(&changer->cur_device->bio_queue) != NULL) { 1250 1251 changer->cur_device->pinfo.generation = 1252 ++changer->devq.generation; 1253 camq_insert(&changer->devq, 1254 (cam_pinfo *)changer->cur_device); 1255 } 1256 } 1257 1258 softc = (struct cd_softc *)camq_remove(&changer->devq, CAMQ_HEAD); 1259 1260 changer->cur_device = softc; 1261 1262 changer->devq.qfrozen_cnt++; 1263 softc->flags |= CD_FLAG_ACTIVE; 1264 1265 /* Just in case this device is waiting */ 1266 wakeup(&softc->changer); 1267 xpt_schedule(softc->periph, /*priority*/ 1); 1268 1269 /* 1270 * Get rid of any pending timeouts, and set a flag to schedule new 1271 * ones so this device gets its full time quantum. 1272 */ 1273 if (changer->flags & CHANGER_TIMEOUT_SCHED) { 1274 untimeout(cdrunchangerqueue, changer, changer->long_handle); 1275 changer->flags &= ~CHANGER_TIMEOUT_SCHED; 1276 } 1277 1278 if (changer->flags & CHANGER_SHORT_TMOUT_SCHED) { 1279 untimeout(cdshorttimeout, changer, changer->short_handle); 1280 changer->flags &= ~CHANGER_SHORT_TMOUT_SCHED; 1281 } 1282 1283 /* 1284 * We need to schedule timeouts, but we only do this after the 1285 * first transaction has completed. This eliminates the changer 1286 * switch time. 1287 */ 1288 changer->flags |= CHANGER_NEED_TIMEOUT; 1289 1290 splx(s); 1291} 1292 1293static void 1294cdchangerschedule(struct cd_softc *softc) 1295{ 1296 struct cdchanger *changer; 1297 int s; 1298 1299 s = splsoftcam(); 1300 1301 changer = softc->changer; 1302 1303 /* 1304 * If this is a changer, and this is the current device, 1305 * and this device has at least the minimum time quantum to 1306 * run, see if we can switch it out. 1307 */ 1308 if ((softc->flags & CD_FLAG_ACTIVE) 1309 && ((changer->flags & CHANGER_SHORT_TMOUT_SCHED) == 0) 1310 && ((changer->flags & CHANGER_NEED_TIMEOUT) == 0)) { 1311 /* 1312 * We try three things here. The first is that we 1313 * check to see whether the schedule on completion 1314 * flag is set. If it is, we decrement the number 1315 * of buffers left, and if it's zero, we reschedule. 1316 * Next, we check to see whether the pending buffer 1317 * queue is empty and whether there are no 1318 * outstanding transactions. If so, we reschedule. 1319 * Next, we see if the pending buffer queue is empty. 1320 * If it is, we set the number of buffers left to 1321 * the current active buffer count and set the 1322 * schedule on complete flag. 1323 */ 1324 if (softc->flags & CD_FLAG_SCHED_ON_COMP) { 1325 if (--softc->bufs_left == 0) { 1326 softc->changer->flags |= 1327 CHANGER_MANUAL_CALL; 1328 softc->flags &= ~CD_FLAG_SCHED_ON_COMP; 1329 cdrunchangerqueue(softc->changer); 1330 } 1331 } else if ((bioq_first(&softc->bio_queue) == NULL) 1332 && (softc->outstanding_cmds == 0)) { 1333 softc->changer->flags |= CHANGER_MANUAL_CALL; 1334 cdrunchangerqueue(softc->changer); 1335 } 1336 } else if ((softc->changer->flags & CHANGER_NEED_TIMEOUT) 1337 && (softc->flags & CD_FLAG_ACTIVE)) { 1338 1339 /* 1340 * Now that the first transaction to this 1341 * particular device has completed, we can go ahead 1342 * and schedule our timeouts. 1343 */ 1344 if ((changer->flags & CHANGER_TIMEOUT_SCHED) == 0) { 1345 changer->long_handle = 1346 timeout(cdrunchangerqueue, changer, 1347 changer_max_busy_seconds * hz); 1348 changer->flags |= CHANGER_TIMEOUT_SCHED; 1349 } else 1350 printf("cdchangerschedule: already have a long" 1351 " timeout!\n"); 1352 1353 if ((changer->flags & CHANGER_SHORT_TMOUT_SCHED) == 0) { 1354 changer->short_handle = 1355 timeout(cdshorttimeout, changer, 1356 changer_min_busy_seconds * hz); 1357 changer->flags |= CHANGER_SHORT_TMOUT_SCHED; 1358 } else 1359 printf("cdchangerschedule: already have a short " 1360 "timeout!\n"); 1361 1362 /* 1363 * We just scheduled timeouts, no need to schedule 1364 * more. 1365 */ 1366 changer->flags &= ~CHANGER_NEED_TIMEOUT; 1367 1368 } 1369 splx(s); 1370} 1371 1372static int 1373cdrunccb(union ccb *ccb, int (*error_routine)(union ccb *ccb, 1374 u_int32_t cam_flags, 1375 u_int32_t sense_flags), 1376 u_int32_t cam_flags, u_int32_t sense_flags) 1377{ 1378 struct cd_softc *softc; 1379 struct cam_periph *periph; 1380 int error; 1381 1382 periph = xpt_path_periph(ccb->ccb_h.path); 1383 softc = (struct cd_softc *)periph->softc; 1384 1385 error = cam_periph_runccb(ccb, error_routine, cam_flags, sense_flags, 1386 softc->device_stats); 1387 1388 if (softc->flags & CD_FLAG_CHANGER) 1389 cdchangerschedule(softc); 1390 1391 return(error); 1392} 1393 1394static union ccb * 1395cdgetccb(struct cam_periph *periph, u_int32_t priority) 1396{ 1397 struct cd_softc *softc; 1398 int s; 1399 1400 softc = (struct cd_softc *)periph->softc; 1401 1402 if (softc->flags & CD_FLAG_CHANGER) { 1403 1404 s = splsoftcam(); 1405 1406 /* 1407 * This should work the first time this device is woken up, 1408 * but just in case it doesn't, we use a while loop. 1409 */ 1410 while ((softc->flags & CD_FLAG_ACTIVE) == 0) { 1411 /* 1412 * If this changer isn't already queued, queue it up. 1413 */ 1414 if (softc->pinfo.index == CAM_UNQUEUED_INDEX) { 1415 softc->pinfo.priority = 1; 1416 softc->pinfo.generation = 1417 ++softc->changer->devq.generation; 1418 camq_insert(&softc->changer->devq, 1419 (cam_pinfo *)softc); 1420 } 1421 if (((softc->changer->flags & CHANGER_TIMEOUT_SCHED)==0) 1422 && ((softc->changer->flags & CHANGER_NEED_TIMEOUT)==0) 1423 && ((softc->changer->flags 1424 & CHANGER_SHORT_TMOUT_SCHED)==0)) { 1425 softc->changer->flags |= CHANGER_MANUAL_CALL; 1426 cdrunchangerqueue(softc->changer); 1427 } else 1428 tsleep(&softc->changer, PRIBIO, "cgticb", 0); 1429 } 1430 splx(s); 1431 } 1432 return(cam_periph_getccb(periph, priority)); 1433} 1434 1435 1436/* 1437 * Actually translate the requested transfer into one the physical driver 1438 * can understand. The transfer is described by a buf and will include 1439 * only one physical transfer. 1440 */ 1441static void 1442cdstrategy(struct bio *bp) 1443{ 1444 struct cam_periph *periph; 1445 struct cd_softc *softc; 1446 int s; 1447 1448 periph = (struct cam_periph *)bp->bio_dev->si_drv1; 1449 if (periph == NULL) { 1450 biofinish(bp, NULL, ENXIO); 1451 return; 1452 } 1453 1454 CAM_DEBUG(periph->path, CAM_DEBUG_TRACE, ("entering cdstrategy\n")); 1455 1456 softc = (struct cd_softc *)periph->softc; 1457 1458 /* 1459 * Mask interrupts so that the pack cannot be invalidated until 1460 * after we are in the queue. Otherwise, we might not properly 1461 * clean up one of the buffers. 1462 */ 1463 s = splbio(); 1464 1465 /* 1466 * If the device has been made invalid, error out 1467 */ 1468 if ((softc->flags & CD_FLAG_INVALID)) { 1469 splx(s); 1470 biofinish(bp, NULL, ENXIO); 1471 return; 1472 } 1473 1474 /* 1475 * If we don't have valid media, look for it before trying to 1476 * schedule the I/O. 1477 */ 1478 if ((softc->flags & CD_FLAG_VALID_MEDIA) == 0) { 1479 int error; 1480 1481 error = cdcheckmedia(periph); 1482 if (error != 0) { 1483 splx(s); 1484 biofinish(bp, NULL, error); 1485 return; 1486 } 1487 } 1488 1489 /* 1490 * Place it in the queue of disk activities for this disk 1491 */ 1492 bioq_disksort(&softc->bio_queue, bp); 1493 1494 splx(s); 1495 1496 /* 1497 * Schedule ourselves for performing the work. We do things 1498 * differently for changers. 1499 */ 1500 if ((softc->flags & CD_FLAG_CHANGER) == 0) 1501 xpt_schedule(periph, /* XXX priority */1); 1502 else 1503 cdschedule(periph, /* priority */ 1); 1504 1505 return; 1506} 1507 1508static void 1509cdstart(struct cam_periph *periph, union ccb *start_ccb) 1510{ 1511 struct cd_softc *softc; 1512 struct bio *bp; 1513 struct ccb_scsiio *csio; 1514 struct scsi_read_capacity_data *rcap; 1515 int s; 1516 1517 softc = (struct cd_softc *)periph->softc; 1518 1519 CAM_DEBUG(periph->path, CAM_DEBUG_TRACE, ("entering cdstart\n")); 1520 1521 switch (softc->state) { 1522 case CD_STATE_NORMAL: 1523 { 1524 int oldspl; 1525 1526 s = splbio(); 1527 bp = bioq_first(&softc->bio_queue); 1528 if (periph->immediate_priority <= periph->pinfo.priority) { 1529 start_ccb->ccb_h.ccb_state = CD_CCB_WAITING; 1530 1531 SLIST_INSERT_HEAD(&periph->ccb_list, &start_ccb->ccb_h, 1532 periph_links.sle); 1533 periph->immediate_priority = CAM_PRIORITY_NONE; 1534 splx(s); 1535 wakeup(&periph->ccb_list); 1536 } else if (bp == NULL) { 1537 splx(s); 1538 xpt_release_ccb(start_ccb); 1539 } else { 1540 bioq_remove(&softc->bio_queue, bp); 1541 1542 devstat_start_transaction_bio(softc->device_stats, bp); 1543 1544 scsi_read_write(&start_ccb->csio, 1545 /*retries*/4, 1546 /* cbfcnp */ cddone, 1547 MSG_SIMPLE_Q_TAG, 1548 /* read */bp->bio_cmd == BIO_READ, 1549 /* byte2 */ 0, 1550 /* minimum_cmd_size */ 10, 1551 /* lba */ bp->bio_blkno / 1552 (softc->params.blksize / DEV_BSIZE), 1553 bp->bio_bcount / softc->params.blksize, 1554 /* data_ptr */ bp->bio_data, 1555 /* dxfer_len */ bp->bio_bcount, 1556 /* sense_len */ SSD_FULL_SIZE, 1557 /* timeout */ 30000); 1558 start_ccb->ccb_h.ccb_state = CD_CCB_BUFFER_IO; 1559 1560 1561 /* 1562 * Block out any asyncronous callbacks 1563 * while we touch the pending ccb list. 1564 */ 1565 oldspl = splcam(); 1566 LIST_INSERT_HEAD(&softc->pending_ccbs, 1567 &start_ccb->ccb_h, periph_links.le); 1568 softc->outstanding_cmds++; 1569 splx(oldspl); 1570 1571 /* We expect a unit attention from this device */ 1572 if ((softc->flags & CD_FLAG_RETRY_UA) != 0) { 1573 start_ccb->ccb_h.ccb_state |= CD_CCB_RETRY_UA; 1574 softc->flags &= ~CD_FLAG_RETRY_UA; 1575 } 1576 1577 start_ccb->ccb_h.ccb_bp = bp; 1578 bp = bioq_first(&softc->bio_queue); 1579 splx(s); 1580 1581 xpt_action(start_ccb); 1582 } 1583 if (bp != NULL) { 1584 /* Have more work to do, so ensure we stay scheduled */ 1585 xpt_schedule(periph, /* XXX priority */1); 1586 } 1587 break; 1588 } 1589 case CD_STATE_PROBE: 1590 { 1591 1592 rcap = (struct scsi_read_capacity_data *)malloc(sizeof(*rcap), 1593 M_TEMP, 1594 M_NOWAIT); 1595 if (rcap == NULL) { 1596 xpt_print_path(periph->path); 1597 printf("cdstart: Couldn't malloc read_capacity data\n"); 1598 /* cd_free_periph??? */ 1599 break; 1600 } 1601 csio = &start_ccb->csio; 1602 scsi_read_capacity(csio, 1603 /*retries*/1, 1604 cddone, 1605 MSG_SIMPLE_Q_TAG, 1606 rcap, 1607 SSD_FULL_SIZE, 1608 /*timeout*/20000); 1609 start_ccb->ccb_h.ccb_bp = NULL; 1610 start_ccb->ccb_h.ccb_state = CD_CCB_PROBE; 1611 xpt_action(start_ccb); 1612 break; 1613 } 1614 } 1615} 1616 1617static void 1618cddone(struct cam_periph *periph, union ccb *done_ccb) 1619{ 1620 struct cd_softc *softc; 1621 struct ccb_scsiio *csio; 1622 1623 CAM_DEBUG(periph->path, CAM_DEBUG_TRACE, ("entering cddone\n")); 1624 1625 softc = (struct cd_softc *)periph->softc; 1626 csio = &done_ccb->csio; 1627 1628 switch (csio->ccb_h.ccb_state & CD_CCB_TYPE_MASK) { 1629 case CD_CCB_BUFFER_IO: 1630 { 1631 struct bio *bp; 1632 int error; 1633 int oldspl; 1634 1635 bp = (struct bio *)done_ccb->ccb_h.ccb_bp; 1636 error = 0; 1637 1638 if ((done_ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) { 1639 int sf; 1640 1641 if ((done_ccb->ccb_h.ccb_state & CD_CCB_RETRY_UA) != 0) 1642 sf = SF_RETRY_UA; 1643 else 1644 sf = 0; 1645 1646 error = cderror(done_ccb, CAM_RETRY_SELTO, sf); 1647 if (error == ERESTART) { 1648 /* 1649 * A retry was scheuled, so 1650 * just return. 1651 */ 1652 return; 1653 } 1654 } 1655 1656 if (error != 0) { 1657 int s; 1658 1659 xpt_print_path(periph->path); 1660 printf("cddone: got error %#x back\n", error); 1661 s = splbio(); 1662 bioq_flush(&softc->bio_queue, NULL, EIO); 1663 splx(s); 1664 bp->bio_resid = bp->bio_bcount; 1665 bp->bio_error = error; 1666 bp->bio_flags |= BIO_ERROR; 1667 cam_release_devq(done_ccb->ccb_h.path, 1668 /*relsim_flags*/0, 1669 /*reduction*/0, 1670 /*timeout*/0, 1671 /*getcount_only*/0); 1672 1673 } else { 1674 bp->bio_resid = csio->resid; 1675 bp->bio_error = 0; 1676 if (bp->bio_resid != 0) { 1677 /* 1678 * Short transfer ??? 1679 * XXX: not sure this is correct for partial 1680 * transfers at EOM 1681 */ 1682 bp->bio_flags |= BIO_ERROR; 1683 } 1684 } 1685 1686 /* 1687 * Block out any asyncronous callbacks 1688 * while we touch the pending ccb list. 1689 */ 1690 oldspl = splcam(); 1691 LIST_REMOVE(&done_ccb->ccb_h, periph_links.le); 1692 softc->outstanding_cmds--; 1693 splx(oldspl); 1694 1695 if (softc->flags & CD_FLAG_CHANGER) 1696 cdchangerschedule(softc); 1697 1698 biofinish(bp, softc->device_stats, 0); 1699 break; 1700 } 1701 case CD_CCB_PROBE: 1702 { 1703 struct scsi_read_capacity_data *rdcap; 1704 char announce_buf[120]; /* 1705 * Currently (9/30/97) the 1706 * longest possible announce 1707 * buffer is 108 bytes, for the 1708 * first error case below. 1709 * That is 39 bytes for the 1710 * basic string, 16 bytes for the 1711 * biggest sense key (hardware 1712 * error), 52 bytes for the 1713 * text of the largest sense 1714 * qualifier valid for a CDROM, 1715 * (0x72, 0x03 or 0x04, 1716 * 0x03), and one byte for the 1717 * null terminating character. 1718 * To allow for longer strings, 1719 * the announce buffer is 120 1720 * bytes. 1721 */ 1722 struct cd_params *cdp; 1723 1724 cdp = &softc->params; 1725 1726 rdcap = (struct scsi_read_capacity_data *)csio->data_ptr; 1727 1728 cdp->disksize = scsi_4btoul (rdcap->addr) + 1; 1729 cdp->blksize = scsi_4btoul (rdcap->length); 1730 1731 if ((csio->ccb_h.status & CAM_STATUS_MASK) == CAM_REQ_CMP) { 1732 1733 snprintf(announce_buf, sizeof(announce_buf), 1734 "cd present [%lu x %lu byte records]", 1735 cdp->disksize, (u_long)cdp->blksize); 1736 1737 } else { 1738 int error; 1739 /* 1740 * Retry any UNIT ATTENTION type errors. They 1741 * are expected at boot. 1742 */ 1743 error = cderror(done_ccb, CAM_RETRY_SELTO, 1744 SF_RETRY_UA | SF_NO_PRINT); 1745 if (error == ERESTART) { 1746 /* 1747 * A retry was scheuled, so 1748 * just return. 1749 */ 1750 return; 1751 } else if (error != 0) { 1752 1753 struct scsi_sense_data *sense; 1754 int asc, ascq; 1755 int sense_key, error_code; 1756 int have_sense; 1757 cam_status status; 1758 struct ccb_getdev cgd; 1759 1760 /* Don't wedge this device's queue */ 1761 cam_release_devq(done_ccb->ccb_h.path, 1762 /*relsim_flags*/0, 1763 /*reduction*/0, 1764 /*timeout*/0, 1765 /*getcount_only*/0); 1766 1767 status = done_ccb->ccb_h.status; 1768 1769 xpt_setup_ccb(&cgd.ccb_h, 1770 done_ccb->ccb_h.path, 1771 /* priority */ 1); 1772 cgd.ccb_h.func_code = XPT_GDEV_TYPE; 1773 xpt_action((union ccb *)&cgd); 1774 1775 if (((csio->ccb_h.flags & CAM_SENSE_PHYS) != 0) 1776 || ((csio->ccb_h.flags & CAM_SENSE_PTR) != 0) 1777 || ((status & CAM_AUTOSNS_VALID) == 0)) 1778 have_sense = FALSE; 1779 else 1780 have_sense = TRUE; 1781 1782 if (have_sense) { 1783 sense = &csio->sense_data; 1784 scsi_extract_sense(sense, &error_code, 1785 &sense_key, 1786 &asc, &ascq); 1787 } 1788 /* 1789 * Attach to anything that claims to be a 1790 * CDROM or WORM device, as long as it 1791 * doesn't return a "Logical unit not 1792 * supported" (0x25) error. 1793 */ 1794 if ((have_sense) && (asc != 0x25) 1795 && (error_code == SSD_CURRENT_ERROR)) { 1796 const char *sense_key_desc; 1797 const char *asc_desc; 1798 1799 scsi_sense_desc(sense_key, asc, ascq, 1800 &cgd.inq_data, 1801 &sense_key_desc, 1802 &asc_desc); 1803 snprintf(announce_buf, 1804 sizeof(announce_buf), 1805 "Attempt to query device " 1806 "size failed: %s, %s", 1807 sense_key_desc, 1808 asc_desc); 1809 } else if ((have_sense == 0) 1810 && ((status & CAM_STATUS_MASK) == 1811 CAM_SCSI_STATUS_ERROR) 1812 && (csio->scsi_status == 1813 SCSI_STATUS_BUSY)) { 1814 snprintf(announce_buf, 1815 sizeof(announce_buf), 1816 "Attempt to query device " 1817 "size failed: SCSI Status: %s", 1818 scsi_status_string(csio)); 1819 } else if (SID_TYPE(&cgd.inq_data) == T_CDROM) { 1820 /* 1821 * We only print out an error for 1822 * CDROM type devices. For WORM 1823 * devices, we don't print out an 1824 * error since a few WORM devices 1825 * don't support CDROM commands. 1826 * If we have sense information, go 1827 * ahead and print it out. 1828 * Otherwise, just say that we 1829 * couldn't attach. 1830 */ 1831 1832 /* 1833 * Just print out the error, not 1834 * the full probe message, when we 1835 * don't attach. 1836 */ 1837 if (have_sense) 1838 scsi_sense_print( 1839 &done_ccb->csio); 1840 else { 1841 xpt_print_path(periph->path); 1842 printf("got CAM status %#x\n", 1843 done_ccb->ccb_h.status); 1844 } 1845 xpt_print_path(periph->path); 1846 printf("fatal error, failed" 1847 " to attach to device\n"); 1848 1849 /* 1850 * Invalidate this peripheral. 1851 */ 1852 cam_periph_invalidate(periph); 1853 1854 announce_buf[0] = '\0'; 1855 } else { 1856 1857 /* 1858 * Invalidate this peripheral. 1859 */ 1860 cam_periph_invalidate(periph); 1861 announce_buf[0] = '\0'; 1862 } 1863 } 1864 } 1865 free(rdcap, M_TEMP); 1866 if (announce_buf[0] != '\0') { 1867 xpt_announce_periph(periph, announce_buf); 1868 if (softc->flags & CD_FLAG_CHANGER) 1869 cdchangerschedule(softc); 1870 /* 1871 * Create our sysctl variables, now that we know 1872 * we have successfully attached. 1873 */ 1874 taskqueue_enqueue(taskqueue_thread,&softc->sysctl_task); 1875 } 1876 softc->state = CD_STATE_NORMAL; 1877 /* 1878 * Since our peripheral may be invalidated by an error 1879 * above or an external event, we must release our CCB 1880 * before releasing the probe lock on the peripheral. 1881 * The peripheral will only go away once the last lock 1882 * is removed, and we need it around for the CCB release 1883 * operation. 1884 */ 1885 xpt_release_ccb(done_ccb); 1886 cam_periph_unlock(periph); 1887 return; 1888 } 1889 case CD_CCB_WAITING: 1890 { 1891 /* Caller will release the CCB */ 1892 CAM_DEBUG(periph->path, CAM_DEBUG_TRACE, 1893 ("trying to wakeup ccbwait\n")); 1894 1895 wakeup(&done_ccb->ccb_h.cbfcnp); 1896 return; 1897 } 1898 default: 1899 break; 1900 } 1901 xpt_release_ccb(done_ccb); 1902} 1903 1904static union cd_pages * 1905cdgetpage(struct cd_mode_params *mode_params) 1906{ 1907 union cd_pages *page; 1908 1909 if (mode_params->cdb_size == 10) 1910 page = (union cd_pages *)find_mode_page_10( 1911 (struct scsi_mode_header_10 *)mode_params->mode_buf); 1912 else 1913 page = (union cd_pages *)find_mode_page_6( 1914 (struct scsi_mode_header_6 *)mode_params->mode_buf); 1915 1916 return (page); 1917} 1918 1919static int 1920cdgetpagesize(int page_num) 1921{ 1922 int i; 1923 1924 for (i = 0; i < (sizeof(cd_page_size_table)/ 1925 sizeof(cd_page_size_table[0])); i++) { 1926 if (cd_page_size_table[i].page == page_num) 1927 return (cd_page_size_table[i].page_size); 1928 } 1929 1930 return (-1); 1931} 1932 1933static int 1934cdioctl(dev_t dev, u_long cmd, caddr_t addr, int flag, struct thread *td) 1935{ 1936 1937 struct cam_periph *periph; 1938 struct cd_softc *softc; 1939 int error; 1940 1941 periph = (struct cam_periph *)dev->si_drv1; 1942 if (periph == NULL) 1943 return(ENXIO); 1944 1945 CAM_DEBUG(periph->path, CAM_DEBUG_TRACE, ("entering cdioctl\n")); 1946 1947 softc = (struct cd_softc *)periph->softc; 1948 1949 CAM_DEBUG(periph->path, CAM_DEBUG_TRACE, 1950 ("trying to do ioctl %#lx\n", cmd)); 1951 1952 error = cam_periph_lock(periph, PRIBIO | PCATCH); 1953 1954 if (error != 0) 1955 return(error); 1956 /* 1957 * If we don't have media loaded, check for it. If still don't 1958 * have media loaded, we can only do a load or eject. 1959 */ 1960 if (((softc->flags & CD_FLAG_VALID_MEDIA) == 0) 1961 && ((cmd != CDIOCCLOSE) 1962 && (cmd != CDIOCEJECT))) { 1963 error = cdcheckmedia(periph); 1964 if (error != 0) { 1965 cam_periph_unlock(periph); 1966 return (error); 1967 } 1968 } 1969 1970 switch (cmd) { 1971 1972 case DIOCGMEDIASIZE: 1973 *(off_t *)addr = 1974 (off_t)softc->params.blksize * softc->params.disksize; 1975 break; 1976 case DIOCGSECTORSIZE: 1977 *(u_int *)addr = softc->params.blksize; 1978 break; 1979 1980 case CDIOCPLAYTRACKS: 1981 { 1982 struct ioc_play_track *args 1983 = (struct ioc_play_track *) addr; 1984 struct cd_mode_params params; 1985 union cd_pages *page; 1986 1987 params.alloc_len = sizeof(union cd_mode_data_6_10); 1988 params.mode_buf = malloc(params.alloc_len, M_TEMP, 1989 M_WAITOK | M_ZERO); 1990 1991 CAM_DEBUG(periph->path, CAM_DEBUG_SUBTRACE, 1992 ("trying to do CDIOCPLAYTRACKS\n")); 1993 1994 error = cdgetmode(periph, ¶ms, AUDIO_PAGE); 1995 if (error) { 1996 free(params.mode_buf, M_TEMP); 1997 break; 1998 } 1999 page = cdgetpage(¶ms); 2000 2001 page->audio.flags &= ~CD_PA_SOTC; 2002 page->audio.flags |= CD_PA_IMMED; 2003 error = cdsetmode(periph, ¶ms); 2004 free(params.mode_buf, M_TEMP); 2005 if (error) 2006 break; 2007 2008 /* 2009 * This was originally implemented with the PLAY 2010 * AUDIO TRACK INDEX command, but that command was 2011 * deprecated after SCSI-2. Most (all?) SCSI CDROM 2012 * drives support it but ATAPI and ATAPI-derivative 2013 * drives don't seem to support it. So we keep a 2014 * cache of the table of contents and translate 2015 * track numbers to MSF format. 2016 */ 2017 if (softc->flags & CD_FLAG_VALID_TOC) { 2018 union msf_lba *sentry, *eentry; 2019 int st, et; 2020 2021 if (args->end_track < 2022 softc->toc.header.ending_track + 1) 2023 args->end_track++; 2024 if (args->end_track > 2025 softc->toc.header.ending_track + 1) 2026 args->end_track = 2027 softc->toc.header.ending_track + 1; 2028 st = args->start_track - 2029 softc->toc.header.starting_track; 2030 et = args->end_track - 2031 softc->toc.header.starting_track; 2032 if ((st < 0) 2033 || (et < 0) 2034 || (st > (softc->toc.header.ending_track - 2035 softc->toc.header.starting_track))) { 2036 error = EINVAL; 2037 break; 2038 } 2039 sentry = &softc->toc.entries[st].addr; 2040 eentry = &softc->toc.entries[et].addr; 2041 error = cdplaymsf(periph, 2042 sentry->msf.minute, 2043 sentry->msf.second, 2044 sentry->msf.frame, 2045 eentry->msf.minute, 2046 eentry->msf.second, 2047 eentry->msf.frame); 2048 } else { 2049 /* 2050 * If we don't have a valid TOC, try the 2051 * play track index command. It is part of 2052 * the SCSI-2 spec, but was removed in the 2053 * MMC specs. ATAPI and ATAPI-derived 2054 * drives don't support it. 2055 */ 2056 if (softc->quirks & CD_Q_BCD_TRACKS) { 2057 args->start_track = 2058 bin2bcd(args->start_track); 2059 args->end_track = 2060 bin2bcd(args->end_track); 2061 } 2062 error = cdplaytracks(periph, 2063 args->start_track, 2064 args->start_index, 2065 args->end_track, 2066 args->end_index); 2067 } 2068 } 2069 break; 2070 case CDIOCPLAYMSF: 2071 { 2072 struct ioc_play_msf *args 2073 = (struct ioc_play_msf *) addr; 2074 struct cd_mode_params params; 2075 union cd_pages *page; 2076 2077 params.alloc_len = sizeof(union cd_mode_data_6_10); 2078 params.mode_buf = malloc(params.alloc_len, M_TEMP, 2079 M_WAITOK | M_ZERO); 2080 2081 CAM_DEBUG(periph->path, CAM_DEBUG_SUBTRACE, 2082 ("trying to do CDIOCPLAYMSF\n")); 2083 2084 error = cdgetmode(periph, ¶ms, AUDIO_PAGE); 2085 if (error) { 2086 free(params.mode_buf, M_TEMP); 2087 break; 2088 } 2089 page = cdgetpage(¶ms); 2090 2091 page->audio.flags &= ~CD_PA_SOTC; 2092 page->audio.flags |= CD_PA_IMMED; 2093 error = cdsetmode(periph, ¶ms); 2094 free(params.mode_buf, M_TEMP); 2095 if (error) 2096 break; 2097 error = cdplaymsf(periph, 2098 args->start_m, 2099 args->start_s, 2100 args->start_f, 2101 args->end_m, 2102 args->end_s, 2103 args->end_f); 2104 } 2105 break; 2106 case CDIOCPLAYBLOCKS: 2107 { 2108 struct ioc_play_blocks *args 2109 = (struct ioc_play_blocks *) addr; 2110 struct cd_mode_params params; 2111 union cd_pages *page; 2112 2113 CAM_DEBUG(periph->path, CAM_DEBUG_SUBTRACE, 2114 ("trying to do CDIOCPLAYBLOCKS\n")); 2115 2116 params.alloc_len = sizeof(union cd_mode_data_6_10); 2117 params.mode_buf = malloc(params.alloc_len, M_TEMP, 2118 M_WAITOK | M_ZERO); 2119 2120 error = cdgetmode(periph, ¶ms, AUDIO_PAGE); 2121 if (error) { 2122 free(params.mode_buf, M_TEMP); 2123 break; 2124 } 2125 page = cdgetpage(¶ms); 2126 2127 page->audio.flags &= ~CD_PA_SOTC; 2128 page->audio.flags |= CD_PA_IMMED; 2129 error = cdsetmode(periph, ¶ms); 2130 free(params.mode_buf, M_TEMP); 2131 if (error) 2132 break; 2133 error = cdplay(periph, args->blk, args->len); 2134 } 2135 break; 2136 case CDIOCREADSUBCHANNEL: 2137 { 2138 struct ioc_read_subchannel *args 2139 = (struct ioc_read_subchannel *) addr; 2140 struct cd_sub_channel_info *data; 2141 u_int32_t len = args->data_len; 2142 2143 CAM_DEBUG(periph->path, CAM_DEBUG_SUBTRACE, 2144 ("trying to do CDIOCREADSUBCHANNEL\n")); 2145 2146 data = malloc(sizeof(struct cd_sub_channel_info), 2147 M_TEMP, M_WAITOK); 2148 2149 if ((len > sizeof(struct cd_sub_channel_info)) || 2150 (len < sizeof(struct cd_sub_channel_header))) { 2151 printf( 2152 "scsi_cd: cdioctl: " 2153 "cdioreadsubchannel: error, len=%d\n", 2154 len); 2155 error = EINVAL; 2156 free(data, M_TEMP); 2157 break; 2158 } 2159 2160 if (softc->quirks & CD_Q_BCD_TRACKS) 2161 args->track = bin2bcd(args->track); 2162 2163 error = cdreadsubchannel(periph, args->address_format, 2164 args->data_format, args->track, data, len); 2165 2166 if (error) { 2167 free(data, M_TEMP); 2168 break; 2169 } 2170 if (softc->quirks & CD_Q_BCD_TRACKS) 2171 data->what.track_info.track_number = 2172 bcd2bin(data->what.track_info.track_number); 2173 len = min(len, ((data->header.data_len[0] << 8) + 2174 data->header.data_len[1] + 2175 sizeof(struct cd_sub_channel_header))); 2176 if (copyout(data, args->data, len) != 0) { 2177 error = EFAULT; 2178 } 2179 free(data, M_TEMP); 2180 } 2181 break; 2182 2183 case CDIOREADTOCHEADER: 2184 { 2185 struct ioc_toc_header *th; 2186 2187 CAM_DEBUG(periph->path, CAM_DEBUG_SUBTRACE, 2188 ("trying to do CDIOREADTOCHEADER\n")); 2189 2190 th = malloc(sizeof(struct ioc_toc_header), M_TEMP, 2191 M_WAITOK); 2192 error = cdreadtoc(periph, 0, 0, (u_int8_t *)th, 2193 sizeof (*th), /*sense_flags*/0); 2194 if (error) { 2195 free(th, M_TEMP); 2196 break; 2197 } 2198 if (softc->quirks & CD_Q_BCD_TRACKS) { 2199 /* we are going to have to convert the BCD 2200 * encoding on the cd to what is expected 2201 */ 2202 th->starting_track = 2203 bcd2bin(th->starting_track); 2204 th->ending_track = bcd2bin(th->ending_track); 2205 } 2206 th->len = ntohs(th->len); 2207 bcopy(th, addr, sizeof(*th)); 2208 free(th, M_TEMP); 2209 } 2210 break; 2211 case CDIOREADTOCENTRYS: 2212 { 2213 struct cd_tocdata *data; 2214 struct cd_toc_single *lead; 2215 struct ioc_read_toc_entry *te = 2216 (struct ioc_read_toc_entry *) addr; 2217 struct ioc_toc_header *th; 2218 u_int32_t len, readlen, idx, num; 2219 u_int32_t starting_track = te->starting_track; 2220 2221 CAM_DEBUG(periph->path, CAM_DEBUG_SUBTRACE, 2222 ("trying to do CDIOREADTOCENTRYS\n")); 2223 2224 data = malloc(sizeof(*data), M_TEMP, M_WAITOK); 2225 lead = malloc(sizeof(*lead), M_TEMP, M_WAITOK); 2226 2227 if (te->data_len < sizeof(struct cd_toc_entry) 2228 || (te->data_len % sizeof(struct cd_toc_entry)) != 0 2229 || (te->address_format != CD_MSF_FORMAT 2230 && te->address_format != CD_LBA_FORMAT)) { 2231 error = EINVAL; 2232 printf("scsi_cd: error in readtocentries, " 2233 "returning EINVAL\n"); 2234 free(data, M_TEMP); 2235 free(lead, M_TEMP); 2236 break; 2237 } 2238 2239 th = &data->header; 2240 error = cdreadtoc(periph, 0, 0, (u_int8_t *)th, 2241 sizeof (*th), /*sense_flags*/0); 2242 if (error) { 2243 free(data, M_TEMP); 2244 free(lead, M_TEMP); 2245 break; 2246 } 2247 2248 if (softc->quirks & CD_Q_BCD_TRACKS) { 2249 /* we are going to have to convert the BCD 2250 * encoding on the cd to what is expected 2251 */ 2252 th->starting_track = 2253 bcd2bin(th->starting_track); 2254 th->ending_track = bcd2bin(th->ending_track); 2255 } 2256 2257 if (starting_track == 0) 2258 starting_track = th->starting_track; 2259 else if (starting_track == LEADOUT) 2260 starting_track = th->ending_track + 1; 2261 else if (starting_track < th->starting_track || 2262 starting_track > th->ending_track + 1) { 2263 printf("scsi_cd: error in readtocentries, " 2264 "returning EINVAL\n"); 2265 free(data, M_TEMP); 2266 free(lead, M_TEMP); 2267 error = EINVAL; 2268 break; 2269 } 2270 2271 /* calculate reading length without leadout entry */ 2272 readlen = (th->ending_track - starting_track + 1) * 2273 sizeof(struct cd_toc_entry); 2274 2275 /* and with leadout entry */ 2276 len = readlen + sizeof(struct cd_toc_entry); 2277 if (te->data_len < len) { 2278 len = te->data_len; 2279 if (readlen > len) 2280 readlen = len; 2281 } 2282 if (len > sizeof(data->entries)) { 2283 printf("scsi_cd: error in readtocentries, " 2284 "returning EINVAL\n"); 2285 error = EINVAL; 2286 free(data, M_TEMP); 2287 free(lead, M_TEMP); 2288 break; 2289 } 2290 num = len / sizeof(struct cd_toc_entry); 2291 2292 if (readlen > 0) { 2293 error = cdreadtoc(periph, te->address_format, 2294 starting_track, 2295 (u_int8_t *)data, 2296 readlen + sizeof (*th), 2297 /*sense_flags*/0); 2298 if (error) { 2299 free(data, M_TEMP); 2300 free(lead, M_TEMP); 2301 break; 2302 } 2303 } 2304 2305 /* make leadout entry if needed */ 2306 idx = starting_track + num - 1; 2307 if (softc->quirks & CD_Q_BCD_TRACKS) 2308 th->ending_track = bcd2bin(th->ending_track); 2309 if (idx == th->ending_track + 1) { 2310 error = cdreadtoc(periph, te->address_format, 2311 LEADOUT, (u_int8_t *)lead, 2312 sizeof(*lead), 2313 /*sense_flags*/0); 2314 if (error) { 2315 free(data, M_TEMP); 2316 free(lead, M_TEMP); 2317 break; 2318 } 2319 data->entries[idx - starting_track] = 2320 lead->entry; 2321 } 2322 if (softc->quirks & CD_Q_BCD_TRACKS) { 2323 for (idx = 0; idx < num - 1; idx++) { 2324 data->entries[idx].track = 2325 bcd2bin(data->entries[idx].track); 2326 } 2327 } 2328 2329 error = copyout(data->entries, te->data, len); 2330 free(data, M_TEMP); 2331 free(lead, M_TEMP); 2332 } 2333 break; 2334 case CDIOREADTOCENTRY: 2335 { 2336 struct cd_toc_single *data; 2337 struct ioc_read_toc_single_entry *te = 2338 (struct ioc_read_toc_single_entry *) addr; 2339 struct ioc_toc_header *th; 2340 u_int32_t track; 2341 2342 CAM_DEBUG(periph->path, CAM_DEBUG_SUBTRACE, 2343 ("trying to do CDIOREADTOCENTRY\n")); 2344 2345 data = malloc(sizeof(*data), M_TEMP, M_WAITOK); 2346 2347 if (te->address_format != CD_MSF_FORMAT 2348 && te->address_format != CD_LBA_FORMAT) { 2349 printf("error in readtocentry, " 2350 " returning EINVAL\n"); 2351 free(data, M_TEMP); 2352 error = EINVAL; 2353 break; 2354 } 2355 2356 th = &data->header; 2357 error = cdreadtoc(periph, 0, 0, (u_int8_t *)th, 2358 sizeof (*th), /*sense_flags*/0); 2359 if (error) { 2360 free(data, M_TEMP); 2361 break; 2362 } 2363 2364 if (softc->quirks & CD_Q_BCD_TRACKS) { 2365 /* we are going to have to convert the BCD 2366 * encoding on the cd to what is expected 2367 */ 2368 th->starting_track = 2369 bcd2bin(th->starting_track); 2370 th->ending_track = bcd2bin(th->ending_track); 2371 } 2372 track = te->track; 2373 if (track == 0) 2374 track = th->starting_track; 2375 else if (track == LEADOUT) 2376 /* OK */; 2377 else if (track < th->starting_track || 2378 track > th->ending_track + 1) { 2379 printf("error in readtocentry, " 2380 " returning EINVAL\n"); 2381 free(data, M_TEMP); 2382 error = EINVAL; 2383 break; 2384 } 2385 2386 error = cdreadtoc(periph, te->address_format, track, 2387 (u_int8_t *)data, sizeof(*data), 2388 /*sense_flags*/0); 2389 if (error) { 2390 free(data, M_TEMP); 2391 break; 2392 } 2393 2394 if (softc->quirks & CD_Q_BCD_TRACKS) 2395 data->entry.track = bcd2bin(data->entry.track); 2396 bcopy(&data->entry, &te->entry, 2397 sizeof(struct cd_toc_entry)); 2398 free(data, M_TEMP); 2399 } 2400 break; 2401 case CDIOCSETPATCH: 2402 { 2403 struct ioc_patch *arg = (struct ioc_patch *)addr; 2404 struct cd_mode_params params; 2405 union cd_pages *page; 2406 2407 CAM_DEBUG(periph->path, CAM_DEBUG_SUBTRACE, 2408 ("trying to do CDIOCSETPATCH\n")); 2409 2410 params.alloc_len = sizeof(union cd_mode_data_6_10); 2411 params.mode_buf = malloc(params.alloc_len, M_TEMP, 2412 M_WAITOK | M_ZERO); 2413 error = cdgetmode(periph, ¶ms, AUDIO_PAGE); 2414 if (error) { 2415 free(params.mode_buf, M_TEMP); 2416 break; 2417 } 2418 page = cdgetpage(¶ms); 2419 2420 page->audio.port[LEFT_PORT].channels = 2421 arg->patch[0]; 2422 page->audio.port[RIGHT_PORT].channels = 2423 arg->patch[1]; 2424 page->audio.port[2].channels = arg->patch[2]; 2425 page->audio.port[3].channels = arg->patch[3]; 2426 error = cdsetmode(periph, ¶ms); 2427 free(params.mode_buf, M_TEMP); 2428 } 2429 break; 2430 case CDIOCGETVOL: 2431 { 2432 struct ioc_vol *arg = (struct ioc_vol *) addr; 2433 struct cd_mode_params params; 2434 union cd_pages *page; 2435 2436 CAM_DEBUG(periph->path, CAM_DEBUG_SUBTRACE, 2437 ("trying to do CDIOCGETVOL\n")); 2438 2439 params.alloc_len = sizeof(union cd_mode_data_6_10); 2440 params.mode_buf = malloc(params.alloc_len, M_TEMP, 2441 M_WAITOK | M_ZERO); 2442 error = cdgetmode(periph, ¶ms, AUDIO_PAGE); 2443 if (error) { 2444 free(params.mode_buf, M_TEMP); 2445 break; 2446 } 2447 page = cdgetpage(¶ms); 2448 2449 arg->vol[LEFT_PORT] = 2450 page->audio.port[LEFT_PORT].volume; 2451 arg->vol[RIGHT_PORT] = 2452 page->audio.port[RIGHT_PORT].volume; 2453 arg->vol[2] = page->audio.port[2].volume; 2454 arg->vol[3] = page->audio.port[3].volume; 2455 free(params.mode_buf, M_TEMP); 2456 } 2457 break; 2458 case CDIOCSETVOL: 2459 { 2460 struct ioc_vol *arg = (struct ioc_vol *) addr; 2461 struct cd_mode_params params; 2462 union cd_pages *page; 2463 2464 CAM_DEBUG(periph->path, CAM_DEBUG_SUBTRACE, 2465 ("trying to do CDIOCSETVOL\n")); 2466 2467 params.alloc_len = sizeof(union cd_mode_data_6_10); 2468 params.mode_buf = malloc(params.alloc_len, M_TEMP, 2469 M_WAITOK | M_ZERO); 2470 error = cdgetmode(periph, ¶ms, AUDIO_PAGE); 2471 if (error) { 2472 free(params.mode_buf, M_TEMP); 2473 break; 2474 } 2475 page = cdgetpage(¶ms); 2476 2477 page->audio.port[LEFT_PORT].channels = CHANNEL_0; 2478 page->audio.port[LEFT_PORT].volume = 2479 arg->vol[LEFT_PORT]; 2480 page->audio.port[RIGHT_PORT].channels = CHANNEL_1; 2481 page->audio.port[RIGHT_PORT].volume = 2482 arg->vol[RIGHT_PORT]; 2483 page->audio.port[2].volume = arg->vol[2]; 2484 page->audio.port[3].volume = arg->vol[3]; 2485 error = cdsetmode(periph, ¶ms); 2486 free(params.mode_buf, M_TEMP); 2487 } 2488 break; 2489 case CDIOCSETMONO: 2490 { 2491 struct cd_mode_params params; 2492 union cd_pages *page; 2493 2494 CAM_DEBUG(periph->path, CAM_DEBUG_SUBTRACE, 2495 ("trying to do CDIOCSETMONO\n")); 2496 2497 params.alloc_len = sizeof(union cd_mode_data_6_10); 2498 params.mode_buf = malloc(params.alloc_len, M_TEMP, 2499 M_WAITOK | M_ZERO); 2500 error = cdgetmode(periph, ¶ms, AUDIO_PAGE); 2501 if (error) { 2502 free(params.mode_buf, M_TEMP); 2503 break; 2504 } 2505 page = cdgetpage(¶ms); 2506 2507 page->audio.port[LEFT_PORT].channels = 2508 LEFT_CHANNEL | RIGHT_CHANNEL; 2509 page->audio.port[RIGHT_PORT].channels = 2510 LEFT_CHANNEL | RIGHT_CHANNEL; 2511 page->audio.port[2].channels = 0; 2512 page->audio.port[3].channels = 0; 2513 error = cdsetmode(periph, ¶ms); 2514 free(params.mode_buf, M_TEMP); 2515 } 2516 break; 2517 case CDIOCSETSTEREO: 2518 { 2519 struct cd_mode_params params; 2520 union cd_pages *page; 2521 2522 CAM_DEBUG(periph->path, CAM_DEBUG_SUBTRACE, 2523 ("trying to do CDIOCSETSTEREO\n")); 2524 2525 params.alloc_len = sizeof(union cd_mode_data_6_10); 2526 params.mode_buf = malloc(params.alloc_len, M_TEMP, 2527 M_WAITOK | M_ZERO); 2528 error = cdgetmode(periph, ¶ms, AUDIO_PAGE); 2529 if (error) { 2530 free(params.mode_buf, M_TEMP); 2531 break; 2532 } 2533 page = cdgetpage(¶ms); 2534 2535 page->audio.port[LEFT_PORT].channels = 2536 LEFT_CHANNEL; 2537 page->audio.port[RIGHT_PORT].channels = 2538 RIGHT_CHANNEL; 2539 page->audio.port[2].channels = 0; 2540 page->audio.port[3].channels = 0; 2541 error = cdsetmode(periph, ¶ms); 2542 free(params.mode_buf, M_TEMP); 2543 } 2544 break; 2545 case CDIOCSETMUTE: 2546 { 2547 struct cd_mode_params params; 2548 union cd_pages *page; 2549 2550 CAM_DEBUG(periph->path, CAM_DEBUG_SUBTRACE, 2551 ("trying to do CDIOCSETMUTE\n")); 2552 2553 params.alloc_len = sizeof(union cd_mode_data_6_10); 2554 params.mode_buf = malloc(params.alloc_len, M_TEMP, 2555 M_WAITOK | M_ZERO); 2556 error = cdgetmode(periph, ¶ms, AUDIO_PAGE); 2557 if (error) { 2558 free(¶ms, M_TEMP); 2559 break; 2560 } 2561 page = cdgetpage(¶ms); 2562 2563 page->audio.port[LEFT_PORT].channels = 0; 2564 page->audio.port[RIGHT_PORT].channels = 0; 2565 page->audio.port[2].channels = 0; 2566 page->audio.port[3].channels = 0; 2567 error = cdsetmode(periph, ¶ms); 2568 free(params.mode_buf, M_TEMP); 2569 } 2570 break; 2571 case CDIOCSETLEFT: 2572 { 2573 struct cd_mode_params params; 2574 union cd_pages *page; 2575 2576 CAM_DEBUG(periph->path, CAM_DEBUG_SUBTRACE, 2577 ("trying to do CDIOCSETLEFT\n")); 2578 2579 params.alloc_len = sizeof(union cd_mode_data_6_10); 2580 params.mode_buf = malloc(params.alloc_len, M_TEMP, 2581 M_WAITOK | M_ZERO); 2582 2583 error = cdgetmode(periph, ¶ms, AUDIO_PAGE); 2584 if (error) { 2585 free(params.mode_buf, M_TEMP); 2586 break; 2587 } 2588 page = cdgetpage(¶ms); 2589 2590 page->audio.port[LEFT_PORT].channels = LEFT_CHANNEL; 2591 page->audio.port[RIGHT_PORT].channels = LEFT_CHANNEL; 2592 page->audio.port[2].channels = 0; 2593 page->audio.port[3].channels = 0; 2594 error = cdsetmode(periph, ¶ms); 2595 free(params.mode_buf, M_TEMP); 2596 } 2597 break; 2598 case CDIOCSETRIGHT: 2599 { 2600 struct cd_mode_params params; 2601 union cd_pages *page; 2602 2603 CAM_DEBUG(periph->path, CAM_DEBUG_SUBTRACE, 2604 ("trying to do CDIOCSETRIGHT\n")); 2605 2606 params.alloc_len = sizeof(union cd_mode_data_6_10); 2607 params.mode_buf = malloc(params.alloc_len, M_TEMP, 2608 M_WAITOK | M_ZERO); 2609 2610 error = cdgetmode(periph, ¶ms, AUDIO_PAGE); 2611 if (error) { 2612 free(params.mode_buf, M_TEMP); 2613 break; 2614 } 2615 page = cdgetpage(¶ms); 2616 2617 page->audio.port[LEFT_PORT].channels = RIGHT_CHANNEL; 2618 page->audio.port[RIGHT_PORT].channels = RIGHT_CHANNEL; 2619 page->audio.port[2].channels = 0; 2620 page->audio.port[3].channels = 0; 2621 error = cdsetmode(periph, ¶ms); 2622 free(params.mode_buf, M_TEMP); 2623 } 2624 break; 2625 case CDIOCRESUME: 2626 error = cdpause(periph, 1); 2627 break; 2628 case CDIOCPAUSE: 2629 error = cdpause(periph, 0); 2630 break; 2631 case CDIOCSTART: 2632 error = cdstartunit(periph, 0); 2633 break; 2634 case CDIOCCLOSE: 2635 error = cdstartunit(periph, 1); 2636 break; 2637 case CDIOCSTOP: 2638 error = cdstopunit(periph, 0); 2639 break; 2640 case CDIOCEJECT: 2641 error = cdstopunit(periph, 1); 2642 break; 2643 case CDIOCALLOW: 2644 cdprevent(periph, PR_ALLOW); 2645 break; 2646 case CDIOCPREVENT: 2647 cdprevent(periph, PR_PREVENT); 2648 break; 2649 case CDIOCSETDEBUG: 2650 /* sc_link->flags |= (SDEV_DB1 | SDEV_DB2); */ 2651 error = ENOTTY; 2652 break; 2653 case CDIOCCLRDEBUG: 2654 /* sc_link->flags &= ~(SDEV_DB1 | SDEV_DB2); */ 2655 error = ENOTTY; 2656 break; 2657 case CDIOCRESET: 2658 /* return (cd_reset(periph)); */ 2659 error = ENOTTY; 2660 break; 2661 case CDRIOCREADSPEED: 2662 error = cdsetspeed(periph, *(u_int32_t *)addr, CDR_MAX_SPEED); 2663 break; 2664 case CDRIOCWRITESPEED: 2665 error = cdsetspeed(periph, CDR_MAX_SPEED, *(u_int32_t *)addr); 2666 break; 2667 case DVDIOCSENDKEY: 2668 case DVDIOCREPORTKEY: { 2669 struct dvd_authinfo *authinfo; 2670 2671 authinfo = (struct dvd_authinfo *)addr; 2672 2673 if (cmd == DVDIOCREPORTKEY) 2674 error = cdreportkey(periph, authinfo); 2675 else 2676 error = cdsendkey(periph, authinfo); 2677 break; 2678 } 2679 case DVDIOCREADSTRUCTURE: { 2680 struct dvd_struct *dvdstruct; 2681 2682 dvdstruct = (struct dvd_struct *)addr; 2683 2684 error = cdreaddvdstructure(periph, dvdstruct); 2685 2686 break; 2687 } 2688 default: 2689 error = cam_periph_ioctl(periph, cmd, addr, cderror); 2690 break; 2691 } 2692 2693 cam_periph_unlock(periph); 2694 2695 CAM_DEBUG(periph->path, CAM_DEBUG_TRACE, ("leaving cdioctl\n")); 2696 if (error && bootverbose) { 2697 printf("scsi_cd.c::ioctl cmd=%08lx error=%d\n", cmd, error); 2698 } 2699 2700 return (error); 2701} 2702 2703static void 2704cdprevent(struct cam_periph *periph, int action) 2705{ 2706 union ccb *ccb; 2707 struct cd_softc *softc; 2708 int error; 2709 2710 CAM_DEBUG(periph->path, CAM_DEBUG_TRACE, ("entering cdprevent\n")); 2711 2712 softc = (struct cd_softc *)periph->softc; 2713 2714 if (((action == PR_ALLOW) 2715 && (softc->flags & CD_FLAG_DISC_LOCKED) == 0) 2716 || ((action == PR_PREVENT) 2717 && (softc->flags & CD_FLAG_DISC_LOCKED) != 0)) { 2718 return; 2719 } 2720 2721 ccb = cdgetccb(periph, /* priority */ 1); 2722 2723 scsi_prevent(&ccb->csio, 2724 /*retries*/ 1, 2725 cddone, 2726 MSG_SIMPLE_Q_TAG, 2727 action, 2728 SSD_FULL_SIZE, 2729 /* timeout */60000); 2730 2731 error = cdrunccb(ccb, cderror, /*cam_flags*/CAM_RETRY_SELTO, 2732 /*sense_flags*/SF_RETRY_UA|SF_NO_PRINT); 2733 2734 xpt_release_ccb(ccb); 2735 2736 if (error == 0) { 2737 if (action == PR_ALLOW) 2738 softc->flags &= ~CD_FLAG_DISC_LOCKED; 2739 else 2740 softc->flags |= CD_FLAG_DISC_LOCKED; 2741 } 2742} 2743 2744static int 2745cdcheckmedia(struct cam_periph *periph) 2746{ 2747 struct cd_softc *softc; 2748 struct ioc_toc_header *toch; 2749 struct cd_toc_single leadout; 2750 u_int32_t size, toclen; 2751 int error, num_entries, cdindex; 2752 2753 softc = (struct cd_softc *)periph->softc; 2754 2755 cdprevent(periph, PR_PREVENT); 2756 2757 /* 2758 * Get the disc size and block size. If we can't get it, we don't 2759 * have media, most likely. 2760 */ 2761 if ((error = cdsize(periph, &size)) != 0) { 2762 softc->flags &= ~(CD_FLAG_VALID_MEDIA|CD_FLAG_VALID_TOC); 2763 cdprevent(periph, PR_ALLOW); 2764 return (error); 2765 } else 2766 softc->flags |= CD_FLAG_VALID_MEDIA; 2767 2768 /* 2769 * Now we check the table of contents. This (currently) is only 2770 * used for the CDIOCPLAYTRACKS ioctl. It may be used later to do 2771 * things like present a separate entry in /dev for each track, 2772 * like that acd(4) driver does. 2773 */ 2774 bzero(&softc->toc, sizeof(softc->toc)); 2775 toch = &softc->toc.header; 2776 /* 2777 * We will get errors here for media that doesn't have a table of 2778 * contents. According to the MMC-3 spec: "When a Read TOC/PMA/ATIP 2779 * command is presented for a DDCD/CD-R/RW media, where the first TOC 2780 * has not been recorded (no complete session) and the Format codes 2781 * 0000b, 0001b, or 0010b are specified, this command shall be rejected 2782 * with an INVALID FIELD IN CDB. Devices that are not capable of 2783 * reading an incomplete session on DDC/CD-R/RW media shall report 2784 * CANNOT READ MEDIUM - INCOMPATIBLE FORMAT." 2785 * 2786 * So this isn't fatal if we can't read the table of contents, it 2787 * just means that the user won't be able to issue the play tracks 2788 * ioctl, and likely lots of other stuff won't work either. They 2789 * need to burn the CD before we can do a whole lot with it. So 2790 * we don't print anything here if we get an error back. 2791 */ 2792 error = cdreadtoc(periph, 0, 0, (u_int8_t *)toch, sizeof(*toch), 2793 SF_NO_PRINT); 2794 /* 2795 * Errors in reading the table of contents aren't fatal, we just 2796 * won't have a valid table of contents cached. 2797 */ 2798 if (error != 0) { 2799 error = 0; 2800 bzero(&softc->toc, sizeof(softc->toc)); 2801 goto bailout; 2802 } 2803 2804 if (softc->quirks & CD_Q_BCD_TRACKS) { 2805 toch->starting_track = bcd2bin(toch->starting_track); 2806 toch->ending_track = bcd2bin(toch->ending_track); 2807 } 2808 2809 /* Number of TOC entries, plus leadout */ 2810 num_entries = (toch->ending_track - toch->starting_track) + 2; 2811 2812 if (num_entries <= 0) 2813 goto bailout; 2814 2815 toclen = num_entries * sizeof(struct cd_toc_entry); 2816 2817 error = cdreadtoc(periph, CD_MSF_FORMAT, toch->starting_track, 2818 (u_int8_t *)&softc->toc, toclen + sizeof(*toch), 2819 SF_NO_PRINT); 2820 if (error != 0) { 2821 error = 0; 2822 bzero(&softc->toc, sizeof(softc->toc)); 2823 goto bailout; 2824 } 2825 2826 if (softc->quirks & CD_Q_BCD_TRACKS) { 2827 toch->starting_track = bcd2bin(toch->starting_track); 2828 toch->ending_track = bcd2bin(toch->ending_track); 2829 } 2830 /* 2831 * XXX KDM is this necessary? Probably only if the drive doesn't 2832 * return leadout information with the table of contents. 2833 */ 2834 cdindex = toch->starting_track + num_entries -1; 2835 if (cdindex == toch->ending_track + 1) { 2836 2837 error = cdreadtoc(periph, CD_MSF_FORMAT, LEADOUT, 2838 (u_int8_t *)&leadout, sizeof(leadout), 2839 SF_NO_PRINT); 2840 if (error != 0) { 2841 error = 0; 2842 goto bailout; 2843 } 2844 softc->toc.entries[cdindex - toch->starting_track] = 2845 leadout.entry; 2846 } 2847 if (softc->quirks & CD_Q_BCD_TRACKS) { 2848 for (cdindex = 0; cdindex < num_entries - 1; cdindex++) { 2849 softc->toc.entries[cdindex].track = 2850 bcd2bin(softc->toc.entries[cdindex].track); 2851 } 2852 } 2853 2854 softc->flags |= CD_FLAG_VALID_TOC; 2855 2856bailout: 2857 2858 /* 2859 * We unconditionally (re)set the blocksize each time the 2860 * CD device is opened. This is because the CD can change, 2861 * and therefore the blocksize might change. 2862 * XXX problems here if some slice or partition is still 2863 * open with the old size? 2864 */ 2865 if ((softc->device_stats->flags & DEVSTAT_BS_UNAVAILABLE) != 0) 2866 softc->device_stats->flags &= ~DEVSTAT_BS_UNAVAILABLE; 2867 softc->device_stats->block_size = softc->params.blksize; 2868 2869 return (error); 2870} 2871 2872static int 2873cdsize(struct cam_periph *periph, u_int32_t *size) 2874{ 2875 struct cd_softc *softc; 2876 union ccb *ccb; 2877 struct scsi_read_capacity_data *rcap_buf; 2878 int error; 2879 2880 CAM_DEBUG(periph->path, CAM_DEBUG_TRACE, ("entering cdsize\n")); 2881 2882 softc = (struct cd_softc *)periph->softc; 2883 2884 ccb = cdgetccb(periph, /* priority */ 1); 2885 2886 rcap_buf = malloc(sizeof(struct scsi_read_capacity_data), 2887 M_TEMP, M_WAITOK); 2888 2889 scsi_read_capacity(&ccb->csio, 2890 /*retries*/ 1, 2891 cddone, 2892 MSG_SIMPLE_Q_TAG, 2893 rcap_buf, 2894 SSD_FULL_SIZE, 2895 /* timeout */20000); 2896 2897 error = cdrunccb(ccb, cderror, /*cam_flags*/CAM_RETRY_SELTO, 2898 /*sense_flags*/SF_RETRY_UA|SF_NO_PRINT); 2899 2900 xpt_release_ccb(ccb); 2901 2902 softc->params.disksize = scsi_4btoul(rcap_buf->addr) + 1; 2903 softc->params.blksize = scsi_4btoul(rcap_buf->length); 2904 /* 2905 * SCSI-3 mandates that the reported blocksize shall be 2048. 2906 * Older drives sometimes report funny values, trim it down to 2907 * 2048, or other parts of the kernel will get confused. 2908 * 2909 * XXX we leave drives alone that might report 512 bytes, as 2910 * well as drives reporting more weird sizes like perhaps 4K. 2911 */ 2912 if (softc->params.blksize > 2048 && softc->params.blksize <= 2352) 2913 softc->params.blksize = 2048; 2914 2915 free(rcap_buf, M_TEMP); 2916 *size = softc->params.disksize; 2917 2918 return (error); 2919 2920} 2921 2922static int 2923cd6byteworkaround(union ccb *ccb) 2924{ 2925 u_int8_t *cdb; 2926 struct cam_periph *periph; 2927 struct cd_softc *softc; 2928 struct cd_mode_params *params; 2929 int frozen, found; 2930 2931 periph = xpt_path_periph(ccb->ccb_h.path); 2932 softc = (struct cd_softc *)periph->softc; 2933 2934 cdb = ccb->csio.cdb_io.cdb_bytes; 2935 2936 if ((ccb->ccb_h.flags & CAM_CDB_POINTER) 2937 || ((cdb[0] != MODE_SENSE_6) 2938 && (cdb[0] != MODE_SELECT_6))) 2939 return (0); 2940 2941 /* 2942 * Because there is no convenient place to stash the overall 2943 * cd_mode_params structure pointer, we have to grab it like this. 2944 * This means that ALL MODE_SENSE and MODE_SELECT requests in the 2945 * cd(4) driver MUST go through cdgetmode() and cdsetmode()! 2946 * 2947 * XXX It would be nice if, at some point, we could increase the 2948 * number of available peripheral private pointers. Both pointers 2949 * are currently used in most every peripheral driver. 2950 */ 2951 found = 0; 2952 2953 STAILQ_FOREACH(params, &softc->mode_queue, links) { 2954 if (params->mode_buf == ccb->csio.data_ptr) { 2955 found = 1; 2956 break; 2957 } 2958 } 2959 2960 /* 2961 * This shouldn't happen. All mode sense and mode select 2962 * operations in the cd(4) driver MUST go through cdgetmode() and 2963 * cdsetmode()! 2964 */ 2965 if (found == 0) { 2966 xpt_print_path(periph->path); 2967 printf("mode buffer not found in mode queue!\n"); 2968 return (0); 2969 } 2970 2971 params->cdb_size = 10; 2972 softc->minimum_command_size = 10; 2973 xpt_print_path(ccb->ccb_h.path); 2974 printf("%s(6) failed, increasing minimum CDB size to 10 bytes\n", 2975 (cdb[0] == MODE_SENSE_6) ? "MODE_SENSE" : "MODE_SELECT"); 2976 2977 if (cdb[0] == MODE_SENSE_6) { 2978 struct scsi_mode_sense_10 ms10; 2979 struct scsi_mode_sense_6 *ms6; 2980 int len; 2981 2982 ms6 = (struct scsi_mode_sense_6 *)cdb; 2983 2984 bzero(&ms10, sizeof(ms10)); 2985 ms10.opcode = MODE_SENSE_10; 2986 ms10.byte2 = ms6->byte2; 2987 ms10.page = ms6->page; 2988 2989 /* 2990 * 10 byte mode header, block descriptor, 2991 * sizeof(union cd_pages) 2992 */ 2993 len = sizeof(struct cd_mode_data_10); 2994 ccb->csio.dxfer_len = len; 2995 2996 scsi_ulto2b(len, ms10.length); 2997 ms10.control = ms6->control; 2998 bcopy(&ms10, cdb, 10); 2999 ccb->csio.cdb_len = 10; 3000 } else { 3001 struct scsi_mode_select_10 ms10; 3002 struct scsi_mode_select_6 *ms6; 3003 struct scsi_mode_header_6 *header6; 3004 struct scsi_mode_header_10 *header10; 3005 struct scsi_mode_page_header *page_header; 3006 int blk_desc_len, page_num, page_size, len; 3007 3008 ms6 = (struct scsi_mode_select_6 *)cdb; 3009 3010 bzero(&ms10, sizeof(ms10)); 3011 ms10.opcode = MODE_SELECT_10; 3012 ms10.byte2 = ms6->byte2; 3013 3014 header6 = (struct scsi_mode_header_6 *)params->mode_buf; 3015 header10 = (struct scsi_mode_header_10 *)params->mode_buf; 3016 3017 page_header = find_mode_page_6(header6); 3018 page_num = page_header->page_code; 3019 3020 blk_desc_len = header6->blk_desc_len; 3021 3022 page_size = cdgetpagesize(page_num); 3023 3024 if (page_size != (page_header->page_length + 3025 sizeof(*page_header))) 3026 page_size = page_header->page_length + 3027 sizeof(*page_header); 3028 3029 len = sizeof(*header10) + blk_desc_len + page_size; 3030 3031 len = min(params->alloc_len, len); 3032 3033 /* 3034 * Since the 6 byte parameter header is shorter than the 10 3035 * byte parameter header, we need to copy the actual mode 3036 * page data, and the block descriptor, if any, so things wind 3037 * up in the right place. The regions will overlap, but 3038 * bcopy() does the right thing. 3039 */ 3040 bcopy(params->mode_buf + sizeof(*header6), 3041 params->mode_buf + sizeof(*header10), 3042 len - sizeof(*header10)); 3043 3044 /* Make sure these fields are set correctly. */ 3045 scsi_ulto2b(0, header10->data_length); 3046 header10->medium_type = 0; 3047 scsi_ulto2b(blk_desc_len, header10->blk_desc_len); 3048 3049 ccb->csio.dxfer_len = len; 3050 3051 scsi_ulto2b(len, ms10.length); 3052 ms10.control = ms6->control; 3053 bcopy(&ms10, cdb, 10); 3054 ccb->csio.cdb_len = 10; 3055 } 3056 3057 frozen = (ccb->ccb_h.status & CAM_DEV_QFRZN) != 0; 3058 ccb->ccb_h.status = CAM_REQUEUE_REQ; 3059 xpt_action(ccb); 3060 if (frozen) { 3061 cam_release_devq(ccb->ccb_h.path, 3062 /*relsim_flags*/0, 3063 /*openings*/0, 3064 /*timeout*/0, 3065 /*getcount_only*/0); 3066 } 3067 3068 return (ERESTART); 3069} 3070 3071static int 3072cderror(union ccb *ccb, u_int32_t cam_flags, u_int32_t sense_flags) 3073{ 3074 struct cd_softc *softc; 3075 struct cam_periph *periph; 3076 int error; 3077 3078 periph = xpt_path_periph(ccb->ccb_h.path); 3079 softc = (struct cd_softc *)periph->softc; 3080 3081 error = 0; 3082 3083 /* 3084 * We use a status of CAM_REQ_INVALID as shorthand -- if a 6 byte 3085 * CDB comes back with this particular error, try transforming it 3086 * into the 10 byte version. 3087 */ 3088 if ((ccb->ccb_h.status & CAM_STATUS_MASK) == CAM_REQ_INVALID) { 3089 error = cd6byteworkaround(ccb); 3090 } else if (((ccb->ccb_h.status & CAM_STATUS_MASK) == 3091 CAM_SCSI_STATUS_ERROR) 3092 && (ccb->ccb_h.status & CAM_AUTOSNS_VALID) 3093 && (ccb->csio.scsi_status == SCSI_STATUS_CHECK_COND) 3094 && ((ccb->ccb_h.flags & CAM_SENSE_PHYS) == 0) 3095 && ((ccb->ccb_h.flags & CAM_SENSE_PTR) == 0)) { 3096 int sense_key, error_code, asc, ascq; 3097 3098 scsi_extract_sense(&ccb->csio.sense_data, 3099 &error_code, &sense_key, &asc, &ascq); 3100 if (sense_key == SSD_KEY_ILLEGAL_REQUEST) 3101 error = cd6byteworkaround(ccb); 3102 } 3103 3104 if (error == ERESTART) 3105 return (error); 3106 3107 /* 3108 * XXX 3109 * Until we have a better way of doing pack validation, 3110 * don't treat UAs as errors. 3111 */ 3112 sense_flags |= SF_RETRY_UA; 3113 return (cam_periph_error(ccb, cam_flags, sense_flags, 3114 &softc->saved_ccb)); 3115} 3116 3117/* 3118 * Read table of contents 3119 */ 3120static int 3121cdreadtoc(struct cam_periph *periph, u_int32_t mode, u_int32_t start, 3122 u_int8_t *data, u_int32_t len, u_int32_t sense_flags) 3123{ 3124 struct scsi_read_toc *scsi_cmd; 3125 u_int32_t ntoc; 3126 struct ccb_scsiio *csio; 3127 union ccb *ccb; 3128 int error; 3129 3130 ntoc = len; 3131 error = 0; 3132 3133 ccb = cdgetccb(periph, /* priority */ 1); 3134 3135 csio = &ccb->csio; 3136 3137 cam_fill_csio(csio, 3138 /* retries */ 1, 3139 /* cbfcnp */ cddone, 3140 /* flags */ CAM_DIR_IN, 3141 /* tag_action */ MSG_SIMPLE_Q_TAG, 3142 /* data_ptr */ data, 3143 /* dxfer_len */ len, 3144 /* sense_len */ SSD_FULL_SIZE, 3145 sizeof(struct scsi_read_toc), 3146 /* timeout */ 50000); 3147 3148 scsi_cmd = (struct scsi_read_toc *)&csio->cdb_io.cdb_bytes; 3149 bzero (scsi_cmd, sizeof(*scsi_cmd)); 3150 3151 if (mode == CD_MSF_FORMAT) 3152 scsi_cmd->byte2 |= CD_MSF; 3153 scsi_cmd->from_track = start; 3154 /* scsi_ulto2b(ntoc, (u_int8_t *)scsi_cmd->data_len); */ 3155 scsi_cmd->data_len[0] = (ntoc) >> 8; 3156 scsi_cmd->data_len[1] = (ntoc) & 0xff; 3157 3158 scsi_cmd->op_code = READ_TOC; 3159 3160 error = cdrunccb(ccb, cderror, /*cam_flags*/CAM_RETRY_SELTO, 3161 /*sense_flags*/SF_RETRY_UA | sense_flags); 3162 3163 xpt_release_ccb(ccb); 3164 3165 return(error); 3166} 3167 3168static int 3169cdreadsubchannel(struct cam_periph *periph, u_int32_t mode, 3170 u_int32_t format, int track, 3171 struct cd_sub_channel_info *data, u_int32_t len) 3172{ 3173 struct scsi_read_subchannel *scsi_cmd; 3174 struct ccb_scsiio *csio; 3175 union ccb *ccb; 3176 int error; 3177 3178 error = 0; 3179 3180 ccb = cdgetccb(periph, /* priority */ 1); 3181 3182 csio = &ccb->csio; 3183 3184 cam_fill_csio(csio, 3185 /* retries */ 1, 3186 /* cbfcnp */ cddone, 3187 /* flags */ CAM_DIR_IN, 3188 /* tag_action */ MSG_SIMPLE_Q_TAG, 3189 /* data_ptr */ (u_int8_t *)data, 3190 /* dxfer_len */ len, 3191 /* sense_len */ SSD_FULL_SIZE, 3192 sizeof(struct scsi_read_subchannel), 3193 /* timeout */ 50000); 3194 3195 scsi_cmd = (struct scsi_read_subchannel *)&csio->cdb_io.cdb_bytes; 3196 bzero (scsi_cmd, sizeof(*scsi_cmd)); 3197 3198 scsi_cmd->op_code = READ_SUBCHANNEL; 3199 if (mode == CD_MSF_FORMAT) 3200 scsi_cmd->byte1 |= CD_MSF; 3201 scsi_cmd->byte2 = SRS_SUBQ; 3202 scsi_cmd->subchan_format = format; 3203 scsi_cmd->track = track; 3204 scsi_ulto2b(len, (u_int8_t *)scsi_cmd->data_len); 3205 scsi_cmd->control = 0; 3206 3207 error = cdrunccb(ccb, cderror, /*cam_flags*/CAM_RETRY_SELTO, 3208 /*sense_flags*/SF_RETRY_UA); 3209 3210 xpt_release_ccb(ccb); 3211 3212 return(error); 3213} 3214 3215 3216/* 3217 * All MODE_SENSE requests in the cd(4) driver MUST go through this 3218 * routine. See comments in cd6byteworkaround() for details. 3219 */ 3220static int 3221cdgetmode(struct cam_periph *periph, struct cd_mode_params *data, 3222 u_int32_t page) 3223{ 3224 struct ccb_scsiio *csio; 3225 struct cd_softc *softc; 3226 union ccb *ccb; 3227 int param_len; 3228 int error; 3229 3230 softc = (struct cd_softc *)periph->softc; 3231 3232 ccb = cdgetccb(periph, /* priority */ 1); 3233 3234 csio = &ccb->csio; 3235 3236 data->cdb_size = softc->minimum_command_size; 3237 if (data->cdb_size < 10) 3238 param_len = sizeof(struct cd_mode_data); 3239 else 3240 param_len = sizeof(struct cd_mode_data_10); 3241 3242 /* Don't say we've got more room than we actually allocated */ 3243 param_len = min(param_len, data->alloc_len); 3244 3245 scsi_mode_sense_len(csio, 3246 /* retries */ 1, 3247 /* cbfcnp */ cddone, 3248 /* tag_action */ MSG_SIMPLE_Q_TAG, 3249 /* dbd */ 0, 3250 /* page_code */ SMS_PAGE_CTRL_CURRENT, 3251 /* page */ page, 3252 /* param_buf */ data->mode_buf, 3253 /* param_len */ param_len, 3254 /* minimum_cmd_size */ softc->minimum_command_size, 3255 /* sense_len */ SSD_FULL_SIZE, 3256 /* timeout */ 50000); 3257 3258 /* 3259 * It would be nice not to have to do this, but there's no 3260 * available pointer in the CCB that would allow us to stuff the 3261 * mode params structure in there and retrieve it in 3262 * cd6byteworkaround(), so we can set the cdb size. The cdb size 3263 * lets the caller know what CDB size we ended up using, so they 3264 * can find the actual mode page offset. 3265 */ 3266 STAILQ_INSERT_TAIL(&softc->mode_queue, data, links); 3267 3268 error = cdrunccb(ccb, cderror, /*cam_flags*/CAM_RETRY_SELTO, 3269 /*sense_flags*/SF_RETRY_UA); 3270 3271 xpt_release_ccb(ccb); 3272 3273 STAILQ_REMOVE(&softc->mode_queue, data, cd_mode_params, links); 3274 3275 /* 3276 * This is a bit of belt-and-suspenders checking, but if we run 3277 * into a situation where the target sends back multiple block 3278 * descriptors, we might not have enough space in the buffer to 3279 * see the whole mode page. Better to return an error than 3280 * potentially access memory beyond our malloced region. 3281 */ 3282 if (error == 0) { 3283 u_int32_t data_len; 3284 3285 if (data->cdb_size == 10) { 3286 struct scsi_mode_header_10 *hdr10; 3287 3288 hdr10 = (struct scsi_mode_header_10 *)data->mode_buf; 3289 data_len = scsi_2btoul(hdr10->data_length); 3290 data_len += sizeof(hdr10->data_length); 3291 } else { 3292 struct scsi_mode_header_6 *hdr6; 3293 3294 hdr6 = (struct scsi_mode_header_6 *)data->mode_buf; 3295 data_len = hdr6->data_length; 3296 data_len += sizeof(hdr6->data_length); 3297 } 3298 3299 /* 3300 * Complain if there is more mode data available than we 3301 * allocated space for. This could potentially happen if 3302 * we miscalculated the page length for some reason, if the 3303 * drive returns multiple block descriptors, or if it sets 3304 * the data length incorrectly. 3305 */ 3306 if (data_len > data->alloc_len) { 3307 xpt_print_path(periph->path); 3308 printf("allocated modepage %d length %d < returned " 3309 "length %d\n", page, data->alloc_len, data_len); 3310 3311 error = ENOSPC; 3312 } 3313 } 3314 return (error); 3315} 3316 3317/* 3318 * All MODE_SELECT requests in the cd(4) driver MUST go through this 3319 * routine. See comments in cd6byteworkaround() for details. 3320 */ 3321static int 3322cdsetmode(struct cam_periph *periph, struct cd_mode_params *data) 3323{ 3324 struct ccb_scsiio *csio; 3325 struct cd_softc *softc; 3326 union ccb *ccb; 3327 int cdb_size, param_len; 3328 int error; 3329 3330 softc = (struct cd_softc *)periph->softc; 3331 3332 ccb = cdgetccb(periph, /* priority */ 1); 3333 3334 csio = &ccb->csio; 3335 3336 error = 0; 3337 3338 /* 3339 * If the data is formatted for the 10 byte version of the mode 3340 * select parameter list, we need to use the 10 byte CDB. 3341 * Otherwise, we use whatever the stored minimum command size. 3342 */ 3343 if (data->cdb_size == 10) 3344 cdb_size = data->cdb_size; 3345 else 3346 cdb_size = softc->minimum_command_size; 3347 3348 if (cdb_size >= 10) { 3349 struct scsi_mode_header_10 *mode_header; 3350 u_int32_t data_len; 3351 3352 mode_header = (struct scsi_mode_header_10 *)data->mode_buf; 3353 3354 data_len = scsi_2btoul(mode_header->data_length); 3355 3356 scsi_ulto2b(0, mode_header->data_length); 3357 /* 3358 * SONY drives do not allow a mode select with a medium_type 3359 * value that has just been returned by a mode sense; use a 3360 * medium_type of 0 (Default) instead. 3361 */ 3362 mode_header->medium_type = 0; 3363 3364 /* 3365 * Pass back whatever the drive passed to us, plus the size 3366 * of the data length field. 3367 */ 3368 param_len = data_len + sizeof(mode_header->data_length); 3369 3370 } else { 3371 struct scsi_mode_header_6 *mode_header; 3372 3373 mode_header = (struct scsi_mode_header_6 *)data->mode_buf; 3374 3375 param_len = mode_header->data_length + 1; 3376 3377 mode_header->data_length = 0; 3378 /* 3379 * SONY drives do not allow a mode select with a medium_type 3380 * value that has just been returned by a mode sense; use a 3381 * medium_type of 0 (Default) instead. 3382 */ 3383 mode_header->medium_type = 0; 3384 } 3385 3386 /* Don't say we've got more room than we actually allocated */ 3387 param_len = min(param_len, data->alloc_len); 3388 3389 scsi_mode_select_len(csio, 3390 /* retries */ 1, 3391 /* cbfcnp */ cddone, 3392 /* tag_action */ MSG_SIMPLE_Q_TAG, 3393 /* scsi_page_fmt */ 1, 3394 /* save_pages */ 0, 3395 /* param_buf */ data->mode_buf, 3396 /* param_len */ param_len, 3397 /* minimum_cmd_size */ cdb_size, 3398 /* sense_len */ SSD_FULL_SIZE, 3399 /* timeout */ 50000); 3400 3401 /* See comments in cdgetmode() and cd6byteworkaround(). */ 3402 STAILQ_INSERT_TAIL(&softc->mode_queue, data, links); 3403 3404 error = cdrunccb(ccb, cderror, /*cam_flags*/CAM_RETRY_SELTO, 3405 /*sense_flags*/SF_RETRY_UA); 3406 3407 xpt_release_ccb(ccb); 3408 3409 STAILQ_REMOVE(&softc->mode_queue, data, cd_mode_params, links); 3410 3411 return (error); 3412} 3413 3414 3415static int 3416cdplay(struct cam_periph *periph, u_int32_t blk, u_int32_t len) 3417{ 3418 struct ccb_scsiio *csio; 3419 union ccb *ccb; 3420 int error; 3421 u_int8_t cdb_len; 3422 3423 error = 0; 3424 ccb = cdgetccb(periph, /* priority */ 1); 3425 csio = &ccb->csio; 3426 /* 3427 * Use the smallest possible command to perform the operation. 3428 */ 3429 if ((len & 0xffff0000) == 0) { 3430 /* 3431 * We can fit in a 10 byte cdb. 3432 */ 3433 struct scsi_play_10 *scsi_cmd; 3434 3435 scsi_cmd = (struct scsi_play_10 *)&csio->cdb_io.cdb_bytes; 3436 bzero (scsi_cmd, sizeof(*scsi_cmd)); 3437 scsi_cmd->op_code = PLAY_10; 3438 scsi_ulto4b(blk, (u_int8_t *)scsi_cmd->blk_addr); 3439 scsi_ulto2b(len, (u_int8_t *)scsi_cmd->xfer_len); 3440 cdb_len = sizeof(*scsi_cmd); 3441 } else { 3442 struct scsi_play_12 *scsi_cmd; 3443 3444 scsi_cmd = (struct scsi_play_12 *)&csio->cdb_io.cdb_bytes; 3445 bzero (scsi_cmd, sizeof(*scsi_cmd)); 3446 scsi_cmd->op_code = PLAY_12; 3447 scsi_ulto4b(blk, (u_int8_t *)scsi_cmd->blk_addr); 3448 scsi_ulto4b(len, (u_int8_t *)scsi_cmd->xfer_len); 3449 cdb_len = sizeof(*scsi_cmd); 3450 } 3451 cam_fill_csio(csio, 3452 /*retries*/2, 3453 cddone, 3454 /*flags*/CAM_DIR_NONE, 3455 MSG_SIMPLE_Q_TAG, 3456 /*dataptr*/NULL, 3457 /*datalen*/0, 3458 /*sense_len*/SSD_FULL_SIZE, 3459 cdb_len, 3460 /*timeout*/50 * 1000); 3461 3462 error = cdrunccb(ccb, cderror, /*cam_flags*/CAM_RETRY_SELTO, 3463 /*sense_flags*/SF_RETRY_UA); 3464 3465 xpt_release_ccb(ccb); 3466 3467 return(error); 3468} 3469 3470static int 3471cdplaymsf(struct cam_periph *periph, u_int32_t startm, u_int32_t starts, 3472 u_int32_t startf, u_int32_t endm, u_int32_t ends, u_int32_t endf) 3473{ 3474 struct scsi_play_msf *scsi_cmd; 3475 struct ccb_scsiio *csio; 3476 union ccb *ccb; 3477 int error; 3478 3479 error = 0; 3480 3481 ccb = cdgetccb(periph, /* priority */ 1); 3482 3483 csio = &ccb->csio; 3484 3485 cam_fill_csio(csio, 3486 /* retries */ 1, 3487 /* cbfcnp */ cddone, 3488 /* flags */ CAM_DIR_NONE, 3489 /* tag_action */ MSG_SIMPLE_Q_TAG, 3490 /* data_ptr */ NULL, 3491 /* dxfer_len */ 0, 3492 /* sense_len */ SSD_FULL_SIZE, 3493 sizeof(struct scsi_play_msf), 3494 /* timeout */ 50000); 3495 3496 scsi_cmd = (struct scsi_play_msf *)&csio->cdb_io.cdb_bytes; 3497 bzero (scsi_cmd, sizeof(*scsi_cmd)); 3498 3499 scsi_cmd->op_code = PLAY_MSF; 3500 scsi_cmd->start_m = startm; 3501 scsi_cmd->start_s = starts; 3502 scsi_cmd->start_f = startf; 3503 scsi_cmd->end_m = endm; 3504 scsi_cmd->end_s = ends; 3505 scsi_cmd->end_f = endf; 3506 3507 error = cdrunccb(ccb, cderror, /*cam_flags*/CAM_RETRY_SELTO, 3508 /*sense_flags*/SF_RETRY_UA); 3509 3510 xpt_release_ccb(ccb); 3511 3512 return(error); 3513} 3514 3515 3516static int 3517cdplaytracks(struct cam_periph *periph, u_int32_t strack, u_int32_t sindex, 3518 u_int32_t etrack, u_int32_t eindex) 3519{ 3520 struct scsi_play_track *scsi_cmd; 3521 struct ccb_scsiio *csio; 3522 union ccb *ccb; 3523 int error; 3524 3525 error = 0; 3526 3527 ccb = cdgetccb(periph, /* priority */ 1); 3528 3529 csio = &ccb->csio; 3530 3531 cam_fill_csio(csio, 3532 /* retries */ 1, 3533 /* cbfcnp */ cddone, 3534 /* flags */ CAM_DIR_NONE, 3535 /* tag_action */ MSG_SIMPLE_Q_TAG, 3536 /* data_ptr */ NULL, 3537 /* dxfer_len */ 0, 3538 /* sense_len */ SSD_FULL_SIZE, 3539 sizeof(struct scsi_play_track), 3540 /* timeout */ 50000); 3541 3542 scsi_cmd = (struct scsi_play_track *)&csio->cdb_io.cdb_bytes; 3543 bzero (scsi_cmd, sizeof(*scsi_cmd)); 3544 3545 scsi_cmd->op_code = PLAY_TRACK; 3546 scsi_cmd->start_track = strack; 3547 scsi_cmd->start_index = sindex; 3548 scsi_cmd->end_track = etrack; 3549 scsi_cmd->end_index = eindex; 3550 3551 error = cdrunccb(ccb, cderror, /*cam_flags*/CAM_RETRY_SELTO, 3552 /*sense_flags*/SF_RETRY_UA); 3553 3554 xpt_release_ccb(ccb); 3555 3556 return(error); 3557} 3558 3559static int 3560cdpause(struct cam_periph *periph, u_int32_t go) 3561{ 3562 struct scsi_pause *scsi_cmd; 3563 struct ccb_scsiio *csio; 3564 union ccb *ccb; 3565 int error; 3566 3567 error = 0; 3568 3569 ccb = cdgetccb(periph, /* priority */ 1); 3570 3571 csio = &ccb->csio; 3572 3573 cam_fill_csio(csio, 3574 /* retries */ 1, 3575 /* cbfcnp */ cddone, 3576 /* flags */ CAM_DIR_NONE, 3577 /* tag_action */ MSG_SIMPLE_Q_TAG, 3578 /* data_ptr */ NULL, 3579 /* dxfer_len */ 0, 3580 /* sense_len */ SSD_FULL_SIZE, 3581 sizeof(struct scsi_pause), 3582 /* timeout */ 50000); 3583 3584 scsi_cmd = (struct scsi_pause *)&csio->cdb_io.cdb_bytes; 3585 bzero (scsi_cmd, sizeof(*scsi_cmd)); 3586 3587 scsi_cmd->op_code = PAUSE; 3588 scsi_cmd->resume = go; 3589 3590 error = cdrunccb(ccb, cderror, /*cam_flags*/CAM_RETRY_SELTO, 3591 /*sense_flags*/SF_RETRY_UA); 3592 3593 xpt_release_ccb(ccb); 3594 3595 return(error); 3596} 3597 3598static int 3599cdstartunit(struct cam_periph *periph, int load) 3600{ 3601 union ccb *ccb; 3602 int error; 3603 3604 error = 0; 3605 3606 ccb = cdgetccb(periph, /* priority */ 1); 3607 3608 scsi_start_stop(&ccb->csio, 3609 /* retries */ 1, 3610 /* cbfcnp */ cddone, 3611 /* tag_action */ MSG_SIMPLE_Q_TAG, 3612 /* start */ TRUE, 3613 /* load_eject */ load, 3614 /* immediate */ FALSE, 3615 /* sense_len */ SSD_FULL_SIZE, 3616 /* timeout */ 50000); 3617 3618 error = cdrunccb(ccb, cderror, /*cam_flags*/CAM_RETRY_SELTO, 3619 /*sense_flags*/SF_RETRY_UA); 3620 3621 xpt_release_ccb(ccb); 3622 3623 return(error); 3624} 3625 3626static int 3627cdstopunit(struct cam_periph *periph, u_int32_t eject) 3628{ 3629 union ccb *ccb; 3630 int error; 3631 3632 error = 0; 3633 3634 ccb = cdgetccb(periph, /* priority */ 1); 3635 3636 scsi_start_stop(&ccb->csio, 3637 /* retries */ 1, 3638 /* cbfcnp */ cddone, 3639 /* tag_action */ MSG_SIMPLE_Q_TAG, 3640 /* start */ FALSE, 3641 /* load_eject */ eject, 3642 /* immediate */ FALSE, 3643 /* sense_len */ SSD_FULL_SIZE, 3644 /* timeout */ 50000); 3645 3646 error = cdrunccb(ccb, cderror, /*cam_flags*/CAM_RETRY_SELTO, 3647 /*sense_flags*/SF_RETRY_UA); 3648 3649 xpt_release_ccb(ccb); 3650 3651 return(error); 3652} 3653 3654static int 3655cdsetspeed(struct cam_periph *periph, u_int32_t rdspeed, u_int32_t wrspeed) 3656{ 3657 struct scsi_set_speed *scsi_cmd; 3658 struct ccb_scsiio *csio; 3659 union ccb *ccb; 3660 int error; 3661 3662 error = 0; 3663 ccb = cdgetccb(periph, /* priority */ 1); 3664 csio = &ccb->csio; 3665 3666 /* Preserve old behavior: units in multiples of CDROM speed */ 3667 if (rdspeed < 177) 3668 rdspeed *= 177; 3669 if (wrspeed < 177) 3670 wrspeed *= 177; 3671 3672 cam_fill_csio(csio, 3673 /* retries */ 1, 3674 /* cbfcnp */ cddone, 3675 /* flags */ CAM_DIR_NONE, 3676 /* tag_action */ MSG_SIMPLE_Q_TAG, 3677 /* data_ptr */ NULL, 3678 /* dxfer_len */ 0, 3679 /* sense_len */ SSD_FULL_SIZE, 3680 sizeof(struct scsi_set_speed), 3681 /* timeout */ 50000); 3682 3683 scsi_cmd = (struct scsi_set_speed *)&csio->cdb_io.cdb_bytes; 3684 bzero(scsi_cmd, sizeof(*scsi_cmd)); 3685 3686 scsi_cmd->opcode = SET_CD_SPEED; 3687 scsi_ulto2b(rdspeed, scsi_cmd->readspeed); 3688 scsi_ulto2b(wrspeed, scsi_cmd->writespeed); 3689 3690 error = cdrunccb(ccb, cderror, /*cam_flags*/CAM_RETRY_SELTO, 3691 /*sense_flags*/SF_RETRY_UA); 3692 3693 xpt_release_ccb(ccb); 3694 3695 return(error); 3696} 3697 3698static int 3699cdreportkey(struct cam_periph *periph, struct dvd_authinfo *authinfo) 3700{ 3701 union ccb *ccb; 3702 u_int8_t *databuf; 3703 u_int32_t lba; 3704 int error; 3705 int length; 3706 3707 error = 0; 3708 databuf = NULL; 3709 lba = 0; 3710 3711 ccb = cdgetccb(periph, /* priority */ 1); 3712 3713 switch (authinfo->format) { 3714 case DVD_REPORT_AGID: 3715 length = sizeof(struct scsi_report_key_data_agid); 3716 break; 3717 case DVD_REPORT_CHALLENGE: 3718 length = sizeof(struct scsi_report_key_data_challenge); 3719 break; 3720 case DVD_REPORT_KEY1: 3721 length = sizeof(struct scsi_report_key_data_key1_key2); 3722 break; 3723 case DVD_REPORT_TITLE_KEY: 3724 length = sizeof(struct scsi_report_key_data_title); 3725 /* The lba field is only set for the title key */ 3726 lba = authinfo->lba; 3727 break; 3728 case DVD_REPORT_ASF: 3729 length = sizeof(struct scsi_report_key_data_asf); 3730 break; 3731 case DVD_REPORT_RPC: 3732 length = sizeof(struct scsi_report_key_data_rpc); 3733 break; 3734 case DVD_INVALIDATE_AGID: 3735 length = 0; 3736 break; 3737 default: 3738 error = EINVAL; 3739 goto bailout; 3740 break; /* NOTREACHED */ 3741 } 3742 3743 if (length != 0) { 3744 databuf = malloc(length, M_DEVBUF, M_WAITOK | M_ZERO); 3745 } else 3746 databuf = NULL; 3747 3748 3749 scsi_report_key(&ccb->csio, 3750 /* retries */ 1, 3751 /* cbfcnp */ cddone, 3752 /* tag_action */ MSG_SIMPLE_Q_TAG, 3753 /* lba */ lba, 3754 /* agid */ authinfo->agid, 3755 /* key_format */ authinfo->format, 3756 /* data_ptr */ databuf, 3757 /* dxfer_len */ length, 3758 /* sense_len */ SSD_FULL_SIZE, 3759 /* timeout */ 50000); 3760 3761 error = cdrunccb(ccb, cderror, /*cam_flags*/CAM_RETRY_SELTO, 3762 /*sense_flags*/SF_RETRY_UA); 3763 3764 if (error != 0) 3765 goto bailout; 3766 3767 if (ccb->csio.resid != 0) { 3768 xpt_print_path(periph->path); 3769 printf("warning, residual for report key command is %d\n", 3770 ccb->csio.resid); 3771 } 3772 3773 switch(authinfo->format) { 3774 case DVD_REPORT_AGID: { 3775 struct scsi_report_key_data_agid *agid_data; 3776 3777 agid_data = (struct scsi_report_key_data_agid *)databuf; 3778 3779 authinfo->agid = (agid_data->agid & RKD_AGID_MASK) >> 3780 RKD_AGID_SHIFT; 3781 break; 3782 } 3783 case DVD_REPORT_CHALLENGE: { 3784 struct scsi_report_key_data_challenge *chal_data; 3785 3786 chal_data = (struct scsi_report_key_data_challenge *)databuf; 3787 3788 bcopy(chal_data->challenge_key, authinfo->keychal, 3789 min(sizeof(chal_data->challenge_key), 3790 sizeof(authinfo->keychal))); 3791 break; 3792 } 3793 case DVD_REPORT_KEY1: { 3794 struct scsi_report_key_data_key1_key2 *key1_data; 3795 3796 key1_data = (struct scsi_report_key_data_key1_key2 *)databuf; 3797 3798 bcopy(key1_data->key1, authinfo->keychal, 3799 min(sizeof(key1_data->key1), sizeof(authinfo->keychal))); 3800 break; 3801 } 3802 case DVD_REPORT_TITLE_KEY: { 3803 struct scsi_report_key_data_title *title_data; 3804 3805 title_data = (struct scsi_report_key_data_title *)databuf; 3806 3807 authinfo->cpm = (title_data->byte0 & RKD_TITLE_CPM) >> 3808 RKD_TITLE_CPM_SHIFT; 3809 authinfo->cp_sec = (title_data->byte0 & RKD_TITLE_CP_SEC) >> 3810 RKD_TITLE_CP_SEC_SHIFT; 3811 authinfo->cgms = (title_data->byte0 & RKD_TITLE_CMGS_MASK) >> 3812 RKD_TITLE_CMGS_SHIFT; 3813 bcopy(title_data->title_key, authinfo->keychal, 3814 min(sizeof(title_data->title_key), 3815 sizeof(authinfo->keychal))); 3816 break; 3817 } 3818 case DVD_REPORT_ASF: { 3819 struct scsi_report_key_data_asf *asf_data; 3820 3821 asf_data = (struct scsi_report_key_data_asf *)databuf; 3822 3823 authinfo->asf = asf_data->success & RKD_ASF_SUCCESS; 3824 break; 3825 } 3826 case DVD_REPORT_RPC: { 3827 struct scsi_report_key_data_rpc *rpc_data; 3828 3829 rpc_data = (struct scsi_report_key_data_rpc *)databuf; 3830 3831 authinfo->reg_type = (rpc_data->byte4 & RKD_RPC_TYPE_MASK) >> 3832 RKD_RPC_TYPE_SHIFT; 3833 authinfo->vend_rsts = 3834 (rpc_data->byte4 & RKD_RPC_VENDOR_RESET_MASK) >> 3835 RKD_RPC_VENDOR_RESET_SHIFT; 3836 authinfo->user_rsts = rpc_data->byte4 & RKD_RPC_USER_RESET_MASK; 3837 authinfo->region = rpc_data->region_mask; 3838 authinfo->rpc_scheme = rpc_data->rpc_scheme1; 3839 break; 3840 } 3841 case DVD_INVALIDATE_AGID: 3842 break; 3843 default: 3844 /* This should be impossible, since we checked above */ 3845 error = EINVAL; 3846 goto bailout; 3847 break; /* NOTREACHED */ 3848 } 3849bailout: 3850 if (databuf != NULL) 3851 free(databuf, M_DEVBUF); 3852 3853 xpt_release_ccb(ccb); 3854 3855 return(error); 3856} 3857 3858static int 3859cdsendkey(struct cam_periph *periph, struct dvd_authinfo *authinfo) 3860{ 3861 union ccb *ccb; 3862 u_int8_t *databuf; 3863 int length; 3864 int error; 3865 3866 error = 0; 3867 databuf = NULL; 3868 3869 ccb = cdgetccb(periph, /* priority */ 1); 3870 3871 switch(authinfo->format) { 3872 case DVD_SEND_CHALLENGE: { 3873 struct scsi_report_key_data_challenge *challenge_data; 3874 3875 length = sizeof(*challenge_data); 3876 3877 challenge_data = malloc(length, M_DEVBUF, M_WAITOK | M_ZERO); 3878 3879 databuf = (u_int8_t *)challenge_data; 3880 3881 scsi_ulto2b(length - sizeof(challenge_data->data_len), 3882 challenge_data->data_len); 3883 3884 bcopy(authinfo->keychal, challenge_data->challenge_key, 3885 min(sizeof(authinfo->keychal), 3886 sizeof(challenge_data->challenge_key))); 3887 break; 3888 } 3889 case DVD_SEND_KEY2: { 3890 struct scsi_report_key_data_key1_key2 *key2_data; 3891 3892 length = sizeof(*key2_data); 3893 3894 key2_data = malloc(length, M_DEVBUF, M_WAITOK | M_ZERO); 3895 3896 databuf = (u_int8_t *)key2_data; 3897 3898 scsi_ulto2b(length - sizeof(key2_data->data_len), 3899 key2_data->data_len); 3900 3901 bcopy(authinfo->keychal, key2_data->key1, 3902 min(sizeof(authinfo->keychal), sizeof(key2_data->key1))); 3903 3904 break; 3905 } 3906 case DVD_SEND_RPC: { 3907 struct scsi_send_key_data_rpc *rpc_data; 3908 3909 length = sizeof(*rpc_data); 3910 3911 rpc_data = malloc(length, M_DEVBUF, M_WAITOK | M_ZERO); 3912 3913 databuf = (u_int8_t *)rpc_data; 3914 3915 scsi_ulto2b(length - sizeof(rpc_data->data_len), 3916 rpc_data->data_len); 3917 3918 rpc_data->region_code = authinfo->region; 3919 break; 3920 } 3921 default: 3922 error = EINVAL; 3923 goto bailout; 3924 break; /* NOTREACHED */ 3925 } 3926 3927 scsi_send_key(&ccb->csio, 3928 /* retries */ 1, 3929 /* cbfcnp */ cddone, 3930 /* tag_action */ MSG_SIMPLE_Q_TAG, 3931 /* agid */ authinfo->agid, 3932 /* key_format */ authinfo->format, 3933 /* data_ptr */ databuf, 3934 /* dxfer_len */ length, 3935 /* sense_len */ SSD_FULL_SIZE, 3936 /* timeout */ 50000); 3937 3938 error = cdrunccb(ccb, cderror, /*cam_flags*/CAM_RETRY_SELTO, 3939 /*sense_flags*/SF_RETRY_UA); 3940 3941bailout: 3942 3943 if (databuf != NULL) 3944 free(databuf, M_DEVBUF); 3945 3946 xpt_release_ccb(ccb); 3947 3948 return(error); 3949} 3950 3951static int 3952cdreaddvdstructure(struct cam_periph *periph, struct dvd_struct *dvdstruct) 3953{ 3954 union ccb *ccb; 3955 u_int8_t *databuf; 3956 u_int32_t address; 3957 int error; 3958 int length; 3959 3960 error = 0; 3961 databuf = NULL; 3962 /* The address is reserved for many of the formats */ 3963 address = 0; 3964 3965 ccb = cdgetccb(periph, /* priority */ 1); 3966 3967 switch(dvdstruct->format) { 3968 case DVD_STRUCT_PHYSICAL: 3969 length = sizeof(struct scsi_read_dvd_struct_data_physical); 3970 break; 3971 case DVD_STRUCT_COPYRIGHT: 3972 length = sizeof(struct scsi_read_dvd_struct_data_copyright); 3973 break; 3974 case DVD_STRUCT_DISCKEY: 3975 length = sizeof(struct scsi_read_dvd_struct_data_disc_key); 3976 break; 3977 case DVD_STRUCT_BCA: 3978 length = sizeof(struct scsi_read_dvd_struct_data_bca); 3979 break; 3980 case DVD_STRUCT_MANUFACT: 3981 length = sizeof(struct scsi_read_dvd_struct_data_manufacturer); 3982 break; 3983 case DVD_STRUCT_CMI: 3984 error = ENODEV; 3985 goto bailout; 3986#ifdef notyet 3987 length = sizeof(struct scsi_read_dvd_struct_data_copy_manage); 3988 address = dvdstruct->address; 3989#endif 3990 break; /* NOTREACHED */ 3991 case DVD_STRUCT_PROTDISCID: 3992 length = sizeof(struct scsi_read_dvd_struct_data_prot_discid); 3993 break; 3994 case DVD_STRUCT_DISCKEYBLOCK: 3995 length = sizeof(struct scsi_read_dvd_struct_data_disc_key_blk); 3996 break; 3997 case DVD_STRUCT_DDS: 3998 length = sizeof(struct scsi_read_dvd_struct_data_dds); 3999 break; 4000 case DVD_STRUCT_MEDIUM_STAT: 4001 length = sizeof(struct scsi_read_dvd_struct_data_medium_status); 4002 break; 4003 case DVD_STRUCT_SPARE_AREA: 4004 length = sizeof(struct scsi_read_dvd_struct_data_spare_area); 4005 break; 4006 case DVD_STRUCT_RMD_LAST: 4007 error = ENODEV; 4008 goto bailout; 4009#ifdef notyet 4010 length = sizeof(struct scsi_read_dvd_struct_data_rmd_borderout); 4011 address = dvdstruct->address; 4012#endif 4013 break; /* NOTREACHED */ 4014 case DVD_STRUCT_RMD_RMA: 4015 error = ENODEV; 4016 goto bailout; 4017#ifdef notyet 4018 length = sizeof(struct scsi_read_dvd_struct_data_rmd); 4019 address = dvdstruct->address; 4020#endif 4021 break; /* NOTREACHED */ 4022 case DVD_STRUCT_PRERECORDED: 4023 length = sizeof(struct scsi_read_dvd_struct_data_leadin); 4024 break; 4025 case DVD_STRUCT_UNIQUEID: 4026 length = sizeof(struct scsi_read_dvd_struct_data_disc_id); 4027 break; 4028 case DVD_STRUCT_DCB: 4029 error = ENODEV; 4030 goto bailout; 4031#ifdef notyet 4032 length = sizeof(struct scsi_read_dvd_struct_data_dcb); 4033 address = dvdstruct->address; 4034#endif 4035 break; /* NOTREACHED */ 4036 case DVD_STRUCT_LIST: 4037 /* 4038 * This is the maximum allocation length for the READ DVD 4039 * STRUCTURE command. There's nothing in the MMC3 spec 4040 * that indicates a limit in the amount of data that can 4041 * be returned from this call, other than the limits 4042 * imposed by the 2-byte length variables. 4043 */ 4044 length = 65535; 4045 break; 4046 default: 4047 error = EINVAL; 4048 goto bailout; 4049 break; /* NOTREACHED */ 4050 } 4051 4052 if (length != 0) { 4053 databuf = malloc(length, M_DEVBUF, M_WAITOK | M_ZERO); 4054 } else 4055 databuf = NULL; 4056 4057 scsi_read_dvd_structure(&ccb->csio, 4058 /* retries */ 1, 4059 /* cbfcnp */ cddone, 4060 /* tag_action */ MSG_SIMPLE_Q_TAG, 4061 /* lba */ address, 4062 /* layer_number */ dvdstruct->layer_num, 4063 /* key_format */ dvdstruct->format, 4064 /* agid */ dvdstruct->agid, 4065 /* data_ptr */ databuf, 4066 /* dxfer_len */ length, 4067 /* sense_len */ SSD_FULL_SIZE, 4068 /* timeout */ 50000); 4069 4070 error = cdrunccb(ccb, cderror, /*cam_flags*/CAM_RETRY_SELTO, 4071 /*sense_flags*/SF_RETRY_UA); 4072 4073 if (error != 0) 4074 goto bailout; 4075 4076 switch(dvdstruct->format) { 4077 case DVD_STRUCT_PHYSICAL: { 4078 struct scsi_read_dvd_struct_data_layer_desc *inlayer; 4079 struct dvd_layer *outlayer; 4080 struct scsi_read_dvd_struct_data_physical *phys_data; 4081 4082 phys_data = 4083 (struct scsi_read_dvd_struct_data_physical *)databuf; 4084 inlayer = &phys_data->layer_desc; 4085 outlayer = (struct dvd_layer *)&dvdstruct->data; 4086 4087 dvdstruct->length = sizeof(*inlayer); 4088 4089 outlayer->book_type = (inlayer->book_type_version & 4090 RDSD_BOOK_TYPE_MASK) >> RDSD_BOOK_TYPE_SHIFT; 4091 outlayer->book_version = (inlayer->book_type_version & 4092 RDSD_BOOK_VERSION_MASK); 4093 outlayer->disc_size = (inlayer->disc_size_max_rate & 4094 RDSD_DISC_SIZE_MASK) >> RDSD_DISC_SIZE_SHIFT; 4095 outlayer->max_rate = (inlayer->disc_size_max_rate & 4096 RDSD_MAX_RATE_MASK); 4097 outlayer->nlayers = (inlayer->layer_info & 4098 RDSD_NUM_LAYERS_MASK) >> RDSD_NUM_LAYERS_SHIFT; 4099 outlayer->track_path = (inlayer->layer_info & 4100 RDSD_TRACK_PATH_MASK) >> RDSD_TRACK_PATH_SHIFT; 4101 outlayer->layer_type = (inlayer->layer_info & 4102 RDSD_LAYER_TYPE_MASK); 4103 outlayer->linear_density = (inlayer->density & 4104 RDSD_LIN_DENSITY_MASK) >> RDSD_LIN_DENSITY_SHIFT; 4105 outlayer->track_density = (inlayer->density & 4106 RDSD_TRACK_DENSITY_MASK); 4107 outlayer->bca = (inlayer->bca & RDSD_BCA_MASK) >> 4108 RDSD_BCA_SHIFT; 4109 outlayer->start_sector = scsi_3btoul(inlayer->main_data_start); 4110 outlayer->end_sector = scsi_3btoul(inlayer->main_data_end); 4111 outlayer->end_sector_l0 = 4112 scsi_3btoul(inlayer->end_sector_layer0); 4113 break; 4114 } 4115 case DVD_STRUCT_COPYRIGHT: { 4116 struct scsi_read_dvd_struct_data_copyright *copy_data; 4117 4118 copy_data = (struct scsi_read_dvd_struct_data_copyright *) 4119 databuf; 4120 4121 dvdstruct->cpst = copy_data->cps_type; 4122 dvdstruct->rmi = copy_data->region_info; 4123 dvdstruct->length = 0; 4124 4125 break; 4126 } 4127 default: 4128 /* 4129 * Tell the user what the overall length is, no matter 4130 * what we can actually fit in the data buffer. 4131 */ 4132 dvdstruct->length = length - ccb->csio.resid - 4133 sizeof(struct scsi_read_dvd_struct_data_header); 4134 4135 /* 4136 * But only actually copy out the smaller of what we read 4137 * in or what the structure can take. 4138 */ 4139 bcopy(databuf + sizeof(struct scsi_read_dvd_struct_data_header), 4140 dvdstruct->data, 4141 min(sizeof(dvdstruct->data), dvdstruct->length)); 4142 break; 4143 } 4144bailout: 4145 4146 if (databuf != NULL) 4147 free(databuf, M_DEVBUF); 4148 4149 xpt_release_ccb(ccb); 4150 4151 return(error); 4152} 4153 4154void 4155scsi_report_key(struct ccb_scsiio *csio, u_int32_t retries, 4156 void (*cbfcnp)(struct cam_periph *, union ccb *), 4157 u_int8_t tag_action, u_int32_t lba, u_int8_t agid, 4158 u_int8_t key_format, u_int8_t *data_ptr, u_int32_t dxfer_len, 4159 u_int8_t sense_len, u_int32_t timeout) 4160{ 4161 struct scsi_report_key *scsi_cmd; 4162 4163 scsi_cmd = (struct scsi_report_key *)&csio->cdb_io.cdb_bytes; 4164 bzero(scsi_cmd, sizeof(*scsi_cmd)); 4165 scsi_cmd->opcode = REPORT_KEY; 4166 scsi_ulto4b(lba, scsi_cmd->lba); 4167 scsi_ulto2b(dxfer_len, scsi_cmd->alloc_len); 4168 scsi_cmd->agid_keyformat = (agid << RK_KF_AGID_SHIFT) | 4169 (key_format & RK_KF_KEYFORMAT_MASK); 4170 4171 cam_fill_csio(csio, 4172 retries, 4173 cbfcnp, 4174 /*flags*/ (dxfer_len == 0) ? CAM_DIR_NONE : CAM_DIR_IN, 4175 tag_action, 4176 /*data_ptr*/ data_ptr, 4177 /*dxfer_len*/ dxfer_len, 4178 sense_len, 4179 sizeof(*scsi_cmd), 4180 timeout); 4181} 4182 4183void 4184scsi_send_key(struct ccb_scsiio *csio, u_int32_t retries, 4185 void (*cbfcnp)(struct cam_periph *, union ccb *), 4186 u_int8_t tag_action, u_int8_t agid, u_int8_t key_format, 4187 u_int8_t *data_ptr, u_int32_t dxfer_len, u_int8_t sense_len, 4188 u_int32_t timeout) 4189{ 4190 struct scsi_send_key *scsi_cmd; 4191 4192 scsi_cmd = (struct scsi_send_key *)&csio->cdb_io.cdb_bytes; 4193 bzero(scsi_cmd, sizeof(*scsi_cmd)); 4194 scsi_cmd->opcode = SEND_KEY; 4195 4196 scsi_ulto2b(dxfer_len, scsi_cmd->param_len); 4197 scsi_cmd->agid_keyformat = (agid << RK_KF_AGID_SHIFT) | 4198 (key_format & RK_KF_KEYFORMAT_MASK); 4199 4200 cam_fill_csio(csio, 4201 retries, 4202 cbfcnp, 4203 /*flags*/ CAM_DIR_OUT, 4204 tag_action, 4205 /*data_ptr*/ data_ptr, 4206 /*dxfer_len*/ dxfer_len, 4207 sense_len, 4208 sizeof(*scsi_cmd), 4209 timeout); 4210} 4211 4212 4213void 4214scsi_read_dvd_structure(struct ccb_scsiio *csio, u_int32_t retries, 4215 void (*cbfcnp)(struct cam_periph *, union ccb *), 4216 u_int8_t tag_action, u_int32_t address, 4217 u_int8_t layer_number, u_int8_t format, u_int8_t agid, 4218 u_int8_t *data_ptr, u_int32_t dxfer_len, 4219 u_int8_t sense_len, u_int32_t timeout) 4220{ 4221 struct scsi_read_dvd_structure *scsi_cmd; 4222 4223 scsi_cmd = (struct scsi_read_dvd_structure *)&csio->cdb_io.cdb_bytes; 4224 bzero(scsi_cmd, sizeof(*scsi_cmd)); 4225 scsi_cmd->opcode = READ_DVD_STRUCTURE; 4226 4227 scsi_ulto4b(address, scsi_cmd->address); 4228 scsi_cmd->layer_number = layer_number; 4229 scsi_cmd->format = format; 4230 scsi_ulto2b(dxfer_len, scsi_cmd->alloc_len); 4231 /* The AGID is the top two bits of this byte */ 4232 scsi_cmd->agid = agid << 6; 4233 4234 cam_fill_csio(csio, 4235 retries, 4236 cbfcnp, 4237 /*flags*/ CAM_DIR_IN, 4238 tag_action, 4239 /*data_ptr*/ data_ptr, 4240 /*dxfer_len*/ dxfer_len, 4241 sense_len, 4242 sizeof(*scsi_cmd), 4243 timeout); 4244} 4245