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