1 /*
2 * Copyright (c) 1990 University of Utah.
3 * Copyright (c) 1990, 1993
4 * The Regents of the University of California. All rights reserved.
5 *
6 * This code is derived from software contributed to Berkeley by
7 * the Systems Programming Group of the University of Utah Computer
8 * Science Department.
9 *
10 * %sccs.include.redist.c%
11 *
12 * from: Utah $Hdr: st.c 1.11 92/01/21$
13 *
14 * @(#)st.c 8.5 (Berkeley) 01/09/95
15 */
16
17 /*
18 * SCSI CCS (Command Command Set) tape driver.
19 *
20 * Specific to Exabyte:
21 * mt status: residual="Mbytes to LEOM"
22 * minor bit 4 [b1bbbb] (aka /dev/rst16) selects short filemarks
23 * minor bit 5 [1bbbbb] (aka /dev/rst32) selects fix block mode, 1k blocks.
24 *
25 * Archive drive:
26 * can read both QIC-24 and QIC-II. But only writes
27 * QIC-24.
28 *
29 * Supports Archive Viper QIC-150 tape drive, but scsi.c reports selection
30 * errors.
31 *
32 * Supports Archive Python DAT drive, but will sometimes hang machine.
33 *
34 * Supports HP 35450A DAT drive, but will sometimes hang machine.
35 * Partitioning of tape not supported.
36 * Vendor unique support has not been added.
37 *
38 *
39 * Supports Archive VIPER (QIC-150).
40 * Mostly Supports Archive PYTHON (DAT).
41 * Hangs if write after spin down.
42 * Need scsi.c that does connect/disconnect.
43 */
44
45 /*
46 * support for the block device not implemented
47 */
48
49 #include "st.h"
50 #if NST > 0
51
52 #include <sys/param.h>
53 #include <sys/systm.h>
54 #include <sys/buf.h>
55 #include <sys/file.h>
56 #include <sys/proc.h>
57 #include <sys/ioctl.h>
58 #include <sys/tty.h>
59 #include <sys/mtio.h>
60 #include <sys/kernel.h>
61 #include <sys/tprintf.h>
62
63 #include <hp/dev/device.h>
64 #include <hp300/dev/scsireg.h>
65 #include <hp300/dev/stvar.h>
66
67 extern int scsi_test_unit_rdy();
68 extern int scsi_request_sense();
69 extern int scsiustart();
70 extern int scsigo();
71 extern void scsifree();
72 extern void scsireset();
73 extern void scsi_delay();
74 extern int scsi_tt_oddio();
75
76 extern int scsi_immed_command();
77
78 int stinit(), ststart(), stgo(), stintr();
79 struct driver stdriver = {
80 stinit, "st", ststart, stgo, stintr,
81 };
82
83 struct st_softc {
84 struct hp_device *sc_hd;
85 struct devqueue sc_dq;
86 long sc_blkno; /* (possible block device support?) */
87 long sc_resid; /* (possible block device support?) */
88 int sc_flags;
89 int sc_blklen; /* 0 = variable len records */
90 int sc_filepos; /* file position on tape */
91 long sc_numblks; /* number of blocks on tape */
92 short sc_type; /* ansi scsi type */
93 short sc_punit; /* physical unit (scsi lun) */
94 short sc_tapeid; /* tape drive id */
95 char sc_datalen[32]; /* additional data length on some commands */
96 short sc_tticntdwn; /* interrupts between TTi display updates */
97 tpr_t sc_ctty;
98 struct buf *sc_bp;
99 u_char sc_cmd;
100 } st_softc[NST];
101
102 /* softc flags */
103 #define STF_ALIVE 0x0001
104 #define STF_OPEN 0x0002
105 #define STF_WMODE 0x0004
106 #define STF_WRTTN 0x0008
107 #define STF_CMD 0x0010
108 #define STF_LEOT 0x0020
109 #define STF_MOVED 0x0040
110
111 struct st_mode st_mode[NST];
112
113 /*
114 * Maybe this should not be global, but gives chance to get
115 * tape remaining, Rewrites/ECC, etc outside the driver
116 */
117 static struct st_xsense {
118 struct scsi_xsense sc_xsense; /* data from sense */
119 struct exb_xsense exb_xsense; /* additional info from exabyte */
120 } st_xsense[NST];
121
122 static struct scsi_fmt_cdb stcmd[NST];
123
124 static struct scsi_fmt_cdb st_read_cmd = { 6, CMD_READ };
125 static struct scsi_fmt_cdb st_write_cmd = { 6, CMD_WRITE };
126
127 struct buf sttab[NST];
128 struct buf stbuf[NST];
129
130 #define UNIT(x) (minor(x) & 3)
131 #define stpunit(x) ((x) & 7)
132
133 #define STDEV_NOREWIND 0x04
134 #define STDEV_HIDENSITY 0x08
135 #define STDEV_EXSFMK 0x10
136 #define STDEV_FIXEDBLK 0x20
137
138 #ifdef DEBUG
139 int st_debug = 0x0000;
140 #define ST_OPEN 0x0001
141 #define ST_GO 0x0002
142 #define ST_FMKS 0x0004
143 #define ST_OPENSTAT 0x0008
144 #define ST_BRESID 0x0010
145 #define ST_ODDIO 0x0020
146 #endif
147
148 /*
149 * Patchable variable. If an even length read is requested a dma transfer is
150 * used. Only after the read will we find out if the read had an odd number
151 * of bytes. The HP98658 hardware cannot do odd length transfers, the last
152 * byte of the data will always be 0x00. Normally, the driver will complain
153 * about such transfers and return EIO. However, if st_dmaoddretry is non-
154 * zero, the driver will try and issue a BSR and then re-read the data using
155 * 'programmed transfer mode'. In most cases this works, however for unknown
156 * reasons it will hang the machine in certain cases.
157 *
158 * Note:
159 * Odd length read requests are always done using programmed transfer mode.
160 */
161 int st_dmaoddretry = 0;
162
163 /*
164 * Exabyte only:
165 * From adb can have access to fixed vs. variable length modes.
166 * Use 0x400 for 1k (best capacity) fixed length records.
167 * In st_open, if minor bit 4 set then 1k records are used.
168 * If st_exblken is set to anything other then 0 we are in fixed length mode.
169 * Minor bit 5 requests 1K fixed-length, overriding any setting of st_exblklen.
170 */
171 int st_exblklen = 0;
172
173 /* exabyte here for adb access, set at open time */
174 #define EX_CT 0x80 /* international cart - more space W/P6 */
175 #define EX_ND 0x20 /* no disconnect */
176 #define EX_NBE 0x08 /* no busy enable */
177 #define EX_EBD 0x04 /* even byte disconnect */
178 #define EX_PE 0x02 /* parity enable */
179 #define EX_NAL 0x01 /* no auto load */
180 int st_exvup = (EX_CT|EX_ND|EX_NBE); /* vendor unique parameters */
181
182 /*
183 * motion and reconnect thresholds guidelines:
184 * write operation; lower motion threshold for faster transfer
185 * raise reconnect threshold for slower transfer
186 * read operation; lower motion threshold for slower transfer
187 * raise reconnect threshold for faster transfer
188 */
189 int st_exmotthr = 0x80; /* motion threshold, 0x80 default */
190 int st_exreconthr = 0xa0; /* reconnect threshold, 0xa0 default */
191 int st_exgapthr = 7; /* gap threshold, 7 default */
192 #ifdef TTI
193 int st_extti = 0x01; /* bitmask of unit numbers, do extra */
194 /* sensing so TTi display gets updated */
195 #endif
196
stinit(hd)197 stinit(hd)
198 register struct hp_device *hd;
199 {
200 register struct st_softc *sc = &st_softc[hd->hp_unit];
201 register struct buf *bp;
202
203 for (bp = sttab; bp < &sttab[NST]; bp++)
204 bp->b_actb = &bp->b_actf;
205 sc->sc_hd = hd;
206 sc->sc_punit = stpunit(hd->hp_flags);
207 sc->sc_type = stident(sc, hd);
208 if (sc->sc_type < 0)
209 return(0);
210 sc->sc_dq.dq_ctlr = hd->hp_ctlr;
211 sc->sc_dq.dq_unit = hd->hp_unit;
212 sc->sc_dq.dq_slave = hd->hp_slave;
213 sc->sc_dq.dq_driver = &stdriver;
214 sc->sc_blkno = 0;
215 sc->sc_flags = STF_ALIVE;
216 return(1);
217 }
218
stident(sc,hd)219 stident(sc, hd)
220 register struct st_softc *sc;
221 register struct hp_device *hd;
222 {
223 int unit;
224 int ctlr, slave;
225 int i, stat, inqlen;
226 char idstr[32];
227 static int havest = 0;
228 struct st_inquiry {
229 struct scsi_inquiry inqbuf;
230 struct exb_inquiry exb_inquiry;
231 } st_inqbuf;
232 static struct scsi_fmt_cdb st_inq = {
233 6,
234 CMD_INQUIRY, 0, 0, 0, sizeof(st_inqbuf), 0
235 };
236
237 ctlr = hd->hp_ctlr;
238 slave = hd->hp_slave;
239 unit = sc->sc_punit;
240 scsi_delay(-1);
241
242 inqlen = 0x05; /* min */
243 st_inq.cdb[4] = 0x05;
244 stat = scsi_immed_command(ctlr, slave, unit, &st_inq,
245 (u_char *)&st_inqbuf, inqlen, B_READ);
246 /* do twice as first command on some scsi tapes always fails */
247 stat = scsi_immed_command(ctlr, slave, unit, &st_inq,
248 (u_char *)&st_inqbuf, inqlen, B_READ);
249 if (stat == -1)
250 goto failed;
251
252 if ((st_inqbuf.inqbuf.type != 0x01 || /* sequential access device */
253 st_inqbuf.inqbuf.qual != 0x80 || /* removable media */
254 (st_inqbuf.inqbuf.version != 0x01 && /* current ANSI SCSI spec */
255 st_inqbuf.inqbuf.version != 0x02)) /* 0x02 is for HP DAT */
256 &&
257 (st_inqbuf.inqbuf.type != 0x01 || /* M4 ??! */
258 /*
259 * the M4 is a little too smart (ass?) for its own good:
260 * qual codes:
261 * 0x80: you can take the tape out (unit not online)
262 * 0xf8: online and at 6250bpi
263 * 0xf9: online and at 1600bpi
264 */
265 st_inqbuf.inqbuf.version != 0x09)) /* M4 tape */
266 {
267 printf("st: wrong specs: type %x qual %x version %d\n", st_inqbuf.inqbuf.type,
268 st_inqbuf.inqbuf.qual, st_inqbuf.inqbuf.version);
269 goto failed;
270 }
271
272 /* now get additonal info */
273 inqlen = 0x05 + st_inqbuf.inqbuf.len;
274 st_inq.cdb[4] = inqlen;
275 bzero(&st_inqbuf, sizeof(st_inqbuf));
276 stat = scsi_immed_command(ctlr, slave, unit, &st_inq,
277 (u_char *)&st_inqbuf, inqlen, B_READ);
278
279 if (st_inqbuf.inqbuf.len >= 28) {
280 bcopy((caddr_t)&st_inqbuf.inqbuf.vendor_id, (caddr_t)idstr, 28);
281 for (i = 27; i > 23; --i)
282 if (idstr[i] != ' ')
283 break;
284 idstr[i+1] = 0;
285 for (i = 23; i > 7; --i)
286 if (idstr[i] != ' ')
287 break;
288 idstr[i+1] = 0;
289 for (i = 7; i >= 0; --i)
290 if (idstr[i] != ' ')
291 break;
292 idstr[i+1] = 0;
293 printf("st%d: %s, %s rev %s\n", hd->hp_unit, idstr, &idstr[8],
294 &idstr[24]);
295 } else if (inqlen == 5)
296 /* great it's a stupid device, doesn't know it's know name */
297 idstr[0] = idstr[8] = '\0';
298 else
299 idstr[8] = '\0';
300
301 if (stat == 0xff) {
302 printf("st%d: Cant handle this tape drive\n", hd->hp_unit);
303 goto failed;
304 }
305
306 if (bcmp("EXB-8200", &idstr[8], 8) == 0) {
307 sc->sc_tapeid = MT_ISEXABYTE;
308 sc->sc_datalen[CMD_REQUEST_SENSE] = 26;
309 sc->sc_datalen[CMD_INQUIRY] = 52;
310 sc->sc_datalen[CMD_MODE_SELECT] = 17;
311 sc->sc_datalen[CMD_MODE_SENSE] = 17;
312 } else if (bcmp("VIPER 150", &idstr[8], 9) == 0) {
313 sc->sc_tapeid = MT_ISVIPER1;
314 sc->sc_datalen[CMD_REQUEST_SENSE] = 14;
315 sc->sc_datalen[CMD_INQUIRY] = 36;
316 sc->sc_datalen[CMD_MODE_SELECT] = 12;
317 sc->sc_datalen[CMD_MODE_SENSE] = 12;
318 } else if (bcmp("Python 25501", &idstr[8], 12) == 0) {
319 sc->sc_tapeid = MT_ISPYTHON;
320 sc->sc_datalen[CMD_REQUEST_SENSE] = 14;
321 sc->sc_datalen[CMD_INQUIRY] = 36;
322 sc->sc_datalen[CMD_MODE_SELECT] = 12;
323 sc->sc_datalen[CMD_MODE_SENSE] = 12;
324 } else if (bcmp("HP35450A", &idstr[8], 8) == 0) {
325 /* XXX "extra" stat makes the HP drive happy at boot time */
326 stat = scsi_test_unit_rdy(ctlr, slave, unit);
327 sc->sc_tapeid = MT_ISHPDAT;
328 sc->sc_datalen[CMD_REQUEST_SENSE] = 14;
329 sc->sc_datalen[CMD_INQUIRY] = 36;
330 sc->sc_datalen[CMD_MODE_SELECT] = 12;
331 sc->sc_datalen[CMD_MODE_SENSE] = 12;
332 } else if (bcmp("123107 SCSI", &idstr[8], 11) == 0 ||
333 bcmp("OPEN REEL TAPE", &idstr[8], 14) == 0) {
334 sc->sc_tapeid = MT_ISMFOUR;
335 sc->sc_datalen[CMD_REQUEST_SENSE] = 8;
336 sc->sc_datalen[CMD_INQUIRY] = 5;
337 sc->sc_datalen[CMD_MODE_SELECT] = 12;
338 sc->sc_datalen[CMD_MODE_SENSE] = 12;
339 } else {
340 if (idstr[8] == '\0')
341 printf("st%d: No ID, assuming Archive\n", hd->hp_unit);
342 else
343 printf("st%d: Unsupported tape device\n", hd->hp_unit);
344 sc->sc_tapeid = MT_ISAR;
345 sc->sc_datalen[CMD_REQUEST_SENSE] = 8;
346 sc->sc_datalen[CMD_INQUIRY] = 5;
347 sc->sc_datalen[CMD_MODE_SELECT] = 12;
348 sc->sc_datalen[CMD_MODE_SENSE] = 12;
349 }
350
351 sc->sc_filepos = 0;
352
353 /* load xsense */
354 stxsense(ctlr, slave, unit, sc);
355
356 scsi_delay(0);
357 /* XXX if we have a tape, we must up the delays in the HA driver */
358 if (!havest) {
359 havest = 1;
360 scsi_delay(20000);
361 }
362 return(st_inqbuf.inqbuf.type);
363 failed:
364 scsi_delay(0);
365 return(-1);
366 }
367
stopen(dev,flag,type,p)368 stopen(dev, flag, type, p)
369 dev_t dev;
370 int flag, type;
371 struct proc *p;
372 {
373 register struct st_softc *sc = &st_softc[UNIT(dev)];
374 register struct st_xsense *xsense;
375 register int count;
376 register int stat;
377 int ctlr, slave, unit;
378 struct mode_select_data msd;
379 struct mode_sense mode;
380 int modlen;
381 int error;
382 static struct scsi_fmt_cdb modsel = {
383 6,
384 CMD_MODE_SELECT, 0, 0, 0, sizeof(msd), 0
385 };
386 static struct scsi_fmt_cdb modsense = {
387 6,
388 CMD_MODE_SENSE, 0, 0, 0, sizeof(mode), 0
389 };
390
391 ctlr = sc->sc_dq.dq_ctlr;
392 slave = sc->sc_dq.dq_slave;
393 unit = sc->sc_punit;
394 xsense = &st_xsense[UNIT(dev)];
395
396 if (UNIT(dev) > NST || (sc->sc_flags & STF_ALIVE) == 0)
397 return(ENXIO);
398 if (sc->sc_flags & STF_OPEN)
399 return(EBUSY);
400
401 /*
402 * Be prepared to print error messages
403 */
404 sc->sc_ctty = tprintf_open(p);
405
406 /* do a mode sense to get current */
407 modlen = sc->sc_datalen[CMD_MODE_SENSE];
408 modsense.cdb[4] = modlen;
409 stat = scsi_immed_command(ctlr, slave, unit, &modsense,
410 (u_char *)&mode, modlen, B_READ);
411
412 /* do a mode sense to get current */
413 modlen = sc->sc_datalen[CMD_MODE_SENSE];
414 modsense.cdb[4] = modlen;
415 stat = scsi_immed_command(ctlr, slave, unit, &modsense,
416 (u_char *)&mode, modlen, B_READ);
417
418 /* set record length */
419 switch (sc->sc_tapeid) {
420 case MT_ISAR:
421 sc->sc_blklen = 512;
422 break;
423 case MT_ISEXABYTE:
424 if (minor(dev) & STDEV_FIXEDBLK)
425 sc->sc_blklen = 0x400;
426 else
427 sc->sc_blklen = st_exblklen;
428 break;
429 case MT_ISHPDAT:
430 sc->sc_blklen = 512;
431 break;
432 case MT_ISVIPER1:
433 sc->sc_blklen = 512;
434 break;
435 case MT_ISPYTHON:
436 sc->sc_blklen = 512;
437 break;
438 case MT_ISMFOUR:
439 sc->sc_blklen = 0;
440 break;
441 default:
442 if ((mode.md.blklen2 << 16 |
443 mode.md.blklen1 << 8 |
444 mode.md.blklen0) != 0)
445 sc->sc_blklen = mode.md.blklen2 << 16 |
446 mode.md.blklen1 << 8 |
447 mode.md.blklen0;
448 else
449 sc->sc_blklen = 512;
450 }
451
452 /* setup for mode select */
453 msd.rsvd1 = 0;
454 msd.rsvd2 = 0;
455 msd.rsvd3 = 0;
456 msd.buff = 1;
457 msd.speed = 0;
458 msd.blkdeslen = 0x08;
459 msd.density = 0;
460 msd.blks2 = 0;
461 msd.blks1 = 0;
462 msd.blks0 = 0;
463 msd.rsvd4 = 0;
464 msd.blklen2 = (sc->sc_blklen >> 16) & 0xff;
465 msd.blklen1 = (sc->sc_blklen >> 8) & 0xff;
466 msd.blklen0 = sc->sc_blklen & 0xff;
467
468 /*
469 * Do we have any density problems?
470 */
471
472 switch (sc->sc_tapeid) {
473 case MT_ISAR:
474 if (minor(dev) & STDEV_HIDENSITY)
475 msd.density = 0x5;
476 else {
477 if (flag & FWRITE) {
478 uprintf("Can only write QIC-24\n");
479 return(EIO);
480 }
481 msd.density = 0x4;
482 }
483 break;
484 case MT_ISEXABYTE:
485 if (minor(dev) & STDEV_HIDENSITY)
486 uprintf("EXB-8200 density support only\n");
487 msd.vupb = (u_char)st_exvup;
488 msd.rsvd5 = 0;
489 msd.p5 = 0;
490 msd.motionthres = (u_char)st_exmotthr;
491 msd.reconthres = (u_char)st_exreconthr;
492 msd.gapthres = (u_char)st_exgapthr;
493 break;
494 case MT_ISHPDAT:
495 case MT_ISVIPER1:
496 case MT_ISPYTHON:
497 if (minor(dev) & STDEV_HIDENSITY)
498 uprintf("Only one density supported\n");
499 break;
500 case MT_ISMFOUR:
501 break; /* XXX could do density select? */
502 default:
503 uprintf("Unsupported drive\n");
504 return(EIO);
505 }
506
507 modlen = sc->sc_datalen[CMD_MODE_SELECT];
508 modsel.cdb[4] = modlen;
509
510 /* mode select */
511 count = 0;
512 retryselect:
513 stat = scsi_immed_command(ctlr, slave, unit, &modsel,
514 (u_char *)&msd, modlen, B_WRITE);
515 /*
516 * First command after power cycle, bus reset or tape change
517 * will error. Try command again
518 */
519 if (stat == STS_CHECKCOND) {
520 sc->sc_filepos = 0;
521 stxsense(ctlr, slave, unit, sc);
522 stat = scsi_immed_command(ctlr, slave, unit, &modsel,
523 (u_char *)&msd, modlen, B_WRITE);
524 #ifdef DEBUG
525 if (stat && (st_debug & ST_OPEN))
526 printf("stopen: stat on mode select 0x%x second try\n", stat);
527 #endif
528 if (stat == STS_CHECKCOND) {
529 stxsense(ctlr, slave, unit, sc);
530 prtkey(UNIT(dev), sc);
531 }
532 if (stat)
533 return(EIO);
534 }
535 if (stat == -1 || stat == STS_BUSY) {
536 /*
537 * XXX it might just be that the bus is busy because
538 * another tape is doing a command. This would change
539 * with connect/disconnect, ie. the other drive would
540 * not hold onto the bus.
541 *
542 * Sleep on lbolt for up to 20 minutes (max time to FSF
543 * an exabyte to EOT: 16:xx minutes)
544 */
545 if (++count > 60*20) {
546 uprintf("SCSI bus timeout\n");
547 return(EBUSY);
548 }
549 if (error = tsleep((caddr_t)&lbolt, PZERO | PCATCH,
550 "st_scsiwait", 0))
551 return (error);
552 goto retryselect;
553 }
554
555 /* drive ready ? */
556 stat = scsi_test_unit_rdy(ctlr, slave, unit);
557
558 if (stat == STS_CHECKCOND) {
559 stxsense(ctlr, slave, unit, sc);
560 switch (sc->sc_tapeid) {
561 case MT_ISEXABYTE:
562 if ((xsense->sc_xsense.key & XSK_NOTRDY) &&
563 xsense->exb_xsense.tnp)
564 uprintf("no cartridge\n");
565 else if (xsense->sc_xsense.key & XSK_NOTRDY)
566 uprintf("cartridge not loaded\n");
567 else if (xsense->sc_xsense.key & XSK_UNTATTEN) {
568 uprintf("new cart/power interrupt\n");
569 stat = 0;
570 } else if ((xsense->sc_xsense.key & XSK_UNTATTEN) &&
571 xsense->exb_xsense.tnp)
572 uprintf("cartridge unloading\n");
573 else
574 prtkey(UNIT(dev), sc);
575 break;
576 case MT_ISMFOUR:
577 case MT_ISAR:
578 if (xsense->sc_xsense.key & XSK_UNTATTEN)
579 stat = scsi_test_unit_rdy(ctlr, slave, unit);
580 if (stat == STS_CHECKCOND) {
581 stxsense(ctlr, slave, unit, sc);
582 if (xsense->sc_xsense.key)
583 prtkey(UNIT(dev), sc);
584 } else {
585 sc->sc_filepos = 0; /* new tape */
586 stat = 0;
587 }
588 break;
589 case MT_ISHPDAT:
590 case MT_ISVIPER1:
591 case MT_ISPYTHON:
592 if (xsense->sc_xsense.key & XSK_UNTATTEN)
593 stat = scsi_test_unit_rdy(ctlr, slave, unit);
594 if (stat == STS_CHECKCOND) {
595 stxsense(ctlr, slave, unit, sc);
596 if (xsense->sc_xsense.key)
597 prtkey(UNIT(dev), sc);
598 }
599 break;
600 default:
601 uprintf("st%d: not ready\n", UNIT(dev));
602 prtkey(UNIT(dev), sc);
603 break;
604 }
605 }
606 if (stat)
607 return(EIO);
608
609 /* mode sense */
610 modlen = sc->sc_datalen[CMD_MODE_SENSE];
611 modsense.cdb[4] = modlen;
612 stat = scsi_immed_command(ctlr, slave, unit, &modsense,
613 (u_char *)&mode, modlen, B_READ);
614 #ifdef DEBUG
615 if (st_debug & ST_OPENSTAT)
616 prtmodstat(&mode);
617 #endif
618
619 if (stat == STS_CHECKCOND) {
620 stxsense(ctlr, slave, unit, sc);
621 #ifdef DEBUG
622 if (st_debug & ST_OPEN)
623 dumpxsense(xsense);
624 #endif
625 }
626 if (stat)
627 return(EIO);
628
629 if ((flag & FWRITE) && mode.md.wp) {
630 uprintf("st:%d write protected\n", UNIT(dev));
631 return(EACCES);
632 }
633
634 /* save total number of blocks on tape */
635 sc->sc_numblks = mode.md.numblk2 << 16 |
636 mode.md.numblk1 << 8 |
637 mode.md.numblk0;
638
639 if (xsense->sc_xsense.eom && !(sc->sc_flags & STF_LEOT))
640 sc->sc_filepos = 0;
641 #ifdef DEBUG
642 if (st_debug & ST_FMKS)
643 printf("st%d: open filepos = %d\n", UNIT(dev), sc->sc_filepos);
644 #endif
645
646 sc->sc_flags |= (STF_OPEN);
647 if (flag & FWRITE)
648 sc->sc_flags |= STF_WMODE;
649 sc->sc_flags &= ~STF_MOVED;
650
651 #ifdef TTI
652 /* make stats available, also lit up TTi display */
653 sc->sc_tticntdwn = 100;
654 #endif
655 stxsense(ctlr, slave, unit, sc);
656
657 return(0);
658 }
659
660 /*ARGSUSED*/
stclose(dev,flag)661 stclose(dev, flag)
662 dev_t dev;
663 int flag;
664 {
665 register struct st_softc *sc = &st_softc[UNIT(dev)];
666 register int hit = 0;
667
668 if ((sc->sc_flags & (STF_WMODE|STF_WRTTN)) == (STF_WMODE|STF_WRTTN)) {
669 /*
670 * Cartridge tapes don't do double EOFs on EOT.
671 * We assume that variable-block devices use double EOF.
672 */
673 stcommand(dev, MTWEOF, 1);
674 if (sc->sc_blklen == 0) {
675 stcommand(dev, MTWEOF, 1);
676 stcommand(dev, MTBSR, 1);
677 }
678 hit++;
679 }
680 if ((minor(dev) & STDEV_NOREWIND) == 0) {
681 stcommand(dev, MTREW, 1);
682 hit++;
683 }
684 #ifdef NOTDEF
685 /* wait until more stable before trying [XXX Needed ?] */
686 if (!hit && (sc->sc_flags & SFT_WMODE))
687 /* force out any any bufferd write data */
688 stcommand(dev, MTFSR, 0);
689 #endif
690 /* make stats available */
691 stxsense(sc->sc_dq.dq_ctlr, sc->sc_dq.dq_slave, sc->sc_punit, sc);
692
693 sc->sc_flags &= ~(STF_OPEN|STF_WMODE|STF_WRTTN);
694 tprintf_close(sc->sc_ctty);
695 return(0); /* XXX */
696 }
697
698 void
ststrategy(bp)699 ststrategy(bp)
700 register struct buf *bp;
701 {
702 struct buf *dp;
703 int unit, s;
704
705 unit = UNIT(bp->b_dev);
706 dp = &sttab[unit];
707 bp->b_actf = NULL;
708 s = splbio();
709 bp->b_actb = dp->b_actb;
710 *dp->b_actb = bp;
711 dp->b_actb = &bp->b_actf;
712 if (dp->b_active == 0) {
713 dp->b_active = 1;
714 stustart(unit);
715 }
716 splx(s);
717 }
718
stustart(unit)719 stustart(unit)
720 int unit;
721 {
722 if (scsireq(&st_softc[unit].sc_dq))
723 ststart(unit);
724 }
725
ststart(unit)726 ststart(unit)
727 int unit;
728 {
729 struct hp_device *hp = st_softc[unit].sc_hd;
730
731 if (scsiustart(hp->hp_ctlr))
732 stgo(unit);
733 }
734
stgo(unit)735 stgo(unit)
736 int unit;
737 {
738 register struct st_softc *sc = &st_softc[unit];
739 register struct scsi_fmt_cdb *cmd;
740 register struct buf *bp = sttab[unit].b_actf;
741 struct hp_device *hp = sc->sc_hd;
742 int pad, stat;
743 long nblks;
744
745 if (sc->sc_flags & STF_CMD) {
746 cmd = &stcmd[unit];
747 pad = 0;
748 } else {
749 cmd = bp->b_flags & B_READ ? &st_read_cmd : &st_write_cmd;
750 if (sc->sc_blklen)
751 cmd->cdb[1] |= 0x01; /* fixed mode */
752 else
753 cmd->cdb[1] &= 0xfe;
754 if (bp->b_flags & B_READ)
755 sc->sc_flags &= ~STF_WRTTN;
756 else
757 sc->sc_flags |= STF_WRTTN;
758
759 if (sc->sc_blklen) { /* fixed mode */
760 nblks = bp->b_bcount / sc->sc_blklen;
761 if (bp->b_bcount % sc->sc_blklen) {
762 tprintf(sc->sc_ctty,
763 "st%d: I/O not block aligned %d/%ld\n",
764 unit, sc->sc_blklen, bp->b_bcount);
765 cmd->cdb[1] &= 0xfe; /* force error */
766 }
767 } else /* variable len */
768 nblks = bp->b_bcount;
769
770 *(u_char *)(&cmd->cdb[2]) = (u_char) (nblks >> 16);
771 *(u_char *)(&cmd->cdb[3]) = (u_char) (nblks >> 8);
772 *(u_char *)(&cmd->cdb[4]) = (u_char) nblks;
773 /*
774 * Always Zero. We are either writing in variable
775 * length mode we are writing in fixed block mode,
776 * or we are going to do odd length IO and are not
777 * going to use DMA.
778 */
779 pad = 0;
780 }
781
782 #ifdef DEBUG
783 if (st_debug & ST_GO)
784 printf("stgo: cmd len %d [0]0x%x [1]0x%x [2]0x%x [3]0x%x [4]0x%x [5]0x%x\n",
785 cmd->len, cmd->cdb[0], cmd->cdb[1], cmd->cdb[2],
786 cmd->cdb[3], cmd->cdb[4], cmd->cdb[5]);
787 #endif
788
789 sc->sc_flags |= STF_MOVED;
790 if (bp->b_bcount & 1) {
791 #ifdef DEBUG
792 if (st_debug & ST_ODDIO)
793 printf("stgo%d: odd count %d using manual transfer\n",
794 unit, bp->b_bcount);
795 #endif
796 stat = scsi_tt_oddio(hp->hp_ctlr, hp->hp_slave, sc->sc_punit,
797 bp->b_un.b_addr, bp->b_bcount,
798 bp->b_flags, 1);
799 if (stat == 0) {
800 bp->b_resid = 0;
801 stfinish(unit, sc, bp);
802 }
803 } else
804 stat = scsigo(hp->hp_ctlr, hp->hp_slave, sc->sc_punit,
805 bp, cmd, pad);
806 if (stat) {
807 bp->b_error = EIO;
808 bp->b_flags |= B_ERROR;
809 stxsense(sc->sc_dq.dq_ctlr, sc->sc_dq.dq_slave,
810 sc->sc_punit, sc);
811 sterror(unit, sc, stat);
812 stfinish(unit, sc, bp);
813 }
814 }
815
stfinish(unit,sc,bp)816 stfinish(unit, sc, bp)
817 int unit;
818 struct st_softc *sc;
819 struct buf *bp;
820 {
821 register struct buf *dp;
822
823 sttab[unit].b_errcnt = 0;
824 if (dp = bp->b_actf)
825 dp->b_actb = bp->b_actb;
826 else
827 sttab[unit].b_actb = bp->b_actb;
828 *bp->b_actb = dp;
829 iodone(bp);
830 scsifree(&sc->sc_dq);
831 if (sttab[unit].b_actf)
832 stustart(unit);
833 else
834 sttab[unit].b_active = 0;
835 }
836
stread(dev,uio)837 stread(dev, uio)
838 dev_t dev;
839 struct uio *uio;
840 {
841 int unit = UNIT(dev);
842
843 return(physio(ststrategy, &stbuf[unit], dev, B_READ, minphys, uio));
844 }
845
stwrite(dev,uio)846 stwrite(dev, uio)
847 dev_t dev;
848 struct uio *uio;
849 {
850 int unit = UNIT(dev);
851
852 return(physio(ststrategy, &stbuf[unit], dev, B_WRITE, minphys, uio));
853 }
854
855 /*ARGSUSED*/
stdump(dev)856 stdump(dev)
857 dev_t dev;
858 {
859 return(ENXIO);
860 }
861
862 /*ARGSUSED*/
stioctl(dev,cmd,data,flag)863 stioctl(dev, cmd, data, flag)
864 dev_t dev;
865 u_long cmd;
866 caddr_t data;
867 int flag;
868 {
869 register struct st_softc *sc = &st_softc[UNIT(dev)];
870 register int cnt;
871 register struct mtget *mtget;
872 register struct st_xsense *xp = &st_xsense[UNIT(dev)];
873 register struct mtop *op;
874 long resid;
875
876 switch (cmd) {
877
878 /* tape operation */
879 case MTIOCTOP:
880 op = (struct mtop *)data;
881 switch (op->mt_op) {
882
883 case MTBSR:
884 case MTFSR:
885 if (sc->sc_tapeid == MT_ISAR)
886 return(ENXIO);
887 case MTWEOF:
888 case MTFSF:
889 case MTBSF:
890 cnt = (int)op->mt_count;
891 break;
892
893 case MTREW:
894 case MTOFFL:
895 cnt = 1;
896 break;
897
898 case MTNOP:
899 return(0);
900 default:
901 return(EINVAL);
902 }
903 if (cnt <= 0)
904 return(EINVAL);
905 stcommand(dev, (u_int)op->mt_op, cnt);
906 break;
907
908 /* drive status */
909 case MTIOCGET:
910 mtget = (struct mtget *)data;
911 stxsense(sc->sc_dq.dq_ctlr, sc->sc_dq.dq_slave,
912 sc->sc_punit, sc);
913 mtget->mt_type = sc->sc_tapeid;
914 mtget->mt_dsreg = 0;
915 mtget->mt_erreg = ((xp->sc_xsense.valid << 15) |
916 (xp->sc_xsense.filemark << 14) |
917 (xp->sc_xsense.eom << 13) |
918 (xp->sc_xsense.ili << 12) |
919 (xp->sc_xsense.key << 8));
920
921 if (sc->sc_tapeid == MT_ISEXABYTE) {
922 mtget->mt_dsreg = sc->sc_flags;
923 resid = (xp->exb_xsense.tplft2 << 16 |
924 xp->exb_xsense.tplft1 << 8 |
925 xp->exb_xsense.tplft0);
926 mtget->mt_resid = resid / 1000;
927 if (sc->sc_numblks - resid)
928 mtget->mt_erreg |=
929 (((xp->exb_xsense.rwerrcnt2 << 16 |
930 xp->exb_xsense.rwerrcnt1 << 8 |
931 xp->exb_xsense.rwerrcnt0) * 100) /
932 (sc->sc_numblks - resid)) & 0xff;
933 } else if (xp->sc_xsense.valid) {
934 resid = ((xp->sc_xsense.info1 << 24) |
935 (xp->sc_xsense.info2 << 16) |
936 (xp->sc_xsense.info3 << 8) |
937 (xp->sc_xsense.info4));
938 if (sc->sc_blklen) /* if fixed mode */
939 resid *= sc->sc_blklen;
940 mtget->mt_resid = resid;
941 } else
942 mtget->mt_resid = 0;
943 break;
944
945 default:
946 return(ENXIO);
947 }
948 return(0);
949 }
950
stintr(unit,stat)951 stintr(unit, stat)
952 int unit, stat;
953 {
954 register struct st_softc *sc = &st_softc[unit];
955 register struct st_xsense *xp = &st_xsense[unit];
956 register struct buf *bp = sttab[unit].b_actf;
957 struct hp_device *hp = sc->sc_hd;
958
959 #ifdef DEBUG
960 if (bp == NULL) {
961 printf("st%d: bp == NULL\n", unit);
962 return;
963 }
964 #endif
965 switch (stat) {
966 /* scsi command completed ok */
967 case 0:
968 bp->b_resid = 0;
969 break;
970
971 /* more status */
972 case STS_CHECKCOND:
973 stxsense(sc->sc_dq.dq_ctlr, sc->sc_dq.dq_slave,
974 sc->sc_punit, sc);
975 if (xp->sc_xsense.valid) {
976 bp->b_resid = (u_long)((xp->sc_xsense.info1 << 24) |
977 (xp->sc_xsense.info2 << 16) |
978 (xp->sc_xsense.info3 << 8) |
979 (xp->sc_xsense.info4));
980 if (sc->sc_blklen) /* fixed mode */
981 bp->b_resid *= sc->sc_blklen;
982 }
983 if (xp->sc_xsense.filemark) {
984 sc->sc_filepos++;
985 break;
986 }
987 if (xp->sc_xsense.key != XSK_NOSENCE
988 && xp->sc_xsense.key != XSK_NOTUSED1
989 && xp->sc_xsense.key != XSK_NOTUSEDC
990 && xp->sc_xsense.key != XSK_NOTUSEDE) {
991 sterror(unit, sc, stat);
992 bp->b_flags |= B_ERROR;
993 bp->b_error = EIO;
994 break;
995 }
996 if (xp->sc_xsense.ili) {
997 /*
998 * Fixed length blocks, an error.
999 */
1000 if (sc->sc_blklen) {
1001 tprintf(sc->sc_ctty,
1002 "st%d: Incorrect Length Indicator, blkcnt diff %d\n",
1003 unit, sc->sc_blklen - bp->b_resid);
1004 bp->b_flags |= B_ERROR;
1005 bp->b_error = EIO;
1006 break;
1007 }
1008 /*
1009 * Variable length but read more than requested,
1010 * an error. (XXX ??? wrong for 9 track?)
1011 */
1012 if (bp->b_resid < 0) {
1013 bp->b_resid = 0;
1014 bp->b_flags |= B_ERROR;
1015 bp->b_error = ENOMEM;
1016 break;
1017 }
1018 /*
1019 * Variable length and odd, may require special
1020 * handling.
1021 */
1022 if (bp->b_resid & 1 && (sc->sc_tapeid != MT_ISAR)) {
1023 /*
1024 * Normal behavior, treat as an error.
1025 */
1026 if (!st_dmaoddretry) {
1027 tprintf(sc->sc_ctty,
1028 "st%d: Odd length read %d\n",
1029 UNIT(bp->b_dev),
1030 bp->b_bcount - bp->b_resid);
1031 bp->b_error = EIO;
1032 bp->b_flags |= B_ERROR;
1033 break;
1034 }
1035 /*
1036 * Attempt to back up and re-read using oddio.
1037 */
1038 #ifdef DEBUG
1039 if (st_debug & ST_ODDIO)
1040 printf("st%d: stintr odd count %d, do BSR then oddio\n",
1041 UNIT(bp->b_dev),
1042 bp->b_bcount - bp->b_resid);
1043 #endif
1044 stat = scsi_tt_oddio(hp->hp_ctlr, hp->hp_slave,
1045 sc->sc_punit, 0, -1, 0, 0);
1046 if (stat == 0)
1047 stat = scsi_tt_oddio(hp->hp_ctlr,
1048 hp->hp_slave,
1049 sc->sc_punit,
1050 bp->b_un.b_addr,
1051 bp->b_bcount - bp->b_resid,
1052 bp->b_flags, 0);
1053 if (stat) {
1054 bp->b_error = EIO;
1055 bp->b_flags |= B_ERROR;
1056 stxsense(sc->sc_dq.dq_ctlr, sc->sc_dq.dq_slave,
1057 sc->sc_punit, sc);
1058 sterror(unit, sc, stat);
1059 }
1060 }
1061 break;
1062 }
1063 if (xp->sc_xsense.eom) {
1064 bp->b_flags |= B_ERROR;
1065 bp->b_error = ENOSPC;
1066 break;
1067 }
1068 tprintf(sc->sc_ctty, "st%d: unknown scsi error\n", unit);
1069 bp->b_flags |= B_ERROR;
1070 bp->b_error = EIO;
1071 break;
1072
1073 default:
1074 printf("st%d: stintr unknown stat 0x%x\n", unit, stat);
1075 break;
1076 }
1077 #ifdef DEBUG
1078 if ((st_debug & ST_BRESID) && bp->b_resid != 0)
1079 printf("b_resid %d b_flags 0x%x b_error 0x%x\n",
1080 bp->b_resid, bp->b_flags, bp->b_error);
1081 #endif
1082 /* asked for more filemarks then on tape */
1083 if (bp->b_resid != 0 &&
1084 (sc->sc_flags & STF_CMD) && sc->sc_cmd == CMD_SPACE) {
1085 sc->sc_filepos -= bp->b_resid;
1086 if (sc->sc_filepos < 0)
1087 sc->sc_filepos = 0;
1088 }
1089
1090 #ifdef TTI
1091 if (st_extti & (1<<unit) &&
1092 sc->sc_type == MT_ISEXABYTE) /* to make display lit up */
1093 /*
1094 * XXX severe performance penality for this.
1095 * Try and throttle by not calling stxsense on every intr.
1096 * Mostly for TTi we, get a stxsense call in open and close.
1097 */
1098 if (sc->sc_tticntdwn-- == 0) {
1099 stxsense(sc->sc_dq.dq_ctlr, sc->sc_dq.dq_slave,
1100 sc->sc_punit, sc);
1101 sc->sc_tticntdwn = 100;
1102 }
1103 #endif
1104
1105 stfinish(unit, sc, bp);
1106 }
1107
stcommand(dev,command,cnt)1108 stcommand(dev, command, cnt)
1109 dev_t dev;
1110 u_int command;
1111 int cnt;
1112 {
1113 register struct st_softc *sc = &st_softc[UNIT(dev)];
1114 register struct buf *bp = &stbuf[UNIT(dev)];
1115 register struct scsi_fmt_cdb *cmd = &stcmd[UNIT(dev)];
1116 register cmdcnt;
1117 int s;
1118
1119 cmd->len = 6; /* all tape commands are cdb6 */
1120 cmd->cdb[1] = sc->sc_punit;
1121 cmd->cdb[2] = cmd->cdb[3] = cmd->cdb[4] = cmd->cdb[5] = 0;
1122 cmdcnt = 0;
1123
1124 /*
1125 * XXX Assumption is that everything except Archive can take
1126 * repeat count in cdb block.
1127 */
1128 switch (command) {
1129 case MTWEOF:
1130 cmd->cdb[0] = CMD_WRITE_FILEMARK;
1131 if (sc->sc_tapeid != MT_ISAR) {
1132 cmdcnt = cnt;
1133 cnt = 1;
1134 } else
1135 cmdcnt = 1;
1136 *(u_char *)(&cmd->cdb[2]) = (u_char) (cmdcnt >> 16);
1137 *(u_char *)(&cmd->cdb[3]) = (u_char) (cmdcnt >> 8);
1138 *(u_char *)(&cmd->cdb[4]) = (u_char) cmdcnt;
1139
1140 if (sc->sc_tapeid == MT_ISEXABYTE &&
1141 (minor(dev) & STDEV_EXSFMK)) /* short filemarks */
1142 cmd->cdb[5] |= 0x80;
1143 else
1144 cmd->cdb[5] &= 0x7f;
1145 break;
1146 case MTBSF:
1147 /* Archive can't back up, will not get to BSR case */
1148 if (sc->sc_tapeid == MT_ISAR) {
1149 if ((sc->sc_filepos - cnt) < 0) {
1150 stcommand(dev, MTREW, 1);
1151 return;
1152 }
1153 cmdcnt = sc->sc_filepos - cnt + 1;
1154 stcommand(dev, MTREW, 1);
1155 stcommand(dev, MTFSF, cmdcnt);
1156 return;
1157 }
1158 case MTBSR:
1159 case MTFSR:
1160 case MTFSF:
1161 if (command == MTBSF || command == MTBSR)
1162 cnt = cnt * (-1); /* backward move */
1163 if (command == MTFSF || command == MTBSF)
1164 cmd->cdb[1] |= 0x01; /* filemarks */
1165 else
1166 cmd->cdb[1] |= 0x00; /* logical blocks */
1167 if (sc->sc_tapeid != MT_ISAR) {
1168 cmdcnt = cnt;
1169 cnt = 1;
1170 } else
1171 cmdcnt = 1;
1172 *(u_char *)(&cmd->cdb[2]) = (u_char) (cmdcnt >> 16);
1173 *(u_char *)(&cmd->cdb[3]) = (u_char) (cmdcnt >> 8);
1174 *(u_char *)(&cmd->cdb[4]) = (u_char) cmdcnt;
1175 cmd->cdb[0] = CMD_SPACE;
1176 break;
1177 case MTREW:
1178 cmd->cdb[0] = CMD_REWIND;
1179 sc->sc_filepos = 0;
1180 break;
1181 case MTOFFL:
1182 cmd->cdb[0] = CMD_LOADUNLOAD;
1183 sc->sc_filepos = 0;
1184 break;
1185 default:
1186 printf("st%d: stcommand bad command 0x%x\n",
1187 UNIT(dev), command);
1188 }
1189
1190 sc->sc_flags |= STF_CMD;
1191 sc->sc_cmd = cmd->cdb[0];
1192
1193 sc->sc_bp = bp;
1194 again:
1195 #ifdef DEBUG
1196 if (st_debug & ST_FMKS)
1197 printf("st%d: stcommand filepos %d cmdcnt %d cnt %d\n",
1198 UNIT(dev), sc->sc_filepos, cmdcnt, cnt);
1199 #endif
1200 s = splbio();
1201 while (bp->b_flags & B_BUSY) {
1202 if (bp->b_flags & B_DONE)
1203 break;
1204 bp->b_flags |= B_WANTED;
1205 sleep((caddr_t)bp, PRIBIO);
1206 }
1207 bp->b_flags = B_BUSY|B_READ;
1208 splx(s);
1209 bp->b_dev = dev;
1210 bp->b_bcount = 0;
1211 bp->b_resid = 0;
1212 bp->b_blkno = 0;
1213 bp->b_error = 0;
1214 ststrategy(bp);
1215 iowait(bp);
1216 if (bp->b_flags & B_WANTED)
1217 wakeup((caddr_t)bp);
1218 bp->b_flags &= B_ERROR;
1219
1220 if (command == MTWEOF || command == MTFSF || command == MTBSF)
1221 sc->sc_filepos += cmdcnt;
1222
1223 if (--cnt > 0)
1224 goto again;
1225
1226 sc->sc_flags |= STF_MOVED;
1227 sc->sc_flags &= ~(STF_CMD|STF_WRTTN);
1228 }
1229
sterror(unit,sc,stat)1230 sterror(unit, sc, stat)
1231 int unit, stat;
1232 struct st_softc *sc;
1233 {
1234 /* stxsense must have been called before sterror() */
1235 if (stat & STS_CHECKCOND)
1236 prtkey(unit, sc);
1237 else if (stat)
1238 tprintf(sc->sc_ctty,
1239 "st%d: bad scsi status 0x%x\n", unit, stat);
1240
1241 if ((sc->sc_flags & STF_CMD) && sc->sc_cmd == CMD_SPACE) /* fsf */
1242 sc->sc_filepos--;
1243 }
1244
stxsense(ctlr,slave,unit,sc)1245 stxsense(ctlr, slave, unit, sc)
1246 int ctlr, slave, unit;
1247 struct st_softc *sc;
1248 {
1249 u_char *sensebuf;
1250 unsigned len;
1251
1252 sensebuf = (u_char *)&st_xsense[sc->sc_dq.dq_unit];
1253 len = sc->sc_datalen[CMD_REQUEST_SENSE];
1254 scsi_request_sense(ctlr, slave, unit, sensebuf, len);
1255 }
1256
prtkey(unit,sc)1257 prtkey(unit, sc)
1258 int unit;
1259 struct st_softc *sc;
1260 {
1261 register struct st_xsense *xp = &st_xsense[unit];
1262
1263 switch (xp->sc_xsense.key) {
1264 case XSK_NOSENCE:
1265 break;
1266 case XSK_NOTUSED1:
1267 case XSK_NOTUSEDC:
1268 case XSK_NOTUSEDE:
1269 break;
1270 case XSK_REVERVED:
1271 tprintf(sc->sc_ctty, "st%d: Reserved sense key 0x%x\n",
1272 unit, xp->sc_xsense.key);
1273 break;
1274 case XSK_NOTRDY:
1275 tprintf(sc->sc_ctty, "st%d: NOT READY\n", unit);
1276 break;
1277 case XSK_MEDERR:
1278 tprintf(sc->sc_ctty, "st%d: MEDIUM ERROR\n", unit);
1279 break;
1280 case XSK_HRDWERR:
1281 tprintf(sc->sc_ctty, "st%d: HARDWARE ERROR\n", unit);
1282 break;
1283 case XSK_ILLREQ:
1284 tprintf(sc->sc_ctty, "st%d: ILLEGAL REQUEST\n", unit);
1285 break;
1286 case XSK_UNTATTEN:
1287 tprintf(sc->sc_ctty, "st%d: UNIT ATTENTION\n", unit);
1288 break;
1289 case XSK_DATAPROT:
1290 tprintf(sc->sc_ctty, "st%d: DATA PROTECT\n", unit);
1291 break;
1292 case XSK_BLNKCHK:
1293 tprintf(sc->sc_ctty, "st%d: BLANK CHECK\n", unit);
1294 break;
1295 case XSK_VENDOR:
1296 tprintf(sc->sc_ctty, "st%d: VENDER UNIQUE SENSE KEY ", unit);
1297 switch (sc->sc_tapeid) {
1298 case MT_ISEXABYTE:
1299 tprintf(sc->sc_ctty, "Exabyte: ");
1300 if (xp->exb_xsense.xfr)
1301 tprintf(sc->sc_ctty,
1302 "Transfer Abort Error\n");
1303 if (xp->exb_xsense.tmd)
1304 tprintf(sc->sc_ctty,
1305 "Tape Mark Detect Error\n");
1306 break;
1307 default:
1308 tprintf(sc->sc_ctty, "\n");
1309 }
1310 break;
1311 case XSK_CPYABORT:
1312 tprintf(sc->sc_ctty, "st%d: COPY ABORTED\n", unit);
1313 break;
1314 case XSK_ABORTCMD:
1315 tprintf(sc->sc_ctty, "st%d: ABORTED COMMAND\n", unit);
1316 break;
1317 case XSK_VOLOVER:
1318 tprintf(sc->sc_ctty, "st%d: VOLUME OVERFLOW\n", unit);
1319 break;
1320 default:
1321 tprintf(sc->sc_ctty, "st%d: unknown sense key 0x%x\n",
1322 unit, xp->sc_xsense.key);
1323 }
1324 if (sc->sc_tapeid == MT_ISEXABYTE) {
1325 if (xp->exb_xsense.bpe)
1326 tprintf(sc->sc_ctty, "st%d: Bus Parity Errorn", unit);
1327 if (xp->exb_xsense.fpe)
1328 tprintf(sc->sc_ctty,
1329 "st%d: Formatted Buffer Parity Errorn", unit);
1330 if (xp->exb_xsense.eco)
1331 tprintf(sc->sc_ctty, "st%d: Error Counter Overflown",
1332 unit);
1333 if (xp->exb_xsense.tme)
1334 tprintf(sc->sc_ctty, "st%d: Tape Motion Errorn", unit);
1335 if (xp->exb_xsense.xfr)
1336 tprintf(sc->sc_ctty, "st%d: Transfer About Errorn",
1337 unit);
1338 if (xp->exb_xsense.tmd)
1339 tprintf(sc->sc_ctty, "st%d: Tape Mark Detect Errorn",
1340 unit);
1341 if (xp->exb_xsense.fmke)
1342 tprintf(sc->sc_ctty, "st%d: Filemark Errorn", unit);
1343 if (xp->exb_xsense.ure)
1344 tprintf(sc->sc_ctty, "st%d: Under Run Errorn", unit);
1345 if (xp->exb_xsense.sse)
1346 tprintf(sc->sc_ctty, "st%d: Servo System Errorn",
1347 unit);
1348 if (xp->exb_xsense.fe)
1349 tprintf(sc->sc_ctty, "st%d: Formatter Errorn", unit);
1350 if (xp->exb_xsense.wseb)
1351 tprintf(sc->sc_ctty, "st%d: WSEB Errorn", unit);
1352 if (xp->exb_xsense.wseo)
1353 tprintf(sc->sc_ctty, "st%d: WSEO Errorn", unit);
1354 }
1355 }
1356
1357 #ifdef DEBUG
1358
1359 dumpxsense(sensebuf)
1360 struct st_xsense *sensebuf;
1361 {
1362 struct st_xsense *xp = sensebuf;
1363
1364 printf("valid 0x%x errorclass 0x%x errorcode 0x%x\n",
1365 xp->sc_xsense.valid,
1366 xp->sc_xsense.class, xp->sc_xsense.code);
1367 printf("seg number 0x%x\n", xp->sc_xsense.segment);
1368 printf("FMK 0x%x EOM 0x%x ILI 0x%x RSVD 0x%x sensekey 0x%x\n",
1369 xp->sc_xsense.filemark, xp->sc_xsense.eom, xp->sc_xsense.ili,
1370 xp->sc_xsense.rsvd, xp->sc_xsense.key);
1371 printf("info 0x%lx\n",
1372 (u_long)((xp->sc_xsense.info1<<24)|(xp->sc_xsense.info2<<16)|
1373 (xp->sc_xsense.info3<<8)|(xp->sc_xsense.info4)) );
1374 printf("ASenseL 0x%x\n", xp->sc_xsense.len);
1375
1376 if (xp->sc_xsense.len != 0x12) /* MT_ISEXB Exabyte only ?? */
1377 return; /* What about others */
1378
1379 printf("ASenseC 0x%x\n", xp->exb_xsense.addsens);
1380 printf("AsenseQ 0x%x\n", xp->exb_xsense.addsensq);
1381 printf("R/W Errors 0x%lx\n",
1382 (u_long)((xp->exb_xsense.rwerrcnt2<<16)|
1383 (xp->exb_xsense.rwerrcnt1<<8)|
1384 (xp->exb_xsense.rwerrcnt1)) );
1385 printf("PF 0x%x BPE 0x%x FPE 0x%x ME 0x%x ECO 0x%x TME 0x%x TNP 0x%x BOT 0x%x\n",
1386 xp->exb_xsense.pf, xp->exb_xsense.bpe, xp->exb_xsense.fpe,
1387 xp->exb_xsense.me, xp->exb_xsense.eco, xp->exb_xsense.tme,
1388 xp->exb_xsense.tnp, xp->exb_xsense.bot);
1389 printf("XFR 0x%x TMD 0x%x WP 0x%x FMKE 0x%x URE 0x%x WE1 0x%x SSE 0x%x FE 0x%x\n",
1390 xp->exb_xsense.xfr, xp->exb_xsense.tmd, xp->exb_xsense.wp,
1391 xp->exb_xsense.fmke, xp->exb_xsense.ure, xp->exb_xsense.we1,
1392 xp->exb_xsense.sse, xp->exb_xsense.fe);
1393 printf("WSEB 0x%x WSEO 0x%x\n",
1394 xp->exb_xsense.wseb, xp->exb_xsense.wseo);
1395 printf("Remaining Tape 0x%lx\n",
1396 (u_long)((xp->exb_xsense.tplft2<<16)|
1397 (xp->exb_xsense.tplft1<<8)|
1398 (xp->exb_xsense.tplft0)) );
1399 }
1400
1401 prtmodsel(msd, modlen)
1402 struct mode_select_data *msd;
1403 int modlen;
1404 {
1405 printf("Modsel command. len is 0x%x.\n", modlen);
1406 printf("rsvd1 0x%x rsvd2 0x%x rsvd3 0x%x bufferd 0x%x speed 0x%x bckdeslen 0x%x\n",
1407 msd->rsvd1,msd->rsvd2,msd->rsvd3,msd->buff,msd->speed,msd->blkdeslen);
1408 printf("density 0x%x blks2 0x%x blks1 0x%x blks0 0x%x rsvd 0x%x blklen2 0x%x blklen1 0x%x blklen0 0x%x\n",
1409 msd->density,msd->blks2,msd->blks1,msd->blks0,msd->rsvd4,msd->blklen2,msd->blklen1,msd->blklen0);
1410 printf("vupb 0x%x rsvd 0x%x p5 0x%x motionthres 0x%x reconthres 0x%x gapthres 0x%x \n",
1411 msd->vupb,msd->rsvd5,msd->p5,msd->motionthres,msd->reconthres,msd->gapthres);
1412 }
1413
1414 prtmodstat(mode)
1415 struct mode_sense *mode;
1416 {
1417 printf("Mode Status\n");
1418 printf("sdl 0x%x medtype 0x%x wp 0x%x bfmd 0x%x speed 0x%x bdl 0x%x\n",
1419 mode->md.sdl, mode->md.medtype, mode->md.wp, mode->md.bfmd,
1420 mode->md.speed, mode->md.bdl);
1421 printf("dencod 0x%x numblk 0x%x blklen 0x%x\n",
1422 mode->md.dencod,
1423 (mode->md.numblk2<<16)|(mode->md.numblk1<<8)|(mode->md.numblk0),
1424 (mode->md.blklen2<<16)|(mode->md.blklen1<<8)|(mode->md.blklen0) );
1425 printf("ct 0x%x nd 0x%x nbe 0x%x edb 0x%x pe 0x%x nal 0x%x p5 0x%x\n",
1426 mode->ex.ct, mode->ex.nd, mode->ex.nbe,
1427 mode->ex.ebd, mode->ex.pe, mode->ex.nal, mode->ex.p5);
1428 printf("motionthres 0x%x reconthres 0x%x gapthres 0x%x\n",
1429 mode->ex.motionthres, mode->ex.reconthres, mode->ex.gapthres);
1430 }
1431 #endif /* DEBUG */
1432
1433 #endif
1434