1*145Sbill /* dz.c 3.5 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" 17*145Sbill 18*145Sbill /* 19*145Sbill * When running dz's using only SAE (silo alarm) on input 20*145Sbill * it is necessary to call dzrint() at clock interrupt time. 21*145Sbill * This is unsafe unless spl5()s in tty code are changed to 22*145Sbill * spl6()s to block clock interrupts. Note that the dh driver 23*145Sbill * currently in use works the same way as the dz, even though 24*145Sbill * we could try to more intelligently manage its silo. 25*145Sbill * Thus don't take this out if you have no dz's unless you 26*145Sbill * change clock.c and dhtimer(). 27*145Sbill */ 28*145Sbill #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 207119Sbill c = 0177; /* DEL = interrupt */ 208119Sbill if (c&OVERRUN) 209119Sbill printf("o"); 210119Sbill if (c&PERROR) 211119Sbill /* parity error */ 212119Sbill if (((tp->t_flags & (EVENP|ODDP)) == EVENP) 213119Sbill || ((tp->t_flags & (EVENP|ODDP)) == ODDP)) 214119Sbill continue; 215114Sbill #ifdef BERKNET 216140Sbill if (tp->t_line == NETLDISC) { 217114Sbill c &= 0177; 218114Sbill NETINPUT(c, tp); 219114Sbill } else 220114Sbill #endif 221114Sbill (*linesw[tp->t_line].l_rint)(c, tp); 222119Sbill } 22317Sbill } 224140Sbill splx(s); 22517Sbill } 22617Sbill 22717Sbill /*ARGSUSED*/ 22817Sbill dzioctl(dev, cmd, addr, flag) 22917Sbill caddr_t addr; 23017Sbill dev_t dev; 23117Sbill { 23217Sbill register struct tty *tp; 23317Sbill 23417Sbill tp = &dz_tty[minor(dev)]; 235114Sbill cmd = (*linesw[tp->t_line].l_ioctl)(tp, cmd, addr); 236114Sbill if (cmd == 0) 237114Sbill return; 23817Sbill if (ttioccomm(cmd, tp, addr, dev)) { 23917Sbill if (cmd==TIOCSETP || cmd==TIOCSETN) 24017Sbill dzparam(minor(dev)); 24117Sbill } else 24217Sbill u.u_error = ENOTTY; 24317Sbill } 24417Sbill 24517Sbill dzparam(dev) 24617Sbill { 24717Sbill register struct tty *tp; 24817Sbill register struct device *dzaddr; 24917Sbill register short lpr; 25017Sbill 25117Sbill tp = &dz_tty[dev]; 25217Sbill dzaddr = dzpdma[dev].p_addr; 25317Sbill dzaddr->dzcsr = DZ_IEN; 254119Sbill dzact |= (1<<(dev>>3)); 25517Sbill if (tp->t_ispeed == 0) { 25617Sbill dzmodem(dev, OFF); /* hang up line */ 25717Sbill return; 25817Sbill } 25917Sbill lpr = (dz_speeds[tp->t_ispeed]<<8) | (dev & 07); 26017Sbill if (tp->t_flags & RAW) 26117Sbill lpr |= BITS8; 26217Sbill else 26317Sbill lpr |= (BITS7|PENABLE); 26417Sbill if ((tp->t_flags & EVENP) == 0) 26517Sbill lpr |= OPAR; 26617Sbill if (tp->t_ispeed == 3) 26717Sbill lpr |= TWOSB; /* 110 baud: 2 stop bits */ 26817Sbill dzaddr->dzlpr = lpr; 26917Sbill } 27017Sbill 27117Sbill dzxint(tp) 27217Sbill register struct tty *tp; 27317Sbill { 27417Sbill register struct pdma *dp; 275*145Sbill register s; 276*145Sbill s = spl6(); /* block the clock */ 27717Sbill 27817Sbill dp = &dzpdma[tp-dz_tty]; 27917Sbill tp->t_state &= ~BUSY; 28017Sbill if (tp->t_state & FLUSH) 28117Sbill tp->t_state &= ~FLUSH; 28217Sbill else 28317Sbill ndflush(&tp->t_outq, dp->p_end-tp->t_outq.c_cf); 28417Sbill if (tp->t_line) 28517Sbill (*linesw[tp->t_line].l_start)(tp); 28617Sbill else 28717Sbill dzstart(tp); 28817Sbill if (tp->t_outq.c_cc == 0 || (tp->t_state&BUSY)==0) 28917Sbill dp->p_addr->dztcr &= ~(1 << ((tp-dz_tty) % 8)); 290*145Sbill splx(s); 29117Sbill } 29217Sbill 29317Sbill dzstart(tp) 29417Sbill register struct tty *tp; 29517Sbill { 29617Sbill register struct pdma *dp; 29717Sbill register struct device *dzaddr; 29817Sbill register cc; 29917Sbill int sps; 30017Sbill 30117Sbill dp = &dzpdma[tp-dz_tty]; 30217Sbill dzaddr = dp->p_addr; 30317Sbill sps = spl5(); 30417Sbill if (tp->t_state & (TIMEOUT|BUSY|TTSTOP)) 30517Sbill goto out; 30617Sbill if (tp->t_outq.c_cc <= TTLOWAT && tp->t_state&ASLEEP) { 30717Sbill tp->t_state &= ~ASLEEP; 30817Sbill if (tp->t_chan) 30917Sbill mcstart(tp->t_chan, (caddr_t)&tp->t_outq); 31017Sbill else 31117Sbill wakeup((caddr_t)&tp->t_outq); 31217Sbill } 31317Sbill if (tp->t_outq.c_cc == 0) 31417Sbill goto out; 31517Sbill if (tp->t_flags&RAW) 31617Sbill cc = ndqb(&tp->t_outq, 0); 31717Sbill else { 31817Sbill cc = ndqb(&tp->t_outq, 0200); 31917Sbill if (cc == 0) { 32017Sbill cc = getc(&tp->t_outq); 32117Sbill timeout(ttrstrt, (caddr_t)tp, (cc&0177) + 6); 32217Sbill tp->t_state |= TIMEOUT; 32317Sbill goto out; 32417Sbill } 32517Sbill } 32617Sbill tp->t_state |= BUSY; 32717Sbill dp->p_end = dp->p_mem = tp->t_outq.c_cf; 32817Sbill dp->p_end += cc; 32917Sbill dzaddr->dztcr |= 1 << ((tp-dz_tty) % 8); 33017Sbill out: 33117Sbill splx(sps); 33217Sbill } 33317Sbill 33417Sbill /* 33517Sbill * Stop output on a line. 33617Sbill * Assume call is made at spl6. 33717Sbill */ 33817Sbill /*ARGSUSED*/ 33917Sbill dzstop(tp, flag) 34017Sbill register struct tty *tp; 34117Sbill { 34217Sbill register struct pdma *dp; 34317Sbill register int s; 34417Sbill 34517Sbill dp = &dzpdma[tp-dz_tty]; 34617Sbill s = spl6(); 34717Sbill if (tp->t_state & BUSY) { 34817Sbill dp->p_end = dp->p_mem; 34917Sbill if ((tp->t_state&TTSTOP)==0) { 35017Sbill tp->t_state |= FLUSH; 35117Sbill } 35217Sbill } 35317Sbill splx(s); 35417Sbill } 35517Sbill 35617Sbill dzmodem(dev, flag) 35717Sbill register int dev; 35817Sbill { 35917Sbill register struct device *dzaddr; 36017Sbill register char bit; 36117Sbill 36217Sbill dzaddr = dzpdma[dev].p_addr; 36317Sbill bit = 1<<(dev&07); 36417Sbill if (flag == OFF) 36517Sbill dzaddr->dzdtr &= ~bit; 36617Sbill else 36717Sbill dzaddr->dzdtr |= bit; 36817Sbill } 36917Sbill 37017Sbill dzscan() 37117Sbill { 37217Sbill register i; 37317Sbill register struct device *dzaddr; 37417Sbill register bit; 37517Sbill register struct tty *tp; 37617Sbill 37717Sbill for (i = 0; i < dz_cnt ; i++) { 37817Sbill dzaddr = dzpdma[i].p_addr; 37917Sbill tp = &dz_tty[i]; 38017Sbill bit = 1<<(i&07); 38117Sbill if (dzaddr->dzmsr & bit) { 38217Sbill /* carrier present */ 38317Sbill if ((tp->t_state & CARR_ON) == 0) { 38417Sbill wakeup((caddr_t)&tp->t_rawq); 38517Sbill tp->t_state |= CARR_ON; 38617Sbill } 38717Sbill } else { 38817Sbill if ((tp->t_state & CARR_ON)) { 38917Sbill /* carrier lost */ 39017Sbill signal(tp->t_pgrp, SIGHUP); 39117Sbill dzaddr->dzdtr &= ~bit; 39217Sbill flushtty(tp); 39317Sbill } 39417Sbill tp->t_state &= ~CARR_ON; 39517Sbill } 39617Sbill } 39717Sbill timeout(dzscan, (caddr_t)0, 2*HZ); 39817Sbill } 399119Sbill 400119Sbill dztimer() 401119Sbill { 402119Sbill 403119Sbill dzrint(0); 404119Sbill } 405