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