1*12449Ssam /* dmf.c 4.17 83/05/14 */ 26940Ssam 36940Ssam #include "dmf.h" 46940Ssam #if NDMF > 0 56940Ssam /* 66940Ssam * DMF32 driver 76940Ssam * 86940Ssam * TODO: 96940Ssam * test with modem 106940Ssam * load as much as possible into silo 116940Ssam * get correct numbers for receive silo parameter timeout 126940Ssam * use auto XON/XOFF 136940Ssam * test reset code 146940Ssam * test with more than one unit 156940Ssam * optimize for efficient DMA and dynamically 166940Ssam * decide between silo and DMA mode 176940Ssam */ 189772Ssam #include "../machine/pte.h" 199772Ssam 206940Ssam #include "bk.h" 216940Ssam #include "../h/param.h" 226940Ssam #include "../h/conf.h" 236940Ssam #include "../h/dir.h" 246940Ssam #include "../h/user.h" 259550Ssam #include "../h/ioctl.h" 266940Ssam #include "../h/tty.h" 276940Ssam #include "../h/map.h" 286940Ssam #include "../h/buf.h" 296940Ssam #include "../h/vm.h" 306940Ssam #include "../h/bk.h" 316940Ssam #include "../h/clist.h" 326940Ssam #include "../h/file.h" 337726Sroot #include "../h/uio.h" 346940Ssam 358473Sroot #include "../vaxuba/ubareg.h" 368473Sroot #include "../vaxuba/ubavar.h" 37*12449Ssam #include "../vaxuba/dmfreg.h" 388473Sroot 396940Ssam /* 406940Ssam * Definition of the driver for the auto-configuration program. 416940Ssam */ 426940Ssam int dmfprobe(), dmfattach(), dmfrint(), dmfxint(); 436940Ssam struct uba_device *dmfinfo[NDMF]; 446940Ssam u_short dmfstd[] = { 0 }; 456940Ssam struct uba_driver dmfdriver = 466940Ssam { dmfprobe, 0, dmfattach, 0, dmfstd, "dmf", dmfinfo }; 476940Ssam 486940Ssam /* 496940Ssam * Local variables for the driver 506940Ssam */ 516940Ssam char dmf_speeds[] = 526940Ssam { 0, 0, 1, 2, 3, 4, 0, 5, 6, 7, 010, 012, 014, 016, 017, 0 }; 536940Ssam 546940Ssam struct tty dmf_tty[NDMF*8]; 556940Ssam char dmfsoftCAR[NDMF]; 568778Sroot #ifndef lint 578778Sroot int ndmf = NDMF*8; /* used by iostat */ 588778Sroot #endif 596940Ssam int dmfact; /* mask of active dmf's */ 606940Ssam int dmfstart(), ttrstrt(); 616940Ssam 626940Ssam #ifdef DMFDMA 636940Ssam /* 646940Ssam * The clist space is mapped by the driver onto each UNIBUS. 656940Ssam * The UBACVT macro converts a clist space address for unibus uban 666940Ssam * into an i/o space address for the DMA routine. 676940Ssam */ 686940Ssam int dmf_ubinfo[MAXNUBA]; /* info about allocated unibus map */ 696940Ssam static int cbase[MAXNUBA]; /* base address in unibus map */ 706940Ssam #define UBACVT(x, uban) (cbase[uban] + ((x)-(char *)cfree)) 716940Ssam #endif 726940Ssam 736940Ssam /* 746940Ssam * Routine for configuration to set dmf interrupt. 756940Ssam */ 766940Ssam /*ARGSUSED*/ 776940Ssam dmfprobe(reg, ctlr) 786940Ssam caddr_t reg; 796940Ssam int ctlr; 806940Ssam { 816940Ssam register int br, cvec; /* these are ``value-result'' */ 826940Ssam register struct dmfdevice *dmfaddr = (struct dmfdevice *)reg; 836940Ssam 846940Ssam #ifdef lint 856940Ssam br = 0; cvec = br; br = cvec; 868808Sroot dmfxint(0); dmfrint(0); 878808Sroot dmfsrint(); dmfsxint(); dmfdaint(); dmfdbint(); dmflint(); 886940Ssam #endif 896940Ssam br = 0x15; 906940Ssam cvec = (uba_hd[numuba].uh_lastiv -= 4*8); 916940Ssam dmfaddr->dmfccsr0 = cvec >> 2; 926940Ssam /* NEED TO SAVE IT SOMEWHERE FOR OTHER DEVICES */ 937412Skre return (sizeof (struct dmfdevice)); 946940Ssam } 956940Ssam 966940Ssam /* 976940Ssam * Routine called to attach a dmf. 986940Ssam */ 996940Ssam dmfattach(ui) 1006940Ssam struct uba_device *ui; 1016940Ssam { 1026940Ssam 1036940Ssam dmfsoftCAR[ui->ui_unit] = ui->ui_flags; 1046940Ssam } 1056940Ssam 1066940Ssam 1076940Ssam /* 1086940Ssam * Open a DMF32 line, mapping the clist onto the uba if this 1096940Ssam * is the first dmf on this uba. Turn on this dmf if this is 1106940Ssam * the first use of it. 1116940Ssam */ 1126940Ssam /*ARGSUSED*/ 1136940Ssam dmfopen(dev, flag) 1146940Ssam dev_t dev; 1156940Ssam { 1166940Ssam register struct tty *tp; 1176940Ssam register int unit, dmf; 1186940Ssam register struct dmfdevice *addr; 1196940Ssam register struct uba_device *ui; 1206940Ssam int s; 1216940Ssam 1226940Ssam unit = minor(dev); 1236940Ssam dmf = unit >> 3; 1248567Sroot if (unit >= NDMF*8 || (ui = dmfinfo[dmf])== 0 || ui->ui_alive == 0) 1258567Sroot return (ENXIO); 1266940Ssam tp = &dmf_tty[unit]; 1278567Sroot if (tp->t_state&TS_XCLUDE && u.u_uid!=0) 1288567Sroot return (EBUSY); 1296940Ssam addr = (struct dmfdevice *)ui->ui_addr; 1306940Ssam tp->t_addr = (caddr_t)addr; 1316940Ssam tp->t_oproc = dmfstart; 1326971Ssam tp->t_state |= TS_WOPEN; 1336940Ssam /* 1346940Ssam * While setting up state for this uba and this dmf, 1356940Ssam * block uba resets which can clear the state. 1366940Ssam */ 1376940Ssam s = spl5(); 1386940Ssam #ifdef DMFDMA 1396940Ssam if (dmf_ubinfo[ui->ui_ubanum] == 0) { 1406940Ssam dmf_ubinfo[ui->ui_ubanum] = 1416940Ssam uballoc(ui->ui_ubanum, (caddr_t)cfree, 1426940Ssam nclist*sizeof(struct cblock), 0); 1436940Ssam cbase[ui->ui_ubanum] = dmf_ubinfo[ui->ui_ubanum]&0x3ffff; 1446940Ssam } 1456940Ssam #endif 1466940Ssam if ((dmfact&(1<<dmf)) == 0) { 1476940Ssam addr->dmfcsr |= DMF_IE; 1486940Ssam dmfact |= (1<<dmf); 1496940Ssam addr->dmfrsp = 1; /* DON'T KNOW WHAT TO SET IT TO YET */ 1506940Ssam } 1516940Ssam splx(s); 1526940Ssam /* 1536940Ssam * If this is first open, initialze tty state to default. 1546940Ssam */ 1556971Ssam if ((tp->t_state&TS_ISOPEN) == 0) { 1566940Ssam ttychars(tp); 1576940Ssam if (tp->t_ispeed == 0) { 1586940Ssam tp->t_ispeed = B300; 1596940Ssam tp->t_ospeed = B300; 1606940Ssam tp->t_flags = ODDP|EVENP|ECHO; 1616940Ssam } 1626940Ssam dmfparam(unit); 1636940Ssam } 1646940Ssam /* 1656940Ssam * Wait for carrier, then process line discipline specific open. 1666940Ssam */ 1676940Ssam if ((dmfmctl(dev, DMF_ON, DMSET) & (DMF_CAR<<8)) || 1686940Ssam (dmfsoftCAR[dmf] & (1<<(unit&07)))) 1696971Ssam tp->t_state |= TS_CARR_ON; 1706940Ssam s = spl5(); 1716971Ssam while ((tp->t_state & TS_CARR_ON) == 0) { 1726971Ssam tp->t_state |= TS_WOPEN; 1736940Ssam sleep((caddr_t)&tp->t_rawq, TTIPRI); 1746940Ssam } 1756940Ssam splx(s); 1768567Sroot return ((*linesw[tp->t_line].l_open)(dev, tp)); 1776940Ssam } 1786940Ssam 1796940Ssam /* 1806940Ssam * Close a DMF32 line. 1816940Ssam */ 1826940Ssam /*ARGSUSED*/ 1836940Ssam dmfclose(dev, flag) 1846940Ssam dev_t dev; 1856940Ssam int flag; 1866940Ssam { 1876940Ssam register struct tty *tp; 1886940Ssam register unit; 1896940Ssam 1906940Ssam unit = minor(dev); 1916940Ssam tp = &dmf_tty[unit]; 1926940Ssam (*linesw[tp->t_line].l_close)(tp); 1938702Sroot (void) dmfmctl(unit, DMF_BRK, DMBIC); 1946971Ssam if (tp->t_state&TS_HUPCLS || (tp->t_state&TS_ISOPEN)==0) 1958702Sroot (void) dmfmctl(unit, DMF_OFF, DMSET); 1966940Ssam ttyclose(tp); 1976940Ssam } 1986940Ssam 1997726Sroot dmfread(dev, uio) 2006940Ssam dev_t dev; 2017726Sroot struct uio *uio; 2026940Ssam { 2036940Ssam register struct tty *tp; 2046940Ssam 2056940Ssam tp = &dmf_tty[minor(dev)]; 2067726Sroot return ((*linesw[tp->t_line].l_read)(tp, uio)); 2076940Ssam } 2086940Ssam 2097832Sroot dmfwrite(dev, uio) 2106940Ssam dev_t dev; 2117832Sroot struct uio *uio; 2126940Ssam { 2136940Ssam register struct tty *tp; 2146940Ssam 2156940Ssam tp = &dmf_tty[minor(dev)]; 2168530Sroot return ((*linesw[tp->t_line].l_write)(tp, uio)); 2176940Ssam } 2186940Ssam 2196940Ssam /* 2206940Ssam * DMF32 receiver interrupt. 2216940Ssam */ 2226940Ssam dmfrint(dmf) 2236940Ssam int dmf; 2246940Ssam { 2256940Ssam register struct tty *tp; 2266940Ssam register c; 2276940Ssam register struct dmfdevice *addr; 2286940Ssam register struct tty *tp0; 2296940Ssam register struct uba_device *ui; 230*12449Ssam int overrun = 0, s; 2316940Ssam 2326940Ssam ui = dmfinfo[dmf]; 2336940Ssam if (ui == 0 || ui->ui_alive == 0) 2346940Ssam return; 2356940Ssam addr = (struct dmfdevice *)ui->ui_addr; 2366940Ssam tp0 = &dmf_tty[dmf<<3]; 2376940Ssam /* 2386940Ssam * Loop fetching characters from the silo for this 2396940Ssam * dmf until there are no more in the silo. 2406940Ssam */ 2416940Ssam while ((c = addr->dmfrbuf) < 0) { 2426940Ssam tp = tp0 + ((c>>8)&07); 2436940Ssam if (c & DMF_DSC) { 244*12449Ssam s = spl5(); 2456940Ssam addr->dmfcsr = DMF_IE | DMFIR_TBUF | ((c>>8)&07); 2466940Ssam if (addr->dmfrms & DMF_CAR) { 2476971Ssam if ((tp->t_state & TS_CARR_ON) == 0) { 2486940Ssam wakeup((caddr_t)&tp->t_rawq); 2496971Ssam tp->t_state |= TS_CARR_ON; 2506940Ssam } 2516940Ssam } else { 2526971Ssam if (tp->t_state & TS_CARR_ON) { 2536940Ssam gsignal(tp->t_pgrp, SIGHUP); 2546940Ssam gsignal(tp->t_pgrp, SIGCONT); 2556940Ssam addr->dmfcsr = DMF_IE | DMFIR_LCR | 2566940Ssam ((c>>8)&07); 2576940Ssam addr->dmftms = 0; 2586940Ssam flushtty(tp, FREAD|FWRITE); 2596940Ssam } 2606971Ssam tp->t_state &= ~TS_CARR_ON; 2616940Ssam } 262*12449Ssam splx(s); 2636940Ssam continue; 2646940Ssam } 2656971Ssam if ((tp->t_state&TS_ISOPEN)==0) { 2666940Ssam wakeup((caddr_t)tp); 2676940Ssam continue; 2686940Ssam } 2696940Ssam if (c & DMF_PE) 2706940Ssam if ((tp->t_flags&(EVENP|ODDP))==EVENP 2716940Ssam || (tp->t_flags&(EVENP|ODDP))==ODDP ) 2726940Ssam continue; 2736940Ssam if ((c & DMF_DO) && overrun == 0) { 2746940Ssam printf("dmf%d: silo overflow\n", dmf); 2756940Ssam overrun = 1; 2766940Ssam } 2776940Ssam if (c & DMF_FE) 2786940Ssam /* 2796940Ssam * At framing error (break) generate 2806940Ssam * a null (in raw mode, for getty), or a 2816940Ssam * interrupt (in cooked/cbreak mode). 2826940Ssam */ 2836940Ssam if (tp->t_flags&RAW) 2846940Ssam c = 0; 2856940Ssam else 2869550Ssam c = tp->t_intrc; 2876940Ssam #if NBK > 0 2886940Ssam if (tp->t_line == NETLDISC) { 2896940Ssam c &= 0177; 2906940Ssam BKINPUT(c, tp); 2916940Ssam } else 2926940Ssam #endif 2936940Ssam (*linesw[tp->t_line].l_rint)(c, tp); 2946940Ssam } 2956940Ssam } 2966940Ssam 2976940Ssam /* 2986940Ssam * Ioctl for DMF32. 2996940Ssam */ 3006940Ssam /*ARGSUSED*/ 3017630Ssam dmfioctl(dev, cmd, data, flag) 3026940Ssam dev_t dev; 3037630Ssam caddr_t data; 3046940Ssam { 3056940Ssam register struct tty *tp; 3066940Ssam register int unit = minor(dev); 3078567Sroot int error; 3086940Ssam 3096940Ssam tp = &dmf_tty[unit]; 3108567Sroot error = (*linesw[tp->t_line].l_ioctl)(tp, cmd, data, flag); 3118567Sroot if (error >= 0) 3128567Sroot return (error); 3138567Sroot error = ttioctl(tp, cmd, data, flag); 3148567Sroot if (error >= 0) { 3157630Ssam if (cmd == TIOCSETP || cmd == TIOCSETN) 3166940Ssam dmfparam(unit); 3178567Sroot return (error); 3188567Sroot } 3198567Sroot switch (cmd) { 3206940Ssam 3216940Ssam case TIOCSBRK: 3228702Sroot (void) dmfmctl(dev, DMF_BRK, DMBIS); 3236940Ssam break; 3247630Ssam 3256940Ssam case TIOCCBRK: 3268702Sroot (void) dmfmctl(dev, DMF_BRK, DMBIC); 3276940Ssam break; 3287630Ssam 3296940Ssam case TIOCSDTR: 3308702Sroot (void) dmfmctl(dev, DMF_DTR|DMF_RTS, DMBIS); 3316940Ssam break; 3327630Ssam 3336940Ssam case TIOCCDTR: 3348702Sroot (void) dmfmctl(dev, DMF_DTR|DMF_RTS, DMBIC); 3356940Ssam break; 3367630Ssam 3376940Ssam case TIOCMSET: 3388702Sroot (void) dmfmctl(dev, dmtodmf(*(int *)data), DMSET); 3396940Ssam break; 3407630Ssam 3416940Ssam case TIOCMBIS: 3428702Sroot (void) dmfmctl(dev, dmtodmf(*(int *)data), DMBIS); 3436940Ssam break; 3447630Ssam 3456940Ssam case TIOCMBIC: 3468702Sroot (void) dmfmctl(dev, dmtodmf(*(int *)data), DMBIC); 3476940Ssam break; 3487630Ssam 3496940Ssam case TIOCMGET: 3507630Ssam *(int *)data = dmftodm(dmfmctl(dev, 0, DMGET)); 3516940Ssam break; 3527630Ssam 3536940Ssam default: 3548567Sroot return (ENOTTY); 3556940Ssam } 3568567Sroot return (0); 3576940Ssam } 3586940Ssam 3596940Ssam dmtodmf(bits) 3606940Ssam register int bits; 3616940Ssam { 3626940Ssam register int b; 3636940Ssam 3646940Ssam b = bits & 012; 3656940Ssam if (bits & DML_ST) b |= DMF_RATE; 3666940Ssam if (bits & DML_RTS) b |= DMF_RTS; 3676940Ssam if (bits & DML_USR) b |= DMF_USRW; 3686940Ssam return(b); 3696940Ssam } 3706940Ssam 3716940Ssam dmftodm(bits) 3726940Ssam register int bits; 3736940Ssam { 3746940Ssam register int b; 3756940Ssam 3766940Ssam b = (bits & 012) | ((bits >> 7) & 0760) | DML_LE; 3776940Ssam if (bits & DMF_USRR) b |= DML_USR; 3786940Ssam if (bits & DMF_RTS) b |= DML_RTS; 3796940Ssam return(b); 3806940Ssam } 3816940Ssam 3826940Ssam 3836940Ssam /* 3846940Ssam * Set parameters from open or stty into the DMF hardware 3856940Ssam * registers. 3866940Ssam */ 3876940Ssam dmfparam(unit) 3886940Ssam register int unit; 3896940Ssam { 3906940Ssam register struct tty *tp; 3916940Ssam register struct dmfdevice *addr; 3926940Ssam register int lpar, lcr; 3936940Ssam int s; 3946940Ssam 3956940Ssam tp = &dmf_tty[unit]; 3966940Ssam addr = (struct dmfdevice *)tp->t_addr; 3976940Ssam /* 3986940Ssam * Block interrupts so parameters will be set 3996940Ssam * before the line interrupts. 4006940Ssam */ 4016940Ssam s = spl5(); 4026940Ssam addr->dmfcsr = (unit&07) | DMFIR_LCR | DMF_IE; 4036940Ssam if ((tp->t_ispeed)==0) { 4046971Ssam tp->t_state |= TS_HUPCLS; 4058702Sroot (void) dmfmctl(unit, DMF_OFF, DMSET); 4066940Ssam return; 4076940Ssam } 4086940Ssam lpar = (dmf_speeds[tp->t_ospeed]<<12) | (dmf_speeds[tp->t_ispeed]<<8); 4096940Ssam lcr = DMFLCR_ENA; 4106940Ssam if ((tp->t_ispeed) == B134) 4116940Ssam lpar |= BITS6|PENABLE; 4129550Ssam else if (tp->t_flags & (RAW|LITOUT)) 4136940Ssam lpar |= BITS8; 4146940Ssam else { 4156940Ssam lpar |= BITS7|PENABLE; 4166940Ssam /* CHECK FOR XON/XOFF AND SET lcr |= DMF_AUTOX; */ 4176940Ssam } 4186940Ssam if ((tp->t_flags&EVENP) == 0) 4196940Ssam lpar |= OPAR; 4206940Ssam if ((tp->t_ospeed) == B110) 4216940Ssam lpar |= TWOSB; 4226940Ssam lpar |= (unit&07); 4236940Ssam addr->dmflpr = lpar; 424*12449Ssam SETLCR(addr, lcr); 4256940Ssam splx(s); 4266940Ssam } 4276940Ssam 4286940Ssam /* 4296940Ssam * DMF32 transmitter interrupt. 4306940Ssam * Restart the idle line. 4316940Ssam */ 4326940Ssam dmfxint(dmf) 4336940Ssam int dmf; 4346940Ssam { 4356940Ssam register struct tty *tp; 4366940Ssam register struct dmfdevice *addr; 4376940Ssam register struct uba_device *ui; 4386940Ssam register int unit, t; 4396940Ssam #ifdef DMFDMA 4406940Ssam short cntr; 441*12449Ssam int s; 4426940Ssam #endif 4436940Ssam 4446940Ssam ui = dmfinfo[dmf]; 4456940Ssam addr = (struct dmfdevice *)ui->ui_addr; 4466940Ssam while ((t = addr->dmfcsr) & DMF_TI) { 4476940Ssam unit = dmf*8 + ((t>>8)&07); 4486940Ssam tp = &dmf_tty[unit]; 4496971Ssam tp->t_state &= ~TS_BUSY; 4506940Ssam if (t & DMF_NXM) { 4516940Ssam printf("dmf%d: NXM line %d\n", dmf, unit&7); 4526940Ssam /* SHOULD RESTART OR SOMETHING... */ 4536940Ssam } 4546971Ssam if (tp->t_state&TS_FLUSH) 4556971Ssam tp->t_state &= ~TS_FLUSH; 4566940Ssam #ifdef DMFDMA 4576940Ssam else { 458*12449Ssam s = spl5(); 4596940Ssam addr->dmfcsr = DMFIR_TBUF | DMF_IE | (unit&07); 4606940Ssam if (addr->dmftsc == 0) { 4616940Ssam /* 4626940Ssam * Do arithmetic in a short to make up 4636940Ssam * for lost 16&17 bits. 4646940Ssam */ 4656940Ssam addr->dmfcsr = DMFIR_TBA | DMF_IE | (unit&07); 4666940Ssam cntr = addr->dmftba - 4676940Ssam UBACVT(tp->t_outq.c_cf, ui->ui_ubanum); 4686940Ssam ndflush(&tp->t_outq, (int)cntr); 4696940Ssam } 470*12449Ssam splx(s); 4716940Ssam } 4726940Ssam #endif 4736940Ssam if (tp->t_line) 4746940Ssam (*linesw[tp->t_line].l_start)(tp); 4756940Ssam else 4766940Ssam dmfstart(tp); 4776940Ssam } 4786940Ssam } 4796940Ssam 4806940Ssam /* 4816940Ssam * Start (restart) transmission on the given DMF32 line. 4826940Ssam */ 4836940Ssam dmfstart(tp) 4846940Ssam register struct tty *tp; 4856940Ssam { 4866940Ssam register struct dmfdevice *addr; 4878607Sroot register int unit, nch; 4886940Ssam int s; 4896940Ssam 4906940Ssam unit = minor(tp->t_dev); 4916940Ssam unit &= 07; 4926940Ssam addr = (struct dmfdevice *)tp->t_addr; 4936940Ssam 4946940Ssam /* 4956940Ssam * Must hold interrupts in following code to prevent 4966940Ssam * state of the tp from changing. 4976940Ssam */ 4986940Ssam s = spl5(); 4996940Ssam /* 5006940Ssam * If it's currently active, or delaying, no need to do anything. 5016940Ssam */ 5026971Ssam if (tp->t_state&(TS_TIMEOUT|TS_BUSY|TS_TTSTOP)) 5036940Ssam goto out; 5046940Ssam /* 5056940Ssam * If there are still characters in the silo, 5066940Ssam * just reenable the transmitter. 5076940Ssam */ 5086940Ssam addr->dmfcsr = DMF_IE | DMFIR_TBUF | unit; 5096940Ssam if (addr->dmftsc) { 5106940Ssam addr->dmfcsr = DMF_IE | DMFIR_LCR | unit; 511*12449Ssam SETLCR(addr, addr->dmflcr|DMF_TE); 5126971Ssam tp->t_state |= TS_BUSY; 5136940Ssam goto out; 5146940Ssam } 5156940Ssam /* 5166940Ssam * If there are sleepers, and output has drained below low 5176940Ssam * water mark, wake up the sleepers. 5186940Ssam */ 5196971Ssam if ((tp->t_state&TS_ASLEEP) && tp->t_outq.c_cc<=TTLOWAT(tp)) { 5206971Ssam tp->t_state &= ~TS_ASLEEP; 5216963Ssam wakeup((caddr_t)&tp->t_outq); 5226940Ssam } 5236940Ssam /* 5246940Ssam * Now restart transmission unless the output queue is 5256940Ssam * empty. 5266940Ssam */ 5276940Ssam if (tp->t_outq.c_cc == 0) 5286940Ssam goto out; 5299550Ssam if (tp->t_flags & (RAW|LITOUT)) 5306940Ssam nch = ndqb(&tp->t_outq, 0); 5316940Ssam else { 5326940Ssam nch = ndqb(&tp->t_outq, 0200); 5336940Ssam /* 5346940Ssam * If first thing on queue is a delay process it. 5356940Ssam */ 5366940Ssam if (nch == 0) { 5376940Ssam nch = getc(&tp->t_outq); 5386940Ssam timeout(ttrstrt, (caddr_t)tp, (nch&0x7f)+6); 5396971Ssam tp->t_state |= TS_TIMEOUT; 5406940Ssam goto out; 5416940Ssam } 5426940Ssam } 5436940Ssam /* 5446940Ssam * If characters to transmit, restart transmission. 5456940Ssam */ 5466940Ssam if (nch) { 5476940Ssam #ifdef DMFDMA 5486940Ssam addr->dmfcsr = DMF_IE | DMFIR_LCR | unit; 549*12449Ssam SETLCR(addr, addr->dmflcr|DMF_TE); 5506940Ssam car = UBACVT(tp->t_outq.c_cf, dmfinfo[dmf]->ui_ubanum); 5516940Ssam addr->dmfcsr = DMF_IE | DMFIR_TBA | unit; 5526940Ssam addr->dmftba = car; 5536940Ssam addr->dmftcc = ((car>>2)&0xc000) | nch; 5546940Ssam #else 5556940Ssam register char *cp = tp->t_outq.c_cf; 5566940Ssam register int i; 5576940Ssam 5586940Ssam nch = MIN(nch, DMF_SILOCNT); 5596940Ssam addr->dmfcsr = DMF_IE | DMFIR_LCR | unit; 560*12449Ssam SETLCR(addr, addr->dmflcr|DMF_TE); 5616940Ssam addr->dmfcsr = DMF_IE | DMFIR_TBUF | unit; 5626940Ssam for (i = 0; i < nch; i++) 5636940Ssam addr->dmftbuf = *cp++; 5646940Ssam ndflush(&tp->t_outq, nch); 5656940Ssam #endif 5666971Ssam tp->t_state |= TS_BUSY; 5676940Ssam } 5686940Ssam out: 5696940Ssam splx(s); 5706940Ssam } 5716940Ssam 5726940Ssam /* 5736940Ssam * Stop output on a line, e.g. for ^S/^Q or output flush. 5746940Ssam */ 5756940Ssam /*ARGSUSED*/ 5766940Ssam dmfstop(tp, flag) 5776940Ssam register struct tty *tp; 5786940Ssam { 5796940Ssam register struct dmfdevice *addr; 5806940Ssam register int unit, s; 5816940Ssam 5826940Ssam addr = (struct dmfdevice *)tp->t_addr; 5836940Ssam /* 5846940Ssam * Block input/output interrupts while messing with state. 5856940Ssam */ 5866940Ssam s = spl5(); 5876971Ssam if (tp->t_state & TS_BUSY) { 5886940Ssam /* 5896940Ssam * Device is transmitting; stop output 5906940Ssam * by selecting the line and disabling 5916940Ssam * the transmitter. If this is a flush 5926940Ssam * request then flush the output silo, 5936940Ssam * otherwise we will pick up where we 5946940Ssam * left off by enabling the transmitter. 5956940Ssam */ 5966940Ssam unit = minor(tp->t_dev); 5976940Ssam addr->dmfcsr = DMFIR_LCR | (unit&07) | DMF_IE; 598*12449Ssam SETLCR(addr, addr->dmflcr &~ DMF_TE); 5996971Ssam if ((tp->t_state&TS_TTSTOP)==0) { 6006971Ssam tp->t_state |= TS_FLUSH; 601*12449Ssam SETLCR(addr, addr->dmflcr|DMF_FLUSH); 6026940Ssam } else 6036971Ssam tp->t_state &= ~TS_BUSY; 6046940Ssam } 6056940Ssam splx(s); 6066940Ssam } 6076940Ssam 6086940Ssam /* 6096940Ssam * DMF32 modem control 6106940Ssam */ 6116940Ssam dmfmctl(dev, bits, how) 6126940Ssam dev_t dev; 6136940Ssam int bits, how; 6146940Ssam { 6156940Ssam register struct dmfdevice *dmfaddr; 6166940Ssam register int unit, mbits, lcr; 6176940Ssam int s; 6186940Ssam 6196940Ssam unit = minor(dev); 6206940Ssam dmfaddr = (struct dmfdevice *)(dmf_tty[unit].t_addr); 6216940Ssam unit &= 07; 6226940Ssam s = spl5(); 6236940Ssam dmfaddr->dmfcsr = DMF_IE | DMFIR_TBUF | unit; 6246940Ssam mbits = dmfaddr->dmfrms << 8; 6256940Ssam dmfaddr->dmfcsr = DMF_IE | DMFIR_LCR | unit; 6266940Ssam mbits |= dmfaddr->dmftms; 6276940Ssam lcr = dmfaddr->dmflcr; 6286940Ssam switch (how) { 6296940Ssam case DMSET: 630*12449Ssam mbits = (mbits &0xff00) | bits; 6316940Ssam break; 6326940Ssam 6336940Ssam case DMBIS: 6346940Ssam mbits |= bits; 6356940Ssam break; 6366940Ssam 6376940Ssam case DMBIC: 6386940Ssam mbits &= ~bits; 6396940Ssam break; 6406940Ssam 6416940Ssam case DMGET: 6426940Ssam (void) splx(s); 6436940Ssam return(mbits); 6446940Ssam } 6456940Ssam if (mbits & DMF_BRK) 6466940Ssam lcr |= DMF_RBRK; 6476940Ssam else 6486940Ssam lcr &= ~DMF_RBRK; 649*12449Ssam lcr = ((mbits & 037) << 8) | (lcr & 0xff); 650*12449Ssam dmfaddr->dmfun.dmfirw = lcr; 6516940Ssam (void) splx(s); 6526940Ssam return(mbits); 6536940Ssam } 6546940Ssam 6556940Ssam /* 6566940Ssam * Reset state of driver if UBA reset was necessary. 6576940Ssam * Reset the csr, lpr, and lcr registers on open lines, and 6586940Ssam * restart transmitters. 6596940Ssam */ 6606940Ssam dmfreset(uban) 6616940Ssam int uban; 6626940Ssam { 6636940Ssam register int dmf, unit; 6646940Ssam register struct tty *tp; 6656940Ssam register struct uba_device *ui; 6666940Ssam register struct dmfdevice *addr; 6676940Ssam int i; 6686940Ssam 6696940Ssam #ifdef DMFDMA 6706940Ssam if (dmf_ubinfo[uban] == 0) 6716940Ssam return; 6726940Ssam dmf_ubinfo[uban] = uballoc(uban, (caddr_t)cfree, 6736940Ssam nclist*sizeof (struct cblock), 0); 6746940Ssam cbase[uban] = dmf_ubinfo[uban]&0x3ffff; 6756940Ssam #endif 6766940Ssam for (dmf = 0; dmf < NDMF; dmf++) { 6776940Ssam ui = dmfinfo[dmf]; 6786940Ssam if (ui == 0 || ui->ui_alive == 0 || ui->ui_ubanum != uban) 6796940Ssam continue; 6806940Ssam printf(" dmf%d", dmf); 6816940Ssam addr = (struct dmfdevice *)ui->ui_addr; 6826940Ssam addr->dmfcsr = DMF_IE; 6836940Ssam addr->dmfrsp = 1; 6846940Ssam unit = dmf * 8; 6856940Ssam for (i = 0; i < 8; i++) { 6866940Ssam tp = &dmf_tty[unit]; 6876971Ssam if (tp->t_state & (TS_ISOPEN|TS_WOPEN)) { 6886940Ssam dmfparam(unit); 6898702Sroot (void) dmfmctl(unit, DMF_ON, DMSET); 6906971Ssam tp->t_state &= ~TS_BUSY; 6916940Ssam dmfstart(tp); 6926940Ssam } 6936940Ssam unit++; 6946940Ssam } 6956940Ssam } 6966940Ssam } 6976940Ssam 6986940Ssam /* stubs for interrupt routines for devices not yet supported */ 6996940Ssam 7006940Ssam dmfsrint() { printf("dmfsrint\n"); } 7016940Ssam 7026940Ssam dmfsxint() { printf("dmfsxint\n"); } 7036940Ssam 7046940Ssam dmfdaint() { printf("dmfdaint\n"); } 7056940Ssam 7066940Ssam dmfdbint() { printf("dmfdbint\n"); } 7076940Ssam 7086940Ssam dmflint() { printf("dmflint\n"); } 7096940Ssam #endif 710