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