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