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