📄 dmz.c
字号:
#ifndef lintstatic char *sccsid = "@(#)dmz.c 4.1 (ULTRIX) 7/2/90";#endif lint/************************************************************************ * * * Copyright (c) 1985-88 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. * * * ************************************************************************//* * dmz.c 6.1 7/29/83 * * Modification history * * DMZ32 terminal driver * * 5-May-85 - Larry Cohen * * Derived from 4.2BSD labeled: dmz.c 6.1 83/07/29. * Add dma support, switch between dma and silo - derived from UCB. * * 16-Jan-86 - Larry Cohen * * Add full DEC standard 52 support. * * 18-Mar-86 - jaw * * br/cvec changed to NOT use registers. * * 14-Apr-86 - jaw * * remove MAXNUBA references.....use NUBA only! * * 26-Apr-86 - ricky palmer * * Added new DEVIOCGET ioctl request code. V2.0 * * 11-Jul-86 - ricky palmer * * Added adpt and nexus fields to DEVIOCGET code. * * 05-Aug-86 - Tim Burke * * In dmzrint, record present time in timestamp in the event of * a carrier drop. * * 12-Aug-86 - Tim Burke * * Set dmz_mindma to a value of 200 to prevent dma transfers from occuring. * This is to aviod hardware problems with NXM errors, and should be * changed back when the device is fixed. * * 25-Aug-86 - Tim Burke * * Insure that line is dropped and will restart on a false call to modem. * Also change state to ~TS_CARR_ON to kill associated processes. * * 26-Aug-86 - rsp (Ricky Palmer) * * Cleaned up devioctl code to (1) zero out devget structure * upon entry and (2) use strlen instead of fixed storage * for bcopy's. Fixed code to handle 24 lines instead of 32. * * 4-Dec-86 - Tim Burke * * Bug fix to modem control. In dmz_tty_drop routine, clear the stopped * state to prevent modem lines from hanging on close. * * 15-Dec-86 - Tim Burke * * When a break occurs, (interpreted as a framing error) set the variable * c to be the interrupt character. There was a problem here due to the * fact that sign extension is done which causes unwanted side affects. To * solve this bug, the character is stripped to 8 bits. * * Modified probe routine to wait for self test to complete. * * Fix DEVIOGET to return propper modem status information. * * 9-Jan-86 - Tim Burke * * Bug fix to TIOCMODEM to clear modem flags if signals are not up. * * 28-Jan-87 - Tim Burke * * Added the capability to ignore the "DSR" modem signal. This is being * done to allow modems that do not follow DEC Standard 52 to still * function as they would have prior to the addition of DECSTD52 code * into the drivers. If the driver is setup to ignore "DSR" then it will * not be following DECSTD52. To follow DECSTD52 set dmzdsr to "1", to * ignore "DSR" set dmzdsr to be "0"; * * 3-Mar-87 - Tim Burke * * Added full TERMIO functionality to terminal subsystem. * Fixup master reset code in probe routine to work on a per-octet basis. * * * 27-Jul-87 - Dan Stuart & Tim Burke * * Changed to properly link logical and physical lines, and index * properly into dmz_tty. Finishes 32 -> 24 lines changes by rsp above. * * 8-Sep-87 - rsp (Ricky Palmer) * * Defined and used LINEMASK where appropriate to correctly set * line number. * * 9-Sept-87 - Tim Burke * * Added support for hardware auto flow control on the outgoing side. This * will provide quick response to start/stop characters which will reduce * buffer overflow on the receiving device. * * * 1-Dec-87 - Tim Burke * * Added support for both System V termio(7) and POSIX termios(7). These * changes also include support for 8-bit canonical processing. Changes * involve: * * - Default settings on first open depend on mode of open. For termio * opens the defaults are "RAW" style, while non-termio opens default * to the traditional "cooked" style. * - The driver now represents its terminal attributes and special * characters in the POSIX termios data structure. This contrasts the * original approach of storing attributes and special chars in the * t_flags, ltchars and tchars. * - New termio ioctls: TCSANOW, TCSADRAIN, TCSADFLUSH, TCSETA, TESETAW, * TCSETAF. * - Addition of LPASS8 to local mode word for 8-bit canonical support. * * 29-Jan-88 - Tim Burke * Changed most softCAR[unit&LINEMASK] references to use the CLOCAL * bit of the control flags to determine if the line is set to be a * modem line or a direct connect. The setting of softCAR[] remains * to allow one to set default settings for device open. * * 16-May-88 - Tim Burke * * Call param routine for setting of local mode word because it can * affect bit size and parity. * * 14-Jul-88 - Tim Burke * * The probe routine has been modified to accept only one parameter. * The controller number is not passed to this routine. * * 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. * * 18-Aug-88 - Tim Burke * * If PARMRK is set and a BREAK occurs, return '\0377','\0','\0'. * * 25-Jan-89 - Randall Brown * * Changed cd_drop to look at LNOHANG. Changed close routine to look * at HUPCL. * * 12-Jun-89 - dws * * Added trusted path support. * * 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. * * 15-Aug-89 - Randall Brown * * Changed all references of TCSADFLUSH to TCSAFLUSH * * 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. */#include "dmz.h"#if NDMZ > 0 || defined(BINARY)#include "../data/dmz_data.c"int dmzdebug = 0;/* * Definition of the driver for the auto-configuration program. * There are three sets of interrupt vectors for the dmz32 - one set * for each octet of lines. */int dmzprobe(), dmzattach(), dmzrinta(), dmzxinta(), dmzbaudrate(), dmzrintb(), dmzxintb(), dmzrintc(), dmzxintc();int dmz_cd_drop(), dmz_dsr_check(), dmz_cd_down(), dmz_tty_drop();struct timeval dmzzerotime = {0,0};int dmzcdtime = 2;u_short dmzstd[] = { 0 };struct uba_driver dmzdriver = { dmzprobe, 0, dmzattach, 0, dmzstd, "dmz", dmzinfo };int dmz_timeout = 10; /* silo timeout, in ms */ /* * dmz_mindma should be set to a value of 4, such that dma is performed * on blocks of four or greater characters to transfer. Presently * there is a hardware problem in the dmz device causing large * numbers of NXM errors to occur. These errors could potentially * cause system panics. As a temporary fix, the value of dmz_mindma * is set to be greater that 60 (which is the largest possible clist * size, which prevents dma from being done. This fix could * potentially degrade performance to produce stable operation. */int dmz_mindma = 200; /* don't dma below this point *//* * Local variables for the driver */char dmz_speeds[] = { 0, 0, 1, 2, 3, 4, 0, 5, 6, 7, 010, 012, 014, 016, 017, 0 };short dmz_valid_speeds = 0x7fbf; /* 0,1,1,1, 1,1,1,1, 1,0,1,1, 1,1,1,1 */int dmzstart(), ttrstrt();#define NUMLINES 24 /* 24 lines on a DMZ */#ifndef MODEM_CD#define MODEM_CD 0x01#define MODEM_DSR 0x02#define MODEM_CTS 0x04#define MODEM_DSR_START 0x08#endif/* * The clist space is mapped by the driver onto each UNIBUS. * The UBACVT macro converts a clist space address for unibus uban * into an i/o space address for the DMA routine. */#define UBACVT(x, uban) (cbase[uban] + ((x)-(char *)cfree))/* * Routine for configuration to set dmz interrupt. *//*ARGSUSED*/dmzprobe(reg) caddr_t reg;{ register struct dmzdevice *dmzaddr = (struct dmzdevice *)reg; register struct octet *oaddr; register int totaldelay;#ifdef lint dmzxinta(0); dmzrinta(0); dmzxintb(0); dmzrintb(0); dmzxintc(0); dmzrintc(0);#endif if(dmzdebug) printf("dmzprobe\n"); /* * If a self test is not being done, start one up. Wait for the * self-test to complete before interrupting. Done on a per-octet basis. */ for ( oaddr=dmzaddr->octets; oaddr<=dmzaddr->octets+2; ++oaddr ) { if ( (oaddr->dmzcsr&DMZ_CLR) == 0 ) oaddr->dmzcsr |= DMZ_CLR; totaldelay = 0; while ( (oaddr->dmzcsr&DMZ_CLR) && (totaldelay<=70) ) { totaldelay++; DELAY(50000); } if ( oaddr->dmzcsr & DMZ_CLR ) printf("Warning: DMZ Master Clear failure, octet %d\n", oaddr-dmzaddr->octets); } if ((dmzaddr->dmzccsr0 & DMZ_IDENT) != DMZ_IDENT) { printf("dmzprobe: not a dmz\n"); return; } br = 0x15; /* load base of interrupt vectors */ dmzaddr->dmzccsr0 = ((uba_hd[numuba].uh_lastiv -= 4*6) >> 2); /* try to generate an interrupt on the first octet */ oaddr = dmzaddr->octets; /* first octet */ oaddr->dmzcsr = DMZ_IE | DMZIR_LCR; oaddr->dmzlcr = DMZ_TE | DMZ_FLUSH; DELAY(100000); /* wait 1/10'th of a sec for interrupt */ { int temp = oaddr->dmzcsr; /* clear interrupt flag */ } if (cvec && cvec != 0x200) /* check to see if interrupt occurred */ cvec -= 4; /* point to first interrupt vector (recv)*/ else uba_hd[numuba].uh_lastiv += 4*6; /* no interrupt * restore floating vector. */ /* NEED TO SAVE IT SOMEWHERE FOR OTHER DEVICES */ return (sizeof (struct dmzdevice));}/* * Routine called to attach a dmz. */dmzattach(ui) struct uba_device *ui;{ dmzsoftCAR[ui->ui_unit] = ui->ui_flags; dmzdefaultCAR[ui->ui_unit] = ui->ui_flags; if (dmzdebug) printf("dmzattach: unit=%d, flags=%x\n", ui->ui_unit, ui->ui_flags);}/* * Open a DMZ32 line, mapping the clist onto the uba if this * is the first dmz on this uba. Turn on this dmz if this is * the first use of it. *//*ARGSUSED*/dmzopen(dev, flag) dev_t dev;{ register struct tty *tp; register int unit, dmz, octetnum; register struct octet *oaddr; /* pointer to octet set */ register struct uba_device *ui; register int maxdmzlines; int s; int inuse; /*hold state of inuse bit while blocked waiting for carr*/ unit = minor(dev); dmz = unit / NUMLINES; /* module number */ maxdmzlines = ndmz; /* NDMZ * 24 = maximun number of line */ if (unit >= maxdmzlines || (ui = dmzinfo[dmz])== 0 || ui->ui_alive == 0) return (ENXIO); tp = &dmz_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); octetnum = ( unit % NUMLINES ) / 8; /* get octet #, line # later */ oaddr = &((struct dmzdevice *)ui->ui_addr)->octets[octetnum]; tp->t_addr = (caddr_t)oaddr; tp->t_oproc = dmzstart; tp->t_baudrate = dmzbaudrate; tp->t_state |= TS_WOPEN;#ifdef DMZDEBUG if (dmzdebug) mprintf("dmzopen: unit=%d, oaddr=%x, tp=%x\n", unit, oaddr, tp);#endif /* * While setting up state for this uba and this dmz, * block uba resets which can clear the state. */ s = spl5(); while (tty_ubinfo[ui->ui_ubanum] == -1) /* need this lock because uballoc can sleep */ sleep(&tty_ubinfo[ui->ui_ubanum], TTIPRI); if (tty_ubinfo[ui->ui_ubanum] == 0) { tty_ubinfo[ui->ui_ubanum] = -1; tty_ubinfo[ui->ui_ubanum] = uballoc(ui->ui_ubanum, (caddr_t)cfree, nclist*sizeof(struct cblock), 0); wakeup(&tty_ubinfo[ui->ui_ubanum]); } cbase[ui->ui_ubanum] = tty_ubinfo[ui->ui_ubanum]&0x3ffff; oaddr->dmzcsr |= DMZ_IE; splx(s); if ((tp->t_state&TS_ISOPEN) == 0) { dmzmodem[unit] = MODEM_DSR_START; oaddr->dmzrsp = dmz_timeout; } tty_def_open(tp, dev, flag, (dmzsoftCAR[dmz]&(1<<(unit%NUMLINES)))); dmzparam(unit); /* * Wait for carrier, then process line discipline specific open. */ s = spl5(); dmzmctl(dev, DMZ_ON, DMSET); /* assert DTR */ if (tp->t_cflag & CLOCAL) {#ifdef DMZDEBUG if (dmzdebug) mprintf("dmzopen: local, unit=%d\n", unit);#endif tp->t_state |= TS_CARR_ON; dmzmodem[unit] = MODEM_CTS|MODEM_CD|MODEM_DSR; } else if ((flag & (O_NDELAY|O_NONBLOCK)) == 0) { oaddr->dmzcsr = DMZ_IE | DMZIR_TBUF | (unit&07); /* * DSR should not come up until DTR is asserted * normally. 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 * an enormously slow modem and it has not deasserted * DSR yet. */ if (oaddr->dmzrms&DMZ_DSR) {#ifdef notdef timeout(wakeup, (caddr_t) &tp->t_dev, 2*hz); sleep((caddr_t)&tp->t_dev, PZERO-10);#endif#ifdef DMZDEBUG if ((dmzdebug) && (oaddr->dmzrms&DMZ_DSR)) mprintf("dmz%d: DSR up before DTR\n", unit);#endif DMZDEBUG } /* * lets assume we have a valid DSR signal now */ oaddr->dmzcsr = DMZ_IE | DMZIR_TBUF | (unit&07);#ifdef DMZDEBUG if (dmzdebug) mprintf("dmzopen: is dsr up?, unit=%d\n", unit);#endif /* * 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 (dmzdsr) { if (oaddr->dmzrms&DMZ_DSR) {#ifdef DMZDEBUG if (dmzdebug) mprintf("dmzopen: dsr up, unit=%d\n", unit);#endif dmzmodem[unit] |= (MODEM_DSR_START|MODEM_DSR); tp->t_dev = dev; /* need it for timeouts */ timeout(dmz_dsr_check, tp, hz*30); timeout(dmz_dsr_check, tp, hz/2); } } else { dmzmodem[unit] |= (MODEM_DSR_START|MODEM_DSR); dmz_dsr_check(tp); } } if (flag & (O_NDELAY|O_NONBLOCK)) {#ifdef DMZDEBUG if (dmzdebug) mprintf("dmzopen: O_NDELAY, unit=%d\n", unit);#endif 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 wakeup is due to a false call. */ if (dmzmodem[unit]&MODEM_BADCALL){ splx(s); 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)) { splx(s); 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; splx(s); return ((*linesw[tp->t_line].l_open)(dev, tp));}/* * Close a DMZ32 line. *//*ARGSUSED*/dmzclose(dev, flag) dev_t dev; int flag;{ register struct tty *tp; register unit; register dmz, s; register struct octet *addr; unit = minor(dev); dmz = unit / NUMLINES; tp = &dmz_tty[unit];#ifdef DMZDEBUG if (dmzdebug) mprintf("dmzclose: unit=%d, oaddr=%x\n", unit, tp->t_addr);#endif s = spl5(); if (tp->t_line) (*linesw[tp->t_line].l_close)(tp); (void) dmzmctl(unit, DMZ_BRK, DMBIC); if ((tp->t_cflag&HUPCL) || (tp->t_state&TS_ISOPEN)==0) { (void) dmzmctl(unit, DMZ_OFF, DMSET); tp->t_state &= ~TS_CARR_ON; /* prevents recv intr. timeouts */ if ((tp->t_cflag & CLOCAL) == 0) {#ifdef DMZDEBUG if (dmzdebug) mprintf("dmzclose: drop dtr, unit=%d, oaddr=%x\n", unit, tp->t_addr);#endif tp->t_state |= TS_CLOSING; /* wait for DSR to drop */ addr = (struct octet *)tp->t_addr; addr->dmzcsr = DMZ_IE | DMZIR_TBUF | (unit&07); /* * If the DSR signal is being followed, give the modem * 5 seconds to deasset it. */ if (dmzdsr && (addr->dmzrms&DMZ_DSR)) { timeout(wakeup, (caddr_t) &tp->t_dev, 5*hz); sleep((caddr_t)&tp->t_dev, PZERO-10); } timeout(wakeup, (caddr_t) &tp->t_dev, hz/5); sleep((caddr_t)&tp->t_dev, PZERO-10);#ifdef DMZDEBUG if (dmzdebug && (addr->dmzrms&DMZ_DSR) ) mprintf("dmzclose: dsr still on, unit=%d, oaddr=%x\n", unit, tp->t_addr);#endif tp->t_state &= ~(TS_CLOSING); wakeup((caddr_t)&tp->t_rawq); } } /* reset line to default mode */ dmzsoftCAR[dmz] &= ~(1<<(unit%NUMLINES)); dmzsoftCAR[dmz] |= (1<<(unit%NUMLINES)) & dmzdefaultCAR[dmz]; ttyclose(tp); dmzmodem[unit] = 0; tty_def_close(tp); splx(s);}dmzread(dev, uio) dev_t dev; struct uio *uio;{ register struct tty *tp; tp = &dmz_tty[minor(dev)]; return ((*linesw[tp->t_line].l_read)(tp, uio));}dmzwrite(dev, uio) dev_t dev; struct uio *uio;{
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -