1 /* 2 * Written by Julian Elischer (julian@tfs.com) 3 * for TRW Financial Systems for use under the MACH(2.5) operating system. 4 * Hacked by Theo de Raadt <deraadt@fsa.ca> 5 * 6 * TRW Financial Systems, in accordance with their agreement with Carnegie 7 * Mellon University, makes this software available to CMU to distribute 8 * or use in any manner that they see fit as long as this message is kept with 9 * the software. For this reason TFS also grants any other persons or 10 * organisations permission to use or modify this software. 11 * 12 * TFS supplies this software to be publicly redistributed 13 * on the understanding that TFS is not responsible for the correct 14 * functioning of this software in any circumstances. 15 * 16 * $Id: cd.c,v 1.18 1993/08/04 19:33:44 brezak Exp $ 17 */ 18 19 #define SPLCD splbio 20 #define ESUCCESS 0 21 22 #include "cd.h" 23 #include "sys/types.h" 24 #include "sys/param.h" 25 #include "sys/dkbad.h" 26 #include "sys/systm.h" 27 #include "sys/conf.h" 28 #include "sys/file.h" 29 #include "sys/stat.h" 30 #include "sys/ioctl.h" 31 #include "sys/buf.h" 32 #include "sys/uio.h" 33 #include "sys/malloc.h" 34 #include "sys/cdio.h" 35 36 #include "sys/errno.h" 37 #include "sys/disklabel.h" 38 #include "scsi/scsi_all.h" 39 #include "scsi/scsi_cd.h" 40 #include "scsi/cddefs.h" 41 #include "scsi/scsi_disk.h" /* rw_big and start_stop come from there */ 42 #include "scsi/scsiconf.h" 43 44 long int cdstrats,cdqueues; 45 46 47 #ifdef DDB 48 int Debugger(); 49 #else 50 #define Debugger() 51 #endif 52 53 54 #define PAGESIZ 4096 55 #define SECSIZE 2048 /* XXX */ /* default only */ 56 #define CDOUTSTANDING 2 57 #define CDQSIZE 4 58 #define CD_RETRIES 4 59 60 #define UNITSHIFT 3 61 #define PARTITION(z) (minor(z) & 0x07) 62 #define RAW_PART 3 63 #define UNIT(z) ( (minor(z) >> UNITSHIFT) ) 64 65 #undef NCD 66 #define NCD ( makedev(1,0) >> UNITSHIFT) 67 68 extern int hz; 69 int cd_done(); 70 int cdstrategy(); 71 int cd_debug = 0; 72 73 struct buf cd_buf_queue[NCD]; 74 struct scsi_xfer cd_scsi_xfer[NCD][CDOUTSTANDING]; /* XXX */ 75 struct scsi_xfer *cd_free_xfer[NCD]; 76 int cd_xfer_block_wait[NCD]; 77 78 struct cd_data *cd_data[NCD]; 79 80 #define CD_STOP 0 81 #define CD_START 1 82 #define CD_EJECT -2 83 84 /* 85 * The routine called by the low level scsi routine when it discovers 86 * A device suitable for this driver 87 */ 88 int 89 cdattach(int masunit, struct scsi_switch *sw, int physid, int *unit) 90 { 91 unsigned char *tbl; 92 struct cd_data *cd; 93 struct cd_parms *dp; 94 int targ, lun, i; 95 96 targ = physid >> 3; 97 lun = physid & 7; 98 99 if(*unit == -1) { 100 for(i=0; i<NCD && *unit==-1; i++) 101 if(cd_data[i]==NULL) 102 *unit = i; 103 } 104 if(*unit >= NCD || *unit == -1) 105 return 0; 106 if(cd_data[*unit]) 107 return 0; 108 109 cd = cd_data[*unit] = (struct cd_data *)malloc(sizeof *cd, 110 M_TEMP, M_NOWAIT); 111 if(!cd) 112 return 0; 113 bzero(cd, sizeof *cd); 114 115 dp = &(cd->params); 116 if(scsi_debug & PRINTROUTINES) printf("cdattach: "); 117 118 /*******************************************************\ 119 * Store information needed to contact our base driver * 120 \*******************************************************/ 121 cd->sc_sw = sw; 122 cd->ctlr = masunit; 123 cd->targ = targ; 124 cd->lu = lun; 125 cd->cmdscount = CDOUTSTANDING; /* XXX (ask the board) */ 126 127 128 i = cd->cmdscount; 129 while(i--) { 130 cd_scsi_xfer[*unit][i].next = cd_free_xfer[*unit]; 131 cd_free_xfer[*unit] = &cd_scsi_xfer[*unit][i]; 132 } 133 /*******************************************************\ 134 * Use the subdriver to request information regarding * 135 * the drive. We cannot use interrupts yet, so the * 136 * request must specify this. * 137 \*******************************************************/ 138 cd_get_parms(*unit, SCSI_NOSLEEP | SCSI_NOMASK | SCSI_SILENT); 139 printf("cd%d at %s%d targ %d lun %d: %s\n", 140 *unit, sw->name, masunit, targ, lun, 141 dp->disksize ? "loaded" : "empty"); 142 cd->flags |= CDINIT; 143 return 1; 144 } 145 146 147 /*******************************************************\ 148 * open the device. Make sure the partition info * 149 * is a up-to-date as can be. * 150 \*******************************************************/ 151 cdopen(dev_t dev) 152 { 153 int errcode = 0; 154 int unit, part; 155 struct cd_parms cd_parms; 156 struct cd_data *cd; 157 158 unit = UNIT(dev); 159 part = PARTITION(dev); 160 161 if(scsi_debug & (PRINTROUTINES | TRACEOPENS)) 162 printf("cd%d: open dev=0x%x partition %d)\n", 163 unit, dev, part); 164 165 /*******************************************************\ 166 * Check the unit is legal * 167 \*******************************************************/ 168 if( unit >= NCD ) 169 return(ENXIO); 170 cd = cd_data[unit]; 171 if(!cd) 172 return ENXIO; 173 if (! (cd->flags & CDINIT)) 174 return(ENXIO); 175 176 /*******************************************************\ 177 * If it's been invalidated, and not everybody has * 178 * closed it then forbid re-entry. * 179 * (may have changed media) * 180 \*******************************************************/ 181 if ((! (cd->flags & CDVALID)) 182 && ( cd->openparts)) 183 return(ENXIO); 184 /*******************************************************\ 185 * Check that it is still responding and ok. * 186 * if the media has been changed this will result in a * 187 * "unit attention" error which the error code will * 188 * disregard because the CDVALID flag is not yet set * 189 \*******************************************************/ 190 if (cd_req_sense(unit, SCSI_SILENT) != 0) { 191 if(scsi_debug & TRACEOPENS) 192 printf("not reponding\n"); 193 return(ENXIO); 194 } 195 if(scsi_debug & TRACEOPENS) 196 printf("Device present\n"); 197 /*******************************************************\ 198 * In case it is a funny one, tell it to start * 199 * not needed for hard drives * 200 \*******************************************************/ 201 cd_start_unit(unit,part,CD_START); 202 cd_prevent_unit(unit,PR_PREVENT,SCSI_SILENT); 203 if(scsi_debug & TRACEOPENS) 204 printf("started "); 205 /*******************************************************\ 206 * Load the physical device parameters * 207 \*******************************************************/ 208 cd_get_parms(unit, 0); 209 if(scsi_debug & TRACEOPENS) 210 printf("Params loaded "); 211 /*******************************************************\ 212 * Load the partition info if not already loaded * 213 \*******************************************************/ 214 cdgetdisklabel(unit); 215 if(scsi_debug & TRACEOPENS) 216 printf("Disklabel fabricated "); 217 /*******************************************************\ 218 * Check the partition is legal * 219 \*******************************************************/ 220 if (( part >= cd->disklabel.d_npartitions ) 221 && (part != RAW_PART)) 222 { 223 if(scsi_debug & TRACEOPENS) 224 printf("partition %d > %d\n",part 225 ,cd->disklabel.d_npartitions); 226 cd_prevent_unit(unit,PR_ALLOW,SCSI_SILENT); 227 return(ENXIO); 228 } 229 /*******************************************************\ 230 * Check that the partition exists * 231 \*******************************************************/ 232 if (( cd->disklabel.d_partitions[part].p_fstype != FS_UNUSED ) 233 || (part == RAW_PART)) 234 { 235 cd->partflags[part] |= CDOPEN; 236 cd->openparts |= (1 << part); 237 if(scsi_debug & TRACEOPENS) 238 printf("open complete\n"); 239 cd->flags |= CDVALID; 240 } 241 else 242 { 243 if(scsi_debug & TRACEOPENS) 244 printf("part %d type UNUSED\n",part); 245 cd_prevent_unit(unit,PR_ALLOW,SCSI_SILENT); 246 return(ENXIO); 247 } 248 return(0); 249 } 250 251 /*******************************************************\ 252 * Get ownership of a scsi_xfer structure * 253 * If need be, sleep on it, until it comes free * 254 \*******************************************************/ 255 struct scsi_xfer *cd_get_xs(unit,flags) 256 int flags; 257 int unit; 258 { 259 struct scsi_xfer *xs; 260 int s; 261 262 if(flags & (SCSI_NOSLEEP | SCSI_NOMASK)) 263 { 264 if (xs = cd_free_xfer[unit]) 265 { 266 cd_free_xfer[unit] = xs->next; 267 xs->flags = 0; 268 } 269 } 270 else 271 { 272 s = SPLCD(); 273 while (!(xs = cd_free_xfer[unit])) 274 { 275 cd_xfer_block_wait[unit]++; /* someone waiting! */ 276 tsleep((caddr_t)&cd_free_xfer[unit], PRIBIO+1, 277 "cd_get_xs", 0); 278 cd_xfer_block_wait[unit]--; 279 } 280 cd_free_xfer[unit] = xs->next; 281 splx(s); 282 xs->flags = 0; 283 } 284 return(xs); 285 } 286 287 /*******************************************************\ 288 * Free a scsi_xfer, wake processes waiting for it * 289 \*******************************************************/ 290 void 291 cd_free_xs(int unit, struct scsi_xfer *xs, int flags) 292 { 293 int s; 294 295 if(flags & SCSI_NOMASK) 296 { 297 if (cd_xfer_block_wait[unit]) 298 { 299 printf("cd%d: doing a wakeup from NOMASK mode\n", unit); 300 wakeup((caddr_t)&cd_free_xfer[unit]); 301 } 302 xs->next = cd_free_xfer[unit]; 303 cd_free_xfer[unit] = xs; 304 } 305 else 306 { 307 s = SPLCD(); 308 if (cd_xfer_block_wait[unit]) 309 wakeup((caddr_t)&cd_free_xfer[unit]); 310 xs->next = cd_free_xfer[unit]; 311 cd_free_xfer[unit] = xs; 312 splx(s); 313 } 314 } 315 316 /*******************************************************\ 317 * trim the size of the transfer if needed, * 318 * called by physio * 319 * basically the smaller of our max and the scsi driver's* 320 * minphys (note we have no max ourselves) * 321 \*******************************************************/ 322 /* Trim buffer length if buffer-size is bigger than page size */ 323 void cdminphys(bp) 324 struct buf *bp; 325 { 326 (*(cd_data[UNIT(bp->b_dev)]->sc_sw->scsi_minphys))(bp); 327 } 328 329 /*******************************************************\ 330 * Actually translate the requested transfer into * 331 * one the physical driver can understand * 332 * The transfer is described by a buf and will include * 333 * only one physical transfer. * 334 \*******************************************************/ 335 336 int cdstrategy(bp) 337 struct buf *bp; 338 { 339 struct buf *dp; 340 unsigned int opri; 341 struct cd_data *cd ; 342 int unit; 343 344 cdstrats++; 345 unit = UNIT((bp->b_dev)); 346 cd = cd_data[unit]; 347 if(scsi_debug & PRINTROUTINES) printf("\ncdstrategy "); 348 if(scsi_debug & SHOWREQUESTS) printf("cd%d: %d bytes @ blk%d\n", 349 unit,bp->b_bcount,bp->b_blkno); 350 351 if(!cd) { 352 bp->b_error = EIO; 353 goto bad; 354 } 355 if(!(cd->flags & CDVALID)) { 356 bp->b_error = EIO; 357 goto bad; 358 } 359 360 cdminphys(bp); 361 /*******************************************************\ 362 * If the device has been made invalid, error out * 363 * maybe the media changed * 364 \*******************************************************/ 365 366 /*******************************************************\ 367 * can't ever write to a CD * 368 \*******************************************************/ 369 if ((bp->b_flags & B_READ) == 0) { 370 bp->b_error = EROFS; 371 goto bad; 372 } 373 /*******************************************************\ 374 * If it's a null transfer, return immediatly * 375 \*******************************************************/ 376 if (bp->b_bcount == 0) { 377 goto done; 378 } 379 380 /*******************************************************\ 381 * Decide which unit and partition we are talking about * 382 \*******************************************************/ 383 if(PARTITION(bp->b_dev) != RAW_PART) 384 { 385 if (!(cd->flags & CDHAVELABEL)) 386 { 387 bp->b_error = EIO; 388 goto bad; 389 } 390 /* 391 * do bounds checking, adjust transfer. if error, process. 392 * if end of partition, just return 393 */ 394 if (bounds_check_with_label(bp,&cd->disklabel,1) <= 0) 395 goto done; 396 /* otherwise, process transfer request */ 397 } 398 399 opri = SPLCD(); 400 dp = &cd_buf_queue[unit]; 401 402 /*******************************************************\ 403 * Place it in the queue of disk activities for this disk* 404 \*******************************************************/ 405 disksort(dp, bp); 406 407 /*******************************************************\ 408 * Tell the device to get going on the transfer if it's * 409 * not doing anything, otherwise just wait for completion* 410 \*******************************************************/ 411 cdstart(unit); 412 413 splx(opri); 414 return; 415 bad: 416 bp->b_flags |= B_ERROR; 417 done: 418 419 /*******************************************************\ 420 * Correctly set the buf to indicate a completed xfer * 421 \*******************************************************/ 422 bp->b_resid = bp->b_bcount; 423 biodone(bp); 424 return; 425 } 426 427 /***************************************************************\ 428 * cdstart looks to see if there is a buf waiting for the device * 429 * and that the device is not already busy. If both are true, * 430 * It deques the buf and creates a scsi command to perform the * 431 * transfer in the buf. The transfer request will call cd_done * 432 * on completion, which will in turn call this routine again * 433 * so that the next queued transfer is performed. * 434 * The bufs are queued by the strategy routine (cdstrategy) * 435 * * 436 * This routine is also called after other non-queued requests * 437 * have been made of the scsi driver, to ensure that the queue * 438 * continues to be drained. * 439 * * 440 * must be called at the correct (highish) spl level * 441 \***************************************************************/ 442 /* cdstart() is called at SPLCD from cdstrategy and cd_done*/ 443 void 444 cdstart(int unit) 445 { 446 register struct buf *bp = 0; 447 register struct buf *dp; 448 struct scsi_xfer *xs; 449 struct scsi_rw_big cmd; 450 int blkno, nblk; 451 struct cd_data *cd = cd_data[unit]; 452 struct partition *p ; 453 454 if(scsi_debug & PRINTROUTINES) printf("cdstart%d ",unit); 455 /*******************************************************\ 456 * See if there is a buf to do and we are not already * 457 * doing one * 458 \*******************************************************/ 459 if(!cd_free_xfer[unit]) 460 { 461 return; /* none for us, unit already underway */ 462 } 463 464 if(cd_xfer_block_wait[unit]) /* there is one, but a special waits */ 465 { 466 return; /* give the special that's waiting a chance to run */ 467 } 468 469 470 dp = &cd_buf_queue[unit]; 471 if ((bp = dp->b_actf) != NULL) /* yes, an assign */ 472 { 473 dp->b_actf = bp->av_forw; 474 } 475 else 476 { 477 return; 478 } 479 480 xs=cd_get_xs(unit,0); /* ok we can grab it */ 481 xs->flags = INUSE; /* Now ours */ 482 /***************************************************************\ 483 * Should reject all queued entries if CDVALID is not true * 484 \***************************************************************/ 485 if(!(cd->flags & CDVALID)) 486 { 487 goto bad; /* no I/O.. media changed or something */ 488 } 489 490 /*******************************************************\ 491 * We have a buf, now we should move the data into * 492 * a scsi_xfer definition and try start it * 493 \*******************************************************/ 494 /*******************************************************\ 495 * First, translate the block to absolute * 496 * and put it in terms of the logical blocksize of the * 497 * device.. * 498 \*******************************************************/ 499 p = cd->disklabel.d_partitions + PARTITION(bp->b_dev); 500 blkno = ((bp->b_blkno / (cd->params.blksize/512)) + p->p_offset); 501 nblk = (bp->b_bcount + (cd->params.blksize - 1)) / (cd->params.blksize); 502 503 /*******************************************************\ 504 * Fill out the scsi command * 505 \*******************************************************/ 506 bzero(&cmd, sizeof(cmd)); 507 cmd.op_code = READ_BIG; 508 cmd.addr_3 = (blkno & 0xff000000) >> 24; 509 cmd.addr_2 = (blkno & 0xff0000) >> 16; 510 cmd.addr_1 = (blkno & 0xff00) >> 8; 511 cmd.addr_0 = blkno & 0xff; 512 cmd.length2 = (nblk & 0xff00) >> 8; 513 cmd.length1 = (nblk & 0xff); 514 /*******************************************************\ 515 * Fill out the scsi_xfer structure * 516 * Note: we cannot sleep as we may be an interrupt * 517 \*******************************************************/ 518 xs->flags |= SCSI_NOSLEEP; 519 xs->adapter = cd->ctlr; 520 xs->targ = cd->targ; 521 xs->lu = cd->lu; 522 xs->retries = CD_RETRIES; 523 xs->timeout = 10000;/* 10000 millisecs for a disk !*/ 524 xs->cmd = (struct scsi_generic *)&cmd; 525 xs->cmdlen = sizeof(cmd); 526 xs->resid = bp->b_bcount; 527 xs->when_done = cd_done; 528 xs->done_arg = unit; 529 xs->done_arg2 = (int)xs; 530 xs->error = XS_NOERROR; 531 xs->bp = bp; 532 xs->data = (u_char *)bp->b_un.b_addr; 533 xs->datalen = bp->b_bcount; 534 535 /*******************************************************\ 536 * Pass all this info to the scsi driver. * 537 \*******************************************************/ 538 if ( (*(cd->sc_sw->scsi_cmd))(xs) != SUCCESSFULLY_QUEUED) 539 { 540 printf("cd%d: oops not queued",unit); 541 goto bad; 542 } 543 cdqueues++; 544 return; 545 bad: xs->error = XS_DRIVER_STUFFUP; 546 cd_done(unit,xs); 547 } 548 549 /*******************************************************\ 550 * This routine is called by the scsi interrupt when * 551 * the transfer is complete. (or failed) * 552 \*******************************************************/ 553 int cd_done(unit,xs) 554 int unit; 555 struct scsi_xfer *xs; 556 { 557 struct buf *bp; 558 int retval; 559 560 if(scsi_debug & PRINTROUTINES) printf("cd_done%d ",unit); 561 if (! (xs->flags & INUSE)) /* paranoia always pays off */ 562 panic("scsi_xfer not in use!"); 563 if(bp = xs->bp) 564 { 565 switch(xs->error) 566 { 567 case XS_NOERROR: 568 bp->b_error = 0; 569 bp->b_resid = 0; 570 break; 571 572 case XS_SENSE: 573 retval = (cd_interpret_sense(unit,xs)); 574 if(retval) 575 { 576 bp->b_flags |= B_ERROR; 577 bp->b_error = retval; 578 } 579 break; 580 581 case XS_TIMEOUT: 582 printf("cd%d: timeout\n",unit); 583 584 case XS_BUSY: 585 /***********************************\ 586 * Just resubmit it straight back to * 587 * the SCSI driver to try it again * 588 \***********************************/ 589 if(xs->retries--) 590 { 591 xs->error = XS_NOERROR; 592 xs->flags &= ~ITSDONE; 593 if ( (*(cd_data[unit]->sc_sw->scsi_cmd))(xs) 594 == SUCCESSFULLY_QUEUED) 595 { /* shhh! don't wake the job, ok? */ 596 /* don't tell cdstart either, */ 597 return; 598 } 599 /* xs->error is set by the scsi driver */ 600 } /* Fall through */ 601 602 case XS_DRIVER_STUFFUP: 603 bp->b_flags |= B_ERROR; 604 bp->b_error = EIO; 605 break; 606 default: 607 printf("cd%d: unknown error category from scsi driver\n" 608 ,unit); 609 } 610 biodone(bp); 611 cd_free_xs(unit,xs,0); 612 cdstart(unit); /* If there's anything waiting.. do it */ 613 } 614 else /* special has finished */ 615 { 616 wakeup((caddr_t)xs); 617 } 618 } 619 /*******************************************************\ 620 * Perform special action on behalf of the user * 621 * Knows about the internals of this device * 622 \*******************************************************/ 623 cdioctl(dev_t dev, int cmd, caddr_t addr, int flag) 624 { 625 int error = 0; 626 unsigned int opri; 627 unsigned char unit, part; 628 register struct cd_data *cd; 629 630 631 /*******************************************************\ 632 * Find the device that the user is talking about * 633 \*******************************************************/ 634 unit = UNIT(dev); 635 part = PARTITION(dev); 636 cd = cd_data[unit]; 637 if(scsi_debug & PRINTROUTINES) printf("cdioctl%d ",unit); 638 639 /*******************************************************\ 640 * If the device is not valid.. abandon ship * 641 \*******************************************************/ 642 if(!cd) 643 return ENXIO; 644 if (!(cd_data[unit]->flags & CDVALID)) 645 return ENXIO; 646 647 switch(cmd) 648 { 649 650 case DIOCSBAD: 651 error = EINVAL; 652 break; 653 654 case DIOCGDINFO: 655 *(struct disklabel *)addr = cd->disklabel; 656 break; 657 658 case DIOCGPART: 659 ((struct partinfo *)addr)->disklab = &cd->disklabel; 660 ((struct partinfo *)addr)->part = 661 &cd->disklabel.d_partitions[PARTITION(dev)]; 662 break; 663 664 case DIOCWDINFO: 665 case DIOCSDINFO: 666 if ((flag & FWRITE) == 0) 667 error = EBADF; 668 else 669 error = setdisklabel(&cd->disklabel, 670 (struct disklabel *)addr, 671 /*(cd->flags & DKFL_BSDLABEL) ? cd->openparts : */0, 672 0); 673 if (error == 0) { 674 cd->flags |= CDHAVELABEL; 675 } 676 break; 677 678 case DIOCWLABEL: 679 error = EBADF; 680 break; 681 682 case CDIOCPLAYTRACKS: 683 { 684 struct ioc_play_track *args 685 = (struct ioc_play_track *)addr; 686 struct cd_mode_data data; 687 if(error = cd_get_mode(unit,&data,AUDIO_PAGE)) 688 break; 689 data.page.audio.sotc = 0; 690 data.page.audio.immed = 1; 691 if(error = cd_set_mode(unit,&data)) 692 break; 693 return(cd_play_tracks(unit 694 ,args->start_track 695 ,args->start_index 696 ,args->end_track 697 ,args->end_index 698 )); 699 } 700 break; 701 case CDIOCPLAYMSF: 702 { 703 struct ioc_play_msf *args 704 = (struct ioc_play_msf *)addr; 705 struct cd_mode_data data; 706 if(error = cd_get_mode(unit,&data,AUDIO_PAGE)) 707 break; 708 data.page.audio.sotc = 0; 709 data.page.audio.immed = 1; 710 if(error = cd_set_mode(unit,&data)) 711 break; 712 return(cd_play_msf(unit 713 ,args->start_m 714 ,args->start_s 715 ,args->start_f 716 ,args->end_m 717 ,args->end_s 718 ,args->end_f 719 )); 720 } 721 break; 722 case CDIOCPLAYBLOCKS: 723 { 724 struct ioc_play_blocks *args 725 = (struct ioc_play_blocks *)addr; 726 struct cd_mode_data data; 727 if(error = cd_get_mode(unit,&data,AUDIO_PAGE)) 728 break; 729 data.page.audio.sotc = 0; 730 data.page.audio.immed = 1; 731 if(error = cd_set_mode(unit,&data)) 732 break; 733 return(cd_play(unit,args->blk,args->len)); 734 735 736 } 737 break; 738 case CDIOCREADSUBCHANNEL: 739 { 740 struct ioc_read_subchannel *args 741 = (struct ioc_read_subchannel *)addr; 742 struct cd_sub_channel_info data; 743 int len=args->data_len; 744 if(len>sizeof(data)|| 745 len<sizeof(struct cd_sub_channel_header)) { 746 error=EINVAL; 747 break; 748 } 749 if(error = cd_read_subchannel(unit,args->address_format, 750 args->data_format,args->track,&data,len)) { 751 break; 752 } 753 len=MIN(len,((data.header.data_len[0]<<8)+data.header.data_len[1]+ 754 sizeof(struct cd_sub_channel_header))); 755 if(copyout(&data,args->data,len)!=0) { 756 error=EFAULT; 757 } 758 } 759 break; 760 case CDIOREADTOCHEADER: 761 { 762 struct ioc_toc_header th; 763 if( error = cd_read_toc(unit, 0, 0, 764 (struct cd_toc_entry *)&th,sizeof(th))) 765 break; 766 th.len=(th.len&0xff)<<8+((th.len>>8)&0xff); 767 bcopy(&th,addr,sizeof(th)); 768 } 769 break; 770 case CDIOREADTOCENTRYS: 771 { 772 struct ioc_read_toc_entry *te= 773 (struct ioc_read_toc_entry *)addr; 774 struct cd_toc_entry data[65]; 775 struct ioc_toc_header *th; 776 int len=te->data_len; 777 th=(struct ioc_toc_header *)data; 778 779 if(len>sizeof(data) || len<sizeof(struct cd_toc_entry)) { 780 error=EINVAL; 781 break; 782 } 783 if(error = cd_read_toc(unit,te->address_format, 784 te->starting_track, 785 (struct cd_toc_entry *)data, 786 len)) 787 break; 788 len=MIN(len,((((th->len&0xff)<<8)+((th->len>>8)))+ 789 sizeof(*th))); 790 if(copyout(th,te->data,len)!=0) { 791 error=EFAULT; 792 } 793 794 } 795 break; 796 case CDIOCSETPATCH: 797 { 798 struct ioc_patch *arg = (struct ioc_patch *)addr; 799 struct cd_mode_data data; 800 if(error = cd_get_mode(unit,&data,AUDIO_PAGE)) 801 break; 802 data.page.audio.port[LEFT_PORT].channels = arg->patch[0]; 803 data.page.audio.port[RIGHT_PORT].channels = arg->patch[1]; 804 data.page.audio.port[2].channels = arg->patch[2]; 805 data.page.audio.port[3].channels = arg->patch[3]; 806 if(error = cd_set_mode(unit,&data)) 807 break; 808 } 809 break; 810 case CDIOCGETVOL: 811 { 812 struct ioc_vol *arg = (struct ioc_vol *)addr; 813 struct cd_mode_data data; 814 if(error = cd_get_mode(unit,&data,AUDIO_PAGE)) 815 break; 816 arg->vol[LEFT_PORT] = data.page.audio.port[LEFT_PORT].volume; 817 arg->vol[RIGHT_PORT] = data.page.audio.port[RIGHT_PORT].volume; 818 arg->vol[2] = data.page.audio.port[2].volume; 819 arg->vol[3] = data.page.audio.port[3].volume; 820 } 821 break; 822 case CDIOCSETVOL: 823 { 824 struct ioc_vol *arg = (struct ioc_vol *)addr; 825 struct cd_mode_data data; 826 if(error = cd_get_mode(unit,&data,AUDIO_PAGE)) 827 break; 828 data.page.audio.port[LEFT_PORT].volume = arg->vol[LEFT_PORT]; 829 data.page.audio.port[RIGHT_PORT].volume = arg->vol[RIGHT_PORT]; 830 data.page.audio.port[2].volume = arg->vol[2]; 831 data.page.audio.port[3].volume = arg->vol[3]; 832 if(error = cd_set_mode(unit,&data)) 833 break; 834 } 835 break; 836 case CDIOCSETMONO: 837 { 838 struct ioc_vol *arg = (struct ioc_vol *)addr; 839 struct cd_mode_data data; 840 if(error = cd_get_mode(unit,&data,AUDIO_PAGE)) 841 break; 842 data.page.audio.port[LEFT_PORT].channels = LEFT_CHANNEL|RIGHT_CHANNEL|4|8; 843 data.page.audio.port[RIGHT_PORT].channels = LEFT_CHANNEL|RIGHT_CHANNEL; 844 data.page.audio.port[2].channels = 0; 845 data.page.audio.port[3].channels = 0; 846 if(error = cd_set_mode(unit,&data)) 847 break; 848 } 849 break; 850 case CDIOCSETSTERIO: 851 { 852 struct ioc_vol *arg = (struct ioc_vol *)addr; 853 struct cd_mode_data data; 854 if(error = cd_get_mode(unit,&data,AUDIO_PAGE)) 855 break; 856 data.page.audio.port[LEFT_PORT].channels = LEFT_CHANNEL; 857 data.page.audio.port[RIGHT_PORT].channels = RIGHT_CHANNEL; 858 data.page.audio.port[2].channels = 0; 859 data.page.audio.port[3].channels = 0; 860 if(error = cd_set_mode(unit,&data)) 861 break; 862 } 863 break; 864 case CDIOCSETMUTE: 865 { 866 struct ioc_vol *arg = (struct ioc_vol *)addr; 867 struct cd_mode_data data; 868 if(error = cd_get_mode(unit,&data,AUDIO_PAGE)) 869 break; 870 data.page.audio.port[LEFT_PORT].channels = 0; 871 data.page.audio.port[RIGHT_PORT].channels = 0; 872 data.page.audio.port[2].channels = 0; 873 data.page.audio.port[3].channels = 0; 874 if(error = cd_set_mode(unit,&data)) 875 break; 876 } 877 break; 878 case CDIOCSETLEFT: 879 { 880 struct ioc_vol *arg = (struct ioc_vol *)addr; 881 struct cd_mode_data data; 882 if(error = cd_get_mode(unit,&data,AUDIO_PAGE)) 883 break; 884 data.page.audio.port[LEFT_PORT].channels = 15; 885 data.page.audio.port[RIGHT_PORT].channels = 15; 886 data.page.audio.port[2].channels = 15; 887 data.page.audio.port[3].channels = 15; 888 if(error = cd_set_mode(unit,&data)) 889 break; 890 } 891 break; 892 case CDIOCSETRIGHT: 893 { 894 struct ioc_vol *arg = (struct ioc_vol *)addr; 895 struct cd_mode_data data; 896 if(error = cd_get_mode(unit,&data,AUDIO_PAGE)) 897 break; 898 data.page.audio.port[LEFT_PORT].channels = RIGHT_CHANNEL; 899 data.page.audio.port[RIGHT_PORT].channels = RIGHT_CHANNEL; 900 data.page.audio.port[2].channels = 0; 901 data.page.audio.port[3].channels = 0; 902 if(error = cd_set_mode(unit,&data)) 903 break; 904 } 905 break; 906 case CDIOCRESUME: 907 error = cd_pause(unit,1); 908 break; 909 case CDIOCPAUSE: 910 error = cd_pause(unit,0); 911 break; 912 case CDIOCSTART: 913 error = cd_start_unit(unit,part,CD_START); 914 break; 915 case CDIOCSTOP: 916 error = cd_start_unit(unit,part,CD_STOP); 917 break; 918 case CDIOCEJECT: 919 error = cd_start_unit(unit,part,CD_EJECT); 920 break; 921 case CDIOCSETDEBUG: 922 scsi_debug = 0xfff; cd_debug = 0xfff; 923 break; 924 case CDIOCCLRDEBUG: 925 scsi_debug = 0; cd_debug = 0; 926 break; 927 case CDIOCRESET: 928 return(cd_reset(unit)); 929 break; 930 default: 931 error = ENOTTY; 932 break; 933 } 934 return (error); 935 } 936 937 938 /*******************************************************\ 939 * Load the label information on the named device * 940 * * 941 * EVENTUALLY take information about different * 942 * data tracks from the TOC and put it in the disklabel * 943 \*******************************************************/ 944 int cdgetdisklabel(unit) 945 unsigned char unit; 946 { 947 /*unsigned int n, m;*/ 948 char *errstring; 949 struct cd_data *cd = cd_data[unit]; 950 951 /*******************************************************\ 952 * If the inflo is already loaded, use it * 953 \*******************************************************/ 954 if(cd->flags & CDHAVELABEL) return; 955 956 bzero(&cd->disklabel,sizeof(struct disklabel)); 957 /*******************************************************\ 958 * make partition 3 the whole disk in case of failure * 959 * then get pdinfo * 960 \*******************************************************/ 961 strncpy(cd->disklabel.d_typename,"scsi cd_rom",16); 962 strncpy(cd->disklabel.d_packname,"ficticious",16); 963 cd->disklabel.d_secsize = cd->params.blksize; /* as long as it's not 0 */ 964 cd->disklabel.d_nsectors = 100; 965 cd->disklabel.d_ntracks = 1; 966 cd->disklabel.d_ncylinders = (cd->params.disksize / 100) + 1; 967 cd->disklabel.d_secpercyl = 100; 968 cd->disklabel.d_secperunit = cd->params.disksize; 969 cd->disklabel.d_rpm = 300; 970 cd->disklabel.d_interleave = 1; 971 cd->disklabel.d_flags = D_REMOVABLE; 972 973 cd->disklabel.d_npartitions = 1; 974 cd->disklabel.d_partitions[0].p_offset = 0; 975 cd->disklabel.d_partitions[0].p_size = cd->params.disksize; 976 cd->disklabel.d_partitions[0].p_fstype = 9; 977 978 cd->disklabel.d_magic = DISKMAGIC; 979 cd->disklabel.d_magic2 = DISKMAGIC; 980 cd->disklabel.d_checksum = dkcksum(&(cd->disklabel)); 981 982 /*******************************************************\ 983 * Signal to other users and routines that we now have a * 984 * disklabel that represents the media (maybe) * 985 \*******************************************************/ 986 cd->flags |= CDHAVELABEL; 987 return(ESUCCESS); 988 } 989 990 /*******************************************************\ 991 * Find out form the device what it's capacity is * 992 \*******************************************************/ 993 cd_size(unit, flags) 994 { 995 struct scsi_read_cd_cap_data rdcap; 996 struct scsi_read_cd_capacity scsi_cmd; 997 int size; 998 int blksize; 999 1000 /*******************************************************\ 1001 * make up a scsi command and ask the scsi driver to do * 1002 * it for you. * 1003 \*******************************************************/ 1004 bzero((struct scsi_generic *)&scsi_cmd, sizeof(scsi_cmd)); 1005 scsi_cmd.op_code = READ_CD_CAPACITY; 1006 1007 /*******************************************************\ 1008 * If the command works, interpret the result as a 4 byte* 1009 * number of blocks * 1010 \*******************************************************/ 1011 if (cd_scsi_cmd(unit, 1012 (struct scsi_generic *)&scsi_cmd, 1013 sizeof(scsi_cmd), 1014 (u_char *)&rdcap, 1015 sizeof(rdcap), 1016 2000, 1017 flags) != 0) 1018 { 1019 if(!(flags & SCSI_SILENT)) 1020 printf("cd%d: could not get size\n", unit); 1021 return(0); 1022 } else { 1023 size = rdcap.addr_0 + 1 ; 1024 size += rdcap.addr_1 << 8; 1025 size += rdcap.addr_2 << 16; 1026 size += rdcap.addr_3 << 24; 1027 blksize = rdcap.length_0 ; 1028 blksize += rdcap.length_1 << 8; 1029 blksize += rdcap.length_2 << 16; 1030 blksize += rdcap.length_3 << 24; 1031 } 1032 if(cd_debug)printf("cd%d: %d %d byte blocks\n",unit,size,blksize); 1033 cd_data[unit]->params.disksize = size; 1034 cd_data[unit]->params.blksize = blksize; 1035 return(size); 1036 } 1037 1038 /*******************************************************\ 1039 * Check with the device that it is ok, (via scsi driver)* 1040 \*******************************************************/ 1041 cd_req_sense(unit, flags) 1042 { 1043 struct scsi_sense_data sense_data; 1044 struct scsi_sense scsi_cmd; 1045 1046 bzero((struct scsi_generic *)&scsi_cmd, sizeof(scsi_cmd)); 1047 scsi_cmd.op_code = REQUEST_SENSE; 1048 scsi_cmd.length = sizeof(sense_data); 1049 1050 if (cd_scsi_cmd(unit, 1051 (struct scsi_generic *)&scsi_cmd, 1052 sizeof(scsi_cmd), 1053 (u_char *)&sense_data, 1054 sizeof(sense_data), 1055 2000, 1056 flags) != 0) 1057 { 1058 return(ENXIO); 1059 } 1060 else 1061 return(0); 1062 } 1063 1064 /*******************************************************\ 1065 * Get the requested page into the buffer given * 1066 \*******************************************************/ 1067 cd_get_mode(unit,data,page) 1068 int unit; 1069 struct cd_mode_data *data; 1070 int page; 1071 { 1072 struct scsi_mode_sense scsi_cmd; 1073 int retval; 1074 1075 bzero((struct scsi_generic *)&scsi_cmd, sizeof(scsi_cmd)); 1076 bzero(data,sizeof(*data)); 1077 scsi_cmd.op_code = MODE_SENSE; 1078 scsi_cmd.page_code = page; 1079 scsi_cmd.length = sizeof(*data) & 0xff; 1080 retval = cd_scsi_cmd(unit, 1081 (struct scsi_generic *)&scsi_cmd, 1082 sizeof(scsi_cmd), 1083 (u_char *)data, 1084 sizeof(*data), 1085 20000, /* should be immed */ 1086 0); 1087 return (retval); 1088 } 1089 /*******************************************************\ 1090 * Get the requested page into the buffer given * 1091 \*******************************************************/ 1092 cd_set_mode(unit,data) 1093 int unit; 1094 struct cd_mode_data *data; 1095 { 1096 struct scsi_mode_select scsi_cmd; 1097 1098 bzero((struct scsi_generic *)&scsi_cmd, sizeof(scsi_cmd)); 1099 scsi_cmd.op_code = MODE_SELECT; 1100 scsi_cmd.pf = 1; 1101 scsi_cmd.length = sizeof(*data) & 0xff; 1102 data->header.data_length = 0; 1103 /*show_mem(data,sizeof(*data));/**/ 1104 return (cd_scsi_cmd(unit, 1105 (struct scsi_generic *)&scsi_cmd, 1106 sizeof(scsi_cmd), 1107 (u_char *)data, 1108 sizeof(*data), 1109 20000, /* should be immed */ 1110 0) 1111 ); 1112 } 1113 /*******************************************************\ 1114 * Get scsi driver to send a "start playing" command * 1115 \*******************************************************/ 1116 cd_play(unit,blk,len) 1117 int unit,blk,len; 1118 { 1119 struct scsi_play scsi_cmd; 1120 int retval; 1121 1122 bzero((struct scsi_generic *)&scsi_cmd, sizeof(scsi_cmd)); 1123 scsi_cmd.op_code = PLAY; 1124 scsi_cmd.blk_addr[0] = (blk >> 24) & 0xff; 1125 scsi_cmd.blk_addr[1] = (blk >> 16) & 0xff; 1126 scsi_cmd.blk_addr[2] = (blk >> 8) & 0xff; 1127 scsi_cmd.blk_addr[3] = blk & 0xff; 1128 scsi_cmd.xfer_len[0] = (len >> 8) & 0xff; 1129 scsi_cmd.xfer_len[1] = len & 0xff; 1130 retval = cd_scsi_cmd(unit, 1131 (struct scsi_generic *)&scsi_cmd, 1132 sizeof(scsi_cmd), 1133 0, 1134 0, 1135 200000, /* should be immed */ 1136 0); 1137 return(retval); 1138 } 1139 /*******************************************************\ 1140 * Get scsi driver to send a "start playing" command * 1141 \*******************************************************/ 1142 cd_play_big(unit,blk,len) 1143 int unit,blk,len; 1144 { 1145 struct scsi_play_big scsi_cmd; 1146 int retval; 1147 1148 bzero((struct scsi_generic *)&scsi_cmd, sizeof(scsi_cmd)); 1149 scsi_cmd.op_code = PLAY_BIG; 1150 scsi_cmd.blk_addr[0] = (blk >> 24) & 0xff; 1151 scsi_cmd.blk_addr[1] = (blk >> 16) & 0xff; 1152 scsi_cmd.blk_addr[2] = (blk >> 8) & 0xff; 1153 scsi_cmd.blk_addr[3] = blk & 0xff; 1154 scsi_cmd.xfer_len[0] = (len >> 24) & 0xff; 1155 scsi_cmd.xfer_len[1] = (len >> 16) & 0xff; 1156 scsi_cmd.xfer_len[2] = (len >> 8) & 0xff; 1157 scsi_cmd.xfer_len[3] = len & 0xff; 1158 retval = cd_scsi_cmd(unit, 1159 (struct scsi_generic *)&scsi_cmd, 1160 sizeof(scsi_cmd), 1161 0, 1162 0, 1163 20000, /* should be immed */ 1164 0); 1165 return(retval); 1166 } 1167 /*******************************************************\ 1168 * Get scsi driver to send a "start playing" command * 1169 \*******************************************************/ 1170 cd_play_tracks(unit,strack,sindex,etrack,eindex) 1171 int unit,strack,sindex,etrack,eindex; 1172 { 1173 struct scsi_play_track scsi_cmd; 1174 int retval; 1175 1176 bzero((struct scsi_generic *)&scsi_cmd, sizeof(scsi_cmd)); 1177 scsi_cmd.op_code = PLAY_TRACK; 1178 scsi_cmd.start_track = strack; 1179 scsi_cmd.start_index = sindex; 1180 scsi_cmd.end_track = etrack; 1181 scsi_cmd.end_index = eindex; 1182 retval = cd_scsi_cmd(unit, 1183 (struct scsi_generic *)&scsi_cmd, 1184 sizeof(scsi_cmd), 1185 0, 1186 0, 1187 20000, /* should be immed */ 1188 0); 1189 return(retval); 1190 } 1191 /*******************************************************\ 1192 * Get scsi driver to send a "play msf" command * 1193 \*******************************************************/ 1194 cd_play_msf(unit,sm,ss,sf,em,es,ef) 1195 int unit; 1196 u_char sm,ss,sf,em,es,ef; 1197 { 1198 struct scsi_play_msf scsi_cmd; 1199 int retval; 1200 1201 bzero((struct scsi_generic *)&scsi_cmd, sizeof(scsi_cmd)); 1202 scsi_cmd.op_code = PLAY_MSF; 1203 scsi_cmd.start_m = sm; 1204 scsi_cmd.start_s = ss; 1205 scsi_cmd.start_f = sf; 1206 scsi_cmd.end_m = em; 1207 scsi_cmd.end_s = es; 1208 scsi_cmd.end_f = ef; 1209 retval = cd_scsi_cmd(unit, 1210 (struct scsi_generic *)&scsi_cmd, 1211 sizeof(scsi_cmd), 1212 0, 1213 0, 1214 20000, /* should be immed */ 1215 0); 1216 return(retval); 1217 } 1218 /*******************************************************\ 1219 * Get scsi driver to send a "start up" command * 1220 \*******************************************************/ 1221 cd_pause(unit,go) 1222 int unit,go; 1223 { 1224 struct scsi_pause scsi_cmd; 1225 1226 bzero((struct scsi_generic *)&scsi_cmd, sizeof(scsi_cmd)); 1227 scsi_cmd.op_code = PAUSE; 1228 scsi_cmd.resume = go; 1229 1230 return (cd_scsi_cmd(unit, 1231 (struct scsi_generic *)&scsi_cmd, 1232 sizeof(scsi_cmd), 1233 0, 1234 0, 1235 2000, 1236 0)); 1237 } 1238 /*******************************************************\ 1239 * Get scsi driver to send a "start up" command * 1240 \*******************************************************/ 1241 cd_reset(unit) 1242 int unit; 1243 { 1244 return(cd_scsi_cmd(unit,0,0,0,0,2000,SCSI_RESET)); 1245 } 1246 /*******************************************************\ 1247 * Get scsi driver to send a "start up" command * 1248 \*******************************************************/ 1249 cd_start_unit(unit,part,type) 1250 { 1251 struct scsi_start_stop scsi_cmd; 1252 1253 if(type==CD_EJECT && (cd_data[unit]->openparts&~(1<<part)) == 0 ) { 1254 cd_prevent_unit(unit,CD_EJECT,0); 1255 } 1256 1257 bzero((struct scsi_generic *)&scsi_cmd, sizeof(scsi_cmd)); 1258 scsi_cmd.op_code = START_STOP; 1259 scsi_cmd.start = type==CD_START?1:0; 1260 scsi_cmd.loej = type==CD_EJECT?1:0; 1261 1262 if (cd_scsi_cmd(unit, 1263 (struct scsi_generic *)&scsi_cmd, 1264 sizeof(scsi_cmd), 1265 0, 1266 0, 1267 2000, 1268 0) != 0) { 1269 return(ENXIO); 1270 } else 1271 return(0); 1272 } 1273 /*******************************************************\ 1274 * Prevent or allow the user to remove the disk * 1275 \*******************************************************/ 1276 cd_prevent_unit(unit,type,flags) 1277 int unit,type,flags; 1278 { 1279 struct scsi_prevent scsi_cmd; 1280 1281 if(type==CD_EJECT || type==PR_PREVENT || cd_data[unit]->openparts == 0 ) { 1282 bzero((struct scsi_generic *)&scsi_cmd, sizeof(scsi_cmd)); 1283 scsi_cmd.op_code = PREVENT_ALLOW; 1284 scsi_cmd.prevent=type==CD_EJECT?PR_ALLOW:type; 1285 if (cd_scsi_cmd(unit, 1286 (struct scsi_generic *)&scsi_cmd, 1287 sizeof(struct scsi_prevent), 1288 0, 1289 0, 1290 5000, 1291 0) != 0) 1292 { 1293 if(!(flags & SCSI_SILENT)) 1294 printf("cannot prevent/allow on cd%d\n", unit); 1295 return(0); 1296 } 1297 } 1298 return(1); 1299 } 1300 1301 /******************************************************\ 1302 * Read Subchannel * 1303 \******************************************************/ 1304 1305 cd_read_subchannel(unit,mode,format,track,data,len) 1306 int unit,mode,format,len; 1307 struct cd_sub_channel_info *data; 1308 { 1309 struct scsi_read_subchannel scsi_cmd; 1310 int error; 1311 1312 bzero((struct scsi_generic *)&scsi_cmd,sizeof(scsi_cmd)); 1313 1314 scsi_cmd.op_code=READ_SUBCHANNEL; 1315 if(mode==CD_MSF_FORMAT) 1316 scsi_cmd.msf=1; 1317 scsi_cmd.subQ=1; 1318 scsi_cmd.subchan_format=format; 1319 scsi_cmd.track=track; 1320 scsi_cmd.data_len[0]=(len)>>8; 1321 scsi_cmd.data_len[1]=(len)&0xff; 1322 return cd_scsi_cmd(unit, 1323 (struct scsi_generic *)&scsi_cmd, 1324 sizeof(struct scsi_read_subchannel), 1325 (u_char *)data, 1326 len, 1327 5000, 1328 0); 1329 } 1330 1331 /*******************************************************\ 1332 * Read Table of contents * 1333 \*******************************************************/ 1334 cd_read_toc(unit,mode,start,data,len) 1335 int unit,mode,start,len; 1336 struct cd_toc_entry *data; 1337 { 1338 struct scsi_read_toc scsi_cmd; 1339 int error; 1340 int ntoc; 1341 1342 bzero((struct scsi_generic *)&scsi_cmd,sizeof(scsi_cmd)); 1343 /*if(len!=sizeof(struct ioc_toc_header)) 1344 ntoc=((len)-sizeof(struct ioc_toc_header))/sizeof(struct cd_toc_entry); 1345 else*/ 1346 ntoc=len; 1347 1348 scsi_cmd.op_code=READ_TOC; 1349 if(mode==CD_MSF_FORMAT) 1350 scsi_cmd.msf=1; 1351 scsi_cmd.from_track=start; 1352 scsi_cmd.data_len[0]=(ntoc)>>8; 1353 scsi_cmd.data_len[1]=(ntoc)&0xff; 1354 return cd_scsi_cmd(unit, 1355 (struct scsi_generic *)&scsi_cmd, 1356 sizeof(struct scsi_read_toc), 1357 (u_char *)data, 1358 len, 1359 5000, 1360 0); 1361 } 1362 1363 1364 #define b2tol(a) (((unsigned)(a##_1) << 8) + (unsigned)a##_0 ) 1365 1366 /*******************************************************\ 1367 * Get the scsi driver to send a full inquiry to the * 1368 * device and use the results to fill out the disk * 1369 * parameter structure. * 1370 \*******************************************************/ 1371 1372 int cd_get_parms(unit, flags) 1373 { 1374 struct cd_data *cd = cd_data[unit]; 1375 1376 1377 if(!cd) 1378 return 0; 1379 if(cd->flags & CDVALID) 1380 return 0; 1381 1382 /*******************************************************\ 1383 * give a number of sectors so that sec * trks * cyls * 1384 * is <= disk_size * 1385 \*******************************************************/ 1386 if(cd_size(unit, flags)) 1387 { 1388 cd->flags |= CDVALID; 1389 return(0); 1390 } 1391 else 1392 { 1393 return(ENXIO); 1394 } 1395 } 1396 1397 /*******************************************************\ 1398 * close the device.. only called if we are the LAST * 1399 * occurence of an open device * 1400 \*******************************************************/ 1401 int 1402 cdclose(dev_t dev) 1403 { 1404 unsigned char unit, part; 1405 unsigned int old_priority; 1406 1407 unit = UNIT(dev); 1408 part = PARTITION(dev); 1409 if(scsi_debug & TRACEOPENS) 1410 printf("closing cd%d part %d\n",unit,part); 1411 cd_data[unit]->partflags[part] &= ~CDOPEN; 1412 cd_data[unit]->openparts &= ~(1 << part); 1413 cd_prevent_unit(unit,PR_ALLOW,SCSI_SILENT); 1414 return(0); 1415 } 1416 1417 /*******************************************************\ 1418 * ask the scsi driver to perform a command for us. * 1419 * Call it through the switch table, and tell it which * 1420 * sub-unit we want, and what target and lu we wish to * 1421 * talk to. Also tell it where to find the command * 1422 * how long int is. * 1423 * Also tell it where to read/write the data, and how * 1424 * long the data is supposed to be * 1425 \*******************************************************/ 1426 int cd_scsi_cmd(unit,scsi_cmd,cmdlen,data_addr,datalen,timeout,flags) 1427 1428 int unit,flags; 1429 struct scsi_generic *scsi_cmd; 1430 int cmdlen; 1431 int timeout; 1432 u_char *data_addr; 1433 int datalen; 1434 { 1435 struct scsi_xfer *xs; 1436 int retval; 1437 int s; 1438 struct cd_data *cd = cd_data[unit]; 1439 1440 if(scsi_debug & PRINTROUTINES) printf("\ncd_scsi_cmd%d ",unit); 1441 if(cd->sc_sw) /* If we have a scsi driver */ 1442 { 1443 xs = cd_get_xs(unit,flags); /* should wait unless booting */ 1444 if(!xs) 1445 { 1446 printf("cd%d: cd_scsi_cmd: controller busy" 1447 " (this should never happen)\n",unit); 1448 return(EBUSY); 1449 } 1450 xs->flags |= INUSE; 1451 /*******************************************************\ 1452 * Fill out the scsi_xfer structure * 1453 \*******************************************************/ 1454 xs->flags |= flags; 1455 xs->adapter = cd->ctlr; 1456 xs->targ = cd->targ; 1457 xs->lu = cd->lu; 1458 xs->retries = CD_RETRIES; 1459 xs->timeout = timeout; 1460 xs->cmd = scsi_cmd; 1461 xs->cmdlen = cmdlen; 1462 xs->data = data_addr; 1463 xs->datalen = datalen; 1464 xs->resid = datalen; 1465 xs->when_done = (flags & SCSI_NOMASK) 1466 ?(int (*)())0 1467 :cd_done; 1468 xs->done_arg = unit; 1469 xs->done_arg2 = (int)xs; 1470 retry: xs->error = XS_NOERROR; 1471 xs->bp = 0; 1472 retval = (*(cd->sc_sw->scsi_cmd))(xs); 1473 switch(retval) 1474 { 1475 case SUCCESSFULLY_QUEUED: 1476 s = splbio(); 1477 while(!(xs->flags & ITSDONE)) 1478 tsleep((caddr_t)xs,PRIBIO+1, "cd_cmd", 0); 1479 splx(s); 1480 1481 case HAD_ERROR: 1482 /*printf("err = %d ",xs->error);*/ 1483 switch(xs->error) 1484 { 1485 case XS_NOERROR: 1486 retval = ESUCCESS; 1487 break; 1488 case XS_SENSE: 1489 retval = (cd_interpret_sense(unit,xs)); 1490 break; 1491 case XS_DRIVER_STUFFUP: 1492 retval = EIO; 1493 break; 1494 1495 1496 case XS_BUSY: 1497 case XS_TIMEOUT: 1498 if(xs->retries-- ) 1499 { 1500 xs->flags &= ~ITSDONE; 1501 goto retry; 1502 } 1503 retval = EIO; 1504 break; 1505 default: 1506 retval = EIO; 1507 printf("cd%d: unknown error category from scsi driver\n" 1508 ,unit); 1509 } 1510 break; 1511 case COMPLETE: 1512 retval = ESUCCESS; 1513 break; 1514 case TRY_AGAIN_LATER: 1515 if(xs->retries-- ) 1516 { 1517 if(tsleep( 0,PRIBIO + 2,"retry",hz * 2)) 1518 { 1519 xs->flags &= ~ITSDONE; 1520 goto retry; 1521 } 1522 } 1523 retval = EIO; 1524 break; 1525 default: 1526 retval = EIO; 1527 } 1528 cd_free_xs(unit,xs,flags); 1529 cdstart(unit); /* check if anything is waiting fr the xs */ 1530 } 1531 else 1532 { 1533 printf("cd%d: not set up\n",unit); 1534 return(EINVAL); 1535 } 1536 return(retval); 1537 } 1538 /***************************************************************\ 1539 * Look at the returned sense and act on the error and detirmine * 1540 * The unix error number to pass back... (0 = report no error) * 1541 \***************************************************************/ 1542 1543 int cd_interpret_sense(unit,xs) 1544 int unit; 1545 struct scsi_xfer *xs; 1546 { 1547 struct scsi_sense_data *sense; 1548 int key; 1549 int silent; 1550 1551 /***************************************************************\ 1552 * If the flags say errs are ok, then always return ok. * 1553 \***************************************************************/ 1554 if (xs->flags & SCSI_ERR_OK) return(ESUCCESS); 1555 silent = (xs->flags & SCSI_SILENT); 1556 1557 sense = &(xs->sense); 1558 switch(sense->error_class) 1559 { 1560 case 7: 1561 { 1562 key=sense->ext.extended.sense_key; 1563 switch(key) 1564 { 1565 case 0x0: 1566 return(ESUCCESS); 1567 case 0x1: 1568 if(!silent) 1569 { 1570 printf("cd%d: soft error(corrected) ", unit); 1571 if(sense->valid) 1572 { 1573 printf("block no. %d (decimal)", 1574 (sense->ext.extended.info[0] <<24) | 1575 (sense->ext.extended.info[1] <<16) | 1576 (sense->ext.extended.info[2] <<8) | 1577 (sense->ext.extended.info[3] )); 1578 } 1579 printf("\n"); 1580 } 1581 return(ESUCCESS); 1582 case 0x2: 1583 if(!silent)printf("cd%d: not ready\n", 1584 unit); 1585 return(ENODEV); 1586 case 0x3: 1587 if(!silent) 1588 { 1589 printf("cd%d: medium error ", unit); 1590 if(sense->valid) 1591 { 1592 printf("block no. %d (decimal)", 1593 (sense->ext.extended.info[0] <<24) | 1594 (sense->ext.extended.info[1] <<16) | 1595 (sense->ext.extended.info[2] <<8) | 1596 (sense->ext.extended.info[3] )); 1597 } 1598 printf("\n"); 1599 } 1600 return(EIO); 1601 case 0x4: 1602 if(!silent)printf("cd%d: non-media hardware failure\n", 1603 unit); 1604 return(EIO); 1605 case 0x5: 1606 if(!silent)printf("cd%d: illegal request\n", 1607 unit); 1608 return(EINVAL); 1609 case 0x6: 1610 if(!silent)printf("cd%d: media change\n", unit); 1611 cd_data[unit]->flags &= ~(CDVALID | CDHAVELABEL); 1612 if (cd_data[unit]->openparts) 1613 { 1614 return(EIO); 1615 } 1616 return(ESUCCESS); 1617 case 0x7: 1618 if(!silent) 1619 { 1620 printf("cd%d: attempted protection violation ", 1621 unit); 1622 if(sense->valid) 1623 { 1624 printf("block no. %d (decimal)\n", 1625 (sense->ext.extended.info[0] <<24) | 1626 (sense->ext.extended.info[1] <<16) | 1627 (sense->ext.extended.info[2] <<8) | 1628 (sense->ext.extended.info[3] )); 1629 } 1630 printf("\n"); 1631 } 1632 return(EACCES); 1633 case 0x8: 1634 if(!silent) 1635 { 1636 printf("cd%d: block wrong state (worm)\n", 1637 unit); 1638 if(sense->valid) 1639 { 1640 printf("block no. %d (decimal)\n", 1641 (sense->ext.extended.info[0] <<24) | 1642 (sense->ext.extended.info[1] <<16) | 1643 (sense->ext.extended.info[2] <<8) | 1644 (sense->ext.extended.info[3] )); 1645 } 1646 printf("\n"); 1647 } 1648 return(EIO); 1649 case 0x9: 1650 if(!silent)printf("cd%d: vendor unique\n", 1651 unit); 1652 return(EIO); 1653 case 0xa: 1654 if(!silent)printf("cd%d: copy aborted\n", 1655 unit); 1656 return(EIO); 1657 case 0xb: 1658 if(!silent)printf("cd%d: command aborted\n", 1659 unit); 1660 return(EIO); 1661 case 0xc: 1662 if(!silent) 1663 { 1664 printf("cd%d: search returned\n", 1665 unit); 1666 if(sense->valid) 1667 { 1668 printf("block no. %d (decimal)\n", 1669 (sense->ext.extended.info[0] <<24) | 1670 (sense->ext.extended.info[1] <<16) | 1671 (sense->ext.extended.info[2] <<8) | 1672 (sense->ext.extended.info[3] )); 1673 } 1674 printf("\n"); 1675 } 1676 return(ESUCCESS); 1677 case 0xd: 1678 if(!silent)printf("cd%d: volume overflow\n", 1679 unit); 1680 return(ENOSPC); 1681 case 0xe: 1682 if(!silent) 1683 { 1684 printf("cd%d: verify miscompare\n", 1685 unit); 1686 if(sense->valid) 1687 { 1688 printf("block no. %d (decimal)\n", 1689 (sense->ext.extended.info[0] <<24) | 1690 (sense->ext.extended.info[1] <<16) | 1691 (sense->ext.extended.info[2] <<8) | 1692 (sense->ext.extended.info[3] )); 1693 } 1694 printf("\n"); 1695 } 1696 return(EIO); 1697 case 0xf: 1698 if(!silent)printf("cd%d: unknown error key\n", 1699 unit); 1700 return(EIO); 1701 } 1702 break; 1703 } 1704 case 0: 1705 case 1: 1706 case 2: 1707 case 3: 1708 case 4: 1709 case 5: 1710 case 6: 1711 { 1712 if(!silent)printf("cd%d: error class %d code %d\n", 1713 unit, 1714 sense->error_class, 1715 sense->error_code); 1716 if(sense->valid) 1717 if(!silent)printf("block no. %d (decimal)\n", 1718 (sense->ext.unextended.blockhi <<16) 1719 + (sense->ext.unextended.blockmed <<8) 1720 + (sense->ext.unextended.blocklow )); 1721 } 1722 return(EIO); 1723 } 1724 } 1725 1726 1727 1728 1729 int 1730 cdsize(dev_t dev) 1731 { 1732 return (-1); 1733 } 1734 1735 show_mem(address,num) 1736 unsigned char *address; 1737 int num; 1738 { 1739 int x,y; 1740 printf("------------------------------"); 1741 for (y = 0; y<num; y += 1) 1742 { 1743 if(!(y % 16)) 1744 printf("\n%03d: ",y); 1745 printf("%02x ",*address++); 1746 } 1747 printf("\n------------------------------\n"); 1748 } 1749 1750