Annotation of sys/arch/mvme68k/dev/cl.c, Revision 1.1
1.1 ! nbrk 1: /* $OpenBSD: cl.c,v 1.43 2006/06/11 20:46:50 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: /* DMA mode still does not work!!! */
! 28:
! 29: #include <sys/param.h>
! 30: #include <sys/ioctl.h>
! 31: #include <sys/proc.h>
! 32: #include <sys/tty.h>
! 33: #include <sys/uio.h>
! 34: #include <sys/systm.h>
! 35: #include <sys/time.h>
! 36: #include <sys/device.h>
! 37: #include <sys/syslog.h>
! 38:
! 39: #include <machine/autoconf.h>
! 40: #include <machine/conf.h>
! 41: #include <machine/cpu.h>
! 42:
! 43: #include <dev/cons.h>
! 44:
! 45: #include <mvme68k/dev/clreg.h>
! 46:
! 47: #include "cl.h"
! 48:
! 49: #ifdef DDB
! 50: #include <ddb/db_var.h>
! 51: #endif
! 52:
! 53: #include "pcctwo.h"
! 54:
! 55: #if NPCCTWO > 0
! 56: #include <mvme68k/dev/pcctworeg.h>
! 57: #endif
! 58:
! 59: #define splcl() spltty()
! 60: #define USE_BUFFER
! 61:
! 62: /* min timeout 0xa, what is a good value */
! 63: #define CL_TIMEOUT 0x10
! 64: #define CL_FIFO_MAX 0x10
! 65: #define CL_FIFO_CNT 0xc
! 66: #define CL_RX_TIMEOUT 0x10
! 67:
! 68: #define CL_RXDMAINT 0x82
! 69: #define CL_TXDMAINT 0x42
! 70: #define CL_TXMASK 0x47
! 71: #define CL_RXMASK 0x87
! 72: #define CL_TXINTR 0x02
! 73: #define CL_RXINTR 0x02
! 74:
! 75: struct cl_cons {
! 76: paddr_t cl_paddr;
! 77: struct clreg *cl_vaddr;
! 78: volatile struct pcctworeg *pcctwoaddr;
! 79: u_char channel;
! 80: } cl_cons;
! 81:
! 82: struct cl_info {
! 83: struct tty *tty;
! 84: u_char cl_swflags;
! 85: u_char cl_softchar;
! 86: u_char cl_consio;
! 87: u_char cl_speed;
! 88: u_char cl_parstop; /* parity, stop bits. */
! 89: u_char cl_rxmode;
! 90: u_char cl_txmode;
! 91: u_char cl_clen;
! 92: u_char cl_parity;
! 93: u_char transmitting;
! 94: u_long txcnt;
! 95: u_long rxcnt;
! 96:
! 97: void *rx[2];
! 98: void *rxp[2];
! 99: void *tx[2];
! 100: void *txp[2];
! 101:
! 102: volatile u_char *pconsum;
! 103: volatile u_char *psupply;
! 104: volatile u_char *buffer;
! 105: volatile int nchar;
! 106: };
! 107: #define CLCD_PORTS_PER_CHIP 4
! 108: #define CL_BUFSIZE 256
! 109:
! 110: #ifndef DO_MALLOC
! 111: /* four (4) buffers per port */
! 112: char cl_dmabuf [CLCD_PORTS_PER_CHIP * CL_BUFSIZE * 4];
! 113: #endif
! 114:
! 115: struct clsoftc {
! 116: struct device sc_dev;
! 117: time_t sc_rotime; /* time of last ring overrun */
! 118: time_t sc_fotime; /* time of last fifo overrun */
! 119: u_char *pbase;
! 120: struct clreg *cl_reg;
! 121: struct cl_info sc_cl[CLCD_PORTS_PER_CHIP];
! 122: struct intrhand sc_ih_e;
! 123: struct intrhand sc_ih_m;
! 124: struct intrhand sc_ih_t;
! 125: struct intrhand sc_ih_r;
! 126: char sc_errintrname[16 + 4];
! 127: char sc_mxintrname[16 + 3];
! 128: char sc_rxintrname[16 + 3];
! 129: char sc_txintrname[16 + 3];
! 130: int sc_flags;
! 131: u_int8_t ssir;
! 132: };
! 133:
! 134: const struct {
! 135: u_int speed;
! 136: u_char divisor;
! 137: u_char clock;
! 138: u_char rx_timeout;
! 139: } cl_clocks[] = {
! 140: { 64000, 0x26, 0, 0x01},
! 141: { 56000, 0x2c, 0, 0x01},
! 142: { 38400, 0x40, 0, 0x01},
! 143: { 19200, 0x81, 0, 0x02},
! 144: { 9600, 0x40, 1, 0x04},
! 145: { 7200, 0x56, 1, 0x04},
! 146: { 4800, 0x81, 1, 0x08},
! 147: { 3600, 0xad, 1, 0x08},
! 148: { 2400, 0x40, 2, 0x10},
! 149: { 1200, 0x81, 2, 0x20},
! 150: { 600, 0x40, 3, 0x40},
! 151: { 300, 0x81, 3, 0x80},
! 152: { 150, 0x40, 3, 0x80},
! 153: { 110, 0x58, 4, 0xff},
! 154: { 50, 0xC2, 4, 0xff},
! 155: { 0, 0x00, 0, 0},
! 156: };
! 157:
! 158: /* prototypes */
! 159: cons_decl(cl);
! 160: u_char cl_clkdiv(int speed);
! 161: u_char cl_clknum(int speed);
! 162: u_char cl_clkrxtimeout(int speed);
! 163: void clstart(struct tty *tp);
! 164: void cl_unblock(struct tty *tp);
! 165: int clccparam(struct clsoftc *sc, struct termios *par, int channel);
! 166:
! 167: int clparam(struct tty *tp, struct termios *t);
! 168: int cl_mintr(void *);
! 169: int cl_txintr(void *);
! 170: int cl_rxintr(void *);
! 171: void cl_overflow(struct clsoftc *sc, int channel, time_t *ptime, u_char *msg);
! 172: void cl_parity(struct clsoftc *sc, int channel);
! 173: void cl_frame(struct clsoftc *sc, int channel);
! 174: void cl_break( struct clsoftc *sc, int channel);
! 175: int clmctl(dev_t dev, int bits, int how);
! 176: void cl_dumpport(int channel);
! 177:
! 178: int clprobe(struct device *parent, void *self, void *aux);
! 179: void clattach(struct device *parent, struct device *self, void *aux);
! 180:
! 181: void cl_initchannel(struct clsoftc *sc, int channel);
! 182: void clputc(struct clsoftc *sc, int unit, u_char c);
! 183: u_char clgetc(struct clsoftc *sc, int *channel);
! 184: void cloutput(struct tty *tp);
! 185: void cl_softint(void *);
! 186: void cl_appendbufn(struct clsoftc *sc, u_char channel, u_char *buf, u_short cnt);
! 187:
! 188: struct tty *cltty(dev_t);
! 189: int cl_instat(struct clsoftc *);
! 190: void clcnpollc(dev_t, int);
! 191: void cl_break(struct clsoftc *, int);
! 192: void cl_appendbuf(struct clsoftc *, u_char, u_char);
! 193:
! 194: struct cfattach cl_ca = {
! 195: sizeof(struct clsoftc), clprobe, clattach
! 196: };
! 197:
! 198: struct cfdriver cl_cd = {
! 199: NULL, "cl", DV_TTY
! 200: };
! 201:
! 202: #define CLCDBUF 80
! 203:
! 204: #define CL_UNIT(x) (minor(x) >> 2)
! 205: #define CL_CHANNEL(x) (minor(x) & 3)
! 206: #define CL_TTY(x) (minor(x))
! 207:
! 208: struct tty *
! 209: cltty(dev)
! 210: dev_t dev;
! 211: {
! 212: int unit, channel;
! 213: struct clsoftc *sc;
! 214: unit = CL_UNIT(dev);
! 215: if (unit >= cl_cd.cd_ndevs ||
! 216: (sc = (struct clsoftc *) cl_cd.cd_devs[unit]) == NULL) {
! 217: return (NULL);
! 218: }
! 219: channel = CL_CHANNEL(dev);
! 220: return sc->sc_cl[channel].tty;
! 221: }
! 222:
! 223: int
! 224: clprobe(parent, self, aux)
! 225: struct device *parent;
! 226: void *self;
! 227: void *aux;
! 228: {
! 229: /* probing onboard 166/167/177/187 CL-cd2400
! 230: * should be previously configured,
! 231: * we can check the value before resetting the chip
! 232: */
! 233: struct clreg *cl_reg;
! 234: struct confargs *ca = aux;
! 235: int ret;
! 236: if (cputyp != CPU_167 && cputyp != CPU_166 && cputyp != CPU_177)
! 237: {
! 238: return 0;
! 239: }
! 240: cl_reg = (struct clreg *)ca->ca_vaddr;
! 241:
! 242: #if 0
! 243: ret = !badvaddr(&cl_reg->cl_gfrcr,1);
! 244: #else
! 245: ret = 1;
! 246: #endif
! 247: return ret;
! 248: }
! 249:
! 250: void
! 251: clattach(parent, self, aux)
! 252: struct device *parent;
! 253: struct device *self;
! 254: void *aux;
! 255: {
! 256: struct clsoftc *sc = (struct clsoftc *)self;
! 257: struct confargs *ca = aux;
! 258: int i;
! 259:
! 260: sc->cl_reg = (struct clreg *)ca->ca_vaddr;
! 261:
! 262: if (ca->ca_paddr == cl_cons.cl_paddr) {
! 263: /* if this device is configured as console,
! 264: * line cl_cons.channel is the console */
! 265: sc->sc_cl[0].cl_consio = 1;
! 266: printf(": console");
! 267: } else {
! 268: /* reset chip only if we are not console device */
! 269: /* wait for GFRCR */
! 270: }
! 271: /* allow chip to settle before continuing */
! 272: delay(800);
! 273:
! 274: /* set up global registers */
! 275: sc->cl_reg->cl_tpr = CL_TIMEOUT;
! 276: sc->cl_reg->cl_rpilr = 0x03;
! 277: sc->cl_reg->cl_tpilr = 0x02;
! 278: sc->cl_reg->cl_mpilr = 0x01;
! 279:
! 280: #ifdef DO_MALLOC
! 281: sc->sc_cl[0].rx[0] = (void *)(dvma_malloc(16 * CL_BUFSIZE));
! 282: #else
! 283: sc->sc_cl[0].rx[0] = (void *) (&cl_dmabuf);
! 284: #endif
! 285: sc->sc_cl[0].rx[1] = (void *)(((int)sc->sc_cl[0].rx[0]) + CL_BUFSIZE);
! 286: sc->sc_cl[1].rx[0] = (void *)(((int)sc->sc_cl[0].rx[1]) + CL_BUFSIZE);
! 287: sc->sc_cl[1].rx[1] = (void *)(((int)sc->sc_cl[1].rx[0]) + CL_BUFSIZE);
! 288:
! 289: sc->sc_cl[2].rx[0] = (void *)(((int)sc->sc_cl[1].rx[1]) + CL_BUFSIZE);
! 290: sc->sc_cl[2].rx[1] = (void *)(((int)sc->sc_cl[2].rx[0]) + CL_BUFSIZE);
! 291: sc->sc_cl[3].rx[0] = (void *)(((int)sc->sc_cl[2].rx[1]) + CL_BUFSIZE);
! 292: sc->sc_cl[3].rx[1] = (void *)(((int)sc->sc_cl[3].rx[0]) + CL_BUFSIZE);
! 293:
! 294: sc->sc_cl[0].tx[0] = (void *)(((int)sc->sc_cl[3].rx[1]) + CL_BUFSIZE);
! 295: sc->sc_cl[0].tx[1] = (void *)(((int)sc->sc_cl[0].tx[0]) + CL_BUFSIZE);
! 296: sc->sc_cl[1].tx[0] = (void *)(((int)sc->sc_cl[0].tx[1]) + CL_BUFSIZE);
! 297: sc->sc_cl[1].tx[1] = (void *)(((int)sc->sc_cl[1].tx[0]) + CL_BUFSIZE);
! 298:
! 299: sc->sc_cl[2].tx[0] = (void *)(((int)sc->sc_cl[1].tx[1]) + CL_BUFSIZE);
! 300: sc->sc_cl[2].tx[1] = (void *)(((int)sc->sc_cl[2].tx[0]) + CL_BUFSIZE);
! 301: sc->sc_cl[3].tx[0] = (void *)(((int)sc->sc_cl[2].tx[1]) + CL_BUFSIZE);
! 302: sc->sc_cl[3].tx[1] = (void *)(((int)sc->sc_cl[3].tx[0]) + CL_BUFSIZE);
! 303: #ifdef USE_BUFFER
! 304: /* receive buffer and dma buffer are "shared" */
! 305: for (i = 0; i < CLCD_PORTS_PER_CHIP; i++) {
! 306: sc->sc_cl[i].buffer = sc->sc_cl[i].rx[0];
! 307: sc->sc_cl[i].pconsum = sc->sc_cl[i].buffer;
! 308: sc->sc_cl[i].psupply = sc->sc_cl[i].buffer;
! 309: sc->sc_cl[i].nchar = 0;
! 310: }
! 311: sc->ssir = allocate_sir(cl_softint, (void *)sc);
! 312: #endif
! 313: for (i = 0; i < CLCD_PORTS_PER_CHIP; i++) {
! 314: #if 0
! 315: int j;
! 316:
! 317: for (j = 0; j < 2 ; j++) {
! 318: sc->sc_cl[i].rxp[j] = (void *)kvtop(sc->sc_cl[i].rx[j]);
! 319: printf("cl[%d].rxbuf[%d] %x p %x\n",
! 320: i, j, sc->sc_cl[i].rx[j], sc->sc_cl[i].rxp[j]);
! 321: sc->sc_cl[i].txp[j] = (void *)kvtop(sc->sc_cl[i].tx[j]);
! 322: printf("cl[%d].txbuf[%d] %x p %x\n",
! 323: i, j, sc->sc_cl[i].tx[j], sc->sc_cl[i].txp[j]);
! 324: }
! 325: #endif
! 326:
! 327: #if 0
! 328: sc->sc_cl[i].cl_rxmode =
! 329: !(!((flags >> (i * CL_FLAG_BIT_PCH)) & 0x01));
! 330: sc->sc_cl[i].cl_txmode =
! 331: !(!((flags >> (i * CL_FLAG_BIT_PCH)) & 0x02));
! 332: sc->sc_cl[i].cl_softchar =
! 333: !(!((flags >> (i * CL_FLAG_BIT_PCH)) & 0x04));
! 334: #endif
! 335: cl_initchannel(sc, i);
! 336: }
! 337:
! 338: /* enable interrupts */
! 339: sc->sc_ih_e.ih_fn = cl_rxintr;
! 340: sc->sc_ih_e.ih_arg = sc;
! 341: sc->sc_ih_e.ih_ipl = ca->ca_ipl;
! 342: sc->sc_ih_e.ih_wantframe = 0;
! 343:
! 344: sc->sc_ih_m.ih_fn = cl_mintr;
! 345: sc->sc_ih_m.ih_arg = sc;
! 346: sc->sc_ih_m.ih_ipl = ca->ca_ipl;
! 347: sc->sc_ih_m.ih_wantframe = 0;
! 348:
! 349: sc->sc_ih_t.ih_fn = cl_txintr;
! 350: sc->sc_ih_t.ih_arg = sc;
! 351: sc->sc_ih_t.ih_ipl = ca->ca_ipl;
! 352: sc->sc_ih_t.ih_wantframe = 0;
! 353:
! 354: sc->sc_ih_r.ih_fn = cl_rxintr;
! 355: sc->sc_ih_r.ih_arg = sc;
! 356: sc->sc_ih_r.ih_ipl = ca->ca_ipl;
! 357: sc->sc_ih_r.ih_wantframe = 0;
! 358:
! 359: snprintf(sc->sc_errintrname, sizeof sc->sc_errintrname,
! 360: "%s_err", self->dv_xname);
! 361: snprintf(sc->sc_mxintrname, sizeof sc->sc_mxintrname,
! 362: "%s_mx", self->dv_xname);
! 363: snprintf(sc->sc_rxintrname, sizeof sc->sc_rxintrname,
! 364: "%s_rx", self->dv_xname);
! 365: snprintf(sc->sc_txintrname, sizeof sc->sc_txintrname,
! 366: "%s_tx", self->dv_xname);
! 367:
! 368: pcctwointr_establish(PCC2V_SCC_RXE,&sc->sc_ih_e, sc->sc_errintrname);
! 369: pcctwointr_establish(PCC2V_SCC_M,&sc->sc_ih_m, sc->sc_mxintrname);
! 370: pcctwointr_establish(PCC2V_SCC_TX,&sc->sc_ih_t, sc->sc_txintrname);
! 371: pcctwointr_establish(PCC2V_SCC_RX,&sc->sc_ih_r, sc->sc_rxintrname);
! 372: sys_pcc2->pcc2_sccerr = 0x01; /* clear errors */
! 373:
! 374: /* enable all interrupts at ca_ipl */
! 375: sys_pcc2->pcc2_sccirq = PCC2_IRQ_IEN | (ca->ca_ipl & 0x7);
! 376: sys_pcc2->pcc2_scctx = PCC2_IRQ_IEN | (ca->ca_ipl & 0x7);
! 377: sys_pcc2->pcc2_sccrx = PCC2_IRQ_IEN | (ca->ca_ipl & 0x7);
! 378:
! 379: printf("\n");
! 380: }
! 381:
! 382: void
! 383: cl_initchannel(sc, channel)
! 384: struct clsoftc *sc;
! 385: int channel;
! 386: {
! 387: int s;
! 388: struct clreg *cl_reg = sc->cl_reg;
! 389:
! 390: /* set up option registers */
! 391: sc->sc_cl[channel].tty = NULL;
! 392: s = splhigh();
! 393:
! 394: cl_reg->cl_car = (u_char) channel;
! 395: cl_reg->cl_livr = PCC2_VECBASE + 0xc;/* set vector base at 5C */
! 396: cl_reg->cl_ier = 0x00;
! 397:
! 398: if (sc->sc_cl[channel].cl_consio == 0) {
! 399: cl_reg->cl_cmr = 0x02;
! 400: cl_reg->cl_cor1 = 0x17;
! 401: cl_reg->cl_cor2 = 0x00;
! 402: cl_reg->cl_cor3 = 0x02;
! 403: cl_reg->cl_cor4 = 0xec;
! 404: cl_reg->cl_cor5 = 0xec;
! 405: cl_reg->cl_cor6 = 0x00;
! 406: cl_reg->cl_cor7 = 0x00;
! 407: cl_reg->cl_schr1 = 0x00;
! 408: cl_reg->cl_schr2 = 0x00;
! 409: cl_reg->cl_schr3 = 0x00;
! 410: cl_reg->cl_schr4 = 0x00;
! 411: cl_reg->cl_scrl = 0x00;
! 412: cl_reg->cl_scrh = 0x00;
! 413: cl_reg->cl_lnxt = 0x00;
! 414: cl_reg->cl_rbpr = 0x40; /* 9600 */
! 415: cl_reg->cl_rcor = 0x01;
! 416: cl_reg->cl_tbpr = 0x40; /* 9600 */
! 417: cl_reg->cl_tcor = 0x01 << 5;
! 418: /* console port should be 0x88 already */
! 419: cl_reg->cl_msvr_rts = 0x00;
! 420: cl_reg->cl_msvr_dtr = 0x00;
! 421: cl_reg->cl_rtprl = CL_RX_TIMEOUT;
! 422: cl_reg->cl_rtprh = 0x00;
! 423:
! 424: sc->cl_reg->cl_ccr = 0x20;
! 425: while (sc->cl_reg->cl_ccr != 0)
! 426: ;
! 427: }
! 428:
! 429: splx(s);
! 430: }
! 431:
! 432:
! 433: int cldefaultrate = TTYDEF_SPEED;
! 434:
! 435: int clmctl (dev, bits, how)
! 436: dev_t dev;
! 437: int bits;
! 438: int how;
! 439: {
! 440: int s;
! 441: struct clsoftc *sc;
! 442: /* should only be called with valid device */
! 443: sc = (struct clsoftc *) cl_cd.cd_devs[CL_UNIT(dev)];
! 444: /*
! 445: printf("mctl: dev %x, bits %x, how %x,\n",dev, bits, how);
! 446: */
! 447: /* settings are currently ignored */
! 448: s = splcl();
! 449: switch (how) {
! 450: case DMSET:
! 451: if( bits & TIOCM_RTS) {
! 452: sc->cl_reg->cl_msvr_rts = 0x01;
! 453: } else {
! 454: sc->cl_reg->cl_msvr_rts = 0x00;
! 455: }
! 456: if( bits & TIOCM_DTR) {
! 457: sc->cl_reg->cl_msvr_dtr = 0x02;
! 458: } else {
! 459: sc->cl_reg->cl_msvr_dtr = 0x00;
! 460: }
! 461: break;
! 462:
! 463: case DMBIC:
! 464: if( bits & TIOCM_RTS) {
! 465: sc->cl_reg->cl_msvr_rts = 0x00;
! 466: }
! 467: if( bits & TIOCM_DTR) {
! 468: sc->cl_reg->cl_msvr_dtr = 0x00;
! 469: }
! 470: break;
! 471:
! 472: case DMBIS:
! 473: if( bits & TIOCM_RTS) {
! 474: sc->cl_reg->cl_msvr_rts = 0x01;
! 475: }
! 476: if( bits & TIOCM_DTR) {
! 477: sc->cl_reg->cl_msvr_dtr = 0x02;
! 478: }
! 479: break;
! 480:
! 481: case DMGET:
! 482: bits = 0;
! 483:
! 484: {
! 485: u_char msvr;
! 486: msvr = sc->cl_reg->cl_msvr_rts;
! 487: if( msvr & 0x80) {
! 488: bits |= TIOCM_DSR;
! 489: }
! 490: if( msvr & 0x40) {
! 491: bits |= TIOCM_CD;
! 492: }
! 493: if( msvr & 0x20) {
! 494: bits |= TIOCM_CTS;
! 495: }
! 496: if( msvr & 0x10) {
! 497: bits |= TIOCM_DTR;
! 498: }
! 499: if( msvr & 0x02) {
! 500: bits |= TIOCM_DTR;
! 501: }
! 502: if( msvr & 0x01) {
! 503: bits |= TIOCM_RTS;
! 504: }
! 505:
! 506: }
! 507: break;
! 508: }
! 509: splx(s);
! 510: #if 0
! 511: bits = 0;
! 512: /* proper defaults? */
! 513: bits |= TIOCM_DTR;
! 514: bits |= TIOCM_RTS;
! 515: bits |= TIOCM_CTS;
! 516: bits |= TIOCM_CD;
! 517: /* bits |= TIOCM_RI; */
! 518: bits |= TIOCM_DSR;
! 519: #endif
! 520:
! 521: /*
! 522: printf("retbits %x\n", bits);
! 523: */
! 524: return(bits);
! 525: }
! 526:
! 527: int
! 528: clopen(dev, flag, mode, p)
! 529: dev_t dev;
! 530: int flag;
! 531: int mode;
! 532: struct proc *p;
! 533: {
! 534: int s, unit, channel;
! 535: struct cl_info *cl;
! 536: struct clsoftc *sc;
! 537: struct tty *tp;
! 538:
! 539: unit = CL_UNIT(dev);
! 540: if (unit >= cl_cd.cd_ndevs ||
! 541: (sc = (struct clsoftc *) cl_cd.cd_devs[unit]) == NULL) {
! 542: return (ENODEV);
! 543: }
! 544: channel = CL_CHANNEL(dev);
! 545: cl = &sc->sc_cl[channel];
! 546: s = splcl();
! 547: if (cl->tty) {
! 548: tp = cl->tty;
! 549: } else {
! 550: tp = cl->tty = ttymalloc();
! 551: }
! 552: tp->t_oproc = clstart;
! 553: tp->t_param = clparam;
! 554: tp->t_dev = dev;
! 555:
! 556: if ((tp->t_state & TS_ISOPEN) == 0) {
! 557: tp->t_state |= TS_WOPEN;
! 558: ttychars(tp);
! 559: if (tp->t_ispeed == 0) {
! 560: /*
! 561: * only when cleared do we reset to defaults.
! 562: */
! 563: tp->t_iflag = TTYDEF_IFLAG;
! 564: tp->t_oflag = TTYDEF_OFLAG;
! 565: tp->t_lflag = TTYDEF_LFLAG;
! 566: tp->t_ispeed = tp->t_ospeed = cldefaultrate;
! 567:
! 568: if(sc->sc_cl[channel].cl_consio != 0) {
! 569: /* console is 8N1 */
! 570: tp->t_cflag = (CREAD | CS8 | HUPCL);
! 571: } else {
! 572: tp->t_cflag = TTYDEF_CFLAG;
! 573: }
! 574: }
! 575: /*
! 576: * do these all the time
! 577: */
! 578: if (cl->cl_swflags & TIOCFLAG_CLOCAL)
! 579: tp->t_cflag |= CLOCAL;
! 580: if (cl->cl_swflags & TIOCFLAG_CRTSCTS)
! 581: tp->t_cflag |= CRTSCTS;
! 582: if (cl->cl_swflags & TIOCFLAG_MDMBUF)
! 583: tp->t_cflag |= MDMBUF;
! 584: clparam(tp, &tp->t_termios);
! 585: ttsetwater(tp);
! 586:
! 587: (void)clmctl(dev, TIOCM_DTR | TIOCM_RTS, DMSET);
! 588: #ifdef XXX
! 589: if ((cl->cl_swflags & TIOCFLAG_SOFTCAR) ||
! 590: (clmctl(dev, 0, DMGET) & TIOCM_CD)) {
! 591: tp->t_state |= TS_CARR_ON;
! 592: } else {
! 593: tp->t_state &= ~TS_CARR_ON;
! 594: }
! 595: #endif
! 596: tp->t_state |= TS_CARR_ON;
! 597: {
! 598: u_char save = sc->cl_reg->cl_car;
! 599: sc->cl_reg->cl_car = channel;
! 600: sc->cl_reg->cl_ier = 0x88;
! 601: #ifdef CL_DMA_WORKS
! 602: {
! 603: sc->cl_reg->cl_cmr =
! 604: /* CL_TXDMAINT | */ CL_RXDMAINT;
! 605: sc->cl_reg->cl_ier = 0xa8;
! 606: sc->cl_reg->cl_licr = 0x00;
! 607: }
! 608: sc->cl_reg->cl_arbadrl =
! 609: ((u_long)sc->sc_cl[channel].rxp[0]) & 0xffff;
! 610: sc->cl_reg->cl_arbadru =
! 611: ((u_long)sc->sc_cl[channel].rxp[0]) >> 16;
! 612: sc->cl_reg->cl_brbadrl =
! 613: ((u_long)sc->sc_cl[channel].rxp[1]) & 0xffff;
! 614: sc->cl_reg->cl_brbadru =
! 615: ((u_long)sc->sc_cl[channel].rxp[1]) >> 16;
! 616: sc->cl_reg->cl_atbadrl =
! 617: ((u_long)sc->sc_cl[channel].txp[0]) & 0xffff;
! 618: sc->cl_reg->cl_atbadru =
! 619: ((u_long)sc->sc_cl[channel].txp[0]) >> 16;
! 620: sc->cl_reg->cl_btbadrl =
! 621: ((u_long)sc->sc_cl[channel].txp[1]) & 0xffff;
! 622: sc->cl_reg->cl_btbadru =
! 623: ((u_long)sc->sc_cl[channel].txp[1]) >> 16;
! 624: sc->cl_reg->cl_arbcnt = CL_BUFSIZE;
! 625: sc->cl_reg->cl_brbcnt = CL_BUFSIZE;
! 626: sc->cl_reg->cl_arbsts = 0x01;
! 627: sc->cl_reg->cl_brbsts = 0x01;
! 628: if (channel == 2) { /* test one channel now */
! 629: /* shift for tx DMA */
! 630: /* no shift for rx DMA */
! 631: #if 0
! 632: /* tx only */
! 633: sc->cl_reg->cl_licr = (CL_DMAMODE << 4);
! 634: sc->cl_reg->cl_cmr = 0x42;
! 635: #endif
! 636: /* rx only */
! 637: sc->cl_reg->cl_licr = 0x00;
! 638: sc->cl_reg->cl_cmr = 0x82;
! 639: }
! 640: sc->cl_reg->cl_ccr = 0x20;
! 641: while (sc->cl_reg->cl_ccr != 0) {
! 642: }
! 643: #endif /* CL_DMA_WORKS */
! 644: sc->cl_reg->cl_car = save;
! 645: }
! 646: } else if (tp->t_state & TS_XCLUDE && p->p_ucred->cr_uid != 0) {
! 647: splx(s);
! 648: return(EBUSY);
! 649: }
! 650: #ifdef XXX
! 651: /*
! 652: * if NONBLOCK requested, ignore carrier
! 653: */
! 654: if (flag & O_NONBLOCK)
! 655: goto done;
! 656: #endif
! 657:
! 658: splx(s);
! 659: /*
! 660: * Reset the tty pointer, as there could have been a dialout
! 661: * use of the tty with a dialin open waiting.
! 662: */
! 663: tp->t_dev = dev;
! 664: #ifdef DEBUG
! 665: cl_dumpport(channel);
! 666: #endif
! 667: return((*linesw[tp->t_line].l_open)(dev, tp));
! 668: }
! 669: int clparam(tp, t)
! 670: struct tty *tp;
! 671: struct termios *t;
! 672: {
! 673: int unit, channel;
! 674: struct clsoftc *sc;
! 675: int s;
! 676: dev_t dev;
! 677:
! 678: dev = tp->t_dev;
! 679: unit = CL_UNIT(dev);
! 680: if (unit >= cl_cd.cd_ndevs ||
! 681: (sc = (struct clsoftc *) cl_cd.cd_devs[unit]) == NULL) {
! 682: return (ENODEV);
! 683: }
! 684: channel = CL_CHANNEL(dev);
! 685: tp->t_ispeed = t->c_ispeed;
! 686: tp->t_ospeed = t->c_ospeed;
! 687: tp->t_cflag = t->c_cflag;
! 688: clccparam(sc, t, channel);
! 689: s = splcl();
! 690: cl_unblock(tp);
! 691: splx(s);
! 692: return 0;
! 693: }
! 694:
! 695: #if 0
! 696: void cloutput(tp)
! 697: struct tty *tp;
! 698: {
! 699: int cc, s, unit, cnt;
! 700: u_char *tptr;
! 701: int channel;
! 702: struct clsoftc *sc;
! 703: dev_t dev;
! 704: u_char cl_obuffer[CLCDBUF+1];
! 705:
! 706: dev = tp->t_dev;
! 707: unit = CL_UNIT(dev);
! 708: if (unit >= cl_cd.cd_ndevs ||
! 709: (sc = (struct clsoftc *) cl_cd.cd_devs[unit]) == NULL) {
! 710: return;
! 711: }
! 712: channel = CL_CHANNEL(dev);
! 713:
! 714: if ((tp->t_state & TS_ISOPEN) == 0)
! 715: return;
! 716:
! 717: s = splcl();
! 718: cc = tp->t_outq.c_cc;
! 719: while (cc > 0) {
! 720: /*XXX*/
! 721: cnt = min (CLCDBUF,cc);
! 722: cnt = q_to_b(&tp->t_outq, cl_obuffer, cnt);
! 723: if (cnt == 0) {
! 724: break;
! 725: }
! 726: for (tptr = cl_obuffer; tptr < &cl_obuffer[cnt]; tptr++) {
! 727: clputc(sc, channel, *tptr);
! 728: }
! 729: cc -= cnt;
! 730: }
! 731: splx(s);
! 732: }
! 733: #endif
! 734:
! 735: int
! 736: clclose(dev, flag, mode, p)
! 737: dev_t dev;
! 738: int flag;
! 739: int mode;
! 740: struct proc *p;
! 741: {
! 742: int unit, channel;
! 743: struct tty *tp;
! 744: struct cl_info *cl;
! 745: struct clsoftc *sc;
! 746: int s;
! 747: unit = CL_UNIT(dev);
! 748: if (unit >= cl_cd.cd_ndevs ||
! 749: (sc = (struct clsoftc *) cl_cd.cd_devs[unit]) == NULL) {
! 750: return (ENODEV);
! 751: }
! 752: channel = CL_CHANNEL(dev);
! 753: cl = &sc->sc_cl[channel];
! 754: tp = cl->tty;
! 755: (*linesw[tp->t_line].l_close)(tp, flag);
! 756:
! 757: s = splcl();
! 758:
! 759: sc->cl_reg->cl_car = channel;
! 760: if(cl->cl_consio == 0 && (tp->t_cflag & HUPCL) != 0) {
! 761: sc->cl_reg->cl_msvr_rts = 0x00;
! 762: sc->cl_reg->cl_msvr_dtr = 0x00;
! 763: sc->cl_reg->cl_ccr = 0x05;
! 764: }
! 765:
! 766: splx(s);
! 767: ttyclose(tp);
! 768:
! 769: #if 0
! 770: cl->tty = NULL;
! 771: #endif
! 772: #ifdef DEBUG
! 773: cl_dumpport(channel);
! 774: #endif
! 775:
! 776: return 0;
! 777: }
! 778:
! 779: int
! 780: clread (dev, uio, flag)
! 781: dev_t dev;
! 782: struct uio *uio;
! 783: int flag;
! 784: {
! 785: int unit, channel;
! 786: struct tty *tp;
! 787: struct cl_info *cl;
! 788: struct clsoftc *sc;
! 789: unit = CL_UNIT(dev);
! 790: if (unit >= cl_cd.cd_ndevs ||
! 791: (sc = (struct clsoftc *) cl_cd.cd_devs[unit]) == NULL) {
! 792: return (ENODEV);
! 793: }
! 794: channel = CL_CHANNEL(dev);
! 795: cl = &sc->sc_cl[channel];
! 796: tp = cl->tty;
! 797: if (!tp)
! 798: return ENXIO;
! 799: return((*linesw[tp->t_line].l_read)(tp, uio, flag));
! 800: }
! 801:
! 802: int
! 803: clwrite (dev, uio, flag)
! 804: dev_t dev;
! 805: struct uio *uio;
! 806: int flag;
! 807: {
! 808: int unit, channel;
! 809: struct tty *tp;
! 810: struct cl_info *cl;
! 811: struct clsoftc *sc;
! 812: unit = CL_UNIT(dev);
! 813: if (unit >= cl_cd.cd_ndevs ||
! 814: (sc = (struct clsoftc *) cl_cd.cd_devs[unit]) == NULL) {
! 815: return (ENODEV);
! 816: }
! 817: channel = CL_CHANNEL(dev);
! 818: cl = &sc->sc_cl[channel];
! 819: tp = cl->tty;
! 820: if (!tp)
! 821: return ENXIO;
! 822: return((*linesw[tp->t_line].l_write)(tp, uio, flag));
! 823: }
! 824:
! 825: int
! 826: clioctl(dev, cmd, data, flag, p)
! 827: dev_t dev;
! 828: u_long cmd;
! 829: caddr_t data;
! 830: int flag;
! 831: struct proc *p;
! 832: {
! 833: int error;
! 834: int unit, channel;
! 835: struct tty *tp;
! 836: struct cl_info *cl;
! 837: struct clsoftc *sc;
! 838: unit = CL_UNIT(dev);
! 839: if (unit >= cl_cd.cd_ndevs ||
! 840: (sc = (struct clsoftc *) cl_cd.cd_devs[unit]) == NULL) {
! 841: return (ENODEV);
! 842: }
! 843: channel = CL_CHANNEL(dev);
! 844: cl = &sc->sc_cl[channel];
! 845: tp = cl->tty;
! 846: if (!tp)
! 847: return ENXIO;
! 848:
! 849: error = (*linesw[tp->t_line].l_ioctl)(tp, cmd, data, flag, p);
! 850: if (error >= 0)
! 851: return(error);
! 852:
! 853: error = ttioctl(tp, cmd, data, flag, p);
! 854: if (error >= 0)
! 855: return(error);
! 856:
! 857: switch (cmd) {
! 858: case TIOCSBRK:
! 859: /* */
! 860: break;
! 861:
! 862: case TIOCCBRK:
! 863: /* */
! 864: break;
! 865:
! 866: case TIOCSDTR:
! 867: (void) clmctl(dev, TIOCM_DTR | TIOCM_RTS, DMBIS);
! 868: break;
! 869:
! 870: case TIOCCDTR:
! 871: (void) clmctl(dev, TIOCM_DTR | TIOCM_RTS, DMBIC);
! 872: break;
! 873:
! 874: case TIOCMSET:
! 875: (void) clmctl(dev, *(int *) data, DMSET);
! 876: break;
! 877:
! 878: case TIOCMBIS:
! 879: (void) clmctl(dev, *(int *) data, DMBIS);
! 880: break;
! 881:
! 882: case TIOCMBIC:
! 883: (void) clmctl(dev, *(int *) data, DMBIC);
! 884: break;
! 885:
! 886: case TIOCMGET:
! 887: *(int *)data = clmctl(dev, 0, DMGET);
! 888: break;
! 889: case TIOCGFLAGS:
! 890: *(int *)data = cl->cl_swflags;
! 891: break;
! 892: case TIOCSFLAGS:
! 893: error = suser(p, 0);
! 894: if (error != 0)
! 895: return(EPERM);
! 896:
! 897: cl->cl_swflags = *(int *)data;
! 898: cl->cl_swflags &= /* only allow valid flags */
! 899: (TIOCFLAG_SOFTCAR | TIOCFLAG_CLOCAL | TIOCFLAG_CRTSCTS);
! 900: break;
! 901: default:
! 902: return(ENOTTY);
! 903: }
! 904:
! 905: return 0;
! 906: }
! 907: int
! 908: clstop(tp, flag)
! 909: struct tty *tp;
! 910: int flag;
! 911: {
! 912: int s;
! 913:
! 914: s = splcl();
! 915: if (tp->t_state & TS_BUSY) {
! 916: if ((tp->t_state & TS_TTSTOP) == 0)
! 917: tp->t_state |= TS_FLUSH;
! 918: }
! 919: splx(s);
! 920: return 0;
! 921: }
! 922:
! 923: void
! 924: clcnprobe(cp)
! 925: struct consdev *cp;
! 926: {
! 927: int maj;
! 928:
! 929: switch (cputyp) {
! 930: case CPU_167:
! 931: case CPU_177:
! 932: break;
! 933: default:
! 934: return;
! 935: }
! 936:
! 937: /* locate the major number */
! 938: for (maj = 0; maj < nchrdev; maj++)
! 939: if (cdevsw[maj].d_open == clopen)
! 940: break;
! 941: cp->cn_dev = makedev (maj, 0);
! 942: cp->cn_pri = CN_NORMAL;
! 943: }
! 944:
! 945: void
! 946: clcninit(cp)
! 947: struct consdev *cp;
! 948: {
! 949: struct clreg *cl_reg;
! 950:
! 951: cl_cons.cl_paddr = 0xfff45000;
! 952: cl_cons.cl_vaddr = (struct clreg *)IIOV(cl_cons.cl_paddr);
! 953: cl_cons.pcctwoaddr = (void *)IIOV(0xfff42000);
! 954: cl_reg = cl_cons.cl_vaddr;
! 955:
! 956: /* reset the chip? */
! 957: #ifdef CLCD_DO_RESET
! 958: #endif
! 959:
! 960: #if 1
! 961: /* set up globals */
! 962: cl_reg->cl_tftc = 0x10;
! 963: cl_reg->cl_tpr = CL_TIMEOUT; /* is this correct?? */
! 964: cl_reg->cl_rpilr = 0x03;
! 965: cl_reg->cl_tpilr = 0x02;
! 966: cl_reg->cl_mpilr = 0x01;
! 967:
! 968: /* set up the tty00 to be 9600 8N1 */
! 969: cl_reg->cl_car = 0x00;
! 970: cl_reg->cl_cor1 = 0x17; /* No parity, ignore parity, 8 bit char */
! 971: cl_reg->cl_cor2 = 0x00;
! 972: cl_reg->cl_cor3 = 0x02; /* 1 stop bit */
! 973: cl_reg->cl_cor4 = 0x00;
! 974: cl_reg->cl_cor5 = 0x00;
! 975: cl_reg->cl_cor6 = 0x00;
! 976: cl_reg->cl_cor7 = 0x00;
! 977: cl_reg->cl_schr1 = 0x00;
! 978: cl_reg->cl_schr2 = 0x00;
! 979: cl_reg->cl_schr3 = 0x00;
! 980: cl_reg->cl_schr4 = 0x00;
! 981: cl_reg->cl_scrl = 0x00;
! 982: cl_reg->cl_scrh = 0x00;
! 983: cl_reg->cl_lnxt = 0x00;
! 984: cl_reg->cl_cpsr = 0x00;
! 985: #endif
! 986: }
! 987:
! 988: int
! 989: cl_instat(sc)
! 990: struct clsoftc *sc;
! 991: {
! 992: struct clreg *cl_reg;
! 993: if ( NULL == sc) {
! 994: cl_reg = cl_cons.cl_vaddr;
! 995: } else {
! 996: cl_reg = sc->cl_reg;
! 997: }
! 998: return (cl_reg->cl_rir & 0x40);
! 999: }
! 1000: int
! 1001: clcngetc(dev)
! 1002: dev_t dev;
! 1003: {
! 1004: u_char val, reoir, licr, isrl, data, fifo_cnt;
! 1005: #if 0
! 1006: u_char status;
! 1007: #endif
! 1008: int got_char = 0;
! 1009: u_char ier_old = 0xff;
! 1010: struct clreg *cl_reg = cl_cons.cl_vaddr;
! 1011: volatile struct pcctworeg *pcc2_base = cl_cons.pcctwoaddr;
! 1012:
! 1013: cl_reg->cl_car = 0;
! 1014: if (!(cl_reg->cl_ier & 0x08)) {
! 1015: ier_old = cl_reg->cl_ier;
! 1016: cl_reg->cl_ier = 0x08;
! 1017: }
! 1018: while (got_char == 0) {
! 1019: val = cl_reg->cl_rir;
! 1020: /* if no receive interrupt pending wait */
! 1021: if (!(val & 0x80)) {
! 1022: continue;
! 1023: }
! 1024: /* XXX do we need to suck the entire FIFO contents? */
! 1025: reoir = pcc2_base->pcc2_sccrxiack; /* receive PIACK */
! 1026: licr = cl_reg->cl_licr;
! 1027: if (((licr >> 2) & 0x3) == 0) {
! 1028: /* is the interrupt for us (port 0) */
! 1029: /* the character is for us yea. */
! 1030: isrl = cl_reg->cl_risrl;
! 1031: #if 0
! 1032: if (isrl & 0x01) {
! 1033: status = BREAK;
! 1034: }
! 1035: if (isrl & 0x02) {
! 1036: status = FRAME;
! 1037: }
! 1038: if (isrl & 0x04) {
! 1039: status = PARITY;
! 1040: }
! 1041: if (isrl & 0x08) {
! 1042: status = OVERFLOW;
! 1043: }
! 1044: /* we do not have special characters ;-) */
! 1045: #endif
! 1046: fifo_cnt = cl_reg->cl_rfoc;
! 1047: data = cl_reg->cl_rdr;
! 1048: if (ier_old != 0xff) {
! 1049: cl_reg->cl_ier = ier_old;
! 1050: }
! 1051: got_char = 1;
! 1052: cl_reg->cl_teoir = 0x00;
! 1053: } else {
! 1054: data = cl_reg->cl_rdr;
! 1055: cl_reg->cl_teoir = 0x00;
! 1056: }
! 1057:
! 1058: }
! 1059:
! 1060: return data;
! 1061: }
! 1062:
! 1063: void
! 1064: clcnputc(dev, c)
! 1065: dev_t dev;
! 1066: u_char c;
! 1067: {
! 1068: clputc(0, 0, c);
! 1069: }
! 1070:
! 1071: void
! 1072: clcnpollc(dev, on)
! 1073: dev_t dev;
! 1074: int on;
! 1075: {
! 1076: if (1 == on) {
! 1077: /* enable polling */
! 1078: } else {
! 1079: /* disable polling */
! 1080: }
! 1081: return;
! 1082: }
! 1083:
! 1084: void
! 1085: clputc(sc, unit, c)
! 1086: struct clsoftc *sc;
! 1087: int unit;
! 1088: u_char c;
! 1089: {
! 1090: int s;
! 1091: u_char schar;
! 1092: u_char oldchannel;
! 1093: struct clreg *cl_reg;
! 1094: if (0 == sc) {
! 1095: /* output on console */
! 1096: cl_reg = cl_cons.cl_vaddr;
! 1097: } else {
! 1098: cl_reg = sc->cl_reg;
! 1099: }
! 1100: #ifdef NEW_CLCD_STRUCT
! 1101: /* should we disable, flush and all that goo? */
! 1102: cl->car = unit;
! 1103: schar = cl->schr3;
! 1104: cl->schr3 = c;
! 1105: cl->stcr = 0x08 | 0x03; /* send special char, char 3 */
! 1106: while (0 != cl->stcr) {
! 1107: /* wait until cl notices the command
! 1108: * otherwise it may not notice the character
! 1109: * if we send characters too fast.
! 1110: */
! 1111: }
! 1112: cl->schr3 = schar;
! 1113: #else
! 1114: if (unit == 0) {
! 1115: s = splhigh();
! 1116: oldchannel = cl_reg->cl_car;
! 1117: cl_reg->cl_car = unit;
! 1118: schar = cl_reg->cl_schr3;
! 1119: cl_reg->cl_schr3 = c;
! 1120: cl_reg->cl_stcr = 0x08 | 0x03; /* send special char, char 3 */
! 1121: while (0 != cl_reg->cl_stcr) {
! 1122: /* wait until cl notices the command
! 1123: * otherwise it may not notice the character
! 1124: * if we send characters too fast.
! 1125: */
! 1126: }
! 1127: DELAY(5);
! 1128: cl_reg->cl_schr3 = schar;
! 1129: cl_reg->cl_car = oldchannel;
! 1130: splx(s);
! 1131: } else {
! 1132: s = splhigh();
! 1133: oldchannel = cl_reg->cl_car;
! 1134: cl_reg->cl_car = unit;
! 1135: if (cl_reg->cl_tftc > 0) {
! 1136: cl_reg->cl_tdr = c;
! 1137: }
! 1138: cl_reg->cl_car = oldchannel;
! 1139: splx(s);
! 1140: }
! 1141: #endif
! 1142: return;
! 1143: }
! 1144:
! 1145: u_char
! 1146: clgetc(sc, channel)
! 1147: struct clsoftc *sc;
! 1148: int *channel;
! 1149: {
! 1150: struct clreg *cl_reg;
! 1151: volatile struct pcctworeg *pcc2_base;
! 1152: u_char val, reoir, licr, isrl, fifo_cnt, data;
! 1153: if (sc == NULL) {
! 1154: cl_reg = cl_cons.cl_vaddr;
! 1155: pcc2_base = cl_cons.pcctwoaddr;
! 1156: } else {
! 1157: cl_reg = sc->cl_reg;
! 1158: pcc2_base = sys_pcc2;
! 1159: }
! 1160: val = cl_reg->cl_rir;
! 1161: /* if no receive interrupt pending wait */
! 1162: if (!(val & 0x80)) {
! 1163: return 0;
! 1164: }
! 1165: /* XXX do we need to suck the entire FIFO contents? */
! 1166: reoir = pcc2_base->pcc2_sccrxiack; /* receive PIACK */
! 1167: licr = cl_reg->cl_licr;
! 1168: *channel = (licr >> 2) & 0x3;
! 1169: /* is the interrupt for us (port 0) */
! 1170: /* the character is for us yea. */
! 1171: isrl = cl_reg->cl_risrl;
! 1172: #if 0
! 1173: if (isrl & 0x01) {
! 1174: status = BREAK;
! 1175: }
! 1176: if (isrl & 0x02) {
! 1177: status = FRAME;
! 1178: }
! 1179: if (isrl & 0x04) {
! 1180: status = PARITY;
! 1181: }
! 1182: if (isrl & 0x08) {
! 1183: status = OVERFLOW;
! 1184: }
! 1185: /* we do not have special characters ;-) */
! 1186: #endif
! 1187: fifo_cnt = cl_reg->cl_rfoc;
! 1188: if (fifo_cnt > 0) {
! 1189: data = cl_reg->cl_rdr;
! 1190: cl_reg->cl_teoir = 0x00;
! 1191: } else {
! 1192: data = 0;
! 1193: cl_reg->cl_teoir = 0x08;
! 1194: }
! 1195: return data;
! 1196: }
! 1197: int
! 1198: clccparam(sc, par, channel)
! 1199: struct clsoftc *sc;
! 1200: struct termios *par;
! 1201: int channel;
! 1202: {
! 1203: u_int divisor, clk, clen;
! 1204: int s, imask, ints;
! 1205:
! 1206: s = splcl();
! 1207: sc->cl_reg->cl_car = channel;
! 1208: if (par->c_ospeed == 0) {
! 1209: /* dont kill the console */
! 1210: if(sc->sc_cl[channel].cl_consio == 0) {
! 1211: /* disconnect, drop RTS DTR stop receiver */
! 1212: sc->cl_reg->cl_msvr_rts = 0x00;
! 1213: sc->cl_reg->cl_msvr_dtr = 0x00;
! 1214: sc->cl_reg->cl_ccr = 0x05;
! 1215: }
! 1216: splx(s);
! 1217: return (0xff);
! 1218: }
! 1219:
! 1220: sc->cl_reg->cl_msvr_rts = 0x03;
! 1221: sc->cl_reg->cl_msvr_dtr = 0x03;
! 1222:
! 1223: divisor = cl_clkdiv(par->c_ospeed);
! 1224: clk = cl_clknum(par->c_ospeed);
! 1225: sc->cl_reg->cl_tbpr = divisor;
! 1226: sc->cl_reg->cl_tcor = clk << 5;
! 1227: divisor = cl_clkdiv(par->c_ispeed);
! 1228: clk = cl_clknum(par->c_ispeed);
! 1229: sc->cl_reg->cl_rbpr = divisor;
! 1230: sc->cl_reg->cl_rcor = clk;
! 1231: sc->cl_reg->cl_rtprl = cl_clkrxtimeout(par->c_ispeed);
! 1232: sc->cl_reg->cl_rtprh = 0x00;
! 1233:
! 1234: switch (par->c_cflag & CSIZE) {
! 1235: case CS5:
! 1236: clen = 4; /* this is the mask for the chip. */
! 1237: imask = 0x1F;
! 1238: break;
! 1239: case CS6:
! 1240: clen = 5;
! 1241: imask = 0x3F;
! 1242: break;
! 1243: case CS7:
! 1244: clen = 6;
! 1245: imask = 0x7F;
! 1246: break;
! 1247: default:
! 1248: clen = 7;
! 1249: imask = 0xFF;
! 1250: }
! 1251: sc->cl_reg->cl_cor3 = par->c_cflag & PARENB ? 4 : 2;
! 1252:
! 1253: {
! 1254: u_char cor1;
! 1255: if (par->c_cflag & PARENB) {
! 1256: if (par->c_cflag & PARODD) {
! 1257: cor1 = 0xE0 | clen ; /* odd */
! 1258: } else {
! 1259: cor1 = 0x40 | clen ; /* even */
! 1260: }
! 1261: } else {
! 1262: cor1 = 0x10 | clen; /* ignore parity */
! 1263: }
! 1264: if (sc->cl_reg->cl_cor1 != cor1) {
! 1265: sc->cl_reg->cl_cor1 = cor1;
! 1266: sc->cl_reg->cl_ccr = 0x20;
! 1267: while (sc->cl_reg->cl_ccr != 0) {
! 1268: }
! 1269: }
! 1270: }
! 1271:
! 1272: if (sc->sc_cl[channel].cl_consio == 0 && (par->c_cflag & CREAD) == 0)
! 1273: sc->cl_reg->cl_ccr = 0x08;
! 1274: else
! 1275: sc->cl_reg->cl_ccr = 0x0a;
! 1276: while (sc->cl_reg->cl_ccr != 0) {
! 1277: }
! 1278: ints = 0;
! 1279: #define SCC_DSR 0x80
! 1280: #define SCC_DCD 0x40
! 1281: #define SCC_CTS 0x20
! 1282: if ((par->c_cflag & CLOCAL) == 0) {
! 1283: ints |= SCC_DCD;
! 1284: }
! 1285: if ((par->c_cflag & CCTS_OFLOW) != 0) {
! 1286: ints |= SCC_CTS;
! 1287: }
! 1288: if ((par->c_cflag & CRTSCTS) != 0) {
! 1289: ints |= SCC_CTS;
! 1290: }
! 1291: #ifdef DONT_LET_HARDWARE
! 1292: if ((par->c_cflag & CCTS_IFLOW) != 0) {
! 1293: ints |= SCC_DSR;
! 1294: }
! 1295: #endif
! 1296: sc->cl_reg->cl_cor4 = ints | CL_FIFO_CNT;
! 1297: sc->cl_reg->cl_cor5 = ints | CL_FIFO_CNT;
! 1298:
! 1299: return imask;
! 1300: }
! 1301: static int clknum = 0;
! 1302: u_char
! 1303: cl_clkdiv(speed)
! 1304: int speed;
! 1305: {
! 1306: int i = 0;
! 1307: if (cl_clocks[clknum].speed == speed) {
! 1308: return cl_clocks[clknum].divisor;
! 1309: }
! 1310: for (i = 0; cl_clocks[i].speed != 0; i++) {
! 1311: if (cl_clocks[i].speed == speed) {
! 1312: clknum = i;
! 1313: return cl_clocks[clknum].divisor;
! 1314: }
! 1315: }
! 1316: /* return some sane value if unknown speed */
! 1317: return cl_clocks[4].divisor;
! 1318: }
! 1319: u_char
! 1320: cl_clknum(speed)
! 1321: int speed;
! 1322: {
! 1323: int found = 0;
! 1324: int i = 0;
! 1325: if (cl_clocks[clknum].speed == speed) {
! 1326: return cl_clocks[clknum].clock;
! 1327: }
! 1328: for (i = 0; found != 0 && cl_clocks[i].speed != 0; i++) {
! 1329: if (cl_clocks[clknum].speed == speed) {
! 1330: clknum = i;
! 1331: return cl_clocks[clknum].clock;
! 1332: }
! 1333: }
! 1334: /* return some sane value if unknown speed */
! 1335: return cl_clocks[4].clock;
! 1336: }
! 1337: u_char
! 1338: cl_clkrxtimeout(speed)
! 1339: int speed;
! 1340: {
! 1341: int i = 0;
! 1342: if (cl_clocks[clknum].speed == speed) {
! 1343: return cl_clocks[clknum].rx_timeout;
! 1344: }
! 1345: for (i = 0; cl_clocks[i].speed != 0; i++) {
! 1346: if (cl_clocks[i].speed == speed) {
! 1347: clknum = i;
! 1348: return cl_clocks[clknum].rx_timeout;
! 1349: }
! 1350: }
! 1351: /* return some sane value if unknown speed */
! 1352: return cl_clocks[4].rx_timeout;
! 1353: }
! 1354: void
! 1355: cl_unblock(tp)
! 1356: struct tty *tp;
! 1357: {
! 1358: tp->t_state &= ~TS_FLUSH;
! 1359: if (tp->t_outq.c_cc != 0)
! 1360: clstart(tp);
! 1361: }
! 1362: void
! 1363: clstart(tp)
! 1364: struct tty *tp;
! 1365: {
! 1366: dev_t dev;
! 1367: #if 0
! 1368: u_char cbuf;
! 1369: int cnt;
! 1370: #endif
! 1371: struct clsoftc *sc;
! 1372: int channel, unit, s;
! 1373:
! 1374: dev = tp->t_dev;
! 1375: channel = CL_CHANNEL(dev);
! 1376: /* hack to test output on non console only */
! 1377: #if 0
! 1378: if (channel == 0) {
! 1379: cloutput(tp);
! 1380: return;
! 1381: }
! 1382: #endif
! 1383: unit = CL_UNIT(dev);
! 1384: if (unit >= cl_cd.cd_ndevs ||
! 1385: (sc = (struct clsoftc *) cl_cd.cd_devs[unit]) == NULL) {
! 1386: return;
! 1387: }
! 1388:
! 1389: if ((tp->t_state & TS_ISOPEN) == 0)
! 1390: return;
! 1391:
! 1392: s = splcl();
! 1393: #if 0
! 1394: if (sc->sc_cl[channel].transmitting == 1) {
! 1395: /* i'm busy, go away, I will get to it later. */
! 1396: splx(s);
! 1397: return;
! 1398: }
! 1399: cnt = q_to_b(&tp->t_outq, &cbuf, 1);
! 1400: if ( cnt != 0 ) {
! 1401: sc->sc_cl[channel].transmitting = 1;
! 1402: sc->cl_reg->cl_car = channel;
! 1403: sc->cl_reg->cl_tdr = cbuf;
! 1404: } else {
! 1405: sc->sc_cl[channel].transmitting = 0;
! 1406: }
! 1407: #else
! 1408: if ((tp->t_state & (TS_TIMEOUT | TS_BUSY | TS_TTSTOP | TS_FLUSH)) == 0)
! 1409: {
! 1410: tp->t_state |= TS_BUSY;
! 1411: sc->cl_reg->cl_car = channel;
! 1412: sc->cl_reg->cl_ier = sc->cl_reg->cl_ier | 0x3;
! 1413: }
! 1414: #endif
! 1415: splx(s);
! 1416: return;
! 1417: }
! 1418: int
! 1419: cl_mintr(arg)
! 1420: void *arg;
! 1421: {
! 1422: struct clsoftc *sc = (struct clsoftc *)arg;
! 1423: u_char mir, misr, msvr;
! 1424: int channel;
! 1425: if(((mir = sc->cl_reg->cl_mir) & 0x40) == 0x0) {
! 1426: /* only if intr is not shared? */
! 1427: log(LOG_WARNING, "cl_mintr extra intr\n");
! 1428: return 0;
! 1429: }
! 1430:
! 1431: channel = mir & 0x03;
! 1432: misr = sc->cl_reg->cl_misr;
! 1433: msvr = sc->cl_reg->cl_msvr_rts;
! 1434: if (misr & 0x01) {
! 1435: /* timers are not currently used?? */
! 1436: log(LOG_WARNING, "cl_mintr: channel %x timer 1 unexpected\n",channel);
! 1437: }
! 1438: if (misr & 0x02) {
! 1439: /* timers are not currently used?? */
! 1440: log(LOG_WARNING, "cl_mintr: channel %x timer 2 unexpected\n",channel);
! 1441: }
! 1442: if (misr & 0x20) {
! 1443: struct tty *tp = sc->sc_cl[channel].tty;
! 1444: #ifdef VERBOSE_LOG_MESSAGES
! 1445: log(LOG_WARNING, "cl_mintr: channel %x cts %x\n",channel,
! 1446: ((msvr & 0x20) != 0x0)
! 1447: );
! 1448: #endif
! 1449: if (msvr & 0x20) {
! 1450: cl_unblock(tp);
! 1451: }
! 1452: }
! 1453: if (misr & 0x40) {
! 1454: struct tty *tp = sc->sc_cl[channel].tty;
! 1455: #ifdef VERBOSE_LOG_MESSAGES
! 1456: log(LOG_WARNING, "cl_mintr: channel %x cd %x\n",channel,
! 1457: ((msvr & 0x40) != 0x0)
! 1458: );
! 1459: #endif
! 1460: ttymodem(tp, ((msvr & 0x40) != 0x0) );
! 1461: }
! 1462: if (misr & 0x80) {
! 1463: #ifdef VERBOSE_LOG_MESSAGES
! 1464: log(LOG_WARNING, "cl_mintr: channel %x dsr %x\n",channel,
! 1465: ((msvr & 0x80) != 0x0)
! 1466: );
! 1467: #endif
! 1468: }
! 1469: sc->cl_reg->cl_meoir = 0x00;
! 1470: return 1;
! 1471: }
! 1472:
! 1473: int
! 1474: cl_txintr(arg)
! 1475: void *arg;
! 1476: {
! 1477: struct clsoftc *sc = (struct clsoftc *)arg;
! 1478: static int empty = 0;
! 1479: u_char tir, cmr, teoir;
! 1480: u_char max;
! 1481: int channel;
! 1482: struct tty *tp;
! 1483: int cnt;
! 1484: u_char buffer[CL_FIFO_MAX +1];
! 1485: u_char *tptr;
! 1486: if(((tir = sc->cl_reg->cl_tir) & 0x40) == 0x0) {
! 1487: /* only if intr is not shared ??? */
! 1488: log(LOG_WARNING, "cl_txintr extra intr\n");
! 1489: return 0;
! 1490: }
! 1491:
! 1492: channel = tir & 0x03;
! 1493: cmr = sc->cl_reg->cl_cmr;
! 1494:
! 1495: sc->sc_cl[channel].txcnt ++;
! 1496:
! 1497: tp = sc->sc_cl[channel].tty;
! 1498: if (tp == NULL || (tp->t_state & TS_ISOPEN) == 0) {
! 1499: sc->cl_reg->cl_ier = sc->cl_reg->cl_ier & ~0x3;
! 1500: sc->cl_reg->cl_teoir = 0x08;
! 1501: return 1;
! 1502: }
! 1503: switch (cmr & CL_TXMASK) {
! 1504: case CL_TXDMAINT:
! 1505: {
! 1506: u_char dmabsts;
! 1507: int nbuf, busy, resid;
! 1508: void *pbuffer;
! 1509: dmabsts = sc->cl_reg->cl_dmabsts;
! 1510: log(LOG_WARNING, "cl_txintr: DMAMODE channel %x dmabsts %x\n",
! 1511: channel, dmabsts);
! 1512: nbuf = ((dmabsts & 0x8) >> 3) & 0x1;
! 1513: busy = ((dmabsts & 0x4) >> 2) & 0x1;
! 1514:
! 1515: do {
! 1516: pbuffer = sc->sc_cl[channel].tx[nbuf];
! 1517: resid = tp->t_outq.c_cc;
! 1518: cnt = min (CL_BUFSIZE,resid);
! 1519: log(LOG_WARNING, "cl_txintr: resid %x cnt %x pbuf %p\n",
! 1520: resid, cnt, pbuffer);
! 1521: if (cnt != 0) {
! 1522: cnt = q_to_b(&tp->t_outq, pbuffer, cnt);
! 1523: resid -= cnt;
! 1524: if (nbuf == 0) {
! 1525: sc->cl_reg->cl_atbadru =
! 1526: ((u_long) sc->sc_cl[channel].txp[nbuf]) >> 16;
! 1527: sc->cl_reg->cl_atbadrl =
! 1528: ((u_long) sc->sc_cl[channel].txp[nbuf]) & 0xffff;
! 1529: sc->cl_reg->cl_atbcnt = cnt;
! 1530: sc->cl_reg->cl_atbsts = 0x43;
! 1531: } else {
! 1532: sc->cl_reg->cl_btbadru =
! 1533: ((u_long) sc->sc_cl[channel].txp[nbuf]) >> 16;
! 1534: sc->cl_reg->cl_btbadrl =
! 1535: ((u_long) sc->sc_cl[channel].txp[nbuf]) & 0xffff;
! 1536: sc->cl_reg->cl_btbcnt = cnt;
! 1537: sc->cl_reg->cl_btbsts = 0x43;
! 1538: }
! 1539: teoir = 0x08;
! 1540: } else {
! 1541: teoir = 0x08;
! 1542: if (tp->t_state & TS_BUSY) {
! 1543: tp->t_state &= ~(TS_BUSY | TS_FLUSH);
! 1544: if (tp->t_state & TS_ASLEEP) {
! 1545: tp->t_state &= ~TS_ASLEEP;
! 1546: wakeup((caddr_t) &tp->t_outq);
! 1547: }
! 1548: selwakeup(&tp->t_wsel);
! 1549: }
! 1550: sc->cl_reg->cl_ier = sc->cl_reg->cl_ier & ~0x3;
! 1551: }
! 1552: nbuf = ~nbuf & 0x1;
! 1553: busy--;
! 1554: } while (resid != 0 && busy != -1);/* if not busy do other buffer */
! 1555: log(LOG_WARNING, "cl_txintr: done\n");
! 1556: }
! 1557: break;
! 1558: case CL_TXINTR:
! 1559: max = sc->cl_reg->cl_tftc;
! 1560: cnt = min ((int)max,tp->t_outq.c_cc);
! 1561: if (cnt != 0) {
! 1562: cnt = q_to_b(&tp->t_outq, buffer, cnt);
! 1563: empty = 0;
! 1564: for (tptr = buffer; tptr < &buffer[cnt]; tptr++) {
! 1565: sc->cl_reg->cl_tdr = *tptr;
! 1566: }
! 1567: teoir = 0x00;
! 1568: } else {
! 1569: if (empty > 5 && ((empty % 20000 )== 0)) {
! 1570: log(LOG_WARNING, "cl_txintr to many empty intr %d channel %d\n",
! 1571: empty, channel);
! 1572: }
! 1573: empty++;
! 1574: teoir = 0x08;
! 1575: if (tp->t_state & TS_BUSY) {
! 1576: tp->t_state &= ~(TS_BUSY | TS_FLUSH);
! 1577: if (tp->t_state & TS_ASLEEP) {
! 1578: tp->t_state &= ~TS_ASLEEP;
! 1579: wakeup((caddr_t) &tp->t_outq);
! 1580: }
! 1581: selwakeup(&tp->t_wsel);
! 1582: }
! 1583: sc->cl_reg->cl_ier = sc->cl_reg->cl_ier & ~0x3;
! 1584: }
! 1585: break;
! 1586: default:
! 1587: log(LOG_WARNING, "cl_txintr unknown mode %x\n", cmr);
! 1588: /* we probably will go to hell quickly now */
! 1589: teoir = 0x08;
! 1590: }
! 1591: sc->cl_reg->cl_teoir = teoir;
! 1592: return 1;
! 1593: }
! 1594:
! 1595: int
! 1596: cl_rxintr(arg)
! 1597: void *arg;
! 1598: {
! 1599: struct clsoftc *sc = (struct clsoftc *)arg;
! 1600: u_char rir, channel, cmr, risrl;
! 1601: u_char fifocnt;
! 1602: struct tty *tp;
! 1603: int i;
! 1604: u_char reoir;
! 1605: u_char buffer[CL_FIFO_MAX +1];
! 1606: #ifdef DDB
! 1607: int wantddb = 0;
! 1608: #endif
! 1609:
! 1610: rir = sc->cl_reg->cl_rir;
! 1611: if((rir & 0x40) == 0x0) {
! 1612: /* only if intr is not shared ??? */
! 1613: log(LOG_WARNING, "cl_rxintr extra intr\n");
! 1614: return 0;
! 1615: }
! 1616:
! 1617: channel = rir & 0x3;
! 1618: cmr = sc->cl_reg->cl_cmr;
! 1619: reoir = 0x08;
! 1620:
! 1621: sc->sc_cl[channel].rxcnt ++;
! 1622: risrl = sc->cl_reg->cl_risrl;
! 1623: if (risrl & 0x80) {
! 1624: /* timeout, no characters */
! 1625: reoir = 0x08;
! 1626: } else
! 1627: /* We don't need no sinkin special characters */
! 1628: if (risrl & 0x08) {
! 1629: cl_overflow (sc, channel, &sc->sc_fotime, "fifo");
! 1630: reoir = 0x08;
! 1631: } else
! 1632: if (risrl & 0x04) {
! 1633: cl_parity(sc, channel);
! 1634: reoir = 0x08;
! 1635: } else
! 1636: if (risrl & 0x02) {
! 1637: cl_frame(sc, channel);
! 1638: reoir = 0x08;
! 1639: } else
! 1640: if (risrl & 0x01) {
! 1641: #ifdef DDB
! 1642: if (sc->sc_cl[channel].cl_consio)
! 1643: wantddb = db_console;
! 1644: #endif
! 1645: cl_break(sc, channel);
! 1646: reoir = 0x08;
! 1647: }
! 1648:
! 1649: switch (cmr & CL_RXMASK) {
! 1650: case CL_RXDMAINT:
! 1651: {
! 1652: int nbuf;
! 1653: u_short cnt;
! 1654: int bufcomplete;
! 1655: u_char status, dmabsts;
! 1656: u_char risrh = sc->cl_reg->cl_risrh;
! 1657: dmabsts = sc->cl_reg->cl_dmabsts;
! 1658: #ifdef DMA_DEBUG
! 1659: log(LOG_WARNING, "cl_txintr: DMAMODE channel %x dmabsts %x risrl %x risrh %x\n",
! 1660: channel, dmabsts, risrl, risrh);
! 1661: #endif
! 1662: nbuf = (risrh & 0x08) ? 1 : 0;
! 1663: bufcomplete = (risrh & 0x20) ? 1 : 0;
! 1664: if (nbuf == 0) {
! 1665: cnt = sc->cl_reg->cl_arbcnt;
! 1666: status = sc->cl_reg->cl_arbsts;
! 1667: } else {
! 1668: cnt = sc->cl_reg->cl_brbcnt;
! 1669: status = sc->cl_reg->cl_brbsts;
! 1670: }
! 1671: #ifdef DMA_DEBUG
! 1672: log(LOG_WARNING, "cl_rxintr: 1channel %x buf %x cnt %x status %x\n",
! 1673: channel, nbuf, cnt, status);
! 1674: #endif
! 1675: #ifdef USE_BUFFER
! 1676: cl_appendbufn(sc, channel,
! 1677: sc->sc_cl[channel].rx[nbuf], cnt);
! 1678: #else
! 1679: {
! 1680: int i;
! 1681: u_char *pbuf;
! 1682: tp = sc->sc_cl[channel].tty;
! 1683: pbuf = sc->sc_cl[channel].rx[nbuf];
! 1684: /* this should be done at off level */
! 1685: {
! 1686: u_short rcbadru, rcbadrl;
! 1687: u_char arbsts, brbsts;
! 1688: u_char *pbufs, *pbufe;
! 1689: rcbadru = sc->cl_reg->cl_rcbadru;
! 1690: rcbadrl = sc->cl_reg->cl_rcbadrl;
! 1691: arbsts = sc->cl_reg->cl_arbsts;
! 1692: brbsts = sc->cl_reg->cl_brbsts;
! 1693: pbufs = sc->sc_cl[channel].rxp[nbuf];
! 1694: pbufe = (u_char *)(((u_long)rcbadru << 16) | (u_long)rcbadrl);
! 1695: cnt = pbufe - pbufs;
! 1696: #ifdef DMA_DEBUG
! 1697: log(LOG_WARNING, "cl_rxintr: rcbadru %x rcbadrl %x arbsts %x brbsts %x cnt %x\n",
! 1698: rcbadru, rcbadrl, arbsts, brbsts, cnt);
! 1699: #endif
! 1700: #ifdef DMA_DEBUG1
! 1701: log(LOG_WARNING, "cl_rxintr: buf %x cnt %x\n",
! 1702: nbuf, cnt);
! 1703: #endif
! 1704: }
! 1705: reoir = 0x0 | (bufcomplete) ? 0 : 0xd0;
! 1706: sc->cl_reg->cl_reoir = reoir;
! 1707: #ifdef DMA_DEBUG
! 1708: log(LOG_WARNING, "cl_rxintr: reoir %x\n", reoir);
! 1709: #endif
! 1710: delay(10); /* give the chip a moment */
! 1711: #ifdef DMA_DEBUG
! 1712: log(LOG_WARNING, "cl_rxintr: 2channel %x buf %x cnt %x status %x\n",
! 1713: channel, nbuf, cnt, status);
! 1714: #endif
! 1715: for (i = 0; i < cnt; i++) {
! 1716: u_char c;
! 1717: c = pbuf[i];
! 1718: (*linesw[tp->t_line].l_rint)(c,tp);
! 1719: }
! 1720: /* this should be done at off level */
! 1721: if (nbuf == 0) {
! 1722: sc->cl_reg->cl_arbcnt = CL_BUFSIZE;
! 1723: sc->cl_reg->cl_arbsts = 0x01;
! 1724: } else {
! 1725: sc->cl_reg->cl_brbcnt = CL_BUFSIZE;
! 1726: sc->cl_reg->cl_brbsts = 0x01;
! 1727: }
! 1728: }
! 1729: #endif
! 1730: }
! 1731: sc->cl_reg->cl_reoir = reoir;
! 1732: break;
! 1733: case CL_RXINTR:
! 1734: fifocnt = sc->cl_reg->cl_rfoc;
! 1735: tp = sc->sc_cl[channel].tty;
! 1736: for (i = 0; i < fifocnt; i++) {
! 1737: buffer[i] = sc->cl_reg->cl_rdr;
! 1738: }
! 1739: if (NULL == tp) {
! 1740: /* if the channel is not configured,
! 1741: * dont send characters upstream.
! 1742: * also fix problem with NULL dereference
! 1743: */
! 1744: reoir = 0x00;
! 1745: break;
! 1746: }
! 1747:
! 1748: sc->cl_reg->cl_reoir = reoir;
! 1749: #ifdef USE_BUFFER
! 1750: cl_appendbufn(sc, channel, buffer, fifocnt);
! 1751: #else
! 1752: for (i = 0; i < fifocnt; i++) {
! 1753: u_char c;
! 1754: c = buffer[i];
! 1755: /* does any restricitions exist on spl
! 1756: * for this call
! 1757: */
! 1758: (*linesw[tp->t_line].l_rint)(c,tp);
! 1759: reoir = 0x00;
! 1760: }
! 1761: #endif
! 1762: break;
! 1763: default:
! 1764: log(LOG_WARNING, "cl_rxintr unknown mode %x\n", cmr);
! 1765: /* we probably will go to hell quickly now */
! 1766: reoir = 0x08;
! 1767: sc->cl_reg->cl_reoir = reoir;
! 1768: }
! 1769: #ifdef DDB
! 1770: if (wantddb != 0)
! 1771: Debugger();
! 1772: #endif
! 1773: return 1;
! 1774: }
! 1775:
! 1776: void
! 1777: cl_overflow (sc, channel, ptime, msg)
! 1778: struct clsoftc *sc;
! 1779: int channel;
! 1780: time_t *ptime;
! 1781: u_char *msg;
! 1782: {
! 1783: /*
! 1784: if (*ptime != time.tv_sec) {
! 1785: */
! 1786: {
! 1787: /*
! 1788: *ptime = time.tv_sec;
! 1789: */
! 1790: log(LOG_WARNING, "%s%d[%d]: %s overrun\n", cl_cd.cd_name,
! 1791: 0 /* fix */, channel, msg);
! 1792: }
! 1793: return;
! 1794: }
! 1795: void
! 1796: cl_parity (sc, channel)
! 1797: struct clsoftc *sc;
! 1798: int channel;
! 1799: {
! 1800: #ifdef VERBOSE_LOG_MESSAGES
! 1801: log(LOG_WARNING, "%s%d[%d]: parity error\n", cl_cd.cd_name, 0, channel);
! 1802: #endif
! 1803: return;
! 1804: }
! 1805: void
! 1806: cl_frame (sc, channel)
! 1807: struct clsoftc *sc;
! 1808: int channel;
! 1809: {
! 1810: #ifdef VERBOSE_LOG_MESSAGES
! 1811: log(LOG_WARNING, "%s%d[%d]: frame error\n", cl_cd.cd_name, 0, channel);
! 1812: #endif
! 1813: return;
! 1814: }
! 1815: void
! 1816: cl_break (sc, channel)
! 1817: struct clsoftc *sc;
! 1818: int channel;
! 1819: {
! 1820: #ifdef VERBOSE_LOG_MESSAGES
! 1821: log(LOG_WARNING, "%s%d[%d]: break detected\n", cl_cd.cd_name, 0, channel);
! 1822: #endif
! 1823: return;
! 1824: }
! 1825:
! 1826: void
! 1827: cl_dumpport(channel)
! 1828: int channel;
! 1829: {
! 1830: u_char livr, cmr, cor1, cor2, cor3, cor4, cor5, cor6, cor7,
! 1831: schr1, schr2, schr3, schr4, scrl, scrh, lnxt,
! 1832: rbpr, rcor, tbpr, tcor, rpilr, rir, tpr, ier, ccr,
! 1833: dmabsts, arbsts, brbsts, atbsts, btbsts,
! 1834: csr, rts, dtr, rtprl, rtprh;
! 1835: volatile void * parbadru, *parbadrl, *parbsts, *parbcnt;
! 1836: u_short rcbadru, rcbadrl, arbadru, arbadrl, arbcnt,
! 1837: brbadru, brbadrl, brbcnt;
! 1838: u_short tcbadru, tcbadrl, atbadru, atbadrl, atbcnt,
! 1839: btbadru, btbadrl, btbcnt;
! 1840: struct clsoftc *sc;
! 1841:
! 1842: struct clreg *cl_reg;
! 1843: int s;
! 1844:
! 1845: cl_reg = cl_cons.cl_vaddr;
! 1846:
! 1847: sc = (struct clsoftc *) cl_cd.cd_devs[0];
! 1848:
! 1849: s = splcl();
! 1850: cl_reg->cl_car = (u_char) channel;
! 1851: livr = cl_reg->cl_livr;
! 1852: cmr = cl_reg->cl_cmr;
! 1853: cor1 = cl_reg->cl_cor1;
! 1854: cor2 = cl_reg->cl_cor2;
! 1855: cor3 = cl_reg->cl_cor3;
! 1856: cor4 = cl_reg->cl_cor4;
! 1857: cor5 = cl_reg->cl_cor5;
! 1858: cor6 = cl_reg->cl_cor6;
! 1859: cor7 = cl_reg->cl_cor7;
! 1860: schr1 = cl_reg->cl_schr1;
! 1861: schr2 = cl_reg->cl_schr2;
! 1862: schr3 = cl_reg->cl_schr3;
! 1863: schr4 = cl_reg->cl_schr4;
! 1864: scrl = cl_reg->cl_scrl;
! 1865: scrh = cl_reg->cl_scrh;
! 1866: lnxt = cl_reg->cl_lnxt;
! 1867: rbpr = cl_reg->cl_rbpr;
! 1868: rcor = cl_reg->cl_rcor;
! 1869: tbpr = cl_reg->cl_tbpr;
! 1870: rpilr = cl_reg->cl_rpilr;
! 1871: rir = cl_reg->cl_rir;
! 1872: ier = cl_reg->cl_ier;
! 1873: ccr = cl_reg->cl_ccr;
! 1874: tcor = cl_reg->cl_tcor;
! 1875: csr = cl_reg->cl_csr;
! 1876: tpr = cl_reg->cl_tpr;
! 1877: rts = cl_reg->cl_msvr_rts;
! 1878: dtr = cl_reg->cl_msvr_dtr;
! 1879: rtprl = cl_reg->cl_rtprl;
! 1880: rtprh = cl_reg->cl_rtprh;
! 1881: dmabsts = cl_reg->cl_dmabsts;
! 1882: tcbadru = cl_reg->cl_tcbadru;
! 1883: tcbadrl = cl_reg->cl_tcbadrl;
! 1884: rcbadru = cl_reg->cl_rcbadru;
! 1885: rcbadrl = cl_reg->cl_rcbadrl;
! 1886:
! 1887: parbadru = &(cl_reg->cl_arbadru);
! 1888: parbadrl = &(cl_reg->cl_arbadrl);
! 1889: parbcnt = &(cl_reg->cl_arbcnt);
! 1890: parbsts = &(cl_reg->cl_arbsts);
! 1891:
! 1892: arbadru = cl_reg->cl_arbadru;
! 1893: arbadrl = cl_reg->cl_arbadrl;
! 1894: arbcnt = cl_reg->cl_arbcnt;
! 1895: arbsts = cl_reg->cl_arbsts;
! 1896:
! 1897: brbadru = cl_reg->cl_brbadru;
! 1898: brbadrl = cl_reg->cl_brbadrl;
! 1899: brbcnt = cl_reg->cl_brbcnt;
! 1900: brbsts = cl_reg->cl_brbsts;
! 1901:
! 1902: atbadru = cl_reg->cl_atbadru;
! 1903: atbadrl = cl_reg->cl_atbadrl;
! 1904: atbcnt = cl_reg->cl_atbcnt;
! 1905: atbsts = cl_reg->cl_atbsts;
! 1906:
! 1907: btbadru = cl_reg->cl_btbadru;
! 1908: btbadrl = cl_reg->cl_btbadrl;
! 1909: btbcnt = cl_reg->cl_btbcnt;
! 1910: btbsts = cl_reg->cl_btbsts;
! 1911:
! 1912: splx(s);
! 1913:
! 1914: printf("{ port %x livr %x cmr %x\n",
! 1915: channel,livr, cmr);
! 1916: printf("cor1 %x cor2 %x cor3 %x cor4 %x cor5 %x cor6 %x cor7 %x\n",
! 1917: cor1, cor2, cor3, cor4, cor5, cor6, cor7);
! 1918: printf("schr1 %x schr2 %x schr3 %x schr4 %x\n",
! 1919: schr1, schr2, schr3, schr4);
! 1920: printf("scrl %x scrh %x lnxt %x\n",
! 1921: scrl, scrh, lnxt);
! 1922: printf("rbpr %x rcor %x tbpr %x tcor %x\n",
! 1923: rbpr, rcor, tbpr, tcor);
! 1924: printf("rpilr %x rir %x ier %x ccr %x\n",
! 1925: rpilr, rir, ier, ccr);
! 1926: printf("tpr %x csr %x rts %x dtr %x\n",
! 1927: tpr, csr, rts, dtr);
! 1928: printf("rtprl %x rtprh %x\n",
! 1929: rtprl, rtprh);
! 1930: printf("rxcnt %lx txcnt %lx\n",
! 1931: sc->sc_cl[channel].rxcnt, sc->sc_cl[channel].txcnt);
! 1932: printf("dmabsts %x, tcbadru %x, tcbadrl %x, rcbadru %x, rcbadrl %x,\n",
! 1933: dmabsts, tcbadru, tcbadrl, rcbadru, rcbadrl );
! 1934: printf("parbadru %p, parbadrl %p, parbcnt %p, parbsts %p\n",
! 1935: parbadru, parbadrl, parbcnt, parbsts);
! 1936: printf("arbadru %x, arbadrl %x, arbcnt %x, arbsts %x\n",
! 1937: arbadru, arbadrl, arbcnt, arbsts);
! 1938: printf("brbadru %x, brbadrl %x, brbcnt %x, brbsts %x\n",
! 1939: brbadru, brbadrl, brbcnt, brbsts);
! 1940: printf("atbadru %x, atbadrl %x, atbcnt %x, atbsts %x\n",
! 1941: atbadru, atbadrl, atbcnt, atbsts);
! 1942: printf("btbadru %x, btbadrl %x, btbcnt %x, btbsts %x\n",
! 1943: btbadru, btbadrl, btbcnt, btbsts);
! 1944: printf("}\n");
! 1945: return;
! 1946: }
! 1947: #ifdef USE_BUFFER
! 1948: void
! 1949: cl_appendbuf(sc, channel, c)
! 1950: struct clsoftc *sc;
! 1951: u_char channel;
! 1952: u_char c;
! 1953: {
! 1954: /* int s; */
! 1955: /* s = splcl(); */
! 1956: if (1 + sc->sc_cl[channel].nchar >= CL_BUFSIZE ) {
! 1957: cl_overflow (sc, channel, &sc->sc_fotime, "rbuf");
! 1958: /* just toss the character */
! 1959: return;
! 1960: }
! 1961: *(sc->sc_cl[channel].psupply++) = c;
! 1962: if (&(sc->sc_cl[channel].buffer[CL_BUFSIZE])
! 1963: == sc->sc_cl[channel].psupply) {
! 1964: sc->sc_cl[channel].psupply = sc->sc_cl[channel].buffer;
! 1965: }
! 1966: sc->sc_cl[channel].nchar ++;
! 1967: setsoftint(sc->ssir);
! 1968: /* splx (s); */
! 1969:
! 1970: }
! 1971: void
! 1972: cl_appendbufn(sc, channel, buf, cnt)
! 1973: struct clsoftc *sc;
! 1974: u_char channel;
! 1975: u_char *buf;
! 1976: u_short cnt;
! 1977: {
! 1978: /* int s; */
! 1979: int i;
! 1980: /* s = splcl(); */ /* should be called at splcl(). */
! 1981: if (cnt + sc->sc_cl[channel].nchar >= CL_BUFSIZE ) {
! 1982: cl_overflow (sc, channel, &sc->sc_fotime, "rbuf");
! 1983: /* just toss the character(s)
! 1984: * It could be argued that not all of the charactes
! 1985: * should be tossed, just the ones that actually
! 1986: * overflow the buffer. eh, O well.
! 1987: */
! 1988: return;
! 1989: }
! 1990: for (i = 0; i < cnt; i++) {
! 1991: *(sc->sc_cl[channel].psupply++) = buf[i];
! 1992: if (&(sc->sc_cl[channel].buffer[CL_BUFSIZE]) == sc->sc_cl[channel].psupply)
! 1993: {
! 1994: sc->sc_cl[channel].psupply = sc->sc_cl[channel].buffer;
! 1995: }
! 1996: sc->sc_cl[channel].nchar ++;
! 1997: }
! 1998: setsoftint(sc->ssir);
! 1999: /* splx (s); */
! 2000: }
! 2001:
! 2002: void
! 2003: cl_softint(arg)
! 2004: void *arg;
! 2005: {
! 2006: struct clsoftc *sc = (struct clsoftc *)arg;
! 2007: int i;
! 2008: int s;
! 2009: u_char c;
! 2010: struct tty *tp;
! 2011:
! 2012: for (i = 0 ; i < CLCD_PORTS_PER_CHIP; i ++) {
! 2013: /* printf("channel %x sc %x\n", i, sc); */
! 2014: tp = sc->sc_cl[i].tty;
! 2015: /* printf("channel %x pconsum %x\n", i, sc->sc_cl[i].pconsum); */
! 2016: while (sc->sc_cl[i].nchar > 0) {
! 2017: s = splcl();
! 2018: c = *(sc->sc_cl[i].pconsum++);
! 2019: if (&(sc->sc_cl[i].buffer[CL_BUFSIZE]) == sc->sc_cl[i].pconsum)
! 2020: {
! 2021: sc->sc_cl[i].pconsum = sc->sc_cl[i].buffer;
! 2022: }
! 2023: sc->sc_cl[i].nchar--;
! 2024: splx(s);
! 2025: (*linesw[tp->t_line].l_rint)(c,tp);
! 2026: }
! 2027: }
! 2028: }
! 2029: #endif
CVSweb