1*3819Swnj /* dz.c 4.26 81/05/29 */ 217Sbill 31935Swnj #include "dz.h" 42645Swnj #if NDZ > 0 517Sbill /* 617Sbill * DZ-11 Driver 72469Swnj * 82469Swnj * This driver mimics dh.c; see it for explanation of common code. 917Sbill */ 102731Swnj #include "bk.h" 1117Sbill #include "../h/param.h" 1217Sbill #include "../h/systm.h" 1317Sbill #include "../h/tty.h" 1417Sbill #include "../h/dir.h" 1517Sbill #include "../h/user.h" 1617Sbill #include "../h/map.h" 1717Sbill #include "../h/pte.h" 182395Swnj #include "../h/buf.h" 192567Swnj #include "../h/vm.h" 202976Swnj #include "../h/ubavar.h" 2117Sbill #include "../h/conf.h" 2217Sbill #include "../h/pdma.h" 23114Sbill #include "../h/bk.h" 24871Sbill #include "../h/file.h" 251786Sbill #include "../h/mx.h" 26145Sbill 272469Swnj /* 282469Swnj * Driver information for auto-configuration stuff. 292469Swnj */ 302606Swnj int dzprobe(), dzattach(), dzrint(); 312976Swnj struct uba_device *dzinfo[NDZ]; 322395Swnj u_short dzstd[] = { 0 }; 332395Swnj struct uba_driver dzdriver = 342606Swnj { dzprobe, 0, dzattach, 0, dzstd, "dz", dzinfo }; 352395Swnj 362645Swnj #define NDZLINE (NDZ*8) 3717Sbill 382469Swnj /* 392469Swnj * Registers and bits 402469Swnj */ 412469Swnj 422469Swnj /* Bits in dzlpr */ 432457Swnj #define BITS7 020 442457Swnj #define BITS8 030 452457Swnj #define TWOSB 040 462457Swnj #define PENABLE 0100 472457Swnj #define OPAR 0200 4817Sbill 492469Swnj /* Bits in dzrbuf */ 502469Swnj #define DZ_PE 010000 512469Swnj #define DZ_FE 020000 522469Swnj #define DZ_DO 040000 532469Swnj 542469Swnj /* Bits in dzcsr */ 552469Swnj #define DZ_CLR 020 /* Reset dz */ 562469Swnj #define DZ_MSE 040 /* Master Scan Enable */ 572469Swnj #define DZ_RIE 0100 /* Receiver Interrupt Enable */ 582469Swnj #define DZ_SAE 010000 /* Silo Alarm Enable */ 592469Swnj #define DZ_TIE 040000 /* Transmit Interrupt Enable */ 603440Sroot #if NBK == 0 613440Sroot #define DZ_IEN (DZ_MSE|DZ_RIE|DZ_TIE) 623440Sroot #else 633440Sroot #define DZ_IEN (DZ_MSE|DZ_RIE|DZ_TIE|DZ_SAE) 643440Sroot #endif 652469Swnj 662469Swnj /* Flags for modem-control */ 672469Swnj #define DZ_ON 1 682469Swnj #define DZ_OFF 0 6917Sbill 702469Swnj int dzstart(), dzxint(), dzdma(); 71114Sbill int ttrstrt(); 722645Swnj struct tty dz_tty[NDZLINE]; 732645Swnj int dz_cnt = { NDZLINE }; 74119Sbill int dzact; 7517Sbill 7617Sbill struct device { 772469Swnj short dzcsr; /* control-status register */ 782469Swnj short dzrbuf; /* receiver buffer */ 792469Swnj #define dzlpr dzrbuf /* line parameter reg is write of dzrbuf */ 802469Swnj char dztcr; /* transmit control register */ 812469Swnj char dzdtr; /* data terminal ready */ 822469Swnj char dztbuf; /* transmit buffer */ 832469Swnj char dzbrk; /* break control */ 842469Swnj #define dzmsr dzbrk /* modem status register */ 8517Sbill }; 862469Swnj /* 872469Swnj * Software copy of dzbrk since it isn't readable 882469Swnj */ 892645Swnj char dz_brk[NDZ]; 902645Swnj char dzsoftCAR[NDZ]; 9117Sbill 922469Swnj /* 932469Swnj * The dz doesn't interrupt on carrier transitions, so 942469Swnj * we have to use a timer to watch it. 952469Swnj */ 962469Swnj char dz_timer; /* timer started? */ 972469Swnj 982469Swnj /* 992469Swnj * Pdma structures for fast output code 1002469Swnj */ 1012645Swnj struct pdma dzpdma[NDZLINE]; 1022469Swnj 1032395Swnj char dz_speeds[] = 1042395Swnj { 0,020,021,022,023,024,0,025,026,027,030,032,034,036,0,0 }; 10517Sbill 1062606Swnj dzprobe(reg) 1072395Swnj caddr_t reg; 1082395Swnj { 1092457Swnj register int br, cvec; 1102457Swnj register struct device *dzaddr = (struct device *)reg; 1112395Swnj 1122606Swnj #ifdef lint 1133102Swnj br = 0; cvec = br; br = cvec; 1142606Swnj #endif 1152469Swnj dzaddr->dzcsr = DZ_TIE|DZ_MSE; 1162422Skre dzaddr->dztcr = 1; /* enable any line */ 1172457Swnj DELAY(100000); 1182469Swnj dzaddr->dzcsr = DZ_CLR; /* reset everything */ 1192457Swnj if (cvec && cvec != 0x200) 1202457Swnj cvec -= 4; 1212457Swnj return (1); 1222395Swnj } 1232395Swnj 1242606Swnj dzattach(ui) 1252976Swnj register struct uba_device *ui; 1262395Swnj { 1272395Swnj register struct pdma *pdp = &dzpdma[ui->ui_unit*8]; 1282395Swnj register struct tty *tp = &dz_tty[ui->ui_unit*8]; 1292606Swnj register int cntr; 1302645Swnj extern dzscan(); 1312395Swnj 1322606Swnj for (cntr = 0; cntr < 8; cntr++) { 1332606Swnj pdp->p_addr = (struct device *)ui->ui_addr; 1342395Swnj pdp->p_arg = (int)tp; 1352395Swnj pdp->p_fcn = dzxint; 1362395Swnj pdp++, tp++; 1372395Swnj } 1382567Swnj dzsoftCAR[ui->ui_unit] = ui->ui_flags; 1392627Swnj if (dz_timer == 0) { 1402627Swnj dz_timer++; 1412756Swnj timeout(dzscan, (caddr_t)0, hz); 1422627Swnj } 1432395Swnj return (1); 1442395Swnj } 1452395Swnj 14617Sbill /*ARGSUSED*/ 1472395Swnj dzopen(dev, flag) 1482395Swnj dev_t dev; 14917Sbill { 15017Sbill register struct tty *tp; 1512395Swnj register int unit; 15217Sbill 1532395Swnj unit = minor(dev); 1542395Swnj if (unit >= dz_cnt || dzpdma[unit].p_addr == 0) { 15517Sbill u.u_error = ENXIO; 15617Sbill return; 15717Sbill } 1582395Swnj tp = &dz_tty[unit]; 1592395Swnj tp->t_addr = (caddr_t)&dzpdma[unit]; 16017Sbill tp->t_oproc = dzstart; 16117Sbill tp->t_iproc = NULL; 16217Sbill tp->t_state |= WOPEN; 16317Sbill if ((tp->t_state & ISOPEN) == 0) { 16417Sbill ttychars(tp); 1652469Swnj tp->t_ospeed = tp->t_ispeed = B300; 16617Sbill tp->t_flags = ODDP|EVENP|ECHO; 1672469Swnj /* tp->t_state |= HUPCLS; */ 1682395Swnj dzparam(unit); 16917Sbill } else if (tp->t_state&XCLUDE && u.u_uid != 0) { 17017Sbill u.u_error = EBUSY; 17117Sbill return; 17217Sbill } 1732469Swnj dzmodem(unit, DZ_ON); 174114Sbill (void) spl5(); 17517Sbill while ((tp->t_state & CARR_ON) == 0) { 17617Sbill tp->t_state |= WOPEN; 17717Sbill sleep((caddr_t)&tp->t_rawq, TTIPRI); 17817Sbill } 179114Sbill (void) spl0(); 1802395Swnj (*linesw[tp->t_line].l_open)(dev, tp); 18117Sbill } 18217Sbill 1832395Swnj /*ARGSUSED*/ 1842395Swnj dzclose(dev, flag) 1852395Swnj dev_t dev; 18617Sbill { 18717Sbill register struct tty *tp; 1882395Swnj register int unit; 1892395Swnj int dz; 19017Sbill 1912395Swnj unit = minor(dev); 1922395Swnj dz = unit >> 3; 1932395Swnj tp = &dz_tty[unit]; 19417Sbill (*linesw[tp->t_line].l_close)(tp); 1952197Stoy ((struct pdma *)(tp->t_addr))->p_addr->dzbrk = 1962395Swnj (dz_brk[dz] &= ~(1 << (unit&07))); 19717Sbill if (tp->t_state & HUPCLS) 1982469Swnj dzmodem(unit, DZ_OFF); 19917Sbill ttyclose(tp); 20017Sbill } 20117Sbill 2022395Swnj dzread(dev) 2032395Swnj dev_t dev; 20417Sbill { 20517Sbill register struct tty *tp; 20617Sbill 2072395Swnj tp = &dz_tty[minor(dev)]; 20817Sbill (*linesw[tp->t_line].l_read)(tp); 20917Sbill } 21017Sbill 2112395Swnj dzwrite(dev) 2122395Swnj dev_t dev; 21317Sbill { 21417Sbill register struct tty *tp; 21517Sbill 2162395Swnj tp = &dz_tty[minor(dev)]; 21717Sbill (*linesw[tp->t_line].l_write)(tp); 21817Sbill } 21917Sbill 220119Sbill /*ARGSUSED*/ 2212395Swnj dzrint(dz) 2222395Swnj int dz; 22317Sbill { 22417Sbill register struct tty *tp; 22517Sbill register int c; 22617Sbill register struct device *dzaddr; 227119Sbill register struct tty *tp0; 2282395Swnj register int unit; 2292923Swnj int overrun = 0; 23017Sbill 2312457Swnj if ((dzact & (1<<dz)) == 0) 2322457Swnj return; 2332457Swnj unit = dz * 8; 2342457Swnj dzaddr = dzpdma[unit].p_addr; 2352457Swnj tp0 = &dz_tty[unit]; 2362457Swnj while ((c = dzaddr->dzrbuf) < 0) { /* char present */ 2372457Swnj tp = tp0 + ((c>>8)&07); 2382457Swnj if (tp >= &dz_tty[dz_cnt]) 23917Sbill continue; 2402457Swnj if ((tp->t_state & ISOPEN) == 0) { 2412457Swnj wakeup((caddr_t)&tp->t_rawq); 2422457Swnj continue; 2432457Swnj } 2442469Swnj if (c&DZ_FE) 2452457Swnj if (tp->t_flags & RAW) 2462469Swnj c = 0; 2472457Swnj else 2482457Swnj c = tun.t_intrc; 2492923Swnj if (c&DZ_DO && overrun == 0) { 2502923Swnj printf("dz%d: silo overflow\n", dz); 2512923Swnj overrun = 1; 2522923Swnj } 2532469Swnj if (c&DZ_PE) 2542457Swnj if (((tp->t_flags & (EVENP|ODDP)) == EVENP) 2552457Swnj || ((tp->t_flags & (EVENP|ODDP)) == ODDP)) 25617Sbill continue; 2572731Swnj #if NBK > 0 2582457Swnj if (tp->t_line == NETLDISC) { 2592457Swnj c &= 0177; 2602457Swnj BKINPUT(c, tp); 2612457Swnj } else 2622731Swnj #endif 2632457Swnj (*linesw[tp->t_line].l_rint)(c, tp); 26417Sbill } 26517Sbill } 26617Sbill 26717Sbill /*ARGSUSED*/ 26817Sbill dzioctl(dev, cmd, addr, flag) 2692395Swnj dev_t dev; 2702395Swnj caddr_t addr; 27117Sbill { 27217Sbill register struct tty *tp; 2732395Swnj register int unit = minor(dev); 2742395Swnj register int dz = unit >> 3; 27517Sbill 2762395Swnj tp = &dz_tty[unit]; 277114Sbill cmd = (*linesw[tp->t_line].l_ioctl)(tp, cmd, addr); 278114Sbill if (cmd == 0) 279114Sbill return; 2801896Swnj if (ttioctl(tp, cmd, addr, flag)) { 28117Sbill if (cmd==TIOCSETP || cmd==TIOCSETN) 2822395Swnj dzparam(unit); 283170Sbill } else switch(cmd) { 2842395Swnj 285170Sbill case TIOCSBRK: 286882Sbill ((struct pdma *)(tp->t_addr))->p_addr->dzbrk = 2872395Swnj (dz_brk[dz] |= 1 << (unit&07)); 288170Sbill break; 289170Sbill case TIOCCBRK: 290882Sbill ((struct pdma *)(tp->t_addr))->p_addr->dzbrk = 2912395Swnj (dz_brk[dz] &= ~(1 << (unit&07))); 292170Sbill break; 293170Sbill case TIOCSDTR: 2942469Swnj dzmodem(unit, DZ_ON); 295170Sbill break; 296170Sbill case TIOCCDTR: 2972469Swnj dzmodem(unit, DZ_OFF); 298170Sbill break; 299170Sbill default: 30017Sbill u.u_error = ENOTTY; 301170Sbill } 30217Sbill } 30317Sbill 3042395Swnj dzparam(unit) 3052395Swnj register int unit; 30617Sbill { 30717Sbill register struct tty *tp; 30817Sbill register struct device *dzaddr; 3092395Swnj register int lpr; 31017Sbill 3112395Swnj tp = &dz_tty[unit]; 3122395Swnj dzaddr = dzpdma[unit].p_addr; 31317Sbill dzaddr->dzcsr = DZ_IEN; 3142395Swnj dzact |= (1<<(unit>>3)); 31517Sbill if (tp->t_ispeed == 0) { 3162469Swnj dzmodem(unit, DZ_OFF); /* hang up line */ 31717Sbill return; 31817Sbill } 3192395Swnj lpr = (dz_speeds[tp->t_ispeed]<<8) | (unit & 07); 3202296Swnj if ((tp->t_local&LLITOUT) || (tp->t_flags&RAW)) 32117Sbill lpr |= BITS8; 32217Sbill else 32317Sbill lpr |= (BITS7|PENABLE); 32417Sbill if ((tp->t_flags & EVENP) == 0) 32517Sbill lpr |= OPAR; 3262469Swnj if (tp->t_ispeed == B110) 3272469Swnj lpr |= TWOSB; 32817Sbill dzaddr->dzlpr = lpr; 32917Sbill } 33017Sbill 33117Sbill dzxint(tp) 3322395Swnj register struct tty *tp; 33317Sbill { 33417Sbill register struct pdma *dp; 335145Sbill register s; 33617Sbill 3372469Swnj s = spl5(); /* block pdma interrupts */ 3382395Swnj dp = (struct pdma *)tp->t_addr; 33917Sbill tp->t_state &= ~BUSY; 34017Sbill if (tp->t_state & FLUSH) 34117Sbill tp->t_state &= ~FLUSH; 34217Sbill else 343281Sbill ndflush(&tp->t_outq, dp->p_mem-tp->t_outq.c_cf); 34417Sbill if (tp->t_line) 34517Sbill (*linesw[tp->t_line].l_start)(tp); 34617Sbill else 34717Sbill dzstart(tp); 34817Sbill if (tp->t_outq.c_cc == 0 || (tp->t_state&BUSY)==0) 3492395Swnj dp->p_addr->dztcr &= ~(1 << (minor(tp->t_dev)&07)); 350145Sbill splx(s); 35117Sbill } 35217Sbill 35317Sbill dzstart(tp) 3542395Swnj register struct tty *tp; 35517Sbill { 35617Sbill register struct pdma *dp; 35717Sbill register struct device *dzaddr; 3582395Swnj register int cc; 3592395Swnj int s; 36017Sbill 3612395Swnj dp = (struct pdma *)tp->t_addr; 36217Sbill dzaddr = dp->p_addr; 3632395Swnj s = spl5(); 36417Sbill if (tp->t_state & (TIMEOUT|BUSY|TTSTOP)) 36517Sbill goto out; 366921Sbill if (tp->t_state&ASLEEP && tp->t_outq.c_cc <= TTLOWAT(tp)) { 36717Sbill tp->t_state &= ~ASLEEP; 36817Sbill if (tp->t_chan) 36917Sbill mcstart(tp->t_chan, (caddr_t)&tp->t_outq); 37017Sbill else 37117Sbill wakeup((caddr_t)&tp->t_outq); 37217Sbill } 37317Sbill if (tp->t_outq.c_cc == 0) 37417Sbill goto out; 375*3819Swnj if (tp->t_flags&RAW || tp->t_local&LLITOUT) 37617Sbill cc = ndqb(&tp->t_outq, 0); 37717Sbill else { 37817Sbill cc = ndqb(&tp->t_outq, 0200); 37917Sbill if (cc == 0) { 38017Sbill cc = getc(&tp->t_outq); 3812469Swnj timeout(ttrstrt, (caddr_t)tp, (cc&0x7f) + 6); 38217Sbill tp->t_state |= TIMEOUT; 38317Sbill goto out; 38417Sbill } 38517Sbill } 38617Sbill tp->t_state |= BUSY; 38717Sbill dp->p_end = dp->p_mem = tp->t_outq.c_cf; 38817Sbill dp->p_end += cc; 3892469Swnj dzaddr->dztcr |= 1 << (minor(tp->t_dev) & 07); /* force intr */ 3902395Swnj out: 3912395Swnj splx(s); 39217Sbill } 39317Sbill 39417Sbill /* 39517Sbill * Stop output on a line. 39617Sbill */ 39717Sbill /*ARGSUSED*/ 39817Sbill dzstop(tp, flag) 3992395Swnj register struct tty *tp; 40017Sbill { 40117Sbill register struct pdma *dp; 40217Sbill register int s; 40317Sbill 4042395Swnj dp = (struct pdma *)tp->t_addr; 4052457Swnj s = spl5(); 40617Sbill if (tp->t_state & BUSY) { 40717Sbill dp->p_end = dp->p_mem; 4082395Swnj if ((tp->t_state&TTSTOP)==0) 40917Sbill tp->t_state |= FLUSH; 41017Sbill } 41117Sbill splx(s); 41217Sbill } 41317Sbill 4142395Swnj dzmodem(unit, flag) 4152395Swnj register int unit; 41617Sbill { 41717Sbill register struct device *dzaddr; 41817Sbill register char bit; 41917Sbill 4202395Swnj dzaddr = dzpdma[unit].p_addr; 4212395Swnj bit = 1<<(unit&07); 4222469Swnj if (flag == DZ_OFF) 42317Sbill dzaddr->dzdtr &= ~bit; 42417Sbill else 42517Sbill dzaddr->dzdtr |= bit; 42617Sbill } 42717Sbill 42817Sbill dzscan() 42917Sbill { 43017Sbill register i; 43117Sbill register struct device *dzaddr; 43217Sbill register bit; 43317Sbill register struct tty *tp; 43417Sbill 43517Sbill for (i = 0; i < dz_cnt ; i++) { 43617Sbill dzaddr = dzpdma[i].p_addr; 4372627Swnj if (dzaddr == 0) 4382627Swnj continue; 43917Sbill tp = &dz_tty[i]; 44017Sbill bit = 1<<(i&07); 4412606Swnj if ((dzsoftCAR[i>>3]&bit) || (dzaddr->dzmsr&bit)) { 44217Sbill /* carrier present */ 44317Sbill if ((tp->t_state & CARR_ON) == 0) { 44417Sbill wakeup((caddr_t)&tp->t_rawq); 44517Sbill tp->t_state |= CARR_ON; 44617Sbill } 44717Sbill } else { 4482469Swnj if ((tp->t_state&CARR_ON) && 4492469Swnj (tp->t_local&LNOHANG)==0) { 45017Sbill /* carrier lost */ 451882Sbill if (tp->t_state&ISOPEN) { 452170Sbill gsignal(tp->t_pgrp, SIGHUP); 453205Sbill gsignal(tp->t_pgrp, SIGCONT); 454170Sbill dzaddr->dzdtr &= ~bit; 455871Sbill flushtty(tp, FREAD|FWRITE); 456170Sbill } 457170Sbill tp->t_state &= ~CARR_ON; 45817Sbill } 45917Sbill } 46017Sbill } 4612756Swnj timeout(dzscan, (caddr_t)0, 2*hz); 46217Sbill } 463119Sbill 464119Sbill dztimer() 465119Sbill { 4662457Swnj int dz; 467119Sbill 4682645Swnj for (dz = 0; dz < NDZ; dz++) 4692457Swnj dzrint(dz); 470119Sbill } 471281Sbill 472281Sbill /* 473281Sbill * Reset state of driver if UBA reset was necessary. 474301Sbill * Reset parameters and restart transmission on open lines. 475281Sbill */ 4762395Swnj dzreset(uban) 4772422Skre int uban; 478281Sbill { 4792395Swnj register int unit; 480281Sbill register struct tty *tp; 4812976Swnj register struct uba_device *ui; 482281Sbill 4832645Swnj for (unit = 0; unit < NDZLINE; unit++) { 4842422Skre ui = dzinfo[unit >> 3]; 4852422Skre if (ui == 0 || ui->ui_ubanum != uban || ui->ui_alive == 0) 4862422Skre continue; 4872923Swnj if (unit%8 == 0) 4882923Swnj printf(" dz%d", unit>>3); 4892395Swnj tp = &dz_tty[unit]; 490281Sbill if (tp->t_state & (ISOPEN|WOPEN)) { 4912395Swnj dzparam(unit); 4922469Swnj dzmodem(unit, DZ_ON); 493301Sbill tp->t_state &= ~BUSY; 494301Sbill dzstart(tp); 495281Sbill } 496281Sbill } 497281Sbill dztimer(); 498281Sbill } 4991562Sbill #endif 500