xref: /original-bsd/sys/vax/uba/dmz.c (revision de3f5c4e)
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.11 (Berkeley) 05/09/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 
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 
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*/
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*/
171 dmzclose(dev, flag)
172 	dev_t dev;
173 	int flag;
174 {
175 
176 	return (dmxclose(&dmz_tty[minor(dev)]));
177 }
178 
179 dmzread(dev, uio, flag)
180 	dev_t dev;
181 	struct uio *uio;
182 {
183 	register struct tty *tp;
184 
185 	tp = &dmz_tty[minor(dev)];
186 	return ((*linesw[tp->t_line].l_read)(tp, uio, flag));
187 }
188 
189 dmzwrite(dev, uio)
190 	dev_t dev;
191 	struct uio *uio;
192 {
193 	register struct tty *tp;
194 
195 	tp = &dmz_tty[minor(dev)];
196 	return ((*linesw[tp->t_line].l_write)(tp, uio));
197 }
198 
199 /*
200  * DMZ32 receiver interrupts.
201  */
202 dmzrinta(dmz)
203 	int dmz;
204 {
205 	struct uba_device *ui;
206 
207 	ui = dmzinfo[dmz];
208 	if (ui == 0 || ui->ui_alive == 0)
209 		return;
210 	dmxrint(&dmz_softc[3 * dmz + 0]);
211 }
212 
213 dmzrintb(dmz)
214 	int dmz;
215 {
216 	struct uba_device *ui;
217 
218 	ui = dmzinfo[dmz];
219 	if (ui == 0 || ui->ui_alive == 0)
220 		return;
221 	dmxrint(&dmz_softc[3 * dmz + 1]);
222 }
223 
224 dmzrintc(dmz)
225 	int dmz;
226 {
227 	struct uba_device *ui;
228 
229 	ui = dmzinfo[dmz];
230 	if (ui == 0 || ui->ui_alive == 0)
231 		return;
232 	dmxrint(&dmz_softc[3 * dmz + 2]);
233 }
234 
235 /*
236  * Ioctl for DMZ32.
237  */
238 dmzioctl(dev, cmd, data, flag)
239 	dev_t dev;
240 	caddr_t data;
241 {
242 	int unit = minor(dev);
243 
244 	return (dmxioctl(&dmz_tty[unit], cmd, data, flag));
245 }
246 
247 /*
248  * DMZ32 transmitter interrupts.
249  */
250 dmzxinta(dmz)
251 	int dmz;
252 {
253 
254 	dmxxint(&dmz_softc[3 * dmz + 0]);
255 }
256 
257 dmzxintb(dmz)
258 	int dmz;
259 {
260 
261 	dmxxint(&dmz_softc[3 * dmz + 1]);
262 }
263 
264 dmzxintc(dmz)
265 	int dmz;
266 {
267 
268 	dmxxint(&dmz_softc[3 * dmz + 2]);
269 }
270 
271 /*
272  * Start (restart) transmission on the given line.
273  */
274 dmzstart(tp)
275 	struct tty *tp;
276 {
277 
278 	dmxstart(tp, &dmz_softc[minor(tp->t_dev) >> 3]);
279 }
280 
281 /*
282  * Stop output on a line, e.g. for ^S/^Q or output flush.
283  */
284 dmzstop(tp, flag)
285 	struct tty *tp;
286 {
287 
288 	dmxstop(tp, &dmz_softc[minor(tp->t_dev) >> 3], flag);
289 }
290 
291 /*
292  * Reset state of driver if UBA reset was necessary.
293  * Reset the csr, lpr, and lcr registers on open lines, and
294  * restart transmitters.
295  */
296 dmzreset(uban)
297 	int uban;
298 {
299 	register int dmz;
300 	register struct tty *tp;
301 	register struct uba_device *ui;
302 	register struct dmzdevice *addr;
303 	int i;
304 
305 	for (dmz = 0; dmz < NDMZ; dmz++) {
306 		ui = dmzinfo[dmz];
307 		if (ui == 0 || ui->ui_alive == 0 || ui->ui_ubanum != uban)
308 			continue;
309 		printf("dmz%d ", dmz);
310 		addr = (struct dmzdevice *)ui->ui_addr;
311 
312 		if (dmz_uballoc[uban] == dmz) {
313 			int info;
314 
315 			info = uballoc(uban, (caddr_t)cfree,
316 			    nclist * sizeof(struct cblock), UBA_CANTWAIT);
317 			if (info)
318 				cbase[uban] = UBAI_ADDR(info);
319 			else {
320 				printf(" [can't get uba map]");
321 				cbase[uban] = -1;
322 			}
323 		}
324 
325 		for (i = 0; i < 3; i++)
326 			if (dmz_softc[3 * dmz + i].dmx_flags & DMX_ACTIVE) {
327 				addr->dmz_octet[i].csr = DMF_IE;
328 				addr->dmz_octet[i].rsp = dmx_timeout;
329 			}
330 
331 		/*
332 		 * If a unit is open or waiting for open to complete,
333 		 * reset it.
334 		 */
335 		tp = &dmz_tty[dmz * 24];
336 		for (i = 0; i < 24; i++, tp++) {
337 			if (tp->t_state & (TS_ISOPEN | TS_WOPEN)) {
338 				dmxparam(tp, &tp->t_termios);
339 				(void) dmxmctl(tp, DMF_ON, DMSET);
340 				tp->t_state &= ~TS_BUSY;
341 				dmzstart(tp);
342 			}
343 		}
344 	}
345 }
346 #endif
347