xref: /csrg-svn/sys/vax/stand/ut.c (revision 33534)
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.3 (Berkeley) 02/22/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 		printf("ut: nonexistent device\n");
38 		return (ENXIO);
39 	}
40 	utstrategy(io, UT_REW);
41 	for (skip = io->i_part; skip--;)
42 		utstrategy(io, UT_SFORWF);
43 	return (0);
44 }
45 
46 utclose(io)
47 	register struct iob *io;
48 {
49 	utstrategy(io, UT_REW);
50 }
51 
52 #define	UTWAIT(addr) { \
53 	do \
54 		word = addr->utcs1; \
55 	while((word&UT_RDY) == 0); \
56 }
57 
58 utstrategy(io, func)
59 	register struct iob *io;
60 {
61 	register struct utdevice *addr;
62 	register u_short word;
63 	register int errcnt;
64 	int info, resid;
65 	u_short dens;
66 
67 	addr = (struct utdevice *)ubamem(io->i_unit, utstd[io->i_ctlr]);
68 	dens = io->i_unit | PDP11FMT | UT_PE;
69 	errcnt = 0;
70 retry:
71 	utquiet(addr);
72 	addr->uttc = dens;
73 	info = ubasetup(io, 1);
74 	addr->utwc = -((io->i_cc+1) >> 1);
75 	addr->utfc = -io->i_cc;
76 	if (func == READ) {
77 		addr->utba = info;
78 		addr->utcs1 = UT_RCOM | ((info>>8) & 0x30) | UT_GO;
79 	} else if (func == WRITE) {
80 		addr->utba = info;
81 		addr->utcs1 = UT_WCOM | ((info>>8) & 0x30) | UT_GO;
82 	} else if (func == UT_SREV) {
83 		addr->utcs1 = UT_SREV | UT_GO;
84 		return (0);
85 	} else
86 		addr->utcs1 = func | UT_GO;
87 	UTWAIT(addr);
88 	ubafree(io, info);
89 	word = addr->utds;
90 	if (word&(UTDS_EOT|UTDS_TM)) {
91 		addr->utcs1 = UT_CLEAR | UT_GO;
92 		goto done;
93 	}
94 	if ((word&UTDS_ERR) || (addr->utcs1&UT_TRE)) {
95 		printf("ut error: cs1=%b er=%b cs2=%b ds=%b",
96 		  addr->utcs1, UT_BITS, addr->uter, UTER_BITS,
97 		  addr->utcs2, UTCS2_BITS, word, UTDS_BITS);
98 		if (errcnt++ == 10) {
99 			printf("ut: unrecovered error\n");
100 			return (-1);
101 		}
102 		if (addr->utcs1&UT_TRE)
103 			addr->utcs2 |= UTCS2_CLR;
104 		addr->utcs1 = UT_CLEAR | UT_GO;
105 		utstrategy(io, UT_SREV);
106 		utquiet(addr);
107 		if (func == WRITE) {
108 			addr->utcs1 = UT_ERASE | UT_GO;
109 			UTWAIT(addr);
110 		}
111 		goto retry;
112 	}
113 	if (errcnt)
114 		printf("ut: recovered by retry\n");
115 done:
116 	if (func == READ) {
117 		resid = 0;
118 		if (io->i_cc > MASKREG(addr->utfc))
119 			resid = io->i_cc - MASKREG(addr->utfc);
120 	} else
121 		resid = MASKREG(-addr->utfc);
122 	return (io->i_cc - resid);
123 }
124 
125 static
126 utquiet(addr)
127 	register struct utdevice *addr;
128 {
129 	register u_short word;
130 
131 	UTWAIT(addr);
132 	do
133 		word = addr->utds;
134 	while ((word&UTDS_DRY) == 0 && (word&UTDS_PIP));
135 }
136