123235Smckusick /*
229304Smckusick * Copyright (c) 1982, 1986 Regents of the University of California.
323235Smckusick * All rights reserved. The Berkeley software License Agreement
423235Smckusick * specifies the terms and conditions for redistribution.
523235Smckusick *
6*49100Sbostic * @(#)mt.c 7.7 (Berkeley) 05/04/91
723235Smckusick */
85151Ssam
95151Ssam /*
105151Ssam * TM78/TU78 tape driver
1110776Ssam * Made to work reliably by by Jeffrey R. Schwab (Purdue)
125151Ssam */
1345803Sbostic #include "../include/pte.h"
145151Ssam
1545803Sbostic #include "sys/param.h"
169186Ssam
1745803Sbostic #include "../mba/mtreg.h"
1845803Sbostic #include "../mba/mbareg.h"
199186Ssam
2045803Sbostic #include "stand/saio.h"
215151Ssam #include "savax.h"
225151Ssam
235151Ssam short mttypes[] =
245151Ssam { MBDT_TU78, 0 };
255151Ssam
265151Ssam #define MASKREG(reg) ((reg)&0xffff)
275151Ssam
mtopen(io)285151Ssam mtopen(io)
295151Ssam register struct iob *io;
305151Ssam {
3133529Sbostic register struct mtdevice *mtaddr;
3233529Sbostic register int i, skip;
335151Ssam
3433529Sbostic if (mbainit(io->i_adapt) == 0)
3533529Sbostic return (EADAPT);
3633529Sbostic mtaddr = (struct mtdevice *)mbadrv(io->i_adapt, io->i_ctlr);
3733529Sbostic for (i = 0;; i++) {
3833529Sbostic if (!mttypes[i]) {
3933529Sbostic printf("mt: not a tape\n");
4033529Sbostic return (ENXIO);
4133529Sbostic }
425151Ssam if (mttypes[i] == (mtaddr->mtdt&MBDT_TYPE))
4333529Sbostic break;
4433529Sbostic }
455151Ssam mtaddr->mtid = MTID_CLR;
465151Ssam DELAY(250);
4733529Sbostic while ((mtaddr->mtid & MTID_RDY) == 0);
4810776Ssam
4910776Ssam /* clear any attention bits present on open */
5010776Ssam i = mtaddr->mtner;
5110776Ssam mtaddr->mtas = mtaddr->mtas;
5210776Ssam
535151Ssam mtstrategy(io, MT_REW);
5433529Sbostic for (skip = io->i_part; skip--;) {
555151Ssam io->i_cc = -1;
565151Ssam mtstrategy(io, MT_SFORWF);
575151Ssam }
5833408Skarels return (0);
595151Ssam }
605151Ssam
mtclose(io)615151Ssam mtclose(io)
625151Ssam register struct iob *io;
635151Ssam {
645151Ssam mtstrategy(io, MT_REW);
655151Ssam }
665151Ssam
mtstrategy(io,func)675151Ssam mtstrategy(io, func)
685151Ssam register struct iob *io;
695151Ssam int func;
705151Ssam {
715151Ssam register int errcnt, s, ic;
7233529Sbostic register struct mtdevice *mtaddr;
7333529Sbostic struct mba_regs *mba;
745151Ssam
755151Ssam errcnt = 0;
7633529Sbostic mtaddr = (struct mtdevice *)mbadrv(io->i_adapt, io->i_ctlr);
7733529Sbostic mba = mbamba(io->i_adapt);
785151Ssam retry:
7910776Ssam /* code to trap for attention up prior to start of command */
8010776Ssam if ((mtaddr->mtas & 0xffff) != 0) {
8110776Ssam printf("mt unexpected attention er=%x - continuing\n",
8210776Ssam MASKREG(mtaddr->mtner));
8310776Ssam mtaddr->mtas = mtaddr->mtas;
8410776Ssam }
8510776Ssam
86*49100Sbostic if (func == F_READ || func == F_WRITE) {
875151Ssam mtaddr->mtca = 1<<2; /* 1 record */
885151Ssam mtaddr->mtbc = io->i_cc;
8933529Sbostic mbastart(io, io->i_ctlr, func);
9010776Ssam /* wait for mba to go idle and read result status */
9110776Ssam while((mba->mba_sr & MBSR_DTBUSY) != 0)
9210776Ssam ;
9310776Ssam ic = mtaddr->mter & MTER_INTCODE;
945151Ssam } else {
955151Ssam mtaddr->mtncs[0] = (-io->i_cc << 8)|func|MT_GO;
965151Ssam rwait:
975151Ssam do
985151Ssam s = mtaddr->mtas&0xffff;
995151Ssam while (s == 0);
10010776Ssam ic = mtaddr->mtner & MTER_INTCODE;
1015151Ssam mtaddr->mtas = mtaddr->mtas; /* clear attention */
1025151Ssam }
1035151Ssam switch (ic) {
1045151Ssam case MTER_TM:
1055151Ssam case MTER_EOT:
1065151Ssam case MTER_LEOT:
1075151Ssam return (0);
1085151Ssam
1095151Ssam case MTER_DONE:
11010776Ssam /* make sure a record was read */
11110776Ssam if ((mtaddr->mtca & (1 << 2)) != 0) {
11210776Ssam printf("mt record count not decremented - retrying\n");
11310776Ssam goto retry;
11410776Ssam }
1155151Ssam break;
1165151Ssam
1175151Ssam case MTER_RWDING:
1185151Ssam goto rwait;
1195151Ssam default:
12010776Ssam printf("mt hard error: er=%x\n",
1215151Ssam MASKREG(mtaddr->mter));
1225151Ssam mtaddr->mtid = MTID_CLR;
1235151Ssam DELAY(250);
1245151Ssam while ((mtaddr->mtid & MTID_RDY) == 0)
1255151Ssam ;
1265151Ssam return (-1);
1275151Ssam
1285151Ssam case MTER_RETRY:
12910776Ssam printf("mt error: er=%x\n", MASKREG(mtaddr->mter));
13033529Sbostic if (errcnt++ == 10) {
1315151Ssam printf("mt: unrecovered error\n");
1325151Ssam return (-1);
1335151Ssam }
1345151Ssam goto retry;
1355151Ssam }
1365151Ssam if (errcnt)
1375151Ssam printf("mt: recovered by retry\n");
1385151Ssam return (io->i_cc); /* NO PARTIAL RECORD READS!!! */
1395151Ssam }
140