1 /* $NetBSD: sbjcn.c,v 1.28 2011/07/10 23:32:03 matt Exp $ */ 2 3 /* 4 * Copyright 2000, 2001 5 * Broadcom Corporation. All rights reserved. 6 * 7 * This software is furnished under license and may be used and copied only 8 * in accordance with the following terms and conditions. Subject to these 9 * conditions, you may download, copy, install, use, modify and distribute 10 * modified or unmodified copies of this software in source and/or binary 11 * form. No title or ownership is transferred hereby. 12 * 13 * 1) Any source code used, modified or distributed must reproduce and 14 * retain this copyright notice and list of conditions as they appear in 15 * the source file. 16 * 17 * 2) No right is granted to use any trade name, trademark, or logo of 18 * Broadcom Corporation. The "Broadcom Corporation" name may not be 19 * used to endorse or promote products derived from this software 20 * without the prior written permission of Broadcom Corporation. 21 * 22 * 3) THIS SOFTWARE IS PROVIDED "AS-IS" AND ANY EXPRESS OR IMPLIED 23 * WARRANTIES, INCLUDING BUT NOT LIMITED TO, ANY IMPLIED WARRANTIES OF 24 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, OR 25 * NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT SHALL BROADCOM BE LIABLE 26 * FOR ANY DAMAGES WHATSOEVER, AND IN PARTICULAR, BROADCOM SHALL NOT BE 27 * LIABLE FOR DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 28 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 29 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR 30 * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 31 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE 32 * OR OTHERWISE), EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 33 */ 34 35 /* from: $NetBSD: com.c,v 1.172 2000/05/03 19:19:04 thorpej Exp */ 36 37 /*- 38 * Copyright (c) 1998, 1999 The NetBSD Foundation, Inc. 39 * All rights reserved. 40 * 41 * This code is derived from software contributed to The NetBSD Foundation 42 * by Charles M. Hannum. 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 * 53 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 54 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 55 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 56 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 57 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 58 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 59 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 60 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 61 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 62 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 63 * POSSIBILITY OF SUCH DAMAGE. 64 */ 65 66 /* 67 * Copyright (c) 1991 The Regents of the University of California. 68 * All rights reserved. 69 * 70 * Redistribution and use in source and binary forms, with or without 71 * modification, are permitted provided that the following conditions 72 * are met: 73 * 1. Redistributions of source code must retain the above copyright 74 * notice, this list of conditions and the following disclaimer. 75 * 2. Redistributions in binary form must reproduce the above copyright 76 * notice, this list of conditions and the following disclaimer in the 77 * documentation and/or other materials provided with the distribution. 78 * 3. Neither the name of the University nor the names of its contributors 79 * may be used to endorse or promote products derived from this software 80 * without specific prior written permission. 81 * 82 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 83 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 84 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 85 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 86 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 87 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 88 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 89 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 90 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 91 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 92 * SUCH DAMAGE. 93 * 94 * @(#)com.c 7.5 (Berkeley) 5/16/91 95 */ 96 97 /* 98 * `sbjcn' driver, supports console over SiByte SB-1250 JTAG. 99 * 100 * Accesses a section of JTAG memory space to mimic a console, 101 * if there's a matching program outside to communicate with. 102 * If nobody is there, things will be very quiet. 103 */ 104 105 #include <sys/cdefs.h> 106 __KERNEL_RCSID(0, "$NetBSD: sbjcn.c,v 1.28 2011/07/10 23:32:03 matt Exp $"); 107 108 #define SBJCN_DEBUG 109 110 #include "opt_ddb.h" 111 #include "ioconf.h" 112 113 #include <sys/param.h> 114 #include <sys/systm.h> 115 #include <sys/ioctl.h> 116 #include <sys/select.h> 117 #include <sys/tty.h> 118 #include <sys/proc.h> 119 #include <sys/conf.h> 120 #include <sys/file.h> 121 #include <sys/uio.h> 122 #include <sys/kernel.h> 123 #include <sys/syslog.h> 124 #include <sys/types.h> 125 #include <sys/device.h> 126 #include <sys/malloc.h> 127 #include <sys/vnode.h> 128 #include <sys/kauth.h> 129 130 #include <sbmips/dev/sbscd/sbscdvar.h> 131 #include <sbmips/dev/sbscd/sbjcnvar.h> 132 133 #include <dev/cons.h> 134 135 #include <mips/locore.h> 136 137 void sbjcn_attach_channel(struct sbjcn_softc *sc, int chan, int intr); 138 static void sbjcncn_grabdword(struct sbjcn_channel *ch); 139 static char sbjcncn_nextbyte(struct sbjcn_channel *ch); 140 static void sbjcn_cngrabdword(void); 141 142 #if defined(DDB) || defined(KGDB) 143 static void sbjcn_enable_debugport(struct sbjcn_channel *ch); 144 #endif 145 void sbjcn_config(struct sbjcn_channel *ch); 146 void sbjcn_shutdown(struct sbjcn_channel *ch); 147 int sbjcn_speed(long, long *); 148 static int cflag2modes(tcflag_t, u_char *, u_char *); 149 int sbjcn_param(struct tty *, struct termios *); 150 void sbjcn_start(struct tty *); 151 int sbjcn_hwiflow(struct tty *, int); 152 153 void sbjcn_loadchannelregs(struct sbjcn_channel *); 154 void sbjcn_dohwiflow(struct sbjcn_channel *); 155 void sbjcn_break(struct sbjcn_channel *, int); 156 void sbjcn_modem(struct sbjcn_channel *, int); 157 void tiocm_to_sbjcn(struct sbjcn_channel *, int, int); 158 int sbjcn_to_tiocm(struct sbjcn_channel *); 159 void sbjcn_iflush(struct sbjcn_channel *); 160 161 int sbjcn_init(u_long addr, int chan, int rate, tcflag_t cflag); 162 int sbjcn_common_getc(u_long addr, int chan); 163 void sbjcn_common_putc(u_long addr, int chan, int c); 164 165 int sbjcn_cngetc(dev_t dev); 166 void sbjcn_cnputc(dev_t dev, int c); 167 void sbjcn_cnpollc(dev_t dev, int on); 168 169 dev_type_open(sbjcnopen); 170 dev_type_close(sbjcnclose); 171 dev_type_read(sbjcnread); 172 dev_type_write(sbjcnwrite); 173 dev_type_ioctl(sbjcnioctl); 174 dev_type_stop(sbjcnstop); 175 dev_type_tty(sbjcntty); 176 177 const struct cdevsw sbjcn_cdevsw = { 178 sbjcnopen, sbjcnclose, sbjcnread, sbjcnwrite, sbjcnioctl, 179 sbjcnstop, sbjcntty, nopoll, nommap, ttykqfilter, D_TTY 180 }; 181 182 #define integrate static inline 183 integrate void sbjcn_rxsoft(struct sbjcn_channel *, struct tty *); 184 integrate void sbjcn_txsoft(struct sbjcn_channel *, struct tty *); 185 integrate void sbjcn_stsoft(struct sbjcn_channel *, struct tty *); 186 integrate void sbjcn_schedrx(struct sbjcn_channel *); 187 integrate void sbjcn_recv(struct sbjcn_channel *ch); 188 void sbjcn_diag(void *); 189 void sbjcn_callout(void *); 190 191 /* 192 * Make this an option variable one can patch. 193 * But be warned: this must be a power of 2! 194 */ 195 u_int sbjcn_rbuf_size = SBJCN_RING_SIZE; 196 197 /* Stop input when 3/4 of the ring is full; restart when only 1/4 is full. */ 198 u_int sbjcn_rbuf_hiwat = (SBJCN_RING_SIZE * 1) / 4; 199 u_int sbjcn_rbuf_lowat = (SBJCN_RING_SIZE * 3) / 4; 200 201 static int sbjcn_cons_present; 202 static int sbjcn_cons_attached; 203 static u_long sbjcn_cons_addr; 204 static int sbjcn_cons_chan; 205 static int sbjcn_cons_rate; 206 static tcflag_t sbjcn_cons_cflag; 207 static int sbjcn_cons_waiting_input; 208 static uint64_t sbjcn_cons_input_buf; 209 210 #ifdef KGDB 211 #include <sys/kgdb.h> 212 213 static int sbjcn_kgdb_present; 214 static int sbjcn_kgdb_attached; 215 static u_long sbjcn_kgdb_addr; 216 static int sbjcn_kgdb_chan; 217 218 int sbjcn_kgdb_getc(void *); 219 void sbjcn_kgdb_putc(void *, int); 220 #endif /* KGDB */ 221 222 static int sbjcn_match(device_t, cfdata_t, void *); 223 static void sbjcn_attach(device_t, device_t, void *); 224 225 CFATTACH_DECL_NEW(sbjcn, sizeof(struct sbjcn_softc), 226 sbjcn_match, sbjcn_attach, NULL, NULL); 227 228 #define READ_REG(rp) (mips3_ld((volatile uint64_t *)(rp))) 229 #define WRITE_REG(rp, val) (mips3_sd((volatile uint64_t *)(rp), (val))) 230 231 #define JTAG_CONS_CONTROL 0x00 232 #define JTAG_CONS_INPUT 0x20 233 #define JTAG_CONS_OUTPUT 0x40 234 #define JTAG_CONS_MAGICNUM 0x50FABEEF12349873 235 236 #define jtag_input_len(data) (((data) >> 56) & 0xFF) 237 238 239 static int 240 sbjcn_match(device_t parent, cfdata_t match, void *aux) 241 { 242 struct sbscd_attach_args *sa = aux; 243 244 if (sa->sa_locs.sa_type != SBSCD_DEVTYPE_JTAGCONS) 245 return (0); 246 247 return 1; 248 } 249 250 static void 251 sbjcn_attach(device_t parent, device_t self, void *aux) 252 { 253 struct sbjcn_softc *sc = device_private(self); 254 struct sbscd_attach_args *sa = aux; 255 256 sc->sc_dev = self; 257 sc->sc_addr = sa->sa_base + sa->sa_locs.sa_offset; 258 259 aprint_normal("\n"); 260 sbjcn_attach_channel(sc, 0, sa->sa_locs.sa_intr[0]); 261 } 262 263 void 264 sbjcn_attach_channel(struct sbjcn_softc *sc, int chan, int intr) 265 { 266 struct sbjcn_channel *ch = &sc->sc_channels[chan]; 267 u_long chan_addr; 268 struct tty *tp; 269 270 ch->ch_sc = sc; 271 ch->ch_num = chan; 272 273 chan_addr = sc->sc_addr + (0x100 * chan); 274 ch->ch_base = (void *)MIPS_PHYS_TO_KSEG1(chan_addr); 275 ch->ch_input_reg = 276 (void *)MIPS_PHYS_TO_KSEG1(sc->sc_addr + JTAG_CONS_INPUT); 277 ch->ch_output_reg = 278 (void *)MIPS_PHYS_TO_KSEG1(sc->sc_addr + JTAG_CONS_OUTPUT); 279 ch->ch_control_reg = 280 (void *)MIPS_PHYS_TO_KSEG1(sc->sc_addr + JTAG_CONS_CONTROL); 281 ch->ch_waiting_input = 0; 282 283 ch->ch_i_dcd = ch->ch_i_dcd_pin = 0 /* XXXCGD */; 284 ch->ch_i_cts = ch->ch_i_cts_pin = 0 /* XXXCGD */; 285 ch->ch_i_dsr = ch->ch_i_dsr_pin = 0 /* XXXCGD */; 286 ch->ch_i_ri = ch->ch_i_ri_pin = 0 /* XXXCGD */; 287 ch->ch_i_mask = 288 ch->ch_i_dcd | ch->ch_i_cts | ch->ch_i_dsr | ch->ch_i_ri; 289 ch->ch_o_dtr = ch->ch_o_dtr_pin = 0 /* XXXCGD */; 290 ch->ch_o_rts = ch->ch_o_rts_pin = 0 /* XXXCGD */; 291 ch->ch_o_mask = ch->ch_o_dtr | ch->ch_o_rts; 292 293 callout_init(&ch->ch_diag_callout, 0); 294 callout_init(&ch->ch_callout, 0); 295 296 /* Disable interrupts before configuring the device. */ 297 ch->ch_imr = 0; 298 299 if (sbjcn_cons_present && 300 sbjcn_cons_addr == chan_addr && sbjcn_cons_chan == chan) { 301 sbjcn_cons_attached = 1; 302 303 /* Make sure the console is always "hardwired". */ 304 delay(1000); /* wait for output to finish */ 305 SET(ch->ch_hwflags, SBJCN_HW_CONSOLE); 306 SET(ch->ch_swflags, TIOCFLAG_SOFTCAR); 307 } 308 309 tp = tty_alloc(); 310 tp->t_oproc = sbjcn_start; 311 tp->t_param = sbjcn_param; 312 tp->t_hwiflow = sbjcn_hwiflow; 313 314 ch->ch_tty = tp; 315 ch->ch_rbuf = malloc(sbjcn_rbuf_size << 1, M_DEVBUF, M_NOWAIT); 316 if (ch->ch_rbuf == NULL) { 317 aprint_error_dev(sc->sc_dev, 318 "channel %d: unable to allocate ring buffer\n", 319 chan); 320 return; 321 } 322 ch->ch_ebuf = ch->ch_rbuf + (sbjcn_rbuf_size << 1); 323 324 tty_attach(tp); 325 326 if (ISSET(ch->ch_hwflags, SBJCN_HW_CONSOLE)) { 327 int maj; 328 329 /* locate the major number */ 330 maj = cdevsw_lookup_major(&sbjcn_cdevsw); 331 332 cn_tab->cn_dev = makedev(maj, 333 (device_unit(sc->sc_dev) << 1) + chan); 334 335 aprint_normal_dev(sc->sc_dev, "channel %d: %s\n", 336 chan, "console"); 337 } 338 339 #ifdef KGDB 340 /* 341 * Allow kgdb to "take over" this port. If this is 342 * the kgdb device, it has exclusive use. 343 */ 344 if (sbjcn_kgdb_present && 345 sbjcn_kgdb_addr == chan_addr && sbjcn_kgdb_chan == chan) { 346 sbjcn_kgdb_attached = 1; 347 348 SET(ch->ch_hwflags, SBJCN_HW_KGDB); 349 aprint_normal_dev(sc->sc_dev, "channel %d: %s\n", 350 chan, "kgdb"); 351 } 352 #endif 353 354 sbjcn_config(ch); 355 356 callout_reset(&ch->ch_callout, hz/10, sbjcn_callout, ch); 357 358 SET(ch->ch_hwflags, SBJCN_HW_DEV_OK); 359 } 360 361 int 362 sbjcn_speed(long speed, long *brcp) 363 { 364 #define divrnd(n, q) (((n)*2/(q)+1)/2) /* divide and round off */ 365 366 int x, err; 367 int frequency = 100000000; 368 369 *brcp = divrnd(frequency / 20, speed) - 1; 370 371 if (speed <= 0) 372 return (-1); 373 x = divrnd(frequency / 20, speed); 374 if (x <= 0) 375 return (-1); 376 err = divrnd(((quad_t)frequency) * 1000 / 20, speed * x) - 1000; 377 if (err < 0) 378 err = -err; 379 if (err > SBJCN_TOLERANCE) 380 return (-1); 381 *brcp = x - 1; 382 return (0); 383 384 #undef divrnd 385 } 386 387 #ifdef SBJCN_DEBUG 388 void sbjcn_status(struct sbjcn_channel *, char *); 389 390 int sbjcn_debug = 1 /* XXXCGD */; 391 392 void 393 sbjcn_status(struct sbjcn_channel *ch, char *str) 394 { 395 struct sbjcn_softc *sc = ch->ch_sc; 396 struct tty *tp = ch->ch_tty; 397 398 aprint_normal_dev(sc->sc_dev, 399 "chan %d: %s %sclocal %sdcd %sts_carr_on %sdtr %stx_stopped\n", 400 ch->ch_num, str, 401 ISSET(tp->t_cflag, CLOCAL) ? "+" : "-", 402 ISSET(ch->ch_iports, ch->ch_i_dcd) ? "+" : "-", 403 ISSET(tp->t_state, TS_CARR_ON) ? "+" : "-", 404 ISSET(ch->ch_oports, ch->ch_o_dtr) ? "+" : "-", 405 ch->ch_tx_stopped ? "+" : "-"); 406 407 aprint_normal_dev(sc->sc_dev, 408 "chan %d: %s %scrtscts %scts %sts_ttstop %srts %xrx_flags\n", 409 ch->ch_num, str, 410 ISSET(tp->t_cflag, CRTSCTS) ? "+" : "-", 411 ISSET(ch->ch_iports, ch->ch_i_cts) ? "+" : "-", 412 ISSET(tp->t_state, TS_TTSTOP) ? "+" : "-", 413 ISSET(ch->ch_oports, ch->ch_o_rts) ? "+" : "-", 414 ch->ch_rx_flags); 415 } 416 #endif 417 418 #if defined(DDB) || defined(KGDB) 419 static void 420 sbjcn_enable_debugport(struct sbjcn_channel *ch) 421 { 422 int s; 423 424 /* Turn on line break interrupt, set carrier. */ 425 s = splserial(); 426 427 ch->ch_imr = 0x04; 428 SET(ch->ch_oports, ch->ch_o_dtr | ch->ch_o_rts); 429 430 splx(s); 431 } 432 #endif 433 434 void 435 sbjcn_config(struct sbjcn_channel *ch) 436 { 437 438 /* Disable interrupts before configuring the device. */ 439 ch->ch_imr = 0x00; 440 441 #ifdef DDB 442 if (ISSET(ch->ch_hwflags, SBJCN_HW_CONSOLE)) 443 sbjcn_enable_debugport(ch); 444 #endif 445 446 #ifdef KGDB 447 /* 448 * Allow kgdb to "take over" this port. If this is 449 * the kgdb device, it has exclusive use. 450 */ 451 if (ISSET(ch->ch_hwflags, SBJCN_HW_KGDB)) 452 sbjcn_enable_debugport(ch); 453 #endif 454 } 455 456 void 457 sbjcn_shutdown(struct sbjcn_channel *ch) 458 { 459 struct tty *tp = ch->ch_tty; 460 int s; 461 462 s = splserial(); 463 464 /* If we were asserting flow control, then deassert it. */ 465 SET(ch->ch_rx_flags, RX_IBUF_BLOCKED); 466 sbjcn_dohwiflow(ch); 467 468 /* Clear any break condition set with TIOCSBRK. */ 469 sbjcn_break(ch, 0); 470 471 /* 472 * Hang up if necessary. Wait a bit, so the other side has time to 473 * notice even if we immediately open the port again. 474 */ 475 if (ISSET(tp->t_cflag, HUPCL)) { 476 sbjcn_modem(ch, 0); 477 (void) tsleep(ch, TTIPRI, ttclos, hz); 478 } 479 480 /* Turn off interrupts. */ 481 #ifdef DDB 482 if (ISSET(ch->ch_hwflags, SBJCN_HW_CONSOLE)) 483 ch->ch_imr = 0x04; /* interrupt on break */ 484 else 485 #endif 486 ch->ch_imr = 0; 487 488 splx(s); 489 } 490 491 int 492 sbjcnopen(dev_t dev, int flag, int mode, struct lwp *l) 493 { 494 int chan = SBJCN_CHAN(dev); 495 struct sbjcn_softc *sc; 496 struct sbjcn_channel *ch; 497 struct tty *tp; 498 int s, s2; 499 int error; 500 501 sc = device_lookup_private(&sbjcn_cd, SBJCN_UNIT(dev)); 502 if (sc == NULL) 503 return (ENXIO); 504 505 ch = &sc->sc_channels[chan]; 506 if (!ISSET(ch->ch_hwflags, SBJCN_HW_DEV_OK) || ch->ch_rbuf == NULL) 507 return (ENXIO); 508 509 #ifdef KGDB 510 /* 511 * If this is the kgdb port, no other use is permitted. 512 */ 513 if (ISSET(ch->ch_hwflags, SBJCN_HW_KGDB)) 514 return (EBUSY); 515 #endif 516 517 tp = ch->ch_tty; 518 519 if (kauth_authorize_device_tty(l->l_cred, KAUTH_DEVICE_TTY_OPEN, tp)) 520 return (EBUSY); 521 522 s = spltty(); 523 524 /* 525 * Do the following iff this is a first open. 526 */ 527 if (!ISSET(tp->t_state, TS_ISOPEN) && tp->t_wopen == 0) { 528 struct termios t; 529 530 tp->t_dev = dev; 531 532 s2 = splserial(); 533 534 /* Turn on receive, break, and status change interrupts. */ 535 ch->ch_imr = 0xe; 536 537 /* Fetch the current modem control status, needed later. */ 538 ch->ch_iports = 0; 539 ch->ch_iports_delta = 0; 540 splx(s2); 541 542 /* 543 * Initialize the termios status to the defaults. Add in the 544 * sticky bits from TIOCSFLAGS. 545 */ 546 t.c_ispeed = 0; 547 if (ISSET(ch->ch_hwflags, SBJCN_HW_CONSOLE)) { 548 t.c_ospeed = sbjcn_cons_rate; 549 t.c_cflag = sbjcn_cons_cflag; 550 } else { 551 t.c_ospeed = TTYDEF_SPEED; 552 t.c_cflag = TTYDEF_CFLAG; 553 } 554 if (ISSET(ch->ch_swflags, TIOCFLAG_CLOCAL)) 555 SET(t.c_cflag, CLOCAL); 556 if (ISSET(ch->ch_swflags, TIOCFLAG_CRTSCTS)) 557 SET(t.c_cflag, CRTSCTS); 558 if (ISSET(ch->ch_swflags, TIOCFLAG_MDMBUF)) 559 SET(t.c_cflag, MDMBUF); 560 /* Make sure sbjcn_param() will do something. */ 561 tp->t_ospeed = 0; 562 (void) sbjcn_param(tp, &t); 563 tp->t_iflag = TTYDEF_IFLAG; 564 tp->t_oflag = TTYDEF_OFLAG; 565 tp->t_lflag = TTYDEF_LFLAG; 566 ttychars(tp); 567 ttsetwater(tp); 568 569 s2 = splserial(); 570 571 /* 572 * Turn on DTR. We must always do this, even if carrier is not 573 * present, because otherwise we'd have to use TIOCSDTR 574 * immediately after setting CLOCAL, which applications do not 575 * expect. We always assert DTR while the device is open 576 * unless explicitly requested to deassert it. 577 */ 578 sbjcn_modem(ch, 1); 579 580 /* Clear the input ring, and unblock. */ 581 ch->ch_rbput = ch->ch_rbget = ch->ch_rbuf; 582 ch->ch_rbavail = sbjcn_rbuf_size; 583 sbjcn_iflush(ch); 584 CLR(ch->ch_rx_flags, RX_ANY_BLOCK); 585 sbjcn_dohwiflow(ch); 586 587 #ifdef SBJCN_DEBUG 588 if (sbjcn_debug) 589 sbjcn_status(ch, "sbjcnopen "); 590 #endif 591 592 splx(s2); 593 } 594 595 splx(s); 596 597 error = ttyopen(tp, SBJCN_DIALOUT(dev), ISSET(flag, O_NONBLOCK)); 598 if (error) 599 goto bad; 600 601 error = (*tp->t_linesw->l_open)(dev, tp); 602 if (error) 603 goto bad; 604 605 return (0); 606 607 bad: 608 if (!ISSET(tp->t_state, TS_ISOPEN) && tp->t_wopen == 0) { 609 /* 610 * We failed to open the device, and nobody else had it opened. 611 * Clean up the state as appropriate. 612 */ 613 sbjcn_shutdown(ch); 614 } 615 616 return (error); 617 } 618 619 int 620 sbjcnclose(dev_t dev, int flag, int mode, struct proc *p) 621 { 622 struct sbjcn_softc *sc = device_lookup_private(&sbjcn_cd, SBJCN_UNIT(dev)); 623 struct sbjcn_channel *ch = &sc->sc_channels[SBJCN_CHAN(dev)]; 624 struct tty *tp = ch->ch_tty; 625 626 /* XXX This is for cons.c. */ 627 if (!ISSET(tp->t_state, TS_ISOPEN)) 628 return (0); 629 630 (*tp->t_linesw->l_close)(tp, flag); 631 ttyclose(tp); 632 633 if (!ISSET(tp->t_state, TS_ISOPEN) && tp->t_wopen == 0) { 634 /* 635 * Although we got a last close, the device may still be in 636 * use; e.g. if this was the dialout node, and there are still 637 * processes waiting for carrier on the non-dialout node. 638 */ 639 sbjcn_shutdown(ch); 640 } 641 642 return (0); 643 } 644 645 int 646 sbjcnread(dev_t dev, struct uio *uio, int flag) 647 { 648 struct sbjcn_softc *sc = device_lookup_private(&sbjcn_cd, SBJCN_UNIT(dev)); 649 struct sbjcn_channel *ch = &sc->sc_channels[SBJCN_CHAN(dev)]; 650 struct tty *tp = ch->ch_tty; 651 652 return ((*tp->t_linesw->l_read)(tp, uio, flag)); 653 } 654 655 int 656 sbjcnwrite(dev_t dev, struct uio *uio, int flag) 657 { 658 struct sbjcn_softc *sc = device_lookup_private(&sbjcn_cd, SBJCN_UNIT(dev)); 659 struct sbjcn_channel *ch = &sc->sc_channels[SBJCN_CHAN(dev)]; 660 struct tty *tp = ch->ch_tty; 661 662 return ((*tp->t_linesw->l_write)(tp, uio, flag)); 663 } 664 665 struct tty * 666 sbjcntty(dev_t dev) 667 { 668 struct sbjcn_softc *sc = device_lookup_private(&sbjcn_cd, SBJCN_UNIT(dev)); 669 struct sbjcn_channel *ch = &sc->sc_channels[SBJCN_CHAN(dev)]; 670 struct tty *tp = ch->ch_tty; 671 672 return (tp); 673 } 674 675 int 676 sbjcnioctl(dev_t dev, u_long cmd, void *data, int flag, struct lwp *l) 677 { 678 struct sbjcn_softc *sc = device_lookup_private(&sbjcn_cd, SBJCN_UNIT(dev)); 679 struct sbjcn_channel *ch = &sc->sc_channels[SBJCN_CHAN(dev)]; 680 struct tty *tp = ch->ch_tty; 681 int error; 682 int s; 683 684 error = (*tp->t_linesw->l_ioctl)(tp, cmd, data, flag, p); 685 if (error >= 0) 686 return (error); 687 688 error = ttioctl(tp, cmd, data, flag, p); 689 if (error >= 0) 690 return (error); 691 692 error = 0; 693 694 s = splserial(); 695 696 switch (cmd) { 697 case TIOCSBRK: 698 sbjcn_break(ch, 1); 699 break; 700 701 case TIOCCBRK: 702 sbjcn_break(ch, 0); 703 break; 704 705 case TIOCSDTR: 706 sbjcn_modem(ch, 1); 707 break; 708 709 case TIOCCDTR: 710 sbjcn_modem(ch, 0); 711 break; 712 713 case TIOCGFLAGS: 714 *(int *)data = ch->ch_swflags; 715 break; 716 717 case TIOCSFLAGS: 718 error = kauth_authorize_device_tty(l->l_cred, 719 KAUTH_DEVICE_TTY_PRIVSET, tp); 720 if (error) 721 break; 722 ch->ch_swflags = *(int *)data; 723 break; 724 725 case TIOCMSET: 726 case TIOCMBIS: 727 case TIOCMBIC: 728 tiocm_to_sbjcn(ch, cmd, *(int *)data); 729 break; 730 731 case TIOCMGET: 732 *(int *)data = sbjcn_to_tiocm(ch); 733 break; 734 735 default: 736 error = ENOTTY; 737 break; 738 } 739 740 splx(s); 741 742 #ifdef SBJCN_DEBUG 743 if (sbjcn_debug) 744 sbjcn_status(ch, "sbjcn_ioctl "); 745 #endif 746 747 return (error); 748 } 749 750 integrate void 751 sbjcn_schedrx(struct sbjcn_channel *ch) 752 { 753 754 ch->ch_rx_ready = 1; 755 756 /* Next callout will detect this flag. */ 757 } 758 759 void 760 sbjcn_break(struct sbjcn_channel *ch, int onoff) 761 { 762 /* XXXKW do something? */ 763 } 764 765 void 766 sbjcn_modem(struct sbjcn_channel *ch, int onoff) 767 { 768 769 if (ch->ch_o_dtr == 0) 770 return; 771 772 if (onoff) 773 SET(ch->ch_oports, ch->ch_o_dtr); 774 else 775 CLR(ch->ch_oports, ch->ch_o_dtr); 776 777 if (!ch->ch_heldchange) { 778 if (ch->ch_tx_busy) { 779 ch->ch_heldtbc = ch->ch_tbc; 780 ch->ch_tbc = 0; 781 ch->ch_heldchange = 1; 782 } else 783 sbjcn_loadchannelregs(ch); 784 } 785 } 786 787 void 788 tiocm_to_sbjcn(struct sbjcn_channel *ch, int how, int ttybits) 789 { 790 u_char bits; 791 792 bits = 0; 793 if (ISSET(ttybits, TIOCM_DTR)) 794 SET(bits, ch->ch_o_dtr); 795 if (ISSET(ttybits, TIOCM_RTS)) 796 SET(bits, ch->ch_o_rts); 797 798 switch (how) { 799 case TIOCMBIC: 800 CLR(ch->ch_oports, bits); 801 break; 802 803 case TIOCMBIS: 804 SET(ch->ch_oports, bits); 805 break; 806 807 case TIOCMSET: 808 ch->ch_oports = bits; 809 break; 810 } 811 812 if (!ch->ch_heldchange) { 813 if (ch->ch_tx_busy) { 814 ch->ch_heldtbc = ch->ch_tbc; 815 ch->ch_tbc = 0; 816 ch->ch_heldchange = 1; 817 } else 818 sbjcn_loadchannelregs(ch); 819 } 820 } 821 822 int 823 sbjcn_to_tiocm(struct sbjcn_channel *ch) 824 { 825 u_char hwbits; 826 int ttybits = 0; 827 828 hwbits = ch->ch_oports; 829 if (ISSET(hwbits, ch->ch_o_dtr)) 830 SET(ttybits, TIOCM_DTR); 831 if (ISSET(hwbits, ch->ch_o_rts)) 832 SET(ttybits, TIOCM_RTS); 833 834 hwbits = ch->ch_iports; 835 if (ISSET(hwbits, ch->ch_i_dcd)) 836 SET(ttybits, TIOCM_CD); 837 if (ISSET(hwbits, ch->ch_i_cts)) 838 SET(ttybits, TIOCM_CTS); 839 if (ISSET(hwbits, ch->ch_i_dsr)) 840 SET(ttybits, TIOCM_DSR); 841 if (ISSET(hwbits, ch->ch_i_ri)) 842 SET(ttybits, TIOCM_RI); 843 844 if (ch->ch_imr != 0) 845 SET(ttybits, TIOCM_LE); 846 847 return (ttybits); 848 } 849 850 static int 851 cflag2modes(tcflag_t cflag, u_char *mode1p, u_char *mode2p) 852 { 853 u_char mode1; 854 u_char mode2; 855 int err = 0; 856 857 mode1 = mode2 = 0; 858 859 switch (ISSET(cflag, CSIZE)) { 860 case CS7: 861 mode1 |= 2; /* XXX */ 862 break; 863 default: 864 err = -1; 865 /* FALLTHRU for sanity */ 866 case CS8: 867 mode1 |= 3; /* XXX */ 868 break; 869 } 870 if (!ISSET(cflag, PARENB)) 871 mode1 |= 2 << 3; 872 else { 873 mode1 |= 0 << 3; 874 if (ISSET(cflag, PARODD)) 875 mode1 |= 1 << 2; 876 } 877 878 if (ISSET(cflag, CSTOPB)) 879 mode2 |= 1 << 3; /* two stop bits XXX not std */ 880 881 if (ISSET(cflag, CRTSCTS)) { 882 mode1 |= 1 << 7; 883 mode2 |= 1 << 4; 884 } 885 886 *mode1p = mode1; 887 *mode2p = mode2; 888 return (err); 889 } 890 891 int 892 sbjcn_param(struct tty *tp, struct termios *t) 893 { 894 struct sbjcn_softc *sc = device_lookup_private(&sbjcn_cd, SBJCN_UNIT(tp->t_dev)); 895 struct sbjcn_channel *ch = &sc->sc_channels[SBJCN_CHAN(tp->t_dev)]; 896 long brc; 897 u_char mode1, mode2; 898 int s; 899 900 /* XXX reset to console parameters if console? */ 901 #if 0 902 XXX disable, enable. 903 #endif 904 905 /* Check requested parameters. */ 906 if (sbjcn_speed(t->c_ospeed, &brc) < 0) 907 return (EINVAL); 908 if (t->c_ispeed && t->c_ispeed != t->c_ospeed) 909 return (EINVAL); 910 911 /* 912 * For the console, always force CLOCAL and !HUPCL, so that the port 913 * is always active. 914 */ 915 if (ISSET(ch->ch_swflags, TIOCFLAG_SOFTCAR) || 916 ISSET(ch->ch_hwflags, SBJCN_HW_CONSOLE)) { 917 SET(t->c_cflag, CLOCAL); 918 CLR(t->c_cflag, HUPCL); 919 } 920 921 /* 922 * If there were no changes, don't do anything. This avoids dropping 923 * input and improves performance when all we did was frob things like 924 * VMIN and VTIME. 925 */ 926 if (tp->t_ospeed == t->c_ospeed && 927 tp->t_cflag == t->c_cflag) 928 return (0); 929 930 if (cflag2modes(t->c_cflag, &mode1, &mode2) < 0) 931 return (EINVAL); 932 933 s = splserial(); 934 935 ch->ch_mode1 = mode1; 936 ch->ch_mode2 = mode2; 937 938 /* 939 * If we're not in a mode that assumes a connection is present, then 940 * ignore carrier changes. 941 */ 942 if (ISSET(t->c_cflag, CLOCAL | MDMBUF)) 943 ch->ch_i_dcd = 0; 944 else 945 ch->ch_i_dcd = ch->ch_i_dcd_pin; 946 /* 947 * Set the flow control pins depending on the current flow control 948 * mode. 949 */ 950 if (ISSET(t->c_cflag, CRTSCTS)) { 951 ch->ch_o_dtr = ch->ch_o_dtr_pin; 952 ch->ch_o_rts = ch->ch_o_rts_pin; 953 ch->ch_i_cts = ch->ch_i_cts_pin; 954 /* hw controle enable bits in mod regs set by cflag2modes */ 955 } else if (ISSET(t->c_cflag, MDMBUF)) { 956 /* 957 * For DTR/DCD flow control, make sure we don't toggle DTR for 958 * carrier detection. 959 */ 960 ch->ch_o_dtr = 0; 961 ch->ch_o_rts = ch->ch_o_dtr_pin; 962 ch->ch_i_cts = ch->ch_i_dcd_pin; 963 } else { 964 /* 965 * If no flow control, then always set RTS. This will make 966 * the other side happy if it mistakenly thinks we're doing 967 * RTS/CTS flow control. 968 */ 969 ch->ch_o_dtr = ch->ch_o_dtr_pin | ch->ch_o_rts_pin; 970 ch->ch_o_rts = 0; 971 ch->ch_i_cts = 0; 972 if (ISSET(ch->ch_oports, ch->ch_o_dtr_pin)) 973 SET(ch->ch_oports, ch->ch_o_rts_pin); 974 else 975 CLR(ch->ch_oports, ch->ch_o_rts_pin); 976 } 977 /* XXX maybe mask the ports which generate intrs? */ 978 979 ch->ch_brc = brc; 980 981 /* XXX maybe set fifo-full receive mode if RTSCTS and high speed? */ 982 983 /* And copy to tty. */ 984 tp->t_ispeed = 0; 985 tp->t_ospeed = t->c_ospeed; 986 tp->t_cflag = t->c_cflag; 987 988 if (!ch->ch_heldchange) { 989 if (ch->ch_tx_busy) { 990 ch->ch_heldtbc = ch->ch_tbc; 991 ch->ch_tbc = 0; 992 ch->ch_heldchange = 1; 993 } else 994 sbjcn_loadchannelregs(ch); 995 } 996 997 if (!ISSET(t->c_cflag, CHWFLOW)) { 998 /* Disable the high water mark. */ 999 ch->ch_r_hiwat = 0; 1000 ch->ch_r_lowat = 0; 1001 if (ISSET(ch->ch_rx_flags, RX_TTY_OVERFLOWED)) { 1002 CLR(ch->ch_rx_flags, RX_TTY_OVERFLOWED); 1003 sbjcn_schedrx(ch); 1004 } 1005 if (ISSET(ch->ch_rx_flags, RX_TTY_BLOCKED|RX_IBUF_BLOCKED)) { 1006 CLR(ch->ch_rx_flags, RX_TTY_BLOCKED|RX_IBUF_BLOCKED); 1007 sbjcn_dohwiflow(ch); 1008 } 1009 } else { 1010 ch->ch_r_hiwat = sbjcn_rbuf_hiwat; 1011 ch->ch_r_lowat = sbjcn_rbuf_lowat; 1012 } 1013 1014 splx(s); 1015 1016 /* 1017 * Update the tty layer's idea of the carrier bit, in case we changed 1018 * CLOCAL or MDMBUF. We don't hang up here; we only do that by 1019 * explicit request. 1020 */ 1021 (void) (*tp->t_linesw->l_modem)(tp, 1022 ISSET(ch->ch_iports, ch->ch_i_dcd)); 1023 1024 #ifdef SBJCN_DEBUG 1025 if (sbjcn_debug) 1026 sbjcn_status(ch, "sbjcnparam "); 1027 #endif 1028 1029 if (!ISSET(t->c_cflag, CHWFLOW)) { 1030 if (ch->ch_tx_stopped) { 1031 ch->ch_tx_stopped = 0; 1032 sbjcn_start(tp); 1033 } 1034 } 1035 1036 return (0); 1037 } 1038 1039 void 1040 sbjcn_iflush(struct sbjcn_channel *ch) 1041 { 1042 uint64_t reg; 1043 int timo; 1044 1045 timo = 50000; 1046 /* flush any pending I/O */ 1047 while (((reg = READ_REG(ch->ch_input_reg)) != 0) && --timo) 1048 ; 1049 1050 #ifdef DIAGNOSTIC 1051 if (!timo) 1052 aprint_error_dev(ch->ch_sc->sc_dev, 1053 "sbjcn_iflush timeout %02x\n", reg); 1054 #endif 1055 } 1056 1057 void 1058 sbjcn_loadchannelregs(struct sbjcn_channel *ch) 1059 { 1060 } 1061 1062 int 1063 sbjcn_hwiflow(struct tty *tp, int block) 1064 { 1065 struct sbjcn_softc *sc = device_lookup_private(&sbjcn_cd, SBJCN_UNIT(tp->t_dev)); 1066 struct sbjcn_channel *ch = &sc->sc_channels[SBJCN_CHAN(tp->t_dev)]; 1067 int s; 1068 1069 if (ch->ch_o_rts == 0) 1070 return (0); 1071 1072 s = splserial(); 1073 if (block) { 1074 if (!ISSET(ch->ch_rx_flags, RX_TTY_BLOCKED)) { 1075 SET(ch->ch_rx_flags, RX_TTY_BLOCKED); 1076 sbjcn_dohwiflow(ch); 1077 } 1078 } else { 1079 if (ISSET(ch->ch_rx_flags, RX_TTY_OVERFLOWED)) { 1080 CLR(ch->ch_rx_flags, RX_TTY_OVERFLOWED); 1081 sbjcn_schedrx(ch); 1082 } 1083 if (ISSET(ch->ch_rx_flags, RX_TTY_BLOCKED)) { 1084 CLR(ch->ch_rx_flags, RX_TTY_BLOCKED); 1085 sbjcn_dohwiflow(ch); 1086 } 1087 } 1088 splx(s); 1089 return (1); 1090 } 1091 1092 /* 1093 * (un)block input via hw flowcontrol 1094 */ 1095 void 1096 sbjcn_dohwiflow(struct sbjcn_channel *ch) 1097 { 1098 1099 if (ch->ch_o_rts == 0) 1100 return; 1101 1102 if (ISSET(ch->ch_rx_flags, RX_ANY_BLOCK)) { 1103 CLR(ch->ch_oports, ch->ch_o_rts); 1104 CLR(ch->ch_oports_active, ch->ch_o_rts); 1105 } else { 1106 SET(ch->ch_oports, ch->ch_o_rts); 1107 SET(ch->ch_oports_active, ch->ch_o_rts); 1108 } 1109 } 1110 1111 void 1112 sbjcn_start(struct tty *tp) 1113 { 1114 struct sbjcn_softc *sc = device_lookup_private(&sbjcn_cd, SBJCN_UNIT(tp->t_dev)); 1115 struct sbjcn_channel *ch = &sc->sc_channels[SBJCN_CHAN(tp->t_dev)]; 1116 int s; 1117 1118 s = spltty(); 1119 if (ISSET(tp->t_state, TS_BUSY | TS_TIMEOUT | TS_TTSTOP)) 1120 goto out; 1121 if (ch->ch_tx_stopped) 1122 goto out; 1123 if (!ttypull(tp)) 1124 goto out; 1125 1126 /* Grab the first contiguous region of buffer space. */ 1127 { 1128 u_char *tba; 1129 int tbc; 1130 1131 tba = tp->t_outq.c_cf; 1132 tbc = ndqb(&tp->t_outq, 0); 1133 1134 (void)splserial(); 1135 1136 ch->ch_tba = tba; 1137 ch->ch_tbc = tbc; 1138 } 1139 1140 SET(tp->t_state, TS_BUSY); 1141 ch->ch_tx_busy = 1; 1142 1143 /* Output the first chunk of the contiguous buffer. */ 1144 { 1145 while (ch->ch_tbc) { 1146 uint64_t data; 1147 int bytes, i; 1148 1149 bytes = (ch->ch_tbc > 7) ? 7 : ch->ch_tbc; 1150 data = bytes; 1151 for (i=0; i<bytes; i++) { 1152 data <<= 8; 1153 data |= *ch->ch_tba++; 1154 } 1155 if (bytes < 7) 1156 data <<= 56-(bytes<<3); 1157 ch->ch_tbc -= bytes; 1158 WRITE_REG(ch->ch_output_reg, data); 1159 } 1160 ch->ch_tx_busy = 0; 1161 ch->ch_tx_done = 1; 1162 } 1163 out: 1164 splx(s); 1165 return; 1166 } 1167 1168 /* 1169 * Stop output on a line. 1170 */ 1171 void 1172 sbjcnstop(struct tty *tp, int flag) 1173 { 1174 struct sbjcn_softc *sc = device_lookup_private(&sbjcn_cd, SBJCN_UNIT(tp->t_dev)); 1175 struct sbjcn_channel *ch = &sc->sc_channels[SBJCN_CHAN(tp->t_dev)]; 1176 int s; 1177 1178 s = splserial(); 1179 if (ISSET(tp->t_state, TS_BUSY)) { 1180 /* Stop transmitting at the next chunk. */ 1181 ch->ch_tbc = 0; 1182 ch->ch_heldtbc = 0; 1183 if (!ISSET(tp->t_state, TS_TTSTOP)) 1184 SET(tp->t_state, TS_FLUSH); 1185 } 1186 splx(s); 1187 } 1188 1189 void 1190 sbjcn_diag(void *arg) 1191 { 1192 struct sbjcn_channel *ch = arg; 1193 struct sbjcn_softc *sc = ch->ch_sc; 1194 int overflows, floods; 1195 int s; 1196 1197 s = splserial(); 1198 overflows = ch->ch_overflows; 1199 ch->ch_overflows = 0; 1200 floods = ch->ch_floods; 1201 ch->ch_floods = 0; 1202 ch->ch_errors = 0; 1203 splx(s); 1204 1205 log(LOG_WARNING, "%s: channel %d: %d fifo overflow%s, %d ibuf flood%s\n", 1206 device_xname(sc->sc_dev), ch->ch_num, 1207 overflows, overflows == 1 ? "" : "s", 1208 floods, floods == 1 ? "" : "s"); 1209 } 1210 1211 integrate void 1212 sbjcn_rxsoft(struct sbjcn_channel *ch, struct tty *tp) 1213 { 1214 int (*rint)(int c, struct tty *tp) = tp->t_linesw->l_rint; 1215 u_char *get, *end; 1216 u_int cc, scc; 1217 u_char sr; 1218 int code; 1219 int s; 1220 1221 end = ch->ch_ebuf; 1222 get = ch->ch_rbget; 1223 scc = cc = sbjcn_rbuf_size - ch->ch_rbavail; 1224 1225 if (cc == sbjcn_rbuf_size) { 1226 ch->ch_floods++; 1227 if (ch->ch_errors++ == 0) 1228 callout_reset(&ch->ch_diag_callout, 60 * hz, 1229 sbjcn_diag, ch); 1230 } 1231 1232 while (cc) { 1233 code = get[0]; 1234 sr = get[1]; 1235 if (ISSET(sr, 0xf0)) { 1236 if (ISSET(sr, 0x10)) { 1237 ch->ch_overflows++; 1238 if (ch->ch_errors++ == 0) 1239 callout_reset(&ch->ch_diag_callout, 1240 60 * hz, sbjcn_diag, ch); 1241 } 1242 if (ISSET(sr, 0xc0)) 1243 SET(code, TTY_FE); 1244 if (ISSET(sr, 0x20)) 1245 SET(code, TTY_PE); 1246 } 1247 if ((*rint)(code, tp) == -1) { 1248 /* 1249 * The line discipline's buffer is out of space. 1250 */ 1251 if (!ISSET(ch->ch_rx_flags, RX_TTY_BLOCKED)) { 1252 /* 1253 * We're either not using flow control, or the 1254 * line discipline didn't tell us to block for 1255 * some reason. Either way, we have no way to 1256 * know when there's more space available, so 1257 * just drop the rest of the data. 1258 */ 1259 get += cc << 1; 1260 if (get >= end) 1261 get -= sbjcn_rbuf_size << 1; 1262 cc = 0; 1263 } else { 1264 /* 1265 * Don't schedule any more receive processing 1266 * until the line discipline tells us there's 1267 * space available (through comhwiflow()). 1268 * Leave the rest of the data in the input 1269 * buffer. 1270 */ 1271 SET(ch->ch_rx_flags, RX_TTY_OVERFLOWED); 1272 } 1273 break; 1274 } 1275 get += 2; 1276 if (get >= end) 1277 get = ch->ch_rbuf; 1278 cc--; 1279 } 1280 1281 if (cc != scc) { 1282 ch->ch_rbget = get; 1283 s = splserial(); 1284 cc = ch->ch_rbavail += scc - cc; 1285 /* Buffers should be ok again, release possible block. */ 1286 if (cc >= ch->ch_r_lowat) { 1287 if (ISSET(ch->ch_rx_flags, RX_IBUF_OVERFLOWED)) { 1288 CLR(ch->ch_rx_flags, RX_IBUF_OVERFLOWED); 1289 SET(ch->ch_imr, 0x02); 1290 } 1291 if (ISSET(ch->ch_rx_flags, RX_IBUF_BLOCKED)) { 1292 CLR(ch->ch_rx_flags, RX_IBUF_BLOCKED); 1293 sbjcn_dohwiflow(ch); 1294 } 1295 } 1296 splx(s); 1297 } 1298 } 1299 1300 integrate void 1301 sbjcn_txsoft(struct sbjcn_channel *ch, struct tty *tp) 1302 { 1303 1304 CLR(tp->t_state, TS_BUSY); 1305 if (ISSET(tp->t_state, TS_FLUSH)) 1306 CLR(tp->t_state, TS_FLUSH); 1307 else 1308 ndflush(&tp->t_outq, (int)(ch->ch_tba - tp->t_outq.c_cf)); 1309 (*tp->t_linesw->l_start)(tp); 1310 } 1311 1312 integrate void 1313 sbjcn_stsoft(struct sbjcn_channel *ch, struct tty *tp) 1314 { 1315 u_char iports, delta; 1316 int s; 1317 1318 s = splserial(); 1319 iports = ch->ch_iports; 1320 delta = ch->ch_iports_delta; 1321 ch->ch_iports_delta = 0; 1322 splx(s); 1323 1324 if (ISSET(delta, ch->ch_i_dcd)) { 1325 /* 1326 * Inform the tty layer that carrier detect changed. 1327 */ 1328 (void) (*tp->t_linesw->l_modem)(tp, 1329 ISSET(iports, ch->ch_i_dcd)); 1330 } 1331 1332 if (ISSET(delta, ch->ch_i_cts)) { 1333 /* Block or unblock output according to flow control. */ 1334 if (ISSET(iports, ch->ch_i_cts)) { 1335 ch->ch_tx_stopped = 0; 1336 (*tp->t_linesw->l_start)(tp); 1337 } else { 1338 ch->ch_tx_stopped = 1; 1339 } 1340 } 1341 1342 #ifdef SBJCN_DEBUG 1343 if (sbjcn_debug) 1344 sbjcn_status(ch, "sbjcn_stsoft"); 1345 #endif 1346 } 1347 1348 integrate void 1349 sbjcn_recv(struct sbjcn_channel *ch) 1350 { 1351 u_char *put, *end; 1352 u_int cc; 1353 1354 end = ch->ch_ebuf; 1355 put = ch->ch_rbput; 1356 cc = ch->ch_rbavail; 1357 1358 /* XXX process break */ 1359 1360 sbjcncn_grabdword(ch); 1361 if (ch->ch_waiting_input) { 1362 if (!ISSET(ch->ch_rx_flags, RX_IBUF_OVERFLOWED)) { 1363 while (cc > 0) { 1364 put[0] = sbjcncn_nextbyte(ch); 1365 put[1] = 1; /* XXXKW ? */ 1366 put += 2; 1367 if (put >= end) 1368 put = ch->ch_rbuf; 1369 cc--; 1370 1371 if (!ch->ch_waiting_input) 1372 break; 1373 } 1374 1375 /* 1376 * Current string of incoming characters ended 1377 * because no more data was available or we 1378 * ran out of space. Schedule a receive event 1379 * if any data was received. If we're out of 1380 * space, turn off receive interrupts. 1381 */ 1382 ch->ch_rbput = put; 1383 ch->ch_rbavail = cc; 1384 if (!ISSET(ch->ch_rx_flags, RX_TTY_OVERFLOWED)) 1385 ch->ch_rx_ready = 1; 1386 1387 /* 1388 * See if we are in danger of overflowing a 1389 * buffer. If so, use hardware flow control 1390 * to ease the pressure. 1391 */ 1392 if (!ISSET(ch->ch_rx_flags, RX_IBUF_BLOCKED) && 1393 cc < ch->ch_r_hiwat) { 1394 SET(ch->ch_rx_flags, RX_IBUF_BLOCKED); 1395 sbjcn_dohwiflow(ch); 1396 } 1397 1398 /* 1399 * If we're out of space, disable receive 1400 * interrupts until the queue has drained 1401 * a bit. 1402 */ 1403 if (!cc) { 1404 SET(ch->ch_rx_flags, 1405 RX_IBUF_OVERFLOWED); 1406 CLR(ch->ch_imr, 0x02); 1407 } 1408 } else { 1409 /* XXX panic? */ 1410 CLR(ch->ch_imr, 0x02); 1411 // continue; 1412 } 1413 } 1414 1415 /* 1416 * If we've delayed a parameter change, do it now, and restart 1417 * output. 1418 */ 1419 if (ch->ch_heldchange) { 1420 sbjcn_loadchannelregs(ch); 1421 ch->ch_heldchange = 0; 1422 ch->ch_tbc = ch->ch_heldtbc; 1423 ch->ch_heldtbc = 0; 1424 } 1425 } 1426 1427 void 1428 sbjcn_callout(void *arg) 1429 { 1430 struct sbjcn_channel *ch = arg; 1431 struct tty *tp = ch->ch_tty; 1432 1433 /* XXX get stuff */ 1434 sbjcn_recv(ch); 1435 1436 /* XXX check receive */ 1437 if (ch->ch_rx_ready) { 1438 ch->ch_rx_ready = 0; 1439 sbjcn_rxsoft(ch, tp); 1440 } 1441 1442 /* XXX check transmit */ 1443 if (ch->ch_tx_done) { 1444 ch->ch_tx_done = 0; 1445 sbjcn_txsoft(ch, tp); 1446 } 1447 1448 callout_reset(&ch->ch_callout, hz/10, sbjcn_callout, ch); 1449 } 1450 1451 static char sbjcncn_nextbyte(struct sbjcn_channel *ch) 1452 { 1453 char c; 1454 1455 sbjcncn_grabdword(ch); 1456 c = (ch->ch_input_buf >> 56) & 0xff; 1457 ch->ch_input_buf <<= 8; 1458 ch->ch_waiting_input--; 1459 return c; 1460 } 1461 1462 static void sbjcncn_grabdword(struct sbjcn_channel *ch) 1463 { 1464 uint64_t inbuf; 1465 1466 if (ch->ch_waiting_input) 1467 return; 1468 1469 inbuf = READ_REG(ch->ch_input_reg); 1470 ch->ch_waiting_input = jtag_input_len(inbuf); 1471 ch->ch_input_buf = inbuf << 8; 1472 } 1473 1474 /* 1475 * Initialize UART for use as console or KGDB line. 1476 */ 1477 int 1478 sbjcn_init(u_long addr, int chan, int rate, tcflag_t cflag) 1479 { 1480 /* XXXKW Anything to do here? */ 1481 return (0); 1482 } 1483 1484 /* 1485 * Following are all routines needed for sbjcn to act as console 1486 */ 1487 int 1488 sbjcn_cnattach(u_long addr, int chan, int rate, tcflag_t cflag) 1489 { 1490 int res; 1491 uint64_t ctrl_val; 1492 static struct consdev sbjcn_cons = { 1493 NULL, NULL, sbjcn_cngetc, sbjcn_cnputc, sbjcn_cnpollc, NULL, 1494 NODEV, CN_NORMAL 1495 }; 1496 1497 res = sbjcn_init(addr, chan, rate, cflag); 1498 if (res) 1499 return (res); 1500 1501 cn_tab = &sbjcn_cons; 1502 1503 sbjcn_cons_present = 1; 1504 sbjcn_cons_addr = addr; 1505 sbjcn_cons_waiting_input = 0; 1506 sbjcn_cons_chan = chan; 1507 sbjcn_cons_rate = rate; 1508 sbjcn_cons_cflag = cflag; 1509 1510 /* Wait for sign of life from the other end */ 1511 while ((ctrl_val = READ_REG(MIPS_PHYS_TO_KSEG1(sbjcn_cons_addr + JTAG_CONS_CONTROL))) == 0) 1512 ; 1513 1514 return (ctrl_val != JTAG_CONS_MAGICNUM); 1515 } 1516 1517 int 1518 sbjcn_cngetc(dev_t dev) 1519 { 1520 char c; 1521 1522 while (sbjcn_cons_waiting_input == 0) 1523 sbjcn_cngrabdword(); 1524 1525 c = (sbjcn_cons_input_buf >> 56) & 0xff; 1526 sbjcn_cons_input_buf <<= 8; 1527 sbjcn_cons_waiting_input--; 1528 1529 return c; 1530 } 1531 1532 /* 1533 * Console kernel output character routine. 1534 */ 1535 void 1536 sbjcn_cnputc(dev_t dev, int c) 1537 { 1538 uint64_t outbuf; 1539 1540 outbuf = (1LL << 56) | (((uint64_t)c) << 48); 1541 WRITE_REG(MIPS_PHYS_TO_KSEG1(sbjcn_cons_addr + JTAG_CONS_OUTPUT), outbuf); 1542 } 1543 1544 void 1545 sbjcn_cnpollc(dev_t dev, int on) 1546 { 1547 1548 } 1549 1550 static void sbjcn_cngrabdword(void) 1551 { 1552 uint64_t inbuf; 1553 1554 if (sbjcn_cons_waiting_input) 1555 return; 1556 1557 inbuf = READ_REG(MIPS_PHYS_TO_KSEG1(sbjcn_cons_addr + JTAG_CONS_INPUT)); 1558 sbjcn_cons_waiting_input = jtag_input_len(inbuf); 1559 sbjcn_cons_input_buf = inbuf << 8; 1560 } 1561 1562 #ifdef KGDB 1563 int 1564 sbjcn_kgdb_attach(u_long addr, int chan, int rate, tcflag_t cflag) 1565 { 1566 int res; 1567 1568 if (!sbjcn_cons_present && 1569 sbjcn_cons_addr == addr && sbjcn_cons_chan == chan) 1570 return (EBUSY); /* cannot share with console */ 1571 1572 res = sbjcn_init(addr, chan, rate, cflag); 1573 if (res) 1574 return (res); 1575 1576 kgdb_attach(sbjcn_kgdb_getc, sbjcn_kgdb_putc, NULL); 1577 kgdb_dev = 123; /* unneeded, only to satisfy some tests */ 1578 kgdb_rate = rate; 1579 1580 sbjcn_kgdb_present = 1; 1581 /* XXX sbjcn_init wants addr, but we need the offset addr */ 1582 sbjcn_kgdb_addr = addr + (chan * 0x100); 1583 sbjcn_kgdb_chan = chan; 1584 1585 return (0); 1586 } 1587 1588 /* ARGSUSED */ 1589 int 1590 sbjcn_kgdb_getc(void *arg) 1591 { 1592 1593 return (sbjcn_common_getc(sbjcn_kgdb_addr, sbjcn_kgdb_chan)); 1594 } 1595 1596 /* ARGSUSED */ 1597 void 1598 sbjcn_kgdb_putc(void *arg, int c) 1599 { 1600 1601 sbjcn_common_putc(sbjcn_kgdb_addr, sbjcn_kgdb_chan, c); 1602 } 1603 #endif /* KGDB */ 1604 1605 /* 1606 * helper function to identify the sbjcn channels used by 1607 * console or KGDB (and not yet autoconf attached) 1608 */ 1609 int 1610 sbjcn_is_console(u_long addr, int chan) 1611 { 1612 1613 if (sbjcn_cons_present && !sbjcn_cons_attached && 1614 sbjcn_cons_addr == addr && sbjcn_cons_chan == chan) 1615 return (1); 1616 #ifdef KGDB 1617 if (sbjcn_kgdb_present && !sbjcn_kgdb_attached && 1618 sbjcn_kgdb_addr == addr && sbjcn_kgdb_chan == chan) 1619 return (1); 1620 #endif 1621 return (0); 1622 } 1623