|
|
1.1 ! root 1: /* ! 2: * Written by Julian Elischer ([email protected]) ! 3: * for TRW Financial Systems for use under the MACH(2.5) operating system. ! 4: * ! 5: * TRW Financial Systems, in accordance with their agreement with Carnegie ! 6: * Mellon University, makes this software available to CMU to distribute ! 7: * or use in any manner that they see fit as long as this message is kept with ! 8: * the software. For this reason TFS also grants any other persons or ! 9: * organisations permission to use or modify this software. ! 10: * ! 11: * TFS supplies this software to be publicly redistributed ! 12: * on the understanding that TFS is not responsible for the correct ! 13: * functioning of this software in any circumstances. ! 14: * ! 15: * ! 16: * PATCHES MAGIC LEVEL PATCH THAT GOT US HERE ! 17: * -------------------- ----- ---------------------- ! 18: * CURRENT PATCH LEVEL: 1 00098 ! 19: * -------------------- ----- ---------------------- ! 20: * ! 21: * 16 Feb 93 Julian Elischer ADDED for SCSI system ! 22: */ ! 23: ! 24: /* ! 25: * Ported to run under 386BSD by Julian Elischer ([email protected]) Sept 1992 ! 26: */ ! 27: ! 28: ! 29: /* ! 30: * To do: ! 31: * work out some better way of guessing what a good timeout is going ! 32: * to be depending on whether we expect to retension or not. ! 33: * ! 34: */ ! 35: ! 36: #include <sys/types.h> ! 37: #include <st.h> ! 38: ! 39: #include <sys/param.h> ! 40: #include <sys/systm.h> ! 41: ! 42: #include <sys/errno.h> ! 43: #include <sys/ioctl.h> ! 44: #include <sys/buf.h> ! 45: #include <sys/proc.h> ! 46: #include <sys/user.h> ! 47: #include <sys/mtio.h> ! 48: ! 49: #if defined(OSF) ! 50: #define SECSIZE 512 ! 51: #endif /* defined(OSF) */ ! 52: ! 53: #include <scsi/scsi_all.h> ! 54: #include <scsi/scsi_tape.h> ! 55: #include <scsi/scsiconf.h> ! 56: ! 57: ! 58: long int ststrats,stqueues; ! 59: ! 60: ! 61: #define PAGESIZ 4096 ! 62: #define STQSIZE 4 ! 63: #define ST_RETRIES 4 ! 64: ! 65: ! 66: #define MODE(z) ( (minor(z) & 0x03) ) ! 67: #define DSTY(z) ( ((minor(z) >> 2) & 0x03) ) ! 68: #define UNIT(z) ( (minor(z) >> 4) ) ! 69: ! 70: #define DSTY_QIC120 3 ! 71: #define DSTY_QIC150 2 ! 72: #define DSTY_QIC525 1 ! 73: ! 74: #define QIC120 0x0f ! 75: #define QIC150 0x10 ! 76: #define QIC525 0x11 ! 77: ! 78: ! 79: ! 80: ! 81: #ifndef __386BSD__ ! 82: struct buf stbuf[NST][STQSIZE]; /* buffer for raw io (one per device) */ ! 83: struct buf *stbuf_free[NST]; /* queue of free buffers for raw io */ ! 84: #endif __386BSD__ ! 85: struct buf st_buf_queue[NST]; ! 86: int ststrategy(); ! 87: void stminphys(); ! 88: struct scsi_xfer st_scsi_xfer[NST]; ! 89: int st_xfer_block_wait[NST]; ! 90: ! 91: #if defined(OSF) ! 92: caddr_t st_window[NST]; ! 93: #endif /* defined(OSF) */ ! 94: #ifndef MACH ! 95: #define ESUCCESS 0 ! 96: #endif MACH ! 97: ! 98: int st_info_valid[NST]; /* the info about the device is valid */ ! 99: int st_initialized[NST] ; ! 100: int st_debug = 0; ! 101: ! 102: int stattach(); ! 103: int st_done(); ! 104: struct st_data ! 105: { ! 106: int flags; ! 107: struct scsi_switch *sc_sw; /* address of scsi low level switch */ ! 108: int ctlr; /* so they know which one we want */ ! 109: int targ; /* our scsi target ID */ ! 110: int lu; /* out scsi lu */ ! 111: int blkmin; /* min blk size */ ! 112: int blkmax; /* max blk size */ ! 113: int numblks; /* nominal blocks capacity */ ! 114: int blksiz; /* nominal block size */ ! 115: }st_data[NST]; ! 116: #define ST_OPEN 0x01 ! 117: #define ST_NOREWIND 0x02 ! 118: #define ST_WRITTEN 0x04 ! 119: #define ST_FIXEDBLOCKS 0x10 ! 120: #define ST_AT_FILEMARK 0x20 ! 121: #define ST_AT_EOM 0x40 ! 122: ! 123: #define ST_PER_ACTION (ST_AT_FILEMARK | ST_AT_EOM) ! 124: #define ST_PER_OPEN (ST_OPEN | ST_NOREWIND | ST_WRITTEN | ST_PER_ACTION) ! 125: #define ST_PER_MEDIA ST_FIXEDBLOCKS ! 126: ! 127: static int next_st_unit = 0; ! 128: /***********************************************************************\ ! 129: * The routine called by the low level scsi routine when it discovers * ! 130: * A device suitable for this driver * ! 131: \***********************************************************************/ ! 132: ! 133: int stattach(ctlr,targ,lu,scsi_switch) ! 134: struct scsi_switch *scsi_switch; ! 135: { ! 136: int unit,i; ! 137: unsigned char *tbl; ! 138: struct st_data *st; ! 139: ! 140: if(scsi_debug & PRINTROUTINES) printf("stattach: "); ! 141: /*******************************************************\ ! 142: * Check we have the resources for another drive * ! 143: \*******************************************************/ ! 144: unit = next_st_unit++; ! 145: if( unit >= NST) ! 146: { ! 147: printf("Too many scsi tapes..(%d > %d) reconfigure kernel",(unit + 1),NST); ! 148: return(0); ! 149: } ! 150: st = st_data + unit; ! 151: /*******************************************************\ ! 152: * Store information needed to contact our base driver * ! 153: \*******************************************************/ ! 154: st->sc_sw = scsi_switch; ! 155: st->ctlr = ctlr; ! 156: st->targ = targ; ! 157: st->lu = lu; ! 158: ! 159: /*******************************************************\ ! 160: * Use the subdriver to request information regarding * ! 161: * the drive. We cannot use interrupts yet, so the * ! 162: * request must specify this. * ! 163: \*******************************************************/ ! 164: if((st_mode_sense(unit, SCSI_NOSLEEP | SCSI_NOMASK | SCSI_SILENT))) ! 165: { ! 166: printf(" st%d: scsi tape drive, %d blocks of %d bytes\n", ! 167: unit, st->numblks, st->blksiz); ! 168: } ! 169: else ! 170: { ! 171: printf(" st%d: scsi tape drive :- offline\n", unit); ! 172: } ! 173: /*******************************************************\ ! 174: * Set up the bufs for this device * ! 175: \*******************************************************/ ! 176: #ifndef __386BSD__ ! 177: stbuf_free[unit] = (struct buf *)0; ! 178: for (i = 1; i < STQSIZE; i++) ! 179: { ! 180: stbuf[unit][i].b_forw = stbuf_free[unit]; ! 181: stbuf_free[unit]=&stbuf[unit][i]; ! 182: } ! 183: #endif __386BSD__ ! 184: st_buf_queue[unit].b_active = 0; ! 185: st_buf_queue[unit].b_actf = st_buf_queue[unit].b_actl = 0; ! 186: st_initialized[unit] = 1; ! 187: ! 188: #if defined(OSF) ! 189: st_window[unit] = (caddr_t)alloc_kva(SECSIZE*256+PAGESIZ); ! 190: #endif /* defined(OSF) */ ! 191: ! 192: return; ! 193: ! 194: } ! 195: ! 196: ! 197: ! 198: /*******************************************************\ ! 199: * open the device. * ! 200: \*******************************************************/ ! 201: stopen(dev) ! 202: { ! 203: int errcode = 0; ! 204: int unit,mode,dsty; ! 205: int dsty_code; ! 206: struct st_data *st; ! 207: unit = UNIT(dev); ! 208: mode = MODE(dev); ! 209: dsty = DSTY(dev); ! 210: st = st_data + unit; ! 211: ! 212: /*******************************************************\ ! 213: * Check the unit is legal * ! 214: \*******************************************************/ ! 215: if ( unit >= NST ) ! 216: { ! 217: errcode = ENXIO; ! 218: return(errcode); ! 219: } ! 220: /*******************************************************\ ! 221: * Only allow one at a time * ! 222: \*******************************************************/ ! 223: if(st->flags & ST_OPEN) ! 224: { ! 225: errcode = EBUSY; ! 226: goto bad; ! 227: } ! 228: /*******************************************************\ ! 229: * Set up the mode flags according to the minor number * ! 230: * ensure all open flags are in a known state * ! 231: \*******************************************************/ ! 232: st->flags &= ~ST_PER_OPEN; ! 233: switch(mode) ! 234: { ! 235: case 2: ! 236: case 0: ! 237: st->flags &= ~ST_NOREWIND; ! 238: break; ! 239: case 3: ! 240: case 1: ! 241: st->flags |= ST_NOREWIND; ! 242: break; ! 243: default: ! 244: printf("st%d: Bad mode (minor number)%d\n",unit,mode); ! 245: return(EINVAL); ! 246: } ! 247: /*******************************************************\ ! 248: * Check density code: 0 is drive default * ! 249: \*******************************************************/ ! 250: switch(dsty) ! 251: { ! 252: case 0: dsty_code = 0; break; ! 253: case DSTY_QIC120: dsty_code = QIC120; break; ! 254: case DSTY_QIC150: dsty_code = QIC150; break; ! 255: case DSTY_QIC525: dsty_code = QIC525; break; ! 256: default: ! 257: printf("st%d: Bad density (minor number)%d\n",unit,dsty); ! 258: return(EINVAL); ! 259: } ! 260: if(scsi_debug & (PRINTROUTINES | TRACEOPENS)) ! 261: printf("stopen: dev=0x%x (unit %d (of %d))\n" ! 262: , dev, unit, NST); ! 263: /*******************************************************\ ! 264: * Make sure the device has been initialised * ! 265: \*******************************************************/ ! 266: ! 267: if (!st_initialized[unit]) ! 268: return(ENXIO); ! 269: /*******************************************************\ ! 270: * Check that it is still responding and ok. * ! 271: \*******************************************************/ ! 272: ! 273: if(scsi_debug & TRACEOPENS) ! 274: printf("device is "); ! 275: if (!(st_req_sense(unit, 0))) ! 276: { ! 277: errcode = ENXIO; ! 278: if(scsi_debug & TRACEOPENS) ! 279: printf("not responding\n"); ! 280: goto bad; ! 281: } ! 282: if(scsi_debug & TRACEOPENS) ! 283: printf("ok\n"); ! 284: ! 285: if(!(st_test_ready(unit,0))) ! 286: { ! 287: printf("st%d not ready\n",unit); ! 288: return(EIO); ! 289: } ! 290: ! 291: if(!st_info_valid[unit]) /* is media new? */ ! 292: if(!st_load(unit,LD_LOAD,0)) ! 293: { ! 294: return(EIO); ! 295: } ! 296: ! 297: if(!st_rd_blk_lim(unit,0)) ! 298: { ! 299: return(EIO); ! 300: } ! 301: ! 302: if(!st_mode_sense(unit,0)) ! 303: { ! 304: return(EIO); ! 305: } ! 306: ! 307: if(!st_mode_select(unit,0,dsty_code)) ! 308: { ! 309: return(EIO); ! 310: } ! 311: ! 312: st_info_valid[unit] = TRUE; ! 313: ! 314: st_prevent(unit,PR_PREVENT,0); /* who cares if it fails? */ ! 315: ! 316: /*******************************************************\ ! 317: * Load the physical device parameters * ! 318: \*******************************************************/ ! 319: if(scsi_debug & TRACEOPENS) ! 320: printf("Params loaded "); ! 321: ! 322: ! 323: st->flags |= ST_OPEN; ! 324: ! 325: bad: ! 326: return(errcode); ! 327: } ! 328: ! 329: /*******************************************************\ ! 330: * close the device.. only called if we are the LAST * ! 331: * occurence of an open device * ! 332: \*******************************************************/ ! 333: stclose(dev) ! 334: { ! 335: unsigned char unit,mode; ! 336: struct st_data *st; ! 337: ! 338: unit = UNIT(dev); ! 339: mode = MODE(dev); ! 340: st = st_data + unit; ! 341: ! 342: if(scsi_debug & TRACEOPENS) ! 343: printf("Closing device"); ! 344: if(st->flags & ST_WRITTEN) ! 345: { ! 346: st_write_filemarks(unit,1,0); ! 347: } ! 348: st->flags &= ~ST_WRITTEN; ! 349: switch(mode) ! 350: { ! 351: case 0: ! 352: st_rewind(unit,FALSE,SCSI_SILENT); ! 353: st_prevent(unit,PR_ALLOW,SCSI_SILENT); ! 354: break; ! 355: case 1: ! 356: st_prevent(unit,PR_ALLOW,SCSI_SILENT); ! 357: break; ! 358: case 2: ! 359: st_rewind(unit,FALSE,SCSI_SILENT); ! 360: st_prevent(unit,PR_ALLOW,SCSI_SILENT); ! 361: st_load(unit,LD_UNLOAD,SCSI_SILENT); ! 362: break; ! 363: case 3: ! 364: st_prevent(unit,PR_ALLOW,SCSI_SILENT); ! 365: st_load(unit,LD_UNLOAD,SCSI_SILENT); ! 366: break; ! 367: default: ! 368: printf("st%d:close: Bad mode (minor number)%d how's it open?\n" ! 369: ,unit,mode); ! 370: return(EINVAL); ! 371: } ! 372: st->flags &= ~ST_PER_OPEN; ! 373: return(0); ! 374: } ! 375: ! 376: #ifndef __386BSD__ ! 377: /*******************************************************\ ! 378: * Get ownership of this unit's buf * ! 379: * If need be, sleep on it, until it comes free * ! 380: \*******************************************************/ ! 381: struct buf * ! 382: st_get_buf(unit) { ! 383: struct buf *rc; ! 384: ! 385: while (!(rc = stbuf_free[unit])) ! 386: sleep((caddr_t)&stbuf_free[unit], PRIBIO+1); ! 387: stbuf_free[unit] = stbuf_free[unit]->b_forw; ! 388: rc->b_error = 0; ! 389: rc->b_resid = 0; ! 390: rc->b_flags = 0; ! 391: return(rc); ! 392: } ! 393: ! 394: /*******************************************************\ ! 395: * Free this unit's buf, wake processes waiting for it * ! 396: \*******************************************************/ ! 397: st_free_buf(unit,bp) ! 398: struct buf *bp; ! 399: { ! 400: if (!stbuf_free[unit]) ! 401: wakeup((caddr_t)&stbuf_free[unit]); ! 402: bp->b_forw = stbuf_free[unit]; ! 403: stbuf_free[unit] = bp; ! 404: } ! 405: ! 406: ! 407: /*******************************************************\ ! 408: * Get the buf for this unit and use physio to do it * ! 409: \*******************************************************/ ! 410: stread(dev,uio) ! 411: register short dev; ! 412: struct uio *uio; ! 413: { ! 414: int unit = UNIT(dev); ! 415: struct buf *bp = st_get_buf(unit); ! 416: int rc; ! 417: rc = physio(ststrategy, bp, dev, B_READ, stminphys, uio); ! 418: st_free_buf(unit,bp); ! 419: return(rc); ! 420: } ! 421: ! 422: /*******************************************************\ ! 423: * Get the buf for this unit and use physio to do it * ! 424: \*******************************************************/ ! 425: stwrite(dev,uio) ! 426: dev_t dev; ! 427: struct uio *uio; ! 428: { ! 429: int unit = UNIT(dev); ! 430: struct buf *bp = st_get_buf(unit); ! 431: int rc; ! 432: ! 433: rc = physio(ststrategy, bp, dev, B_WRITE, stminphys, uio); ! 434: st_free_buf(unit,bp); ! 435: return(rc); ! 436: } ! 437: ! 438: ! 439: #endif __386BSD__ ! 440: /*******************************************************\ ! 441: * trim the size of the transfer if needed, * ! 442: * called by physio * ! 443: * basically the smaller of our min and the scsi driver's* ! 444: * minphys * ! 445: \*******************************************************/ ! 446: void stminphys(bp) ! 447: struct buf *bp; ! 448: { ! 449: (*(st_data[UNIT(bp->b_dev)].sc_sw->scsi_minphys))(bp); ! 450: } ! 451: ! 452: /*******************************************************\ ! 453: * Actually translate the requested transfer into * ! 454: * one the physical driver can understand * ! 455: * The transfer is described by a buf and will include * ! 456: * only one physical transfer. * ! 457: \*******************************************************/ ! 458: ! 459: int ststrategy(bp) ! 460: struct buf *bp; ! 461: { ! 462: struct buf *dp; ! 463: unsigned char unit; ! 464: unsigned int opri; ! 465: ! 466: ststrats++; ! 467: unit = UNIT((bp->b_dev)); ! 468: if(scsi_debug & PRINTROUTINES) printf("\nststrategy "); ! 469: if(scsi_debug & SHOWREQUESTS) printf("st%d: %d bytes @ blk%d\n", ! 470: unit,bp->b_bcount,bp->b_blkno); ! 471: /*******************************************************\ ! 472: * If it's a null transfer, return immediatly * ! 473: \*******************************************************/ ! 474: if (bp->b_bcount == 0) { ! 475: goto done; ! 476: } ! 477: ! 478: /*******************************************************\ ! 479: * Odd sized request on fixed drives are verboten * ! 480: \*******************************************************/ ! 481: if((st_data[unit].flags & ST_FIXEDBLOCKS) ! 482: && bp->b_bcount % st_data[unit].blkmin) ! 483: { ! 484: printf("st%d: bad request, must be multiple of %d\n", ! 485: unit, st_data[unit].blkmin); ! 486: bp->b_error = EIO; ! 487: goto bad; ! 488: } ! 489: ! 490: #ifdef __386BSD__ ! 491: stminphys(bp); ! 492: #endif __386BSD__ ! 493: opri = splbio(); ! 494: dp = &st_buf_queue[unit]; ! 495: ! 496: /*******************************************************\ ! 497: * Place it in the queue of disk activities for this tape* ! 498: * at the end * ! 499: \*******************************************************/ ! 500: while ( dp->b_actf) ! 501: { ! 502: dp = dp->b_actf; ! 503: } ! 504: dp->b_actf = bp; ! 505: bp->b_actf = NULL; ! 506: ! 507: /*******************************************************\ ! 508: * Tell the device to get going on the transfer if it's * ! 509: * not doing anything, otherwise just wait for completion* ! 510: \*******************************************************/ ! 511: ststart(unit); ! 512: ! 513: splx(opri); ! 514: return; ! 515: bad: ! 516: bp->b_flags |= B_ERROR; ! 517: done: ! 518: /*******************************************************\ ! 519: * Correctly set the buf to indicate a completed xfer * ! 520: \*******************************************************/ ! 521: iodone(bp); ! 522: return; ! 523: } ! 524: ! 525: ! 526: /***************************************************************\ ! 527: * ststart looks to see if there is a buf waiting for the device * ! 528: * and that the device is not already busy. If both are true, * ! 529: * It deques the buf and creates a scsi command to perform the * ! 530: * transfer in the buf. The transfer request will call st_done * ! 531: * on completion, which will in turn call this routine again * ! 532: * so that the next queued transfer is performed. * ! 533: * The bufs are queued by the strategy routine (ststrategy) * ! 534: * * ! 535: * This routine is also called after other non-queued requests * ! 536: * have been made of the scsi driver, to ensure that the queue * ! 537: * continues to be drained. * ! 538: \***************************************************************/ ! 539: /* ststart() is called at splbio */ ! 540: ststart(unit) ! 541: { ! 542: int drivecount; ! 543: register struct buf *bp = 0; ! 544: register struct buf *dp; ! 545: struct scsi_xfer *xs; ! 546: struct scsi_rw_tape cmd; ! 547: int blkno, nblk; ! 548: struct st_data *st; ! 549: ! 550: ! 551: st = st_data + unit; ! 552: ! 553: if(scsi_debug & PRINTROUTINES) printf("ststart%d ",unit); ! 554: /*******************************************************\ ! 555: * See if there is a buf to do and we are not already * ! 556: * doing one * ! 557: \*******************************************************/ ! 558: xs=&st_scsi_xfer[unit]; ! 559: if(xs->flags & INUSE) ! 560: { ! 561: return; /* unit already underway */ ! 562: } ! 563: trynext: ! 564: if(st_xfer_block_wait[unit]) /* a special awaits, let it proceed first */ ! 565: { ! 566: wakeup(&st_xfer_block_wait[unit]); ! 567: return; ! 568: } ! 569: ! 570: dp = &st_buf_queue[unit]; ! 571: if ((bp = dp->b_actf) != NULL) ! 572: { ! 573: dp->b_actf = bp->b_actf; ! 574: } ! 575: else /* no work to do */ ! 576: { ! 577: return; ! 578: } ! 579: xs->flags = INUSE; /* Now ours */ ! 580: ! 581: ! 582: /*******************************************************\ ! 583: * We have a buf, now we should move the data into * ! 584: * a scsi_xfer definition and try start it * ! 585: \*******************************************************/ ! 586: ! 587: /*******************************************************\ ! 588: * If we are at a filemark but have not reported it yet * ! 589: * then we should report it now * ! 590: \*******************************************************/ ! 591: if(st->flags & ST_AT_FILEMARK) ! 592: { ! 593: bp->b_error = 0; ! 594: bp->b_flags |= B_ERROR; /* EOF*/ ! 595: st->flags &= ~ST_AT_FILEMARK; ! 596: biodone(bp); ! 597: xs->flags = 0; /* won't need it now */ ! 598: goto trynext; ! 599: } ! 600: /*******************************************************\ ! 601: * If we are at EOM but have not reported it yet * ! 602: * then we should report it now * ! 603: \*******************************************************/ ! 604: if(st->flags & ST_AT_EOM) ! 605: { ! 606: bp->b_error = EIO; ! 607: bp->b_flags |= B_ERROR; ! 608: st->flags &= ~ST_AT_EOM; ! 609: biodone(bp); ! 610: xs->flags = 0; /* won't need it now */ ! 611: goto trynext; ! 612: } ! 613: /*******************************************************\ ! 614: * Fill out the scsi command * ! 615: \*******************************************************/ ! 616: bzero(&cmd, sizeof(cmd)); ! 617: if((bp->b_flags & B_READ) == B_WRITE) ! 618: { ! 619: st->flags |= ST_WRITTEN; ! 620: xs->flags |= SCSI_DATA_OUT; ! 621: } ! 622: else ! 623: { ! 624: xs->flags |= SCSI_DATA_IN; ! 625: } ! 626: cmd.op_code = (bp->b_flags & B_READ) ! 627: ? READ_COMMAND_TAPE ! 628: : WRITE_COMMAND_TAPE; ! 629: ! 630: /*******************************************************\ ! 631: * Handle "fixed-block-mode" tape drives by using the * ! 632: * block count instead of the length. * ! 633: \*******************************************************/ ! 634: if(st->flags & ST_FIXEDBLOCKS) ! 635: { ! 636: cmd.fixed = 1; ! 637: lto3b(bp->b_bcount/st->blkmin,cmd.len); ! 638: } ! 639: else ! 640: { ! 641: lto3b(bp->b_bcount,cmd.len); ! 642: } ! 643: ! 644: /*******************************************************\ ! 645: * Fill out the scsi_xfer structure * ! 646: * Note: we cannot sleep as we may be an interrupt * ! 647: \*******************************************************/ ! 648: xs->flags |= SCSI_NOSLEEP; ! 649: xs->adapter = st->ctlr; ! 650: xs->targ = st->targ; ! 651: xs->lu = st->lu; ! 652: xs->retries = 1; /* can't retry on tape*/ ! 653: xs->timeout = 100000; /* allow 100 secs for retension */ ! 654: xs->cmd = (struct scsi_generic *)&cmd; ! 655: xs->cmdlen = sizeof(cmd); ! 656: xs->data = (u_char *)bp->b_un.b_addr; ! 657: xs->datalen = bp->b_bcount; ! 658: xs->resid = bp->b_bcount; ! 659: xs->when_done = st_done; ! 660: xs->done_arg = unit; ! 661: xs->done_arg2 = (int)xs; ! 662: xs->error = XS_NOERROR; ! 663: xs->bp = bp; ! 664: /*******************************************************\ ! 665: * Pass all this info to the scsi driver. * ! 666: \*******************************************************/ ! 667: ! 668: ! 669: #if defined(OSF)||defined(FIX_ME) ! 670: if (bp->b_flags & B_PHYS) { ! 671: xs->data = (u_char*)map_pva_kva(bp->b_proc, bp->b_un.b_addr, ! 672: bp->b_bcount, st_window[unit], ! 673: (bp->b_flags&B_READ)?B_WRITE:B_READ); ! 674: } else { ! 675: xs->data = (u_char*)bp->b_un.b_addr; ! 676: } ! 677: #endif /* defined(OSF) */ ! 678: ! 679: if ( (*(st->sc_sw->scsi_cmd))(xs) != SUCCESSFULLY_QUEUED) ! 680: { ! 681: printf("st%d: oops not queued",unit); ! 682: xs->error = XS_DRIVER_STUFFUP; ! 683: st_done(unit,xs); ! 684: } ! 685: stqueues++; ! 686: } ! 687: ! 688: /*******************************************************\ ! 689: * This routine is called by the scsi interrupt when * ! 690: * the transfer is complete. ! 691: \*******************************************************/ ! 692: int st_done(unit,xs) ! 693: int unit; ! 694: struct scsi_xfer *xs; ! 695: { ! 696: struct buf *bp; ! 697: int retval; ! 698: ! 699: if(scsi_debug & PRINTROUTINES) printf("st_done%d ",unit); ! 700: if (! (xs->flags & INUSE)) ! 701: panic("scsi_xfer not in use!"); ! 702: if(bp = xs->bp) ! 703: { ! 704: switch(xs->error) ! 705: { ! 706: case XS_NOERROR: ! 707: bp->b_flags &= ~B_ERROR; ! 708: bp->b_error = 0; ! 709: bp->b_resid = 0; ! 710: break; ! 711: case XS_SENSE: ! 712: retval = (st_interpret_sense(unit,xs)); ! 713: if(retval) ! 714: { ! 715: /***************************************\ ! 716: * We have a real error, the bit should * ! 717: * be set to indicate this. The return * ! 718: * value will contain the unix error code* ! 719: * that the error interpretation routine * ! 720: * thought was suitable, so pass this * ! 721: * value back in the buf structure. * ! 722: * Furthermore we return information * ! 723: * saying that no data was transferred * ! 724: \***************************************/ ! 725: bp->b_flags |= B_ERROR; ! 726: bp->b_error = retval; ! 727: bp->b_resid = bp->b_bcount; ! 728: st_data[unit].flags ! 729: &= ~(ST_AT_FILEMARK|ST_AT_EOM); ! 730: } ! 731: else ! 732: { ! 733: /***********************************************\ ! 734: * The error interpretation code has declared * ! 735: * that it wasn't a real error, or at least that * ! 736: * we should be ignoring it if it was. * ! 737: \***********************************************/ ! 738: if(xs->resid && ( xs->resid != xs->datalen )) ! 739: { ! 740: /***************************************\ ! 741: * Here we have the tricky part.. * ! 742: * We successfully read less data than * ! 743: * we requested. (but not 0) * ! 744: *------for variable blocksize tapes:----* ! 745: * UNDER 386BSD: * ! 746: * We should legitimatly have the error * ! 747: * bit set, with the error value set to * ! 748: * zero.. This is to indicate to the * ! 749: * physio code that while we didn't get * ! 750: * as much information as was requested, * ! 751: * we did reach the end of the record * ! 752: * and so physio should not call us * ! 753: * again for more data... we have it all * ! 754: * SO SET THE ERROR BIT! * ! 755: * * ! 756: * UNDER MACH:(CMU) * ! 757: * To indicate the same as above, we * ! 758: * need only have a non 0 resid that is * ! 759: * less than the b_bcount, but the * ! 760: * ERROR BIT MUST BE CLEAR! (sigh) * ! 761: * * ! 762: * UNDER OSF1: * ! 763: * To indicate the same as above, we * ! 764: * need to have a non 0 resid that is * ! 765: * less than the b_bcount, but the * ! 766: * ERROR BIT MUST BE SET! (gasp)(sigh) * ! 767: * * ! 768: *-------for fixed blocksize device------* ! 769: * We could have read some successful * ! 770: * records before hitting * ! 771: * the EOF or EOT. These must be passed * ! 772: * to the user, before we report the * ! 773: * EOx. Only if there is no data for the * ! 774: * user do we report it now. (via an EIO * ! 775: * for EOM and resid == count for EOF). * ! 776: * We will report the EOx NEXT time.. * ! 777: \***************************************/ ! 778: #ifdef MACH /*osf and cmu varieties */ ! 779: #ifdef OSF ! 780: bp->b_flags |= B_ERROR; ! 781: #else OSF ! 782: bp->b_flags &= ~B_ERROR; ! 783: #endif OSF ! 784: #endif MACH ! 785: #ifdef __386BSD__ ! 786: bp->b_flags |= B_ERROR; ! 787: #endif __386BSD__ ! 788: bp->b_error = 0; ! 789: bp->b_resid = xs->resid; ! 790: if((st_data[unit].flags & ST_FIXEDBLOCKS)) ! 791: { ! 792: bp->b_resid *= st_data[unit].blkmin; ! 793: if( (st_data[unit].flags & ST_AT_EOM) ! 794: && (bp->b_resid == bp->b_bcount)) ! 795: { ! 796: bp->b_error = EIO; ! 797: st_data[unit].flags ! 798: &= ~ST_AT_EOM; ! 799: } ! 800: } ! 801: xs->error = XS_NOERROR; ! 802: break; ! 803: } ! 804: else ! 805: { ! 806: /***************************************\ ! 807: * We have come out of the error handler * ! 808: * with no error code.. we have also * ! 809: * not had an ili (would have gone to * ! 810: * the previous clause). Now we need to * ! 811: * distiguish between succesful read of * ! 812: * no data (EOF or EOM) and successfull * ! 813: * read of all requested data. * ! 814: * At least all o/s agree that: * ! 815: * 0 bytes read with no error is EOF * ! 816: * 0 bytes read with an EIO is EOM * ! 817: \***************************************/ ! 818: ! 819: bp->b_resid = bp->b_bcount; ! 820: if(st_data[unit].flags & ST_AT_FILEMARK) ! 821: { ! 822: st_data[unit].flags &= ~ST_AT_FILEMARK; ! 823: bp->b_flags &= ~B_ERROR; ! 824: bp->b_error = 0; ! 825: break; ! 826: } ! 827: if(st_data[unit].flags & ST_AT_EOM) ! 828: { ! 829: bp->b_flags |= B_ERROR; ! 830: bp->b_error = EIO; ! 831: st_data[unit].flags &= ~ST_AT_EOM; ! 832: break; ! 833: } ! 834: printf("st%d:error ignored\n" ,unit); ! 835: } ! 836: } ! 837: break; ! 838: ! 839: case XS_TIMEOUT: ! 840: printf("st%d timeout\n",unit); ! 841: break; ! 842: ! 843: case XS_BUSY: /* should retry */ /* how? */ ! 844: /************************************************/ ! 845: /* SHOULD put buf back at head of queue */ ! 846: /* and decrement retry count in (*xs) */ ! 847: /* HOWEVER, this should work as a kludge */ ! 848: /************************************************/ ! 849: if(xs->retries--) ! 850: { ! 851: xs->flags &= ~ITSDONE; ! 852: xs->error = XS_NOERROR; ! 853: if ( (*(st_data[unit].sc_sw->scsi_cmd))(xs) ! 854: == SUCCESSFULLY_QUEUED) ! 855: { /* don't wake the job, ok? */ ! 856: return; ! 857: } ! 858: printf("device busy"); ! 859: xs->flags |= ITSDONE; ! 860: } ! 861: ! 862: case XS_DRIVER_STUFFUP: ! 863: bp->b_flags |= B_ERROR; ! 864: bp->b_error = EIO; ! 865: break; ! 866: default: ! 867: printf("st%d: unknown error category from scsi driver\n" ! 868: ,unit); ! 869: } ! 870: biodone(bp); ! 871: xs->flags = 0; /* no longer in use */ ! 872: ststart(unit); /* If there's another waiting.. do it */ ! 873: } ! 874: else ! 875: { ! 876: wakeup(xs); ! 877: } ! 878: } ! 879: /*******************************************************\ ! 880: * Perform special action on behalf of the user * ! 881: * Knows about the internals of this device * ! 882: \*******************************************************/ ! 883: stioctl(dev, cmd, arg, mode) ! 884: dev_t dev; ! 885: int cmd; ! 886: caddr_t arg; ! 887: { ! 888: register i,j; ! 889: unsigned int opri; ! 890: int errcode = 0; ! 891: unsigned char unit; ! 892: int number,flags,ret; ! 893: ! 894: /*******************************************************\ ! 895: * Find the device that the user is talking about * ! 896: \*******************************************************/ ! 897: flags = 0; /* give error messages, act on errors etc. */ ! 898: unit = UNIT(dev); ! 899: ! 900: switch(cmd) ! 901: { ! 902: ! 903: case MTIOCGET: ! 904: { ! 905: struct mtget *g = (struct mtget *) arg; ! 906: ! 907: bzero(g, sizeof(struct mtget)); ! 908: g->mt_type = 0x7; /* Ultrix compat */ /*?*/ ! 909: ret=TRUE; ! 910: break; ! 911: } ! 912: ! 913: ! 914: case MTIOCTOP: ! 915: { ! 916: struct mtop *mt = (struct mtop *) arg; ! 917: ! 918: if (st_debug) ! 919: printf("[sctape_sstatus: %x %x]\n", ! 920: mt->mt_op, mt->mt_count); ! 921: ! 922: ! 923: ! 924: /* compat: in U*x it is a short */ ! 925: number = mt->mt_count; ! 926: switch ((short)(mt->mt_op)) ! 927: { ! 928: case MTWEOF: /* write an end-of-file record */ ! 929: ret = st_write_filemarks(unit,number,flags); ! 930: st_data[unit].flags &= ~ST_WRITTEN; ! 931: break; ! 932: case MTFSF: /* forward space file */ ! 933: ret = st_space(unit,number,SP_FILEMARKS,flags); ! 934: break; ! 935: case MTBSF: /* backward space file */ ! 936: ret = st_space(unit,-number,SP_FILEMARKS,flags); ! 937: break; ! 938: case MTFSR: /* forward space record */ ! 939: ret = st_space(unit,number,SP_BLKS,flags); ! 940: break; ! 941: case MTBSR: /* backward space record */ ! 942: ret = st_space(unit,-number,SP_BLKS,flags); ! 943: break; ! 944: case MTREW: /* rewind */ ! 945: ret = st_rewind(unit,FALSE,flags); ! 946: break; ! 947: case MTOFFL: /* rewind and put the drive offline */ ! 948: if((ret = st_rewind(unit,FALSE,flags))) ! 949: { ! 950: st_prevent(unit,PR_ALLOW,0); ! 951: ret = st_load(unit,LD_UNLOAD,flags); ! 952: } ! 953: else ! 954: { ! 955: printf("rewind failed, unit still loaded\n"); ! 956: } ! 957: break; ! 958: case MTNOP: /* no operation, sets status only */ ! 959: case MTCACHE: /* enable controller cache */ ! 960: case MTNOCACHE: /* disable controller cache */ ! 961: ret = TRUE;; ! 962: break; ! 963: default: ! 964: return EINVAL; ! 965: } ! 966: break; ! 967: } ! 968: case MTIOCIEOT: ! 969: case MTIOCEEOT: ! 970: ret=TRUE; ! 971: break; ! 972: } ! 973: ! 974: return(ret?ESUCCESS:EIO); ! 975: } ! 976: ! 977: ! 978: /*******************************************************\ ! 979: * Check with the device that it is ok, (via scsi driver)* ! 980: \*******************************************************/ ! 981: st_req_sense(unit, flags) ! 982: int flags; ! 983: { ! 984: struct scsi_sense_data sense; ! 985: struct scsi_sense scsi_cmd; ! 986: ! 987: bzero(&scsi_cmd, sizeof(scsi_cmd)); ! 988: scsi_cmd.op_code = REQUEST_SENSE; ! 989: scsi_cmd.length = sizeof(sense); ! 990: ! 991: if (st_scsi_cmd(unit, ! 992: &scsi_cmd, ! 993: sizeof(scsi_cmd), ! 994: &sense, ! 995: sizeof(sense), ! 996: 100000, ! 997: flags | SCSI_DATA_IN) != 0) ! 998: { ! 999: return(FALSE); ! 1000: } ! 1001: else ! 1002: return(TRUE); ! 1003: } ! 1004: ! 1005: /*******************************************************\ ! 1006: * Get scsi driver to send a "are you ready" command * ! 1007: \*******************************************************/ ! 1008: st_test_ready(unit,flags) ! 1009: int unit,flags; ! 1010: { ! 1011: struct scsi_test_unit_ready scsi_cmd; ! 1012: ! 1013: bzero(&scsi_cmd, sizeof(scsi_cmd)); ! 1014: scsi_cmd.op_code = TEST_UNIT_READY; ! 1015: ! 1016: if (st_scsi_cmd(unit, ! 1017: &scsi_cmd, ! 1018: sizeof(scsi_cmd), ! 1019: 0, ! 1020: 0, ! 1021: 100000, ! 1022: flags) != 0) { ! 1023: return(FALSE); ! 1024: } else ! 1025: return(TRUE); ! 1026: } ! 1027: ! 1028: ! 1029: #ifdef __STDC__ ! 1030: #define b2tol(a) (((unsigned)(a##_1) << 8) + (unsigned)a##_0 ) ! 1031: #else ! 1032: #define b2tol(a) (((unsigned)(a/**/_1) << 8) + (unsigned)a/**/_0 ) ! 1033: #endif ! 1034: ! 1035: /*******************************************************\ ! 1036: * Ask the drive what it's min and max blk sizes are. * ! 1037: \*******************************************************/ ! 1038: st_rd_blk_lim(unit, flags) ! 1039: int unit,flags; ! 1040: { ! 1041: struct scsi_blk_limits scsi_cmd; ! 1042: struct scsi_blk_limits_data scsi_blkl; ! 1043: struct st_data *st = st_data + unit; ! 1044: /*******************************************************\ ! 1045: * First check if we have it all loaded * ! 1046: \*******************************************************/ ! 1047: if (st_info_valid[unit]) goto done; ! 1048: ! 1049: /*******************************************************\ ! 1050: * do a 'Read Block Limits' * ! 1051: \*******************************************************/ ! 1052: bzero(&scsi_cmd, sizeof(scsi_cmd)); ! 1053: scsi_cmd.op_code = READ_BLK_LIMITS; ! 1054: ! 1055: /*******************************************************\ ! 1056: * do the command, update the global values * ! 1057: \*******************************************************/ ! 1058: if (st_scsi_cmd(unit, ! 1059: &scsi_cmd, ! 1060: sizeof(scsi_cmd), ! 1061: &scsi_blkl, ! 1062: sizeof(scsi_blkl), ! 1063: 5000, ! 1064: flags | SCSI_DATA_IN) != 0) ! 1065: { ! 1066: if(!(flags & SCSI_SILENT)) ! 1067: printf("could not get blk limits for unit %d\n", unit); ! 1068: st_info_valid[unit] = FALSE; ! 1069: return(FALSE); ! 1070: } ! 1071: if (st_debug) ! 1072: { ! 1073: printf(" (%d <= blksiz <= %d\n) ", ! 1074: b2tol(scsi_blkl.min_length), ! 1075: _3btol(&scsi_blkl.max_length_2)); ! 1076: } ! 1077: st->blkmin = b2tol(scsi_blkl.min_length); ! 1078: st->blkmax = _3btol(&scsi_blkl.max_length_2); ! 1079: ! 1080: done: ! 1081: if(st->blkmin && (st->blkmin == st->blkmax)) ! 1082: { ! 1083: st->flags |= ST_FIXEDBLOCKS; ! 1084: } ! 1085: return(TRUE); ! 1086: } ! 1087: /*******************************************************\ ! 1088: * Get the scsi driver to send a full inquiry to the * ! 1089: * device and use the results to fill out the global * ! 1090: * parameter structure. * ! 1091: \*******************************************************/ ! 1092: st_mode_sense(unit, flags) ! 1093: int unit,flags; ! 1094: { ! 1095: struct scsi_mode_sense scsi_cmd; ! 1096: struct ! 1097: { ! 1098: struct scsi_mode_header_tape header; ! 1099: struct blk_desc blk_desc; ! 1100: }scsi_sense; ! 1101: struct st_data *st = st_data + unit; ! 1102: ! 1103: /*******************************************************\ ! 1104: * First check if we have it all loaded * ! 1105: \*******************************************************/ ! 1106: if (st_info_valid[unit]) return(TRUE); ! 1107: /*******************************************************\ ! 1108: * First do a mode sense * ! 1109: \*******************************************************/ ! 1110: bzero(&scsi_cmd, sizeof(scsi_cmd)); ! 1111: scsi_cmd.op_code = MODE_SENSE; ! 1112: scsi_cmd.length = sizeof(scsi_sense); ! 1113: /*******************************************************\ ! 1114: * do the command, but we don't need the results * ! 1115: * just print them for our interest's sake * ! 1116: \*******************************************************/ ! 1117: if (st_scsi_cmd(unit, ! 1118: &scsi_cmd, ! 1119: sizeof(scsi_cmd), ! 1120: &scsi_sense, ! 1121: sizeof(scsi_sense), ! 1122: 5000, ! 1123: flags | SCSI_DATA_IN) != 0) ! 1124: { ! 1125: if(!(flags & SCSI_SILENT)) ! 1126: printf("could not mode sense for unit %d\n", unit); ! 1127: st_info_valid[unit] = FALSE; ! 1128: return(FALSE); ! 1129: } ! 1130: if (st_debug) ! 1131: { ! 1132: printf("unit %d: %d blocks of %d bytes, write %s, %sbuffered", ! 1133: unit, ! 1134: _3btol(&scsi_sense.blk_desc.nblocks), ! 1135: _3btol(&scsi_sense.blk_desc.blklen), ! 1136: (scsi_sense.header.write_protected ? ! 1137: "protected" : "enabled"), ! 1138: (scsi_sense.header.buf_mode ? ! 1139: "" : "un") ! 1140: ); ! 1141: } ! 1142: st->numblks = _3btol(&scsi_sense.blk_desc.nblocks); ! 1143: st->blksiz = _3btol(&scsi_sense.blk_desc.blklen); ! 1144: return(TRUE); ! 1145: } ! 1146: ! 1147: /*******************************************************\ ! 1148: * Get the scsi driver to send a full inquiry to the * ! 1149: * device and use the results to fill out the global * ! 1150: * parameter structure. * ! 1151: \*******************************************************/ ! 1152: st_mode_select(unit, flags, dsty_code) ! 1153: int unit,flags,dsty_code; ! 1154: { ! 1155: struct scsi_mode_select scsi_cmd; ! 1156: struct ! 1157: { ! 1158: struct scsi_mode_header_tape header; ! 1159: struct blk_desc blk_desc; ! 1160: }dat; ! 1161: struct st_data *st = st_data + unit; ! 1162: ! 1163: /*******************************************************\ ! 1164: * Set up for a mode select * ! 1165: \*******************************************************/ ! 1166: bzero(&dat, sizeof(dat)); ! 1167: bzero(&scsi_cmd, sizeof(scsi_cmd)); ! 1168: scsi_cmd.op_code = MODE_SELECT; ! 1169: scsi_cmd.length = sizeof(dat); ! 1170: dat.header.blk_desc_len = sizeof(struct blk_desc); ! 1171: dat.header.buf_mode = 1; ! 1172: dat.blk_desc.density = dsty_code; ! 1173: if(st->flags & ST_FIXEDBLOCKS) ! 1174: { ! 1175: lto3b( st->blkmin , dat.blk_desc.blklen); ! 1176: } ! 1177: /* lto3b( st->numblks , dat.blk_desc.nblocks); use defaults!!!! ! 1178: lto3b( st->blksiz , dat.blk_desc.blklen); ! 1179: */ ! 1180: /*******************************************************\ ! 1181: * do the command * ! 1182: \*******************************************************/ ! 1183: if (st_scsi_cmd(unit, ! 1184: &scsi_cmd, ! 1185: sizeof(scsi_cmd), ! 1186: &dat, ! 1187: sizeof(dat), ! 1188: 5000, ! 1189: flags | SCSI_DATA_OUT) != 0) ! 1190: { ! 1191: if(!(flags & SCSI_SILENT)) ! 1192: printf("could not mode select for unit %d\n", unit); ! 1193: st_info_valid[unit] = FALSE; ! 1194: return(FALSE); ! 1195: } ! 1196: return(TRUE); ! 1197: } ! 1198: ! 1199: /*******************************************************\ ! 1200: * skip N blocks/filemarks/seq filemarks/eom * ! 1201: \*******************************************************/ ! 1202: st_space(unit,number,what,flags) ! 1203: int unit,number,what,flags; ! 1204: { ! 1205: struct scsi_space scsi_cmd; ! 1206: ! 1207: /* if we are at a filemark now, we soon won't be*/ ! 1208: st_data[unit].flags &= ~(ST_AT_FILEMARK | ST_AT_EOM); ! 1209: bzero(&scsi_cmd, sizeof(scsi_cmd)); ! 1210: scsi_cmd.op_code = SPACE; ! 1211: scsi_cmd.code = what; ! 1212: lto3b(number,scsi_cmd.number); ! 1213: if (st_scsi_cmd(unit, ! 1214: &scsi_cmd, ! 1215: sizeof(scsi_cmd), ! 1216: 0, ! 1217: 0, ! 1218: 600000, /* 10 mins enough? */ ! 1219: flags) != 0) ! 1220: { ! 1221: if(!(flags & SCSI_SILENT)) ! 1222: printf("could not space st%d\n", unit); ! 1223: st_info_valid[unit] = FALSE; ! 1224: return(FALSE); ! 1225: } ! 1226: return(TRUE); ! 1227: } ! 1228: /*******************************************************\ ! 1229: * write N filemarks * ! 1230: \*******************************************************/ ! 1231: st_write_filemarks(unit,number,flags) ! 1232: int unit,number,flags; ! 1233: { ! 1234: struct scsi_write_filemarks scsi_cmd; ! 1235: ! 1236: st_data[unit].flags &= ~(ST_AT_FILEMARK); ! 1237: bzero(&scsi_cmd, sizeof(scsi_cmd)); ! 1238: scsi_cmd.op_code = WRITE_FILEMARKS; ! 1239: lto3b(number,scsi_cmd.number); ! 1240: if (st_scsi_cmd(unit, ! 1241: &scsi_cmd, ! 1242: sizeof(scsi_cmd), ! 1243: 0, ! 1244: 0, ! 1245: 100000, /* 10 secs.. (may need to repos head )*/ ! 1246: flags) != 0) ! 1247: { ! 1248: if(!(flags & SCSI_SILENT)) ! 1249: printf("could not write_filemarks st%d\n", unit); ! 1250: st_info_valid[unit] = FALSE; ! 1251: return(FALSE); ! 1252: } ! 1253: return(TRUE); ! 1254: } ! 1255: /*******************************************************\ ! 1256: * load /unload (with retension if true) * ! 1257: \*******************************************************/ ! 1258: st_load(unit,type,flags) ! 1259: int unit,type,flags; ! 1260: { ! 1261: struct scsi_load scsi_cmd; ! 1262: ! 1263: st_data[unit].flags &= ~(ST_AT_FILEMARK | ST_AT_EOM); ! 1264: bzero(&scsi_cmd, sizeof(scsi_cmd)); ! 1265: scsi_cmd.op_code = LOAD_UNLOAD; ! 1266: scsi_cmd.load=type; ! 1267: if (type == LD_LOAD) ! 1268: { ! 1269: /*scsi_cmd.reten=TRUE;*/ ! 1270: scsi_cmd.reten=FALSE; ! 1271: } ! 1272: else ! 1273: { ! 1274: scsi_cmd.reten=FALSE; ! 1275: } ! 1276: if (st_scsi_cmd(unit, ! 1277: &scsi_cmd, ! 1278: sizeof(scsi_cmd), ! 1279: 0, ! 1280: 0, ! 1281: 30000, /* 30 secs */ ! 1282: flags) != 0) ! 1283: { ! 1284: if(!(flags & SCSI_SILENT)) ! 1285: printf("cannot load/unload st%d\n", unit); ! 1286: st_info_valid[unit] = FALSE; ! 1287: return(FALSE); ! 1288: } ! 1289: return(TRUE); ! 1290: } ! 1291: /*******************************************************\ ! 1292: * Prevent or allow the user to remove the tape * ! 1293: \*******************************************************/ ! 1294: st_prevent(unit,type,flags) ! 1295: int unit,type,flags; ! 1296: { ! 1297: struct scsi_prevent scsi_cmd; ! 1298: ! 1299: bzero(&scsi_cmd, sizeof(scsi_cmd)); ! 1300: scsi_cmd.op_code = PREVENT_ALLOW; ! 1301: scsi_cmd.prevent=type; ! 1302: if (st_scsi_cmd(unit, ! 1303: &scsi_cmd, ! 1304: sizeof(scsi_cmd), ! 1305: 0, ! 1306: 0, ! 1307: 5000, ! 1308: flags) != 0) ! 1309: { ! 1310: if(!(flags & SCSI_SILENT)) ! 1311: printf("cannot prevent/allow on st%d\n", unit); ! 1312: st_info_valid[unit] = FALSE; ! 1313: return(FALSE); ! 1314: } ! 1315: return(TRUE); ! 1316: } ! 1317: /*******************************************************\ ! 1318: * Rewind the device * ! 1319: \*******************************************************/ ! 1320: st_rewind(unit,immed,flags) ! 1321: int unit,immed,flags; ! 1322: { ! 1323: struct scsi_rewind scsi_cmd; ! 1324: ! 1325: st_data[unit].flags &= ~(ST_AT_FILEMARK | ST_AT_EOM); ! 1326: bzero(&scsi_cmd, sizeof(scsi_cmd)); ! 1327: scsi_cmd.op_code = REWIND; ! 1328: scsi_cmd.immed=immed; ! 1329: if (st_scsi_cmd(unit, ! 1330: &scsi_cmd, ! 1331: sizeof(scsi_cmd), ! 1332: 0, ! 1333: 0, ! 1334: immed?5000:300000, /* 5 sec or 5 min */ ! 1335: flags) != 0) ! 1336: { ! 1337: if(!(flags & SCSI_SILENT)) ! 1338: printf("could not rewind st%d\n", unit); ! 1339: st_info_valid[unit] = FALSE; ! 1340: return(FALSE); ! 1341: } ! 1342: return(TRUE); ! 1343: } ! 1344: /*******************************************************\ ! 1345: * ask the scsi driver to perform a command for us. * ! 1346: * Call it through the switch table, and tell it which * ! 1347: * sub-unit we want, and what target and lu we wish to * ! 1348: * talk to. Also tell it where to find the command * ! 1349: * how long int is. * ! 1350: * Also tell it where to read/write the data, and how * ! 1351: * long the data is supposed to be * ! 1352: \*******************************************************/ ! 1353: int st_scsi_cmd(unit,scsi_cmd,cmdlen,data_addr,datalen,timeout,flags) ! 1354: ! 1355: int unit,flags; ! 1356: struct scsi_generic *scsi_cmd; ! 1357: int cmdlen; ! 1358: int timeout; ! 1359: u_char *data_addr; ! 1360: int datalen; ! 1361: { ! 1362: struct scsi_xfer *xs; ! 1363: int retval; ! 1364: int s; ! 1365: struct st_data *st = st_data + unit; ! 1366: ! 1367: if(scsi_debug & PRINTROUTINES) printf("\nst_scsi_cmd%d ",unit); ! 1368: if(st->sc_sw) /* If we have a scsi driver */ ! 1369: { ! 1370: ! 1371: xs = &(st_scsi_xfer[unit]); ! 1372: if(!(flags & SCSI_NOMASK)) ! 1373: s = splbio(); ! 1374: st_xfer_block_wait[unit]++; /* there is someone waiting */ ! 1375: while (xs->flags & INUSE) ! 1376: { ! 1377: sleep(&st_xfer_block_wait[unit],PRIBIO+1); ! 1378: } ! 1379: st_xfer_block_wait[unit]--; ! 1380: xs->flags = INUSE; ! 1381: if(!(flags & SCSI_NOMASK)) ! 1382: splx(s); ! 1383: ! 1384: /*******************************************************\ ! 1385: * Fill out the scsi_xfer structure * ! 1386: \*******************************************************/ ! 1387: xs->flags |= flags; ! 1388: xs->adapter = st->ctlr; ! 1389: xs->targ = st->targ; ! 1390: xs->lu = st->lu; ! 1391: xs->retries = ST_RETRIES; ! 1392: xs->timeout = timeout; ! 1393: xs->cmd = scsi_cmd; ! 1394: xs->cmdlen = cmdlen; ! 1395: xs->data = data_addr; ! 1396: xs->datalen = datalen; ! 1397: xs->resid = datalen; ! 1398: xs->when_done = (flags & SCSI_NOMASK) ! 1399: ?(int (*)())0 ! 1400: :st_done; ! 1401: xs->done_arg = unit; ! 1402: xs->done_arg2 = (int)xs; ! 1403: retry: xs->error = XS_NOERROR; ! 1404: xs->bp = 0; ! 1405: retval = (*(st->sc_sw->scsi_cmd))(xs); ! 1406: switch(retval) ! 1407: { ! 1408: case SUCCESSFULLY_QUEUED: ! 1409: s = splbio(); ! 1410: while(!(xs->flags & ITSDONE)) ! 1411: sleep(xs,PRIBIO+1); ! 1412: splx(s); ! 1413: ! 1414: case HAD_ERROR: ! 1415: case COMPLETE: ! 1416: switch(xs->error) ! 1417: { ! 1418: case XS_NOERROR: ! 1419: retval = ESUCCESS; ! 1420: break; ! 1421: case XS_SENSE: ! 1422: retval = (st_interpret_sense(unit,xs)); ! 1423: /* only useful for reads */ ! 1424: if (retval) ! 1425: { /* error... don't care about filemarks */ ! 1426: st->flags &= ~(ST_AT_FILEMARK ! 1427: | ST_AT_EOM); ! 1428: } ! 1429: else ! 1430: { ! 1431: xs->error = XS_NOERROR; ! 1432: retval = ESUCCESS; ! 1433: } ! 1434: break; ! 1435: case XS_DRIVER_STUFFUP: ! 1436: retval = EIO; ! 1437: break; ! 1438: case XS_TIMEOUT: ! 1439: if(xs->retries-- ) ! 1440: { ! 1441: xs->flags &= ~ITSDONE; ! 1442: goto retry; ! 1443: } ! 1444: retval = EIO; ! 1445: break; ! 1446: case XS_BUSY: ! 1447: if(xs->retries-- ) ! 1448: { ! 1449: xs->flags &= ~ITSDONE; ! 1450: goto retry; ! 1451: } ! 1452: retval = EIO; ! 1453: break; ! 1454: default: ! 1455: retval = EIO; ! 1456: printf("st%d: unknown error category from scsi driver\n" ! 1457: ,unit); ! 1458: break; ! 1459: } ! 1460: break; ! 1461: case TRY_AGAIN_LATER: ! 1462: if(xs->retries-- ) ! 1463: { ! 1464: xs->flags &= ~ITSDONE; ! 1465: goto retry; ! 1466: } ! 1467: retval = EIO; ! 1468: break; ! 1469: default: ! 1470: retval = EIO; ! 1471: } ! 1472: xs->flags = 0; /* it's free! */ ! 1473: ststart(unit); ! 1474: } ! 1475: else ! 1476: { ! 1477: printf("st%d: not set up\n",unit); ! 1478: return(EINVAL); ! 1479: } ! 1480: return(retval); ! 1481: } ! 1482: /***************************************************************\ ! 1483: * Look at the returned sense and act on the error and detirmine * ! 1484: * The unix error number to pass back... (0 = report no error) * ! 1485: \***************************************************************/ ! 1486: ! 1487: int st_interpret_sense(unit,xs) ! 1488: int unit; ! 1489: struct scsi_xfer *xs; ! 1490: { ! 1491: struct scsi_sense_data *sense; ! 1492: int key; ! 1493: int silent = xs->flags & SCSI_SILENT; ! 1494: ! 1495: /***************************************************************\ ! 1496: * If errors are ok, report a success * ! 1497: \***************************************************************/ ! 1498: if(xs->flags & SCSI_ERR_OK) return(ESUCCESS); ! 1499: ! 1500: /***************************************************************\ ! 1501: * Get the sense fields and work out what CLASS * ! 1502: \***************************************************************/ ! 1503: sense = &(xs->sense); ! 1504: if(st_debug) ! 1505: { ! 1506: int count = 0; ! 1507: printf("code%x class%x valid%x\n" ! 1508: ,sense->error_code ! 1509: ,sense->error_class ! 1510: ,sense->valid); ! 1511: printf("seg%x key%x ili%x eom%x fmark%x\n" ! 1512: ,sense->ext.extended.segment ! 1513: ,sense->ext.extended.sense_key ! 1514: ,sense->ext.extended.ili ! 1515: ,sense->ext.extended.eom ! 1516: ,sense->ext.extended.filemark); ! 1517: printf("info: %x %x %x %x followed by %d extra bytes\n" ! 1518: ,sense->ext.extended.info[0] ! 1519: ,sense->ext.extended.info[1] ! 1520: ,sense->ext.extended.info[2] ! 1521: ,sense->ext.extended.info[3] ! 1522: ,sense->ext.extended.extra_len); ! 1523: printf("extra: "); ! 1524: while(count < sense->ext.extended.extra_len) ! 1525: { ! 1526: printf ("%x ",sense->ext.extended.extra_bytes[count++]); ! 1527: } ! 1528: printf("\n"); ! 1529: } ! 1530: switch(sense->error_class) ! 1531: { ! 1532: /***************************************************************\ ! 1533: * If it's class 7, use the extended stuff and interpret the key * ! 1534: \***************************************************************/ ! 1535: case 7: ! 1536: { ! 1537: if(sense->ext.extended.eom) ! 1538: { ! 1539: st_data[unit].flags |= ST_AT_EOM; ! 1540: } ! 1541: ! 1542: if(sense->ext.extended.filemark) ! 1543: { ! 1544: st_data[unit].flags |= ST_AT_FILEMARK; ! 1545: } ! 1546: ! 1547: if(sense->ext.extended.ili) ! 1548: { ! 1549: if(sense->valid) ! 1550: { ! 1551: /*******************************\ ! 1552: * In all ili cases, note that * ! 1553: * the resid is non-0 AND not * ! 1554: * unchanged. * ! 1555: \*******************************/ ! 1556: xs->resid ! 1557: = ntohl(*((long *)sense->ext.extended.info)); ! 1558: if(xs->bp) ! 1559: { ! 1560: if(xs->resid < 0) ! 1561: { /* never on block devices */ ! 1562: /***********************\ ! 1563: * it's only really bad * ! 1564: * if we have lost data * ! 1565: * (the record was * ! 1566: * bigger than the read) * ! 1567: \***********************/ ! 1568: return(EIO); ! 1569: } ! 1570: } ! 1571: } ! 1572: else ! 1573: { /* makes no sense.. complain */ ! 1574: printf("BAD length error?"); ! 1575: } ! 1576: }/* there may be some other error. check the rest */ ! 1577: ! 1578: key=sense->ext.extended.sense_key; ! 1579: switch(key) ! 1580: { ! 1581: case 0x0: ! 1582: return(ESUCCESS); ! 1583: case 0x1: ! 1584: if(!silent) ! 1585: { ! 1586: printf("st%d: soft error(corrected) ", unit); ! 1587: if(sense->valid) ! 1588: { ! 1589: printf("block no. %d (decimal)\n", ! 1590: (sense->ext.extended.info[0] <<24)| ! 1591: (sense->ext.extended.info[1] <<16)| ! 1592: (sense->ext.extended.info[2] <<8)| ! 1593: (sense->ext.extended.info[3] )); ! 1594: } ! 1595: else ! 1596: { ! 1597: printf("\n"); ! 1598: } ! 1599: } ! 1600: return(ESUCCESS); ! 1601: case 0x2: ! 1602: if(!silent) printf("st%d: not ready\n ", unit); ! 1603: return(ENODEV); ! 1604: case 0x3: ! 1605: if(!silent) ! 1606: { ! 1607: printf("st%d: medium error ", unit); ! 1608: if(sense->valid) ! 1609: { ! 1610: printf("block no. %d (decimal)\n", ! 1611: (sense->ext.extended.info[0] <<24)| ! 1612: (sense->ext.extended.info[1] <<16)| ! 1613: (sense->ext.extended.info[2] <<8)| ! 1614: (sense->ext.extended.info[3] )); ! 1615: } ! 1616: else ! 1617: { ! 1618: printf("\n"); ! 1619: } ! 1620: } ! 1621: return(EIO); ! 1622: case 0x4: ! 1623: if(!silent) printf("st%d: non-media hardware failure\n ", ! 1624: unit); ! 1625: return(EIO); ! 1626: case 0x5: ! 1627: if(!silent) printf("st%d: illegal request\n ", unit); ! 1628: return(EINVAL); ! 1629: case 0x6: ! 1630: if(!silent) printf("st%d: Unit attention.\n ", unit); ! 1631: st_data[unit].flags &= ~(ST_AT_FILEMARK|ST_AT_EOM); ! 1632: st_info_valid[unit] = FALSE; ! 1633: if (st_data[unit].flags & ST_OPEN) /* TEMP!!!! */ ! 1634: return(EIO); ! 1635: else ! 1636: return(ESUCCESS); ! 1637: case 0x7: ! 1638: if(!silent) ! 1639: { ! 1640: printf("st%d: attempted protection violation " ! 1641: , unit); ! 1642: if(sense->valid) ! 1643: { ! 1644: printf("block no. %d (decimal)\n", ! 1645: (sense->ext.extended.info[0] <<24)| ! 1646: (sense->ext.extended.info[1] <<16)| ! 1647: (sense->ext.extended.info[2] <<8)| ! 1648: (sense->ext.extended.info[3] )); ! 1649: } ! 1650: else ! 1651: { ! 1652: printf("\n"); ! 1653: } ! 1654: } ! 1655: return(EACCES); ! 1656: case 0x8: ! 1657: if(!silent) ! 1658: { ! 1659: printf("st%d: block wrong state (worm)\n " ! 1660: , unit); ! 1661: if(sense->valid) ! 1662: { ! 1663: printf("block no. %d (decimal)\n", ! 1664: (sense->ext.extended.info[0] <<24)| ! 1665: (sense->ext.extended.info[1] <<16)| ! 1666: (sense->ext.extended.info[2] <<8)| ! 1667: (sense->ext.extended.info[3] )); ! 1668: } ! 1669: else ! 1670: { ! 1671: printf("\n"); ! 1672: } ! 1673: } ! 1674: return(EIO); ! 1675: case 0x9: ! 1676: if(!silent) printf("st%d: vendor unique\n", ! 1677: unit); ! 1678: return(EIO); ! 1679: case 0xa: ! 1680: if(!silent) printf("st%d: copy aborted\n ", ! 1681: unit); ! 1682: return(EIO); ! 1683: case 0xb: ! 1684: if(!silent) printf("st%d: command aborted\n ", ! 1685: unit); ! 1686: return(EIO); ! 1687: case 0xc: ! 1688: if(!silent) ! 1689: { ! 1690: printf("st%d: search returned\n ", unit); ! 1691: if(sense->valid) ! 1692: { ! 1693: printf("block no. %d (decimal)\n", ! 1694: (sense->ext.extended.info[0] <<24)| ! 1695: (sense->ext.extended.info[1] <<16)| ! 1696: (sense->ext.extended.info[2] <<8)| ! 1697: (sense->ext.extended.info[3] )); ! 1698: } ! 1699: else ! 1700: { ! 1701: printf("\n"); ! 1702: } ! 1703: } ! 1704: return(ESUCCESS); ! 1705: case 0xd: ! 1706: if(!silent) printf("st%d: volume overflow\n ", ! 1707: unit); ! 1708: return(ENOSPC); ! 1709: case 0xe: ! 1710: if(!silent) ! 1711: { ! 1712: printf("st%d: verify miscompare\n ", unit); ! 1713: if(sense->valid) ! 1714: { ! 1715: printf("block no. %d (decimal)\n", ! 1716: (sense->ext.extended.info[0] <<24)| ! 1717: (sense->ext.extended.info[1] <<16)| ! 1718: (sense->ext.extended.info[2] <<8)| ! 1719: (sense->ext.extended.info[3] )); ! 1720: } ! 1721: else ! 1722: { ! 1723: printf("\n"); ! 1724: } ! 1725: } ! 1726: return(EIO); ! 1727: case 0xf: ! 1728: if(!silent) printf("st%d: unknown error key\n ", ! 1729: unit); ! 1730: return(EIO); ! 1731: } ! 1732: break; ! 1733: } ! 1734: /***************************************************************\ ! 1735: * If it's NOT class 7, just report it. * ! 1736: \***************************************************************/ ! 1737: case 0: ! 1738: case 1: ! 1739: case 2: ! 1740: case 3: ! 1741: case 4: ! 1742: case 5: ! 1743: case 6: ! 1744: { ! 1745: if(!silent) printf("st%d: error class %d code %d\n", ! 1746: unit, ! 1747: sense->error_class, ! 1748: sense->error_code); ! 1749: if(sense->valid) ! 1750: if(!silent) printf("block no. %d (decimal)\n", ! 1751: (sense->ext.unextended.blockhi <<16), ! 1752: + (sense->ext.unextended.blockmed <<8), ! 1753: + (sense->ext.unextended.blocklow )); ! 1754: } ! 1755: return(EIO); ! 1756: } ! 1757: } ! 1758: ! 1759: #if defined(OSF) ! 1760: ! 1761: stsize(dev_t dev) ! 1762: { ! 1763: printf("stsize() -- not implemented\n"); ! 1764: return(0); ! 1765: } ! 1766: ! 1767: stdump() ! 1768: { ! 1769: printf("stdump() -- not implemented\n"); ! 1770: return(-1); ! 1771: } ! 1772: ! 1773: #endif /* defined(OSF) */ ! 1774:
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.