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