1*170Sbill /* dz.c 3.6 10/14/12 */ 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; 6417Sbill 6517Sbill struct device { 6617Sbill short dzcsr; 6717Sbill short dzrbuf; 6817Sbill char dztcr; 6917Sbill char dzdtr; 7017Sbill char dztbuf; 7117Sbill char dzbrk; 7217Sbill }; 7317Sbill 7417Sbill struct pdma dzpdma[] = { 7517Sbill (struct device *)(DZADDR), NULL, NULL, (int)&dz_tty[0], dzxint, 7617Sbill (struct device *)(DZADDR), NULL, NULL, (int)&dz_tty[1], dzxint, 7717Sbill (struct device *)(DZADDR), NULL, NULL, (int)&dz_tty[2], dzxint, 7817Sbill (struct device *)(DZADDR), NULL, NULL, (int)&dz_tty[3], dzxint, 7917Sbill (struct device *)(DZADDR), NULL, NULL, (int)&dz_tty[4], dzxint, 8017Sbill (struct device *)(DZADDR), NULL, NULL, (int)&dz_tty[5], dzxint, 8117Sbill (struct device *)(DZADDR), NULL, NULL, (int)&dz_tty[6], dzxint, 8217Sbill (struct device *)(DZADDR), NULL, NULL, (int)&dz_tty[7], dzxint, 8317Sbill #ifdef ERNIE 8417Sbill (struct device *)(DZADDR+010), NULL, NULL, (int)&dz_tty[8], dzxint, 8517Sbill (struct device *)(DZADDR+010), NULL, NULL, (int)&dz_tty[9], dzxint, 8617Sbill (struct device *)(DZADDR+010), NULL, NULL, (int)&dz_tty[10], dzxint, 8717Sbill (struct device *)(DZADDR+010), NULL, NULL, (int)&dz_tty[11], dzxint, 8817Sbill (struct device *)(DZADDR+010), NULL, NULL, (int)&dz_tty[12], dzxint, 8917Sbill (struct device *)(DZADDR+010), NULL, NULL, (int)&dz_tty[13], dzxint, 9017Sbill (struct device *)(DZADDR+010), NULL, NULL, (int)&dz_tty[14], dzxint, 9117Sbill (struct device *)(DZADDR+010), NULL, NULL, (int)&dz_tty[15], dzxint, 9217Sbill (struct device *)(DZADDR+020), NULL, NULL, (int)&dz_tty[16], dzxint, 9317Sbill (struct device *)(DZADDR+020), NULL, NULL, (int)&dz_tty[17], dzxint, 9417Sbill (struct device *)(DZADDR+020), NULL, NULL, (int)&dz_tty[18], dzxint, 9517Sbill (struct device *)(DZADDR+020), NULL, NULL, (int)&dz_tty[19], dzxint, 9617Sbill (struct device *)(DZADDR+020), NULL, NULL, (int)&dz_tty[20], dzxint, 9717Sbill (struct device *)(DZADDR+020), NULL, NULL, (int)&dz_tty[21], dzxint, 9817Sbill (struct device *)(DZADDR+020), NULL, NULL, (int)&dz_tty[22], dzxint, 9917Sbill (struct device *)(DZADDR+020), NULL, NULL, (int)&dz_tty[23], dzxint, 10017Sbill #endif 10117Sbill }; 10217Sbill char dz_timer; 10317Sbill char dz_speeds[] = { 10417Sbill 0, 020 , 021 , 022 , 023 , 024 , 0, 025, 10517Sbill 026 , 027 , 030 , 032 , 034 , 036 , 0 , 0, 10617Sbill }; 10717Sbill 10817Sbill /*ARGSUSED*/ 10917Sbill dzopen(d, flag) 11017Sbill { 11117Sbill register struct tty *tp; 11217Sbill register dev; 11317Sbill extern dzscan(); 11417Sbill 11517Sbill dev = minor(d); 11617Sbill if (dev >= dz_cnt) { 11717Sbill u.u_error = ENXIO; 11817Sbill return; 11917Sbill } 12017Sbill if (dz_timer == 0) { 12117Sbill dz_timer++; 12217Sbill timeout(dzscan, (caddr_t)0, 60); 12317Sbill } 12417Sbill tp = &dz_tty[dev]; 12517Sbill tp->t_addr = (caddr_t)&dzpdma[dev]; 12617Sbill tp->t_oproc = dzstart; 12717Sbill tp->t_iproc = NULL; 12817Sbill tp->t_state |= WOPEN; 12917Sbill if ((tp->t_state & ISOPEN) == 0) { 13017Sbill ttychars(tp); 13117Sbill tp->t_ospeed = tp->t_ispeed = SSPEED; 13217Sbill tp->t_flags = ODDP|EVENP|ECHO; 13317Sbill /*tp->t_state |= HUPCLS;*/ 13417Sbill dzparam(dev); 13517Sbill } else if (tp->t_state&XCLUDE && u.u_uid != 0) { 13617Sbill u.u_error = EBUSY; 13717Sbill return; 13817Sbill } 13917Sbill dzmodem(dev, ON); 140114Sbill (void) spl5(); 14117Sbill while ((tp->t_state & CARR_ON) == 0) { 14217Sbill tp->t_state |= WOPEN; 14317Sbill sleep((caddr_t)&tp->t_rawq, TTIPRI); 14417Sbill } 145114Sbill (void) spl0(); 14617Sbill (*linesw[tp->t_line].l_open)(d, tp); 14717Sbill } 14817Sbill 14917Sbill dzclose(d) 15017Sbill { 15117Sbill register struct tty *tp; 15217Sbill register dev; 15317Sbill 15417Sbill dev = minor(d); 15517Sbill tp = &dz_tty[dev]; 15617Sbill (*linesw[tp->t_line].l_close)(tp); 15717Sbill if (tp->t_state & HUPCLS) 15817Sbill dzmodem(dev, OFF); 15917Sbill ttyclose(tp); 16017Sbill } 16117Sbill 16217Sbill dzread(d) 16317Sbill { 16417Sbill register struct tty *tp; 16517Sbill 16617Sbill tp = &dz_tty[minor(d)]; 16717Sbill (*linesw[tp->t_line].l_read)(tp); 16817Sbill } 16917Sbill 17017Sbill dzwrite(d) 17117Sbill { 17217Sbill register struct tty *tp; 17317Sbill 17417Sbill tp = &dz_tty[minor(d)]; 17517Sbill (*linesw[tp->t_line].l_write)(tp); 17617Sbill } 17717Sbill 178119Sbill /*ARGSUSED*/ 17917Sbill dzrint(dev) 18017Sbill { 18117Sbill register struct tty *tp; 18217Sbill register int c; 18317Sbill register struct device *dzaddr; 184119Sbill register struct tty *tp0; 185140Sbill int s; 18617Sbill 187140Sbill s = spl6(); /* see comment in clock.c */ 188119Sbill /* as long as we are here, service them all */ 189119Sbill for (dev = 0; dev < NDZ; dev += 8) { 190119Sbill if ((dzact & (1<<(dev>>3))) == 0) 19117Sbill continue; 192119Sbill dzaddr = dzpdma[dev].p_addr; 193119Sbill tp0 = &dz_tty[dev]; 194119Sbill while ((c = dzaddr->dzrbuf) < 0) { /* char present */ 195119Sbill tp = tp0 + ((c>>8)&07); 196119Sbill if (tp >= &dz_tty[dz_cnt]) 19717Sbill continue; 198119Sbill if ((tp->t_state & ISOPEN) == 0) { 199119Sbill wakeup((caddr_t)&tp->t_rawq); 200119Sbill continue; 201119Sbill } 202119Sbill if (c&FRERROR) 203119Sbill /* framing error = break */ 204119Sbill if (tp->t_flags & RAW) 205119Sbill c = 0; /* null for getty */ 206119Sbill else 207*170Sbill #ifdef IIASA 208*170Sbill continue; 209*170Sbill #else 210*170Sbill c = 0177; /* tun.t_intrc? */ 211*170Sbill #endif 212119Sbill if (c&OVERRUN) 213119Sbill printf("o"); 214119Sbill if (c&PERROR) 215119Sbill /* parity error */ 216119Sbill if (((tp->t_flags & (EVENP|ODDP)) == EVENP) 217119Sbill || ((tp->t_flags & (EVENP|ODDP)) == ODDP)) 218119Sbill continue; 219140Sbill if (tp->t_line == NETLDISC) { 220114Sbill c &= 0177; 221*170Sbill BKINPUT(c, tp); 222114Sbill } else 223114Sbill (*linesw[tp->t_line].l_rint)(c, tp); 224119Sbill } 22517Sbill } 226140Sbill splx(s); 22717Sbill } 22817Sbill 22917Sbill /*ARGSUSED*/ 23017Sbill dzioctl(dev, cmd, addr, flag) 23117Sbill caddr_t addr; 23217Sbill dev_t dev; 23317Sbill { 23417Sbill register struct tty *tp; 23517Sbill 23617Sbill tp = &dz_tty[minor(dev)]; 237114Sbill cmd = (*linesw[tp->t_line].l_ioctl)(tp, cmd, addr); 238114Sbill if (cmd == 0) 239114Sbill return; 24017Sbill if (ttioccomm(cmd, tp, addr, dev)) { 24117Sbill if (cmd==TIOCSETP || cmd==TIOCSETN) 24217Sbill dzparam(minor(dev)); 243*170Sbill } else switch(cmd) { 244*170Sbill case TIOCSBRK: 245*170Sbill ((struct device *)(tp->t_addr))->dzbrk |= 1 << (dev&07); 246*170Sbill break; 247*170Sbill case TIOCCBRK: 248*170Sbill ((struct device *)(tp->t_addr))->dzbrk &= ~(1 << (dev&07)); 249*170Sbill break; 250*170Sbill case TIOCSDTR: 251*170Sbill dzmodem(dev, ON); 252*170Sbill break; 253*170Sbill case TIOCCDTR: 254*170Sbill dzmodem(dev, OFF); 255*170Sbill break; 256*170Sbill default: 25717Sbill u.u_error = ENOTTY; 258*170Sbill } 25917Sbill } 26017Sbill 26117Sbill dzparam(dev) 26217Sbill { 26317Sbill register struct tty *tp; 26417Sbill register struct device *dzaddr; 26517Sbill register short lpr; 26617Sbill 26717Sbill tp = &dz_tty[dev]; 26817Sbill dzaddr = dzpdma[dev].p_addr; 26917Sbill dzaddr->dzcsr = DZ_IEN; 270119Sbill dzact |= (1<<(dev>>3)); 27117Sbill if (tp->t_ispeed == 0) { 27217Sbill dzmodem(dev, OFF); /* hang up line */ 27317Sbill return; 27417Sbill } 27517Sbill lpr = (dz_speeds[tp->t_ispeed]<<8) | (dev & 07); 27617Sbill if (tp->t_flags & RAW) 27717Sbill lpr |= BITS8; 27817Sbill else 27917Sbill lpr |= (BITS7|PENABLE); 28017Sbill if ((tp->t_flags & EVENP) == 0) 28117Sbill lpr |= OPAR; 28217Sbill if (tp->t_ispeed == 3) 28317Sbill lpr |= TWOSB; /* 110 baud: 2 stop bits */ 28417Sbill dzaddr->dzlpr = lpr; 28517Sbill } 28617Sbill 28717Sbill dzxint(tp) 28817Sbill register struct tty *tp; 28917Sbill { 29017Sbill register struct pdma *dp; 291145Sbill register s; 292145Sbill s = spl6(); /* block the clock */ 29317Sbill 29417Sbill dp = &dzpdma[tp-dz_tty]; 29517Sbill tp->t_state &= ~BUSY; 29617Sbill if (tp->t_state & FLUSH) 29717Sbill tp->t_state &= ~FLUSH; 29817Sbill else 29917Sbill ndflush(&tp->t_outq, dp->p_end-tp->t_outq.c_cf); 30017Sbill if (tp->t_line) 30117Sbill (*linesw[tp->t_line].l_start)(tp); 30217Sbill else 30317Sbill dzstart(tp); 30417Sbill if (tp->t_outq.c_cc == 0 || (tp->t_state&BUSY)==0) 30517Sbill dp->p_addr->dztcr &= ~(1 << ((tp-dz_tty) % 8)); 306145Sbill splx(s); 30717Sbill } 30817Sbill 30917Sbill dzstart(tp) 31017Sbill register struct tty *tp; 31117Sbill { 31217Sbill register struct pdma *dp; 31317Sbill register struct device *dzaddr; 31417Sbill register cc; 31517Sbill int sps; 31617Sbill 31717Sbill dp = &dzpdma[tp-dz_tty]; 31817Sbill dzaddr = dp->p_addr; 31917Sbill sps = spl5(); 32017Sbill if (tp->t_state & (TIMEOUT|BUSY|TTSTOP)) 32117Sbill goto out; 32217Sbill if (tp->t_outq.c_cc <= TTLOWAT && tp->t_state&ASLEEP) { 32317Sbill tp->t_state &= ~ASLEEP; 32417Sbill if (tp->t_chan) 32517Sbill mcstart(tp->t_chan, (caddr_t)&tp->t_outq); 32617Sbill else 32717Sbill wakeup((caddr_t)&tp->t_outq); 32817Sbill } 32917Sbill if (tp->t_outq.c_cc == 0) 33017Sbill goto out; 33117Sbill if (tp->t_flags&RAW) 33217Sbill cc = ndqb(&tp->t_outq, 0); 33317Sbill else { 33417Sbill cc = ndqb(&tp->t_outq, 0200); 33517Sbill if (cc == 0) { 33617Sbill cc = getc(&tp->t_outq); 33717Sbill timeout(ttrstrt, (caddr_t)tp, (cc&0177) + 6); 33817Sbill tp->t_state |= TIMEOUT; 33917Sbill goto out; 34017Sbill } 34117Sbill } 34217Sbill tp->t_state |= BUSY; 34317Sbill dp->p_end = dp->p_mem = tp->t_outq.c_cf; 34417Sbill dp->p_end += cc; 34517Sbill dzaddr->dztcr |= 1 << ((tp-dz_tty) % 8); 34617Sbill out: 34717Sbill splx(sps); 34817Sbill } 34917Sbill 35017Sbill /* 35117Sbill * Stop output on a line. 35217Sbill * Assume call is made at spl6. 35317Sbill */ 35417Sbill /*ARGSUSED*/ 35517Sbill dzstop(tp, flag) 35617Sbill register struct tty *tp; 35717Sbill { 35817Sbill register struct pdma *dp; 35917Sbill register int s; 36017Sbill 36117Sbill dp = &dzpdma[tp-dz_tty]; 36217Sbill s = spl6(); 36317Sbill if (tp->t_state & BUSY) { 36417Sbill dp->p_end = dp->p_mem; 36517Sbill if ((tp->t_state&TTSTOP)==0) { 36617Sbill tp->t_state |= FLUSH; 36717Sbill } 36817Sbill } 36917Sbill splx(s); 37017Sbill } 37117Sbill 37217Sbill dzmodem(dev, flag) 37317Sbill register int dev; 37417Sbill { 37517Sbill register struct device *dzaddr; 37617Sbill register char bit; 37717Sbill 37817Sbill dzaddr = dzpdma[dev].p_addr; 37917Sbill bit = 1<<(dev&07); 38017Sbill if (flag == OFF) 38117Sbill dzaddr->dzdtr &= ~bit; 38217Sbill else 38317Sbill dzaddr->dzdtr |= bit; 38417Sbill } 38517Sbill 38617Sbill dzscan() 38717Sbill { 38817Sbill register i; 38917Sbill register struct device *dzaddr; 39017Sbill register bit; 39117Sbill register struct tty *tp; 39217Sbill 39317Sbill for (i = 0; i < dz_cnt ; i++) { 39417Sbill dzaddr = dzpdma[i].p_addr; 39517Sbill tp = &dz_tty[i]; 39617Sbill bit = 1<<(i&07); 39717Sbill if (dzaddr->dzmsr & bit) { 39817Sbill /* carrier present */ 39917Sbill if ((tp->t_state & CARR_ON) == 0) { 40017Sbill wakeup((caddr_t)&tp->t_rawq); 40117Sbill tp->t_state |= CARR_ON; 40217Sbill } 40317Sbill } else { 40417Sbill if ((tp->t_state & CARR_ON)) { 40517Sbill /* carrier lost */ 406*170Sbill if (tp->t_state&ISOPEN && 407*170Sbill (tp->t_local&LNOHANG) == 0) { 408*170Sbill gsignal(tp->t_pgrp, SIGHUP); 409*170Sbill dzaddr->dzdtr &= ~bit; 410*170Sbill flushtty(tp); 411*170Sbill } 412*170Sbill tp->t_state &= ~CARR_ON; 41317Sbill } 41417Sbill } 41517Sbill } 41617Sbill timeout(dzscan, (caddr_t)0, 2*HZ); 41717Sbill } 418119Sbill 419119Sbill dztimer() 420119Sbill { 421119Sbill 422119Sbill dzrint(0); 423119Sbill } 424