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