1 /* 2 */ 3 /* 4 * HISTORY 5 * 6 * 7 * PATCHES MAGIC LEVEL PATCH THAT GOT US HERE 8 * -------------------- ----- ---------------------- 9 * CURRENT PATCH LEVEL: 1 00098 10 * -------------------- ----- ---------------------- 11 * 12 * 16 Feb 93 Julian Elischer ADDED for SCSI system 13 * 14 */ 15 16 #include <sys/types.h> 17 #include <ch.h> 18 19 #include <sys/param.h> 20 #include <sys/systm.h> 21 22 #include <sys/errno.h> 23 #include <sys/ioctl.h> 24 #include <sys/buf.h> 25 #include <sys/proc.h> 26 #include <sys/user.h> 27 #include <sys/chio.h> 28 29 #if defined(OSF) 30 #define SECSIZE 512 31 #endif /* defined(OSF) */ 32 33 #include <scsi/scsi_all.h> 34 #include <scsi/scsi_changer.h> 35 #include <scsi/scsiconf.h> 36 37 38 struct scsi_xfer ch_scsi_xfer[NCH]; 39 int ch_xfer_block_wait[NCH]; 40 41 42 #define PAGESIZ 4096 43 #define STQSIZE 4 44 #define CH_RETRIES 4 45 46 47 #define MODE(z) ( (minor(z) & 0x0F) ) 48 #define UNIT(z) ( (minor(z) >> 4) ) 49 50 #ifndef MACH 51 #define ESUCCESS 0 52 #endif MACH 53 54 int ch_info_valid[NCH]; /* the info about the device is valid */ 55 int ch_initialized[NCH] ; 56 int ch_debug = 1; 57 58 int chattach(); 59 int ch_done(); 60 struct ch_data 61 { 62 int flags; 63 struct scsi_switch *sc_sw; /* address of scsi low level switch */ 64 int ctlr; /* so they know which one we want */ 65 int targ; /* our scsi target ID */ 66 int lu; /* out scsi lu */ 67 short chmo; /* Offset of first CHM */ 68 short chms; /* No. of CHM */ 69 short slots; /* No. of Storage Elements */ 70 short sloto; /* Offset of first SE */ 71 short imexs; /* No. of Import/Export Slots */ 72 short imexo; /* Offset of first IM/EX */ 73 short drives; /* No. of CTS */ 74 short driveo; /* Offset of first CTS */ 75 short rot; /* CHM can rotate */ 76 u_long op_matrix; /* possible opertaions */ 77 u_short lsterr; /* details of lasterror */ 78 u_char stor; /* posible Storage locations */ 79 }ch_data[NCH]; 80 81 #define CH_OPEN 0x01 82 #define CH_KNOWN 0x02 83 84 static int next_ch_unit = 0; 85 /***********************************************************************\ 86 * The routine called by the low level scsi routine when it discovers * 87 * A device suitable for this driver * 88 \***********************************************************************/ 89 90 int chattach(ctlr,targ,lu,scsi_switch) 91 struct scsi_switch *scsi_switch; 92 { 93 int unit,i,stat; 94 unsigned char *tbl; 95 96 if(scsi_debug & PRINTROUTINES) printf("chattach: "); 97 /*******************************************************\ 98 * Check we have the resources for another drive * 99 \*******************************************************/ 100 unit = next_ch_unit++; 101 if( unit >= NCH) 102 { 103 printf("Too many scsi changers..(%d > %d) reconfigure kernel",(unit + 1),NCH); 104 return(0); 105 } 106 /*******************************************************\ 107 * Store information needed to contact our base driver * 108 \*******************************************************/ 109 ch_data[unit].sc_sw = scsi_switch; 110 ch_data[unit].ctlr = ctlr; 111 ch_data[unit].targ = targ; 112 ch_data[unit].lu = lu; 113 114 /*******************************************************\ 115 * Use the subdriver to request information regarding * 116 * the drive. We cannot use interrupts yet, so the * 117 * request must specify this. * 118 \*******************************************************/ 119 if((ch_mode_sense(unit, SCSI_NOSLEEP | SCSI_NOMASK /*| SCSI_SILENT*/))) 120 { 121 printf(" ch%d: scsi changer, %d slot(s) %d drive(s) %d arm(s) %d i/e-slot(s) \n", 122 unit, ch_data[unit].slots, ch_data[unit].drives, ch_data[unit].chms, ch_data[unit].imexs); 123 stat=CH_KNOWN; 124 } 125 else 126 { 127 printf(" ch%d: scsi changer :- offline\n", unit); 128 stat=CH_OPEN; 129 } 130 ch_initialized[unit] = stat; 131 132 return; 133 134 } 135 136 137 138 /*******************************************************\ 139 * open the device. * 140 \*******************************************************/ 141 chopen(dev) 142 { 143 int errcode = 0; 144 int unit,mode; 145 146 unit = UNIT(dev); 147 mode = MODE(dev); 148 149 /*******************************************************\ 150 * Check the unit is legal * 151 \*******************************************************/ 152 if ( unit >= NCH ) 153 { 154 printf("ch %d > %d\n",unit,NCH); 155 errcode = ENXIO; 156 return(errcode); 157 } 158 /*******************************************************\ 159 * Only allow one at a time * 160 \*******************************************************/ 161 if(ch_data[unit].flags & CH_OPEN) 162 { 163 printf("CH%d already open\n",unit); 164 errcode = ENXIO; 165 goto bad; 166 } 167 168 if(ch_debug||(scsi_debug & (PRINTROUTINES | TRACEOPENS))) 169 printf("chopen: dev=0x%x (unit %d (of %d))\n" 170 , dev, unit, NCH); 171 /*******************************************************\ 172 * Make sure the device has been initialised * 173 \*******************************************************/ 174 175 if (!ch_initialized[unit]) 176 return(ENXIO); 177 if (ch_initialized[unit]!=CH_KNOWN) { 178 if((ch_mode_sense(unit, SCSI_NOSLEEP | SCSI_NOMASK /*| SCSI_SILENT*/))) 179 { 180 ch_initialized[unit]=CH_KNOWN; 181 } 182 else 183 { 184 printf(" ch%d: scsi changer :- offline\n", unit); 185 return(ENXIO); 186 } 187 } 188 /*******************************************************\ 189 * Check that it is still responding and ok. * 190 \*******************************************************/ 191 192 if(ch_debug || (scsi_debug & TRACEOPENS)) 193 printf("device is "); 194 if (!(ch_req_sense(unit, 0))) 195 { 196 errcode = ENXIO; 197 if(ch_debug || (scsi_debug & TRACEOPENS)) 198 printf("not responding\n"); 199 goto bad; 200 } 201 if(ch_debug || (scsi_debug & TRACEOPENS)) 202 printf("ok\n"); 203 204 if(!(ch_test_ready(unit,0))) 205 { 206 printf("ch%d not ready\n",unit); 207 return(EIO); 208 } 209 210 ch_info_valid[unit] = TRUE; 211 212 /*******************************************************\ 213 * Load the physical device parameters * 214 \*******************************************************/ 215 216 ch_data[unit].flags = CH_OPEN; 217 return(errcode); 218 bad: 219 return(errcode); 220 } 221 222 /*******************************************************\ 223 * close the device.. only called if we are the LAST * 224 * occurence of an open device * 225 \*******************************************************/ 226 chclose(dev) 227 { 228 unsigned char unit,mode; 229 230 unit = UNIT(dev); 231 mode = MODE(dev); 232 233 if(scsi_debug & TRACEOPENS) 234 printf("Closing device"); 235 ch_data[unit].flags = 0; 236 return(0); 237 } 238 239 240 241 /***************************************************************\ 242 * chstart * 243 * This routine is also called after other non-queued requests * 244 * have been made of the scsi driver, to ensure that the queue * 245 * continues to be drained. * 246 \***************************************************************/ 247 /* chstart() is called at splbio */ 248 chstart(unit) 249 { 250 int drivecount; 251 register struct buf *bp = 0; 252 register struct buf *dp; 253 struct scsi_xfer *xs; 254 int blkno, nblk; 255 256 257 if(scsi_debug & PRINTROUTINES) printf("chstart%d ",unit); 258 /*******************************************************\ 259 * See if there is a buf to do and we are not already * 260 * doing one * 261 \*******************************************************/ 262 xs=&ch_scsi_xfer[unit]; 263 if(xs->flags & INUSE) 264 { 265 return; /* unit already underway */ 266 } 267 if(ch_xfer_block_wait[unit]) /* a special awaits, let it proceed first */ 268 { 269 wakeup(&ch_xfer_block_wait[unit]); 270 return; 271 } 272 273 return; 274 275 } 276 277 278 /*******************************************************\ 279 * This routine is called by the scsi interrupt when * 280 * the transfer is complete. 281 \*******************************************************/ 282 int ch_done(unit,xs) 283 int unit; 284 struct scsi_xfer *xs; 285 { 286 struct buf *bp; 287 int retval; 288 289 if(ch_debug||(scsi_debug & PRINTROUTINES)) printf("ch_done%d ",unit); 290 if (! (xs->flags & INUSE)) 291 panic("scsi_xfer not in use!"); 292 wakeup(xs); 293 } 294 /*******************************************************\ 295 * Perform special action on behalf of the user * 296 * Knows about the internals of this device * 297 \*******************************************************/ 298 chioctl(dev, cmd, arg, mode) 299 dev_t dev; 300 int cmd; 301 caddr_t arg; 302 { 303 /* struct ch_cmd_buf *args;*/ 304 union scsi_cmd *scsi_cmd; 305 register i,j; 306 unsigned int opri; 307 int errcode = 0; 308 unsigned char unit; 309 int number,flags,ret; 310 311 /*******************************************************\ 312 * Find the device that the user is talking about * 313 \*******************************************************/ 314 flags = 0; /* give error messages, act on errors etc. */ 315 unit = UNIT(dev); 316 317 switch(cmd) 318 { 319 case CHIOOP: { 320 struct chop *ch=(struct chop *) arg; 321 if (ch_debug) 322 printf("[chtape_chop: %x]\n", ch->ch_op); 323 324 switch ((short)(ch->ch_op)) { 325 case CHGETPARAM: 326 ch->u.getparam.chmo= ch_data[unit].chmo; 327 ch->u.getparam.chms= ch_data[unit].chms; 328 ch->u.getparam.sloto= ch_data[unit].sloto; 329 ch->u.getparam.slots= ch_data[unit].slots; 330 ch->u.getparam.imexo= ch_data[unit].imexo; 331 ch->u.getparam.imexs= ch_data[unit].imexs; 332 ch->u.getparam.driveo= ch_data[unit].driveo; 333 ch->u.getparam.drives= ch_data[unit].drives; 334 ch->u.getparam.rot= ch_data[unit].rot; 335 ch->result=0; 336 return 0; 337 break; 338 case CHPOSITION: 339 return ch_position(unit,&ch->result,ch->u.position.chm, 340 ch->u.position.to, 341 flags); 342 case CHMOVE: 343 return ch_move(unit,&ch->result, ch->u.position.chm, 344 ch->u.move.from, ch->u.move.to, 345 flags); 346 case CHGETELEM: 347 return ch_getelem(unit,&ch->result, ch->u.get_elem_stat.type, 348 ch->u.get_elem_stat.from, &ch->u.get_elem_stat.elem_data, 349 flags); 350 default: 351 return EINVAL; 352 } 353 354 } 355 default: 356 return EINVAL; 357 } 358 359 return(ret?ESUCCESS:EIO); 360 } 361 362 ch_getelem(unit,stat,type,from,data,flags) 363 int unit,from,flags; 364 short *stat; 365 char *data; 366 { 367 struct scsi_read_element_status scsi_cmd; 368 char elbuf[32]; 369 int ret; 370 371 bzero(&scsi_cmd, sizeof(scsi_cmd)); 372 scsi_cmd.op_code = READ_ELEMENT_STATUS; 373 scsi_cmd.element_type_code=type; 374 scsi_cmd.starting_element_addr[0]=(from>>8)&0xff; 375 scsi_cmd.starting_element_addr[1]=from&0xff; 376 scsi_cmd.number_of_elements[1]=1; 377 scsi_cmd.allocation_length[2]=32; 378 379 if ((ret=ch_scsi_cmd(unit, 380 &scsi_cmd, 381 sizeof(scsi_cmd), 382 elbuf, 383 32, 384 100000, 385 flags) !=ESUCCESS)) { 386 *stat=ch_data[unit].lsterr; 387 bcopy(elbuf+16,data,16); 388 return ret; 389 } 390 bcopy(elbuf+16,data,16); /*Just a hack sh */ 391 return ret; 392 } 393 394 ch_move(unit,stat,chm,from,to,flags) 395 int unit,chm,from,to,flags; 396 short *stat; 397 { 398 struct scsi_move_medium scsi_cmd; 399 int ret; 400 401 bzero(&scsi_cmd, sizeof(scsi_cmd)); 402 scsi_cmd.op_code = MOVE_MEDIUM; 403 scsi_cmd.transport_element_address[0]=(chm>>8)&0xff; 404 scsi_cmd.transport_element_address[1]=chm&0xff; 405 scsi_cmd.source_address[0]=(from>>8)&0xff; 406 scsi_cmd.source_address[1]=from&0xff; 407 scsi_cmd.destination_address[0]=(to>>8)&0xff; 408 scsi_cmd.destination_address[1]=to&0xff; 409 scsi_cmd.invert=(chm&CH_INVERT)?1:0; 410 if ((ret=ch_scsi_cmd(unit, 411 &scsi_cmd, 412 sizeof(scsi_cmd), 413 NULL, 414 0, 415 100000, 416 flags) !=ESUCCESS)) { 417 *stat=ch_data[unit].lsterr; 418 return ret; 419 } 420 return ret; 421 } 422 423 ch_position(unit,stat,chm,to,flags) 424 int unit,chm,to,flags; 425 short *stat; 426 { 427 struct scsi_position_to_element scsi_cmd; 428 int ret; 429 430 bzero(&scsi_cmd, sizeof(scsi_cmd)); 431 scsi_cmd.op_code = POSITION_TO_ELEMENT; 432 scsi_cmd.transport_element_address[0]=(chm>>8)&0xff; 433 scsi_cmd.transport_element_address[1]=chm&0xff; 434 scsi_cmd.source_address[0]=(to>>8)&0xff; 435 scsi_cmd.source_address[1]=to&0xff; 436 scsi_cmd.invert=(chm&CH_INVERT)?1:0; 437 if ((ret=ch_scsi_cmd(unit, 438 &scsi_cmd, 439 sizeof(scsi_cmd), 440 NULL, 441 0, 442 100000, 443 flags) !=ESUCCESS)) { 444 *stat=ch_data[unit].lsterr; 445 return ret; 446 } 447 return ret; 448 } 449 450 /*******************************************************\ 451 * Check with the device that it is ok, (via scsi driver)* 452 \*******************************************************/ 453 ch_req_sense(unit, flags) 454 int flags; 455 { 456 struct scsi_sense_data sense; 457 struct scsi_sense scsi_cmd; 458 459 bzero(&scsi_cmd, sizeof(scsi_cmd)); 460 scsi_cmd.op_code = REQUEST_SENSE; 461 scsi_cmd.length = sizeof(sense); 462 463 if (ch_scsi_cmd(unit, 464 &scsi_cmd, 465 sizeof(struct scsi_sense), 466 &sense, 467 sizeof(sense), 468 100000, 469 flags | SCSI_DATA_IN) != 0) 470 { 471 return(FALSE); 472 } 473 else 474 return(TRUE); 475 } 476 477 /*******************************************************\ 478 * Get scsi driver to send a "are you ready" command * 479 \*******************************************************/ 480 ch_test_ready(unit,flags) 481 int unit,flags; 482 { 483 struct scsi_test_unit_ready scsi_cmd; 484 485 bzero(&scsi_cmd, sizeof(scsi_cmd)); 486 scsi_cmd.op_code = TEST_UNIT_READY; 487 488 if (ch_scsi_cmd(unit, 489 &scsi_cmd, 490 sizeof(struct scsi_test_unit_ready), 491 0, 492 0, 493 100000, 494 flags) != 0) { 495 return(FALSE); 496 } else 497 return(TRUE); 498 } 499 500 501 #ifdef __STDC__ 502 #define b2tol(a) (((unsigned)(a##_1) << 8) + (unsigned)a##_0 ) 503 #else 504 #define b2tol(a) (((unsigned)(a/**/_1) << 8) + (unsigned)a/**/_0 ) 505 #endif 506 507 /*******************************************************\ 508 * Get the scsi driver to send a full inquiry to the * 509 * device and use the results to fill out the global * 510 * parameter structure. * 511 \*******************************************************/ 512 ch_mode_sense(unit, flags) 513 int unit,flags; 514 { 515 struct scsi_mode_sense scsi_cmd; 516 u_char scsi_sense[128]; /* Can't use scsi_mode_sense_data because of */ 517 /* missing block descriptor */ 518 u_char *b; 519 int i,l; 520 521 /*******************************************************\ 522 * First check if we have it all loaded * 523 \*******************************************************/ 524 if (ch_info_valid[unit]==CH_KNOWN) return(TRUE); 525 /*******************************************************\ 526 * First do a mode sense * 527 \*******************************************************/ 528 ch_info_valid[unit] &= ~CH_KNOWN; 529 for(l=1;l>=0;l--) { 530 bzero(&scsi_cmd, sizeof(scsi_cmd)); 531 scsi_cmd.op_code = MODE_SENSE; 532 scsi_cmd.dbd = l; 533 scsi_cmd.page_code = 0x3f; /* All Pages */ 534 scsi_cmd.length = sizeof(scsi_sense); 535 /*******************************************************\ 536 * do the command, but we don't need the results * 537 * just print them for our interest's sake * 538 \*******************************************************/ 539 if (ch_scsi_cmd(unit, 540 &scsi_cmd, 541 sizeof(struct scsi_mode_sense), 542 &scsi_sense, 543 sizeof(scsi_sense), 544 5000, 545 flags | SCSI_DATA_IN) == 0) { 546 ch_info_valid[unit] = CH_KNOWN; 547 break; 548 } 549 } 550 if (ch_info_valid[unit]!=CH_KNOWN) { 551 if(!(flags & SCSI_SILENT)) 552 printf("could not mode sense for unit %d\n", unit); 553 return(FALSE); 554 } 555 l=scsi_sense[0]-3; 556 b=&scsi_sense[4]; 557 /*****************************\ 558 * To avoid alignment problems * 559 \*****************************/ 560 /*FIX THIS FOR MSB */ 561 #define p2copy(valp) (valp[1]+ (valp[0]<<8));valp+=2 562 #define p4copy(valp) (valp[3]+ (valp[2]<<8) + (valp[1]<<16) + (valp[0]<<24));valp+=4 563 #if 0 564 printf("\nmode_sense %d\n",l); 565 for(i=0;i<l+4;i++) { 566 printf("%x%c",scsi_sense[i],i%8==7?'\n':':'); 567 } 568 printf("\n"); 569 #endif 570 for(i=0;i<l;) { 571 int pc=(*b++)&0x3f; 572 int pl=*b++; 573 u_char *bb=b; 574 switch(pc) { 575 case 0x1d: 576 ch_data[unit].chmo =p2copy(bb); 577 ch_data[unit].chms =p2copy(bb); 578 ch_data[unit].sloto =p2copy(bb); 579 ch_data[unit].slots =p2copy(bb); 580 ch_data[unit].imexo =p2copy(bb); 581 ch_data[unit].imexs =p2copy(bb); 582 ch_data[unit].driveo =p2copy(bb); 583 ch_data[unit].drives =p2copy(bb); 584 break; 585 case 0x1e: 586 ch_data[unit].rot = (*b)&1; 587 break; 588 case 0x1f: 589 ch_data[unit].stor = *b&0xf; 590 bb+=2; 591 ch_data[unit].stor =p4copy(bb); 592 break; 593 default: 594 break; 595 } 596 b+=pl; 597 i+=pl+2; 598 } 599 if (ch_debug) 600 { 601 printf("unit %d: cht(%d-%d)slot(%d-%d)imex(%d-%d)cts(%d-%d) %s rotate\n", 602 unit, 603 ch_data[unit].chmo, 604 ch_data[unit].chms, 605 ch_data[unit].sloto, 606 ch_data[unit].slots, 607 ch_data[unit].imexo, 608 ch_data[unit].imexs, 609 ch_data[unit].driveo, 610 ch_data[unit].drives, 611 ch_data[unit].rot?"can":"can't"); 612 } 613 return(TRUE); 614 } 615 616 /*******************************************************\ 617 * ask the scsi driver to perform a command for us. * 618 * Call it through the switch table, and tell it which * 619 * sub-unit we want, and what target and lu we wish to * 620 * talk to. Also tell it where to find the command * 621 * how long int is. * 622 * Also tell it where to read/write the data, and how * 623 * long the data is supposed to be * 624 \*******************************************************/ 625 int ch_scsi_cmd(unit,scsi_cmd,cmdlen,data_addr,datalen,timeout,flags) 626 627 int unit,flags; 628 struct scsi_generic *scsi_cmd; 629 int cmdlen; 630 int timeout; 631 u_char *data_addr; 632 int datalen; 633 { 634 struct scsi_xfer *xs; 635 int retval; 636 int s; 637 638 if(ch_debug||(scsi_debug & PRINTROUTINES)) printf("\nch_scsi_cmd%d %x", 639 unit,scsi_cmd->opcode); 640 if(ch_data[unit].sc_sw) /* If we have a scsi driver */ 641 { 642 643 xs = &(ch_scsi_xfer[unit]); 644 if(!(flags & SCSI_NOMASK)) 645 s = splbio(); 646 ch_xfer_block_wait[unit]++; /* there is someone waiting */ 647 while (xs->flags & INUSE) 648 { 649 sleep(&ch_xfer_block_wait[unit],PRIBIO+1); 650 } 651 ch_xfer_block_wait[unit]--; 652 xs->flags = INUSE; 653 if(!(flags & SCSI_NOMASK)) 654 splx(s); 655 656 /*******************************************************\ 657 * Fill out the scsi_xfer structure * 658 \*******************************************************/ 659 xs->flags |= flags; 660 xs->adapter = ch_data[unit].ctlr; 661 xs->targ = ch_data[unit].targ; 662 xs->lu = ch_data[unit].lu; 663 xs->retries = CH_RETRIES; 664 xs->timeout = timeout; 665 xs->cmd = scsi_cmd; 666 xs->cmdlen = cmdlen; 667 xs->data = data_addr; 668 xs->datalen = datalen; 669 xs->resid = datalen; 670 xs->when_done = (flags & SCSI_NOMASK) 671 ?(int (*)())0 672 :ch_done; 673 xs->done_arg = unit; 674 xs->done_arg2 = (int)xs; 675 retry: xs->error = XS_NOERROR; 676 xs->bp = 0; 677 ch_data[unit].lsterr=0; 678 retval = (*(ch_data[unit].sc_sw->scsi_cmd))(xs); 679 switch(retval) 680 { 681 case SUCCESSFULLY_QUEUED: 682 while(!(xs->flags & ITSDONE)) 683 sleep(xs,PRIBIO+1); 684 685 case HAD_ERROR: 686 case COMPLETE: 687 switch(xs->error) 688 { 689 case XS_NOERROR: 690 retval = ESUCCESS; 691 break; 692 case XS_SENSE: 693 retval = (ch_interpret_sense(unit,xs)); 694 break; 695 case XS_DRIVER_STUFFUP: 696 retval = EIO; 697 break; 698 case XS_TIMEOUT: 699 if(xs->retries-- ) 700 { 701 xs->flags &= ~ITSDONE; 702 goto retry; 703 } 704 retval = EIO; 705 break; 706 case XS_BUSY: 707 if(xs->retries-- ) 708 { 709 xs->flags &= ~ITSDONE; 710 goto retry; 711 } 712 retval = EIO; 713 break; 714 default: 715 retval = EIO; 716 printf("st%d: unknown error category from scsi driver\n" 717 ,unit); 718 break; 719 } 720 break; 721 case TRY_AGAIN_LATER: 722 if(xs->retries-- ) 723 { 724 xs->flags &= ~ITSDONE; 725 goto retry; 726 } 727 retval = EIO; 728 break; 729 default: 730 retval = EIO; 731 } 732 xs->flags = 0; /* it's free! */ 733 chstart(unit); 734 } 735 else 736 { 737 printf("chd: not set up\n",unit); 738 return(EINVAL); 739 } 740 return(retval); 741 } 742 /***************************************************************\ 743 * Look at the returned sense and act on the error and detirmine * 744 * The unix error number to pass back... (0 = report no error) * 745 \***************************************************************/ 746 747 int ch_interpret_sense(unit,xs) 748 int unit; 749 struct scsi_xfer *xs; 750 { 751 struct scsi_sense_data *sense; 752 int key; 753 int silent = xs->flags & SCSI_SILENT; 754 755 /***************************************************************\ 756 * If errors are ok, report a success * 757 \***************************************************************/ 758 if(xs->flags & SCSI_ERR_OK) return(ESUCCESS); 759 760 /***************************************************************\ 761 * Get the sense fields and work out what CLASS * 762 \***************************************************************/ 763 sense = &(xs->sense); 764 switch(sense->error_class) 765 { 766 /***************************************************************\ 767 * If it's class 7, use the extended stuff and interpret the key * 768 \***************************************************************/ 769 case 7: 770 { 771 key=sense->ext.extended.sense_key; 772 if(sense->ext.extended.ili) 773 if(!silent) 774 { 775 printf("length error "); 776 } 777 if(sense->valid) 778 xs->resid = ntohl(*((long *)sense->ext.extended.info)); 779 if(xs->bp) 780 { 781 xs->bp->b_flags |= B_ERROR; 782 return(ESUCCESS); 783 } 784 if(sense->ext.extended.eom) 785 if(!silent) printf("end of medium "); 786 if(sense->ext.extended.filemark) 787 if(!silent) printf("filemark "); 788 if(ch_debug) 789 { 790 printf("code%x class%x valid%x\n" 791 ,sense->error_code 792 ,sense->error_class 793 ,sense->valid); 794 printf("seg%x key%x ili%x eom%x fmark%x\n" 795 ,sense->ext.extended.segment 796 ,sense->ext.extended.sense_key 797 ,sense->ext.extended.ili 798 ,sense->ext.extended.eom 799 ,sense->ext.extended.filemark); 800 printf("info: %x %x %x %x followed by %d extra bytes\n" 801 ,sense->ext.extended.info[0] 802 ,sense->ext.extended.info[1] 803 ,sense->ext.extended.info[2] 804 ,sense->ext.extended.info[3] 805 ,sense->ext.extended.extra_len); 806 printf("extra: %x %x %x %x %x %x %x %x %x %x %x %x %x %x %x %x\n" 807 ,sense->ext.extended.extra_bytes[0] 808 ,sense->ext.extended.extra_bytes[1] 809 ,sense->ext.extended.extra_bytes[2] 810 ,sense->ext.extended.extra_bytes[3] 811 ,sense->ext.extended.extra_bytes[4] 812 ,sense->ext.extended.extra_bytes[5] 813 ,sense->ext.extended.extra_bytes[6] 814 ,sense->ext.extended.extra_bytes[7] 815 ,sense->ext.extended.extra_bytes[8] 816 ,sense->ext.extended.extra_bytes[9] 817 ,sense->ext.extended.extra_bytes[10] 818 ,sense->ext.extended.extra_bytes[11] 819 ,sense->ext.extended.extra_bytes[12] 820 ,sense->ext.extended.extra_bytes[13] 821 ,sense->ext.extended.extra_bytes[14] 822 ,sense->ext.extended.extra_bytes[15]); 823 824 } 825 switch(key) 826 { 827 case 0x0: 828 return(ESUCCESS); 829 case 0x1: 830 if(!silent) 831 { 832 printf("st%d: soft error(corrected) ", unit); 833 if(sense->valid) 834 { 835 printf("block no. %d (decimal)\n", 836 (sense->ext.extended.info[0] <<24)| 837 (sense->ext.extended.info[1] <<16)| 838 (sense->ext.extended.info[2] <<8)| 839 (sense->ext.extended.info[3] )); 840 } 841 else 842 { 843 printf("\n"); 844 } 845 } 846 return(ESUCCESS); 847 case 0x2: 848 if(!silent) printf("st%d: not ready\n ", unit); 849 ch_data[unit].lsterr=(sense->ext.extended.info[12]<<8)| 850 sense->ext.extended.info[13] ; 851 return(ENODEV); 852 case 0x3: 853 if(!silent) 854 { 855 printf("st%d: medium error ", unit); 856 if(sense->valid) 857 { 858 printf("block no. %d (decimal)\n", 859 (sense->ext.extended.info[0] <<24)| 860 (sense->ext.extended.info[1] <<16)| 861 (sense->ext.extended.info[2] <<8)| 862 (sense->ext.extended.info[3] )); 863 } 864 else 865 { 866 printf("\n"); 867 } 868 } 869 return(EIO); 870 case 0x4: 871 if(!silent) printf("st%d: non-media hardware failure\n ", 872 unit); 873 ch_data[unit].lsterr=(sense->ext.extended.info[12]<<8)| 874 sense->ext.extended.info[13] ; 875 return(EIO); 876 case 0x5: 877 if(!silent) printf("st%d: illegal request\n ", unit); 878 ch_data[unit].lsterr=(sense->ext.extended.info[12]<<8)| 879 sense->ext.extended.info[13] ; 880 return(EINVAL); 881 case 0x6: 882 if(!silent)printf("st%d: media change\n", unit); 883 ch_data[unit].lsterr=(sense->ext.extended.info[12]<<8)| 884 sense->ext.extended.info[13] ; 885 ch_info_valid[unit] = FALSE; 886 if (ch_data[unit].flags & CH_OPEN) /* TEMP!!!! */ 887 return(EIO); 888 else 889 return(ESUCCESS); 890 case 0x7: 891 if(!silent) 892 { 893 printf("st%d: attempted protection violation " 894 , unit); 895 if(sense->valid) 896 { 897 printf("block no. %d (decimal)\n", 898 (sense->ext.extended.info[0] <<24)| 899 (sense->ext.extended.info[1] <<16)| 900 (sense->ext.extended.info[2] <<8)| 901 (sense->ext.extended.info[3] )); 902 } 903 else 904 { 905 printf("\n"); 906 } 907 } 908 return(EACCES); 909 case 0x8: 910 if(!silent) 911 { 912 printf("st%d: block wrong state (worm)\n " 913 , unit); 914 if(sense->valid) 915 { 916 printf("block no. %d (decimal)\n", 917 (sense->ext.extended.info[0] <<24)| 918 (sense->ext.extended.info[1] <<16)| 919 (sense->ext.extended.info[2] <<8)| 920 (sense->ext.extended.info[3] )); 921 } 922 else 923 { 924 printf("\n"); 925 } 926 } 927 return(EIO); 928 case 0x9: 929 if(!silent) printf("st%d: vendor unique\n", 930 unit); 931 return(EIO); 932 case 0xa: 933 if(!silent) printf("st%d: copy aborted\n ", 934 unit); 935 return(EIO); 936 case 0xb: 937 if(!silent) printf("st%d: command aborted\n ", 938 unit); 939 ch_data[unit].lsterr=(sense->ext.extended.info[12]<<8)| 940 sense->ext.extended.info[13] ; 941 return(EIO); 942 case 0xc: 943 if(!silent) 944 { 945 printf("st%d: search returned\n ", unit); 946 if(sense->valid) 947 { 948 printf("block no. %d (decimal)\n", 949 (sense->ext.extended.info[0] <<24)| 950 (sense->ext.extended.info[1] <<16)| 951 (sense->ext.extended.info[2] <<8)| 952 (sense->ext.extended.info[3] )); 953 } 954 else 955 { 956 printf("\n"); 957 } 958 } 959 return(ESUCCESS); 960 case 0xd: 961 if(!silent) printf("st%d: volume overflow\n ", 962 unit); 963 return(ENOSPC); 964 case 0xe: 965 if(!silent) 966 { 967 printf("st%d: verify miscompare\n ", unit); 968 if(sense->valid) 969 { 970 printf("block no. %d (decimal)\n", 971 (sense->ext.extended.info[0] <<24)| 972 (sense->ext.extended.info[1] <<16)| 973 (sense->ext.extended.info[2] <<8)| 974 (sense->ext.extended.info[3] )); 975 } 976 else 977 { 978 printf("\n"); 979 } 980 } 981 return(EIO); 982 case 0xf: 983 if(!silent) printf("st%d: unknown error key\n ", 984 unit); 985 return(EIO); 986 } 987 break; 988 } 989 /***************************************************************\ 990 * If it's NOT class 7, just report it. * 991 \***************************************************************/ 992 case 0: 993 case 1: 994 case 2: 995 case 3: 996 case 4: 997 case 5: 998 case 6: 999 { 1000 if(!silent) printf("st%d: error class %d code %d\n", 1001 unit, 1002 sense->error_class, 1003 sense->error_code); 1004 if(sense->valid) 1005 if(!silent) printf("block no. %d (decimal)\n", 1006 (sense->ext.unextended.blockhi <<16), 1007 + (sense->ext.unextended.blockmed <<8), 1008 + (sense->ext.unextended.blocklow )); 1009 } 1010 return(EIO); 1011 } 1012 } 1013 1014 1015 1016