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*45804Sbostic * @(#)dz.c 7.10 (Berkeley) 12/16/90 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 */ 16*45804Sbostic #include "sys/param.h" 17*45804Sbostic #include "sys/systm.h" 18*45804Sbostic #include "sys/ioctl.h" 19*45804Sbostic #include "sys/tty.h" 20*45804Sbostic #include "sys/user.h" 21*45804Sbostic #include "sys/proc.h" 22*45804Sbostic #include "sys/map.h" 23*45804Sbostic #include "sys/buf.h" 24*45804Sbostic #include "sys/vm.h" 25*45804Sbostic #include "sys/conf.h" 26*45804Sbostic #include "sys/bkmac.h" 27*45804Sbostic #include "sys/file.h" 28*45804Sbostic #include "sys/uio.h" 29*45804Sbostic #include "sys/kernel.h" 30*45804Sbostic #include "sys/syslog.h" 31145Sbill 3217123Sbloom #include "pdma.h" 3317123Sbloom #include "ubavar.h" 3417123Sbloom #include "dzreg.h" 35*45804Sbostic #include "../include/pte.h" 368474Sroot 372469Swnj /* 382469Swnj * Driver information for auto-configuration stuff. 392469Swnj */ 402606Swnj int dzprobe(), dzattach(), dzrint(); 412976Swnj struct uba_device *dzinfo[NDZ]; 422395Swnj u_short dzstd[] = { 0 }; 432395Swnj struct uba_driver dzdriver = 442606Swnj { dzprobe, 0, dzattach, 0, dzstd, "dz", dzinfo }; 452395Swnj 462645Swnj #define NDZLINE (NDZ*8) 4716191Skarels #define FASTTIMER (hz/30) /* rate to drain silos, when in use */ 482469Swnj 492469Swnj int dzstart(), dzxint(), dzdma(); 50114Sbill int ttrstrt(); 512645Swnj struct tty dz_tty[NDZLINE]; 522645Swnj int dz_cnt = { NDZLINE }; 53119Sbill int dzact; 5416191Skarels int dzsilos; /* mask of dz's with silo in use */ 5516191Skarels int dzchars[NDZ]; /* recent input count */ 5616191Skarels int dzrate[NDZ]; /* smoothed input count */ 5716191Skarels int dztimerintvl; /* time interval for dztimer */ 5816191Skarels int dzhighrate = 100; /* silo on if dzchars > dzhighrate */ 5916191Skarels int dzlowrate = 75; /* silo off if dzrate < dzlowrate */ 6017Sbill 615731Sroot #define dzwait(x) while (((x)->dzlcs & DZ_ACK) == 0) 625731Sroot 632469Swnj /* 642469Swnj * Software copy of dzbrk since it isn't readable 652469Swnj */ 662645Swnj char dz_brk[NDZ]; 672645Swnj char dzsoftCAR[NDZ]; 685731Sroot char dz_lnen[NDZ]; /* saved line enable bits for DZ32 */ 6917Sbill 702469Swnj /* 715731Sroot * The dz11 doesn't interrupt on carrier transitions, so 722469Swnj * we have to use a timer to watch it. 732469Swnj */ 742469Swnj char dz_timer; /* timer started? */ 752469Swnj 762469Swnj /* 772469Swnj * Pdma structures for fast output code 782469Swnj */ 792645Swnj struct pdma dzpdma[NDZLINE]; 802469Swnj 8139061Smarc struct speedtab dzspeedtab[] = { 8239061Smarc 0, 0, 8339061Smarc 50, 020, 8439061Smarc 75, 021, 8539061Smarc 110, 022, 8639061Smarc 134, 023, 8739061Smarc 150, 024, 8839061Smarc 300, 025, 8939061Smarc 600, 026, 9039061Smarc 1200, 027, 9139061Smarc 1800, 030, 9239061Smarc 2400, 032, 9339061Smarc 4800, 034, 9439061Smarc 9600, 036, 9539061Smarc 19200, 037, 9639061Smarc EXTA, 037, 9739061Smarc -1, -1 9839061Smarc }; 9917Sbill 10025397Skarels #ifndef PORTSELECTOR 10139061Smarc #define ISPEED TTYDEF_SPEED 10239061Smarc #define LFLAG TTYDEF_LFLAG 1036616Ssam #else 1046616Ssam #define ISPEED B4800 10539061Smarc #define LFLAG (TTYDEF_LFLAG&~ECHO) 1066616Ssam #endif 1076616Ssam 1082606Swnj dzprobe(reg) 1092395Swnj caddr_t reg; 1102395Swnj { 1112457Swnj register int br, cvec; 11210019Ssam register struct dzdevice *dzaddr = (struct dzdevice *)reg; 1132395Swnj 1142606Swnj #ifdef lint 1153102Swnj br = 0; cvec = br; br = cvec; 1164933Swnj dzrint(0); dzxint((struct tty *)0); 1172606Swnj #endif 1185731Sroot dzaddr->dzcsr = DZ_TIE|DZ_MSE|DZ_32; 1195731Sroot if (dzaddr->dzcsr & DZ_32) 1205731Sroot dzaddr->dzlnen = 1; 1215731Sroot else 1225731Sroot dzaddr->dztcr = 1; /* enable any line */ 1232457Swnj DELAY(100000); 1245731Sroot dzaddr->dzcsr = DZ_CLR|DZ_32; /* reset everything */ 1252457Swnj if (cvec && cvec != 0x200) 1262457Swnj cvec -= 4; 12710019Ssam return (sizeof (struct dzdevice)); 1282395Swnj } 1292395Swnj 1302606Swnj dzattach(ui) 1312976Swnj register struct uba_device *ui; 1322395Swnj { 1332395Swnj register struct pdma *pdp = &dzpdma[ui->ui_unit*8]; 1342395Swnj register struct tty *tp = &dz_tty[ui->ui_unit*8]; 1352606Swnj register int cntr; 1362645Swnj extern dzscan(); 1372395Swnj 1382606Swnj for (cntr = 0; cntr < 8; cntr++) { 13910019Ssam pdp->p_addr = (struct dzdevice *)ui->ui_addr; 1402395Swnj pdp->p_arg = (int)tp; 1412395Swnj pdp->p_fcn = dzxint; 1422395Swnj pdp++, tp++; 1432395Swnj } 1442567Swnj dzsoftCAR[ui->ui_unit] = ui->ui_flags; 1452627Swnj if (dz_timer == 0) { 1462627Swnj dz_timer++; 1472756Swnj timeout(dzscan, (caddr_t)0, hz); 14816191Skarels dztimerintvl = FASTTIMER; 1492627Swnj } 1502395Swnj } 1512395Swnj 15217Sbill /*ARGSUSED*/ 1532395Swnj dzopen(dev, flag) 1542395Swnj dev_t dev; 15517Sbill { 15617Sbill register struct tty *tp; 1572395Swnj register int unit; 15840725Skarels int error, dzparam(); 15917Sbill 1602395Swnj unit = minor(dev); 1618568Sroot if (unit >= dz_cnt || dzpdma[unit].p_addr == 0) 1628568Sroot return (ENXIO); 1632395Swnj tp = &dz_tty[unit]; 1642395Swnj tp->t_addr = (caddr_t)&dzpdma[unit]; 16517Sbill tp->t_oproc = dzstart; 16639061Smarc tp->t_param = dzparam; 16739061Smarc tp->t_dev = dev; 1685407Swnj if ((tp->t_state & TS_ISOPEN) == 0) { 16944393Smarc tp->t_state |= TS_WOPEN; 17017Sbill ttychars(tp); 17127050Skarels #ifndef PORTSELECTOR 17227050Skarels if (tp->t_ispeed == 0) { 17339061Smarc #endif 17439061Smarc tp->t_iflag = TTYDEF_IFLAG; 17539061Smarc tp->t_oflag = TTYDEF_OFLAG; 17639061Smarc tp->t_cflag = TTYDEF_CFLAG; 17739061Smarc tp->t_lflag = LFLAG; 17839061Smarc tp->t_ispeed = tp->t_ospeed = ISPEED; 17939061Smarc #ifdef PORTSELECTOR 18039061Smarc tp->t_cflag |= HUPCL; 18139061Smarc #else 18227050Skarels } 18339061Smarc #endif 18439061Smarc dzparam(tp, &tp->t_termios); 18539061Smarc 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(); 19040725Skarels while ((flag&O_NONBLOCK) == 0 && (tp->t_cflag&CLOCAL) == 0 && 19139061Smarc (tp->t_state & TS_CARR_ON) == 0) { 1925407Swnj tp->t_state |= TS_WOPEN; 19344393Smarc if (error = ttysleep(tp, (caddr_t)&tp->t_rawq, TTIPRI | PCATCH, 19444393Smarc ttopen, 0)) 19540725Skarels break; 19617Sbill } 197114Sbill (void) spl0(); 19840725Skarels if (error) 19940725Skarels return (error); 2008568Sroot return ((*linesw[tp->t_line].l_open)(dev, tp)); 20117Sbill } 20217Sbill 2032395Swnj /*ARGSUSED*/ 2042395Swnj dzclose(dev, flag) 2052395Swnj dev_t dev; 20617Sbill { 20717Sbill register struct tty *tp; 2082395Swnj register int unit; 20910019Ssam register struct dzdevice *dzaddr; 2106150Ssam int dz; 21117Sbill 2122395Swnj unit = minor(dev); 2132395Swnj dz = unit >> 3; 2142395Swnj tp = &dz_tty[unit]; 21517Sbill (*linesw[tp->t_line].l_close)(tp); 2165731Sroot dzaddr = dzpdma[unit].p_addr; 2175731Sroot if (dzaddr->dzcsr&DZ_32) 2186157Ssam (void) dzmctl(dev, DZ_BRK, DMBIC); 2195731Sroot else 2205731Sroot dzaddr->dzbrk = (dz_brk[dz] &= ~(1 << (unit&07))); 22139061Smarc if (tp->t_cflag&HUPCL || tp->t_state&TS_WOPEN || 22239061Smarc (tp->t_state&TS_ISOPEN) == 0) 2236157Ssam (void) dzmctl(dev, DZ_OFF, DMSET); 22440725Skarels return (ttyclose(tp)); 22517Sbill } 22617Sbill 22739061Smarc dzread(dev, uio, flag) 2282395Swnj dev_t dev; 2297727Sroot struct uio *uio; 23017Sbill { 23117Sbill register struct tty *tp; 23217Sbill 2332395Swnj tp = &dz_tty[minor(dev)]; 23439061Smarc return ((*linesw[tp->t_line].l_read)(tp, uio, flag)); 23517Sbill } 23617Sbill 23739061Smarc dzwrite(dev, uio, flag) 2382395Swnj dev_t dev; 2397833Sroot struct uio *uio; 24017Sbill { 24117Sbill register struct tty *tp; 24217Sbill 2432395Swnj tp = &dz_tty[minor(dev)]; 24439061Smarc return ((*linesw[tp->t_line].l_write)(tp, uio, flag)); 24517Sbill } 24617Sbill 247119Sbill /*ARGSUSED*/ 2482395Swnj dzrint(dz) 2492395Swnj int dz; 25017Sbill { 25117Sbill register struct tty *tp; 25239061Smarc register int c, cc; 25310019Ssam register struct dzdevice *dzaddr; 254119Sbill register struct tty *tp0; 2552395Swnj register int unit; 2562923Swnj int overrun = 0; 25717Sbill 2582457Swnj if ((dzact & (1<<dz)) == 0) 2592457Swnj return; 2602457Swnj unit = dz * 8; 2612457Swnj dzaddr = dzpdma[unit].p_addr; 2622457Swnj tp0 = &dz_tty[unit]; 2635731Sroot dzaddr->dzcsr &= ~(DZ_RIE|DZ_MIE); /* the manual says this song */ 2645731Sroot dzaddr->dzcsr |= DZ_RIE|DZ_MIE; /* and dance is necessary */ 2655731Sroot while (dzaddr->dzcsr & DZ_MSC) { /* DZ32 modem change interrupt */ 2665731Sroot c = dzaddr->dzmtsr; 2675731Sroot tp = tp0 + (c&7); 2685731Sroot if (tp >= &dz_tty[dz_cnt]) 2695731Sroot break; 2705731Sroot dzaddr->dzlcs = c&7; /* get status of modem lines */ 2715731Sroot dzwait(dzaddr); /* wait for them */ 2725731Sroot if (c & DZ_CD) /* carrier status change? */ 2735731Sroot if (dzaddr->dzlcs & DZ_CD) { /* carrier up? */ 27425397Skarels /* carrier present */ 27525397Skarels (void)(*linesw[tp->t_line].l_modem)(tp, 1); 27625397Skarels } else if ((*linesw[tp->t_line].l_modem)(tp, 0) == 0) 27725397Skarels dzaddr->dzlcs = DZ_ACK|(c&7); 2785731Sroot } 2792457Swnj while ((c = dzaddr->dzrbuf) < 0) { /* char present */ 28039061Smarc cc = c&0xff; 28116191Skarels dzchars[dz]++; 2822457Swnj tp = tp0 + ((c>>8)&07); 2832457Swnj if (tp >= &dz_tty[dz_cnt]) 28417Sbill continue; 2855407Swnj if ((tp->t_state & TS_ISOPEN) == 0) { 2862457Swnj wakeup((caddr_t)&tp->t_rawq); 2876616Ssam #ifdef PORTSELECTOR 2886616Ssam if ((tp->t_state&TS_WOPEN) == 0) 2896616Ssam #endif 29025397Skarels continue; 2912457Swnj } 2922469Swnj if (c&DZ_FE) 29339061Smarc cc |= TTY_FE; 2942923Swnj if (c&DZ_DO && overrun == 0) { 29524843Seric log(LOG_WARNING, "dz%d,%d: silo overflow\n", dz, (c>>8)&7); 2962923Swnj overrun = 1; 2972923Swnj } 2982469Swnj if (c&DZ_PE) 29939061Smarc cc |= TTY_PE; 30039061Smarc (*linesw[tp->t_line].l_rint)(cc, tp); 30117Sbill } 30217Sbill } 30317Sbill 30417Sbill /*ARGSUSED*/ 3057631Ssam dzioctl(dev, cmd, data, flag) 3062395Swnj dev_t dev; 3077631Ssam caddr_t data; 30817Sbill { 30917Sbill register struct tty *tp; 3102395Swnj register int unit = minor(dev); 3112395Swnj register int dz = unit >> 3; 31210019Ssam register struct dzdevice *dzaddr; 3138568Sroot int error; 31417Sbill 3152395Swnj tp = &dz_tty[unit]; 3168568Sroot error = (*linesw[tp->t_line].l_ioctl)(tp, cmd, data, flag); 3178568Sroot if (error >= 0) 3188568Sroot return (error); 3198568Sroot error = ttioctl(tp, cmd, data, flag); 32039061Smarc if (error >= 0) 3218568Sroot return (error); 32239061Smarc 3238568Sroot switch (cmd) { 3242395Swnj 325170Sbill case TIOCSBRK: 3265731Sroot dzaddr = ((struct pdma *)(tp->t_addr))->p_addr; 3275731Sroot if (dzaddr->dzcsr&DZ_32) 3286157Ssam (void) dzmctl(dev, DZ_BRK, DMBIS); 3295731Sroot else 3305731Sroot dzaddr->dzbrk = (dz_brk[dz] |= 1 << (unit&07)); 331170Sbill break; 3327631Ssam 333170Sbill case TIOCCBRK: 3345731Sroot dzaddr = ((struct pdma *)(tp->t_addr))->p_addr; 3355731Sroot if (dzaddr->dzcsr&DZ_32) 3366157Ssam (void) dzmctl(dev, DZ_BRK, DMBIC); 3375731Sroot else 3385731Sroot dzaddr->dzbrk = (dz_brk[dz] &= ~(1 << (unit&07))); 339170Sbill break; 3407631Ssam 341170Sbill case TIOCSDTR: 3426157Ssam (void) dzmctl(dev, DZ_DTR|DZ_RTS, DMBIS); 343170Sbill break; 3447631Ssam 345170Sbill case TIOCCDTR: 3466157Ssam (void) dzmctl(dev, DZ_DTR|DZ_RTS, DMBIC); 347170Sbill break; 3487631Ssam 3495731Sroot case TIOCMSET: 3507631Ssam (void) dzmctl(dev, dmtodz(*(int *)data), DMSET); 3515731Sroot break; 3527631Ssam 3535731Sroot case TIOCMBIS: 3547631Ssam (void) dzmctl(dev, dmtodz(*(int *)data), DMBIS); 3555731Sroot break; 3567631Ssam 3575731Sroot case TIOCMBIC: 3587631Ssam (void) dzmctl(dev, dmtodz(*(int *)data), DMBIC); 3595731Sroot break; 3607631Ssam 3615731Sroot case TIOCMGET: 3627631Ssam *(int *)data = dztodm(dzmctl(dev, 0, DMGET)); 3635731Sroot break; 3647631Ssam 365170Sbill default: 3668568Sroot return (ENOTTY); 367170Sbill } 3688568Sroot return (0); 36917Sbill } 3705731Sroot 3715731Sroot dmtodz(bits) 3725731Sroot register int bits; 3735731Sroot { 3745731Sroot register int b; 3755731Sroot 3765731Sroot b = (bits >>1) & 0370; 3775731Sroot if (bits & DML_ST) b |= DZ_ST; 3785731Sroot if (bits & DML_RTS) b |= DZ_RTS; 3795731Sroot if (bits & DML_DTR) b |= DZ_DTR; 3805731Sroot if (bits & DML_LE) b |= DZ_LE; 3815731Sroot return(b); 3825731Sroot } 3835731Sroot 3845731Sroot dztodm(bits) 3855731Sroot register int bits; 3865731Sroot { 3875731Sroot register int b; 3885731Sroot 3895731Sroot b = (bits << 1) & 0360; 3905731Sroot if (bits & DZ_DSR) b |= DML_DSR; 3915731Sroot if (bits & DZ_DTR) b |= DML_DTR; 3925731Sroot if (bits & DZ_ST) b |= DML_ST; 3935731Sroot if (bits & DZ_RTS) b |= DML_RTS; 3945731Sroot return(b); 3955731Sroot } 39617Sbill 39739061Smarc dzparam(tp, t) 39839061Smarc register struct tty *tp; 39939061Smarc register struct termios *t; 40017Sbill { 40110019Ssam register struct dzdevice *dzaddr; 4022395Swnj register int lpr; 40339061Smarc register int cflag = t->c_cflag; 40439061Smarc int unit = minor(tp->t_dev); 40539061Smarc int ospeed = ttspeedtab(t->c_ospeed, dzspeedtab); 40639061Smarc 40739061Smarc /* check requested parameters */ 40839061Smarc if (ospeed < 0 || (t->c_ispeed && t->c_ispeed != t->c_ospeed) || 40939061Smarc (cflag&CSIZE) == CS5 || (cflag&CSIZE) == CS6) 41039061Smarc return(EINVAL); 41139061Smarc /* and copy to tty */ 41239061Smarc tp->t_ispeed = t->c_ispeed; 41339061Smarc tp->t_ospeed = t->c_ospeed; 41439061Smarc tp->t_cflag = cflag; 41539061Smarc 4162395Swnj dzaddr = dzpdma[unit].p_addr; 41716191Skarels if (dzsilos & (1 << (unit >> 3))) 41816191Skarels dzaddr->dzcsr = DZ_IEN | DZ_SAE; 41916191Skarels else 42016191Skarels dzaddr->dzcsr = DZ_IEN; 4212395Swnj dzact |= (1<<(unit>>3)); 42239061Smarc if (ospeed == 0) { 4236157Ssam (void) dzmctl(unit, DZ_OFF, DMSET); /* hang up line */ 42417Sbill return; 42517Sbill } 42639061Smarc lpr = (ospeed<<8) | (unit & 07); 42739061Smarc if ((cflag&CSIZE) == CS7) 42839061Smarc lpr |= BITS7; 42939061Smarc else 43017Sbill lpr |= BITS8; 43139061Smarc if (cflag&PARENB) 43239061Smarc lpr |= PENABLE; 43339061Smarc if (cflag&PARODD) 43417Sbill lpr |= OPAR; 43539061Smarc if (cflag&CSTOPB) 4362469Swnj lpr |= TWOSB; 43717Sbill dzaddr->dzlpr = lpr; 43839061Smarc return 0; 43917Sbill } 44017Sbill 44117Sbill dzxint(tp) 4422395Swnj register struct tty *tp; 44317Sbill { 44417Sbill register struct pdma *dp; 44516191Skarels register dz, unit; 44617Sbill 4472395Swnj dp = (struct pdma *)tp->t_addr; 4485407Swnj tp->t_state &= ~TS_BUSY; 4495407Swnj if (tp->t_state & TS_FLUSH) 4505407Swnj tp->t_state &= ~TS_FLUSH; 4515731Sroot else { 452281Sbill ndflush(&tp->t_outq, dp->p_mem-tp->t_outq.c_cf); 4535731Sroot dp->p_end = dp->p_mem = tp->t_outq.c_cf; 4545731Sroot } 45517Sbill if (tp->t_line) 45617Sbill (*linesw[tp->t_line].l_start)(tp); 45717Sbill else 45817Sbill dzstart(tp); 4595731Sroot dz = minor(tp->t_dev) >> 3; 4605731Sroot unit = minor(tp->t_dev) & 7; 4615407Swnj if (tp->t_outq.c_cc == 0 || (tp->t_state&TS_BUSY)==0) 4625731Sroot if (dp->p_addr->dzcsr & DZ_32) 4635731Sroot dp->p_addr->dzlnen = (dz_lnen[dz] &= ~(1<<unit)); 4645731Sroot else 4655731Sroot dp->p_addr->dztcr &= ~(1<<unit); 46617Sbill } 46717Sbill 46817Sbill dzstart(tp) 4692395Swnj register struct tty *tp; 47017Sbill { 47117Sbill register struct pdma *dp; 47210019Ssam register struct dzdevice *dzaddr; 4732395Swnj register int cc; 4745731Sroot int s, dz, unit; 47517Sbill 4762395Swnj dp = (struct pdma *)tp->t_addr; 47717Sbill dzaddr = dp->p_addr; 4782395Swnj s = spl5(); 4795407Swnj if (tp->t_state & (TS_TIMEOUT|TS_BUSY|TS_TTSTOP)) 48017Sbill goto out; 48139061Smarc if (tp->t_outq.c_cc <= tp->t_lowat) { 4825407Swnj if (tp->t_state&TS_ASLEEP) { 4835407Swnj tp->t_state &= ~TS_ASLEEP; 4845407Swnj wakeup((caddr_t)&tp->t_outq); 4855407Swnj } 4865407Swnj if (tp->t_wsel) { 4875407Swnj selwakeup(tp->t_wsel, tp->t_state & TS_WCOLL); 4885407Swnj tp->t_wsel = 0; 4895407Swnj tp->t_state &= ~TS_WCOLL; 4905407Swnj } 49117Sbill } 49217Sbill if (tp->t_outq.c_cc == 0) 49317Sbill goto out; 4949551Ssam if (tp->t_flags & (RAW|LITOUT)) 49517Sbill cc = ndqb(&tp->t_outq, 0); 49617Sbill else { 49717Sbill cc = ndqb(&tp->t_outq, 0200); 49817Sbill if (cc == 0) { 49917Sbill cc = getc(&tp->t_outq); 5002469Swnj timeout(ttrstrt, (caddr_t)tp, (cc&0x7f) + 6); 5015407Swnj tp->t_state |= TS_TIMEOUT; 50217Sbill goto out; 50317Sbill } 50417Sbill } 5055407Swnj tp->t_state |= TS_BUSY; 50617Sbill dp->p_end = dp->p_mem = tp->t_outq.c_cf; 50717Sbill dp->p_end += cc; 5085731Sroot dz = minor(tp->t_dev) >> 3; 5095731Sroot unit = minor(tp->t_dev) & 7; 5105731Sroot if (dzaddr->dzcsr & DZ_32) 5115731Sroot dzaddr->dzlnen = (dz_lnen[dz] |= (1<<unit)); 5125731Sroot else 5135731Sroot dzaddr->dztcr |= (1<<unit); 5142395Swnj out: 5152395Swnj splx(s); 51617Sbill } 51717Sbill 51817Sbill /* 51917Sbill * Stop output on a line. 52017Sbill */ 52117Sbill /*ARGSUSED*/ 52217Sbill dzstop(tp, flag) 5232395Swnj register struct tty *tp; 52417Sbill { 52517Sbill register struct pdma *dp; 52617Sbill register int s; 52717Sbill 5282395Swnj dp = (struct pdma *)tp->t_addr; 5292457Swnj s = spl5(); 5305407Swnj if (tp->t_state & TS_BUSY) { 53117Sbill dp->p_end = dp->p_mem; 5325407Swnj if ((tp->t_state&TS_TTSTOP)==0) 5335407Swnj tp->t_state |= TS_FLUSH; 53417Sbill } 53517Sbill splx(s); 53617Sbill } 53717Sbill 5385731Sroot dzmctl(dev, bits, how) 5395731Sroot dev_t dev; 5405731Sroot int bits, how; 54117Sbill { 54210019Ssam register struct dzdevice *dzaddr; 5435731Sroot register int unit, mbits; 5445731Sroot int b, s; 5455731Sroot 5465731Sroot unit = minor(dev); 5475731Sroot b = 1<<(unit&7); 5482395Swnj dzaddr = dzpdma[unit].p_addr; 5495731Sroot s = spl5(); 5505731Sroot if (dzaddr->dzcsr & DZ_32) { 5515731Sroot dzwait(dzaddr) 5525731Sroot DELAY(100); /* IS 100 TOO MUCH? */ 5535731Sroot dzaddr->dzlcs = unit&7; 5545731Sroot DELAY(100); 5555731Sroot dzwait(dzaddr) 5565731Sroot DELAY(100); 5575731Sroot mbits = dzaddr->dzlcs; 5585731Sroot mbits &= 0177770; 5595731Sroot } else { 5605731Sroot mbits = (dzaddr->dzdtr & b) ? DZ_DTR : 0; 5615731Sroot mbits |= (dzaddr->dzmsr & b) ? DZ_CD : 0; 5625731Sroot mbits |= (dzaddr->dztbuf & b) ? DZ_RI : 0; 5635731Sroot } 5645731Sroot switch (how) { 5655731Sroot case DMSET: 5665731Sroot mbits = bits; 5675731Sroot break; 5685731Sroot 5695731Sroot case DMBIS: 5705731Sroot mbits |= bits; 5715731Sroot break; 5725731Sroot 5735731Sroot case DMBIC: 5745731Sroot mbits &= ~bits; 5755731Sroot break; 5765731Sroot 5775731Sroot case DMGET: 5785731Sroot (void) splx(s); 5795731Sroot return(mbits); 5805731Sroot } 5815731Sroot if (dzaddr->dzcsr & DZ_32) { 5825731Sroot mbits |= DZ_ACK|(unit&7); 5835731Sroot dzaddr->dzlcs = mbits; 5845731Sroot } else { 5855731Sroot if (mbits & DZ_DTR) 5865731Sroot dzaddr->dzdtr |= b; 5875731Sroot else 5885731Sroot dzaddr->dzdtr &= ~b; 5895731Sroot } 59030387Skarels if (mbits & DZ_DTR && dzsoftCAR[unit >> 3] & b) 59130387Skarels dz_tty[unit].t_state |= TS_CARR_ON; 5925731Sroot (void) splx(s); 5935731Sroot return(mbits); 59417Sbill } 59517Sbill 59616191Skarels int dztransitions, dzfasttimers; /*DEBUG*/ 59717Sbill dzscan() 59817Sbill { 59917Sbill register i; 60010019Ssam register struct dzdevice *dzaddr; 60117Sbill register bit; 60217Sbill register struct tty *tp; 6035731Sroot register car; 60416191Skarels int olddzsilos = dzsilos; 60516191Skarels int dztimer(); 60617Sbill 60717Sbill for (i = 0; i < dz_cnt ; i++) { 60817Sbill dzaddr = dzpdma[i].p_addr; 6092627Swnj if (dzaddr == 0) 6102627Swnj continue; 61117Sbill tp = &dz_tty[i]; 61217Sbill bit = 1<<(i&07); 6135731Sroot car = 0; 6145731Sroot if (dzsoftCAR[i>>3]&bit) 6155731Sroot car = 1; 6165731Sroot else if (dzaddr->dzcsr & DZ_32) { 6175731Sroot dzaddr->dzlcs = i&07; 6185731Sroot dzwait(dzaddr); 6195731Sroot car = dzaddr->dzlcs & DZ_CD; 6205731Sroot } else 6215731Sroot car = dzaddr->dzmsr&bit; 6225731Sroot if (car) { 62317Sbill /* carrier present */ 62425397Skarels if ((tp->t_state & TS_CARR_ON) == 0) 62525397Skarels (void)(*linesw[tp->t_line].l_modem)(tp, 1); 62625397Skarels } else if ((tp->t_state&TS_CARR_ON) && 62725397Skarels (*linesw[tp->t_line].l_modem)(tp, 0) == 0) 62825397Skarels dzaddr->dzdtr &= ~bit; 62917Sbill } 63016191Skarels for (i = 0; i < NDZ; i++) { 63116191Skarels ave(dzrate[i], dzchars[i], 8); 63216191Skarels if (dzchars[i] > dzhighrate && ((dzsilos & (1 << i)) == 0)) { 63316397Ssam dzpdma[i << 3].p_addr->dzcsr = DZ_IEN | DZ_SAE; 63416191Skarels dzsilos |= (1 << i); 63516191Skarels dztransitions++; /*DEBUG*/ 63616191Skarels } else if ((dzsilos & (1 << i)) && (dzrate[i] < dzlowrate)) { 63716397Ssam dzpdma[i << 3].p_addr->dzcsr = DZ_IEN; 63816191Skarels dzsilos &= ~(1 << i); 63916191Skarels } 64016191Skarels dzchars[i] = 0; 64116191Skarels } 64216191Skarels if (dzsilos && !olddzsilos) 64316191Skarels timeout(dztimer, (caddr_t)0, dztimerintvl); 64416191Skarels timeout(dzscan, (caddr_t)0, hz); 64517Sbill } 646119Sbill 647119Sbill dztimer() 648119Sbill { 6498160Sroot register int dz; 65016191Skarels register int s; 651119Sbill 65216191Skarels if (dzsilos == 0) 65316191Skarels return; 65416191Skarels s = spl5(); 65516191Skarels dzfasttimers++; /*DEBUG*/ 6562645Swnj for (dz = 0; dz < NDZ; dz++) 65716191Skarels if (dzsilos & (1 << dz)) 65816191Skarels dzrint(dz); 6598160Sroot splx(s); 66016191Skarels timeout(dztimer, (caddr_t) 0, dztimerintvl); 661119Sbill } 662281Sbill 663281Sbill /* 664281Sbill * Reset state of driver if UBA reset was necessary. 665301Sbill * Reset parameters and restart transmission on open lines. 666281Sbill */ 6672395Swnj dzreset(uban) 6682422Skre int uban; 669281Sbill { 6702395Swnj register int unit; 671281Sbill register struct tty *tp; 6722976Swnj register struct uba_device *ui; 673281Sbill 6742645Swnj for (unit = 0; unit < NDZLINE; unit++) { 6752422Skre ui = dzinfo[unit >> 3]; 6762422Skre if (ui == 0 || ui->ui_ubanum != uban || ui->ui_alive == 0) 6772422Skre continue; 6782923Swnj if (unit%8 == 0) 6792923Swnj printf(" dz%d", unit>>3); 6802395Swnj tp = &dz_tty[unit]; 6815407Swnj if (tp->t_state & (TS_ISOPEN|TS_WOPEN)) { 6822395Swnj dzparam(unit); 6836157Ssam (void) dzmctl(unit, DZ_ON, DMSET); 6845407Swnj tp->t_state &= ~TS_BUSY; 685301Sbill dzstart(tp); 686281Sbill } 687281Sbill } 688281Sbill } 6891562Sbill #endif 690