1*3102Swnj /* dz.c 4.22 03/09/81 */ 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 */ 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(); 682645Swnj struct tty dz_tty[NDZLINE]; 692645Swnj int dz_cnt = { NDZLINE }; 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 */ 852645Swnj char dz_brk[NDZ]; 862645Swnj char dzsoftCAR[NDZ]; 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 */ 972645Swnj struct pdma dzpdma[NDZLINE]; 982469Swnj 992395Swnj char dz_speeds[] = 1002395Swnj { 0,020,021,022,023,024,0,025,026,027,030,032,034,036,0,0 }; 10117Sbill 1022606Swnj dzprobe(reg) 1032395Swnj caddr_t reg; 1042395Swnj { 1052457Swnj register int br, cvec; 1062457Swnj register struct device *dzaddr = (struct device *)reg; 1072395Swnj 1082606Swnj #ifdef lint 109*3102Swnj br = 0; cvec = br; br = cvec; 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 return (1); 1402395Swnj } 1412395Swnj 14217Sbill /*ARGSUSED*/ 1432395Swnj dzopen(dev, flag) 1442395Swnj dev_t dev; 14517Sbill { 14617Sbill register struct tty *tp; 1472395Swnj register int unit; 14817Sbill 1492395Swnj unit = minor(dev); 1502395Swnj if (unit >= dz_cnt || dzpdma[unit].p_addr == 0) { 15117Sbill u.u_error = ENXIO; 15217Sbill return; 15317Sbill } 1542395Swnj tp = &dz_tty[unit]; 1552395Swnj tp->t_addr = (caddr_t)&dzpdma[unit]; 15617Sbill tp->t_oproc = dzstart; 15717Sbill tp->t_iproc = NULL; 15817Sbill tp->t_state |= WOPEN; 15917Sbill if ((tp->t_state & ISOPEN) == 0) { 16017Sbill ttychars(tp); 1612469Swnj tp->t_ospeed = tp->t_ispeed = B300; 16217Sbill tp->t_flags = ODDP|EVENP|ECHO; 1632469Swnj /* tp->t_state |= HUPCLS; */ 1642395Swnj dzparam(unit); 16517Sbill } else if (tp->t_state&XCLUDE && u.u_uid != 0) { 16617Sbill u.u_error = EBUSY; 16717Sbill return; 16817Sbill } 1692469Swnj dzmodem(unit, DZ_ON); 170114Sbill (void) spl5(); 17117Sbill while ((tp->t_state & CARR_ON) == 0) { 17217Sbill tp->t_state |= WOPEN; 17317Sbill sleep((caddr_t)&tp->t_rawq, TTIPRI); 17417Sbill } 175114Sbill (void) spl0(); 1762395Swnj (*linesw[tp->t_line].l_open)(dev, tp); 17717Sbill } 17817Sbill 1792395Swnj /*ARGSUSED*/ 1802395Swnj dzclose(dev, flag) 1812395Swnj dev_t dev; 18217Sbill { 18317Sbill register struct tty *tp; 1842395Swnj register int unit; 1852395Swnj int dz; 18617Sbill 1872395Swnj unit = minor(dev); 1882395Swnj dz = unit >> 3; 1892395Swnj tp = &dz_tty[unit]; 19017Sbill (*linesw[tp->t_line].l_close)(tp); 1912197Stoy ((struct pdma *)(tp->t_addr))->p_addr->dzbrk = 1922395Swnj (dz_brk[dz] &= ~(1 << (unit&07))); 19317Sbill if (tp->t_state & HUPCLS) 1942469Swnj dzmodem(unit, DZ_OFF); 19517Sbill ttyclose(tp); 19617Sbill } 19717Sbill 1982395Swnj dzread(dev) 1992395Swnj dev_t dev; 20017Sbill { 20117Sbill register struct tty *tp; 20217Sbill 2032395Swnj tp = &dz_tty[minor(dev)]; 20417Sbill (*linesw[tp->t_line].l_read)(tp); 20517Sbill } 20617Sbill 2072395Swnj dzwrite(dev) 2082395Swnj dev_t dev; 20917Sbill { 21017Sbill register struct tty *tp; 21117Sbill 2122395Swnj tp = &dz_tty[minor(dev)]; 21317Sbill (*linesw[tp->t_line].l_write)(tp); 21417Sbill } 21517Sbill 216119Sbill /*ARGSUSED*/ 2172395Swnj dzrint(dz) 2182395Swnj int dz; 21917Sbill { 22017Sbill register struct tty *tp; 22117Sbill register int c; 22217Sbill register struct device *dzaddr; 223119Sbill register struct tty *tp0; 2242395Swnj register int unit; 2252923Swnj int overrun = 0; 22617Sbill 2272457Swnj if ((dzact & (1<<dz)) == 0) 2282457Swnj return; 2292457Swnj unit = dz * 8; 2302457Swnj dzaddr = dzpdma[unit].p_addr; 2312457Swnj tp0 = &dz_tty[unit]; 2322457Swnj while ((c = dzaddr->dzrbuf) < 0) { /* char present */ 2332457Swnj tp = tp0 + ((c>>8)&07); 2342457Swnj if (tp >= &dz_tty[dz_cnt]) 23517Sbill continue; 2362457Swnj if ((tp->t_state & ISOPEN) == 0) { 2372457Swnj wakeup((caddr_t)&tp->t_rawq); 2382457Swnj continue; 2392457Swnj } 2402469Swnj if (c&DZ_FE) 2412457Swnj if (tp->t_flags & RAW) 2422469Swnj c = 0; 2432457Swnj else 2442457Swnj c = tun.t_intrc; 2452923Swnj if (c&DZ_DO && overrun == 0) { 2462923Swnj printf("dz%d: silo overflow\n", dz); 2472923Swnj overrun = 1; 2482923Swnj } 2492469Swnj if (c&DZ_PE) 2502457Swnj if (((tp->t_flags & (EVENP|ODDP)) == EVENP) 2512457Swnj || ((tp->t_flags & (EVENP|ODDP)) == ODDP)) 25217Sbill continue; 2532731Swnj #if NBK > 0 2542457Swnj if (tp->t_line == NETLDISC) { 2552457Swnj c &= 0177; 2562457Swnj BKINPUT(c, tp); 2572457Swnj } else 2582731Swnj #endif 2592457Swnj (*linesw[tp->t_line].l_rint)(c, tp); 26017Sbill } 26117Sbill } 26217Sbill 26317Sbill /*ARGSUSED*/ 26417Sbill dzioctl(dev, cmd, addr, flag) 2652395Swnj dev_t dev; 2662395Swnj caddr_t addr; 26717Sbill { 26817Sbill register struct tty *tp; 2692395Swnj register int unit = minor(dev); 2702395Swnj register int dz = unit >> 3; 27117Sbill 2722395Swnj tp = &dz_tty[unit]; 273114Sbill cmd = (*linesw[tp->t_line].l_ioctl)(tp, cmd, addr); 274114Sbill if (cmd == 0) 275114Sbill return; 2761896Swnj if (ttioctl(tp, cmd, addr, flag)) { 27717Sbill if (cmd==TIOCSETP || cmd==TIOCSETN) 2782395Swnj dzparam(unit); 279170Sbill } else switch(cmd) { 2802395Swnj 281170Sbill case TIOCSBRK: 282882Sbill ((struct pdma *)(tp->t_addr))->p_addr->dzbrk = 2832395Swnj (dz_brk[dz] |= 1 << (unit&07)); 284170Sbill break; 285170Sbill case TIOCCBRK: 286882Sbill ((struct pdma *)(tp->t_addr))->p_addr->dzbrk = 2872395Swnj (dz_brk[dz] &= ~(1 << (unit&07))); 288170Sbill break; 289170Sbill case TIOCSDTR: 2902469Swnj dzmodem(unit, DZ_ON); 291170Sbill break; 292170Sbill case TIOCCDTR: 2932469Swnj dzmodem(unit, DZ_OFF); 294170Sbill break; 295170Sbill default: 29617Sbill u.u_error = ENOTTY; 297170Sbill } 29817Sbill } 29917Sbill 3002395Swnj dzparam(unit) 3012395Swnj register int unit; 30217Sbill { 30317Sbill register struct tty *tp; 30417Sbill register struct device *dzaddr; 3052395Swnj register int lpr; 30617Sbill 3072395Swnj tp = &dz_tty[unit]; 3082395Swnj dzaddr = dzpdma[unit].p_addr; 30917Sbill dzaddr->dzcsr = DZ_IEN; 3102395Swnj dzact |= (1<<(unit>>3)); 31117Sbill if (tp->t_ispeed == 0) { 3122469Swnj dzmodem(unit, DZ_OFF); /* hang up line */ 31317Sbill return; 31417Sbill } 3152395Swnj lpr = (dz_speeds[tp->t_ispeed]<<8) | (unit & 07); 3162296Swnj if ((tp->t_local&LLITOUT) || (tp->t_flags&RAW)) 31717Sbill lpr |= BITS8; 31817Sbill else 31917Sbill lpr |= (BITS7|PENABLE); 32017Sbill if ((tp->t_flags & EVENP) == 0) 32117Sbill lpr |= OPAR; 3222469Swnj if (tp->t_ispeed == B110) 3232469Swnj lpr |= TWOSB; 32417Sbill dzaddr->dzlpr = lpr; 32517Sbill } 32617Sbill 32717Sbill dzxint(tp) 3282395Swnj register struct tty *tp; 32917Sbill { 33017Sbill register struct pdma *dp; 331145Sbill register s; 33217Sbill 3332469Swnj s = spl5(); /* block pdma interrupts */ 3342395Swnj dp = (struct pdma *)tp->t_addr; 33517Sbill tp->t_state &= ~BUSY; 33617Sbill if (tp->t_state & FLUSH) 33717Sbill tp->t_state &= ~FLUSH; 33817Sbill else 339281Sbill ndflush(&tp->t_outq, dp->p_mem-tp->t_outq.c_cf); 34017Sbill if (tp->t_line) 34117Sbill (*linesw[tp->t_line].l_start)(tp); 34217Sbill else 34317Sbill dzstart(tp); 34417Sbill if (tp->t_outq.c_cc == 0 || (tp->t_state&BUSY)==0) 3452395Swnj dp->p_addr->dztcr &= ~(1 << (minor(tp->t_dev)&07)); 346145Sbill splx(s); 34717Sbill } 34817Sbill 34917Sbill dzstart(tp) 3502395Swnj register struct tty *tp; 35117Sbill { 35217Sbill register struct pdma *dp; 35317Sbill register struct device *dzaddr; 3542395Swnj register int cc; 3552395Swnj int s; 35617Sbill 3572395Swnj dp = (struct pdma *)tp->t_addr; 35817Sbill dzaddr = dp->p_addr; 3592395Swnj s = spl5(); 36017Sbill if (tp->t_state & (TIMEOUT|BUSY|TTSTOP)) 36117Sbill goto out; 362921Sbill if (tp->t_state&ASLEEP && tp->t_outq.c_cc <= TTLOWAT(tp)) { 36317Sbill tp->t_state &= ~ASLEEP; 36417Sbill if (tp->t_chan) 36517Sbill mcstart(tp->t_chan, (caddr_t)&tp->t_outq); 36617Sbill else 36717Sbill wakeup((caddr_t)&tp->t_outq); 36817Sbill } 36917Sbill if (tp->t_outq.c_cc == 0) 37017Sbill goto out; 37117Sbill if (tp->t_flags&RAW) 37217Sbill cc = ndqb(&tp->t_outq, 0); 37317Sbill else { 37417Sbill cc = ndqb(&tp->t_outq, 0200); 37517Sbill if (cc == 0) { 37617Sbill cc = getc(&tp->t_outq); 3772469Swnj timeout(ttrstrt, (caddr_t)tp, (cc&0x7f) + 6); 37817Sbill tp->t_state |= TIMEOUT; 37917Sbill goto out; 38017Sbill } 38117Sbill } 38217Sbill tp->t_state |= BUSY; 38317Sbill dp->p_end = dp->p_mem = tp->t_outq.c_cf; 38417Sbill dp->p_end += cc; 3852469Swnj dzaddr->dztcr |= 1 << (minor(tp->t_dev) & 07); /* force intr */ 3862395Swnj out: 3872395Swnj splx(s); 38817Sbill } 38917Sbill 39017Sbill /* 39117Sbill * Stop output on a line. 39217Sbill */ 39317Sbill /*ARGSUSED*/ 39417Sbill dzstop(tp, flag) 3952395Swnj register struct tty *tp; 39617Sbill { 39717Sbill register struct pdma *dp; 39817Sbill register int s; 39917Sbill 4002395Swnj dp = (struct pdma *)tp->t_addr; 4012457Swnj s = spl5(); 40217Sbill if (tp->t_state & BUSY) { 40317Sbill dp->p_end = dp->p_mem; 4042395Swnj if ((tp->t_state&TTSTOP)==0) 40517Sbill tp->t_state |= FLUSH; 40617Sbill } 40717Sbill splx(s); 40817Sbill } 40917Sbill 4102395Swnj dzmodem(unit, flag) 4112395Swnj register int unit; 41217Sbill { 41317Sbill register struct device *dzaddr; 41417Sbill register char bit; 41517Sbill 4162395Swnj dzaddr = dzpdma[unit].p_addr; 4172395Swnj bit = 1<<(unit&07); 4182469Swnj if (flag == DZ_OFF) 41917Sbill dzaddr->dzdtr &= ~bit; 42017Sbill else 42117Sbill dzaddr->dzdtr |= bit; 42217Sbill } 42317Sbill 42417Sbill dzscan() 42517Sbill { 42617Sbill register i; 42717Sbill register struct device *dzaddr; 42817Sbill register bit; 42917Sbill register struct tty *tp; 43017Sbill 43117Sbill for (i = 0; i < dz_cnt ; i++) { 43217Sbill dzaddr = dzpdma[i].p_addr; 4332627Swnj if (dzaddr == 0) 4342627Swnj continue; 43517Sbill tp = &dz_tty[i]; 43617Sbill bit = 1<<(i&07); 4372606Swnj if ((dzsoftCAR[i>>3]&bit) || (dzaddr->dzmsr&bit)) { 43817Sbill /* carrier present */ 43917Sbill if ((tp->t_state & CARR_ON) == 0) { 44017Sbill wakeup((caddr_t)&tp->t_rawq); 44117Sbill tp->t_state |= CARR_ON; 44217Sbill } 44317Sbill } else { 4442469Swnj if ((tp->t_state&CARR_ON) && 4452469Swnj (tp->t_local&LNOHANG)==0) { 44617Sbill /* carrier lost */ 447882Sbill if (tp->t_state&ISOPEN) { 448170Sbill gsignal(tp->t_pgrp, SIGHUP); 449205Sbill gsignal(tp->t_pgrp, SIGCONT); 450170Sbill dzaddr->dzdtr &= ~bit; 451871Sbill flushtty(tp, FREAD|FWRITE); 452170Sbill } 453170Sbill tp->t_state &= ~CARR_ON; 45417Sbill } 45517Sbill } 45617Sbill } 4572756Swnj timeout(dzscan, (caddr_t)0, 2*hz); 45817Sbill } 459119Sbill 460119Sbill dztimer() 461119Sbill { 4622457Swnj int dz; 463119Sbill 4642645Swnj for (dz = 0; dz < NDZ; dz++) 4652457Swnj dzrint(dz); 466119Sbill } 467281Sbill 468281Sbill /* 469281Sbill * Reset state of driver if UBA reset was necessary. 470301Sbill * Reset parameters and restart transmission on open lines. 471281Sbill */ 4722395Swnj dzreset(uban) 4732422Skre int uban; 474281Sbill { 4752395Swnj register int unit; 476281Sbill register struct tty *tp; 4772976Swnj register struct uba_device *ui; 478281Sbill 4792645Swnj for (unit = 0; unit < NDZLINE; unit++) { 4802422Skre ui = dzinfo[unit >> 3]; 4812422Skre if (ui == 0 || ui->ui_ubanum != uban || ui->ui_alive == 0) 4822422Skre continue; 4832923Swnj if (unit%8 == 0) 4842923Swnj printf(" dz%d", unit>>3); 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