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