1 /*-
2 * Copyright (c) 1982, 1986 The Regents of the University of California.
3 * All rights reserved.
4 *
5 * %sccs.include.proprietary.c%
6 *
7 * @(#)mt.c 7.11 (Berkeley) 09/23/93
8 */
9
10 #include "mu.h"
11 #if NMT > 0
12 /*
13 * TM78/TU78 tape driver
14 *
15 * Original author - ?
16 * Most error recovery bug fixes - ggs (ulysses!ggs)
17 * `read reverse' error recovery - ggs (ulysses!ggs)
18 *
19 * OPTIONS:
20 * MTLERRM - Long error message text - twd, Brown University
21 *
22 * TODO:
23 * Add odd byte count kludge from VMS driver (?)
24 * Write dump routine
25 */
26
27 #include "sys/param.h"
28 #include "sys/systm.h"
29 #include "sys/buf.h"
30 #include "sys/conf.h"
31 #include "sys/file.h"
32 #include "sys/user.h"
33 #include "sys/proc.h"
34 #include "sys/map.h"
35 #include "sys/ioctl.h"
36 #include "sys/mtio.h"
37 #include "sys/cmap.h"
38 #include "sys/tty.h"
39 #include "sys/syslog.h"
40
41 #include "../include/pte.h"
42 #include "../include/cpu.h"
43 #include "mbareg.h"
44 #include "mbavar.h"
45 #include "mtreg.h"
46
47 #define MTTIMEOUT 10000 /* loop limit for controller test */
48 #define INF 1000000L /* a block number that won't exist */
49 #define MASKREG(r) ((r) & 0xffff) /* the control registers have 16 bits */
50
51 /* Bits for sc_flags */
52
53 #define H_WRITTEN 01 /* last operation was a write */
54 #define H_EOT 02 /* end of tape encountered */
55 #define H_IEOT 04 /* ignore EOT condition */
56
57 int mt_do_readrev = 1;
58
59 /* Per unit status information */
60
61 struct mu_softc {
62 char sc_openf; /* unit is open if != 0 */
63 char sc_flags; /* state flags */
64 daddr_t sc_blkno; /* current physical block number */
65 daddr_t sc_nxrec; /* firewall input block number */
66 u_short sc_erreg; /* copy of mter or mtner */
67 u_short sc_dsreg; /* copy of mtds */
68 short sc_resid; /* residual function count for ioctl */
69 short sc_dens; /* density code - MT_GCR or zero */
70 int sc_i_mtas; /* mtas at slave attach time */
71 int sc_i_mtner; /* mtner at slave attach time */
72 int sc_i_mtds; /* mtds at slave attach time */
73 caddr_t sc_ctty; /* record user's tty for errors */
74 int sc_blks; /* number of I/O operations since open */
75 int sc_softerrs; /* number of soft I/O errors since open */
76 } mu_softc[NMU];
77
78 struct buf cmtbuf[NMT]; /* tape command buffer structures */
79
80 struct mba_device *mtinfo[NMT]; /* unit to ctlr structures */
81 struct mba_slave *muinfo[NMU]; /* unit to slave structures */
82
83 char mtds_bits[] = MTDS_BITS; /* mtds bit names for error messages */
84 short mttypes[] = { MBDT_TU78, 0 };
85
86 int mtattach(), mtslave(), mtustart(), mtstart(), mtndtint(), mtdtint();
87 struct mba_driver mtdriver =
88 { mtattach, mtslave, mtustart, mtstart, mtdtint, mtndtint,
89 mttypes, "mt", "mu", mtinfo };
90
91 /* Bits in minor device */
92 #define MUUNIT(dev) (minor(dev)&03)
93 #define H_NOREWIND 04
94 #define H_6250BPI 010
95
96 #define MTUNIT(dev) (muinfo[MUUNIT(dev)]->ms_ctlr)
97
98 void mtcreset();
99
100 /*ARGSUSED*/
101 mtattach(mi)
102 struct mba_device *mi;
103 {
104
105 /* void */
106 }
107
108 mtslave(mi, ms, sn)
109 struct mba_device *mi;
110 struct mba_slave *ms;
111 int sn;
112 {
113 register struct mu_softc *sc = &mu_softc[ms->ms_unit];
114 register struct mtdevice *mtaddr = (struct mtdevice *)mi->mi_drv;
115 int s = spl5(), rtn = 0, i;
116
117 /*
118 * Just in case the controller is ill, reset it. Then issue
119 * a sense operation and wait about a second for it to respond.
120 */
121 mtcreset(mtaddr);
122 mtaddr->mtas = -1;
123 mtaddr->mtncs[sn] = MT_SENSE|MT_GO;
124 for (i = MTTIMEOUT; i > 0; i--) {
125 DELAY(50);
126 if (MASKREG(mtaddr->mtas) != 0)
127 break;
128 }
129 sc->sc_i_mtas = mtaddr->mtas;
130 sc->sc_i_mtner = mtaddr->mtner;
131 sc->sc_i_mtds = mtaddr->mtds;
132
133 /*
134 * If no response, whimper. If wrong response, call it an
135 * unsolicited interrupt and use mtndtint to log and correct.
136 * Otherwise, note whether this slave exists.
137 */
138 if (i <= 0)
139 printf("mt: controller hung\n");
140 else if ((mtaddr->mtner & MTER_INTCODE) != MTER_DONE)
141 (void) mtndtint(mi);
142 else if (mtaddr->mtds & MTDS_PRES) {
143 muinfo[ms->ms_unit] = ms;
144 rtn = 1;
145 }
146
147 /* cancel the interrupt, then wait a little while for it to go away */
148 mtaddr->mtas = mtaddr->mtas;
149 DELAY(10);
150 splx(s);
151 return (rtn);
152 }
153
mtopen(dev,flag)154 mtopen(dev, flag)
155 dev_t dev;
156 int flag;
157 {
158 register int muunit;
159 register struct mu_softc *sc;
160 register struct mba_slave *ms;
161
162 muunit = MUUNIT(dev);
163 if (muunit >= NMU || (ms = muinfo[muunit]) == NULL ||
164 ms->ms_alive == 0 || mtinfo[ms->ms_ctlr]->mi_alive == 0)
165 return (ENXIO);
166 if ((sc = &mu_softc[muunit])->sc_openf)
167 return (EBUSY);
168 sc->sc_openf = 1;
169 sc->sc_dens = (minor(dev) & H_6250BPI) ? MT_GCR : 0;
170 mtcommand(dev, MT_SENSE, 1);
171 if ((sc->sc_dsreg & MTDS_ONL) == 0) {
172 uprintf("mu%d: not online\n", muunit);
173 sc->sc_openf = 0;
174 return (EIO);
175 }
176 if ((sc->sc_dsreg & MTDS_AVAIL) == 0) {
177 uprintf("mu%d: not online (port selector)\n", muunit);
178 sc->sc_openf = 0;
179 return (EIO);
180 }
181 if ((flag & FWRITE) && (sc->sc_dsreg & MTDS_FPT)) {
182 uprintf("mu%d: no write ring\n", muunit);
183 sc->sc_openf = 0;
184 return (EIO);
185 }
186 if ((sc->sc_dsreg & MTDS_BOT) == 0 && (flag & FWRITE) &&
187 (sc->sc_dens == MT_GCR) != ((sc->sc_dsreg & MTDS_PE) == 0)) {
188 uprintf("mu%d: can't change density in mid-tape\n", muunit);
189 sc->sc_openf = 0;
190 return (EIO);
191 }
192 sc->sc_blkno = (daddr_t)0;
193
194 /*
195 * Since cooked I/O may do a read-ahead before a write, trash
196 * on a tape can make the first write fail. Suppress the first
197 * read-ahead unless definitely doing read-write.
198 */
199 sc->sc_nxrec = ((flag & (FTRUNC | FWRITE)) == (FTRUNC | FWRITE)) ?
200 (daddr_t)0 : (daddr_t)INF;
201 sc->sc_flags = 0;
202 sc->sc_blks = 0;
203 sc->sc_softerrs = 0;
204 sc->sc_ctty = (caddr_t)(u.u_procp->p_flag & P_CONTROLT ?
205 u.u_procp->p_session->s_ttyp : 0);
206 return (0);
207 }
208
mtclose(dev,flag)209 mtclose(dev, flag)
210 register dev_t dev;
211 register int flag;
212 {
213 register struct mu_softc *sc = &mu_softc[MUUNIT(dev)];
214
215 if ((flag & (FREAD | FWRITE)) == FWRITE ||
216 ((flag & FWRITE) && (sc->sc_flags & H_WRITTEN)))
217 mtcommand(dev, MT_CLS|sc->sc_dens, 1);
218 if ((minor(dev) & H_NOREWIND) == 0)
219 mtcommand(dev, MT_REW, 0);
220 if (sc->sc_blks > 100 && sc->sc_softerrs > sc->sc_blks / 100)
221 log(LOG_INFO, "mu%d: %d soft errors in %d blocks\n",
222 MUUNIT(dev), sc->sc_softerrs, sc->sc_blks);
223 sc->sc_openf = 0;
224 return (0);
225 }
226
mtcommand(dev,com,count)227 mtcommand(dev, com, count)
228 dev_t dev;
229 int com, count;
230 {
231 register struct buf *bp;
232 int s;
233
234 bp = &cmtbuf[MTUNIT(dev)];
235 s = spl5();
236 while (bp->b_flags & B_BUSY) {
237 if (bp->b_repcnt == 0 && (bp->b_flags & B_DONE))
238 break;
239 bp->b_flags |= B_WANTED;
240 sleep((caddr_t)bp, PRIBIO);
241 }
242 bp->b_flags = B_BUSY|B_READ;
243 splx(s);
244 bp->b_dev = dev;
245 bp->b_command = com;
246 bp->b_repcnt = count;
247 bp->b_blkno = 0;
248 bp->b_error = 0;
249 mtstrategy(bp);
250 if (count == 0)
251 return;
252 biowait(bp);
253 if (bp->b_flags & B_WANTED)
254 wakeup((caddr_t)bp);
255 bp->b_flags &= B_ERROR;
256 }
257
mtstrategy(bp)258 mtstrategy(bp)
259 register struct buf *bp;
260 {
261 register struct buf *dp;
262 struct mba_device *mi = mtinfo[MTUNIT(bp->b_dev)];
263 int s;
264
265 /*
266 * If this is a data transfer operation, set the resid to a
267 * default value (EOF) to simplify getting it right during
268 * error recovery or bail out.
269 */
270 if (bp != &cmtbuf[MTUNIT(bp->b_dev)])
271 bp->b_resid = bp->b_bcount;
272
273 /*
274 * Link this request onto the end of the queue for this
275 * controller, then start I/O if not already active.
276 */
277 bp->av_forw = NULL;
278 dp = &mi->mi_tab;
279 s = spl5();
280 if (dp->b_actf == NULL)
281 dp->b_actf = bp;
282 else
283 dp->b_actl->av_forw = bp;
284 dp->b_actl = bp;
285 if (dp->b_active == 0)
286 mbustart(mi);
287 splx(s);
288 }
289
mtustart(mi)290 mtustart(mi)
291 register struct mba_device *mi;
292 {
293 register struct mtdevice *mtaddr = (struct mtdevice *)mi->mi_drv;
294 register struct buf *bp = mi->mi_tab.b_actf;
295 register struct mu_softc *sc = &mu_softc[MUUNIT(bp->b_dev)];
296 daddr_t blkno;
297 int count;
298
299 if (sc->sc_openf < 0) {
300 bp->b_flags |= B_ERROR;
301 return (MBU_NEXT);
302 }
303 if (bp != &cmtbuf[MTUNIT(bp->b_dev)]) {
304 /*
305 * Data transfer. If write at end of tape,
306 * signal "no space" unless suppressed
307 * by MTIOCIEOT.
308 */
309 if ((sc->sc_flags & (H_EOT | H_IEOT)) == H_EOT &&
310 (bp->b_flags & B_READ) == 0) {
311 bp->b_flags |= B_ERROR;
312 bp->b_error = ENOSPC;
313 return (MBU_NEXT);
314 }
315
316 if (bp->b_flags & B_RAW) {
317 /* raw transfer; never seek */
318 sc->sc_blkno = bdbtofsb(bp->b_blkno);
319 sc->sc_nxrec = sc->sc_blkno + 1;
320 } else {
321 /* seek beyond end of file */
322 if (bdbtofsb(bp->b_blkno) > sc->sc_nxrec) {
323 bp->b_flags |= B_ERROR;
324 bp->b_error = ENXIO;
325 return (MBU_NEXT);
326 }
327
328 /*
329 * This should be end of file, but the buffer
330 * system wants a one-block look-ahead. Humor it.
331 */
332 if (bdbtofsb(bp->b_blkno) == sc->sc_nxrec &&
333 bp->b_flags & B_READ) {
334 bp->b_resid = bp->b_bcount;
335 clrbuf(bp);
336 return (MBU_NEXT);
337 }
338
339 /* If writing, mark the next block invalid. */
340 if ((bp->b_flags & B_READ) == 0)
341 sc->sc_nxrec = bdbtofsb(bp->b_blkno) + 1;
342 }
343 } else {
344 /* It's a command, do it now. */
345 mtaddr->mtncs[MUUNIT(bp->b_dev)] =
346 (bp->b_repcnt<<8)|bp->b_command|MT_GO;
347 return (MBU_STARTED);
348 }
349
350 /*
351 * If raw I/O, or if the tape is positioned correctly for
352 * cooked I/O, set the byte count, unit number and repeat count
353 * then tell the MASSBUS to proceed. Note that a negative
354 * bcount tells mbstart to map the buffer for "read backwards".
355 */
356 if ((blkno = sc->sc_blkno) == bdbtofsb(bp->b_blkno)) {
357 if (mi->mi_tab.b_errcnt == 2) {
358 mtaddr->mtbc = -bp->b_bcount;
359 mtaddr->mtca = MUUNIT(bp->b_dev);
360 } else {
361 mtaddr->mtbc = bp->b_bcount;
362 mtaddr->mtca = (1<<2)|MUUNIT(bp->b_dev);
363 }
364 return (MBU_DODATA);
365 }
366
367 /* Issue skip operations to position the next block for cooked I/O. */
368
369 if (blkno < bdbtofsb(bp->b_blkno))
370 count = bdbtofsb(bp->b_blkno) - blkno;
371 else
372 count = blkno - bdbtofsb(bp->b_blkno);
373 if ((unsigned)count > 0377)
374 count = 0377;
375 mtaddr->mtncs[MUUNIT(bp->b_dev)] = count | MT_SFORW|MT_GO;
376 return (MBU_STARTED);
377 }
378
mtstart(mi)379 mtstart(mi)
380 register struct mba_device *mi;
381 {
382 register struct buf *bp = mi->mi_tab.b_actf;
383 register struct mu_softc *sc = &mu_softc[MUUNIT(bp->b_dev)];
384
385 if (bp->b_flags & B_READ)
386 if (mi->mi_tab.b_errcnt == 2)
387 return (MT_READREV|MT_GO);
388 else
389 return (MT_READ|MT_GO);
390 else
391 return (MT_WRITE|sc->sc_dens|MT_GO);
392 }
393
mtdtint(mi,mbsr)394 mtdtint(mi, mbsr)
395 register struct mba_device *mi;
396 int mbsr;
397 {
398 register struct mtdevice *mtaddr = (struct mtdevice *)mi->mi_drv;
399 register struct buf *bp = mi->mi_tab.b_actf;
400 register struct mu_softc *sc;
401 register int er;
402
403 /* I'M still NOT SURE IF THIS SHOULD ALWAYS BE THE CASE SO FOR NOW... */
404 if ((mtaddr->mtca & 3) != MUUNIT(bp->b_dev)) {
405 printf("mt: wrong unit!\n");
406 mtaddr->mtca = MUUNIT(bp->b_dev);
407 }
408
409 er = MASKREG(mtaddr->mter);
410 sc = &mu_softc[MUUNIT(bp->b_dev)];
411 sc->sc_erreg = er;
412 if (bp->b_flags & B_READ)
413 sc->sc_flags &= ~H_WRITTEN;
414 else
415 sc->sc_flags |= H_WRITTEN;
416 switch (er & MTER_INTCODE) {
417
418 case MTER_EOT:
419 sc->sc_flags |= H_EOT;
420 /* fall into MTER_DONE */
421
422 case MTER_DONE:
423 sc->sc_blkno++;
424 if (mi->mi_tab.b_errcnt == 2) {
425 bp->b_bcount = bp->b_resid;
426 bp->b_resid -= MASKREG(mtaddr->mtbc);
427 if (bp->b_resid > 0 && (bp->b_flags & B_RAW) == 0)
428 bp->b_flags |= B_ERROR;
429 } else
430 bp->b_resid = 0;
431 break;
432
433 case MTER_SHRTREC:
434 sc->sc_blkno++;
435 bp->b_bcount = bp->b_resid;
436 bp->b_resid -= MASKREG(mtaddr->mtbc);
437 if ((bp->b_flags & B_RAW) == 0)
438 bp->b_flags |= B_ERROR;
439 break;
440
441 case MTER_RETRY:
442 /*
443 * Simple re-try. Since resid is always a copy of the
444 * original byte count, use it to restore the count.
445 */
446 mi->mi_tab.b_errcnt = 1;
447 bp->b_bcount = bp->b_resid;
448 return (MBD_RETRY);
449
450 case MTER_RDOPP:
451 /*
452 * The controller just decided to read it backwards.
453 * If the controller returns a byte count of zero,
454 * change it to 1, since zero encodes 65536, which
455 * isn't quite what we had in mind. The byte count
456 * may be larger than the size of the input buffer, so
457 * limit the count to the buffer size. After
458 * making the byte count reasonable, set bcount to the
459 * negative of the controller's version of the byte
460 * count so that the start address for the transfer is
461 * set up correctly.
462 */
463 if (mt_do_readrev) {
464 mi->mi_tab.b_errcnt = 2;
465 if ((bp->b_bcount = MASKREG(mtaddr->mtbc)) == 0)
466 bp->b_bcount = 1;
467 if (bp->b_bcount > bp->b_resid)
468 bp->b_bcount = bp->b_resid;
469 bp->b_bcount = -(bp->b_bcount);
470 return(MBD_RETRY);
471 } else if (MASKREG(mtaddr->mtbc) <= bp->b_resid) {
472 sc->sc_blkno++;
473 bp->b_bcount = bp->b_resid;
474 bp->b_resid -= MASKREG(mtaddr->mtbc);
475 bp->b_flags |= B_ERROR;
476 break;
477 }
478 bp->b_flags |= B_ERROR;
479 /* fall into MTER_LONGREC */
480
481 case MTER_LONGREC:
482 sc->sc_blkno++;
483 bp->b_bcount = bp->b_resid;
484 bp->b_resid = 0;
485 bp->b_error = ENOMEM;
486 bp->b_flags |= B_ERROR;
487 break;
488
489 case MTER_NOTCAP:
490 printf("mu%d: blank tape\n", MUUNIT(bp->b_dev));
491 goto err;
492
493 case MTER_TM:
494 /*
495 * End of file. Since the default byte count has
496 * already been set, just count the block and proceed.
497 */
498 sc->sc_blkno++;
499 err:
500 sc->sc_nxrec = bdbtofsb(bp->b_blkno);
501 break;
502
503 case MTER_OFFLINE:
504 if (sc->sc_openf > 0) {
505 sc->sc_openf = -1;
506 tprintf(sc->sc_ctty, "mu%d: offline\n",
507 MUUNIT(bp->b_dev));
508 }
509 bp->b_flags |= B_ERROR;
510 break;
511
512 case MTER_NOTAVL:
513 if (sc->sc_openf > 0) {
514 sc->sc_openf = -1;
515 tprintf(sc->sc_ctty, "mu%d: offline (port selector)\n",
516 MUUNIT(bp->b_dev));
517 }
518 bp->b_flags |= B_ERROR;
519 break;
520
521 case MTER_FPT:
522 tprintf(sc->sc_ctty, "mu%d: no write ring\n",
523 MUUNIT(bp->b_dev));
524 bp->b_flags |= B_ERROR;
525 break;
526
527 case MTER_UNREAD:
528 sc->sc_blkno++;
529 bp->b_bcount = bp->b_resid;
530 bp->b_resid -= MIN(MASKREG(mtaddr->mtbc), bp->b_bcount);
531
532 /* code 010 means a garbage record, nothing serious. */
533 if ((er & MTER_FAILCODE) == (010 << MTER_FSHIFT)) {
534 tprintf(sc->sc_ctty,
535 "mu%d: rn=%d bn=%d unreadable record\n",
536 MUUNIT(bp->b_dev), sc->sc_blkno, bp->b_blkno);
537 bp->b_flags |= B_ERROR;
538 break;
539 }
540
541 /*
542 * Anything else might be a hardware problem,
543 * fall into the error report.
544 */
545
546 default:
547 /*
548 * The bits in sc->sc_dsreg are from the last sense
549 * command. To get the most recent copy, you have to
550 * do a sense at interrupt level, which requires nested
551 * error processing. This is a bit messy, so leave
552 * well enough alone.
553 */
554 tprintf(sc->sc_ctty, "\
555 mu%d: hard error (data transfer) rn=%d bn=%d mbsr=%b er=0%o ds=%b\n",
556 MUUNIT(bp->b_dev), sc->sc_blkno, bp->b_blkno,
557 mbsr, mbsr_bits, er,
558 MASKREG(sc->sc_dsreg), mtds_bits);
559 #ifdef MTLERRM
560 mtintfail(er);
561 #endif
562 bp->b_flags |= B_ERROR;
563
564 /*
565 * The TM78 manual says to reset the controller after
566 * TM fault B or MASSBUS fault.
567 */
568 if ((er & MTER_INTCODE) == MTER_TMFLTB ||
569 (er & MTER_INTCODE) == MTER_MBFLT)
570 mtcreset(mtaddr);
571 }
572
573 /*
574 * Just in case some strange error slipped through (drive off
575 * line during read-reverse error recovery comes to mind), make
576 * sure the byte count is reasonable.
577 */
578 if (bp->b_bcount < 0)
579 bp->b_bcount = bp->b_resid;
580
581 if ((bp->b_flags & B_ERROR) == 0) {
582 /* this counts reverse reads as soft errors */
583 sc->sc_blks++;
584 if (mi->mi_tab.b_errcnt) /* alternatively, if == 1 */
585 sc->sc_softerrs++;
586 }
587 return (MBD_DONE);
588 }
589
mtndtint(mi)590 mtndtint(mi)
591 register struct mba_device *mi;
592 {
593 register struct mtdevice *mtaddr = (struct mtdevice *)mi->mi_drv;
594 register struct buf *bp = mi->mi_tab.b_actf;
595 register struct mu_softc *sc;
596 register int er, fc;
597 int unit;
598
599 unit = (mtaddr->mtner >> 8) & 3;
600 er = MASKREG(mtaddr->mtner);
601 sc = &mu_softc[unit];
602 sc->sc_erreg = er;
603
604 /* Check for unsolicited interrupts. */
605 if (bp == NULL || unit != MUUNIT(bp->b_dev)) {
606 if ((er & MTER_INTCODE) == MTER_ONLINE)
607 return (MBN_SKIP);
608
609 printf("mu%d: stray intr (non data transfer) er=0%o ds=%b\n",
610 unit, er, MASKREG(sc->sc_dsreg), mtds_bits);
611 #ifdef MTLERRM
612 mtintfail(er);
613 #endif
614 if ((er & MTER_INTCODE) == MTER_TMFLTB ||
615 (er & MTER_INTCODE) == MTER_MBFLT) {
616 /*
617 * Reset the controller, then set error status
618 * if there was anything active when the fault
619 * occurred. This may shoot an innocent
620 * bystander, but it's better than letting
621 * an error slip through.
622 */
623 mtcreset(mtaddr);
624 if (bp != NULL) {
625 bp->b_flags |= B_ERROR;
626 return (MBN_DONE);
627 }
628 }
629 return (MBN_SKIP);
630 }
631
632 fc = (mtaddr->mtncs[unit] >> 8) & 0xff;
633 sc->sc_resid = fc;
634
635 /*
636 * Clear the "written" flag after any operation that changes
637 * the position of the tape.
638 */
639 if (bp != &cmtbuf[MTUNIT(bp->b_dev)] || bp->b_command != MT_SENSE)
640 sc->sc_flags &= ~H_WRITTEN;
641
642 switch (er & MTER_INTCODE) {
643
644 case MTER_EOT:
645 sc->sc_flags |= H_EOT;
646 /* fall into MTER_DONE */
647
648 case MTER_DONE:
649 /* If this is a command buffer, just update the status. */
650 if (bp == &cmtbuf[MTUNIT(bp->b_dev)]) {
651 done:
652 if (bp->b_command == MT_SENSE)
653 sc->sc_dsreg = MASKREG(mtaddr->mtds);
654 return (MBN_DONE);
655 }
656
657 /*
658 * It's not a command buffer, must be a cooked I/O
659 * skip operation (perhaps a shaky assumption, but it
660 * wasn't my idea).
661 */
662 if ((fc = bdbtofsb(bp->b_blkno) - sc->sc_blkno) < 0)
663 sc->sc_blkno -= MIN(0377, -fc);
664 else
665 sc->sc_blkno += MIN(0377, fc);
666 return (MBN_RETRY);
667
668 case MTER_ONLINE: /* ddj -- shouldn't happen but did */
669 case MTER_RWDING:
670 return (MBN_SKIP); /* ignore "rewind started" interrupt */
671
672 case MTER_NOTCAP:
673 tprintf(sc->sc_ctty, "mu%d: blank tape\n", MUUNIT(bp->b_dev));
674 bp->b_flags |= B_ERROR;
675 return (MBN_DONE);
676
677 case MTER_TM:
678 case MTER_LEOT:
679 /*
680 * For an ioctl skip operation, count a tape mark as
681 * a record. If there's anything left to do, update
682 * the repeat count and re-start the command.
683 */
684 if (bp == &cmtbuf[MTUNIT(bp->b_dev)]) {
685 if ((sc->sc_resid = bp->b_repcnt = fc - 1) == 0)
686 return (MBN_DONE);
687 else
688 return (MBN_RETRY);
689 } else {
690 /*
691 * Cooked I/O again. Just update the books and
692 * wait for someone else to return end of file or
693 * complain about a bad seek.
694 */
695 if (sc->sc_blkno > bdbtofsb(bp->b_blkno)) {
696 sc->sc_nxrec = bdbtofsb(bp->b_blkno) + fc - 1;
697 sc->sc_blkno = sc->sc_nxrec;
698 } else {
699 sc->sc_nxrec = bdbtofsb(bp->b_blkno) - fc;
700 sc->sc_blkno = sc->sc_nxrec + 1;
701 }
702 }
703 return (MBN_RETRY);
704
705 case MTER_FPT:
706 tprintf(sc->sc_ctty, "mu%d: no write ring\n",
707 MUUNIT(bp->b_dev));
708 bp->b_flags |= B_ERROR;
709 return (MBN_DONE);
710
711 case MTER_OFFLINE:
712 /* If `off line' was intentional, don't complain. */
713 if (bp == &cmtbuf[MTUNIT(bp->b_dev)] &&
714 bp->b_command == MT_UNLOAD)
715 return(MBN_DONE);
716 if (sc->sc_openf > 0) {
717 sc->sc_openf = -1;
718 tprintf(sc->sc_ctty, "mu%d: offline\n",
719 MUUNIT(bp->b_dev));
720 }
721 bp->b_flags |= B_ERROR;
722 return (MBN_DONE);
723
724 case MTER_NOTAVL:
725 if (sc->sc_openf > 0) {
726 sc->sc_openf = -1;
727 tprintf(sc->sc_ctty, "mu%d: offline (port selector)\n",
728 MUUNIT(bp->b_dev));
729 }
730 bp->b_flags |= B_ERROR;
731 return (MBN_DONE);
732
733 case MTER_BOT:
734 if (bp == &cmtbuf[MTUNIT(bp->b_dev)])
735 goto done;
736 /* fall through */
737
738 default:
739 tprintf(sc->sc_ctty, "\
740 mu%d: hard error (non data transfer) rn=%d bn=%d er=0%o ds=%b\n",
741 MUUNIT(bp->b_dev), sc->sc_blkno, bp->b_blkno,
742 er, MASKREG(sc->sc_dsreg), mtds_bits);
743 #ifdef MTLERRM
744 mtintfail(er);
745 #endif
746 if ((er & MTER_INTCODE) == MTER_TMFLTB ||
747 (er & MTER_INTCODE) == MTER_MBFLT)
748 mtcreset(mtaddr); /* reset the controller */
749 bp->b_flags |= B_ERROR;
750 return (MBN_DONE);
751 }
752 /* NOTREACHED */
753 }
754
755 void
mtcreset(mtaddr)756 mtcreset(mtaddr)
757 register struct mtdevice *mtaddr;
758 {
759 register int i;
760
761 mtaddr->mtid = MTID_CLR; /* reset the TM78 */
762 DELAY(200);
763 for (i = MTTIMEOUT; i > 0; i--) {
764 DELAY(50); /* don't nag */
765 if ((mtaddr->mtid & MTID_RDY) != 0)
766 return; /* exit when ready */
767 }
768 printf("mt: controller hung\n");
769 }
770
771 /*ARGSUSED*/
mtioctl(dev,cmd,data,flag)772 mtioctl(dev, cmd, data, flag)
773 dev_t dev;
774 int cmd;
775 caddr_t data;
776 int flag;
777 {
778 register struct mu_softc *sc = &mu_softc[MUUNIT(dev)];
779 register struct buf *bp = &cmtbuf[MTUNIT(dev)];
780 register struct mtop *mtop;
781 register struct mtget *mtget;
782 int callcount, fcount, error = 0;
783 int op;
784
785 /* We depend on the values and order of the MT codes here. */
786
787 static mtops[] =
788 {MT_WTM,MT_SFORWF,MT_SREVF,MT_SFORW,MT_SREV,MT_REW,MT_UNLOAD,MT_SENSE};
789
790 switch (cmd) {
791
792 /* tape operation */
793
794 case MTIOCTOP:
795 mtop = (struct mtop *)data;
796 switch (mtop->mt_op) {
797
798 case MTWEOF:
799 callcount = mtop->mt_count;
800 fcount = 1;
801 break;
802
803 case MTFSF: case MTBSF:
804 callcount = mtop->mt_count;
805 fcount = 1;
806 break;
807
808 case MTFSR: case MTBSR:
809 callcount = 1;
810 fcount = mtop->mt_count;
811 break;
812
813 case MTREW: case MTOFFL:
814 callcount = 1;
815 fcount = 1;
816 break;
817
818 default:
819 return (ENXIO);
820 }
821 if (callcount <= 0 || fcount <= 0)
822 return (EINVAL);
823 op = mtops[mtop->mt_op];
824 if (op == MT_WTM)
825 op |= sc->sc_dens;
826 while (--callcount >= 0) {
827 register int n, fc = fcount;
828
829 do {
830 n = MIN(fc, 0xff);
831 mtcommand(dev, op, n);
832 n -= sc->sc_resid;
833 fc -= n;
834 switch (mtop->mt_op) {
835
836 case MTWEOF:
837 sc->sc_blkno += (daddr_t)n;
838 sc->sc_nxrec = sc->sc_blkno - 1;
839 break;
840
841 case MTOFFL:
842 case MTREW:
843 case MTFSF:
844 sc->sc_blkno = (daddr_t)0;
845 sc->sc_nxrec = (daddr_t)INF;
846 break;
847
848 case MTBSF:
849 if (sc->sc_resid) {
850 sc->sc_blkno = (daddr_t)0;
851 sc->sc_nxrec = (daddr_t)INF;
852 } else {
853 sc->sc_blkno = (daddr_t)(-1);
854 sc->sc_nxrec = (daddr_t)(-1);
855 }
856 break;
857
858 case MTFSR:
859 sc->sc_blkno += (daddr_t)n;
860 break;
861
862 case MTBSR:
863 sc->sc_blkno -= (daddr_t)n;
864 break;
865 }
866 if (sc->sc_resid)
867 break;
868 } while (fc);
869 if (fc) {
870 sc->sc_resid = callcount + fc;
871 if (mtop->mt_op == MTFSR ||
872 mtop->mt_op == MTBSR)
873 return (EIO);
874 break;
875 }
876 if (bp->b_flags & B_ERROR)
877 break;
878 }
879 if (bp->b_flags&B_ERROR)
880 if ((error = bp->b_error)==0)
881 return (EIO);
882 return (error);
883
884 /* tape status */
885 case MTIOCGET:
886 mtget = (struct mtget *)data;
887 mtget->mt_erreg = sc->sc_erreg;
888 mtget->mt_resid = sc->sc_resid;
889 mtcommand(dev, MT_SENSE, 1); /* update drive status */
890 mtget->mt_dsreg = sc->sc_dsreg;
891 mtget->mt_type = MT_ISMT;
892 break;
893
894 /* ignore EOT condition */
895 case MTIOCIEOT:
896 sc->sc_flags |= H_IEOT;
897 break;
898
899 /* enable EOT condition */
900 case MTIOCEEOT:
901 sc->sc_flags &= ~H_IEOT;
902 break;
903
904 default:
905 return (ENXIO);
906 }
907 return (0);
908 }
909
910 #define DBSIZE 20
911
mtdump()912 mtdump()
913 {
914 register struct mba_device *mi;
915 register struct mba_regs *mp;
916 int blk, num;
917 int start;
918
919 start = 0;
920 num = maxfree;
921 #define phys(a,b) ((b)((int)(a)&0x7fffffff))
922 if (mtinfo[0] == 0)
923 return (ENXIO);
924 mi = phys(mtinfo[0], struct mba_device *);
925 mp = phys(mi->mi_hd, struct mba_hd *)->mh_physmba;
926 mp->mba_cr = MBCR_IE;
927 #if lint
928 blk = 0; num = blk; start = num; blk = start;
929 return (0);
930 #endif
931 #ifdef notyet
932 mtaddr = (struct mtdevice *)&mp->mba_drv[mi->mi_drive];
933 mtaddr->mttc = MTTC_PDP11|MTTC_1600BPI;
934 mtaddr->mtcs1 = MT_DCLR|MT_GO;
935 while (num > 0) {
936 blk = num > DBSIZE ? DBSIZE : num;
937 mtdwrite(start, blk, mtaddr, mp);
938 start += blk;
939 num -= blk;
940 }
941 mteof(mtaddr);
942 mteof(mtaddr);
943 mtwait(mtaddr);
944 if (mtaddr->mtds&MTDS_ERR)
945 return (EIO);
946 mtaddr->mtcs1 = MT_REW|MT_GO;
947 return (0);
948 }
949
mtdwrite(dbuf,num,mtaddr,mp)950 mtdwrite(dbuf, num, mtaddr, mp)
951 register dbuf, num;
952 register struct mtdevice *mtaddr;
953 struct mba_regs *mp;
954 {
955 register struct pte *io;
956 register int i;
957
958 mtwait(mtaddr);
959 io = mp->mba_map;
960 for (i = 0; i < num; i++)
961 *(int *)io++ = dbuf++ | PG_V;
962 mtaddr->mtfc = -(num*NBPG);
963 mp->mba_sr = -1;
964 mp->mba_bcr = -(num*NBPG);
965 mp->mba_var = 0;
966 mtaddr->mtcs1 = MT_WCOM|MT_GO;
967 }
968
969 mtwait(mtaddr)
970 struct mtdevice *mtaddr;
971 {
972 register s;
973
974 do
975 s = mtaddr->mtds;
976 while ((s & MTDS_DRY) == 0);
977 }
978
979 mteof(mtaddr)
980 struct mtdevice *mtaddr;
981 {
982
983 mtwait(mtaddr);
984 mtaddr->mtcs1 = MT_WEOF|MT_GO;
985 #endif notyet
986 }
987
988 #ifdef MTLERRM
989 /*
990 * Failure messages for each failure code, per interrupt code.
991 * Each table ends with a code of -1 as a default.
992 */
993 struct fmesg {
994 int f_code;
995 char *f_mesg;
996 };
997
998 static char unclass[] = "unclassified failure code";
999
1000 /* MTER_BOT */
1001 static struct fmesg botmsg[] = {
1002 01, "tape was at BOT",
1003 02, "BOT seen after tape started",
1004 03, "ARA ID detected",
1005 -1, unclass
1006 };
1007
1008 /* MTER_NOTRDY */
1009 static struct fmesg notrdymsg[] = {
1010 01, "TU on-line but not ready",
1011 02, "fatal error has occurred",
1012 03, "access allowed but not ready",
1013 -1, unclass
1014 };
1015
1016 /* MTER_NOTCAP */
1017 static struct fmesg notcapmsg[] = {
1018 01, "no record found within 25 feet",
1019 02, "ID burst neither PE nor GCR",
1020 03, "ARA ID not found",
1021 04, "no gap found after ID burst",
1022 -1, unclass
1023 };
1024
1025 /* MTER_LONGREC */
1026 static struct fmesg longrecmsg[] = {
1027 00, "extended sense data not found",
1028 01, "extended sense data updated",
1029 -1, unclass
1030 };
1031
1032 /* MTER_UNREAD, MTER_ERROR, MTER_EOTERR, MTER_BADTAPE */
1033 static struct fmesg code22msg[] = {
1034 01, "GCR write error",
1035 02, "GCR read error",
1036 03, "PE read error",
1037 04, "PE write error",
1038 05, "at least 1 bit set in ECCSTA",
1039 06, "PE write error",
1040 07, "GCR write error",
1041 010, "RSTAT contains bad code",
1042 011, "PE write error",
1043 012, "MASSBUS parity error",
1044 013, "invalid data transferred",
1045 -1, unclass
1046 };
1047
1048 /* MTER_TMFLTA */
1049 static struct fmesg tmfltamsg[] = {
1050 01, "illegal command code",
1051 02, "DT command issued when NDT command active",
1052 03, "WMC error",
1053 04, "RUN not received from MASSBUS controller",
1054 05, "mismatch in command read - function routine",
1055 06, "ECC ROM parity error",
1056 07, "XMC ROM parity error",
1057 010, "mismatch in command read - ID burst command",
1058 011, "mismatch in command read - verify ARA burst command",
1059 012, "mismatch in command read - verify ARA ID command",
1060 013, "mismatch in command read - verify gap command",
1061 014, "mismatch in command read - read id burst command",
1062 015, "mismatch in command read - verify ARA ID command",
1063 016, "mismatch in command read - verify gap command",
1064 017, "mismatch in command read - find gap command",
1065 020, "WMC LEFT failed to set",
1066 021, "XL PE set in INTSTA register",
1067 022, "XMC DONE did not set",
1068 023, "WMC ROM PE or RD PE set in WMCERR register",
1069 -1, unclass
1070 };
1071
1072 /* MTER_TUFLTA */
1073 static struct fmesg tufltamsg[] = {
1074 01, "TU status parity error",
1075 02, "TU command parity error",
1076 03, "rewinding tape went offline",
1077 04, "tape went not ready during DSE",
1078 05, "TU CMD status changed during DSE",
1079 06, "TU never came up to speed",
1080 07, "TU velocity changed",
1081 010, "TU CMD did not load correctly to start tape motion",
1082 011, "TU CMD did not load correctly to set drive density",
1083 012, "TU CMD did not load correctly to start tape motion to write BOT ID",
1084 013, "TU CMD did not load correctly to backup tape to BOT after failing to write BOT ID",
1085 014, "failed to write density ID burst",
1086 015, "failed to write ARA burst",
1087 016, "failed to write ARA ID",
1088 017, "ARA error bit set in MTA status B register",
1089 021, "could not find a gap after ID code was written correctly",
1090 022, "TU CMD did not load correctly to start tape motion to read ID burst",
1091 023, "timeout looking for BOT after detecting ARA ID burst",
1092 024, "failed to write tape mark",
1093 025, "tape never came up to speed while trying to reposition for retry of writing tape mark",
1094 026, "TU CMD did not load correctly to start tape motion in erase gap routine",
1095 027, "could not detect a gap in in erase gap routine",
1096 030, "could not detect a gap after writing record",
1097 031, "read path terminated before entire record was written",
1098 032, "could not find a gap after writing record and read path terminated early",
1099 033, "TU CMD did not load correctly to backup for retry of write tape mark",
1100 034, "TU velocity changed after up to speed while trying to reposition for retry of writing tape mark",
1101 035, "TU CMD did not load correctly to backup to retry a load of BOT ID",
1102 036, "timeout looking for BOT after failing to write BOT ID",
1103 037, "TU velocity changed while writing PE gap before starting to write record",
1104 040, "TU CMD did not load correctly to set PE tape density at start of write BOT ID burst",
1105 041, "TU CMD did not load correctly to set GCR tape density after writing Density ID",
1106 042, "TU CMD did not load correctly to set PE tape density at start of read from BOT",
1107 043, "TU CMD did not load correctly to set GCR tape density after reading a GCR Density ID burst",
1108 };
1109
1110 /* MTER_TMFLTB */
1111 static char inlinetest[] = "inline test failed";
1112 static struct fmesg tmfltbmsg[] = {
1113 00, "RST0 interrupt occurred with TM RDY set",
1114 01, "power failed to interrupt",
1115 02, "unknown interrupt on channel 5.5",
1116 03, "unknown interrupt on channel 6.5",
1117 04, "unknown interrupt on channel 7",
1118 05, "unknown interrupt on channel 7.5",
1119 06, "CAS contention retry count expired",
1120 07, "CAS contention error not retryable",
1121 010, "queue error, could not find queue entry",
1122 011, "queue entry already full",
1123 012, "8085 ROM parity error",
1124 013, inlinetest,
1125 013, inlinetest,
1126 014, inlinetest,
1127 015, inlinetest,
1128 016, inlinetest,
1129 017, inlinetest,
1130 020, inlinetest,
1131 021, inlinetest,
1132 022, inlinetest,
1133 023, inlinetest,
1134 024, inlinetest,
1135 025, inlinetest,
1136 026, inlinetest,
1137 027, inlinetest,
1138 030, inlinetest,
1139 031, inlinetest,
1140 032, inlinetest,
1141 033, inlinetest,
1142 034, inlinetest,
1143 035, inlinetest,
1144 036, inlinetest,
1145 037, inlinetest,
1146 040, inlinetest,
1147 041, inlinetest,
1148 042, inlinetest,
1149 043, inlinetest,
1150 044, inlinetest,
1151 045, inlinetest,
1152 046, inlinetest,
1153 047, inlinetest,
1154 050, inlinetest,
1155 051, inlinetest,
1156 052, inlinetest,
1157 053, inlinetest,
1158 054, inlinetest,
1159 055, inlinetest,
1160 056, inlinetest,
1161 057, inlinetest,
1162 -1, unclass
1163 };
1164
1165 /* MTER_MBFLT */
1166 static struct fmesg mbfltmsg[] = {
1167 01, "control bus parity error",
1168 02, "illegal register referenced",
1169 -1, unclass
1170 };
1171
1172 /*
1173 * MTER_LEOT, MTER_RWDING, NTER_NOTAVL, MTER_NONEX, MTER_KEYFAIL,
1174 * and default: no failure message.
1175 */
1176 static struct fmesg nullmsg[] = {
1177 -1, ""
1178 };
1179
1180 /*
1181 * Interrupt code table.
1182 */
1183 static struct errmsg {
1184 int e_code;
1185 char *e_mesg;
1186 struct fmesg *e_fmesg;
1187 } errmsg[] = {
1188 MTER_BOT, "unexpected BOT", botmsg,
1189 MTER_LEOT, "unexpected LEOT", nullmsg,
1190 MTER_RWDING, "tape rewinding", nullmsg,
1191 MTER_NOTRDY, "drive not ready", notrdymsg,
1192 MTER_NOTAVL, "drive not available", nullmsg,
1193 MTER_NONEX, "unit does not exist", nullmsg,
1194 MTER_NOTCAP, "not capable", notcapmsg,
1195 MTER_LONGREC, "long record", longrecmsg,
1196 MTER_UNREAD, "unreadable record", code22msg,
1197 MTER_ERROR, "error", code22msg,
1198 MTER_EOTERR, "EOT error", code22msg,
1199 MTER_BADTAPE, "tape position lost", code22msg,
1200 MTER_TMFLTA, "TM fault A", tmfltamsg,
1201 MTER_TUFLTA, "TU fault A", tufltamsg,
1202 MTER_TMFLTB, "TM fault B", tmfltbmsg,
1203 MTER_MBFLT, "MB fault", mbfltmsg,
1204 MTER_KEYFAIL, "keypad entry error", nullmsg,
1205 -1, "unclassified error", nullmsg
1206 };
1207
1208 /*
1209 * Decode an interrupt-time failure.
1210 */
mtintfail(erreg)1211 mtintfail(erreg)
1212 int erreg;
1213 {
1214 register struct errmsg *e;
1215 register struct fmesg *f;
1216 register int ecode, fcode;
1217
1218 ecode = erreg & MTER_INTCODE;
1219 fcode = (erreg & MTER_FAILCODE) >> MTER_FSHIFT;
1220 for (e = errmsg; e->e_code >= 0; e++)
1221 if (e->e_code == ecode)
1222 break;
1223 for (f = e->e_fmesg; f->f_code >= 0; f++)
1224 if (f->f_code == fcode)
1225 break;
1226 printf(" interrupt code = 0%o <%s>\n", ecode, e->e_mesg);
1227 printf(" failure code = 0%o <%s>\n", fcode, f->f_mesg);
1228 }
1229 #endif /* MTLERRM */
1230 #endif /* NMT > 0 */
1231