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