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