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