📄 fas.c
字号:
done = FALSE; /* not done if we got an int */ old_recv_count = fip->recv_ring_cnt; do { /* read in all the characters from the FIFO */ if ((status = fas_inb (fip, LINE_STATUS_PORT)) & LS_RCV_INT) { if (!drop_mode && (fip->device_flags.i & DF_DEVICE_IS_NS16550A)) { /* Drop receiver trigger levels to make sure that we will see all received characters in all NS16550A. This prevents multiple interrupts if we receive characters on more than one unit. */ old_fip = fip; for (fip = fas_first_int_user [vect]; fip; fip = fip->next_int_user) { if ((fip->device_flags.i & DF_DEVICE_IS_NS16550A) && (fip != old_fip)) { fip->device_flags.s |= DF_NS16550A_DROP_MODE; fas_first_outb (fip, NS_FIFO_CTL_PORT, NS_FIFO_DROP_CMD); } } fip = old_fip; drop_mode = TRUE; } status = fas_rproc (fip, status); sysinfo.rcvint++; } /* Is it a transmitter empty int ? */ if ((status & LS_XMIT_AVAIL) && (fip->device_flags.i & DF_XMIT_BUSY)) { fip->device_flags.s &= ~DF_XMIT_BUSY; fas_xproc (fip); if (!(fip->device_flags.i & DF_XMIT_BUSY)) { fip->device_flags.s |= DF_GUARD_TIMEOUT; fip->tty->t_state |= TIMEOUT; fip->timeout_idx = timeout ( fas_timeout, fip, fas_ctimes [fip->cflag & CBAUD]); } sysinfo.xmtint++; } /* Has there been a polarity change on some of the modem lines ? */ if ((status = fas_inb (fip, MDM_STATUS_PORT)) & MS_ANY_DELTA) { /* Do special RING line handling. RING generates an int only on the trailing edge. */ status = (status & ~MS_RING_PRESENT) | (fip->new_msr & MS_RING_PRESENT); if (status & MS_RING_TEDGE)#if defined(FASI) fip->rings_detected++,#endif /* FASI */ status |= MS_RING_PRESENT; if ((status ^ fip->new_msr) & MS_ANY_PRESENT) { /* check for excessive modem status interrupts */ if (++fip->msi_cnt > (MAX_MSI_CNT / HZ) * (EVENT_TIME * HZ / 1000)) { fip->ier = IE_NONE; fas_outb (fip, INT_ENABLE_PORT, fip->ier); } /* check hw flow flags */ fas_fproc (fip, status); fip->new_msr = status; event_sched (fip, EF_DO_MPROC); } sysinfo.mdmint++;#if defined(FASI) fip->modem_status_events++;#endif /* FASI */ } } while (!(fas_inb (fip, INT_ID_PORT) & II_NO_INTS_PENDING)); /* schedule character transfer to UNIX buffer */ if (fip->recv_ring_cnt#if defined (HAVE_VPIX) && (((fip->iflag & DOSMODE) ? MAX_VPIX_FILL - MIN_READ_CHUNK : MAX_UNIX_FILL - MIN_READ_CHUNK) >= fip->tty->t_rawq.c_cc)#else && ((MAX_UNIX_FILL - MIN_READ_CHUNK) >= fip->tty->t_rawq.c_cc)#endif && !(fip->flow_flags.i & FF_RXFER_STOPPED)) { event_sched (fip, EF_DO_RXFER); } /* check input buffer high/low water marks */ if (fip->recv_ring_cnt != old_recv_count) fas_ihlw_check (fip); } } while (!done); /* clear the shared interrupt since we have scanned all of the ports that share this interrupt vector */ if (port = fas_int_ack_port [vect]) (void) outb (port, fas_int_ack [vect]); return (0);}/* hardware flow control interrupt handler */static voidfas_fproc (fip, mdm_status)register struct fas_info *fip;register uint mdm_status;{ /* Check the output flow control signals and set the state flag accordingly. */ if (!(~mdm_status & fip->flow.m.oc) || (~mdm_status & fip->flow.m.oe) || !(fip->flow_flags.i & FF_HWO_HANDSHAKE)) { if (fip->flow_flags.i & FF_HWO_STOPPED) { fip->flow_flags.s &= ~FF_HWO_STOPPED; fas_xproc (fip); } } else#if defined(FASI) fip->xmtr_hw_flow_count++, wakeup((caddr_t)&fip->device_flags.i),#endif /* FASI */ fip->flow_flags.s |= FF_HWO_STOPPED;}/* modem status handler */static voidfas_mproc (fip)register struct fas_info *fip;{ register struct tty *ttyp; register uint mdm_status; uint vpix_status; int old_level; ttyp = fip->tty; mdm_status = fip->new_msr; fip->new_msr &= ~MS_RING_PRESENT; /* Check the carrier detect signal and set the state flags accordingly. Also, if not in clocal mode, send SIGHUP on carrier loss and flush the buffers. */ if (!(fip->cflag & CLOCAL)) { if (!(~mdm_status & fip->modem.m.ca)) { ttyp->t_state |= CARR_ON; /* Unblock getty open only if it is ready to run. */ if ((ttyp->t_state & WOPEN) && (~fip->msr & fip->modem.m.ca))#if defined(FASI) {#endif (void) wakeup ((caddr_t) &ttyp->t_canq);#if defined(FASI) (void)wakeup((caddr_t)&fip->device_flags.i); }#endif } else { if (!(~fip->msr & fip->modem.m.ca)) { ttyp->t_state &= ~CARR_ON; old_level = SPLWRK (); if (ttyp->t_state & ISOPEN) (void) signal (ttyp->t_pgrp, SIGHUP); (void) ttyflush (ttyp, FREAD | FWRITE); (void) splx (old_level); } } }#if defined (HAVE_VPIX) if (((fip->iflag & (DOSMODE | PARMRK)) == (DOSMODE | PARMRK)) && (fip->v86_intmask != V86VI_KBD)) { /* prepare status bits for VP/ix */ vpix_status = (((mdm_status ^ fip->msr) >> 4) & MS_ANY_DELTA) | (mdm_status & (MS_CTS_PRESENT | MS_DSR_PRESENT | MS_DCD_PRESENT)); if (fip->flow_flags.i & FF_HWO_HANDSHAKE) { vpix_status &= ~((fip->flow.m.oc | fip->flow.m.oe) >> 4); vpix_status |= fip->flow.m.oc | fip->flow.m.oe; } /* send status bits to VP/ix */ if ((vpix_status & MS_ANY_DELTA) && fas_vpix_sr (fip, 2, vpix_status)) event_sched (fip, EF_DO_RXFER); }#endif fip->msr = mdm_status & ~MS_RING_PRESENT; /* re-schedule if modem status flags have changed in the mean time */ if ((fip->new_msr ^ fip->msr) & MS_ANY_PRESENT) { event_sched (fip, EF_DO_MPROC) }#if defined(FASI) else (void)wakeup((caddr_t)&fip->device_flags.i);#endif /* FASI */}/* Receiver interrupt handler. Translates input characters to character sequences as described in TERMIO(7) man page.*/static uintfas_rproc (fip, line_status)register struct fas_info *fip;uint line_status;{ struct tty *ttyp; uint charac; register uint csize; unchar metta [4]; REGVAR; ttyp = fip->tty; fas_first_ctl (fip, RCV_DATA_PORT); /* Translate characters from FIFO according to the TERMIO(7) man page. */ do { charac = (line_status & LS_RCV_AVAIL)#if defined(FASI) ? (fip->characters_received++,fas_inb (fip, RCV_DATA_PORT))#else ? fas_inb (fip, RCV_DATA_PORT)#endif /* FASI */ : 0; /* was line status int only */ /* do we have to junk the character ? */ if (!(fip->cflag & CREAD) || ((ttyp->t_state & (ISOPEN | CARR_ON)) != (ISOPEN | CARR_ON))) { /* if there are FIFOs we take a short cut */ if (fip->device_flags.i & DF_DEVICE_IS_NS16550A) fas_outb (fip, NS_FIFO_CTL_PORT, NS_FIFO_SETUP_CMD | NS_FIFO_CLR_RECV); else if (fip->device_flags.i & DF_DEVICE_IS_I82510) { fas_outb (fip, I_BANK_PORT, I_BANK_1); fas_outb (fip, I_RCM_PORT, I_FIFO_CLR_RECV); fas_outb (fip, I_BANK_PORT, I_BANK_0); } continue; } csize = 0; /* strip off 8th bit ? */ if (fip->iflag & ISTRIP) charac &= 0x7f; /* ignore parity errors ? */ if ((line_status & LS_PARITY_ERROR) && !(fip->iflag & INPCK)) line_status &= ~LS_PARITY_ERROR;#if defined(FASI) if(line_status & LS_OVERRUN) fip->overrun_errors++;#endif /* FASI */ /* do we have some kind of character error ? */ if (line_status & (LS_PARITY_ERROR | LS_FRAMING_ERROR | LS_BREAK_DETECTED)) {#if defined(FASI) if(line_status & LS_PARITY_ERROR) fip->parity_errors++; if(line_status & LS_FRAMING_ERROR) fip->framing_errors++; if(line_status & LS_BREAK_DETECTED) fip->breaks_detected++;#endif /* FASI */#if defined (HAVE_VPIX) if ((fip->iflag & (DOSMODE | PARMRK)) == (DOSMODE | PARMRK)) { /* send status bits to VP/ix */ (void) fas_vpix_sr (fip, 1, (line_status & (LS_PARITY_ERROR | LS_FRAMING_ERROR | LS_BREAK_DETECTED)) | LS_RCV_AVAIL | LS_XMIT_AVAIL | LS_XMIT_COMPLETE); goto valid_char; }#endif /* is it a BREAK ? */ if (line_status & LS_BREAK_DETECTED) { if (!(fip->iflag & IGNBRK)) if (fip->iflag & BRKINT) { /* do BREAK interrupt */ event_sched (fip, EF_DO_BRKINT); } else { metta [csize] = 0; csize++; if (fip->iflag & PARMRK) { metta [csize] = 0; csize++; metta [csize] = 0xff; csize++; } } } else if (!(fip->iflag & IGNPAR)) if (fip->iflag & PARMRK) { metta [csize] = charac; csize++; metta [csize] = 0; csize++; metta [csize] = 0xff; csize++; } else { metta [csize] = 0; csize++; } } else /* is there a character to process ? */ if (line_status & LS_RCV_AVAIL) { if (fip->iflag & IXON) { /* do output start/stop handling */ if (fip->flow_flags.i & FF_SWO_STOPPED) {#if defined (HAVE_VPIX) if ((charac == fip->v86_ss.ss_start)#else if ((charac == CSTART)#endif || (fip->iflag & IXANY)) { fip->flow_flags.s &= ~FF_SWO_STOPPED; ttyp->t_state &= ~TTSTOP; /* restart output */ fas_xproc (fip); } } else {#if defined (HAVE_VPIX) if (charac == fip->v86_ss.ss_stop)#else if (charac == CSTOP)#endif { fip->flow_flags.s |= FF_SWO_STOPPED; ttyp->t_state |= TTSTOP; } } /* we don't put start/stop characters into the receiver buffer */#if defined (HAVE_VPIX) if ((charac == fip->v86_ss.ss_start) || (charac == fip->v86_ss.ss_stop))#else if ((charac == CSTART) || (charac == CSTOP))#endif continue; }valid_char: if ((charac == 0xff) && (fip->iflag & PARMRK)) { metta [csize] = 0xff; csize++; metta [csize] = 0xff; csize++; } else { /* we take a short-cut if only one character has to be put into the receiver buffer */ if (fip->recv_ring_cnt < RECV_BUFF_SIZE) { fip->recv_ring_cnt++; *fip->recv_ring_put_ptr = charac; if (++fip->recv_ring_put_ptr != &fip->recv_buffer [RECV_BUFF_SIZE]) continue; fip->recv_ring_put_ptr = &fip->recv_buffer [0]; } continue; } } if (!(csize) || (fip->recv_ring_cnt + csize > RECV_BUFF_SIZE)) continue; /* nothing to put into recv buffer */ fip->recv_ring_cnt += csize; /* store translation in ring buffer */ do { do { *fip->recv_ring_put_ptr = (metta - 1) [csize]; if (++fip->recv_ring_put_ptr == &fip->recv_buffer [RECV_BUFF_SIZE]) break; } while (--csize); if (!csize) break; fip->recv_ring_put_ptr = &fip->recv_buffer [0]; } while (--csize); } while ((line_status = fas_inb (fip, LINE_STATUS_PORT)) & LS_RCV_INT); return (line_status);}/* Output characters to the transmitter register. */static voidfas_xproc (fip)register struct fas_info *fip;{ register uint num_to_output; REGVAR; /* proceed only if transmitter is available */ if ((fip->device_flags.i & (DF_XMIT_BUSY | DF_XMIT_BREAK | DF_XMIT_LOCKED)) || (fip->flow_flags.i & FF_HWO_STOPPED)) goto sched; num_to_output = fip->xmit_fifo_size; /* handle XON/XOFF input flow control requests */ if (fip->flow_flags.i & FF_SW_FC_REQ) {#if defined (HAVE_VPIX) fas_first_outb (fip, XMT_DATA_PORT, (fip->flow_flags.i & FF_SWI_STOPPED) ? fip->v86_ss.ss_stop : fip->v86_ss.ss_start);#else fas_first_outb (fip, XMT_DATA_PORT, (fip->flow_flags.i & FF_SWI_STOPPED) ? CSTOP : CSTART);#endif fip->tty->t_state &= ~(TTXON | TTXOFF); fip->device_flags.s |= DF_XMIT_BUSY; fip->flow_flags.s &= ~FF_SW_FC_REQ; /* disable guard timeout */ if (fip->device_flags.i & DF_GUARD_TIMEOUT) { fip->device_flags.s &= ~DF_GUARD_TIMEOUT; fip->tty->t_state &= ~TIMEOUT; (void) untimeout (fip->timeout_idx); } num_to_output--; } /* bail out if output is suspended by XOFF */ if (fip->flow_flags.i & FF_SWO_STOPPED)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -