|
|
1.1 ! root 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: Unit attention.\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:
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.