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