1 /* dz.c 4.25 81/05/09 */ 2 3 #include "dz.h" 4 #if NDZ > 0 5 /* 6 * DZ-11 Driver 7 * 8 * This driver mimics dh.c; see it for explanation of common code. 9 */ 10 #include "bk.h" 11 #include "../h/param.h" 12 #include "../h/systm.h" 13 #include "../h/tty.h" 14 #include "../h/dir.h" 15 #include "../h/user.h" 16 #include "../h/map.h" 17 #include "../h/pte.h" 18 #include "../h/buf.h" 19 #include "../h/vm.h" 20 #include "../h/ubavar.h" 21 #include "../h/conf.h" 22 #include "../h/pdma.h" 23 #include "../h/bk.h" 24 #include "../h/file.h" 25 #include "../h/mx.h" 26 27 /* 28 * Driver information for auto-configuration stuff. 29 */ 30 int dzprobe(), dzattach(), dzrint(); 31 struct uba_device *dzinfo[NDZ]; 32 u_short dzstd[] = { 0 }; 33 struct uba_driver dzdriver = 34 { dzprobe, 0, dzattach, 0, dzstd, "dz", dzinfo }; 35 36 #define NDZLINE (NDZ*8) 37 38 /* 39 * Registers and bits 40 */ 41 42 /* Bits in dzlpr */ 43 #define BITS7 020 44 #define BITS8 030 45 #define TWOSB 040 46 #define PENABLE 0100 47 #define OPAR 0200 48 49 /* Bits in dzrbuf */ 50 #define DZ_PE 010000 51 #define DZ_FE 020000 52 #define DZ_DO 040000 53 54 /* Bits in dzcsr */ 55 #define DZ_CLR 020 /* Reset dz */ 56 #define DZ_MSE 040 /* Master Scan Enable */ 57 #define DZ_RIE 0100 /* Receiver Interrupt Enable */ 58 #define DZ_SAE 010000 /* Silo Alarm Enable */ 59 #define DZ_TIE 040000 /* Transmit Interrupt Enable */ 60 #if NBK == 0 61 #define DZ_IEN (DZ_MSE|DZ_RIE|DZ_TIE) 62 #else 63 #define DZ_IEN (DZ_MSE|DZ_RIE|DZ_TIE|DZ_SAE) 64 #endif 65 66 /* Flags for modem-control */ 67 #define DZ_ON 1 68 #define DZ_OFF 0 69 70 int dzstart(), dzxint(), dzdma(); 71 int ttrstrt(); 72 struct tty dz_tty[NDZLINE]; 73 int dz_cnt = { NDZLINE }; 74 int dzact; 75 76 struct device { 77 short dzcsr; /* control-status register */ 78 short dzrbuf; /* receiver buffer */ 79 #define dzlpr dzrbuf /* line parameter reg is write of dzrbuf */ 80 char dztcr; /* transmit control register */ 81 char dzdtr; /* data terminal ready */ 82 char dztbuf; /* transmit buffer */ 83 char dzbrk; /* break control */ 84 #define dzmsr dzbrk /* modem status register */ 85 }; 86 /* 87 * Software copy of dzbrk since it isn't readable 88 */ 89 char dz_brk[NDZ]; 90 char dzsoftCAR[NDZ]; 91 92 /* 93 * The dz doesn't interrupt on carrier transitions, so 94 * we have to use a timer to watch it. 95 */ 96 char dz_timer; /* timer started? */ 97 98 /* 99 * Pdma structures for fast output code 100 */ 101 struct pdma dzpdma[NDZLINE]; 102 103 char dz_speeds[] = 104 { 0,020,021,022,023,024,0,025,026,027,030,032,034,036,0,0 }; 105 106 dzprobe(reg) 107 caddr_t reg; 108 { 109 register int br, cvec; 110 register struct device *dzaddr = (struct device *)reg; 111 112 #ifdef lint 113 br = 0; cvec = br; br = cvec; 114 #endif 115 dzaddr->dzcsr = DZ_TIE|DZ_MSE; 116 dzaddr->dztcr = 1; /* enable any line */ 117 DELAY(100000); 118 dzaddr->dzcsr = DZ_CLR; /* reset everything */ 119 if (cvec && cvec != 0x200) 120 cvec -= 4; 121 return (1); 122 } 123 124 dzattach(ui) 125 register struct uba_device *ui; 126 { 127 register struct pdma *pdp = &dzpdma[ui->ui_unit*8]; 128 register struct tty *tp = &dz_tty[ui->ui_unit*8]; 129 register int cntr; 130 extern dzscan(); 131 132 for (cntr = 0; cntr < 8; cntr++) { 133 pdp->p_addr = (struct device *)ui->ui_addr; 134 pdp->p_arg = (int)tp; 135 pdp->p_fcn = dzxint; 136 pdp++, tp++; 137 } 138 dzsoftCAR[ui->ui_unit] = ui->ui_flags; 139 if (dz_timer == 0) { 140 dz_timer++; 141 timeout(dzscan, (caddr_t)0, hz); 142 } 143 return (1); 144 } 145 146 /*ARGSUSED*/ 147 dzopen(dev, flag) 148 dev_t dev; 149 { 150 register struct tty *tp; 151 register int unit; 152 153 unit = minor(dev); 154 if (unit >= dz_cnt || dzpdma[unit].p_addr == 0) { 155 u.u_error = ENXIO; 156 return; 157 } 158 tp = &dz_tty[unit]; 159 tp->t_addr = (caddr_t)&dzpdma[unit]; 160 tp->t_oproc = dzstart; 161 tp->t_iproc = NULL; 162 tp->t_state |= WOPEN; 163 if ((tp->t_state & ISOPEN) == 0) { 164 ttychars(tp); 165 tp->t_ospeed = tp->t_ispeed = B300; 166 tp->t_flags = ODDP|EVENP|ECHO; 167 /* tp->t_state |= HUPCLS; */ 168 dzparam(unit); 169 } else if (tp->t_state&XCLUDE && u.u_uid != 0) { 170 u.u_error = EBUSY; 171 return; 172 } 173 dzmodem(unit, DZ_ON); 174 (void) spl5(); 175 while ((tp->t_state & CARR_ON) == 0) { 176 tp->t_state |= WOPEN; 177 sleep((caddr_t)&tp->t_rawq, TTIPRI); 178 } 179 (void) spl0(); 180 (*linesw[tp->t_line].l_open)(dev, tp); 181 } 182 183 /*ARGSUSED*/ 184 dzclose(dev, flag) 185 dev_t dev; 186 { 187 register struct tty *tp; 188 register int unit; 189 int dz; 190 191 unit = minor(dev); 192 dz = unit >> 3; 193 tp = &dz_tty[unit]; 194 (*linesw[tp->t_line].l_close)(tp); 195 ((struct pdma *)(tp->t_addr))->p_addr->dzbrk = 196 (dz_brk[dz] &= ~(1 << (unit&07))); 197 if (tp->t_state & HUPCLS) 198 dzmodem(unit, DZ_OFF); 199 ttyclose(tp); 200 } 201 202 dzread(dev) 203 dev_t dev; 204 { 205 register struct tty *tp; 206 207 tp = &dz_tty[minor(dev)]; 208 (*linesw[tp->t_line].l_read)(tp); 209 } 210 211 dzwrite(dev) 212 dev_t dev; 213 { 214 register struct tty *tp; 215 216 tp = &dz_tty[minor(dev)]; 217 (*linesw[tp->t_line].l_write)(tp); 218 } 219 220 /*ARGSUSED*/ 221 dzrint(dz) 222 int dz; 223 { 224 register struct tty *tp; 225 register int c; 226 register struct device *dzaddr; 227 register struct tty *tp0; 228 register int unit; 229 int overrun = 0; 230 231 if ((dzact & (1<<dz)) == 0) 232 return; 233 unit = dz * 8; 234 dzaddr = dzpdma[unit].p_addr; 235 tp0 = &dz_tty[unit]; 236 while ((c = dzaddr->dzrbuf) < 0) { /* char present */ 237 tp = tp0 + ((c>>8)&07); 238 if (tp >= &dz_tty[dz_cnt]) 239 continue; 240 if ((tp->t_state & ISOPEN) == 0) { 241 wakeup((caddr_t)&tp->t_rawq); 242 continue; 243 } 244 if (c&DZ_FE) 245 if (tp->t_flags & RAW) 246 c = 0; 247 else 248 c = tun.t_intrc; 249 if (c&DZ_DO && overrun == 0) { 250 printf("dz%d: silo overflow\n", dz); 251 overrun = 1; 252 } 253 if (c&DZ_PE) 254 if (((tp->t_flags & (EVENP|ODDP)) == EVENP) 255 || ((tp->t_flags & (EVENP|ODDP)) == ODDP)) 256 continue; 257 #if NBK > 0 258 if (tp->t_line == NETLDISC) { 259 c &= 0177; 260 BKINPUT(c, tp); 261 } else 262 #endif 263 (*linesw[tp->t_line].l_rint)(c, tp); 264 } 265 } 266 267 /*ARGSUSED*/ 268 dzioctl(dev, cmd, addr, flag) 269 dev_t dev; 270 caddr_t addr; 271 { 272 register struct tty *tp; 273 register int unit = minor(dev); 274 register int dz = unit >> 3; 275 276 tp = &dz_tty[unit]; 277 cmd = (*linesw[tp->t_line].l_ioctl)(tp, cmd, addr); 278 if (cmd == 0) 279 return; 280 if (ttioctl(tp, cmd, addr, flag)) { 281 if (cmd==TIOCSETP || cmd==TIOCSETN) 282 dzparam(unit); 283 } else switch(cmd) { 284 285 case TIOCSBRK: 286 ((struct pdma *)(tp->t_addr))->p_addr->dzbrk = 287 (dz_brk[dz] |= 1 << (unit&07)); 288 break; 289 case TIOCCBRK: 290 ((struct pdma *)(tp->t_addr))->p_addr->dzbrk = 291 (dz_brk[dz] &= ~(1 << (unit&07))); 292 break; 293 case TIOCSDTR: 294 dzmodem(unit, DZ_ON); 295 break; 296 case TIOCCDTR: 297 dzmodem(unit, DZ_OFF); 298 break; 299 default: 300 u.u_error = ENOTTY; 301 } 302 } 303 304 dzparam(unit) 305 register int unit; 306 { 307 register struct tty *tp; 308 register struct device *dzaddr; 309 register int lpr; 310 311 tp = &dz_tty[unit]; 312 dzaddr = dzpdma[unit].p_addr; 313 dzaddr->dzcsr = DZ_IEN; 314 dzact |= (1<<(unit>>3)); 315 if (tp->t_ispeed == 0) { 316 dzmodem(unit, DZ_OFF); /* hang up line */ 317 return; 318 } 319 lpr = (dz_speeds[tp->t_ispeed]<<8) | (unit & 07); 320 if ((tp->t_local&LLITOUT) || (tp->t_flags&RAW)) 321 lpr |= BITS8; 322 else 323 lpr |= (BITS7|PENABLE); 324 if ((tp->t_flags & EVENP) == 0) 325 lpr |= OPAR; 326 if (tp->t_ispeed == B110) 327 lpr |= TWOSB; 328 dzaddr->dzlpr = lpr; 329 } 330 331 dzxint(tp) 332 register struct tty *tp; 333 { 334 register struct pdma *dp; 335 register s; 336 337 s = spl5(); /* block pdma interrupts */ 338 dp = (struct pdma *)tp->t_addr; 339 tp->t_state &= ~BUSY; 340 if (tp->t_state & FLUSH) 341 tp->t_state &= ~FLUSH; 342 else 343 ndflush(&tp->t_outq, dp->p_mem-tp->t_outq.c_cf); 344 if (tp->t_line) 345 (*linesw[tp->t_line].l_start)(tp); 346 else 347 dzstart(tp); 348 if (tp->t_outq.c_cc == 0 || (tp->t_state&BUSY)==0) 349 dp->p_addr->dztcr &= ~(1 << (minor(tp->t_dev)&07)); 350 splx(s); 351 } 352 353 dzstart(tp) 354 register struct tty *tp; 355 { 356 register struct pdma *dp; 357 register struct device *dzaddr; 358 register int cc; 359 int s; 360 361 dp = (struct pdma *)tp->t_addr; 362 dzaddr = dp->p_addr; 363 s = spl5(); 364 if (tp->t_state & (TIMEOUT|BUSY|TTSTOP)) 365 goto out; 366 if (tp->t_state&ASLEEP && tp->t_outq.c_cc <= TTLOWAT(tp)) { 367 tp->t_state &= ~ASLEEP; 368 if (tp->t_chan) 369 mcstart(tp->t_chan, (caddr_t)&tp->t_outq); 370 else 371 wakeup((caddr_t)&tp->t_outq); 372 } 373 if (tp->t_outq.c_cc == 0) 374 goto out; 375 if (tp->t_flags&RAW || tp->t_flags&LLITOUT) 376 cc = ndqb(&tp->t_outq, 0); 377 else { 378 cc = ndqb(&tp->t_outq, 0200); 379 if (cc == 0) { 380 cc = getc(&tp->t_outq); 381 timeout(ttrstrt, (caddr_t)tp, (cc&0x7f) + 6); 382 tp->t_state |= TIMEOUT; 383 goto out; 384 } 385 } 386 tp->t_state |= BUSY; 387 dp->p_end = dp->p_mem = tp->t_outq.c_cf; 388 dp->p_end += cc; 389 dzaddr->dztcr |= 1 << (minor(tp->t_dev) & 07); /* force intr */ 390 out: 391 splx(s); 392 } 393 394 /* 395 * Stop output on a line. 396 */ 397 /*ARGSUSED*/ 398 dzstop(tp, flag) 399 register struct tty *tp; 400 { 401 register struct pdma *dp; 402 register int s; 403 404 dp = (struct pdma *)tp->t_addr; 405 s = spl5(); 406 if (tp->t_state & BUSY) { 407 dp->p_end = dp->p_mem; 408 if ((tp->t_state&TTSTOP)==0) 409 tp->t_state |= FLUSH; 410 } 411 splx(s); 412 } 413 414 dzmodem(unit, flag) 415 register int unit; 416 { 417 register struct device *dzaddr; 418 register char bit; 419 420 dzaddr = dzpdma[unit].p_addr; 421 bit = 1<<(unit&07); 422 if (flag == DZ_OFF) 423 dzaddr->dzdtr &= ~bit; 424 else 425 dzaddr->dzdtr |= bit; 426 } 427 428 dzscan() 429 { 430 register i; 431 register struct device *dzaddr; 432 register bit; 433 register struct tty *tp; 434 435 for (i = 0; i < dz_cnt ; i++) { 436 dzaddr = dzpdma[i].p_addr; 437 if (dzaddr == 0) 438 continue; 439 tp = &dz_tty[i]; 440 bit = 1<<(i&07); 441 if ((dzsoftCAR[i>>3]&bit) || (dzaddr->dzmsr&bit)) { 442 /* carrier present */ 443 if ((tp->t_state & CARR_ON) == 0) { 444 wakeup((caddr_t)&tp->t_rawq); 445 tp->t_state |= CARR_ON; 446 } 447 } else { 448 if ((tp->t_state&CARR_ON) && 449 (tp->t_local&LNOHANG)==0) { 450 /* carrier lost */ 451 if (tp->t_state&ISOPEN) { 452 gsignal(tp->t_pgrp, SIGHUP); 453 gsignal(tp->t_pgrp, SIGCONT); 454 dzaddr->dzdtr &= ~bit; 455 flushtty(tp, FREAD|FWRITE); 456 } 457 tp->t_state &= ~CARR_ON; 458 } 459 } 460 } 461 timeout(dzscan, (caddr_t)0, 2*hz); 462 } 463 464 dztimer() 465 { 466 int dz; 467 468 for (dz = 0; dz < NDZ; dz++) 469 dzrint(dz); 470 } 471 472 /* 473 * Reset state of driver if UBA reset was necessary. 474 * Reset parameters and restart transmission on open lines. 475 */ 476 dzreset(uban) 477 int uban; 478 { 479 register int unit; 480 register struct tty *tp; 481 register struct uba_device *ui; 482 483 for (unit = 0; unit < NDZLINE; unit++) { 484 ui = dzinfo[unit >> 3]; 485 if (ui == 0 || ui->ui_ubanum != uban || ui->ui_alive == 0) 486 continue; 487 if (unit%8 == 0) 488 printf(" dz%d", unit>>3); 489 tp = &dz_tty[unit]; 490 if (tp->t_state & (ISOPEN|WOPEN)) { 491 dzparam(unit); 492 dzmodem(unit, DZ_ON); 493 tp->t_state &= ~BUSY; 494 dzstart(tp); 495 } 496 } 497 dztimer(); 498 } 499 #endif 500