Use common zs code.

This commit is contained in:
gwr 1997-10-17 23:59:44 +00:00
parent b4e346f85d
commit 0308bf1ac6
16 changed files with 1875 additions and 3559 deletions

View File

@ -1,4 +1,4 @@
# $NetBSD: GENERIC,v 1.49 1997/09/27 09:56:25 mrg Exp $
# $NetBSD: GENERIC,v 1.50 1997/10/17 23:59:44 gwr Exp $
include "arch/sparc/conf/std.sparc"
@ -133,11 +133,19 @@ zs0 at mainbus0 # sun4c
zs0 at obio0 # sun4m
zs0 at obio0 addr 0xf1000000 level 12 flags 0x103 # sun4/200 and sun4/300
zs0 at obio0 addr 0x01000000 level 12 flags 0x103 # sun4/100
zstty0 at zs0 channel 0 # ttya
zstty1 at zs0 channel 1 # ttyb
zs1 at mainbus0 # sun4c
zs1 at obio0 # sun4m
zs1 at obio0 addr 0xf0000000 level 12 flags 0x103 # sun4/200 and sun4/300
zs1 at obio0 addr 0x00000000 level 12 flags 0x103 # sun4/100
kbd0 at zs1 channel 0 # keyboard
ms0 at zs1 channel 1 # mouse
zs2 at obio0 addr 0xe0000000 level 12 flags 0x103 # sun4/300
zstty2 at zs2 channel 0 # ttyc
zstty3 at zs2 channel 1 # ttyd
#
# Note the flags on the esp entries below, that work around
@ -295,7 +303,6 @@ fd* at fdc0 # the drive itself
pseudo-device loop # loopback interface; required
pseudo-device pty 32 # pseudo-ttys (for network, etc.)
pseudo-device sl 2 # SLIP interfaces
pseudo-device kbd # Sun keyboard
pseudo-device ppp 2 # PPP interfaces
pseudo-device tun 4 # Network "tunnel" device
pseudo-device bpfilter 16 # Berkeley Packet Filter

View File

@ -1,4 +1,4 @@
# $NetBSD: files.sparc,v 1.44 1997/08/31 21:29:16 pk Exp $
# $NetBSD: files.sparc,v 1.45 1997/10/17 23:59:57 gwr Exp $
# @(#)files.sparc 8.1 (Berkeley) 7/19/93
# sparc-specific configuration info
@ -56,9 +56,10 @@ device memreg
attach memreg at mainbus, obio
file arch/sparc/sparc/memreg.c
device zs
device zs {channel = -1}
attach zs at mainbus, obio
file arch/sparc/dev/zs.c zs needs-count
file dev/ic/z8530sc.c zs
device fdc {}
attach fdc at mainbus, obio
@ -71,6 +72,28 @@ device sbus { slot = -1, offset = -1 }
attach sbus at mainbus, iommu
file arch/sparc/dev/sbus.c sbus
#
# Console (zs) related stuff
#
device zstty: tty
attach zstty at zs
file dev/ic/z8530tty.c zstty needs-flag
file arch/sparc/dev/zs_kgdb.c kgdb
define zsevent
file dev/sun/event.c zsevent
device kbd: zsevent
attach kbd at zs
file dev/sun/kbd.c kbd needs-flag
file dev/sun/kbd_tables.c kbd
file arch/sparc/dev/kd.c kbd
device ms: zsevent
attach ms at zs
file dev/sun/ms.c ms needs-flag
#
# Machine-independent SCSI drivers
@ -174,17 +197,12 @@ file arch/sparc/dev/if_en_sbus.c en_sbus
attach isp at sbus with isp_sbus
file arch/sparc/dev/isp_sbus.c isp_sbus
pseudo-device kbd
#
# Generic Sun stuff
#
include "../../../dev/sun/files.sun"
file arch/sparc/dev/cons.c
file dev/cons.c
file arch/sparc/dev/fb.c
file arch/sparc/dev/ms.c
file arch/sparc/dev/kbd.c kbd
file arch/sparc/fpu/fpu.c
file arch/sparc/fpu/fpu_add.c

View File

@ -1,701 +0,0 @@
/* $NetBSD: cons.c,v 1.30 1997/07/07 23:30:23 pk 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.
*
* @(#)cons.c 8.3 (Berkeley) 12/14/93
*/
/*
* Console (indirect) driver.
*/
#include <sys/param.h>
#include <sys/proc.h>
#include <sys/systm.h>
#include <sys/ioctl.h>
#include <sys/tty.h>
#include <sys/file.h>
#include <sys/conf.h>
#include <dev/cons.h>
#include <machine/bsd_openprom.h>
#include <machine/eeprom.h>
#include <machine/psl.h>
#include <machine/cpu.h>
#include <machine/kbd.h>
#if defined(SUN4)
#include <machine/oldmon.h>
#endif
#include <machine/autoconf.h>
#include <machine/conf.h>
#ifdef RASTERCONSOLE
#include <machine/fbio.h>
#include <machine/fbvar.h>
#endif
#include "zs.h"
struct tty *constty = 0; /* virtual console output device */
struct tty *fbconstty = 0; /* tty structure for frame buffer console */
int rom_console_input; /* when set, hardclock calls cnrom() */
int cons_ocount; /* output byte count */
/*
* The output driver may munge the minor number in cons.t_dev.
*/
struct tty cons; /* rom console tty device */
static void (*fcnstop) __P((struct tty *, int));
static void cnstart __P((struct tty *));
void cnstop __P((struct tty *, int));
static void cnfbstart __P((struct tty *));
static void cnfbstop __P((struct tty *, int));
static void cnfbdma __P((void *));
static struct tty *xxcntty __P((dev_t));
extern char char_type[];
/*XXX*/
static struct tty *
xxcntty(dev_t dev)
{
return &cons;
}
void
consinit()
{
register struct tty *tp = &cons;
register int in, out;
/*XXX*/ cdevsw[0].d_tty = xxcntty;
tp->t_dev = makedev(0, 0); /* /dev/console */
tp->t_ispeed = tp->t_ospeed = TTYDEF_SPEED;
tp->t_param = (int (*)(struct tty *, struct termios *))nullop;
if (promvec->pv_romvec_vers > 2) {
/* We need to probe the PROM device tree */
register int node,fd;
char buffer[128];
register struct nodeops *no;
register struct v2devops *op;
register char *cp;
extern int fbnode;
in = out = -1;
no = promvec->pv_nodeops;
op = &promvec->pv_v2devops;
node = findroot();
if (no->no_proplen(node, "stdin-path") >= sizeof(buffer)) {
printf("consinit: increase buffer size and recompile\n");
goto setup_output;
}
/* XXX: fix above */
no->no_getprop(node, "stdin-path",buffer);
/*
* Open an "instance" of this device.
* You'd think it would be appropriate to call v2_close()
* on the handle when we're done with it. But that seems
* to cause the device to shut down somehow; for the moment,
* we simply leave it open...
*/
if ((fd = op->v2_open(buffer)) == 0 ||
(node = op->v2_fd_phandle(fd)) == 0) {
printf("consinit: bogus stdin path %s.\n",buffer);
goto setup_output;
}
if (no->no_proplen(node,"keyboard") >= 0) {
in = PROMDEV_KBD;
goto setup_output;
}
if (strcmp(getpropstring(node,"device_type"),"serial") != 0) {
/* not a serial, not keyboard. what is it?!? */
in = -1;
goto setup_output;
}
/*
* At this point we assume the device path is in the form
* ....device@x,y:a for ttya and ...device@x,y:b for ttyb.
* If it isn't, we defer to the ROM
*/
cp = buffer;
while (*cp)
cp++;
cp -= 2;
#ifdef DEBUG
if (cp < buffer)
panic("consinit: bad stdin path %s",buffer);
#endif
/* XXX: only allows tty's a->z, assumes PROMDEV_TTYx contig */
if (cp[0]==':' && cp[1] >= 'a' && cp[1] <= 'z')
in = PROMDEV_TTYA + (cp[1] - 'a');
/* else use rom */
setup_output:
node = findroot();
if (no->no_proplen(node, "stdout-path") >= sizeof(buffer)) {
printf("consinit: increase buffer size and recompile\n");
goto setup_console;
}
/* XXX: fix above */
no->no_getprop(node, "stdout-path", buffer);
if ((fd = op->v2_open(buffer)) == 0 ||
(node = op->v2_fd_phandle(fd)) == 0) {
printf("consinit: bogus stdout path %s.\n",buffer);
goto setup_output;
}
if (strcmp(getpropstring(node,"device_type"),"display") == 0) {
/* frame buffer output */
out = PROMDEV_SCREEN;
fbnode = node;
} else if (strcmp(getpropstring(node,"device_type"), "serial")
!= 0) {
/* not screen, not serial. Whatzit? */
out = -1;
} else { /* serial console. which? */
/*
* At this point we assume the device path is in the
* form:
* ....device@x,y:a for ttya, etc.
* If it isn't, we defer to the ROM
*/
cp = buffer;
while (*cp)
cp++;
cp -= 2;
#ifdef DEBUG
if (cp < buffer)
panic("consinit: bad stdout path %s",buffer);
#endif
/* XXX: only allows tty's a->z, assumes PROMDEV_TTYx contig */
if (cp[0]==':' && cp[1] >= 'a' && cp[1] <= 'z')
out = PROMDEV_TTYA + (cp[1] - 'a');
else out = -1;
}
} else {
in = *promvec->pv_stdin;
out = *promvec->pv_stdout;
}
setup_console:
switch (in) {
#if NZS > 0
case PROMDEV_TTYA:
zsconsole(tp, 0, 0, NULL);
break;
case PROMDEV_TTYB:
zsconsole(tp, 1, 0, NULL);
break;
#endif
case PROMDEV_KBD:
/*
* Tell the keyboard driver to direct ASCII input here.
*/
kbd_ascii(tp);
break;
default:
rom_console_input = 1;
printf("unknown console input source %d; using rom\n", in);
break;
}
switch (out) {
#if NZS > 0
case PROMDEV_TTYA:
zsconsole(tp, 0, 1, &fcnstop);
break;
case PROMDEV_TTYB:
zsconsole(tp, 1, 1, &fcnstop);
break;
#endif
case PROMDEV_SCREEN:
fbconstty = tp;
tp->t_oproc = cnfbstart;
fcnstop = cnfbstop;
break;
default:
printf("unknown console output sink %d; using rom\n", out);
tp->t_oproc = cnstart;
fcnstop = (void (*)(struct tty *, int))nullop;
break;
}
}
/* ARGSUSED */
int
cnopen(dev, flag, mode, p)
dev_t dev;
int flag, mode;
struct proc *p;
{
register struct tty *tp = &cons;
static int firstopen = 1;
static int rows = 0, cols = 0;
if (firstopen) {
clalloc(&tp->t_rawq, 1024, 1);
clalloc(&tp->t_canq, 1024, 1);
/* output queue doesn't need quoting */
clalloc(&tp->t_outq, 1024, 0);
tty_attach(tp);
/*
* get the console struct winsize.
*/
#ifdef RASTERCONSOLE
if (fbconstty) {
rows = fbrcons_rows();
cols = fbrcons_cols();
}
#endif
if (CPU_ISSUN4COR4M) {
int i;
char *prop;
if (rows == 0 &&
(prop = getpropstring(optionsnode, "screen-#rows"))) {
i = 0;
while (*prop != '\0')
i = i * 10 + *prop++ - '0';
rows = (unsigned short)i;
}
if (cols == 0 &&
(prop = getpropstring(optionsnode, "screen-#columns"))) {
i = 0;
while (*prop != '\0')
i = i * 10 + *prop++ - '0';
cols = (unsigned short)i;
}
}
if (CPU_ISSUN4) {
struct eeprom *ep = (struct eeprom *)eeprom_va;
if (ep) {
if (rows == 0)
rows = (u_short)ep->eeTtyRows;
if (cols == 0)
cols = (u_short)ep->eeTtyCols;
}
}
firstopen = 0;
}
if ((tp->t_state & TS_ISOPEN) == 0) {
/*
* Leave baud rate alone!
*/
ttychars(tp);
tp->t_iflag = TTYDEF_IFLAG;
tp->t_oflag = TTYDEF_OFLAG;
tp->t_lflag = TTYDEF_LFLAG;
tp->t_cflag = TTYDEF_CFLAG;
tp->t_state = TS_ISOPEN | TS_CARR_ON;
(void)(*tp->t_param)(tp, &tp->t_termios);
ttsetwater(tp);
tp->t_winsize.ws_row = rows;
tp->t_winsize.ws_col = cols;
} else if (tp->t_state & TS_XCLUDE && p->p_ucred->cr_uid != 0)
return (EBUSY);
return ((*linesw[tp->t_line].l_open)(dev, tp));
}
/* ARGSUSED */
int
cnclose(dev, flag, mode, p)
dev_t dev;
int flag, mode;
struct proc *p;
{
register struct tty *tp = &cons;
(*linesw[tp->t_line].l_close)(tp, flag);
ttyclose(tp);
return (0);
}
/* ARGSUSED */
int
cnread(dev, uio, flag)
dev_t dev;
struct uio *uio;
int flag;
{
register struct tty *tp = &cons;
return ((*linesw[tp->t_line].l_read)(tp, uio, flag));
}
/* ARGSUSED */
int
cnwrite(dev, uio, flag)
dev_t dev;
struct uio *uio;
int flag;
{
register struct tty *tp;
if ((tp = constty) == NULL ||
(tp->t_state & (TS_CARR_ON|TS_ISOPEN)) != (TS_CARR_ON|TS_ISOPEN))
tp = &cons;
return ((*linesw[tp->t_line].l_write)(tp, uio, flag));
}
int
cnioctl(dev, cmd, data, flag, p)
dev_t dev;
u_long cmd;
caddr_t data;
int flag;
struct proc *p;
{
register struct tty *tp;
int error;
/*
* Superuser can always use this to wrest control of console
* output from the "virtual" console.
*/
if (cmd == TIOCCONS && constty) {
error = suser(p->p_ucred, (u_short *)NULL);
if (error)
return (error);
constty = NULL;
return (0);
}
tp = &cons;
if ((error = linesw[tp->t_line].l_ioctl(tp, cmd, data, flag, p)) >= 0)
return (error);
if ((error = ttioctl(tp, cmd, data, flag, p)) >= 0)
return (error);
return (ENOTTY);
}
int
cnpoll(dev, events, p)
dev_t dev;
int events;
struct proc *p;
{
return (ttpoll(makedev(major(dev), 0), events, p));
}
/*
* The rest of this code is run only when we are using the ROM vectors.
*/
/*
* Generic output. We just call putchar. (Very bad for performance.)
*/
static void
cnstart(tp)
register struct tty *tp;
{
register int c, s;
register union {
void (*v1)__P((int));
int (*v3)__P((int, void *, int));
} putc;
register int fd = 0, v;
s = spltty();
if (tp->t_state & (TS_TIMEOUT | TS_TTSTOP)) {
splx(s);
return;
}
if ((v = promvec->pv_romvec_vers) > 2) {
putc.v3 = promvec->pv_v2devops.v2_write;
fd = *promvec->pv_v2bootargs.v2_fd1;
} else
putc.v1 = promvec->pv_putchar;
while (tp->t_outq.c_cc) {
c = getc(&tp->t_outq);
/*
* *%&!*& ROM monitor console putchar is not reentrant!
* splhigh/tty around it so as not to run so long with
* clock interrupts blocked.
*/
(void) splhigh();
if (v > 2) {
unsigned char c0 = c & 0177;
(*putc.v3)(fd, &c0, 1);
} else
(*putc.v1)(c & 0177);
(void) spltty();
}
if (tp->t_state & TS_ASLEEP) { /* can't happen? */
tp->t_state &= ~TS_ASLEEP;
wakeup((caddr_t)&tp->t_outq);
}
selwakeup(&tp->t_wsel);
splx(s);
}
void
cnstop(tp, flag)
register struct tty *tp;
int flag;
{
(*fcnstop)(tp, flag);
}
/*
* Frame buffer output.
* We use pseudo-DMA, via the ROM `write string' function, called from
* software clock interrupts.
*/
static void
cnfbstart(tp)
register struct tty *tp;
{
register int s;
s = spltty(); /* paranoid: splsoftclock should suffice */
if (tp->t_state & (TS_TIMEOUT | TS_BUSY | TS_TTSTOP)) {
splx(s);
return;
}
/*
* 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);
}
if (tp->t_outq.c_cc) {
tp->t_state |= TS_BUSY;
if (s == 0) {
(void) splsoftclock();
cnfbdma((void *)tp);
} else
timeout(cnfbdma, tp, 1);
}
splx(s);
}
/*
* Stop frame buffer output: just assert TS_FLUSH if necessary.
*/
static void
cnfbstop(tp, flag)
register struct tty *tp;
int flag;
{
register int s = spltty(); /* paranoid */
if ((tp->t_state & (TS_BUSY | TS_TTSTOP)) == TS_BUSY)
tp->t_state |= TS_FLUSH;
splx(s);
}
/*
* Do pseudo-dma (called from software interrupt).
*/
static void
cnfbdma(tpaddr)
void *tpaddr;
{
register struct tty *tp = tpaddr;
register unsigned char *p, *q;
register int n, c, s;
s = spltty(); /* paranoid */
if (tp->t_state & TS_FLUSH) {
tp->t_state &= ~(TS_BUSY | TS_FLUSH);
splx(s);
} else {
tp->t_state &= ~TS_BUSY;
splx(s);
p = tp->t_outq.c_cf;
n = ndqb(&tp->t_outq, 0);
for (q = p, c = n; --c >= 0; q++)
if (*q & 0200) /* high bits seem to be bad */
*q &= ~0200;
if (promvec->pv_romvec_vers > 2) {
(*promvec->pv_v2devops.v2_write)
(*promvec->pv_v2bootargs.v2_fd1, p, n);
} else
(*promvec->pv_putstr)((char *)p, n);
ndflush(&tp->t_outq, n);
}
if (tp->t_line)
(*linesw[tp->t_line].l_start)(tp);
else
cnfbstart(tp);
}
/*
* The following is for rom console input. The rom will not call
* an `interrupt' routine on console input ready, so we must poll.
* This is all rather sad.
*/
volatile int cn_rxc = -1; /* XXX receive `silo' */
/* called from hardclock, which is above spltty, so no tty calls! */
int
cnrom()
{
register int c;
if (cn_rxc >= 0)
return (1);
if (promvec->pv_romvec_vers > 2) {
unsigned char c0;
if ((*promvec->pv_v2devops.v2_read)
(*promvec->pv_v2bootargs.v2_fd0, &c0, 1) <= 0)
return (0);
c = c0;
} else if ((c = (*promvec->pv_nbgetchar)()) < 0)
return (0);
cn_rxc = c;
return (1);
}
/* pseudo console software interrupt scheduled when cnrom() returns 1 */
void
cnrint()
{
register struct tty *tp;
register int c, s;
s = splclock();
c = cn_rxc;
cn_rxc = -1;
splx(s);
if (c < 0)
return;
tp = &cons;
if ((tp->t_cflag & CSIZE) == CS7) {
/* XXX this should be done elsewhere, if at all */
if (tp->t_cflag & PARENB)
if (tp->t_cflag & PARODD ?
(char_type[c & 0177] & 0200) == (c & 0200) :
(char_type[c & 0177] & 0200) != (c & 0200))
c |= TTY_PE;
c &= ~0200;
}
(*linesw[tp->t_line].l_rint)(c, tp);
}
int
cngetc()
{
register int s, c;
if (promvec->pv_romvec_vers > 2) {
register int n = 0;
unsigned char c0;
s = splhigh();
while (n <= 0) {
n = (*promvec->pv_v2devops.v2_read)
(*promvec->pv_v2bootargs.v2_fd0, &c0, 1);
}
splx(s);
c = c0;
} else {
#if defined(SUN4)
/* SUN4 PROM: must turn off echo to avoid double char echo */
extern struct om_vector *oldpvec;
int saveecho = 0;
#endif
s = splhigh();
#if defined(SUN4)
if (CPU_ISSUN4) {
saveecho = *(oldpvec->echo);
*(oldpvec->echo) = 0;
}
#endif
c = (*promvec->pv_getchar)();
#if defined(SUN4)
if (CPU_ISSUN4)
*(oldpvec->echo) = saveecho;
#endif
splx(s);
}
if (c == '\r')
c = '\n';
return (c);
}
void
cnputc(c)
register int c;
{
register int s;
if (c == '\n')
cnputc('\r');
s = splhigh();
if (promvec->pv_romvec_vers > 2) {
unsigned char c0 = c;
(*promvec->pv_v2devops.v2_write)
(*promvec->pv_v2bootargs.v2_fd1, &c0, 1);
} else
(*promvec->pv_putchar)(c);
splx(s);
}
void
cnpollc(on)
int on;
{
}

18
sys/arch/sparc/dev/cons.h Normal file
View File

@ -0,0 +1,18 @@
struct consdev;
struct zs_chanstate;
extern void *zs_conschan;
extern void nullcnprobe __P((struct consdev *));
extern int zs_getc __P((void *arg));
extern void zs_putc __P((void *arg, int c));
struct zschan *
zs_get_chan_addr __P((int zsc_unit, int channel));
#ifdef KGDB
void zs_kgdb_init __P((void));
void zskgdb __P((struct zs_chanstate *));
#endif

View File

@ -1,823 +0,0 @@
/* $NetBSD: kbd.c,v 1.28 1997/09/13 19:12:18 pk 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/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 <sys/signalvar.h>
#include <sys/conf.h>
#include <machine/autoconf.h>
#include <machine/conf.h>
#include <machine/vuid_event.h>
#include <dev/sun/event_var.h>
#include <machine/kbd.h>
#include <machine/kbio.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 */
u_char kbd_pending; /* Another code from the keyboard is due */
u_char kbd_id; /* a place to store the ID */
u_char kbd_layout; /* a place to store layout */
char kbd_leds; /* LED state */
};
/*
* 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 */
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_reset __P((struct kbd_state *));
static int kbd_translate __P((int, struct kbd_state *));
void kbdattach __P((int));
void kbd_repeat __P((void *arg));
/* set in kbdattach() */
int kbd_repeat_start;
int kbd_repeat_step;
/*
* Attach the console keyboard ASCII (up-link) interface.
* This happens before kbd_serial.
*/
void
kbd_ascii(tp)
struct tty *tp;
{
kbd_softc.k_cons = tp;
}
/*
* Attach the console keyboard serial (down-link) interface.
* We pick up the initial keyboard click state here as well.
*/
void
kbd_serial(tp, iopen, iclose)
struct tty *tp;
void (*iopen) __P((struct tty *));
void (*iclose) __P((struct tty *));
{
register struct kbd_softc *k;
register char *cp;
k = &kbd_softc;
k->k_kbd = tp;
k->k_open = iopen;
k->k_close = iclose;
if (!CPU_ISSUN4) {
cp = getpropstring(optionsnode, "keyboard-click?");
if (cp && strcmp(cp, "true") == 0)
k->k_state.kbd_click = 1;
}
}
/*
* Called from main() during pseudo-device setup. If this keyboard is
* the console, this is our chance to open the underlying serial port and
* send a RESET, so that we can find out what kind of keyboard it is.
*/
void
kbdattach(kbd)
int kbd;
{
register struct kbd_softc *k;
register struct tty *tp;
kbd_repeat_start = hz/5;
kbd_repeat_step = hz/20;
if (kbd_softc.k_cons != NULL) {
k = &kbd_softc;
tp = k->k_kbd;
(*k->k_open)(tp); /* never to be closed */
if (ttyoutput(KBD_CMD_RESET, tp) >= 0)
panic("kbdattach");
(*tp->t_oproc)(tp); /* get it going */
/*
* Wait here for the keyboard initialization to complete
* since subsequent kernel console access (ie. cnget())
* may cause the PROM to interfere with the device.
*/
if (tsleep((caddr_t)&kbd_softc.k_state,
PZERO | PCATCH, devopn, hz) != 0) {
/* no response */
printf("kbd: reset failed\n");
kbd_reset(&kbd_softc.k_state);
}
}
}
void
kbd_reset(ks)
register struct kbd_state *ks;
{
/*
* On first identification, set up the table pointers.
*/
if (ks->kbd_unshifted == NULL) {
ks->kbd_unshifted = kbd_unshifted;
ks->kbd_shifted = kbd_shifted;
ks->kbd_cur = ks->kbd_unshifted;
}
/* 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;
default:
printf("Unknown keyboard type %d\n", ks->kbd_id);
}
ks->kbd_leds = 0;
}
/*
* Turn keyboard up/down codes into ASCII.
*/
static int
kbd_translate(c, ks)
register int c;
register struct kbd_state *ks;
{
register int down;
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(arg)
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(c)
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.
* The printf below should be shortened and/or replaced with a
* call to log() after this is tested (and how will we test it?!).
*/
if (c & (TTY_FE|TTY_PE)) {
printf("keyboard input parity or framing 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_pending == KBD_RESET) {
k->k_state.kbd_pending = 0;
k->k_state.kbd_id = c;
kbd_reset(&k->k_state);
if (c == KB_SUN4) {
/* Arrange to get keyboard layout as well */
(void)ttyoutput(KBD_CMD_GLAYOUT, k->k_kbd);
(*k->k_kbd->t_oproc)(k->k_kbd);
} else
wakeup((caddr_t)&k->k_state);
return;
}
/* Read the keyboard layout if we read a KBD_LAYOUT last time */
if (k->k_state.kbd_pending == KBD_LAYOUT) {
k->k_state.kbd_pending = 0;
k->k_state.kbd_layout = c;
/*
* Wake up anyone waiting for type.
*/
wakeup((caddr_t)&k->k_state);
return;
}
/*
* If reset or layout in progress, setup to grab the accompanying
* keyboard response next time (id on reset, dip switch on layout).
*/
if (c == KBD_RESET || c == KBD_LAYOUT) {
k->k_state.kbd_pending = c;
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, &k->k_state);
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, flags, mode, p)
dev_t dev;
int flags;
int mode;
struct proc *p;
{
int s, error;
struct tty *tp;
if (kbd_softc.k_events.ev_io)
return (EBUSY);
kbd_softc.k_events.ev_io = p;
/*
* If no console keyboard, tell the device to open up, maybe for
* the first time. Then make sure we know what kind of keyboard
* it is.
*/
tp = kbd_softc.k_kbd;
if (kbd_softc.k_cons == NULL)
(*kbd_softc.k_open)(tp);
error = 0;
s = spltty();
if (kbd_softc.k_state.kbd_cur == NULL) {
(void) ttyoutput(KBD_CMD_RESET, tp);
(*tp->t_oproc)(tp);
error = tsleep((caddr_t)&kbd_softc.k_state, PZERO | PCATCH,
devopn, hz);
if (error == EWOULDBLOCK) /* no response */
error = ENXIO;
}
splx(s);
if (error) {
kbd_softc.k_events.ev_io = NULL;
return (error);
}
ev_init(&kbd_softc.k_events);
return (0);
}
int
kbdclose(dev, flags, mode, p)
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);
if (kbd_softc.k_cons == NULL)
(*kbd_softc.k_close)(kbd_softc.k_kbd);
kbd_softc.k_events.ev_io = NULL;
return (0);
}
int
kbdread(dev, uio, flags)
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, uio, flags)
dev_t dev;
struct uio *uio;
int flags;
{
return (EOPNOTSUPP);
}
int
kbdioctl(dev, cmd, data, flag, p)
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 (in an inappropriate fashion)
* if a type 3 keyboard is really a type 3 keyboard.
* Say yes (inappropriately).
*/
((struct okiockey *)data)->kio_entry = (u_char)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:
*(unsigned int *)data = k->k_state.kbd_layout;
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
kbdpoll(dev, events, p)
dev_t dev;
int events;
struct proc *p;
{
return (ev_poll(&kbd_softc.k_events, events, 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(cmd, isuser)
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);
}

591
sys/arch/sparc/dev/kd.c Normal file
View File

@ -0,0 +1,591 @@
/* $NetBSD: kd.c,v 1.1 1997/10/18 00:00:30 gwr Exp $ */
/*-
* Copyright (c) 1996 The NetBSD Foundation, Inc.
* All rights reserved.
*
* This code is derived from software contributed to The NetBSD Foundation
* by Gordon W. Ross.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* 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 NetBSD
* Foundation, Inc. and its contributors.
* 4. Neither the name of The NetBSD Foundation nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
/*
* Keyboard/Display device.
*
* This driver exists simply to provide a tty device that
* the indirect console driver can point to.
* The kbd driver sends its input here.
* Output goes to the screen via PROM printf.
*/
#include <sys/param.h>
#include <sys/proc.h>
#include <sys/systm.h>
#include <sys/ioctl.h>
#include <sys/tty.h>
#include <sys/file.h>
#include <sys/conf.h>
#include <sys/device.h>
#include <machine/bsd_openprom.h>
#include <machine/eeprom.h>
#include <machine/psl.h>
#include <machine/cpu.h>
#include <machine/kbd.h>
#if defined(SUN4)
#include <machine/oldmon.h>
#endif
#include <machine/autoconf.h>
#include <machine/conf.h>
#ifdef RASTERCONSOLE
#include <machine/fbio.h>
#include <machine/fbvar.h>
#endif
#include <dev/cons.h>
#include <dev/sun/kbd_xlate.h>
#include <sparc/dev/cons.h>
extern void fb_unblank __P((void)); /* XXX */
struct tty *fbconstty = 0; /* tty structure for frame buffer console */
#define KDMAJOR 1
#define PUT_WSIZE 64
struct kd_softc {
struct device kd_dev; /* required first: base device */
struct tty *kd_tty;
int rows, cols;
};
/*
* There is no point in pretending there might be
* more than one keyboard/display device.
*/
static struct kd_softc kd_softc;
static int kd_is_console;
static int kdparam(struct tty *, struct termios *);
static void kdstart(struct tty *);
int rom_console_input; /* when set, hardclock calls cnrom() */
int cons_ocount; /* output byte count */
/* Now talking directly to the zs, so this is not needed. */
int
cnrom()
{
return (0);
}
void
cnrint()
{
}
/*
* This is called by kbd_attach()
* XXX - Make this a proper child of kbd?
*/
void
kd_init(unit)
int unit;
{
struct kd_softc *kd;
struct tty *tp;
if (unit != 0)
return;
kd = &kd_softc; /* XXX */
tp = ttymalloc();
tp->t_oproc = kdstart;
tp->t_param = kdparam;
tp->t_dev = makedev(KDMAJOR, unit);
#if 1 /* XXX - Why? */
clalloc(&tp->t_rawq, 1024, 1);
clalloc(&tp->t_canq, 1024, 1);
/* output queue doesn't need quoting */
clalloc(&tp->t_outq, 1024, 0);
#endif
tty_attach(tp);
kd->kd_tty = tp;
/*
* get the console struct winsize.
*/
if (kd_is_console) {
fbconstty = tp;
#ifdef RASTERCONSOLE
kd->rows = fbrcons_rows();
kd->cols = fbrcons_cols();
#endif
}
if (CPU_ISSUN4COR4M) {
int i;
char *prop;
if (kd->rows == 0 &&
(prop = getpropstring(optionsnode, "screen-#rows"))) {
i = 0;
while (*prop != '\0')
i = i * 10 + *prop++ - '0';
kd->rows = (unsigned short)i;
}
if (kd->cols == 0 &&
(prop = getpropstring(optionsnode, "screen-#columns"))) {
i = 0;
while (*prop != '\0')
i = i * 10 + *prop++ - '0';
kd->cols = (unsigned short)i;
}
}
if (CPU_ISSUN4) {
struct eeprom *ep = (struct eeprom *)eeprom_va;
if (ep) {
if (kd->rows == 0)
kd->rows = (u_short)ep->eeTtyRows;
if (kd->cols == 0)
kd->cols = (u_short)ep->eeTtyCols;
}
}
return;
}
struct tty *
kdtty(dev)
dev_t dev;
{
struct kd_softc *kd;
kd = &kd_softc; /* XXX */
return (kd->kd_tty);
}
int
kdopen(dev, flag, mode, p)
dev_t dev;
int flag, mode;
struct proc *p;
{
struct kd_softc *kd;
int error, s, unit;
struct tty *tp;
unit = minor(dev);
if (unit != 0)
return ENXIO;
kd = &kd_softc; /* XXX */
tp = kd->kd_tty;
if ((error = kbd_iopen(unit)) != 0) {
#ifdef DIAGNOSTIC
printf("kd: kbd_iopen, error=%d\n", error);
#endif
return (error);
}
/* 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) {
/* 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;
(void) kdparam(tp, &tp->t_termios);
ttsetwater(tp);
tp->t_winsize.ws_row = kd->rows;
tp->t_winsize.ws_col = kd->cols;
/* 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));
}
int
kdclose(dev, flag, mode, p)
dev_t dev;
int flag, mode;
struct proc *p;
{
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);
return (0);
}
int
kdread(dev, uio, flag)
dev_t dev;
struct uio *uio;
int flag;
{
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));
}
int
kdwrite(dev, uio, flag)
dev_t dev;
struct uio *uio;
int flag;
{
struct kd_softc *kd;
struct tty *tp;
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;
u_long cmd;
caddr_t data;
int flag;
struct proc *p;
{
struct kd_softc *kd;
struct tty *tp;
int error;
kd = &kd_softc; /* XXX */
tp = kd->kd_tty;
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;
/* Handle any ioctl commands specific to kbd/display. */
/* XXX - Send KB* ioctls to kbd module? */
/* XXX - Send FB* ioctls to fb module? */
return ENOTTY;
}
void
kdstop(tp, flag)
struct tty *tp;
int flag;
{
}
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;
}
static void kd_later(void*);
static void kd_putfb(struct tty *);
static void
kdstart(tp)
struct tty *tp;
{
struct clist *cl;
register int s;
s = spltty();
if (tp->t_state & (TS_BUSY|TS_TTSTOP|TS_TIMEOUT))
goto out;
cl = &tp->t_outq;
if (cl->c_cc) {
if (kd_is_console) {
tp->t_state |= TS_BUSY;
if ((s & PSR_PIL) == 0) {
/* called at level zero - update screen now. */
(void) splsoftclock();
kd_putfb(tp);
(void) spltty();
tp->t_state &= ~TS_BUSY;
} else {
/* called at interrupt level - do it later */
timeout(kd_later, (void*)tp, 0);
}
} else {
/*
* This driver uses the PROM for writing the screen,
* and that only works if this is the console device.
* If this is not the console, just flush the output.
* Sorry. (In that case, use xdm instead of getty.)
*/
ndflush(cl, cl->c_cc);
}
}
if (cl->c_cc <= tp->t_lowat) {
if (tp->t_state & TS_ASLEEP) {
tp->t_state &= ~TS_ASLEEP;
wakeup((caddr_t)cl);
}
selwakeup(&tp->t_wsel);
}
out:
splx(s);
}
/*
* Timeout function to do delayed writes to the screen.
* Called at splsoftclock when requested by kdstart.
*/
static void
kd_later(tpaddr)
void *tpaddr;
{
struct tty *tp = tpaddr;
register int s;
kd_putfb(tp);
s = spltty();
tp->t_state &= ~TS_BUSY;
(*linesw[tp->t_line].l_start)(tp);
splx(s);
}
/*
* Put text on the screen using the PROM monitor.
* This can take a while, so to avoid missing
* interrupts, this is called at splsoftclock.
*/
static void
kd_putfb(tp)
struct tty *tp;
{
char buf[PUT_WSIZE];
struct clist *cl = &tp->t_outq;
char *p, *end;
int len;
while ((len = q_to_b(cl, buf, PUT_WSIZE-1)) > 0) {
/* PROM will barf if high bits are set. */
p = buf;
end = buf + len;
while (p < end)
*p++ &= 0x7f;
/* Now let the PROM print it. */
if (promvec->pv_romvec_vers > 2) {
(*promvec->pv_v2devops.v2_write)
(*promvec->pv_v2bootargs.v2_fd1, buf, len);
} else
(*promvec->pv_putstr)(buf, len);
}
}
/*
* Our "interrupt" routine for input. This is called by
* the keyboard driver (dev/sun/kbd.c) at spltty.
*/
void
kd_input(c)
int c;
{
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;
(*linesw[tp->t_line].l_rint)(c, tp);
}
/****************************************************************
* kd console support
****************************************************************/
/* The debugger gets its own key translation state. */
static struct kbd_state kdcn_state;
static void kdcnprobe __P((struct consdev *));
static void kdcninit __P((struct consdev *));
static int kdcngetc __P((dev_t));
static void kdcnputc __P((dev_t, int));
static void kdcnpollc __P((dev_t, int));
struct consdev consdev_kd = {
kdcnprobe,
kdcninit,
kdcngetc,
kdcnputc,
kdcnpollc,
};
/* We never call this. */
static void
kdcnprobe(cn)
struct consdev *cn;
{
}
static void
kdcninit(cn)
struct consdev *cn;
{
struct kbd_state *ks = &kdcn_state;
cn->cn_dev = makedev(KDMAJOR, 0);
cn->cn_pri = CN_INTERNAL;
/* This prepares kbd_translate() */
ks->kbd_id = KBD_MIN_TYPE;
kbd_xlate_init(ks);
/* Indicate that it is OK to use the PROM fbwrite */
kd_is_console = 1;
}
static int
kdcngetc(dev)
dev_t dev;
{
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;
case KEYSYM_ALL_UP:
/* No toggle keys here. */
ks->kbd_modbits = 0;
break;
default: /* ignore all other keysyms */
break;
}
}
out:
return (keysym);
}
static void
kdcnputc(dev, c)
dev_t dev;
int c;
{
char c0 = (c & 0x7f);
if (promvec->pv_romvec_vers > 2)
(*promvec->pv_v2devops.v2_write)
(*promvec->pv_v2bootargs.v2_fd1, &c0, 1);
else
(*promvec->pv_putchar)(c);
}
static void
kdcnpollc(dev, on)
dev_t dev;
int on;
{
struct kbd_state *ks = &kdcn_state;
if (on) {
/* Entering debugger. */
fb_unblank();
/* Clear shift keys too. */
ks->kbd_modbits = 0;
} else {
/* Resuming kernel. */
}
}

View File

@ -1,346 +0,0 @@
/* $NetBSD: ms.c,v 1.10 1996/09/12 01:36:18 mrg 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/ioctl.h>
#include <sys/kernel.h>
#include <sys/proc.h>
#include <sys/syslog.h>
#include <sys/systm.h>
#include <sys/tty.h>
#include <sys/signalvar.h>
#include <sys/conf.h>
#include <machine/vuid_event.h>
#include <machine/cpu.h>
#include <machine/kbd.h>
#include <machine/conf.h>
#include <dev/sun/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.
* The Sun 4 needs to have the baud rate set explicitly, but we handle
* that in ms_open().
*/
void
ms_serial(tp, iopen, iclose)
struct tty *tp;
void (*iopen) __P((struct tty *));
void (*iclose) __P((struct tty *));
{
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;
{
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 */
if (CPU_ISSUN4) {
/* We need to set the baud rate on the mouse. */
ms_softc.ms_mouse->t_ispeed =
ms_softc.ms_mouse->t_ospeed = 1200;
}
(*ms_softc.ms_open)(ms_softc.ms_mouse);
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;
{
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
mspoll(dev, events, p)
dev_t dev;
int events;
struct proc *p;
{
return (ev_poll(&ms_softc.ms_events, events, p));
}

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,291 @@
/* $NetBSD: zs_kgdb.c,v 1.1 1997/10/18 00:00:51 gwr Exp $ */
/*-
* Copyright (c) 1996 The NetBSD Foundation, Inc.
* All rights reserved.
*
* This code is derived from software contributed to The NetBSD Foundation
* by Gordon W. Ross.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* 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 NetBSD
* Foundation, Inc. and its contributors.
* 4. Neither the name of The NetBSD Foundation nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
/*
* Hooks for kgdb when attached via the z8530 driver
*
* To use this, build a kernel with: option KGDB, and
* boot that kernel with "-d". (The kernel will call
* zs_kgdb_init, kgdb_connect.) When the console prints
* "kgdb waiting..." you run "gdb -k kernel" and do:
* (gdb) set remotebaud 19200
* (gdb) target remote /dev/ttyb
*/
#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 <sys/kgdb.h>
#include <dev/ic/z8530reg.h>
#include <machine/z8530var.h>
#include <sparc/dev/cons.h>
/* The Sun3 provides a 4.9152 MHz clock to the ZS chips. */
#define PCLK (9600 * 512) /* PCLK pin input clock rate */
#define ZSHARD_PRI 6 /* Wired on the CPU board... */
#define ZS_DELAY() (CPU_ISSUN4C ? (0) : delay(2))
/* 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;
};
static void zs_setparam __P((struct zs_chanstate *, int, int));
struct zsops zsops_kgdb;
static u_char zs_kgdb_regs[16] = {
0, /* 0: CMD (reset, etc.) */
0, /* 1: ~(ZSWR1_RIE | ZSWR1_TIE | ZSWR1_SIE) */
0, /* 2: 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 | ZSWR9_NO_VECTOR,
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_ENA | ZSWR14_BAUD_FROM_PCLK,
ZSWR15_BREAK_IE | ZSWR15_DCD_IE,
};
/*
* This replaces "zs_reset()" in the sparc driver.
*/
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) {
cs->cs_preg[1] = ZSWR1_RIE | ZSWR1_SIE;
}
/* Initialize the speed, etc. */
tconst = BPS_TO_TCONST(cs->cs_brg_clk, 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.
* Called after cninit(), so printf() etc. works.
*/
void
zs_kgdb_init()
{
struct zs_chanstate cs;
volatile struct zschan *zc;
int channel, zsc_unit;
/* printf("zs_kgdb_init: kgdb_dev=0x%x\n", kgdb_dev); */
if (major(kgdb_dev) != zs_major)
return;
/* Note: (ttya,ttyb) on zsc1, and (ttyc,ttyd) on zsc0 */
zsc_unit = (kgdb_dev & 2) ? 0 : 1;
channel = kgdb_dev & 1;
printf("zs_kgdb_init: attaching tty%c at %d baud\n",
'a' + (kgdb_dev & 3), kgdb_rate);
/* Setup temporary chanstate. */
bzero((caddr_t)&cs, sizeof(cs));
zc = zs_get_chan_addr(zsc_unit, channel);
if (zc == NULL) {
printf("zs_kgdb_init: zs not mapped.\n");
kgdb_dev = -1;
return;
}
cs.cs_channel = channel;
cs.cs_brg_clk = PCLK / 16;
cs.cs_reg_csr = &zc->zc_csr;
cs.cs_reg_data = &zc->zc_data;
/* 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;
{
if (dev != kgdb_dev)
return (0);
/*
* Yes, this is port in use by kgdb.
*/
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.
*/
void
zskgdb(cs)
struct zs_chanstate *cs;
{
int 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)
****************************************************************/
static void zs_kgdb_rxint __P((struct zs_chanstate *));
static void zs_kgdb_txint __P((struct zs_chanstate *));
static void zs_kgdb_stint __P((struct zs_chanstate *));
static void zs_kgdb_softint __P((struct zs_chanstate *));
int kgdb_input_lost;
static void
zs_kgdb_rxint(cs)
struct zs_chanstate *cs;
{
register u_char c, rr1;
/*
* First read the status, because reading the received char
* destroys the status of this char.
*/
rr1 = zs_read_reg(cs, 1);
c = zs_read_data(cs);
if (rr1 & (ZSRR1_FE | ZSRR1_DO | ZSRR1_PE)) {
/* Clear the receive error. */
zs_write_csr(cs, ZSWR0_RESET_ERRORS);
}
if (c == KGDB_START) {
zskgdb(cs);
} else {
kgdb_input_lost++;
}
}
static void
zs_kgdb_txint(cs)
register struct zs_chanstate *cs;
{
register int rr0;
rr0 = zs_read_csr(cs);
zs_write_csr(cs, ZSWR0_RESET_TXINT);
}
static void
zs_kgdb_stint(cs)
register struct zs_chanstate *cs;
{
register int rr0;
rr0 = zs_read_csr(cs);
zs_write_csr(cs, ZSWR0_RESET_STATUS);
/*
* Check here for console break, so that we can abort
* even when interrupts are locking up the machine.
*/
if (rr0 & ZSRR0_BREAK) {
zskgdb(cs);
}
}
static void
zs_kgdb_softint(cs)
struct zs_chanstate *cs;
{
printf("zs_kgdb_softint?\n");
}
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 */
};

View File

@ -1,188 +0,0 @@
/* $NetBSD: zsvar.h,v 1.10 1997/04/14 21:26:28 pk 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.
*
* @(#)zsvar.h 8.1 (Berkeley) 6/11/93
*/
/*
* Register layout is machine-dependent...
*/
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 {
struct zschan zs_chan[2];
};
/*
* 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.
*/
/* 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)
/* forard decl */
struct zs_softc;
struct zs_chanstate {
struct zs_chanstate *cs_next; /* linked list for zshard() */
struct zs_softc *cs_sc; /* pointer to softc */
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) */
char cs_deferred_cc; /* deferred zscnputc() output */
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 */
u_int cs_ringmask; /* mask, reflecting size of `rbuf' */
int *cs_rbuf; /* 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.
*
* On the SparcStation the 1.6 microsecond recovery time is
* handled in hardware. On the older Sun4 machine it isn't, and
* software must deal with the problem.
*
* However, it *is* a problem on some Sun4m's (i.e. the SS20) (XXX: why?).
* Thus we leave in the delay.
*
* XXX: (ABB) Think about this more.
*/
#if defined(SUN4)
#define ZS_READ(c, r) zs_read(c, r)
#define ZS_WRITE(c, r, v) zs_write(c, r, v)
#define ZS_DELAY() (CPU_ISSUN4C ? (0) : delay(1))
#else /* SUN4 */
#define ZS_READ(c, r) ((c)->zc_csr = (r), (c)->zc_csr)
#define ZS_WRITE(c, r, v) ((c)->zc_csr = (r), (c)->zc_csr = (v))
#define ZS_DELAY() (CPU_ISSUN4M ? delay(1) : 0)
#endif /* SUN4 */

View File

@ -1,4 +1,4 @@
/* $NetBSD: conf.h,v 1.8 1996/12/31 07:12:43 mrg Exp $ */
/* $NetBSD: conf.h,v 1.9 1997/10/18 00:01:05 gwr Exp $ */
/*
* Copyright (c) 1996 Christos Zoulas. All rights reserved.
@ -60,6 +60,7 @@ cdev_decl(fb);
cdev_decl(ms);
cdev_decl(kbd);
cdev_decl(kd);
cdev_decl(bwtwo);

View File

@ -1,4 +1,4 @@
/* $NetBSD: kbd.h,v 1.6 1996/03/31 22:21:35 pk Exp $ */
/* $NetBSD: kbd.h,v 1.7 1997/10/18 00:01:15 gwr Exp $ */
/*
* Copyright (c) 1992, 1993
@ -56,9 +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_LAYOUT 0xfe /* keyboard `get layout' response */
#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,19 +81,14 @@
#define KBD_CMD_NOBELL 3 /* turn bell off */
#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_GLAYOUT 15 /* get DIP switch (type 4 kbd) */
#define KBD_CMD_SETLED 14 /* set LED state (type 4 kbd) */
#define KBD_CMD_GETLAYOUT 15 /* get DIP switch (type 4 kbd) */
#define LED_NUM_LOCK 0x1
#define LED_COMPOSE 0x2
#define LED_SCROLL_LOCK 0x4
#define LED_CAPS_LOCK 0x8
void kbd_serial __P((struct tty *,
void (*)(struct tty *), void (*)(struct tty *)));
void ms_serial __P((struct tty *,
void (*)(struct tty *), void (*)(struct tty *)));
void kbd_rint __P((int));
void ms_rint __P((int));
void kbd_ascii __P((struct tty *));
#ifdef _KERNEL
int kbd_docmd __P((int, int));
#endif

View File

@ -1,4 +1,4 @@
/* $NetBSD: kbio.h,v 1.4 1995/05/10 16:07:27 pk Exp $ */
/* $NetBSD: kbio.h,v 1.5 1997/10/18 00:01:23 gwr Exp $ */
/*
* Copyright (c) 1992, 1993
@ -66,46 +66,53 @@
* Keyboard commands and types are defined in kbd.h as they are actually
* real hardware commands and type numbers.
*/
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
#if 0 /* XXX - This is wrong. Programs testing this expect 0xA2 */
#define HOLE 0x302 /* value for kio_entry to say `really type 3' */
#endif
#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 KIOCLAYOUT _IOR('k', 20, int) /* get keyboard layout */
#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 */
#define TR_NONE 0 /* X compat, unsupported */
#define TR_ASCII 1 /* X compat, unsupported */

View File

@ -0,0 +1,85 @@
/* $NetBSD: z8530var.h,v 1.1 1997/10/18 00:01:30 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.
*
* @(#)zsvar.h 8.1 (Berkeley) 6/11/93
*/
#include <dev/ic/z8530sc.h>
struct zsc_softc {
struct device zsc_dev; /* required first: base device */
struct zs_chanstate *zsc_cs[2]; /* channel A and B soft state */
/* Machine-dependent part follows... */
struct evcnt zsc_intrcnt; /* count interrupts */
struct zs_chanstate zsc_cs_store[2];
};
/*
* Functions to read and write individual registers in a channel.
* The ZS chip requires a 1.6 uSec. recovery time between accesses.
* On the SparcStation the recovery time is handled in hardware.
* On the older Sun4 machine it isn't, and software must do it.
*
* However, it *is* a problem on some Sun4m's (i.e. the SS20) (XXX: why?).
* Thus we leave in the delay (done in the functions below).
* XXX: (ABB) Think about this more.
*
* The functions below could be macros instead if we are concerned
* about the function call overhead where ZS_DELAY does nothing.
*/
u_char zs_read_reg __P((struct zs_chanstate *cs, u_char reg));
u_char zs_read_csr __P((struct zs_chanstate *cs));
u_char zs_read_data __P((struct zs_chanstate *cs));
void zs_write_reg __P((struct zs_chanstate *cs, u_char reg, u_char val));
void zs_write_csr __P((struct zs_chanstate *cs, u_char val));
void zs_write_data __P((struct zs_chanstate *cs, u_char val));
/* The sparc has splzs() in psl.h */
/* We want to call it "zs" instead of "zsc" (sigh). */
#ifndef ZSCCF_CHANNEL
#define ZSCCF_CHANNEL 0
#define ZSCCF_CHANNEL_DEFAULT -1
#endif

View File

@ -1,4 +1,4 @@
/* $NetBSD: autoconf.c,v 1.79 1997/09/27 18:01:35 pk Exp $ */
/* $NetBSD: autoconf.c,v 1.80 1997/10/18 00:01:42 gwr Exp $ */
/*
* Copyright (c) 1996
@ -225,9 +225,7 @@ bootstrap()
cpuinfo.mmu_nregion,
cpuinfo.mmu_nsegment);
#ifdef KGDB
zs_kgdb_init(); /* XXX */
#endif
/* Moved zs_kgdb_init() to dev/zs.c:consinit(). */
#ifdef DDB
db_machine_init();
ddb_init();
@ -444,12 +442,14 @@ bootpath_build()
break;
case 'd': /* kgdb - always on zs XXX */
#ifdef KGDB
#if defined(KGDB)
boothowto |= RB_KDB; /* XXX unused */
kgdb_debug_panic = 1;
kgdb_connect(1);
#elif defined(DDB)
Debugger();
#else
printf("kernel not compiled with KGDB\n");
printf("kernel has no debugger\n");
#endif
break;

View File

@ -1,4 +1,4 @@
/* $NetBSD: conf.c,v 1.50 1997/10/16 23:43:16 christos Exp $ */
/* $NetBSD: conf.c,v 1.51 1997/10/18 00:01:55 gwr Exp $ */
/*
* Copyright (c) 1992, 1993
@ -67,7 +67,10 @@
#include "cd.h"
#include "uk.h"
#include "zs.h"
#include "kbd.h"
#include "ms.h"
#include "zstty.h"
#include "fdc.h" /* has NFDC and NFD; see files.sparc */
#include "bwtwo.h"
#include "cgtwo.h"
@ -116,20 +119,20 @@ int nblkdev = sizeof(bdevsw) / sizeof(bdevsw[0]);
struct cdevsw cdevsw[] =
{
cdev_cn_init(1,cn), /* 0: virtual console */
cdev_notdef(), /* 1 */
cdev_tty_init(NKBD,kd), /* 1: Sun keyboard/display */
cdev_ctty_init(1,ctty), /* 2: controlling terminal */
cdev_mm_init(1,mm), /* 3: /dev/{null,mem,kmem,...} */
cdev_notdef(), /* 4 */
cdev_notdef(), /* 5 */
cdev_notdef(), /* 6 */
cdev_notdef(), /* 5: tapemaster tape */
cdev_notdef(), /* 6: systech/versatec */
cdev_swap_init(1,sw), /* 7: /dev/drum (swap pseudo-device) */
cdev_notdef(), /* 8 */
cdev_disk_init(NXY,xy), /* 9: SMD disk */
cdev_notdef(), /* 10 */
cdev_notdef(), /* 11 */
cdev_tty_init(NZS,zs), /* 12: zs serial */
cdev_gen_init(1,ms), /* 13: /dev/mouse */
cdev_notdef(), /* 14 */
cdev_notdef(), /* 8: Archive QIC-11 tape */
cdev_disk_init(NXY,xy), /* 9: SMD disk on Xylogics 450/451 */
cdev_notdef(), /* 10: systech multi-terminal board */
cdev_notdef(), /* 11: DES encryption chip */
cdev_tty_init(NZSTTY,zs), /* 12: Zilog 8350 serial port */
cdev_mouse_init(NMS,ms), /* 13: /dev/mouse */
cdev_notdef(), /* 14: cgone */
cdev_notdef(), /* 15: sun /dev/winNNN */
cdev_log_init(1,log), /* 16: /dev/klog */
cdev_disk_init(NSD,sd), /* 17: SCSI disk */
@ -143,9 +146,9 @@ struct cdevsw cdevsw[] =
cdev_ipf_init(NIPFILTER,ipl), /* 25: ip-filter device */
cdev_notdef(), /* 26 */
cdev_fb_init(NBWTWO,bwtwo), /* 27: /dev/bwtwo */
cdev_notdef(), /* 28 */
cdev_gen_init(1,kbd), /* 29: /dev/kbd */
cdev_notdef(), /* 30 */
cdev_notdef(), /* 28: Systech VPC-2200 versatec/centronics */
cdev_mouse_init(NKBD,kbd), /* 29: /dev/kbd */
cdev_notdef(), /* 30: Xylogics tape */
cdev_fb_init(NCGTWO,cgtwo), /* 31: /dev/cgtwo */
cdev_notdef(), /* 32: should be /dev/gpone */
cdev_notdef(), /* 33 */