summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--sys/arch/hp300/dev/ct.c31
-rw-r--r--sys/arch/hp300/hp300/locore.s105
-rw-r--r--sys/arch/hp300/hp300/machdep.c20
-rw-r--r--sys/arch/sun3/conf/files.sun339
-rw-r--r--sys/arch/sun3/conf/std.sun311
-rw-r--r--sys/arch/sun3/dev/event.c171
-rw-r--r--sys/arch/sun3/dev/kbd.c808
-rw-r--r--sys/arch/sun3/dev/kd.c286
-rw-r--r--sys/arch/sun3/dev/ms.c358
-rw-r--r--sys/arch/sun3/dev/zs.c1784
-rw-r--r--sys/arch/sun3/dev/zs_kgdb.c277
-rw-r--r--sys/arch/sun3/dev/zsvar.h152
-rw-r--r--sys/arch/sun3/include/kbd.h8
-rw-r--r--sys/arch/sun3/include/kbio.h34
-rw-r--r--sys/arch/sun3/include/z8530var.h (renamed from sys/arch/sun3/dev/event_var.h)61
-rw-r--r--sys/arch/sun3/sun3/conf.c41
16 files changed, 932 insertions, 3254 deletions
diff --git a/sys/arch/hp300/dev/ct.c b/sys/arch/hp300/dev/ct.c
index e3ad6174909..06e30357198 100644
--- a/sys/arch/hp300/dev/ct.c
+++ b/sys/arch/hp300/dev/ct.c
@@ -1,4 +1,4 @@
-/* $NetBSD: ct.c,v 1.13 1995/12/02 18:21:52 thorpej Exp $ */
+/* $NetBSD: ct.c,v 1.14 1996/01/23 00:28:09 scottr Exp $ */
/*
* Copyright (c) 1982, 1990, 1993
@@ -380,22 +380,22 @@ ctcommand(dev, cmd, cnt)
bp->b_un.b_addr = nbp->b_un.b_addr;
bp->b_bcount = MAXBSIZE;
}
-again:
- bp->b_flags = B_BUSY;
- if (cmd == MTBSF) {
- sc->sc_blkno = sc->sc_eofs[sc->sc_eofp];
- sc->sc_eofp--;
+
+ while (cnt-- > 0) {
+ bp->b_flags = B_BUSY;
+ if (cmd == MTBSF) {
+ sc->sc_blkno = sc->sc_eofs[sc->sc_eofp];
+ sc->sc_eofp--;
#ifdef DEBUG
- if (ctdebug & CT_BSF)
- printf("%s: backup eof pos %d blk %d\n",
- sc->sc_hd->hp_xname, sc->sc_eofp,
- sc->sc_eofs[sc->sc_eofp]);
+ if (ctdebug & CT_BSF)
+ printf("%s: backup eof pos %d blk %d\n",
+ sc->sc_hd->hp_xname, sc->sc_eofp,
+ sc->sc_eofs[sc->sc_eofp]);
#endif
+ }
+ ctstrategy(bp);
+ iowait(bp);
}
- ctstrategy(bp);
- iowait(bp);
- if (--cnt > 0)
- goto again;
bp->b_flags = 0;
sc->sc_flags &= ~CTF_CMD;
if (nbp)
@@ -444,7 +444,6 @@ ctstart(unit)
register int i;
bp = cttab[unit].b_actf;
-again:
if ((sc->sc_flags & CTF_CMD) && sc->sc_bp == bp) {
switch(sc->sc_cmd) {
@@ -804,7 +803,6 @@ ctread(dev, uio, flags)
struct uio *uio;
int flags;
{
-
return (physio(ctstrategy, NULL, dev, B_READ, minphys, uio));
}
@@ -814,7 +812,6 @@ ctwrite(dev, uio, flags)
struct uio *uio;
int flags;
{
-
/* XXX: check for hardware write-protect? */
return (physio(ctstrategy, NULL, dev, B_WRITE, minphys, uio));
}
diff --git a/sys/arch/hp300/hp300/locore.s b/sys/arch/hp300/hp300/locore.s
index 98f31668f9a..514efd22c11 100644
--- a/sys/arch/hp300/hp300/locore.s
+++ b/sys/arch/hp300/hp300/locore.s
@@ -1,6 +1,4 @@
-/* $NetBSD: locore.s,v 1.46 1995/12/11 17:09:11 thorpej Exp $ */
-
-#undef STACKCHECK /* doesn't work any more */
+/* $NetBSD: locore.s,v 1.47 1996/01/16 22:24:28 thorpej Exp $ */
/*
* Copyright (c) 1988 University of Utah.
@@ -44,19 +42,6 @@
* @(#)locore.s 8.6 (Berkeley) 5/27/94
*/
-/*
- * STACKCHECK enables two types of kernel stack checking:
- * 1. stack "overflow". On every clock interrupt we ensure that
- * the current kernel stack has not grown into the user struct
- * page, i.e. size exceeded UPAGES-1 pages.
- * 2. stack "underflow". Before every rte to user mode we ensure
- * that we will be exactly at the base of the stack after the
- * exception frame has been popped.
- * Both checks are performed at splclock since they operate on the
- * global temporary stack.
- */
-/* #define STACKCHECK */
-
#include "assym.s"
#include <hp300/hp300/vectors.s>
@@ -417,11 +402,7 @@ Ltrap1:
movl a0,usp | user SP
moveml sp@+,#0x7FFF | restore most registers
addql #8,sp | pop SP and stack adjust
-#ifdef STACKCHECK
- jra Ldorte
-#else
rte
-#endif
/*
* Routines for traps 1 and 2. The meaning of the two traps depends
@@ -607,26 +588,6 @@ Lnotdma:
jra rei
_lev6intr:
-#ifdef STACKCHECK
- .globl _panicstr,_badkstack
- cmpl #_kstack+NBPG,sp | are we still in stack page?
- jcc Lstackok | yes, continue normally
- tstl _curproc | if !curproc could have switch_exited,
- jeq Lstackok | might be on tmpstk
- tstl _panicstr | have we paniced?
- jne Lstackok | yes, do not re-panic
- movl sp@(4),tmpstk-4 | no, copy common
- movl sp@,tmpstk-8 | frame info
- movl sp,tmpstk-16 | no, save original SP
- lea tmpstk-16,sp | switch to tmpstk
- moveml #0xFFFE,sp@- | push remaining registers
- movl #1,sp@- | is an overflow
- jbsr _badkstack | badkstack(1, frame)
- addql #4,sp
- moveml sp@+,#0x7FFF | restore most registers
- movl sp@,sp | and SP
-Lstackok:
-#endif
moveml #0xC0C0,sp@- | save scratch registers
CLKADDR(a0)
movb a0@(CLKSR),d0 | read clock status
@@ -725,10 +686,6 @@ _lev7intr:
.globl _astpending
.globl rei
rei:
-#ifdef STACKCHECK
- tstl _panicstr | have we paniced?
- jne Ldorte1 | yes, do not make matters worse
-#endif
tstl _astpending | AST pending?
jeq Lchksir | no, go check for SIR
Lrei1:
@@ -751,11 +708,7 @@ Lrei2:
jne Laststkadj | yes, go to it
moveml sp@+,#0x7FFF | no, restore most user regs
addql #8,sp | toss SP and stack adjust
-#ifdef STACKCHECK
- jra Ldorte
-#else
rte | and do real RTE
-#endif
Laststkadj:
lea sp@(FR_HW),a1 | pointer to HW frame
addql #8,a1 | source pointer
@@ -766,11 +719,7 @@ Laststkadj:
movl a0,sp@(FR_SP) | new SSP
moveml sp@+,#0x7FFF | restore user registers
movl sp@,sp | and our SP
-#ifdef STACKCHECK
- jra Ldorte
-#else
rte | and do real RTE
-#endif
Lchksir:
tstb _ssir | SIR pending?
jeq Ldorte | no, all done
@@ -797,64 +746,12 @@ Lsir1:
movl a0,usp | user SP
moveml sp@+,#0x7FFF | and all remaining registers
addql #8,sp | pop SP and stack adjust
-#ifdef STACKCHECK
- jra Ldorte
-#else
rte
-#endif
Lnosir:
movl sp@+,d0 | restore scratch register
Ldorte:
-#ifdef STACKCHECK
- movw #SPL6,sr | avoid trouble
- btst #5,sp@ | are we returning to user mode?
- jne Ldorte1 | no, skip it
- movl a6,tmpstk-20
- movl d0,tmpstk-76
- moveq #0,d0
- movb sp@(6),d0 | get format/vector
- lsrl #3,d0 | convert to index
- lea _exframesize,a6 | into exframesize
- addl d0,a6 | to get pointer to correct entry
- movw a6@,d0 | get size for this frame
- addql #8,d0 | adjust for unaccounted for bytes
- lea _kstackatbase,a6 | desired stack base
- subl d0,a6 | - frame size == our stack
- cmpl a6,sp | are we where we think?
- jeq Ldorte2 | yes, skip it
- lea tmpstk,a6 | will be using tmpstk
- movl sp@(4),a6@- | copy common
- movl sp@,a6@- | frame info
- clrl a6@-
- movl sp,a6@- | save sp
- subql #4,a6 | skip over already saved a6
- moveml #0x7FFC,a6@- | push remaining regs (d0/a6/a7 done)
- lea a6@(-4),sp | switch to tmpstk (skip saved d0)
- clrl sp@- | is an underflow
- jbsr _badkstack | badkstack(0, frame)
- addql #4,sp
- moveml sp@+,#0x7FFF | restore most registers
- movl sp@,sp | and SP
- rte
-Ldorte2:
- movl tmpstk-76,d0
- movl tmpstk-20,a6
-Ldorte1:
-#endif
rte | real return
-#ifdef STACKCHECK
-/*
- * Kernel access to the current processes kernel stack is via a fixed
- * virtual address. It is at the same address as in the users VA space.
- */
- .data
- .set _kstack,USRSTACK
- .set _kstackatbase,USRSTACK+USPACE-4
- .globl _kstackatbase
- .globl _kstack
-#endif
-
#define RELOC(var, ar) \
lea var,ar; \
addl a5,ar
diff --git a/sys/arch/hp300/hp300/machdep.c b/sys/arch/hp300/hp300/machdep.c
index bd0aa9fbec8..df2eed1a657 100644
--- a/sys/arch/hp300/hp300/machdep.c
+++ b/sys/arch/hp300/hp300/machdep.c
@@ -1,4 +1,4 @@
-/* $NetBSD: machdep.c,v 1.55 1996/01/04 22:21:51 jtc Exp $ */
+/* $NetBSD: machdep.c,v 1.56 1996/01/16 22:24:33 thorpej Exp $ */
/*
* Copyright (c) 1988 University of Utah.
@@ -1685,24 +1685,6 @@ hexstr(val, len)
return(nbuf);
}
-#ifdef STACKCHECK
-char oflowmsg[] = "k-stack overflow";
-char uflowmsg[] = "k-stack underflow";
-
-badkstack(oflow, fr)
- int oflow;
- struct frame fr;
-{
- extern char kstackatbase[];
-
- printf("%s: sp should be %x\n",
- oflow ? oflowmsg : uflowmsg,
- kstackatbase - (exframesize[fr.f_format] + 8));
- regdump(&fr, 0);
- panic(oflow ? oflowmsg : uflowmsg);
-}
-#endif
-
/*
* cpu_exec_aout_makecmds():
* cpu-dependent a.out format hook for execve().
diff --git a/sys/arch/sun3/conf/files.sun3 b/sys/arch/sun3/conf/files.sun3
index 152485f630b..3a78a19496d 100644
--- a/sys/arch/sun3/conf/files.sun3
+++ b/sys/arch/sun3/conf/files.sun3
@@ -1,4 +1,4 @@
-# $NetBSD: files.sun3,v 1.16 1996/01/01 22:48:55 thorpej Exp $
+# $NetBSD: files.sun3,v 1.17 1996/01/24 22:39:48 gwr Exp $
#
# sun3-specific configuration info
@@ -32,7 +32,6 @@ file arch/sun3/sun3/vm_machdep.c
file arch/m68k/fpe/fpu_emulate.c fpu_emulate
file arch/m68k/m68k/copy.s
file dev/cons.c
-file dev/cninit.c
# Declare our "catch-all" root node.
device mainbus at root {}
@@ -63,11 +62,6 @@ file arch/sun3/dev/obmem.c obmem
file arch/sun3/dev/vme.c vmes vmel
#
-# Sun-compatible Frame Buffers (?)
-#
-define sunfb {}
-
-#
# Machine-independent SCSI drivers
#
include "../../../scsi/files.scsi"
@@ -75,8 +69,6 @@ include "../../../scsi/files.scsi"
#
# On-Board I/O (OBIO)
#
-device zs at obio: tty
-file arch/sun3/dev/zs.c zs needs-count
device eeprom at obio
file arch/sun3/dev/eeprom.c eeprom
@@ -99,6 +91,12 @@ device ncr_si at obio, vmes: scsi, ncr5380sbc
file arch/sun3/dev/ncr_si.c ncr_si
#
+# Sun-compatible Frame Buffers (?)
+#
+define sunfb
+file arch/sun3/dev/fb.c sunfb
+
+#
# On-Board MEMory (OBMEM)
#
device bwtwo at obmem: sunfb
@@ -133,11 +131,24 @@ file arch/sun3/dev/idprom.c idprom needs-count
#
# Console (zs) related stuff
#
-file arch/sun3/dev/kbd.c zs
-file arch/sun3/dev/event.c zs
-file arch/sun3/dev/kd.c zs
-file arch/sun3/dev/ms.c zs
-file arch/sun3/dev/fb.c
+device zsc at obio {channel = -1}
+file arch/sun3/dev/zs.c zsc needs-flag
+file dev/ic/z8530sc.c zsc
+
+device zstty at zsc: tty
+file dev/ic/z8530tty.c zstty needs-flag
+
+define zsevent
+file dev/sun/event.c zsevent
+
+device kbd at zsc: zsevent
+file dev/sun/kbd.c kbd needs-flag
+file dev/sun/kbd_tables.c kbd
+file arch/sun3/dev/kd.c kbd
+
+device ms at zsc: zsevent
+file dev/sun/ms.c ms needs-flag
+
# RAM Disk for boot tape
device rd at mainbus
diff --git a/sys/arch/sun3/conf/std.sun3 b/sys/arch/sun3/conf/std.sun3
index c3c09188da2..efd888ba2d0 100644
--- a/sys/arch/sun3/conf/std.sun3
+++ b/sys/arch/sun3/conf/std.sun3
@@ -1,4 +1,4 @@
-# $NetBSD: std.sun3,v 1.13 1995/10/08 23:38:46 gwr Exp $
+# $NetBSD: std.sun3,v 1.14 1996/01/24 22:39:56 gwr Exp $
# Standard information for sun3's.
machine sun3 m68k
@@ -25,11 +25,16 @@ vmel0 at mainbus?
idprom0 at obctl? addr ?
# OBIO
-zs0 at obio? addr ?
-zs1 at obio? addr ?
eeprom0 at obio? addr ?
clock0 at obio? addr ?
+# Console (zs) stuff
+zsc0 at obio? addr ?
+zsc1 at obio? addr ?
+kbd0 at zsc0 channel 0
+ms0 at zsc0 channel 1
+zstty* at zsc? channel ?
+
# Standard defines
# XXX - Still needed?
diff --git a/sys/arch/sun3/dev/event.c b/sys/arch/sun3/dev/event.c
deleted file mode 100644
index a20bd5f230b..00000000000
--- a/sys/arch/sun3/dev/event.c
+++ /dev/null
@@ -1,171 +0,0 @@
-/* $NetBSD: event.c,v 1.4 1994/12/01 22:46:23 gwr Exp $ */
-
-/*
- * 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.
- *
- * @(#)event.c 8.1 (Berkeley) 6/11/93
- */
-
-/*
- * Internal `Firm_event' interface for the keyboard and mouse drivers.
- */
-
-#include <sys/param.h>
-#include <sys/fcntl.h>
-#include <sys/malloc.h>
-#include <sys/proc.h>
-#include <sys/systm.h>
-#include <sys/vnode.h>
-
-#include <machine/vuid_event.h>
-#include "event_var.h"
-
-/*
- * Initialize a firm_event queue.
- */
-void
-ev_init(ev)
- register struct evvar *ev;
-{
-
- ev->ev_get = ev->ev_put = 0;
- ev->ev_q = malloc((u_long)EV_QSIZE * sizeof(struct firm_event),
- M_DEVBUF, M_WAITOK);
- bzero((caddr_t)ev->ev_q, EV_QSIZE * sizeof(struct firm_event));
-}
-
-/*
- * Tear down a firm_event queue.
- */
-void
-ev_fini(ev)
- register struct evvar *ev;
-{
-
- free(ev->ev_q, M_DEVBUF);
-}
-
-/*
- * User-level interface: read, select.
- * (User cannot write an event queue.)
- */
-int
-ev_read(ev, uio, flags)
- register struct evvar *ev;
- struct uio *uio;
- int flags;
-{
- int s, n, cnt, error;
-
- /*
- * Make sure we can return at least 1.
- */
- if (uio->uio_resid < sizeof(struct firm_event))
- return (EMSGSIZE); /* ??? */
- s = splev();
- while (ev->ev_get == ev->ev_put) {
- if (flags & IO_NDELAY) {
- splx(s);
- return (EWOULDBLOCK);
- }
- ev->ev_wanted = 1;
- error = tsleep((caddr_t)ev, PEVENT | PCATCH, "firm_event", 0);
- if (error) {
- splx(s);
- return (error);
- }
- }
- /*
- * Move firm_events from tail end of queue (there is at least one
- * there).
- */
- if (ev->ev_put < ev->ev_get)
- cnt = EV_QSIZE - ev->ev_get; /* events in [get..QSIZE) */
- else
- cnt = ev->ev_put - ev->ev_get; /* events in [get..put) */
- splx(s);
- n = howmany(uio->uio_resid, sizeof(struct firm_event));
- if (cnt > n)
- cnt = n;
- error = uiomove((caddr_t)&ev->ev_q[ev->ev_get],
- cnt * sizeof(struct firm_event), uio);
- n -= cnt;
- /*
- * If we do not wrap to 0, used up all our space, or had an error,
- * stop. Otherwise move from front of queue to put index, if there
- * is anything there to move.
- */
- if ((ev->ev_get = (ev->ev_get + cnt) % EV_QSIZE) != 0 ||
- n == 0 || error || (cnt = ev->ev_put) == 0)
- return (error);
- if (cnt > n)
- cnt = n;
- error = uiomove((caddr_t)&ev->ev_q[0],
- cnt * sizeof(struct firm_event), uio);
- ev->ev_get = cnt;
- return (error);
-}
-
-int
-ev_select(ev, rw, p)
- register struct evvar *ev;
- int rw;
- struct proc *p;
-{
- int s = splev();
-
- switch (rw) {
-
- case FREAD:
- /* succeed if there is something to read */
- if (ev->ev_get != ev->ev_put) {
- splx(s);
- return (1);
- }
- selrecord(p, &ev->ev_sel);
- break;
-
- case FWRITE:
- return (1); /* always fails => never blocks */
- }
- splx(s);
- return (0);
-}
diff --git a/sys/arch/sun3/dev/kbd.c b/sys/arch/sun3/dev/kbd.c
deleted file mode 100644
index 19266cd1017..00000000000
--- a/sys/arch/sun3/dev/kbd.c
+++ /dev/null
@@ -1,808 +0,0 @@
-/* $NetBSD: kbd.c,v 1.11 1995/10/08 23:40:42 gwr Exp $ */
-
-/*
- * 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.
- *
- * @(#)kbd.c 8.2 (Berkeley) 10/30/93
- */
-
-/*
- * Keyboard driver (/dev/kbd -- note that we do not have minor numbers
- * [yet?]). Translates incoming bytes to ASCII or to `firm_events' and
- * passes them up to the appropriate reader.
- */
-
-#include <sys/param.h>
-#include <sys/conf.h>
-#include <sys/device.h>
-#include <sys/ioctl.h>
-#include <sys/kernel.h>
-#include <sys/proc.h>
-#include <sys/syslog.h>
-#include <sys/systm.h>
-#include <sys/tty.h>
-
-#include <machine/autoconf.h>
-#include <machine/kbd.h>
-#include <machine/kbio.h>
-#include <machine/vuid_event.h>
-
-#include "event_var.h"
-
-/*
- * Sun keyboard definitions (from Sprite).
- * These apply to type 2, 3 and 4 keyboards.
- */
-#define KEY_CODE(c) ((c) & KBD_KEYMASK) /* keyboard code index */
-#define KEY_UP(c) ((c) & KBD_UP) /* true => key went up */
-
-/*
- * Each KEY_CODE(x) can be translated via the tables below.
- * The result is either a valid ASCII value in [0..0x7f] or is one
- * of the following `magic' values saying something interesting
- * happened. If LSHIFT or RSHIFT has changed state the next
- * lookup should come from the appropriate table; if ALLUP is
- * sent all keys (including both shifts and the control key) are
- * now up, and the next byte is the keyboard ID code.
- *
- * These tables ignore all function keys (on the theory that if you
- * want these keys, you should use a window system). Note that
- * `caps lock' is just mapped as `ignore' (so there!). (Only the
- * type 3 and 4 keyboards have a caps lock key anyway.)
- */
-#define KEY_MAGIC 0x80 /* flag => magic value */
-#define KEY_IGNORE 0x80
-#define KEY_L1 KEY_IGNORE
-#define KEY_CAPSLOCK KEY_IGNORE
-#define KEY_LSHIFT 0x81
-#define KEY_RSHIFT 0x82
-#define KEY_CONTROL 0x83
-#define KEY_ALLUP 0x84 /* all keys are now up; also reset */
-
-/*
- * Decode tables for type 2, 3, and 4 keyboards
- * (stolen from Sprite; see also kbd.h).
- */
-static u_char kbd_unshifted[] = {
-/* 0 */ KEY_IGNORE, KEY_L1, KEY_IGNORE, KEY_IGNORE,
-/* 4 */ KEY_IGNORE, KEY_IGNORE, KEY_IGNORE, KEY_IGNORE,
-/* 8 */ KEY_IGNORE, KEY_IGNORE, KEY_IGNORE, KEY_IGNORE,
-/* 12 */ KEY_IGNORE, KEY_IGNORE, KEY_IGNORE, KEY_IGNORE,
-/* 16 */ KEY_IGNORE, KEY_IGNORE, KEY_IGNORE, KEY_IGNORE,
-/* 20 */ KEY_IGNORE, KEY_IGNORE, KEY_IGNORE, KEY_IGNORE,
-/* 24 */ KEY_IGNORE, KEY_IGNORE, KEY_IGNORE, KEY_IGNORE,
-/* 28 */ KEY_IGNORE, '\033', '1', '2',
-/* 32 */ '3', '4', '5', '6',
-/* 36 */ '7', '8', '9', '0',
-/* 40 */ '-', '=', '`', '\b',
-/* 44 */ KEY_IGNORE, KEY_IGNORE, KEY_IGNORE, KEY_IGNORE,
-/* 48 */ KEY_IGNORE, KEY_IGNORE, KEY_IGNORE, KEY_IGNORE,
-/* 52 */ KEY_IGNORE, '\t', 'q', 'w',
-/* 56 */ 'e', 'r', 't', 'y',
-/* 60 */ 'u', 'i', 'o', 'p',
-/* 64 */ '[', ']', '\177', KEY_IGNORE,
-/* 68 */ KEY_IGNORE, KEY_IGNORE, KEY_IGNORE, KEY_IGNORE,
-/* 72 */ KEY_IGNORE, KEY_IGNORE, KEY_IGNORE, KEY_IGNORE,
-/* 76 */ KEY_CONTROL, 'a', 's', 'd',
-/* 80 */ 'f', 'g', 'h', 'j',
-/* 84 */ 'k', 'l', ';', '\'',
-/* 88 */ '\\', '\r', KEY_IGNORE, KEY_IGNORE,
-/* 92 */ KEY_IGNORE, KEY_IGNORE, KEY_IGNORE, KEY_IGNORE,
-/* 96 */ KEY_IGNORE, KEY_IGNORE, KEY_IGNORE, KEY_LSHIFT,
-/* 100 */ 'z', 'x', 'c', 'v',
-/* 104 */ 'b', 'n', 'm', ',',
-/* 108 */ '.', '/', KEY_RSHIFT, '\n',
-/* 112 */ KEY_IGNORE, KEY_IGNORE, KEY_IGNORE, KEY_IGNORE,
-/* 116 */ KEY_IGNORE, KEY_IGNORE, KEY_IGNORE, KEY_CAPSLOCK,
-/* 120 */ KEY_IGNORE, ' ', KEY_IGNORE, KEY_IGNORE,
-/* 124 */ KEY_IGNORE, KEY_IGNORE, KEY_IGNORE, KEY_ALLUP,
-};
-
-static u_char kbd_shifted[] = {
-/* 0 */ KEY_IGNORE, KEY_L1, KEY_IGNORE, KEY_IGNORE,
-/* 4 */ KEY_IGNORE, KEY_IGNORE, KEY_IGNORE, KEY_IGNORE,
-/* 8 */ KEY_IGNORE, KEY_IGNORE, KEY_IGNORE, KEY_IGNORE,
-/* 12 */ KEY_IGNORE, KEY_IGNORE, KEY_IGNORE, KEY_IGNORE,
-/* 16 */ KEY_IGNORE, KEY_IGNORE, KEY_IGNORE, KEY_IGNORE,
-/* 20 */ KEY_IGNORE, KEY_IGNORE, KEY_IGNORE, KEY_IGNORE,
-/* 24 */ KEY_IGNORE, KEY_IGNORE, KEY_IGNORE, KEY_IGNORE,
-/* 28 */ KEY_IGNORE, '\033', '!', '@',
-/* 32 */ '#', '$', '%', '^',
-/* 36 */ '&', '*', '(', ')',
-/* 40 */ '_', '+', '~', '\b',
-/* 44 */ KEY_IGNORE, KEY_IGNORE, KEY_IGNORE, KEY_IGNORE,
-/* 48 */ KEY_IGNORE, KEY_IGNORE, KEY_IGNORE, KEY_IGNORE,
-/* 52 */ KEY_IGNORE, '\t', 'Q', 'W',
-/* 56 */ 'E', 'R', 'T', 'Y',
-/* 60 */ 'U', 'I', 'O', 'P',
-/* 64 */ '{', '}', '\177', KEY_IGNORE,
-/* 68 */ KEY_IGNORE, KEY_IGNORE, KEY_IGNORE, KEY_IGNORE,
-/* 72 */ KEY_IGNORE, KEY_IGNORE, KEY_IGNORE, KEY_IGNORE,
-/* 76 */ KEY_CONTROL, 'A', 'S', 'D',
-/* 80 */ 'F', 'G', 'H', 'J',
-/* 84 */ 'K', 'L', ':', '"',
-/* 88 */ '|', '\r', KEY_IGNORE, KEY_IGNORE,
-/* 92 */ KEY_IGNORE, KEY_IGNORE, KEY_IGNORE, KEY_IGNORE,
-/* 96 */ KEY_IGNORE, KEY_IGNORE, KEY_IGNORE, KEY_LSHIFT,
-/* 100 */ 'Z', 'X', 'C', 'V',
-/* 104 */ 'B', 'N', 'M', '<',
-/* 108 */ '>', '?', KEY_RSHIFT, '\n',
-/* 112 */ KEY_IGNORE, KEY_IGNORE, KEY_IGNORE, KEY_IGNORE,
-/* 116 */ KEY_IGNORE, KEY_IGNORE, KEY_IGNORE, KEY_CAPSLOCK,
-/* 120 */ KEY_IGNORE, ' ', KEY_IGNORE, KEY_IGNORE,
-/* 124 */ KEY_IGNORE, KEY_IGNORE, KEY_IGNORE, KEY_ALLUP,
-};
-
-/*
- * We need to remember the state of the keyboard's shift and control
- * keys, and we need a per-type translation table.
- */
-struct kbd_state {
- const u_char *kbd_unshifted; /* unshifted keys */
- const u_char *kbd_shifted; /* shifted keys */
- const u_char *kbd_cur; /* current keys (either of the preceding) */
- union {
- char c[2]; /* left and right shift keys */
- short s; /* true => either shift key */
- } kbd_shift;
-#define kbd_lshift kbd_shift.c[0]
-#define kbd_rshift kbd_shift.c[1]
-#define kbd_anyshift kbd_shift.s
- char kbd_control; /* true => ctrl down */
- char kbd_click; /* true => keyclick enabled */
- char kbd_takeid; /* take next byte as ID */
- u_char kbd_id; /* a place to store the ID */
- char kbd_leds; /* LED state */
- char _pad;
-};
-
-/*
- * Keyboard driver state. The ascii and kbd links go up and down and
- * we just sit in the middle doing translation. Note that it is possible
- * to get just one of the two links, in which case /dev/kbd is unavailable.
- * The downlink supplies us with `internal' open and close routines which
- * will enable dataflow across the downlink. We promise to call open when
- * we are willing to take keystrokes, and to call close when we are not.
- * If /dev/kbd is not the console tty input source, we do this whenever
- * /dev/kbd is in use; otherwise we just leave it open forever.
- */
-struct kbd_softc {
- struct tty *k_cons; /* uplink for ASCII data to console */
- struct tty *k_kbd; /* downlink for output to keyboard */
- void (*k_open) __P((struct tty *)); /* enable dataflow */
- void (*k_close) __P((struct tty *)); /* disable dataflow */
- int k_evmode; /* set if we should produce events */
- int k_isopen; /* set if open has been done */
- struct kbd_state k_state; /* ASCII decode state */
- struct evvar k_events; /* event queue state */
- int k_repeatc; /* repeated character */
- int k_repeating; /* we've called timeout() */
-} kbd_softc;
-
-/* Prototypes */
-void kbd_ascii(struct tty *);
-void kbd_serial(struct tty *, void (*)(), void (*)());
-int kbd_iopen(void);
-void kbd_reset(struct kbd_softc *);
-int kbd_translate(int);
-void kbd_rint(int);
-int kbdopen(dev_t, int, int, struct proc *);
-int kbdclose(dev_t, int, int, struct proc *);
-int kbdread(dev_t, struct uio *, int);
-int kbdwrite(dev_t, struct uio *, int);
-int kbdioctl(dev_t, u_long, caddr_t, int, struct proc *);
-int kbdselect(dev_t, int, struct proc *);
-int kbd_docmd(int, int);
-
-/* set in kbdattach() */
-int kbd_repeat_start;
-int kbd_repeat_step;
-
-/*
- * Initialization done by either kdcninit or kbd_iopen
- */
-void
-kbd_init_tables()
-{
- struct kbd_state *ks;
-
- ks = &kbd_softc.k_state;
- if (ks->kbd_cur == NULL) {
- ks->kbd_cur = kbd_unshifted;
- ks->kbd_unshifted = kbd_unshifted;
- ks->kbd_shifted = kbd_shifted;
- }
-}
-
-/*
- * Attach the console keyboard ASCII (up-link) interface.
- * This is called by the "kd" (keyboard/display) driver to
- * tell this module where to send read-side data.
- */
-void
-kbd_ascii(struct tty *tp)
-{
- kbd_softc.k_cons = tp;
-}
-
-/*
- * Attach the console keyboard serial (down-link) interface.
- * This is called by the "zs" driver for the keyboard port
- * to tell this module how to talk to the keyboard.
- */
-void
-kbd_serial(struct tty *tp, void (*iopen)(), void (*iclose)())
-{
- register struct kbd_softc *k;
-
- k = &kbd_softc;
- k->k_kbd = tp;
- k->k_open = iopen;
- k->k_close = iclose;
-
- /* Do this before any calls to kbd_rint(). */
- kbd_init_tables();
-
- /* Now attach the (kd) pseudo-driver. */
- kd_attach(1); /* This calls kbd_ascii() */
-}
-
-/*
- * Initialization to be done at first open.
- * This is called from kbdopen or kdopen (in kd.c)
- */
-int
-kbd_iopen()
-{
- struct kbd_softc *k;
- struct tty *tp;
- int error, s;
-
- k = &kbd_softc;
-
- /* Tolerate extra calls. */
- if (k->k_isopen)
- return (0);
-
- /* Make sure "down" link (to zs1a) is established. */
- tp = k->k_kbd;
- if (tp == NULL)
- return (ENXIO);
-
- kbd_repeat_start = hz/2;
- kbd_repeat_step = hz/20;
-
- /* Open the "down" link (never to be closed). */
- tp->t_ispeed = tp->t_ospeed = 1200;
- (*k->k_open)(tp);
-
- /* Reset the keyboard and find out its type. */
- s = spltty();
- (void) ttyoutput(KBD_CMD_RESET, tp);
- (*tp->t_oproc)(tp);
- /* The wakeup for this sleep is in kbd_reset(). */
- error = tsleep((caddr_t)k, PZERO | PCATCH,
- devopn, hz);
- if (error == EWOULDBLOCK) { /* no response */
- log(LOG_ERR, "keyboard reset failed\n");
- /*
- * Allow the open anyway (to keep getty happy)
- * but assume the "least common denominator".
- */
- k->k_state.kbd_id = KB_SUN2;
- error = 0;
- }
-
- if (error == 0)
- k->k_isopen = 1;
-
- splx(s);
- return error;
-}
-
-void
-kbd_reset(k)
- struct kbd_softc *k;
-{
- struct kbd_state *ks;
-
- ks = &k->k_state;
-
- /*
- * On first identification, wake up anyone waiting for type
- * and set up the table pointers.
- */
- if (k->k_isopen == 0)
- wakeup((caddr_t)k);
-
- /* Restore keyclick, if necessary */
- switch (ks->kbd_id) {
-
- case KB_SUN2:
- /* Type 2 keyboards don't support keyclick */
- break;
-
- case KB_SUN3:
- /* Type 3 keyboards come up with keyclick on */
- if (!ks->kbd_click)
- (void) kbd_docmd(KBD_CMD_NOCLICK, 0);
- break;
-
- case KB_SUN4:
- /* Type 4 keyboards come up with keyclick off */
- if (ks->kbd_click)
- (void) kbd_docmd(KBD_CMD_CLICK, 0);
- break;
- }
-
- /* LEDs are off after reset. */
- ks->kbd_leds = 0;
-}
-
-/*
- * Turn keyboard up/down codes into ASCII.
- */
-int
-kbd_translate(register int c)
-{
- register struct kbd_state *ks;
- register int down;
-
- ks = &kbd_softc.k_state;
- if (ks->kbd_cur == NULL) {
- /*
- * Do not know how to translate yet.
- * We will find out when a RESET comes along.
- */
- return (-1);
- }
- down = !KEY_UP(c);
- c = ks->kbd_cur[KEY_CODE(c)];
- if (c & KEY_MAGIC) {
- switch (c) {
-
- case KEY_LSHIFT:
- ks->kbd_lshift = down;
- break;
-
- case KEY_RSHIFT:
- ks->kbd_rshift = down;
- break;
-
- case KEY_ALLUP:
- ks->kbd_anyshift = 0;
- ks->kbd_control = 0;
- break;
-
- case KEY_CONTROL:
- ks->kbd_control = down;
- /* FALLTHROUGH */
-
- case KEY_IGNORE:
- return (-1);
-
- default:
- panic("kbd_translate");
- }
- if (ks->kbd_anyshift)
- ks->kbd_cur = ks->kbd_shifted;
- else
- ks->kbd_cur = ks->kbd_unshifted;
- return (-1);
- }
- if (!down)
- return (-1);
- if (ks->kbd_control) {
- /* control space and unshifted control atsign return null */
- if (c == ' ' || c == '2')
- return (0);
- /* unshifted control hat */
- if (c == '6')
- return ('^' & 0x1f);
- /* standard controls */
- if (c >= '@' && c < 0x7f)
- return (c & 0x1f);
- }
- return (c);
-}
-
-void
-kbd_repeat(void *arg)
-{
- struct kbd_softc *k = (struct kbd_softc *)arg;
- int s = spltty();
-
- if (k->k_repeating && k->k_repeatc >= 0 && k->k_cons != NULL) {
- ttyinput(k->k_repeatc, k->k_cons);
- timeout(kbd_repeat, k, kbd_repeat_step);
- }
- splx(s);
-}
-
-void
-kbd_rint(register int c)
-{
- register struct kbd_softc *k = &kbd_softc;
- register struct firm_event *fe;
- register int put;
-
- if (k->k_repeating) {
- k->k_repeating = 0;
- untimeout(kbd_repeat, k);
- }
-
- /*
- * Reset keyboard after serial port overrun, so we can resynch.
- */
- if (c & (TTY_FE|TTY_PE)) {
- log(LOG_ERR, "keyboard input error (0x%x)\n", c);
- (void) ttyoutput(KBD_CMD_RESET, k->k_kbd);
- (*k->k_kbd->t_oproc)(k->k_kbd);
- return;
- }
-
- /* Read the keyboard id if we read a KBD_RESET last time */
- if (k->k_state.kbd_takeid) {
- k->k_state.kbd_takeid = 0;
- k->k_state.kbd_id = c;
- kbd_reset(k);
- return;
- }
-
- /* If we have been reset, setup to grab the keyboard id next time */
- if (c == KBD_RESET) {
- k->k_state.kbd_takeid = 1;
- return;
- }
-
- /*
- * If /dev/kbd is not connected in event mode, but we are sending
- * data to /dev/console, translate and send upstream. Note that
- * we will get this while opening /dev/kbd if it is not already
- * open and we do not know its type.
- */
- if (!k->k_evmode) {
- c = kbd_translate(c);
- if (c >= 0 && k->k_cons != NULL) {
- ttyinput(c, k->k_cons);
- k->k_repeating = 1;
- k->k_repeatc = c;
- timeout(kbd_repeat, k, kbd_repeat_start);
- }
- return;
- }
-
- /*
- * IDLEs confuse the MIT X11R4 server badly, so we must drop them.
- * This is bad as it means the server will not automatically resync
- * on all-up IDLEs, but I did not drop them before, and the server
- * goes crazy when it comes time to blank the screen....
- */
- if (c == KBD_IDLE)
- return;
-
- /*
- * Keyboard is generating events. Turn this keystroke into an
- * event and put it in the queue. If the queue is full, the
- * keystroke is lost (sorry!).
- */
- put = k->k_events.ev_put;
- fe = &k->k_events.ev_q[put];
- put = (put + 1) % EV_QSIZE;
- if (put == k->k_events.ev_get) {
- log(LOG_WARNING, "keyboard event queue overflow\n"); /* ??? */
- return;
- }
- fe->id = KEY_CODE(c);
- fe->value = KEY_UP(c) ? VKEY_UP : VKEY_DOWN;
- fe->time = time;
- k->k_events.ev_put = put;
- EV_WAKEUP(&k->k_events);
-}
-
-int
-kbdopen(dev_t dev, int flags, int mode, struct proc *p)
-{
- int error;
-
-#if 1 /* XXX - temporary hack */
- /* XXX - Should make login chown devices in /etc/fbtab */
- /* Require root or same UID as the kd session leader. */
- if (p->p_ucred->cr_uid) {
- struct tty *kd_tp;
- struct proc *kd_p;
- extern struct tty *kdtty();
-
- /* Make sure kd is attached and open. */
- kd_tp = kdtty(0);
- if ((kd_tp == NULL) || (kd_tp->t_session == NULL))
- return (EPERM);
- kd_p = kd_tp->t_session->s_leader;
- if (p->p_ucred->cr_uid != kd_p->p_ucred->cr_uid)
- return (EACCES);
- }
-#endif
-
- /* Exclusive open required for /dev/kbd */
- if (kbd_softc.k_events.ev_io)
- return (EBUSY);
- kbd_softc.k_events.ev_io = p;
-
- if ((error = kbd_iopen()) != 0) {
- kbd_softc.k_events.ev_io = NULL;
- return (error);
- }
- ev_init(&kbd_softc.k_events);
- return (0);
-}
-
-int
-kbdclose(dev_t dev, int flags, int mode, struct proc *p)
-{
-
- /*
- * Turn off event mode, dump the queue, and close the keyboard
- * unless it is supplying console input.
- */
- kbd_softc.k_evmode = 0;
- ev_fini(&kbd_softc.k_events);
- kbd_softc.k_events.ev_io = NULL;
- return (0);
-}
-
-int
-kbdread(dev_t dev, struct uio *uio, int flags)
-{
-
- return (ev_read(&kbd_softc.k_events, uio, flags));
-}
-
-/* this routine should not exist, but is convenient to write here for now */
-int
-kbdwrite(dev_t dev, struct uio *uio, int flags)
-{
-
- return (EOPNOTSUPP);
-}
-
-int
-kbdioctl(dev_t dev, u_long cmd, register caddr_t data,
- int flag, struct proc *p)
-{
- register struct kbd_softc *k = &kbd_softc;
- register struct kiockey *kmp;
- register u_char *tp;
-
- switch (cmd) {
-
- case KIOCTRANS:
- if (*(int *)data == TR_UNTRANS_EVENT)
- return (0);
- break;
-
- case KIOCGTRANS:
- /*
- * Get translation mode
- */
- *(int *)data = TR_UNTRANS_EVENT;
- return (0);
-
- case KIOCGETKEY:
- if (((struct okiockey *)data)->kio_station == 118) {
- /*
- * This is X11 asking if a type 3 keyboard is
- * really a type 3 keyboard. Say yes.
- */
- ((struct okiockey *)data)->kio_entry = HOLE;
- return (0);
- }
- break;
-
- case KIOCSKEY:
- kmp = (struct kiockey *)data;
-
- switch (kmp->kio_tablemask) {
- case KIOC_NOMASK:
- tp = kbd_unshifted;
- break;
- case KIOC_SHIFTMASK:
- tp = kbd_shifted;
- break;
- default:
- /* Silently ignore unsupported masks */
- return (0);
- }
- if (kmp->kio_entry & 0xff80)
- /* Silently ignore funny entries */
- return (0);
-
- tp[kmp->kio_station] = kmp->kio_entry;
- return (0);
-
- case KIOCGKEY:
- kmp = (struct kiockey *)data;
-
- switch (kmp->kio_tablemask) {
- case KIOC_NOMASK:
- tp = kbd_unshifted;
- break;
- case KIOC_SHIFTMASK:
- tp = kbd_shifted;
- break;
- default:
- return (0);
- }
- kmp->kio_entry = tp[kmp->kio_station] & ~KEY_MAGIC;
- return (0);
-
- case KIOCCMD:
- /*
- * ``unimplemented commands are ignored'' (blech)
- * so cannot check return value from kbd_docmd
- */
-#ifdef notyet
- while (kbd_docmd(*(int *)data, 1) == ENOSPC) /*ERESTART?*/
- (void) sleep((caddr_t)&lbolt, TTOPRI);
-#else
- (void) kbd_docmd(*(int *)data, 1);
-#endif
- return (0);
-
- case KIOCTYPE:
- *(int *)data = k->k_state.kbd_id;
- return (0);
-
- case KIOCSDIRECT:
- k->k_evmode = *(int *)data;
- return (0);
-
- case KIOCLAYOUT:
- *data = 0;
- return (0);
-
- case KIOCSLED:
- if (k->k_state.kbd_id != KB_SUN4) {
- /* xxx NYI */
- k->k_state.kbd_leds = *(char*)data;
- } else {
- int s;
- char leds = *(char *)data;
- struct tty *tp = kbd_softc.k_kbd;
- s = spltty();
- if (tp->t_outq.c_cc > 120)
- (void) tsleep((caddr_t)&lbolt, TTIPRI,
- ttyout, 0);
- splx(s);
- if (ttyoutput(KBD_CMD_SETLED, tp) >= 0)
- return (ENOSPC); /* ERESTART? */
- k->k_state.kbd_leds = leds;
- if (ttyoutput(leds, tp) >= 0)
- return (ENOSPC); /* ERESTART? */
- (*tp->t_oproc)(tp);
- }
- return (0);
-
- case KIOCGLED:
- *(char *)data = k->k_state.kbd_leds;
- return (0);
-
- case FIONBIO: /* we will remove this someday (soon???) */
- return (0);
-
- case FIOASYNC:
- k->k_events.ev_async = *(int *)data != 0;
- return (0);
-
- case TIOCSPGRP:
- if (*(int *)data != k->k_events.ev_io->p_pgid)
- return (EPERM);
- return (0);
-
- default:
- return (ENOTTY);
- }
-
- /*
- * We identified the ioctl, but we do not handle it.
- */
- return (EOPNOTSUPP); /* misuse, but what the heck */
-}
-
-int
-kbdselect(dev_t dev, int rw, struct proc *p)
-{
-
- return (ev_select(&kbd_softc.k_events, rw, p));
-}
-
-/*
- * Execute a keyboard command; return 0 on success.
- * If `isuser', force a small delay before output if output queue
- * is flooding. (The keyboard runs at 1200 baud, or 120 cps.)
- */
-int
-kbd_docmd(int cmd, int isuser)
-{
- register struct tty *tp = kbd_softc.k_kbd;
- register struct kbd_softc *k = &kbd_softc;
- int s;
-
- if (tp == NULL)
- return (ENXIO); /* ??? */
- switch (cmd) {
-
- case KBD_CMD_BELL:
- case KBD_CMD_NOBELL:
- /* Supported by type 2, 3, and 4 keyboards */
- break;
-
- case KBD_CMD_CLICK:
- /* Unsupported by type 2 keyboards */
- if (k->k_state.kbd_id != KB_SUN2) {
- k->k_state.kbd_click = 1;
- break;
- }
- return (EINVAL);
-
- case KBD_CMD_NOCLICK:
- /* Unsupported by type 2 keyboards */
- if (k->k_state.kbd_id != KB_SUN2) {
- k->k_state.kbd_click = 0;
- break;
- }
- return (EINVAL);
-
- default:
- return (EINVAL); /* ENOTTY? EOPNOTSUPP? */
- }
-
- if (isuser) {
- s = spltty();
- if (tp->t_outq.c_cc > 120)
- (void) tsleep((caddr_t)&lbolt, TTIPRI,
- ttyout, 0);
- splx(s);
- }
- if (ttyoutput(cmd, tp) >= 0)
- return (ENOSPC); /* ERESTART? */
- (*tp->t_oproc)(tp);
- return (0);
-}
diff --git a/sys/arch/sun3/dev/kd.c b/sys/arch/sun3/dev/kd.c
index 12826032f73..61307b54697 100644
--- a/sys/arch/sun3/dev/kd.c
+++ b/sys/arch/sun3/dev/kd.c
@@ -1,4 +1,4 @@
-/* $NetBSD: kd.c,v 1.13 1995/04/26 23:20:15 gwr Exp $ */
+/* $NetBSD: kd.c,v 1.14 1996/01/24 22:40:20 gwr Exp $ */
/*
* Copyright (c) 1994, 1995 Gordon W. Ross
@@ -53,42 +53,61 @@
#include <machine/psl.h>
#include <dev/cons.h>
+#include <dev/sun/kbd_xlate.h>
-#define BURST 64
+#define KDMAJOR 1
+#define PUT_WSIZE 64
+
+cdev_decl(kd); /* open, close, read, write, ioctl, stop, ... */
+
+struct kd_softc {
+ struct device kd_dev; /* required first: base device */
+ struct tty *kd_tty;
+};
/*
* There is no point in pretending there might be
* more than one keyboard/display device.
*/
-struct tty *kd_tty[1];
-
-int kdopen(dev_t, int, int, struct proc *);
-int kdclose(dev_t, int, int, struct proc *);
-int kdread(dev_t, struct uio *, int);
-int kdwrite(dev_t, struct uio *, int);
-int kdioctl(dev_t, int, caddr_t, int, struct proc *);
+struct kd_softc kd_softc;
static int kdparam(struct tty *, struct termios *);
static void kdstart(struct tty *);
int kd_is_console;
-/* This is called by kbd_serial() like a pseudo-device. */
+/*
+ * This is called by kbd_attach()
+ * XXX - Make this a proper child of kbd?
+ */
void
-kd_attach(n)
- int n;
+kd_init(unit)
+ int unit;
{
- kd_tty[0] = ttymalloc();
+ struct kd_softc *kd;
+ struct tty *tp;
+
+ if (unit != 0)
+ return;
+ kd = &kd_softc; /* XXX */
+ tp = ttymalloc();
- /* Tell keyboard module where to send read data. */
- kbd_ascii(kd_tty[0]);
+ kd->kd_tty = tp;
+ tp->t_oproc = kdstart;
+ tp->t_param = kdparam;
+ tp->t_dev = makedev(KDMAJOR, unit);
+
+ return;
}
struct tty *
kdtty(dev)
dev_t dev;
{
- return kd_tty[0];
+ struct kd_softc *kd;
+
+ kd = &kd_softc; /* XXX */
+ return (kd->kd_tty);
}
int
@@ -97,39 +116,49 @@ kdopen(dev, flag, mode, p)
int flag, mode;
struct proc *p;
{
- int error, unit;
+ struct kd_softc *kd;
+ int error, s, unit;
struct tty *tp;
unit = minor(dev);
- if (unit) return ENXIO;
-
- tp = kd_tty[unit];
- if (tp == NULL)
+ if (unit != 0)
return ENXIO;
+ kd = &kd_softc; /* XXX */
+ tp = kd->kd_tty;
- if ((error = kbd_iopen()) != 0) {
+ if ((error = kbd_iopen(unit)) != 0) {
#ifdef DIAGNOSTIC
printf("kd: kbd_iopen, error=%d\n", error);
#endif
return (error);
}
- tp->t_oproc = kdstart;
- tp->t_param = kdparam;
- tp->t_dev = dev;
+ /* It's simpler to do this up here. */
+ if (((tp->t_state & (TS_ISOPEN | TS_XCLUDE))
+ == (TS_ISOPEN | TS_XCLUDE))
+ && (p->p_ucred->cr_uid != 0) )
+ {
+ return (EBUSY);
+ }
+
+ s = spltty();
+
if ((tp->t_state & TS_ISOPEN) == 0) {
- tp->t_state |= TS_WOPEN;
+ /* First open. */
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 = TTYDEF_SPEED;
- kdparam(tp, &tp->t_termios);
+ (void) kdparam(tp, &tp->t_termios);
ttsetwater(tp);
- } else if (tp->t_state & TS_XCLUDE && p->p_ucred->cr_uid != 0)
- return EBUSY;
- tp->t_state |= TS_CARR_ON;
+ /* Flush pending input? Clear translator? */
+ /* This (pseudo)device always has SOFTCAR */
+ tp->t_state |= TS_CARR_ON;
+ }
+
+ splx(s);
return ((*linesw[tp->t_line].l_open)(dev, tp));
}
@@ -140,8 +169,15 @@ kdclose(dev, flag, mode, p)
int flag, mode;
struct proc *p;
{
- int unit = minor(dev);
- struct tty *tp = kd_tty[unit];
+ struct kd_softc *kd;
+ struct tty *tp;
+
+ kd = &kd_softc; /* XXX */
+ tp = kd->kd_tty;
+
+ /* XXX This is for cons.c. */
+ if ((tp->t_state & TS_ISOPEN) == 0)
+ return 0;
(*linesw[tp->t_line].l_close)(tp, flag);
ttyclose(tp);
@@ -154,8 +190,11 @@ kdread(dev, uio, flag)
struct uio *uio;
int flag;
{
- int unit = minor(dev);
- struct tty *tp = kd_tty[unit];
+ struct kd_softc *kd;
+ struct tty *tp;
+
+ kd = &kd_softc; /* XXX */
+ tp = kd->kd_tty;
return ((*linesw[tp->t_line].l_read)(tp, uio, flag));
}
@@ -166,31 +205,29 @@ kdwrite(dev, uio, flag)
struct uio *uio;
int flag;
{
- int unit = minor(dev);
- struct tty *tp = kd_tty[unit];
-
- return ((*linesw[tp->t_line].l_write)(tp, uio, flag));
-}
-
-int
-kdstop(tp, flag)
+ struct kd_softc *kd;
struct tty *tp;
- int flag;
-{
+ kd = &kd_softc; /* XXX */
+ tp = kd->kd_tty;
+
+ return ((*linesw[tp->t_line].l_write)(tp, uio, flag));
}
int
kdioctl(dev, cmd, data, flag, p)
dev_t dev;
- int cmd;
+ u_long cmd;
caddr_t data;
int flag;
struct proc *p;
{
+ struct kd_softc *kd;
+ struct tty *tp;
int error;
- int unit = minor(dev);
- struct tty *tp = kd_tty[unit];
+
+ kd = &kd_softc; /* XXX */
+ tp = kd->kd_tty;
error = (*linesw[tp->t_line].l_ioctl)(tp, cmd, data, flag, p);
if (error >= 0)
@@ -206,6 +243,28 @@ kdioctl(dev, cmd, data, flag, p)
return ENOTTY;
}
+
+static int
+kdparam(tp, t)
+ struct tty *tp;
+ struct termios *t;
+{
+ /* XXX - These are ignored... */
+ tp->t_ispeed = t->c_ispeed;
+ tp->t_ospeed = t->c_ospeed;
+ tp->t_cflag = t->c_cflag;
+ return 0;
+}
+
+
+int
+kdstop(tp, flag)
+ struct tty *tp;
+ int flag;
+{
+
+}
+
static void kd_later(void*);
static void kd_putfb(struct tty *);
@@ -285,12 +344,12 @@ kd_later(tpaddr)
static void kd_putfb(tp)
struct tty *tp;
{
- char buf[BURST];
+ char buf[PUT_WSIZE];
struct clist *cl = &tp->t_outq;
char *p, *end;
int len;
- while ((len = q_to_b(cl, buf, BURST-1)) > 0) {
+ while ((len = q_to_b(cl, buf, PUT_WSIZE-1)) > 0) {
/* PROM will barf if high bits are set. */
p = buf;
end = buf + len;
@@ -300,70 +359,98 @@ static void kd_putfb(tp)
}
}
-
-static int
-kdparam(tp, t)
- struct tty *tp;
- struct termios *t;
+/*
+ * Our "interrupt" routine for input.
+ */
+void
+kd_input(c)
+ int c;
{
- /* XXX - These are ignored... */
- tp->t_ispeed = t->c_ispeed;
- tp->t_ospeed = t->c_ospeed;
- tp->t_cflag = t->c_cflag;
- return 0;
-}
+ struct kd_softc *kd = &kd_softc;
+ struct tty *tp;
+ /* XXX: Make sure the device is open. */
+ tp = kd->kd_tty;
+ if (tp == NULL)
+ return;
+ if ((tp->t_state & TS_ISOPEN) == 0)
+ return;
-/*
- * kd console support
- */
+ ttyinput(c, kd->kd_tty);
+}
-extern int zscnprobe_kbd(), zscngetc(), kbd_translate();
-kdcnprobe(cp)
- struct consdev *cp;
-{
- int maj;
+/****************************************************************
+ * kd console support
+ ****************************************************************/
- /* locate the major number */
- for (maj = 0; maj < nchrdev; maj++)
- if (cdevsw[maj].d_open == (void*)kdopen)
- break;
+extern void *zs_conschan;
+extern int zs_getc();
+extern void nullcnprobe();
+cons_decl(kd);
- /* initialize required fields */
- cp->cn_dev = makedev(maj, 0);
- cp->cn_pri = zscnprobe_kbd();
-}
+/* The debugger gets its own key translation state. */
+static struct kbd_state kdcn_state;
-kdcninit(cp)
- struct consdev *cp;
+void
+kdcninit(cn)
+ struct consdev *cn;
{
+ struct kbd_state *ks = &kdcn_state;
- /* This prepares zscngetc() */
- zs_set_conschan(1, 0);
+ mon_printf("console on kd0 (keyboard/display)\n");
/* This prepares kbd_translate() */
- kbd_init_tables();
+ ks->kbd_id = KBD_MIN_TYPE;
+ kbd_xlate_init(ks);
/* Indicate that it is OK to use the PROM fbwrite */
kd_is_console = 1;
-
- mon_printf("console on kd0 (keyboard/display)\n");
}
+int
kdcngetc(dev)
dev_t dev;
{
- int c;
+ struct kbd_state *ks = &kdcn_state;
+ int code, class, data, keysym;
+
+ for (;;) {
+ code = zs_getc(zs_conschan);
+ keysym = kbd_code_to_keysym(ks, code);
+ class = KEYSYM_CLASS(keysym);
+
+ switch (class) {
+ case KEYSYM_ASCII:
+ goto out;
+
+ case KEYSYM_CLRMOD:
+ case KEYSYM_SETMOD:
+ data = (keysym & 0x1F);
+ /* Only allow ctrl or shift. */
+ if (data > KBMOD_SHIFT_R)
+ break;
+ data = 1 << data;
+ if (class == KEYSYM_SETMOD)
+ ks->kbd_modbits |= data;
+ else
+ ks->kbd_modbits &= ~data;
+ break;
- do {
- c = zscngetc(0);
- c = kbd_translate(c);
- } while (c == -1);
+ case KEYSYM_ALL_UP:
+ /* No toggle keys here. */
+ ks->kbd_modbits = 0;
+ break;
- return (c);
+ default: /* ignore all other keysyms */
+ break;
+ }
+ }
+out:
+ return (keysym);
}
+void
kdcnputc(dev, c)
dev_t dev;
int c;
@@ -376,6 +463,25 @@ void kdcnpollc(dev, on)
dev_t dev;
int on;
{
- if (on)
+ struct kbd_state *ks = &kdcn_state;
+
+ if (on) {
+ /* Entering debugger. */
fb_unblank();
+ /* Clear shift keys too. */
+ ks->kbd_modbits = 0;
+ } else {
+ /* Resuming kernel. */
+ }
}
+
+struct consdev consdev_kd = {
+ nullcnprobe,
+ kdcninit,
+ kdcngetc,
+ kdcnputc,
+ kdcnpollc,
+ makedev(KDMAJOR, 0),
+ CN_INTERNAL
+};
+
diff --git a/sys/arch/sun3/dev/ms.c b/sys/arch/sun3/dev/ms.c
deleted file mode 100644
index 4fb884c0f63..00000000000
--- a/sys/arch/sun3/dev/ms.c
+++ /dev/null
@@ -1,358 +0,0 @@
-/* $NetBSD: ms.c,v 1.6 1995/10/08 23:40:44 gwr Exp $ */
-
-/*
- * 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.
- *
- * @(#)ms.c 8.1 (Berkeley) 6/11/93
- */
-
-/*
- * Mouse driver.
- */
-
-#include <sys/param.h>
-#include <sys/conf.h>
-#include <sys/ioctl.h>
-#include <sys/kernel.h>
-#include <sys/proc.h>
-#include <sys/syslog.h>
-#include <sys/systm.h>
-#include <sys/tty.h>
-
-#include <machine/vuid_event.h>
-#include "event_var.h"
-
-/*
- * Mouse state. A Mouse Systems mouse is a fairly simple device,
- * producing five-byte blobs of the form:
- *
- * b dx dy dx dy
- *
- * where b is the button state, encoded as 0x80|(~buttons)---there are
- * three buttons (4=left, 2=middle, 1=right)---and dx,dy are X and Y
- * delta values, none of which have are in [0x80..0x87]. (This lets
- * us sync up with the mouse after an error.)
- */
-struct ms_softc {
- 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 */
- volatile int ms_ready; /* event queue is ready */
- struct evvar ms_events; /* event queue state */
-} ms_softc;
-
-/*
- * Attach the mouse serial (down-link) interface.
- */
-void
-ms_serial(tp, iopen, iclose)
- struct tty *tp;
- void (*iopen)(), (*iclose)();
-{
-
- ms_softc.ms_mouse = tp;
- ms_softc.ms_open = iopen;
- ms_softc.ms_close = iclose;
-}
-
-void
-ms_rint(c)
- 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, 2, 4, 4, 4, 4 };
- static const int to_id[] = { MS_RIGHT, MS_MIDDLE, 0, MS_LEFT };
-
- /*
- * Discard input if not ready. Drop sync on parity or framing
- * error; gain sync on button byte.
- */
- 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;
- }
- if ((unsigned)(c - 0x80) < 8) /* if in 0x80..0x87 */
- ms->ms_byteno = 0;
-
- /*
- * Run the decode loop, adding to the current information.
- * We add, rather than replace, deltas, so that if the event queue
- * fills, we accumulate data for when it opens up again.
- */
- switch (ms->ms_byteno) {
-
- case -1:
- return;
-
- case 0:
- /* buttons */
- ms->ms_byteno = 1;
- ms->ms_mb = (~c) & 0x7;
- return;
-
- case 1:
- /* first delta-x */
- ms->ms_byteno = 2;
- ms->ms_dx += (char)c;
- return;
-
- case 2:
- /* first delta-y */
- ms->ms_byteno = 3;
- ms->ms_dy += (char)c;
- return;
-
- case 3:
- /* second delta-x */
- ms->ms_byteno = 4;
- ms->ms_dx += (char)c;
- return;
-
- case 4:
- /* second delta-x */
- ms->ms_byteno = -1; /* wait for button-byte again */
- ms->ms_dy += (char)c;
- break;
-
- default:
- panic("ms_rint");
- /* NOTREACHED */
- }
-
- /*
- * We have at least one event (mouse button, delta-X, or
- * delta-Y; possibly all three, and possibly three separate
- * button events). Deliver these events until we are out
- * of changes or out of room. As events get delivered,
- * mark them `unchanged'.
- */
- any = 0;
- get = ms->ms_events.ev_get;
- put = ms->ms_events.ev_put;
- fe = &ms->ms_events.ev_q[put];
-
- /* NEXT prepares to put the next event, backing off if necessary */
-#define NEXT \
- if ((++put) % EV_QSIZE == get) { \
- put--; \
- goto out; \
- }
- /* ADVANCE completes the `put' of the event */
-#define ADVANCE \
- fe++; \
- if (put >= EV_QSIZE) { \
- put = 0; \
- fe = &ms->ms_events.ev_q[0]; \
- } \
- any = 1
-
- mb = ms->ms_mb;
- ub = ms->ms_ub;
- while ((d = mb ^ ub) != 0) {
- /*
- * Mouse button change. Convert up to three changes
- * to the `first' change, and drop it into the event queue.
- */
- NEXT;
- d = to_one[d - 1]; /* from 1..7 to {1,2,4} */
- fe->id = to_id[d - 1]; /* from {1,2,4} to ID */
- fe->value = mb & d ? VKEY_DOWN : VKEY_UP;
- fe->time = time;
- ADVANCE;
- ub ^= d;
- }
- if (ms->ms_dx) {
- NEXT;
- fe->id = LOC_X_DELTA;
- fe->value = ms->ms_dx;
- fe->time = time;
- ADVANCE;
- ms->ms_dx = 0;
- }
- if (ms->ms_dy) {
- NEXT;
- fe->id = LOC_Y_DELTA;
- fe->value = ms->ms_dy;
- fe->time = time;
- ADVANCE;
- ms->ms_dy = 0;
- }
-out:
- if (any) {
- ms->ms_ub = ub;
- ms->ms_events.ev_put = put;
- EV_WAKEUP(&ms->ms_events);
- }
-}
-
-int
-msopen(dev, flags, mode, p)
- dev_t dev;
- int flags, mode;
- struct proc *p;
-{
- int s, error;
- struct tty *tp;
-
-#if 1 /* XXX - temporary hack */
- /* XXX - Should make login chown devices in /etc/fbtab */
- /* Require root or same UID as the kd session leader. */
- if (p->p_ucred->cr_uid) {
- struct tty *kd_tp;
- struct proc *kd_p;
- extern struct tty *kdtty();
-
- /* Make sure kd is attached and open. */
- kd_tp = kdtty(0);
- if ((kd_tp == NULL) || (kd_tp->t_session == NULL))
- return (EPERM);
- kd_p = kd_tp->t_session->s_leader;
- if (p->p_ucred->cr_uid != kd_p->p_ucred->cr_uid)
- return (EACCES);
- }
-#endif
-
- /* This is an exclusive open device. */
- 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 */
-
- tp = ms_softc.ms_mouse;
- tp->t_ispeed = tp->t_ospeed = 1200;
- (*ms_softc.ms_open)(tp);
-
- ms_softc.ms_ready = 1; /* start accepting events */
- return (0);
-}
-
-int
-msclose(dev, flags, mode, p)
- dev_t dev;
- int flags, mode;
- struct proc *p;
-{
-
- 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);
-}
-
-int
-msread(dev, uio, flags)
- dev_t dev;
- struct uio *uio;
- int flags;
-{
-
- 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;
-{
- int s;
-
- 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);
- }
- return (ENOTTY);
-}
-
-int
-msselect(dev, rw, p)
- dev_t dev;
- int rw;
- struct proc *p;
-{
-
- return (ev_select(&ms_softc.ms_events, rw, p));
-}
diff --git a/sys/arch/sun3/dev/zs.c b/sys/arch/sun3/dev/zs.c
index 550f60b1d51..152b40b67f3 100644
--- a/sys/arch/sun3/dev/zs.c
+++ b/sys/arch/sun3/dev/zs.c
@@ -1,18 +1,8 @@
-/* $NetBSD: zs.c,v 1.30 1995/10/08 23:42:59 gwr Exp $ */
+/* $NetBSD: zs.c,v 1.31 1996/01/24 22:40:25 gwr Exp $ */
/*
- * 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.
+ * Copyright (c) 1995 Gordon W. Ross
+ * All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
@@ -22,38 +12,31 @@
* 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
+ * 3. The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ * 4. 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.
+ * This product includes software developed by Gordon Ross
*
- * @(#)zs.c 8.1 (Berkeley) 7/19/93
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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.
+ * Runs two serial lines per chip using slave drivers.
+ * Plain tty/async lines use the zs_async slave.
+ * Sun keyboard/mouse uses the zs_kbd/zs_ms slaves.
*/
-#define NZS 2 /* XXX */
#include <sys/param.h>
#include <sys/systm.h>
@@ -67,34 +50,22 @@
#include <sys/kernel.h>
#include <sys/syslog.h>
+#include <dev/cons.h>
+#include <dev/ic/z8530reg.h>
+#include <machine/z8530var.h>
+
#include <machine/autoconf.h>
#include <machine/cpu.h>
+#include <machine/eeprom.h>
#include <machine/isr.h>
#include <machine/obio.h>
#include <machine/mon.h>
-#include <machine/eeprom.h>
-#include <machine/kbd.h>
-
-#include <dev/cons.h>
-
-#include <dev/ic/z8530reg.h>
-#include <sun3/dev/zsvar.h>
/*
- * 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...
+ * XXX: Hard code this to make console init easier...
*/
-#undef TTYDEF_CFLAG
-#define TTYDEF_CFLAG (CREAD | CS8 | HUPCL)
-
-#ifdef KGDB
-#include <machine/remote-sl.h>
-#endif
-
-#define ZSMAJOR 12 /* XXX */
+#define NZS 2 /* XXX */
-#define ZS_KBD 2 /* XXX */
-#define ZS_MOUSE 3 /* XXX */
/* The Sun3 provides a 4.9152 MHz clock to the ZS chips. */
#define PCLK (9600 * 512) /* PCLK pin input clock rate */
@@ -105,80 +76,68 @@
#define ZSHARD_PRI 6 /* Wired on the CPU board... */
#define ZSSOFT_PRI 3 /* Want tty pri (4) but this is OK. */
-/*
- * 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 */
+
+/* The layout of this is hardware-dependent (padding, order). */
+struct zschan {
+ volatile u_char zc_csr; /* ctrl,status, and indirect access */
+ u_char zc_xxx0;
+ volatile u_char zc_data; /* data */
+ u_char zc_xxx1;
+};
+struct zsdevice {
+ /* Yes, they are backwards. */
+ struct zschan zs_chan_b;
+ struct zschan zs_chan_a;
};
-static struct tty *zs_tty[NZS * 2]; /* XXX should be dynamic */
-/* Definition of the driver for autoconfig. */
-static int zs_match(struct device *, void *, void *);
-static void zs_attach(struct device *, struct device *, void *);
-
-struct cfdriver zscd = {
- NULL, "zs", zs_match, zs_attach,
- DV_TTY, sizeof(struct zsinfo) };
-
-/* Interrupt handlers. */
-static int zshard(int);
-static int zssoft(int);
-
-struct zs_chanstate *zslist;
-
-/* Routines called from other code. */
-int zsopen(dev_t, int, int, struct proc *);
-int zsclose(dev_t, int, int, struct proc *);
-static void zsiopen(struct tty *);
-static void zsiclose(struct tty *);
-static void zsstart(struct tty *);
-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 *);
-static u_char zs_read(volatile struct zschan *, u_char);
-static u_char zs_write(volatile struct zschan *, u_char, u_char);
-
-/* Console stuff. */
-static volatile struct zschan *zs_conschan;
-
-#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 *);
-#endif
+/* Default OBIO addresses. */
+static int zs_physaddr[NZS] = { OBIO_KEYBD_MS, OBIO_ZS };
+/* Saved PROM mappings */
+static struct zsdevice *zsaddr[NZS]; /* See zs_init() */
+/* Flags from cninit() */
+static int zs_hwflags[NZS][2];
+/* Default speed for each channel */
+static int zs_defspeed[NZS][2] = {
+ { 1200, /* keyboard */
+ 1200 }, /* mouse */
+ { 9600, /* ttya */
+ 9600 }, /* ttyb */
+};
-/*
- * 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 */
+/* Find PROM mappings (for console support). */
+void zs_init()
+{
+ int i;
+
+ for (i = 0; i < NZS; i++) {
+ zsaddr[i] = (struct zsdevice *)
+ obio_find_mapping(zs_physaddr[i], OBIO_ZS_SIZE);
+ }
+}
+
-int zssoftpending; /* We have done isr_soft_request() */
+struct zschan *
+zs_get_chan_addr(zsc_unit, channel)
+ int zsc_unit, channel;
+{
+ struct zsdevice *addr;
+ struct zschan *zc;
-static struct zsdevice *zsaddr[NZS]; /* XXX, but saves work */
+ if (zsc_unit >= NZS)
+ return NULL;
+ addr = zsaddr[zsc_unit];
+ if (addr == NULL)
+ return NULL;
+ if (channel == 0) {
+ zc = &addr->zs_chan_a;
+ } else {
+ zc = &addr->zs_chan_b;
+ }
+ return (zc);
+}
-/* Default OBIO addresses. */
-static int zs_physaddr[NZS] = { OBIO_ZS, OBIO_KEYBD_MS };
static u_char zs_init_reg[16] = {
0, /* 0: CMD (reset, etc.) */
@@ -190,35 +149,44 @@ static u_char zs_init_reg[16] = {
0, /* 6: TXSYNC/SYNCLO */
0, /* 7: RXSYNC/SYNCHI */
0, /* 8: alias for data port */
- 0, /* 9: ZSWR9_MASTER_IE (later) */
+ ZSWR9_MASTER_IE,
0, /*10: Misc. TX/RX control bits */
ZSWR11_TXCLK_BAUD | ZSWR11_RXCLK_BAUD,
- 0, /*12: BAUDLO (later) */
- 0, /*13: BAUDHI (later) */
+ 14, /*12: BAUDLO (default=9600) */
+ 0, /*13: BAUDHI (default=9600) */
ZSWR14_BAUD_FROM_PCLK | ZSWR14_BAUD_ENA,
ZSWR15_BREAK_IE | ZSWR15_DCD_IE,
};
-/* Find PROM mappings (for console support). */
-void zs_init()
-{
- int i;
- for (i = 0; i < NZS; i++) {
- zsaddr[i] = (struct zsdevice *)
- obio_find_mapping(zs_physaddr[i], OBIO_ZS_SIZE);
- }
-}
+/****************************************************************
+ * Autoconfig
+ ****************************************************************/
+
+/* Definition of the driver for autoconfig. */
+static int zsc_match(struct device *, void *, void *);
+static void zsc_attach(struct device *, struct device *, void *);
+
+struct cfdriver zsccd = {
+ NULL, "zsc", zsc_match, zsc_attach,
+ DV_DULL, sizeof(struct zsc_softc), NULL,
+};
+
+static int zshard(void *);
+static int zssoft(void *);
+
/*
- * 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
-zs_match(struct device *parent, void *vcf, void *args)
+zsc_match(parent, vcf, aux)
+ struct device *parent;
+ void *vcf;
+ void *aux;
{
struct cfdata *cf = vcf;
- struct confargs *ca = args;
+ struct confargs *ca = aux;
int unit, x;
void *zsva;
@@ -226,6 +194,7 @@ zs_match(struct device *parent, void *vcf, void *args)
if (unit < 0 || unit >= NZS)
return (0);
+ /* Make sure zs_init() found mappings. */
zsva = zsaddr[unit];
if (zsva == NULL)
return (0);
@@ -240,279 +209,227 @@ zs_match(struct device *parent, void *vcf, void *args)
return (x != -1);
}
+static int
+zsc_print(aux, name)
+ void *aux;
+ char *name;
+{
+ struct zsc_attach_args *args = aux;
+
+ if (name != NULL)
+ printf("%s: ", name);
+
+ if (args->channel != -1)
+ printf(" channel %d", args->channel);
+
+ return UNCONF;
+}
+
/*
* 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?
+ * Match slave number to zs unit number, so that misconfiguration will
+ * not set up the keyboard as ttya, etc.
*/
static void
-zs_attach(struct device *parent, struct device *self, void *args)
-{
- struct cfdata *cf;
- struct confargs *ca;
- register int zs, unit;
- register struct zsinfo *zi;
- register struct zs_chanstate *cs;
- register volatile struct zsdevice *addr;
- register struct tty *tp, *ctp;
- int softcar;
+zsc_attach(parent, self, aux)
+ struct device *parent;
+ struct device *self;
+ void *aux;
+{
+ struct zsc_softc *zsc = (void *) self;
+ struct confargs *ca = aux;
+ struct zsc_attach_args zsc_args;
+ volatile struct zschan *zc;
+ struct zs_chanstate *cs;
+ int zsc_unit, channel;
+ int reset, s;
static int didintr;
- cf = self->dv_cfdata;
- zs = self->dv_unit;
- ca = args;
+ zsc_unit = zsc->zsc_dev.dv_unit;
printf(" softpri %d\n", ZSSOFT_PRI);
- if (zsaddr[zs] == NULL)
- panic("zs_attach: zs%d not mapped\n", zs);
- addr = zsaddr[zs];
+ /* Use the mapping setup by the Sun PROM. */
+ if (zsaddr[zsc_unit] == NULL)
+ panic("zs_attach: zs%d not mapped\n", zsc_unit);
- if (!didintr) {
- didintr = 1;
- isr_add_autovect(zssoft, NULL, ZSSOFT_PRI);
- isr_add_autovect(zshard, NULL, ZSHARD_PRI);
- }
+ /*
+ * Initialize software state for each channel.
+ */
+ for (channel = 0; channel < 2; channel++) {
+ cs = &zsc->zsc_cs[channel];
- zi = (struct zsinfo *)self;
- zi->zi_zs = addr;
- unit = zs * 2;
- cs = zi->zi_cs;
- softcar = cf->cf_flags;
-
- if(!zs_tty[unit])
- zs_tty[unit] = ttymalloc();
- if(!zs_tty[unit+1])
- zs_tty[unit+1] = 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;
-
- tp = zs_tty[unit];
- cs->cs_unit = unit;
- cs->cs_zc = &addr->zs_chan[ZS_CHAN_A];
- cs->cs_speed = zs_getspeed(cs->cs_zc);
-#ifdef DEBUG
- mon_printf("zs%da speed %d ", zs, cs->cs_speed);
-#endif
- cs->cs_softcar = softcar & 1;
- cs->cs_ttyp = tp;
- tp->t_dev = makedev(ZSMAJOR, unit);
- tp->t_oproc = zsstart;
- tp->t_param = zsparam;
- if (cs->cs_zc == zs_conschan) {
- /* This unit is the console. */
- cs->cs_consio = 1;
- cs->cs_brkabort = 1;
- cs->cs_softcar = 1;
- /* Call zsparam so interrupts get enabled. */
- tp->t_ispeed = tp->t_ospeed = cs->cs_speed;
- tp->t_cflag = TTYDEF_CFLAG;
- (void) zsparam(tp, &tp->t_termios);
- } else {
- /* Can not run kgdb on the console? */
-#ifdef KGDB
- zs_checkkgdb(unit, cs, tp);
-#endif
- }
-#if 0
- /* XXX - Drop carrier here? -gwr */
- zs_modem(cs, cs->cs_softcar ? 1 : 0);
-#endif
+ zc = zs_get_chan_addr(zsc_unit, channel);
+ cs->cs_reg_csr = &zc->zc_csr;
+ cs->cs_reg_data = &zc->zc_data;
+
+ cs->cs_channel = channel;
+ cs->cs_private = NULL;
+ cs->cs_ops = &zsops_null;
+
+ /* Define BAUD rate clock for the MI code. */
+ cs->cs_pclk_div16 = PCLK / 16;
+
+ /* XXX: get defspeed from EEPROM instead? */
+ cs->cs_defspeed = zs_defspeed[zsc_unit][channel];
+
+ bcopy(zs_init_reg, cs->cs_creg, 16);
+ bcopy(zs_init_reg, cs->cs_preg, 16);
- if (unit == ZS_KBD) {
/*
- * Keyboard: tell /dev/kbd driver how to talk to us.
+ * Clear the master interrupt enable.
+ * The INTENA is common to both channels,
+ * so just do it on the A channel.
*/
- tp->t_ispeed = tp->t_ospeed = cs->cs_speed;
- tp->t_cflag = CS8;
- /* zsparam called by zsiopen */
- 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_zc = &addr->zs_chan[ZS_CHAN_B];
- cs->cs_speed = zs_getspeed(cs->cs_zc);
-#ifdef DEBUG
- mon_printf("zs%db speed %d\n", zs, cs->cs_speed);
-#endif
- cs->cs_softcar = softcar & 2;
- cs->cs_ttyp = tp;
- tp->t_dev = makedev(ZSMAJOR, unit);
- tp->t_oproc = zsstart;
- tp->t_param = zsparam;
- if (cs->cs_zc == zs_conschan) {
- /* This unit is the console. */
- cs->cs_consio = 1;
- cs->cs_brkabort = 1;
- cs->cs_softcar = 1;
- tp->t_ispeed = tp->t_ospeed = cs->cs_speed;
- tp->t_cflag = TTYDEF_CFLAG;
- (void) zsparam(tp, &tp->t_termios);
- } else {
- /* Can not run kgdb on the console? */
-#ifdef KGDB
- zs_checkkgdb(unit, cs, tp);
-#endif
- }
-#if 0
- /* XXX - Drop carrier here? -gwr */
- zs_modem(cs, cs->cs_softcar ? 1 : 0);
-#endif
+ if (channel == 0) {
+ ZS_WRITE(cs, 9, 0);
+ }
- if (unit == ZS_MOUSE) {
/*
- * Mouse: tell /dev/mouse driver how to talk to us.
+ * Look for a child driver for this channel.
+ * The child attach will setup the hardware.
*/
- tp->t_ispeed = tp->t_ospeed = cs->cs_speed;
- tp->t_cflag = CS8;
- /* zsparam called by zsiopen */
- ms_serial(tp, zsiopen, zsiclose);
+ zsc_args.channel = channel;
+ zsc_args.hwflags = zs_hwflags[zsc_unit][channel];
+ if (!config_found(self, (void *) &zsc_args, zsc_print)) {
+ /* No sub-driver. Just reset it. */
+ reset = (channel == 0) ?
+ ZSWR9_A_RESET : ZSWR9_B_RESET;
+ s = splzs();
+ ZS_WRITE(cs, 9, reset);
+ splx(s);
+ }
}
-}
-/*
- * XXX - Temporary hack...
- */
-struct tty *
-zstty(dev)
- dev_t dev;
-{
- int unit = minor(dev);
+ /* Now safe to install interrupt handlers */
+ if (!didintr) {
+ didintr = 1;
+ isr_add_autovect(zssoft, NULL, ZSSOFT_PRI);
+ isr_add_autovect(zshard, NULL, ZSHARD_PRI);
+ }
- return (zs_tty[unit]);
+ /*
+ * Set the master interrupt enable and interrupt vector.
+ * (common to both channels, do it on A)
+ */
+ cs = &zsc->zsc_cs[0];
+ s = splzs();
+ /* interrupt vector */
+ ZS_WRITE(cs, 2, zs_init_reg[2]);
+ /* master interrupt control (enable) */
+ ZS_WRITE(cs, 9, zs_init_reg[9]);
+ splx(s);
}
-/*
- * Put a channel in a known state. Interrupts may be left disabled
- * or enabled, as desired. (Used only by kgdb)
- */
-static void
-zs_reset(zc, inten, speed)
- volatile struct zschan *zc;
- int inten, speed;
+static int
+zshard(arg)
+ void *arg;
{
- int tconst;
- u_char reg[16];
-
- bcopy(zs_init_reg, reg, 16);
- if (inten)
- reg[9] |= ZSWR9_MASTER_IE;
-
- tconst = BPS_TO_TCONST(PCLK / 16, speed);
- reg[12] = tconst;
- reg[13] = tconst >> 8;
- zs_loadchannelregs(zc, reg);
+ struct zsc_softc *zsc;
+ int unit, rval;
+
+ /* Do ttya/ttyb first, because they go faster. */
+ rval = 0;
+ unit = zsccd.cd_ndevs;
+ while (--unit >= 0) {
+ zsc = zsccd.cd_devs[unit];
+ if (zsc != NULL) {
+ rval |= zsc_intr_hard(zsc);
+ }
+ }
+ return (rval);
}
-/*
- * Console support
- */
+int zssoftpending;
-/*
- * Used by the kd driver to find out if it can work.
- */
-int
-zscnprobe_kbd()
-{
- if (zsaddr[1] == NULL) {
- mon_printf("zscnprobe_kbd: zs1 not yet mapped\n");
- return CN_DEAD;
+void
+zsc_req_softint(zsc)
+ struct zsc_softc *zsc;
+{
+ if (zssoftpending == 0) {
+ /* We are at splzs here, so no need to lock. */
+ zssoftpending = ZSSOFT_PRI;
+ isr_soft_request(ZSSOFT_PRI);
}
- return CN_INTERNAL;
}
-/*
- * This is the console probe routine for ttya and ttyb.
- */
static int
-zscnprobe(struct consdev *cn, int unit)
+zssoft(arg)
+ void *arg;
{
- int maj;
-
- if (zsaddr[0] == NULL) {
- mon_printf("zscnprobe: zs0 not mapped\n");
- cn->cn_pri = CN_DEAD;
- return 0;
- }
- /* XXX - Also try to make sure it exists? */
-
- /* locate the major number */
- for (maj = 0; maj < nchrdev; maj++)
- if (cdevsw[maj].d_open == (void*)zsopen)
- break;
+ struct zsc_softc *zsc;
+ int unit;
- cn->cn_dev = makedev(maj, unit);
+ /* This is not the only ISR on this IPL. */
+ if (zssoftpending == 0)
+ return (0);
- /* Use EEPROM console setting to decide "remote" console. */
- /* Note: EE_CONS_TTYA + 1 == EE_CONS_TTYB */
- if (ee_console == (EE_CONS_TTYA + unit)) {
- cn->cn_pri = CN_REMOTE;
- } else {
- cn->cn_pri = CN_NORMAL;
+ /*
+ * The soft intr. bit will be set by zshard only if
+ * the variable zssoftpending is zero. The order of
+ * these next two statements prevents our clearing
+ * the soft intr bit just after zshard has set it.
+ */
+ isr_soft_clear(ZSSOFT_PRI);
+ zssoftpending = 0;
+
+ /* Do ttya/ttyb first, because they go faster. */
+ unit = zsccd.cd_ndevs;
+ while (--unit >= 0) {
+ zsc = zsccd.cd_devs[unit];
+ if (zsc != NULL) {
+ (void) zsc_intr_soft(zsc);
+ }
}
- return (0);
+ return (1);
}
-/* This is the constab entry for TTYA. */
-int
-zscnprobe_a(struct consdev *cn)
-{
- return (zscnprobe(cn, 0));
-}
-/* This is the constab entry for TTYB. */
-int
-zscnprobe_b(struct consdev *cn)
-{
- return (zscnprobe(cn, 1));
-}
+/*
+ * Read or write the chip with suitable delays.
+ */
-/* Called by kdcninit() or below. */
-void
-zs_set_conschan(unit, ab)
- int unit, ab;
+u_char
+zs_read_reg(cs, reg)
+ struct zs_chanstate *cs;
+ u_char reg;
{
- volatile struct zsdevice *addr;
+ u_char val;
- addr = zsaddr[unit];
- zs_conschan = ((ab == 0) ?
- &addr->zs_chan[ZS_CHAN_A] :
- &addr->zs_chan[ZS_CHAN_B] );
+ *cs->cs_reg_csr = reg;
+ ZS_DELAY();
+ val = *cs->cs_reg_csr;
+ ZS_DELAY();
+ return val;
}
-/* Attach as console. Also set zs_conschan */
-int
-zscninit(struct consdev *cn)
+void
+zs_write_reg(cs, reg, val)
+ struct zs_chanstate *cs;
+ u_char reg, val;
{
- int ab = minor(cn->cn_dev) & 1;
- zs_set_conschan(0, ab);
- mon_printf("console on zs0 (tty%c)\n", 'a' + ab);
+ *cs->cs_reg_csr = reg;
+ ZS_DELAY();
+ *cs->cs_reg_csr = val;
+ ZS_DELAY();
}
+/****************************************************************
+ * Console support functions (Sun3 specific!)
+ ****************************************************************/
/*
- * Polled console input putchar.
+ * Polled input char.
*/
int
-zscngetc(dev)
- dev_t dev;
+zs_getc(arg)
+ void *arg;
{
- register volatile struct zschan *zc = zs_conschan;
+ register volatile struct zschan *zc = arg;
register int s, c, rr0;
- if (zc == NULL)
- return (0);
-
s = splhigh();
-
/* Wait for a character to arrive. */
do {
rr0 = zc->zc_csr;
@@ -521,7 +438,6 @@ zscngetc(dev)
c = zc->zc_data;
ZS_DELAY();
-
splx(s);
/*
@@ -532,24 +448,17 @@ zscngetc(dev)
}
/*
- * Polled console output putchar.
+ * Polled output char.
*/
-int
-zscnputc(dev, c)
- dev_t dev;
+void
+zs_putc(arg, c)
+ void *arg;
int c;
{
- register volatile struct zschan *zc = zs_conschan;
+ register volatile struct zschan *zc = arg;
register int s, rr0;
- if (zc == NULL) {
- s = splhigh();
- mon_putchar(c);
- splx(s);
- return (0);
- }
s = splhigh();
-
/* Wait for transmitter to become ready. */
do {
rr0 = zc->zc_csr;
@@ -561,1105 +470,132 @@ zscnputc(dev, c)
splx(s);
}
-#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(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));
-}
-
+extern struct consdev consdev_kd; /* keyboard/display */
+extern struct consdev consdev_tty;
+extern struct consdev *cn_tab; /* physical console device info */
+extern void nullcnpollc();
-/*
- * 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;
-}
+void *zs_conschan;
/*
- * Do an internal close. Eventually we should shut off the chip when both
- * ports on it are closed.
+ * This function replaces sys/dev/cninit.c
+ * Determine which device is the console using
+ * the "console" byte from the EEPROM.
*/
-static void
-zsiclose(tp)
- struct tty *tp;
+void
+cninit()
{
+ struct zschan *zc;
+ struct consdev *cn;
+ int zsc_unit, channel;
- ttylclose(tp, 0); /* ??? */
- ttyclose(tp); /* ??? */
- tp->t_state = 0;
-}
+ switch (ee_console) {
+ case EE_CONS_TTYA:
+ case EE_CONS_TTYB:
+ zsc_unit = 1;
+ channel = (ee_console & 1);
+ cn = &consdev_tty;
+ cn->cn_dev = makedev(ZSTTY_MAJOR, channel);
+ cn->cn_pri = CN_REMOTE;
+ break;
-/*
- * 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;
-{
- register struct tty *tp;
- register struct zs_chanstate *cs;
- struct zsinfo *zi;
- int unit = minor(dev), zs = unit >> 1, error, s;
-
-#ifdef DEBUG
- mon_printf("zs_open\n");
-#endif
- if (zs >= zscd.cd_ndevs || (zi = zscd.cd_devs[zs]) == NULL ||
- unit == ZS_KBD || unit == ZS_MOUSE)
- return (ENXIO);
- cs = &zi->zi_cs[unit & 1];
- tp = cs->cs_ttyp;
- s = spltty();
- if ((tp->t_state & TS_ISOPEN) == 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);
- } else if (tp->t_state & TS_XCLUDE && p->p_ucred->cr_uid != 0) {
- splx(s);
- return (EBUSY);
- }
- error = 0;
-#ifdef DEBUG
- mon_printf("wait for carrier...\n");
-#endif
- for (;;) {
- register int rr0;
-
- /* loop, turning on the device, until carrier present */
- zs_modem(cs, 1);
- /* May never get status intr if carrier already on. -gwr */
- rr0 = cs->cs_zc->zc_csr;
- ZS_DELAY();
- if (rr0 & ZSRR0_DCD)
- tp->t_state |= TS_CARR_ON;
- if (cs->cs_softcar)
- tp->t_state |= TS_CARR_ON;
- if (flags & O_NONBLOCK || tp->t_cflag & CLOCAL ||
- tp->t_state & TS_CARR_ON)
- break;
- tp->t_state |= TS_WOPEN;
- if (error = ttysleep(tp, (caddr_t)&tp->t_rawq, TTIPRI | PCATCH,
- ttopen, 0)) {
- if (!(tp->t_state & TS_ISOPEN)) {
- zs_modem(cs, 0);
- tp->t_state &= ~TS_WOPEN;
- ttwakeup(tp);
- }
- splx(s);
- return error;
- }
+ default:
+ mon_printf("cninit: unknown eeprom console setting\n");
+ /* assume keyboard/display */
+ /* fallthrough */
+ case EE_CONS_BW:
+ case EE_CONS_COLOR:
+ case EE_CONS_P4OPT:
+ zsc_unit = 0;
+ channel = 0;
+ cn = &consdev_kd;
+ /* Set cn_dev, cn_pri in kd.c */
+ break;
}
-#ifdef DEBUG
- mon_printf("...carrier %s\n",
- (tp->t_state & TS_CARR_ON) ? "on" : "off");
-#endif
- splx(s);
- if (error == 0)
- error = linesw[tp->t_line].l_open(dev, tp);
- if (error)
- zs_modem(cs, 0);
- return (error);
-}
-/*
- * Close a zs serial port.
- */
-int
-zsclose(dev, flags, mode, p)
- dev_t dev;
- int flags;
- int mode;
- struct proc *p;
-{
- register struct zs_chanstate *cs;
- register struct tty *tp;
- struct zsinfo *zi;
- int unit = minor(dev), s;
-
-#ifdef DEBUG
- mon_printf("zs_close\n");
-#endif
- zi = zscd.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_cflag & HUPCL || tp->t_state & TS_WOPEN ||
- (tp->t_state & TS_ISOPEN) == 0) {
- zs_modem(cs, 0);
- /* hold low for 1 second */
- (void) tsleep((caddr_t)cs, TTIPRI, ttclos, hz);
- }
- if (cs->cs_creg[5] & ZSWR5_BREAK)
- {
- 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);
- }
- 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);
+ zc = zs_get_chan_addr(zsc_unit, channel);
+ if (zc == NULL) {
+ mon_printf("cninit: zs not mapped.\n");
+ return;
}
-#endif
- return (0);
+ zs_conschan = zc;
+ zs_hwflags[zsc_unit][channel] = ZS_HWFLAG_CONSOLE;
+ cn_tab = cn;
+ (*cn->cn_init)(cn);
}
-/*
- * Read/write zs serial port.
- */
-int
-zsread(dev, uio, flags)
- dev_t dev;
- struct uio *uio;
- int flags;
-{
- register struct tty *tp = zs_tty[minor(dev)];
- return (linesw[tp->t_line].l_read(tp, uio, flags));
+/* We never call this. */
+void
+nullcnprobe(cn)
+ struct consdev *cn;
+{
}
-int
-zswrite(dev, uio, flags)
- dev_t dev;
- struct uio *uio;
- int flags;
+void
+zscninit(cn)
+ struct consdev *cn;
{
- register struct tty *tp = zs_tty[minor(dev)];
+ int unit = minor(cn->cn_dev) & 1;
- return (linesw[tp->t_line].l_write(tp, uio, flags));
+ mon_printf("console is zstty%d (tty%c)\n",
+ unit, unit + 'a');
}
/*
- * 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.
+ * Polled console input putchar.
*/
-/* ARGSUSED */
int
-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;
- static int zsrint(struct zs_chanstate *, volatile struct zschan *);
- static int zsxint(struct zs_chanstate *, volatile struct zschan *);
- static int zssint(struct zs_chanstate *, volatile struct zschan *);
-
- for (a = zslist; a != NULL; a = b->cs_next) {
- rr3 = ZS_READ(a->cs_zc, 3);
-
- /* XXX - This should loop to empty the on-chip fifo. */
- 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;
- }
- 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;
- }
-
- /* XXX - This should loop to empty the on-chip fifo. */
- 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;
- }
- 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 (zssoftpending == 0) {
- /* We are at splzs here, so no need to lock. */
- zssoftpending = ZSSOFT_PRI;
- isr_soft_request(ZSSOFT_PRI);
- }
- }
- return (intflags & 2);
-}
-
-static int
-zsrint(cs, zc)
- register struct zs_chanstate *cs;
- register volatile struct zschan *zc;
+zscngetc(dev)
+ dev_t dev;
{
+ register volatile struct zschan *zc = zs_conschan;
register int c;
- c = zc->zc_data;
- ZS_DELAY();
-
- 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();
- /* Debugger done. Send L1-up in case X is running. */
- conk->conk_l1 = 0;
- c = (KBD_L1|KBD_UP);
- }
- }
-#ifdef KGDB
- if (c == FRAME_START && cs->cs_kgdb &&
- (cs->cs_ttyp->t_state & TS_ISOPEN) == 0) {
- zskgdb(cs->cs_unit);
- c = 0;
- goto clearit;
- }
-#endif
- /* compose receive character and status */
- c <<= 8;
- c |= ZS_READ(zc, 1);
- c = ZRING_MAKE(ZRING_RINT, c);
-
-clearit:
- /* clear receive error & interrupt condition */
- zc->zc_csr = ZSWR0_RESET_ERRORS;
- ZS_DELAY();
- zc->zc_csr = ZSWR0_CLR_INTR;
- ZS_DELAY();
+ c = zs_getc(zc);
return (c);
}
-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) {
- /* Wait for end of break to avoid PROM abort. */
- do {
- rr0 = zc->zc_csr;
- ZS_DELAY();
- } while (rr0 & ZSRR0_BREAK);
- zsabort();
- return (0);
- }
- return (ZRING_MAKE(ZRING_SINT, rr0));
-}
-
-zsabort()
-{
- /* XXX - Always available, but may be the PROM monitor. */
- Debugger();
-}
-
-#ifdef KGDB
/*
- * KGDB framing character received: enter kernel debugger. This probably
- * should time out after a few seconds to avoid hanging on spurious input.
- */
-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);
- }
-}
-
-/*
- * ZS software interrupt. Scan all channels for deferred interrupts.
+ * Polled console output putchar.
*/
-int
-zssoft(arg)
- int 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;
-
- /* This is not the only ISR on this IPL. */
- if (zssoftpending == 0)
- return (0);
-
- /*
- * The soft intr. bit will be set by zshard only if
- * the variable zssoftpending is zero. The order of
- * these next two statements prevents our clearing
- * the soft intr bit just after zshard has set it.
- */
- isr_soft_clear(ZSSOFT_PRI);
- zssoftpending = 0; /* Now zshard may set it again. */
-
- 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 */
- continue;
- 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
- */
- if (unit == ZS_KBD)
- kbd_rint(cc);
- 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;
- }
- return (1);
-}
-
-int
-zsioctl(dev, cmd, data, flag, p)
+void
+zscnputc(dev, c)
dev_t dev;
- u_long cmd;
- caddr_t data;
- int flag;
- struct proc *p;
+ int c;
{
- int unit = minor(dev);
- struct zsinfo *zi = zscd.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_zc == zs_conschan))
- {
- 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;
+ register volatile struct zschan *zc = zs_conschan;
- case TIOCMSET:
- case TIOCMBIS:
- case TIOCMBIC:
- case TIOCMGET:
- default:
- return (ENOTTY);
- }
- return (0);
+ zs_putc(zc, c);
}
-/*
- * Start or restart transmission.
- */
-static void
-zsstart(tp)
- register struct tty *tp;
-{
- register struct zs_chanstate *cs;
- register int s, nch;
- int unit = minor(tp->t_dev);
- struct zsinfo *zi = zscd.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);
- }
+struct consdev consdev_tty = {
+ nullcnprobe,
+ zscninit,
+ zscngetc,
+ zscnputc,
+ nullcnpollc,
+};
- 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.
+ * Handle user request to enter kernel debugger.
*/
void
-zsstop(tp, flag)
- register struct tty *tp;
- int flag;
-{
- register struct zs_chanstate *cs;
- register int s, unit = minor(tp->t_dev);
- struct zsinfo *zi = zscd.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.
- */
-static int
-zsparam(tp, t)
- register struct tty *tp;
- register struct termios *t;
-{
- int unit = minor(tp->t_dev);
- struct zsinfo *zi = zscd.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 4.9 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();
- bcopy(zs_init_reg, cs->cs_preg, 16);
- cs->cs_preg[12] = tmp;
- cs->cs_preg[13] = tmp >> 8;
- cs->cs_preg[9] |= ZSWR9_MASTER_IE;
- 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;
-
- /*
- * 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)
- struct zs_chanstate *cs;
- int onoff;
-{
- 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);
-}
-
-/*
- * 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.
- */
-static void
-zs_loadchannelregs(zc, reg)
- volatile struct zschan *zc;
- u_char *reg;
-{
- int i;
-
- zc->zc_csr = ZSM_RESET_ERR; /* reset error condition */
- ZS_DELAY();
-
-#if 1 /* XXX - Is this really a good idea? -gwr */
- i = zc->zc_data; /* drain fifo */
- ZS_DELAY();
- i = zc->zc_data;
- ZS_DELAY();
- i = zc->zc_data;
- ZS_DELAY();
-#endif
-
- /* baud clock divisor, stop bits, parity */
- ZS_WRITE(zc, 4, reg[4]);
-
- /* misc. TX/RX control bits */
- ZS_WRITE(zc, 10, reg[10]);
-
- /* char size, enable (RX/TX) */
- ZS_WRITE(zc, 3, reg[3] & ~ZSWR3_RX_ENABLE);
- ZS_WRITE(zc, 5, reg[5] & ~ZSWR5_TX_ENABLE);
-
- /* interrupt enables: TX, TX, STATUS */
- ZS_WRITE(zc, 1, reg[1]);
-
- /* interrupt vector */
- ZS_WRITE(zc, 2, reg[2]);
-
- /* master interrupt control */
- ZS_WRITE(zc, 9, reg[9]);
-
- /* clock mode control */
- ZS_WRITE(zc, 11, reg[11]);
-
- /* baud rate (lo/hi) */
- ZS_WRITE(zc, 12, reg[12]);
- ZS_WRITE(zc, 13, reg[13]);
-
- /* Misc. control bits */
- ZS_WRITE(zc, 14, reg[14]);
-
- /* which lines cause status interrupts */
- ZS_WRITE(zc, 15, reg[15]);
-
- /* char size, enable (RX/TX)*/
- ZS_WRITE(zc, 3, reg[3]);
- ZS_WRITE(zc, 5, reg[5]);
-}
-
-static u_char
-zs_read(zc, reg)
- volatile struct zschan *zc;
- u_char reg;
-{
- u_char val;
-
- zc->zc_csr = reg;
- ZS_DELAY();
- val = zc->zc_csr;
- ZS_DELAY();
- return val;
-}
-
-static u_char
-zs_write(zc, reg, val)
- volatile struct zschan *zc;
- u_char reg, val;
-{
- zc->zc_csr = reg;
- ZS_DELAY();
- zc->zc_csr = val;
- ZS_DELAY();
- return val;
-}
-
-#ifdef KGDB
-/*
- * Get a character from the given kgdb channel. Called at splhigh().
- * XXX - Add delays, or combine with zscngetc()...
- */
-static int
-zs_kgdb_getc(arg)
- void *arg;
-{
- register volatile struct zschan *zc = (volatile struct zschan *)arg;
- register int c, rr0;
-
- do {
- rr0 = zc->zc_csr;
- ZS_DELAY();
- } while ((rr0 & ZSRR0_RX_READY) == 0);
- c = zc->zc_data;
- ZS_DELAY();
- return (c);
-}
-
-/*
- * Put a character to the given kgdb channel. Called at splhigh().
- */
-static void
-zs_kgdb_putc(arg, c)
- void *arg;
- int c;
+zs_abort()
{
- register volatile struct zschan *zc = (volatile struct zschan *)arg;
- register int c, rr0;
+ register volatile struct zschan *zc = zs_conschan;
+ int rr0;
+ /* Wait for end of break to avoid PROM abort. */
+ /* XXX - Limit the wait? */
do {
rr0 = zc->zc_csr;
ZS_DELAY();
- } while ((rr0 & ZSRR0_TX_READY) == 0);
- zc->zc_data = c;
- ZS_DELAY();
-}
-
-/*
- * Set up for kgdb; called at boot time before configuration.
- * KGDB interrupts will be enabled later when zs0 is configured.
- */
-void
-zs_kgdb_init()
-{
- volatile struct zsdevice *addr;
- volatile struct zschan *zc;
- int unit, zs;
+ } while (rr0 & ZSRR0_BREAK);
- if (major(kgdb_dev) != ZSMAJOR)
- return;
- unit = minor(kgdb_dev);
- /*
- * Unit must be 0 or 1 (zs0).
- */
- if ((unsigned)unit >= ZS_KBD) {
- printf("zs_kgdb_init: bad minor dev %d\n", unit);
- return;
- }
- zs = unit >> 1;
- unit &= 1;
-
- if (zsaddr[0] == NULL)
- panic("kbdb_attach: zs0 not yet mapped");
- addr = zsaddr[0];
-
- 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);
+ /* XXX - Always available, but may be the PROM monitor. */
+ Debugger();
}
-#endif /* KGDB */
diff --git a/sys/arch/sun3/dev/zs_kgdb.c b/sys/arch/sun3/dev/zs_kgdb.c
new file mode 100644
index 00000000000..5793efa529a
--- /dev/null
+++ b/sys/arch/sun3/dev/zs_kgdb.c
@@ -0,0 +1,277 @@
+
+/*
+ * 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.
+ *
+ * @(#)zs.c 8.1 (Berkeley) 7/19/93
+ */
+
+/*
+ * Hooks for kgdb when attached vi the z8530 driver
+ * XXX - not tested yet...
+ */
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/proc.h>
+#include <sys/device.h>
+#include <sys/conf.h>
+#include <sys/ioctl.h>
+#include <sys/kernel.h>
+#include <sys/syslog.h>
+
+#include <dev/ic/z8530reg.h>
+#include <machine/z8530var.h>
+
+#include <machine/remote-sl.h>
+
+/* The Sun3 provides a 4.9152 MHz clock to the ZS chips. */
+#define PCLK (9600 * 512) /* PCLK pin input clock rate */
+
+extern int kgdb_dev;
+extern int kgdb_rate;
+
+struct zschan * zs_get_chan_addr __P((int zsc_unit, int channel));
+
+extern int zs_getc __P((void *arg));
+extern void zs_putc __P((void *arg, int c));
+
+struct zsops zsops_kgdb;
+
+static u_char zs_kgdb_regs[16] = {
+ 0, /* 0: CMD (reset, etc.) */
+ ZSWR1_RIE, /* NOT: (ZSWR1_TIE | ZSWR1_SIE) */
+ 0x18 + ZSHARD_PRI, /* 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,
+ 0, /*10: Misc. TX/RX control bits */
+ ZSWR11_TXCLK_BAUD | ZSWR11_RXCLK_BAUD,
+ 14, /*12: BAUDLO (default=9600) */
+ 0, /*13: BAUDHI (default=9600) */
+ ZSWR14_BAUD_FROM_PCLK | ZSWR14_BAUD_ENA,
+ ZSWR15_BREAK_IE | ZSWR15_DCD_IE,
+};
+
+static void
+zs_setparam(cs, iena, rate)
+ struct zs_chanstate *cs;
+ int iena;
+ int rate;
+{
+ int s, tconst;
+
+ bcopy(zs_kgdb_regs, cs->cs_preg, 16);
+
+ if (iena == 0) {
+ cs->cs_preg[1] = 0;
+ }
+
+ /* Initialize the speed, etc. */
+ tconst = BPS_TO_TCONST(cs->cs_pclk_div16, rate);
+ cs->cs_preg[5] |= ZSWR5_DTR | ZSWR5_RTS;
+ cs->cs_preg[12] = tconst;
+ cs->cs_preg[13] = tconst >> 8;
+
+ s = splhigh();
+ zs_loadchannelregs(cs);
+ splx(s);
+
+
+/*
+ * Set up for kgdb; called at boot time before configuration.
+ * KGDB interrupts will be enabled later when zs0 is configured.
+ */
+void
+zs_kgdb_init()
+{
+ struct zs_chanstate cs;
+ volatile struct zschan *zc;
+ int channel, zsc_unit;
+
+ if (major(kgdb_dev) != ZSMAJOR)
+ return;
+
+ zsc_unit = 1; /* XXX */
+ channel = minor(kgdb_dev) & 1;
+ printf("zs_kgdb_init: attaching zstty%d at %d baud\n",
+ channel, kgdb_rate);
+
+ /* Setup temporary chanstate. */
+ bzero((caddr_t)&cs, sizeof(cs));
+ zc = zs_get_chan_addr(zsc_unit, channel);
+ cs.cs_reg_csr = &zc->zc_csr;
+ cs.cs_reg_data = &zc->zc_data;
+ cs.cs_channel = channel;
+ cs.cs_pclk_div16 = PCLK / 16;
+
+ /* Now set parameters. (interrupts disabled) */
+ zs_setparam(&cs, 0, kgdb_rate);
+
+ /* Store the getc/putc functions and arg. */
+ kgdb_attach(zs_getc, zs_putc, (void *)zc);
+}
+
+/*
+ * This is a "hook" called by zstty_attach to allow the tty
+ * to be "taken over" for exclusive use by kgdb.
+ * Return non-zero if this is the kgdb port.
+ *
+ * Set the speed to kgdb_rate, CS8, etc.
+ */
+int
+zs_check_kgdb(cs, dev)
+ struct zs_chanstate *cs;
+ int dev;
+{
+ int tconst;
+
+ if (dev != kgdb_dev)
+ return (0);
+
+ /*
+ * Yes, this is the kgdb port. Finish the autoconfig
+ * message and set up the port for our exclusive use.
+ */
+ printf(" (kgdb,%d)\n", kgdb_rate);
+
+ cs->cs_private = NULL;
+ cs->cs_ops = &zsops_kgdb;
+
+ /* Now set parameters. (interrupts enabled) */
+ zs_setparam(&cs, 1, kgdb_rate);
+
+ return (1);
+}
+
+/*
+ * KGDB framing character received: enter kernel debugger. This probably
+ * should time out after a few seconds to avoid hanging on spurious input.
+ */
+zskgdb()
+{
+ unit = minor(kgdb_dev);
+
+ printf("zstty%d: kgdb interrupt\n", unit);
+ /* This will trap into the debugger. */
+ kgdb_connect(1);
+}
+
+
+/****************************************************************
+ * Interface to the lower layer (zscc)
+ ****************************************************************/
+
+int kgdb_input_lost;
+
+static int
+zs_kgdb_rxint(cs)
+ register struct zs_chanstate *cs;
+{
+ register u_char c, rr1;
+
+ /* Read the input data ASAP. */
+ c = *(cs->cs_reg_data);
+ ZS_DELAY();
+
+ /* Save the status register too. */
+ rr1 = ZS_READ(cs, 1);
+
+ if (rr1 & (ZSRR1_FE | ZSRR1_DO | ZSRR1_PE)) {
+ /* Clear the receive error. */
+ *(cs->cs_reg_csr) = ZSWR0_RESET_ERRORS;
+ ZS_DELAY();
+ }
+
+ if (c == FRAME_START) {
+ zskgdb();
+ } else {
+ kgdb_input_lost++;
+ }
+
+ return(0);
+}
+
+static int
+zs_kgdb_txint(cs)
+ register struct zs_chanstate *cs;
+{
+ register int count, rval;
+
+ *(cs->cs_reg_csr) = ZSWR0_RESET_TXINT;
+ ZS_DELAY();
+
+ return (0);
+}
+
+static int
+zs_kgdb_stint(cs)
+ register struct zs_chanstate *cs;
+{
+ register int rr0;
+
+ rr0 = *(cs->cs_reg_csr);
+ ZS_DELAY();
+
+ *(cs->cs_reg_csr) = ZSWR0_RESET_STATUS;
+ ZS_DELAY();
+
+ return (0);
+}
+
+static int
+zs_kgdb_softint(cs)
+ struct zs_chanstate *cs;
+{
+ printf("zs_kgdb_softint?\n");
+ return (0);
+}
+
+struct zsops zsops_kgdb = {
+ zs_kgdb_rxint, /* receive char available */
+ zs_kgdb_stint, /* external/status */
+ zs_kgdb_txint, /* xmit buffer empty */
+ zs_kgdb_softint, /* process software interrupt */
+};
diff --git a/sys/arch/sun3/dev/zsvar.h b/sys/arch/sun3/dev/zsvar.h
deleted file mode 100644
index eebeea54ff8..00000000000
--- a/sys/arch/sun3/dev/zsvar.h
+++ /dev/null
@@ -1,152 +0,0 @@
-/* $NetBSD: zsvar.h,v 1.7 1995/04/11 02:41:49 mycroft Exp $ */
-
-/*
- * 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
- */
-
-/*
- * 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 256 /* ZS line ring buffer size */
-#define ZLRB_RING_MASK 255 /* 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() delay2us()
diff --git a/sys/arch/sun3/include/kbd.h b/sys/arch/sun3/include/kbd.h
index dcb5f3773aa..106195b551c 100644
--- a/sys/arch/sun3/include/kbd.h
+++ b/sys/arch/sun3/include/kbd.h
@@ -1,4 +1,4 @@
-/* $NetBSD: kbd.h,v 1.2 1995/05/24 20:57:00 gwr Exp $ */
+/* $NetBSD: kbd.h,v 1.3 1996/01/24 22:40:40 gwr Exp $ */
/*
* Copyright (c) 1992, 1993
@@ -56,8 +56,11 @@
* KBD_IDLE does not take the place of any `up' transitions (it merely occurs
* after them).
*/
-#define KBD_RESET 0xff /* keyboard `reset' response */
+#define KBD_RESET 0xff /* `reset' response (ID follows) */
+#define KBD_LAYOUT 0xfe /* Indicates that `layout' follows */
#define KBD_IDLE 0x7f /* keyboard `all keys are up' code */
+#define KBD_ERROR 0x7e /* keyboard detected an error */
+#define KBD_SPECIAL(c) (((c) & 0x7e) == 0x7e)
/* Keyboard IDs */
#define KB_SUN2 2 /* type 2 keyboard */
@@ -79,6 +82,7 @@
#define KBD_CMD_CLICK 10 /* turn keyclick on */
#define KBD_CMD_NOCLICK 11 /* turn keyclick off */
#define KBD_CMD_SETLED 14 /* set LED state (type 4 kbd) */
+#define KBD_CMD_GETLAYOUT 15 /* ask for layout (type 4 kbd) */
#define LED_NUM_LOCK 0x1
#define LED_COMPOSE 0x2
diff --git a/sys/arch/sun3/include/kbio.h b/sys/arch/sun3/include/kbio.h
index 596e78182f4..f12b495e798 100644
--- a/sys/arch/sun3/include/kbio.h
+++ b/sys/arch/sun3/include/kbio.h
@@ -1,4 +1,4 @@
-/* $NetBSD: kbio.h,v 1.3 1995/08/08 20:57:51 gwr Exp $ */
+/* $NetBSD: kbio.h,v 1.4 1996/01/24 22:40:43 gwr Exp $ */
/*
* Copyright (c) 1992, 1993
@@ -68,42 +68,44 @@
*/
struct okiockey { /* Out-dated key translation structure */
- int kio_tablemask; /* whatever */
+ int kio_tablemask; /* whatever */
u_char kio_station; /* key number */
- u_char kio_entry; /* HOLE if not present */
+ u_char kio_entry; /* 0xA2 (HOLE) if not present */
char kio_text[10]; /* the silly escape sequences (unsupported) */
};
-struct kiockey {
- int kio_tablemask; /* whatever */
+struct kiockeymap {
+ int kio_tablemask; /* whatever */
u_char kio_station; /* key number */
- u_short kio_entry; /* HOLE if not present */
+ u_short kio_entry; /* keymap entry - see kbd_map.h */
char kio_text[10]; /* the silly escape sequences (unsupported) */
};
/*
* Values for kio_tablemask. These determine which table to read/modify
- * in KIOC[SG]KEY ioctls. Currently, we only have "non-shift" and "shift"
- * tables.
+ * in KIOC[SG]KEY ioctls. Currently handle: {NO,SHIFT,CTRL,UP}MASK
+ * Note: these are SunOS-4.1 compatible values
*/
-#define KIOC_NOMASK 0x0
-#define KIOC_CAPSMASK 0x1
-#define KIOC_SHIFTMASK 0xe
+#define KIOC_NOMASK 0x00
+#define KIOC_CAPSMASK 0x01
+#define KIOC_SHIFTMASK 0x0E
#define KIOC_CTRLMASK 0x30
+#define KIOC_UPMASK 0x80
#define KIOC_ALTGMASK 0x200
+#define KIOC_ALTMASK 0x400
#define KIOC_NUMLMASK 0x800
-#define HOLE 0x302 /* value for kio_entry to say `really type 3' */
-
#define KIOCTRANS _IOW('k', 0, int) /* set translation mode */
- /* (we only accept TR_UNTRANS_EVENT) */
+
+#define KIOCSETKEY _IOWR('k', 1, struct okiockey) /* fill in kio_entry */
#define KIOCGETKEY _IOWR('k', 2, struct okiockey) /* fill in kio_entry */
+
#define KIOCGTRANS _IOR('k', 5, int) /* get translation mode */
#define KIOCCMD _IOW('k', 8, int) /* X uses this to ring bell */
#define KIOCTYPE _IOR('k', 9, int) /* get keyboard type */
#define KIOCSDIRECT _IOW('k', 10, int) /* keys to console? */
-#define KIOCSKEY _IOW('k', 12, struct kiockey) /* set xlat mode */
-#define KIOCGKEY _IOWR('k', 13, struct kiockey) /* get xlat mode */
+#define KIOCSKEY _IOW('k', 12, struct kiockeymap) /* set xlat mode */
+#define KIOCGKEY _IOWR('k', 13, struct kiockeymap) /* get xlat mode */
#define KIOCSLED _IOW('k', 14, char) /* set LED state */
#define KIOCGLED _IOR('k', 15, char) /* get LED state */
#define KIOCLAYOUT _IOR('k', 20, int) /* get keyboard layout */
diff --git a/sys/arch/sun3/dev/event_var.h b/sys/arch/sun3/include/z8530var.h
index 463a4eb2f8c..9eb9551daf2 100644
--- a/sys/arch/sun3/dev/event_var.h
+++ b/sys/arch/sun3/include/z8530var.h
@@ -1,6 +1,7 @@
-/* $NetBSD: event_var.h,v 1.3 1994/11/21 21:30:47 gwr Exp $ */
+/* $NetBSD: z8530var.h,v 1.2 1996/01/24 22:40:48 gwr Exp $ */
/*
+ * Copyright (c) 1994 Gordon W. Ross
* Copyright (c) 1992, 1993
* The Regents of the University of California. All rights reserved.
*
@@ -41,48 +42,36 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
- * from: @(#)event_var.h 8.1 (Berkeley) 6/11/93
- * from: Hdr: event_var.h,v 1.5 92/11/26 01:11:51 torek Exp (LBL)
+ * @(#)zsvar.h 8.1 (Berkeley) 6/11/93
*/
+#include <dev/ic/z8530sc.h>
+
/*
- * Internal `Firm_event' interface for the keyboard and mouse drivers.
- * The drivers are expected not to place events in the queue above spltty(),
- * i.e., are expected to run off serial ports.
+ * Macros to read and write individual registers (except 0) in a channel.
+ * The ZS chip requires a 1.6 uSec. recovery time between accesses, and
+ * the Sun3 hardware does NOT take care of this for you.
*/
+#define ZS_READ(c, r) zs_read_reg(c, r)
+#define ZS_WRITE(c, r, v) zs_write_reg(c, r, v)
+#define ZS_DELAY() delay2us()
-/* EV_QSIZE should be a power of two so that `%' is fast */
-#define EV_QSIZE 256 /* may need tuning; this uses 2k */
-
-struct evvar {
- u_int ev_get; /* get (read) index (modified synchronously) */
- volatile u_int ev_put; /* put (write) index (modified by interrupt) */
- struct selinfo ev_sel; /* process selecting */
- struct proc *ev_io; /* process that opened queue (can get SIGIO) */
- char ev_wanted; /* wake up on input ready */
- char ev_async; /* send SIGIO on input ready */
- struct firm_event *ev_q;/* circular buffer (queue) of events */
-};
-
-#define splev() spltty()
+u_char zs_read_reg __P((struct zs_chanstate *zc, u_char reg));
+void zs_write_reg __P((struct zs_chanstate *zc, u_char reg, u_char val));
-#define EV_WAKEUP(ev) { \
- selwakeup(&(ev)->ev_sel); \
- if ((ev)->ev_wanted) { \
- (ev)->ev_wanted = 0; \
- wakeup((caddr_t)(ev)); \
- } \
- if ((ev)->ev_async) \
- psignal((ev)->ev_io, SIGIO); \
-}
+/*
+ * How to request a "soft" interrupt.
+ * This could be a macro if you like.
+ */
+void zsc_req_softint __P((struct zsc_softc *zsc));
-void ev_init __P((struct evvar *));
-void ev_fini __P((struct evvar *));
-int ev_read __P((struct evvar *, struct uio *, int));
-int ev_select __P((struct evvar *, int, struct proc *));
+/* Handle user request to enter kernel debugger. */
+void zs_abort();
/*
- * PEVENT is set just above PSOCK, which is just above TTIPRI, on the
- * theory that mouse and keyboard `user' input should be quick.
+ * 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...
*/
-#define PEVENT 23
+#define ZSTTY_MAJOR 12 /* XXX */
+#define ZSTTY_DEF_CFLAG (CREAD | CS8 | HUPCL)
diff --git a/sys/arch/sun3/sun3/conf.c b/sys/arch/sun3/sun3/conf.c
index 2a1c1d87444..63be5b4b7c4 100644
--- a/sys/arch/sun3/sun3/conf.c
+++ b/sys/arch/sun3/sun3/conf.c
@@ -1,4 +1,4 @@
-/* $NetBSD: conf.c,v 1.45 1995/10/29 04:15:59 gwr Exp $ */
+/* $NetBSD: conf.c,v 1.46 1996/01/24 22:40:58 gwr Exp $ */
/*-
* Copyright (c) 1994 Adam Glass, Gordon W. Ross
@@ -165,19 +165,6 @@ cdev_decl(bpf);
cdev_decl(tun);
-/* open, close, read, ioctl */
-cdev_decl(ipl);
-#define cdev_gen_ipf(c,n) { \
- dev_init(c,n,open), dev_init(c,n,close), dev_init(c,n,read), \
- (dev_type_write((*))) enodev, dev_init(c,n,ioctl), \
- (dev_type_stop((*))) nullop, 0, (dev_type_select((*))) enodev, \
- (dev_type_mmap((*))) enodev, 0 }
-#ifdef IPFILTER
-#define NIPF 1
-#else
-#define NIPF 0
-#endif
-
struct cdevsw cdevsw[] =
{
cdev_cn_init(1,cn), /* 0: virtual console */
@@ -252,7 +239,6 @@ struct cdevsw cdevsw[] =
cdev_notdef(), /* 69: /dev/audio */
cdev_notdef(), /* 70: open prom */
cdev_notdef(), /* 71: (sg?) */
- cdev_gen_ipf(NIPF,ipl), /* 72: IP filter log */
};
int nchrdev = sizeof(cdevsw) / sizeof(cdevsw[0]);
@@ -382,28 +368,3 @@ chrtoblk(dev)
return (makedev(blkmaj, minor(dev)));
}
-/*
- * This entire table could be autoconfig()ed but that would mean that
- * the kernel's idea of the console could be out of sync with that of
- * the standalone boot. I think it best that they both use the same
- * known algorithm unless we see a pressing need otherwise.
- */
-#include <dev/cons.h>
-
-cons_decl(kd);
-#define zscnpollc nullcnpollc
-
-cons_decl(zs);
-dev_type_cnprobe(zscnprobe_a);
-dev_type_cnprobe(zscnprobe_b);
-
-struct consdev constab[] = {
-#if NZS > 0
- { zscnprobe_a, zscninit, zscngetc, zscnputc, zscnpollc },
- { zscnprobe_b, zscninit, zscngetc, zscnputc, zscnpollc },
-#endif
-#if NKD > 0
- cons_init(kd),
-#endif
- { 0 }, /* REQIURED! */
-};