📄 dh.c
字号:
#ifndef lintstatic char *sccsid = "@(#)dh.c 4.1 ULTRIX 7/2/90";#endif lint/************************************************************************ * * * Copyright (c) 1988 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. * * * ************************************************************************//* dh.c 6.1 83/07/29 */#include "dh.h"#if NDH > 0 || defined(BINARY)/* * DH-11/DM-11 driver * 14-Apr-86 -- jaw * remove MAXNUBA referances.....use NUBA only! * * 18-mar-86 -- jaw br/cvec changed to NOT use registers. * * 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. * * 15-Dec-87 - Tim Burke * * changed t_intrc to tp->t_cc[VINTR] so that this code will compile * without errors in the wake of termio changes. Note that this driver * has not been updated to full termio compatibility with the other * device drivers and will probably not work any more. * * 28-Jan-88 - Tim Burke * * Changed references to t_ispeed and t_ospeed to use the POSIX cflag. * This is needed because t_ispeed and t_ospeed have been removed from * the tty structure. * These changes have been made to allow this driver to COMPILE in light * of the termio tty changes. To date these changes are not complete for * termio; nor have I been able to test them due to hardware unavailablity. */#include "../data/dh_data.c" /* * Definition of the driver for the auto-configuration program. * There is one definition for the dh and one for the dm. */int dhprobe(), dhattach(), dhrint(), dhxint(), dhtimer();u_short dhstd[] = { 0 };struct uba_driver dhdriver = { dhprobe, 0, dhattach, 0, dhstd, "dh", dhinfo };int dmprobe(), dmattach(), dmintr();u_short dmstd[] = { 0 };struct uba_driver dmdriver = { dmprobe, 0, dmattach, 0, dmstd, "dm", dminfo };#ifndef PORTSELECTOR#define ISPEED B300#define IFLAGS (EVENP|ODDP|ECHO)#define LFLAG (ISIG|ICANON|ECHO)#else#define ISPEED B4800#define IFLAGS (EVENP|ODDP)#define LFLAG (ISIG|ICANON)#endif/* termio flags will be set to these default values in non-termio mode to * provide a backward compatible ULTRIX environment. */#define IFLAG (BRKINT|IGNPAR|ISTRIP|IXON|IXANY)#define OFLAG (OPOST)#define CFLAG (PARENB|CREAD|CS7|ISPEED)#define FASTTIMER (hz/30) /* scan rate with silos on */int dhact; /* mask of active dh's */int dhsilos; /* mask of dh's with silo in use */int dhhighrate = 100; /* silo on if dhchars > dhhighrate */int dhlowrate = 75; /* silo off if dhrate < dhlowrate */static short timerstarted;int dhstart(), ttrstrt();/* * 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 force a dh to interrupt. * Set to transmit at 9600 baud, and cause a transmitter interrupt. *//*ARGSUSED*/dhprobe(reg) caddr_t reg;{ register struct dhdevice *dhaddr = (struct dhdevice *)reg;#ifdef lint if (ndh11 == 0) ndh11 = 1; dhrint(0); dhxint(0);#endif#ifndef notdef dhaddr->un.dhcsr = DH_RIE|DH_MM|DH_RI; DELAY(1000); dhaddr->un.dhcsr &= ~DH_RI; dhaddr->un.dhcsr = 0;#else dhaddr->un.dhcsr = DH_TIE; DELAY(5); dhaddr->dhlpr = (B9600 << 10) | (B9600 << 6) | BITS7|PENABLE; dhaddr->dhbcr = -1; dhaddr->dhcar = 0; dhaddr->dhbar = 1; DELAY(100000); /* wait 1/10'th of a sec for interrupt */ dhaddr->un.dhcsr = 0; if (cvec && cvec != 0x200) cvec -= 4; /* transmit -> receive */#endif return (sizeof (struct dhdevice));}/* * Routine called to attach a dh. */dhattach(ui) struct uba_device *ui;{ dhsoftCAR[ui->ui_unit] = ui->ui_flags; dhdefaultCAR[ui->ui_unit] = ui->ui_flags;}/* * Configuration routine to cause a dm to interrupt. */dmprobe(reg) caddr_t reg;{ register int br, vec; /* value-result */ register struct dmdevice *dmaddr = (struct dmdevice *)reg;#ifdef lint br = 0; vec = br; br = vec; dmintr(0);#endif dmaddr->dmcsr = DM_DONE|DM_IE; DELAY(20); dmaddr->dmcsr = 0; return (1);}/*ARGSUSED*/dmattach(ui) struct uba_device *ui;{ /* no local state to set up */}/* * Open a DH11 line, mapping the clist onto the uba if this * is the first dh on this uba. Turn on this dh if this is * the first use of it. Also do a dmopen to wait for carrier. *//*ARGSUSED*/dhopen(dev, flag) dev_t dev;{ register struct tty *tp; register int unit, dh; register struct dhdevice *addr; register struct uba_device *ui; int s; unit = minor(dev); dh = unit >> 4; if (unit >= nNDH*16 || (ui = dhinfo[dh])== 0 || ui->ui_alive == 0) return (ENXIO); tp = &dh11[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 dhdevice *)ui->ui_addr; tp->t_addr = (caddr_t)addr; tp->t_oproc = dhstart; tp->t_state |= TS_WOPEN; /* * While setting up state for this uba and this dh, * 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) { /* 512+ is a kludge to try to get around a hardware problem */ tty_ubinfo[ui->ui_ubanum] = -1; tty_ubinfo[ui->ui_ubanum] = uballoc(ui->ui_ubanum, (caddr_t)cfree, 512+nclist*sizeof(struct cblock), 0); wakeup(&tty_ubinfo[ui->ui_ubanum]); } cbase[ui->ui_ubanum] = tty_ubinfo[ui->ui_ubanum]&0x3ffff; if (timerstarted == 0) { timerstarted++; timeout(dhtimer, (caddr_t) 0, hz); } if ((dhact&(1<<dh)) == 0) { addr->un.dhcsr |= DH_IE; dhact |= (1<<dh); addr->dhsilo = 0; } splx(s); /* * If this is first open, initialze tty state to default. */ if ((tp->t_state&TS_ISOPEN) == 0) { ttychars(tp);#ifndef PORTSELECTOR if ((tp->t_cflag & CBAUD) == 0) {#endif tp->t_flags = IFLAGS; tp->t_iflag = IFLAG; tp->t_oflag = OFLAG; tp->t_lflag = LFLAG; tp->t_cflag = CFLAG; tp->t_cflag_ext = ISPEED;#ifndef PORTSELECTOR }#endif dhparam(unit); } /* * Wait for carrier, then process line discipline specific open. */ dmopen(dev, flag); return ((*linesw[tp->t_line].l_open)(dev, tp));}/* * Close a DH11 line, turning off the DM11. *//*ARGSUSED*/dhclose(dev, flag) dev_t dev; int flag;{ register struct tty *tp; register unit; register dh; unit = minor(dev); dh = unit >> 4; tp = &dh11[unit]; (*linesw[tp->t_line].l_close)(tp); ((struct dhdevice *)(tp->t_addr))->dhbreak &= ~(1<<(unit&017)); if (tp->t_cflag&HUPCL || (tp->t_state&TS_ISOPEN)==0) { dmctl(unit, DML_OFF, DMSET); if ((dhsoftCAR[dh] & (1<<(unit&0xf)))==0) { /*drop DTR for at least a sec. if modem line*/ tp->t_state |= TS_CLOSING; sleep((caddr_t)&lbolt, PZERO-10); sleep((caddr_t)&lbolt, PZERO-10); tp->t_state &= ~(TS_CLOSING); wakeup((caddr_t)&tp->t_rawq); } } dhsoftCAR[dh] &= ~(1<<(unit&0xf)); dhsoftCAR[dh] |= (1<<(unit&0xf)) & dhdefaultCAR[dh]; ttyclose(tp);}dhread(dev, uio) dev_t dev; struct uio *uio;{ register struct tty *tp = &dh11[minor(dev)]; return ((*linesw[tp->t_line].l_read)(tp, uio));}dhwrite(dev, uio) dev_t dev; struct uio *uio;{ register struct tty *tp = &dh11[minor(dev)]; return ((*linesw[tp->t_line].l_write)(tp, uio));}/* * DH11 receiver interrupt. */dhrint(dh) int dh;{ register struct tty *tp; register c; register struct dhdevice *addr; register struct tty *tp0; register struct uba_device *ui; int overrun = 0; ui = dhinfo[dh]; if (ui == 0 || ui->ui_alive == 0) return; addr = (struct dhdevice *)ui->ui_addr; tp0 = &dh11[dh<<4]; /* * Loop fetching characters from the silo for this * dh until there are no more in the silo. */ while ((c = addr->dhrcr) < 0) { tp = tp0 + ((c>>8)&0xf); dhchars[dh]++;#ifndef PORTSELECTOR if ((tp->t_state&TS_ISOPEN)==0) {#else if ((tp->t_state&(TS_ISOPEN|TS_WOPEN))==0) {#endif wakeup((caddr_t)tp); continue; } if (c & DH_PE) if ((tp->t_flags&(EVENP|ODDP))==EVENP || (tp->t_flags&(EVENP|ODDP))==ODDP ) continue; if ((c & DH_DO) && overrun == 0) { printf("dh%d: silo overflow\n", dh); overrun = 1; } if (c & DH_FE) /* * At framing error (break) generate * a null (in raw mode, for getty), or a * interrupt (in cooked/cbreak mode). */ if (tp->t_flags&RAW) c = 0; else { c = tp->t_cc[VINTR]; /* * Strip extraneous sign extension bits. */ c &= 0377; }#if NHC > 0 if (tp->t_line == HCLDISC) { HCINPUT(c, tp); } else#endif (*linesw[tp->t_line].l_rint)(c, tp); }}/* * Ioctl for DH11. *//*ARGSUSED*/dhioctl(dev, cmd, data, flag) caddr_t data;{ register struct tty *tp; register int unit = minor(dev); register int dh; register int s; int error; dh = unit >> 4; tp = &dh11[unit]; error = (*linesw[tp->t_line].l_ioctl)(tp, cmd, data, flag); if (error >= 0) return (error); error = ttioctl(tp, cmd, data, flag); if (error >= 0) { if (cmd == TIOCSETP || cmd == TIOCSETN) dhparam(unit); return (error); } switch (cmd) { case TIOCSBRK: ((struct dhdevice *)(tp->t_addr))->dhbreak |= 1<<(unit&017); break; case TIOCCBRK: ((struct dhdevice *)(tp->t_addr))->dhbreak &= ~(1<<(unit&017)); break; case TIOCSDTR: dmctl(unit, DML_DTR|DML_RTS, DMBIS); break; case TIOCCDTR: dmctl(unit, DML_DTR|DML_RTS, DMBIC); break; case TIOCNMODEM: /* ignore modem status */ s = spl5(); dhsoftCAR[dh] |= (1<<(unit&0xf)); if (*(int *)data) /* make mode permanent */ dhdefaultCAR[dh] |= (1<<(unit&0xf)); tp->t_state |= TS_CARR_ON; splx(s); break; case TIOCMODEM: /* look at modem status - sleep if no carrier */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -