1*1786Sbill /* dz.c 4.2 11/09/80 */ 217Sbill 31562Sbill #include "../conf/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" 1517Sbill #include "../h/uba.h" 1617Sbill #include "../h/conf.h" 1717Sbill #include "../h/pdma.h" 18114Sbill #include "../h/bk.h" 19871Sbill #include "../h/file.h" 20*1786Sbill #include "../h/mx.h" 21145Sbill 22145Sbill /* 23145Sbill * When running dz's using only SAE (silo alarm) on input 24145Sbill * it is necessary to call dzrint() at clock interrupt time. 25145Sbill * This is unsafe unless spl5()s in tty code are changed to 26145Sbill * spl6()s to block clock interrupts. Note that the dh driver 27145Sbill * currently in use works the same way as the dz, even though 28145Sbill * we could try to more intelligently manage its silo. 29145Sbill * Thus don't take this out if you have no dz's unless you 30145Sbill * change clock.c and dhtimer(). 31145Sbill */ 32145Sbill #define spl5 spl6 3317Sbill 34882Sbill #define NDZ (NDZ11*8) 3517Sbill 3617Sbill #define BITS7 020 3717Sbill #define BITS8 030 3817Sbill #define TWOSB 040 3917Sbill #define PENABLE 0100 4017Sbill #define OPAR 0200 4117Sbill #define MSE 040 /* Master Scan Enable */ 4217Sbill #define RIE 0100 /* Receiver Interrupt Enable */ 43119Sbill #define SAE 010000 /* Silo Alarm Enable */ 44119Sbill #define TIE 040000 /* Transmit Interrupt Enable */ 45119Sbill #define DZ_IEN (MSE+RIE+TIE+SAE) 4617Sbill #define PERROR 010000 4717Sbill #define FRERROR 020000 48119Sbill #define OVERRUN 040000 4917Sbill #define SSPEED 7 /* std speed = 300 baud */ 5017Sbill 5117Sbill 5217Sbill #define dzlpr dzrbuf 5317Sbill #define dzmsr dzbrk 5417Sbill #define ON 1 5517Sbill #define OFF 0 5617Sbill 5717Sbill int dzstart(); 5817Sbill int dzxint(); 59114Sbill int ttrstrt(); 6017Sbill struct tty dz_tty[NDZ]; 6117Sbill int dz_cnt = { NDZ }; 62119Sbill int dzact; 63281Sbill int dzinit; 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, 831599Sbill #if NDZ11 >= 2 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, 92882Sbill #endif 931599Sbill #if NDZ11 >= 3 9417Sbill (struct device *)(DZADDR+020), NULL, NULL, (int)&dz_tty[16], dzxint, 9517Sbill (struct device *)(DZADDR+020), NULL, NULL, (int)&dz_tty[17], dzxint, 9617Sbill (struct device *)(DZADDR+020), NULL, NULL, (int)&dz_tty[18], dzxint, 9717Sbill (struct device *)(DZADDR+020), NULL, NULL, (int)&dz_tty[19], dzxint, 9817Sbill (struct device *)(DZADDR+020), NULL, NULL, (int)&dz_tty[20], dzxint, 9917Sbill (struct device *)(DZADDR+020), NULL, NULL, (int)&dz_tty[21], dzxint, 10017Sbill (struct device *)(DZADDR+020), NULL, NULL, (int)&dz_tty[22], dzxint, 10117Sbill (struct device *)(DZADDR+020), NULL, NULL, (int)&dz_tty[23], dzxint, 10217Sbill #endif 1031599Sbill #if NDZ11 >= 4 104882Sbill (struct device *)(DZADDR+030), NULL, NULL, (int)&dz_tty[24], dzxint, 105882Sbill (struct device *)(DZADDR+030), NULL, NULL, (int)&dz_tty[25], dzxint, 106882Sbill (struct device *)(DZADDR+030), NULL, NULL, (int)&dz_tty[26], dzxint, 107882Sbill (struct device *)(DZADDR+030), NULL, NULL, (int)&dz_tty[27], dzxint, 108882Sbill (struct device *)(DZADDR+030), NULL, NULL, (int)&dz_tty[28], dzxint, 109882Sbill (struct device *)(DZADDR+030), NULL, NULL, (int)&dz_tty[29], dzxint, 110882Sbill (struct device *)(DZADDR+030), NULL, NULL, (int)&dz_tty[30], dzxint, 111882Sbill (struct device *)(DZADDR+030), NULL, NULL, (int)&dz_tty[31], dzxint, 112882Sbill #endif 11317Sbill }; 11417Sbill char dz_timer; 11517Sbill char dz_speeds[] = { 11617Sbill 0, 020 , 021 , 022 , 023 , 024 , 0, 025, 11717Sbill 026 , 027 , 030 , 032 , 034 , 036 , 0 , 0, 11817Sbill }; 11917Sbill 12017Sbill /*ARGSUSED*/ 12117Sbill dzopen(d, flag) 12217Sbill { 12317Sbill register struct tty *tp; 12417Sbill register dev; 12517Sbill extern dzscan(); 12617Sbill 12717Sbill dev = minor(d); 12817Sbill if (dev >= dz_cnt) { 12917Sbill u.u_error = ENXIO; 13017Sbill return; 13117Sbill } 13217Sbill if (dz_timer == 0) { 13317Sbill dz_timer++; 13417Sbill timeout(dzscan, (caddr_t)0, 60); 13517Sbill } 13617Sbill tp = &dz_tty[dev]; 13717Sbill tp->t_addr = (caddr_t)&dzpdma[dev]; 13817Sbill tp->t_oproc = dzstart; 13917Sbill tp->t_iproc = NULL; 14017Sbill tp->t_state |= WOPEN; 14117Sbill if ((tp->t_state & ISOPEN) == 0) { 14217Sbill ttychars(tp); 14317Sbill tp->t_ospeed = tp->t_ispeed = SSPEED; 14417Sbill tp->t_flags = ODDP|EVENP|ECHO; 14517Sbill /*tp->t_state |= HUPCLS;*/ 14617Sbill dzparam(dev); 14717Sbill } else if (tp->t_state&XCLUDE && u.u_uid != 0) { 14817Sbill u.u_error = EBUSY; 14917Sbill return; 15017Sbill } 15117Sbill dzmodem(dev, ON); 152114Sbill (void) spl5(); 15317Sbill while ((tp->t_state & CARR_ON) == 0) { 15417Sbill tp->t_state |= WOPEN; 15517Sbill sleep((caddr_t)&tp->t_rawq, TTIPRI); 15617Sbill } 157114Sbill (void) spl0(); 15817Sbill (*linesw[tp->t_line].l_open)(d, tp); 15917Sbill } 16017Sbill 16117Sbill dzclose(d) 16217Sbill { 16317Sbill register struct tty *tp; 16417Sbill register dev; 16517Sbill 16617Sbill dev = minor(d); 16717Sbill tp = &dz_tty[dev]; 16817Sbill (*linesw[tp->t_line].l_close)(tp); 16917Sbill if (tp->t_state & HUPCLS) 17017Sbill dzmodem(dev, OFF); 17117Sbill ttyclose(tp); 17217Sbill } 17317Sbill 17417Sbill dzread(d) 17517Sbill { 17617Sbill register struct tty *tp; 17717Sbill 17817Sbill tp = &dz_tty[minor(d)]; 17917Sbill (*linesw[tp->t_line].l_read)(tp); 18017Sbill } 18117Sbill 18217Sbill dzwrite(d) 18317Sbill { 18417Sbill register struct tty *tp; 18517Sbill 18617Sbill tp = &dz_tty[minor(d)]; 18717Sbill (*linesw[tp->t_line].l_write)(tp); 18817Sbill } 18917Sbill 190119Sbill /*ARGSUSED*/ 19117Sbill dzrint(dev) 19217Sbill { 19317Sbill register struct tty *tp; 19417Sbill register int c; 19517Sbill register struct device *dzaddr; 196119Sbill register struct tty *tp0; 197140Sbill int s; 19817Sbill 199140Sbill s = spl6(); /* see comment in clock.c */ 200119Sbill /* as long as we are here, service them all */ 201119Sbill for (dev = 0; dev < NDZ; dev += 8) { 202119Sbill if ((dzact & (1<<(dev>>3))) == 0) 20317Sbill continue; 204119Sbill dzaddr = dzpdma[dev].p_addr; 205119Sbill tp0 = &dz_tty[dev]; 206119Sbill while ((c = dzaddr->dzrbuf) < 0) { /* char present */ 207119Sbill tp = tp0 + ((c>>8)&07); 208119Sbill if (tp >= &dz_tty[dz_cnt]) 20917Sbill continue; 210119Sbill if ((tp->t_state & ISOPEN) == 0) { 211119Sbill wakeup((caddr_t)&tp->t_rawq); 212119Sbill continue; 213119Sbill } 214119Sbill if (c&FRERROR) 215119Sbill /* framing error = break */ 216119Sbill if (tp->t_flags & RAW) 217119Sbill c = 0; /* null for getty */ 218119Sbill else 219170Sbill #ifdef IIASA 220170Sbill continue; 221170Sbill #else 222185Sbill c = tun.t_intrc; 223170Sbill #endif 224119Sbill if (c&OVERRUN) 225119Sbill printf("o"); 226119Sbill if (c&PERROR) 227119Sbill /* parity error */ 228119Sbill if (((tp->t_flags & (EVENP|ODDP)) == EVENP) 229119Sbill || ((tp->t_flags & (EVENP|ODDP)) == ODDP)) 230119Sbill continue; 231140Sbill if (tp->t_line == NETLDISC) { 232114Sbill c &= 0177; 233170Sbill BKINPUT(c, tp); 234114Sbill } else 235114Sbill (*linesw[tp->t_line].l_rint)(c, tp); 236119Sbill } 23717Sbill } 238140Sbill splx(s); 23917Sbill } 24017Sbill 24117Sbill /*ARGSUSED*/ 24217Sbill dzioctl(dev, cmd, addr, flag) 24317Sbill caddr_t addr; 24417Sbill dev_t dev; 24517Sbill { 24617Sbill register struct tty *tp; 247882Sbill static char dz_brk[NDZ11]; 24817Sbill 24917Sbill tp = &dz_tty[minor(dev)]; 250114Sbill cmd = (*linesw[tp->t_line].l_ioctl)(tp, cmd, addr); 251114Sbill if (cmd == 0) 252114Sbill return; 253902Sbill if (ttioctl(cmd, tp, addr, dev, flag)) { 25417Sbill if (cmd==TIOCSETP || cmd==TIOCSETN) 25517Sbill dzparam(minor(dev)); 256170Sbill } else switch(cmd) { 257170Sbill case TIOCSBRK: 258882Sbill ((struct pdma *)(tp->t_addr))->p_addr->dzbrk = 259882Sbill (dz_brk[minor(dev)>>3] |= 1 << (dev&07)); 260170Sbill break; 261170Sbill case TIOCCBRK: 262882Sbill ((struct pdma *)(tp->t_addr))->p_addr->dzbrk = 263882Sbill (dz_brk[minor(dev)>>3] &= ~(1 << (dev&07))); 264170Sbill break; 265170Sbill case TIOCSDTR: 266210Sbill dzmodem(minor(dev), ON); 267170Sbill break; 268170Sbill case TIOCCDTR: 269210Sbill dzmodem(minor(dev), OFF); 270170Sbill break; 271170Sbill default: 27217Sbill u.u_error = ENOTTY; 273170Sbill } 27417Sbill } 27517Sbill 27617Sbill dzparam(dev) 27717Sbill { 27817Sbill register struct tty *tp; 27917Sbill register struct device *dzaddr; 28017Sbill register short lpr; 28117Sbill 28217Sbill tp = &dz_tty[dev]; 28317Sbill dzaddr = dzpdma[dev].p_addr; 28417Sbill dzaddr->dzcsr = DZ_IEN; 285119Sbill dzact |= (1<<(dev>>3)); 28617Sbill if (tp->t_ispeed == 0) { 28717Sbill dzmodem(dev, OFF); /* hang up line */ 28817Sbill return; 28917Sbill } 29017Sbill lpr = (dz_speeds[tp->t_ispeed]<<8) | (dev & 07); 291882Sbill #ifndef IIASA 29217Sbill if (tp->t_flags & RAW) 29317Sbill lpr |= BITS8; 29417Sbill else 29517Sbill lpr |= (BITS7|PENABLE); 29617Sbill if ((tp->t_flags & EVENP) == 0) 29717Sbill lpr |= OPAR; 298882Sbill #else IIASA 299882Sbill if ((tp->t_flags & (EVENP|ODDP)) == (EVENP|ODDP)) 300882Sbill lpr |= BITS8; 301882Sbill else if (tp->t_flags & EVENP) 302882Sbill lpr |= (BITS7|PENABLE); 303882Sbill else if (tp->t_flags & ODDP) 304882Sbill lpr |= (BITS7|OPAR|PENABLE); 305882Sbill else 306882Sbill lpr |= BITS7; 307882Sbill #endif IIASA 30817Sbill if (tp->t_ispeed == 3) 30917Sbill lpr |= TWOSB; /* 110 baud: 2 stop bits */ 31017Sbill dzaddr->dzlpr = lpr; 31117Sbill } 31217Sbill 31317Sbill dzxint(tp) 31417Sbill register struct tty *tp; 31517Sbill { 31617Sbill register struct pdma *dp; 317145Sbill register s; 318145Sbill s = spl6(); /* block the clock */ 31917Sbill 32017Sbill dp = &dzpdma[tp-dz_tty]; 32117Sbill tp->t_state &= ~BUSY; 32217Sbill if (tp->t_state & FLUSH) 32317Sbill tp->t_state &= ~FLUSH; 32417Sbill else 325281Sbill ndflush(&tp->t_outq, dp->p_mem-tp->t_outq.c_cf); 32617Sbill if (tp->t_line) 32717Sbill (*linesw[tp->t_line].l_start)(tp); 32817Sbill else 32917Sbill dzstart(tp); 33017Sbill if (tp->t_outq.c_cc == 0 || (tp->t_state&BUSY)==0) 33117Sbill dp->p_addr->dztcr &= ~(1 << ((tp-dz_tty) % 8)); 332145Sbill splx(s); 33317Sbill } 33417Sbill 33517Sbill dzstart(tp) 33617Sbill register struct tty *tp; 33717Sbill { 33817Sbill register struct pdma *dp; 33917Sbill register struct device *dzaddr; 34017Sbill register cc; 34117Sbill int sps; 34217Sbill 34317Sbill dp = &dzpdma[tp-dz_tty]; 34417Sbill dzaddr = dp->p_addr; 34517Sbill sps = spl5(); 34617Sbill if (tp->t_state & (TIMEOUT|BUSY|TTSTOP)) 34717Sbill goto out; 348921Sbill if (tp->t_state&ASLEEP && tp->t_outq.c_cc <= TTLOWAT(tp)) { 34917Sbill tp->t_state &= ~ASLEEP; 35017Sbill if (tp->t_chan) 35117Sbill mcstart(tp->t_chan, (caddr_t)&tp->t_outq); 35217Sbill else 35317Sbill wakeup((caddr_t)&tp->t_outq); 35417Sbill } 35517Sbill if (tp->t_outq.c_cc == 0) 35617Sbill goto out; 35717Sbill if (tp->t_flags&RAW) 35817Sbill cc = ndqb(&tp->t_outq, 0); 35917Sbill else { 36017Sbill cc = ndqb(&tp->t_outq, 0200); 36117Sbill if (cc == 0) { 36217Sbill cc = getc(&tp->t_outq); 36317Sbill timeout(ttrstrt, (caddr_t)tp, (cc&0177) + 6); 36417Sbill tp->t_state |= TIMEOUT; 36517Sbill goto out; 36617Sbill } 36717Sbill } 36817Sbill tp->t_state |= BUSY; 36917Sbill dp->p_end = dp->p_mem = tp->t_outq.c_cf; 37017Sbill dp->p_end += cc; 37117Sbill dzaddr->dztcr |= 1 << ((tp-dz_tty) % 8); 37217Sbill out: 37317Sbill splx(sps); 37417Sbill } 37517Sbill 37617Sbill /* 37717Sbill * Stop output on a line. 37817Sbill * Assume call is made at spl6. 37917Sbill */ 38017Sbill /*ARGSUSED*/ 38117Sbill dzstop(tp, flag) 38217Sbill register struct tty *tp; 38317Sbill { 38417Sbill register struct pdma *dp; 38517Sbill register int s; 38617Sbill 38717Sbill dp = &dzpdma[tp-dz_tty]; 38817Sbill s = spl6(); 38917Sbill if (tp->t_state & BUSY) { 39017Sbill dp->p_end = dp->p_mem; 39117Sbill if ((tp->t_state&TTSTOP)==0) { 39217Sbill tp->t_state |= FLUSH; 39317Sbill } 39417Sbill } 39517Sbill splx(s); 39617Sbill } 39717Sbill 39817Sbill dzmodem(dev, flag) 39917Sbill register int dev; 40017Sbill { 40117Sbill register struct device *dzaddr; 40217Sbill register char bit; 40317Sbill 40417Sbill dzaddr = dzpdma[dev].p_addr; 40517Sbill bit = 1<<(dev&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); 42317Sbill if (dzaddr->dzmsr & bit) { 42417Sbill /* carrier present */ 42517Sbill if ((tp->t_state & CARR_ON) == 0) { 42617Sbill wakeup((caddr_t)&tp->t_rawq); 42717Sbill tp->t_state |= CARR_ON; 42817Sbill } 42917Sbill } else { 430882Sbill if ((tp->t_state&CARR_ON) && (tp->t_local&LNOHANG) == 0) { 43117Sbill /* carrier lost */ 432882Sbill if (tp->t_state&ISOPEN) { 433170Sbill gsignal(tp->t_pgrp, SIGHUP); 434205Sbill gsignal(tp->t_pgrp, SIGCONT); 435170Sbill dzaddr->dzdtr &= ~bit; 436871Sbill flushtty(tp, FREAD|FWRITE); 437170Sbill } 438170Sbill tp->t_state &= ~CARR_ON; 43917Sbill } 44017Sbill } 44117Sbill } 44217Sbill timeout(dzscan, (caddr_t)0, 2*HZ); 44317Sbill } 444119Sbill 445119Sbill dztimer() 446119Sbill { 447119Sbill 448119Sbill dzrint(0); 449119Sbill } 450281Sbill 451281Sbill /* 452281Sbill * Reset state of driver if UBA reset was necessary. 453301Sbill * Reset parameters and restart transmission on open lines. 454281Sbill */ 455281Sbill dzreset() 456281Sbill { 457281Sbill int d; 458281Sbill register struct tty *tp; 459281Sbill 460281Sbill printf(" dz"); 461281Sbill for (d = 0; d < NDZ; d++) { 462281Sbill tp = &dz_tty[d]; 463281Sbill if (tp->t_state & (ISOPEN|WOPEN)) { 464281Sbill dzparam(d); 465301Sbill dzmodem(d, ON); 466301Sbill tp->t_state &= ~BUSY; 467301Sbill dzstart(tp); 468281Sbill } 469281Sbill } 470281Sbill dztimer(); 471281Sbill } 4721562Sbill #endif 473