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