reorganization to move ufsmount ops to be vnode ops;
[unix-history] / usr / src / sys / vax / stand / tm.c
/*
* Copyright (c) 1982, 1986, 1988 Regents of the University of California.
* All rights reserved. The Berkeley software License Agreement
* specifies the terms and conditions for redistribution.
*
* @(#)tm.c 7.8 (Berkeley) %G%
*/
/*
* TM11/TE??
*/
#include "sys/param.h"
#include "../include/pte.h"
#include "../uba/ubareg.h"
#include "../uba/tmreg.h"
#include "stand/saio.h"
#include "savax.h"
#define MAXCTLR 1 /* all addresses must be specified */
u_short tmstd[MAXCTLR] = { 0172520 };
tmopen(io)
register struct iob *io;
{
register int skip;
if ((u_int)io->i_adapt >= nuba)
return (EADAPT);
if ((u_int)io->i_ctlr >= MAXCTLR)
return (ECTLR);
if (badaddr((char *)ubamem(io->i_adapt, tmstd[io->i_ctlr]), sizeof(short)))
return (ENXIO);
tmstrategy(io, TM_REW);
for (skip = io->i_part; skip--;) {
io->i_cc = 0;
tmstrategy(io, TM_SFORW);
}
return (0);
}
tmclose(io)
register struct iob *io;
{
tmstrategy(io, TM_REW);
}
tmstrategy(io, func)
register struct iob *io;
{
register int com, errcnt;
register struct tmdevice *tmaddr;
int word, info;
tmaddr = (struct tmdevice *)ubamem(io->i_adapt, tmstd[io->i_ctlr]);
errcnt = 0;
retry:
tmquiet(tmaddr);
info = ubasetup(io, 1);
tmaddr->tmbc = -io->i_cc;
tmaddr->tmba = info;
com = (io->i_unit<<8) | TM_GO;
if (func == F_READ)
tmaddr->tmcs = com | TM_RCOM;
else if (func == F_WRITE)
tmaddr->tmcs = com | TM_WCOM;
else if (func == TM_SREV) {
tmaddr->tmbc = -1;
tmaddr->tmcs = com | TM_SREV;
return (0);
} else
tmaddr->tmcs = com | func;
for (;;) {
word = tmaddr->tmcs;
DELAY(100);
if (word & TM_CUR)
break;
}
ubafree(io, info);
word = tmaddr->tmer;
if (word & TMER_EOT)
return (0);
if (word & TM_ERR) {
if (word & TMER_EOF)
return (0);
printf("tm tape error: er=%b\n", word, TMER_BITS);
if (errcnt++ == 10) {
printf("tm: unrecovered error\n");
return (-1);
}
tmstrategy(io, TM_SREV);
goto retry;
}
if (errcnt)
printf("tm: recovered by retry\n");
if (word & TMER_EOF)
return (0);
return (io->i_cc + tmaddr->tmbc);
}
tmquiet(tmaddr)
register struct tmdevice *tmaddr;
{
register word;
for (;;) {
word = tmaddr->tmcs;
DELAY(100);
if (word&TM_CUR)
break;
}
for (;;) {
word = tmaddr->tmer;
DELAY(100);
if ((word&TMER_TUR) && (word&TMER_SDWN)==0)
break;
}
}