1*281Sbill /* dz.c 3.11 06/22/80 */ 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" 17145Sbill 18145Sbill /* 19145Sbill * When running dz's using only SAE (silo alarm) on input 20145Sbill * it is necessary to call dzrint() at clock interrupt time. 21145Sbill * This is unsafe unless spl5()s in tty code are changed to 22145Sbill * spl6()s to block clock interrupts. Note that the dh driver 23145Sbill * currently in use works the same way as the dz, even though 24145Sbill * we could try to more intelligently manage its silo. 25145Sbill * Thus don't take this out if you have no dz's unless you 26145Sbill * change clock.c and dhtimer(). 27145Sbill */ 28145Sbill #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; 64*281Sbill int dzinit; 65*281Sbill int dzdtr[(NDZ+7)/8]; 6617Sbill 6717Sbill struct device { 6817Sbill short dzcsr; 6917Sbill short dzrbuf; 7017Sbill char dztcr; 7117Sbill char dzdtr; 7217Sbill char dztbuf; 7317Sbill char dzbrk; 7417Sbill }; 7517Sbill 7617Sbill struct pdma dzpdma[] = { 7717Sbill (struct device *)(DZADDR), NULL, NULL, (int)&dz_tty[0], dzxint, 7817Sbill (struct device *)(DZADDR), NULL, NULL, (int)&dz_tty[1], dzxint, 7917Sbill (struct device *)(DZADDR), NULL, NULL, (int)&dz_tty[2], dzxint, 8017Sbill (struct device *)(DZADDR), NULL, NULL, (int)&dz_tty[3], dzxint, 8117Sbill (struct device *)(DZADDR), NULL, NULL, (int)&dz_tty[4], dzxint, 8217Sbill (struct device *)(DZADDR), NULL, NULL, (int)&dz_tty[5], dzxint, 8317Sbill (struct device *)(DZADDR), NULL, NULL, (int)&dz_tty[6], dzxint, 8417Sbill (struct device *)(DZADDR), NULL, NULL, (int)&dz_tty[7], dzxint, 8517Sbill #ifdef ERNIE 8617Sbill (struct device *)(DZADDR+010), NULL, NULL, (int)&dz_tty[8], dzxint, 8717Sbill (struct device *)(DZADDR+010), NULL, NULL, (int)&dz_tty[9], dzxint, 8817Sbill (struct device *)(DZADDR+010), NULL, NULL, (int)&dz_tty[10], dzxint, 8917Sbill (struct device *)(DZADDR+010), NULL, NULL, (int)&dz_tty[11], dzxint, 9017Sbill (struct device *)(DZADDR+010), NULL, NULL, (int)&dz_tty[12], dzxint, 9117Sbill (struct device *)(DZADDR+010), NULL, NULL, (int)&dz_tty[13], dzxint, 9217Sbill (struct device *)(DZADDR+010), NULL, NULL, (int)&dz_tty[14], dzxint, 9317Sbill (struct device *)(DZADDR+010), NULL, NULL, (int)&dz_tty[15], dzxint, 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 10317Sbill }; 10417Sbill char dz_timer; 10517Sbill char dz_speeds[] = { 10617Sbill 0, 020 , 021 , 022 , 023 , 024 , 0, 025, 10717Sbill 026 , 027 , 030 , 032 , 034 , 036 , 0 , 0, 10817Sbill }; 10917Sbill 11017Sbill /*ARGSUSED*/ 11117Sbill dzopen(d, flag) 11217Sbill { 11317Sbill register struct tty *tp; 11417Sbill register dev; 11517Sbill extern dzscan(); 11617Sbill 11717Sbill dev = minor(d); 11817Sbill if (dev >= dz_cnt) { 11917Sbill u.u_error = ENXIO; 12017Sbill return; 12117Sbill } 12217Sbill if (dz_timer == 0) { 12317Sbill dz_timer++; 12417Sbill timeout(dzscan, (caddr_t)0, 60); 12517Sbill } 12617Sbill tp = &dz_tty[dev]; 12717Sbill tp->t_addr = (caddr_t)&dzpdma[dev]; 12817Sbill tp->t_oproc = dzstart; 12917Sbill tp->t_iproc = NULL; 13017Sbill tp->t_state |= WOPEN; 13117Sbill if ((tp->t_state & ISOPEN) == 0) { 13217Sbill ttychars(tp); 13317Sbill tp->t_ospeed = tp->t_ispeed = SSPEED; 13417Sbill tp->t_flags = ODDP|EVENP|ECHO; 13517Sbill /*tp->t_state |= HUPCLS;*/ 13617Sbill dzparam(dev); 13717Sbill } else if (tp->t_state&XCLUDE && u.u_uid != 0) { 13817Sbill u.u_error = EBUSY; 13917Sbill return; 14017Sbill } 14117Sbill dzmodem(dev, ON); 142114Sbill (void) spl5(); 14317Sbill while ((tp->t_state & CARR_ON) == 0) { 14417Sbill tp->t_state |= WOPEN; 14517Sbill sleep((caddr_t)&tp->t_rawq, TTIPRI); 14617Sbill } 147114Sbill (void) spl0(); 14817Sbill (*linesw[tp->t_line].l_open)(d, tp); 14917Sbill } 15017Sbill 15117Sbill dzclose(d) 15217Sbill { 15317Sbill register struct tty *tp; 15417Sbill register dev; 15517Sbill 15617Sbill dev = minor(d); 15717Sbill tp = &dz_tty[dev]; 15817Sbill (*linesw[tp->t_line].l_close)(tp); 15917Sbill if (tp->t_state & HUPCLS) 16017Sbill dzmodem(dev, OFF); 16117Sbill ttyclose(tp); 16217Sbill } 16317Sbill 16417Sbill dzread(d) 16517Sbill { 16617Sbill register struct tty *tp; 16717Sbill 16817Sbill tp = &dz_tty[minor(d)]; 16917Sbill (*linesw[tp->t_line].l_read)(tp); 17017Sbill } 17117Sbill 17217Sbill dzwrite(d) 17317Sbill { 17417Sbill register struct tty *tp; 17517Sbill 17617Sbill tp = &dz_tty[minor(d)]; 17717Sbill (*linesw[tp->t_line].l_write)(tp); 17817Sbill } 17917Sbill 180119Sbill /*ARGSUSED*/ 18117Sbill dzrint(dev) 18217Sbill { 18317Sbill register struct tty *tp; 18417Sbill register int c; 18517Sbill register struct device *dzaddr; 186119Sbill register struct tty *tp0; 187140Sbill int s; 18817Sbill 189140Sbill s = spl6(); /* see comment in clock.c */ 190119Sbill /* as long as we are here, service them all */ 191119Sbill for (dev = 0; dev < NDZ; dev += 8) { 192119Sbill if ((dzact & (1<<(dev>>3))) == 0) 19317Sbill continue; 194119Sbill dzaddr = dzpdma[dev].p_addr; 195119Sbill tp0 = &dz_tty[dev]; 196119Sbill while ((c = dzaddr->dzrbuf) < 0) { /* char present */ 197119Sbill tp = tp0 + ((c>>8)&07); 198119Sbill if (tp >= &dz_tty[dz_cnt]) 19917Sbill continue; 200119Sbill if ((tp->t_state & ISOPEN) == 0) { 201119Sbill wakeup((caddr_t)&tp->t_rawq); 202119Sbill continue; 203119Sbill } 204119Sbill if (c&FRERROR) 205119Sbill /* framing error = break */ 206119Sbill if (tp->t_flags & RAW) 207119Sbill c = 0; /* null for getty */ 208119Sbill else 209170Sbill #ifdef IIASA 210170Sbill continue; 211170Sbill #else 212185Sbill c = tun.t_intrc; 213170Sbill #endif 214119Sbill if (c&OVERRUN) 215119Sbill printf("o"); 216119Sbill if (c&PERROR) 217119Sbill /* parity error */ 218119Sbill if (((tp->t_flags & (EVENP|ODDP)) == EVENP) 219119Sbill || ((tp->t_flags & (EVENP|ODDP)) == ODDP)) 220119Sbill continue; 221140Sbill if (tp->t_line == NETLDISC) { 222114Sbill c &= 0177; 223170Sbill BKINPUT(c, tp); 224114Sbill } else 225114Sbill (*linesw[tp->t_line].l_rint)(c, tp); 226119Sbill } 22717Sbill } 228140Sbill splx(s); 22917Sbill } 23017Sbill 23117Sbill /*ARGSUSED*/ 23217Sbill dzioctl(dev, cmd, addr, flag) 23317Sbill caddr_t addr; 23417Sbill dev_t dev; 23517Sbill { 23617Sbill register struct tty *tp; 23717Sbill 23817Sbill tp = &dz_tty[minor(dev)]; 239114Sbill cmd = (*linesw[tp->t_line].l_ioctl)(tp, cmd, addr); 240114Sbill if (cmd == 0) 241114Sbill return; 24217Sbill if (ttioccomm(cmd, tp, addr, dev)) { 24317Sbill if (cmd==TIOCSETP || cmd==TIOCSETN) 24417Sbill dzparam(minor(dev)); 245170Sbill } else switch(cmd) { 246170Sbill case TIOCSBRK: 247170Sbill ((struct device *)(tp->t_addr))->dzbrk |= 1 << (dev&07); 248170Sbill break; 249170Sbill case TIOCCBRK: 250170Sbill ((struct device *)(tp->t_addr))->dzbrk &= ~(1 << (dev&07)); 251170Sbill break; 252170Sbill case TIOCSDTR: 253210Sbill dzmodem(minor(dev), ON); 254170Sbill break; 255170Sbill case TIOCCDTR: 256210Sbill dzmodem(minor(dev), OFF); 257170Sbill break; 258170Sbill default: 25917Sbill u.u_error = ENOTTY; 260170Sbill } 26117Sbill } 26217Sbill 26317Sbill dzparam(dev) 26417Sbill { 26517Sbill register struct tty *tp; 26617Sbill register struct device *dzaddr; 26717Sbill register short lpr; 26817Sbill 26917Sbill tp = &dz_tty[dev]; 27017Sbill dzaddr = dzpdma[dev].p_addr; 27117Sbill dzaddr->dzcsr = DZ_IEN; 272119Sbill dzact |= (1<<(dev>>3)); 27317Sbill if (tp->t_ispeed == 0) { 27417Sbill dzmodem(dev, OFF); /* hang up line */ 27517Sbill return; 27617Sbill } 27717Sbill lpr = (dz_speeds[tp->t_ispeed]<<8) | (dev & 07); 27817Sbill if (tp->t_flags & RAW) 27917Sbill lpr |= BITS8; 28017Sbill else 28117Sbill lpr |= (BITS7|PENABLE); 28217Sbill if ((tp->t_flags & EVENP) == 0) 28317Sbill lpr |= OPAR; 28417Sbill if (tp->t_ispeed == 3) 28517Sbill lpr |= TWOSB; /* 110 baud: 2 stop bits */ 28617Sbill dzaddr->dzlpr = lpr; 28717Sbill } 28817Sbill 28917Sbill dzxint(tp) 29017Sbill register struct tty *tp; 29117Sbill { 29217Sbill register struct pdma *dp; 293145Sbill register s; 294145Sbill s = spl6(); /* block the clock */ 29517Sbill 29617Sbill dp = &dzpdma[tp-dz_tty]; 29717Sbill tp->t_state &= ~BUSY; 29817Sbill if (tp->t_state & FLUSH) 29917Sbill tp->t_state &= ~FLUSH; 30017Sbill else 301*281Sbill ndflush(&tp->t_outq, dp->p_mem-tp->t_outq.c_cf); 30217Sbill if (tp->t_line) 30317Sbill (*linesw[tp->t_line].l_start)(tp); 30417Sbill else 30517Sbill dzstart(tp); 30617Sbill if (tp->t_outq.c_cc == 0 || (tp->t_state&BUSY)==0) 30717Sbill dp->p_addr->dztcr &= ~(1 << ((tp-dz_tty) % 8)); 308145Sbill splx(s); 30917Sbill } 31017Sbill 31117Sbill dzstart(tp) 31217Sbill register struct tty *tp; 31317Sbill { 31417Sbill register struct pdma *dp; 31517Sbill register struct device *dzaddr; 31617Sbill register cc; 31717Sbill int sps; 31817Sbill 31917Sbill dp = &dzpdma[tp-dz_tty]; 32017Sbill dzaddr = dp->p_addr; 32117Sbill sps = spl5(); 32217Sbill if (tp->t_state & (TIMEOUT|BUSY|TTSTOP)) 32317Sbill goto out; 32417Sbill if (tp->t_outq.c_cc <= TTLOWAT && tp->t_state&ASLEEP) { 32517Sbill tp->t_state &= ~ASLEEP; 32617Sbill if (tp->t_chan) 32717Sbill mcstart(tp->t_chan, (caddr_t)&tp->t_outq); 32817Sbill else 32917Sbill wakeup((caddr_t)&tp->t_outq); 33017Sbill } 33117Sbill if (tp->t_outq.c_cc == 0) 33217Sbill goto out; 33317Sbill if (tp->t_flags&RAW) 33417Sbill cc = ndqb(&tp->t_outq, 0); 33517Sbill else { 33617Sbill cc = ndqb(&tp->t_outq, 0200); 33717Sbill if (cc == 0) { 33817Sbill cc = getc(&tp->t_outq); 33917Sbill timeout(ttrstrt, (caddr_t)tp, (cc&0177) + 6); 34017Sbill tp->t_state |= TIMEOUT; 34117Sbill goto out; 34217Sbill } 34317Sbill } 34417Sbill tp->t_state |= BUSY; 34517Sbill dp->p_end = dp->p_mem = tp->t_outq.c_cf; 34617Sbill dp->p_end += cc; 34717Sbill dzaddr->dztcr |= 1 << ((tp-dz_tty) % 8); 34817Sbill out: 34917Sbill splx(sps); 35017Sbill } 35117Sbill 35217Sbill /* 35317Sbill * Stop output on a line. 35417Sbill * Assume call is made at spl6. 35517Sbill */ 35617Sbill /*ARGSUSED*/ 35717Sbill dzstop(tp, flag) 35817Sbill register struct tty *tp; 35917Sbill { 36017Sbill register struct pdma *dp; 36117Sbill register int s; 36217Sbill 36317Sbill dp = &dzpdma[tp-dz_tty]; 36417Sbill s = spl6(); 36517Sbill if (tp->t_state & BUSY) { 36617Sbill dp->p_end = dp->p_mem; 36717Sbill if ((tp->t_state&TTSTOP)==0) { 36817Sbill tp->t_state |= FLUSH; 36917Sbill } 37017Sbill } 37117Sbill splx(s); 37217Sbill } 37317Sbill 37417Sbill dzmodem(dev, flag) 37517Sbill register int dev; 37617Sbill { 37717Sbill register struct device *dzaddr; 37817Sbill register char bit; 37917Sbill 38017Sbill dzaddr = dzpdma[dev].p_addr; 38117Sbill bit = 1<<(dev&07); 38217Sbill if (flag == OFF) 38317Sbill dzaddr->dzdtr &= ~bit; 38417Sbill else 38517Sbill dzaddr->dzdtr |= bit; 386*281Sbill dzdtr[minor(dev)>>3] = dzaddr->dzdtr; 38717Sbill } 38817Sbill 38917Sbill dzscan() 39017Sbill { 39117Sbill register i; 39217Sbill register struct device *dzaddr; 39317Sbill register bit; 39417Sbill register struct tty *tp; 39517Sbill 39617Sbill for (i = 0; i < dz_cnt ; i++) { 39717Sbill dzaddr = dzpdma[i].p_addr; 39817Sbill tp = &dz_tty[i]; 39917Sbill bit = 1<<(i&07); 40017Sbill if (dzaddr->dzmsr & bit) { 40117Sbill /* carrier present */ 40217Sbill if ((tp->t_state & CARR_ON) == 0) { 40317Sbill wakeup((caddr_t)&tp->t_rawq); 40417Sbill tp->t_state |= CARR_ON; 40517Sbill } 40617Sbill } else { 40717Sbill if ((tp->t_state & CARR_ON)) { 40817Sbill /* carrier lost */ 409170Sbill if (tp->t_state&ISOPEN && 410170Sbill (tp->t_local&LNOHANG) == 0) { 411170Sbill gsignal(tp->t_pgrp, SIGHUP); 412205Sbill gsignal(tp->t_pgrp, SIGCONT); 413170Sbill dzaddr->dzdtr &= ~bit; 414*281Sbill dzdtr[i>>3] = dzaddr->dzdtr; 415170Sbill flushtty(tp); 416170Sbill } 417170Sbill tp->t_state &= ~CARR_ON; 41817Sbill } 41917Sbill } 42017Sbill } 42117Sbill timeout(dzscan, (caddr_t)0, 2*HZ); 42217Sbill } 423119Sbill 424119Sbill dztimer() 425119Sbill { 426119Sbill 427119Sbill dzrint(0); 428119Sbill } 429*281Sbill 430*281Sbill /* 431*281Sbill * Reset state of driver if UBA reset was necessary. 432*281Sbill * Reset all the dzdtr registers, then the csr and lpr 433*281Sbill * registers, then restart all pending transmissions. 434*281Sbill */ 435*281Sbill dzreset() 436*281Sbill { 437*281Sbill int d; 438*281Sbill register struct tty *tp; 439*281Sbill 440*281Sbill printf(" dz"); 441*281Sbill dzinit = 1; 442*281Sbill for (d = 0; d < NDZ; d += 8) 443*281Sbill dzpdma[d].p_addr->dzdtr = dzdtr[d>>3]; 444*281Sbill for (d = 0; d < NDZ; d++) { 445*281Sbill tp = &dz_tty[d]; 446*281Sbill if (tp->t_state & (ISOPEN|WOPEN)) { 447*281Sbill dzparam(d); 448*281Sbill dzxint(tp); 449*281Sbill } 450*281Sbill } 451*281Sbill dztimer(); 452*281Sbill dzinit = 0; 453*281Sbill } 454