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