1*2457Swnj /* dz.c 4.12 02/16/81 */ 217Sbill 31935Swnj #include "dz.h" 41562Sbill #if NDZ11 > 0 5*2457Swnj #define DELAY(i) { register int j = i; while (--j > 0); } 617Sbill /* 717Sbill * DZ-11 Driver 817Sbill */ 917Sbill #include "../h/param.h" 1017Sbill #include "../h/systm.h" 1117Sbill #include "../h/tty.h" 1217Sbill #include "../h/dir.h" 1317Sbill #include "../h/user.h" 1417Sbill #include "../h/map.h" 1517Sbill #include "../h/pte.h" 162395Swnj #include "../h/buf.h" 1717Sbill #include "../h/uba.h" 1817Sbill #include "../h/conf.h" 1917Sbill #include "../h/pdma.h" 20114Sbill #include "../h/bk.h" 21871Sbill #include "../h/file.h" 221786Sbill #include "../h/mx.h" 23145Sbill 242395Swnj int dzcntrlr(), dzslave(), dzrint(); 252395Swnj struct uba_dinfo *dzinfo[NDZ11]; 262395Swnj u_short dzstd[] = { 0 }; 272395Swnj struct uba_driver dzdriver = 28*2457Swnj { dzcntrlr, dzslave, 0, 0, dzstd, "dz", dzinfo }; 292395Swnj 30*2457Swnj #define NDZ (NDZ11*8) 3117Sbill 32*2457Swnj #define BITS7 020 33*2457Swnj #define BITS8 030 34*2457Swnj #define TWOSB 040 35*2457Swnj #define PENABLE 0100 36*2457Swnj #define OPAR 0200 372422Skre #define CLR 020 /* Reset dz */ 38*2457Swnj #define MSE 040 /* Master Scan Enable */ 39*2457Swnj #define RIE 0100 /* Receiver Interrupt Enable */ 40119Sbill #define SAE 010000 /* Silo Alarm Enable */ 41*2457Swnj #define TIE 040000 /* Transmit Interrupt Enable */ 42*2457Swnj #define DZ_IEN (MSE+RIE+TIE+SAE) 43*2457Swnj #define PERROR 010000 44*2457Swnj #define FRERROR 020000 45119Sbill #define OVERRUN 040000 46*2457Swnj #define SSPEED 7 /* std speed = 300 baud */ 4717Sbill 4817Sbill #define dzlpr dzrbuf 49*2457Swnj #define dzmsr dzbrk 50*2457Swnj #define ON 1 51*2457Swnj #define OFF 0 5217Sbill 5317Sbill int dzstart(); 5417Sbill int dzxint(); 552395Swnj int dzdma(); 56114Sbill int ttrstrt(); 5717Sbill struct tty dz_tty[NDZ]; 5817Sbill int dz_cnt = { NDZ }; 59119Sbill int dzact; 6017Sbill 6117Sbill struct device { 6217Sbill short dzcsr; 6317Sbill short dzrbuf; 6417Sbill char dztcr; 6517Sbill char dzdtr; 6617Sbill char dztbuf; 6717Sbill char dzbrk; 6817Sbill }; 6917Sbill 702395Swnj struct pdma dzpdma[NDZ]; 7117Sbill char dz_timer; 722395Swnj char dz_speeds[] = 732395Swnj { 0,020,021,022,023,024,0,025,026,027,030,032,034,036,0,0 }; 742395Swnj char dz_brk[NDZ11]; 7517Sbill 762395Swnj dzcntrlr(ui, reg) 772395Swnj struct uba_dinfo *ui; 782395Swnj caddr_t reg; 792395Swnj { 80*2457Swnj register int br, cvec; 81*2457Swnj register struct device *dzaddr = (struct device *)reg; 822395Swnj 832422Skre dzaddr->dzcsr = TIE|MSE; 842422Skre dzaddr->dztcr = 1; /* enable any line */ 85*2457Swnj DELAY(100000); 862422Skre dzaddr->dzcsr = CLR; /* reset everything */ 87*2457Swnj if (cvec && cvec != 0x200) 88*2457Swnj cvec -= 4; 89*2457Swnj return (1); 902395Swnj } 912395Swnj 922395Swnj dzslave(ui, reg, slaveno, uban) 932395Swnj register struct uba_dinfo *ui; 942395Swnj caddr_t reg; 952395Swnj { 962395Swnj register struct pdma *pdp = &dzpdma[ui->ui_unit*8]; 972395Swnj register struct tty *tp = &dz_tty[ui->ui_unit*8]; 982395Swnj register int cnt; 992395Swnj caddr_t cp; 1002395Swnj 1012395Swnj for (cnt = 0; cnt < 8; cnt++) { 1022395Swnj pdp->p_addr = (struct device *)reg; 1032395Swnj pdp->p_arg = (int)tp; 1042395Swnj pdp->p_fcn = dzxint; 1052395Swnj pdp++, tp++; 1062395Swnj } 1072395Swnj return (1); 1082395Swnj } 1092395Swnj 11017Sbill /*ARGSUSED*/ 1112395Swnj dzopen(dev, flag) 1122395Swnj dev_t dev; 11317Sbill { 11417Sbill register struct tty *tp; 1152395Swnj register int unit; 11617Sbill extern dzscan(); 11717Sbill 1182395Swnj unit = minor(dev); 1192395Swnj if (unit >= dz_cnt || dzpdma[unit].p_addr == 0) { 12017Sbill u.u_error = ENXIO; 12117Sbill return; 12217Sbill } 12317Sbill if (dz_timer == 0) { 12417Sbill dz_timer++; 12517Sbill timeout(dzscan, (caddr_t)0, 60); 12617Sbill } 1272395Swnj tp = &dz_tty[unit]; 1282395Swnj tp->t_addr = (caddr_t)&dzpdma[unit]; 12917Sbill tp->t_oproc = dzstart; 13017Sbill tp->t_iproc = NULL; 13117Sbill tp->t_state |= WOPEN; 13217Sbill if ((tp->t_state & ISOPEN) == 0) { 13317Sbill ttychars(tp); 13417Sbill tp->t_ospeed = tp->t_ispeed = SSPEED; 13517Sbill tp->t_flags = ODDP|EVENP|ECHO; 13617Sbill /*tp->t_state |= HUPCLS;*/ 1372395Swnj dzparam(unit); 13817Sbill } else if (tp->t_state&XCLUDE && u.u_uid != 0) { 13917Sbill u.u_error = EBUSY; 14017Sbill return; 14117Sbill } 1422395Swnj dzmodem(unit, ON); 143114Sbill (void) spl5(); 14417Sbill while ((tp->t_state & CARR_ON) == 0) { 14517Sbill tp->t_state |= WOPEN; 14617Sbill sleep((caddr_t)&tp->t_rawq, TTIPRI); 14717Sbill } 148114Sbill (void) spl0(); 1492395Swnj (*linesw[tp->t_line].l_open)(dev, tp); 15017Sbill } 15117Sbill 1522395Swnj /*ARGSUSED*/ 1532395Swnj dzclose(dev, flag) 1542395Swnj dev_t dev; 15517Sbill { 15617Sbill register struct tty *tp; 1572395Swnj register int unit; 1582395Swnj int dz; 15917Sbill 1602395Swnj unit = minor(dev); 1612395Swnj dz = unit >> 3; 1622395Swnj tp = &dz_tty[unit]; 16317Sbill (*linesw[tp->t_line].l_close)(tp); 1642197Stoy ((struct pdma *)(tp->t_addr))->p_addr->dzbrk = 1652395Swnj (dz_brk[dz] &= ~(1 << (unit&07))); 16617Sbill if (tp->t_state & HUPCLS) 1672395Swnj dzmodem(unit, OFF); 16817Sbill ttyclose(tp); 16917Sbill } 17017Sbill 1712395Swnj dzread(dev) 1722395Swnj dev_t dev; 17317Sbill { 17417Sbill register struct tty *tp; 17517Sbill 1762395Swnj tp = &dz_tty[minor(dev)]; 17717Sbill (*linesw[tp->t_line].l_read)(tp); 17817Sbill } 17917Sbill 1802395Swnj dzwrite(dev) 1812395Swnj dev_t dev; 18217Sbill { 18317Sbill register struct tty *tp; 18417Sbill 1852395Swnj tp = &dz_tty[minor(dev)]; 18617Sbill (*linesw[tp->t_line].l_write)(tp); 18717Sbill } 18817Sbill 189119Sbill /*ARGSUSED*/ 1902395Swnj dzrint(dz) 1912395Swnj int dz; 19217Sbill { 19317Sbill register struct tty *tp; 19417Sbill register int c; 19517Sbill register struct device *dzaddr; 196119Sbill register struct tty *tp0; 1972395Swnj register int unit; 198140Sbill int s; 19917Sbill 200*2457Swnj if ((dzact & (1<<dz)) == 0) 201*2457Swnj return; 202*2457Swnj unit = dz * 8; 203*2457Swnj dzaddr = dzpdma[unit].p_addr; 204*2457Swnj tp0 = &dz_tty[unit]; 205*2457Swnj while ((c = dzaddr->dzrbuf) < 0) { /* char present */ 206*2457Swnj tp = tp0 + ((c>>8)&07); 207*2457Swnj if (tp >= &dz_tty[dz_cnt]) 20817Sbill continue; 209*2457Swnj if ((tp->t_state & ISOPEN) == 0) { 210*2457Swnj wakeup((caddr_t)&tp->t_rawq); 211*2457Swnj continue; 212*2457Swnj } 213*2457Swnj if (c&FRERROR) 214*2457Swnj /* framing error = break */ 215*2457Swnj if (tp->t_flags & RAW) 216*2457Swnj c = 0; /* null for getty */ 217*2457Swnj else 218*2457Swnj c = tun.t_intrc; 219*2457Swnj if (c&OVERRUN) 220*2457Swnj printf("o"); 221*2457Swnj if (c&PERROR) 222*2457Swnj /* parity error */ 223*2457Swnj if (((tp->t_flags & (EVENP|ODDP)) == EVENP) 224*2457Swnj || ((tp->t_flags & (EVENP|ODDP)) == ODDP)) 22517Sbill continue; 226*2457Swnj if (tp->t_line == NETLDISC) { 227*2457Swnj c &= 0177; 228*2457Swnj BKINPUT(c, tp); 229*2457Swnj } else 230*2457Swnj (*linesw[tp->t_line].l_rint)(c, tp); 23117Sbill } 23217Sbill } 23317Sbill 23417Sbill /*ARGSUSED*/ 23517Sbill dzioctl(dev, cmd, addr, flag) 2362395Swnj dev_t dev; 2372395Swnj caddr_t addr; 23817Sbill { 23917Sbill register struct tty *tp; 2402395Swnj register int unit = minor(dev); 2412395Swnj register int dz = unit >> 3; 24217Sbill 2432395Swnj tp = &dz_tty[unit]; 244114Sbill cmd = (*linesw[tp->t_line].l_ioctl)(tp, cmd, addr); 245114Sbill if (cmd == 0) 246114Sbill return; 2471896Swnj if (ttioctl(tp, cmd, addr, flag)) { 24817Sbill if (cmd==TIOCSETP || cmd==TIOCSETN) 2492395Swnj dzparam(unit); 250170Sbill } else switch(cmd) { 2512395Swnj 252170Sbill case TIOCSBRK: 253882Sbill ((struct pdma *)(tp->t_addr))->p_addr->dzbrk = 2542395Swnj (dz_brk[dz] |= 1 << (unit&07)); 255170Sbill break; 256170Sbill case TIOCCBRK: 257882Sbill ((struct pdma *)(tp->t_addr))->p_addr->dzbrk = 2582395Swnj (dz_brk[dz] &= ~(1 << (unit&07))); 259170Sbill break; 260170Sbill case TIOCSDTR: 2612395Swnj dzmodem(unit, ON); 262170Sbill break; 263170Sbill case TIOCCDTR: 2642395Swnj dzmodem(unit, OFF); 265170Sbill break; 266170Sbill default: 26717Sbill u.u_error = ENOTTY; 268170Sbill } 26917Sbill } 27017Sbill 2712395Swnj dzparam(unit) 2722395Swnj register int unit; 27317Sbill { 27417Sbill register struct tty *tp; 27517Sbill register struct device *dzaddr; 2762395Swnj register int lpr; 27717Sbill 2782395Swnj tp = &dz_tty[unit]; 2792395Swnj dzaddr = dzpdma[unit].p_addr; 28017Sbill dzaddr->dzcsr = DZ_IEN; 2812395Swnj dzact |= (1<<(unit>>3)); 28217Sbill if (tp->t_ispeed == 0) { 2832395Swnj dzmodem(unit, OFF); /* hang up line */ 28417Sbill return; 28517Sbill } 2862395Swnj lpr = (dz_speeds[tp->t_ispeed]<<8) | (unit & 07); 2872296Swnj if ((tp->t_local&LLITOUT) || (tp->t_flags&RAW)) 28817Sbill lpr |= BITS8; 28917Sbill else 29017Sbill lpr |= (BITS7|PENABLE); 29117Sbill if ((tp->t_flags & EVENP) == 0) 29217Sbill lpr |= OPAR; 29317Sbill if (tp->t_ispeed == 3) 29417Sbill lpr |= TWOSB; /* 110 baud: 2 stop bits */ 29517Sbill dzaddr->dzlpr = lpr; 29617Sbill } 29717Sbill 29817Sbill dzxint(tp) 2992395Swnj register struct tty *tp; 30017Sbill { 30117Sbill register struct pdma *dp; 302145Sbill register s; 30317Sbill 304*2457Swnj s = spl5(); 3052395Swnj dp = (struct pdma *)tp->t_addr; 30617Sbill tp->t_state &= ~BUSY; 30717Sbill if (tp->t_state & FLUSH) 30817Sbill tp->t_state &= ~FLUSH; 30917Sbill else 310281Sbill ndflush(&tp->t_outq, dp->p_mem-tp->t_outq.c_cf); 31117Sbill if (tp->t_line) 31217Sbill (*linesw[tp->t_line].l_start)(tp); 31317Sbill else 31417Sbill dzstart(tp); 31517Sbill if (tp->t_outq.c_cc == 0 || (tp->t_state&BUSY)==0) 3162395Swnj dp->p_addr->dztcr &= ~(1 << (minor(tp->t_dev)&07)); 317145Sbill splx(s); 31817Sbill } 31917Sbill 32017Sbill dzstart(tp) 3212395Swnj register struct tty *tp; 32217Sbill { 32317Sbill register struct pdma *dp; 32417Sbill register struct device *dzaddr; 3252395Swnj register int cc; 3262395Swnj int s; 32717Sbill 3282395Swnj dp = (struct pdma *)tp->t_addr; 32917Sbill dzaddr = dp->p_addr; 3302395Swnj s = spl5(); 33117Sbill if (tp->t_state & (TIMEOUT|BUSY|TTSTOP)) 33217Sbill goto out; 333921Sbill if (tp->t_state&ASLEEP && tp->t_outq.c_cc <= TTLOWAT(tp)) { 33417Sbill tp->t_state &= ~ASLEEP; 33517Sbill if (tp->t_chan) 33617Sbill mcstart(tp->t_chan, (caddr_t)&tp->t_outq); 33717Sbill else 33817Sbill wakeup((caddr_t)&tp->t_outq); 33917Sbill } 34017Sbill if (tp->t_outq.c_cc == 0) 34117Sbill goto out; 34217Sbill if (tp->t_flags&RAW) 34317Sbill cc = ndqb(&tp->t_outq, 0); 34417Sbill else { 34517Sbill cc = ndqb(&tp->t_outq, 0200); 34617Sbill if (cc == 0) { 34717Sbill cc = getc(&tp->t_outq); 34817Sbill timeout(ttrstrt, (caddr_t)tp, (cc&0177) + 6); 34917Sbill tp->t_state |= TIMEOUT; 35017Sbill goto out; 35117Sbill } 35217Sbill } 35317Sbill tp->t_state |= BUSY; 35417Sbill dp->p_end = dp->p_mem = tp->t_outq.c_cf; 35517Sbill dp->p_end += cc; 3562395Swnj dzaddr->dztcr |= 1 << (minor(tp->t_dev) & 07); 3572395Swnj out: 3582395Swnj splx(s); 35917Sbill } 36017Sbill 36117Sbill /* 36217Sbill * Stop output on a line. 36317Sbill */ 36417Sbill /*ARGSUSED*/ 36517Sbill dzstop(tp, flag) 3662395Swnj register struct tty *tp; 36717Sbill { 36817Sbill register struct pdma *dp; 36917Sbill register int s; 37017Sbill 3712395Swnj dp = (struct pdma *)tp->t_addr; 372*2457Swnj s = spl5(); 37317Sbill if (tp->t_state & BUSY) { 37417Sbill dp->p_end = dp->p_mem; 3752395Swnj if ((tp->t_state&TTSTOP)==0) 37617Sbill tp->t_state |= FLUSH; 37717Sbill } 37817Sbill splx(s); 37917Sbill } 38017Sbill 3812395Swnj dzmodem(unit, flag) 3822395Swnj register int unit; 38317Sbill { 38417Sbill register struct device *dzaddr; 38517Sbill register char bit; 38617Sbill 3872395Swnj dzaddr = dzpdma[unit].p_addr; 3882395Swnj bit = 1<<(unit&07); 38917Sbill if (flag == OFF) 39017Sbill dzaddr->dzdtr &= ~bit; 39117Sbill else 39217Sbill dzaddr->dzdtr |= bit; 39317Sbill } 39417Sbill 39517Sbill dzscan() 39617Sbill { 39717Sbill register i; 39817Sbill register struct device *dzaddr; 39917Sbill register bit; 40017Sbill register struct tty *tp; 40117Sbill 40217Sbill for (i = 0; i < dz_cnt ; i++) { 40317Sbill dzaddr = dzpdma[i].p_addr; 40417Sbill tp = &dz_tty[i]; 40517Sbill bit = 1<<(i&07); 4062422Skre #ifdef BERT 4072422Skre if (dzaddr->dzmsr & bit || i == 6 || i == 7) { 4082422Skre #else 4092422Skre if (dzaddr->dzmsr & bit) { 4102422Skre #endif 41117Sbill /* carrier present */ 41217Sbill if ((tp->t_state & CARR_ON) == 0) { 41317Sbill wakeup((caddr_t)&tp->t_rawq); 41417Sbill tp->t_state |= CARR_ON; 41517Sbill } 41617Sbill } else { 4172395Swnj if ((tp->t_state&CARR_ON) && (tp->t_local&LNOHANG)==0) { 41817Sbill /* carrier lost */ 419882Sbill if (tp->t_state&ISOPEN) { 420170Sbill gsignal(tp->t_pgrp, SIGHUP); 421205Sbill gsignal(tp->t_pgrp, SIGCONT); 422170Sbill dzaddr->dzdtr &= ~bit; 423871Sbill flushtty(tp, FREAD|FWRITE); 424170Sbill } 425170Sbill tp->t_state &= ~CARR_ON; 42617Sbill } 42717Sbill } 42817Sbill } 42917Sbill timeout(dzscan, (caddr_t)0, 2*HZ); 43017Sbill } 431119Sbill 432119Sbill dztimer() 433119Sbill { 434*2457Swnj int dz; 435119Sbill 436*2457Swnj for (dz = 0; dz < NDZ11; dz++) 437*2457Swnj dzrint(dz); 438119Sbill } 439281Sbill 440281Sbill /* 441281Sbill * Reset state of driver if UBA reset was necessary. 442301Sbill * Reset parameters and restart transmission on open lines. 443281Sbill */ 4442395Swnj dzreset(uban) 4452422Skre int uban; 446281Sbill { 4472395Swnj register int unit; 448281Sbill register struct tty *tp; 4492422Skre register struct uba_dinfo *ui; 4502422Skre int any = 0; 451281Sbill 4522395Swnj for (unit = 0; unit < NDZ; unit++) { 4532422Skre ui = dzinfo[unit >> 3]; 4542422Skre if (ui == 0 || ui->ui_ubanum != uban || ui->ui_alive == 0) 4552422Skre continue; 4562422Skre if (any == 0) { 4572422Skre printf(" dz"); 4582422Skre any++; 4592422Skre } 4602395Swnj tp = &dz_tty[unit]; 461281Sbill if (tp->t_state & (ISOPEN|WOPEN)) { 4622395Swnj dzparam(unit); 4632395Swnj dzmodem(unit, ON); 464301Sbill tp->t_state &= ~BUSY; 465301Sbill dzstart(tp); 466281Sbill } 467281Sbill } 468281Sbill dztimer(); 469281Sbill } 4701562Sbill #endif 471