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

📄 scc.c

📁 早期freebsd实现
💻 C
📖 第 1 页 / 共 2 页
字号:
/*- * Copyright (c) 1992, 1993 *	The Regents of the University of California.  All rights reserved. * * This code is derived from software contributed to Berkeley by * Ralph Campbell and Rick Macklem. * * 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. * *	@(#)scc.c	8.2 (Berkeley) 11/30/93 *//*  * Mach Operating System * Copyright (c) 1991,1990,1989 Carnegie Mellon University * All Rights Reserved. *  * Permission to use, copy, modify and distribute this software and its * documentation is hereby granted, provided that both the copyright * notice and this permission notice appear in all copies of the * software, derivative works or modified versions, and any portions * thereof, and that both notices appear in supporting documentation. *  * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS  * CONDITION.  CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE. *  * Carnegie Mellon requests users of this software to return to *  *  Software Distribution Coordinator  or  Software.Distribution@CS.CMU.EDU *  School of Computer Science *  Carnegie Mellon University *  Pittsburgh PA 15213-3890 *  * any improvements or extensions that they make and grant Carnegie the * rights to redistribute these changes. */#include <scc.h>#if NSCC > 0/* * Intel 82530 dual usart chip driver. Supports the serial port(s) on the * Personal DECstation 5000/xx and DECstation 5000/1xx, plus the keyboard * and mouse on the 5000/1xx. (Don't ask me where the A channel signals * are on the 5000/xx.) * * See: Intel MicroCommunications Handbook, Section 2, pg. 155-173, 1992. */#include <sys/param.h>#include <sys/systm.h>#include <sys/ioctl.h>#include <sys/tty.h>#include <sys/proc.h>#include <sys/map.h>#include <sys/buf.h>#include <sys/conf.h>#include <sys/file.h>#include <sys/uio.h>#include <sys/kernel.h>#include <sys/syslog.h>#include <machine/pmioctl.h>#include <pmax/dev/device.h>#include <pmax/dev/pdma.h>#include <pmax/dev/sccreg.h>#include <pmax/dev/fbreg.h>#include <pmax/pmax/cons.h>#include <pmax/pmax/pmaxtype.h>extern int pmax_boardtype;extern struct consdev cn_tab;extern void ttrstrt	__P((void *));extern void KBDReset	__P((dev_t, void (*)()));extern void MouseInit	__P((dev_t, void (*)(), int (*)()));/* * Driver information for auto-configuration stuff. */int	sccprobe(), sccopen(), sccparam(), sccGetc();void	sccintr(), sccstart(), sccPutc();struct	driver sccdriver = {	"scc", sccprobe, 0, 0, sccintr,};#define	NSCCLINE 	(NSCC*2)#define	SCCUNIT(dev)	(minor(dev) >> 1)#define	SCCLINE(dev)	(minor(dev) & 0x1)struct	tty scc_tty[NSCCLINE];void	(*sccDivertXInput)();	/* X windows keyboard input routine */void	(*sccMouseEvent)();	/* X windows mouse motion event routine */void	(*sccMouseButtons)();	/* X windows mouse buttons event routine */#ifdef DEBUGint	debugChar;#endifstatic void scc_modem_intr(), sccreset();struct scc_softc {	struct pdma scc_pdma[2];	struct {		u_char	wr1;		u_char	wr3;		u_char	wr4;		u_char	wr5;		u_char	wr14;	} scc_wreg[2];	int	scc_softCAR;} scc_softc[NSCC];struct speedtab sccspeedtab[] = {	0,	0,	50,	4606,	75,	3070,	110,	2093,	134,	1711,	150,	1534,	300,	766,	600,	382,	1200,	190,	1800,	126,	2400,	94,	4800,	46,	9600,	22,	19200,	10,	38400,	4,	-1,	-1};#ifndef	PORTSELECTOR#define	ISPEED	TTYDEF_SPEED#define	LFLAG	TTYDEF_LFLAG#else#define	ISPEED	B4800#define	LFLAG	(TTYDEF_LFLAG & ~ECHO)#endif/* * Test to see if device is present. * Return true if found and initialized ok. */sccprobe(cp)	register struct pmax_ctlr *cp;{	register struct scc_softc *sc;	register struct pdma *pdp;	register struct tty *tp;	register int cntr;	struct tty ctty;	struct termios cterm;	int s;	if (cp->pmax_unit >= NSCC)		return (0);	if (badaddr(cp->pmax_addr, 2))		return (0);	/*	 * For a remote console, wait a while for previous output to	 * complete.	 */	if (major(cn_tab.cn_dev) == SCCDEV && cn_tab.cn_screen == 0 &&		SCCUNIT(cn_tab.cn_dev) == cp->pmax_unit)		DELAY(10000);	sc = &scc_softc[cp->pmax_unit];	pdp = &sc->scc_pdma[0];	/* init pseudo DMA structures */	tp = &scc_tty[cp->pmax_unit * 2];	for (cntr = 0; cntr < 2; cntr++) {		pdp->p_addr = (void *)cp->pmax_addr;		pdp->p_arg = (int)tp;		pdp->p_fcn = (void (*)())0;		tp->t_dev = (dev_t)((cp->pmax_unit << 1) | cntr);		pdp++, tp++;	}	sc->scc_softCAR = cp->pmax_flags | 0x2;	/* reset chip */	sccreset(sc);	/*	 * Special handling for consoles.	 */	if (cn_tab.cn_screen) {		if (cn_tab.cn_kbdgetc == sccGetc) {			if (cp->pmax_unit == 1) {				s = spltty();				ctty.t_dev = makedev(SCCDEV, SCCKBD_PORT);				cterm.c_cflag = CS8;				cterm.c_ospeed = cterm.c_ispeed = 4800;				(void) sccparam(&ctty, &cterm);				DELAY(10000);#ifdef notyet				/*				 * For some reason doing this hangs the 3min				 * during booting. Fortunately the keyboard				 * works ok without it.				 */				KBDReset(ctty.t_dev, sccPutc);#endif				DELAY(10000);				splx(s);			} else if (cp->pmax_unit == 0) {				s = spltty();				ctty.t_dev = makedev(SCCDEV, SCCMOUSE_PORT);				cterm.c_cflag = CS8 | PARENB | PARODD;				cterm.c_ospeed = cterm.c_ispeed = 4800;				(void) sccparam(&ctty, &cterm);				DELAY(10000);				MouseInit(ctty.t_dev, sccPutc, sccGetc);				DELAY(10000);				splx(s);			}		}	} else if (SCCUNIT(cn_tab.cn_dev) == cp->pmax_unit) {		s = spltty();		ctty.t_dev = cn_tab.cn_dev;		cterm.c_cflag = CS8;		cterm.c_ospeed = cterm.c_ispeed = 9600;		(void) sccparam(&ctty, &cterm);		DELAY(1000);		cn_tab.cn_disabled = 0;		splx(s);	}	printf("scc%d at nexus0 csr 0x%x priority %d\n",		cp->pmax_unit, cp->pmax_addr, cp->pmax_pri);	return (1);}/* * Reset the chip. */static voidsccreset(sc)	register struct scc_softc *sc;{	register scc_regmap_t *regs;	register u_char val;	regs = (scc_regmap_t *)sc->scc_pdma[0].p_addr;	/*	 * Chip once-only initialization	 *	 * NOTE: The wiring we assume is the one on the 3min:	 *	 *	out	A-TxD	-->	TxD	keybd or mouse	 *	in	A-RxD	-->	RxD	keybd or mouse	 *	out	A-DTR~	-->	DTR	comm	 *	out	A-RTS~	-->	RTS	comm	 *	in	A-CTS~	-->	SI	comm	 *	in	A-DCD~	-->	RI	comm	 *	in	A-SYNCH~-->	DSR	comm	 *	out	B-TxD	-->	TxD	comm	 *	in	B-RxD	-->	RxD	comm	 *	in	B-RxC	-->	TRxCB	comm	 *	in	B-TxC	-->	RTxCB	comm	 *	out	B-RTS~	-->	SS	comm	 *	in	B-CTS~	-->	CTS	comm	 *	in	B-DCD~	-->	CD	comm	 */	SCC_INIT_REG(regs, SCC_CHANNEL_A);	SCC_INIT_REG(regs, SCC_CHANNEL_B);	SCC_WRITE_REG(regs, SCC_CHANNEL_A, SCC_WR9, SCC_WR9_HW_RESET);	DELAY(50000);	/*enough ? */	SCC_WRITE_REG(regs, SCC_CHANNEL_A, SCC_WR9, 0);	/* program the interrupt vector */	SCC_WRITE_REG(regs, SCC_CHANNEL_A, SCC_WR2, 0xf0);	SCC_WRITE_REG(regs, SCC_CHANNEL_B, SCC_WR2, 0xf0);	SCC_WRITE_REG(regs, SCC_CHANNEL_A, SCC_WR9, SCC_WR9_VIS);	/* timing base defaults */	sc->scc_wreg[SCC_CHANNEL_A].wr4 = SCC_WR4_CLK_x16;	sc->scc_wreg[SCC_CHANNEL_B].wr4 = SCC_WR4_CLK_x16;	/* enable DTR, RTS and SS */	sc->scc_wreg[SCC_CHANNEL_B].wr5 = SCC_WR5_RTS;	sc->scc_wreg[SCC_CHANNEL_A].wr5 = SCC_WR5_RTS | SCC_WR5_DTR;	/* baud rates */	val = SCC_WR14_BAUDR_ENABLE|SCC_WR14_BAUDR_SRC;	sc->scc_wreg[SCC_CHANNEL_B].wr14 = val;	sc->scc_wreg[SCC_CHANNEL_A].wr14 = val;	/* interrupt conditions */	val =	SCC_WR1_RXI_ALL_CHAR | SCC_WR1_PARITY_IE |		SCC_WR1_EXT_IE;	sc->scc_wreg[SCC_CHANNEL_A].wr1 = val;	sc->scc_wreg[SCC_CHANNEL_B].wr1 = val;}sccopen(dev, flag, mode, p)	dev_t dev;	int flag, mode;	struct proc *p;{	register struct scc_softc *sc;	register struct tty *tp;	register int unit, line;	int s, error = 0;	unit = SCCUNIT(dev);	if (unit >= NSCC)		return (ENXIO);	line = SCCLINE(dev);	sc = &scc_softc[unit];	if (sc->scc_pdma[line].p_addr == (void *)0)		return (ENXIO);	tp = &scc_tty[minor(dev)];	tp->t_oproc = sccstart;	tp->t_param = sccparam;	tp->t_dev = dev;	if ((tp->t_state & TS_ISOPEN) == 0) {		tp->t_state |= TS_WOPEN;		ttychars(tp);#ifndef PORTSELECTOR		if (tp->t_ispeed == 0) {#endif			tp->t_iflag = TTYDEF_IFLAG;			tp->t_oflag = TTYDEF_OFLAG;			tp->t_cflag = TTYDEF_CFLAG;			tp->t_lflag = LFLAG;			tp->t_ispeed = tp->t_ospeed = ISPEED;#ifdef PORTSELECTOR			tp->t_cflag |= HUPCL;#else		}#endif		(void) sccparam(tp, &tp->t_termios);		ttsetwater(tp);	} else if ((tp->t_state & TS_XCLUDE) && curproc->p_ucred->cr_uid != 0)		return (EBUSY);	(void) sccmctl(dev, DML_DTR, DMSET);	s = spltty();	while (!(flag & O_NONBLOCK) && !(tp->t_cflag & CLOCAL) &&	       !(tp->t_state & TS_CARR_ON)) {		tp->t_state |= TS_WOPEN;		if (error = ttysleep(tp, (caddr_t)&tp->t_rawq, TTIPRI | PCATCH,		    ttopen, 0))			break;	}	splx(s);	if (error)		return (error);	return ((*linesw[tp->t_line].l_open)(dev, tp));}/*ARGSUSED*/sccclose(dev, flag, mode, p)	dev_t dev;	int flag, mode;	struct proc *p;{	register struct scc_softc *sc = &scc_softc[SCCUNIT(dev)];	register struct tty *tp;	register int bit, line;	tp = &scc_tty[minor(dev)];	line = SCCLINE(dev);	if (sc->scc_wreg[line].wr5 & SCC_WR5_SEND_BREAK) {		sc->scc_wreg[line].wr5 &= ~SCC_WR5_SEND_BREAK;		ttyoutput(0, tp);	}	(*linesw[tp->t_line].l_close)(tp, flag);	if ((tp->t_cflag & HUPCL) || (tp->t_state & TS_WOPEN) ||	    !(tp->t_state & TS_ISOPEN))		(void) sccmctl(dev, 0, DMSET);	return (ttyclose(tp));}sccread(dev, uio, flag)	dev_t dev;	struct uio *uio;{	register struct tty *tp;	tp = &scc_tty[minor(dev)];	return ((*linesw[tp->t_line].l_read)(tp, uio, flag));}sccwrite(dev, uio, flag)	dev_t dev;	struct uio *uio;{	register struct tty *tp;	tp = &scc_tty[minor(dev)];	return ((*linesw[tp->t_line].l_write)(tp, uio, flag));}/*ARGSUSED*/sccioctl(dev, cmd, data, flag, p)	dev_t dev;	int cmd;	caddr_t data;	int flag;	struct proc *p;{	register struct scc_softc *sc;	register struct tty *tp;	int error, line;	tp = &scc_tty[minor(dev)];	error = (*linesw[tp->t_line].l_ioctl)(tp, cmd, data, flag, p);	if (error >= 0)		return (error);	error = ttioctl(tp, cmd, data, flag);	if (error >= 0)		return (error);	line = SCCLINE(dev);	sc = &scc_softc[SCCUNIT(dev)];	switch (cmd) {	case TIOCSBRK:		sc->scc_wreg[line].wr5 |= SCC_WR5_SEND_BREAK;		ttyoutput(0, tp);		break;	case TIOCCBRK:		sc->scc_wreg[line].wr5 &= ~SCC_WR5_SEND_BREAK;		ttyoutput(0, tp);		break;	case TIOCSDTR:		(void) sccmctl(dev, DML_DTR|DML_RTS, DMBIS);		break;	case TIOCCDTR:		(void) sccmctl(dev, DML_DTR|DML_RTS, DMBIC);		break;	case TIOCMSET:		(void) sccmctl(dev, *(int *)data, DMSET);		break;	case TIOCMBIS:		(void) sccmctl(dev, *(int *)data, DMBIS);		break;	case TIOCMBIC:		(void) sccmctl(dev, *(int *)data, DMBIC);		break;	case TIOCMGET:		*(int *)data = sccmctl(dev, 0, DMGET);		break;	default:		return (ENOTTY);	}	return (0);}sccparam(tp, t)	register struct tty *tp;	register struct termios *t;{	register struct scc_softc *sc;	register scc_regmap_t *regs;	register int line;	register u_char value, wvalue;	register int cflag = t->c_cflag;	int ospeed;        if (t->c_ispeed && t->c_ispeed != t->c_ospeed)                return (EINVAL);	sc = &scc_softc[SCCUNIT(tp->t_dev)];	line = SCCLINE(tp->t_dev);	regs = (scc_regmap_t *)sc->scc_pdma[line].p_addr;	ospeed = ttspeedtab(t->c_ospeed, sccspeedtab);        if (ospeed < 0)                return (EINVAL);        /* and copy to tty */        tp->t_ispeed = t->c_ispeed;        tp->t_ospeed = t->c_ospeed;        tp->t_cflag = cflag;	/*	 * Handle console specially.	 */	if (cn_tab.cn_screen) {		if (minor(tp->t_dev) == SCCKBD_PORT) {			cflag = CS8;			ospeed = ttspeedtab(4800, sccspeedtab);		} else if (minor(tp->t_dev) == SCCMOUSE_PORT) {			cflag = CS8 | PARENB | PARODD;			ospeed = ttspeedtab(4800, sccspeedtab);		}	} else if (tp->t_dev == cn_tab.cn_dev) {		cflag = CS8;		ospeed = ttspeedtab(9600, sccspeedtab);

⌨️ 快捷键说明

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