1*2197Stoy /* dz.c 4.6 01/19/81 */ 217Sbill 31935Swnj #include "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" 201786Sbill #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; 6317Sbill 6417Sbill struct device { 6517Sbill short dzcsr; 6617Sbill short dzrbuf; 6717Sbill char dztcr; 6817Sbill char dzdtr; 6917Sbill char dztbuf; 7017Sbill char dzbrk; 7117Sbill }; 7217Sbill 7317Sbill struct pdma dzpdma[] = { 7417Sbill (struct device *)(DZADDR), NULL, NULL, (int)&dz_tty[0], dzxint, 7517Sbill (struct device *)(DZADDR), NULL, NULL, (int)&dz_tty[1], dzxint, 7617Sbill (struct device *)(DZADDR), NULL, NULL, (int)&dz_tty[2], dzxint, 7717Sbill (struct device *)(DZADDR), NULL, NULL, (int)&dz_tty[3], dzxint, 7817Sbill (struct device *)(DZADDR), NULL, NULL, (int)&dz_tty[4], dzxint, 7917Sbill (struct device *)(DZADDR), NULL, NULL, (int)&dz_tty[5], dzxint, 8017Sbill (struct device *)(DZADDR), NULL, NULL, (int)&dz_tty[6], dzxint, 8117Sbill (struct device *)(DZADDR), NULL, NULL, (int)&dz_tty[7], dzxint, 821599Sbill #if NDZ11 >= 2 8317Sbill (struct device *)(DZADDR+010), NULL, NULL, (int)&dz_tty[8], dzxint, 8417Sbill (struct device *)(DZADDR+010), NULL, NULL, (int)&dz_tty[9], dzxint, 8517Sbill (struct device *)(DZADDR+010), NULL, NULL, (int)&dz_tty[10], dzxint, 8617Sbill (struct device *)(DZADDR+010), NULL, NULL, (int)&dz_tty[11], dzxint, 8717Sbill (struct device *)(DZADDR+010), NULL, NULL, (int)&dz_tty[12], dzxint, 8817Sbill (struct device *)(DZADDR+010), NULL, NULL, (int)&dz_tty[13], dzxint, 8917Sbill (struct device *)(DZADDR+010), NULL, NULL, (int)&dz_tty[14], dzxint, 9017Sbill (struct device *)(DZADDR+010), NULL, NULL, (int)&dz_tty[15], dzxint, 91882Sbill #endif 921599Sbill #if NDZ11 >= 3 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 1021599Sbill #if NDZ11 >= 4 103882Sbill (struct device *)(DZADDR+030), NULL, NULL, (int)&dz_tty[24], dzxint, 104882Sbill (struct device *)(DZADDR+030), NULL, NULL, (int)&dz_tty[25], dzxint, 105882Sbill (struct device *)(DZADDR+030), NULL, NULL, (int)&dz_tty[26], dzxint, 106882Sbill (struct device *)(DZADDR+030), NULL, NULL, (int)&dz_tty[27], dzxint, 107882Sbill (struct device *)(DZADDR+030), NULL, NULL, (int)&dz_tty[28], dzxint, 108882Sbill (struct device *)(DZADDR+030), NULL, NULL, (int)&dz_tty[29], dzxint, 109882Sbill (struct device *)(DZADDR+030), NULL, NULL, (int)&dz_tty[30], dzxint, 110882Sbill (struct device *)(DZADDR+030), NULL, NULL, (int)&dz_tty[31], dzxint, 111882Sbill #endif 11217Sbill }; 11317Sbill char dz_timer; 11417Sbill char dz_speeds[] = { 11517Sbill 0, 020 , 021 , 022 , 023 , 024 , 0, 025, 11617Sbill 026 , 027 , 030 , 032 , 034 , 036 , 0 , 0, 11717Sbill }; 118*2197Stoy char dz_brk[NDZ11]; 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); 169*2197Stoy /* 170*2197Stoy * Turn the break bit off in case it was left on by a TIOCSBRK 171*2197Stoy * but not turned off by TIOCCBRK 172*2197Stoy */ 173*2197Stoy ((struct pdma *)(tp->t_addr))->p_addr->dzbrk = 174*2197Stoy (dz_brk[minor(dev)>>3] &= ~(1 << (dev&07))); 17517Sbill if (tp->t_state & HUPCLS) 17617Sbill dzmodem(dev, OFF); 17717Sbill ttyclose(tp); 17817Sbill } 17917Sbill 18017Sbill dzread(d) 18117Sbill { 18217Sbill register struct tty *tp; 18317Sbill 18417Sbill tp = &dz_tty[minor(d)]; 18517Sbill (*linesw[tp->t_line].l_read)(tp); 18617Sbill } 18717Sbill 18817Sbill dzwrite(d) 18917Sbill { 19017Sbill register struct tty *tp; 19117Sbill 19217Sbill tp = &dz_tty[minor(d)]; 19317Sbill (*linesw[tp->t_line].l_write)(tp); 19417Sbill } 19517Sbill 196119Sbill /*ARGSUSED*/ 19717Sbill dzrint(dev) 19817Sbill { 19917Sbill register struct tty *tp; 20017Sbill register int c; 20117Sbill register struct device *dzaddr; 202119Sbill register struct tty *tp0; 203140Sbill int s; 20417Sbill 205140Sbill s = spl6(); /* see comment in clock.c */ 206119Sbill /* as long as we are here, service them all */ 207119Sbill for (dev = 0; dev < NDZ; dev += 8) { 208119Sbill if ((dzact & (1<<(dev>>3))) == 0) 20917Sbill continue; 210119Sbill dzaddr = dzpdma[dev].p_addr; 211119Sbill tp0 = &dz_tty[dev]; 212119Sbill while ((c = dzaddr->dzrbuf) < 0) { /* char present */ 213119Sbill tp = tp0 + ((c>>8)&07); 214119Sbill if (tp >= &dz_tty[dz_cnt]) 21517Sbill continue; 216119Sbill if ((tp->t_state & ISOPEN) == 0) { 217119Sbill wakeup((caddr_t)&tp->t_rawq); 218119Sbill continue; 219119Sbill } 220119Sbill if (c&FRERROR) 221119Sbill /* framing error = break */ 222119Sbill if (tp->t_flags & RAW) 223119Sbill c = 0; /* null for getty */ 224119Sbill else 225170Sbill #ifdef IIASA 226170Sbill continue; 227170Sbill #else 228185Sbill c = tun.t_intrc; 229170Sbill #endif 230119Sbill if (c&OVERRUN) 231119Sbill printf("o"); 232119Sbill if (c&PERROR) 233119Sbill /* parity error */ 234119Sbill if (((tp->t_flags & (EVENP|ODDP)) == EVENP) 235119Sbill || ((tp->t_flags & (EVENP|ODDP)) == ODDP)) 236119Sbill continue; 237140Sbill if (tp->t_line == NETLDISC) { 238114Sbill c &= 0177; 239170Sbill BKINPUT(c, tp); 240114Sbill } else 241114Sbill (*linesw[tp->t_line].l_rint)(c, tp); 242119Sbill } 24317Sbill } 244140Sbill splx(s); 24517Sbill } 24617Sbill 24717Sbill /*ARGSUSED*/ 24817Sbill dzioctl(dev, cmd, addr, flag) 24917Sbill caddr_t addr; 25017Sbill dev_t dev; 25117Sbill { 25217Sbill register struct tty *tp; 25317Sbill 25417Sbill tp = &dz_tty[minor(dev)]; 255114Sbill cmd = (*linesw[tp->t_line].l_ioctl)(tp, cmd, addr); 256114Sbill if (cmd == 0) 257114Sbill return; 2581896Swnj if (ttioctl(tp, cmd, addr, flag)) { 25917Sbill if (cmd==TIOCSETP || cmd==TIOCSETN) 26017Sbill dzparam(minor(dev)); 261170Sbill } else switch(cmd) { 262170Sbill case TIOCSBRK: 263882Sbill ((struct pdma *)(tp->t_addr))->p_addr->dzbrk = 264882Sbill (dz_brk[minor(dev)>>3] |= 1 << (dev&07)); 265170Sbill break; 266170Sbill case TIOCCBRK: 267882Sbill ((struct pdma *)(tp->t_addr))->p_addr->dzbrk = 268882Sbill (dz_brk[minor(dev)>>3] &= ~(1 << (dev&07))); 269170Sbill break; 270170Sbill case TIOCSDTR: 271210Sbill dzmodem(minor(dev), ON); 272170Sbill break; 273170Sbill case TIOCCDTR: 274210Sbill dzmodem(minor(dev), OFF); 275170Sbill break; 276170Sbill default: 27717Sbill u.u_error = ENOTTY; 278170Sbill } 27917Sbill } 28017Sbill 28117Sbill dzparam(dev) 28217Sbill { 28317Sbill register struct tty *tp; 28417Sbill register struct device *dzaddr; 28517Sbill register short lpr; 28617Sbill 28717Sbill tp = &dz_tty[dev]; 28817Sbill dzaddr = dzpdma[dev].p_addr; 28917Sbill dzaddr->dzcsr = DZ_IEN; 290119Sbill dzact |= (1<<(dev>>3)); 29117Sbill if (tp->t_ispeed == 0) { 29217Sbill dzmodem(dev, OFF); /* hang up line */ 29317Sbill return; 29417Sbill } 29517Sbill lpr = (dz_speeds[tp->t_ispeed]<<8) | (dev & 07); 296882Sbill #ifndef IIASA 29717Sbill if (tp->t_flags & RAW) 29817Sbill lpr |= BITS8; 29917Sbill else 30017Sbill lpr |= (BITS7|PENABLE); 30117Sbill if ((tp->t_flags & EVENP) == 0) 30217Sbill lpr |= OPAR; 303882Sbill #else IIASA 304882Sbill if ((tp->t_flags & (EVENP|ODDP)) == (EVENP|ODDP)) 305882Sbill lpr |= BITS8; 306882Sbill else if (tp->t_flags & EVENP) 307882Sbill lpr |= (BITS7|PENABLE); 308882Sbill else if (tp->t_flags & ODDP) 309882Sbill lpr |= (BITS7|OPAR|PENABLE); 310882Sbill else 311882Sbill lpr |= BITS7; 312882Sbill #endif IIASA 31317Sbill if (tp->t_ispeed == 3) 31417Sbill lpr |= TWOSB; /* 110 baud: 2 stop bits */ 31517Sbill dzaddr->dzlpr = lpr; 31617Sbill } 31717Sbill 31817Sbill dzxint(tp) 31917Sbill register struct tty *tp; 32017Sbill { 32117Sbill register struct pdma *dp; 322145Sbill register s; 323145Sbill s = spl6(); /* block the clock */ 32417Sbill 32517Sbill dp = &dzpdma[tp-dz_tty]; 32617Sbill tp->t_state &= ~BUSY; 32717Sbill if (tp->t_state & FLUSH) 32817Sbill tp->t_state &= ~FLUSH; 32917Sbill else 330281Sbill ndflush(&tp->t_outq, dp->p_mem-tp->t_outq.c_cf); 33117Sbill if (tp->t_line) 33217Sbill (*linesw[tp->t_line].l_start)(tp); 33317Sbill else 33417Sbill dzstart(tp); 33517Sbill if (tp->t_outq.c_cc == 0 || (tp->t_state&BUSY)==0) 33617Sbill dp->p_addr->dztcr &= ~(1 << ((tp-dz_tty) % 8)); 337145Sbill splx(s); 33817Sbill } 33917Sbill 34017Sbill dzstart(tp) 34117Sbill register struct tty *tp; 34217Sbill { 34317Sbill register struct pdma *dp; 34417Sbill register struct device *dzaddr; 34517Sbill register cc; 34617Sbill int sps; 34717Sbill 34817Sbill dp = &dzpdma[tp-dz_tty]; 34917Sbill dzaddr = dp->p_addr; 35017Sbill sps = spl5(); 35117Sbill if (tp->t_state & (TIMEOUT|BUSY|TTSTOP)) 35217Sbill goto out; 353921Sbill if (tp->t_state&ASLEEP && tp->t_outq.c_cc <= TTLOWAT(tp)) { 35417Sbill tp->t_state &= ~ASLEEP; 35517Sbill if (tp->t_chan) 35617Sbill mcstart(tp->t_chan, (caddr_t)&tp->t_outq); 35717Sbill else 35817Sbill wakeup((caddr_t)&tp->t_outq); 35917Sbill } 36017Sbill if (tp->t_outq.c_cc == 0) 36117Sbill goto out; 36217Sbill if (tp->t_flags&RAW) 36317Sbill cc = ndqb(&tp->t_outq, 0); 36417Sbill else { 36517Sbill cc = ndqb(&tp->t_outq, 0200); 36617Sbill if (cc == 0) { 36717Sbill cc = getc(&tp->t_outq); 36817Sbill timeout(ttrstrt, (caddr_t)tp, (cc&0177) + 6); 36917Sbill tp->t_state |= TIMEOUT; 37017Sbill goto out; 37117Sbill } 37217Sbill } 37317Sbill tp->t_state |= BUSY; 37417Sbill dp->p_end = dp->p_mem = tp->t_outq.c_cf; 37517Sbill dp->p_end += cc; 37617Sbill dzaddr->dztcr |= 1 << ((tp-dz_tty) % 8); 37717Sbill out: 37817Sbill splx(sps); 37917Sbill } 38017Sbill 38117Sbill /* 38217Sbill * Stop output on a line. 38317Sbill * Assume call is made at spl6. 38417Sbill */ 38517Sbill /*ARGSUSED*/ 38617Sbill dzstop(tp, flag) 38717Sbill register struct tty *tp; 38817Sbill { 38917Sbill register struct pdma *dp; 39017Sbill register int s; 39117Sbill 39217Sbill dp = &dzpdma[tp-dz_tty]; 39317Sbill s = spl6(); 39417Sbill if (tp->t_state & BUSY) { 39517Sbill dp->p_end = dp->p_mem; 39617Sbill if ((tp->t_state&TTSTOP)==0) { 39717Sbill tp->t_state |= FLUSH; 39817Sbill } 39917Sbill } 40017Sbill splx(s); 40117Sbill } 40217Sbill 40317Sbill dzmodem(dev, flag) 40417Sbill register int dev; 40517Sbill { 40617Sbill register struct device *dzaddr; 40717Sbill register char bit; 40817Sbill 40917Sbill dzaddr = dzpdma[dev].p_addr; 41017Sbill bit = 1<<(dev&07); 41117Sbill if (flag == OFF) 41217Sbill dzaddr->dzdtr &= ~bit; 41317Sbill else 41417Sbill dzaddr->dzdtr |= bit; 41517Sbill } 41617Sbill 41717Sbill dzscan() 41817Sbill { 41917Sbill register i; 42017Sbill register struct device *dzaddr; 42117Sbill register bit; 42217Sbill register struct tty *tp; 42317Sbill 42417Sbill for (i = 0; i < dz_cnt ; i++) { 42517Sbill dzaddr = dzpdma[i].p_addr; 42617Sbill tp = &dz_tty[i]; 42717Sbill bit = 1<<(i&07); 42817Sbill if (dzaddr->dzmsr & bit) { 42917Sbill /* carrier present */ 43017Sbill if ((tp->t_state & CARR_ON) == 0) { 43117Sbill wakeup((caddr_t)&tp->t_rawq); 43217Sbill tp->t_state |= CARR_ON; 43317Sbill } 43417Sbill } else { 435882Sbill if ((tp->t_state&CARR_ON) && (tp->t_local&LNOHANG) == 0) { 43617Sbill /* carrier lost */ 437882Sbill if (tp->t_state&ISOPEN) { 438170Sbill gsignal(tp->t_pgrp, SIGHUP); 439205Sbill gsignal(tp->t_pgrp, SIGCONT); 440170Sbill dzaddr->dzdtr &= ~bit; 441871Sbill flushtty(tp, FREAD|FWRITE); 442170Sbill } 443170Sbill tp->t_state &= ~CARR_ON; 44417Sbill } 44517Sbill } 44617Sbill } 44717Sbill timeout(dzscan, (caddr_t)0, 2*HZ); 44817Sbill } 449119Sbill 450119Sbill dztimer() 451119Sbill { 452119Sbill 453119Sbill dzrint(0); 454119Sbill } 455281Sbill 456281Sbill /* 457281Sbill * Reset state of driver if UBA reset was necessary. 458301Sbill * Reset parameters and restart transmission on open lines. 459281Sbill */ 460281Sbill dzreset() 461281Sbill { 462281Sbill int d; 463281Sbill register struct tty *tp; 464281Sbill 465281Sbill printf(" dz"); 466281Sbill for (d = 0; d < NDZ; d++) { 467281Sbill tp = &dz_tty[d]; 468281Sbill if (tp->t_state & (ISOPEN|WOPEN)) { 469281Sbill dzparam(d); 470301Sbill dzmodem(d, ON); 471301Sbill tp->t_state &= ~BUSY; 472301Sbill dzstart(tp); 473281Sbill } 474281Sbill } 475281Sbill dztimer(); 476281Sbill } 4771562Sbill #endif 478