1*2567Swnj /* dz.c 4.14 02/19/81 */ 217Sbill 31935Swnj #include "dz.h" 41562Sbill #if NDZ11 > 0 52457Swnj #define DELAY(i) { register int j = i; while (--j > 0); } 617Sbill /* 717Sbill * DZ-11 Driver 82469Swnj * 92469Swnj * This driver mimics dh.c; see it for explanation of common code. 1017Sbill */ 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" 19*2567Swnj #include "../h/vm.h" 2017Sbill #include "../h/uba.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 */ 302395Swnj int dzcntrlr(), dzslave(), dzrint(); 312395Swnj struct uba_dinfo *dzinfo[NDZ11]; 322395Swnj u_short dzstd[] = { 0 }; 332395Swnj struct uba_driver dzdriver = 342457Swnj { dzcntrlr, dzslave, 0, 0, dzstd, "dz", dzinfo }; 352395Swnj 362457Swnj #define NDZ (NDZ11*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 */ 602469Swnj #define DZ_IEN (DZ_MSE+DZ_RIE+DZ_TIE+DZ_SAE) 612469Swnj 622469Swnj /* Flags for modem-control */ 632469Swnj #define DZ_ON 1 642469Swnj #define DZ_OFF 0 6517Sbill 662469Swnj int dzstart(), dzxint(), dzdma(); 67114Sbill int ttrstrt(); 6817Sbill struct tty dz_tty[NDZ]; 6917Sbill int dz_cnt = { NDZ }; 70119Sbill int dzact; 7117Sbill 7217Sbill struct device { 732469Swnj short dzcsr; /* control-status register */ 742469Swnj short dzrbuf; /* receiver buffer */ 752469Swnj #define dzlpr dzrbuf /* line parameter reg is write of dzrbuf */ 762469Swnj char dztcr; /* transmit control register */ 772469Swnj char dzdtr; /* data terminal ready */ 782469Swnj char dztbuf; /* transmit buffer */ 792469Swnj char dzbrk; /* break control */ 802469Swnj #define dzmsr dzbrk /* modem status register */ 8117Sbill }; 822469Swnj /* 832469Swnj * Software copy of dzbrk since it isn't readable 842469Swnj */ 852469Swnj char dz_brk[NDZ11]; 86*2567Swnj char dzsoftCAR[NDZ11]; 8717Sbill 882469Swnj /* 892469Swnj * The dz doesn't interrupt on carrier transitions, so 902469Swnj * we have to use a timer to watch it. 912469Swnj */ 922469Swnj char dz_timer; /* timer started? */ 932469Swnj 942469Swnj /* 952469Swnj * Pdma structures for fast output code 962469Swnj */ 972395Swnj struct pdma dzpdma[NDZ]; 982469Swnj 992395Swnj char dz_speeds[] = 1002395Swnj { 0,020,021,022,023,024,0,025,026,027,030,032,034,036,0,0 }; 10117Sbill 1022395Swnj dzcntrlr(ui, reg) 1032395Swnj struct uba_dinfo *ui; 1042395Swnj caddr_t reg; 1052395Swnj { 1062457Swnj register int br, cvec; 1072457Swnj register struct device *dzaddr = (struct device *)reg; 1082395Swnj 1092469Swnj dzaddr->dzcsr = DZ_TIE|DZ_MSE; 1102422Skre dzaddr->dztcr = 1; /* enable any line */ 1112457Swnj DELAY(100000); 1122469Swnj dzaddr->dzcsr = DZ_CLR; /* reset everything */ 1132457Swnj if (cvec && cvec != 0x200) 1142457Swnj cvec -= 4; 1152457Swnj return (1); 1162395Swnj } 1172395Swnj 1182469Swnj /* 1192469Swnj * Called by auto-configure to initialize good dz's; 1202469Swnj * set up pdma structures. 1212469Swnj */ 122*2567Swnj dzslave(ui, reg) 1232395Swnj register struct uba_dinfo *ui; 1242395Swnj caddr_t reg; 1252395Swnj { 1262395Swnj register struct pdma *pdp = &dzpdma[ui->ui_unit*8]; 1272395Swnj register struct tty *tp = &dz_tty[ui->ui_unit*8]; 1282395Swnj register int cnt; 1292395Swnj 1302395Swnj for (cnt = 0; cnt < 8; cnt++) { 1312395Swnj pdp->p_addr = (struct device *)reg; 1322395Swnj pdp->p_arg = (int)tp; 1332395Swnj pdp->p_fcn = dzxint; 1342395Swnj pdp++, tp++; 1352395Swnj } 136*2567Swnj dzsoftCAR[ui->ui_unit] = ui->ui_flags; 1372395Swnj return (1); 1382395Swnj } 1392395Swnj 14017Sbill /*ARGSUSED*/ 1412395Swnj dzopen(dev, flag) 1422395Swnj dev_t dev; 14317Sbill { 14417Sbill register struct tty *tp; 1452395Swnj register int unit; 14617Sbill extern dzscan(); 14717Sbill 1482395Swnj unit = minor(dev); 1492395Swnj if (unit >= dz_cnt || dzpdma[unit].p_addr == 0) { 15017Sbill u.u_error = ENXIO; 15117Sbill return; 15217Sbill } 15317Sbill if (dz_timer == 0) { 15417Sbill dz_timer++; 1552469Swnj timeout(dzscan, (caddr_t)0, HZ); 15617Sbill } 1572395Swnj tp = &dz_tty[unit]; 1582395Swnj tp->t_addr = (caddr_t)&dzpdma[unit]; 15917Sbill tp->t_oproc = dzstart; 16017Sbill tp->t_iproc = NULL; 16117Sbill tp->t_state |= WOPEN; 16217Sbill if ((tp->t_state & ISOPEN) == 0) { 16317Sbill ttychars(tp); 1642469Swnj tp->t_ospeed = tp->t_ispeed = B300; 16517Sbill tp->t_flags = ODDP|EVENP|ECHO; 1662469Swnj /* tp->t_state |= HUPCLS; */ 1672395Swnj dzparam(unit); 16817Sbill } else if (tp->t_state&XCLUDE && u.u_uid != 0) { 16917Sbill u.u_error = EBUSY; 17017Sbill return; 17117Sbill } 1722469Swnj dzmodem(unit, DZ_ON); 173114Sbill (void) spl5(); 17417Sbill while ((tp->t_state & CARR_ON) == 0) { 17517Sbill tp->t_state |= WOPEN; 17617Sbill sleep((caddr_t)&tp->t_rawq, TTIPRI); 17717Sbill } 178114Sbill (void) spl0(); 1792395Swnj (*linesw[tp->t_line].l_open)(dev, tp); 18017Sbill } 18117Sbill 1822395Swnj /*ARGSUSED*/ 1832395Swnj dzclose(dev, flag) 1842395Swnj dev_t dev; 18517Sbill { 18617Sbill register struct tty *tp; 1872395Swnj register int unit; 1882395Swnj int dz; 18917Sbill 1902395Swnj unit = minor(dev); 1912395Swnj dz = unit >> 3; 1922395Swnj tp = &dz_tty[unit]; 19317Sbill (*linesw[tp->t_line].l_close)(tp); 1942197Stoy ((struct pdma *)(tp->t_addr))->p_addr->dzbrk = 1952395Swnj (dz_brk[dz] &= ~(1 << (unit&07))); 19617Sbill if (tp->t_state & HUPCLS) 1972469Swnj dzmodem(unit, DZ_OFF); 19817Sbill ttyclose(tp); 19917Sbill } 20017Sbill 2012395Swnj dzread(dev) 2022395Swnj dev_t dev; 20317Sbill { 20417Sbill register struct tty *tp; 20517Sbill 2062395Swnj tp = &dz_tty[minor(dev)]; 20717Sbill (*linesw[tp->t_line].l_read)(tp); 20817Sbill } 20917Sbill 2102395Swnj dzwrite(dev) 2112395Swnj dev_t dev; 21217Sbill { 21317Sbill register struct tty *tp; 21417Sbill 2152395Swnj tp = &dz_tty[minor(dev)]; 21617Sbill (*linesw[tp->t_line].l_write)(tp); 21717Sbill } 21817Sbill 219119Sbill /*ARGSUSED*/ 2202395Swnj dzrint(dz) 2212395Swnj int dz; 22217Sbill { 22317Sbill register struct tty *tp; 22417Sbill register int c; 22517Sbill register struct device *dzaddr; 226119Sbill register struct tty *tp0; 2272395Swnj register int unit; 228140Sbill int s; 22917Sbill 2302457Swnj if ((dzact & (1<<dz)) == 0) 2312457Swnj return; 2322457Swnj unit = dz * 8; 2332457Swnj dzaddr = dzpdma[unit].p_addr; 2342457Swnj tp0 = &dz_tty[unit]; 2352457Swnj while ((c = dzaddr->dzrbuf) < 0) { /* char present */ 2362457Swnj tp = tp0 + ((c>>8)&07); 2372457Swnj if (tp >= &dz_tty[dz_cnt]) 23817Sbill continue; 2392457Swnj if ((tp->t_state & ISOPEN) == 0) { 2402457Swnj wakeup((caddr_t)&tp->t_rawq); 2412457Swnj continue; 2422457Swnj } 2432469Swnj if (c&DZ_FE) 2442457Swnj if (tp->t_flags & RAW) 2452469Swnj c = 0; 2462457Swnj else 2472457Swnj c = tun.t_intrc; 2482469Swnj if (c&DZ_DO) 2492457Swnj printf("o"); 2502469Swnj if (c&DZ_PE) 2512457Swnj if (((tp->t_flags & (EVENP|ODDP)) == EVENP) 2522457Swnj || ((tp->t_flags & (EVENP|ODDP)) == ODDP)) 25317Sbill continue; 2542457Swnj if (tp->t_line == NETLDISC) { 2552457Swnj c &= 0177; 2562457Swnj BKINPUT(c, tp); 2572457Swnj } else 2582457Swnj (*linesw[tp->t_line].l_rint)(c, tp); 25917Sbill } 26017Sbill } 26117Sbill 26217Sbill /*ARGSUSED*/ 26317Sbill dzioctl(dev, cmd, addr, flag) 2642395Swnj dev_t dev; 2652395Swnj caddr_t addr; 26617Sbill { 26717Sbill register struct tty *tp; 2682395Swnj register int unit = minor(dev); 2692395Swnj register int dz = unit >> 3; 27017Sbill 2712395Swnj tp = &dz_tty[unit]; 272114Sbill cmd = (*linesw[tp->t_line].l_ioctl)(tp, cmd, addr); 273114Sbill if (cmd == 0) 274114Sbill return; 2751896Swnj if (ttioctl(tp, cmd, addr, flag)) { 27617Sbill if (cmd==TIOCSETP || cmd==TIOCSETN) 2772395Swnj dzparam(unit); 278170Sbill } else switch(cmd) { 2792395Swnj 280170Sbill case TIOCSBRK: 281882Sbill ((struct pdma *)(tp->t_addr))->p_addr->dzbrk = 2822395Swnj (dz_brk[dz] |= 1 << (unit&07)); 283170Sbill break; 284170Sbill case TIOCCBRK: 285882Sbill ((struct pdma *)(tp->t_addr))->p_addr->dzbrk = 2862395Swnj (dz_brk[dz] &= ~(1 << (unit&07))); 287170Sbill break; 288170Sbill case TIOCSDTR: 2892469Swnj dzmodem(unit, DZ_ON); 290170Sbill break; 291170Sbill case TIOCCDTR: 2922469Swnj dzmodem(unit, DZ_OFF); 293170Sbill break; 294170Sbill default: 29517Sbill u.u_error = ENOTTY; 296170Sbill } 29717Sbill } 29817Sbill 2992395Swnj dzparam(unit) 3002395Swnj register int unit; 30117Sbill { 30217Sbill register struct tty *tp; 30317Sbill register struct device *dzaddr; 3042395Swnj register int lpr; 30517Sbill 3062395Swnj tp = &dz_tty[unit]; 3072395Swnj dzaddr = dzpdma[unit].p_addr; 30817Sbill dzaddr->dzcsr = DZ_IEN; 3092395Swnj dzact |= (1<<(unit>>3)); 31017Sbill if (tp->t_ispeed == 0) { 3112469Swnj dzmodem(unit, DZ_OFF); /* hang up line */ 31217Sbill return; 31317Sbill } 3142395Swnj lpr = (dz_speeds[tp->t_ispeed]<<8) | (unit & 07); 3152296Swnj if ((tp->t_local&LLITOUT) || (tp->t_flags&RAW)) 31617Sbill lpr |= BITS8; 31717Sbill else 31817Sbill lpr |= (BITS7|PENABLE); 31917Sbill if ((tp->t_flags & EVENP) == 0) 32017Sbill lpr |= OPAR; 3212469Swnj if (tp->t_ispeed == B110) 3222469Swnj lpr |= TWOSB; 32317Sbill dzaddr->dzlpr = lpr; 32417Sbill } 32517Sbill 32617Sbill dzxint(tp) 3272395Swnj register struct tty *tp; 32817Sbill { 32917Sbill register struct pdma *dp; 330145Sbill register s; 33117Sbill 3322469Swnj s = spl5(); /* block pdma interrupts */ 3332395Swnj dp = (struct pdma *)tp->t_addr; 33417Sbill tp->t_state &= ~BUSY; 33517Sbill if (tp->t_state & FLUSH) 33617Sbill tp->t_state &= ~FLUSH; 33717Sbill else 338281Sbill ndflush(&tp->t_outq, dp->p_mem-tp->t_outq.c_cf); 33917Sbill if (tp->t_line) 34017Sbill (*linesw[tp->t_line].l_start)(tp); 34117Sbill else 34217Sbill dzstart(tp); 34317Sbill if (tp->t_outq.c_cc == 0 || (tp->t_state&BUSY)==0) 3442395Swnj dp->p_addr->dztcr &= ~(1 << (minor(tp->t_dev)&07)); 345145Sbill splx(s); 34617Sbill } 34717Sbill 34817Sbill dzstart(tp) 3492395Swnj register struct tty *tp; 35017Sbill { 35117Sbill register struct pdma *dp; 35217Sbill register struct device *dzaddr; 3532395Swnj register int cc; 3542395Swnj int s; 35517Sbill 3562395Swnj dp = (struct pdma *)tp->t_addr; 35717Sbill dzaddr = dp->p_addr; 3582395Swnj s = spl5(); 35917Sbill if (tp->t_state & (TIMEOUT|BUSY|TTSTOP)) 36017Sbill goto out; 361921Sbill if (tp->t_state&ASLEEP && tp->t_outq.c_cc <= TTLOWAT(tp)) { 36217Sbill tp->t_state &= ~ASLEEP; 36317Sbill if (tp->t_chan) 36417Sbill mcstart(tp->t_chan, (caddr_t)&tp->t_outq); 36517Sbill else 36617Sbill wakeup((caddr_t)&tp->t_outq); 36717Sbill } 36817Sbill if (tp->t_outq.c_cc == 0) 36917Sbill goto out; 37017Sbill if (tp->t_flags&RAW) 37117Sbill cc = ndqb(&tp->t_outq, 0); 37217Sbill else { 37317Sbill cc = ndqb(&tp->t_outq, 0200); 37417Sbill if (cc == 0) { 37517Sbill cc = getc(&tp->t_outq); 3762469Swnj timeout(ttrstrt, (caddr_t)tp, (cc&0x7f) + 6); 37717Sbill tp->t_state |= TIMEOUT; 37817Sbill goto out; 37917Sbill } 38017Sbill } 38117Sbill tp->t_state |= BUSY; 38217Sbill dp->p_end = dp->p_mem = tp->t_outq.c_cf; 38317Sbill dp->p_end += cc; 3842469Swnj dzaddr->dztcr |= 1 << (minor(tp->t_dev) & 07); /* force intr */ 3852395Swnj out: 3862395Swnj splx(s); 38717Sbill } 38817Sbill 38917Sbill /* 39017Sbill * Stop output on a line. 39117Sbill */ 39217Sbill /*ARGSUSED*/ 39317Sbill dzstop(tp, flag) 3942395Swnj register struct tty *tp; 39517Sbill { 39617Sbill register struct pdma *dp; 39717Sbill register int s; 39817Sbill 3992395Swnj dp = (struct pdma *)tp->t_addr; 4002457Swnj s = spl5(); 40117Sbill if (tp->t_state & BUSY) { 40217Sbill dp->p_end = dp->p_mem; 4032395Swnj if ((tp->t_state&TTSTOP)==0) 40417Sbill tp->t_state |= FLUSH; 40517Sbill } 40617Sbill splx(s); 40717Sbill } 40817Sbill 4092395Swnj dzmodem(unit, flag) 4102395Swnj register int unit; 41117Sbill { 41217Sbill register struct device *dzaddr; 41317Sbill register char bit; 41417Sbill 4152395Swnj dzaddr = dzpdma[unit].p_addr; 4162395Swnj bit = 1<<(unit&07); 4172469Swnj if (flag == DZ_OFF) 41817Sbill dzaddr->dzdtr &= ~bit; 41917Sbill else 42017Sbill dzaddr->dzdtr |= bit; 42117Sbill } 42217Sbill 42317Sbill dzscan() 42417Sbill { 42517Sbill register i; 42617Sbill register struct device *dzaddr; 42717Sbill register bit; 42817Sbill register struct tty *tp; 42917Sbill 43017Sbill for (i = 0; i < dz_cnt ; i++) { 43117Sbill dzaddr = dzpdma[i].p_addr; 43217Sbill tp = &dz_tty[i]; 43317Sbill bit = 1<<(i&07); 434*2567Swnj if ((dzsoftCAR[i]&bit) || (dzaddr->dzmsr&bit)) { 43517Sbill /* carrier present */ 43617Sbill if ((tp->t_state & CARR_ON) == 0) { 43717Sbill wakeup((caddr_t)&tp->t_rawq); 43817Sbill tp->t_state |= CARR_ON; 43917Sbill } 44017Sbill } else { 4412469Swnj if ((tp->t_state&CARR_ON) && 4422469Swnj (tp->t_local&LNOHANG)==0) { 44317Sbill /* carrier lost */ 444882Sbill if (tp->t_state&ISOPEN) { 445170Sbill gsignal(tp->t_pgrp, SIGHUP); 446205Sbill gsignal(tp->t_pgrp, SIGCONT); 447170Sbill dzaddr->dzdtr &= ~bit; 448871Sbill flushtty(tp, FREAD|FWRITE); 449170Sbill } 450170Sbill tp->t_state &= ~CARR_ON; 45117Sbill } 45217Sbill } 45317Sbill } 45417Sbill timeout(dzscan, (caddr_t)0, 2*HZ); 45517Sbill } 456119Sbill 457119Sbill dztimer() 458119Sbill { 4592457Swnj int dz; 460119Sbill 4612457Swnj for (dz = 0; dz < NDZ11; dz++) 4622457Swnj dzrint(dz); 463119Sbill } 464281Sbill 465281Sbill /* 466281Sbill * Reset state of driver if UBA reset was necessary. 467301Sbill * Reset parameters and restart transmission on open lines. 468281Sbill */ 4692395Swnj dzreset(uban) 4702422Skre int uban; 471281Sbill { 4722395Swnj register int unit; 473281Sbill register struct tty *tp; 4742422Skre register struct uba_dinfo *ui; 4752422Skre int any = 0; 476281Sbill 4772395Swnj for (unit = 0; unit < NDZ; unit++) { 4782422Skre ui = dzinfo[unit >> 3]; 4792422Skre if (ui == 0 || ui->ui_ubanum != uban || ui->ui_alive == 0) 4802422Skre continue; 4812422Skre if (any == 0) { 4822422Skre printf(" dz"); 4832422Skre any++; 4842422Skre } 4852395Swnj tp = &dz_tty[unit]; 486281Sbill if (tp->t_state & (ISOPEN|WOPEN)) { 4872395Swnj dzparam(unit); 4882469Swnj dzmodem(unit, DZ_ON); 489301Sbill tp->t_state &= ~BUSY; 490301Sbill dzstart(tp); 491281Sbill } 492281Sbill } 493281Sbill dztimer(); 494281Sbill } 4951562Sbill #endif 496