1*2645Swnj /* dz.c 4.17 02/23/81 */ 217Sbill 31935Swnj #include "dz.h" 4*2645Swnj #if NDZ > 0 52457Swnj #define DELAY(i) { register int j = i; while (--j > 0); } 617Sbill /* 717Sbill * DZ-11 Driver 82469Swnj * 92469Swnj * This driver mimics dh.c; see it for explanation of common code. 1017Sbill */ 1117Sbill #include "../h/param.h" 1217Sbill #include "../h/systm.h" 1317Sbill #include "../h/tty.h" 1417Sbill #include "../h/dir.h" 1517Sbill #include "../h/user.h" 1617Sbill #include "../h/map.h" 1717Sbill #include "../h/pte.h" 182395Swnj #include "../h/buf.h" 192567Swnj #include "../h/vm.h" 2017Sbill #include "../h/uba.h" 2117Sbill #include "../h/conf.h" 2217Sbill #include "../h/pdma.h" 23114Sbill #include "../h/bk.h" 24871Sbill #include "../h/file.h" 251786Sbill #include "../h/mx.h" 26145Sbill 272469Swnj /* 282469Swnj * Driver information for auto-configuration stuff. 292469Swnj */ 302606Swnj int dzprobe(), dzattach(), dzrint(); 31*2645Swnj struct uba_dinfo *dzinfo[NDZ]; 322395Swnj u_short dzstd[] = { 0 }; 332395Swnj struct uba_driver dzdriver = 342606Swnj { dzprobe, 0, dzattach, 0, dzstd, "dz", dzinfo }; 352395Swnj 36*2645Swnj #define NDZLINE (NDZ*8) 3717Sbill 382469Swnj /* 392469Swnj * Registers and bits 402469Swnj */ 412469Swnj 422469Swnj /* Bits in dzlpr */ 432457Swnj #define BITS7 020 442457Swnj #define BITS8 030 452457Swnj #define TWOSB 040 462457Swnj #define PENABLE 0100 472457Swnj #define OPAR 0200 4817Sbill 492469Swnj /* Bits in dzrbuf */ 502469Swnj #define DZ_PE 010000 512469Swnj #define DZ_FE 020000 522469Swnj #define DZ_DO 040000 532469Swnj 542469Swnj /* Bits in dzcsr */ 552469Swnj #define DZ_CLR 020 /* Reset dz */ 562469Swnj #define DZ_MSE 040 /* Master Scan Enable */ 572469Swnj #define DZ_RIE 0100 /* Receiver Interrupt Enable */ 582469Swnj #define DZ_SAE 010000 /* Silo Alarm Enable */ 592469Swnj #define DZ_TIE 040000 /* Transmit Interrupt Enable */ 602469Swnj #define DZ_IEN (DZ_MSE+DZ_RIE+DZ_TIE+DZ_SAE) 612469Swnj 622469Swnj /* Flags for modem-control */ 632469Swnj #define DZ_ON 1 642469Swnj #define DZ_OFF 0 6517Sbill 662469Swnj int dzstart(), dzxint(), dzdma(); 67114Sbill int ttrstrt(); 68*2645Swnj struct tty dz_tty[NDZLINE]; 69*2645Swnj int dz_cnt = { NDZLINE }; 70119Sbill int dzact; 7117Sbill 7217Sbill struct device { 732469Swnj short dzcsr; /* control-status register */ 742469Swnj short dzrbuf; /* receiver buffer */ 752469Swnj #define dzlpr dzrbuf /* line parameter reg is write of dzrbuf */ 762469Swnj char dztcr; /* transmit control register */ 772469Swnj char dzdtr; /* data terminal ready */ 782469Swnj char dztbuf; /* transmit buffer */ 792469Swnj char dzbrk; /* break control */ 802469Swnj #define dzmsr dzbrk /* modem status register */ 8117Sbill }; 822469Swnj /* 832469Swnj * Software copy of dzbrk since it isn't readable 842469Swnj */ 85*2645Swnj char dz_brk[NDZ]; 86*2645Swnj char dzsoftCAR[NDZ]; 8717Sbill 882469Swnj /* 892469Swnj * The dz doesn't interrupt on carrier transitions, so 902469Swnj * we have to use a timer to watch it. 912469Swnj */ 922469Swnj char dz_timer; /* timer started? */ 932469Swnj 942469Swnj /* 952469Swnj * Pdma structures for fast output code 962469Swnj */ 97*2645Swnj struct pdma dzpdma[NDZLINE]; 982469Swnj 992395Swnj char dz_speeds[] = 1002395Swnj { 0,020,021,022,023,024,0,025,026,027,030,032,034,036,0,0 }; 10117Sbill 1022606Swnj dzprobe(reg) 1032395Swnj caddr_t reg; 1042395Swnj { 1052457Swnj register int br, cvec; 1062457Swnj register struct device *dzaddr = (struct device *)reg; 1072395Swnj 1082606Swnj #ifdef lint 1092606Swnj br = 0; br = cvec; cvec = br; 1102606Swnj #endif 1112469Swnj dzaddr->dzcsr = DZ_TIE|DZ_MSE; 1122422Skre dzaddr->dztcr = 1; /* enable any line */ 1132457Swnj DELAY(100000); 1142469Swnj dzaddr->dzcsr = DZ_CLR; /* reset everything */ 1152457Swnj if (cvec && cvec != 0x200) 1162457Swnj cvec -= 4; 1172457Swnj return (1); 1182395Swnj } 1192395Swnj 1202606Swnj dzattach(ui) 1212395Swnj register struct uba_dinfo *ui; 1222395Swnj { 1232395Swnj register struct pdma *pdp = &dzpdma[ui->ui_unit*8]; 1242395Swnj register struct tty *tp = &dz_tty[ui->ui_unit*8]; 1252606Swnj register int cntr; 126*2645Swnj extern dzscan(); 1272395Swnj 1282606Swnj for (cntr = 0; cntr < 8; cntr++) { 1292606Swnj pdp->p_addr = (struct device *)ui->ui_addr; 1302395Swnj pdp->p_arg = (int)tp; 1312395Swnj pdp->p_fcn = dzxint; 1322395Swnj pdp++, tp++; 1332395Swnj } 1342567Swnj dzsoftCAR[ui->ui_unit] = ui->ui_flags; 1352627Swnj if (dz_timer == 0) { 1362627Swnj dz_timer++; 1372627Swnj timeout(dzscan, (caddr_t)0, HZ); 1382627Swnj } 1392395Swnj return (1); 1402395Swnj } 1412395Swnj 14217Sbill /*ARGSUSED*/ 1432395Swnj dzopen(dev, flag) 1442395Swnj dev_t dev; 14517Sbill { 14617Sbill register struct tty *tp; 1472395Swnj register int unit; 14817Sbill 1492395Swnj unit = minor(dev); 1502395Swnj if (unit >= dz_cnt || dzpdma[unit].p_addr == 0) { 15117Sbill u.u_error = ENXIO; 15217Sbill return; 15317Sbill } 1542395Swnj tp = &dz_tty[unit]; 1552395Swnj tp->t_addr = (caddr_t)&dzpdma[unit]; 15617Sbill tp->t_oproc = dzstart; 15717Sbill tp->t_iproc = NULL; 15817Sbill tp->t_state |= WOPEN; 15917Sbill if ((tp->t_state & ISOPEN) == 0) { 16017Sbill ttychars(tp); 1612469Swnj tp->t_ospeed = tp->t_ispeed = B300; 16217Sbill tp->t_flags = ODDP|EVENP|ECHO; 1632469Swnj /* tp->t_state |= HUPCLS; */ 1642395Swnj dzparam(unit); 16517Sbill } else if (tp->t_state&XCLUDE && u.u_uid != 0) { 16617Sbill u.u_error = EBUSY; 16717Sbill return; 16817Sbill } 1692469Swnj dzmodem(unit, DZ_ON); 170114Sbill (void) spl5(); 17117Sbill while ((tp->t_state & CARR_ON) == 0) { 17217Sbill tp->t_state |= WOPEN; 17317Sbill sleep((caddr_t)&tp->t_rawq, TTIPRI); 17417Sbill } 175114Sbill (void) spl0(); 1762395Swnj (*linesw[tp->t_line].l_open)(dev, tp); 17717Sbill } 17817Sbill 1792395Swnj /*ARGSUSED*/ 1802395Swnj dzclose(dev, flag) 1812395Swnj dev_t dev; 18217Sbill { 18317Sbill register struct tty *tp; 1842395Swnj register int unit; 1852395Swnj int dz; 18617Sbill 1872395Swnj unit = minor(dev); 1882395Swnj dz = unit >> 3; 1892395Swnj tp = &dz_tty[unit]; 19017Sbill (*linesw[tp->t_line].l_close)(tp); 1912197Stoy ((struct pdma *)(tp->t_addr))->p_addr->dzbrk = 1922395Swnj (dz_brk[dz] &= ~(1 << (unit&07))); 19317Sbill if (tp->t_state & HUPCLS) 1942469Swnj dzmodem(unit, DZ_OFF); 19517Sbill ttyclose(tp); 19617Sbill } 19717Sbill 1982395Swnj dzread(dev) 1992395Swnj dev_t dev; 20017Sbill { 20117Sbill register struct tty *tp; 20217Sbill 2032395Swnj tp = &dz_tty[minor(dev)]; 20417Sbill (*linesw[tp->t_line].l_read)(tp); 20517Sbill } 20617Sbill 2072395Swnj dzwrite(dev) 2082395Swnj dev_t dev; 20917Sbill { 21017Sbill register struct tty *tp; 21117Sbill 2122395Swnj tp = &dz_tty[minor(dev)]; 21317Sbill (*linesw[tp->t_line].l_write)(tp); 21417Sbill } 21517Sbill 216119Sbill /*ARGSUSED*/ 2172395Swnj dzrint(dz) 2182395Swnj int dz; 21917Sbill { 22017Sbill register struct tty *tp; 22117Sbill register int c; 22217Sbill register struct device *dzaddr; 223119Sbill register struct tty *tp0; 2242395Swnj register int unit; 22517Sbill 2262457Swnj if ((dzact & (1<<dz)) == 0) 2272457Swnj return; 2282457Swnj unit = dz * 8; 2292457Swnj dzaddr = dzpdma[unit].p_addr; 2302457Swnj tp0 = &dz_tty[unit]; 2312457Swnj while ((c = dzaddr->dzrbuf) < 0) { /* char present */ 2322457Swnj tp = tp0 + ((c>>8)&07); 2332457Swnj if (tp >= &dz_tty[dz_cnt]) 23417Sbill continue; 2352457Swnj if ((tp->t_state & ISOPEN) == 0) { 2362457Swnj wakeup((caddr_t)&tp->t_rawq); 2372457Swnj continue; 2382457Swnj } 2392469Swnj if (c&DZ_FE) 2402457Swnj if (tp->t_flags & RAW) 2412469Swnj c = 0; 2422457Swnj else 2432457Swnj c = tun.t_intrc; 2442469Swnj if (c&DZ_DO) 2452457Swnj printf("o"); 2462469Swnj if (c&DZ_PE) 2472457Swnj if (((tp->t_flags & (EVENP|ODDP)) == EVENP) 2482457Swnj || ((tp->t_flags & (EVENP|ODDP)) == ODDP)) 24917Sbill continue; 2502457Swnj if (tp->t_line == NETLDISC) { 2512457Swnj c &= 0177; 2522457Swnj BKINPUT(c, tp); 2532457Swnj } else 2542457Swnj (*linesw[tp->t_line].l_rint)(c, tp); 25517Sbill } 25617Sbill } 25717Sbill 25817Sbill /*ARGSUSED*/ 25917Sbill dzioctl(dev, cmd, addr, flag) 2602395Swnj dev_t dev; 2612395Swnj caddr_t addr; 26217Sbill { 26317Sbill register struct tty *tp; 2642395Swnj register int unit = minor(dev); 2652395Swnj register int dz = unit >> 3; 26617Sbill 2672395Swnj tp = &dz_tty[unit]; 268114Sbill cmd = (*linesw[tp->t_line].l_ioctl)(tp, cmd, addr); 269114Sbill if (cmd == 0) 270114Sbill return; 2711896Swnj if (ttioctl(tp, cmd, addr, flag)) { 27217Sbill if (cmd==TIOCSETP || cmd==TIOCSETN) 2732395Swnj dzparam(unit); 274170Sbill } else switch(cmd) { 2752395Swnj 276170Sbill case TIOCSBRK: 277882Sbill ((struct pdma *)(tp->t_addr))->p_addr->dzbrk = 2782395Swnj (dz_brk[dz] |= 1 << (unit&07)); 279170Sbill break; 280170Sbill case TIOCCBRK: 281882Sbill ((struct pdma *)(tp->t_addr))->p_addr->dzbrk = 2822395Swnj (dz_brk[dz] &= ~(1 << (unit&07))); 283170Sbill break; 284170Sbill case TIOCSDTR: 2852469Swnj dzmodem(unit, DZ_ON); 286170Sbill break; 287170Sbill case TIOCCDTR: 2882469Swnj dzmodem(unit, DZ_OFF); 289170Sbill break; 290170Sbill default: 29117Sbill u.u_error = ENOTTY; 292170Sbill } 29317Sbill } 29417Sbill 2952395Swnj dzparam(unit) 2962395Swnj register int unit; 29717Sbill { 29817Sbill register struct tty *tp; 29917Sbill register struct device *dzaddr; 3002395Swnj register int lpr; 30117Sbill 3022395Swnj tp = &dz_tty[unit]; 3032395Swnj dzaddr = dzpdma[unit].p_addr; 30417Sbill dzaddr->dzcsr = DZ_IEN; 3052395Swnj dzact |= (1<<(unit>>3)); 30617Sbill if (tp->t_ispeed == 0) { 3072469Swnj dzmodem(unit, DZ_OFF); /* hang up line */ 30817Sbill return; 30917Sbill } 3102395Swnj lpr = (dz_speeds[tp->t_ispeed]<<8) | (unit & 07); 3112296Swnj if ((tp->t_local&LLITOUT) || (tp->t_flags&RAW)) 31217Sbill lpr |= BITS8; 31317Sbill else 31417Sbill lpr |= (BITS7|PENABLE); 31517Sbill if ((tp->t_flags & EVENP) == 0) 31617Sbill lpr |= OPAR; 3172469Swnj if (tp->t_ispeed == B110) 3182469Swnj lpr |= TWOSB; 31917Sbill dzaddr->dzlpr = lpr; 32017Sbill } 32117Sbill 32217Sbill dzxint(tp) 3232395Swnj register struct tty *tp; 32417Sbill { 32517Sbill register struct pdma *dp; 326145Sbill register s; 32717Sbill 3282469Swnj s = spl5(); /* block pdma interrupts */ 3292395Swnj dp = (struct pdma *)tp->t_addr; 33017Sbill tp->t_state &= ~BUSY; 33117Sbill if (tp->t_state & FLUSH) 33217Sbill tp->t_state &= ~FLUSH; 33317Sbill else 334281Sbill ndflush(&tp->t_outq, dp->p_mem-tp->t_outq.c_cf); 33517Sbill if (tp->t_line) 33617Sbill (*linesw[tp->t_line].l_start)(tp); 33717Sbill else 33817Sbill dzstart(tp); 33917Sbill if (tp->t_outq.c_cc == 0 || (tp->t_state&BUSY)==0) 3402395Swnj dp->p_addr->dztcr &= ~(1 << (minor(tp->t_dev)&07)); 341145Sbill splx(s); 34217Sbill } 34317Sbill 34417Sbill dzstart(tp) 3452395Swnj register struct tty *tp; 34617Sbill { 34717Sbill register struct pdma *dp; 34817Sbill register struct device *dzaddr; 3492395Swnj register int cc; 3502395Swnj int s; 35117Sbill 3522395Swnj dp = (struct pdma *)tp->t_addr; 35317Sbill dzaddr = dp->p_addr; 3542395Swnj s = spl5(); 35517Sbill if (tp->t_state & (TIMEOUT|BUSY|TTSTOP)) 35617Sbill goto out; 357921Sbill if (tp->t_state&ASLEEP && tp->t_outq.c_cc <= TTLOWAT(tp)) { 35817Sbill tp->t_state &= ~ASLEEP; 35917Sbill if (tp->t_chan) 36017Sbill mcstart(tp->t_chan, (caddr_t)&tp->t_outq); 36117Sbill else 36217Sbill wakeup((caddr_t)&tp->t_outq); 36317Sbill } 36417Sbill if (tp->t_outq.c_cc == 0) 36517Sbill goto out; 36617Sbill if (tp->t_flags&RAW) 36717Sbill cc = ndqb(&tp->t_outq, 0); 36817Sbill else { 36917Sbill cc = ndqb(&tp->t_outq, 0200); 37017Sbill if (cc == 0) { 37117Sbill cc = getc(&tp->t_outq); 3722469Swnj timeout(ttrstrt, (caddr_t)tp, (cc&0x7f) + 6); 37317Sbill tp->t_state |= TIMEOUT; 37417Sbill goto out; 37517Sbill } 37617Sbill } 37717Sbill tp->t_state |= BUSY; 37817Sbill dp->p_end = dp->p_mem = tp->t_outq.c_cf; 37917Sbill dp->p_end += cc; 3802469Swnj dzaddr->dztcr |= 1 << (minor(tp->t_dev) & 07); /* force intr */ 3812395Swnj out: 3822395Swnj splx(s); 38317Sbill } 38417Sbill 38517Sbill /* 38617Sbill * Stop output on a line. 38717Sbill */ 38817Sbill /*ARGSUSED*/ 38917Sbill dzstop(tp, flag) 3902395Swnj register struct tty *tp; 39117Sbill { 39217Sbill register struct pdma *dp; 39317Sbill register int s; 39417Sbill 3952395Swnj dp = (struct pdma *)tp->t_addr; 3962457Swnj s = spl5(); 39717Sbill if (tp->t_state & BUSY) { 39817Sbill dp->p_end = dp->p_mem; 3992395Swnj if ((tp->t_state&TTSTOP)==0) 40017Sbill tp->t_state |= FLUSH; 40117Sbill } 40217Sbill splx(s); 40317Sbill } 40417Sbill 4052395Swnj dzmodem(unit, flag) 4062395Swnj register int unit; 40717Sbill { 40817Sbill register struct device *dzaddr; 40917Sbill register char bit; 41017Sbill 4112395Swnj dzaddr = dzpdma[unit].p_addr; 4122395Swnj bit = 1<<(unit&07); 4132469Swnj if (flag == DZ_OFF) 41417Sbill dzaddr->dzdtr &= ~bit; 41517Sbill else 41617Sbill dzaddr->dzdtr |= bit; 41717Sbill } 41817Sbill 41917Sbill dzscan() 42017Sbill { 42117Sbill register i; 42217Sbill register struct device *dzaddr; 42317Sbill register bit; 42417Sbill register struct tty *tp; 42517Sbill 42617Sbill for (i = 0; i < dz_cnt ; i++) { 42717Sbill dzaddr = dzpdma[i].p_addr; 4282627Swnj if (dzaddr == 0) 4292627Swnj continue; 43017Sbill tp = &dz_tty[i]; 43117Sbill bit = 1<<(i&07); 4322606Swnj if ((dzsoftCAR[i>>3]&bit) || (dzaddr->dzmsr&bit)) { 43317Sbill /* carrier present */ 43417Sbill if ((tp->t_state & CARR_ON) == 0) { 43517Sbill wakeup((caddr_t)&tp->t_rawq); 43617Sbill tp->t_state |= CARR_ON; 43717Sbill } 43817Sbill } else { 4392469Swnj if ((tp->t_state&CARR_ON) && 4402469Swnj (tp->t_local&LNOHANG)==0) { 44117Sbill /* carrier lost */ 442882Sbill if (tp->t_state&ISOPEN) { 443170Sbill gsignal(tp->t_pgrp, SIGHUP); 444205Sbill gsignal(tp->t_pgrp, SIGCONT); 445170Sbill dzaddr->dzdtr &= ~bit; 446871Sbill flushtty(tp, FREAD|FWRITE); 447170Sbill } 448170Sbill tp->t_state &= ~CARR_ON; 44917Sbill } 45017Sbill } 45117Sbill } 45217Sbill timeout(dzscan, (caddr_t)0, 2*HZ); 45317Sbill } 454119Sbill 455119Sbill dztimer() 456119Sbill { 4572457Swnj int dz; 458119Sbill 459*2645Swnj for (dz = 0; dz < NDZ; dz++) 4602457Swnj dzrint(dz); 461119Sbill } 462281Sbill 463281Sbill /* 464281Sbill * Reset state of driver if UBA reset was necessary. 465301Sbill * Reset parameters and restart transmission on open lines. 466281Sbill */ 4672395Swnj dzreset(uban) 4682422Skre int uban; 469281Sbill { 4702395Swnj register int unit; 471281Sbill register struct tty *tp; 4722422Skre register struct uba_dinfo *ui; 4732422Skre int any = 0; 474281Sbill 475*2645Swnj for (unit = 0; unit < NDZLINE; unit++) { 4762422Skre ui = dzinfo[unit >> 3]; 4772422Skre if (ui == 0 || ui->ui_ubanum != uban || ui->ui_alive == 0) 4782422Skre continue; 4792422Skre if (any == 0) { 4802422Skre printf(" dz"); 4812422Skre any++; 4822422Skre } 4832395Swnj tp = &dz_tty[unit]; 484281Sbill if (tp->t_state & (ISOPEN|WOPEN)) { 4852395Swnj dzparam(unit); 4862469Swnj dzmodem(unit, DZ_ON); 487301Sbill tp->t_state &= ~BUSY; 488301Sbill dzstart(tp); 489281Sbill } 490281Sbill } 491281Sbill dztimer(); 492281Sbill } 4931562Sbill #endif 494