Commit | Line | Data |
---|---|---|
da7c5cc6 KM |
1 | /* |
2 | * Copyright (c) 1982 Regents of the University of California. | |
3 | * All rights reserved. The Berkeley software License Agreement | |
4 | * specifies the terms and conditions for redistribution. | |
5 | * | |
74bfa0d5 | 6 | * @(#)dz.c 6.10 (Berkeley) %G% |
da7c5cc6 | 7 | */ |
5074fa57 | 8 | |
66b4fb09 | 9 | #include "dz.h" |
a3cb8f60 | 10 | #if NDZ > 0 |
5074fa57 | 11 | /* |
4abcd051 | 12 | * DZ-11/DZ-32 Driver |
7e00c42b BJ |
13 | * |
14 | * This driver mimics dh.c; see it for explanation of common code. | |
5074fa57 | 15 | */ |
e2c4935e | 16 | #include "bk.h" |
961945a8 SL |
17 | |
18 | #include "../machine/pte.h" | |
19 | ||
52163dab JB |
20 | #include "param.h" |
21 | #include "systm.h" | |
22 | #include "ioctl.h" | |
23 | #include "tty.h" | |
24 | #include "dir.h" | |
25 | #include "user.h" | |
26 | #include "proc.h" | |
27 | #include "map.h" | |
28 | #include "buf.h" | |
29 | #include "vm.h" | |
30 | #include "conf.h" | |
31 | #include "bkmac.h" | |
32 | #include "file.h" | |
33 | #include "uio.h" | |
34 | #include "kernel.h" | |
b50ce881 | 35 | #include "syslog.h" |
d3ebf5ee | 36 | |
52163dab JB |
37 | #include "pdma.h" |
38 | #include "ubavar.h" | |
39 | #include "dzreg.h" | |
896962b1 | 40 | |
7e00c42b BJ |
41 | /* |
42 | * Driver information for auto-configuration stuff. | |
43 | */ | |
71236e46 | 44 | int dzprobe(), dzattach(), dzrint(); |
6a1a96ff | 45 | struct uba_device *dzinfo[NDZ]; |
3f3a34c3 | 46 | u_short dzstd[] = { 0 }; |
3f3a34c3 | 47 | struct uba_driver dzdriver = |
71236e46 | 48 | { dzprobe, 0, dzattach, 0, dzstd, "dz", dzinfo }; |
3f3a34c3 | 49 | |
a3cb8f60 | 50 | #define NDZLINE (NDZ*8) |
acd2f01b | 51 | #define FASTTIMER (hz/30) /* rate to drain silos, when in use */ |
bea90e0b | 52 | |
7e00c42b | 53 | int dzstart(), dzxint(), dzdma(); |
771d8988 | 54 | int ttrstrt(); |
a3cb8f60 BJ |
55 | struct tty dz_tty[NDZLINE]; |
56 | int dz_cnt = { NDZLINE }; | |
9dca4f86 | 57 | int dzact; |
acd2f01b MK |
58 | int dzsilos; /* mask of dz's with silo in use */ |
59 | int dzchars[NDZ]; /* recent input count */ | |
60 | int dzrate[NDZ]; /* smoothed input count */ | |
61 | int dztimerintvl; /* time interval for dztimer */ | |
62 | int dzhighrate = 100; /* silo on if dzchars > dzhighrate */ | |
63 | int dzlowrate = 75; /* silo off if dzrate < dzlowrate */ | |
5074fa57 | 64 | |
bea90e0b BJ |
65 | #define dzwait(x) while (((x)->dzlcs & DZ_ACK) == 0) |
66 | ||
7e00c42b BJ |
67 | /* |
68 | * Software copy of dzbrk since it isn't readable | |
69 | */ | |
a3cb8f60 BJ |
70 | char dz_brk[NDZ]; |
71 | char dzsoftCAR[NDZ]; | |
bea90e0b | 72 | char dz_lnen[NDZ]; /* saved line enable bits for DZ32 */ |
5074fa57 | 73 | |
7e00c42b | 74 | /* |
bea90e0b | 75 | * The dz11 doesn't interrupt on carrier transitions, so |
7e00c42b BJ |
76 | * we have to use a timer to watch it. |
77 | */ | |
78 | char dz_timer; /* timer started? */ | |
79 | ||
80 | /* | |
81 | * Pdma structures for fast output code | |
82 | */ | |
a3cb8f60 | 83 | struct pdma dzpdma[NDZLINE]; |
7e00c42b | 84 | |
3f3a34c3 | 85 | char dz_speeds[] = |
57644725 | 86 | { 0,020,021,022,023,024,0,025,026,027,030,032,034,036,037,0 }; |
5074fa57 | 87 | |
74bfa0d5 MK |
88 | #ifndef PORTSELECTOR |
89 | #define ISPEED B9600 | |
df07bd9e SL |
90 | #define IFLAGS (EVENP|ODDP|ECHO) |
91 | #else | |
92 | #define ISPEED B4800 | |
93 | #define IFLAGS (EVENP|ODDP) | |
94 | #endif | |
95 | ||
71236e46 | 96 | dzprobe(reg) |
3f3a34c3 BJ |
97 | caddr_t reg; |
98 | { | |
88d5b764 | 99 | register int br, cvec; |
4abcd051 | 100 | register struct dzdevice *dzaddr = (struct dzdevice *)reg; |
3f3a34c3 | 101 | |
71236e46 | 102 | #ifdef lint |
a0eab615 | 103 | br = 0; cvec = br; br = cvec; |
89b8a44c | 104 | dzrint(0); dzxint((struct tty *)0); |
71236e46 | 105 | #endif |
bea90e0b BJ |
106 | dzaddr->dzcsr = DZ_TIE|DZ_MSE|DZ_32; |
107 | if (dzaddr->dzcsr & DZ_32) | |
108 | dzaddr->dzlnen = 1; | |
109 | else | |
110 | dzaddr->dztcr = 1; /* enable any line */ | |
88d5b764 | 111 | DELAY(100000); |
bea90e0b | 112 | dzaddr->dzcsr = DZ_CLR|DZ_32; /* reset everything */ |
88d5b764 BJ |
113 | if (cvec && cvec != 0x200) |
114 | cvec -= 4; | |
4abcd051 | 115 | return (sizeof (struct dzdevice)); |
3f3a34c3 BJ |
116 | } |
117 | ||
71236e46 | 118 | dzattach(ui) |
6a1a96ff | 119 | register struct uba_device *ui; |
3f3a34c3 BJ |
120 | { |
121 | register struct pdma *pdp = &dzpdma[ui->ui_unit*8]; | |
122 | register struct tty *tp = &dz_tty[ui->ui_unit*8]; | |
71236e46 | 123 | register int cntr; |
a3cb8f60 | 124 | extern dzscan(); |
3f3a34c3 | 125 | |
71236e46 | 126 | for (cntr = 0; cntr < 8; cntr++) { |
4abcd051 | 127 | pdp->p_addr = (struct dzdevice *)ui->ui_addr; |
3f3a34c3 BJ |
128 | pdp->p_arg = (int)tp; |
129 | pdp->p_fcn = dzxint; | |
130 | pdp++, tp++; | |
131 | } | |
7e286c72 | 132 | dzsoftCAR[ui->ui_unit] = ui->ui_flags; |
be2b272c BJ |
133 | if (dz_timer == 0) { |
134 | dz_timer++; | |
7780575a | 135 | timeout(dzscan, (caddr_t)0, hz); |
acd2f01b | 136 | dztimerintvl = FASTTIMER; |
be2b272c | 137 | } |
3f3a34c3 BJ |
138 | } |
139 | ||
5074fa57 | 140 | /*ARGSUSED*/ |
3f3a34c3 BJ |
141 | dzopen(dev, flag) |
142 | dev_t dev; | |
5074fa57 BJ |
143 | { |
144 | register struct tty *tp; | |
3f3a34c3 | 145 | register int unit; |
5074fa57 | 146 | |
3f3a34c3 | 147 | unit = minor(dev); |
7da157da BJ |
148 | if (unit >= dz_cnt || dzpdma[unit].p_addr == 0) |
149 | return (ENXIO); | |
3f3a34c3 BJ |
150 | tp = &dz_tty[unit]; |
151 | tp->t_addr = (caddr_t)&dzpdma[unit]; | |
5074fa57 | 152 | tp->t_oproc = dzstart; |
941944c9 | 153 | if ((tp->t_state & TS_ISOPEN) == 0) { |
5074fa57 | 154 | ttychars(tp); |
df07bd9e SL |
155 | tp->t_ospeed = tp->t_ispeed = ISPEED; |
156 | tp->t_flags = IFLAGS; | |
941944c9 | 157 | /* tp->t_state |= TS_HUPCLS; */ |
3f3a34c3 | 158 | dzparam(unit); |
7da157da BJ |
159 | } else if (tp->t_state&TS_XCLUDE && u.u_uid != 0) |
160 | return (EBUSY); | |
668cc26d | 161 | (void) dzmctl(dev, DZ_ON, DMSET); |
771d8988 | 162 | (void) spl5(); |
941944c9 BJ |
163 | while ((tp->t_state & TS_CARR_ON) == 0) { |
164 | tp->t_state |= TS_WOPEN; | |
5074fa57 BJ |
165 | sleep((caddr_t)&tp->t_rawq, TTIPRI); |
166 | } | |
771d8988 | 167 | (void) spl0(); |
7da157da | 168 | return ((*linesw[tp->t_line].l_open)(dev, tp)); |
5074fa57 BJ |
169 | } |
170 | ||
3f3a34c3 BJ |
171 | /*ARGSUSED*/ |
172 | dzclose(dev, flag) | |
173 | dev_t dev; | |
5074fa57 BJ |
174 | { |
175 | register struct tty *tp; | |
3f3a34c3 | 176 | register int unit; |
4abcd051 | 177 | register struct dzdevice *dzaddr; |
fa627691 | 178 | int dz; |
5074fa57 | 179 | |
3f3a34c3 BJ |
180 | unit = minor(dev); |
181 | dz = unit >> 3; | |
182 | tp = &dz_tty[unit]; | |
5074fa57 | 183 | (*linesw[tp->t_line].l_close)(tp); |
bea90e0b BJ |
184 | dzaddr = dzpdma[unit].p_addr; |
185 | if (dzaddr->dzcsr&DZ_32) | |
668cc26d | 186 | (void) dzmctl(dev, DZ_BRK, DMBIC); |
bea90e0b BJ |
187 | else |
188 | dzaddr->dzbrk = (dz_brk[dz] &= ~(1 << (unit&07))); | |
4f5daa2a | 189 | if ((tp->t_state&(TS_HUPCLS|TS_WOPEN)) || (tp->t_state&TS_ISOPEN) == 0) |
668cc26d | 190 | (void) dzmctl(dev, DZ_OFF, DMSET); |
5074fa57 BJ |
191 | ttyclose(tp); |
192 | } | |
193 | ||
740e4029 | 194 | dzread(dev, uio) |
3f3a34c3 | 195 | dev_t dev; |
740e4029 | 196 | struct uio *uio; |
5074fa57 BJ |
197 | { |
198 | register struct tty *tp; | |
199 | ||
3f3a34c3 | 200 | tp = &dz_tty[minor(dev)]; |
740e4029 | 201 | return ((*linesw[tp->t_line].l_read)(tp, uio)); |
5074fa57 BJ |
202 | } |
203 | ||
406ddcbe | 204 | dzwrite(dev, uio) |
3f3a34c3 | 205 | dev_t dev; |
406ddcbe | 206 | struct uio *uio; |
5074fa57 BJ |
207 | { |
208 | register struct tty *tp; | |
209 | ||
3f3a34c3 | 210 | tp = &dz_tty[minor(dev)]; |
078d920f | 211 | return ((*linesw[tp->t_line].l_write)(tp, uio)); |
5074fa57 BJ |
212 | } |
213 | ||
9dca4f86 | 214 | /*ARGSUSED*/ |
3f3a34c3 BJ |
215 | dzrint(dz) |
216 | int dz; | |
5074fa57 BJ |
217 | { |
218 | register struct tty *tp; | |
219 | register int c; | |
4abcd051 | 220 | register struct dzdevice *dzaddr; |
9dca4f86 | 221 | register struct tty *tp0; |
3f3a34c3 | 222 | register int unit; |
b19fe459 | 223 | int overrun = 0; |
5074fa57 | 224 | |
88d5b764 BJ |
225 | if ((dzact & (1<<dz)) == 0) |
226 | return; | |
227 | unit = dz * 8; | |
228 | dzaddr = dzpdma[unit].p_addr; | |
229 | tp0 = &dz_tty[unit]; | |
bea90e0b BJ |
230 | dzaddr->dzcsr &= ~(DZ_RIE|DZ_MIE); /* the manual says this song */ |
231 | dzaddr->dzcsr |= DZ_RIE|DZ_MIE; /* and dance is necessary */ | |
232 | while (dzaddr->dzcsr & DZ_MSC) { /* DZ32 modem change interrupt */ | |
233 | c = dzaddr->dzmtsr; | |
234 | tp = tp0 + (c&7); | |
235 | if (tp >= &dz_tty[dz_cnt]) | |
236 | break; | |
237 | dzaddr->dzlcs = c&7; /* get status of modem lines */ | |
238 | dzwait(dzaddr); /* wait for them */ | |
239 | if (c & DZ_CD) /* carrier status change? */ | |
240 | if (dzaddr->dzlcs & DZ_CD) { /* carrier up? */ | |
74bfa0d5 MK |
241 | /* carrier present */ |
242 | (void)(*linesw[tp->t_line].l_modem)(tp, 1); | |
243 | } else if ((*linesw[tp->t_line].l_modem)(tp, 0) == 0) | |
244 | dzaddr->dzlcs = DZ_ACK|(c&7); | |
bea90e0b | 245 | } |
88d5b764 | 246 | while ((c = dzaddr->dzrbuf) < 0) { /* char present */ |
acd2f01b | 247 | dzchars[dz]++; |
88d5b764 BJ |
248 | tp = tp0 + ((c>>8)&07); |
249 | if (tp >= &dz_tty[dz_cnt]) | |
250 | continue; | |
941944c9 | 251 | if ((tp->t_state & TS_ISOPEN) == 0) { |
88d5b764 | 252 | wakeup((caddr_t)&tp->t_rawq); |
df07bd9e SL |
253 | #ifdef PORTSELECTOR |
254 | if ((tp->t_state&TS_WOPEN) == 0) | |
255 | #endif | |
74bfa0d5 | 256 | continue; |
9dca4f86 | 257 | } |
7e00c42b | 258 | if (c&DZ_FE) |
88d5b764 | 259 | if (tp->t_flags & RAW) |
7e00c42b | 260 | c = 0; |
88d5b764 | 261 | else |
21a85e60 | 262 | c = tp->t_intrc; |
b19fe459 | 263 | if (c&DZ_DO && overrun == 0) { |
283ffc90 | 264 | log(LOG_WARNING, "dz%d,%d: silo overflow\n", dz, (c>>8)&7); |
b19fe459 BJ |
265 | overrun = 1; |
266 | } | |
7e00c42b | 267 | if (c&DZ_PE) |
88d5b764 BJ |
268 | if (((tp->t_flags & (EVENP|ODDP)) == EVENP) |
269 | || ((tp->t_flags & (EVENP|ODDP)) == ODDP)) | |
270 | continue; | |
e2c4935e | 271 | #if NBK > 0 |
88d5b764 BJ |
272 | if (tp->t_line == NETLDISC) { |
273 | c &= 0177; | |
274 | BKINPUT(c, tp); | |
275 | } else | |
e2c4935e | 276 | #endif |
88d5b764 | 277 | (*linesw[tp->t_line].l_rint)(c, tp); |
5074fa57 BJ |
278 | } |
279 | } | |
280 | ||
281 | /*ARGSUSED*/ | |
942f05a9 | 282 | dzioctl(dev, cmd, data, flag) |
3f3a34c3 | 283 | dev_t dev; |
942f05a9 | 284 | caddr_t data; |
5074fa57 BJ |
285 | { |
286 | register struct tty *tp; | |
3f3a34c3 BJ |
287 | register int unit = minor(dev); |
288 | register int dz = unit >> 3; | |
4abcd051 | 289 | register struct dzdevice *dzaddr; |
7da157da | 290 | int error; |
5074fa57 | 291 | |
3f3a34c3 | 292 | tp = &dz_tty[unit]; |
7da157da BJ |
293 | error = (*linesw[tp->t_line].l_ioctl)(tp, cmd, data, flag); |
294 | if (error >= 0) | |
295 | return (error); | |
296 | error = ttioctl(tp, cmd, data, flag); | |
297 | if (error >= 0) { | |
21220e35 JB |
298 | if (cmd == TIOCSETP || cmd == TIOCSETN || cmd == TIOCLBIS || |
299 | cmd == TIOCLBIC || cmd == TIOCLSET) | |
3f3a34c3 | 300 | dzparam(unit); |
7da157da BJ |
301 | return (error); |
302 | } | |
303 | switch (cmd) { | |
3f3a34c3 | 304 | |
dc44829a | 305 | case TIOCSBRK: |
bea90e0b BJ |
306 | dzaddr = ((struct pdma *)(tp->t_addr))->p_addr; |
307 | if (dzaddr->dzcsr&DZ_32) | |
668cc26d | 308 | (void) dzmctl(dev, DZ_BRK, DMBIS); |
bea90e0b BJ |
309 | else |
310 | dzaddr->dzbrk = (dz_brk[dz] |= 1 << (unit&07)); | |
dc44829a | 311 | break; |
942f05a9 | 312 | |
dc44829a | 313 | case TIOCCBRK: |
bea90e0b BJ |
314 | dzaddr = ((struct pdma *)(tp->t_addr))->p_addr; |
315 | if (dzaddr->dzcsr&DZ_32) | |
668cc26d | 316 | (void) dzmctl(dev, DZ_BRK, DMBIC); |
bea90e0b BJ |
317 | else |
318 | dzaddr->dzbrk = (dz_brk[dz] &= ~(1 << (unit&07))); | |
dc44829a | 319 | break; |
942f05a9 | 320 | |
dc44829a | 321 | case TIOCSDTR: |
668cc26d | 322 | (void) dzmctl(dev, DZ_DTR|DZ_RTS, DMBIS); |
dc44829a | 323 | break; |
942f05a9 | 324 | |
dc44829a | 325 | case TIOCCDTR: |
668cc26d | 326 | (void) dzmctl(dev, DZ_DTR|DZ_RTS, DMBIC); |
bea90e0b | 327 | break; |
942f05a9 | 328 | |
bea90e0b | 329 | case TIOCMSET: |
942f05a9 | 330 | (void) dzmctl(dev, dmtodz(*(int *)data), DMSET); |
bea90e0b | 331 | break; |
942f05a9 | 332 | |
bea90e0b | 333 | case TIOCMBIS: |
942f05a9 | 334 | (void) dzmctl(dev, dmtodz(*(int *)data), DMBIS); |
bea90e0b | 335 | break; |
942f05a9 | 336 | |
bea90e0b | 337 | case TIOCMBIC: |
942f05a9 | 338 | (void) dzmctl(dev, dmtodz(*(int *)data), DMBIC); |
bea90e0b | 339 | break; |
942f05a9 | 340 | |
bea90e0b | 341 | case TIOCMGET: |
942f05a9 | 342 | *(int *)data = dztodm(dzmctl(dev, 0, DMGET)); |
dc44829a | 343 | break; |
942f05a9 | 344 | |
dc44829a | 345 | default: |
7da157da | 346 | return (ENOTTY); |
dc44829a | 347 | } |
7da157da | 348 | return (0); |
5074fa57 | 349 | } |
bea90e0b BJ |
350 | |
351 | dmtodz(bits) | |
352 | register int bits; | |
353 | { | |
354 | register int b; | |
355 | ||
356 | b = (bits >>1) & 0370; | |
357 | if (bits & DML_ST) b |= DZ_ST; | |
358 | if (bits & DML_RTS) b |= DZ_RTS; | |
359 | if (bits & DML_DTR) b |= DZ_DTR; | |
360 | if (bits & DML_LE) b |= DZ_LE; | |
361 | return(b); | |
362 | } | |
363 | ||
364 | dztodm(bits) | |
365 | register int bits; | |
366 | { | |
367 | register int b; | |
368 | ||
369 | b = (bits << 1) & 0360; | |
370 | if (bits & DZ_DSR) b |= DML_DSR; | |
371 | if (bits & DZ_DTR) b |= DML_DTR; | |
372 | if (bits & DZ_ST) b |= DML_ST; | |
373 | if (bits & DZ_RTS) b |= DML_RTS; | |
374 | return(b); | |
375 | } | |
5074fa57 | 376 | |
3f3a34c3 BJ |
377 | dzparam(unit) |
378 | register int unit; | |
5074fa57 BJ |
379 | { |
380 | register struct tty *tp; | |
4abcd051 | 381 | register struct dzdevice *dzaddr; |
3f3a34c3 | 382 | register int lpr; |
5074fa57 | 383 | |
3f3a34c3 BJ |
384 | tp = &dz_tty[unit]; |
385 | dzaddr = dzpdma[unit].p_addr; | |
acd2f01b MK |
386 | if (dzsilos & (1 << (unit >> 3))) |
387 | dzaddr->dzcsr = DZ_IEN | DZ_SAE; | |
388 | else | |
389 | dzaddr->dzcsr = DZ_IEN; | |
3f3a34c3 | 390 | dzact |= (1<<(unit>>3)); |
5074fa57 | 391 | if (tp->t_ispeed == 0) { |
668cc26d | 392 | (void) dzmctl(unit, DZ_OFF, DMSET); /* hang up line */ |
5074fa57 BJ |
393 | return; |
394 | } | |
3f3a34c3 | 395 | lpr = (dz_speeds[tp->t_ispeed]<<8) | (unit & 07); |
fb01874e | 396 | if (tp->t_flags & (RAW|LITOUT|PASS8)) |
5074fa57 BJ |
397 | lpr |= BITS8; |
398 | else | |
399 | lpr |= (BITS7|PENABLE); | |
400 | if ((tp->t_flags & EVENP) == 0) | |
401 | lpr |= OPAR; | |
7e00c42b BJ |
402 | if (tp->t_ispeed == B110) |
403 | lpr |= TWOSB; | |
5074fa57 BJ |
404 | dzaddr->dzlpr = lpr; |
405 | } | |
406 | ||
407 | dzxint(tp) | |
3f3a34c3 | 408 | register struct tty *tp; |
5074fa57 BJ |
409 | { |
410 | register struct pdma *dp; | |
acd2f01b | 411 | register dz, unit; |
5074fa57 | 412 | |
3f3a34c3 | 413 | dp = (struct pdma *)tp->t_addr; |
941944c9 BJ |
414 | tp->t_state &= ~TS_BUSY; |
415 | if (tp->t_state & TS_FLUSH) | |
416 | tp->t_state &= ~TS_FLUSH; | |
bea90e0b | 417 | else { |
46014098 | 418 | ndflush(&tp->t_outq, dp->p_mem-tp->t_outq.c_cf); |
bea90e0b BJ |
419 | dp->p_end = dp->p_mem = tp->t_outq.c_cf; |
420 | } | |
5074fa57 BJ |
421 | if (tp->t_line) |
422 | (*linesw[tp->t_line].l_start)(tp); | |
423 | else | |
424 | dzstart(tp); | |
bea90e0b BJ |
425 | dz = minor(tp->t_dev) >> 3; |
426 | unit = minor(tp->t_dev) & 7; | |
941944c9 | 427 | if (tp->t_outq.c_cc == 0 || (tp->t_state&TS_BUSY)==0) |
bea90e0b BJ |
428 | if (dp->p_addr->dzcsr & DZ_32) |
429 | dp->p_addr->dzlnen = (dz_lnen[dz] &= ~(1<<unit)); | |
430 | else | |
431 | dp->p_addr->dztcr &= ~(1<<unit); | |
5074fa57 BJ |
432 | } |
433 | ||
434 | dzstart(tp) | |
3f3a34c3 | 435 | register struct tty *tp; |
5074fa57 BJ |
436 | { |
437 | register struct pdma *dp; | |
4abcd051 | 438 | register struct dzdevice *dzaddr; |
3f3a34c3 | 439 | register int cc; |
bea90e0b | 440 | int s, dz, unit; |
5074fa57 | 441 | |
3f3a34c3 | 442 | dp = (struct pdma *)tp->t_addr; |
5074fa57 | 443 | dzaddr = dp->p_addr; |
3f3a34c3 | 444 | s = spl5(); |
941944c9 | 445 | if (tp->t_state & (TS_TIMEOUT|TS_BUSY|TS_TTSTOP)) |
5074fa57 | 446 | goto out; |
941944c9 BJ |
447 | if (tp->t_outq.c_cc <= TTLOWAT(tp)) { |
448 | if (tp->t_state&TS_ASLEEP) { | |
449 | tp->t_state &= ~TS_ASLEEP; | |
450 | wakeup((caddr_t)&tp->t_outq); | |
451 | } | |
452 | if (tp->t_wsel) { | |
453 | selwakeup(tp->t_wsel, tp->t_state & TS_WCOLL); | |
454 | tp->t_wsel = 0; | |
455 | tp->t_state &= ~TS_WCOLL; | |
456 | } | |
5074fa57 BJ |
457 | } |
458 | if (tp->t_outq.c_cc == 0) | |
459 | goto out; | |
21a85e60 | 460 | if (tp->t_flags & (RAW|LITOUT)) |
5074fa57 BJ |
461 | cc = ndqb(&tp->t_outq, 0); |
462 | else { | |
463 | cc = ndqb(&tp->t_outq, 0200); | |
464 | if (cc == 0) { | |
465 | cc = getc(&tp->t_outq); | |
7e00c42b | 466 | timeout(ttrstrt, (caddr_t)tp, (cc&0x7f) + 6); |
941944c9 | 467 | tp->t_state |= TS_TIMEOUT; |
5074fa57 BJ |
468 | goto out; |
469 | } | |
470 | } | |
941944c9 | 471 | tp->t_state |= TS_BUSY; |
5074fa57 BJ |
472 | dp->p_end = dp->p_mem = tp->t_outq.c_cf; |
473 | dp->p_end += cc; | |
bea90e0b BJ |
474 | dz = minor(tp->t_dev) >> 3; |
475 | unit = minor(tp->t_dev) & 7; | |
476 | if (dzaddr->dzcsr & DZ_32) | |
477 | dzaddr->dzlnen = (dz_lnen[dz] |= (1<<unit)); | |
478 | else | |
479 | dzaddr->dztcr |= (1<<unit); | |
3f3a34c3 BJ |
480 | out: |
481 | splx(s); | |
5074fa57 BJ |
482 | } |
483 | ||
484 | /* | |
485 | * Stop output on a line. | |
5074fa57 BJ |
486 | */ |
487 | /*ARGSUSED*/ | |
488 | dzstop(tp, flag) | |
3f3a34c3 | 489 | register struct tty *tp; |
5074fa57 BJ |
490 | { |
491 | register struct pdma *dp; | |
492 | register int s; | |
493 | ||
3f3a34c3 | 494 | dp = (struct pdma *)tp->t_addr; |
88d5b764 | 495 | s = spl5(); |
941944c9 | 496 | if (tp->t_state & TS_BUSY) { |
5074fa57 | 497 | dp->p_end = dp->p_mem; |
941944c9 BJ |
498 | if ((tp->t_state&TS_TTSTOP)==0) |
499 | tp->t_state |= TS_FLUSH; | |
5074fa57 BJ |
500 | } |
501 | splx(s); | |
502 | } | |
503 | ||
bea90e0b BJ |
504 | dzmctl(dev, bits, how) |
505 | dev_t dev; | |
506 | int bits, how; | |
5074fa57 | 507 | { |
4abcd051 | 508 | register struct dzdevice *dzaddr; |
bea90e0b BJ |
509 | register int unit, mbits; |
510 | int b, s; | |
511 | ||
512 | unit = minor(dev); | |
513 | b = 1<<(unit&7); | |
3f3a34c3 | 514 | dzaddr = dzpdma[unit].p_addr; |
bea90e0b BJ |
515 | s = spl5(); |
516 | if (dzaddr->dzcsr & DZ_32) { | |
517 | dzwait(dzaddr) | |
518 | DELAY(100); /* IS 100 TOO MUCH? */ | |
519 | dzaddr->dzlcs = unit&7; | |
520 | DELAY(100); | |
521 | dzwait(dzaddr) | |
522 | DELAY(100); | |
523 | mbits = dzaddr->dzlcs; | |
524 | mbits &= 0177770; | |
525 | } else { | |
526 | mbits = (dzaddr->dzdtr & b) ? DZ_DTR : 0; | |
527 | mbits |= (dzaddr->dzmsr & b) ? DZ_CD : 0; | |
528 | mbits |= (dzaddr->dztbuf & b) ? DZ_RI : 0; | |
529 | } | |
530 | switch (how) { | |
531 | case DMSET: | |
532 | mbits = bits; | |
533 | break; | |
534 | ||
535 | case DMBIS: | |
536 | mbits |= bits; | |
537 | break; | |
538 | ||
539 | case DMBIC: | |
540 | mbits &= ~bits; | |
541 | break; | |
542 | ||
543 | case DMGET: | |
544 | (void) splx(s); | |
545 | return(mbits); | |
546 | } | |
547 | if (dzaddr->dzcsr & DZ_32) { | |
548 | mbits |= DZ_ACK|(unit&7); | |
549 | dzaddr->dzlcs = mbits; | |
550 | } else { | |
551 | if (mbits & DZ_DTR) | |
552 | dzaddr->dzdtr |= b; | |
553 | else | |
554 | dzaddr->dzdtr &= ~b; | |
555 | } | |
556 | (void) splx(s); | |
557 | return(mbits); | |
5074fa57 BJ |
558 | } |
559 | ||
acd2f01b | 560 | int dztransitions, dzfasttimers; /*DEBUG*/ |
5074fa57 BJ |
561 | dzscan() |
562 | { | |
563 | register i; | |
4abcd051 | 564 | register struct dzdevice *dzaddr; |
5074fa57 BJ |
565 | register bit; |
566 | register struct tty *tp; | |
bea90e0b | 567 | register car; |
acd2f01b MK |
568 | int olddzsilos = dzsilos; |
569 | int dztimer(); | |
5074fa57 BJ |
570 | |
571 | for (i = 0; i < dz_cnt ; i++) { | |
572 | dzaddr = dzpdma[i].p_addr; | |
be2b272c BJ |
573 | if (dzaddr == 0) |
574 | continue; | |
5074fa57 BJ |
575 | tp = &dz_tty[i]; |
576 | bit = 1<<(i&07); | |
bea90e0b BJ |
577 | car = 0; |
578 | if (dzsoftCAR[i>>3]&bit) | |
579 | car = 1; | |
580 | else if (dzaddr->dzcsr & DZ_32) { | |
581 | dzaddr->dzlcs = i&07; | |
582 | dzwait(dzaddr); | |
583 | car = dzaddr->dzlcs & DZ_CD; | |
584 | } else | |
585 | car = dzaddr->dzmsr&bit; | |
586 | if (car) { | |
5074fa57 | 587 | /* carrier present */ |
74bfa0d5 MK |
588 | if ((tp->t_state & TS_CARR_ON) == 0) |
589 | (void)(*linesw[tp->t_line].l_modem)(tp, 1); | |
590 | } else if ((tp->t_state&TS_CARR_ON) && | |
591 | (*linesw[tp->t_line].l_modem)(tp, 0) == 0) | |
592 | dzaddr->dzdtr &= ~bit; | |
5074fa57 | 593 | } |
acd2f01b MK |
594 | for (i = 0; i < NDZ; i++) { |
595 | ave(dzrate[i], dzchars[i], 8); | |
596 | if (dzchars[i] > dzhighrate && ((dzsilos & (1 << i)) == 0)) { | |
abca5f3b | 597 | dzpdma[i << 3].p_addr->dzcsr = DZ_IEN | DZ_SAE; |
acd2f01b MK |
598 | dzsilos |= (1 << i); |
599 | dztransitions++; /*DEBUG*/ | |
600 | } else if ((dzsilos & (1 << i)) && (dzrate[i] < dzlowrate)) { | |
abca5f3b | 601 | dzpdma[i << 3].p_addr->dzcsr = DZ_IEN; |
acd2f01b MK |
602 | dzsilos &= ~(1 << i); |
603 | } | |
604 | dzchars[i] = 0; | |
605 | } | |
606 | if (dzsilos && !olddzsilos) | |
607 | timeout(dztimer, (caddr_t)0, dztimerintvl); | |
608 | timeout(dzscan, (caddr_t)0, hz); | |
5074fa57 | 609 | } |
9dca4f86 BJ |
610 | |
611 | dztimer() | |
612 | { | |
aa890753 | 613 | register int dz; |
acd2f01b | 614 | register int s; |
9dca4f86 | 615 | |
acd2f01b MK |
616 | if (dzsilos == 0) |
617 | return; | |
618 | s = spl5(); | |
619 | dzfasttimers++; /*DEBUG*/ | |
a3cb8f60 | 620 | for (dz = 0; dz < NDZ; dz++) |
acd2f01b MK |
621 | if (dzsilos & (1 << dz)) |
622 | dzrint(dz); | |
aa890753 | 623 | splx(s); |
acd2f01b | 624 | timeout(dztimer, (caddr_t) 0, dztimerintvl); |
9dca4f86 | 625 | } |
46014098 BJ |
626 | |
627 | /* | |
628 | * Reset state of driver if UBA reset was necessary. | |
0072a3c2 | 629 | * Reset parameters and restart transmission on open lines. |
46014098 | 630 | */ |
3f3a34c3 | 631 | dzreset(uban) |
5aa9d5ea | 632 | int uban; |
46014098 | 633 | { |
3f3a34c3 | 634 | register int unit; |
46014098 | 635 | register struct tty *tp; |
6a1a96ff | 636 | register struct uba_device *ui; |
46014098 | 637 | |
a3cb8f60 | 638 | for (unit = 0; unit < NDZLINE; unit++) { |
5aa9d5ea RE |
639 | ui = dzinfo[unit >> 3]; |
640 | if (ui == 0 || ui->ui_ubanum != uban || ui->ui_alive == 0) | |
641 | continue; | |
b19fe459 BJ |
642 | if (unit%8 == 0) |
643 | printf(" dz%d", unit>>3); | |
3f3a34c3 | 644 | tp = &dz_tty[unit]; |
941944c9 | 645 | if (tp->t_state & (TS_ISOPEN|TS_WOPEN)) { |
3f3a34c3 | 646 | dzparam(unit); |
668cc26d | 647 | (void) dzmctl(unit, DZ_ON, DMSET); |
941944c9 | 648 | tp->t_state &= ~TS_BUSY; |
0072a3c2 | 649 | dzstart(tp); |
46014098 BJ |
650 | } |
651 | } | |
46014098 | 652 | } |
a5cc519e | 653 | #endif |