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