Annotation of sys/arch/mvme68k/dev/zs.c, Revision 1.1
1.1 ! nbrk 1: /* $OpenBSD: zs.c,v 1.25 2006/06/11 20:46:50 miod Exp $ */
! 2:
! 3: /*
! 4: * Copyright (c) 2000 Steve Murphree, Jr.
! 5: * Copyright (c) 1995 Theo de Raadt
! 6: * Copyright (c) 1993 Paul Mackerras.
! 7: * All rights reserved.
! 8: *
! 9: * Redistribution and use in source and binary forms, with or without
! 10: * modification, are permitted provided that the following conditions
! 11: * are met:
! 12: * 1. Redistributions of source code must retain the above copyright
! 13: * notice, this list of conditions and the following disclaimer.
! 14: * 2. Redistributions in binary form must reproduce the above copyright
! 15: * notice, this list of conditions and the following disclaimer in the
! 16: * documentation and/or other materials provided with the distribution.
! 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 OF
! 27: * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
! 28: */
! 29: /*
! 30: * Serial I/O via an SCC,
! 31: */
! 32: #include <sys/param.h>
! 33: #include <sys/ioctl.h>
! 34: #include <sys/proc.h>
! 35: #include <sys/user.h>
! 36: #include <sys/tty.h>
! 37: #include <sys/uio.h>
! 38: #include <sys/systm.h>
! 39: #include <sys/kernel.h>
! 40: #include <sys/syslog.h>
! 41: #include <sys/fcntl.h>
! 42: #include <sys/device.h>
! 43:
! 44: #include <machine/autoconf.h>
! 45: #include <machine/conf.h>
! 46: #include <machine/cpu.h>
! 47:
! 48: #ifdef DDB
! 49: #include <ddb/db_var.h>
! 50: #endif
! 51:
! 52: #include <dev/cons.h>
! 53:
! 54: #include <mvme68k/dev/scc.h>
! 55:
! 56: #include "pcc.h"
! 57: #include "mc.h"
! 58:
! 59: #if NPCC > 0
! 60: #include <mvme68k/dev/pccreg.h>
! 61: #endif
! 62: #if NMC > 0
! 63: #include <mvme68k/dev/mcreg.h>
! 64: #endif
! 65:
! 66: #include "zs.h"
! 67:
! 68: #define NZSLINE (NZS*2)
! 69:
! 70: #define RECV_BUF 512
! 71: #define ERROR_DET 0xed
! 72:
! 73: #define TS_DRAIN TS_FLUSH /* waiting for output to drain */
! 74:
! 75: #define splzs() _splraise(PSL_S | PSL_IPL4)
! 76:
! 77: struct zs {
! 78: short flags; /* see below */
! 79: char rr0; /* holds previous CTS, DCD state */
! 80: u_char imask; /* mask for input chars */
! 81: int nzs_open; /* # opens as /dev/zsn */
! 82: struct tty *tty; /* link to tty structure */
! 83: struct sccregs scc; /* SCC shadow registers */
! 84: u_char *rcv_get;
! 85: u_char *rcv_put;
! 86: u_char *rcv_end;
! 87: volatile int rcv_count;
! 88: int rcv_len;
! 89: char *send_ptr;
! 90: int send_count;
! 91: int sent_count;
! 92: volatile char modem_state;
! 93: volatile char modem_change;
! 94: volatile short hflags;
! 95: char rcv_buf[RECV_BUF];
! 96: };
! 97:
! 98: /* Bits in flags */
! 99: #define ZS_SIDEA 1
! 100: #define ZS_INITED 2
! 101: #define ZS_INTEN 4
! 102: #define ZS_RESET 8
! 103: #define ZS_CONSOLE 0x20
! 104:
! 105: /* Bits in hflags */
! 106: #define ZH_OBLOCK 1 /* output blocked by CTS */
! 107: #define ZH_SIRQ 2 /* soft interrupt request */
! 108: #define ZH_TXING 4 /* transmitter active */
! 109: #define ZH_RXOVF 8 /* receiver buffer overflow */
! 110:
! 111: struct zssoftc {
! 112: struct device sc_dev;
! 113: struct zs sc_zs[2];
! 114: struct intrhand sc_ih;
! 115: int sc_flags;
! 116: };
! 117: #define ZSSF_85230 1
! 118:
! 119: struct tty *zs_tty[NZSLINE];
! 120:
! 121: struct termios zs_cons_termios;
! 122: int zs_cons_unit = 0;
! 123: int zs_is_console = 0;
! 124: struct sccregs *zs_cons_scc;
! 125:
! 126: void zsstart(struct tty *);
! 127: int zsparam(struct tty *, struct termios *);
! 128: int zsirq(void *);
! 129: int zsregs(vaddr_t, int, volatile u_char **, volatile u_char **);
! 130: int zspclk(void);
! 131:
! 132: u_int8_t sir_zs;
! 133: void zs_softint(void *);
! 134:
! 135: #define zsunit(dev) (minor(dev) >> 1)
! 136: #define zsside(dev) (minor(dev) & 1)
! 137:
! 138: /*
! 139: * Autoconfiguration stuff.
! 140: */
! 141: void zsattach(struct device *, struct device *, void *);
! 142: int zsmatch(struct device *, void *, void *);
! 143:
! 144: struct cfattach zs_ca = {
! 145: sizeof(struct zssoftc), zsmatch, zsattach
! 146: };
! 147:
! 148: struct cfdriver zs_cd = {
! 149: NULL, "zs", DV_TTY
! 150: };
! 151:
! 152: void zs_ttydef(struct zs *);
! 153: struct tty *zstty(dev_t);
! 154: void zs_init(struct zs *);
! 155: void zscc_init(struct zs *, struct termios *);
! 156: int zscc_params(struct sccregs *, struct termios *);
! 157: int zscc_mget(struct sccregs *);
! 158: void zscc_mset(struct sccregs *, int);
! 159: void zscc_mclr(struct sccregs *, int);
! 160: void zs_drain(struct zs *);
! 161: void zs_unblock(struct tty *);
! 162: void zs_txint(struct zs *);
! 163: void zs_rxint(struct zs *);
! 164: void zs_extint(struct zs *);
! 165: cons_decl(zs);
! 166:
! 167: int
! 168: zsmatch(parent, vcf, args)
! 169: struct device *parent;
! 170: void *vcf, *args;
! 171: {
! 172: struct confargs *ca = args;
! 173: unsigned char *zstest = (unsigned char *)ca->ca_vaddr;
! 174: /*
! 175: * If zs1 is in the config, we must test to see if it really exists.
! 176: * Some 162s only have one scc device, but the memory location for
! 177: * the second scc still checks valid and every byte contains 0xFF. So
! 178: * this is what we test with for now. XXX - smurph
! 179: */
! 180: if (!badvaddr((vaddr_t)ca->ca_vaddr, 1))
! 181: if (*zstest == 0xFF)
! 182: return (0);
! 183: else
! 184: return (1);
! 185: else
! 186: return (0);
! 187: }
! 188:
! 189: void
! 190: zsattach(parent, self, args)
! 191: struct device *parent, *self;
! 192: void *args;
! 193: {
! 194: struct zssoftc *sc;
! 195: struct zs *zp, *zc;
! 196: u_char ir;
! 197: volatile struct scc *scc;
! 198: volatile u_char *scc_cr, *scc_dr;
! 199: struct confargs *ca = args;
! 200: int zs_level = ca->ca_ipl;
! 201: int size;
! 202: static int initirq = 0;
! 203:
! 204: sc = (struct zssoftc *) self;
! 205:
! 206: /* connect the interrupt */
! 207: sc->sc_ih.ih_fn = zsirq;
! 208: sc->sc_ih.ih_arg = (void *)self->dv_unit;
! 209: sc->sc_ih.ih_ipl = zs_level;
! 210: sc->sc_ih.ih_wantframe = 0;
! 211:
! 212: switch (ca->ca_bustype) {
! 213: #if NPCC > 0
! 214: case BUS_PCC:
! 215: pccintr_establish(PCCV_ZS, &sc->sc_ih, self->dv_xname);
! 216: break;
! 217: #endif
! 218: #if NMC > 0
! 219: case BUS_MC:
! 220: if (sys_mc->mc_chiprev == 0x01)
! 221: /*
! 222: * MC rev 0x01 has a bug and can not access scc regs directly.
! 223: * Macros will do the right thing based on the value of
! 224: * mc_rev1_bug - XXX smurph
! 225: */
! 226: mc_rev1_bug = 1; /* defined in scc.h */
! 227: mcintr_establish(MCV_ZS, &sc->sc_ih, self->dv_xname);
! 228: break;
! 229: #endif
! 230: }
! 231:
! 232: zp = &sc->sc_zs[0];
! 233: scc = (volatile struct scc *)ca->ca_vaddr;
! 234:
! 235: /*
! 236: * the locations of the control and data register move around
! 237: * on different MVME models, so we generate independent pointers
! 238: * to them.
! 239: */
! 240: size = zsregs(ca->ca_vaddr, 0, &scc_cr, &scc_dr);
! 241:
! 242: if (zs_is_console && self->dv_unit == zs_cons_unit) {
! 243: /* SCC is the console - it's already reset */
! 244: zc = zp + zsside(zs_cons_unit);
! 245: zc->scc = *zs_cons_scc;
! 246: zs_cons_scc = &zc->scc;
! 247: zc->flags |= ZS_CONSOLE;
! 248: } else {
! 249: /* reset the SCC */
! 250: *(scc_cr + size) = 0;
! 251: *(scc_cr + size) = 9;
! 252: *(scc_cr + size) = 0xC0; /* hardware reset of SCC, both sides */
! 253: }
! 254:
! 255: /* side A */
! 256: zp->scc.s_cr = scc_cr + size;
! 257: zp->scc.s_dr = scc_dr + size;
! 258: zp->flags |= ZS_SIDEA | ZS_RESET;
! 259:
! 260: /* side B */
! 261: ++zp;
! 262: zp->scc.s_cr = scc_cr;
! 263: zp->scc.s_dr = scc_dr;
! 264: zp->flags |= ZS_RESET;
! 265:
! 266: if (sir_zs == 0)
! 267: sir_zs = allocate_sir(zs_softint, 0);
! 268:
! 269: printf("\n");
! 270:
! 271: /*
! 272: * XXX we end up doing this twice... once for
! 273: * each ZS chip. We should really not turn interrupts on until
! 274: * we have initialized the last of the two chips. But then we
! 275: * will need to search the config system to see if we will be
! 276: * called for the 2nd chip... otherwise, a config without a zs1
! 277: * would never enable interrupts!
! 278: */
! 279: switch (ca->ca_bustype) {
! 280: #if NPCC > 0
! 281: case BUS_PCC:
! 282: ir = sys_pcc->pcc_zsirq;
! 283: if ((ir & PCC_IRQ_IPL) != 0 && (ir & PCC_IRQ_IPL) != zs_level)
! 284: panic("zs configured at different IPLs");
! 285: if (initirq)
! 286: break;
! 287: sys_pcc->pcc_zsirq = zs_level | PCC_IRQ_IEN | PCC_ZS_PCCVEC;
! 288: break;
! 289: #endif
! 290: #if NMC > 0
! 291: case BUS_MC:
! 292: ir = sys_mc->mc_zsirq;
! 293: if ((ir & MC_IRQ_IPL) != 0 && (ir & MC_IRQ_IPL) != zs_level)
! 294: panic("zs configured at different IPLs");
! 295: if (initirq)
! 296: break;
! 297: sys_mc->mc_zsirq = zs_level | MC_IRQ_IEN;
! 298: break;
! 299: #endif
! 300: }
! 301: initirq = 1;
! 302: }
! 303:
! 304: void
! 305: zs_ttydef(zp)
! 306: struct zs *zp;
! 307: {
! 308: struct tty *tp = zp->tty;
! 309:
! 310: if ((zp->flags & ZS_CONSOLE) == 0) {
! 311: tp->t_iflag = TTYDEF_IFLAG;
! 312: tp->t_oflag = TTYDEF_OFLAG;
! 313: tp->t_cflag = TTYDEF_CFLAG;
! 314: tp->t_lflag = TTYDEF_LFLAG;
! 315: tp->t_ispeed = tp->t_ospeed = TTYDEF_SPEED;
! 316: } else
! 317: tp->t_termios = zs_cons_termios;
! 318: ttychars(tp);
! 319: ttsetwater(tp);
! 320: tp->t_oproc = zsstart;
! 321: tp->t_param = zsparam;
! 322:
! 323: zp->rcv_get = zp->rcv_buf;
! 324: zp->rcv_put = zp->rcv_buf;
! 325: zp->rcv_end = zp->rcv_buf + sizeof(zp->rcv_buf);
! 326: zp->rcv_len = sizeof(zp->rcv_buf) / 2;
! 327: }
! 328:
! 329: struct tty *
! 330: zstty(dev)
! 331: dev_t dev;
! 332: {
! 333: if (minor(dev) < NZSLINE)
! 334: return (zs_tty[minor(dev)]);
! 335: return (NULL);
! 336: }
! 337:
! 338: /* ARGSUSED */
! 339: int
! 340: zsopen(dev, flag, mode, p)
! 341: dev_t dev;
! 342: int flag, mode;
! 343: struct proc *p;
! 344: {
! 345: register struct tty *tp;
! 346: int error;
! 347: struct zs *zp;
! 348: struct zssoftc *sc;
! 349:
! 350: if (zsunit(dev) >= zs_cd.cd_ndevs ||
! 351: (sc = (struct zssoftc *) zs_cd.cd_devs[zsunit(dev)]) == NULL)
! 352: return (ENODEV);
! 353:
! 354: zp = &sc->sc_zs[zsside(dev)];
! 355: if (zp->tty == NULL) {
! 356: zp->tty = ttymalloc();
! 357: zs_ttydef(zp);
! 358: if (minor(dev) < NZSLINE)
! 359: zs_tty[minor(dev)] = zp->tty;
! 360: }
! 361: tp = zp->tty;
! 362: tp->t_dev = dev;
! 363:
! 364: if ((tp->t_state & TS_ISOPEN) == 0) {
! 365: tp->t_state |= TS_WOPEN;
! 366: zs_init(zp);
! 367: if ((zp->modem_state & SCC_DCD) != 0)
! 368: tp->t_state |= TS_CARR_ON;
! 369: } else if (tp->t_state & TS_XCLUDE && p->p_ucred->cr_uid != 0)
! 370: return (EBUSY);
! 371:
! 372: error = ((*linesw[tp->t_line].l_open) (dev, tp));
! 373:
! 374: if (error == 0)
! 375: ++zp->nzs_open;
! 376: return (error);
! 377: }
! 378:
! 379: int
! 380: zsclose(dev, flag, mode, p)
! 381: dev_t dev;
! 382: int flag, mode;
! 383: struct proc *p;
! 384: {
! 385: struct zs *zp;
! 386: struct tty *tp;
! 387: struct zssoftc *sc;
! 388: int s;
! 389:
! 390: if (zsunit(dev) >= zs_cd.cd_ndevs ||
! 391: (sc = (struct zssoftc *) zs_cd.cd_devs[zsunit(dev)]) == NULL)
! 392: return (ENODEV);
! 393: zp = &sc->sc_zs[zsside(dev)];
! 394: tp = zp->tty;
! 395:
! 396: (*linesw[tp->t_line].l_close) (tp, flag);
! 397: s = splzs();
! 398: if ((zp->flags & ZS_CONSOLE) == 0 && (tp->t_cflag & HUPCL) != 0)
! 399: ZBIC(&zp->scc, 5, 0x82); /* drop DTR, RTS */
! 400: ZBIC(&zp->scc, 3, 1); /* disable receiver */
! 401: splx(s);
! 402: ttyclose(tp);
! 403: zp->nzs_open = 0;
! 404: return (0);
! 405: }
! 406:
! 407: /*ARGSUSED*/
! 408: int
! 409: zsread(dev, uio, flag)
! 410: dev_t dev;
! 411: struct uio *uio;
! 412: int flag;
! 413: {
! 414: struct zssoftc *sc = (struct zssoftc *) zs_cd.cd_devs[zsunit(dev)];
! 415: struct zs *zp = &sc->sc_zs[zsside(dev)];
! 416: struct tty *tp = zp->tty;
! 417:
! 418: return ((*linesw[tp->t_line].l_read) (tp, uio, flag));
! 419: }
! 420:
! 421: /*ARGSUSED*/
! 422: int
! 423: zswrite(dev, uio, flag)
! 424: dev_t dev;
! 425: struct uio *uio;
! 426: int flag;
! 427: {
! 428: struct zssoftc *sc = (struct zssoftc *) zs_cd.cd_devs[zsunit(dev)];
! 429: struct zs *zp = &sc->sc_zs[zsside(dev)];
! 430: struct tty *tp = zp->tty;
! 431:
! 432: return ((*linesw[tp->t_line].l_write) (tp, uio, flag));
! 433: }
! 434:
! 435: int
! 436: zsioctl(dev, cmd, data, flag, p)
! 437: dev_t dev;
! 438: u_long cmd;
! 439: caddr_t data;
! 440: int flag;
! 441: struct proc *p;
! 442: {
! 443: struct zssoftc *sc = (struct zssoftc *) zs_cd.cd_devs[zsunit(dev)];
! 444: struct zs *zp = &sc->sc_zs[zsside(dev)];
! 445: struct tty *tp = zp->tty;
! 446: register struct sccregs *scc = &zp->scc;
! 447: register int error, s;
! 448:
! 449: error = (*linesw[tp->t_line].l_ioctl) (tp, cmd, data, flag, p);
! 450: if (error >= 0)
! 451: return (error);
! 452: error = ttioctl(tp, cmd, data, flag, p);
! 453: if (error >= 0)
! 454: return (error);
! 455: error = 0;
! 456: s = splzs();
! 457: switch (cmd) {
! 458: case TIOCSDTR:
! 459: ZBIS(scc, 5, 0x80);
! 460: break;
! 461: case TIOCCDTR:
! 462: ZBIC(scc, 5, 0x80);
! 463: break;
! 464: case TIOCSBRK:
! 465: splx(s);
! 466: zs_drain(zp);
! 467: s = splzs();
! 468: ZBIS(scc, 5, 0x10);
! 469: spltty();
! 470: zs_unblock(tp);
! 471: break;
! 472: case TIOCCBRK:
! 473: ZBIC(scc, 5, 0x10);
! 474: break;
! 475: case TIOCMGET:
! 476: *(int *) data = zscc_mget(scc);
! 477: break;
! 478: case TIOCMSET:
! 479: zscc_mset(scc, *(int *) data);
! 480: zscc_mclr(scc, ~*(int *) data);
! 481: break;
! 482: case TIOCMBIS:
! 483: zscc_mset(scc, *(int *) data);
! 484: break;
! 485: case TIOCMBIC:
! 486: zscc_mclr(scc, *(int *) data);
! 487: break;
! 488: default:
! 489: error = ENOTTY;
! 490: }
! 491: splx(s);
! 492: return (error);
! 493: }
! 494:
! 495: int
! 496: zsparam(tp, t)
! 497: struct tty *tp;
! 498: struct termios *t;
! 499: {
! 500: struct zssoftc *sc = (struct zssoftc *) zs_cd.cd_devs[zsunit(tp->t_dev)];
! 501: struct zs *zp = &sc->sc_zs[zsside(tp->t_dev)];
! 502: register int s;
! 503:
! 504: zs_drain(zp);
! 505: s = splzs();
! 506: zp->imask = zscc_params(&zp->scc, t);
! 507: tp->t_ispeed = t->c_ispeed;
! 508: tp->t_ospeed = t->c_ospeed;
! 509: tp->t_cflag = t->c_cflag;
! 510: if ((tp->t_cflag & CCTS_OFLOW) == 0)
! 511: zp->hflags &= ~ZH_OBLOCK;
! 512: else if ((zp->modem_state & 0x20) == 0)
! 513: zp->hflags |= ZH_OBLOCK;
! 514: spltty();
! 515: zs_unblock(tp);
! 516: splx(s);
! 517: return (0);
! 518: }
! 519:
! 520: void
! 521: zsstart(tp)
! 522: struct tty *tp;
! 523: {
! 524: struct zssoftc *sc = (struct zssoftc *) zs_cd.cd_devs[zsunit(tp->t_dev)];
! 525: struct zs *zp = &sc->sc_zs[zsside(tp->t_dev)];
! 526: register int s, n;
! 527:
! 528: s = spltty();
! 529: if ((tp->t_state & (TS_TIMEOUT | TS_BUSY | TS_TTSTOP | TS_DRAIN)) == 0) {
! 530: n = ndqb(&tp->t_outq, 0);
! 531: if (n > 0) {
! 532: tp->t_state |= TS_BUSY;
! 533: splzs();
! 534: zp->hflags |= ZH_TXING;
! 535: zp->send_ptr = tp->t_outq.c_cf;
! 536: zp->send_count = n;
! 537: zp->sent_count = 0;
! 538: zs_txint(zp);
! 539: spltty();
! 540: }
! 541: }
! 542: splx(s);
! 543: }
! 544:
! 545: int
! 546: zsstop(tp, flag)
! 547: struct tty *tp;
! 548: int flag;
! 549: {
! 550: struct zssoftc *sc = (struct zssoftc *) zs_cd.cd_devs[zsunit(tp->t_dev)];
! 551: struct zs *zp = &sc->sc_zs[zsside(tp->t_dev)];
! 552: int s, n;
! 553:
! 554: s = splzs();
! 555: zp->send_count = 0;
! 556: n = zp->sent_count;
! 557: zp->sent_count = 0;
! 558: if ((tp->t_state & TS_BUSY) != 0 && (flag & FWRITE) == 0) {
! 559: tp->t_state &= ~TS_BUSY;
! 560: spltty();
! 561: ndflush(&tp->t_outq, n);
! 562: if (tp->t_outq.c_cc <= tp->t_lowat) {
! 563: if (tp->t_state & TS_ASLEEP) {
! 564: tp->t_state &= ~TS_ASLEEP;
! 565: wakeup((caddr_t) & tp->t_outq);
! 566: }
! 567: selwakeup(&tp->t_wsel);
! 568: }
! 569: }
! 570: splx(s);
! 571: return (0);
! 572: }
! 573:
! 574: void
! 575: zs_init(zp)
! 576: struct zs *zp;
! 577: {
! 578: register int s;
! 579:
! 580: s = splzs();
! 581: zscc_init(zp, &zp->tty->t_termios);
! 582: zp->rr0 = zp->modem_state = ZREAD0(&zp->scc);
! 583: ZBIS(&zp->scc, 1, 0x13);/* ints on tx, rx and ext/status */
! 584: ZBIS(&zp->scc, 9, 8); /* enable ints */
! 585: zp->flags |= ZS_INTEN;
! 586: splx(s);
! 587: }
! 588:
! 589: void
! 590: zscc_init(zp, par)
! 591: struct zs *zp;
! 592: struct termios *par;
! 593: {
! 594: struct sccregs *scc;
! 595:
! 596: scc = &zp->scc;
! 597: #if defined(MVME162) || defined(MVME172)
! 598: if (cputyp == CPU_162 || cputyp == CPU_172)
! 599: ZWRITE(scc, 2, MC_VECBASE+MCV_ZS);
! 600: #endif
! 601: ZWRITE(scc, 10, 0);
! 602: ZWRITE(scc, 11, 0x50); /* rx & tx clock = brgen */
! 603: ZWRITE(scc, 14, 3); /* brgen enabled, from pclk */
! 604: zp->imask = zscc_params(scc, par);
! 605: ZBIS(scc, 5, 0x82); /* set DTR and RTS */
! 606: zp->flags |= ZS_INITED;
! 607: }
! 608:
! 609: int
! 610: zscc_params(scc, par)
! 611: struct sccregs *scc;
! 612: struct termios *par;
! 613: {
! 614: unsigned divisor, speed;
! 615: int spd, imask, ints;
! 616:
! 617: speed = par->c_ospeed;
! 618: if (speed == 0) {
! 619: /* disconnect - drop DTR & RTS, disable receiver */
! 620: ZBIC(scc, 5, 0x82);
! 621: ZBIC(scc, 3, 1);
! 622: return (0xFF);
! 623: }
! 624: if ((par->c_cflag & CREAD) == 0)
! 625: ZBIC(scc, 3, 1);/* disable receiver */
! 626: divisor = (zspclk() / 32 + (speed >> 1)) / speed - 2;
! 627: ZWRITE(scc, 12, divisor);
! 628: ZWRITE(scc, 13, divisor >> 8);
! 629: switch (par->c_cflag & CSIZE) {
! 630: case CS5:
! 631: spd = 0;
! 632: imask = 0x1F;
! 633: break;
! 634: case CS6:
! 635: spd = 0x40;
! 636: imask = 0x3F;
! 637: break;
! 638: case CS7:
! 639: spd = 0x20;
! 640: imask = 0x7F;
! 641: break;
! 642: default:
! 643: spd = 0x60;
! 644: imask = 0xFF;
! 645: }
! 646: ZWRITE(scc, 5, (scc->s_val[5] & ~0x60) | spd);
! 647: ZWRITE(scc, 3, (scc->s_val[3] & ~0xC0) | (spd << 1));
! 648: spd = par->c_cflag & CSTOPB ? 8 : 0;
! 649: spd |= par->c_cflag & PARENB ? par->c_cflag & PARODD ? 1 : 3 : 0;
! 650: ZWRITE(scc, 4, 0x44 | spd);
! 651: ZBIS(scc, 5, 8); /* enable transmitter */
! 652: if ((par->c_cflag & CREAD) != 0)
! 653: ZBIS(scc, 3, 1);/* enable receiver */
! 654: ints = 0;
! 655: if ((par->c_cflag & CLOCAL) == 0)
! 656: ints |= SCC_DCD;
! 657: if ((par->c_cflag & CCTS_OFLOW) != 0)
! 658: ints |= SCC_CTS;
! 659: #if 0
! 660: if (cputyp == CPU_162 || cputyp == CPU_172) {
! 661: ZWRITE(scc, 15, ints | 1);
! 662: /*
! 663: * now.. register 7 has become register 7': disable all
! 664: * 82530-only features for now
! 665: */
! 666: ZWRITE(scc, 7, 0x20);
! 667: }
! 668: #endif
! 669: ZWRITE(scc, 15, ints);
! 670: return (imask);
! 671: }
! 672:
! 673: int
! 674: zscc_mget(scc)
! 675: register struct sccregs *scc;
! 676: {
! 677: int bits = 0, rr0;
! 678:
! 679: if ((scc->s_val[3] & SCC_RCVEN) != 0)
! 680: bits |= TIOCM_LE;
! 681: if ((scc->s_val[5] & SCC_DTR) != 0)
! 682: bits |= TIOCM_DTR;
! 683: if ((scc->s_val[5] & SCC_RTS) != 0)
! 684: bits |= TIOCM_RTS;
! 685: rr0 = ZREAD0(scc);
! 686: if ((rr0 & SCC_CTS) != 0)
! 687: bits |= TIOCM_CTS;
! 688: if ((rr0 & SCC_DCD) != 0)
! 689: bits |= TIOCM_CAR;
! 690: return (bits);
! 691: }
! 692:
! 693: void
! 694: zscc_mset(scc, bits)
! 695: register struct sccregs *scc;
! 696: int bits;
! 697: {
! 698: if ((bits & TIOCM_LE) != 0)
! 699: ZBIS(scc, 3, SCC_RCVEN);
! 700: if ((bits & TIOCM_DTR) != 0)
! 701: ZBIS(scc, 5, SCC_DTR);
! 702: if ((bits & TIOCM_RTS) != 0)
! 703: ZBIS(scc, 5, SCC_RTS);
! 704: }
! 705:
! 706: void
! 707: zscc_mclr(scc, bits)
! 708: register struct sccregs *scc;
! 709: int bits;
! 710: {
! 711: if ((bits & TIOCM_LE) != 0)
! 712: ZBIC(scc, 3, SCC_RCVEN);
! 713: if ((bits & TIOCM_DTR) != 0)
! 714: ZBIC(scc, 5, TIOCM_DTR);
! 715: if ((bits & TIOCM_RTS) != 0)
! 716: ZBIC(scc, 5, SCC_RTS);
! 717: }
! 718:
! 719: void
! 720: zs_drain(zp)
! 721: register struct zs *zp;
! 722: {
! 723: register int s;
! 724:
! 725: zp->tty->t_state |= TS_DRAIN;
! 726: /* wait for Tx buffer empty and All sent bits to be set */
! 727: s = splzs();
! 728: while ((ZREAD0(&zp->scc) & SCC_TXRDY) == 0 ||
! 729: (ZREAD(&zp->scc, 1) & 1) == 0) {
! 730: splx(s);
! 731: DELAY(100);
! 732: s = splzs();
! 733: }
! 734: splx(s);
! 735: }
! 736:
! 737: void
! 738: zs_unblock(tp)
! 739: register struct tty *tp;
! 740: {
! 741: tp->t_state &= ~TS_DRAIN;
! 742: if (tp->t_outq.c_cc != 0)
! 743: zsstart(tp);
! 744: }
! 745:
! 746: /*
! 747: * Hardware interrupt from an SCC.
! 748: */
! 749: int
! 750: zsirq(arg)
! 751: void *arg;
! 752: {
! 753: int unit = (int)arg;
! 754: struct zssoftc *sc = (struct zssoftc *) zs_cd.cd_devs[unit];
! 755: struct zs *zp = &sc->sc_zs[0];
! 756: int ipend;
! 757:
! 758: ipend = ZREAD(&zp->scc, 3); /* read int pending from A side */
! 759: if (ipend == 0)
! 760: return (0);
! 761: if ((ipend & 0x20) != 0)
! 762: zs_rxint(zp);
! 763: if ((ipend & 0x10) != 0)
! 764: zs_txint(zp);
! 765: if ((ipend & 0x8) != 0)
! 766: zs_extint(zp);
! 767: ++zp; /* now look for B side ints */
! 768: if ((ipend & 0x4) != 0)
! 769: zs_rxint(zp);
! 770: if ((ipend & 0x2) != 0)
! 771: zs_txint(zp);
! 772: if ((ipend & 0x1) != 0)
! 773: zs_extint(zp);
! 774: ZWRITE0(&zp->scc, 0x38); /* reset highest IUS */
! 775:
! 776: return (1);
! 777: }
! 778:
! 779: void
! 780: zs_txint(zp)
! 781: register struct zs *zp;
! 782: {
! 783: struct sccregs *scc;
! 784: int c;
! 785: u_char *get;
! 786:
! 787: scc = &zp->scc;
! 788: ZWRITE0(scc, 0x28); /* reset Tx interrupt */
! 789: if ((zp->hflags & ZH_OBLOCK) == 0) {
! 790: get = zp->send_ptr;
! 791: while ((ZREAD0(scc) & SCC_TXRDY) != 0 && zp->send_count > 0) {
! 792: c = *get++;
! 793: ZWRITED(scc, c);
! 794: --zp->send_count;
! 795: ++zp->sent_count;
! 796: }
! 797: zp->send_ptr = get;
! 798: if (zp->send_count == 0 && (zp->hflags & ZH_TXING) != 0) {
! 799: zp->hflags &= ~ZH_TXING;
! 800: zp->hflags |= ZH_SIRQ;
! 801: setsoftint(sir_zs);
! 802: }
! 803: }
! 804: }
! 805:
! 806: void
! 807: zs_rxint(zp)
! 808: register struct zs *zp;
! 809: {
! 810: register int stat, c, n, extra;
! 811: u_char *put;
! 812:
! 813: put = zp->rcv_put;
! 814: n = zp->rcv_count;
! 815: for (;;) {
! 816: if ((ZREAD0(&zp->scc) & SCC_RXFULL) == 0) /* check Rx full */
! 817: break;
! 818: stat = ZREAD(&zp->scc, 1) & 0x70;
! 819: c = ZREADD(&zp->scc) & zp->imask;
! 820: /* stat encodes parity, overrun, framing errors */
! 821: if (stat != 0)
! 822: ZWRITE0(&zp->scc, 0x30); /* reset error */
! 823: if ((zp->hflags & ZH_RXOVF) != 0) {
! 824: zp->hflags &= ~ZH_RXOVF;
! 825: stat |= 0x20;
! 826: }
! 827: extra = (stat != 0 || c == ERROR_DET) ? 2 : 0;
! 828: if (n + extra + 1 < zp->rcv_len) {
! 829: if (extra != 0) {
! 830: *put++ = ERROR_DET;
! 831: if (put >= zp->rcv_end)
! 832: put = zp->rcv_buf;
! 833: *put++ = stat;
! 834: if (put >= zp->rcv_end)
! 835: put = zp->rcv_buf;
! 836: n += 2;
! 837: }
! 838: *put++ = c;
! 839: if (put >= zp->rcv_end)
! 840: put = zp->rcv_buf;
! 841: ++n;
! 842: } else
! 843: zp->hflags |= ZH_RXOVF;
! 844: }
! 845: if (n > zp->rcv_count) {
! 846: zp->rcv_put = put;
! 847: zp->rcv_count = n;
! 848: zp->hflags |= ZH_SIRQ;
! 849: setsoftint(sir_zs);
! 850: }
! 851: }
! 852:
! 853: /* Ext/status interrupt */
! 854: void
! 855: zs_extint(zp)
! 856: register struct zs *zp;
! 857: {
! 858: int rr0;
! 859: struct tty *tp = zp->tty;
! 860:
! 861: rr0 = ZREAD0(&zp->scc);
! 862: ZWRITE0(&zp->scc, 0x10);/* reset ext/status int */
! 863:
! 864: /* Handle break */
! 865: if (rr0 & 0x80) {
! 866: #ifdef DDB
! 867: if (ISSET(zp->flags, ZS_CONSOLE) && db_console != 0)
! 868: Debugger();
! 869: #endif
! 870: }
! 871:
! 872: if ((tp->t_cflag & CCTS_OFLOW) != 0) {
! 873: if ((rr0 & 0x20) == 0)
! 874: zp->hflags |= ZH_OBLOCK;
! 875: else {
! 876: zp->hflags &= ~ZH_OBLOCK;
! 877: if ((rr0 & SCC_TXRDY) != 0)
! 878: zs_txint(zp);
! 879: }
! 880: }
! 881: zp->modem_change |= rr0 ^ zp->modem_state;
! 882: zp->modem_state = rr0;
! 883: zp->hflags |= ZH_SIRQ;
! 884: setsoftint(sir_zs);
! 885: }
! 886:
! 887: /* ARGSUSED */
! 888: void
! 889: zs_softint(arg)
! 890: void *arg;
! 891: {
! 892: int s, c, stat, rr0;
! 893: struct zs *zp;
! 894: struct tty *tp;
! 895: u_char *get;
! 896: int unit, side;
! 897:
! 898: s = splzs();
! 899: for (unit = 0; unit < zs_cd.cd_ndevs; ++unit) {
! 900: if (zs_cd.cd_devs[unit] == NULL)
! 901: continue;
! 902: zp = &((struct zssoftc *) zs_cd.cd_devs[unit])->sc_zs[0];
! 903: for (side = 0; side < 2; ++side, ++zp) {
! 904: if ((zp->hflags & ZH_SIRQ) == 0)
! 905: continue;
! 906: zp->hflags &= ~ZH_SIRQ;
! 907: tp = zp->tty;
! 908:
! 909: /* check for tx done */
! 910: spltty();
! 911: if (tp != NULL && zp->send_count == 0
! 912: && (tp->t_state & TS_BUSY) != 0) {
! 913: tp->t_state &= ~(TS_BUSY | TS_FLUSH);
! 914: ndflush(&tp->t_outq, zp->sent_count);
! 915: if (tp->t_outq.c_cc <= tp->t_lowat) {
! 916: if (tp->t_state & TS_ASLEEP) {
! 917: tp->t_state &= ~TS_ASLEEP;
! 918: wakeup((caddr_t) & tp->t_outq);
! 919: }
! 920: selwakeup(&tp->t_wsel);
! 921: }
! 922: if (tp->t_line != 0)
! 923: (*linesw[tp->t_line].l_start) (tp);
! 924: else
! 925: zsstart(tp);
! 926: }
! 927: splzs();
! 928:
! 929: /* check for received characters */
! 930: get = zp->rcv_get;
! 931: while (zp->rcv_count > 0) {
! 932: c = *get++;
! 933: if (get >= zp->rcv_end)
! 934: get = zp->rcv_buf;
! 935: if (c == ERROR_DET) {
! 936: stat = *get++;
! 937: if (get >= zp->rcv_end)
! 938: get = zp->rcv_buf;
! 939: c = *get++;
! 940: if (get >= zp->rcv_end)
! 941: get = zp->rcv_buf;
! 942: zp->rcv_count -= 3;
! 943: } else {
! 944: stat = 0;
! 945: --zp->rcv_count;
! 946: }
! 947: spltty();
! 948: if (tp == NULL || (tp->t_state & TS_ISOPEN) == 0)
! 949: continue;
! 950: if (zp->nzs_open == 0) {
! 951:
! 952: } else {
! 953: if ((stat & 0x10) != 0)
! 954: c |= TTY_PE;
! 955: if ((stat & 0x20) != 0) {
! 956: log(LOG_WARNING, "zs: fifo overflow\n");
! 957: c |= TTY_FE; /* need some error for
! 958: * slip stuff */
! 959: }
! 960: if ((stat & 0x40) != 0)
! 961: c |= TTY_FE;
! 962: (*linesw[tp->t_line].l_rint) (c, tp);
! 963: }
! 964: splzs();
! 965: }
! 966: zp->rcv_get = get;
! 967:
! 968: /* check for modem lines changing */
! 969: while (zp->modem_change != 0 || zp->modem_state != zp->rr0) {
! 970: rr0 = zp->rr0 ^ zp->modem_change;
! 971: zp->modem_change = rr0 ^ zp->modem_state;
! 972:
! 973: /* Check if DCD (carrier detect) has changed */
! 974: if (tp != NULL && (rr0 & 8) != (zp->rr0 & 8)) {
! 975: spltty();
! 976: ttymodem(tp, rr0 & 8);
! 977: /* XXX possibly should disable line if
! 978: * return value is 0 */
! 979: splzs();
! 980: }
! 981: zp->rr0 = rr0;
! 982: }
! 983: }
! 984: }
! 985: splx(s);
! 986: }
! 987:
! 988: /*
! 989: * Routines for using side A of the first SCC as a console.
! 990: */
! 991:
! 992: /* probe for the SCC; should check hardware */
! 993: void
! 994: zscnprobe(cp)
! 995: struct consdev *cp;
! 996: {
! 997: int maj;
! 998:
! 999: switch (cputyp) {
! 1000: case CPU_147:
! 1001: case CPU_162:
! 1002: case CPU_172:
! 1003: break;
! 1004: default:
! 1005: return;
! 1006: }
! 1007:
! 1008: /* locate the major number */
! 1009: for (maj = 0; maj < nchrdev; maj++)
! 1010: if (cdevsw[maj].d_open == zsopen)
! 1011: break;
! 1012:
! 1013: cp->cn_dev = makedev(maj, 0);
! 1014: cp->cn_pri = CN_NORMAL;
! 1015: }
! 1016:
! 1017: /* initialize the keyboard for use as the console */
! 1018: struct termios zscn_termios = {
! 1019: TTYDEF_IFLAG,
! 1020: TTYDEF_OFLAG,
! 1021: (CREAD | CS8 | HUPCL),
! 1022: TTYDEF_LFLAG,
! 1023: {0},
! 1024: TTYDEF_SPEED,
! 1025: TTYDEF_SPEED
! 1026: };
! 1027:
! 1028: struct sccregs zs_cons_sccregs;
! 1029: int zs_cons_imask;
! 1030:
! 1031: /* Polling routine for console input from a serial port. */
! 1032: int
! 1033: zscngetc(dev)
! 1034: dev_t dev;
! 1035: {
! 1036: register struct sccregs *scc = zs_cons_scc;
! 1037: int c, s, stat;
! 1038:
! 1039: s = splhigh(); /* XXX was splzs() */
! 1040: for (;;) {
! 1041: while ((ZREAD0(scc) & SCC_RXFULL) == 0) /* wait for Rx full */
! 1042: ;
! 1043: stat = ZREAD(scc, 1) & 0x70;
! 1044: c = ZREADD(scc) & zs_cons_imask;
! 1045: /* stat encodes parity, overrun, framing errors */
! 1046: if (stat == 0)
! 1047: break;
! 1048: ZWRITE0(scc, 0x30); /* reset error */
! 1049: }
! 1050: splx(s);
! 1051: return (c);
! 1052: }
! 1053:
! 1054: void
! 1055: zscnputc(dev, c)
! 1056: dev_t dev;
! 1057: int c;
! 1058: {
! 1059: register struct sccregs *scc = zs_cons_scc;
! 1060: int s;
! 1061:
! 1062: s = splhigh(); /* XXX was splzs() */
! 1063: while ((ZREAD0(scc) & SCC_TXRDY) == 0)
! 1064: ;
! 1065: ZWRITED(scc, c);
! 1066: splx(s);
! 1067: }
! 1068:
! 1069: void
! 1070: zscninit(cp)
! 1071: struct consdev *cp;
! 1072: {
! 1073: int unit = 0;
! 1074: struct termios *tiop = &zscn_termios;
! 1075: volatile u_char *scc_cr, *scc_dr;
! 1076: struct sccregs *scc;
! 1077: int size;
! 1078:
! 1079: zs_cons_unit = unit;
! 1080: zs_is_console = 1;
! 1081: zs_cons_scc = scc = &zs_cons_sccregs;
! 1082:
! 1083: /*
! 1084: * the locations of the control and data register move around
! 1085: * on different MVME models, so we generate independent pointers
! 1086: * to them.
! 1087: */
! 1088: size = zsregs(0, unit, &scc_cr, &scc_dr);
! 1089:
! 1090: *(scc_cr + size) = 0;
! 1091: *(scc_cr + size) = 9;
! 1092: *(scc_cr + size) = 0xC0; /* hardware reset of SCC, both sides */
! 1093: if (!zsside(unit)) {
! 1094: scc_cr += size;
! 1095: scc_dr += size;
! 1096: }
! 1097:
! 1098: scc->s_cr = scc_cr;
! 1099: scc->s_dr = scc_dr;
! 1100: #if defined(MVME162) || defined(MVME172)
! 1101: if (cputyp == CPU_162 || cputyp == CPU_172)
! 1102: ZWRITE(scc, 2, MC_VECBASE+MCV_ZS);
! 1103: #endif
! 1104: ZWRITE(scc, 10, 0);
! 1105: ZWRITE(scc, 11, 0x50); /* rx & tx clock = brgen */
! 1106: ZWRITE(scc, 14, 3); /* brgen enabled, from pclk */
! 1107: zs_cons_imask = zscc_params(scc, tiop);
! 1108: ZBIS(scc, 5, 0x82); /* set DTR and RTS */
! 1109:
! 1110: zs_cons_termios = *tiop;/* save for later */
! 1111: }
! 1112:
! 1113: #ifdef MVME147
! 1114: u_long zs_cons_addrs_147[] = { ZS0_PHYS_147, ZS1_PHYS_147};
! 1115: #endif
! 1116: #if defined(MVME162) || defined(MVME172)
! 1117: u_long zs_cons_addrs_162[] = { ZS0_PHYS_162, ZS1_PHYS_162};
! 1118: #endif
! 1119:
! 1120: /*
! 1121: * fills in pointers to the registers and returns how far apart
! 1122: * the two halves of the chip are.
! 1123: *
! 1124: * it vaddr == NULL, it tries to determine the hardware address in
! 1125: * an intelligent fashion from the unit number.
! 1126: */
! 1127: int
! 1128: zsregs(va, unit, crp, drp)
! 1129: vaddr_t va;
! 1130: int unit;
! 1131: volatile u_char **crp, **drp;
! 1132: {
! 1133: #ifdef MVME147
! 1134: volatile struct scc_147 *scc_adr_147;
! 1135: #endif
! 1136: #if defined(MVME162) || defined(MVME172)
! 1137: volatile struct scc_162 *scc_adr_162;
! 1138: #endif
! 1139: volatile u_char *scc_cr, *scc_dr;
! 1140: int size;
! 1141:
! 1142: switch (cputyp) {
! 1143: #ifdef MVME147
! 1144: case CPU_147:
! 1145: if (va == 0)
! 1146: va = IIOV(zs_cons_addrs_147[unit]);
! 1147: scc_adr_147 = (volatile struct scc_147 *)va;
! 1148: scc_cr = &scc_adr_147->cr;
! 1149: scc_dr = &scc_adr_147->dr;
! 1150: size = sizeof(struct scc_147);
! 1151: break;
! 1152: #endif
! 1153: #if defined(MVME162) || defined(MVME172)
! 1154: case CPU_162:
! 1155: case CPU_172:
! 1156: if (va == 0)
! 1157: va = IIOV(zs_cons_addrs_162[unit]);
! 1158: scc_adr_162 = (volatile struct scc_162 *)va;
! 1159: scc_cr = &scc_adr_162->cr;
! 1160: scc_dr = &scc_adr_162->dr;
! 1161: size = sizeof(struct scc_162);
! 1162: break;
! 1163: #endif
! 1164: }
! 1165:
! 1166: *crp = scc_cr;
! 1167: *drp = scc_dr;
! 1168: return (size);
! 1169: }
! 1170:
! 1171: int
! 1172: zspclk()
! 1173: {
! 1174: switch (cputyp) {
! 1175: #ifdef MVME147
! 1176: case CPU_147:
! 1177: return (PCLK_FREQ_147);
! 1178: #endif
! 1179: #if defined(MVME162) || defined(MVME172)
! 1180: case CPU_162:
! 1181: case CPU_172:
! 1182: return (PCLK_FREQ_162);
! 1183: #endif
! 1184: default:
! 1185: return 0;
! 1186: }
! 1187: }
CVSweb