Subject: kern/3528: New hp300 kernel features
To: None <gnats-bugs@gnats.netbsd.org>
From: Mike <mike@pressed.spam.frisbee.net.au>
List: netbsd-bugs
Date: 04/24/1997 09:40:13
>Number: 3528
>Category: kern
>Synopsis: New hp300 kernel features
>Confidential: no
>Severity: non-critical
>Priority: medium
>Responsible: kern-bug-people (Kernel Bug People)
>State: open
>Class: change-request
>Submitter-Id: net
>Arrival-Date: Thu Apr 24 09:50:01 1997
>Last-Modified:
>Originator: Mike
>Organization:
Mike Smith Network Support
>Release: 1.2D ~20/4/97
>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;
/*
>Audit-Trail:
>Unformatted: