123250Smckusick /*
235052Skarels * Copyright (c) 1982, 1986, 1988 Regents of the University of California.
323250Smckusick * All rights reserved. The Berkeley software License Agreement
423250Smckusick * specifies the terms and conditions for redistribution.
523250Smckusick *
6*49100Sbostic * @(#)ut.c 7.8 (Berkeley) 05/04/91
723250Smckusick */
85152Ssam
95152Ssam /*
105152Ssam * SI Model 9700 -- emulates TU45 on the UNIBUS
115152Ssam */
125152Ssam
1345803Sbostic #include "sys/param.h"
149186Ssam
1545803Sbostic #include "../include/pte.h"
1635052Skarels
1745803Sbostic #include "../uba/ubareg.h"
1845803Sbostic #include "../uba/utreg.h"
199186Ssam
2045803Sbostic #include "stand/saio.h"
215152Ssam #include "savax.h"
225152Ssam
2311177Ssam #define MASKREG(reg) ((reg)&0xffff)
245152Ssam
2533534Sbostic #define MAXCTLR 1 /* all addresses must be specified */
2633534Sbostic u_short utstd[MAXCTLR] = { 0172440 }; /* non-standard */
275152Ssam
utopen(io)285152Ssam utopen(io)
295152Ssam register struct iob *io;
305152Ssam {
3133534Sbostic register int skip;
325152Ssam
3335052Skarels if ((u_int)io->i_adapt >= nuba)
3435052Skarels return (EADAPT);
3533534Sbostic if ((u_int)io->i_ctlr >= MAXCTLR)
3633534Sbostic return (ECTLR);
3733551Sbostic if (badaddr((char *)ubamem(io->i_unit, utstd[io->i_ctlr]), sizeof(short)))
3833408Skarels return (ENXIO);
395152Ssam utstrategy(io, UT_REW);
4033534Sbostic for (skip = io->i_part; skip--;)
4111412Ssam utstrategy(io, UT_SFORWF);
4233408Skarels return (0);
435152Ssam }
445152Ssam
utclose(io)455152Ssam utclose(io)
465152Ssam register struct iob *io;
475152Ssam {
485152Ssam utstrategy(io, UT_REW);
495152Ssam }
505152Ssam
5133534Sbostic #define UTWAIT(addr) { \
5233534Sbostic do \
5333534Sbostic word = addr->utcs1; \
5433534Sbostic while((word&UT_RDY) == 0); \
5533534Sbostic }
565152Ssam
utstrategy(io,func)575152Ssam utstrategy(io, func)
585152Ssam register struct iob *io;
595152Ssam {
6033534Sbostic register struct utdevice *addr;
615152Ssam register u_short word;
625152Ssam register int errcnt;
6311177Ssam int info, resid;
645152Ssam u_short dens;
655152Ssam
6633534Sbostic addr = (struct utdevice *)ubamem(io->i_unit, utstd[io->i_ctlr]);
6733534Sbostic dens = io->i_unit | PDP11FMT | UT_PE;
685152Ssam errcnt = 0;
695152Ssam retry:
705152Ssam utquiet(addr);
715152Ssam addr->uttc = dens;
725152Ssam info = ubasetup(io, 1);
735152Ssam addr->utwc = -((io->i_cc+1) >> 1);
745152Ssam addr->utfc = -io->i_cc;
75*49100Sbostic if (func == F_READ) {
765152Ssam addr->utba = info;
775152Ssam addr->utcs1 = UT_RCOM | ((info>>8) & 0x30) | UT_GO;
78*49100Sbostic } else if (func == F_WRITE) {
795152Ssam addr->utba = info;
805152Ssam addr->utcs1 = UT_WCOM | ((info>>8) & 0x30) | UT_GO;
815152Ssam } else if (func == UT_SREV) {
825152Ssam addr->utcs1 = UT_SREV | UT_GO;
835152Ssam return (0);
845152Ssam } else
855152Ssam addr->utcs1 = func | UT_GO;
8633534Sbostic UTWAIT(addr);
875152Ssam ubafree(io, info);
885152Ssam word = addr->utds;
895152Ssam if (word&(UTDS_EOT|UTDS_TM)) {
905152Ssam addr->utcs1 = UT_CLEAR | UT_GO;
9111177Ssam goto done;
925152Ssam }
935152Ssam if ((word&UTDS_ERR) || (addr->utcs1&UT_TRE)) {
9433534Sbostic printf("ut error: cs1=%b er=%b cs2=%b ds=%b",
9533534Sbostic addr->utcs1, UT_BITS, addr->uter, UTER_BITS,
9633534Sbostic addr->utcs2, UTCS2_BITS, word, UTDS_BITS);
9733534Sbostic if (errcnt++ == 10) {
9833534Sbostic printf("ut: unrecovered error\n");
9911177Ssam return (-1);
1005152Ssam }
1015152Ssam if (addr->utcs1&UT_TRE)
1025152Ssam addr->utcs2 |= UTCS2_CLR;
1035152Ssam addr->utcs1 = UT_CLEAR | UT_GO;
1045152Ssam utstrategy(io, UT_SREV);
1055152Ssam utquiet(addr);
106*49100Sbostic if (func == F_WRITE) {
1075152Ssam addr->utcs1 = UT_ERASE | UT_GO;
10833534Sbostic UTWAIT(addr);
1095152Ssam }
1105152Ssam goto retry;
1115152Ssam }
1125152Ssam if (errcnt)
11333534Sbostic printf("ut: recovered by retry\n");
11411177Ssam done:
115*49100Sbostic if (func == F_READ) {
11611177Ssam resid = 0;
11711177Ssam if (io->i_cc > MASKREG(addr->utfc))
11811177Ssam resid = io->i_cc - MASKREG(addr->utfc);
11911177Ssam } else
12011177Ssam resid = MASKREG(-addr->utfc);
12111177Ssam return (io->i_cc - resid);
1225152Ssam }
1235152Ssam
12433534Sbostic static
utquiet(addr)1255152Ssam utquiet(addr)
1265152Ssam register struct utdevice *addr;
1275152Ssam {
1285152Ssam register u_short word;
1295152Ssam
13033534Sbostic UTWAIT(addr);
1315152Ssam do
1325152Ssam word = addr->utds;
1335152Ssam while ((word&UTDS_DRY) == 0 && (word&UTDS_PIP));
1345152Ssam }
135