/* * Magtape driver */ #include #include #include #include "../saio.h" #define CDISARM 0xc0 #define CENABLE 0x40 #define CCLEAR 0x20 #define CREAD 0x21 #define CWRITE 0x22 #define CWF 0x30 #define CRW 0x38 #define CFF 0x23 #define CBF 0x13 #define CBR 0x11 #define ERR 0x80 #define EOF 0x40 #define EOT 0x20 #define NMTN 0x10 #define BSY 0x04 #define DU 0x01 #define STOP 0x48 #define GO 0x50 #define READ_GO 0x70 #define SELCHBSY 0x08 char mtaddr[] = { 0x85 }; char mtselch = 0xf0; mtclose(io) register struct iob *io; { mtstrategy(io, CRW); } mtopen(io) register struct iob *io; { register mt, skip; if ((mt = io->i_deva) == 0) mt = mtaddr[io->i_unit]; oc(mt, CCLEAR); oc(mt, CDISARM); mtstrategy(io, CRW); skip = io->i_boff; while (skip--) mtstrategy(io, CFF); } mtstrategy(io, func) register struct iob *io; { register int mt, selch, errcnt, stat; if ((mt = io->i_deva) == 0) mt = mtaddr[io->i_unit]; errcnt = 0; retry: if (ss(mt) & DU) { printf("Tape offline ad=%x\n", mt); return(-1); } switch (func) { case CRW: /* rewind */ case CFF: /* forward space file */ oc(mt, func); mtquiet(mt); break; case READ: /* read record */ case WRITE: /* write record */ if ((selch = io->i_selch) == 0) selch = mtselch; oc(selch, STOP); wdh(selch, io->i_ma); wdh(selch, io->i_ma + io->i_cc - 1); if (func == READ) { oc(mt, CREAD); oc(selch, READ_GO); } else { oc(mt, CWRITE); oc(selch, GO); } while (ss(selch) & SELCHBSY) ; oc(selch, STOP); mtquiet(mt); if ((stat = ss(mt)) & (EOF|EOT)) return(0); if (stat & ERR) { if (errcnt == 0) printf("Tape error: er=%x ad=%x", stat, mt); if (errcnt==10) { printf("\n"); return(-1); } errcnt++; oc(mt, CBR); mtquiet(mt); goto retry; } if (errcnt) printf(" recovered by retry\n"); return(((rdh(selch)+1) & ~01) - io->i_ma); } } mtquiet(addr) { while ((ss(addr) & NMTN) == 0) ; }