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