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