123324Smckusick /* 229213Smckusick * Copyright (c) 1982, 1986 Regents of the University of California. 323324Smckusick * All rights reserved. The Berkeley software License Agreement 423324Smckusick * specifies the terms and conditions for redistribution. 523324Smckusick * 6*30322Skarels * @(#)dmf.c 7.3 (Berkeley) 12/19/86 723324Smckusick */ 86940Ssam 96940Ssam #include "dmf.h" 106940Ssam #if NDMF > 0 116940Ssam /* 126940Ssam * DMF32 driver 136940Ssam * 1421955Sbloom * 156940Ssam * TODO: 166940Ssam * test with modem 176940Ssam * load as much as possible into silo 186940Ssam * use auto XON/XOFF 196940Ssam * test reset code 2021955Sbloom **************************** 2121955Sbloom * DMF32 line printer driver 2221955Sbloom * 2321955Sbloom * the line printer on dmfx is indicated by a minor device code of 128+x 2421955Sbloom * 2521955Sbloom * the flags field of the config file is interpreted like so: 2621955Sbloom * bits meaning 2721955Sbloom * ---- ------- 2821955Sbloom * 0-7 soft carrier bits for ttys part of dmf32 2921955Sbloom * 8-15 number of cols/line on the line printer 3021955Sbloom * if 0, 132 will be used. 3121955Sbloom * 16-23 number of lines/page on the line printer 3221955Sbloom * if 0, 66 will be used. 3326910Skarels * 24 if 1 DO NOT use the auto format mode of the 3426910Skarels * line printer parallel port 356940Ssam */ 369772Ssam #include "../machine/pte.h" 379772Ssam 386940Ssam #include "bk.h" 3916063Skarels #include "uba.h" 4017124Sbloom #include "param.h" 4117124Sbloom #include "conf.h" 4217124Sbloom #include "dir.h" 4317124Sbloom #include "user.h" 4426836Skarels #include "proc.h" 4517124Sbloom #include "ioctl.h" 4617124Sbloom #include "tty.h" 4717124Sbloom #include "map.h" 4817124Sbloom #include "buf.h" 4917124Sbloom #include "vm.h" 5017124Sbloom #include "bkmac.h" 5117124Sbloom #include "clist.h" 5217124Sbloom #include "file.h" 5317124Sbloom #include "uio.h" 5421955Sbloom #include "kernel.h" 5518312Sralph #include "syslog.h" 566940Ssam 5717124Sbloom #include "ubareg.h" 5817124Sbloom #include "ubavar.h" 5917124Sbloom #include "dmfreg.h" 608473Sroot 616940Ssam /* 626940Ssam * Definition of the driver for the auto-configuration program. 636940Ssam */ 646940Ssam int dmfprobe(), dmfattach(), dmfrint(), dmfxint(); 6521955Sbloom int dmflint(); 666940Ssam struct uba_device *dmfinfo[NDMF]; 676940Ssam u_short dmfstd[] = { 0 }; 686940Ssam struct uba_driver dmfdriver = 696940Ssam { dmfprobe, 0, dmfattach, 0, dmfstd, "dmf", dmfinfo }; 706940Ssam 7125449Skarels int dmf_timeout = 10; /* silo timeout, in ms */ 7221955Sbloom int dmf_mindma = 4; /* don't dma below this point */ 7321955Sbloom 746940Ssam /* 756940Ssam * Local variables for the driver 766940Ssam */ 776940Ssam char dmf_speeds[] = 786940Ssam { 0, 0, 1, 2, 3, 4, 0, 5, 6, 7, 010, 012, 014, 016, 017, 0 }; 796940Ssam 8025449Skarels #ifndef PORTSELECTOR 8125449Skarels #define ISPEED B9600 8225449Skarels #define IFLAGS (EVENP|ODDP|ECHO) 8325449Skarels #else 8425449Skarels #define ISPEED B4800 8525449Skarels #define IFLAGS (EVENP|ODDP) 8625449Skarels #endif 8725449Skarels 886940Ssam struct tty dmf_tty[NDMF*8]; 896940Ssam char dmfsoftCAR[NDMF]; 9021955Sbloom 9126366Skarels struct dmfl_softc { 9226366Skarels u_int dmfl_state; /* soft state bits */ 9326366Skarels int dmfl_info; /* uba info */ 9426366Skarels u_short dmfl_lines; /* lines per page (66 def.) */ 9526366Skarels u_short dmfl_cols; /* cols per line (132 def.) */ 9626910Skarels u_short dmfl_format; /* fflag for auto form feed */ 9726366Skarels char dmfl_buf[DMFL_BUFSIZ]; 9821955Sbloom } dmfl_softc[NDMF]; 9921955Sbloom 10021955Sbloom /* 10121955Sbloom * convert device number into DMF line printer unit number 10221955Sbloom */ 10321955Sbloom #define DMFL_UNIT(d) (minor(d)&0xF) /* up to 16 DMFs */ 10421955Sbloom 10521955Sbloom #define ASLP 1 /* waiting for interrupt from dmf */ 10621955Sbloom #define OPEN 2 /* line printer is open */ 10721955Sbloom #define ERROR 4 /* error while printing, driver 10821955Sbloom refuses to do anything till closed */ 10926910Skarels #define MOREIO 8 /* more data for printer */ 11021955Sbloom 1118778Sroot #ifndef lint 1128778Sroot int ndmf = NDMF*8; /* used by iostat */ 1138778Sroot #endif 1146940Ssam int dmfact; /* mask of active dmf's */ 1156940Ssam int dmfstart(), ttrstrt(); 1166940Ssam 1176940Ssam /* 118*30322Skarels * The clist space is mapped by one terminal driver onto each UNIBUS. 119*30322Skarels * The identity of the board which allocated resources is recorded, 120*30322Skarels * so the process may be repeated after UNIBUS resets. 1216940Ssam * The UBACVT macro converts a clist space address for unibus uban 1226940Ssam * into an i/o space address for the DMA routine. 1236940Ssam */ 124*30322Skarels int dmf_uballoc[NUBA]; /* which dmf (if any) allocated unibus map */ 125*30322Skarels int cbase[NUBA]; /* base address of clists in unibus map */ 1266940Ssam #define UBACVT(x, uban) (cbase[uban] + ((x)-(char *)cfree)) 12721955Sbloom char dmf_dma[NDMF*8]; 1286940Ssam 1296940Ssam /* 1306940Ssam * Routine for configuration to set dmf interrupt. 1316940Ssam */ 1326940Ssam /*ARGSUSED*/ 1336940Ssam dmfprobe(reg, ctlr) 1346940Ssam caddr_t reg; 13521955Sbloom struct uba_device *ctlr; 1366940Ssam { 1376940Ssam register int br, cvec; /* these are ``value-result'' */ 1386940Ssam register struct dmfdevice *dmfaddr = (struct dmfdevice *)reg; 13921955Sbloom register int i; 14021955Sbloom register unsigned int a; 14121955Sbloom static char *dmfdevs[]= 14221955Sbloom {"parallel","printer","synch","asynch"}; 14321955Sbloom unsigned int dmfoptions; 14425449Skarels static int (*intrv[3])() = { (int (*)())0, (int (*)())0, (int (*)())0 }; 1456940Ssam 1466940Ssam #ifdef lint 1476940Ssam br = 0; cvec = br; br = cvec; 1488808Sroot dmfxint(0); dmfrint(0); 14926366Skarels dmfsrint(); dmfsxint(); dmfdaint(); dmfdbint(); dmflint(0); 1506940Ssam #endif 15121955Sbloom /* 15221955Sbloom * Pick the usual size DMF vector here (don't decrement it here). 15321955Sbloom * grab configuration; note that the DMF32 15421955Sbloom * doesn't seem to put the right bits in this 15521955Sbloom * register until AFTER the interrupt vector is set. 15621955Sbloom */ 1576940Ssam br = 0x15; 15821955Sbloom cvec = (uba_hd[numuba].uh_lastiv - 4*8); 15925449Skarels dmfaddr->dmfccsr0 = (cvec >> 2); 16021955Sbloom dmfoptions = dmfaddr->dmfccsr0 & DMFC_CONFMASK; 16121955Sbloom 16221955Sbloom /* catch a couple of special cases: Able vmz/32n and vmz/lp */ 16321955Sbloom if (dmfoptions == DMFC_ASYNC) { 16425449Skarels /* Async portion only */ 16525449Skarels 16625449Skarels cvec = (uba_hd[numuba].uh_lastiv -= 8); 16725449Skarels dmfaddr->dmfccsr0 = (cvec - 2*8) >> 2; 16825449Skarels intrv[0] = ctlr->ui_intr[4]; 16925449Skarels intrv[1] = ctlr->ui_intr[5]; 17025449Skarels ctlr->ui_intr = intrv; 17126312Skarels } else if (dmfoptions == DMFC_LP) { 17225449Skarels /* LP portion only */ 17321955Sbloom 17425449Skarels cvec = (uba_hd[numuba].uh_lastiv -= 8); 17525449Skarels ctlr->ui_intr = &ctlr->ui_intr[6]; 17626312Skarels } else if (dmfoptions == (DMFC_LP|DMFC_ASYNC)) { 17725449Skarels /* LP ans Async portions only */ 17825449Skarels 17925449Skarels cvec = (uba_hd[numuba].uh_lastiv -= 2*8); 18025449Skarels ctlr->ui_intr = &ctlr->ui_intr[4]; 18126312Skarels } else { 18225449Skarels /* All other configurations get everything */ 18321955Sbloom 18421955Sbloom cvec = (uba_hd[numuba].uh_lastiv -= 4*8); 18521955Sbloom } 18625449Skarels a = (dmfoptions >> 12) & 0xf; 18725449Skarels printf("dmf%d:", ctlr->ui_unit); 18826312Skarels for (i = 0; a != 0; ++i, a >>= 1) { 18926312Skarels if (a & 1) 19025449Skarels printf(" %s",dmfdevs[i]); 19125449Skarels } 19225449Skarels printf(".\n"); 19321955Sbloom 19421955Sbloom if (dmfoptions & DMFC_LP) 19527057Skarels dmfaddr->dmfl_ctrl = DMFL_RESET; 1967412Skre return (sizeof (struct dmfdevice)); 1976940Ssam } 1986940Ssam 1996940Ssam /* 2006940Ssam * Routine called to attach a dmf. 2016940Ssam */ 2026940Ssam dmfattach(ui) 2036940Ssam struct uba_device *ui; 2046940Ssam { 20521955Sbloom register int cols = (ui->ui_flags>>8) & 0xff; 20621955Sbloom register int lines = (ui->ui_flags>>16) & 0xff; 2076940Ssam 20821955Sbloom dmfsoftCAR[ui->ui_unit] = ui->ui_flags & 0xff; 20927052Skarels dmfl_softc[ui->ui_unit].dmfl_cols = cols == 0 ? DMFL_DEFCOLS : cols; 21027052Skarels dmfl_softc[ui->ui_unit].dmfl_lines = lines == 0 ? DMFL_DEFLINES : lines; 21126910Skarels if ((ui->ui_flags >> 24) & 0x1) 21226910Skarels dmfl_softc[ui->ui_unit].dmfl_format = (2 << 8); 21326910Skarels else 21426910Skarels dmfl_softc[ui->ui_unit].dmfl_format = (2 << 8) | DMFL_FORMAT; 21526221Skarels cbase[ui->ui_ubanum] = -1; 216*30322Skarels dmf_uballoc[ui->ui_unit] = -1; 2176940Ssam } 2186940Ssam 2196940Ssam 2206940Ssam /* 2216940Ssam * Open a DMF32 line, mapping the clist onto the uba if this 2226940Ssam * is the first dmf on this uba. Turn on this dmf if this is 2236940Ssam * the first use of it. 2246940Ssam */ 2256940Ssam /*ARGSUSED*/ 2266940Ssam dmfopen(dev, flag) 2276940Ssam dev_t dev; 2286940Ssam { 2296940Ssam register struct tty *tp; 2306940Ssam register int unit, dmf; 2316940Ssam register struct dmfdevice *addr; 2326940Ssam register struct uba_device *ui; 2336940Ssam int s; 2346940Ssam 2356940Ssam unit = minor(dev); 23626312Skarels if (unit & 0200) 23726312Skarels return (dmflopen(dev,flag)); 2386940Ssam dmf = unit >> 3; 2398567Sroot if (unit >= NDMF*8 || (ui = dmfinfo[dmf])== 0 || ui->ui_alive == 0) 2408567Sroot return (ENXIO); 2416940Ssam tp = &dmf_tty[unit]; 2428567Sroot if (tp->t_state&TS_XCLUDE && u.u_uid!=0) 2438567Sroot return (EBUSY); 2446940Ssam addr = (struct dmfdevice *)ui->ui_addr; 2456940Ssam tp->t_addr = (caddr_t)addr; 2466940Ssam tp->t_oproc = dmfstart; 2476971Ssam tp->t_state |= TS_WOPEN; 2486940Ssam /* 2496940Ssam * While setting up state for this uba and this dmf, 2506940Ssam * block uba resets which can clear the state. 2516940Ssam */ 25221955Sbloom s = spltty(); 25326221Skarels if (cbase[ui->ui_ubanum] == -1) { 254*30322Skarels dmf_uballoc[ui->ui_ubanum] = dmf; 255*30322Skarels cbase[ui->ui_ubanum] = UBAI_ADDR(uballoc(ui->ui_ubanum, 256*30322Skarels (caddr_t)cfree, nclist*sizeof(struct cblock), 0)); 2576940Ssam } 2586940Ssam if ((dmfact&(1<<dmf)) == 0) { 2596940Ssam addr->dmfcsr |= DMF_IE; 2606940Ssam dmfact |= (1<<dmf); 26121955Sbloom addr->dmfrsp = dmf_timeout; 2626940Ssam } 2636940Ssam splx(s); 2646940Ssam /* 26526910Skarels * If this is first open, initialize tty state to default. 2666940Ssam */ 2676971Ssam if ((tp->t_state&TS_ISOPEN) == 0) { 2686940Ssam ttychars(tp); 26927052Skarels #ifndef PORTSELECTOR 27026910Skarels if (tp->t_ispeed == 0) { 27127052Skarels #else 27227052Skarels tp->t_state |= TS_HUPCLS; 27327052Skarels #endif PORTSELECTOR 27426910Skarels tp->t_ispeed = ISPEED; 27526910Skarels tp->t_ospeed = ISPEED; 27626910Skarels tp->t_flags = IFLAGS; 27727052Skarels #ifndef PORTSELECTOR 27826910Skarels } 27927052Skarels #endif PORTSELECTOR 2806940Ssam dmfparam(unit); 2816940Ssam } 2826940Ssam /* 2836940Ssam * Wait for carrier, then process line discipline specific open. 2846940Ssam */ 28521955Sbloom s = spltty(); 28626910Skarels for (;;) { 28726910Skarels if ((dmfmctl(dev, DMF_ON, DMSET) & (DMF_CAR<<8)) || 28826910Skarels (dmfsoftCAR[dmf] & (1<<(unit&07)))) 28926910Skarels tp->t_state |= TS_CARR_ON; 29026910Skarels if (tp->t_state & TS_CARR_ON) 29126910Skarels break; 2926971Ssam tp->t_state |= TS_WOPEN; 2936940Ssam sleep((caddr_t)&tp->t_rawq, TTIPRI); 2946940Ssam } 2956940Ssam splx(s); 2968567Sroot return ((*linesw[tp->t_line].l_open)(dev, tp)); 2976940Ssam } 2986940Ssam 2996940Ssam /* 3006940Ssam * Close a DMF32 line. 3016940Ssam */ 3026940Ssam /*ARGSUSED*/ 3036940Ssam dmfclose(dev, flag) 3046940Ssam dev_t dev; 3056940Ssam int flag; 3066940Ssam { 3076940Ssam register struct tty *tp; 3086940Ssam register unit; 3096940Ssam 3106940Ssam unit = minor(dev); 31126312Skarels if (unit & 0200) { 31226312Skarels dmflclose(dev,flag); 31326312Skarels return; 31426312Skarels } 31521955Sbloom 3166940Ssam tp = &dmf_tty[unit]; 3176940Ssam (*linesw[tp->t_line].l_close)(tp); 3188702Sroot (void) dmfmctl(unit, DMF_BRK, DMBIC); 3196971Ssam if (tp->t_state&TS_HUPCLS || (tp->t_state&TS_ISOPEN)==0) 3208702Sroot (void) dmfmctl(unit, DMF_OFF, DMSET); 3216940Ssam ttyclose(tp); 3226940Ssam } 3236940Ssam 3247726Sroot dmfread(dev, uio) 3256940Ssam dev_t dev; 3267726Sroot struct uio *uio; 3276940Ssam { 3286940Ssam register struct tty *tp; 3296940Ssam 33026312Skarels if (minor(dev) & 0200) 33121955Sbloom return(ENXIO); 3326940Ssam tp = &dmf_tty[minor(dev)]; 3337726Sroot return ((*linesw[tp->t_line].l_read)(tp, uio)); 3346940Ssam } 3356940Ssam 3367832Sroot dmfwrite(dev, uio) 3376940Ssam dev_t dev; 3387832Sroot struct uio *uio; 3396940Ssam { 3406940Ssam register struct tty *tp; 3416940Ssam 34226312Skarels if (minor(dev) & 0200) 34326312Skarels return (dmflwrite(dev,uio)); 3446940Ssam tp = &dmf_tty[minor(dev)]; 3458530Sroot return ((*linesw[tp->t_line].l_write)(tp, uio)); 3466940Ssam } 3476940Ssam 3486940Ssam /* 3496940Ssam * DMF32 receiver interrupt. 3506940Ssam */ 3516940Ssam dmfrint(dmf) 3526940Ssam int dmf; 3536940Ssam { 3546940Ssam register c; 35526312Skarels register struct tty *tp; 3566940Ssam register struct dmfdevice *addr; 3576940Ssam register struct tty *tp0; 35821955Sbloom int unit; 35925449Skarels int overrun = 0; 36026312Skarels register struct uba_device *ui; 3616940Ssam 36226312Skarels ui = dmfinfo[dmf]; 36326312Skarels if (ui == 0 || ui->ui_alive == 0) 36426312Skarels return; 36526312Skarels addr = (struct dmfdevice *)ui->ui_addr; 36621955Sbloom tp0 = &dmf_tty[dmf * 8]; 3676940Ssam /* 3686940Ssam * Loop fetching characters from the silo for this 3696940Ssam * dmf until there are no more in the silo. 3706940Ssam */ 3716940Ssam while ((c = addr->dmfrbuf) < 0) { 37221955Sbloom 37321955Sbloom unit = (c >> 8) & 07; 37421955Sbloom tp = tp0 + unit; 3756940Ssam if (c & DMF_DSC) { 37621955Sbloom addr->dmfcsr = DMF_IE | DMFIR_TBUF | unit; 37725449Skarels if (addr->dmfrms & DMF_CAR) 37825449Skarels (void)(*linesw[tp->t_line].l_modem)(tp, 1); 37926312Skarels else if ((dmfsoftCAR[dmf] & (1 << unit)) == 0 && 38025449Skarels (*linesw[tp->t_line].l_modem)(tp, 0) == 0) { 38125449Skarels addr->dmfcsr = DMF_IE | DMFIR_LCR | unit; 38225449Skarels addr->dmflctms = DMFLCR_ENA; 3836940Ssam } 3846940Ssam continue; 3856940Ssam } 38626312Skarels if ((tp->t_state&TS_ISOPEN) == 0) { 38725449Skarels wakeup((caddr_t)&tp->t_rawq); 38825449Skarels #ifdef PORTSELECTOR 38926312Skarels if ((tp->t_state & TS_WOPEN) == 0) 39025449Skarels #endif 39125449Skarels continue; 3926940Ssam } 39321956Sbloom if (c & (DMF_PE|DMF_DO|DMF_FE)) { 39421955Sbloom if (c & DMF_PE) 39526312Skarels if ((tp->t_flags & (EVENP|ODDP)) == EVENP 39626312Skarels || (tp->t_flags & (EVENP|ODDP)) == ODDP) 39721955Sbloom continue; 39821955Sbloom if ((c & DMF_DO) && overrun == 0) { 39924842Seric log(LOG_WARNING, "dmf%d: silo overflow\n", dmf); 40021955Sbloom overrun = 1; 40121955Sbloom } 40221955Sbloom if (c & DMF_FE) 40321955Sbloom /* 40421955Sbloom * At framing error (break) generate 40521955Sbloom * a null (in raw mode, for getty), or a 40621955Sbloom * interrupt (in cooked/cbreak mode). 40721955Sbloom */ 40826312Skarels if (tp->t_flags & RAW) 40921955Sbloom c = 0; 41021955Sbloom else 41121955Sbloom c = tp->t_intrc; 4126940Ssam } 4136940Ssam #if NBK > 0 4146940Ssam if (tp->t_line == NETLDISC) { 4156940Ssam c &= 0177; 4166940Ssam BKINPUT(c, tp); 4176940Ssam } else 4186940Ssam #endif 4196940Ssam (*linesw[tp->t_line].l_rint)(c, tp); 4206940Ssam } 4216940Ssam } 4226940Ssam 4236940Ssam /* 4246940Ssam * Ioctl for DMF32. 4256940Ssam */ 4266940Ssam /*ARGSUSED*/ 4277630Ssam dmfioctl(dev, cmd, data, flag) 4286940Ssam dev_t dev; 4297630Ssam caddr_t data; 4306940Ssam { 4316940Ssam register struct tty *tp; 4326940Ssam register int unit = minor(dev); 4338567Sroot int error; 4346940Ssam 43526312Skarels if (unit & 0200) 43621955Sbloom return (ENOTTY); 4376940Ssam tp = &dmf_tty[unit]; 4388567Sroot error = (*linesw[tp->t_line].l_ioctl)(tp, cmd, data, flag); 4398567Sroot if (error >= 0) 4408567Sroot return (error); 4418567Sroot error = ttioctl(tp, cmd, data, flag); 4428567Sroot if (error >= 0) { 44317562Sbloom if (cmd == TIOCSETP || cmd == TIOCSETN || cmd == TIOCLBIS || 44417562Sbloom cmd == TIOCLBIC || cmd == TIOCLSET) 4456940Ssam dmfparam(unit); 4468567Sroot return (error); 4478567Sroot } 4488567Sroot switch (cmd) { 4496940Ssam 4506940Ssam case TIOCSBRK: 4518702Sroot (void) dmfmctl(dev, DMF_BRK, DMBIS); 4526940Ssam break; 4537630Ssam 4546940Ssam case TIOCCBRK: 4558702Sroot (void) dmfmctl(dev, DMF_BRK, DMBIC); 4566940Ssam break; 4577630Ssam 4586940Ssam case TIOCSDTR: 4598702Sroot (void) dmfmctl(dev, DMF_DTR|DMF_RTS, DMBIS); 4606940Ssam break; 4617630Ssam 4626940Ssam case TIOCCDTR: 4638702Sroot (void) dmfmctl(dev, DMF_DTR|DMF_RTS, DMBIC); 4646940Ssam break; 4657630Ssam 4666940Ssam case TIOCMSET: 4678702Sroot (void) dmfmctl(dev, dmtodmf(*(int *)data), DMSET); 4686940Ssam break; 4697630Ssam 4706940Ssam case TIOCMBIS: 4718702Sroot (void) dmfmctl(dev, dmtodmf(*(int *)data), DMBIS); 4726940Ssam break; 4737630Ssam 4746940Ssam case TIOCMBIC: 4758702Sroot (void) dmfmctl(dev, dmtodmf(*(int *)data), DMBIC); 4766940Ssam break; 4777630Ssam 4786940Ssam case TIOCMGET: 4797630Ssam *(int *)data = dmftodm(dmfmctl(dev, 0, DMGET)); 4806940Ssam break; 4817630Ssam 4826940Ssam default: 4838567Sroot return (ENOTTY); 4846940Ssam } 4858567Sroot return (0); 4866940Ssam } 4876940Ssam 4886940Ssam dmtodmf(bits) 4896940Ssam register int bits; 4906940Ssam { 4916940Ssam register int b; 4926940Ssam 4936940Ssam b = bits & 012; 4946940Ssam if (bits & DML_ST) b |= DMF_RATE; 4956940Ssam if (bits & DML_RTS) b |= DMF_RTS; 4966940Ssam if (bits & DML_USR) b |= DMF_USRW; 4976940Ssam return(b); 4986940Ssam } 4996940Ssam 5006940Ssam dmftodm(bits) 5016940Ssam register int bits; 5026940Ssam { 5036940Ssam register int b; 5046940Ssam 5056940Ssam b = (bits & 012) | ((bits >> 7) & 0760) | DML_LE; 5066940Ssam if (bits & DMF_USRR) b |= DML_USR; 5076940Ssam if (bits & DMF_RTS) b |= DML_RTS; 5086940Ssam return(b); 5096940Ssam } 5106940Ssam 5116940Ssam 5126940Ssam /* 5136940Ssam * Set parameters from open or stty into the DMF hardware 5146940Ssam * registers. 5156940Ssam */ 5166940Ssam dmfparam(unit) 5176940Ssam register int unit; 5186940Ssam { 5196940Ssam register struct tty *tp; 5206940Ssam register struct dmfdevice *addr; 5216940Ssam register int lpar, lcr; 5226940Ssam int s; 5236940Ssam 5246940Ssam tp = &dmf_tty[unit]; 5256940Ssam addr = (struct dmfdevice *)tp->t_addr; 5266940Ssam /* 5276940Ssam * Block interrupts so parameters will be set 5286940Ssam * before the line interrupts. 5296940Ssam */ 53021955Sbloom s = spltty(); 5316940Ssam addr->dmfcsr = (unit&07) | DMFIR_LCR | DMF_IE; 5326940Ssam if ((tp->t_ispeed)==0) { 5336971Ssam tp->t_state |= TS_HUPCLS; 5348702Sroot (void) dmfmctl(unit, DMF_OFF, DMSET); 53525449Skarels splx(s); 5366940Ssam return; 5376940Ssam } 5386940Ssam lpar = (dmf_speeds[tp->t_ospeed]<<12) | (dmf_speeds[tp->t_ispeed]<<8); 5396940Ssam lcr = DMFLCR_ENA; 5406940Ssam if ((tp->t_ispeed) == B134) 5416940Ssam lpar |= BITS6|PENABLE; 54224270Slepreau else if (tp->t_flags & (RAW|LITOUT|PASS8)) 5436940Ssam lpar |= BITS8; 5446940Ssam else { 5456940Ssam lpar |= BITS7|PENABLE; 5466940Ssam /* CHECK FOR XON/XOFF AND SET lcr |= DMF_AUTOX; */ 5476940Ssam } 54812450Ssam if (tp->t_flags&EVENP) 54912450Ssam lpar |= EPAR; 5506940Ssam if ((tp->t_ospeed) == B110) 5516940Ssam lpar |= TWOSB; 5526940Ssam lpar |= (unit&07); 5536940Ssam addr->dmflpr = lpar; 55425654Skarels addr->dmflctms = (addr->dmflctms &~ 0xff) | lcr; 5556940Ssam splx(s); 5566940Ssam } 5576940Ssam 5586940Ssam /* 5596940Ssam * DMF32 transmitter interrupt. 5606940Ssam * Restart the idle line. 5616940Ssam */ 5626940Ssam dmfxint(dmf) 5636940Ssam int dmf; 5646940Ssam { 56526312Skarels int unit0 = dmf * 8; 56626312Skarels struct tty *tp0 = &dmf_tty[unit0]; 5676940Ssam register struct tty *tp; 5686940Ssam register struct dmfdevice *addr; 5696940Ssam register struct uba_device *ui; 57021955Sbloom register int t; 5716940Ssam short cntr; 5726940Ssam 5736940Ssam ui = dmfinfo[dmf]; 5746940Ssam addr = (struct dmfdevice *)ui->ui_addr; 5756940Ssam while ((t = addr->dmfcsr) & DMF_TI) { 57621955Sbloom if (t & DMF_NXM) 57721955Sbloom /* SHOULD RESTART OR SOMETHING... */ 57821955Sbloom printf("dmf%d: NXM line %d\n", dmf, t >> 8 & 7); 57921955Sbloom t = t >> 8 & 7; 58021955Sbloom tp = tp0 + t; 5816971Ssam tp->t_state &= ~TS_BUSY; 5826971Ssam if (tp->t_state&TS_FLUSH) 5836971Ssam tp->t_state &= ~TS_FLUSH; 58429549Skarels else if (dmf_dma[unit0 + t]) 58529549Skarels ndflush(&tp->t_outq, (int)dmf_dma[unit0 + t]); 58629549Skarels dmf_dma[unit0 + t] = 0; 5876940Ssam if (tp->t_line) 5886940Ssam (*linesw[tp->t_line].l_start)(tp); 5896940Ssam else 5906940Ssam dmfstart(tp); 5916940Ssam } 5926940Ssam } 5936940Ssam 5946940Ssam /* 5956940Ssam * Start (restart) transmission on the given DMF32 line. 5966940Ssam */ 5976940Ssam dmfstart(tp) 5986940Ssam register struct tty *tp; 5996940Ssam { 6006940Ssam register struct dmfdevice *addr; 6018607Sroot register int unit, nch; 6026940Ssam int s; 60321955Sbloom register int dmf; 6046940Ssam 6056940Ssam unit = minor(tp->t_dev); 60621955Sbloom dmf = unit >> 3; 6076940Ssam unit &= 07; 6086940Ssam addr = (struct dmfdevice *)tp->t_addr; 6096940Ssam 6106940Ssam /* 6116940Ssam * Must hold interrupts in following code to prevent 6126940Ssam * state of the tp from changing. 6136940Ssam */ 61421955Sbloom s = spltty(); 6156940Ssam /* 6166940Ssam * If it's currently active, or delaying, no need to do anything. 6176940Ssam */ 6186971Ssam if (tp->t_state&(TS_TIMEOUT|TS_BUSY|TS_TTSTOP)) 6196940Ssam goto out; 6206940Ssam /* 6216940Ssam * If there are still characters in the silo, 6226940Ssam * just reenable the transmitter. 6236940Ssam */ 6246940Ssam addr->dmfcsr = DMF_IE | DMFIR_TBUF | unit; 6256940Ssam if (addr->dmftsc) { 6266940Ssam addr->dmfcsr = DMF_IE | DMFIR_LCR | unit; 62725449Skarels addr->dmflctms = addr->dmflctms | DMF_TE; 6286971Ssam tp->t_state |= TS_BUSY; 6296940Ssam goto out; 6306940Ssam } 6316940Ssam /* 6326940Ssam * If there are sleepers, and output has drained below low 6336940Ssam * water mark, wake up the sleepers. 6346940Ssam */ 63521955Sbloom if (tp->t_outq.c_cc<=TTLOWAT(tp)) { 63621955Sbloom if (tp->t_state&TS_ASLEEP) { 63721955Sbloom tp->t_state &= ~TS_ASLEEP; 63821955Sbloom wakeup((caddr_t)&tp->t_outq); 63921955Sbloom } 64021955Sbloom if (tp->t_wsel) { 64121955Sbloom selwakeup(tp->t_wsel, tp->t_state & TS_WCOLL); 64221955Sbloom tp->t_wsel = 0; 64321955Sbloom tp->t_state &= ~TS_WCOLL; 64421955Sbloom } 6456940Ssam } 6466940Ssam /* 6476940Ssam * Now restart transmission unless the output queue is 6486940Ssam * empty. 6496940Ssam */ 6506940Ssam if (tp->t_outq.c_cc == 0) 6516940Ssam goto out; 6529550Ssam if (tp->t_flags & (RAW|LITOUT)) 6536940Ssam nch = ndqb(&tp->t_outq, 0); 6546940Ssam else { 65521955Sbloom if ((nch = ndqb(&tp->t_outq, 0200)) == 0) { 65621955Sbloom /* 65721955Sbloom * If first thing on queue is a delay process it. 65821955Sbloom */ 6596940Ssam nch = getc(&tp->t_outq); 6606940Ssam timeout(ttrstrt, (caddr_t)tp, (nch&0x7f)+6); 6616971Ssam tp->t_state |= TS_TIMEOUT; 6626940Ssam goto out; 6636940Ssam } 6646940Ssam } 6656940Ssam /* 6666940Ssam * If characters to transmit, restart transmission. 6676940Ssam */ 66821955Sbloom if (nch >= dmf_mindma) { 66921955Sbloom register car; 67021955Sbloom 67129549Skarels dmf_dma[minor(tp->t_dev)] = nch; 6726940Ssam addr->dmfcsr = DMF_IE | DMFIR_LCR | unit; 67325449Skarels addr->dmflctms = addr->dmflctms | DMF_TE; 6746940Ssam car = UBACVT(tp->t_outq.c_cf, dmfinfo[dmf]->ui_ubanum); 6756940Ssam addr->dmfcsr = DMF_IE | DMFIR_TBA | unit; 6766940Ssam addr->dmftba = car; 67721955Sbloom addr->dmftcc = ((car >> 2) & 0xc000) | nch; 67821955Sbloom tp->t_state |= TS_BUSY; 67921955Sbloom } else if (nch) { 6806940Ssam register char *cp = tp->t_outq.c_cf; 6816940Ssam register int i; 6826940Ssam 68321955Sbloom dmf_dma[minor(tp->t_dev)] = 0; 6846940Ssam nch = MIN(nch, DMF_SILOCNT); 6856940Ssam addr->dmfcsr = DMF_IE | DMFIR_LCR | unit; 68625449Skarels addr->dmflctms = addr->dmflctms | DMF_TE; 6876940Ssam addr->dmfcsr = DMF_IE | DMFIR_TBUF | unit; 6886940Ssam for (i = 0; i < nch; i++) 6896940Ssam addr->dmftbuf = *cp++; 6906940Ssam ndflush(&tp->t_outq, nch); 6916971Ssam tp->t_state |= TS_BUSY; 6926940Ssam } 6936940Ssam out: 6946940Ssam splx(s); 6956940Ssam } 6966940Ssam 6976940Ssam /* 6986940Ssam * Stop output on a line, e.g. for ^S/^Q or output flush. 6996940Ssam */ 7006940Ssam /*ARGSUSED*/ 7016940Ssam dmfstop(tp, flag) 7026940Ssam register struct tty *tp; 7036940Ssam { 7046940Ssam register struct dmfdevice *addr; 70521955Sbloom register unit = minor(tp->t_dev) & 7; 70621955Sbloom int s; 7076940Ssam 7086940Ssam addr = (struct dmfdevice *)tp->t_addr; 7096940Ssam /* 7106940Ssam * Block input/output interrupts while messing with state. 7116940Ssam */ 71221955Sbloom s = spltty(); 71321955Sbloom if (flag) { 71421955Sbloom addr->dmfcsr = DMF_IE | DMFIR_TBUF | unit; 71521955Sbloom if (addr->dmftsc) { 71621955Sbloom /* 71721955Sbloom * Flush regardless of whether we're transmitting 71821955Sbloom * (TS_BUSY), if the silo contains untransmitted 71921955Sbloom * characters. 72021955Sbloom */ 72121955Sbloom addr->dmfcsr = DMFIR_LCR | unit | DMF_IE; 72225449Skarels addr->dmflctms = addr->dmflctms | DMF_TE | DMF_FLUSH; 72321955Sbloom /* this will interrupt so let dmfxint handle the rest */ 72421955Sbloom tp->t_state |= TS_FLUSH|TS_BUSY; 72521955Sbloom } 72621955Sbloom } else { 72721955Sbloom if (tp->t_state & TS_BUSY) { 72821955Sbloom /* 72921955Sbloom * Stop transmission by disabling 73021955Sbloom * the transmitter. We'll pick up where we 73121955Sbloom * left off by reenabling in dmfstart. 73221955Sbloom */ 73321955Sbloom addr->dmfcsr = DMFIR_LCR | unit | DMF_IE; 73425449Skarels addr->dmflctms = addr->dmflctms &~ DMF_TE; 73521955Sbloom /* no interrupt here */ 7366971Ssam tp->t_state &= ~TS_BUSY; 73721955Sbloom } 7386940Ssam } 7396940Ssam splx(s); 7406940Ssam } 7416940Ssam 7426940Ssam /* 7436940Ssam * DMF32 modem control 7446940Ssam */ 7456940Ssam dmfmctl(dev, bits, how) 7466940Ssam dev_t dev; 7476940Ssam int bits, how; 7486940Ssam { 7496940Ssam register struct dmfdevice *dmfaddr; 7506940Ssam register int unit, mbits, lcr; 7516940Ssam int s; 7526940Ssam 7536940Ssam unit = minor(dev); 7546940Ssam dmfaddr = (struct dmfdevice *)(dmf_tty[unit].t_addr); 7556940Ssam unit &= 07; 75621955Sbloom s = spltty(); 7576940Ssam dmfaddr->dmfcsr = DMF_IE | DMFIR_TBUF | unit; 7586940Ssam mbits = dmfaddr->dmfrms << 8; 7596940Ssam dmfaddr->dmfcsr = DMF_IE | DMFIR_LCR | unit; 76025654Skarels lcr = dmfaddr->dmflctms; 76125449Skarels mbits |= (lcr & 0xff00) >> 8; 7626940Ssam switch (how) { 7636940Ssam case DMSET: 76412449Ssam mbits = (mbits &0xff00) | bits; 7656940Ssam break; 7666940Ssam 7676940Ssam case DMBIS: 7686940Ssam mbits |= bits; 7696940Ssam break; 7706940Ssam 7716940Ssam case DMBIC: 7726940Ssam mbits &= ~bits; 7736940Ssam break; 7746940Ssam 7756940Ssam case DMGET: 7766940Ssam (void) splx(s); 7776940Ssam return(mbits); 7786940Ssam } 7796940Ssam if (mbits & DMF_BRK) 7806940Ssam lcr |= DMF_RBRK; 7816940Ssam else 7826940Ssam lcr &= ~DMF_RBRK; 78325449Skarels dmfaddr->dmflctms = ((mbits & 037) << 8) | (lcr & 0xff); 7846940Ssam (void) splx(s); 7856940Ssam return(mbits); 7866940Ssam } 7876940Ssam 7886940Ssam /* 7896940Ssam * Reset state of driver if UBA reset was necessary. 7906940Ssam * Reset the csr, lpr, and lcr registers on open lines, and 7916940Ssam * restart transmitters. 7926940Ssam */ 7936940Ssam dmfreset(uban) 7946940Ssam int uban; 7956940Ssam { 7966940Ssam register int dmf, unit; 7976940Ssam register struct tty *tp; 7986940Ssam register struct uba_device *ui; 7996940Ssam register struct dmfdevice *addr; 8006940Ssam int i; 8016940Ssam 8026940Ssam for (dmf = 0; dmf < NDMF; dmf++) { 8036940Ssam ui = dmfinfo[dmf]; 8046940Ssam if (ui == 0 || ui->ui_alive == 0 || ui->ui_ubanum != uban) 8056940Ssam continue; 8066940Ssam printf(" dmf%d", dmf); 807*30322Skarels if (dmf_uballoc[uban] == dmf) { 808*30322Skarels int info; 809*30322Skarels 810*30322Skarels info = uballoc(uban, (caddr_t)cfree, 811*30322Skarels nclist * sizeof(struct cblock), UBA_CANTWAIT); 812*30322Skarels if (info) 813*30322Skarels cbase[uban] = UBAI_ADDR(info); 814*30322Skarels else { 815*30322Skarels printf(" [can't get uba map]"); 816*30322Skarels cbase[uban] = -1; 817*30322Skarels } 81825449Skarels } 8196940Ssam addr = (struct dmfdevice *)ui->ui_addr; 8206940Ssam addr->dmfcsr = DMF_IE; 82121955Sbloom addr->dmfrsp = dmf_timeout; 8226940Ssam unit = dmf * 8; 8236940Ssam for (i = 0; i < 8; i++) { 8246940Ssam tp = &dmf_tty[unit]; 8256971Ssam if (tp->t_state & (TS_ISOPEN|TS_WOPEN)) { 8266940Ssam dmfparam(unit); 8278702Sroot (void) dmfmctl(unit, DMF_ON, DMSET); 8286971Ssam tp->t_state &= ~TS_BUSY; 8296940Ssam dmfstart(tp); 8306940Ssam } 8316940Ssam unit++; 8326940Ssam } 8336940Ssam } 8346940Ssam } 8356940Ssam 83626312Skarels /* 83726312Skarels * dmflopen -- open the line printer port on a dmf32 83821955Sbloom */ 83926312Skarels /* ARGSUSED */ 84026312Skarels dmflopen(dev, flag) 84126312Skarels dev_t dev; 84226312Skarels int flag; 84321955Sbloom { 84421955Sbloom register int dmf; 84521955Sbloom register struct dmfl_softc *sc; 84621955Sbloom register struct uba_device *ui; 84721955Sbloom register struct dmfdevice *addr; 84821955Sbloom 84926312Skarels dmf = DMFL_UNIT(dev); 85026910Skarels if (dmf >= NDMF || (ui = dmfinfo[dmf]) == 0 || ui->ui_alive == 0) 85126910Skarels return (ENXIO); 85226910Skarels sc = &dmfl_softc[dmf]; 85326910Skarels if (sc->dmfl_state & OPEN) 85426910Skarels return (EBUSY); 85521955Sbloom addr = (struct dmfdevice *)ui->ui_addr; 85626910Skarels if (addr->dmfl_ctrl & DMFL_OFFLINE) { 85726910Skarels #ifdef notdef 85826910Skarels log(LOG_WARNING, "dmf%d: line printer offline/jammed\n", 85926910Skarels dmf); 86026910Skarels #endif 86126312Skarels return (EIO); 86221955Sbloom } 86326910Skarels if ((addr->dmfl_ctrl & DMFL_CONV)) { 86426910Skarels log(LOG_WARNING, "dmf%d: line printer disconnected\n", dmf); 86526312Skarels return (EIO); 86621955Sbloom } 86721955Sbloom 86826910Skarels addr->dmfl_ctrl = 0; 86921955Sbloom sc->dmfl_state |= OPEN; 87026312Skarels return (0); 87121955Sbloom } 87221955Sbloom 87326312Skarels /* ARGSUSED */ 87426312Skarels dmflclose(dev, flag) 87526312Skarels dev_t dev; 87626312Skarels int flag; 87721955Sbloom { 87826910Skarels register int dmf = DMFL_UNIT(dev); 87921955Sbloom register struct dmfl_softc *sc = &dmfl_softc[dmf]; 88026910Skarels register struct uba_device *ui = dmfinfo[dmf]; 88121955Sbloom 88221955Sbloom sc->dmfl_state = 0; 88326312Skarels if (sc->dmfl_info != 0) 88426910Skarels ubarelse((int)ui->ui_ubanum, &sc->dmfl_info); 88521955Sbloom 88626910Skarels ((struct dmfdevice *)ui->ui_addr)->dmfl_ctrl = 0; 88721955Sbloom } 88821955Sbloom 88926312Skarels dmflwrite(dev, uio) 89026312Skarels dev_t dev; 89126312Skarels struct uio *uio; 89221955Sbloom { 89326366Skarels register int n; 89421955Sbloom register int error; 89521955Sbloom register struct dmfl_softc *sc; 89621955Sbloom 89721955Sbloom sc = &dmfl_softc[DMFL_UNIT(dev)]; 89826910Skarels if (sc->dmfl_state & ERROR) 89926910Skarels return (EIO); 90026910Skarels while (n = (unsigned)uio->uio_resid) { 90126910Skarels if (n > DMFL_BUFSIZ) { 90226910Skarels n = DMFL_BUFSIZ; 90326910Skarels sc->dmfl_state |= MOREIO; 90426910Skarels } else 90526910Skarels sc->dmfl_state &= ~MOREIO; 90626910Skarels if (error = uiomove(sc->dmfl_buf, (int)n, UIO_WRITE, uio)) 90726312Skarels return (error); 90826910Skarels if (error = dmflout(dev, sc->dmfl_buf, n)) 90926312Skarels return (error); 91021955Sbloom } 91126312Skarels return (0); 91221955Sbloom } 91321955Sbloom 91421955Sbloom 91526312Skarels /* 91626312Skarels * dmflout -- start io operation to dmf line printer 91721955Sbloom * cp is addr of buf of n chars to be sent. 91821955Sbloom * 91921955Sbloom * -- dmf will be put in formatted output mode, this will 92021955Sbloom * be selectable from an ioctl if the 92121955Sbloom * need ever arises. 92221955Sbloom */ 92326312Skarels dmflout(dev, cp, n) 92426312Skarels dev_t dev; 92526312Skarels char *cp; 92626312Skarels int n; 92721955Sbloom { 92821955Sbloom register struct dmfl_softc *sc; 92921955Sbloom register int dmf; 93021955Sbloom register struct uba_device *ui; 93121955Sbloom register struct dmfdevice *d; 93226910Skarels int s; 93321955Sbloom 93426312Skarels dmf = DMFL_UNIT(dev); 93526312Skarels sc = &dmfl_softc[dmf]; 93626312Skarels if (sc->dmfl_state & ERROR) 93726312Skarels return (EIO); 93826312Skarels ui = dmfinfo[dmf]; 93926312Skarels /* 94026312Skarels * allocate unibus resources, will be released when io 94126312Skarels * operation is done. 94221955Sbloom */ 94326910Skarels if (sc->dmfl_info == 0) 94426910Skarels sc->dmfl_info = uballoc(ui->ui_ubanum, cp, n, 0); 94526312Skarels d = (struct dmfdevice *)ui->ui_addr; 94626910Skarels d->dmfl_ctrl = sc->dmfl_format; /* indir reg 2 */ 94721955Sbloom /* indir reg auto increments on r/w */ 94821955Sbloom /* SO DON'T CHANGE THE ORDER OF THIS CODE */ 94926910Skarels d->dmfl_indrct = 0; /* prefix chars & num */ 95026910Skarels d->dmfl_indrct = 0; /* suffix chars & num */ 95126910Skarels d->dmfl_indrct = sc->dmfl_info; /* dma lo 16 bits addr */ 95226910Skarels d->dmfl_indrct = -n; /* number of chars */ 95321955Sbloom 95426910Skarels d->dmfl_indrct = ((sc->dmfl_info>>16)&3) | DMFL_OPTIONS; 95526910Skarels /* dma hi 2 bits addr */ 95626910Skarels d->dmfl_indrct = sc->dmfl_lines /* lines per page */ 95726910Skarels | (sc->dmfl_cols<<8); /* carriage width */ 95821955Sbloom sc->dmfl_state |= ASLP; 95926910Skarels s = spltty(); 96026910Skarels d->dmfl_ctrl |= DMFL_PEN | DMFL_IE; 96126312Skarels while (sc->dmfl_state & ASLP) { 96226910Skarels sleep(sc->dmfl_buf, PZERO + 8); 96326312Skarels while (sc->dmfl_state & ERROR) { 96426910Skarels timeout(dmflint, (caddr_t)dmf, 10 * hz); 96526910Skarels sleep((caddr_t)&sc->dmfl_state, PZERO + 8); 96621955Sbloom } 96721955Sbloom } 96826910Skarels splx(s); 96926312Skarels return (0); 97021955Sbloom } 97126312Skarels 97226312Skarels /* 97326312Skarels * dmflint -- handle an interrupt from the line printer part of the dmf32 97421955Sbloom */ 97521955Sbloom dmflint(dmf) 97626312Skarels int dmf; 97721955Sbloom { 97821955Sbloom register struct uba_device *ui; 97921955Sbloom register struct dmfl_softc *sc; 98021955Sbloom register struct dmfdevice *d; 98126910Skarels short dmfl_stats; 98221955Sbloom 98326312Skarels ui = dmfinfo[dmf]; 98426312Skarels sc = &dmfl_softc[dmf]; 98526312Skarels d = (struct dmfdevice *)ui->ui_addr; 98621955Sbloom 98726910Skarels d->dmfl_ctrl &= ~DMFL_IE; 98827057Skarels dmfl_stats = d->dmfl_ctrl; 98926312Skarels if (sc->dmfl_state & ERROR) { 99026910Skarels if ((dmfl_stats & DMFL_OFFLINE) == 0) 99121955Sbloom sc->dmfl_state &= ~ERROR; 99226366Skarels wakeup((caddr_t)&sc->dmfl_state); 99321955Sbloom return; 99421955Sbloom } 99526910Skarels if (dmfl_stats & DMFL_DMAERR) 99626910Skarels log(LOG_WARNING, "dmf%d: NXM\n", dmf); 99726910Skarels if (dmfl_stats & DMFL_OFFLINE) { 99826910Skarels log(LOG_WARNING, "dmf%d: printer error\n", dmf); 99921955Sbloom sc->dmfl_state |= ERROR; 100021955Sbloom } 100121955Sbloom #ifdef notdef 100226910Skarels if (dmfl_stats & DMFL_PDONE) { 100326910Skarels printf("bytes= %d\n", d->dmfl_indrct); 100426910Skarels printf("lines= %d\n", d->dmfl_indrct); 100526910Skarels } 100621955Sbloom #endif 100721955Sbloom sc->dmfl_state &= ~ASLP; 100826910Skarels wakeup((caddr_t)sc->dmfl_buf); 100926910Skarels if (sc->dmfl_info && (sc->dmfl_state & MOREIO) == 0) 101026312Skarels ubarelse(ui->ui_ubanum, &sc->dmfl_info); 101121955Sbloom } 101221955Sbloom 10136940Ssam /* stubs for interrupt routines for devices not yet supported */ 10146940Ssam 101526312Skarels dmfsrint() 101626312Skarels { 101726312Skarels printf("dmfsrint\n"); 101826312Skarels } 10196940Ssam 102026312Skarels dmfsxint() 102126312Skarels { 102226312Skarels printf("dmfsxint\n"); 102326312Skarels } 10246940Ssam 102526312Skarels dmfdaint() 102626312Skarels { 102726312Skarels printf("dmfdaint\n"); 102826312Skarels } 10296940Ssam 103026312Skarels dmfdbint() 103126312Skarels { 103226312Skarels printf("dmfdbint\n"); 103326312Skarels } 103426910Skarels #endif NDMF 1035