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