📄 dmb.c
字号:
/* * Reset state of driver if BI reset was necessary. * Reset the csr and lpr registers on open lines, and * restart transmitters. */dmbreset(binum) int binum; /* bi adapter that reset */{ register int dmb, unit; register struct tty *tp; register struct uba_device *ui; register struct dmb_device *addr; register int i; for (dmb = 0; dmb < nNDMB; dmb++) { ui = dmbinfo[dmb]; if (ui == 0 || ui->ui_alive == 0 || ui->ui_adpt != binum) continue; printf(" dmb%d", dmb); addr = (struct dmb_device *)ui->ui_addr; /* * Enable external vector */ DMB_LOCK(dmb); addr->dmb_biic.biic_int_ctrl |= BIIC_EXVEC; addr->dmb_acsr2 = (dmb_timeout << 16); /* 10 ms */ DMB_UNLOCK(dmb); unit = dmb * NUMLINES; for (i = 0; i < NUMLINES; i++) { tp = &dmb_tty[unit]; smp_lock(&tp->t_lk_tty,LK_RETRY); if (tp->t_state & (TS_ISOPEN|TS_WOPEN)) { DMB_LOCK(dmb); dmbparam(unit); /* resets lpr reg */ DMB_UNLOCK(dmb); tp->t_state &= ~TS_BUSY; dmbstart(tp); } smp_unlock(&tp->t_lk_tty); unit++; /* increment the line number */ } }}/* * dmblopen -- open the line printer port on a dmb32 *//*ARGSUSED*/dmblopen(dev,flag) dev_t dev; int flag;{ register int dmb; register struct dmbl_softc *sc; register struct uba_device *ui; register struct dmb_device *addr; register int s; dmb = minor(dev) & LINEMASK ; if (dmb >= nNDMB) return (ENXIO); ui = dmbinfo[dmb]; sc = &dmbl_softc[dmb]; if ((sc->dmbl_state & OPEN) || (ui == 0) || (ui->ui_alive == 0) || (dmb_lines[ui->ui_unit] != DMB_8_LINES)) { return(ENXIO); } addr = (struct dmb_device *)ui->ui_addr;# ifdef DEBUG if ((addr->dmb_pcsrhigh & DMB_PROFFLINE)) { printd("dmb%d: line printer offline/jammed\n", dmb); return(EIO); }# endif if ((addr->dmb_pcsrhigh & DMB_PRCONNECT) == 0) { printf("dmb%d: line printer disconnected\n", dmb); return(EIO); } /* * disable interrupts */ s = spltty(); DMB_LOCK(dmb); addr->dmb_pcsrlow = 0; sc->dmbl_state |= OPEN; DMB_UNLOCK(dmb); splx(s); return(0);}/*ARGSUSED*/dmblclose(dev,flag) dev_t dev; int flag;{ register int dmb; register struct dmbl_softc *sc; register int s; dmb = minor(dev) & LINEMASK; sc = &dmbl_softc[dmb]; s = spltty(); DMB_LOCK(dmb); /* If we're not waiting for something to complete, then go ahead and print the form feed. R. Craig Peterson */ if (!(sc->dmbl_state & ASLP)) dmblout(dev,"\f",1); sc->dmbl_state = 0; /* * disable interrupts */ ((struct dmb_device *)(dmbinfo[dmb]->ui_addr))->dmb_pcsrlow = 0; DMB_UNLOCK(dmb); splx(s); return(0);}dmblwrite(dev,uio) dev_t dev; struct uio *uio;{ register unsigned int n; register int error; register struct dmbl_softc *sc; register int s, dmb; dmb = minor(dev) & LINEMASK; sc = &dmbl_softc[dmb]; if (sc->dmbl_state & ERROR) return(EIO); while(n = min(DMBL_BUFSIZE,(unsigned)uio->uio_resid)) { if (error = uiomove(&sc->dmbl_buf[0],(int)n,UIO_WRITE,uio)) { printf("uio move error\n"); return(error); } s = spltty(); DMB_LOCK(dmb); error = dmblout(dev,&sc->dmbl_buf[0],n); DMB_UNLOCK(dmb); splx(s); if (error) return(error); } return(0);}/* * dmblout -- start io operation to dmb line printer * cp is addr of buf of n chars to be sent. * * -- dmb will NOT be put in formatted output mode, this will * be selectable from an ioctl if the * need ever arises. */dmblout(dev,cp,n) dev_t dev; char *cp; int n;{ register struct dmbl_softc *sc; register int dmb; register struct uba_device *ui; register struct dmb_device *addr; dmb = minor(dev) & LINEMASK; sc = &dmbl_softc[dmb]; if (sc->dmbl_state & ERROR) return(EIO); ui = dmbinfo[dmb]; addr = (struct dmb_device *)ui->ui_addr; addr->dmb_pbufad = (long) svtophy(cp); addr->dmb_pbufct = (n << DMB_PRCHARCT); addr->dmb_psiz = (sc->dmbl_lines << DMB_PRPAGE) | (sc->dmbl_cols); sc->dmbl_state |= ASLP; addr->dmb_pcsrlow = DMB_PRIE; addr->dmb_pctrl |= (DMB_PRSTART | DMB_PRPHYS); while(sc->dmbl_state & ASLP) { sleep_unlock((caddr_t)&sc->dmbl_buf[0],(PZERO+8),&lk_dmb[dmb]); spltty(); DMB_LOCK(dmb); while(sc->dmbl_state&ERROR) { timeout(dmblint,dmb,10*hz); sleep_unlock((caddr_t)&sc->dmbl_state,(PZERO+8), &lk_dmb[dmb]); spltty(); DMB_LOCK(dmb); } /*if (sc->dmbl_state&ERROR) return (EIO);*/ } return(0);}/* * dmblint -- handle an interrupt from the line printer part of the dmb32 */dmblint(dmb) register int dmb;{ register struct uba_device *ui; register struct dmbl_softc *sc; register struct dmb_device *addr; register int s; int post_wakeup = 0; ui = dmbinfo[dmb]; sc = &dmbl_softc[dmb]; addr = (struct dmb_device *)ui->ui_addr; s = spltty(); DMB_LOCK(dmb); addr->dmb_pcsrlow = 0; /* disable interrupts */ if (sc->dmbl_state & ERROR) {# ifdef DEBUG printd("dmb%d: intr while in error state\n", dmb);# endif if ((addr->dmb_pcsrhigh & DMB_PROFFLINE) == 0) sc->dmbl_state &= ~ERROR; post_wakeup = WAKEUP_STATE; goto dmbendlint; } if (addr->dmb_pctrl & DMB_PRERROR) printf("dmb%d: Printer DMA Error %x\n", dmb, ((addr->dmb_pctrl & DMB_PRERROR)>>16)); if (addr->dmb_pcsrhigh & DMB_PROFFLINE) {# ifdef DEBUG printd("dmb%d: printer offline\n", dmb);# endif sc->dmbl_state |= ERROR; }# ifdef DEBUG if (addr->dmb_pctrl & DMB_PRSTART) printd("DMB%d printer intr w/ DMA START still set\n", dmb); else { printd("bytes= %d\n", addr->dmb_pcar & DMB_PRCHAR); printd("lines= %d\n",addr->dmb_pcar & DMB_PRLINE); }# endif sc->dmbl_state &= ~ASLP; post_wakeup = WAKEUP_BUF;dmbendlint: DMB_UNLOCK(dmb); if (post_wakeup) { if (post_wakeup & WAKEUP_STATE) wakeup(&sc->dmbl_state); else wakeup(&sc->dmbl_buf[0]); } splx(s);}/* stub for synchronous device interrupt routine which is not supported */dmbsint() { printf("dmbsint\n"); }/* * Called from a timeout routine. */dmb_cd_drop(tp) register struct tty *tp;{ register struct dmb_device *addr; register int unit, dmb; int post_wakeup; unit = minor(tp->t_dev); dmb = unit >> LINEBITS; addr = (struct dmb_device *)tp->t_addr; DMB_LOCK(dmb); addr->dmb_acsr = DMB_IE | (unit&LINEMASK); if ((tp->t_state&TS_CARR_ON) && ((addr->dmb_lstatlow & DMB_DCD) == 0)) {# ifdef DEBUG printd("dmb_cd: no CD, tp=0x%x\n", tp);# endif dmb_tty_drop(tp,&post_wakeup); goto dmb_cd_end; } dmbmodem[unit] |= MODEM_CD;# ifdef DEBUG printd("dmb_cd: CD is up, tp=0x%x\n", tp);# endifdmb_cd_end: DMB_UNLOCK(dmb); if (post_wakeup) wakeup((caddr_t)&tp->t_rawq);}/* * dmb_dsr_check_timeout * * Re-acquire locks on the tty line and multiplexer board before checking * to see if the modem signals are present. If connection establishment * fails wakeup on the raw queue to allow another try. */dmb_dsr_check_timeout(tp) register struct tty *tp;{ register int s,dmb; int post_wakeup = 0; dmb = minor(tp->t_dev)>>LINEBITS; DMB_TTY_LOCK(tp,s); DMB_LOCK(dmb); dmb_dsr_check(tp,&post_wakeup); DMB_UNLOCK(dmb); DMB_TTY_UNLOCK(tp,s); if (post_wakeup) wakeup((caddr_t)&tp->t_rawq);}/* * dmb_dsr_check * * When initiating a modem connection you must first leave the line idle for * 500ms. If all the appropriate modem leads do not rise within 30 seconds * then throw in the towel. */dmb_dsr_check(tp,post_wakeup) register struct tty *tp; register int *post_wakeup;{ int unit; register struct dmb_device *addr; unit = minor(tp->t_dev); addr = (struct dmb_device *)tp->t_addr; /* * The line must remain dormant for the first 500ms. Now that the * time period has expired, look to see if the appropriate modem * signals have been asserted to establish the connection. */ if (dmbmodem[unit] & MODEM_DSR_START) { dmbmodem[unit] &= ~MODEM_DSR_START; addr->dmb_acsr = DMB_IE | (unit&LINEMASK); /* * If dmbdsr is set look for DSR|CTS|CD, otherwise look * for CD|CTS only. */ if (dmbdsr) { if ((addr->dmb_lstatlow & DMB_XMIT) == DMB_XMIT) dmb_start_tty(tp,post_wakeup); } else { if ((addr->dmb_lstatlow & DMB_NODSR) == DMB_NODSR) dmb_start_tty(tp,post_wakeup); } return; } /* * CD has not come up within the 30 second interval. Give up on * establishing this connection. */ if ((tp->t_state&TS_CARR_ON)==0) { dmb_tty_drop(tp,post_wakeup);# ifdef DEBUG printd("dmb_dsr: no carrier, tp=0x%x\n", tp);# endif }# ifdef DEBUG else printd("dmb_dsr: carrier is up, tp=0x%x\n", tp);# endif}/* * cd_down return 1 if carrier has been down for at least 2 secs. */dmb_cd_down(tp) register struct tty *tp;{ register int msecs; register int unit; unit = minor(tp->t_dev); msecs = 1000000 * (time.tv_sec - dmbtimestamp[unit].tv_sec) + (time.tv_usec - dmbtimestamp[unit].tv_usec); if (msecs > 2000000) return(1); else return(0);}/* * dmb_tty_drop * * Close down a modem line by deasserting DTR. Wakeup on rawq to allert * any processes which may be waiting for an open to succeed which has * timed out. */dmb_tty_drop(tp,post_wakeup) register struct tty *tp; register int *post_wakeup;{ register struct dmb_device *addr; register int unit; if (tp->t_flags&NOHANG) return; unit = minor(tp->t_dev); dmbmodem[unit] = MODEM_BADCALL; tp->t_state &= ~(TS_CARR_ON|TS_TTSTOP|TS_BUSY|TS_ISUSP); *post_wakeup = WAKEUP_RAWQ; gsignal(tp->t_pgrp, SIGHUP); gsignal(tp->t_pgrp, SIGCONT); addr = (struct dmb_device *)tp->t_addr; addr->dmb_acsr = DMB_IE | ((minor(tp->t_dev)) & LINEMASK); addr->dmb_lpr &= ~(DMB_DTR | DMB_RTS); /* turn off DTR & RTS */}/* * dmb_start_tty * * Mark line as usable after all modem control leads have been asserted. * Wakeup on rawq to allert processes which have been waiting for the open * to succeed. */dmb_start_tty(tp,post_wakeup) register struct tty *tp; register int *post_wakeup;{ register int unit = minor(tp->t_dev); unit = minor(tp->t_dev); tp->t_state &= ~TS_ONDELAY; tp->t_state |= TS_CARR_ON; if (dmbmodem[unit]&MODEM_DSR) untimeout(dmb_dsr_check_timeout, tp); dmbmodem[unit] |= MODEM_CD|MODEM_CTS|MODEM_DSR; dmbtimestamp[unit] = dmbzerotime; *post_wakeup = WAKEUP_RAWQ;}dmbbaudrate(speed)register int speed;{ if (dmb_valid_speeds & (1 << speed)) return(1); else return(0);}#endif
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -