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