📄 dmf.c
字号:
#ifndef lintstatic char *sccsid = "@(#)dmf.c 4.2 (ULTRIX) 8/13/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. * * * ************************************************************************//* * dmf.c 6.1 7/29/83 * * Modification history * * DMF32 terminal driver * * 5-May-85 - Larry Cohen * * Derived from 4.2BSD labeled: dmf.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 dmfrint, record present time in timestamp in the event of * a carrier drop. * * 25-Aug-86 - Tim Burke * * Insure that line drops and restarts on false calls. Also change * state to ~TS_CARR_ON to terminate all processes on line. * * 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. * * 4-Dec-86 - Tim Burke * * Bug fix to modem control. In dmf_tty_drop routine, clear the stopped * state to prevent modem lines from hanging on close. * * 4-Dec-86 - Tim Burke * * Bug fix to dmfreset code. Saves software programmable interrupt * vector as established in the probe routine so that it may be restored * in the reset routine. * * 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-87 - 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 dmfdsr to "1", to * ignore "DSR" set dmfdsr to be "0"; * * 6-Feb-87 - Tim Burke * * Removed printf of master reset failure in probe routine, as it may be * incorrectly appearing. (Particularly in the DMF & DMZ drivers) * * 3-Mar-87 - Tim Burke * * Added full TERMIO functionality to terminal subsystem. * * 2-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. * * 8-Sep-87 - Ricky Palmer (rsp) * * Defined LINEMASK for this driver and replaced all hardcoded references * to "07" to be LINEMASK. Also fixed DEVIOCGET code to use LINEMASK * as well. * * * 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'. * * 02-Sep-88 - Tim Burke * * Return EINVAL instead of ENOTTY for POSIX programs on invalid ioctls. * * 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. * * July 5, 1990 Kuo-Hsiung Hsieh * Added a delay before we set a break condition on a transmission * line. On dmf async drive, a break might be insert before a * character if there happened to be a character in the transmission * buffer. This will cause some problems in interpreting actual * flow of data in this io stream. The fix is similar to DC driver, * except there is no data corruption problem involved here. */#include "dmf.h"#if NDMF > 0 || defined(BINARY)#include "../data/dmf_data.c"/* * The line printer port is indicated by a minor device code of 128+x. * The flags field of the config file is interpreted as: * * bits meaning * ---- ------- * 0-7 soft carrier bits for ttys part of dmf32 * 8-15 number of cols/line on the line printer * if 0, 132 will be used. * 16-23 number of lines/page on the line printer * if 0, 66 will be used. * *//* * Definition of the driver for the auto-configuration program. */int dmfprobe(), dmfattach(), dmfrint(), dmfxint(), dmfbaudrate();int dmf_cd_drop(), dmf_dsr_check(), dmf_cd_down(), dmf_tty_drop();void dmfsetbreak();struct timeval dmfzerotime = {0,0};int dmfcdtime = 2;int dmflint();struct uba_device *dmfinfo[NDMF];u_short dmfstd[] = { 0 };struct uba_driver dmfdriver = { dmfprobe, 0, dmfattach, 0, dmfstd, "dmf", dmfinfo };int dmfdebug;int dmf_timeout = 10; /* silo timeout, in ms */int dmf_mindma = 4; /* don't dma below this point *//* * Local variables for the driver */char dmf_speeds[] = { 0, 0, 1, 2, 3, 4, 0, 5, 6, 7, 010, 012, 014, 016, 017, 0 };/* minumum delay value for setting a break condition. If we set * a break condition without delaying this minimum interval, we * might insert a break in the middle of a character string. This * could cause side effect in processing io buffer. * The delay values are calculated based on the following equation; * 12 (bits/char) * 64 (hz) / baudrate + 2 (safety factor). * B50 is an exception. It required - 32 (1/2 hz). This is almost * equivalent to two character time. */u_char dmf_delay[] = {0,32,13,9,8,7,0,5,4,3,3,3,2,2,2,0};short dmf_valid_speeds = 0x7fbf; /* 0,1,1,1, 1,1,1,1, 1,0,1,1, 1,1,1,1 */#define ASLP 1 /* waiting for interrupt from dmf */#define OPEN 2 /* line printer is open */#define ERROR 4 /* error while printing, driver refuses to do anything till closed */int dmfstart(), ttrstrt();#ifndef MODEM_CD#define MODEM_CD 0x01#define MODEM_DSR 0x02#define MODEM_CTS 0x04#define MODEM_DSR_START 0x08#endif#define LINEMASK 0x07 /* mask of higher bits of csr to get a line # *//* * 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 dmf interrupt. *//*ARGSUSED*/dmfprobe(reg) caddr_t reg;{ register struct dmfdevice *dmfaddr = (struct dmfdevice *)reg; register int totaldelay;#ifdef lint dmfxint(0); dmfrint(0); dmfsrint(); dmfsxint(); dmfdaint(); dmfdbint(); dmflint();#endif if(dmfdebug) printf("dmfprobe\n"); /* * If a self test is not being done, start one up. Wait for the * self-test (to a max of 4 sec.) to complete before interrupting. */ if ((dmfaddr->dmfcsr & DMF_CLR) == 0) dmfaddr->dmfcsr |= DMF_CLR; totaldelay = 0; while ( (dmfaddr->dmfcsr & DMF_CLR) && ( totaldelay <= 70) ){ totaldelay++; DELAY(50000); } /* * This message may be incorrectly printed - particularly in the * DMF & DMZ drivers. if (dmfaddr->dmfcsr & DMF_CLR) printf("Warning: DMF device failed to exit self-test\n"); */ br = 0x15; cvec = (uba_hd[numuba].uh_lastiv -= 4*8); dmfaddr->dmfccsr0 = (cvec >> 2); dmfaddr->dmfl[0] = DMFL_RESET; /* NEED TO SAVE IT SOMEWHERE FOR OTHER DEVICES */ return (sizeof (struct dmfdevice));}/* * Routine called to attach a dmf. */dmfattach(ui) struct uba_device *ui;{ register int cols = (ui->ui_flags>>8) & 0xff; register int lines = (ui->ui_flags>>16) & 0xff; dmfsoftCAR[ui->ui_unit] = ui->ui_flags & 0xff; dmfdefaultCAR[ui->ui_unit] = ui->ui_flags & 0xff; dmfl_softc[ui->ui_unit].dmfl_cols = cols==0?DMFL_DEFCOLS:cols; dmfl_softc[ui->ui_unit].dmfl_lines = lines==0?DMFL_DEFLINES:lines;}/* * Open a DMF32 line, mapping the clist onto the uba if this * is the first dmf on this uba. Turn on this dmf if this is * the first use of it. *//*ARGSUSED*/dmfopen(dev, flag) dev_t dev;{ register struct tty *tp; register int unit, dmf; register struct dmfdevice *addr; register struct uba_device *ui; int s; int inuse; /*hold state of inuse bit while blocked waiting for carr*/ unit = minor(dev); if(unit & 0200) return(dmflopen(dev,flag)); dmf = unit >> 3; if (unit >= ndmf || (ui = dmfinfo[dmf])== 0 || ui->ui_alive == 0) return (ENXIO); tp = &dmf_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); addr = (struct dmfdevice *)ui->ui_addr; tp->t_addr = (caddr_t)addr; tp->t_oproc = dmfstart; tp->t_baudrate = dmfbaudrate; tp->t_state |= TS_WOPEN; /* * While setting up state for this uba and this dmf, * 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; addr->dmfcsr |= DMF_IE; splx(s); if ((tp->t_state&TS_ISOPEN) == 0) { dmfmodem[unit] = MODEM_DSR_START; /* prevents spurious startups */ addr->dmfrsp = dmf_timeout; } tty_def_open(tp, dev, flag, (dmfsoftCAR[dmf]&(1<<(unit&LINEMASK)))); dmfparam(unit); /* * Wait for carrier, then process line discipline specific open. */ s = spl5(); dmfmctl(dev, DMF_ON, DMSET); /* set DTR */ if (tp->t_cflag & CLOCAL) {#ifdef DMFDEBUG if (dmfdebug) mprintf("dmfopen: local, unit=%d\n", unit);#endif tp->t_state |= TS_CARR_ON; dmfmodem[unit] = MODEM_CTS|MODEM_CD|MODEM_DSR; } else if ((flag & (O_NDELAY|O_NONBLOCK)) == 0) { /* * 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. */ addr->dmfcsr = DMF_IE | DMFIR_TBUF | (unit&LINEMASK); /* * 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 (dmfdsr) { if (addr->dmfrms&DMF_DSR) {#ifdef DMFDEBUG if (dmfdebug) mprintf("dmfopen: modem, unit=%d\n", unit);#endif dmfmodem[unit] |= (MODEM_DSR_START|MODEM_DSR); tp->t_dev = dev; /* need it for timeouts */ timeout(dmf_dsr_check, tp, hz*30); timeout(dmf_dsr_check, tp, hz/2); } } else { dmfmodem[unit] |= (MODEM_DSR_START|MODEM_DSR); dmf_dsr_check(tp); } } if (flag & (O_NDELAY|O_NONBLOCK)) tp->t_state |= TS_ONDELAY; else
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -