diff options
-rw-r--r-- | sys/arch/hp300/dev/ct.c | 31 | ||||
-rw-r--r-- | sys/arch/hp300/hp300/locore.s | 105 | ||||
-rw-r--r-- | sys/arch/hp300/hp300/machdep.c | 20 | ||||
-rw-r--r-- | sys/arch/sun3/conf/files.sun3 | 39 | ||||
-rw-r--r-- | sys/arch/sun3/conf/std.sun3 | 11 | ||||
-rw-r--r-- | sys/arch/sun3/dev/event.c | 171 | ||||
-rw-r--r-- | sys/arch/sun3/dev/kbd.c | 808 | ||||
-rw-r--r-- | sys/arch/sun3/dev/kd.c | 286 | ||||
-rw-r--r-- | sys/arch/sun3/dev/ms.c | 358 | ||||
-rw-r--r-- | sys/arch/sun3/dev/zs.c | 1784 | ||||
-rw-r--r-- | sys/arch/sun3/dev/zs_kgdb.c | 277 | ||||
-rw-r--r-- | sys/arch/sun3/dev/zsvar.h | 152 | ||||
-rw-r--r-- | sys/arch/sun3/include/kbd.h | 8 | ||||
-rw-r--r-- | sys/arch/sun3/include/kbio.h | 34 | ||||
-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.c | 41 |
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! */ -}; |