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