📄 fas.c
字号:
{ port_stat [unit] = '?'; continue; /* a hardware error */ } /* test the chip thoroughly */ if ((port_stat [unit] = (fas_test_device (fip) + '0')) != '0') { continue; /* a hardware error */ } fip->lcr = 0; fas_outb (fip, LINE_CTL_PORT, fip->lcr); fip->mcr = fas_mcb [unit] | fip->modem.m.di; fas_outb (fip, MDM_CTL_PORT, fip->mcr); port_stat [unit] = '*'; /* let's see if it's an NS16550A */ fas_outb (fip, NS_FIFO_CTL_PORT, NS_FIFO_INIT_CMD); if (!(~fas_inb (fip, INT_ID_PORT) & II_NS_FIFO_ENABLED)) { fip->device_flags.s |= DF_DEVICE_IS_NS16550A; fip->xmit_fifo_size = OUTPUT_NS_FIFO_SIZE; port_stat [unit] = 'F'; fas_outb (fip, NS_FIFO_CTL_PORT, NS_FIFO_CLEAR_CMD); } else { fas_outb (fip, NS_FIFO_CTL_PORT, NS_FIFO_CLEAR_CMD); /* or is it an i82510 ? */ fas_outb (fip, I_BANK_PORT, I_BANK_2); if (!(~fas_inb (fip, I_BANK_PORT) & I_BANK_2)) { fip->device_flags.s |= DF_DEVICE_IS_I82510; fip->xmit_fifo_size = OUTPUT_I_FIFO_SIZE; port_stat [unit] = 'f'; fas_outb (fip, I_BANK_PORT, I_BANK_1); fas_outb (fip, I_TCM_PORT, I_FIFO_CLR_XMIT); fas_outb (fip, I_RCM_PORT, I_FIFO_CLR_RECV); } fas_outb (fip, I_BANK_PORT, I_BANK_0); } /* disable FIFOs if requested in space.c */ if ((fas_port [unit] & NO_FIFO) && (fip->device_flags.i & (DF_DEVICE_IS_NS16550A | DF_DEVICE_IS_I82510))) { fip->device_flags.s &= ~(DF_DEVICE_IS_NS16550A | DF_DEVICE_IS_I82510); fip->xmit_fifo_size = 1; port_stat [unit] = '+'; } /* clear potential interrupts */ (void) fas_inb (fip, MDM_STATUS_PORT); (void) fas_inb (fip, RCV_DATA_PORT); (void) fas_inb (fip, RCV_DATA_PORT); (void) fas_inb (fip, LINE_STATUS_PORT); (void) fas_inb (fip, INT_ID_PORT); if (port = fas_int_ack_port [fip->vec]) (void) outb (port, fas_int_ack [fip->vec]); /* show that it is present and configured */ fip->device_flags.s |= DF_DEVICE_CONFIGURED; } }#if defined (NEED_PUT_GETCHAR) fip = &fas_info [0]; fip->mcr &= ~fip->modem.m.di; fip->mcr |= INITIAL_MDM_CONTROL; fas_first_outb (fip, MDM_CTL_PORT, fip->mcr); fip->lcr = INITIAL_LINE_CONTROL; fas_outb (fip, LINE_CTL_PORT, fip->lcr | LC_ENABLE_DIVISOR); fas_outb (fip, DIVISOR_LSB_PORT, INITIAL_BAUD_RATE); fas_outb (fip, DIVISOR_MSB_PORT, (INITIAL_BAUD_RATE) >> 8); fas_outb (fip, LINE_CTL_PORT, fip->lcr);#endif#if defined (SCO) || defined (XENIX) for (unit = 0; unit < fas_physical_units; unit++) (void) printcfg ("fas", (uint) ((ushort) (fas_port [unit])), 7, fas_vec [unit], -1,#if defined (FASI) "unit=%d type=%c FAS/i 2.08.01",#else "unit=%d type=%c release=2.08.0",#endif /* FASI */ unit, port_stat [unit]);#else port_stat [unit] = '\0'; (void) printf ("\nFAS 2.08.0 async driver: Unit 0-%d init state is [%s]\n\n", unit - 1, port_stat);#endif return (0);}/* Open a tty line. This function is called for every open, as opposed to the fasclose function which is called only with the last close.*/intfasopen (dev, flag)int dev;int flag;{ register struct fas_info *fip; register struct tty *ttyp; register uint open_mode; uint physical_unit; int old_level; physical_unit = GET_UNIT (dev); /* check for valid port number */ if (physical_unit >= fas_physical_units) { u.u_error = ENXIO; return (-1); } fip = fas_info_ptr [physical_unit]; /* was the port present at init time ? */ if (!(fip->device_flags.i & DF_DEVICE_CONFIGURED)) { u.u_error = ENXIO; return (-1); } open_mode = GET_OPEN_MODE (dev); old_level = SPLINT (); get_device_lock (fip, TTIPRI); /* If this is a getty open, the device is already open for dialout and the FNDELAY flag is not set, wait until device is closed. */ while ((open_mode & OS_OPEN_FOR_GETTY) && (fip->o_state & OS_OPEN_FOR_DIALOUT) && !(flag & FNDELAY)) { release_device_lock (fip); (void) sleep ((caddr_t) &fip->o_state, TTIPRI); get_device_lock (fip, TTIPRI); } /* If the device is already open and another open uses a different open mode or if a getty open waits for carrier and doesn't allow parallel dialout opens, return with EBUSY error. */ if ((fip->o_state & ((open_mode & OS_OPEN_FOR_GETTY) ? (OS_OPEN_STATES | OS_WAIT_OPEN) : (OS_OPEN_STATES | OS_NO_DIALOUT))) && ((flag & FEXCL) || ((open_mode ^ fip->o_state) & (u.u_uid ? OS_TEST_MASK : OS_SU_TEST_MASK)))) { u.u_error = EBUSY; release_device_lock (fip); (void) splx (old_level); return (-1); } /* disable subsequent opens */ if (flag & FEXCL) open_mode |= OS_EXCLUSIVE_OPEN_1; /* set up pointer to tty structure */ ttyp = (open_mode & OS_OPEN_FOR_GETTY) ? fas_tty_ptr [physical_unit + fas_physical_units] : fas_tty_ptr [physical_unit]; /* things to do on first open only */ if (!(fip->o_state & ((open_mode & OS_OPEN_FOR_GETTY) ? (OS_OPEN_STATES | OS_WAIT_OPEN) : OS_OPEN_STATES))) { /* init data structures */ fip->tty = ttyp; (void) ttinit (ttyp); ttyp->t_proc = fas_proc; fip->po_state = fip->o_state; fip->o_state = open_mode & ~OS_OPEN_STATES;#if defined (HAVE_VPIX) /* initialize VP/ix related variables */ fip->v86_proc = (v86_t *) NULL; fip->v86_intmask = 0; fip->v86_ss.ss_start = CSTART; fip->v86_ss.ss_stop = CSTOP;#endif fas_open_device (fip); /* open physical device */ fas_param (fip, HARD_INIT); /* set up port registers */ /* allow pending tty interrupts */ (void) SPLWRK (); (void) SPLINT (); } /* If getty open and the FNDELAY flag is not set, block and wait for carrier if device not yet open. */ if ((open_mode & OS_OPEN_FOR_GETTY) && !(flag & FNDELAY)) { /* sleep while open for dialout or no carrier */ while ((fip->o_state & OS_OPEN_FOR_DIALOUT) || !(ttyp->t_state & (ISOPEN | CARR_ON))) { ttyp->t_state |= WOPEN; release_device_lock (fip); (void) sleep ((caddr_t) &ttyp->t_canq, TTIPRI); get_device_lock (fip, TTIPRI); } ttyp->t_state &= ~WOPEN; } /* wakeup processes that are still sleeping in getty open */ if (ttyp->t_state & WOPEN)#if defined(FASI) {#endif (void) wakeup ((caddr_t) &ttyp->t_canq);#if defined(FASI) (void) wakeup ((caddr_t) &fip->device_flags.i); }#endif /* we need to flush the receiver with the first open */ if (!(fip->o_state & OS_OPEN_STATES)) fas_cmd (fip, ttyp, T_RFLUSH); (*linesw [ttyp->t_line].l_open) (ttyp); /* set open type flags */ fip->o_state = open_mode; release_device_lock (fip); (void) splx (old_level); return (0);}/* Close a tty line. This is only called if there is no other concurrent open left. A blocked getty open is not counted as a concurrent open because in this state it isn't really open.*/intfasclose (dev)int dev;{ register struct fas_info *fip; register struct tty *ttyp; uint physical_unit; uint open_mode; int old_level; void (*old_sigkill)(); physical_unit = GET_UNIT (dev); fip = fas_info_ptr [physical_unit]; open_mode = GET_OPEN_MODE (dev); /* set up pointer to tty structure */ ttyp = (open_mode & OS_OPEN_FOR_GETTY) ? fas_tty_ptr [physical_unit + fas_physical_units] : fas_tty_ptr [physical_unit]; old_level = SPLINT (); get_device_lock (fip, TTIPRI); /* wait for output buffer drain only if device was open */ if (ttyp->t_state & ISOPEN) { /* flush the output buffer immediately if the device has been shut down because of an error */ if (!(fip->device_flags.i & DF_DEVICE_CONFIGURED)) { (void) ttyflush (ttyp, FWRITE); } /* wait for buffer drain and catch interrupts */ while (ttyp->t_outq.c_cc || (ttyp->t_state & (BUSY | TIMEOUT))) { old_sigkill = u.u_signal [SIGKILL - 1]; /* allow kill signal if close on exit */ if (old_sigkill == SIG_IGN) u.u_signal [SIGKILL - 1] = SIG_DFL; ttyp->t_state |= TTIOW; if (sleep ((caddr_t) &ttyp->t_oflag, TTOPRI | PCATCH)) { /* caught signal */ ttyp->t_state &= ~TTIOW; /* If close on exit, flush output buffer to allow completion of the fasclose() function. Otherwise, do the normal signal handling. */ if (old_sigkill == SIG_IGN) (void) ttyflush (ttyp, FWRITE); else { release_device_lock (fip); (void) splx (old_level); longjmp (u.u_qsav); } } if (old_sigkill == SIG_IGN) u.u_signal [SIGKILL - 1] = old_sigkill; } } (*linesw [ttyp->t_line].l_close) (ttyp); /* allow pending tty interrupts */ (void) SPLWRK (); (void) SPLINT (); if (open_mode & OS_OPEN_FOR_GETTY) { /* not waiting any more */ ttyp->t_state &= ~WOPEN; if (!(fip->o_state & OS_OPEN_FOR_DIALOUT)) { fas_close_device (fip); fip->o_state = OS_DEVICE_CLOSED; } else fip->po_state = OS_DEVICE_CLOSED; } else { fas_close_device (fip); fip->o_state = OS_DEVICE_CLOSED; /* If there is a waiting getty open on this port, reopen the physical device. */ if (fip->po_state & OS_WAIT_OPEN) { /* get the getty version of the tty structure */ fip->tty = fas_tty_ptr [physical_unit + fas_physical_units]; fip->o_state = fip->po_state; fip->po_state = OS_DEVICE_CLOSED;#if defined (HAVE_VPIX) /* initialize VP/ix related variables */ fip->v86_proc = (v86_t *) NULL; fip->v86_intmask = 0; fip->v86_ss.ss_start = CSTART; fip->v86_ss.ss_stop = CSTOP;#endif if (!(fip->device_flags.i & DF_DO_HANGUP)) { fas_open_device (fip); /* set up port registers */ fas_param (fip, HARD_INIT); } } (void) wakeup ((caddr_t) &fip->o_state); } if (!(fip->device_flags.i & DF_DO_HANGUP)) release_device_lock (fip);#if defined(FASI) (void)wakeup((caddr_t)&fip->device_flags.i);#endif (void) splx (old_level); return (0);}/* read characters from the input buffer */intfasread (dev)int dev;{ register struct fas_info *fip; register struct tty *ttyp; int old_level; fip = fas_info_ptr [GET_UNIT (dev)]; /* was the port present at init time ? */ if (!(fip->device_flags.i & DF_DEVICE_CONFIGURED)) { u.u_error = ENXIO; return (-1); } ttyp = fip->tty; (*linesw [ttyp->t_line].l_read) (ttyp); old_level = SPLINT (); /* 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) >= ttyp->t_rawq.c_cc)#else && ((MAX_UNIX_FILL - MIN_READ_CHUNK) >= ttyp->t_rawq.c_cc)#endif && !(fip->flow_flags.i & FF_RXFER_STOPPED)) { event_sched (fip, EF_DO_RXFER); }#if defined(FASI) (void)wakeup((caddr_t)&fip->device_flags.i);#endif (void) splx (old_level); return (0);}/* write characters to the output buffer */intfaswrite (dev)int dev;{ register struct fas_info *fip; register struct tty *ttyp; fip = fas_info_ptr [GET_UNIT (dev)]; /* was the port present at init time ? */ if (!(fip->device_flags.i & DF_DEVICE_CONFIGURED)) { u.u_error = ENXIO; return (-1); } ttyp = fip->tty; (*linesw [ttyp->t_line].l_write) (ttyp); return (0);}/*+------------------------------------------------------------------------- strlen(str)--------------------------------------------------------------------------*/#if defined(FASI)static intstrlen(str)register char *str;{register len = 0; while(*str++) len++; return(len);} /* end of strlen */#endif /* FASI *//* process ioctl calls */intfasioctl (dev, cmd, arg3, arg4)int dev;int cmd;union ioctl_arg arg3;int arg4;{ register struct fas_info *fip; register struct tty *ttyp; int v86_cmd, v86_data; int old_level; REGVAR; fip = fas_info_ptr [GET_UNIT (dev)]; /* was the port present at init time ? */ if (!(fip->device_flags.i & DF_DEVICE_CONFIGURED)) { u.u_error = ENXIO; return (-1); } ttyp = fip->tty; /* process ioctl commands */ switch (cmd) {#if defined (FASI) case FASIC_SIP_CHANGE: (void) sleep ((caddr_t) &fip->device_flags.i, PZERO + 1); case FASIC_SIP: if(copyout((char *)fip,arg3.cparg,sizeof(*fip))) { u.u_error = EFAULT; return(-1); } return(fasiintr_entries); case FASIC_DVR_IDENT: if(copyout(fasi_driver_ident,arg3.cparg, strlen(fasi_driver_ident) + 1)) { u.u_error = EFAULT; return(-1); } break; case FASIC_SPACE_IDENT: if(copyout(fasi_space_ident,arg3.cparg, strlen(fasi_space_ident) + 1)) { u.u_error = EFAULT; return(-1); } break; case FASIC_MSR: return((unsigned int)fip->msr); case FASIC_LCR: return((unsigned int)fip->lcr); case FASIC_IER: return((unsigned int)fip->ier); case FASIC_MCR: return((unsigned int)fip->mcr); case FASIC_RESET_STAT: old_level = SPLINT(); fip->characters_received = 0;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -