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