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