1 /* $NetBSD: sbjcn.c,v 1.1 2002/03/05 23:46:42 simonb 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. Neither the "Broadcom Corporation" name nor any 19 * trademark or logo of Broadcom Corporation may be used to endorse or 20 * promote products derived from this software without the prior written 21 * permission of Broadcom Corporation. 22 * 23 * 3) THIS SOFTWARE IS PROVIDED "AS-IS" AND ANY EXPRESS OR IMPLIED 24 * WARRANTIES, INCLUDING BUT NOT LIMITED TO, ANY IMPLIED WARRANTIES OF 25 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, OR 26 * NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT SHALL BROADCOM BE LIABLE 27 * FOR ANY DAMAGES WHATSOEVER, AND IN PARTICULAR, BROADCOM SHALL NOT BE 28 * LIABLE FOR DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 29 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 30 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR 31 * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 32 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE 33 * OR OTHERWISE), EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 34 */ 35 36 #define SBJCN_DEBUG 37 38 /* from: $NetBSD: com.c,v 1.172 2000/05/03 19:19:04 thorpej Exp */ 39 40 /*- 41 * Copyright (c) 1998, 1999 The NetBSD Foundation, Inc. 42 * All rights reserved. 43 * 44 * This code is derived from software contributed to The NetBSD Foundation 45 * by Charles M. Hannum. 46 * 47 * Redistribution and use in source and binary forms, with or without 48 * modification, are permitted provided that the following conditions 49 * are met: 50 * 1. Redistributions of source code must retain the above copyright 51 * notice, this list of conditions and the following disclaimer. 52 * 2. Redistributions in binary form must reproduce the above copyright 53 * notice, this list of conditions and the following disclaimer in the 54 * documentation and/or other materials provided with the distribution. 55 * 3. All advertising materials mentioning features or use of this software 56 * must display the following acknowledgement: 57 * This product includes software developed by the NetBSD 58 * Foundation, Inc. and its contributors. 59 * 4. Neither the name of The NetBSD Foundation nor the names of its 60 * contributors may be used to endorse or promote products derived 61 * from this software without specific prior written permission. 62 * 63 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 64 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 65 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 66 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 67 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 68 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 69 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 70 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 71 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 72 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 73 * POSSIBILITY OF SUCH DAMAGE. 74 */ 75 76 /* 77 * Copyright (c) 1991 The Regents of the University of California. 78 * All rights reserved. 79 * 80 * Redistribution and use in source and binary forms, with or without 81 * modification, are permitted provided that the following conditions 82 * are met: 83 * 1. Redistributions of source code must retain the above copyright 84 * notice, this list of conditions and the following disclaimer. 85 * 2. Redistributions in binary form must reproduce the above copyright 86 * notice, this list of conditions and the following disclaimer in the 87 * documentation and/or other materials provided with the distribution. 88 * 3. All advertising materials mentioning features or use of this software 89 * must display the following acknowledgement: 90 * This product includes software developed by the University of 91 * California, Berkeley and its contributors. 92 * 4. Neither the name of the University nor the names of its contributors 93 * may be used to endorse or promote products derived from this software 94 * without specific prior written permission. 95 * 96 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 97 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 98 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 99 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 100 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 101 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 102 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 103 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 104 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 105 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 106 * SUCH DAMAGE. 107 * 108 * @(#)com.c 7.5 (Berkeley) 5/16/91 109 */ 110 111 /* 112 * `sbjcn' driver, supports console over SiByte SB-1250 JTAG. 113 * 114 * Accesses a section of JTAG memory space to mimic a console, 115 * if there's a matching program outside to communicate with. 116 * If nobody is there, things will be very quiet. 117 */ 118 119 #include "opt_ddb.h" 120 121 #include <sys/param.h> 122 #include <sys/systm.h> 123 #include <sys/ioctl.h> 124 #include <sys/select.h> 125 #include <sys/tty.h> 126 #include <sys/proc.h> 127 #include <sys/user.h> 128 #include <sys/conf.h> 129 #include <sys/file.h> 130 #include <sys/uio.h> 131 #include <sys/kernel.h> 132 #include <sys/syslog.h> 133 #include <sys/types.h> 134 #include <sys/device.h> 135 #include <sys/malloc.h> 136 #include <sys/vnode.h> 137 138 #include <sbmips/dev/sbscd/sbscdvar.h> 139 #include <sbmips/dev/sbscd/sbjcnvar.h> 140 #include <dev/cons.h> 141 #include <machine/locore.h> 142 143 void sbjcn_attach_channel(struct sbjcn_softc *sc, int chan, int intr); 144 static void sbjcncn_grabdword(struct sbjcn_channel *ch); 145 static char sbjcncn_nextbyte(struct sbjcn_channel *ch); 146 static void sbjcn_cngrabdword(void); 147 148 #if defined(DDB) || defined(KGDB) 149 static void sbjcn_enable_debugport(struct sbjcn_channel *ch); 150 #endif 151 void sbjcn_config(struct sbjcn_channel *ch); 152 void sbjcn_shutdown(struct sbjcn_channel *ch); 153 int sbjcn_speed(long, long *); 154 static int cflag2modes(tcflag_t, u_char *, u_char *); 155 int sbjcn_param(struct tty *, struct termios *); 156 void sbjcn_start(struct tty *); 157 void sbjcnstop(struct tty *, int); 158 int sbjcn_hwiflow(struct tty *, int); 159 160 void sbjcn_loadchannelregs(struct sbjcn_channel *); 161 void sbjcn_dohwiflow(struct sbjcn_channel *); 162 void sbjcn_break(struct sbjcn_channel *, int); 163 void sbjcn_modem(struct sbjcn_channel *, int); 164 void tiocm_to_sbjcn(struct sbjcn_channel *, int, int); 165 int sbjcn_to_tiocm(struct sbjcn_channel *); 166 void sbjcn_iflush(struct sbjcn_channel *); 167 168 int sbjcn_init(u_long addr, int chan, int rate, tcflag_t cflag); 169 int sbjcn_common_getc(u_long addr, int chan); 170 void sbjcn_common_putc(u_long addr, int chan, int c); 171 172 /* XXX: These belong elsewhere */ 173 cdev_decl(sbjcn); 174 175 int sbjcn_cngetc(dev_t dev); 176 void sbjcn_cnputc(dev_t dev, int c); 177 void sbjcn_cnpollc(dev_t dev, int on); 178 179 extern struct cfdriver sbjcn_cd; 180 181 #define integrate static inline 182 integrate void sbjcn_rxsoft(struct sbjcn_channel *, struct tty *); 183 integrate void sbjcn_txsoft(struct sbjcn_channel *, struct tty *); 184 integrate void sbjcn_stsoft(struct sbjcn_channel *, struct tty *); 185 integrate void sbjcn_schedrx(struct sbjcn_channel *); 186 integrate void sbjcn_recv(struct sbjcn_channel *ch); 187 void sbjcn_diag(void *); 188 void sbjcn_callout(void *); 189 190 /* 191 * Make this an option variable one can patch. 192 * But be warned: this must be a power of 2! 193 */ 194 u_int sbjcn_rbuf_size = SBJCN_RING_SIZE; 195 196 /* Stop input when 3/4 of the ring is full; restart when only 1/4 is full. */ 197 u_int sbjcn_rbuf_hiwat = (SBJCN_RING_SIZE * 1) / 4; 198 u_int sbjcn_rbuf_lowat = (SBJCN_RING_SIZE * 3) / 4; 199 200 static int sbjcn_cons_present; 201 static int sbjcn_cons_attached; 202 static u_long sbjcn_cons_addr; 203 static int sbjcn_cons_chan; 204 static int sbjcn_cons_rate; 205 static tcflag_t sbjcn_cons_cflag; 206 static int sbjcn_cons_waiting_input; 207 static uint64_t sbjcn_cons_input_buf; 208 209 #ifdef KGDB 210 #include <sys/kgdb.h> 211 212 static int sbjcn_kgdb_present; 213 static int sbjcn_kgdb_attached; 214 static u_long sbjcn_kgdb_addr; 215 static int sbjcn_kgdb_chan; 216 217 int sbjcn_kgdb_getc(void *); 218 void sbjcn_kgdb_putc(void *, int); 219 #endif /* KGDB */ 220 221 static int sbjcn_match(struct device *, struct cfdata *, void *); 222 static void sbjcn_attach(struct device *, struct device *, void *); 223 224 const struct cfattach sbjcn_ca = { 225 sizeof(struct sbjcn_softc), sbjcn_match, sbjcn_attach, 226 }; 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); 293 callout_init(&ch->ch_callout); 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 for (maj = 0; maj < nchrdev; maj++) 329 if (cdevsw[maj].d_open == sbjcnopen) 330 break; 331 332 cn_tab->cn_dev = makedev(maj, (sc->sc_dev.dv_unit << 1) + chan); 333 334 printf("%s: channel %d: console\n", sc->sc_dev.dv_xname, chan); 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 printf("%s: channel %d: kgdb\n", sc->sc_dev.dv_xname, chan); 348 } 349 #endif 350 351 sbjcn_config(ch); 352 353 callout_reset(&ch->ch_callout, hz/10, sbjcn_callout, ch); 354 355 SET(ch->ch_hwflags, SBJCN_HW_DEV_OK); 356 } 357 358 int 359 sbjcn_speed(long speed, long *brcp) 360 { 361 #define divrnd(n, q) (((n)*2/(q)+1)/2) /* divide and round off */ 362 363 int x, err; 364 int frequency = 100000000; 365 366 *brcp = divrnd(frequency / 20, speed) - 1; 367 368 if (speed <= 0) 369 return (-1); 370 x = divrnd(frequency / 20, speed); 371 if (x <= 0) 372 return (-1); 373 err = divrnd(((quad_t)frequency) * 1000 / 20, speed * x) - 1000; 374 if (err < 0) 375 err = -err; 376 if (err > SBJCN_TOLERANCE) 377 return (-1); 378 *brcp = x - 1; 379 return (0); 380 381 #undef divrnd 382 } 383 384 #ifdef SBJCN_DEBUG 385 void sbjcn_status(struct sbjcn_channel *, char *); 386 387 int sbjcn_debug = 1 /* XXXCGD */; 388 389 void 390 sbjcn_status(struct sbjcn_channel *ch, char *str) 391 { 392 struct sbjcn_softc *sc = ch->ch_sc; 393 struct tty *tp = ch->ch_tty; 394 395 printf("%s: chan %d: %s %sclocal %sdcd %sts_carr_on %sdtr %stx_stopped\n", 396 sc->sc_dev.dv_xname, ch->ch_num, str, 397 ISSET(tp->t_cflag, CLOCAL) ? "+" : "-", 398 ISSET(ch->ch_iports, ch->ch_i_dcd) ? "+" : "-", 399 ISSET(tp->t_state, TS_CARR_ON) ? "+" : "-", 400 ISSET(ch->ch_oports, ch->ch_o_dtr) ? "+" : "-", 401 ch->ch_tx_stopped ? "+" : "-"); 402 403 printf("%s: chan %d: %s %scrtscts %scts %sts_ttstop %srts %xrx_flags\n", 404 sc->sc_dev.dv_xname, ch->ch_num, str, 405 ISSET(tp->t_cflag, CRTSCTS) ? "+" : "-", 406 ISSET(ch->ch_iports, ch->ch_i_cts) ? "+" : "-", 407 ISSET(tp->t_state, TS_TTSTOP) ? "+" : "-", 408 ISSET(ch->ch_oports, ch->ch_o_rts) ? "+" : "-", 409 ch->ch_rx_flags); 410 } 411 #endif 412 413 #if defined(DDB) || defined(KGDB) 414 static void 415 sbjcn_enable_debugport(struct sbjcn_channel *ch) 416 { 417 int s; 418 419 /* Turn on line break interrupt, set carrier. */ 420 s = splserial(); 421 422 ch->ch_imr = 0x04; 423 SET(ch->ch_oports, ch->ch_o_dtr | ch->ch_o_rts); 424 425 splx(s); 426 } 427 #endif 428 429 void 430 sbjcn_config(struct sbjcn_channel *ch) 431 { 432 433 /* Disable interrupts before configuring the device. */ 434 ch->ch_imr = 0x00; 435 436 #ifdef DDB 437 if (ISSET(ch->ch_hwflags, SBJCN_HW_CONSOLE)) 438 sbjcn_enable_debugport(ch); 439 #endif 440 441 #ifdef KGDB 442 /* 443 * Allow kgdb to "take over" this port. If this is 444 * the kgdb device, it has exclusive use. 445 */ 446 if (ISSET(ch->ch_hwflags, SBJCN_HW_KGDB)) 447 sbjcn_enable_debugport(ch); 448 #endif 449 } 450 451 void 452 sbjcn_shutdown(struct sbjcn_channel *ch) 453 { 454 struct tty *tp = ch->ch_tty; 455 int s; 456 457 s = splserial(); 458 459 /* If we were asserting flow control, then deassert it. */ 460 SET(ch->ch_rx_flags, RX_IBUF_BLOCKED); 461 sbjcn_dohwiflow(ch); 462 463 /* Clear any break condition set with TIOCSBRK. */ 464 sbjcn_break(ch, 0); 465 466 /* 467 * Hang up if necessary. Wait a bit, so the other side has time to 468 * notice even if we immediately open the port again. 469 */ 470 if (ISSET(tp->t_cflag, HUPCL)) { 471 sbjcn_modem(ch, 0); 472 (void) tsleep(ch, TTIPRI, ttclos, hz); 473 } 474 475 /* Turn off interrupts. */ 476 #ifdef DDB 477 if (ISSET(ch->ch_hwflags, SBJCN_HW_CONSOLE)) 478 ch->ch_imr = 0x04; /* interrupt on break */ 479 else 480 #endif 481 ch->ch_imr = 0; 482 483 splx(s); 484 } 485 486 int 487 sbjcnopen(dev_t dev, int flag, int mode, struct proc *p) 488 { 489 int unit = SBJCN_UNIT(dev); 490 int chan = SBJCN_CHAN(dev); 491 struct sbjcn_softc *sc; 492 struct sbjcn_channel *ch; 493 struct tty *tp; 494 int s, s2; 495 int error; 496 497 if (unit >= sbjcn_cd.cd_ndevs) 498 return (ENXIO); 499 sc = sbjcn_cd.cd_devs[unit]; 500 if (sc == 0) 501 return (ENXIO); 502 ch = &sc->sc_channels[chan]; 503 if (!ISSET(ch->ch_hwflags, SBJCN_HW_DEV_OK) || ch->ch_rbuf == NULL) 504 return (ENXIO); 505 506 #ifdef KGDB 507 /* 508 * If this is the kgdb port, no other use is permitted. 509 */ 510 if (ISSET(ch->ch_hwflags, SBJCN_HW_KGDB)) 511 return (EBUSY); 512 #endif 513 514 tp = ch->ch_tty; 515 516 if (ISSET(tp->t_state, TS_ISOPEN) && 517 ISSET(tp->t_state, TS_XCLUDE) && 518 p->p_ucred->cr_uid != 0) 519 return (EBUSY); 520 521 s = spltty(); 522 523 /* 524 * Do the following iff this is a first open. 525 */ 526 if (!ISSET(tp->t_state, TS_ISOPEN) && tp->t_wopen == 0) { 527 struct termios t; 528 529 tp->t_dev = dev; 530 531 s2 = splserial(); 532 533 /* Turn on receive, break, and status change interrupts. */ 534 ch->ch_imr = 0xe; 535 536 /* Fetch the current modem control status, needed later. */ 537 ch->ch_iports = 0; 538 ch->ch_iports_delta = 0; 539 splx(s2); 540 541 /* 542 * Initialize the termios status to the defaults. Add in the 543 * sticky bits from TIOCSFLAGS. 544 */ 545 t.c_ispeed = 0; 546 if (ISSET(ch->ch_hwflags, SBJCN_HW_CONSOLE)) { 547 t.c_ospeed = sbjcn_cons_rate; 548 t.c_cflag = sbjcn_cons_cflag; 549 } else { 550 t.c_ospeed = TTYDEF_SPEED; 551 t.c_cflag = TTYDEF_CFLAG; 552 } 553 if (ISSET(ch->ch_swflags, TIOCFLAG_CLOCAL)) 554 SET(t.c_cflag, CLOCAL); 555 if (ISSET(ch->ch_swflags, TIOCFLAG_CRTSCTS)) 556 SET(t.c_cflag, CRTSCTS); 557 if (ISSET(ch->ch_swflags, TIOCFLAG_MDMBUF)) 558 SET(t.c_cflag, MDMBUF); 559 /* Make sure sbjcn_param() will do something. */ 560 tp->t_ospeed = 0; 561 (void) sbjcn_param(tp, &t); 562 tp->t_iflag = TTYDEF_IFLAG; 563 tp->t_oflag = TTYDEF_OFLAG; 564 tp->t_lflag = TTYDEF_LFLAG; 565 ttychars(tp); 566 ttsetwater(tp); 567 568 s2 = splserial(); 569 570 /* 571 * Turn on DTR. We must always do this, even if carrier is not 572 * present, because otherwise we'd have to use TIOCSDTR 573 * immediately after setting CLOCAL, which applications do not 574 * expect. We always assert DTR while the device is open 575 * unless explicitly requested to deassert it. 576 */ 577 sbjcn_modem(ch, 1); 578 579 /* Clear the input ring, and unblock. */ 580 ch->ch_rbput = ch->ch_rbget = ch->ch_rbuf; 581 ch->ch_rbavail = sbjcn_rbuf_size; 582 sbjcn_iflush(ch); 583 CLR(ch->ch_rx_flags, RX_ANY_BLOCK); 584 sbjcn_dohwiflow(ch); 585 586 #ifdef SBJCN_DEBUG 587 if (sbjcn_debug) 588 sbjcn_status(ch, "sbjcnopen "); 589 #endif 590 591 splx(s2); 592 } 593 594 splx(s); 595 596 error = ttyopen(tp, SBJCN_DIALOUT(dev), ISSET(flag, O_NONBLOCK)); 597 if (error) 598 goto bad; 599 600 error = (*tp->t_linesw->l_open)(dev, tp); 601 if (error) 602 goto bad; 603 604 return (0); 605 606 bad: 607 if (!ISSET(tp->t_state, TS_ISOPEN) && tp->t_wopen == 0) { 608 /* 609 * We failed to open the device, and nobody else had it opened. 610 * Clean up the state as appropriate. 611 */ 612 sbjcn_shutdown(ch); 613 } 614 615 return (error); 616 } 617 618 int 619 sbjcnclose(dev_t dev, int flag, int mode, struct proc *p) 620 { 621 struct sbjcn_softc *sc = sbjcn_cd.cd_devs[SBJCN_UNIT(dev)]; 622 struct sbjcn_channel *ch = &sc->sc_channels[SBJCN_CHAN(dev)]; 623 struct tty *tp = ch->ch_tty; 624 625 /* XXX This is for cons.c. */ 626 if (!ISSET(tp->t_state, TS_ISOPEN)) 627 return (0); 628 629 (*tp->t_linesw->l_close)(tp, flag); 630 ttyclose(tp); 631 632 if (!ISSET(tp->t_state, TS_ISOPEN) && tp->t_wopen == 0) { 633 /* 634 * Although we got a last close, the device may still be in 635 * use; e.g. if this was the dialout node, and there are still 636 * processes waiting for carrier on the non-dialout node. 637 */ 638 sbjcn_shutdown(ch); 639 } 640 641 return (0); 642 } 643 644 int 645 sbjcnread(dev_t dev, struct uio *uio, int flag) 646 { 647 struct sbjcn_softc *sc = sbjcn_cd.cd_devs[SBJCN_UNIT(dev)]; 648 struct sbjcn_channel *ch = &sc->sc_channels[SBJCN_CHAN(dev)]; 649 struct tty *tp = ch->ch_tty; 650 651 return ((*tp->t_linesw->l_read)(tp, uio, flag)); 652 } 653 654 int 655 sbjcnwrite(dev_t dev, struct uio *uio, int flag) 656 { 657 struct sbjcn_softc *sc = sbjcn_cd.cd_devs[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_write)(tp, uio, flag)); 662 } 663 664 struct tty * 665 sbjcntty(dev_t dev) 666 { 667 struct sbjcn_softc *sc = sbjcn_cd.cd_devs[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); 672 } 673 674 int 675 sbjcnioctl(dev_t dev, u_long cmd, caddr_t data, int flag, struct proc *p) 676 { 677 struct sbjcn_softc *sc = sbjcn_cd.cd_devs[SBJCN_UNIT(dev)]; 678 struct sbjcn_channel *ch = &sc->sc_channels[SBJCN_CHAN(dev)]; 679 struct tty *tp = ch->ch_tty; 680 int error; 681 int s; 682 683 error = (*tp->t_linesw->l_ioctl)(tp, cmd, data, flag, p); 684 if (error >= 0) 685 return (error); 686 687 error = ttioctl(tp, cmd, data, flag, p); 688 if (error >= 0) 689 return (error); 690 691 error = 0; 692 693 s = splserial(); 694 695 switch (cmd) { 696 case TIOCSBRK: 697 sbjcn_break(ch, 1); 698 break; 699 700 case TIOCCBRK: 701 sbjcn_break(ch, 0); 702 break; 703 704 case TIOCSDTR: 705 sbjcn_modem(ch, 1); 706 break; 707 708 case TIOCCDTR: 709 sbjcn_modem(ch, 0); 710 break; 711 712 case TIOCGFLAGS: 713 *(int *)data = ch->ch_swflags; 714 break; 715 716 case TIOCSFLAGS: 717 error = suser(p->p_ucred, &p->p_acflag); 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(cflag, mode1p, mode2p) 850 tcflag_t cflag; 851 u_char *mode1p; 852 u_char *mode2p; 853 { 854 u_char mode1; 855 u_char mode2; 856 int err = 0; 857 858 mode1 = mode2 = 0; 859 860 switch (ISSET(cflag, CSIZE)) { 861 case CS7: 862 mode1 |= 2; /* XXX */ 863 break; 864 default: 865 err = -1; 866 /* FALLTHRU for sanity */ 867 case CS8: 868 mode1 |= 3; /* XXX */ 869 break; 870 } 871 if (!ISSET(cflag, PARENB)) 872 mode1 |= 2 << 3; 873 else { 874 mode1 |= 0 << 3; 875 if (ISSET(cflag, PARODD)) 876 mode1 |= 1 << 2; 877 } 878 879 if (ISSET(cflag, CSTOPB)) 880 mode2 |= 1 << 3; /* two stop bits XXX not std */ 881 882 if (ISSET(cflag, CRTSCTS)) { 883 mode1 |= 1 << 7; 884 mode2 |= 1 << 4; 885 } 886 887 *mode1p = mode1; 888 *mode2p = mode2; 889 return (err); 890 } 891 892 int 893 sbjcn_param(struct tty *tp, struct termios *t) 894 { 895 struct sbjcn_softc *sc = sbjcn_cd.cd_devs[SBJCN_UNIT(tp->t_dev)]; 896 struct sbjcn_channel *ch = &sc->sc_channels[SBJCN_CHAN(tp->t_dev)]; 897 long brc; 898 u_char mode1, mode2; 899 int s; 900 901 /* XXX reset to console parameters if console? */ 902 #if 0 903 XXX disable, enable. 904 #endif 905 906 /* Check requested parameters. */ 907 if (sbjcn_speed(t->c_ospeed, &brc) < 0) 908 return (EINVAL); 909 if (t->c_ispeed && t->c_ispeed != t->c_ospeed) 910 return (EINVAL); 911 912 /* 913 * For the console, always force CLOCAL and !HUPCL, so that the port 914 * is always active. 915 */ 916 if (ISSET(ch->ch_swflags, TIOCFLAG_SOFTCAR) || 917 ISSET(ch->ch_hwflags, SBJCN_HW_CONSOLE)) { 918 SET(t->c_cflag, CLOCAL); 919 CLR(t->c_cflag, HUPCL); 920 } 921 922 /* 923 * If there were no changes, don't do anything. This avoids dropping 924 * input and improves performance when all we did was frob things like 925 * VMIN and VTIME. 926 */ 927 if (tp->t_ospeed == t->c_ospeed && 928 tp->t_cflag == t->c_cflag) 929 return (0); 930 931 if (cflag2modes(t->c_cflag, &mode1, &mode2) < 0) 932 return (EINVAL); 933 934 s = splserial(); 935 936 ch->ch_mode1 = mode1; 937 ch->ch_mode2 = mode2; 938 939 /* 940 * If we're not in a mode that assumes a connection is present, then 941 * ignore carrier changes. 942 */ 943 if (ISSET(t->c_cflag, CLOCAL | MDMBUF)) 944 ch->ch_i_dcd = 0; 945 else 946 ch->ch_i_dcd = ch->ch_i_dcd_pin; 947 /* 948 * Set the flow control pins depending on the current flow control 949 * mode. 950 */ 951 if (ISSET(t->c_cflag, CRTSCTS)) { 952 ch->ch_o_dtr = ch->ch_o_dtr_pin; 953 ch->ch_o_rts = ch->ch_o_rts_pin; 954 ch->ch_i_cts = ch->ch_i_cts_pin; 955 /* hw controle enable bits in mod regs set by cflag2modes */ 956 } else if (ISSET(t->c_cflag, MDMBUF)) { 957 /* 958 * For DTR/DCD flow control, make sure we don't toggle DTR for 959 * carrier detection. 960 */ 961 ch->ch_o_dtr = 0; 962 ch->ch_o_rts = ch->ch_o_dtr_pin; 963 ch->ch_i_cts = ch->ch_i_dcd_pin; 964 } else { 965 /* 966 * If no flow control, then always set RTS. This will make 967 * the other side happy if it mistakenly thinks we're doing 968 * RTS/CTS flow control. 969 */ 970 ch->ch_o_dtr = ch->ch_o_dtr_pin | ch->ch_o_rts_pin; 971 ch->ch_o_rts = 0; 972 ch->ch_i_cts = 0; 973 if (ISSET(ch->ch_oports, ch->ch_o_dtr_pin)) 974 SET(ch->ch_oports, ch->ch_o_rts_pin); 975 else 976 CLR(ch->ch_oports, ch->ch_o_rts_pin); 977 } 978 /* XXX maybe mask the ports which generate intrs? */ 979 980 ch->ch_brc = brc; 981 982 /* XXX maybe set fifo-full receive mode if RTSCTS and high speed? */ 983 984 /* And copy to tty. */ 985 tp->t_ispeed = 0; 986 tp->t_ospeed = t->c_ospeed; 987 tp->t_cflag = t->c_cflag; 988 989 if (!ch->ch_heldchange) { 990 if (ch->ch_tx_busy) { 991 ch->ch_heldtbc = ch->ch_tbc; 992 ch->ch_tbc = 0; 993 ch->ch_heldchange = 1; 994 } else 995 sbjcn_loadchannelregs(ch); 996 } 997 998 if (!ISSET(t->c_cflag, CHWFLOW)) { 999 /* Disable the high water mark. */ 1000 ch->ch_r_hiwat = 0; 1001 ch->ch_r_lowat = 0; 1002 if (ISSET(ch->ch_rx_flags, RX_TTY_OVERFLOWED)) { 1003 CLR(ch->ch_rx_flags, RX_TTY_OVERFLOWED); 1004 sbjcn_schedrx(ch); 1005 } 1006 if (ISSET(ch->ch_rx_flags, RX_TTY_BLOCKED|RX_IBUF_BLOCKED)) { 1007 CLR(ch->ch_rx_flags, RX_TTY_BLOCKED|RX_IBUF_BLOCKED); 1008 sbjcn_dohwiflow(ch); 1009 } 1010 } else { 1011 ch->ch_r_hiwat = sbjcn_rbuf_hiwat; 1012 ch->ch_r_lowat = sbjcn_rbuf_lowat; 1013 } 1014 1015 splx(s); 1016 1017 /* 1018 * Update the tty layer's idea of the carrier bit, in case we changed 1019 * CLOCAL or MDMBUF. We don't hang up here; we only do that by 1020 * explicit request. 1021 */ 1022 (void) (*tp->t_linesw->l_modem)(tp, 1023 ISSET(ch->ch_iports, ch->ch_i_dcd)); 1024 1025 #ifdef SBJCN_DEBUG 1026 if (sbjcn_debug) 1027 sbjcn_status(ch, "sbjcnparam "); 1028 #endif 1029 1030 if (!ISSET(t->c_cflag, CHWFLOW)) { 1031 if (ch->ch_tx_stopped) { 1032 ch->ch_tx_stopped = 0; 1033 sbjcn_start(tp); 1034 } 1035 } 1036 1037 return (0); 1038 } 1039 1040 void 1041 sbjcn_iflush(struct sbjcn_channel *ch) 1042 { 1043 uint64_t reg; 1044 int timo; 1045 1046 timo = 50000; 1047 /* flush any pending I/O */ 1048 while (((reg = READ_REG(ch->ch_input_reg)) != 0) && --timo) 1049 ; 1050 1051 #ifdef DIAGNOSTIC 1052 if (!timo) 1053 printf("%s: sbjcn_iflush timeout %02x\n", 1054 ch->ch_sc->sc_dev.dv_xname, reg); 1055 #endif 1056 } 1057 1058 void 1059 sbjcn_loadchannelregs(struct sbjcn_channel *ch) 1060 { 1061 } 1062 1063 int 1064 sbjcn_hwiflow(struct tty *tp, int block) 1065 { 1066 struct sbjcn_softc *sc = sbjcn_cd.cd_devs[SBJCN_UNIT(tp->t_dev)]; 1067 struct sbjcn_channel *ch = &sc->sc_channels[SBJCN_CHAN(tp->t_dev)]; 1068 int s; 1069 1070 if (ch->ch_o_rts == 0) 1071 return (0); 1072 1073 s = splserial(); 1074 if (block) { 1075 if (!ISSET(ch->ch_rx_flags, RX_TTY_BLOCKED)) { 1076 SET(ch->ch_rx_flags, RX_TTY_BLOCKED); 1077 sbjcn_dohwiflow(ch); 1078 } 1079 } else { 1080 if (ISSET(ch->ch_rx_flags, RX_TTY_OVERFLOWED)) { 1081 CLR(ch->ch_rx_flags, RX_TTY_OVERFLOWED); 1082 sbjcn_schedrx(ch); 1083 } 1084 if (ISSET(ch->ch_rx_flags, RX_TTY_BLOCKED)) { 1085 CLR(ch->ch_rx_flags, RX_TTY_BLOCKED); 1086 sbjcn_dohwiflow(ch); 1087 } 1088 } 1089 splx(s); 1090 return (1); 1091 } 1092 1093 /* 1094 * (un)block input via hw flowcontrol 1095 */ 1096 void 1097 sbjcn_dohwiflow(struct sbjcn_channel *ch) 1098 { 1099 1100 if (ch->ch_o_rts == 0) 1101 return; 1102 1103 if (ISSET(ch->ch_rx_flags, RX_ANY_BLOCK)) { 1104 CLR(ch->ch_oports, ch->ch_o_rts); 1105 CLR(ch->ch_oports_active, ch->ch_o_rts); 1106 } else { 1107 SET(ch->ch_oports, ch->ch_o_rts); 1108 SET(ch->ch_oports_active, ch->ch_o_rts); 1109 } 1110 } 1111 1112 void 1113 sbjcn_start(struct tty *tp) 1114 { 1115 struct sbjcn_softc *sc = sbjcn_cd.cd_devs[SBJCN_UNIT(tp->t_dev)]; 1116 struct sbjcn_channel *ch = &sc->sc_channels[SBJCN_CHAN(tp->t_dev)]; 1117 int s; 1118 1119 s = spltty(); 1120 if (ISSET(tp->t_state, TS_BUSY | TS_TIMEOUT | TS_TTSTOP)) 1121 goto out; 1122 if (ch->ch_tx_stopped) 1123 goto out; 1124 1125 if (tp->t_outq.c_cc <= tp->t_lowat) { 1126 if (ISSET(tp->t_state, TS_ASLEEP)) { 1127 CLR(tp->t_state, TS_ASLEEP); 1128 wakeup(&tp->t_outq); 1129 } 1130 selwakeup(&tp->t_wsel); 1131 if (tp->t_outq.c_cc == 0) 1132 goto out; 1133 } 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 = sbjcn_cd.cd_devs[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(arg) 1200 void *arg; 1201 { 1202 struct sbjcn_channel *ch = arg; 1203 struct sbjcn_softc *sc = ch->ch_sc; 1204 int overflows, floods; 1205 int s; 1206 1207 s = splserial(); 1208 overflows = ch->ch_overflows; 1209 ch->ch_overflows = 0; 1210 floods = ch->ch_floods; 1211 ch->ch_floods = 0; 1212 ch->ch_errors = 0; 1213 splx(s); 1214 1215 log(LOG_WARNING, "%s: channel %d: %d fifo overflow%s, %d ibuf flood%s\n", 1216 sc->sc_dev.dv_xname, ch->ch_num, 1217 overflows, overflows == 1 ? "" : "s", 1218 floods, floods == 1 ? "" : "s"); 1219 } 1220 1221 integrate void 1222 sbjcn_rxsoft(struct sbjcn_channel *ch, struct tty *tp) 1223 { 1224 int (*rint)(int c, struct tty *tp) = tp->t_linesw->l_rint; 1225 u_char *get, *end; 1226 u_int cc, scc; 1227 u_char sr; 1228 int code; 1229 int s; 1230 1231 end = ch->ch_ebuf; 1232 get = ch->ch_rbget; 1233 scc = cc = sbjcn_rbuf_size - ch->ch_rbavail; 1234 1235 if (cc == sbjcn_rbuf_size) { 1236 ch->ch_floods++; 1237 if (ch->ch_errors++ == 0) 1238 callout_reset(&ch->ch_diag_callout, 60 * hz, 1239 sbjcn_diag, ch); 1240 } 1241 1242 while (cc) { 1243 code = get[0]; 1244 sr = get[1]; 1245 if (ISSET(sr, 0xf0)) { 1246 if (ISSET(sr, 0x10)) { 1247 ch->ch_overflows++; 1248 if (ch->ch_errors++ == 0) 1249 callout_reset(&ch->ch_diag_callout, 1250 60 * hz, sbjcn_diag, ch); 1251 } 1252 if (ISSET(sr, 0xc0)) 1253 SET(code, TTY_FE); 1254 if (ISSET(sr, 0x20)) 1255 SET(code, TTY_PE); 1256 } 1257 if ((*rint)(code, tp) == -1) { 1258 /* 1259 * The line discipline's buffer is out of space. 1260 */ 1261 if (!ISSET(ch->ch_rx_flags, RX_TTY_BLOCKED)) { 1262 /* 1263 * We're either not using flow control, or the 1264 * line discipline didn't tell us to block for 1265 * some reason. Either way, we have no way to 1266 * know when there's more space available, so 1267 * just drop the rest of the data. 1268 */ 1269 get += cc << 1; 1270 if (get >= end) 1271 get -= sbjcn_rbuf_size << 1; 1272 cc = 0; 1273 } else { 1274 /* 1275 * Don't schedule any more receive processing 1276 * until the line discipline tells us there's 1277 * space available (through comhwiflow()). 1278 * Leave the rest of the data in the input 1279 * buffer. 1280 */ 1281 SET(ch->ch_rx_flags, RX_TTY_OVERFLOWED); 1282 } 1283 break; 1284 } 1285 get += 2; 1286 if (get >= end) 1287 get = ch->ch_rbuf; 1288 cc--; 1289 } 1290 1291 if (cc != scc) { 1292 ch->ch_rbget = get; 1293 s = splserial(); 1294 cc = ch->ch_rbavail += scc - cc; 1295 /* Buffers should be ok again, release possible block. */ 1296 if (cc >= ch->ch_r_lowat) { 1297 if (ISSET(ch->ch_rx_flags, RX_IBUF_OVERFLOWED)) { 1298 CLR(ch->ch_rx_flags, RX_IBUF_OVERFLOWED); 1299 SET(ch->ch_imr, 0x02); 1300 } 1301 if (ISSET(ch->ch_rx_flags, RX_IBUF_BLOCKED)) { 1302 CLR(ch->ch_rx_flags, RX_IBUF_BLOCKED); 1303 sbjcn_dohwiflow(ch); 1304 } 1305 } 1306 splx(s); 1307 } 1308 } 1309 1310 integrate void 1311 sbjcn_txsoft(struct sbjcn_channel *ch, struct tty *tp) 1312 { 1313 1314 CLR(tp->t_state, TS_BUSY); 1315 if (ISSET(tp->t_state, TS_FLUSH)) 1316 CLR(tp->t_state, TS_FLUSH); 1317 else 1318 ndflush(&tp->t_outq, (int)(ch->ch_tba - tp->t_outq.c_cf)); 1319 (*tp->t_linesw->l_start)(tp); 1320 } 1321 1322 integrate void 1323 sbjcn_stsoft(struct sbjcn_channel *ch, struct tty *tp) 1324 { 1325 u_char iports, delta; 1326 int s; 1327 1328 s = splserial(); 1329 iports = ch->ch_iports; 1330 delta = ch->ch_iports_delta; 1331 ch->ch_iports_delta = 0; 1332 splx(s); 1333 1334 if (ISSET(delta, ch->ch_i_dcd)) { 1335 /* 1336 * Inform the tty layer that carrier detect changed. 1337 */ 1338 (void) (*tp->t_linesw->l_modem)(tp, 1339 ISSET(iports, ch->ch_i_dcd)); 1340 } 1341 1342 if (ISSET(delta, ch->ch_i_cts)) { 1343 /* Block or unblock output according to flow control. */ 1344 if (ISSET(iports, ch->ch_i_cts)) { 1345 ch->ch_tx_stopped = 0; 1346 (*tp->t_linesw->l_start)(tp); 1347 } else { 1348 ch->ch_tx_stopped = 1; 1349 } 1350 } 1351 1352 #ifdef SBJCN_DEBUG 1353 if (sbjcn_debug) 1354 sbjcn_status(ch, "sbjcn_stsoft"); 1355 #endif 1356 } 1357 1358 integrate void 1359 sbjcn_recv(struct sbjcn_channel *ch) 1360 { 1361 u_char *put, *end; 1362 u_int cc; 1363 1364 end = ch->ch_ebuf; 1365 put = ch->ch_rbput; 1366 cc = ch->ch_rbavail; 1367 1368 /* XXX process break */ 1369 1370 sbjcncn_grabdword(ch); 1371 if (ch->ch_waiting_input) { 1372 if (!ISSET(ch->ch_rx_flags, RX_IBUF_OVERFLOWED)) { 1373 while (cc > 0) { 1374 put[0] = sbjcncn_nextbyte(ch); 1375 put[1] = 1; /* XXXKW ? */ 1376 put += 2; 1377 if (put >= end) 1378 put = ch->ch_rbuf; 1379 cc--; 1380 1381 if (!ch->ch_waiting_input) 1382 break; 1383 } 1384 1385 /* 1386 * Current string of incoming characters ended 1387 * because no more data was available or we 1388 * ran out of space. Schedule a receive event 1389 * if any data was received. If we're out of 1390 * space, turn off receive interrupts. 1391 */ 1392 ch->ch_rbput = put; 1393 ch->ch_rbavail = cc; 1394 if (!ISSET(ch->ch_rx_flags, RX_TTY_OVERFLOWED)) 1395 ch->ch_rx_ready = 1; 1396 1397 /* 1398 * See if we are in danger of overflowing a 1399 * buffer. If so, use hardware flow control 1400 * to ease the pressure. 1401 */ 1402 if (!ISSET(ch->ch_rx_flags, RX_IBUF_BLOCKED) && 1403 cc < ch->ch_r_hiwat) { 1404 SET(ch->ch_rx_flags, RX_IBUF_BLOCKED); 1405 sbjcn_dohwiflow(ch); 1406 } 1407 1408 /* 1409 * If we're out of space, disable receive 1410 * interrupts until the queue has drained 1411 * a bit. 1412 */ 1413 if (!cc) { 1414 SET(ch->ch_rx_flags, 1415 RX_IBUF_OVERFLOWED); 1416 CLR(ch->ch_imr, 0x02); 1417 } 1418 } else { 1419 /* XXX panic? */ 1420 CLR(ch->ch_imr, 0x02); 1421 // continue; 1422 } 1423 } 1424 1425 /* 1426 * If we've delayed a parameter change, do it now, and restart 1427 * output. 1428 */ 1429 if (ch->ch_heldchange) { 1430 sbjcn_loadchannelregs(ch); 1431 ch->ch_heldchange = 0; 1432 ch->ch_tbc = ch->ch_heldtbc; 1433 ch->ch_heldtbc = 0; 1434 } 1435 } 1436 1437 void 1438 sbjcn_callout(void *arg) 1439 { 1440 struct sbjcn_channel *ch = arg; 1441 struct tty *tp = ch->ch_tty; 1442 1443 /* XXX get stuff */ 1444 sbjcn_recv(ch); 1445 1446 /* XXX check receive */ 1447 if (ch->ch_rx_ready) { 1448 ch->ch_rx_ready = 0; 1449 sbjcn_rxsoft(ch, tp); 1450 } 1451 1452 /* XXX check transmit */ 1453 if (ch->ch_tx_done) { 1454 ch->ch_tx_done = 0; 1455 sbjcn_txsoft(ch, tp); 1456 } 1457 1458 callout_reset(&ch->ch_callout, hz/10, sbjcn_callout, ch); 1459 } 1460 1461 static char sbjcncn_nextbyte(struct sbjcn_channel *ch) 1462 { 1463 char c; 1464 1465 sbjcncn_grabdword(ch); 1466 c = (ch->ch_input_buf >> 56) & 0xff; 1467 ch->ch_input_buf <<= 8; 1468 ch->ch_waiting_input--; 1469 return c; 1470 } 1471 1472 static void sbjcncn_grabdword(struct sbjcn_channel *ch) 1473 { 1474 uint64_t inbuf; 1475 1476 if (ch->ch_waiting_input) 1477 return; 1478 1479 inbuf = READ_REG(ch->ch_input_reg); 1480 ch->ch_waiting_input = jtag_input_len(inbuf); 1481 ch->ch_input_buf = inbuf << 8; 1482 } 1483 1484 /* 1485 * Initialize UART for use as console or KGDB line. 1486 */ 1487 int 1488 sbjcn_init(u_long addr, int chan, int rate, tcflag_t cflag) 1489 { 1490 /* XXXKW Anything to do here? */ 1491 return (0); 1492 } 1493 1494 /* 1495 * Following are all routines needed for sbjcn to act as console 1496 */ 1497 int 1498 sbjcn_cnattach(u_long addr, int chan, int rate, tcflag_t cflag) 1499 { 1500 int res; 1501 uint64_t ctrl_val; 1502 static struct consdev sbjcn_cons = { 1503 NULL, NULL, sbjcn_cngetc, sbjcn_cnputc, sbjcn_cnpollc, NULL, 1504 NODEV, CN_NORMAL 1505 }; 1506 1507 res = sbjcn_init(addr, chan, rate, cflag); 1508 if (res) 1509 return (res); 1510 1511 cn_tab = &sbjcn_cons; 1512 1513 sbjcn_cons_present = 1; 1514 sbjcn_cons_addr = addr; 1515 sbjcn_cons_waiting_input = 0; 1516 sbjcn_cons_chan = chan; 1517 sbjcn_cons_rate = rate; 1518 sbjcn_cons_cflag = cflag; 1519 1520 /* Wait for sign of life from the other end */ 1521 while ((ctrl_val = READ_REG(MIPS_PHYS_TO_KSEG1(sbjcn_cons_addr + JTAG_CONS_CONTROL))) == 0) 1522 ; 1523 1524 return (ctrl_val != JTAG_CONS_MAGICNUM); 1525 } 1526 1527 int 1528 sbjcn_cngetc(dev_t dev) 1529 { 1530 char c; 1531 1532 while (sbjcn_cons_waiting_input == 0) 1533 sbjcn_cngrabdword(); 1534 1535 c = (sbjcn_cons_input_buf >> 56) & 0xff; 1536 sbjcn_cons_input_buf <<= 8; 1537 sbjcn_cons_waiting_input--; 1538 1539 return c; 1540 } 1541 1542 /* 1543 * Console kernel output character routine. 1544 */ 1545 void 1546 sbjcn_cnputc(dev_t dev, int c) 1547 { 1548 uint64_t outbuf; 1549 1550 outbuf = (1LL << 56) | (((uint64_t)c) << 48); 1551 WRITE_REG(MIPS_PHYS_TO_KSEG1(sbjcn_cons_addr + JTAG_CONS_OUTPUT), outbuf); 1552 } 1553 1554 void 1555 sbjcn_cnpollc(dev_t dev, int on) 1556 { 1557 1558 } 1559 1560 static void sbjcn_cngrabdword(void) 1561 { 1562 uint64_t inbuf; 1563 1564 if (sbjcn_cons_waiting_input) 1565 return; 1566 1567 inbuf = READ_REG(MIPS_PHYS_TO_KSEG1(sbjcn_cons_addr + JTAG_CONS_INPUT)); 1568 sbjcn_cons_waiting_input = jtag_input_len(inbuf); 1569 sbjcn_cons_input_buf = inbuf << 8; 1570 } 1571 1572 #ifdef KGDB 1573 int 1574 sbjcn_kgdb_attach(u_long addr, int chan, int rate, tcflag_t cflag) 1575 { 1576 int res; 1577 1578 if (!sbjcn_cons_present && 1579 sbjcn_cons_addr == addr && sbjcn_cons_chan == chan) 1580 return (EBUSY); /* cannot share with console */ 1581 1582 res = sbjcn_init(addr, chan, rate, cflag); 1583 if (res) 1584 return (res); 1585 1586 kgdb_attach(sbjcn_kgdb_getc, sbjcn_kgdb_putc, NULL); 1587 kgdb_dev = 123; /* unneeded, only to satisfy some tests */ 1588 kgdb_rate = rate; 1589 1590 sbjcn_kgdb_present = 1; 1591 /* XXX sbjcn_init wants addr, but we need the offset addr */ 1592 sbjcn_kgdb_addr = addr + (chan * 0x100); 1593 sbjcn_kgdb_chan = chan; 1594 1595 return (0); 1596 } 1597 1598 /* ARGSUSED */ 1599 int 1600 sbjcn_kgdb_getc(arg) 1601 void *arg; 1602 { 1603 1604 return (sbjcn_common_getc(sbjcn_kgdb_addr, sbjcn_kgdb_chan)); 1605 } 1606 1607 /* ARGSUSED */ 1608 void 1609 sbjcn_kgdb_putc(arg, c) 1610 void *arg; 1611 int c; 1612 { 1613 1614 sbjcn_common_putc(sbjcn_kgdb_addr, sbjcn_kgdb_chan, c); 1615 } 1616 #endif /* KGDB */ 1617 1618 /* 1619 * helper function to identify the sbjcn channels used by 1620 * console or KGDB (and not yet autoconf attached) 1621 */ 1622 int 1623 sbjcn_is_console(u_long addr, int chan) 1624 { 1625 1626 if (sbjcn_cons_present && !sbjcn_cons_attached && 1627 sbjcn_cons_addr == addr && sbjcn_cons_chan == chan) 1628 return (1); 1629 #ifdef KGDB 1630 if (sbjcn_kgdb_present && !sbjcn_kgdb_attached && 1631 sbjcn_kgdb_addr == addr && sbjcn_kgdb_chan == chan) 1632 return (1); 1633 #endif 1634 return (0); 1635 } 1636