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.8 (Berkeley) 05/04/91
7 */
8
9 /*
10 * SI Model 9700 -- emulates TU45 on the UNIBUS
11 */
12
13 #include "sys/param.h"
14
15 #include "../include/pte.h"
16
17 #include "../uba/ubareg.h"
18 #include "../uba/utreg.h"
19
20 #include "stand/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
utopen(io)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
utclose(io)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
utstrategy(io,func)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 == F_READ) {
76 addr->utba = info;
77 addr->utcs1 = UT_RCOM | ((info>>8) & 0x30) | UT_GO;
78 } else if (func == F_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 == F_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 == F_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
utquiet(addr)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