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