📄 zs.c
字号:
/* * 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 + -