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