1 /* $NetBSD: cd.c,v 1.56 1995/01/30 11:50:23 mycroft Exp $ */ 2 3 /* 4 * Copyright (c) 1994, 1995 Charles 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 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 <sys/types.h> 50 #include <sys/param.h> 51 #include <sys/systm.h> 52 #include <sys/kernel.h> 53 #include <sys/conf.h> 54 #include <sys/file.h> 55 #include <sys/stat.h> 56 #include <sys/ioctl.h> 57 #include <sys/buf.h> 58 #include <sys/uio.h> 59 #include <sys/malloc.h> 60 #include <sys/errno.h> 61 #include <sys/device.h> 62 #include <sys/disklabel.h> 63 #include <sys/disk.h> 64 #include <sys/cdio.h> 65 66 #include <scsi/scsi_all.h> 67 #include <scsi/scsi_cd.h> 68 #include <scsi/scsi_disk.h> /* rw_big and start_stop come from there */ 69 #include <scsi/scsiconf.h> 70 71 #ifdef DDB 72 int Debugger(); 73 #else /* DDB */ 74 #define Debugger() 75 #endif /* DDB */ 76 77 #define CDOUTSTANDING 2 78 #define CDRETRIES 1 79 80 #define CDUNIT(z) DISKUNIT(z) 81 #define CDPART(z) DISKPART(z) 82 #define MAKECDDEV(maj, unit, part) MAKEDISKDEV(maj, unit, part) 83 84 struct cd_softc { 85 struct device sc_dev; 86 struct dkdevice sc_dk; 87 88 int flags; 89 #define CDF_LOCKED 0x01 90 #define CDF_WANTED 0x02 91 struct scsi_link *sc_link; /* address of scsi low level switch */ 92 struct cd_parms { 93 int blksize; 94 u_long disksize; /* total number sectors */ 95 } params; 96 struct buf buf_queue; 97 }; 98 99 int cdmatch __P((struct device *, void *, void *)); 100 void cdattach __P((struct device *, struct device *, void *)); 101 102 struct cfdriver cdcd = { 103 NULL, "cd", cdmatch, cdattach, DV_DISK, sizeof(struct cd_softc) 104 }; 105 106 void cdgetdisklabel __P((struct cd_softc *)); 107 int cd_get_parms __P((struct cd_softc *, int)); 108 void cdstrategy __P((struct buf *)); 109 void cdstart __P((struct cd_softc *)); 110 111 struct dkdriver cddkdriver = { cdstrategy }; 112 113 struct scsi_device cd_switch = { 114 NULL, /* use default error handler */ 115 cdstart, /* we have a queue, which is started by this */ 116 NULL, /* we do not have an async handler */ 117 NULL, /* use default 'done' routine */ 118 }; 119 120 struct scsi_inquiry_pattern cd_patterns[] = { 121 {T_CDROM, T_REMOV, 122 "", "", ""}, 123 #if 0 124 {T_CDROM, T_REMOV, /* more luns */ 125 "PIONEER ", "CD-ROM DRM-600 ", ""}, 126 #endif 127 }; 128 129 int 130 cdmatch(parent, match, aux) 131 struct device *parent; 132 void *match, *aux; 133 { 134 struct cfdata *cf = match; 135 struct scsibus_attach_args *sa = aux; 136 int priority; 137 138 (void)scsi_inqmatch(sa->sa_inqbuf, 139 (caddr_t)cd_patterns, sizeof(cd_patterns)/sizeof(cd_patterns[0]), 140 sizeof(cd_patterns[0]), &priority); 141 return (priority); 142 } 143 144 /* 145 * The routine called by the low level scsi routine when it discovers 146 * A device suitable for this driver 147 */ 148 void 149 cdattach(parent, self, aux) 150 struct device *parent, *self; 151 void *aux; 152 { 153 struct cd_softc *cd = (void *)self; 154 struct cd_parms *dp = &cd->params; 155 struct scsibus_attach_args *sa = aux; 156 struct scsi_link *sc_link = sa->sa_sc_link; 157 158 SC_DEBUG(sc_link, SDEV_DB2, ("cdattach: ")); 159 160 /* 161 * Store information needed to contact our base driver 162 */ 163 cd->sc_link = sc_link; 164 sc_link->device = &cd_switch; 165 sc_link->device_softc = cd; 166 if (sc_link->openings > CDOUTSTANDING) 167 sc_link->openings = CDOUTSTANDING; 168 169 cd->sc_dk.dk_driver = &cddkdriver; 170 #if !defined(i386) || defined(NEWCONFIG) 171 dk_establish(&cd->sc_dk, &cd->sc_dev); 172 #endif 173 174 /* 175 * Use the subdriver to request information regarding 176 * the drive. We cannot use interrupts yet, so the 177 * request must specify this. 178 */ 179 if (scsi_start(cd->sc_link, SSS_START, 180 SCSI_AUTOCONF | SCSI_IGNORE_ILLEGAL_REQUEST | SCSI_IGNORE_MEDIA_CHANGE | SCSI_SILENT) || 181 cd_get_parms(cd, SCSI_AUTOCONF) != 0) 182 printf(": drive empty\n"); 183 else 184 printf(": cd present, %d x %d byte records\n", 185 cd->params.disksize, cd->params.blksize); 186 } 187 188 /* 189 * open the device. Make sure the partition info is a up-to-date as can be. 190 */ 191 int 192 cdopen(dev, flag, fmt) 193 dev_t dev; 194 int flag, fmt; 195 { 196 int error; 197 int unit, part; 198 struct cd_softc *cd; 199 struct scsi_link *sc_link; 200 201 unit = CDUNIT(dev); 202 if (unit >= cdcd.cd_ndevs) 203 return ENXIO; 204 cd = cdcd.cd_devs[unit]; 205 if (!cd) 206 return ENXIO; 207 208 part = CDPART(dev); 209 sc_link = cd->sc_link; 210 211 SC_DEBUG(sc_link, SDEV_DB1, 212 ("cdopen: dev=0x%x (unit %d (of %d), partition %d)\n", dev, unit, 213 cdcd.cd_ndevs, part)); 214 215 while ((cd->flags & CDF_LOCKED) != 0) { 216 cd->flags |= CDF_WANTED; 217 if ((error = tsleep(cd, PRIBIO | PCATCH, "cdopn", 0)) != 0) 218 return error; 219 } 220 221 if (cd->sc_dk.dk_openmask != 0) { 222 /* 223 * If any partition is open, but the disk has been invalidated, 224 * disallow further opens. 225 */ 226 if ((sc_link->flags & SDEV_MEDIA_LOADED) == 0) 227 return ENXIO; 228 } else { 229 cd->flags |= CDF_LOCKED; 230 231 /* Check that it is still responding and ok. */ 232 if (error = scsi_test_unit_ready(sc_link, 233 SCSI_IGNORE_ILLEGAL_REQUEST | SCSI_IGNORE_MEDIA_CHANGE | SCSI_IGNORE_NOT_READY)) 234 goto bad3; 235 236 /* Start the pack spinning if necessary. */ 237 if (error = scsi_start(sc_link, SSS_START, 238 SCSI_IGNORE_ILLEGAL_REQUEST | SCSI_IGNORE_MEDIA_CHANGE | SCSI_SILENT)) 239 goto bad3; 240 241 sc_link->flags |= SDEV_OPEN; 242 243 /* Lock the pack in. */ 244 if (error = scsi_prevent(sc_link, PR_PREVENT, 245 SCSI_IGNORE_ILLEGAL_REQUEST | SCSI_IGNORE_MEDIA_CHANGE)) 246 goto bad; 247 248 if ((sc_link->flags & SDEV_MEDIA_LOADED) == 0) { 249 sc_link->flags |= SDEV_MEDIA_LOADED; 250 251 /* Load the physical device parameters. */ 252 if (cd_get_parms(cd, 0) != 0) { 253 error = ENXIO; 254 goto bad2; 255 } 256 SC_DEBUG(sc_link, SDEV_DB3, ("Params loaded ")); 257 258 /* Fabricate a disk label. */ 259 cdgetdisklabel(cd); 260 SC_DEBUG(sc_link, SDEV_DB3, ("Disklabel fabricated ")); 261 } 262 263 cd->flags &= ~CDF_LOCKED; 264 if ((cd->flags & CDF_WANTED) != 0) { 265 cd->flags &= ~CDF_WANTED; 266 wakeup(cd); 267 } 268 } 269 270 /* Check that the partition exists. */ 271 if (part != RAW_PART && 272 (part >= cd->sc_dk.dk_label.d_npartitions || 273 cd->sc_dk.dk_label.d_partitions[part].p_fstype == FS_UNUSED)) { 274 error = ENXIO; 275 goto bad; 276 } 277 278 /* Insure only one open at a time. */ 279 switch (fmt) { 280 case S_IFCHR: 281 cd->sc_dk.dk_copenmask |= (1 << part); 282 break; 283 case S_IFBLK: 284 cd->sc_dk.dk_bopenmask |= (1 << part); 285 break; 286 } 287 cd->sc_dk.dk_openmask = cd->sc_dk.dk_copenmask | cd->sc_dk.dk_bopenmask; 288 289 SC_DEBUG(sc_link, SDEV_DB3, ("open complete\n")); 290 return 0; 291 292 bad2: 293 sc_link->flags &= ~SDEV_MEDIA_LOADED; 294 295 bad: 296 if (cd->sc_dk.dk_openmask == 0) { 297 scsi_prevent(sc_link, PR_ALLOW, 298 SCSI_IGNORE_ILLEGAL_REQUEST | SCSI_IGNORE_MEDIA_CHANGE); 299 sc_link->flags &= ~SDEV_OPEN; 300 301 bad3: 302 cd->flags &= ~CDF_LOCKED; 303 if ((cd->flags & CDF_WANTED) != 0) { 304 cd->flags &= ~CDF_WANTED; 305 wakeup(cd); 306 } 307 } 308 309 return error; 310 } 311 312 /* 313 * close the device.. only called if we are the LAST 314 * occurence of an open device 315 */ 316 int 317 cdclose(dev, flag, fmt) 318 dev_t dev; 319 int flag, fmt; 320 { 321 struct cd_softc *cd = cdcd.cd_devs[CDUNIT(dev)]; 322 int part = CDPART(dev); 323 int s; 324 325 switch (fmt) { 326 case S_IFCHR: 327 cd->sc_dk.dk_copenmask &= ~(1 << part); 328 break; 329 case S_IFBLK: 330 cd->sc_dk.dk_bopenmask &= ~(1 << part); 331 break; 332 } 333 cd->sc_dk.dk_openmask = cd->sc_dk.dk_copenmask | cd->sc_dk.dk_bopenmask; 334 335 if (cd->sc_dk.dk_openmask == 0) { 336 cd->flags |= CDF_LOCKED; 337 338 #if 0 339 s = splbio(); 340 while (...) { 341 cd->flags |= CDF_WAITING; 342 if ((error = tsleep(cd, PRIBIO | PCATCH, "cdcls", 0)) != 0) 343 return error; 344 } 345 splx(s); 346 #endif 347 348 scsi_prevent(cd->sc_link, PR_ALLOW, 349 SCSI_IGNORE_ILLEGAL_REQUEST | SCSI_IGNORE_NOT_READY); 350 cd->sc_link->flags &= ~SDEV_OPEN; 351 352 cd->flags &= ~CDF_LOCKED; 353 if ((cd->flags & CDF_WANTED) != 0) { 354 cd->flags &= ~CDF_WANTED; 355 wakeup(cd); 356 } 357 } 358 359 return 0; 360 } 361 362 /* 363 * trim the size of the transfer if needed, 364 * called by physio 365 * basically the smaller of our max and the scsi driver's 366 * minphys (note we have no max ourselves) 367 * 368 * Trim buffer length if buffer-size is bigger than page size 369 */ 370 void 371 cdminphys(bp) 372 struct buf *bp; 373 { 374 register struct cd_softc *cd = cdcd.cd_devs[CDUNIT(bp->b_dev)]; 375 376 (cd->sc_link->adapter->scsi_minphys) (bp); 377 } 378 379 /* 380 * Actually translate the requested transfer into one the physical driver can 381 * understand. The transfer is described by a buf and will include only one 382 * physical transfer. 383 */ 384 void 385 cdstrategy(bp) 386 struct buf *bp; 387 { 388 struct cd_softc *cd = cdcd.cd_devs[CDUNIT(bp->b_dev)]; 389 int opri; 390 391 SC_DEBUG(cd->sc_link, SDEV_DB2, ("cdstrategy ")); 392 SC_DEBUG(cd->sc_link, SDEV_DB1, 393 ("%d bytes @ blk %d\n", bp->b_bcount, bp->b_blkno)); 394 cdminphys(bp); 395 /* 396 * If the device has been made invalid, error out 397 * maybe the media changed 398 */ 399 if (!(cd->sc_link->flags & SDEV_MEDIA_LOADED)) { 400 bp->b_error = EIO; 401 goto bad; 402 } 403 /* 404 * can't ever write to a CD 405 */ 406 if ((bp->b_flags & B_READ) == 0) { 407 bp->b_error = EROFS; 408 goto bad; 409 } 410 /* 411 * If it's a null transfer, return immediately 412 */ 413 if (bp->b_bcount == 0) 414 goto done; 415 416 /* 417 * Do bounds checking, adjust transfer. if error, process. 418 * If end of partition, just return. 419 */ 420 if (bounds_check_with_label(bp, &cd->sc_dk.dk_label, 0) <= 0) 421 goto done; 422 423 opri = splbio(); 424 425 /* 426 * Place it in the queue of disk activities for this disk 427 */ 428 disksort(&cd->buf_queue, bp); 429 430 /* 431 * Tell the device to get going on the transfer if it's 432 * not doing anything, otherwise just wait for completion 433 */ 434 cdstart(cd); 435 436 splx(opri); 437 return; 438 439 bad: 440 bp->b_flags |= B_ERROR; 441 done: 442 /* 443 * Correctly set the buf to indicate a completed xfer 444 */ 445 bp->b_resid = bp->b_bcount; 446 biodone(bp); 447 } 448 449 /* 450 * cdstart looks to see if there is a buf waiting for the device 451 * and that the device is not already busy. If both are true, 452 * It deques the buf and creates a scsi command to perform the 453 * transfer in the buf. The transfer request will call scsi_done 454 * on completion, which will in turn call this routine again 455 * so that the next queued transfer is performed. 456 * The bufs are queued by the strategy routine (cdstrategy) 457 * 458 * This routine is also called after other non-queued requests 459 * have been made of the scsi driver, to ensure that the queue 460 * continues to be drained. 461 * 462 * must be called at the correct (highish) spl level 463 * cdstart() is called at splbio from cdstrategy and scsi_done 464 */ 465 void 466 cdstart(cd) 467 register struct cd_softc *cd; 468 { 469 register struct scsi_link *sc_link = cd->sc_link; 470 struct buf *bp = 0; 471 struct buf *dp; 472 struct scsi_rw_big cmd; 473 int blkno, nblks; 474 struct partition *p; 475 476 SC_DEBUG(sc_link, SDEV_DB2, ("cdstart ")); 477 /* 478 * See if there is a buf to do and we are not already 479 * doing one 480 */ 481 while (sc_link->openings > 0) { 482 /* 483 * there is excess capacity, but a special waits 484 * It'll need the adapter as soon as we clear out of the 485 * way and let it run (user level wait). 486 */ 487 if (sc_link->flags & SDEV_WAITING) { 488 sc_link->flags &= ~SDEV_WAITING; 489 wakeup((caddr_t)sc_link); 490 return; 491 } 492 493 /* 494 * See if there is a buf with work for us to do.. 495 */ 496 dp = &cd->buf_queue; 497 if ((bp = dp->b_actf) == NULL) /* yes, an assign */ 498 return; 499 dp->b_actf = bp->b_actf; 500 501 /* 502 * If the deivce has become invalid, abort all the 503 * reads and writes until all files have been closed and 504 * re-opened 505 */ 506 if (!(sc_link->flags & SDEV_MEDIA_LOADED)) { 507 bp->b_error = EIO; 508 bp->b_flags |= B_ERROR; 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. Really a bit silly 518 * until we have real partitions, but. 519 */ 520 blkno = 521 bp->b_blkno / (cd->sc_dk.dk_label.d_secsize / DEV_BSIZE); 522 if (CDPART(bp->b_dev) != RAW_PART) { 523 p = &cd->sc_dk.dk_label.d_partitions[CDPART(bp->b_dev)]; 524 blkno += p->p_offset; 525 } 526 nblks = howmany(bp->b_bcount, cd->sc_dk.dk_label.d_secsize); 527 528 /* 529 * Fill out the scsi command 530 */ 531 bzero(&cmd, sizeof(cmd)); 532 cmd.opcode = (bp->b_flags & B_READ) ? READ_BIG : WRITE_BIG; 533 cmd.addr_3 = (blkno & 0xff000000) >> 24; 534 cmd.addr_2 = (blkno & 0xff0000) >> 16; 535 cmd.addr_1 = (blkno & 0xff00) >> 8; 536 cmd.addr_0 = blkno & 0xff; 537 cmd.length2 = (nblks & 0xff00) >> 8; 538 cmd.length1 = (nblks & 0xff); 539 540 /* 541 * Call the routine that chats with the adapter. 542 * Note: we cannot sleep as we may be an interrupt 543 */ 544 if (scsi_scsi_cmd(sc_link, (struct scsi_generic *)&cmd, 545 sizeof(cmd), (u_char *) bp->b_data, bp->b_bcount, 546 CDRETRIES, 30000, bp, SCSI_NOSLEEP | 547 ((bp->b_flags & B_READ) ? SCSI_DATA_IN : SCSI_DATA_OUT))) 548 printf("%s: not queued", cd->sc_dev.dv_xname); 549 } 550 } 551 552 /* 553 * Perform special action on behalf of the user. 554 * Knows about the internals of this device 555 */ 556 int 557 cdioctl(dev, cmd, addr, flag, p) 558 dev_t dev; 559 u_long cmd; 560 caddr_t addr; 561 int flag; 562 struct proc *p; 563 { 564 struct cd_softc *cd = cdcd.cd_devs[CDUNIT(dev)]; 565 int error; 566 567 SC_DEBUG(cd->sc_link, SDEV_DB2, ("cdioctl 0x%x ", cmd)); 568 569 /* 570 * If the device is not valid.. abandon ship 571 */ 572 if (!(cd->sc_link->flags & SDEV_MEDIA_LOADED)) 573 return EIO; 574 575 switch (cmd) { 576 case DIOCGDINFO: 577 *(struct disklabel *)addr = cd->sc_dk.dk_label; 578 return 0; 579 580 case DIOCGPART: 581 ((struct partinfo *)addr)->disklab = &cd->sc_dk.dk_label; 582 ((struct partinfo *)addr)->part = 583 &cd->sc_dk.dk_label.d_partitions[CDPART(dev)]; 584 return 0; 585 586 case DIOCWDINFO: 587 case DIOCSDINFO: 588 if ((flag & FWRITE) == 0) 589 return EBADF; 590 error = setdisklabel(&cd->sc_dk.dk_label, 591 (struct disklabel *)addr, /*cd->sc_dk.dk_openmask : */0, 592 &cd->sc_dk.dk_cpulabel); 593 return error; 594 595 case DIOCWLABEL: 596 return EBADF; 597 598 case CDIOCPLAYTRACKS: { 599 struct ioc_play_track *args = (struct ioc_play_track *)addr; 600 struct cd_mode_data data; 601 if (error = cd_get_mode(cd, &data, AUDIO_PAGE)) 602 return error; 603 data.page.audio.flags &= ~CD_PA_SOTC; 604 data.page.audio.flags |= CD_PA_IMMED; 605 if (error = cd_set_mode(cd, &data)) 606 return error; 607 return cd_play_tracks(cd, args->start_track, args->start_index, 608 args->end_track, args->end_index); 609 } 610 case CDIOCPLAYMSF: { 611 struct ioc_play_msf *args 612 = (struct ioc_play_msf *)addr; 613 struct cd_mode_data data; 614 if (error = cd_get_mode(cd, &data, AUDIO_PAGE)) 615 return error; 616 data.page.audio.flags &= ~CD_PA_SOTC; 617 data.page.audio.flags |= CD_PA_IMMED; 618 if (error = cd_set_mode(cd, &data)) 619 return error; 620 return cd_play_msf(cd, args->start_m, args->start_s, 621 args->start_f, args->end_m, args->end_s, args->end_f); 622 } 623 case CDIOCPLAYBLOCKS: { 624 struct ioc_play_blocks *args 625 = (struct ioc_play_blocks *)addr; 626 struct cd_mode_data data; 627 if (error = cd_get_mode(cd, &data, AUDIO_PAGE)) 628 return error; 629 data.page.audio.flags &= ~CD_PA_SOTC; 630 data.page.audio.flags |= CD_PA_IMMED; 631 if (error = cd_set_mode(cd, &data)) 632 return error; 633 return cd_play(cd, args->blk, args->len); 634 } 635 case CDIOCREADSUBCHANNEL: { 636 struct ioc_read_subchannel *args 637 = (struct ioc_read_subchannel *)addr; 638 struct cd_sub_channel_info data; 639 int len = args->data_len; 640 if (len > sizeof(data) || 641 len < sizeof(struct cd_sub_channel_header)) 642 return EINVAL; 643 if (error = cd_read_subchannel(cd, args->address_format, 644 args->data_format, args->track, &data, len)) 645 return error; 646 len = min(len, ((data.header.data_len[0] << 8) + 647 data.header.data_len[1] + 648 sizeof(struct cd_sub_channel_header))); 649 return copyout(&data, args->data, len); 650 } 651 case CDIOREADTOCHEADER: { 652 struct ioc_toc_header th; 653 if (error = cd_read_toc(cd, 0, 0, &th, sizeof(th))) 654 return error; 655 th.len = ntohs(th.len); 656 bcopy(&th, addr, sizeof(th)); 657 return 0; 658 } 659 case CDIOREADTOCENTRYS: { 660 struct cd_toc { 661 struct ioc_toc_header header; 662 struct cd_toc_entry entries[65]; 663 } data; 664 struct ioc_read_toc_entry *te = 665 (struct ioc_read_toc_entry *)addr; 666 struct ioc_toc_header *th; 667 int len = te->data_len; 668 th = &data.header; 669 670 if (len > sizeof(data.entries) || 671 len < sizeof(struct cd_toc_entry)) 672 return EINVAL; 673 if (error = cd_read_toc(cd, te->address_format, 674 te->starting_track, (struct cd_toc_entry *)&data, 675 len + sizeof(struct ioc_toc_header))) 676 return error; 677 len = min(len, ntohs(th->len) - (sizeof(th->starting_track) + 678 sizeof(th->ending_track))); 679 return copyout(data.entries, te->data, len); 680 } 681 case CDIOCSETPATCH: { 682 struct ioc_patch *arg = (struct ioc_patch *)addr; 683 struct cd_mode_data data; 684 if (error = cd_get_mode(cd, &data, AUDIO_PAGE)) 685 return error; 686 data.page.audio.port[LEFT_PORT].channels = arg->patch[0]; 687 data.page.audio.port[RIGHT_PORT].channels = arg->patch[1]; 688 data.page.audio.port[2].channels = arg->patch[2]; 689 data.page.audio.port[3].channels = arg->patch[3]; 690 return cd_set_mode(cd, &data); 691 } 692 case CDIOCGETVOL: { 693 struct ioc_vol *arg = (struct ioc_vol *)addr; 694 struct cd_mode_data data; 695 if (error = cd_get_mode(cd, &data, AUDIO_PAGE)) 696 return error; 697 arg->vol[LEFT_PORT] = data.page.audio.port[LEFT_PORT].volume; 698 arg->vol[RIGHT_PORT] = data.page.audio.port[RIGHT_PORT].volume; 699 arg->vol[2] = data.page.audio.port[2].volume; 700 arg->vol[3] = data.page.audio.port[3].volume; 701 return 0; 702 } 703 case CDIOCSETVOL: { 704 struct ioc_vol *arg = (struct ioc_vol *)addr; 705 struct cd_mode_data data; 706 if (error = cd_get_mode(cd, &data, AUDIO_PAGE)) 707 return error; 708 data.page.audio.port[LEFT_PORT].channels = CHANNEL_0; 709 data.page.audio.port[LEFT_PORT].volume = arg->vol[LEFT_PORT]; 710 data.page.audio.port[RIGHT_PORT].channels = CHANNEL_1; 711 data.page.audio.port[RIGHT_PORT].volume = arg->vol[RIGHT_PORT]; 712 data.page.audio.port[2].volume = arg->vol[2]; 713 data.page.audio.port[3].volume = arg->vol[3]; 714 return cd_set_mode(cd, &data); 715 } 716 case CDIOCSETMONO: { 717 struct ioc_vol *arg = (struct ioc_vol *)addr; 718 struct cd_mode_data data; 719 if (error = cd_get_mode(cd, &data, AUDIO_PAGE)) 720 return error; 721 data.page.audio.port[LEFT_PORT].channels = 722 LEFT_CHANNEL | RIGHT_CHANNEL | 4 | 8; 723 data.page.audio.port[RIGHT_PORT].channels = 724 LEFT_CHANNEL | RIGHT_CHANNEL; 725 data.page.audio.port[2].channels = 0; 726 data.page.audio.port[3].channels = 0; 727 return cd_set_mode(cd, &data); 728 } 729 case CDIOCSETSTEREO: { 730 struct ioc_vol *arg = (struct ioc_vol *)addr; 731 struct cd_mode_data data; 732 if (error = cd_get_mode(cd, &data, AUDIO_PAGE)) 733 return error; 734 data.page.audio.port[LEFT_PORT].channels = LEFT_CHANNEL; 735 data.page.audio.port[RIGHT_PORT].channels = RIGHT_CHANNEL; 736 data.page.audio.port[2].channels = 0; 737 data.page.audio.port[3].channels = 0; 738 return cd_set_mode(cd, &data); 739 } 740 case CDIOCSETMUTE: { 741 struct ioc_vol *arg = (struct ioc_vol *)addr; 742 struct cd_mode_data data; 743 if (error = cd_get_mode(cd, &data, AUDIO_PAGE)) 744 return error; 745 data.page.audio.port[LEFT_PORT].channels = 0; 746 data.page.audio.port[RIGHT_PORT].channels = 0; 747 data.page.audio.port[2].channels = 0; 748 data.page.audio.port[3].channels = 0; 749 return cd_set_mode(cd, &data); 750 } 751 case CDIOCSETLEFT: { 752 struct ioc_vol *arg = (struct ioc_vol *)addr; 753 struct cd_mode_data data; 754 if (error = cd_get_mode(cd, &data, AUDIO_PAGE)) 755 return error; 756 data.page.audio.port[LEFT_PORT].channels = LEFT_CHANNEL; 757 data.page.audio.port[RIGHT_PORT].channels = LEFT_CHANNEL; 758 data.page.audio.port[2].channels = 0; 759 data.page.audio.port[3].channels = 0; 760 return cd_set_mode(cd, &data); 761 } 762 case CDIOCSETRIGHT: { 763 struct ioc_vol *arg = (struct ioc_vol *)addr; 764 struct cd_mode_data data; 765 if (error = cd_get_mode(cd, &data, AUDIO_PAGE)) 766 return error; 767 data.page.audio.port[LEFT_PORT].channels = RIGHT_CHANNEL; 768 data.page.audio.port[RIGHT_PORT].channels = RIGHT_CHANNEL; 769 data.page.audio.port[2].channels = 0; 770 data.page.audio.port[3].channels = 0; 771 return cd_set_mode(cd, &data); 772 } 773 case CDIOCRESUME: 774 return cd_pause(cd, 1); 775 case CDIOCPAUSE: 776 return cd_pause(cd, 0); 777 case CDIOCSTART: 778 return scsi_start(cd->sc_link, SSS_START, 0); 779 case CDIOCSTOP: 780 return scsi_start(cd->sc_link, SSS_STOP, 0); 781 case CDIOCEJECT: 782 return scsi_start(cd->sc_link, SSS_STOP|SSS_LOEJ, 0); 783 case CDIOCALLOW: 784 return scsi_prevent(cd->sc_link, PR_ALLOW, 0); 785 case CDIOCPREVENT: 786 return scsi_prevent(cd->sc_link, PR_PREVENT, 0); 787 case CDIOCSETDEBUG: 788 cd->sc_link->flags |= (SDEV_DB1 | SDEV_DB2); 789 return 0; 790 case CDIOCCLRDEBUG: 791 cd->sc_link->flags &= ~(SDEV_DB1 | SDEV_DB2); 792 return 0; 793 case CDIOCRESET: 794 return cd_reset(cd); 795 default: 796 if (CDPART(dev) != RAW_PART) 797 return ENOTTY; 798 return scsi_do_ioctl(cd->sc_link, dev, cmd, addr, flag, p); 799 } 800 801 #ifdef DIAGNOSTIC 802 panic("cdioctl: impossible"); 803 #endif 804 } 805 806 /* 807 * Load the label information on the named device 808 * Actually fabricate a disklabel 809 * 810 * EVENTUALLY take information about different 811 * data tracks from the TOC and put it in the disklabel 812 */ 813 void 814 cdgetdisklabel(cd) 815 struct cd_softc *cd; 816 { 817 818 bzero(&cd->sc_dk.dk_label, sizeof(struct disklabel)); 819 bzero(&cd->sc_dk.dk_cpulabel, sizeof(struct cpu_disklabel)); 820 821 cd->sc_dk.dk_label.d_secsize = cd->params.blksize; 822 cd->sc_dk.dk_label.d_ntracks = 1; 823 cd->sc_dk.dk_label.d_nsectors = 100; 824 cd->sc_dk.dk_label.d_ncylinders = (cd->params.disksize / 100) + 1; 825 cd->sc_dk.dk_label.d_secpercyl = 826 cd->sc_dk.dk_label.d_ntracks * cd->sc_dk.dk_label.d_nsectors; 827 828 strncpy(cd->sc_dk.dk_label.d_typename, "SCSI CD-ROM", 16); 829 cd->sc_dk.dk_label.d_type = DTYPE_SCSI; 830 strncpy(cd->sc_dk.dk_label.d_packname, "ficticious", 16); 831 cd->sc_dk.dk_label.d_secperunit = cd->params.disksize; 832 cd->sc_dk.dk_label.d_rpm = 300; 833 cd->sc_dk.dk_label.d_interleave = 1; 834 cd->sc_dk.dk_label.d_flags = D_REMOVABLE; 835 836 cd->sc_dk.dk_label.d_partitions[0].p_offset = 0; 837 cd->sc_dk.dk_label.d_partitions[0].p_size = 838 cd->sc_dk.dk_label.d_secperunit * 839 (cd->sc_dk.dk_label.d_secsize / DEV_BSIZE); 840 cd->sc_dk.dk_label.d_partitions[0].p_fstype = FS_ISO9660; 841 cd->sc_dk.dk_label.d_npartitions = 1; 842 843 cd->sc_dk.dk_label.d_magic = DISKMAGIC; 844 cd->sc_dk.dk_label.d_magic2 = DISKMAGIC; 845 cd->sc_dk.dk_label.d_checksum = dkcksum(&cd->sc_dk.dk_label); 846 } 847 848 /* 849 * Find out from the device what it's capacity is 850 */ 851 u_long 852 cd_size(cd, flags) 853 struct cd_softc *cd; 854 int flags; 855 { 856 struct scsi_read_cd_cap_data rdcap; 857 struct scsi_read_cd_capacity scsi_cmd; 858 int blksize; 859 u_long size; 860 861 /* 862 * make up a scsi command and ask the scsi driver to do 863 * it for you. 864 */ 865 bzero(&scsi_cmd, sizeof(scsi_cmd)); 866 scsi_cmd.opcode = READ_CD_CAPACITY; 867 868 /* 869 * If the command works, interpret the result as a 4 byte 870 * number of blocks and a blocksize 871 */ 872 if (scsi_scsi_cmd(cd->sc_link, (struct scsi_generic *)&scsi_cmd, 873 sizeof(scsi_cmd), (u_char *)&rdcap, sizeof(rdcap), CDRETRIES, 874 2000, NULL, flags | SCSI_DATA_IN) != 0) 875 return 0; 876 877 blksize = (rdcap.length_3 << 24) + (rdcap.length_2 << 16) + 878 (rdcap.length_1 << 8) + rdcap.length_0; 879 if (blksize < 512) 880 blksize = 2048; /* some drives lie ! */ 881 cd->params.blksize = blksize; 882 883 size = (rdcap.addr_3 << 24) + (rdcap.addr_2 << 16) + 884 (rdcap.addr_1 << 8) + rdcap.addr_0 + 1; 885 if (size < 100) 886 size = 400000; /* ditto */ 887 cd->params.disksize = size; 888 889 return size; 890 } 891 892 /* 893 * Get the requested page into the buffer given 894 */ 895 int 896 cd_get_mode(cd, data, page) 897 struct cd_softc *cd; 898 struct cd_mode_data *data; 899 int page; 900 { 901 struct scsi_mode_sense scsi_cmd; 902 int error; 903 904 bzero(&scsi_cmd, sizeof(scsi_cmd)); 905 bzero(data, sizeof(*data)); 906 scsi_cmd.opcode = MODE_SENSE; 907 scsi_cmd.page = page; 908 scsi_cmd.length = sizeof(*data) & 0xff; 909 return scsi_scsi_cmd(cd->sc_link, (struct scsi_generic *)&scsi_cmd, 910 sizeof(scsi_cmd), (u_char *)data, sizeof(*data), CDRETRIES, 20000, 911 NULL, SCSI_DATA_IN); 912 } 913 914 /* 915 * Get the requested page into the buffer given 916 */ 917 int 918 cd_set_mode(cd, data) 919 struct cd_softc *cd; 920 struct cd_mode_data *data; 921 { 922 struct scsi_mode_select scsi_cmd; 923 924 bzero(&scsi_cmd, sizeof(scsi_cmd)); 925 scsi_cmd.opcode = MODE_SELECT; 926 scsi_cmd.byte2 |= SMS_PF; 927 scsi_cmd.length = sizeof(*data) & 0xff; 928 data->header.data_length = 0; 929 return scsi_scsi_cmd(cd->sc_link, (struct scsi_generic *)&scsi_cmd, 930 sizeof(scsi_cmd), (u_char *)data, sizeof(*data), CDRETRIES, 20000, 931 NULL, SCSI_DATA_OUT); 932 } 933 934 /* 935 * Get scsi driver to send a "start playing" command 936 */ 937 int 938 cd_play(cd, blkno, nblks) 939 struct cd_softc *cd; 940 int blkno, nblks; 941 { 942 struct scsi_play scsi_cmd; 943 944 bzero(&scsi_cmd, sizeof(scsi_cmd)); 945 scsi_cmd.opcode = PLAY; 946 scsi_cmd.blk_addr[0] = (blkno >> 24) & 0xff; 947 scsi_cmd.blk_addr[1] = (blkno >> 16) & 0xff; 948 scsi_cmd.blk_addr[2] = (blkno >> 8) & 0xff; 949 scsi_cmd.blk_addr[3] = blkno & 0xff; 950 scsi_cmd.xfer_len[0] = (nblks >> 8) & 0xff; 951 scsi_cmd.xfer_len[1] = nblks & 0xff; 952 return scsi_scsi_cmd(cd->sc_link, (struct scsi_generic *)&scsi_cmd, 953 sizeof(scsi_cmd), 0, 0, CDRETRIES, 200000, NULL, 0); 954 } 955 956 /* 957 * Get scsi driver to send a "start playing" command 958 */ 959 int 960 cd_play_big(cd, blkno, nblks) 961 struct cd_softc *cd; 962 int blkno, nblks; 963 { 964 struct scsi_play_big scsi_cmd; 965 966 bzero(&scsi_cmd, sizeof(scsi_cmd)); 967 scsi_cmd.opcode = PLAY_BIG; 968 scsi_cmd.blk_addr[0] = (blkno >> 24) & 0xff; 969 scsi_cmd.blk_addr[1] = (blkno >> 16) & 0xff; 970 scsi_cmd.blk_addr[2] = (blkno >> 8) & 0xff; 971 scsi_cmd.blk_addr[3] = blkno & 0xff; 972 scsi_cmd.xfer_len[0] = (nblks >> 24) & 0xff; 973 scsi_cmd.xfer_len[1] = (nblks >> 16) & 0xff; 974 scsi_cmd.xfer_len[2] = (nblks >> 8) & 0xff; 975 scsi_cmd.xfer_len[3] = nblks & 0xff; 976 return scsi_scsi_cmd(cd->sc_link, (struct scsi_generic *)&scsi_cmd, 977 sizeof(scsi_cmd), 0, 0, CDRETRIES, 20000, NULL, 0); 978 } 979 980 /* 981 * Get scsi driver to send a "start playing" command 982 */ 983 int 984 cd_play_tracks(cd, strack, sindex, etrack, eindex) 985 struct cd_softc *cd; 986 int strack, sindex, etrack, eindex; 987 { 988 struct scsi_play_track scsi_cmd; 989 990 bzero(&scsi_cmd, sizeof(scsi_cmd)); 991 scsi_cmd.opcode = PLAY_TRACK; 992 scsi_cmd.start_track = strack; 993 scsi_cmd.start_index = sindex; 994 scsi_cmd.end_track = etrack; 995 scsi_cmd.end_index = eindex; 996 return scsi_scsi_cmd(cd->sc_link, (struct scsi_generic *)&scsi_cmd, 997 sizeof(scsi_cmd), 0, 0, CDRETRIES, 20000, NULL, 0); 998 } 999 1000 /* 1001 * Get scsi driver to send a "play msf" command 1002 */ 1003 int 1004 cd_play_msf(cd, startm, starts, startf, endm, ends, endf) 1005 struct cd_softc *cd; 1006 int startm, starts, startf, endm, ends, endf; 1007 { 1008 struct scsi_play_msf scsi_cmd; 1009 1010 bzero(&scsi_cmd, sizeof(scsi_cmd)); 1011 scsi_cmd.opcode = PLAY_MSF; 1012 scsi_cmd.start_m = startm; 1013 scsi_cmd.start_s = starts; 1014 scsi_cmd.start_f = startf; 1015 scsi_cmd.end_m = endm; 1016 scsi_cmd.end_s = ends; 1017 scsi_cmd.end_f = endf; 1018 return scsi_scsi_cmd(cd->sc_link, (struct scsi_generic *)&scsi_cmd, 1019 sizeof(scsi_cmd), 0, 0, CDRETRIES, 2000, NULL, 0); 1020 } 1021 1022 /* 1023 * Get scsi driver to send a "start up" command 1024 */ 1025 int 1026 cd_pause(cd, go) 1027 struct cd_softc *cd; 1028 int go; 1029 { 1030 struct scsi_pause scsi_cmd; 1031 1032 bzero(&scsi_cmd, sizeof(scsi_cmd)); 1033 scsi_cmd.opcode = PAUSE; 1034 scsi_cmd.resume = go; 1035 return scsi_scsi_cmd(cd->sc_link, (struct scsi_generic *)&scsi_cmd, 1036 sizeof(scsi_cmd), 0, 0, CDRETRIES, 2000, NULL, 0); 1037 } 1038 1039 /* 1040 * Get scsi driver to send a "RESET" command 1041 */ 1042 int 1043 cd_reset(cd) 1044 struct cd_softc *cd; 1045 { 1046 1047 return scsi_scsi_cmd(cd->sc_link, 0, 0, 0, 0, CDRETRIES, 2000, NULL, 1048 SCSI_RESET); 1049 } 1050 1051 /* 1052 * Read subchannel 1053 */ 1054 int 1055 cd_read_subchannel(cd, mode, format, track, data, len) 1056 struct cd_softc *cd; 1057 int mode, format, len; 1058 struct cd_sub_channel_info *data; 1059 { 1060 struct scsi_read_subchannel scsi_cmd; 1061 1062 bzero(&scsi_cmd, sizeof(scsi_cmd)); 1063 scsi_cmd.opcode = READ_SUBCHANNEL; 1064 if (mode == CD_MSF_FORMAT) 1065 scsi_cmd.byte2 |= CD_MSF; 1066 scsi_cmd.byte3 = SRS_SUBQ; 1067 scsi_cmd.subchan_format = format; 1068 scsi_cmd.track = track; 1069 scsi_cmd.data_len[0] = (len) >> 8; 1070 scsi_cmd.data_len[1] = (len) & 0xff; 1071 return scsi_scsi_cmd(cd->sc_link, (struct scsi_generic *)&scsi_cmd, 1072 sizeof(struct scsi_read_subchannel), (u_char *)data, len, 1073 CDRETRIES, 5000, NULL, SCSI_DATA_IN); 1074 } 1075 1076 /* 1077 * Read table of contents 1078 */ 1079 int 1080 cd_read_toc(cd, mode, start, data, len) 1081 struct cd_softc *cd; 1082 int mode, start, len; 1083 struct cd_toc_entry *data; 1084 { 1085 struct scsi_read_toc scsi_cmd; 1086 int ntoc; 1087 1088 bzero(&scsi_cmd, sizeof(scsi_cmd)); 1089 /*if (len!=sizeof(struct ioc_toc_header)) 1090 * ntoc=((len)-sizeof(struct ioc_toc_header))/sizeof(struct cd_toc_entry); 1091 * else */ 1092 ntoc = len; 1093 scsi_cmd.opcode = READ_TOC; 1094 if (mode == CD_MSF_FORMAT) 1095 scsi_cmd.byte2 |= CD_MSF; 1096 scsi_cmd.from_track = start; 1097 scsi_cmd.data_len[0] = (ntoc) >> 8; 1098 scsi_cmd.data_len[1] = (ntoc) & 0xff; 1099 return scsi_scsi_cmd(cd->sc_link, (struct scsi_generic *)&scsi_cmd, 1100 sizeof(struct scsi_read_toc), (u_char *)data, len, CDRETRIES, 1101 5000, NULL, SCSI_DATA_IN); 1102 } 1103 1104 /* 1105 * Get the scsi driver to send a full inquiry to the device and use the 1106 * results to fill out the disk parameter structure. 1107 */ 1108 int 1109 cd_get_parms(cd, flags) 1110 struct cd_softc *cd; 1111 int flags; 1112 { 1113 1114 /* 1115 * give a number of sectors so that sec * trks * cyls 1116 * is <= disk_size 1117 */ 1118 if (cd_size(cd, flags) == 0) 1119 return ENXIO; 1120 1121 return 0; 1122 } 1123 1124 int 1125 cdsize(dev) 1126 dev_t dev; 1127 { 1128 1129 return -1; 1130 } 1131 1132 int 1133 cddump() 1134 { 1135 1136 /* Not implemented. */ 1137 return EINVAL; 1138 } 1139