⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 vx.c

📁 早期freebsd实现
💻 C
📖 第 1 页 / 共 3 页
字号:
#ifdef notnow	switch (t->c_cflag & CSIZE) {	/* XXX */	case CS8:#endif		cp->par[4] = BITS8;		/* 8 bits of data */#ifdef notnow		break;	case CS7:		cp->par[4] = BITS7;		/* 7 bits of data */		break;	case CS6:		cp->par[4] = BITS6;		/* 6 bits of data */		break;	case CS5:		cp->par[4] = BITS5;		/* 5 bits of data */		break;	}	if ((t->c_cflag & PARENB) == 0)		/* XXX */#endif		cp->par[7] = VNOPARITY;		/* no parity */#ifdef notnow	else if (t->c_cflag&PARODD)		cp->par[7] = VODDP;	/* odd parity */	else		cp->par[7] = VEVENP;	/* even parity */#endif	cp->par[5] = (t->c_cflag&CSTOPB) ? VSTOP2 : VSTOP1;	cp->par[6] = speedcode;	if (vcmd((int)vs->vs_nbr, (caddr_t)&cp->cmd) && wait)		error = tsleep((caddr_t)cp, TTIPRI | PCATCH, ttyout, 0);	if ((t->c_ospeed)==0) {		tp->t_cflag |= HUPCL;		vcmodem(tp->t_dev, VMOD_OFF);	}	splx(s);	return (error);}/* * VIOCX command response interrupt. * For transmission, restart output to any active port. * For all other commands, just clean up. */vxxint(vx, cp)	register int vx;	register struct vxcmd *cp;{	register struct vxmit *vp;	register struct tty *tp, *tp0;	register struct vx_softc *vs;	vs = &vx_softc[vx];	cp = (struct vxcmd *)((long *)cp-1);	switch (cp->cmd&0xff00) {	case VXC_LIDENT:	/* initialization complete */		if (vs->vs_state == VXS_RESET) {			vxfnreset(vx, cp);			vinthandl(vx, ((V_BSY|RSPquals) << 8)|V_INTR);		}		cp->cmd++;		return;	case VXC_XMITDTA:	case VXC_XMITIMM:		break;	case VXC_LPARAX:		wakeup((caddr_t)cp);		/* fall thru... */	default:	/* VXC_MDMCTL or VXC_FDTATOX */		vrelease(vs, cp);		if (vs->vs_state == VXS_RESET)			vinthandl(vx, ((V_BSY|RSPquals) << 8)|V_INTR);		return;	}	tp0 = &vx_tty[vx*16];	vp = (struct vxmit *)(cp->par + (cp->cmd & 07)*sizeof (struct vxmit));	for (; vp >= (struct vxmit *)cp->par; vp--) {		tp = tp0 + (vp->line & 017);		tp->t_state &= ~TS_BUSY;		if (tp->t_state & TS_FLUSH) {			tp->t_state &= ~TS_FLUSH;			wakeup((caddr_t)&tp->t_state);		} else		 	ndflush(&tp->t_outq, vp->bcount+1);	}	vrelease(vs, cp);	if (vs->vs_vers == VXV_NEW)		(*linesw[tp->t_line].l_start)(tp);	else {		tp0 = &vx_tty[vx*16 + vs->vs_hiport];		for(tp = &vx_tty[vx*16 + vs->vs_loport]; tp <= tp0; tp++)			(*linesw[tp->t_line].l_start)(tp);		if ((cp = nextcmd(vs)) != NULL) {	/* command to send? */			vs->vs_xmtcnt++;			(void) vcmd(vx, (caddr_t)&cp->cmd);		}	}	vs->vs_xmtcnt--;}/* * Force out partial XMIT command after timeout */vxforce(vs)	register struct vx_softc *vs;{	register struct vxcmd *cp;	int s;	s = spl8();	if ((cp = nextcmd(vs)) != NULL) {		vs->vs_xmtcnt++;		(void) vcmd((int)vs->vs_nbr, (caddr_t)&cp->cmd);	}	splx(s);}/* * Start (restart) transmission on the given VX line. */vxstart(tp)	register struct tty *tp;{	register short n;	register struct vx_softc *vs;	int s, port;	s = spl8();	port = VXPORT(minor(tp->t_dev));	vs = (struct vx_softc *)tp->t_addr;	if ((tp->t_state&(TS_TIMEOUT|TS_BUSY|TS_TTSTOP)) == 0) {		if (tp->t_outq.c_cc <= tp->t_lowat) {			if (tp->t_state&TS_ASLEEP) {				tp->t_state &= ~TS_ASLEEP;				wakeup((caddr_t)&tp->t_outq);			}			if (tp->t_wsel) {				selwakeup(tp->t_wsel, tp->t_state & TS_WCOLL);				tp->t_wsel = 0;				tp->t_state &= ~TS_WCOLL;			}		}		if (tp->t_outq.c_cc == 0) {			splx(s);			return;		}		scope_out(3);		if (1 || !(tp->t_oflag&OPOST))	/* XXX */			n = ndqb(&tp->t_outq, 0);		else {			n = ndqb(&tp->t_outq, 0200);			if (n == 0) {				n = getc(&tp->t_outq);				timeout(ttrstrt, (caddr_t)tp, (n&0177)+6);				tp->t_state |= TS_TIMEOUT;				n = 0;			}		}		if (n) {			tp->t_state |= TS_BUSY;			vsetq(vs, port, (char *)tp->t_outq.c_cf, n);		}	}	splx(s);}/* * Stop output on a line. */vxstop(tp)	register struct tty *tp;{	int s;	s = spl8();	if (tp->t_state&TS_BUSY)		if ((tp->t_state&TS_TTSTOP) == 0)			tp->t_state |= TS_FLUSH;	splx(s);}static	int vxbbno = -1;/* * VIOCX Initialization.  Makes free lists of command buffers. * Resets all viocx's.  Issues a LIDENT command to each * viocx to establish interrupt vectors and logical port numbers. */vxinit(vx, wait)	register int vx;	int wait;{	register struct vx_softc *vs;	register struct vxdevice *addr;	register struct vxcmd *cp;	register char *resp;	register int j;	char type, *typestring;	vs = &vx_softc[vx];	addr = vs->vs_addr;	type = addr->v_ident;	vs->vs_vers = (type&VXT_NEW) ? VXV_NEW : VXV_OLD;	if (vs->vs_vers == VXV_NEW)		vs->vs_silosiz = addr->v_maxsilo;	switch (type) {	case VXT_VIOCX:	case VXT_VIOCX|VXT_NEW:		typestring = "VIOC-X";		/* set soft carrier for printer ports */		for (j = 0; j < 16; j++)			if (vs->vs_softCAR & (1 << j) ||			    addr->v_portyp[j] == VXT_PARALLEL) {				vs->vs_softCAR |= 1 << j;				addr->v_dcd |= 1 << j;			}		break;	case VXT_PVIOCX:	case VXT_PVIOCX|VXT_NEW:		typestring = "VIOC-X (old connector panel)";		break;	case VXT_VIOCBOP:		/* VIOC-BOP */		vs->vs_type = 1;		vs->vs_bop = ++vxbbno;		printf("VIOC-BOP no. %d at %x\n", vs->vs_bop, addr);		goto unsup;	default:		printf("vx%d: unknown type %x\n", vx, type);	unsup:		vxinfo[vx]->ui_alive = 0;		return;	}	vs->vs_nbr = vx;		/* assign board number */	vs->vs_maxcmd = (vs->vs_vers == VXV_NEW) ? 24 : 4;	/*	 * Initialize all cmd buffers by linking them	 * into a free list.	 */	for (j = 0; j < NVCXBUFS; j++) {		cp = &vs->vs_lst[j];		cp->c_fwd = &vs->vs_lst[j+1];	}	vs->vs_avail = &vs->vs_lst[0];	/* set idx to 1st free buf */	cp->c_fwd = (struct vxcmd *)0;	/* mark last buf in free list */	/*	 * Establish the interrupt vectors and define the port numbers.	 */	cp = vobtain(vs);	cp->cmd = VXC_LIDENT;	cp->par[0] = vs->vs_ivec; 	/* ack vector */	cp->par[1] = cp->par[0]+1;	/* cmd resp vector */	cp->par[3] = cp->par[0]+2;	/* unsol intr vector */	cp->par[4] = 15;		/* max ports, no longer used */	cp->par[5] = 0;			/* set 1st port number */	(void) vcmd(vx, (caddr_t)&cp->cmd);	if (!wait)		return;	for (j = 0; cp->cmd == VXC_LIDENT && j < 4000000; j++)		;	if (j >= 4000000)		printf("vx%d: didn't respond to LIDENT\n", vx);  	/* calculate address of response buffer */ 	resp = (char *)addr + (addr->v_rspoff&0x3fff);	if (resp[0] != 0 && (resp[0]&0177) != 3) {		vrelease(vs, cp);	/* init failed */		return;	}	vs->vs_loport = cp->par[5];	vs->vs_hiport = cp->par[7];	printf("vx%d: %s%s, ports %d-%d\n", vx,	    (vs->vs_vers == VXV_NEW) ? "" : "old ", typestring,	    vs->vs_loport, vs->vs_hiport);	vrelease(vs, cp);}/* * Obtain a command buffer */struct vxcmd *vobtain(vs)	register struct vx_softc *vs;{	register struct vxcmd *p;	int s;	s = spl8();	p = vs->vs_avail;	if (p == (struct vxcmd *)0) {#ifdef VX_DEBUG		if (vxintr4&VXNOBUF)			vxintr4 &= ~VXNOBUF;#endif		printf("vx%d: no buffers\n", vs->vs_nbr);		vxstreset(vs->vs_nbr);		splx(s);		return (vobtain(vs));	}	vs->vs_avail = p->c_fwd;	splx(s);	return ((struct vxcmd *)p);}/* * Release a command buffer */vrelease(vs, cp)	register struct vx_softc *vs;	register struct vxcmd *cp;{	int s;#ifdef VX_DEBUG	if (vxintr4&VXNOBUF)		return;#endif	s = spl8();	cp->c_fwd = vs->vs_avail;	vs->vs_avail = cp;	splx(s);}struct vxcmd *nextcmd(vs)	register struct vx_softc *vs;{	register struct vxcmd *cp;	int s;	s = spl8();	cp = vs->vs_build;	vs->vs_build = (struct vxcmd *)0;	splx(s);	return (cp);}/* * Assemble transmits into a multiple command; * up to 8 transmits to 8 lines can be assembled together * (on PVIOCX only). */vsetq(vs, line, addr, n)	register struct vx_softc *vs;	caddr_t	addr;{	register struct vxcmd *cp;	register struct vxmit *mp;	/*	 * Grab a new command buffer or append	 * to the current one being built.	 */	cp = vs->vs_build;	if (cp == (struct vxcmd *)0) {		cp = vobtain(vs);		vs->vs_build = cp;		cp->cmd = VXC_XMITDTA;	} else {		if ((cp->cmd & 07) == 07 || vs->vs_vers == VXV_NEW) {			printf("vx%d: setq overflow\n", vs-vx_softc);			vxstreset((int)vs->vs_nbr);			return;		}		cp->cmd++;	}	/*	 * Select the next vxmit buffer and copy the	 * characters into the buffer (if there's room	 * and the device supports ``immediate mode'',	 * or store an indirect pointer to the data.	 */	mp = (struct vxmit *)(cp->par + (cp->cmd & 07)*sizeof (struct vxmit));	mp->bcount = n-1;	mp->line = line;	if (vs->vs_vers == VXV_NEW && n <= sizeof (mp->ostream)) {		cp->cmd = VXC_XMITIMM;		bcopy(addr, mp->ostream, (unsigned)n);	} else {		/* get system address of clist block */		addr = (caddr_t)vtoph((struct proc *)0, (unsigned)addr);		bcopy((caddr_t)&addr, mp->ostream, sizeof (addr));	}	/*	 * We send the data immediately if a VIOCX,	 * the command buffer is full, or if we've nothing	 * currently outstanding.  If we don't send it,	 * set a timeout to force the data to be sent soon.	 */	if (vs->vs_vers == VXV_NEW || (cp->cmd & 07) == 7 ||	    vs->vs_xmtcnt == 0) {		vs->vs_xmtcnt++;		(void) vcmd((int)vs->vs_nbr, (char *)&cp->cmd);		vs->vs_build = 0;	} else		timeout(vxforce, (caddr_t)vs, 3);}/* * Write a command out to the VIOC */vcmd(vx, cmdad)	register int vx;	register caddr_t cmdad;{	register struct vcmds *cp;	register struct vx_softc *vs = &vx_softc[vx];	int s;	s = spl8();	/*	 * When the vioc is resetting, don't process	 * anything other than VXC_LIDENT commands.	 */	if (vs->vs_state == VXS_RESET && cmdad != NULL) {		struct vxcmd *vcp = (struct vxcmd *)(cmdad-sizeof (vcp->c_fwd));		if (vcp->cmd != VXC_LIDENT) {			vrelease(vs, vcp);			return (0);		}	}	cp = &vs->vs_cmds;	if (cmdad != (caddr_t)0) {		cp->cmdbuf[cp->v_fill] = cmdad;		if (++cp->v_fill >= VC_CMDBUFL)			cp->v_fill = 0;		if (cp->v_fill == cp->v_empty) {			printf("vx%d: cmd q overflow\n", vx);			vxstreset(vx);			splx(s);			return (0);		}		cp->v_cmdsem++;	}	if (cp->v_cmdsem && cp->v_curcnt < vs->vs_maxcmd) {		cp->v_cmdsem--;		cp->v_curcnt++;		vinthandl(vx, ((V_BSY|CMDquals) << 8)|V_INTR);	}	splx(s);	return (1);}/* * VIOC acknowledge interrupt.  The VIOC has received the new * command.  If no errors, the new command becomes one of 16 (max) * current commands being executed. */vackint(vx)	register vx;{	register struct vxdevice *vp;	register struct vcmds *cp;	struct vx_softc *vs;	int s;	scope_out(5);	vs = &vx_softc[vx];	if (vs->vs_type)	/* Its a BOP */		return;	s = spl8();	vp = vs->vs_addr;	cp = &vs->vs_cmds;	if (vp->v_vcid&V_ERR) {		register char *resp;		register i;

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -