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