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