123326Smckusick /* 229219Smckusick * Copyright (c) 1982, 1986 Regents of the University of California. 323326Smckusick * All rights reserved. The Berkeley software License Agreement 423326Smckusick * specifies the terms and conditions for redistribution. 523326Smckusick * 6*39061Smarc * @(#)dz.c 7.4 (Berkeley) 09/06/89 723326Smckusick */ 817Sbill 91935Swnj #include "dz.h" 102645Swnj #if NDZ > 0 1117Sbill /* 1210019Ssam * DZ-11/DZ-32 Driver 132469Swnj * 142469Swnj * This driver mimics dh.c; see it for explanation of common code. 1517Sbill */ 1617123Sbloom #include "param.h" 1717123Sbloom #include "systm.h" 1817123Sbloom #include "ioctl.h" 1917123Sbloom #include "tty.h" 2017123Sbloom #include "dir.h" 2117123Sbloom #include "user.h" 2217123Sbloom #include "proc.h" 2317123Sbloom #include "map.h" 2417123Sbloom #include "buf.h" 2517123Sbloom #include "vm.h" 2617123Sbloom #include "conf.h" 2717123Sbloom #include "bkmac.h" 2817123Sbloom #include "file.h" 2917123Sbloom #include "uio.h" 3017123Sbloom #include "kernel.h" 3118313Sralph #include "syslog.h" 32145Sbill 3317123Sbloom #include "pdma.h" 3417123Sbloom #include "ubavar.h" 3517123Sbloom #include "dzreg.h" 36*39061Smarc #include "machine/pte.h" 378474Sroot 382469Swnj /* 392469Swnj * Driver information for auto-configuration stuff. 402469Swnj */ 412606Swnj int dzprobe(), dzattach(), dzrint(); 422976Swnj struct uba_device *dzinfo[NDZ]; 432395Swnj u_short dzstd[] = { 0 }; 442395Swnj struct uba_driver dzdriver = 452606Swnj { dzprobe, 0, dzattach, 0, dzstd, "dz", dzinfo }; 462395Swnj 472645Swnj #define NDZLINE (NDZ*8) 4816191Skarels #define FASTTIMER (hz/30) /* rate to drain silos, when in use */ 492469Swnj 502469Swnj int dzstart(), dzxint(), dzdma(); 51114Sbill int ttrstrt(); 522645Swnj struct tty dz_tty[NDZLINE]; 532645Swnj int dz_cnt = { NDZLINE }; 54119Sbill int dzact; 5516191Skarels int dzsilos; /* mask of dz's with silo in use */ 5616191Skarels int dzchars[NDZ]; /* recent input count */ 5716191Skarels int dzrate[NDZ]; /* smoothed input count */ 5816191Skarels int dztimerintvl; /* time interval for dztimer */ 5916191Skarels int dzhighrate = 100; /* silo on if dzchars > dzhighrate */ 6016191Skarels int dzlowrate = 75; /* silo off if dzrate < dzlowrate */ 6117Sbill 625731Sroot #define dzwait(x) while (((x)->dzlcs & DZ_ACK) == 0) 635731Sroot 642469Swnj /* 652469Swnj * Software copy of dzbrk since it isn't readable 662469Swnj */ 672645Swnj char dz_brk[NDZ]; 682645Swnj char dzsoftCAR[NDZ]; 695731Sroot char dz_lnen[NDZ]; /* saved line enable bits for DZ32 */ 7017Sbill 712469Swnj /* 725731Sroot * The dz11 doesn't interrupt on carrier transitions, so 732469Swnj * we have to use a timer to watch it. 742469Swnj */ 752469Swnj char dz_timer; /* timer started? */ 762469Swnj 772469Swnj /* 782469Swnj * Pdma structures for fast output code 792469Swnj */ 802645Swnj struct pdma dzpdma[NDZLINE]; 812469Swnj 82*39061Smarc struct speedtab dzspeedtab[] = { 83*39061Smarc 0, 0, 84*39061Smarc 50, 020, 85*39061Smarc 75, 021, 86*39061Smarc 110, 022, 87*39061Smarc 134, 023, 88*39061Smarc 150, 024, 89*39061Smarc 300, 025, 90*39061Smarc 600, 026, 91*39061Smarc 1200, 027, 92*39061Smarc 1800, 030, 93*39061Smarc 2400, 032, 94*39061Smarc 4800, 034, 95*39061Smarc 9600, 036, 96*39061Smarc 19200, 037, 97*39061Smarc EXTA, 037, 98*39061Smarc -1, -1 99*39061Smarc }; 10017Sbill 10125397Skarels #ifndef PORTSELECTOR 102*39061Smarc #define ISPEED TTYDEF_SPEED 103*39061Smarc #define LFLAG TTYDEF_LFLAG 1046616Ssam #else 1056616Ssam #define ISPEED B4800 106*39061Smarc #define LFLAG (TTYDEF_LFLAG&~ECHO) 1076616Ssam #endif 1086616Ssam 1092606Swnj dzprobe(reg) 1102395Swnj caddr_t reg; 1112395Swnj { 1122457Swnj register int br, cvec; 11310019Ssam register struct dzdevice *dzaddr = (struct dzdevice *)reg; 1142395Swnj 1152606Swnj #ifdef lint 1163102Swnj br = 0; cvec = br; br = cvec; 1174933Swnj dzrint(0); dzxint((struct tty *)0); 1182606Swnj #endif 1195731Sroot dzaddr->dzcsr = DZ_TIE|DZ_MSE|DZ_32; 1205731Sroot if (dzaddr->dzcsr & DZ_32) 1215731Sroot dzaddr->dzlnen = 1; 1225731Sroot else 1235731Sroot dzaddr->dztcr = 1; /* enable any line */ 1242457Swnj DELAY(100000); 1255731Sroot dzaddr->dzcsr = DZ_CLR|DZ_32; /* reset everything */ 1262457Swnj if (cvec && cvec != 0x200) 1272457Swnj cvec -= 4; 12810019Ssam return (sizeof (struct dzdevice)); 1292395Swnj } 1302395Swnj 1312606Swnj dzattach(ui) 1322976Swnj register struct uba_device *ui; 1332395Swnj { 1342395Swnj register struct pdma *pdp = &dzpdma[ui->ui_unit*8]; 1352395Swnj register struct tty *tp = &dz_tty[ui->ui_unit*8]; 1362606Swnj register int cntr; 1372645Swnj extern dzscan(); 1382395Swnj 1392606Swnj for (cntr = 0; cntr < 8; cntr++) { 14010019Ssam pdp->p_addr = (struct dzdevice *)ui->ui_addr; 1412395Swnj pdp->p_arg = (int)tp; 1422395Swnj pdp->p_fcn = dzxint; 1432395Swnj pdp++, tp++; 1442395Swnj } 1452567Swnj dzsoftCAR[ui->ui_unit] = ui->ui_flags; 1462627Swnj if (dz_timer == 0) { 1472627Swnj dz_timer++; 1482756Swnj timeout(dzscan, (caddr_t)0, hz); 14916191Skarels dztimerintvl = FASTTIMER; 1502627Swnj } 1512395Swnj } 1522395Swnj 15317Sbill /*ARGSUSED*/ 1542395Swnj dzopen(dev, flag) 1552395Swnj dev_t dev; 15617Sbill { 15717Sbill register struct tty *tp; 1582395Swnj register int unit; 159*39061Smarc int dzparam(); 16017Sbill 1612395Swnj unit = minor(dev); 1628568Sroot if (unit >= dz_cnt || dzpdma[unit].p_addr == 0) 1638568Sroot return (ENXIO); 1642395Swnj tp = &dz_tty[unit]; 1652395Swnj tp->t_addr = (caddr_t)&dzpdma[unit]; 16617Sbill tp->t_oproc = dzstart; 167*39061Smarc tp->t_param = dzparam; 168*39061Smarc tp->t_dev = dev; 1695407Swnj if ((tp->t_state & TS_ISOPEN) == 0) { 17017Sbill ttychars(tp); 17127050Skarels #ifndef PORTSELECTOR 17227050Skarels if (tp->t_ispeed == 0) { 173*39061Smarc #endif 174*39061Smarc tp->t_iflag = TTYDEF_IFLAG; 175*39061Smarc tp->t_oflag = TTYDEF_OFLAG; 176*39061Smarc tp->t_cflag = TTYDEF_CFLAG; 177*39061Smarc tp->t_lflag = LFLAG; 178*39061Smarc tp->t_ispeed = tp->t_ospeed = ISPEED; 179*39061Smarc #ifdef PORTSELECTOR 180*39061Smarc tp->t_cflag |= HUPCL; 181*39061Smarc #else 18227050Skarels } 183*39061Smarc #endif 184*39061Smarc dzparam(tp, &tp->t_termios); 185*39061Smarc ttsetwater(tp); 1868568Sroot } else if (tp->t_state&TS_XCLUDE && u.u_uid != 0) 1878568Sroot return (EBUSY); 1886157Ssam (void) dzmctl(dev, DZ_ON, DMSET); 189114Sbill (void) spl5(); 190*39061Smarc while (!(flag&O_NONBLOCK) && !(tp->t_cflag&CLOCAL) && 191*39061Smarc (tp->t_state & TS_CARR_ON) == 0) { 1925407Swnj tp->t_state |= TS_WOPEN; 19317Sbill sleep((caddr_t)&tp->t_rawq, TTIPRI); 19417Sbill } 195114Sbill (void) spl0(); 1968568Sroot return ((*linesw[tp->t_line].l_open)(dev, tp)); 19717Sbill } 19817Sbill 1992395Swnj /*ARGSUSED*/ 2002395Swnj dzclose(dev, flag) 2012395Swnj dev_t dev; 20217Sbill { 20317Sbill register struct tty *tp; 2042395Swnj register int unit; 20510019Ssam register struct dzdevice *dzaddr; 2066150Ssam int dz; 20717Sbill 2082395Swnj unit = minor(dev); 2092395Swnj dz = unit >> 3; 2102395Swnj tp = &dz_tty[unit]; 21117Sbill (*linesw[tp->t_line].l_close)(tp); 2125731Sroot dzaddr = dzpdma[unit].p_addr; 2135731Sroot if (dzaddr->dzcsr&DZ_32) 2146157Ssam (void) dzmctl(dev, DZ_BRK, DMBIC); 2155731Sroot else 2165731Sroot dzaddr->dzbrk = (dz_brk[dz] &= ~(1 << (unit&07))); 217*39061Smarc if (tp->t_cflag&HUPCL || tp->t_state&TS_WOPEN || 218*39061Smarc (tp->t_state&TS_ISOPEN) == 0) 2196157Ssam (void) dzmctl(dev, DZ_OFF, DMSET); 22017Sbill ttyclose(tp); 22117Sbill } 22217Sbill 223*39061Smarc dzread(dev, uio, flag) 2242395Swnj dev_t dev; 2257727Sroot struct uio *uio; 22617Sbill { 22717Sbill register struct tty *tp; 22817Sbill 2292395Swnj tp = &dz_tty[minor(dev)]; 230*39061Smarc return ((*linesw[tp->t_line].l_read)(tp, uio, flag)); 23117Sbill } 23217Sbill 233*39061Smarc dzwrite(dev, uio, flag) 2342395Swnj dev_t dev; 2357833Sroot struct uio *uio; 23617Sbill { 23717Sbill register struct tty *tp; 23817Sbill 2392395Swnj tp = &dz_tty[minor(dev)]; 240*39061Smarc return ((*linesw[tp->t_line].l_write)(tp, uio, flag)); 24117Sbill } 24217Sbill 243119Sbill /*ARGSUSED*/ 2442395Swnj dzrint(dz) 2452395Swnj int dz; 24617Sbill { 24717Sbill register struct tty *tp; 248*39061Smarc register int c, cc; 24910019Ssam register struct dzdevice *dzaddr; 250119Sbill register struct tty *tp0; 2512395Swnj register int unit; 2522923Swnj int overrun = 0; 25317Sbill 2542457Swnj if ((dzact & (1<<dz)) == 0) 2552457Swnj return; 2562457Swnj unit = dz * 8; 2572457Swnj dzaddr = dzpdma[unit].p_addr; 2582457Swnj tp0 = &dz_tty[unit]; 2595731Sroot dzaddr->dzcsr &= ~(DZ_RIE|DZ_MIE); /* the manual says this song */ 2605731Sroot dzaddr->dzcsr |= DZ_RIE|DZ_MIE; /* and dance is necessary */ 2615731Sroot while (dzaddr->dzcsr & DZ_MSC) { /* DZ32 modem change interrupt */ 2625731Sroot c = dzaddr->dzmtsr; 2635731Sroot tp = tp0 + (c&7); 2645731Sroot if (tp >= &dz_tty[dz_cnt]) 2655731Sroot break; 2665731Sroot dzaddr->dzlcs = c&7; /* get status of modem lines */ 2675731Sroot dzwait(dzaddr); /* wait for them */ 2685731Sroot if (c & DZ_CD) /* carrier status change? */ 2695731Sroot if (dzaddr->dzlcs & DZ_CD) { /* carrier up? */ 27025397Skarels /* carrier present */ 27125397Skarels (void)(*linesw[tp->t_line].l_modem)(tp, 1); 27225397Skarels } else if ((*linesw[tp->t_line].l_modem)(tp, 0) == 0) 27325397Skarels dzaddr->dzlcs = DZ_ACK|(c&7); 2745731Sroot } 2752457Swnj while ((c = dzaddr->dzrbuf) < 0) { /* char present */ 276*39061Smarc cc = c&0xff; 27716191Skarels dzchars[dz]++; 2782457Swnj tp = tp0 + ((c>>8)&07); 2792457Swnj if (tp >= &dz_tty[dz_cnt]) 28017Sbill continue; 2815407Swnj if ((tp->t_state & TS_ISOPEN) == 0) { 2822457Swnj wakeup((caddr_t)&tp->t_rawq); 2836616Ssam #ifdef PORTSELECTOR 2846616Ssam if ((tp->t_state&TS_WOPEN) == 0) 2856616Ssam #endif 28625397Skarels continue; 2872457Swnj } 2882469Swnj if (c&DZ_FE) 289*39061Smarc cc |= TTY_FE; 2902923Swnj if (c&DZ_DO && overrun == 0) { 29124843Seric log(LOG_WARNING, "dz%d,%d: silo overflow\n", dz, (c>>8)&7); 2922923Swnj overrun = 1; 2932923Swnj } 2942469Swnj if (c&DZ_PE) 295*39061Smarc cc |= TTY_PE; 296*39061Smarc (*linesw[tp->t_line].l_rint)(cc, tp); 29717Sbill } 29817Sbill } 29917Sbill 30017Sbill /*ARGSUSED*/ 3017631Ssam dzioctl(dev, cmd, data, flag) 3022395Swnj dev_t dev; 3037631Ssam caddr_t data; 30417Sbill { 30517Sbill register struct tty *tp; 3062395Swnj register int unit = minor(dev); 3072395Swnj register int dz = unit >> 3; 30810019Ssam register struct dzdevice *dzaddr; 3098568Sroot int error; 31017Sbill 3112395Swnj tp = &dz_tty[unit]; 3128568Sroot error = (*linesw[tp->t_line].l_ioctl)(tp, cmd, data, flag); 3138568Sroot if (error >= 0) 3148568Sroot return (error); 3158568Sroot error = ttioctl(tp, cmd, data, flag); 316*39061Smarc if (error >= 0) 3178568Sroot return (error); 318*39061Smarc 3198568Sroot switch (cmd) { 3202395Swnj 321170Sbill case TIOCSBRK: 3225731Sroot dzaddr = ((struct pdma *)(tp->t_addr))->p_addr; 3235731Sroot if (dzaddr->dzcsr&DZ_32) 3246157Ssam (void) dzmctl(dev, DZ_BRK, DMBIS); 3255731Sroot else 3265731Sroot dzaddr->dzbrk = (dz_brk[dz] |= 1 << (unit&07)); 327170Sbill break; 3287631Ssam 329170Sbill case TIOCCBRK: 3305731Sroot dzaddr = ((struct pdma *)(tp->t_addr))->p_addr; 3315731Sroot if (dzaddr->dzcsr&DZ_32) 3326157Ssam (void) dzmctl(dev, DZ_BRK, DMBIC); 3335731Sroot else 3345731Sroot dzaddr->dzbrk = (dz_brk[dz] &= ~(1 << (unit&07))); 335170Sbill break; 3367631Ssam 337170Sbill case TIOCSDTR: 3386157Ssam (void) dzmctl(dev, DZ_DTR|DZ_RTS, DMBIS); 339170Sbill break; 3407631Ssam 341170Sbill case TIOCCDTR: 3426157Ssam (void) dzmctl(dev, DZ_DTR|DZ_RTS, DMBIC); 343170Sbill break; 3447631Ssam 3455731Sroot case TIOCMSET: 3467631Ssam (void) dzmctl(dev, dmtodz(*(int *)data), DMSET); 3475731Sroot break; 3487631Ssam 3495731Sroot case TIOCMBIS: 3507631Ssam (void) dzmctl(dev, dmtodz(*(int *)data), DMBIS); 3515731Sroot break; 3527631Ssam 3535731Sroot case TIOCMBIC: 3547631Ssam (void) dzmctl(dev, dmtodz(*(int *)data), DMBIC); 3555731Sroot break; 3567631Ssam 3575731Sroot case TIOCMGET: 3587631Ssam *(int *)data = dztodm(dzmctl(dev, 0, DMGET)); 3595731Sroot break; 3607631Ssam 361170Sbill default: 3628568Sroot return (ENOTTY); 363170Sbill } 3648568Sroot return (0); 36517Sbill } 3665731Sroot 3675731Sroot dmtodz(bits) 3685731Sroot register int bits; 3695731Sroot { 3705731Sroot register int b; 3715731Sroot 3725731Sroot b = (bits >>1) & 0370; 3735731Sroot if (bits & DML_ST) b |= DZ_ST; 3745731Sroot if (bits & DML_RTS) b |= DZ_RTS; 3755731Sroot if (bits & DML_DTR) b |= DZ_DTR; 3765731Sroot if (bits & DML_LE) b |= DZ_LE; 3775731Sroot return(b); 3785731Sroot } 3795731Sroot 3805731Sroot dztodm(bits) 3815731Sroot register int bits; 3825731Sroot { 3835731Sroot register int b; 3845731Sroot 3855731Sroot b = (bits << 1) & 0360; 3865731Sroot if (bits & DZ_DSR) b |= DML_DSR; 3875731Sroot if (bits & DZ_DTR) b |= DML_DTR; 3885731Sroot if (bits & DZ_ST) b |= DML_ST; 3895731Sroot if (bits & DZ_RTS) b |= DML_RTS; 3905731Sroot return(b); 3915731Sroot } 39217Sbill 393*39061Smarc dzparam(tp, t) 394*39061Smarc register struct tty *tp; 395*39061Smarc register struct termios *t; 39617Sbill { 39710019Ssam register struct dzdevice *dzaddr; 3982395Swnj register int lpr; 399*39061Smarc register int cflag = t->c_cflag; 400*39061Smarc int unit = minor(tp->t_dev); 401*39061Smarc int ospeed = ttspeedtab(t->c_ospeed, dzspeedtab); 402*39061Smarc 403*39061Smarc /* check requested parameters */ 404*39061Smarc if (ospeed < 0 || (t->c_ispeed && t->c_ispeed != t->c_ospeed) || 405*39061Smarc (cflag&CSIZE) == CS5 || (cflag&CSIZE) == CS6) 406*39061Smarc return(EINVAL); 407*39061Smarc /* and copy to tty */ 408*39061Smarc tp->t_ispeed = t->c_ispeed; 409*39061Smarc tp->t_ospeed = t->c_ospeed; 410*39061Smarc tp->t_cflag = cflag; 411*39061Smarc 4122395Swnj dzaddr = dzpdma[unit].p_addr; 41316191Skarels if (dzsilos & (1 << (unit >> 3))) 41416191Skarels dzaddr->dzcsr = DZ_IEN | DZ_SAE; 41516191Skarels else 41616191Skarels dzaddr->dzcsr = DZ_IEN; 4172395Swnj dzact |= (1<<(unit>>3)); 418*39061Smarc if (ospeed == 0) { 4196157Ssam (void) dzmctl(unit, DZ_OFF, DMSET); /* hang up line */ 42017Sbill return; 42117Sbill } 422*39061Smarc lpr = (ospeed<<8) | (unit & 07); 423*39061Smarc if ((cflag&CSIZE) == CS7) 424*39061Smarc lpr |= BITS7; 425*39061Smarc else 42617Sbill lpr |= BITS8; 427*39061Smarc if (cflag&PARENB) 428*39061Smarc lpr |= PENABLE; 429*39061Smarc if (cflag&PARODD) 43017Sbill lpr |= OPAR; 431*39061Smarc if (cflag&CSTOPB) 4322469Swnj lpr |= TWOSB; 43317Sbill dzaddr->dzlpr = lpr; 434*39061Smarc return 0; 43517Sbill } 43617Sbill 43717Sbill dzxint(tp) 4382395Swnj register struct tty *tp; 43917Sbill { 44017Sbill register struct pdma *dp; 44116191Skarels register dz, unit; 44217Sbill 4432395Swnj dp = (struct pdma *)tp->t_addr; 4445407Swnj tp->t_state &= ~TS_BUSY; 4455407Swnj if (tp->t_state & TS_FLUSH) 4465407Swnj tp->t_state &= ~TS_FLUSH; 4475731Sroot else { 448281Sbill ndflush(&tp->t_outq, dp->p_mem-tp->t_outq.c_cf); 4495731Sroot dp->p_end = dp->p_mem = tp->t_outq.c_cf; 4505731Sroot } 45117Sbill if (tp->t_line) 45217Sbill (*linesw[tp->t_line].l_start)(tp); 45317Sbill else 45417Sbill dzstart(tp); 4555731Sroot dz = minor(tp->t_dev) >> 3; 4565731Sroot unit = minor(tp->t_dev) & 7; 4575407Swnj if (tp->t_outq.c_cc == 0 || (tp->t_state&TS_BUSY)==0) 4585731Sroot if (dp->p_addr->dzcsr & DZ_32) 4595731Sroot dp->p_addr->dzlnen = (dz_lnen[dz] &= ~(1<<unit)); 4605731Sroot else 4615731Sroot dp->p_addr->dztcr &= ~(1<<unit); 46217Sbill } 46317Sbill 46417Sbill dzstart(tp) 4652395Swnj register struct tty *tp; 46617Sbill { 46717Sbill register struct pdma *dp; 46810019Ssam register struct dzdevice *dzaddr; 4692395Swnj register int cc; 4705731Sroot int s, dz, unit; 47117Sbill 4722395Swnj dp = (struct pdma *)tp->t_addr; 47317Sbill dzaddr = dp->p_addr; 4742395Swnj s = spl5(); 4755407Swnj if (tp->t_state & (TS_TIMEOUT|TS_BUSY|TS_TTSTOP)) 47617Sbill goto out; 477*39061Smarc if (tp->t_outq.c_cc <= tp->t_lowat) { 4785407Swnj if (tp->t_state&TS_ASLEEP) { 4795407Swnj tp->t_state &= ~TS_ASLEEP; 4805407Swnj wakeup((caddr_t)&tp->t_outq); 4815407Swnj } 4825407Swnj if (tp->t_wsel) { 4835407Swnj selwakeup(tp->t_wsel, tp->t_state & TS_WCOLL); 4845407Swnj tp->t_wsel = 0; 4855407Swnj tp->t_state &= ~TS_WCOLL; 4865407Swnj } 48717Sbill } 48817Sbill if (tp->t_outq.c_cc == 0) 48917Sbill goto out; 4909551Ssam if (tp->t_flags & (RAW|LITOUT)) 49117Sbill cc = ndqb(&tp->t_outq, 0); 49217Sbill else { 49317Sbill cc = ndqb(&tp->t_outq, 0200); 49417Sbill if (cc == 0) { 49517Sbill cc = getc(&tp->t_outq); 4962469Swnj timeout(ttrstrt, (caddr_t)tp, (cc&0x7f) + 6); 4975407Swnj tp->t_state |= TS_TIMEOUT; 49817Sbill goto out; 49917Sbill } 50017Sbill } 5015407Swnj tp->t_state |= TS_BUSY; 50217Sbill dp->p_end = dp->p_mem = tp->t_outq.c_cf; 50317Sbill dp->p_end += cc; 5045731Sroot dz = minor(tp->t_dev) >> 3; 5055731Sroot unit = minor(tp->t_dev) & 7; 5065731Sroot if (dzaddr->dzcsr & DZ_32) 5075731Sroot dzaddr->dzlnen = (dz_lnen[dz] |= (1<<unit)); 5085731Sroot else 5095731Sroot dzaddr->dztcr |= (1<<unit); 5102395Swnj out: 5112395Swnj splx(s); 51217Sbill } 51317Sbill 51417Sbill /* 51517Sbill * Stop output on a line. 51617Sbill */ 51717Sbill /*ARGSUSED*/ 51817Sbill dzstop(tp, flag) 5192395Swnj register struct tty *tp; 52017Sbill { 52117Sbill register struct pdma *dp; 52217Sbill register int s; 52317Sbill 5242395Swnj dp = (struct pdma *)tp->t_addr; 5252457Swnj s = spl5(); 5265407Swnj if (tp->t_state & TS_BUSY) { 52717Sbill dp->p_end = dp->p_mem; 5285407Swnj if ((tp->t_state&TS_TTSTOP)==0) 5295407Swnj tp->t_state |= TS_FLUSH; 53017Sbill } 53117Sbill splx(s); 53217Sbill } 53317Sbill 5345731Sroot dzmctl(dev, bits, how) 5355731Sroot dev_t dev; 5365731Sroot int bits, how; 53717Sbill { 53810019Ssam register struct dzdevice *dzaddr; 5395731Sroot register int unit, mbits; 5405731Sroot int b, s; 5415731Sroot 5425731Sroot unit = minor(dev); 5435731Sroot b = 1<<(unit&7); 5442395Swnj dzaddr = dzpdma[unit].p_addr; 5455731Sroot s = spl5(); 5465731Sroot if (dzaddr->dzcsr & DZ_32) { 5475731Sroot dzwait(dzaddr) 5485731Sroot DELAY(100); /* IS 100 TOO MUCH? */ 5495731Sroot dzaddr->dzlcs = unit&7; 5505731Sroot DELAY(100); 5515731Sroot dzwait(dzaddr) 5525731Sroot DELAY(100); 5535731Sroot mbits = dzaddr->dzlcs; 5545731Sroot mbits &= 0177770; 5555731Sroot } else { 5565731Sroot mbits = (dzaddr->dzdtr & b) ? DZ_DTR : 0; 5575731Sroot mbits |= (dzaddr->dzmsr & b) ? DZ_CD : 0; 5585731Sroot mbits |= (dzaddr->dztbuf & b) ? DZ_RI : 0; 5595731Sroot } 5605731Sroot switch (how) { 5615731Sroot case DMSET: 5625731Sroot mbits = bits; 5635731Sroot break; 5645731Sroot 5655731Sroot case DMBIS: 5665731Sroot mbits |= bits; 5675731Sroot break; 5685731Sroot 5695731Sroot case DMBIC: 5705731Sroot mbits &= ~bits; 5715731Sroot break; 5725731Sroot 5735731Sroot case DMGET: 5745731Sroot (void) splx(s); 5755731Sroot return(mbits); 5765731Sroot } 5775731Sroot if (dzaddr->dzcsr & DZ_32) { 5785731Sroot mbits |= DZ_ACK|(unit&7); 5795731Sroot dzaddr->dzlcs = mbits; 5805731Sroot } else { 5815731Sroot if (mbits & DZ_DTR) 5825731Sroot dzaddr->dzdtr |= b; 5835731Sroot else 5845731Sroot dzaddr->dzdtr &= ~b; 5855731Sroot } 58630387Skarels if (mbits & DZ_DTR && dzsoftCAR[unit >> 3] & b) 58730387Skarels dz_tty[unit].t_state |= TS_CARR_ON; 5885731Sroot (void) splx(s); 5895731Sroot return(mbits); 59017Sbill } 59117Sbill 59216191Skarels int dztransitions, dzfasttimers; /*DEBUG*/ 59317Sbill dzscan() 59417Sbill { 59517Sbill register i; 59610019Ssam register struct dzdevice *dzaddr; 59717Sbill register bit; 59817Sbill register struct tty *tp; 5995731Sroot register car; 60016191Skarels int olddzsilos = dzsilos; 60116191Skarels int dztimer(); 60217Sbill 60317Sbill for (i = 0; i < dz_cnt ; i++) { 60417Sbill dzaddr = dzpdma[i].p_addr; 6052627Swnj if (dzaddr == 0) 6062627Swnj continue; 60717Sbill tp = &dz_tty[i]; 60817Sbill bit = 1<<(i&07); 6095731Sroot car = 0; 6105731Sroot if (dzsoftCAR[i>>3]&bit) 6115731Sroot car = 1; 6125731Sroot else if (dzaddr->dzcsr & DZ_32) { 6135731Sroot dzaddr->dzlcs = i&07; 6145731Sroot dzwait(dzaddr); 6155731Sroot car = dzaddr->dzlcs & DZ_CD; 6165731Sroot } else 6175731Sroot car = dzaddr->dzmsr&bit; 6185731Sroot if (car) { 61917Sbill /* carrier present */ 62025397Skarels if ((tp->t_state & TS_CARR_ON) == 0) 62125397Skarels (void)(*linesw[tp->t_line].l_modem)(tp, 1); 62225397Skarels } else if ((tp->t_state&TS_CARR_ON) && 62325397Skarels (*linesw[tp->t_line].l_modem)(tp, 0) == 0) 62425397Skarels dzaddr->dzdtr &= ~bit; 62517Sbill } 62616191Skarels for (i = 0; i < NDZ; i++) { 62716191Skarels ave(dzrate[i], dzchars[i], 8); 62816191Skarels if (dzchars[i] > dzhighrate && ((dzsilos & (1 << i)) == 0)) { 62916397Ssam dzpdma[i << 3].p_addr->dzcsr = DZ_IEN | DZ_SAE; 63016191Skarels dzsilos |= (1 << i); 63116191Skarels dztransitions++; /*DEBUG*/ 63216191Skarels } else if ((dzsilos & (1 << i)) && (dzrate[i] < dzlowrate)) { 63316397Ssam dzpdma[i << 3].p_addr->dzcsr = DZ_IEN; 63416191Skarels dzsilos &= ~(1 << i); 63516191Skarels } 63616191Skarels dzchars[i] = 0; 63716191Skarels } 63816191Skarels if (dzsilos && !olddzsilos) 63916191Skarels timeout(dztimer, (caddr_t)0, dztimerintvl); 64016191Skarels timeout(dzscan, (caddr_t)0, hz); 64117Sbill } 642119Sbill 643119Sbill dztimer() 644119Sbill { 6458160Sroot register int dz; 64616191Skarels register int s; 647119Sbill 64816191Skarels if (dzsilos == 0) 64916191Skarels return; 65016191Skarels s = spl5(); 65116191Skarels dzfasttimers++; /*DEBUG*/ 6522645Swnj for (dz = 0; dz < NDZ; dz++) 65316191Skarels if (dzsilos & (1 << dz)) 65416191Skarels dzrint(dz); 6558160Sroot splx(s); 65616191Skarels timeout(dztimer, (caddr_t) 0, dztimerintvl); 657119Sbill } 658281Sbill 659281Sbill /* 660281Sbill * Reset state of driver if UBA reset was necessary. 661301Sbill * Reset parameters and restart transmission on open lines. 662281Sbill */ 6632395Swnj dzreset(uban) 6642422Skre int uban; 665281Sbill { 6662395Swnj register int unit; 667281Sbill register struct tty *tp; 6682976Swnj register struct uba_device *ui; 669281Sbill 6702645Swnj for (unit = 0; unit < NDZLINE; unit++) { 6712422Skre ui = dzinfo[unit >> 3]; 6722422Skre if (ui == 0 || ui->ui_ubanum != uban || ui->ui_alive == 0) 6732422Skre continue; 6742923Swnj if (unit%8 == 0) 6752923Swnj printf(" dz%d", unit>>3); 6762395Swnj tp = &dz_tty[unit]; 6775407Swnj if (tp->t_state & (TS_ISOPEN|TS_WOPEN)) { 6782395Swnj dzparam(unit); 6796157Ssam (void) dzmctl(unit, DZ_ON, DMSET); 6805407Swnj tp->t_state &= ~TS_BUSY; 681301Sbill dzstart(tp); 682281Sbill } 683281Sbill } 684281Sbill } 6851562Sbill #endif 686