static char sccsid[] = "%W%"; /* * TE16 tape driver */ #include "saio.h" struct device { int htcs1; int htds; int hter; int htmr; int htas; int htfc; int htdt; int htck; int htsn; int httc; }; /* * VAX Massbus adapter registers */ struct mba_regs { int mba_csr, mba_cr, mba_sr, mba_var, mba_bcr; }; #define MBA_MAP 0x800 #define MBA_ERB 0x400 #define MBA1 ((struct mba_regs *)0x20012000) #define HTADDR ((struct device *)0x20012400) #define NUNIT 4 static daddr_t _eof[NUNIT]; #define GO 01 #define REW 06 #define DCLR 010 #define ERASE 024 #define WEOF 026 #define SFORW 030 #define SREV 032 #define WCOM 060 #define RCOM 070 #define TRE 040000 #define P800 01300 /* 800 + pdp11 mode */ #define P1600 02300 /* 1600 + pdp11 mode */ #define TM 04 #define DRY 0200 #define MOL 010000 #define INIT 01 #define DTABT 0x1000 static _tcommand (io, com, htaddr) register struct iob *io; register com; register struct device *htaddr; { register unit; unit = io->i_dp->dt_unit & 03; htaddr->htcs1 = com | GO; while ((htaddr->htds & DRY) == 0); if (htaddr->htds & TM) { _eof[unit]++; return (0); } if (MBA1->mba_sr & DTABT) return (-1); return ((htaddr->htfc & 0xffff) + (com == RCOM ? 0 : io->i_cc)); } _htclose (io) register struct iob *io; { register flag, unit; register struct device *htaddr; htaddr = (struct device *) (((int *) HTADDR) + 32*(unit & 03)); flag = io->i_flgs; unit = io->i_dp->dt_unit & 03; htaddr->htfc = 0; if (flag & F_WRITE) { _tcommand (io, WEOF, htaddr); _tcommand (io, WEOF, htaddr); } if ((io->i_dp->dt_unit & 04) == 0) _tcommand (io, REW, htaddr); else if (flag & F_WRITE) _tcommand (io, SREV, htaddr); else if (!_eof[unit]) _tcommand (io, SFORW, htaddr); _eof[unit] = 0; } _htstrategy (io, func) register struct iob *io; { register com, unit; int errcnt = 0; int den, dev; int ret; register struct device *htaddr; register i, *mbap, frame; dev = io->i_dp->dt_unit; unit = dev & 03; htaddr = (struct device *) (((int *) HTADDR) + 32*unit); MBA1->mba_cr = INIT; htaddr->htcs1 = DCLR | GO; if (func == READ) com = RCOM; else if (func == WRITE) com = WCOM; else com = func; den = ((dev & 010) ? P1600 : P800) | unit; if ((htaddr->httc & 03777) != den) htaddr->httc = den; if ((htaddr->htds & MOL) == 0) { _prs ("TE16 unit not ready\n"); while ((htaddr->htds & MOL) == 0); } mbap = (int *) MBA1; mbap += MBA_MAP / 4; frame = ((int) io->i_ma) >> 9; for (i = ((io->i_cc + 511) >> 9) + 1; i > 0; i--) *mbap++ = 0x80000000 | frame++; *mbap = 0; /* invalidate mba entry */ do { MBA1->mba_var = ((int) io->i_ma) & 0x1ff; MBA1->mba_bcr = htaddr->htfc = -io->i_cc; _eof[unit] = 0; while ((htaddr->htds & DRY) == 0); if ((ret = _tcommand (io, com, htaddr)) > 0) return (ret); MBA1->mba_cr = INIT; htaddr->htcs1 = DCLR | GO; if (ret == 0) return (0); htaddr->htfc = -1; while ((htaddr->htds & DRY) == 0); _tcommand (io, SREV, htaddr); if (com == WCOM) { while ((htaddr->htds & DRY) == 0); _tcommand (io, ERASE, htaddr); } } while (++errcnt < 10); errno = EIO; return (-1); }