1*1935Swnj /* dz.c 4.5 12/19/80 */ 217Sbill 3*1935Swnj #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 }; 11817Sbill 11917Sbill /*ARGSUSED*/ 12017Sbill dzopen(d, flag) 12117Sbill { 12217Sbill register struct tty *tp; 12317Sbill register dev; 12417Sbill extern dzscan(); 12517Sbill 12617Sbill dev = minor(d); 12717Sbill if (dev >= dz_cnt) { 12817Sbill u.u_error = ENXIO; 12917Sbill return; 13017Sbill } 13117Sbill if (dz_timer == 0) { 13217Sbill dz_timer++; 13317Sbill timeout(dzscan, (caddr_t)0, 60); 13417Sbill } 13517Sbill tp = &dz_tty[dev]; 13617Sbill tp->t_addr = (caddr_t)&dzpdma[dev]; 13717Sbill tp->t_oproc = dzstart; 13817Sbill tp->t_iproc = NULL; 13917Sbill tp->t_state |= WOPEN; 14017Sbill if ((tp->t_state & ISOPEN) == 0) { 14117Sbill ttychars(tp); 14217Sbill tp->t_ospeed = tp->t_ispeed = SSPEED; 14317Sbill tp->t_flags = ODDP|EVENP|ECHO; 14417Sbill /*tp->t_state |= HUPCLS;*/ 14517Sbill dzparam(dev); 14617Sbill } else if (tp->t_state&XCLUDE && u.u_uid != 0) { 14717Sbill u.u_error = EBUSY; 14817Sbill return; 14917Sbill } 15017Sbill dzmodem(dev, ON); 151114Sbill (void) spl5(); 15217Sbill while ((tp->t_state & CARR_ON) == 0) { 15317Sbill tp->t_state |= WOPEN; 15417Sbill sleep((caddr_t)&tp->t_rawq, TTIPRI); 15517Sbill } 156114Sbill (void) spl0(); 15717Sbill (*linesw[tp->t_line].l_open)(d, tp); 15817Sbill } 15917Sbill 16017Sbill dzclose(d) 16117Sbill { 16217Sbill register struct tty *tp; 16317Sbill register dev; 16417Sbill 16517Sbill dev = minor(d); 16617Sbill tp = &dz_tty[dev]; 16717Sbill (*linesw[tp->t_line].l_close)(tp); 16817Sbill if (tp->t_state & HUPCLS) 16917Sbill dzmodem(dev, OFF); 17017Sbill ttyclose(tp); 17117Sbill } 17217Sbill 17317Sbill dzread(d) 17417Sbill { 17517Sbill register struct tty *tp; 17617Sbill 17717Sbill tp = &dz_tty[minor(d)]; 17817Sbill (*linesw[tp->t_line].l_read)(tp); 17917Sbill } 18017Sbill 18117Sbill dzwrite(d) 18217Sbill { 18317Sbill register struct tty *tp; 18417Sbill 18517Sbill tp = &dz_tty[minor(d)]; 18617Sbill (*linesw[tp->t_line].l_write)(tp); 18717Sbill } 18817Sbill 189119Sbill /*ARGSUSED*/ 19017Sbill dzrint(dev) 19117Sbill { 19217Sbill register struct tty *tp; 19317Sbill register int c; 19417Sbill register struct device *dzaddr; 195119Sbill register struct tty *tp0; 196140Sbill int s; 19717Sbill 198140Sbill s = spl6(); /* see comment in clock.c */ 199119Sbill /* as long as we are here, service them all */ 200119Sbill for (dev = 0; dev < NDZ; dev += 8) { 201119Sbill if ((dzact & (1<<(dev>>3))) == 0) 20217Sbill continue; 203119Sbill dzaddr = dzpdma[dev].p_addr; 204119Sbill tp0 = &dz_tty[dev]; 205119Sbill while ((c = dzaddr->dzrbuf) < 0) { /* char present */ 206119Sbill tp = tp0 + ((c>>8)&07); 207119Sbill if (tp >= &dz_tty[dz_cnt]) 20817Sbill continue; 209119Sbill if ((tp->t_state & ISOPEN) == 0) { 210119Sbill wakeup((caddr_t)&tp->t_rawq); 211119Sbill continue; 212119Sbill } 213119Sbill if (c&FRERROR) 214119Sbill /* framing error = break */ 215119Sbill if (tp->t_flags & RAW) 216119Sbill c = 0; /* null for getty */ 217119Sbill else 218170Sbill #ifdef IIASA 219170Sbill continue; 220170Sbill #else 221185Sbill c = tun.t_intrc; 222170Sbill #endif 223119Sbill if (c&OVERRUN) 224119Sbill printf("o"); 225119Sbill if (c&PERROR) 226119Sbill /* parity error */ 227119Sbill if (((tp->t_flags & (EVENP|ODDP)) == EVENP) 228119Sbill || ((tp->t_flags & (EVENP|ODDP)) == ODDP)) 229119Sbill continue; 230140Sbill if (tp->t_line == NETLDISC) { 231114Sbill c &= 0177; 232170Sbill BKINPUT(c, tp); 233114Sbill } else 234114Sbill (*linesw[tp->t_line].l_rint)(c, tp); 235119Sbill } 23617Sbill } 237140Sbill splx(s); 23817Sbill } 23917Sbill 24017Sbill /*ARGSUSED*/ 24117Sbill dzioctl(dev, cmd, addr, flag) 24217Sbill caddr_t addr; 24317Sbill dev_t dev; 24417Sbill { 24517Sbill register struct tty *tp; 246882Sbill static char dz_brk[NDZ11]; 24717Sbill 24817Sbill tp = &dz_tty[minor(dev)]; 249114Sbill cmd = (*linesw[tp->t_line].l_ioctl)(tp, cmd, addr); 250114Sbill if (cmd == 0) 251114Sbill return; 2521896Swnj if (ttioctl(tp, cmd, addr, flag)) { 25317Sbill if (cmd==TIOCSETP || cmd==TIOCSETN) 25417Sbill dzparam(minor(dev)); 255170Sbill } else switch(cmd) { 256170Sbill case TIOCSBRK: 257882Sbill ((struct pdma *)(tp->t_addr))->p_addr->dzbrk = 258882Sbill (dz_brk[minor(dev)>>3] |= 1 << (dev&07)); 259170Sbill break; 260170Sbill case TIOCCBRK: 261882Sbill ((struct pdma *)(tp->t_addr))->p_addr->dzbrk = 262882Sbill (dz_brk[minor(dev)>>3] &= ~(1 << (dev&07))); 263170Sbill break; 264170Sbill case TIOCSDTR: 265210Sbill dzmodem(minor(dev), ON); 266170Sbill break; 267170Sbill case TIOCCDTR: 268210Sbill dzmodem(minor(dev), OFF); 269170Sbill break; 270170Sbill default: 27117Sbill u.u_error = ENOTTY; 272170Sbill } 27317Sbill } 27417Sbill 27517Sbill dzparam(dev) 27617Sbill { 27717Sbill register struct tty *tp; 27817Sbill register struct device *dzaddr; 27917Sbill register short lpr; 28017Sbill 28117Sbill tp = &dz_tty[dev]; 28217Sbill dzaddr = dzpdma[dev].p_addr; 28317Sbill dzaddr->dzcsr = DZ_IEN; 284119Sbill dzact |= (1<<(dev>>3)); 28517Sbill if (tp->t_ispeed == 0) { 28617Sbill dzmodem(dev, OFF); /* hang up line */ 28717Sbill return; 28817Sbill } 28917Sbill lpr = (dz_speeds[tp->t_ispeed]<<8) | (dev & 07); 290882Sbill #ifndef IIASA 29117Sbill if (tp->t_flags & RAW) 29217Sbill lpr |= BITS8; 29317Sbill else 29417Sbill lpr |= (BITS7|PENABLE); 29517Sbill if ((tp->t_flags & EVENP) == 0) 29617Sbill lpr |= OPAR; 297882Sbill #else IIASA 298882Sbill if ((tp->t_flags & (EVENP|ODDP)) == (EVENP|ODDP)) 299882Sbill lpr |= BITS8; 300882Sbill else if (tp->t_flags & EVENP) 301882Sbill lpr |= (BITS7|PENABLE); 302882Sbill else if (tp->t_flags & ODDP) 303882Sbill lpr |= (BITS7|OPAR|PENABLE); 304882Sbill else 305882Sbill lpr |= BITS7; 306882Sbill #endif IIASA 30717Sbill if (tp->t_ispeed == 3) 30817Sbill lpr |= TWOSB; /* 110 baud: 2 stop bits */ 30917Sbill dzaddr->dzlpr = lpr; 31017Sbill } 31117Sbill 31217Sbill dzxint(tp) 31317Sbill register struct tty *tp; 31417Sbill { 31517Sbill register struct pdma *dp; 316145Sbill register s; 317145Sbill s = spl6(); /* block the clock */ 31817Sbill 31917Sbill dp = &dzpdma[tp-dz_tty]; 32017Sbill tp->t_state &= ~BUSY; 32117Sbill if (tp->t_state & FLUSH) 32217Sbill tp->t_state &= ~FLUSH; 32317Sbill else 324281Sbill ndflush(&tp->t_outq, dp->p_mem-tp->t_outq.c_cf); 32517Sbill if (tp->t_line) 32617Sbill (*linesw[tp->t_line].l_start)(tp); 32717Sbill else 32817Sbill dzstart(tp); 32917Sbill if (tp->t_outq.c_cc == 0 || (tp->t_state&BUSY)==0) 33017Sbill dp->p_addr->dztcr &= ~(1 << ((tp-dz_tty) % 8)); 331145Sbill splx(s); 33217Sbill } 33317Sbill 33417Sbill dzstart(tp) 33517Sbill register struct tty *tp; 33617Sbill { 33717Sbill register struct pdma *dp; 33817Sbill register struct device *dzaddr; 33917Sbill register cc; 34017Sbill int sps; 34117Sbill 34217Sbill dp = &dzpdma[tp-dz_tty]; 34317Sbill dzaddr = dp->p_addr; 34417Sbill sps = spl5(); 34517Sbill if (tp->t_state & (TIMEOUT|BUSY|TTSTOP)) 34617Sbill goto out; 347921Sbill if (tp->t_state&ASLEEP && tp->t_outq.c_cc <= TTLOWAT(tp)) { 34817Sbill tp->t_state &= ~ASLEEP; 34917Sbill if (tp->t_chan) 35017Sbill mcstart(tp->t_chan, (caddr_t)&tp->t_outq); 35117Sbill else 35217Sbill wakeup((caddr_t)&tp->t_outq); 35317Sbill } 35417Sbill if (tp->t_outq.c_cc == 0) 35517Sbill goto out; 35617Sbill if (tp->t_flags&RAW) 35717Sbill cc = ndqb(&tp->t_outq, 0); 35817Sbill else { 35917Sbill cc = ndqb(&tp->t_outq, 0200); 36017Sbill if (cc == 0) { 36117Sbill cc = getc(&tp->t_outq); 36217Sbill timeout(ttrstrt, (caddr_t)tp, (cc&0177) + 6); 36317Sbill tp->t_state |= TIMEOUT; 36417Sbill goto out; 36517Sbill } 36617Sbill } 36717Sbill tp->t_state |= BUSY; 36817Sbill dp->p_end = dp->p_mem = tp->t_outq.c_cf; 36917Sbill dp->p_end += cc; 37017Sbill dzaddr->dztcr |= 1 << ((tp-dz_tty) % 8); 37117Sbill out: 37217Sbill splx(sps); 37317Sbill } 37417Sbill 37517Sbill /* 37617Sbill * Stop output on a line. 37717Sbill * Assume call is made at spl6. 37817Sbill */ 37917Sbill /*ARGSUSED*/ 38017Sbill dzstop(tp, flag) 38117Sbill register struct tty *tp; 38217Sbill { 38317Sbill register struct pdma *dp; 38417Sbill register int s; 38517Sbill 38617Sbill dp = &dzpdma[tp-dz_tty]; 38717Sbill s = spl6(); 38817Sbill if (tp->t_state & BUSY) { 38917Sbill dp->p_end = dp->p_mem; 39017Sbill if ((tp->t_state&TTSTOP)==0) { 39117Sbill tp->t_state |= FLUSH; 39217Sbill } 39317Sbill } 39417Sbill splx(s); 39517Sbill } 39617Sbill 39717Sbill dzmodem(dev, flag) 39817Sbill register int dev; 39917Sbill { 40017Sbill register struct device *dzaddr; 40117Sbill register char bit; 40217Sbill 40317Sbill dzaddr = dzpdma[dev].p_addr; 40417Sbill bit = 1<<(dev&07); 40517Sbill if (flag == OFF) 40617Sbill dzaddr->dzdtr &= ~bit; 40717Sbill else 40817Sbill dzaddr->dzdtr |= bit; 40917Sbill } 41017Sbill 41117Sbill dzscan() 41217Sbill { 41317Sbill register i; 41417Sbill register struct device *dzaddr; 41517Sbill register bit; 41617Sbill register struct tty *tp; 41717Sbill 41817Sbill for (i = 0; i < dz_cnt ; i++) { 41917Sbill dzaddr = dzpdma[i].p_addr; 42017Sbill tp = &dz_tty[i]; 42117Sbill bit = 1<<(i&07); 42217Sbill if (dzaddr->dzmsr & bit) { 42317Sbill /* carrier present */ 42417Sbill if ((tp->t_state & CARR_ON) == 0) { 42517Sbill wakeup((caddr_t)&tp->t_rawq); 42617Sbill tp->t_state |= CARR_ON; 42717Sbill } 42817Sbill } else { 429882Sbill if ((tp->t_state&CARR_ON) && (tp->t_local&LNOHANG) == 0) { 43017Sbill /* carrier lost */ 431882Sbill if (tp->t_state&ISOPEN) { 432170Sbill gsignal(tp->t_pgrp, SIGHUP); 433205Sbill gsignal(tp->t_pgrp, SIGCONT); 434170Sbill dzaddr->dzdtr &= ~bit; 435871Sbill flushtty(tp, FREAD|FWRITE); 436170Sbill } 437170Sbill tp->t_state &= ~CARR_ON; 43817Sbill } 43917Sbill } 44017Sbill } 44117Sbill timeout(dzscan, (caddr_t)0, 2*HZ); 44217Sbill } 443119Sbill 444119Sbill dztimer() 445119Sbill { 446119Sbill 447119Sbill dzrint(0); 448119Sbill } 449281Sbill 450281Sbill /* 451281Sbill * Reset state of driver if UBA reset was necessary. 452301Sbill * Reset parameters and restart transmission on open lines. 453281Sbill */ 454281Sbill dzreset() 455281Sbill { 456281Sbill int d; 457281Sbill register struct tty *tp; 458281Sbill 459281Sbill printf(" dz"); 460281Sbill for (d = 0; d < NDZ; d++) { 461281Sbill tp = &dz_tty[d]; 462281Sbill if (tp->t_state & (ISOPEN|WOPEN)) { 463281Sbill dzparam(d); 464301Sbill dzmodem(d, ON); 465301Sbill tp->t_state &= ~BUSY; 466301Sbill dzstart(tp); 467281Sbill } 468281Sbill } 469281Sbill dztimer(); 470281Sbill } 4711562Sbill #endif 472