1 /* $NetBSD: ser.c,v 1.1 1997/05/25 12:41:57 leo Exp $ */ 2 3 /*- 4 * Copyright (c) 1997 The NetBSD Foundation, Inc. 5 * All rights reserved. 6 * 7 * This code is derived from software contributed to The NetBSD Foundation 8 * by Leo Weppelman. 9 * 10 * The driver structure is based on the i386 com-driver from Charles M. Hannum. 11 * 12 * Redistribution and use in source and binary forms, with or without 13 * modification, are permitted provided that the following conditions 14 * are met: 15 * 1. Redistributions of source code must retain the above copyright 16 * notice, this list of conditions and the following disclaimer. 17 * 2. Redistributions in binary form must reproduce the above copyright 18 * notice, this list of conditions and the following disclaimer in the 19 * documentation and/or other materials provided with the distribution. 20 * 3. All advertising materials mentioning features or use of this software 21 * must display the following acknowledgement: 22 * This product includes software developed by the NetBSD 23 * Foundation, Inc. and its contributors. 24 * 4. Neither the name of The NetBSD Foundation nor the names of its 25 * contributors may be used to endorse or promote products derived 26 * from this software without specific prior written permission. 27 * 28 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 29 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 30 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 31 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 32 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 33 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 34 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 35 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 36 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 37 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 38 * POSSIBILITY OF SUCH DAMAGE. 39 */ 40 #include <sys/param.h> 41 #include <sys/systm.h> 42 #include <sys/ioctl.h> 43 #include <sys/select.h> 44 #include <sys/tty.h> 45 #include <sys/proc.h> 46 #include <sys/user.h> 47 #include <sys/conf.h> 48 #include <sys/file.h> 49 #include <sys/uio.h> 50 #include <sys/kernel.h> 51 #include <sys/syslog.h> 52 #include <sys/types.h> 53 #include <sys/device.h> 54 55 #include <m68k/asm_single.h> 56 57 #include <machine/iomap.h> 58 #include <machine/mfp.h> 59 #include <atari/atari/intr.h> 60 #include <atari/dev/ym2149reg.h> 61 #include <atari/dev/serreg.h> 62 63 /* #define SER_DEBUG */ 64 65 #define SERUNIT(x) (minor(x)) 66 67 /* XXX */ 68 #define CONSBAUD 9600 69 #define CONSCFLAG TTYDEF_CFLAG 70 /* end XXX */ 71 72 /* Macros to clear/set/test flags. */ 73 #define SET(t, f) (t) |= (f) 74 #define CLR(t, f) (t) &= ~(f) 75 #define ISSET(t, f) ((t) & (f)) 76 77 #define splserial() spl6() 78 79 /* Buffer size for character buffer */ 80 #define RXBUFSIZE 2048 /* More than enough.. */ 81 #define RXBUFMASK (RXBUFSIZE-1) /* Only iff previous is a power of 2 */ 82 #define RXHIWAT (RXBUFSIZE >> 2) 83 84 struct ser_softc { 85 struct device sc_dev; 86 struct tty *sc_tty; 87 88 int sc_overflows; 89 int sc_floods; 90 int sc_errors; 91 92 u_char sc_hwflags; 93 u_char sc_swflags; 94 95 int sc_ospeed; /* delay + timer-d data */ 96 u_char sc_imra; 97 u_char sc_imrb; 98 u_char sc_ucr; /* Uart control */ 99 u_char sc_msr; /* Modem status */ 100 u_char sc_tsr; /* Tranceiver status */ 101 u_char sc_rsr; /* Receiver status */ 102 u_char sc_mcr; /* (Pseudo) Modem ctrl. */ 103 104 u_char sc_msr_delta; 105 u_char sc_msr_mask; 106 u_char sc_mcr_active; 107 u_char sc_mcr_dtr, sc_mcr_rts, sc_msr_cts, sc_msr_dcd; 108 109 int sc_r_hiwat; 110 volatile u_int sc_rbget; 111 volatile u_int sc_rbput; 112 volatile u_int sc_rbavail; 113 u_char sc_rbuf[RXBUFSIZE]; 114 u_char sc_lbuf[RXBUFSIZE]; 115 116 volatile u_char sc_rx_blocked; 117 volatile u_char sc_rx_ready; 118 volatile u_char sc_tx_busy; 119 volatile u_char sc_tx_done; 120 volatile u_char sc_tx_stopped; 121 volatile u_char sc_st_check; 122 123 u_char *sc_tba; 124 int sc_tbc; 125 int sc_heldtbc; 126 127 volatile u_char sc_heldchange; 128 }; 129 130 /* 131 * For sc_hwflags: 132 */ 133 #define SER_HW_CONSOLE 0x01 134 135 cdev_decl(ser); 136 137 void ser_break __P((struct ser_softc *, int)); 138 void ser_hwiflow __P((struct ser_softc *, int)); 139 void ser_iflush __P((struct ser_softc *)); 140 void ser_loadchannelregs __P((struct ser_softc *)); 141 void ser_modem __P((struct ser_softc *, int)); 142 void serdiag __P((void *)); 143 int serhwiflow __P((struct tty *, int)); 144 void serinit __P((int)); 145 void serinitcons __P((int)); 146 int baud; 147 int sermintr __P((void *)); 148 int sertrintr __P((void *)); 149 int serparam __P((struct tty *, struct termios *)); 150 void serstart __P((struct tty *)); 151 152 struct consdev; 153 void sercnprobe __P((struct consdev *)); 154 void sercninit __P((struct consdev *)); 155 int sercngetc __P((dev_t)); 156 void sercnputc __P((dev_t, int)); 157 void sercnpollc __P((dev_t, int)); 158 159 static void sermsrint __P((struct ser_softc *, struct tty*)); 160 static void serrxint __P((struct ser_softc *, struct tty*)); 161 static int serspeed __P((long)); 162 static void sersoft __P((void *)); 163 static void sertxint __P((struct ser_softc *, struct tty*)); 164 165 static volatile int ser_softintr_scheduled = 0; 166 static int sermajor; 167 168 /* 169 * Autoconfig stuff 170 */ 171 static void serattach __P((struct device *, struct device *, void *)); 172 static int sermatch __P((struct device *, struct cfdata *, void *)); 173 174 struct cfattach ser_ca = { 175 sizeof(struct ser_softc), sermatch, serattach 176 }; 177 178 struct cfdriver ser_cd = { 179 NULL, "ser", DV_TTY, NULL, 0 180 }; 181 182 /*ARGSUSED*/ 183 static int 184 sermatch(pdp, cfp, auxp) 185 struct device *pdp; 186 struct cfdata *cfp; 187 void *auxp; 188 { 189 if (!strcmp((char *)auxp, "ser") && cfp->cf_unit == 0) 190 return (1); 191 return (0); 192 } 193 194 /*ARGSUSED*/ 195 static void 196 serattach(pdp, dp, auxp) 197 struct device *pdp, *dp; 198 void *auxp; 199 { 200 struct ser_softc *sc = (void *)dp; 201 202 if (intr_establish(1, USER_VEC, 0, (hw_ifun_t)sermintr, sc) == NULL) 203 printf("serattach: Can't establish interrupt (1)\n"); 204 if (intr_establish(2, USER_VEC, 0, (hw_ifun_t)sermintr, sc) == NULL) 205 printf("serattach: Can't establish interrupt (2)\n"); 206 if (intr_establish(14, USER_VEC, 0, (hw_ifun_t)sermintr, sc) == NULL) 207 printf("serattach: Can't establish interrupt (14)\n"); 208 if (intr_establish(9, USER_VEC, 0, (hw_ifun_t)sertrintr, sc) == NULL) 209 printf("serattach: Can't establish interrupt (9)\n"); 210 if (intr_establish(10, USER_VEC, 0, (hw_ifun_t)sertrintr, sc) == NULL) 211 printf("serattach: Can't establish interrupt (10)\n"); 212 if (intr_establish(11, USER_VEC, 0, (hw_ifun_t)sertrintr, sc) == NULL) 213 printf("serattach: Can't establish interrupt (11)\n"); 214 if (intr_establish(12, USER_VEC, 0, (hw_ifun_t)sertrintr, sc) == NULL) 215 printf("serattach: Can't establish interrupt (12)\n"); 216 217 ym2149_rts(1); 218 ym2149_dtr(1); 219 220 /* 221 * Enable but mask interrupts... 222 * XXX: Look at edge-sensitivity for DCD/CTS interrupts. 223 */ 224 MFP->mf_ierb |= IB_SCTS|IB_SDCD; 225 MFP->mf_iera |= IA_RRDY|IA_RERR|IA_TRDY|IA_TERR; 226 MFP->mf_imrb &= ~(IB_SCTS|IB_SDCD); 227 MFP->mf_imra &= ~(IA_RRDY|IA_RERR|IA_TRDY|IA_TERR); 228 229 #ifdef SERCONSOLE 230 /* 231 * Activate serial console when DCD present... 232 */ 233 if (!(MFP->mf_gpip & MCR_DCD)) 234 SET(sc->sc_hwflags, SER_HW_CONSOLE); 235 #endif /* SERCONSOLE */ 236 237 printf("\n"); 238 if (ISSET(sc->sc_hwflags, SER_HW_CONSOLE)) { 239 serinit(CONSBAUD); 240 printf("%s: console\n", sc->sc_dev.dv_xname); 241 } 242 } 243 244 #ifdef SER_DEBUG 245 void serstatus __P((struct ser_softc *, char *)); 246 void 247 serstatus(sc, str) 248 struct ser_softc *sc; 249 char *str; 250 { 251 struct tty *tp = sc->sc_tty; 252 253 printf("%s: %s %sclocal %sdcd %sts_carr_on %sdtr %stx_stopped\n", 254 sc->sc_dev.dv_xname, str, 255 ISSET(tp->t_cflag, CLOCAL) ? "+" : "-", 256 ISSET(sc->sc_msr, MCR_DCD) ? "+" : "-", 257 ISSET(tp->t_state, TS_CARR_ON) ? "+" : "-", 258 ISSET(sc->sc_mcr, MCR_DTR) ? "+" : "-", 259 sc->sc_tx_stopped ? "+" : "-"); 260 261 printf("%s: %s %scrtscts %scts %sts_ttstop %srts %srx_blocked\n", 262 sc->sc_dev.dv_xname, str, 263 ISSET(tp->t_cflag, CRTSCTS) ? "+" : "-", 264 ISSET(sc->sc_msr, MCR_CTS) ? "+" : "-", 265 ISSET(tp->t_state, TS_TTSTOP) ? "+" : "-", 266 ISSET(sc->sc_mcr, MCR_RTS) ? "+" : "-", 267 sc->sc_rx_blocked ? "+" : "-"); 268 } 269 #endif /* SER_DEBUG */ 270 271 int 272 seropen(dev, flag, mode, p) 273 dev_t dev; 274 int flag, mode; 275 struct proc *p; 276 { 277 int unit = SERUNIT(dev); 278 struct ser_softc *sc; 279 struct tty *tp; 280 int s, s2; 281 int error = 0; 282 283 if (unit >= ser_cd.cd_ndevs) 284 return (ENXIO); 285 sc = ser_cd.cd_devs[unit]; 286 if (!sc) 287 return (ENXIO); 288 289 if (!sc->sc_tty) { 290 tp = sc->sc_tty = ttymalloc(); 291 tty_attach(tp); 292 } else 293 tp = sc->sc_tty; 294 295 if (ISSET(tp->t_state, TS_ISOPEN) && 296 ISSET(tp->t_state, TS_XCLUDE) && 297 p->p_ucred->cr_uid != 0) 298 return (EBUSY); 299 300 s = spltty(); 301 302 /* We need to set this early for the benefit of sersoft(). */ 303 SET(tp->t_state, TS_WOPEN); 304 305 /* 306 * Do the following if this is a first open. 307 */ 308 if (!ISSET(tp->t_state, TS_ISOPEN)) { 309 struct termios t; 310 311 /* Turn on interrupts. */ 312 sc->sc_imra = IA_RRDY|IA_RERR|IA_TRDY|IA_TERR; 313 sc->sc_imrb = IB_SCTS|IB_SDCD; 314 single_inst_bset_b(MFP->mf_imra, sc->sc_imra); 315 single_inst_bset_b(MFP->mf_imrb, sc->sc_imrb); 316 317 /* Fetch the current modem control status, needed later. */ 318 sc->sc_msr = ~MFP->mf_gpip & (IO_SDCD|IO_SCTS|IO_SRI); 319 320 /* Add some entry points needed by the tty layer. */ 321 tp->t_oproc = serstart; 322 tp->t_param = serparam; 323 tp->t_hwiflow = serhwiflow; 324 tp->t_dev = dev; 325 326 /* 327 * Initialize the termios status to the defaults. Add in the 328 * sticky bits from TIOCSFLAGS. 329 */ 330 t.c_ispeed = 0; 331 if (ISSET(sc->sc_hwflags, SER_HW_CONSOLE)) { 332 t.c_ospeed = CONSBAUD; 333 t.c_cflag = CONSCFLAG; 334 } 335 else { 336 t.c_ospeed = TTYDEF_SPEED; 337 t.c_cflag = TTYDEF_CFLAG; 338 } 339 if (ISSET(sc->sc_swflags, TIOCFLAG_CLOCAL)) 340 SET(t.c_cflag, CLOCAL); 341 if (ISSET(sc->sc_swflags, TIOCFLAG_CRTSCTS)) 342 SET(t.c_cflag, CRTSCTS); 343 if (ISSET(sc->sc_swflags, TIOCFLAG_MDMBUF)) 344 SET(t.c_cflag, MDMBUF); 345 tp->t_iflag = TTYDEF_IFLAG; 346 tp->t_oflag = TTYDEF_OFLAG; 347 tp->t_lflag = TTYDEF_LFLAG; 348 ttychars(tp); 349 (void) serparam(tp, &t); 350 ttsetwater(tp); 351 352 s2 = splserial(); 353 354 /* 355 * Turn on DTR. We must always do this, even if carrier is not 356 * present, because otherwise we'd have to use TIOCSDTR 357 * immediately after setting CLOCAL. We will drop DTR only on 358 * the next high-low transition of DCD, or by explicit request. 359 */ 360 ser_modem(sc, 1); 361 362 /* Clear the input ring, and unblock. */ 363 sc->sc_rbput = sc->sc_rbget = 0; 364 sc->sc_rbavail = RXBUFSIZE; 365 ser_iflush(sc); 366 sc->sc_rx_blocked = 0; 367 ser_hwiflow(sc, 0); 368 369 #ifdef SER_DEBUG 370 serstatus(sc, "seropen "); 371 #endif 372 373 splx(s2); 374 } 375 error = 0; 376 377 /* If we're doing a blocking open... */ 378 if (!ISSET(flag, O_NONBLOCK)) 379 /* ...then wait for carrier. */ 380 while (!ISSET(tp->t_state, TS_CARR_ON) && 381 !ISSET(tp->t_cflag, CLOCAL | MDMBUF)) { 382 error = ttysleep(tp, &tp->t_rawq, TTIPRI | PCATCH, 383 ttopen, 0); 384 if (error) { 385 /* 386 * If the open was interrupted and nobody 387 * else has the device open, then hang up. 388 */ 389 if (!ISSET(tp->t_state, TS_ISOPEN)) { 390 ser_modem(sc, 0); 391 CLR(tp->t_state, TS_WOPEN); 392 ttwakeup(tp); 393 } 394 break; 395 } 396 SET(tp->t_state, TS_WOPEN); 397 } 398 399 splx(s); 400 if (error == 0) 401 error = (*linesw[tp->t_line].l_open)(dev, tp); 402 return (error); 403 } 404 405 int 406 serclose(dev, flag, mode, p) 407 dev_t dev; 408 int flag, mode; 409 struct proc *p; 410 { 411 int unit = SERUNIT(dev); 412 struct ser_softc *sc = ser_cd.cd_devs[unit]; 413 struct tty *tp = sc->sc_tty; 414 int s; 415 416 /* XXX This is for cons.c. */ 417 if (!ISSET(tp->t_state, TS_ISOPEN)) 418 return (0); 419 420 (*linesw[tp->t_line].l_close)(tp, flag); 421 ttyclose(tp); 422 423 /* If we were asserting flow control, then deassert it. */ 424 sc->sc_rx_blocked = 1; 425 ser_hwiflow(sc, 1); 426 427 /* Clear any break condition set with TIOCSBRK. */ 428 ser_break(sc, 0); 429 430 /* 431 * Hang up if necessary. Wait a bit, so the other side has time to 432 * notice even if we immediately open the port again. 433 */ 434 if (ISSET(tp->t_cflag, HUPCL)) { 435 ser_modem(sc, 0); 436 (void) tsleep(sc, TTIPRI, ttclos, hz); 437 } 438 439 s = splserial(); 440 /* Turn off interrupts. */ 441 CLR(sc->sc_imra, IA_RRDY|IA_RERR|IA_TRDY|IA_TERR); 442 CLR(sc->sc_imrb, IB_SCTS|IB_SDCD); 443 single_inst_bclr_b(MFP->mf_imrb, IB_SCTS|IB_SDCD); 444 single_inst_bclr_b(MFP->mf_imra, IA_RRDY|IA_RERR|IA_TRDY|IA_TERR); 445 splx(s); 446 447 return (0); 448 } 449 450 int 451 serread(dev, uio, flag) 452 dev_t dev; 453 struct uio *uio; 454 int flag; 455 { 456 struct ser_softc *sc = ser_cd.cd_devs[SERUNIT(dev)]; 457 struct tty *tp = sc->sc_tty; 458 459 return ((*linesw[tp->t_line].l_read)(tp, uio, flag)); 460 } 461 462 int 463 serwrite(dev, uio, flag) 464 dev_t dev; 465 struct uio *uio; 466 int flag; 467 { 468 struct ser_softc *sc = ser_cd.cd_devs[SERUNIT(dev)]; 469 struct tty *tp = sc->sc_tty; 470 471 return ((*linesw[tp->t_line].l_write)(tp, uio, flag)); 472 } 473 474 struct tty * 475 sertty(dev) 476 dev_t dev; 477 { 478 struct ser_softc *sc = ser_cd.cd_devs[SERUNIT(dev)]; 479 struct tty *tp = sc->sc_tty; 480 481 return (tp); 482 } 483 484 int 485 serioctl(dev, cmd, data, flag, p) 486 dev_t dev; 487 u_long cmd; 488 caddr_t data; 489 int flag; 490 struct proc *p; 491 { 492 int unit = SERUNIT(dev); 493 struct ser_softc *sc = ser_cd.cd_devs[unit]; 494 struct tty *tp = sc->sc_tty; 495 int error; 496 497 error = (*linesw[tp->t_line].l_ioctl)(tp, cmd, data, flag, p); 498 if (error >= 0) 499 return (error); 500 501 error = ttioctl(tp, cmd, data, flag, p); 502 if (error >= 0) 503 return (error); 504 505 switch (cmd) { 506 case TIOCSBRK: 507 ser_break(sc, 1); 508 break; 509 510 case TIOCCBRK: 511 ser_break(sc, 0); 512 break; 513 514 case TIOCSDTR: 515 ser_modem(sc, 1); 516 break; 517 518 case TIOCCDTR: 519 ser_modem(sc, 0); 520 break; 521 522 case TIOCGFLAGS: 523 *(int *)data = sc->sc_swflags; 524 break; 525 526 case TIOCSFLAGS: 527 error = suser(p->p_ucred, &p->p_acflag); 528 if (error) 529 return (error); 530 sc->sc_swflags = *(int *)data; 531 break; 532 533 case TIOCMSET: 534 case TIOCMBIS: 535 case TIOCMBIC: 536 case TIOCMGET: 537 default: 538 return (ENOTTY); 539 } 540 541 #ifdef SER_DEBUG 542 serstatus(sc, "serioctl "); 543 #endif 544 545 return (0); 546 } 547 548 void 549 ser_break(sc, onoff) 550 struct ser_softc *sc; 551 int onoff; 552 { 553 int s; 554 555 s = splserial(); 556 if (onoff) 557 SET(sc->sc_tsr, TSR_SBREAK); 558 else 559 CLR(sc->sc_tsr, TSR_SBREAK); 560 561 if (!sc->sc_heldchange) { 562 if (sc->sc_tx_busy) { 563 sc->sc_heldtbc = sc->sc_tbc; 564 sc->sc_tbc = 0; 565 sc->sc_heldchange = 1; 566 } else 567 ser_loadchannelregs(sc); 568 } 569 splx(s); 570 } 571 572 void 573 ser_modem(sc, onoff) 574 struct ser_softc *sc; 575 int onoff; 576 { 577 int s; 578 579 s = splserial(); 580 if (onoff) 581 SET(sc->sc_mcr, sc->sc_mcr_dtr); 582 else 583 CLR(sc->sc_mcr, sc->sc_mcr_dtr); 584 585 if (!sc->sc_heldchange) { 586 if (sc->sc_tx_busy) { 587 sc->sc_heldtbc = sc->sc_tbc; 588 sc->sc_tbc = 0; 589 sc->sc_heldchange = 1; 590 } else 591 ser_loadchannelregs(sc); 592 } 593 splx(s); 594 } 595 596 int 597 serparam(tp, t) 598 struct tty *tp; 599 struct termios *t; 600 { 601 struct ser_softc *sc = ser_cd.cd_devs[SERUNIT(tp->t_dev)]; 602 int ospeed = serspeed(t->c_ospeed); 603 u_char ucr; 604 int s; 605 606 /* check requested parameters */ 607 if (ospeed < 0) 608 return (EINVAL); 609 if (t->c_ispeed && t->c_ispeed != t->c_ospeed) 610 return (EINVAL); 611 612 sc->sc_rsr = RSR_ENAB; 613 sc->sc_tsr = TSR_ENAB; 614 615 ucr = UCR_CLKDIV; 616 617 switch (ISSET(t->c_cflag, CSIZE)) { 618 case CS5: 619 SET(ucr, UCR_5BITS); 620 break; 621 case CS6: 622 SET(ucr, UCR_6BITS); 623 break; 624 case CS7: 625 SET(ucr, UCR_7BITS); 626 break; 627 case CS8: 628 SET(ucr, UCR_8BITS); 629 break; 630 } 631 if (ISSET(t->c_cflag, PARENB)) { 632 SET(ucr, UCR_PENAB); 633 if (!ISSET(t->c_cflag, PARODD)) 634 SET(ucr, UCR_PEVEN); 635 } 636 if (ISSET(t->c_cflag, CSTOPB)) 637 SET(ucr, UCR_STOPB2); 638 else 639 SET(ucr, UCR_STOPB1); 640 641 s = splserial(); 642 643 sc->sc_ucr = ucr; 644 645 /* 646 * For the console, always force CLOCAL and !HUPCL, so that the port 647 * is always active. 648 */ 649 if (ISSET(sc->sc_swflags, TIOCFLAG_SOFTCAR) || 650 ISSET(sc->sc_hwflags, SER_HW_CONSOLE)) { 651 SET(t->c_cflag, CLOCAL); 652 CLR(t->c_cflag, HUPCL); 653 } 654 655 /* 656 * If we're not in a mode that assumes a connection is present, then 657 * ignore carrier changes. 658 */ 659 if (ISSET(t->c_cflag, CLOCAL | MDMBUF)) 660 sc->sc_msr_dcd = 0; 661 else 662 sc->sc_msr_dcd = MCR_DCD; 663 /* 664 * Set the flow control pins depending on the current flow control 665 * mode. 666 */ 667 if (ISSET(t->c_cflag, CRTSCTS)) { 668 sc->sc_mcr_dtr = MCR_DTR; 669 sc->sc_mcr_rts = MCR_RTS; 670 sc->sc_msr_cts = MCR_CTS; 671 sc->sc_r_hiwat = RXHIWAT; 672 } else if (ISSET(t->c_cflag, MDMBUF)) { 673 /* 674 * For DTR/DCD flow control, make sure we don't toggle DTR for 675 * carrier detection. 676 */ 677 sc->sc_mcr_dtr = 0; 678 sc->sc_mcr_rts = MCR_DTR; 679 sc->sc_msr_cts = MCR_DCD; 680 sc->sc_r_hiwat = RXHIWAT; 681 } else { 682 /* 683 * If no flow control, then always set RTS. This will make 684 * the other side happy if it mistakenly thinks we're doing 685 * RTS/CTS flow control. 686 */ 687 sc->sc_mcr_dtr = MCR_DTR | MCR_RTS; 688 sc->sc_mcr_rts = 0; 689 sc->sc_msr_cts = 0; 690 sc->sc_r_hiwat = 0; 691 if (ISSET(sc->sc_mcr, MCR_DTR)) 692 SET(sc->sc_mcr, MCR_RTS); 693 else 694 CLR(sc->sc_mcr, MCR_RTS); 695 } 696 sc->sc_msr_mask = sc->sc_msr_cts | sc->sc_msr_dcd; 697 698 #if 0 699 if (ospeed == 0) 700 CLR(sc->sc_mcr, sc->sc_mcr_dtr); 701 else 702 SET(sc->sc_mcr, sc->sc_mcr_dtr); 703 #endif 704 705 sc->sc_ospeed = ospeed; 706 707 /* and copy to tty */ 708 tp->t_ispeed = 0; 709 tp->t_ospeed = t->c_ospeed; 710 tp->t_cflag = t->c_cflag; 711 712 if (!sc->sc_heldchange) { 713 if (sc->sc_tx_busy) { 714 sc->sc_heldtbc = sc->sc_tbc; 715 sc->sc_tbc = 0; 716 sc->sc_heldchange = 1; 717 } else 718 ser_loadchannelregs(sc); 719 } 720 721 splx(s); 722 723 /* 724 * Update the tty layer's idea of the carrier bit, in case we changed 725 * CLOCAL or MDMBUF. We don't hang up here; we only do that if we 726 * lose carrier while carrier detection is on. 727 */ 728 (void) (*linesw[tp->t_line].l_modem)(tp, ISSET(sc->sc_msr, MCR_DCD)); 729 730 #ifdef SER_DEBUG 731 serstatus(sc, "serparam "); 732 #endif 733 734 /* XXXXX FIX ME */ 735 /* Block or unblock as needed. */ 736 if (!ISSET(t->c_cflag, CHWFLOW)) { 737 if (sc->sc_rx_blocked) { 738 sc->sc_rx_blocked = 0; 739 ser_hwiflow(sc, 0); 740 } 741 if (sc->sc_tx_stopped) { 742 sc->sc_tx_stopped = 0; 743 serstart(tp); 744 } 745 } else { 746 #if 0 747 sermsrint(sc, tp); 748 #endif 749 } 750 751 return (0); 752 } 753 754 void 755 ser_iflush(sc) 756 struct ser_softc *sc; 757 { 758 u_char tmp; 759 760 /* flush any pending I/O */ 761 while (ISSET(MFP->mf_rsr, RSR_CIP|RSR_BFULL)) 762 tmp = MFP->mf_udr; 763 } 764 765 void 766 ser_loadchannelregs(sc) 767 struct ser_softc *sc; 768 { 769 /* XXXXX necessary? */ 770 ser_iflush(sc); 771 772 /* 773 * No interrupts please... 774 */ 775 if((MFP->mf_imra & (IA_RRDY|IA_RERR|IA_TRDY|IA_TERR)) != sc->sc_imra) { 776 printf("loadchannelregs: mf_imra: %x sc_imra: %x\n", (u_int)MFP->mf_imra, 777 (u_int)sc->sc_imra); 778 } 779 if((MFP->mf_imrb & (IB_SCTS|IB_SDCD)) != sc->sc_imrb) { 780 printf("loadchannelregs: mf_imrb: %x sc_imrb: %x\n", (u_int)MFP->mf_imrb, 781 (u_int)sc->sc_imrb); 782 } 783 single_inst_bclr_b(MFP->mf_imra, IA_RRDY|IA_RERR|IA_TRDY|IA_TERR); 784 single_inst_bclr_b(MFP->mf_imrb, IB_SCTS|IB_SDCD); 785 786 MFP->mf_ucr = sc->sc_ucr; 787 MFP->mf_rsr = sc->sc_rsr; 788 MFP->mf_tsr = sc->sc_tsr; 789 790 single_inst_bclr_b(MFP->mf_tcdcr, 0x07); 791 MFP->mf_tddr = sc->sc_ospeed; 792 single_inst_bset_b(MFP->mf_tcdcr, (sc->sc_ospeed >> 8) & 0x0f); 793 794 sc->sc_mcr_active = sc->sc_mcr; 795 ym2149_rts(!(sc->sc_mcr_active & MCR_RTS)); 796 ym2149_dtr(!(sc->sc_mcr_active & MCR_DTR)); 797 798 single_inst_bset_b(MFP->mf_imra, sc->sc_imra); 799 single_inst_bset_b(MFP->mf_imrb, sc->sc_imrb); 800 } 801 802 int 803 serhwiflow(tp, block) 804 struct tty *tp; 805 int block; 806 { 807 struct ser_softc *sc = ser_cd.cd_devs[SERUNIT(tp->t_dev)]; 808 int s; 809 810 if (sc->sc_mcr_rts == 0) 811 return (0); 812 813 s = splserial(); 814 if (block) { 815 /* 816 * The tty layer is asking us to block input. 817 * If we already did it, just return TRUE. 818 */ 819 if (sc->sc_rx_blocked) 820 goto out; 821 sc->sc_rx_blocked = 1; 822 } else { 823 /* 824 * The tty layer is asking us to resume input. 825 * The input ring is always empty by now. 826 */ 827 sc->sc_rx_blocked = 0; 828 } 829 ser_hwiflow(sc, block); 830 out: 831 splx(s); 832 return (1); 833 } 834 835 /* 836 * (un)block input via hw flowcontrol 837 */ 838 void 839 ser_hwiflow(sc, block) 840 struct ser_softc *sc; 841 int block; 842 { 843 if (sc->sc_mcr_rts == 0) 844 return; 845 846 if (block) { 847 CLR(sc->sc_mcr, sc->sc_mcr_rts); 848 CLR(sc->sc_mcr_active, sc->sc_mcr_rts); 849 } else { 850 SET(sc->sc_mcr, sc->sc_mcr_rts); 851 SET(sc->sc_mcr_active, sc->sc_mcr_rts); 852 } 853 ym2149_rts(sc->sc_mcr_active & MCR_RTS); 854 } 855 856 void 857 serstart(tp) 858 struct tty *tp; 859 { 860 struct ser_softc *sc = ser_cd.cd_devs[SERUNIT(tp->t_dev)]; 861 int s; 862 863 s = spltty(); 864 if (ISSET(tp->t_state, TS_BUSY)) 865 goto out; 866 if (ISSET(tp->t_state, TS_TIMEOUT | TS_TTSTOP)) 867 goto stopped; 868 869 if (sc->sc_tx_stopped) 870 goto stopped; 871 872 if (tp->t_outq.c_cc <= tp->t_lowat) { 873 if (ISSET(tp->t_state, TS_ASLEEP)) { 874 CLR(tp->t_state, TS_ASLEEP); 875 wakeup(&tp->t_outq); 876 } 877 selwakeup(&tp->t_wsel); 878 if (tp->t_outq.c_cc == 0) 879 goto stopped; 880 } 881 882 /* Grab the first contiguous region of buffer space. */ 883 { 884 u_char *tba; 885 int tbc; 886 887 tba = tp->t_outq.c_cf; 888 tbc = ndqb(&tp->t_outq, 0); 889 890 (void)splserial(); 891 892 sc->sc_tba = tba; 893 sc->sc_tbc = tbc; 894 } 895 896 SET(tp->t_state, TS_BUSY); 897 sc->sc_tx_busy = 1; 898 899 /* Enable transmit completion interrupts if necessary. */ 900 if (!ISSET(sc->sc_imra, IA_TRDY)) { 901 SET(sc->sc_imra, IA_TRDY|IA_TERR); 902 single_inst_bset_b(MFP->mf_imra, IA_TRDY|IA_TERR); 903 } 904 905 /* Output the first char */ 906 MFP->mf_udr = *sc->sc_tba; 907 sc->sc_tbc --; 908 sc->sc_tba ++; 909 910 splx(s); 911 return; 912 913 stopped: 914 /* Disable transmit completion interrupts if necessary. */ 915 if (ISSET(sc->sc_imra, IA_TRDY)) { 916 CLR(sc->sc_imra, IA_TRDY|IA_TERR); 917 single_inst_bclr_b(MFP->mf_imra, IA_TRDY|IA_TERR); 918 } 919 out: 920 splx(s); 921 return; 922 } 923 924 /* 925 * Stop output on a line. 926 */ 927 void 928 serstop(tp, flag) 929 struct tty *tp; 930 int flag; 931 { 932 struct ser_softc *sc = ser_cd.cd_devs[SERUNIT(tp->t_dev)]; 933 int s; 934 935 s = splserial(); 936 if (ISSET(tp->t_state, TS_BUSY)) { 937 /* Stop transmitting at the next chunk. */ 938 sc->sc_tbc = 0; 939 sc->sc_heldtbc = 0; 940 if (!ISSET(tp->t_state, TS_TTSTOP)) 941 SET(tp->t_state, TS_FLUSH); 942 } 943 splx(s); 944 } 945 946 void 947 serdiag(arg) 948 void *arg; 949 { 950 struct ser_softc *sc = arg; 951 int overflows, floods; 952 int s; 953 954 s = splserial(); 955 overflows = sc->sc_overflows; 956 sc->sc_overflows = 0; 957 floods = sc->sc_floods; 958 sc->sc_floods = 0; 959 sc->sc_errors = 0; 960 splx(s); 961 962 log(LOG_WARNING, 963 "%s: %d silo overflow%s, %d ibuf flood%s\n", 964 sc->sc_dev.dv_xname, 965 overflows, overflows == 1 ? "" : "s", 966 floods, floods == 1 ? "" : "s"); 967 } 968 969 static void 970 serrxint(sc, tp) 971 struct ser_softc *sc; 972 struct tty *tp; 973 { 974 u_int get, cc, scc; 975 int code; 976 u_char rsr; 977 int s; 978 static int lsrmap[8] = { 979 0, TTY_PE, 980 TTY_FE, TTY_PE|TTY_FE, 981 TTY_FE, TTY_PE|TTY_FE, 982 TTY_FE, TTY_PE|TTY_FE 983 }; 984 985 get = sc->sc_rbget; 986 scc = cc = RXBUFSIZE - sc->sc_rbavail; 987 988 if (cc == RXBUFSIZE) { 989 sc->sc_floods++; 990 if (sc->sc_errors++ == 0) 991 timeout(serdiag, sc, 60 * hz); 992 } 993 994 while (cc--) { 995 rsr = sc->sc_lbuf[get]; 996 if (ISSET(rsr, RSR_BREAK)) { 997 #ifdef DDB 998 if (ISSET(sc->sc_hwflags, SER_HW_CONSOLE)) 999 Debugger(); 1000 #endif 1001 } 1002 else if (ISSET(rsr, RSR_OERR)) { 1003 sc->sc_overflows++; 1004 if (sc->sc_errors++ == 0) 1005 timeout(serdiag, sc, 60 * hz); 1006 } 1007 code = sc->sc_rbuf[get] | 1008 lsrmap[(rsr & (RSR_BREAK|RSR_FERR|RSR_PERR)) >> 3]; 1009 (*linesw[tp->t_line].l_rint)(code, tp); 1010 get = (get + 1) & RXBUFMASK; 1011 } 1012 1013 sc->sc_rbget = get; 1014 s = splserial(); 1015 sc->sc_rbavail += scc; 1016 /* 1017 * Buffers should be ok again, release possible block, but only if the 1018 * tty layer isn't blocking too. 1019 */ 1020 if (sc->sc_rx_blocked && !ISSET(tp->t_state, TS_TBLOCK)) { 1021 sc->sc_rx_blocked = 0; 1022 ser_hwiflow(sc, 0); 1023 } 1024 splx(s); 1025 } 1026 1027 static void 1028 sertxint(sc, tp) 1029 struct ser_softc *sc; 1030 struct tty *tp; 1031 { 1032 1033 CLR(tp->t_state, TS_BUSY); 1034 if (ISSET(tp->t_state, TS_FLUSH)) 1035 CLR(tp->t_state, TS_FLUSH); 1036 else 1037 ndflush(&tp->t_outq, (int)(sc->sc_tba - tp->t_outq.c_cf)); 1038 (*linesw[tp->t_line].l_start)(tp); 1039 } 1040 1041 static void 1042 sermsrint(sc, tp) 1043 struct ser_softc *sc; 1044 struct tty *tp; 1045 { 1046 u_char msr, delta; 1047 int s; 1048 1049 s = splserial(); 1050 msr = sc->sc_msr; 1051 delta = sc->sc_msr_delta; 1052 sc->sc_msr_delta = 0; 1053 splx(s); 1054 1055 if (ISSET(delta, sc->sc_msr_dcd)) { 1056 /* 1057 * Inform the tty layer that carrier detect changed. 1058 */ 1059 (void) (*linesw[tp->t_line].l_modem)(tp, ISSET(msr, MCR_DCD)); 1060 } 1061 1062 if (ISSET(delta, sc->sc_msr_cts)) { 1063 /* Block or unblock output according to flow control. */ 1064 if (ISSET(msr, sc->sc_msr_cts)) { 1065 sc->sc_tx_stopped = 0; 1066 (*linesw[tp->t_line].l_start)(tp); 1067 } else { 1068 sc->sc_tx_stopped = 1; 1069 serstop(tp, 0); 1070 } 1071 } 1072 1073 #ifdef SER_DEBUG 1074 serstatus(sc, "sermsrint"); 1075 #endif 1076 } 1077 1078 void 1079 sersoft(arg) 1080 void *arg; 1081 { 1082 struct ser_softc *sc = arg; 1083 struct tty *tp; 1084 1085 ser_softintr_scheduled = 0; 1086 1087 tp = sc->sc_tty; 1088 if (tp == NULL || !ISSET(tp->t_state, TS_ISOPEN | TS_WOPEN)) 1089 return; 1090 1091 if (sc->sc_rx_ready) { 1092 sc->sc_rx_ready = 0; 1093 serrxint(sc, tp); 1094 } 1095 1096 if (sc->sc_st_check) { 1097 sc->sc_st_check = 0; 1098 sermsrint(sc, tp); 1099 } 1100 1101 if (sc->sc_tx_done) { 1102 sc->sc_tx_done = 0; 1103 sertxint(sc, tp); 1104 } 1105 } 1106 1107 int 1108 sermintr(arg) 1109 void *arg; 1110 { 1111 struct ser_softc *sc = arg; 1112 u_char msr, delta; 1113 1114 msr = ~MFP->mf_gpip; 1115 delta = msr ^ sc->sc_msr; 1116 sc->sc_msr = sc->sc_msr & ~(MCR_CTS|MCR_DCD|MCR_RI); 1117 sc->sc_msr |= msr & (MCR_CTS|MCR_DCD|MCR_RI); 1118 1119 if (ISSET(delta, sc->sc_msr_mask)) { 1120 sc->sc_msr_delta |= delta; 1121 1122 /* 1123 * Stop output immediately if we lose the output 1124 * flow control signal or carrier detect. 1125 */ 1126 if (ISSET(~msr, sc->sc_msr_mask)) { 1127 sc->sc_tbc = 0; 1128 sc->sc_heldtbc = 0; 1129 #ifdef SER_DEBUG 1130 serstatus(sc, "sermintr "); 1131 #endif 1132 } 1133 1134 sc->sc_st_check = 1; 1135 } 1136 if (!ser_softintr_scheduled) 1137 add_sicallback((si_farg)sersoft, sc, 0); 1138 return 1; 1139 } 1140 1141 int 1142 sertrintr(arg) 1143 void *arg; 1144 { 1145 struct ser_softc *sc = arg; 1146 u_int put, cc; 1147 u_char rsr, tsr; 1148 1149 put = sc->sc_rbput; 1150 cc = sc->sc_rbavail; 1151 1152 rsr = MFP->mf_rsr; 1153 if (ISSET(rsr, RSR_BFULL|RSR_BREAK)) { 1154 for (; ISSET(rsr, RSR_BFULL|RSR_BREAK) && cc > 0; cc--) { 1155 sc->sc_rbuf[put] = MFP->mf_udr; 1156 sc->sc_lbuf[put] = rsr; 1157 put = (put + 1) & RXBUFMASK; 1158 if ((rsr & RSR_BREAK) && (MFP->mf_rsr & RSR_BREAK)) 1159 rsr = 0; 1160 else rsr = MFP->mf_rsr; 1161 } 1162 /* 1163 * Current string of incoming characters ended because 1164 * no more data was available. Schedule a receive event 1165 * if any data was received. Drop any characters that 1166 * we couldn't handle. 1167 */ 1168 sc->sc_rbput = put; 1169 sc->sc_rbavail = cc; 1170 sc->sc_rx_ready = 1; 1171 /* 1172 * See if we are in danger of overflowing a buffer. If 1173 * so, use hardware flow control to ease the pressure. 1174 */ 1175 if (sc->sc_rx_blocked == 0 && 1176 cc < sc->sc_r_hiwat) { 1177 sc->sc_rx_blocked = 1; 1178 ser_hwiflow(sc, 1); 1179 } 1180 /* 1181 * If we're out of space, throw away any further input. 1182 */ 1183 if (!cc) { 1184 while (ISSET(rsr, RSR_BFULL|RSR_BREAK)) { 1185 rsr = MFP->mf_udr; 1186 rsr = MFP->mf_rsr; 1187 } 1188 } 1189 } 1190 1191 /* 1192 * Done handling any receive interrupts. See if data can be 1193 * transmitted as well. Schedule tx done event if no data left 1194 * and tty was marked busy. 1195 */ 1196 tsr = MFP->mf_tsr; 1197 if (ISSET(tsr, TSR_BE)) { 1198 /* 1199 * If we've delayed a parameter change, do it now, and restart 1200 * output. 1201 */ 1202 if (sc->sc_heldchange) { 1203 ser_loadchannelregs(sc); 1204 sc->sc_heldchange = 0; 1205 sc->sc_tbc = sc->sc_heldtbc; 1206 sc->sc_heldtbc = 0; 1207 } 1208 /* Output the next character, if any. */ 1209 if (sc->sc_tbc > 0) { 1210 MFP->mf_udr = *sc->sc_tba; 1211 sc->sc_tbc --; 1212 sc->sc_tba ++; 1213 } else if (sc->sc_tx_busy) { 1214 sc->sc_tx_busy = 0; 1215 sc->sc_tx_done = 1; 1216 } 1217 } 1218 1219 if (!ser_softintr_scheduled) 1220 add_sicallback((si_farg)sersoft, sc, 0); 1221 return 1; 1222 } 1223 1224 static int 1225 serspeed(speed) 1226 long speed; 1227 { 1228 #define divrnd(n, q) (((n)*2/(q)+1)/2) /* divide and round off */ 1229 1230 int div, x, err; 1231 1232 if (speed <= 0) 1233 return (-1); 1234 1235 for (div = 4; div <= 64; div *= 4) { 1236 x = divrnd((SER_FREQ / div), speed); 1237 1238 /* 1239 * The value must fit in the timer-d dataregister. If 1240 * not, try another delay-mode. 1241 */ 1242 if ((x/2) > 255) 1243 continue; 1244 1245 /* 1246 * Baudrate to high for the interface or cannot be made 1247 * within tolerance. 1248 */ 1249 if (x <= 0) 1250 return (-1); 1251 1252 err = divrnd((SER_FREQ / div) * 1000, speed * x) - 1000; 1253 if (err < 0) 1254 err = -err; 1255 if (err > SER_TOLERANCE) 1256 continue; 1257 1258 /* 1259 * Translate 'div' to delay-code 1260 */ 1261 if (div == 4) 1262 div = 1; 1263 else if (div == 16) 1264 div = 3; 1265 else if (div == 64) 1266 div = 5; 1267 1268 return ((x/2) | (div << 8)); 1269 } 1270 return (-1); 1271 1272 #undef divrnd(n, q) 1273 } 1274 1275 /* 1276 * Following are all routines needed for SER to act as console 1277 */ 1278 #include <dev/cons.h> 1279 1280 void 1281 sercnprobe(cp) 1282 struct consdev *cp; 1283 { 1284 /* 1285 * Activate serial console when DCD present... 1286 */ 1287 if (MFP->mf_gpip & MCR_DCD) { 1288 cp->cn_pri = CN_DEAD; 1289 return; 1290 } 1291 for (sermajor = 0; sermajor < nchrdev; sermajor++) 1292 if (cdevsw[sermajor].d_open == seropen) 1293 break; 1294 1295 /* initialize required fields */ 1296 cp->cn_dev = makedev(sermajor, 0); /* XXX: LWP What unit? */ 1297 #ifdef SERCONSOLE 1298 cp->cn_pri = CN_REMOTE; /* Force a serial port console */ 1299 #else 1300 cp->cn_pri = CN_NORMAL; 1301 #endif 1302 } 1303 1304 void 1305 sercninit(cp) 1306 struct consdev *cp; 1307 { 1308 serinitcons(CONSBAUD); 1309 } 1310 1311 /* 1312 * Initialize UART to known state. 1313 */ 1314 void 1315 serinit(baud) 1316 int baud; 1317 { 1318 int ospeed = serspeed(baud); 1319 1320 MFP->mf_ucr = UCR_CLKDIV|UCR_8BITS|UCR_STOPB1; 1321 MFP->mf_rsr = RSR_ENAB; 1322 MFP->mf_tsr = TSR_ENAB; 1323 1324 single_inst_bclr_b(MFP->mf_tcdcr, 0x07); 1325 MFP->mf_tddr = ospeed; 1326 single_inst_bset_b(MFP->mf_tcdcr, (ospeed >> 8) & 0x0f); 1327 } 1328 1329 /* 1330 * Set UART for console use. Do normal init, then enable interrupts. 1331 */ 1332 void 1333 serinitcons(baud) 1334 int baud; 1335 { 1336 serinit(baud); 1337 1338 /* Set rts/dtr */ 1339 ym2149_rts(0); 1340 ym2149_dtr(0); 1341 1342 single_inst_bset_b(MFP->mf_imra, (IA_RRDY|IA_RERR|IA_TRDY|IA_TERR)); 1343 } 1344 1345 int 1346 sercngetc(dev) 1347 dev_t dev; 1348 { 1349 u_char stat, c; 1350 int s; 1351 1352 s = splserial(); 1353 while (!ISSET(stat = MFP->mf_rsr, RSR_BFULL)) { 1354 if (!ISSET(stat, RSR_ENAB)) /* XXX */ 1355 MFP->mf_rsr |= RSR_ENAB; 1356 if (stat & (RSR_FERR|RSR_PERR|RSR_OERR)) 1357 c = MFP->mf_udr; 1358 } 1359 c = MFP->mf_udr; 1360 splx(s); 1361 return c; 1362 } 1363 1364 u_int s_imra; 1365 u_int s_stat1, s_stat2, s_stat3; 1366 void 1367 sercnputc(dev, c) 1368 dev_t dev; 1369 int c; 1370 { 1371 int timo; 1372 u_char stat, imra; 1373 1374 /* Mask serial interrupts */ 1375 imra = MFP->mf_imra & (IA_RRDY|IA_RERR|IA_TRDY|IA_TERR); 1376 single_inst_bclr_b(MFP->mf_imra, imra); 1377 s_imra = imra; 1378 1379 /* wait for any pending transmission to finish */ 1380 timo = 50000; 1381 s_stat1 = MFP->mf_tsr; 1382 while (!ISSET(stat = MFP->mf_tsr, TSR_BE) && --timo) 1383 ; 1384 MFP->mf_udr = c; 1385 /* wait for this transmission to complete */ 1386 timo = 1500000; 1387 s_stat2 = MFP->mf_tsr; 1388 while (!ISSET(stat = MFP->mf_tsr, TSR_BE) && --timo) 1389 ; 1390 1391 s_stat3 = MFP->mf_tsr; 1392 /* Clear pending serial interrupts and re-enable */ 1393 single_inst_bclr_b(MFP->mf_ipra, imra); 1394 single_inst_bset_b(MFP->mf_imra, imra); 1395 } 1396 1397 void 1398 sercnpollc(dev, on) 1399 dev_t dev; 1400 int on; 1401 { 1402 1403 } 1404