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