cd.c revision 1.319
1/* $NetBSD: cd.c,v 1.319 2014/04/18 06:23:32 martin Exp $ */ 2 3/*- 4 * Copyright (c) 1998, 2001, 2003, 2004, 2005, 2008 The NetBSD Foundation, 5 * Inc. All rights reserved. 6 * 7 * This code is derived from software contributed to The NetBSD Foundation 8 * by Charles M. Hannum. 9 * 10 * MMC framework implemented and contributed to the NetBSD Foundation by 11 * Reinoud Zandijk. 12 * 13 * Redistribution and use in source and binary forms, with or without 14 * modification, are permitted provided that the following conditions 15 * are met: 16 * 1. Redistributions of source code must retain the above copyright 17 * notice, this list of conditions and the following disclaimer. 18 * 2. Redistributions in binary form must reproduce the above copyright 19 * notice, this list of conditions and the following disclaimer in the 20 * documentation and/or other materials provided with the distribution. 21 * 22 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 23 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 24 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 25 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 26 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 27 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 28 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 29 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 30 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 31 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 32 * POSSIBILITY OF SUCH DAMAGE. 33 */ 34 35/* 36 * Originally written by Julian Elischer (julian@tfs.com) 37 * for TRW Financial Systems for use under the MACH(2.5) operating system. 38 * 39 * TRW Financial Systems, in accordance with their agreement with Carnegie 40 * Mellon University, makes this software available to CMU to distribute 41 * or use in any manner that they see fit as long as this message is kept with 42 * the software. For this reason TFS also grants any other persons or 43 * organisations permission to use or modify this software. 44 * 45 * TFS supplies this software to be publicly redistributed 46 * on the understanding that TFS is not responsible for the correct 47 * functioning of this software in any circumstances. 48 * 49 * Ported to run under 386BSD by Julian Elischer (julian@tfs.com) Sept 1992 50 */ 51 52#include <sys/cdefs.h> 53__KERNEL_RCSID(0, "$NetBSD: cd.c,v 1.319 2014/04/18 06:23:32 martin Exp $"); 54 55#include <sys/param.h> 56#include <sys/systm.h> 57#include <sys/kernel.h> 58#include <sys/file.h> 59#include <sys/stat.h> 60#include <sys/ioctl.h> 61#include <sys/buf.h> 62#include <sys/bufq.h> 63#include <sys/uio.h> 64#include <sys/malloc.h> 65#include <sys/errno.h> 66#include <sys/device.h> 67#include <sys/disklabel.h> 68#include <sys/disk.h> 69#include <sys/cdio.h> 70#include <sys/dvdio.h> 71#include <sys/scsiio.h> 72#include <sys/proc.h> 73#include <sys/conf.h> 74#include <sys/vnode.h> 75#include <sys/rnd.h> 76 77#include <dev/scsipi/scsi_spc.h> 78#include <dev/scsipi/scsipi_all.h> 79#include <dev/scsipi/scsipi_cd.h> 80#include <dev/scsipi/scsipi_disk.h> /* rw_big and start_stop come */ 81#include <dev/scsipi/scsi_all.h> 82 /* from there */ 83#include <dev/scsipi/scsi_disk.h> /* rw comes from there */ 84#include <dev/scsipi/scsipiconf.h> 85#include <dev/scsipi/scsipi_base.h> 86#include <dev/scsipi/cdvar.h> 87 88#include <prop/proplib.h> 89 90#define CDUNIT(z) DISKUNIT(z) 91#define CDPART(z) DISKPART(z) 92#define CDMINOR(unit, part) DISKMINOR(unit, part) 93#define MAKECDDEV(maj, unit, part) MAKEDISKDEV(maj, unit, part) 94 95#define MAXTRACK 99 96#define CD_BLOCK_OFFSET 150 97#define CD_FRAMES 75 98#define CD_SECS 60 99 100#define CD_TOC_FORM 0 /* formatted TOC, exposed to userland */ 101#define CD_TOC_MSINFO 1 /* multi-session info */ 102#define CD_TOC_RAW 2 /* raw TOC as on disc, unprocessed */ 103#define CD_TOC_PMA 3 /* PMA, used as intermediate (rare use) */ 104#define CD_TOC_ATIP 4 /* pressed space of recordable */ 105#define CD_TOC_CDTEXT 5 /* special CD-TEXT, rarely used */ 106 107#define P5LEN 0x32 108#define MS5LEN (P5LEN + 8 + 2) 109 110struct cd_formatted_toc { 111 struct ioc_toc_header header; 112 struct cd_toc_entry entries[MAXTRACK+1]; /* One extra for the */ 113 /* leadout */ 114}; 115 116struct cdbounce { 117 struct buf *obp; /* original buf */ 118 int doff; /* byte offset in orig. buf */ 119 int soff; /* byte offset in bounce buf */ 120 int resid; /* residual i/o in orig. buf */ 121 int bcount; /* actual obp bytes in bounce */ 122}; 123 124static void cdstart(struct scsipi_periph *); 125static void cdrestart(void *); 126static void cdminphys(struct buf *); 127static void cdgetdefaultlabel(struct cd_softc *, struct cd_formatted_toc *, 128 struct disklabel *); 129static void cdgetdisklabel(struct cd_softc *); 130static void cddone(struct scsipi_xfer *, int); 131static void cdbounce(struct buf *); 132static int cd_interpret_sense(struct scsipi_xfer *); 133static u_long cd_size(struct cd_softc *, int); 134static int cd_play(struct cd_softc *, int, int); 135static int cd_play_tracks(struct cd_softc *, struct cd_formatted_toc *, 136 int, int, int, int); 137static int cd_play_msf(struct cd_softc *, int, int, int, int, int, int); 138static int cd_pause(struct cd_softc *, int); 139static int cd_reset(struct cd_softc *); 140static int cd_read_subchannel(struct cd_softc *, int, int, int, 141 struct cd_sub_channel_info *, int, int); 142static int cd_read_toc(struct cd_softc *, int, int, int, 143 struct cd_formatted_toc *, int, int, int); 144static int cd_get_parms(struct cd_softc *, int); 145static int cd_load_toc(struct cd_softc *, int, struct cd_formatted_toc *, int); 146static int cdreadmsaddr(struct cd_softc *, struct cd_formatted_toc *,int *); 147static int cdcachesync(struct scsipi_periph *periph, int flags); 148 149static int dvd_auth(struct cd_softc *, dvd_authinfo *); 150static int dvd_read_physical(struct cd_softc *, dvd_struct *); 151static int dvd_read_copyright(struct cd_softc *, dvd_struct *); 152static int dvd_read_disckey(struct cd_softc *, dvd_struct *); 153static int dvd_read_bca(struct cd_softc *, dvd_struct *); 154static int dvd_read_manufact(struct cd_softc *, dvd_struct *); 155static int dvd_read_struct(struct cd_softc *, dvd_struct *); 156 157static int cd_mode_sense(struct cd_softc *, u_int8_t, void *, size_t, int, 158 int, int *); 159static int cd_mode_select(struct cd_softc *, u_int8_t, void *, size_t, 160 int, int); 161static int cd_setchan(struct cd_softc *, int, int, int, int, int); 162static int cd_getvol(struct cd_softc *, struct ioc_vol *, int); 163static int cd_setvol(struct cd_softc *, const struct ioc_vol *, int); 164static int cd_set_pa_immed(struct cd_softc *, int); 165static int cd_load_unload(struct cd_softc *, struct ioc_load_unload *); 166static int cd_setblksize(struct cd_softc *); 167 168static int cdmatch(device_t, cfdata_t, void *); 169static void cdattach(device_t, device_t, void *); 170static int cddetach(device_t, int); 171 172static int mmc_getdiscinfo(struct scsipi_periph *, struct mmc_discinfo *); 173static int mmc_gettrackinfo(struct scsipi_periph *, struct mmc_trackinfo *); 174static int mmc_do_op(struct scsipi_periph *, struct mmc_op *); 175static int mmc_setup_writeparams(struct scsipi_periph *, struct mmc_writeparams *); 176 177static void cd_set_geometry(struct cd_softc *); 178 179CFATTACH_DECL3_NEW(cd, sizeof(struct cd_softc), cdmatch, cdattach, cddetach, 180 NULL, NULL, NULL, DVF_DETACH_SHUTDOWN); 181 182extern struct cfdriver cd_cd; 183 184static const struct scsipi_inquiry_pattern cd_patterns[] = { 185 {T_CDROM, T_REMOV, 186 "", "", ""}, 187 {T_WORM, T_REMOV, 188 "", "", ""}, 189#if 0 190 {T_CDROM, T_REMOV, /* more luns */ 191 "PIONEER ", "CD-ROM DRM-600 ", ""}, 192#endif 193 {T_DIRECT, T_REMOV, 194 "NEC CD-ROM DRIVE:260", "", ""}, 195}; 196 197static dev_type_open(cdopen); 198static dev_type_close(cdclose); 199static dev_type_read(cdread); 200static dev_type_write(cdwrite); 201static dev_type_ioctl(cdioctl); 202static dev_type_strategy(cdstrategy); 203static dev_type_dump(cddump); 204static dev_type_size(cdsize); 205 206const struct bdevsw cd_bdevsw = { 207 .d_open = cdopen, 208 .d_close = cdclose, 209 .d_strategy = cdstrategy, 210 .d_ioctl = cdioctl, 211 .d_dump = cddump, 212 .d_psize = cdsize, 213 .d_flag = D_DISK 214}; 215 216const struct cdevsw cd_cdevsw = { 217 .d_open = cdopen, 218 .d_close = cdclose, 219 .d_read = cdread, 220 .d_write = cdwrite, 221 .d_ioctl = cdioctl, 222 .d_stop = nostop, 223 .d_tty = notty, 224 .d_poll = nopoll, 225 .d_mmap = nommap, 226 .d_kqfilter = nokqfilter, 227 .d_flag = D_DISK 228}; 229 230static struct dkdriver cddkdriver = { cdstrategy, NULL }; 231 232static const struct scsipi_periphsw cd_switch = { 233 cd_interpret_sense, /* use our error handler first */ 234 cdstart, /* we have a queue, which is started by this */ 235 NULL, /* we do not have an async handler */ 236 cddone, /* deal with stats at interrupt time */ 237}; 238 239/* 240 * The routine called by the low level scsi routine when it discovers 241 * A device suitable for this driver 242 */ 243static int 244cdmatch(device_t parent, cfdata_t match, void *aux) 245{ 246 struct scsipibus_attach_args *sa = aux; 247 int priority; 248 249 (void)scsipi_inqmatch(&sa->sa_inqbuf, 250 cd_patterns, sizeof(cd_patterns) / sizeof(cd_patterns[0]), 251 sizeof(cd_patterns[0]), &priority); 252 253 return (priority); 254} 255 256static void 257cdattach(device_t parent, device_t self, void *aux) 258{ 259 struct cd_softc *cd = device_private(self); 260 struct scsipibus_attach_args *sa = aux; 261 struct scsipi_periph *periph = sa->sa_periph; 262 263 SC_DEBUG(periph, SCSIPI_DB2, ("cdattach: ")); 264 265 cd->sc_dev = self; 266 267 mutex_init(&cd->sc_lock, MUTEX_DEFAULT, IPL_NONE); 268 269 if (SCSIPI_BUSTYPE_TYPE(scsipi_periph_bustype(sa->sa_periph)) == 270 SCSIPI_BUSTYPE_SCSI && periph->periph_version == 0) 271 cd->flags |= CDF_ANCIENT; 272 273 bufq_alloc(&cd->buf_queue, "disksort", BUFQ_SORT_RAWBLOCK); 274 275 callout_init(&cd->sc_callout, 0); 276 277 /* 278 * Store information needed to contact our base driver 279 */ 280 cd->sc_periph = periph; 281 282 periph->periph_dev = cd->sc_dev; 283 periph->periph_switch = &cd_switch; 284 285 /* 286 * Increase our openings to the maximum-per-periph 287 * supported by the adapter. This will either be 288 * clamped down or grown by the adapter if necessary. 289 */ 290 periph->periph_openings = 291 SCSIPI_CHAN_MAX_PERIPH(periph->periph_channel); 292 periph->periph_flags |= PERIPH_GROW_OPENINGS; 293 294 /* 295 * Initialize and attach the disk structure. 296 */ 297 disk_init(&cd->sc_dk, device_xname(cd->sc_dev), &cddkdriver); 298 disk_attach(&cd->sc_dk); 299 300 aprint_normal("\n"); 301 aprint_naive("\n"); 302 303 rnd_attach_source(&cd->rnd_source, device_xname(cd->sc_dev), 304 RND_TYPE_DISK, 0); 305 306 if (!pmf_device_register(self, NULL, NULL)) 307 aprint_error_dev(self, "couldn't establish power handler\n"); 308} 309 310static int 311cddetach(device_t self, int flags) 312{ 313 struct cd_softc *cd = device_private(self); 314 int s, bmaj, cmaj, i, mn; 315 316 /* locate the major number */ 317 bmaj = bdevsw_lookup_major(&cd_bdevsw); 318 cmaj = cdevsw_lookup_major(&cd_cdevsw); 319 /* Nuke the vnodes for any open instances */ 320 for (i = 0; i < MAXPARTITIONS; i++) { 321 mn = CDMINOR(device_unit(self), i); 322 vdevgone(bmaj, mn, mn, VBLK); 323 vdevgone(cmaj, mn, mn, VCHR); 324 } 325 326 /* kill any pending restart */ 327 callout_stop(&cd->sc_callout); 328 329 s = splbio(); 330 331 /* Kill off any queued buffers. */ 332 bufq_drain(cd->buf_queue); 333 334 bufq_free(cd->buf_queue); 335 336 /* Kill off any pending commands. */ 337 scsipi_kill_pending(cd->sc_periph); 338 339 splx(s); 340 341 mutex_destroy(&cd->sc_lock); 342 343 /* Detach from the disk list. */ 344 disk_detach(&cd->sc_dk); 345 disk_destroy(&cd->sc_dk); 346 347 /* Unhook the entropy source. */ 348 rnd_detach_source(&cd->rnd_source); 349 350 return (0); 351} 352 353/* 354 * open the device. Make sure the partition info is a up-to-date as can be. 355 */ 356static int 357cdopen(dev_t dev, int flag, int fmt, struct lwp *l) 358{ 359 struct cd_softc *cd; 360 struct scsipi_periph *periph; 361 struct scsipi_adapter *adapt; 362 int part; 363 int error; 364 int rawpart; 365 366 cd = device_lookup_private(&cd_cd, CDUNIT(dev)); 367 if (cd == NULL) 368 return (ENXIO); 369 370 periph = cd->sc_periph; 371 adapt = periph->periph_channel->chan_adapter; 372 part = CDPART(dev); 373 374 SC_DEBUG(periph, SCSIPI_DB1, 375 ("cdopen: dev=0x%"PRIu64" (unit %"PRIu32" (of %d), partition %"PRId32")\n",dev, 376 CDUNIT(dev), cd_cd.cd_ndevs, CDPART(dev))); 377 378 /* 379 * If this is the first open of this device, add a reference 380 * to the adapter. 381 */ 382 if (cd->sc_dk.dk_openmask == 0 && 383 (error = scsipi_adapter_addref(adapt)) != 0) 384 return (error); 385 386 mutex_enter(&cd->sc_lock); 387 388 rawpart = (part == RAW_PART && fmt == S_IFCHR); 389 if ((periph->periph_flags & PERIPH_OPEN) != 0) { 390 /* 391 * If any partition is open, but the disk has been invalidated, 392 * disallow further opens. 393 */ 394 if ((periph->periph_flags & PERIPH_MEDIA_LOADED) == 0 && 395 !rawpart) { 396 error = EIO; 397 goto bad3; 398 } 399 } else { 400 /* Check that it is still responding and ok. */ 401 error = scsipi_test_unit_ready(periph, 402 XS_CTL_IGNORE_ILLEGAL_REQUEST | XS_CTL_IGNORE_MEDIA_CHANGE | 403 XS_CTL_SILENT); 404 405 /* 406 * Start the pack spinning if necessary. Always allow the 407 * raw parition to be opened, for raw IOCTLs. Data transfers 408 * will check for SDEV_MEDIA_LOADED. 409 */ 410 if (error == EIO) { 411 int error2; 412 int silent; 413 414 if (rawpart) 415 silent = XS_CTL_SILENT; 416 else 417 silent = 0; 418 419 error2 = scsipi_start(periph, SSS_START, silent); 420 switch (error2) { 421 case 0: 422 error = 0; 423 break; 424 case EIO: 425 case EINVAL: 426 break; 427 default: 428 error = error2; 429 break; 430 } 431 } 432 if (error) { 433 if (rawpart) 434 goto out; 435 goto bad3; 436 } 437 438 periph->periph_flags |= PERIPH_OPEN; 439 440 /* Lock the pack in. */ 441 error = scsipi_prevent(periph, SPAMR_PREVENT_DT, 442 XS_CTL_IGNORE_ILLEGAL_REQUEST | XS_CTL_IGNORE_MEDIA_CHANGE); 443 SC_DEBUG(periph, SCSIPI_DB1, 444 ("cdopen: scsipi_prevent, error=%d\n", error)); 445 if (error) { 446 if (rawpart) 447 goto out; 448 goto bad; 449 } 450 451 if ((periph->periph_flags & PERIPH_MEDIA_LOADED) == 0) { 452 /* Load the physical device parameters. */ 453 if (cd_get_parms(cd, 0) != 0) { 454 if (rawpart) 455 goto out; 456 error = ENXIO; 457 goto bad; 458 } 459 periph->periph_flags |= PERIPH_MEDIA_LOADED; 460 SC_DEBUG(periph, SCSIPI_DB3, ("Params loaded ")); 461 462 /* Fabricate a disk label. */ 463 cdgetdisklabel(cd); 464 SC_DEBUG(periph, SCSIPI_DB3, ("Disklabel fabricated ")); 465 466 cd_set_geometry(cd); 467 } 468 } 469 470 /* Check that the partition exists. */ 471 if (part != RAW_PART && 472 (part >= cd->sc_dk.dk_label->d_npartitions || 473 cd->sc_dk.dk_label->d_partitions[part].p_fstype == FS_UNUSED)) { 474 error = ENXIO; 475 goto bad; 476 } 477 478out: /* Insure only one open at a time. */ 479 switch (fmt) { 480 case S_IFCHR: 481 cd->sc_dk.dk_copenmask |= (1 << part); 482 break; 483 case S_IFBLK: 484 cd->sc_dk.dk_bopenmask |= (1 << part); 485 break; 486 } 487 cd->sc_dk.dk_openmask = 488 cd->sc_dk.dk_copenmask | cd->sc_dk.dk_bopenmask; 489 490 SC_DEBUG(periph, SCSIPI_DB3, ("open complete\n")); 491 mutex_exit(&cd->sc_lock); 492 return (0); 493 494bad: 495 if (cd->sc_dk.dk_openmask == 0) { 496 scsipi_prevent(periph, SPAMR_ALLOW, 497 XS_CTL_IGNORE_ILLEGAL_REQUEST | XS_CTL_IGNORE_MEDIA_CHANGE); 498 periph->periph_flags &= ~PERIPH_OPEN; 499 } 500 501bad3: 502 mutex_exit(&cd->sc_lock); 503 if (cd->sc_dk.dk_openmask == 0) 504 scsipi_adapter_delref(adapt); 505 return (error); 506} 507 508/* 509 * close the device.. only called if we are the LAST 510 * occurence of an open device 511 */ 512static int 513cdclose(dev_t dev, int flag, int fmt, struct lwp *l) 514{ 515 struct cd_softc *cd = device_lookup_private(&cd_cd, CDUNIT(dev)); 516 struct scsipi_periph *periph = cd->sc_periph; 517 struct scsipi_adapter *adapt = periph->periph_channel->chan_adapter; 518 int part = CDPART(dev); 519 int silent = 0; 520 521 if (part == RAW_PART && ((cd->sc_dk.dk_label->d_npartitions == 0) || 522 (part < cd->sc_dk.dk_label->d_npartitions && 523 cd->sc_dk.dk_label->d_partitions[part].p_fstype == FS_UNUSED))) 524 silent = XS_CTL_SILENT; 525 526 mutex_enter(&cd->sc_lock); 527 528 switch (fmt) { 529 case S_IFCHR: 530 cd->sc_dk.dk_copenmask &= ~(1 << part); 531 break; 532 case S_IFBLK: 533 cd->sc_dk.dk_bopenmask &= ~(1 << part); 534 break; 535 } 536 cd->sc_dk.dk_openmask = 537 cd->sc_dk.dk_copenmask | cd->sc_dk.dk_bopenmask; 538 539 if (cd->sc_dk.dk_openmask == 0) { 540 /* synchronise caches on last close */ 541 cdcachesync(periph, silent); 542 543 /* drain outstanding calls */ 544 scsipi_wait_drain(periph); 545 546 scsipi_prevent(periph, SPAMR_ALLOW, 547 XS_CTL_IGNORE_ILLEGAL_REQUEST | XS_CTL_IGNORE_MEDIA_CHANGE | 548 XS_CTL_IGNORE_NOT_READY | silent); 549 periph->periph_flags &= ~PERIPH_OPEN; 550 551 scsipi_wait_drain(periph); 552 553 scsipi_adapter_delref(adapt); 554 } 555 556 mutex_exit(&cd->sc_lock); 557 return (0); 558} 559 560/* 561 * Actually translate the requested transfer into one the physical driver can 562 * understand. The transfer is described by a buf and will include only one 563 * physical transfer. 564 */ 565static void 566cdstrategy(struct buf *bp) 567{ 568 struct cd_softc *cd = device_lookup_private(&cd_cd,CDUNIT(bp->b_dev)); 569 struct disklabel *lp; 570 struct scsipi_periph *periph = cd->sc_periph; 571 daddr_t blkno; 572 int s; 573 574 SC_DEBUG(cd->sc_periph, SCSIPI_DB2, ("cdstrategy ")); 575 SC_DEBUG(cd->sc_periph, SCSIPI_DB1, 576 ("%d bytes @ blk %" PRId64 "\n", bp->b_bcount, bp->b_blkno)); 577 /* 578 * If the device has been made invalid, error out 579 * maybe the media changed 580 */ 581 if ((periph->periph_flags & PERIPH_MEDIA_LOADED) == 0) { 582 if (periph->periph_flags & PERIPH_OPEN) 583 bp->b_error = EIO; 584 else 585 bp->b_error = ENODEV; 586 goto done; 587 } 588 589 lp = cd->sc_dk.dk_label; 590 591 /* 592 * The transfer must be a whole number of blocks, offset must not 593 * be negative. 594 */ 595 if ((bp->b_bcount % lp->d_secsize) != 0 || 596 bp->b_blkno < 0 ) { 597 bp->b_error = EINVAL; 598 goto done; 599 } 600 /* 601 * If it's a null transfer, return immediately 602 */ 603 if (bp->b_bcount == 0) 604 goto done; 605 606 /* 607 * Do bounds checking, adjust transfer. if error, process. 608 * If end of partition, just return. 609 */ 610 if (CDPART(bp->b_dev) == RAW_PART) { 611 if (bounds_check_with_mediasize(bp, DEV_BSIZE, 612 cd->params.disksize512) <= 0) 613 goto done; 614 } else { 615 if (bounds_check_with_label(&cd->sc_dk, bp, 616 (cd->flags & (CDF_WLABEL|CDF_LABELLING)) != 0) <= 0) 617 goto done; 618 } 619 620 /* 621 * Now convert the block number to absolute and put it in 622 * terms of the device's logical block size. 623 */ 624 blkno = bp->b_blkno / (lp->d_secsize / DEV_BSIZE); 625 if (CDPART(bp->b_dev) != RAW_PART) 626 blkno += lp->d_partitions[CDPART(bp->b_dev)].p_offset; 627 628 bp->b_rawblkno = blkno; 629 630 /* 631 * If the disklabel sector size does not match the device 632 * sector size we may need to do some extra work. 633 */ 634 if (lp->d_secsize != cd->params.blksize) { 635 636 /* 637 * If the xfer is not a multiple of the device block size 638 * or it is not block aligned, we need to bounce it. 639 */ 640 if ((bp->b_bcount % cd->params.blksize) != 0 || 641 ((blkno * lp->d_secsize) % cd->params.blksize) != 0) { 642 struct cdbounce *bounce; 643 struct buf *nbp; 644 long count; 645 646 if ((bp->b_flags & B_READ) == 0) { 647 648 /* XXXX We don't support bouncing writes. */ 649 bp->b_error = EACCES; 650 goto done; 651 } 652 653 bounce = malloc(sizeof(*bounce), M_DEVBUF, M_NOWAIT); 654 if (!bounce) { 655 /* No memory -- fail the iop. */ 656 bp->b_error = ENOMEM; 657 goto done; 658 } 659 660 bounce->obp = bp; 661 bounce->resid = bp->b_bcount; 662 bounce->doff = 0; 663 count = ((blkno * lp->d_secsize) % cd->params.blksize); 664 bounce->soff = count; 665 count += bp->b_bcount; 666 count = roundup(count, cd->params.blksize); 667 bounce->bcount = bounce->resid; 668 if (count > MAXPHYS) { 669 bounce->bcount = MAXPHYS - bounce->soff; 670 count = MAXPHYS; 671 } 672 673 blkno = ((blkno * lp->d_secsize) / cd->params.blksize); 674 nbp = getiobuf(NULL, false); 675 if (!nbp) { 676 /* No memory -- fail the iop. */ 677 free(bounce, M_DEVBUF); 678 bp->b_error = ENOMEM; 679 goto done; 680 } 681 nbp->b_data = malloc(count, M_DEVBUF, M_NOWAIT); 682 if (!nbp->b_data) { 683 /* No memory -- fail the iop. */ 684 free(bounce, M_DEVBUF); 685 putiobuf(nbp); 686 bp->b_error = ENOMEM; 687 goto done; 688 } 689 690 /* Set up the IOP to the bounce buffer. */ 691 nbp->b_error = 0; 692 nbp->b_proc = bp->b_proc; 693 nbp->b_bcount = count; 694 nbp->b_bufsize = count; 695 nbp->b_rawblkno = blkno; 696 nbp->b_flags = bp->b_flags | B_READ; 697 nbp->b_oflags = bp->b_oflags; 698 nbp->b_cflags = bp->b_cflags; 699 nbp->b_iodone = cdbounce; 700 701 /* store bounce state in b_private and use new buf */ 702 nbp->b_private = bounce; 703 704 BIO_COPYPRIO(nbp, bp); 705 706 bp = nbp; 707 708 } else { 709 /* Xfer is aligned -- just adjust the start block */ 710 bp->b_rawblkno = (blkno * lp->d_secsize) / 711 cd->params.blksize; 712 } 713 } 714 s = splbio(); 715 716 /* 717 * Place it in the queue of disk activities for this disk. 718 * 719 * XXX Only do disksort() if the current operating mode does not 720 * XXX include tagged queueing. 721 */ 722 bufq_put(cd->buf_queue, bp); 723 724 /* 725 * Tell the device to get going on the transfer if it's 726 * not doing anything, otherwise just wait for completion 727 */ 728 cdstart(cd->sc_periph); 729 730 splx(s); 731 return; 732 733done: 734 /* 735 * Correctly set the buf to indicate a completed xfer 736 */ 737 bp->b_resid = bp->b_bcount; 738 biodone(bp); 739} 740 741/* 742 * cdstart looks to see if there is a buf waiting for the device 743 * and that the device is not already busy. If both are true, 744 * It deques the buf and creates a scsi command to perform the 745 * transfer in the buf. The transfer request will call scsipi_done 746 * on completion, which will in turn call this routine again 747 * so that the next queued transfer is performed. 748 * The bufs are queued by the strategy routine (cdstrategy) 749 * 750 * This routine is also called after other non-queued requests 751 * have been made of the scsi driver, to ensure that the queue 752 * continues to be drained. 753 * 754 * must be called at the correct (highish) spl level 755 * cdstart() is called at splbio from cdstrategy, cdrestart and scsipi_done 756 */ 757static void 758cdstart(struct scsipi_periph *periph) 759{ 760 struct cd_softc *cd = device_private(periph->periph_dev); 761 struct buf *bp = 0; 762 struct scsipi_rw_10 cmd_big; 763 struct scsi_rw_6 cmd_small; 764 struct scsipi_generic *cmdp; 765 struct scsipi_xfer *xs; 766 int flags, nblks, cmdlen, error __diagused; 767 768 SC_DEBUG(periph, SCSIPI_DB2, ("cdstart ")); 769 /* 770 * Check if the device has room for another command 771 */ 772 while (periph->periph_active < periph->periph_openings) { 773 /* 774 * there is excess capacity, but a special waits 775 * It'll need the adapter as soon as we clear out of the 776 * way and let it run (user level wait). 777 */ 778 if (periph->periph_flags & PERIPH_WAITING) { 779 periph->periph_flags &= ~PERIPH_WAITING; 780 wakeup((void *)periph); 781 return; 782 } 783 784 /* 785 * If the device has become invalid, abort all the 786 * reads and writes until all files have been closed and 787 * re-opened 788 */ 789 if (__predict_false( 790 (periph->periph_flags & PERIPH_MEDIA_LOADED) == 0)) { 791 if ((bp = bufq_get(cd->buf_queue)) != NULL) { 792 bp->b_error = EIO; 793 bp->b_resid = bp->b_bcount; 794 biodone(bp); 795 continue; 796 } else { 797 return; 798 } 799 } 800 801 /* 802 * See if there is a buf with work for us to do.. 803 */ 804 if ((bp = bufq_peek(cd->buf_queue)) == NULL) 805 return; 806 807 /* 808 * We have a buf, now we should make a command. 809 */ 810 811 nblks = howmany(bp->b_bcount, cd->params.blksize); 812 813 /* 814 * Fill out the scsi command. If the transfer will 815 * fit in a "small" cdb, use it. 816 */ 817 if (((bp->b_rawblkno & 0x1fffff) == bp->b_rawblkno) && 818 ((nblks & 0xff) == nblks) && 819 !(periph->periph_quirks & PQUIRK_ONLYBIG)) { 820 /* 821 * We can fit in a small cdb. 822 */ 823 memset(&cmd_small, 0, sizeof(cmd_small)); 824 cmd_small.opcode = (bp->b_flags & B_READ) ? 825 SCSI_READ_6_COMMAND : SCSI_WRITE_6_COMMAND; 826 _lto3b(bp->b_rawblkno, cmd_small.addr); 827 cmd_small.length = nblks & 0xff; 828 cmdlen = sizeof(cmd_small); 829 cmdp = (struct scsipi_generic *)&cmd_small; 830 } else { 831 /* 832 * Need a large cdb. 833 */ 834 memset(&cmd_big, 0, sizeof(cmd_big)); 835 cmd_big.opcode = (bp->b_flags & B_READ) ? 836 READ_10 : WRITE_10; 837 _lto4b(bp->b_rawblkno, cmd_big.addr); 838 _lto2b(nblks, cmd_big.length); 839 cmdlen = sizeof(cmd_big); 840 cmdp = (struct scsipi_generic *)&cmd_big; 841 } 842 843 /* Instrumentation. */ 844 disk_busy(&cd->sc_dk); 845 846 /* 847 * Figure out what flags to use. 848 */ 849 flags = XS_CTL_NOSLEEP|XS_CTL_ASYNC|XS_CTL_SIMPLE_TAG; 850 if (bp->b_flags & B_READ) 851 flags |= XS_CTL_DATA_IN; 852 else 853 flags |= XS_CTL_DATA_OUT; 854 855 /* 856 * Call the routine that chats with the adapter. 857 * Note: we cannot sleep as we may be an interrupt 858 */ 859 xs = scsipi_make_xs(periph, cmdp, cmdlen, 860 (u_char *)bp->b_data, bp->b_bcount, 861 CDRETRIES, 30000, bp, flags); 862 if (__predict_false(xs == NULL)) { 863 /* 864 * out of memory. Keep this buffer in the queue, and 865 * retry later. 866 */ 867 callout_reset(&cd->sc_callout, hz / 2, cdrestart, 868 periph); 869 return; 870 } 871 /* 872 * need to dequeue the buffer before queuing the command, 873 * because cdstart may be called recursively from the 874 * HBA driver 875 */ 876#ifdef DIAGNOSTIC 877 if (bufq_get(cd->buf_queue) != bp) 878 panic("cdstart(): dequeued wrong buf"); 879#else 880 bufq_get(cd->buf_queue); 881#endif 882 error = scsipi_execute_xs(xs); 883 /* with a scsipi_xfer preallocated, scsipi_command can't fail */ 884 KASSERT(error == 0); 885 } 886} 887 888static void 889cdrestart(void *v) 890{ 891 int s = splbio(); 892 cdstart((struct scsipi_periph *)v); 893 splx(s); 894} 895 896static void 897cddone(struct scsipi_xfer *xs, int error) 898{ 899 struct cd_softc *cd = device_private(xs->xs_periph->periph_dev); 900 struct buf *bp = xs->bp; 901 902 if (bp) { 903 /* note, bp->b_resid is NOT initialised */ 904 bp->b_error = error; 905 bp->b_resid = xs->resid; 906 if (error) { 907 /* on a read/write error bp->b_resid is zero, so fix */ 908 bp->b_resid = bp->b_bcount; 909 } 910 911 disk_unbusy(&cd->sc_dk, bp->b_bcount - bp->b_resid, 912 (bp->b_flags & B_READ)); 913 rnd_add_uint32(&cd->rnd_source, bp->b_rawblkno); 914 915 biodone(bp); 916 } 917} 918 919static void 920cdbounce(struct buf *bp) 921{ 922 struct cdbounce *bounce = (struct cdbounce *)bp->b_private; 923 struct buf *obp = bounce->obp; 924 struct cd_softc *cd = 925 device_lookup_private(&cd_cd, CDUNIT(obp->b_dev)); 926 struct disklabel *lp = cd->sc_dk.dk_label; 927 928 if (bp->b_error != 0) { 929 /* EEK propagate the error and free the memory */ 930 goto done; 931 } 932 933 KASSERT(obp->b_flags & B_READ); 934 935 /* copy bounce buffer to final destination */ 936 memcpy((char *)obp->b_data + bounce->doff, 937 (char *)bp->b_data + bounce->soff, bounce->bcount); 938 939 /* check if we need more I/O, i.e. bounce put us over MAXPHYS */ 940 KASSERT(bounce->resid >= bounce->bcount); 941 bounce->resid -= bounce->bcount; 942 if (bounce->resid > 0) { 943 struct buf *nbp; 944 daddr_t blkno; 945 long count; 946 int s; 947 948 blkno = obp->b_rawblkno + 949 ((obp->b_bcount - bounce->resid) / lp->d_secsize); 950 count = ((blkno * lp->d_secsize) % cd->params.blksize); 951 blkno = (blkno * lp->d_secsize) / cd->params.blksize; 952 bounce->soff = count; 953 bounce->doff += bounce->bcount; 954 count += bounce->resid; 955 count = roundup(count, cd->params.blksize); 956 bounce->bcount = bounce->resid; 957 if (count > MAXPHYS) { 958 bounce->bcount = MAXPHYS - bounce->soff; 959 count = MAXPHYS; 960 } 961 962 nbp = getiobuf(NULL, false); 963 if (!nbp) { 964 /* No memory -- fail the iop. */ 965 bp->b_error = ENOMEM; 966 goto done; 967 } 968 969 /* Set up the IOP to the bounce buffer. */ 970 nbp->b_error = 0; 971 nbp->b_proc = obp->b_proc; 972 nbp->b_bcount = count; 973 nbp->b_bufsize = count; 974 nbp->b_data = bp->b_data; 975 nbp->b_rawblkno = blkno; 976 nbp->b_flags = obp->b_flags | B_READ; 977 nbp->b_oflags = obp->b_oflags; 978 nbp->b_cflags = obp->b_cflags; 979 nbp->b_iodone = cdbounce; 980 981 /* store bounce state in b_private and use new buf */ 982 nbp->b_private = bounce; 983 984 BIO_COPYPRIO(nbp, obp); 985 986 bp->b_data = NULL; 987 putiobuf(bp); 988 989 /* enqueue the request and return */ 990 s = splbio(); 991 bufq_put(cd->buf_queue, nbp); 992 cdstart(cd->sc_periph); 993 splx(s); 994 995 return; 996 } 997 998done: 999 obp->b_error = bp->b_error; 1000 obp->b_resid = bp->b_resid; 1001 free(bp->b_data, M_DEVBUF); 1002 free(bounce, M_DEVBUF); 1003 bp->b_data = NULL; 1004 putiobuf(bp); 1005 biodone(obp); 1006} 1007 1008static int 1009cd_interpret_sense(struct scsipi_xfer *xs) 1010{ 1011 struct scsipi_periph *periph = xs->xs_periph; 1012 struct scsi_sense_data *sense = &xs->sense.scsi_sense; 1013 int retval = EJUSTRETURN; 1014 1015 /* 1016 * If it isn't a extended or extended/deferred error, let 1017 * the generic code handle it. 1018 */ 1019 if (SSD_RCODE(sense->response_code) != SSD_RCODE_CURRENT && 1020 SSD_RCODE(sense->response_code) != SSD_RCODE_DEFERRED) 1021 return (retval); 1022 1023 /* 1024 * If we got a "Unit not ready" (SKEY_NOT_READY) and "Logical Unit 1025 * Is In The Process of Becoming Ready" (Sense code 0x04,0x01), then 1026 * wait a bit for the drive to spin up 1027 */ 1028 1029 if ((SSD_SENSE_KEY(sense->flags) == SKEY_NOT_READY) && 1030 (sense->asc == 0x04) && (sense->ascq == 0x01)) { 1031 /* 1032 * Sleep for 5 seconds to wait for the drive to spin up 1033 */ 1034 1035 SC_DEBUG(periph, SCSIPI_DB1, ("Waiting 5 sec for CD " 1036 "spinup\n")); 1037 if (!callout_pending(&periph->periph_callout)) 1038 scsipi_periph_freeze(periph, 1); 1039 callout_reset(&periph->periph_callout, 1040 5 * hz, scsipi_periph_timed_thaw, periph); 1041 retval = ERESTART; 1042 } 1043 1044 /* 1045 * If we got a "Unit not ready" (SKEY_NOT_READY) and "Logical Unit Not 1046 * Ready, Operation In Progress" (Sense code 0x04, 0x07), 1047 * then wait for the specified time 1048 */ 1049 1050 if ((SSD_SENSE_KEY(sense->flags) == SKEY_NOT_READY) && 1051 (sense->asc == 0x04) && (sense->ascq == 0x07)) { 1052 /* 1053 * we could listen to the delay; but it looks like the skey 1054 * data is not always returned. 1055 */ 1056 /* cd_delay = _2btol(sense->sks.sks_bytes); */ 1057 1058 /* wait for a half second and get going again */ 1059 if (!callout_pending(&periph->periph_callout)) 1060 scsipi_periph_freeze(periph, 1); 1061 callout_reset(&periph->periph_callout, 1062 hz/2, scsipi_periph_timed_thaw, periph); 1063 retval = ERESTART; 1064 } 1065 1066 /* 1067 * If we got a "Unit not ready" (SKEY_NOT_READY) and "Long write in 1068 * progress" (Sense code 0x04, 0x08), then wait for the specified 1069 * time 1070 */ 1071 1072 if ((SSD_SENSE_KEY(sense->flags) == SKEY_NOT_READY) && 1073 (sense->asc == 0x04) && (sense->ascq == 0x08)) { 1074 /* 1075 * long write in process; we could listen to the delay; but it 1076 * looks like the skey data is not always returned. 1077 */ 1078 /* cd_delay = _2btol(sense->sks.sks_bytes); */ 1079 1080 /* wait for a half second and get going again */ 1081 if (!callout_pending(&periph->periph_callout)) 1082 scsipi_periph_freeze(periph, 1); 1083 callout_reset(&periph->periph_callout, 1084 hz/2, scsipi_periph_timed_thaw, periph); 1085 retval = ERESTART; 1086 } 1087 1088 return (retval); 1089} 1090 1091static void 1092cdminphys(struct buf *bp) 1093{ 1094 struct cd_softc *cd = device_lookup_private(&cd_cd, CDUNIT(bp->b_dev)); 1095 long xmax; 1096 1097 /* 1098 * If the device is ancient, we want to make sure that 1099 * the transfer fits into a 6-byte cdb. 1100 * 1101 * XXX Note that the SCSI-I spec says that 256-block transfers 1102 * are allowed in a 6-byte read/write, and are specified 1103 * by settng the "length" to 0. However, we're conservative 1104 * here, allowing only 255-block transfers in case an 1105 * ancient device gets confused by length == 0. A length of 0 1106 * in a 10-byte read/write actually means 0 blocks. 1107 */ 1108 if (cd->flags & CDF_ANCIENT) { 1109 xmax = cd->sc_dk.dk_label->d_secsize * 0xff; 1110 1111 if (bp->b_bcount > xmax) 1112 bp->b_bcount = xmax; 1113 } 1114 1115 (*cd->sc_periph->periph_channel->chan_adapter->adapt_minphys)(bp); 1116} 1117 1118static int 1119cdread(dev_t dev, struct uio *uio, int ioflag) 1120{ 1121 return (physio(cdstrategy, NULL, dev, B_READ, cdminphys, uio)); 1122} 1123 1124static int 1125cdwrite(dev_t dev, struct uio *uio, int ioflag) 1126{ 1127 return (physio(cdstrategy, NULL, dev, B_WRITE, cdminphys, uio)); 1128} 1129 1130#if 0 /* XXX Not used */ 1131/* 1132 * conversion between minute-seconde-frame and logical block address 1133 * addresses format 1134 */ 1135static void 1136lba2msf(u_long lba, u_char *m, u_char *s, u_char *f) 1137{ 1138 u_long tmp; 1139 1140 tmp = lba + CD_BLOCK_OFFSET; /* offset of first logical frame */ 1141 tmp &= 0xffffff; /* negative lbas use only 24 bits */ 1142 *m = tmp / (CD_SECS * CD_FRAMES); 1143 tmp %= (CD_SECS * CD_FRAMES); 1144 *s = tmp / CD_FRAMES; 1145 *f = tmp % CD_FRAMES; 1146} 1147#endif /* XXX Not used */ 1148 1149/* 1150 * Convert an hour:minute:second:frame address to a logical block adres. In 1151 * theory the number of secs/minute and number of frames/second could be 1152 * configured differently in the device as could the block offset but in 1153 * practice these values are rock solid and most drives don't even allow 1154 * theses values to be changed. 1155 */ 1156static uint32_t 1157hmsf2lba(uint8_t h, uint8_t m, uint8_t s, uint8_t f) 1158{ 1159 return (((((uint32_t) h * 60 + m) * CD_SECS) + s) * CD_FRAMES + f) 1160 - CD_BLOCK_OFFSET; 1161} 1162 1163static int 1164cdreadmsaddr(struct cd_softc *cd, struct cd_formatted_toc *toc, int *addr) 1165{ 1166 struct scsipi_periph *periph = cd->sc_periph; 1167 int error; 1168 struct cd_toc_entry *cte; 1169 1170 error = cd_read_toc(cd, CD_TOC_FORM, 0, 0, toc, 1171 sizeof(struct ioc_toc_header) + sizeof(struct cd_toc_entry), 1172 0, 0x40 /* control word for "get MS info" */); 1173 1174 if (error) 1175 return (error); 1176 1177 cte = &toc->entries[0]; 1178 if (periph->periph_quirks & PQUIRK_LITTLETOC) { 1179 cte->addr.lba = le32toh(cte->addr.lba); 1180 toc->header.len = le16toh(toc->header.len); 1181 } else { 1182 cte->addr.lba = be32toh(cte->addr.lba); 1183 toc->header.len = be16toh(toc->header.len); 1184 } 1185 1186 *addr = (toc->header.len >= 10 && cte->track > 1) ? 1187 cte->addr.lba : 0; 1188 return 0; 1189} 1190 1191/* synchronise caches code from sd.c, move to scsipi_ioctl.c ? */ 1192static int 1193cdcachesync(struct scsipi_periph *periph, int flags) { 1194 struct scsi_synchronize_cache_10 cmd; 1195 1196 /* 1197 * Issue a SYNCHRONIZE CACHE. MMC devices have to issue with address 0 1198 * and length 0 as it can't synchronise parts of the disc per spec. 1199 * We ignore ILLEGAL REQUEST in the event that the command is not 1200 * supported by the device, and poll for completion so that we know 1201 * that the cache has actually been flushed. 1202 * 1203 * XXX should we handle the PQUIRK_NOSYNCCACHE ? 1204 */ 1205 1206 memset(&cmd, 0, sizeof(cmd)); 1207 cmd.opcode = SCSI_SYNCHRONIZE_CACHE_10; 1208 1209 return (scsipi_command(periph, (void *)&cmd, sizeof(cmd), 0, 0, 1210 CDRETRIES, 30000, NULL, flags | XS_CTL_IGNORE_ILLEGAL_REQUEST)); 1211} 1212 1213static int 1214do_cdioreadentries(struct cd_softc *cd, struct ioc_read_toc_entry *te, 1215 struct cd_formatted_toc *toc) 1216{ 1217 /* READ TOC format 0 command, entries */ 1218 struct ioc_toc_header *th; 1219 struct cd_toc_entry *cte; 1220 u_int len = te->data_len; 1221 int ntracks; 1222 int error; 1223 1224 th = &toc->header; 1225 1226 if (len > sizeof(toc->entries) || 1227 len < sizeof(toc->entries[0])) 1228 return (EINVAL); 1229 error = cd_read_toc(cd, CD_TOC_FORM, te->address_format, 1230 te->starting_track, toc, 1231 sizeof(toc->header) + len, 1232 0, 0); 1233 if (error) 1234 return (error); 1235 if (te->address_format == CD_LBA_FORMAT) 1236 for (ntracks = 1237 th->ending_track - th->starting_track + 1; 1238 ntracks >= 0; ntracks--) { 1239 cte = &toc->entries[ntracks]; 1240 cte->addr_type = CD_LBA_FORMAT; 1241 if (cd->sc_periph->periph_quirks & PQUIRK_LITTLETOC) 1242 cte->addr.lba = le32toh(cte->addr.lba); 1243 else 1244 cte->addr.lba = be32toh(cte->addr.lba); 1245 } 1246 if (cd->sc_periph->periph_quirks & PQUIRK_LITTLETOC) 1247 th->len = le16toh(th->len); 1248 else 1249 th->len = be16toh(th->len); 1250 return 0; 1251} 1252 1253/* 1254 * Perform special action on behalf of the user. 1255 * Knows about the internals of this device 1256 */ 1257static int 1258cdioctl(dev_t dev, u_long cmd, void *addr, int flag, struct lwp *l) 1259{ 1260 struct cd_softc *cd = device_lookup_private(&cd_cd, CDUNIT(dev)); 1261 struct scsipi_periph *periph = cd->sc_periph; 1262 struct cd_formatted_toc toc; 1263 int part = CDPART(dev); 1264 int error; 1265 int s; 1266#ifdef __HAVE_OLD_DISKLABEL 1267 struct disklabel *newlabel = NULL; 1268#endif 1269 1270 SC_DEBUG(cd->sc_periph, SCSIPI_DB2, ("cdioctl 0x%lx ", cmd)); 1271 1272 /* 1273 * If the device is not valid, some IOCTLs can still be 1274 * handled on the raw partition. Check this here. 1275 */ 1276 if ((periph->periph_flags & PERIPH_MEDIA_LOADED) == 0) { 1277 switch (cmd) { 1278 case DIOCWLABEL: 1279 case DIOCLOCK: 1280 case ODIOCEJECT: 1281 case DIOCEJECT: 1282 case DIOCCACHESYNC: 1283 case DIOCTUR: 1284 case SCIOCIDENTIFY: 1285 case OSCIOCIDENTIFY: 1286 case SCIOCCOMMAND: 1287 case SCIOCDEBUG: 1288 case CDIOCGETVOL: 1289 case CDIOCSETVOL: 1290 case CDIOCSETMONO: 1291 case CDIOCSETSTEREO: 1292 case CDIOCSETMUTE: 1293 case CDIOCSETLEFT: 1294 case CDIOCSETRIGHT: 1295 case CDIOCCLOSE: 1296 case CDIOCEJECT: 1297 case CDIOCALLOW: 1298 case CDIOCPREVENT: 1299 case CDIOCSETDEBUG: 1300 case CDIOCCLRDEBUG: 1301 case CDIOCRESET: 1302 case SCIOCRESET: 1303 case CDIOCLOADUNLOAD: 1304 case DVD_AUTH: 1305 case DVD_READ_STRUCT: 1306 case DIOCGSTRATEGY: 1307 case DIOCSSTRATEGY: 1308 if (part == RAW_PART) 1309 break; 1310 /* FALLTHROUGH */ 1311 default: 1312 if ((periph->periph_flags & PERIPH_OPEN) == 0) 1313 return (ENODEV); 1314 else 1315 return (EIO); 1316 } 1317 } 1318 1319 error = disk_ioctl(&cd->sc_dk, cmd, addr, flag, l); 1320 if (error != EPASSTHROUGH) 1321 return (error); 1322 1323 error = 0; 1324 switch (cmd) { 1325 case DIOCGDINFO: 1326 *(struct disklabel *)addr = *(cd->sc_dk.dk_label); 1327 return (0); 1328#ifdef __HAVE_OLD_DISKLABEL 1329 case ODIOCGDINFO: 1330 newlabel = malloc(sizeof (*newlabel), M_TEMP, M_WAITOK); 1331 if (newlabel == NULL) 1332 return (EIO); 1333 memcpy(newlabel, cd->sc_dk.dk_label, sizeof (*newlabel)); 1334 if (newlabel->d_npartitions > OLDMAXPARTITIONS) 1335 error = ENOTTY; 1336 else 1337 memcpy(addr, newlabel, sizeof (struct olddisklabel)); 1338 free(newlabel, M_TEMP); 1339 return error; 1340#endif 1341 1342 case DIOCGPART: 1343 ((struct partinfo *)addr)->disklab = cd->sc_dk.dk_label; 1344 ((struct partinfo *)addr)->part = 1345 &cd->sc_dk.dk_label->d_partitions[part]; 1346 return (0); 1347 1348 case DIOCWDINFO: 1349 case DIOCSDINFO: 1350#ifdef __HAVE_OLD_DISKLABEL 1351 case ODIOCWDINFO: 1352 case ODIOCSDINFO: 1353#endif 1354 { 1355 struct disklabel *lp; 1356 1357 if ((flag & FWRITE) == 0) 1358 return (EBADF); 1359 1360#ifdef __HAVE_OLD_DISKLABEL 1361 if (cmd == ODIOCSDINFO || cmd == ODIOCWDINFO) { 1362 newlabel = malloc(sizeof (*newlabel), M_TEMP, 1363 M_WAITOK | M_ZERO); 1364 if (newlabel == NULL) 1365 return (EIO); 1366 memcpy(newlabel, addr, sizeof (struct olddisklabel)); 1367 lp = newlabel; 1368 } else 1369#endif 1370 lp = addr; 1371 1372 mutex_enter(&cd->sc_lock); 1373 cd->flags |= CDF_LABELLING; 1374 1375 error = setdisklabel(cd->sc_dk.dk_label, 1376 lp, /*cd->sc_dk.dk_openmask : */0, 1377 cd->sc_dk.dk_cpulabel); 1378 if (error == 0) { 1379 /* XXX ? */ 1380 } 1381 1382 cd->flags &= ~CDF_LABELLING; 1383 mutex_exit(&cd->sc_lock); 1384#ifdef __HAVE_OLD_DISKLABEL 1385 if (newlabel != NULL) 1386 free(newlabel, M_TEMP); 1387#endif 1388 return (error); 1389 } 1390 1391 case DIOCWLABEL: 1392 return (EBADF); 1393 1394 case DIOCGDEFLABEL: 1395 cdgetdefaultlabel(cd, &toc, addr); 1396 return (0); 1397 1398#ifdef __HAVE_OLD_DISKLABEL 1399 case ODIOCGDEFLABEL: 1400 newlabel = malloc(sizeof (*newlabel), M_TEMP, M_WAITOK); 1401 if (newlabel == NULL) 1402 return (EIO); 1403 cdgetdefaultlabel(cd, &toc, newlabel); 1404 if (newlabel->d_npartitions > OLDMAXPARTITIONS) 1405 error = ENOTTY; 1406 else 1407 memcpy(addr, newlabel, sizeof (struct olddisklabel)); 1408 free(newlabel, M_TEMP); 1409 return error; 1410#endif 1411 1412 case DIOCTUR: { 1413 /* test unit ready */ 1414 error = scsipi_test_unit_ready(cd->sc_periph, XS_CTL_SILENT); 1415 *((int*)addr) = (error == 0); 1416 if (error == ENODEV || error == EIO || error == 0) 1417 return 0; 1418 return error; 1419 } 1420 1421 case CDIOCPLAYTRACKS: { 1422 /* PLAY_MSF command */ 1423 struct ioc_play_track *args = addr; 1424 1425 if ((error = cd_set_pa_immed(cd, 0)) != 0) 1426 return (error); 1427 return (cd_play_tracks(cd, &toc, args->start_track, 1428 args->start_index, args->end_track, args->end_index)); 1429 } 1430 case CDIOCPLAYMSF: { 1431 /* PLAY_MSF command */ 1432 struct ioc_play_msf *args = addr; 1433 1434 if ((error = cd_set_pa_immed(cd, 0)) != 0) 1435 return (error); 1436 return (cd_play_msf(cd, args->start_m, args->start_s, 1437 args->start_f, args->end_m, args->end_s, args->end_f)); 1438 } 1439 case CDIOCPLAYBLOCKS: { 1440 /* PLAY command */ 1441 struct ioc_play_blocks *args = addr; 1442 1443 if ((error = cd_set_pa_immed(cd, 0)) != 0) 1444 return (error); 1445 return (cd_play(cd, args->blk, args->len)); 1446 } 1447 case CDIOCREADSUBCHANNEL: { 1448 /* READ_SUBCHANNEL command */ 1449 struct ioc_read_subchannel *args = addr; 1450 struct cd_sub_channel_info data; 1451 u_int len = args->data_len; 1452 1453 if (len > sizeof(data) || 1454 len < sizeof(struct cd_sub_channel_header)) 1455 return (EINVAL); 1456 error = cd_read_subchannel(cd, args->address_format, 1457 args->data_format, args->track, &data, len, 0); 1458 if (error) 1459 return (error); 1460 len = min(len, _2btol(data.header.data_len) + 1461 sizeof(struct cd_sub_channel_header)); 1462 return (copyout(&data, args->data, len)); 1463 } 1464 case CDIOCREADSUBCHANNEL_BUF: { 1465 /* As CDIOCREADSUBCHANNEL, but without a 2nd buffer area */ 1466 struct ioc_read_subchannel_buf *args = addr; 1467 if (args->req.data_len != sizeof args->info) 1468 return EINVAL; 1469 return cd_read_subchannel(cd, args->req.address_format, 1470 args->req.data_format, args->req.track, &args->info, 1471 sizeof(args->info), 0); 1472 } 1473 case CDIOREADTOCHEADER: { 1474 /* READ TOC format 0 command, static header */ 1475 if ((error = cd_read_toc(cd, CD_TOC_FORM, 0, 0, 1476 &toc, sizeof(toc.header), 0, 0)) != 0) 1477 return (error); 1478 if (cd->sc_periph->periph_quirks & PQUIRK_LITTLETOC) 1479 toc.header.len = le16toh(toc.header.len); 1480 else 1481 toc.header.len = be16toh(toc.header.len); 1482 memcpy(addr, &toc.header, sizeof(toc.header)); 1483 return (0); 1484 } 1485 case CDIOREADTOCENTRYS: { 1486 struct ioc_read_toc_entry *te = addr; 1487 error = do_cdioreadentries(cd, te, &toc); 1488 if (error != 0) 1489 return error; 1490 return copyout(toc.entries, te->data, min(te->data_len, 1491 toc.header.len - (sizeof(toc.header.starting_track) 1492 + sizeof(toc.header.ending_track)))); 1493 } 1494 case CDIOREADTOCENTRIES_BUF: { 1495 struct ioc_read_toc_entry_buf *te = addr; 1496 error = do_cdioreadentries(cd, &te->req, &toc); 1497 if (error != 0) 1498 return error; 1499 memcpy(te->entry, toc.entries, min(te->req.data_len, 1500 toc.header.len - (sizeof(toc.header.starting_track) 1501 + sizeof(toc.header.ending_track)))); 1502 return 0; 1503 } 1504 case CDIOREADMSADDR: { 1505 /* READ TOC format 0 command, length of first track only */ 1506 int sessno = *(int*)addr; 1507 1508 if (sessno != 0) 1509 return (EINVAL); 1510 1511 return (cdreadmsaddr(cd, &toc, addr)); 1512 } 1513 case CDIOCSETPATCH: { 1514 struct ioc_patch *arg = addr; 1515 1516 return (cd_setchan(cd, arg->patch[0], arg->patch[1], 1517 arg->patch[2], arg->patch[3], 0)); 1518 } 1519 case CDIOCGETVOL: { 1520 /* MODE SENSE command (AUDIO page) */ 1521 struct ioc_vol *arg = addr; 1522 1523 return (cd_getvol(cd, arg, 0)); 1524 } 1525 case CDIOCSETVOL: { 1526 /* MODE SENSE/MODE SELECT commands (AUDIO page) */ 1527 struct ioc_vol *arg = addr; 1528 1529 return (cd_setvol(cd, arg, 0)); 1530 } 1531 case CDIOCSETMONO: 1532 /* MODE SENSE/MODE SELECT commands (AUDIO page) */ 1533 return (cd_setchan(cd, BOTH_CHANNEL, BOTH_CHANNEL, 1534 MUTE_CHANNEL, MUTE_CHANNEL, 0)); 1535 1536 case CDIOCSETSTEREO: 1537 /* MODE SENSE/MODE SELECT commands (AUDIO page) */ 1538 return (cd_setchan(cd, LEFT_CHANNEL, RIGHT_CHANNEL, 1539 MUTE_CHANNEL, MUTE_CHANNEL, 0)); 1540 1541 case CDIOCSETMUTE: 1542 /* MODE SENSE/MODE SELECT commands (AUDIO page) */ 1543 return (cd_setchan(cd, MUTE_CHANNEL, MUTE_CHANNEL, 1544 MUTE_CHANNEL, MUTE_CHANNEL, 0)); 1545 1546 case CDIOCSETLEFT: 1547 /* MODE SENSE/MODE SELECT commands (AUDIO page) */ 1548 return (cd_setchan(cd, LEFT_CHANNEL, LEFT_CHANNEL, 1549 MUTE_CHANNEL, MUTE_CHANNEL, 0)); 1550 1551 case CDIOCSETRIGHT: 1552 /* MODE SENSE/MODE SELECT commands (AUDIO page) */ 1553 return (cd_setchan(cd, RIGHT_CHANNEL, RIGHT_CHANNEL, 1554 MUTE_CHANNEL, MUTE_CHANNEL, 0)); 1555 1556 case CDIOCRESUME: 1557 /* PAUSE command */ 1558 return (cd_pause(cd, PA_RESUME)); 1559 case CDIOCPAUSE: 1560 /* PAUSE command */ 1561 return (cd_pause(cd, PA_PAUSE)); 1562 case CDIOCSTART: 1563 return (scsipi_start(periph, SSS_START, 0)); 1564 case CDIOCSTOP: 1565 return (scsipi_start(periph, SSS_STOP, 0)); 1566 case CDIOCCLOSE: 1567 return (scsipi_start(periph, SSS_START|SSS_LOEJ, 1568 XS_CTL_IGNORE_NOT_READY | XS_CTL_IGNORE_MEDIA_CHANGE)); 1569 case DIOCEJECT: 1570 if (*(int *)addr == 0) { 1571 /* 1572 * Don't force eject: check that we are the only 1573 * partition open. If so, unlock it. 1574 */ 1575 if ((cd->sc_dk.dk_openmask & ~(1 << part)) == 0 && 1576 cd->sc_dk.dk_bopenmask + cd->sc_dk.dk_copenmask == 1577 cd->sc_dk.dk_openmask) { 1578 error = scsipi_prevent(periph, SPAMR_ALLOW, 1579 XS_CTL_IGNORE_NOT_READY); 1580 if (error) 1581 return (error); 1582 } else { 1583 return (EBUSY); 1584 } 1585 } 1586 /* FALLTHROUGH */ 1587 case CDIOCEJECT: /* FALLTHROUGH */ 1588 case ODIOCEJECT: 1589 error = scsipi_start(periph, SSS_STOP|SSS_LOEJ, 0); 1590 if (error == 0) { 1591 int i; 1592 1593 /* 1594 * We have just successfully ejected the medium, 1595 * all partitions cached are meaningless now. 1596 * Make sure cdclose() will do silent operations 1597 * now by marking all partitions unused. 1598 * Before any real access, a new (default-)disk- 1599 * label will be generated anyway. 1600 */ 1601 for (i = 0; i < cd->sc_dk.dk_label->d_npartitions; 1602 i++) 1603 cd->sc_dk.dk_label->d_partitions[i].p_fstype = 1604 FS_UNUSED; 1605 } 1606 return error; 1607 case DIOCCACHESYNC: 1608 /* SYNCHRONISE CACHES command */ 1609 return (cdcachesync(periph, 0)); 1610 case CDIOCALLOW: 1611 return (scsipi_prevent(periph, SPAMR_ALLOW, 0)); 1612 case CDIOCPREVENT: 1613 return (scsipi_prevent(periph, SPAMR_PREVENT_DT, 0)); 1614 case DIOCLOCK: 1615 return (scsipi_prevent(periph, 1616 (*(int *)addr) ? SPAMR_PREVENT_DT : SPAMR_ALLOW, 0)); 1617 case CDIOCSETDEBUG: 1618 cd->sc_periph->periph_dbflags |= (SCSIPI_DB1 | SCSIPI_DB2); 1619 return (0); 1620 case CDIOCCLRDEBUG: 1621 cd->sc_periph->periph_dbflags &= ~(SCSIPI_DB1 | SCSIPI_DB2); 1622 return (0); 1623 case CDIOCRESET: 1624 case SCIOCRESET: 1625 return (cd_reset(cd)); 1626 case CDIOCLOADUNLOAD: 1627 /* LOAD_UNLOAD command */ 1628 return (cd_load_unload(cd, addr)); 1629 case DVD_AUTH: 1630 /* GPCMD_REPORT_KEY or GPCMD_SEND_KEY command */ 1631 return (dvd_auth(cd, addr)); 1632 case DVD_READ_STRUCT: 1633 /* GPCMD_READ_DVD_STRUCTURE command */ 1634 return (dvd_read_struct(cd, addr)); 1635 case MMCGETDISCINFO: 1636 /* 1637 * GET_CONFIGURATION, READ_DISCINFO, READ_TRACKINFO, 1638 * (READ_TOCf2, READ_CD_CAPACITY and GET_CONFIGURATION) commands 1639 */ 1640 return mmc_getdiscinfo(periph, (struct mmc_discinfo *) addr); 1641 case MMCGETTRACKINFO: 1642 /* READ TOCf2, READ_CD_CAPACITY and READ_TRACKINFO commands */ 1643 return mmc_gettrackinfo(periph, (struct mmc_trackinfo *) addr); 1644 case MMCOP: 1645 /* 1646 * CLOSE TRACK/SESSION, RESERVE_TRACK, REPAIR_TRACK, 1647 * SYNCHRONISE_CACHE commands 1648 */ 1649 return mmc_do_op(periph, (struct mmc_op *) addr); 1650 case MMCSETUPWRITEPARAMS : 1651 /* MODE SENSE page 5, MODE_SELECT page 5 commands */ 1652 return mmc_setup_writeparams(periph, (struct mmc_writeparams *) addr); 1653 case DIOCGSTRATEGY: 1654 { 1655 struct disk_strategy *dks = addr; 1656 1657 s = splbio(); 1658 strlcpy(dks->dks_name, bufq_getstrategyname(cd->buf_queue), 1659 sizeof(dks->dks_name)); 1660 splx(s); 1661 dks->dks_paramlen = 0; 1662 1663 return 0; 1664 } 1665 case DIOCSSTRATEGY: 1666 { 1667 struct disk_strategy *dks = addr; 1668 struct bufq_state *new; 1669 struct bufq_state *old; 1670 1671 if ((flag & FWRITE) == 0) { 1672 return EBADF; 1673 } 1674 if (dks->dks_param != NULL) { 1675 return EINVAL; 1676 } 1677 dks->dks_name[sizeof(dks->dks_name) - 1] = 0; /* ensure term */ 1678 error = bufq_alloc(&new, dks->dks_name, 1679 BUFQ_EXACT|BUFQ_SORT_RAWBLOCK); 1680 if (error) { 1681 return error; 1682 } 1683 s = splbio(); 1684 old = cd->buf_queue; 1685 bufq_move(new, old); 1686 cd->buf_queue = new; 1687 splx(s); 1688 bufq_free(old); 1689 1690 return 0; 1691 } 1692 default: 1693 if (part != RAW_PART) 1694 return (ENOTTY); 1695 return (scsipi_do_ioctl(periph, dev, cmd, addr, flag, l)); 1696 } 1697 1698#ifdef DIAGNOSTIC 1699 panic("cdioctl: impossible"); 1700#endif 1701} 1702 1703static void 1704cdgetdefaultlabel(struct cd_softc *cd, struct cd_formatted_toc *toc, 1705 struct disklabel *lp) 1706{ 1707 int lastsession; 1708 1709 memset(lp, 0, sizeof(struct disklabel)); 1710 1711 lp->d_secsize = cd->params.blksize; 1712 lp->d_ntracks = 1; 1713 lp->d_nsectors = 100; 1714 lp->d_ncylinders = (cd->params.disksize / 100) + 1; 1715 lp->d_secpercyl = lp->d_ntracks * lp->d_nsectors; 1716 1717 switch (SCSIPI_BUSTYPE_TYPE(scsipi_periph_bustype(cd->sc_periph))) { 1718 case SCSIPI_BUSTYPE_SCSI: 1719 lp->d_type = DTYPE_SCSI; 1720 break; 1721 case SCSIPI_BUSTYPE_ATAPI: 1722 lp->d_type = DTYPE_ATAPI; 1723 break; 1724 } 1725 /* 1726 * XXX 1727 * We could probe the mode pages to figure out what kind of disc it is. 1728 * Is this worthwhile? 1729 */ 1730 strncpy(lp->d_typename, "optical media", 16); 1731 strncpy(lp->d_packname, "fictitious", 16); 1732 lp->d_secperunit = cd->params.disksize; 1733 lp->d_rpm = 300; 1734 lp->d_interleave = 1; 1735 lp->d_flags = D_REMOVABLE | D_SCSI_MMC; 1736 1737 if (cdreadmsaddr(cd, toc, &lastsession) != 0) 1738 lastsession = 0; 1739 1740 lp->d_partitions[0].p_offset = 0; 1741 lp->d_partitions[0].p_size = lp->d_secperunit; 1742 lp->d_partitions[0].p_cdsession = lastsession; 1743 lp->d_partitions[0].p_fstype = FS_ISO9660; 1744 1745 lp->d_partitions[RAW_PART].p_offset = 0; 1746 lp->d_partitions[RAW_PART].p_size = lp->d_secperunit; 1747 lp->d_partitions[RAW_PART].p_fstype = FS_UDF; 1748 1749 lp->d_npartitions = RAW_PART + 1; 1750 1751 lp->d_magic = DISKMAGIC; 1752 lp->d_magic2 = DISKMAGIC; 1753 lp->d_checksum = dkcksum(lp); 1754} 1755 1756/* 1757 * Load the label information on the named device 1758 * Actually fabricate a disklabel 1759 * 1760 * EVENTUALLY take information about different 1761 * data tracks from the TOC and put it in the disklabel 1762 */ 1763static void 1764cdgetdisklabel(struct cd_softc *cd) 1765{ 1766 struct disklabel *lp = cd->sc_dk.dk_label; 1767 struct cd_formatted_toc toc; 1768 const char *errstring; 1769 int bmajor; 1770 1771 memset(cd->sc_dk.dk_cpulabel, 0, sizeof(struct cpu_disklabel)); 1772 1773 cdgetdefaultlabel(cd, &toc, lp); 1774 1775 /* 1776 * Call the generic disklabel extraction routine 1777 * 1778 * bmajor follows ata_raid code 1779 */ 1780 bmajor = devsw_name2blk(device_xname(cd->sc_dev), NULL, 0); 1781 errstring = readdisklabel(MAKECDDEV(bmajor, 1782 device_unit(cd->sc_dev), RAW_PART), 1783 cdstrategy, lp, cd->sc_dk.dk_cpulabel); 1784 1785 /* if all went OK, we are passed a NULL error string */ 1786 if (errstring == NULL) 1787 return; 1788 1789 /* Reset to default label -- after printing error and the warning */ 1790 aprint_error_dev(cd->sc_dev, "%s\n", errstring); 1791 memset(cd->sc_dk.dk_cpulabel, 0, sizeof(struct cpu_disklabel)); 1792 cdgetdefaultlabel(cd, &toc, lp); 1793} 1794 1795/* 1796 * Reading a disc's total capacity is apparently a very difficult issue for the 1797 * SCSI standardisation group. Every disc type seems to have its own 1798 * (re)invented size request method and modifiers. The failsafe way of 1799 * determining the total (max) capacity i.e. not the recorded capacity but the 1800 * total maximum capacity is to request the info on the last track and 1801 * calculate the last lba. 1802 * 1803 * For ROM drives, we go for the CD recorded capacity. For recordable devices 1804 * we count. 1805 */ 1806static int 1807read_cd_capacity(struct scsipi_periph *periph, u_int *blksize, u_long *last_lba) 1808{ 1809 struct scsipi_read_cd_capacity cap_cmd; 1810 /* 1811 * XXX: see PR 48550 and PR 48754: 1812 * the ahcisata(4) driver can not deal with unaligned 1813 * data, so align this "a bit" 1814 */ 1815 struct scsipi_read_cd_cap_data cap __aligned(2); 1816 struct scsipi_read_discinfo di_cmd; 1817 struct scsipi_read_discinfo_data di; 1818 struct scsipi_read_trackinfo ti_cmd; 1819 struct scsipi_read_trackinfo_data ti; 1820 uint32_t track_start, track_size; 1821 int error, flags, msb, lsb, last_track; 1822 1823 /* if the device doesn't grok capacity, return the dummies */ 1824 if (periph->periph_quirks & PQUIRK_NOCAPACITY) 1825 return 0; 1826 1827 /* first try read CD capacity for blksize and last recorded lba */ 1828 /* issue the cd capacity request */ 1829 flags = XS_CTL_DATA_IN; 1830 memset(&cap_cmd, 0, sizeof(cap_cmd)); 1831 memset(&cap, 0, sizeof(cap)); 1832 cap_cmd.opcode = READ_CD_CAPACITY; 1833 1834 error = scsipi_command(periph, 1835 (void *) &cap_cmd, sizeof(cap_cmd), 1836 (void *) &cap, sizeof(cap), 1837 CDRETRIES, 30000, NULL, flags); 1838 if (error) 1839 return error; 1840 1841 /* retrieve values and sanity check them */ 1842 *blksize = _4btol(cap.length); 1843 *last_lba = _4btol(cap.addr); 1844 1845 /* blksize is 2048 for CD, but some drives give gibberish */ 1846 if ((*blksize < 512) || ((*blksize & 511) != 0) 1847 || (*blksize > 16*1024)) { 1848 if (*blksize > 16*1024) 1849 aprint_error("read_cd_capacity: extra large block " 1850 "size %u found - limiting to 2kByte\n", 1851 *blksize); 1852 *blksize = 2048; /* some drives lie ! */ 1853 } 1854 1855 /* recordables have READ_DISCINFO implemented */ 1856 flags = XS_CTL_DATA_IN | XS_CTL_SILENT; 1857 memset(&di_cmd, 0, sizeof(di_cmd)); 1858 di_cmd.opcode = READ_DISCINFO; 1859 _lto2b(READ_DISCINFO_BIGSIZE, di_cmd.data_len); 1860 1861 error = scsipi_command(periph, 1862 (void *) &di_cmd, sizeof(di_cmd), 1863 (void *) &di, READ_DISCINFO_BIGSIZE, 1864 CDRETRIES, 30000, NULL, flags); 1865 if (error == 0) { 1866 msb = di.last_track_last_session_msb; 1867 lsb = di.last_track_last_session_lsb; 1868 last_track = (msb << 8) | lsb; 1869 1870 /* request info on last track */ 1871 memset(&ti_cmd, 0, sizeof(ti_cmd)); 1872 ti_cmd.opcode = READ_TRACKINFO; 1873 ti_cmd.addr_type = 1; /* on tracknr */ 1874 _lto4b(last_track, ti_cmd.address); /* tracknr */ 1875 _lto2b(sizeof(ti), ti_cmd.data_len); 1876 1877 error = scsipi_command(periph, 1878 (void *) &ti_cmd, sizeof(ti_cmd), 1879 (void *) &ti, sizeof(ti), 1880 CDRETRIES, 30000, NULL, flags); 1881 if (error == 0) { 1882 track_start = _4btol(ti.track_start); 1883 track_size = _4btol(ti.track_size); 1884 1885 /* overwrite only with a sane value */ 1886 if (track_start + track_size >= 100) 1887 *last_lba = (u_long) track_start + track_size -1; 1888 } 1889 } 1890 1891 /* sanity check for lba_size */ 1892 if (*last_lba < 100) 1893 *last_lba = 400000-1; 1894 1895 return 0; 1896} 1897 1898/* 1899 * Find out from the device what it's capacity is 1900 */ 1901static u_long 1902cd_size(struct cd_softc *cd, int flags) 1903{ 1904 u_int blksize = 2048; 1905 u_long last_lba = 0, size; 1906 int error; 1907 1908 error = read_cd_capacity(cd->sc_periph, &blksize, &last_lba); 1909 if (error) 1910 goto error; 1911 1912 if (blksize != 2048) { 1913 if (cd_setblksize(cd) == 0) { 1914 blksize = 2048; 1915 error = read_cd_capacity(cd->sc_periph, 1916 &blksize, &last_lba); 1917 if (error) 1918 goto error; 1919 } 1920 } 1921 1922 size = last_lba + 1; 1923 cd->params.blksize = blksize; 1924 cd->params.disksize = size; 1925 cd->params.disksize512 = ((u_int64_t)cd->params.disksize * blksize) / DEV_BSIZE; 1926 1927 SC_DEBUG(cd->sc_periph, SCSIPI_DB2, 1928 ("cd_size: %u %lu\n", blksize, size)); 1929 1930 return size; 1931 1932error: 1933 /* something went wrong */ 1934 cd->params.blksize = 2048; 1935 cd->params.disksize = 0; 1936 cd->params.disksize512 = 0; 1937 1938 SC_DEBUG(cd->sc_periph, SCSIPI_DB2, ("cd_size: failed\n")); 1939 1940 return 0; 1941} 1942 1943/* 1944 * Get scsi driver to send a "start playing" command 1945 */ 1946static int 1947cd_play(struct cd_softc *cd, int blkno, int nblks) 1948{ 1949 struct scsipi_play cmd; 1950 1951 memset(&cmd, 0, sizeof(cmd)); 1952 cmd.opcode = PLAY; 1953 _lto4b(blkno, cmd.blk_addr); 1954 _lto2b(nblks, cmd.xfer_len); 1955 1956 return (scsipi_command(cd->sc_periph, (void *)&cmd, sizeof(cmd), 0, 0, 1957 CDRETRIES, 30000, NULL, 0)); 1958} 1959 1960/* 1961 * Get scsi driver to send a "start playing" command 1962 */ 1963static int 1964cd_play_tracks(struct cd_softc *cd, struct cd_formatted_toc *toc, int strack, 1965 int sindex, int etrack, int eindex) 1966{ 1967 int error; 1968 1969 if (!etrack) 1970 return (EIO); 1971 if (strack > etrack) 1972 return (EINVAL); 1973 1974 error = cd_load_toc(cd, CD_TOC_FORM, toc, 0); 1975 if (error) 1976 return (error); 1977 1978 if (++etrack > (toc->header.ending_track+1)) 1979 etrack = toc->header.ending_track+1; 1980 1981 strack -= toc->header.starting_track; 1982 etrack -= toc->header.starting_track; 1983 if (strack < 0) 1984 return (EINVAL); 1985 1986 return (cd_play_msf(cd, toc->entries[strack].addr.msf.minute, 1987 toc->entries[strack].addr.msf.second, 1988 toc->entries[strack].addr.msf.frame, 1989 toc->entries[etrack].addr.msf.minute, 1990 toc->entries[etrack].addr.msf.second, 1991 toc->entries[etrack].addr.msf.frame)); 1992} 1993 1994/* 1995 * Get scsi driver to send a "play msf" command 1996 */ 1997static int 1998cd_play_msf(struct cd_softc *cd, int startm, int starts, int startf, int endm, 1999 int ends, int endf) 2000{ 2001 struct scsipi_play_msf cmd; 2002 2003 memset(&cmd, 0, sizeof(cmd)); 2004 cmd.opcode = PLAY_MSF; 2005 cmd.start_m = startm; 2006 cmd.start_s = starts; 2007 cmd.start_f = startf; 2008 cmd.end_m = endm; 2009 cmd.end_s = ends; 2010 cmd.end_f = endf; 2011 2012 return (scsipi_command(cd->sc_periph, (void *)&cmd, sizeof(cmd), 0, 0, 2013 CDRETRIES, 30000, NULL, 0)); 2014} 2015 2016/* 2017 * Get scsi driver to send a "start up" command 2018 */ 2019static int 2020cd_pause(struct cd_softc *cd, int go) 2021{ 2022 struct scsipi_pause cmd; 2023 2024 memset(&cmd, 0, sizeof(cmd)); 2025 cmd.opcode = PAUSE; 2026 cmd.resume = go & 0xff; 2027 2028 return (scsipi_command(cd->sc_periph, (void *)&cmd, sizeof(cmd), 0, 0, 2029 CDRETRIES, 30000, NULL, 0)); 2030} 2031 2032/* 2033 * Get scsi driver to send a "RESET" command 2034 */ 2035static int 2036cd_reset(struct cd_softc *cd) 2037{ 2038 2039 return (scsipi_command(cd->sc_periph, 0, 0, 0, 0, 2040 CDRETRIES, 30000, NULL, XS_CTL_RESET)); 2041} 2042 2043/* 2044 * Read subchannel 2045 */ 2046static int 2047cd_read_subchannel(struct cd_softc *cd, int mode, int format, int track, 2048 struct cd_sub_channel_info *data, int len, int flags) 2049{ 2050 struct scsipi_read_subchannel cmd; 2051 2052 memset(&cmd, 0, sizeof(cmd)); 2053 cmd.opcode = READ_SUBCHANNEL; 2054 if (mode == CD_MSF_FORMAT) 2055 cmd.byte2 |= CD_MSF; 2056 cmd.byte3 = SRS_SUBQ; 2057 cmd.subchan_format = format; 2058 cmd.track = track; 2059 _lto2b(len, cmd.data_len); 2060 2061 return (scsipi_command(cd->sc_periph, 2062 (void *)&cmd, sizeof(struct scsipi_read_subchannel), 2063 (void *)data, len, 2064 CDRETRIES, 30000, NULL, flags | XS_CTL_DATA_IN | XS_CTL_SILENT)); 2065} 2066 2067/* 2068 * Read table of contents 2069 */ 2070static int 2071cd_read_toc(struct cd_softc *cd, int respf, int mode, int start, 2072 struct cd_formatted_toc *toc, int len, int flags, int control) 2073{ 2074 struct scsipi_read_toc cmd; 2075 int ntoc; 2076 2077 memset(&cmd, 0, sizeof(cmd)); 2078#if 0 2079 if (len != sizeof(struct ioc_toc_header)) 2080 ntoc = ((len) - sizeof(struct ioc_toc_header)) / 2081 sizeof(struct cd_toc_entry); 2082 else 2083#endif 2084 ntoc = len; 2085 cmd.opcode = READ_TOC; 2086 if (mode == CD_MSF_FORMAT) 2087 cmd.addr_mode |= CD_MSF; 2088 cmd.resp_format = respf; 2089 cmd.from_track = start; 2090 _lto2b(ntoc, cmd.data_len); 2091 cmd.control = control; 2092 2093 return (scsipi_command(cd->sc_periph, 2094 (void *)&cmd, sizeof(cmd), (void *)toc, len, CDRETRIES, 2095 30000, NULL, flags | XS_CTL_DATA_IN)); 2096} 2097 2098static int 2099cd_load_toc(struct cd_softc *cd, int respf, struct cd_formatted_toc *toc, int flags) 2100{ 2101 int ntracks, len, error; 2102 2103 if ((error = cd_read_toc(cd, respf, 0, 0, toc, sizeof(toc->header), 2104 flags, 0)) != 0) 2105 return (error); 2106 2107 ntracks = toc->header.ending_track - toc->header.starting_track + 1; 2108 len = (ntracks + 1) * sizeof(struct cd_toc_entry) + 2109 sizeof(toc->header); 2110 if ((error = cd_read_toc(cd, respf, CD_MSF_FORMAT, 0, toc, len, 2111 flags, 0)) != 0) 2112 return (error); 2113 return (0); 2114} 2115 2116/* 2117 * Get the scsi driver to send a full inquiry to the device and use the 2118 * results to fill out the disk parameter structure. 2119 */ 2120static int 2121cd_get_parms(struct cd_softc *cd, int flags) 2122{ 2123 2124 /* 2125 * give a number of sectors so that sec * trks * cyls 2126 * is <= disk_size 2127 */ 2128 if (cd_size(cd, flags) == 0) 2129 return (ENXIO); 2130 disk_blocksize(&cd->sc_dk, cd->params.blksize); 2131 return (0); 2132} 2133 2134static int 2135cdsize(dev_t dev) 2136{ 2137 2138 /* CD-ROMs are read-only. */ 2139 return (-1); 2140} 2141 2142static int 2143cddump(dev_t dev, daddr_t blkno, void *va, size_t size) 2144{ 2145 2146 /* Not implemented. */ 2147 return (ENXIO); 2148} 2149 2150#define dvd_copy_key(dst, src) memcpy((dst), (src), sizeof(dvd_key)) 2151#define dvd_copy_challenge(dst, src) memcpy((dst), (src), sizeof(dvd_challenge)) 2152 2153static int 2154dvd_auth(struct cd_softc *cd, dvd_authinfo *a) 2155{ 2156 struct scsipi_generic cmd; 2157 u_int8_t bf[20]; 2158 int error; 2159 2160 memset(cmd.bytes, 0, 15); 2161 memset(bf, 0, sizeof(bf)); 2162 2163 switch (a->type) { 2164 case DVD_LU_SEND_AGID: 2165 cmd.opcode = GPCMD_REPORT_KEY; 2166 cmd.bytes[8] = 8; 2167 cmd.bytes[9] = 0 | (0 << 6); 2168 error = scsipi_command(cd->sc_periph, &cmd, 12, bf, 8, 2169 CDRETRIES, 30000, NULL, XS_CTL_DATA_IN); 2170 if (error) 2171 return (error); 2172 a->lsa.agid = bf[7] >> 6; 2173 return (0); 2174 2175 case DVD_LU_SEND_CHALLENGE: 2176 cmd.opcode = GPCMD_REPORT_KEY; 2177 cmd.bytes[8] = 16; 2178 cmd.bytes[9] = 1 | (a->lsc.agid << 6); 2179 error = scsipi_command(cd->sc_periph, &cmd, 12, bf, 16, 2180 CDRETRIES, 30000, NULL, XS_CTL_DATA_IN); 2181 if (error) 2182 return (error); 2183 dvd_copy_challenge(a->lsc.chal, &bf[4]); 2184 return (0); 2185 2186 case DVD_LU_SEND_KEY1: 2187 cmd.opcode = GPCMD_REPORT_KEY; 2188 cmd.bytes[8] = 12; 2189 cmd.bytes[9] = 2 | (a->lsk.agid << 6); 2190 error = scsipi_command(cd->sc_periph, &cmd, 12, bf, 12, 2191 CDRETRIES, 30000, NULL, XS_CTL_DATA_IN); 2192 if (error) 2193 return (error); 2194 dvd_copy_key(a->lsk.key, &bf[4]); 2195 return (0); 2196 2197 case DVD_LU_SEND_TITLE_KEY: 2198 cmd.opcode = GPCMD_REPORT_KEY; 2199 _lto4b(a->lstk.lba, &cmd.bytes[1]); 2200 cmd.bytes[8] = 12; 2201 cmd.bytes[9] = 4 | (a->lstk.agid << 6); 2202 error = scsipi_command(cd->sc_periph, &cmd, 12, bf, 12, 2203 CDRETRIES, 30000, NULL, XS_CTL_DATA_IN); 2204 if (error) 2205 return (error); 2206 a->lstk.cpm = (bf[4] >> 7) & 1; 2207 a->lstk.cp_sec = (bf[4] >> 6) & 1; 2208 a->lstk.cgms = (bf[4] >> 4) & 3; 2209 dvd_copy_key(a->lstk.title_key, &bf[5]); 2210 return (0); 2211 2212 case DVD_LU_SEND_ASF: 2213 cmd.opcode = GPCMD_REPORT_KEY; 2214 cmd.bytes[8] = 8; 2215 cmd.bytes[9] = 5 | (a->lsasf.agid << 6); 2216 error = scsipi_command(cd->sc_periph, &cmd, 12, bf, 8, 2217 CDRETRIES, 30000, NULL, XS_CTL_DATA_IN); 2218 if (error) 2219 return (error); 2220 a->lsasf.asf = bf[7] & 1; 2221 return (0); 2222 2223 case DVD_HOST_SEND_CHALLENGE: 2224 cmd.opcode = GPCMD_SEND_KEY; 2225 cmd.bytes[8] = 16; 2226 cmd.bytes[9] = 1 | (a->hsc.agid << 6); 2227 bf[1] = 14; 2228 dvd_copy_challenge(&bf[4], a->hsc.chal); 2229 error = scsipi_command(cd->sc_periph, &cmd, 12, bf, 16, 2230 CDRETRIES, 30000, NULL, XS_CTL_DATA_OUT); 2231 if (error) 2232 return (error); 2233 a->type = DVD_LU_SEND_KEY1; 2234 return (0); 2235 2236 case DVD_HOST_SEND_KEY2: 2237 cmd.opcode = GPCMD_SEND_KEY; 2238 cmd.bytes[8] = 12; 2239 cmd.bytes[9] = 3 | (a->hsk.agid << 6); 2240 bf[1] = 10; 2241 dvd_copy_key(&bf[4], a->hsk.key); 2242 error = scsipi_command(cd->sc_periph, &cmd, 12, bf, 12, 2243 CDRETRIES, 30000, NULL, XS_CTL_DATA_OUT); 2244 if (error) { 2245 a->type = DVD_AUTH_FAILURE; 2246 return (error); 2247 } 2248 a->type = DVD_AUTH_ESTABLISHED; 2249 return (0); 2250 2251 case DVD_INVALIDATE_AGID: 2252 cmd.opcode = GPCMD_REPORT_KEY; 2253 cmd.bytes[9] = 0x3f | (a->lsa.agid << 6); 2254 error = scsipi_command(cd->sc_periph, &cmd, 12, bf, 16, 2255 CDRETRIES, 30000, NULL, 0); 2256 if (error) 2257 return (error); 2258 return (0); 2259 2260 case DVD_LU_SEND_RPC_STATE: 2261 cmd.opcode = GPCMD_REPORT_KEY; 2262 cmd.bytes[8] = 8; 2263 cmd.bytes[9] = 8 | (0 << 6); 2264 error = scsipi_command(cd->sc_periph, &cmd, 12, bf, 8, 2265 CDRETRIES, 30000, NULL, XS_CTL_DATA_IN); 2266 if (error) 2267 return (error); 2268 a->lrpcs.type = (bf[4] >> 6) & 3; 2269 a->lrpcs.vra = (bf[4] >> 3) & 7; 2270 a->lrpcs.ucca = (bf[4]) & 7; 2271 a->lrpcs.region_mask = bf[5]; 2272 a->lrpcs.rpc_scheme = bf[6]; 2273 return (0); 2274 2275 case DVD_HOST_SEND_RPC_STATE: 2276 cmd.opcode = GPCMD_SEND_KEY; 2277 cmd.bytes[8] = 8; 2278 cmd.bytes[9] = 6 | (0 << 6); 2279 bf[1] = 6; 2280 bf[4] = a->hrpcs.pdrc; 2281 error = scsipi_command(cd->sc_periph, &cmd, 12, bf, 8, 2282 CDRETRIES, 30000, NULL, XS_CTL_DATA_OUT); 2283 if (error) 2284 return (error); 2285 return (0); 2286 2287 default: 2288 return (ENOTTY); 2289 } 2290} 2291 2292static int 2293dvd_read_physical(struct cd_softc *cd, dvd_struct *s) 2294{ 2295 struct scsipi_generic cmd; 2296 u_int8_t bf[4 + 4 * 20], *bufp; 2297 int error; 2298 struct dvd_layer *layer; 2299 int i; 2300 2301 memset(cmd.bytes, 0, 15); 2302 memset(bf, 0, sizeof(bf)); 2303 cmd.opcode = GPCMD_READ_DVD_STRUCTURE; 2304 cmd.bytes[6] = s->type; 2305 _lto2b(sizeof(bf), &cmd.bytes[7]); 2306 2307 cmd.bytes[5] = s->physical.layer_num; 2308 error = scsipi_command(cd->sc_periph, &cmd, 12, bf, sizeof(bf), 2309 CDRETRIES, 30000, NULL, XS_CTL_DATA_IN); 2310 if (error) 2311 return (error); 2312 for (i = 0, bufp = &bf[4], layer = &s->physical.layer[0]; i < 4; 2313 i++, bufp += 20, layer++) { 2314 memset(layer, 0, sizeof(*layer)); 2315 layer->book_version = bufp[0] & 0xf; 2316 layer->book_type = bufp[0] >> 4; 2317 layer->min_rate = bufp[1] & 0xf; 2318 layer->disc_size = bufp[1] >> 4; 2319 layer->layer_type = bufp[2] & 0xf; 2320 layer->track_path = (bufp[2] >> 4) & 1; 2321 layer->nlayers = (bufp[2] >> 5) & 3; 2322 layer->track_density = bufp[3] & 0xf; 2323 layer->linear_density = bufp[3] >> 4; 2324 layer->start_sector = _4btol(&bufp[4]); 2325 layer->end_sector = _4btol(&bufp[8]); 2326 layer->end_sector_l0 = _4btol(&bufp[12]); 2327 layer->bca = bufp[16] >> 7; 2328 } 2329 return (0); 2330} 2331 2332static int 2333dvd_read_copyright(struct cd_softc *cd, dvd_struct *s) 2334{ 2335 struct scsipi_generic cmd; 2336 u_int8_t bf[8]; 2337 int error; 2338 2339 memset(cmd.bytes, 0, 15); 2340 memset(bf, 0, sizeof(bf)); 2341 cmd.opcode = GPCMD_READ_DVD_STRUCTURE; 2342 cmd.bytes[6] = s->type; 2343 _lto2b(sizeof(bf), &cmd.bytes[7]); 2344 2345 cmd.bytes[5] = s->copyright.layer_num; 2346 error = scsipi_command(cd->sc_periph, &cmd, 12, bf, sizeof(bf), 2347 CDRETRIES, 30000, NULL, XS_CTL_DATA_IN); 2348 if (error) 2349 return (error); 2350 s->copyright.cpst = bf[4]; 2351 s->copyright.rmi = bf[5]; 2352 return (0); 2353} 2354 2355static int 2356dvd_read_disckey(struct cd_softc *cd, dvd_struct *s) 2357{ 2358 struct scsipi_generic cmd; 2359 u_int8_t *bf; 2360 int error; 2361 2362 bf = malloc(4 + 2048, M_TEMP, M_WAITOK|M_ZERO); 2363 if (bf == NULL) 2364 return EIO; 2365 memset(cmd.bytes, 0, 15); 2366 cmd.opcode = GPCMD_READ_DVD_STRUCTURE; 2367 cmd.bytes[6] = s->type; 2368 _lto2b(4 + 2048, &cmd.bytes[7]); 2369 2370 cmd.bytes[9] = s->disckey.agid << 6; 2371 error = scsipi_command(cd->sc_periph, &cmd, 12, bf, 4 + 2048, 2372 CDRETRIES, 30000, NULL, XS_CTL_DATA_IN); 2373 if (error == 0) 2374 memcpy(s->disckey.value, &bf[4], 2048); 2375 free(bf, M_TEMP); 2376 return error; 2377} 2378 2379static int 2380dvd_read_bca(struct cd_softc *cd, dvd_struct *s) 2381{ 2382 struct scsipi_generic cmd; 2383 u_int8_t bf[4 + 188]; 2384 int error; 2385 2386 memset(cmd.bytes, 0, 15); 2387 memset(bf, 0, sizeof(bf)); 2388 cmd.opcode = GPCMD_READ_DVD_STRUCTURE; 2389 cmd.bytes[6] = s->type; 2390 _lto2b(sizeof(bf), &cmd.bytes[7]); 2391 2392 error = scsipi_command(cd->sc_periph, &cmd, 12, bf, sizeof(bf), 2393 CDRETRIES, 30000, NULL, XS_CTL_DATA_IN); 2394 if (error) 2395 return (error); 2396 s->bca.len = _2btol(&bf[0]); 2397 if (s->bca.len < 12 || s->bca.len > 188) 2398 return (EIO); 2399 memcpy(s->bca.value, &bf[4], s->bca.len); 2400 return (0); 2401} 2402 2403static int 2404dvd_read_manufact(struct cd_softc *cd, dvd_struct *s) 2405{ 2406 struct scsipi_generic cmd; 2407 u_int8_t *bf; 2408 int error; 2409 2410 bf = malloc(4 + 2048, M_TEMP, M_WAITOK|M_ZERO); 2411 if (bf == NULL) 2412 return (EIO); 2413 memset(cmd.bytes, 0, 15); 2414 cmd.opcode = GPCMD_READ_DVD_STRUCTURE; 2415 cmd.bytes[6] = s->type; 2416 _lto2b(4 + 2048, &cmd.bytes[7]); 2417 2418 error = scsipi_command(cd->sc_periph, &cmd, 12, bf, 4 + 2048, 2419 CDRETRIES, 30000, NULL, XS_CTL_DATA_IN); 2420 if (error == 0) { 2421 s->manufact.len = _2btol(&bf[0]); 2422 if (s->manufact.len >= 0 && s->manufact.len <= 2048) 2423 memcpy(s->manufact.value, &bf[4], s->manufact.len); 2424 else 2425 error = EIO; 2426 } 2427 free(bf, M_TEMP); 2428 return error; 2429} 2430 2431static int 2432dvd_read_struct(struct cd_softc *cd, dvd_struct *s) 2433{ 2434 2435 switch (s->type) { 2436 case DVD_STRUCT_PHYSICAL: 2437 return (dvd_read_physical(cd, s)); 2438 case DVD_STRUCT_COPYRIGHT: 2439 return (dvd_read_copyright(cd, s)); 2440 case DVD_STRUCT_DISCKEY: 2441 return (dvd_read_disckey(cd, s)); 2442 case DVD_STRUCT_BCA: 2443 return (dvd_read_bca(cd, s)); 2444 case DVD_STRUCT_MANUFACT: 2445 return (dvd_read_manufact(cd, s)); 2446 default: 2447 return (EINVAL); 2448 } 2449} 2450 2451static int 2452cd_mode_sense(struct cd_softc *cd, u_int8_t byte2, void *sense, size_t size, 2453 int page, int flags, int *big) 2454{ 2455 2456 if (cd->sc_periph->periph_quirks & PQUIRK_ONLYBIG) { 2457 *big = 1; 2458 return scsipi_mode_sense_big(cd->sc_periph, byte2, page, sense, 2459 size + sizeof(struct scsi_mode_parameter_header_10), 2460 flags, CDRETRIES, 20000); 2461 } else { 2462 *big = 0; 2463 return scsipi_mode_sense(cd->sc_periph, byte2, page, sense, 2464 size + sizeof(struct scsi_mode_parameter_header_6), 2465 flags, CDRETRIES, 20000); 2466 } 2467} 2468 2469static int 2470cd_mode_select(struct cd_softc *cd, u_int8_t byte2, void *sense, size_t size, 2471 int flags, int big) 2472{ 2473 2474 if (big) { 2475 struct scsi_mode_parameter_header_10 *header = sense; 2476 2477 _lto2b(0, header->data_length); 2478 return scsipi_mode_select_big(cd->sc_periph, byte2, sense, 2479 size + sizeof(struct scsi_mode_parameter_header_10), 2480 flags, CDRETRIES, 20000); 2481 } else { 2482 struct scsi_mode_parameter_header_6 *header = sense; 2483 2484 header->data_length = 0; 2485 return scsipi_mode_select(cd->sc_periph, byte2, sense, 2486 size + sizeof(struct scsi_mode_parameter_header_6), 2487 flags, CDRETRIES, 20000); 2488 } 2489} 2490 2491static int 2492cd_set_pa_immed(struct cd_softc *cd, int flags) 2493{ 2494 struct { 2495 union { 2496 struct scsi_mode_parameter_header_6 small; 2497 struct scsi_mode_parameter_header_10 big; 2498 } header; 2499 struct cd_audio_page page; 2500 } data; 2501 int error; 2502 uint8_t oflags; 2503 int big, byte2; 2504 struct cd_audio_page *page; 2505 2506 byte2 = SMS_DBD; 2507try_again: 2508 if ((error = cd_mode_sense(cd, byte2, &data, sizeof(data.page), 2509 AUDIO_PAGE, flags, &big)) != 0) { 2510 if (byte2 == SMS_DBD) { 2511 /* Device may not understand DBD; retry without */ 2512 byte2 = 0; 2513 goto try_again; 2514 } 2515 return (error); 2516 } 2517 2518 if (big) 2519 page = (void *)((u_long)&data.header.big + 2520 sizeof data.header.big + 2521 _2btol(data.header.big.blk_desc_len)); 2522 else 2523 page = (void *)((u_long)&data.header.small + 2524 sizeof data.header.small + 2525 data.header.small.blk_desc_len); 2526 2527 oflags = page->flags; 2528 page->flags &= ~CD_PA_SOTC; 2529 page->flags |= CD_PA_IMMED; 2530 if (oflags == page->flags) 2531 return (0); 2532 2533 return (cd_mode_select(cd, SMS_PF, &data, 2534 sizeof(struct scsi_mode_page_header) + page->pg_length, 2535 flags, big)); 2536} 2537 2538static int 2539cd_setchan(struct cd_softc *cd, int p0, int p1, int p2, int p3, int flags) 2540{ 2541 struct { 2542 union { 2543 struct scsi_mode_parameter_header_6 small; 2544 struct scsi_mode_parameter_header_10 big; 2545 } header; 2546 struct cd_audio_page page; 2547 } data; 2548 int error; 2549 int big, byte2; 2550 struct cd_audio_page *page; 2551 2552 byte2 = SMS_DBD; 2553try_again: 2554 if ((error = cd_mode_sense(cd, byte2, &data, sizeof(data.page), 2555 AUDIO_PAGE, flags, &big)) != 0) { 2556 if (byte2 == SMS_DBD) { 2557 /* Device may not understand DBD; retry without */ 2558 byte2 = 0; 2559 goto try_again; 2560 } 2561 return (error); 2562 } 2563 2564 if (big) 2565 page = (void *)((u_long)&data.header.big + 2566 sizeof data.header.big + 2567 _2btol(data.header.big.blk_desc_len)); 2568 else 2569 page = (void *)((u_long)&data.header.small + 2570 sizeof data.header.small + 2571 data.header.small.blk_desc_len); 2572 2573 page->port[0].channels = p0; 2574 page->port[1].channels = p1; 2575 page->port[2].channels = p2; 2576 page->port[3].channels = p3; 2577 2578 return (cd_mode_select(cd, SMS_PF, &data, 2579 sizeof(struct scsi_mode_page_header) + page->pg_length, 2580 flags, big)); 2581} 2582 2583static int 2584cd_getvol(struct cd_softc *cd, struct ioc_vol *arg, int flags) 2585{ 2586 struct { 2587 union { 2588 struct scsi_mode_parameter_header_6 small; 2589 struct scsi_mode_parameter_header_10 big; 2590 } header; 2591 struct cd_audio_page page; 2592 } data; 2593 int error; 2594 int big, byte2; 2595 struct cd_audio_page *page; 2596 2597 byte2 = SMS_DBD; 2598try_again: 2599 if ((error = cd_mode_sense(cd, byte2, &data, sizeof(data.page), 2600 AUDIO_PAGE, flags, &big)) != 0) { 2601 if (byte2 == SMS_DBD) { 2602 /* Device may not understand DBD; retry without */ 2603 byte2 = 0; 2604 goto try_again; 2605 } 2606 return (error); 2607 } 2608 2609 if (big) 2610 page = (void *)((u_long)&data.header.big + 2611 sizeof data.header.big + 2612 _2btol(data.header.big.blk_desc_len)); 2613 else 2614 page = (void *)((u_long)&data.header.small + 2615 sizeof data.header.small + 2616 data.header.small.blk_desc_len); 2617 2618 arg->vol[0] = page->port[0].volume; 2619 arg->vol[1] = page->port[1].volume; 2620 arg->vol[2] = page->port[2].volume; 2621 arg->vol[3] = page->port[3].volume; 2622 2623 return (0); 2624} 2625 2626static int 2627cd_setvol(struct cd_softc *cd, const struct ioc_vol *arg, int flags) 2628{ 2629 struct { 2630 union { 2631 struct scsi_mode_parameter_header_6 small; 2632 struct scsi_mode_parameter_header_10 big; 2633 } header; 2634 struct cd_audio_page page; 2635 } data, mask; 2636 int error; 2637 int big, byte2; 2638 struct cd_audio_page *page, *page2; 2639 2640 byte2 = SMS_DBD; 2641try_again: 2642 if ((error = cd_mode_sense(cd, byte2, &data, sizeof(data.page), 2643 AUDIO_PAGE, flags, &big)) != 0) { 2644 if (byte2 == SMS_DBD) { 2645 /* Device may not understand DBD; retry without */ 2646 byte2 = 0; 2647 goto try_again; 2648 } 2649 return (error); 2650 } 2651 if ((error = cd_mode_sense(cd, byte2, &mask, sizeof(mask.page), 2652 AUDIO_PAGE|SMS_PCTRL_CHANGEABLE, flags, &big)) != 0) 2653 return (error); 2654 2655 if (big) { 2656 page = (void *)((u_long)&data.header.big + 2657 sizeof data.header.big + 2658 _2btol(data.header.big.blk_desc_len)); 2659 page2 = (void *)((u_long)&mask.header.big + 2660 sizeof mask.header.big + 2661 _2btol(mask.header.big.blk_desc_len)); 2662 } else { 2663 page = (void *)((u_long)&data.header.small + 2664 sizeof data.header.small + 2665 data.header.small.blk_desc_len); 2666 page2 = (void *)((u_long)&mask.header.small + 2667 sizeof mask.header.small + 2668 mask.header.small.blk_desc_len); 2669 } 2670 2671 page->port[0].volume = arg->vol[0] & page2->port[0].volume; 2672 page->port[1].volume = arg->vol[1] & page2->port[1].volume; 2673 page->port[2].volume = arg->vol[2] & page2->port[2].volume; 2674 page->port[3].volume = arg->vol[3] & page2->port[3].volume; 2675 2676 page->port[0].channels = CHANNEL_0; 2677 page->port[1].channels = CHANNEL_1; 2678 2679 return (cd_mode_select(cd, SMS_PF, &data, 2680 sizeof(struct scsi_mode_page_header) + page->pg_length, 2681 flags, big)); 2682} 2683 2684static int 2685cd_load_unload(struct cd_softc *cd, struct ioc_load_unload *args) 2686{ 2687 struct scsipi_load_unload cmd; 2688 2689 memset(&cmd, 0, sizeof(cmd)); 2690 cmd.opcode = LOAD_UNLOAD; 2691 cmd.options = args->options; /* ioctl uses MMC values */ 2692 cmd.slot = args->slot; 2693 2694 return (scsipi_command(cd->sc_periph, (void *)&cmd, sizeof(cmd), 0, 0, 2695 CDRETRIES, 200000, NULL, 0)); 2696} 2697 2698static int 2699cd_setblksize(struct cd_softc *cd) 2700{ 2701 struct { 2702 union { 2703 struct scsi_mode_parameter_header_6 small; 2704 struct scsi_mode_parameter_header_10 big; 2705 } header; 2706 struct scsi_general_block_descriptor blk_desc; 2707 } data; 2708 int error; 2709 int big, bsize; 2710 struct scsi_general_block_descriptor *bdesc; 2711 2712 if ((error = cd_mode_sense(cd, 0, &data, sizeof(data.blk_desc), 0, 0, 2713 &big)) != 0) 2714 return (error); 2715 2716 if (big) { 2717 bdesc = (void *)(&data.header.big + 1); 2718 bsize = _2btol(data.header.big.blk_desc_len); 2719 } else { 2720 bdesc = (void *)(&data.header.small + 1); 2721 bsize = data.header.small.blk_desc_len; 2722 } 2723 2724 if (bsize == 0) { 2725printf("cd_setblksize: trying to change bsize, but no blk_desc\n"); 2726 return (EINVAL); 2727 } 2728 if (_3btol(bdesc->blklen) == 2048) { 2729printf("cd_setblksize: trying to change bsize, but blk_desc is correct\n"); 2730 return (EINVAL); 2731 } 2732 2733 _lto3b(2048, bdesc->blklen); 2734 2735 return (cd_mode_select(cd, SMS_PF, &data, sizeof(data.blk_desc), 0, 2736 big)); 2737} 2738 2739 2740static int 2741mmc_profile2class(uint16_t mmc_profile) 2742{ 2743 switch (mmc_profile) { 2744 case 0x01 : /* SCSI discs */ 2745 case 0x02 : 2746 /* this can't happen really, cd.c wouldn't have matched */ 2747 return MMC_CLASS_DISC; 2748 case 0x03 : /* Magneto Optical with sector erase */ 2749 case 0x04 : /* Magneto Optical write once */ 2750 case 0x05 : /* Advance Storage Magneto Optical */ 2751 return MMC_CLASS_MO; 2752 case 0x00 : /* Unknown MMC profile, can also be CD-ROM */ 2753 case 0x08 : /* CD-ROM */ 2754 case 0x09 : /* CD-R */ 2755 case 0x0a : /* CD-RW */ 2756 return MMC_CLASS_CD; 2757 case 0x10 : /* DVD-ROM */ 2758 case 0x11 : /* DVD-R */ 2759 case 0x12 : /* DVD-RAM */ 2760 case 0x13 : /* DVD-RW restricted overwrite */ 2761 case 0x14 : /* DVD-RW sequential */ 2762 case 0x1a : /* DVD+RW */ 2763 case 0x1b : /* DVD+R */ 2764 case 0x2a : /* DVD+RW Dual layer */ 2765 case 0x2b : /* DVD+R Dual layer */ 2766 case 0x50 : /* HD DVD-ROM */ 2767 case 0x51 : /* HD DVD-R */ 2768 case 0x52 : /* HD DVD-RW; DVD-RAM like */ 2769 return MMC_CLASS_DVD; 2770 case 0x40 : /* BD-ROM */ 2771 case 0x41 : /* BD-R Sequential recording (SRM) */ 2772 case 0x42 : /* BD-R Ramdom Recording (RRM) */ 2773 case 0x43 : /* BD-RE */ 2774 return MMC_CLASS_BD; 2775 } 2776 return MMC_CLASS_UNKN; 2777} 2778 2779 2780/* 2781 * Drive/media combination is reflected in a series of features that can 2782 * either be current or dormant. We try to make sense out of them to create a 2783 * set of easy to use flags that abstract the device/media capabilities. 2784 */ 2785 2786static void 2787mmc_process_feature(struct mmc_discinfo *mmc_discinfo, 2788 uint16_t feature, int cur, uint8_t *rpos) 2789{ 2790 uint32_t blockingnr; 2791 uint64_t flags; 2792 2793 if (cur == 1) { 2794 flags = mmc_discinfo->mmc_cur; 2795 } else { 2796 flags = mmc_discinfo->mmc_cap; 2797 } 2798 2799 switch (feature) { 2800 case 0x0010 : /* random readable feature */ 2801 blockingnr = rpos[5] | (rpos[4] << 8); 2802 if (blockingnr > 1) 2803 flags |= MMC_CAP_PACKET; 2804 2805 /* RW error page */ 2806 break; 2807 case 0x0020 : /* random writable feature */ 2808 flags |= MMC_CAP_RECORDABLE; 2809 flags |= MMC_CAP_REWRITABLE; 2810 blockingnr = rpos[9] | (rpos[8] << 8); 2811 if (blockingnr > 1) 2812 flags |= MMC_CAP_PACKET; 2813 break; 2814 case 0x0021 : /* incremental streaming write feature */ 2815 flags |= MMC_CAP_RECORDABLE; 2816 flags |= MMC_CAP_SEQUENTIAL; 2817 if (cur) 2818 mmc_discinfo->link_block_penalty = rpos[4]; 2819 if (rpos[2] & 1) 2820 flags |= MMC_CAP_ZEROLINKBLK; 2821 break; 2822 case 0x0022 : /* (obsolete) erase support feature */ 2823 flags |= MMC_CAP_RECORDABLE; 2824 flags |= MMC_CAP_ERASABLE; 2825 break; 2826 case 0x0023 : /* formatting media support feature */ 2827 flags |= MMC_CAP_RECORDABLE; 2828 flags |= MMC_CAP_FORMATTABLE; 2829 break; 2830 case 0x0024 : /* hardware assised defect management feature */ 2831 flags |= MMC_CAP_HW_DEFECTFREE; 2832 break; 2833 case 0x0025 : /* write once */ 2834 flags |= MMC_CAP_RECORDABLE; 2835 break; 2836 case 0x0026 : /* restricted overwrite feature */ 2837 flags |= MMC_CAP_RECORDABLE; 2838 flags |= MMC_CAP_REWRITABLE; 2839 flags |= MMC_CAP_STRICTOVERWRITE; 2840 break; 2841 case 0x0028 : /* MRW formatted media support feature */ 2842 flags |= MMC_CAP_MRW; 2843 break; 2844 case 0x002b : /* DVD+R read (and opt. write) support */ 2845 flags |= MMC_CAP_SEQUENTIAL; 2846 if (rpos[0] & 1) /* write support */ 2847 flags |= MMC_CAP_RECORDABLE; 2848 break; 2849 case 0x002c : /* rigid restricted overwrite feature */ 2850 flags |= MMC_CAP_RECORDABLE; 2851 flags |= MMC_CAP_REWRITABLE; 2852 flags |= MMC_CAP_STRICTOVERWRITE; 2853 if (rpos[0] & 1) /* blank bit */ 2854 flags |= MMC_CAP_BLANKABLE; 2855 break; 2856 case 0x002d : /* track at once recording feature */ 2857 flags |= MMC_CAP_RECORDABLE; 2858 flags |= MMC_CAP_SEQUENTIAL; 2859 break; 2860 case 0x002f : /* DVD-R/-RW write feature */ 2861 flags |= MMC_CAP_RECORDABLE; 2862 if (rpos[0] & 2) /* DVD-RW bit */ 2863 flags |= MMC_CAP_BLANKABLE; 2864 break; 2865 case 0x0038 : /* BD-R SRM with pseudo overwrite */ 2866 flags |= MMC_CAP_PSEUDOOVERWRITE; 2867 break; 2868 default : 2869 /* ignore */ 2870 break; 2871 } 2872 2873 if (cur == 1) { 2874 mmc_discinfo->mmc_cur = flags; 2875 } else { 2876 mmc_discinfo->mmc_cap = flags; 2877 } 2878} 2879 2880static int 2881mmc_getdiscinfo_cdrom(struct scsipi_periph *periph, 2882 struct mmc_discinfo *mmc_discinfo) 2883{ 2884 struct scsipi_read_toc gtoc_cmd; 2885 struct scsipi_toc_header *toc_hdr; 2886 struct scsipi_toc_msinfo *toc_msinfo; 2887 const uint32_t buffer_size = 1024; 2888 uint32_t req_size; 2889 uint8_t *buffer; 2890 int error, flags; 2891 2892 buffer = malloc(buffer_size, M_TEMP, M_WAITOK); 2893 /* 2894 * Fabricate mmc_discinfo for CD-ROM. Some values are really `dont 2895 * care' but others might be of interest to programs. 2896 */ 2897 2898 mmc_discinfo->disc_state = MMC_STATE_FULL; 2899 mmc_discinfo->last_session_state = MMC_STATE_FULL; 2900 mmc_discinfo->bg_format_state = MMC_BGFSTATE_COMPLETED; 2901 mmc_discinfo->link_block_penalty = 7; /* not relevant */ 2902 2903 /* get number of sessions and first tracknr in last session */ 2904 flags = XS_CTL_DATA_IN; 2905 memset(>oc_cmd, 0, sizeof(gtoc_cmd)); 2906 gtoc_cmd.opcode = READ_TOC; 2907 gtoc_cmd.addr_mode = CD_MSF; /* not relevant */ 2908 gtoc_cmd.resp_format = CD_TOC_MSINFO; /* multisession info */ 2909 gtoc_cmd.from_track = 0; /* reserved, must be 0 */ 2910 req_size = sizeof(*toc_hdr) + sizeof(*toc_msinfo); 2911 _lto2b(req_size, gtoc_cmd.data_len); 2912 2913 error = scsipi_command(periph, 2914 (void *)>oc_cmd, sizeof(gtoc_cmd), 2915 (void *)buffer, req_size, 2916 CDRETRIES, 30000, NULL, flags); 2917 if (error) 2918 goto out; 2919 toc_hdr = (struct scsipi_toc_header *) buffer; 2920 toc_msinfo = (struct scsipi_toc_msinfo *) (buffer + 4); 2921 mmc_discinfo->num_sessions = toc_hdr->last - toc_hdr->first + 1; 2922 mmc_discinfo->first_track = toc_hdr->first; 2923 mmc_discinfo->first_track_last_session = toc_msinfo->tracknr; 2924 2925 /* get last track of last session */ 2926 flags = XS_CTL_DATA_IN; 2927 gtoc_cmd.resp_format = CD_TOC_FORM; /* formatted toc */ 2928 req_size = sizeof(*toc_hdr); 2929 _lto2b(req_size, gtoc_cmd.data_len); 2930 2931 error = scsipi_command(periph, 2932 (void *)>oc_cmd, sizeof(gtoc_cmd), 2933 (void *)buffer, req_size, 2934 CDRETRIES, 30000, NULL, flags); 2935 if (error) 2936 goto out; 2937 toc_hdr = (struct scsipi_toc_header *) buffer; 2938 mmc_discinfo->last_track_last_session = toc_hdr->last; 2939 mmc_discinfo->num_tracks = toc_hdr->last - toc_hdr->first + 1; 2940 2941 /* TODO how to handle disc_barcode and disc_id */ 2942 /* done */ 2943 2944out: 2945 free(buffer, M_TEMP); 2946 return error; 2947} 2948 2949static int 2950mmc_getdiscinfo_dvdrom(struct scsipi_periph *periph, 2951 struct mmc_discinfo *mmc_discinfo) 2952{ 2953 struct scsipi_read_toc gtoc_cmd; 2954 struct scsipi_toc_header toc_hdr; 2955 uint32_t req_size; 2956 int error, flags; 2957 2958 /* 2959 * Fabricate mmc_discinfo for DVD-ROM. Some values are really `dont 2960 * care' but others might be of interest to programs. 2961 */ 2962 2963 mmc_discinfo->disc_state = MMC_STATE_FULL; 2964 mmc_discinfo->last_session_state = MMC_STATE_FULL; 2965 mmc_discinfo->bg_format_state = MMC_BGFSTATE_COMPLETED; 2966 mmc_discinfo->link_block_penalty = 16; /* not relevant */ 2967 2968 /* get number of sessions and first tracknr in last session */ 2969 flags = XS_CTL_DATA_IN; 2970 memset(>oc_cmd, 0, sizeof(gtoc_cmd)); 2971 gtoc_cmd.opcode = READ_TOC; 2972 gtoc_cmd.addr_mode = 0; /* LBA */ 2973 gtoc_cmd.resp_format = CD_TOC_FORM; /* multisession info */ 2974 gtoc_cmd.from_track = 1; /* first track */ 2975 req_size = sizeof(toc_hdr); 2976 _lto2b(req_size, gtoc_cmd.data_len); 2977 2978 error = scsipi_command(periph, 2979 (void *)>oc_cmd, sizeof(gtoc_cmd), 2980 (void *)&toc_hdr, req_size, 2981 CDRETRIES, 30000, NULL, flags); 2982 if (error) 2983 return error; 2984 2985 /* DVD-ROM squashes the track/session space */ 2986 mmc_discinfo->num_sessions = toc_hdr.last - toc_hdr.first + 1; 2987 mmc_discinfo->num_tracks = mmc_discinfo->num_sessions; 2988 mmc_discinfo->first_track = toc_hdr.first; 2989 mmc_discinfo->first_track_last_session = toc_hdr.last; 2990 mmc_discinfo->last_track_last_session = toc_hdr.last; 2991 2992 /* TODO how to handle disc_barcode and disc_id */ 2993 /* done */ 2994 return 0; 2995} 2996 2997static int 2998mmc_getdiscinfo(struct scsipi_periph *periph, 2999 struct mmc_discinfo *mmc_discinfo) 3000{ 3001 struct scsipi_get_configuration gc_cmd; 3002 struct scsipi_get_conf_data *gc; 3003 struct scsipi_get_conf_feature *gcf; 3004 struct scsipi_read_discinfo di_cmd; 3005 struct scsipi_read_discinfo_data di; 3006 const uint32_t buffer_size = 1024; 3007 uint32_t feat_tbl_len, pos; 3008 u_long last_lba = 0; 3009 uint8_t *buffer, *fpos; 3010 int feature, last_feature, features_len, feature_cur, feature_len; 3011 int lsb, msb, error, flags; 3012 3013 feat_tbl_len = buffer_size; 3014 3015 buffer = malloc(buffer_size, M_TEMP, M_WAITOK); 3016 3017 /* initialise structure */ 3018 memset(mmc_discinfo, 0, sizeof(struct mmc_discinfo)); 3019 mmc_discinfo->mmc_profile = 0x00; /* unknown */ 3020 mmc_discinfo->mmc_class = MMC_CLASS_UNKN; 3021 mmc_discinfo->mmc_cur = 0; 3022 mmc_discinfo->mmc_cap = 0; 3023 mmc_discinfo->link_block_penalty = 0; 3024 3025 /* determine mmc profile and class */ 3026 flags = XS_CTL_DATA_IN; 3027 memset(&gc_cmd, 0, sizeof(gc_cmd)); 3028 gc_cmd.opcode = GET_CONFIGURATION; 3029 _lto2b(GET_CONF_NO_FEATURES_LEN, gc_cmd.data_len); 3030 3031 gc = (struct scsipi_get_conf_data *) buffer; 3032 3033 error = scsipi_command(periph, 3034 (void *)&gc_cmd, sizeof(gc_cmd), 3035 (void *) gc, GET_CONF_NO_FEATURES_LEN, 3036 CDRETRIES, 30000, NULL, flags); 3037 if (error) 3038 goto out; 3039 3040 mmc_discinfo->mmc_profile = _2btol(gc->mmc_profile); 3041 mmc_discinfo->mmc_class = mmc_profile2class(mmc_discinfo->mmc_profile); 3042 3043 /* assume 2048 sector size unless told otherwise */ 3044 mmc_discinfo->sector_size = 2048; 3045 error = read_cd_capacity(periph, &mmc_discinfo->sector_size, &last_lba); 3046 if (error) 3047 goto out; 3048 3049 mmc_discinfo->last_possible_lba = (uint32_t) last_lba; 3050 3051 /* Read in all features to determine device capabilities */ 3052 last_feature = feature = 0; 3053 do { 3054 /* determine mmc profile and class */ 3055 flags = XS_CTL_DATA_IN; 3056 memset(&gc_cmd, 0, sizeof(gc_cmd)); 3057 gc_cmd.opcode = GET_CONFIGURATION; 3058 _lto2b(last_feature, gc_cmd.start_at_feature); 3059 _lto2b(feat_tbl_len, gc_cmd.data_len); 3060 memset(gc, 0, feat_tbl_len); 3061 3062 error = scsipi_command(periph, 3063 (void *)&gc_cmd, sizeof(gc_cmd), 3064 (void *) gc, feat_tbl_len, 3065 CDRETRIES, 30000, NULL, flags); 3066 if (error) { 3067 /* ieeek... break out of loop... i dunno what to do */ 3068 break; 3069 } 3070 3071 features_len = _4btol(gc->data_len); 3072 if (features_len < 4 || features_len > feat_tbl_len) 3073 break; 3074 3075 pos = 0; 3076 fpos = &gc->feature_desc[0]; 3077 while (pos < features_len - 4) { 3078 gcf = (struct scsipi_get_conf_feature *) fpos; 3079 3080 feature = _2btol(gcf->featurecode); 3081 feature_cur = gcf->flags & 1; 3082 feature_len = gcf->additional_length; 3083 3084 mmc_process_feature(mmc_discinfo, 3085 feature, feature_cur, 3086 gcf->feature_dependent); 3087 3088 last_feature = MAX(last_feature, feature); 3089#ifdef DIAGNOSTIC 3090 /* assert((feature_len & 3) == 0); */ 3091 if ((feature_len & 3) != 0) { 3092 printf("feature %d having length %d\n", 3093 feature, feature_len); 3094 } 3095#endif 3096 3097 pos += 4 + feature_len; 3098 fpos += 4 + feature_len; 3099 } 3100 /* unlikely to ever grow past our 1kb buffer */ 3101 } while (features_len >= 0xffff); 3102 3103 /* 3104 * Fixup CD-RW drives that are on crack. 3105 * 3106 * Some drives report the capability to incrementally write 3107 * sequentially on CD-R(W) media... nice, but this should not be 3108 * active for a fixed packet formatted CD-RW media. Other report the 3109 * ability of HW_DEFECTFREE even when the media is NOT MRW 3110 * formatted.... 3111 */ 3112 if (mmc_discinfo->mmc_profile == 0x0a) { 3113 if ((mmc_discinfo->mmc_cur & MMC_CAP_SEQUENTIAL) == 0) 3114 mmc_discinfo->mmc_cur |= MMC_CAP_STRICTOVERWRITE; 3115 if (mmc_discinfo->mmc_cur & MMC_CAP_STRICTOVERWRITE) 3116 mmc_discinfo->mmc_cur &= ~MMC_CAP_SEQUENTIAL; 3117 if (mmc_discinfo->mmc_cur & MMC_CAP_MRW) { 3118 mmc_discinfo->mmc_cur &= ~MMC_CAP_SEQUENTIAL; 3119 mmc_discinfo->mmc_cur &= ~MMC_CAP_STRICTOVERWRITE; 3120 } else { 3121 mmc_discinfo->mmc_cur &= ~MMC_CAP_HW_DEFECTFREE; 3122 } 3123 } 3124 if (mmc_discinfo->mmc_profile == 0x09) { 3125 mmc_discinfo->mmc_cur &= ~MMC_CAP_REWRITABLE; 3126 } 3127 3128#ifdef DEBUG 3129 printf("CD mmc %d, mmc_cur 0x%"PRIx64", mmc_cap 0x%"PRIx64"\n", 3130 mmc_discinfo->mmc_profile, 3131 mmc_discinfo->mmc_cur, mmc_discinfo->mmc_cap); 3132#endif 3133 3134 /* read in disc state and number of sessions and tracks */ 3135 flags = XS_CTL_DATA_IN | XS_CTL_SILENT; 3136 memset(&di_cmd, 0, sizeof(di_cmd)); 3137 di_cmd.opcode = READ_DISCINFO; 3138 di_cmd.data_len[1] = READ_DISCINFO_BIGSIZE; 3139 3140 error = scsipi_command(periph, 3141 (void *)&di_cmd, sizeof(di_cmd), 3142 (void *)&di, READ_DISCINFO_BIGSIZE, 3143 CDRETRIES, 30000, NULL, flags); 3144 3145 if (error) { 3146 /* discinfo call failed, emulate for cd-rom/dvd-rom */ 3147 if (mmc_discinfo->mmc_profile == 0x08) /* CD-ROM */ 3148 return mmc_getdiscinfo_cdrom(periph, mmc_discinfo); 3149 if (mmc_discinfo->mmc_profile == 0x10) /* DVD-ROM */ 3150 return mmc_getdiscinfo_dvdrom(periph, mmc_discinfo); 3151 /* CD/DVD drive is violating specs */ 3152 error = EIO; 3153 goto out; 3154 } 3155 3156 /* call went OK */ 3157 mmc_discinfo->disc_state = di.disc_state & 3; 3158 mmc_discinfo->last_session_state = (di.disc_state >> 2) & 3; 3159 mmc_discinfo->bg_format_state = (di.disc_state2 & 3); 3160 3161 lsb = di.num_sessions_lsb; 3162 msb = di.num_sessions_msb; 3163 mmc_discinfo->num_sessions = lsb | (msb << 8); 3164 3165 mmc_discinfo->first_track = di.first_track; 3166 lsb = di.first_track_last_session_lsb; 3167 msb = di.first_track_last_session_msb; 3168 mmc_discinfo->first_track_last_session = lsb | (msb << 8); 3169 lsb = di.last_track_last_session_lsb; 3170 msb = di.last_track_last_session_msb; 3171 mmc_discinfo->last_track_last_session = lsb | (msb << 8); 3172 3173 mmc_discinfo->num_tracks = mmc_discinfo->last_track_last_session - 3174 mmc_discinfo->first_track + 1; 3175 3176 /* set misc. flags and parameters from this disc info */ 3177 if (di.disc_state & 16) 3178 mmc_discinfo->mmc_cur |= MMC_CAP_BLANKABLE; 3179 3180 if (di.disc_state2 & 128) { 3181 mmc_discinfo->disc_id = _4btol(di.discid); 3182 mmc_discinfo->disc_flags |= MMC_DFLAGS_DISCIDVALID; 3183 } 3184 if (di.disc_state2 & 64) { 3185 mmc_discinfo->disc_barcode = _8btol(di.disc_bar_code); 3186 mmc_discinfo->disc_flags |= MMC_DFLAGS_BARCODEVALID; 3187 } 3188 if (di.disc_state2 & 32) 3189 mmc_discinfo->disc_flags |= MMC_DFLAGS_UNRESTRICTED; 3190 3191 if (di.disc_state2 & 16) { 3192 mmc_discinfo->application_code = di.application_code; 3193 mmc_discinfo->disc_flags |= MMC_DFLAGS_APPCODEVALID; 3194 } 3195 3196 /* done */ 3197 3198out: 3199 free(buffer, M_TEMP); 3200 return error; 3201} 3202 3203static int 3204mmc_gettrackinfo_cdrom(struct scsipi_periph *periph, 3205 struct mmc_trackinfo *trackinfo) 3206{ 3207 struct scsipi_read_toc gtoc_cmd; 3208 struct scsipi_toc_header *toc_hdr; 3209 struct scsipi_toc_rawtoc *rawtoc; 3210 uint32_t track_start, track_size; 3211 uint32_t last_recorded, next_writable; 3212 uint32_t lba, next_track_start, lead_out; 3213 const uint32_t buffer_size = 4 * 1024; /* worst case TOC estimate */ 3214 uint8_t *buffer; 3215 uint8_t track_sessionnr, sessionnr, adr, tno, point; 3216 uint8_t control, tmin, tsec, tframe, pmin, psec, pframe; 3217 int size, req_size; 3218 int error, flags; 3219 3220 buffer = malloc(buffer_size, M_TEMP, M_WAITOK); 3221 3222 /* 3223 * Emulate read trackinfo for CD-ROM using the raw-TOC. 3224 * 3225 * Not all information is present and this presents a problem. Track 3226 * starts are known for each track but other values are deducted. 3227 * 3228 * For a complete overview of `magic' values used here, see the 3229 * SCSI/ATAPI MMC documentation. Note that the `magic' values have no 3230 * names, they are specified as numbers. 3231 */ 3232 3233 /* get raw toc to process, first header to check size */ 3234 flags = XS_CTL_DATA_IN | XS_CTL_SILENT; 3235 memset(>oc_cmd, 0, sizeof(gtoc_cmd)); 3236 gtoc_cmd.opcode = READ_TOC; 3237 gtoc_cmd.addr_mode = CD_MSF; /* not relevant */ 3238 gtoc_cmd.resp_format = CD_TOC_RAW; /* raw toc */ 3239 gtoc_cmd.from_track = 1; /* first session */ 3240 req_size = sizeof(*toc_hdr); 3241 _lto2b(req_size, gtoc_cmd.data_len); 3242 3243 error = scsipi_command(periph, 3244 (void *)>oc_cmd, sizeof(gtoc_cmd), 3245 (void *)buffer, req_size, 3246 CDRETRIES, 30000, NULL, flags); 3247 if (error) 3248 goto out; 3249 toc_hdr = (struct scsipi_toc_header *) buffer; 3250 if (_2btol(toc_hdr->length) > buffer_size - 2) { 3251#ifdef DIAGNOSTIC 3252 printf("increase buffersize in mmc_readtrackinfo_cdrom\n"); 3253#endif 3254 error = ENOBUFS; 3255 goto out; 3256 } 3257 3258 /* read in complete raw toc */ 3259 req_size = _2btol(toc_hdr->length); 3260 req_size = 2*((req_size + 1) / 2); /* for ATAPI */ 3261 _lto2b(req_size, gtoc_cmd.data_len); 3262 3263 error = scsipi_command(periph, 3264 (void *)>oc_cmd, sizeof(gtoc_cmd), 3265 (void *)buffer, req_size, 3266 CDRETRIES, 30000, NULL, flags); 3267 if (error) 3268 goto out; 3269 3270 toc_hdr = (struct scsipi_toc_header *) buffer; 3271 rawtoc = (struct scsipi_toc_rawtoc *) (buffer + 4); 3272 3273 track_start = 0; 3274 track_size = 0; 3275 last_recorded = 0; 3276 next_writable = 0; 3277 flags = 0; 3278 3279 next_track_start = 0; 3280 track_sessionnr = MAXTRACK; /* by definition */ 3281 lead_out = 0; 3282 3283 size = req_size - sizeof(struct scsipi_toc_header) + 1; 3284 while (size > 0) { 3285 /* get track start and session end */ 3286 tno = rawtoc->tno; 3287 sessionnr = rawtoc->sessionnr; 3288 adr = rawtoc->adrcontrol >> 4; 3289 control = rawtoc->adrcontrol & 0xf; 3290 point = rawtoc->point; 3291 tmin = rawtoc->min; 3292 tsec = rawtoc->sec; 3293 tframe = rawtoc->frame; 3294 pmin = rawtoc->pmin; 3295 psec = rawtoc->psec; 3296 pframe = rawtoc->pframe; 3297 3298 if (tno == 0 && sessionnr && adr == 1) { 3299 lba = hmsf2lba(0, pmin, psec, pframe); 3300 if (point == trackinfo->tracknr) { 3301 track_start = lba; 3302 track_sessionnr = sessionnr; 3303 } 3304 if (point == trackinfo->tracknr + 1) { 3305 /* estimate size */ 3306 track_size = lba - track_start; 3307 next_track_start = lba; 3308 } 3309 if (point == 0xa2) { 3310 lead_out = lba; 3311 } 3312 if (point <= 0x63) { 3313 /* CD's ok, DVD are glued */ 3314 /* last_tracknr = point; */ 3315 } 3316 if (sessionnr == track_sessionnr) { 3317 last_recorded = lead_out; 3318 } 3319 } 3320 if (tno == 0 && sessionnr && adr == 5) { 3321 lba = hmsf2lba(0, tmin, tsec, tframe); 3322 if (sessionnr == track_sessionnr) { 3323 next_writable = lba; 3324 } 3325 } 3326 3327 if ((control & (3<<2)) == 4) /* 01xxb */ 3328 flags |= MMC_TRACKINFO_DATA; 3329 if ((control & (1<<2)) == 0) { /* x0xxb */ 3330 flags |= MMC_TRACKINFO_AUDIO; 3331 if (control & 1) /* xxx1b */ 3332 flags |= MMC_TRACKINFO_PRE_EMPH; 3333 } 3334 3335 rawtoc++; 3336 size -= sizeof(struct scsipi_toc_rawtoc); 3337 } 3338 3339 /* process found values; some voodoo */ 3340 /* if no tracksize tracknr is the last of the disc */ 3341 if ((track_size == 0) && last_recorded) { 3342 track_size = last_recorded - track_start; 3343 } 3344 /* if last_recorded < tracksize, tracksize is overestimated */ 3345 if (last_recorded) { 3346 if (last_recorded - track_start <= track_size) { 3347 track_size = last_recorded - track_start; 3348 flags |= MMC_TRACKINFO_LRA_VALID; 3349 } 3350 } 3351 /* check if its a the last track of the sector */ 3352 if (next_writable) { 3353 if (next_track_start > next_writable) 3354 flags |= MMC_TRACKINFO_NWA_VALID; 3355 } 3356 3357 /* no flag set -> no values */ 3358 if ((flags & MMC_TRACKINFO_LRA_VALID) == 0) 3359 last_recorded = 0; 3360 if ((flags & MMC_TRACKINFO_NWA_VALID) == 0) 3361 next_writable = 0; 3362 3363 /* fill in */ 3364 /* trackinfo->tracknr preserved */ 3365 trackinfo->sessionnr = track_sessionnr; 3366 trackinfo->track_mode = 7; /* data, incremental */ 3367 trackinfo->data_mode = 8; /* 2048 bytes mode1 */ 3368 3369 trackinfo->flags = flags; 3370 trackinfo->track_start = track_start; 3371 trackinfo->next_writable = next_writable; 3372 trackinfo->free_blocks = 0; 3373 trackinfo->packet_size = 1; 3374 trackinfo->track_size = track_size; 3375 trackinfo->last_recorded = last_recorded; 3376 3377out: 3378 free(buffer, M_TEMP); 3379 return error; 3380 3381} 3382 3383static int 3384mmc_gettrackinfo_dvdrom(struct scsipi_periph *periph, 3385 struct mmc_trackinfo *trackinfo) 3386{ 3387 struct scsipi_read_toc gtoc_cmd; 3388 struct scsipi_toc_header *toc_hdr; 3389 struct scsipi_toc_formatted *toc; 3390 uint32_t tracknr, track_start, track_size; 3391 uint32_t lba, lead_out; 3392 const uint32_t buffer_size = 4 * 1024; /* worst case TOC estimate */ 3393 uint8_t *buffer; 3394 uint8_t control, last_tracknr; 3395 int size, req_size; 3396 int error, flags; 3397 3398 3399 buffer = malloc(buffer_size, M_TEMP, M_WAITOK); 3400 /* 3401 * Emulate read trackinfo for DVD-ROM. We can't use the raw-TOC as the 3402 * CD-ROM emulation uses since the specification tells us that no such 3403 * thing is defined for DVD's. The reason for this is due to the large 3404 * number of tracks and that would clash with the `magic' values. This 3405 * suxs. 3406 * 3407 * Not all information is present and this presents a problem. 3408 * Track starts are known for each track but other values are 3409 * deducted. 3410 */ 3411 3412 /* get formatted toc to process, first header to check size */ 3413 flags = XS_CTL_DATA_IN | XS_CTL_SILENT; 3414 memset(>oc_cmd, 0, sizeof(gtoc_cmd)); 3415 gtoc_cmd.opcode = READ_TOC; 3416 gtoc_cmd.addr_mode = 0; /* lba's please */ 3417 gtoc_cmd.resp_format = CD_TOC_FORM; /* formatted toc */ 3418 gtoc_cmd.from_track = 1; /* first track */ 3419 req_size = sizeof(*toc_hdr); 3420 _lto2b(req_size, gtoc_cmd.data_len); 3421 3422 error = scsipi_command(periph, 3423 (void *)>oc_cmd, sizeof(gtoc_cmd), 3424 (void *)buffer, req_size, 3425 CDRETRIES, 30000, NULL, flags); 3426 if (error) 3427 goto out; 3428 toc_hdr = (struct scsipi_toc_header *) buffer; 3429 if (_2btol(toc_hdr->length) > buffer_size - 2) { 3430#ifdef DIAGNOSTIC 3431 printf("incease buffersize in mmc_readtrackinfo_dvdrom\n"); 3432#endif 3433 error = ENOBUFS; 3434 goto out; 3435 } 3436 3437 /* read in complete formatted toc */ 3438 req_size = _2btol(toc_hdr->length); 3439 _lto2b(req_size, gtoc_cmd.data_len); 3440 3441 error = scsipi_command(periph, 3442 (void *)>oc_cmd, sizeof(gtoc_cmd), 3443 (void *)buffer, req_size, 3444 CDRETRIES, 30000, NULL, flags); 3445 if (error) 3446 goto out; 3447 3448 toc_hdr = (struct scsipi_toc_header *) buffer; 3449 toc = (struct scsipi_toc_formatted *) (buffer + 4); 3450 3451 /* as in read disc info, all sessions are converted to tracks */ 3452 /* track 1.. -> offsets, sizes can be (rougly) estimated (16 ECC) */ 3453 /* last track -> we got the size from the lead-out */ 3454 3455 tracknr = 0; 3456 last_tracknr = toc_hdr->last; 3457 track_start = 0; 3458 track_size = 0; 3459 lead_out = 0; 3460 flags = 0; 3461 3462 size = req_size - sizeof(struct scsipi_toc_header) + 1; 3463 while (size > 0) { 3464 /* remember, DVD-ROM: tracknr == sessionnr */ 3465 lba = _4btol(toc->msf_lba); 3466 tracknr = toc->tracknr; 3467 control = toc->adrcontrol & 0xf; 3468 3469 if (trackinfo->tracknr == tracknr) { 3470 track_start = lba; 3471 } 3472 if (trackinfo->tracknr == tracknr+1) { 3473 track_size = lba - track_start; 3474 track_size -= 16; /* link block ? */ 3475 } 3476 if (tracknr == 0xAA) { 3477 lead_out = lba; 3478 } 3479 3480 if ((control & (3<<2)) == 4) /* 01xxb */ 3481 flags |= MMC_TRACKINFO_DATA; 3482 if ((control & (1<<2)) == 0) { /* x0xxb */ 3483 flags |= MMC_TRACKINFO_AUDIO; 3484 if (control & (1<<3)) /* 10xxb */ 3485 flags |= MMC_TRACKINFO_AUDIO_4CHAN; 3486 if (control & 1) /* xxx1b */ 3487 flags |= MMC_TRACKINFO_PRE_EMPH; 3488 } 3489 3490 toc++; 3491 size -= sizeof(struct scsipi_toc_formatted); 3492 } 3493 if (trackinfo->tracknr == last_tracknr) { 3494 track_size = lead_out - track_start; 3495 } 3496 3497 /* fill in */ 3498 /* trackinfo->tracknr preserved */ 3499 trackinfo->sessionnr = trackinfo->tracknr; 3500 trackinfo->track_mode = 0; /* unknown */ 3501 trackinfo->data_mode = 8; /* 2048 bytes mode1 */ 3502 3503 trackinfo->flags = flags; 3504 trackinfo->track_start = track_start; 3505 trackinfo->next_writable = 0; 3506 trackinfo->free_blocks = 0; 3507 trackinfo->packet_size = 16; /* standard length 16 blocks ECC */ 3508 trackinfo->track_size = track_size; 3509 trackinfo->last_recorded = 0; 3510 3511out: 3512 free(buffer, M_TEMP); 3513 return error; 3514} 3515 3516static int 3517mmc_gettrackinfo(struct scsipi_periph *periph, 3518 struct mmc_trackinfo *trackinfo) 3519{ 3520 struct scsipi_read_trackinfo ti_cmd; 3521 struct scsipi_read_trackinfo_data ti; 3522 struct scsipi_get_configuration gc_cmd; 3523 struct scsipi_get_conf_data gc; 3524 int error, flags; 3525 int mmc_profile; 3526 3527 /* set up SCSI call with track number from trackinfo.tracknr */ 3528 flags = XS_CTL_DATA_IN | XS_CTL_SILENT; 3529 memset(&ti_cmd, 0, sizeof(ti_cmd)); 3530 ti_cmd.opcode = READ_TRACKINFO; 3531 ti_cmd.addr_type = READ_TRACKINFO_ADDR_TRACK; 3532 ti_cmd.data_len[1] = READ_TRACKINFO_RETURNSIZE; 3533 3534 /* trackinfo.tracknr contains number of tracks to query */ 3535 _lto4b(trackinfo->tracknr, ti_cmd.address); 3536 error = scsipi_command(periph, 3537 (void *)&ti_cmd, sizeof(ti_cmd), 3538 (void *)&ti, READ_TRACKINFO_RETURNSIZE, 3539 CDRETRIES, 30000, NULL, flags); 3540 3541 if (error) { 3542 /* trackinfo call failed, emulate for cd-rom/dvd-rom */ 3543 /* first determine mmc profile */ 3544 flags = XS_CTL_DATA_IN; 3545 memset(&gc_cmd, 0, sizeof(gc_cmd)); 3546 gc_cmd.opcode = GET_CONFIGURATION; 3547 _lto2b(GET_CONF_NO_FEATURES_LEN, gc_cmd.data_len); 3548 3549 error = scsipi_command(periph, 3550 (void *)&gc_cmd, sizeof(gc_cmd), 3551 (void *)&gc, GET_CONF_NO_FEATURES_LEN, 3552 CDRETRIES, 30000, NULL, flags); 3553 if (error) 3554 return error; 3555 mmc_profile = _2btol(gc.mmc_profile); 3556 3557 /* choose emulation */ 3558 if (mmc_profile == 0x08) /* CD-ROM */ 3559 return mmc_gettrackinfo_cdrom(periph, trackinfo); 3560 if (mmc_profile == 0x10) /* DVD-ROM */ 3561 return mmc_gettrackinfo_dvdrom(periph, trackinfo); 3562 /* CD/DVD drive is violating specs */ 3563 return EIO; 3564 } 3565 3566 /* (re)initialise structure */ 3567 memset(trackinfo, 0, sizeof(struct mmc_trackinfo)); 3568 3569 /* account for short returns screwing up track and session msb */ 3570 if ((ti.data_len[1] | (ti.data_len[0] << 8)) <= 32) { 3571 ti.track_msb = 0; 3572 ti.session_msb = 0; 3573 } 3574 3575 trackinfo->tracknr = ti.track_lsb | (ti.track_msb << 8); 3576 trackinfo->sessionnr = ti.session_lsb | (ti.session_msb << 8); 3577 trackinfo->track_mode = ti.track_info_1 & 0xf; 3578 trackinfo->data_mode = ti.track_info_2 & 0xf; 3579 3580 flags = 0; 3581 if (ti.track_info_1 & 0x10) 3582 flags |= MMC_TRACKINFO_COPY; 3583 if (ti.track_info_1 & 0x20) 3584 flags |= MMC_TRACKINFO_DAMAGED; 3585 if (ti.track_info_2 & 0x10) 3586 flags |= MMC_TRACKINFO_FIXED_PACKET; 3587 if (ti.track_info_2 & 0x20) 3588 flags |= MMC_TRACKINFO_INCREMENTAL; 3589 if (ti.track_info_2 & 0x40) 3590 flags |= MMC_TRACKINFO_BLANK; 3591 if (ti.track_info_2 & 0x80) 3592 flags |= MMC_TRACKINFO_RESERVED; 3593 if (ti.data_valid & 0x01) 3594 flags |= MMC_TRACKINFO_NWA_VALID; 3595 if (ti.data_valid & 0x02) 3596 flags |= MMC_TRACKINFO_LRA_VALID; 3597 if ((trackinfo->track_mode & (3<<2)) == 4) /* 01xxb */ 3598 flags |= MMC_TRACKINFO_DATA; 3599 if ((trackinfo->track_mode & (1<<2)) == 0) { /* x0xxb */ 3600 flags |= MMC_TRACKINFO_AUDIO; 3601 if (trackinfo->track_mode & (1<<3)) /* 10xxb */ 3602 flags |= MMC_TRACKINFO_AUDIO_4CHAN; 3603 if (trackinfo->track_mode & 1) /* xxx1b */ 3604 flags |= MMC_TRACKINFO_PRE_EMPH; 3605 } 3606 3607 trackinfo->flags = flags; 3608 trackinfo->track_start = _4btol(ti.track_start); 3609 trackinfo->next_writable = _4btol(ti.next_writable); 3610 trackinfo->free_blocks = _4btol(ti.free_blocks); 3611 trackinfo->packet_size = _4btol(ti.packet_size); 3612 trackinfo->track_size = _4btol(ti.track_size); 3613 trackinfo->last_recorded = _4btol(ti.last_recorded); 3614 3615 return 0; 3616} 3617 3618static int 3619mmc_doclose(struct scsipi_periph *periph, int param, int func) { 3620 struct scsipi_close_tracksession close_cmd; 3621 int error, flags; 3622 3623 /* set up SCSI call with track number */ 3624 flags = XS_CTL_DATA_OUT; 3625 memset(&close_cmd, 0, sizeof(close_cmd)); 3626 close_cmd.opcode = CLOSE_TRACKSESSION; 3627 close_cmd.function = func; 3628 _lto2b(param, close_cmd.tracksessionnr); 3629 3630 error = scsipi_command(periph, 3631 (void *) &close_cmd, sizeof(close_cmd), 3632 NULL, 0, 3633 CDRETRIES, 120000, NULL, flags); 3634 3635 return error; 3636} 3637 3638static int 3639mmc_do_closetrack(struct scsipi_periph *periph, struct mmc_op *mmc_op) 3640{ 3641 int mmc_profile = mmc_op->mmc_profile; 3642 3643 switch (mmc_profile) { 3644 case 0x12 : /* DVD-RAM */ 3645 case 0x1a : /* DVD+RW */ 3646 case 0x2a : /* DVD+RW Dual layer */ 3647 case 0x42 : /* BD-R Ramdom Recording (RRM) */ 3648 case 0x43 : /* BD-RE */ 3649 case 0x52 : /* HD DVD-RW ; DVD-RAM like */ 3650 return EINVAL; 3651 } 3652 3653 return mmc_doclose(periph, mmc_op->tracknr, 1); 3654} 3655 3656static int 3657mmc_do_close_or_finalise(struct scsipi_periph *periph, struct mmc_op *mmc_op) 3658{ 3659 uint8_t blob[MS5LEN], *page5; 3660 int mmc_profile = mmc_op->mmc_profile; 3661 int func, close, flags; 3662 int error; 3663 3664 close = (mmc_op->operation == MMC_OP_CLOSESESSION); 3665 3666 switch (mmc_profile) { 3667 case 0x09 : /* CD-R */ 3668 case 0x0a : /* CD-RW */ 3669 /* Special case : need to update MS field in mode page 5 */ 3670 memset(blob, 0, sizeof(blob)); 3671 page5 = blob+8; 3672 3673 flags = XS_CTL_DATA_IN; 3674 error = scsipi_mode_sense_big(periph, SMS_PF, 5, 3675 (void *)blob, sizeof(blob), flags, CDRETRIES, 20000); 3676 if (error) 3677 return error; 3678 3679 /* set multi session field when closing a session only */ 3680 page5[3] &= 63; 3681 if (close) 3682 page5[3] |= 3 << 6; 3683 3684 flags = XS_CTL_DATA_OUT; 3685 error = scsipi_mode_select_big(periph, SMS_PF, 3686 (void *)blob, sizeof(blob), flags, CDRETRIES, 20000); 3687 if (error) 3688 return error; 3689 /* and use funtion 2 */ 3690 func = 2; 3691 break; 3692 case 0x11 : /* DVD-R (DL) */ 3693 case 0x13 : /* DVD-RW restricted overwrite */ 3694 case 0x14 : /* DVD-RW sequential */ 3695 func = close ? 2 : 3; 3696 break; 3697 case 0x1b : /* DVD+R */ 3698 case 0x2b : /* DVD+R Dual layer */ 3699 case 0x51 : /* HD DVD-R */ 3700 case 0x41 : /* BD-R Sequential recording (SRM) */ 3701 func = close ? 2 : 6; 3702 break; 3703 case 0x12 : /* DVD-RAM */ 3704 case 0x1a : /* DVD+RW */ 3705 case 0x2a : /* DVD+RW Dual layer */ 3706 case 0x42 : /* BD-R Ramdom Recording (RRM) */ 3707 case 0x43 : /* BD-RE */ 3708 case 0x52 : /* HD DVD-RW; DVD-RAM like */ 3709 return EINVAL; 3710 default: 3711 printf("MMC close/finalise passed wrong device type! (%d)\n", 3712 mmc_profile); 3713 return EINVAL; 3714 } 3715 3716 return mmc_doclose(periph, mmc_op->sessionnr, func); 3717} 3718 3719static int 3720mmc_do_reserve_track(struct scsipi_periph *periph, struct mmc_op *mmc_op) 3721{ 3722 struct scsipi_reserve_track reserve_cmd; 3723 uint32_t extent; 3724 int error, flags; 3725 3726 /* TODO make mmc safeguards? */ 3727 extent = mmc_op->extent; 3728 /* TODO min/max support? */ 3729 3730 /* set up SCSI call with requested space */ 3731 flags = XS_CTL_DATA_OUT; 3732 memset(&reserve_cmd, 0, sizeof(reserve_cmd)); 3733 reserve_cmd.opcode = RESERVE_TRACK; 3734 _lto4b(extent, reserve_cmd.reservation_size); 3735 3736 error = scsipi_command(periph, 3737 (void *) &reserve_cmd, sizeof(reserve_cmd), 3738 NULL, 0, 3739 CDRETRIES, 30000, NULL, flags); 3740 3741 return error; 3742} 3743 3744static int 3745mmc_do_reserve_track_nwa(struct scsipi_periph *periph, struct mmc_op *mmc_op) 3746{ 3747 /* XXX assumes that NWA given is valid */ 3748 switch (mmc_op->mmc_profile) { 3749 case 0x09 : /* CD-R */ 3750 /* XXX unknown boundary checks XXX */ 3751 if (mmc_op->extent <= 152) 3752 return EINVAL; 3753 /* CD-R takes 152 sectors to close track */ 3754 mmc_op->extent -= 152; 3755 return mmc_do_reserve_track(periph, mmc_op); 3756 case 0x11 : /* DVD-R (DL) */ 3757 case 0x1b : /* DVD+R */ 3758 case 0x2b : /* DVD+R Dual layer */ 3759 if (mmc_op->extent % 16) 3760 return EINVAL; 3761 /* upto one ECC block of 16 sectors lost */ 3762 mmc_op->extent -= 16; 3763 return mmc_do_reserve_track(periph, mmc_op); 3764 case 0x41 : /* BD-R Sequential recording (SRM) */ 3765 case 0x51 : /* HD DVD-R */ 3766 if (mmc_op->extent % 32) 3767 return EINVAL; 3768 /* one ECC block of 32 sectors lost (AFAIK) */ 3769 mmc_op->extent -= 32; 3770 return mmc_do_reserve_track(periph, mmc_op); 3771 } 3772 3773 /* unknown behaviour or invalid disc type */ 3774 return EINVAL; 3775} 3776 3777static int 3778mmc_do_repair_track(struct scsipi_periph *periph, struct mmc_op *mmc_op) 3779{ 3780 struct scsipi_repair_track repair_cmd; 3781 int error, flags; 3782 3783 /* TODO make mmc safeguards? */ 3784 3785 /* set up SCSI call with track number */ 3786 flags = XS_CTL_DATA_OUT; 3787 memset(&repair_cmd, 0, sizeof(repair_cmd)); 3788 repair_cmd.opcode = REPAIR_TRACK; 3789 _lto2b(mmc_op->tracknr, repair_cmd.tracknr); 3790 3791 error = scsipi_command(periph, 3792 (void *) &repair_cmd, sizeof(repair_cmd), 3793 NULL, 0, 3794 CDRETRIES, 30000, NULL, flags); 3795 3796 return error; 3797} 3798 3799static int 3800mmc_do_op(struct scsipi_periph *periph, struct mmc_op *mmc_op) 3801{ 3802 /* guard operation value */ 3803 if (mmc_op->operation < 1 || mmc_op->operation > MMC_OP_MAX) 3804 return EINVAL; 3805 3806 /* synchronise cache is special since it doesn't rely on mmc_profile */ 3807 if (mmc_op->operation == MMC_OP_SYNCHRONISECACHE) 3808 return cdcachesync(periph, 0); 3809 3810 /* zero mmc_profile means unknown disc so operations are not defined */ 3811 if (mmc_op->mmc_profile == 0) { 3812#ifdef DEBUG 3813 printf("mmc_do_op called with mmc_profile = 0\n"); 3814#endif 3815 return EINVAL; 3816 } 3817 3818 /* do the operations */ 3819 switch (mmc_op->operation) { 3820 case MMC_OP_CLOSETRACK : 3821 return mmc_do_closetrack(periph, mmc_op); 3822 case MMC_OP_CLOSESESSION : 3823 case MMC_OP_FINALISEDISC : 3824 return mmc_do_close_or_finalise(periph, mmc_op); 3825 case MMC_OP_RESERVETRACK : 3826 return mmc_do_reserve_track(periph, mmc_op); 3827 case MMC_OP_RESERVETRACK_NWA : 3828 return mmc_do_reserve_track_nwa(periph, mmc_op); 3829 case MMC_OP_REPAIRTRACK : 3830 return mmc_do_repair_track(periph, mmc_op); 3831 case MMC_OP_UNCLOSELASTSESSION : 3832 /* TODO unclose last session support */ 3833 return EINVAL; 3834 default : 3835 printf("mmc_do_op: unhandled operation %d\n", mmc_op->operation); 3836 } 3837 3838 return EINVAL; 3839} 3840 3841static int 3842mmc_setup_writeparams(struct scsipi_periph *periph, 3843 struct mmc_writeparams *mmc_writeparams) 3844{ 3845 struct mmc_trackinfo trackinfo; 3846 uint8_t blob[MS5LEN]; 3847 uint8_t *page5; 3848 int flags, error; 3849 int track_mode, data_mode; 3850 3851 /* setup mode page 5 for CD only */ 3852 if (mmc_writeparams->mmc_class != MMC_CLASS_CD) 3853 return 0; 3854 3855 memset(blob, 0, sizeof(blob)); 3856 page5 = blob+8; 3857 3858 /* read mode page 5 (with header) */ 3859 flags = XS_CTL_DATA_IN; 3860 error = scsipi_mode_sense_big(periph, SMS_PF, 5, (void *)blob, 3861 sizeof(blob), flags, CDRETRIES, 20000); 3862 if (error) 3863 return error; 3864 3865 /* set page length for reasurance */ 3866 page5[1] = P5LEN; /* page length */ 3867 3868 /* write type packet/incremental */ 3869 page5[2] &= 0xf0; 3870 3871 /* set specified mode parameters */ 3872 track_mode = mmc_writeparams->track_mode; 3873 data_mode = mmc_writeparams->data_mode; 3874 if (track_mode <= 0 || track_mode > 15) 3875 return EINVAL; 3876 if (data_mode < 1 || data_mode > 2) 3877 return EINVAL; 3878 3879 /* if a tracknr is passed, setup according to the track */ 3880 if (mmc_writeparams->tracknr > 0) { 3881 trackinfo.tracknr = mmc_writeparams->tracknr; 3882 error = mmc_gettrackinfo(periph, &trackinfo); 3883 if (error) 3884 return error; 3885 if ((trackinfo.flags & MMC_TRACKINFO_BLANK) == 0) { 3886 track_mode = trackinfo.track_mode; 3887 data_mode = trackinfo.data_mode; 3888 } 3889 mmc_writeparams->blockingnr = trackinfo.packet_size; 3890 } 3891 3892 /* copy track mode and data mode from trackinfo */ 3893 page5[3] &= 16; /* keep only `Copy' bit */ 3894 page5[3] |= (3 << 6) | track_mode; 3895 page5[4] &= 0xf0; /* wipe data block type */ 3896 if (data_mode == 1) { 3897 /* select ISO mode 1 (CD only) */ 3898 page5[4] |= 8; 3899 /* select session format normal disc (CD only) */ 3900 page5[8] = 0; 3901 } else { 3902 /* select ISO mode 2; XA form 1 (CD only) */ 3903 page5[4] |= 10; 3904 /* select session format CD-ROM XA disc (CD only) */ 3905 page5[8] = 0x20; 3906 } 3907 if (mmc_writeparams->mmc_cur & MMC_CAP_SEQUENTIAL) { 3908 if (mmc_writeparams->mmc_cur & MMC_CAP_ZEROLINKBLK) { 3909 /* set BUFE buffer underrun protection */ 3910 page5[2] |= 1<<6; 3911 } 3912 /* allow for multi session */ 3913 page5[3] |= 3 << 6; 3914 } else { 3915 /* select fixed packets */ 3916 page5[3] |= 1<<5; 3917 _lto4b(mmc_writeparams->blockingnr, &(page5[10])); 3918 } 3919 3920 /* write out updated mode page 5 (with header) */ 3921 flags = XS_CTL_DATA_OUT; 3922 error = scsipi_mode_select_big(periph, SMS_PF, (void *)blob, 3923 sizeof(blob), flags, CDRETRIES, 20000); 3924 if (error) 3925 return error; 3926 3927 return 0; 3928} 3929 3930static void 3931cd_set_geometry(struct cd_softc *cd) 3932{ 3933 struct disk_geom *dg = &cd->sc_dk.dk_geom; 3934 3935 memset(dg, 0, sizeof(*dg)); 3936 3937 dg->dg_secperunit = cd->params.disksize; 3938 dg->dg_secsize = cd->params.blksize; 3939 3940 disk_set_info(cd->sc_dev, &cd->sc_dk, NULL); 3941} 3942