1*921Sbill /* dz.c 3.16 09/27/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" 17871Sbill #include "../h/file.h" 18145Sbill 19145Sbill /* 20145Sbill * When running dz's using only SAE (silo alarm) on input 21145Sbill * it is necessary to call dzrint() at clock interrupt time. 22145Sbill * This is unsafe unless spl5()s in tty code are changed to 23145Sbill * spl6()s to block clock interrupts. Note that the dh driver 24145Sbill * currently in use works the same way as the dz, even though 25145Sbill * we could try to more intelligently manage its silo. 26145Sbill * Thus don't take this out if you have no dz's unless you 27145Sbill * change clock.c and dhtimer(). 28145Sbill */ 29145Sbill #define spl5 spl6 3017Sbill 3117Sbill #define DZADDR (UBA0_DEV + 0160100) 32882Sbill #ifdef DISTRIB 33882Sbill #define NDZ11 1 3417Sbill #else 35*921Sbill #define NDZ11 4 3617Sbill #endif 37882Sbill #define NDZ (NDZ11*8) 3817Sbill 3917Sbill #define BITS7 020 4017Sbill #define BITS8 030 4117Sbill #define TWOSB 040 4217Sbill #define PENABLE 0100 4317Sbill #define OPAR 0200 4417Sbill #define MSE 040 /* Master Scan Enable */ 4517Sbill #define RIE 0100 /* Receiver Interrupt Enable */ 46119Sbill #define SAE 010000 /* Silo Alarm Enable */ 47119Sbill #define TIE 040000 /* Transmit Interrupt Enable */ 48119Sbill #define DZ_IEN (MSE+RIE+TIE+SAE) 4917Sbill #define PERROR 010000 5017Sbill #define FRERROR 020000 51119Sbill #define OVERRUN 040000 5217Sbill #define SSPEED 7 /* std speed = 300 baud */ 5317Sbill 5417Sbill 5517Sbill #define dzlpr dzrbuf 5617Sbill #define dzmsr dzbrk 5717Sbill #define ON 1 5817Sbill #define OFF 0 5917Sbill 6017Sbill int dzstart(); 6117Sbill int dzxint(); 62114Sbill int ttrstrt(); 6317Sbill struct tty dz_tty[NDZ]; 6417Sbill int dz_cnt = { NDZ }; 65119Sbill int dzact; 66281Sbill int dzinit; 6717Sbill 6817Sbill struct device { 6917Sbill short dzcsr; 7017Sbill short dzrbuf; 7117Sbill char dztcr; 7217Sbill char dzdtr; 7317Sbill char dztbuf; 7417Sbill char dzbrk; 7517Sbill }; 7617Sbill 7717Sbill struct pdma dzpdma[] = { 7817Sbill (struct device *)(DZADDR), NULL, NULL, (int)&dz_tty[0], dzxint, 7917Sbill (struct device *)(DZADDR), NULL, NULL, (int)&dz_tty[1], dzxint, 8017Sbill (struct device *)(DZADDR), NULL, NULL, (int)&dz_tty[2], dzxint, 8117Sbill (struct device *)(DZADDR), NULL, NULL, (int)&dz_tty[3], dzxint, 8217Sbill (struct device *)(DZADDR), NULL, NULL, (int)&dz_tty[4], dzxint, 8317Sbill (struct device *)(DZADDR), NULL, NULL, (int)&dz_tty[5], dzxint, 8417Sbill (struct device *)(DZADDR), NULL, NULL, (int)&dz_tty[6], dzxint, 8517Sbill (struct device *)(DZADDR), NULL, NULL, (int)&dz_tty[7], dzxint, 86882Sbill #if NDZ >= 2 8717Sbill (struct device *)(DZADDR+010), NULL, NULL, (int)&dz_tty[8], dzxint, 8817Sbill (struct device *)(DZADDR+010), NULL, NULL, (int)&dz_tty[9], dzxint, 8917Sbill (struct device *)(DZADDR+010), NULL, NULL, (int)&dz_tty[10], dzxint, 9017Sbill (struct device *)(DZADDR+010), NULL, NULL, (int)&dz_tty[11], dzxint, 9117Sbill (struct device *)(DZADDR+010), NULL, NULL, (int)&dz_tty[12], dzxint, 9217Sbill (struct device *)(DZADDR+010), NULL, NULL, (int)&dz_tty[13], dzxint, 9317Sbill (struct device *)(DZADDR+010), NULL, NULL, (int)&dz_tty[14], dzxint, 9417Sbill (struct device *)(DZADDR+010), NULL, NULL, (int)&dz_tty[15], dzxint, 95882Sbill #endif 96882Sbill #if NDZ >= 3 9717Sbill (struct device *)(DZADDR+020), NULL, NULL, (int)&dz_tty[16], dzxint, 9817Sbill (struct device *)(DZADDR+020), NULL, NULL, (int)&dz_tty[17], dzxint, 9917Sbill (struct device *)(DZADDR+020), NULL, NULL, (int)&dz_tty[18], dzxint, 10017Sbill (struct device *)(DZADDR+020), NULL, NULL, (int)&dz_tty[19], dzxint, 10117Sbill (struct device *)(DZADDR+020), NULL, NULL, (int)&dz_tty[20], dzxint, 10217Sbill (struct device *)(DZADDR+020), NULL, NULL, (int)&dz_tty[21], dzxint, 10317Sbill (struct device *)(DZADDR+020), NULL, NULL, (int)&dz_tty[22], dzxint, 10417Sbill (struct device *)(DZADDR+020), NULL, NULL, (int)&dz_tty[23], dzxint, 10517Sbill #endif 106882Sbill #if NDZ >= 4 107882Sbill (struct device *)(DZADDR+030), NULL, NULL, (int)&dz_tty[24], dzxint, 108882Sbill (struct device *)(DZADDR+030), NULL, NULL, (int)&dz_tty[25], dzxint, 109882Sbill (struct device *)(DZADDR+030), NULL, NULL, (int)&dz_tty[26], dzxint, 110882Sbill (struct device *)(DZADDR+030), NULL, NULL, (int)&dz_tty[27], dzxint, 111882Sbill (struct device *)(DZADDR+030), NULL, NULL, (int)&dz_tty[28], dzxint, 112882Sbill (struct device *)(DZADDR+030), NULL, NULL, (int)&dz_tty[29], dzxint, 113882Sbill (struct device *)(DZADDR+030), NULL, NULL, (int)&dz_tty[30], dzxint, 114882Sbill (struct device *)(DZADDR+030), NULL, NULL, (int)&dz_tty[31], dzxint, 115882Sbill #endif 11617Sbill }; 11717Sbill char dz_timer; 11817Sbill char dz_speeds[] = { 11917Sbill 0, 020 , 021 , 022 , 023 , 024 , 0, 025, 12017Sbill 026 , 027 , 030 , 032 , 034 , 036 , 0 , 0, 12117Sbill }; 12217Sbill 12317Sbill /*ARGSUSED*/ 12417Sbill dzopen(d, flag) 12517Sbill { 12617Sbill register struct tty *tp; 12717Sbill register dev; 12817Sbill extern dzscan(); 12917Sbill 13017Sbill dev = minor(d); 13117Sbill if (dev >= dz_cnt) { 13217Sbill u.u_error = ENXIO; 13317Sbill return; 13417Sbill } 13517Sbill if (dz_timer == 0) { 13617Sbill dz_timer++; 13717Sbill timeout(dzscan, (caddr_t)0, 60); 13817Sbill } 13917Sbill tp = &dz_tty[dev]; 14017Sbill tp->t_addr = (caddr_t)&dzpdma[dev]; 14117Sbill tp->t_oproc = dzstart; 14217Sbill tp->t_iproc = NULL; 14317Sbill tp->t_state |= WOPEN; 14417Sbill if ((tp->t_state & ISOPEN) == 0) { 14517Sbill ttychars(tp); 14617Sbill tp->t_ospeed = tp->t_ispeed = SSPEED; 14717Sbill tp->t_flags = ODDP|EVENP|ECHO; 14817Sbill /*tp->t_state |= HUPCLS;*/ 14917Sbill dzparam(dev); 15017Sbill } else if (tp->t_state&XCLUDE && u.u_uid != 0) { 15117Sbill u.u_error = EBUSY; 15217Sbill return; 15317Sbill } 15417Sbill dzmodem(dev, ON); 155114Sbill (void) spl5(); 15617Sbill while ((tp->t_state & CARR_ON) == 0) { 15717Sbill tp->t_state |= WOPEN; 15817Sbill sleep((caddr_t)&tp->t_rawq, TTIPRI); 15917Sbill } 160114Sbill (void) spl0(); 16117Sbill (*linesw[tp->t_line].l_open)(d, tp); 16217Sbill } 16317Sbill 16417Sbill dzclose(d) 16517Sbill { 16617Sbill register struct tty *tp; 16717Sbill register dev; 16817Sbill 16917Sbill dev = minor(d); 17017Sbill tp = &dz_tty[dev]; 17117Sbill (*linesw[tp->t_line].l_close)(tp); 17217Sbill if (tp->t_state & HUPCLS) 17317Sbill dzmodem(dev, OFF); 17417Sbill ttyclose(tp); 17517Sbill } 17617Sbill 17717Sbill dzread(d) 17817Sbill { 17917Sbill register struct tty *tp; 18017Sbill 18117Sbill tp = &dz_tty[minor(d)]; 18217Sbill (*linesw[tp->t_line].l_read)(tp); 18317Sbill } 18417Sbill 18517Sbill dzwrite(d) 18617Sbill { 18717Sbill register struct tty *tp; 18817Sbill 18917Sbill tp = &dz_tty[minor(d)]; 19017Sbill (*linesw[tp->t_line].l_write)(tp); 19117Sbill } 19217Sbill 193119Sbill /*ARGSUSED*/ 19417Sbill dzrint(dev) 19517Sbill { 19617Sbill register struct tty *tp; 19717Sbill register int c; 19817Sbill register struct device *dzaddr; 199119Sbill register struct tty *tp0; 200140Sbill int s; 20117Sbill 202140Sbill s = spl6(); /* see comment in clock.c */ 203119Sbill /* as long as we are here, service them all */ 204119Sbill for (dev = 0; dev < NDZ; dev += 8) { 205119Sbill if ((dzact & (1<<(dev>>3))) == 0) 20617Sbill continue; 207119Sbill dzaddr = dzpdma[dev].p_addr; 208119Sbill tp0 = &dz_tty[dev]; 209119Sbill while ((c = dzaddr->dzrbuf) < 0) { /* char present */ 210119Sbill tp = tp0 + ((c>>8)&07); 211119Sbill if (tp >= &dz_tty[dz_cnt]) 21217Sbill continue; 213119Sbill if ((tp->t_state & ISOPEN) == 0) { 214119Sbill wakeup((caddr_t)&tp->t_rawq); 215119Sbill continue; 216119Sbill } 217119Sbill if (c&FRERROR) 218119Sbill /* framing error = break */ 219119Sbill if (tp->t_flags & RAW) 220119Sbill c = 0; /* null for getty */ 221119Sbill else 222170Sbill #ifdef IIASA 223170Sbill continue; 224170Sbill #else 225185Sbill c = tun.t_intrc; 226170Sbill #endif 227119Sbill if (c&OVERRUN) 228119Sbill printf("o"); 229119Sbill if (c&PERROR) 230119Sbill /* parity error */ 231119Sbill if (((tp->t_flags & (EVENP|ODDP)) == EVENP) 232119Sbill || ((tp->t_flags & (EVENP|ODDP)) == ODDP)) 233119Sbill continue; 234140Sbill if (tp->t_line == NETLDISC) { 235114Sbill c &= 0177; 236170Sbill BKINPUT(c, tp); 237114Sbill } else 238114Sbill (*linesw[tp->t_line].l_rint)(c, tp); 239119Sbill } 24017Sbill } 241140Sbill splx(s); 24217Sbill } 24317Sbill 24417Sbill /*ARGSUSED*/ 24517Sbill dzioctl(dev, cmd, addr, flag) 24617Sbill caddr_t addr; 24717Sbill dev_t dev; 24817Sbill { 24917Sbill register struct tty *tp; 250882Sbill static char dz_brk[NDZ11]; 25117Sbill 25217Sbill tp = &dz_tty[minor(dev)]; 253114Sbill cmd = (*linesw[tp->t_line].l_ioctl)(tp, cmd, addr); 254114Sbill if (cmd == 0) 255114Sbill return; 256902Sbill if (ttioctl(cmd, tp, addr, dev, flag)) { 25717Sbill if (cmd==TIOCSETP || cmd==TIOCSETN) 25817Sbill dzparam(minor(dev)); 259170Sbill } else switch(cmd) { 260170Sbill case TIOCSBRK: 261882Sbill ((struct pdma *)(tp->t_addr))->p_addr->dzbrk = 262882Sbill (dz_brk[minor(dev)>>3] |= 1 << (dev&07)); 263170Sbill break; 264170Sbill case TIOCCBRK: 265882Sbill ((struct pdma *)(tp->t_addr))->p_addr->dzbrk = 266882Sbill (dz_brk[minor(dev)>>3] &= ~(1 << (dev&07))); 267170Sbill break; 268170Sbill case TIOCSDTR: 269210Sbill dzmodem(minor(dev), ON); 270170Sbill break; 271170Sbill case TIOCCDTR: 272210Sbill dzmodem(minor(dev), OFF); 273170Sbill break; 274170Sbill default: 27517Sbill u.u_error = ENOTTY; 276170Sbill } 27717Sbill } 27817Sbill 27917Sbill dzparam(dev) 28017Sbill { 28117Sbill register struct tty *tp; 28217Sbill register struct device *dzaddr; 28317Sbill register short lpr; 28417Sbill 28517Sbill tp = &dz_tty[dev]; 28617Sbill dzaddr = dzpdma[dev].p_addr; 28717Sbill dzaddr->dzcsr = DZ_IEN; 288119Sbill dzact |= (1<<(dev>>3)); 28917Sbill if (tp->t_ispeed == 0) { 29017Sbill dzmodem(dev, OFF); /* hang up line */ 29117Sbill return; 29217Sbill } 29317Sbill lpr = (dz_speeds[tp->t_ispeed]<<8) | (dev & 07); 294882Sbill #ifndef IIASA 29517Sbill if (tp->t_flags & RAW) 29617Sbill lpr |= BITS8; 29717Sbill else 29817Sbill lpr |= (BITS7|PENABLE); 29917Sbill if ((tp->t_flags & EVENP) == 0) 30017Sbill lpr |= OPAR; 301882Sbill #else IIASA 302882Sbill if ((tp->t_flags & (EVENP|ODDP)) == (EVENP|ODDP)) 303882Sbill lpr |= BITS8; 304882Sbill else if (tp->t_flags & EVENP) 305882Sbill lpr |= (BITS7|PENABLE); 306882Sbill else if (tp->t_flags & ODDP) 307882Sbill lpr |= (BITS7|OPAR|PENABLE); 308882Sbill else 309882Sbill lpr |= BITS7; 310882Sbill #endif IIASA 31117Sbill if (tp->t_ispeed == 3) 31217Sbill lpr |= TWOSB; /* 110 baud: 2 stop bits */ 31317Sbill dzaddr->dzlpr = lpr; 31417Sbill } 31517Sbill 31617Sbill dzxint(tp) 31717Sbill register struct tty *tp; 31817Sbill { 31917Sbill register struct pdma *dp; 320145Sbill register s; 321145Sbill s = spl6(); /* block the clock */ 32217Sbill 32317Sbill dp = &dzpdma[tp-dz_tty]; 32417Sbill tp->t_state &= ~BUSY; 32517Sbill if (tp->t_state & FLUSH) 32617Sbill tp->t_state &= ~FLUSH; 32717Sbill else 328281Sbill ndflush(&tp->t_outq, dp->p_mem-tp->t_outq.c_cf); 32917Sbill if (tp->t_line) 33017Sbill (*linesw[tp->t_line].l_start)(tp); 33117Sbill else 33217Sbill dzstart(tp); 33317Sbill if (tp->t_outq.c_cc == 0 || (tp->t_state&BUSY)==0) 33417Sbill dp->p_addr->dztcr &= ~(1 << ((tp-dz_tty) % 8)); 335145Sbill splx(s); 33617Sbill } 33717Sbill 33817Sbill dzstart(tp) 33917Sbill register struct tty *tp; 34017Sbill { 34117Sbill register struct pdma *dp; 34217Sbill register struct device *dzaddr; 34317Sbill register cc; 34417Sbill int sps; 34517Sbill 34617Sbill dp = &dzpdma[tp-dz_tty]; 34717Sbill dzaddr = dp->p_addr; 34817Sbill sps = spl5(); 34917Sbill if (tp->t_state & (TIMEOUT|BUSY|TTSTOP)) 35017Sbill goto out; 351*921Sbill if (tp->t_state&ASLEEP && tp->t_outq.c_cc <= TTLOWAT(tp)) { 35217Sbill tp->t_state &= ~ASLEEP; 35317Sbill if (tp->t_chan) 35417Sbill mcstart(tp->t_chan, (caddr_t)&tp->t_outq); 35517Sbill else 35617Sbill wakeup((caddr_t)&tp->t_outq); 35717Sbill } 35817Sbill if (tp->t_outq.c_cc == 0) 35917Sbill goto out; 36017Sbill if (tp->t_flags&RAW) 36117Sbill cc = ndqb(&tp->t_outq, 0); 36217Sbill else { 36317Sbill cc = ndqb(&tp->t_outq, 0200); 36417Sbill if (cc == 0) { 36517Sbill cc = getc(&tp->t_outq); 36617Sbill timeout(ttrstrt, (caddr_t)tp, (cc&0177) + 6); 36717Sbill tp->t_state |= TIMEOUT; 36817Sbill goto out; 36917Sbill } 37017Sbill } 37117Sbill tp->t_state |= BUSY; 37217Sbill dp->p_end = dp->p_mem = tp->t_outq.c_cf; 37317Sbill dp->p_end += cc; 37417Sbill dzaddr->dztcr |= 1 << ((tp-dz_tty) % 8); 37517Sbill out: 37617Sbill splx(sps); 37717Sbill } 37817Sbill 37917Sbill /* 38017Sbill * Stop output on a line. 38117Sbill * Assume call is made at spl6. 38217Sbill */ 38317Sbill /*ARGSUSED*/ 38417Sbill dzstop(tp, flag) 38517Sbill register struct tty *tp; 38617Sbill { 38717Sbill register struct pdma *dp; 38817Sbill register int s; 38917Sbill 39017Sbill dp = &dzpdma[tp-dz_tty]; 39117Sbill s = spl6(); 39217Sbill if (tp->t_state & BUSY) { 39317Sbill dp->p_end = dp->p_mem; 39417Sbill if ((tp->t_state&TTSTOP)==0) { 39517Sbill tp->t_state |= FLUSH; 39617Sbill } 39717Sbill } 39817Sbill splx(s); 39917Sbill } 40017Sbill 40117Sbill dzmodem(dev, flag) 40217Sbill register int dev; 40317Sbill { 40417Sbill register struct device *dzaddr; 40517Sbill register char bit; 40617Sbill 40717Sbill dzaddr = dzpdma[dev].p_addr; 40817Sbill bit = 1<<(dev&07); 40917Sbill if (flag == OFF) 41017Sbill dzaddr->dzdtr &= ~bit; 41117Sbill else 41217Sbill dzaddr->dzdtr |= bit; 41317Sbill } 41417Sbill 41517Sbill dzscan() 41617Sbill { 41717Sbill register i; 41817Sbill register struct device *dzaddr; 41917Sbill register bit; 42017Sbill register struct tty *tp; 42117Sbill 42217Sbill for (i = 0; i < dz_cnt ; i++) { 42317Sbill dzaddr = dzpdma[i].p_addr; 42417Sbill tp = &dz_tty[i]; 42517Sbill bit = 1<<(i&07); 42617Sbill if (dzaddr->dzmsr & bit) { 42717Sbill /* carrier present */ 42817Sbill if ((tp->t_state & CARR_ON) == 0) { 42917Sbill wakeup((caddr_t)&tp->t_rawq); 43017Sbill tp->t_state |= CARR_ON; 43117Sbill } 43217Sbill } else { 433882Sbill if ((tp->t_state&CARR_ON) && (tp->t_local&LNOHANG) == 0) { 43417Sbill /* carrier lost */ 435882Sbill if (tp->t_state&ISOPEN) { 436170Sbill gsignal(tp->t_pgrp, SIGHUP); 437205Sbill gsignal(tp->t_pgrp, SIGCONT); 438170Sbill dzaddr->dzdtr &= ~bit; 439871Sbill flushtty(tp, FREAD|FWRITE); 440170Sbill } 441170Sbill tp->t_state &= ~CARR_ON; 44217Sbill } 44317Sbill } 44417Sbill } 44517Sbill timeout(dzscan, (caddr_t)0, 2*HZ); 44617Sbill } 447119Sbill 448119Sbill dztimer() 449119Sbill { 450119Sbill 451119Sbill dzrint(0); 452119Sbill } 453281Sbill 454281Sbill /* 455281Sbill * Reset state of driver if UBA reset was necessary. 456301Sbill * Reset parameters and restart transmission on open lines. 457281Sbill */ 458281Sbill dzreset() 459281Sbill { 460281Sbill int d; 461281Sbill register struct tty *tp; 462281Sbill 463281Sbill printf(" dz"); 464281Sbill for (d = 0; d < NDZ; d++) { 465281Sbill tp = &dz_tty[d]; 466281Sbill if (tp->t_state & (ISOPEN|WOPEN)) { 467281Sbill dzparam(d); 468301Sbill dzmodem(d, ON); 469301Sbill tp->t_state &= ~BUSY; 470301Sbill dzstart(tp); 471281Sbill } 472281Sbill } 473281Sbill dztimer(); 474281Sbill } 475