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