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