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