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