1 /*- 2 * Copyright (c) 1992, 1993 3 * The Regents of the University of California. All rights reserved. 4 * 5 * This code is derived from software contributed to Berkeley by 6 * Ralph Campbell and Rick Macklem. 7 * 8 * %sccs.include.redist.c% 9 * 10 * @(#)dc.c 8.4 (Berkeley) 07/14/94 11 */ 12 13 /* 14 * devDC7085.c -- 15 * 16 * This file contains machine-dependent routines that handle the 17 * output queue for the serial lines. 18 * 19 * Copyright (C) 1989 Digital Equipment Corporation. 20 * Permission to use, copy, modify, and distribute this software and 21 * its documentation for any purpose and without fee is hereby granted, 22 * provided that the above copyright notice appears in all copies. 23 * Digital Equipment Corporation makes no representations about the 24 * suitability of this software for any purpose. It is provided "as is" 25 * without express or implied warranty. 26 * 27 * from: $Header: /sprite/src/kernel/dev/ds3100.md/RCS/devDC7085.c, 28 * v 1.4 89/08/29 11:55:30 nelson Exp $ SPRITE (DECWRL)"; 29 */ 30 31 #include <dc.h> 32 #if NDC > 0 33 /* 34 * DC7085 (DZ-11 look alike) Driver 35 */ 36 #include <sys/param.h> 37 #include <sys/systm.h> 38 #include <sys/ioctl.h> 39 #include <sys/tty.h> 40 #include <sys/proc.h> 41 #include <sys/map.h> 42 #include <sys/buf.h> 43 #include <sys/conf.h> 44 #include <sys/file.h> 45 #include <sys/uio.h> 46 #include <sys/kernel.h> 47 #include <sys/syslog.h> 48 49 #include <machine/dc7085cons.h> 50 #include <machine/pmioctl.h> 51 52 #include <pmax/pmax/pmaxtype.h> 53 #include <pmax/pmax/cons.h> 54 55 #include <pmax/dev/device.h> 56 #include <pmax/dev/pdma.h> 57 #include <pmax/dev/fbreg.h> 58 59 extern int pmax_boardtype; 60 extern struct consdev cn_tab; 61 62 /* 63 * Driver information for auto-configuration stuff. 64 */ 65 int dcprobe(); 66 void dcintr(); 67 struct driver dcdriver = { 68 "dc", dcprobe, 0, 0, dcintr, 69 }; 70 71 #define NDCLINE (NDC*4) 72 73 void dcstart __P((struct tty *)); 74 void dcxint __P((struct tty *)); 75 void dcPutc __P((dev_t, int)); 76 void dcscan __P((void *)); 77 extern void ttrstrt __P((void *)); 78 int dcGetc __P((dev_t)); 79 int dcparam __P((struct tty *, struct termios *)); 80 81 struct tty dc_tty[NDCLINE]; 82 int dc_cnt = NDCLINE; 83 void (*dcDivertXInput)(); /* X windows keyboard input routine */ 84 void (*dcMouseEvent)(); /* X windows mouse motion event routine */ 85 void (*dcMouseButtons)(); /* X windows mouse buttons event routine */ 86 #ifdef DEBUG 87 int debugChar; 88 #endif 89 90 /* 91 * Software copy of brk register since it isn't readable 92 */ 93 int dc_brk[NDC]; 94 char dcsoftCAR[NDC]; /* mask of dc's with carrier on (DSR) */ 95 96 /* 97 * The DC7085 doesn't interrupt on carrier transitions, so 98 * we have to use a timer to watch it. 99 */ 100 int dc_timer; /* true if timer started */ 101 102 /* 103 * Pdma structures for fast output code 104 */ 105 struct pdma dcpdma[NDCLINE]; 106 107 struct speedtab dcspeedtab[] = { 108 0, 0, 109 50, LPR_B50, 110 75, LPR_B75, 111 110, LPR_B110, 112 134, LPR_B134, 113 150, LPR_B150, 114 300, LPR_B300, 115 600, LPR_B600, 116 1200, LPR_B1200, 117 1800, LPR_B1800, 118 2400, LPR_B2400, 119 4800, LPR_B4800, 120 9600, LPR_B9600, 121 19200, LPR_B19200, 122 -1, -1 123 }; 124 125 #ifndef PORTSELECTOR 126 #define ISPEED TTYDEF_SPEED 127 #define LFLAG TTYDEF_LFLAG 128 #else 129 #define ISPEED B4800 130 #define LFLAG (TTYDEF_LFLAG & ~ECHO) 131 #endif 132 133 /* 134 * Test to see if device is present. 135 * Return true if found and initialized ok. 136 */ 137 dcprobe(cp) 138 register struct pmax_ctlr *cp; 139 { 140 register dcregs *dcaddr; 141 register struct pdma *pdp; 142 register struct tty *tp; 143 register int cntr; 144 int s; 145 146 if (cp->pmax_unit >= NDC) 147 return (0); 148 if (badaddr(cp->pmax_addr, 2)) 149 return (0); 150 151 /* 152 * For a remote console, wait a while for previous output to 153 * complete. 154 */ 155 if (major(cn_tab.cn_dev) == DCDEV && cp->pmax_unit == 0 && 156 cn_tab.cn_screen == 0) 157 DELAY(10000); 158 159 /* reset chip */ 160 dcaddr = (dcregs *)cp->pmax_addr; 161 dcaddr->dc_csr = CSR_CLR; 162 MachEmptyWriteBuffer(); 163 while (dcaddr->dc_csr & CSR_CLR) 164 ; 165 dcaddr->dc_csr = CSR_MSE | CSR_TIE | CSR_RIE; 166 167 /* init pseudo DMA structures */ 168 pdp = &dcpdma[cp->pmax_unit * 4]; 169 tp = &dc_tty[cp->pmax_unit * 4]; 170 for (cntr = 0; cntr < 4; cntr++) { 171 pdp->p_addr = (void *)dcaddr; 172 pdp->p_arg = (int)tp; 173 pdp->p_fcn = dcxint; 174 pdp++, tp++; 175 } 176 dcsoftCAR[cp->pmax_unit] = cp->pmax_flags | 0xB; 177 178 if (dc_timer == 0) { 179 dc_timer = 1; 180 timeout(dcscan, (void *)0, hz); 181 } 182 183 /* 184 * Special handling for consoles. 185 */ 186 if (cp->pmax_unit == 0) { 187 if (cn_tab.cn_screen) { 188 s = spltty(); 189 dcaddr->dc_lpr = LPR_RXENAB | LPR_8_BIT_CHAR | 190 LPR_B4800 | DCKBD_PORT; 191 MachEmptyWriteBuffer(); 192 dcaddr->dc_lpr = LPR_RXENAB | LPR_B4800 | LPR_OPAR | 193 LPR_PARENB | LPR_8_BIT_CHAR | DCMOUSE_PORT; 194 MachEmptyWriteBuffer(); 195 DELAY(1000); 196 KBDReset(makedev(DCDEV, DCKBD_PORT), dcPutc); 197 MouseInit(makedev(DCDEV, DCMOUSE_PORT), dcPutc, dcGetc); 198 splx(s); 199 } else if (major(cn_tab.cn_dev) == DCDEV) { 200 s = spltty(); 201 dcaddr->dc_lpr = LPR_RXENAB | LPR_8_BIT_CHAR | 202 LPR_B9600 | minor(cn_tab.cn_dev); 203 MachEmptyWriteBuffer(); 204 DELAY(1000); 205 cn_tab.cn_disabled = 0; 206 splx(s); 207 } 208 } 209 printf("dc%d at nexus0 csr 0x%x priority %d\n", 210 cp->pmax_unit, cp->pmax_addr, cp->pmax_pri); 211 return (1); 212 } 213 214 dcopen(dev, flag, mode, p) 215 dev_t dev; 216 int flag, mode; 217 struct proc *p; 218 { 219 register struct tty *tp; 220 register int unit; 221 int s, error = 0; 222 223 unit = minor(dev); 224 if (unit >= dc_cnt || dcpdma[unit].p_addr == (void *)0) 225 return (ENXIO); 226 tp = &dc_tty[unit]; 227 tp->t_oproc = dcstart; 228 tp->t_param = dcparam; 229 tp->t_dev = dev; 230 if ((tp->t_state & TS_ISOPEN) == 0) { 231 tp->t_state |= TS_WOPEN; 232 ttychars(tp); 233 #ifndef PORTSELECTOR 234 if (tp->t_ispeed == 0) { 235 #endif 236 tp->t_iflag = TTYDEF_IFLAG; 237 tp->t_oflag = TTYDEF_OFLAG; 238 tp->t_cflag = TTYDEF_CFLAG; 239 tp->t_lflag = LFLAG; 240 tp->t_ispeed = tp->t_ospeed = ISPEED; 241 #ifdef PORTSELECTOR 242 tp->t_cflag |= HUPCL; 243 #else 244 } 245 #endif 246 (void) dcparam(tp, &tp->t_termios); 247 ttsetwater(tp); 248 } else if ((tp->t_state & TS_XCLUDE) && curproc->p_ucred->cr_uid != 0) 249 return (EBUSY); 250 (void) dcmctl(dev, DML_DTR | DML_RTS, DMSET); 251 s = spltty(); 252 while (!(flag & O_NONBLOCK) && !(tp->t_cflag & CLOCAL) && 253 !(tp->t_state & TS_CARR_ON)) { 254 tp->t_state |= TS_WOPEN; 255 if (error = ttysleep(tp, (caddr_t)&tp->t_rawq, TTIPRI | PCATCH, 256 ttopen, 0)) 257 break; 258 } 259 splx(s); 260 if (error) 261 return (error); 262 return ((*linesw[tp->t_line].l_open)(dev, tp)); 263 } 264 265 /*ARGSUSED*/ 266 dcclose(dev, flag, mode, p) 267 dev_t dev; 268 int flag, mode; 269 struct proc *p; 270 { 271 register struct tty *tp; 272 register int unit, bit; 273 274 unit = minor(dev); 275 tp = &dc_tty[unit]; 276 bit = 1 << ((unit & 03) + 8); 277 if (dc_brk[unit >> 2] & bit) { 278 dc_brk[unit >> 2] &= ~bit; 279 ttyoutput(0, tp); 280 } 281 (*linesw[tp->t_line].l_close)(tp, flag); 282 if ((tp->t_cflag & HUPCL) || (tp->t_state & TS_WOPEN) || 283 !(tp->t_state & TS_ISOPEN)) 284 (void) dcmctl(dev, 0, DMSET); 285 return (ttyclose(tp)); 286 } 287 288 dcread(dev, uio, flag) 289 dev_t dev; 290 struct uio *uio; 291 { 292 register struct tty *tp; 293 294 tp = &dc_tty[minor(dev)]; 295 if ((tp->t_cflag & CRTS_IFLOW) && (tp->t_state & TS_TBLOCK) && 296 tp->t_rawq.c_cc < TTYHOG/5) { 297 tp->t_state &= ~TS_TBLOCK; 298 (void) dcmctl(dev, DML_RTS, DMBIS); 299 } 300 return ((*linesw[tp->t_line].l_read)(tp, uio, flag)); 301 } 302 303 dcwrite(dev, uio, flag) 304 dev_t dev; 305 struct uio *uio; 306 { 307 register struct tty *tp; 308 309 tp = &dc_tty[minor(dev)]; 310 return ((*linesw[tp->t_line].l_write)(tp, uio, flag)); 311 } 312 313 /*ARGSUSED*/ 314 dcioctl(dev, cmd, data, flag, p) 315 dev_t dev; 316 int cmd; 317 caddr_t data; 318 int flag; 319 struct proc *p; 320 { 321 register struct tty *tp; 322 register int unit = minor(dev); 323 register int dc = unit >> 2; 324 int error; 325 326 tp = &dc_tty[unit]; 327 error = (*linesw[tp->t_line].l_ioctl)(tp, cmd, data, flag, p); 328 if (error >= 0) 329 return (error); 330 error = ttioctl(tp, cmd, data, flag); 331 if (error >= 0) 332 return (error); 333 334 switch (cmd) { 335 336 case TIOCSBRK: 337 dc_brk[dc] |= 1 << ((unit & 03) + 8); 338 ttyoutput(0, tp); 339 break; 340 341 case TIOCCBRK: 342 dc_brk[dc] &= ~(1 << ((unit & 03) + 8)); 343 ttyoutput(0, tp); 344 break; 345 346 case TIOCSDTR: 347 (void) dcmctl(dev, DML_DTR | DML_RTS, DMBIS); 348 break; 349 350 case TIOCCDTR: 351 (void) dcmctl(dev, DML_DTR | DML_RTS, DMBIC); 352 break; 353 354 case TIOCMSET: 355 (void) dcmctl(dev, *(int *)data, DMSET); 356 break; 357 358 case TIOCMBIS: 359 (void) dcmctl(dev, *(int *)data, DMBIS); 360 break; 361 362 case TIOCMBIC: 363 (void) dcmctl(dev, *(int *)data, DMBIC); 364 break; 365 366 case TIOCMGET: 367 *(int *)data = dcmctl(dev, 0, DMGET); 368 break; 369 370 default: 371 return (ENOTTY); 372 } 373 return (0); 374 } 375 376 dcparam(tp, t) 377 register struct tty *tp; 378 register struct termios *t; 379 { 380 register dcregs *dcaddr; 381 register int lpr; 382 register int cflag = t->c_cflag; 383 int unit = minor(tp->t_dev); 384 int ospeed = ttspeedtab(t->c_ospeed, dcspeedtab); 385 int s; 386 387 /* check requested parameters */ 388 if (ospeed < 0 || (t->c_ispeed && t->c_ispeed != t->c_ospeed) || 389 (cflag & CSIZE) == CS5 || (cflag & CSIZE) == CS6 || 390 (pmax_boardtype == DS_PMAX && t->c_ospeed == 19200)) 391 return (EINVAL); 392 /* and copy to tty */ 393 tp->t_ispeed = t->c_ispeed; 394 tp->t_ospeed = t->c_ospeed; 395 tp->t_cflag = cflag; 396 397 /* 398 * Handle console cases specially. 399 */ 400 if (cn_tab.cn_screen) { 401 if (unit == DCKBD_PORT) { 402 lpr = LPR_RXENAB | LPR_8_BIT_CHAR | 403 LPR_B4800 | DCKBD_PORT; 404 goto out; 405 } else if (unit == DCMOUSE_PORT) { 406 lpr = LPR_RXENAB | LPR_B4800 | LPR_OPAR | 407 LPR_PARENB | LPR_8_BIT_CHAR | DCMOUSE_PORT; 408 goto out; 409 } 410 } else if (tp->t_dev == cn_tab.cn_dev) { 411 lpr = LPR_RXENAB | LPR_8_BIT_CHAR | LPR_B9600 | unit; 412 goto out; 413 } 414 if (ospeed == 0) { 415 (void) dcmctl(unit, 0, DMSET); /* hang up line */ 416 return (0); 417 } 418 lpr = LPR_RXENAB | ospeed | (unit & 03); 419 if ((cflag & CSIZE) == CS7) 420 lpr |= LPR_7_BIT_CHAR; 421 else 422 lpr |= LPR_8_BIT_CHAR; 423 if (cflag & PARENB) 424 lpr |= LPR_PARENB; 425 if (cflag & PARODD) 426 lpr |= LPR_OPAR; 427 if (cflag & CSTOPB) 428 lpr |= LPR_2_STOP; 429 out: 430 dcaddr = (dcregs *)dcpdma[unit].p_addr; 431 s = spltty(); 432 dcaddr->dc_lpr = lpr; 433 MachEmptyWriteBuffer(); 434 splx(s); 435 DELAY(10); 436 return (0); 437 } 438 439 /* 440 * Check for interrupts from all devices. 441 */ 442 void 443 dcintr(unit) 444 register int unit; 445 { 446 register dcregs *dcaddr; 447 register unsigned csr; 448 449 unit <<= 2; 450 dcaddr = (dcregs *)dcpdma[unit].p_addr; 451 while ((csr = dcaddr->dc_csr) & (CSR_RDONE | CSR_TRDY)) { 452 if (csr & CSR_RDONE) 453 dcrint(unit); 454 if (csr & CSR_TRDY) 455 dcxint(&dc_tty[unit + ((csr >> 8) & 03)]); 456 } 457 } 458 459 dcrint(unit) 460 register int unit; 461 { 462 register dcregs *dcaddr; 463 register struct tty *tp; 464 register int c, cc; 465 register struct tty *tp0; 466 int overrun = 0; 467 468 dcaddr = (dcregs *)dcpdma[unit].p_addr; 469 tp0 = &dc_tty[unit]; 470 while ((c = dcaddr->dc_rbuf) < 0) { /* char present */ 471 cc = c & 0xff; 472 tp = tp0 + ((c >> 8) & 03); 473 if ((c & RBUF_OERR) && overrun == 0) { 474 log(LOG_WARNING, "dc%d,%d: silo overflow\n", unit >> 2, 475 (c >> 8) & 03); 476 overrun = 1; 477 } 478 /* the keyboard requires special translation */ 479 if (tp == &dc_tty[DCKBD_PORT] && cn_tab.cn_screen) { 480 #ifdef KADB 481 if (cc == LK_DO) { 482 spl0(); 483 kdbpanic(); 484 return; 485 } 486 #endif 487 #ifdef DEBUG 488 debugChar = cc; 489 #endif 490 if (dcDivertXInput) { 491 (*dcDivertXInput)(cc); 492 return; 493 } 494 if ((cc = kbdMapChar(cc)) < 0) 495 return; 496 } else if (tp == &dc_tty[DCMOUSE_PORT] && dcMouseButtons) { 497 register MouseReport *mrp; 498 static MouseReport currentRep; 499 500 mrp = ¤tRep; 501 mrp->byteCount++; 502 if (cc & MOUSE_START_FRAME) { 503 /* 504 * The first mouse report byte (button state). 505 */ 506 mrp->state = cc; 507 if (mrp->byteCount > 1) 508 mrp->byteCount = 1; 509 } else if (mrp->byteCount == 2) { 510 /* 511 * The second mouse report byte (delta x). 512 */ 513 mrp->dx = cc; 514 } else if (mrp->byteCount == 3) { 515 /* 516 * The final mouse report byte (delta y). 517 */ 518 mrp->dy = cc; 519 mrp->byteCount = 0; 520 if (mrp->dx != 0 || mrp->dy != 0) { 521 /* 522 * If the mouse moved, 523 * post a motion event. 524 */ 525 (*dcMouseEvent)(mrp); 526 } 527 (*dcMouseButtons)(mrp); 528 } 529 return; 530 } 531 if (!(tp->t_state & TS_ISOPEN)) { 532 wakeup((caddr_t)&tp->t_rawq); 533 #ifdef PORTSELECTOR 534 if (!(tp->t_state & TS_WOPEN)) 535 #endif 536 return; 537 } 538 if (c & RBUF_FERR) 539 cc |= TTY_FE; 540 if (c & RBUF_PERR) 541 cc |= TTY_PE; 542 if ((tp->t_cflag & CRTS_IFLOW) && !(tp->t_state & TS_TBLOCK) && 543 tp->t_rawq.c_cc + tp->t_canq.c_cc >= TTYHOG) { 544 tp->t_state &= ~TS_TBLOCK; 545 (void) dcmctl(tp->t_dev, DML_RTS, DMBIC); 546 } 547 (*linesw[tp->t_line].l_rint)(cc, tp); 548 } 549 DELAY(10); 550 } 551 552 void 553 dcxint(tp) 554 register struct tty *tp; 555 { 556 register struct pdma *dp; 557 register dcregs *dcaddr; 558 int unit; 559 560 dp = &dcpdma[unit = minor(tp->t_dev)]; 561 if (dp->p_mem < dp->p_end) { 562 dcaddr = (dcregs *)dp->p_addr; 563 /* check for hardware flow control of output */ 564 if ((tp->t_cflag & CCTS_OFLOW) && pmax_boardtype != DS_PMAX) { 565 switch (unit) { 566 case DCCOMM_PORT: 567 if (dcaddr->dc_msr & MSR_CTS2) 568 break; 569 goto stop; 570 571 case DCPRINTER_PORT: 572 if (dcaddr->dc_msr & MSR_CTS3) 573 break; 574 stop: 575 tp->t_state &= ~TS_BUSY; 576 tp->t_state |= TS_TTSTOP; 577 ndflush(&tp->t_outq, dp->p_mem-tp->t_outq.c_cf); 578 dp->p_end = dp->p_mem = tp->t_outq.c_cf; 579 dcaddr->dc_tcr &= ~(1 << unit); 580 MachEmptyWriteBuffer(); 581 DELAY(10); 582 return; 583 } 584 } 585 dcaddr->dc_tdr = dc_brk[unit >> 2] | *(u_char *)dp->p_mem; 586 dp->p_mem++; 587 MachEmptyWriteBuffer(); 588 DELAY(10); 589 return; 590 } 591 tp->t_state &= ~TS_BUSY; 592 if (tp->t_state & TS_FLUSH) 593 tp->t_state &= ~TS_FLUSH; 594 else { 595 ndflush(&tp->t_outq, dp->p_mem - tp->t_outq.c_cf); 596 dp->p_end = dp->p_mem = tp->t_outq.c_cf; 597 } 598 if (tp->t_line) 599 (*linesw[tp->t_line].l_start)(tp); 600 else 601 dcstart(tp); 602 if (tp->t_outq.c_cc == 0 || !(tp->t_state & TS_BUSY)) { 603 dcaddr = (dcregs *)dp->p_addr; 604 dcaddr->dc_tcr &= ~(1 << (unit & 03)); 605 MachEmptyWriteBuffer(); 606 DELAY(10); 607 } 608 } 609 610 void 611 dcstart(tp) 612 register struct tty *tp; 613 { 614 register struct pdma *dp; 615 register dcregs *dcaddr; 616 register int cc; 617 int unit, s; 618 619 dp = &dcpdma[unit = minor(tp->t_dev)]; 620 dcaddr = (dcregs *)dp->p_addr; 621 s = spltty(); 622 if (tp->t_state & (TS_TIMEOUT|TS_BUSY|TS_TTSTOP)) 623 goto out; 624 if (tp->t_outq.c_cc <= tp->t_lowat) { 625 if (tp->t_state & TS_ASLEEP) { 626 tp->t_state &= ~TS_ASLEEP; 627 wakeup((caddr_t)&tp->t_outq); 628 } 629 selwakeup(&tp->t_wsel); 630 } 631 if (tp->t_outq.c_cc == 0) 632 goto out; 633 /* handle console specially */ 634 if (tp == &dc_tty[DCKBD_PORT] && cn_tab.cn_screen) { 635 while (tp->t_outq.c_cc > 0) { 636 cc = getc(&tp->t_outq) & 0x7f; 637 cnputc(cc); 638 } 639 /* 640 * After we flush the output queue we may need to wake 641 * up the process that made the output. 642 */ 643 if (tp->t_outq.c_cc <= tp->t_lowat) { 644 if (tp->t_state & TS_ASLEEP) { 645 tp->t_state &= ~TS_ASLEEP; 646 wakeup((caddr_t)&tp->t_outq); 647 } 648 selwakeup(&tp->t_wsel); 649 } 650 goto out; 651 } 652 cc = ndqb(&tp->t_outq, 0); 653 tp->t_state |= TS_BUSY; 654 dp->p_end = dp->p_mem = tp->t_outq.c_cf; 655 dp->p_end += cc; 656 dcaddr->dc_tcr |= 1 << (unit & 03); 657 MachEmptyWriteBuffer(); 658 out: 659 splx(s); 660 } 661 662 /* 663 * Stop output on a line. 664 */ 665 /*ARGSUSED*/ 666 dcstop(tp, flag) 667 register struct tty *tp; 668 { 669 register struct pdma *dp; 670 register int s; 671 672 dp = &dcpdma[minor(tp->t_dev)]; 673 s = spltty(); 674 if (tp->t_state & TS_BUSY) { 675 dp->p_end = dp->p_mem; 676 if (!(tp->t_state & TS_TTSTOP)) 677 tp->t_state |= TS_FLUSH; 678 } 679 splx(s); 680 } 681 682 dcmctl(dev, bits, how) 683 dev_t dev; 684 int bits, how; 685 { 686 register dcregs *dcaddr; 687 register int unit, mbits; 688 int b, s; 689 register int tcr, msr; 690 691 unit = minor(dev); 692 b = 1 << (unit & 03); 693 dcaddr = (dcregs *)dcpdma[unit].p_addr; 694 s = spltty(); 695 /* only channel 2 has modem control on a DECstation 2100/3100 */ 696 mbits = DML_DTR | DML_RTS | DML_DSR | DML_CAR; 697 switch (unit & 03) { 698 case 2: 699 mbits = 0; 700 tcr = dcaddr->dc_tcr; 701 if (tcr & TCR_DTR2) 702 mbits |= DML_DTR; 703 if (pmax_boardtype != DS_PMAX && (tcr & TCR_RTS2)) 704 mbits |= DML_RTS; 705 msr = dcaddr->dc_msr; 706 if (msr & MSR_CD2) 707 mbits |= DML_CAR; 708 if (msr & MSR_DSR2) { 709 if (pmax_boardtype == DS_PMAX) 710 mbits |= DML_CAR | DML_DSR; 711 else 712 mbits |= DML_DSR; 713 } 714 break; 715 716 case 3: 717 if (pmax_boardtype != DS_PMAX) { 718 mbits = 0; 719 tcr = dcaddr->dc_tcr; 720 if (tcr & TCR_DTR3) 721 mbits |= DML_DTR; 722 if (tcr & TCR_RTS3) 723 mbits |= DML_RTS; 724 msr = dcaddr->dc_msr; 725 if (msr & MSR_CD3) 726 mbits |= DML_CAR; 727 if (msr & MSR_DSR3) 728 mbits |= DML_DSR; 729 } 730 } 731 switch (how) { 732 case DMSET: 733 mbits = bits; 734 break; 735 736 case DMBIS: 737 mbits |= bits; 738 break; 739 740 case DMBIC: 741 mbits &= ~bits; 742 break; 743 744 case DMGET: 745 (void) splx(s); 746 return (mbits); 747 } 748 switch (unit & 03) { 749 case 2: 750 tcr = dcaddr->dc_tcr; 751 if (mbits & DML_DTR) 752 tcr |= TCR_DTR2; 753 else 754 tcr &= ~TCR_DTR2; 755 if (pmax_boardtype != DS_PMAX) { 756 if (mbits & DML_RTS) 757 tcr |= TCR_RTS2; 758 else 759 tcr &= ~TCR_RTS2; 760 } 761 dcaddr->dc_tcr = tcr; 762 break; 763 764 case 3: 765 if (pmax_boardtype != DS_PMAX) { 766 tcr = dcaddr->dc_tcr; 767 if (mbits & DML_DTR) 768 tcr |= TCR_DTR3; 769 else 770 tcr &= ~TCR_DTR3; 771 if (mbits & DML_RTS) 772 tcr |= TCR_RTS3; 773 else 774 tcr &= ~TCR_RTS3; 775 dcaddr->dc_tcr = tcr; 776 } 777 } 778 if ((mbits & DML_DTR) && (dcsoftCAR[unit >> 2] & b)) 779 dc_tty[unit].t_state |= TS_CARR_ON; 780 (void) splx(s); 781 return (mbits); 782 } 783 784 /* 785 * This is called by timeout() periodically. 786 * Check to see if modem status bits have changed. 787 */ 788 void 789 dcscan(arg) 790 void *arg; 791 { 792 register dcregs *dcaddr; 793 register struct tty *tp; 794 register int unit, limit, dtr, dsr; 795 int s; 796 797 /* only channel 2 has modem control on a DECstation 2100/3100 */ 798 dtr = TCR_DTR2; 799 dsr = MSR_DSR2; 800 limit = (pmax_boardtype == DS_PMAX) ? 2 : 3; 801 s = spltty(); 802 for (unit = 2; unit <= limit; unit++, dtr >>= 2, dsr >>= 8) { 803 tp = &dc_tty[unit]; 804 dcaddr = (dcregs *)dcpdma[unit].p_addr; 805 if (dcaddr->dc_msr & dsr) { 806 /* carrier present */ 807 if (!(tp->t_state & TS_CARR_ON)) 808 (void)(*linesw[tp->t_line].l_modem)(tp, 1); 809 } else if ((tp->t_state & TS_CARR_ON) && 810 (*linesw[tp->t_line].l_modem)(tp, 0) == 0) 811 dcaddr->dc_tcr &= ~dtr; 812 /* 813 * If we are using hardware flow control and output is stopped, 814 * then resume transmit. 815 */ 816 if ((tp->t_cflag & CCTS_OFLOW) && (tp->t_state & TS_TTSTOP) && 817 pmax_boardtype != DS_PMAX) { 818 switch (unit) { 819 case DCCOMM_PORT: 820 if (dcaddr->dc_msr & MSR_CTS2) 821 break; 822 continue; 823 824 case DCPRINTER_PORT: 825 if (dcaddr->dc_msr & MSR_CTS3) 826 break; 827 continue; 828 } 829 tp->t_state &= ~TS_TTSTOP; 830 dcstart(tp); 831 } 832 } 833 splx(s); 834 timeout(dcscan, (void *)0, hz); 835 } 836 837 /* 838 * ---------------------------------------------------------------------------- 839 * 840 * dcGetc -- 841 * 842 * Read a character from a serial line. 843 * 844 * Results: 845 * A character read from the serial port. 846 * 847 * Side effects: 848 * None. 849 * 850 * ---------------------------------------------------------------------------- 851 */ 852 int 853 dcGetc(dev) 854 dev_t dev; 855 { 856 register dcregs *dcaddr; 857 register int c; 858 int s; 859 860 dcaddr = (dcregs *)dcpdma[minor(dev)].p_addr; 861 if (!dcaddr) 862 return (0); 863 s = spltty(); 864 for (;;) { 865 if (!(dcaddr->dc_csr & CSR_RDONE)) 866 continue; 867 c = dcaddr->dc_rbuf; 868 DELAY(10); 869 if (((c >> 8) & 03) == (minor(dev) & 03)) 870 break; 871 } 872 splx(s); 873 return (c & 0xff); 874 } 875 876 /* 877 * Send a char on a port, non interrupt driven. 878 */ 879 void 880 dcPutc(dev, c) 881 dev_t dev; 882 int c; 883 { 884 register dcregs *dcaddr; 885 register u_short tcr; 886 register int timeout; 887 int s, line; 888 889 s = spltty(); 890 891 dcaddr = (dcregs *)dcpdma[minor(dev)].p_addr; 892 tcr = dcaddr->dc_tcr; 893 dcaddr->dc_tcr = tcr | (1 << minor(dev)); 894 MachEmptyWriteBuffer(); 895 DELAY(10); 896 while (1) { 897 /* 898 * Wait for transmitter to be not busy. 899 */ 900 timeout = 1000000; 901 while (!(dcaddr->dc_csr & CSR_TRDY) && timeout > 0) 902 timeout--; 903 if (timeout == 0) { 904 printf("dcPutc: timeout waiting for CSR_TRDY\n"); 905 break; 906 } 907 line = (dcaddr->dc_csr >> 8) & 3; 908 /* 909 * Check to be sure its the right port. 910 */ 911 if (line != minor(dev)) { 912 tcr |= 1 << line; 913 dcaddr->dc_tcr &= ~(1 << line); 914 MachEmptyWriteBuffer(); 915 DELAY(10); 916 continue; 917 } 918 /* 919 * Start sending the character. 920 */ 921 dcaddr->dc_tdr = dc_brk[0] | (c & 0xff); 922 MachEmptyWriteBuffer(); 923 DELAY(10); 924 /* 925 * Wait for character to be sent. 926 */ 927 while (1) { 928 /* 929 * cc -O bug: this code produces and infinite loop! 930 * while (!(dcaddr->dc_csr & CSR_TRDY)) 931 * ; 932 */ 933 timeout = 1000000; 934 while (!(dcaddr->dc_csr & CSR_TRDY) && timeout > 0) 935 timeout--; 936 line = (dcaddr->dc_csr >> 8) & 3; 937 if (line != minor(dev)) { 938 tcr |= 1 << line; 939 dcaddr->dc_tcr &= ~(1 << line); 940 MachEmptyWriteBuffer(); 941 DELAY(10); 942 continue; 943 } 944 dcaddr->dc_tcr &= ~(1 << minor(dev)); 945 MachEmptyWriteBuffer(); 946 DELAY(10); 947 break; 948 } 949 break; 950 } 951 /* 952 * Enable interrupts for other lines which became ready. 953 */ 954 if (tcr & 0xF) { 955 dcaddr->dc_tcr = tcr; 956 MachEmptyWriteBuffer(); 957 DELAY(10); 958 } 959 960 splx(s); 961 } 962 #endif /* NDC */ 963