?? dmb.c
字號:
printd("dmbattach: addr = 0x%x, flags = 0x%x, unit = %d\n", addr, ui->ui_flags, ui->ui_unit);# endif /* * ui_flags format: * DMB: 0-7 dmbsoftcar, 8-15 printer cols, 16-23 printer rows. * DHB: 0-15 dmbsoftcar * * Set soft carrier (local lines) & line printer characteristics */ if (dmb_lines[ui->ui_unit] == DMB_8_LINES) { dmbsoftCAR[ui->ui_unit] = ui->ui_flags & 0xff; dmbdefaultCAR[ui->ui_unit] = ui->ui_flags & 0xff; cols = (ui->ui_flags>>8) & 0xff; lines = (ui->ui_flags>>16) & 0xff; } else /* 16 line dhb device */ { dmbsoftCAR[ui->ui_unit] = ui->ui_flags & 0xffff; dmbdefaultCAR[ui->ui_unit] = ui->ui_flags & 0xffff; cols = (ui->ui_flags>>16) & 0xff; /* just in case ... */ lines = (ui->ui_flags>>24) & 0xff; } dmbl_softc[ui->ui_unit].dmbl_cols = (cols == 0?DMBL_DEFCOLS:cols); dmbl_softc[ui->ui_unit].dmbl_lines = (lines == 0?DMBL_DEFLINES:lines); /* * Initialize SMP locks. One lock per dmb board, and one tty lock * for each line on the board. Specify this driver as being MP safe. */ lockinit(&lk_dmb[ui->ui_unit], &lock_device15_d); for (i=0; i< NUMLINES ; i++) { tp = &dmb_tty[(ui->ui_unit * NUMLINES)+i]; lockinit(&tp->t_lk_tty, &lock_tty_d); tp->t_smp = 1; } }/* * Open a DMB32 line. * Turn on this dmb if this is the first use of it. *//*ARGSUSED*/dmbopen(dev, flag) dev_t dev; int flag;{ register struct tty *tp; register int unit, dmb; register struct dmb_device *addr; register struct uba_device *ui; int s,error; int inuse; /* hold state of inuse bit while blocked waiting for carr */ int post_wakeup = 0; unit = minor(dev); if (unit & 0200) return(dmblopen(dev,flag)); dmb = unit >> LINEBITS;# ifdef DEBUG printd("dmbopen: dev = 0x%x, flag = 0x%x, unit = 0x%x\n", dev, flag, unit);# endif if (unit >= ndmb || (ui = dmbinfo[dmb])== 0 || ui->ui_alive == 0) return (ENXIO); tp = &dmb_tty[unit]; DMB_TTY_LOCK(tp,s); if (tp->t_state&TS_XCLUDE && u.u_uid != 0) { DMB_TTY_UNLOCK(tp,s); return (EBUSY); } while (tp->t_state&TS_CLOSING) { /* let DTR stay down for awhile */ sleep_unlock((caddr_t)&tp->t_rawq, TTIPRI,&tp->t_lk_tty); DMB_TTY_LOCK(tp,s); } addr = (struct dmb_device *)ui->ui_addr; tp->t_addr = (caddr_t)addr; tp->t_oproc = dmbstart; tp->t_baudrate = dmbbaudrate; tp->t_state |= TS_WOPEN; DMB_LOCK(dmb); tty_def_open(tp, dev, flag, (dmbsoftCAR[dmb]&(1<<(unit&LINEMASK)))); if ((tp->t_state&TS_ISOPEN) == 0) { dmbmodem[unit] = MODEM_DSR_START; /* prevents spurious startups */ /* * Set the receive fifo timeout to this number of miliseconds. */ addr->dmb_acsr2 = (dmb_timeout << 16); } /* * Interrupts are enabled in dmbparam. */ dmbparam(unit); /* * Wait for carrier, then process line discipline specific open. */ addr->dmb_acsr = (unit & LINEMASK) | DMB_IE; /* line select */ addr->dmb_lpr |= (DMB_DTR | DMB_RTS); if (tp->t_cflag & CLOCAL) {# ifdef DEBUG printd("dmbopen: local, tp=0x%x\n", tp);# endif tp->t_state |= TS_CARR_ON; dmbmodem[unit] = MODEM_CTS|MODEM_CD|MODEM_DSR; } else if ((flag & (O_NDELAY|O_NONBLOCK)) == 0) { /* * DSR should not normally come up until DTR is asserted * However if TS_HUPCL is not set, it is * possible to get here with all modem signals * already asserted. Or we could be dealing with * a very slow modem and it has not deasserted DSR yet. * Interrupts are enabled earlier in dmbparam. * * If the DSR signal is being followed, wait at most * 30 seconds for CD, and don't transmit in the first * 500ms. Otherwise immediately look for CD|CTS. */ if (dmbdsr) { if (addr->dmb_lstatlow & DMB_DSR) {# ifdef DEBUG printd("dmbopen: modem, unit=%d\n", unit);# endif dmbmodem[unit] |= (MODEM_DSR_START|MODEM_DSR); tp->t_dev = dev; /* need it for timeouts */ timeout(dmb_dsr_check_timeout, tp, hz*30); timeout(dmb_dsr_check_timeout, tp, hz/2); } } else { dmbmodem[unit] |= (MODEM_DSR_START|MODEM_DSR); dmb_dsr_check(tp,&post_wakeup); } } DMB_UNLOCK(dmb); if (flag & (O_NDELAY|O_NONBLOCK)) tp->t_state |= TS_ONDELAY; else while ((tp->t_state & TS_CARR_ON) == 0) { tp->t_state |= TS_WOPEN; inuse = tp->t_state&TS_INUSE; sleep_unlock((caddr_t)&tp->t_rawq,TTIPRI,&tp->t_lk_tty); DMB_TTY_LOCK(tp,s); /* * See if wakeup was caused by a false start. */ if (dmbmodem[unit]&MODEM_BADCALL){ DMB_TTY_UNLOCK(tp,s); if (post_wakeup) wakeup((caddr_t)&tp->t_rawq); return(EWOULDBLOCK); } /* * If we opened "block if in use" and * the terminal was not in use at that time * but it became "in use" while we were * waiting for carrier then return. */ if ((flag & O_BLKINUSE) && (inuse==0) && (tp->t_state&TS_INUSE)) { DMB_TTY_UNLOCK(tp,s); if (post_wakeup) wakeup((caddr_t)&tp->t_rawq); return(EALREADY); } } /* * Set state bit to tell tty.c not to assign this line as the * controlling terminal for the process which opens this line. */ if ((flag & O_NOCTTY) && (u.u_procp->p_progenv == A_POSIX)) tp->t_state |= TS_ONOCTTY; error = (*linesw[tp->t_line].l_open)(dev, tp); DMB_TTY_UNLOCK(tp,s); if (post_wakeup) wakeup((caddr_t)&tp->t_rawq); return(error);}/* * Close a DMB32 line. *//*ARGSUSED*/dmbclose(dev, flag) dev_t dev; int flag;{ register struct tty *tp; register int unit; register int dmb; register struct dmb_device *addr; int post_wakeup = 0; int s; unit = minor(dev); if (unit & 0200){ dmblclose(dev,flag); return; } dmb = unit >> LINEBITS; tp = &dmb_tty[unit]; addr = (struct dmb_device *)tp->t_addr;# ifdef DEBUG printd("dmbclose: dev = 0x%x, flag = 0x%x, unit = 0x%x, addr = 0x%x\n", dev, flag, unit, addr);# endif DMB_TTY_LOCK(tp,s); if (tp->t_line) (*linesw[tp->t_line].l_close)(tp); DMB_LOCK(dmb); if ((tp->t_cflag&HUPCL) || (tp->t_state&TS_ISOPEN)==0) { addr->dmb_acsr = (unit & LINEMASK) | DMB_IE; addr->dmb_lpr &= ~(DMB_DTR | DMB_RTS); tp->t_state &= ~TS_CARR_ON; /* prevents recv intr. timeouts */ if ((tp->t_cflag & CLOCAL) == 0) { /* * Drop DTR for at least a half sec. if modem line */ tp->t_state |= TS_CLOSING; /* * Wait for DSR to drop */ addr = (struct dmb_device *)tp->t_addr; addr->dmb_acsr = DMB_IE | (unit&LINEMASK); /* * If the DSR signal is being followed, give the * modem at most 5 seconds to deassert it. */ if (dmbdsr && (addr->dmb_lstatlow & DMB_DSR)) { timeout(wakeup, (caddr_t) &tp->t_dev, 5*hz); DMB_UNLOCK(dmb); sleep_unlock((caddr_t)&tp->t_dev, PZERO-10, &tp->t_lk_tty); DMB_TTY_LOCK(tp,s); DMB_LOCK(dmb); } timeout(wakeup, (caddr_t) &tp->t_dev, hz/5); DMB_UNLOCK(dmb); sleep_unlock((caddr_t)&tp->t_dev, PZERO-10, &tp->t_lk_tty); DMB_TTY_LOCK(tp,s); DMB_LOCK(dmb); tp->t_state &= ~(TS_CLOSING); post_wakeup = WAKEUP_RAWQ; } addr->dmb_acsr = (unit & LINEMASK) | DMB_IE; addr->dmb_lpr &= ~DMB_RXENA; } dmbsoftCAR[dmb] &= ~(1<<(unit&LINEMASK)); dmbsoftCAR[dmb] |= (1<<(unit&LINEMASK)) & dmbdefaultCAR[dmb]; DMB_UNLOCK(dmb); ttyclose(tp); dmbmodem[unit] = 0; tty_def_close(tp); DMB_TTY_UNLOCK(tp,s); if (post_wakeup) wakeup((caddr_t)&tp->t_rawq);}dmbread(dev, uio) dev_t dev; struct uio *uio;{ register struct tty *tp; register int unit; unit = minor(dev); if (unit & 0200) /* read from lp device */ return(ENXIO); tp = &dmb_tty[unit]; return ((*linesw[tp->t_line].l_read)(tp, uio));}dmbwrite(dev, uio) dev_t dev; struct uio *uio;{ register int unit; register struct tty *tp; unit = minor(dev); if (unit & 0200) /* write to parallel port */ return(dmblwrite(dev,uio)); tp = &dmb_tty[unit]; return ((*linesw[tp->t_line].l_write)(tp, uio));}/* * DMB32 interrupts at one location with async interrupts. * Examine Transmitter Action bit in "tbuf" register to determine * if there is a transmit interrupt. * Examine Data Valid bit in "rbuf" register to determine * if there is a receive interrupt. */dmbaint(dmb) int dmb;{ register struct dmb_device *addr; register struct uba_device *ui; /* * The dmb is interrupting at ipl14. * For this reason an spltty is used to bump the ipl up to ipl15. */ spltty(); ui = dmbinfo[dmb]; addr = (struct dmb_device *)ui->ui_addr; if (addr->dmb_tbuf & DMB_TXACT) dmbxint(dmb); if (addr->dmb_rbuf & DMB_DATAVALID) dmbrint(dmb);}/* * DMB32 receiver interrupt. */dmbrint(dmb) int dmb;{ register struct tty *tp; register long c; register struct dmb_device *addr; struct tty *tp0; register struct uba_device *ui; register int line; register int flg; int overrun = 0; u_char *modem0, *modem; int modem_cont; int post_wakeup = 0; ui = dmbinfo[dmb]; if (ui == 0 || ui->ui_alive == 0) return; addr = (struct dmb_device *)ui->ui_addr; tp0 = &dmb_tty[dmb<<LINEBITS]; modem0 = &dmbmodem[dmb<<LINEBITS]; /* * Loop fetching characters from the receive fifo for this * dmb until there are no more in the fifo. * * First get a copy of the rbuf then make sure no other processor * is servicing this interrupt by seeing if the rbuf contents have * changed in the meantime. */ while ((c = addr->dmb_rbuf) < 0) { /* if c < 0 then data valid bit is set */ line = (c>>16)&LINEMASK; tp = tp0 + line; smp_lock(&tp->t_lk_tty,LK_RETRY); DMB_LOCK(dmb); if ((c = addr->dmb_rbuf) >= 0) { DMB_UNLOCK(dmb); smp_unlock(&tp->t_lk_tty); break; } if (line != (((addr->dmb_rbuf)>>16) & LINEMASK)) { DMB_UNLOCK(dmb); smp_unlock(&tp->t_lk_tty); continue; } addr->dmb_rbuf = 0; /* pop the fifo */ DMB_UNLOCK(dmb); flg = tp->t_iflag; modem = modem0 + line;# ifdef DEBUG printd10("dmbrint: tp = 0x%x, c = 0x%x\n", tp, c);# endif /* * Check for modem transitions */ if (c & DMB_NONCHAR) { if (c & DMB_DIAG) goto dmbrunlock; /* ignore diagnostic info */# ifdef DEBUG printd("dmbrint: modem change, line = %d, tp = 0x%x, c = 0x%x, lstat = 0x%x\n", line, tp, c, addr->dmb_lstatlow);# endif DEBUG if (tp->t_cflag & CLOCAL) goto dmbrunlock; DMB_LOCK(dmb); addr->dmb_acsr = (line | DMB_IE); modem_cont = 0; /* * Drop DTR immediately if DSR gone away. * If really an active close then do not * send signals. */ if ((addr->dmb_lstatlow & DMB_DSR) == 0) { if (tp->t_state&TS_CLOSING) { untimeout(wakeup, (caddr_t) &tp->t_dev); post_wakeup = WAKEUP_DEV;# ifdef DEBUG printd("dmbrint: dsr closing down, line=%d\n",line);# endif DEBUG DMB_UNLOCK(dmb); goto dmbrunlock; } if (tp->t_state & TS_CARR_ON) {# ifdef DEBUG printd("dmbrint: DSR drop, line = %d\n",line);# endif DEBUG /* * Drop line if DSR is being followed. */ if (dmbdsr) { dmb_tty_drop(tp,&post_wakeup); /* * Move continue here in order * to examine other transitions. */ DMB_UNLOCK(dmb); goto dmbrunlock; } } } /* * Check for transient CD drops. * Only drop DTR if CD is down for more than 2 secs. */ if (tp->t_state&TS_CARR_ON) if ((addr->dmb_lstatlow & DMB_DCD)==0) { if (*modem & MODEM_CD) { /* only start timer once */# ifdef DEBUG printd("dmbrint, cd_drop,line = %d\n",line);# endif DEBUG *modem &= ~MODEM_CD; dmbtimestamp[minor(tp->t_dev)] = time; timeout(dmb_cd_drop, tp, hz*dmbcdtime); modem_cont = 1; } } else /* * CD has come up again. * Stop timeout from occurring if set. * If interval is more than 2 secs then * drop DTR. */ if ((*modem & MODEM_CD)==0) { untimeout(dmb_cd_drop, tp); if (dmb_cd_down(tp)){ /* drop connection */ dmb_tty_drop(tp,&post_wakeup);
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -