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