1 /* $NetBSD: epcom.c,v 1.35 2022/02/12 03:24:34 riastradh Exp $ */ 2 /* 3 * Copyright (c) 1998, 1999, 2001, 2002, 2004 The NetBSD Foundation, Inc. 4 * All rights reserved. 5 * 6 * This code is derived from software contributed to The NetBSD Foundation 7 * by Jesse Off 8 * 9 * This code is derived from software contributed to The NetBSD Foundation 10 * by Ichiro FUKUHARA and Naoto Shimazaki. 11 * 12 * This code is derived from software contributed to The NetBSD Foundation 13 * by IWAMOTO Toshihiro. 14 * 15 * This code is derived from software contributed to The NetBSD Foundation 16 * by Charles M. Hannum. 17 * 18 * Redistribution and use in source and binary forms, with or without 19 * modification, are permitted provided that the following conditions 20 * are met: 21 * 1. Redistributions of source code must retain the above copyright 22 * notice, this list of conditions and the following disclaimer. 23 * 2. Redistributions in binary form must reproduce the above copyright 24 * notice, this list of conditions and the following disclaimer in the 25 * documentation and/or other materials provided with the distribution. 26 * 27 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 28 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 29 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 30 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 31 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 32 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 33 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 34 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 35 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 36 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 37 * POSSIBILITY OF SUCH DAMAGE. 38 */ 39 40 /* 41 * Copyright (c) 1991 The Regents of the University of California. 42 * All rights reserved. 43 * 44 * Redistribution and use in source and binary forms, with or without 45 * modification, are permitted provided that the following conditions 46 * are met: 47 * 1. Redistributions of source code must retain the above copyright 48 * notice, this list of conditions and the following disclaimer. 49 * 2. Redistributions in binary form must reproduce the above copyright 50 * notice, this list of conditions and the following disclaimer in the 51 * documentation and/or other materials provided with the distribution. 52 * 3. Neither the name of the University nor the names of its contributors 53 * may be used to endorse or promote products derived from this software 54 * without specific prior written permission. 55 * 56 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 57 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 58 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 59 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 60 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 61 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 62 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 63 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 64 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 65 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 66 * SUCH DAMAGE. 67 * 68 * @(#)com.c 7.5 (Berkeley) 5/16/91 69 */ 70 71 /* 72 * TODO: hardware flow control 73 */ 74 75 #include <sys/cdefs.h> 76 __KERNEL_RCSID(0, "$NetBSD: epcom.c,v 1.35 2022/02/12 03:24:34 riastradh Exp $"); 77 78 #include "opt_ddb.h" 79 #include "opt_kgdb.h" 80 #include "epcom.h" 81 82 #ifdef RND_COM 83 #include <sys/rndsource.h> 84 #endif 85 86 /* 87 * Override cnmagic(9) macro before including <sys/systm.h>. 88 * We need to know if cn_check_magic triggered debugger, so set a flag. 89 * Callers of cn_check_magic must declare int cn_trapped = 0; 90 * XXX: this is *ugly*! 91 */ 92 #define cn_trap() \ 93 do { \ 94 console_debugger(); \ 95 cn_trapped = 1; \ 96 } while (/* CONSTCOND */ 0) 97 98 99 #include <sys/param.h> 100 #include <sys/systm.h> 101 #include <sys/types.h> 102 #include <sys/conf.h> 103 #include <sys/file.h> 104 #include <sys/device.h> 105 #include <sys/kernel.h> 106 #include <sys/kmem.h> 107 #include <sys/tty.h> 108 #include <sys/uio.h> 109 #include <sys/vnode.h> 110 #include <sys/kauth.h> 111 112 #include <machine/intr.h> 113 #include <sys/bus.h> 114 115 #include <arm/ep93xx/epcomreg.h> 116 #include <arm/ep93xx/epcomvar.h> 117 #include <arm/ep93xx/ep93xxreg.h> 118 #include <arm/ep93xx/ep93xxvar.h> 119 120 #include <dev/cons.h> 121 122 static int epcomparam(struct tty *, struct termios *); 123 static void epcomstart(struct tty *); 124 static int epcomhwiflow(struct tty *, int); 125 126 static u_int cflag2lcrhi(tcflag_t); 127 static void epcom_iflush(struct epcom_softc *); 128 static void epcom_set(struct epcom_softc *); 129 130 int epcomcngetc(dev_t); 131 void epcomcnputc(dev_t, int); 132 void epcomcnpollc(dev_t, int); 133 134 static void epcomsoft(void* arg); 135 inline static void epcom_txsoft(struct epcom_softc *, struct tty *); 136 inline static void epcom_rxsoft(struct epcom_softc *, struct tty *); 137 138 void epcomcnprobe(struct consdev *); 139 void epcomcninit(struct consdev *); 140 141 static struct epcom_cons_softc { 142 bus_space_tag_t sc_iot; 143 bus_space_handle_t sc_ioh; 144 bus_addr_t sc_hwbase; 145 int sc_ospeed; 146 tcflag_t sc_cflag; 147 } epcomcn_sc; 148 149 static int epcom_common_getc(struct epcom_cons_softc *, dev_t); 150 static void epcom_common_putc(struct epcom_cons_softc *, int); 151 static void epcominit(struct epcom_cons_softc *, bus_space_tag_t, 152 bus_addr_t, bus_space_handle_t, int, tcflag_t); 153 154 static struct cnm_state epcom_cnm_state; 155 156 extern struct cfdriver epcom_cd; 157 158 dev_type_open(epcomopen); 159 dev_type_close(epcomclose); 160 dev_type_read(epcomread); 161 dev_type_write(epcomwrite); 162 dev_type_ioctl(epcomioctl); 163 dev_type_stop(epcomstop); 164 dev_type_tty(epcomtty); 165 dev_type_poll(epcompoll); 166 167 const struct cdevsw epcom_cdevsw = { 168 .d_open = epcomopen, 169 .d_close = epcomclose, 170 .d_read = epcomread, 171 .d_write = epcomwrite, 172 .d_ioctl = epcomioctl, 173 .d_stop = epcomstop, 174 .d_tty = epcomtty, 175 .d_poll = epcompoll, 176 .d_mmap = nommap, 177 .d_kqfilter = ttykqfilter, 178 .d_discard = nodiscard, 179 .d_flag = D_TTY 180 }; 181 182 struct consdev epcomcons = { 183 NULL, NULL, epcomcngetc, epcomcnputc, epcomcnpollc, NULL, 184 NULL, NULL, NODEV, CN_NORMAL 185 }; 186 187 #if defined(KGDB) 188 #include <sys/kgdb.h> 189 190 static int epcom_kgdb_getc(void *); 191 static void epcom_kgdb_putc(void *, int); 192 193 /* 194 * Reuse the console softc structure because 195 * we'll be reusing the console I/O code. 196 */ 197 static struct epcom_cons_softc kgdb_sc; 198 #endif 199 200 #ifndef DEFAULT_COMSPEED 201 #define DEFAULT_COMSPEED 115200 202 #endif 203 204 #define COMUNIT(x) TTUNIT(x) 205 #define COMDIALOUT(x) TTDIALOUT(x) 206 207 #define COM_ISALIVE(sc) ((sc)->enabled != 0 && \ 208 device_is_active((sc)->sc_dev)) 209 210 void 211 epcom_attach_subr(struct epcom_softc *sc) 212 { 213 struct tty *tp; 214 215 if (sc->sc_iot == epcomcn_sc.sc_iot 216 && sc->sc_hwbase == epcomcn_sc.sc_hwbase) { 217 sc->sc_lcrlo = EPCOMSPEED2BRD(epcomcn_sc.sc_ospeed) & 0xff; 218 sc->sc_lcrmid = EPCOMSPEED2BRD(epcomcn_sc.sc_ospeed) >> 8; 219 220 /* Make sure the console is always "hardwired". */ 221 delay(10000); /* wait for output to finish */ 222 SET(sc->sc_hwflags, COM_HW_CONSOLE); 223 SET(sc->sc_swflags, TIOCFLAG_SOFTCAR); 224 } 225 226 tp = tty_alloc(); 227 tp->t_oproc = epcomstart; 228 tp->t_param = epcomparam; 229 tp->t_hwiflow = epcomhwiflow; 230 231 sc->sc_tty = tp; 232 sc->sc_rbuf = kmem_alloc(EPCOM_RING_SIZE << 1, KM_SLEEP); 233 sc->sc_rbput = sc->sc_rbget = sc->sc_rbuf; 234 sc->sc_rbavail = EPCOM_RING_SIZE; 235 sc->sc_ebuf = sc->sc_rbuf + (EPCOM_RING_SIZE << 1); 236 sc->sc_tbc = 0; 237 238 sc->sc_lcrlo = EPCOMSPEED2BRD(DEFAULT_COMSPEED) & 0xff; 239 sc->sc_lcrmid = EPCOMSPEED2BRD(DEFAULT_COMSPEED) >> 8; 240 sc->sc_lcrhi = cflag2lcrhi(CS8); /* 8N1 */ 241 242 tty_attach(tp); 243 244 if (ISSET(sc->sc_hwflags, COM_HW_CONSOLE)) { 245 int maj; 246 247 /* locate the major number */ 248 maj = cdevsw_lookup_major(&epcom_cdevsw); 249 250 cn_tab->cn_dev = makedev(maj, device_unit(sc->sc_dev)); 251 252 aprint_normal("%s: console\n", device_xname(sc->sc_dev)); 253 } 254 255 #ifdef KGDB 256 /* 257 * Allow kgdb to "take over" this port. If this is 258 * the kgdb device, it has exclusive use. 259 */ 260 if (sc->sc_iot == kgdb_sc.sc_iot && 261 sc->sc_hwbase == kgdb_sc.sc_hwbase) { 262 SET(sc->sc_hwflags, COM_HW_KGDB); 263 device_printf(sc->sc_dev, "kgdb\n"); 264 } 265 #endif 266 267 sc->sc_si = softint_establish(SOFTINT_SERIAL, epcomsoft, sc); 268 269 #ifdef RND_COM 270 rnd_attach_source(&sc->rnd_source, device_xname(sc->sc_dev), 271 RND_TYPE_TTY, RND_FLAG_DEFAULT); 272 #endif 273 274 /* if there are no enable/disable functions, assume the device 275 is always enabled */ 276 if (!sc->enable) 277 sc->enabled = 1; 278 279 /* XXX configure register */ 280 /* xxx_config(sc) */ 281 282 SET(sc->sc_hwflags, COM_HW_DEV_OK); 283 } 284 285 static int 286 epcomparam(struct tty *tp, struct termios *t) 287 { 288 struct epcom_softc *sc 289 = device_lookup_private(&epcom_cd, COMUNIT(tp->t_dev)); 290 int s; 291 292 if (COM_ISALIVE(sc) == 0) 293 return (EIO); 294 295 if (t->c_ispeed && t->c_ispeed != t->c_ospeed) 296 return (EINVAL); 297 298 /* 299 * For the console, always force CLOCAL and !HUPCL, so that the port 300 * is always active. 301 */ 302 if (ISSET(sc->sc_swflags, TIOCFLAG_SOFTCAR) || 303 ISSET(sc->sc_hwflags, COM_HW_CONSOLE)) { 304 SET(t->c_cflag, CLOCAL); 305 CLR(t->c_cflag, HUPCL); 306 } 307 308 /* 309 * If there were no changes, don't do anything. This avoids dropping 310 * input and improves performance when all we did was frob things like 311 * VMIN and VTIME. 312 */ 313 if (tp->t_ospeed == t->c_ospeed && 314 tp->t_cflag == t->c_cflag) 315 return (0); 316 317 s = splserial(); 318 319 sc->sc_lcrhi = cflag2lcrhi(t->c_cflag); 320 sc->sc_lcrlo = EPCOMSPEED2BRD(t->c_ospeed) & 0xff; 321 sc->sc_lcrmid = EPCOMSPEED2BRD(t->c_ospeed) >> 8; 322 323 /* And copy to tty. */ 324 tp->t_ispeed = 0; 325 tp->t_ospeed = t->c_ospeed; 326 tp->t_cflag = t->c_cflag; 327 epcom_set(sc); 328 329 splx(s); 330 331 /* 332 * Update the tty layer's idea of the carrier bit. 333 * We tell tty the carrier is always on. 334 */ 335 (void) (*tp->t_linesw->l_modem)(tp, 1); 336 337 #ifdef COM_DEBUG 338 if (com_debug) 339 comstatus(sc, "comparam "); 340 #endif 341 342 if (!ISSET(t->c_cflag, CHWFLOW)) { 343 if (sc->sc_tx_stopped) { 344 sc->sc_tx_stopped = 0; 345 epcomstart(tp); 346 } 347 } 348 349 return (0); 350 } 351 352 static int 353 epcomhwiflow(struct tty *tp, int block) 354 { 355 return (0); 356 } 357 358 static void 359 epcom_filltx(struct epcom_softc *sc) 360 { 361 bus_space_tag_t iot = sc->sc_iot; 362 bus_space_handle_t ioh = sc->sc_ioh; 363 int n; 364 365 n = 0; 366 while ((bus_space_read_4(iot, ioh, EPCOM_Flag) & Flag_TXFF) == 0) { 367 if (n >= sc->sc_tbc) 368 break; 369 bus_space_write_4(iot, ioh, EPCOM_Data, 370 0xff & *(sc->sc_tba + n)); 371 n++; 372 } 373 sc->sc_tbc -= n; 374 sc->sc_tba += n; 375 } 376 377 static void 378 epcomstart(struct tty *tp) 379 { 380 struct epcom_softc *sc 381 = device_lookup_private(&epcom_cd, COMUNIT(tp->t_dev)); 382 int s; 383 384 if (COM_ISALIVE(sc) == 0) 385 return; 386 387 s = spltty(); 388 if (ISSET(tp->t_state, TS_BUSY | TS_TIMEOUT | TS_TTSTOP)) 389 goto out; 390 if (sc->sc_tx_stopped) 391 goto out; 392 if (!ttypull(tp)) 393 goto out; 394 395 /* Grab the first contiguous region of buffer space. */ 396 { 397 u_char *tba; 398 int tbc; 399 400 tba = tp->t_outq.c_cf; 401 tbc = ndqb(&tp->t_outq, 0); 402 403 (void)splserial(); 404 405 sc->sc_tba = tba; 406 sc->sc_tbc = tbc; 407 } 408 409 SET(tp->t_state, TS_BUSY); 410 sc->sc_tx_busy = 1; 411 412 /* Output the first chunk of the contiguous buffer. */ 413 epcom_filltx(sc); 414 415 if (!ISSET(sc->sc_ctrl, Ctrl_TIE)) { 416 SET(sc->sc_ctrl, Ctrl_TIE); 417 epcom_set(sc); 418 } 419 420 out: 421 splx(s); 422 return; 423 } 424 425 static void 426 epcom_break(struct epcom_softc *sc, int onoff) 427 { 428 if (onoff) 429 SET(sc->sc_lcrhi, LinCtrlHigh_BRK); 430 else 431 CLR(sc->sc_lcrhi, LinCtrlHigh_BRK); 432 epcom_set(sc); 433 } 434 435 static void 436 epcom_shutdown(struct epcom_softc *sc) 437 { 438 int s; 439 440 s = splserial(); 441 442 /* Turn off interrupts. */ 443 CLR(sc->sc_ctrl, (Ctrl_TIE|Ctrl_RTIE|Ctrl_RIE)); 444 445 /* Clear any break condition set with TIOCSBRK. */ 446 epcom_break(sc, 0); 447 epcom_set(sc); 448 449 if (sc->disable) { 450 #ifdef DIAGNOSTIC 451 if (!sc->enabled) 452 panic("epcom_shutdown: not enabled?"); 453 #endif 454 (*sc->disable)(sc); 455 sc->enabled = 0; 456 } 457 splx(s); 458 } 459 460 int 461 epcomopen(dev_t dev, int flag, int mode, struct lwp *l) 462 { 463 struct epcom_softc *sc; 464 struct tty *tp; 465 int s, s2; 466 int error; 467 468 sc = device_lookup_private(&epcom_cd, COMUNIT(dev)); 469 if (sc == NULL || !ISSET(sc->sc_hwflags, COM_HW_DEV_OK) || 470 sc->sc_rbuf == NULL) 471 return (ENXIO); 472 473 if (!device_is_active(sc->sc_dev)) 474 return (ENXIO); 475 476 #ifdef KGDB 477 /* 478 * If this is the kgdb port, no other use is permitted. 479 */ 480 if (ISSET(sc->sc_hwflags, COM_HW_KGDB)) 481 return (EBUSY); 482 #endif 483 484 tp = sc->sc_tty; 485 486 if (kauth_authorize_device_tty(l->l_cred, KAUTH_DEVICE_TTY_OPEN, tp)) 487 return (EBUSY); 488 489 s = spltty(); 490 491 /* 492 * Do the following iff this is a first open. 493 */ 494 if (!ISSET(tp->t_state, TS_ISOPEN) && tp->t_wopen == 0) { 495 struct termios t; 496 497 tp->t_dev = dev; 498 499 s2 = splserial(); 500 501 if (sc->enable) { 502 if ((*sc->enable)(sc)) { 503 splx(s2); 504 splx(s); 505 printf("%s: device enable failed\n", 506 device_xname(sc->sc_dev)); 507 return (EIO); 508 } 509 sc->enabled = 1; 510 #if 0 511 /* XXXXXXXXXXXXXXX */ 512 com_config(sc); 513 #endif 514 } 515 516 /* Turn on interrupts. */ 517 SET(sc->sc_ctrl, (Ctrl_UARTE|Ctrl_RIE|Ctrl_RTIE)); 518 epcom_set(sc); 519 520 #if 0 521 /* Fetch the current modem control status, needed later. */ 522 sc->sc_msr = bus_space_read_1(sc->sc_iot, sc->sc_ioh, com_msr); 523 524 /* Clear PPS capture state on first open. */ 525 sc->sc_ppsmask = 0; 526 sc->ppsparam.mode = 0; 527 #endif 528 529 splx(s2); 530 531 /* 532 * Initialize the termios status to the defaults. Add in the 533 * sticky bits from TIOCSFLAGS. 534 */ 535 t.c_ispeed = 0; 536 if (ISSET(sc->sc_hwflags, COM_HW_CONSOLE)) { 537 t.c_ospeed = epcomcn_sc.sc_ospeed; 538 t.c_cflag = epcomcn_sc.sc_cflag; 539 } else { 540 t.c_ospeed = TTYDEF_SPEED; 541 t.c_cflag = TTYDEF_CFLAG; 542 } 543 if (ISSET(sc->sc_swflags, TIOCFLAG_CLOCAL)) 544 SET(t.c_cflag, CLOCAL); 545 if (ISSET(sc->sc_swflags, TIOCFLAG_CRTSCTS)) 546 SET(t.c_cflag, CRTSCTS); 547 if (ISSET(sc->sc_swflags, TIOCFLAG_MDMBUF)) 548 SET(t.c_cflag, MDMBUF); 549 /* Make sure epcomparam() will do something. */ 550 tp->t_ospeed = 0; 551 (void) epcomparam(tp, &t); 552 tp->t_iflag = TTYDEF_IFLAG; 553 tp->t_oflag = TTYDEF_OFLAG; 554 tp->t_lflag = TTYDEF_LFLAG; 555 ttychars(tp); 556 ttsetwater(tp); 557 558 s2 = splserial(); 559 560 /* Clear the input ring, and unblock. */ 561 sc->sc_rbput = sc->sc_rbget = sc->sc_rbuf; 562 sc->sc_rbavail = EPCOM_RING_SIZE; 563 epcom_iflush(sc); 564 CLR(sc->sc_rx_flags, RX_ANY_BLOCK); 565 566 #ifdef COM_DEBUG 567 if (epcom_debug) 568 comstatus(sc, "epcomopen "); 569 #endif 570 571 splx(s2); 572 } 573 574 splx(s); 575 576 error = ttyopen(tp, COMDIALOUT(dev), ISSET(flag, O_NONBLOCK)); 577 if (error) 578 goto bad; 579 580 error = (*tp->t_linesw->l_open)(dev, tp); 581 if (error) 582 goto bad; 583 584 return (0); 585 586 bad: 587 if (!ISSET(tp->t_state, TS_ISOPEN) && tp->t_wopen == 0) { 588 /* 589 * We failed to open the device, and nobody else had it opened. 590 * Clean up the state as appropriate. 591 */ 592 epcom_shutdown(sc); 593 } 594 595 return (error); 596 } 597 598 int 599 epcomclose(dev_t dev, int flag, int mode, struct lwp *l) 600 { 601 struct epcom_softc *sc = device_lookup_private(&epcom_cd, COMUNIT(dev)); 602 struct tty *tp = sc->sc_tty; 603 604 /* XXX This is for cons.c. */ 605 if (!ISSET(tp->t_state, TS_ISOPEN)) 606 return (0); 607 608 (*tp->t_linesw->l_close)(tp, flag); 609 ttyclose(tp); 610 611 if (COM_ISALIVE(sc) == 0) 612 return (0); 613 614 if (!ISSET(tp->t_state, TS_ISOPEN) && tp->t_wopen == 0) { 615 /* 616 * Although we got a last close, the device may still be in 617 * use; e.g. if this was the dialout node, and there are still 618 * processes waiting for carrier on the non-dialout node. 619 */ 620 epcom_shutdown(sc); 621 } 622 623 return (0); 624 } 625 626 int 627 epcomread(dev_t dev, struct uio *uio, int flag) 628 { 629 struct epcom_softc *sc = device_lookup_private(&epcom_cd, COMUNIT(dev)); 630 struct tty *tp = sc->sc_tty; 631 632 if (COM_ISALIVE(sc) == 0) 633 return (EIO); 634 635 return ((*tp->t_linesw->l_read)(tp, uio, flag)); 636 } 637 638 int 639 epcomwrite(dev_t dev, struct uio *uio, int flag) 640 { 641 struct epcom_softc *sc = device_lookup_private(&epcom_cd, COMUNIT(dev)); 642 struct tty *tp = sc->sc_tty; 643 644 if (COM_ISALIVE(sc) == 0) 645 return (EIO); 646 647 return ((*tp->t_linesw->l_write)(tp, uio, flag)); 648 } 649 650 int 651 epcompoll(dev_t dev, int events, struct lwp *l) 652 { 653 struct epcom_softc *sc = device_lookup_private(&epcom_cd, COMUNIT(dev)); 654 struct tty *tp = sc->sc_tty; 655 656 if (COM_ISALIVE(sc) == 0) 657 return (EIO); 658 659 return ((*tp->t_linesw->l_poll)(tp, events, l)); 660 } 661 662 struct tty * 663 epcomtty(dev_t dev) 664 { 665 struct epcom_softc *sc = device_lookup_private(&epcom_cd, COMUNIT(dev)); 666 struct tty *tp = sc->sc_tty; 667 668 return (tp); 669 } 670 671 int 672 epcomioctl(dev_t dev, u_long cmd, void *data, int flag, struct lwp *l) 673 { 674 struct epcom_softc *sc = device_lookup_private(&epcom_cd, COMUNIT(dev)); 675 struct tty *tp = sc->sc_tty; 676 int error; 677 int s; 678 679 if (COM_ISALIVE(sc) == 0) 680 return (EIO); 681 682 error = (*tp->t_linesw->l_ioctl)(tp, cmd, data, flag, l); 683 if (error != EPASSTHROUGH) 684 return (error); 685 686 error = ttioctl(tp, cmd, data, flag, l); 687 if (error != EPASSTHROUGH) 688 return (error); 689 690 error = 0; 691 692 s = splserial(); 693 694 switch (cmd) { 695 case TIOCSBRK: 696 epcom_break(sc, 1); 697 break; 698 699 case TIOCCBRK: 700 epcom_break(sc, 0); 701 break; 702 703 case TIOCGFLAGS: 704 *(int *)data = sc->sc_swflags; 705 break; 706 707 case TIOCSFLAGS: 708 error = kauth_authorize_device_tty(l->l_cred, 709 KAUTH_DEVICE_TTY_PRIVSET, tp); 710 if (error) 711 break; 712 sc->sc_swflags = *(int *)data; 713 break; 714 715 default: 716 error = EPASSTHROUGH; 717 break; 718 } 719 720 splx(s); 721 722 return (error); 723 } 724 725 /* 726 * Stop output on a line. 727 */ 728 void 729 epcomstop(struct tty *tp, int flag) 730 { 731 struct epcom_softc *sc 732 = device_lookup_private(&epcom_cd, COMUNIT(tp->t_dev)); 733 int s; 734 735 s = splserial(); 736 if (ISSET(tp->t_state, TS_BUSY)) { 737 /* Stop transmitting at the next chunk. */ 738 sc->sc_tbc = 0; 739 if (!ISSET(tp->t_state, TS_TTSTOP)) 740 SET(tp->t_state, TS_FLUSH); 741 } 742 splx(s); 743 } 744 745 static u_int 746 cflag2lcrhi(tcflag_t cflag) 747 { 748 u_int lcrhi; 749 750 switch (cflag & CSIZE) { 751 case CS7: 752 lcrhi = 0x40; 753 break; 754 case CS6: 755 lcrhi = 0x20; 756 break; 757 case CS8: 758 default: 759 lcrhi = 0x60; 760 break; 761 } 762 lcrhi |= (cflag & PARENB) ? LinCtrlHigh_PEN : 0; 763 lcrhi |= (cflag & PARODD) ? 0 : LinCtrlHigh_EPS; 764 lcrhi |= (cflag & CSTOPB) ? LinCtrlHigh_STP2 : 0; 765 lcrhi |= LinCtrlHigh_FEN; /* FIFO always enabled */ 766 767 return (lcrhi); 768 } 769 770 static void 771 epcom_iflush(struct epcom_softc *sc) 772 { 773 bus_space_tag_t iot = sc->sc_iot; 774 bus_space_handle_t ioh = sc->sc_ioh; 775 #ifdef DIAGNOSTIC 776 int reg; 777 #endif 778 int timo; 779 780 #ifdef DIAGNOSTIC 781 reg = 0xffff; 782 #endif 783 timo = 50000; 784 /* flush any pending I/O */ 785 while ((bus_space_read_4(iot, ioh, EPCOM_Flag) & Flag_RXFE) == 0 786 && --timo) 787 #ifdef DIAGNOSTIC 788 reg = 789 #else 790 (void) 791 #endif 792 bus_space_read_4(iot, ioh, EPCOM_Data); 793 #ifdef DIAGNOSTIC 794 if (!timo) 795 printf("%s: com_iflush timeout %02x\n", device_xname(sc->sc_dev), 796 reg); 797 #endif 798 } 799 800 static void 801 epcom_set(struct epcom_softc *sc) 802 { 803 bus_space_write_4(sc->sc_iot, sc->sc_ioh, EPCOM_LinCtrlLow, 804 sc->sc_lcrlo); 805 bus_space_write_4(sc->sc_iot, sc->sc_ioh, EPCOM_LinCtrlMid, 806 sc->sc_lcrmid); 807 bus_space_write_4(sc->sc_iot, sc->sc_ioh, EPCOM_LinCtrlHigh, 808 sc->sc_lcrhi); 809 bus_space_write_4(sc->sc_iot, sc->sc_ioh, EPCOM_Ctrl, 810 sc->sc_ctrl); 811 } 812 813 int 814 epcomcnattach(bus_space_tag_t iot, bus_addr_t iobase, bus_space_handle_t ioh, 815 int ospeed, tcflag_t cflag) 816 { 817 cn_tab = &epcomcons; 818 cn_init_magic(&epcom_cnm_state); 819 cn_set_magic("\047\001"); 820 821 epcominit(&epcomcn_sc, iot, iobase, ioh, ospeed, cflag); 822 823 return (0); 824 } 825 826 void 827 epcomcnprobe(struct consdev *cp) 828 { 829 cp->cn_pri = CN_REMOTE; 830 } 831 832 void 833 epcomcnpollc(dev_t dev, int on) 834 { 835 } 836 837 void 838 epcomcnputc(dev_t dev, int c) 839 { 840 epcom_common_putc(&epcomcn_sc, c); 841 } 842 843 static void 844 epcom_common_putc(struct epcom_cons_softc *sc, int c) 845 { 846 int s; 847 bus_space_tag_t iot = sc->sc_iot; 848 bus_space_handle_t ioh = sc->sc_ioh; 849 850 s = splserial(); 851 852 while((bus_space_read_4(iot, ioh, EPCOM_Flag) & Flag_TXFF) != 0) 853 ; 854 855 bus_space_write_4(iot, ioh, EPCOM_Data, c); 856 857 #ifdef DEBUG 858 if (c == '\r') { 859 while((bus_space_read_4(iot, ioh, EPCOM_Flag) & Flag_TXFE) == 0) 860 ; 861 } 862 #endif 863 864 splx(s); 865 } 866 867 int 868 epcomcngetc(dev_t dev) 869 { 870 return epcom_common_getc (&epcomcn_sc, dev); 871 } 872 873 static int 874 epcom_common_getc(struct epcom_cons_softc *sc, dev_t dev) 875 { 876 int c, sts; 877 int s; 878 bus_space_tag_t iot = sc->sc_iot; 879 bus_space_handle_t ioh = sc->sc_ioh; 880 881 s = splserial(); 882 883 while((bus_space_read_4(iot, ioh, EPCOM_Flag) & Flag_RXFE) != 0) 884 ; 885 886 c = bus_space_read_4(iot, ioh, EPCOM_Data); 887 sts = bus_space_read_4(iot, ioh, EPCOM_RXSts); 888 if (ISSET(sts, RXSts_BE)) c = CNC_BREAK; 889 #ifdef DDB 890 extern int db_active; 891 if (!db_active) 892 #endif 893 { 894 int cn_trapped __unused = 0; 895 896 cn_check_magic(dev, c, epcom_cnm_state); 897 } 898 c &= 0xff; 899 splx(s); 900 901 return (c); 902 } 903 904 inline static void 905 epcom_txsoft(struct epcom_softc *sc, struct tty *tp) 906 { 907 CLR(tp->t_state, TS_BUSY); 908 if (ISSET(tp->t_state, TS_FLUSH)) 909 CLR(tp->t_state, TS_FLUSH); 910 else 911 ndflush(&tp->t_outq, (int)(sc->sc_tba - tp->t_outq.c_cf)); 912 (*tp->t_linesw->l_start)(tp); 913 } 914 915 inline static void 916 epcom_rxsoft(struct epcom_softc *sc, struct tty *tp) 917 { 918 int (*rint)(int, struct tty *) = tp->t_linesw->l_rint; 919 u_char *get, *end; 920 u_int cc, scc; 921 u_char sts; 922 int code; 923 int s; 924 925 end = sc->sc_ebuf; 926 get = sc->sc_rbget; 927 scc = cc = EPCOM_RING_SIZE - sc->sc_rbavail; 928 #if 0 929 if (cc == EPCOM_RING_SIZE) { 930 sc->sc_floods++; 931 if (sc->sc_errors++ == 0) 932 callout_reset(&sc->sc_diag_callout, 60 * hz, 933 comdiag, sc); 934 } 935 #endif 936 while (cc) { 937 code = get[0]; 938 sts = get[1]; 939 if (ISSET(sts, RXSts_OE | RXSts_FE | RXSts_PE | RXSts_BE)) { 940 #if 0 941 if (ISSET(lsr, DR_ROR)) { 942 sc->sc_overflows++; 943 if (sc->sc_errors++ == 0) 944 callout_reset(&sc->sc_diag_callout, 945 60 * hz, comdiag, sc); 946 } 947 #endif 948 if (ISSET(sts, (RXSts_FE|RXSts_BE))) 949 SET(code, TTY_FE); 950 if (ISSET(sts, RXSts_PE)) 951 SET(code, TTY_PE); 952 } 953 if ((*rint)(code, tp) == -1) { 954 /* 955 * The line discipline's buffer is out of space. 956 */ 957 if (!ISSET(sc->sc_rx_flags, RX_TTY_BLOCKED)) { 958 /* 959 * We're either not using flow control, or the 960 * line discipline didn't tell us to block for 961 * some reason. Either way, we have no way to 962 * know when there's more space available, so 963 * just drop the rest of the data. 964 */ 965 get += cc << 1; 966 if (get >= end) 967 get -= EPCOM_RING_SIZE << 1; 968 cc = 0; 969 } else { 970 /* 971 * Don't schedule any more receive processing 972 * until the line discipline tells us there's 973 * space available (through comhwiflow()). 974 * Leave the rest of the data in the input 975 * buffer. 976 */ 977 SET(sc->sc_rx_flags, RX_TTY_OVERFLOWED); 978 } 979 break; 980 } 981 get += 2; 982 if (get >= end) 983 get = sc->sc_rbuf; 984 cc--; 985 } 986 987 if (cc != scc) { 988 sc->sc_rbget = get; 989 s = splserial(); 990 991 cc = sc->sc_rbavail += scc - cc; 992 /* Buffers should be ok again, release possible block. */ 993 if (cc >= 1) { 994 if (ISSET(sc->sc_rx_flags, RX_IBUF_OVERFLOWED)) { 995 CLR(sc->sc_rx_flags, RX_IBUF_OVERFLOWED); 996 SET(sc->sc_ctrl, (Ctrl_RIE|Ctrl_RTIE)); 997 epcom_set(sc); 998 } 999 if (ISSET(sc->sc_rx_flags, RX_IBUF_BLOCKED)) { 1000 CLR(sc->sc_rx_flags, RX_IBUF_BLOCKED); 1001 #if 0 1002 com_hwiflow(sc); 1003 #endif 1004 } 1005 } 1006 splx(s); 1007 } 1008 } 1009 1010 static void 1011 epcomsoft(void* arg) 1012 { 1013 struct epcom_softc *sc = arg; 1014 1015 if (COM_ISALIVE(sc) == 0) 1016 return; 1017 1018 if (sc->sc_rx_ready) { 1019 sc->sc_rx_ready = 0; 1020 epcom_rxsoft(sc, sc->sc_tty); 1021 } 1022 if (sc->sc_tx_done) { 1023 sc->sc_tx_done = 0; 1024 epcom_txsoft(sc, sc->sc_tty); 1025 } 1026 } 1027 1028 int 1029 epcomintr(void* arg) 1030 { 1031 struct epcom_softc *sc = arg; 1032 bus_space_tag_t iot = sc->sc_iot; 1033 bus_space_handle_t ioh = sc->sc_ioh; 1034 u_char *put, *end; 1035 u_int cc; 1036 u_int flagr; 1037 uint32_t c, csts; 1038 1039 (void) bus_space_read_4(iot, ioh, EPCOM_IntIDIntClr); 1040 1041 if (COM_ISALIVE(sc) == 0) 1042 panic("intr on disabled epcom"); 1043 1044 flagr = bus_space_read_4(iot, ioh, EPCOM_Flag); 1045 1046 end = sc->sc_ebuf; 1047 put = sc->sc_rbput; 1048 cc = sc->sc_rbavail; 1049 1050 if (!(ISSET(flagr, Flag_RXFE))) { 1051 if (!ISSET(sc->sc_rx_flags, RX_IBUF_OVERFLOWED)) { 1052 while (cc > 0) { 1053 if (ISSET(flagr, Flag_RXFE)) 1054 break; 1055 c = bus_space_read_4(iot, ioh, EPCOM_Data); 1056 csts = bus_space_read_4(iot, ioh, EPCOM_RXSts); 1057 if (ISSET(csts, RXSts_BE)) { 1058 int cn_trapped = 0; 1059 1060 cn_check_magic(sc->sc_tty->t_dev, 1061 CNC_BREAK, epcom_cnm_state); 1062 if (cn_trapped) 1063 goto next; 1064 #if defined(KGDB) && !defined(DDB) 1065 if (ISSET(sc->sc_hwflags, COM_HW_KGDB)){ 1066 kgdb_connect(1); 1067 goto next; 1068 } 1069 #endif 1070 } else { 1071 int cn_trapped = 0; 1072 1073 cn_check_magic(sc->sc_tty->t_dev, 1074 (c & 0xff), epcom_cnm_state); 1075 if (cn_trapped) 1076 goto next; 1077 } 1078 1079 1080 put[0] = c & 0xff; 1081 put[1] = csts & 0xf; 1082 put += 2; 1083 if (put >= end) 1084 put = sc->sc_rbuf; 1085 cc--; 1086 next: 1087 flagr = bus_space_read_4(iot, ioh, EPCOM_Flag); 1088 } 1089 1090 /* 1091 * Current string of incoming characters ended because 1092 * no more data was available or we ran out of space. 1093 * Schedule a receive event if any data was received. 1094 * If we're out of space, turn off receive interrupts. 1095 */ 1096 sc->sc_rbput = put; 1097 sc->sc_rbavail = cc; 1098 if (!ISSET(sc->sc_rx_flags, RX_TTY_OVERFLOWED)) 1099 sc->sc_rx_ready = 1; 1100 1101 /* 1102 * See if we are in danger of overflowing a buffer. If 1103 * so, use hardware flow control to ease the pressure. 1104 */ 1105 1106 /* but epcom cannot. X-( */ 1107 1108 /* 1109 * If we're out of space, disable receive interrupts 1110 * until the queue has drained a bit. 1111 */ 1112 if (!cc) { 1113 SET(sc->sc_rx_flags, RX_IBUF_OVERFLOWED); 1114 CLR(sc->sc_ctrl, (Ctrl_RIE|Ctrl_RTIE)); 1115 epcom_set(sc); 1116 } 1117 } else { 1118 #ifdef DIAGNOSTIC 1119 panic("epcomintr: we shouldn't reach here"); 1120 #endif 1121 CLR(sc->sc_ctrl, (Ctrl_RIE|Ctrl_RTIE)); 1122 epcom_set(sc); 1123 } 1124 } 1125 1126 /* 1127 * Done handling any receive interrupts. See if data can be 1128 * transmitted as well. Schedule tx done event if no data left 1129 * and tty was marked busy. 1130 */ 1131 1132 if (!ISSET(flagr, Flag_TXFF) && sc->sc_tbc > 0) { 1133 /* Output the next chunk of the contiguous buffer, if any. */ 1134 epcom_filltx(sc); 1135 } else { 1136 /* Disable transmit completion interrupts if necessary. */ 1137 if (ISSET(sc->sc_ctrl, Ctrl_TIE)) { 1138 CLR(sc->sc_ctrl, Ctrl_TIE); 1139 epcom_set(sc); 1140 } 1141 if (sc->sc_tx_busy) { 1142 sc->sc_tx_busy = 0; 1143 sc->sc_tx_done = 1; 1144 } 1145 } 1146 1147 /* Wake up the poller. */ 1148 softint_schedule(sc->sc_si); 1149 1150 #if 0 /* XXX: broken */ 1151 #ifdef RND_COM 1152 rnd_add_uint32(&sc->rnd_source, intr ^ flagr); 1153 #endif 1154 #endif 1155 return (1); 1156 } 1157 1158 #ifdef KGDB 1159 int 1160 epcom_kgdb_attach(bus_space_tag_t iot, bus_addr_t iobase, int rate, 1161 tcflag_t cflag) 1162 { 1163 bus_space_handle_t ioh; 1164 1165 if (iot == epcomcn_sc.sc_iot && iobase == epcomcn_sc.sc_hwbase) { 1166 #if !defined(DDB) 1167 return EBUSY; /* cannot share with console */ 1168 #else 1169 /* 1170 * XXX I have no intention of ever testing and code path 1171 * implied by getting here 1172 */ 1173 kgdb_sc = epcomcn_sc; 1174 #endif 1175 } else { 1176 bus_space_map(iot, iobase, EP93XX_APB_UART_SIZE, 0, &ioh); 1177 epcominit(&kgdb_sc, iot, iobase, ioh, rate, cflag); 1178 } 1179 1180 kgdb_attach(epcom_kgdb_getc, epcom_kgdb_putc, &kgdb_sc); 1181 kgdb_dev = 123; /* unneeded, only to satisfy some tests */ 1182 1183 return 0; 1184 } 1185 1186 static int 1187 epcom_kgdb_getc (void *sc) 1188 { 1189 return epcom_common_getc(sc, NODEV); 1190 } 1191 1192 static void 1193 epcom_kgdb_putc (void *sc, int c) 1194 { 1195 epcom_common_putc(sc, c); 1196 } 1197 #endif /* KGDB */ 1198 1199 /* 1200 * Common code used for initialisation of the console or KGDB connection 1201 */ 1202 static void 1203 epcominit(struct epcom_cons_softc *sc, bus_space_tag_t iot, 1204 bus_addr_t iobase, bus_space_handle_t ioh, int rate, tcflag_t cflag) 1205 { 1206 u_int lcrlo, lcrmid, lcrhi, ctrl, pwrcnt; 1207 bus_space_handle_t syscon_ioh; 1208 1209 sc->sc_iot = iot; 1210 sc->sc_ioh = ioh; 1211 sc->sc_hwbase = iobase; 1212 sc->sc_ospeed = rate; 1213 sc->sc_cflag = cflag; 1214 1215 lcrhi = cflag2lcrhi(cflag); 1216 lcrlo = EPCOMSPEED2BRD(rate) & 0xff; 1217 lcrmid = EPCOMSPEED2BRD(rate) >> 8; 1218 ctrl = Ctrl_UARTE; 1219 1220 /* Make sure the UARTs are clocked at the system default rate */ 1221 bus_space_map(iot, EP93XX_APB_HWBASE + EP93XX_APB_SYSCON, 1222 EP93XX_APB_SYSCON_SIZE, 0, &syscon_ioh); 1223 pwrcnt = bus_space_read_4(iot, syscon_ioh, EP93XX_SYSCON_PwrCnt); 1224 pwrcnt &= ~(PwrCnt_UARTBAUD); 1225 bus_space_write_4(iot, syscon_ioh, EP93XX_SYSCON_PwrCnt, pwrcnt); 1226 bus_space_unmap(iot, syscon_ioh, EP93XX_APB_SYSCON_SIZE); 1227 1228 bus_space_write_4(iot, ioh, EPCOM_LinCtrlLow, lcrlo); 1229 bus_space_write_4(iot, ioh, EPCOM_LinCtrlMid, lcrmid); 1230 bus_space_write_4(iot, ioh, EPCOM_LinCtrlHigh, lcrhi); 1231 bus_space_write_4(iot, ioh, EPCOM_Ctrl, ctrl); 1232 } 1233