cd.c revision 1.107
1/* $NetBSD: cd.c,v 1.107 1997/10/18 19:50:51 thorpej Exp $ */ 2 3/* 4 * Copyright (c) 1994, 1995, 1997 Charles M. Hannum. All rights reserved. 5 * 6 * Redistribution and use in source and binary forms, with or without 7 * modification, are permitted provided that the following conditions 8 * are met: 9 * 1. Redistributions of source code must retain the above copyright 10 * notice, this list of conditions and the following disclaimer. 11 * 2. Redistributions in binary form must reproduce the above copyright 12 * notice, this list of conditions and the following disclaimer in the 13 * documentation and/or other materials provided with the distribution. 14 * 3. All advertising materials mentioning features or use of this software 15 * must display the following acknowledgement: 16 * This product includes software developed by Charles M. Hannum. 17 * 4. The name of the author may not be used to endorse or promote products 18 * derived from this software without specific prior written permission. 19 * 20 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 21 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 22 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 23 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 24 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 25 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 26 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 27 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 28 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 29 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 30 */ 31 32/* 33 * Originally written by Julian Elischer (julian@tfs.com) 34 * for TRW Financial Systems for use under the MACH(2.5) operating system. 35 * 36 * TRW Financial Systems, in accordance with their agreement with Carnegie 37 * Mellon University, makes this software available to CMU to distribute 38 * or use in any manner that they see fit as long as this message is kept with 39 * the software. For this reason TFS also grants any other persons or 40 * organisations permission to use or modify this software. 41 * 42 * TFS supplies this software to be publicly redistributed 43 * on the understanding that TFS is not responsible for the correct 44 * functioning of this software in any circumstances. 45 * 46 * Ported to run under 386BSD by Julian Elischer (julian@tfs.com) Sept 1992 47 */ 48 49#include "rnd.h" 50 51#include <sys/types.h> 52#include <sys/param.h> 53#include <sys/systm.h> 54#include <sys/kernel.h> 55#include <sys/file.h> 56#include <sys/stat.h> 57#include <sys/ioctl.h> 58#include <sys/buf.h> 59#include <sys/uio.h> 60#include <sys/malloc.h> 61#include <sys/errno.h> 62#include <sys/device.h> 63#include <sys/disklabel.h> 64#include <sys/disk.h> 65#include <sys/cdio.h> 66#include <sys/proc.h> 67#include <sys/conf.h> 68#if NRND > 0 69#include <sys/rnd.h> 70#endif 71 72#include <dev/scsipi/scsipi_all.h> 73#include <dev/scsipi/scsipi_cd.h> 74#include <dev/scsipi/scsipi_disk.h> /* rw_big and start_stop come */ 75 /* from there */ 76#include <dev/scsipi/scsi_disk.h> /* rw comes from there */ 77#include <dev/scsipi/scsipiconf.h> 78#include <dev/scsipi/cd_link.h> 79 80#include "cd.h" /* NCD_SCSI and NCD_ATAPI come */ 81 /* from here */ 82 83#define CDUNIT(z) DISKUNIT(z) 84#define CDPART(z) DISKPART(z) 85#define MAKECDDEV(maj, unit, part) MAKEDISKDEV(maj, unit, part) 86 87#define MAXTRACK 99 88#define CD_BLOCK_OFFSET 150 89#define CD_FRAMES 75 90#define CD_SECS 60 91 92struct cd_toc { 93 struct ioc_toc_header header; 94 struct cd_toc_entry entries[MAXTRACK+1]; /* One extra for the */ 95 /* leadout */ 96}; 97 98int cdlock __P((struct cd_softc *)); 99void cdunlock __P((struct cd_softc *)); 100void cdstart __P((void *)); 101void cdminphys __P((struct buf *)); 102void cdgetdefaultlabel __P((struct cd_softc *, struct disklabel *)); 103void cdgetdisklabel __P((struct cd_softc *)); 104void cddone __P((struct scsipi_xfer *)); 105u_long cd_size __P((struct cd_softc *, int)); 106void lba2msf __P((u_long, u_char *, u_char *, u_char *)); 107u_long msf2lba __P((u_char, u_char, u_char)); 108int cd_play __P((struct cd_softc *, int, int)); 109int cd_play_tracks __P((struct cd_softc *, int, int, int, int)); 110int cd_play_msf __P((struct cd_softc *, int, int, int, int, int, int)); 111int cd_pause __P((struct cd_softc *, int)); 112int cd_reset __P((struct cd_softc *)); 113int cd_read_subchannel __P((struct cd_softc *, int, int, int, 114 struct cd_sub_channel_info *, int)); 115int cd_read_toc __P((struct cd_softc *, int, int, void *, int)); 116int cd_get_parms __P((struct cd_softc *, int)); 117int cd_load_toc __P((struct cd_softc *, struct cd_toc *)); 118 119struct cfdriver cd_cd = { 120 NULL, "cd", DV_DISK 121}; 122 123struct dkdriver cddkdriver = { cdstrategy }; 124 125struct scsipi_device cd_switch = { 126 NULL, /* use default error handler */ 127 cdstart, /* we have a queue, which is started by this */ 128 NULL, /* we do not have an async handler */ 129 cddone, /* deal with stats at interrupt time */ 130}; 131 132/* 133 * The routine called by the low level scsi routine when it discovers 134 * A device suitable for this driver 135 */ 136void 137cdattach(parent, cd, sc_link, ops) 138 struct device *parent; 139 struct cd_softc *cd; 140 struct scsipi_link *sc_link; 141 const struct cd_ops *ops; 142{ 143 SC_DEBUG(sc_link, SDEV_DB2, ("cdattach: ")); 144 145 /* 146 * Store information needed to contact our base driver 147 */ 148 cd->sc_link = sc_link; 149 cd->sc_ops = ops; 150 sc_link->device = &cd_switch; 151 sc_link->device_softc = cd; 152 if (sc_link->openings > CDOUTSTANDING) 153 sc_link->openings = CDOUTSTANDING; 154 155 /* 156 * Initialize and attach the disk structure. 157 */ 158 cd->sc_dk.dk_driver = &cddkdriver; 159 cd->sc_dk.dk_name = cd->sc_dev.dv_xname; 160 disk_attach(&cd->sc_dk); 161 162#if !defined(i386) 163 dk_establish(&cd->sc_dk, &cd->sc_dev); /* XXX */ 164#endif 165 166 printf("\n"); 167 168#if NRND > 0 169 rnd_attach_source(&cd->rnd_source, cd->sc_dev.dv_xname, RND_TYPE_DISK); 170#endif 171} 172 173/* 174 * Wait interruptibly for an exclusive lock. 175 * 176 * XXX 177 * Several drivers do this; it should be abstracted and made MP-safe. 178 */ 179int 180cdlock(cd) 181 struct cd_softc *cd; 182{ 183 int error; 184 185 while ((cd->flags & CDF_LOCKED) != 0) { 186 cd->flags |= CDF_WANTED; 187 if ((error = tsleep(cd, PRIBIO | PCATCH, "cdlck", 0)) != 0) 188 return (error); 189 } 190 cd->flags |= CDF_LOCKED; 191 return (0); 192} 193 194/* 195 * Unlock and wake up any waiters. 196 */ 197void 198cdunlock(cd) 199 struct cd_softc *cd; 200{ 201 202 cd->flags &= ~CDF_LOCKED; 203 if ((cd->flags & CDF_WANTED) != 0) { 204 cd->flags &= ~CDF_WANTED; 205 wakeup(cd); 206 } 207} 208 209/* 210 * open the device. Make sure the partition info is a up-to-date as can be. 211 */ 212int 213cdopen(dev, flag, fmt, p) 214 dev_t dev; 215 int flag, fmt; 216 struct proc *p; 217{ 218 struct cd_softc *cd; 219 struct scsipi_link *sc_link; 220 int unit, part; 221 int error; 222 223 unit = CDUNIT(dev); 224 if (unit >= cd_cd.cd_ndevs) 225 return (ENXIO); 226 cd = cd_cd.cd_devs[unit]; 227 if (cd == NULL) 228 return (ENXIO); 229 230 sc_link = cd->sc_link; 231 232 SC_DEBUG(sc_link, SDEV_DB1, 233 ("cdopen: dev=0x%x (unit %d (of %d), partition %d)\n", dev, unit, 234 cd_cd.cd_ndevs, CDPART(dev))); 235 236 if ((error = cdlock(cd)) != 0) 237 return (error); 238 239 if (cd->sc_dk.dk_openmask != 0) { 240 /* 241 * If any partition is open, but the disk has been invalidated, 242 * disallow further opens. 243 */ 244 if ((sc_link->flags & SDEV_MEDIA_LOADED) == 0) { 245 error = EIO; 246 goto bad3; 247 } 248 } else { 249 /* Check that it is still responding and ok. */ 250 error = scsipi_test_unit_ready(sc_link, 251 SCSI_IGNORE_ILLEGAL_REQUEST | SCSI_IGNORE_MEDIA_CHANGE | 252 SCSI_IGNORE_NOT_READY); 253 SC_DEBUG(sc_link, SDEV_DB1, 254 ("cdopen: scsipi_test_unit_ready, error=%d\n", error)); 255 if (error) 256 goto bad3; 257 258 /* Start the pack spinning if necessary. */ 259 error = scsipi_start(sc_link, SSS_START, 260 SCSI_IGNORE_ILLEGAL_REQUEST | SCSI_IGNORE_MEDIA_CHANGE | 261 SCSI_SILENT); 262 SC_DEBUG(sc_link, SDEV_DB1, 263 ("cdopen: scsipi_start, error=%d\n", error)); 264 if (error) 265 goto bad3; 266 267 sc_link->flags |= SDEV_OPEN; 268 269 /* Lock the pack in. */ 270 error = scsipi_prevent(sc_link, PR_PREVENT, 271 SCSI_IGNORE_ILLEGAL_REQUEST | SCSI_IGNORE_MEDIA_CHANGE); 272 SC_DEBUG(sc_link, SDEV_DB1, 273 ("cdopen: scsipi_prevent, error=%d\n", error)); 274 if (error) 275 goto bad; 276 277 if ((sc_link->flags & SDEV_MEDIA_LOADED) == 0) { 278 sc_link->flags |= SDEV_MEDIA_LOADED; 279 280 /* Load the physical device parameters. */ 281 if (cd_get_parms(cd, 0) != 0) { 282 error = ENXIO; 283 goto bad2; 284 } 285 SC_DEBUG(sc_link, SDEV_DB3, ("Params loaded ")); 286 287 /* Fabricate a disk label. */ 288 cdgetdisklabel(cd); 289 SC_DEBUG(sc_link, SDEV_DB3, ("Disklabel fabricated ")); 290 } 291 } 292 293 part = CDPART(dev); 294 295 /* Check that the partition exists. */ 296 if (part != RAW_PART && 297 (part >= cd->sc_dk.dk_label->d_npartitions || 298 cd->sc_dk.dk_label->d_partitions[part].p_fstype == FS_UNUSED)) { 299 error = ENXIO; 300 goto bad; 301 } 302 303 /* Insure only one open at a time. */ 304 switch (fmt) { 305 case S_IFCHR: 306 cd->sc_dk.dk_copenmask |= (1 << part); 307 break; 308 case S_IFBLK: 309 cd->sc_dk.dk_bopenmask |= (1 << part); 310 break; 311 } 312 cd->sc_dk.dk_openmask = 313 cd->sc_dk.dk_copenmask | cd->sc_dk.dk_bopenmask; 314 315 SC_DEBUG(sc_link, SDEV_DB3, ("open complete\n")); 316 cdunlock(cd); 317 return (0); 318 319bad2: 320 sc_link->flags &= ~SDEV_MEDIA_LOADED; 321 322bad: 323 if (cd->sc_dk.dk_openmask == 0) { 324 scsipi_prevent(sc_link, PR_ALLOW, 325 SCSI_IGNORE_ILLEGAL_REQUEST | SCSI_IGNORE_MEDIA_CHANGE); 326 sc_link->flags &= ~SDEV_OPEN; 327 } 328 329bad3: 330 cdunlock(cd); 331 return (error); 332} 333 334/* 335 * close the device.. only called if we are the LAST 336 * occurence of an open device 337 */ 338int 339cdclose(dev, flag, fmt, p) 340 dev_t dev; 341 int flag, fmt; 342 struct proc *p; 343{ 344 struct cd_softc *cd = cd_cd.cd_devs[CDUNIT(dev)]; 345 int part = CDPART(dev); 346 int error; 347 348 if ((error = cdlock(cd)) != 0) 349 return (error); 350 351 switch (fmt) { 352 case S_IFCHR: 353 cd->sc_dk.dk_copenmask &= ~(1 << part); 354 break; 355 case S_IFBLK: 356 cd->sc_dk.dk_bopenmask &= ~(1 << part); 357 break; 358 } 359 cd->sc_dk.dk_openmask = 360 cd->sc_dk.dk_copenmask | cd->sc_dk.dk_bopenmask; 361 362 if (cd->sc_dk.dk_openmask == 0) { 363 /* XXXX Must wait for I/O to complete! */ 364 365 scsipi_prevent(cd->sc_link, PR_ALLOW, 366 SCSI_IGNORE_ILLEGAL_REQUEST | SCSI_IGNORE_NOT_READY); 367 cd->sc_link->flags &= ~SDEV_OPEN; 368 } 369 370 cdunlock(cd); 371 return (0); 372} 373 374/* 375 * Actually translate the requested transfer into one the physical driver can 376 * understand. The transfer is described by a buf and will include only one 377 * physical transfer. 378 */ 379void 380cdstrategy(bp) 381 struct buf *bp; 382{ 383 struct cd_softc *cd = cd_cd.cd_devs[CDUNIT(bp->b_dev)]; 384 int opri; 385 386 SC_DEBUG(cd->sc_link, SDEV_DB2, ("cdstrategy ")); 387 SC_DEBUG(cd->sc_link, SDEV_DB1, 388 ("%ld bytes @ blk %d\n", bp->b_bcount, bp->b_blkno)); 389 /* 390 * The transfer must be a whole number of blocks. 391 */ 392 if ((bp->b_bcount % cd->sc_dk.dk_label->d_secsize) != 0) { 393 bp->b_error = EINVAL; 394 goto bad; 395 } 396 /* 397 * If the device has been made invalid, error out 398 * maybe the media changed 399 */ 400 if ((cd->sc_link->flags & SDEV_MEDIA_LOADED) == 0) { 401 bp->b_error = EIO; 402 goto bad; 403 } 404 /* 405 * If it's a null transfer, return immediately 406 */ 407 if (bp->b_bcount == 0) 408 goto done; 409 410 /* 411 * Do bounds checking, adjust transfer. if error, process. 412 * If end of partition, just return. 413 */ 414 if (CDPART(bp->b_dev) != RAW_PART && 415 bounds_check_with_label(bp, cd->sc_dk.dk_label, 416 (cd->flags & (CDF_WLABEL|CDF_LABELLING)) != 0) <= 0) 417 goto done; 418 419 opri = splbio(); 420 421 /* 422 * Place it in the queue of disk activities for this disk 423 */ 424 disksort(&cd->buf_queue, bp); 425 426 /* 427 * Tell the device to get going on the transfer if it's 428 * not doing anything, otherwise just wait for completion 429 */ 430 cdstart(cd); 431 432 splx(opri); 433 return; 434 435bad: 436 bp->b_flags |= B_ERROR; 437done: 438 /* 439 * Correctly set the buf to indicate a completed xfer 440 */ 441 bp->b_resid = bp->b_bcount; 442 biodone(bp); 443} 444 445/* 446 * cdstart looks to see if there is a buf waiting for the device 447 * and that the device is not already busy. If both are true, 448 * It deques the buf and creates a scsi command to perform the 449 * transfer in the buf. The transfer request will call scsipi_done 450 * on completion, which will in turn call this routine again 451 * so that the next queued transfer is performed. 452 * The bufs are queued by the strategy routine (cdstrategy) 453 * 454 * This routine is also called after other non-queued requests 455 * have been made of the scsi driver, to ensure that the queue 456 * continues to be drained. 457 * 458 * must be called at the correct (highish) spl level 459 * cdstart() is called at splbio from cdstrategy and scsipi_done 460 */ 461void 462cdstart(v) 463 register void *v; 464{ 465 register struct cd_softc *cd = v; 466 register struct scsipi_link *sc_link = cd->sc_link; 467 struct disklabel *lp = cd->sc_dk.dk_label; 468 struct buf *bp = 0; 469 struct buf *dp; 470 struct scsipi_rw_big cmd_big; 471#if NCD_SCSI > 0 472 struct scsi_rw cmd_small; 473#endif 474 struct scsipi_generic *cmdp; 475 int blkno, nblks, cmdlen; 476 struct partition *p; 477 478 SC_DEBUG(sc_link, SDEV_DB2, ("cdstart ")); 479 /* 480 * Check if the device has room for another command 481 */ 482 while (sc_link->openings > 0) { 483 /* 484 * there is excess capacity, but a special waits 485 * It'll need the adapter as soon as we clear out of the 486 * way and let it run (user level wait). 487 */ 488 if (sc_link->flags & SDEV_WAITING) { 489 sc_link->flags &= ~SDEV_WAITING; 490 wakeup((caddr_t)sc_link); 491 return; 492 } 493 494 /* 495 * See if there is a buf with work for us to do.. 496 */ 497 dp = &cd->buf_queue; 498 if ((bp = dp->b_actf) == NULL) /* yes, an assign */ 499 return; 500 dp->b_actf = bp->b_actf; 501 502 /* 503 * If the deivce has become invalid, abort all the 504 * reads and writes until all files have been closed and 505 * re-opened 506 */ 507 if ((sc_link->flags & SDEV_MEDIA_LOADED) == 0) { 508 bp->b_error = EIO; 509 bp->b_flags |= B_ERROR; 510 bp->b_resid = bp->b_bcount; 511 biodone(bp); 512 continue; 513 } 514 515 /* 516 * We have a buf, now we should make a command 517 * 518 * First, translate the block to absolute and put it in terms 519 * of the logical blocksize of the device. 520 */ 521 blkno = bp->b_blkno / (lp->d_secsize / DEV_BSIZE); 522 if (CDPART(bp->b_dev) != RAW_PART) { 523 p = &lp->d_partitions[CDPART(bp->b_dev)]; 524 blkno += p->p_offset; 525 } 526 nblks = howmany(bp->b_bcount, lp->d_secsize); 527 528#if NCD_SCSI > 0 529 /* 530 * Fill out the scsi command. If the transfer will 531 * fit in a "small" cdb, use it. 532 */ 533 if (((blkno & 0x1fffff) == blkno) && 534 ((nblks & 0xff) == nblks) && sc_link->type == BUS_SCSI) { 535 /* 536 * We can fit in a small cdb. 537 */ 538 bzero(&cmd_small, sizeof(cmd_small)); 539 cmd_small.opcode = (bp->b_flags & B_READ) ? 540 SCSI_READ_COMMAND : SCSI_WRITE_COMMAND; 541 _lto3b(blkno, cmd_small.addr); 542 cmd_small.length = nblks & 0xff; 543 cmdlen = sizeof(cmd_small); 544 cmdp = (struct scsipi_generic *)&cmd_small; 545 } else 546#endif 547 { 548 /* 549 * Need a large cdb. 550 */ 551 bzero(&cmd_big, sizeof(cmd_big)); 552 cmd_big.opcode = (bp->b_flags & B_READ) ? 553 READ_BIG : WRITE_BIG; 554 _lto4b(blkno, cmd_big.addr); 555 _lto2b(nblks, cmd_big.length); 556 cmdlen = sizeof(cmd_big); 557 cmdp = (struct scsipi_generic *)&cmd_big; 558 } 559 560 /* Instrumentation. */ 561 disk_busy(&cd->sc_dk); 562 563 /* 564 * Call the routine that chats with the adapter. 565 * Note: we cannot sleep as we may be an interrupt 566 */ 567 if (scsipi_command(sc_link, cmdp, cmdlen, (u_char *)bp->b_data, 568 bp->b_bcount, CDRETRIES, 30000, bp, SCSI_NOSLEEP | 569 ((bp->b_flags & B_READ) ? SCSI_DATA_IN : SCSI_DATA_OUT))) { 570 disk_unbusy(&cd->sc_dk, 0); 571 printf("%s: not queued", cd->sc_dev.dv_xname); 572 } 573 } 574} 575 576void 577cddone(xs) 578 struct scsipi_xfer *xs; 579{ 580 struct cd_softc *cd = xs->sc_link->device_softc; 581 582 if (xs->bp != NULL) { 583 disk_unbusy(&cd->sc_dk, xs->bp->b_bcount - xs->bp->b_resid); 584#if NRND > 0 585 rnd_add_uint32(&cd->rnd_source, xs->bp->b_blkno); 586#endif 587 } 588} 589 590void 591cdminphys(bp) 592 struct buf *bp; 593{ 594 struct cd_softc *cd = cd_cd.cd_devs[CDUNIT(bp->b_dev)]; 595 long max; 596 597 /* 598 * If the device is ancient, we want to make sure that 599 * the transfer fits into a 6-byte cdb. 600 * 601 * XXX Note that the SCSI-I spec says that 256-block transfers 602 * are allowed in a 6-byte read/write, and are specified 603 * by settng the "length" to 0. However, we're conservative 604 * here, allowing only 255-block transfers in case an 605 * ancient device gets confused by length == 0. A length of 0 606 * in a 10-byte read/write actually means 0 blocks. 607 */ 608 if (cd->flags & CDF_ANCIENT) { 609 max = cd->sc_dk.dk_label->d_secsize * 0xff; 610 611 if (bp->b_bcount > max) 612 bp->b_bcount = max; 613 } 614 615 (*cd->sc_link->adapter->scsipi_minphys)(bp); 616} 617 618int 619cdread(dev, uio, ioflag) 620 dev_t dev; 621 struct uio *uio; 622 int ioflag; 623{ 624 625 return (physio(cdstrategy, NULL, dev, B_READ, cdminphys, uio)); 626} 627 628int 629cdwrite(dev, uio, ioflag) 630 dev_t dev; 631 struct uio *uio; 632 int ioflag; 633{ 634 635 return (physio(cdstrategy, NULL, dev, B_WRITE, cdminphys, uio)); 636} 637 638/* 639 * conversion between minute-seconde-frame and logical block adress 640 * adresses format 641 */ 642void 643lba2msf (lba, m, s, f) 644 u_long lba; 645 u_char *m, *s, *f; 646{ 647 u_long tmp; 648 649 tmp = lba + CD_BLOCK_OFFSET; /* offset of first logical frame */ 650 tmp &= 0xffffff; /* negative lbas use only 24 bits */ 651 *m = tmp / (CD_SECS * CD_FRAMES); 652 tmp %= (CD_SECS * CD_FRAMES); 653 *s = tmp / CD_FRAMES; 654 *f = tmp % CD_FRAMES; 655} 656 657u_long 658msf2lba (m, s, f) 659 u_char m, s, f; 660{ 661 662 return ((((m * CD_SECS) + s) * CD_FRAMES + f) - CD_BLOCK_OFFSET); 663} 664 665 666/* 667 * Perform special action on behalf of the user. 668 * Knows about the internals of this device 669 */ 670int 671cdioctl(dev, cmd, addr, flag, p) 672 dev_t dev; 673 u_long cmd; 674 caddr_t addr; 675 int flag; 676 struct proc *p; 677{ 678 struct cd_softc *cd = cd_cd.cd_devs[CDUNIT(dev)]; 679 int error; 680 681 SC_DEBUG(cd->sc_link, SDEV_DB2, ("cdioctl 0x%lx ", cmd)); 682 683 /* 684 * If the device is not valid.. abandon ship 685 */ 686 if ((cd->sc_link->flags & SDEV_MEDIA_LOADED) == 0) 687 return (EIO); 688 689 switch (cmd) { 690 case DIOCGDINFO: 691 *(struct disklabel *)addr = *(cd->sc_dk.dk_label); 692 return (0); 693 694 case DIOCGPART: 695 ((struct partinfo *)addr)->disklab = cd->sc_dk.dk_label; 696 ((struct partinfo *)addr)->part = 697 &cd->sc_dk.dk_label->d_partitions[CDPART(dev)]; 698 return (0); 699 700 case DIOCWDINFO: 701 case DIOCSDINFO: 702 if ((flag & FWRITE) == 0) 703 return (EBADF); 704 705 if ((error = cdlock(cd)) != 0) 706 return (error); 707 cd->flags |= CDF_LABELLING; 708 709 error = setdisklabel(cd->sc_dk.dk_label, 710 (struct disklabel *)addr, /*cd->sc_dk.dk_openmask : */0, 711 cd->sc_dk.dk_cpulabel); 712 if (error == 0) { 713 /* XXX ? */ 714 } 715 716 cd->flags &= ~CDF_LABELLING; 717 cdunlock(cd); 718 return (error); 719 720 case DIOCWLABEL: 721 return (EBADF); 722 723 case DIOCGDEFLABEL: 724 cdgetdefaultlabel(cd, (struct disklabel *)addr); 725 return (0); 726 727 case CDIOCPLAYTRACKS: { 728 struct ioc_play_track *args = (struct ioc_play_track *)addr; 729 730 if ((error = (*cd->sc_ops->cdo_set_pa_immed)(cd)) != 0) 731 return (error); 732 return (cd_play_tracks(cd, args->start_track, 733 args->start_index, args->end_track, args->end_index)); 734 } 735 case CDIOCPLAYMSF: { 736 struct ioc_play_msf *args = (struct ioc_play_msf *)addr; 737 738 if ((error = (*cd->sc_ops->cdo_set_pa_immed)(cd)) != 0) 739 return (error); 740 return (cd_play_msf(cd, args->start_m, args->start_s, 741 args->start_f, args->end_m, args->end_s, args->end_f)); 742 } 743 case CDIOCPLAYBLOCKS: { 744 struct ioc_play_blocks *args = (struct ioc_play_blocks *)addr; 745 746 if ((error = (*cd->sc_ops->cdo_set_pa_immed)(cd)) != 0) 747 return (error); 748 return (cd_play(cd, args->blk, args->len)); 749 } 750 case CDIOCREADSUBCHANNEL: { 751 struct ioc_read_subchannel *args = 752 (struct ioc_read_subchannel *)addr; 753 struct cd_sub_channel_info data; 754 int len = args->data_len; 755 756 if (len > sizeof(data) || 757 len < sizeof(struct cd_sub_channel_header)) 758 return (EINVAL); 759 error = cd_read_subchannel(cd, args->address_format, 760 args->data_format, args->track, &data, len); 761 if (error) 762 return (error); 763 len = min(len, _2btol(data.header.data_len) + 764 sizeof(struct cd_sub_channel_header)); 765 return (copyout(&data, args->data, len)); 766 } 767 case CDIOREADTOCHEADER: { 768 struct ioc_toc_header th; 769 770 if ((error = cd_read_toc(cd, 0, 0, &th, sizeof(th))) != 0) 771 return (error); 772 if (cd->sc_link->quirks & ADEV_LITTLETOC) { 773#if BYTE_ORDER == BIG_ENDIAN 774 bswap((u_int8_t *)&th.len, sizeof(th.len)); 775#endif 776 } else 777 th.len = ntohs(th.len); 778 bcopy(&th, addr, sizeof(th)); 779 return (0); 780 } 781 case CDIOREADTOCENTRYS: { 782 struct cd_toc toc; 783 struct ioc_read_toc_entry *te = 784 (struct ioc_read_toc_entry *)addr; 785 struct ioc_toc_header *th; 786 struct cd_toc_entry *cte; 787 int len = te->data_len; 788 int ntracks; 789 790 th = &toc.header; 791 792 if (len > sizeof(toc.entries) || 793 len < sizeof(struct cd_toc_entry)) 794 return (EINVAL); 795 error = cd_read_toc(cd, te->address_format, te->starting_track, 796 &toc, len + sizeof(struct ioc_toc_header)); 797 if (error) 798 return (error); 799 if (te->address_format == CD_LBA_FORMAT) 800 for (ntracks = 801 th->ending_track - th->starting_track + 1; 802 ntracks >= 0; ntracks--) { 803 cte = &toc.entries[ntracks]; 804 cte->addr_type = CD_LBA_FORMAT; 805 if (cd->sc_link->quirks & ADEV_LITTLETOC) { 806#if BYTE_ORDER == BIG_ENDIAN 807 bswap((u_int8_t*)&cte->addr, 808 sizeof(cte->addr)); 809#endif 810 } else 811 cte->addr.lba = ntohl(cte->addr.lba); 812 } 813 if (cd->sc_link->quirks & ADEV_LITTLETOC) { 814#if BYTE_ORDER == BIG_ENDIAN 815 bswap((u_int8_t*)&th->len, sizeof(th->len)); 816#endif 817 } else 818 th->len = ntohs(th->len); 819 len = min(len, th->len - (sizeof(th->starting_track) + 820 sizeof(th->ending_track))); 821 return (copyout(toc.entries, te->data, len)); 822 } 823 case CDIOCSETPATCH: { 824 struct ioc_patch *arg = (struct ioc_patch *)addr; 825 826 return ((*cd->sc_ops->cdo_setchan)(cd, arg->patch[0], 827 arg->patch[1], arg->patch[2], arg->patch[3])); 828 } 829 case CDIOCGETVOL: { 830 struct ioc_vol *arg = (struct ioc_vol *)addr; 831 832 return ((*cd->sc_ops->cdo_getvol)(cd, arg)); 833 } 834 case CDIOCSETVOL: { 835 struct ioc_vol *arg = (struct ioc_vol *)addr; 836 837 return ((*cd->sc_ops->cdo_setvol)(cd, arg)); 838 } 839 840 case CDIOCSETMONO: 841 return ((*cd->sc_ops->cdo_setchan)(cd, BOTH_CHANNEL, 842 BOTH_CHANNEL, MUTE_CHANNEL, MUTE_CHANNEL)); 843 844 case CDIOCSETSTEREO: 845 return ((*cd->sc_ops->cdo_setchan)(cd, LEFT_CHANNEL, 846 RIGHT_CHANNEL, MUTE_CHANNEL, MUTE_CHANNEL)); 847 848 case CDIOCSETMUTE: 849 return ((*cd->sc_ops->cdo_setchan)(cd, MUTE_CHANNEL, 850 MUTE_CHANNEL, MUTE_CHANNEL, MUTE_CHANNEL)); 851 852 case CDIOCSETLEFT: 853 return ((*cd->sc_ops->cdo_setchan)(cd, LEFT_CHANNEL, 854 LEFT_CHANNEL, MUTE_CHANNEL, MUTE_CHANNEL)); 855 856 case CDIOCSETRIGHT: 857 return ((*cd->sc_ops->cdo_setchan)(cd, RIGHT_CHANNEL, 858 RIGHT_CHANNEL, MUTE_CHANNEL, MUTE_CHANNEL)); 859 860 case CDIOCRESUME: 861 return (cd_pause(cd, PA_RESUME)); 862 case CDIOCPAUSE: 863 return (cd_pause(cd, PA_PAUSE)); 864 case CDIOCSTART: 865 return (scsipi_start(cd->sc_link, SSS_START, 0)); 866 case CDIOCSTOP: 867 return (scsipi_start(cd->sc_link, SSS_STOP, 0)); 868 case CDIOCEJECT: /* FALLTHROUGH */ 869 case DIOCEJECT: 870 return (scsipi_start(cd->sc_link, SSS_STOP|SSS_LOEJ, 0)); 871 case CDIOCALLOW: 872 return (scsipi_prevent(cd->sc_link, PR_ALLOW, 0)); 873 case CDIOCPREVENT: 874 return (scsipi_prevent(cd->sc_link, PR_PREVENT, 0)); 875 case DIOCLOCK: 876 return (scsipi_prevent(cd->sc_link, 877 (*(int *)addr) ? PR_PREVENT : PR_ALLOW, 0)); 878 case CDIOCSETDEBUG: 879 cd->sc_link->flags |= (SDEV_DB1 | SDEV_DB2); 880 return (0); 881 case CDIOCCLRDEBUG: 882 cd->sc_link->flags &= ~(SDEV_DB1 | SDEV_DB2); 883 return (0); 884 case CDIOCRESET: 885 return (cd_reset(cd)); 886 887 default: 888 if (CDPART(dev) != RAW_PART) 889 return (ENOTTY); 890 return (scsipi_do_ioctl(cd->sc_link, dev, cmd, addr, flag, p)); 891 } 892 893#ifdef DIAGNOSTIC 894 panic("cdioctl: impossible"); 895#endif 896} 897 898void 899cdgetdefaultlabel(cd, lp) 900 struct cd_softc *cd; 901 struct disklabel *lp; 902{ 903 904 bzero(lp, sizeof(struct disklabel)); 905 906 lp->d_secsize = cd->params.blksize; 907 lp->d_ntracks = 1; 908 lp->d_nsectors = 100; 909 lp->d_ncylinders = (cd->params.disksize / 100) + 1; 910 lp->d_secpercyl = lp->d_ntracks * lp->d_nsectors; 911 912 strncpy(lp->d_typename, "SCSI CD-ROM", 16); 913 lp->d_type = DTYPE_SCSI; 914 strncpy(lp->d_packname, "fictitious", 16); 915 lp->d_secperunit = cd->params.disksize; 916 lp->d_rpm = 300; 917 lp->d_interleave = 1; 918 lp->d_flags = D_REMOVABLE; 919 920 lp->d_partitions[0].p_offset = 0; 921 lp->d_partitions[0].p_size = 922 lp->d_secperunit * (lp->d_secsize / DEV_BSIZE); 923 lp->d_partitions[0].p_fstype = FS_ISO9660; 924 lp->d_partitions[RAW_PART].p_offset = 0; 925 lp->d_partitions[RAW_PART].p_size = 926 lp->d_secperunit * (lp->d_secsize / DEV_BSIZE); 927 lp->d_partitions[RAW_PART].p_fstype = FS_ISO9660; 928 lp->d_npartitions = RAW_PART + 1; 929 930 lp->d_magic = DISKMAGIC; 931 lp->d_magic2 = DISKMAGIC; 932 lp->d_checksum = dkcksum(lp); 933} 934 935/* 936 * Load the label information on the named device 937 * Actually fabricate a disklabel 938 * 939 * EVENTUALLY take information about different 940 * data tracks from the TOC and put it in the disklabel 941 */ 942void 943cdgetdisklabel(cd) 944 struct cd_softc *cd; 945{ 946 struct disklabel *lp = cd->sc_dk.dk_label; 947 948 bzero(cd->sc_dk.dk_cpulabel, sizeof(struct cpu_disklabel)); 949 950 cdgetdefaultlabel(cd, lp); 951} 952 953/* 954 * Find out from the device what it's capacity is 955 */ 956u_long 957cd_size(cd, flags) 958 struct cd_softc *cd; 959 int flags; 960{ 961 struct scsipi_read_cd_cap_data rdcap; 962 struct scsipi_read_cd_capacity scsipi_cmd; 963 int blksize; 964 u_long size; 965 966 if (cd->sc_link->quirks & ADEV_NOCAPACITY) { 967 /* 968 * the drive doesn't support the READ_CD_CAPACITY command 969 * use a fake size 970 */ 971 cd->params.blksize = 2048; 972 cd->params.disksize = 400000; 973 return (400000); 974 } 975 976 /* 977 * make up a scsi command and ask the scsi driver to do 978 * it for you. 979 */ 980 bzero(&scsipi_cmd, sizeof(scsipi_cmd)); 981 scsipi_cmd.opcode = READ_CD_CAPACITY; 982 983 /* 984 * If the command works, interpret the result as a 4 byte 985 * number of blocks and a blocksize 986 */ 987 if (scsipi_command(cd->sc_link, 988 (struct scsipi_generic *)&scsipi_cmd, sizeof(scsipi_cmd), 989 (u_char *)&rdcap, sizeof(rdcap), CDRETRIES, 20000, NULL, 990 flags | SCSI_DATA_IN) != 0) 991 return (0); 992 993 blksize = _4btol(rdcap.length); 994 if ((blksize < 512) || ((blksize & 511) != 0)) 995 blksize = 2048; /* some drives lie ! */ 996 cd->params.blksize = blksize; 997 998 size = _4btol(rdcap.addr) + 1; 999 if (size < 100) 1000 size = 400000; /* ditto */ 1001 cd->params.disksize = size; 1002 1003 SC_DEBUG(cd->sc_link, SDEV_DB2, ("cd_sise: %d %ld\n", blksize, size)); 1004 return (size); 1005} 1006 1007/* 1008 * Get scsi driver to send a "start playing" command 1009 */ 1010int 1011cd_play(cd, blkno, nblks) 1012 struct cd_softc *cd; 1013 int blkno, nblks; 1014{ 1015 struct scsipi_play scsipi_cmd; 1016 1017 bzero(&scsipi_cmd, sizeof(scsipi_cmd)); 1018 scsipi_cmd.opcode = PLAY; 1019 _lto4b(blkno, scsipi_cmd.blk_addr); 1020 _lto2b(nblks, scsipi_cmd.xfer_len); 1021 return (scsipi_command(cd->sc_link, 1022 (struct scsipi_generic *)&scsipi_cmd, sizeof(scsipi_cmd), 1023 0, 0, CDRETRIES, 200000, NULL, 0)); 1024} 1025 1026/* 1027 * Get scsi driver to send a "start playing" command 1028 */ 1029int 1030cd_play_tracks(cd, strack, sindex, etrack, eindex) 1031 struct cd_softc *cd; 1032 int strack, sindex, etrack, eindex; 1033{ 1034 struct cd_toc toc; 1035 int error; 1036 1037 if (!etrack) 1038 return (EIO); 1039 if (strack > etrack) 1040 return (EINVAL); 1041 1042 if ((error = cd_load_toc(cd, &toc)) != 0) 1043 return (error); 1044 1045 if (++etrack > (toc.header.ending_track+1)) 1046 etrack = toc.header.ending_track+1; 1047 1048 strack -= toc.header.starting_track; 1049 etrack -= toc.header.starting_track; 1050 if (strack < 0) 1051 return (EINVAL); 1052 1053 return (cd_play_msf(cd, toc.entries[strack].addr.msf.minute, 1054 toc.entries[strack].addr.msf.second, 1055 toc.entries[strack].addr.msf.frame, 1056 toc.entries[etrack].addr.msf.minute, 1057 toc.entries[etrack].addr.msf.second, 1058 toc.entries[etrack].addr.msf.frame)); 1059} 1060 1061/* 1062 * Get scsi driver to send a "play msf" command 1063 */ 1064int 1065cd_play_msf(cd, startm, starts, startf, endm, ends, endf) 1066 struct cd_softc *cd; 1067 int startm, starts, startf, endm, ends, endf; 1068{ 1069 struct scsipi_play_msf scsipi_cmd; 1070 1071 bzero(&scsipi_cmd, sizeof(scsipi_cmd)); 1072 scsipi_cmd.opcode = PLAY_MSF; 1073 scsipi_cmd.start_m = startm; 1074 scsipi_cmd.start_s = starts; 1075 scsipi_cmd.start_f = startf; 1076 scsipi_cmd.end_m = endm; 1077 scsipi_cmd.end_s = ends; 1078 scsipi_cmd.end_f = endf; 1079 return (scsipi_command(cd->sc_link, 1080 (struct scsipi_generic *)&scsipi_cmd, sizeof(scsipi_cmd), 1081 0, 0, CDRETRIES, 2000, NULL, 0)); 1082} 1083 1084/* 1085 * Get scsi driver to send a "start up" command 1086 */ 1087int 1088cd_pause(cd, go) 1089 struct cd_softc *cd; 1090 int go; 1091{ 1092 struct scsipi_pause scsipi_cmd; 1093 1094 bzero(&scsipi_cmd, sizeof(scsipi_cmd)); 1095 scsipi_cmd.opcode = PAUSE; 1096 scsipi_cmd.resume = go & 0xff; 1097 return (scsipi_command(cd->sc_link, 1098 (struct scsipi_generic *)&scsipi_cmd, sizeof(scsipi_cmd), 1099 0, 0, CDRETRIES, 2000, NULL, 0)); 1100} 1101 1102/* 1103 * Get scsi driver to send a "RESET" command 1104 */ 1105int 1106cd_reset(cd) 1107 struct cd_softc *cd; 1108{ 1109 1110 return (scsipi_command(cd->sc_link, 0, 0, 0, 0, 1111 CDRETRIES, 2000, NULL, SCSI_RESET)); 1112} 1113 1114/* 1115 * Read subchannel 1116 */ 1117int 1118cd_read_subchannel(cd, mode, format, track, data, len) 1119 struct cd_softc *cd; 1120 int mode, format, track, len; 1121 struct cd_sub_channel_info *data; 1122{ 1123 struct scsipi_read_subchannel scsipi_cmd; 1124 1125 bzero(&scsipi_cmd, sizeof(scsipi_cmd)); 1126 scsipi_cmd.opcode = READ_SUBCHANNEL; 1127 if (mode == CD_MSF_FORMAT) 1128 scsipi_cmd.byte2 |= CD_MSF; 1129 scsipi_cmd.byte3 = SRS_SUBQ; 1130 scsipi_cmd.subchan_format = format; 1131 scsipi_cmd.track = track; 1132 _lto2b(len, scsipi_cmd.data_len); 1133 return (scsipi_command(cd->sc_link, 1134 (struct scsipi_generic *)&scsipi_cmd, 1135 sizeof(struct scsipi_read_subchannel), (u_char *)data, len, 1136 CDRETRIES, 5000, NULL, SCSI_DATA_IN|SCSI_SILENT)); 1137} 1138 1139/* 1140 * Read table of contents 1141 */ 1142int 1143cd_read_toc(cd, mode, start, data, len) 1144 struct cd_softc *cd; 1145 int mode, start, len; 1146 void *data; 1147{ 1148 struct scsipi_read_toc scsipi_cmd; 1149 int ntoc; 1150 1151 bzero(&scsipi_cmd, sizeof(scsipi_cmd)); 1152#if 0 1153 if (len != sizeof(struct ioc_toc_header)) 1154 ntoc = ((len) - sizeof(struct ioc_toc_header)) / 1155 sizeof(struct cd_toc_entry); 1156 else 1157#endif 1158 ntoc = len; 1159 scsipi_cmd.opcode = READ_TOC; 1160 if (mode == CD_MSF_FORMAT) 1161 scsipi_cmd.byte2 |= CD_MSF; 1162 scsipi_cmd.from_track = start; 1163 _lto2b(ntoc, scsipi_cmd.data_len); 1164 return (scsipi_command(cd->sc_link, 1165 (struct scsipi_generic *)&scsipi_cmd, 1166 sizeof(struct scsipi_read_toc), (u_char *)data, len, CDRETRIES, 1167 5000, NULL, SCSI_DATA_IN)); 1168} 1169 1170int 1171cd_load_toc(cd, toc) 1172 struct cd_softc *cd; 1173 struct cd_toc *toc; 1174{ 1175 int ntracks, len, error; 1176 1177 if ((error = cd_read_toc(cd, 0, 0, toc, sizeof(toc->header))) != 0) 1178 return (error); 1179 1180 ntracks = toc->header.ending_track - toc->header.starting_track + 1; 1181 len = (ntracks + 1) * sizeof(struct cd_toc_entry) + 1182 sizeof(toc->header); 1183 if ((error = cd_read_toc(cd, CD_MSF_FORMAT, 0, toc, len)) != 0) 1184 return (error); 1185 return (0); 1186} 1187 1188/* 1189 * Get the scsi driver to send a full inquiry to the device and use the 1190 * results to fill out the disk parameter structure. 1191 */ 1192int 1193cd_get_parms(cd, flags) 1194 struct cd_softc *cd; 1195 int flags; 1196{ 1197 1198 /* 1199 * give a number of sectors so that sec * trks * cyls 1200 * is <= disk_size 1201 */ 1202 if (cd_size(cd, flags) == 0) 1203 return (ENXIO); 1204 return (0); 1205} 1206 1207int 1208cdsize(dev) 1209 dev_t dev; 1210{ 1211 1212 /* CD-ROMs are read-only. */ 1213 return (-1); 1214} 1215 1216int 1217cddump(dev, blkno, va, size) 1218 dev_t dev; 1219 daddr_t blkno; 1220 caddr_t va; 1221 size_t size; 1222{ 1223 1224 /* Not implemented. */ 1225 return (ENXIO); 1226} 1227