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