📄 vx.c
字号:
/* * Copyright (c) 1988 Regents of the University of California. * All rights reserved. * * This code is derived from software contributed to Berkeley by * Computer Consoles Inc. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. All advertising materials mentioning features or use of this software * must display the following acknowledgement: * This product includes software developed by the University of * California, Berkeley and its contributors. * 4. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * @(#)vx.c 7.13 (Berkeley) 5/16/91 */#include "vx.h"#if NVX > 0/* * VIOC-X driver */#ifdef VXPERF#define DOSCOPE#endif#include "sys/param.h"#include "sys/ioctl.h"#include "sys/tty.h"#include "sys/user.h"#include "sys/map.h"#include "sys/buf.h"#include "sys/conf.h"#include "sys/file.h"#include "sys/proc.h"#include "sys/vm.h"#include "sys/kernel.h"#include "sys/syslog.h"#include "../include/pte.h"#include "../vba/vbavar.h"#include "../vba/vbaparam.h"#include "../vba/vxreg.h"#include "../vba/scope.h"#ifdef VX_DEBUGlong vxintr4 = 0;#define VXERR4 1#define VXNOBUF 2long vxdebug = 0;#define VXVCM 1#define VXVCC 2#define VXVCX 4#endif/* * Interrupt type bits passed to vinthandl(). */#define CMDquals 0 /* command completed interrupt */#define RSPquals 1 /* command response interrupt */#define UNSquals 2 /* unsolicited interrupt */#define VXUNIT(n) ((n) >> 4)#define VXPORT(n) ((n) & 0xf)struct tty vx_tty[NVX*16];#ifndef lintint nvx = NVX*16;#endifint vxstart(), ttrstrt();struct vxcmd *vobtain(), *nextcmd();/* * Driver information for auto-configuration stuff. */int vxprobe(), vxattach(), vxrint();struct vba_device *vxinfo[NVX];long vxstd[] = { 0 };struct vba_driver vxdriver = { vxprobe, 0, vxattach, 0, vxstd, "vx", vxinfo };struct vx_softc { struct vxdevice *vs_addr; /* H/W address */ u_char vs_type; /* 0: viox-x/vioc-b, 1: vioc-bop */ u_char vs_bop; /* bop board # for vioc-bop's */ u_char vs_loport; /* low port nbr */ u_char vs_hiport; /* high port nbr */ u_short vs_nbr; /* viocx number */ u_short vs_maxcmd; /* max number of concurrent cmds */ u_short vs_silosiz; /* silo size */ short vs_vers; /* vioc/pvioc version */#define VXV_OLD 0 /* PVIOCX | VIOCX */#define VXV_NEW 1 /* NPVIOCX | NVIOCX */ short vs_state; /* controller state */#define VXS_READY 0 /* ready for commands */#define VXS_RESET 1 /* in process of reseting */ u_short vs_softCAR; /* soft carrier */ u_int vs_ivec; /* interrupt vector base */ caddr_t vs_mricmd; /* most recent issued cmd */ /* The remaining fields are zeroed on reset... */#define vs_zero vs_xmtcnt int vs_xmtcnt; /* xmit commands pending */ struct vxcmd *vs_avail;/* next available command buffer */ struct vxcmd *vs_build; struct vxcmd vs_lst[NVCXBUFS]; struct vcmds vs_cmds;} vx_softc[NVX];struct speedtab vxspeedtab[] = { EXTA, V19200, EXTB, V19200, 19200, V19200, 9600, 13, 4800, 12, 2400, 11, 1800, 10, 1200, 9, 600, 8, 300, 7, 200, 6, 150, 5, 134, 4, 110, 3, 75, 2, 50, 1, 0, 0, -1, -1,};vxprobe(reg, vi) caddr_t reg; struct vba_device *vi;{ register int br, cvec; /* must be r12, r11 */ register struct vxdevice *vp; register struct vx_softc *vs; struct pte *dummypte;#ifdef lint br = 0; cvec = br; br = cvec; vackint(0); vunsol(0); vcmdrsp(0);#ifdef VX_DEBUG vxfreset(0);#endif#endif /* lint */ /* * If on an HCX-9, the device has a 32-bit address, * and we receive that address so we can set up a map. * On VERSAbus devices, the address is 24-bit, and is * already mapped (into vmem[]) by autoconf. */ if (!(reg >= vmem && reg < &vmem[ctob(VBIOSIZE)]) && /* XXX */ !vbmemalloc(16, reg, &dummypte, ®)) { printf("vx%d: vbmemalloc failed.\n", vi->ui_unit); return(0); } vp = (struct vxdevice *)reg; if (badaddr((caddr_t)vp, 1)) return (0); vp->v_fault = 0; vp->v_vioc = V_BSY; vp->v_hdwre = V_RESET; /* reset interrupt */ DELAY(4000000); if (vp->v_fault != VXF_READY) return (0); vs = &vx_softc[vi->ui_unit];#ifdef notdef /* * Align vioc interrupt vector base to 4 vector * boundary and fitting in 8 bits (is this necessary, * wish we had documentation). */ if ((vi->ui_hd->vh_lastiv -= 3) > 0xff) vi->ui_hd->vh_lastiv = 0xff; vs->vs_ivec = vi->ui_hd->vh_lastiv = vi->ui_hd->vh_lastiv &~ 0x3;#else vs->vs_ivec = 0x40+vi->ui_unit*4;#endif br = 0x18, cvec = vs->vs_ivec; /* XXX */ return (sizeof (struct vxdevice));}vxattach(vi) register struct vba_device *vi;{ register struct vx_softc *vs = &vx_softc[vi->ui_unit]; vs->vs_softCAR = vi->ui_flags; vs->vs_addr = (struct vxdevice *)vi->ui_addr; vxinit(vi->ui_unit, 1);}/* * Open a VX line. *//*ARGSUSED*/vxopen(dev, flag) dev_t dev; int flag;{ register struct tty *tp; /* pointer to tty struct for port */ register struct vx_softc *vs; register struct vba_device *vi; int unit, vx, s, error = 0; int vxparam(); unit = minor(dev); vx = VXUNIT(unit); if (vx >= NVX || (vi = vxinfo[vx])== 0 || vi->ui_alive == 0) return (ENXIO); vs = &vx_softc[vx]; tp = &vx_tty[unit]; unit = VXPORT(unit); if (tp->t_state&TS_XCLUDE && u.u_uid != 0) return (EBUSY); if (unit < vs->vs_loport || unit > vs->vs_hiport) return (ENXIO); tp->t_addr = (caddr_t)vs; tp->t_oproc = vxstart; tp->t_param = vxparam; tp->t_dev = dev; s = spl8(); if ((tp->t_state&TS_ISOPEN) == 0) { tp->t_state |= TS_WOPEN; ttychars(tp); if (tp->t_ispeed == 0) { tp->t_iflag = TTYDEF_IFLAG; tp->t_oflag = TTYDEF_OFLAG; tp->t_lflag = TTYDEF_LFLAG; tp->t_cflag = TTYDEF_CFLAG; tp->t_ispeed = tp->t_ospeed = TTYDEF_SPEED; } vxparam(tp, &tp->t_termios); ttsetwater(tp); } vcmodem(dev, VMOD_ON); while (!(flag&O_NONBLOCK) && !(tp->t_cflag&CLOCAL) && (tp->t_state&TS_CARR_ON) == 0) { tp->t_state |= TS_WOPEN; if (error = ttysleep(tp, (caddr_t)&tp->t_rawq, TTIPRI | PCATCH, ttopen, 0)) break; } if (error == 0) error = (*linesw[tp->t_line].l_open)(dev,tp); splx(s); return (error);}/* * Close a VX line. *//*ARGSUSED*/vxclose(dev, flag, mode, p) dev_t dev; int flag, mode; struct proc *p;{ register struct tty *tp; int unit, s, error = 0; unit = minor(dev); tp = &vx_tty[unit]; s = spl8(); (*linesw[tp->t_line].l_close)(tp, flag); if (tp->t_cflag & HUPCL || (tp->t_state & TS_ISOPEN) == 0) vcmodem(dev, VMOD_OFF); /* wait for the last response */ while (tp->t_state&TS_FLUSH && error == 0) error = tsleep((caddr_t)&tp->t_state, TTOPRI | PCATCH, ttclos, 0); splx(s); if (error) return (error); return (ttyclose(tp));}/* * Read from a VX line. */vxread(dev, uio, flag) dev_t dev; struct uio *uio;{ struct tty *tp = &vx_tty[minor(dev)]; return ((*linesw[tp->t_line].l_read)(tp, uio, flag));}/* * write on a VX line */vxwrite(dev, uio, flag) dev_t dev; struct uio *uio;{ register struct tty *tp = &vx_tty[minor(dev)]; return ((*linesw[tp->t_line].l_write)(tp, uio, flag));}/* * VIOCX unsolicited interrupt. */vxrint(vx) register vx;{ register struct tty *tp, *tp0; register struct vxdevice *addr; register struct vx_softc *vs; struct vba_device *vi; register int nc, c; register struct silo { u_char data, port; } *sp; short *osp; int overrun = 0; vi = vxinfo[vx]; if (vi == 0 || vi->ui_alive == 0) return; addr = (struct vxdevice *)vi->ui_addr; switch (addr->v_uqual&037) { case 0: break; case 2: if (addr->v_ustat == VP_SILO_OFLOW) log(LOG_ERR, "vx%d: input silo overflow\n", vx); else { printf("vx%d: vc proc err, ustat %x\n", vx, addr->v_ustat); vxstreset(vx); } return; case 3: vcmintr(vx); return; case 4: return; default: printf("vx%d: vc uqual err, uqual %x\n", vx, addr->v_uqual); vxstreset(vx); return; } vs = &vx_softc[vx]; if (vs->vs_vers == VXV_NEW) sp = (struct silo *)((caddr_t)addr + *(short *)addr->v_usdata); else sp = (struct silo *)((caddr_t)addr+VX_SILO+(addr->v_usdata[0]<<6)); nc = *(osp = (short *)sp); if (nc == 0) return; if (vs->vs_vers == VXV_NEW && nc > vs->vs_silosiz) { printf("vx%d: %d exceeds silo size\n", nc); nc = vs->vs_silosiz; } tp0 = &vx_tty[vx*16]; sp = (struct silo *)(((short *)sp)+1); for (; nc > 0; nc--, sp = (struct silo *)(((short *)sp)+1)) { c = sp->port & 017; if (vs->vs_loport > c || c > vs->vs_hiport) continue; tp = tp0 + c; if( (tp->t_state&TS_ISOPEN) == 0) { wakeup((caddr_t)&tp->t_rawq); continue; } c = sp->data&((tp->t_cflag&CSIZE)==CS8 ? 0xff : 0x7f); if ((sp->port&VX_RO) == VX_RO && !overrun) { log(LOG_ERR, "vx%d: receiver overrun\n", vi->ui_unit); overrun = 1; continue; } if (sp->port&VX_PE) c |= TTY_PE; if (sp->port&VX_FE) c |= TTY_FE; (*linesw[tp->t_line].l_rint)(c, tp); } *osp = 0;}/* * Ioctl for VX. */vxioctl(dev, cmd, data, flag) dev_t dev; caddr_t data;{ register struct tty *tp; int error; tp = &vx_tty[minor(dev)]; 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) return (error); return (ENOTTY);}vxparam(tp, t) struct tty *tp; struct termios *t;{ return (vxcparam(tp, t, 1));}/* * Set parameters from open or stty into the VX hardware * registers. */vxcparam(tp, t, wait) struct tty *tp; struct termios *t; int wait;{ register struct vx_softc *vs; register struct vxcmd *cp; int s, error = 0; int speedcode = ttspeedtab(t->c_ospeed, vxspeedtab); if (speedcode < 0 || (t->c_ispeed != t->c_ospeed && t->c_ispeed)) return (EINVAL); vs = (struct vx_softc *)tp->t_addr; cp = vobtain(vs); s = spl8(); /* * Construct ``load parameters'' command block * to setup baud rates, xon-xoff chars, parity, * and stop bits for the specified port. */ cp->cmd = VXC_LPARAX; cp->par[1] = VXPORT(minor(tp->t_dev)); /* * note: if the hardware does flow control, ^V doesn't work * to escape ^S */ if (t->c_iflag&IXON) { if (t->c_cc[VSTART] == _POSIX_VDISABLE) cp->par[2] = 0; else cp->par[2] = t->c_cc[VSTART]; if (t->c_cc[VSTOP] == _POSIX_VDISABLE) cp->par[3] = 0; else cp->par[3] = t->c_cc[VSTOP]; } else cp->par[2] = cp->par[3] = 0;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -