1 /*- 2 * Copyright (c) 1992 The Regents of the University of California. 3 * 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 * @(#)scc.c 7.2 (Berkeley) 12/20/92 11 */ 12 13 /* 14 * Mach Operating System 15 * Copyright (c) 1991,1990,1989 Carnegie Mellon University 16 * All Rights Reserved. 17 * 18 * Permission to use, copy, modify and distribute this software and its 19 * documentation is hereby granted, provided that both the copyright 20 * notice and this permission notice appear in all copies of the 21 * software, derivative works or modified versions, and any portions 22 * thereof, and that both notices appear in supporting documentation. 23 * 24 * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS 25 * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR 26 * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE. 27 * 28 * Carnegie Mellon requests users of this software to return to 29 * 30 * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU 31 * School of Computer Science 32 * Carnegie Mellon University 33 * Pittsburgh PA 15213-3890 34 * 35 * any improvements or extensions that they make and grant Carnegie the 36 * rights to redistribute these changes. 37 */ 38 39 #include <scc.h> 40 #if NSCC > 0 41 /* 42 * Intel 82530 dual usart chip driver. Supports the serial port(s) on the 43 * Personal DECstation 5000/xx and DECstation 5000/1xx, plus the keyboard 44 * and mouse on the 5000/1xx. (Don't ask me where the A channel signals 45 * are on the 5000/xx.) 46 * 47 * See: Intel MicroCommunications Handbook, Section 2, pg. 155-173, 1992. 48 */ 49 #include <sys/param.h> 50 #include <sys/systm.h> 51 #include <sys/ioctl.h> 52 #include <sys/tty.h> 53 #include <sys/proc.h> 54 #include <sys/map.h> 55 #include <sys/buf.h> 56 #include <sys/conf.h> 57 #include <sys/file.h> 58 #include <sys/uio.h> 59 #include <sys/kernel.h> 60 #include <sys/syslog.h> 61 62 #include <machine/pmioctl.h> 63 64 #include <pmax/dev/device.h> 65 #include <pmax/dev/pdma.h> 66 #include <pmax/dev/sccreg.h> 67 #include <pmax/dev/fbreg.h> 68 69 #include <pmax/pmax/cons.h> 70 #include <pmax/pmax/pmaxtype.h> 71 72 extern int pmax_boardtype; 73 extern struct consdev cn_tab; 74 extern void ttrstrt __P((void *)); 75 extern void KBDReset __P((dev_t, void (*)())); 76 extern void MouseInit __P((dev_t, void (*)(), int (*)())); 77 78 /* 79 * Driver information for auto-configuration stuff. 80 */ 81 int sccprobe(), sccopen(), sccparam(), sccGetc(); 82 void sccintr(), sccstart(), sccPutc(); 83 struct driver sccdriver = { 84 "scc", sccprobe, 0, 0, sccintr, 85 }; 86 87 #define NSCCLINE (NSCC*2) 88 #define SCCUNIT(dev) (minor(dev) >> 1) 89 #define SCCLINE(dev) (minor(dev) & 0x1) 90 91 struct tty scc_tty[NSCCLINE]; 92 void (*sccDivertXInput)(); /* X windows keyboard input routine */ 93 void (*sccMouseEvent)(); /* X windows mouse motion event routine */ 94 void (*sccMouseButtons)(); /* X windows mouse buttons event routine */ 95 #ifdef DEBUG 96 int debugChar; 97 #endif 98 static void scc_modem_intr(), sccreset(); 99 100 struct scc_softc { 101 struct pdma scc_pdma[2]; 102 struct { 103 u_char wr1; 104 u_char wr3; 105 u_char wr4; 106 u_char wr5; 107 u_char wr14; 108 } scc_wreg[2]; 109 int scc_softCAR; 110 } scc_softc[NSCC]; 111 112 struct speedtab sccspeedtab[] = { 113 0, 0, 114 50, 4606, 115 75, 3070, 116 110, 2093, 117 134, 1711, 118 150, 1534, 119 300, 766, 120 600, 382, 121 1200, 190, 122 1800, 126, 123 2400, 94, 124 4800, 46, 125 9600, 22, 126 19200, 10, 127 38400, 4, 128 -1, -1 129 }; 130 131 #ifndef PORTSELECTOR 132 #define ISPEED TTYDEF_SPEED 133 #define LFLAG TTYDEF_LFLAG 134 #else 135 #define ISPEED B4800 136 #define LFLAG (TTYDEF_LFLAG & ~ECHO) 137 #endif 138 139 /* 140 * Test to see if device is present. 141 * Return true if found and initialized ok. 142 */ 143 sccprobe(cp) 144 register struct pmax_ctlr *cp; 145 { 146 register struct scc_softc *sc; 147 register struct pdma *pdp; 148 register struct tty *tp; 149 register int cntr; 150 struct tty ctty; 151 struct termios cterm; 152 int s; 153 154 if (cp->pmax_unit >= NSCC) 155 return (0); 156 if (badaddr(cp->pmax_addr, 2)) 157 return (0); 158 159 /* 160 * For a remote console, wait a while for previous output to 161 * complete. 162 */ 163 if (major(cn_tab.cn_dev) == SCCDEV && cn_tab.cn_screen == 0 && 164 SCCUNIT(cn_tab.cn_dev) == cp->pmax_unit) 165 DELAY(10000); 166 167 sc = &scc_softc[cp->pmax_unit]; 168 pdp = &sc->scc_pdma[0]; 169 170 /* init pseudo DMA structures */ 171 tp = &scc_tty[cp->pmax_unit * 2]; 172 for (cntr = 0; cntr < 2; cntr++) { 173 pdp->p_addr = (void *)cp->pmax_addr; 174 pdp->p_arg = (int)tp; 175 pdp->p_fcn = (void (*)())0; 176 tp->t_addr = (caddr_t)pdp; 177 tp->t_dev = (dev_t)((cp->pmax_unit << 1) | cntr); 178 pdp++, tp++; 179 } 180 sc->scc_softCAR = cp->pmax_flags | 0x2; 181 182 /* reset chip */ 183 sccreset(sc); 184 185 /* 186 * Special handling for consoles. 187 */ 188 if (cn_tab.cn_screen) { 189 if (cn_tab.cn_kbdgetc == sccGetc) { 190 if (cp->pmax_unit == 0) { 191 s = spltty(); 192 ctty.t_dev = makedev(SCCDEV, SCCKBD_PORT); 193 cterm.c_cflag = CS8; 194 cterm.c_ospeed = cterm.c_ispeed = 4800; 195 (void) sccparam(&ctty, &cterm); 196 DELAY(1000); 197 KBDReset(ctty.t_dev, sccPutc); 198 splx(s); 199 } else if (cp->pmax_unit == 1) { 200 s = spltty(); 201 ctty.t_dev = makedev(SCCDEV, SCCMOUSE_PORT); 202 cterm.c_cflag = CS8 | PARENB | PARODD; 203 cterm.c_ospeed = cterm.c_ispeed = 4800; 204 (void) sccparam(&ctty, &cterm); 205 DELAY(1000); 206 MouseInit(ctty.t_dev, sccPutc, sccGetc); 207 splx(s); 208 } 209 } 210 } else if (SCCUNIT(cn_tab.cn_dev) == cp->pmax_unit) { 211 s = spltty(); 212 ctty.t_dev = cn_tab.cn_dev; 213 cterm.c_cflag = CS8; 214 cterm.c_ospeed = cterm.c_ispeed = 9600; 215 (void) sccparam(&ctty, &cterm); 216 DELAY(1000); 217 cn_tab.cn_disabled = 0; 218 splx(s); 219 } 220 printf("scc%d at nexus0 csr 0x%x priority %d\n", 221 cp->pmax_unit, cp->pmax_addr, cp->pmax_pri); 222 return (1); 223 } 224 225 /* 226 * Reset the chip. 227 */ 228 static void 229 sccreset(sc) 230 register struct scc_softc *sc; 231 { 232 register scc_regmap_t *regs; 233 register u_char val; 234 235 regs = (scc_regmap_t *)sc->scc_pdma[0].p_addr; 236 /* 237 * Chip once-only initialization 238 * 239 * NOTE: The wiring we assume is the one on the 3min: 240 * 241 * out A-TxD --> TxD keybd or mouse 242 * in A-RxD --> RxD keybd or mouse 243 * out A-DTR~ --> DTR comm 244 * out A-RTS~ --> RTS comm 245 * in A-CTS~ --> SI comm 246 * in A-DCD~ --> RI comm 247 * in A-SYNCH~--> DSR comm 248 * out B-TxD --> TxD comm 249 * in B-RxD --> RxD comm 250 * in B-RxC --> TRxCB comm 251 * in B-TxC --> RTxCB comm 252 * out B-RTS~ --> SS comm 253 * in B-CTS~ --> CTS comm 254 * in B-DCD~ --> CD comm 255 */ 256 SCC_INIT_REG(regs, SCC_CHANNEL_A); 257 SCC_INIT_REG(regs, SCC_CHANNEL_B); 258 SCC_WRITE_REG(regs, SCC_CHANNEL_A, SCC_WR9, SCC_WR9_HW_RESET); 259 DELAY(50000); /*enough ? */ 260 SCC_WRITE_REG(regs, SCC_CHANNEL_A, SCC_WR9, 0); 261 262 /* program the interrupt vector */ 263 SCC_WRITE_REG(regs, SCC_CHANNEL_A, SCC_WR2, 0xf0); 264 SCC_WRITE_REG(regs, SCC_CHANNEL_B, SCC_WR2, 0xf0); 265 SCC_WRITE_REG(regs, SCC_CHANNEL_A, SCC_WR9, SCC_WR9_VIS); 266 267 /* timing base defaults */ 268 sc->scc_wreg[SCC_CHANNEL_A].wr4 = SCC_WR4_CLK_x16; 269 sc->scc_wreg[SCC_CHANNEL_B].wr4 = SCC_WR4_CLK_x16; 270 271 /* enable DTR, RTS and SS */ 272 sc->scc_wreg[SCC_CHANNEL_B].wr5 = SCC_WR5_RTS; 273 sc->scc_wreg[SCC_CHANNEL_A].wr5 = SCC_WR5_RTS | SCC_WR5_DTR; 274 275 /* baud rates */ 276 val = SCC_WR14_BAUDR_ENABLE|SCC_WR14_BAUDR_SRC; 277 sc->scc_wreg[SCC_CHANNEL_B].wr14 = val; 278 sc->scc_wreg[SCC_CHANNEL_A].wr14 = val; 279 280 /* interrupt conditions */ 281 val = SCC_WR1_RXI_ALL_CHAR | SCC_WR1_PARITY_IE | 282 SCC_WR1_EXT_IE; 283 sc->scc_wreg[SCC_CHANNEL_A].wr1 = val; 284 sc->scc_wreg[SCC_CHANNEL_B].wr1 = val; 285 } 286 287 sccopen(dev, flag, mode, p) 288 dev_t dev; 289 int flag, mode; 290 struct proc *p; 291 { 292 register struct scc_softc *sc; 293 register struct tty *tp; 294 register int unit, line; 295 int s, error = 0; 296 297 unit = SCCUNIT(dev); 298 if (unit >= NSCC) 299 return (ENXIO); 300 line = SCCLINE(dev); 301 sc = &scc_softc[unit]; 302 if (sc->scc_pdma[line].p_addr == (void *)0) 303 return (ENXIO); 304 tp = &scc_tty[minor(dev)]; 305 tp->t_addr = (caddr_t)&sc->scc_pdma[line]; 306 tp->t_oproc = sccstart; 307 tp->t_param = sccparam; 308 tp->t_dev = dev; 309 if ((tp->t_state & TS_ISOPEN) == 0) { 310 tp->t_state |= TS_WOPEN; 311 ttychars(tp); 312 #ifndef PORTSELECTOR 313 if (tp->t_ispeed == 0) { 314 #endif 315 tp->t_iflag = TTYDEF_IFLAG; 316 tp->t_oflag = TTYDEF_OFLAG; 317 tp->t_cflag = TTYDEF_CFLAG; 318 tp->t_lflag = LFLAG; 319 tp->t_ispeed = tp->t_ospeed = ISPEED; 320 #ifdef PORTSELECTOR 321 tp->t_cflag |= HUPCL; 322 #else 323 } 324 #endif 325 (void) sccparam(tp, &tp->t_termios); 326 ttsetwater(tp); 327 } else if ((tp->t_state & TS_XCLUDE) && curproc->p_ucred->cr_uid != 0) 328 return (EBUSY); 329 (void) sccmctl(dev, DML_DTR, DMSET); 330 s = spltty(); 331 while (!(flag & O_NONBLOCK) && !(tp->t_cflag & CLOCAL) && 332 !(tp->t_state & TS_CARR_ON)) { 333 tp->t_state |= TS_WOPEN; 334 if (error = ttysleep(tp, (caddr_t)&tp->t_rawq, TTIPRI | PCATCH, 335 ttopen, 0)) 336 break; 337 } 338 splx(s); 339 if (error) 340 return (error); 341 return ((*linesw[tp->t_line].l_open)(dev, tp)); 342 } 343 344 /*ARGSUSED*/ 345 sccclose(dev, flag, mode, p) 346 dev_t dev; 347 int flag, mode; 348 struct proc *p; 349 { 350 register struct scc_softc *sc = &scc_softc[SCCUNIT(dev)]; 351 register struct tty *tp; 352 register int bit, line; 353 354 tp = &scc_tty[minor(dev)]; 355 line = SCCLINE(dev); 356 if (sc->scc_wreg[line].wr5 & SCC_WR5_SEND_BREAK) { 357 sc->scc_wreg[line].wr5 &= ~SCC_WR5_SEND_BREAK; 358 ttyoutput(0, tp); 359 } 360 (*linesw[tp->t_line].l_close)(tp, flag); 361 if ((tp->t_cflag & HUPCL) || (tp->t_state & TS_WOPEN) || 362 !(tp->t_state & TS_ISOPEN)) 363 (void) sccmctl(dev, 0, DMSET); 364 return (ttyclose(tp)); 365 } 366 367 sccread(dev, uio, flag) 368 dev_t dev; 369 struct uio *uio; 370 { 371 register struct tty *tp; 372 373 tp = &scc_tty[minor(dev)]; 374 return ((*linesw[tp->t_line].l_read)(tp, uio, flag)); 375 } 376 377 sccwrite(dev, uio, flag) 378 dev_t dev; 379 struct uio *uio; 380 { 381 register struct tty *tp; 382 383 tp = &scc_tty[minor(dev)]; 384 return ((*linesw[tp->t_line].l_write)(tp, uio, flag)); 385 } 386 387 /*ARGSUSED*/ 388 sccioctl(dev, cmd, data, flag, p) 389 dev_t dev; 390 int cmd; 391 caddr_t data; 392 int flag; 393 struct proc *p; 394 { 395 register struct scc_softc *sc; 396 register struct tty *tp; 397 int error, line; 398 399 tp = &scc_tty[minor(dev)]; 400 error = (*linesw[tp->t_line].l_ioctl)(tp, cmd, data, flag, p); 401 if (error >= 0) 402 return (error); 403 error = ttioctl(tp, cmd, data, flag); 404 if (error >= 0) 405 return (error); 406 407 line = SCCLINE(dev); 408 sc = &scc_softc[SCCUNIT(dev)]; 409 switch (cmd) { 410 411 case TIOCSBRK: 412 sc->scc_wreg[line].wr5 |= SCC_WR5_SEND_BREAK; 413 ttyoutput(0, tp); 414 break; 415 416 case TIOCCBRK: 417 sc->scc_wreg[line].wr5 &= ~SCC_WR5_SEND_BREAK; 418 ttyoutput(0, tp); 419 break; 420 421 case TIOCSDTR: 422 (void) sccmctl(dev, DML_DTR|DML_RTS, DMBIS); 423 break; 424 425 case TIOCCDTR: 426 (void) sccmctl(dev, DML_DTR|DML_RTS, DMBIC); 427 break; 428 429 case TIOCMSET: 430 (void) sccmctl(dev, *(int *)data, DMSET); 431 break; 432 433 case TIOCMBIS: 434 (void) sccmctl(dev, *(int *)data, DMBIS); 435 break; 436 437 case TIOCMBIC: 438 (void) sccmctl(dev, *(int *)data, DMBIC); 439 break; 440 441 case TIOCMGET: 442 *(int *)data = sccmctl(dev, 0, DMGET); 443 break; 444 445 default: 446 return (ENOTTY); 447 } 448 return (0); 449 } 450 451 sccparam(tp, t) 452 register struct tty *tp; 453 register struct termios *t; 454 { 455 register struct scc_softc *sc; 456 register scc_regmap_t *regs; 457 register int line; 458 register u_char value, wvalue; 459 register int cflag = t->c_cflag; 460 int ospeed; 461 462 if (t->c_ispeed && t->c_ispeed != t->c_ospeed) 463 return (EINVAL); 464 sc = &scc_softc[SCCUNIT(tp->t_dev)]; 465 line = SCCLINE(tp->t_dev); 466 regs = (scc_regmap_t *)sc->scc_pdma[line].p_addr; 467 ospeed = ttspeedtab(t->c_ospeed, sccspeedtab); 468 if (ospeed < 0) 469 return (EINVAL); 470 /* and copy to tty */ 471 tp->t_ispeed = t->c_ispeed; 472 tp->t_ospeed = t->c_ospeed; 473 tp->t_cflag = cflag; 474 475 /* 476 * Handle console specially. 477 */ 478 if (cn_tab.cn_screen) { 479 if (minor(tp->t_dev) == SCCKBD_PORT) { 480 cflag = CS8; 481 ospeed = ttspeedtab(4800, sccspeedtab); 482 } else if (minor(tp->t_dev) == SCCMOUSE_PORT) { 483 cflag = CS8 | PARENB | PARODD; 484 ospeed = ttspeedtab(4800, sccspeedtab); 485 } 486 } else if (tp->t_dev == cn_tab.cn_dev) { 487 cflag = CS8; 488 ospeed = ttspeedtab(9600, sccspeedtab); 489 } 490 if (ospeed == 0) { 491 (void) sccmctl(tp->t_dev, 0, DMSET); /* hang up line */ 492 return (0); 493 } 494 495 /* reset line */ 496 if (line == SCC_CHANNEL_A) 497 value = SCC_WR9_RESET_CHA_A; 498 else 499 value = SCC_WR9_RESET_CHA_B; 500 SCC_WRITE_REG(regs, line, SCC_WR9, value); 501 DELAY(25); 502 503 /* stop bits, normally 1 */ 504 value = sc->scc_wreg[line].wr4 & 0xf0; 505 if (cflag & CSTOPB) 506 value |= SCC_WR4_2_STOP; 507 else 508 value |= SCC_WR4_1_STOP; 509 if ((cflag & PARODD) == 0) 510 value |= SCC_WR4_EVEN_PARITY; 511 if (cflag & PARENB) 512 value |= SCC_WR4_PARITY_ENABLE; 513 514 /* set it now, remember it must be first after reset */ 515 sc->scc_wreg[line].wr4 = value; 516 SCC_WRITE_REG(regs, line, SCC_WR4, value); 517 518 /* vector again */ 519 SCC_WRITE_REG(regs, line, SCC_WR2, 0xf0); 520 521 /* clear break, keep rts dtr */ 522 wvalue = sc->scc_wreg[line].wr5 & (SCC_WR5_DTR|SCC_WR5_RTS); 523 switch (cflag & CSIZE) { 524 case CS5: 525 value = SCC_WR3_RX_5_BITS; 526 wvalue |= SCC_WR5_TX_5_BITS; 527 break; 528 case CS6: 529 value = SCC_WR3_RX_6_BITS; 530 wvalue |= SCC_WR5_TX_6_BITS; 531 break; 532 case CS7: 533 value = SCC_WR3_RX_7_BITS; 534 wvalue |= SCC_WR5_TX_7_BITS; 535 break; 536 case CS8: 537 default: 538 value = SCC_WR3_RX_8_BITS; 539 wvalue |= SCC_WR5_TX_8_BITS; 540 }; 541 sc->scc_wreg[line].wr3 = value; 542 SCC_WRITE_REG(regs, line, SCC_WR3, value); 543 sc->scc_wreg[line].wr5 = wvalue; 544 SCC_WRITE_REG(regs, line, SCC_WR5, wvalue); 545 SCC_WRITE_REG(regs, line, SCC_WR6, 0); 546 SCC_WRITE_REG(regs, line, SCC_WR7, 0); 547 SCC_WRITE_REG(regs, line, SCC_WR9, SCC_WR9_VIS); 548 SCC_WRITE_REG(regs, line, SCC_WR10, 0); 549 value = SCC_WR11_RCLK_BAUDR | SCC_WR11_XTLK_BAUDR | 550 SCC_WR11_TRc_OUT | SCC_WR11_TRcOUT_BAUDR; 551 SCC_WRITE_REG(regs, line, SCC_WR11, value); 552 SCC_SET_TIMING_BASE(regs, line, ospeed); 553 value = sc->scc_wreg[line].wr14; 554 SCC_WRITE_REG(regs, line, SCC_WR14, value); 555 value = SCC_WR15_BREAK_IE | SCC_WR15_CTS_IE | SCC_WR15_DCD_IE; 556 SCC_WRITE_REG(regs, line, SCC_WR15, value); 557 558 /* and now the enables */ 559 value = sc->scc_wreg[line].wr3 | SCC_WR3_RX_ENABLE; 560 SCC_WRITE_REG(regs, line, SCC_WR3, value); 561 value = sc->scc_wreg[line].wr5 | SCC_WR5_TX_ENABLE; 562 sc->scc_wreg[line].wr5 = value; 563 SCC_WRITE_REG(regs, line, SCC_WR5, value); 564 565 /* master inter enable */ 566 value = SCC_WR9_MASTER_IE | SCC_WR9_VIS; 567 SCC_WRITE_REG(regs, line, SCC_WR9, value); 568 SCC_WRITE_REG(regs, line, SCC_WR1, sc->scc_wreg[line].wr1); 569 MachEmptyWriteBuffer(); 570 return (0); 571 } 572 573 /* 574 * Check for interrupts from all devices. 575 */ 576 void 577 sccintr(unit) 578 register int unit; 579 { 580 register scc_regmap_t *regs; 581 register struct tty *tp; 582 register struct pdma *dp; 583 register struct scc_softc *sc; 584 register int cc, chan, rr1, rr2, rr3; 585 int overrun = 0; 586 587 sc = &scc_softc[unit]; 588 regs = (scc_regmap_t *)sc->scc_pdma[0].p_addr; 589 unit <<= 1; 590 for (;;) { 591 SCC_READ_REG(regs, SCC_CHANNEL_B, SCC_RR2, rr2); 592 rr2 = SCC_RR2_STATUS(rr2); 593 /* are we done yet ? */ 594 if (rr2 == 6) { /* strange, distinguished value */ 595 SCC_READ_REG(regs, SCC_CHANNEL_A, SCC_RR3, rr3); 596 if (rr3 == 0) 597 return; 598 } 599 600 SCC_WRITE_REG(regs, SCC_CHANNEL_A, SCC_RR0, SCC_RESET_HIGHEST_IUS); 601 if ((rr2 == SCC_RR2_A_XMIT_DONE) || (rr2 == SCC_RR2_B_XMIT_DONE)) { 602 chan = (rr2 == SCC_RR2_A_XMIT_DONE) ? 603 SCC_CHANNEL_A : SCC_CHANNEL_B; 604 tp = &scc_tty[unit | chan]; 605 dp = (struct pdma *)tp->t_addr; 606 if (dp->p_mem < dp->p_end) { 607 SCC_WRITE_DATA(regs, chan, *dp->p_mem++); 608 MachEmptyWriteBuffer(); 609 } else { 610 tp->t_state &= ~TS_BUSY; 611 if (tp->t_state & TS_FLUSH) 612 tp->t_state &= ~TS_FLUSH; 613 else { 614 ndflush(&tp->t_outq, dp->p_mem-tp->t_outq.c_cf); 615 dp->p_end = dp->p_mem = tp->t_outq.c_cf; 616 } 617 if (tp->t_line) 618 (*linesw[tp->t_line].l_start)(tp); 619 else 620 sccstart(tp); 621 if (tp->t_outq.c_cc == 0 || !(tp->t_state & TS_BUSY)) { 622 SCC_READ_REG(regs, chan, SCC_RR15, cc); 623 cc &= ~SCC_WR15_TX_UNDERRUN_IE; 624 SCC_WRITE_REG(regs, chan, SCC_WR15, cc); 625 cc = sc->scc_wreg[chan].wr1 & ~SCC_WR1_TX_IE; 626 SCC_WRITE_REG(regs, chan, SCC_WR1, cc); 627 sc->scc_wreg[chan].wr1 = cc; 628 MachEmptyWriteBuffer(); 629 } 630 } 631 } else if (rr2 == SCC_RR2_A_RECV_DONE || 632 rr2 == SCC_RR2_B_RECV_DONE || rr2 == SCC_RR2_A_RECV_SPECIAL || 633 rr2 == SCC_RR2_B_RECV_SPECIAL) { 634 if (rr2 == SCC_RR2_A_RECV_DONE || rr2 == SCC_RR2_A_RECV_SPECIAL) 635 chan = SCC_CHANNEL_A; 636 else 637 chan = SCC_CHANNEL_B; 638 tp = &scc_tty[unit | chan]; 639 SCC_READ_DATA(regs, chan, cc); 640 if (rr2 == SCC_RR2_A_RECV_SPECIAL || 641 rr2 == SCC_RR2_B_RECV_SPECIAL) { 642 SCC_READ_REG(regs, chan, SCC_RR1, rr1); 643 SCC_WRITE_REG(regs, chan, SCC_RR0, SCC_RESET_ERROR); 644 if ((rr1 & SCC_RR1_RX_OVERRUN) && overrun == 0) { 645 log(LOG_WARNING, "scc%d,%d: silo overflow\n", 646 unit >> 1, chan); 647 overrun = 1; 648 } 649 } 650 651 /* 652 * Keyboard needs special treatment. 653 */ 654 if (tp == &scc_tty[SCCKBD_PORT] && cn_tab.cn_screen) { 655 #ifdef KADB 656 if (cc == LK_DO) { 657 spl0(); 658 kdbpanic(); 659 return; 660 } 661 #endif 662 #ifdef DEBUG 663 debugChar = cc; 664 #endif 665 if (sccDivertXInput) { 666 (*sccDivertXInput)(cc); 667 continue; 668 } 669 if ((cc = kbdMapChar(cc)) < 0) 670 continue; 671 /* 672 * Now for mousey 673 */ 674 } else if (tp == &scc_tty[SCCMOUSE_PORT] && sccMouseButtons) { 675 register MouseReport *mrp; 676 static MouseReport currentRep; 677 678 mrp = ¤tRep; 679 mrp->byteCount++; 680 if (cc & MOUSE_START_FRAME) { 681 /* 682 * The first mouse report byte (button state). 683 */ 684 mrp->state = cc; 685 if (mrp->byteCount > 1) 686 mrp->byteCount = 1; 687 } else if (mrp->byteCount == 2) { 688 /* 689 * The second mouse report byte (delta x). 690 */ 691 mrp->dx = cc; 692 } else if (mrp->byteCount == 3) { 693 /* 694 * The final mouse report byte (delta y). 695 */ 696 mrp->dy = cc; 697 mrp->byteCount = 0; 698 if (mrp->dx != 0 || mrp->dy != 0) { 699 /* 700 * If the mouse moved, 701 * post a motion event. 702 */ 703 (*sccMouseEvent)(mrp); 704 } 705 (*sccMouseButtons)(mrp); 706 } 707 continue; 708 } 709 if (!(tp->t_state & TS_ISOPEN)) { 710 wakeup((caddr_t)&tp->t_rawq); 711 #ifdef PORTSELECTOR 712 if (!(tp->t_state & TS_WOPEN)) 713 #endif 714 continue; 715 } 716 if (rr2 == SCC_RR2_A_RECV_SPECIAL || 717 rr2 == SCC_RR2_B_RECV_SPECIAL) { 718 if (rr1 & SCC_RR1_PARITY_ERR) 719 cc |= TTY_PE; 720 if (rr1 & SCC_RR1_FRAME_ERR) 721 cc |= TTY_FE; 722 } 723 (*linesw[tp->t_line].l_rint)(cc, tp); 724 } else if ((rr2 == SCC_RR2_A_EXT_STATUS) || (rr2 == SCC_RR2_B_EXT_STATUS)) { 725 chan = (rr2 == SCC_RR2_A_EXT_STATUS) ? 726 SCC_CHANNEL_A : SCC_CHANNEL_B; 727 SCC_WRITE_REG(regs, chan, SCC_RR0, SCC_RESET_EXT_IP); 728 scc_modem_intr(unit | chan); 729 } 730 } 731 } 732 733 void 734 sccstart(tp) 735 register struct tty *tp; 736 { 737 register struct pdma *dp; 738 register scc_regmap_t *regs; 739 register struct scc_softc *sc; 740 register int cc, chan; 741 u_char temp; 742 int s, sendone; 743 744 dp = (struct pdma *)tp->t_addr; 745 regs = (scc_regmap_t *)dp->p_addr; 746 sc = &scc_softc[SCCUNIT(tp->t_dev)]; 747 s = spltty(); 748 if (tp->t_state & (TS_TIMEOUT|TS_BUSY|TS_TTSTOP)) 749 goto out; 750 if (tp->t_outq.c_cc <= tp->t_lowat) { 751 if (tp->t_state & TS_ASLEEP) { 752 tp->t_state &= ~TS_ASLEEP; 753 wakeup((caddr_t)&tp->t_outq); 754 } 755 selwakeup(&tp->t_wsel); 756 } 757 if (tp->t_outq.c_cc == 0) 758 goto out; 759 /* handle console specially */ 760 if (tp == &scc_tty[SCCKBD_PORT] && cn_tab.cn_screen) { 761 while (tp->t_outq.c_cc > 0) { 762 cc = getc(&tp->t_outq) & 0x7f; 763 cnputc(cc); 764 } 765 /* 766 * After we flush the output queue we may need to wake 767 * up the process that made the output. 768 */ 769 if (tp->t_outq.c_cc <= tp->t_lowat) { 770 if (tp->t_state & TS_ASLEEP) { 771 tp->t_state &= ~TS_ASLEEP; 772 wakeup((caddr_t)&tp->t_outq); 773 } 774 selwakeup(&tp->t_wsel); 775 } 776 goto out; 777 } 778 if (tp->t_flags & (RAW|LITOUT)) 779 cc = ndqb(&tp->t_outq, 0); 780 else { 781 cc = ndqb(&tp->t_outq, 0200); 782 if (cc == 0) { 783 cc = getc(&tp->t_outq); 784 timeout(ttrstrt, (void *)tp, (cc & 0x7f) + 6); 785 tp->t_state |= TS_TIMEOUT; 786 goto out; 787 } 788 } 789 tp->t_state |= TS_BUSY; 790 dp->p_end = dp->p_mem = tp->t_outq.c_cf; 791 dp->p_end += cc; 792 793 /* 794 * Enable transmission and send the first char, as required. 795 */ 796 chan = SCCLINE(tp->t_dev); 797 SCC_READ_REG(regs, chan, SCC_RR0, temp); 798 sendone = (temp & SCC_RR0_TX_EMPTY); 799 SCC_READ_REG(regs, chan, SCC_RR15, temp); 800 temp |= SCC_WR15_TX_UNDERRUN_IE; 801 SCC_WRITE_REG(regs, chan, SCC_WR15, temp); 802 temp = sc->scc_wreg[chan].wr1 | SCC_WR1_TX_IE; 803 SCC_WRITE_REG(regs, chan, SCC_WR1, temp); 804 sc->scc_wreg[chan].wr1 = temp; 805 if (sendone) { 806 #ifdef DIAGNOSTIC 807 if (cc == 0) 808 panic("sccstart: No chars"); 809 #endif 810 SCC_WRITE_DATA(regs, chan, *dp->p_mem++); 811 } 812 MachEmptyWriteBuffer(); 813 out: 814 splx(s); 815 } 816 817 /* 818 * Stop output on a line. 819 */ 820 /*ARGSUSED*/ 821 sccstop(tp, flag) 822 register struct tty *tp; 823 { 824 register struct pdma *dp; 825 register int s; 826 827 dp = (struct pdma *)tp->t_addr; 828 s = spltty(); 829 if (tp->t_state & TS_BUSY) { 830 dp->p_end = dp->p_mem; 831 if (!(tp->t_state & TS_TTSTOP)) 832 tp->t_state |= TS_FLUSH; 833 } 834 splx(s); 835 } 836 837 sccmctl(dev, bits, how) 838 dev_t dev; 839 int bits, how; 840 { 841 register struct scc_softc *sc; 842 register scc_regmap_t *regs; 843 register int line, mbits; 844 register u_char value; 845 int s; 846 847 sc = &scc_softc[SCCUNIT(dev)]; 848 line = SCCLINE(dev); 849 regs = (scc_regmap_t *)sc->scc_pdma[line].p_addr; 850 s = spltty(); 851 /* 852 * only channel B has modem control, however the DTR and RTS 853 * pins on the comm port are wired to the DTR and RTS A channel 854 * signals. 855 */ 856 mbits = DML_DTR | DML_DSR | DML_CAR; 857 if (line == SCC_CHANNEL_B) { 858 if (sc->scc_wreg[SCC_CHANNEL_A].wr5 & SCC_WR5_DTR) 859 mbits = DML_DTR | DML_DSR; 860 else 861 mbits = 0; 862 SCC_READ_REG_ZERO(regs, SCC_CHANNEL_B, value); 863 if (value & SCC_RR0_DCD) 864 mbits |= DML_CAR; 865 } 866 switch (how) { 867 case DMSET: 868 mbits = bits; 869 break; 870 871 case DMBIS: 872 mbits |= bits; 873 break; 874 875 case DMBIC: 876 mbits &= ~bits; 877 break; 878 879 case DMGET: 880 (void) splx(s); 881 return (mbits); 882 } 883 if (line == SCC_CHANNEL_B) { 884 if (mbits & DML_DTR) 885 sc->scc_wreg[SCC_CHANNEL_A].wr5 |= SCC_WR5_DTR; 886 else 887 sc->scc_wreg[SCC_CHANNEL_A].wr5 &= ~SCC_WR5_DTR; 888 SCC_WRITE_REG(regs, SCC_CHANNEL_A, SCC_WR5, 889 sc->scc_wreg[SCC_CHANNEL_A].wr5); 890 } 891 if ((mbits & DML_DTR) && (sc->scc_softCAR & (1 << line))) 892 scc_tty[minor(dev)].t_state |= TS_CARR_ON; 893 (void) splx(s); 894 return (mbits); 895 } 896 897 /* 898 * Check for carrier transition. 899 */ 900 static void 901 scc_modem_intr(dev) 902 dev_t dev; 903 { 904 register scc_regmap_t *regs; 905 register struct scc_softc *sc; 906 register struct tty *tp; 907 register int car, chan; 908 register u_char value; 909 int s; 910 911 sc = &scc_softc[SCCUNIT(dev)]; 912 tp = &scc_tty[minor(dev)]; 913 regs = (scc_regmap_t *)((struct pdma *)tp->t_addr)->p_addr; 914 chan = SCCLINE(dev); 915 if (chan == SCC_CHANNEL_A) 916 return; 917 s = spltty(); 918 if (sc->scc_softCAR & (1 << chan)) 919 car = 1; 920 else { 921 SCC_READ_REG_ZERO(regs, chan, value); 922 car = value & SCC_RR0_DCD; 923 } 924 if (car) { 925 /* carrier present */ 926 if (!(tp->t_state & TS_CARR_ON)) 927 (void)(*linesw[tp->t_line].l_modem)(tp, 1); 928 } else if (tp->t_state & TS_CARR_ON) 929 (void)(*linesw[tp->t_line].l_modem)(tp, 0); 930 splx(s); 931 } 932 933 /* 934 * Get a char off the appropriate line via. a busy wait loop. 935 */ 936 int 937 sccGetc(dev) 938 dev_t dev; 939 { 940 register scc_regmap_t *regs; 941 register int c, line; 942 register u_char value; 943 int s; 944 945 line = SCCLINE(dev); 946 regs = (scc_regmap_t *)scc_softc[SCCUNIT(dev)].scc_pdma[line].p_addr; 947 if (!regs) 948 return (0); 949 s = spltty(); 950 for (;;) { 951 SCC_READ_REG(regs, line, SCC_RR0, value); 952 if (value & SCC_RR0_RX_AVAIL) { 953 SCC_READ_REG(regs, line, SCC_RR1, value); 954 if (value & (SCC_RR1_PARITY_ERR | SCC_RR1_RX_OVERRUN | 955 SCC_RR1_FRAME_ERR)) { 956 SCC_WRITE_REG(regs, line, SCC_WR0, SCC_RESET_ERROR); 957 SCC_WRITE_REG(regs, SCC_CHANNEL_A, SCC_WR0, 958 SCC_RESET_HIGHEST_IUS); 959 } else { 960 SCC_READ_DATA(regs, line, c); 961 SCC_WRITE_REG(regs, SCC_CHANNEL_A, SCC_WR0, 962 SCC_RESET_HIGHEST_IUS); 963 splx(s); 964 return (c & 0xff); 965 } 966 } else 967 DELAY(10); 968 } 969 } 970 971 /* 972 * Send a char on a port, via a busy wait loop. 973 */ 974 void 975 sccPutc(dev, c) 976 dev_t dev; 977 int c; 978 { 979 register scc_regmap_t *regs; 980 register int line; 981 register u_char value; 982 int s; 983 984 s = spltty(); 985 line = SCCLINE(dev); 986 regs = (scc_regmap_t *)scc_softc[SCCUNIT(dev)].scc_pdma[line].p_addr; 987 988 /* 989 * Wait for transmitter to be not busy. 990 */ 991 do { 992 SCC_READ_REG(regs, line, SCC_RR0, value); 993 if (value & SCC_RR0_TX_EMPTY) 994 break; 995 DELAY(100); 996 } while (1); 997 998 /* 999 * Send the char. 1000 */ 1001 SCC_WRITE_DATA(regs, line, c); 1002 MachEmptyWriteBuffer(); 1003 splx(s); 1004 } 1005 #endif /* NSCC */ 1006