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