1*140Sbill /* dz.c 3.4 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" 1717Sbill 1817Sbill #define DZADDR (UBA0_DEV + 0160100) 1917Sbill #ifdef ERNIE 2017Sbill #define NDZ (3*8) 2117Sbill #else 2217Sbill #define NDZ (8) 2317Sbill #endif 2417Sbill 2517Sbill #define BITS7 020 2617Sbill #define BITS8 030 2717Sbill #define TWOSB 040 2817Sbill #define PENABLE 0100 2917Sbill #define OPAR 0200 3017Sbill #define MSE 040 /* Master Scan Enable */ 3117Sbill #define RIE 0100 /* Receiver Interrupt Enable */ 32119Sbill #define SAE 010000 /* Silo Alarm Enable */ 33119Sbill #define TIE 040000 /* Transmit Interrupt Enable */ 34119Sbill #define DZ_IEN (MSE+RIE+TIE+SAE) 3517Sbill #define PERROR 010000 3617Sbill #define FRERROR 020000 37119Sbill #define OVERRUN 040000 3817Sbill #define SSPEED 7 /* std speed = 300 baud */ 3917Sbill 4017Sbill 4117Sbill #define dzlpr dzrbuf 4217Sbill #define dzmsr dzbrk 4317Sbill #define ON 1 4417Sbill #define OFF 0 4517Sbill 4617Sbill int dzstart(); 4717Sbill int dzxint(); 48114Sbill int ttrstrt(); 4917Sbill struct tty dz_tty[NDZ]; 5017Sbill int dz_cnt = { NDZ }; 51119Sbill int dzact; 5217Sbill 5317Sbill struct device { 5417Sbill short dzcsr; 5517Sbill short dzrbuf; 5617Sbill char dztcr; 5717Sbill char dzdtr; 5817Sbill char dztbuf; 5917Sbill char dzbrk; 6017Sbill }; 6117Sbill 6217Sbill struct pdma dzpdma[] = { 6317Sbill (struct device *)(DZADDR), NULL, NULL, (int)&dz_tty[0], dzxint, 6417Sbill (struct device *)(DZADDR), NULL, NULL, (int)&dz_tty[1], dzxint, 6517Sbill (struct device *)(DZADDR), NULL, NULL, (int)&dz_tty[2], dzxint, 6617Sbill (struct device *)(DZADDR), NULL, NULL, (int)&dz_tty[3], dzxint, 6717Sbill (struct device *)(DZADDR), NULL, NULL, (int)&dz_tty[4], dzxint, 6817Sbill (struct device *)(DZADDR), NULL, NULL, (int)&dz_tty[5], dzxint, 6917Sbill (struct device *)(DZADDR), NULL, NULL, (int)&dz_tty[6], dzxint, 7017Sbill (struct device *)(DZADDR), NULL, NULL, (int)&dz_tty[7], dzxint, 7117Sbill #ifdef ERNIE 7217Sbill (struct device *)(DZADDR+010), NULL, NULL, (int)&dz_tty[8], dzxint, 7317Sbill (struct device *)(DZADDR+010), NULL, NULL, (int)&dz_tty[9], dzxint, 7417Sbill (struct device *)(DZADDR+010), NULL, NULL, (int)&dz_tty[10], dzxint, 7517Sbill (struct device *)(DZADDR+010), NULL, NULL, (int)&dz_tty[11], dzxint, 7617Sbill (struct device *)(DZADDR+010), NULL, NULL, (int)&dz_tty[12], dzxint, 7717Sbill (struct device *)(DZADDR+010), NULL, NULL, (int)&dz_tty[13], dzxint, 7817Sbill (struct device *)(DZADDR+010), NULL, NULL, (int)&dz_tty[14], dzxint, 7917Sbill (struct device *)(DZADDR+010), NULL, NULL, (int)&dz_tty[15], dzxint, 8017Sbill (struct device *)(DZADDR+020), NULL, NULL, (int)&dz_tty[16], dzxint, 8117Sbill (struct device *)(DZADDR+020), NULL, NULL, (int)&dz_tty[17], dzxint, 8217Sbill (struct device *)(DZADDR+020), NULL, NULL, (int)&dz_tty[18], dzxint, 8317Sbill (struct device *)(DZADDR+020), NULL, NULL, (int)&dz_tty[19], dzxint, 8417Sbill (struct device *)(DZADDR+020), NULL, NULL, (int)&dz_tty[20], dzxint, 8517Sbill (struct device *)(DZADDR+020), NULL, NULL, (int)&dz_tty[21], dzxint, 8617Sbill (struct device *)(DZADDR+020), NULL, NULL, (int)&dz_tty[22], dzxint, 8717Sbill (struct device *)(DZADDR+020), NULL, NULL, (int)&dz_tty[23], dzxint, 8817Sbill #endif 8917Sbill }; 9017Sbill char dz_timer; 9117Sbill char dz_speeds[] = { 9217Sbill 0, 020 , 021 , 022 , 023 , 024 , 0, 025, 9317Sbill 026 , 027 , 030 , 032 , 034 , 036 , 0 , 0, 9417Sbill }; 9517Sbill 9617Sbill /*ARGSUSED*/ 9717Sbill dzopen(d, flag) 9817Sbill { 9917Sbill register struct tty *tp; 10017Sbill register dev; 10117Sbill extern dzscan(); 10217Sbill 10317Sbill dev = minor(d); 10417Sbill if (dev >= dz_cnt) { 10517Sbill u.u_error = ENXIO; 10617Sbill return; 10717Sbill } 10817Sbill if (dz_timer == 0) { 10917Sbill dz_timer++; 11017Sbill timeout(dzscan, (caddr_t)0, 60); 11117Sbill } 11217Sbill tp = &dz_tty[dev]; 11317Sbill tp->t_addr = (caddr_t)&dzpdma[dev]; 11417Sbill tp->t_oproc = dzstart; 11517Sbill tp->t_iproc = NULL; 11617Sbill tp->t_state |= WOPEN; 11717Sbill if ((tp->t_state & ISOPEN) == 0) { 11817Sbill ttychars(tp); 11917Sbill tp->t_ospeed = tp->t_ispeed = SSPEED; 12017Sbill tp->t_flags = ODDP|EVENP|ECHO; 12117Sbill /*tp->t_state |= HUPCLS;*/ 12217Sbill dzparam(dev); 12317Sbill } else if (tp->t_state&XCLUDE && u.u_uid != 0) { 12417Sbill u.u_error = EBUSY; 12517Sbill return; 12617Sbill } 12717Sbill dzmodem(dev, ON); 128114Sbill (void) spl5(); 12917Sbill while ((tp->t_state & CARR_ON) == 0) { 13017Sbill tp->t_state |= WOPEN; 13117Sbill sleep((caddr_t)&tp->t_rawq, TTIPRI); 13217Sbill } 133114Sbill (void) spl0(); 13417Sbill (*linesw[tp->t_line].l_open)(d, tp); 13517Sbill } 13617Sbill 13717Sbill dzclose(d) 13817Sbill { 13917Sbill register struct tty *tp; 14017Sbill register dev; 14117Sbill 14217Sbill dev = minor(d); 14317Sbill tp = &dz_tty[dev]; 14417Sbill (*linesw[tp->t_line].l_close)(tp); 14517Sbill if (tp->t_state & HUPCLS) 14617Sbill dzmodem(dev, OFF); 14717Sbill ttyclose(tp); 14817Sbill } 14917Sbill 15017Sbill dzread(d) 15117Sbill { 15217Sbill register struct tty *tp; 15317Sbill 15417Sbill tp = &dz_tty[minor(d)]; 15517Sbill (*linesw[tp->t_line].l_read)(tp); 15617Sbill } 15717Sbill 15817Sbill dzwrite(d) 15917Sbill { 16017Sbill register struct tty *tp; 16117Sbill 16217Sbill tp = &dz_tty[minor(d)]; 16317Sbill (*linesw[tp->t_line].l_write)(tp); 16417Sbill } 16517Sbill 166119Sbill /*ARGSUSED*/ 16717Sbill dzrint(dev) 16817Sbill { 16917Sbill register struct tty *tp; 17017Sbill register int c; 17117Sbill register struct device *dzaddr; 172119Sbill register struct tty *tp0; 173*140Sbill int s; 17417Sbill 175*140Sbill s = spl6(); /* see comment in clock.c */ 176119Sbill /* as long as we are here, service them all */ 177119Sbill for (dev = 0; dev < NDZ; dev += 8) { 178119Sbill if ((dzact & (1<<(dev>>3))) == 0) 17917Sbill continue; 180119Sbill dzaddr = dzpdma[dev].p_addr; 181119Sbill tp0 = &dz_tty[dev]; 182119Sbill while ((c = dzaddr->dzrbuf) < 0) { /* char present */ 183119Sbill tp = tp0 + ((c>>8)&07); 184119Sbill if (tp >= &dz_tty[dz_cnt]) 18517Sbill continue; 186119Sbill if ((tp->t_state & ISOPEN) == 0) { 187119Sbill wakeup((caddr_t)&tp->t_rawq); 188119Sbill continue; 189119Sbill } 190119Sbill if (c&FRERROR) 191119Sbill /* framing error = break */ 192119Sbill if (tp->t_flags & RAW) 193119Sbill c = 0; /* null for getty */ 194119Sbill else 195119Sbill c = 0177; /* DEL = interrupt */ 196119Sbill if (c&OVERRUN) 197119Sbill printf("o"); 198119Sbill if (c&PERROR) 199119Sbill /* parity error */ 200119Sbill if (((tp->t_flags & (EVENP|ODDP)) == EVENP) 201119Sbill || ((tp->t_flags & (EVENP|ODDP)) == ODDP)) 202119Sbill continue; 203114Sbill #ifdef BERKNET 204*140Sbill if (tp->t_line == NETLDISC) { 205114Sbill c &= 0177; 206114Sbill NETINPUT(c, tp); 207114Sbill } else 208114Sbill #endif 209114Sbill (*linesw[tp->t_line].l_rint)(c, tp); 210119Sbill } 21117Sbill } 212*140Sbill splx(s); 21317Sbill } 21417Sbill 21517Sbill /*ARGSUSED*/ 21617Sbill dzioctl(dev, cmd, addr, flag) 21717Sbill caddr_t addr; 21817Sbill dev_t dev; 21917Sbill { 22017Sbill register struct tty *tp; 22117Sbill 22217Sbill tp = &dz_tty[minor(dev)]; 223114Sbill cmd = (*linesw[tp->t_line].l_ioctl)(tp, cmd, addr); 224114Sbill if (cmd == 0) 225114Sbill return; 22617Sbill if (ttioccomm(cmd, tp, addr, dev)) { 22717Sbill if (cmd==TIOCSETP || cmd==TIOCSETN) 22817Sbill dzparam(minor(dev)); 22917Sbill } else 23017Sbill u.u_error = ENOTTY; 23117Sbill } 23217Sbill 23317Sbill dzparam(dev) 23417Sbill { 23517Sbill register struct tty *tp; 23617Sbill register struct device *dzaddr; 23717Sbill register short lpr; 23817Sbill 23917Sbill tp = &dz_tty[dev]; 24017Sbill dzaddr = dzpdma[dev].p_addr; 24117Sbill dzaddr->dzcsr = DZ_IEN; 242119Sbill dzact |= (1<<(dev>>3)); 24317Sbill if (tp->t_ispeed == 0) { 24417Sbill dzmodem(dev, OFF); /* hang up line */ 24517Sbill return; 24617Sbill } 24717Sbill lpr = (dz_speeds[tp->t_ispeed]<<8) | (dev & 07); 24817Sbill if (tp->t_flags & RAW) 24917Sbill lpr |= BITS8; 25017Sbill else 25117Sbill lpr |= (BITS7|PENABLE); 25217Sbill if ((tp->t_flags & EVENP) == 0) 25317Sbill lpr |= OPAR; 25417Sbill if (tp->t_ispeed == 3) 25517Sbill lpr |= TWOSB; /* 110 baud: 2 stop bits */ 25617Sbill dzaddr->dzlpr = lpr; 25717Sbill } 25817Sbill 25917Sbill dzxint(tp) 26017Sbill register struct tty *tp; 26117Sbill { 26217Sbill register struct pdma *dp; 26317Sbill 26417Sbill dp = &dzpdma[tp-dz_tty]; 26517Sbill tp->t_state &= ~BUSY; 26617Sbill if (tp->t_state & FLUSH) 26717Sbill tp->t_state &= ~FLUSH; 26817Sbill else 26917Sbill ndflush(&tp->t_outq, dp->p_end-tp->t_outq.c_cf); 27017Sbill if (tp->t_line) 27117Sbill (*linesw[tp->t_line].l_start)(tp); 27217Sbill else 27317Sbill dzstart(tp); 27417Sbill if (tp->t_outq.c_cc == 0 || (tp->t_state&BUSY)==0) 27517Sbill dp->p_addr->dztcr &= ~(1 << ((tp-dz_tty) % 8)); 27617Sbill } 27717Sbill 27817Sbill dzstart(tp) 27917Sbill register struct tty *tp; 28017Sbill { 28117Sbill register struct pdma *dp; 28217Sbill register struct device *dzaddr; 28317Sbill register cc; 28417Sbill int sps; 28517Sbill 28617Sbill dp = &dzpdma[tp-dz_tty]; 28717Sbill dzaddr = dp->p_addr; 28817Sbill sps = spl5(); 28917Sbill if (tp->t_state & (TIMEOUT|BUSY|TTSTOP)) 29017Sbill goto out; 29117Sbill if (tp->t_outq.c_cc <= TTLOWAT && tp->t_state&ASLEEP) { 29217Sbill tp->t_state &= ~ASLEEP; 29317Sbill if (tp->t_chan) 29417Sbill mcstart(tp->t_chan, (caddr_t)&tp->t_outq); 29517Sbill else 29617Sbill wakeup((caddr_t)&tp->t_outq); 29717Sbill } 29817Sbill if (tp->t_outq.c_cc == 0) 29917Sbill goto out; 30017Sbill if (tp->t_flags&RAW) 30117Sbill cc = ndqb(&tp->t_outq, 0); 30217Sbill else { 30317Sbill cc = ndqb(&tp->t_outq, 0200); 30417Sbill if (cc == 0) { 30517Sbill cc = getc(&tp->t_outq); 30617Sbill timeout(ttrstrt, (caddr_t)tp, (cc&0177) + 6); 30717Sbill tp->t_state |= TIMEOUT; 30817Sbill goto out; 30917Sbill } 31017Sbill } 31117Sbill tp->t_state |= BUSY; 31217Sbill dp->p_end = dp->p_mem = tp->t_outq.c_cf; 31317Sbill dp->p_end += cc; 31417Sbill dzaddr->dztcr |= 1 << ((tp-dz_tty) % 8); 31517Sbill out: 31617Sbill splx(sps); 31717Sbill } 31817Sbill 31917Sbill /* 32017Sbill * Stop output on a line. 32117Sbill * Assume call is made at spl6. 32217Sbill */ 32317Sbill /*ARGSUSED*/ 32417Sbill dzstop(tp, flag) 32517Sbill register struct tty *tp; 32617Sbill { 32717Sbill register struct pdma *dp; 32817Sbill register int s; 32917Sbill 33017Sbill dp = &dzpdma[tp-dz_tty]; 33117Sbill s = spl6(); 33217Sbill if (tp->t_state & BUSY) { 33317Sbill dp->p_end = dp->p_mem; 33417Sbill if ((tp->t_state&TTSTOP)==0) { 33517Sbill tp->t_state |= FLUSH; 33617Sbill } 33717Sbill } 33817Sbill splx(s); 33917Sbill } 34017Sbill 34117Sbill dzmodem(dev, flag) 34217Sbill register int dev; 34317Sbill { 34417Sbill register struct device *dzaddr; 34517Sbill register char bit; 34617Sbill 34717Sbill dzaddr = dzpdma[dev].p_addr; 34817Sbill bit = 1<<(dev&07); 34917Sbill if (flag == OFF) 35017Sbill dzaddr->dzdtr &= ~bit; 35117Sbill else 35217Sbill dzaddr->dzdtr |= bit; 35317Sbill } 35417Sbill 35517Sbill dzscan() 35617Sbill { 35717Sbill register i; 35817Sbill register struct device *dzaddr; 35917Sbill register bit; 36017Sbill register struct tty *tp; 36117Sbill 36217Sbill for (i = 0; i < dz_cnt ; i++) { 36317Sbill dzaddr = dzpdma[i].p_addr; 36417Sbill tp = &dz_tty[i]; 36517Sbill bit = 1<<(i&07); 36617Sbill if (dzaddr->dzmsr & bit) { 36717Sbill /* carrier present */ 36817Sbill if ((tp->t_state & CARR_ON) == 0) { 36917Sbill wakeup((caddr_t)&tp->t_rawq); 37017Sbill tp->t_state |= CARR_ON; 37117Sbill } 37217Sbill } else { 37317Sbill if ((tp->t_state & CARR_ON)) { 37417Sbill /* carrier lost */ 37517Sbill signal(tp->t_pgrp, SIGHUP); 37617Sbill dzaddr->dzdtr &= ~bit; 37717Sbill flushtty(tp); 37817Sbill } 37917Sbill tp->t_state &= ~CARR_ON; 38017Sbill } 38117Sbill } 38217Sbill timeout(dzscan, (caddr_t)0, 2*HZ); 38317Sbill } 384119Sbill 385119Sbill dztimer() 386119Sbill { 387119Sbill 388119Sbill dzrint(0); 389119Sbill } 390