1 /* $Id: at91dbgu.c,v 1.18 2020/11/20 18:03:52 thorpej Exp $ */ 2 /* $NetBSD: at91dbgu.c,v 1.18 2020/11/20 18:03:52 thorpej Exp $ */ 3 4 /* 5 * 6 * Copyright (c) 1998, 1999, 2001, 2002, 2004 The NetBSD Foundation, Inc. 7 * All rights reserved. 8 * 9 * This code is derived from software contributed to The NetBSD Foundation 10 * by Jesse Off 11 * 12 * This code is derived from software contributed to The NetBSD Foundation 13 * by Ichiro FUKUHARA and Naoto Shimazaki. 14 * 15 * This code is derived from software contributed to The NetBSD Foundation 16 * by IWAMOTO Toshihiro. 17 * 18 * This code is derived from software contributed to The NetBSD Foundation 19 * by Charles M. Hannum. 20 * 21 * Redistribution and use in source and binary forms, with or without 22 * modification, are permitted provided that the following conditions 23 * are met: 24 * 1. Redistributions of source code must retain the above copyright 25 * notice, this list of conditions and the following disclaimer. 26 * 2. Redistributions in binary form must reproduce the above copyright 27 * notice, this list of conditions and the following disclaimer in the 28 * documentation and/or other materials provided with the distribution. 29 * 30 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 31 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 32 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 33 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 34 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 35 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 36 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 37 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 38 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 39 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 40 * POSSIBILITY OF SUCH DAMAGE. 41 */ 42 43 /* 44 * Copyright (c) 1991 The Regents of the University of California. 45 * All rights reserved. 46 * 47 * Redistribution and use in source and binary forms, with or without 48 * modification, are permitted provided that the following conditions 49 * are met: 50 * 1. Redistributions of source code must retain the above copyright 51 * notice, this list of conditions and the following disclaimer. 52 * 2. Redistributions in binary form must reproduce the above copyright 53 * notice, this list of conditions and the following disclaimer in the 54 * documentation and/or other materials provided with the distribution. 55 * 3. Neither the name of the University nor the names of its contributors 56 * may be used to endorse or promote products derived from this software 57 * without specific prior written permission. 58 * 59 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 60 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 61 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 62 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 63 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 64 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 65 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 66 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 67 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 68 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 69 * SUCH DAMAGE. 70 * 71 * @(#)com.c 7.5 (Berkeley) 5/16/91 72 */ 73 74 /* 75 * TODO: hardware flow control 76 */ 77 78 #include <sys/cdefs.h> 79 __KERNEL_RCSID(0, "$NetBSD: at91dbgu.c,v 1.18 2020/11/20 18:03:52 thorpej Exp $"); 80 81 #include "opt_ddb.h" 82 #include "opt_kgdb.h" 83 84 #include "rnd.h" 85 #ifdef RND_COM 86 #include <sys/rndsource.h> 87 #endif 88 89 /* 90 * Override cnmagic(9) macro before including <sys/systm.h>. 91 * We need to know if cn_check_magic triggered debugger, so set a flag. 92 * Callers of cn_check_magic must declare int cn_trapped = 0; 93 * XXX: this is *ugly*! 94 */ 95 #define cn_trap() \ 96 do { \ 97 console_debugger(); \ 98 cn_trapped = 1; \ 99 } while (/* CONSTCOND */ 0) 100 101 102 #include <sys/param.h> 103 #include <sys/systm.h> 104 #include <sys/types.h> 105 #include <sys/conf.h> 106 #include <sys/file.h> 107 #include <sys/device.h> 108 #include <sys/kernel.h> 109 #include <sys/kmem.h> 110 #include <sys/tty.h> 111 #include <sys/uio.h> 112 #include <sys/vnode.h> 113 #include <sys/kauth.h> 114 115 #include <machine/intr.h> 116 #include <sys/bus.h> 117 118 #include <arm/at91/at91reg.h> 119 #include <arm/at91/at91var.h> 120 #include <arm/at91/at91dbguvar.h> 121 #include <arm/at91/at91dbgureg.h> 122 123 #include <dev/cons.h> 124 125 static int at91dbgu_match(device_t, cfdata_t, void *); 126 static void at91dbgu_attach(device_t, device_t, void *); 127 128 static int at91dbgu_param(struct tty *, struct termios *); 129 static void at91dbgu_start(struct tty *); 130 static int at91dbgu_hwiflow(struct tty *, int); 131 132 #if 0 133 static u_int cflag2lcrhi(tcflag_t); 134 #endif 135 static void at91dbgu_iflush(struct at91dbgu_softc *); 136 static void at91dbgu_set(struct at91dbgu_softc *); 137 138 int at91dbgu_cn_getc(dev_t); 139 void at91dbgu_cn_putc(dev_t, int); 140 void at91dbgu_cn_pollc(dev_t, int); 141 142 static void at91dbgu_soft(void* arg); 143 inline static void at91dbgu_txsoft(struct at91dbgu_softc *, struct tty *); 144 inline static void at91dbgu_rxsoft(struct at91dbgu_softc *, struct tty *); 145 146 void at91dbgu_cn_probe(struct consdev *); 147 void at91dbgu_cn_init(struct consdev *); 148 149 static struct at91dbgu_cons_softc { 150 bus_space_tag_t sc_iot; 151 bus_space_handle_t sc_ioh; 152 bus_addr_t sc_hwbase; 153 int sc_ospeed; 154 tcflag_t sc_cflag; 155 int sc_attached; 156 157 uint8_t *sc_rx_ptr; 158 uint8_t sc_rx_fifo[64]; 159 } dbgu_cn_sc; 160 161 static struct cnm_state at91dbgu_cnm_state; 162 163 CFATTACH_DECL_NEW(at91dbgu, sizeof(struct at91dbgu_softc), 164 at91dbgu_match, at91dbgu_attach, NULL, NULL); 165 166 extern struct cfdriver at91dbgu_cd; 167 168 dev_type_open(at91dbgu_open); 169 dev_type_close(at91dbgu_close); 170 dev_type_read(at91dbgu_read); 171 dev_type_write(at91dbgu_write); 172 dev_type_ioctl(at91dbgu_ioctl); 173 dev_type_stop(at91dbgu_stop); 174 dev_type_tty(at91dbgu_tty); 175 dev_type_poll(at91dbgu_poll); 176 177 const struct cdevsw at91dbgu_cdevsw = { 178 .d_open = at91dbgu_open, 179 .d_close = at91dbgu_close, 180 .d_read = at91dbgu_read, 181 .d_write = at91dbgu_write, 182 .d_ioctl = at91dbgu_ioctl, 183 .d_stop = at91dbgu_stop, 184 .d_tty = at91dbgu_tty, 185 .d_poll = at91dbgu_poll, 186 .d_mmap = nommap, 187 .d_kqfilter = ttykqfilter, 188 .d_discard = nodiscard, 189 .d_flag = D_TTY 190 }; 191 192 struct consdev at91dbgu_cons = { 193 at91dbgu_cn_probe, NULL, at91dbgu_cn_getc, at91dbgu_cn_putc, at91dbgu_cn_pollc, NULL, 194 NULL, NULL, NODEV, CN_REMOTE 195 }; 196 197 #ifndef DEFAULT_COMSPEED 198 #define DEFAULT_COMSPEED 115200 199 #endif 200 201 #define COMUNIT(x) TTUNIT(x) 202 #define COMDIALOUT(x) TTDIALOUT(x) 203 204 #define COM_ISALIVE(sc) ((sc)->enabled != 0 && device_is_active((sc)->sc_dev)) 205 206 static int 207 at91dbgu_match(device_t parent, cfdata_t match, void *aux) 208 { 209 if (strcmp(match->cf_name, "at91dbgu") == 0) 210 return 2; 211 return 0; 212 } 213 214 static int 215 dbgu_intr(void* arg); 216 217 static void 218 at91dbgu_attach(device_t parent, device_t self, void *aux) 219 { 220 struct at91dbgu_softc *sc = device_private(self); 221 struct at91bus_attach_args *sa = aux; 222 struct tty *tp; 223 224 printf("\n"); 225 226 sc->sc_dev = self; 227 bus_space_map(sa->sa_iot, sa->sa_addr, sa->sa_size, 0, &sc->sc_ioh); 228 sc->sc_iot = sa->sa_iot; 229 sc->sc_hwbase = sa->sa_addr; 230 231 DBGUREG(DBGU_IDR) = -1; 232 at91_intr_establish(sa->sa_pid, IPL_SERIAL, INTR_HIGH_LEVEL, dbgu_intr, sc); 233 DBGU_INIT(AT91_MSTCLK, 115200U); 234 235 if (sc->sc_iot == dbgu_cn_sc.sc_iot 236 && sc->sc_hwbase == dbgu_cn_sc.sc_hwbase) { 237 dbgu_cn_sc.sc_attached = 1; 238 /* Make sure the console is always "hardwired". */ 239 delay(10000); /* wait for output to finish */ 240 SET(sc->sc_hwflags, COM_HW_CONSOLE); 241 SET(sc->sc_swflags, TIOCFLAG_SOFTCAR); 242 SET(sc->sc_ier, DBGU_INT_RXRDY); 243 DBGUREG(DBGU_IER) = DBGU_INT_RXRDY; // @@@@@ 244 } 245 246 tp = tty_alloc(); 247 tp->t_oproc = at91dbgu_start; 248 tp->t_param = at91dbgu_param; 249 tp->t_hwiflow = at91dbgu_hwiflow; 250 251 sc->sc_tty = tp; 252 sc->sc_rbuf = kmem_alloc(AT91DBGU_RING_SIZE << 1, KM_SLEEP); 253 sc->sc_rbput = sc->sc_rbget = sc->sc_rbuf; 254 sc->sc_rbavail = AT91DBGU_RING_SIZE; 255 sc->sc_ebuf = sc->sc_rbuf + (AT91DBGU_RING_SIZE << 1); 256 sc->sc_tbc = 0; 257 258 tty_attach(tp); 259 260 if (ISSET(sc->sc_hwflags, COM_HW_CONSOLE)) { 261 int maj; 262 263 /* locate the major number */ 264 maj = cdevsw_lookup_major(&at91dbgu_cdevsw); 265 266 cn_tab->cn_dev = makedev(maj, device_unit(sc->sc_dev)); 267 268 aprint_normal("%s: console (maj %u min %u cn_dev %#"PRIx64")\n", 269 device_xname(sc->sc_dev), maj, device_unit(sc->sc_dev), 270 cn_tab->cn_dev); 271 } 272 273 sc->sc_si = softint_establish(SOFTINT_SERIAL, at91dbgu_soft, sc); 274 275 #ifdef RND_COM 276 rnd_attach_source(&sc->rnd_source, device_xname(sc->sc_dev), 277 RND_TYPE_TTY, RND_FLAG_DEFAULT); 278 #endif 279 280 /* if there are no enable/disable functions, assume the device 281 is always enabled */ 282 if (!sc->enable) 283 sc->enabled = 1; 284 285 /* XXX configure register */ 286 /* xxx_config(sc) */ 287 288 SET(sc->sc_hwflags, COM_HW_DEV_OK); 289 } 290 291 static int 292 at91dbgu_param(struct tty *tp, struct termios *t) 293 { 294 struct at91dbgu_softc *sc 295 = device_lookup_private(&at91dbgu_cd, COMUNIT(tp->t_dev)); 296 int s; 297 298 if (COM_ISALIVE(sc) == 0) 299 return (EIO); 300 301 if (t->c_ispeed && t->c_ispeed != t->c_ospeed) 302 return (EINVAL); 303 304 /* 305 * For the console, always force CLOCAL and !HUPCL, so that the port 306 * is always active. 307 */ 308 if (ISSET(sc->sc_swflags, TIOCFLAG_SOFTCAR) || 309 ISSET(sc->sc_hwflags, COM_HW_CONSOLE)) { 310 SET(t->c_cflag, CLOCAL); 311 CLR(t->c_cflag, HUPCL); 312 } 313 314 /* 315 * If there were no changes, don't do anything. This avoids dropping 316 * input and improves performance when all we did was frob things like 317 * VMIN and VTIME. 318 */ 319 if (tp->t_ospeed == t->c_ospeed && 320 tp->t_cflag == t->c_cflag) 321 return (0); 322 323 s = splserial(); 324 325 sc->sc_brgr = (AT91_MSTCLK / 16 + t->c_ospeed / 2) / t->c_ospeed; 326 327 /* And copy to tty. */ 328 tp->t_ispeed = 0; 329 tp->t_ospeed = t->c_ospeed; 330 tp->t_cflag = t->c_cflag; 331 at91dbgu_set(sc); 332 333 splx(s); 334 335 /* 336 * Update the tty layer's idea of the carrier bit. 337 * We tell tty the carrier is always on. 338 */ 339 (void) (*tp->t_linesw->l_modem)(tp, 1); 340 341 #ifdef COM_DEBUG 342 if (com_debug) 343 comstatus(sc, "comparam "); 344 #endif 345 346 if (!ISSET(t->c_cflag, CHWFLOW)) { 347 if (sc->sc_tx_stopped) { 348 sc->sc_tx_stopped = 0; 349 at91dbgu_start(tp); 350 } 351 } 352 353 return (0); 354 } 355 356 static int 357 at91dbgu_hwiflow(struct tty *tp, int block) 358 { 359 return (0); 360 } 361 362 static void 363 at91dbgu_filltx(struct at91dbgu_softc *sc) 364 { 365 #if 0 366 bus_space_tag_t iot = sc->sc_iot; 367 bus_space_handle_t ioh = sc->sc_ioh; 368 #endif 369 int n; 370 371 n = 0; 372 while (DBGUREG(DBGU_SR) & DBGU_SR_TXRDY) { 373 if (n >= sc->sc_tbc) 374 break; 375 DBGUREG(DBGU_THR) = *(sc->sc_tba + n) & 0xff; 376 n++; 377 } 378 sc->sc_tbc -= n; 379 sc->sc_tba += n; 380 } 381 382 static void 383 at91dbgu_start(struct tty *tp) 384 { 385 struct at91dbgu_softc *sc 386 = device_lookup_private(&at91dbgu_cd, COMUNIT(tp->t_dev)); 387 int s; 388 389 if (COM_ISALIVE(sc) == 0) 390 return; 391 392 s = spltty(); 393 if (ISSET(tp->t_state, TS_BUSY | TS_TIMEOUT | TS_TTSTOP)) 394 goto out; 395 if (sc->sc_tx_stopped) 396 goto out; 397 if (!ttypull(tp)) 398 goto out; 399 400 /* Grab the first contiguous region of buffer space. */ 401 { 402 u_char *tba; 403 int tbc; 404 405 tba = tp->t_outq.c_cf; 406 tbc = ndqb(&tp->t_outq, 0); 407 408 (void)splserial(); 409 410 sc->sc_tba = tba; 411 sc->sc_tbc = tbc; 412 } 413 414 SET(tp->t_state, TS_BUSY); 415 sc->sc_tx_busy = 1; 416 417 /* Output the first chunk of the contiguous buffer. */ 418 at91dbgu_filltx(sc); 419 420 SET(sc->sc_ier, DBGU_INT_TXRDY); 421 DBGUREG(DBGU_IER) = DBGU_INT_TXRDY; 422 423 out: 424 splx(s); 425 return; 426 } 427 428 static void 429 at91dbgu_break(struct at91dbgu_softc *sc, int onoff) 430 { 431 // @@@ we must disconnect the TX pin from the DBGU and control 432 // @@@ the pin directly to support this... 433 } 434 435 static void 436 at91dbgu_shutdown(struct at91dbgu_softc *sc) 437 { 438 int s; 439 440 s = splserial(); 441 442 /* Turn off interrupts. */ 443 DBGUREG(DBGU_IDR) = -1; 444 445 /* Clear any break condition set with TIOCSBRK. */ 446 at91dbgu_break(sc, 0); 447 at91dbgu_set(sc); 448 449 if (sc->disable) { 450 #ifdef DIAGNOSTIC 451 if (!sc->enabled) 452 panic("at91dbgu_shutdown: not enabled?"); 453 #endif 454 (*sc->disable)(sc); 455 sc->enabled = 0; 456 } 457 splx(s); 458 } 459 460 int 461 at91dbgu_open(dev_t dev, int flag, int mode, struct lwp *l) 462 { 463 struct at91dbgu_softc *sc; 464 struct tty *tp; 465 int s, s2; 466 int error; 467 468 sc = device_lookup_private(&at91dbgu_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 sc->sc_ier |= DBGU_INT_RXRDY; 518 DBGUREG(DBGU_IER) = DBGU_INT_RXRDY; 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 = dbgu_cn_sc.sc_ospeed; 538 t.c_cflag = dbgu_cn_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 at91dbgu_param() will do something. */ 550 tp->t_ospeed = 0; 551 (void) at91dbgu_param(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 = AT91DBGU_RING_SIZE; 563 at91dbgu_iflush(sc); 564 CLR(sc->sc_rx_flags, RX_ANY_BLOCK); 565 566 #ifdef COM_DEBUG 567 if (at91dbgu_debug) 568 comstatus(sc, "at91dbgu_open "); 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 at91dbgu_shutdown(sc); 593 } 594 595 return (error); 596 } 597 598 int 599 at91dbgu_close(dev_t dev, int flag, int mode, struct lwp *l) 600 { 601 struct at91dbgu_softc *sc = device_lookup_private(&at91dbgu_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 at91dbgu_shutdown(sc); 621 } 622 623 return (0); 624 } 625 626 int 627 at91dbgu_read(dev_t dev, struct uio *uio, int flag) 628 { 629 struct at91dbgu_softc *sc = device_lookup_private(&at91dbgu_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 at91dbgu_write(dev_t dev, struct uio *uio, int flag) 640 { 641 struct at91dbgu_softc *sc = device_lookup_private(&at91dbgu_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 at91dbgu_poll(dev_t dev, int events, struct lwp *l) 652 { 653 struct at91dbgu_softc *sc = device_lookup_private(&at91dbgu_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 at91dbgu_tty(dev_t dev) 664 { 665 struct at91dbgu_softc *sc = device_lookup_private(&at91dbgu_cd, COMUNIT(dev)); 666 struct tty *tp = sc->sc_tty; 667 668 return (tp); 669 } 670 671 int 672 at91dbgu_ioctl(dev_t dev, u_long cmd, void *data, int flag, struct lwp *l) 673 { 674 struct at91dbgu_softc *sc = device_lookup_private(&at91dbgu_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 at91dbgu_break(sc, 1); 697 break; 698 699 case TIOCCBRK: 700 at91dbgu_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 at91dbgu_stop(struct tty *tp, int flag) 730 { 731 struct at91dbgu_softc *sc 732 = device_lookup_private(&at91dbgu_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 #if 0 746 static u_int 747 cflag2lcrhi(tcflag_t cflag) 748 { 749 uint32_t mr; 750 751 switch (cflag & CSIZE) { 752 default: 753 mr = 0x0; 754 break; 755 } 756 #if 0 757 mr |= (cflag & PARENB) ? LinCtrlHigh_PEN : 0; 758 mr |= (cflag & PARODD) ? 0 : LinCtrlHigh_EPS; 759 mr |= (cflag & CSTOPB) ? LinCtrlHigh_STP2 : 0; 760 mr |= LinCtrlHigh_FEN; /* FIFO always enabled */ 761 #endif 762 mr |= DBGU_MR_PAR_NONE; 763 return (mr); 764 } 765 #endif 766 767 static void 768 at91dbgu_iflush(struct at91dbgu_softc *sc) 769 { 770 #if 0 771 bus_space_tag_t iot = sc->sc_iot; 772 bus_space_handle_t ioh = sc->sc_ioh; 773 #endif 774 #ifdef DIAGNOSTIC 775 int reg; 776 #endif 777 int timo; 778 779 #ifdef DIAGNOSTIC 780 reg = 0xffff; 781 #endif 782 timo = 50000; 783 /* flush any pending I/O */ 784 while (DBGUREG(DBGU_SR) & DBGU_SR_RXRDY 785 && --timo) 786 #ifdef DIAGNOSTIC 787 reg = 788 #else 789 (void) 790 #endif 791 DBGUREG(DBGU_RHR); 792 #ifdef DIAGNOSTIC 793 if (!timo) 794 printf("%s: com_iflush timeout %02x\n", device_xname(sc->sc_dev), 795 reg); 796 #endif 797 } 798 799 static void 800 at91dbgu_set(struct at91dbgu_softc *sc) 801 { 802 DBGUREG(DBGU_MR) = DBGU_MR_PAR_NONE; 803 DBGUREG(DBGU_BRGR) = sc->sc_brgr; 804 DBGUREG(DBGU_CR) = DBGU_CR_TXEN | DBGU_CR_RXEN; // @@@ just in case 805 } 806 807 void 808 at91dbgu_cn_attach(bus_space_tag_t iot, bus_addr_t iobase, bus_space_handle_t ioh, 809 int ospeed, tcflag_t cflag); 810 void 811 at91dbgu_cn_attach(bus_space_tag_t iot, bus_addr_t iobase, bus_space_handle_t ioh, 812 int ospeed, tcflag_t cflag) 813 { 814 cn_tab = &at91dbgu_cons; 815 cn_init_magic(&at91dbgu_cnm_state); 816 cn_set_magic("\047\001"); 817 818 dbgu_cn_sc.sc_iot = iot; 819 dbgu_cn_sc.sc_ioh = ioh; 820 dbgu_cn_sc.sc_hwbase = iobase; 821 dbgu_cn_sc.sc_ospeed = ospeed; 822 dbgu_cn_sc.sc_cflag = cflag; 823 824 DBGU_INIT(AT91_MSTCLK, ospeed); 825 } 826 827 void at91dbgu_attach_cn(bus_space_tag_t iot, int ospeed, int cflag) 828 { 829 bus_space_handle_t ioh; 830 bus_space_map(iot, AT91DBGU_BASE, AT91DBGU_SIZE, 0, &ioh); 831 at91dbgu_cn_attach(iot, AT91DBGU_BASE, ioh, ospeed, cflag); 832 } 833 834 void 835 at91dbgu_cn_probe(struct consdev *cp) 836 { 837 cp->cn_pri = CN_REMOTE; 838 } 839 840 void 841 at91dbgu_cn_pollc(dev_t dev, int on) 842 { 843 if (on) { 844 // enable polling mode 845 DBGUREG(DBGU_IDR) = DBGU_INT_RXRDY; 846 } else { 847 // disable polling mode 848 DBGUREG(DBGU_IER) = DBGU_INT_RXRDY; 849 } 850 } 851 852 void 853 at91dbgu_cn_putc(dev_t dev, int c) 854 { 855 #if 0 856 bus_space_tag_t iot = dbgu_cn_sc.sc_iot; 857 bus_space_handle_t ioh = dbgu_cn_sc.sc_ioh; 858 #endif 859 DBGU_PUTC(c); 860 861 #ifdef DEBUG 862 if (c == '\r') { 863 int s = splserial(); 864 while((DBGUREG(DBGU_SR) & DBGU_SR_TXEMPTY) == 0) { 865 splx(s); 866 s = splserial(); 867 } 868 splx(s); 869 } 870 #endif 871 872 } 873 874 int 875 at91dbgu_cn_getc(dev_t dev) 876 { 877 int c, sr; 878 int s; 879 #if 0 880 bus_space_tag_t iot = dbgu_cn_sc.sc_iot; 881 bus_space_handle_t ioh = dbgu_cn_sc.sc_ioh; 882 #endif 883 884 s = splserial(); 885 886 while ((c = DBGU_PEEKC()) == -1) { 887 splx(s); 888 s = splserial(); 889 } 890 ; 891 sr = DBGUREG(DBGU_SR); 892 if (ISSET(sr, DBGU_SR_FRAME) && c == 0) { 893 DBGUREG(DBGU_CR) = DBGU_CR_RSTSTA; // reset status bits 894 c = CNC_BREAK; 895 } 896 #ifdef DDB 897 extern int db_active; 898 if (!db_active) 899 #endif 900 { 901 int cn_trapped __unused = 0; 902 903 cn_check_magic(dev, c, at91dbgu_cnm_state); 904 } 905 splx(s); 906 907 c &= 0xff; 908 909 return (c); 910 } 911 912 inline static void 913 at91dbgu_txsoft(struct at91dbgu_softc *sc, struct tty *tp) 914 { 915 CLR(tp->t_state, TS_BUSY); 916 if (ISSET(tp->t_state, TS_FLUSH)) 917 CLR(tp->t_state, TS_FLUSH); 918 else 919 ndflush(&tp->t_outq, (int)(sc->sc_tba - tp->t_outq.c_cf)); 920 (*tp->t_linesw->l_start)(tp); 921 } 922 923 inline static void 924 at91dbgu_rxsoft(struct at91dbgu_softc *sc, struct tty *tp) 925 { 926 int (*rint)(int, struct tty *) = tp->t_linesw->l_rint; 927 u_char *get, *end; 928 u_int cc, scc; 929 u_char sts; 930 int code; 931 int s; 932 933 end = sc->sc_ebuf; 934 get = sc->sc_rbget; 935 scc = cc = AT91DBGU_RING_SIZE - sc->sc_rbavail; 936 #if 0 937 if (cc == AT91DBGU_RING_SIZE) { 938 sc->sc_floods++; 939 if (sc->sc_errors++ == 0) 940 callout_reset(&sc->sc_diag_callout, 60 * hz, 941 comdiag, sc); 942 } 943 #endif 944 while (cc) { 945 code = get[0]; 946 sts = get[1]; 947 if (ISSET(sts, DBGU_SR_PARE | DBGU_SR_FRAME | DBGU_SR_OVRE)) { 948 #if 0 949 if (ISSET(lsr, DR_ROR)) { 950 sc->sc_overflows++; 951 if (sc->sc_errors++ == 0) 952 callout_reset(&sc->sc_diag_callout, 953 60 * hz, comdiag, sc); 954 } 955 #endif 956 if (ISSET(sts, (DBGU_SR_FRAME | DBGU_SR_OVRE))) 957 SET(code, TTY_FE); 958 if (ISSET(sts, DBGU_SR_PARE)) 959 SET(code, TTY_PE); 960 } 961 if ((*rint)(code, tp) == -1) { 962 /* 963 * The line discipline's buffer is out of space. 964 */ 965 if (!ISSET(sc->sc_rx_flags, RX_TTY_BLOCKED)) { 966 /* 967 * We're either not using flow control, or the 968 * line discipline didn't tell us to block for 969 * some reason. Either way, we have no way to 970 * know when there's more space available, so 971 * just drop the rest of the data. 972 */ 973 get += cc << 1; 974 if (get >= end) 975 get -= AT91DBGU_RING_SIZE << 1; 976 cc = 0; 977 } else { 978 /* 979 * Don't schedule any more receive processing 980 * until the line discipline tells us there's 981 * space available (through comhwiflow()). 982 * Leave the rest of the data in the input 983 * buffer. 984 */ 985 SET(sc->sc_rx_flags, RX_TTY_OVERFLOWED); 986 } 987 break; 988 } 989 get += 2; 990 if (get >= end) 991 get = sc->sc_rbuf; 992 cc--; 993 } 994 995 if (cc != scc) { 996 sc->sc_rbget = get; 997 s = splserial(); 998 999 cc = sc->sc_rbavail += scc - cc; 1000 /* Buffers should be ok again, release possible block. */ 1001 if (cc >= 1) { 1002 if (ISSET(sc->sc_rx_flags, RX_IBUF_OVERFLOWED)) { 1003 CLR(sc->sc_rx_flags, RX_IBUF_OVERFLOWED); 1004 DBGUREG(DBGU_IER) = DBGU_INT_RXRDY; 1005 } 1006 if (ISSET(sc->sc_rx_flags, RX_IBUF_BLOCKED)) { 1007 CLR(sc->sc_rx_flags, RX_IBUF_BLOCKED); 1008 #if 0 1009 com_hwiflow(sc); 1010 #endif 1011 } 1012 } 1013 splx(s); 1014 } 1015 } 1016 1017 static void 1018 at91dbgu_soft(void* arg) 1019 { 1020 struct at91dbgu_softc *sc = arg; 1021 1022 if (COM_ISALIVE(sc) == 0) 1023 return; 1024 1025 if (sc->sc_rx_ready) { 1026 sc->sc_rx_ready = 0; 1027 at91dbgu_rxsoft(sc, sc->sc_tty); 1028 } 1029 if (sc->sc_tx_done) { 1030 sc->sc_tx_done = 0; 1031 at91dbgu_txsoft(sc, sc->sc_tty); 1032 } 1033 } 1034 1035 1036 static int 1037 dbgu_intr(void* arg) 1038 { 1039 struct at91dbgu_softc *sc = arg; 1040 #if 0 1041 bus_space_tag_t iot = sc->sc_iot; 1042 bus_space_handle_t ioh = sc->sc_ioh; 1043 #endif 1044 u_char *put, *end; 1045 u_int cc; 1046 uint32_t imr, sr; 1047 int c = 0; 1048 imr = DBGUREG(DBGU_IMR); 1049 #if 0 1050 if (!imr) 1051 return 0; 1052 #endif 1053 sr = DBGUREG(DBGU_SR); 1054 if (!(sr & imr)) { 1055 if (sr & DBGU_SR_RXRDY) { 1056 // printf("sr=0x%08x imr=0x%08x\n", sr, imr); 1057 } 1058 return 0; 1059 } 1060 1061 end = sc->sc_ebuf; 1062 put = sc->sc_rbput; 1063 cc = sc->sc_rbavail; 1064 1065 // ok, we DO have some interrupts to serve! 1066 if (sr & DBGU_SR_RXRDY) { 1067 int cn_trapped = 0; 1068 1069 c = DBGUREG(DBGU_RHR); 1070 if (ISSET(sr, (DBGU_SR_OVRE | DBGU_SR_FRAME | DBGU_SR_PARE))) 1071 DBGUREG(DBGU_CR) = DBGU_CR_RSTSTA; 1072 if (ISSET(sr, DBGU_SR_FRAME) && c == 0) { 1073 c = CNC_BREAK; 1074 } 1075 #ifdef DDB 1076 extern int db_active; 1077 if (!db_active) 1078 #endif 1079 cn_check_magic(cn_tab->cn_dev, c, at91dbgu_cnm_state); 1080 if (!cn_trapped && cc) { 1081 put[0] = c & 0xff; 1082 put[1] = sr & 0xff; 1083 put += 2; 1084 if (put >= end) 1085 put = sc->sc_rbuf; 1086 cc--; 1087 /* 1088 * Current string of incoming characters ended because 1089 * no more data was available or we ran out of space. 1090 * Schedule a receive event if any data was received. 1091 * If we're out of space, turn off receive interrupts. 1092 */ 1093 sc->sc_rbput = put; 1094 sc->sc_rbavail = cc; 1095 if (!ISSET(sc->sc_rx_flags, RX_TTY_OVERFLOWED)) 1096 sc->sc_rx_ready = 1; 1097 1098 /* 1099 * See if we are in danger of overflowing a buffer. If 1100 * so, use hardware flow control to ease the pressure. 1101 */ 1102 1103 /* but at91dbgu cannot (yet). X-( */ 1104 1105 /* 1106 * If we're out of space, disable receive interrupts 1107 * until the queue has drained a bit. 1108 */ 1109 if (!cc) { 1110 SET(sc->sc_rx_flags, RX_IBUF_OVERFLOWED); 1111 } 1112 } 1113 } 1114 1115 /* 1116 * Done handling any receive interrupts. See if data can be 1117 * transmitted as well. Schedule tx done event if no data left 1118 * and tty was marked busy. 1119 */ 1120 1121 if (ISSET(sr, DBGU_SR_TXRDY) && sc->sc_tbc > 0) { 1122 /* Output the next chunk of the contiguous buffer, if any. */ 1123 at91dbgu_filltx(sc); 1124 } else { 1125 /* Disable transmit completion interrupts if necessary. */ 1126 DBGUREG(DBGU_IDR) = DBGU_INT_TXRDY; 1127 if (sc->sc_tx_busy) { 1128 sc->sc_tx_busy = 0; 1129 sc->sc_tx_done = 1; 1130 } 1131 } 1132 1133 /* Wake up the poller. */ 1134 softint_schedule(sc->sc_si); 1135 #if 0 1136 #ifdef RND_COM 1137 rnd_add_uint32(&sc->rnd_source, imr ^ sr ^ c); 1138 #endif 1139 #endif 1140 1141 return (1); 1142 } 1143