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