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