4.4BSD/usr/src/sys/vax/stand/ut.c

Compare this file to the similar file:
Show the results in this format:

/*
 * 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.
 *
 *	@(#)ut.c	7.8 (Berkeley) 5/4/91
 */

/*
 * SI Model 9700 -- emulates TU45 on the UNIBUS
 */

#include "sys/param.h"

#include "../include/pte.h"

#include "../uba/ubareg.h"
#include "../uba/utreg.h"

#include "stand/saio.h"
#include "savax.h"

#define	MASKREG(reg)	((reg)&0xffff)

#define	MAXCTLR		1		/* all addresses must be specified */
u_short	utstd[MAXCTLR] = { 0172440 };	/* non-standard */

utopen(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_unit, utstd[io->i_ctlr]), sizeof(short)))
		return (ENXIO);
	utstrategy(io, UT_REW);
	for (skip = io->i_part; skip--;)
		utstrategy(io, UT_SFORWF);
	return (0);
}

utclose(io)
	register struct iob *io;
{
	utstrategy(io, UT_REW);
}

#define	UTWAIT(addr) { \
	do \
		word = addr->utcs1; \
	while((word&UT_RDY) == 0); \
}

utstrategy(io, func)
	register struct iob *io;
{
	register struct utdevice *addr;
	register u_short word;
	register int errcnt;
	int info, resid;
	u_short dens;

	addr = (struct utdevice *)ubamem(io->i_unit, utstd[io->i_ctlr]);
	dens = io->i_unit | PDP11FMT | UT_PE;
	errcnt = 0;
retry:
	utquiet(addr);
	addr->uttc = dens;
	info = ubasetup(io, 1);
	addr->utwc = -((io->i_cc+1) >> 1);
	addr->utfc = -io->i_cc;
	if (func == F_READ) {
		addr->utba = info;
		addr->utcs1 = UT_RCOM | ((info>>8) & 0x30) | UT_GO;
	} else if (func == F_WRITE) {
		addr->utba = info;
		addr->utcs1 = UT_WCOM | ((info>>8) & 0x30) | UT_GO;
	} else if (func == UT_SREV) {
		addr->utcs1 = UT_SREV | UT_GO;
		return (0);
	} else
		addr->utcs1 = func | UT_GO;
	UTWAIT(addr);
	ubafree(io, info);
	word = addr->utds;
	if (word&(UTDS_EOT|UTDS_TM)) {
		addr->utcs1 = UT_CLEAR | UT_GO;
		goto done;
	}
	if ((word&UTDS_ERR) || (addr->utcs1&UT_TRE)) {
		printf("ut error: cs1=%b er=%b cs2=%b ds=%b",
		  addr->utcs1, UT_BITS, addr->uter, UTER_BITS,
		  addr->utcs2, UTCS2_BITS, word, UTDS_BITS);
		if (errcnt++ == 10) {
			printf("ut: unrecovered error\n");
			return (-1);
		}
		if (addr->utcs1&UT_TRE)
			addr->utcs2 |= UTCS2_CLR;
		addr->utcs1 = UT_CLEAR | UT_GO;
		utstrategy(io, UT_SREV);
		utquiet(addr);
		if (func == F_WRITE) {
			addr->utcs1 = UT_ERASE | UT_GO;
			UTWAIT(addr);
		}
		goto retry;
	}
	if (errcnt)
		printf("ut: recovered by retry\n");
done:
	if (func == F_READ) {
		resid = 0;
		if (io->i_cc > MASKREG(addr->utfc))
			resid = io->i_cc - MASKREG(addr->utfc);
	} else
		resid = MASKREG(-addr->utfc);
	return (io->i_cc - resid);
}

static
utquiet(addr)
	register struct utdevice *addr;
{
	register u_short word;

	UTWAIT(addr);
	do
		word = addr->utds;
	while ((word&UTDS_DRY) == 0 && (word&UTDS_PIP));
}