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