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