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

📄 mp.c

📁 早期freebsd实现
💻 C
📖 第 1 页 / 共 3 页
字号:
/* * 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. * *	@(#)mp.c	7.17 (Berkeley) 5/16/91 */#include "mp.h"#if NMP > 0/* * Multi Protocol Communications Controller (MPCC). * Asynchronous Terminal Protocol Support. */#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/errno.h"#include "sys/syslog.h"#include "sys/vmmac.h"#include "sys/kernel.h"#include "sys/clist.h"#include "../include/pte.h"#include "../include/mtpr.h"#include "../vba/vbavar.h"#include "../vba/mpreg.h"#define	MPCHUNK	16#define	MPPORT(n)	((n) & 0xf)#define	MPUNIT(n)	((n) >> 4)/* * Driver information for auto-configuration stuff. */int     mpprobe(), mpattach(), mpintr();struct  vba_device *mpinfo[NMP];long    mpstd[] = { 0 };struct  vba_driver mpdriver =    { mpprobe, 0, mpattach, 0, mpstd, "mp", mpinfo };int	mpstart();int	mpparam();struct	mpevent *mpparam2();struct	mpevent *mp_getevent();/* * The following structure is needed to deal with mpcc's convoluted * method for locating it's mblok structures (hold your stomach). * When an mpcc is reset at boot time it searches host memory * looking for a string that says ``ThIs Is MpCc''.  The mpcc * then reads the structure to locate the pointer to it's mblok * structure (you can wretch now). */struct mpbogus {	char	s[12];			/* `ThIs Is MpCc'' */	u_char	status;	u_char	unused;	u_short	magic;	struct	mblok *mb;	struct	mblok *mbloks[NMP];	/* can support at most 16 mpcc's */} mpbogus = { 'T','h','I','s',' ','I','s',' ','M','p','C','c' };/* * Software state per unit. */struct	mpsoftc {	u_int	ms_ivec;		/* interrupt vector */	u_int	ms_softCAR;		/* software carrier for async */	struct	mblok *ms_mb;		/* mpcc status area */	struct	vb_buf ms_buf;		/* vba resources for ms_mb */	struct	hxmtl ms_hxl[MPMAXPORT];/* host transmit list */	struct	asyncparam ms_async[MPMAXPORT][MPINSET];/* async structs */	char	ms_cbuf[MPMAXPORT][MPOUTSET][CBSIZE];/* input character buffers */} mp_softc[NMP];struct	speedtab	  mpspeedtab[] = {	9600,	M9600,	  /* baud rate = 9600 */	4800,	M4800,	  /* baud rate = 4800 */	2400,	M2400,	  /* baud rate = 2400 */	1800,	M1800,	  /* baud rate = 1800 */	1200,	M1200,	  /* baud rate = 1200 */	600,	M600,	  /* baud rate = 600 */	300,	M300,	  /* baud rate = 300 */	200,	M200,	  /* baud rate = 200 */	150,	M150,	  /* baud rate = 150 */	134,	M134_5,	  /* baud rate = 134.5 */	110,	M110,	  /* baud rate = 110 */	75,	M75,	  /* baud rate = 75 */	50,	M50,	  /* baud rate = 50 */	0,	M0,	  /* baud rate = 0 */	2000,	M2000,	  /* baud rate = 2000 */	3600,	M3600,	  /* baud rate = 3600 */	7200,	M7200,	  /* baud rate = 7200 */	19200,	M19200,	  /* baud rate = 19,200 */	24000,	M24000,	  /* baud rate = 24,000 */	28400,	M28400,	  /* baud rate = 28,400 */	37800,	M37800,	  /* baud rate = 37,800 */	40300,	M40300,	  /* baud rate = 40,300 */	48000,	M48000,	  /* baud rate = 48,000 */	52000,	M52000,	  /* baud rate = 52,000 */	56800,	M56800,	  /* baud rate = 56,800 */	EXTA,	MEXTA,	  /* baud rate = Ext A */	EXTB,	MEXTB,	  /* baud rate = Ext B */	-1,	-1,};struct	tty mp_tty[NMP*MPCHUNK];#ifndef lintint	nmp = NMP*MPCHUNK;#endifint	ttrstrt();mpprobe(reg, vi)	caddr_t reg;	struct vba_device *vi;{	register int br, cvec;	register struct mpsoftc *ms;#ifdef lint	br = 0; cvec = br; br = cvec;	mpintr(0);	mpdlintr(0);#endif	if (badaddr(reg, 2))		return (0);	ms = &mp_softc[vi->ui_unit];	/*	 * Allocate page tables and mblok	 * structure (mblok in non-cached memory).	 */	if (vbainit(&ms->ms_buf, sizeof (struct mblok), VB_32BIT) == 0) {		printf("mp%d: vbainit failed\n", vi->ui_unit);		return (0);	}	ms->ms_mb = (struct mblok *)ms->ms_buf.vb_rawbuf;	ms->ms_ivec = MPINTRBASE + 2*vi->ui_unit;	/* XXX */	br = 0x14, cvec = ms->ms_ivec;			/* XXX */	return (sizeof (*reg));}mpattach(vi)	register struct vba_device *vi;{	register struct mpsoftc *ms = &mp_softc[vi->ui_unit];	ms->ms_softCAR = vi->ui_flags;	/*	 * Setup pointer to mblok, initialize bogus	 * status block used by mpcc to locate the pointer	 * and then poke the mpcc to get it to search host	 * memory to find mblok pointer.	 */	mpbogus.mbloks[vi->ui_unit] = (struct mblok *)ms->ms_buf.vb_physbuf;	*(short *)vi->ui_addr = 0x100;		/* magic */}/* * Open an mpcc port. *//* ARGSUSED */mpopen(dev, mode)	dev_t dev;{	register struct tty *tp;	register struct mpsoftc *ms;	int error, s, port, unit, mpu;	struct vba_device *vi;	struct mpport *mp;	struct mpevent *ev;	unit = minor(dev);	mpu = MPUNIT(unit);	if (mpu >= NMP || (vi = mpinfo[mpu]) == 0 || vi->ui_alive == 0)		return (ENXIO);	tp = &mp_tty[unit];	if (tp->t_state & TS_XCLUDE && u.u_uid != 0)		return (EBUSY);	ms = &mp_softc[mpu];	port = MPPORT(unit);	if (ms->ms_mb->mb_proto[port] != MPPROTO_ASYNC ||	    ms->ms_mb->mb_status != MP_OPOPEN)		return (ENXIO);	mp = &ms->ms_mb->mb_port[port];		/* host mpcc struct */	s = spl8();	/*	 * serialize open and close events	 */	while ((mp->mp_flags & MP_PROGRESS) || ((tp->t_state & TS_WOPEN) && 	    !(mode&O_NONBLOCK) && !(tp->t_cflag&CLOCAL)))		if (error = tsleep((caddr_t)&tp->t_canq, TTIPRI | PCATCH,		    ttopen, 0)) {			splx(s);			return (error);		}restart:	tp->t_state |= TS_WOPEN;	tp->t_addr = (caddr_t)ms;	tp->t_oproc = mpstart;	tp->t_param = mpparam;	tp->t_dev = dev;	if ((tp->t_state & TS_ISOPEN) == 0) {		ttychars(tp);		if (tp->t_ispeed == 0) {			tp->t_ispeed = TTYDEF_SPEED;			tp->t_ospeed = TTYDEF_SPEED;			tp->t_iflag = TTYDEF_IFLAG;			tp->t_oflag = TTYDEF_OFLAG;			tp->t_lflag = TTYDEF_LFLAG;			tp->t_cflag = TTYDEF_CFLAG;		}		/*		 * Initialize port state: init MPCC interface		 * structures for port and setup modem control.		 */		error = mpportinit(ms, mp, port);		if (error)			goto bad;		ev = mpparam2(tp, &tp->t_termios);		if (ev == 0) {			error = ENOBUFS;			goto bad;		}		mp->mp_flags |= MP_PROGRESS;		mpcmd(ev, EVCMD_OPEN, 0, ms->ms_mb, port);		/*		 * wait for port to start		 */		while (mp->mp_proto != MPPROTO_ASYNC)			if (error = tsleep((caddr_t)&tp->t_canq,			    TTIPRI | PCATCH, ttopen, 0))				goto bad;		ttsetwater(tp);		mp->mp_flags &= ~MP_PROGRESS;	}	while ((mode&O_NONBLOCK) == 0 && (tp->t_cflag&CLOCAL) == 0 &&  	    (tp->t_state & TS_CARR_ON) == 0) {		if (error = ttysleep(tp, (caddr_t)&tp->t_rawq, TTIPRI | PCATCH,		    ttopen, 0))			goto bad;		/*		 * a mpclose() might have disabled port. if so restart		 */		if (mp->mp_proto != MPPROTO_ASYNC)			goto restart;		tp->t_state |= TS_WOPEN;	}	error = (*linesw[tp->t_line].l_open)(dev,tp);done:	splx(s);	/*	 * wakeup those processes waiting for the open to complete	 */	wakeup((caddr_t)&tp->t_canq);	return (error);bad:	tp->t_state &= ~TS_WOPEN;	goto done;}/* * Close an mpcc port. *//* ARGSUSED */mpclose(dev, flag)	dev_t dev;{	register struct tty *tp;	register struct mpport *mp;	register struct mpevent *ev;	int s, port, unit, error = 0;	struct mblok *mb;	unit = minor(dev);	tp = &mp_tty[unit];	port = MPPORT(unit);	mb = mp_softc[MPUNIT(unit)].ms_mb;	mp = &mb->mb_port[port];	s = spl8();	if (mp->mp_flags & MP_PROGRESS) {		if (mp->mp_flags & MP_REMBSY) {			mp->mp_flags &= ~MP_REMBSY;			splx(s);			return (0);		}		while (mp->mp_flags & MP_PROGRESS)			if (error = tsleep((caddr_t)&tp->t_canq,			    TTIPRI | PCATCH, ttclos, 0)) {				splx(s);				return (error);			}	}	mp->mp_flags |= MP_PROGRESS;	(*linesw[tp->t_line].l_close)(tp, flag);	ev = mp_getevent(mp, unit, 1);	if (ev == 0) {		error = ENOBUFS;		mp->mp_flags &= ~MP_PROGRESS;		goto out;	}	if (tp->t_state & TS_HUPCLS || (tp->t_state & TS_ISOPEN) == 0)		mpmodem(unit, MMOD_OFF);	else		mpmodem(unit, MMOD_ON);	mpcmd(ev, EVCMD_CLOSE, 0, mb, port);	error = ttyclose(tp);out:	if (mp->mp_flags & MP_REMBSY)		mpclean(mb, port);	else		while (mp->mp_flags & MP_PROGRESS && error == 0)			error = tsleep((caddr_t)&tp->t_canq, TTIPRI | PCATCH,			    ttclos, 0);	splx(s);	return (error);}/* * Read from an mpcc port. */mpread(dev, uio, flag)	dev_t dev;	struct uio *uio;{	struct tty *tp;	tp = &mp_tty[minor(dev)];	return ((*linesw[tp->t_line].l_read)(tp, uio, flag));}/* * Write to an mpcc port. */mpwrite(dev, uio, flag)	dev_t dev;	struct uio *uio;{	struct tty *tp;	tp = &mp_tty[minor(dev)];	return ((*linesw[tp->t_line].l_write)(tp, uio, flag));}/* * Ioctl for a mpcc port */mpioctl(dev, cmd, data, flag)	dev_t dev;	caddr_t data;{	register struct tty *tp;	register struct mpsoftc *ms;	register struct mpport *mp;	register struct mpevent *ev;	int s, port, error, unit;	struct mblok *mb;	unit = minor(dev);	tp = &mp_tty[unit];	ms = &mp_softc[MPUNIT(unit)];	mb = ms->ms_mb;	port = MPPORT(unit);	mp = &mb->mb_port[port];	if (mp->mp_proto != MPPROTO_ASYNC)		return(ENXIO);	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);	switch (cmd) {	case TIOCSBRK:			/* send break */	case TIOCCBRK:			/* clear break */		s = spl8();		while (mp->mp_flags & MP_IOCTL) {			if (error = tsleep((caddr_t)&tp->t_canq,			    TTIPRI | PCATCH, ttyout, 0)) {				splx(s);				return (error);			}			if (mp->mp_proto != MPPROTO_ASYNC) {				splx(s);				return (ENXIO);			}		}		ev = mp_getevent(mp, unit, 0);		if (ev) {			mp->mp_flags |= MP_IOCTL;			mpcmd(ev, EVCMD_IOCTL,			    (cmd == TIOCSBRK ? A_BRKON : A_BRKOFF), mb, port);		} else			error = ENOBUFS;		splx(s);		break;	case TIOCSDTR:			/* set dtr control line */		break;	case TIOCCDTR:			/* clear dtr control line */		break;	default:		error = ENOTTY;		break;	}	return (error);}mpparam(tp, t)	struct tty *tp;	struct termios *t;{	register struct mpevent *ev;	int unit = minor(tp->t_dev);	struct mpsoftc *ms = &mp_softc[MPUNIT(unit)];	struct mblok *mb = ms->ms_mb;	ev = mpparam2(tp, t);	if (ev == 0)		return (ENOBUFS);	mpcmd(ev, EVCMD_IOCTL, A_CHGALL, mb, MPPORT(unit));	return (0);}	struct mpevent *mpparam2(tp, t)	register struct tty *tp;	struct termios *t;{	register struct mpevent *ev;	register struct mpport *mp;	int unit = minor(tp->t_dev);	struct mblok *mb;	struct mpsoftc *ms;	register struct asyncparam *asp;	int port, speedcode;	ms = &mp_softc[MPUNIT(unit)];	mb = ms->ms_mb;	port = MPPORT(unit);	mp = &mb->mb_port[port];	ev = mp_getevent(mp, unit, 0);	/* XXX */	speedcode = ttspeedtab(t->c_ospeed, mpspeedtab);	if (ev == 0 || speedcode < 0) {printf("mp mpunit %d port %d param2 failed ev: %x speed %d, wanted %d\n",			MPUNIT(unit), port, ev, speedcode, t->c_ospeed);		return (0);	/* XXX */	}	/* YUCK */	asp = &ms->ms_async[port][mp->mp_on?mp->mp_on-1:MPINSET-1];	asp->ap_xon = t->c_cc[VSTART];	asp->ap_xoff = t->c_cc[VSTOP];	if (!(t->c_iflag&IXON) || (asp->ap_xon == _POSIX_VDISABLE) || 	    (asp->ap_xoff == _POSIX_VDISABLE))		asp->ap_xena = MPA_DIS;	else		asp->ap_xena = MPA_ENA;	asp->ap_xany = ((t->c_iflag & IXANY) ? MPA_ENA : MPA_DIS);#ifdef notnow	if (t->t_cflag&CSIZE) == CS8) {#endif		asp->ap_data = MPCHAR_8;		asp->ap_parity = MPPAR_NONE;#ifdef notnow	} else {		asp->ap_data = MPCHAR_7;		if ((t->c_flags & (EVENP|ODDP)) == ODDP) /* XXX */			asp->ap_parity = MPPAR_ODD;		else			asp->ap_parity = MPPAR_EVEN;	}#endif	asp->ap_loop = MPA_DIS;		/* disable loopback */	asp->ap_rtimer = A_RCVTIM;	/* default receive timer */	if (t->c_ospeed == B110)		asp->ap_stop = MPSTOP_2;	else		asp->ap_stop = MPSTOP_1;	if (t->c_ospeed == 0) {		tp->t_state |= TS_HUPCLS;		setm(&asp->ap_modem, 0, DROP);		seti(&asp->ap_intena, A_DCD);

⌨️ 快捷键说明

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