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