1*2923Swnj /* dz.c 4.20 03/06/81 */ 217Sbill 31935Swnj #include "dz.h" 42645Swnj #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 */ 112731Swnj #include "bk.h" 1217Sbill #include "../h/param.h" 1317Sbill #include "../h/systm.h" 1417Sbill #include "../h/tty.h" 1517Sbill #include "../h/dir.h" 1617Sbill #include "../h/user.h" 1717Sbill #include "../h/map.h" 1817Sbill #include "../h/pte.h" 192395Swnj #include "../h/buf.h" 202567Swnj #include "../h/vm.h" 2117Sbill #include "../h/uba.h" 2217Sbill #include "../h/conf.h" 2317Sbill #include "../h/pdma.h" 24114Sbill #include "../h/bk.h" 25871Sbill #include "../h/file.h" 261786Sbill #include "../h/mx.h" 27145Sbill 282469Swnj /* 292469Swnj * Driver information for auto-configuration stuff. 302469Swnj */ 312606Swnj int dzprobe(), dzattach(), dzrint(); 322645Swnj struct uba_dinfo *dzinfo[NDZ]; 332395Swnj u_short dzstd[] = { 0 }; 342395Swnj struct uba_driver dzdriver = 352606Swnj { dzprobe, 0, dzattach, 0, dzstd, "dz", dzinfo }; 362395Swnj 372645Swnj #define NDZLINE (NDZ*8) 3817Sbill 392469Swnj /* 402469Swnj * Registers and bits 412469Swnj */ 422469Swnj 432469Swnj /* Bits in dzlpr */ 442457Swnj #define BITS7 020 452457Swnj #define BITS8 030 462457Swnj #define TWOSB 040 472457Swnj #define PENABLE 0100 482457Swnj #define OPAR 0200 4917Sbill 502469Swnj /* Bits in dzrbuf */ 512469Swnj #define DZ_PE 010000 522469Swnj #define DZ_FE 020000 532469Swnj #define DZ_DO 040000 542469Swnj 552469Swnj /* Bits in dzcsr */ 562469Swnj #define DZ_CLR 020 /* Reset dz */ 572469Swnj #define DZ_MSE 040 /* Master Scan Enable */ 582469Swnj #define DZ_RIE 0100 /* Receiver Interrupt Enable */ 592469Swnj #define DZ_SAE 010000 /* Silo Alarm Enable */ 602469Swnj #define DZ_TIE 040000 /* Transmit Interrupt Enable */ 612469Swnj #define DZ_IEN (DZ_MSE+DZ_RIE+DZ_TIE+DZ_SAE) 622469Swnj 632469Swnj /* Flags for modem-control */ 642469Swnj #define DZ_ON 1 652469Swnj #define DZ_OFF 0 6617Sbill 672469Swnj int dzstart(), dzxint(), dzdma(); 68114Sbill int ttrstrt(); 692645Swnj struct tty dz_tty[NDZLINE]; 702645Swnj int dz_cnt = { NDZLINE }; 71119Sbill int dzact; 7217Sbill 7317Sbill struct device { 742469Swnj short dzcsr; /* control-status register */ 752469Swnj short dzrbuf; /* receiver buffer */ 762469Swnj #define dzlpr dzrbuf /* line parameter reg is write of dzrbuf */ 772469Swnj char dztcr; /* transmit control register */ 782469Swnj char dzdtr; /* data terminal ready */ 792469Swnj char dztbuf; /* transmit buffer */ 802469Swnj char dzbrk; /* break control */ 812469Swnj #define dzmsr dzbrk /* modem status register */ 8217Sbill }; 832469Swnj /* 842469Swnj * Software copy of dzbrk since it isn't readable 852469Swnj */ 862645Swnj char dz_brk[NDZ]; 872645Swnj char dzsoftCAR[NDZ]; 8817Sbill 892469Swnj /* 902469Swnj * The dz doesn't interrupt on carrier transitions, so 912469Swnj * we have to use a timer to watch it. 922469Swnj */ 932469Swnj char dz_timer; /* timer started? */ 942469Swnj 952469Swnj /* 962469Swnj * Pdma structures for fast output code 972469Swnj */ 982645Swnj struct pdma dzpdma[NDZLINE]; 992469Swnj 1002395Swnj char dz_speeds[] = 1012395Swnj { 0,020,021,022,023,024,0,025,026,027,030,032,034,036,0,0 }; 10217Sbill 1032606Swnj dzprobe(reg) 1042395Swnj caddr_t reg; 1052395Swnj { 1062457Swnj register int br, cvec; 1072457Swnj register struct device *dzaddr = (struct device *)reg; 1082395Swnj 1092606Swnj #ifdef lint 1102606Swnj br = 0; br = cvec; cvec = br; 1112606Swnj #endif 1122469Swnj dzaddr->dzcsr = DZ_TIE|DZ_MSE; 1132422Skre dzaddr->dztcr = 1; /* enable any line */ 1142457Swnj DELAY(100000); 1152469Swnj dzaddr->dzcsr = DZ_CLR; /* reset everything */ 1162457Swnj if (cvec && cvec != 0x200) 1172457Swnj cvec -= 4; 1182457Swnj return (1); 1192395Swnj } 1202395Swnj 1212606Swnj dzattach(ui) 1222395Swnj register struct uba_dinfo *ui; 1232395Swnj { 1242395Swnj register struct pdma *pdp = &dzpdma[ui->ui_unit*8]; 1252395Swnj register struct tty *tp = &dz_tty[ui->ui_unit*8]; 1262606Swnj register int cntr; 1272645Swnj extern dzscan(); 1282395Swnj 1292606Swnj for (cntr = 0; cntr < 8; cntr++) { 1302606Swnj pdp->p_addr = (struct device *)ui->ui_addr; 1312395Swnj pdp->p_arg = (int)tp; 1322395Swnj pdp->p_fcn = dzxint; 1332395Swnj pdp++, tp++; 1342395Swnj } 1352567Swnj dzsoftCAR[ui->ui_unit] = ui->ui_flags; 1362627Swnj if (dz_timer == 0) { 1372627Swnj dz_timer++; 1382756Swnj timeout(dzscan, (caddr_t)0, hz); 1392627Swnj } 1402395Swnj return (1); 1412395Swnj } 1422395Swnj 14317Sbill /*ARGSUSED*/ 1442395Swnj dzopen(dev, flag) 1452395Swnj dev_t dev; 14617Sbill { 14717Sbill register struct tty *tp; 1482395Swnj register int unit; 14917Sbill 1502395Swnj unit = minor(dev); 1512395Swnj if (unit >= dz_cnt || dzpdma[unit].p_addr == 0) { 15217Sbill u.u_error = ENXIO; 15317Sbill return; 15417Sbill } 1552395Swnj tp = &dz_tty[unit]; 1562395Swnj tp->t_addr = (caddr_t)&dzpdma[unit]; 15717Sbill tp->t_oproc = dzstart; 15817Sbill tp->t_iproc = NULL; 15917Sbill tp->t_state |= WOPEN; 16017Sbill if ((tp->t_state & ISOPEN) == 0) { 16117Sbill ttychars(tp); 1622469Swnj tp->t_ospeed = tp->t_ispeed = B300; 16317Sbill tp->t_flags = ODDP|EVENP|ECHO; 1642469Swnj /* tp->t_state |= HUPCLS; */ 1652395Swnj dzparam(unit); 16617Sbill } else if (tp->t_state&XCLUDE && u.u_uid != 0) { 16717Sbill u.u_error = EBUSY; 16817Sbill return; 16917Sbill } 1702469Swnj dzmodem(unit, DZ_ON); 171114Sbill (void) spl5(); 17217Sbill while ((tp->t_state & CARR_ON) == 0) { 17317Sbill tp->t_state |= WOPEN; 17417Sbill sleep((caddr_t)&tp->t_rawq, TTIPRI); 17517Sbill } 176114Sbill (void) spl0(); 1772395Swnj (*linesw[tp->t_line].l_open)(dev, tp); 17817Sbill } 17917Sbill 1802395Swnj /*ARGSUSED*/ 1812395Swnj dzclose(dev, flag) 1822395Swnj dev_t dev; 18317Sbill { 18417Sbill register struct tty *tp; 1852395Swnj register int unit; 1862395Swnj int dz; 18717Sbill 1882395Swnj unit = minor(dev); 1892395Swnj dz = unit >> 3; 1902395Swnj tp = &dz_tty[unit]; 19117Sbill (*linesw[tp->t_line].l_close)(tp); 1922197Stoy ((struct pdma *)(tp->t_addr))->p_addr->dzbrk = 1932395Swnj (dz_brk[dz] &= ~(1 << (unit&07))); 19417Sbill if (tp->t_state & HUPCLS) 1952469Swnj dzmodem(unit, DZ_OFF); 19617Sbill ttyclose(tp); 19717Sbill } 19817Sbill 1992395Swnj dzread(dev) 2002395Swnj dev_t dev; 20117Sbill { 20217Sbill register struct tty *tp; 20317Sbill 2042395Swnj tp = &dz_tty[minor(dev)]; 20517Sbill (*linesw[tp->t_line].l_read)(tp); 20617Sbill } 20717Sbill 2082395Swnj dzwrite(dev) 2092395Swnj dev_t dev; 21017Sbill { 21117Sbill register struct tty *tp; 21217Sbill 2132395Swnj tp = &dz_tty[minor(dev)]; 21417Sbill (*linesw[tp->t_line].l_write)(tp); 21517Sbill } 21617Sbill 217119Sbill /*ARGSUSED*/ 2182395Swnj dzrint(dz) 2192395Swnj int dz; 22017Sbill { 22117Sbill register struct tty *tp; 22217Sbill register int c; 22317Sbill register struct device *dzaddr; 224119Sbill register struct tty *tp0; 2252395Swnj register int unit; 226*2923Swnj int overrun = 0; 22717Sbill 2282457Swnj if ((dzact & (1<<dz)) == 0) 2292457Swnj return; 2302457Swnj unit = dz * 8; 2312457Swnj dzaddr = dzpdma[unit].p_addr; 2322457Swnj tp0 = &dz_tty[unit]; 2332457Swnj while ((c = dzaddr->dzrbuf) < 0) { /* char present */ 2342457Swnj tp = tp0 + ((c>>8)&07); 2352457Swnj if (tp >= &dz_tty[dz_cnt]) 23617Sbill continue; 2372457Swnj if ((tp->t_state & ISOPEN) == 0) { 2382457Swnj wakeup((caddr_t)&tp->t_rawq); 2392457Swnj continue; 2402457Swnj } 2412469Swnj if (c&DZ_FE) 2422457Swnj if (tp->t_flags & RAW) 2432469Swnj c = 0; 2442457Swnj else 2452457Swnj c = tun.t_intrc; 246*2923Swnj if (c&DZ_DO && overrun == 0) { 247*2923Swnj printf("dz%d: silo overflow\n", dz); 248*2923Swnj overrun = 1; 249*2923Swnj } 2502469Swnj if (c&DZ_PE) 2512457Swnj if (((tp->t_flags & (EVENP|ODDP)) == EVENP) 2522457Swnj || ((tp->t_flags & (EVENP|ODDP)) == ODDP)) 25317Sbill continue; 2542731Swnj #if NBK > 0 2552457Swnj if (tp->t_line == NETLDISC) { 2562457Swnj c &= 0177; 2572457Swnj BKINPUT(c, tp); 2582457Swnj } else 2592731Swnj #endif 2602457Swnj (*linesw[tp->t_line].l_rint)(c, tp); 26117Sbill } 26217Sbill } 26317Sbill 26417Sbill /*ARGSUSED*/ 26517Sbill dzioctl(dev, cmd, addr, flag) 2662395Swnj dev_t dev; 2672395Swnj caddr_t addr; 26817Sbill { 26917Sbill register struct tty *tp; 2702395Swnj register int unit = minor(dev); 2712395Swnj register int dz = unit >> 3; 27217Sbill 2732395Swnj tp = &dz_tty[unit]; 274114Sbill cmd = (*linesw[tp->t_line].l_ioctl)(tp, cmd, addr); 275114Sbill if (cmd == 0) 276114Sbill return; 2771896Swnj if (ttioctl(tp, cmd, addr, flag)) { 27817Sbill if (cmd==TIOCSETP || cmd==TIOCSETN) 2792395Swnj dzparam(unit); 280170Sbill } else switch(cmd) { 2812395Swnj 282170Sbill case TIOCSBRK: 283882Sbill ((struct pdma *)(tp->t_addr))->p_addr->dzbrk = 2842395Swnj (dz_brk[dz] |= 1 << (unit&07)); 285170Sbill break; 286170Sbill case TIOCCBRK: 287882Sbill ((struct pdma *)(tp->t_addr))->p_addr->dzbrk = 2882395Swnj (dz_brk[dz] &= ~(1 << (unit&07))); 289170Sbill break; 290170Sbill case TIOCSDTR: 2912469Swnj dzmodem(unit, DZ_ON); 292170Sbill break; 293170Sbill case TIOCCDTR: 2942469Swnj dzmodem(unit, DZ_OFF); 295170Sbill break; 296170Sbill default: 29717Sbill u.u_error = ENOTTY; 298170Sbill } 29917Sbill } 30017Sbill 3012395Swnj dzparam(unit) 3022395Swnj register int unit; 30317Sbill { 30417Sbill register struct tty *tp; 30517Sbill register struct device *dzaddr; 3062395Swnj register int lpr; 30717Sbill 3082395Swnj tp = &dz_tty[unit]; 3092395Swnj dzaddr = dzpdma[unit].p_addr; 31017Sbill dzaddr->dzcsr = DZ_IEN; 3112395Swnj dzact |= (1<<(unit>>3)); 31217Sbill if (tp->t_ispeed == 0) { 3132469Swnj dzmodem(unit, DZ_OFF); /* hang up line */ 31417Sbill return; 31517Sbill } 3162395Swnj lpr = (dz_speeds[tp->t_ispeed]<<8) | (unit & 07); 3172296Swnj if ((tp->t_local&LLITOUT) || (tp->t_flags&RAW)) 31817Sbill lpr |= BITS8; 31917Sbill else 32017Sbill lpr |= (BITS7|PENABLE); 32117Sbill if ((tp->t_flags & EVENP) == 0) 32217Sbill lpr |= OPAR; 3232469Swnj if (tp->t_ispeed == B110) 3242469Swnj lpr |= TWOSB; 32517Sbill dzaddr->dzlpr = lpr; 32617Sbill } 32717Sbill 32817Sbill dzxint(tp) 3292395Swnj register struct tty *tp; 33017Sbill { 33117Sbill register struct pdma *dp; 332145Sbill register s; 33317Sbill 3342469Swnj s = spl5(); /* block pdma interrupts */ 3352395Swnj dp = (struct pdma *)tp->t_addr; 33617Sbill tp->t_state &= ~BUSY; 33717Sbill if (tp->t_state & FLUSH) 33817Sbill tp->t_state &= ~FLUSH; 33917Sbill else 340281Sbill ndflush(&tp->t_outq, dp->p_mem-tp->t_outq.c_cf); 34117Sbill if (tp->t_line) 34217Sbill (*linesw[tp->t_line].l_start)(tp); 34317Sbill else 34417Sbill dzstart(tp); 34517Sbill if (tp->t_outq.c_cc == 0 || (tp->t_state&BUSY)==0) 3462395Swnj dp->p_addr->dztcr &= ~(1 << (minor(tp->t_dev)&07)); 347145Sbill splx(s); 34817Sbill } 34917Sbill 35017Sbill dzstart(tp) 3512395Swnj register struct tty *tp; 35217Sbill { 35317Sbill register struct pdma *dp; 35417Sbill register struct device *dzaddr; 3552395Swnj register int cc; 3562395Swnj int s; 35717Sbill 3582395Swnj dp = (struct pdma *)tp->t_addr; 35917Sbill dzaddr = dp->p_addr; 3602395Swnj s = spl5(); 36117Sbill if (tp->t_state & (TIMEOUT|BUSY|TTSTOP)) 36217Sbill goto out; 363921Sbill if (tp->t_state&ASLEEP && tp->t_outq.c_cc <= TTLOWAT(tp)) { 36417Sbill tp->t_state &= ~ASLEEP; 36517Sbill if (tp->t_chan) 36617Sbill mcstart(tp->t_chan, (caddr_t)&tp->t_outq); 36717Sbill else 36817Sbill wakeup((caddr_t)&tp->t_outq); 36917Sbill } 37017Sbill if (tp->t_outq.c_cc == 0) 37117Sbill goto out; 37217Sbill if (tp->t_flags&RAW) 37317Sbill cc = ndqb(&tp->t_outq, 0); 37417Sbill else { 37517Sbill cc = ndqb(&tp->t_outq, 0200); 37617Sbill if (cc == 0) { 37717Sbill cc = getc(&tp->t_outq); 3782469Swnj timeout(ttrstrt, (caddr_t)tp, (cc&0x7f) + 6); 37917Sbill tp->t_state |= TIMEOUT; 38017Sbill goto out; 38117Sbill } 38217Sbill } 38317Sbill tp->t_state |= BUSY; 38417Sbill dp->p_end = dp->p_mem = tp->t_outq.c_cf; 38517Sbill dp->p_end += cc; 3862469Swnj dzaddr->dztcr |= 1 << (minor(tp->t_dev) & 07); /* force intr */ 3872395Swnj out: 3882395Swnj splx(s); 38917Sbill } 39017Sbill 39117Sbill /* 39217Sbill * Stop output on a line. 39317Sbill */ 39417Sbill /*ARGSUSED*/ 39517Sbill dzstop(tp, flag) 3962395Swnj register struct tty *tp; 39717Sbill { 39817Sbill register struct pdma *dp; 39917Sbill register int s; 40017Sbill 4012395Swnj dp = (struct pdma *)tp->t_addr; 4022457Swnj s = spl5(); 40317Sbill if (tp->t_state & BUSY) { 40417Sbill dp->p_end = dp->p_mem; 4052395Swnj if ((tp->t_state&TTSTOP)==0) 40617Sbill tp->t_state |= FLUSH; 40717Sbill } 40817Sbill splx(s); 40917Sbill } 41017Sbill 4112395Swnj dzmodem(unit, flag) 4122395Swnj register int unit; 41317Sbill { 41417Sbill register struct device *dzaddr; 41517Sbill register char bit; 41617Sbill 4172395Swnj dzaddr = dzpdma[unit].p_addr; 4182395Swnj bit = 1<<(unit&07); 4192469Swnj if (flag == DZ_OFF) 42017Sbill dzaddr->dzdtr &= ~bit; 42117Sbill else 42217Sbill dzaddr->dzdtr |= bit; 42317Sbill } 42417Sbill 42517Sbill dzscan() 42617Sbill { 42717Sbill register i; 42817Sbill register struct device *dzaddr; 42917Sbill register bit; 43017Sbill register struct tty *tp; 43117Sbill 43217Sbill for (i = 0; i < dz_cnt ; i++) { 43317Sbill dzaddr = dzpdma[i].p_addr; 4342627Swnj if (dzaddr == 0) 4352627Swnj continue; 43617Sbill tp = &dz_tty[i]; 43717Sbill bit = 1<<(i&07); 4382606Swnj if ((dzsoftCAR[i>>3]&bit) || (dzaddr->dzmsr&bit)) { 43917Sbill /* carrier present */ 44017Sbill if ((tp->t_state & CARR_ON) == 0) { 44117Sbill wakeup((caddr_t)&tp->t_rawq); 44217Sbill tp->t_state |= CARR_ON; 44317Sbill } 44417Sbill } else { 4452469Swnj if ((tp->t_state&CARR_ON) && 4462469Swnj (tp->t_local&LNOHANG)==0) { 44717Sbill /* carrier lost */ 448882Sbill if (tp->t_state&ISOPEN) { 449170Sbill gsignal(tp->t_pgrp, SIGHUP); 450205Sbill gsignal(tp->t_pgrp, SIGCONT); 451170Sbill dzaddr->dzdtr &= ~bit; 452871Sbill flushtty(tp, FREAD|FWRITE); 453170Sbill } 454170Sbill tp->t_state &= ~CARR_ON; 45517Sbill } 45617Sbill } 45717Sbill } 4582756Swnj timeout(dzscan, (caddr_t)0, 2*hz); 45917Sbill } 460119Sbill 461119Sbill dztimer() 462119Sbill { 4632457Swnj int dz; 464119Sbill 4652645Swnj for (dz = 0; dz < NDZ; dz++) 4662457Swnj dzrint(dz); 467119Sbill } 468281Sbill 469281Sbill /* 470281Sbill * Reset state of driver if UBA reset was necessary. 471301Sbill * Reset parameters and restart transmission on open lines. 472281Sbill */ 4732395Swnj dzreset(uban) 4742422Skre int uban; 475281Sbill { 4762395Swnj register int unit; 477281Sbill register struct tty *tp; 4782422Skre register struct uba_dinfo *ui; 479281Sbill 4802645Swnj for (unit = 0; unit < NDZLINE; unit++) { 4812422Skre ui = dzinfo[unit >> 3]; 4822422Skre if (ui == 0 || ui->ui_ubanum != uban || ui->ui_alive == 0) 4832422Skre continue; 484*2923Swnj if (unit%8 == 0) 485*2923Swnj printf(" dz%d", unit>>3); 4862395Swnj tp = &dz_tty[unit]; 487281Sbill if (tp->t_state & (ISOPEN|WOPEN)) { 4882395Swnj dzparam(unit); 4892469Swnj dzmodem(unit, DZ_ON); 490301Sbill tp->t_state &= ~BUSY; 491301Sbill dzstart(tp); 492281Sbill } 493281Sbill } 494281Sbill dztimer(); 495281Sbill } 4961562Sbill #endif 497