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