1*5407Swnj /* dz.c 4.32 82/01/14 */ 217Sbill 31935Swnj #include "dz.h" 42645Swnj #if NDZ > 0 517Sbill /* 64933Swnj * 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" 25145Sbill 262469Swnj /* 272469Swnj * Driver information for auto-configuration stuff. 282469Swnj */ 292606Swnj int dzprobe(), dzattach(), dzrint(); 302976Swnj struct uba_device *dzinfo[NDZ]; 312395Swnj u_short dzstd[] = { 0 }; 322395Swnj struct uba_driver dzdriver = 332606Swnj { dzprobe, 0, dzattach, 0, dzstd, "dz", dzinfo }; 342395Swnj 352645Swnj #define NDZLINE (NDZ*8) 3617Sbill 372469Swnj /* 382469Swnj * Registers and bits 392469Swnj */ 402469Swnj 412469Swnj /* Bits in dzlpr */ 422457Swnj #define BITS7 020 432457Swnj #define BITS8 030 442457Swnj #define TWOSB 040 452457Swnj #define PENABLE 0100 462457Swnj #define OPAR 0200 4717Sbill 482469Swnj /* Bits in dzrbuf */ 492469Swnj #define DZ_PE 010000 502469Swnj #define DZ_FE 020000 512469Swnj #define DZ_DO 040000 522469Swnj 532469Swnj /* Bits in dzcsr */ 542469Swnj #define DZ_CLR 020 /* Reset dz */ 552469Swnj #define DZ_MSE 040 /* Master Scan Enable */ 562469Swnj #define DZ_RIE 0100 /* Receiver Interrupt Enable */ 572469Swnj #define DZ_SAE 010000 /* Silo Alarm Enable */ 582469Swnj #define DZ_TIE 040000 /* Transmit Interrupt Enable */ 593440Sroot #define DZ_IEN (DZ_MSE|DZ_RIE|DZ_TIE|DZ_SAE) 602469Swnj 612469Swnj /* Flags for modem-control */ 622469Swnj #define DZ_ON 1 632469Swnj #define DZ_OFF 0 6417Sbill 652469Swnj int dzstart(), dzxint(), dzdma(); 66114Sbill int ttrstrt(); 672645Swnj struct tty dz_tty[NDZLINE]; 682645Swnj int dz_cnt = { NDZLINE }; 69119Sbill int dzact; 7017Sbill 7117Sbill struct device { 722469Swnj short dzcsr; /* control-status register */ 732469Swnj short dzrbuf; /* receiver buffer */ 742469Swnj #define dzlpr dzrbuf /* line parameter reg is write of dzrbuf */ 752469Swnj char dztcr; /* transmit control register */ 762469Swnj char dzdtr; /* data terminal ready */ 772469Swnj char dztbuf; /* transmit buffer */ 782469Swnj char dzbrk; /* break control */ 792469Swnj #define dzmsr dzbrk /* modem status register */ 8017Sbill }; 812469Swnj /* 822469Swnj * Software copy of dzbrk since it isn't readable 832469Swnj */ 842645Swnj char dz_brk[NDZ]; 852645Swnj char dzsoftCAR[NDZ]; 8617Sbill 872469Swnj /* 882469Swnj * The dz doesn't interrupt on carrier transitions, so 892469Swnj * we have to use a timer to watch it. 902469Swnj */ 912469Swnj char dz_timer; /* timer started? */ 922469Swnj 932469Swnj /* 942469Swnj * Pdma structures for fast output code 952469Swnj */ 962645Swnj struct pdma dzpdma[NDZLINE]; 972469Swnj 982395Swnj char dz_speeds[] = 992395Swnj { 0,020,021,022,023,024,0,025,026,027,030,032,034,036,0,0 }; 10017Sbill 1012606Swnj dzprobe(reg) 1022395Swnj caddr_t reg; 1032395Swnj { 1042457Swnj register int br, cvec; 1052457Swnj register struct device *dzaddr = (struct device *)reg; 1062395Swnj 1072606Swnj #ifdef lint 1083102Swnj br = 0; cvec = br; br = cvec; 1094933Swnj dzrint(0); dzxint((struct tty *)0); 1102606Swnj #endif 1112469Swnj dzaddr->dzcsr = DZ_TIE|DZ_MSE; 1122422Skre dzaddr->dztcr = 1; /* enable any line */ 1132457Swnj DELAY(100000); 1142469Swnj dzaddr->dzcsr = DZ_CLR; /* reset everything */ 1152457Swnj if (cvec && cvec != 0x200) 1162457Swnj cvec -= 4; 1172457Swnj return (1); 1182395Swnj } 1192395Swnj 1202606Swnj dzattach(ui) 1212976Swnj register struct uba_device *ui; 1222395Swnj { 1232395Swnj register struct pdma *pdp = &dzpdma[ui->ui_unit*8]; 1242395Swnj register struct tty *tp = &dz_tty[ui->ui_unit*8]; 1252606Swnj register int cntr; 1262645Swnj extern dzscan(); 1272395Swnj 1282606Swnj for (cntr = 0; cntr < 8; cntr++) { 1292606Swnj pdp->p_addr = (struct device *)ui->ui_addr; 1302395Swnj pdp->p_arg = (int)tp; 1312395Swnj pdp->p_fcn = dzxint; 1322395Swnj pdp++, tp++; 1332395Swnj } 1342567Swnj dzsoftCAR[ui->ui_unit] = ui->ui_flags; 1352627Swnj if (dz_timer == 0) { 1362627Swnj dz_timer++; 1372756Swnj timeout(dzscan, (caddr_t)0, hz); 1382627Swnj } 1392395Swnj } 1402395Swnj 14117Sbill /*ARGSUSED*/ 1422395Swnj dzopen(dev, flag) 1432395Swnj dev_t dev; 14417Sbill { 14517Sbill register struct tty *tp; 1462395Swnj register int unit; 14717Sbill 1482395Swnj unit = minor(dev); 1492395Swnj if (unit >= dz_cnt || dzpdma[unit].p_addr == 0) { 15017Sbill u.u_error = ENXIO; 15117Sbill return; 15217Sbill } 1532395Swnj tp = &dz_tty[unit]; 1542395Swnj tp->t_addr = (caddr_t)&dzpdma[unit]; 15517Sbill tp->t_oproc = dzstart; 156*5407Swnj tp->t_state |= TS_WOPEN; 157*5407Swnj if ((tp->t_state & TS_ISOPEN) == 0) { 15817Sbill ttychars(tp); 1592469Swnj tp->t_ospeed = tp->t_ispeed = B300; 16017Sbill tp->t_flags = ODDP|EVENP|ECHO; 161*5407Swnj /* tp->t_state |= TS_HUPCLS; */ 1622395Swnj dzparam(unit); 163*5407Swnj } else if (tp->t_state&TS_XCLUDE && u.u_uid != 0) { 16417Sbill u.u_error = EBUSY; 16517Sbill return; 16617Sbill } 1672469Swnj dzmodem(unit, DZ_ON); 168114Sbill (void) spl5(); 169*5407Swnj while ((tp->t_state & TS_CARR_ON) == 0) { 170*5407Swnj tp->t_state |= TS_WOPEN; 17117Sbill sleep((caddr_t)&tp->t_rawq, TTIPRI); 17217Sbill } 173114Sbill (void) spl0(); 1742395Swnj (*linesw[tp->t_line].l_open)(dev, tp); 17517Sbill } 17617Sbill 1772395Swnj /*ARGSUSED*/ 1782395Swnj dzclose(dev, flag) 1792395Swnj dev_t dev; 18017Sbill { 18117Sbill register struct tty *tp; 1822395Swnj register int unit; 1832395Swnj int dz; 18417Sbill 1852395Swnj unit = minor(dev); 1862395Swnj dz = unit >> 3; 1872395Swnj tp = &dz_tty[unit]; 18817Sbill (*linesw[tp->t_line].l_close)(tp); 1892197Stoy ((struct pdma *)(tp->t_addr))->p_addr->dzbrk = 1902395Swnj (dz_brk[dz] &= ~(1 << (unit&07))); 191*5407Swnj if (tp->t_state & TS_HUPCLS) 1922469Swnj dzmodem(unit, DZ_OFF); 19317Sbill ttyclose(tp); 19417Sbill } 19517Sbill 1962395Swnj dzread(dev) 1972395Swnj dev_t dev; 19817Sbill { 19917Sbill register struct tty *tp; 20017Sbill 2012395Swnj tp = &dz_tty[minor(dev)]; 20217Sbill (*linesw[tp->t_line].l_read)(tp); 20317Sbill } 20417Sbill 2052395Swnj dzwrite(dev) 2062395Swnj dev_t dev; 20717Sbill { 20817Sbill register struct tty *tp; 20917Sbill 2102395Swnj tp = &dz_tty[minor(dev)]; 21117Sbill (*linesw[tp->t_line].l_write)(tp); 21217Sbill } 21317Sbill 214119Sbill /*ARGSUSED*/ 2152395Swnj dzrint(dz) 2162395Swnj int dz; 21717Sbill { 21817Sbill register struct tty *tp; 21917Sbill register int c; 22017Sbill register struct device *dzaddr; 221119Sbill register struct tty *tp0; 2222395Swnj register int unit; 2232923Swnj int overrun = 0; 22417Sbill 2252457Swnj if ((dzact & (1<<dz)) == 0) 2262457Swnj return; 2272457Swnj unit = dz * 8; 2282457Swnj dzaddr = dzpdma[unit].p_addr; 2292457Swnj tp0 = &dz_tty[unit]; 2302457Swnj while ((c = dzaddr->dzrbuf) < 0) { /* char present */ 2312457Swnj tp = tp0 + ((c>>8)&07); 2322457Swnj if (tp >= &dz_tty[dz_cnt]) 23317Sbill continue; 234*5407Swnj if ((tp->t_state & TS_ISOPEN) == 0) { 2352457Swnj wakeup((caddr_t)&tp->t_rawq); 2362457Swnj continue; 2372457Swnj } 2382469Swnj if (c&DZ_FE) 2392457Swnj if (tp->t_flags & RAW) 2402469Swnj c = 0; 2412457Swnj else 2422457Swnj c = tun.t_intrc; 2432923Swnj if (c&DZ_DO && overrun == 0) { 2442923Swnj printf("dz%d: silo overflow\n", dz); 2452923Swnj overrun = 1; 2462923Swnj } 2472469Swnj if (c&DZ_PE) 2482457Swnj if (((tp->t_flags & (EVENP|ODDP)) == EVENP) 2492457Swnj || ((tp->t_flags & (EVENP|ODDP)) == ODDP)) 25017Sbill continue; 2512731Swnj #if NBK > 0 2522457Swnj if (tp->t_line == NETLDISC) { 2532457Swnj c &= 0177; 2542457Swnj BKINPUT(c, tp); 2552457Swnj } else 2562731Swnj #endif 2572457Swnj (*linesw[tp->t_line].l_rint)(c, tp); 25817Sbill } 25917Sbill } 26017Sbill 26117Sbill /*ARGSUSED*/ 26217Sbill dzioctl(dev, cmd, addr, flag) 2632395Swnj dev_t dev; 2642395Swnj caddr_t addr; 26517Sbill { 26617Sbill register struct tty *tp; 2672395Swnj register int unit = minor(dev); 2682395Swnj register int dz = unit >> 3; 26917Sbill 2702395Swnj tp = &dz_tty[unit]; 271114Sbill cmd = (*linesw[tp->t_line].l_ioctl)(tp, cmd, addr); 272114Sbill if (cmd == 0) 273114Sbill return; 2741896Swnj if (ttioctl(tp, cmd, addr, flag)) { 27517Sbill if (cmd==TIOCSETP || cmd==TIOCSETN) 2762395Swnj dzparam(unit); 277170Sbill } else switch(cmd) { 2782395Swnj 279170Sbill case TIOCSBRK: 280882Sbill ((struct pdma *)(tp->t_addr))->p_addr->dzbrk = 2812395Swnj (dz_brk[dz] |= 1 << (unit&07)); 282170Sbill break; 283170Sbill case TIOCCBRK: 284882Sbill ((struct pdma *)(tp->t_addr))->p_addr->dzbrk = 2852395Swnj (dz_brk[dz] &= ~(1 << (unit&07))); 286170Sbill break; 287170Sbill case TIOCSDTR: 2882469Swnj dzmodem(unit, DZ_ON); 289170Sbill break; 290170Sbill case TIOCCDTR: 2912469Swnj dzmodem(unit, DZ_OFF); 292170Sbill break; 293170Sbill default: 29417Sbill u.u_error = ENOTTY; 295170Sbill } 29617Sbill } 29717Sbill 2982395Swnj dzparam(unit) 2992395Swnj register int unit; 30017Sbill { 30117Sbill register struct tty *tp; 30217Sbill register struct device *dzaddr; 3032395Swnj register int lpr; 30417Sbill 3052395Swnj tp = &dz_tty[unit]; 3062395Swnj dzaddr = dzpdma[unit].p_addr; 30717Sbill dzaddr->dzcsr = DZ_IEN; 3082395Swnj dzact |= (1<<(unit>>3)); 30917Sbill if (tp->t_ispeed == 0) { 3102469Swnj dzmodem(unit, DZ_OFF); /* hang up line */ 31117Sbill return; 31217Sbill } 3132395Swnj lpr = (dz_speeds[tp->t_ispeed]<<8) | (unit & 07); 3142296Swnj if ((tp->t_local&LLITOUT) || (tp->t_flags&RAW)) 31517Sbill lpr |= BITS8; 31617Sbill else 31717Sbill lpr |= (BITS7|PENABLE); 31817Sbill if ((tp->t_flags & EVENP) == 0) 31917Sbill lpr |= OPAR; 3202469Swnj if (tp->t_ispeed == B110) 3212469Swnj lpr |= TWOSB; 32217Sbill dzaddr->dzlpr = lpr; 32317Sbill } 32417Sbill 32517Sbill dzxint(tp) 3262395Swnj register struct tty *tp; 32717Sbill { 32817Sbill register struct pdma *dp; 329145Sbill register s; 33017Sbill 3312469Swnj s = spl5(); /* block pdma interrupts */ 3322395Swnj dp = (struct pdma *)tp->t_addr; 333*5407Swnj tp->t_state &= ~TS_BUSY; 334*5407Swnj if (tp->t_state & TS_FLUSH) 335*5407Swnj tp->t_state &= ~TS_FLUSH; 33617Sbill else 337281Sbill ndflush(&tp->t_outq, dp->p_mem-tp->t_outq.c_cf); 33817Sbill if (tp->t_line) 33917Sbill (*linesw[tp->t_line].l_start)(tp); 34017Sbill else 34117Sbill dzstart(tp); 342*5407Swnj if (tp->t_outq.c_cc == 0 || (tp->t_state&TS_BUSY)==0) 3432395Swnj dp->p_addr->dztcr &= ~(1 << (minor(tp->t_dev)&07)); 344145Sbill splx(s); 34517Sbill } 34617Sbill 34717Sbill dzstart(tp) 3482395Swnj register struct tty *tp; 34917Sbill { 35017Sbill register struct pdma *dp; 35117Sbill register struct device *dzaddr; 3522395Swnj register int cc; 3532395Swnj int s; 35417Sbill 3552395Swnj dp = (struct pdma *)tp->t_addr; 35617Sbill dzaddr = dp->p_addr; 3572395Swnj s = spl5(); 358*5407Swnj if (tp->t_state & (TS_TIMEOUT|TS_BUSY|TS_TTSTOP)) 35917Sbill goto out; 360*5407Swnj if (tp->t_outq.c_cc <= TTLOWAT(tp)) { 361*5407Swnj if (tp->t_state&TS_ASLEEP) { 362*5407Swnj tp->t_state &= ~TS_ASLEEP; 363*5407Swnj wakeup((caddr_t)&tp->t_outq); 364*5407Swnj } 365*5407Swnj if (tp->t_wsel) { 366*5407Swnj selwakeup(tp->t_wsel, tp->t_state & TS_WCOLL); 367*5407Swnj tp->t_wsel = 0; 368*5407Swnj tp->t_state &= ~TS_WCOLL; 369*5407Swnj } 37017Sbill } 37117Sbill if (tp->t_outq.c_cc == 0) 37217Sbill goto out; 3733819Swnj if (tp->t_flags&RAW || tp->t_local&LLITOUT) 37417Sbill cc = ndqb(&tp->t_outq, 0); 37517Sbill else { 37617Sbill cc = ndqb(&tp->t_outq, 0200); 37717Sbill if (cc == 0) { 37817Sbill cc = getc(&tp->t_outq); 3792469Swnj timeout(ttrstrt, (caddr_t)tp, (cc&0x7f) + 6); 380*5407Swnj tp->t_state |= TS_TIMEOUT; 38117Sbill goto out; 38217Sbill } 38317Sbill } 384*5407Swnj tp->t_state |= TS_BUSY; 38517Sbill dp->p_end = dp->p_mem = tp->t_outq.c_cf; 38617Sbill dp->p_end += cc; 3872469Swnj dzaddr->dztcr |= 1 << (minor(tp->t_dev) & 07); /* force intr */ 3882395Swnj out: 3892395Swnj splx(s); 39017Sbill } 39117Sbill 39217Sbill /* 39317Sbill * Stop output on a line. 39417Sbill */ 39517Sbill /*ARGSUSED*/ 39617Sbill dzstop(tp, flag) 3972395Swnj register struct tty *tp; 39817Sbill { 39917Sbill register struct pdma *dp; 40017Sbill register int s; 40117Sbill 4022395Swnj dp = (struct pdma *)tp->t_addr; 4032457Swnj s = spl5(); 404*5407Swnj if (tp->t_state & TS_BUSY) { 40517Sbill dp->p_end = dp->p_mem; 406*5407Swnj if ((tp->t_state&TS_TTSTOP)==0) 407*5407Swnj tp->t_state |= TS_FLUSH; 40817Sbill } 40917Sbill splx(s); 41017Sbill } 41117Sbill 4122395Swnj dzmodem(unit, flag) 4132395Swnj register int unit; 41417Sbill { 41517Sbill register struct device *dzaddr; 41617Sbill register char bit; 41717Sbill 4182395Swnj dzaddr = dzpdma[unit].p_addr; 4192395Swnj bit = 1<<(unit&07); 4202469Swnj if (flag == DZ_OFF) 42117Sbill dzaddr->dzdtr &= ~bit; 42217Sbill else 42317Sbill dzaddr->dzdtr |= bit; 42417Sbill } 42517Sbill 42617Sbill dzscan() 42717Sbill { 42817Sbill register i; 42917Sbill register struct device *dzaddr; 43017Sbill register bit; 43117Sbill register struct tty *tp; 43217Sbill 43317Sbill for (i = 0; i < dz_cnt ; i++) { 43417Sbill dzaddr = dzpdma[i].p_addr; 4352627Swnj if (dzaddr == 0) 4362627Swnj continue; 43717Sbill tp = &dz_tty[i]; 43817Sbill bit = 1<<(i&07); 4392606Swnj if ((dzsoftCAR[i>>3]&bit) || (dzaddr->dzmsr&bit)) { 44017Sbill /* carrier present */ 441*5407Swnj if ((tp->t_state & TS_CARR_ON) == 0) { 44217Sbill wakeup((caddr_t)&tp->t_rawq); 443*5407Swnj tp->t_state |= TS_CARR_ON; 44417Sbill } 44517Sbill } else { 446*5407Swnj if ((tp->t_state&TS_CARR_ON) && 4472469Swnj (tp->t_local&LNOHANG)==0) { 44817Sbill /* carrier lost */ 449*5407Swnj if (tp->t_state&TS_ISOPEN) { 450170Sbill gsignal(tp->t_pgrp, SIGHUP); 451205Sbill gsignal(tp->t_pgrp, SIGCONT); 452170Sbill dzaddr->dzdtr &= ~bit; 453871Sbill flushtty(tp, FREAD|FWRITE); 454170Sbill } 455*5407Swnj tp->t_state &= ~TS_CARR_ON; 45617Sbill } 45717Sbill } 45817Sbill } 4592756Swnj timeout(dzscan, (caddr_t)0, 2*hz); 46017Sbill } 461119Sbill 462119Sbill dztimer() 463119Sbill { 4642457Swnj int dz; 465119Sbill 4662645Swnj for (dz = 0; dz < NDZ; dz++) 4672457Swnj dzrint(dz); 468119Sbill } 469281Sbill 470281Sbill /* 471281Sbill * Reset state of driver if UBA reset was necessary. 472301Sbill * Reset parameters and restart transmission on open lines. 473281Sbill */ 4742395Swnj dzreset(uban) 4752422Skre int uban; 476281Sbill { 4772395Swnj register int unit; 478281Sbill register struct tty *tp; 4792976Swnj register struct uba_device *ui; 480281Sbill 4812645Swnj for (unit = 0; unit < NDZLINE; unit++) { 4822422Skre ui = dzinfo[unit >> 3]; 4832422Skre if (ui == 0 || ui->ui_ubanum != uban || ui->ui_alive == 0) 4842422Skre continue; 4852923Swnj if (unit%8 == 0) 4862923Swnj printf(" dz%d", unit>>3); 4872395Swnj tp = &dz_tty[unit]; 488*5407Swnj if (tp->t_state & (TS_ISOPEN|TS_WOPEN)) { 4892395Swnj dzparam(unit); 4902469Swnj dzmodem(unit, DZ_ON); 491*5407Swnj tp->t_state &= ~TS_BUSY; 492301Sbill dzstart(tp); 493281Sbill } 494281Sbill } 495281Sbill dztimer(); 496281Sbill } 4971562Sbill #endif 498