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