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