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