📄 fc.c
字号:
#ifndef lintstatic char *sccsid = "@(#)fc.c 4.1 (ULTRIX) 7/2/90";#endif lint/************************************************************************ * * * Copyright (c) 1985, 1986, 1987 by * * Digital Equipment Corporation, Maynard, MA * * All rights reserved. * * * * This software is furnished under a license and may be used and * * copied only in accordance with the terms of such license and * * with the inclusion of the above copyright notice. This * * software or any other copies thereof may not be provided or * * otherwise made available to any other person. No title to and * * ownership of the software is hereby transferred. * * * * This software is derived from software received from the * * University of California, Berkeley, and from Bell * * Laboratories. Use, duplication, or disclosure is subject to * * restrictions under license agreements with University of * * California and with AT&T. * * * * The information in this software is subject to change without * * notice and should not be construed as a commitment by Digital * * Equipment Corporation. * * * * Digital assumes no responsibility for the use or reliability * * of its software on equipment which is not supplied by Digital. * * * ************************************************************************/#include "fc.h"#if NFC > 0 || defined(BINARY)/* * Firefox serial line unit driver * * Modification History: * * 31-Oct-89 - Randall Brown * * Added the support to allow the device to determine if baudrate is * supported before it is set in the tty data structures. * * 15-Aug-89 - Randall Brown * * Changed all references of TCSADFLUSH to TCSAFLUSH * * 21-Jul-89 - Randall Brown * * Moved default open and default close code to tty.c and call it * using tty_def_open() and tty_def_close(). In the close routine, * don't clear the baudrate so that subsequent opens will keep the * present attributes. This only applies to a Berkeley environment. * * 12-Jun-89 - dws * Added trusted path support. * * 15-Feb-89 - darrell * Removed the global variable ka60_expect_memerr. * * 12-Jan-89 - jaw * merge Xe changes for FFox drivers * * 25-Jan-89 - Randall Brown * * Changed cd_drop to look at LNOHANG. Changed close routine to look * at HUPCL. * * 20-Jan-89 - darrell * Cleanup, and added a module counter to keep track of the number * of memory modules in the system. * * 18-Nov-88 - darrell (for tim) * Fixed a bug where the system would hang during boot if a character * was typed on the keyboard or if the mouse was moved. * * 28-Sep-88 - darrell * Changed all writes to fbicsr to be read-modif-write accesses * so as to not change the value of the LEDS on any hardware modules. * * 28-Sep-88 - Randall Brown * Fixed a bug in fcxint so that the transmitter interrupt will be * acknowledged when the terminal is in the stop state. * * 27-Sep-88 - darrell * Added mapping code for FGCTSIXSmap. * * 13-Sep-88 - Ali Rafieymehr * * Fixed a bug which was causing the "select" not to work for * alternate console. * * 02-Sep-88 - Tim Burke * * Return EINVAL instead of ENOTTY for POSIX programs on invalid ioctls. * * 18-Aug-88 - Tim Burke * * If PARMRK is set and a BREAK occurs, return '\0377','\0','\0'. * * 5-Aug-88 - Tim Burke * * Return the 2 character sequence 0377, 0377 upon receipt of a valid * 0377 character only when PARMRK is set under the termio line disc. * * 12-15-87 darrell * Copied this file from ss.c. */#include "../data/fc_data.c"int fcdebug = 0;int fcbail1 = 0; /* Bit spin count failures */int fcbail2 = 0;int fcbail3 = 0;int ff_diagcons = 0; /* 0 = LEGSS, 1 = VT220 *//** Driver information for auto-configuration stuff.*/int fcprobe(), fcattach(), fcrint();int fc_cd_drop(), fc_dsr_check(), fc_cd_down(), fc_tty_drop(); /* Modem */u_short fcstd[] = { 0 };struct uba_driver fcdriver ={ fcprobe, 0, fcattach, 0, fcstd, "fc", fcinfo };int fcstart(), fcxint(), fcdma(), fcbaudrate();int ttrstrt();int fcact;/* * Graphics device driver entry points. * Used to call graphics device driver as needed. */extern (*vs_gdopen)();extern (*vs_gdclose)();extern (*vs_gdread)();extern (*vs_gdwrite)();extern (*vs_gdselect)();extern (*vs_gdkint)();extern (*vs_gdioctl)();extern (*vs_gdstop)();#define FASTTIMER (hz/30) /* rate to drain silos, when in use */#define MODEM_UNIT 2 /* Modem control only on unit 2 */#define LINEMASK 0x03 /* line unit mask */int fcsilos; /* mask of SLU's with silo in use */int fctimerintvl; /* time interval for fctimer */int fchighrate = 100; /* silo on if fcchars > fchighrate */int fclowrate = 75; /* silo off if fcrate < fclowrate *//** The SLU doesn't interrupt on carrier transitions, so* we have to use a timer to watch it.*/char fc_timer; /* timer started? */char fc_speeds[] ={ 0,020,021,022,023,024,0,025,026,027,030,032,034,036,037,0 };short fc_valid_speeds = 0x7fbf; /* 0,1,1,1, 1,1,1,1, 1,0,1,1, 1,1,1,1 */u_char fccan_previous; /* Used to detect modem transitions */extern long cpu_fbic_addr;extern struct mb_node mbus_nodes[];extern struct cpusw *cpup; /* pointer to cpusw entry */long cpu_fbic_addr;struct tty sm_tty;fcprobe(reg) caddr_t reg;{ register struct fc_regs *fcaddr = (struct fc_regs *)reg; int i; int tries; /* * ONLY on a Firefox */ if(cpu != VAX_60) return(0); /* * Hit master clear to reset chip to known state. * Give time for self test to pass. */ tries = 0; fcaddr->fccsr = FC_CLR; while ((fcaddr->fccsr & FC_CLR) & (tries++ < 10)) { DELAY(100000); }#ifdef notdef /* * Cause the DZ to interrupt */ fcaddr->fccsr = FC_TIE | FC_MSE; fcaddr->fctcr = 0x8; /* enable line 3 */ /* The DZ should interrupt during this delay */ DELAY(100000); fcaddr->fccsr = FC_MSE; fcaddr->fctcr = 0;#endif notdef return (1); /* 1 not sizeof anything, just says probe succeeded */}fcattach(ui) register struct uba_device *ui;{ register struct pdma *pdp = &fcpdma[ui->ui_unit*4]; register struct tty *tp = &fc_tty[ui->ui_unit*4]; register int cntr; register struct fc_regs *fcaddr = (struct fc_regs *)ffcons; extern fcscan(); for (cntr = 0; cntr < 4; cntr++) { /* dzdevice looks wrong, but see vaxuba/pdma.h for reason */ pdp->p_addr = (struct dzdevice *)&fcaddr->fccsr; pdp->p_arg = (int)tp; pdp->p_fcn = fcxint; pdp++, tp++; } fcsoftCAR[ui->ui_unit] = ui->ui_flags; fcdefaultCAR[ui->ui_unit] = ui->ui_flags; fcmodem = 0; if (fc_timer == 0) { fc_timer++; timeout(fcscan, (caddr_t)0, hz); fctimerintvl = FASTTIMER; }}/*ARGSUSED*/fcopen(dev, flag) dev_t dev;{ register struct fc_regs *fcaddr = (struct fc_regs *)ffcons; register struct tty *tp; register int unit; register int maj; int inuse; /*hold state of inuse bit while blocked waiting for carr*/# ifdef DEBUG if (fcdebug > 1) cprintf("fcopen\n");# endif DEBUG maj = major(dev); /* * If a diagnostic console is attached to SLU line 3, * don't allow open of the printer port (also line 3). * This could cause lpr to write to the console. */ if ((ff_diagcons) && (maj == FCMAJOR)) { if((minor(dev)&LINEMASK) == 3) { cprintf("out ENXIO 1"); return (ENXIO); } } unit = minor(dev);# ifdef DEBUG if (fcdebug > 1) cprintf("fcopen: unit = %d\n",unit);# endif DEBUG if((ff_diagcons) && (maj == CONSOLEMAJOR) && ((unit&LINEMASK) == 0)) unit |= 3; if (unit >= fc_cnt || fcpdma[unit].p_addr == 0) {# ifdef DEBUG if (fcdebug) cprintf("fcopen:fc_cnt=%d, p_addr=%x\n",fc_cnt, fcpdma[unit].p_addr);# endif DEBUG return (ENXIO); } /* * Never allow open of device 54/0 (/dev/tty00) * because it conflicts with 0/0 (/dev/console). */ if ((unit == 0) && (maj == FCMAJOR)) {# ifdef DEBUG cprintf("out ENXIO 3");# endif DEBUG return (ENXIO); } /* * If the console is a graphics device (VAXstation 2000), * don't allow open of device 54/1 (/dev/tty01) * because it conflicts with 0/1 (graphics pointer device). if (vs_gdopen && (unit == 1) && (maj == FCMAJOR)) {# ifdef DEBUG if (fcdebug) cprintf("fcopen: out ENXIO 3.5\n");# endif DEBUG return (ENXIO); } /* * Call the graphics device open routine * if there is one and the open if for the fancy tube. */ if ((vs_gdopen && (unit <= 1)) || (vs_gdopen && (unit == 2) && (maj == CONSOLEMAJOR))) return((*vs_gdopen)(dev, flag)); tp = &fc_tty[unit]; if (tp->t_state&TS_XCLUDE && u.u_uid != 0){ return (EBUSY); } while (tp->t_state&TS_CLOSING) { /* let DTR stay down for awhile */ sleep((caddr_t)&tp->t_rawq, TTIPRI); } tp->t_addr = (caddr_t)&fcpdma[unit]; tp->t_oproc = fcstart; tp->t_baudrate = fcbaudrate; tty_def_open(tp, dev, flag, (fcsoftCAR[unit>>2]&(1<<(unit&LINEMASK)))); if ((tp->t_state & TS_ISOPEN) == 0) { if (unit == MODEM_UNIT) fcmodem = MODEM_DSR_START; if((maj == CONSOLEMAJOR) && ((minor(dev)&3) == 0)) { tp->t_cflag &= ~CBAUD; tp->t_cflag = B9600; tp->t_cflag_ext &= ~CBAUD; tp->t_cflag_ext = B9600; tp->t_flags = ANYP|ECHO|CRMOD; tp->t_iflag |= ICRNL; /* Map CRMOD */ tp->t_oflag |= ONLCR; /* Map CRMOD */ } } fcparam(unit); /* enables interrupts */ (void) spl6(); /* * No modem control provided for lines with softCAR set. * Modem control provided only for line 2. */ if ((unit != MODEM_UNIT) || (tp->t_cflag & CLOCAL)) { /* * This is a local connection - ignore carrier * receive enable interrupts enabled above via fcparam() */ tp->t_state |= TS_CARR_ON; /* fcscan sets */ if (unit == MODEM_UNIT) fcaddr->fcdtr |= (FC_RDTR|FC_RRTS); /* * 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; (void) spl0(); return ((*linesw[tp->t_line].l_open)(dev, tp)); } /* * this is a modem line */ /* receive enable interrupts enabled above via fcparam() */ fcaddr->fcdtr |= (FC_RDTR|FC_RRTS); /* * After DSR first comes up we must wait for the other signals * before commencing transmission. */ if ((flag & (O_NDELAY|O_NONBLOCK)) == 0) { /* * Delay before examining other signals if DSR is being followed * otherwise proceed directly to fc_dsr_check to look for * carrier detect and clear to send. */ if (fcdsr) { if ((fcaddr->fcmsr)&FC_RDSR) { fcmodem |= (MODEM_DSR_START|MODEM_DSR); tp->t_dev = dev; /* need it for timeouts */ /* * Give Carrier and CTS 30 sec. to come up. * Prevent any transmission in the first 500ms. */ timeout(fc_dsr_check, tp, hz*30); timeout(fc_dsr_check, tp, hz/2); } } /* * Ignoring DSR so immediately check for CD & CTS. */ else { fcmodem |= (MODEM_DSR_START|MODEM_DSR); fc_dsr_check(tp); } }# ifdef DEBUG if (fcdebug) cprintf("fcopen: line=%d, state=%x, tp=%x\n", unit, tp->t_state, tp);# endif DEBUG 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((caddr_t)&tp->t_rawq, TTIPRI); /* * See if we were awoken by a false call to the modem * line by a non-modem. */ if (fcmodem&MODEM_BADCALL){ (void) spl0(); return(EWOULDBLOCK); } /* if we opened "block if in use" and * the terminal was not inuse at that time * but is became "in use" while we were * waiting for carrier then return */ if ((flag & O_BLKINUSE) && (inuse==0) && (tp->t_state&TS_INUSE)) { (void) spl0(); 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; (void) spl0(); return ((*linesw[tp->t_line].l_open)(dev, tp));}/*ARGSUSED*/fcclose(dev, flag) dev_t dev;{ register struct tty *tp; register int unit; register int s; register struct fc_regs *fcaddr = (struct fc_regs *)ffcons; int fc; extern int wakeup(); unit = minor(dev); if((ff_diagcons) && (major(dev) == CONSOLEMAJOR) && ((unit&LINEMASK) == 0)) unit |= 3; /* * Call the craphics device close routine * if ther is one and the close is for it. */ if ((vs_gdclose && (unit <= 1)) || (vs_gdclose && (unit == 2) && (major(dev) == CONSOLEMAJOR))){ (*vs_gdclose)(dev, flag); return; } fc = unit >> 2;# ifdef DEBUG if (fcdebug) cprintf("fcclose: unit=%x, fc=%x\n",unit,fc);# endif DEBUG tp = &fc_tty[unit]; /* * Do line discipline specific close functions then return here * in the old line disc for final closing. */ if (tp->t_line) (*linesw[tp->t_line].l_close)(tp); /* * fcbrk is write-only and sends a BREAK (SPACE condition) until * the break control bit is cleared. Here we are clearing any * breaks for this line on close. */ fcaddr->fcbrk = (fc_brk[fc] &= ~(1 << (unit&LINEMASK))); if ((tp->t_cflag&HUPCL) || (tp->t_state&TS_WOPEN) || (tp->t_state&TS_ISOPEN)==0) { tp->t_state &= ~TS_CARR_ON; /* prevents recv intr. timeouts */ if (unit == MODEM_UNIT) { /* * Drop appropriate signals to terminate the connection. */ fcaddr->fcdtr &= ~(FC_RDTR|FC_RRTS); if ((tp->t_cflag & CLOCAL) == 0) { s = spl6(); /*drop DTR for at least a sec. if modem line*/# ifdef DEBUG if (fcdebug) cprintf("fcclose: DTR drop, state =%x\n" ,tp->t_state);# endif DEBUG tp->t_state |= TS_CLOSING; /* * Wait at most 5 sec for DSR to go off. * Also hold DTR down for a period. */ if (fcdsr && (fcaddr->fcmsr & FC_RDSR)) { timeout(wakeup,(caddr_t)&tp->t_dev,5*hz); sleep((caddr_t)&tp->t_dev, PZERO-10); } /* * Hold DTR down for 200+ ms. */ timeout(wakeup, (caddr_t) &tp->t_dev, hz/5); sleep((caddr_t)&tp->t_dev, PZERO-10); tp->t_state &= ~(TS_CLOSING); wakeup((caddr_t)&tp->t_rawq); splx(s); } } /* * No disabling of interrupts is done. Characters read in on * a non-open line will be discarded. */ } /* reset line to default mode */ fcsoftCAR[fc] &= ~(1<<(unit&LINEMASK)); fcsoftCAR[fc] |= (1<<(unit&LINEMASK)) & fcdefaultCAR[fc]; if (unit == MODEM_UNIT) fcmodem = 0; ttyclose(tp); tty_def_close(tp);}/* * fcread() shared with graphics device drivers (sm & sg). */fcread(dev, uio) dev_t dev; struct uio *uio;{ register struct tty *tp; register int unit; unit = minor(dev); if((ff_diagcons) && (major(dev) == CONSOLEMAJOR) && ((unit&LINEMASK) == 0)) unit |= 3; if((unit == 1) && vs_gdread) return((*vs_gdread)(dev, uio)); if (vs_gdopen && (unit == 2) && (major(dev) == CONSOLEMAJOR)) tp = &sm_tty; else tp = &fc_tty[unit]; return ((*linesw[tp->t_line].l_read)(tp, uio));}/* * fcwrite() shared with graphics device drivers (sm & sg). */fcwrite(dev, uio) dev_t dev; struct uio *uio;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -