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.29 1994/06/16 15:57:39 chopps 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 bp->b_error = EIO; 460 bp->b_flags |= B_ERROR; 461 biodone(bp); 462 continue; 463 } 464 465 /* 466 * We have a buf, now we should make a command 467 * 468 * First, translate the block to absolute and put it in terms 469 * of the logical blocksize of the device. Really a bit silly 470 * until we have real partitions, but. 471 */ 472 blkno = bp->b_blkno / (cd->params.blksize / DEV_BSIZE); 473 if (CDPART(bp->b_dev) != RAW_PART) { 474 p = &cd->sc_dk.dk_label.d_partitions[CDPART(bp->b_dev)]; 475 blkno += p->p_offset; 476 } 477 nblks = (bp->b_bcount + (cd->params.blksize - 1)) / 478 cd->params.blksize; 479 480 /* 481 * Fill out the scsi command 482 */ 483 bzero(&cmd, sizeof(cmd)); 484 cmd.op_code = (bp->b_flags & B_READ) ? READ_BIG : WRITE_BIG; 485 cmd.addr_3 = (blkno & 0xff000000) >> 24; 486 cmd.addr_2 = (blkno & 0xff0000) >> 16; 487 cmd.addr_1 = (blkno & 0xff00) >> 8; 488 cmd.addr_0 = blkno & 0xff; 489 cmd.length2 = (nblks & 0xff00) >> 8; 490 cmd.length1 = (nblks & 0xff); 491 492 /* 493 * Call the routine that chats with the adapter. 494 * Note: we cannot sleep as we may be an interrupt 495 */ 496 if (scsi_scsi_cmd(sc_link, (struct scsi_generic *) &cmd, 497 sizeof(cmd), (u_char *) bp->b_data, bp->b_bcount, 498 CDRETRIES, 30000, bp, SCSI_NOSLEEP | 499 ((bp->b_flags & B_READ) ? SCSI_DATA_IN : SCSI_DATA_OUT)) 500 != SUCCESSFULLY_QUEUED) 501 printf("%s: not queued", cd->sc_dev.dv_xname); 502 } 503 } 504 505 /* 506 * Perform special action on behalf of the user. 507 * Knows about the internals of this device 508 */ 509 int 510 cdioctl(dev, cmd, addr, flag) 511 dev_t dev; 512 int cmd; 513 caddr_t addr; 514 int flag; 515 { 516 int error; 517 int unit, part; 518 register struct cd_data *cd; 519 520 /* 521 * Find the device that the user is talking about 522 */ 523 unit = CDUNIT(dev); 524 part = CDPART(dev); 525 cd = cdcd.cd_devs[unit]; 526 SC_DEBUG(cd->sc_link, SDEV_DB2, ("cdioctl 0x%x ", cmd)); 527 528 /* 529 * If the device is not valid.. abandon ship 530 */ 531 if (!(cd->sc_link->flags & SDEV_MEDIA_LOADED)) 532 return EIO; 533 534 switch (cmd) { 535 case DIOCSBAD: 536 return EINVAL; 537 538 case DIOCGDINFO: 539 *(struct disklabel *) addr = cd->sc_dk.dk_label; 540 return 0; 541 542 case DIOCGPART: 543 ((struct partinfo *) addr)->disklab = &cd->sc_dk.dk_label; 544 ((struct partinfo *) addr)->part = 545 &cd->sc_dk.dk_label.d_partitions[CDPART(dev)]; 546 return 0; 547 548 /* 549 * a bit silly, but someone might want to test something on a 550 * section of cdrom. 551 */ 552 case DIOCWDINFO: 553 case DIOCSDINFO: 554 if ((flag & FWRITE) == 0) 555 return EBADF; 556 error = setdisklabel(&cd->sc_dk.dk_label, 557 (struct disklabel *) addr, 0, 0); 558 return error; 559 560 case DIOCWLABEL: 561 return EBADF; 562 563 case CDIOCPLAYTRACKS: { 564 struct ioc_play_track *args = (struct ioc_play_track *) addr; 565 struct cd_mode_data data; 566 if (error = cd_get_mode(cd, &data, AUDIO_PAGE)) 567 return error; 568 data.page.audio.flags &= ~CD_PA_SOTC; 569 data.page.audio.flags |= CD_PA_IMMED; 570 if (error = cd_set_mode(cd, &data)) 571 return error; 572 return cd_play_tracks(cd, args->start_track, args->start_index, 573 args->end_track, args->end_index); 574 } 575 case CDIOCPLAYMSF: { 576 struct ioc_play_msf *args 577 = (struct ioc_play_msf *) addr; 578 struct cd_mode_data data; 579 if (error = cd_get_mode(cd, &data, AUDIO_PAGE)) 580 return error; 581 data.page.audio.flags &= ~CD_PA_SOTC; 582 data.page.audio.flags |= CD_PA_IMMED; 583 if (error = cd_set_mode(cd, &data)) 584 return error; 585 return cd_play_msf(cd, args->start_m, args->start_s, 586 args->start_f, args->end_m, args->end_s, args->end_f); 587 } 588 case CDIOCPLAYBLOCKS: { 589 struct ioc_play_blocks *args 590 = (struct ioc_play_blocks *) addr; 591 struct cd_mode_data data; 592 if (error = cd_get_mode(cd, &data, AUDIO_PAGE)) 593 return error; 594 data.page.audio.flags &= ~CD_PA_SOTC; 595 data.page.audio.flags |= CD_PA_IMMED; 596 if (error = cd_set_mode(cd, &data)) 597 return error; 598 return cd_play(cd, args->blk, args->len); 599 } 600 case CDIOCREADSUBCHANNEL: { 601 struct ioc_read_subchannel *args 602 = (struct ioc_read_subchannel *) addr; 603 struct cd_sub_channel_info data; 604 u_int32 len = args->data_len; 605 if (len > sizeof(data) || 606 len < sizeof(struct cd_sub_channel_header)) 607 return EINVAL; 608 if (error = cd_read_subchannel(cd, args->address_format, 609 args->data_format, args->track, &data, len)) 610 return error; 611 len = min(len, ((data.header.data_len[0] << 8) + 612 data.header.data_len[1] + 613 sizeof(struct cd_sub_channel_header))); 614 return copyout(&data, args->data, len); 615 } 616 case CDIOREADTOCHEADER: { 617 struct ioc_toc_header th; 618 if (error = cd_read_toc(cd, 0, 0, &th, sizeof(th))) 619 return error; 620 th.len = ntohs(th.len); 621 bcopy(&th, addr, sizeof(th)); 622 return 0; 623 } 624 case CDIOREADTOCENTRYS: { 625 struct cd_toc { 626 struct ioc_toc_header header; 627 struct cd_toc_entry entries[65]; 628 } data; 629 struct ioc_read_toc_entry *te = 630 (struct ioc_read_toc_entry *) addr; 631 struct ioc_toc_header *th; 632 u_int32 len = te->data_len; 633 th = &data.header; 634 635 if (len > sizeof(data.entries) || 636 len < sizeof(struct cd_toc_entry)) 637 return EINVAL; 638 if (error = cd_read_toc(cd, te->address_format, 639 te->starting_track, (struct cd_toc_entry *) &data, 640 len + sizeof(struct ioc_toc_header))) 641 return error; 642 len = min(len, ntohs(th->len) - (sizeof(th->starting_track) + 643 sizeof(th->ending_track))); 644 return copyout(data.entries, te->data, len); 645 } 646 case CDIOCSETPATCH: { 647 struct ioc_patch *arg = (struct ioc_patch *) addr; 648 struct cd_mode_data data; 649 if (error = cd_get_mode(cd, &data, AUDIO_PAGE)) 650 return error; 651 data.page.audio.port[LEFT_PORT].channels = arg->patch[0]; 652 data.page.audio.port[RIGHT_PORT].channels = arg->patch[1]; 653 data.page.audio.port[2].channels = arg->patch[2]; 654 data.page.audio.port[3].channels = arg->patch[3]; 655 return cd_set_mode(cd, &data); 656 } 657 case CDIOCGETVOL: { 658 struct ioc_vol *arg = (struct ioc_vol *) addr; 659 struct cd_mode_data data; 660 if (error = cd_get_mode(cd, &data, AUDIO_PAGE)) 661 return error; 662 arg->vol[LEFT_PORT] = data.page.audio.port[LEFT_PORT].volume; 663 arg->vol[RIGHT_PORT] = data.page.audio.port[RIGHT_PORT].volume; 664 arg->vol[2] = data.page.audio.port[2].volume; 665 arg->vol[3] = data.page.audio.port[3].volume; 666 return 0; 667 } 668 case CDIOCSETVOL: { 669 struct ioc_vol *arg = (struct ioc_vol *) addr; 670 struct cd_mode_data data; 671 if (error = cd_get_mode(cd, &data, AUDIO_PAGE)) 672 return error; 673 data.page.audio.port[LEFT_PORT].channels = CHANNEL_0; 674 data.page.audio.port[LEFT_PORT].volume = arg->vol[LEFT_PORT]; 675 data.page.audio.port[RIGHT_PORT].channels = CHANNEL_1; 676 data.page.audio.port[RIGHT_PORT].volume = arg->vol[RIGHT_PORT]; 677 data.page.audio.port[2].volume = arg->vol[2]; 678 data.page.audio.port[3].volume = arg->vol[3]; 679 return cd_set_mode(cd, &data); 680 } 681 case CDIOCSETMONO: { 682 struct ioc_vol *arg = (struct ioc_vol *) addr; 683 struct cd_mode_data data; 684 if (error = cd_get_mode(cd, &data, AUDIO_PAGE)) 685 return error; 686 data.page.audio.port[LEFT_PORT].channels = 687 LEFT_CHANNEL | RIGHT_CHANNEL | 4 | 8; 688 data.page.audio.port[RIGHT_PORT].channels = 689 LEFT_CHANNEL | RIGHT_CHANNEL; 690 data.page.audio.port[2].channels = 0; 691 data.page.audio.port[3].channels = 0; 692 return cd_set_mode(cd, &data); 693 } 694 case CDIOCSETSTERIO: { 695 struct ioc_vol *arg = (struct ioc_vol *) addr; 696 struct cd_mode_data data; 697 if (error = cd_get_mode(cd, &data, AUDIO_PAGE)) 698 return error; 699 data.page.audio.port[LEFT_PORT].channels = LEFT_CHANNEL; 700 data.page.audio.port[RIGHT_PORT].channels = RIGHT_CHANNEL; 701 data.page.audio.port[2].channels = 0; 702 data.page.audio.port[3].channels = 0; 703 return cd_set_mode(cd, &data); 704 } 705 case CDIOCSETMUTE: { 706 struct ioc_vol *arg = (struct ioc_vol *) addr; 707 struct cd_mode_data data; 708 if (error = cd_get_mode(cd, &data, AUDIO_PAGE)) 709 return error; 710 data.page.audio.port[LEFT_PORT].channels = 0; 711 data.page.audio.port[RIGHT_PORT].channels = 0; 712 data.page.audio.port[2].channels = 0; 713 data.page.audio.port[3].channels = 0; 714 return cd_set_mode(cd, &data); 715 } 716 case CDIOCSETLEFT: { 717 struct ioc_vol *arg = (struct ioc_vol *) addr; 718 struct cd_mode_data data; 719 if (error = cd_get_mode(cd, &data, AUDIO_PAGE)) 720 return error; 721 data.page.audio.port[LEFT_PORT].channels = LEFT_CHANNEL; 722 data.page.audio.port[RIGHT_PORT].channels = LEFT_CHANNEL; 723 data.page.audio.port[2].channels = 0; 724 data.page.audio.port[3].channels = 0; 725 return cd_set_mode(cd, &data); 726 } 727 case CDIOCSETRIGHT: { 728 struct ioc_vol *arg = (struct ioc_vol *) addr; 729 struct cd_mode_data data; 730 if (error = cd_get_mode(cd, &data, AUDIO_PAGE)) 731 return error; 732 data.page.audio.port[LEFT_PORT].channels = RIGHT_CHANNEL; 733 data.page.audio.port[RIGHT_PORT].channels = RIGHT_CHANNEL; 734 data.page.audio.port[2].channels = 0; 735 data.page.audio.port[3].channels = 0; 736 return cd_set_mode(cd, &data); 737 } 738 case CDIOCRESUME: 739 return cd_pause(cd, 1); 740 case CDIOCPAUSE: 741 return cd_pause(cd, 0); 742 case CDIOCSTART: 743 return scsi_start(cd->sc_link, SSS_START, 0); 744 case CDIOCSTOP: 745 return scsi_start(cd->sc_link, SSS_STOP, 0); 746 case CDIOCEJECT: 747 return scsi_start(cd->sc_link, SSS_LOEJ, 0); 748 case CDIOCALLOW: 749 return scsi_prevent(cd->sc_link, PR_ALLOW, 0); 750 case CDIOCPREVENT: 751 return scsi_prevent(cd->sc_link, PR_PREVENT, 0); 752 case CDIOCSETDEBUG: 753 cd->sc_link->flags |= (SDEV_DB1 | SDEV_DB2); 754 return 0; 755 case CDIOCCLRDEBUG: 756 cd->sc_link->flags &= ~(SDEV_DB1 | SDEV_DB2); 757 return 0; 758 case CDIOCRESET: 759 return cd_reset(cd); 760 default: 761 if (part != RAW_PART) 762 return ENOTTY; 763 return scsi_do_ioctl(cd->sc_link, cmd, addr, flag); 764 } 765 #ifdef DIAGNOSTIC 766 panic("cdioctl: impossible"); 767 #endif 768 } 769 770 /* 771 * Load the label information on the named device 772 * Actually fabricate a disklabel 773 * 774 * EVENTUALLY take information about different 775 * data tracks from the TOC and put it in the disklabel 776 */ 777 int 778 cdgetdisklabel(cd) 779 struct cd_data *cd; 780 { 781 char *errstring; 782 783 bzero(&cd->sc_dk.dk_label, sizeof(struct disklabel)); 784 bzero(&cd->sc_dk.dk_cpulabel, sizeof(struct cpu_disklabel)); 785 /* 786 * make partition 0 the whole disk 787 * remember that comparisons with the partition are done 788 * assuming the blocks are 512 bytes so fudge it. 789 */ 790 cd->sc_dk.dk_label.d_partitions[0].p_offset = 0; 791 cd->sc_dk.dk_label.d_partitions[0].p_size = 792 cd->params.disksize * (cd->params.blksize / DEV_BSIZE); 793 cd->sc_dk.dk_label.d_partitions[0].p_fstype = FS_ISO9660; 794 cd->sc_dk.dk_label.d_npartitions = 1; 795 796 cd->sc_dk.dk_label.d_secsize = cd->params.blksize; 797 cd->sc_dk.dk_label.d_ntracks = 1; 798 cd->sc_dk.dk_label.d_nsectors = 100; 799 cd->sc_dk.dk_label.d_ncylinders = (cd->params.disksize / 100) + 1; 800 cd->sc_dk.dk_label.d_secpercyl = 100; 801 802 strncpy(cd->sc_dk.dk_label.d_typename, "scsi cd_rom", 16); 803 strncpy(cd->sc_dk.dk_label.d_packname, "ficticious", 16); 804 cd->sc_dk.dk_label.d_secperunit = cd->params.disksize; 805 cd->sc_dk.dk_label.d_rpm = 300; 806 cd->sc_dk.dk_label.d_interleave = 1; 807 cd->sc_dk.dk_label.d_flags = D_REMOVABLE; 808 cd->sc_dk.dk_label.d_magic = DISKMAGIC; 809 cd->sc_dk.dk_label.d_magic2 = DISKMAGIC; 810 cd->sc_dk.dk_label.d_checksum = dkcksum(&cd->sc_dk.dk_label); 811 812 /* 813 * Signal to other users and routines that we now have a 814 * disklabel that represents the media (maybe) 815 */ 816 return 0; 817 } 818 819 /* 820 * Find out from the device what it's capacity is 821 */ 822 u_int32 823 cd_size(cd, flags) 824 struct cd_data *cd; 825 int flags; 826 { 827 struct scsi_read_cd_cap_data rdcap; 828 struct scsi_read_cd_capacity scsi_cmd; 829 u_int32 size, blksize; 830 831 /* 832 * make up a scsi command and ask the scsi driver to do 833 * it for you. 834 */ 835 bzero(&scsi_cmd, sizeof(scsi_cmd)); 836 scsi_cmd.op_code = READ_CD_CAPACITY; 837 838 /* 839 * If the command works, interpret the result as a 4 byte 840 * number of blocks and a blocksize 841 */ 842 if (scsi_scsi_cmd(cd->sc_link, (struct scsi_generic *) &scsi_cmd, 843 sizeof(scsi_cmd), (u_char *) &rdcap, sizeof(rdcap), CDRETRIES, 844 20000, NULL, SCSI_DATA_IN | flags) != 0) { 845 if (!(flags & SCSI_SILENT)) 846 printf("%s: could not get size\n", 847 cd->sc_dev.dv_xname); 848 return 0; 849 } else { 850 size = (rdcap.addr_3 << 24) + (rdcap.addr_2 << 16) + 851 (rdcap.addr_1 << 8) + rdcap.addr_0 + 1; 852 blksize = (rdcap.length_3 << 24) + (rdcap.length_2 << 16) + 853 (rdcap.length_1 << 8) + rdcap.length_0; 854 } 855 if (blksize < 512) 856 blksize = 2048; /* some drives lie ! */ 857 if (size < 100) 858 size = 400000; /* ditto */ 859 cd->params.disksize = size; 860 cd->params.blksize = blksize; 861 return size; 862 } 863 864 /* 865 * Get the requested page into the buffer given 866 */ 867 int 868 cd_get_mode(cd, data, page) 869 struct cd_data *cd; 870 struct cd_mode_data *data; 871 int page; 872 { 873 struct scsi_mode_sense scsi_cmd; 874 int error; 875 876 bzero(&scsi_cmd, sizeof(scsi_cmd)); 877 bzero(data, sizeof(*data)); 878 scsi_cmd.op_code = MODE_SENSE; 879 scsi_cmd.page = page; 880 scsi_cmd.length = sizeof(*data) & 0xff; 881 return scsi_scsi_cmd(cd->sc_link, (struct scsi_generic *) &scsi_cmd, 882 sizeof(scsi_cmd), (u_char *) data, sizeof(*data), CDRETRIES, 20000, 883 NULL, SCSI_DATA_IN); 884 } 885 886 /* 887 * Get the requested page into the buffer given 888 */ 889 int 890 cd_set_mode(cd, data) 891 struct cd_data *cd; 892 struct cd_mode_data *data; 893 { 894 struct scsi_mode_select scsi_cmd; 895 896 bzero(&scsi_cmd, sizeof(scsi_cmd)); 897 scsi_cmd.op_code = MODE_SELECT; 898 scsi_cmd.byte2 |= SMS_PF; 899 scsi_cmd.length = sizeof(*data) & 0xff; 900 data->header.data_length = 0; 901 return scsi_scsi_cmd(cd->sc_link, (struct scsi_generic *) &scsi_cmd, 902 sizeof(scsi_cmd), (u_char *) data, sizeof(*data), CDRETRIES, 20000, 903 NULL, SCSI_DATA_OUT); 904 } 905 906 /* 907 * Get scsi driver to send a "start playing" command 908 */ 909 int 910 cd_play(cd, blkno, nblks) 911 struct cd_data *cd; 912 int blkno, nblks; 913 { 914 struct scsi_play scsi_cmd; 915 916 bzero(&scsi_cmd, sizeof(scsi_cmd)); 917 scsi_cmd.op_code = PLAY; 918 scsi_cmd.blk_addr[0] = (blkno >> 24) & 0xff; 919 scsi_cmd.blk_addr[1] = (blkno >> 16) & 0xff; 920 scsi_cmd.blk_addr[2] = (blkno >> 8) & 0xff; 921 scsi_cmd.blk_addr[3] = blkno & 0xff; 922 scsi_cmd.xfer_len[0] = (nblks >> 8) & 0xff; 923 scsi_cmd.xfer_len[1] = nblks & 0xff; 924 return scsi_scsi_cmd(cd->sc_link, (struct scsi_generic *) &scsi_cmd, 925 sizeof(scsi_cmd), 0, 0, CDRETRIES, 200000, NULL, 0); 926 } 927 928 /* 929 * Get scsi driver to send a "start playing" command 930 */ 931 int 932 cd_play_big(cd, blkno, nblks) 933 struct cd_data *cd; 934 int blkno, nblks; 935 { 936 struct scsi_play_big scsi_cmd; 937 938 bzero(&scsi_cmd, sizeof(scsi_cmd)); 939 scsi_cmd.op_code = PLAY_BIG; 940 scsi_cmd.blk_addr[0] = (blkno >> 24) & 0xff; 941 scsi_cmd.blk_addr[1] = (blkno >> 16) & 0xff; 942 scsi_cmd.blk_addr[2] = (blkno >> 8) & 0xff; 943 scsi_cmd.blk_addr[3] = blkno & 0xff; 944 scsi_cmd.xfer_len[0] = (nblks >> 24) & 0xff; 945 scsi_cmd.xfer_len[1] = (nblks >> 16) & 0xff; 946 scsi_cmd.xfer_len[2] = (nblks >> 8) & 0xff; 947 scsi_cmd.xfer_len[3] = nblks & 0xff; 948 return scsi_scsi_cmd(cd->sc_link, (struct scsi_generic *) &scsi_cmd, 949 sizeof(scsi_cmd), 0, 0, CDRETRIES, 20000, NULL, 0); 950 } 951 952 /* 953 * Get scsi driver to send a "start playing" command 954 */ 955 int 956 cd_play_tracks(cd, strack, sindex, etrack, eindex) 957 struct cd_data *cd; 958 int strack, sindex, etrack, eindex; 959 { 960 struct scsi_play_track scsi_cmd; 961 962 bzero(&scsi_cmd, sizeof(scsi_cmd)); 963 scsi_cmd.op_code = PLAY_TRACK; 964 scsi_cmd.start_track = strack; 965 scsi_cmd.start_index = sindex; 966 scsi_cmd.end_track = etrack; 967 scsi_cmd.end_index = eindex; 968 return scsi_scsi_cmd(cd->sc_link, (struct scsi_generic *) &scsi_cmd, 969 sizeof(scsi_cmd), 0, 0, CDRETRIES, 20000, NULL, 0); 970 } 971 972 /* 973 * Get scsi driver to send a "play msf" command 974 */ 975 int 976 cd_play_msf(cd, startm, starts, startf, endm, ends, endf) 977 struct cd_data *cd; 978 int startm, starts, startf, endm, ends, endf; 979 { 980 struct scsi_play_msf scsi_cmd; 981 982 bzero(&scsi_cmd, sizeof(scsi_cmd)); 983 scsi_cmd.op_code = PLAY_MSF; 984 scsi_cmd.start_m = startm; 985 scsi_cmd.start_s = starts; 986 scsi_cmd.start_f = startf; 987 scsi_cmd.end_m = endm; 988 scsi_cmd.end_s = ends; 989 scsi_cmd.end_f = endf; 990 return scsi_scsi_cmd(cd->sc_link, (struct scsi_generic *) &scsi_cmd, 991 sizeof(scsi_cmd), 0, 0, CDRETRIES, 2000, NULL, 0); 992 } 993 994 /* 995 * Get scsi driver to send a "start up" command 996 */ 997 int 998 cd_pause(cd, go) 999 struct cd_data *cd; 1000 int go; 1001 { 1002 struct scsi_pause scsi_cmd; 1003 1004 bzero(&scsi_cmd, sizeof(scsi_cmd)); 1005 scsi_cmd.op_code = PAUSE; 1006 scsi_cmd.resume = go; 1007 return scsi_scsi_cmd(cd->sc_link, (struct scsi_generic *) &scsi_cmd, 1008 sizeof(scsi_cmd), 0, 0, CDRETRIES, 2000, NULL, 0); 1009 } 1010 1011 /* 1012 * Get scsi driver to send a "RESET" command 1013 */ 1014 int 1015 cd_reset(cd) 1016 struct cd_data *cd; 1017 { 1018 1019 return scsi_scsi_cmd(cd->sc_link, 0, 0, 0, 0, CDRETRIES, 2000, NULL, 1020 SCSI_RESET); 1021 } 1022 1023 /* 1024 * Read subchannel 1025 */ 1026 int 1027 cd_read_subchannel(cd, mode, format, track, data, len) 1028 struct cd_data *cd; 1029 int mode, format, len; 1030 struct cd_sub_channel_info *data; 1031 { 1032 struct scsi_read_subchannel scsi_cmd; 1033 1034 bzero(&scsi_cmd, sizeof(scsi_cmd)); 1035 scsi_cmd.op_code = READ_SUBCHANNEL; 1036 if (mode == CD_MSF_FORMAT) 1037 scsi_cmd.byte2 |= CD_MSF; 1038 scsi_cmd.byte3 = SRS_SUBQ; 1039 scsi_cmd.subchan_format = format; 1040 scsi_cmd.track = track; 1041 scsi_cmd.data_len[0] = (len) >> 8; 1042 scsi_cmd.data_len[1] = (len) & 0xff; 1043 return scsi_scsi_cmd(cd->sc_link, (struct scsi_generic *) &scsi_cmd, 1044 sizeof(struct scsi_read_subchannel), (u_char *) data, len, 1045 CDRETRIES, 5000, NULL, SCSI_DATA_IN); 1046 } 1047 1048 /* 1049 * Read table of contents 1050 */ 1051 int 1052 cd_read_toc(cd, mode, start, data, len) 1053 struct cd_data *cd; 1054 int mode, start, len; 1055 struct cd_toc_entry *data; 1056 { 1057 struct scsi_read_toc scsi_cmd; 1058 int ntoc; 1059 1060 bzero(&scsi_cmd, sizeof(scsi_cmd)); 1061 /*if (len!=sizeof(struct ioc_toc_header)) 1062 * ntoc=((len)-sizeof(struct ioc_toc_header))/sizeof(struct cd_toc_entry); 1063 * else */ 1064 ntoc = len; 1065 scsi_cmd.op_code = READ_TOC; 1066 if (mode == CD_MSF_FORMAT) 1067 scsi_cmd.byte2 |= CD_MSF; 1068 scsi_cmd.from_track = start; 1069 scsi_cmd.data_len[0] = (ntoc) >> 8; 1070 scsi_cmd.data_len[1] = (ntoc) & 0xff; 1071 return scsi_scsi_cmd(cd->sc_link, (struct scsi_generic *) &scsi_cmd, 1072 sizeof(struct scsi_read_toc), (u_char *) data, len, CDRETRIES, 1073 5000, NULL, SCSI_DATA_IN); 1074 } 1075 1076 #define b2tol(a) (((unsigned)(a##_1) << 8) + (unsigned)a##_0) 1077 1078 /* 1079 * Get the scsi driver to send a full inquiry to the device and use the 1080 * results to fill out the disk parameter structure. 1081 */ 1082 int 1083 cd_get_parms(cd, flags) 1084 struct cd_data *cd; 1085 int flags; 1086 { 1087 1088 /* 1089 * First check if we have it all loaded 1090 */ 1091 if (cd->sc_link->flags & SDEV_MEDIA_LOADED) 1092 return 0; 1093 1094 /* 1095 * give a number of sectors so that sec * trks * cyls 1096 * is <= disk_size 1097 */ 1098 if (!cd_size(cd, flags)) 1099 return ENXIO; 1100 1101 cd->sc_link->flags |= SDEV_MEDIA_LOADED; 1102 return 0; 1103 } 1104 1105 int 1106 cdsize(dev) 1107 dev_t dev; 1108 { 1109 1110 return -1; 1111 } 1112 1113 int 1114 cddump() 1115 { 1116 1117 /* Not implemented. */ 1118 return EINVAL; 1119 } 1120