1 /* $NetBSD: sbscn.c,v 1.15 2005/12/11 12:18:13 christos 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 * `sbscn' driver, supports SiByte SB-1250 SOC DUART. 106 * 107 * This DUART is quite similar in programming model to the scn2681/68681 108 * DUARTs supported by the NetBSD/amiga `mfc' and NetBSD/pc532 `scn' 109 * driver, but substantial rework would have been necessary to make 110 * those drivers sane w.r.t. bus_space (which would then have been 111 * required on NetBSD/sbmips very early on), and to accommodate the 112 * different register mappings. 113 * 114 * So, another driver. Eventually there should be One True Driver, 115 * but we're not here to save the world. 116 */ 117 118 #include <sys/cdefs.h> 119 __KERNEL_RCSID(0, "$NetBSD: sbscn.c,v 1.15 2005/12/11 12:18:13 christos Exp $"); 120 121 #define SBSCN_DEBUG 122 123 #include "opt_ddb.h" 124 125 #include "rnd.h" 126 #if NRND > 0 && defined(RND_SBSCN) 127 #include <sys/rnd.h> 128 #endif 129 130 #include <sys/param.h> 131 #include <sys/systm.h> 132 #include <sys/ioctl.h> 133 #include <sys/select.h> 134 #include <sys/tty.h> 135 #include <sys/proc.h> 136 #include <sys/user.h> 137 #include <sys/conf.h> 138 #include <sys/file.h> 139 #include <sys/uio.h> 140 #include <sys/kernel.h> 141 #include <sys/syslog.h> 142 #include <sys/types.h> 143 #include <sys/device.h> 144 #include <sys/malloc.h> 145 #include <sys/vnode.h> 146 147 #include <mips/sibyte/dev/sbobiovar.h> 148 #if 0 149 #include <mips/sibyte/dev/sbscnreg.h> 150 #endif 151 #include <mips/sibyte/dev/sbscnvar.h> 152 #include <dev/cons.h> 153 #include <machine/locore.h> 154 155 void sbscn_attach_channel(struct sbscn_softc *sc, int chan, int intr); 156 #if defined(DDB) || defined(KGDB) 157 static void sbscn_enable_debugport(struct sbscn_channel *ch); 158 #endif 159 void sbscn_config(struct sbscn_channel *ch); 160 void sbscn_shutdown(struct sbscn_channel *ch); 161 int sbscn_speed(long, long *); 162 static int cflag2modes(tcflag_t, u_char *, u_char *); 163 int sbscn_param(struct tty *, struct termios *); 164 void sbscn_start(struct tty *); 165 int sbscn_hwiflow(struct tty *, int); 166 167 void sbscn_loadchannelregs(struct sbscn_channel *); 168 void sbscn_dohwiflow(struct sbscn_channel *); 169 void sbscn_break(struct sbscn_channel *, int); 170 void sbscn_modem(struct sbscn_channel *, int); 171 void tiocm_to_sbscn(struct sbscn_channel *, int, int); 172 int sbscn_to_tiocm(struct sbscn_channel *); 173 void sbscn_iflush(struct sbscn_channel *); 174 175 int sbscn_init(u_long addr, int chan, int rate, tcflag_t cflag); 176 int sbscn_common_getc(u_long addr, int chan); 177 void sbscn_common_putc(u_long addr, int chan, int c); 178 void sbscn_intr(void *arg, uint32_t status, uint32_t pc); 179 180 int sbscn_cngetc(dev_t dev); 181 void sbscn_cnputc(dev_t dev, int c); 182 void sbscn_cnpollc(dev_t dev, int on); 183 184 extern struct cfdriver sbscn_cd; 185 186 dev_type_open(sbscnopen); 187 dev_type_close(sbscnclose); 188 dev_type_read(sbscnread); 189 dev_type_write(sbscnwrite); 190 dev_type_ioctl(sbscnioctl); 191 dev_type_stop(sbscnstop); 192 dev_type_tty(sbscntty); 193 dev_type_poll(sbscnpoll); 194 195 const struct cdevsw sbscn_cdevsw = { 196 sbscnopen, sbscnclose, sbscnread, sbscnwrite, sbscnioctl, 197 sbscnstop, sbscntty, sbscnpoll, nommap, ttykqfilter, D_TTY 198 }; 199 200 #define integrate static inline 201 void sbscn_soft(void *); 202 integrate void sbscn_rxsoft(struct sbscn_channel *, struct tty *); 203 integrate void sbscn_txsoft(struct sbscn_channel *, struct tty *); 204 integrate void sbscn_stsoft(struct sbscn_channel *, struct tty *); 205 integrate void sbscn_schedrx(struct sbscn_channel *); 206 void sbscn_diag(void *); 207 208 /* 209 * Make this an option variable one can patch. 210 * But be warned: this must be a power of 2! 211 */ 212 u_int sbscn_rbuf_size = SBSCN_RING_SIZE; 213 214 /* Stop input when 3/4 of the ring is full; restart when only 1/4 is full. */ 215 u_int sbscn_rbuf_hiwat = (SBSCN_RING_SIZE * 1) / 4; 216 u_int sbscn_rbuf_lowat = (SBSCN_RING_SIZE * 3) / 4; 217 218 static int sbscn_cons_present; 219 static int sbscn_cons_attached; 220 static u_long sbscn_cons_addr; 221 static int sbscn_cons_chan; 222 static int sbscn_cons_rate; 223 static tcflag_t sbscn_cons_cflag; 224 225 #ifdef KGDB 226 #include <sys/kgdb.h> 227 228 static int sbscn_kgdb_present; 229 static int sbscn_kgdb_attached; 230 static u_long sbscn_kgdb_addr; 231 static int sbscn_kgdb_chan; 232 233 int sbscn_kgdb_getc(void *); 234 void sbscn_kgdb_putc(void *, int); 235 #endif /* KGDB */ 236 237 static int sbscn_match(struct device *, struct cfdata *, void *); 238 static void sbscn_attach(struct device *, struct device *, void *); 239 240 CFATTACH_DECL(sbscn, sizeof(struct sbscn_softc), 241 sbscn_match, sbscn_attach, NULL, NULL); 242 243 #define READ_REG(rp) (mips3_ld((int64_t *)__UNVOLATILE(rp))) 244 #define WRITE_REG(rp, val) (mips3_sd((uint64_t *)__UNVOLATILE(rp), (val))) 245 246 /* 247 * input and output signals are actually the _inverse_ of the bits in the 248 * input and output port registers! 249 */ 250 #define GET_INPUT_SIGNALS(ch) \ 251 ((~READ_REG(MIPS_PHYS_TO_KSEG1((ch)->ch_sc->sc_addr + 0x280))) & (ch)->ch_i_mask) 252 #define SET_OUTPUT_SIGNALS(ch, val) \ 253 do { \ 254 int sigs_to_set, sigs_to_clr; \ 255 \ 256 sigs_to_set = (ch)->ch_o_mask & val; \ 257 sigs_to_clr = (ch)->ch_o_mask & ~val; \ 258 \ 259 /* set signals by clearing op bits, and vice versa */ \ 260 WRITE_REG(MIPS_PHYS_TO_KSEG1((ch)->ch_sc->sc_addr + 0x2c0), \ 261 sigs_to_set); \ 262 WRITE_REG(MIPS_PHYS_TO_KSEG1((ch)->ch_sc->sc_addr + 0x2b0), \ 263 sigs_to_clr); \ 264 } while (0) 265 266 static int 267 sbscn_match(struct device *parent, struct cfdata *match, void *aux) 268 { 269 struct sbobio_attach_args *sap = aux; 270 271 if (sap->sa_locs.sa_type != SBOBIO_DEVTYPE_DUART) 272 return (0); 273 274 return 1; 275 } 276 277 static void 278 sbscn_attach(struct device *parent, struct device *self, void *aux) 279 { 280 struct sbscn_softc *sc = (struct sbscn_softc *)self; 281 struct sbobio_attach_args *sap = aux; 282 int i; 283 284 sc->sc_addr = sap->sa_base + sap->sa_locs.sa_offset; 285 286 printf("\n"); 287 for (i = 0; i < 2; i++) 288 sbscn_attach_channel(sc, i, sap->sa_locs.sa_intr[i]); 289 290 /* init duart_opcr */ 291 WRITE_REG(MIPS_PHYS_TO_KSEG1(sc->sc_addr + 0x270), 0); 292 /* init duart_aux_ctrl */ 293 WRITE_REG(MIPS_PHYS_TO_KSEG1(sc->sc_addr + 0x210), 0x0f); /* XXX */ 294 } 295 296 void 297 sbscn_attach_channel(struct sbscn_softc *sc, int chan, int intr) 298 { 299 struct sbscn_channel *ch = &sc->sc_channels[chan]; 300 u_long chan_addr; 301 struct tty *tp; 302 303 ch->ch_sc = sc; 304 ch->ch_num = chan; 305 306 chan_addr = sc->sc_addr + (0x100 * chan); 307 ch->ch_base = (void *)MIPS_PHYS_TO_KSEG1(chan_addr); 308 ch->ch_isr_base = 309 (void *)MIPS_PHYS_TO_KSEG1(sc->sc_addr + 0x220 + (0x20 * chan)); 310 ch->ch_imr_base = 311 (void *)MIPS_PHYS_TO_KSEG1(sc->sc_addr + 0x230 + (0x20 * chan)); 312 #ifdef XXXCGDnotyet 313 ch->ch_inchg_base = 314 (void *)MIPS_PHYS_TO_KSEG1(sc->sc_addr + 0x2d0 + (0x10 * chan)); 315 #endif 316 317 ch->ch_i_dcd = ch->ch_i_dcd_pin = 0 /* XXXCGD */; 318 ch->ch_i_cts = ch->ch_i_cts_pin = 0 /* XXXCGD */; 319 ch->ch_i_dsr = ch->ch_i_dsr_pin = 0 /* XXXCGD */; 320 ch->ch_i_ri = ch->ch_i_ri_pin = 0 /* XXXCGD */; 321 ch->ch_i_mask = 322 ch->ch_i_dcd | ch->ch_i_cts | ch->ch_i_dsr | ch->ch_i_ri; 323 ch->ch_o_dtr = ch->ch_o_dtr_pin = 0 /* XXXCGD */; 324 ch->ch_o_rts = ch->ch_o_rts_pin = 0 /* XXXCGD */; 325 ch->ch_o_mask = ch->ch_o_dtr | ch->ch_o_rts; 326 327 ch->ch_intrhand = cpu_intr_establish(intr, IPL_SERIAL, sbscn_intr, ch); 328 callout_init(&ch->ch_diag_callout); 329 330 /* Disable interrupts before configuring the device. */ 331 ch->ch_imr = 0; 332 WRITE_REG(ch->ch_imr_base, ch->ch_imr); 333 334 if (sbscn_cons_present && 335 sbscn_cons_addr == chan_addr && sbscn_cons_chan == chan) { 336 sbscn_cons_attached = 1; 337 338 /* Make sure the console is always "hardwired". */ 339 delay(1000); /* wait for output to finish */ 340 SET(ch->ch_hwflags, SBSCN_HW_CONSOLE); 341 SET(ch->ch_swflags, TIOCFLAG_SOFTCAR); 342 } 343 344 tp = ttymalloc(); 345 tp->t_oproc = sbscn_start; 346 tp->t_param = sbscn_param; 347 tp->t_hwiflow = sbscn_hwiflow; 348 349 ch->ch_tty = tp; 350 ch->ch_rbuf = malloc(sbscn_rbuf_size << 1, M_DEVBUF, M_NOWAIT); 351 if (ch->ch_rbuf == NULL) { 352 printf("%s: channel %d: unable to allocate ring buffer\n", 353 sc->sc_dev.dv_xname, chan); 354 return; 355 } 356 ch->ch_ebuf = ch->ch_rbuf + (sbscn_rbuf_size << 1); 357 358 tty_attach(tp); 359 360 if (ISSET(ch->ch_hwflags, SBSCN_HW_CONSOLE)) { 361 int maj; 362 363 /* locate the major number */ 364 maj = cdevsw_lookup_major(&sbscn_cdevsw); 365 366 cn_tab->cn_dev = makedev(maj, (sc->sc_dev.dv_unit << 1) + chan); 367 368 printf("%s: channel %d: console\n", sc->sc_dev.dv_xname, chan); 369 } 370 371 #ifdef KGDB 372 /* 373 * Allow kgdb to "take over" this port. If this is 374 * the kgdb device, it has exclusive use. 375 */ 376 if (sbscn_kgdb_present && 377 sbscn_kgdb_addr == chan_addr && sbscn_kgdb_chan == chan) { 378 sbscn_kgdb_attached = 1; 379 380 SET(sc->sc_hwflags, SBSCN_HW_KGDB); 381 printf("%s: channel %d: kgdb\n", sc->sc_dev.dv_xname, chan); 382 } 383 #endif 384 385 ch->ch_si = softintr_establish(IPL_SOFTSERIAL, sbscn_soft, ch); 386 387 #if NRND > 0 && defined(RND_SBSCN) 388 rnd_attach_source(&ch->ch_rnd_source, sc->sc_dev.dv_xname, 389 RND_TYPE_TTY, 0); 390 #endif 391 392 sbscn_config(ch); 393 394 SET(ch->ch_hwflags, SBSCN_HW_DEV_OK); 395 } 396 397 int 398 sbscn_speed(long speed, long *brcp) 399 { 400 #define divrnd(n, q) (((n)*2/(q)+1)/2) /* divide and round off */ 401 402 int x, err; 403 int frequency = 100000000; 404 405 *brcp = divrnd(frequency / 20, speed) - 1; 406 407 if (speed <= 0) 408 return (-1); 409 x = divrnd(frequency / 20, speed); 410 if (x <= 0) 411 return (-1); 412 err = divrnd(((quad_t)frequency) * 1000 / 20, speed * x) - 1000; 413 if (err < 0) 414 err = -err; 415 if (err > SBSCN_TOLERANCE) 416 return (-1); 417 *brcp = x - 1; 418 return (0); 419 420 #undef divrnd 421 } 422 423 #ifdef SBSCN_DEBUG 424 void sbscn_status(struct sbscn_channel *, const char *); 425 426 int sbscn_debug = 0 /* XXXCGD */; 427 428 void 429 sbscn_status(struct sbscn_channel *ch, const char *str) 430 { 431 struct sbscn_softc *sc = ch->ch_sc; 432 struct tty *tp = ch->ch_tty; 433 434 printf("%s: chan %d: %s %sclocal %sdcd %sts_carr_on %sdtr %stx_stopped\n", 435 sc->sc_dev.dv_xname, ch->ch_num, str, 436 ISSET(tp->t_cflag, CLOCAL) ? "+" : "-", 437 ISSET(ch->ch_iports, ch->ch_i_dcd) ? "+" : "-", 438 ISSET(tp->t_state, TS_CARR_ON) ? "+" : "-", 439 ISSET(ch->ch_oports, ch->ch_o_dtr) ? "+" : "-", 440 ch->ch_tx_stopped ? "+" : "-"); 441 442 printf("%s: chan %d: %s %scrtscts %scts %sts_ttstop %srts %xrx_flags\n", 443 sc->sc_dev.dv_xname, ch->ch_num, str, 444 ISSET(tp->t_cflag, CRTSCTS) ? "+" : "-", 445 ISSET(ch->ch_iports, ch->ch_i_cts) ? "+" : "-", 446 ISSET(tp->t_state, TS_TTSTOP) ? "+" : "-", 447 ISSET(ch->ch_oports, ch->ch_o_rts) ? "+" : "-", 448 ch->ch_rx_flags); 449 } 450 #endif 451 452 #if defined(DDB) || defined(KGDB) 453 static void 454 sbscn_enable_debugport(struct sbscn_channel *ch) 455 { 456 int s; 457 458 /* Turn on line break interrupt, set carrier. */ 459 s = splserial(); 460 461 #if 0 /* DO NOT turn on break interrupt at this time. */ 462 ch->ch_imr = 0x04; 463 #else 464 ch->ch_imr = 0x00; 465 #endif 466 WRITE_REG(ch->ch_imr_base, ch->ch_imr); 467 SET(ch->ch_oports, ch->ch_o_dtr | ch->ch_o_rts); 468 SET_OUTPUT_SIGNALS(ch, ch->ch_oports); 469 470 splx(s); 471 } 472 #endif 473 474 void 475 sbscn_config(struct sbscn_channel *ch) 476 { 477 478 /* Disable interrupts before configuring the device. */ 479 ch->ch_imr = 0x00; 480 WRITE_REG(ch->ch_imr_base, ch->ch_imr); 481 482 #ifdef DDB 483 if (ISSET(ch->ch_hwflags, SBSCN_HW_CONSOLE)) 484 sbscn_enable_debugport(ch); 485 #endif 486 487 #ifdef KGDB 488 /* 489 * Allow kgdb to "take over" this port. If this is 490 * the kgdb device, it has exclusive use. 491 */ 492 if (ISSET(ch->ch_hwflags, SBSCN_HW_KGDB)) 493 sbscn_enable_debugport(ch); 494 #endif 495 } 496 497 void 498 sbscn_shutdown(struct sbscn_channel *ch) 499 { 500 struct tty *tp = ch->ch_tty; 501 int s; 502 503 s = splserial(); 504 505 /* If we were asserting flow control, then deassert it. */ 506 SET(ch->ch_rx_flags, RX_IBUF_BLOCKED); 507 sbscn_dohwiflow(ch); 508 509 /* Clear any break condition set with TIOCSBRK. */ 510 sbscn_break(ch, 0); 511 512 /* 513 * Hang up if necessary. Wait a bit, so the other side has time to 514 * notice even if we immediately open the port again. 515 * Avoid tsleeping above splhigh(). 516 */ 517 if (ISSET(tp->t_cflag, HUPCL)) { 518 sbscn_modem(ch, 0); 519 splx(s); 520 /* XXX tsleep will only timeout */ 521 (void) tsleep(ch, TTIPRI, ttclos, hz); 522 s = splserial(); 523 } 524 525 /* Turn off interrupts. */ 526 #ifdef DDB 527 if (ISSET(ch->ch_hwflags, SBSCN_HW_CONSOLE)) 528 #if 0 /* DO NOT turn on break interrupt at this time. */ 529 ch->ch_imr = 0x04; /* interrupt on break */ 530 #else 531 ch->ch_imr = 0x00; 532 #endif 533 else 534 #endif 535 ch->ch_imr = 0; 536 WRITE_REG(ch->ch_imr_base, ch->ch_imr); 537 538 splx(s); 539 } 540 541 int 542 sbscnopen(dev_t dev, int flag, int mode, struct lwp *l) 543 { 544 int unit = SBSCN_UNIT(dev); 545 int chan = SBSCN_CHAN(dev); 546 struct sbscn_softc *sc; 547 struct sbscn_channel *ch; 548 struct tty *tp; 549 int s, s2; 550 int error; 551 552 if (unit >= sbscn_cd.cd_ndevs) 553 return (ENXIO); 554 sc = sbscn_cd.cd_devs[unit]; 555 if (sc == 0) 556 return (ENXIO); 557 ch = &sc->sc_channels[chan]; 558 if (!ISSET(ch->ch_hwflags, SBSCN_HW_DEV_OK) || ch->ch_rbuf == NULL) 559 return (ENXIO); 560 561 #ifdef KGDB 562 /* 563 * If this is the kgdb port, no other use is permitted. 564 */ 565 if (ISSET(ch->ch_hwflags, SBSCN_HW_KGDB)) 566 return (EBUSY); 567 #endif 568 569 tp = ch->ch_tty; 570 571 if (ISSET(tp->t_state, TS_ISOPEN) && 572 ISSET(tp->t_state, TS_XCLUDE) && 573 suser(l->l_proc->p_ucred, &l->l_proc->p_acflag) != 0) 574 return (EBUSY); 575 576 s = spltty(); 577 578 /* 579 * Do the following iff this is a first open. 580 */ 581 if (!ISSET(tp->t_state, TS_ISOPEN) && tp->t_wopen == 0) { 582 struct termios t; 583 584 tp->t_dev = dev; 585 586 s2 = splserial(); 587 588 /* Turn on receive, break, and status change interrupts. */ 589 #if 0 /* DO NOT turn on break or status change interrupt at this time. */ 590 ch->ch_imr = 0xe; 591 #else 592 ch->ch_imr = 0x2; 593 #endif 594 WRITE_REG(ch->ch_imr_base, ch->ch_imr); 595 596 /* Fetch the current modem control status, needed later. */ 597 ch->ch_iports = GET_INPUT_SIGNALS(ch); 598 ch->ch_iports_delta = 0; 599 splx(s2); 600 601 /* 602 * Initialize the termios status to the defaults. Add in the 603 * sticky bits from TIOCSFLAGS. 604 */ 605 t.c_ispeed = 0; 606 if (ISSET(ch->ch_hwflags, SBSCN_HW_CONSOLE)) { 607 t.c_ospeed = sbscn_cons_rate; 608 t.c_cflag = sbscn_cons_cflag; 609 } else { 610 t.c_ospeed = TTYDEF_SPEED; 611 t.c_cflag = TTYDEF_CFLAG; 612 } 613 if (ISSET(ch->ch_swflags, TIOCFLAG_CLOCAL)) 614 SET(t.c_cflag, CLOCAL); 615 if (ISSET(ch->ch_swflags, TIOCFLAG_CRTSCTS)) 616 SET(t.c_cflag, CRTSCTS); 617 if (ISSET(ch->ch_swflags, TIOCFLAG_MDMBUF)) 618 SET(t.c_cflag, MDMBUF); 619 /* Make sure sbscn_param() will do something. */ 620 tp->t_ospeed = 0; 621 (void) sbscn_param(tp, &t); 622 tp->t_iflag = TTYDEF_IFLAG; 623 tp->t_oflag = TTYDEF_OFLAG; 624 tp->t_lflag = TTYDEF_LFLAG; 625 ttychars(tp); 626 ttsetwater(tp); 627 628 s2 = splserial(); 629 630 /* 631 * Turn on DTR. We must always do this, even if carrier is not 632 * present, because otherwise we'd have to use TIOCSDTR 633 * immediately after setting CLOCAL, which applications do not 634 * expect. We always assert DTR while the device is open 635 * unless explicitly requested to deassert it. 636 */ 637 sbscn_modem(ch, 1); 638 639 /* Clear the input ring, and unblock. */ 640 ch->ch_rbput = ch->ch_rbget = ch->ch_rbuf; 641 ch->ch_rbavail = sbscn_rbuf_size; 642 sbscn_iflush(ch); 643 CLR(ch->ch_rx_flags, RX_ANY_BLOCK); 644 sbscn_dohwiflow(ch); 645 646 #ifdef SBSCN_DEBUG 647 if (sbscn_debug) 648 sbscn_status(ch, "sbscnopen "); 649 #endif 650 651 splx(s2); 652 } 653 654 splx(s); 655 656 error = ttyopen(tp, SBSCN_DIALOUT(dev), ISSET(flag, O_NONBLOCK)); 657 if (error) 658 goto bad; 659 660 error = (*tp->t_linesw->l_open)(dev, tp); 661 if (error) 662 goto bad; 663 664 return (0); 665 666 bad: 667 if (!ISSET(tp->t_state, TS_ISOPEN) && tp->t_wopen == 0) { 668 /* 669 * We failed to open the device, and nobody else had it opened. 670 * Clean up the state as appropriate. 671 */ 672 sbscn_shutdown(ch); 673 } 674 675 return (error); 676 } 677 678 int 679 sbscnclose(dev_t dev, int flag, int mode, struct lwp *l) 680 { 681 struct sbscn_softc *sc = sbscn_cd.cd_devs[SBSCN_UNIT(dev)]; 682 struct sbscn_channel *ch = &sc->sc_channels[SBSCN_CHAN(dev)]; 683 struct tty *tp = ch->ch_tty; 684 685 /* XXX This is for cons.c. */ 686 if (!ISSET(tp->t_state, TS_ISOPEN)) 687 return (0); 688 689 (*tp->t_linesw->l_close)(tp, flag); 690 ttyclose(tp); 691 692 if (!ISSET(tp->t_state, TS_ISOPEN) && tp->t_wopen == 0) { 693 /* 694 * Although we got a last close, the device may still be in 695 * use; e.g. if this was the dialout node, and there are still 696 * processes waiting for carrier on the non-dialout node. 697 */ 698 sbscn_shutdown(ch); 699 } 700 701 return (0); 702 } 703 704 int 705 sbscnread(dev_t dev, struct uio *uio, int flag) 706 { 707 struct sbscn_softc *sc = sbscn_cd.cd_devs[SBSCN_UNIT(dev)]; 708 struct sbscn_channel *ch = &sc->sc_channels[SBSCN_CHAN(dev)]; 709 struct tty *tp = ch->ch_tty; 710 711 return ((*tp->t_linesw->l_read)(tp, uio, flag)); 712 } 713 714 int 715 sbscnwrite(dev_t dev, struct uio *uio, int flag) 716 { 717 struct sbscn_softc *sc = sbscn_cd.cd_devs[SBSCN_UNIT(dev)]; 718 struct sbscn_channel *ch = &sc->sc_channels[SBSCN_CHAN(dev)]; 719 struct tty *tp = ch->ch_tty; 720 721 return ((*tp->t_linesw->l_write)(tp, uio, flag)); 722 } 723 724 int 725 sbscnpoll(dev_t dev, int events, struct lwp *l) 726 { 727 struct sbscn_softc *sc = sbscn_cd.cd_devs[SBSCN_UNIT(dev)]; 728 struct sbscn_channel *ch = &sc->sc_channels[SBSCN_CHAN(dev)]; 729 struct tty *tp = ch->ch_tty; 730 731 return ((*tp->t_linesw->l_poll)(tp, events, l)); 732 } 733 734 struct tty * 735 sbscntty(dev_t dev) 736 { 737 struct sbscn_softc *sc = sbscn_cd.cd_devs[SBSCN_UNIT(dev)]; 738 struct sbscn_channel *ch = &sc->sc_channels[SBSCN_CHAN(dev)]; 739 struct tty *tp = ch->ch_tty; 740 741 return (tp); 742 } 743 744 int 745 sbscnioctl(dev_t dev, u_long cmd, caddr_t data, int flag, struct lwp *l) 746 { 747 struct sbscn_softc *sc = sbscn_cd.cd_devs[SBSCN_UNIT(dev)]; 748 struct sbscn_channel *ch = &sc->sc_channels[SBSCN_CHAN(dev)]; 749 struct tty *tp = ch->ch_tty; 750 int error; 751 int s; 752 753 error = (*tp->t_linesw->l_ioctl)(tp, cmd, data, flag, l); 754 if (error != EPASSTHROUGH) 755 return (error); 756 757 error = ttioctl(tp, cmd, data, flag, l); 758 if (error != EPASSTHROUGH) 759 return (error); 760 761 error = 0; 762 763 s = splserial(); 764 765 switch (cmd) { 766 case TIOCSBRK: 767 sbscn_break(ch, 1); 768 break; 769 770 case TIOCCBRK: 771 sbscn_break(ch, 0); 772 break; 773 774 case TIOCSDTR: 775 sbscn_modem(ch, 1); 776 break; 777 778 case TIOCCDTR: 779 sbscn_modem(ch, 0); 780 break; 781 782 case TIOCGFLAGS: 783 *(int *)data = ch->ch_swflags; 784 break; 785 786 case TIOCSFLAGS: 787 error = suser(l->l_proc->p_ucred, &l->l_proc->p_acflag); 788 if (error) 789 break; 790 ch->ch_swflags = *(int *)data; 791 break; 792 793 case TIOCMSET: 794 case TIOCMBIS: 795 case TIOCMBIC: 796 tiocm_to_sbscn(ch, cmd, *(int *)data); 797 break; 798 799 case TIOCMGET: 800 *(int *)data = sbscn_to_tiocm(ch); 801 break; 802 803 default: 804 error = EPASSTHROUGH; 805 break; 806 } 807 808 splx(s); 809 810 #ifdef SBSCN_DEBUG 811 if (sbscn_debug) 812 sbscn_status(ch, "sbscn_ioctl "); 813 #endif 814 815 return (error); 816 } 817 818 integrate void 819 sbscn_schedrx(struct sbscn_channel *ch) 820 { 821 822 ch->ch_rx_ready = 1; 823 824 /* Wake up the poller. */ 825 softintr_schedule(ch->ch_si); 826 } 827 828 void 829 sbscn_break(struct sbscn_channel *ch, int onoff) 830 { 831 832 /* XXXCGD delay break until not busy */ 833 if (onoff) 834 WRITE_REG(ch->ch_base + 0x50, 0x60); 835 else 836 WRITE_REG(ch->ch_base + 0x50, 0x70); 837 838 #if 0 839 if (!ch->ch_heldchange) { 840 if (ch->ch_tx_busy) { 841 ch->ch_heldtbc = ch->ch_tbc; 842 ch->ch_tbc = 0; 843 ch->ch_heldchange = 1; 844 } else 845 sbscn_loadchannelregs(ch); 846 } 847 #endif 848 } 849 850 void 851 sbscn_modem(struct sbscn_channel *ch, int onoff) 852 { 853 854 if (ch->ch_o_dtr == 0) 855 return; 856 857 if (onoff) 858 SET(ch->ch_oports, ch->ch_o_dtr); 859 else 860 CLR(ch->ch_oports, ch->ch_o_dtr); 861 862 if (!ch->ch_heldchange) { 863 if (ch->ch_tx_busy) { 864 ch->ch_heldtbc = ch->ch_tbc; 865 ch->ch_tbc = 0; 866 ch->ch_heldchange = 1; 867 } else 868 sbscn_loadchannelregs(ch); 869 } 870 } 871 872 void 873 tiocm_to_sbscn(struct sbscn_channel *ch, int how, int ttybits) 874 { 875 u_char bits; 876 877 bits = 0; 878 if (ISSET(ttybits, TIOCM_DTR)) 879 SET(bits, ch->ch_o_dtr); 880 if (ISSET(ttybits, TIOCM_RTS)) 881 SET(bits, ch->ch_o_rts); 882 883 switch (how) { 884 case TIOCMBIC: 885 CLR(ch->ch_oports, bits); 886 break; 887 888 case TIOCMBIS: 889 SET(ch->ch_oports, bits); 890 break; 891 892 case TIOCMSET: 893 ch->ch_oports = bits; 894 break; 895 } 896 897 if (!ch->ch_heldchange) { 898 if (ch->ch_tx_busy) { 899 ch->ch_heldtbc = ch->ch_tbc; 900 ch->ch_tbc = 0; 901 ch->ch_heldchange = 1; 902 } else 903 sbscn_loadchannelregs(ch); 904 } 905 } 906 907 int 908 sbscn_to_tiocm(struct sbscn_channel *ch) 909 { 910 u_char hwbits; 911 int ttybits = 0; 912 913 hwbits = ch->ch_oports; 914 if (ISSET(hwbits, ch->ch_o_dtr)) 915 SET(ttybits, TIOCM_DTR); 916 if (ISSET(hwbits, ch->ch_o_rts)) 917 SET(ttybits, TIOCM_RTS); 918 919 hwbits = ch->ch_iports; 920 if (ISSET(hwbits, ch->ch_i_dcd)) 921 SET(ttybits, TIOCM_CD); 922 if (ISSET(hwbits, ch->ch_i_cts)) 923 SET(ttybits, TIOCM_CTS); 924 if (ISSET(hwbits, ch->ch_i_dsr)) 925 SET(ttybits, TIOCM_DSR); 926 if (ISSET(hwbits, ch->ch_i_ri)) 927 SET(ttybits, TIOCM_RI); 928 929 if (ch->ch_imr != 0) 930 SET(ttybits, TIOCM_LE); 931 932 return (ttybits); 933 } 934 935 static int 936 cflag2modes(cflag, mode1p, mode2p) 937 tcflag_t cflag; 938 u_char *mode1p; 939 u_char *mode2p; 940 { 941 u_char mode1; 942 u_char mode2; 943 int err = 0; 944 945 mode1 = mode2 = 0; 946 947 switch (ISSET(cflag, CSIZE)) { 948 case CS7: 949 mode1 |= 2; /* XXX */ 950 break; 951 default: 952 err = -1; 953 /* FALLTHRU for sanity */ 954 case CS8: 955 mode1 |= 3; /* XXX */ 956 break; 957 } 958 if (!ISSET(cflag, PARENB)) 959 mode1 |= 2 << 3; 960 else { 961 mode1 |= 0 << 3; 962 if (ISSET(cflag, PARODD)) 963 mode1 |= 1 << 2; 964 } 965 966 if (ISSET(cflag, CSTOPB)) 967 mode2 |= 1 << 3; /* two stop bits XXX not std */ 968 969 if (ISSET(cflag, CRTSCTS)) { 970 mode1 |= 1 << 7; 971 mode2 |= 1 << 4; 972 } 973 974 *mode1p = mode1; 975 *mode2p = mode2; 976 return (err); 977 } 978 979 int 980 sbscn_param(struct tty *tp, struct termios *t) 981 { 982 struct sbscn_softc *sc = sbscn_cd.cd_devs[SBSCN_UNIT(tp->t_dev)]; 983 struct sbscn_channel *ch = &sc->sc_channels[SBSCN_CHAN(tp->t_dev)]; 984 long brc; 985 u_char mode1, mode2; 986 int s; 987 988 /* XXX reset to console parameters if console? */ 989 #if 0 990 XXX disable, enable. 991 #endif 992 993 /* Check requested parameters. */ 994 if (sbscn_speed(t->c_ospeed, &brc) < 0) 995 return (EINVAL); 996 if (t->c_ispeed && t->c_ispeed != t->c_ospeed) 997 return (EINVAL); 998 999 /* 1000 * For the console, always force CLOCAL and !HUPCL, so that the port 1001 * is always active. 1002 */ 1003 if (ISSET(ch->ch_swflags, TIOCFLAG_SOFTCAR) || 1004 ISSET(ch->ch_hwflags, SBSCN_HW_CONSOLE)) { 1005 SET(t->c_cflag, CLOCAL); 1006 CLR(t->c_cflag, HUPCL); 1007 } 1008 1009 /* 1010 * If there were no changes, don't do anything. This avoids dropping 1011 * input and improves performance when all we did was frob things like 1012 * VMIN and VTIME. 1013 */ 1014 if (tp->t_ospeed == t->c_ospeed && 1015 tp->t_cflag == t->c_cflag) 1016 return (0); 1017 1018 if (cflag2modes(t->c_cflag, &mode1, &mode2) < 0) 1019 return (EINVAL); 1020 1021 s = splserial(); 1022 1023 ch->ch_mode1 = mode1; 1024 ch->ch_mode2 = mode2; 1025 1026 /* 1027 * If we're not in a mode that assumes a connection is present, then 1028 * ignore carrier changes. 1029 */ 1030 if (ISSET(t->c_cflag, CLOCAL | MDMBUF)) 1031 ch->ch_i_dcd = 0; 1032 else 1033 ch->ch_i_dcd = ch->ch_i_dcd_pin; 1034 /* 1035 * Set the flow control pins depending on the current flow control 1036 * mode. 1037 */ 1038 if (ISSET(t->c_cflag, CRTSCTS)) { 1039 ch->ch_o_dtr = ch->ch_o_dtr_pin; 1040 ch->ch_o_rts = ch->ch_o_rts_pin; 1041 ch->ch_i_cts = ch->ch_i_cts_pin; 1042 /* hw controle enable bits in mod regs set by cflag2modes */ 1043 } else if (ISSET(t->c_cflag, MDMBUF)) { 1044 /* 1045 * For DTR/DCD flow control, make sure we don't toggle DTR for 1046 * carrier detection. 1047 */ 1048 ch->ch_o_dtr = 0; 1049 ch->ch_o_rts = ch->ch_o_dtr_pin; 1050 ch->ch_i_cts = ch->ch_i_dcd_pin; 1051 } else { 1052 /* 1053 * If no flow control, then always set RTS. This will make 1054 * the other side happy if it mistakenly thinks we're doing 1055 * RTS/CTS flow control. 1056 */ 1057 ch->ch_o_dtr = ch->ch_o_dtr_pin | ch->ch_o_rts_pin; 1058 ch->ch_o_rts = 0; 1059 ch->ch_i_cts = 0; 1060 if (ISSET(ch->ch_oports, ch->ch_o_dtr_pin)) 1061 SET(ch->ch_oports, ch->ch_o_rts_pin); 1062 else 1063 CLR(ch->ch_oports, ch->ch_o_rts_pin); 1064 } 1065 /* XXX maybe mask the ports which generate intrs? */ 1066 1067 ch->ch_brc = brc; 1068 1069 /* XXX maybe set fifo-full receive mode if RTSCTS and high speed? */ 1070 1071 /* And copy to tty. */ 1072 tp->t_ispeed = 0; 1073 tp->t_ospeed = t->c_ospeed; 1074 tp->t_cflag = t->c_cflag; 1075 1076 if (!ch->ch_heldchange) { 1077 if (ch->ch_tx_busy) { 1078 ch->ch_heldtbc = ch->ch_tbc; 1079 ch->ch_tbc = 0; 1080 ch->ch_heldchange = 1; 1081 } else 1082 sbscn_loadchannelregs(ch); 1083 } 1084 1085 if (!ISSET(t->c_cflag, CHWFLOW)) { 1086 /* Disable the high water mark. */ 1087 ch->ch_r_hiwat = 0; 1088 ch->ch_r_lowat = 0; 1089 if (ISSET(ch->ch_rx_flags, RX_TTY_OVERFLOWED)) { 1090 CLR(ch->ch_rx_flags, RX_TTY_OVERFLOWED); 1091 sbscn_schedrx(ch); 1092 } 1093 if (ISSET(ch->ch_rx_flags, RX_TTY_BLOCKED|RX_IBUF_BLOCKED)) { 1094 CLR(ch->ch_rx_flags, RX_TTY_BLOCKED|RX_IBUF_BLOCKED); 1095 sbscn_dohwiflow(ch); 1096 } 1097 } else { 1098 ch->ch_r_hiwat = sbscn_rbuf_hiwat; 1099 ch->ch_r_lowat = sbscn_rbuf_lowat; 1100 } 1101 1102 splx(s); 1103 1104 /* 1105 * Update the tty layer's idea of the carrier bit, in case we changed 1106 * CLOCAL or MDMBUF. We don't hang up here; we only do that by 1107 * explicit request. 1108 */ 1109 (void) (*tp->t_linesw->l_modem)(tp, 1110 ISSET(ch->ch_iports, ch->ch_i_dcd)); 1111 1112 #ifdef SBSCN_DEBUG 1113 if (sbscn_debug) 1114 sbscn_status(ch, "sbscnparam "); 1115 #endif 1116 1117 if (!ISSET(t->c_cflag, CHWFLOW)) { 1118 if (ch->ch_tx_stopped) { 1119 ch->ch_tx_stopped = 0; 1120 sbscn_start(tp); 1121 } 1122 } 1123 1124 return (0); 1125 } 1126 1127 void 1128 sbscn_iflush(struct sbscn_channel *ch) 1129 { 1130 #ifdef DIAGNOSTIC 1131 int reg; 1132 #endif 1133 int timo; 1134 1135 #ifdef DIAGNOSTIC 1136 reg = 0xffff; 1137 #endif 1138 timo = 50000; 1139 /* flush any pending I/O */ 1140 while (ISSET(READ_REG(ch->ch_base + 0x20), 0x01) 1141 && --timo) 1142 #ifdef DIAGNOSTIC 1143 reg = 1144 #else 1145 (void) 1146 #endif 1147 READ_REG(ch->ch_base + 0x60); 1148 #ifdef DIAGNOSTIC 1149 if (!timo) 1150 printf("%s: sbscn_iflush timeout %02x\n", 1151 ch->ch_sc->sc_dev.dv_xname, reg & 0xff); 1152 #endif 1153 } 1154 1155 void 1156 sbscn_loadchannelregs(struct sbscn_channel *ch) 1157 { 1158 1159 /* XXXXX necessary? */ 1160 sbscn_iflush(ch); 1161 1162 WRITE_REG(ch->ch_imr_base, 0); 1163 1164 // XXX disable? 1165 WRITE_REG(ch->ch_base + 0x00, ch->ch_mode1); 1166 WRITE_REG(ch->ch_base + 0x10, ch->ch_mode2); 1167 WRITE_REG(ch->ch_base + 0x30, ch->ch_brc); 1168 1169 ch->ch_oports_active = ch->ch_oports; 1170 SET_OUTPUT_SIGNALS(ch, ch->ch_oports_active); 1171 1172 WRITE_REG(ch->ch_imr_base, ch->ch_imr); 1173 } 1174 1175 int 1176 sbscn_hwiflow(struct tty *tp, int block) 1177 { 1178 struct sbscn_softc *sc = sbscn_cd.cd_devs[SBSCN_UNIT(tp->t_dev)]; 1179 struct sbscn_channel *ch = &sc->sc_channels[SBSCN_CHAN(tp->t_dev)]; 1180 int s; 1181 1182 if (ch->ch_o_rts == 0) 1183 return (0); 1184 1185 s = splserial(); 1186 if (block) { 1187 if (!ISSET(ch->ch_rx_flags, RX_TTY_BLOCKED)) { 1188 SET(ch->ch_rx_flags, RX_TTY_BLOCKED); 1189 sbscn_dohwiflow(ch); 1190 } 1191 } else { 1192 if (ISSET(ch->ch_rx_flags, RX_TTY_OVERFLOWED)) { 1193 CLR(ch->ch_rx_flags, RX_TTY_OVERFLOWED); 1194 sbscn_schedrx(ch); 1195 } 1196 if (ISSET(ch->ch_rx_flags, RX_TTY_BLOCKED)) { 1197 CLR(ch->ch_rx_flags, RX_TTY_BLOCKED); 1198 sbscn_dohwiflow(ch); 1199 } 1200 } 1201 splx(s); 1202 return (1); 1203 } 1204 1205 /* 1206 * (un)block input via hw flowcontrol 1207 */ 1208 void 1209 sbscn_dohwiflow(struct sbscn_channel *ch) 1210 { 1211 1212 if (ch->ch_o_rts == 0) 1213 return; 1214 1215 if (ISSET(ch->ch_rx_flags, RX_ANY_BLOCK)) { 1216 CLR(ch->ch_oports, ch->ch_o_rts); 1217 CLR(ch->ch_oports_active, ch->ch_o_rts); 1218 } else { 1219 SET(ch->ch_oports, ch->ch_o_rts); 1220 SET(ch->ch_oports_active, ch->ch_o_rts); 1221 } 1222 SET_OUTPUT_SIGNALS(ch, ch->ch_oports_active); 1223 } 1224 1225 void 1226 sbscn_start(struct tty *tp) 1227 { 1228 struct sbscn_softc *sc = sbscn_cd.cd_devs[SBSCN_UNIT(tp->t_dev)]; 1229 struct sbscn_channel *ch = &sc->sc_channels[SBSCN_CHAN(tp->t_dev)]; 1230 int s; 1231 1232 s = spltty(); 1233 if (ISSET(tp->t_state, TS_BUSY | TS_TIMEOUT | TS_TTSTOP)) 1234 goto out; 1235 if (ch->ch_tx_stopped) 1236 goto out; 1237 1238 if (tp->t_outq.c_cc <= tp->t_lowat) { 1239 if (ISSET(tp->t_state, TS_ASLEEP)) { 1240 CLR(tp->t_state, TS_ASLEEP); 1241 wakeup(&tp->t_outq); 1242 } 1243 selwakeup(&tp->t_wsel); 1244 if (tp->t_outq.c_cc == 0) 1245 goto out; 1246 } 1247 1248 /* Grab the first contiguous region of buffer space. */ 1249 { 1250 u_char *tba; 1251 int tbc; 1252 1253 tba = tp->t_outq.c_cf; 1254 tbc = ndqb(&tp->t_outq, 0); 1255 1256 (void)splserial(); 1257 1258 ch->ch_tba = tba; 1259 ch->ch_tbc = tbc; 1260 } 1261 1262 SET(tp->t_state, TS_BUSY); 1263 ch->ch_tx_busy = 1; 1264 1265 /* Enable transmit completion interrupts if necessary. */ 1266 if (!ISSET(ch->ch_imr, 0x1)) { 1267 SET(ch->ch_imr, 0x1); 1268 WRITE_REG(ch->ch_imr_base, ch->ch_imr); 1269 } 1270 1271 /* Output the first chunk of the contiguous buffer. */ 1272 { 1273 u_char c; 1274 1275 while (ch->ch_tbc && READ_REG(ch->ch_base + 0x20) & 0x04) { 1276 c = *ch->ch_tba++; 1277 ch->ch_tbc--; 1278 WRITE_REG(ch->ch_base + 0x70, c); 1279 } 1280 } 1281 out: 1282 splx(s); 1283 return; 1284 } 1285 1286 /* 1287 * Stop output on a line. 1288 */ 1289 void 1290 sbscnstop(struct tty *tp, int flag) 1291 { 1292 struct sbscn_softc *sc = sbscn_cd.cd_devs[SBSCN_UNIT(tp->t_dev)]; 1293 struct sbscn_channel *ch = &sc->sc_channels[SBSCN_CHAN(tp->t_dev)]; 1294 int s; 1295 1296 s = splserial(); 1297 if (ISSET(tp->t_state, TS_BUSY)) { 1298 /* Stop transmitting at the next chunk. */ 1299 ch->ch_tbc = 0; 1300 ch->ch_heldtbc = 0; 1301 if (!ISSET(tp->t_state, TS_TTSTOP)) 1302 SET(tp->t_state, TS_FLUSH); 1303 } 1304 splx(s); 1305 } 1306 1307 void 1308 sbscn_diag(arg) 1309 void *arg; 1310 { 1311 struct sbscn_channel *ch = arg; 1312 struct sbscn_softc *sc = ch->ch_sc; 1313 int overflows, floods; 1314 int s; 1315 1316 s = splserial(); 1317 overflows = ch->ch_overflows; 1318 ch->ch_overflows = 0; 1319 floods = ch->ch_floods; 1320 ch->ch_floods = 0; 1321 ch->ch_errors = 0; 1322 splx(s); 1323 1324 log(LOG_WARNING, "%s: channel %d: %d fifo overflow%s, %d ibuf flood%s\n", 1325 sc->sc_dev.dv_xname, ch->ch_num, 1326 overflows, overflows == 1 ? "" : "s", 1327 floods, floods == 1 ? "" : "s"); 1328 } 1329 1330 integrate void 1331 sbscn_rxsoft(struct sbscn_channel *ch, struct tty *tp) 1332 { 1333 int (*rint)(int, struct tty *) = tp->t_linesw->l_rint; 1334 u_char *get, *end; 1335 u_int cc, scc; 1336 u_char sr; 1337 int code; 1338 int s; 1339 1340 end = ch->ch_ebuf; 1341 get = ch->ch_rbget; 1342 scc = cc = sbscn_rbuf_size - ch->ch_rbavail; 1343 1344 if (cc == sbscn_rbuf_size) { 1345 ch->ch_floods++; 1346 if (ch->ch_errors++ == 0) 1347 callout_reset(&ch->ch_diag_callout, 60 * hz, 1348 sbscn_diag, ch); 1349 } 1350 1351 while (cc) { 1352 code = get[0]; 1353 sr = get[1]; 1354 if (ISSET(sr, 0xf0)) { 1355 if (ISSET(sr, 0x10)) { 1356 ch->ch_overflows++; 1357 if (ch->ch_errors++ == 0) 1358 callout_reset(&ch->ch_diag_callout, 1359 60 * hz, sbscn_diag, ch); 1360 } 1361 if (ISSET(sr, 0xc0)) 1362 SET(code, TTY_FE); 1363 if (ISSET(sr, 0x20)) 1364 SET(code, TTY_PE); 1365 } 1366 if ((*rint)(code, tp) == -1) { 1367 /* 1368 * The line discipline's buffer is out of space. 1369 */ 1370 if (!ISSET(ch->ch_rx_flags, RX_TTY_BLOCKED)) { 1371 /* 1372 * We're either not using flow control, or the 1373 * line discipline didn't tell us to block for 1374 * some reason. Either way, we have no way to 1375 * know when there's more space available, so 1376 * just drop the rest of the data. 1377 */ 1378 get += cc << 1; 1379 if (get >= end) 1380 get -= sbscn_rbuf_size << 1; 1381 cc = 0; 1382 } else { 1383 /* 1384 * Don't schedule any more receive processing 1385 * until the line discipline tells us there's 1386 * space available (through comhwiflow()). 1387 * Leave the rest of the data in the input 1388 * buffer. 1389 */ 1390 SET(ch->ch_rx_flags, RX_TTY_OVERFLOWED); 1391 } 1392 break; 1393 } 1394 get += 2; 1395 if (get >= end) 1396 get = ch->ch_rbuf; 1397 cc--; 1398 } 1399 1400 if (cc != scc) { 1401 ch->ch_rbget = get; 1402 s = splserial(); 1403 cc = ch->ch_rbavail += scc - cc; 1404 /* Buffers should be ok again, release possible block. */ 1405 if (cc >= ch->ch_r_lowat) { 1406 if (ISSET(ch->ch_rx_flags, RX_IBUF_OVERFLOWED)) { 1407 CLR(ch->ch_rx_flags, RX_IBUF_OVERFLOWED); 1408 SET(ch->ch_imr, 0x02); 1409 WRITE_REG(ch->ch_imr_base, ch->ch_imr); 1410 } 1411 if (ISSET(ch->ch_rx_flags, RX_IBUF_BLOCKED)) { 1412 CLR(ch->ch_rx_flags, RX_IBUF_BLOCKED); 1413 sbscn_dohwiflow(ch); 1414 } 1415 } 1416 splx(s); 1417 } 1418 } 1419 1420 integrate void 1421 sbscn_txsoft(struct sbscn_channel *ch, struct tty *tp) 1422 { 1423 1424 CLR(tp->t_state, TS_BUSY); 1425 if (ISSET(tp->t_state, TS_FLUSH)) 1426 CLR(tp->t_state, TS_FLUSH); 1427 else 1428 ndflush(&tp->t_outq, (int)(ch->ch_tba - tp->t_outq.c_cf)); 1429 (*tp->t_linesw->l_start)(tp); 1430 } 1431 1432 integrate void 1433 sbscn_stsoft(struct sbscn_channel *ch, struct tty *tp) 1434 { 1435 u_char iports, delta; 1436 int s; 1437 1438 s = splserial(); 1439 iports = ch->ch_iports; 1440 delta = ch->ch_iports_delta; 1441 ch->ch_iports_delta = 0; 1442 splx(s); 1443 1444 if (ISSET(delta, ch->ch_i_dcd)) { 1445 /* 1446 * Inform the tty layer that carrier detect changed. 1447 */ 1448 (void) (*tp->t_linesw->l_modem)(tp, 1449 ISSET(iports, ch->ch_i_dcd)); 1450 } 1451 1452 if (ISSET(delta, ch->ch_i_cts)) { 1453 /* Block or unblock output according to flow control. */ 1454 if (ISSET(iports, ch->ch_i_cts)) { 1455 ch->ch_tx_stopped = 0; 1456 (*tp->t_linesw->l_start)(tp); 1457 } else { 1458 ch->ch_tx_stopped = 1; 1459 } 1460 } 1461 1462 #ifdef SBSCN_DEBUG 1463 if (sbscn_debug) 1464 sbscn_status(ch, "sbscn_stsoft"); 1465 #endif 1466 } 1467 1468 void 1469 sbscn_soft(void *arg) 1470 { 1471 struct sbscn_channel *ch = arg; 1472 struct tty *tp = ch->ch_tty; 1473 1474 if (ch->ch_rx_ready) { 1475 ch->ch_rx_ready = 0; 1476 sbscn_rxsoft(ch, tp); 1477 } 1478 1479 if (ch->ch_st_check) { 1480 ch->ch_st_check = 0; 1481 sbscn_stsoft(ch, tp); 1482 } 1483 1484 if (ch->ch_tx_done) { 1485 ch->ch_tx_done = 0; 1486 sbscn_txsoft(ch, tp); 1487 } 1488 } 1489 1490 void 1491 sbscn_intr(void *arg, uint32_t status, uint32_t pc) 1492 { 1493 struct sbscn_channel *ch = arg; 1494 u_char *put, *end; 1495 u_int cc; 1496 u_char isr, sr; 1497 1498 /* read ISR */ 1499 isr = READ_REG(ch->ch_isr_base) & ch->ch_imr; 1500 if (isr == 0) 1501 return; 1502 1503 end = ch->ch_ebuf; 1504 put = ch->ch_rbput; 1505 cc = ch->ch_rbavail; 1506 1507 do { 1508 u_char iports, delta; 1509 1510 if (isr & 0x02) { 1511 1512 sr = READ_REG(ch->ch_base + 0x20); 1513 /* XXX sr 0x01 bit must be set at this point */ 1514 1515 #if defined(DDB) || defined(KGDB) 1516 if ((sr & 0x80) == 0x80) { 1517 #ifdef DDB 1518 if (ISSET(ch->ch_hwflags, SBSCN_HW_CONSOLE)) { 1519 (void)READ_REG(ch->ch_base + 0x60); 1520 console_debugger(); 1521 continue; 1522 } 1523 #endif 1524 #ifdef KGDB 1525 if (ISSET(ch->ch_hwflags, SBSCN_HW_KGDB)) { 1526 (void)READ_REG(ch->ch_base + 0x60); 1527 kgdb_connect(1); 1528 continue; 1529 } 1530 #endif 1531 } 1532 #endif /* DDB || KGDB */ 1533 1534 if (!ISSET(ch->ch_rx_flags, RX_IBUF_OVERFLOWED)) { 1535 while (cc > 0) { 1536 put[0] = READ_REG(ch->ch_base + 0x60); 1537 put[1] = sr; 1538 put += 2; 1539 if (put >= end) 1540 put = ch->ch_rbuf; 1541 cc--; 1542 1543 sr = READ_REG(ch->ch_base + 0x20); 1544 if (!ISSET(sr, 0x02)) 1545 break; 1546 } 1547 1548 /* 1549 * Current string of incoming characters ended 1550 * because no more data was available or we 1551 * ran out of space. Schedule a receive event 1552 * if any data was received. If we're out of 1553 * space, turn off receive interrupts. 1554 */ 1555 ch->ch_rbput = put; 1556 ch->ch_rbavail = cc; 1557 if (!ISSET(ch->ch_rx_flags, RX_TTY_OVERFLOWED)) 1558 ch->ch_rx_ready = 1; 1559 1560 /* 1561 * See if we are in danger of overflowing a 1562 * buffer. If so, use hardware flow control 1563 * to ease the pressure. 1564 */ 1565 if (!ISSET(ch->ch_rx_flags, RX_IBUF_BLOCKED) && 1566 cc < ch->ch_r_hiwat) { 1567 SET(ch->ch_rx_flags, RX_IBUF_BLOCKED); 1568 sbscn_dohwiflow(ch); 1569 } 1570 1571 /* 1572 * If we're out of space, disable receive 1573 * interrupts until the queue has drained 1574 * a bit. 1575 */ 1576 if (!cc) { 1577 SET(ch->ch_rx_flags, 1578 RX_IBUF_OVERFLOWED); 1579 CLR(ch->ch_imr, 0x02); 1580 WRITE_REG(ch->ch_imr_base, ch->ch_imr); 1581 } 1582 } else { 1583 /* XXX panic? */ 1584 CLR(ch->ch_imr, 0x02); 1585 WRITE_REG(ch->ch_imr_base, ch->ch_imr); 1586 continue; 1587 } 1588 } 1589 1590 if (isr & 0x01) { 1591 CLR(ch->ch_imr, 0x01); 1592 WRITE_REG(ch->ch_imr_base, ch->ch_imr); 1593 } 1594 1595 #if 0 1596 XXX 1597 if (isr & 0x08) { 1598 clear input signal change! 1599 } 1600 #endif 1601 iports = GET_INPUT_SIGNALS(ch); 1602 delta = iports ^ ch->ch_iports; 1603 ch->ch_iports = iports; 1604 1605 /* 1606 * Process normal status changes 1607 */ 1608 if (ISSET(delta, ch->ch_i_mask)) { 1609 SET(ch->ch_iports_delta, delta); 1610 1611 /* 1612 * Stop output immediately if we lose the output 1613 * flow control signal or carrier detect. 1614 */ 1615 if (ISSET(~iports, ch->ch_i_mask)) { 1616 ch->ch_tbc = 0; 1617 ch->ch_heldtbc = 0; 1618 #ifdef SBSCN_DEBUG 1619 if (sbscn_debug) 1620 sbscn_status(ch, "sbscn_intr "); 1621 #endif 1622 } 1623 1624 ch->ch_st_check = 1; 1625 } 1626 } while ((isr = (READ_REG(ch->ch_isr_base) & ch->ch_imr)) != 0); 1627 1628 /* 1629 * Done handling any receive interrupts and status changes, and 1630 * clearing the tx-ready interrupt if it was set. See if data can 1631 * be transmitted as well. Schedule tx done event if no data left 1632 * and tty was marked busy. 1633 */ 1634 sr = READ_REG(ch->ch_base + 0x20); 1635 if (ISSET(sr, 0x4)) { 1636 1637 /* 1638 * If we've delayed a parameter change, do it now, and restart 1639 * output. 1640 */ 1641 if (ch->ch_heldchange) { 1642 sbscn_loadchannelregs(ch); 1643 ch->ch_heldchange = 0; 1644 ch->ch_tbc = ch->ch_heldtbc; 1645 ch->ch_heldtbc = 0; 1646 } 1647 1648 /* Output the next chunk of the contiguous buffer, if any. */ 1649 if (ch->ch_tbc > 0) { 1650 int wrote1; 1651 u_char c; 1652 1653 wrote1 = 0; 1654 while (ch->ch_tbc && 1655 READ_REG(ch->ch_base + 0x20) & 0x04) { 1656 wrote1 = 1; 1657 c = *ch->ch_tba++; 1658 ch->ch_tbc--; 1659 WRITE_REG(ch->ch_base + 0x70, c); 1660 } 1661 if (wrote1) { 1662 SET(ch->ch_imr, 0x01); 1663 WRITE_REG(ch->ch_imr_base, ch->ch_imr); 1664 } 1665 } else { 1666 /* 1667 * transmit completion interrupts already disabled, 1668 * mark the channel tx state as done. 1669 */ 1670 if (ch->ch_tx_busy) { 1671 ch->ch_tx_busy = 0; 1672 ch->ch_tx_done = 1; 1673 } 1674 } 1675 } 1676 1677 /* Wake up the poller. */ 1678 softintr_schedule(ch->ch_si); 1679 1680 #if NRND > 0 && defined(RND_SBSCN) 1681 rnd_add_uint32(&ch->ch_rnd_source, isr | sr); 1682 #endif 1683 } 1684 1685 /* 1686 * The following functions are polled getc and putc routines, shared 1687 * by the console and kgdb glue. 1688 */ 1689 1690 int 1691 sbscn_common_getc(u_long addr, int chan) 1692 { 1693 int s = splhigh(); 1694 u_long base = MIPS_PHYS_TO_KSEG1(addr + (chan * 0x100)); 1695 int c; 1696 1697 /* block until a character becomes available */ 1698 while ((READ_REG(base + 0x20) & 0x01) == 0) 1699 continue; 1700 1701 c = READ_REG(base + 0x60) & 0xff; 1702 splx(s); 1703 return (c); 1704 } 1705 1706 void 1707 sbscn_common_putc(u_long addr, int chan, int c) 1708 { 1709 int s = splhigh(); 1710 int timo; 1711 u_long base = MIPS_PHYS_TO_KSEG1(addr + (chan * 0x100)); 1712 1713 /* wait for any pending transmission to finish */ 1714 timo = 1500000; 1715 while ((READ_REG(base + 0x20) & 0x08) == 0 && --timo) 1716 continue; 1717 1718 WRITE_REG(base + 0x70, c); 1719 1720 /* wait for this transmission to complete */ 1721 timo = 15000000; 1722 while ((READ_REG(base + 0x20) & 0x08) == 0 && --timo) 1723 continue; 1724 1725 splx(s); 1726 } 1727 1728 /* 1729 * Initialize UART for use as console or KGDB line. 1730 */ 1731 int 1732 sbscn_init(u_long addr, int chan, int rate, tcflag_t cflag) 1733 { 1734 #if 1 1735 u_long chanregbase = MIPS_PHYS_TO_KSEG1(addr + (chan * 0x100)); 1736 u_long imaskreg = MIPS_PHYS_TO_KSEG1(addr + 0x230 + (chan * 0x20)); 1737 u_char mode1, mode2; 1738 u_long brc; 1739 volatile int timo; 1740 1741 WRITE_REG(imaskreg, 0); /* disable channel intrs */ 1742 1743 /* XXX should we really do the following? how about only if enabled? */ 1744 /* wait for any pending transmission to finish */ 1745 timo = 1500000; 1746 while ((READ_REG(chanregbase + 0x20) & 0x08) == 0 && --timo) 1747 continue; 1748 1749 /* XXX: wait a little. THIS SHOULD NOT BE NECESSARY!!! (?) */ 1750 timo = 1500000; 1751 while (--timo) 1752 ; 1753 1754 WRITE_REG(chanregbase + 0x50, 2 << 4); /* reset receiver */ 1755 WRITE_REG(chanregbase + 0x50, 3 << 4); /* reset transmitter */ 1756 1757 /* set up the line for use */ 1758 (void)cflag2modes(cflag, &mode1, &mode2); 1759 (void)sbscn_speed(rate, &brc); 1760 WRITE_REG(chanregbase + 0x00, mode1); 1761 WRITE_REG(chanregbase + 0x10, mode2); 1762 WRITE_REG(chanregbase + 0x30, brc); 1763 1764 /* enable transmit and receive */ 1765 #define M_DUART_RX_EN 0x01 1766 #define M_DUART_TX_EN 0x04 1767 WRITE_REG(chanregbase + 0x50,M_DUART_RX_EN | M_DUART_TX_EN); 1768 #endif 1769 1770 /* XXX: wait a little. THIS SHOULD NOT BE NECESSARY!!! (?) */ 1771 timo = 1500000; 1772 while (--timo) 1773 ; 1774 1775 #if 0 /* XXXCGD */ 1776 bus_space_handle_t ioh; 1777 1778 if (bus_space_map(iot, iobase, COM_NPORTS, 0, &ioh)) 1779 return (ENOMEM); /* ??? */ 1780 1781 bus_space_write_1(iot, ioh, com_lcr, LCR_EERS); 1782 bus_space_write_1(iot, ioh, com_efr, 0); 1783 bus_space_write_1(iot, ioh, com_lcr, LCR_DLAB); 1784 rate = comspeed(rate, frequency); 1785 bus_space_write_1(iot, ioh, com_dlbl, rate); 1786 bus_space_write_1(iot, ioh, com_dlbh, rate >> 8); 1787 bus_space_write_1(iot, ioh, com_lcr, cflag2lcr(cflag)); 1788 bus_space_write_1(iot, ioh, com_mcr, MCR_DTR | MCR_RTS); 1789 bus_space_write_1(iot, ioh, com_fifo, 1790 FIFO_ENABLE | FIFO_RCV_RST | FIFO_XMT_RST | FIFO_TRIGGER_1); 1791 bus_space_write_1(iot, ioh, com_ier, 0); 1792 1793 *iohp = ioh; 1794 return (0); 1795 #endif /* XXXCGD */ 1796 /* XXXCGD */ 1797 return (0); 1798 } 1799 1800 /* 1801 * Following are all routines needed for sbscn to act as console 1802 */ 1803 int 1804 sbscn_cnattach(u_long addr, int chan, int rate, tcflag_t cflag) 1805 { 1806 int res; 1807 static struct consdev sbscn_cons = { 1808 NULL, NULL, sbscn_cngetc, sbscn_cnputc, sbscn_cnpollc, NULL, 1809 NULL, NULL, NODEV, CN_NORMAL 1810 }; 1811 1812 res = sbscn_init(addr, chan, rate, cflag); 1813 if (res) 1814 return (res); 1815 1816 cn_tab = &sbscn_cons; 1817 1818 sbscn_cons_present = 1; 1819 sbscn_cons_addr = addr; 1820 sbscn_cons_chan = chan; 1821 sbscn_cons_rate = rate; 1822 sbscn_cons_cflag = cflag; 1823 1824 return (0); 1825 } 1826 1827 int 1828 sbscn_cngetc(dev_t dev) 1829 { 1830 1831 return (sbscn_common_getc(sbscn_cons_addr, sbscn_cons_chan)); 1832 } 1833 1834 /* 1835 * Console kernel output character routine. 1836 */ 1837 void 1838 sbscn_cnputc(dev_t dev, int c) 1839 { 1840 1841 sbscn_common_putc(sbscn_cons_addr, sbscn_cons_chan, c); 1842 } 1843 1844 void 1845 sbscn_cnpollc(dev_t dev, int on) 1846 { 1847 1848 } 1849 1850 #ifdef KGDB 1851 int 1852 sbscn_kgdb_attach(u_long addr, int chan, int rate, tcflag_t cflag) 1853 { 1854 int res; 1855 1856 if (!sbscn_cons_present && 1857 sbscn_cons_addr == addr && sbscn_cons_chan == chan) 1858 return (EBUSY); /* cannot share with console */ 1859 1860 res = sbscn_init(addr, chan, rate, cflag); 1861 if (res) 1862 return (res); 1863 1864 kgdb_attach(sbscn_kgdb_getc, sbscn_kgdb_putc, NULL); 1865 kgdb_dev = 123; /* unneeded, only to satisfy some tests */ 1866 1867 sbscn_kgdb_present = 1; 1868 sbscn_kgdb_addr = addr; 1869 sbscn_kgdb_chan = chan; 1870 1871 return (0); 1872 } 1873 1874 /* ARGSUSED */ 1875 int 1876 sbscn_kgdb_getc(arg) 1877 void *arg; 1878 { 1879 1880 return (sbscn_common_getc(sbscn_kgdb_addr, sbscn_kgdb_chan)); 1881 } 1882 1883 /* ARGSUSED */ 1884 void 1885 sbscn_kgdb_putc(arg, c) 1886 void *arg; 1887 int c; 1888 { 1889 1890 sbscn_common_getc(sbscn_kgdb_addr, sbscn_kgdb_chan, c); 1891 } 1892 #endif /* KGDB */ 1893 1894 /* 1895 * helper function to identify the sbscn channels used by 1896 * console or KGDB (and not yet autoconf attached) 1897 */ 1898 int 1899 sbscn_is_console(u_long addr, int chan) 1900 { 1901 1902 if (sbscn_cons_present && !sbscn_cons_attached && 1903 sbscn_cons_addr == addr && sbscn_cons_chan == chan) 1904 return (1); 1905 #ifdef KGDB 1906 if (sbscn_kgdb_present && !sbscn_kgdb_attached && 1907 sbscn_kgdb_addr == addr && sbscn_kgdb_chan == chan) 1908 return (1); 1909 #endif 1910 return (0); 1911 } 1912