1*2469Swnj /* dz.c 4.13 02/17/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 8*2469Swnj * 9*2469Swnj * 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" 1917Sbill #include "../h/uba.h" 2017Sbill #include "../h/conf.h" 2117Sbill #include "../h/pdma.h" 22114Sbill #include "../h/bk.h" 23871Sbill #include "../h/file.h" 241786Sbill #include "../h/mx.h" 25145Sbill 26*2469Swnj /* 27*2469Swnj * Driver information for auto-configuration stuff. 28*2469Swnj */ 292395Swnj int dzcntrlr(), dzslave(), dzrint(); 302395Swnj struct uba_dinfo *dzinfo[NDZ11]; 312395Swnj u_short dzstd[] = { 0 }; 322395Swnj struct uba_driver dzdriver = 332457Swnj { dzcntrlr, dzslave, 0, 0, dzstd, "dz", dzinfo }; 342395Swnj 352457Swnj #define NDZ (NDZ11*8) 3617Sbill 37*2469Swnj /* 38*2469Swnj * Registers and bits 39*2469Swnj */ 40*2469Swnj 41*2469Swnj /* Bits in dzlpr */ 422457Swnj #define BITS7 020 432457Swnj #define BITS8 030 442457Swnj #define TWOSB 040 452457Swnj #define PENABLE 0100 462457Swnj #define OPAR 0200 4717Sbill 48*2469Swnj /* Bits in dzrbuf */ 49*2469Swnj #define DZ_PE 010000 50*2469Swnj #define DZ_FE 020000 51*2469Swnj #define DZ_DO 040000 52*2469Swnj 53*2469Swnj /* Bits in dzcsr */ 54*2469Swnj #define DZ_CLR 020 /* Reset dz */ 55*2469Swnj #define DZ_MSE 040 /* Master Scan Enable */ 56*2469Swnj #define DZ_RIE 0100 /* Receiver Interrupt Enable */ 57*2469Swnj #define DZ_SAE 010000 /* Silo Alarm Enable */ 58*2469Swnj #define DZ_TIE 040000 /* Transmit Interrupt Enable */ 59*2469Swnj #define DZ_IEN (DZ_MSE+DZ_RIE+DZ_TIE+DZ_SAE) 60*2469Swnj 61*2469Swnj /* Flags for modem-control */ 62*2469Swnj #define DZ_ON 1 63*2469Swnj #define DZ_OFF 0 6417Sbill 65*2469Swnj int dzstart(), dzxint(), dzdma(); 66114Sbill int ttrstrt(); 6717Sbill struct tty dz_tty[NDZ]; 6817Sbill int dz_cnt = { NDZ }; 69119Sbill int dzact; 7017Sbill 7117Sbill struct device { 72*2469Swnj short dzcsr; /* control-status register */ 73*2469Swnj short dzrbuf; /* receiver buffer */ 74*2469Swnj #define dzlpr dzrbuf /* line parameter reg is write of dzrbuf */ 75*2469Swnj char dztcr; /* transmit control register */ 76*2469Swnj char dzdtr; /* data terminal ready */ 77*2469Swnj char dztbuf; /* transmit buffer */ 78*2469Swnj char dzbrk; /* break control */ 79*2469Swnj #define dzmsr dzbrk /* modem status register */ 8017Sbill }; 81*2469Swnj /* 82*2469Swnj * Software copy of dzbrk since it isn't readable 83*2469Swnj */ 84*2469Swnj char dz_brk[NDZ11]; 8517Sbill 86*2469Swnj /* 87*2469Swnj * The dz doesn't interrupt on carrier transitions, so 88*2469Swnj * we have to use a timer to watch it. 89*2469Swnj */ 90*2469Swnj char dz_timer; /* timer started? */ 91*2469Swnj 92*2469Swnj /* 93*2469Swnj * Pdma structures for fast output code 94*2469Swnj */ 952395Swnj struct pdma dzpdma[NDZ]; 96*2469Swnj 972395Swnj char dz_speeds[] = 982395Swnj { 0,020,021,022,023,024,0,025,026,027,030,032,034,036,0,0 }; 9917Sbill 1002395Swnj dzcntrlr(ui, reg) 1012395Swnj struct uba_dinfo *ui; 1022395Swnj caddr_t reg; 1032395Swnj { 1042457Swnj register int br, cvec; 1052457Swnj register struct device *dzaddr = (struct device *)reg; 1062395Swnj 107*2469Swnj dzaddr->dzcsr = DZ_TIE|DZ_MSE; 1082422Skre dzaddr->dztcr = 1; /* enable any line */ 1092457Swnj DELAY(100000); 110*2469Swnj dzaddr->dzcsr = DZ_CLR; /* reset everything */ 1112457Swnj if (cvec && cvec != 0x200) 1122457Swnj cvec -= 4; 1132457Swnj return (1); 1142395Swnj } 1152395Swnj 116*2469Swnj /* 117*2469Swnj * Called by auto-configure to initialize good dz's; 118*2469Swnj * set up pdma structures. 119*2469Swnj */ 1202395Swnj dzslave(ui, reg, slaveno, uban) 1212395Swnj register struct uba_dinfo *ui; 1222395Swnj caddr_t reg; 1232395Swnj { 1242395Swnj register struct pdma *pdp = &dzpdma[ui->ui_unit*8]; 1252395Swnj register struct tty *tp = &dz_tty[ui->ui_unit*8]; 1262395Swnj register int cnt; 1272395Swnj 1282395Swnj for (cnt = 0; cnt < 8; cnt++) { 1292395Swnj pdp->p_addr = (struct device *)reg; 1302395Swnj pdp->p_arg = (int)tp; 1312395Swnj pdp->p_fcn = dzxint; 1322395Swnj pdp++, tp++; 1332395Swnj } 1342395Swnj return (1); 1352395Swnj } 1362395Swnj 13717Sbill /*ARGSUSED*/ 1382395Swnj dzopen(dev, flag) 1392395Swnj dev_t dev; 14017Sbill { 14117Sbill register struct tty *tp; 1422395Swnj register int unit; 14317Sbill extern dzscan(); 14417Sbill 1452395Swnj unit = minor(dev); 1462395Swnj if (unit >= dz_cnt || dzpdma[unit].p_addr == 0) { 14717Sbill u.u_error = ENXIO; 14817Sbill return; 14917Sbill } 15017Sbill if (dz_timer == 0) { 15117Sbill dz_timer++; 152*2469Swnj timeout(dzscan, (caddr_t)0, HZ); 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); 161*2469Swnj tp->t_ospeed = tp->t_ispeed = B300; 16217Sbill tp->t_flags = ODDP|EVENP|ECHO; 163*2469Swnj /* 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 } 169*2469Swnj 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) 194*2469Swnj 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; 225140Sbill int s; 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 } 240*2469Swnj if (c&DZ_FE) 2412457Swnj if (tp->t_flags & RAW) 242*2469Swnj c = 0; 2432457Swnj else 2442457Swnj c = tun.t_intrc; 245*2469Swnj if (c&DZ_DO) 2462457Swnj printf("o"); 247*2469Swnj if (c&DZ_PE) 2482457Swnj if (((tp->t_flags & (EVENP|ODDP)) == EVENP) 2492457Swnj || ((tp->t_flags & (EVENP|ODDP)) == ODDP)) 25017Sbill continue; 2512457Swnj if (tp->t_line == NETLDISC) { 2522457Swnj c &= 0177; 2532457Swnj BKINPUT(c, tp); 2542457Swnj } else 2552457Swnj (*linesw[tp->t_line].l_rint)(c, tp); 25617Sbill } 25717Sbill } 25817Sbill 25917Sbill /*ARGSUSED*/ 26017Sbill dzioctl(dev, cmd, addr, flag) 2612395Swnj dev_t dev; 2622395Swnj caddr_t addr; 26317Sbill { 26417Sbill register struct tty *tp; 2652395Swnj register int unit = minor(dev); 2662395Swnj register int dz = unit >> 3; 26717Sbill 2682395Swnj tp = &dz_tty[unit]; 269114Sbill cmd = (*linesw[tp->t_line].l_ioctl)(tp, cmd, addr); 270114Sbill if (cmd == 0) 271114Sbill return; 2721896Swnj if (ttioctl(tp, cmd, addr, flag)) { 27317Sbill if (cmd==TIOCSETP || cmd==TIOCSETN) 2742395Swnj dzparam(unit); 275170Sbill } else switch(cmd) { 2762395Swnj 277170Sbill case TIOCSBRK: 278882Sbill ((struct pdma *)(tp->t_addr))->p_addr->dzbrk = 2792395Swnj (dz_brk[dz] |= 1 << (unit&07)); 280170Sbill break; 281170Sbill case TIOCCBRK: 282882Sbill ((struct pdma *)(tp->t_addr))->p_addr->dzbrk = 2832395Swnj (dz_brk[dz] &= ~(1 << (unit&07))); 284170Sbill break; 285170Sbill case TIOCSDTR: 286*2469Swnj dzmodem(unit, DZ_ON); 287170Sbill break; 288170Sbill case TIOCCDTR: 289*2469Swnj dzmodem(unit, DZ_OFF); 290170Sbill break; 291170Sbill default: 29217Sbill u.u_error = ENOTTY; 293170Sbill } 29417Sbill } 29517Sbill 2962395Swnj dzparam(unit) 2972395Swnj register int unit; 29817Sbill { 29917Sbill register struct tty *tp; 30017Sbill register struct device *dzaddr; 3012395Swnj register int lpr; 30217Sbill 3032395Swnj tp = &dz_tty[unit]; 3042395Swnj dzaddr = dzpdma[unit].p_addr; 30517Sbill dzaddr->dzcsr = DZ_IEN; 3062395Swnj dzact |= (1<<(unit>>3)); 30717Sbill if (tp->t_ispeed == 0) { 308*2469Swnj dzmodem(unit, DZ_OFF); /* hang up line */ 30917Sbill return; 31017Sbill } 3112395Swnj lpr = (dz_speeds[tp->t_ispeed]<<8) | (unit & 07); 3122296Swnj if ((tp->t_local&LLITOUT) || (tp->t_flags&RAW)) 31317Sbill lpr |= BITS8; 31417Sbill else 31517Sbill lpr |= (BITS7|PENABLE); 31617Sbill if ((tp->t_flags & EVENP) == 0) 31717Sbill lpr |= OPAR; 318*2469Swnj if (tp->t_ispeed == B110) 319*2469Swnj lpr |= TWOSB; 32017Sbill dzaddr->dzlpr = lpr; 32117Sbill } 32217Sbill 32317Sbill dzxint(tp) 3242395Swnj register struct tty *tp; 32517Sbill { 32617Sbill register struct pdma *dp; 327145Sbill register s; 32817Sbill 329*2469Swnj s = spl5(); /* block pdma interrupts */ 3302395Swnj dp = (struct pdma *)tp->t_addr; 33117Sbill tp->t_state &= ~BUSY; 33217Sbill if (tp->t_state & FLUSH) 33317Sbill tp->t_state &= ~FLUSH; 33417Sbill else 335281Sbill ndflush(&tp->t_outq, dp->p_mem-tp->t_outq.c_cf); 33617Sbill if (tp->t_line) 33717Sbill (*linesw[tp->t_line].l_start)(tp); 33817Sbill else 33917Sbill dzstart(tp); 34017Sbill if (tp->t_outq.c_cc == 0 || (tp->t_state&BUSY)==0) 3412395Swnj dp->p_addr->dztcr &= ~(1 << (minor(tp->t_dev)&07)); 342145Sbill splx(s); 34317Sbill } 34417Sbill 34517Sbill dzstart(tp) 3462395Swnj register struct tty *tp; 34717Sbill { 34817Sbill register struct pdma *dp; 34917Sbill register struct device *dzaddr; 3502395Swnj register int cc; 3512395Swnj int s; 35217Sbill 3532395Swnj dp = (struct pdma *)tp->t_addr; 35417Sbill dzaddr = dp->p_addr; 3552395Swnj s = spl5(); 35617Sbill if (tp->t_state & (TIMEOUT|BUSY|TTSTOP)) 35717Sbill goto out; 358921Sbill if (tp->t_state&ASLEEP && tp->t_outq.c_cc <= TTLOWAT(tp)) { 35917Sbill tp->t_state &= ~ASLEEP; 36017Sbill if (tp->t_chan) 36117Sbill mcstart(tp->t_chan, (caddr_t)&tp->t_outq); 36217Sbill else 36317Sbill wakeup((caddr_t)&tp->t_outq); 36417Sbill } 36517Sbill if (tp->t_outq.c_cc == 0) 36617Sbill goto out; 36717Sbill if (tp->t_flags&RAW) 36817Sbill cc = ndqb(&tp->t_outq, 0); 36917Sbill else { 37017Sbill cc = ndqb(&tp->t_outq, 0200); 37117Sbill if (cc == 0) { 37217Sbill cc = getc(&tp->t_outq); 373*2469Swnj timeout(ttrstrt, (caddr_t)tp, (cc&0x7f) + 6); 37417Sbill tp->t_state |= TIMEOUT; 37517Sbill goto out; 37617Sbill } 37717Sbill } 37817Sbill tp->t_state |= BUSY; 37917Sbill dp->p_end = dp->p_mem = tp->t_outq.c_cf; 38017Sbill dp->p_end += cc; 381*2469Swnj dzaddr->dztcr |= 1 << (minor(tp->t_dev) & 07); /* force intr */ 3822395Swnj out: 3832395Swnj splx(s); 38417Sbill } 38517Sbill 38617Sbill /* 38717Sbill * Stop output on a line. 38817Sbill */ 38917Sbill /*ARGSUSED*/ 39017Sbill dzstop(tp, flag) 3912395Swnj register struct tty *tp; 39217Sbill { 39317Sbill register struct pdma *dp; 39417Sbill register int s; 39517Sbill 3962395Swnj dp = (struct pdma *)tp->t_addr; 3972457Swnj s = spl5(); 39817Sbill if (tp->t_state & BUSY) { 39917Sbill dp->p_end = dp->p_mem; 4002395Swnj if ((tp->t_state&TTSTOP)==0) 40117Sbill tp->t_state |= FLUSH; 40217Sbill } 40317Sbill splx(s); 40417Sbill } 40517Sbill 4062395Swnj dzmodem(unit, flag) 4072395Swnj register int unit; 40817Sbill { 40917Sbill register struct device *dzaddr; 41017Sbill register char bit; 41117Sbill 4122395Swnj dzaddr = dzpdma[unit].p_addr; 4132395Swnj bit = 1<<(unit&07); 414*2469Swnj if (flag == DZ_OFF) 41517Sbill dzaddr->dzdtr &= ~bit; 41617Sbill else 41717Sbill dzaddr->dzdtr |= bit; 41817Sbill } 41917Sbill 42017Sbill dzscan() 42117Sbill { 42217Sbill register i; 42317Sbill register struct device *dzaddr; 42417Sbill register bit; 42517Sbill register struct tty *tp; 42617Sbill 42717Sbill for (i = 0; i < dz_cnt ; i++) { 42817Sbill dzaddr = dzpdma[i].p_addr; 42917Sbill tp = &dz_tty[i]; 43017Sbill bit = 1<<(i&07); 4312422Skre #ifdef BERT 4322422Skre if (dzaddr->dzmsr & bit || i == 6 || i == 7) { 4332422Skre #else 4342422Skre if (dzaddr->dzmsr & bit) { 4352422Skre #endif 43617Sbill /* carrier present */ 43717Sbill if ((tp->t_state & CARR_ON) == 0) { 43817Sbill wakeup((caddr_t)&tp->t_rawq); 43917Sbill tp->t_state |= CARR_ON; 44017Sbill } 44117Sbill } else { 442*2469Swnj if ((tp->t_state&CARR_ON) && 443*2469Swnj (tp->t_local&LNOHANG)==0) { 44417Sbill /* carrier lost */ 445882Sbill if (tp->t_state&ISOPEN) { 446170Sbill gsignal(tp->t_pgrp, SIGHUP); 447205Sbill gsignal(tp->t_pgrp, SIGCONT); 448170Sbill dzaddr->dzdtr &= ~bit; 449871Sbill flushtty(tp, FREAD|FWRITE); 450170Sbill } 451170Sbill tp->t_state &= ~CARR_ON; 45217Sbill } 45317Sbill } 45417Sbill } 45517Sbill timeout(dzscan, (caddr_t)0, 2*HZ); 45617Sbill } 457119Sbill 458119Sbill dztimer() 459119Sbill { 4602457Swnj int dz; 461119Sbill 4622457Swnj for (dz = 0; dz < NDZ11; dz++) 4632457Swnj dzrint(dz); 464119Sbill } 465281Sbill 466281Sbill /* 467281Sbill * Reset state of driver if UBA reset was necessary. 468301Sbill * Reset parameters and restart transmission on open lines. 469281Sbill */ 4702395Swnj dzreset(uban) 4712422Skre int uban; 472281Sbill { 4732395Swnj register int unit; 474281Sbill register struct tty *tp; 4752422Skre register struct uba_dinfo *ui; 4762422Skre int any = 0; 477281Sbill 4782395Swnj for (unit = 0; unit < NDZ; unit++) { 4792422Skre ui = dzinfo[unit >> 3]; 4802422Skre if (ui == 0 || ui->ui_ubanum != uban || ui->ui_alive == 0) 4812422Skre continue; 4822422Skre if (any == 0) { 4832422Skre printf(" dz"); 4842422Skre any++; 4852422Skre } 4862395Swnj tp = &dz_tty[unit]; 487281Sbill if (tp->t_state & (ISOPEN|WOPEN)) { 4882395Swnj dzparam(unit); 489*2469Swnj dzmodem(unit, DZ_ON); 490301Sbill tp->t_state &= ~BUSY; 491301Sbill dzstart(tp); 492281Sbill } 493281Sbill } 494281Sbill dztimer(); 495281Sbill } 4961562Sbill #endif 497