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