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