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