xref: /original-bsd/sys/vax/stand/ut.c (revision 2bd07fe6)
1 /*
2  * Copyright (c) 1982, 1986, 1988 Regents of the University of California.
3  * All rights reserved.  The Berkeley software License Agreement
4  * specifies the terms and conditions for redistribution.
5  *
6  *	@(#)ut.c	7.6 (Berkeley) 04/04/90
7  */
8 
9 /*
10  * SI Model 9700 -- emulates TU45 on the UNIBUS
11  */
12 
13 #include "param.h"
14 
15 #include "../vax/pte.h"
16 
17 #include "../vaxuba/ubareg.h"
18 #include "../vaxuba/utreg.h"
19 
20 #include "saio.h"
21 #include "savax.h"
22 
23 #define	MASKREG(reg)	((reg)&0xffff)
24 
25 #define	MAXCTLR		1		/* all addresses must be specified */
26 u_short	utstd[MAXCTLR] = { 0172440 };	/* non-standard */
27 
28 utopen(io)
29 	register struct iob *io;
30 {
31 	register int skip;
32 
33 	if ((u_int)io->i_adapt >= nuba)
34 		return (EADAPT);
35 	if ((u_int)io->i_ctlr >= MAXCTLR)
36 		return (ECTLR);
37 	if (badaddr((char *)ubamem(io->i_unit, utstd[io->i_ctlr]), sizeof(short)))
38 		return (ENXIO);
39 	utstrategy(io, UT_REW);
40 	for (skip = io->i_part; skip--;)
41 		utstrategy(io, UT_SFORWF);
42 	return (0);
43 }
44 
45 utclose(io)
46 	register struct iob *io;
47 {
48 	utstrategy(io, UT_REW);
49 }
50 
51 #define	UTWAIT(addr) { \
52 	do \
53 		word = addr->utcs1; \
54 	while((word&UT_RDY) == 0); \
55 }
56 
57 utstrategy(io, func)
58 	register struct iob *io;
59 {
60 	register struct utdevice *addr;
61 	register u_short word;
62 	register int errcnt;
63 	int info, resid;
64 	u_short dens;
65 
66 	addr = (struct utdevice *)ubamem(io->i_unit, utstd[io->i_ctlr]);
67 	dens = io->i_unit | PDP11FMT | UT_PE;
68 	errcnt = 0;
69 retry:
70 	utquiet(addr);
71 	addr->uttc = dens;
72 	info = ubasetup(io, 1);
73 	addr->utwc = -((io->i_cc+1) >> 1);
74 	addr->utfc = -io->i_cc;
75 	if (func == READ) {
76 		addr->utba = info;
77 		addr->utcs1 = UT_RCOM | ((info>>8) & 0x30) | UT_GO;
78 	} else if (func == WRITE) {
79 		addr->utba = info;
80 		addr->utcs1 = UT_WCOM | ((info>>8) & 0x30) | UT_GO;
81 	} else if (func == UT_SREV) {
82 		addr->utcs1 = UT_SREV | UT_GO;
83 		return (0);
84 	} else
85 		addr->utcs1 = func | UT_GO;
86 	UTWAIT(addr);
87 	ubafree(io, info);
88 	word = addr->utds;
89 	if (word&(UTDS_EOT|UTDS_TM)) {
90 		addr->utcs1 = UT_CLEAR | UT_GO;
91 		goto done;
92 	}
93 	if ((word&UTDS_ERR) || (addr->utcs1&UT_TRE)) {
94 		printf("ut error: cs1=%b er=%b cs2=%b ds=%b",
95 		  addr->utcs1, UT_BITS, addr->uter, UTER_BITS,
96 		  addr->utcs2, UTCS2_BITS, word, UTDS_BITS);
97 		if (errcnt++ == 10) {
98 			printf("ut: unrecovered error\n");
99 			return (-1);
100 		}
101 		if (addr->utcs1&UT_TRE)
102 			addr->utcs2 |= UTCS2_CLR;
103 		addr->utcs1 = UT_CLEAR | UT_GO;
104 		utstrategy(io, UT_SREV);
105 		utquiet(addr);
106 		if (func == WRITE) {
107 			addr->utcs1 = UT_ERASE | UT_GO;
108 			UTWAIT(addr);
109 		}
110 		goto retry;
111 	}
112 	if (errcnt)
113 		printf("ut: recovered by retry\n");
114 done:
115 	if (func == READ) {
116 		resid = 0;
117 		if (io->i_cc > MASKREG(addr->utfc))
118 			resid = io->i_cc - MASKREG(addr->utfc);
119 	} else
120 		resid = MASKREG(-addr->utfc);
121 	return (io->i_cc - resid);
122 }
123 
124 static
125 utquiet(addr)
126 	register struct utdevice *addr;
127 {
128 	register u_short word;
129 
130 	UTWAIT(addr);
131 	do
132 		word = addr->utds;
133 	while ((word&UTDS_DRY) == 0 && (word&UTDS_PIP));
134 }
135