Annotation of sys/arch/mvme68k/dev/wl.c, Revision 1.1
1.1 ! nbrk 1: /* $OpenBSD: wl.c,v 1.18 2005/11/24 22:43:16 miod Exp $ */
! 2:
! 3: /*
! 4: * Copyright (c) 1995 Dale Rahn. All rights reserved.
! 5: *
! 6: * Redistribution and use in source and binary forms, with or without
! 7: * modification, are permitted provided that the following conditions
! 8: * are met:
! 9: * 1. Redistributions of source code must retain the above copyright
! 10: * notice, this list of conditions and the following disclaimer.
! 11: * 2. Redistributions in binary form must reproduce the above copyright
! 12: * notice, this list of conditions and the following disclaimer in the
! 13: * documentation and/or other materials provided with the distribution.
! 14: *
! 15: * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
! 16: * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
! 17: * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
! 18: * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
! 19: * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
! 20: * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
! 21: * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
! 22: * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
! 23: * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
! 24: * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
! 25: */
! 26:
! 27: #include <sys/param.h>
! 28: #include <sys/ioctl.h>
! 29: #include <sys/proc.h>
! 30: #include <sys/tty.h>
! 31: #include <sys/uio.h>
! 32: #include <sys/systm.h>
! 33: #include <sys/time.h>
! 34: #include <sys/device.h>
! 35: #include <sys/syslog.h>
! 36:
! 37: #include <machine/autoconf.h>
! 38: #include <machine/conf.h>
! 39: #include <machine/cpu.h>
! 40:
! 41: #include <mvme68k/dev/wlreg.h>
! 42: #include <mvme68k/dev/vme.h>
! 43:
! 44: #include "cl.h"
! 45:
! 46: #include "vmes.h"
! 47:
! 48: #define splcl() spltty()
! 49:
! 50: /* min timeout 0xa, what is a good value */
! 51: #define CL_TIMEOUT 0x10
! 52: #define CL_FIFO_MAX 0x10
! 53: #define CL_FIFO_CNT 0xc
! 54: #define CL_RX_TIMEOUT 0x10
! 55:
! 56: #define CL_RXDMAINT 0x82
! 57: #define CL_TXDMAINT 0x42
! 58: #define CL_TXMASK 0x47
! 59: #define CL_RXMASK 0x87
! 60: #define CL_TXINTR 0x02
! 61: #define CL_RXINTR 0x02
! 62:
! 63: #define WLRAMLEN (1 << 16)
! 64: struct clboard {
! 65: union {
! 66: struct clreg clreg;
! 67: volatile char xx[256];
! 68: } chips[2];
! 69: union {
! 70: volatile u_char base;
! 71: volatile char xx[256];
! 72: } sram;
! 73: union {
! 74: volatile u_char val;
! 75: volatile char xx[256];
! 76: } ringstatus;
! 77: union {
! 78: volatile u_char val;
! 79: volatile char xx[256];
! 80: } ringreset;
! 81: union {
! 82: volatile u_char val;
! 83: volatile char xx[256];
! 84: } master;
! 85: union {
! 86: volatile u_char val;
! 87: volatile char xx[256];
! 88: } reset;
! 89: };
! 90:
! 91:
! 92: struct cl_info {
! 93: struct tty *tty;
! 94: u_char cl_swflags;
! 95: u_char cl_softchar;
! 96: u_char cl_speed;
! 97: u_char cl_parstop; /* parity, stop bits. */
! 98: u_char cl_rxmode;
! 99: u_char cl_txmode;
! 100: u_char cl_clen;
! 101: u_char cl_parity;
! 102: u_char transmitting;
! 103: u_long txcnt;
! 104: u_long rxcnt;
! 105:
! 106: volatile void *rx[2];
! 107: volatile void *rxp[2];
! 108: volatile void *tx[2];
! 109: volatile void *txp[2];
! 110: };
! 111: #define CLCD_PORTS_PER_CHIP 4
! 112: #define CL_BUFSIZE 128
! 113:
! 114: struct wlsoftc {
! 115: struct device sc_dev;
! 116: char sc_txintrname[16 + 3];
! 117: char sc_rxintrname[16 + 3];
! 118: char sc_mxintrname[16 + 3];
! 119:
! 120: time_t sc_rotime; /* time of last ring overrun */
! 121: time_t sc_fotime; /* time of last fifo overrun */
! 122:
! 123: u_char sc_memv;
! 124: paddr_t sc_memvme;
! 125: void *sc_memp;
! 126: vaddr_t sc_memkv;
! 127:
! 128: struct clreg *cl_reg;
! 129: struct cl_info sc_cl[CLCD_PORTS_PER_CHIP];
! 130: struct intrhand sc_ih_e;
! 131: struct intrhand sc_ih_m;
! 132: struct intrhand sc_ih_t;
! 133: struct intrhand sc_ih_r;
! 134: u_char sc_vec;
! 135: int sc_flags;
! 136: };
! 137:
! 138: struct {
! 139: u_int speed;
! 140: u_char divisor;
! 141: u_char clock;
! 142: u_char rx_timeout;
! 143: } cl_clocks[] = {
! 144: /* 30.000 MHz */
! 145: { 64000, 0x3a, 0, 0x01 },
! 146: { 56000, 0x42, 0, 0x01 },
! 147: { 38400, 0x61, 0, 0x01 },
! 148: { 19200, 0xc2, 0, 0x01 },
! 149: { 9600, 0x61, 1, 0x02 },
! 150: { 7200, 0x81, 1, 0x04 },
! 151: { 4800, 0xc2, 1, 0x04 },
! 152: { 3600, 0x40, 2, 0x08 },
! 153: { 2400, 0x61, 2, 0x10 },
! 154: { 1200, 0xc2, 2, 0x20 },
! 155: { 600, 0x61, 3, 0x40 },
! 156: { 300, 0xc2, 3, 0x80 },
! 157: { 150, 0x61, 4, 0xa0 },
! 158: { 110, 0x84, 4, 0xff },
! 159: { 50, 0x00, 5, 0xff },
! 160: { 0, 0x00, 0, 0},
! 161: };
! 162:
! 163: /* prototypes */
! 164: u_char cl_clkdiv(int speed);
! 165: u_char cl_clknum(int speed);
! 166: u_char cl_clkrxtimeout(int speed);
! 167: void clstart(struct tty *tp);
! 168: void cl_unblock(struct tty *tp);
! 169: int clccparam(struct wlsoftc *sc, struct termios *par, int channel);
! 170:
! 171: int clparam(struct tty *tp, struct termios *t);
! 172: int cl_intr(struct wlsoftc *sc, int);
! 173: int cl_mintr(struct wlsoftc *sc);
! 174: int cl_txintr(struct wlsoftc *sc);
! 175: int cl_rxintr(struct wlsoftc *sc);
! 176: void cl_overflow(struct wlsoftc *sc, int channel, long *ptime, u_char *msg);
! 177: void cl_parity(struct wlsoftc *sc, int channel);
! 178: void cl_frame(struct wlsoftc *sc, int channel);
! 179: void cl_break( struct wlsoftc *sc, int channel);
! 180: int clmctl(dev_t dev, int bits, int how);
! 181: void cl_dumpport(int channel);
! 182:
! 183: int wlprobe(struct device *parent, void *self, void *aux);
! 184: void wlattach(struct device *parent, struct device *self, void *aux);
! 185:
! 186: static void cl_initchannel(struct wlsoftc *sc, int channel);
! 187: static void clputc(struct wlsoftc *sc, int unit, u_char c);
! 188: static u_char clgetc(struct wlsoftc *sc, int *channel);
! 189: static void cloutput(struct tty *tp);
! 190:
! 191: struct cfattach wl_ca = {
! 192: sizeof(struct wlsoftc), wlprobe, wlattach
! 193: };
! 194:
! 195: struct cfdriver wl_cd = {
! 196: NULL, "wl", DV_TTY
! 197: };
! 198:
! 199: #define CLCDBUF 80
! 200:
! 201: #define CL_UNIT(x) (minor(x) >> 2)
! 202: #define CL_CHANNEL(x) (minor(x) & 3)
! 203: #define CL_TTY(x) (minor(x))
! 204:
! 205: extern int cputyp;
! 206:
! 207: struct tty *
! 208: wltty(dev)
! 209: dev_t dev;
! 210: {
! 211: int unit = CL_UNIT(dev);
! 212: int channel;
! 213: struct wlsoftc *sc;
! 214:
! 215: if (unit >= wl_cd.cd_ndevs ||
! 216: (sc = (struct wlsoftc *) wl_cd.cd_devs[unit]) == NULL)
! 217: return (NULL);
! 218: channel = CL_CHANNEL(dev);
! 219: return sc->sc_cl[channel].tty;
! 220: }
! 221:
! 222: int
! 223: wlprobe(parent, self, aux)
! 224: struct device *parent;
! 225: void *self;
! 226: void *aux;
! 227: {
! 228: struct confargs *ca = aux;
! 229: struct wlsoftc *sc = self;
! 230: struct clreg *cl_reg = (struct clreg *)ca->ca_vaddr;
! 231:
! 232: if (ca->ca_vec & 0x03) {
! 233: printf("%s: bad vector\n", sc->sc_dev.dv_xname);
! 234: return (0);
! 235: }
! 236: return (!badvaddr(&cl_reg->cl_gfrcr, 1));
! 237: }
! 238:
! 239: void
! 240: wlattach(parent, self, aux)
! 241: struct device *parent;
! 242: struct device *self;
! 243: void *aux;
! 244: {
! 245: struct wlsoftc *sc = (struct wlsoftc *)self;
! 246: struct confargs *ca = aux;
! 247: struct clboard *clb = (struct clboard *)ca->ca_vaddr;
! 248: void *p;
! 249: int i, j, s;
! 250:
! 251: sc->cl_reg = (struct clreg *)&clb->chips[0].clreg;
! 252: sc->sc_vec = ca->ca_vec;
! 253:
! 254: sc->sc_memv = 0xa5 + 0;
! 255: sc->sc_memvme = ((0xff00 + sc->sc_memv) << 16);
! 256:
! 257: clb->reset.val = 0xff; /* reset card */
! 258: DELAY(1000);
! 259: clb->sram.base = (sc->sc_memvme >> 16) & 0xff;
! 260: DELAY(1000);
! 261: clb->master.val = 0x01; /* enable sram decoder */
! 262: DELAY(1000);
! 263:
! 264: printf(":");
! 265: /*printf(" va=%x sc=%x slot 0x%02x vmes 0x%08x", sc->cl_reg, sc,
! 266: sc->sc_memv, sc->sc_memvme);*/
! 267:
! 268: while (sc->cl_reg->cl_gfrcr == 0x00)
! 269: ;
! 270: sc->cl_reg->cl_ccr = 0x10; /* reset it */
! 271: while (sc->cl_reg->cl_gfrcr == 0x00)
! 272: ;
! 273: if (sc->cl_reg->cl_gfrcr <= 0x10)
! 274: printf(" rev %c", 'A' + sc->cl_reg->cl_gfrcr);
! 275: else
! 276: printf(" rev 0x%02x", sc->cl_reg->cl_gfrcr);
! 277: printf("\n");
! 278:
! 279: /* set up global registers */
! 280: sc->cl_reg->cl_tpr = CL_TIMEOUT;
! 281: sc->cl_reg->cl_rpilr = (ca->ca_ipl << 1) | 1;
! 282: sc->cl_reg->cl_tpilr = (ca->ca_ipl << 1) | 1;
! 283: sc->cl_reg->cl_mpilr = (ca->ca_ipl << 1) | 1;
! 284:
! 285: sc->sc_memkv = vmemap(((struct vmessoftc *)parent)->sc_vme,
! 286: sc->sc_memvme, WLRAMLEN, BUS_VMES);
! 287: sc->sc_memp = (void *)kvtop(sc->sc_memkv);
! 288: if (sc->sc_memkv == 0)
! 289: printf("%s: got no memory", sc->sc_dev.dv_xname);
! 290: else if (badvaddr(sc->sc_memkv, 1))
! 291: printf("%s: cannot tap 0x%08x", sc->sc_dev.dv_xname, sc->sc_memkv);
! 292: else {
! 293: u_char *x = (u_char *)sc->sc_memkv;
! 294:
! 295: /*printf("%s: pa 0x%08x va 0x%08x", sc->sc_dev.dv_xname,
! 296: sc->sc_memp, sc->sc_memkv);*/
! 297: x[0] = 0xaa;
! 298: x[1] = 0x55;
! 299: if (x[0] != 0xaa || x[1] != 0x55)
! 300: printf(" 0x%02x 0x%02x", x[0], x[1]);
! 301: x[0] = 0x55;
! 302: x[1] = 0xaa;
! 303: if (x[0] != 0x55 || x[1] != 0xaa)
! 304: printf(" 0x%02x 0x%02x", x[0], x[1]);
! 305: bzero(x, WLRAMLEN);
! 306: }
! 307:
! 308: /* enable interrupts */
! 309: sc->sc_ih_e.ih_fn = cl_intr;
! 310: sc->sc_ih_e.ih_arg = sc;
! 311: sc->sc_ih_e.ih_ipl = ca->ca_ipl;
! 312: sc->sc_ih_e.ih_wantframe = 0;
! 313:
! 314: sc->sc_ih_m.ih_fn = cl_intr;
! 315: sc->sc_ih_m.ih_arg = sc;
! 316: sc->sc_ih_m.ih_ipl = ca->ca_ipl;
! 317: sc->sc_ih_m.ih_wantframe = 0;
! 318:
! 319: sc->sc_ih_t.ih_fn = cl_intr;
! 320: sc->sc_ih_t.ih_arg = sc;
! 321: sc->sc_ih_t.ih_ipl = ca->ca_ipl;
! 322: sc->sc_ih_t.ih_wantframe = 0;
! 323:
! 324: sc->sc_ih_r.ih_fn = cl_intr;
! 325: sc->sc_ih_r.ih_arg = sc;
! 326: sc->sc_ih_r.ih_ipl = ca->ca_ipl;
! 327: sc->sc_ih_r.ih_wantframe = 0;
! 328:
! 329: snprintf(sc->sc_txintrname, sizeof sc->sc_txintrname,
! 330: "%s_tx", self->dv_xname);
! 331: snprintf(sc->sc_rxintrname, sizeof sc->sc_rxintrname,
! 332: "%s_rx", self->dv_xname);
! 333: snprintf(sc->sc_mxintrname, sizeof sc->sc_mxintrname,
! 334: "%s_mx", self->dv_xname);
! 335:
! 336: vmeintr_establish(ca->ca_vec + 0, &sc->sc_ih_e, sc->sc_rxintrname);
! 337: vmeintr_establish(ca->ca_vec + 1, &sc->sc_ih_m, sc->sc_mxintrname);
! 338: vmeintr_establish(ca->ca_vec + 2, &sc->sc_ih_t, sc->sc_txintrname);
! 339: vmeintr_establish(ca->ca_vec + 3, &sc->sc_ih_r, sc->sc_rxintrname);
! 340:
! 341: p = (void *)sc->sc_memkv;
! 342: s = splhigh();
! 343: for (i = 0; i < CLCD_PORTS_PER_CHIP; i++) {
! 344: for (j = 0; j < 2; j++) {
! 345: sc->sc_cl[i].rx[j] = p;
! 346: sc->sc_cl[i].rxp[j] = (void *)(p - (void *)sc->sc_memkv);
! 347: /*printf("%d:%d rx v %x p %x\n",
! 348: i, j, sc->sc_cl[i].rx[j], sc->sc_cl[i].rxp[j]);*/
! 349: p += CL_BUFSIZE;
! 350: }
! 351: for (j = 0; j < 2; j++) {
! 352: sc->sc_cl[i].tx[j] = p;
! 353: sc->sc_cl[i].txp[j] = (void *)(p - (void *)sc->sc_memkv);
! 354: /*printf("%d:%d tx v %x p %x\n",
! 355: i, j, sc->sc_cl[i].tx[j], sc->sc_cl[i].txp[j]);*/
! 356: p += CL_BUFSIZE;
! 357: }
! 358: cl_initchannel(sc, i);
! 359: }
! 360: splx(s);
! 361: }
! 362:
! 363: static void
! 364: cl_initchannel(sc, channel)
! 365: struct wlsoftc *sc;
! 366: int channel;
! 367: {
! 368: struct clreg *cl_reg = sc->cl_reg;
! 369:
! 370: /* set up option registers */
! 371: cl_reg->cl_car = channel;
! 372: cl_reg->cl_livr = sc->sc_vec;
! 373: cl_reg->cl_ier = 0x00;
! 374: cl_reg->cl_cmr = 0x02;
! 375: cl_reg->cl_cor1 = 0x17;
! 376: cl_reg->cl_cor2 = 0x00;
! 377: cl_reg->cl_cor3 = 0x02;
! 378: cl_reg->cl_cor4 = 0xec;
! 379: cl_reg->cl_cor5 = 0xec;
! 380: cl_reg->cl_cor6 = 0x00;
! 381: cl_reg->cl_cor7 = 0x00;
! 382: cl_reg->cl_schr1 = 0x00;
! 383: cl_reg->cl_schr2 = 0x00;
! 384: cl_reg->cl_schr3 = 0x00;
! 385: cl_reg->cl_schr4 = 0x00;
! 386: cl_reg->cl_scrl = 0x00;
! 387: cl_reg->cl_scrh = 0x00;
! 388: cl_reg->cl_lnxt = 0x00;
! 389: cl_reg->cl_rbpr = 0x40; /* 9600 */
! 390: cl_reg->cl_rcor = 0x01;
! 391: cl_reg->cl_tbpr = 0x40; /* 9600 */
! 392: cl_reg->cl_tcor = 0x01 << 5;
! 393: /* console port should be 0x88 already */
! 394: cl_reg->cl_msvr_rts = 0x00;
! 395: cl_reg->cl_msvr_dtr = 0x00;
! 396: cl_reg->cl_rtprl = CL_RX_TIMEOUT;
! 397: cl_reg->cl_rtprh = 0x00;
! 398: sc->cl_reg->cl_ccr = 0x20;
! 399: while (sc->cl_reg->cl_ccr != 0)
! 400: ;
! 401: }
! 402:
! 403:
! 404: int cldefaultrate = TTYDEF_SPEED;
! 405:
! 406: int clmctl (dev, bits, how)
! 407: dev_t dev;
! 408: int bits;
! 409: int how;
! 410: {
! 411: int s;
! 412: struct wlsoftc *sc;
! 413: /* should only be called with valid device */
! 414: sc = (struct wlsoftc *) wl_cd.cd_devs[CL_UNIT(dev)];
! 415: /*
! 416: printf("mctl: dev %x, bits %x, how %x,\n",dev, bits, how);
! 417: */
! 418: /* settings are currently ignored */
! 419: s = splcl();
! 420: switch (how) {
! 421: case DMSET:
! 422: if( bits & TIOCM_RTS) {
! 423: sc->cl_reg->cl_msvr_rts = 0x01;
! 424: } else {
! 425: sc->cl_reg->cl_msvr_rts = 0x00;
! 426: }
! 427: if( bits & TIOCM_DTR) {
! 428: sc->cl_reg->cl_msvr_dtr = 0x02;
! 429: } else {
! 430: sc->cl_reg->cl_msvr_dtr = 0x00;
! 431: }
! 432: break;
! 433:
! 434: case DMBIC:
! 435: if( bits & TIOCM_RTS) {
! 436: sc->cl_reg->cl_msvr_rts = 0x00;
! 437: }
! 438: if( bits & TIOCM_DTR) {
! 439: sc->cl_reg->cl_msvr_dtr = 0x00;
! 440: }
! 441: break;
! 442:
! 443: case DMBIS:
! 444: if( bits & TIOCM_RTS) {
! 445: sc->cl_reg->cl_msvr_rts = 0x01;
! 446: }
! 447: if( bits & TIOCM_DTR) {
! 448: sc->cl_reg->cl_msvr_dtr = 0x02;
! 449: }
! 450: break;
! 451:
! 452: case DMGET:
! 453: bits = 0;
! 454:
! 455: {
! 456: u_char msvr;
! 457: msvr = sc->cl_reg->cl_msvr_rts;
! 458: if( msvr & 0x80) {
! 459: bits |= TIOCM_DSR;
! 460: }
! 461: if( msvr & 0x40) {
! 462: bits |= TIOCM_CD;
! 463: }
! 464: if( msvr & 0x20) {
! 465: bits |= TIOCM_CTS;
! 466: }
! 467: if( msvr & 0x10) {
! 468: bits |= TIOCM_DTR;
! 469: }
! 470: if( msvr & 0x02) {
! 471: bits |= TIOCM_DTR;
! 472: }
! 473: if( msvr & 0x01) {
! 474: bits |= TIOCM_RTS;
! 475: }
! 476:
! 477: }
! 478: break;
! 479: }
! 480: splx(s);
! 481: #if 0
! 482: bits = 0;
! 483: /* proper defaults? */
! 484: bits |= TIOCM_DTR;
! 485: bits |= TIOCM_RTS;
! 486: bits |= TIOCM_CTS;
! 487: bits |= TIOCM_CD;
! 488: /* bits |= TIOCM_RI; */
! 489: bits |= TIOCM_DSR;
! 490: #endif
! 491:
! 492: /*
! 493: printf("retbits %x\n", bits);
! 494: */
! 495: return(bits);
! 496: }
! 497:
! 498: int
! 499: wlopen(dev, flag, mode, p)
! 500: dev_t dev;
! 501: int flag;
! 502: int mode;
! 503: struct proc *p;
! 504: {
! 505: int s, unit, channel;
! 506: struct cl_info *cl;
! 507: struct wlsoftc *sc;
! 508: struct tty *tp;
! 509:
! 510: unit = CL_UNIT(dev);
! 511: if (unit >= wl_cd.cd_ndevs ||
! 512: (sc = (struct wlsoftc *) wl_cd.cd_devs[unit]) == NULL) {
! 513: return (ENODEV);
! 514: }
! 515: channel = CL_CHANNEL(dev);
! 516: cl = &sc->sc_cl[channel];
! 517: s = splcl();
! 518: if (cl->tty) {
! 519: tp = cl->tty;
! 520: } else {
! 521: tp = cl->tty = ttymalloc();
! 522: }
! 523: tp->t_oproc = clstart;
! 524: tp->t_param = clparam;
! 525: tp->t_dev = dev;
! 526:
! 527: if ((tp->t_state & TS_ISOPEN) == 0) {
! 528: tp->t_state |= TS_WOPEN;
! 529: ttychars(tp);
! 530: if (tp->t_ispeed == 0) {
! 531: /*
! 532: * only when cleared do we reset to defaults.
! 533: */
! 534: tp->t_iflag = TTYDEF_IFLAG;
! 535: tp->t_oflag = TTYDEF_OFLAG;
! 536: tp->t_lflag = TTYDEF_LFLAG;
! 537: tp->t_ispeed = tp->t_ospeed = cldefaultrate;
! 538:
! 539: tp->t_cflag = TTYDEF_CFLAG;
! 540: }
! 541: /*
! 542: * do these all the time
! 543: */
! 544: if (cl->cl_swflags & TIOCFLAG_CLOCAL)
! 545: tp->t_cflag |= CLOCAL;
! 546: if (cl->cl_swflags & TIOCFLAG_CRTSCTS)
! 547: tp->t_cflag |= CRTSCTS;
! 548: if (cl->cl_swflags & TIOCFLAG_MDMBUF)
! 549: tp->t_cflag |= MDMBUF;
! 550: clparam(tp, &tp->t_termios);
! 551: ttsetwater(tp);
! 552:
! 553: (void)clmctl(dev, TIOCM_DTR | TIOCM_RTS, DMSET);
! 554: tp->t_state |= TS_CARR_ON;
! 555: {
! 556: u_char save = sc->cl_reg->cl_car;
! 557: sc->cl_reg->cl_car = channel;
! 558: sc->cl_reg->cl_ier = IER_MDM | IER_RXD;
! 559: sc->cl_reg->cl_car = save;
! 560: }
! 561: } else if (tp->t_state & TS_XCLUDE && p->p_ucred->cr_uid != 0) {
! 562: splx(s);
! 563: return(EBUSY);
! 564: }
! 565:
! 566: splx(s);
! 567: /*
! 568: * Reset the tty pointer, as there could have been a dialout
! 569: * use of the tty with a dialin open waiting.
! 570: */
! 571: tp->t_dev = dev;
! 572: return((*linesw[tp->t_line].l_open)(dev, tp));
! 573: }
! 574:
! 575: int clparam(tp, t)
! 576: struct tty *tp;
! 577: struct termios *t;
! 578: {
! 579: int unit, channel;
! 580: struct wlsoftc *sc;
! 581: int s;
! 582: dev_t dev;
! 583:
! 584: dev = tp->t_dev;
! 585: unit = CL_UNIT(dev);
! 586: if (unit >= wl_cd.cd_ndevs ||
! 587: (sc = (struct wlsoftc *) wl_cd.cd_devs[unit]) == NULL) {
! 588: return (ENODEV);
! 589: }
! 590: channel = CL_CHANNEL(dev);
! 591: tp->t_ispeed = t->c_ispeed;
! 592: tp->t_ospeed = t->c_ospeed;
! 593: tp->t_cflag = t->c_cflag;
! 594: clccparam(sc, t, channel);
! 595: s = splcl();
! 596: cl_unblock(tp);
! 597: splx(s);
! 598: return 0;
! 599: }
! 600:
! 601: void cloutput(tp)
! 602: struct tty *tp;
! 603: {
! 604: int cc, s, unit, cnt;
! 605: u_char *tptr;
! 606: int channel;
! 607: struct wlsoftc *sc;
! 608: dev_t dev;
! 609: u_char cl_obuffer[CLCDBUF+1];
! 610:
! 611: dev = tp->t_dev;
! 612: unit = CL_UNIT(dev);
! 613: if (unit >= wl_cd.cd_ndevs ||
! 614: (sc = (struct wlsoftc *) wl_cd.cd_devs[unit]) == NULL) {
! 615: return;
! 616: }
! 617: channel = CL_CHANNEL(dev);
! 618:
! 619: if ((tp->t_state & TS_ISOPEN) == 0)
! 620: return;
! 621:
! 622: s = splcl();
! 623: cc = tp->t_outq.c_cc;
! 624: while (cc > 0) {
! 625: /*XXX*/
! 626: cnt = min(CLCDBUF,cc);
! 627: cnt = q_to_b(&tp->t_outq, cl_obuffer, cnt);
! 628: if (cnt == 0) {
! 629: break;
! 630: }
! 631: for (tptr = cl_obuffer; tptr < &cl_obuffer[cnt]; tptr++) {
! 632: clputc(sc, channel, *tptr);
! 633: }
! 634: cc -= cnt;
! 635: }
! 636: splx(s);
! 637: }
! 638:
! 639: int
! 640: wlclose(dev, flag, mode, p)
! 641: dev_t dev;
! 642: int flag;
! 643: int mode;
! 644: struct proc *p;
! 645: {
! 646: int unit, channel;
! 647: struct tty *tp;
! 648: struct cl_info *cl;
! 649: struct wlsoftc *sc;
! 650: int s;
! 651: unit = CL_UNIT(dev);
! 652: if (unit >= wl_cd.cd_ndevs ||
! 653: (sc = (struct wlsoftc *) wl_cd.cd_devs[unit]) == NULL) {
! 654: return (ENODEV);
! 655: }
! 656: channel = CL_CHANNEL(dev);
! 657: cl = &sc->sc_cl[channel];
! 658: tp = cl->tty;
! 659: (*linesw[tp->t_line].l_close)(tp, flag);
! 660:
! 661: s = splcl();
! 662:
! 663: sc->cl_reg->cl_car = channel;
! 664: if((tp->t_cflag & HUPCL) != 0) {
! 665: sc->cl_reg->cl_msvr_rts = 0x00;
! 666: sc->cl_reg->cl_msvr_dtr = 0x00;
! 667: sc->cl_reg->cl_ccr = 0x05;
! 668: sc->cl_reg->cl_ier = 0x00;
! 669: }
! 670:
! 671: splx(s);
! 672: ttyclose(tp);
! 673:
! 674: #if 0
! 675: cl->tty = NULL;
! 676: #endif
! 677: return (0);
! 678: }
! 679:
! 680: int
! 681: wlread(dev, uio, flag)
! 682: dev_t dev;
! 683: struct uio *uio;
! 684: int flag;
! 685: {
! 686: int unit, channel;
! 687: struct tty *tp;
! 688: struct cl_info *cl;
! 689: struct wlsoftc *sc;
! 690: unit = CL_UNIT(dev);
! 691: if (unit >= wl_cd.cd_ndevs ||
! 692: (sc = (struct wlsoftc *) wl_cd.cd_devs[unit]) == NULL) {
! 693: return (ENODEV);
! 694: }
! 695: channel = CL_CHANNEL(dev);
! 696: cl = &sc->sc_cl[channel];
! 697: tp = cl->tty;
! 698: if (!tp)
! 699: return ENXIO;
! 700: return((*linesw[tp->t_line].l_read)(tp, uio, flag));
! 701: }
! 702: int
! 703: wlwrite(dev, uio, flag)
! 704: dev_t dev;
! 705: struct uio *uio;
! 706: int flag;
! 707: {
! 708: int unit, channel;
! 709: struct tty *tp;
! 710: struct cl_info *cl;
! 711: struct wlsoftc *sc;
! 712: unit = CL_UNIT(dev);
! 713: if (unit >= wl_cd.cd_ndevs ||
! 714: (sc = (struct wlsoftc *) wl_cd.cd_devs[unit]) == NULL) {
! 715: return (ENODEV);
! 716: }
! 717: channel = CL_CHANNEL(dev);
! 718: cl = &sc->sc_cl[channel];
! 719: tp = cl->tty;
! 720: if (!tp)
! 721: return ENXIO;
! 722: return((*linesw[tp->t_line].l_write)(tp, uio, flag));
! 723: }
! 724: int
! 725: wlioctl(dev, cmd, data, flag, p)
! 726: dev_t dev;
! 727: u_long cmd;
! 728: caddr_t data;
! 729: int flag;
! 730: struct proc *p;
! 731: {
! 732: int error;
! 733: int unit, channel;
! 734: struct tty *tp;
! 735: struct cl_info *cl;
! 736: struct wlsoftc *sc;
! 737: unit = CL_UNIT(dev);
! 738: if (unit >= wl_cd.cd_ndevs ||
! 739: (sc = (struct wlsoftc *) wl_cd.cd_devs[unit]) == NULL) {
! 740: return (ENODEV);
! 741: }
! 742: channel = CL_CHANNEL(dev);
! 743: cl = &sc->sc_cl[channel];
! 744: tp = cl->tty;
! 745: if (!tp)
! 746: return ENXIO;
! 747:
! 748: error = (*linesw[tp->t_line].l_ioctl)(tp, cmd, data, flag, p);
! 749: if (error >= 0)
! 750: return(error);
! 751:
! 752: error = ttioctl(tp, cmd, data, flag, p);
! 753: if (error >= 0)
! 754: return(error);
! 755:
! 756: switch (cmd) {
! 757: case TIOCSBRK:
! 758: /* */
! 759: break;
! 760:
! 761: case TIOCCBRK:
! 762: /* */
! 763: break;
! 764:
! 765: case TIOCSDTR:
! 766: (void) clmctl(dev, TIOCM_DTR | TIOCM_RTS, DMBIS);
! 767: break;
! 768:
! 769: case TIOCCDTR:
! 770: (void) clmctl(dev, TIOCM_DTR | TIOCM_RTS, DMBIC);
! 771: break;
! 772:
! 773: case TIOCMSET:
! 774: (void) clmctl(dev, *(int *) data, DMSET);
! 775: break;
! 776:
! 777: case TIOCMBIS:
! 778: (void) clmctl(dev, *(int *) data, DMBIS);
! 779: break;
! 780:
! 781: case TIOCMBIC:
! 782: (void) clmctl(dev, *(int *) data, DMBIC);
! 783: break;
! 784:
! 785: case TIOCMGET:
! 786: *(int *)data = clmctl(dev, 0, DMGET);
! 787: break;
! 788: case TIOCGFLAGS:
! 789: *(int *)data = cl->cl_swflags;
! 790: break;
! 791: case TIOCSFLAGS:
! 792: error = suser(p, 0);
! 793: if (error != 0)
! 794: return(EPERM);
! 795:
! 796: cl->cl_swflags = *(int *)data;
! 797: cl->cl_swflags &= /* only allow valid flags */
! 798: (TIOCFLAG_SOFTCAR | TIOCFLAG_CLOCAL | TIOCFLAG_CRTSCTS);
! 799: break;
! 800: default:
! 801: return(ENOTTY);
! 802: }
! 803:
! 804: return 0;
! 805: }
! 806: int
! 807: wlstop(tp, flag)
! 808: struct tty *tp;
! 809: int flag;
! 810: {
! 811: int s;
! 812:
! 813: s = splcl();
! 814: if (tp->t_state & TS_BUSY) {
! 815: if ((tp->t_state & TS_TTSTOP) == 0)
! 816: tp->t_state |= TS_FLUSH;
! 817: }
! 818: splx(s);
! 819: return 0;
! 820: }
! 821:
! 822: static u_char
! 823: clgetc(sc, channel)
! 824: struct wlsoftc *sc;
! 825: int *channel;
! 826: {
! 827: struct clreg *cl_reg;
! 828: u_char reoir, licr, isrl, fifo_cnt, data;
! 829:
! 830: cl_reg = sc->cl_reg;
! 831: /* if no receive interrupt pending wait */
! 832: if ((cl_reg->cl_rir & RIR_REN) == 0) {
! 833: return 0;
! 834: }
! 835: /* XXX do we need to suck the entire FIFO contents? */
! 836: licr = cl_reg->cl_licr;
! 837: *channel = (licr >> 2) & 0x3;
! 838: /* is the interrupt for us (port 0) */
! 839: /* the character is for us yea. */
! 840: isrl = cl_reg->cl_risrl;
! 841: #if 0
! 842: if (isrl & 0x01) {
! 843: status = BREAK;
! 844: }
! 845: if (isrl & 0x02) {
! 846: status = FRAME;
! 847: }
! 848: if (isrl & 0x04) {
! 849: status = PARITY;
! 850: }
! 851: if (isrl & 0x08) {
! 852: status = OVERFLOW;
! 853: }
! 854: /* we do not have special characters ;-) */
! 855: #endif
! 856: fifo_cnt = cl_reg->cl_rfoc;
! 857: if (fifo_cnt > 0) {
! 858: data = cl_reg->cl_rdr;
! 859: cl_reg->cl_teoir = 0x00;
! 860: } else {
! 861: data = 0;
! 862: cl_reg->cl_teoir = 0x08;
! 863: }
! 864: return data;
! 865: }
! 866:
! 867: int
! 868: clccparam(sc, par, channel)
! 869: struct wlsoftc *sc;
! 870: struct termios *par;
! 871: int channel;
! 872: {
! 873: u_int divisor, clk, clen;
! 874: int s, imask, ints;
! 875:
! 876: s = splcl();
! 877: sc->cl_reg->cl_car = channel;
! 878: if (par->c_ospeed == 0) {
! 879: /* disconnect, drop RTS DTR stop receiver */
! 880: sc->cl_reg->cl_msvr_rts = 0x00;
! 881: sc->cl_reg->cl_msvr_dtr = 0x00;
! 882: sc->cl_reg->cl_ccr = 0x05;
! 883: splx(s);
! 884: return (0xff);
! 885: }
! 886:
! 887: sc->cl_reg->cl_msvr_rts = 0x03;
! 888: sc->cl_reg->cl_msvr_dtr = 0x03;
! 889:
! 890: divisor = cl_clkdiv(par->c_ospeed);
! 891: clk = cl_clknum(par->c_ospeed);
! 892: sc->cl_reg->cl_tbpr = divisor;
! 893: sc->cl_reg->cl_tcor = clk << 5;
! 894: divisor = cl_clkdiv(par->c_ispeed);
! 895: clk = cl_clknum(par->c_ispeed);
! 896: sc->cl_reg->cl_rbpr = divisor;
! 897: sc->cl_reg->cl_rcor = clk;
! 898: sc->cl_reg->cl_rtprl = cl_clkrxtimeout(par->c_ispeed);
! 899: sc->cl_reg->cl_rtprh = 0x00;
! 900:
! 901: switch (par->c_cflag & CSIZE) {
! 902: case CS5:
! 903: clen = 4; /* this is the mask for the chip. */
! 904: imask = 0x1F;
! 905: break;
! 906: case CS6:
! 907: clen = 5;
! 908: imask = 0x3F;
! 909: break;
! 910: case CS7:
! 911: clen = 6;
! 912: imask = 0x7F;
! 913: break;
! 914: default:
! 915: clen = 7;
! 916: imask = 0xFF;
! 917: }
! 918: sc->cl_reg->cl_cor3 = par->c_cflag & PARENB ? 4 : 2;
! 919:
! 920: {
! 921: u_char cor1;
! 922: if (par->c_cflag & PARENB) {
! 923: if (par->c_cflag & PARODD) {
! 924: cor1 = 0xE0 | clen ; /* odd */
! 925: } else {
! 926: cor1 = 0x40 | clen ; /* even */
! 927: }
! 928: } else {
! 929: cor1 = 0x10 | clen; /* ignore parity */
! 930: }
! 931: if (sc->cl_reg->cl_cor1 != cor1) {
! 932: sc->cl_reg->cl_cor1 = cor1;
! 933: sc->cl_reg->cl_ccr = 0x20;
! 934: while (sc->cl_reg->cl_ccr != 0)
! 935: ;
! 936: }
! 937: }
! 938:
! 939: if ((par->c_cflag & CREAD) == 0) {
! 940: sc->cl_reg->cl_ccr = 0x08;
! 941: } else {
! 942: sc->cl_reg->cl_ccr = 0x0a;
! 943: }
! 944: while (sc->cl_reg->cl_ccr != 0)
! 945: ;
! 946:
! 947: ints = 0;
! 948: #define SCC_DSR 0x80
! 949: #define SCC_DCD 0x40
! 950: #define SCC_CTS 0x20
! 951: if ((par->c_cflag & CLOCAL) == 0) {
! 952: ints |= SCC_DCD;
! 953: }
! 954: if ((par->c_cflag & CCTS_OFLOW) != 0) {
! 955: ints |= SCC_CTS;
! 956: }
! 957: if ((par->c_cflag & CRTSCTS) != 0) {
! 958: ints |= SCC_CTS;
! 959: }
! 960: #ifdef DONT_LET_HARDWARE
! 961: if ((par->c_cflag & CCTS_IFLOW) != 0) {
! 962: ints |= SCC_DSR;
! 963: }
! 964: #endif
! 965: sc->cl_reg->cl_cor4 = ints | CL_FIFO_CNT;
! 966: sc->cl_reg->cl_cor5 = ints | CL_FIFO_CNT;
! 967:
! 968: return imask;
! 969: }
! 970:
! 971: static int clknum = 0;
! 972:
! 973: u_char
! 974: cl_clkdiv(speed)
! 975: int speed;
! 976: {
! 977: int i = 0;
! 978:
! 979: if (cl_clocks[clknum].speed == speed)
! 980: return cl_clocks[clknum].divisor;
! 981:
! 982: for (i = 0; cl_clocks[i].speed != 0; i++) {
! 983: if (cl_clocks[i].speed == speed) {
! 984: clknum = i;
! 985: return cl_clocks[clknum].divisor;
! 986: }
! 987: }
! 988:
! 989: /* return some sane value if unknown speed */
! 990: clknum = 4;
! 991: return cl_clocks[clknum].divisor;
! 992: }
! 993: u_char
! 994: cl_clknum(speed)
! 995: int speed;
! 996: {
! 997: int found = 0;
! 998: int i = 0;
! 999: if (cl_clocks[clknum].speed == speed) {
! 1000: return cl_clocks[clknum].clock;
! 1001: }
! 1002: for (i = 0; found != 0 && cl_clocks[i].speed != 0; i++) {
! 1003: if (cl_clocks[clknum].speed == speed) {
! 1004: clknum = i;
! 1005: return cl_clocks[clknum].clock;
! 1006: }
! 1007: }
! 1008: /* return some sane value if unknown speed */
! 1009: return cl_clocks[4].clock;
! 1010: }
! 1011: u_char
! 1012: cl_clkrxtimeout(speed)
! 1013: int speed;
! 1014: {
! 1015: int i = 0;
! 1016: if (cl_clocks[clknum].speed == speed) {
! 1017: return cl_clocks[clknum].rx_timeout;
! 1018: }
! 1019: for (i = 0; cl_clocks[i].speed != 0; i++) {
! 1020: if (cl_clocks[i].speed == speed) {
! 1021: clknum = i;
! 1022: return cl_clocks[clknum].rx_timeout;
! 1023: }
! 1024: }
! 1025: /* return some sane value if unknown speed */
! 1026: return cl_clocks[4].rx_timeout;
! 1027: }
! 1028: void
! 1029: cl_unblock(tp)
! 1030: struct tty *tp;
! 1031: {
! 1032: tp->t_state &= ~TS_FLUSH;
! 1033: if (tp->t_outq.c_cc != 0)
! 1034: clstart(tp);
! 1035: }
! 1036: void
! 1037: clstart(tp)
! 1038: struct tty *tp;
! 1039: {
! 1040: dev_t dev;
! 1041: u_char cbuf;
! 1042: struct wlsoftc *sc;
! 1043: int channel, unit, s, cnt;
! 1044:
! 1045: dev = tp->t_dev;
! 1046: channel = CL_CHANNEL(dev);
! 1047: unit = CL_UNIT(dev);
! 1048: if (unit >= wl_cd.cd_ndevs ||
! 1049: (sc = (struct wlsoftc *) wl_cd.cd_devs[unit]) == NULL) {
! 1050: return;
! 1051: }
! 1052:
! 1053: if ((tp->t_state & TS_ISOPEN) == 0)
! 1054: return;
! 1055:
! 1056: s = splcl();
! 1057: if ((tp->t_state & (TS_TIMEOUT | TS_BUSY | TS_TTSTOP | TS_FLUSH)) == 0) {
! 1058: tp->t_state |= TS_BUSY;
! 1059: sc->cl_reg->cl_car = channel;
! 1060: sc->cl_reg->cl_ier = sc->cl_reg->cl_ier | IER_TXMPTY | IER_TXD;
! 1061: #if 0
! 1062: zscnputc(0, 'S');
! 1063: #endif
! 1064: }
! 1065: splx(s);
! 1066: }
! 1067:
! 1068: int
! 1069: cl_intr(sc, vec)
! 1070: struct wlsoftc *sc;
! 1071: int vec;
! 1072: {
! 1073: u_char livr = sc->cl_reg->cl_livr;
! 1074: u_char stk = sc->cl_reg->cl_stk;
! 1075: int i = 0;
! 1076:
! 1077: stk = ((stk & 0x80) >> 6) | (stk & 0x01);
! 1078: #if 1
! 1079: zscnputc(0, '[');
! 1080: zscnputc(0, '0' + vec - 0x70);
! 1081: zscnputc(0, '0' + livr - 0x70);
! 1082: zscnputc(0, '0' + stk);
! 1083: zscnputc(0, ']');
! 1084: #endif
! 1085:
! 1086: switch (stk & 3) {
! 1087: case 0:
! 1088: #if 0
! 1089: i += cl_rxintr(sc);
! 1090: i += cl_mintr(sc);
! 1091: i += cl_txintr(sc);
! 1092: #else
! 1093: i += cl_rxintr(sc);
! 1094: #endif
! 1095: break;
! 1096: case 1:
! 1097: i += cl_mintr(sc);
! 1098: break;
! 1099: case 2:
! 1100: i += cl_txintr(sc);
! 1101: break;
! 1102: case 3:
! 1103: i += cl_rxintr(sc);
! 1104: break;
! 1105: }
! 1106: return (i);
! 1107: }
! 1108:
! 1109: int
! 1110: cl_mintr(sc)
! 1111: struct wlsoftc *sc;
! 1112: {
! 1113: u_char mir, misr, msvr;
! 1114: int channel;
! 1115: struct tty *tp;
! 1116:
! 1117: mir = sc->cl_reg->cl_mir;
! 1118: if((mir & MIR_MACT) == 0)
! 1119: return 0;
! 1120: zscnputc(0, 'M');
! 1121:
! 1122: misr = sc->cl_reg->cl_misr;
! 1123: msvr = sc->cl_reg->cl_msvr_rts;
! 1124: channel = mir & MIR_MCM_M;
! 1125:
! 1126: printf("stk 0x%x mir 0x%x chan 0x%x\n",
! 1127: sc->cl_reg->cl_stk, mir, channel);
! 1128:
! 1129: if (misr & MISR_TIMER1) {
! 1130: /* timers are not currently used?? */
! 1131: log(LOG_WARNING, "cl_mintr: channel %x timer 1 unexpected\n",channel);
! 1132: }
! 1133: if (misr & MISR_TIMER2) {
! 1134: /* timers are not currently used?? */
! 1135: log(LOG_WARNING, "cl_mintr: channel %x timer 2 unexpected\n",channel);
! 1136: }
! 1137: if (misr & MISR_CTSCHG) {
! 1138: log(LOG_WARNING, "cl_mintr: channel %x cts %x\n",channel,
! 1139: ((msvr & 0x20) != 0x0));
! 1140: }
! 1141: if (misr & MISR_CDCHG) {
! 1142: struct tty *tp = sc->sc_cl[channel].tty;
! 1143: log(LOG_WARNING, "cl_mintr: channel %x cd %x\n",channel,
! 1144: ((msvr & 0x40) != 0x0));
! 1145: ttymodem(tp, ((msvr & 0x40) != 0x0) );
! 1146: }
! 1147: if (misr & MISR_DSRCHG) {
! 1148: log(LOG_WARNING, "cl_mintr: channel %x dsr %x\n",channel,
! 1149: ((msvr & 0x80) != 0x0));
! 1150: }
! 1151: sc->cl_reg->cl_meoir = 0x00;
! 1152: return 1;
! 1153: }
! 1154:
! 1155: int
! 1156: cl_txintr(sc)
! 1157: struct wlsoftc *sc;
! 1158: {
! 1159: static int empty = 0;
! 1160: u_char tir, cmr, teoir, tisr, tftc;
! 1161: int chan;
! 1162: struct tty *tp;
! 1163: int cnt;
! 1164: u_char buffer[CL_FIFO_MAX +1];
! 1165: u_char *tptr;
! 1166: u_char dmabsts;
! 1167: int nbuf, busy, resid;
! 1168: void *pbuffer;
! 1169:
! 1170: tir = sc->cl_reg->cl_tir;
! 1171: if((tir & (TIR_TEN|TIR_TACT)) == 0)
! 1172: return 0;
! 1173: #if 0
! 1174: zscnputc(0, 'T');
! 1175: #endif
! 1176:
! 1177: cmr = sc->cl_reg->cl_cmr;
! 1178: chan = tir & TIR_TCN_M;
! 1179: tisr = sc->cl_reg->cl_tisr;
! 1180: tftc = sc->cl_reg->cl_tftc;
! 1181:
! 1182: printf("stk 0x%x tir 0x%x chan 0x%x cmr 0x%x tisr 0x%x tftc 0x%x\n",
! 1183: sc->cl_reg->cl_stk, tir, chan, cmr, tisr, tftc);
! 1184:
! 1185: sc->sc_cl[chan].txcnt++;
! 1186: tp = sc->sc_cl[chan].tty;
! 1187:
! 1188: if (tp == NULL || (tp->t_state & TS_ISOPEN) == 0) {
! 1189: sc->cl_reg->cl_ier = sc->cl_reg->cl_ier & ~(IER_TXMPTY|IER_TXD);
! 1190: sc->cl_reg->cl_teoir = TEOIR_NOTRANSF;
! 1191: return 1;
! 1192: }
! 1193:
! 1194: switch (cmr & CL_TXMASK) {
! 1195: case CL_TXINTR:
! 1196: cnt = min((int)tftc, tp->t_outq.c_cc);
! 1197: if (cnt != 0) {
! 1198: /*printf("s%d ", cnt);*/
! 1199: cnt = q_to_b(&tp->t_outq, buffer, cnt);
! 1200: /*printf("%d:", cnt);*/
! 1201: empty = 0;
! 1202: for (tptr = buffer; tptr < &buffer[cnt]; tptr++) {
! 1203: /*printf("%c", *tptr);*/
! 1204: sc->cl_reg->cl_tdr = *tptr;
! 1205: }
! 1206: /*printf("\n", cnt);*/
! 1207: teoir = 0;
! 1208: } else {
! 1209: if (empty > 5 && ((empty % 20000 )== 0))
! 1210: log(LOG_WARNING, "cl_txintr empty intr %d chan %d\n",
! 1211: empty, chan);
! 1212: empty++;
! 1213: teoir = TEOIR_NOTRANSF;
! 1214: if (tp->t_state & TS_BUSY) {
! 1215: tp->t_state &= ~(TS_BUSY | TS_FLUSH);
! 1216: if (tp->t_state & TS_ASLEEP) {
! 1217: tp->t_state &= ~TS_ASLEEP;
! 1218: wakeup((caddr_t) &tp->t_outq);
! 1219: }
! 1220: selwakeup(&tp->t_wsel);
! 1221: }
! 1222: sc->cl_reg->cl_ier = sc->cl_reg->cl_ier & ~(IER_TXMPTY|IER_TXD);
! 1223: }
! 1224: break;
! 1225: default:
! 1226: log(LOG_WARNING, "cl_txintr unknown mode %x\n", cmr);
! 1227: /* we probably will go to hell quickly now */
! 1228: teoir = TEOIR_NOTRANSF;
! 1229: break;
! 1230: }
! 1231: sc->cl_reg->cl_teoir = teoir;
! 1232: return (1);
! 1233: }
! 1234:
! 1235: int
! 1236: cl_rxintr(sc)
! 1237: struct wlsoftc *sc;
! 1238: {
! 1239: u_char rir, chan, cmr, risrl;
! 1240: u_char buffer[CL_FIFO_MAX +1];
! 1241: u_char reoir = REOIR_NOTRANSF, fifocnt, c;
! 1242: struct tty *tp;
! 1243: int i;
! 1244:
! 1245: rir = sc->cl_reg->cl_rir;
! 1246: if((rir & RIR_RACT) == 0)
! 1247: return 0;
! 1248: #if 0
! 1249: zscnputc(0, 'R');
! 1250: #endif
! 1251:
! 1252: cmr = sc->cl_reg->cl_cmr;
! 1253: risrl = sc->cl_reg->cl_risrl;
! 1254: chan = rir & RIR_RCN_M;
! 1255:
! 1256: /*printf("stk 0x%x rir 0x%x chan 0x%x cmr 0x%x risrl 0x%x\n",
! 1257: sc->cl_reg->cl_stk, rir, chan, cmr, risrl);*/
! 1258:
! 1259: sc->sc_cl[chan].rxcnt++;
! 1260:
! 1261: if (risrl & RISRL_TIMEOUT) {
! 1262: reoir = REOIR_NOTRANSF;
! 1263: } else if (risrl & RISRL_OE) {
! 1264: cl_overflow(sc, chan, &sc->sc_fotime, "fifo");
! 1265: reoir = REOIR_NOTRANSF;
! 1266: } else if (risrl & RISRL_PE) {
! 1267: cl_parity(sc, chan);
! 1268: reoir = REOIR_NOTRANSF;
! 1269: } else if (risrl & RISRL_FE) {
! 1270: cl_frame(sc, chan);
! 1271: reoir = REOIR_NOTRANSF;
! 1272: } else if (risrl & RISRL_BREAK) {
! 1273: cl_break(sc, chan);
! 1274: reoir = REOIR_NOTRANSF;
! 1275: } else {
! 1276: switch (cmr & CL_RXMASK) {
! 1277: case CL_RXINTR:
! 1278: fifocnt = sc->cl_reg->cl_rfoc;
! 1279: tp = sc->sc_cl[chan].tty;
! 1280: for (i = 0; i < fifocnt; i++)
! 1281: buffer[i] = sc->cl_reg->cl_rdr;
! 1282: if (NULL == tp) {
! 1283: /*
! 1284: * if the channel is not configured,
! 1285: * dont send characters upstream.
! 1286: * also fix problem with NULL dereference
! 1287: */
! 1288: reoir = 0;
! 1289: break;
! 1290: }
! 1291:
! 1292: sc->cl_reg->cl_reoir = reoir;
! 1293: for (i = 0; i < fifocnt; i++) {
! 1294: u_char c = buffer[i];
! 1295:
! 1296: /* does any restricitions exist on spl for this call */
! 1297: (*linesw[tp->t_line].l_rint)(c, tp);
! 1298: reoir = 0;
! 1299: }
! 1300: break;
! 1301: default:
! 1302: log(LOG_WARNING, "cl_rxintr unknown mode %x\n", cmr);
! 1303: /* we probably will go to hell quickly now */
! 1304: reoir = REOIR_NOTRANSF;
! 1305: break;
! 1306: }
! 1307: }
! 1308: sc->cl_reg->cl_reoir = reoir;
! 1309: return (1);
! 1310: }
! 1311:
! 1312: void
! 1313: cl_overflow (sc, channel, ptime, msg)
! 1314: struct wlsoftc *sc;
! 1315: int channel;
! 1316: long *ptime;
! 1317: u_char *msg;
! 1318: {
! 1319: /*
! 1320: if (*ptime != time.tv_sec) {
! 1321: */
! 1322: {
! 1323: /*
! 1324: *ptime = time.tv_sec;
! 1325: */
! 1326: log(LOG_WARNING, "%s%d[%d]: %s overrun\n", wl_cd.cd_name,
! 1327: 0 /* fix */, channel, msg);
! 1328: }
! 1329: }
! 1330:
! 1331: void
! 1332: cl_parity (sc, channel)
! 1333: struct wlsoftc *sc;
! 1334: int channel;
! 1335: {
! 1336: log(LOG_WARNING, "%s%d[%d]: parity error\n", wl_cd.cd_name, 0, channel);
! 1337: }
! 1338:
! 1339: void
! 1340: cl_frame (sc, channel)
! 1341: struct wlsoftc *sc;
! 1342: int channel;
! 1343: {
! 1344: log(LOG_WARNING, "%s%d[%d]: frame error\n", wl_cd.cd_name, 0, channel);
! 1345: }
! 1346:
! 1347: void
! 1348: cl_break (sc, channel)
! 1349: struct wlsoftc *sc;
! 1350: int channel;
! 1351: {
! 1352: log(LOG_WARNING, "%s%d[%d]: break detected\n", wl_cd.cd_name, 0, channel);
! 1353: }
! 1354:
! 1355: void
! 1356: cl_dumpport0()
! 1357: {
! 1358: cl_dumpport(0);
! 1359: }
! 1360:
! 1361: void
! 1362: cl_dumpport1()
! 1363: {
! 1364: cl_dumpport(1);
! 1365: }
! 1366:
! 1367: void
! 1368: cl_dumpport2()
! 1369: {
! 1370: cl_dumpport(2);
! 1371: }
! 1372:
! 1373: void
! 1374: cl_dumpport3()
! 1375: {
! 1376: cl_dumpport(3);
! 1377: }
! 1378:
! 1379: void
! 1380: cl_dumpport(channel)
! 1381: int channel;
! 1382: {
! 1383: u_char livr, cmr, cor1, cor2, cor3, cor4, cor5, cor6, cor7,
! 1384: schr1, schr2, schr3, schr4, scrl, scrh, lnxt,
! 1385: rbpr, rcor, tbpr, tcor, rpilr, rir, tpr, ier, ccr,
! 1386: dmabsts, arbsts, brbsts, atbsts, btbsts,
! 1387: csr, rts, dtr, rtprl, rtprh;
! 1388: volatile void * parbadru, *parbadrl, *parbsts, *parbcnt;
! 1389: u_short rcbadru, rcbadrl, arbadru, arbadrl, arbcnt,
! 1390: brbadru, brbadrl, brbcnt;
! 1391: u_short tcbadru, tcbadrl, atbadru, atbadrl, atbcnt,
! 1392: btbadru, btbadrl, btbcnt;
! 1393: struct wlsoftc *sc;
! 1394:
! 1395: struct clreg *cl_reg;
! 1396: int s;
! 1397:
! 1398: sc = (struct wlsoftc *) wl_cd.cd_devs[0];
! 1399: cl_reg = sc->cl_reg;
! 1400:
! 1401: s = splcl();
! 1402: cl_reg->cl_car = (u_char) channel;
! 1403: livr = cl_reg->cl_livr;
! 1404: cmr = cl_reg->cl_cmr;
! 1405: cor1 = cl_reg->cl_cor1;
! 1406: cor2 = cl_reg->cl_cor2;
! 1407: cor3 = cl_reg->cl_cor3;
! 1408: cor4 = cl_reg->cl_cor4;
! 1409: cor5 = cl_reg->cl_cor5;
! 1410: cor6 = cl_reg->cl_cor6;
! 1411: cor7 = cl_reg->cl_cor7;
! 1412: schr1 = cl_reg->cl_schr1;
! 1413: schr2 = cl_reg->cl_schr2;
! 1414: schr3 = cl_reg->cl_schr3;
! 1415: schr4 = cl_reg->cl_schr4;
! 1416: scrl = cl_reg->cl_scrl;
! 1417: scrh = cl_reg->cl_scrh;
! 1418: lnxt = cl_reg->cl_lnxt;
! 1419: rbpr = cl_reg->cl_rbpr;
! 1420: rcor = cl_reg->cl_rcor;
! 1421: tbpr = cl_reg->cl_tbpr;
! 1422: rpilr = cl_reg->cl_rpilr;
! 1423: ier = cl_reg->cl_ier;
! 1424: ccr = cl_reg->cl_ccr;
! 1425: tcor = cl_reg->cl_tcor;
! 1426: csr = cl_reg->cl_csr;
! 1427: tpr = cl_reg->cl_tpr;
! 1428: rts = cl_reg->cl_msvr_rts;
! 1429: dtr = cl_reg->cl_msvr_dtr;
! 1430: rtprl = cl_reg->cl_rtprl;
! 1431: rtprh = cl_reg->cl_rtprh;
! 1432: dmabsts = cl_reg->cl_dmabsts;
! 1433: tcbadru = cl_reg->cl_tcbadru;
! 1434: tcbadrl = cl_reg->cl_tcbadrl;
! 1435: rcbadru = cl_reg->cl_rcbadru;
! 1436: rcbadrl = cl_reg->cl_rcbadrl;
! 1437:
! 1438: parbadru = &(cl_reg->cl_arbadru);
! 1439: parbadrl = &(cl_reg->cl_arbadrl);
! 1440: parbcnt = &(cl_reg->cl_arbcnt);
! 1441: parbsts = &(cl_reg->cl_arbsts);
! 1442:
! 1443: arbadru = cl_reg->cl_arbadru;
! 1444: arbadrl = cl_reg->cl_arbadrl;
! 1445: arbcnt = cl_reg->cl_arbcnt;
! 1446: arbsts = cl_reg->cl_arbsts;
! 1447:
! 1448: brbadru = cl_reg->cl_brbadru;
! 1449: brbadrl = cl_reg->cl_brbadrl;
! 1450: brbcnt = cl_reg->cl_brbcnt;
! 1451: brbsts = cl_reg->cl_brbsts;
! 1452:
! 1453: atbadru = cl_reg->cl_atbadru;
! 1454: atbadrl = cl_reg->cl_atbadrl;
! 1455: atbcnt = cl_reg->cl_atbcnt;
! 1456: atbsts = cl_reg->cl_atbsts;
! 1457:
! 1458: btbadru = cl_reg->cl_btbadru;
! 1459: btbadrl = cl_reg->cl_btbadrl;
! 1460: btbcnt = cl_reg->cl_btbcnt;
! 1461: btbsts = cl_reg->cl_btbsts;
! 1462:
! 1463: splx(s);
! 1464:
! 1465: printf("{ port %x livr %x cmr %x\n",
! 1466: channel,livr, cmr);
! 1467: printf("cor1 %x cor2 %x cor3 %x cor4 %x cor5 %x cor6 %x cor7 %x\n",
! 1468: cor1, cor2, cor3, cor4, cor5, cor6, cor7);
! 1469: printf("schr1 %x schr2 %x schr3 %x schr4 %x\n",
! 1470: schr1, schr2, schr3, schr4);
! 1471: printf("scrl %x scrh %x lnxt %x\n",
! 1472: scrl, scrh, lnxt);
! 1473: printf("rbpr %x rcor %x tbpr %x tcor %x\n",
! 1474: rbpr, rcor, tbpr, tcor);
! 1475: printf("rpilr %x rir %x ier %x ccr %x\n",
! 1476: rpilr, rir, ier, ccr);
! 1477: printf("tpr %x csr %x rts %x dtr %x\n",
! 1478: tpr, csr, rts, dtr);
! 1479: printf("rtprl %x rtprh %x\n",
! 1480: rtprl, rtprh);
! 1481: printf("rxcnt %x txcnt %x\n",
! 1482: sc->sc_cl[channel].rxcnt, sc->sc_cl[channel].txcnt);
! 1483: printf("dmabsts %x, tcbadru %x, tcbadrl %x, rcbadru %x, rcbadrl %x,\n",
! 1484: dmabsts, tcbadru, tcbadrl, rcbadru, rcbadrl );
! 1485: printf("parbadru %x, parbadrl %x, parbcnt %x, parbsts %x\n",
! 1486: parbadru, parbadrl, parbcnt, parbsts);
! 1487: printf("arbadru %x, arbadrl %x, arbcnt %x, arbsts %x\n",
! 1488: arbadru, arbadrl, arbcnt, arbsts);
! 1489: printf("brbadru %x, brbadrl %x, brbcnt %x, brbsts %x\n",
! 1490: brbadru, brbadrl, brbcnt, brbsts);
! 1491: printf("atbadru %x, atbadrl %x, atbcnt %x, atbsts %x\n",
! 1492: atbadru, atbadrl, atbcnt, atbsts);
! 1493: printf("btbadru %x, btbadrl %x, btbcnt %x, btbsts %x\n",
! 1494: btbadru, btbadrl, btbcnt, btbsts);
! 1495: printf("}\n");
! 1496: }
! 1497:
! 1498: static void
! 1499: clputc(sc, unit, c)
! 1500: struct wlsoftc *sc;
! 1501: int unit;
! 1502: u_char c;
! 1503: {
! 1504: int s;
! 1505: u_char schar;
! 1506: u_char oldchannel;
! 1507: struct clreg *cl_reg;
! 1508: cl_reg = sc->cl_reg;
! 1509:
! 1510: s = splhigh();
! 1511: oldchannel = cl_reg->cl_car;
! 1512: cl_reg->cl_car = unit;
! 1513: if (cl_reg->cl_tftc > 0) {
! 1514: cl_reg->cl_tdr = c;
! 1515: }
! 1516: cl_reg->cl_car = oldchannel;
! 1517: splx(s);
! 1518: }
CVSweb