From 4df8f47ebce8692d72a97e7b8bd490b1340e7c6a Mon Sep 17 00:00:00 2001 From: minoura Date: Wed, 5 Aug 1998 16:08:33 +0000 Subject: [PATCH] Switched to MI zs driver. --- sys/arch/x68k/conf/ALL | 14 +- sys/arch/x68k/conf/EMPTY | 7 +- sys/arch/x68k/conf/GENERIC | 7 +- sys/arch/x68k/conf/INSTALL | 6 +- sys/arch/x68k/conf/JUPITER | 7 +- sys/arch/x68k/conf/MARINE | 8 +- sys/arch/x68k/conf/NBTY | 8 +- sys/arch/x68k/conf/SMALL030 | 6 +- sys/arch/x68k/conf/files.x68k | 19 +- sys/arch/x68k/dev/ms.c | 604 ++++++++--- sys/arch/x68k/dev/zs.c | 1772 +++++++------------------------- sys/arch/x68k/dev/zsvar.h | 152 --- sys/arch/x68k/x68k/conf.c | 11 +- sys/arch/x68k/x68k/iodevice.h | 6 +- sys/arch/x68k/x68k/locore.s | 12 +- sys/arch/x68k/x68k/machdep.c | 4 +- sys/arch/x68k/x68k/trap.c | 6 +- sys/arch/x68k/x68k/x68k_init.c | 12 +- 18 files changed, 899 insertions(+), 1762 deletions(-) delete mode 100644 sys/arch/x68k/dev/zsvar.h diff --git a/sys/arch/x68k/conf/ALL b/sys/arch/x68k/conf/ALL index c6ecbc9fb362..53cd7983f0d7 100644 --- a/sys/arch/x68k/conf/ALL +++ b/sys/arch/x68k/conf/ALL @@ -1,4 +1,4 @@ -# $NetBSD: ALL,v 1.20 1998/06/26 01:54:13 lukem Exp $ +# $NetBSD: ALL,v 1.21 1998/08/05 16:08:33 minoura Exp $ # # ALL -- everything that's currently supported @@ -102,8 +102,15 @@ config netbsd root on ? type ? mainbus0 at root -zs0 at mainbus0 # Zilog serial -zs1 at mainbus0 # Zilog serial +zsc0 at mainbus0 +zstty0 at zsc0 channel 0 # built-in RS-232C +ms0 at zsc0 channel 1 # standard mouse +zsc1 at mainbus0 +zstty2 at zsc1 channel 0 +zstty3 at zsc1 channel 1 +zsc2 at mainbus0 +zstty4 at zsc2 channel 0 +zstty5 at zsc2 channel 1 par0 at mainbus0 # builtin parallel port spc0 at mainbus0 # builtin scsi spc1 at mainbus0 # external scsi @@ -139,7 +146,6 @@ pseudo-device bpfilter 16 # packet filter pseudo-device tun 4 # tunnel pseudo-device pty 64 # pseudo-terminals pseudo-device kbd # kbd -pseudo-device mouse # mouse pseudo-device sram # battery-backuped static RAM pseudo-device bell # OPM bell pseudo-device pow 2 # software power switch diff --git a/sys/arch/x68k/conf/EMPTY b/sys/arch/x68k/conf/EMPTY index fdf08447ae19..786db47efe75 100644 --- a/sys/arch/x68k/conf/EMPTY +++ b/sys/arch/x68k/conf/EMPTY @@ -1,11 +1,11 @@ -# $NetBSD: EMPTY,v 1.8 1998/06/26 01:54:14 lukem Exp $ +# $NetBSD: EMPTY,v 1.9 1998/08/05 16:08:34 minoura Exp $ # # EMPTY # #--- from std.x68k -# $NetBSD: EMPTY,v 1.8 1998/06/26 01:54:14 lukem Exp $ +# $NetBSD: EMPTY,v 1.9 1998/08/05 16:08:34 minoura Exp $ # # standard x68k information # @@ -16,7 +16,8 @@ options MACHINE_NONCONTIG # Non-contiguous memory support mainbus0 at root -zs0 at mainbus0 # Zilog serial +zsc0 at mainbus0 +zstty0 at zsc0 channel 0 # built-in RS-232C #par0 at mainbus0 # builtin parallel port spc0 at mainbus0 # scsi scsibus* at spc? diff --git a/sys/arch/x68k/conf/GENERIC b/sys/arch/x68k/conf/GENERIC index ff15553a1397..b5f67c9cc007 100644 --- a/sys/arch/x68k/conf/GENERIC +++ b/sys/arch/x68k/conf/GENERIC @@ -1,4 +1,4 @@ -# $NetBSD: GENERIC,v 1.19 1998/06/26 01:54:14 lukem Exp $ +# $NetBSD: GENERIC,v 1.20 1998/08/05 16:08:34 minoura Exp $ # # GENERIC @@ -100,7 +100,9 @@ config netbsd root on ? type ? mainbus0 at root -zs0 at mainbus0 # Zilog serial +zsc0 at mainbus0 +zstty0 at zsc0 channel 0 # built-in RS-232C +ms0 at zsc0 channel 1 # standard mouse par0 at mainbus0 # builtin parallel port spc0 at mainbus0 # builtin scsi spc1 at mainbus0 # external scsi @@ -141,7 +143,6 @@ pseudo-device ppp 2 # point-to-point protocol #pseudo-device bpfilter 16 # packet filter pseudo-device pty 32 # pseudo-terminals pseudo-device kbd # kbd -pseudo-device mouse # mouse #pseudo-device sram # static RAM pseudo-device bell # OPM bell pseudo-device pow 2 # software power switch diff --git a/sys/arch/x68k/conf/INSTALL b/sys/arch/x68k/conf/INSTALL index a495a5cf9c49..12812289f0ed 100644 --- a/sys/arch/x68k/conf/INSTALL +++ b/sys/arch/x68k/conf/INSTALL @@ -1,4 +1,4 @@ -# $NetBSD: INSTALL,v 1.4 1998/06/30 11:59:09 msaitoh Exp $ +# $NetBSD: INSTALL,v 1.5 1998/08/05 16:08:34 minoura Exp $ # # ALL -- everything that's currently supported @@ -76,8 +76,8 @@ config netbsd root on ? type ? mainbus0 at root -zs0 at mainbus0 # Zilog serial -zs1 at mainbus0 # Zilog serial +zsc0 at mainbus0 +zstty0 at zsc0 channel 0 # built-in RS-232C spc0 at mainbus0 # builtin scsi spc1 at mainbus0 # external scsi scsibus* at spc? diff --git a/sys/arch/x68k/conf/JUPITER b/sys/arch/x68k/conf/JUPITER index a4dd8ed2e4e7..c41ba89dba67 100644 --- a/sys/arch/x68k/conf/JUPITER +++ b/sys/arch/x68k/conf/JUPITER @@ -1,4 +1,4 @@ -# $NetBSD: JUPITER,v 1.10 1998/06/26 01:54:14 lukem Exp $ +# $NetBSD: JUPITER,v 1.11 1998/08/05 16:08:34 minoura Exp $ # # JUPITER @@ -97,7 +97,9 @@ config netbsd root on ? type ? mainbus0 at root -zs0 at mainbus0 # Zilog serial +zsc0 at mainbus0 +zstty0 at zsc0 channel 0 # built-in RS-232C +ms0 at zsc0 channel 1 # standard mouse par0 at mainbus0 # builtin parallel port spc0 at mainbus0 # scsi scsibus* at spc? @@ -136,7 +138,6 @@ pseudo-device bpfilter 16 # packet filter pseudo-device tun 4 # tunnel pseudo-device pty 64 # pseudo-terminals pseudo-device kbd # kbd -pseudo-device mouse # mouse pseudo-device sram # static RAM pseudo-device bell # OPM bell pseudo-device pow 2 # software power switch diff --git a/sys/arch/x68k/conf/MARINE b/sys/arch/x68k/conf/MARINE index bb5b1ff6ce8b..613e95e4cde5 100644 --- a/sys/arch/x68k/conf/MARINE +++ b/sys/arch/x68k/conf/MARINE @@ -1,4 +1,4 @@ -# $NetBSD: MARINE,v 1.10 1998/06/26 01:54:14 lukem Exp $ +# $NetBSD: MARINE,v 1.11 1998/08/05 16:08:35 minoura Exp $ # # MARINE @@ -104,8 +104,9 @@ fdc0 at mainbus0 # floppy controller fd* at fdc0 unit ? # builtin floppy drive # further builtin devices -zs0 at mainbus0 # Zilog serial -zs1 at mainbus0 # Zilog serial +zsc0 at mainbus0 +zstty0 at zsc0 channel 0 # built-in RS-232C +ms0 at zsc0 channel 1 # standard mouse par0 at mainbus0 # builtin parallel port # SCSI devices @@ -126,7 +127,6 @@ pseudo-device ppp 1 # point-to-point protocol #pseudo-device tun 4 # tunnel pseudo-device kbd # kbd pseudo-device pty 32 # pseudo-terminals -pseudo-device mouse # mouse #pseudo-device sram # battery-backuped static RAM pseudo-device loop # loopback; recommended pseudo-device ether # ethernet diff --git a/sys/arch/x68k/conf/NBTY b/sys/arch/x68k/conf/NBTY index 308afe4551b3..7f863023a351 100644 --- a/sys/arch/x68k/conf/NBTY +++ b/sys/arch/x68k/conf/NBTY @@ -1,4 +1,4 @@ -# $NetBSD: NBTY,v 1.11 1998/06/26 01:54:15 lukem Exp $ +# $NetBSD: NBTY,v 1.12 1998/08/05 16:08:35 minoura Exp $ # # ALL -- everything that's currently supported @@ -110,8 +110,9 @@ fdc0 at mainbus0 # floppy controller fd* at fdc0 unit ? # builtin floppy drive # further builtin devices -zs0 at mainbus0 # Zilog serial -zs1 at mainbus0 # Zilog serial +zsc0 at mainbus0 +zstty0 at zsc0 channel 0 # built-in RS-232C +ms0 at zsc0 channel 1 # standard mouse par0 at mainbus0 # builtin parallel port xcom0 at mainbus0 # NS16550 @@ -150,7 +151,6 @@ pseudo-device bpfilter 8 # packet filter pseudo-device tun 4 # tunnel pseudo-device pty 64 # pseudo-terminals pseudo-device kbd # kbd -pseudo-device mouse # mouse pseudo-device sram # static RAM pseudo-device loop # loopback; recommended #pseudo-device ether # ethernet diff --git a/sys/arch/x68k/conf/SMALL030 b/sys/arch/x68k/conf/SMALL030 index b53cf7f4aca4..dc1f5fcb1ed8 100644 --- a/sys/arch/x68k/conf/SMALL030 +++ b/sys/arch/x68k/conf/SMALL030 @@ -1,4 +1,4 @@ -# $NetBSD: SMALL030,v 1.9 1998/06/26 01:54:15 lukem Exp $ +# $NetBSD: SMALL030,v 1.10 1998/08/05 16:08:35 minoura Exp $ # # SMALL030 -- small configuration with mc68030 processor @@ -100,7 +100,9 @@ spc0 at mainbus0 # builtin scsi spc1 at mainbus0 # external scsi scsibus* at spc? -zs0 at mainbus0 # Zilog serial +zsc0 at mainbus0 +zstty0 at zsc0 channel 0 # built-in RS-232C +#ms0 at zsc0 channel 1 # standard mouse #zs1 at mainbus0 # Zilog serial #par0 at mainbus0 # builtin parallel port grfbus0 at mainbus0 # bitmapped display's diff --git a/sys/arch/x68k/conf/files.x68k b/sys/arch/x68k/conf/files.x68k index 914189024691..2af168c7f064 100644 --- a/sys/arch/x68k/conf/files.x68k +++ b/sys/arch/x68k/conf/files.x68k @@ -1,4 +1,4 @@ -# $NetBSD: files.x68k,v 1.20 1998/05/31 23:28:07 thorpej Exp $ +# $NetBSD: files.x68k,v 1.21 1998/08/05 16:08:35 minoura Exp $ # # new style config file for x68k architecture # @@ -74,9 +74,18 @@ device fd: disk attach fd at fdc file arch/x68k/dev/fd.c fd needs-flag -device zs: tty -attach zs at mainbus -file arch/x68k/dev/zs.c zs needs-count +device zsc {channel = -1} +attach zsc at mainbus +file arch/x68k/dev/zs.c zsc needs-flag +file dev/ic/z8530sc.c zsc + +device zstty: tty +attach zstty at zsc +file dev/ic/z8530tty.c zstty needs-flag + +device ms: event +attach ms at zsc +file arch/x68k/dev/ms.c ms needs-flag device xcom: tty attach xcom at mainbus @@ -87,8 +96,6 @@ attach par at mainbus file arch/x68k/dev/par.c par needs-flag file arch/x68k/dev/rtclock.c -pseudo-device mouse -file arch/x68k/dev/ms.c mouse # graphic devices define grfb {} diff --git a/sys/arch/x68k/dev/ms.c b/sys/arch/x68k/dev/ms.c index d23044e7ee70..db8518519479 100644 --- a/sys/arch/x68k/dev/ms.c +++ b/sys/arch/x68k/dev/ms.c @@ -1,4 +1,4 @@ -/* $NetBSD: ms.c,v 1.4 1997/10/12 06:42:18 oki Exp $ */ +/* $NetBSD: ms.c,v 1.5 1998/08/05 16:08:36 minoura Exp $ */ /* * Copyright (c) 1992, 1993 @@ -45,7 +45,7 @@ */ /* - * Mouse driver. + * X68k mouse driver. */ #include @@ -56,11 +56,32 @@ #include #include #include +#include -#include +#include +#include + +#include #include -#include +#include "locators.h" + +/* + * How many input characters we can buffer. + * The port-specific var.h may override this. + * Note: must be a power of two! + */ +#define MS_RX_RING_SIZE 256 +#define MS_RX_RING_MASK (MS_RX_RING_SIZE-1) +/* + * Output buffer. Only need a few chars. + */ +#define MS_TX_RING_SIZE 16 +#define MS_TX_RING_MASK (MS_TX_RING_SIZE-1) +/* + * Mouse serial line is fixed at 4800 bps. + */ +#define MS_BPS 4800 /* * Mouse state. A SHARP X1/X680x0 mouse is a fairly simple device, @@ -70,67 +91,260 @@ * * where b is the button state, encoded as 0x80|(buttons)---there are * two buttons (2=left, 1=right)---and dx,dy are X and Y delta values. + * + * It needs trigger for the transmission. When zs RTS negated, the mouse + * begins the sequence. RTS assertion has no effect. */ struct ms_softc { + struct device ms_dev; /* required first: base device */ + struct zs_chanstate *ms_cs; + + /* Flags to communicate with ms_softintr() */ + volatile int ms_intr_flags; +#define INTR_RX_OVERRUN 1 +#define INTR_TX_EMPTY 2 +#define INTR_ST_CHECK 4 + + /* + * The receive ring buffer. + */ + u_int ms_rbget; /* ring buffer `get' index */ + volatile u_int ms_rbput; /* ring buffer `put' index */ + u_short ms_rbuf[MS_RX_RING_SIZE]; /* rr1, data pairs */ + + /* + * State of input translator + */ short ms_byteno; /* input byte number, for decode */ char ms_mb; /* mouse button state */ char ms_ub; /* user button state */ int ms_dx; /* delta-x */ int ms_dy; /* delta-y */ - struct tty *ms_mouse; /* downlink for output to mouse */ - void (*ms_open) __P((struct tty *)); /* enable dataflow */ - void (*ms_close) __P((struct tty *));/* disable dataflow */ + int ms_rts; /* MSCTRL */ + int ms_nodata; + + /* + * State of upper interface. + */ volatile int ms_ready; /* event queue is ready */ struct evvar ms_events; /* event queue state */ } ms_softc; cdev_decl(ms); -void ms_serial __P((struct tty *, void(*)(struct tty *), - void(*)(struct tty *))); -void ms_modem __P((int)); -void ms_rint __P((int)); -void mouseattach __P((void)); +static int ms_match __P((struct device*, struct cfdata*, void*)); +static void ms_attach __P((struct device*, struct device*, void*)); +static void ms_trigger __P((struct zs_chanstate*, int)); +void ms_modem __P((void)); + +struct cfattach ms_ca = { + sizeof(struct ms_softc), ms_match, ms_attach +}; + +extern struct zsops zsops_ms; +extern struct cfdriver ms_cd; /* - * Attach the mouse serial (down-link) interface. - * Do we need to set it to 4800 baud, 8 bits? - * Test by power cycling and not booting Human68k before BSD? + * ms_match: how is this zs channel configured? */ -void -ms_serial(tp, iopen, iclose) - struct tty *tp; - void (*iopen) __P((struct tty *)); - void (*iclose) __P((struct tty *)); +int +ms_match(parent, cf, aux) + struct device *parent; + struct cfdata *cf; + void *aux; { + struct zsc_attach_args *args = aux; + struct zsc_softc *zsc = (void*) parent; - ms_softc.ms_mouse = tp; - ms_softc.ms_open = iopen; - ms_softc.ms_close = iclose; + /* Exact match required for the mouse. */ + if (cf->cf_loc[ZSCCF_CHANNEL] != args->channel) + return 0; + if (args->channel != 1) + return 0; + + return 1; } -void -ms_modem(onoff) - register int onoff; -{ - static int oonoff; +void +ms_attach(parent, self, aux) + struct device *parent, *self; + void *aux; - if (ms_softc.ms_ready == 1) { - if (ms_softc.ms_byteno == -1) - ms_softc.ms_byteno = onoff = 0; - if (oonoff != onoff) { - zs_msmodem(onoff); - oonoff = onoff; - } +{ + struct zsc_softc *zsc = (void *) parent; + struct ms_softc *ms = (void *) self; + struct zsc_attach_args *args = aux; + struct zs_chanstate *cs; + struct cfdata *cf; + int reset, s; + + cf = ms->ms_dev.dv_cfdata; + cs = zsc->zsc_cs[1]; + cs->cs_private = ms; + cs->cs_ops = &zsops_ms; + ms->ms_cs = cs; + + /* Initialize the speed, etc. */ + s = splzs(); + /* May need reset... */ + reset = ZSWR9_B_RESET; + zs_write_reg(cs, 9, reset); + /* We don't care about status or tx interrupts. */ + cs->cs_preg[1] = ZSWR1_RIE; + cs->cs_preg[4] = ZSWR4_CLK_X16 | ZSWR4_TWOSB; + (void) zs_set_speed(cs, MS_BPS); + zs_loadchannelregs(cs); + splx(s); + + /* Initialize translator. */ + ms->ms_ready = 0; + + printf ("\n"); +} + +/**************************************************************** + * Entry points for /dev/mouse + * (open,close,read,write,...) + ****************************************************************/ + +int +msopen(dev, flags, mode, p) + dev_t dev; + int flags, mode; + struct proc *p; +{ + struct ms_softc *ms; + int unit; + +printf ("msopen\n"); + unit = minor(dev); + if (unit >= ms_cd.cd_ndevs) + return (ENXIO); + ms = ms_cd.cd_devs[unit]; + if (ms == NULL) + return (ENXIO); + + /* This is an exclusive open device. */ + if (ms->ms_events.ev_io) + return (EBUSY); + ms->ms_events.ev_io = p; + ev_init(&ms->ms_events); /* may cause sleep */ + + ms->ms_ready = 1; /* start accepting events */ + ms->ms_rts = 1; + ms_trigger(ms->ms_cs, 1); /* set MSCTR high (standby) */ + ms->ms_byteno = -1; + ms->ms_nodata = 0; + return (0); +} + +int +msclose(dev, flags, mode, p) + dev_t dev; + int flags, mode; + struct proc *p; +{ + struct ms_softc *ms; + + ms = ms_cd.cd_devs[minor(dev)]; + ms->ms_ready = 0; /* stop accepting events */ + ev_fini(&ms->ms_events); + + ms->ms_events.ev_io = NULL; + return (0); +} + +int +msread(dev, uio, flags) + dev_t dev; + struct uio *uio; + int flags; +{ + struct ms_softc *ms; + + ms = ms_cd.cd_devs[minor(dev)]; + return (ev_read(&ms->ms_events, uio, flags)); +} + +/* this routine should not exist, but is convenient to write here for now */ +int +mswrite(dev, uio, flags) + dev_t dev; + struct uio *uio; + int flags; +{ + + return (EOPNOTSUPP); +} + +int +msioctl(dev, cmd, data, flag, p) + dev_t dev; + u_long cmd; + register caddr_t data; + int flag; + struct proc *p; +{ + struct ms_softc *ms; + + ms = ms_cd.cd_devs[minor(dev)]; + + switch (cmd) { + + case FIONBIO: /* we will remove this someday (soon???) */ + return (0); + + case FIOASYNC: + ms->ms_events.ev_async = *(int *)data != 0; + return (0); + + case TIOCSPGRP: + if (*(int *)data != ms->ms_events.ev_io->p_pgid) + return (EPERM); + return (0); + + case VUIDGFORMAT: + /* we only do firm_events */ + *(int *)data = VUID_FIRM_EVENT; + return (0); + + case VUIDSFORMAT: + if (*(int *)data != VUID_FIRM_EVENT) + return (EINVAL); + return (0); } + return (ENOTTY); } -void -ms_rint(c) +int +mspoll(dev, events, p) + dev_t dev; + int events; + struct proc *p; +{ + struct ms_softc *ms; + + ms = ms_cd.cd_devs[minor(dev)]; + return (ev_poll(&ms->ms_events, events, p)); +} + + +/**************************************************************** + * Middle layer (translator) + ****************************************************************/ + +static void ms_input __P((struct ms_softc *, int c)); + + +/* + * Called by our ms_softint() routine on input. + */ +static void +ms_input(ms, c) + register struct ms_softc *ms; register int c; { register struct firm_event *fe; - register struct ms_softc *ms = &ms_softc; register int mb, ub, d, get, put, any; static const char to_one[] = { 1, 2, 3 }; static const int to_id[] = { MS_LEFT, MS_RIGHT, MS_MIDDLE }; @@ -141,13 +355,8 @@ ms_rint(c) */ if (ms->ms_ready == 0) return; - if (c & (TTY_FE|TTY_PE)) { - log(LOG_WARNING, - "mouse input parity or framing error (0x%x)\n", c); - ms->ms_byteno = -1; - return; - } + ms->ms_nodata = 0; /* * Run the decode loop, adding to the current information. * We add, rather than replace, deltas, so that if the event queue @@ -161,7 +370,7 @@ ms_rint(c) case 0: /* buttons */ ms->ms_byteno = 1; - ms->ms_mb = c & 0x7; + ms->ms_mb = c & 0x3; return; case 1: @@ -172,12 +381,12 @@ ms_rint(c) case 2: /* delta-y */ - ms->ms_byteno = -1 /* wait for button-byte again */; + ms->ms_byteno = -1; ms->ms_dy += (char)c; break; default: - panic("ms_rint"); + panic("ms_input"); /* NOTREACHED */ } @@ -206,7 +415,6 @@ ms_rint(c) put = 0; \ fe = &ms->ms_events.ev_q[0]; \ } \ - any = 1 mb = ms->ms_mb; ub = ms->ms_ub; @@ -222,6 +430,7 @@ ms_rint(c) fe->time = time; ADVANCE; ub ^= d; + any++; } if (ms->ms_dx) { NEXT; @@ -230,14 +439,16 @@ ms_rint(c) fe->time = time; ADVANCE; ms->ms_dx = 0; + any++; } if (ms->ms_dy) { NEXT; fe->id = LOC_Y_DELTA; - fe->value = -ms->ms_dy; /* XXX? */ + fe->value = -ms->ms_dy; /* XXX? */ fe->time = time; ADVANCE; ms->ms_dy = 0; + any++; } out: if (any) { @@ -247,100 +458,225 @@ out: } } -int -msopen(dev, flags, mode, p) - dev_t dev; - int flags, mode; - struct proc *p; -{ - if (ms_softc.ms_events.ev_io) - return (EBUSY); - ms_softc.ms_events.ev_io = p; - ev_init(&ms_softc.ms_events); /* may cause sleep */ - ms_softc.ms_ready = 1; /* start accepting events */ - (*ms_softc.ms_open)(ms_softc.ms_mouse); - return (0); -} -int -msclose(dev, flags, mode, p) - dev_t dev; - int flags, mode; - struct proc *p; +/**************************************************************** + * Interface to the lower layer (zscc) + ****************************************************************/ + +static void ms_rxint __P((struct zs_chanstate *)); +static void ms_txint __P((struct zs_chanstate *)); +static void ms_stint __P((struct zs_chanstate *)); +static void ms_softint __P((struct zs_chanstate *)); + +static void +ms_rxint(cs) + register struct zs_chanstate *cs; { + register struct ms_softc *ms; + register int put, put_next; + register u_char c, rr1; - ms_modem(0); - ms_softc.ms_ready = 0; /* stop accepting events */ - ev_fini(&ms_softc.ms_events); - (*ms_softc.ms_close)(ms_softc.ms_mouse); - ms_softc.ms_events.ev_io = NULL; - return (0); -} + ms = cs->cs_private; + put = ms->ms_rbput; -int -msread(dev, uio, flags) - dev_t dev; - struct uio *uio; - int flags; -{ + /* + * First read the status, because reading the received char + * destroys the status of this char. + */ + rr1 = zs_read_reg(cs, 1); + c = zs_read_data(cs); - return (ev_read(&ms_softc.ms_events, uio, flags)); -} - -/* this routine should not exist, but is convenient to write here for now */ -int -mswrite(dev, uio, flags) - dev_t dev; - struct uio *uio; - int flags; -{ - - return (EOPNOTSUPP); -} - -int -msioctl(dev, cmd, data, flag, p) - dev_t dev; - u_long cmd; - register caddr_t data; - int flag; - struct proc *p; -{ - switch (cmd) { - - case FIONBIO: /* we will remove this someday (soon???) */ - return (0); - - case FIOASYNC: - ms_softc.ms_events.ev_async = *(int *)data != 0; - return (0); - - case TIOCSPGRP: - if (*(int *)data != ms_softc.ms_events.ev_io->p_pgid) - return (EPERM); - return (0); - - case VUIDGFORMAT: - /* we only do firm_events */ - *(int *)data = VUID_FIRM_EVENT; - return (0); - - case VUIDSFORMAT: - if (*(int *)data != VUID_FIRM_EVENT) - return (EINVAL); - return (0); + if (rr1 & (ZSRR1_FE | ZSRR1_DO | ZSRR1_PE)) { + /* Clear the receive error. */ + zs_write_csr(cs, ZSWR0_RESET_ERRORS); } - return (ENOTTY); + + ms->ms_rbuf[put] = (c << 8) | rr1; + put_next = (put + 1) & MS_RX_RING_MASK; + + /* Would overrun if increment makes (put==get). */ + if (put_next == ms->ms_rbget) { + ms->ms_intr_flags |= INTR_RX_OVERRUN; + } else { + /* OK, really increment. */ + put = put_next; + } + + /* Done reading. */ + ms->ms_rbput = put; + + /* Ask for softint() call. */ + cs->cs_softreq = 1; } -int -mspoll(dev, events, p) - dev_t dev; - int events; - struct proc *p; + +static void +ms_txint(cs) + register struct zs_chanstate *cs; { + register struct ms_softc *ms; - return (ev_poll(&ms_softc.ms_events, events, p)); + ms = cs->cs_private; + zs_write_csr(cs, ZSWR0_RESET_TXINT); + ms->ms_intr_flags |= INTR_TX_EMPTY; + /* Ask for softint() call. */ + cs->cs_softreq = 1; } + +static void +ms_stint(cs) + register struct zs_chanstate *cs; +{ + register struct ms_softc *ms; + register int rr0; + + ms = cs->cs_private; + + rr0 = zs_read_csr(cs); + zs_write_csr(cs, ZSWR0_RESET_STATUS); + + /* + * We have to accumulate status line changes here. + * Otherwise, if we get multiple status interrupts + * before the softint runs, we could fail to notice + * some status line changes in the softint routine. + * Fix from Bill Studenmund, October 1996. + */ + cs->cs_rr0_delta |= (cs->cs_rr0 ^ rr0); + cs->cs_rr0 = rr0; + ms->ms_intr_flags |= INTR_ST_CHECK; + + /* Ask for softint() call. */ + cs->cs_softreq = 1; +} + + +static void +ms_softint(cs) + struct zs_chanstate *cs; +{ + register struct ms_softc *ms; + register int get, c, s; + int intr_flags; + register u_short ring_data; + + ms = cs->cs_private; + + /* Atomically get and clear flags. */ + s = splzs(); + intr_flags = ms->ms_intr_flags; + ms->ms_intr_flags = 0; + + /* Now lower to spltty for the rest. */ + (void) spltty(); + + /* + * Copy data from the receive ring to the event layer. + */ + get = ms->ms_rbget; + while (get != ms->ms_rbput) { + ring_data = ms->ms_rbuf[get]; + get = (get + 1) & MS_RX_RING_MASK; + + /* low byte of ring_data is rr1 */ + c = (ring_data >> 8) & 0xff; + + if (ring_data & ZSRR1_DO) + intr_flags |= INTR_RX_OVERRUN; + if (ring_data & (ZSRR1_FE | ZSRR1_PE)) { + log(LOG_ERR, "%s: input error (0x%x)\n", + ms->ms_dev.dv_xname, ring_data); + c = -1; /* signal input error */ + } + + /* Pass this up to the "middle" layer. */ + ms_input(ms, c); + } + if (intr_flags & INTR_RX_OVERRUN) { + log(LOG_ERR, "%s: input overrun\n", + ms->ms_dev.dv_xname); + } + ms->ms_rbget = get; + + if (intr_flags & INTR_TX_EMPTY) { + /* + * Transmit done. (Not expected.) + */ + log(LOG_ERR, "%s: transmit interrupt?\n", + ms->ms_dev.dv_xname); + } + + if (intr_flags & INTR_ST_CHECK) { + /* + * Status line change. (Not expected.) + */ + log(LOG_ERR, "%s: status interrupt?\n", + ms->ms_dev.dv_xname); + cs->cs_rr0_delta = 0; + } + + splx(s); +} + +struct zsops zsops_ms = { + ms_rxint, /* receive char available */ + ms_stint, /* external/status */ + ms_txint, /* xmit buffer empty */ + ms_softint, /* process software interrupt */ +}; + + +static void +ms_trigger (cs, onoff) + struct zs_chanstate *cs; + int onoff; +{ + /* for front connected one */ + if (onoff) + cs->cs_preg[5] |= ZSWR5_RTS; + else + cs->cs_preg[5] &= ~ZSWR5_RTS; + cs->cs_creg[5] = cs->cs_preg[5]; + zs_write_reg(cs, 5, cs->cs_preg[5]); + + /* for keyborad connected one */ + while (!(mfp.tsr & MFP_TSR_BE)); + mfp.udr = onoff | 0x40; +} + +/* + * mouse timer interrupt. + * called after system tick interrupt is done. + */ void -mouseattach(){} /* XXX pseudo-device */ +ms_modem(void) +{ + struct ms_softc *ms = ms_cd.cd_devs[0]; + int s; + + if (!ms->ms_ready) + return; + if (ms->ms_nodata++ > 300) { /* XXX */ + log(LOG_ERR, "%s: no data for 3 secs. resetting.\n", + ms->ms_dev.dv_xname); + ms->ms_nodata = 0; + ms->ms_byteno = -1; + ms->ms_rts = 1; + ms_trigger(ms->ms_cs, 1); + return; + } + + s = splzs(); + if (ms->ms_rts) { + if (ms->ms_byteno == -1) { + /* start next sequence */ + ms->ms_rts = 0; + ms_trigger(ms->ms_cs, ms->ms_rts); + ms->ms_byteno = 0; + } + } else { + ms->ms_rts = 1; + ms_trigger(ms->ms_cs, ms->ms_rts); + } + splx(s); +} diff --git a/sys/arch/x68k/dev/zs.c b/sys/arch/x68k/dev/zs.c index eda628a90119..994deba6166c 100644 --- a/sys/arch/x68k/dev/zs.c +++ b/sys/arch/x68k/dev/zs.c @@ -1,17 +1,12 @@ -/* $NetBSD: zs.c,v 1.11 1998/08/04 16:51:52 minoura Exp $ */ +/* $NetBSD: zs.c,v 1.12 1998/08/05 16:08:36 minoura Exp $ */ -/* - * Copyright (c) 1992, 1993 - * The Regents of the University of California. All rights reserved. +/*- + * Copyright (c) 1998 Minoura Makoto + * Copyright (c) 1996 The NetBSD Foundation, Inc. + * 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. + * This code is derived from software contributed to The NetBSD Foundation + * by Gordon W. Ross. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -23,191 +18,115 @@ * 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 product includes software developed by the NetBSD + * Foundation, Inc. and its contributors. + * 4. Neither the name of The NetBSD Foundation 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 + * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. 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 FOUNDATION 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. */ /* - * Zilog Z8530 (ZSCC) driver. + * Zilog Z8530 Dual UART driver (machine-dependent part) * - * 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. + * X68k uses one Z8530 built-in. Channel A is for RS-232C serial port; + * while channel B is dedicated to the mouse. + * Extra Z8530's can be installed. This driver supports up to 5 chips + * including the built-in one. */ -#include "opt_ddb.h" - -#include "zs.h" -#if NZS > 0 - #include #include -#include -#include #include +#include #include #include +#include +#include #include #include -#include #include #include +#include +/*#include */ -#include #include -#include -#ifdef KGDB -#include -#endif +#include "zsc.h" /* NZSC */ +#include "zstty.h" -#define ZSMAJOR 12 /* XXX */ +/* Make life easier for the initialized arrays here. */ -#define ZSUNIT(x) (minor(x) & 0x7f) -#define ZSDIALOUT(x) (minor(x) & 0x80) -#define ZS_MOUSE 1 /* XXX */ - -#define PCLK (5*1000*1000) /* PCLK pin input clock rate */ - -#if 0 -/* - * 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 -#endif +extern void Debugger __P((void)); /* - * Software state per found chip. This would be called `zs_softc', - * but the previous driver had a rather different zs_softc.... + * Some warts needed by z8530tty.c - + * The default parity REALLY needs to be the same as the PROM uses, + * or you can not see messages done with printf during boot-up... */ -struct zs_softc { - 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 */ +int zs_def_cflag = (CREAD | CS8 | HUPCL); +int zs_major = 12; + +/* + * X68k provides a 5.0 MHz clock to the ZS chips. + * XXX: use 4.9152MHz constant for now!!! + */ +#define PCLK (9600 * 512) /* PCLK pin input clock rate */ + +static u_char zs_init_reg[16] = { + 0, /* 0: CMD (reset, etc.) */ + 0, /* 1: No interrupts yet. */ + 0x70, /* 2: XXX: IVECT */ + ZSWR3_RX_8 | ZSWR3_RX_ENABLE, + ZSWR4_CLK_X16 | ZSWR4_ONESB | ZSWR4_EVENP, + ZSWR5_TX_8 | ZSWR5_TX_ENABLE, + 0, /* 6: TXSYNC/SYNCLO */ + 0, /* 7: RXSYNC/SYNCHI */ + 0, /* 8: alias for data port */ + ZSWR9_MASTER_IE, + ZSWR10_NRZ, /*10: Misc. TX/RX control bits */ + ZSWR11_TXCLK_BAUD | ZSWR11_RXCLK_BAUD, + 14, /*12: BAUDLO (default=9600) */ + 0, /*13: BAUDHI (default=9600) */ + ZSWR14_BAUD_ENA | ZSWR14_BAUD_FROM_PCLK, + ZSWR15_BREAK_IE | ZSWR15_DCD_IE, }; -struct tty *zs_tty[NZS * 2]; /* XXX should be dynamic */ +static volatile struct zschan *conschan = 0; + + +/**************************************************************** + * Autoconfig + ****************************************************************/ /* Definition of the driver for autoconfig. */ -static int zsmatch __P((struct device *, struct cfdata *, void *)); -static void zsattach __P((struct device *, struct device *, void *)); +static int zs_match __P((struct device *, struct cfdata *, void *)); +static void zs_attach __P((struct device *, struct device *, void *)); +static int zs_print __P((void *, const char *name)); -struct cfattach zs_ca = { - sizeof(struct zs_softc), zsmatch, zsattach +struct cfattach zsc_ca = { + sizeof(struct zsc_softc), zs_match, zs_attach }; -extern struct cfdriver zs_cd; +extern struct cfdriver zsc_cd; -#ifdef x68k -static struct zs_chanstate *zsms; -void zs_msmodem __P((int)); -#endif +static volatile struct zsdevice *findzs(int); +int zshard __P((void)); +int zssoft __P((void *)); +static int zs_get_speed __P((struct zs_chanstate *)); -/* Interrupt handlers. */ -void zshard __P((int)); -int zssoft __P((void *)); - -struct zs_chanstate *zslist; - -/* Routines called from other code. */ -cdev_decl(zs); - -static void zsiopen __P((struct tty *)); -static void zsiclose __P((struct tty *)); -static void zs_shutdown __P((struct zs_chanstate *cs)); -static void zsstart __P((struct tty *)); -void zsstop __P((struct tty *, int)); -static int zsparam __P((struct tty *, struct termios *)); -static int zshwiflow __P((struct tty *, int)); - -/* Routines purely local to this driver. */ -static int zs_getspeed __P((volatile struct zschan *)); -#ifdef KGDB -static void zs_reset __P((volatile struct zschan *, int, int)); -#endif -static void zs_modem __P((struct zs_chanstate *, int)); -static void zs_loadchannelregs __P((volatile struct zschan *, u_char *)); -static void zsabort __P((void)); -static int zsrint __P((struct zs_chanstate *, volatile struct zschan *)); -static int zsxint __P((struct zs_chanstate *, volatile struct zschan *)); -static int zssint __P((struct zs_chanstate *, volatile struct zschan *)); -static void zsoverrun __P((int, long *, char *)); - -/* Console stuff. */ -static struct tty *zs_ctty; /* console `struct tty *' */ -static int zs_consin = -1, zs_consout = -1; -static void zscnputc __P((int)); /* console putc function */ -static volatile struct zschan *zs_conschan; -static struct tty *zs_checkcons __P((struct zs_softc *, 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 __P((int, struct zs_chanstate *, struct tty *)); -#endif - -static volatile struct zsdevice *findzs __P((int)); -static volatile struct zsdevice *zsaddr[NZS]; /* XXX, but saves work */ - -int zshardscope; -int zsshortcuts; /* number of "shortcut" software interrupts */ - -static u_int zs_read __P((volatile struct zschan *, u_int reg)); -static u_int zs_write __P((volatile struct zschan *, u_int, u_int)); - -static u_int -zs_read(zc, reg) - volatile struct zschan *zc; - u_int reg; -{ - u_char val; - - zc->zc_csr = reg; - ZS_DELAY(); - val = zc->zc_csr; - ZS_DELAY(); - return val; -} - -static u_int -zs_write(zc, reg, val) - volatile struct zschan *zc; - u_int reg, val; -{ - zc->zc_csr = reg; - ZS_DELAY(); - zc->zc_csr = val; - ZS_DELAY(); - return val; -} /* * find zs address for x68k architecture @@ -225,11 +144,10 @@ findzs(zs) } /* - * Match slave number to zs unit number, so that misconfiguration will - * not set up the keyboard as ttya, etc. + * Is the zs chip present? */ static int -zsmatch(parent, cfp, aux) +zs_match(parent, cfp, aux) struct device *parent; struct cfdata *cfp; void *aux; @@ -245,1339 +163,347 @@ zsmatch(parent, cfp, aux) /* * 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 void -zsattach(parent, dev, aux) +zs_attach(parent, self, aux) struct device *parent; - struct device *dev; + struct device *self; void *aux; { - register int zs = dev->dv_unit, unit; - register struct zs_softc *zi; - register struct zs_chanstate *cs; - register volatile struct zsdevice *addr; - register struct tty *tp, *ctp; - register struct confargs *ca = aux; - int pri; - - if ((addr = zsaddr[zs]) == NULL) - addr = zsaddr[zs] = findzs(zs); - printf(" (%s)\n", zs ? "external" : "onboard"); - zi = (struct zs_softc *)dev; - zi->zi_zs = addr; - unit = zs * 2; - cs = zi->zi_cs; - cs->cs_ttyp = tp = ttymalloc(); - - /* 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[ZS_CHAN_A]); - cs->cs_zc = &addr->zs_chan[ZS_CHAN_A]; - tp->t_dev = makedev(ZSMAJOR, unit); - tp->t_oproc = zsstart; - tp->t_param = zsparam; - tp->t_hwiflow = zshwiflow; - if ((ctp = zs_checkcons(zi, unit, cs)) != NULL) - cs->cs_ttyp = tp = ctp; -#ifdef KGDB - if (ctp == NULL) - zs_checkkgdb(unit, cs, tp); -#endif -#ifdef sun - 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 */ - } -#endif - if (tp != ctp) - tty_attach(tp); - ZS_WRITE(cs->cs_zc, 2, 0x70 + zs); /* XXX interrupt vector */ - unit++; - cs++; - cs->cs_ttyp = tp = ttymalloc(); - cs->cs_unit = unit; - cs->cs_speed = zs_getspeed(&addr->zs_chan[ZS_CHAN_B]); - cs->cs_zc = &addr->zs_chan[ZS_CHAN_B]; - tp->t_dev = makedev(ZSMAJOR, unit); - tp->t_oproc = zsstart; - tp->t_param = zsparam; - if (unit != ZS_MOUSE) - tp->t_hwiflow = zshwiflow; - if ((ctp = zs_checkcons(zi, unit, cs)) != NULL) - cs->cs_ttyp = tp = ctp; -#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 | CSTOPB; - ms_serial(tp, zsiopen, zsiclose); -#ifdef x68k - zsms = cs; -#endif - } else { - if (tp != ctp) - tty_attach(tp); - } -} - -#ifdef KGDB -/* - * Put a channel in a known state. Interrupts may be left disabled - * or enabled, as desired. - */ -static void -zs_reset(zc, inten, speed) + struct zsc_softc *zsc = (void *) self; + struct zsc_attach_args zsc_args; 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); -} -#endif - -/* - * Polled console output putchar. - */ -static void -zscnputc(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 (CPU_ISSUN4C && s <= (12 << 8)) - (void) splzs(); -#endif - while ((zc->zc_csr & ZSRR0_TX_READY) == 0) - ZS_DELAY(); - zc->zc_data = c; - ZS_DELAY(); - 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(zi, unit, cs) - struct zs_softc *zi; - int unit; struct zs_chanstate *cs; -{ - register struct tty *tp; - char *i, *o; + int s, zs_unit, channel; - if ((tp = zs_ctty) == NULL) /* XXX */ - return (0); - i = zs_consin == unit ? "input" : NULL; - o = zs_consout == unit ? "output" : NULL; - if (i == NULL && o == NULL) - return (0); + zs_unit = zsc->zsc_dev.dv_unit; + zsc->zsc_addr = (void*) findzs (zs_unit); - /* rewire the minor device (gack) */ - tp->t_dev = makedev(major(tp->t_dev), unit); + printf("\n"); /* - * 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 + * Initialize software state for each channel. */ - if (i) { - tp->t_param = zsparam; - tp->t_ispeed = tp->t_ospeed = cs->cs_speed; - tp->t_cflag = CS8; - ttsetwater(tp); + for (channel = 0; channel < 2; channel++) { + struct device *child; + + zsc_args.channel = channel; + zsc_args.hwflags = 0; + cs = &zsc->zsc_cs_store[channel]; + zsc->zsc_cs[channel] = cs; + + cs->cs_channel = channel; + cs->cs_private = NULL; + cs->cs_ops = &zsops_null; + cs->cs_brg_clk = PCLK / 16; + + if (channel == 0) + zc = (void*) &zsc->zsc_addr->zs_chan_a; + else + zc = (void*) &zsc->zsc_addr->zs_chan_b; + cs->cs_reg_csr = &zc->zc_csr; + cs->cs_reg_data = &zc->zc_data; + + zs_init_reg[2] = 0x70 + zs_unit; + bcopy(zs_init_reg, cs->cs_creg, 16); + bcopy(zs_init_reg, cs->cs_preg, 16); + + cs->cs_defspeed = 9600; + cs->cs_defcflag = zs_def_cflag; + + /* Make these correspond to cs_defcflag (-crtscts) */ + cs->cs_rr0_dcd = ZSRR0_DCD; + cs->cs_rr0_cts = 0; + cs->cs_wr5_dtr = ZSWR5_DTR | ZSWR5_RTS; + cs->cs_wr5_rts = 0; + + /* + * Clear the master interrupt enable. + * The INTENA is common to both channels, + * so just do it on the A channel. + */ + if (channel == 0) { + s = splzs(); + zs_write_reg(cs, 9, 0); + splx(s); + } + + /* + * Look for a child driver for this channel. + * The child attach will setup the hardware. + */ + child = config_found(self, (void *)&zsc_args, zs_print); + if (child == NULL) { + /* No sub-driver. Just reset it. */ + u_char reset = (channel == 0) ? + ZSWR9_A_RESET : ZSWR9_B_RESET; + s = splzs(); + zs_write_reg(cs, 9, reset); + splx(s); + } } - if (o) { - tp->t_oproc = zsstart; - } - printf("%s%c: console %s\n", - zi->zi_dev.dv_xname, (unit & 1) + 'a', i ? (o ? "i/o" : i) : o); - cs->cs_consio = 1; - cs->cs_brkabort = 1; - return (tp); -} - -#ifdef KGDB -/* - * The kgdb zs port, if any, was altered at boot time (see zs_kgdb_init). - * Pick up the current speed and character size and restore the original - * speed. - */ -static void -zs_checkkgdb(unit, cs, tp) - int unit; - struct zs_chanstate *cs; - struct tty *tp; -{ - - if (kgdb_dev == makedev(ZSMAJOR, unit)) { - tp->t_ispeed = tp->t_ospeed = kgdb_rate; - tp->t_cflag = CS8; - cs->cs_kgdb = 1; - cs->cs_speed = zs_kgdb_savedspeed; - (void) zsparam(tp, &tp->t_termios); - } -} -#endif - -/* - * Compute the current baud rate given a ZSCC channel. - */ -static int -zs_getspeed(zc) - register volatile struct zschan *zc; -{ - register int tconst; - - tconst = ZS_READ(zc, 12); - tconst |= ZS_READ(zc, 13) << 8; - return (TCONST_TO_BPS(PCLK / 16, tconst)); -} - - -/* - * Do an internal open. - */ -static void -zsiopen(tp) - struct tty *tp; -{ - - (void) zsparam(tp, &tp->t_termios); - ttsetwater(tp); - tp->t_state = TS_ISOPEN | TS_CARR_ON; -} - -/* - * Do an internal close. Eventually we should shut off the chip when both - * ports on it are closed. - */ -static void -zsiclose(tp) - struct tty *tp; -{ - - ttylclose(tp, 0); /* ??? */ - ttyclose(tp); /* ??? */ - tp->t_state = 0; -} - - -static void -zs_shutdown(cs) - struct zs_chanstate *cs; -{ - struct tty *tp = cs->cs_ttyp; - int s; + /* + * Set the master interrupt enable and interrupt vector. + * (common to both channels, do it on A) + */ + cs = zsc->zsc_cs[0]; s = splzs(); - - /* XXX not yet */ - - /* Clear any break condition set with TIOCSBRK. */ - cs->cs_preg[5] &= ~ZSWR5_BREAK; - cs->cs_creg[5] &= ~ZSWR5_BREAK; - ZS_WRITE(cs->cs_zc, 5, cs->cs_creg[5]); - - /* - * Hang up if necessary. Wait a bit, so the other side has time to - * notice even if we immediately open the port again. - */ - if (tp->t_cflag & HUPCL) { - zs_modem(cs, 0); - (void) tsleep(cs, TTIPRI, ttclos, hz); - } - + /* interrupt vector */ + zs_write_reg(cs, 2, 0x70 + zs_unit); + /* master interrupt control (enable) */ + zs_write_reg(cs, 9, zs_init_reg[9]); splx(s); } -/* - * Open a zs serial port. This interface may not be used to open - * the keyboard and mouse ports. (XXX) - */ -int -zsopen(dev, flags, mode, p) - dev_t dev; - int flags; - int mode; - struct proc *p; +static int +zs_print(aux, name) + void *aux; + const char *name; { - register struct tty *tp; - register struct zs_chanstate *cs; - struct zs_softc *zi; - int unit = ZSUNIT(dev), zs = unit >> 1, error, s; + struct zsc_attach_args *args = aux; - if (zs >= zs_cd.cd_ndevs || (zi = zs_cd.cd_devs[zs]) == NULL || - unit == ZS_MOUSE) - return (ENXIO); - if (zi->zi_zs == NULL) - return (ENXIO); - cs = &zi->zi_cs[unit & 1]; - if (cs->cs_consio) - return (ENXIO); /* ??? */ - tp = cs->cs_ttyp; - if ((tp->t_state & TS_ISOPEN) && - (tp->t_state & TS_XCLUDE) && - p->p_ucred->cr_uid != 0) - return (EBUSY); + if (name != NULL) + printf("%s: ", name); - s = spltty(); + if (args->channel != -1) + printf(" channel %d", args->channel); - if ((tp->t_state & TS_ISOPEN) == 0 && tp->t_wopen == 0) { - ttychars(tp); - 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 = cs->cs_speed; - (void) zsparam(tp, &tp->t_termios); - ttsetwater(tp); - } - - splx(s); - - error = ttyopen(tp, ZSDIALOUT(dev), flags & O_NONBLOCK); - if (error) - goto bad; - - error = (*linesw[tp->t_line].l_open)(dev, tp); - if (error) - goto bad; - - return (0); - -bad: - if ((tp->t_state & TS_ISOPEN) == 0 && tp->t_wopen == 0) { - /* - * We failed to open the device, and nobody else had it opened. - * Clean up the state as appropriate. - */ - zs_shutdown(cs); - } - - return (error); + return UNCONF; } +static volatile int zssoftpending; + /* - * Close a zs serial port. + * Our ZS chips all share a common, autovectored interrupt, + * so we have to look at all of them on each interrupt. */ int -zsclose(dev, flags, mode, p) - dev_t dev; - int flags; - int mode; - struct proc *p; +zshard(void) { - register struct zs_chanstate *cs; - register struct tty *tp; - struct zs_softc *zi; - int unit = ZSUNIT(dev), s; + register struct zsc_softc *zsc; + register int unit, rval, softreq; - zi = zs_cd.cd_devs[unit >> 1]; - cs = &zi->zi_cs[unit & 1]; - tp = cs->cs_ttyp; - linesw[tp->t_line].l_close(tp, flags); - if ((tp->t_state & TS_ISOPEN) == 0 && tp->t_wopen == 0) { - /* - * Although we got a last close, the device may still be in - * use; e.g. if this was the dialout node, and there are still - * processes waiting for carrier on the non-dialout node. - */ - zs_shutdown(cs); + rval = softreq = 0; + for (unit = 0; unit < zsc_cd.cd_ndevs; unit++) { + zsc = zsc_cd.cd_devs[unit]; + if (zsc == NULL) + continue; + rval |= zsc_intr_hard(zsc); + softreq |= zsc->zsc_cs[0]->cs_softreq; + softreq |= zsc->zsc_cs[1]->cs_softreq; } - ttyclose(tp); -#ifdef KGDB - /* Reset the speed if we're doing kgdb on this port */ - if (cs->cs_kgdb) { - tp->t_ispeed = tp->t_ospeed = kgdb_rate; - (void) zsparam(tp, &tp->t_termios); - } -#endif - return (0); -} -/* - * Read/write zs serial port. - */ -int -zsread(dev, uio, flags) - dev_t dev; - struct uio *uio; - int flags; -{ - register struct zs_chanstate *cs; - register struct zs_softc *zi; - register struct tty *tp; - int unit = ZSUNIT(dev); - - zi = zs_cd.cd_devs[unit >> 1]; - cs = &zi->zi_cs[unit & 1]; - tp = cs->cs_ttyp; - - return (linesw[tp->t_line].l_read(tp, uio, flags)); - -} - -int -zswrite(dev, uio, flags) - dev_t dev; - struct uio *uio; - int flags; -{ - register struct zs_chanstate *cs; - register struct zs_softc *zi; - register struct tty *tp; - int unit = ZSUNIT(dev); - - zi = zs_cd.cd_devs[unit >> 1]; - cs = &zi->zi_cs[unit & 1]; - tp = cs->cs_ttyp; - - return (linesw[tp->t_line].l_write(tp, uio, flags)); -} - -struct tty * -zstty(dev) - dev_t dev; -{ - register struct zs_chanstate *cs; - register struct zs_softc *zi; - int unit = ZSUNIT(dev); - - zi = zs_cd.cd_devs[unit >> 1]; - cs = &zi->zi_cs[unit & 1]; - - return (cs->cs_ttyp); - -} - -/* - * ZS hardware interrupt. Scan all ZS channels. NB: we know here that - * channels are kept in (A,B) pairs. - * - * Do just a little, then get out; set a software interrupt if more - * work is needed. - * - * We deliberately ignore the vectoring Zilog gives us, and match up - * only the number of `reset interrupt under service' operations, not - * the order. - */ -/* ARGSUSED */ -void -zshard(intrarg) - int intrarg; -{ - register struct zs_chanstate *a; -#define b (a + 1) - register volatile struct zschan *zc; - register int rr3, intflags = 0, v, i; - - a = &((struct zs_softc*)zs_cd.cd_devs[(intrarg >> 2) & 0x0f])->zi_cs[0]; - rr3 = ZS_READ(a->cs_zc, 3); - if (rr3 & (ZSRR3_IP_A_RX|ZSRR3_IP_A_TX|ZSRR3_IP_A_STAT)) { - intflags |= 2; - zc = a->cs_zc; - i = a->cs_rbput; - if (rr3 & ZSRR3_IP_A_RX && (v = zsrint(a, zc)) != 0) { - a->cs_rbuf[i++ & ZLRB_RING_MASK] = v; - intflags |= 1; - } - if (rr3 & ZSRR3_IP_A_TX && (v = zsxint(a, zc)) != 0) { - a->cs_rbuf[i++ & ZLRB_RING_MASK] = v; - intflags |= 1; - intflags |= 4; - } - if (rr3 & ZSRR3_IP_A_STAT && (v = zssint(a, zc)) != 0) { - a->cs_rbuf[i++ & ZLRB_RING_MASK] = v; - intflags |= 1; - } - a->cs_rbput = i; - } - if (rr3 & (ZSRR3_IP_B_RX|ZSRR3_IP_B_TX|ZSRR3_IP_B_STAT)) { - intflags |= 2; - zc = b->cs_zc; - i = b->cs_rbput; - if (rr3 & ZSRR3_IP_B_RX && (v = zsrint(b, zc)) != 0) { - b->cs_rbuf[i++ & ZLRB_RING_MASK] = v; - intflags |= 1; - } - if (rr3 & ZSRR3_IP_B_TX && (v = zsxint(b, zc)) != 0) { - b->cs_rbuf[i++ & ZLRB_RING_MASK] = v; - intflags |= 1; - intflags |= 4; - } - if (rr3 & ZSRR3_IP_B_STAT && (v = zssint(b, zc)) != 0) { - b->cs_rbuf[i++ & ZLRB_RING_MASK] = v; - intflags |= 1; - } - b->cs_rbput = i; - } -#undef b - if (intflags & 1) { -#if defined(SUN4C) || defined(SUN4M) - if (CPU_ISSUN4M || CPU_ISSUN4C) { - /* XXX -- but this will go away when zshard moves to locore.s */ - struct clockframe *p = intrarg; - - if ((p->psr & PSR_PIL) < (PIL_TTY << 8)) { - zsshortcuts++; - (void) spltty(); - if (zshardscope) { - LED_ON; - LED_OFF; - } - return (zssoft(intrarg)); - } - } -#endif -#if x68k -#define PSL_TTY PSL_IPL4 /* XXX */ - if (((intrarg >> 16) & PSL_IPL) < PSL_TTY) { - zsshortcuts++; - (void) spltty(); - zssoft(0/*intrarg*/); - return; - } + /* We are at splzs here, so no need to lock. */ + if (softreq && (zssoftpending == 0)) { + zssoftpending = 1; setsoftserial(); -#else - ienab_bis(IE_ZSSOFT); -#endif - } -} - -static int -zsrint(cs, zc) - register struct zs_chanstate *cs; - register volatile struct zschan *zc; -{ - register int c = zc->zc_data; - - ZS_DELAY(); -#ifndef x68k - if (cs->cs_conk) { - register struct conk_state *conk = &zsconk_state; - - /* - * Check here for console abort function, so that we - * can abort even when interrupts are locking up the - * machine. - */ - if (c == KBD_RESET) { - conk->conk_id = 1; /* ignore next byte */ - conk->conk_l1 = 0; - } else if (conk->conk_id) - conk->conk_id = 0; /* stop ignoring bytes */ - else if (c == KBD_L1) - conk->conk_l1 = 1; /* L1 went down */ - else if (c == (KBD_L1|KBD_UP)) - conk->conk_l1 = 0; /* L1 went up */ - else if (c == KBD_A && conk->conk_l1) { - zsabort(); - conk->conk_l1 = 0; /* we never see the up */ - goto clearit; /* eat the A after L1-A */ - } - } -#endif -#ifdef KGDB - if (c == FRAME_START && cs->cs_kgdb && - (cs->cs_ttyp->t_state & TS_ISOPEN) == 0) { - zskgdb(cs->cs_unit); - goto clearit; - } -#endif - /* compose receive character and status */ - c <<= 8; - c |= ZS_READ(zc, 1); - - /* clear receive error & interrupt condition */ - zc->zc_csr = ZSWR0_RESET_ERRORS; - ZS_DELAY(); - zc->zc_csr = ZSWR0_CLR_INTR; - ZS_DELAY(); - - return (ZRING_MAKE(ZRING_RINT, c)); - -clearit: - zc->zc_csr = ZSWR0_RESET_ERRORS; - ZS_DELAY(); - zc->zc_csr = ZSWR0_CLR_INTR; - ZS_DELAY(); - return (0); -} - -static int -zsxint(cs, zc) - register struct zs_chanstate *cs; - register volatile struct zschan *zc; -{ - register int i = cs->cs_tbc; - - if (i == 0) { - zc->zc_csr = ZSWR0_RESET_TXINT; - ZS_DELAY(); - zc->zc_csr = ZSWR0_CLR_INTR; - ZS_DELAY(); - return (ZRING_MAKE(ZRING_XINT, 0)); - } - cs->cs_tbc = i - 1; - zc->zc_data = *cs->cs_tba++; - ZS_DELAY(); - zc->zc_csr = ZSWR0_CLR_INTR; - ZS_DELAY(); - return (0); -} - -static int -zssint(cs, zc) - register struct zs_chanstate *cs; - register volatile struct zschan *zc; -{ - register int rr0; - - rr0 = zc->zc_csr; - ZS_DELAY(); - zc->zc_csr = ZSWR0_RESET_STATUS; - ZS_DELAY(); - zc->zc_csr = ZSWR0_CLR_INTR; - ZS_DELAY(); - /* - * The chip's hardware flow control is, as noted in zsreg.h, - * busted---if the DCD line goes low the chip shuts off the - * receiver (!). If we want hardware CTS flow control but do - * not have it, and carrier is now on, turn HFC on; if we have - * HFC now but carrier has gone low, turn it off. - */ - if (rr0 & ZSRR0_DCD) { - if (cs->cs_ttyp->t_cflag & CCTS_OFLOW && - (cs->cs_creg[3] & ZSWR3_HFC) == 0) { - cs->cs_creg[3] |= ZSWR3_HFC; - ZS_WRITE(zc, 3, cs->cs_creg[3]); - } - } else { - if (cs->cs_creg[3] & ZSWR3_HFC) { - cs->cs_creg[3] &= ~ZSWR3_HFC; - ZS_WRITE(zc, 3, cs->cs_creg[3]); - } - } - if ((rr0 & ZSRR0_BREAK) && cs->cs_brkabort) { -#ifdef SUN4 - /* - * XXX This might not be necessary. Test and - * delete if it isn't. - */ - if (CPU_ISSUN4) { - while (zc->zc_csr & ZSRR0_BREAK) - ZS_DELAY(); - } -#endif - zsabort(); - return (0); - } - return (ZRING_MAKE(ZRING_SINT, rr0)); -} - -static void -zsabort() -{ - -#ifdef DDB - Debugger(); -#else - printf("stopping on keyboard abort\n"); -#ifndef x68k - callrom(); -#endif -#endif -} - -#ifdef KGDB -/* - * KGDB framing character received: enter kernel debugger. This probably - * should time out after a few seconds to avoid hanging on spurious input. - */ -void -zskgdb(unit) - int unit; -{ - - printf("zs%d%c: kgdb interrupt\n", unit >> 1, (unit & 1) + 'a'); - kgdb_connect(1); -} -#endif - -/* - * Print out a ring or fifo overrun error message. - */ -static void -zsoverrun(unit, ptime, what) - int unit; - long *ptime; - char *what; -{ - - if (*ptime != time.tv_sec) { - *ptime = time.tv_sec; - log(LOG_WARNING, "zs%d%c: %s overrun\n", unit >> 1, - (unit & 1) + 'a', what); } + return (rval); } /* - * ZS software interrupt. Scan all channels for deferred interrupts. + * Similar scheme as for zshard (look at all of them) */ int zssoft(arg) void *arg; { - register struct zs_chanstate *cs; - register volatile struct zschan *zc; - register struct linesw *line; - register struct tty *tp; - register int get, n, c, cc, unit, s; - int retval = 0; + register struct zsc_softc *zsc; + register int s, unit; - for (cs = zslist; cs != NULL; cs = cs->cs_next) { - get = cs->cs_rbget; -again: - n = cs->cs_rbput; /* atomic */ - if (get == n) /* nothing more on this line */ + /* This is not the only ISR on this IPL. */ + if (zssoftpending == 0) + return (0); + + zssoftpending = 0; + + /* Make sure we call the tty layer at spltty. */ + s = spltty(); + for (unit = 0; unit < zsc_cd.cd_ndevs; unit++) { + zsc = zsc_cd.cd_devs[unit]; + if (zsc == NULL) continue; - retval = 1; - unit = cs->cs_unit; /* set up to handle interrupts */ - zc = cs->cs_zc; - tp = cs->cs_ttyp; - line = &linesw[tp->t_line]; - /* - * Compute the number of interrupts in the receive ring. - * If the count is overlarge, we lost some events, and - * must advance to the first valid one. It may get - * overwritten if more data are arriving, but this is - * too expensive to check and gains nothing (we already - * lost out; all we can do at this point is trade one - * kind of loss for another). - */ - n -= get; - if (n > ZLRB_RING_SIZE) { - zsoverrun(unit, &cs->cs_rotime, "ring"); - get += n - ZLRB_RING_SIZE; - n = ZLRB_RING_SIZE; - } - while (--n >= 0) { - /* race to keep ahead of incoming interrupts */ - c = cs->cs_rbuf[get++ & ZLRB_RING_MASK]; - switch (ZRING_TYPE(c)) { - - case ZRING_RINT: - c = ZRING_VALUE(c); - if (c & ZSRR1_DO) - zsoverrun(unit, &cs->cs_fotime, "fifo"); - cc = c >> 8; - if (c & ZSRR1_FE) - cc |= TTY_FE; - if (c & ZSRR1_PE) - cc |= TTY_PE; - /* - * this should be done through - * bstreams XXX gag choke - */ - else if (unit == ZS_MOUSE) - ms_rint(cc); - else - line->l_rint(cc, tp); - break; - - case ZRING_XINT: - /* - * Transmit done: change registers and resume, - * or clear BUSY. - */ - if (cs->cs_heldchange) { - s = splzs(); - c = zc->zc_csr; - ZS_DELAY(); - if ((c & ZSRR0_DCD) == 0) - cs->cs_preg[3] &= ~ZSWR3_HFC; - bcopy((caddr_t)cs->cs_preg, - (caddr_t)cs->cs_creg, 16); - zs_loadchannelregs(zc, cs->cs_creg); - splx(s); - cs->cs_heldchange = 0; - if (cs->cs_heldtbc && - (tp->t_state & TS_TTSTOP) == 0) { - cs->cs_tbc = cs->cs_heldtbc - 1; - zc->zc_data = *cs->cs_tba++; - ZS_DELAY(); - goto again; - } - } - tp->t_state &= ~TS_BUSY; - if (tp->t_state & TS_FLUSH) - tp->t_state &= ~TS_FLUSH; - else - ndflush(&tp->t_outq, - cs->cs_tba - (caddr_t)tp->t_outq.c_cf); - line->l_start(tp); - break; - - case ZRING_SINT: - /* - * Status line change. HFC bit is run in - * hardware interrupt, to avoid locking - * at splzs here. - */ - c = ZRING_VALUE(c); - if ((c ^ cs->cs_rr0) & ZSRR0_DCD) { - cc = (c & ZSRR0_DCD) != 0; - if (line->l_modem(tp, cc) == 0) - zs_modem(cs, cc); - } - cs->cs_rr0 = c; - break; - - default: - log(LOG_ERR, "zs%d%c: bad ZRING_TYPE (%x)\n", - unit >> 1, (unit & 1) + 'a', c); - break; - } - } - cs->cs_rbget = get; - goto again; + (void) zsc_intr_soft(zsc); } - return (retval); + splx(s); + return (1); +} + + +/* + * Compute the current baud rate given a ZS channel. + */ +static int +zs_get_speed(cs) + struct zs_chanstate *cs; +{ + int tconst; + + tconst = zs_read_reg(cs, 12); + tconst |= zs_read_reg(cs, 13) << 8; + return (TCONST_TO_BPS(cs->cs_brg_clk, tconst)); +} + +/* + * MD functions for setting the baud rate and control modes. + */ +int +zs_set_speed(cs, bps) + struct zs_chanstate *cs; + int bps; /* bits per second */ +{ + int tconst, real_bps; + + if (bps == 0) + return (0); + +#ifdef DIAGNOSTIC + if (cs->cs_brg_clk == 0) + panic("zs_set_speed"); +#endif + + tconst = BPS_TO_TCONST(cs->cs_brg_clk, bps); + if (tconst < 0) + return (EINVAL); + + /* Convert back to make sure we can do it. */ + real_bps = TCONST_TO_BPS(cs->cs_brg_clk, tconst); + + /* XXX - Allow some tolerance here? */ + if (real_bps != bps) + return (EINVAL); + + cs->cs_preg[12] = tconst; + cs->cs_preg[13] = tconst >> 8; + + /* Caller will stuff the pending registers. */ + return (0); } int -zsioctl(dev, cmd, data, flag, p) - dev_t dev; - u_long cmd; - caddr_t data; - int flag; - struct proc *p; -{ - int unit = ZSUNIT(dev); - struct zs_softc *zi = zs_cd.cd_devs[unit >> 1]; - register struct zs_chanstate *cs = &zi->zi_cs[unit & 1]; - register struct tty *tp = cs->cs_ttyp; - register int error, s; - - error = linesw[tp->t_line].l_ioctl(tp, cmd, data, flag, p); - if (error >= 0) - return (error); - error = ttioctl(tp, cmd, data, flag, p); - if (error >= 0) - return (error); - - switch (cmd) { - case TIOCSBRK: - s = splzs(); - cs->cs_preg[5] |= ZSWR5_BREAK; - cs->cs_creg[5] |= ZSWR5_BREAK; - ZS_WRITE(cs->cs_zc, 5, cs->cs_creg[5]); - splx(s); - break; - case TIOCCBRK: - s = splzs(); - cs->cs_preg[5] &= ~ZSWR5_BREAK; - cs->cs_creg[5] &= ~ZSWR5_BREAK; - ZS_WRITE(cs->cs_zc, 5, cs->cs_creg[5]); - splx(s); - break; - case TIOCGFLAGS: { - int bits = 0; - - if (cs->cs_softcar) - bits |= TIOCFLAG_SOFTCAR; - if (cs->cs_creg[15] & ZSWR15_DCD_IE) - bits |= TIOCFLAG_CLOCAL; - if (cs->cs_creg[3] & ZSWR3_HFC) - bits |= TIOCFLAG_CRTSCTS; - *(int *)data = bits; - break; - } - case TIOCSFLAGS: { - int userbits, driverbits = 0; - - error = suser(p->p_ucred, &p->p_acflag); - if (error != 0) - return (EPERM); - - userbits = *(int *)data; - - /* - * can have `local' or `softcar', and `rtscts' or `mdmbuf' - # defaulting to software flow control. - */ - if (userbits & TIOCFLAG_SOFTCAR && userbits & TIOCFLAG_CLOCAL) - return(EINVAL); - if (userbits & TIOCFLAG_MDMBUF) /* don't support this (yet?) */ - return(ENXIO); - - s = splzs(); - if ((userbits & TIOCFLAG_SOFTCAR) || cs->cs_consio) { - cs->cs_softcar = 1; /* turn on softcar */ - cs->cs_preg[15] &= ~ZSWR15_DCD_IE; /* turn off dcd */ - cs->cs_creg[15] &= ~ZSWR15_DCD_IE; - ZS_WRITE(cs->cs_zc, 15, cs->cs_creg[15]); - } else if (userbits & TIOCFLAG_CLOCAL) { - cs->cs_softcar = 0; /* turn off softcar */ - cs->cs_preg[15] |= ZSWR15_DCD_IE; /* turn on dcd */ - cs->cs_creg[15] |= ZSWR15_DCD_IE; - ZS_WRITE(cs->cs_zc, 15, cs->cs_creg[15]); - tp->t_termios.c_cflag |= CLOCAL; - } - if (userbits & TIOCFLAG_CRTSCTS) { - cs->cs_preg[15] |= ZSWR15_CTS_IE; - cs->cs_creg[15] |= ZSWR15_CTS_IE; - ZS_WRITE(cs->cs_zc, 15, cs->cs_creg[15]); - cs->cs_preg[3] |= ZSWR3_HFC; - cs->cs_creg[3] |= ZSWR3_HFC; - ZS_WRITE(cs->cs_zc, 3, cs->cs_creg[3]); - tp->t_termios.c_cflag |= CRTSCTS; - } else { - /* no mdmbuf, so we must want software flow control */ - cs->cs_preg[15] &= ~ZSWR15_CTS_IE; - cs->cs_creg[15] &= ~ZSWR15_CTS_IE; - ZS_WRITE(cs->cs_zc, 15, cs->cs_creg[15]); - cs->cs_preg[3] &= ~ZSWR3_HFC; - cs->cs_creg[3] &= ~ZSWR3_HFC; - ZS_WRITE(cs->cs_zc, 3, cs->cs_creg[3]); - tp->t_termios.c_cflag &= ~CRTSCTS; - } - splx(s); - break; - } - case TIOCSDTR: - zs_modem(cs, 1); - break; - case TIOCCDTR: - zs_modem(cs, 0); - break; - case TIOCMSET: - case TIOCMBIS: - case TIOCMBIC: - case TIOCMGET: - default: - return (ENOTTY); - } - return (0); -} - -/* - * Start or restart transmission. - */ -static void -zsstart(tp) - register struct tty *tp; -{ - register struct zs_chanstate *cs; - register int s, nch; - int unit = ZSUNIT(tp->t_dev); - struct zs_softc *zi = zs_cd.cd_devs[unit >> 1]; - - cs = &zi->zi_cs[unit & 1]; - s = spltty(); - - /* - * If currently active or delaying, no need to do anything. - */ - if (tp->t_state & (TS_TIMEOUT | TS_BUSY | TS_TTSTOP)) - goto out; - - /* - * If there are sleepers, and output has drained below low - * water mark, awaken. - */ - if (tp->t_outq.c_cc <= tp->t_lowat) { - if (tp->t_state & TS_ASLEEP) { - tp->t_state &= ~TS_ASLEEP; - wakeup((caddr_t)&tp->t_outq); - } - selwakeup(&tp->t_wsel); - } - - nch = ndqb(&tp->t_outq, 0); /* XXX */ - if (nch) { - register char *p = tp->t_outq.c_cf; - - /* mark busy, enable tx done interrupts, & send first byte */ - tp->t_state |= TS_BUSY; - (void) splzs(); - cs->cs_preg[1] |= ZSWR1_TIE; - cs->cs_creg[1] |= ZSWR1_TIE; - ZS_WRITE(cs->cs_zc, 1, cs->cs_creg[1]); - cs->cs_zc->zc_data = *p; - ZS_DELAY(); - cs->cs_tba = p + 1; - cs->cs_tbc = nch - 1; - } else { - /* - * Nothing to send, turn off transmit done interrupts. - * This is useful if something is doing polled output. - */ - (void) splzs(); - cs->cs_preg[1] &= ~ZSWR1_TIE; - cs->cs_creg[1] &= ~ZSWR1_TIE; - ZS_WRITE(cs->cs_zc, 1, cs->cs_creg[1]); - } -out: - splx(s); -} - -/* - * Stop output, e.g., for ^S or output flush. - */ -void -zsstop(tp, flag) - register struct tty *tp; - int flag; -{ - register struct zs_chanstate *cs; - register int s, unit = ZSUNIT(tp->t_dev); - struct zs_softc *zi = zs_cd.cd_devs[unit >> 1]; - - cs = &zi->zi_cs[unit & 1]; - s = splzs(); - if (tp->t_state & TS_BUSY) { - /* - * Device is transmitting; must stop it. - */ - cs->cs_tbc = 0; - if ((tp->t_state & TS_TTSTOP) == 0) - tp->t_state |= TS_FLUSH; - } - splx(s); -} - -/* - * Set ZS tty parameters from termios. - * - * This routine makes use of the fact that only registers - * 1, 3, 4, 5, 9, 10, 11, 12, 13, 14, and 15 are written. - */ -static int -zsparam(tp, t) - register struct tty *tp; - register struct termios *t; -{ - int unit = ZSUNIT(tp->t_dev); - struct zs_softc *zi = zs_cd.cd_devs[unit >> 1]; - register struct zs_chanstate *cs = &zi->zi_cs[unit & 1]; - register int tmp, tmp5, cflag, s; - - /* - * Because PCLK is only run at 5 MHz, the fastest we - * can go is 51200 baud (this corresponds to TC=1). - * This is somewhat unfortunate as there is no real - * reason we should not be able to handle higher rates. - */ - tmp = t->c_ospeed; - if (tmp < 0 || (t->c_ispeed && t->c_ispeed != tmp)) - return (EINVAL); - if (tmp == 0) { - /* stty 0 => drop DTR and RTS */ - zs_modem(cs, 0); - return (0); - } - tmp = BPS_TO_TCONST(PCLK / 16, tmp); - if (tmp < 2) - return (EINVAL); - - cflag = t->c_cflag; - tp->t_ispeed = tp->t_ospeed = TCONST_TO_BPS(PCLK / 16, tmp); - tp->t_cflag = cflag; - - /* - * Block interrupts so that state will not - * be altered until we are done setting it up. - */ - s = splzs(); - cs->cs_preg[12] = tmp; - cs->cs_preg[13] = tmp >> 8; - cs->cs_preg[1] = ZSWR1_RIE | ZSWR1_TIE | ZSWR1_SIE; - switch (cflag & CSIZE) { - case CS5: - tmp = ZSWR3_RX_5; - tmp5 = ZSWR5_TX_5; - break; - case CS6: - tmp = ZSWR3_RX_6; - tmp5 = ZSWR5_TX_6; - break; - case CS7: - tmp = ZSWR3_RX_7; - tmp5 = ZSWR5_TX_7; - break; - case CS8: - default: - tmp = ZSWR3_RX_8; - tmp5 = ZSWR5_TX_8; - break; - } - - /* - * Output hardware flow control on the chip is horrendous: if - * carrier detect drops, the receiver is disabled. Hence we - * can only do this when the carrier is on. - */ - tmp |= ZSWR3_RX_ENABLE; - if (cflag & CCTS_OFLOW) { - if (cs->cs_zc->zc_csr & ZSRR0_DCD) - tmp |= ZSWR3_HFC; - ZS_DELAY(); - } - cs->cs_preg[3] = tmp; - cs->cs_preg[5] = tmp5 | ZSWR5_TX_ENABLE | ZSWR5_DTR | ZSWR5_RTS; - - tmp = ZSWR4_CLK_X16 | (cflag & CSTOPB ? ZSWR4_TWOSB : ZSWR4_ONESB); - if ((cflag & PARODD) == 0) - tmp |= ZSWR4_EVENP; - if (cflag & PARENB) - tmp |= ZSWR4_PARENB; - cs->cs_preg[4] = tmp; - cs->cs_preg[9] = ZSWR9_MASTER_IE /*| ZSWR9_NO_VECTOR*/; - cs->cs_preg[10] = ZSWR10_NRZ; - cs->cs_preg[11] = ZSWR11_TXCLK_BAUD | ZSWR11_RXCLK_BAUD; - cs->cs_preg[14] = ZSWR14_BAUD_FROM_PCLK | ZSWR14_BAUD_ENA; - cs->cs_preg[15] = ZSWR15_BREAK_IE | ZSWR15_DCD_IE; - - /* - * If nothing is being transmitted, set up new current values, - * else mark them as pending. - */ - if (cs->cs_heldchange == 0) { - if (cs->cs_ttyp->t_state & TS_BUSY) { - cs->cs_heldtbc = cs->cs_tbc; - cs->cs_tbc = 0; - cs->cs_heldchange = 1; - } else { - bcopy((caddr_t)cs->cs_preg, (caddr_t)cs->cs_creg, 16); - zs_loadchannelregs(cs->cs_zc, cs->cs_creg); - } - } - splx(s); - return (0); -} - -/* - * Raise or lower modem control (DTR/RTS) signals. If a character is - * in transmission, the change is deferred. - */ -static void -zs_modem(cs, onoff) +zs_set_modes(cs, cflag) struct zs_chanstate *cs; - int onoff; + int cflag; /* bits per second */ { - int s, bis, and; - - if (onoff) { - bis = ZSWR5_DTR | ZSWR5_RTS; - and = ~0; - } else { - bis = 0; - and = ~(ZSWR5_DTR | ZSWR5_RTS); - } - s = splzs(); - cs->cs_preg[5] = (cs->cs_preg[5] | bis) & and; - if (cs->cs_heldchange == 0) { - if (cs->cs_ttyp->t_state & TS_BUSY) { - cs->cs_heldtbc = cs->cs_tbc; - cs->cs_tbc = 0; - cs->cs_heldchange = 1; - } else { - cs->cs_creg[5] = (cs->cs_creg[5] | bis) & and; - ZS_WRITE(cs->cs_zc, 5, cs->cs_creg[5]); - } - } - splx(s); -} - -/* - * Hardware flow (RTS) control. - */ -static int -zshwiflow(tp, flag) - struct tty *tp; - int flag; -{ - int unit = ZSUNIT(tp->t_dev); - struct zs_softc *zi = zs_cd.cd_devs[unit >> 1]; - register struct zs_chanstate *cs = &zi->zi_cs[unit & 1]; int s; -#if 0 - printf ("zshwiflow %d\n", flag); -#endif + /* + * Output hardware flow control on the chip is horrendous: + * if carrier detect drops, the receiver is disabled, and if + * CTS drops, the transmitter is stoped IN MID CHARACTER! + * Therefore, NEVER set the HFC bit, and instead use the + * status interrupt to detect CTS changes. + */ s = splzs(); - if (flag) { - cs->cs_preg[5] &= ~ZSWR5_RTS; - cs->cs_creg[5] &= ~ZSWR5_RTS; - ZS_WRITE(cs->cs_zc, 5, cs->cs_creg[5]); + if ((cflag & (CLOCAL | MDMBUF)) != 0) + cs->cs_rr0_dcd = 0; + else + cs->cs_rr0_dcd = ZSRR0_DCD; + if ((cflag & CRTSCTS) != 0) { + cs->cs_wr5_dtr = ZSWR5_DTR; + cs->cs_wr5_rts = ZSWR5_RTS; + cs->cs_rr0_cts = ZSRR0_CTS; + } else if ((cflag & MDMBUF) != 0) { + cs->cs_wr5_dtr = 0; + cs->cs_wr5_rts = ZSWR5_DTR; + cs->cs_rr0_cts = ZSRR0_DCD; } else { - cs->cs_preg[5] |= ZSWR5_RTS; - cs->cs_creg[5] |= ZSWR5_RTS; - ZS_WRITE(cs->cs_zc, 5, cs->cs_creg[5]); + cs->cs_wr5_dtr = ZSWR5_DTR | ZSWR5_RTS; + cs->cs_wr5_rts = 0; + cs->cs_rr0_cts = 0; } splx(s); - return 1; + + /* Caller will stuff the pending registers. */ + return (0); } + /* - * Write the given register set to the given zs channel in the proper order. - * The channel must not be transmitting at the time. The receiver will - * be disabled for the time it takes to write all the registers. + * Read or write the chip with suitable delays. */ -static void -zs_loadchannelregs(zc, reg) - volatile struct zschan *zc; - u_char *reg; -{ - int i; - zc->zc_csr = ZSM_RESET_ERR; /* reset error condition */ +u_char +zs_read_reg(cs, reg) + struct zs_chanstate *cs; + u_char reg; +{ + u_char val; + + *cs->cs_reg_csr = reg; ZS_DELAY(); - i = zc->zc_data; /* drain fifo */ + val = *cs->cs_reg_csr; ZS_DELAY(); - i = zc->zc_data; - ZS_DELAY(); - i = zc->zc_data; - ZS_DELAY(); - ZS_WRITE(zc, 4, reg[4]); - ZS_WRITE(zc, 10, reg[10]); - ZS_WRITE(zc, 3, reg[3] & ~ZSWR3_RX_ENABLE); - ZS_WRITE(zc, 5, reg[5] & ~ZSWR5_TX_ENABLE); - ZS_WRITE(zc, 1, reg[1]); - ZS_WRITE(zc, 9, reg[9]); - ZS_WRITE(zc, 11, reg[11]); - ZS_WRITE(zc, 12, reg[12]); - ZS_WRITE(zc, 13, reg[13]); - ZS_WRITE(zc, 14, reg[14]); - ZS_WRITE(zc, 15, reg[15]); - ZS_WRITE(zc, 3, reg[3]); - ZS_WRITE(zc, 5, reg[5]); + return val; } -#ifdef x68k void -zs_msmodem(onoff) - int onoff; +zs_write_reg(cs, reg, val) + struct zs_chanstate *cs; + u_char reg, val; { - if (zsms != NULL) { - zs_modem(zsms, onoff); - while(!(mfp.tsr & MFP_TSR_BE)) - /* XXX wait */ ; - mfp.udr = 0x40 | (onoff ? 0 : 1); - } -} -#endif - -#ifdef KGDB -/* - * Get a character from the given kgdb channel. Called at splhigh(). - */ -static int -zs_kgdb_getc(arg) - void *arg; -{ - register volatile struct zschan *zc = (volatile struct zschan *)arg; - - while ((zc->zc_csr & ZSRR0_RX_READY) == 0) - ZS_DELAY(); - return (zc->zc_data); + *cs->cs_reg_csr = reg; + ZS_DELAY(); + *cs->cs_reg_csr = val; + ZS_DELAY(); } -/* - * Put a character to the given kgdb channel. Called at splhigh(). - */ -static void -zs_kgdb_putc(arg, c) - void *arg; - int c; +u_char zs_read_csr(cs) + struct zs_chanstate *cs; { - register volatile struct zschan *zc = (volatile struct zschan *)arg; + register u_char val; - while ((zc->zc_csr & ZSRR0_TX_READY) == 0) - ZS_DELAY(); - zc->zc_data = c; + val = *cs->cs_reg_csr; + ZS_DELAY(); + return val; +} + +void zs_write_csr(cs, val) + struct zs_chanstate *cs; + u_char val; +{ + *cs->cs_reg_csr = val; + ZS_DELAY(); +} + +u_char zs_read_data(cs) + struct zs_chanstate *cs; +{ + register u_char val; + + val = *cs->cs_reg_data; + ZS_DELAY(); + return val; +} + +void zs_write_data(cs, val) + struct zs_chanstate *cs; + u_char val; +{ + *cs->cs_reg_data = val; ZS_DELAY(); } /* - * Set up for kgdb; called at boot time before configuration. - * KGDB interrupts will be enabled later when zs0 is configured. + * Handle user request to enter kernel debugger. */ void -zs_kgdb_init() +zs_abort(cs) + struct zs_chanstate *cs; { - volatile struct zsdevice *addr; - volatile struct zschan *zc; - int unit, zs; + int rr0; - if (major(kgdb_dev) != ZSMAJOR) - return; - unit = ZSUNIT(kgdb_dev); - zs = unit >> 1; - if ((addr = zsaddr[zs]) == NULL) - addr = zsaddr[zs] = findzs(zs); - unit &= 1; - zc = unit == 0 ? &addr->zs_chan[ZS_CHAN_A] : &addr->zs_chan[ZS_CHAN_B]; - zs_kgdb_savedspeed = zs_getspeed(zc); - printf("zs_kgdb_init: attaching zs%d%c at %d baud\n", - zs, unit + 'a', kgdb_rate); - zs_reset(zc, 1, kgdb_rate); - kgdb_attach(zs_kgdb_getc, zs_kgdb_putc, (void *)zc); -} -#endif /* KGDB */ + /* Wait for end of break to avoid PROM abort. */ + /* XXX - Limit the wait? */ + do { + rr0 = *cs->cs_reg_csr; + ZS_DELAY(); + } while (rr0 & ZSRR0_BREAK); + +#ifdef DDB + Debugger(); +#else + printf ("BREAK!!\n"); #endif +} diff --git a/sys/arch/x68k/dev/zsvar.h b/sys/arch/x68k/dev/zsvar.h deleted file mode 100644 index 9dcf17c3fee0..000000000000 --- a/sys/arch/x68k/dev/zsvar.h +++ /dev/null @@ -1,152 +0,0 @@ -/* - * Copyright (c) 1994 Gordon W. Ross - * 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. - * - * @(#)zsvar.h 8.1 (Berkeley) 6/11/93 - * - * $NetBSD: zsvar.h,v 1.2 1997/10/13 14:22:58 lukem Exp $ - */ - -/* - * Software state, per zs channel. - * - * The zs chip has insufficient buffering, so we provide a software - * buffer using a two-level interrupt scheme. The hardware (high priority) - * interrupt simply grabs the `cause' of the interrupt and stuffs it into - * a ring buffer. It then schedules a software interrupt; the latter - * empties the ring as fast as it can, hoping to avoid overflow. - * - * Interrupts can happen because of: - * - received data; - * - transmit pseudo-DMA done; and - * - status change. - * These are all stored together in the (single) ring. The size of the - * ring is a power of two, to make % operations fast. Since we need two - * bits to distinguish the interrupt type, and up to 16 for the received - * data plus RR1 status, we use 32 bits per ring entry. - * - * When the value is a character + RR1 status, the character is in the - * upper 8 bits of the RR1 status. - */ -#define ZLRB_RING_SIZE 16384 /* ZS line ring buffer size */ -#define ZLRB_RING_MASK 16383 /* mask for same */ - -/* 0 is reserved (means "no interrupt") */ -#define ZRING_RINT 1 /* receive data interrupt */ -#define ZRING_XINT 2 /* transmit done interrupt */ -#define ZRING_SINT 3 /* status change interrupt */ - -#define ZRING_TYPE(x) ((x) & 3) -#define ZRING_VALUE(x) ((x) >> 8) -#define ZRING_MAKE(t, v) ((t) | (v) << 8) - -struct zs_chanstate { - struct zs_chanstate *cs_next; /* linked list for zshard() */ - volatile struct zschan *cs_zc; /* points to hardware regs */ - int cs_unit; /* unit number */ - struct tty *cs_ttyp; /* ### */ - - /* - * We must keep a copy of the write registers as they are - * mostly write-only and we sometimes need to set and clear - * individual bits (e.g., in WR3). Not all of these are - * needed but 16 bytes is cheap and this makes the addressing - * simpler. Unfortunately, we can only write to some registers - * when the chip is not actually transmitting, so whenever - * we are expecting a `transmit done' interrupt the preg array - * is allowed to `get ahead' of the current values. In a - * few places we must change the current value of a register, - * rather than (or in addition to) the pending value; for these - * cs_creg[] contains the current value. - */ - u_char cs_creg[16]; /* current values */ - u_char cs_preg[16]; /* pending values */ - u_char cs_heldchange; /* change pending (creg != preg) */ - u_char cs_rr0; /* last rr0 processed */ - - /* pure software data, per channel */ - char cs_softcar; /* software carrier */ - char cs_conk; /* is console keyboard, decode L1-A */ - char cs_brkabort; /* abort (as if via L1-A) on BREAK */ - char cs_kgdb; /* enter debugger on frame char */ - char cs_consio; /* port does /dev/console I/O */ - char cs_xxx; /* (spare) */ - int cs_speed; /* default baud rate (from ROM) */ - - /* - * The transmit byte count and address are used for pseudo-DMA - * output in the hardware interrupt code. PDMA can be suspended - * to get pending changes done; heldtbc is used for this. It can - * also be stopped for ^S; this sets TS_TTSTOP in tp->t_state. - */ - int cs_tbc; /* transmit byte count */ - caddr_t cs_tba; /* transmit buffer address */ - int cs_heldtbc; /* held tbc while xmission stopped */ - - /* - * Printing an overrun error message often takes long enough to - * cause another overrun, so we only print one per second. - */ - long cs_rotime; /* time of last ring overrun */ - long cs_fotime; /* time of last fifo overrun */ - - /* - * The ring buffer. - */ - u_int cs_rbget; /* ring buffer `get' index */ - volatile u_int cs_rbput; /* ring buffer `put' index */ - int cs_rbuf[ZLRB_RING_SIZE];/* type, value pairs */ -}; - -/* - * N.B.: the keyboard is channel 1, the mouse channel 0; ttyb is 1, ttya - * is 0. In other words, the things are BACKWARDS. - */ -#define ZS_CHAN_A 1 -#define ZS_CHAN_B 0 - -/* - * Macros to read and write individual registers (except 0) in a channel. - * The ZS chip requires a 1.6 uSec. recovery time between accesses. - */ -#define ZS_READ(c, r) zs_read(c, r) -#define ZS_WRITE(c, r, v) zs_write(c, r, v) -#define ZS_DELAY() DELAY(2)/*asm("nop")*/ diff --git a/sys/arch/x68k/x68k/conf.c b/sys/arch/x68k/x68k/conf.c index 053810e790ce..7f62c2d78d8d 100644 --- a/sys/arch/x68k/x68k/conf.c +++ b/sys/arch/x68k/x68k/conf.c @@ -1,4 +1,4 @@ -/* $NetBSD: conf.c,v 1.13 1997/10/15 23:39:42 thorpej Exp $ */ +/* $NetBSD: conf.c,v 1.14 1998/08/05 16:08:37 minoura Exp $ */ /*- * Copyright (c) 1991 The Regents of the University of California. @@ -156,6 +156,7 @@ cdev_decl(md); cdev_decl(st); cdev_decl(fd); cdev_decl(kbd); +#include "ms.h" cdev_decl(ms); dev_decl(filedesc,open); #include "audio.h" @@ -169,7 +170,7 @@ cdev_decl(tun); #include "xcom.h" cdev_decl(com); -#include "zs.h" +#include "zstty.h" cdev_decl(zs); #include "pow.h" cdev_decl(pow); @@ -196,10 +197,14 @@ struct cdevsw cdevsw[] = cdev_disk_init(NCD,cd), /* 9: SCSI cdrom */ cdev_grf_init(NGRF,grf), /* 10: frame buffer */ cdev_par_init(NPAR,par), /* 11: parallel interface */ - cdev_tty_init(NZS,zs), /* 12: zs serial */ + cdev_tty_init(NZSTTY,zs), /* 12: zs serial */ cdev_ite_init(NITE,ite), /* 13: console terminal emulator */ cdev_gen_init(1,kbd), /* 14: /dev/kbd */ +#if NMS > 0 cdev_gen_init(1,ms), /* 15: /dev/mouse */ +#else + cdev_notdef(), +#endif cdev_tty_init(NXCOM,com), /* 16: serial port */ cdev_gen_init(NAUDIO,audio), /* 17: /dev/adpcm /dev/pcm /dev/audio */ cdev_disk_init(NFD,fd), /* 18: floppy disk */ diff --git a/sys/arch/x68k/x68k/iodevice.h b/sys/arch/x68k/x68k/iodevice.h index bf2a4d43b863..767191bf923b 100644 --- a/sys/arch/x68k/x68k/iodevice.h +++ b/sys/arch/x68k/x68k/iodevice.h @@ -1,4 +1,4 @@ -/* $NetBSD: iodevice.h,v 1.4 1997/10/11 11:15:00 oki Exp $ */ +/* $NetBSD: iodevice.h,v 1.5 1998/08/05 16:08:37 minoura Exp $ */ /* * Copyright (c) 1993, 1994, 1995 Masaru Oki @@ -263,7 +263,9 @@ struct zschan { }; struct zsdevice { - struct zschan zs_chan[2]; /* channel A = 1, B = 0 : 8 bytes */ + /* Yes, they are backwards. */ + struct zschan zs_chan_b; + struct zschan zs_chan_a; char pad4; unsigned char bstat; /* external only : 2 bytes */ char pad[6]; /* --- : 6 bytes */ }; diff --git a/sys/arch/x68k/x68k/locore.s b/sys/arch/x68k/x68k/locore.s index 8dbbb41ca10b..d7072f6f9b92 100644 --- a/sys/arch/x68k/x68k/locore.s +++ b/sys/arch/x68k/x68k/locore.s @@ -1,4 +1,4 @@ -/* $NetBSD: locore.s,v 1.30 1998/07/04 22:18:47 jonathan Exp $ */ +/* $NetBSD: locore.s,v 1.31 1998/08/05 16:08:38 minoura Exp $ */ /* * Copyright (c) 1988 University of Utah. @@ -525,8 +525,8 @@ ENTRY_NOPROFILE(spurintr) /* level 0 */ rte | XXX mfpcure (x680x0 hardware bug) _zstrap: -#include "zs.h" -#if NZS > 0 +#include "zsc.h" +#if NZSC > 0 INTERRUPT_SAVEREG movw sp@(22),sp@- | push exception vector info movw sr,d0 @@ -811,9 +811,11 @@ _timertrap: lea sp@(16),a1 | a1 = &clockframe movl a1,sp@- jbsr _hardclock | hardclock(&frame) - movl #1,sp@ - jbsr _ms_modem | ms_modem(1) addql #4,sp +#include "ms.h" +#if NMS > 0 + jbsr _ms_modem +#endif #if defined(UVM) addql #1,_C_LABEL(uvmexp)+UVMEXP_INTRS | chalk up another interrupt #else diff --git a/sys/arch/x68k/x68k/machdep.c b/sys/arch/x68k/x68k/machdep.c index ee21ed3d5176..c937448803be 100644 --- a/sys/arch/x68k/x68k/machdep.c +++ b/sys/arch/x68k/x68k/machdep.c @@ -1,4 +1,4 @@ -/* $NetBSD: machdep.c,v 1.40 1998/08/05 14:40:20 minoura Exp $ */ +/* $NetBSD: machdep.c,v 1.41 1998/08/05 16:08:38 minoura Exp $ */ /* * Copyright (c) 1988 University of Utah. @@ -239,7 +239,7 @@ consinit() #else uvm_page_physload(atop(avail_start), atop(avail_end), atop(avail_start), atop(avail_end), - VM_FREELIST_DEFAULT); + VM_FREELIST_DEFAILT); #endif #else /* not UVM */ #ifdef MACHINE_NONCONTIG diff --git a/sys/arch/x68k/x68k/trap.c b/sys/arch/x68k/x68k/trap.c index 3aa969f4f736..55bb88dc39b0 100644 --- a/sys/arch/x68k/x68k/trap.c +++ b/sys/arch/x68k/x68k/trap.c @@ -1,4 +1,4 @@ -/* $NetBSD: trap.c,v 1.21 1998/07/04 22:18:47 jonathan Exp $ */ +/* $NetBSD: trap.c,v 1.22 1998/08/05 16:08:38 minoura Exp $ */ /* * Copyright (c) 1988 University of Utah. @@ -557,8 +557,8 @@ trap(type, code, v, frame) #else cnt.v_soft++; #endif -#include "zs.h" -#if NZS > 0 +#include "zsc.h" +#if NZSC > 0 zssoft(0); #endif } diff --git a/sys/arch/x68k/x68k/x68k_init.c b/sys/arch/x68k/x68k/x68k_init.c index bb97b09b4887..5ea79e2151cd 100644 --- a/sys/arch/x68k/x68k/x68k_init.c +++ b/sys/arch/x68k/x68k/x68k_init.c @@ -1,4 +1,4 @@ -/* $NetBSD: x68k_init.c,v 1.4 1997/10/11 11:13:54 oki Exp $ */ +/* $NetBSD: x68k_init.c,v 1.5 1998/08/05 16:08:39 minoura Exp $ */ /* * Copyright (c) 1996 Masaru Oki. @@ -33,7 +33,7 @@ #include #include -#define zschan IODEVbase->io_inscc.zs_chan +#define zsdev IODEVbase->io_inscc volatile struct IODEVICE *IODEVbase = (volatile struct IODEVICE *) PHYS_IODEV; @@ -49,15 +49,15 @@ intr_reset() ioctlr.intr = 0; /* Internal RS-232C port */ - zschan[1].zc_csr = 1; + zsdev.zs_chan_a.zc_csr = 1; asm("nop"); - zschan[1].zc_csr = 0; + zsdev.zs_chan_a.zc_csr = 0; asm("nop"); /* mouse */ - zschan[0].zc_csr = 1; + zsdev.zs_chan_b.zc_csr = 1; asm("nop"); - zschan[0].zc_csr = 0; + zsdev.zs_chan_b.zc_csr = 0; asm("nop"); while(!(mfp.tsr & MFP_TSR_BE)) ;