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*45804Sbostic * @(#)dmf.c 7.13 (Berkeley) 12/16/90 723324Smckusick */ 86940Ssam 96940Ssam /* 106940Ssam * DMF32 driver 116940Ssam * 1221955Sbloom * 136940Ssam * TODO: 146940Ssam * test with modem 156940Ssam * load as much as possible into silo 166940Ssam * use auto XON/XOFF 176940Ssam * test reset code 186940Ssam */ 1930537Skarels #include "dmf.h" 2030537Skarels #if NDMF > 0 2130537Skarels 2230537Skarels #ifndef NDMF_LP 2330537Skarels #define NDMF_LP NDMF 2430537Skarels #endif NDMF_LP 25*45804Sbostic #include "../include/pte.h" 269772Ssam 27*45804Sbostic #include "sys/param.h" 2816063Skarels #include "uba.h" 29*45804Sbostic #include "sys/conf.h" 30*45804Sbostic #include "sys/user.h" 31*45804Sbostic #include "sys/proc.h" 32*45804Sbostic #include "sys/ioctl.h" 33*45804Sbostic #include "sys/tty.h" 34*45804Sbostic #include "sys/map.h" 35*45804Sbostic #include "sys/buf.h" 36*45804Sbostic #include "sys/vm.h" 37*45804Sbostic #include "sys/bkmac.h" 38*45804Sbostic #include "sys/clist.h" 39*45804Sbostic #include "sys/file.h" 40*45804Sbostic #include "sys/uio.h" 41*45804Sbostic #include "sys/kernel.h" 42*45804Sbostic #include "sys/syslog.h" 436940Ssam 4430537Skarels #include "dmx.h" 4517124Sbloom #include "ubareg.h" 4617124Sbloom #include "ubavar.h" 4730537Skarels #include "dmxreg.h" 4817124Sbloom #include "dmfreg.h" 4930537Skarels #include "dmreg.h" 508473Sroot 5130537Skarels extern int dmx_timeout; /* silo timeout, in ms */ 5230537Skarels int dmfstart(); 5330537Skarels 546940Ssam /* 5530537Skarels * The clist space is mapped by one terminal driver onto each UNIBUS. 5630537Skarels * The identity of the board which allocated resources is recorded, 5730537Skarels * so the process may be repeated after UNIBUS resets. 5830537Skarels * The UBACVT macro converts a clist space address for unibus uban 5930537Skarels * into an i/o space address for the DMA routine. 606940Ssam */ 6130537Skarels int dmf_uballoc[NUBA]; /* which dmf (if any) allocated unibus map */ 6230537Skarels int cbase[NUBA]; /* base address of clists in unibus map */ 6330537Skarels 6430537Skarels /* 6530537Skarels * Autoconfiguration and variables for DMF32 6630537Skarels */ 676940Ssam int dmfprobe(), dmfattach(), dmfrint(), dmfxint(); 6821955Sbloom int dmflint(); 696940Ssam struct uba_device *dmfinfo[NDMF]; 706940Ssam u_short dmfstd[] = { 0 }; 716940Ssam struct uba_driver dmfdriver = 726940Ssam { dmfprobe, 0, dmfattach, 0, dmfstd, "dmf", dmfinfo }; 736940Ssam 746940Ssam struct tty dmf_tty[NDMF*8]; 7530537Skarels struct dmx_softc dmf_softc[NDMF]; 768778Sroot #ifndef lint 778778Sroot int ndmf = NDMF*8; /* used by iostat */ 788778Sroot #endif 796940Ssam 806940Ssam /* 816940Ssam * Routine for configuration to set dmf interrupt. 826940Ssam */ 836940Ssam /*ARGSUSED*/ 846940Ssam dmfprobe(reg, ctlr) 856940Ssam caddr_t reg; 8621955Sbloom struct uba_device *ctlr; 876940Ssam { 886940Ssam register int br, cvec; /* these are ``value-result'' */ 896940Ssam register struct dmfdevice *dmfaddr = (struct dmfdevice *)reg; 9021955Sbloom register int i; 9121955Sbloom register unsigned int a; 9221955Sbloom static char *dmfdevs[]= 9321955Sbloom {"parallel","printer","synch","asynch"}; 9421955Sbloom unsigned int dmfoptions; 9525449Skarels static int (*intrv[3])() = { (int (*)())0, (int (*)())0, (int (*)())0 }; 966940Ssam 976940Ssam #ifdef lint 986940Ssam br = 0; cvec = br; br = cvec; 998808Sroot dmfxint(0); dmfrint(0); 10026366Skarels dmfsrint(); dmfsxint(); dmfdaint(); dmfdbint(); dmflint(0); 1016940Ssam #endif 10221955Sbloom /* 10321955Sbloom * Pick the usual size DMF vector here (don't decrement it here). 10421955Sbloom * grab configuration; note that the DMF32 10521955Sbloom * doesn't seem to put the right bits in this 10621955Sbloom * register until AFTER the interrupt vector is set. 10721955Sbloom */ 1086940Ssam br = 0x15; 10921955Sbloom cvec = (uba_hd[numuba].uh_lastiv - 4*8); 11025449Skarels dmfaddr->dmfccsr0 = (cvec >> 2); 11121955Sbloom dmfoptions = dmfaddr->dmfccsr0 & DMFC_CONFMASK; 11221955Sbloom 11321955Sbloom /* catch a couple of special cases: Able vmz/32n and vmz/lp */ 11421955Sbloom if (dmfoptions == DMFC_ASYNC) { 11525449Skarels /* Async portion only */ 11625449Skarels 11725449Skarels cvec = (uba_hd[numuba].uh_lastiv -= 8); 11825449Skarels dmfaddr->dmfccsr0 = (cvec - 2*8) >> 2; 11925449Skarels intrv[0] = ctlr->ui_intr[4]; 12025449Skarels intrv[1] = ctlr->ui_intr[5]; 12125449Skarels ctlr->ui_intr = intrv; 12226312Skarels } else if (dmfoptions == DMFC_LP) { 12325449Skarels /* LP portion only */ 12421955Sbloom 12525449Skarels cvec = (uba_hd[numuba].uh_lastiv -= 8); 12625449Skarels ctlr->ui_intr = &ctlr->ui_intr[6]; 12726312Skarels } else if (dmfoptions == (DMFC_LP|DMFC_ASYNC)) { 12830537Skarels /* LP and Async portions only */ 12925449Skarels 13025449Skarels cvec = (uba_hd[numuba].uh_lastiv -= 2*8); 13125449Skarels ctlr->ui_intr = &ctlr->ui_intr[4]; 13226312Skarels } else { 13325449Skarels /* All other configurations get everything */ 13421955Sbloom 13521955Sbloom cvec = (uba_hd[numuba].uh_lastiv -= 4*8); 13621955Sbloom } 13725449Skarels a = (dmfoptions >> 12) & 0xf; 13825449Skarels printf("dmf%d:", ctlr->ui_unit); 13926312Skarels for (i = 0; a != 0; ++i, a >>= 1) { 14026312Skarels if (a & 1) 14125449Skarels printf(" %s",dmfdevs[i]); 14225449Skarels } 14325449Skarels printf(".\n"); 14421955Sbloom 14521955Sbloom if (dmfoptions & DMFC_LP) 14627057Skarels dmfaddr->dmfl_ctrl = DMFL_RESET; 1477412Skre return (sizeof (struct dmfdevice)); 1486940Ssam } 1496940Ssam 1506940Ssam /* 1516940Ssam * Routine called to attach a dmf. 1526940Ssam */ 1536940Ssam dmfattach(ui) 15430537Skarels register struct uba_device *ui; 1556940Ssam { 15630537Skarels register struct dmx_softc *sc; 1576940Ssam 15830537Skarels sc = &dmf_softc[ui->ui_unit]; 15930537Skarels sc->dmx_type = 'f'; 16030537Skarels sc->dmx_unit = ui->ui_unit; 16130537Skarels sc->dmx_unit0 = 0; 16230537Skarels sc->dmx_ubanum = ui->ui_ubanum; 16330537Skarels sc->dmx_softCAR = ui->ui_flags & 0xff; 16430537Skarels sc->dmx_tty = &dmf_tty[ui->ui_unit * 8]; 16530537Skarels sc->dmx_octet = 16630537Skarels (struct dmx_octet *)&((struct dmfdevice *)ui->ui_addr)->dmfa; 16730537Skarels 16826221Skarels cbase[ui->ui_ubanum] = -1; 16936610Sbostic dmf_uballoc[ui->ui_ubanum] = -1; 17030537Skarels #if NDMF_LP > 0 17130537Skarels dmflattach(ui); 17230537Skarels #endif NDMF_LP 1736940Ssam } 1746940Ssam 1756940Ssam /* 1766940Ssam * Open a DMF32 line, mapping the clist onto the uba if this 1776940Ssam * is the first dmf on this uba. Turn on this dmf if this is 1786940Ssam * the first use of it. 1796940Ssam */ 1806940Ssam /*ARGSUSED*/ 1816940Ssam dmfopen(dev, flag) 1826940Ssam dev_t dev; 1836940Ssam { 1846940Ssam register struct tty *tp; 18530537Skarels register struct dmx_softc *sc; 18630537Skarels int unit, dmf; 1876940Ssam register struct dmfdevice *addr; 1886940Ssam register struct uba_device *ui; 1896940Ssam int s; 19039061Smarc int dmxparam(); 1916940Ssam 1926940Ssam unit = minor(dev); 19326312Skarels if (unit & 0200) 19426312Skarels return (dmflopen(dev,flag)); 1956940Ssam dmf = unit >> 3; 1968567Sroot if (unit >= NDMF*8 || (ui = dmfinfo[dmf])== 0 || ui->ui_alive == 0) 1978567Sroot return (ENXIO); 19830537Skarels 1996940Ssam tp = &dmf_tty[unit]; 20030537Skarels sc = &dmf_softc[dmf]; 2016940Ssam addr = (struct dmfdevice *)ui->ui_addr; 20230537Skarels tp->t_addr = (caddr_t)(&addr->dmfa); 2036940Ssam tp->t_oproc = dmfstart; 20430537Skarels tp->t_dev = dev; /* needed before dmxopen */ 20539061Smarc tp->t_param = dmxparam; 20630537Skarels 2076940Ssam /* 20830537Skarels * While setting up state for this uba, 2096940Ssam * block uba resets which can clear the state. 2106940Ssam */ 21130537Skarels s = spl6(); 21226221Skarels if (cbase[ui->ui_ubanum] == -1) { 21330322Skarels dmf_uballoc[ui->ui_ubanum] = dmf; 21430322Skarels cbase[ui->ui_ubanum] = UBAI_ADDR(uballoc(ui->ui_ubanum, 21530322Skarels (caddr_t)cfree, nclist*sizeof(struct cblock), 0)); 2166940Ssam } 2176940Ssam splx(s); 21830537Skarels 21939061Smarc return (dmxopen(tp, sc, flag)); 2206940Ssam } 2216940Ssam 2226940Ssam /* 2236940Ssam * Close a DMF32 line. 2246940Ssam */ 2256940Ssam /*ARGSUSED*/ 2266940Ssam dmfclose(dev, flag) 2276940Ssam dev_t dev; 2286940Ssam int flag; 2296940Ssam { 2306940Ssam register unit; 2316940Ssam 2326940Ssam unit = minor(dev); 23326312Skarels if (unit & 0200) { 23430537Skarels dmflclose(dev, flag); 23526312Skarels return; 23626312Skarels } 23740729Skarels return (dmxclose(&dmf_tty[unit])); 2386940Ssam } 2396940Ssam 24039061Smarc dmfread(dev, uio, flag) 2416940Ssam dev_t dev; 2427726Sroot struct uio *uio; 2436940Ssam { 2446940Ssam register struct tty *tp; 2456940Ssam 24626312Skarels if (minor(dev) & 0200) 24721955Sbloom return(ENXIO); 2486940Ssam tp = &dmf_tty[minor(dev)]; 24939061Smarc return ((*linesw[tp->t_line].l_read)(tp, uio, flag)); 2506940Ssam } 2516940Ssam 2527832Sroot dmfwrite(dev, uio) 2536940Ssam dev_t dev; 2547832Sroot struct uio *uio; 2556940Ssam { 2566940Ssam register struct tty *tp; 2576940Ssam 25826312Skarels if (minor(dev) & 0200) 25926312Skarels return (dmflwrite(dev,uio)); 2606940Ssam tp = &dmf_tty[minor(dev)]; 2618530Sroot return ((*linesw[tp->t_line].l_write)(tp, uio)); 2626940Ssam } 2636940Ssam 2646940Ssam /* 2656940Ssam * DMF32 receiver interrupt. 2666940Ssam */ 2676940Ssam dmfrint(dmf) 2686940Ssam int dmf; 2696940Ssam { 27030537Skarels struct uba_device *ui; 2716940Ssam 27226312Skarels ui = dmfinfo[dmf]; 27326312Skarels if (ui == 0 || ui->ui_alive == 0) 27426312Skarels return; 27530537Skarels dmxrint(&dmf_softc[dmf]); 2766940Ssam } 2776940Ssam 2786940Ssam /* 2796940Ssam * Ioctl for DMF32. 2806940Ssam */ 2817630Ssam dmfioctl(dev, cmd, data, flag) 2826940Ssam dev_t dev; 2837630Ssam caddr_t data; 2846940Ssam { 28530537Skarels int unit = minor(dev); 2866940Ssam 28726312Skarels if (unit & 0200) 28821955Sbloom return (ENOTTY); 28930537Skarels return (dmxioctl(&dmf_tty[unit], cmd, data, flag)); 2906940Ssam } 2916940Ssam 2926940Ssam /* 2936940Ssam * DMF32 transmitter interrupt. 2946940Ssam * Restart the idle line. 2956940Ssam */ 2966940Ssam dmfxint(dmf) 2976940Ssam int dmf; 2986940Ssam { 2996940Ssam 30030537Skarels dmxxint(&dmf_softc[dmf]); 3016940Ssam } 3026940Ssam 3036940Ssam /* 30430537Skarels * Start (restart) transmission on the given line. 3056940Ssam */ 3066940Ssam dmfstart(tp) 30730537Skarels struct tty *tp; 3086940Ssam { 3096940Ssam 31030537Skarels dmxstart(tp, &dmf_softc[minor(tp->t_dev) >> 3]); 3116940Ssam } 3126940Ssam 3136940Ssam /* 3146940Ssam * Stop output on a line, e.g. for ^S/^Q or output flush. 3156940Ssam */ 3166940Ssam dmfstop(tp, flag) 31730537Skarels struct tty *tp; 3186940Ssam { 3196940Ssam 32030537Skarels dmxstop(tp, &dmf_softc[minor(tp->t_dev) >> 3], flag); 3216940Ssam } 3226940Ssam 3236940Ssam /* 3246940Ssam * Reset state of driver if UBA reset was necessary. 3256940Ssam * Reset the csr, lpr, and lcr registers on open lines, and 3266940Ssam * restart transmitters. 3276940Ssam */ 3286940Ssam dmfreset(uban) 3296940Ssam int uban; 3306940Ssam { 33130537Skarels register int dmf; 3326940Ssam register struct tty *tp; 3336940Ssam register struct uba_device *ui; 3346940Ssam register struct dmfdevice *addr; 3356940Ssam int i; 3366940Ssam 3376940Ssam for (dmf = 0; dmf < NDMF; dmf++) { 3386940Ssam ui = dmfinfo[dmf]; 3396940Ssam if (ui == 0 || ui->ui_alive == 0 || ui->ui_ubanum != uban) 3406940Ssam continue; 3416940Ssam printf(" dmf%d", dmf); 34230322Skarels if (dmf_uballoc[uban] == dmf) { 34330322Skarels int info; 34430322Skarels 34530322Skarels info = uballoc(uban, (caddr_t)cfree, 34630322Skarels nclist * sizeof(struct cblock), UBA_CANTWAIT); 34730322Skarels if (info) 34830322Skarels cbase[uban] = UBAI_ADDR(info); 34930322Skarels else { 35030322Skarels printf(" [can't get uba map]"); 35130322Skarels cbase[uban] = -1; 35230322Skarels } 35325449Skarels } 3546940Ssam addr = (struct dmfdevice *)ui->ui_addr; 35530537Skarels addr->dmfa.csr = DMF_IE; 35630537Skarels addr->dmfa.rsp = dmx_timeout; 35730537Skarels tp = &dmf_tty[dmf * 8]; 35830537Skarels for (i = 0; i < 8; i++, tp++) { 3596971Ssam if (tp->t_state & (TS_ISOPEN|TS_WOPEN)) { 36039061Smarc dmxparam(tp, &tp->t_termios); 36130537Skarels (void) dmxmctl(tp, DMF_ON, DMSET); 3626971Ssam tp->t_state &= ~TS_BUSY; 3636940Ssam dmfstart(tp); 3646940Ssam } 3656940Ssam } 36630537Skarels #if NDMF_LP > 0 36730537Skarels dmflint(dmf); 36830537Skarels #endif 3696940Ssam } 3706940Ssam } 3716940Ssam 37230537Skarels #if NDMF_LP > 0 37326312Skarels /* 37430537Skarels * DMF32 line printer driver 37530537Skarels * 37630537Skarels * the line printer on dmfx is indicated by a minor device code of 128+x 37730537Skarels * 37830537Skarels * the flags field of the config file is interpreted like so: 37930537Skarels * bits meaning 38030537Skarels * ---- ------- 38130537Skarels * 0-7 soft carrier bits for ttys part of dmf32 38230537Skarels * 8-15 number of cols/line on the line printer 38330537Skarels * if 0, 132 will be used. 38430537Skarels * 16-23 number of lines/page on the line printer 38530537Skarels * if 0, 66 will be used. 38630537Skarels * 24 if 1 DO NOT use the auto format mode of the 38730537Skarels * line printer parallel port 38830537Skarels */ 38930537Skarels 39030537Skarels struct dmfl_softc { 39130537Skarels u_int dmfl_state; /* soft state bits */ 39230537Skarels int dmfl_info; /* uba info */ 39330537Skarels u_short dmfl_lines; /* lines per page (66 def.) */ 39430537Skarels u_short dmfl_cols; /* cols per line (132 def.) */ 39530537Skarels u_short dmfl_format; /* fflag for auto form feed */ 39630537Skarels char dmfl_buf[DMFL_BUFSIZ]; 39730537Skarels } dmfl_softc[NDMF]; 39830537Skarels 39930537Skarels /* 40030537Skarels * convert device number into DMF line printer unit number 40130537Skarels */ 40230537Skarels #define DMFL_UNIT(d) (minor(d) & 0xf) /* up to 16 DMFs */ 40330537Skarels 40430537Skarels #define ASLP 1 /* waiting for interrupt from dmf */ 40530537Skarels #define OPEN 2 /* line printer is open */ 40630537Skarels #define ERROR 4 /* error while printing, driver 40730537Skarels refuses to do anything till closed */ 40830537Skarels #define MOREIO 8 /* more data for printer */ 40930537Skarels 41030537Skarels /* 41130537Skarels * Attach printer portion of dmf. 41230537Skarels */ 41330537Skarels dmflattach(ui) 41430537Skarels register struct uba_device *ui; 41530537Skarels { 41630537Skarels register int unit = ui->ui_unit; 41730537Skarels register int cols = (ui->ui_flags>>8) & 0xff; 41830537Skarels register int lines = (ui->ui_flags>>16) & 0xff; 41930537Skarels register struct dmfl_softc *sc; 42030537Skarels 42130537Skarels sc = &dmfl_softc[unit]; 42230537Skarels sc->dmfl_cols = cols == 0 ? DMFL_DEFCOLS : cols; 42330537Skarels sc->dmfl_lines = lines == 0 ? DMFL_DEFLINES : lines; 42430537Skarels if ((ui->ui_flags >> 24) & 0x1) 42530537Skarels sc->dmfl_format = (2 << 8); 42630537Skarels else 42730537Skarels sc->dmfl_format = (2 << 8) | DMFL_FORMAT; 42830537Skarels } 42930537Skarels 43030537Skarels /* 43126312Skarels * dmflopen -- open the line printer port on a dmf32 43221955Sbloom */ 43326312Skarels /* ARGSUSED */ 43426312Skarels dmflopen(dev, flag) 43526312Skarels dev_t dev; 43626312Skarels int flag; 43721955Sbloom { 43821955Sbloom register int dmf; 43921955Sbloom register struct dmfl_softc *sc; 44021955Sbloom register struct uba_device *ui; 44121955Sbloom register struct dmfdevice *addr; 44221955Sbloom 44326312Skarels dmf = DMFL_UNIT(dev); 44426910Skarels if (dmf >= NDMF || (ui = dmfinfo[dmf]) == 0 || ui->ui_alive == 0) 44526910Skarels return (ENXIO); 44626910Skarels sc = &dmfl_softc[dmf]; 44726910Skarels if (sc->dmfl_state & OPEN) 44826910Skarels return (EBUSY); 44921955Sbloom addr = (struct dmfdevice *)ui->ui_addr; 45026910Skarels if (addr->dmfl_ctrl & DMFL_OFFLINE) { 45126910Skarels #ifdef notdef 45226910Skarels log(LOG_WARNING, "dmf%d: line printer offline/jammed\n", 45326910Skarels dmf); 45426910Skarels #endif 45526312Skarels return (EIO); 45621955Sbloom } 45726910Skarels if ((addr->dmfl_ctrl & DMFL_CONV)) { 45826910Skarels log(LOG_WARNING, "dmf%d: line printer disconnected\n", dmf); 45926312Skarels return (EIO); 46021955Sbloom } 46121955Sbloom 46226910Skarels addr->dmfl_ctrl = 0; 46321955Sbloom sc->dmfl_state |= OPEN; 46426312Skarels return (0); 46521955Sbloom } 46621955Sbloom 46726312Skarels /* ARGSUSED */ 46826312Skarels dmflclose(dev, flag) 46926312Skarels dev_t dev; 47026312Skarels int flag; 47121955Sbloom { 47226910Skarels register int dmf = DMFL_UNIT(dev); 47321955Sbloom register struct dmfl_softc *sc = &dmfl_softc[dmf]; 47426910Skarels register struct uba_device *ui = dmfinfo[dmf]; 47521955Sbloom 47621955Sbloom sc->dmfl_state = 0; 47726312Skarels if (sc->dmfl_info != 0) 47826910Skarels ubarelse((int)ui->ui_ubanum, &sc->dmfl_info); 47921955Sbloom 48026910Skarels ((struct dmfdevice *)ui->ui_addr)->dmfl_ctrl = 0; 48121955Sbloom } 48221955Sbloom 48326312Skarels dmflwrite(dev, uio) 48426312Skarels dev_t dev; 48526312Skarels struct uio *uio; 48621955Sbloom { 48726366Skarels register int n; 48821955Sbloom register int error; 48921955Sbloom register struct dmfl_softc *sc; 49021955Sbloom 49121955Sbloom sc = &dmfl_softc[DMFL_UNIT(dev)]; 49226910Skarels if (sc->dmfl_state & ERROR) 49326910Skarels return (EIO); 49426910Skarels while (n = (unsigned)uio->uio_resid) { 49526910Skarels if (n > DMFL_BUFSIZ) { 49626910Skarels n = DMFL_BUFSIZ; 49726910Skarels sc->dmfl_state |= MOREIO; 49826910Skarels } else 49926910Skarels sc->dmfl_state &= ~MOREIO; 50037765Smckusick if (error = uiomove(sc->dmfl_buf, (int)n, uio)) 50126312Skarels return (error); 50226910Skarels if (error = dmflout(dev, sc->dmfl_buf, n)) 50326312Skarels return (error); 50421955Sbloom } 50526312Skarels return (0); 50621955Sbloom } 50721955Sbloom 50821955Sbloom 50926312Skarels /* 51026312Skarels * dmflout -- start io operation to dmf line printer 51121955Sbloom * cp is addr of buf of n chars to be sent. 51221955Sbloom * 51321955Sbloom * -- dmf will be put in formatted output mode, this will 51421955Sbloom * be selectable from an ioctl if the 51521955Sbloom * need ever arises. 51621955Sbloom */ 51726312Skarels dmflout(dev, cp, n) 51826312Skarels dev_t dev; 51926312Skarels char *cp; 52026312Skarels int n; 52121955Sbloom { 52221955Sbloom register struct dmfl_softc *sc; 52321955Sbloom register int dmf; 52421955Sbloom register struct uba_device *ui; 52521955Sbloom register struct dmfdevice *d; 52640729Skarels int s, error; 52721955Sbloom 52826312Skarels dmf = DMFL_UNIT(dev); 52926312Skarels sc = &dmfl_softc[dmf]; 53026312Skarels if (sc->dmfl_state & ERROR) 53126312Skarels return (EIO); 53226312Skarels ui = dmfinfo[dmf]; 53326312Skarels /* 53426312Skarels * allocate unibus resources, will be released when io 53526312Skarels * operation is done. 53621955Sbloom */ 53726910Skarels if (sc->dmfl_info == 0) 53826910Skarels sc->dmfl_info = uballoc(ui->ui_ubanum, cp, n, 0); 53926312Skarels d = (struct dmfdevice *)ui->ui_addr; 54026910Skarels d->dmfl_ctrl = sc->dmfl_format; /* indir reg 2 */ 54121955Sbloom /* indir reg auto increments on r/w */ 54221955Sbloom /* SO DON'T CHANGE THE ORDER OF THIS CODE */ 54326910Skarels d->dmfl_indrct = 0; /* prefix chars & num */ 54426910Skarels d->dmfl_indrct = 0; /* suffix chars & num */ 54526910Skarels d->dmfl_indrct = sc->dmfl_info; /* dma lo 16 bits addr */ 54626910Skarels d->dmfl_indrct = -n; /* number of chars */ 54721955Sbloom 54826910Skarels d->dmfl_indrct = ((sc->dmfl_info>>16)&3) | DMFL_OPTIONS; 54926910Skarels /* dma hi 2 bits addr */ 55026910Skarels d->dmfl_indrct = sc->dmfl_lines /* lines per page */ 55126910Skarels | (sc->dmfl_cols<<8); /* carriage width */ 55221955Sbloom sc->dmfl_state |= ASLP; 55340729Skarels error = 0; 55426910Skarels s = spltty(); 55526910Skarels d->dmfl_ctrl |= DMFL_PEN | DMFL_IE; 55626312Skarels while (sc->dmfl_state & ASLP) { 55740729Skarels if (error = tsleep(sc->dmfl_buf, (PZERO + 8) | PCATCH, 55840729Skarels ttyout, 0)) 55940729Skarels break; 56026312Skarels while (sc->dmfl_state & ERROR) { 56126910Skarels timeout(dmflint, (caddr_t)dmf, 10 * hz); 56240729Skarels if (error = tsleep((caddr_t)&sc->dmfl_state, 56340729Skarels (PZERO + 8) | PCATCH, ttyout, 0)) 56440729Skarels goto out; 56521955Sbloom } 56621955Sbloom } 56740729Skarels out: 56826910Skarels splx(s); 56926312Skarels return (0); 57021955Sbloom } 57126312Skarels 57226312Skarels /* 57326312Skarels * dmflint -- handle an interrupt from the line printer part of the dmf32 57421955Sbloom */ 57521955Sbloom dmflint(dmf) 57626312Skarels int dmf; 57721955Sbloom { 57821955Sbloom register struct uba_device *ui; 57921955Sbloom register struct dmfl_softc *sc; 58021955Sbloom register struct dmfdevice *d; 58126910Skarels short dmfl_stats; 58221955Sbloom 58326312Skarels ui = dmfinfo[dmf]; 58426312Skarels sc = &dmfl_softc[dmf]; 58526312Skarels d = (struct dmfdevice *)ui->ui_addr; 58621955Sbloom 58726910Skarels d->dmfl_ctrl &= ~DMFL_IE; 58827057Skarels dmfl_stats = d->dmfl_ctrl; 58926312Skarels if (sc->dmfl_state & ERROR) { 59026910Skarels if ((dmfl_stats & DMFL_OFFLINE) == 0) 59121955Sbloom sc->dmfl_state &= ~ERROR; 59226366Skarels wakeup((caddr_t)&sc->dmfl_state); 59321955Sbloom return; 59421955Sbloom } 59526910Skarels if (dmfl_stats & DMFL_DMAERR) 59626910Skarels log(LOG_WARNING, "dmf%d: NXM\n", dmf); 59726910Skarels if (dmfl_stats & DMFL_OFFLINE) { 59826910Skarels log(LOG_WARNING, "dmf%d: printer error\n", dmf); 59921955Sbloom sc->dmfl_state |= ERROR; 60021955Sbloom } 60121955Sbloom #ifdef notdef 60226910Skarels if (dmfl_stats & DMFL_PDONE) { 60326910Skarels printf("bytes= %d\n", d->dmfl_indrct); 60426910Skarels printf("lines= %d\n", d->dmfl_indrct); 60526910Skarels } 60621955Sbloom #endif 60721955Sbloom sc->dmfl_state &= ~ASLP; 60826910Skarels wakeup((caddr_t)sc->dmfl_buf); 60926910Skarels if (sc->dmfl_info && (sc->dmfl_state & MOREIO) == 0) 61026312Skarels ubarelse(ui->ui_ubanum, &sc->dmfl_info); 61121955Sbloom } 61230537Skarels #endif NDMF_LP 61321955Sbloom 6146940Ssam /* stubs for interrupt routines for devices not yet supported */ 6156940Ssam 61626312Skarels dmfsrint() 61726312Skarels { 61826312Skarels printf("dmfsrint\n"); 61926312Skarels } 6206940Ssam 62126312Skarels dmfsxint() 62226312Skarels { 62326312Skarels printf("dmfsxint\n"); 62426312Skarels } 6256940Ssam 62626312Skarels dmfdaint() 62726312Skarels { 62826312Skarels printf("dmfdaint\n"); 62926312Skarels } 6306940Ssam 63126312Skarels dmfdbint() 63226312Skarels { 63326312Skarels printf("dmfdbint\n"); 63426312Skarels } 63526910Skarels #endif NDMF 636