1*2422Skre /* dz.c 4.11 02/15/81 */ 217Sbill 31935Swnj #include "dz.h" 41562Sbill #if NDZ11 > 0 517Sbill /* 617Sbill * DZ-11 Driver 717Sbill */ 817Sbill #include "../h/param.h" 917Sbill #include "../h/systm.h" 1017Sbill #include "../h/tty.h" 1117Sbill #include "../h/dir.h" 1217Sbill #include "../h/user.h" 1317Sbill #include "../h/map.h" 1417Sbill #include "../h/pte.h" 152395Swnj #include "../h/buf.h" 1617Sbill #include "../h/uba.h" 1717Sbill #include "../h/conf.h" 1817Sbill #include "../h/pdma.h" 19114Sbill #include "../h/bk.h" 20871Sbill #include "../h/file.h" 211786Sbill #include "../h/mx.h" 22145Sbill 23145Sbill /* 24145Sbill * When running dz's using only SAE (silo alarm) on input 25145Sbill * it is necessary to call dzrint() at clock interrupt time. 26145Sbill * This is unsafe unless spl5()s in tty code are changed to 27145Sbill * spl6()s to block clock interrupts. Note that the dh driver 28145Sbill * currently in use works the same way as the dz, even though 29145Sbill * we could try to more intelligently manage its silo. 30145Sbill * Thus don't take this out if you have no dz's unless you 31145Sbill * change clock.c and dhtimer(). 322395Swnj * 332395Swnj * SHOULD RATHER QUEUE SOFTWARE INTERRUPT AT CLOCK TIME. 34145Sbill */ 35145Sbill #define spl5 spl6 3617Sbill 372395Swnj int dzcntrlr(), dzslave(), dzrint(); 382395Swnj struct uba_dinfo *dzinfo[NDZ11]; 392395Swnj u_short dzstd[] = { 0 }; 402395Swnj struct uba_driver dzdriver = 41*2422Skre { dzcntrlr, dzslave, (int (*)())0, 0, 0, dzstd, "dz", dzinfo }; 422395Swnj 43882Sbill #define NDZ (NDZ11*8) 4417Sbill 4517Sbill #define BITS7 020 4617Sbill #define BITS8 030 4717Sbill #define TWOSB 040 4817Sbill #define PENABLE 0100 4917Sbill #define OPAR 0200 50*2422Skre #define CLR 020 /* Reset dz */ 5117Sbill #define MSE 040 /* Master Scan Enable */ 5217Sbill #define RIE 0100 /* Receiver Interrupt Enable */ 53119Sbill #define SAE 010000 /* Silo Alarm Enable */ 54119Sbill #define TIE 040000 /* Transmit Interrupt Enable */ 55119Sbill #define DZ_IEN (MSE+RIE+TIE+SAE) 5617Sbill #define PERROR 010000 5717Sbill #define FRERROR 020000 58119Sbill #define OVERRUN 040000 5917Sbill #define SSPEED 7 /* std speed = 300 baud */ 6017Sbill 6117Sbill #define dzlpr dzrbuf 6217Sbill #define dzmsr dzbrk 6317Sbill #define ON 1 6417Sbill #define OFF 0 6517Sbill 6617Sbill int dzstart(); 6717Sbill int dzxint(); 682395Swnj int dzdma(); 69114Sbill int ttrstrt(); 7017Sbill struct tty dz_tty[NDZ]; 7117Sbill int dz_cnt = { NDZ }; 72119Sbill int dzact; 7317Sbill 7417Sbill struct device { 7517Sbill short dzcsr; 7617Sbill short dzrbuf; 7717Sbill char dztcr; 7817Sbill char dzdtr; 7917Sbill char dztbuf; 8017Sbill char dzbrk; 8117Sbill }; 8217Sbill 832395Swnj struct pdma dzpdma[NDZ]; 8417Sbill char dz_timer; 852395Swnj char dz_speeds[] = 862395Swnj { 0,020,021,022,023,024,0,025,026,027,030,032,034,036,0,0 }; 872395Swnj char dz_brk[NDZ11]; 8817Sbill 892395Swnj dzcntrlr(ui, reg) 902395Swnj struct uba_dinfo *ui; 912395Swnj caddr_t reg; 922395Swnj { 93*2422Skre int i; /* NB: NOT REGISTER */ 94*2422Skre struct device *dzaddr = (struct device *)reg; 952395Swnj 96*2422Skre dzaddr->dzcsr = TIE|MSE; 97*2422Skre dzaddr->dztcr = 1; /* enable any line */ 98*2422Skre for (i = 0; i < 1000000; i++) 99*2422Skre ; 100*2422Skre dzaddr->dzcsr = CLR; /* reset everything */ 101*2422Skre asm("cmpl r10,$0x200;beql 1f;subl2 $4,r10;1:;"); 102*2422Skre return(1); 1032395Swnj } 1042395Swnj 1052395Swnj dzslave(ui, reg, slaveno, uban) 1062395Swnj register struct uba_dinfo *ui; 1072395Swnj caddr_t reg; 1082395Swnj { 1092395Swnj register struct pdma *pdp = &dzpdma[ui->ui_unit*8]; 1102395Swnj register struct tty *tp = &dz_tty[ui->ui_unit*8]; 1112395Swnj register int cnt; 1122395Swnj caddr_t cp; 1132395Swnj 1142395Swnj for (cnt = 0; cnt < 8; cnt++) { 1152395Swnj pdp->p_addr = (struct device *)reg; 1162395Swnj pdp->p_arg = (int)tp; 1172395Swnj pdp->p_fcn = dzxint; 1182395Swnj pdp++, tp++; 1192395Swnj } 1202395Swnj return (1); 1212395Swnj } 1222395Swnj 12317Sbill /*ARGSUSED*/ 1242395Swnj dzopen(dev, flag) 1252395Swnj dev_t dev; 12617Sbill { 12717Sbill register struct tty *tp; 1282395Swnj register int unit; 12917Sbill extern dzscan(); 13017Sbill 1312395Swnj unit = minor(dev); 1322395Swnj if (unit >= dz_cnt || dzpdma[unit].p_addr == 0) { 13317Sbill u.u_error = ENXIO; 13417Sbill return; 13517Sbill } 13617Sbill if (dz_timer == 0) { 13717Sbill dz_timer++; 13817Sbill timeout(dzscan, (caddr_t)0, 60); 13917Sbill } 1402395Swnj tp = &dz_tty[unit]; 1412395Swnj tp->t_addr = (caddr_t)&dzpdma[unit]; 14217Sbill tp->t_oproc = dzstart; 14317Sbill tp->t_iproc = NULL; 14417Sbill tp->t_state |= WOPEN; 14517Sbill if ((tp->t_state & ISOPEN) == 0) { 14617Sbill ttychars(tp); 14717Sbill tp->t_ospeed = tp->t_ispeed = SSPEED; 14817Sbill tp->t_flags = ODDP|EVENP|ECHO; 14917Sbill /*tp->t_state |= HUPCLS;*/ 1502395Swnj dzparam(unit); 15117Sbill } else if (tp->t_state&XCLUDE && u.u_uid != 0) { 15217Sbill u.u_error = EBUSY; 15317Sbill return; 15417Sbill } 1552395Swnj dzmodem(unit, ON); 156114Sbill (void) spl5(); 15717Sbill while ((tp->t_state & CARR_ON) == 0) { 15817Sbill tp->t_state |= WOPEN; 15917Sbill sleep((caddr_t)&tp->t_rawq, TTIPRI); 16017Sbill } 161114Sbill (void) spl0(); 1622395Swnj (*linesw[tp->t_line].l_open)(dev, tp); 16317Sbill } 16417Sbill 1652395Swnj /*ARGSUSED*/ 1662395Swnj dzclose(dev, flag) 1672395Swnj dev_t dev; 16817Sbill { 16917Sbill register struct tty *tp; 1702395Swnj register int unit; 1712395Swnj int dz; 17217Sbill 1732395Swnj unit = minor(dev); 1742395Swnj dz = unit >> 3; 1752395Swnj tp = &dz_tty[unit]; 17617Sbill (*linesw[tp->t_line].l_close)(tp); 1772197Stoy ((struct pdma *)(tp->t_addr))->p_addr->dzbrk = 1782395Swnj (dz_brk[dz] &= ~(1 << (unit&07))); 17917Sbill if (tp->t_state & HUPCLS) 1802395Swnj dzmodem(unit, OFF); 18117Sbill ttyclose(tp); 18217Sbill } 18317Sbill 1842395Swnj dzread(dev) 1852395Swnj dev_t dev; 18617Sbill { 18717Sbill register struct tty *tp; 18817Sbill 1892395Swnj tp = &dz_tty[minor(dev)]; 19017Sbill (*linesw[tp->t_line].l_read)(tp); 19117Sbill } 19217Sbill 1932395Swnj dzwrite(dev) 1942395Swnj dev_t dev; 19517Sbill { 19617Sbill register struct tty *tp; 19717Sbill 1982395Swnj tp = &dz_tty[minor(dev)]; 19917Sbill (*linesw[tp->t_line].l_write)(tp); 20017Sbill } 20117Sbill 202119Sbill /*ARGSUSED*/ 2032395Swnj dzrint(dz) 2042395Swnj int dz; 20517Sbill { 20617Sbill register struct tty *tp; 20717Sbill register int c; 20817Sbill register struct device *dzaddr; 209119Sbill register struct tty *tp0; 2102395Swnj register int unit; 211140Sbill int s; 21217Sbill 213140Sbill s = spl6(); /* see comment in clock.c */ 214119Sbill /* as long as we are here, service them all */ 2152395Swnj for (unit = 0; unit < NDZ; unit += 8) { 2162395Swnj if ((dzact & (1<<(unit>>3))) == 0) 21717Sbill continue; 2182395Swnj dzaddr = dzpdma[unit].p_addr; 2192395Swnj tp0 = &dz_tty[unit]; 220119Sbill while ((c = dzaddr->dzrbuf) < 0) { /* char present */ 221119Sbill tp = tp0 + ((c>>8)&07); 222119Sbill if (tp >= &dz_tty[dz_cnt]) 22317Sbill continue; 224119Sbill if ((tp->t_state & ISOPEN) == 0) { 225119Sbill wakeup((caddr_t)&tp->t_rawq); 226119Sbill continue; 227119Sbill } 228119Sbill if (c&FRERROR) 229119Sbill /* framing error = break */ 230119Sbill if (tp->t_flags & RAW) 231119Sbill c = 0; /* null for getty */ 232119Sbill else 233185Sbill c = tun.t_intrc; 234119Sbill if (c&OVERRUN) 235119Sbill printf("o"); 236119Sbill if (c&PERROR) 237119Sbill /* parity error */ 238119Sbill if (((tp->t_flags & (EVENP|ODDP)) == EVENP) 239119Sbill || ((tp->t_flags & (EVENP|ODDP)) == ODDP)) 240119Sbill continue; 241140Sbill if (tp->t_line == NETLDISC) { 242114Sbill c &= 0177; 243170Sbill BKINPUT(c, tp); 244114Sbill } else 245114Sbill (*linesw[tp->t_line].l_rint)(c, tp); 246119Sbill } 24717Sbill } 248140Sbill splx(s); 24917Sbill } 25017Sbill 25117Sbill /*ARGSUSED*/ 25217Sbill dzioctl(dev, cmd, addr, flag) 2532395Swnj dev_t dev; 2542395Swnj caddr_t addr; 25517Sbill { 25617Sbill register struct tty *tp; 2572395Swnj register int unit = minor(dev); 2582395Swnj register int dz = unit >> 3; 25917Sbill 2602395Swnj tp = &dz_tty[unit]; 261114Sbill cmd = (*linesw[tp->t_line].l_ioctl)(tp, cmd, addr); 262114Sbill if (cmd == 0) 263114Sbill return; 2641896Swnj if (ttioctl(tp, cmd, addr, flag)) { 26517Sbill if (cmd==TIOCSETP || cmd==TIOCSETN) 2662395Swnj dzparam(unit); 267170Sbill } else switch(cmd) { 2682395Swnj 269170Sbill case TIOCSBRK: 270882Sbill ((struct pdma *)(tp->t_addr))->p_addr->dzbrk = 2712395Swnj (dz_brk[dz] |= 1 << (unit&07)); 272170Sbill break; 273170Sbill case TIOCCBRK: 274882Sbill ((struct pdma *)(tp->t_addr))->p_addr->dzbrk = 2752395Swnj (dz_brk[dz] &= ~(1 << (unit&07))); 276170Sbill break; 277170Sbill case TIOCSDTR: 2782395Swnj dzmodem(unit, ON); 279170Sbill break; 280170Sbill case TIOCCDTR: 2812395Swnj dzmodem(unit, OFF); 282170Sbill break; 283170Sbill default: 28417Sbill u.u_error = ENOTTY; 285170Sbill } 28617Sbill } 28717Sbill 2882395Swnj dzparam(unit) 2892395Swnj register int unit; 29017Sbill { 29117Sbill register struct tty *tp; 29217Sbill register struct device *dzaddr; 2932395Swnj register int lpr; 29417Sbill 2952395Swnj tp = &dz_tty[unit]; 2962395Swnj dzaddr = dzpdma[unit].p_addr; 29717Sbill dzaddr->dzcsr = DZ_IEN; 2982395Swnj dzact |= (1<<(unit>>3)); 29917Sbill if (tp->t_ispeed == 0) { 3002395Swnj dzmodem(unit, OFF); /* hang up line */ 30117Sbill return; 30217Sbill } 3032395Swnj lpr = (dz_speeds[tp->t_ispeed]<<8) | (unit & 07); 3042296Swnj if ((tp->t_local&LLITOUT) || (tp->t_flags&RAW)) 30517Sbill lpr |= BITS8; 30617Sbill else 30717Sbill lpr |= (BITS7|PENABLE); 30817Sbill if ((tp->t_flags & EVENP) == 0) 30917Sbill lpr |= OPAR; 31017Sbill if (tp->t_ispeed == 3) 31117Sbill lpr |= TWOSB; /* 110 baud: 2 stop bits */ 31217Sbill dzaddr->dzlpr = lpr; 31317Sbill } 31417Sbill 31517Sbill dzxint(tp) 3162395Swnj register struct tty *tp; 31717Sbill { 31817Sbill register struct pdma *dp; 319145Sbill register s; 320145Sbill s = spl6(); /* block the clock */ 32117Sbill 3222395Swnj dp = (struct pdma *)tp->t_addr; 32317Sbill tp->t_state &= ~BUSY; 32417Sbill if (tp->t_state & FLUSH) 32517Sbill tp->t_state &= ~FLUSH; 32617Sbill else 327281Sbill ndflush(&tp->t_outq, dp->p_mem-tp->t_outq.c_cf); 32817Sbill if (tp->t_line) 32917Sbill (*linesw[tp->t_line].l_start)(tp); 33017Sbill else 33117Sbill dzstart(tp); 33217Sbill if (tp->t_outq.c_cc == 0 || (tp->t_state&BUSY)==0) 3332395Swnj dp->p_addr->dztcr &= ~(1 << (minor(tp->t_dev)&07)); 334145Sbill splx(s); 33517Sbill } 33617Sbill 33717Sbill dzstart(tp) 3382395Swnj register struct tty *tp; 33917Sbill { 34017Sbill register struct pdma *dp; 34117Sbill register struct device *dzaddr; 3422395Swnj register int cc; 3432395Swnj int s; 34417Sbill 3452395Swnj dp = (struct pdma *)tp->t_addr; 34617Sbill dzaddr = dp->p_addr; 3472395Swnj s = spl5(); 34817Sbill if (tp->t_state & (TIMEOUT|BUSY|TTSTOP)) 34917Sbill goto out; 350921Sbill if (tp->t_state&ASLEEP && tp->t_outq.c_cc <= TTLOWAT(tp)) { 35117Sbill tp->t_state &= ~ASLEEP; 35217Sbill if (tp->t_chan) 35317Sbill mcstart(tp->t_chan, (caddr_t)&tp->t_outq); 35417Sbill else 35517Sbill wakeup((caddr_t)&tp->t_outq); 35617Sbill } 35717Sbill if (tp->t_outq.c_cc == 0) 35817Sbill goto out; 35917Sbill if (tp->t_flags&RAW) 36017Sbill cc = ndqb(&tp->t_outq, 0); 36117Sbill else { 36217Sbill cc = ndqb(&tp->t_outq, 0200); 36317Sbill if (cc == 0) { 36417Sbill cc = getc(&tp->t_outq); 36517Sbill timeout(ttrstrt, (caddr_t)tp, (cc&0177) + 6); 36617Sbill tp->t_state |= TIMEOUT; 36717Sbill goto out; 36817Sbill } 36917Sbill } 37017Sbill tp->t_state |= BUSY; 37117Sbill dp->p_end = dp->p_mem = tp->t_outq.c_cf; 37217Sbill dp->p_end += cc; 3732395Swnj dzaddr->dztcr |= 1 << (minor(tp->t_dev) & 07); 3742395Swnj out: 3752395Swnj splx(s); 37617Sbill } 37717Sbill 37817Sbill /* 37917Sbill * Stop output on a line. 38017Sbill */ 38117Sbill /*ARGSUSED*/ 38217Sbill dzstop(tp, flag) 3832395Swnj register struct tty *tp; 38417Sbill { 38517Sbill register struct pdma *dp; 38617Sbill register int s; 38717Sbill 3882395Swnj dp = (struct pdma *)tp->t_addr; 38917Sbill s = spl6(); 39017Sbill if (tp->t_state & BUSY) { 39117Sbill dp->p_end = dp->p_mem; 3922395Swnj if ((tp->t_state&TTSTOP)==0) 39317Sbill tp->t_state |= FLUSH; 39417Sbill } 39517Sbill splx(s); 39617Sbill } 39717Sbill 3982395Swnj dzmodem(unit, flag) 3992395Swnj register int unit; 40017Sbill { 40117Sbill register struct device *dzaddr; 40217Sbill register char bit; 40317Sbill 4042395Swnj dzaddr = dzpdma[unit].p_addr; 4052395Swnj bit = 1<<(unit&07); 40617Sbill if (flag == OFF) 40717Sbill dzaddr->dzdtr &= ~bit; 40817Sbill else 40917Sbill dzaddr->dzdtr |= bit; 41017Sbill } 41117Sbill 41217Sbill dzscan() 41317Sbill { 41417Sbill register i; 41517Sbill register struct device *dzaddr; 41617Sbill register bit; 41717Sbill register struct tty *tp; 41817Sbill 41917Sbill for (i = 0; i < dz_cnt ; i++) { 42017Sbill dzaddr = dzpdma[i].p_addr; 42117Sbill tp = &dz_tty[i]; 42217Sbill bit = 1<<(i&07); 423*2422Skre #ifdef BERT 424*2422Skre if (dzaddr->dzmsr & bit || i == 6 || i == 7) { 425*2422Skre #else 426*2422Skre if (dzaddr->dzmsr & bit) { 427*2422Skre #endif 42817Sbill /* carrier present */ 42917Sbill if ((tp->t_state & CARR_ON) == 0) { 43017Sbill wakeup((caddr_t)&tp->t_rawq); 43117Sbill tp->t_state |= CARR_ON; 43217Sbill } 43317Sbill } else { 4342395Swnj if ((tp->t_state&CARR_ON) && (tp->t_local&LNOHANG)==0) { 43517Sbill /* carrier lost */ 436882Sbill if (tp->t_state&ISOPEN) { 437170Sbill gsignal(tp->t_pgrp, SIGHUP); 438205Sbill gsignal(tp->t_pgrp, SIGCONT); 439170Sbill dzaddr->dzdtr &= ~bit; 440871Sbill flushtty(tp, FREAD|FWRITE); 441170Sbill } 442170Sbill tp->t_state &= ~CARR_ON; 44317Sbill } 44417Sbill } 44517Sbill } 44617Sbill timeout(dzscan, (caddr_t)0, 2*HZ); 44717Sbill } 448119Sbill 449119Sbill dztimer() 450119Sbill { 451119Sbill 452119Sbill dzrint(0); 453119Sbill } 454281Sbill 455281Sbill /* 456281Sbill * Reset state of driver if UBA reset was necessary. 457301Sbill * Reset parameters and restart transmission on open lines. 458281Sbill */ 4592395Swnj dzreset(uban) 460*2422Skre int uban; 461281Sbill { 4622395Swnj register int unit; 463281Sbill register struct tty *tp; 464*2422Skre register struct uba_dinfo *ui; 465*2422Skre int any = 0; 466281Sbill 4672395Swnj for (unit = 0; unit < NDZ; unit++) { 468*2422Skre ui = dzinfo[unit >> 3]; 469*2422Skre if (ui == 0 || ui->ui_ubanum != uban || ui->ui_alive == 0) 470*2422Skre continue; 471*2422Skre if (any == 0) { 472*2422Skre printf(" dz"); 473*2422Skre any++; 474*2422Skre } 4752395Swnj tp = &dz_tty[unit]; 476281Sbill if (tp->t_state & (ISOPEN|WOPEN)) { 4772395Swnj dzparam(unit); 4782395Swnj dzmodem(unit, ON); 479301Sbill tp->t_state &= ~BUSY; 480301Sbill dzstart(tp); 481281Sbill } 482281Sbill } 483281Sbill dztimer(); 484281Sbill } 4851562Sbill #endif 486