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