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

📄 zs.c

📁 早期freebsd实现
💻 C
📖 第 1 页 / 共 3 页
字号:
/* * Copyright (c) 1992, 1993 *	The Regents of the University of California.  All rights reserved. * * This software was developed by the Computer Systems Engineering group * at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and * contributed to Berkeley. * * 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, Lawrence Berkeley Laboratory. * * 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. * *	@(#)zs.c	8.1 (Berkeley) 7/19/93 * * from: $Header: zs.c,v 1.30 93/07/19 23:44:42 torek Exp $ *//* * Zilog Z8530 (ZSCC) driver. * * Runs two tty ports (ttya and ttyb) on zs0, * and runs a keyboard and mouse on zs1. * * This driver knows far too much about chip to usage mappings. */#define	NZS	2		/* XXX */#include <sys/param.h>#include <sys/proc.h>#include <sys/device.h>#include <sys/conf.h>#include <sys/file.h>#include <sys/ioctl.h>#include <sys/tty.h>#include <sys/time.h>#include <sys/kernel.h>#include <sys/syslog.h>#include <machine/autoconf.h>#include <machine/cpu.h>#include <sparc/sparc/vaddrs.h>#include <sparc/sparc/auxreg.h>#include <sparc/dev/kbd.h>#include <sparc/dev/zsreg.h>#include <sparc/dev/zsvar.h>#ifdef KGDB#include <machine/remote-sl.h>#endif#define	ZSMAJOR	12		/* XXX */#define	ZS_KBD		2	/* XXX */#define	ZS_MOUSE	3	/* XXX *//* the magic number below was stolen from the Sprite source. */#define PCLK	(19660800/4)	/* PCLK pin input clock rate *//* * Select software interrupt bit based on TTY ipl. */#if PIL_TTY == 1# define IE_ZSSOFT IE_L1#elif PIL_TTY == 4# define IE_ZSSOFT IE_L4#elif PIL_TTY == 6# define IE_ZSSOFT IE_L6#else# error "no suitable software interrupt bit"#endif/* * Software state per found chip.  This would be called `zs_softc', * but the previous driver had a rather different zs_softc.... */struct zsinfo {	struct	device zi_dev;		/* base device */	volatile struct zsdevice *zi_zs;/* chip registers */	struct	zs_chanstate zi_cs[2];	/* channel A and B software state */};struct tty zs_tty[NZS * 2];		/* XXX should be dynamic *//* Definition of the driver for autoconfig. */static int	zsmatch(struct device *, struct cfdata *, void *);static void	zsattach(struct device *, struct device *, void *);struct cfdriver zscd =    { NULL, "zs", zsmatch, zsattach, DV_TTY, sizeof(struct zsinfo) };/* Interrupt handlers. */static int	zshard(void *);static struct intrhand levelhard = { zshard };static int	zssoft(void *);static struct intrhand levelsoft = { zssoft };struct zs_chanstate *zslist;/* Routines called from other code. */static void	zsiopen(struct tty *);static void	zsiclose(struct tty *);static void	zsstart(struct tty *);static void	zsstop(struct tty *, int);static int	zsparam(struct tty *, struct termios *);/* Routines purely local to this driver. */static int	zs_getspeed(volatile struct zschan *);static void	zs_reset(volatile struct zschan *, int, int);static void	zs_modem(struct zs_chanstate *, int);static void	zs_loadchannelregs(volatile struct zschan *, u_char *);/* Console stuff. */static struct tty *zs_ctty;	/* console `struct tty *' */static int zs_consin = -1, zs_consout = -1;static int zscnputc(int);	/* console putc function */static volatile struct zschan *zs_conschan;static struct tty *zs_checkcons(struct zsinfo *, int, struct zs_chanstate *);#ifdef KGDB/* KGDB stuff.  Must reboot to change zs_kgdbunit. */extern int kgdb_dev, kgdb_rate;static int zs_kgdb_savedspeed;static void zs_checkkgdb(int, struct zs_chanstate *, struct tty *);#endifextern volatile struct zsdevice *findzs(int);static volatile struct zsdevice *zsaddr[NZS];	/* XXX, but saves work *//* * Console keyboard L1-A processing is done in the hardware interrupt code, * so we need to duplicate some of the console keyboard decode state.  (We * must not use the regular state as the hardware code keeps ahead of the * software state: the software state tracks the most recent ring input but * the hardware state tracks the most recent ZSCC input.)  See also kbd.h. */static struct conk_state {	/* console keyboard state */	char	conk_id;	/* true => ID coming up (console only) */	char	conk_l1;	/* true => L1 pressed (console only) */} zsconk_state;int zshardscope;int zsshortcuts;		/* number of "shortcut" software interrupts *//* * Match slave number to zs unit number, so that misconfiguration will * not set up the keyboard as ttya, etc. */static intzsmatch(struct device *parent, struct cfdata *cf, void *aux){	struct romaux *ra = aux;	return (getpropint(ra->ra_node, "slave", -2) == cf->cf_unit);}/* * Attach a found zs. * * USE ROM PROPERTIES port-a-ignore-cd AND port-b-ignore-cd FOR * SOFT CARRIER, AND keyboard PROPERTY FOR KEYBOARD/MOUSE? */static voidzsattach(struct device *parent, struct device *dev, void *aux){	register int zs = dev->dv_unit, unit;	register struct zsinfo *zi;	register struct zs_chanstate *cs;	register volatile struct zsdevice *addr;	register struct tty *tp, *ctp;	register struct romaux *ra = aux;	int pri, softcar;	static int didintr, prevpri;	if ((addr = zsaddr[zs]) == NULL)		addr = zsaddr[zs] = findzs(zs);	if ((void *)addr != ra->ra_vaddr)		panic("zsattach");	if (ra->ra_nintr != 1) {		printf(": expected 1 interrupt, got %d\n", ra->ra_nintr);		return;	}	pri = ra->ra_intr[0].int_pri;	printf(" pri %d, softpri %d\n", pri, PIL_TTY);	if (!didintr) {		didintr = 1;		prevpri = pri;		intr_establish(pri, &levelhard);		intr_establish(PIL_TTY, &levelsoft);	} else if (pri != prevpri)		panic("broken zs interrupt scheme");	zi = (struct zsinfo *)dev;	zi->zi_zs = addr;	unit = zs * 2;	cs = zi->zi_cs;	tp = &zs_tty[unit];	if (unit == 0) {		/* Get software carrier flags from options node in OPENPROM. */		extern int optionsnode;		softcar = 0;		if (*getpropstring(optionsnode, "ttya-ignore-cd") == 't')			softcar |= 1;		if (*getpropstring(optionsnode, "ttyb-ignore-cd") == 't')			softcar |= 2;	} else		softcar = dev->dv_cfdata->cf_flags;	/* link into interrupt list with order (A,B) (B=A+1) */	cs[0].cs_next = &cs[1];	cs[1].cs_next = zslist;	zslist = cs;	cs->cs_unit = unit;	cs->cs_speed = zs_getspeed(&addr->zs_chan[CHAN_A]);	cs->cs_softcar = softcar & 1;	cs->cs_zc = &addr->zs_chan[CHAN_A];	tp->t_dev = makedev(ZSMAJOR, unit);	tp->t_oproc = zsstart;	tp->t_param = zsparam;	tp->t_stop = zsstop;	if ((ctp = zs_checkcons(zi, unit, cs)) != NULL)		tp = ctp;	cs->cs_ttyp = tp;#ifdef KGDB	if (ctp == NULL)		zs_checkkgdb(unit, cs, tp);#endif	if (unit == ZS_KBD) {		/*		 * Keyboard: tell /dev/kbd driver how to talk to us.		 */		tp->t_ispeed = tp->t_ospeed = cs->cs_speed;		tp->t_cflag = CS8;		kbd_serial(tp, zsiopen, zsiclose);		cs->cs_conk = 1;		/* do L1-A processing */	}	unit++;	cs++;	tp = &zs_tty[unit];	cs->cs_unit = unit;	cs->cs_speed = zs_getspeed(&addr->zs_chan[CHAN_B]);	cs->cs_softcar = softcar & 2;	cs->cs_zc = &addr->zs_chan[CHAN_B];	tp->t_dev = makedev(ZSMAJOR, unit);	tp->t_oproc = zsstart;	tp->t_param = zsparam;	tp->t_stop = zsstop;	if ((ctp = zs_checkcons(zi, unit, cs)) != NULL)		tp = ctp;	cs->cs_ttyp = tp;#ifdef KGDB	if (ctp == NULL)		zs_checkkgdb(unit, cs, tp);#endif	if (unit == ZS_MOUSE) {		/*		 * Mouse: tell /dev/mouse driver how to talk to us.		 */		tp->t_ispeed = tp->t_ospeed = cs->cs_speed;		tp->t_cflag = CS8;		ms_serial(tp, zsiopen, zsiclose);	}}/* * Put a channel in a known state.  Interrupts may be left disabled * or enabled, as desired. */static voidzs_reset(zc, inten, speed)	volatile struct zschan *zc;	int inten, speed;{	int tconst;	static u_char reg[16] = {		0,		0,		0,		ZSWR3_RX_8 | ZSWR3_RX_ENABLE,		ZSWR4_CLK_X16 | ZSWR4_ONESB | ZSWR4_EVENP,		ZSWR5_TX_8 | ZSWR5_TX_ENABLE,		0,		0,		0,		0,		ZSWR10_NRZ,		ZSWR11_TXCLK_BAUD | ZSWR11_RXCLK_BAUD,		0,		0,		ZSWR14_BAUD_FROM_PCLK | ZSWR14_BAUD_ENA,		ZSWR15_BREAK_IE | ZSWR15_DCD_IE,	};	reg[9] = inten ? ZSWR9_MASTER_IE | ZSWR9_NO_VECTOR : ZSWR9_NO_VECTOR;	tconst = BPS_TO_TCONST(PCLK / 16, speed);	reg[12] = tconst;	reg[13] = tconst >> 8;	zs_loadchannelregs(zc, reg);}/* * Declare the given tty (which is in fact &cons) as a console input * or output.  This happens before the zs chip is attached; the hookup * is finished later, in zs_setcons() below. * * This is used only for ports a and b.  The console keyboard is decoded * independently (we always send unit-2 input to /dev/kbd, which will * direct it to /dev/console if appropriate). */voidzsconsole(tp, unit, out)	register struct tty *tp;	register int unit;	int out;{	extern int (*v_putc)();	int zs;	volatile struct zsdevice *addr;	if (unit >= ZS_KBD)		panic("zsconsole");	if (out) {		zs_consout = unit;		zs = unit >> 1;		if ((addr = zsaddr[zs]) == NULL)			addr = zsaddr[zs] = findzs(zs);		zs_conschan = (unit & 1) == 0 ? &addr->zs_chan[CHAN_A] :		    &addr->zs_chan[CHAN_B];		v_putc = zscnputc;	} else		zs_consin = unit;	zs_ctty = tp;}/* * Polled console output putchar. */static intzscnputc(c)	int c;{	register volatile struct zschan *zc = zs_conschan;	register int s;	if (c == '\n')		zscnputc('\r');	/*	 * Must block output interrupts (i.e., raise to >= splzs) without	 * lowering current ipl.  Need a better way.	 */	s = splhigh();#ifdef sun4c		/* XXX */	if (s <= (12 << 8))		(void) splzs();#endif	while ((zc->zc_csr & ZSRR0_TX_READY) == 0)		continue;	zc->zc_data = c;	splx(s);}/* * Set up the given unit as console input, output, both, or neither, as * needed.  Return console tty if it is to receive console input. */static struct tty *zs_checkcons(struct zsinfo *zi, int unit, struct zs_chanstate *cs){	register struct tty *tp;	char *i, *o;	if ((tp = zs_ctty) == NULL)		return (0);	i = zs_consin == unit ? "input" : NULL;	o = zs_consout == unit ? "output" : NULL;	if (i == NULL && o == NULL)		return (0);	/* rewire the minor device (gack) */	tp->t_dev = makedev(major(tp->t_dev), unit);	/*	 * Rewire input and/or output.  Note that baud rate reflects	 * input settings, not output settings, but we can do no better	 * if the console is split across two ports.	 *	 * XXX	split consoles don't work anyway -- this needs to be	 *	thrown away and redone	 */	if (i) {		tp->t_param = zsparam;		tp->t_ispeed = tp->t_ospeed = cs->cs_speed;		tp->t_cflag = CS8;		ttsetwater(tp);	}	if (o) {		tp->t_oproc = zsstart;		tp->t_stop = zsstop;	}	printf("%s%c: console %s\n",

⌨️ 快捷键说明

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