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