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