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