1*2606Swnj /* dz.c 4.15 02/21/81 */ 217Sbill 31935Swnj #include "dz.h" 41562Sbill #if NDZ11 > 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 */ 30*2606Swnj int dzprobe(), dzattach(), dzrint(); 312395Swnj struct uba_dinfo *dzinfo[NDZ11]; 322395Swnj u_short dzstd[] = { 0 }; 332395Swnj struct uba_driver dzdriver = 34*2606Swnj { dzprobe, 0, dzattach, 0, dzstd, "dz", dzinfo }; 352395Swnj 362457Swnj #define NDZ (NDZ11*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(); 6817Sbill struct tty dz_tty[NDZ]; 6917Sbill int dz_cnt = { NDZ }; 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 */ 852469Swnj char dz_brk[NDZ11]; 862567Swnj char dzsoftCAR[NDZ11]; 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 */ 972395Swnj struct pdma dzpdma[NDZ]; 982469Swnj 992395Swnj char dz_speeds[] = 1002395Swnj { 0,020,021,022,023,024,0,025,026,027,030,032,034,036,0,0 }; 10117Sbill 102*2606Swnj dzprobe(reg) 1032395Swnj caddr_t reg; 1042395Swnj { 1052457Swnj register int br, cvec; 1062457Swnj register struct device *dzaddr = (struct device *)reg; 1072395Swnj 108*2606Swnj #ifdef lint 109*2606Swnj br = 0; br = cvec; cvec = br; 110*2606Swnj #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 120*2606Swnj 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]; 125*2606Swnj register int cntr; 1262395Swnj 127*2606Swnj for (cntr = 0; cntr < 8; cntr++) { 128*2606Swnj pdp->p_addr = (struct device *)ui->ui_addr; 1292395Swnj pdp->p_arg = (int)tp; 1302395Swnj pdp->p_fcn = dzxint; 1312395Swnj pdp++, tp++; 1322395Swnj } 1332567Swnj dzsoftCAR[ui->ui_unit] = ui->ui_flags; 1342395Swnj return (1); 1352395Swnj } 1362395Swnj 13717Sbill /*ARGSUSED*/ 1382395Swnj dzopen(dev, flag) 1392395Swnj dev_t dev; 14017Sbill { 14117Sbill register struct tty *tp; 1422395Swnj register int unit; 14317Sbill extern dzscan(); 14417Sbill 1452395Swnj unit = minor(dev); 1462395Swnj if (unit >= dz_cnt || dzpdma[unit].p_addr == 0) { 14717Sbill u.u_error = ENXIO; 14817Sbill return; 14917Sbill } 15017Sbill if (dz_timer == 0) { 15117Sbill dz_timer++; 1522469Swnj timeout(dzscan, (caddr_t)0, HZ); 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; 42817Sbill tp = &dz_tty[i]; 42917Sbill bit = 1<<(i&07); 430*2606Swnj if ((dzsoftCAR[i>>3]&bit) || (dzaddr->dzmsr&bit)) { 43117Sbill /* carrier present */ 43217Sbill if ((tp->t_state & CARR_ON) == 0) { 43317Sbill wakeup((caddr_t)&tp->t_rawq); 43417Sbill tp->t_state |= CARR_ON; 43517Sbill } 43617Sbill } else { 4372469Swnj if ((tp->t_state&CARR_ON) && 4382469Swnj (tp->t_local&LNOHANG)==0) { 43917Sbill /* carrier lost */ 440882Sbill if (tp->t_state&ISOPEN) { 441170Sbill gsignal(tp->t_pgrp, SIGHUP); 442205Sbill gsignal(tp->t_pgrp, SIGCONT); 443170Sbill dzaddr->dzdtr &= ~bit; 444871Sbill flushtty(tp, FREAD|FWRITE); 445170Sbill } 446170Sbill tp->t_state &= ~CARR_ON; 44717Sbill } 44817Sbill } 44917Sbill } 45017Sbill timeout(dzscan, (caddr_t)0, 2*HZ); 45117Sbill } 452119Sbill 453119Sbill dztimer() 454119Sbill { 4552457Swnj int dz; 456119Sbill 4572457Swnj for (dz = 0; dz < NDZ11; dz++) 4582457Swnj dzrint(dz); 459119Sbill } 460281Sbill 461281Sbill /* 462281Sbill * Reset state of driver if UBA reset was necessary. 463301Sbill * Reset parameters and restart transmission on open lines. 464281Sbill */ 4652395Swnj dzreset(uban) 4662422Skre int uban; 467281Sbill { 4682395Swnj register int unit; 469281Sbill register struct tty *tp; 4702422Skre register struct uba_dinfo *ui; 4712422Skre int any = 0; 472281Sbill 4732395Swnj for (unit = 0; unit < NDZ; unit++) { 4742422Skre ui = dzinfo[unit >> 3]; 4752422Skre if (ui == 0 || ui->ui_ubanum != uban || ui->ui_alive == 0) 4762422Skre continue; 4772422Skre if (any == 0) { 4782422Skre printf(" dz"); 4792422Skre any++; 4802422Skre } 4812395Swnj tp = &dz_tty[unit]; 482281Sbill if (tp->t_state & (ISOPEN|WOPEN)) { 4832395Swnj dzparam(unit); 4842469Swnj dzmodem(unit, DZ_ON); 485301Sbill tp->t_state &= ~BUSY; 486301Sbill dzstart(tp); 487281Sbill } 488281Sbill } 489281Sbill dztimer(); 490281Sbill } 4911562Sbill #endif 492