s/tp->t_char/tp->t_chan/
[unix-history] / usr / src / sys / vax / uba / dz.c
CommitLineData
dc44829a 1/* dz.c 3.6 %H% */
5074fa57
BJ
2
3/*
4 * DZ-11 Driver
5 */
6#include "../h/param.h"
7#include "../h/systm.h"
8#include "../h/tty.h"
9#include "../h/dir.h"
10#include "../h/user.h"
11#include "../h/map.h"
12#include "../h/pte.h"
13#include "../h/uba.h"
14#include "../h/conf.h"
15#include "../h/pdma.h"
771d8988 16#include "../h/bk.h"
d3ebf5ee
BJ
17
18/*
19 * When running dz's using only SAE (silo alarm) on input
20 * it is necessary to call dzrint() at clock interrupt time.
21 * This is unsafe unless spl5()s in tty code are changed to
22 * spl6()s to block clock interrupts. Note that the dh driver
23 * currently in use works the same way as the dz, even though
24 * we could try to more intelligently manage its silo.
25 * Thus don't take this out if you have no dz's unless you
26 * change clock.c and dhtimer().
27 */
28#define spl5 spl6
5074fa57
BJ
29
30#define DZADDR (UBA0_DEV + 0160100)
31#ifdef ERNIE
32#define NDZ (3*8)
33#else
34#define NDZ (8)
35#endif
36
37#define BITS7 020
38#define BITS8 030
39#define TWOSB 040
40#define PENABLE 0100
41#define OPAR 0200
42#define MSE 040 /* Master Scan Enable */
43#define RIE 0100 /* Receiver Interrupt Enable */
9dca4f86
BJ
44#define SAE 010000 /* Silo Alarm Enable */
45#define TIE 040000 /* Transmit Interrupt Enable */
46#define DZ_IEN (MSE+RIE+TIE+SAE)
5074fa57
BJ
47#define PERROR 010000
48#define FRERROR 020000
9dca4f86 49#define OVERRUN 040000
5074fa57
BJ
50#define SSPEED 7 /* std speed = 300 baud */
51
52
53#define dzlpr dzrbuf
54#define dzmsr dzbrk
55#define ON 1
56#define OFF 0
57
58int dzstart();
59int dzxint();
771d8988 60int ttrstrt();
5074fa57
BJ
61struct tty dz_tty[NDZ];
62int dz_cnt = { NDZ };
9dca4f86 63int dzact;
5074fa57
BJ
64
65struct device {
66 short dzcsr;
67 short dzrbuf;
68 char dztcr;
69 char dzdtr;
70 char dztbuf;
71 char dzbrk;
72};
73
74struct pdma dzpdma[] = {
75 (struct device *)(DZADDR), NULL, NULL, (int)&dz_tty[0], dzxint,
76 (struct device *)(DZADDR), NULL, NULL, (int)&dz_tty[1], dzxint,
77 (struct device *)(DZADDR), NULL, NULL, (int)&dz_tty[2], dzxint,
78 (struct device *)(DZADDR), NULL, NULL, (int)&dz_tty[3], dzxint,
79 (struct device *)(DZADDR), NULL, NULL, (int)&dz_tty[4], dzxint,
80 (struct device *)(DZADDR), NULL, NULL, (int)&dz_tty[5], dzxint,
81 (struct device *)(DZADDR), NULL, NULL, (int)&dz_tty[6], dzxint,
82 (struct device *)(DZADDR), NULL, NULL, (int)&dz_tty[7], dzxint,
83#ifdef ERNIE
84 (struct device *)(DZADDR+010), NULL, NULL, (int)&dz_tty[8], dzxint,
85 (struct device *)(DZADDR+010), NULL, NULL, (int)&dz_tty[9], dzxint,
86 (struct device *)(DZADDR+010), NULL, NULL, (int)&dz_tty[10], dzxint,
87 (struct device *)(DZADDR+010), NULL, NULL, (int)&dz_tty[11], dzxint,
88 (struct device *)(DZADDR+010), NULL, NULL, (int)&dz_tty[12], dzxint,
89 (struct device *)(DZADDR+010), NULL, NULL, (int)&dz_tty[13], dzxint,
90 (struct device *)(DZADDR+010), NULL, NULL, (int)&dz_tty[14], dzxint,
91 (struct device *)(DZADDR+010), NULL, NULL, (int)&dz_tty[15], dzxint,
92 (struct device *)(DZADDR+020), NULL, NULL, (int)&dz_tty[16], dzxint,
93 (struct device *)(DZADDR+020), NULL, NULL, (int)&dz_tty[17], dzxint,
94 (struct device *)(DZADDR+020), NULL, NULL, (int)&dz_tty[18], dzxint,
95 (struct device *)(DZADDR+020), NULL, NULL, (int)&dz_tty[19], dzxint,
96 (struct device *)(DZADDR+020), NULL, NULL, (int)&dz_tty[20], dzxint,
97 (struct device *)(DZADDR+020), NULL, NULL, (int)&dz_tty[21], dzxint,
98 (struct device *)(DZADDR+020), NULL, NULL, (int)&dz_tty[22], dzxint,
99 (struct device *)(DZADDR+020), NULL, NULL, (int)&dz_tty[23], dzxint,
100#endif
101};
102char dz_timer;
103char dz_speeds[] = {
104 0, 020 , 021 , 022 , 023 , 024 , 0, 025,
105 026 , 027 , 030 , 032 , 034 , 036 , 0 , 0,
106};
107
108/*ARGSUSED*/
109dzopen(d, flag)
110{
111 register struct tty *tp;
112 register dev;
113 extern dzscan();
114
115 dev = minor(d);
116 if (dev >= dz_cnt) {
117 u.u_error = ENXIO;
118 return;
119 }
120 if (dz_timer == 0) {
121 dz_timer++;
122 timeout(dzscan, (caddr_t)0, 60);
123 }
124 tp = &dz_tty[dev];
125 tp->t_addr = (caddr_t)&dzpdma[dev];
126 tp->t_oproc = dzstart;
127 tp->t_iproc = NULL;
128 tp->t_state |= WOPEN;
129 if ((tp->t_state & ISOPEN) == 0) {
130 ttychars(tp);
131 tp->t_ospeed = tp->t_ispeed = SSPEED;
132 tp->t_flags = ODDP|EVENP|ECHO;
133 /*tp->t_state |= HUPCLS;*/
134 dzparam(dev);
135 } else if (tp->t_state&XCLUDE && u.u_uid != 0) {
136 u.u_error = EBUSY;
137 return;
138 }
139 dzmodem(dev, ON);
771d8988 140 (void) spl5();
5074fa57
BJ
141 while ((tp->t_state & CARR_ON) == 0) {
142 tp->t_state |= WOPEN;
143 sleep((caddr_t)&tp->t_rawq, TTIPRI);
144 }
771d8988 145 (void) spl0();
5074fa57
BJ
146 (*linesw[tp->t_line].l_open)(d, tp);
147}
148
149dzclose(d)
150{
151 register struct tty *tp;
152 register dev;
153
154 dev = minor(d);
155 tp = &dz_tty[dev];
156 (*linesw[tp->t_line].l_close)(tp);
157 if (tp->t_state & HUPCLS)
158 dzmodem(dev, OFF);
159 ttyclose(tp);
160}
161
162dzread(d)
163{
164 register struct tty *tp;
165
166 tp = &dz_tty[minor(d)];
167 (*linesw[tp->t_line].l_read)(tp);
168}
169
170dzwrite(d)
171{
172 register struct tty *tp;
173
174 tp = &dz_tty[minor(d)];
175 (*linesw[tp->t_line].l_write)(tp);
176}
177
9dca4f86 178/*ARGSUSED*/
5074fa57
BJ
179dzrint(dev)
180{
181 register struct tty *tp;
182 register int c;
183 register struct device *dzaddr;
9dca4f86 184 register struct tty *tp0;
5c6adb3e 185 int s;
5074fa57 186
5c6adb3e 187 s = spl6(); /* see comment in clock.c */
9dca4f86
BJ
188 /* as long as we are here, service them all */
189 for (dev = 0; dev < NDZ; dev += 8) {
190 if ((dzact & (1<<(dev>>3))) == 0)
5074fa57 191 continue;
9dca4f86
BJ
192 dzaddr = dzpdma[dev].p_addr;
193 tp0 = &dz_tty[dev];
194 while ((c = dzaddr->dzrbuf) < 0) { /* char present */
195 tp = tp0 + ((c>>8)&07);
196 if (tp >= &dz_tty[dz_cnt])
5074fa57 197 continue;
9dca4f86
BJ
198 if ((tp->t_state & ISOPEN) == 0) {
199 wakeup((caddr_t)&tp->t_rawq);
200 continue;
201 }
202 if (c&FRERROR)
203 /* framing error = break */
204 if (tp->t_flags & RAW)
205 c = 0; /* null for getty */
206 else
dc44829a
BJ
207#ifdef IIASA
208 continue;
209#else
210 c = 0177; /* tun.t_intrc? */
211#endif
9dca4f86
BJ
212 if (c&OVERRUN)
213 printf("o");
214 if (c&PERROR)
215 /* parity error */
216 if (((tp->t_flags & (EVENP|ODDP)) == EVENP)
217 || ((tp->t_flags & (EVENP|ODDP)) == ODDP))
218 continue;
5c6adb3e 219 if (tp->t_line == NETLDISC) {
771d8988 220 c &= 0177;
dc44829a 221 BKINPUT(c, tp);
771d8988 222 } else
771d8988 223 (*linesw[tp->t_line].l_rint)(c, tp);
9dca4f86 224 }
5074fa57 225 }
5c6adb3e 226 splx(s);
5074fa57
BJ
227}
228
229/*ARGSUSED*/
230dzioctl(dev, cmd, addr, flag)
231caddr_t addr;
232dev_t dev;
233{
234 register struct tty *tp;
235
236 tp = &dz_tty[minor(dev)];
771d8988
BJ
237 cmd = (*linesw[tp->t_line].l_ioctl)(tp, cmd, addr);
238 if (cmd == 0)
239 return;
5074fa57
BJ
240 if (ttioccomm(cmd, tp, addr, dev)) {
241 if (cmd==TIOCSETP || cmd==TIOCSETN)
242 dzparam(minor(dev));
dc44829a
BJ
243 } else switch(cmd) {
244 case TIOCSBRK:
245 ((struct device *)(tp->t_addr))->dzbrk |= 1 << (dev&07);
246 break;
247 case TIOCCBRK:
248 ((struct device *)(tp->t_addr))->dzbrk &= ~(1 << (dev&07));
249 break;
250 case TIOCSDTR:
251 dzmodem(dev, ON);
252 break;
253 case TIOCCDTR:
254 dzmodem(dev, OFF);
255 break;
256 default:
5074fa57 257 u.u_error = ENOTTY;
dc44829a 258 }
5074fa57
BJ
259}
260
261dzparam(dev)
262{
263 register struct tty *tp;
264 register struct device *dzaddr;
265 register short lpr;
266
267 tp = &dz_tty[dev];
268 dzaddr = dzpdma[dev].p_addr;
269 dzaddr->dzcsr = DZ_IEN;
9dca4f86 270 dzact |= (1<<(dev>>3));
5074fa57
BJ
271 if (tp->t_ispeed == 0) {
272 dzmodem(dev, OFF); /* hang up line */
273 return;
274 }
275 lpr = (dz_speeds[tp->t_ispeed]<<8) | (dev & 07);
276 if (tp->t_flags & RAW)
277 lpr |= BITS8;
278 else
279 lpr |= (BITS7|PENABLE);
280 if ((tp->t_flags & EVENP) == 0)
281 lpr |= OPAR;
282 if (tp->t_ispeed == 3)
283 lpr |= TWOSB; /* 110 baud: 2 stop bits */
284 dzaddr->dzlpr = lpr;
285}
286
287dzxint(tp)
288register struct tty *tp;
289{
290 register struct pdma *dp;
d3ebf5ee
BJ
291 register s;
292 s = spl6(); /* block the clock */
5074fa57
BJ
293
294 dp = &dzpdma[tp-dz_tty];
295 tp->t_state &= ~BUSY;
296 if (tp->t_state & FLUSH)
297 tp->t_state &= ~FLUSH;
298 else
299 ndflush(&tp->t_outq, dp->p_end-tp->t_outq.c_cf);
300 if (tp->t_line)
301 (*linesw[tp->t_line].l_start)(tp);
302 else
303 dzstart(tp);
304 if (tp->t_outq.c_cc == 0 || (tp->t_state&BUSY)==0)
305 dp->p_addr->dztcr &= ~(1 << ((tp-dz_tty) % 8));
d3ebf5ee 306 splx(s);
5074fa57
BJ
307}
308
309dzstart(tp)
310register struct tty *tp;
311{
312 register struct pdma *dp;
313 register struct device *dzaddr;
314 register cc;
315 int sps;
5074fa57
BJ
316
317 dp = &dzpdma[tp-dz_tty];
318 dzaddr = dp->p_addr;
319 sps = spl5();
320 if (tp->t_state & (TIMEOUT|BUSY|TTSTOP))
321 goto out;
322 if (tp->t_outq.c_cc <= TTLOWAT && tp->t_state&ASLEEP) {
323 tp->t_state &= ~ASLEEP;
324 if (tp->t_chan)
325 mcstart(tp->t_chan, (caddr_t)&tp->t_outq);
326 else
327 wakeup((caddr_t)&tp->t_outq);
328 }
329 if (tp->t_outq.c_cc == 0)
330 goto out;
331 if (tp->t_flags&RAW)
332 cc = ndqb(&tp->t_outq, 0);
333 else {
334 cc = ndqb(&tp->t_outq, 0200);
335 if (cc == 0) {
336 cc = getc(&tp->t_outq);
337 timeout(ttrstrt, (caddr_t)tp, (cc&0177) + 6);
338 tp->t_state |= TIMEOUT;
339 goto out;
340 }
341 }
342 tp->t_state |= BUSY;
343 dp->p_end = dp->p_mem = tp->t_outq.c_cf;
344 dp->p_end += cc;
345 dzaddr->dztcr |= 1 << ((tp-dz_tty) % 8);
346 out:
347 splx(sps);
348}
349
350/*
351 * Stop output on a line.
352 * Assume call is made at spl6.
353 */
354/*ARGSUSED*/
355dzstop(tp, flag)
356register struct tty *tp;
357{
358 register struct pdma *dp;
359 register int s;
360
361 dp = &dzpdma[tp-dz_tty];
362 s = spl6();
363 if (tp->t_state & BUSY) {
364 dp->p_end = dp->p_mem;
365 if ((tp->t_state&TTSTOP)==0) {
366 tp->t_state |= FLUSH;
367 }
368 }
369 splx(s);
370}
371
372dzmodem(dev, flag)
373register int dev;
374{
375 register struct device *dzaddr;
376 register char bit;
377
378 dzaddr = dzpdma[dev].p_addr;
379 bit = 1<<(dev&07);
380 if (flag == OFF)
381 dzaddr->dzdtr &= ~bit;
382 else
383 dzaddr->dzdtr |= bit;
384}
385
386dzscan()
387{
388 register i;
389 register struct device *dzaddr;
390 register bit;
391 register struct tty *tp;
392
393 for (i = 0; i < dz_cnt ; i++) {
394 dzaddr = dzpdma[i].p_addr;
395 tp = &dz_tty[i];
396 bit = 1<<(i&07);
397 if (dzaddr->dzmsr & bit) {
398 /* carrier present */
399 if ((tp->t_state & CARR_ON) == 0) {
400 wakeup((caddr_t)&tp->t_rawq);
401 tp->t_state |= CARR_ON;
402 }
403 } else {
404 if ((tp->t_state & CARR_ON)) {
405 /* carrier lost */
dc44829a
BJ
406 if (tp->t_state&ISOPEN &&
407 (tp->t_local&LNOHANG) == 0) {
408 gsignal(tp->t_pgrp, SIGHUP);
409 dzaddr->dzdtr &= ~bit;
410 flushtty(tp);
411 }
412 tp->t_state &= ~CARR_ON;
5074fa57 413 }
5074fa57
BJ
414 }
415 }
416 timeout(dzscan, (caddr_t)0, 2*HZ);
417}
9dca4f86
BJ
418
419dztimer()
420{
421
422 dzrint(0);
423}