1 /*
2 * Copyright (c) 1985, 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 * @(#)dmz.c 7.12 (Berkeley) 05/16/91
7 */
8
9 /*
10 * DMZ-32 driver
11 */
12
13 #include "dmz.h"
14 #if NDMZ > 0
15
16 #include "../include/pte.h"
17
18 #include "sys/param.h"
19 #include "uba.h"
20 #include "sys/conf.h"
21 #include "sys/user.h"
22 #include "sys/proc.h"
23 #include "sys/ioctl.h"
24 #include "sys/tty.h"
25 #include "sys/map.h"
26 #include "sys/buf.h"
27 #include "sys/vm.h"
28 #include "sys/clist.h"
29 #include "sys/file.h"
30 #include "sys/uio.h"
31 #include "sys/kernel.h"
32 #include "sys/syslog.h"
33
34 #include "dmx.h"
35 #include "ubareg.h"
36 #include "ubavar.h"
37 #include "dmxreg.h"
38 #include "dmzreg.h"
39 #include "dmreg.h"
40
41 extern int dmx_timeout; /* silo timeout, in ms */
42 int dmzstart();
43
44 /*
45 * The clist space is mapped by one terminal driver onto each UNIBUS.
46 * The identity of the board which allocated resources is recorded,
47 * so the process may be repeated after UNIBUS resets.
48 * The UBACVT macro converts a clist space address for unibus uban
49 * into an i/o space address for the DMA routine.
50 */
51 int dmz_uballoc[NUBA]; /* which dmz (if any) allocated unibus map */
52 int cbase[NUBA]; /* base address of clists in unibus map */
53
54 /*
55 * Autoconfiguration and variables for DMZ32
56 */
57 int dmzprobe(), dmzattach();
58 struct uba_device *dmzinfo[NDMZ];
59 u_short dmzstd[] = { 0 };
60 struct uba_driver dmzdriver = {
61 dmzprobe, 0, dmzattach, 0, dmzstd, "dmz", dmzinfo
62 };
63
64 struct tty dmz_tty[NDMZ*24];
65 struct dmx_softc dmz_softc[3 * NDMZ];
66 #ifndef lint
67 int ndmz = NDMZ*24; /* used by iostat */
68 #endif
69
dmzprobe(reg)70 dmzprobe(reg)
71 caddr_t reg;
72 {
73 register int br, cvec;
74 register struct dmzdevice *dmz_addr;
75 register unsigned int a;
76
77 dmz_addr = (struct dmzdevice *)reg;
78
79 #ifdef lint
80 br = 0; cvec = br; br = cvec; dmzxinta(0); dmzxintb(0); dmzxintc(0);
81 dmzrinta(0); dmzrintb(0); dmzrintc(0);
82 #endif
83
84 br = 0x15;
85
86 a = dmz_addr->dmz_config;
87 if (((a>>12) & ~DMZ_INTERFACE) != 0) {
88 printf(" Unknown interface type\n");
89 return (0);
90 }
91 if (((a>>8) & DMZ_NOC_MASK) != 3) {
92 printf(" Not all octets are available\n");
93 return (0);
94 }
95
96 cvec = (uba_hd[numuba].uh_lastiv -= 4 * 6);
97 dmz_addr->dmz_config = cvec >> 2;
98
99 return (sizeof(struct dmzdevice));
100 }
101
dmzattach(ui)102 dmzattach(ui)
103 register struct uba_device *ui;
104 {
105 register struct dmx_softc *sc;
106 register int i;
107
108 sc = &dmz_softc[3 * ui->ui_unit];
109 for (i = 0; i < 3; i++, sc++) {
110 sc->dmx_type = 'z';
111 sc->dmx_unit = ui->ui_unit;
112 sc->dmx_unit0 = 8 * i;
113 sc->dmx_ubanum = ui->ui_ubanum;
114 sc->dmx_softCAR = (ui->ui_flags >> (8 * i)) & 0xff;
115 sc->dmx_tty = &dmz_tty[((ui->ui_unit * 3) + i) * 8];
116 sc->dmx_octet = (struct dmx_octet *)
117 &((struct dmzdevice *)ui->ui_addr)->dmz_octet[i];
118 }
119
120 cbase[ui->ui_ubanum] = -1;
121 dmz_uballoc[ui->ui_ubanum] = -1;
122 }
123
124 /*
125 * Open a DMF32 line, mapping the clist onto the uba if this
126 * is the first dmf on this uba. Turn on this dmf if this is
127 * the first use of it.
128 */
129 /*ARGSUSED*/
dmzopen(dev,flag)130 dmzopen(dev, flag)
131 dev_t dev;
132 {
133 register struct tty *tp;
134 struct dmx_softc *sc;
135 int unit, dmz;
136 struct uba_device *ui;
137 int s;
138 int dmxparam();
139
140 unit = minor(dev);
141 dmz = DMZ(unit);
142 if (unit >= NDMZ*24 || (ui = dmzinfo[dmz])== 0 || ui->ui_alive == 0)
143 return (ENXIO);
144
145 tp = &dmz_tty[unit];
146 sc = &dmz_softc[unit / 8];
147 tp->t_addr = (caddr_t)sc->dmx_octet;
148 tp->t_oproc = dmzstart;
149 tp->t_dev = dev; /* needed before dmxopen */
150 tp->t_param = dmxparam;
151
152 /*
153 * While setting up state for this uba,
154 * block uba resets which can clear the state.
155 */
156 s = spl6();
157 if (cbase[ui->ui_ubanum] == -1) {
158 dmz_uballoc[ui->ui_ubanum] = dmz;
159 cbase[ui->ui_ubanum] = UBAI_ADDR(uballoc(ui->ui_ubanum,
160 (caddr_t)cfree, nclist*sizeof(struct cblock), 0));
161 }
162 splx(s);
163
164 return (dmxopen(tp, sc, flag));
165 }
166
167 /*
168 * Close a DMZ32 line.
169 */
170 /*ARGSUSED*/
dmzclose(dev,flag,mode,p)171 dmzclose(dev, flag, mode, p)
172 dev_t dev;
173 int flag, mode;
174 struct proc *p;
175 {
176
177 return (dmxclose(&dmz_tty[minor(dev)]), flag);
178 }
179
dmzread(dev,uio,flag)180 dmzread(dev, uio, flag)
181 dev_t dev;
182 struct uio *uio;
183 {
184 register struct tty *tp;
185
186 tp = &dmz_tty[minor(dev)];
187 return ((*linesw[tp->t_line].l_read)(tp, uio, flag));
188 }
189
dmzwrite(dev,uio)190 dmzwrite(dev, uio)
191 dev_t dev;
192 struct uio *uio;
193 {
194 register struct tty *tp;
195
196 tp = &dmz_tty[minor(dev)];
197 return ((*linesw[tp->t_line].l_write)(tp, uio));
198 }
199
200 /*
201 * DMZ32 receiver interrupts.
202 */
dmzrinta(dmz)203 dmzrinta(dmz)
204 int dmz;
205 {
206 struct uba_device *ui;
207
208 ui = dmzinfo[dmz];
209 if (ui == 0 || ui->ui_alive == 0)
210 return;
211 dmxrint(&dmz_softc[3 * dmz + 0]);
212 }
213
dmzrintb(dmz)214 dmzrintb(dmz)
215 int dmz;
216 {
217 struct uba_device *ui;
218
219 ui = dmzinfo[dmz];
220 if (ui == 0 || ui->ui_alive == 0)
221 return;
222 dmxrint(&dmz_softc[3 * dmz + 1]);
223 }
224
dmzrintc(dmz)225 dmzrintc(dmz)
226 int dmz;
227 {
228 struct uba_device *ui;
229
230 ui = dmzinfo[dmz];
231 if (ui == 0 || ui->ui_alive == 0)
232 return;
233 dmxrint(&dmz_softc[3 * dmz + 2]);
234 }
235
236 /*
237 * Ioctl for DMZ32.
238 */
dmzioctl(dev,cmd,data,flag)239 dmzioctl(dev, cmd, data, flag)
240 dev_t dev;
241 caddr_t data;
242 {
243 int unit = minor(dev);
244
245 return (dmxioctl(&dmz_tty[unit], cmd, data, flag));
246 }
247
248 /*
249 * DMZ32 transmitter interrupts.
250 */
dmzxinta(dmz)251 dmzxinta(dmz)
252 int dmz;
253 {
254
255 dmxxint(&dmz_softc[3 * dmz + 0]);
256 }
257
dmzxintb(dmz)258 dmzxintb(dmz)
259 int dmz;
260 {
261
262 dmxxint(&dmz_softc[3 * dmz + 1]);
263 }
264
dmzxintc(dmz)265 dmzxintc(dmz)
266 int dmz;
267 {
268
269 dmxxint(&dmz_softc[3 * dmz + 2]);
270 }
271
272 /*
273 * Start (restart) transmission on the given line.
274 */
275 dmzstart(tp)
276 struct tty *tp;
277 {
278
279 dmxstart(tp, &dmz_softc[minor(tp->t_dev) >> 3]);
280 }
281
282 /*
283 * Stop output on a line, e.g. for ^S/^Q or output flush.
284 */
285 dmzstop(tp, flag)
286 struct tty *tp;
287 {
288
289 dmxstop(tp, &dmz_softc[minor(tp->t_dev) >> 3], flag);
290 }
291
292 /*
293 * Reset state of driver if UBA reset was necessary.
294 * Reset the csr, lpr, and lcr registers on open lines, and
295 * restart transmitters.
296 */
dmzreset(uban)297 dmzreset(uban)
298 int uban;
299 {
300 register int dmz;
301 register struct tty *tp;
302 register struct uba_device *ui;
303 register struct dmzdevice *addr;
304 int i;
305
306 for (dmz = 0; dmz < NDMZ; dmz++) {
307 ui = dmzinfo[dmz];
308 if (ui == 0 || ui->ui_alive == 0 || ui->ui_ubanum != uban)
309 continue;
310 printf("dmz%d ", dmz);
311 addr = (struct dmzdevice *)ui->ui_addr;
312
313 if (dmz_uballoc[uban] == dmz) {
314 int info;
315
316 info = uballoc(uban, (caddr_t)cfree,
317 nclist * sizeof(struct cblock), UBA_CANTWAIT);
318 if (info)
319 cbase[uban] = UBAI_ADDR(info);
320 else {
321 printf(" [can't get uba map]");
322 cbase[uban] = -1;
323 }
324 }
325
326 for (i = 0; i < 3; i++)
327 if (dmz_softc[3 * dmz + i].dmx_flags & DMX_ACTIVE) {
328 addr->dmz_octet[i].csr = DMF_IE;
329 addr->dmz_octet[i].rsp = dmx_timeout;
330 }
331
332 /*
333 * If a unit is open or waiting for open to complete,
334 * reset it.
335 */
336 tp = &dmz_tty[dmz * 24];
337 for (i = 0; i < 24; i++, tp++) {
338 if (tp->t_state & (TS_ISOPEN | TS_WOPEN)) {
339 dmxparam(tp, &tp->t_termios);
340 (void) dmxmctl(tp, DMF_ON, DMSET);
341 tp->t_state &= ~TS_BUSY;
342 dmzstart(tp);
343 }
344 }
345 }
346 }
347 #endif
348