NetBSD Problem Report #3528
Received: (qmail-queue invoked from smtpd); 24 Apr 1997 16:35:58 -0000
Message-Id: <199704241640.JAA02037@pressed.spam.frisbee.net.au>
Date: Thu, 24 Apr 1997 09:40:13 -0700 (PDT)
From: Mike <mike@pressed.spam.frisbee.net.au>
Reply-To: miff@spam.frisbee.net.au
To: gnats-bugs@gnats.netbsd.org
Subject: New hp300 kernel features
X-Send-Pr-Version: 3.95
>Number: 3528
>Category: port-hp300
>Synopsis: New hp300 kernel features
>Confidential: no
>Severity: non-critical
>Priority: medium
>Responsible: tsutsui
>State: closed
>Class: change-request
>Submitter-Id: net
>Arrival-Date: Thu Apr 24 09:50:01 +0000 1997
>Closed-Date: Sat Mar 05 11:47:16 +0000 2011
>Last-Modified: Fri May 23 03:25:52 +0000 2014
>Originator: Mike
>Release: 1.2D ~20/4/97
>Organization:
Mike Smith Network Support
>Environment:
HP9000/4xx
System: NetBSD pressed.spam.frisbee.net.au 1.2D NetBSD 1.2D (TEST) #4: Thu Apr 24 08:17:51 PDT 1997 mike@pressed.spam.frisbee.net.au:/remote6/hp300/playpen/sys/arch/hp300/compile/TEST hp300
>Description:
New support for :
- differentiating 345/375/400 (experimental) as well as 380/425.
- Domain keyboards
- Apollo serial ports on the 'frodo' chip
- general 'frodo' support
>How-To-Repeat:
Apply the following patch.
>Fix:
diff -crN /sys/arch/hp300/conf/TEST conf/TEST
*** /sys/arch/hp300/conf/TEST Wed Dec 31 16:00:00 1969
--- conf/TEST Thu Apr 24 09:15:59 1997
***************
*** 0 ****
--- 1,75 ----
+
+ # Include attributes common to all hp300s
+ include "arch/hp300/conf/std.hp300"
+
+ # Support for various CPU types
+ options HP380 # includes 425t, 425s, 433s
+
+ # Need to set locally
+ maxusers 32
+
+ # Standard system options
+ options COMPAT_43 # compatibility with 4.3BSD interfaces
+ options COMPAT_44 # compatibility with 4.4BSD binaries
+ options NKMEMCLUSTERS=1024 # 4K pages in kernel malloc pool
+ options LKM # Loadable kernel modules
+
+ # Filesystems
+ file-system FFS # fast filesystem
+ file-system NFS # Network filesystem client
+ file-system UNION # Union filesystem (req. for FDESC)
+ file-system KERNFS # kernel data-structure filesystem
+ file-system FDESC # user file descriptor filesystem
+ file-system PROCFS # /proc filesystem
+ file-system MFS # Memory-based filesystem
+
+ # Filesystem options
+ options FIFO # POSIX fifo support (in all filesystems)
+
+ # Networking options
+ options INET # Internet protocols
+ options TCP_COMPAT_42 # compatibility with 4.2BSD TCP/IP
+
+ # Options for HP hardware
+ options FPSP # floating point interface for 68040
+ options USELEDS # make the lights twinkle
+ options COMPAT_NOLABEL # defaults for unlabeled disks
+
+ options COMPAT_M68K4K # compat. with NetBSD/m68k4k binaries
+
+ # Debugging options
+ options DDB # Kernel Dynamic Debugger
+
+ config netbsd root on ? type ?
+
+ mainbus0 at root # root "bus"
+
+ intio0 at mainbus0 # internal i/o space
+ dio0 at mainbus0 # DIO/DIO-II bus
+
+ frodo0 at intio0
+ dnkbd0 at frodo0 channel 0
+ apci0 at frodo0 channel 1
+ apci1 at frodo0 channel 2
+ apci2 at frodo0 channel 3
+
+ # Hyperion framebuffer
+ hyper* at dio? scode ?
+
+ # Framebuffer abstraction
+ grf* at hyper?
+
+ # Internal Terminal Emulator
+ ite* at grf?
+
+ dca0 at dio? scode 9 flags 1 # DCA serial interfaces
+
+ le* at dio? scode ? # LANCE ethernet interfaces
+
+ oscsi* at dio? scode ? # SCSI
+ sd* at oscsi? target ? lun? # disk
+
+ pseudo-device pty 64 # pseudo ptys
+ pseudo-device bpfilter 16 # Berkeley packet filter
+ pseudo-device loop # loopback network interface
+ pseudo-device ccd 2
diff -crN /sys/arch/hp300/conf/files.hp300 conf/files.hp300
*** /sys/arch/hp300/conf/files.hp300 Mon Apr 14 04:24:54 1997
--- conf/files.hp300 Wed Apr 23 22:35:20 1997
***************
*** 153,158 ****
--- 153,178 ----
file arch/hp300/dev/hil.c
file arch/hp300/dev/hil_keymaps.c
+ # Automatic keyboard configuration
+ file arch/hp300/dev/kbdconf.c
+
+ #
+ # Apollo utility chip ('frodo')
+ #
+ device frodo { channel = -1 }
+ attach frodo at intio
+ file arch/hp300/dev/frodo.c frodo
+
+ # Domain keyboard
+ device dnkbd: tty
+ attach dnkbd at frodo
+ file arch/hp300/dev/dnkbd.c dnkbd needs-flag
+
+ # Apollo serial ports
+ device apci: tty
+ attach apci at frodo
+ file arch/hp300/dev/apci.c apci needs-flag
+
#
# Non-device files
#
diff -crN /sys/arch/hp300/dev/apci.c dev/apci.c
*** /sys/arch/hp300/dev/apci.c Wed Dec 31 16:00:00 1969
--- dev/apci.c Thu Apr 24 08:23:28 1997
***************
*** 0 ****
--- 1,728 ----
+ /* $NetBSD$ */
+
+ /*
+ * Copyright (c) 1997 Michael Smith. All rights reserved.
+ *
+ * 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 AUTHOR 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.
+ *
+ */
+
+ /*
+ * Driver for the 8250-like UARTs in the "Apollo Utility" chip (frodo)
+ * found in HP9000/4xx series workstations.
+ *
+ * Draws a lot of code from the dca driver, which handles similar hardware.
+ */
+
+ #include <sys/param.h>
+ #include <sys/systm.h>
+ #include <sys/ioctl.h>
+ #include <sys/proc.h>
+ #include <sys/tty.h>
+ #include <sys/conf.h>
+ #include <sys/file.h>
+ #include <sys/uio.h>
+ #include <sys/kernel.h>
+ #include <sys/syslog.h>
+ #include <sys/device.h>
+
+ #include <machine/autoconf.h>
+ #include <machine/cpu.h>
+
+ #include <dev/cons.h>
+
+ #include "dca.h" /* for NDCA */
+
+ #include <hp300/dev/frodovar.h>
+ #include <hp300/dev/frodoreg.h>
+ #include <hp300/dev/dcareg.h> /* for the register bit defines */
+ #include <hp300/dev/apcireg.h>
+
+ /* #define APCI_DEBUG */
+
+ #ifdef APCI_DEBUG
+ #define D(x) x
+ #else
+ #define D(x)
+ #endif
+
+ struct apci_softc
+ {
+ struct device sc_dev; /* device housekeeping */
+ struct apciregs *sc_apci; /* pointer to hardware */
+ int sc_unit; /* unit number */
+ struct tty *sc_tty;
+ int sc_ferr, sc_perr, sc_oflow, sc_toterr;
+ short sc_flags;
+
+ #define APCI_ACTIVE (1<<0) /* unit is valid */
+ #define APCI_OPEN (1<<1) /* unit is open */
+ #define APCI_FLOWCTRL (1<<2) /* unit has hardware flow control */
+ };
+
+ static int apcimatch(struct device *parent, struct cfdata *match, void *aux);
+ static void apciattach(struct device *parent, struct device *self, void *aux);
+ static int apciintr(void *arg);
+ static void apcieint(struct apci_softc *sc, int stat);
+ static void apcimint(struct apci_softc *sc, u_char stat);
+ static int apciparam(register struct tty *tp, register struct termios *t);
+ static void apcistart(register struct tty *tp);
+ static int apcimctl(struct apci_softc *sc, int bits, int how);
+ static void apciinit(struct apciregs *apci, int rate);
+ static void apcitimeout(void *scp);
+
+ static int apcidefaultrate = TTYDEF_SPEED;
+
+ struct speedtab apcispeedtab[] = {
+ { 0, 0 },
+ { 50, APCIBRD(50) },
+ { 75, APCIBRD(75) },
+ { 110, APCIBRD(110) },
+ { 134, APCIBRD(134) },
+ { 150, APCIBRD(150) },
+ { 200, APCIBRD(200) },
+ { 300, APCIBRD(300) },
+ { 600, APCIBRD(600) },
+ { 1200, APCIBRD(1200) },
+ { 1800, APCIBRD(1800) },
+ { 2400, APCIBRD(2400) },
+ { 4800, APCIBRD(4800) },
+ { 9600, APCIBRD(9600) },
+ { 19200, APCIBRD(19200) },
+ { 38400, APCIBRD(38400) },
+ { -1, -1 }
+ };
+
+
+ struct cfattach apci_ca = {
+ sizeof(struct apci_softc), apcimatch, apciattach
+ };
+
+ struct cfdriver apci_cd = {
+ NULL, "apci", DV_TTY
+ };
+
+ cdev_decl(apci);
+
+ /* nothing magic here */
+ #define APCIUNIT(x) minor(x)
+
+ static int
+ apcimatch(struct device *parent, struct cfdata *match, void *aux)
+ {
+ struct frodo_attach_args *fa = aux;
+
+ /* check unit # */
+ if (match->cf_unit >= APCI_MAXPORT) {
+ return(0);
+ }
+ /* XXX This is Not the right way to go about this */
+ #if NDCA > 0
+ if (fa->fa_channel == 1) {
+ D(printf("apci%d: disabled due to conflict with dca0\n", match->cf_unit));
+ return(0);
+ }
+ #endif
+ return(1);
+ }
+
+ static void
+ apciattach(struct device *parent, struct device *self, void *aux)
+ {
+ struct apci_softc *sc = (struct apci_softc *)self;
+ struct frodo_attach_args *fa = aux;
+
+ /* base address for registers (space is already mapped) */
+ sc->sc_apci = (struct apciregs *)FRODO_STOV(fa->fa_channel);
+ sc->sc_unit = self->dv_unit;
+ sc->sc_flags = APCI_ACTIVE;
+
+ /* register our interrupt handler */
+ frodo_intr_establish(parent, apciintr, sc, APCI_INTR0 + fa->fa_channel);
+
+ /* per-unit special processing (note switch on channel not unit number) */
+ switch (fa->fa_channel) {
+ case 1: /* console port in apollo mode */
+ case 2:
+ case 3:
+ sc->sc_flags |= APCI_FLOWCTRL;
+ break;
+ default:
+ }
+
+ printf(": 8250-like UART\n");
+ }
+
+ int
+ apciopen(dev_t dev, int flag, int mode, struct proc *p)
+ {
+ int unit = APCIUNIT(dev);
+ struct apci_softc *sc;
+ struct tty *tp;
+ struct apciregs *apci;
+ u_char code;
+ int s, error = 0;
+
+ if ((unit >= apci_cd.cd_ndevs) ||
+ ((sc = apci_cd.cd_devs[unit]) == NULL) ||
+ !(sc->sc_flags & APCI_ACTIVE))
+ return(ENXIO); /* nup, not happy */
+
+ D(printf("%s: open\n", sc->sc_dev.dv_xname, unit));
+
+ apci = sc->sc_apci;
+ if (sc->sc_tty == NULL) {
+ tp = sc->sc_tty = ttymalloc();
+ tty_attach(tp);
+ } else {
+ tp = sc->sc_tty;
+ }
+ tp->t_oproc = apcistart;
+ tp->t_param = apciparam;
+ tp->t_dev = dev;
+
+ if ((tp->t_state & TS_ISOPEN) == 0) {
+ /*
+ * Sanity clause: reset the card on first open.
+ * The card might be left in an inconsistent state
+ * if card memory is read inadvertently.
+ */
+ apciinit(apci, apcidefaultrate);
+
+ tp->t_state |= TS_WOPEN;
+ 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 = apcidefaultrate;
+
+ s = spltty();
+
+ apciparam(tp, &tp->t_termios);
+ ttsetwater(tp);
+
+ /* Flush any pending I/O */
+ while ((apci->ap_iir & IIR_IMASK) == IIR_RXRDY)
+ code = apci->ap_data;
+ } else if (tp->t_state&TS_XCLUDE && p->p_ucred->cr_uid != 0)
+ return (EBUSY);
+ else
+ s = spltty();
+
+ /* if port has flow control */
+ if (sc->sc_flags & APCI_FLOWCTRL) {
+ /* Set modem control state */
+ (void)apcimctl(sc, MCR_DTR | MCR_RTS, DMSET);
+ /* Wait for carrier if necessary. */
+ if ((flag & O_NONBLOCK) == 0)
+ while ((tp->t_cflag & CLOCAL) == 0 &&
+ (tp->t_state & TS_CARR_ON) == 0) {
+ tp->t_state |= TS_WOPEN;
+ error = ttysleep(tp, (caddr_t)&tp->t_rawq,
+ TTIPRI | PCATCH, ttopen, 0);
+ if (error) {
+ splx(s);
+ D(printf("\n"));
+ return (error);
+ }
+ }
+ } else {
+ /* fake carrier */
+ tp->t_state |= TS_CARR_ON;
+ }
+
+ splx(s);
+
+ if (error == 0)
+ error = (*linesw[tp->t_line].l_open)(dev, tp);
+
+ if (error == 0)
+ sc->sc_flags |= APCI_OPEN;
+
+ /* clear errors, start timeout */
+ sc->sc_ferr = sc->sc_perr = sc->sc_oflow = sc->sc_toterr = 0;
+ timeout(apcitimeout, sc, hz);
+ return(error);
+ }
+
+ int
+ apciclose(dev_t dev, int flag, int mode, struct proc *p)
+ {
+ int unit = APCIUNIT(dev);
+ struct apci_softc *sc = apci_cd.cd_devs[unit];
+ struct tty *tp = sc->sc_tty;
+ struct apciregs *apci = sc->sc_apci;
+ int s;
+
+ D(printf("%s: close\n", sc->sc_dev.dv_xname, unit));
+
+ (*linesw[tp->t_line].l_close)(tp, flag);
+
+ s = spltty();
+
+ apci->ap_cfcr &= ~CFCR_SBREAK;
+ apci->ap_ier = 0;
+ if (tp->t_cflag & HUPCL) {
+ /* XXX perhaps only clear DTR */
+ (void)apcimctl(sc, 0, DMSET);
+ }
+ tp->t_state &= ~(TS_BUSY | TS_FLUSH);
+ splx(s);
+ ttyclose(tp);
+ sc->sc_flags &= ~APCI_OPEN;
+ return (0);
+ }
+
+ int
+ apciread(dev_t dev, struct uio *uio, int flag)
+ {
+ int unit = APCIUNIT(dev);
+ struct apci_softc *sc = apci_cd.cd_devs[unit];
+ struct tty *tp = sc->sc_tty;
+ int error;
+
+ D(printf("%s: read", sc->sc_dev.dv_xname, unit));
+
+ error = (*linesw[tp->t_line].l_read)(tp, uio, flag);
+ D(printf(" returns %d\n", error));
+ return (error);
+ }
+
+ int
+ apciwrite(dev_t dev, struct uio *uio, int flag)
+ {
+ struct apci_softc *sc = apci_cd.cd_devs[APCIUNIT(dev)];
+ struct tty *tp = sc->sc_tty;
+
+ return((*linesw[tp->t_line].l_write)(tp, uio, flag));
+ }
+
+ static int
+ apciintr(void *arg)
+ {
+ struct apci_softc *sc = arg;
+ register struct apciregs *apci = sc->sc_apci;
+ register struct tty *tp = sc->sc_tty;
+ register u_char iir, c;
+ int iflowdone = 0;
+ int worked = 0;
+
+ D(printf("%s: interrupt", sc->sc_dev.dv_xname, sc->sc_unit));
+
+ for (;;) {
+ iir = apci->ap_iir; /* get UART status */
+ D(printf(" iir %x", iir));
+
+ switch (iir & IIR_IMASK) {
+
+ case IIR_RLS:
+ D(printf(" rls"));
+ apcieint(sc, apci->ap_lsr);
+ break;
+
+ case IIR_RXRDY:
+ case IIR_RXTOUT: /* should unroll somewhat for speed/FIFO here */
+ c = apci->ap_data;
+ D(printf(" rxrdy %x", c));
+
+ if ((tp->t_state & TS_ISOPEN) != 0)
+ (*linesw[tp->t_line].l_rint)(c, tp);
+ if (!iflowdone && (tp->t_cflag&CRTS_IFLOW) &&
+ tp->t_rawq.c_cc > TTYHOG/2) {
+ apci->ap_mcr &= ~MCR_RTS;
+ iflowdone = 1;
+ }
+ break;
+
+ case IIR_TXRDY:
+ D(printf(" txrdy"));
+ tp->t_state &=~ (TS_BUSY|TS_FLUSH);
+ if (tp->t_line)
+ (*linesw[tp->t_line].l_start)(tp);
+ else
+ apcistart(tp);
+ break;
+
+ default:
+ if (iir & IIR_NOPEND) { /* nothing actually pending */
+ D(printf(" done\n"));
+ return (worked);
+ }
+ log(LOG_WARNING, "%s: weird interrupt: 0x%x\n", sc->sc_dev.dv_xname, iir);
+ /* fall through */
+ case IIR_MLSC:
+ D(printf(" mlsc"));
+ apcimint(sc, apci->ap_msr);
+ break;
+ }
+ worked = 1;
+ }
+ }
+
+ static void
+ apcieint(struct apci_softc *sc, int stat)
+ {
+ struct tty *tp = sc->sc_tty;
+ struct apciregs *apci = sc->sc_apci;
+ int c;
+
+ c = apci->ap_data; /* get received character (if any) */
+ D(printf(" %x,%x", stat, c));
+
+ if ((tp->t_state & TS_ISOPEN) == 0) {
+ return;
+ }
+ if (stat & (LSR_BI | LSR_FE)) {
+ c |= TTY_FE;
+ sc->sc_ferr++;
+ } else if (stat & LSR_PE) {
+ c |= TTY_PE;
+ sc->sc_perr++;
+ } else if (stat & LSR_OE) {
+ sc->sc_oflow++;
+ }
+ (*linesw[tp->t_line].l_rint)(c, tp);
+ }
+
+ static void
+ apcimint(struct apci_softc *sc, u_char stat)
+ {
+ struct tty *tp = sc->sc_tty;
+ struct apciregs *apci = sc->sc_apci;
+
+ D(printf(" msr %x", stat));
+
+ if (stat & MSR_DDCD)
+ if (stat & MSR_DCD)
+ (void)(*linesw[tp->t_line].l_modem)(tp, 1);
+ else if ((*linesw[tp->t_line].l_modem)(tp, 0) == 0)
+ apci->ap_mcr &= ~(MCR_DTR | MCR_RTS);
+
+ /*
+ * CTS change.
+ * If doing HW output flow control start/stop output as appropriate.
+ */
+ if ((stat & MSR_DCTS) &&
+ (tp->t_state & TS_ISOPEN) && (tp->t_cflag & CCTS_OFLOW)) {
+ if (stat & MSR_CTS) {
+ tp->t_state &=~ TS_TTSTOP;
+ apcistart(tp);
+ } else {
+ tp->t_state |= TS_TTSTOP;
+ }
+ }
+ }
+
+
+ struct tty *
+ apcitty(dev_t dev)
+ {
+ struct apci_softc *sc = apci_cd.cd_devs[APCIUNIT(dev)];
+
+ return(sc->sc_tty);
+ }
+
+ int
+ apciioctl(dev_t dev, u_long cmd, caddr_t data, int flag, struct proc *p)
+ {
+ int unit = APCIUNIT(dev);
+ struct apci_softc *sc = apci_cd.cd_devs[unit];
+ struct tty *tp = sc->sc_tty;
+ struct apciregs *apci = sc->sc_apci;
+ int error;
+
+ /* handle discipline and tty ioctls first */
+ 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);
+
+ /* ok, so maybe it's for us */
+
+ switch (cmd) {
+ case TIOCSBRK:
+ apci->ap_cfcr |= CFCR_SBREAK;
+ break;
+
+ case TIOCCBRK:
+ apci->ap_cfcr &= ~CFCR_SBREAK;
+ break;
+
+ case TIOCSDTR:
+ (void) apcimctl(sc, MCR_DTR | MCR_RTS, DMBIS);
+ break;
+
+ case TIOCCDTR:
+ (void) apcimctl(sc, MCR_DTR | MCR_RTS, DMBIC);
+ break;
+
+ case TIOCMSET:
+ (void) apcimctl(sc, *(int *)data, DMSET);
+ break;
+
+ case TIOCMBIS:
+ (void) apcimctl(sc, *(int *)data, DMBIS);
+ break;
+
+ case TIOCMBIC:
+ (void) apcimctl(sc, *(int *)data, DMBIC);
+ break;
+
+ case TIOCMGET:
+ *(int *)data = apcimctl(sc, 0, DMGET);
+ break;
+
+ case TIOCGFLAGS: {
+ int bits = 0;
+
+ if (tp->t_cflag & CLOCAL)
+ bits |= TIOCFLAG_CLOCAL;
+
+ *(int *)data = bits;
+ break;
+ }
+
+ case TIOCSFLAGS: {
+ int userbits;
+
+ error = suser(p->p_ucred, &p->p_acflag);
+ if (error)
+ return (EPERM);
+
+ userbits = *(int *)data;
+
+ if (userbits & TIOCFLAG_CLOCAL)
+ tp->t_cflag |= CLOCAL;
+
+ break;
+ }
+
+ default:
+ return(ENOTTY);
+ }
+ return(0);
+ }
+
+ static int
+ apciparam(register struct tty *tp, register struct termios *t)
+ {
+ int unit = APCIUNIT(tp->t_dev);
+ struct apci_softc *sc = apci_cd.cd_devs[unit];
+ struct apciregs *apci = sc->sc_apci;
+ int cfcr, cflag = t->c_cflag;
+ int ospeed = ttspeedtab(t->c_ospeed, apcispeedtab);
+ int s;
+
+ /* check requested parameters */
+ if (ospeed < 0 || (t->c_ispeed && t->c_ispeed != t->c_ospeed))
+ return (EINVAL);
+
+ switch (cflag & CSIZE) {
+ case CS5:
+ cfcr = CFCR_5BITS;
+ break;
+
+ case CS6:
+ cfcr = CFCR_6BITS;
+ break;
+
+ case CS7:
+ cfcr = CFCR_7BITS;
+ break;
+
+ case CS8:
+ cfcr = CFCR_8BITS;
+ break;
+ }
+ if (cflag & PARENB) {
+ cfcr |= CFCR_PENAB;
+ if ((cflag & PARODD) == 0)
+ cfcr |= CFCR_PEVEN;
+ }
+ if (cflag & CSTOPB)
+ cfcr |= CFCR_STOPB;
+
+ s = spltty();
+
+ if (ospeed == 0)
+ (void) apcimctl(sc, 0, DMSET); /* hang up line */
+
+ #if 0
+ if (ospeed != 0) { /* open divisor latch, set speed */
+ apci->ap_cfcr |= CFCR_DLAB;
+ apci->ap_data = ospeed & 0xFF;
+ apci->ap_ier = ospeed >> 8;
+ }
+ apci->ap_cfcr = cfcr; /* set cfcr, close latch if open */
+ #endif
+
+ /* and copy to tty */
+ tp->t_ispeed = t->c_ispeed;
+ tp->t_ospeed = t->c_ospeed;
+ tp->t_cflag = cflag;
+
+ /* set interrupt enables; frodo is already expecting us */
+ apci->ap_ier = IER_ERXRDY | IER_ETXRDY | IER_ERLS | IER_EMSC;
+
+ splx(s);
+ return (0);
+ }
+
+ static void
+ apcistart(register struct tty *tp)
+ {
+ int s, unit = APCIUNIT(tp->t_dev);
+ struct apci_softc *sc = apci_cd.cd_devs[unit];
+ struct apciregs *apci = sc->sc_apci;
+
+ s = spltty();
+
+ if (tp->t_state & (TS_TIMEOUT|TS_TTSTOP))
+ goto out;
+ 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);
+ }
+ if (tp->t_outq.c_cc == 0)
+ goto out;
+ selwakeup(&tp->t_wsel);
+ }
+ if (apci->ap_lsr & LSR_TXRDY) {
+ tp->t_state |= TS_BUSY;
+ apci->ap_data = getc(&tp->t_outq);
+ }
+ out:
+ splx(s);
+ }
+
+
+ /*
+ * stop output on a line
+ */
+ void
+ apcistop(register struct tty *tp, int flag)
+ {
+ register int s;
+
+ s = spltty();
+ /* if busy and not already stopped */
+ if ((tp->t_state & TS_BUSY) && !(tp->t_state & TS_TTSTOP))
+ tp->t_state |= TS_FLUSH;
+ splx(s);
+ }
+
+ static int
+ apcimctl(struct apci_softc *sc, int bits, int how)
+ {
+ struct apciregs *apci = sc->sc_apci;
+ int s;
+
+ return(0);
+
+ /*
+ * Always make sure MCR_IEN is set (unless setting to 0)
+ */
+ if (how == DMBIS || (how == DMSET && bits))
+ bits |= MCR_IEN;
+ else if (how == DMBIC)
+ bits &= ~MCR_IEN;
+ s = spltty();
+
+ switch (how) {
+ case DMSET:
+ apci->ap_mcr = bits;
+ break;
+
+ case DMBIS:
+ apci->ap_mcr |= bits;
+ break;
+
+ case DMBIC:
+ apci->ap_mcr &= ~bits;
+ break;
+
+ case DMGET:
+ bits = apci->ap_msr;
+ break;
+ }
+ (void) splx(s);
+ return(bits);
+ }
+
+ static void
+ apciinit(struct apciregs *apci, int rate)
+ {
+ int s;
+ short stat;
+
+ s = spltty();
+
+ rate = ttspeedtab(rate, apcispeedtab);
+ #if 0
+ apci->ap_cfcr = CFCR_DLAB;
+ /* get old divisor */
+ orate = ((int)apci->ap_ier << 8) + apci->ap_data;
+ D(printf("apciinit: old divisor %d\n", orate));
+ apci->ap_data = rate & 0xFF;
+ apci->ap_ier = rate >> 8;
+ apci->ap_cfcr = CFCR_8BITS;
+ #endif
+ apci->ap_ier = IER_ERXRDY | IER_ETXRDY;
+ /* do this like HP seems to */
+ apci->ap_fifo = FIFO_ENABLE | FIFO_XMT_RST;
+ apci->ap_fifo = FIFO_ENABLE | FIFO_RCV_RST;
+ apci->ap_mcr = MCR_DTR | MCR_RTS;
+ DELAY(100);
+ stat = apci->ap_iir;
+ splx(s);
+ }
+
+ static void
+ apcitimeout(void *scp)
+ {
+ struct apci_softc *sc = scp;
+ int ferr, perr, oflow;
+ int s;
+
+ if (!(sc->sc_flags & APCI_OPEN))
+ return; /* port closed */
+
+ /* errors? */
+ if (sc->sc_ferr || sc->sc_perr || sc->sc_oflow) {
+ s = spltty(); /* disable interrupts for as short as possible */
+ ferr = sc->sc_ferr;
+ perr = sc->sc_perr;
+ oflow = sc->sc_oflow;
+ sc->sc_ferr = sc->sc_perr = sc->sc_oflow = 0;
+ splx(s);
+ sc->sc_toterr += ferr + perr + oflow;
+ printf("%s: errors %d frame %d parity %d overflow %d total",
+ sc->sc_dev.dv_xname, ferr, perr, oflow, sc->sc_toterr);
+ }
+
+ timeout(apcitimeout, sc, hz);
+ }
+
diff -crN /sys/arch/hp300/dev/apcireg.h dev/apcireg.h
*** /sys/arch/hp300/dev/apcireg.h Tue Apr 15 04:17:50 1997
--- dev/apcireg.h Thu Apr 24 07:36:20 1997
***************
*** 1,4 ****
! /* $NetBSD: apcireg.h,v 1.1 1997/04/14 20:36:11 thorpej Exp $ */
/*
* Copyright (c) 1997 Michael Smith. All rights reserved.
--- 1,4 ----
! /* $NetBSD$ */
/*
* Copyright (c) 1997 Michael Smith. All rights reserved.
***************
*** 23,56 ****
* 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.
*/
#include <hp300/dev/iotypes.h>
! struct apciregs {
! vu_char ap_data;
! u_char pad0[3];
! vu_char ap_ier;
! u_char pad1[3];
! vu_char ap_iir;
! #define ap_fifo ap_iir
! u_char pad2[3];
! vu_char ap_cfcr;
! u_char pad3[3];
! vu_char ap_mcr;
! u_char pad4[3];
! vu_char ap_lsr;
! u_char pad5[3];
! vu_char ap_msr;
! u_char pad6[3];
! vu_char ap_scratch;
};
/* max number of apci ports */
! #define APCI_MAXPORT 4
! /* Frodo interrupt number of lowest apci port */
! #define APCI_INTR0 12
/*
* baudrate divisor calculations.
--- 23,59 ----
* 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.
+ *
*/
#include <hp300/dev/iotypes.h>
! /* 8250-like UART on a 32-bit bus */
! struct apciregs
! {
! vu_char ap_data;
! u_char pad0[3];
! vu_char ap_ier;
! u_char pad1[3];
! vu_char ap_iir;
! #define ap_fifo ap_iir
! u_char pad2[3];
! vu_char ap_cfcr;
! u_char pad3[3];
! vu_char ap_mcr;
! u_char pad4[3];
! vu_char ap_lsr;
! u_char pad5[3];
! vu_char ap_msr;
! u_char pad6[3];
! vu_char ap_scratch;
};
/* max number of apci ports */
! #define APCI_MAXPORT 4
! /* frodo interrupt number of lowest apci port */
! #define APCI_INTR0 12
/*
* baudrate divisor calculations.
***************
*** 59,62 ****
* factor of 500400. (Using exactly 8MHz gives framing errors with
* the Apollo keyboard.)
*/
! #define APCIBRD(x) (500000 / (x))
--- 62,67 ----
* factor of 500400. (Using exactly 8MHz gives framing errors with
* the Apollo keyboard.)
*/
! #define APCIBRD(x) (500400 / (x))
!
!
diff -crN /sys/arch/hp300/dev/dnkbd.c dev/dnkbd.c
*** /sys/arch/hp300/dev/dnkbd.c Wed Dec 31 16:00:00 1969
--- dev/dnkbd.c Thu Apr 24 08:35:57 1997
***************
*** 0 ****
--- 1,704 ----
+ /* $NetBSD$ */
+
+ /*
+ * Copyright (c) 1997 Michael Smith. All rights reserved.
+ *
+ * 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 AUTHOR 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.
+ *
+ */
+
+ /*
+ * Driver for an Apollo keyboard on an 8250-like UART in the "Apollo Utility"
+ * chip (frodo) found in HP9000/4xx series workstations.
+ *
+ * Serial comms is a cut-down subset of that in the apci driver, with the
+ * tty-related stuff removed.
+ *
+ * Random notes on the Apollo keyboard :
+ *
+ * - Powers up in 'cooked' mode, where the alpha keys generate ascii rather
+ * than make/break codes. Other keys seem to behave OK though.
+ *
+ * - Alt L/R keys generate two-byte sequence :
+ * make break
+ * L 0xfe,2 0xfe,3
+ * R 0xfe,0 0xfe,1
+ *
+ * - Mouse activity shows up inline in 4-byte packets introduced with 0xdf.
+ * Byte 1 is 1MRL0000 where M, R, L are the mouse buttons, and 0 is
+ * down, 1 is up.
+ * Byte 2 is 2's complement X movement, +ve to the right.
+ * Byte 3 is 2's complement Y movement, +ve is up.
+ *
+ * - Keyboard recognises commands sent to it, all preceded by 0xff. Commands
+ * are echoed once sent completely.
+ *
+ * 0x00 go to cooked mode.
+ * 0x01 go to 'raw' (scancode) mode.
+ * 0x12,0x21 status report as <id1>\r<id2>\r<model>\r followed by 0xff
+ * and then the cooked/raw status.
+ * 0x21,0x81 beep on XXX beep commands are wrong?
+ * 0x21,0x82 beep off
+ *
+ * Some version examples :
+ *
+ * <3-@> <1-0> <SD-03687-MS> Apollo p/n 007121 REV 00 ('old-style' US layout)
+ * <3-@> <2-0> <SD-03683-MS> Apollo p/n 007121 REV 01 ('old-style' US layout)
+ * <3-@> <2-0> <SD-03980-MS> Apollo 3500? keyboard.
+ * <3-@> <X-X> <RX-60857-HW> HP p/n A1630-82001 R2 ('new-style' off 425t, US layout),
+ * also Apollo p/n 014555-002 ('new-style' off DN5500, US layout).
+ * So, what's the country code?
+ *
+ */
+
+ #include <sys/param.h>
+ #include <sys/systm.h>
+ #include <sys/ioctl.h>
+ #include <sys/proc.h>
+ #include <sys/conf.h>
+ #include <sys/file.h>
+ #include <sys/uio.h>
+ #include <sys/kernel.h>
+ #include <sys/syslog.h>
+ #include <sys/device.h>
+ #include <sys/malloc.h>
+
+ #include <machine/autoconf.h>
+ #include <machine/cpu.h>
+
+ #include <dev/cons.h>
+
+ #include <hp300/hp300/led.h>
+
+ #include "dnkbd.h" /* for NDNKBD */
+ #include "ite.h" /* for NITE */
+
+ #include <hp300/dev/frodovar.h>
+ #include <hp300/dev/frodoreg.h>
+ #include <hp300/dev/dcareg.h> /* for the register bit defines */
+ #include <hp300/dev/apcireg.h>
+ #include <hp300/dev/itevar.h>
+ #include <hp300/dev/kbdvar.h>
+ #include <hp300/dev/dnkbd_keymaps.h>
+
+
+ /* #define DNKBD_DEBUG*/
+
+ #ifdef DNKBD_DEBUG
+ #define D(x) x
+ #else
+ #define D(x)
+ #endif
+
+ #define DNKBD_RAW 0x01 /* keyboard operation modes */
+ #define DNKBD_COOKED 0x00
+
+ #define KC_BREAK 0x80 /* mask for 'break' code */
+ #define KC_REPEAT 0x7f /* auto-repeat code */
+
+ #define KB_IDLE 0 /* quiescent */
+ #define KB_MPKT 1 /* reassembling a mouse packet */
+
+ struct dnkbd_softc
+ {
+ struct device sc_dev; /* device housekeeping */
+ struct apciregs *sc_apci; /* pointer to hardware */
+
+ char id1[8], id2[8]; /* keyboard revision identifiers */
+ char model[16];
+ };
+
+ static struct dn_kbdmap *dnkbd_keymap;
+
+ static int dnkbdmatch(struct device *parent, struct cfdata *match, void *aux);
+ static void dnkbdattach(struct device *parent, struct device *self, void *aux);
+ static int dnkbdintr(void *arg);
+
+ static void dnkbd_setup(struct dnkbd_softc *sc, int verbose);
+ static int dnkbd_scodexlt(int c, int polling);
+ static int dnkbd_command(struct apciregs *apci, int cmdlen, u_char *command);
+ static int dnkbd_pollin(struct apciregs *apci, int timeout);
+ static void dnkbd_pollout(struct apciregs *apci, int c);
+ static void dnkbd_pollflush(struct apciregs *apci);
+ static void dnkbd_apciinit(struct apciregs *apci);
+
+ struct cfattach dnkbd_ca = {
+ sizeof(struct dnkbd_softc), dnkbdmatch, dnkbdattach
+ };
+
+ struct cfdriver dnkbd_cd = {
+ NULL, "dnkbd", DV_TTY
+ };
+
+ cdev_decl(dnkbd);
+
+ static int rep_div = 2; /* auto-repeat divisor */
+ static int rep_delay = 10; /* auto-repeat initial delay */
+
+ #define DNKBDUNIT(x) (minor(x) >> 1) /* LSB is keyboard/mouse selector */
+ #define DNKBDDEV(x) (minor(x) & 1)
+
+ #define DNKBD_KBD 0 /* minor encoding */
+ #define DNKBD_MSE 1
+
+ /*
+ ** dnkbdmatch
+ **
+ ** Only allow one instance, as we have lots of static data in the
+ ** scancode state machine.
+ */
+ static int
+ dnkbdmatch(struct device *parent, struct cfdata *match, void *aux)
+ {
+ static int initted = 0;
+
+ if (initted++)
+ return(0);
+ return(1);
+ }
+
+ /*
+ ** dnkbdattach
+ **
+ ** Do attach and initialise hardware.
+ */
+ static void
+ dnkbdattach(struct device *parent, struct device *self, void *aux)
+ {
+ struct dnkbd_softc *sc = (struct dnkbd_softc *)self;
+ struct frodo_attach_args *fa = aux;
+
+ /* base address for registers (space is already mapped) */
+ sc->sc_apci = (struct apciregs *)FRODO_STOV(fa->fa_channel);
+
+ /* register our interrupt handler */
+ frodo_intr_establish(parent, dnkbdintr, sc, APCI_INTR0);
+
+ dnkbd_apciinit(sc->sc_apci); /* configure UART */
+ dnkbd_setup(sc, 1); /* setup keyboard, interrogate */
+
+ printf("\n");
+
+ /* now enable keyboard interrupts, I think we're ready */
+ sc->sc_apci->ap_ier = IER_ERXRDY; /* enable RX interrupts */
+ }
+
+ /*
+ ** dnkbd_setup
+ **
+ ** Talk to the keyboard (in non-interrupt-driven mode).
+ ** Find out what it is, then set it to raw mode.
+ */
+ static void
+ dnkbd_setup(struct dnkbd_softc *sc, int verbose)
+ {
+ u_char crbuf[32];
+ int i, j, c;
+
+ crbuf[0] = 0x12; /* send 'what are you' command */
+ crbuf[1] = 0x21;
+ if (dnkbd_command(sc->sc_apci, 2, crbuf)) {
+ if (verbose)
+ printf(" no keyboard");
+ return;
+ }
+
+ for (i = 0; i < (sizeof(crbuf) - 1); i++) {
+ c = dnkbd_pollin(sc->sc_apci, 100000);
+ if (c == -1) /* timeout */
+ break;
+ crbuf[i] = c; /* got a character */
+ }
+ crbuf[i] = 0;
+
+ for (i = 0, j = 0; (j < sizeof(sc->id1)) && (crbuf[i] != '\r'); i++, j++)
+ sc->id1[j] = crbuf[i]; /* copy up to \r */
+ sc->id1[j] = 0; /* terminate */
+ for (i++, j = 0; (j < sizeof(sc->id2)) && (crbuf[i] != '\r'); i++, j++)
+ sc->id2[j] = crbuf[i]; /* copy up to \r */
+ sc->id2[j] = 0; /* terminate */
+ for (i++, j = 0; (j < sizeof(sc->model)) && (crbuf[i] != '\r'); i++, j++)
+ sc->model[j] = crbuf[i]; /* copy up to \r */
+ sc->model[j] = 0; /* terminate */
+
+ if (verbose) /* tell what we know? */
+ printf(": <%s>", sc->model);
+
+ crbuf[0] = DNKBD_RAW; /* set for raw mode */
+ if (dnkbd_command(sc->sc_apci, 1, crbuf)) {
+ if (verbose)
+ printf(" (raw mode failed)");
+ return;
+ }
+ }
+
+ /*
+ ** dnkbdopen
+ */
+ int
+ dnkbdopen(dev_t dev, int flag, int mode, struct proc *p)
+ {
+ D(printf("dnkbdopen:\n"));
+ return(ENXIO);
+ }
+
+ /*
+ ** dnkbdclose
+ */
+ int
+ dnkbdclose(dev_t dev, int flag, int mode, struct proc *p)
+ {
+ D(printf("dnkbdclose:\n"));
+ return (ENXIO);
+ }
+
+ /*
+ ** dnkbdread
+ */
+ int
+ dnkbdread(dev_t dev, struct uio *uio, int flag)
+ {
+ D(printf("dnkbdread:\n"));
+ return(0);
+ }
+
+ /*
+ ** dnkbd_scodexlt
+ **
+ ** Process an incoming scancode. If (polling) is true, returns
+ ** a keypress or -1, otherwise passes key events off to ite and returns
+ ** zero if it did any work.
+ */
+ static int
+ dnkbd_scodexlt(int c, int polling)
+ {
+ /*
+ * Keep our state here because we may need it before the softc is
+ * allocated. XXX ick.
+ */
+ static int inpstate = KB_IDLE; /* state of the input parse engine */
+ static int currkey = -1; /* the last 'normal' scancode we received */
+ static int rep_cnt; /* auto-repeat counter */
+ static int mpbuf[4]; /* reassembly buffer for mouse packet */
+ static int mplen; /* mouse packet length counter */
+ static int inpmod = 0; /* input modifier(s) */
+
+ int kbreak;
+ int retval = -1; /* default to no output */
+ int xc; /* translated code */
+ int i;
+
+ switch (inpstate) { /* what are we doing just now? */
+
+ default:
+ case KB_IDLE: /* waiting for a key or prefix */
+
+ /* check for mouse traffic */
+ if (c == 0xdf) { /* mouse packet starts */
+ mplen = 0;
+ mpbuf[0] = c;
+ inpstate = KB_MPKT;
+ break;
+ }
+
+ /* get make/break status, mask to keycode */
+ kbreak = c & KC_BREAK; /* check for break code */
+ c = c & 0x7f; /* mask extraneous rubbish */
+
+ /* not mouse, how about auto-repeat? */
+ if (c == KC_REPEAT) { /* auto-repeat scancode */
+ if (currkey == -1) /* no code to repeat */
+ break; /* do nothing, and do it right now */
+ if (++rep_cnt < rep_div)
+ break; /* not time for another one yet */
+ c = currkey; /* time to repeat */
+ rep_cnt = 0; /* wait for next time */
+ }
+
+ /* break code on repeating key? */
+ if (kbreak && (c == currkey)) { /* repeating key goes up */
+ currkey = -1; /* stop repeating */
+ break; /* nothing more to do */
+ }
+
+ /* look up the translated version of our scancode */
+ switch (inpmod) { /* which keymap? */
+ case K_CAP:
+ case K_SHF:
+ xc = dnkbd_keymap->kbd_shiftmap[c];
+ break;
+ case K_CTL:
+ xc = dnkbd_keymap->kbd_ctrlmap[c];
+ break;
+ case K_SHF | K_CTL:
+ case K_SHF | K_CAP | K_CTL:
+ xc = dnkbd_keymap->kbd_ctrlshiftmap[c];
+ break;
+ default: /* includes meta state */
+ xc = dnkbd_keymap->kbd_keymap[c];
+ break;
+ }
+
+ switch (xc) { /* do what with it? */
+
+ case K_CAP: /* modifier? */
+ case K_SHF:
+ case K_CTL:
+ case K_ALT:
+ inpmod = kbreak ? inpmod & ~xc : inpmod | xc;
+ break;
+
+ case K_IGN: /* do-nothing? */
+ if (!polling && !kbreak) /* ought to check the stringmap */
+ if (dnkbd_keymap->kbd_stringmap[c] != NULL) {
+ if (currkey != c) { /* new interesting key? */
+ currkey = c; /* initialise auto-repeat counter */
+ rep_cnt = -rep_delay;
+ }
+ for (i = 0; dnkbd_keymap->kbd_stringmap[c][i] != 0; i++)
+ itekbdin(dnkbd_keymap->kbd_stringmap[c][i]);
+ retval = 0; /* did something */
+ }
+ break;
+
+ case K_DBG: /* XXX break to debugger? */
+ break;
+
+ default: /* keystroke that we might care about */
+ if (!kbreak) {
+ if (currkey != c) { /* new interesting key? */
+ currkey = c; /* initialise auto-repeat counter */
+ rep_cnt = -rep_delay;
+ }
+ if (inpmod & K_ALT)
+ xc |= 0x80; /* meta-mode */
+ if (polling) {
+ retval = xc; /* this is what we have */
+ } else {
+ D(printf("[%x:%x]", inpmod, xc));
+ itekbdin(xc); /* give it to ite */
+ retval = 0; /* did something */
+ }
+ }
+ break;
+ }
+ break;
+
+ case KB_MPKT: /* reassembling a rodent datagram */
+ mpbuf[mplen++] = c; /* another byte */
+ if (mplen >= 4) { /* got the packet ?*/
+ inpstate = KB_IDLE; /* go idle */
+ }
+ break;
+ }
+ return(retval);
+ }
+
+ /*
+ ** dnkbdintr
+ **
+ ** Take an interrupt. The only interrupts we believe in
+ ** are receive interrupts; anything else is either bogus
+ ** or useless.
+ */
+ static int
+ dnkbdintr(void *arg)
+ {
+ struct dnkbd_softc *sc = arg;
+ register struct apciregs *apci = sc->sc_apci;
+ register u_char iir, lsr;
+ register int c;
+
+ for (;;) {
+ iir = apci->ap_iir; /* get UART status */
+
+ switch (iir & IIR_IMASK) {
+
+ case IIR_RLS: /* should never happen */
+ c = apci->ap_lsr; /* do this to clear interrupt */
+ break;
+
+ case IIR_RXRDY: /* data arriveth */
+ case IIR_RXTOUT:
+ while ((lsr = apci->ap_lsr) & LSR_RXRDY) {
+ /* convert to kbd event, give to ite */
+ (void)dnkbd_scodexlt(apci->ap_data, 0);
+ }
+ break;
+
+ case IIR_TXRDY: /* not interesting, shouldn't happen */
+ break;
+
+ case IIR_MLSC:
+ c = apci->ap_msr; /* clear the interrupt */
+ break;
+
+ default:
+ if (iir & IIR_NOPEND) { /* nothing pending now */
+ return(1); /* always claim we did something */
+ }
+ panic("%s: bogus interrupt iir %x", sc->sc_dev.dv_xname, iir);
+ }
+ }
+ }
+
+ /*
+ ** dnkbdioctl
+ **
+ ** No ioctls (yet)
+ */
+ int
+ dnkbdioctl(dev_t dev, u_long cmd, caddr_t data, int flag, struct proc *p)
+ {
+
+ /* what should we support, and how? */
+
+ switch (cmd) {
+ default:
+ return(ENOTTY);
+ }
+ return(0);
+ }
+
+ /*
+ ** dnkbdpoll
+ **
+ ** poll interface, not implemented yet.
+ */
+ int
+ dnkbdpoll(dev_t dev, int events, struct proc *p)
+ {
+ return(0);
+ }
+
+ /*
+ ** dnkbd_command
+ **
+ ** Send and wait for acknowledgement of (command).
+ ** XXX this can take hundreds of milliseconds, spent at spltty.
+ ** Should _not_ be used other than at system startup time.
+ */
+ static int
+ dnkbd_command(struct apciregs *apci, int cmdlen, u_char *command)
+ {
+ int s, i, c;
+
+ s = spltty();
+
+ dnkbd_pollflush(apci); /* dump input queue */
+ dnkbd_pollout(apci, 0xff); /* send command escape */
+ for (i = 0; i < cmdlen; i++)
+ dnkbd_pollout(apci, command[i]); /* send command bytes */
+
+ do { /* wait for echo */
+ c = dnkbd_pollin(apci, 0);
+ if (c == -1) {
+ return(EIO);
+ }
+ } while (c != 0xff);
+
+ for (i = 0; i < cmdlen; i++) { /* wait for command echo */
+ c = dnkbd_pollin(apci, 100000);
+ if (c != command[i])
+ return(EIO);
+ }
+ return(0);
+ }
+
+ /*
+ ** Polled-mode input/output/flush, call at spltty() or with UART
+ ** interrupts disabled.
+ */
+ static int
+ dnkbd_pollin(struct apciregs *apci, int timeout)
+ {
+ int c;
+
+ while(!(apci->ap_lsr & LSR_RXRDY)) { /* spin waiting, use lousy timeout */
+ if (timeout != 0) {
+ if (--timeout == 0)
+ return -1;
+ }
+ }
+ c = apci->ap_data;
+ return(c);
+ }
+
+ static void
+ dnkbd_pollout(struct apciregs *apci, int c)
+ {
+ while(!(apci->ap_lsr & LSR_TXRDY))
+ ; /* spin waiting for space to xmit */
+ apci->ap_data = c;
+ }
+
+ static void
+ dnkbd_pollflush(struct apciregs *apci)
+ {
+ int spin = 10; /* more than this and we are in big trouble */
+
+ while(spin-- && (dnkbd_pollin(apci, 10) != -1))
+ ; /* spin discarding data */
+ }
+
+ /*
+ ** dnkbd_apciinit
+ **
+ ** Initialise the apci UART at (apci) for keyboard use. Don't
+ ** play with the interrupt status.
+ */
+ static void
+ dnkbd_apciinit(struct apciregs *apci)
+ {
+ int rate, s;
+
+ s = spltty();
+ rate = APCIBRD(1200); /* keyboard does 1200bps */
+
+ apci->ap_cfcr = CFCR_DLAB;
+ apci->ap_data = rate & 0xFF;
+ apci->ap_ier = rate >> 8;
+ apci->ap_cfcr = CFCR_8BITS | CFCR_PEVEN | CFCR_PENAB;
+ /* do this like HP seems to */
+ apci->ap_fifo = FIFO_ENABLE | FIFO_XMT_RST;
+ apci->ap_fifo = FIFO_ENABLE | FIFO_RCV_RST;
+ apci->ap_mcr = MCR_DTR | MCR_RTS;
+ splx(s);
+ }
+
+ /*
+ ** ITE cooked keyboard functions
+ */
+
+ void
+ dnkbdbell(int unit)
+ {
+ /* XXX Info we have on bell command appears to be wrong? */
+ }
+
+ /*
+ ** dnkbdenable
+ **
+ ** Allow the keyboard to send ite stuff. We can't do that
+ ** until interrupts are enabled, and that happens after this
+ ** anyway, so just clear out anything pending so far.
+ */
+ void
+ dnkbdenable(int unit)
+ {
+ struct apciregs *apci = (struct apciregs *)0x81c000;
+ int s;
+
+ if (unit == 0) {
+ D(printf("dnkbdenable\n"));
+ s = spltty();
+ dnkbd_pollflush(apci); /* drain any input */
+ splx(s);
+ }
+ }
+
+ /*
+ ** dnkbddisable
+ **
+ ** Stop the keyboard sending ite stuff. Not used.
+ */
+ void
+ dnkbddisable(int unit)
+ {
+ struct apciregs *apci = (struct apciregs *)0x81c000;
+ int s;
+
+ if (unit == 0) {
+ D(printf("dnkbdisable\n"));
+ s = spltty();
+ dnkbd_pollflush(apci); /* drain any input */
+ splx(s);
+ }
+ }
+
+
+
+ /*
+ ** Apollo keyboard console support
+ */
+
+ static struct apciregs *dnkbd_cn_device = NULL;
+
+ /*
+ ** dnkbdgetc
+ **
+ ** Read bytes(s) from keyboard, feed through scancode parser, return
+ ** when we have a character.
+ */
+ int
+ dnkbdgetc(void)
+ {
+ struct apciregs *apci = dnkbd_cn_device;
+ int s, c;
+
+ if (apci == NULL) /* not console keyboard */
+ return(0);
+
+ D(printf("dnkbdgetc\n"));
+
+ /* XXX should be splraise? */
+ s = spltty(); /* inhibit interrupts */
+ do {
+ c = dnkbd_scodexlt(dnkbd_pollin(apci, 0), 1); /* get a character, translate */
+ } while (c == -1);
+ splx(s);
+
+ D(printf(" [%x]", c));
+ return(c & 0xff); /* mask rubbish */
+ }
+
+ /*
+ ** dnkbdinit
+ **
+ ** Do enough initialisation of the keyboard UART to
+ ** be able to talk to it, and return 1 if there's actually
+ ** a keyboard plugged in.
+ */
+ int
+ dnkbdinit(void)
+ {
+ struct apciregs *apci = (struct apciregs *)0x81c000;
+ u_char cbuf;
+
+ D(printf("Look for Apollo keyboard at %p...", apci));
+ if (badaddr((caddr_t)apci)) {
+ D(printf("nothing there\n"));
+ return(0);
+ }
+ /* setup UART, not strictly required as the firmware has already done this */
+ dnkbd_apciinit(apci);
+ dnkbd_cn_device = apci; /* save for later reference */
+ cbuf = DNKBD_RAW; /* set for raw mode */
+ if (dnkbd_command(apci, 1, &cbuf)) {
+ D(printf("won't go to raw mode\n"));
+ return(0); /* nope, let it use the HIL default instead */
+ }
+ D(printf("using for console\n"));
+ /* Go with the US keymap for now */
+ dnkbd_keymap = &dnkbd_keymaps[0];
+ return(1);
+ }
diff -crN /sys/arch/hp300/dev/dnkbd_keymaps.h dev/dnkbd_keymaps.h
*** /sys/arch/hp300/dev/dnkbd_keymaps.h Wed Dec 31 16:00:00 1969
--- dev/dnkbd_keymaps.h Wed Apr 23 20:14:40 1997
***************
*** 0 ****
--- 1,247 ----
+ /* $NetBSD$ */
+
+ /*
+ * Copyright (c) 1997 Michael Smith. All rights reserved.
+ *
+ * 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 AUTHOR 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.
+ *
+ */
+
+ /*
+ * Apollo keyboard keymaps.
+ *
+ * Note that, as of now, there is only one keymap, and it is not known
+ * how to determine which keymap a keyboard uses anyway.
+ *
+ * These keymaps assume the keyboard in 'raw' mode (mode 1).
+ */
+
+ struct dn_kbdmap
+ {
+ /* XXX layout identifier? */
+ char *kbd_desc;
+ int *kbd_keymap;
+ int *kbd_shiftmap;
+ int *kbd_ctrlmap;
+ int *kbd_ctrlshiftmap;
+ char **kbd_stringmap;
+ };
+
+ /*
+ * In all maps other than the string maps, the following defines apply :
+ */
+
+ #define K_IGN 0xffff /* ignore the keystroke */
+ #define K_SHF 0x0100 /* set/clear the shift flag */
+ #define K_CTL 0x0200 /* set/clear the control flag */
+ #define K_ALT 0x0400 /* set/clear the alt (meta) flag */
+ #define K_CAP 0x0800 /* set/clear the capslock flag */
+ #define K_DBG 0x8000 /* break to the debugger */
+
+ /*
+ * In the string maps, NULL indicates no string mapping, otherwise
+ * the character string provided will be generated on a key-down
+ * event only.
+ */
+
+ static int dnkbd_us_keymap[] = {
+ /* Ins Line Char F0 F1 F2 F3 07 */
+ K_IGN, K_IGN, K_IGN, K_IGN, K_IGN, K_IGN, K_IGN, K_IGN,
+ /* F4 F5 F6 F7 F8 F9 Again Read 0f */
+ K_IGN, K_IGN, K_IGN, K_IGN, K_IGN, K_IGN, K_IGN, K_IGN,
+ /* Save Abort Help Undo Move Esc 17 */
+ K_IGN, K_IGN, K_IGN, K_IGN, K_IGN, K_IGN, K_IGN, 0x1b,
+ /* 1 2 3 4 5 6 7 8 1f */
+ '1', '2', '3', '4', '5', '6', '7', '8',
+ /* 9 0 - = ` BS BOL 27 */
+ '9', '0', '-', '=', '`', '\b', K_IGN, K_IGN,
+ /* Shell EOL Tab q w e 2f */
+ K_IGN, K_IGN, K_IGN, K_IGN, '\t', 'q', 'w', 'e',
+ /* r t y u i o p [ 37 */
+ 'r', 't', 'y', 'u', 'i', 'o', 'p', '[',
+ /* ] Del kp7 kp8 kp9 kp+ 3f */
+ ']', K_IGN, 0x7f, K_IGN, '7', '8', '9', '+',
+ /* Sleft Up Srght Ctrl a s 47 */
+ K_IGN, K_IGN, K_IGN, K_CTL, K_IGN, K_IGN, 'a', 's',
+ /* d f g h j k l ; 4f */
+ 'd', 'f', 'g', 'h', 'j', 'k', 'l', ';',
+ /* ' Ret \ kp4 kp5 kp6 57 */
+ '\'', K_IGN, '\r', '\\', K_IGN, '4', '5', '6',
+ /* kp- Left Next Rght Rept LShft 5f */
+ '-', K_IGN, K_IGN, K_IGN, K_IGN, K_IGN, K_SHF, K_IGN,
+ /* z x c v b n m , 67 */
+ 'z', 'x', 'c', 'v', 'b', 'n', 'm', ',',
+ /* . / RShft Pop kp1 kp2 6f */
+ '.', '/', K_SHF, K_IGN, K_IGN, K_IGN, '1', '2',
+ /* kp3 Sup Down Sdwn Lalt Space Ralt 77 */
+ '3', K_IGN, K_IGN, K_IGN, K_IGN, K_ALT, ' ', K_ALT,
+ /* kp0 kp. kpEnt 7f */
+ K_IGN, '0', K_IGN, '.', '\r', K_IGN, K_CAP, K_IGN
+ };
+
+ static int dnkbd_us_shiftmap[] = {
+ /* Ins Line Char F0 F1 F2 F3 07 */
+ K_IGN, K_IGN, K_IGN, K_IGN, K_IGN, K_IGN, K_IGN, K_IGN,
+ /* F4 F5 F6 F7 F8 F9 Again Read 0f */
+ K_IGN, K_IGN, K_IGN, K_IGN, K_IGN, K_IGN, K_IGN, K_IGN,
+ /* Save Abort Help Undo Move Esc 17 */
+ K_IGN, K_IGN, K_IGN, K_IGN, K_IGN, K_IGN, K_IGN, K_IGN,
+ /* 1 2 3 4 5 6 7 8 1f */
+ '!', '@', '#', '$', '%', '^', '&', '*',
+ /* 9 0 - = ` BS BOL 27 */
+ '(', ')', '_', '+', '~', K_IGN, K_IGN, K_IGN,
+ /* Shell EOL Tab q w e 2f */
+ K_IGN, K_IGN, K_IGN, K_IGN, K_IGN, 'Q', 'W', 'E',
+ /* r t y u i o p [ 37 */
+ 'R', 'T', 'Y', 'U', 'I', 'O', 'P', '{',
+ /* ] Del kp7 kp8 kp9 kp+ 3f */
+ '}', K_IGN, K_IGN, K_IGN, '7', '8', '9', '+',
+ /* Sleft Up Srght Ctrl a s 47 */
+ K_IGN, K_IGN, K_IGN, K_CTL, K_IGN, K_IGN, 'A', 'S',
+ /* d f g h j k l ; 4f */
+ 'D', 'F', 'G', 'H', 'J', 'K', 'L', ':',
+ /* ' Ret \ kp4 kp5 kp6 57 */
+ '"', K_IGN, K_IGN, '|', K_IGN, '4', '5', '6',
+ /* kp- Left Next Rght Rept LShft 5f */
+ '-', K_IGN, K_IGN, K_IGN, K_IGN, K_IGN, K_SHF, K_IGN,
+ /* z x c v b n m , 67 */
+ 'Z', 'X', 'C', 'V', 'B', 'N', 'M', '<',
+ /* . / RShft Pop kp1 kp2 6f */
+ '>', '?', K_SHF, K_IGN, K_IGN, K_IGN, '1', '2',
+ /* kp3 Sup Down Sdwn Lalt Space Ralt 77 */
+ '3', K_IGN, K_IGN, K_IGN, K_IGN, K_ALT, ' ', K_ALT,
+ /* kp0 kp. kpEnt 7f */
+ K_IGN, '0', K_IGN, '.', '\r', K_IGN, K_CAP, K_IGN
+ };
+
+ static int dnkbd_us_ctrlmap[] = {
+ /* Ins Line Char F0 F1 F2 F3 07 */
+ K_IGN, K_IGN, K_IGN, K_IGN, K_IGN, K_IGN, K_IGN, K_IGN,
+ /* F4 F5 F6 F7 F8 F9 Again Read 0f */
+ K_IGN, K_IGN, K_IGN, K_IGN, K_IGN, K_IGN, K_IGN, K_IGN,
+ /* Save Abort Help Undo Move Esc 17 */
+ K_IGN, K_IGN, K_IGN, K_IGN, K_IGN, K_IGN, K_IGN, K_IGN,
+ /* 1 2 3 4 5 6 7 8 1f */
+ K_IGN, K_IGN, K_IGN, K_IGN, K_IGN, K_IGN, K_IGN, K_IGN,
+ /* 9 0 - = ` BS BOL 27 */
+ K_IGN, K_IGN, K_IGN, K_IGN, K_IGN, K_IGN, K_IGN, K_IGN,
+ /* Shell EOL Tab q w e 2f */
+ K_IGN, K_IGN, K_IGN, K_IGN, K_IGN, 0x11, 0x17, 0x05,
+ /* r t y u i o p [ 37 */
+ 0x12, 0x14, 0x19, 0x15, 0x09, 0x0f, 0x10, K_IGN,
+ /* ] Del kp7 kp8 kp9 kp+ 3f */
+ K_IGN, K_IGN, K_IGN, K_IGN, K_IGN, K_IGN, K_IGN, K_IGN,
+ /* Sleft Up Srght Ctrl a s 47 */
+ K_IGN, K_IGN, K_IGN, K_CTL, K_IGN, K_IGN, 0x01, 0x13,
+ /* d f g h j k l ; 4f */
+ 0x04, 0x06, 0x07, 0x08, 0x0a, 0x0b, 0x0c, K_IGN,
+ /* ' Ret \ kp4 kp5 kp6 57 */
+ K_IGN, K_IGN, K_IGN, 0x1c, K_IGN, K_IGN, K_IGN, K_IGN,
+ /* kp- Left Next Rght Rept LShft 5f */
+ K_IGN, K_IGN, K_IGN, K_IGN, K_IGN, K_IGN, K_SHF, K_IGN,
+ /* z x c v b n m , 67 */
+ 0x1a, 0x18, 0x03, 0x16, 0x02, 0x0e, 0x0d, K_IGN,
+ /* . / RShft Pop kp1 kp2 6f */
+ K_IGN, K_IGN, K_SHF, K_IGN, K_IGN, K_IGN, K_IGN, K_IGN,
+ /* kp3 Sup Down Sdwn Lalt Space Ralt 77 */
+ K_IGN, K_IGN, K_IGN, K_IGN, K_IGN, K_ALT, K_IGN, K_ALT,
+ /* kp0 kp. kpEnt 7f */
+ K_IGN, K_IGN, K_IGN, K_IGN, K_IGN, K_IGN, K_CAP, K_IGN
+ };
+
+ static int dnkbd_us_ctrlshiftmap[] = {
+ /* Ins Line Char F0 F1 F2 F3 07 */
+ K_IGN, K_IGN, K_IGN, K_IGN, K_IGN, K_IGN, K_IGN, K_IGN,
+ /* F4 F5 F6 F7 F8 F9 Again Read 0f */
+ K_IGN, K_IGN, K_IGN, K_IGN, K_IGN, K_IGN, K_IGN, K_IGN,
+ /* Save Abort Help Undo Move Esc 17 */
+ K_IGN, K_IGN, K_IGN, K_IGN, K_IGN, K_IGN, K_IGN, K_IGN,
+ /* 1 2 3 4 5 6 7 8 1f */
+ K_IGN, K_IGN, K_IGN, K_IGN, K_IGN, K_IGN, K_IGN, K_IGN,
+ /* 9 0 - = ` BS BOL 27 */
+ K_IGN, K_IGN, K_IGN, K_IGN, K_IGN, K_IGN, K_IGN, K_IGN,
+ /* Shell EOL Tab q w e 2f */
+ K_IGN, K_IGN, K_IGN, K_IGN, K_IGN, K_IGN, K_IGN, K_IGN,
+ /* r t y u i o p [ 37 */
+ K_IGN, K_IGN, K_IGN, K_IGN, K_IGN, K_IGN, K_IGN, K_IGN,
+ /* ] Del kp7 kp8 kp9 kp+ 3f */
+ K_IGN, K_IGN, K_IGN, K_IGN, K_IGN, K_IGN, K_IGN, K_IGN,
+ /* Sleft Up Srght Ctrl a s 47 */
+ K_IGN, K_IGN, K_IGN, K_CTL, K_IGN, K_IGN, K_IGN, K_IGN,
+ /* d f g h j k l ; 4f */
+ K_IGN, K_IGN, K_IGN, K_IGN, K_IGN, K_IGN, K_IGN, K_IGN,
+ /* ' Ret \ kp4 kp5 kp6 57 */
+ K_IGN, K_IGN, K_IGN, K_IGN, K_IGN, K_IGN, K_IGN, K_IGN,
+ /* kp- Left Next Rght Rept LShft 5f */
+ K_IGN, K_IGN, K_IGN, K_IGN, K_IGN, K_IGN, K_SHF, K_IGN,
+ /* z x c v b n m , 67 */
+ K_IGN, K_IGN, K_IGN, K_IGN, K_IGN, K_IGN, K_IGN, K_IGN,
+ /* . / RShft Pop kp1 kp2 6f */
+ K_IGN, K_IGN, K_SHF, K_IGN, K_IGN, K_IGN, K_IGN, K_IGN,
+ /* kp3 Sup Down Sdwn Lalt Space Ralt 77 */
+ K_IGN, K_IGN, K_IGN, K_IGN, K_IGN, K_ALT, K_IGN, K_ALT,
+ /* kp0 kp. kpEnt 7f */
+ K_IGN, K_IGN, K_IGN, K_IGN, K_IGN, K_IGN, K_CAP, K_IGN
+ };
+
+ static char *dnkbd_us_stringmap[] = {
+ /* Ins Line Char F0 F1 F2 F3 07 */
+ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
+ /* F4 F5 F6 F7 F8 F9 Again Read 0f */
+ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
+ /* Save Abort Help Undo Move Esc 17 */
+ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
+ /* 1 2 3 4 5 6 7 8 1f */
+ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
+ /* 9 0 - = ` BS BOL 27 */
+ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
+ /* Shell EOL Tab q w e 2f */
+ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
+ /* r t y u i o p [ 37 */
+ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
+ /* ] Del kp7 kp8 kp9 kp+ 3f */
+ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
+ /* Sleft Up Srght Ctrl a s 47 */
+ NULL, "\033A",NULL, NULL, NULL, NULL, NULL, NULL,
+ /* d f g h j k l ; 4f */
+ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
+ /* ' Ret \ kp4 kp5 kp6 57 */
+ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
+ /* kp- Left Next Rght Rept LShft 5f */
+ NULL, "\033D",NULL, "\033C",NULL, NULL, NULL, NULL,
+ /* z x c v b n m , 67 */
+ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
+ /* . / RShft Pop kp1 kp2 6f */
+ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
+ /* kp3 Sup Down Sdwn Lalt Space Ralt 77 */
+ NULL, NULL, NULL, "\033B",NULL, NULL, NULL, NULL,
+ /* kp0 kp. kpEnt 7f */
+ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL
+ };
+
+ static struct dn_kbdmap dnkbd_keymaps[] = {
+ {"US", dnkbd_us_keymap, dnkbd_us_shiftmap, dnkbd_us_ctrlmap,
+ dnkbd_us_ctrlshiftmap, dnkbd_us_stringmap},
+ {NULL, NULL, NULL, NULL, NULL, NULL}
+ };
+
+
diff -crN /sys/arch/hp300/dev/frodo.c dev/frodo.c
*** /sys/arch/hp300/dev/frodo.c Wed Dec 31 16:00:00 1969
--- dev/frodo.c Thu Apr 24 09:35:44 1997
***************
*** 0 ****
--- 1,340 ----
+ /* $NetBSD$ */
+
+ /*
+ * Copyright (c) 1997 Michael Smith. All rights reserved.
+ *
+ * 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 AUTHOR 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.
+ *
+ */
+
+ /*
+ * Support for the "Frodo" (aka "Apollo Utility") chip found in
+ * HP Apollo 9000/4xx workstations.
+ */
+
+ #include <sys/param.h>
+ #include <sys/systm.h>
+ #include <sys/ioctl.h>
+ #include <sys/proc.h>
+ #include <sys/tty.h>
+ #include <sys/conf.h>
+ #include <sys/file.h>
+ #include <sys/uio.h>
+ #include <sys/kernel.h>
+ #include <sys/syslog.h>
+ #include <sys/device.h>
+
+ #include <machine/autoconf.h>
+ #include <machine/cpu.h>
+ #include <machine/intr.h>
+
+ #include <hp300/dev/intiovar.h>
+
+ #include <hp300/dev/frodoreg.h>
+ #include <hp300/dev/frodovar.h>
+
+ /*#define FRODO_DEBUG*/
+
+ #ifdef FRODO_DEBUG
+ #define D(x) x
+ #else
+ #define D(x)
+ #endif
+
+ struct frodo_isr
+ {
+ int (*isr_func)(void *);
+ caddr_t isr_arg;
+ };
+
+ struct frodo_softc
+ {
+ struct device sc_dev; /* device glue */
+ vu_char *sc_base; /* base address of the Frodo part */
+ u_long sc_ints[16]; /* interrupt counters */
+ struct frodo_isr sc_isr[FRODO_NISR]; /* interrupt handlers */
+ };
+
+ static int frodomatch(struct device *parent, struct cfdata *cf, void *aux);
+ static void frodoattach(struct device *parent, struct device *self, void *aux);
+ static int frodoprint(void *aux, const char *pnp);
+ static int frodosearch(struct device *parent, struct cfdata *cf, void *aux);
+ static int frodointr(void *);
+ static int frodonullintr(void *arg);
+ void frodo_dumpregs(void);
+ void frodo_intcount(struct frodo_softc *sc);
+
+ struct cfattach frodo_ca = {
+ sizeof(struct frodo_softc), frodomatch, frodoattach
+ };
+
+ struct cfdriver frodo_cd = {
+ NULL, "frodo", DV_DULL
+ };
+
+ static int
+ frodomatch(struct device *parent, struct cfdata *match, void *aux)
+ {
+ caddr_t fbase;
+ struct intio_attach_args *ia = (struct intio_attach_args *)aux;
+ static int frodo_matched = 0;
+
+ if (frodo_matched) { /* only allow one instance */
+ D(printf("Duplicate frodomatch!\n"));
+ return(0);
+ }
+
+ switch (machineid) {
+ case HP_400:
+ case HP_425:
+ case HP_433:
+ fbase = (caddr_t)IIOV(FRODO_BASE);
+ if (!badaddr(fbase)) { /* is there anything there? */
+ ia->ia_addr = fbase;
+ frodo_matched = 1;
+ return(1);
+ }
+ }
+ return(0);
+ }
+
+ static void
+ frodoattach(struct device *parent, struct device *self, void *aux)
+ {
+ struct frodo_softc *sc = (struct frodo_softc *)self;
+ struct intio_attach_args *ia = aux;
+ int i;
+
+ /* clear interrupt counters, other setup */
+ bzero(sc->sc_ints, sizeof(sc->sc_ints));
+ sc->sc_base = (vu_char *)ia->ia_addr;
+
+ /* we could use this for something, I'm sure. */
+ if (!(sc->sc_base[FRODO_IISR] & FRODO_IISR_SERVICE))
+ printf(" (Service Mode)");
+
+ printf("\n");
+
+ /* disable all frodo interrupts, reenabled as devices attach */
+ frodo_imask(sc, 0, 0xffff);
+ /* clear any pending frodo interrupts (some sources claim these are read-only) */
+ sc->sc_base[FRODO_PIC_PU] = sc->sc_base[FRODO_PIC_PL] = 0xff;
+ /* set interrupt polarities */
+ sc->sc_base[FRODO_PIO_IPR] = 0x10;
+ /* all interrupts are edge triggered (except DMA, which we don't care about) */
+ sc->sc_base[FRODO_PIO_IELR] = 0xcf;
+
+ /* clear interrupt handlers */
+ for (i = 0; i < FRODO_NISR; i++) {
+ sc->sc_isr[i].isr_func = frodonullintr;
+ sc->sc_isr[i].isr_arg = (caddr_t)i;
+ }
+
+ /*
+ * Establish our interrupt handler - moderate priority. This
+ * should be raised if people think that they are going to do
+ * anything serious with the serial ports.
+ *
+ * We do this before searching for subdevices so that they can
+ * generate interrupts immediately.
+ */
+ (void)intr_establish(frodointr, sc, 5, IPL_TTY);
+
+ /* search for and attach subdevices */
+ config_search(frodosearch, self, NULL);
+
+ D(frodo_dumpregs());
+ }
+
+ static int
+ frodoprint(void *aux, const char *pnp)
+ {
+ struct frodo_attach_args *fa = aux;
+
+ printf(",%d", fa->fa_channel);
+ return(UNCONF);
+ }
+
+ static int
+ frodosearch(struct device *parent, struct cfdata *cf, void *aux)
+ {
+ struct frodo_attach_args fa;
+
+ /* clear it */
+ bzero(&fa, sizeof(fa));
+ /* get subdevice number */
+ fa.fa_channel = cf->frodocf_channel;
+ if ((fa.fa_channel >= 0) && (fa.fa_channel < FRODO_MAXDEVS)) {
+ if ((*cf->cf_attach->ca_match)(parent, cf, &fa) > 0)
+ config_attach(parent, cf, &fa, frodoprint);
+ }
+ return(0);
+ }
+
+ /*
+ ** Take a frodo interrupt.
+ **
+ */
+ static int
+ frodointr(void *arg)
+ {
+ struct frodo_softc *sc = arg;
+ int taken = 0;
+ int ipend;
+
+ /* quick look to see if we have a pending interrupt */
+ if (!FRODO_GETPEND(sc->sc_base))
+ return(0); /* not for us, get out */
+
+ do {
+ /*
+ * There is no need to clear the interrupt; reading from here
+ * does that for us
+ */
+ ipend = FRODO_IPEND(sc->sc_base); /* get pending interrupt */
+ (void)sc->sc_isr[ipend].isr_func(sc->sc_isr[ipend].isr_arg);
+ sc->sc_ints[ipend]++; /* increment counter */
+ if (taken++ > 100) { /* too many? */
+ D(frodo_dumpregs());
+ D(frodo_intcount(sc));
+ panic("looped frodo interrupts\n");
+ }
+ } while (FRODO_GETPEND(sc->sc_base));
+
+ return(taken);
+ }
+
+ static int
+ frodonullintr(void *arg)
+ {
+ printf("spurious frodo interrupt %x\n", (int)arg);
+ return(0);
+ }
+
+ /*
+ ** Add a frodo interrupt handler
+ */
+ void
+ frodo_intr_establish(void *scp, int (*func)(void *arg), void *arg, int level)
+ {
+ struct frodo_softc *sc = scp;
+
+ if ((level < 0) || (level >= FRODO_NISR))
+ panic("frodo_intr_establish: bad interrupt level %d", level);
+ if (sc->sc_isr[level].isr_func != frodonullintr)
+ panic("frodo_intr_establish: interrupt %d already allocated", level);
+
+ sc->sc_isr[level].isr_func = func;
+ sc->sc_isr[level].isr_arg = arg;
+
+ /* unmask the interrupt */
+ frodo_imask(sc, (1<<level), 0);
+ }
+
+ void
+ frodo_imask(void *scp, u_short set, u_short clear)
+ {
+ u_short imask;
+ struct frodo_softc *sc = scp;
+
+ /* get current mask */
+ imask = FRODO_GETMASK(sc->sc_base);
+
+ imask |= set;
+ imask &= ~clear;
+
+ FRODO_SETMASK(sc->sc_base, imask);
+ }
+
+ void
+ frodo_dumpregs(void)
+ {
+ u_char *fp = (u_char *)IIOV(FRODO_BASE);
+ int i;
+
+ printf("timer : ");
+ for (i = 0; i < 0xf; i += 2) {
+ printf("%02x", fp[FRODO_TIMER+i]);
+ }
+ printf("\niisr :");
+ if (!(fp[FRODO_IISR] & FRODO_IISR_IOCHK))
+ printf(" IOCHK");
+ if (!(fp[FRODO_IISR] & FRODO_IISR_IHI))
+ printf(" HI");
+ if (!(fp[FRODO_IISR] & FRODO_IISR_IMID))
+ printf(" MID");
+ if (!(fp[FRODO_IISR] & FRODO_IISR_ILOW))
+ printf(" LOW");
+ if (!(fp[FRODO_IISR] & FRODO_IISR_SERVICE))
+ printf(" SERVICE");
+ printf(" (%02x)",fp[FRODO_IISR]);
+
+ printf("\ndiagctl : %02x",fp[FRODO_DIAGCTL]);
+ printf("\npicmask : %c%c%c%c%c%c%c%c %c%c%c%c%c%c%c%c",
+ fp[FRODO_PIC_MU] & 0x80 ? '3':'.',
+ fp[FRODO_PIC_MU] & 0x40 ? '2':'.',
+ fp[FRODO_PIC_MU] & 0x20 ? '1':'.',
+ fp[FRODO_PIC_MU] & 0x10 ? '0':'.',
+ fp[FRODO_PIC_MU] & 0x08 ? '?':'.',
+ fp[FRODO_PIC_MU] & 0x04 ? '?':'.',
+ fp[FRODO_PIC_MU] & 0x02 ? '?':'.',
+ fp[FRODO_PIC_MU] & 0x01 ? '?':'.',
+ fp[FRODO_PIC_ML] & 0x80 ? '?':'.',
+ fp[FRODO_PIC_ML] & 0x40 ? '?':'.',
+ fp[FRODO_PIC_ML] & 0x20 ? '?':'.',
+ fp[FRODO_PIC_ML] & 0x10 ? '?':'.',
+ fp[FRODO_PIC_ML] & 0x08 ? '?':'.',
+ fp[FRODO_PIC_ML] & 0x04 ? '?':'.',
+ fp[FRODO_PIC_ML] & 0x02 ? '?':'.',
+ fp[FRODO_PIC_ML] & 0x01 ? '?':'.');
+
+ printf("\npicpend : %c%c%c%c%c%c%c%c %c%c%c%c%c%c%c%c",
+ fp[FRODO_PIC_PU] & 0x80 ? '3':'.',
+ fp[FRODO_PIC_PU] & 0x40 ? '2':'.',
+ fp[FRODO_PIC_PU] & 0x20 ? '1':'.',
+ fp[FRODO_PIC_PU] & 0x10 ? '0':'.',
+ fp[FRODO_PIC_PU] & 0x08 ? '?':'.',
+ fp[FRODO_PIC_PU] & 0x04 ? '?':'.',
+ fp[FRODO_PIC_PU] & 0x02 ? '?':'.',
+ fp[FRODO_PIC_PU] & 0x01 ? '?':'.',
+ fp[FRODO_PIC_PL] & 0x80 ? '?':'.',
+ fp[FRODO_PIC_PL] & 0x40 ? '?':'.',
+ fp[FRODO_PIC_PL] & 0x20 ? '?':'.',
+ fp[FRODO_PIC_PL] & 0x10 ? '?':'.',
+ fp[FRODO_PIC_PL] & 0x08 ? '?':'.',
+ fp[FRODO_PIC_PL] & 0x04 ? '?':'.',
+ fp[FRODO_PIC_PL] & 0x02 ? '?':'.',
+ fp[FRODO_PIC_PL] & 0x01 ? '?':'.');
+ printf("\npicivr : %02x\n",fp[FRODO_PIC_IVR]);
+ }
+
+ void
+ frodo_intcount(struct frodo_softc *sc)
+ {
+ printf("\nicount : %lx %lx %lx %lx %lx %lx %lx %lx %lx %lx %lx %lx %lx %lx %lx %lx\n",
+ sc->sc_ints[0], sc->sc_ints[1], sc->sc_ints[2], sc->sc_ints[3],
+ sc->sc_ints[4], sc->sc_ints[5], sc->sc_ints[6], sc->sc_ints[7],
+ sc->sc_ints[8], sc->sc_ints[9], sc->sc_ints[10], sc->sc_ints[11],
+ sc->sc_ints[12], sc->sc_ints[13], sc->sc_ints[14], sc->sc_ints[15]);
+ }
+
+
diff -crN /sys/arch/hp300/dev/frodo.c~ dev/frodo.c~
*** /sys/arch/hp300/dev/frodo.c~ Wed Dec 31 16:00:00 1969
--- dev/frodo.c~ Thu Apr 24 08:21:21 1997
***************
*** 0 ****
--- 1,346 ----
+ /* $NetBSD$ */
+
+ /*
+ * Copyright (c) 1997 Michael Smith. All rights reserved.
+ *
+ * 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 AUTHOR 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.
+ *
+ */
+
+ /*
+ * Support for the "Frodo" (aka "Apollo Utility") chip found in
+ * HP Apollo 9000/4xx workstations.
+ */
+
+ #include <sys/param.h>
+ #include <sys/systm.h>
+ #include <sys/ioctl.h>
+ #include <sys/proc.h>
+ #include <sys/tty.h>
+ #include <sys/conf.h>
+ #include <sys/file.h>
+ #include <sys/uio.h>
+ #include <sys/kernel.h>
+ #include <sys/syslog.h>
+ #include <sys/device.h>
+
+ #include <machine/autoconf.h>
+ #include <machine/cpu.h>
+ #include <machine/intr.h>
+
+ #include <hp300/dev/intiovar.h>
+
+ #include <hp300/dev/frodoreg.h>
+ #include <hp300/dev/frodovar.h>
+
+ /*#define FRODO_DEBUG*/
+
+ #ifdef FRODO_DEBUG
+ #define D(x) x
+ #else
+ #define D(x)
+ #endif
+
+ struct frodo_isr
+ {
+ int (*isr_func)(void *);
+ caddr_t isr_arg;
+ };
+
+ struct frodo_softc
+ {
+ struct device sc_dev; /* device glue */
+ vu_char *sc_base; /* base address of the Frodo part */
+ u_long sc_ints[16]; /* interrupt counters */
+ struct frodo_isr sc_isr[FRODO_NISR]; /* interrupt handlers */
+ };
+
+ static int frodomatch(struct device *parent, struct cfdata *cf, void *aux);
+ static void frodoattach(struct device *parent, struct device *self, void *aux);
+ static int frodoprint(void *aux, const char *pnp);
+ static int frodosearch(struct device *parent, struct cfdata *cf, void *aux);
+ static int frodointr(void *);
+ static int frodonullintr(void *arg);
+ void frodo_dumpregs(void);
+ void frodo_intcount(struct frodo_softc *sc);
+
+ struct cfattach frodo_ca = {
+ sizeof(struct frodo_softc), frodomatch, frodoattach
+ };
+
+ struct cfdriver frodo_cd = {
+ NULL, "frodo", DV_DULL
+ };
+
+ static int
+ frodomatch(struct device *parent, struct cfdata *match, void *aux)
+ {
+ caddr_t fbase;
+ struct intio_attach_args *ia = (struct intio_attach_args *)aux;
+ static int frodo_matched = 0;
+
+ if (frodo_matched) { /* only allow one instance */
+ D(printf("Duplicate frodomatch!\n"));
+ return(0);
+ }
+
+ switch (machineid) {
+ case HP_400:
+ case HP_425:
+ case HP_433:
+ fbase = (caddr_t)IIOV(FRODO_BASE);
+ if (!badaddr(fbase)) { /* is there anything there? */
+ ia->ia_addr = fbase;
+ frodo_matched = 1;
+ return(1);
+ }
+ }
+ return(0);
+ }
+
+ static void
+ frodoattach(struct device *parent, struct device *self, void *aux)
+ {
+ struct frodo_softc *sc = (struct frodo_softc *)self;
+ struct intio_attach_args *ia = aux;
+ int i;
+
+ /* clear interrupt counters, other setup */
+ bzero(sc->sc_ints, sizeof(sc->sc_ints));
+ sc->sc_base = (vu_char *)ia->ia_addr;
+
+ /* we could use this for something, I'm sure. */
+ if (!(sc->sc_base[FRODO_IISR] & FRODO_IISR_SERVICE))
+ printf(" (Service Mode)");
+
+ printf("\n");
+
+ /* disable all frodo interrupts, reenabled as devices attach */
+ frodo_imask(sc, 0, 0xffff);
+ /* clear any pending frodo interrupts (some sources claim these are read-only) */
+ sc->sc_base[FRODO_PIC_PU] = sc->sc_base[FRODO_PIC_PL] = 0xff;
+ /* set interrupt polarities */
+ sc->sc_base[FRODO_PIO_IPR] = 0x10;
+ /* all interrupts are edge triggered (except DMA, which we don't care about) */
+ sc->sc_base[FRODO_PIO_IELR] = 0xcf;
+
+ /* clear interrupt handlers */
+ for (i = 0; i < FRODO_NISR; i++) {
+ sc->sc_isr[i].isr_func = frodonullintr;
+ sc->sc_isr[i].isr_arg = (caddr_t)i;
+ }
+
+ /*
+ * Establish our interrupt handler - moderate priority. This
+ * should be raised if people think that they are going to do
+ * anything serious with the serial ports.
+ *
+ * We do this before searching for subdevices so that they can
+ * generate interrupts immediately.
+ */
+ (void)intr_establish(frodointr, sc, 5, IPL_TTY);
+
+ /* search for and attach subdevices */
+ config_search(frodosearch, self, NULL);
+
+ /*
+ * XXX we should perhaps program FRODO_PIC_IVR with something, but
+ * perhaps this is only relevant if we want it to autovector.
+ * Certainly it seems to work just fine without touching it.
+ */
+
+ D(frodo_dumpregs());
+ }
+
+ static int
+ frodoprint(void *aux, const char *pnp)
+ {
+ struct frodo_attach_args *fa = aux;
+
+ printf(",%d", fa->fa_channel);
+ return(UNCONF);
+ }
+
+ static int
+ frodosearch(struct device *parent, struct cfdata *cf, void *aux)
+ {
+ struct frodo_attach_args fa;
+
+ /* clear it */
+ bzero(&fa, sizeof(fa));
+ /* get subdevice number */
+ fa.fa_channel = cf->frodocf_channel;
+ if ((fa.fa_channel >= 0) && (fa.fa_channel < FRODO_MAXDEVS)) {
+ if ((*cf->cf_attach->ca_match)(parent, cf, &fa) > 0)
+ config_attach(parent, cf, &fa, frodoprint);
+ }
+ return(0);
+ }
+
+ /*
+ ** Take a frodo interrupt.
+ **
+ */
+ static int
+ frodointr(void *arg)
+ {
+ struct frodo_softc *sc = arg;
+ int taken = 0;
+ int ipend;
+
+ /* quick look to see if we have a pending interrupt */
+ if (!FRODO_GETPEND(sc->sc_base))
+ return(0); /* not for us, get out */
+
+ do {
+ /*
+ * There is no need to clear the interrupt; reading from here
+ * does that for us
+ */
+ ipend = FRODO_IPEND(sc->sc_base); /* get pending interrupt */
+ (void)sc->sc_isr[ipend].isr_func(sc->sc_isr[ipend].isr_arg);
+ sc->sc_ints[ipend]++; /* increment counter */
+ if (taken++ > 100) { /* too many? */
+ D(frodo_dumpregs());
+ D(frodo_intcount(sc));
+ panic("looped frodo interrupts\n");
+ }
+ } while (FRODO_GETPEND(sc->sc_base));
+
+ return(taken);
+ }
+
+ static int
+ frodonullintr(void *arg)
+ {
+ printf("spurious frodo interrupt %x\n", (int)arg);
+ return(0);
+ }
+
+ /*
+ ** Add a frodo interrupt handler
+ */
+ void
+ frodo_intr_establish(void *scp, int (*func)(void *arg), void *arg, int level)
+ {
+ struct frodo_softc *sc = scp;
+
+ if ((level < 0) || (level >= FRODO_NISR))
+ panic("frodo_intr_establish: bad interrupt level %d", level);
+ if (sc->sc_isr[level].isr_func != frodonullintr)
+ panic("frodo_intr_establish: interrupt %d already allocated", level);
+
+ sc->sc_isr[level].isr_func = func;
+ sc->sc_isr[level].isr_arg = arg;
+
+ /* unmask the interrupt */
+ frodo_imask(sc, (1<<level), 0);
+ }
+
+ void
+ frodo_imask(void *scp, u_short set, u_short clear)
+ {
+ u_short imask;
+ struct frodo_softc *sc = scp;
+
+ /* get current mask */
+ imask = FRODO_GETMASK(sc->sc_base);
+
+ imask |= set;
+ imask &= ~clear;
+
+ FRODO_SETMASK(sc->sc_base, imask);
+ }
+
+ void
+ frodo_dumpregs(void)
+ {
+ u_char *fp = (u_char *)IIOV(FRODO_BASE);
+ int i;
+
+ printf("timer : ");
+ for (i = 0; i < 0xf; i += 2) {
+ printf("%02x", fp[FRODO_TIMER+i]);
+ }
+ printf("\niisr :");
+ if (!(fp[FRODO_IISR] & FRODO_IISR_IOCHK))
+ printf(" IOCHK");
+ if (!(fp[FRODO_IISR] & FRODO_IISR_IHI))
+ printf(" HI");
+ if (!(fp[FRODO_IISR] & FRODO_IISR_IMID))
+ printf(" MID");
+ if (!(fp[FRODO_IISR] & FRODO_IISR_ILOW))
+ printf(" LOW");
+ if (!(fp[FRODO_IISR] & FRODO_IISR_SERVICE))
+ printf(" SERVICE");
+ printf(" (%02x)",fp[FRODO_IISR]);
+
+ printf("\ndiagctl : %02x",fp[FRODO_DIAGCTL]);
+ printf("\npicmask : %c%c%c%c%c%c%c%c %c%c%c%c%c%c%c%c",
+ fp[FRODO_PIC_MU] & 0x80 ? '3':'.',
+ fp[FRODO_PIC_MU] & 0x40 ? '2':'.',
+ fp[FRODO_PIC_MU] & 0x20 ? '1':'.',
+ fp[FRODO_PIC_MU] & 0x10 ? '0':'.',
+ fp[FRODO_PIC_MU] & 0x08 ? '?':'.',
+ fp[FRODO_PIC_MU] & 0x04 ? '?':'.',
+ fp[FRODO_PIC_MU] & 0x02 ? '?':'.',
+ fp[FRODO_PIC_MU] & 0x01 ? '?':'.',
+ fp[FRODO_PIC_ML] & 0x80 ? '?':'.',
+ fp[FRODO_PIC_ML] & 0x40 ? '?':'.',
+ fp[FRODO_PIC_ML] & 0x20 ? '?':'.',
+ fp[FRODO_PIC_ML] & 0x10 ? '?':'.',
+ fp[FRODO_PIC_ML] & 0x08 ? '?':'.',
+ fp[FRODO_PIC_ML] & 0x04 ? '?':'.',
+ fp[FRODO_PIC_ML] & 0x02 ? '?':'.',
+ fp[FRODO_PIC_ML] & 0x01 ? '?':'.');
+
+ printf("\npicpend : %c%c%c%c%c%c%c%c %c%c%c%c%c%c%c%c",
+ fp[FRODO_PIC_PU] & 0x80 ? '3':'.',
+ fp[FRODO_PIC_PU] & 0x40 ? '2':'.',
+ fp[FRODO_PIC_PU] & 0x20 ? '1':'.',
+ fp[FRODO_PIC_PU] & 0x10 ? '0':'.',
+ fp[FRODO_PIC_PU] & 0x08 ? '?':'.',
+ fp[FRODO_PIC_PU] & 0x04 ? '?':'.',
+ fp[FRODO_PIC_PU] & 0x02 ? '?':'.',
+ fp[FRODO_PIC_PU] & 0x01 ? '?':'.',
+ fp[FRODO_PIC_PL] & 0x80 ? '?':'.',
+ fp[FRODO_PIC_PL] & 0x40 ? '?':'.',
+ fp[FRODO_PIC_PL] & 0x20 ? '?':'.',
+ fp[FRODO_PIC_PL] & 0x10 ? '?':'.',
+ fp[FRODO_PIC_PL] & 0x08 ? '?':'.',
+ fp[FRODO_PIC_PL] & 0x04 ? '?':'.',
+ fp[FRODO_PIC_PL] & 0x02 ? '?':'.',
+ fp[FRODO_PIC_PL] & 0x01 ? '?':'.');
+ printf("\npicivr : %02x\n",fp[FRODO_PIC_IVR]);
+ }
+
+ void
+ frodo_intcount(struct frodo_softc *sc)
+ {
+ printf("\nicount : %lx %lx %lx %lx %lx %lx %lx %lx %lx %lx %lx %lx %lx %lx %lx %lx\n",
+ sc->sc_ints[0], sc->sc_ints[1], sc->sc_ints[2], sc->sc_ints[3],
+ sc->sc_ints[4], sc->sc_ints[5], sc->sc_ints[6], sc->sc_ints[7],
+ sc->sc_ints[8], sc->sc_ints[9], sc->sc_ints[10], sc->sc_ints[11],
+ sc->sc_ints[12], sc->sc_ints[13], sc->sc_ints[14], sc->sc_ints[15]);
+ }
+
+
diff -crN /sys/arch/hp300/dev/frodoreg.h dev/frodoreg.h
*** /sys/arch/hp300/dev/frodoreg.h Wed Dec 31 16:00:00 1969
--- dev/frodoreg.h Thu Apr 24 08:03:24 1997
***************
*** 0 ****
--- 1,100 ----
+ /* $NetBSD$ */
+
+ /*
+ * Copyright (c) 1997 Michael Smith. All rights reserved.
+ *
+ * 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 AUTHOR 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.
+ *
+ */
+
+ #include <hp300/dev/iotypes.h>
+
+ /* Base address of the Frodo part */
+ #define FRODO_BASE (INTIOBASE + 0x1c000)
+
+ /* Total number of frodo "devices" (4 UARTs, 3 (E)ISA slots & the timer) */
+ #define FRODO_MAXDEVS 8
+
+ /* Where we find the 8250-like apci ports, and how far apart they are */
+ #define FRODO_APCIBASE 0x0
+ #define FRODO_ACPISPACE 0x20
+
+ /* Other things in the Frodo part */
+ #define FRODO_CALENDAR 0x80 /* mc146818-like calendar */
+ /* calendar has no battery, so we ignore it here */
+
+ #define FRODO_TIMER 0xa0 /* 8254-like timer */
+ #define FRODO_T1_CTR 0xa0 /* counter 1 */
+ #define FRODO_T2_CTR 0xa4 /* counter 2 */
+ #define FRODO_T3_CTR 0xa8 /* counter 3 */
+ #define FRODO_T_CTRL 0xac /* control register */
+ #define FRODO_T_PSCALE 0xb0 /* prescaler */
+ #define FRODO_T_PCOUNT 0xb4 /* precounter ? */
+ #define FRODO_T_OVCOUNT 0xb8 /* overflow counter (0, 1, 2) */
+
+ #define FRODO_PIO 0xc0 /* programmable I/O */
+ #define FRODO_IISR 0xc0 /* ISA Interrupt Status Register (also PIR)*/
+ #define FRODO_IISR_SERVICE (1<<0) /* service switch 'on' if 0 */
+ #define FRODO_IISR_ILOW (1<<1) /* IRQ 3,4,5 or 6 on ISA if 1 */
+ #define FRODO_IISR_IMID (1<<2) /* IRQ 7,9,10 or 11 on ISA if 1 */
+ #define FRODO_IISR_IHI (1<<3) /* IRQ 12,13,14 or 15 on ISA if 1 */
+ /* 4,5 were used for SCSI on the DN2500, 6 is unused */
+ #define FRODO_IISR_IOCHK (1<<7) /* ISA board asserted IOCHK if low */
+ #define FRODO_PIO_IPR 0xc4 /* input polarity register (ints 7->0) */
+ #define FRODO_PIO_IELR 0xc8 /* input edge/level register */
+
+ /* this is probably not used on the 4xx */
+ #define FRODO_DIAGCTL 0xd0 /* Diagnostic Control Register */
+
+ #define FRODO_PIC_MU 0xe0 /* upper Interrupt Mask register */
+ #define FRODO_PIC_ML 0xe4 /* lower Interrupt Mask register */
+ #define FRODO_PIC_PU 0xe8 /* upper Interrupt Pending register */
+ #define FRODO_PIC_PL 0xec /* lower Interrupt Pending register */
+ #define FRODO_PIC_IVR 0xf8 /* Interrupt Vector register */
+ #define FRODO_PIC_ACK 0xfc /* Interrupt Acknowledge */
+
+ /* manipulate interrupt registers */
+ #define FRODO_GETMASK(base) (((u_short)(base[FRODO_PIC_MU])<<8)+base[FRODO_PIC_ML])
+ #define FRODO_SETMASK(base,val) { \
+ base[FRODO_PIC_MU] = (val>>8)&0xff; \
+ base[FRODO_PIC_ML] = val & 0xff; \
+ }
+ #define FRODO_GETPEND(base) (((u_short)(base[FRODO_PIC_PU])<<8)+base[FRODO_PIC_PL])
+ #define FRODO_IPEND(base) ((u_char)(base[FRODO_PIC_ACK]) & 0x0f)
+
+ /* interrupt bits (combined regs) (bit 0 is unused) */
+ #define FRODO_PIC_ILOW (1<<1)
+ #define FRODO_PIC_IMID (1<<2)
+ #define FRODO_PIC_IHI (1<<3)
+ #define FRODO_PIC_SCSIDMA (1<<4) /* unused */
+ #define FRODO_PIC_SCSI (1<<5) /* unused */
+ #define FRODO_PIC_HORIZ (1<<6) /* unused */
+ #define FRODO_PIC_IOCHK (1<<7)
+ #define FRODO_PIC_CALENDAR (1<<8) /* unused */
+ #define FRODO_PIC_TIMER0 (1<<9)
+ #define FRODO_PIC_TIMER1 (1<<10)
+ #define FRODO_PIC_TIMER2 (1<<11)
+ #define FRODO_PIC_APCI0 (1<<12)
+ #define FRODO_PIC_APCI1 (1<<13)
+ #define FRODO_PIC_APCI2 (1<<14)
+ #define FRODO_PIC_APCI3 (1<<15)
+
diff -crN /sys/arch/hp300/dev/frodovar.h dev/frodovar.h
*** /sys/arch/hp300/dev/frodovar.h Wed Dec 31 16:00:00 1969
--- dev/frodovar.h Thu Apr 24 08:04:22 1997
***************
*** 0 ****
--- 1,59 ----
+ /* $NetBSD$ */
+
+ /*
+ * Copyright (c) 1997 Michael Smith. All rights reserved.
+ *
+ * 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 AUTHOR 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.
+ *
+ */
+
+ /*
+ * Autoconfiguration definitions and prototypes for the Frodo ASIC in
+ * the HP9000/4xx series.
+ */
+
+ /*
+ * Arguments used to attach a device to the internal i/o space.
+ */
+ struct frodo_attach_args {
+ int fa_channel; /* subdevice index */
+ };
+ #define frodocf_channel cf_loc[0];
+
+ /*
+ * Translate a frodo subdevice number into an address in IIO space.
+ */
+ #define FRODO_STOV(x) IIOV(((x) * 0x20) + FRODO_BASE)
+
+ /* set/clear frodo interrupts */
+ extern void frodo_imask(void *scp, u_short set, u_short clear);
+
+ /* establish a frodo interrupt */
+ extern void frodo_intr_establish(void *scp, int (*func)(void *arg), void *arg, int level);
+
+ /* number of frodo interrupt handlers */
+ #define FRODO_NISR 16
+
+
+
+
+
diff -crN /sys/arch/hp300/dev/hil.c dev/hil.c
*** /sys/arch/hp300/dev/hil.c Thu Apr 3 04:22:38 1997
--- dev/hil.c Wed Apr 23 22:30:22 1997
***************
*** 59,64 ****
--- 59,65 ----
#include <hp300/dev/hilioctl.h>
#include <hp300/dev/hilvar.h>
#include <hp300/dev/itevar.h>
+ #include <hp300/dev/kbdvar.h>
#include <hp300/dev/kbdmap.h>
#include <machine/cpu.h>
***************
*** 96,107 ****
extern struct emul emul_hpux;
#endif
! /* XXX ITE interface */
! char *kbd_keymap;
! char *kbd_shiftmap;
! char *kbd_ctrlmap;
! char *kbd_ctrlshiftmap;
! char **kbd_stringmap;
/* symbolic sleep message strings */
char hilin[] = "hilin";
--- 97,104 ----
extern struct emul emul_hpux;
#endif
! /* current keyboard maps */
! struct hil_kbdmap *hil_keymap = NULL;
/* symbolic sleep message strings */
char hilin[] = "hilin";
***************
*** 115,120 ****
--- 112,118 ----
int hiliddev __P((struct hil_softc *));
void hilint __P((int));
+ void hil_process_key __P((u_char, u_char));
void hil_process_int __P((struct hil_softc *, u_char, u_char));
void hilevent __P((struct hil_softc *));
void hpuxhilevent __P((struct hil_softc *, struct hilloopdev *));
***************
*** 138,147 ****
struct hil_softc *hilp = &hil_softc[unit];
int i;
- /* XXX ITE interface */
- extern char us_keymap[], us_shiftmap[], us_ctrlmap[],
- us_ctrlshiftmap[], *us_stringmap[];
-
#ifdef DEBUG
if (hildebug & HDB_FOLLOW)
printf("hilsoftinit(%d, %p)\n", unit, hilbase);
--- 136,141 ----
***************
*** 175,185 ****
* keyboards.
*/
hilp->hl_kbdlang = KBD_DEFAULT;
! kbd_keymap = us_keymap; /* XXX */
! kbd_shiftmap = us_shiftmap; /* XXX */
! kbd_ctrlmap = us_ctrlmap; /* XXX */
! kbd_ctrlshiftmap = us_ctrlshiftmap; /* XXX */
! kbd_stringmap = us_stringmap; /* XXX */
}
void
--- 169,175 ----
* keyboards.
*/
hilp->hl_kbdlang = KBD_DEFAULT;
! hil_keymap = &hil_kbd_map[0]; /* default to first map */
}
void
***************
*** 203,209 ****
*/
hilreset(hilp);
hilinfo(unit);
! kbdenable(unit);
}
/* ARGSUSED */
--- 193,199 ----
*/
hilreset(hilp);
hilinfo(unit);
! hilkbdenable(unit);
}
/* ARGSUSED */
***************
*** 362,368 ****
printf("hilclose: keyboard %d cooked\n",
hilp->hl_kbddev);
#endif
! kbdenable(HILLOOP(dev));
}
splx(s);
return (0);
--- 352,358 ----
printf("hilclose: keyboard %d cooked\n",
hilp->hl_kbddev);
#endif
! hilkbdenable(HILLOOP(dev));
}
splx(s);
return (0);
***************
*** 833,838 ****
--- 823,886 ----
#include "ite.h"
void
+ hil_process_key(stat, c)
+ u_char stat, c;
+ {
+ static int capsmode = 0;
+ static int metamode = 0;
+ char code, *str;
+
+ switch (c & 0xFF) {
+ case KBD_CAPSLOCK:
+ capsmode = !capsmode;
+ return;
+
+ case KBD_EXT_LEFT_DOWN:
+ case KBD_EXT_RIGHT_DOWN:
+ metamode = 1;
+ return;
+
+ case KBD_EXT_LEFT_UP:
+ case KBD_EXT_RIGHT_UP:
+ metamode = 0;
+ return;
+ }
+
+ c &= KBD_CHARMASK;
+ switch ((stat>>KBD_SSHIFT) & KBD_SMASK) {
+
+ default:
+ case KBD_KEY:
+ if (!capsmode) {
+ code = hil_keymap->kbd_keymap[c];
+ break;
+ }
+ /* FALLTHROUGH */
+
+ case KBD_SHIFT:
+ code = hil_keymap->kbd_shiftmap[c];
+ break;
+
+ case KBD_CTRL:
+ code = hil_keymap->kbd_ctrlmap[c];
+ break;
+
+ case KBD_CTRLSHIFT:
+ code = hil_keymap->kbd_ctrlshiftmap[c];
+ break;
+ }
+
+ if (code == NULL && (str = hil_keymap->kbd_stringmap[c]) != NULL) {
+ while (*str)
+ itekbdin(*str++);
+ } else {
+ if (metamode)
+ code |= 0x80;
+ itekbdin(code);
+ }
+ }
+
+ void
hil_process_int(hilp, stat, c)
struct hil_softc *hilp;
u_char stat, c;
***************
*** 850,856 ****
case HIL_SHIFT:
case HIL_CTRL:
case HIL_CTRLSHIFT:
! itefilter(stat, c);
return;
#endif
--- 898,904 ----
case HIL_SHIFT:
case HIL_CTRL:
case HIL_CTRLSHIFT:
! hil_process_key(stat, c);
return;
#endif
***************
*** 1152,1158 ****
*/
void
! kbdbell(unit)
int unit;
{
struct hil_softc *hilp = &hil_softc[unit];
--- 1200,1206 ----
*/
void
! hilkbdbell(unit)
int unit;
{
struct hil_softc *hilp = &hil_softc[unit];
***************
*** 1161,1167 ****
}
void
! kbdenable(unit)
int unit;
{
struct hil_softc *hilp = &hil_softc[unit];
--- 1209,1215 ----
}
void
! hilkbdenable(unit)
int unit;
{
struct hil_softc *hilp = &hil_softc[unit];
***************
*** 1181,1187 ****
}
void
! kbddisable(unit)
int unit;
{
}
--- 1229,1235 ----
}
void
! hilkbddisable(unit)
int unit;
{
}
***************
*** 1192,1200 ****
*/
struct hil_dev *hilkbd_cn_device;
- char *kbd_cn_keymap;
- char *kbd_cn_shiftmap;
- char *kbd_cn_ctrlmap;
/*
* XXX: read keyboard directly and return code.
--- 1240,1245 ----
***************
*** 1202,1209 ****
* reading from the keyboard in the normal, interrupt driven fashion.
*/
int
! kbdgetc(statp)
! int *statp;
{
int c, stat;
int s;
--- 1247,1253 ----
* reading from the keyboard in the normal, interrupt driven fashion.
*/
int
! hilkbdgetc(void)
{
int c, stat;
int s;
***************
*** 1220,1226 ****
;
c = READHILDATA(hilkbd_cn_device);
splx(s);
! *statp = stat;
return (c);
}
--- 1264,1284 ----
;
c = READHILDATA(hilkbd_cn_device);
splx(s);
!
! switch ((stat >> KBD_SSHIFT) & KBD_SMASK) {
! case KBD_SHIFT:
! c = hil_keymap->kbd_shiftmap[c & KBD_CHARMASK];
! break;
! case KBD_CTRL:
! c = hil_keymap->kbd_ctrlmap[c & KBD_CHARMASK];
! break;
! case KBD_KEY:
! c = hil_keymap->kbd_keymap[c & KBD_CHARMASK];
! break;
! default:
! c = 0;
! break;
! }
return (c);
}
***************
*** 1228,1249 ****
* Perform basic initialization of the HIL keyboard, suitable
* for early console use.
*/
! void
! kbdcninit()
{
struct hil_dev *h = HILADDR; /* == VA (see hilreg.h) */
! struct kbdmap *km;
u_char lang;
- /* XXX from hil_keymaps.c */
- extern char us_keymap[], us_shiftmap[], us_ctrlmap[];
-
hilkbd_cn_device = h;
! /* Default to US-ASCII keyboard. */
! kbd_cn_keymap = us_keymap;
! kbd_cn_shiftmap = us_shiftmap;
! kbd_cn_ctrlmap = us_ctrlmap;
HILWAIT(h);
WRITEHILCMD(h, HIL_SETARR);
--- 1286,1310 ----
* Perform basic initialization of the HIL keyboard, suitable
* for early console use.
*/
! int
! hilkbdinit()
{
struct hil_dev *h = HILADDR; /* == VA (see hilreg.h) */
! struct hil_kbdmap *km;
u_char lang;
hilkbd_cn_device = h;
! /* see if there's a HIL keyboard there */
! HILWAIT(h);
! WRITEHILCMD(h, HIL_READKBDSADR);
! HILDATAWAIT(h);
! lang = READHILDATA(h);
! if (lang == 0) /* nope, no keyboard */
! return(0);
!
! /* select default keyboard */
! hil_keymap = &hil_kbd_map[0];
HILWAIT(h);
WRITEHILCMD(h, HIL_SETARR);
***************
*** 1253,1267 ****
WRITEHILCMD(h, HIL_READKBDLANG);
HILDATAWAIT(h);
lang = READHILDATA(h);
! for (km = kbd_map; km->kbd_code; km++) {
if (km->kbd_code == lang) {
! kbd_cn_keymap = km->kbd_keymap;
! kbd_cn_shiftmap = km->kbd_shiftmap;
! kbd_cn_ctrlmap = km->kbd_ctrlmap;
}
}
HILWAIT(h);
WRITEHILCMD(h, HIL_INTON);
}
/* End of HIL console keyboard code. */
--- 1314,1327 ----
WRITEHILCMD(h, HIL_READKBDLANG);
HILDATAWAIT(h);
lang = READHILDATA(h);
! for (km = hil_kbd_map; km->kbd_code; km++) {
if (km->kbd_code == lang) {
! hil_keymap = km;
}
}
HILWAIT(h);
WRITEHILCMD(h, HIL_INTON);
+ return(1);
}
/* End of HIL console keyboard code. */
***************
*** 1304,1317 ****
{
struct hil_softc *hilp = &hil_softc[unit];
int id, len;
! struct kbdmap *km;
/*
* Keyboard info.
*/
if (hilp->hl_kbddev) {
printf("hil%d: ", hilp->hl_kbddev);
! for (km = kbd_map; km->kbd_code; km++)
if (km->kbd_code == hilp->hl_kbdlang) {
printf("%s ", km->kbd_desc);
break;
--- 1364,1377 ----
{
struct hil_softc *hilp = &hil_softc[unit];
int id, len;
! struct hil_kbdmap *km;
/*
* Keyboard info.
*/
if (hilp->hl_kbddev) {
printf("hil%d: ", hilp->hl_kbddev);
! for (km = hil_kbd_map; km->kbd_code; km++)
if (km->kbd_code == hilp->hl_kbdlang) {
printf("%s ", km->kbd_desc);
break;
***************
*** 1448,1464 ****
hilp->hl_kbdlang, db);
#endif
if (hilp->hl_kbdlang != KBD_SPECIAL) {
! struct kbdmap *km;
! for (km = kbd_map; km->kbd_code; km++) {
if (km->kbd_code == db) {
hilp->hl_kbdlang = db;
! /* XXX */
! kbd_keymap = km->kbd_keymap;
! kbd_shiftmap = km->kbd_shiftmap;
! kbd_ctrlmap = km->kbd_ctrlmap;
! kbd_ctrlshiftmap = km->kbd_ctrlshiftmap;
! kbd_stringmap = km->kbd_stringmap;
break;
}
}
--- 1508,1519 ----
hilp->hl_kbdlang, db);
#endif
if (hilp->hl_kbdlang != KBD_SPECIAL) {
! struct hil_kbdmap *km;
! for (km = hil_kbd_map; km->kbd_code; km++) {
if (km->kbd_code == db) {
hilp->hl_kbdlang = db;
! hil_keymap = km;
break;
}
}
diff -crN /sys/arch/hp300/dev/hil_keymaps.c dev/hil_keymaps.c
*** /sys/arch/hp300/dev/hil_keymaps.c Mon Mar 31 04:20:19 1997
--- dev/hil_keymaps.c Wed Apr 23 20:37:45 1997
***************
*** 65,71 ****
#include <sys/param.h>
#include <hp300/dev/kbdmap.h>
! char us_keymap[] = {
NULL, '`', '\\', ESC, NULL, DEL, NULL, NULL,
'\n', '\t', NULL, NULL, NULL, NULL, NULL, NULL,
NULL, '\n', NULL, NULL, NULL, NULL, NULL, NULL,
--- 65,71 ----
#include <sys/param.h>
#include <hp300/dev/kbdmap.h>
! char hil_us_keymap[] = {
NULL, '`', '\\', ESC, NULL, DEL, NULL, NULL,
'\n', '\t', NULL, NULL, NULL, NULL, NULL, NULL,
NULL, '\n', NULL, NULL, NULL, NULL, NULL, NULL,
***************
*** 84,90 ****
'z', 'x', 'c', 'v', 'b', 'n', NULL, NULL
};
! char us_shiftmap[] = {
NULL, '~', '|', DEL, NULL, DEL, NULL, NULL,
'\n', '\t', NULL, NULL, NULL, NULL, NULL, NULL,
NULL, '\n', NULL, NULL, NULL, NULL, NULL, NULL,
--- 84,90 ----
'z', 'x', 'c', 'v', 'b', 'n', NULL, NULL
};
! char hil_us_shiftmap[] = {
NULL, '~', '|', DEL, NULL, DEL, NULL, NULL,
'\n', '\t', NULL, NULL, NULL, NULL, NULL, NULL,
NULL, '\n', NULL, NULL, NULL, NULL, NULL, NULL,
***************
*** 103,109 ****
'Z', 'X', 'C', 'V', 'B', 'N', NULL, NULL
};
! char us_ctrlmap[] = {
NULL, '`', '\034', ESC, NULL, DEL, NULL, NULL,
'\n', '\t', NULL, NULL, NULL, NULL, NULL, NULL,
NULL, '\n', NULL, NULL, NULL, NULL, NULL, NULL,
--- 103,109 ----
'Z', 'X', 'C', 'V', 'B', 'N', NULL, NULL
};
! char hil_us_ctrlmap[] = {
NULL, '`', '\034', ESC, NULL, DEL, NULL, NULL,
'\n', '\t', NULL, NULL, NULL, NULL, NULL, NULL,
NULL, '\n', NULL, NULL, NULL, NULL, NULL, NULL,
***************
*** 122,128 ****
'\032', '\030', '\003', '\026', '\002', '\016', NULL, NULL
};
! char us_ctrlshiftmap[] = {
NULL, '~', '|', DEL, NULL, DEL, NULL, NULL,
'\n', '\t', NULL, NULL, NULL, NULL, NULL, NULL,
NULL, '\n', NULL, NULL, NULL, NULL, NULL, NULL,
--- 122,128 ----
'\032', '\030', '\003', '\026', '\002', '\016', NULL, NULL
};
! char hil_us_ctrlshiftmap[] = {
NULL, '~', '|', DEL, NULL, DEL, NULL, NULL,
'\n', '\t', NULL, NULL, NULL, NULL, NULL, NULL,
NULL, '\n', NULL, NULL, NULL, NULL, NULL, NULL,
***************
*** 141,147 ****
'\032', '\030', '\003', '\026', '\002', '\016', NULL, NULL
};
! char *us_stringmap[] = {
NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
NULL, NULL, NULL, NULL, NULL, NULL, "\033V","\033h",
"\033U",NULL, NULL, NULL, NULL, NULL, "\033K","\033J",
--- 141,147 ----
'\032', '\030', '\003', '\026', '\002', '\016', NULL, NULL
};
! char *hil_us_stringmap[] = {
NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
NULL, NULL, NULL, NULL, NULL, NULL, "\033V","\033h",
"\033U",NULL, NULL, NULL, NULL, NULL, "\033K","\033J",
***************
*** 161,167 ****
};
#ifdef UK_KEYBOARD
! char uk_keymap[] = {
NULL, '`', '<', ESC, NULL, DEL, NULL, NULL,
'\n', '\t', NULL, NULL, NULL, NULL, NULL, NULL,
NULL, '\n', NULL, NULL, NULL, NULL, NULL, NULL,
--- 161,167 ----
};
#ifdef UK_KEYBOARD
! char hil_uk_keymap[] = {
NULL, '`', '<', ESC, NULL, DEL, NULL, NULL,
'\n', '\t', NULL, NULL, NULL, NULL, NULL, NULL,
NULL, '\n', NULL, NULL, NULL, NULL, NULL, NULL,
***************
*** 180,186 ****
'z', 'x', 'c', 'v', 'b', 'n', NULL, NULL
};
! char uk_shiftmap[] = {
NULL, '~', '>', DEL, NULL, DEL, NULL, NULL,
'\n', '\t', NULL, NULL, NULL, NULL, NULL, NULL,
NULL, '\n', NULL, NULL, NULL, NULL, NULL, NULL,
--- 180,186 ----
'z', 'x', 'c', 'v', 'b', 'n', NULL, NULL
};
! char hil_uk_shiftmap[] = {
NULL, '~', '>', DEL, NULL, DEL, NULL, NULL,
'\n', '\t', NULL, NULL, NULL, NULL, NULL, NULL,
NULL, '\n', NULL, NULL, NULL, NULL, NULL, NULL,
***************
*** 199,205 ****
'Z', 'X', 'C', 'V', 'B', 'N', NULL, NULL
};
! char uk_ctrlmap[] = {
NULL, '`', '<', ESC, NULL, DEL, NULL, NULL,
'\n', '\t', NULL, NULL, NULL, NULL, NULL, NULL,
NULL, '\n', NULL, NULL, NULL, NULL, NULL, NULL,
--- 199,205 ----
'Z', 'X', 'C', 'V', 'B', 'N', NULL, NULL
};
! char hil_uk_ctrlmap[] = {
NULL, '`', '<', ESC, NULL, DEL, NULL, NULL,
'\n', '\t', NULL, NULL, NULL, NULL, NULL, NULL,
NULL, '\n', NULL, NULL, NULL, NULL, NULL, NULL,
***************
*** 218,224 ****
'\032', '\030', '\003', '\026', '\002', '\016', NULL, NULL
};
! char uk_ctrlshiftmap[] = {
NULL, '~', '>', DEL, NULL, DEL, NULL, NULL,
'\n', '\t', NULL, NULL, NULL, NULL, NULL, NULL,
NULL, '\n', NULL, NULL, NULL, NULL, NULL, NULL,
--- 218,224 ----
'\032', '\030', '\003', '\026', '\002', '\016', NULL, NULL
};
! char hil_uk_ctrlshiftmap[] = {
NULL, '~', '>', DEL, NULL, DEL, NULL, NULL,
'\n', '\t', NULL, NULL, NULL, NULL, NULL, NULL,
NULL, '\n', NULL, NULL, NULL, NULL, NULL, NULL,
***************
*** 239,245 ****
#endif
#ifdef SE_KEYBOARD
! char se_keymap[] = {
NULL, '<', '\'', ESC, NULL, DEL, NULL, NULL,
'\n', '\t', NULL, NULL, NULL, NULL, NULL, NULL,
NULL, '\n', NULL, NULL, NULL, NULL, NULL, NULL,
--- 239,245 ----
#endif
#ifdef SE_KEYBOARD
! char hil_se_keymap[] = {
NULL, '<', '\'', ESC, NULL, DEL, NULL, NULL,
'\n', '\t', NULL, NULL, NULL, NULL, NULL, NULL,
NULL, '\n', NULL, NULL, NULL, NULL, NULL, NULL,
***************
*** 258,264 ****
'z', 'x', 'c', 'v', 'b', 'n', NULL, NULL
};
! char se_shiftmap[] = {
NULL, '>', '*', DEL, NULL, DEL, NULL, NULL,
'\n', '\t', NULL, NULL, NULL, NULL, NULL, NULL,
NULL, '\n', NULL, NULL, NULL, NULL, NULL, NULL,
--- 258,264 ----
'z', 'x', 'c', 'v', 'b', 'n', NULL, NULL
};
! char hil_se_shiftmap[] = {
NULL, '>', '*', DEL, NULL, DEL, NULL, NULL,
'\n', '\t', NULL, NULL, NULL, NULL, NULL, NULL,
NULL, '\n', NULL, NULL, NULL, NULL, NULL, NULL,
***************
*** 277,283 ****
'Z', 'X', 'C', 'V', 'B', 'N', NULL, NULL
};
! char se_ctrlmap[] = {
NULL, '`', '\034', ESC, NULL, DEL, NULL, NULL,
'\n', '\t', NULL, NULL, NULL, NULL, NULL, NULL,
NULL, '\n', NULL, NULL, NULL, NULL, NULL, NULL,
--- 277,283 ----
'Z', 'X', 'C', 'V', 'B', 'N', NULL, NULL
};
! char hil_se_ctrlmap[] = {
NULL, '`', '\034', ESC, NULL, DEL, NULL, NULL,
'\n', '\t', NULL, NULL, NULL, NULL, NULL, NULL,
NULL, '\n', NULL, NULL, NULL, NULL, NULL, NULL,
***************
*** 296,302 ****
'\032', '\030', '\003', '\026', '\002', '\016', NULL, NULL
};
! char se_ctrlshiftmap[] = {
NULL, '~', '|', DEL, NULL, DEL, NULL, NULL,
'\n', '\t', NULL, NULL, NULL, NULL, NULL, NULL,
NULL, '\n', NULL, NULL, NULL, NULL, NULL, NULL,
--- 296,302 ----
'\032', '\030', '\003', '\026', '\002', '\016', NULL, NULL
};
! char hil_se_ctrlshiftmap[] = {
NULL, '~', '|', DEL, NULL, DEL, NULL, NULL,
'\n', '\t', NULL, NULL, NULL, NULL, NULL, NULL,
NULL, '\n', NULL, NULL, NULL, NULL, NULL, NULL,
***************
*** 320,337 ****
* The keyboard map table.
* Lookup is by hardware returned language code.
*/
! struct kbdmap kbd_map[] = {
{ KBD_US, "US ASCII",
! us_keymap, us_shiftmap, us_ctrlmap, us_ctrlshiftmap, us_stringmap },
#ifdef UK_KEYBOARD
{ KBD_UK, "United Kingdom",
! uk_keymap, uk_shiftmap, uk_ctrlmap, uk_ctrlshiftmap, us_stringmap },
#endif
#ifdef SE_KEYBOARD
{ KBD_SE, "Swedish",
! se_keymap, se_shiftmap, se_ctrlmap, se_ctrlshiftmap, us_stringmap },
#endif
{ 0, NULL, NULL, NULL, NULL, NULL, NULL },
--- 320,340 ----
* The keyboard map table.
* Lookup is by hardware returned language code.
*/
! struct hil_kbdmap hil_kbd_map[] = {
{ KBD_US, "US ASCII",
! hil_us_keymap, hil_us_shiftmap, hil_us_ctrlmap,
! hil_us_ctrlshiftmap, hil_us_stringmap },
#ifdef UK_KEYBOARD
{ KBD_UK, "United Kingdom",
! hil_uk_keymap, hil_uk_shiftmap, hil_uk_ctrlmap,
! hil_uk_ctrlshiftmap, hil_us_stringmap },
#endif
#ifdef SE_KEYBOARD
{ KBD_SE, "Swedish",
! hil_se_keymap, hil_se_shiftmap, hil_se_ctrlmap,
! hil_se_ctrlshiftmap, hil_us_stringmap },
#endif
{ 0, NULL, NULL, NULL, NULL, NULL, NULL },
diff -crN /sys/arch/hp300/dev/hilvar.h dev/hilvar.h
*** /sys/arch/hp300/dev/hilvar.h Wed Apr 2 04:24:33 1997
--- dev/hilvar.h Wed Apr 23 22:30:44 1997
***************
*** 119,137 ****
#define KBD_AR2 0x04 /* keyboard auto-repeat rate 2 */
#ifdef _KERNEL
- void kbdbell __P((int));
- void kbdenable __P((int));
- void kbddisable __P((int));
- int kbdgetc __P((int *));
- void kbdcninit __P((void));
-
- int kbdnmi __P((void));
-
void hilsoftinit __P((int, struct hil_dev *));
void hilinit __P((int, struct hil_dev *));
void send_hil_cmd __P((struct hil_dev *, u_char,
! u_char *, u_char, u_char *));
void send_hildev_cmd __P((struct hil_softc *, char, char));
void polloff __P((struct hil_dev *));
--- 119,131 ----
#define KBD_AR2 0x04 /* keyboard auto-repeat rate 2 */
#ifdef _KERNEL
void hilsoftinit __P((int, struct hil_dev *));
void hilinit __P((int, struct hil_dev *));
+ int kbdnmi __P((void));
+
void send_hil_cmd __P((struct hil_dev *, u_char,
! u_char *, u_char, u_char *));
void send_hildev_cmd __P((struct hil_softc *, char, char));
void polloff __P((struct hil_dev *));
diff -crN /sys/arch/hp300/dev/ite.c dev/ite.c
*** /sys/arch/hp300/dev/ite.c Mon Mar 31 04:20:25 1997
--- dev/ite.c Wed Apr 23 22:24:30 1997
***************
*** 64,73 ****
#include <hp300/dev/grfioctl.h>
#include <hp300/dev/grfvar.h>
- #include <hp300/dev/hilioctl.h>
- #include <hp300/dev/hilvar.h>
#include <hp300/dev/itevar.h>
! #include <hp300/dev/kbdmap.h>
/* prototypes for devsw entry points */
cdev_decl(ite);
--- 64,71 ----
#include <hp300/dev/grfioctl.h>
#include <hp300/dev/grfvar.h>
#include <hp300/dev/itevar.h>
! #include <hp300/dev/kbdvar.h>
/* prototypes for devsw entry points */
cdev_decl(ite);
***************
*** 75,80 ****
--- 73,81 ----
#define set_attr(ip, attr) ((ip)->attribute |= (attr))
#define clr_attr(ip, attr) ((ip)->attribute &= ~(attr))
+ #define ESC '\033'
+ #define DEL '\177'
+
/*
* # of chars are output in a single itestart() call.
* If this is too big, user processes will be blocked out for
***************
*** 84,89 ****
--- 85,91 ----
int iteburst = 64;
struct ite_data *kbd_ite = NULL;
+ struct kbdsw *ite_kbd = NULL; /* current keyboard */
int itematch __P((struct device *, struct cfdata *, void *));
void iteattach __P((struct device *, struct device *, void *));
***************
*** 162,167 ****
--- 164,175 ----
* the console probe, so we have to fixup cn_dev here.
*/
cn_tab->cn_dev = makedev(ite_major(), self->dv_unit);
+
+ /*
+ * Mention the keyboard type, if we have one.
+ */
+ if (ite_kbd != NULL)
+ printf(", %s keyboard.", ite_kbd->kbdname);
} else {
ite->sc_data =
(struct ite_data *)malloc(sizeof(struct ite_data),
***************
*** 215,221 ****
if (kbd_ite == NULL || kbd_ite == ip) {
kbd_ite = ip;
! kbdenable(0); /* XXX */
}
iteinit(ip);
--- 223,230 ----
if (kbd_ite == NULL || kbd_ite == ip) {
kbd_ite = ip;
! if (ite_kbd != NULL)
! ite_kbd->kbdenable(0); /* XXX */
}
iteinit(ip);
***************
*** 486,550 ****
}
void
! itefilter(stat, c)
! char stat, c;
{
- static int capsmode = 0;
- static int metamode = 0;
- char code, *str;
struct tty *kbd_tty = kbd_ite->tty;
if (kbd_tty == NULL)
return;
! switch (c & 0xFF) {
! case KBD_CAPSLOCK:
! capsmode = !capsmode;
! return;
!
! case KBD_EXT_LEFT_DOWN:
! case KBD_EXT_RIGHT_DOWN:
! metamode = 1;
! return;
!
! case KBD_EXT_LEFT_UP:
! case KBD_EXT_RIGHT_UP:
! metamode = 0;
! return;
! }
!
! c &= KBD_CHARMASK;
! switch ((stat>>KBD_SSHIFT) & KBD_SMASK) {
! default:
! case KBD_KEY:
! if (!capsmode) {
! code = kbd_keymap[c];
! break;
! }
! /* FALLTHROUGH */
!
! case KBD_SHIFT:
! code = kbd_shiftmap[c];
! break;
!
! case KBD_CTRL:
! code = kbd_ctrlmap[c];
! break;
!
! case KBD_CTRLSHIFT:
! code = kbd_ctrlshiftmap[c];
! break;
! }
!
! if (code == '\0' && (str = kbd_stringmap[c]) != '\0') {
! while (*str)
! (*linesw[kbd_tty->t_line].l_rint)(*str++, kbd_tty);
! } else {
! if (metamode)
! code |= 0x80;
! (*linesw[kbd_tty->t_line].l_rint)(code, kbd_tty);
! }
}
void
--- 495,513 ----
}
+ /*
+ * Take a character from a keyboard handler, pass it up.
+ */
void
! itekbdin(c)
! char c;
{
struct tty *kbd_tty = kbd_ite->tty;
if (kbd_tty == NULL)
return;
! (*linesw[kbd_tty->t_line].l_rint)(c, kbd_tty);
}
void
***************
*** 792,799 ****
break;
case CTRL('G'):
! if (ip == kbd_ite)
! kbdbell(0); /* XXX */
break;
case ESC:
--- 755,762 ----
break;
case CTRL('G'):
! if ((ip == kbd_ite) && (ite_kbd != NULL))
! ite_kbd->kbdbell(0); /* XXX */
break;
case ESC:
***************
*** 945,950 ****
--- 908,914 ----
struct itesw *isw;
{
struct ite_data *ip = &ite_cn;
+ int i;
/*
* Set up required ite data and initialize ite.
***************
*** 955,965 ****
ip->attrbuf = ite_console_attributes;
iteinit(ip);
! /*
! * Initialize the console keyboard.
! */
! kbdcninit();
!
kbd_ite = ip; /* XXX */
}
--- 919,933 ----
ip->attrbuf = ite_console_attributes;
iteinit(ip);
! /*
! * Search for a keyboard
! */
! for (i = 0; kbdsw[i].kbdinit != NULL; i++) {
! if (kbdsw[i].kbdinit()) { /* found one? */
! ite_kbd = &kbdsw[i];
! break;
! }
! }
kbd_ite = ip; /* XXX */
}
***************
*** 968,992 ****
itecngetc(dev)
dev_t dev;
{
! int c;
! int stat;
!
! c = kbdgetc(&stat);
! switch ((stat >> KBD_SSHIFT) & KBD_SMASK) {
! case KBD_SHIFT:
! c = kbd_cn_shiftmap[c & KBD_CHARMASK];
! break;
! case KBD_CTRL:
! c = kbd_cn_ctrlmap[c & KBD_CHARMASK];
! break;
! case KBD_KEY:
! c = kbd_cn_keymap[c & KBD_CHARMASK];
! break;
! default:
! c = 0;
! break;
! }
! return(c);
}
/* ARGSUSED */
--- 936,944 ----
itecngetc(dev)
dev_t dev;
{
! if (ite_kbd)
! return(ite_kbd->kbdgetc());
! return(0);
}
/* ARGSUSED */
diff -crN /sys/arch/hp300/dev/itevar.h dev/itevar.h
*** /sys/arch/hp300/dev/itevar.h Mon Mar 31 04:20:26 1997
--- dev/itevar.h Wed Apr 23 22:24:23 1997
***************
*** 170,192 ****
#define ERASE_CURSOR 0x06
#define MOVE_CURSOR 0x07
- #define KBD_SSHIFT 4 /* bits to shift status */
- #define KBD_CHARMASK 0x7F
-
- /* keyboard status */
- #define KBD_SMASK 0xF /* service request status mask */
- #define KBD_CTRLSHIFT 0x8 /* key + CTRL + SHIFT */
- #define KBD_CTRL 0x9 /* key + CTRL */
- #define KBD_SHIFT 0xA /* key + SHIFT */
- #define KBD_KEY 0xB /* key only */
-
- #define KBD_CAPSLOCK 0x18
-
- #define KBD_EXT_LEFT_DOWN 0x12
- #define KBD_EXT_LEFT_UP 0x92
- #define KBD_EXT_RIGHT_DOWN 0x13
- #define KBD_EXT_RIGHT_UP 0x93
-
#define TABSIZE 8
#define TABEND(ip) ((ip)->tty->t_winsize.ws_col - TABSIZE)
--- 170,175 ----
***************
*** 201,207 ****
void ite_attach_grf __P((int, int));
int iteon __P((struct ite_data *, int));
void iteoff __P((struct ite_data *, int));
! void itefilter __P((char, char));
void itecninit __P((struct grf_data *, struct itesw *));
int itecngetc __P((dev_t));
void itecnputc __P((dev_t, int));
--- 184,190 ----
void ite_attach_grf __P((int, int));
int iteon __P((struct ite_data *, int));
void iteoff __P((struct ite_data *, int));
! void itekbdin __P((char));
void itecninit __P((struct grf_data *, struct itesw *));
int itecngetc __P((dev_t));
void itecnputc __P((dev_t, int));
diff -crN /sys/arch/hp300/dev/kbdconf.c dev/kbdconf.c
*** /sys/arch/hp300/dev/kbdconf.c Wed Dec 31 16:00:00 1969
--- dev/kbdconf.c Wed Apr 23 20:15:03 1997
***************
*** 0 ****
--- 1,60 ----
+ /* $NetBSD$ */
+
+ /*
+ * Copyright (c) 1997 Michael Smith. All rights reserved.
+ * Inspired by code by Jason R. Thorpe.
+ *
+ * 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 AUTHOR 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 "auto" configuration. Oh, for linker sets.
+ */
+
+ #include "dnkbd.h"
+
+ #include <sys/param.h>
+
+ #include <hp300/dev/kbdvar.h>
+
+ /*
+ * The keyboard driver is selected on a first-come, first-served basis.
+ * Both the Domain and HIL keyboards can be reliably detected, but if
+ * neither are plugged in, no keyboard will be enabled (how could we
+ * guess in advance which one you would choose?).
+ *
+ * The HIL driver is always present, and the HIL keyboard is the default,
+ * wheras the Domain keyboard support requires the dnkbd driver.
+ */
+
+ struct kbdsw kbdsw[] = {
+ {"HIL", hilkbdgetc, hilkbdbell, hilkbdinit, hilkbdenable, hilkbddisable},
+ #if NDNKBD > 0
+ /* use the HIL beeper until we work out how to beep the Domain keyboard */
+ {"Domain", dnkbdgetc, hilkbdbell, dnkbdinit, dnkbdenable, dnkbddisable},
+ #endif
+ {"No" , NULL, NULL, NULL, NULL, NULL}
+ };
+
+
+
diff -crN /sys/arch/hp300/dev/kbdmap.h dev/kbdmap.h
*** /sys/arch/hp300/dev/kbdmap.h Mon Oct 14 09:05:51 1996
--- dev/kbdmap.h Thu Apr 24 00:44:41 1997
***************
*** 35,44 ****
* @(#)kbdmap.h 8.1 (Berkeley) 6/10/93
*/
#define ESC '\033'
#define DEL '\177'
! struct kbdmap {
int kbd_code;
char *kbd_desc;
char *kbd_keymap;
--- 35,48 ----
* @(#)kbdmap.h 8.1 (Berkeley) 6/10/93
*/
+ /*
+ * HIL keyboard map definitions
+ */
+
#define ESC '\033'
#define DEL '\177'
! struct hil_kbdmap {
int kbd_code;
char *kbd_desc;
char *kbd_keymap;
***************
*** 56,73 ****
#define KBD_DEFAULT KBD_US /* default type */
! #ifdef _KERNEL
! /* XXX: ITE interface */
! extern char *kbd_keymap;
! extern char *kbd_shiftmap;
! extern char *kbd_ctrlmap;
! extern char *kbd_ctrlshiftmap;
! extern char **kbd_stringmap;
!
! /* XXX: itecngetc() interface */
! extern char *kbd_cn_keymap;
! extern char *kbd_cn_shiftmap;
! extern char *kbd_cn_ctrlmap;
! extern struct kbdmap kbd_map[];
#endif
--- 60,82 ----
#define KBD_DEFAULT KBD_US /* default type */
! #define KBD_SSHIFT 4 /* bits to shift status */
! #define KBD_CHARMASK 0x7F
! /* keyboard status */
! #define KBD_SMASK 0xF /* service request status mask */
! #define KBD_CTRLSHIFT 0x8 /* key + CTRL + SHIFT */
! #define KBD_CTRL 0x9 /* key + CTRL */
! #define KBD_SHIFT 0xA /* key + SHIFT */
! #define KBD_KEY 0xB /* key only */
!
! #define KBD_CAPSLOCK 0x18
!
! #define KBD_EXT_LEFT_DOWN 0x12
! #define KBD_EXT_LEFT_UP 0x92
! #define KBD_EXT_RIGHT_DOWN 0x13
! #define KBD_EXT_RIGHT_UP 0x93
!
! #ifdef _KERNEL
! extern struct hil_kbdmap hil_kbd_map[];
#endif
diff -crN /sys/arch/hp300/dev/kbdvar.h dev/kbdvar.h
*** /sys/arch/hp300/dev/kbdvar.h Wed Dec 31 16:00:00 1969
--- dev/kbdvar.h Wed Apr 23 20:20:52 1997
***************
*** 0 ****
--- 1,61 ----
+ /* $NetBSD$ */
+
+ /*
+ * Copyright (c) 1997 Michael Smith. All rights reserved.
+ * Inspired by code by Jason R. Thorpe.
+ *
+ * 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 AUTHOR 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 driver interface, prototypes and defines.
+ */
+
+ struct kbdsw
+ {
+ const char *kbdname; /* keyboard name */
+ int (*kbdgetc)(void); /* return a character in polled mode */
+ void (*kbdbell)(int unit); /* go beep */
+ int (*kbdinit)(void); /* probe for/init keyboard, returns 1 if present */
+ void (*kbdenable)(int unit); /* allow keyboard to give characters to ite */
+ void (*kbddisable)(int unit); /* stop keyboard giving characters to ite */
+ };
+
+ extern struct kbdsw kbdsw[]; /* array of keyboard drivers */
+
+ /* XXX HIL is not optional */
+ extern int hilkbdgetc(void);
+ extern void hilkbdbell(int unit);
+ extern int hilkbdinit(void);
+ extern void hilkbdenable(int unit);
+ extern void hilkbddisable(int unit);
+
+ /* Apollo keyboard */
+ #if NDNKBD > 0
+ extern int dnkbdgetc(void);
+ extern void dnkbdbell(int unit); /* XXX not currently working */
+ extern int dnkbdinit(void);
+ extern void dnkbdenable(int unit);
+ extern void dnkbddisable(int unit);
+ #endif
+
diff -crN /sys/arch/hp300/hp300/conf.c hp300/conf.c
*** /sys/arch/hp300/hp300/conf.c Tue Apr 1 04:18:14 1997
--- hp300/conf.c Thu Apr 24 00:12:06 1997
***************
*** 98,103 ****
--- 98,110 ----
(dev_type_stop((*))) enodev, 0, dev_init(c,n,poll), \
dev_init(c,n,mmap) }
+ /* open, close, read, ioctl, poll -- XXX what is this? */
+ #define cdev_dnkbd_init(c,n) { \
+ dev_init(c,n,open), dev_init(c,n,close), dev_init(c,n,read), \
+ (dev_type_write((*))) nullop, dev_init(c,n,ioctl), \
+ (dev_type_stop((*))) enodev, 0, dev_init(c,n,poll), \
+ (dev_type_mmap((*))) enodev }
+
cdev_decl(cn);
cdev_decl(ctty);
#define mmread mmrw
***************
*** 121,126 ****
--- 128,137 ----
cdev_decl(ppi);
#include "dca.h"
cdev_decl(dca);
+ #include "apci.h"
+ cdev_decl(apci);
+ #include "dnkbd.h"
+ cdev_decl(dnkbd);
#include "ite.h"
cdev_decl(ite);
/* XXX shouldn't this be optional? */
***************
*** 172,177 ****
--- 183,190 ----
cdev_lkm_dummy(), /* 28 */
cdev_lkm_dummy(), /* 29 */
cdev_lkm_dummy(), /* 30 */
+ cdev_tty_init(NAPCI,apci), /* 31: Apollo serial */
+ cdev_dnkbd_init(NDNKBD,dnkbd), /* 32: Domain keyboard */
};
int nchrdev = sizeof(cdevsw) / sizeof(cdevsw[0]);
diff -crN /sys/arch/hp300/hp300/genassym.cf hp300/genassym.cf
*** /sys/arch/hp300/hp300/genassym.cf Sun Mar 16 04:22:38 1997
--- hp300/genassym.cf Wed Apr 23 19:57:11 1997
***************
*** 97,104 ****
--- 97,107 ----
define HP_360 HP_360
define HP_370 HP_370
define HP_340 HP_340
+ define HP_345 HP_345
define HP_375 HP_375
define HP_380 HP_380
+ define HP_400 HP_400
+ define HP_425 HP_425
define HP_433 HP_433
# values for ectype
diff -crN /sys/arch/hp300/hp300/hpux_machdep.c hp300/hpux_machdep.c
*** /sys/arch/hp300/hp300/hpux_machdep.c Thu Apr 3 04:22:42 1997
--- hp300/hpux_machdep.c Thu Apr 24 09:39:25 1997
***************
*** 117,127 ****
{ HP_320, "320" },
{ HP_330, "330" }, /* includes 318 and 319 */
{ HP_340, "340" },
{ HP_350, "350" },
{ HP_360, "360" },
{ HP_370, "370" },
{ HP_375, "375" }, /* includes 345 and 400 */
! { HP_380, "380" }, /* includes 425 */
{ HP_433, "433" },
{ -1, "3?0" }, /* unknown system (???) */
};
--- 117,130 ----
{ HP_320, "320" },
{ HP_330, "330" }, /* includes 318 and 319 */
{ HP_340, "340" },
+ { HP_345, "345" }, /* XXX not used yet */
{ HP_350, "350" },
{ HP_360, "360" },
{ HP_370, "370" },
{ HP_375, "375" }, /* includes 345 and 400 */
! { HP_380, "380" },
! { HP_400, "400" }, /* XXX not used yet */
! { HP_425, "425" },
{ HP_433, "433" },
{ -1, "3?0" }, /* unknown system (???) */
};
***************
*** 261,272 ****
--- 264,278 ----
return (HPUX_SYSCONF_CPUM020);
case HP_340:
+ case HP_345:
case HP_360:
case HP_370:
case HP_375:
+ case HP_400:
return (HPUX_SYSCONF_CPUM030);
case HP_380:
+ case HP_425:
case HP_433:
return (HPUX_SYSCONF_CPUM040);
diff -crN /sys/arch/hp300/hp300/hpux_machdep.c~ hp300/hpux_machdep.c~
*** /sys/arch/hp300/hp300/hpux_machdep.c~ Wed Dec 31 16:00:00 1969
--- hp300/hpux_machdep.c~ Wed Apr 23 19:58:26 1997
***************
*** 0 ****
--- 1,800 ----
+ /* $NetBSD: hpux_machdep.c,v 1.12 1997/04/02 22:41:34 scottr Exp $ */
+
+ /*
+ * Copyright (c) 1995, 1996, 1997 Jason R. Thorpe. All rights reserved.
+ * Copyright (c) 1988 University of Utah.
+ * Copyright (c) 1990, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * the Systems Programming Group of the University of Utah Computer
+ * Science Department.
+ *
+ * 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. The name of the author may not 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.
+ */
+
+ /*
+ * Machinde-dependent bits for HP-UX binary compatibility.
+ */
+
+ #include <sys/param.h>
+ #include <sys/systm.h>
+ #include <sys/buf.h>
+ #include <sys/conf.h>
+ #include <sys/device.h>
+ #include <sys/exec.h>
+ #include <sys/file.h>
+ #include <sys/filedesc.h>
+ #include <sys/ioctl.h>
+ #include <sys/ipc.h>
+ #include <sys/kernel.h>
+ #include <sys/malloc.h>
+ #include <sys/mman.h>
+ #include <sys/mount.h>
+ #include <sys/namei.h>
+ #include <sys/namei.h>
+ #include <sys/poll.h>
+ #include <sys/proc.h>
+ #include <sys/ptrace.h>
+ #include <sys/signalvar.h>
+ #include <sys/stat.h>
+ #include <sys/syslog.h>
+ #include <sys/tty.h>
+ #include <sys/user.h>
+ #include <sys/vnode.h>
+ #include <sys/wait.h>
+
+ #include <machine/cpu.h>
+ #include <machine/reg.h>
+ #include <machine/psl.h>
+ #include <machine/vmparam.h>
+
+ #include <vm/vm.h>
+ #include <vm/vm_param.h>
+ #include <vm/vm_map.h>
+
+ #include <arch/hp300/dev/grfreg.h>
+ #include <arch/hp300/dev/grfioctl.h>
+ #include <arch/hp300/dev/grfvar.h>
+ #include <arch/hp300/dev/hilreg.h>
+ #include <arch/hp300/dev/hilioctl.h>
+ #include <arch/hp300/dev/hilvar.h>
+
+ #include <sys/syscallargs.h>
+
+ #include <compat/hpux/hpux.h>
+ #include <compat/hpux/hpux_sig.h>
+ #include <compat/hpux/hpux_util.h>
+ #include <compat/hpux/hpux_syscall.h>
+ #include <compat/hpux/hpux_syscallargs.h>
+
+ #include <machine/hpux_machdep.h>
+
+ extern short exframesize[];
+
+ #define NHIL 1 /* XXX */
+ #include "grf.h"
+
+ #if NGRF > 0
+ extern int grfopen __P((dev_t dev, int oflags, int devtype, struct proc *p));
+ #endif
+
+ #if NHIL > 0
+ extern int hilopen __P((dev_t dev, int oflags, int devtype, struct proc *p));
+ #endif
+
+ struct valtostr {
+ int val;
+ const char *str;
+ };
+
+ static struct valtostr machine_table[] = {
+ { HP_320, "320" },
+ { HP_330, "330" }, /* includes 318 and 319 */
+ { HP_340, "340" },
+ { HP_345, "345" }, /* XXX not used yet */
+ { HP_350, "350" },
+ { HP_360, "360" },
+ { HP_370, "370" },
+ { HP_375, "375" }, /* includes 345 and 400 */
+ { HP_380, "380" },
+ { HP_400, "400" }, /* XXX not used yet */
+ { HP_425, "425" },
+ { HP_433, "433" },
+ { -1, "3?0" }, /* unknown system (???) */
+ };
+
+ /*
+ * 6.0 and later context.
+ * XXX what are the HP-UX "localroot" semantics? Should we handle
+ * XXX diskless systems here?
+ */
+ static struct valtostr context_table[] = {
+ { FPU_68040,
+ "standalone HP-MC68040 HP-MC68881 HP-MC68020 HP-MC68010 localroot default"
+ },
+ { FPU_68881,
+ "standalone HP-MC68881 HP-MC68020 HP-MC68010 localroot default"
+ },
+ { FPU_NONE,
+ "standalone HP-MC68020 HP-MC68010 localroot default"
+ },
+ { 0, NULL },
+ };
+
+ #define UOFF(f) ((int)&((struct user *)0)->f)
+ #define HPUOFF(f) ((int)&((struct hpux_user *)0)->f)
+
+ /* simplified FP structure */
+ struct bsdfp {
+ int save[54];
+ int reg[24];
+ int ctrl[3];
+ };
+
+ /*
+ * m68k-specific setup for HP-UX executables.
+ * XXX m68k/m68k/hpux_machdep.c?
+ */
+ int
+ hpux_cpu_makecmds(p, epp)
+ struct proc *p;
+ struct exec_package *epp;
+ {
+ /* struct hpux_exec *hpux_ep = epp->ep_hdr; */
+
+ /* set up command for exec header */
+ NEW_VMCMD(&epp->ep_vmcmds, hpux_cpu_vmcmd,
+ sizeof(struct hpux_exec), (long)epp->ep_hdr, NULLVP, 0, 0);
+ return (0);
+ }
+
+ /*
+ * We need to stash the exec header in the pcb, so we define
+ * this vmcmd to do it for us, since vmcmds are executed once
+ * we're committed to the exec (i.e. the old program has been unmapped).
+ *
+ * The address of the header is in ev->ev_addr and the length is
+ * in ev->ev_len.
+ */
+ int
+ hpux_cpu_vmcmd(p, ev)
+ struct proc *p;
+ struct exec_vmcmd *ev;
+ {
+ struct hpux_exec *execp = (struct hpux_exec *)ev->ev_addr;
+
+ /* Make sure we have room. */
+ if (ev->ev_len <= sizeof(p->p_addr->u_md.md_exec))
+ bcopy((caddr_t)ev->ev_addr, p->p_addr->u_md.md_exec,
+ ev->ev_len);
+
+ /* Deal with misc. HP-UX process attributes. */
+ if (execp->ha_trsize & HPUXM_VALID) {
+ if (execp->ha_trsize & HPUXM_DATAWT)
+ p->p_md.md_flags &= ~MDP_CCBDATA;
+
+ if (execp->ha_trsize & HPUXM_STKWT)
+ p->p_md.md_flags &= ~MDP_CCBSTACK;
+ }
+
+ return (0);
+ }
+
+ /*
+ * Machine-dependent stat structure conversion.
+ */
+ void
+ hpux_cpu_bsd_to_hpux_stat(sb, hsb)
+ struct stat *sb;
+ struct hpux_stat *hsb;
+ {
+
+ /* XXX I don't want to talk about it... */
+ if ((sb->st_mode & S_IFMT) == S_IFCHR) {
+ #if NGRF > 0
+ if (cdevsw[major(sb->st_rdev)].d_open == grfopen)
+ hsb->hst_rdev = grfdevno(sb->st_rdev);
+ #endif
+ #if NHIL > 0
+ if (cdevsw[major(sb->st_rdev)].d_open == hilopen)
+ hsb->hst_rdev = hildevno(sb->st_rdev);
+ #endif
+ }
+ }
+
+ /*
+ * Machine-dependent uname information.
+ */
+ void
+ hpux_cpu_uname(ut)
+ struct hpux_utsname *ut;
+ {
+ int i;
+
+ bzero(ut->machine, sizeof(ut->machine));
+
+ /*
+ * Find the current machine-ID in the table and
+ * copy the string into the uname.
+ */
+ for (i = 0; machine_table[i].val != -1; ++i)
+ if (machine_table[i].val == machineid)
+ break;
+
+ sprintf(ut->machine, "9000/%s", machine_table[i].str);
+ }
+
+ /*
+ * Return arch-type for hpux_sys_sysconf()
+ */
+ int
+ hpux_cpu_sysconf_arch()
+ {
+
+ switch (machineid) {
+ case HP_320:
+ case HP_330:
+ case HP_350:
+ return (HPUX_SYSCONF_CPUM020);
+
+ case HP_340:
+ case HP_345:
+ case HP_360:
+ case HP_370:
+ case HP_375:
+ return (HPUX_SYSCONF_CPUM030);
+
+ case HP_380:
+ case HP_425:
+ case HP_433:
+ return (HPUX_SYSCONF_CPUM040);
+
+ default:
+ return (HPUX_SYSCONF_CPUM020); /* ??? */
+ }
+ /* NOTREACHED */
+ }
+
+ /*
+ * HP-UX advise(2) system call.
+ */
+ int
+ hpux_sys_advise(p, v, retval)
+ struct proc *p;
+ void *v;
+ register_t *retval;
+ {
+ struct hpux_sys_advise_args *uap = v;
+ int error = 0;
+
+ switch (SCARG(uap, arg)) {
+ case 0:
+ p->p_md.md_flags |= MDP_HPUXMMAP;
+ break;
+
+ case 1:
+ ICIA();
+ break;
+
+ case 2:
+ DCIA();
+ break;
+
+ default:
+ error = EINVAL;
+ break;
+ }
+
+ return (error);
+ }
+
+ /*
+ * HP-UX getcontext(2) system call.
+ * Man page lies, behaviour here is based on observed behaviour.
+ */
+ int
+ hpux_sys_getcontext(p, v, retval)
+ struct proc *p;
+ void *v;
+ register_t *retval;
+ {
+ struct hpux_sys_getcontext_args *uap = v;
+ int l, i, error = 0;
+ int len;
+
+ for (i = 0; context_table[i].str != NULL; i++)
+ if (context_table[i].val == fputype)
+ break;
+ if (context_table[i].str == NULL) {
+ /*
+ * XXX What else? It's not like this can happen...
+ */
+ return (EINVAL);
+ }
+
+ /* + 1 ... count the terminating \0. */
+ l = strlen(context_table[i].str) + 1;
+ len = min(SCARG(uap, len), l);
+
+ if (len)
+ error = copyout(context_table[i].str, SCARG(uap, buf), len);
+ if (error == 0)
+ *retval = l;
+ return (0);
+ }
+
+ /*
+ * Brutal hack! Map HP-UX u-area offsets into BSD k-stack offsets.
+ * XXX This probably doesn't work anymore, BTW. --thorpej
+ */
+ int
+ hpux_to_bsd_uoff(off, isps, p)
+ int *off, *isps;
+ struct proc *p;
+ {
+ int *ar0 = p->p_md.md_regs;
+ struct hpux_fp *hp;
+ struct bsdfp *bp;
+ u_int raddr;
+
+ *isps = 0;
+
+ /* u_ar0 field; procxmt puts in U_ar0 */
+ if ((int)off == HPUOFF(hpuxu_ar0))
+ return(UOFF(U_ar0));
+
+ if (fputype) {
+ /* FP registers from PCB */
+ hp = (struct hpux_fp *)HPUOFF(hpuxu_fp);
+ bp = (struct bsdfp *)UOFF(u_pcb.pcb_fpregs);
+
+ if (off >= hp->hpfp_ctrl && off < &hp->hpfp_ctrl[3])
+ return((int)&bp->ctrl[off - hp->hpfp_ctrl]);
+
+ if (off >= hp->hpfp_reg && off < &hp->hpfp_reg[24])
+ return((int)&bp->reg[off - hp->hpfp_reg]);
+ }
+
+ /*
+ * Everything else we recognize comes from the kernel stack,
+ * so we convert off to an absolute address (if not already)
+ * for simplicity.
+ */
+ if (off < (int *)ctob(UPAGES))
+ off = (int *)((u_int)off + (u_int)p->p_addr); /* XXX */
+
+ /*
+ * General registers.
+ * We know that the HP-UX registers are in the same order as ours.
+ * The only difference is that their PS is 2 bytes instead of a
+ * padded 4 like ours throwing the alignment off.
+ */
+ if (off >= ar0 && off < &ar0[18]) {
+ /*
+ * PS: return low word and high word of PC as HP-UX would
+ * (e.g. &u.u_ar0[16.5]).
+ *
+ * XXX we don't do this since HP-UX adb doesn't rely on
+ * it and passing such an offset to procxmt will cause
+ * it to fail anyway. Instead, we just set the offset
+ * to PS and let hpux_ptrace() shift up the value returned.
+ */
+ if (off == &ar0[PS]) {
+ #if 0
+ raddr = (u_int) &((short *)ar0)[PS*2+1];
+ #else
+ raddr = (u_int) &ar0[(int)(off - ar0)];
+ #endif
+ *isps = 1;
+ }
+ /*
+ * PC: off will be &u.u_ar0[16.5] since HP-UX saved PS
+ * is only 16 bits.
+ */
+ else if (off == (int *)&(((short *)ar0)[PS*2+1]))
+ raddr = (u_int) &ar0[PC];
+ /*
+ * D0-D7, A0-A7: easy
+ */
+ else
+ raddr = (u_int) &ar0[(int)(off - ar0)];
+ return((int)(raddr - (u_int)p->p_addr)); /* XXX */
+ }
+
+ /* everything else */
+ return (-1);
+ }
+
+ #define HSS_RTEFRAME 0x01
+ #define HSS_FPSTATE 0x02
+ #define HSS_USERREGS 0x04
+
+ struct hpuxsigstate {
+ int hss_flags; /* which of the following are valid */
+ struct frame hss_frame; /* original exception frame */
+ struct fpframe hss_fpstate; /* 68881/68882 state info */
+ };
+
+ /*
+ * WARNING: code in locore.s assumes the layout shown here for hsf_signum
+ * thru hsf_handler so... don't screw with them!
+ */
+ struct hpuxsigframe {
+ int hsf_signum; /* signo for handler */
+ int hsf_code; /* additional info for handler */
+ struct hpuxsigcontext *hsf_scp; /* context ptr for handler */
+ sig_t hsf_handler; /* handler addr for u_sigc */
+ struct hpuxsigstate hsf_sigstate; /* state of the hardware */
+ struct hpuxsigcontext hsf_sc; /* actual context */
+ };
+
+ #ifdef DEBUG
+ int hpuxsigdebug = 0;
+ int hpuxsigpid = 0;
+ #define SDB_FOLLOW 0x01
+ #define SDB_KSTACK 0x02
+ #define SDB_FPSTATE 0x04
+ #endif
+
+ /*
+ * Send an interrupt to process.
+ */
+ void
+ hpux_sendsig(catcher, sig, mask, code)
+ sig_t catcher;
+ int sig, mask;
+ u_long code;
+ {
+ struct proc *p = curproc;
+ struct hpuxsigframe *kfp, *fp;
+ struct frame *frame;
+ struct sigacts *psp = p->p_sigacts;
+ short ft;
+ int oonstack, fsize;
+ extern char sigcode[], esigcode[];
+
+ frame = (struct frame *)p->p_md.md_regs;
+ ft = frame->f_format;
+ oonstack = psp->ps_sigstk.ss_flags & SS_ONSTACK;
+
+ /*
+ * Allocate and validate space for the signal handler
+ * context. Note that if the stack is in P0 space, the
+ * call to grow() is a nop, and the useracc() check
+ * will fail if the process has not already allocated
+ * the space with a `brk'.
+ */
+ fsize = sizeof(struct hpuxsigframe);
+ if ((psp->ps_flags & SAS_ALTSTACK) && !oonstack &&
+ (psp->ps_sigonstack & sigmask(sig))) {
+ fp = (struct hpuxsigframe *)(psp->ps_sigstk.ss_sp +
+ psp->ps_sigstk.ss_size - fsize);
+ psp->ps_sigstk.ss_flags |= SS_ONSTACK;
+ } else
+ fp = (struct hpuxsigframe *)(frame->f_regs[SP] - fsize);
+ if ((unsigned)fp <= USRSTACK - ctob(p->p_vmspace->vm_ssize))
+ (void)grow(p, (unsigned)fp);
+
+ #ifdef DEBUG
+ if ((hpuxsigdebug & SDB_KSTACK) && p->p_pid == hpuxsigpid)
+ printf("hpux_sendsig(%d): sig %d ssp %p usp %p scp %p ft %d\n",
+ p->p_pid, sig, &oonstack, fp, &fp->hsf_sc, ft);
+ #endif
+
+ if (useracc((caddr_t)fp, fsize, B_WRITE) == 0) {
+ #ifdef DEBUG
+ if ((hpuxsigdebug & SDB_KSTACK) && p->p_pid == hpuxsigpid)
+ printf("hpux_sendsig(%d): useracc failed on sig %d\n",
+ p->p_pid, sig);
+ #endif
+ /*
+ * Process has trashed its stack; give it an illegal
+ * instruction to halt it in its tracks.
+ */
+ SIGACTION(p, SIGILL) = SIG_DFL;
+ sig = sigmask(SIGILL);
+ p->p_sigignore &= ~sig;
+ p->p_sigcatch &= ~sig;
+ p->p_sigmask &= ~sig;
+ psignal(p, SIGILL);
+ return;
+ }
+ kfp = (struct hpuxsigframe *)malloc((u_long)fsize, M_TEMP, M_WAITOK);
+
+ /*
+ * Build the argument list for the signal handler.
+ */
+ kfp->hsf_signum = bsdtohpuxsig(sig);
+ kfp->hsf_code = code;
+ kfp->hsf_scp = &fp->hsf_sc;
+ kfp->hsf_handler = catcher;
+
+ /*
+ * Save necessary hardware state. Currently this includes:
+ * - general registers
+ * - original exception frame (if not a "normal" frame)
+ * - FP coprocessor state
+ */
+ kfp->hsf_sigstate.hss_flags = HSS_USERREGS;
+ bcopy((caddr_t)frame->f_regs,
+ (caddr_t)kfp->hsf_sigstate.hss_frame.f_regs, sizeof frame->f_regs);
+ if (ft >= FMT7) {
+ #ifdef DEBUG
+ if (ft > 15 || exframesize[ft] < 0)
+ panic("hpux_sendsig: bogus frame type");
+ #endif
+ kfp->hsf_sigstate.hss_flags |= HSS_RTEFRAME;
+ kfp->hsf_sigstate.hss_frame.f_format = frame->f_format;
+ kfp->hsf_sigstate.hss_frame.f_vector = frame->f_vector;
+ bcopy((caddr_t)&frame->F_u,
+ (caddr_t)&kfp->hsf_sigstate.hss_frame.F_u, exframesize[ft]);
+
+ /*
+ * Leave an indicator that we need to clean up the kernel
+ * stack. We do this by setting the "pad word" above the
+ * hardware stack frame to the amount the stack must be
+ * adjusted by.
+ *
+ * N.B. we increment rather than just set f_stackadj in
+ * case we are called from syscall when processing a
+ * sigreturn. In that case, f_stackadj may be non-zero.
+ */
+ frame->f_stackadj += exframesize[ft];
+ frame->f_format = frame->f_vector = 0;
+ #ifdef DEBUG
+ if (hpuxsigdebug & SDB_FOLLOW)
+ printf("hpux_sendsig(%d): copy out %d of frame %d\n",
+ p->p_pid, exframesize[ft], ft);
+ #endif
+ }
+ if (fputype) {
+ kfp->hsf_sigstate.hss_flags |= HSS_FPSTATE;
+ m68881_save(&kfp->hsf_sigstate.hss_fpstate);
+ }
+
+ #ifdef DEBUG
+ if ((hpuxsigdebug & SDB_FPSTATE) &&
+ *(char *)&kfp->hsf_sigstate.hss_fpstate)
+ printf("hpux_sendsig(%d): copy out FP state (%x) to %p\n",
+ p->p_pid, *(u_int *)&kfp->hsf_sigstate.hss_fpstate,
+ &kfp->hsf_sigstate.hss_fpstate);
+ #endif
+
+ /*
+ * Build the signal context to be used by hpux_sigreturn.
+ */
+ kfp->hsf_sc.hsc_syscall = 0; /* XXX */
+ kfp->hsf_sc.hsc_action = 0; /* XXX */
+ kfp->hsf_sc.hsc_pad1 = kfp->hsf_sc.hsc_pad2 = 0;
+ kfp->hsf_sc.hsc_onstack = oonstack;
+ kfp->hsf_sc.hsc_mask = mask;
+ kfp->hsf_sc.hsc_sp = frame->f_regs[SP];
+ kfp->hsf_sc.hsc_ps = frame->f_sr;
+ kfp->hsf_sc.hsc_pc = frame->f_pc;
+
+ /* How amazingly convenient! */
+ kfp->hsf_sc._hsc_pad = 0;
+ kfp->hsf_sc._hsc_ap = (int)&fp->hsf_sigstate;
+
+ (void) copyout((caddr_t)kfp, (caddr_t)fp, fsize);
+ frame->f_regs[SP] = (int)fp;
+
+ #ifdef DEBUG
+ if (hpuxsigdebug & SDB_FOLLOW) {
+ printf(
+ "hpux_sendsig(%d): sig %d scp %p fp %p sc_sp %x sc_ap %x\n",
+ p->p_pid, sig, kfp->hsf_scp, fp,
+ kfp->hsf_sc.hsc_sp, kfp->hsf_sc._hsc_ap);
+ }
+ #endif
+
+ /*
+ * Signal trampoline code is at base of user stack.
+ */
+ frame->f_pc = (int)PS_STRINGS - (esigcode - sigcode);
+ #ifdef DEBUG
+ if ((hpuxsigdebug & SDB_KSTACK) && p->p_pid == hpuxsigpid)
+ printf("hpux_sendsig(%d): sig %d returns\n",
+ p->p_pid, sig);
+ #endif
+ free((caddr_t)kfp, M_TEMP);
+ }
+
+ /*
+ * System call to cleanup state after a signal
+ * has been taken. Reset signal mask and
+ * stack state from context left by sendsig (above).
+ * Return to previous pc and psl as specified by
+ * context left by sendsig. Check carefully to
+ * make sure that the user has not modified the
+ * psl to gain improper priviledges or to cause
+ * a machine fault.
+ */
+ /* ARGSUSED */
+ int
+ hpux_sys_sigreturn(p, v, retval)
+ struct proc *p;
+ void *v;
+ register_t *retval;
+ {
+ struct hpux_sys_sigreturn_args /* {
+ syscallarg(struct hpuxsigcontext *) sigcntxp;
+ } */ *uap = v;
+ struct hpuxsigcontext *scp;
+ struct frame *frame;
+ int rf;
+ struct hpuxsigcontext tsigc;
+ struct hpuxsigstate tstate;
+ int flags;
+
+ scp = SCARG(uap, sigcntxp);
+ #ifdef DEBUG
+ if (hpuxsigdebug & SDB_FOLLOW)
+ printf("sigreturn: pid %d, scp %p\n", p->p_pid, scp);
+ #endif
+ if ((int)scp & 1)
+ return (EINVAL);
+
+ /*
+ * Fetch and test the HP-UX context structure.
+ * We grab it all at once for speed.
+ */
+ if (useracc((caddr_t)scp, sizeof (*scp), B_WRITE) == 0 ||
+ copyin((caddr_t)scp, (caddr_t)&tsigc, sizeof tsigc))
+ return (EINVAL);
+ scp = &tsigc;
+ if ((scp->hsc_ps & (PSL_MBZ|PSL_IPL|PSL_S)) != 0)
+ return (EINVAL);
+
+ /*
+ * Restore the user supplied information
+ */
+ if (scp->hsc_onstack & 01)
+ p->p_sigacts->ps_sigstk.ss_flags |= SS_ONSTACK;
+ else
+ p->p_sigacts->ps_sigstk.ss_flags &= ~SS_ONSTACK;
+ p->p_sigmask = scp->hsc_mask &~ sigcantmask;
+ frame = (struct frame *) p->p_md.md_regs;
+ frame->f_regs[SP] = scp->hsc_sp;
+ frame->f_pc = scp->hsc_pc;
+ frame->f_sr = scp->hsc_ps;
+
+ /*
+ * Grab a pointer to the hpuxsigstate.
+ * If zero, the user is probably doing a longjmp.
+ * (This will never happen, really, since HP-UX doesn't
+ * know/care about the state pointer.)
+ */
+ if ((rf = scp->_hsc_ap) == 0)
+ return (EJUSTRETURN);
+
+ /*
+ * See if there is anything to do before we go to the
+ * expense of copying in close to 1/2K of data
+ */
+ flags = fuword((caddr_t)rf);
+ #ifdef DEBUG
+ if (hpuxsigdebug & SDB_FOLLOW)
+ printf("sigreturn(%d): sc_ap %x flags %x\n",
+ p->p_pid, rf, flags);
+ #endif
+ /*
+ * fuword failed (bogus _hsc_ap value).
+ */
+ if (flags == -1)
+ return (EINVAL);
+ if (flags == 0 || copyin((caddr_t)rf, (caddr_t)&tstate, sizeof tstate))
+ return (EJUSTRETURN);
+ #ifdef DEBUG
+ if ((hpuxsigdebug & SDB_KSTACK) && p->p_pid == hpuxsigpid)
+ printf("sigreturn(%d): ssp %p usp %x scp %p ft %d\n",
+ p->p_pid, &flags, scp->hsc_sp, SCARG(uap, sigcntxp),
+ (flags & HSS_RTEFRAME) ? tstate.hss_frame.f_format : -1);
+ #endif
+ /*
+ * Restore most of the users registers except for A6 and SP
+ * which were handled above.
+ */
+ if (flags & HSS_USERREGS)
+ bcopy((caddr_t)tstate.hss_frame.f_regs,
+ (caddr_t)frame->f_regs, sizeof(frame->f_regs)-2*NBPW);
+
+ /*
+ * Restore long stack frames. Note that we do not copy
+ * back the saved SR or PC, they were picked up above from
+ * the sigcontext structure.
+ */
+ if (flags & HSS_RTEFRAME) {
+ int sz;
+
+ /* grab frame type and validate */
+ sz = tstate.hss_frame.f_format;
+ if (sz > 15 || (sz = exframesize[sz]) < 0)
+ return (EINVAL);
+ frame->f_stackadj -= sz;
+ frame->f_format = tstate.hss_frame.f_format;
+ frame->f_vector = tstate.hss_frame.f_vector;
+ bcopy((caddr_t)&tstate.hss_frame.F_u,
+ (caddr_t)&frame->F_u, sz);
+ #ifdef DEBUG
+ if (hpuxsigdebug & SDB_FOLLOW)
+ printf("sigreturn(%d): copy in %d of frame type %d\n",
+ p->p_pid, sz, tstate.hss_frame.f_format);
+ #endif
+ }
+
+ /*
+ * Finally we restore the original FP context
+ */
+ if (flags & HSS_FPSTATE)
+ m68881_restore(&tstate.hss_fpstate);
+
+ #ifdef DEBUG
+ if ((hpuxsigdebug & SDB_FPSTATE) && *(char *)&tstate.hss_fpstate)
+ printf("sigreturn(%d): copied in FP state (%x) at %p\n",
+ p->p_pid, *(u_int *)&tstate.hss_fpstate,
+ &tstate.hss_fpstate);
+
+ if ((hpuxsigdebug & SDB_FOLLOW) ||
+ ((hpuxsigdebug & SDB_KSTACK) && p->p_pid == hpuxsigpid))
+ printf("sigreturn(%d): returns\n", p->p_pid);
+ #endif
+ return (EJUSTRETURN);
+ }
+
+ /*
+ * Set registers on exec.
+ * XXX Should clear registers except sp, pc.
+ */
+ void
+ hpux_setregs(p, pack, stack, retval)
+ struct proc *p;
+ struct exec_package *pack;
+ u_long stack;
+ register_t *retval;
+ {
+ struct frame *frame = (struct frame *)p->p_md.md_regs;
+
+ frame->f_pc = pack->ep_entry & ~1;
+ frame->f_regs[SP] = stack;
+ frame->f_regs[A2] = (int)PS_STRINGS;
+
+ /* restore a null state frame */
+ p->p_addr->u_pcb.pcb_fpregs.fpf_null = 0;
+ if (fputype)
+ m68881_restore(&p->p_addr->u_pcb.pcb_fpregs);
+
+ p->p_md.md_flags &= ~MDP_HPUXMMAP;
+ frame->f_regs[A0] = 0; /* not 68010 (bit 31), no FPA (30) */
+ retval[0] = 0; /* no float card */
+ if (fputype)
+ retval[1] = 1; /* yes 68881 */
+ else
+ retval[1] = 0; /* no 68881 */
+ }
diff -crN /sys/arch/hp300/hp300/locore.s hp300/locore.s
*** /sys/arch/hp300/hp300/locore.s Mon Apr 14 04:25:30 1997
--- hp300/locore.s Thu Apr 24 09:40:17 1997
***************
*** 160,166 ****
movl a1@(MMUCMD),d0 | read it back
btst #16,d0 | still on?
jeq Lstart1 | no, must be a 360
! movl #HP_375,a0@ | yes, must be a 345/375
jra Lhaspac
Lisa370:
movl #HP_370,a0@ | set to 370
--- 160,180 ----
movl a1@(MMUCMD),d0 | read it back
btst #16,d0 | still on?
jeq Lstart1 | no, must be a 360
! RELOC(_mmuid, a0) | save MMU ID byte
! lsrl #8,d0
! movl d0,a0@
! andl #0xff,a0@
! cmpb #1,d0 | id == 1?
! beq Lisa345 | is a 345
! cmpb #3,d0 | id == 3?
! beq Lisa375 | is a 375
! movl #HP_400,a0@ | must be a 400?
! jra Lhaspac
! Lisa345:
! movl #HP_345,a0@
! jra Lhaspac
! Lisa375:
! movl #HP_375,a0@
jra Lhaspac
Lisa370:
movl #HP_370,a0@ | set to 370
***************
*** 184,198 ****
movl #FPU_68040,a0@ | ...and FPU
RELOC(_ectype, a0)
movl #EC_NONE,a0@ | and no cache (for now XXX)
! RELOC(_machineid, a0)
movl a1@(MMUCMD),d0 | read MMU register
lsrl #8,d0 | get apparent ID
cmpb #6,d0 | id == 6?
! jeq Lis33mhz | yes, we have a 433s
movl #HP_380,a0@ | no, we have a 380/425t
jra Lstart1
Lis33mhz:
! movl #HP_433,a0@ | 433s (XXX 425s returns same ID, ugh!)
jra Lstart1
Lis68020:
movl #1,a1@(MMUCMD) | a 68020, write HP MMU location
--- 198,223 ----
movl #FPU_68040,a0@ | ...and FPU
RELOC(_ectype, a0)
movl #EC_NONE,a0@ | and no cache (for now XXX)
! RELOC(_mmuid, a0)
movl a1@(MMUCMD),d0 | read MMU register
lsrl #8,d0 | get apparent ID
+ movl d0,a0@
+ andl #0xff,a0@ | save MMU ID byte
+ RELOC(_machineid, a0)
+ cmpb #4,d0 | id == 4?
+ jeq Lis33mhz | 33MHz Strider (433t)
cmpb #6,d0 | id == 6?
! jeq Lis33mhz | 33MHz Trailways (433s)
! cmpb #5,d0 | id == 5?
! jeq Lis25mhz | 25MHz Strider (425t)
! cmpb #7,d0 | id == 7?
! jeq Lis25mhz | 25MHz Trailways (425s)
movl #HP_380,a0@ | no, we have a 380/425t
jra Lstart1
+ Lis25mhz:
+ movl #HP_425,a0@ | running at 25MHz
Lis33mhz:
! movl #HP_433,a0@ | running at 33MHz
jra Lstart1
Lis68020:
movl #1,a1@(MMUCMD) | a 68020, write HP MMU location
***************
*** 1909,1918 ****
#undef DOREBOOT
.data
! .globl _machineid,_mmutype,_cputype,_ectype,_fputype
.globl _protorp,_prototc
_machineid:
.long HP_320 | default to 320
_mmutype:
.long MMU_HP | default to HP MMU
_cputype:
--- 1934,1945 ----
#undef DOREBOOT
.data
! .globl _machineid,_mmuid,_mmutype,_cputype,_ectype,_fputype
.globl _protorp,_prototc
_machineid:
.long HP_320 | default to 320
+ _mmuid:
+ .long 0 | default to ???
_mmutype:
.long MMU_HP | default to HP MMU
_cputype:
diff -crN /sys/arch/hp300/hp300/locore.s~ hp300/locore.s~
*** /sys/arch/hp300/hp300/locore.s~ Wed Dec 31 16:00:00 1969
--- hp300/locore.s~ Thu Apr 24 08:31:30 1997
***************
*** 0 ****
--- 1,2009 ----
+ /* $NetBSD: locore.s,v 1.70 1997/04/14 02:28:47 thorpej Exp $ */
+
+ /*
+ * Copyright (c) 1994, 1995 Gordon W. Ross
+ * Copyright (c) 1988 University of Utah.
+ * Copyright (c) 1980, 1990, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * the Systems Programming Group of the University of Utah Computer
+ * Science Department.
+ *
+ * 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.
+ *
+ * from: Utah $Hdr: locore.s 1.66 92/12/22$
+ *
+ * @(#)locore.s 8.6 (Berkeley) 5/27/94
+ */
+
+ #include "assym.h"
+ #include <machine/trap.h>
+
+ #define MMUADDR(ar) movl _MMUbase,ar
+ #define CLKADDR(ar) movl _CLKbase,ar
+
+ /*
+ * This is for kvm_mkdb, and should be the address of the beginning
+ * of the kernel text segment (not necessarily the same as kernbase).
+ */
+ .text
+ .globl _kernel_text
+ _kernel_text:
+
+ /*
+ * Clear and skip the first page of text; it will not be mapped.
+ */
+ .fill NBPG/4,4,0
+
+ /*
+ * Temporary stack for a variety of purposes.
+ * Try and make this the first thing is the data segment so it
+ * is page aligned. Note that if we overflow here, we run into
+ * our text segment.
+ */
+ .data
+ .space NBPG
+ tmpstk:
+
+ #include <hp300/hp300/vectors.s>
+
+ .text
+
+ /*
+ * Macro to relocate a symbol, used before MMU is enabled.
+ */
+ #define RELOC(var, ar) \
+ lea var,ar; \
+ addl a5,ar
+
+ /*
+ * Initialization
+ *
+ * A4 contains the address of the end of the symtab
+ * A5 contains physical load point from boot
+ * VBR contains zero from ROM. Exceptions will continue to vector
+ * through ROM until MMU is turned on at which time they will vector
+ * through our table (vectors.s).
+ */
+ .comm _lowram,4
+ .comm _esym,4
+
+ .text
+ .globl _edata
+ .globl _etext,_end
+ .globl start
+ start:
+ movw #PSL_HIGHIPL,sr | no interrupts
+ RELOC(tmpstk, a0)
+ movl a0,sp | give ourselves a temporary stack
+ RELOC(_esym, a0)
+ #if 1
+ movl a4,a0@ | store end of symbol table
+ #else
+ clrl a0@ | no symbol table, yet
+ #endif
+ RELOC(_lowram, a0)
+ movl a5,a0@ | store start of physical memory
+ movl #CACHE_OFF,d0
+ movc d0,cacr | clear and disable on-chip cache(s)
+
+ /* check for internal HP-IB in SYSFLAG */
+ btst #5,0xfffffed2 | internal HP-IB?
+ jeq Lhaveihpib | yes, have HP-IB just continue
+ RELOC(_internalhpib, a0)
+ movl #0,a0@ | no, clear associated address
+ Lhaveihpib:
+
+ RELOC(_boothowto, a0) | save reboot flags
+ movl d7,a0@
+ RELOC(_bootdev, a0) | and boot device
+ movl d6,a0@
+
+ /*
+ * All data registers are now free. All address registers
+ * except a5 are free. a5 is used by the RELOC() macro,
+ * and cannot be used until after the MMU is enabled.
+ */
+
+ /* determine our CPU/MMU combo - check for all regardless of kernel config */
+ movl #INTIOBASE+MMUBASE,a1
+ movl #0x200,d0 | data freeze bit
+ movc d0,cacr | only exists on 68030
+ movc cacr,d0 | read it back
+ tstl d0 | zero?
+ jeq Lnot68030 | yes, we have 68020/68040
+ RELOC(_mmutype, a0) | no, we have 68030
+ movl #MMU_68030,a0@ | set to reflect 68030 PMMU
+ RELOC(_cputype, a0)
+ movl #CPU_68030,a0@ | and 68030 CPU
+ RELOC(_machineid, a0)
+ movl #0x80,a1@(MMUCMD) | set magic cookie
+ movl a1@(MMUCMD),d0 | read it back
+ btst #7,d0 | cookie still on?
+ jeq Lnot370 | no, 360 or 375
+ movl #0,a1@(MMUCMD) | clear magic cookie
+ movl a1@(MMUCMD),d0 | read it back
+ btst #7,d0 | still on?
+ jeq Lisa370 | no, must be a 370
+ movl #HP_340,a0@ | yes, must be a 340
+ jra Lstart1
+ Lnot370:
+ movl #HP_360,a0@ | type is at least a 360
+ movl #0,a1@(MMUCMD) | clear magic cookie2
+ movl a1@(MMUCMD),d0 | read it back
+ btst #16,d0 | still on?
+ jeq Lstart1 | no, must be a 360
+ RELOC(_mmuid, a0) | save MMU ID byte
+ lsrl #8,d0
+ movl d0,a0@
+ andl #0xff,a0@
+ cmpb #1,d0 | id == 1?
+ beq Lisa345 | is a 345
+ cmpb #3,d0 | id == 3?
+ beq Lisa375 | is a 375
+ movl #HP_400,a0@ | must be a 400?
+ jra Lhaspac
+ Lisa345:
+ movl #HP_345,a0@
+ jra Lhaspac
+ Lisa375:
+ movl #HP_375,a0@
+ jra Lhaspac
+ Lisa370:
+ movl #HP_370,a0@ | set to 370
+ Lhaspac:
+ RELOC(_ectype, a0)
+ movl #EC_PHYS,a0@ | also has a physical address cache
+ jra Lstart1
+ Lnot68030:
+ bset #31,d0 | data cache enable bit
+ movc d0,cacr | only exists on 68040
+ movc cacr,d0 | read it back
+ tstl d0 | zero?
+ beq Lis68020 | yes, we have 68020
+ moveq #0,d0 | now turn it back off
+ movec d0,cacr | before we access any data
+ RELOC(_mmutype, a0)
+ movl #MMU_68040,a0@ | with a 68040 MMU
+ RELOC(_cputype, a0)
+ movl #CPU_68040,a0@ | and a 68040 CPU
+ RELOC(_fputype, a0)
+ movl #FPU_68040,a0@ | ...and FPU
+ RELOC(_ectype, a0)
+ movl #EC_NONE,a0@ | and no cache (for now XXX)
+ RELOC(_mmuid, a0)
+ movl a1@(MMUCMD),d0 | read MMU register
+ lsrl #8,d0 | get apparent ID
+ movl d0,a0@
+ andl #0xff,a0@ | save MMU ID byte
+ RELOC(_machineid, a0)
+ cmpb #4,d0 | id == 4?
+ jeq Lis33mhz | 33MHz Strider (433t)
+ cmpb #6,d0 | id == 6?
+ jeq Lis33mhz | 33MHz Trailways (433s)
+ cmpb #5,d0 | id == 5?
+ jeq Lis25mhz | 25MHz Strider (425t)
+ cmpb #7,d0 | id == 7?
+ jeq Lis25mhz | 25MHz Trailways (425s)
+ movl #HP_380,a0@ | no, we have a 380/425t
+ jra Lstart1
+ Lis25mhz:
+ movl #HP_425,a0@
+ Lis33mhz:
+ movl #HP_433,a0@ | 433s (XXX 425s returns same ID, ugh!)
+ jra Lstart1
+ Lis68020:
+ movl #1,a1@(MMUCMD) | a 68020, write HP MMU location
+ movl a1@(MMUCMD),d0 | read it back
+ btst #0,d0 | non-zero?
+ jne Lishpmmu | yes, we have HP MMU
+ RELOC(_mmutype, a0)
+ movl #MMU_68851,a0@ | no, we have PMMU
+ RELOC(_machineid, a0)
+ movl #HP_330,a0@ | and 330 CPU
+ jra Lstart1
+ Lishpmmu:
+ RELOC(_ectype, a0) | 320 or 350
+ movl #EC_VIRT,a0@ | both have a virtual address cache
+ movl #0x80,a1@(MMUCMD) | set magic cookie
+ movl a1@(MMUCMD),d0 | read it back
+ btst #7,d0 | cookie still on?
+ jeq Lis320 | no, just a 320
+ RELOC(_machineid, a0)
+ movl #HP_350,a0@ | yes, a 350
+ jra Lstart1
+ Lis320:
+ RELOC(_machineid, a0)
+ movl #HP_320,a0@
+
+ Lstart1:
+ movl #0,a1@(MMUCMD) | clear out MMU again
+ /* initialize source/destination control registers for movs */
+ moveq #FC_USERD,d0 | user space
+ movc d0,sfc | as source
+ movc d0,dfc | and destination of transfers
+ /* initialize memory sizes (for pmap_bootstrap) */
+ movl #MAXADDR,d1 | last page
+ moveq #PGSHIFT,d2
+ lsrl d2,d1 | convert to page (click) number
+ RELOC(_maxmem, a0)
+ movl d1,a0@ | save as maxmem
+ movl a5,d0 | lowram value from ROM via boot
+ lsrl d2,d0 | convert to page number
+ subl d0,d1 | compute amount of RAM present
+ RELOC(_physmem, a0)
+ movl d1,a0@ | and physmem
+ /* configure kernel and proc0 VA space so we can get going */
+ .globl _Sysseg, _pmap_bootstrap, _avail_start
+ #ifdef DDB
+ RELOC(_esym,a0) | end of static kernel test/data/syms
+ movl a0@,d5
+ jne Lstart2
+ #endif
+ movl #_end,d5 | end of static kernel text/data
+ Lstart2:
+ addl #NBPG-1,d5
+ andl #PG_FRAME,d5 | round to a page
+ movl d5,a4
+ addl a5,a4 | convert to PA
+ pea a5@ | firstpa
+ pea a4@ | nextpa
+ RELOC(_pmap_bootstrap,a0)
+ jbsr a0@ | pmap_bootstrap(firstpa, nextpa)
+ addql #8,sp
+
+ /*
+ * Prepare to enable MMU.
+ * Since the kernel is not mapped logical == physical we must insure
+ * that when the MMU is turned on, all prefetched addresses (including
+ * the PC) are valid. In order guarentee that, we use the last physical
+ * page (which is conveniently mapped == VA) and load it up with enough
+ * code to defeat the prefetch, then we execute the jump back to here.
+ *
+ * Is this all really necessary, or am I paranoid??
+ */
+ RELOC(_Sysseg, a0) | system segment table addr
+ movl a0@,d1 | read value (a KVA)
+ addl a5,d1 | convert to PA
+ RELOC(_mmutype, a0)
+ tstl a0@ | HP MMU?
+ jeq Lhpmmu2 | yes, skip
+ cmpl #MMU_68040,a0@ | 68040?
+ jne Lmotommu1 | no, skip
+ .long 0x4e7b1807 | movc d1,srp
+ jra Lstploaddone
+ Lmotommu1:
+ RELOC(_protorp, a0)
+ movl #0x80000202,a0@ | nolimit + share global + 4 byte PTEs
+ movl d1,a0@(4) | + segtable address
+ pmove a0@,srp | load the supervisor root pointer
+ movl #0x80000002,a0@ | reinit upper half for CRP loads
+ jra Lstploaddone | done
+ Lhpmmu2:
+ moveq #PGSHIFT,d2
+ lsrl d2,d1 | convert to page frame
+ movl d1,INTIOBASE+MMUBASE+MMUSSTP | load in sysseg table register
+ Lstploaddone:
+ lea MAXADDR,a2 | PA of last RAM page
+ RELOC(Lhighcode, a1) | addr of high code
+ RELOC(Lehighcode, a3) | end addr
+ Lcodecopy:
+ movw a1@+,a2@+ | copy a word
+ cmpl a3,a1 | done yet?
+ jcs Lcodecopy | no, keep going
+ jmp MAXADDR | go for it!
+
+ /*
+ * BEGIN MMU TRAMPOLINE. This section of code is not
+ * executed in-place. It's copied to the last page
+ * of RAM (mapped va == pa) and executed there.
+ */
+
+ Lhighcode:
+ /*
+ * Set up the vector table, and race to get the MMU
+ * enabled.
+ */
+ movl #_vectab,d0 | set Vector Base Register
+ movc d0,vbr
+
+ RELOC(_mmutype, a0)
+ tstl a0@ | HP MMU?
+ jeq Lhpmmu3 | yes, skip
+ cmpl #MMU_68040,a0@ | 68040?
+ jne Lmotommu2 | no, skip
+ movw #0,INTIOBASE+MMUBASE+MMUCMD+2
+ movw #MMU_IEN+MMU_CEN+MMU_FPE,INTIOBASE+MMUBASE+MMUCMD+2
+ | enable FPU and caches
+ moveq #0,d0 | ensure TT regs are disabled
+ .long 0x4e7b0004 | movc d0,itt0
+ .long 0x4e7b0005 | movc d0,itt1
+ .long 0x4e7b0006 | movc d0,dtt0
+ .long 0x4e7b0007 | movc d0,dtt1
+ .word 0xf4d8 | cinva bc
+ .word 0xf518 | pflusha
+ movl #0x8000,d0
+ .long 0x4e7b0003 | movc d0,tc
+ movl #0x80008000,d0
+ movc d0,cacr | turn on both caches
+ jmp Lenab1
+ Lmotommu2:
+ movl #MMU_IEN+MMU_FPE,INTIOBASE+MMUBASE+MMUCMD
+ | enable 68881 and i-cache
+ RELOC(_prototc, a2)
+ movl #0x82c0aa00,a2@ | value to load TC with
+ pmove a2@,tc | load it
+ jmp Lenab1
+ Lhpmmu3:
+ movl #0,INTIOBASE+MMUBASE+MMUCMD | clear external cache
+ movl #MMU_ENAB,INTIOBASE+MMUBASE+MMUCMD | turn on MMU
+ jmp Lenab1 | jmp to mapped code
+ Lehighcode:
+
+ /*
+ * END MMU TRAMPOLINE. Address register a5 is now free.
+ */
+
+ /*
+ * Should be running mapped from this point on
+ */
+ Lenab1:
+ /* select the software page size now */
+ lea tmpstk,sp | temporary stack
+ jbsr _vm_set_page_size | select software page size
+ /* set kernel stack, user SP, and initial pcb */
+ movl _proc0paddr,a1 | get proc0 pcb addr
+ lea a1@(USPACE-4),sp | set kernel stack to end of area
+ lea _proc0,a2 | initialize proc0.p_addr so that
+ movl a1,a2@(P_ADDR) | we don't deref NULL in trap()
+ movl #USRSTACK-4,a2
+ movl a2,usp | init user SP
+ movl a1,_curpcb | proc0 is running
+
+ tstl _fputype | Have an FPU?
+ jeq Lenab2 | No, skip.
+ clrl a1@(PCB_FPCTX) | ensure null FP context
+ movl a1,sp@-
+ jbsr _m68881_restore | restore it (does not kill a1)
+ addql #4,sp
+ Lenab2:
+ /* flush TLB and turn on caches */
+ jbsr _TBIA | invalidate TLB
+ cmpl #MMU_68040,_mmutype | 68040?
+ jeq Lnocache0 | yes, cache already on
+ movl #CACHE_ON,d0
+ movc d0,cacr | clear cache(s)
+ tstl _ectype
+ jeq Lnocache0
+ MMUADDR(a0)
+ orl #MMU_CEN,a0@(MMUCMD) | turn on external cache
+ Lnocache0:
+ /* Final setup for call to main(). */
+ jbsr _intr_init | initialize interrupt handlers
+ jbsr _hp300_calibrate_delay | calibrate delay() loop
+
+ /*
+ * Create a fake exception frame so that cpu_fork() can copy it.
+ * main() nevers returns; we exit to user mode from a forked process
+ * later on.
+ */
+ clrw sp@- | vector offset/frame type
+ clrl sp@- | PC - filled in by "execve"
+ movw #PSL_USER,sp@- | in user mode
+ clrl sp@- | stack adjust count and padding
+ lea sp@(-64),sp | construct space for D0-D7/A0-A7
+ lea _proc0,a0 | save pointer to frame
+ movl sp,a0@(P_MD_REGS) | in proc0.p_md.md_regs
+
+ jra _main | main()
+
+ pea Lmainreturned | Yow! Main returned!
+ jbsr _panic
+ /* NOTREACHED */
+ Lmainreturned:
+ .asciz "main() returned"
+ .even
+
+ .globl _proc_trampoline
+ _proc_trampoline:
+ movl a3,sp@-
+ jbsr a2@
+ addql #4,sp
+ movl sp@(FR_SP),a0 | grab and load
+ movl a0,usp | user SP
+ moveml sp@+,#0x7FFF | restore most user regs
+ addql #8,sp | toss SP and stack adjust
+ jra rei | and return
+
+
+ /*
+ * Trap/interrupt vector routines
+ */
+
+ .globl _trap, _nofault, _longjmp
+ _buserr:
+ /*
+ * XXX TODO: look at the mac68k _buserr and generalize
+ * XXX the saving of the fault address so this routine
+ * XXX can be shared.
+ */
+ tstl _nofault | device probe?
+ jeq Lberr | no, handle as usual
+ movl _nofault,sp@- | yes,
+ jbsr _longjmp | longjmp(nofault)
+ Lberr:
+ #if defined(M68040)
+ #if defined(M68020) || defined(M68030)
+ cmpl #MMU_68040,_mmutype | 68040?
+ jne _addrerr | no, skip
+ #endif
+ clrl sp@- | stack adjust count
+ moveml #0xFFFF,sp@- | save user registers
+ movl usp,a0 | save the user SP
+ movl a0,sp@(FR_SP) | in the savearea
+ lea sp@(FR_HW),a1 | grab base of HW berr frame
+ moveq #0,d0
+ movw a1@(12),d0 | grab SSW
+ movl a1@(20),d1 | and fault VA
+ btst #11,d0 | check for mis-aligned access
+ jeq Lberr2 | no, skip
+ addl #3,d1 | yes, get into next page
+ andl #PG_FRAME,d1 | and truncate
+ Lberr2:
+ movl d1,sp@- | push fault VA
+ movl d0,sp@- | and padded SSW
+ btst #10,d0 | ATC bit set?
+ jeq Lisberr | no, must be a real bus error
+ movc dfc,d1 | yes, get MMU fault
+ movc d0,dfc | store faulting function code
+ movl sp@(4),a0 | get faulting address
+ .word 0xf568 | ptestr a0@
+ movc d1,dfc
+ .long 0x4e7a0805 | movc mmusr,d0
+ movw d0,sp@ | save (ONLY LOW 16 BITS!)
+ jra Lismerr
+ #endif
+ _addrerr:
+ clrl sp@- | stack adjust count
+ moveml #0xFFFF,sp@- | save user registers
+ movl usp,a0 | save the user SP
+ movl a0,sp@(FR_SP) | in the savearea
+ lea sp@(FR_HW),a1 | grab base of HW berr frame
+ #if defined(M68040)
+ #if defined(M68020) || defined(M68030)
+ cmpl #MMU_68040,_mmutype | 68040?
+ jne Lbenot040 | no, skip
+ #endif
+ movl a1@(8),sp@- | yes, push fault address
+ clrl sp@- | no SSW for address fault
+ jra Lisaerr | go deal with it
+ Lbenot040:
+ #endif
+ moveq #0,d0
+ movw a1@(10),d0 | grab SSW for fault processing
+ btst #12,d0 | RB set?
+ jeq LbeX0 | no, test RC
+ bset #14,d0 | yes, must set FB
+ movw d0,a1@(10) | for hardware too
+ LbeX0:
+ btst #13,d0 | RC set?
+ jeq LbeX1 | no, skip
+ bset #15,d0 | yes, must set FC
+ movw d0,a1@(10) | for hardware too
+ LbeX1:
+ btst #8,d0 | data fault?
+ jeq Lbe0 | no, check for hard cases
+ movl a1@(16),d1 | fault address is as given in frame
+ jra Lbe10 | thats it
+ Lbe0:
+ btst #4,a1@(6) | long (type B) stack frame?
+ jne Lbe4 | yes, go handle
+ movl a1@(2),d1 | no, can use save PC
+ btst #14,d0 | FB set?
+ jeq Lbe3 | no, try FC
+ addql #4,d1 | yes, adjust address
+ jra Lbe10 | done
+ Lbe3:
+ btst #15,d0 | FC set?
+ jeq Lbe10 | no, done
+ addql #2,d1 | yes, adjust address
+ jra Lbe10 | done
+ Lbe4:
+ movl a1@(36),d1 | long format, use stage B address
+ btst #15,d0 | FC set?
+ jeq Lbe10 | no, all done
+ subql #2,d1 | yes, adjust address
+ Lbe10:
+ movl d1,sp@- | push fault VA
+ movl d0,sp@- | and padded SSW
+ movw a1@(6),d0 | get frame format/vector offset
+ andw #0x0FFF,d0 | clear out frame format
+ cmpw #12,d0 | address error vector?
+ jeq Lisaerr | yes, go to it
+ #if defined(M68K_MMU_MOTOROLA)
+ #if defined(M68K_MMU_HP)
+ tstl _mmutype | HP MMU?
+ jeq Lbehpmmu | yes, skip
+ #endif
+ movl d1,a0 | fault address
+ movl sp@,d0 | function code from ssw
+ btst #8,d0 | data fault?
+ jne Lbe10a
+ movql #1,d0 | user program access FC
+ | (we dont separate data/program)
+ btst #5,a1@ | supervisor mode?
+ jeq Lbe10a | if no, done
+ movql #5,d0 | else supervisor program access
+ Lbe10a:
+ ptestr d0,a0@,#7 | do a table search
+ pmove psr,sp@ | save result
+ movb sp@,d1
+ btst #2,d1 | invalid? (incl. limit viol and berr)
+ jeq Lmightnotbemerr | no -> wp check
+ btst #7,d1 | is it MMU table berr?
+ jeq Lismerr | no, must be fast
+ jra Lisberr1 | real bus err needs not be fast
+ Lmightnotbemerr:
+ btst #3,d1 | write protect bit set?
+ jeq Lisberr1 | no, must be bus error
+ movl sp@,d0 | ssw into low word of d0
+ andw #0xc0,d0 | write protect is set on page:
+ cmpw #0x40,d0 | was it read cycle?
+ jeq Lisberr1 | yes, was not WPE, must be bus err
+ jra Lismerr | no, must be mem err
+ Lbehpmmu:
+ #endif
+ #if defined(M68K_MMU_HP)
+ MMUADDR(a0)
+ movl a0@(MMUSTAT),d0 | read status
+ btst #3,d0 | MMU fault?
+ jeq Lisberr | no, just a non-MMU bus error so skip
+ andl #~MMU_FAULT,a0@(MMUSTAT)| yes, clear fault bits
+ movw d0,sp@ | pass MMU stat in upper half of code
+ #endif
+ Lismerr:
+ movl #T_MMUFLT,sp@- | show that we are an MMU fault
+ jra Ltrapnstkadj | and deal with it
+ Lisaerr:
+ movl #T_ADDRERR,sp@- | mark address error
+ jra Ltrapnstkadj | and deal with it
+ Lisberr1:
+ clrw sp@ | re-clear pad word
+ Lisberr:
+ movl #T_BUSERR,sp@- | mark bus error
+ Ltrapnstkadj:
+ jbsr _trap | handle the error
+ lea sp@(12),sp | pop value args
+ movl sp@(FR_SP),a0 | restore user SP
+ movl a0,usp | from save area
+ movw sp@(FR_ADJ),d0 | need to adjust stack?
+ jne Lstkadj | yes, go to it
+ moveml sp@+,#0x7FFF | no, restore most user regs
+ addql #8,sp | toss SSP and stkadj
+ jra rei | all done
+ Lstkadj:
+ lea sp@(FR_HW),a1 | pointer to HW frame
+ addql #8,a1 | source pointer
+ movl a1,a0 | source
+ addw d0,a0 | + hole size = dest pointer
+ movl a1@-,a0@- | copy
+ movl a1@-,a0@- | 8 bytes
+ movl a0,sp@(FR_SP) | new SSP
+ moveml sp@+,#0x7FFF | restore user registers
+ movl sp@,sp | and our SP
+ jra rei | all done
+
+ /*
+ * FP exceptions.
+ */
+ _fpfline: /* XXXthorpej - candidate for vector patch */
+ #if defined(M68040)
+ cmpl #FPU_68040,_fputype | 68040 FPU?
+ jne Lfp_unimp | no, skip FPSP
+ cmpw #0x202c,sp@(6) | format type 2?
+ jne _illinst | no, not an FP emulation
+ Ldofp_unimp:
+ #ifdef FPSP
+ .globl fpsp_unimp
+ jmp fpsp_unimp | yes, go handle it
+ #endif
+ Lfp_unimp:
+ #endif /* M68040 */
+ #ifdef FPU_EMULATE
+ clrl sp@- | stack adjust count
+ moveml #0xFFFF,sp@- | save registers
+ moveq #T_FPEMULI,d0 | denote as FP emulation trap
+ jra fault | do it
+ #else
+ jra _illinst
+ #endif
+
+ _fpunsupp: /* XXXthorpej - candidate for vector patch */
+ #if defined(M68040)
+ cmpl #FPU_68040,_fputype | 68040 FPU?
+ jne _illinst | no, treat as illinst
+ #ifdef FPSP
+ .globl fpsp_unsupp
+ jmp fpsp_unsupp | yes, go handle it
+ #endif
+ Lfp_unsupp:
+ #endif /* M68040 */
+ #ifdef FPU_EMULATE
+ clrl sp@- | stack adjust count
+ moveml #0xFFFF,sp@- | save registers
+ moveq #T_FPEMULD,d0 | denote as FP emulation trap
+ jra fault | do it
+ #else
+ jra _illinst
+ #endif
+
+ /*
+ * Handles all other FP coprocessor exceptions.
+ * Note that since some FP exceptions generate mid-instruction frames
+ * and may cause signal delivery, we need to test for stack adjustment
+ * after the trap call.
+ */
+ .globl _fpfault
+ _fpfault:
+ clrl sp@- | stack adjust count
+ moveml #0xFFFF,sp@- | save user registers
+ movl usp,a0 | and save
+ movl a0,sp@(FR_SP) | the user stack pointer
+ clrl sp@- | no VA arg
+ movl _curpcb,a0 | current pcb
+ lea a0@(PCB_FPCTX),a0 | address of FP savearea
+ fsave a0@ | save state
+ #if defined(M68040) || defined(M68060)
+ /* always null state frame on 68040, 68060 */
+ cmpl #CPU_68040,_cputype
+ jle Lfptnull
+ #endif
+ tstb a0@ | null state frame?
+ jeq Lfptnull | yes, safe
+ clrw d0 | no, need to tweak BIU
+ movb a0@(1),d0 | get frame size
+ bset #3,a0@(0,d0:w) | set exc_pend bit of BIU
+ Lfptnull:
+ fmovem fpsr,sp@- | push fpsr as code argument
+ frestore a0@ | restore state
+ movl #T_FPERR,sp@- | push type arg
+ jra Ltrapnstkadj | call trap and deal with stack cleanup
+
+ /*
+ * Coprocessor and format errors can generate mid-instruction stack
+ * frames and cause signal delivery hence we need to check for potential
+ * stack adjustment.
+ */
+ _coperr:
+ clrl sp@- | stack adjust count
+ moveml #0xFFFF,sp@-
+ movl usp,a0 | get and save
+ movl a0,sp@(FR_SP) | the user stack pointer
+ clrl sp@- | no VA arg
+ clrl sp@- | or code arg
+ movl #T_COPERR,sp@- | push trap type
+ jra Ltrapnstkadj | call trap and deal with stack adjustments
+
+ _fmterr:
+ clrl sp@- | stack adjust count
+ moveml #0xFFFF,sp@-
+ movl usp,a0 | get and save
+ movl a0,sp@(FR_SP) | the user stack pointer
+ clrl sp@- | no VA arg
+ clrl sp@- | or code arg
+ movl #T_FMTERR,sp@- | push trap type
+ jra Ltrapnstkadj | call trap and deal with stack adjustments
+
+ /*
+ * Other exceptions only cause four and six word stack frame and require
+ * no post-trap stack adjustment.
+ */
+ _illinst:
+ clrl sp@-
+ moveml #0xFFFF,sp@-
+ moveq #T_ILLINST,d0
+ jra fault
+
+ _zerodiv:
+ clrl sp@-
+ moveml #0xFFFF,sp@-
+ moveq #T_ZERODIV,d0
+ jra fault
+
+ _chkinst:
+ clrl sp@-
+ moveml #0xFFFF,sp@-
+ moveq #T_CHKINST,d0
+ jra fault
+
+ _trapvinst:
+ clrl sp@-
+ moveml #0xFFFF,sp@-
+ moveq #T_TRAPVINST,d0
+ jra fault
+
+ _privinst:
+ clrl sp@-
+ moveml #0xFFFF,sp@-
+ moveq #T_PRIVINST,d0
+ jra fault
+
+ .globl fault
+ fault:
+ movl usp,a0 | get and save
+ movl a0,sp@(FR_SP) | the user stack pointer
+ clrl sp@- | no VA arg
+ clrl sp@- | or code arg
+ movl d0,sp@- | push trap type
+ jbsr _trap | handle trap
+ lea sp@(12),sp | pop value args
+ movl sp@(FR_SP),a0 | restore
+ movl a0,usp | user SP
+ moveml sp@+,#0x7FFF | restore most user regs
+ addql #8,sp | pop SP and stack adjust
+ jra rei | all done
+
+ .globl _straytrap
+ _badtrap:
+ moveml #0xC0C0,sp@- | save scratch regs
+ movw sp@(22),sp@- | push exception vector info
+ clrw sp@-
+ movl sp@(22),sp@- | and PC
+ jbsr _straytrap | report
+ addql #8,sp | pop args
+ moveml sp@+,#0x0303 | restore regs
+ jra rei | all done
+
+ .globl _syscall
+ _trap0:
+ clrl sp@- | stack adjust count
+ moveml #0xFFFF,sp@- | save user registers
+ movl usp,a0 | save the user SP
+ movl a0,sp@(FR_SP) | in the savearea
+ movl d0,sp@- | push syscall number
+ jbsr _syscall | handle it
+ addql #4,sp | pop syscall arg
+ tstl _astpending
+ jne Lrei2
+ tstb _ssir
+ jeq Ltrap1
+ movw #SPL1,sr
+ tstb _ssir
+ jne Lsir1
+ Ltrap1:
+ movl sp@(FR_SP),a0 | grab and restore
+ movl a0,usp | user SP
+ moveml sp@+,#0x7FFF | restore most registers
+ addql #8,sp | pop SP and stack adjust
+ rte
+
+ /*
+ * Trap 1 - sigreturn
+ */
+ _trap1:
+ jra sigreturn
+
+ /*
+ * Trap 2 - trace trap
+ */
+ _trap2:
+ jra _trace
+
+ /*
+ * Trap 12 is the entry point for the cachectl "syscall" (both HPUX & BSD)
+ * cachectl(command, addr, length)
+ * command in d0, addr in a1, length in d1
+ */
+ .globl _cachectl
+ _trap12:
+ movl d1,sp@- | push length
+ movl a1,sp@- | push addr
+ movl d0,sp@- | push command
+ jbsr _cachectl | do it
+ lea sp@(12),sp | pop args
+ jra rei | all done
+
+ /*
+ * Trace (single-step) trap. Kernel-mode is special.
+ * User mode traps are simply passed on to trap().
+ */
+ _trace:
+ clrl sp@- | stack adjust count
+ moveml #0xFFFF,sp@-
+ moveq #T_TRACE,d0
+ movw sp@(FR_HW),d1 | get PSW
+ andw #PSL_S,d1 | from system mode?
+ jne kbrkpt | yes, kernel breakpoint
+ jra fault | no, user-mode fault
+
+ /*
+ * Trap 15 is used for:
+ * - GDB breakpoints (in user programs)
+ * - KGDB breakpoints (in the kernel)
+ * - trace traps for SUN binaries (not fully supported yet)
+ * User mode traps are simply passed to trap().
+ */
+ _trap15:
+ clrl sp@- | stack adjust count
+ moveml #0xFFFF,sp@-
+ moveq #T_TRAP15,d0
+ movw sp@(FR_HW),d1 | get PSW
+ andw #PSL_S,d1 | from system mode?
+ jne kbrkpt | yes, kernel breakpoint
+ jra fault | no, user-mode fault
+
+ kbrkpt: | Kernel-mode breakpoint or trace trap. (d0=trap_type)
+ | Save the system sp rather than the user sp.
+ movw #PSL_HIGHIPL,sr | lock out interrupts
+ lea sp@(FR_SIZE),a6 | Save stack pointer
+ movl a6,sp@(FR_SP) | from before trap
+
+ | If were are not on tmpstk switch to it.
+ | (so debugger can change the stack pointer)
+ movl a6,d1
+ cmpl #tmpstk,d1
+ jls Lbrkpt2 | already on tmpstk
+ | Copy frame to the temporary stack
+ movl sp,a0 | a0=src
+ lea tmpstk-96,a1 | a1=dst
+ movl a1,sp | sp=new frame
+ moveq #FR_SIZE,d1
+ Lbrkpt1:
+ movl a0@+,a1@+
+ subql #4,d1
+ bgt Lbrkpt1
+
+ Lbrkpt2:
+ | Call the trap handler for the kernel debugger.
+ | Do not call trap() to do it, so that we can
+ | set breakpoints in trap() if we want. We know
+ | the trap type is either T_TRACE or T_BREAKPOINT.
+ | If we have both DDB and KGDB, let KGDB see it first,
+ | because KGDB will just return 0 if not connected.
+ | Save args in d2, a2
+ movl d0,d2 | trap type
+ movl sp,a2 | frame ptr
+ #ifdef KGDB
+ | Let KGDB handle it (if connected)
+ movl a2,sp@- | push frame ptr
+ movl d2,sp@- | push trap type
+ jbsr _kgdb_trap | handle the trap
+ addql #8,sp | pop args
+ cmpl #0,d0 | did kgdb handle it?
+ jne Lbrkpt3 | yes, done
+ #endif
+ #ifdef DDB
+ | Let DDB handle it
+ movl a2,sp@- | push frame ptr
+ movl d2,sp@- | push trap type
+ jbsr _kdb_trap | handle the trap
+ addql #8,sp | pop args
+ #if 0 /* not needed on hp300 */
+ cmpl #0,d0 | did ddb handle it?
+ jne Lbrkpt3 | yes, done
+ #endif
+ #endif
+ /* Sun 3 drops into PROM here. */
+ Lbrkpt3:
+ | The stack pointer may have been modified, or
+ | data below it modified (by kgdb push call),
+ | so push the hardware frame at the current sp
+ | before restoring registers and returning.
+
+ movl sp@(FR_SP),a0 | modified sp
+ lea sp@(FR_SIZE),a1 | end of our frame
+ movl a1@-,a0@- | copy 2 longs with
+ movl a1@-,a0@- | ... predecrement
+ movl a0,sp@(FR_SP) | sp = h/w frame
+ moveml sp@+,#0x7FFF | restore all but sp
+ movl sp@,sp | ... and sp
+ rte | all done
+
+ /* Use common m68k sigreturn */
+ #include <m68k/m68k/sigreturn.s>
+
+ /*
+ * Interrupt handlers.
+ * All device interrupts are auto-vectored. The CPU provides
+ * the vector 0x18+level. Note we count spurious interrupts, but
+ * we don't do anything else with them.
+ */
+
+ #define INTERRUPT_SAVEREG moveml #0xC0C0,sp@-
+ #define INTERRUPT_RESTOREREG moveml sp@+,#0x0303
+
+ /* Externs. */
+ .globl _hilint, _intr_dispatch, _nmihand
+ .globl _hardclock, _statintr
+
+ _spurintr: /* Level 0 */
+ addql #1,_intrcnt+0
+ addql #1,_cnt+V_INTR
+ jra rei
+
+ _lev1intr: /* Level 1: HIL XXX this needs to go away */
+ INTERRUPT_SAVEREG
+ jbsr _hilint
+ INTERRUPT_RESTOREREG
+ addql #1,_intrcnt+4
+ addql #1,_cnt+V_INTR
+ jra rei
+
+ _intrhand: /* Levels 2 through 5 */
+ INTERRUPT_SAVEREG
+ movw sp@(22),sp@- | push exception vector info
+ clrw sp@-
+ jbsr _intr_dispatch | call dispatch routine
+ addql #4,sp
+ INTERRUPT_RESTOREREG
+ jra rei | all done
+
+ _lev6intr: /* Level 6: clock */
+ INTERRUPT_SAVEREG
+ CLKADDR(a0)
+ movb a0@(CLKSR),d0 | read clock status
+ Lclkagain:
+ btst #0,d0 | clear timer1 int immediately to
+ jeq Lnotim1 | minimize chance of losing another
+ movpw a0@(CLKMSB1),d1 | due to statintr processing delay
+ Lnotim1:
+ btst #2,d0 | timer3 interrupt?
+ jeq Lnotim3 | no, skip statclock
+ movpw a0@(CLKMSB3),d1 | clear timer3 interrupt
+ addql #1,_intrcnt+28 | count clock interrupts
+ lea sp@(16),a1 | a1 = &clockframe
+ movl d0,sp@- | save status
+ movl a1,sp@-
+ jbsr _statintr | statintr(&frame)
+ addql #4,sp
+ movl sp@+,d0 | restore pre-statintr status
+ CLKADDR(a0)
+ Lnotim3:
+ btst #0,d0 | timer1 interrupt?
+ jeq Lrecheck | no, skip hardclock
+ addql #1,_intrcnt+24 | count hardclock interrupts
+ lea sp@(16),a1 | a1 = &clockframe
+ movl a1,sp@-
+ #ifdef USELEDS
+ .globl _ledaddr, _inledcontrol, _ledcontrol, _hz
+ tstl _ledaddr | using LEDs?
+ jeq Lnoled0 | no, skip this code
+ movl heartbeat,d0 | get tick count
+ addql #1,d0 | increment
+ movl _hz,d1
+ addl #50,d1 | get the timing a little closer
+ cmpl #0,beatstatus | time to slow down?
+ jeq SlowThrob
+ lsrl #3,d1 | fast throb
+ SlowThrob:
+ lsrl #1,d1 | slow throb
+ cmpl d0,d1 | are we there yet?
+ jne Lnoled1 | no, nothing to do
+ tstl _inledcontrol | already updating LEDs?
+ jne Lnoled2 | yes, skip it
+ addl #1,beatstatus | incr beat status
+ cmpl #3,beatstatus | time to reset?
+ ble SkipReset
+ movl #0,beatstatus | reset the status indicator
+ SkipReset:
+ movl #LED_PULSE,sp@-
+ movl #LED_DISK+LED_LANRCV+LED_LANXMT,sp@-
+ clrl sp@-
+ jbsr _ledcontrol | toggle pulse, turn all others off
+ lea sp@(12),sp
+ Lnoled2:
+ movql #0,d0
+ Lnoled1:
+ movl d0,heartbeat
+ Lnoled0:
+ #endif
+ jbsr _hardclock | hardclock(&frame)
+ addql #4,sp
+ CLKADDR(a0)
+ Lrecheck:
+ addql #1,_cnt+V_INTR | chalk up another interrupt
+ movb a0@(CLKSR),d0 | see if anything happened
+ jmi Lclkagain | while we were in hardclock/statintr
+ INTERRUPT_RESTOREREG
+ jra rei | all done
+
+ _lev7intr: /* Level 7: Parity errors, reset key */
+ addql #1,_intrcnt+32
+ clrl sp@-
+ moveml #0xFFFF,sp@- | save registers
+ movl usp,a0 | and save
+ movl a0,sp@(FR_SP) | the user stack pointer
+ jbsr _nmihand | call handler
+ movl sp@(FR_SP),a0 | restore
+ movl a0,usp | user SP
+ moveml sp@+,#0x7FFF | and remaining registers
+ addql #8,sp | pop SP and stack adjust
+ jra rei | all done
+
+ /*
+ * Emulation of VAX REI instruction.
+ *
+ * This code deals with checking for and servicing ASTs
+ * (profiling, scheduling) and software interrupts (network, softclock).
+ * We check for ASTs first, just like the VAX. To avoid excess overhead
+ * the T_ASTFLT handling code will also check for software interrupts so we
+ * do not have to do it here. After identifing that we need an AST we
+ * drop the IPL to allow device interrupts.
+ *
+ * This code is complicated by the fact that sendsig may have been called
+ * necessitating a stack cleanup.
+ */
+ .comm _ssir,1
+ .globl _astpending
+ .globl rei
+ rei:
+ tstl _astpending | AST pending?
+ jeq Lchksir | no, go check for SIR
+ Lrei1:
+ btst #5,sp@ | yes, are we returning to user mode?
+ jne Lchksir | no, go check for SIR
+ movw #PSL_LOWIPL,sr | lower SPL
+ clrl sp@- | stack adjust
+ moveml #0xFFFF,sp@- | save all registers
+ movl usp,a1 | including
+ movl a1,sp@(FR_SP) | the users SP
+ Lrei2:
+ clrl sp@- | VA == none
+ clrl sp@- | code == none
+ movl #T_ASTFLT,sp@- | type == async system trap
+ jbsr _trap | go handle it
+ lea sp@(12),sp | pop value args
+ movl sp@(FR_SP),a0 | restore user SP
+ movl a0,usp | from save area
+ movw sp@(FR_ADJ),d0 | need to adjust stack?
+ jne Laststkadj | yes, go to it
+ moveml sp@+,#0x7FFF | no, restore most user regs
+ addql #8,sp | toss SP and stack adjust
+ rte | and do real RTE
+ Laststkadj:
+ lea sp@(FR_HW),a1 | pointer to HW frame
+ addql #8,a1 | source pointer
+ movl a1,a0 | source
+ addw d0,a0 | + hole size = dest pointer
+ movl a1@-,a0@- | copy
+ movl a1@-,a0@- | 8 bytes
+ movl a0,sp@(FR_SP) | new SSP
+ moveml sp@+,#0x7FFF | restore user registers
+ movl sp@,sp | and our SP
+ rte | and do real RTE
+ Lchksir:
+ tstb _ssir | SIR pending?
+ jeq Ldorte | no, all done
+ movl d0,sp@- | need a scratch register
+ movw sp@(4),d0 | get SR
+ andw #PSL_IPL7,d0 | mask all but IPL
+ jne Lnosir | came from interrupt, no can do
+ movl sp@+,d0 | restore scratch register
+ Lgotsir:
+ movw #SPL1,sr | prevent others from servicing int
+ tstb _ssir | too late?
+ jeq Ldorte | yes, oh well...
+ clrl sp@- | stack adjust
+ moveml #0xFFFF,sp@- | save all registers
+ movl usp,a1 | including
+ movl a1,sp@(FR_SP) | the users SP
+ Lsir1:
+ clrl sp@- | VA == none
+ clrl sp@- | code == none
+ movl #T_SSIR,sp@- | type == software interrupt
+ jbsr _trap | go handle it
+ lea sp@(12),sp | pop value args
+ movl sp@(FR_SP),a0 | restore
+ movl a0,usp | user SP
+ moveml sp@+,#0x7FFF | and all remaining registers
+ addql #8,sp | pop SP and stack adjust
+ rte
+ Lnosir:
+ movl sp@+,d0 | restore scratch register
+ Ldorte:
+ rte | real return
+
+ /*
+ * Use common m68k sigcode.
+ */
+ #include <m68k/m68k/sigcode.s>
+
+ /*
+ * Primitives
+ */
+
+ #include <machine/asm.h>
+
+ /*
+ * Use common m68k support routines.
+ */
+ #include <m68k/m68k/support.s>
+
+ .globl _whichqs,_qs,_cnt,_panic
+ .globl _curproc,_want_resched
+
+ /*
+ * Use common m68k process manipulation routines.
+ */
+ #include <m68k/m68k/proc_subr.s>
+
+ Lsw0:
+ .asciz "switch"
+ .even
+
+ .globl _curpcb
+ .globl _masterpaddr | XXX compatibility (debuggers)
+ .data
+ _masterpaddr: | XXX compatibility (debuggers)
+ _curpcb:
+ .long 0
+ mdpflag:
+ .byte 0 | copy of proc md_flags low byte
+ .align 2
+ .comm nullpcb,SIZEOF_PCB
+ .text
+
+ /*
+ * At exit of a process, do a switch for the last time.
+ * Switch to a safe stack and PCB, and deallocate the process's resources.
+ */
+ ENTRY(switch_exit)
+ movl sp@(4),a0
+ movl #nullpcb,_curpcb | save state into garbage pcb
+ lea tmpstk,sp | goto a tmp stack
+
+ /* Free old process's resources. */
+ movl #USPACE,sp@- | size of u-area
+ movl a0@(P_ADDR),sp@- | address of process's u-area
+ movl _kernel_map,sp@- | map it was allocated in
+ jbsr _kmem_free | deallocate it
+ lea sp@(12),sp | pop args
+
+ jra _cpu_switch
+
+ /*
+ * When no processes are on the runq, Swtch branches to Idle
+ * to wait for something to come ready.
+ */
+ .globl Idle
+ Idle:
+ stop #PSL_LOWIPL
+ movw #PSL_HIGHIPL,sr
+ movl _whichqs,d0
+ jeq Idle
+ jra Lsw1
+
+ Lbadsw:
+ movl #Lsw0,sp@-
+ jbsr _panic
+ /*NOTREACHED*/
+
+ /*
+ * cpu_switch()
+ *
+ * NOTE: On the mc68851 (318/319/330) we attempt to avoid flushing the
+ * entire ATC. The effort involved in selective flushing may not be
+ * worth it, maybe we should just flush the whole thing?
+ *
+ * NOTE 2: With the new VM layout we now no longer know if an inactive
+ * user's PTEs have been changed (formerly denoted by the SPTECHG p_flag
+ * bit). For now, we just always flush the full ATC.
+ */
+ ENTRY(cpu_switch)
+ movl _curpcb,a0 | current pcb
+ movw sr,a0@(PCB_PS) | save sr before changing ipl
+ #ifdef notyet
+ movl _curproc,sp@- | remember last proc running
+ #endif
+ clrl _curproc
+
+ /*
+ * Find the highest-priority queue that isn't empty,
+ * then take the first proc from that queue.
+ */
+ movw #PSL_HIGHIPL,sr | lock out interrupts
+ movl _whichqs,d0
+ jeq Idle
+ Lsw1:
+ movl d0,d1
+ negl d0
+ andl d1,d0
+ bfffo d0{#0:#32},d1
+ eorib #31,d1
+
+ movl d1,d0
+ lslb #3,d1 | convert queue number to index
+ addl #_qs,d1 | locate queue (q)
+ movl d1,a1
+ movl a1@(P_FORW),a0 | p = q->p_forw
+ cmpal d1,a0 | anyone on queue?
+ jeq Lbadsw | no, panic
+ movl a0@(P_FORW),a1@(P_FORW) | q->p_forw = p->p_forw
+ movl a0@(P_FORW),a1 | n = p->p_forw
+ movl d1,a1@(P_BACK) | n->p_back = q
+ cmpal d1,a1 | anyone left on queue?
+ jne Lsw2 | yes, skip
+ movl _whichqs,d1
+ bclr d0,d1 | no, clear bit
+ movl d1,_whichqs
+ Lsw2:
+ movl a0,_curproc
+ clrl _want_resched
+ #ifdef notyet
+ movl sp@+,a1
+ cmpl a0,a1 | switching to same proc?
+ jeq Lswdone | yes, skip save and restore
+ #endif
+ /*
+ * Save state of previous process in its pcb.
+ */
+ movl _curpcb,a1
+ moveml #0xFCFC,a1@(PCB_REGS) | save non-scratch registers
+ movl usp,a2 | grab USP (a2 has been saved)
+ movl a2,a1@(PCB_USP) | and save it
+
+ tstl _fputype | Do we have an FPU?
+ jeq Lswnofpsave | No Then don't attempt save.
+ lea a1@(PCB_FPCTX),a2 | pointer to FP save area
+ fsave a2@ | save FP state
+ tstb a2@ | null state frame?
+ jeq Lswnofpsave | yes, all done
+ fmovem fp0-fp7,a2@(216) | save FP general registers
+ fmovem fpcr/fpsr/fpi,a2@(312) | save FP control registers
+ Lswnofpsave:
+
+ #ifdef DIAGNOSTIC
+ tstl a0@(P_WCHAN)
+ jne Lbadsw
+ cmpb #SRUN,a0@(P_STAT)
+ jne Lbadsw
+ #endif
+ clrl a0@(P_BACK) | clear back link
+ movb a0@(P_MD_FLAGS+3),mdpflag | low byte of p_md.md_flags
+ movl a0@(P_ADDR),a1 | get p_addr
+ movl a1,_curpcb
+
+ /* see if pmap_activate needs to be called; should remove this */
+ movl a0@(P_VMSPACE),a0 | vmspace = p->p_vmspace
+ #ifdef DIAGNOSTIC
+ tstl a0 | map == VM_MAP_NULL?
+ jeq Lbadsw | panic
+ #endif
+ lea a0@(VM_PMAP),a0 | pmap = &vmspace.vm_pmap
+ tstl a0@(PM_STCHG) | pmap->st_changed?
+ jeq Lswnochg | no, skip
+ pea a1@ | push pcb (at p_addr)
+ pea a0@ | push pmap
+ jbsr _pmap_activate | pmap_activate(pmap, pcb)
+ addql #8,sp
+ movl _curpcb,a1 | restore p_addr
+ Lswnochg:
+
+ lea tmpstk,sp | now goto a tmp stack for NMI
+ #if defined(M68040)
+ #if defined(M68020) || defined(M68030)
+ cmpl #MMU_68040,_mmutype | 68040?
+ jne Lres1a | no, skip
+ #endif
+ .word 0xf518 | yes, pflusha
+ movl a1@(PCB_USTP),d0 | get USTP
+ moveq #PGSHIFT,d1
+ lsll d1,d0 | convert to addr
+ .long 0x4e7b0806 | movc d0,urp
+ jra Lcxswdone
+ Lres1a:
+ #endif
+ movl #CACHE_CLR,d0
+ movc d0,cacr | invalidate cache(s)
+ #if defined(M68K_MMU_MOTOROLA)
+ #if defined(M68K_MMU_HP)
+ tstl _mmutype | HP MMU?
+ jeq Lhpmmu4 | yes, skip
+ #endif
+ pflusha | flush entire TLB
+ movl a1@(PCB_USTP),d0 | get USTP
+ moveq #PGSHIFT,d1
+ lsll d1,d0 | convert to addr
+ lea _protorp,a0 | CRP prototype
+ movl d0,a0@(4) | stash USTP
+ pmove a0@,crp | load new user root pointer
+ jra Lcxswdone | thats it
+ Lhpmmu4:
+ #endif
+ #if defined(M68K_MMU_HP)
+ MMUADDR(a0)
+ movl a0@(MMUTBINVAL),d1 | invalidate TLB
+ tstl _ectype | got external VAC?
+ jle Lnocache1 | no, skip
+ andl #~MMU_CEN,a0@(MMUCMD) | toggle cache enable
+ orl #MMU_CEN,a0@(MMUCMD) | to clear data cache
+ Lnocache1:
+ movl a1@(PCB_USTP),a0@(MMUUSTP) | context switch
+ #endif
+ Lcxswdone:
+ moveml a1@(PCB_REGS),#0xFCFC | and registers
+ movl a1@(PCB_USP),a0
+ movl a0,usp | and USP
+
+ tstl _fputype | If we don't have an FPU,
+ jeq Lnofprest | don't try to restore it.
+ lea a1@(PCB_FPCTX),a0 | pointer to FP save area
+ tstb a0@ | null state frame?
+ jeq Lresfprest | yes, easy
+ #if defined(M68040)
+ #if defined(M68020) || defined(M68030)
+ cmpl #MMU_68040,_mmutype | 68040?
+ jne Lresnot040 | no, skip
+ #endif
+ clrl sp@- | yes...
+ frestore sp@+ | ...magic!
+ Lresnot040:
+ #endif
+ fmovem a0@(312),fpcr/fpsr/fpi | restore FP control registers
+ fmovem a0@(216),fp0-fp7 | restore FP general registers
+ Lresfprest:
+ frestore a0@ | restore state
+
+ Lnofprest:
+ movw a1@(PCB_PS),sr | no, restore PS
+ moveq #1,d0 | return 1 (for alternate returns)
+ rts
+
+ /*
+ * savectx(pcb)
+ * Update pcb, saving current processor state.
+ */
+ ENTRY(savectx)
+ movl sp@(4),a1
+ movw sr,a1@(PCB_PS)
+ movl usp,a0 | grab USP
+ movl a0,a1@(PCB_USP) | and save it
+ moveml #0xFCFC,a1@(PCB_REGS) | save non-scratch registers
+
+ tstl _fputype | Do we have FPU?
+ jeq Lsvnofpsave | No? Then don't save state.
+ lea a1@(PCB_FPCTX),a0 | pointer to FP save area
+ fsave a0@ | save FP state
+ tstb a0@ | null state frame?
+ jeq Lsvnofpsave | yes, all done
+ fmovem fp0-fp7,a0@(216) | save FP general registers
+ fmovem fpcr/fpsr/fpi,a0@(312) | save FP control registers
+ Lsvnofpsave:
+ moveq #0,d0 | return 0
+ rts
+
+ #if defined(M68040)
+ ENTRY(suline)
+ movl sp@(4),a0 | address to write
+ movl _curpcb,a1 | current pcb
+ movl #Lslerr,a1@(PCB_ONFAULT) | where to return to on a fault
+ movl sp@(8),a1 | address of line
+ movl a1@+,d0 | get lword
+ movsl d0,a0@+ | put lword
+ nop | sync
+ movl a1@+,d0 | get lword
+ movsl d0,a0@+ | put lword
+ nop | sync
+ movl a1@+,d0 | get lword
+ movsl d0,a0@+ | put lword
+ nop | sync
+ movl a1@+,d0 | get lword
+ movsl d0,a0@+ | put lword
+ nop | sync
+ moveq #0,d0 | indicate no fault
+ jra Lsldone
+ Lslerr:
+ moveq #-1,d0
+ Lsldone:
+ movl _curpcb,a1 | current pcb
+ clrl a1@(PCB_ONFAULT) | clear fault address
+ rts
+ #endif
+
+ /*
+ * Invalidate entire TLB.
+ */
+ ENTRY(TBIA)
+ __TBIA:
+ #if defined(M68040)
+ cmpl #MMU_68040,_mmutype | 68040?
+ jne Lmotommu3 | no, skip
+ .word 0xf518 | yes, pflusha
+ rts
+ Lmotommu3:
+ #endif
+ #if defined(M68K_MMU_MOTOROLA)
+ tstl _mmutype | HP MMU?
+ jeq Lhpmmu6 | yes, skip
+ pflusha | flush entire TLB
+ jpl Lmc68851a | 68851 implies no d-cache
+ movl #DC_CLEAR,d0
+ movc d0,cacr | invalidate on-chip d-cache
+ Lmc68851a:
+ rts
+ Lhpmmu6:
+ #endif
+ #if defined(M68K_MMU_HP)
+ MMUADDR(a0)
+ movl a0@(MMUTBINVAL),sp@- | do not ask me, this
+ addql #4,sp | is how hpux does it
+ #ifdef DEBUG
+ tstl fullcflush
+ jne __DCIA | XXX: invalidate entire cache
+ #endif
+ #endif
+ rts
+
+ /*
+ * Invalidate any TLB entry for given VA (TB Invalidate Single)
+ */
+ ENTRY(TBIS)
+ #ifdef DEBUG
+ tstl fulltflush | being conservative?
+ jne __TBIA | yes, flush entire TLB
+ #endif
+ #if defined(M68040)
+ cmpl #MMU_68040,_mmutype | 68040?
+ jne Lmotommu4 | no, skip
+ movl sp@(4),a0
+ movc dfc,d1
+ moveq #1,d0 | user space
+ movc d0,dfc
+ .word 0xf508 | pflush a0@
+ moveq #5,d0 | super space
+ movc d0,dfc
+ .word 0xf508 | pflush a0@
+ movc d1,dfc
+ rts
+ Lmotommu4:
+ #endif
+ #if defined(M68K_MMU_MOTOROLA)
+ tstl _mmutype | HP MMU?
+ jeq Lhpmmu5 | yes, skip
+ movl sp@(4),a0 | get addr to flush
+ jpl Lmc68851b | is 68851?
+ pflush #0,#0,a0@ | flush address from both sides
+ movl #DC_CLEAR,d0
+ movc d0,cacr | invalidate on-chip data cache
+ rts
+ Lmc68851b:
+ pflushs #0,#0,a0@ | flush address from both sides
+ rts
+ Lhpmmu5:
+ #endif
+ #if defined(M68K_MMU_HP)
+ movl sp@(4),d0 | VA to invalidate
+ bclr #0,d0 | ensure even
+ movl d0,a0
+ movw sr,d1 | go critical
+ movw #PSL_HIGHIPL,sr | while in purge space
+ moveq #FC_PURGE,d0 | change address space
+ movc d0,dfc | for destination
+ moveq #0,d0 | zero to invalidate?
+ movsl d0,a0@ | hit it
+ moveq #FC_USERD,d0 | back to old
+ movc d0,dfc | address space
+ movw d1,sr | restore IPL
+ #endif
+ rts
+
+ /*
+ * Invalidate supervisor side of TLB
+ */
+ ENTRY(TBIAS)
+ #ifdef DEBUG
+ tstl fulltflush | being conservative?
+ jne __TBIA | yes, flush everything
+ #endif
+ #if defined(M68040)
+ cmpl #MMU_68040,_mmutype | 68040?
+ jne Lmotommu5 | no, skip
+ .word 0xf518 | yes, pflusha (for now) XXX
+ rts
+ Lmotommu5:
+ #endif
+ #if defined(M68K_MMU_MOTOROLA)
+ tstl _mmutype | HP MMU?
+ jeq Lhpmmu7 | yes, skip
+ jpl Lmc68851c | 68851?
+ pflush #4,#4 | flush supervisor TLB entries
+ movl #DC_CLEAR,d0
+ movc d0,cacr | invalidate on-chip d-cache
+ rts
+ Lmc68851c:
+ pflushs #4,#4 | flush supervisor TLB entries
+ rts
+ Lhpmmu7:
+ #endif
+ #if defined(M68K_MMU_HP)
+ MMUADDR(a0)
+ movl #0x8000,d0 | more
+ movl d0,a0@(MMUTBINVAL) | HP magic
+ #ifdef DEBUG
+ tstl fullcflush
+ jne __DCIS | XXX: invalidate entire sup. cache
+ #endif
+ #endif
+ rts
+
+ /*
+ * Invalidate user side of TLB
+ */
+ ENTRY(TBIAU)
+ #ifdef DEBUG
+ tstl fulltflush | being conservative?
+ jne __TBIA | yes, flush everything
+ #endif
+ #if defined(M68040)
+ cmpl #MMU_68040,_mmutype | 68040?
+ jne Lmotommu6 | no, skip
+ .word 0xf518 | yes, pflusha (for now) XXX
+ rts
+ Lmotommu6:
+ #endif
+ #if defined(M68K_MMU_MOTOROLA)
+ tstl _mmutype | HP MMU?
+ jeq Lhpmmu8 | yes, skip
+ jpl Lmc68851d | 68851?
+ pflush #0,#4 | flush user TLB entries
+ movl #DC_CLEAR,d0
+ movc d0,cacr | invalidate on-chip d-cache
+ rts
+ Lmc68851d:
+ pflushs #0,#4 | flush user TLB entries
+ rts
+ Lhpmmu8:
+ #endif
+ #if defined(M68K_MMU_HP)
+ MMUADDR(a0)
+ moveq #0,d0 | more
+ movl d0,a0@(MMUTBINVAL) | HP magic
+ #ifdef DEBUG
+ tstl fullcflush
+ jne __DCIU | XXX: invalidate entire user cache
+ #endif
+ #endif
+ rts
+
+ /*
+ * Invalidate instruction cache
+ */
+ ENTRY(ICIA)
+ #if defined(M68040)
+ ENTRY(ICPA)
+ cmpl #MMU_68040,_mmutype | 68040
+ jne Lmotommu7 | no, skip
+ .word 0xf498 | cinva ic
+ rts
+ Lmotommu7:
+ #endif
+ movl #IC_CLEAR,d0
+ movc d0,cacr | invalidate i-cache
+ rts
+
+ /*
+ * Invalidate data cache.
+ * HP external cache allows for invalidation of user/supervisor portions.
+ * NOTE: we do not flush 68030 on-chip cache as there are no aliasing
+ * problems with DC_WA. The only cases we have to worry about are context
+ * switch and TLB changes, both of which are handled "in-line" in resume
+ * and TBI*.
+ */
+ ENTRY(DCIA)
+ __DCIA:
+ #if defined(M68040)
+ cmpl #MMU_68040,_mmutype | 68040
+ jne Lmotommu8 | no, skip
+ /* XXX implement */
+ rts
+ Lmotommu8:
+ #endif
+ #if defined(M68K_MMU_HP)
+ tstl _ectype | got external VAC?
+ jle Lnocache2 | no, all done
+ MMUADDR(a0)
+ andl #~MMU_CEN,a0@(MMUCMD) | disable cache in MMU control reg
+ orl #MMU_CEN,a0@(MMUCMD) | reenable cache in MMU control reg
+ Lnocache2:
+ #endif
+ rts
+
+ ENTRY(DCIS)
+ __DCIS:
+ #if defined(M68040)
+ cmpl #MMU_68040,_mmutype | 68040
+ jne Lmotommu9 | no, skip
+ /* XXX implement */
+ rts
+ Lmotommu9:
+ #endif
+ #if defined(M68K_MMU_HP)
+ tstl _ectype | got external VAC?
+ jle Lnocache3 | no, all done
+ MMUADDR(a0)
+ movl a0@(MMUSSTP),d0 | read the supervisor STP
+ movl d0,a0@(MMUSSTP) | write it back
+ Lnocache3:
+ #endif
+ rts
+
+ ENTRY(DCIU)
+ __DCIU:
+ #if defined(M68040)
+ cmpl #MMU_68040,_mmutype | 68040
+ jne LmotommuA | no, skip
+ /* XXX implement */
+ rts
+ LmotommuA:
+ #endif
+ #if defined(M68K_MMU_HP)
+ tstl _ectype | got external VAC?
+ jle Lnocache4 | no, all done
+ MMUADDR(a0)
+ movl a0@(MMUUSTP),d0 | read the user STP
+ movl d0,a0@(MMUUSTP) | write it back
+ Lnocache4:
+ #endif
+ rts
+
+ #if defined(M68040)
+ ENTRY(ICPL)
+ movl sp@(4),a0 | address
+ .word 0xf488 | cinvl ic,a0@
+ rts
+ ENTRY(ICPP)
+ movl sp@(4),a0 | address
+ .word 0xf490 | cinvp ic,a0@
+ rts
+ ENTRY(DCPL)
+ movl sp@(4),a0 | address
+ .word 0xf448 | cinvl dc,a0@
+ rts
+ ENTRY(DCPP)
+ movl sp@(4),a0 | address
+ .word 0xf450 | cinvp dc,a0@
+ rts
+ ENTRY(DCPA)
+ .word 0xf458 | cinva dc
+ rts
+ ENTRY(DCFL)
+ movl sp@(4),a0 | address
+ .word 0xf468 | cpushl dc,a0@
+ rts
+ ENTRY(DCFP)
+ movl sp@(4),a0 | address
+ .word 0xf470 | cpushp dc,a0@
+ rts
+ #endif
+
+ ENTRY(PCIA)
+ #if defined(M68040)
+ ENTRY(DCFA)
+ cmpl #MMU_68040,_mmutype | 68040
+ jne LmotommuB | no, skip
+ .word 0xf478 | cpusha dc
+ rts
+ LmotommuB:
+ #endif
+ #if defined(M68K_MMU_MOTOROLA)
+ movl #DC_CLEAR,d0
+ movc d0,cacr | invalidate on-chip d-cache
+ tstl _ectype | got external PAC?
+ jge Lnocache6 | no, all done
+ MMUADDR(a0)
+ andl #~MMU_CEN,a0@(MMUCMD) | disable cache in MMU control reg
+ orl #MMU_CEN,a0@(MMUCMD) | reenable cache in MMU control reg
+ Lnocache6:
+ #endif
+ rts
+
+ ENTRY(ecacheon)
+ tstl _ectype
+ jeq Lnocache7
+ MMUADDR(a0)
+ orl #MMU_CEN,a0@(MMUCMD)
+ Lnocache7:
+ rts
+
+ ENTRY(ecacheoff)
+ tstl _ectype
+ jeq Lnocache8
+ MMUADDR(a0)
+ andl #~MMU_CEN,a0@(MMUCMD)
+ Lnocache8:
+ rts
+
+ .globl _getsfc, _getdfc
+ _getsfc:
+ movc sfc,d0
+ rts
+ _getdfc:
+ movc dfc,d0
+ rts
+
+ /*
+ * Load a new user segment table pointer.
+ */
+ ENTRY(loadustp)
+ #if defined(M68K_MMU_MOTOROLA)
+ tstl _mmutype | HP MMU?
+ jeq Lhpmmu9 | yes, skip
+ movl sp@(4),d0 | new USTP
+ moveq #PGSHIFT,d1
+ lsll d1,d0 | convert to addr
+ #if defined(M68040)
+ cmpl #MMU_68040,_mmutype | 68040?
+ jne LmotommuC | no, skip
+ .long 0x4e7b0806 | movc d0,urp
+ rts
+ LmotommuC:
+ #endif
+ lea _protorp,a0 | CRP prototype
+ movl d0,a0@(4) | stash USTP
+ pmove a0@,crp | load root pointer
+ movl #DC_CLEAR,d0
+ movc d0,cacr | invalidate on-chip d-cache
+ rts | since pmove flushes TLB
+ Lhpmmu9:
+ #endif
+ #if defined(M68K_MMU_HP)
+ MMUADDR(a0)
+ movl sp@(4),a0@(MMUUSTP) | load a new USTP
+ #endif
+ rts
+
+ ENTRY(ploadw)
+ #if defined(M68K_MMU_MOTOROLA)
+ movl sp@(4),a0 | address to load
+ #if defined(M68K_MMU_HP)
+ tstl _mmutype | HP MMU?
+ jeq Lploadwskp | yes, skip
+ #endif
+ #if defined(M68040)
+ cmpl #MMU_68040,_mmutype | 68040?
+ jeq Lploadwskp | yes, skip
+ #endif
+ ploadw #1,a0@ | pre-load translation
+ Lploadwskp:
+ #endif
+ rts
+
+ /*
+ * Set processor priority level calls. Most are implemented with
+ * inline asm expansions. However, spl0 requires special handling
+ * as we need to check for our emulated software interrupts.
+ */
+
+ ENTRY(spl0)
+ moveq #0,d0
+ movw sr,d0 | get old SR for return
+ movw #PSL_LOWIPL,sr | restore new SR
+ tstb _ssir | software interrupt pending?
+ jeq Lspldone | no, all done
+ subql #4,sp | make room for RTE frame
+ movl sp@(4),sp@(2) | position return address
+ clrw sp@(6) | set frame type 0
+ movw #PSL_LOWIPL,sp@ | and new SR
+ jra Lgotsir | go handle it
+ Lspldone:
+ rts
+
+ /*
+ * _delay(u_int N)
+ *
+ * Delay for at least (N/256) microsecends.
+ * This routine depends on the variable: delay_divisor
+ * which should be set based on the CPU clock rate.
+ */
+ .globl __delay
+ __delay:
+ | d0 = arg = (usecs << 8)
+ movl sp@(4),d0
+ | d1 = delay_divisor
+ movl _delay_divisor,d1
+ L_delay:
+ subl d1,d0
+ jgt L_delay
+ rts
+
+ /*
+ * Save and restore 68881 state.
+ * Pretty awful looking since our assembler does not
+ * recognize FP mnemonics.
+ */
+ ENTRY(m68881_save)
+ movl sp@(4),a0 | save area pointer
+ fsave a0@ | save state
+ tstb a0@ | null state frame?
+ jeq Lm68881sdone | yes, all done
+ fmovem fp0-fp7,a0@(216) | save FP general registers
+ fmovem fpcr/fpsr/fpi,a0@(312) | save FP control registers
+ Lm68881sdone:
+ rts
+
+ ENTRY(m68881_restore)
+ movl sp@(4),a0 | save area pointer
+ tstb a0@ | null state frame?
+ jeq Lm68881rdone | yes, easy
+ fmovem a0@(312),fpcr/fpsr/fpi | restore FP control registers
+ fmovem a0@(216),fp0-fp7 | restore FP general registers
+ Lm68881rdone:
+ frestore a0@ | restore state
+ rts
+
+ /*
+ * Handle the nitty-gritty of rebooting the machine.
+ * Basically we just turn off the MMU and jump to the appropriate ROM routine.
+ * Note that we must be running in an address range that is mapped one-to-one
+ * logical to physical so that the PC is still valid immediately after the MMU
+ * is turned off. We have conveniently mapped the last page of physical
+ * memory this way.
+ */
+ .globl _doboot
+ _doboot:
+ #if defined(M68040)
+ cmpl #MMU_68040,_mmutype | 68040?
+ jeq Lnocache5 | yes, skip
+ #endif
+ movl #CACHE_OFF,d0
+ movc d0,cacr | disable on-chip cache(s)
+ tstl _ectype | external cache?
+ jeq Lnocache5 | no, skip
+ MMUADDR(a0)
+ andl #~MMU_CEN,a0@(MMUCMD) | disable external cache
+ Lnocache5:
+ lea MAXADDR,a0 | last page of physical memory
+ movl _boothowto,a0@+ | store howto
+ movl _bootdev,a0@+ | and devtype
+ lea Lbootcode,a1 | start of boot code
+ lea Lebootcode,a3 | end of boot code
+ Lbootcopy:
+ movw a1@+,a0@+ | copy a word
+ cmpl a3,a1 | done yet?
+ jcs Lbootcopy | no, keep going
+ #if defined(M68040)
+ cmpl #MMU_68040,_mmutype | 68040?
+ jne LmotommuE | no, skip
+ .word 0xf4f8 | cpusha bc
+ LmotommuE:
+ #endif
+ jmp MAXADDR+8 | jump to last page
+
+ #define DOREBOOT \
+ /* Reset Vector Base Register to what PROM expects. */ \
+ movl #0,d0; \
+ movc d0,vbr; \
+ /* Jump to REQ_REBOOT */ \
+ jmp 0x1A4;
+
+ Lbootcode:
+ lea MAXADDR+0x800,sp | physical SP in case of NMI
+ #if defined(M68040)
+ cmpl #MMU_68040,_mmutype | 68040?
+ jne LmotommuF | no, skip
+ movl #0,d0
+ movc d0,cacr | caches off
+ .long 0x4e7b0003 | movc d0,tc
+ movl d2,MAXADDR+NBPG-4 | restore old high page contents
+ DOREBOOT
+ LmotommuF:
+ #endif
+ #if defined(M68K_MMU_MOTOROLA)
+ tstl _mmutype | HP MMU?
+ jeq LhpmmuB | yes, skip
+ movl #0,a0@ | value for pmove to TC (turn off MMU)
+ pmove a0@,tc | disable MMU
+ DOREBOOT
+ LhpmmuB:
+ #endif
+ #if defined(M68K_MMU_HP)
+ MMUADDR(a0)
+ movl #0xFFFF0000,a0@(MMUCMD) | totally disable MMU
+ movl d2,MAXADDR+NBPG-4 | restore old high page contents
+ DOREBOOT
+ #endif
+ Lebootcode:
+
+ #undef DOREBOOT
+
+ .data
+ .globl _machineid,_mmuid,_mmutype,_cputype,_ectype,_fputype
+ .globl _protorp,_prototc
+ _machineid:
+ .long HP_320 | default to 320
+ _mmuid:
+ .long 0 | default to ???
+ _mmutype:
+ .long MMU_HP | default to HP MMU
+ _cputype:
+ .long CPU_68020 | default to 68020 CPU
+ _ectype:
+ .long EC_NONE | external cache type, default to none
+ _fputype:
+ .long FPU_68881 | default to 68881 FPU
+ _protorp:
+ .long 0,0 | prototype root pointer
+ _prototc:
+ .long 0 | prototype translation control
+ .globl _internalhpib
+ _internalhpib:
+ .long 1 | has internal HP-IB, default to yes
+ .globl _cold
+ _cold:
+ .long 1 | cold start flag
+ .globl _want_resched
+ _want_resched:
+ .long 0
+ .globl _intiobase, _intiolimit, _extiobase, _CLKbase, _MMUbase
+ .globl _proc0paddr, _pagezero
+ _proc0paddr:
+ .long 0 | KVA of proc0 u-area
+ _intiobase:
+ .long 0 | KVA of base of internal IO space
+ _intiolimit:
+ .long 0 | KVA of end of internal IO space
+ _extiobase:
+ .long 0 | KVA of base of external IO space
+ _CLKbase:
+ .long 0 | KVA of base of clock registers
+ _MMUbase:
+ .long 0 | KVA of base of HP MMU registers
+ _pagezero:
+ .long 0 | PA of first page of kernel text
+ #ifdef USELEDS
+ heartbeat:
+ .long 0 | clock ticks since last pulse of heartbeat
+ beatstatus:
+ .long 0 | for determining a fast or slow throb
+ #endif
+ #ifdef DEBUG
+ .globl fulltflush, fullcflush
+ fulltflush:
+ .long 0
+ fullcflush:
+ .long 0
+ #endif
+ /* interrupt counters */
+ .globl _intrcnt,_eintrcnt,_intrnames,_eintrnames
+ _intrnames:
+ .asciz "spur"
+ .asciz "hil"
+ .asciz "lev2"
+ .asciz "lev3"
+ .asciz "lev4"
+ .asciz "lev5"
+ .asciz "clock"
+ .asciz "statclock"
+ .asciz "nmi"
+ _eintrnames:
+ .even
+ _intrcnt:
+ .long 0,0,0,0,0,0,0,0,0
+ _eintrcnt:
diff -crN /sys/arch/hp300/hp300/machdep.c hp300/machdep.c
*** /sys/arch/hp300/hp300/machdep.c Thu Apr 10 04:18:24 1997
--- hp300/machdep.c Wed Apr 23 20:12:11 1997
***************
*** 478,483 ****
--- 478,486 ----
case HP_340:
t = "340 (16.67MHz";
break;
+ case HP_345:
+ t = "345 (???MHz";
+ break;
case HP_350:
t = "350 (25MHz";
break;
***************
*** 493,498 ****
--- 496,507 ----
case HP_380:
t = "380/425 (25MHz";
break;
+ case HP_400:
+ t = "400 (50MHz";
+ break;
+ case HP_425:
+ t = "425 (25MHz";
+ break;
case HP_433:
t = "433 (33MHz";
break;
***************
*** 542,548 ****
}
strcat(cpu_model, ")");
printf("%s\n", cpu_model);
! printf("delay constant for this cpu: %d\n", delay_divisor);
/*
* Now that we have told the user what they have,
* let them know if that machine type isn't configured.
--- 551,558 ----
}
strcat(cpu_model, ")");
printf("%s\n", cpu_model);
! printf("delay constant for this cpu: %d MMU ID: %x\n",
! delay_divisor, mmuid);
/*
* Now that we have told the user what they have,
* let them know if that machine type isn't configured.
diff -crN /sys/arch/hp300/stand/Makefile.inc stand/Makefile.inc
*** /sys/arch/hp300/stand/Makefile.inc Tue Apr 15 04:17:55 1997
--- stand/Makefile.inc Thu Apr 24 01:26:11 1997
***************
*** 16,24 ****
COMMONSOURCE= srt0.o autoconf.c clock.c conf.c cons.c devopen.c \
machdep.c prf.c rawfs.c netio.c
! DRIVERSOURCE= ct.c dca.c dcm.c fhpib.c hil.c hpib.c if_le.c \
ite.c ite_dv.c ite_gb.c ite_rb.c ite_subr.c \
! ite_tc.c ite_hy.c nhpib.c rd.c scsi.c sd.c
### Figure out what to use for mkboot
MKBOOTDIR= ${.CURDIR}/../mkboot
--- 16,25 ----
COMMONSOURCE= srt0.o autoconf.c clock.c conf.c cons.c devopen.c \
machdep.c prf.c rawfs.c netio.c
! DRIVERSOURCE= ct.c dca.c dcm.c dnkbd.c fhpib.c hil.c hpib.c if_le.c \
ite.c ite_dv.c ite_gb.c ite_rb.c ite_subr.c \
! ite_tc.c ite_hy.c kbd.c kbdconf.c nhpib.c rd.c \
! scsi.c sd.c
### Figure out what to use for mkboot
MKBOOTDIR= ${.CURDIR}/../mkboot
diff -crN /sys/arch/hp300/stand/common/hil.c stand/common/hil.c
*** /sys/arch/hp300/stand/common/hil.c Tue Apr 15 04:17:55 1997
--- stand/common/hil.c Wed Apr 23 19:49:28 1997
***************
*** 185,191 ****
* The keyboard map table.
* Lookup is by hardware returned language code.
*/
! struct kbdmap hilkbd_map[] = {
KBD_US, NULL,
hil_us_keymap, hil_us_shiftmap, hil_us_ctrlmap, NULL, NULL,
--- 185,191 ----
* The keyboard map table.
* Lookup is by hardware returned language code.
*/
! struct hil_kbdmap hilkbd_map[] = {
KBD_US, NULL,
hil_us_keymap, hil_us_shiftmap, hil_us_ctrlmap, NULL, NULL,
***************
*** 246,252 ****
hilkbd_init()
{
struct hil_dev *hiladdr = HILADDR;
! struct kbdmap *km;
u_char lang;
/*
--- 246,252 ----
hilkbd_init()
{
struct hil_dev *hiladdr = HILADDR;
! struct hil_kbdmap *km;
u_char lang;
/*
>Release-Note:
>Audit-Trail:
Responsible-Changed-From-To: kern-bug-people->thorpej
Responsible-Changed-By: thorpej
Responsible-Changed-When: Fri Apr 25 17:14:15 PDT 1997
Responsible-Changed-Why:
hp300 port is my responsibility.
State-Changed-From-To: open->analyzed
State-Changed-By: thorpej
State-Changed-When: Fri Apr 25 17:15:04 PDT 1997
State-Changed-Why:
Needs some integration work, but is generally sane.
From: "Izumi Tsutsui" <tsutsui@netbsd.org>
To: gnats-bugs@gnats.NetBSD.org
Cc:
Subject: PR/3528 CVS commit: src/sys/arch/hp300
Date: Sat, 12 Feb 2011 15:49:02 +0000
Module Name: src
Committed By: tsutsui
Date: Sat Feb 12 15:49:02 UTC 2011
Modified Files:
src/sys/arch/hp300/conf: GENERIC files.hp300
Added Files:
src/sys/arch/hp300/dev: dnkbd.c dnkbdmap.c dnkbdmap.h
Log Message:
Pull Apollo Domain keyboard and mouse support from OpenBSD.
Untested (no hardware), but no bad sideeffect on 425t without Domain keyboard.
This is the last portion of "new hp300 kernel features" submitted in
PR port-hp300/3528 back in 1997, and I think finally we can close it.
To generate a diff of this commit:
cvs rdiff -u -r1.163 -r1.164 src/sys/arch/hp300/conf/GENERIC
cvs rdiff -u -r1.81 -r1.82 src/sys/arch/hp300/conf/files.hp300
cvs rdiff -u -r0 -r1.1 src/sys/arch/hp300/dev/dnkbd.c \
src/sys/arch/hp300/dev/dnkbdmap.c src/sys/arch/hp300/dev/dnkbdmap.h
Please note that diffs are not public domain; they are subject to the
copyright notices on the relevant files.
Responsible-Changed-From-To: thorpej->tsutsui
Responsible-Changed-By: tsutsui@NetBSD.org
Responsible-Changed-When: Sat, 05 Mar 2011 20:47:16 +0900
Responsible-Changed-Why:
as current maintainer
State-Changed-From-To: analyzed->closed
State-Changed-By: tsutsui@NetBSD.org
State-Changed-When: Sat, 05 Mar 2011 20:47:16 +0900
State-Changed-Why:
Finally NetBSD/hp300 kernel has all features including dnkbd.
>Unformatted:
(Contact us)
$NetBSD: query-full-pr,v 1.39 2013/11/01 18:47:49 spz Exp $
$NetBSD: gnats_config.sh,v 1.8 2006/05/07 09:23:38 tsutsui Exp $
Copyright © 1994-2007
The NetBSD Foundation, Inc. ALL RIGHTS RESERVED.