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

📄 dcm.c

📁 早期freebsd实现
💻 C
📖 第 1 页 / 共 3 页
字号:
/* * Copyright (c) 1988 University of Utah. * Copyright (c) 1982, 1986, 1990, 1993 *	The Regents of the University of California.  All rights reserved. * * This code is derived from software contributed to Berkeley by * the Systems Programming Group of the University of Utah Computer * Science Department. * * 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. * * from Utah: $Hdr: dcm.c 1.29 92/01/21$ * *	@(#)dcm.c	8.4 (Berkeley) 1/12/94 *//* * TODO: *	Timeouts *	Test console support. */#include "dcm.h"#if NDCM > 0/* *  98642/MUX */#include <sys/param.h>#include <sys/systm.h>#include <sys/ioctl.h>#include <sys/proc.h>#include <sys/tty.h>#include <sys/conf.h>#include <sys/file.h>#include <sys/uio.h>#include <sys/kernel.h>#include <sys/syslog.h>#include <sys/time.h>#include <hp/dev/device.h>#include <hp300/dev/dcmreg.h>#include <machine/cpu.h>#include <hp300/hp300/isr.h>#ifndef DEFAULT_BAUD_RATE#define DEFAULT_BAUD_RATE 9600#endifint	dcmprobe(), dcmintr(), dcmparam();void	dcmstart();struct	driver dcmdriver = {	dcmprobe, "dcm",};#define NDCMLINE (NDCM*4)struct	tty dcm_tty[NDCMLINE];struct	modemreg *dcm_modem[NDCMLINE];char	mcndlast[NDCMLINE];	/* XXX last modem status for line */int	ndcm = NDCMLINE;int	dcm_active;int	dcmsoftCAR[NDCM];struct	dcmdevice *dcm_addr[NDCM];struct	isr dcmisr[NDCM];struct speedtab dcmspeedtab[] = {	0,	BR_0,	50,	BR_50,	75,	BR_75,	110,	BR_110,	134,	BR_134,	150,	BR_150,	300,	BR_300,	600,	BR_600,	1200,	BR_1200,	1800,	BR_1800,	2400,	BR_2400,	4800,	BR_4800,	9600,	BR_9600,	19200,	BR_19200,	38400,	BR_38400,	-1,	-1};/* u-sec per character based on baudrate (assumes 1 start/8 data/1 stop bit) */#define	DCM_USPERCH(s)	(10000000 / (s))/* * Per board interrupt scheme.  16.7ms is the polling interrupt rate * (16.7ms is about 550 baud, 38.4k is 72 chars in 16.7ms). */#define DIS_TIMER	0#define DIS_PERCHAR	1#define DIS_RESET	2int	dcmistype = -1;		/* -1 == dynamic, 0 == timer, 1 == perchar */int     dcminterval = 5;	/* interval (secs) between checks */struct	dcmischeme {	int	dis_perchar;	/* non-zero if interrupting per char */	long	dis_time;	/* last time examined */	int	dis_intr;	/* recv interrupts during last interval */	int	dis_char;	/* characters read during last interval */} dcmischeme[NDCM];/* * Console support */#ifdef DCMCONSOLEint	dcmconsole = DCMCONSOLE;#elseint	dcmconsole = -1;#endifint	dcmconsinit;int	dcmdefaultrate = DEFAULT_BAUD_RATE;int	dcmconbrdbusy = 0;int	dcmmajor;extern	struct tty *constty;#ifdef KGDB/* * Kernel GDB support */#include <machine/remote-sl.h>extern dev_t kgdb_dev;extern int kgdb_rate;extern int kgdb_debug_init;#endif/* #define DCMSTATS */#ifdef DEBUGint	dcmdebug = 0x0;#define DDB_SIOERR	0x01#define DDB_PARAM	0x02#define DDB_INPUT	0x04#define DDB_OUTPUT	0x08#define DDB_INTR	0x10#define DDB_IOCTL	0x20#define DDB_INTSCHM	0x40#define DDB_MODEM	0x80#define DDB_OPENCLOSE	0x100#endif#ifdef DCMSTATS#define	DCMRBSIZE	94#define DCMXBSIZE	24struct	dcmstats {	long	xints;		    /* # of xmit ints */	long	xchars;		    /* # of xmit chars */	long	xempty;		    /* times outq is empty in dcmstart */	long	xrestarts;	    /* times completed while xmitting */	long	rints;		    /* # of recv ints */	long	rchars;		    /* # of recv chars */	long	xsilo[DCMXBSIZE+2]; /* times this many chars xmit on one int */	long	rsilo[DCMRBSIZE+2]; /* times this many chars read on one int */} dcmstats[NDCM];#endif#define UNIT(x)		minor(x)#define	BOARD(x)	(((x) >> 2) & 0x3f)#define PORT(x)		((x) & 3)#define MKUNIT(b,p)	(((b) << 2) | (p))/* * Conversion from "HP DCE" to almost-normal DCE: on the 638 8-port mux, * the distribution panel uses "HP DCE" conventions.  If requested via * the device flags, we swap the inputs to something closer to normal DCE, * allowing a straight-through cable to a DTE or a reversed cable * to a DCE (reversing 2-3, 4-5, 8-20 and leaving 6 unconnected; * this gets "DCD" on pin 20 and "CTS" on 4, but doesn't connect * DSR or make RTS work, though).  The following gives the full * details of a cable from this mux panel to a modem: * *		     HP		    modem *		name	pin	pin	name * HP inputs: *		"Rx"	 2	 3	Tx *		CTS	 4	 5	CTS	(only needed for CCTS_OFLOW) *		DCD	20	 8	DCD *		"DSR"	 9	 6	DSR	(unneeded) *		RI	22	22	RI	(unneeded) * * HP outputs: *		"Tx"	 3	 2	Rx *		"DTR"	 6	not connected *		"RTS"	 8	20	DTR *		"SR"	23	 4	RTS	(often not needed) */#define	FLAG_STDDCE	0x10	/* map inputs if this bit is set in flags */#define hp2dce_in(ibits)	(iconv[(ibits) & 0xf])static char iconv[16] = {	0,		MI_DM,		MI_CTS,		MI_CTS|MI_DM,	MI_CD,		MI_CD|MI_DM,	MI_CD|MI_CTS,	MI_CD|MI_CTS|MI_DM,	MI_RI,		MI_RI|MI_DM,	MI_RI|MI_CTS,	MI_RI|MI_CTS|MI_DM,	MI_RI|MI_CD,	MI_RI|MI_CD|MI_DM, MI_RI|MI_CD|MI_CTS,	MI_RI|MI_CD|MI_CTS|MI_DM};dcmprobe(hd)	register struct hp_device *hd;{	register struct dcmdevice *dcm;	register int i;	register int timo = 0;	int s, brd, isconsole, mbits;	dcm = (struct dcmdevice *)hd->hp_addr;	if ((dcm->dcm_rsid & 0x1f) != DCMID)		return (0);	brd = hd->hp_unit;	isconsole = (brd == BOARD(dcmconsole));	/*	 * XXX selected console device (CONSUNIT) as determined by	 * dcmcnprobe does not agree with logical numbering imposed	 * by the config file (i.e. lowest address DCM is not unit	 * CONSUNIT).  Don't recognize this card.	 */	if (isconsole && dcm != dcm_addr[BOARD(dcmconsole)])		return (0);	/*	 * Empirically derived self-test magic	 */	s = spltty();	dcm->dcm_rsid = DCMRS;	DELAY(50000);	/* 5000 is not long enough */	dcm->dcm_rsid = 0; 	dcm->dcm_ic = IC_IE;	dcm->dcm_cr = CR_SELFT;	while ((dcm->dcm_ic & IC_IR) == 0)		if (++timo == 20000)			return (0);	DELAY(50000)	/* XXX why is this needed ???? */	while ((dcm->dcm_iir & IIR_SELFT) == 0)		if (++timo == 400000)			return (0);	DELAY(50000)	/* XXX why is this needed ???? */	if (dcm->dcm_stcon != ST_OK) {		if (!isconsole)			printf("dcm%d: self test failed: %x\n",			       brd, dcm->dcm_stcon);		return (0);	}	dcm->dcm_ic = IC_ID;	splx(s);	hd->hp_ipl = DCMIPL(dcm->dcm_ic);	dcm_addr[brd] = dcm;	dcm_active |= 1 << brd;	dcmsoftCAR[brd] = hd->hp_flags;	dcmisr[brd].isr_ipl = hd->hp_ipl;	dcmisr[brd].isr_arg = brd;	dcmisr[brd].isr_intr = dcmintr;	isrlink(&dcmisr[brd]);#ifdef KGDB	if (major(kgdb_dev) == dcmmajor && BOARD(kgdb_dev) == brd) {		if (dcmconsole == UNIT(kgdb_dev))			kgdb_dev = NODEV; /* can't debug over console port */#ifndef KGDB_CHEAT		/*		 * The following could potentially be replaced		 * by the corresponding code in dcmcnprobe.		 */		else {			(void) dcminit(kgdb_dev, kgdb_rate);			if (kgdb_debug_init) {				printf("dcm%d: ", UNIT(kgdb_dev));				kgdb_connect(1);			} else				printf("dcm%d: kgdb enabled\n", UNIT(kgdb_dev));		}		/* end could be replaced */#endif	}#endif	if (dcmistype == DIS_TIMER)		dcmsetischeme(brd, DIS_RESET|DIS_TIMER);	else		dcmsetischeme(brd, DIS_RESET|DIS_PERCHAR);	/* load pointers to modem control */	dcm_modem[MKUNIT(brd, 0)] = &dcm->dcm_modem0;	dcm_modem[MKUNIT(brd, 1)] = &dcm->dcm_modem1;	dcm_modem[MKUNIT(brd, 2)] = &dcm->dcm_modem2;	dcm_modem[MKUNIT(brd, 3)] = &dcm->dcm_modem3;	/* set DCD (modem) and CTS (flow control) on all ports */	if (dcmsoftCAR[brd] & FLAG_STDDCE)		mbits = hp2dce_in(MI_CD|MI_CTS);	else		mbits = MI_CD|MI_CTS;	for (i = 0; i < 4; i++)		dcm_modem[MKUNIT(brd, i)]->mdmmsk = mbits;	dcm->dcm_ic = IC_IE;		/* turn all interrupts on */	/*	 * Need to reset baud rate, etc. of next print so reset dcmconsole.	 * Also make sure console is always "hardwired"	 */	if (isconsole) {		dcmconsinit = 0;		dcmsoftCAR[brd] |= (1 << PORT(dcmconsole));	}	return (1);}/* ARGSUSED */#ifdef __STDC__dcmopen(dev_t dev, int flag, int mode, struct proc *p)#elsedcmopen(dev, flag, mode, p)	dev_t dev;	int flag, mode;	struct proc *p;#endif{	register struct tty *tp;	register int unit, brd;	int error = 0, mbits;	unit = UNIT(dev);	brd = BOARD(unit);	if (unit >= NDCMLINE || (dcm_active & (1 << brd)) == 0)		return (ENXIO);	tp = &dcm_tty[unit];	tp->t_oproc = dcmstart;	tp->t_param = dcmparam;	tp->t_dev = dev;	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_cflag = TTYDEF_CFLAG;			tp->t_lflag = TTYDEF_LFLAG;			tp->t_ispeed = tp->t_ospeed = TTYDEF_SPEED;		}		(void) dcmparam(tp, &tp->t_termios);		ttsetwater(tp);	} else if (tp->t_state&TS_XCLUDE && p->p_ucred->cr_uid != 0)		return (EBUSY);	mbits = MO_ON;	if (dcmsoftCAR[brd] & FLAG_STDDCE)		mbits |= MO_SR;		/* pin 23, could be used as RTS */	(void) dcmmctl(dev, mbits, DMSET);	/* enable port */	if ((dcmsoftCAR[brd] & (1 << PORT(unit))) ||	    (dcmmctl(dev, MO_OFF, DMGET) & MI_CD))		tp->t_state |= TS_CARR_ON;#ifdef DEBUG	if (dcmdebug & DDB_MODEM)		printf("dcm%d: dcmopen port %d softcarr %c\n",		       brd, unit, (tp->t_state & TS_CARR_ON) ? '1' : '0');#endif	(void) spltty();	while ((flag&O_NONBLOCK) == 0 && (tp->t_cflag&CLOCAL) == 0 &&	    (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;	}	(void) spl0();#ifdef DEBUG	if (dcmdebug & DDB_OPENCLOSE)		printf("dcmopen: u %x st %x fl %x\n",			unit, tp->t_state, tp->t_flags);#endif	if (error == 0)		error = (*linesw[tp->t_line].l_open)(dev, tp);	return (error);} /*ARGSUSED*/dcmclose(dev, flag, mode, p)	dev_t dev;	int flag, mode;	struct proc *p;{	register struct tty *tp;	int unit; 	unit = UNIT(dev);	tp = &dcm_tty[unit];	(*linesw[tp->t_line].l_close)(tp, flag);	if (tp->t_cflag&HUPCL || tp->t_state&TS_WOPEN ||	    (tp->t_state&TS_ISOPEN) == 0)		(void) dcmmctl(dev, MO_OFF, DMSET);#ifdef DEBUG	if (dcmdebug & DDB_OPENCLOSE)		printf("dcmclose: u %x st %x fl %x\n",			unit, tp->t_state, tp->t_flags);#endif	ttyclose(tp);	return (0);} dcmread(dev, uio, flag)	dev_t dev;	struct uio *uio;	int flag;{	register struct tty *tp; 	tp = &dcm_tty[UNIT(dev)];	return ((*linesw[tp->t_line].l_read)(tp, uio, flag));} dcmwrite(dev, uio, flag)	dev_t dev;	struct uio *uio;	int flag;

⌨️ 快捷键说明

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