xref: /original-bsd/sys/vax/uba/dmz.c (revision c87c9427)
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.9 (Berkeley) 04/12/90
7  */
8 
9 /*
10  * DMZ-32 driver
11  */
12 
13 #include "dmz.h"
14 #if NDMZ > 0
15 
16 #include "machine/pte.h"
17 
18 #include "uba.h"
19 #include "param.h"
20 #include "conf.h"
21 #include "user.h"
22 #include "proc.h"
23 #include "ioctl.h"
24 #include "tty.h"
25 #include "map.h"
26 #include "buf.h"
27 #include "vm.h"
28 #include "bkmac.h"
29 #include "clist.h"
30 #include "file.h"
31 #include "uio.h"
32 #include "kernel.h"
33 #include "syslog.h"
34 
35 #include "dmx.h"
36 #include "ubareg.h"
37 #include "ubavar.h"
38 #include "dmxreg.h"
39 #include "dmzreg.h"
40 #include "dmreg.h"
41 
42 extern	int dmx_timeout;		/* silo timeout, in ms */
43 int	dmzstart();
44 
45 /*
46  * The clist space is mapped by one terminal driver onto each UNIBUS.
47  * The identity of the board which allocated resources is recorded,
48  * so the process may be repeated after UNIBUS resets.
49  * The UBACVT macro converts a clist space address for unibus uban
50  * into an i/o space address for the DMA routine.
51  */
52 int	dmz_uballoc[NUBA];	/* which dmz (if any) allocated unibus map */
53 int	cbase[NUBA];		/* base address of clists in unibus map */
54 
55 /*
56  * Autoconfiguration and variables for DMZ32
57  */
58 int dmzprobe(), dmzattach();
59 struct uba_device *dmzinfo[NDMZ];
60 u_short dmzstd[] = { 0 };
61 struct uba_driver dmzdriver = {
62 	dmzprobe, 0, dmzattach, 0, dmzstd, "dmz", dmzinfo
63 };
64 
65 struct	tty dmz_tty[NDMZ*24];
66 struct	dmx_softc dmz_softc[3 * NDMZ];
67 #ifndef lint
68 int	ndmz = NDMZ*24;			/* used by iostat */
69 #endif
70 
71 dmzprobe(reg)
72 	caddr_t reg;
73 {
74 	register int br, cvec;
75 	register struct dmzdevice *dmz_addr;
76 	register unsigned int a;
77 
78 	dmz_addr = (struct dmzdevice *)reg;
79 
80 #ifdef lint
81 	br = 0; cvec = br; br = cvec; dmzxinta(0); dmzxintb(0); dmzxintc(0);
82 	dmzrinta(0); dmzrintb(0); dmzrintc(0);
83 #endif
84 
85 	br = 0x15;
86 
87 	a = dmz_addr->dmz_config;
88 	if (((a>>12) & ~DMZ_INTERFACE) != 0) {
89 		printf("	Unknown interface type\n");
90 		return (0);
91 	}
92 	if (((a>>8) & DMZ_NOC_MASK) != 3) {
93 		printf("	Not all octets are available\n");
94 		return (0);
95 	}
96 
97 	cvec = (uba_hd[numuba].uh_lastiv -= 4 * 6);
98 	dmz_addr->dmz_config = cvec >> 2;
99 
100 	return (sizeof(struct dmzdevice));
101 }
102 
103 dmzattach(ui)
104 	register struct uba_device *ui;
105 {
106 	register struct dmx_softc *sc;
107 	register int i;
108 
109 	sc = &dmz_softc[3 * ui->ui_unit];
110 	for (i = 0; i < 3; i++, sc++) {
111 		sc->dmx_type = 'z';
112 		sc->dmx_unit = ui->ui_unit;
113 		sc->dmx_unit0 = 8 * i;
114 		sc->dmx_ubanum = ui->ui_ubanum;
115 		sc->dmx_softCAR = (ui->ui_flags >> (8 * i)) & 0xff;
116 		sc->dmx_tty = &dmz_tty[((ui->ui_unit * 3) + i) * 8];
117 		sc->dmx_octet = (struct dmx_octet *)
118 		    &((struct dmzdevice *)ui->ui_addr)->dmz_octet[i];
119 	}
120 
121 	cbase[ui->ui_ubanum] = -1;
122 	dmz_uballoc[ui->ui_ubanum] = -1;
123 }
124 
125 /*
126  * Open a DMF32 line, mapping the clist onto the uba if this
127  * is the first dmf on this uba.  Turn on this dmf if this is
128  * the first use of it.
129  */
130 /*ARGSUSED*/
131 dmzopen(dev, flag)
132 	dev_t dev;
133 {
134 	register struct tty *tp;
135 	struct dmx_softc *sc;
136 	int unit, dmz;
137 	struct uba_device *ui;
138 	int s;
139 	int dmxparam();
140 
141 	unit = minor(dev);
142 	dmz = DMZ(unit);
143 	if (unit >= NDMZ*24 || (ui = dmzinfo[dmz])== 0 || ui->ui_alive == 0)
144 		return (ENXIO);
145 
146 	tp = &dmz_tty[unit];
147 	sc = &dmz_softc[unit / 8];
148 	tp->t_addr = (caddr_t)sc->dmx_octet;
149 	tp->t_oproc = dmzstart;
150 	tp->t_dev = dev;			/* needed before dmxopen */
151 	tp->t_param = dmxparam;
152 
153 	/*
154 	 * While setting up state for this uba,
155 	 * block uba resets which can clear the state.
156 	 */
157 	s = spl6();
158 	if (cbase[ui->ui_ubanum] == -1) {
159 		dmz_uballoc[ui->ui_ubanum] = dmz;
160 		cbase[ui->ui_ubanum] = UBAI_ADDR(uballoc(ui->ui_ubanum,
161 		    (caddr_t)cfree, nclist*sizeof(struct cblock), 0));
162 	}
163 	splx(s);
164 
165 	return (dmxopen(tp, sc, flag));
166 }
167 
168 /*
169  * Close a DMZ32 line.
170  */
171 /*ARGSUSED*/
172 dmzclose(dev, flag)
173 	dev_t dev;
174 	int flag;
175 {
176 
177 	return (dmxclose(&dmz_tty[minor(dev)]));
178 }
179 
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 
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  */
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 
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 
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  */
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  */
251 dmzxinta(dmz)
252 	int dmz;
253 {
254 
255 	dmxxint(&dmz_softc[3 * dmz + 0]);
256 }
257 
258 dmzxintb(dmz)
259 	int dmz;
260 {
261 
262 	dmxxint(&dmz_softc[3 * dmz + 1]);
263 }
264 
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  */
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