1 /* $NetBSD: scif.c,v 1.26 2002/05/19 15:10:47 msaitoh Exp $ */ 2 3 /*- 4 * Copyright (C) 1999 T.Horiuchi and SAITOH Masanobu. All rights reserved. 5 * 6 * Redistribution and use in source and binary forms, with or without 7 * modification, are permitted provided that the following conditions 8 * are met: 9 * 1. Redistributions of source code must retain the above copyright 10 * notice, this list of conditions and the following disclaimer. 11 * 2. Redistributions in binary form must reproduce the above copyright 12 * notice, this list of conditions and the following disclaimer in the 13 * documentation and/or other materials provided with the distribution. 14 * 3. The name of the author may not be used to endorse or promote products 15 * derived from this software without specific prior written permission. 16 * 17 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 18 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 19 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 20 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 21 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 22 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 23 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 24 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 26 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 27 */ 28 29 /*- 30 * Copyright (c) 1998, 1999 The NetBSD Foundation, Inc. 31 * All rights reserved. 32 * 33 * This code is derived from software contributed to The NetBSD Foundation 34 * by Charles M. Hannum. 35 * 36 * Redistribution and use in source and binary forms, with or without 37 * modification, are permitted provided that the following conditions 38 * are met: 39 * 1. Redistributions of source code must retain the above copyright 40 * notice, this list of conditions and the following disclaimer. 41 * 2. Redistributions in binary form must reproduce the above copyright 42 * notice, this list of conditions and the following disclaimer in the 43 * documentation and/or other materials provided with the distribution. 44 * 3. All advertising materials mentioning features or use of this software 45 * must display the following acknowledgement: 46 * This product includes software developed by the NetBSD 47 * Foundation, Inc. and its contributors. 48 * 4. Neither the name of The NetBSD Foundation nor the names of its 49 * contributors may be used to endorse or promote products derived 50 * from this software without specific prior written permission. 51 * 52 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 53 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 54 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 55 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 56 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 57 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 58 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 59 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 60 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 61 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 62 * POSSIBILITY OF SUCH DAMAGE. 63 */ 64 65 /* 66 * Copyright (c) 1991 The Regents of the University of California. 67 * All rights reserved. 68 * 69 * Redistribution and use in source and binary forms, with or without 70 * modification, are permitted provided that the following conditions 71 * are met: 72 * 1. Redistributions of source code must retain the above copyright 73 * notice, this list of conditions and the following disclaimer. 74 * 2. Redistributions in binary form must reproduce the above copyright 75 * notice, this list of conditions and the following disclaimer in the 76 * documentation and/or other materials provided with the distribution. 77 * 3. All advertising materials mentioning features or use of this software 78 * must display the following acknowledgement: 79 * This product includes software developed by the University of 80 * California, Berkeley and its contributors. 81 * 4. Neither the name of the University nor the names of its contributors 82 * may be used to endorse or promote products derived from this software 83 * without specific prior written permission. 84 * 85 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 86 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 87 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 88 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 89 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 90 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 91 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 92 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 93 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 94 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 95 * SUCH DAMAGE. 96 * 97 * @(#)com.c 7.5 (Berkeley) 5/16/91 98 */ 99 100 /* 101 * SH internal serial driver 102 * 103 * This code is derived from both z8530tty.c and com.c 104 */ 105 106 #include "opt_kgdb.h" 107 #include "opt_scif.h" 108 109 #include <sys/param.h> 110 #include <sys/systm.h> 111 #include <sys/tty.h> 112 #include <sys/proc.h> 113 #include <sys/conf.h> 114 #include <sys/file.h> 115 #include <sys/syslog.h> 116 #include <sys/kernel.h> 117 #include <sys/device.h> 118 #include <sys/malloc.h> 119 #include <sys/kgdb.h> 120 121 #include <dev/cons.h> 122 123 #include <sh3/clock.h> 124 #include <sh3/exception.h> 125 #include <sh3/scifreg.h> 126 #include <machine/intr.h> 127 128 #include <sh3/dev/scifvar.h> 129 130 #include "locators.h" 131 132 static void scifstart(struct tty *); 133 static int scifparam(struct tty *, struct termios *); 134 static int kgdb_attached; 135 136 void scifcnprobe(struct consdev *); 137 void scifcninit(struct consdev *); 138 void scifcnputc(dev_t, int); 139 int scifcngetc(dev_t); 140 void scifcnpoolc(dev_t, int); 141 void scif_intr_init(void); 142 int scifintr(void *); 143 144 struct scif_softc { 145 struct device sc_dev; /* boilerplate */ 146 struct tty *sc_tty; 147 void *sc_si; 148 149 struct callout sc_diag_ch; 150 151 #if 0 152 bus_space_tag_t sc_iot; /* ISA i/o space identifier */ 153 bus_space_handle_t sc_ioh; /* ISA io handle */ 154 155 int sc_drq; 156 157 int sc_frequency; 158 #endif 159 160 u_int sc_overflows, 161 sc_floods, 162 sc_errors; /* number of retries so far */ 163 u_char sc_status[7]; /* copy of registers */ 164 165 int sc_hwflags; 166 int sc_swflags; 167 u_int sc_fifolen; 168 169 u_int sc_r_hiwat, 170 sc_r_lowat; 171 u_char *volatile sc_rbget, 172 *volatile sc_rbput; 173 volatile u_int sc_rbavail; 174 u_char *sc_rbuf, 175 *sc_ebuf; 176 177 u_char *sc_tba; /* transmit buffer address */ 178 u_int sc_tbc, /* transmit byte count */ 179 sc_heldtbc; 180 181 volatile u_char sc_rx_flags, 182 #define RX_TTY_BLOCKED 0x01 183 #define RX_TTY_OVERFLOWED 0x02 184 #define RX_IBUF_BLOCKED 0x04 185 #define RX_IBUF_OVERFLOWED 0x08 186 #define RX_ANY_BLOCK 0x0f 187 sc_tx_busy, /* working on an output chunk */ 188 sc_tx_done, /* done with one output chunk */ 189 sc_tx_stopped, /* H/W level stop (lost CTS) */ 190 sc_st_check, /* got a status interrupt */ 191 sc_rx_ready; 192 193 volatile u_char sc_heldchange; 194 }; 195 196 /* controller driver configuration */ 197 static int scif_match(struct device *, struct cfdata *, void *); 198 static void scif_attach(struct device *, struct device *, void *); 199 200 void scif_break(struct scif_softc *, int); 201 void scif_iflush(struct scif_softc *); 202 203 #define integrate static inline 204 #ifdef __HAVE_GENERIC_SOFT_INTERRUPTS 205 void scifsoft(void *); 206 #else 207 #ifndef __NO_SOFT_SERIAL_INTERRUPT 208 void scifsoft(void); 209 #else 210 void scifsoft(void *); 211 #endif 212 #endif 213 integrate void scif_rxsoft(struct scif_softc *, struct tty *); 214 integrate void scif_txsoft(struct scif_softc *, struct tty *); 215 integrate void scif_stsoft(struct scif_softc *, struct tty *); 216 integrate void scif_schedrx(struct scif_softc *); 217 void scifdiag(void *); 218 219 220 #define SCIFUNIT_MASK 0x7ffff 221 #define SCIFDIALOUT_MASK 0x80000 222 223 #define SCIFUNIT(x) (minor(x) & SCIFUNIT_MASK) 224 #define SCIFDIALOUT(x) (minor(x) & SCIFDIALOUT_MASK) 225 226 /* Macros to clear/set/test flags. */ 227 #define SET(t, f) (t) |= (f) 228 #define CLR(t, f) (t) &= ~(f) 229 #define ISSET(t, f) ((t) & (f)) 230 231 /* Hardware flag masks */ 232 #define SCIF_HW_NOIEN 0x01 233 #define SCIF_HW_FIFO 0x02 234 #define SCIF_HW_FLOW 0x08 235 #define SCIF_HW_DEV_OK 0x20 236 #define SCIF_HW_CONSOLE 0x40 237 #define SCIF_HW_KGDB 0x80 238 239 /* Buffer size for character buffer */ 240 #define SCIF_RING_SIZE 2048 241 242 /* Stop input when 3/4 of the ring is full; restart when only 1/4 is full. */ 243 u_int scif_rbuf_hiwat = (SCIF_RING_SIZE * 1) / 4; 244 u_int scif_rbuf_lowat = (SCIF_RING_SIZE * 3) / 4; 245 246 #define CONMODE ((TTYDEF_CFLAG & ~(CSIZE | CSTOPB | PARENB)) | CS8) /* 8N1 */ 247 int scifconscflag = CONMODE; 248 int scifisconsole = 0; 249 250 #ifdef SCIFCN_SPEED 251 unsigned int scifcn_speed = SCIFCN_SPEED; 252 #else 253 unsigned int scifcn_speed = 9600; 254 #endif 255 256 #define divrnd(n, q) (((n)*2/(q)+1)/2) /* divide and round off */ 257 258 #ifndef __HAVE_GENERIC_SOFT_INTERRUPTS 259 #ifdef __NO_SOFT_SERIAL_INTERRUPT 260 volatile int scif_softintr_scheduled; 261 struct callout scif_soft_ch = CALLOUT_INITIALIZER; 262 #endif 263 #endif 264 265 u_int scif_rbuf_size = SCIF_RING_SIZE; 266 267 struct cfattach scif_ca = { 268 sizeof(struct scif_softc), scif_match, scif_attach 269 }; 270 271 extern struct cfdriver scif_cd; 272 273 cdev_decl(scif); 274 275 void InitializeScif (unsigned int); 276 277 /* 278 * following functions are debugging prupose only 279 */ 280 #define CR 0x0D 281 #define USART_ON (unsigned int)~0x08 282 283 void scif_putc(unsigned char); 284 unsigned char scif_getc(void); 285 int ScifErrCheck(void); 286 287 /* 288 * InitializeScif 289 * : unsigned int bps; 290 * : SCIF(Serial Communication Interface) 291 */ 292 293 void 294 InitializeScif(unsigned int bps) 295 { 296 297 /* Initialize SCR */ 298 SHREG_SCSCR2 = 0x00; 299 300 #if 0 301 SHREG_SCFCR2 = SCFCR2_TFRST | SCFCR2_RFRST | SCFCR2_MCE; 302 #else 303 SHREG_SCFCR2 = SCFCR2_TFRST | SCFCR2_RFRST; 304 #endif 305 /* Serial Mode Register */ 306 SHREG_SCSMR2 = 0x00; /* 8bit,NonParity,Even,1Stop */ 307 308 /* Bit Rate Register */ 309 SHREG_SCBRR2 = divrnd(sh_clock_get_pclock(), 32 * bps) - 1; 310 311 /* 312 * wait 1mSec, because Send/Recv must begin 1 bit period after 313 * BRR is set. 314 */ 315 delay(1000); 316 317 #if 0 318 SHREG_SCFCR2 = FIFO_RCV_TRIGGER_14 | FIFO_XMT_TRIGGER_1 | SCFCR2_MCE; 319 #else 320 SHREG_SCFCR2 = FIFO_RCV_TRIGGER_14 | FIFO_XMT_TRIGGER_1; 321 #endif 322 323 /* Send permission, Receive permission ON */ 324 SHREG_SCSCR2 = SCSCR2_TE | SCSCR2_RE; 325 326 /* Serial Status Register */ 327 SHREG_SCSSR2 &= SCSSR2_TDFE; /* Clear Status */ 328 } 329 330 331 /* 332 * scif_putc 333 * : unsigned char c; 334 */ 335 336 void 337 scif_putc(unsigned char c) 338 { 339 340 if (c == '\n') 341 scif_putc('\r'); 342 343 /* wait for ready */ 344 while ((SHREG_SCFDR2 & SCFDR2_TXCNT) == SCFDR2_TXF_FULL) 345 ; 346 347 /* write send data to send register */ 348 SHREG_SCFTDR2 = c; 349 350 /* clear ready flag */ 351 SHREG_SCSSR2 &= ~(SCSSR2_TDFE | SCSSR2_TEND); 352 } 353 354 /* 355 * : ScifErrCheck 356 * 0x80 = error 357 * 0x08 = frame error 358 * 0x04 = parity error 359 */ 360 int 361 ScifErrCheck(void) 362 { 363 364 return(SHREG_SCSSR2 & (SCSSR2_ER | SCSSR2_FER | SCSSR2_PER)); 365 } 366 367 /* 368 * scif_getc 369 */ 370 unsigned char 371 scif_getc(void) 372 { 373 unsigned char c, err_c; 374 #ifdef SH4 375 unsigned short err_c2; 376 #endif 377 378 while (1) { 379 /* wait for ready */ 380 while ((SHREG_SCFDR2 & SCFDR2_RECVCNT) == 0) 381 ; 382 383 c = SHREG_SCFRDR2; 384 err_c = SHREG_SCSSR2; 385 SHREG_SCSSR2 &= ~(SCSSR2_ER | SCSSR2_BRK | SCSSR2_RDF 386 | SCSSR2_DR); 387 #ifdef SH4 388 if (CPU_IS_SH4) { 389 err_c2 = SHREG_SCLSR2; 390 SHREG_SCLSR2 &= ~SCLSR2_ORER; 391 } 392 #endif 393 if ((err_c & (SCSSR2_ER | SCSSR2_BRK | SCSSR2_FER 394 | SCSSR2_PER)) == 0) { 395 #ifdef SH4 396 if (CPU_IS_SH4 && ((err_c2 & SCLSR2_ORER) == 0)) 397 #endif 398 return(c); 399 } 400 } 401 402 } 403 404 #if 0 405 #define SCIF_MAX_UNITS 2 406 #else 407 #define SCIF_MAX_UNITS 1 408 #endif 409 410 411 static int 412 scif_match(struct device *parent, struct cfdata *cfp, void *aux) 413 { 414 415 if (strcmp(cfp->cf_driver->cd_name, "scif") 416 || cfp->cf_unit >= SCIF_MAX_UNITS) 417 return 0; 418 419 return 1; 420 } 421 422 static void 423 scif_attach(struct device *parent, struct device *self, void *aux) 424 { 425 struct scif_softc *sc = (struct scif_softc *)self; 426 struct tty *tp; 427 428 sc->sc_hwflags = 0; /* XXX */ 429 sc->sc_swflags = 0; /* XXX */ 430 sc->sc_fifolen = 16; 431 432 if (scifisconsole || kgdb_attached) { 433 /* InitializeScif(scifcn_speed); */ 434 SET(sc->sc_hwflags, SCIF_HW_CONSOLE); 435 SET(sc->sc_swflags, TIOCFLAG_SOFTCAR); 436 if (kgdb_attached) { 437 SET(sc->sc_hwflags, SCIF_HW_KGDB); 438 printf("\n%s: kgdb\n", sc->sc_dev.dv_xname); 439 } else { 440 printf("\n%s: console\n", sc->sc_dev.dv_xname); 441 } 442 } else { 443 InitializeScif(9600); 444 printf("\n"); 445 } 446 447 callout_init(&sc->sc_diag_ch); 448 #ifdef SH4 449 intc_intr_establish(SH4_INTEVT_SCIF_ERI, IST_LEVEL, IPL_SERIAL, 450 scifintr, sc); 451 intc_intr_establish(SH4_INTEVT_SCIF_RXI, IST_LEVEL, IPL_SERIAL, 452 scifintr, sc); 453 intc_intr_establish(SH4_INTEVT_SCIF_BRI, IST_LEVEL, IPL_SERIAL, 454 scifintr, sc); 455 intc_intr_establish(SH4_INTEVT_SCIF_TXI, IST_LEVEL, IPL_SERIAL, 456 scifintr, sc); 457 #else 458 intc_intr_establish(SH7709_INTEVT2_SCIF_ERI, IST_LEVEL, IPL_SERIAL, 459 scifintr, sc); 460 intc_intr_establish(SH7709_INTEVT2_SCIF_RXI, IST_LEVEL, IPL_SERIAL, 461 scifintr, sc); 462 intc_intr_establish(SH7709_INTEVT2_SCIF_BRI, IST_LEVEL, IPL_SERIAL, 463 scifintr, sc); 464 intc_intr_establish(SH7709_INTEVT2_SCIF_TXI, IST_LEVEL, IPL_SERIAL, 465 scifintr, sc); 466 #endif 467 468 #ifdef __HAVE_GENERIC_SOFT_INTERRUPTS 469 sc->sc_si = softintr_establish(IPL_SOFTSERIAL, scifsoft, sc); 470 #endif 471 SET(sc->sc_hwflags, SCIF_HW_DEV_OK); 472 473 tp = ttymalloc(); 474 tp->t_oproc = scifstart; 475 tp->t_param = scifparam; 476 tp->t_hwiflow = NULL; 477 478 sc->sc_tty = tp; 479 sc->sc_rbuf = malloc(scif_rbuf_size << 1, M_DEVBUF, M_NOWAIT); 480 if (sc->sc_rbuf == NULL) { 481 printf("%s: unable to allocate ring buffer\n", 482 sc->sc_dev.dv_xname); 483 return; 484 } 485 sc->sc_ebuf = sc->sc_rbuf + (scif_rbuf_size << 1); 486 487 tty_attach(tp); 488 } 489 490 /* 491 * Start or restart transmission. 492 */ 493 static void 494 scifstart(struct tty *tp) 495 { 496 struct scif_softc *sc = scif_cd.cd_devs[SCIFUNIT(tp->t_dev)]; 497 int s; 498 499 s = spltty(); 500 if (ISSET(tp->t_state, TS_BUSY | TS_TIMEOUT | TS_TTSTOP)) 501 goto out; 502 if (sc->sc_tx_stopped) 503 goto out; 504 505 if (tp->t_outq.c_cc <= tp->t_lowat) { 506 if (ISSET(tp->t_state, TS_ASLEEP)) { 507 CLR(tp->t_state, TS_ASLEEP); 508 wakeup(&tp->t_outq); 509 } 510 selwakeup(&tp->t_wsel); 511 if (tp->t_outq.c_cc == 0) 512 goto out; 513 } 514 515 /* Grab the first contiguous region of buffer space. */ 516 { 517 u_char *tba; 518 int tbc; 519 520 tba = tp->t_outq.c_cf; 521 tbc = ndqb(&tp->t_outq, 0); 522 523 (void)splserial(); 524 525 sc->sc_tba = tba; 526 sc->sc_tbc = tbc; 527 } 528 529 SET(tp->t_state, TS_BUSY); 530 sc->sc_tx_busy = 1; 531 532 /* Enable transmit completion interrupts if necessary. */ 533 SHREG_SCSCR2 |= SCSCR2_TIE | SCSCR2_RIE; 534 535 /* Output the first chunk of the contiguous buffer. */ 536 { 537 int n; 538 int max; 539 int i; 540 541 n = sc->sc_tbc; 542 max = sc->sc_fifolen - ((SHREG_SCFDR2 & SCFDR2_TXCNT) >> 8); 543 if (n > max) 544 n = max; 545 546 for (i = 0; i < n; i++) { 547 scif_putc(*(sc->sc_tba)); 548 sc->sc_tba++; 549 } 550 sc->sc_tbc -= n; 551 } 552 out: 553 splx(s); 554 return; 555 } 556 557 /* 558 * Set SCIF tty parameters from termios. 559 * XXX - Should just copy the whole termios after 560 * making sure all the changes could be done. 561 */ 562 static int 563 scifparam(struct tty *tp, struct termios *t) 564 { 565 struct scif_softc *sc = scif_cd.cd_devs[SCIFUNIT(tp->t_dev)]; 566 int ospeed = t->c_ospeed; 567 int s; 568 569 if (ISSET(sc->sc_dev.dv_flags, DVF_ACTIVE) == 0) 570 return (EIO); 571 572 /* Check requested parameters. */ 573 if (ospeed < 0) 574 return (EINVAL); 575 if (t->c_ispeed && t->c_ispeed != t->c_ospeed) 576 return (EINVAL); 577 578 /* 579 * For the console, always force CLOCAL and !HUPCL, so that the port 580 * is always active. 581 */ 582 if (ISSET(sc->sc_swflags, TIOCFLAG_SOFTCAR) || 583 ISSET(sc->sc_hwflags, SCIF_HW_CONSOLE)) { 584 SET(t->c_cflag, CLOCAL); 585 CLR(t->c_cflag, HUPCL); 586 } 587 588 /* 589 * If there were no changes, don't do anything. This avoids dropping 590 * input and improves performance when all we did was frob things like 591 * VMIN and VTIME. 592 */ 593 if (tp->t_ospeed == t->c_ospeed && 594 tp->t_cflag == t->c_cflag) 595 return (0); 596 597 #if 0 598 /* XXX (msaitoh) */ 599 lcr = ISSET(sc->sc_lcr, LCR_SBREAK) | cflag2lcr(t->c_cflag); 600 #endif 601 602 s = splserial(); 603 604 /* 605 * Set the flow control pins depending on the current flow control 606 * mode. 607 */ 608 if (ISSET(t->c_cflag, CRTSCTS)) { 609 SHREG_SCFCR2 |= SCFCR2_MCE; 610 } else { 611 SHREG_SCFCR2 &= ~SCFCR2_MCE; 612 } 613 614 SHREG_SCBRR2 = divrnd(sh_clock_get_pclock(), 32 * ospeed) -1; 615 616 /* 617 * Set the FIFO threshold based on the receive speed. 618 * 619 * * If it's a low speed, it's probably a mouse or some other 620 * interactive device, so set the threshold low. 621 * * If it's a high speed, trim the trigger level down to prevent 622 * overflows. 623 * * Otherwise set it a bit higher. 624 */ 625 #if 0 626 /* XXX (msaitoh) */ 627 if (ISSET(sc->sc_hwflags, SCIF_HW_HAYESP)) 628 sc->sc_fifo = FIFO_DMA_MODE | FIFO_ENABLE | FIFO_TRIGGER_8; 629 else if (ISSET(sc->sc_hwflags, SCIF_HW_FIFO)) 630 sc->sc_fifo = FIFO_ENABLE | 631 (t->c_ospeed <= 1200 ? FIFO_TRIGGER_1 : 632 t->c_ospeed <= 38400 ? FIFO_TRIGGER_8 : FIFO_TRIGGER_4); 633 else 634 sc->sc_fifo = 0; 635 #endif 636 637 /* And copy to tty. */ 638 tp->t_ispeed = 0; 639 tp->t_ospeed = t->c_ospeed; 640 tp->t_cflag = t->c_cflag; 641 642 if (!sc->sc_heldchange) { 643 if (sc->sc_tx_busy) { 644 sc->sc_heldtbc = sc->sc_tbc; 645 sc->sc_tbc = 0; 646 sc->sc_heldchange = 1; 647 } 648 #if 0 649 /* XXX (msaitoh) */ 650 else 651 scif_loadchannelregs(sc); 652 #endif 653 } 654 655 if (!ISSET(t->c_cflag, CHWFLOW)) { 656 /* Disable the high water mark. */ 657 sc->sc_r_hiwat = 0; 658 sc->sc_r_lowat = 0; 659 if (ISSET(sc->sc_rx_flags, RX_TTY_OVERFLOWED)) { 660 CLR(sc->sc_rx_flags, RX_TTY_OVERFLOWED); 661 scif_schedrx(sc); 662 } 663 } else { 664 sc->sc_r_hiwat = scif_rbuf_hiwat; 665 sc->sc_r_lowat = scif_rbuf_lowat; 666 } 667 668 splx(s); 669 670 #ifdef SCIF_DEBUG 671 if (scif_debug) 672 scifstatus(sc, "scifparam "); 673 #endif 674 675 if (!ISSET(t->c_cflag, CHWFLOW)) { 676 if (sc->sc_tx_stopped) { 677 sc->sc_tx_stopped = 0; 678 scifstart(tp); 679 } 680 } 681 682 return (0); 683 } 684 685 void 686 scif_iflush(struct scif_softc *sc) 687 { 688 int i; 689 unsigned char c; 690 691 i = SHREG_SCFDR2 & SCFDR2_RECVCNT; 692 693 while (i > 0) { 694 c = SHREG_SCFRDR2; 695 SHREG_SCSSR2 &= ~(SCSSR2_RDF | SCSSR2_DR); 696 i--; 697 } 698 } 699 700 int 701 scifopen(dev_t dev, int flag, int mode, struct proc *p) 702 { 703 int unit = SCIFUNIT(dev); 704 struct scif_softc *sc; 705 struct tty *tp; 706 int s, s2; 707 int error; 708 709 if (unit >= scif_cd.cd_ndevs) 710 return (ENXIO); 711 sc = scif_cd.cd_devs[unit]; 712 if (sc == 0 || !ISSET(sc->sc_hwflags, SCIF_HW_DEV_OK) || 713 sc->sc_rbuf == NULL) 714 return (ENXIO); 715 716 if (ISSET(sc->sc_dev.dv_flags, DVF_ACTIVE) == 0) 717 return (ENXIO); 718 719 #ifdef KGDB 720 /* 721 * If this is the kgdb port, no other use is permitted. 722 */ 723 if (ISSET(sc->sc_hwflags, SCIF_HW_KGDB)) 724 return (EBUSY); 725 #endif /* KGDB */ 726 727 tp = sc->sc_tty; 728 729 if (ISSET(tp->t_state, TS_ISOPEN) && 730 ISSET(tp->t_state, TS_XCLUDE) && 731 p->p_ucred->cr_uid != 0) 732 return (EBUSY); 733 734 s = spltty(); 735 736 /* 737 * Do the following iff this is a first open. 738 */ 739 if (!ISSET(tp->t_state, TS_ISOPEN) && tp->t_wopen == 0) { 740 struct termios t; 741 742 tp->t_dev = dev; 743 744 s2 = splserial(); 745 746 /* Turn on interrupts. */ 747 SHREG_SCSCR2 |= SCSCR2_TIE | SCSCR2_RIE; 748 749 splx(s2); 750 751 /* 752 * Initialize the termios status to the defaults. Add in the 753 * sticky bits from TIOCSFLAGS. 754 */ 755 t.c_ispeed = 0; 756 if (ISSET(sc->sc_hwflags, SCIF_HW_CONSOLE)) { 757 t.c_ospeed = scifcn_speed; /* XXX (msaitoh) */ 758 t.c_cflag = scifconscflag; 759 } else { 760 t.c_ospeed = TTYDEF_SPEED; 761 t.c_cflag = TTYDEF_CFLAG; 762 } 763 if (ISSET(sc->sc_swflags, TIOCFLAG_CLOCAL)) 764 SET(t.c_cflag, CLOCAL); 765 if (ISSET(sc->sc_swflags, TIOCFLAG_CRTSCTS)) 766 SET(t.c_cflag, CRTSCTS); 767 if (ISSET(sc->sc_swflags, TIOCFLAG_MDMBUF)) 768 SET(t.c_cflag, MDMBUF); 769 /* Make sure scifparam() will do something. */ 770 tp->t_ospeed = 0; 771 (void) scifparam(tp, &t); 772 tp->t_iflag = TTYDEF_IFLAG; 773 tp->t_oflag = TTYDEF_OFLAG; 774 tp->t_lflag = TTYDEF_LFLAG; 775 ttychars(tp); 776 ttsetwater(tp); 777 778 s2 = splserial(); 779 780 /* Clear the input ring, and unblock. */ 781 sc->sc_rbput = sc->sc_rbget = sc->sc_rbuf; 782 sc->sc_rbavail = scif_rbuf_size; 783 scif_iflush(sc); 784 CLR(sc->sc_rx_flags, RX_ANY_BLOCK); 785 #if 0 786 /* XXX (msaitoh) */ 787 scif_hwiflow(sc); 788 #endif 789 790 #ifdef SCIF_DEBUG 791 if (scif_debug) 792 scifstatus(sc, "scifopen "); 793 #endif 794 795 splx(s2); 796 } 797 798 splx(s); 799 800 error = ttyopen(tp, SCIFDIALOUT(dev), ISSET(flag, O_NONBLOCK)); 801 if (error) 802 goto bad; 803 804 error = (*tp->t_linesw->l_open)(dev, tp); 805 if (error) 806 goto bad; 807 808 return (0); 809 810 bad: 811 812 return (error); 813 } 814 815 int 816 scifclose(dev_t dev, int flag, int mode, struct proc *p) 817 { 818 struct scif_softc *sc = scif_cd.cd_devs[SCIFUNIT(dev)]; 819 struct tty *tp = sc->sc_tty; 820 821 /* XXX This is for cons.c. */ 822 if (!ISSET(tp->t_state, TS_ISOPEN)) 823 return (0); 824 825 (*tp->t_linesw->l_close)(tp, flag); 826 ttyclose(tp); 827 828 if (ISSET(sc->sc_dev.dv_flags, DVF_ACTIVE) == 0) 829 return (0); 830 831 return (0); 832 } 833 834 int 835 scifread(dev_t dev, struct uio *uio, int flag) 836 { 837 struct scif_softc *sc = scif_cd.cd_devs[SCIFUNIT(dev)]; 838 struct tty *tp = sc->sc_tty; 839 840 return ((*tp->t_linesw->l_read)(tp, uio, flag)); 841 } 842 843 int 844 scifwrite(dev_t dev, struct uio *uio, int flag) 845 { 846 struct scif_softc *sc = scif_cd.cd_devs[SCIFUNIT(dev)]; 847 struct tty *tp = sc->sc_tty; 848 849 return ((*tp->t_linesw->l_write)(tp, uio, flag)); 850 } 851 852 int 853 scifpoll(dev_t dev, int events, struct proc *p) 854 { 855 struct scif_softc *sc = scif_cd.cd_devs[SCIFUNIT(dev)]; 856 struct tty *tp = sc->sc_tty; 857 858 return ((*tp->t_linesw->l_poll)(tp, events, p)); 859 } 860 861 struct tty * 862 sciftty(dev_t dev) 863 { 864 struct scif_softc *sc = scif_cd.cd_devs[SCIFUNIT(dev)]; 865 struct tty *tp = sc->sc_tty; 866 867 return (tp); 868 } 869 870 int 871 scifioctl(dev_t dev, u_long cmd, caddr_t data, int flag, struct proc *p) 872 { 873 struct scif_softc *sc = scif_cd.cd_devs[SCIFUNIT(dev)]; 874 struct tty *tp = sc->sc_tty; 875 int error; 876 int s; 877 878 if (ISSET(sc->sc_dev.dv_flags, DVF_ACTIVE) == 0) 879 return (EIO); 880 881 error = (*tp->t_linesw->l_ioctl)(tp, cmd, data, flag, p); 882 if (error != EPASSTHROUGH) 883 return (error); 884 885 error = ttioctl(tp, cmd, data, flag, p); 886 if (error != EPASSTHROUGH) 887 return (error); 888 889 error = 0; 890 891 s = splserial(); 892 893 switch (cmd) { 894 case TIOCSBRK: 895 scif_break(sc, 1); 896 break; 897 898 case TIOCCBRK: 899 scif_break(sc, 0); 900 break; 901 902 case TIOCGFLAGS: 903 *(int *)data = sc->sc_swflags; 904 break; 905 906 case TIOCSFLAGS: 907 error = suser(p->p_ucred, &p->p_acflag); 908 if (error) 909 break; 910 sc->sc_swflags = *(int *)data; 911 break; 912 913 default: 914 error = EPASSTHROUGH; 915 break; 916 } 917 918 splx(s); 919 920 return (error); 921 } 922 923 integrate void 924 scif_schedrx(struct scif_softc *sc) 925 { 926 927 sc->sc_rx_ready = 1; 928 929 /* Wake up the poller. */ 930 #ifdef __HAVE_GENERIC_SOFT_INTERRUPTS 931 softintr_schedule(sc->sc_si); 932 #else 933 #ifndef __NO_SOFT_SERIAL_INTERRUPT 934 setsoftserial(); 935 #else 936 if (!scif_softintr_scheduled) { 937 scif_softintr_scheduled = 1; 938 callout_reset(&scif_soft_ch, 1, scifsoft, NULL); 939 } 940 #endif 941 #endif 942 } 943 944 void 945 scif_break(struct scif_softc *sc, int onoff) 946 { 947 948 if (onoff) 949 SHREG_SCSSR2 &= ~SCSSR2_TDFE; 950 else 951 SHREG_SCSSR2 |= SCSSR2_TDFE; 952 953 #if 0 /* XXX */ 954 if (!sc->sc_heldchange) { 955 if (sc->sc_tx_busy) { 956 sc->sc_heldtbc = sc->sc_tbc; 957 sc->sc_tbc = 0; 958 sc->sc_heldchange = 1; 959 } else 960 scif_loadchannelregs(sc); 961 } 962 #endif 963 } 964 965 /* 966 * Stop output, e.g., for ^S or output flush. 967 */ 968 void 969 scifstop(struct tty *tp, int flag) 970 { 971 struct scif_softc *sc = scif_cd.cd_devs[SCIFUNIT(tp->t_dev)]; 972 int s; 973 974 s = splserial(); 975 if (ISSET(tp->t_state, TS_BUSY)) { 976 /* Stop transmitting at the next chunk. */ 977 sc->sc_tbc = 0; 978 sc->sc_heldtbc = 0; 979 if (!ISSET(tp->t_state, TS_TTSTOP)) 980 SET(tp->t_state, TS_FLUSH); 981 } 982 splx(s); 983 } 984 985 void 986 scif_intr_init() 987 { 988 /* XXX */ 989 } 990 991 void 992 scifdiag(void *arg) 993 { 994 struct scif_softc *sc = arg; 995 int overflows, floods; 996 int s; 997 998 s = splserial(); 999 overflows = sc->sc_overflows; 1000 sc->sc_overflows = 0; 1001 floods = sc->sc_floods; 1002 sc->sc_floods = 0; 1003 sc->sc_errors = 0; 1004 splx(s); 1005 1006 log(LOG_WARNING, "%s: %d silo overflow%s, %d ibuf flood%s\n", 1007 sc->sc_dev.dv_xname, 1008 overflows, overflows == 1 ? "" : "s", 1009 floods, floods == 1 ? "" : "s"); 1010 } 1011 1012 integrate void 1013 scif_rxsoft(struct scif_softc *sc, struct tty *tp) 1014 { 1015 int (*rint)(int c, struct tty *tp) = tp->t_linesw->l_rint; 1016 u_char *get, *end; 1017 u_int cc, scc; 1018 u_char ssr2; 1019 int code; 1020 int s; 1021 1022 end = sc->sc_ebuf; 1023 get = sc->sc_rbget; 1024 scc = cc = scif_rbuf_size - sc->sc_rbavail; 1025 1026 if (cc == scif_rbuf_size) { 1027 sc->sc_floods++; 1028 if (sc->sc_errors++ == 0) 1029 callout_reset(&sc->sc_diag_ch, 60 * hz, scifdiag, sc); 1030 } 1031 1032 while (cc) { 1033 code = get[0]; 1034 ssr2 = get[1]; 1035 if (ISSET(ssr2, SCSSR2_BRK | SCSSR2_FER | SCSSR2_PER)) { 1036 if (ISSET(ssr2, SCSSR2_BRK | SCSSR2_FER)) 1037 SET(code, TTY_FE); 1038 if (ISSET(ssr2, SCSSR2_PER)) 1039 SET(code, TTY_PE); 1040 } 1041 if ((*rint)(code, tp) == -1) { 1042 /* 1043 * The line discipline's buffer is out of space. 1044 */ 1045 if (!ISSET(sc->sc_rx_flags, RX_TTY_BLOCKED)) { 1046 /* 1047 * We're either not using flow control, or the 1048 * line discipline didn't tell us to block for 1049 * some reason. Either way, we have no way to 1050 * know when there's more space available, so 1051 * just drop the rest of the data. 1052 */ 1053 get += cc << 1; 1054 if (get >= end) 1055 get -= scif_rbuf_size << 1; 1056 cc = 0; 1057 } else { 1058 /* 1059 * Don't schedule any more receive processing 1060 * until the line discipline tells us there's 1061 * space available (through scifhwiflow()). 1062 * Leave the rest of the data in the input 1063 * buffer. 1064 */ 1065 SET(sc->sc_rx_flags, RX_TTY_OVERFLOWED); 1066 } 1067 break; 1068 } 1069 get += 2; 1070 if (get >= end) 1071 get = sc->sc_rbuf; 1072 cc--; 1073 } 1074 1075 if (cc != scc) { 1076 sc->sc_rbget = get; 1077 s = splserial(); 1078 cc = sc->sc_rbavail += scc - cc; 1079 /* Buffers should be ok again, release possible block. */ 1080 if (cc >= sc->sc_r_lowat) { 1081 if (ISSET(sc->sc_rx_flags, RX_IBUF_OVERFLOWED)) { 1082 CLR(sc->sc_rx_flags, RX_IBUF_OVERFLOWED); 1083 SHREG_SCSCR2 |= SCSCR2_RIE; 1084 } 1085 #if 0 1086 if (ISSET(sc->sc_rx_flags, RX_IBUF_BLOCKED)) { 1087 CLR(sc->sc_rx_flags, RX_IBUF_BLOCKED); 1088 scif_hwiflow(sc); 1089 } 1090 #endif 1091 } 1092 splx(s); 1093 } 1094 } 1095 1096 integrate void 1097 scif_txsoft(struct scif_softc *sc, struct tty *tp) 1098 { 1099 1100 CLR(tp->t_state, TS_BUSY); 1101 if (ISSET(tp->t_state, TS_FLUSH)) 1102 CLR(tp->t_state, TS_FLUSH); 1103 else 1104 ndflush(&tp->t_outq, (int)(sc->sc_tba - tp->t_outq.c_cf)); 1105 (*tp->t_linesw->l_start)(tp); 1106 } 1107 1108 integrate void 1109 scif_stsoft(struct scif_softc *sc, struct tty *tp) 1110 { 1111 #if 0 1112 /* XXX (msaitoh) */ 1113 u_char msr, delta; 1114 int s; 1115 1116 s = splserial(); 1117 msr = sc->sc_msr; 1118 delta = sc->sc_msr_delta; 1119 sc->sc_msr_delta = 0; 1120 splx(s); 1121 1122 if (ISSET(delta, sc->sc_msr_dcd)) { 1123 /* 1124 * Inform the tty layer that carrier detect changed. 1125 */ 1126 (void) (*tp->t_linesw->l_modem)(tp, ISSET(msr, MSR_DCD)); 1127 } 1128 1129 if (ISSET(delta, sc->sc_msr_cts)) { 1130 /* Block or unblock output according to flow control. */ 1131 if (ISSET(msr, sc->sc_msr_cts)) { 1132 sc->sc_tx_stopped = 0; 1133 (*tp->t_linesw->l_start)(tp); 1134 } else { 1135 sc->sc_tx_stopped = 1; 1136 } 1137 } 1138 1139 #ifdef SCIF_DEBUG 1140 if (scif_debug) 1141 scifstatus(sc, "scif_stsoft"); 1142 #endif 1143 #endif 1144 } 1145 1146 #ifdef __HAVE_GENERIC_SOFT_INTERRUPTS 1147 void 1148 scifsoft(void *arg) 1149 { 1150 struct scif_softc *sc = arg; 1151 struct tty *tp; 1152 1153 if (ISSET(sc->sc_dev.dv_flags, DVF_ACTIVE) == 0) 1154 return; 1155 1156 { 1157 #else 1158 void 1159 #ifndef __NO_SOFT_SERIAL_INTERRUPT 1160 scifsoft() 1161 #else 1162 scifsoft(void *arg) 1163 #endif 1164 { 1165 struct scif_softc *sc; 1166 struct tty *tp; 1167 int unit; 1168 #ifdef __NO_SOFT_SERIAL_INTERRUPT 1169 int s; 1170 1171 s = splsoftserial(); 1172 scif_softintr_scheduled = 0; 1173 #endif 1174 1175 for (unit = 0; unit < scif_cd.cd_ndevs; unit++) { 1176 sc = scif_cd.cd_devs[unit]; 1177 if (sc == NULL || !ISSET(sc->sc_hwflags, SCIF_HW_DEV_OK)) 1178 continue; 1179 1180 if (ISSET(sc->sc_dev.dv_flags, DVF_ACTIVE) == 0) 1181 continue; 1182 1183 tp = sc->sc_tty; 1184 if (tp == NULL) 1185 continue; 1186 if (!ISSET(tp->t_state, TS_ISOPEN) && tp->t_wopen == 0) 1187 continue; 1188 #endif 1189 tp = sc->sc_tty; 1190 1191 if (sc->sc_rx_ready) { 1192 sc->sc_rx_ready = 0; 1193 scif_rxsoft(sc, tp); 1194 } 1195 1196 #if 0 1197 if (sc->sc_st_check) { 1198 sc->sc_st_check = 0; 1199 scif_stsoft(sc, tp); 1200 } 1201 #endif 1202 1203 if (sc->sc_tx_done) { 1204 sc->sc_tx_done = 0; 1205 scif_txsoft(sc, tp); 1206 } 1207 } 1208 1209 #ifndef __HAVE_GENERIC_SOFT_INTERRUPTS 1210 #ifdef __NO_SOFT_SERIAL_INTERRUPT 1211 splx(s); 1212 #endif 1213 #endif 1214 } 1215 1216 int 1217 scifintr(void *arg) 1218 { 1219 struct scif_softc *sc = arg; 1220 u_char *put, *end; 1221 u_int cc; 1222 u_short ssr2; 1223 int count; 1224 1225 if (ISSET(sc->sc_dev.dv_flags, DVF_ACTIVE) == 0) 1226 return (0); 1227 1228 end = sc->sc_ebuf; 1229 put = sc->sc_rbput; 1230 cc = sc->sc_rbavail; 1231 1232 do { 1233 ssr2 = SHREG_SCSSR2; 1234 if (ISSET(ssr2, SCSSR2_BRK)) { 1235 SHREG_SCSSR2 &= ~(SCSSR2_ER | SCSSR2_BRK | SCSSR2_DR); 1236 #ifdef DDB 1237 if (ISSET(sc->sc_hwflags, SCIF_HW_CONSOLE)) { 1238 console_debugger(); 1239 } 1240 #endif /* DDB */ 1241 #ifdef KGDB 1242 if (ISSET(sc->sc_hwflags, SCIF_HW_KGDB)) { 1243 kgdb_connect(1); 1244 } 1245 #endif /* KGDB */ 1246 } 1247 count = SHREG_SCFDR2 & SCFDR2_RECVCNT; 1248 if (count != 0) { 1249 while (1) { 1250 u_char c = SHREG_SCFRDR2; 1251 u_char err = (u_char)(SHREG_SCSSR2 & 0x00ff); 1252 1253 SHREG_SCSSR2 &= ~(SCSSR2_ER | SCSSR2_RDF | SCSSR2_DR); 1254 #ifdef SH4 1255 if (CPU_IS_SH4) 1256 SHREG_SCLSR2 &= ~SCLSR2_ORER; 1257 #endif 1258 if ((cc > 0) && (count > 0)) { 1259 put[0] = c; 1260 put[1] = err; 1261 put += 2; 1262 if (put >= end) 1263 put = sc->sc_rbuf; 1264 cc--; 1265 count--; 1266 } else 1267 break; 1268 } 1269 1270 /* 1271 * Current string of incoming characters ended because 1272 * no more data was available or we ran out of space. 1273 * Schedule a receive event if any data was received. 1274 * If we're out of space, turn off receive interrupts. 1275 */ 1276 sc->sc_rbput = put; 1277 sc->sc_rbavail = cc; 1278 if (!ISSET(sc->sc_rx_flags, RX_TTY_OVERFLOWED)) 1279 sc->sc_rx_ready = 1; 1280 1281 /* 1282 * See if we are in danger of overflowing a buffer. If 1283 * so, use hardware flow control to ease the pressure. 1284 */ 1285 if (!ISSET(sc->sc_rx_flags, RX_IBUF_BLOCKED) && 1286 cc < sc->sc_r_hiwat) { 1287 SET(sc->sc_rx_flags, RX_IBUF_BLOCKED); 1288 #if 0 1289 scif_hwiflow(sc); 1290 #endif 1291 } 1292 1293 /* 1294 * If we're out of space, disable receive interrupts 1295 * until the queue has drained a bit. 1296 */ 1297 if (!cc) { 1298 SET(sc->sc_rx_flags, RX_IBUF_OVERFLOWED); 1299 SHREG_SCSCR2 &= ~SCSCR2_RIE; 1300 } 1301 } else { 1302 if (SHREG_SCSSR2 & (SCSSR2_RDF | SCSSR2_DR)) { 1303 SHREG_SCSCR2 &= ~(SCSCR2_TIE | SCSCR2_RIE); 1304 delay(10); 1305 SHREG_SCSCR2 |= SCSCR2_TIE | SCSCR2_RIE; 1306 continue; 1307 } 1308 } 1309 } while (SHREG_SCSSR2 & (SCSSR2_RDF | SCSSR2_DR)); 1310 1311 #if 0 1312 msr = bus_space_read_1(iot, ioh, scif_msr); 1313 delta = msr ^ sc->sc_msr; 1314 sc->sc_msr = msr; 1315 if (ISSET(delta, sc->sc_msr_mask)) { 1316 SET(sc->sc_msr_delta, delta); 1317 1318 /* 1319 * Pulse-per-second clock signal on edge of DCD? 1320 */ 1321 if (ISSET(delta, sc->sc_ppsmask)) { 1322 struct timeval tv; 1323 if (ISSET(msr, sc->sc_ppsmask) == 1324 sc->sc_ppsassert) { 1325 /* XXX nanotime() */ 1326 microtime(&tv); 1327 TIMEVAL_TO_TIMESPEC(&tv, 1328 &sc->ppsinfo.assert_timestamp); 1329 if (sc->ppsparam.mode & PPS_OFFSETASSERT) { 1330 timespecadd(&sc->ppsinfo.assert_timestamp, 1331 &sc->ppsparam.assert_offset, 1332 &sc->ppsinfo.assert_timestamp); 1333 TIMESPEC_TO_TIMEVAL(&tv, &sc->ppsinfo.assert_timestamp); 1334 } 1335 1336 #ifdef PPS_SYNC 1337 if (sc->ppsparam.mode & PPS_HARDPPSONASSERT) 1338 hardpps(&tv, tv.tv_usec); 1339 #endif 1340 sc->ppsinfo.assert_sequence++; 1341 sc->ppsinfo.current_mode = 1342 sc->ppsparam.mode; 1343 1344 } else if (ISSET(msr, sc->sc_ppsmask) == 1345 sc->sc_ppsclear) { 1346 /* XXX nanotime() */ 1347 microtime(&tv); 1348 TIMEVAL_TO_TIMESPEC(&tv, 1349 &sc->ppsinfo.clear_timestamp); 1350 if (sc->ppsparam.mode & PPS_OFFSETCLEAR) { 1351 timespecadd(&sc->ppsinfo.clear_timestamp, 1352 &sc->ppsparam.clear_offset, 1353 &sc->ppsinfo.clear_timestamp); 1354 TIMESPEC_TO_TIMEVAL(&tv, &sc->ppsinfo.clear_timestamp); 1355 } 1356 1357 #ifdef PPS_SYNC 1358 if (sc->ppsparam.mode & PPS_HARDPPSONCLEAR) 1359 hardpps(&tv, tv.tv_usec); 1360 #endif 1361 sc->ppsinfo.clear_sequence++; 1362 sc->ppsinfo.current_mode = 1363 sc->ppsparam.mode; 1364 } 1365 } 1366 1367 /* 1368 * Stop output immediately if we lose the output 1369 * flow control signal or carrier detect. 1370 */ 1371 if (ISSET(~msr, sc->sc_msr_mask)) { 1372 sc->sc_tbc = 0; 1373 sc->sc_heldtbc = 0; 1374 #ifdef SCIF_DEBUG 1375 if (scif_debug) 1376 scifstatus(sc, "scifintr "); 1377 #endif 1378 } 1379 1380 sc->sc_st_check = 1; 1381 } 1382 #endif 1383 1384 /* 1385 * Done handling any receive interrupts. See if data can be 1386 * transmitted as well. Schedule tx done event if no data left 1387 * and tty was marked busy. 1388 */ 1389 if (((SHREG_SCFDR2 & SCFDR2_TXCNT) >> 8) != 16) { /* XXX (msaitoh) */ 1390 /* 1391 * If we've delayed a parameter change, do it now, and restart 1392 * output. 1393 */ 1394 if (sc->sc_heldchange) { 1395 sc->sc_heldchange = 0; 1396 sc->sc_tbc = sc->sc_heldtbc; 1397 sc->sc_heldtbc = 0; 1398 } 1399 1400 /* Output the next chunk of the contiguous buffer, if any. */ 1401 if (sc->sc_tbc > 0) { 1402 int n; 1403 int max; 1404 int i; 1405 1406 n = sc->sc_tbc; 1407 max = sc->sc_fifolen - 1408 ((SHREG_SCFDR2 & SCFDR2_TXCNT) >> 8); 1409 if (n > max) 1410 n = max; 1411 1412 for (i = 0; i < n; i++) { 1413 scif_putc(*(sc->sc_tba)); 1414 sc->sc_tba++; 1415 } 1416 sc->sc_tbc -= n; 1417 } else { 1418 /* Disable transmit completion interrupts if necessary. */ 1419 #if 0 1420 if (ISSET(sc->sc_ier, IER_ETXRDY)) 1421 #endif 1422 SHREG_SCSCR2 &= ~SCSCR2_TIE; 1423 1424 if (sc->sc_tx_busy) { 1425 sc->sc_tx_busy = 0; 1426 sc->sc_tx_done = 1; 1427 } 1428 } 1429 } 1430 1431 /* Wake up the poller. */ 1432 #ifdef __HAVE_GENERIC_SOFT_INTERRUPTS 1433 softintr_schedule(sc->sc_si); 1434 #else 1435 #ifndef __NO_SOFT_SERIAL_INTERRUPT 1436 setsoftserial(); 1437 #else 1438 if (!scif_softintr_scheduled) { 1439 scif_softintr_scheduled = 1; 1440 callout_reset(&scif_soft_ch, 1, scifsoft, NULL); 1441 } 1442 #endif 1443 #endif 1444 1445 #if NRND > 0 && defined(RND_SCIF) 1446 rnd_add_uint32(&sc->rnd_source, iir | lsr); 1447 #endif 1448 1449 return (1); 1450 } 1451 1452 void 1453 scifcnprobe(struct consdev *cp) 1454 { 1455 int maj; 1456 1457 /* locate the major number */ 1458 for (maj = 0; maj < nchrdev; maj++) 1459 if (cdevsw[maj].d_open == scifopen) 1460 break; 1461 1462 /* Initialize required fields. */ 1463 cp->cn_dev = makedev(maj, 0); 1464 #ifdef SCIFCONSOLE 1465 cp->cn_pri = CN_REMOTE; 1466 #else 1467 cp->cn_pri = CN_NORMAL; 1468 #endif 1469 } 1470 1471 void 1472 scifcninit(struct consdev *cp) 1473 { 1474 1475 InitializeScif(scifcn_speed); 1476 scifisconsole = 1; 1477 } 1478 1479 int 1480 scifcngetc(dev_t dev) 1481 { 1482 int c; 1483 int s; 1484 1485 s = splserial(); 1486 c = scif_getc(); 1487 splx(s); 1488 1489 return (c); 1490 } 1491 1492 void 1493 scifcnputc(dev_t dev, int c) 1494 { 1495 int s; 1496 1497 s = splserial(); 1498 scif_putc((u_char)c); 1499 splx(s); 1500 } 1501 1502 #ifdef KGDB 1503 int 1504 scif_kgdb_init() 1505 { 1506 1507 if (strcmp(kgdb_devname, "scif") != 0) 1508 return (1); 1509 1510 if (scifisconsole) 1511 return (1); /* can't share with console */ 1512 1513 InitializeScif(kgdb_rate); 1514 1515 kgdb_attach((int (*)(void *))scifcngetc, 1516 (void (*)(void *, int))scifcnputc, NULL); 1517 kgdb_dev = 123; /* unneeded, only to satisfy some tests */ 1518 kgdb_attached = 1; 1519 1520 return (0); 1521 } 1522 #endif /* KGDB */ 1523