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 * @(#)scc.c 8.3 (Berkeley) 06/02/95 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_dev = (dev_t)((cp->pmax_unit << 1) | cntr); 177 pdp++, tp++; 178 } 179 sc->scc_softCAR = cp->pmax_flags | 0x2; 180 181 /* reset chip */ 182 sccreset(sc); 183 184 /* 185 * Special handling for consoles. 186 */ 187 if (cn_tab.cn_screen) { 188 if (cn_tab.cn_kbdgetc == sccGetc) { 189 if (cp->pmax_unit == 1) { 190 s = spltty(); 191 ctty.t_dev = makedev(SCCDEV, SCCKBD_PORT); 192 cterm.c_cflag = CS8; 193 cterm.c_ospeed = cterm.c_ispeed = 4800; 194 (void) sccparam(&ctty, &cterm); 195 DELAY(10000); 196 #ifdef notyet 197 /* 198 * For some reason doing this hangs the 3min 199 * during booting. Fortunately the keyboard 200 * works ok without it. 201 */ 202 KBDReset(ctty.t_dev, sccPutc); 203 #endif 204 DELAY(10000); 205 splx(s); 206 } else if (cp->pmax_unit == 0) { 207 s = spltty(); 208 ctty.t_dev = makedev(SCCDEV, SCCMOUSE_PORT); 209 cterm.c_cflag = CS8 | PARENB | PARODD; 210 cterm.c_ospeed = cterm.c_ispeed = 4800; 211 (void) sccparam(&ctty, &cterm); 212 DELAY(10000); 213 MouseInit(ctty.t_dev, sccPutc, sccGetc); 214 DELAY(10000); 215 splx(s); 216 } 217 } 218 } else if (SCCUNIT(cn_tab.cn_dev) == cp->pmax_unit) { 219 s = spltty(); 220 ctty.t_dev = cn_tab.cn_dev; 221 cterm.c_cflag = CS8; 222 cterm.c_ospeed = cterm.c_ispeed = 9600; 223 (void) sccparam(&ctty, &cterm); 224 DELAY(1000); 225 cn_tab.cn_disabled = 0; 226 splx(s); 227 } 228 printf("scc%d at nexus0 csr 0x%x priority %d\n", 229 cp->pmax_unit, cp->pmax_addr, cp->pmax_pri); 230 return (1); 231 } 232 233 /* 234 * Reset the chip. 235 */ 236 static void 237 sccreset(sc) 238 register struct scc_softc *sc; 239 { 240 register scc_regmap_t *regs; 241 register u_char val; 242 243 regs = (scc_regmap_t *)sc->scc_pdma[0].p_addr; 244 /* 245 * Chip once-only initialization 246 * 247 * NOTE: The wiring we assume is the one on the 3min: 248 * 249 * out A-TxD --> TxD keybd or mouse 250 * in A-RxD --> RxD keybd or mouse 251 * out A-DTR~ --> DTR comm 252 * out A-RTS~ --> RTS comm 253 * in A-CTS~ --> SI comm 254 * in A-DCD~ --> RI comm 255 * in A-SYNCH~--> DSR comm 256 * out B-TxD --> TxD comm 257 * in B-RxD --> RxD comm 258 * in B-RxC --> TRxCB comm 259 * in B-TxC --> RTxCB comm 260 * out B-RTS~ --> SS comm 261 * in B-CTS~ --> CTS comm 262 * in B-DCD~ --> CD comm 263 */ 264 SCC_INIT_REG(regs, SCC_CHANNEL_A); 265 SCC_INIT_REG(regs, SCC_CHANNEL_B); 266 SCC_WRITE_REG(regs, SCC_CHANNEL_A, SCC_WR9, SCC_WR9_HW_RESET); 267 DELAY(50000); /*enough ? */ 268 SCC_WRITE_REG(regs, SCC_CHANNEL_A, SCC_WR9, 0); 269 270 /* program the interrupt vector */ 271 SCC_WRITE_REG(regs, SCC_CHANNEL_A, SCC_WR2, 0xf0); 272 SCC_WRITE_REG(regs, SCC_CHANNEL_B, SCC_WR2, 0xf0); 273 SCC_WRITE_REG(regs, SCC_CHANNEL_A, SCC_WR9, SCC_WR9_VIS); 274 275 /* timing base defaults */ 276 sc->scc_wreg[SCC_CHANNEL_A].wr4 = SCC_WR4_CLK_x16; 277 sc->scc_wreg[SCC_CHANNEL_B].wr4 = SCC_WR4_CLK_x16; 278 279 /* enable DTR, RTS and SS */ 280 sc->scc_wreg[SCC_CHANNEL_B].wr5 = SCC_WR5_RTS; 281 sc->scc_wreg[SCC_CHANNEL_A].wr5 = SCC_WR5_RTS | SCC_WR5_DTR; 282 283 /* baud rates */ 284 val = SCC_WR14_BAUDR_ENABLE|SCC_WR14_BAUDR_SRC; 285 sc->scc_wreg[SCC_CHANNEL_B].wr14 = val; 286 sc->scc_wreg[SCC_CHANNEL_A].wr14 = val; 287 288 /* interrupt conditions */ 289 val = SCC_WR1_RXI_ALL_CHAR | SCC_WR1_PARITY_IE | 290 SCC_WR1_EXT_IE; 291 sc->scc_wreg[SCC_CHANNEL_A].wr1 = val; 292 sc->scc_wreg[SCC_CHANNEL_B].wr1 = val; 293 } 294 295 sccopen(dev, flag, mode, p) 296 dev_t dev; 297 int flag, mode; 298 struct proc *p; 299 { 300 register struct scc_softc *sc; 301 register struct tty *tp; 302 register int unit, line; 303 int s, error = 0; 304 305 unit = SCCUNIT(dev); 306 if (unit >= NSCC) 307 return (ENXIO); 308 line = SCCLINE(dev); 309 sc = &scc_softc[unit]; 310 if (sc->scc_pdma[line].p_addr == (void *)0) 311 return (ENXIO); 312 tp = &scc_tty[minor(dev)]; 313 tp->t_oproc = sccstart; 314 tp->t_param = sccparam; 315 tp->t_dev = dev; 316 if ((tp->t_state & TS_ISOPEN) == 0) { 317 tp->t_state |= TS_WOPEN; 318 ttychars(tp); 319 #ifndef PORTSELECTOR 320 if (tp->t_ispeed == 0) { 321 #endif 322 tp->t_iflag = TTYDEF_IFLAG; 323 tp->t_oflag = TTYDEF_OFLAG; 324 tp->t_cflag = TTYDEF_CFLAG; 325 tp->t_lflag = LFLAG; 326 tp->t_ispeed = tp->t_ospeed = ISPEED; 327 #ifdef PORTSELECTOR 328 tp->t_cflag |= HUPCL; 329 #else 330 } 331 #endif 332 (void) sccparam(tp, &tp->t_termios); 333 ttsetwater(tp); 334 } else if ((tp->t_state & TS_XCLUDE) && curproc->p_ucred->cr_uid != 0) 335 return (EBUSY); 336 (void) sccmctl(dev, DML_DTR, DMSET); 337 s = spltty(); 338 while (!(flag & O_NONBLOCK) && !(tp->t_cflag & CLOCAL) && 339 !(tp->t_state & TS_CARR_ON)) { 340 tp->t_state |= TS_WOPEN; 341 if (error = ttysleep(tp, (caddr_t)&tp->t_rawq, TTIPRI | PCATCH, 342 ttopen, 0)) 343 break; 344 } 345 splx(s); 346 if (error) 347 return (error); 348 return ((*linesw[tp->t_line].l_open)(dev, tp)); 349 } 350 351 /*ARGSUSED*/ 352 sccclose(dev, flag, mode, p) 353 dev_t dev; 354 int flag, mode; 355 struct proc *p; 356 { 357 register struct scc_softc *sc = &scc_softc[SCCUNIT(dev)]; 358 register struct tty *tp; 359 register int bit, line; 360 361 tp = &scc_tty[minor(dev)]; 362 line = SCCLINE(dev); 363 if (sc->scc_wreg[line].wr5 & SCC_WR5_SEND_BREAK) { 364 sc->scc_wreg[line].wr5 &= ~SCC_WR5_SEND_BREAK; 365 ttyoutput(0, tp); 366 } 367 (*linesw[tp->t_line].l_close)(tp, flag); 368 if ((tp->t_cflag & HUPCL) || (tp->t_state & TS_WOPEN) || 369 !(tp->t_state & TS_ISOPEN)) 370 (void) sccmctl(dev, 0, DMSET); 371 return (ttyclose(tp)); 372 } 373 374 sccread(dev, uio, flag) 375 dev_t dev; 376 struct uio *uio; 377 { 378 register struct tty *tp; 379 380 tp = &scc_tty[minor(dev)]; 381 return ((*linesw[tp->t_line].l_read)(tp, uio, flag)); 382 } 383 384 sccwrite(dev, uio, flag) 385 dev_t dev; 386 struct uio *uio; 387 { 388 register struct tty *tp; 389 390 tp = &scc_tty[minor(dev)]; 391 return ((*linesw[tp->t_line].l_write)(tp, uio, flag)); 392 } 393 394 /*ARGSUSED*/ 395 sccioctl(dev, cmd, data, flag, p) 396 dev_t dev; 397 u_long cmd; 398 caddr_t data; 399 int flag; 400 struct proc *p; 401 { 402 register struct scc_softc *sc; 403 register struct tty *tp; 404 int error, line; 405 406 tp = &scc_tty[minor(dev)]; 407 error = (*linesw[tp->t_line].l_ioctl)(tp, cmd, data, flag, p); 408 if (error >= 0) 409 return (error); 410 error = ttioctl(tp, cmd, data, flag); 411 if (error >= 0) 412 return (error); 413 414 line = SCCLINE(dev); 415 sc = &scc_softc[SCCUNIT(dev)]; 416 switch (cmd) { 417 418 case TIOCSBRK: 419 sc->scc_wreg[line].wr5 |= SCC_WR5_SEND_BREAK; 420 ttyoutput(0, tp); 421 break; 422 423 case TIOCCBRK: 424 sc->scc_wreg[line].wr5 &= ~SCC_WR5_SEND_BREAK; 425 ttyoutput(0, tp); 426 break; 427 428 case TIOCSDTR: 429 (void) sccmctl(dev, DML_DTR|DML_RTS, DMBIS); 430 break; 431 432 case TIOCCDTR: 433 (void) sccmctl(dev, DML_DTR|DML_RTS, DMBIC); 434 break; 435 436 case TIOCMSET: 437 (void) sccmctl(dev, *(int *)data, DMSET); 438 break; 439 440 case TIOCMBIS: 441 (void) sccmctl(dev, *(int *)data, DMBIS); 442 break; 443 444 case TIOCMBIC: 445 (void) sccmctl(dev, *(int *)data, DMBIC); 446 break; 447 448 case TIOCMGET: 449 *(int *)data = sccmctl(dev, 0, DMGET); 450 break; 451 452 default: 453 return (ENOTTY); 454 } 455 return (0); 456 } 457 458 sccparam(tp, t) 459 register struct tty *tp; 460 register struct termios *t; 461 { 462 register struct scc_softc *sc; 463 register scc_regmap_t *regs; 464 register int line; 465 register u_char value, wvalue; 466 register int cflag = t->c_cflag; 467 int ospeed; 468 469 if (t->c_ispeed && t->c_ispeed != t->c_ospeed) 470 return (EINVAL); 471 sc = &scc_softc[SCCUNIT(tp->t_dev)]; 472 line = SCCLINE(tp->t_dev); 473 regs = (scc_regmap_t *)sc->scc_pdma[line].p_addr; 474 ospeed = ttspeedtab(t->c_ospeed, sccspeedtab); 475 if (ospeed < 0) 476 return (EINVAL); 477 /* and copy to tty */ 478 tp->t_ispeed = t->c_ispeed; 479 tp->t_ospeed = t->c_ospeed; 480 tp->t_cflag = cflag; 481 482 /* 483 * Handle console specially. 484 */ 485 if (cn_tab.cn_screen) { 486 if (minor(tp->t_dev) == SCCKBD_PORT) { 487 cflag = CS8; 488 ospeed = ttspeedtab(4800, sccspeedtab); 489 } else if (minor(tp->t_dev) == SCCMOUSE_PORT) { 490 cflag = CS8 | PARENB | PARODD; 491 ospeed = ttspeedtab(4800, sccspeedtab); 492 } 493 } else if (tp->t_dev == cn_tab.cn_dev) { 494 cflag = CS8; 495 ospeed = ttspeedtab(9600, sccspeedtab); 496 } 497 if (ospeed == 0) { 498 (void) sccmctl(tp->t_dev, 0, DMSET); /* hang up line */ 499 return (0); 500 } 501 502 /* reset line */ 503 if (line == SCC_CHANNEL_A) 504 value = SCC_WR9_RESET_CHA_A; 505 else 506 value = SCC_WR9_RESET_CHA_B; 507 SCC_WRITE_REG(regs, line, SCC_WR9, value); 508 DELAY(25); 509 510 /* stop bits, normally 1 */ 511 value = sc->scc_wreg[line].wr4 & 0xf0; 512 if (cflag & CSTOPB) 513 value |= SCC_WR4_2_STOP; 514 else 515 value |= SCC_WR4_1_STOP; 516 if ((cflag & PARODD) == 0) 517 value |= SCC_WR4_EVEN_PARITY; 518 if (cflag & PARENB) 519 value |= SCC_WR4_PARITY_ENABLE; 520 521 /* set it now, remember it must be first after reset */ 522 sc->scc_wreg[line].wr4 = value; 523 SCC_WRITE_REG(regs, line, SCC_WR4, value); 524 525 /* vector again */ 526 SCC_WRITE_REG(regs, line, SCC_WR2, 0xf0); 527 528 /* clear break, keep rts dtr */ 529 wvalue = sc->scc_wreg[line].wr5 & (SCC_WR5_DTR|SCC_WR5_RTS); 530 switch (cflag & CSIZE) { 531 case CS5: 532 value = SCC_WR3_RX_5_BITS; 533 wvalue |= SCC_WR5_TX_5_BITS; 534 break; 535 case CS6: 536 value = SCC_WR3_RX_6_BITS; 537 wvalue |= SCC_WR5_TX_6_BITS; 538 break; 539 case CS7: 540 value = SCC_WR3_RX_7_BITS; 541 wvalue |= SCC_WR5_TX_7_BITS; 542 break; 543 case CS8: 544 default: 545 value = SCC_WR3_RX_8_BITS; 546 wvalue |= SCC_WR5_TX_8_BITS; 547 }; 548 sc->scc_wreg[line].wr3 = value; 549 SCC_WRITE_REG(regs, line, SCC_WR3, value); 550 sc->scc_wreg[line].wr5 = wvalue; 551 SCC_WRITE_REG(regs, line, SCC_WR5, wvalue); 552 SCC_WRITE_REG(regs, line, SCC_WR6, 0); 553 SCC_WRITE_REG(regs, line, SCC_WR7, 0); 554 SCC_WRITE_REG(regs, line, SCC_WR9, SCC_WR9_VIS); 555 SCC_WRITE_REG(regs, line, SCC_WR10, 0); 556 value = SCC_WR11_RCLK_BAUDR | SCC_WR11_XTLK_BAUDR | 557 SCC_WR11_TRc_OUT | SCC_WR11_TRcOUT_BAUDR; 558 SCC_WRITE_REG(regs, line, SCC_WR11, value); 559 SCC_SET_TIMING_BASE(regs, line, ospeed); 560 value = sc->scc_wreg[line].wr14; 561 SCC_WRITE_REG(regs, line, SCC_WR14, value); 562 value = SCC_WR15_BREAK_IE | SCC_WR15_CTS_IE | SCC_WR15_DCD_IE; 563 SCC_WRITE_REG(regs, line, SCC_WR15, value); 564 565 /* and now the enables */ 566 value = sc->scc_wreg[line].wr3 | SCC_WR3_RX_ENABLE; 567 SCC_WRITE_REG(regs, line, SCC_WR3, value); 568 value = sc->scc_wreg[line].wr5 | SCC_WR5_TX_ENABLE; 569 sc->scc_wreg[line].wr5 = value; 570 SCC_WRITE_REG(regs, line, SCC_WR5, value); 571 572 /* master inter enable */ 573 value = SCC_WR9_MASTER_IE | SCC_WR9_VIS; 574 SCC_WRITE_REG(regs, line, SCC_WR9, value); 575 SCC_WRITE_REG(regs, line, SCC_WR1, sc->scc_wreg[line].wr1); 576 MachEmptyWriteBuffer(); 577 return (0); 578 } 579 580 /* 581 * Check for interrupts from all devices. 582 */ 583 void 584 sccintr(unit) 585 register int unit; 586 { 587 register scc_regmap_t *regs; 588 register struct tty *tp; 589 register struct pdma *dp; 590 register struct scc_softc *sc; 591 register int cc, chan, rr1, rr2, rr3; 592 int overrun = 0; 593 594 sc = &scc_softc[unit]; 595 regs = (scc_regmap_t *)sc->scc_pdma[0].p_addr; 596 unit <<= 1; 597 for (;;) { 598 SCC_READ_REG(regs, SCC_CHANNEL_B, SCC_RR2, rr2); 599 rr2 = SCC_RR2_STATUS(rr2); 600 /* are we done yet ? */ 601 if (rr2 == 6) { /* strange, distinguished value */ 602 SCC_READ_REG(regs, SCC_CHANNEL_A, SCC_RR3, rr3); 603 if (rr3 == 0) 604 return; 605 } 606 607 SCC_WRITE_REG(regs, SCC_CHANNEL_A, SCC_RR0, SCC_RESET_HIGHEST_IUS); 608 if ((rr2 == SCC_RR2_A_XMIT_DONE) || (rr2 == SCC_RR2_B_XMIT_DONE)) { 609 chan = (rr2 == SCC_RR2_A_XMIT_DONE) ? 610 SCC_CHANNEL_A : SCC_CHANNEL_B; 611 tp = &scc_tty[unit | chan]; 612 dp = &sc->scc_pdma[chan]; 613 if (dp->p_mem < dp->p_end) { 614 SCC_WRITE_DATA(regs, chan, *dp->p_mem++); 615 MachEmptyWriteBuffer(); 616 } else { 617 tp->t_state &= ~TS_BUSY; 618 if (tp->t_state & TS_FLUSH) 619 tp->t_state &= ~TS_FLUSH; 620 else { 621 ndflush(&tp->t_outq, dp->p_mem-tp->t_outq.c_cf); 622 dp->p_end = dp->p_mem = tp->t_outq.c_cf; 623 } 624 if (tp->t_line) 625 (*linesw[tp->t_line].l_start)(tp); 626 else 627 sccstart(tp); 628 if (tp->t_outq.c_cc == 0 || !(tp->t_state & TS_BUSY)) { 629 SCC_READ_REG(regs, chan, SCC_RR15, cc); 630 cc &= ~SCC_WR15_TX_UNDERRUN_IE; 631 SCC_WRITE_REG(regs, chan, SCC_WR15, cc); 632 cc = sc->scc_wreg[chan].wr1 & ~SCC_WR1_TX_IE; 633 SCC_WRITE_REG(regs, chan, SCC_WR1, cc); 634 sc->scc_wreg[chan].wr1 = cc; 635 MachEmptyWriteBuffer(); 636 } 637 } 638 } else if (rr2 == SCC_RR2_A_RECV_DONE || 639 rr2 == SCC_RR2_B_RECV_DONE || rr2 == SCC_RR2_A_RECV_SPECIAL || 640 rr2 == SCC_RR2_B_RECV_SPECIAL) { 641 if (rr2 == SCC_RR2_A_RECV_DONE || rr2 == SCC_RR2_A_RECV_SPECIAL) 642 chan = SCC_CHANNEL_A; 643 else 644 chan = SCC_CHANNEL_B; 645 tp = &scc_tty[unit | chan]; 646 SCC_READ_DATA(regs, chan, cc); 647 if (rr2 == SCC_RR2_A_RECV_SPECIAL || 648 rr2 == SCC_RR2_B_RECV_SPECIAL) { 649 SCC_READ_REG(regs, chan, SCC_RR1, rr1); 650 SCC_WRITE_REG(regs, chan, SCC_RR0, SCC_RESET_ERROR); 651 if ((rr1 & SCC_RR1_RX_OVERRUN) && overrun == 0) { 652 log(LOG_WARNING, "scc%d,%d: silo overflow\n", 653 unit >> 1, chan); 654 overrun = 1; 655 } 656 } 657 658 /* 659 * Keyboard needs special treatment. 660 */ 661 if (tp == &scc_tty[SCCKBD_PORT] && cn_tab.cn_screen) { 662 #ifdef KADB 663 if (cc == LK_DO) { 664 spl0(); 665 kdbpanic(); 666 return; 667 } 668 #endif 669 #ifdef DEBUG 670 debugChar = cc; 671 #endif 672 if (sccDivertXInput) { 673 (*sccDivertXInput)(cc); 674 continue; 675 } 676 if ((cc = kbdMapChar(cc)) < 0) 677 continue; 678 /* 679 * Now for mousey 680 */ 681 } else if (tp == &scc_tty[SCCMOUSE_PORT] && sccMouseButtons) { 682 register MouseReport *mrp; 683 static MouseReport currentRep; 684 685 mrp = ¤tRep; 686 mrp->byteCount++; 687 if (cc & MOUSE_START_FRAME) { 688 /* 689 * The first mouse report byte (button state). 690 */ 691 mrp->state = cc; 692 if (mrp->byteCount > 1) 693 mrp->byteCount = 1; 694 } else if (mrp->byteCount == 2) { 695 /* 696 * The second mouse report byte (delta x). 697 */ 698 mrp->dx = cc; 699 } else if (mrp->byteCount == 3) { 700 /* 701 * The final mouse report byte (delta y). 702 */ 703 mrp->dy = cc; 704 mrp->byteCount = 0; 705 if (mrp->dx != 0 || mrp->dy != 0) { 706 /* 707 * If the mouse moved, 708 * post a motion event. 709 */ 710 (*sccMouseEvent)(mrp); 711 } 712 (*sccMouseButtons)(mrp); 713 } 714 continue; 715 } 716 if (!(tp->t_state & TS_ISOPEN)) { 717 wakeup((caddr_t)&tp->t_rawq); 718 #ifdef PORTSELECTOR 719 if (!(tp->t_state & TS_WOPEN)) 720 #endif 721 continue; 722 } 723 if (rr2 == SCC_RR2_A_RECV_SPECIAL || 724 rr2 == SCC_RR2_B_RECV_SPECIAL) { 725 if (rr1 & SCC_RR1_PARITY_ERR) 726 cc |= TTY_PE; 727 if (rr1 & SCC_RR1_FRAME_ERR) 728 cc |= TTY_FE; 729 } 730 (*linesw[tp->t_line].l_rint)(cc, tp); 731 } else if ((rr2 == SCC_RR2_A_EXT_STATUS) || (rr2 == SCC_RR2_B_EXT_STATUS)) { 732 chan = (rr2 == SCC_RR2_A_EXT_STATUS) ? 733 SCC_CHANNEL_A : SCC_CHANNEL_B; 734 SCC_WRITE_REG(regs, chan, SCC_RR0, SCC_RESET_EXT_IP); 735 scc_modem_intr(unit | chan); 736 } 737 } 738 } 739 740 void 741 sccstart(tp) 742 register struct tty *tp; 743 { 744 register struct pdma *dp; 745 register scc_regmap_t *regs; 746 register struct scc_softc *sc; 747 register int cc, chan; 748 u_char temp; 749 int s, sendone; 750 751 sc = &scc_softc[SCCUNIT(tp->t_dev)]; 752 dp = &sc->scc_pdma[SCCLINE(tp->t_dev)]; 753 regs = (scc_regmap_t *)dp->p_addr; 754 s = spltty(); 755 if (tp->t_state & (TS_TIMEOUT|TS_BUSY|TS_TTSTOP)) 756 goto out; 757 if (tp->t_outq.c_cc <= tp->t_lowat) { 758 if (tp->t_state & TS_ASLEEP) { 759 tp->t_state &= ~TS_ASLEEP; 760 wakeup((caddr_t)&tp->t_outq); 761 } 762 selwakeup(&tp->t_wsel); 763 } 764 if (tp->t_outq.c_cc == 0) 765 goto out; 766 /* handle console specially */ 767 if (tp == &scc_tty[SCCKBD_PORT] && cn_tab.cn_screen) { 768 while (tp->t_outq.c_cc > 0) { 769 cc = getc(&tp->t_outq) & 0x7f; 770 cnputc(cc); 771 } 772 /* 773 * After we flush the output queue we may need to wake 774 * up the process that made the output. 775 */ 776 if (tp->t_outq.c_cc <= tp->t_lowat) { 777 if (tp->t_state & TS_ASLEEP) { 778 tp->t_state &= ~TS_ASLEEP; 779 wakeup((caddr_t)&tp->t_outq); 780 } 781 selwakeup(&tp->t_wsel); 782 } 783 goto out; 784 } 785 if (tp->t_flags & (RAW|LITOUT)) 786 cc = ndqb(&tp->t_outq, 0); 787 else { 788 cc = ndqb(&tp->t_outq, 0200); 789 if (cc == 0) { 790 cc = getc(&tp->t_outq); 791 timeout(ttrstrt, (void *)tp, (cc & 0x7f) + 6); 792 tp->t_state |= TS_TIMEOUT; 793 goto out; 794 } 795 } 796 tp->t_state |= TS_BUSY; 797 dp->p_end = dp->p_mem = tp->t_outq.c_cf; 798 dp->p_end += cc; 799 800 /* 801 * Enable transmission and send the first char, as required. 802 */ 803 chan = SCCLINE(tp->t_dev); 804 SCC_READ_REG(regs, chan, SCC_RR0, temp); 805 sendone = (temp & SCC_RR0_TX_EMPTY); 806 SCC_READ_REG(regs, chan, SCC_RR15, temp); 807 temp |= SCC_WR15_TX_UNDERRUN_IE; 808 SCC_WRITE_REG(regs, chan, SCC_WR15, temp); 809 temp = sc->scc_wreg[chan].wr1 | SCC_WR1_TX_IE; 810 SCC_WRITE_REG(regs, chan, SCC_WR1, temp); 811 sc->scc_wreg[chan].wr1 = temp; 812 if (sendone) { 813 #ifdef DIAGNOSTIC 814 if (cc == 0) 815 panic("sccstart: No chars"); 816 #endif 817 SCC_WRITE_DATA(regs, chan, *dp->p_mem++); 818 } 819 MachEmptyWriteBuffer(); 820 out: 821 splx(s); 822 } 823 824 /* 825 * Stop output on a line. 826 */ 827 /*ARGSUSED*/ 828 sccstop(tp, flag) 829 register struct tty *tp; 830 { 831 register struct pdma *dp; 832 register struct scc_softc *sc; 833 register int s; 834 835 sc = &scc_softc[SCCUNIT(tp->t_dev)]; 836 dp = &sc->scc_pdma[SCCLINE(tp->t_dev)]; 837 s = spltty(); 838 if (tp->t_state & TS_BUSY) { 839 dp->p_end = dp->p_mem; 840 if (!(tp->t_state & TS_TTSTOP)) 841 tp->t_state |= TS_FLUSH; 842 } 843 splx(s); 844 } 845 846 sccmctl(dev, bits, how) 847 dev_t dev; 848 int bits, how; 849 { 850 register struct scc_softc *sc; 851 register scc_regmap_t *regs; 852 register int line, mbits; 853 register u_char value; 854 int s; 855 856 sc = &scc_softc[SCCUNIT(dev)]; 857 line = SCCLINE(dev); 858 regs = (scc_regmap_t *)sc->scc_pdma[line].p_addr; 859 s = spltty(); 860 /* 861 * only channel B has modem control, however the DTR and RTS 862 * pins on the comm port are wired to the DTR and RTS A channel 863 * signals. 864 */ 865 mbits = DML_DTR | DML_DSR | DML_CAR; 866 if (line == SCC_CHANNEL_B) { 867 if (sc->scc_wreg[SCC_CHANNEL_A].wr5 & SCC_WR5_DTR) 868 mbits = DML_DTR | DML_DSR; 869 else 870 mbits = 0; 871 SCC_READ_REG_ZERO(regs, SCC_CHANNEL_B, value); 872 if (value & SCC_RR0_DCD) 873 mbits |= DML_CAR; 874 } 875 switch (how) { 876 case DMSET: 877 mbits = bits; 878 break; 879 880 case DMBIS: 881 mbits |= bits; 882 break; 883 884 case DMBIC: 885 mbits &= ~bits; 886 break; 887 888 case DMGET: 889 (void) splx(s); 890 return (mbits); 891 } 892 if (line == SCC_CHANNEL_B) { 893 if (mbits & DML_DTR) 894 sc->scc_wreg[SCC_CHANNEL_A].wr5 |= SCC_WR5_DTR; 895 else 896 sc->scc_wreg[SCC_CHANNEL_A].wr5 &= ~SCC_WR5_DTR; 897 SCC_WRITE_REG(regs, SCC_CHANNEL_A, SCC_WR5, 898 sc->scc_wreg[SCC_CHANNEL_A].wr5); 899 } 900 if ((mbits & DML_DTR) && (sc->scc_softCAR & (1 << line))) 901 scc_tty[minor(dev)].t_state |= TS_CARR_ON; 902 (void) splx(s); 903 return (mbits); 904 } 905 906 /* 907 * Check for carrier transition. 908 */ 909 static void 910 scc_modem_intr(dev) 911 dev_t dev; 912 { 913 register scc_regmap_t *regs; 914 register struct scc_softc *sc; 915 register struct tty *tp; 916 register int car, chan; 917 register u_char value; 918 int s; 919 920 sc = &scc_softc[SCCUNIT(dev)]; 921 tp = &scc_tty[minor(dev)]; 922 chan = SCCLINE(dev); 923 regs = (scc_regmap_t *)sc->scc_pdma[chan].p_addr; 924 if (chan == SCC_CHANNEL_A) 925 return; 926 s = spltty(); 927 if (sc->scc_softCAR & (1 << chan)) 928 car = 1; 929 else { 930 SCC_READ_REG_ZERO(regs, chan, value); 931 car = value & SCC_RR0_DCD; 932 } 933 if (car) { 934 /* carrier present */ 935 if (!(tp->t_state & TS_CARR_ON)) 936 (void)(*linesw[tp->t_line].l_modem)(tp, 1); 937 } else if (tp->t_state & TS_CARR_ON) 938 (void)(*linesw[tp->t_line].l_modem)(tp, 0); 939 splx(s); 940 } 941 942 /* 943 * Get a char off the appropriate line via. a busy wait loop. 944 */ 945 int 946 sccGetc(dev) 947 dev_t dev; 948 { 949 register scc_regmap_t *regs; 950 register int c, line; 951 register u_char value; 952 int s; 953 954 line = SCCLINE(dev); 955 regs = (scc_regmap_t *)scc_softc[SCCUNIT(dev)].scc_pdma[line].p_addr; 956 if (!regs) 957 return (0); 958 s = spltty(); 959 for (;;) { 960 SCC_READ_REG(regs, line, SCC_RR0, value); 961 if (value & SCC_RR0_RX_AVAIL) { 962 SCC_READ_REG(regs, line, SCC_RR1, value); 963 SCC_READ_DATA(regs, line, c); 964 if (value & (SCC_RR1_PARITY_ERR | SCC_RR1_RX_OVERRUN | 965 SCC_RR1_FRAME_ERR)) { 966 SCC_WRITE_REG(regs, line, SCC_WR0, SCC_RESET_ERROR); 967 SCC_WRITE_REG(regs, SCC_CHANNEL_A, SCC_WR0, 968 SCC_RESET_HIGHEST_IUS); 969 } else { 970 SCC_WRITE_REG(regs, SCC_CHANNEL_A, SCC_WR0, 971 SCC_RESET_HIGHEST_IUS); 972 splx(s); 973 return (c & 0xff); 974 } 975 } else 976 DELAY(10); 977 } 978 } 979 980 /* 981 * Send a char on a port, via a busy wait loop. 982 */ 983 void 984 sccPutc(dev, c) 985 dev_t dev; 986 int c; 987 { 988 register scc_regmap_t *regs; 989 register int line; 990 register u_char value; 991 int s; 992 993 s = spltty(); 994 line = SCCLINE(dev); 995 regs = (scc_regmap_t *)scc_softc[SCCUNIT(dev)].scc_pdma[line].p_addr; 996 997 /* 998 * Wait for transmitter to be not busy. 999 */ 1000 do { 1001 SCC_READ_REG(regs, line, SCC_RR0, value); 1002 if (value & SCC_RR0_TX_EMPTY) 1003 break; 1004 DELAY(100); 1005 } while (1); 1006 1007 /* 1008 * Send the char. 1009 */ 1010 SCC_WRITE_DATA(regs, line, c); 1011 MachEmptyWriteBuffer(); 1012 splx(s); 1013 } 1014 #endif /* NSCC */ 1015