|
|
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.