Commit | Line | Data |
---|---|---|
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 | ||
57 | int dzstart(); | |
58 | int dzxint(); | |
771d8988 | 59 | int ttrstrt(); |
5074fa57 BJ |
60 | struct tty dz_tty[NDZ]; |
61 | int dz_cnt = { NDZ }; | |
9dca4f86 | 62 | int dzact; |
5074fa57 BJ |
63 | |
64 | struct device { | |
65 | short dzcsr; | |
66 | short dzrbuf; | |
67 | char dztcr; | |
68 | char dzdtr; | |
69 | char dztbuf; | |
70 | char dzbrk; | |
71 | }; | |
72 | ||
73 | struct 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 | }; |
113 | char dz_timer; | |
114 | char dz_speeds[] = { | |
115 | 0, 020 , 021 , 022 , 023 , 024 , 0, 025, | |
116 | 026 , 027 , 030 , 032 , 034 , 036 , 0 , 0, | |
117 | }; | |
e60fc718 | 118 | char dz_brk[NDZ11]; |
5074fa57 BJ |
119 | |
120 | /*ARGSUSED*/ | |
121 | dzopen(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 | ||
161 | dzclose(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 | ||
180 | dzread(d) | |
181 | { | |
182 | register struct tty *tp; | |
183 | ||
184 | tp = &dz_tty[minor(d)]; | |
185 | (*linesw[tp->t_line].l_read)(tp); | |
186 | } | |
187 | ||
188 | dzwrite(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 |
197 | dzrint(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*/ | |
248 | dzioctl(dev, cmd, addr, flag) | |
249 | caddr_t addr; | |
250 | dev_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 | ||
281 | dzparam(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 | ||
318 | dzxint(tp) | |
319 | register 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 | ||
340 | dzstart(tp) | |
341 | register 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*/ | |
386 | dzstop(tp, flag) | |
387 | register 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 | ||
403 | dzmodem(dev, flag) | |
404 | register 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 | ||
417 | dzscan() | |
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 | |
450 | dztimer() | |
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 | */ |
460 | dzreset() | |
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 |