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