1*301Sbill /* dz.c 3.12 06/23/80 */ 217Sbill 317Sbill /* 417Sbill * DZ-11 Driver 517Sbill */ 617Sbill #include "../h/param.h" 717Sbill #include "../h/systm.h" 817Sbill #include "../h/tty.h" 917Sbill #include "../h/dir.h" 1017Sbill #include "../h/user.h" 1117Sbill #include "../h/map.h" 1217Sbill #include "../h/pte.h" 1317Sbill #include "../h/uba.h" 1417Sbill #include "../h/conf.h" 1517Sbill #include "../h/pdma.h" 16114Sbill #include "../h/bk.h" 17145Sbill 18145Sbill /* 19145Sbill * When running dz's using only SAE (silo alarm) on input 20145Sbill * it is necessary to call dzrint() at clock interrupt time. 21145Sbill * This is unsafe unless spl5()s in tty code are changed to 22145Sbill * spl6()s to block clock interrupts. Note that the dh driver 23145Sbill * currently in use works the same way as the dz, even though 24145Sbill * we could try to more intelligently manage its silo. 25145Sbill * Thus don't take this out if you have no dz's unless you 26145Sbill * change clock.c and dhtimer(). 27145Sbill */ 28145Sbill #define spl5 spl6 2917Sbill 3017Sbill #define DZADDR (UBA0_DEV + 0160100) 3117Sbill #ifdef ERNIE 3217Sbill #define NDZ (3*8) 3317Sbill #else 3417Sbill #define NDZ (8) 3517Sbill #endif 3617Sbill 3717Sbill #define BITS7 020 3817Sbill #define BITS8 030 3917Sbill #define TWOSB 040 4017Sbill #define PENABLE 0100 4117Sbill #define OPAR 0200 4217Sbill #define MSE 040 /* Master Scan Enable */ 4317Sbill #define RIE 0100 /* Receiver Interrupt Enable */ 44119Sbill #define SAE 010000 /* Silo Alarm Enable */ 45119Sbill #define TIE 040000 /* Transmit Interrupt Enable */ 46119Sbill #define DZ_IEN (MSE+RIE+TIE+SAE) 4717Sbill #define PERROR 010000 4817Sbill #define FRERROR 020000 49119Sbill #define OVERRUN 040000 5017Sbill #define SSPEED 7 /* std speed = 300 baud */ 5117Sbill 5217Sbill 5317Sbill #define dzlpr dzrbuf 5417Sbill #define dzmsr dzbrk 5517Sbill #define ON 1 5617Sbill #define OFF 0 5717Sbill 5817Sbill int dzstart(); 5917Sbill int dzxint(); 60114Sbill int ttrstrt(); 6117Sbill struct tty dz_tty[NDZ]; 6217Sbill int dz_cnt = { NDZ }; 63119Sbill int dzact; 64281Sbill int dzinit; 6517Sbill 6617Sbill struct device { 6717Sbill short dzcsr; 6817Sbill short dzrbuf; 6917Sbill char dztcr; 7017Sbill char dzdtr; 7117Sbill char dztbuf; 7217Sbill char dzbrk; 7317Sbill }; 7417Sbill 7517Sbill struct pdma dzpdma[] = { 7617Sbill (struct device *)(DZADDR), NULL, NULL, (int)&dz_tty[0], dzxint, 7717Sbill (struct device *)(DZADDR), NULL, NULL, (int)&dz_tty[1], dzxint, 7817Sbill (struct device *)(DZADDR), NULL, NULL, (int)&dz_tty[2], dzxint, 7917Sbill (struct device *)(DZADDR), NULL, NULL, (int)&dz_tty[3], dzxint, 8017Sbill (struct device *)(DZADDR), NULL, NULL, (int)&dz_tty[4], dzxint, 8117Sbill (struct device *)(DZADDR), NULL, NULL, (int)&dz_tty[5], dzxint, 8217Sbill (struct device *)(DZADDR), NULL, NULL, (int)&dz_tty[6], dzxint, 8317Sbill (struct device *)(DZADDR), NULL, NULL, (int)&dz_tty[7], dzxint, 8417Sbill #ifdef ERNIE 8517Sbill (struct device *)(DZADDR+010), NULL, NULL, (int)&dz_tty[8], dzxint, 8617Sbill (struct device *)(DZADDR+010), NULL, NULL, (int)&dz_tty[9], dzxint, 8717Sbill (struct device *)(DZADDR+010), NULL, NULL, (int)&dz_tty[10], dzxint, 8817Sbill (struct device *)(DZADDR+010), NULL, NULL, (int)&dz_tty[11], dzxint, 8917Sbill (struct device *)(DZADDR+010), NULL, NULL, (int)&dz_tty[12], dzxint, 9017Sbill (struct device *)(DZADDR+010), NULL, NULL, (int)&dz_tty[13], dzxint, 9117Sbill (struct device *)(DZADDR+010), NULL, NULL, (int)&dz_tty[14], dzxint, 9217Sbill (struct device *)(DZADDR+010), NULL, NULL, (int)&dz_tty[15], dzxint, 9317Sbill (struct device *)(DZADDR+020), NULL, NULL, (int)&dz_tty[16], dzxint, 9417Sbill (struct device *)(DZADDR+020), NULL, NULL, (int)&dz_tty[17], dzxint, 9517Sbill (struct device *)(DZADDR+020), NULL, NULL, (int)&dz_tty[18], dzxint, 9617Sbill (struct device *)(DZADDR+020), NULL, NULL, (int)&dz_tty[19], dzxint, 9717Sbill (struct device *)(DZADDR+020), NULL, NULL, (int)&dz_tty[20], dzxint, 9817Sbill (struct device *)(DZADDR+020), NULL, NULL, (int)&dz_tty[21], dzxint, 9917Sbill (struct device *)(DZADDR+020), NULL, NULL, (int)&dz_tty[22], dzxint, 10017Sbill (struct device *)(DZADDR+020), NULL, NULL, (int)&dz_tty[23], dzxint, 10117Sbill #endif 10217Sbill }; 10317Sbill char dz_timer; 10417Sbill char dz_speeds[] = { 10517Sbill 0, 020 , 021 , 022 , 023 , 024 , 0, 025, 10617Sbill 026 , 027 , 030 , 032 , 034 , 036 , 0 , 0, 10717Sbill }; 10817Sbill 10917Sbill /*ARGSUSED*/ 11017Sbill dzopen(d, flag) 11117Sbill { 11217Sbill register struct tty *tp; 11317Sbill register dev; 11417Sbill extern dzscan(); 11517Sbill 11617Sbill dev = minor(d); 11717Sbill if (dev >= dz_cnt) { 11817Sbill u.u_error = ENXIO; 11917Sbill return; 12017Sbill } 12117Sbill if (dz_timer == 0) { 12217Sbill dz_timer++; 12317Sbill timeout(dzscan, (caddr_t)0, 60); 12417Sbill } 12517Sbill tp = &dz_tty[dev]; 12617Sbill tp->t_addr = (caddr_t)&dzpdma[dev]; 12717Sbill tp->t_oproc = dzstart; 12817Sbill tp->t_iproc = NULL; 12917Sbill tp->t_state |= WOPEN; 13017Sbill if ((tp->t_state & ISOPEN) == 0) { 13117Sbill ttychars(tp); 13217Sbill tp->t_ospeed = tp->t_ispeed = SSPEED; 13317Sbill tp->t_flags = ODDP|EVENP|ECHO; 13417Sbill /*tp->t_state |= HUPCLS;*/ 13517Sbill dzparam(dev); 13617Sbill } else if (tp->t_state&XCLUDE && u.u_uid != 0) { 13717Sbill u.u_error = EBUSY; 13817Sbill return; 13917Sbill } 14017Sbill dzmodem(dev, ON); 141114Sbill (void) spl5(); 14217Sbill while ((tp->t_state & CARR_ON) == 0) { 14317Sbill tp->t_state |= WOPEN; 14417Sbill sleep((caddr_t)&tp->t_rawq, TTIPRI); 14517Sbill } 146114Sbill (void) spl0(); 14717Sbill (*linesw[tp->t_line].l_open)(d, tp); 14817Sbill } 14917Sbill 15017Sbill dzclose(d) 15117Sbill { 15217Sbill register struct tty *tp; 15317Sbill register dev; 15417Sbill 15517Sbill dev = minor(d); 15617Sbill tp = &dz_tty[dev]; 15717Sbill (*linesw[tp->t_line].l_close)(tp); 15817Sbill if (tp->t_state & HUPCLS) 15917Sbill dzmodem(dev, OFF); 16017Sbill ttyclose(tp); 16117Sbill } 16217Sbill 16317Sbill dzread(d) 16417Sbill { 16517Sbill register struct tty *tp; 16617Sbill 16717Sbill tp = &dz_tty[minor(d)]; 16817Sbill (*linesw[tp->t_line].l_read)(tp); 16917Sbill } 17017Sbill 17117Sbill dzwrite(d) 17217Sbill { 17317Sbill register struct tty *tp; 17417Sbill 17517Sbill tp = &dz_tty[minor(d)]; 17617Sbill (*linesw[tp->t_line].l_write)(tp); 17717Sbill } 17817Sbill 179119Sbill /*ARGSUSED*/ 18017Sbill dzrint(dev) 18117Sbill { 18217Sbill register struct tty *tp; 18317Sbill register int c; 18417Sbill register struct device *dzaddr; 185119Sbill register struct tty *tp0; 186140Sbill int s; 18717Sbill 188140Sbill s = spl6(); /* see comment in clock.c */ 189119Sbill /* as long as we are here, service them all */ 190119Sbill for (dev = 0; dev < NDZ; dev += 8) { 191119Sbill if ((dzact & (1<<(dev>>3))) == 0) 19217Sbill continue; 193119Sbill dzaddr = dzpdma[dev].p_addr; 194119Sbill tp0 = &dz_tty[dev]; 195119Sbill while ((c = dzaddr->dzrbuf) < 0) { /* char present */ 196119Sbill tp = tp0 + ((c>>8)&07); 197119Sbill if (tp >= &dz_tty[dz_cnt]) 19817Sbill continue; 199119Sbill if ((tp->t_state & ISOPEN) == 0) { 200119Sbill wakeup((caddr_t)&tp->t_rawq); 201119Sbill continue; 202119Sbill } 203119Sbill if (c&FRERROR) 204119Sbill /* framing error = break */ 205119Sbill if (tp->t_flags & RAW) 206119Sbill c = 0; /* null for getty */ 207119Sbill else 208170Sbill #ifdef IIASA 209170Sbill continue; 210170Sbill #else 211185Sbill c = tun.t_intrc; 212170Sbill #endif 213119Sbill if (c&OVERRUN) 214119Sbill printf("o"); 215119Sbill if (c&PERROR) 216119Sbill /* parity error */ 217119Sbill if (((tp->t_flags & (EVENP|ODDP)) == EVENP) 218119Sbill || ((tp->t_flags & (EVENP|ODDP)) == ODDP)) 219119Sbill continue; 220140Sbill if (tp->t_line == NETLDISC) { 221114Sbill c &= 0177; 222170Sbill BKINPUT(c, tp); 223114Sbill } else 224114Sbill (*linesw[tp->t_line].l_rint)(c, tp); 225119Sbill } 22617Sbill } 227140Sbill splx(s); 22817Sbill } 22917Sbill 23017Sbill /*ARGSUSED*/ 23117Sbill dzioctl(dev, cmd, addr, flag) 23217Sbill caddr_t addr; 23317Sbill dev_t dev; 23417Sbill { 23517Sbill register struct tty *tp; 23617Sbill 23717Sbill tp = &dz_tty[minor(dev)]; 238114Sbill cmd = (*linesw[tp->t_line].l_ioctl)(tp, cmd, addr); 239114Sbill if (cmd == 0) 240114Sbill return; 24117Sbill if (ttioccomm(cmd, tp, addr, dev)) { 24217Sbill if (cmd==TIOCSETP || cmd==TIOCSETN) 24317Sbill dzparam(minor(dev)); 244170Sbill } else switch(cmd) { 245170Sbill case TIOCSBRK: 246170Sbill ((struct device *)(tp->t_addr))->dzbrk |= 1 << (dev&07); 247170Sbill break; 248170Sbill case TIOCCBRK: 249170Sbill ((struct device *)(tp->t_addr))->dzbrk &= ~(1 << (dev&07)); 250170Sbill break; 251170Sbill case TIOCSDTR: 252210Sbill dzmodem(minor(dev), ON); 253170Sbill break; 254170Sbill case TIOCCDTR: 255210Sbill dzmodem(minor(dev), OFF); 256170Sbill break; 257170Sbill default: 25817Sbill u.u_error = ENOTTY; 259170Sbill } 26017Sbill } 26117Sbill 26217Sbill dzparam(dev) 26317Sbill { 26417Sbill register struct tty *tp; 26517Sbill register struct device *dzaddr; 26617Sbill register short lpr; 26717Sbill 26817Sbill tp = &dz_tty[dev]; 26917Sbill dzaddr = dzpdma[dev].p_addr; 27017Sbill dzaddr->dzcsr = DZ_IEN; 271119Sbill dzact |= (1<<(dev>>3)); 27217Sbill if (tp->t_ispeed == 0) { 27317Sbill dzmodem(dev, OFF); /* hang up line */ 27417Sbill return; 27517Sbill } 27617Sbill lpr = (dz_speeds[tp->t_ispeed]<<8) | (dev & 07); 27717Sbill if (tp->t_flags & RAW) 27817Sbill lpr |= BITS8; 27917Sbill else 28017Sbill lpr |= (BITS7|PENABLE); 28117Sbill if ((tp->t_flags & EVENP) == 0) 28217Sbill lpr |= OPAR; 28317Sbill if (tp->t_ispeed == 3) 28417Sbill lpr |= TWOSB; /* 110 baud: 2 stop bits */ 28517Sbill dzaddr->dzlpr = lpr; 28617Sbill } 28717Sbill 28817Sbill dzxint(tp) 28917Sbill register struct tty *tp; 29017Sbill { 29117Sbill register struct pdma *dp; 292145Sbill register s; 293145Sbill s = spl6(); /* block the clock */ 29417Sbill 29517Sbill dp = &dzpdma[tp-dz_tty]; 29617Sbill tp->t_state &= ~BUSY; 29717Sbill if (tp->t_state & FLUSH) 29817Sbill tp->t_state &= ~FLUSH; 29917Sbill else 300281Sbill ndflush(&tp->t_outq, dp->p_mem-tp->t_outq.c_cf); 30117Sbill if (tp->t_line) 30217Sbill (*linesw[tp->t_line].l_start)(tp); 30317Sbill else 30417Sbill dzstart(tp); 30517Sbill if (tp->t_outq.c_cc == 0 || (tp->t_state&BUSY)==0) 30617Sbill dp->p_addr->dztcr &= ~(1 << ((tp-dz_tty) % 8)); 307145Sbill splx(s); 30817Sbill } 30917Sbill 31017Sbill dzstart(tp) 31117Sbill register struct tty *tp; 31217Sbill { 31317Sbill register struct pdma *dp; 31417Sbill register struct device *dzaddr; 31517Sbill register cc; 31617Sbill int sps; 31717Sbill 31817Sbill dp = &dzpdma[tp-dz_tty]; 31917Sbill dzaddr = dp->p_addr; 32017Sbill sps = spl5(); 32117Sbill if (tp->t_state & (TIMEOUT|BUSY|TTSTOP)) 32217Sbill goto out; 32317Sbill if (tp->t_outq.c_cc <= TTLOWAT && tp->t_state&ASLEEP) { 32417Sbill tp->t_state &= ~ASLEEP; 32517Sbill if (tp->t_chan) 32617Sbill mcstart(tp->t_chan, (caddr_t)&tp->t_outq); 32717Sbill else 32817Sbill wakeup((caddr_t)&tp->t_outq); 32917Sbill } 33017Sbill if (tp->t_outq.c_cc == 0) 33117Sbill goto out; 33217Sbill if (tp->t_flags&RAW) 33317Sbill cc = ndqb(&tp->t_outq, 0); 33417Sbill else { 33517Sbill cc = ndqb(&tp->t_outq, 0200); 33617Sbill if (cc == 0) { 33717Sbill cc = getc(&tp->t_outq); 33817Sbill timeout(ttrstrt, (caddr_t)tp, (cc&0177) + 6); 33917Sbill tp->t_state |= TIMEOUT; 34017Sbill goto out; 34117Sbill } 34217Sbill } 34317Sbill tp->t_state |= BUSY; 34417Sbill dp->p_end = dp->p_mem = tp->t_outq.c_cf; 34517Sbill dp->p_end += cc; 34617Sbill dzaddr->dztcr |= 1 << ((tp-dz_tty) % 8); 34717Sbill out: 34817Sbill splx(sps); 34917Sbill } 35017Sbill 35117Sbill /* 35217Sbill * Stop output on a line. 35317Sbill * Assume call is made at spl6. 35417Sbill */ 35517Sbill /*ARGSUSED*/ 35617Sbill dzstop(tp, flag) 35717Sbill register struct tty *tp; 35817Sbill { 35917Sbill register struct pdma *dp; 36017Sbill register int s; 36117Sbill 36217Sbill dp = &dzpdma[tp-dz_tty]; 36317Sbill s = spl6(); 36417Sbill if (tp->t_state & BUSY) { 36517Sbill dp->p_end = dp->p_mem; 36617Sbill if ((tp->t_state&TTSTOP)==0) { 36717Sbill tp->t_state |= FLUSH; 36817Sbill } 36917Sbill } 37017Sbill splx(s); 37117Sbill } 37217Sbill 37317Sbill dzmodem(dev, flag) 37417Sbill register int dev; 37517Sbill { 37617Sbill register struct device *dzaddr; 37717Sbill register char bit; 37817Sbill 37917Sbill dzaddr = dzpdma[dev].p_addr; 38017Sbill bit = 1<<(dev&07); 38117Sbill if (flag == OFF) 38217Sbill dzaddr->dzdtr &= ~bit; 38317Sbill else 38417Sbill dzaddr->dzdtr |= bit; 38517Sbill } 38617Sbill 38717Sbill dzscan() 38817Sbill { 38917Sbill register i; 39017Sbill register struct device *dzaddr; 39117Sbill register bit; 39217Sbill register struct tty *tp; 39317Sbill 39417Sbill for (i = 0; i < dz_cnt ; i++) { 39517Sbill dzaddr = dzpdma[i].p_addr; 39617Sbill tp = &dz_tty[i]; 39717Sbill bit = 1<<(i&07); 39817Sbill if (dzaddr->dzmsr & bit) { 39917Sbill /* carrier present */ 40017Sbill if ((tp->t_state & CARR_ON) == 0) { 40117Sbill wakeup((caddr_t)&tp->t_rawq); 40217Sbill tp->t_state |= CARR_ON; 40317Sbill } 40417Sbill } else { 40517Sbill if ((tp->t_state & CARR_ON)) { 40617Sbill /* carrier lost */ 407170Sbill if (tp->t_state&ISOPEN && 408170Sbill (tp->t_local&LNOHANG) == 0) { 409170Sbill gsignal(tp->t_pgrp, SIGHUP); 410205Sbill gsignal(tp->t_pgrp, SIGCONT); 411170Sbill dzaddr->dzdtr &= ~bit; 412170Sbill flushtty(tp); 413170Sbill } 414170Sbill tp->t_state &= ~CARR_ON; 41517Sbill } 41617Sbill } 41717Sbill } 41817Sbill timeout(dzscan, (caddr_t)0, 2*HZ); 41917Sbill } 420119Sbill 421119Sbill dztimer() 422119Sbill { 423119Sbill 424119Sbill dzrint(0); 425119Sbill } 426281Sbill 427281Sbill /* 428281Sbill * Reset state of driver if UBA reset was necessary. 429*301Sbill * Reset parameters and restart transmission on open lines. 430281Sbill */ 431281Sbill dzreset() 432281Sbill { 433281Sbill int d; 434281Sbill register struct tty *tp; 435281Sbill 436281Sbill printf(" dz"); 437281Sbill for (d = 0; d < NDZ; d++) { 438281Sbill tp = &dz_tty[d]; 439281Sbill if (tp->t_state & (ISOPEN|WOPEN)) { 440281Sbill dzparam(d); 441*301Sbill dzmodem(d, ON); 442*301Sbill tp->t_state &= ~BUSY; 443*301Sbill dzstart(tp); 444281Sbill } 445281Sbill } 446281Sbill dztimer(); 447281Sbill } 448