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