NetBSD Problem Report #3528

Received: (qmail-queue invoked from smtpd); 24 Apr 1997 16:35:58 -0000
Message-Id: <199704241640.JAA02037@pressed.spam.frisbee.net.au>
Date: Thu, 24 Apr 1997 09:40:13 -0700 (PDT)
From: Mike <mike@pressed.spam.frisbee.net.au>
Reply-To: miff@spam.frisbee.net.au
To: gnats-bugs@gnats.netbsd.org
Subject: New hp300 kernel features
X-Send-Pr-Version: 3.95

>Number:         3528
>Category:       port-hp300
>Synopsis:       New hp300 kernel features
>Confidential:   no
>Severity:       non-critical
>Priority:       medium
>Responsible:    tsutsui
>State:          closed
>Class:          change-request
>Submitter-Id:   net
>Arrival-Date:   Thu Apr 24 09:50:01 +0000 1997
>Closed-Date:    Sat Mar 05 11:47:16 +0000 2011
>Last-Modified:  Fri May 23 03:25:52 +0000 2014
>Originator:     Mike
>Release:        1.2D ~20/4/97
>Organization:
	Mike Smith Network Support
>Environment:
	HP9000/4xx
System: NetBSD pressed.spam.frisbee.net.au 1.2D NetBSD 1.2D (TEST) #4: Thu Apr 24 08:17:51 PDT 1997 mike@pressed.spam.frisbee.net.au:/remote6/hp300/playpen/sys/arch/hp300/compile/TEST hp300


>Description:
	New support for :
 - differentiating 345/375/400 (experimental) as well as 380/425.
 - Domain keyboards
 - Apollo serial ports on the 'frodo' chip
 - general 'frodo' support
>How-To-Repeat:
	Apply the following patch.
>Fix:


diff -crN /sys/arch/hp300/conf/TEST conf/TEST
*** /sys/arch/hp300/conf/TEST	Wed Dec 31 16:00:00 1969
--- conf/TEST	Thu Apr 24 09:15:59 1997
***************
*** 0 ****
--- 1,75 ----
+ 
+ # Include attributes common to all hp300s
+ include "arch/hp300/conf/std.hp300"
+ 
+ # Support for various CPU types
+ options 	HP380		# includes 425t, 425s, 433s
+ 
+ # Need to set locally
+ maxusers	32
+ 
+ # Standard system options
+ options 	COMPAT_43	# compatibility with 4.3BSD interfaces
+ options 	COMPAT_44	# compatibility with 4.4BSD binaries
+ options 	NKMEMCLUSTERS=1024	# 4K pages in kernel malloc pool
+ options 	LKM		# Loadable kernel modules
+ 
+ # Filesystems
+ file-system 	FFS		# fast filesystem
+ file-system 	NFS		# Network filesystem client
+ file-system 	UNION		# Union filesystem (req. for FDESC)
+ file-system 	KERNFS		# kernel data-structure filesystem
+ file-system 	FDESC		# user file descriptor filesystem
+ file-system 	PROCFS		# /proc filesystem
+ file-system 	MFS		# Memory-based filesystem
+ 
+ # Filesystem options
+ options 	FIFO		# POSIX fifo support (in all filesystems)
+ 
+ # Networking options
+ options 	INET		# Internet protocols
+ options  	TCP_COMPAT_42	# compatibility with 4.2BSD TCP/IP
+ 
+ # Options for HP hardware
+ options 	FPSP		# floating point interface for 68040
+ options 	USELEDS		# make the lights twinkle
+ options 	COMPAT_NOLABEL	# defaults for unlabeled disks
+ 
+ options 	COMPAT_M68K4K	# compat. with NetBSD/m68k4k binaries
+ 
+ # Debugging options
+ options 	DDB		# Kernel Dynamic Debugger
+ 
+ config		netbsd root on ? type ?
+ 
+ mainbus0	at root		# root "bus"
+ 
+ intio0		at mainbus0	# internal i/o space
+ dio0		at mainbus0	# DIO/DIO-II bus
+ 
+ frodo0		at intio0
+ dnkbd0		at frodo0 channel 0
+ apci0		at frodo0 channel 1
+ apci1		at frodo0 channel 2
+ apci2		at frodo0 channel 3
+ 
+ # Hyperion framebuffer
+ hyper*		at dio? scode ?
+ 
+ # Framebuffer abstraction
+ grf*		at hyper?
+ 
+ # Internal Terminal Emulator
+ ite*		at grf?
+ 
+ dca0		at dio? scode 9	flags 1	  # DCA serial interfaces
+ 
+ le*		at dio? scode ?		# LANCE ethernet interfaces
+ 
+ oscsi*		at dio? scode ?		# SCSI
+ sd*		at oscsi? target ? lun? # disk
+ 
+ pseudo-device	pty		64	# pseudo ptys
+ pseudo-device	bpfilter	16	# Berkeley packet filter
+ pseudo-device	loop			# loopback network interface
+ pseudo-device	ccd		2
diff -crN /sys/arch/hp300/conf/files.hp300 conf/files.hp300
*** /sys/arch/hp300/conf/files.hp300	Mon Apr 14 04:24:54 1997
--- conf/files.hp300	Wed Apr 23 22:35:20 1997
***************
*** 153,158 ****
--- 153,178 ----
  file	arch/hp300/dev/hil.c
  file	arch/hp300/dev/hil_keymaps.c

+ # Automatic keyboard configuration
+ file	arch/hp300/dev/kbdconf.c
+ 
+ #
+ # Apollo utility chip ('frodo')
+ #
+ device frodo { channel = -1 }
+ attach frodo at intio
+ file	arch/hp300/dev/frodo.c		frodo
+ 
+ # Domain keyboard
+ device	dnkbd: tty
+ attach	dnkbd at frodo
+ file	arch/hp300/dev/dnkbd.c		dnkbd needs-flag
+ 
+ # Apollo serial ports
+ device	apci: tty
+ attach	apci at frodo
+ file	arch/hp300/dev/apci.c		apci needs-flag
+ 
  #
  # Non-device files
  #
diff -crN /sys/arch/hp300/dev/apci.c dev/apci.c
*** /sys/arch/hp300/dev/apci.c	Wed Dec 31 16:00:00 1969
--- dev/apci.c	Thu Apr 24 08:23:28 1997
***************
*** 0 ****
--- 1,728 ----
+ /*	$NetBSD$ */
+ 
+ /*
+  * Copyright (c) 1997 Michael Smith.  All rights reserved.
+  *
+  * Redistribution and use in source and binary forms, with or without
+  * modification, are permitted provided that the following conditions
+  * are met:
+  * 1. Redistributions of source code must retain the above copyright
+  *    notice, this list of conditions and the following disclaimer.
+  * 2. Redistributions in binary form must reproduce the above copyright
+  *    notice, this list of conditions and the following disclaimer in the
+  *    documentation and/or other materials provided with the distribution.
+  *
+  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+  * SUCH DAMAGE.
+  *
+  */
+ 
+ /*
+  * Driver for the 8250-like UARTs in the "Apollo Utility" chip (frodo)
+  * found in HP9000/4xx series workstations.
+  *
+  * Draws a lot of code from the dca driver, which handles similar hardware.
+  */
+ 
+ #include <sys/param.h>
+ #include <sys/systm.h>
+ #include <sys/ioctl.h>
+ #include <sys/proc.h>
+ #include <sys/tty.h>
+ #include <sys/conf.h>
+ #include <sys/file.h>
+ #include <sys/uio.h>
+ #include <sys/kernel.h>
+ #include <sys/syslog.h>
+ #include <sys/device.h>
+ 
+ #include <machine/autoconf.h>
+ #include <machine/cpu.h>
+ 
+ #include <dev/cons.h>
+ 
+ #include "dca.h"				/* for NDCA */
+ 
+ #include <hp300/dev/frodovar.h>
+ #include <hp300/dev/frodoreg.h>
+ #include <hp300/dev/dcareg.h>			/* for the register bit defines */
+ #include <hp300/dev/apcireg.h>
+ 
+ /* #define APCI_DEBUG */
+ 
+ #ifdef APCI_DEBUG
+ #define D(x)	x
+ #else
+ #define D(x)
+ #endif
+ 
+ struct apci_softc
+ {
+     struct device	sc_dev;			/* device housekeeping */
+     struct apciregs	*sc_apci;		/* pointer to hardware */
+     int			sc_unit;		/* unit number */
+     struct tty		*sc_tty;
+     int			sc_ferr, sc_perr, sc_oflow, sc_toterr;
+     short		sc_flags;
+     
+ #define APCI_ACTIVE	(1<<0)			/* unit is valid */
+ #define APCI_OPEN	(1<<1)			/* unit is open */
+ #define APCI_FLOWCTRL	(1<<2)			/* unit has hardware flow control */
+ };
+     
+ static int	apcimatch(struct device *parent, struct cfdata *match, void *aux);
+ static void	apciattach(struct device *parent, struct device *self, void *aux);
+ static int 	apciintr(void *arg);
+ static void	apcieint(struct apci_softc *sc, int stat);
+ static void	apcimint(struct apci_softc *sc, u_char stat);
+ static int	apciparam(register struct tty *tp, register struct termios *t);
+ static void	apcistart(register struct tty *tp);
+ static int	apcimctl(struct apci_softc *sc, int bits, int how);
+ static void	apciinit(struct apciregs *apci, int rate);
+ static void	apcitimeout(void *scp);
+ 
+ static int apcidefaultrate = TTYDEF_SPEED;
+ 
+ struct speedtab apcispeedtab[] = {
+         {	0,      0		},
+ 	{	50,     APCIBRD(50)	},
+         {	75,     APCIBRD(75)	},
+         {	110,    APCIBRD(110)	},
+         {	134,    APCIBRD(134)	},
+         {	150,    APCIBRD(150)	},
+         {	200,    APCIBRD(200)	},
+         {	300,    APCIBRD(300)	},
+         {	600,    APCIBRD(600)	},
+         {	1200,   APCIBRD(1200)	},
+         {	1800,   APCIBRD(1800)	},
+         {	2400,   APCIBRD(2400)	},
+         {	4800,   APCIBRD(4800)	},
+         {	9600,   APCIBRD(9600)	},
+         {	19200,  APCIBRD(19200)	},
+         {	38400,  APCIBRD(38400)	},
+         {	-1,     -1		}
+ };
+ 
+ 
+ struct cfattach apci_ca = {
+     sizeof(struct apci_softc), apcimatch, apciattach
+ };
+ 
+ struct cfdriver apci_cd = {
+     NULL, "apci", DV_TTY
+ };
+ 
+ cdev_decl(apci);
+ 
+ /* nothing magic here */
+ #define APCIUNIT(x)	minor(x)
+ 
+ static int
+ apcimatch(struct device *parent, struct cfdata *match, void *aux)
+ {
+     struct frodo_attach_args	*fa = aux;
+ 
+     /* check unit # */
+     if (match->cf_unit >= APCI_MAXPORT) {
+ 	return(0);
+     }
+     /* XXX This is Not the right way to go about this */
+ #if NDCA > 0
+     if (fa->fa_channel == 1) {
+ 	D(printf("apci%d: disabled due to conflict with dca0\n", match->cf_unit));
+ 	return(0);
+     }
+ #endif
+     return(1);
+ }
+ 
+ static void
+ apciattach(struct device *parent, struct device *self, void *aux)
+ {
+     struct apci_softc		*sc = (struct apci_softc *)self;
+     struct frodo_attach_args	*fa = aux;
+ 
+     /* base address for registers (space is already mapped) */
+     sc->sc_apci = (struct apciregs *)FRODO_STOV(fa->fa_channel);
+     sc->sc_unit = self->dv_unit;
+     sc->sc_flags = APCI_ACTIVE;
+ 
+     /* register our interrupt handler */
+     frodo_intr_establish(parent, apciintr, sc, APCI_INTR0 + fa->fa_channel);
+ 
+     /* per-unit special processing (note switch on channel not unit number) */
+     switch (fa->fa_channel) {
+     case 1:			/* console port in apollo mode */
+     case 2:
+     case 3:
+ 	sc->sc_flags |= APCI_FLOWCTRL;
+ 	break;
+     default:
+     }
+     
+     printf(": 8250-like UART\n");
+ }
+ 
+ int
+ apciopen(dev_t dev, int flag, int mode, struct proc *p)
+ {
+     int 		unit = APCIUNIT(dev);
+     struct apci_softc	*sc;
+     struct tty 		*tp;
+     struct apciregs	*apci;
+     u_char 		code;
+     int 		s, error = 0;
+     
+     if ((unit >= apci_cd.cd_ndevs)		||
+ 	((sc = apci_cd.cd_devs[unit]) == NULL)	||
+ 	!(sc->sc_flags & APCI_ACTIVE))
+ 	return(ENXIO);				/* nup, not happy */
+ 
+     D(printf("%s: open\n", sc->sc_dev.dv_xname, unit));
+ 
+     apci = sc->sc_apci;
+     if (sc->sc_tty == NULL) {
+ 	tp = sc->sc_tty = ttymalloc();
+ 	tty_attach(tp);
+     } else {
+ 	tp = sc->sc_tty;
+     }
+     tp->t_oproc = apcistart;
+     tp->t_param = apciparam;
+     tp->t_dev = dev;
+     
+     if ((tp->t_state & TS_ISOPEN) == 0) {
+ 	/*
+ 	 * Sanity clause: reset the card on first open.
+ 	 * The card might be left in an inconsistent state
+ 	 * if card memory is read inadvertently.
+ 	 */
+ 	apciinit(apci, apcidefaultrate);
+ 
+ 	tp->t_state |= TS_WOPEN;
+ 	ttychars(tp);
+ 	tp->t_iflag = TTYDEF_IFLAG;
+ 	tp->t_oflag = TTYDEF_OFLAG;
+ 	tp->t_cflag = TTYDEF_CFLAG;
+ 	tp->t_lflag = TTYDEF_LFLAG;
+ 	tp->t_ispeed = tp->t_ospeed = apcidefaultrate;
+ 
+ 	s = spltty();
+ 
+ 	apciparam(tp, &tp->t_termios);
+ 	ttsetwater(tp);
+ 
+ 	/* Flush any pending I/O */
+ 	while ((apci->ap_iir & IIR_IMASK) == IIR_RXRDY)
+ 	    code = apci->ap_data;
+     } else if (tp->t_state&TS_XCLUDE && p->p_ucred->cr_uid != 0)
+ 	return (EBUSY);
+     else
+ 	s = spltty();
+ 
+     /* if port has flow control */ 
+     if (sc->sc_flags & APCI_FLOWCTRL) {
+ 	/* Set modem control state  */
+ 	(void)apcimctl(sc, MCR_DTR | MCR_RTS, DMSET);
+ 	/* Wait for carrier if necessary. */
+ 	if ((flag & O_NONBLOCK) == 0)	
+ 	    while ((tp->t_cflag & CLOCAL) == 0 &&
+ 		   (tp->t_state & TS_CARR_ON) == 0) {
+ 		tp->t_state |= TS_WOPEN; 
+ 		error = ttysleep(tp, (caddr_t)&tp->t_rawq,
+ 				 TTIPRI | PCATCH, ttopen, 0);
+ 		if (error) {
+ 		    splx(s);
+ 		    D(printf("\n"));
+ 		    return (error);
+ 		}
+ 	    }
+     } else {
+ 	/* fake carrier */
+ 	tp->t_state |= TS_CARR_ON;
+     }
+     
+     splx(s);
+ 
+     if (error == 0)
+ 	error = (*linesw[tp->t_line].l_open)(dev, tp);
+ 
+     if (error == 0)
+ 	sc->sc_flags |= APCI_OPEN;
+ 
+     /* clear errors, start timeout */
+     sc->sc_ferr = sc->sc_perr = sc->sc_oflow = sc->sc_toterr = 0;
+     timeout(apcitimeout, sc, hz);
+     return(error);
+ }
+ 
+ int
+ apciclose(dev_t dev, int flag, int mode, struct proc *p)
+ {
+     int			unit = APCIUNIT(dev);
+     struct apci_softc	*sc = apci_cd.cd_devs[unit];
+     struct tty		*tp = sc->sc_tty;
+     struct apciregs	*apci = sc->sc_apci;
+     int			s;
+     
+     D(printf("%s: close\n", sc->sc_dev.dv_xname, unit));
+     
+     (*linesw[tp->t_line].l_close)(tp, flag);
+ 
+     s = spltty();
+ 
+     apci->ap_cfcr &= ~CFCR_SBREAK;
+     apci->ap_ier = 0;
+     if (tp->t_cflag & HUPCL) {
+ 	/* XXX perhaps only clear DTR */
+ 	(void)apcimctl(sc, 0, DMSET);
+     }
+     tp->t_state &= ~(TS_BUSY | TS_FLUSH);
+     splx(s);
+     ttyclose(tp);
+     sc->sc_flags &= ~APCI_OPEN;
+     return (0);
+ }
+ 
+ int
+ apciread(dev_t dev, struct uio *uio, int flag)
+ {
+     int			unit = APCIUNIT(dev);
+     struct apci_softc	*sc = apci_cd.cd_devs[unit];
+     struct tty		*tp = sc->sc_tty;
+     int			error;
+ 
+     D(printf("%s: read", sc->sc_dev.dv_xname, unit));
+ 
+     error = (*linesw[tp->t_line].l_read)(tp, uio, flag);
+     D(printf(" returns %d\n", error));
+     return (error);
+ }
+ 
+ int
+ apciwrite(dev_t dev, struct uio *uio, int flag)
+ {
+     struct apci_softc	*sc = apci_cd.cd_devs[APCIUNIT(dev)];
+     struct tty		*tp = sc->sc_tty;
+     
+     return((*linesw[tp->t_line].l_write)(tp, uio, flag));
+ }
+ 
+ static int 
+ apciintr(void *arg)
+ {	
+     struct apci_softc		*sc = arg;
+     register struct apciregs	*apci = sc->sc_apci;
+     register struct tty		*tp = sc->sc_tty;
+     register u_char		iir, c;
+     int				iflowdone = 0;
+     int				worked = 0;    
+ 
+     D(printf("%s: interrupt", sc->sc_dev.dv_xname, sc->sc_unit));
+ 
+     for (;;) {
+ 	iir = apci->ap_iir;	/* get UART status */
+ 	D(printf(" iir %x", iir));
+ 
+ 	switch (iir & IIR_IMASK) {
+ 
+ 	case IIR_RLS:
+ 	    D(printf(" rls"));
+ 	    apcieint(sc, apci->ap_lsr);
+ 	    break;
+ 
+ 	case IIR_RXRDY:
+ 	case IIR_RXTOUT:	/* should unroll somewhat for speed/FIFO here */
+ 	    c = apci->ap_data;
+ 	    D(printf(" rxrdy %x", c));
+ 	    
+ 	    if ((tp->t_state & TS_ISOPEN) != 0)
+ 		(*linesw[tp->t_line].l_rint)(c, tp);
+ 	    if (!iflowdone && (tp->t_cflag&CRTS_IFLOW) &&
+ 		tp->t_rawq.c_cc > TTYHOG/2) {
+ 		apci->ap_mcr &= ~MCR_RTS;
+ 		iflowdone = 1;
+ 	    }
+ 	    break;
+ 
+ 	case IIR_TXRDY:
+ 	    D(printf(" txrdy"));
+ 	    tp->t_state &=~ (TS_BUSY|TS_FLUSH);
+ 	    if (tp->t_line)
+ 		(*linesw[tp->t_line].l_start)(tp);
+ 	    else
+ 		apcistart(tp);
+ 	    break;
+ 
+ 	default:
+ 	    if (iir & IIR_NOPEND) {		/* nothing actually pending */
+ 		D(printf(" done\n"));
+ 		return (worked);
+ 	    }
+ 	    log(LOG_WARNING, "%s: weird interrupt: 0x%x\n", sc->sc_dev.dv_xname, iir);
+ 	    /* fall through */
+ 	case IIR_MLSC:
+ 	    D(printf(" mlsc"));
+ 	    apcimint(sc, apci->ap_msr);
+ 	    break;
+ 	}
+ 	worked = 1;
+     }
+ }
+ 
+ static void
+ apcieint(struct apci_softc *sc, int stat)
+ {
+     struct tty		*tp = sc->sc_tty;
+     struct apciregs	*apci = sc->sc_apci;
+     int			c;
+ 
+     c = apci->ap_data;				/* get received character (if any) */
+     D(printf(" %x,%x", stat, c));
+     
+     if ((tp->t_state & TS_ISOPEN) == 0) {
+ 	return;
+     }
+     if (stat & (LSR_BI | LSR_FE)) {
+ 	c |= TTY_FE;
+ 	sc->sc_ferr++;
+     } else if (stat & LSR_PE) {
+ 	c |= TTY_PE;
+ 	sc->sc_perr++;
+     } else if (stat & LSR_OE) {
+ 	sc->sc_oflow++;
+     }
+     (*linesw[tp->t_line].l_rint)(c, tp);
+ }
+ 
+ static void
+ apcimint(struct apci_softc *sc, u_char stat)
+ {
+     struct tty		*tp = sc->sc_tty;
+     struct apciregs	*apci = sc->sc_apci;
+ 
+     D(printf(" msr %x", stat));
+ 
+     if (stat & MSR_DDCD)
+ 	if (stat & MSR_DCD)
+ 	    (void)(*linesw[tp->t_line].l_modem)(tp, 1);
+ 	else if ((*linesw[tp->t_line].l_modem)(tp, 0) == 0)
+ 	    apci->ap_mcr &= ~(MCR_DTR | MCR_RTS);
+     
+     /*
+      * CTS change.
+      * If doing HW output flow control start/stop output as appropriate.
+      */
+     if ((stat & MSR_DCTS) &&
+ 	(tp->t_state & TS_ISOPEN) && (tp->t_cflag & CCTS_OFLOW)) {
+ 	if (stat & MSR_CTS) {
+ 	    tp->t_state &=~ TS_TTSTOP;
+ 	    apcistart(tp);
+ 	} else {
+ 	    tp->t_state |= TS_TTSTOP;
+ 	}
+     }
+ }
+ 
+ 
+ struct tty *
+ apcitty(dev_t dev)
+ {
+     struct apci_softc	*sc = apci_cd.cd_devs[APCIUNIT(dev)];
+     
+     return(sc->sc_tty);
+ }
+ 
+ int
+ apciioctl(dev_t dev, u_long cmd, caddr_t data, int flag, struct proc *p)
+ {
+     int			unit = APCIUNIT(dev);
+     struct apci_softc	*sc = apci_cd.cd_devs[unit];
+     struct tty		*tp = sc->sc_tty;
+     struct apciregs	*apci = sc->sc_apci;
+     int			error;
+     
+     /* handle discipline and tty ioctls first */
+     error = (*linesw[tp->t_line].l_ioctl)(tp, cmd, data, flag, p);
+     if (error >= 0)
+ 	return(error);
+     error = ttioctl(tp, cmd, data, flag, p);
+     if (error >= 0)
+ 	return(error);
+ 
+     /* ok, so maybe it's for us */
+ 
+     switch (cmd) {
+     case TIOCSBRK:
+ 	apci->ap_cfcr |= CFCR_SBREAK;
+ 	break;
+ 	
+     case TIOCCBRK:
+ 	apci->ap_cfcr &= ~CFCR_SBREAK;
+ 	break;
+ 	
+     case TIOCSDTR:
+ 	(void) apcimctl(sc, MCR_DTR | MCR_RTS, DMBIS);
+ 	break;
+ 	
+     case TIOCCDTR:
+ 	(void) apcimctl(sc, MCR_DTR | MCR_RTS, DMBIC);
+ 	break;
+ 
+     case TIOCMSET:
+ 	(void) apcimctl(sc, *(int *)data, DMSET);
+ 	break;
+ 
+     case TIOCMBIS:
+ 	(void) apcimctl(sc, *(int *)data, DMBIS);
+ 	break;
+ 
+     case TIOCMBIC:
+ 	(void) apcimctl(sc, *(int *)data, DMBIC);
+ 	break;
+ 
+     case TIOCMGET:
+ 	*(int *)data = apcimctl(sc, 0, DMGET);
+ 	break;
+ 
+     case TIOCGFLAGS: {
+ 	int bits = 0;
+ 
+ 	if (tp->t_cflag & CLOCAL)
+ 	    bits |= TIOCFLAG_CLOCAL;
+ 
+ 	*(int *)data = bits;
+ 	break;
+     }
+ 
+     case TIOCSFLAGS: {
+ 	int userbits;
+ 
+ 	error = suser(p->p_ucred, &p->p_acflag);
+ 	if (error)
+ 	    return (EPERM);
+ 	
+ 	userbits = *(int *)data;
+ 	
+ 	if (userbits & TIOCFLAG_CLOCAL)
+ 	    tp->t_cflag |= CLOCAL;
+ 	
+ 	break;
+     }
+     
+     default:
+ 	return(ENOTTY);
+     }
+     return(0);
+ }
+ 
+ static int
+ apciparam(register struct tty *tp, register struct termios *t)
+ {
+     int			unit = APCIUNIT(tp->t_dev);
+     struct apci_softc	*sc = apci_cd.cd_devs[unit];
+     struct apciregs	*apci = sc->sc_apci;
+     int			cfcr, cflag = t->c_cflag;
+     int			ospeed = ttspeedtab(t->c_ospeed, apcispeedtab);
+     int			s;
+  
+     /* check requested parameters */
+     if (ospeed < 0 || (t->c_ispeed && t->c_ispeed != t->c_ospeed))
+ 	return (EINVAL);
+ 
+     switch (cflag & CSIZE) {
+     case CS5:
+ 	cfcr = CFCR_5BITS;
+ 	break;
+ 
+     case CS6:
+ 	cfcr = CFCR_6BITS;
+ 	break;
+ 
+     case CS7:
+ 	cfcr = CFCR_7BITS;
+ 	break;
+ 
+     case CS8:
+ 	cfcr = CFCR_8BITS;
+ 	break;
+     }
+     if (cflag & PARENB) {
+ 	cfcr |= CFCR_PENAB;
+ 	if ((cflag & PARODD) == 0)
+ 	    cfcr |= CFCR_PEVEN;
+     }
+     if (cflag & CSTOPB)
+ 	cfcr |= CFCR_STOPB;
+ 
+     s = spltty();
+ 
+     if (ospeed == 0)
+ 	(void) apcimctl(sc, 0, DMSET);	/* hang up line */
+ 
+ #if 0
+     if (ospeed != 0) {			/* open divisor latch, set speed */
+ 	apci->ap_cfcr |= CFCR_DLAB;
+ 	apci->ap_data = ospeed & 0xFF;
+ 	apci->ap_ier = ospeed >> 8;
+     }
+     apci->ap_cfcr = cfcr;		/* set cfcr, close latch if open */
+ #endif
+     
+     /* and copy to tty */
+     tp->t_ispeed = t->c_ispeed;
+     tp->t_ospeed = t->c_ospeed;
+     tp->t_cflag = cflag;
+ 
+     /* set interrupt enables; frodo is already expecting us */
+     apci->ap_ier = IER_ERXRDY | IER_ETXRDY | IER_ERLS | IER_EMSC;
+ 
+     splx(s);
+     return (0);
+ }
+ 
+ static void
+ apcistart(register struct tty *tp)
+ {
+     int			s, unit = APCIUNIT(tp->t_dev);
+     struct apci_softc	*sc = apci_cd.cd_devs[unit];
+     struct apciregs	*apci = sc->sc_apci;
+ 
+     s = spltty();
+ 
+     if (tp->t_state & (TS_TIMEOUT|TS_TTSTOP))
+ 	goto out;
+     if (tp->t_outq.c_cc <= tp->t_lowat) {
+ 	if (tp->t_state & TS_ASLEEP) {
+ 	    tp->t_state &= ~TS_ASLEEP;
+ 	    wakeup((caddr_t)&tp->t_outq);
+ 	}
+ 	if (tp->t_outq.c_cc == 0)
+ 	    goto out;
+ 	selwakeup(&tp->t_wsel);
+     }
+     if (apci->ap_lsr & LSR_TXRDY) {
+ 	tp->t_state |= TS_BUSY;
+ 	apci->ap_data = getc(&tp->t_outq); 
+     }
+ out:
+     splx(s);
+ }
+ 
+ 
+ /*
+  * stop output on a line
+  */
+ void
+ apcistop(register struct tty *tp, int flag)
+ {
+     register int s;
+ 
+     s = spltty();
+     /* if busy and not already stopped */
+     if ((tp->t_state & TS_BUSY) && !(tp->t_state & TS_TTSTOP))
+ 	tp->t_state |= TS_FLUSH;
+     splx(s);
+ }
+ 
+ static int
+ apcimctl(struct apci_softc *sc, int bits, int how)
+ {
+     struct apciregs *apci = sc->sc_apci;
+     int s;
+ 
+     return(0);
+     
+     /*
+      * Always make sure MCR_IEN is set (unless setting to 0)
+      */
+     if (how == DMBIS || (how == DMSET && bits))
+ 	bits |= MCR_IEN;
+     else if (how == DMBIC)
+ 	bits &= ~MCR_IEN;
+     s = spltty();
+ 
+     switch (how) {
+     case DMSET:
+ 	apci->ap_mcr = bits;
+ 	break;
+ 
+     case DMBIS:
+ 	apci->ap_mcr |= bits;
+ 	break;
+ 
+     case DMBIC:
+ 	apci->ap_mcr &= ~bits;
+ 	break;
+ 
+     case DMGET:
+ 	bits = apci->ap_msr;
+ 	break;
+     }
+     (void) splx(s);
+     return(bits);
+ }
+ 
+ static void
+ apciinit(struct apciregs *apci, int rate)
+ {
+     int		s;
+     short	stat;
+ 
+     s = spltty();
+ 
+     rate = ttspeedtab(rate, apcispeedtab);
+ #if 0
+     apci->ap_cfcr = CFCR_DLAB;
+     /* get old divisor */
+     orate = ((int)apci->ap_ier << 8) + apci->ap_data;
+     D(printf("apciinit: old divisor %d\n", orate));
+     apci->ap_data = rate & 0xFF;
+     apci->ap_ier  = rate >> 8;
+     apci->ap_cfcr = CFCR_8BITS;
+ #endif
+     apci->ap_ier  = IER_ERXRDY | IER_ETXRDY;
+     /* do this like HP seems to */
+     apci->ap_fifo = FIFO_ENABLE | FIFO_XMT_RST; 
+     apci->ap_fifo = FIFO_ENABLE | FIFO_RCV_RST;
+     apci->ap_mcr  = MCR_DTR | MCR_RTS;
+     DELAY(100);
+     stat = apci->ap_iir;
+     splx(s);
+ }
+ 
+ static void
+ apcitimeout(void *scp)
+ {
+     struct apci_softc	*sc = scp;
+     int			ferr, perr, oflow;
+     int			s;
+     
+     if (!(sc->sc_flags & APCI_OPEN))
+ 	return;				/* port closed */
+     
+     /* errors? */
+     if (sc->sc_ferr || sc->sc_perr || sc->sc_oflow) {
+ 	s = spltty();			/* disable interrupts for as short as possible */
+ 	ferr = sc->sc_ferr;
+ 	perr = sc->sc_perr;
+ 	oflow = sc->sc_oflow;
+ 	sc->sc_ferr = sc->sc_perr = sc->sc_oflow = 0;
+ 	splx(s);
+ 	sc->sc_toterr += ferr + perr + oflow;
+ 	printf("%s: errors  %d frame  %d parity  %d overflow  %d total",
+ 	        sc->sc_dev.dv_xname, ferr, perr, oflow, sc->sc_toterr);
+     }
+     
+     timeout(apcitimeout, sc, hz);
+ }
+ 
diff -crN /sys/arch/hp300/dev/apcireg.h dev/apcireg.h
*** /sys/arch/hp300/dev/apcireg.h	Tue Apr 15 04:17:50 1997
--- dev/apcireg.h	Thu Apr 24 07:36:20 1997
***************
*** 1,4 ****
! /*	$NetBSD: apcireg.h,v 1.1 1997/04/14 20:36:11 thorpej Exp $	*/

  /*
   * Copyright (c) 1997 Michael Smith.  All rights reserved.
--- 1,4 ----
! /*	$NetBSD$ */

  /*
   * Copyright (c) 1997 Michael Smith.  All rights reserved.
***************
*** 23,56 ****
   * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
   * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   * SUCH DAMAGE.
   */

  #include <hp300/dev/iotypes.h>

! struct apciregs {
! 	vu_char		ap_data;
! 	u_char		pad0[3];
! 	vu_char		ap_ier;
! 	u_char		pad1[3];
! 	vu_char		ap_iir;
! #define	ap_fifo	ap_iir
! 	u_char		pad2[3];
! 	vu_char		ap_cfcr;
! 	u_char		pad3[3];
! 	vu_char		ap_mcr;
! 	u_char		pad4[3];
! 	vu_char		ap_lsr;
! 	u_char		pad5[3];
! 	vu_char		ap_msr;
! 	u_char		pad6[3];
! 	vu_char		ap_scratch;
  };

  /* max number of apci ports */
! #define	APCI_MAXPORT	4

! /* Frodo interrupt number of lowest apci port */
! #define	APCI_INTR0	12

  /*
   * baudrate divisor calculations.
--- 23,59 ----
   * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
   * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   * SUCH DAMAGE.
+  *
   */

  #include <hp300/dev/iotypes.h>

! /* 8250-like UART on a 32-bit bus */
! struct apciregs
! {
!     vu_char	ap_data;
!     u_char	pad0[3];
!     vu_char	ap_ier;
!     u_char	pad1[3];
!     vu_char	ap_iir;
! #define ap_fifo ap_iir
!     u_char	pad2[3];
!     vu_char	ap_cfcr;
!     u_char	pad3[3];
!     vu_char	ap_mcr;
!     u_char	pad4[3];
!     vu_char	ap_lsr;
!     u_char	pad5[3];
!     vu_char	ap_msr;
!     u_char	pad6[3];
!     vu_char	ap_scratch;
  };

  /* max number of apci ports */
! #define APCI_MAXPORT	4

! /* frodo interrupt number of lowest apci port */
! #define APCI_INTR0	12

  /*
   * baudrate divisor calculations.
***************
*** 59,62 ****
   * factor of 500400.  (Using exactly 8MHz gives framing errors with
   * the Apollo keyboard.)
   */
! #define	APCIBRD(x)	(500000 / (x))
--- 62,67 ----
   * factor of 500400.  (Using exactly 8MHz gives framing errors with
   * the Apollo keyboard.)
   */
! #define APCIBRD(x)	(500400 / (x))
! 
! 
diff -crN /sys/arch/hp300/dev/dnkbd.c dev/dnkbd.c
*** /sys/arch/hp300/dev/dnkbd.c	Wed Dec 31 16:00:00 1969
--- dev/dnkbd.c	Thu Apr 24 08:35:57 1997
***************
*** 0 ****
--- 1,704 ----
+ /*	$NetBSD$ */
+ 
+ /*
+  * Copyright (c) 1997 Michael Smith.  All rights reserved.
+  *
+  * Redistribution and use in source and binary forms, with or without
+  * modification, are permitted provided that the following conditions
+  * are met:
+  * 1. Redistributions of source code must retain the above copyright
+  *    notice, this list of conditions and the following disclaimer.
+  * 2. Redistributions in binary form must reproduce the above copyright
+  *    notice, this list of conditions and the following disclaimer in the
+  *    documentation and/or other materials provided with the distribution.
+  *
+  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+  * SUCH DAMAGE.
+  *
+  */
+ 
+ /*
+  * Driver for an Apollo keyboard on an 8250-like UART in the "Apollo Utility" 
+  * chip (frodo) found in HP9000/4xx series workstations.
+  *
+  * Serial comms is a cut-down subset of that in the apci driver, with the
+  * tty-related stuff removed.
+  *
+  * Random notes on the Apollo keyboard :
+  *
+  * - Powers up in 'cooked' mode, where the alpha keys generate ascii rather
+  *   than make/break codes.  Other keys seem to behave OK though.
+  *
+  * - Alt L/R keys generate two-byte sequence :
+  *             make     break
+  *       L    0xfe,2   0xfe,3
+  *       R    0xfe,0   0xfe,1
+  *
+  * - Mouse activity shows up inline in 4-byte packets introduced with 0xdf.
+  *   Byte 1 is   1MRL0000    where M, R, L are the mouse buttons, and 0 is
+  *                           down, 1 is up.
+  *   Byte 2 is 2's complement X movement, +ve to the right.
+  *   Byte 3 is 2's complement Y movement, +ve is up.
+  *
+  * - Keyboard recognises commands sent to it, all preceded by 0xff.  Commands
+  *   are echoed once sent completely.
+  *
+  *   0x00	go to cooked mode.
+  *   0x01	go to 'raw' (scancode) mode.
+  *   0x12,0x21	status report as <id1>\r<id2>\r<model>\r followed by 0xff 
+  *		and then the cooked/raw status.
+  *   0x21,0x81	beep on		XXX beep commands are wrong?
+  *   0x21,0x82	beep off
+  *
+  * Some version examples :
+  *
+  * <3-@> <1-0> <SD-03687-MS>	Apollo p/n 007121 REV 00 ('old-style' US layout)
+  * <3-@> <2-0> <SD-03683-MS>	Apollo p/n 007121 REV 01 ('old-style' US layout)
+  * <3-@> <2-0> <SD-03980-MS>	Apollo 3500? keyboard.
+  * <3-@> <X-X> <RX-60857-HW>	HP p/n A1630-82001 R2 ('new-style' off 425t, US layout),
+  *				also Apollo p/n 014555-002 ('new-style' off DN5500, US layout).
+  * So, what's the country code?
+  *
+  */
+ 
+ #include <sys/param.h>
+ #include <sys/systm.h>
+ #include <sys/ioctl.h>
+ #include <sys/proc.h>
+ #include <sys/conf.h>
+ #include <sys/file.h>
+ #include <sys/uio.h>
+ #include <sys/kernel.h>
+ #include <sys/syslog.h>
+ #include <sys/device.h>
+ #include <sys/malloc.h>
+ 
+ #include <machine/autoconf.h>
+ #include <machine/cpu.h>
+ 
+ #include <dev/cons.h>
+ 
+ #include <hp300/hp300/led.h>
+ 
+ #include "dnkbd.h"			/* for NDNKBD */
+ #include "ite.h"			/* for NITE */
+ 
+ #include <hp300/dev/frodovar.h>
+ #include <hp300/dev/frodoreg.h>
+ #include <hp300/dev/dcareg.h>		/* for the register bit defines */
+ #include <hp300/dev/apcireg.h>
+ #include <hp300/dev/itevar.h>
+ #include <hp300/dev/kbdvar.h>
+ #include <hp300/dev/dnkbd_keymaps.h>
+ 
+ 
+ /* #define DNKBD_DEBUG*/
+ 
+ #ifdef DNKBD_DEBUG
+ #define D(x)	x
+ #else
+ #define D(x)
+ #endif
+ 
+ #define DNKBD_RAW	0x01		/* keyboard operation modes */
+ #define DNKBD_COOKED	0x00
+ 
+ #define KC_BREAK	0x80		/* mask for 'break' code */
+ #define KC_REPEAT	0x7f		/* auto-repeat code */
+ 
+ #define KB_IDLE	0			/* quiescent */
+ #define KB_MPKT	1			/* reassembling a mouse packet */
+ 
+ struct dnkbd_softc
+ {
+     struct device	sc_dev;		/* device housekeeping */
+     struct apciregs	*sc_apci;	/* pointer to hardware */
+ 
+     char		id1[8], id2[8];	/* keyboard revision identifiers */
+     char		model[16];
+ };
+ 
+ static struct dn_kbdmap *dnkbd_keymap;
+ 
+ static int	dnkbdmatch(struct device *parent, struct cfdata *match, void *aux);
+ static void	dnkbdattach(struct device *parent, struct device *self, void *aux);
+ static int 	dnkbdintr(void *arg);
+ 
+ static void	dnkbd_setup(struct dnkbd_softc *sc, int verbose);
+ static int	dnkbd_scodexlt(int c, int polling);
+ static int	dnkbd_command(struct apciregs *apci, int cmdlen, u_char *command);
+ static int	dnkbd_pollin(struct apciregs *apci, int timeout);
+ static void	dnkbd_pollout(struct apciregs *apci, int c);
+ static void	dnkbd_pollflush(struct apciregs *apci);
+ static void	dnkbd_apciinit(struct apciregs *apci);
+ 
+ struct cfattach dnkbd_ca = {
+     sizeof(struct dnkbd_softc), dnkbdmatch, dnkbdattach
+ };
+ 
+ struct cfdriver dnkbd_cd = {
+     NULL, "dnkbd", DV_TTY
+ };
+ 
+ cdev_decl(dnkbd);
+ 
+ static int	rep_div = 2;		/* auto-repeat divisor */
+ static int	rep_delay = 10;		/* auto-repeat initial delay */
+ 
+ #define DNKBDUNIT(x)	(minor(x) >> 1)	/* LSB is keyboard/mouse selector */
+ #define DNKBDDEV(x)	(minor(x) & 1)
+ 
+ #define DNKBD_KBD	0		/* minor encoding */
+ #define DNKBD_MSE	1
+ 
+ /*
+ ** dnkbdmatch
+ **
+ ** Only allow one instance, as we have lots of static data in the
+ ** scancode state machine.
+ */
+ static int
+ dnkbdmatch(struct device *parent, struct cfdata *match, void *aux)
+ {
+     static int	initted = 0;
+ 
+     if (initted++)
+ 	return(0);
+     return(1);
+ }
+ 
+ /*
+ ** dnkbdattach
+ **
+ ** Do attach and initialise hardware.
+ */
+ static void
+ dnkbdattach(struct device *parent, struct device *self, void *aux)
+ {
+     struct dnkbd_softc		*sc = (struct dnkbd_softc *)self;
+     struct frodo_attach_args	*fa = aux;
+ 
+     /* base address for registers (space is already mapped) */
+     sc->sc_apci = (struct apciregs *)FRODO_STOV(fa->fa_channel);
+ 
+     /* register our interrupt handler */
+     frodo_intr_establish(parent, dnkbdintr, sc, APCI_INTR0);
+ 
+     dnkbd_apciinit(sc->sc_apci);	/* configure UART */
+     dnkbd_setup(sc, 1);			/* setup keyboard, interrogate */
+ 
+     printf("\n");
+ 
+     /* now enable keyboard interrupts, I think we're ready */
+     sc->sc_apci->ap_ier  = IER_ERXRDY;	/* enable RX interrupts */
+ }
+ 
+ /*
+ ** dnkbd_setup
+ **
+ ** Talk to the keyboard (in non-interrupt-driven mode).
+ ** Find out what it is, then set it to raw mode.
+ */
+ static void
+ dnkbd_setup(struct dnkbd_softc *sc, int verbose)
+ {
+     u_char	crbuf[32];	
+     int		i, j, c;
+ 
+     crbuf[0] = 0x12;			/* send 'what are you' command */
+     crbuf[1] = 0x21;
+     if (dnkbd_command(sc->sc_apci, 2, crbuf)) {
+ 	if (verbose)
+ 	    printf(" no keyboard");
+ 	return;
+     }
+     
+     for (i = 0; i < (sizeof(crbuf) - 1); i++) {
+ 	c = dnkbd_pollin(sc->sc_apci, 100000);
+ 	if (c == -1)			/* timeout */
+ 	    break;
+ 	crbuf[i] = c;			/* got a character */
+     }
+     crbuf[i] = 0;
+     
+     for (i = 0, j = 0; (j < sizeof(sc->id1)) && (crbuf[i] != '\r'); i++, j++)
+ 	sc->id1[j] = crbuf[i];		/* copy up to \r */
+     sc->id1[j] = 0;			/* terminate */
+     for (i++, j = 0; (j < sizeof(sc->id2)) && (crbuf[i] != '\r'); i++, j++)
+ 	sc->id2[j] = crbuf[i];		/* copy up to \r */
+     sc->id2[j] = 0;			/* terminate */
+     for (i++, j = 0; (j < sizeof(sc->model)) && (crbuf[i] != '\r'); i++, j++)
+ 	sc->model[j] = crbuf[i];	/* copy up to \r */
+     sc->model[j] = 0;			/* terminate */
+ 
+     if (verbose)			/* tell what we know? */
+ 	printf(": <%s>", sc->model);
+ 
+     crbuf[0] = DNKBD_RAW;		/* set for raw mode */
+     if (dnkbd_command(sc->sc_apci, 1, crbuf)) {
+ 	if (verbose)
+ 	    printf(" (raw mode failed)");
+ 	return;
+     }
+ }
+ 
+ /*
+ ** dnkbdopen
+ */
+ int
+ dnkbdopen(dev_t dev, int flag, int mode, struct proc *p)
+ {
+     D(printf("dnkbdopen:\n"));
+     return(ENXIO);
+ }
+ 
+ /*
+ ** dnkbdclose
+ */
+ int
+ dnkbdclose(dev_t dev, int flag, int mode, struct proc *p)
+ {
+     D(printf("dnkbdclose:\n"));
+     return (ENXIO);
+ }
+ 
+ /*
+ ** dnkbdread
+ */
+ int
+ dnkbdread(dev_t dev, struct uio *uio, int flag)
+ {
+     D(printf("dnkbdread:\n"));
+     return(0);
+ }
+ 
+ /*
+ ** dnkbd_scodexlt
+ **
+ ** Process an incoming scancode.  If (polling) is true, returns
+ ** a keypress or -1, otherwise passes key events off to ite and returns
+ ** zero if it did any work.
+ */
+ static int
+ dnkbd_scodexlt(int c, int polling)
+ {
+     /* 
+      * Keep our state here because we may need it before the softc is
+      * allocated.   XXX ick.
+      */
+     static int	inpstate = KB_IDLE;	/* state of the input parse engine */
+     static int	currkey = -1;		/* the last 'normal' scancode we received */
+     static int	rep_cnt;		/* auto-repeat counter */
+     static int	mpbuf[4];		/* reassembly buffer for mouse packet */
+     static int	mplen;			/* mouse packet length counter */
+     static int	inpmod = 0;		/* input modifier(s) */
+ 
+     int		kbreak;
+     int		retval = -1;		/* default to no output */
+     int		xc;			/* translated code */
+     int		i;
+ 
+     switch (inpstate) {			/* what are we doing just now? */
+ 
+     default:
+     case KB_IDLE:			/* waiting for a key or prefix */
+ 
+ 	/* check for mouse traffic */
+ 	if (c == 0xdf) {		/* mouse packet starts */
+ 	    mplen = 0;
+ 	    mpbuf[0] = c;
+ 	    inpstate = KB_MPKT;
+ 	    break;
+ 	}
+ 
+ 	/* get make/break status, mask to keycode */
+ 	kbreak = c & KC_BREAK;		/* check for break code */
+ 	c = c & 0x7f;			/* mask extraneous rubbish */
+ 
+ 	/* not mouse, how about auto-repeat? */
+ 	if (c == KC_REPEAT) {		/* auto-repeat scancode */
+ 	    if (currkey == -1)		/* no code to repeat */
+ 		break;			/* do nothing, and do it right now */
+ 	    if (++rep_cnt < rep_div)
+ 		break;			/* not time for another one yet */
+ 	    c = currkey;		/* time to repeat */
+ 	    rep_cnt = 0;		/* wait for next time */
+ 	}
+ 
+ 	/* break code on repeating key? */
+ 	if (kbreak && (c == currkey)) {	/* repeating key goes up */
+ 	    currkey = -1;		/* stop repeating */
+ 	    break;			/* nothing more to do */
+ 	}
+ 
+ 	/* look up the translated version of our scancode */
+ 	switch (inpmod) {		/* which keymap? */
+ 	case K_CAP:
+ 	case K_SHF:
+ 	    xc = dnkbd_keymap->kbd_shiftmap[c];
+ 	    break;
+ 	case K_CTL:
+ 	    xc = dnkbd_keymap->kbd_ctrlmap[c];
+ 	    break;
+ 	case K_SHF | K_CTL:
+ 	case K_SHF | K_CAP | K_CTL:
+ 	    xc = dnkbd_keymap->kbd_ctrlshiftmap[c];
+ 	    break;
+ 	default:			/* includes meta state */
+ 	    xc = dnkbd_keymap->kbd_keymap[c];
+ 	    break;
+ 	}
+ 	    
+ 	switch (xc) {			/* do what with it? */
+ 
+ 	case K_CAP:			/* modifier? */
+ 	case K_SHF:
+ 	case K_CTL:
+ 	case K_ALT:
+ 	    inpmod = kbreak ? inpmod & ~xc : inpmod | xc;
+ 	    break;
+ 
+ 	case K_IGN:			/* do-nothing? */
+ 	    if (!polling && !kbreak)	/* ought to check the stringmap */
+ 		if (dnkbd_keymap->kbd_stringmap[c] != NULL) {
+ 		    if (currkey != c) {	/* new interesting key? */
+ 			currkey = c;	/* initialise auto-repeat counter */
+ 			rep_cnt = -rep_delay;
+ 		    }
+ 		    for (i = 0; dnkbd_keymap->kbd_stringmap[c][i] != 0; i++)
+ 			itekbdin(dnkbd_keymap->kbd_stringmap[c][i]);
+ 		    retval = 0;		/* did something */
+ 		}
+ 	    break;
+ 		
+ 	case K_DBG:			/* XXX break to debugger? */
+ 	    break;
+ 		
+ 	default:			/* keystroke that we might care about */
+ 	    if (!kbreak) {
+ 		if (currkey != c) {	/* new interesting key? */
+ 		    currkey = c;	/* initialise auto-repeat counter */
+ 		    rep_cnt = -rep_delay;
+ 		}
+ 		if (inpmod & K_ALT)
+ 		    xc |= 0x80;		/* meta-mode */
+ 		if (polling) {
+ 		    retval = xc;	/* this is what we have */
+ 		} else {
+ 		    D(printf("[%x:%x]", inpmod, xc));
+ 		    itekbdin(xc);	/* give it to ite */
+ 		    retval = 0;		/* did something */
+ 		}
+ 	    }
+ 	    break;
+ 	}
+ 	break;
+ 
+     case KB_MPKT:			/* reassembling a rodent datagram */
+ 	mpbuf[mplen++] = c;		/* another byte */
+ 	if (mplen >= 4) {		/* got the packet ?*/
+ 	    inpstate = KB_IDLE;		/* go idle */
+ 	}
+ 	break;
+     }
+     return(retval);
+ }
+ 
+ /*
+ ** dnkbdintr
+ **
+ ** Take an interrupt.  The only interrupts we believe in
+ ** are receive interrupts; anything else is either bogus
+ ** or useless.
+ */
+ static int 
+ dnkbdintr(void *arg)
+ {	
+     struct dnkbd_softc		*sc = arg;
+     register struct apciregs	*apci = sc->sc_apci;
+     register u_char		iir, lsr;
+     register int		c;
+ 
+     for (;;) {
+ 	iir = apci->ap_iir;		/* get UART status */
+ 
+ 	switch (iir & IIR_IMASK) {
+ 
+ 	case IIR_RLS:			/* should never happen */
+ 	    c = apci->ap_lsr;		/* do this to clear interrupt */
+ 	    break;
+ 
+ 	case IIR_RXRDY:			/* data arriveth */
+ 	case IIR_RXTOUT:
+ 	    while ((lsr = apci->ap_lsr) & LSR_RXRDY) {
+ 		/* convert to kbd event, give to ite */
+ 		(void)dnkbd_scodexlt(apci->ap_data, 0);
+ 	    }
+ 	    break;
+ 
+ 	case IIR_TXRDY:			/* not interesting, shouldn't happen */
+ 	    break;
+ 
+ 	case IIR_MLSC:
+ 	    c = apci->ap_msr;		/* clear the interrupt */
+ 	    break;
+ 	    
+ 	default:
+ 	    if (iir & IIR_NOPEND) {	/* nothing pending now */
+ 		return(1);		/* always claim we did something */
+ 	    }
+ 	    panic("%s: bogus interrupt iir %x", sc->sc_dev.dv_xname, iir);
+ 	}
+     }
+ }
+ 
+ /*
+ ** dnkbdioctl
+ **
+ ** No ioctls (yet)
+ */
+ int
+ dnkbdioctl(dev_t dev, u_long cmd, caddr_t data, int flag, struct proc *p)
+ {
+     
+     /* what should we support, and how? */
+ 
+     switch (cmd) {
+     default:
+ 	return(ENOTTY);
+     }
+     return(0);
+ }
+ 
+ /*
+ ** dnkbdpoll
+ **
+ ** poll interface, not implemented yet.
+ */
+ int
+ dnkbdpoll(dev_t dev, int events, struct proc *p)
+ {
+     return(0);
+ }
+ 
+ /*
+ ** dnkbd_command
+ **
+ ** Send and wait for acknowledgement of (command).
+ ** XXX this can take hundreds of milliseconds, spent at spltty.
+ ** Should _not_ be used other than at system startup time.
+ */
+ static int
+ dnkbd_command(struct apciregs *apci, int cmdlen, u_char *command)
+ {
+     int			s, i, c;
+ 
+     s = spltty();
+     
+     dnkbd_pollflush(apci);			/* dump input queue */
+     dnkbd_pollout(apci, 0xff);			/* send command escape */
+     for (i = 0; i < cmdlen; i++)
+ 	dnkbd_pollout(apci, command[i]);	/* send command bytes */
+     
+     do {					/* wait for echo */
+ 	c = dnkbd_pollin(apci, 0);
+ 	if (c == -1) {
+ 	    return(EIO);
+ 	}
+     } while (c != 0xff);
+ 
+     for (i = 0; i < cmdlen; i++) {		/* wait for command echo */
+ 	c = dnkbd_pollin(apci, 100000);
+ 	if (c != command[i])
+ 	    return(EIO);
+     }
+     return(0);
+ }
+ 
+ /*
+ ** Polled-mode input/output/flush, call at spltty() or with UART 
+ ** interrupts disabled.
+ */
+ static int
+ dnkbd_pollin(struct apciregs *apci, int timeout)
+ {
+     int			c;
+     
+     while(!(apci->ap_lsr & LSR_RXRDY)) {	/* spin waiting, use lousy timeout */
+ 	if (timeout != 0) {
+ 	    if (--timeout == 0)
+ 		return -1;
+ 	}
+     }
+     c = apci->ap_data;
+     return(c);
+ }
+ 
+ static void
+ dnkbd_pollout(struct apciregs *apci, int c)
+ {
+     while(!(apci->ap_lsr & LSR_TXRDY))
+ 	;			/* spin waiting for space to xmit */
+     apci->ap_data = c;
+ }
+ 
+ static void
+ dnkbd_pollflush(struct apciregs *apci)
+ {
+     int	spin = 10;		/* more than this and we are in big trouble */
+     
+     while(spin-- && (dnkbd_pollin(apci, 10) != -1))
+ 	;			/* spin discarding data */
+ }
+ 
+ /*
+ ** dnkbd_apciinit
+ **
+ ** Initialise the apci UART at (apci) for keyboard use.  Don't
+ ** play with the interrupt status.
+ */
+ static void
+ dnkbd_apciinit(struct apciregs *apci)
+ {
+     int		rate, s;
+ 
+     s = spltty();
+     rate = APCIBRD(1200);				/* keyboard does 1200bps */
+ 
+     apci->ap_cfcr = CFCR_DLAB;
+     apci->ap_data = rate & 0xFF;
+     apci->ap_ier  = rate >> 8;
+     apci->ap_cfcr = CFCR_8BITS | CFCR_PEVEN | CFCR_PENAB;
+     /* do this like HP seems to */
+     apci->ap_fifo = FIFO_ENABLE | FIFO_XMT_RST; 
+     apci->ap_fifo = FIFO_ENABLE | FIFO_RCV_RST;
+     apci->ap_mcr  = MCR_DTR | MCR_RTS;
+     splx(s);
+ }
+ 
+ /*
+ ** ITE cooked keyboard functions
+ */
+ 
+ void
+ dnkbdbell(int unit)
+ {
+     /* XXX Info we have on bell command appears to be wrong? */
+ }
+ 
+ /*
+ ** dnkbdenable
+ **
+ ** Allow the keyboard to send ite stuff.  We can't do that
+ ** until interrupts are enabled, and that happens after this
+ ** anyway, so just clear out anything pending so far.
+ */
+ void
+ dnkbdenable(int unit)
+ {
+     struct apciregs	*apci = (struct apciregs *)0x81c000;
+     int			s;
+ 
+     if (unit == 0) {
+ 	D(printf("dnkbdenable\n"));
+ 	s = spltty();
+ 	dnkbd_pollflush(apci);		/* drain any input */
+ 	splx(s);
+     }
+ }
+ 
+ /*
+ ** dnkbddisable
+ **
+ ** Stop the keyboard sending ite stuff.  Not used.
+ */
+ void
+ dnkbddisable(int unit)
+ {
+     struct apciregs	*apci = (struct apciregs *)0x81c000;
+     int			s;
+ 
+     if (unit == 0) {
+ 	D(printf("dnkbdisable\n"));
+ 	s = spltty();
+ 	dnkbd_pollflush(apci);		/* drain any input */
+ 	splx(s);
+     }
+ }
+ 
+ 
+ 
+ /*
+ ** Apollo keyboard console support
+ */
+ 
+ static struct apciregs *dnkbd_cn_device = NULL;
+ 
+ /*
+ ** dnkbdgetc
+ **
+ ** Read bytes(s) from keyboard, feed through scancode parser, return
+ ** when we have a character.
+ */
+ int
+ dnkbdgetc(void)
+ {
+     struct apciregs	*apci = dnkbd_cn_device;
+     int			s, c;
+ 
+     if (apci == NULL)		/* not console keyboard */
+ 	return(0);
+ 
+     D(printf("dnkbdgetc\n"));
+     
+     /* XXX should be splraise? */
+     s = spltty();					/* inhibit interrupts */
+     do {
+ 	c = dnkbd_scodexlt(dnkbd_pollin(apci, 0), 1);	/* get a character, translate */
+     } while (c == -1);
+     splx(s);
+ 
+     D(printf(" [%x]", c));
+     return(c & 0xff);			/* mask rubbish */
+ }
+ 
+ /*
+ ** dnkbdinit
+ **
+ ** Do enough initialisation of the keyboard UART to
+ ** be able to talk to it, and return 1 if there's actually
+ ** a keyboard plugged in.
+ */
+ int
+ dnkbdinit(void)
+ {
+     struct apciregs	*apci = (struct apciregs *)0x81c000;
+     u_char		cbuf;
+ 
+     D(printf("Look for Apollo keyboard at %p...", apci));
+     if (badaddr((caddr_t)apci)) {
+ 	D(printf("nothing there\n"));
+ 	return(0);
+     }
+     /* setup UART, not strictly required as the firmware has already done this */
+     dnkbd_apciinit(apci);
+     dnkbd_cn_device = apci;	/* save for later reference */
+     cbuf = DNKBD_RAW;		/* set for raw mode */
+     if (dnkbd_command(apci, 1, &cbuf)) {
+ 	D(printf("won't go to raw mode\n"));
+ 	return(0);		/* nope, let it use the HIL default instead */
+     }
+     D(printf("using for console\n"));
+     /* Go with the US keymap for now */
+     dnkbd_keymap = &dnkbd_keymaps[0];
+     return(1);
+ }
diff -crN /sys/arch/hp300/dev/dnkbd_keymaps.h dev/dnkbd_keymaps.h
*** /sys/arch/hp300/dev/dnkbd_keymaps.h	Wed Dec 31 16:00:00 1969
--- dev/dnkbd_keymaps.h	Wed Apr 23 20:14:40 1997
***************
*** 0 ****
--- 1,247 ----
+ /*	$NetBSD$ */
+ 
+ /*
+  * Copyright (c) 1997 Michael Smith.  All rights reserved.
+  *
+  * Redistribution and use in source and binary forms, with or without
+  * modification, are permitted provided that the following conditions
+  * are met:
+  * 1. Redistributions of source code must retain the above copyright
+  *    notice, this list of conditions and the following disclaimer.
+  * 2. Redistributions in binary form must reproduce the above copyright
+  *    notice, this list of conditions and the following disclaimer in the
+  *    documentation and/or other materials provided with the distribution.
+  *
+  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+  * SUCH DAMAGE.
+  *
+  */
+ 
+ /* 
+  * Apollo keyboard keymaps.
+  *
+  * Note that, as of now, there is only one keymap, and it is not known
+  * how to determine which keymap a keyboard uses anyway.
+  *
+  * These keymaps assume the keyboard in 'raw' mode (mode 1).
+  */
+ 
+ struct dn_kbdmap 
+ {
+     /* XXX layout identifier? */
+     char	*kbd_desc;
+     int		*kbd_keymap;
+     int		*kbd_shiftmap;
+     int		*kbd_ctrlmap;
+     int		*kbd_ctrlshiftmap;
+     char	**kbd_stringmap;
+ };
+ 
+ /*
+  * In all maps other than the string maps, the following defines apply :
+  */
+ 
+ #define K_IGN	0xffff		/* ignore the keystroke */
+ #define K_SHF	0x0100		/* set/clear the shift flag */
+ #define K_CTL	0x0200		/* set/clear the control flag */
+ #define K_ALT	0x0400		/* set/clear the alt (meta) flag */
+ #define K_CAP	0x0800		/* set/clear the capslock flag */
+ #define K_DBG	0x8000		/* break to the debugger */
+ 
+ /*
+  * In the string maps, NULL indicates no string mapping, otherwise
+  * the character string provided will be generated on a key-down
+  * event only.
+  */
+ 
+ static int dnkbd_us_keymap[] = {
+ /*          Ins     Line    Char    F0      F1      F2      F3    07 */
+     K_IGN,  K_IGN,  K_IGN,  K_IGN,  K_IGN,  K_IGN,  K_IGN,  K_IGN,
+ /*  F4      F5      F6      F7      F8      F9      Again   Read  0f */
+     K_IGN,  K_IGN,  K_IGN,  K_IGN,  K_IGN,  K_IGN,  K_IGN,  K_IGN,
+ /*  Save    Abort   Help            Undo    Move            Esc   17 */
+     K_IGN,  K_IGN,  K_IGN,  K_IGN,  K_IGN,  K_IGN,  K_IGN,  0x1b,
+ /*   1       2       3       4       5       6       7       8    1f */
+     '1',    '2',    '3',    '4',    '5',    '6',    '7',    '8', 
+ /*   9       0       -       =       `      BS              BOL   27 */
+     '9',    '0',    '-',    '=',    '`',    '\b',   K_IGN,  K_IGN,
+ /*  Shell   EOL                     Tab      q       w       e    2f */
+     K_IGN,  K_IGN,  K_IGN,  K_IGN,  '\t',   'q',    'w',    'e', 
+ /*   r       t       y       u       i       o       p       [    37 */
+     'r',    't',    'y',    'u',    'i',    'o',    'p',    '[', 
+ /*   ]              Del             kp7     kp8     kp9     kp+   3f */
+     ']',    K_IGN,  0x7f,   K_IGN,  '7',    '8',    '9',    '+',
+ /*  Sleft   Up      Srght   Ctrl                     a       s    47 */
+     K_IGN,  K_IGN,  K_IGN,  K_CTL,  K_IGN,  K_IGN,  'a',    's', 
+ /*   d       f       g       h       j       k       l       ;    4f */
+     'd',    'f',    'g',    'h',    'j',    'k',    'l',    ';', 
+ /*   '              Ret      \              kp4     kp5     kp6   57 */
+     '\'',   K_IGN,  '\r',   '\\',   K_IGN,  '4',    '5',    '6',
+ /*  kp-     Left    Next    Rght            Rept    LShft         5f */
+     '-',    K_IGN,  K_IGN,  K_IGN,  K_IGN,  K_IGN,  K_SHF,  K_IGN,
+ /*   z       x       c       v       b       n       m       ,    67 */
+     'z',    'x',    'c',    'v',    'b',    'n',    'm',    ',', 
+ /*   .       /      RShft           Pop             kp1     kp2   6f */
+     '.',    '/',    K_SHF,  K_IGN,  K_IGN,  K_IGN,  '1',    '2',
+ /*  kp3             Sup     Down    Sdwn    Lalt    Space   Ralt  77 */
+     '3',    K_IGN,  K_IGN,  K_IGN,  K_IGN,  K_ALT,  ' ',    K_ALT,
+ /*          kp0             kp.     kpEnt                         7f */
+     K_IGN,  '0',    K_IGN,  '.',    '\r',   K_IGN,  K_CAP,  K_IGN
+ };
+ 
+ static int dnkbd_us_shiftmap[] = {
+ /*          Ins     Line    Char    F0      F1      F2      F3    07 */
+     K_IGN,  K_IGN,  K_IGN,  K_IGN,  K_IGN,  K_IGN,  K_IGN,  K_IGN,
+ /*  F4      F5      F6      F7      F8      F9      Again   Read  0f */
+     K_IGN,  K_IGN,  K_IGN,  K_IGN,  K_IGN,  K_IGN,  K_IGN,  K_IGN,
+ /*  Save    Abort   Help            Undo    Move            Esc   17 */
+     K_IGN,  K_IGN,  K_IGN,  K_IGN,  K_IGN,  K_IGN,  K_IGN,  K_IGN,
+ /*   1       2       3       4       5       6       7       8    1f */
+     '!',    '@',    '#',    '$',    '%',    '^',    '&',    '*', 
+ /*   9       0       -       =       `      BS              BOL   27 */
+     '(',    ')',    '_',    '+',    '~',    K_IGN,  K_IGN,  K_IGN,
+ /*  Shell   EOL                     Tab      q       w       e    2f */
+     K_IGN,  K_IGN,  K_IGN,  K_IGN,  K_IGN,  'Q',    'W',    'E', 
+ /*   r       t       y       u       i       o       p       [    37 */
+     'R',    'T',    'Y',    'U',    'I',    'O',    'P',    '{', 
+ /*   ]              Del             kp7     kp8     kp9     kp+   3f */
+     '}',    K_IGN,  K_IGN,  K_IGN,  '7',    '8',    '9',    '+',
+ /*  Sleft   Up      Srght   Ctrl                     a       s    47 */
+     K_IGN,  K_IGN,  K_IGN,  K_CTL,  K_IGN,  K_IGN,  'A',    'S', 
+ /*   d       f       g       h       j       k       l       ;    4f */
+     'D',    'F',    'G',    'H',    'J',    'K',    'L',    ':', 
+ /*   '              Ret      \              kp4     kp5     kp6   57 */
+     '"',    K_IGN,  K_IGN,  '|',    K_IGN,  '4',    '5',    '6', 
+ /*  kp-     Left    Next    Rght            Rept    LShft         5f */
+     '-',    K_IGN,  K_IGN,  K_IGN,  K_IGN,  K_IGN,  K_SHF,  K_IGN,
+ /*   z       x       c       v       b       n       m       ,    67 */
+     'Z',    'X',    'C',    'V',    'B',    'N',    'M',    '<', 
+ /*   .       /      RShft           Pop             kp1     kp2   6f */
+     '>',    '?',    K_SHF,  K_IGN,  K_IGN,  K_IGN,  '1',    '2', 
+ /*  kp3             Sup     Down    Sdwn    Lalt    Space   Ralt  77 */
+     '3',    K_IGN,  K_IGN,  K_IGN,  K_IGN,  K_ALT,  ' ',    K_ALT,
+ /*          kp0             kp.     kpEnt                         7f */
+     K_IGN,  '0',    K_IGN,  '.',    '\r',   K_IGN,  K_CAP,  K_IGN
+ };
+ 
+ static int dnkbd_us_ctrlmap[] = {
+ /*          Ins     Line    Char    F0      F1      F2      F3    07 */
+     K_IGN,  K_IGN,  K_IGN,  K_IGN,  K_IGN,  K_IGN,  K_IGN,  K_IGN,
+ /*  F4      F5      F6      F7      F8      F9      Again   Read  0f */
+     K_IGN,  K_IGN,  K_IGN,  K_IGN,  K_IGN,  K_IGN,  K_IGN,  K_IGN,
+ /*  Save    Abort   Help            Undo    Move            Esc   17 */
+     K_IGN,  K_IGN,  K_IGN,  K_IGN,  K_IGN,  K_IGN,  K_IGN,  K_IGN,
+ /*   1       2       3       4       5       6       7       8    1f */
+     K_IGN,  K_IGN,  K_IGN,  K_IGN,  K_IGN,  K_IGN,  K_IGN,  K_IGN,
+ /*   9       0       -       =       `      BS              BOL   27 */
+     K_IGN,  K_IGN,  K_IGN,  K_IGN,  K_IGN,  K_IGN,  K_IGN,  K_IGN,
+ /*  Shell   EOL                     Tab      q       w       e    2f */
+     K_IGN,  K_IGN,  K_IGN,  K_IGN,  K_IGN,  0x11,   0x17,   0x05,
+ /*   r       t       y       u       i       o       p       [    37 */
+     0x12,   0x14,   0x19,   0x15,   0x09,   0x0f,   0x10,   K_IGN,
+ /*   ]              Del             kp7     kp8     kp9     kp+   3f */
+     K_IGN,  K_IGN,  K_IGN,  K_IGN,  K_IGN,  K_IGN,  K_IGN,  K_IGN,
+ /*  Sleft   Up      Srght   Ctrl                     a       s    47 */
+     K_IGN,  K_IGN,  K_IGN,  K_CTL,  K_IGN,  K_IGN,  0x01,   0x13,
+ /*   d       f       g       h       j       k       l       ;    4f */
+     0x04,   0x06,   0x07,   0x08,   0x0a,   0x0b,   0x0c,   K_IGN,
+ /*   '              Ret      \              kp4     kp5     kp6   57 */
+     K_IGN,  K_IGN,  K_IGN,  0x1c,   K_IGN,  K_IGN,  K_IGN,  K_IGN,
+ /*  kp-     Left    Next    Rght            Rept    LShft         5f */
+     K_IGN,  K_IGN,  K_IGN,  K_IGN,  K_IGN,  K_IGN,  K_SHF,  K_IGN,
+ /*   z       x       c       v       b       n       m       ,    67 */
+     0x1a,   0x18,   0x03,   0x16,   0x02,   0x0e,   0x0d,   K_IGN,
+ /*   .       /      RShft           Pop             kp1     kp2   6f */
+     K_IGN,  K_IGN,  K_SHF,  K_IGN,  K_IGN,  K_IGN,  K_IGN,  K_IGN,
+ /*  kp3             Sup     Down    Sdwn    Lalt    Space   Ralt  77 */
+     K_IGN,  K_IGN,  K_IGN,  K_IGN,  K_IGN,  K_ALT,  K_IGN,  K_ALT,
+ /*          kp0             kp.     kpEnt                         7f */
+     K_IGN,  K_IGN,  K_IGN,  K_IGN,  K_IGN,  K_IGN,  K_CAP,  K_IGN
+ };
+ 
+ static int dnkbd_us_ctrlshiftmap[] = {
+ /*          Ins     Line    Char    F0      F1      F2      F3    07 */
+     K_IGN,  K_IGN,  K_IGN,  K_IGN,  K_IGN,  K_IGN,  K_IGN,  K_IGN,
+ /*  F4      F5      F6      F7      F8      F9      Again   Read  0f */
+     K_IGN,  K_IGN,  K_IGN,  K_IGN,  K_IGN,  K_IGN,  K_IGN,  K_IGN,
+ /*  Save    Abort   Help            Undo    Move            Esc   17 */
+     K_IGN,  K_IGN,  K_IGN,  K_IGN,  K_IGN,  K_IGN,  K_IGN,  K_IGN,
+ /*   1       2       3       4       5       6       7       8    1f */
+     K_IGN,  K_IGN,  K_IGN,  K_IGN,  K_IGN,  K_IGN,  K_IGN,  K_IGN,
+ /*   9       0       -       =       `      BS              BOL   27 */
+     K_IGN,  K_IGN,  K_IGN,  K_IGN,  K_IGN,  K_IGN,  K_IGN,  K_IGN,
+ /*  Shell   EOL                     Tab      q       w       e    2f */
+     K_IGN,  K_IGN,  K_IGN,  K_IGN,  K_IGN,  K_IGN,  K_IGN,  K_IGN,
+ /*   r       t       y       u       i       o       p       [    37 */
+     K_IGN,  K_IGN,  K_IGN,  K_IGN,  K_IGN,  K_IGN,  K_IGN,  K_IGN,
+ /*   ]              Del             kp7     kp8     kp9     kp+   3f */
+     K_IGN,  K_IGN,  K_IGN,  K_IGN,  K_IGN,  K_IGN,  K_IGN,  K_IGN,
+ /*  Sleft   Up      Srght   Ctrl                     a       s    47 */
+     K_IGN,  K_IGN,  K_IGN,  K_CTL,  K_IGN,  K_IGN,  K_IGN,  K_IGN,
+ /*   d       f       g       h       j       k       l       ;    4f */
+     K_IGN,  K_IGN,  K_IGN,  K_IGN,  K_IGN,  K_IGN,  K_IGN,  K_IGN,
+ /*   '              Ret      \              kp4     kp5     kp6   57 */
+     K_IGN,  K_IGN,  K_IGN,  K_IGN,  K_IGN,  K_IGN,  K_IGN,  K_IGN,
+ /*  kp-     Left    Next    Rght            Rept    LShft         5f */
+     K_IGN,  K_IGN,  K_IGN,  K_IGN,  K_IGN,  K_IGN,  K_SHF,  K_IGN,
+ /*   z       x       c       v       b       n       m       ,    67 */
+     K_IGN,  K_IGN,  K_IGN,  K_IGN,  K_IGN,  K_IGN,  K_IGN,  K_IGN,
+ /*   .       /      RShft           Pop             kp1     kp2   6f */
+     K_IGN,  K_IGN,  K_SHF,  K_IGN,  K_IGN,  K_IGN,  K_IGN,  K_IGN,
+ /*  kp3             Sup     Down    Sdwn    Lalt    Space   Ralt  77 */
+     K_IGN,  K_IGN,  K_IGN,  K_IGN,  K_IGN,  K_ALT,  K_IGN,  K_ALT,
+ /*          kp0             kp.     kpEnt                         7f */
+     K_IGN,  K_IGN,  K_IGN,  K_IGN,  K_IGN,  K_IGN,  K_CAP,  K_IGN
+ };
+ 
+ static char *dnkbd_us_stringmap[] = {
+ /*          Ins     Line    Char    F0      F1      F2      F3    07 */
+     NULL,   NULL,   NULL,   NULL,   NULL,   NULL,   NULL,   NULL,
+ /*  F4      F5      F6      F7      F8      F9      Again   Read  0f */
+     NULL,   NULL,   NULL,   NULL,   NULL,   NULL,   NULL,   NULL,
+ /*  Save    Abort   Help            Undo    Move            Esc   17 */
+     NULL,   NULL,   NULL,   NULL,   NULL,   NULL,   NULL,   NULL,
+ /*   1       2       3       4       5       6       7       8    1f */
+     NULL,   NULL,   NULL,   NULL,   NULL,   NULL,   NULL,   NULL,
+ /*   9       0       -       =       `      BS              BOL   27 */
+     NULL,   NULL,   NULL,   NULL,   NULL,   NULL,   NULL,   NULL,
+ /*  Shell   EOL                     Tab      q       w       e    2f */
+     NULL,   NULL,   NULL,   NULL,   NULL,   NULL,   NULL,   NULL,
+ /*   r       t       y       u       i       o       p       [    37 */
+     NULL,   NULL,   NULL,   NULL,   NULL,   NULL,   NULL,   NULL,
+ /*   ]              Del             kp7     kp8     kp9     kp+   3f */
+     NULL,   NULL,   NULL,   NULL,   NULL,   NULL,   NULL,   NULL,
+ /*  Sleft   Up      Srght   Ctrl                     a       s    47 */
+     NULL,   "\033A",NULL,   NULL,   NULL,   NULL,   NULL,   NULL,
+ /*   d       f       g       h       j       k       l       ;    4f */
+     NULL,   NULL,   NULL,   NULL,   NULL,   NULL,   NULL,   NULL,
+ /*   '              Ret      \              kp4     kp5     kp6   57 */
+     NULL,   NULL,   NULL,   NULL,   NULL,   NULL,   NULL,   NULL,
+ /*  kp-     Left    Next    Rght            Rept    LShft         5f */
+     NULL,   "\033D",NULL,   "\033C",NULL,   NULL,   NULL,   NULL,
+ /*   z       x       c       v       b       n       m       ,    67 */
+     NULL,   NULL,   NULL,   NULL,   NULL,   NULL,   NULL,   NULL,
+ /*   .       /      RShft           Pop             kp1     kp2   6f */
+     NULL,   NULL,   NULL,   NULL,   NULL,   NULL,   NULL,   NULL,
+ /*  kp3             Sup     Down    Sdwn    Lalt    Space   Ralt  77 */
+     NULL,   NULL,   NULL,   "\033B",NULL,   NULL,   NULL,   NULL,
+ /*          kp0             kp.     kpEnt                         7f */
+     NULL,   NULL,   NULL,   NULL,   NULL,   NULL,   NULL,   NULL
+ };
+ 
+ static struct dn_kbdmap dnkbd_keymaps[] = {
+     {"US", dnkbd_us_keymap, dnkbd_us_shiftmap, dnkbd_us_ctrlmap, 
+      dnkbd_us_ctrlshiftmap, dnkbd_us_stringmap},
+     {NULL, NULL, NULL, NULL, NULL, NULL}
+ };
+ 
+ 
diff -crN /sys/arch/hp300/dev/frodo.c dev/frodo.c
*** /sys/arch/hp300/dev/frodo.c	Wed Dec 31 16:00:00 1969
--- dev/frodo.c	Thu Apr 24 09:35:44 1997
***************
*** 0 ****
--- 1,340 ----
+ /*	$NetBSD$ */
+ 
+ /*
+  * Copyright (c) 1997 Michael Smith.  All rights reserved.
+  *
+  * Redistribution and use in source and binary forms, with or without
+  * modification, are permitted provided that the following conditions
+  * are met:
+  * 1. Redistributions of source code must retain the above copyright
+  *    notice, this list of conditions and the following disclaimer.
+  * 2. Redistributions in binary form must reproduce the above copyright
+  *    notice, this list of conditions and the following disclaimer in the
+  *    documentation and/or other materials provided with the distribution.
+  *
+  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+  * SUCH DAMAGE.
+  *
+  */
+ 
+ /*
+  * Support for the "Frodo" (aka "Apollo Utility") chip found in 
+  * HP Apollo 9000/4xx workstations.
+  */
+ 
+ #include <sys/param.h>
+ #include <sys/systm.h>
+ #include <sys/ioctl.h>
+ #include <sys/proc.h>
+ #include <sys/tty.h>
+ #include <sys/conf.h>
+ #include <sys/file.h>
+ #include <sys/uio.h>
+ #include <sys/kernel.h>
+ #include <sys/syslog.h>
+ #include <sys/device.h>
+ 
+ #include <machine/autoconf.h>
+ #include <machine/cpu.h>
+ #include <machine/intr.h>
+ 
+ #include <hp300/dev/intiovar.h>
+ 
+ #include <hp300/dev/frodoreg.h>
+ #include <hp300/dev/frodovar.h>
+ 
+ /*#define FRODO_DEBUG*/
+ 
+ #ifdef FRODO_DEBUG
+ #define D(x)	x
+ #else
+ #define D(x)
+ #endif
+ 
+ struct frodo_isr 
+ {
+     int		(*isr_func)(void *);
+     caddr_t	isr_arg;
+ };
+ 
+ struct frodo_softc 
+ {
+     struct device	sc_dev;			/* device glue */
+     vu_char		*sc_base;		/* base address of the Frodo part */
+     u_long		sc_ints[16];		/* interrupt counters */
+     struct frodo_isr	sc_isr[FRODO_NISR];	/* interrupt handlers */
+ };
+ 
+ static int	frodomatch(struct device *parent, struct cfdata *cf, void *aux);
+ static void	frodoattach(struct device *parent, struct device *self, void *aux);
+ static int	frodoprint(void *aux, const char *pnp);
+ static int	frodosearch(struct device *parent, struct cfdata *cf, void *aux);
+ static int	frodointr(void *);
+ static int	frodonullintr(void *arg);
+ void		frodo_dumpregs(void);
+ void		frodo_intcount(struct frodo_softc *sc);
+ 
+ struct cfattach frodo_ca = {
+     sizeof(struct frodo_softc), frodomatch, frodoattach
+ };
+ 
+ struct cfdriver frodo_cd = {
+     NULL, "frodo", DV_DULL
+ };
+ 
+ static int
+ frodomatch(struct device *parent, struct cfdata *match, void *aux) 
+ {
+     caddr_t			fbase;
+     struct intio_attach_args	*ia = (struct intio_attach_args *)aux;
+     static int			frodo_matched = 0;
+ 
+     if (frodo_matched) {			/* only allow one instance */
+ 	D(printf("Duplicate frodomatch!\n"));
+ 	return(0);
+     }
+     
+     switch (machineid) {
+     case HP_400:
+     case HP_425:
+     case HP_433:
+ 	fbase = (caddr_t)IIOV(FRODO_BASE);
+ 	if (!badaddr(fbase)) {			/* is there anything there? */
+ 	    ia->ia_addr = fbase;
+ 	    frodo_matched = 1;
+ 	    return(1);
+ 	}
+     }
+     return(0);
+ }
+ 
+ static void
+ frodoattach(struct device *parent, struct device *self, void *aux)
+ {
+     struct frodo_softc		*sc = (struct frodo_softc *)self;
+     struct intio_attach_args	*ia = aux;
+     int				i;
+ 
+     /* clear interrupt counters, other setup */
+     bzero(sc->sc_ints, sizeof(sc->sc_ints));
+     sc->sc_base = (vu_char *)ia->ia_addr;
+ 
+     /* we could use this for something, I'm sure. */
+     if (!(sc->sc_base[FRODO_IISR] & FRODO_IISR_SERVICE))
+ 	printf(" (Service Mode)");
+     
+     printf("\n");
+ 
+     /* disable all frodo interrupts, reenabled as devices attach */
+     frodo_imask(sc, 0, 0xffff);
+     /* clear any pending frodo interrupts (some sources claim these are read-only) */
+     sc->sc_base[FRODO_PIC_PU] = sc->sc_base[FRODO_PIC_PL] = 0xff;
+     /* set interrupt polarities */
+     sc->sc_base[FRODO_PIO_IPR] = 0x10;
+     /* all interrupts are edge triggered (except DMA, which we don't care about) */
+     sc->sc_base[FRODO_PIO_IELR] = 0xcf;
+ 
+     /* clear interrupt handlers */
+     for (i = 0; i < FRODO_NISR; i++) {
+ 	sc->sc_isr[i].isr_func = frodonullintr;
+ 	sc->sc_isr[i].isr_arg = (caddr_t)i;
+     }
+ 
+     /* 
+      * Establish our interrupt handler - moderate priority.  This
+      * should be raised if people think that they are going to do
+      * anything serious with the serial ports.
+      *
+      * We do this before searching for subdevices so that they can 
+      * generate interrupts immediately.
+      */
+     (void)intr_establish(frodointr, sc, 5, IPL_TTY);
+ 
+     /* search for and attach subdevices */
+     config_search(frodosearch, self, NULL);
+ 
+     D(frodo_dumpregs());
+ }
+ 
+ static int
+ frodoprint(void *aux, const char *pnp)
+ {
+     struct frodo_attach_args	*fa = aux;
+ 
+     printf(",%d", fa->fa_channel);
+     return(UNCONF);
+ }
+ 
+ static int
+ frodosearch(struct device *parent, struct cfdata *cf, void *aux)
+ {
+     struct frodo_attach_args	fa;
+     
+     /* clear it */
+     bzero(&fa, sizeof(fa));
+     /* get subdevice number */
+     fa.fa_channel = cf->frodocf_channel;
+     if ((fa.fa_channel >= 0) && (fa.fa_channel < FRODO_MAXDEVS)) {
+         if ((*cf->cf_attach->ca_match)(parent, cf, &fa) > 0)
+ 	    config_attach(parent, cf, &fa, frodoprint);
+     }
+     return(0);
+ }
+ 
+ /*
+ ** Take a frodo interrupt.
+ **
+ */
+ static int
+ frodointr(void *arg)
+ {
+     struct frodo_softc	*sc = arg;
+     int			taken = 0;
+     int			ipend;
+ 
+     /* quick look to see if we have a pending interrupt */
+     if (!FRODO_GETPEND(sc->sc_base))
+ 	return(0);				/* not for us, get out */
+     
+     do {
+ 	/*
+ 	 * There is no need to clear the interrupt; reading from here
+ 	 * does that for us
+ 	 */
+ 	ipend = FRODO_IPEND(sc->sc_base);	/* get pending interrupt */
+ 	(void)sc->sc_isr[ipend].isr_func(sc->sc_isr[ipend].isr_arg);
+ 	sc->sc_ints[ipend]++;			/* increment counter */
+ 	if (taken++ > 100) {			/* too many? */
+ 	    D(frodo_dumpregs());
+ 	    D(frodo_intcount(sc));
+ 	    panic("looped frodo interrupts\n");
+ 	}
+     } while (FRODO_GETPEND(sc->sc_base));
+ 
+     return(taken);
+ }
+ 
+ static int
+ frodonullintr(void *arg)
+ {
+     printf("spurious frodo interrupt %x\n", (int)arg);
+     return(0);
+ }
+ 
+ /*
+ ** Add a frodo interrupt handler
+ */
+ void
+ frodo_intr_establish(void *scp, int (*func)(void *arg), void *arg, int level)
+ {
+     struct frodo_softc	*sc = scp;
+ 
+     if ((level < 0) || (level >= FRODO_NISR))
+ 	panic("frodo_intr_establish: bad interrupt level %d", level);
+     if (sc->sc_isr[level].isr_func != frodonullintr)
+ 	panic("frodo_intr_establish: interrupt %d already allocated", level);
+ 
+     sc->sc_isr[level].isr_func = func;
+     sc->sc_isr[level].isr_arg = arg;
+ 
+     /* unmask the interrupt */
+     frodo_imask(sc, (1<<level), 0);
+ }
+ 
+ void
+ frodo_imask(void *scp, u_short set, u_short clear)
+ {
+     u_short		imask;
+     struct frodo_softc	*sc = scp;
+ 
+     /* get current mask */
+     imask = FRODO_GETMASK(sc->sc_base);
+     
+     imask |= set;
+     imask &= ~clear;
+ 
+     FRODO_SETMASK(sc->sc_base, imask);
+ }
+ 
+ void 
+ frodo_dumpregs(void)
+ {
+     u_char	*fp = (u_char *)IIOV(FRODO_BASE);
+     int		i;
+ 
+     printf("timer   : ");
+     for (i = 0; i < 0xf; i += 2) {
+ 	printf("%02x", fp[FRODO_TIMER+i]);
+     }
+     printf("\niisr    :");
+     if (!(fp[FRODO_IISR] & FRODO_IISR_IOCHK))
+ 	printf(" IOCHK");
+     if (!(fp[FRODO_IISR] & FRODO_IISR_IHI))
+ 	printf(" HI");
+     if (!(fp[FRODO_IISR] & FRODO_IISR_IMID))
+ 	printf(" MID");
+     if (!(fp[FRODO_IISR] & FRODO_IISR_ILOW))
+ 	printf(" LOW");
+     if (!(fp[FRODO_IISR] & FRODO_IISR_SERVICE))
+ 	printf(" SERVICE");
+     printf(" (%02x)",fp[FRODO_IISR]);
+     
+     printf("\ndiagctl : %02x",fp[FRODO_DIAGCTL]);
+     printf("\npicmask : %c%c%c%c%c%c%c%c %c%c%c%c%c%c%c%c",
+ 	   fp[FRODO_PIC_MU] & 0x80 ? '3':'.',
+ 	   fp[FRODO_PIC_MU] & 0x40 ? '2':'.',
+ 	   fp[FRODO_PIC_MU] & 0x20 ? '1':'.',
+ 	   fp[FRODO_PIC_MU] & 0x10 ? '0':'.',
+ 	   fp[FRODO_PIC_MU] & 0x08 ? '?':'.',
+ 	   fp[FRODO_PIC_MU] & 0x04 ? '?':'.',
+ 	   fp[FRODO_PIC_MU] & 0x02 ? '?':'.',
+ 	   fp[FRODO_PIC_MU] & 0x01 ? '?':'.',
+ 	   fp[FRODO_PIC_ML] & 0x80 ? '?':'.',
+ 	   fp[FRODO_PIC_ML] & 0x40 ? '?':'.',
+ 	   fp[FRODO_PIC_ML] & 0x20 ? '?':'.',
+ 	   fp[FRODO_PIC_ML] & 0x10 ? '?':'.',
+ 	   fp[FRODO_PIC_ML] & 0x08 ? '?':'.',
+ 	   fp[FRODO_PIC_ML] & 0x04 ? '?':'.',
+ 	   fp[FRODO_PIC_ML] & 0x02 ? '?':'.',
+ 	   fp[FRODO_PIC_ML] & 0x01 ? '?':'.');
+     
+     printf("\npicpend : %c%c%c%c%c%c%c%c %c%c%c%c%c%c%c%c",
+ 	   fp[FRODO_PIC_PU] & 0x80 ? '3':'.',
+ 	   fp[FRODO_PIC_PU] & 0x40 ? '2':'.',
+ 	   fp[FRODO_PIC_PU] & 0x20 ? '1':'.',
+ 	   fp[FRODO_PIC_PU] & 0x10 ? '0':'.',
+ 	   fp[FRODO_PIC_PU] & 0x08 ? '?':'.',
+ 	   fp[FRODO_PIC_PU] & 0x04 ? '?':'.',
+ 	   fp[FRODO_PIC_PU] & 0x02 ? '?':'.',
+ 	   fp[FRODO_PIC_PU] & 0x01 ? '?':'.',
+ 	   fp[FRODO_PIC_PL] & 0x80 ? '?':'.',
+ 	   fp[FRODO_PIC_PL] & 0x40 ? '?':'.',
+ 	   fp[FRODO_PIC_PL] & 0x20 ? '?':'.',
+ 	   fp[FRODO_PIC_PL] & 0x10 ? '?':'.',
+ 	   fp[FRODO_PIC_PL] & 0x08 ? '?':'.',
+ 	   fp[FRODO_PIC_PL] & 0x04 ? '?':'.',
+ 	   fp[FRODO_PIC_PL] & 0x02 ? '?':'.',
+ 	   fp[FRODO_PIC_PL] & 0x01 ? '?':'.');
+     printf("\npicivr  : %02x\n",fp[FRODO_PIC_IVR]);
+ }
+ 
+ void
+ frodo_intcount(struct frodo_softc *sc)
+ {
+     printf("\nicount  : %lx %lx %lx %lx %lx %lx %lx %lx %lx %lx %lx %lx %lx %lx %lx %lx\n",
+ 	   sc->sc_ints[0], sc->sc_ints[1], sc->sc_ints[2], sc->sc_ints[3],
+ 	   sc->sc_ints[4], sc->sc_ints[5], sc->sc_ints[6], sc->sc_ints[7],
+ 	   sc->sc_ints[8], sc->sc_ints[9], sc->sc_ints[10], sc->sc_ints[11],
+ 	   sc->sc_ints[12], sc->sc_ints[13], sc->sc_ints[14], sc->sc_ints[15]);
+ }
+ 
+ 	   
diff -crN /sys/arch/hp300/dev/frodo.c~ dev/frodo.c~
*** /sys/arch/hp300/dev/frodo.c~	Wed Dec 31 16:00:00 1969
--- dev/frodo.c~	Thu Apr 24 08:21:21 1997
***************
*** 0 ****
--- 1,346 ----
+ /*	$NetBSD$ */
+ 
+ /*
+  * Copyright (c) 1997 Michael Smith.  All rights reserved.
+  *
+  * Redistribution and use in source and binary forms, with or without
+  * modification, are permitted provided that the following conditions
+  * are met:
+  * 1. Redistributions of source code must retain the above copyright
+  *    notice, this list of conditions and the following disclaimer.
+  * 2. Redistributions in binary form must reproduce the above copyright
+  *    notice, this list of conditions and the following disclaimer in the
+  *    documentation and/or other materials provided with the distribution.
+  *
+  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+  * SUCH DAMAGE.
+  *
+  */
+ 
+ /*
+  * Support for the "Frodo" (aka "Apollo Utility") chip found in 
+  * HP Apollo 9000/4xx workstations.
+  */
+ 
+ #include <sys/param.h>
+ #include <sys/systm.h>
+ #include <sys/ioctl.h>
+ #include <sys/proc.h>
+ #include <sys/tty.h>
+ #include <sys/conf.h>
+ #include <sys/file.h>
+ #include <sys/uio.h>
+ #include <sys/kernel.h>
+ #include <sys/syslog.h>
+ #include <sys/device.h>
+ 
+ #include <machine/autoconf.h>
+ #include <machine/cpu.h>
+ #include <machine/intr.h>
+ 
+ #include <hp300/dev/intiovar.h>
+ 
+ #include <hp300/dev/frodoreg.h>
+ #include <hp300/dev/frodovar.h>
+ 
+ /*#define FRODO_DEBUG*/
+ 
+ #ifdef FRODO_DEBUG
+ #define D(x)	x
+ #else
+ #define D(x)
+ #endif
+ 
+ struct frodo_isr 
+ {
+     int		(*isr_func)(void *);
+     caddr_t	isr_arg;
+ };
+ 
+ struct frodo_softc 
+ {
+     struct device	sc_dev;			/* device glue */
+     vu_char		*sc_base;		/* base address of the Frodo part */
+     u_long		sc_ints[16];		/* interrupt counters */
+     struct frodo_isr	sc_isr[FRODO_NISR];	/* interrupt handlers */
+ };
+ 
+ static int	frodomatch(struct device *parent, struct cfdata *cf, void *aux);
+ static void	frodoattach(struct device *parent, struct device *self, void *aux);
+ static int	frodoprint(void *aux, const char *pnp);
+ static int	frodosearch(struct device *parent, struct cfdata *cf, void *aux);
+ static int	frodointr(void *);
+ static int	frodonullintr(void *arg);
+ void		frodo_dumpregs(void);
+ void		frodo_intcount(struct frodo_softc *sc);
+ 
+ struct cfattach frodo_ca = {
+     sizeof(struct frodo_softc), frodomatch, frodoattach
+ };
+ 
+ struct cfdriver frodo_cd = {
+     NULL, "frodo", DV_DULL
+ };
+ 
+ static int
+ frodomatch(struct device *parent, struct cfdata *match, void *aux) 
+ {
+     caddr_t			fbase;
+     struct intio_attach_args	*ia = (struct intio_attach_args *)aux;
+     static int			frodo_matched = 0;
+ 
+     if (frodo_matched) {			/* only allow one instance */
+ 	D(printf("Duplicate frodomatch!\n"));
+ 	return(0);
+     }
+     
+     switch (machineid) {
+     case HP_400:
+     case HP_425:
+     case HP_433:
+ 	fbase = (caddr_t)IIOV(FRODO_BASE);
+ 	if (!badaddr(fbase)) {			/* is there anything there? */
+ 	    ia->ia_addr = fbase;
+ 	    frodo_matched = 1;
+ 	    return(1);
+ 	}
+     }
+     return(0);
+ }
+ 
+ static void
+ frodoattach(struct device *parent, struct device *self, void *aux)
+ {
+     struct frodo_softc		*sc = (struct frodo_softc *)self;
+     struct intio_attach_args	*ia = aux;
+     int				i;
+ 
+     /* clear interrupt counters, other setup */
+     bzero(sc->sc_ints, sizeof(sc->sc_ints));
+     sc->sc_base = (vu_char *)ia->ia_addr;
+ 
+     /* we could use this for something, I'm sure. */
+     if (!(sc->sc_base[FRODO_IISR] & FRODO_IISR_SERVICE))
+ 	printf(" (Service Mode)");
+     
+     printf("\n");
+ 
+     /* disable all frodo interrupts, reenabled as devices attach */
+     frodo_imask(sc, 0, 0xffff);
+     /* clear any pending frodo interrupts (some sources claim these are read-only) */
+     sc->sc_base[FRODO_PIC_PU] = sc->sc_base[FRODO_PIC_PL] = 0xff;
+     /* set interrupt polarities */
+     sc->sc_base[FRODO_PIO_IPR] = 0x10;
+     /* all interrupts are edge triggered (except DMA, which we don't care about) */
+     sc->sc_base[FRODO_PIO_IELR] = 0xcf;
+ 
+     /* clear interrupt handlers */
+     for (i = 0; i < FRODO_NISR; i++) {
+ 	sc->sc_isr[i].isr_func = frodonullintr;
+ 	sc->sc_isr[i].isr_arg = (caddr_t)i;
+     }
+ 
+     /* 
+      * Establish our interrupt handler - moderate priority.  This
+      * should be raised if people think that they are going to do
+      * anything serious with the serial ports.
+      *
+      * We do this before searching for subdevices so that they can 
+      * generate interrupts immediately.
+      */
+     (void)intr_establish(frodointr, sc, 5, IPL_TTY);
+ 
+     /* search for and attach subdevices */
+     config_search(frodosearch, self, NULL);
+ 
+     /* 
+      * XXX we should perhaps program FRODO_PIC_IVR with something, but
+      * perhaps this is only relevant if we want it to autovector. 
+      * Certainly it seems to work just fine without touching it.
+      */
+     
+     D(frodo_dumpregs());
+ }
+ 
+ static int
+ frodoprint(void *aux, const char *pnp)
+ {
+     struct frodo_attach_args	*fa = aux;
+ 
+     printf(",%d", fa->fa_channel);
+     return(UNCONF);
+ }
+ 
+ static int
+ frodosearch(struct device *parent, struct cfdata *cf, void *aux)
+ {
+     struct frodo_attach_args	fa;
+     
+     /* clear it */
+     bzero(&fa, sizeof(fa));
+     /* get subdevice number */
+     fa.fa_channel = cf->frodocf_channel;
+     if ((fa.fa_channel >= 0) && (fa.fa_channel < FRODO_MAXDEVS)) {
+         if ((*cf->cf_attach->ca_match)(parent, cf, &fa) > 0)
+ 	    config_attach(parent, cf, &fa, frodoprint);
+     }
+     return(0);
+ }
+ 
+ /*
+ ** Take a frodo interrupt.
+ **
+ */
+ static int
+ frodointr(void *arg)
+ {
+     struct frodo_softc	*sc = arg;
+     int			taken = 0;
+     int			ipend;
+ 
+     /* quick look to see if we have a pending interrupt */
+     if (!FRODO_GETPEND(sc->sc_base))
+ 	return(0);				/* not for us, get out */
+     
+     do {
+ 	/*
+ 	 * There is no need to clear the interrupt; reading from here
+ 	 * does that for us
+ 	 */
+ 	ipend = FRODO_IPEND(sc->sc_base);	/* get pending interrupt */
+ 	(void)sc->sc_isr[ipend].isr_func(sc->sc_isr[ipend].isr_arg);
+ 	sc->sc_ints[ipend]++;			/* increment counter */
+ 	if (taken++ > 100) {			/* too many? */
+ 	    D(frodo_dumpregs());
+ 	    D(frodo_intcount(sc));
+ 	    panic("looped frodo interrupts\n");
+ 	}
+     } while (FRODO_GETPEND(sc->sc_base));
+ 
+     return(taken);
+ }
+ 
+ static int
+ frodonullintr(void *arg)
+ {
+     printf("spurious frodo interrupt %x\n", (int)arg);
+     return(0);
+ }
+ 
+ /*
+ ** Add a frodo interrupt handler
+ */
+ void
+ frodo_intr_establish(void *scp, int (*func)(void *arg), void *arg, int level)
+ {
+     struct frodo_softc	*sc = scp;
+ 
+     if ((level < 0) || (level >= FRODO_NISR))
+ 	panic("frodo_intr_establish: bad interrupt level %d", level);
+     if (sc->sc_isr[level].isr_func != frodonullintr)
+ 	panic("frodo_intr_establish: interrupt %d already allocated", level);
+ 
+     sc->sc_isr[level].isr_func = func;
+     sc->sc_isr[level].isr_arg = arg;
+ 
+     /* unmask the interrupt */
+     frodo_imask(sc, (1<<level), 0);
+ }
+ 
+ void
+ frodo_imask(void *scp, u_short set, u_short clear)
+ {
+     u_short		imask;
+     struct frodo_softc	*sc = scp;
+ 
+     /* get current mask */
+     imask = FRODO_GETMASK(sc->sc_base);
+     
+     imask |= set;
+     imask &= ~clear;
+ 
+     FRODO_SETMASK(sc->sc_base, imask);
+ }
+ 
+ void 
+ frodo_dumpregs(void)
+ {
+     u_char	*fp = (u_char *)IIOV(FRODO_BASE);
+     int		i;
+ 
+     printf("timer   : ");
+     for (i = 0; i < 0xf; i += 2) {
+ 	printf("%02x", fp[FRODO_TIMER+i]);
+     }
+     printf("\niisr    :");
+     if (!(fp[FRODO_IISR] & FRODO_IISR_IOCHK))
+ 	printf(" IOCHK");
+     if (!(fp[FRODO_IISR] & FRODO_IISR_IHI))
+ 	printf(" HI");
+     if (!(fp[FRODO_IISR] & FRODO_IISR_IMID))
+ 	printf(" MID");
+     if (!(fp[FRODO_IISR] & FRODO_IISR_ILOW))
+ 	printf(" LOW");
+     if (!(fp[FRODO_IISR] & FRODO_IISR_SERVICE))
+ 	printf(" SERVICE");
+     printf(" (%02x)",fp[FRODO_IISR]);
+     
+     printf("\ndiagctl : %02x",fp[FRODO_DIAGCTL]);
+     printf("\npicmask : %c%c%c%c%c%c%c%c %c%c%c%c%c%c%c%c",
+ 	   fp[FRODO_PIC_MU] & 0x80 ? '3':'.',
+ 	   fp[FRODO_PIC_MU] & 0x40 ? '2':'.',
+ 	   fp[FRODO_PIC_MU] & 0x20 ? '1':'.',
+ 	   fp[FRODO_PIC_MU] & 0x10 ? '0':'.',
+ 	   fp[FRODO_PIC_MU] & 0x08 ? '?':'.',
+ 	   fp[FRODO_PIC_MU] & 0x04 ? '?':'.',
+ 	   fp[FRODO_PIC_MU] & 0x02 ? '?':'.',
+ 	   fp[FRODO_PIC_MU] & 0x01 ? '?':'.',
+ 	   fp[FRODO_PIC_ML] & 0x80 ? '?':'.',
+ 	   fp[FRODO_PIC_ML] & 0x40 ? '?':'.',
+ 	   fp[FRODO_PIC_ML] & 0x20 ? '?':'.',
+ 	   fp[FRODO_PIC_ML] & 0x10 ? '?':'.',
+ 	   fp[FRODO_PIC_ML] & 0x08 ? '?':'.',
+ 	   fp[FRODO_PIC_ML] & 0x04 ? '?':'.',
+ 	   fp[FRODO_PIC_ML] & 0x02 ? '?':'.',
+ 	   fp[FRODO_PIC_ML] & 0x01 ? '?':'.');
+     
+     printf("\npicpend : %c%c%c%c%c%c%c%c %c%c%c%c%c%c%c%c",
+ 	   fp[FRODO_PIC_PU] & 0x80 ? '3':'.',
+ 	   fp[FRODO_PIC_PU] & 0x40 ? '2':'.',
+ 	   fp[FRODO_PIC_PU] & 0x20 ? '1':'.',
+ 	   fp[FRODO_PIC_PU] & 0x10 ? '0':'.',
+ 	   fp[FRODO_PIC_PU] & 0x08 ? '?':'.',
+ 	   fp[FRODO_PIC_PU] & 0x04 ? '?':'.',
+ 	   fp[FRODO_PIC_PU] & 0x02 ? '?':'.',
+ 	   fp[FRODO_PIC_PU] & 0x01 ? '?':'.',
+ 	   fp[FRODO_PIC_PL] & 0x80 ? '?':'.',
+ 	   fp[FRODO_PIC_PL] & 0x40 ? '?':'.',
+ 	   fp[FRODO_PIC_PL] & 0x20 ? '?':'.',
+ 	   fp[FRODO_PIC_PL] & 0x10 ? '?':'.',
+ 	   fp[FRODO_PIC_PL] & 0x08 ? '?':'.',
+ 	   fp[FRODO_PIC_PL] & 0x04 ? '?':'.',
+ 	   fp[FRODO_PIC_PL] & 0x02 ? '?':'.',
+ 	   fp[FRODO_PIC_PL] & 0x01 ? '?':'.');
+     printf("\npicivr  : %02x\n",fp[FRODO_PIC_IVR]);
+ }
+ 
+ void
+ frodo_intcount(struct frodo_softc *sc)
+ {
+     printf("\nicount  : %lx %lx %lx %lx %lx %lx %lx %lx %lx %lx %lx %lx %lx %lx %lx %lx\n",
+ 	   sc->sc_ints[0], sc->sc_ints[1], sc->sc_ints[2], sc->sc_ints[3],
+ 	   sc->sc_ints[4], sc->sc_ints[5], sc->sc_ints[6], sc->sc_ints[7],
+ 	   sc->sc_ints[8], sc->sc_ints[9], sc->sc_ints[10], sc->sc_ints[11],
+ 	   sc->sc_ints[12], sc->sc_ints[13], sc->sc_ints[14], sc->sc_ints[15]);
+ }
+ 
+ 	   
diff -crN /sys/arch/hp300/dev/frodoreg.h dev/frodoreg.h
*** /sys/arch/hp300/dev/frodoreg.h	Wed Dec 31 16:00:00 1969
--- dev/frodoreg.h	Thu Apr 24 08:03:24 1997
***************
*** 0 ****
--- 1,100 ----
+ /*	$NetBSD$ */
+ 
+ /*
+  * Copyright (c) 1997 Michael Smith.  All rights reserved.
+  *
+  * Redistribution and use in source and binary forms, with or without
+  * modification, are permitted provided that the following conditions
+  * are met:
+  * 1. Redistributions of source code must retain the above copyright
+  *    notice, this list of conditions and the following disclaimer.
+  * 2. Redistributions in binary form must reproduce the above copyright
+  *    notice, this list of conditions and the following disclaimer in the
+  *    documentation and/or other materials provided with the distribution.
+  *
+  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+  * SUCH DAMAGE.
+  *
+  */
+ 
+ #include <hp300/dev/iotypes.h>
+ 
+ /* Base address of the Frodo part */
+ #define FRODO_BASE	(INTIOBASE + 0x1c000)
+ 
+ /* Total number of frodo "devices" (4 UARTs, 3 (E)ISA slots & the timer) */
+ #define FRODO_MAXDEVS	8
+ 
+ /* Where we find the 8250-like apci ports, and how far apart they are */
+ #define FRODO_APCIBASE	0x0
+ #define FRODO_ACPISPACE	0x20
+ 
+ /* Other things in the Frodo part */
+ #define FRODO_CALENDAR	0x80		/* mc146818-like calendar */
+ /* calendar has no battery, so we ignore it here */
+ 
+ #define FRODO_TIMER	0xa0		/* 8254-like timer */
+ #define FRODO_T1_CTR	0xa0		/* counter 1 */
+ #define FRODO_T2_CTR	0xa4		/* counter 2 */
+ #define FRODO_T3_CTR	0xa8		/* counter 3 */
+ #define FRODO_T_CTRL	0xac		/* control register */
+ #define FRODO_T_PSCALE	0xb0		/* prescaler */
+ #define FRODO_T_PCOUNT	0xb4		/* precounter ? */
+ #define FRODO_T_OVCOUNT	0xb8		/* overflow counter (0, 1, 2) */
+ 
+ #define FRODO_PIO	0xc0		/* programmable I/O */
+ #define FRODO_IISR	0xc0		/* ISA Interrupt Status Register (also PIR)*/
+ #define FRODO_IISR_SERVICE	(1<<0)	/* service switch 'on' if 0 */
+ #define FRODO_IISR_ILOW		(1<<1)	/* IRQ 3,4,5 or 6 on ISA if 1 */
+ #define FRODO_IISR_IMID		(1<<2)	/* IRQ 7,9,10 or 11 on ISA if 1 */
+ #define FRODO_IISR_IHI		(1<<3)	/* IRQ 12,13,14 or 15 on ISA if 1 */
+ /* 4,5 were used for SCSI on the DN2500, 6 is unused */
+ #define FRODO_IISR_IOCHK	(1<<7)	/* ISA board asserted IOCHK if low */
+ #define FRODO_PIO_IPR	0xc4		/* input polarity register (ints 7->0) */
+ #define FRODO_PIO_IELR	0xc8		/* input edge/level register */
+ 
+ /* this is probably not used on the 4xx */
+ #define FRODO_DIAGCTL	0xd0		/* Diagnostic Control Register */
+ 
+ #define FRODO_PIC_MU	0xe0		/* upper Interrupt Mask register */
+ #define FRODO_PIC_ML	0xe4		/* lower Interrupt Mask register */
+ #define FRODO_PIC_PU	0xe8		/* upper Interrupt Pending register */
+ #define FRODO_PIC_PL	0xec		/* lower Interrupt Pending register */
+ #define FRODO_PIC_IVR	0xf8		/* Interrupt Vector register */
+ #define FRODO_PIC_ACK	0xfc		/* Interrupt Acknowledge */
+ 
+ /* manipulate interrupt registers */
+ #define FRODO_GETMASK(base)	(((u_short)(base[FRODO_PIC_MU])<<8)+base[FRODO_PIC_ML])
+ #define FRODO_SETMASK(base,val)	{		\
+     base[FRODO_PIC_MU] = (val>>8)&0xff;		\
+     base[FRODO_PIC_ML] = val & 0xff;		\
+ }
+ #define FRODO_GETPEND(base)	(((u_short)(base[FRODO_PIC_PU])<<8)+base[FRODO_PIC_PL])
+ #define FRODO_IPEND(base)	((u_char)(base[FRODO_PIC_ACK]) & 0x0f)
+ 
+ /* interrupt bits (combined regs) (bit 0 is unused) */
+ #define FRODO_PIC_ILOW		(1<<1)
+ #define FRODO_PIC_IMID		(1<<2)
+ #define FRODO_PIC_IHI		(1<<3)
+ #define FRODO_PIC_SCSIDMA	(1<<4)		/* unused */
+ #define FRODO_PIC_SCSI		(1<<5)		/* unused */
+ #define FRODO_PIC_HORIZ		(1<<6)		/* unused */
+ #define FRODO_PIC_IOCHK		(1<<7)
+ #define FRODO_PIC_CALENDAR	(1<<8)		/* unused */
+ #define FRODO_PIC_TIMER0	(1<<9)
+ #define FRODO_PIC_TIMER1	(1<<10)
+ #define FRODO_PIC_TIMER2	(1<<11)
+ #define FRODO_PIC_APCI0		(1<<12)
+ #define FRODO_PIC_APCI1		(1<<13)
+ #define FRODO_PIC_APCI2		(1<<14)
+ #define FRODO_PIC_APCI3		(1<<15)
+ 
diff -crN /sys/arch/hp300/dev/frodovar.h dev/frodovar.h
*** /sys/arch/hp300/dev/frodovar.h	Wed Dec 31 16:00:00 1969
--- dev/frodovar.h	Thu Apr 24 08:04:22 1997
***************
*** 0 ****
--- 1,59 ----
+ /*	$NetBSD$ */
+ 
+ /*
+  * Copyright (c) 1997 Michael Smith.  All rights reserved.
+  *
+  * Redistribution and use in source and binary forms, with or without
+  * modification, are permitted provided that the following conditions
+  * are met:
+  * 1. Redistributions of source code must retain the above copyright
+  *    notice, this list of conditions and the following disclaimer.
+  * 2. Redistributions in binary form must reproduce the above copyright
+  *    notice, this list of conditions and the following disclaimer in the
+  *    documentation and/or other materials provided with the distribution.
+  *
+  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+  * SUCH DAMAGE.
+  *
+  */
+ 
+ /*
+  * Autoconfiguration definitions and prototypes for the Frodo ASIC in
+  * the HP9000/4xx series.
+  */
+ 
+ /*
+  * Arguments used to attach a device to the internal i/o space.
+  */
+ struct frodo_attach_args {
+     int		fa_channel;		/* subdevice index */
+ };
+ #define	frodocf_channel	cf_loc[0];
+ 
+ /*
+  * Translate a frodo subdevice number into an address in IIO space.
+  */
+ #define FRODO_STOV(x)	IIOV(((x) * 0x20) + FRODO_BASE)
+ 
+ /* set/clear frodo interrupts */
+ extern void	frodo_imask(void *scp, u_short set, u_short clear);
+ 
+ /* establish a frodo interrupt */
+ extern void	frodo_intr_establish(void *scp, int (*func)(void *arg), void *arg, int level);
+ 
+ /* number of frodo interrupt handlers */
+ #define FRODO_NISR	16
+ 
+ 
+ 
+ 
+ 
diff -crN /sys/arch/hp300/dev/hil.c dev/hil.c
*** /sys/arch/hp300/dev/hil.c	Thu Apr  3 04:22:38 1997
--- dev/hil.c	Wed Apr 23 22:30:22 1997
***************
*** 59,64 ****
--- 59,65 ----
  #include <hp300/dev/hilioctl.h>
  #include <hp300/dev/hilvar.h>
  #include <hp300/dev/itevar.h>
+ #include <hp300/dev/kbdvar.h>
  #include <hp300/dev/kbdmap.h>

  #include <machine/cpu.h>
***************
*** 96,107 ****
  extern struct emul emul_hpux;
  #endif

! /* XXX ITE interface */
! char *kbd_keymap; 
! char *kbd_shiftmap;
! char *kbd_ctrlmap; 
! char *kbd_ctrlshiftmap;
! char **kbd_stringmap;

  /* symbolic sleep message strings */
  char hilin[] = "hilin";
--- 97,104 ----
  extern struct emul emul_hpux;
  #endif

! /* current keyboard maps */
! struct hil_kbdmap *hil_keymap = NULL;

  /* symbolic sleep message strings */
  char hilin[] = "hilin";
***************
*** 115,120 ****
--- 112,118 ----
  int	hiliddev __P((struct hil_softc *));

  void	hilint __P((int));
+ void	hil_process_key __P((u_char, u_char));
  void	hil_process_int __P((struct hil_softc *, u_char, u_char));
  void	hilevent __P((struct hil_softc *));
  void	hpuxhilevent __P((struct hil_softc *, struct hilloopdev *));
***************
*** 138,147 ****
    	struct hil_softc *hilp = &hil_softc[unit];
  	int i;

- 	/* XXX ITE interface */
- 	extern char us_keymap[], us_shiftmap[], us_ctrlmap[],
- 		    us_ctrlshiftmap[], *us_stringmap[];
- 
  #ifdef DEBUG
  	if (hildebug & HDB_FOLLOW)
  		printf("hilsoftinit(%d, %p)\n", unit, hilbase);
--- 136,141 ----
***************
*** 175,185 ****
  	 * keyboards.
  	 */
  	hilp->hl_kbdlang = KBD_DEFAULT;
! 	kbd_keymap = us_keymap;			/* XXX */
! 	kbd_shiftmap = us_shiftmap;		/* XXX */
! 	kbd_ctrlmap = us_ctrlmap;		/* XXX */
! 	kbd_ctrlshiftmap = us_ctrlshiftmap;	/* XXX */
! 	kbd_stringmap = us_stringmap;		/* XXX */
  }

  void
--- 169,175 ----
  	 * keyboards.
  	 */
  	hilp->hl_kbdlang = KBD_DEFAULT;
! 	hil_keymap = &hil_kbd_map[0];		/* default to first map */
  }

  void
***************
*** 203,209 ****
  	 */
  	hilreset(hilp);
  	hilinfo(unit);
! 	kbdenable(unit);
  }

  /* ARGSUSED */
--- 193,199 ----
  	 */
  	hilreset(hilp);
  	hilinfo(unit);
! 	hilkbdenable(unit);
  }

  /* ARGSUSED */
***************
*** 362,368 ****
  			printf("hilclose: keyboard %d cooked\n",
  			       hilp->hl_kbddev);
  #endif
! 		kbdenable(HILLOOP(dev));
  	}
  	splx(s);
  	return (0);
--- 352,358 ----
  			printf("hilclose: keyboard %d cooked\n",
  			       hilp->hl_kbddev);
  #endif
! 		hilkbdenable(HILLOOP(dev));
  	}
  	splx(s);
  	return (0);
***************
*** 833,838 ****
--- 823,886 ----
  #include "ite.h"

  void
+ hil_process_key(stat, c)
+         u_char stat, c;
+ {
+         static int capsmode = 0;
+         static int metamode = 0;
+         char code, *str;
+ 
+         switch (c & 0xFF) {
+         case KBD_CAPSLOCK:
+ 	    capsmode = !capsmode;
+ 	    return;
+ 
+         case KBD_EXT_LEFT_DOWN:
+         case KBD_EXT_RIGHT_DOWN:
+ 	    metamode = 1;
+ 	    return;
+                 
+         case KBD_EXT_LEFT_UP:
+         case KBD_EXT_RIGHT_UP:
+ 	    metamode = 0;
+ 	    return;
+         }
+ 
+         c &= KBD_CHARMASK;
+         switch ((stat>>KBD_SSHIFT) & KBD_SMASK) {
+ 
+ 	default:
+         case KBD_KEY:
+ 	    if (!capsmode) {
+ 		code = hil_keymap->kbd_keymap[c];
+ 		break;
+ 	    }
+ 	    /* FALLTHROUGH */
+ 
+         case KBD_SHIFT:
+ 	    code = hil_keymap->kbd_shiftmap[c];
+ 	    break;
+ 
+         case KBD_CTRL:
+ 	    code = hil_keymap->kbd_ctrlmap[c];
+ 	    break;
+                 
+         case KBD_CTRLSHIFT:     
+ 	    code = hil_keymap->kbd_ctrlshiftmap[c];
+ 	    break;
+         }
+ 
+         if (code == NULL && (str = hil_keymap->kbd_stringmap[c]) != NULL) {
+ 	    while (*str)
+ 		itekbdin(*str++);
+         } else {
+ 	    if (metamode)
+ 		code |= 0x80;
+ 	    itekbdin(code);
+         }
+ }
+ 
+ void
  hil_process_int(hilp, stat, c)
  	struct hil_softc *hilp;
  	u_char stat, c;
***************
*** 850,856 ****
  	case HIL_SHIFT:
  	case HIL_CTRL:
  	case HIL_CTRLSHIFT:
! 		itefilter(stat, c);
  		return;
  #endif

--- 898,904 ----
  	case HIL_SHIFT:
  	case HIL_CTRL:
  	case HIL_CTRLSHIFT:
! 		hil_process_key(stat, c);
  		return;
  #endif

***************
*** 1152,1158 ****
   */

  void
! kbdbell(unit)
  	int unit;
  {
  	struct hil_softc *hilp = &hil_softc[unit];
--- 1200,1206 ----
   */

  void
! hilkbdbell(unit)
  	int unit;
  {
  	struct hil_softc *hilp = &hil_softc[unit];
***************
*** 1161,1167 ****
  }

  void
! kbdenable(unit)
  	int unit;
  {
  	struct hil_softc *hilp = &hil_softc[unit];
--- 1209,1215 ----
  }

  void
! hilkbdenable(unit)
  	int unit;
  {
  	struct hil_softc *hilp = &hil_softc[unit];
***************
*** 1181,1187 ****
  }

  void
! kbddisable(unit)
  	int unit;
  {
  }
--- 1229,1235 ----
  }

  void
! hilkbddisable(unit)
  	int unit;
  {
  }
***************
*** 1192,1200 ****
   */

  struct	hil_dev *hilkbd_cn_device;
- char	*kbd_cn_keymap;
- char	*kbd_cn_shiftmap;
- char	*kbd_cn_ctrlmap;

  /*
   * XXX: read keyboard directly and return code.
--- 1240,1245 ----
***************
*** 1202,1209 ****
   * reading from the keyboard in the normal, interrupt driven fashion.
   */
  int
! kbdgetc(statp)
! 	int *statp;
  {
  	int c, stat;
  	int s;
--- 1247,1253 ----
   * reading from the keyboard in the normal, interrupt driven fashion.
   */
  int
! hilkbdgetc(void)
  {
  	int c, stat;
  	int s;
***************
*** 1220,1226 ****
  		;
  	c = READHILDATA(hilkbd_cn_device);
  	splx(s);
! 	*statp = stat;
  	return (c);
  }

--- 1264,1284 ----
  		;
  	c = READHILDATA(hilkbd_cn_device);
  	splx(s);
! 
!         switch ((stat >> KBD_SSHIFT) & KBD_SMASK) {
!         case KBD_SHIFT:
! 	    c = hil_keymap->kbd_shiftmap[c & KBD_CHARMASK];
! 	    break;
!         case KBD_CTRL:
! 	    c = hil_keymap->kbd_ctrlmap[c & KBD_CHARMASK];
! 	    break;
!         case KBD_KEY:
! 	    c = hil_keymap->kbd_keymap[c & KBD_CHARMASK];
! 	    break;
!         default:
! 	    c = 0;
! 	    break;
!         }
  	return (c);
  }

***************
*** 1228,1249 ****
   * Perform basic initialization of the HIL keyboard, suitable
   * for early console use.
   */
! void
! kbdcninit()
  {
  	struct hil_dev *h = HILADDR;	/* == VA (see hilreg.h) */
! 	struct kbdmap *km;
  	u_char lang;

- 	/* XXX from hil_keymaps.c */
- 	extern char us_keymap[], us_shiftmap[], us_ctrlmap[];
- 
  	hilkbd_cn_device = h;

! 	/* Default to US-ASCII keyboard. */
! 	kbd_cn_keymap = us_keymap;
! 	kbd_cn_shiftmap = us_shiftmap;
! 	kbd_cn_ctrlmap = us_ctrlmap;

  	HILWAIT(h);
  	WRITEHILCMD(h, HIL_SETARR);
--- 1286,1310 ----
   * Perform basic initialization of the HIL keyboard, suitable
   * for early console use.
   */
! int
! hilkbdinit()
  {
  	struct hil_dev *h = HILADDR;	/* == VA (see hilreg.h) */
! 	struct hil_kbdmap *km;
  	u_char lang;

  	hilkbd_cn_device = h;

!         /* see if there's a HIL keyboard there */
!         HILWAIT(h);
!         WRITEHILCMD(h, HIL_READKBDSADR);
!         HILDATAWAIT(h);
!         lang = READHILDATA(h);
!         if (lang == 0)                  /* nope, no keyboard */
!             return(0);
! 
! 	/* select default keyboard */
! 	hil_keymap = &hil_kbd_map[0];

  	HILWAIT(h);
  	WRITEHILCMD(h, HIL_SETARR);
***************
*** 1253,1267 ****
  	WRITEHILCMD(h, HIL_READKBDLANG);
  	HILDATAWAIT(h);
  	lang = READHILDATA(h);
! 	for (km = kbd_map; km->kbd_code; km++) {
  		if (km->kbd_code == lang) {
! 			kbd_cn_keymap = km->kbd_keymap;
! 			kbd_cn_shiftmap = km->kbd_shiftmap;
! 			kbd_cn_ctrlmap = km->kbd_ctrlmap;
  		}
  	}
  	HILWAIT(h);
  	WRITEHILCMD(h, HIL_INTON);
  }

  /* End of HIL console keyboard code. */
--- 1314,1327 ----
  	WRITEHILCMD(h, HIL_READKBDLANG);
  	HILDATAWAIT(h);
  	lang = READHILDATA(h);
! 	for (km = hil_kbd_map; km->kbd_code; km++) {
  		if (km->kbd_code == lang) {
! 		        hil_keymap = km;
  		}
  	}
  	HILWAIT(h);
  	WRITEHILCMD(h, HIL_INTON);
+ 	return(1);
  }

  /* End of HIL console keyboard code. */
***************
*** 1304,1317 ****
  {
    	struct hil_softc *hilp = &hil_softc[unit];
  	int id, len;
! 	struct kbdmap *km;

  	/*
  	 * Keyboard info.
  	 */
  	if (hilp->hl_kbddev) {
  		printf("hil%d: ", hilp->hl_kbddev);
! 		for (km = kbd_map; km->kbd_code; km++)
  			if (km->kbd_code == hilp->hl_kbdlang) {
  				printf("%s ", km->kbd_desc);
  				break;
--- 1364,1377 ----
  {
    	struct hil_softc *hilp = &hil_softc[unit];
  	int id, len;
! 	struct hil_kbdmap *km;

  	/*
  	 * Keyboard info.
  	 */
  	if (hilp->hl_kbddev) {
  		printf("hil%d: ", hilp->hl_kbddev);
! 		for (km = hil_kbd_map; km->kbd_code; km++)
  			if (km->kbd_code == hilp->hl_kbdlang) {
  				printf("%s ", km->kbd_desc);
  				break;
***************
*** 1448,1464 ****
  		       hilp->hl_kbdlang, db);
  #endif
  	if (hilp->hl_kbdlang != KBD_SPECIAL) {
! 		struct kbdmap *km;

! 		for (km = kbd_map; km->kbd_code; km++) {
  			if (km->kbd_code == db) {
  				hilp->hl_kbdlang = db;
! 				/* XXX */
! 				kbd_keymap = km->kbd_keymap;
! 				kbd_shiftmap = km->kbd_shiftmap;
! 				kbd_ctrlmap = km->kbd_ctrlmap;
! 				kbd_ctrlshiftmap = km->kbd_ctrlshiftmap;
! 				kbd_stringmap = km->kbd_stringmap;
  				break;
  			}
  		}
--- 1508,1519 ----
  		       hilp->hl_kbdlang, db);
  #endif
  	if (hilp->hl_kbdlang != KBD_SPECIAL) {
! 		struct hil_kbdmap *km;

! 		for (km = hil_kbd_map; km->kbd_code; km++) {
  			if (km->kbd_code == db) {
  				hilp->hl_kbdlang = db;
! 				hil_keymap = km;
  				break;
  			}
  		}
diff -crN /sys/arch/hp300/dev/hil_keymaps.c dev/hil_keymaps.c
*** /sys/arch/hp300/dev/hil_keymaps.c	Mon Mar 31 04:20:19 1997
--- dev/hil_keymaps.c	Wed Apr 23 20:37:45 1997
***************
*** 65,71 ****
  #include <sys/param.h>
  #include <hp300/dev/kbdmap.h>

! char	us_keymap[] = {
  	NULL,	'`',	'\\',	ESC,	NULL,	DEL,	NULL,	NULL,  
  	'\n',	'\t',	NULL,	NULL,	NULL,	NULL,	NULL,	NULL,  
  	NULL,	'\n',	NULL,	NULL,	NULL,	NULL,	NULL,	NULL,  
--- 65,71 ----
  #include <sys/param.h>
  #include <hp300/dev/kbdmap.h>

! char	hil_us_keymap[] = {
  	NULL,	'`',	'\\',	ESC,	NULL,	DEL,	NULL,	NULL,  
  	'\n',	'\t',	NULL,	NULL,	NULL,	NULL,	NULL,	NULL,  
  	NULL,	'\n',	NULL,	NULL,	NULL,	NULL,	NULL,	NULL,  
***************
*** 84,90 ****
  	'z',	'x',	'c',	'v',	'b',	'n',	NULL,	NULL
  };

! char	us_shiftmap[] = {
  	NULL,	'~',	'|',	DEL,	NULL,	DEL,	NULL,	NULL,
  	'\n',	'\t',	NULL,	NULL,	NULL,	NULL,	NULL,	NULL,
  	NULL,	'\n',	NULL,	NULL,	NULL,	NULL,	NULL,	NULL,
--- 84,90 ----
  	'z',	'x',	'c',	'v',	'b',	'n',	NULL,	NULL
  };

! char	hil_us_shiftmap[] = {
  	NULL,	'~',	'|',	DEL,	NULL,	DEL,	NULL,	NULL,
  	'\n',	'\t',	NULL,	NULL,	NULL,	NULL,	NULL,	NULL,
  	NULL,	'\n',	NULL,	NULL,	NULL,	NULL,	NULL,	NULL,
***************
*** 103,109 ****
  	'Z',	'X',	'C',	'V',	'B',	'N',	NULL,	NULL
  };

! char	us_ctrlmap[] = {
  	NULL,	'`',	'\034',	ESC,	NULL,	DEL,	NULL,	NULL,
  	'\n',	'\t',	NULL,	NULL,	NULL,	NULL,	NULL,	NULL,
  	NULL,	'\n',	NULL,	NULL,	NULL,	NULL,	NULL,	NULL,
--- 103,109 ----
  	'Z',	'X',	'C',	'V',	'B',	'N',	NULL,	NULL
  };

! char	hil_us_ctrlmap[] = {
  	NULL,	'`',	'\034',	ESC,	NULL,	DEL,	NULL,	NULL,
  	'\n',	'\t',	NULL,	NULL,	NULL,	NULL,	NULL,	NULL,
  	NULL,	'\n',	NULL,	NULL,	NULL,	NULL,	NULL,	NULL,
***************
*** 122,128 ****
  	'\032',	'\030',	'\003',	'\026',	'\002',	'\016',	NULL,	NULL
  };

! char	us_ctrlshiftmap[] = {
  	NULL,	'~',	'|',	DEL,	NULL,	DEL,	NULL,	NULL,
  	'\n',	'\t',	NULL,	NULL,	NULL,	NULL,	NULL,	NULL,
  	NULL,	'\n',	NULL,	NULL,	NULL,	NULL,	NULL,	NULL,
--- 122,128 ----
  	'\032',	'\030',	'\003',	'\026',	'\002',	'\016',	NULL,	NULL
  };

! char	hil_us_ctrlshiftmap[] = {
  	NULL,	'~',	'|',	DEL,	NULL,	DEL,	NULL,	NULL,
  	'\n',	'\t',	NULL,	NULL,	NULL,	NULL,	NULL,	NULL,
  	NULL,	'\n',	NULL,	NULL,	NULL,	NULL,	NULL,	NULL,
***************
*** 141,147 ****
  	'\032',	'\030',	'\003',	'\026',	'\002',	'\016',	NULL,	NULL
  };

! char	*us_stringmap[] = {
  	NULL,	NULL,	NULL,	NULL,	NULL,	NULL,	NULL,	NULL,
  	NULL,	NULL,	NULL,	NULL,	NULL,	NULL,	"\033V","\033h",
  	"\033U",NULL,	NULL,	NULL,	NULL,	NULL,	"\033K","\033J",
--- 141,147 ----
  	'\032',	'\030',	'\003',	'\026',	'\002',	'\016',	NULL,	NULL
  };

! char	*hil_us_stringmap[] = {
  	NULL,	NULL,	NULL,	NULL,	NULL,	NULL,	NULL,	NULL,
  	NULL,	NULL,	NULL,	NULL,	NULL,	NULL,	"\033V","\033h",
  	"\033U",NULL,	NULL,	NULL,	NULL,	NULL,	"\033K","\033J",
***************
*** 161,167 ****
  };

  #ifdef UK_KEYBOARD
! char	uk_keymap[] = {
  	NULL,	'`',	'<',	ESC,	NULL,	DEL,	NULL,	NULL,  
  	'\n',	'\t',	NULL,	NULL,	NULL,	NULL,	NULL,	NULL,  
  	NULL,	'\n',	NULL,	NULL,	NULL,	NULL,	NULL,	NULL,  
--- 161,167 ----
  };

  #ifdef UK_KEYBOARD
! char	hil_uk_keymap[] = {
  	NULL,	'`',	'<',	ESC,	NULL,	DEL,	NULL,	NULL,  
  	'\n',	'\t',	NULL,	NULL,	NULL,	NULL,	NULL,	NULL,  
  	NULL,	'\n',	NULL,	NULL,	NULL,	NULL,	NULL,	NULL,  
***************
*** 180,186 ****
  	'z',	'x',	'c',	'v',	'b',	'n',	NULL,	NULL
  };

! char	uk_shiftmap[] = {
  	NULL,	'~',	'>',	DEL,	NULL,	DEL,	NULL,	NULL,
  	'\n',	'\t',	NULL,	NULL,	NULL,	NULL,	NULL,	NULL,
  	NULL,	'\n',	NULL,	NULL,	NULL,	NULL,	NULL,	NULL,
--- 180,186 ----
  	'z',	'x',	'c',	'v',	'b',	'n',	NULL,	NULL
  };

! char	hil_uk_shiftmap[] = {
  	NULL,	'~',	'>',	DEL,	NULL,	DEL,	NULL,	NULL,
  	'\n',	'\t',	NULL,	NULL,	NULL,	NULL,	NULL,	NULL,
  	NULL,	'\n',	NULL,	NULL,	NULL,	NULL,	NULL,	NULL,
***************
*** 199,205 ****
  	'Z',	'X',	'C',	'V',	'B',	'N',	NULL,	NULL
  };

! char	uk_ctrlmap[] = {
  	NULL,	'`',	'<',	ESC,	NULL,	DEL,	NULL,	NULL,
  	'\n',	'\t',	NULL,	NULL,	NULL,	NULL,	NULL,	NULL,
  	NULL,	'\n',	NULL,	NULL,	NULL,	NULL,	NULL,	NULL,
--- 199,205 ----
  	'Z',	'X',	'C',	'V',	'B',	'N',	NULL,	NULL
  };

! char	hil_uk_ctrlmap[] = {
  	NULL,	'`',	'<',	ESC,	NULL,	DEL,	NULL,	NULL,
  	'\n',	'\t',	NULL,	NULL,	NULL,	NULL,	NULL,	NULL,
  	NULL,	'\n',	NULL,	NULL,	NULL,	NULL,	NULL,	NULL,
***************
*** 218,224 ****
  	'\032',	'\030',	'\003',	'\026',	'\002',	'\016',	NULL,	NULL
  };

! char	uk_ctrlshiftmap[] = {
  	NULL,	'~',	'>',	DEL,	NULL,	DEL,	NULL,	NULL,
  	'\n',	'\t',	NULL,	NULL,	NULL,	NULL,	NULL,	NULL,
  	NULL,	'\n',	NULL,	NULL,	NULL,	NULL,	NULL,	NULL,
--- 218,224 ----
  	'\032',	'\030',	'\003',	'\026',	'\002',	'\016',	NULL,	NULL
  };

! char	hil_uk_ctrlshiftmap[] = {
  	NULL,	'~',	'>',	DEL,	NULL,	DEL,	NULL,	NULL,
  	'\n',	'\t',	NULL,	NULL,	NULL,	NULL,	NULL,	NULL,
  	NULL,	'\n',	NULL,	NULL,	NULL,	NULL,	NULL,	NULL,
***************
*** 239,245 ****
  #endif

  #ifdef SE_KEYBOARD
! char	se_keymap[] = {
  	NULL,	'<',	'\'',	ESC,	NULL,	DEL,	NULL,	NULL,  
  	'\n',	'\t',	NULL,	NULL,	NULL,	NULL,	NULL,	NULL,  
  	NULL,	'\n',	NULL,	NULL,	NULL,	NULL,	NULL,	NULL,  
--- 239,245 ----
  #endif

  #ifdef SE_KEYBOARD
! char	hil_se_keymap[] = {
  	NULL,	'<',	'\'',	ESC,	NULL,	DEL,	NULL,	NULL,  
  	'\n',	'\t',	NULL,	NULL,	NULL,	NULL,	NULL,	NULL,  
  	NULL,	'\n',	NULL,	NULL,	NULL,	NULL,	NULL,	NULL,  
***************
*** 258,264 ****
  	'z',	'x',	'c',	'v',	'b',	'n',	NULL,	NULL
  };

! char	se_shiftmap[] = {
  	NULL,	'>',	'*',	DEL,	NULL,	DEL,	NULL,	NULL,
  	'\n',	'\t',	NULL,	NULL,	NULL,	NULL,	NULL,	NULL,
  	NULL,	'\n',	NULL,	NULL,	NULL,	NULL,	NULL,	NULL,
--- 258,264 ----
  	'z',	'x',	'c',	'v',	'b',	'n',	NULL,	NULL
  };

! char	hil_se_shiftmap[] = {
  	NULL,	'>',	'*',	DEL,	NULL,	DEL,	NULL,	NULL,
  	'\n',	'\t',	NULL,	NULL,	NULL,	NULL,	NULL,	NULL,
  	NULL,	'\n',	NULL,	NULL,	NULL,	NULL,	NULL,	NULL,
***************
*** 277,283 ****
  	'Z',	'X',	'C',	'V',	'B',	'N',	NULL,	NULL
  };

! char	se_ctrlmap[] = {
  	NULL,	'`',	'\034',	ESC,	NULL,	DEL,	NULL,	NULL,
  	'\n',	'\t',	NULL,	NULL,	NULL,	NULL,	NULL,	NULL,
  	NULL,	'\n',	NULL,	NULL,	NULL,	NULL,	NULL,	NULL,
--- 277,283 ----
  	'Z',	'X',	'C',	'V',	'B',	'N',	NULL,	NULL
  };

! char	hil_se_ctrlmap[] = {
  	NULL,	'`',	'\034',	ESC,	NULL,	DEL,	NULL,	NULL,
  	'\n',	'\t',	NULL,	NULL,	NULL,	NULL,	NULL,	NULL,
  	NULL,	'\n',	NULL,	NULL,	NULL,	NULL,	NULL,	NULL,
***************
*** 296,302 ****
  	'\032',	'\030',	'\003',	'\026',	'\002',	'\016',	NULL,	NULL
  };

! char	se_ctrlshiftmap[] = {
  	NULL,	'~',	'|',	DEL,	NULL,	DEL,	NULL,	NULL,
  	'\n',	'\t',	NULL,	NULL,	NULL,	NULL,	NULL,	NULL,
  	NULL,	'\n',	NULL,	NULL,	NULL,	NULL,	NULL,	NULL,
--- 296,302 ----
  	'\032',	'\030',	'\003',	'\026',	'\002',	'\016',	NULL,	NULL
  };

! char	hil_se_ctrlshiftmap[] = {
  	NULL,	'~',	'|',	DEL,	NULL,	DEL,	NULL,	NULL,
  	'\n',	'\t',	NULL,	NULL,	NULL,	NULL,	NULL,	NULL,
  	NULL,	'\n',	NULL,	NULL,	NULL,	NULL,	NULL,	NULL,
***************
*** 320,337 ****
   * The keyboard map table.
   * Lookup is by hardware returned language code.
   */
! struct kbdmap kbd_map[] = {
  	{ KBD_US, "US ASCII",
! 	    us_keymap, us_shiftmap, us_ctrlmap, us_ctrlshiftmap, us_stringmap },

  #ifdef UK_KEYBOARD
  	{ KBD_UK,  "United Kingdom",
! 	    uk_keymap, uk_shiftmap, uk_ctrlmap, uk_ctrlshiftmap, us_stringmap },
  #endif

  #ifdef SE_KEYBOARD
  	{ KBD_SE,  "Swedish",
! 	    se_keymap, se_shiftmap, se_ctrlmap, se_ctrlshiftmap, us_stringmap },
  #endif

  	{ 0,  NULL, NULL,  NULL,  NULL,  NULL, NULL },
--- 320,340 ----
   * The keyboard map table.
   * Lookup is by hardware returned language code.
   */
! struct hil_kbdmap hil_kbd_map[] = {
  	{ KBD_US, "US ASCII",
! 	  hil_us_keymap, hil_us_shiftmap, hil_us_ctrlmap, 
! 	  hil_us_ctrlshiftmap, hil_us_stringmap },

  #ifdef UK_KEYBOARD
  	{ KBD_UK,  "United Kingdom",
! 	  hil_uk_keymap, hil_uk_shiftmap, hil_uk_ctrlmap, 
! 	  hil_uk_ctrlshiftmap, hil_us_stringmap },
  #endif

  #ifdef SE_KEYBOARD
  	{ KBD_SE,  "Swedish",
! 	  hil_se_keymap, hil_se_shiftmap, hil_se_ctrlmap, 
! 	  hil_se_ctrlshiftmap, hil_us_stringmap },
  #endif

  	{ 0,  NULL, NULL,  NULL,  NULL,  NULL, NULL },
diff -crN /sys/arch/hp300/dev/hilvar.h dev/hilvar.h
*** /sys/arch/hp300/dev/hilvar.h	Wed Apr  2 04:24:33 1997
--- dev/hilvar.h	Wed Apr 23 22:30:44 1997
***************
*** 119,137 ****
  #define KBD_AR2		0x04		/* keyboard auto-repeat rate 2 */

  #ifdef _KERNEL
- void	kbdbell __P((int));
- void	kbdenable __P((int));
- void	kbddisable __P((int));
- int	kbdgetc __P((int *));
- void	kbdcninit __P((void));
- 
- int	kbdnmi __P((void));
- 
  void	hilsoftinit __P((int, struct hil_dev *));
  void	hilinit __P((int, struct hil_dev *));

  void	send_hil_cmd __P((struct hil_dev *, u_char,
! 				u_char *, u_char, u_char *));
  void	send_hildev_cmd __P((struct hil_softc *, char, char));

  void	polloff __P((struct hil_dev *));
--- 119,131 ----
  #define KBD_AR2		0x04		/* keyboard auto-repeat rate 2 */

  #ifdef _KERNEL
  void	hilsoftinit __P((int, struct hil_dev *));
  void	hilinit __P((int, struct hil_dev *));

+ int	kbdnmi __P((void));
+ 
  void	send_hil_cmd __P((struct hil_dev *, u_char,
!                                 u_char *, u_char, u_char *));
  void	send_hildev_cmd __P((struct hil_softc *, char, char));

  void	polloff __P((struct hil_dev *));
diff -crN /sys/arch/hp300/dev/ite.c dev/ite.c
*** /sys/arch/hp300/dev/ite.c	Mon Mar 31 04:20:25 1997
--- dev/ite.c	Wed Apr 23 22:24:30 1997
***************
*** 64,73 ****

  #include <hp300/dev/grfioctl.h>
  #include <hp300/dev/grfvar.h>
- #include <hp300/dev/hilioctl.h>
- #include <hp300/dev/hilvar.h>
  #include <hp300/dev/itevar.h>
! #include <hp300/dev/kbdmap.h>

  /* prototypes for devsw entry points */
  cdev_decl(ite);
--- 64,71 ----

  #include <hp300/dev/grfioctl.h>
  #include <hp300/dev/grfvar.h>
  #include <hp300/dev/itevar.h>
! #include <hp300/dev/kbdvar.h>

  /* prototypes for devsw entry points */
  cdev_decl(ite);
***************
*** 75,80 ****
--- 73,81 ----
  #define set_attr(ip, attr)	((ip)->attribute |= (attr))
  #define clr_attr(ip, attr)	((ip)->attribute &= ~(attr))

+ #define        ESC     '\033'
+ #define        DEL     '\177'
+ 
  /*
   * # of chars are output in a single itestart() call.
   * If this is too big, user processes will be blocked out for
***************
*** 84,89 ****
--- 85,91 ----
  int	iteburst = 64;

  struct  ite_data *kbd_ite = NULL;
+ struct	kbdsw *ite_kbd = NULL;		/* current keyboard */

  int	itematch __P((struct device *, struct cfdata *, void *));
  void	iteattach __P((struct device *, struct device *, void *));
***************
*** 162,167 ****
--- 164,175 ----
  		 * the console probe, so we have to fixup cn_dev here.
  		 */
  		cn_tab->cn_dev = makedev(ite_major(), self->dv_unit);
+ 
+                 /* 
+                  * Mention the keyboard type, if we have one.
+                  */
+                 if (ite_kbd != NULL)
+                     printf(", %s keyboard.", ite_kbd->kbdname);
  	} else {
  		ite->sc_data =
  		    (struct ite_data *)malloc(sizeof(struct ite_data),
***************
*** 215,221 ****

  	if (kbd_ite == NULL || kbd_ite == ip) {
  		kbd_ite = ip;
! 		kbdenable(0);		/* XXX */
  	}

  	iteinit(ip);
--- 223,230 ----

  	if (kbd_ite == NULL || kbd_ite == ip) {
  		kbd_ite = ip;
! 		if (ite_kbd != NULL)
! 		    ite_kbd->kbdenable(0);		/* XXX */
  	}

  	iteinit(ip);
***************
*** 486,550 ****

  }

  void
! itefilter(stat, c)
! 	char stat, c;
  {
- 	static int capsmode = 0;
- 	static int metamode = 0;
- 	char code, *str;
  	struct tty *kbd_tty = kbd_ite->tty;

  	if (kbd_tty == NULL)
  		return;

! 	switch (c & 0xFF) {
! 	case KBD_CAPSLOCK:
! 		capsmode = !capsmode;
! 		return;
! 
! 	case KBD_EXT_LEFT_DOWN:
! 	case KBD_EXT_RIGHT_DOWN:
! 		metamode = 1;
! 		return;
! 		
! 	case KBD_EXT_LEFT_UP:
! 	case KBD_EXT_RIGHT_UP:
! 		metamode = 0;
! 		return;
! 	}
! 
! 	c &= KBD_CHARMASK;
! 	switch ((stat>>KBD_SSHIFT) & KBD_SMASK) {
! 	default:
! 	case KBD_KEY:
! 	        if (!capsmode) {
! 			code = kbd_keymap[c];
! 			break;
! 		}
! 		/* FALLTHROUGH */
! 
! 	case KBD_SHIFT:
! 		code = kbd_shiftmap[c];
! 		break;
! 
! 	case KBD_CTRL:
! 		code = kbd_ctrlmap[c];
! 		break;
! 		
! 	case KBD_CTRLSHIFT:	
! 		code = kbd_ctrlshiftmap[c];
! 		break;
!         }
! 
! 	if (code == '\0' && (str = kbd_stringmap[c]) != '\0') {
! 		while (*str)
! 			(*linesw[kbd_tty->t_line].l_rint)(*str++, kbd_tty);
! 	} else {
! 		if (metamode)
! 			code |= 0x80;
! 		(*linesw[kbd_tty->t_line].l_rint)(code, kbd_tty);
! 	}
  }

  void
--- 495,513 ----

  }

+ /*
+  * Take a character from a keyboard handler, pass it up.
+  */
  void
! itekbdin(c)
!         char c;
  {
  	struct tty *kbd_tty = kbd_ite->tty;

  	if (kbd_tty == NULL)
  		return;

! 	(*linesw[kbd_tty->t_line].l_rint)(c, kbd_tty);
  }

  void
***************
*** 792,799 ****
  		break;

  	case CTRL('G'):
! 		if (ip == kbd_ite)
! 			kbdbell(0);	/* XXX */
  		break;

  	case ESC:
--- 755,762 ----
  		break;

  	case CTRL('G'):
! 		if ((ip == kbd_ite) && (ite_kbd != NULL))
! 			ite_kbd->kbdbell(0);	/* XXX */
  		break;

  	case ESC:
***************
*** 945,950 ****
--- 908,914 ----
  	struct itesw *isw;
  {
  	struct ite_data *ip = &ite_cn;
+ 	int i;

  	/*
  	 * Set up required ite data and initialize ite.
***************
*** 955,965 ****
  	ip->attrbuf = ite_console_attributes;
  	iteinit(ip);

! 	/*
! 	 * Initialize the console keyboard.
! 	 */
! 	kbdcninit();
! 
  	kbd_ite = ip;		/* XXX */
  }

--- 919,933 ----
  	ip->attrbuf = ite_console_attributes;
  	iteinit(ip);

!         /*
!          * Search for a keyboard
!          */
!         for (i = 0; kbdsw[i].kbdinit != NULL; i++) {
!             if (kbdsw[i].kbdinit()) {   /* found one? */
!                 ite_kbd = &kbdsw[i];
!                 break;
!             }
!         }
  	kbd_ite = ip;		/* XXX */
  }

***************
*** 968,992 ****
  itecngetc(dev)
  	dev_t dev;
  {
! 	int c;
! 	int stat;
! 
! 	c = kbdgetc(&stat);
! 	switch ((stat >> KBD_SSHIFT) & KBD_SMASK) {
! 	case KBD_SHIFT:
! 		c = kbd_cn_shiftmap[c & KBD_CHARMASK];
! 		break;
! 	case KBD_CTRL:
! 		c = kbd_cn_ctrlmap[c & KBD_CHARMASK];
! 		break;
! 	case KBD_KEY:
! 		c = kbd_cn_keymap[c & KBD_CHARMASK];
! 		break;
! 	default:
! 		c = 0;
! 		break;
! 	}
! 	return(c);
  }

  /* ARGSUSED */
--- 936,944 ----
  itecngetc(dev)
  	dev_t dev;
  {
! 	if (ite_kbd)
! 	    return(ite_kbd->kbdgetc());
! 	return(0);
  }

  /* ARGSUSED */
diff -crN /sys/arch/hp300/dev/itevar.h dev/itevar.h
*** /sys/arch/hp300/dev/itevar.h	Mon Mar 31 04:20:26 1997
--- dev/itevar.h	Wed Apr 23 22:24:23 1997
***************
*** 170,192 ****
  #define ERASE_CURSOR    0x06
  #define MOVE_CURSOR	0x07

- #define KBD_SSHIFT	4		/* bits to shift status */
- #define	KBD_CHARMASK	0x7F
- 
- /* keyboard status */
- #define	KBD_SMASK	0xF		/* service request status mask */
- #define	KBD_CTRLSHIFT	0x8		/* key + CTRL + SHIFT */
- #define	KBD_CTRL	0x9		/* key + CTRL */
- #define	KBD_SHIFT	0xA		/* key + SHIFT */
- #define	KBD_KEY		0xB		/* key only */
- 
- #define KBD_CAPSLOCK    0x18
- 
- #define KBD_EXT_LEFT_DOWN     0x12
- #define KBD_EXT_LEFT_UP       0x92
- #define KBD_EXT_RIGHT_DOWN    0x13
- #define KBD_EXT_RIGHT_UP      0x93
- 
  #define	TABSIZE		8
  #define	TABEND(ip)	((ip)->tty->t_winsize.ws_col - TABSIZE)

--- 170,175 ----
***************
*** 201,207 ****
  void	ite_attach_grf __P((int, int));
  int	iteon __P((struct ite_data *, int));
  void	iteoff __P((struct ite_data *, int));
! void	itefilter __P((char, char));
  void	itecninit __P((struct grf_data *, struct itesw *));
  int	itecngetc __P((dev_t));
  void	itecnputc __P((dev_t, int));
--- 184,190 ----
  void	ite_attach_grf __P((int, int));
  int	iteon __P((struct ite_data *, int));
  void	iteoff __P((struct ite_data *, int));
! void	itekbdin __P((char));
  void	itecninit __P((struct grf_data *, struct itesw *));
  int	itecngetc __P((dev_t));
  void	itecnputc __P((dev_t, int));
diff -crN /sys/arch/hp300/dev/kbdconf.c dev/kbdconf.c
*** /sys/arch/hp300/dev/kbdconf.c	Wed Dec 31 16:00:00 1969
--- dev/kbdconf.c	Wed Apr 23 20:15:03 1997
***************
*** 0 ****
--- 1,60 ----
+ /*	$NetBSD$ */
+ 
+ /*
+  * Copyright (c) 1997 Michael Smith.  All rights reserved.
+  * Inspired by code by Jason R. Thorpe.
+  *
+  * Redistribution and use in source and binary forms, with or without
+  * modification, are permitted provided that the following conditions
+  * are met:
+  * 1. Redistributions of source code must retain the above copyright
+  *    notice, this list of conditions and the following disclaimer.
+  * 2. Redistributions in binary form must reproduce the above copyright
+  *    notice, this list of conditions and the following disclaimer in the
+  *    documentation and/or other materials provided with the distribution.
+  *
+  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+  * SUCH DAMAGE.
+  *
+  */
+ 
+ /*
+  * Keyboard "auto" configuration.  Oh, for linker sets.
+  */
+ 
+ #include "dnkbd.h"
+ 
+ #include <sys/param.h>
+ 
+ #include <hp300/dev/kbdvar.h>
+ 
+ /*
+  * The keyboard driver is selected on a first-come, first-served basis.
+  * Both the Domain and HIL keyboards can be reliably detected, but if
+  * neither are plugged in, no keyboard will be enabled (how could we 
+  * guess in advance which one you would choose?).
+  *
+  * The HIL driver is always present, and the HIL keyboard is the default,
+  * wheras the Domain keyboard support requires the dnkbd driver.
+  */
+ 
+ struct kbdsw kbdsw[] = {
+     {"HIL", hilkbdgetc, hilkbdbell, hilkbdinit, hilkbdenable, hilkbddisable},
+ #if NDNKBD > 0
+     /* use the HIL beeper until we work out how to beep the Domain keyboard */
+     {"Domain", dnkbdgetc, hilkbdbell, dnkbdinit, dnkbdenable, dnkbddisable},
+ #endif
+     {"No" , NULL, NULL, NULL, NULL, NULL}
+ };
+ 
+ 
+ 	
diff -crN /sys/arch/hp300/dev/kbdmap.h dev/kbdmap.h
*** /sys/arch/hp300/dev/kbdmap.h	Mon Oct 14 09:05:51 1996
--- dev/kbdmap.h	Thu Apr 24 00:44:41 1997
***************
*** 35,44 ****
   *	@(#)kbdmap.h	8.1 (Berkeley) 6/10/93
   */

  #define	ESC	'\033'
  #define	DEL	'\177'

! struct kbdmap {
  	int	kbd_code;
  	char	*kbd_desc;
  	char	*kbd_keymap;
--- 35,48 ----
   *	@(#)kbdmap.h	8.1 (Berkeley) 6/10/93
   */

+ /*
+  * HIL keyboard map definitions
+  */
+ 
  #define	ESC	'\033'
  #define	DEL	'\177'

! struct hil_kbdmap {
  	int	kbd_code;
  	char	*kbd_desc;
  	char	*kbd_keymap;
***************
*** 56,73 ****

  #define KBD_DEFAULT	KBD_US		/* default type */

! #ifdef _KERNEL
! /* XXX: ITE interface */
! extern	char *kbd_keymap;
! extern	char *kbd_shiftmap;
! extern	char *kbd_ctrlmap;
! extern	char *kbd_ctrlshiftmap;
! extern	char **kbd_stringmap;
! 
! /* XXX: itecngetc() interface */
! extern	char *kbd_cn_keymap;
! extern	char *kbd_cn_shiftmap;
! extern	char *kbd_cn_ctrlmap;

! extern struct kbdmap kbd_map[];
  #endif
--- 60,82 ----

  #define KBD_DEFAULT	KBD_US		/* default type */

! #define KBD_SSHIFT	4		/* bits to shift status */
! #define	KBD_CHARMASK	0x7F

! /* keyboard status */
! #define	KBD_SMASK	0xF		/* service request status mask */
! #define	KBD_CTRLSHIFT	0x8		/* key + CTRL + SHIFT */
! #define	KBD_CTRL	0x9		/* key + CTRL */
! #define	KBD_SHIFT	0xA		/* key + SHIFT */
! #define	KBD_KEY		0xB		/* key only */
! 
! #define KBD_CAPSLOCK    0x18
! 
! #define KBD_EXT_LEFT_DOWN     0x12
! #define KBD_EXT_LEFT_UP       0x92
! #define KBD_EXT_RIGHT_DOWN    0x13
! #define KBD_EXT_RIGHT_UP      0x93
! 
! #ifdef _KERNEL
! extern struct hil_kbdmap hil_kbd_map[];
  #endif
diff -crN /sys/arch/hp300/dev/kbdvar.h dev/kbdvar.h
*** /sys/arch/hp300/dev/kbdvar.h	Wed Dec 31 16:00:00 1969
--- dev/kbdvar.h	Wed Apr 23 20:20:52 1997
***************
*** 0 ****
--- 1,61 ----
+ /*	$NetBSD$ */
+ 
+ /*
+  * Copyright (c) 1997 Michael Smith.  All rights reserved.
+  * Inspired by code by Jason R. Thorpe.
+  *
+  * Redistribution and use in source and binary forms, with or without
+  * modification, are permitted provided that the following conditions
+  * are met:
+  * 1. Redistributions of source code must retain the above copyright
+  *    notice, this list of conditions and the following disclaimer.
+  * 2. Redistributions in binary form must reproduce the above copyright
+  *    notice, this list of conditions and the following disclaimer in the
+  *    documentation and/or other materials provided with the distribution.
+  *
+  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+  * SUCH DAMAGE.
+  *
+  */
+ 
+ /*
+  * Keyboard driver interface, prototypes and defines.
+  */
+ 
+ struct kbdsw 
+ {
+     const char	*kbdname;			/* keyboard name */
+     int		(*kbdgetc)(void);		/* return a character in polled mode */
+     void	(*kbdbell)(int unit);		/* go beep */
+     int		(*kbdinit)(void);		/* probe for/init keyboard, returns 1 if present */
+     void	(*kbdenable)(int unit);		/* allow keyboard to give characters to ite */
+     void	(*kbddisable)(int unit);	/* stop keyboard giving characters to ite */
+ };
+ 
+ extern struct kbdsw kbdsw[];			/* array of keyboard drivers */
+ 
+ /* XXX HIL is not optional */
+ extern int	hilkbdgetc(void);
+ extern void	hilkbdbell(int unit);
+ extern int	hilkbdinit(void);
+ extern void	hilkbdenable(int unit);
+ extern void	hilkbddisable(int unit);
+ 
+ /* Apollo keyboard */
+ #if NDNKBD > 0
+ extern int	dnkbdgetc(void);
+ extern void	dnkbdbell(int unit);		/* XXX not currently working */
+ extern int	dnkbdinit(void);
+ extern void	dnkbdenable(int unit);
+ extern void	dnkbddisable(int unit);
+ #endif
+ 
diff -crN /sys/arch/hp300/hp300/conf.c hp300/conf.c
*** /sys/arch/hp300/hp300/conf.c	Tue Apr  1 04:18:14 1997
--- hp300/conf.c	Thu Apr 24 00:12:06 1997
***************
*** 98,103 ****
--- 98,110 ----
  	(dev_type_stop((*))) enodev, 0, dev_init(c,n,poll), \
  	dev_init(c,n,mmap) }

+ /* open, close, read, ioctl, poll -- XXX what is this? */
+ #define	cdev_dnkbd_init(c,n) { \
+ 	dev_init(c,n,open), dev_init(c,n,close), dev_init(c,n,read), \
+ 	(dev_type_write((*))) nullop, dev_init(c,n,ioctl), \
+ 	(dev_type_stop((*))) enodev, 0, dev_init(c,n,poll), \
+ 	(dev_type_mmap((*))) enodev }
+ 
  cdev_decl(cn);
  cdev_decl(ctty);
  #define	mmread	mmrw
***************
*** 121,126 ****
--- 128,137 ----
  cdev_decl(ppi);
  #include "dca.h"
  cdev_decl(dca);
+ #include "apci.h"
+ cdev_decl(apci);
+ #include "dnkbd.h"
+ cdev_decl(dnkbd);
  #include "ite.h"
  cdev_decl(ite);
  /* XXX shouldn't this be optional? */
***************
*** 172,177 ****
--- 183,190 ----
  	cdev_lkm_dummy(),		/* 28 */
  	cdev_lkm_dummy(),		/* 29 */
  	cdev_lkm_dummy(),		/* 30 */
+ 	cdev_tty_init(NAPCI,apci),	/* 31: Apollo serial */
+ 	cdev_dnkbd_init(NDNKBD,dnkbd),	/* 32: Domain keyboard */
  };
  int	nchrdev = sizeof(cdevsw) / sizeof(cdevsw[0]);

diff -crN /sys/arch/hp300/hp300/genassym.cf hp300/genassym.cf
*** /sys/arch/hp300/hp300/genassym.cf	Sun Mar 16 04:22:38 1997
--- hp300/genassym.cf	Wed Apr 23 19:57:11 1997
***************
*** 97,104 ****
--- 97,107 ----
  define	HP_360			HP_360
  define	HP_370			HP_370
  define	HP_340			HP_340
+ define	HP_345			HP_345
  define	HP_375			HP_375
  define	HP_380			HP_380
+ define	HP_400			HP_400
+ define	HP_425			HP_425
  define	HP_433			HP_433

  # values for ectype
diff -crN /sys/arch/hp300/hp300/hpux_machdep.c hp300/hpux_machdep.c
*** /sys/arch/hp300/hp300/hpux_machdep.c	Thu Apr  3 04:22:42 1997
--- hp300/hpux_machdep.c	Thu Apr 24 09:39:25 1997
***************
*** 117,127 ****
  	{ HP_320,	"320" },
  	{ HP_330,	"330" },	/* includes 318 and 319 */
  	{ HP_340,	"340" },
  	{ HP_350,	"350" },
  	{ HP_360,	"360" },
  	{ HP_370,	"370" },
  	{ HP_375,	"375" },	/* includes 345 and 400 */
! 	{ HP_380,	"380" },	/* includes 425 */
  	{ HP_433,	"433" },
  	{     -1,	"3?0" },	/* unknown system (???) */
  };
--- 117,130 ----
  	{ HP_320,	"320" },
  	{ HP_330,	"330" },	/* includes 318 and 319 */
  	{ HP_340,	"340" },
+ 	{ HP_345,	"345" },	/* XXX not used yet */
  	{ HP_350,	"350" },
  	{ HP_360,	"360" },
  	{ HP_370,	"370" },
  	{ HP_375,	"375" },	/* includes 345 and 400 */
! 	{ HP_380,	"380" },
! 	{ HP_400,	"400" },	/* XXX not used yet */
! 	{ HP_425,	"425" },
  	{ HP_433,	"433" },
  	{     -1,	"3?0" },	/* unknown system (???) */
  };
***************
*** 261,272 ****
--- 264,278 ----
  		return (HPUX_SYSCONF_CPUM020);

  	case HP_340:
+ 	case HP_345:
  	case HP_360:
  	case HP_370:
  	case HP_375:
+ 	case HP_400:
  		return (HPUX_SYSCONF_CPUM030);

  	case HP_380:
+ 	case HP_425:
  	case HP_433:
  		return (HPUX_SYSCONF_CPUM040);

diff -crN /sys/arch/hp300/hp300/hpux_machdep.c~ hp300/hpux_machdep.c~
*** /sys/arch/hp300/hp300/hpux_machdep.c~	Wed Dec 31 16:00:00 1969
--- hp300/hpux_machdep.c~	Wed Apr 23 19:58:26 1997
***************
*** 0 ****
--- 1,800 ----
+ /*	$NetBSD: hpux_machdep.c,v 1.12 1997/04/02 22:41:34 scottr Exp $	*/
+ 
+ /*
+  * Copyright (c) 1995, 1996, 1997 Jason R. Thorpe.  All rights reserved.
+  * Copyright (c) 1988 University of Utah.
+  * Copyright (c) 1990, 1993
+  *	The Regents of the University of California.  All rights reserved.
+  *
+  * This code is derived from software contributed to Berkeley by
+  * the Systems Programming Group of the University of Utah Computer
+  * Science Department.
+  *
+  * Redistribution and use in source and binary forms, with or without
+  * modification, are permitted provided that the following conditions
+  * are met:
+  * 1. Redistributions of source code must retain the above copyright
+  *    notice, this list of conditions and the following disclaimer.
+  * 2. Redistributions in binary form must reproduce the above copyright
+  *    notice, this list of conditions and the following disclaimer in the
+  *    documentation and/or other materials provided with the distribution.
+  * 3. All advertising materials mentioning features or use of this software
+  *    must display the following acknowledgement:
+  *	This product includes software developed by the University of
+  *	California, Berkeley and its contributors.
+  * 4. The name of the author may not be used to endorse or promote products
+  *    derived from this software without specific prior written permission.
+  *
+  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+  * SUCH DAMAGE.
+  */
+ 
+ /*
+  * Machinde-dependent bits for HP-UX binary compatibility.
+  */
+ 
+ #include <sys/param.h>
+ #include <sys/systm.h>
+ #include <sys/buf.h>
+ #include <sys/conf.h>
+ #include <sys/device.h>
+ #include <sys/exec.h>
+ #include <sys/file.h>
+ #include <sys/filedesc.h>
+ #include <sys/ioctl.h>
+ #include <sys/ipc.h>
+ #include <sys/kernel.h>
+ #include <sys/malloc.h>
+ #include <sys/mman.h>
+ #include <sys/mount.h>
+ #include <sys/namei.h>
+ #include <sys/namei.h>
+ #include <sys/poll.h> 
+ #include <sys/proc.h> 
+ #include <sys/ptrace.h>
+ #include <sys/signalvar.h>
+ #include <sys/stat.h>
+ #include <sys/syslog.h>
+ #include <sys/tty.h>
+ #include <sys/user.h>
+ #include <sys/vnode.h>
+ #include <sys/wait.h> 
+ 
+ #include <machine/cpu.h>
+ #include <machine/reg.h>
+ #include <machine/psl.h>
+ #include <machine/vmparam.h>
+ 
+ #include <vm/vm.h>
+ #include <vm/vm_param.h>
+ #include <vm/vm_map.h> 
+ 
+ #include <arch/hp300/dev/grfreg.h>
+ #include <arch/hp300/dev/grfioctl.h>
+ #include <arch/hp300/dev/grfvar.h>
+ #include <arch/hp300/dev/hilreg.h>
+ #include <arch/hp300/dev/hilioctl.h>
+ #include <arch/hp300/dev/hilvar.h>
+ 
+ #include <sys/syscallargs.h>
+ 
+ #include <compat/hpux/hpux.h>
+ #include <compat/hpux/hpux_sig.h>
+ #include <compat/hpux/hpux_util.h>
+ #include <compat/hpux/hpux_syscall.h>
+ #include <compat/hpux/hpux_syscallargs.h>
+ 
+ #include <machine/hpux_machdep.h>
+ 
+ extern	short exframesize[];
+ 
+ #define NHIL	1	/* XXX */
+ #include "grf.h"
+ 
+ #if NGRF > 0
+ extern	int grfopen __P((dev_t dev, int oflags, int devtype, struct proc *p));
+ #endif
+ 
+ #if NHIL > 0
+ extern	int hilopen __P((dev_t dev, int oflags, int devtype, struct proc *p));
+ #endif
+ 
+ struct valtostr {
+ 	int	val;
+ 	const char *str;
+ };
+ 
+ static struct valtostr machine_table[] = {
+ 	{ HP_320,	"320" },
+ 	{ HP_330,	"330" },	/* includes 318 and 319 */
+ 	{ HP_340,	"340" },
+ 	{ HP_345,	"345" },	/* XXX not used yet */
+ 	{ HP_350,	"350" },
+ 	{ HP_360,	"360" },
+ 	{ HP_370,	"370" },
+ 	{ HP_375,	"375" },	/* includes 345 and 400 */
+ 	{ HP_380,	"380" },
+ 	{ HP_400,	"400" },	/* XXX not used yet */
+ 	{ HP_425,	"425" },
+ 	{ HP_433,	"433" },
+ 	{     -1,	"3?0" },	/* unknown system (???) */
+ };
+ 
+ /*
+  * 6.0 and later context.
+  * XXX what are the HP-UX "localroot" semantics?  Should we handle
+  * XXX diskless systems here?
+  */
+ static struct valtostr context_table[] = {
+ 	{ FPU_68040,
+     "standalone HP-MC68040 HP-MC68881 HP-MC68020 HP-MC68010 localroot default"
+ 	},
+ 	{ FPU_68881,
+     "standalone HP-MC68881 HP-MC68020 HP-MC68010 localroot default"
+ 	},
+ 	{ FPU_NONE,
+     "standalone HP-MC68020 HP-MC68010 localroot default"
+ 	},
+ 	{ 0, NULL },
+ };
+ 
+ #define UOFF(f)		((int)&((struct user *)0)->f)
+ #define HPUOFF(f)	((int)&((struct hpux_user *)0)->f)
+ 
+ /* simplified FP structure */
+ struct bsdfp {
+ 	int save[54];
+ 	int reg[24];
+ 	int ctrl[3];
+ };
+ 
+ /*
+  * m68k-specific setup for HP-UX executables.
+  * XXX m68k/m68k/hpux_machdep.c?
+  */
+ int
+ hpux_cpu_makecmds(p, epp)
+ 	struct proc *p;
+ 	struct exec_package *epp;
+ {
+ 	/* struct hpux_exec *hpux_ep = epp->ep_hdr; */
+ 
+ 	/* set up command for exec header */
+ 	NEW_VMCMD(&epp->ep_vmcmds, hpux_cpu_vmcmd,
+ 	    sizeof(struct hpux_exec), (long)epp->ep_hdr, NULLVP, 0, 0);
+ 	return (0);
+ }
+ 
+ /*
+  * We need to stash the exec header in the pcb, so we define
+  * this vmcmd to do it for us, since vmcmds are executed once
+  * we're committed to the exec (i.e. the old program has been unmapped).
+  *
+  * The address of the header is in ev->ev_addr and the length is
+  * in ev->ev_len.
+  */
+ int
+ hpux_cpu_vmcmd(p, ev)
+ 	struct proc *p;
+ 	struct exec_vmcmd *ev;
+ {
+ 	struct hpux_exec *execp = (struct hpux_exec *)ev->ev_addr;
+ 
+ 	/* Make sure we have room. */
+ 	if (ev->ev_len <= sizeof(p->p_addr->u_md.md_exec))
+ 		bcopy((caddr_t)ev->ev_addr, p->p_addr->u_md.md_exec,
+ 		    ev->ev_len);
+ 
+ 	/* Deal with misc. HP-UX process attributes. */
+ 	if (execp->ha_trsize & HPUXM_VALID) {
+ 		if (execp->ha_trsize & HPUXM_DATAWT)
+ 			p->p_md.md_flags &= ~MDP_CCBDATA;
+ 
+ 		if (execp->ha_trsize & HPUXM_STKWT)
+ 			p->p_md.md_flags &= ~MDP_CCBSTACK;
+ 	}
+ 
+ 	return (0);
+ }
+ 
+ /*
+  * Machine-dependent stat structure conversion.
+  */
+ void
+ hpux_cpu_bsd_to_hpux_stat(sb, hsb)
+ 	struct stat *sb;
+ 	struct hpux_stat *hsb;
+ {
+ 
+ 	/* XXX I don't want to talk about it... */
+ 	if ((sb->st_mode & S_IFMT) == S_IFCHR) {
+ #if NGRF > 0
+ 		if (cdevsw[major(sb->st_rdev)].d_open == grfopen)
+ 			hsb->hst_rdev = grfdevno(sb->st_rdev);
+ #endif
+ #if NHIL > 0
+ 		if (cdevsw[major(sb->st_rdev)].d_open == hilopen)
+ 			hsb->hst_rdev = hildevno(sb->st_rdev);
+ #endif
+ 	}
+ }
+ 
+ /*
+  * Machine-dependent uname information.
+  */
+ void
+ hpux_cpu_uname(ut)
+ 	struct hpux_utsname *ut;
+ {
+ 	int i;
+ 
+ 	bzero(ut->machine, sizeof(ut->machine));
+ 
+ 	/*
+ 	 * Find the current machine-ID in the table and
+ 	 * copy the string into the uname.
+ 	 */
+ 	for (i = 0; machine_table[i].val != -1; ++i)
+ 		if (machine_table[i].val == machineid)
+ 			break;
+ 
+ 	sprintf(ut->machine, "9000/%s", machine_table[i].str);
+ }
+ 
+ /*
+  * Return arch-type for hpux_sys_sysconf()
+  */
+ int
+ hpux_cpu_sysconf_arch()
+ {
+ 
+ 	switch (machineid) {
+ 	case HP_320:
+ 	case HP_330:
+ 	case HP_350:
+ 		return (HPUX_SYSCONF_CPUM020);
+ 
+ 	case HP_340:
+ 	case HP_345:
+ 	case HP_360:
+ 	case HP_370:
+ 	case HP_375:
+ 		return (HPUX_SYSCONF_CPUM030);
+ 
+ 	case HP_380:
+ 	case HP_425:
+ 	case HP_433:
+ 		return (HPUX_SYSCONF_CPUM040);
+ 
+ 	default:
+ 		return (HPUX_SYSCONF_CPUM020);	/* ??? */
+ 	}
+ 	/* NOTREACHED */
+ }
+ 
+ /*
+  * HP-UX advise(2) system call.
+  */
+ int
+ hpux_sys_advise(p, v, retval)
+ 	struct proc *p;
+ 	void *v;
+ 	register_t *retval;
+ {
+ 	struct hpux_sys_advise_args *uap = v;
+ 	int error = 0;
+ 
+ 	switch (SCARG(uap, arg)) {
+ 	case 0:
+ 		p->p_md.md_flags |= MDP_HPUXMMAP; 
+ 		break;
+ 
+ 	case 1:
+ 		ICIA();
+ 		break;
+ 
+ 	case 2:
+ 		DCIA();
+ 		break;
+ 
+ 	default:
+ 		error = EINVAL;
+ 		break;
+ 	}
+ 
+ 	return (error);
+ }
+ 
+ /*
+  * HP-UX getcontext(2) system call.
+  * Man page lies, behaviour here is based on observed behaviour.
+  */
+ int
+ hpux_sys_getcontext(p, v, retval)
+ 	struct proc *p; 
+ 	void *v;
+ 	register_t *retval; 
+ {
+ 	struct hpux_sys_getcontext_args *uap = v;
+ 	int l, i, error = 0;
+ 	int len; 
+ 
+ 	for (i = 0; context_table[i].str != NULL; i++)
+ 		if (context_table[i].val == fputype)
+ 			break;
+ 	if (context_table[i].str == NULL) {
+ 		/*
+ 		 * XXX What else?  It's not like this can happen...
+ 		 */
+ 		return (EINVAL);
+ 	}
+ 
+ 	/* + 1 ... count the terminating \0. */
+ 	l = strlen(context_table[i].str) + 1;
+ 	len = min(SCARG(uap, len), l);
+ 
+ 	if (len)
+ 		error = copyout(context_table[i].str, SCARG(uap, buf), len);
+ 	if (error == 0)
+ 		*retval = l;
+ 	return (0);
+ }
+ 
+ /*
+  * Brutal hack!  Map HP-UX u-area offsets into BSD k-stack offsets.
+  * XXX This probably doesn't work anymore, BTW.  --thorpej
+  */
+ int
+ hpux_to_bsd_uoff(off, isps, p)
+ 	int *off, *isps; 
+ 	struct proc *p;
+ {
+ 	int *ar0 = p->p_md.md_regs;
+ 	struct hpux_fp *hp; 
+ 	struct bsdfp *bp;
+ 	u_int raddr;
+ 
+ 	*isps = 0;
+ 
+ 	/* u_ar0 field; procxmt puts in U_ar0 */
+ 	if ((int)off == HPUOFF(hpuxu_ar0))
+ 		return(UOFF(U_ar0)); 
+ 
+ 	if (fputype) {
+ 		/* FP registers from PCB */
+ 		hp = (struct hpux_fp *)HPUOFF(hpuxu_fp);
+ 		bp = (struct bsdfp *)UOFF(u_pcb.pcb_fpregs);
+ 
+ 		if (off >= hp->hpfp_ctrl && off < &hp->hpfp_ctrl[3])
+ 			return((int)&bp->ctrl[off - hp->hpfp_ctrl]);
+ 
+ 		if (off >= hp->hpfp_reg && off < &hp->hpfp_reg[24])
+ 			return((int)&bp->reg[off - hp->hpfp_reg]);
+ 	}
+ 
+ 	/*
+ 	 * Everything else we recognize comes from the kernel stack,
+ 	 * so we convert off to an absolute address (if not already)
+ 	 * for simplicity.
+ 	 */
+ 	if (off < (int *)ctob(UPAGES))
+ 		off = (int *)((u_int)off + (u_int)p->p_addr);	/* XXX */
+ 
+ 	/*
+ 	 * General registers.
+ 	 * We know that the HP-UX registers are in the same order as ours.
+ 	 * The only difference is that their PS is 2 bytes instead of a
+ 	 * padded 4 like ours throwing the alignment off.
+ 	 */
+ 	if (off >= ar0 && off < &ar0[18]) {
+ 		/*
+ 		 * PS: return low word and high word of PC as HP-UX would
+ 		 * (e.g. &u.u_ar0[16.5]).
+ 		 *
+ 		 * XXX we don't do this since HP-UX adb doesn't rely on
+ 		 * it and passing such an offset to procxmt will cause
+ 		 * it to fail anyway.  Instead, we just set the offset
+ 		 * to PS and let hpux_ptrace() shift up the value returned.
+ 		 */
+ 		if (off == &ar0[PS]) {
+ #if 0
+ 			raddr = (u_int) &((short *)ar0)[PS*2+1];
+ #else
+ 			raddr = (u_int) &ar0[(int)(off - ar0)];
+ #endif
+ 			*isps = 1;
+ 		}
+ 		/*
+ 		 * PC: off will be &u.u_ar0[16.5] since HP-UX saved PS
+ 		 * is only 16 bits.
+ 		 */
+ 		else if (off == (int *)&(((short *)ar0)[PS*2+1]))
+ 			raddr = (u_int) &ar0[PC];
+ 		/*
+ 		 * D0-D7, A0-A7: easy
+ 		 */
+ 		else
+ 			raddr = (u_int) &ar0[(int)(off - ar0)];
+ 		return((int)(raddr - (u_int)p->p_addr));	/* XXX */
+ 	}
+ 
+ 	/* everything else */
+ 	return (-1);
+ }
+ 
+ #define	HSS_RTEFRAME	0x01
+ #define	HSS_FPSTATE	0x02
+ #define	HSS_USERREGS	0x04
+ 
+ struct hpuxsigstate {
+ 	int	hss_flags;		/* which of the following are valid */
+ 	struct	frame hss_frame;	/* original exception frame */
+ 	struct	fpframe hss_fpstate;	/* 68881/68882 state info */
+ };
+ 
+ /*
+  * WARNING: code in locore.s assumes the layout shown here for hsf_signum
+  * thru hsf_handler so... don't screw with them!
+  */
+ struct hpuxsigframe {
+ 	int	hsf_signum;		   /* signo for handler */
+ 	int	hsf_code;		   /* additional info for handler */
+ 	struct	hpuxsigcontext *hsf_scp;   /* context ptr for handler */
+ 	sig_t	hsf_handler;		   /* handler addr for u_sigc */
+ 	struct	hpuxsigstate hsf_sigstate; /* state of the hardware */
+ 	struct	hpuxsigcontext hsf_sc;	   /* actual context */
+ };
+ 
+ #ifdef DEBUG
+ int hpuxsigdebug = 0;
+ int hpuxsigpid = 0;
+ #define SDB_FOLLOW	0x01
+ #define SDB_KSTACK	0x02
+ #define SDB_FPSTATE	0x04
+ #endif
+ 
+ /*
+  * Send an interrupt to process.
+  */
+ void
+ hpux_sendsig(catcher, sig, mask, code)
+ 	sig_t catcher;
+ 	int sig, mask;
+ 	u_long code;
+ {
+ 	struct proc *p = curproc;
+ 	struct hpuxsigframe *kfp, *fp;
+ 	struct frame *frame;
+ 	struct sigacts *psp = p->p_sigacts;
+ 	short ft;
+ 	int oonstack, fsize;
+ 	extern char sigcode[], esigcode[];
+ 
+ 	frame = (struct frame *)p->p_md.md_regs;
+ 	ft = frame->f_format;
+ 	oonstack = psp->ps_sigstk.ss_flags & SS_ONSTACK;
+ 
+ 	/*
+ 	 * Allocate and validate space for the signal handler
+ 	 * context. Note that if the stack is in P0 space, the
+ 	 * call to grow() is a nop, and the useracc() check
+ 	 * will fail if the process has not already allocated
+ 	 * the space with a `brk'.
+ 	 */
+ 	fsize = sizeof(struct hpuxsigframe);
+ 	if ((psp->ps_flags & SAS_ALTSTACK) && !oonstack &&
+ 	    (psp->ps_sigonstack & sigmask(sig))) {
+ 		fp = (struct hpuxsigframe *)(psp->ps_sigstk.ss_sp +
+ 		    psp->ps_sigstk.ss_size - fsize);
+ 		psp->ps_sigstk.ss_flags |= SS_ONSTACK;
+ 	} else
+ 		fp = (struct hpuxsigframe *)(frame->f_regs[SP] - fsize);
+ 	if ((unsigned)fp <= USRSTACK - ctob(p->p_vmspace->vm_ssize)) 
+ 		(void)grow(p, (unsigned)fp);
+ 
+ #ifdef DEBUG
+ 	if ((hpuxsigdebug & SDB_KSTACK) && p->p_pid == hpuxsigpid)
+ 		printf("hpux_sendsig(%d): sig %d ssp %p usp %p scp %p ft %d\n",
+ 		       p->p_pid, sig, &oonstack, fp, &fp->hsf_sc, ft);
+ #endif
+ 
+ 	if (useracc((caddr_t)fp, fsize, B_WRITE) == 0) {
+ #ifdef DEBUG
+ 		if ((hpuxsigdebug & SDB_KSTACK) && p->p_pid == hpuxsigpid)
+ 			printf("hpux_sendsig(%d): useracc failed on sig %d\n",
+ 			       p->p_pid, sig);
+ #endif
+ 		/*
+ 		 * Process has trashed its stack; give it an illegal
+ 		 * instruction to halt it in its tracks.
+ 		 */
+ 		SIGACTION(p, SIGILL) = SIG_DFL;
+ 		sig = sigmask(SIGILL);
+ 		p->p_sigignore &= ~sig;
+ 		p->p_sigcatch &= ~sig;
+ 		p->p_sigmask &= ~sig;
+ 		psignal(p, SIGILL);
+ 		return;
+ 	}
+ 	kfp = (struct hpuxsigframe *)malloc((u_long)fsize, M_TEMP, M_WAITOK);
+ 
+ 	/* 
+ 	 * Build the argument list for the signal handler.
+ 	 */
+ 	kfp->hsf_signum = bsdtohpuxsig(sig);
+ 	kfp->hsf_code = code;
+ 	kfp->hsf_scp = &fp->hsf_sc;
+ 	kfp->hsf_handler = catcher;
+ 
+ 	/*
+ 	 * Save necessary hardware state.  Currently this includes:
+ 	 *	- general registers
+ 	 *	- original exception frame (if not a "normal" frame)
+ 	 *	- FP coprocessor state
+ 	 */
+ 	kfp->hsf_sigstate.hss_flags = HSS_USERREGS;
+ 	bcopy((caddr_t)frame->f_regs,
+ 	    (caddr_t)kfp->hsf_sigstate.hss_frame.f_regs, sizeof frame->f_regs);
+ 	if (ft >= FMT7) {
+ #ifdef DEBUG
+ 		if (ft > 15 || exframesize[ft] < 0)
+ 			panic("hpux_sendsig: bogus frame type");
+ #endif
+ 		kfp->hsf_sigstate.hss_flags |= HSS_RTEFRAME;
+ 		kfp->hsf_sigstate.hss_frame.f_format = frame->f_format;
+ 		kfp->hsf_sigstate.hss_frame.f_vector = frame->f_vector;
+ 		bcopy((caddr_t)&frame->F_u,
+ 		    (caddr_t)&kfp->hsf_sigstate.hss_frame.F_u, exframesize[ft]);
+ 
+ 		/*
+ 		 * Leave an indicator that we need to clean up the kernel
+ 		 * stack.  We do this by setting the "pad word" above the
+ 		 * hardware stack frame to the amount the stack must be
+ 		 * adjusted by.
+ 		 *
+ 		 * N.B. we increment rather than just set f_stackadj in
+ 		 * case we are called from syscall when processing a
+ 		 * sigreturn.  In that case, f_stackadj may be non-zero.
+ 		 */
+ 		frame->f_stackadj += exframesize[ft];
+ 		frame->f_format = frame->f_vector = 0;
+ #ifdef DEBUG
+ 		if (hpuxsigdebug & SDB_FOLLOW)
+ 			printf("hpux_sendsig(%d): copy out %d of frame %d\n",
+ 			       p->p_pid, exframesize[ft], ft);
+ #endif
+ 	}
+ 	if (fputype) {
+ 		kfp->hsf_sigstate.hss_flags |= HSS_FPSTATE;
+ 		m68881_save(&kfp->hsf_sigstate.hss_fpstate);
+ 	}
+ 
+ #ifdef DEBUG
+ 	if ((hpuxsigdebug & SDB_FPSTATE) &&
+ 	    *(char *)&kfp->hsf_sigstate.hss_fpstate)
+ 		printf("hpux_sendsig(%d): copy out FP state (%x) to %p\n",
+ 		       p->p_pid, *(u_int *)&kfp->hsf_sigstate.hss_fpstate,
+ 		       &kfp->hsf_sigstate.hss_fpstate);
+ #endif
+ 
+ 	/*
+ 	 * Build the signal context to be used by hpux_sigreturn.
+ 	 */
+ 	kfp->hsf_sc.hsc_syscall	= 0;		/* XXX */
+ 	kfp->hsf_sc.hsc_action	= 0;		/* XXX */
+ 	kfp->hsf_sc.hsc_pad1	= kfp->hsf_sc.hsc_pad2 = 0;
+ 	kfp->hsf_sc.hsc_onstack	= oonstack;
+ 	kfp->hsf_sc.hsc_mask	= mask;
+ 	kfp->hsf_sc.hsc_sp	= frame->f_regs[SP];
+ 	kfp->hsf_sc.hsc_ps	= frame->f_sr;
+ 	kfp->hsf_sc.hsc_pc	= frame->f_pc;
+ 
+ 	/* How amazingly convenient! */
+ 	kfp->hsf_sc._hsc_pad	= 0;
+ 	kfp->hsf_sc._hsc_ap	= (int)&fp->hsf_sigstate;
+ 
+ 	(void) copyout((caddr_t)kfp, (caddr_t)fp, fsize);
+ 	frame->f_regs[SP] = (int)fp;
+ 
+ #ifdef DEBUG
+ 	if (hpuxsigdebug & SDB_FOLLOW) {
+ 		printf(
+ 		  "hpux_sendsig(%d): sig %d scp %p fp %p sc_sp %x sc_ap %x\n",
+ 		   p->p_pid, sig, kfp->hsf_scp, fp,
+ 		   kfp->hsf_sc.hsc_sp, kfp->hsf_sc._hsc_ap);
+ 	}
+ #endif
+ 
+ 	/*
+ 	 * Signal trampoline code is at base of user stack.
+ 	 */
+ 	frame->f_pc = (int)PS_STRINGS - (esigcode - sigcode);
+ #ifdef DEBUG
+ 	if ((hpuxsigdebug & SDB_KSTACK) && p->p_pid == hpuxsigpid)
+ 		printf("hpux_sendsig(%d): sig %d returns\n",
+ 		       p->p_pid, sig);
+ #endif
+ 	free((caddr_t)kfp, M_TEMP);
+ }
+ 
+ /*
+  * System call to cleanup state after a signal
+  * has been taken.  Reset signal mask and
+  * stack state from context left by sendsig (above).
+  * Return to previous pc and psl as specified by
+  * context left by sendsig. Check carefully to
+  * make sure that the user has not modified the
+  * psl to gain improper priviledges or to cause
+  * a machine fault.
+  */
+ /* ARGSUSED */
+ int
+ hpux_sys_sigreturn(p, v, retval)
+ 	struct proc *p;
+ 	void *v;
+ 	register_t *retval;
+ {
+ 	struct hpux_sys_sigreturn_args /* {
+ 		syscallarg(struct hpuxsigcontext *) sigcntxp;
+ 	} */ *uap = v;
+ 	struct hpuxsigcontext *scp;
+ 	struct frame *frame;
+ 	int rf;
+ 	struct hpuxsigcontext tsigc;
+ 	struct hpuxsigstate tstate;
+ 	int flags;
+ 
+ 	scp = SCARG(uap, sigcntxp);
+ #ifdef DEBUG
+ 	if (hpuxsigdebug & SDB_FOLLOW)
+ 		printf("sigreturn: pid %d, scp %p\n", p->p_pid, scp);
+ #endif
+ 	if ((int)scp & 1)
+ 		return (EINVAL);
+ 
+ 	/*
+ 	 * Fetch and test the HP-UX context structure.
+ 	 * We grab it all at once for speed.
+ 	 */
+ 	if (useracc((caddr_t)scp, sizeof (*scp), B_WRITE) == 0 ||
+ 	    copyin((caddr_t)scp, (caddr_t)&tsigc, sizeof tsigc))
+ 		return (EINVAL);
+ 	scp = &tsigc;
+ 	if ((scp->hsc_ps & (PSL_MBZ|PSL_IPL|PSL_S)) != 0)
+ 		return (EINVAL);
+ 
+ 	/*
+ 	 * Restore the user supplied information
+ 	 */
+ 	if (scp->hsc_onstack & 01)
+ 		p->p_sigacts->ps_sigstk.ss_flags |= SS_ONSTACK;
+ 	else
+ 		p->p_sigacts->ps_sigstk.ss_flags &= ~SS_ONSTACK;
+ 	p->p_sigmask = scp->hsc_mask &~ sigcantmask;
+ 	frame = (struct frame *) p->p_md.md_regs;
+ 	frame->f_regs[SP] = scp->hsc_sp;
+ 	frame->f_pc = scp->hsc_pc;
+ 	frame->f_sr = scp->hsc_ps;
+ 
+ 	/*
+ 	 * Grab a pointer to the hpuxsigstate.
+ 	 * If zero, the user is probably doing a longjmp.
+ 	 * (This will never happen, really, since HP-UX doesn't
+ 	 * know/care about the state pointer.)
+ 	 */
+ 	if ((rf = scp->_hsc_ap) == 0)
+ 		return (EJUSTRETURN);
+ 
+ 	/*
+ 	 * See if there is anything to do before we go to the
+ 	 * expense of copying in close to 1/2K of data
+ 	 */
+ 	flags = fuword((caddr_t)rf);
+ #ifdef DEBUG
+ 	if (hpuxsigdebug & SDB_FOLLOW)
+ 		printf("sigreturn(%d): sc_ap %x flags %x\n",
+ 		       p->p_pid, rf, flags);
+ #endif
+ 	/*
+ 	 * fuword failed (bogus _hsc_ap value).
+ 	 */
+ 	if (flags == -1)
+ 		return (EINVAL);
+ 	if (flags == 0 || copyin((caddr_t)rf, (caddr_t)&tstate, sizeof tstate))
+ 		return (EJUSTRETURN);
+ #ifdef DEBUG
+ 	if ((hpuxsigdebug & SDB_KSTACK) && p->p_pid == hpuxsigpid)
+ 		printf("sigreturn(%d): ssp %p usp %x scp %p ft %d\n",
+ 		       p->p_pid, &flags, scp->hsc_sp, SCARG(uap, sigcntxp),
+ 		       (flags & HSS_RTEFRAME) ? tstate.hss_frame.f_format : -1);
+ #endif
+ 	/*
+ 	 * Restore most of the users registers except for A6 and SP
+ 	 * which were handled above.
+ 	 */
+ 	if (flags & HSS_USERREGS)
+ 		bcopy((caddr_t)tstate.hss_frame.f_regs,
+ 		    (caddr_t)frame->f_regs, sizeof(frame->f_regs)-2*NBPW);
+ 
+ 	/*
+ 	 * Restore long stack frames.  Note that we do not copy
+ 	 * back the saved SR or PC, they were picked up above from
+ 	 * the sigcontext structure.
+ 	 */
+ 	if (flags & HSS_RTEFRAME) {
+ 		int sz;
+ 		
+ 		/* grab frame type and validate */
+ 		sz = tstate.hss_frame.f_format;
+ 		if (sz > 15 || (sz = exframesize[sz]) < 0)
+ 			return (EINVAL);
+ 		frame->f_stackadj -= sz;
+ 		frame->f_format = tstate.hss_frame.f_format;
+ 		frame->f_vector = tstate.hss_frame.f_vector;
+ 		bcopy((caddr_t)&tstate.hss_frame.F_u,
+ 		    (caddr_t)&frame->F_u, sz);
+ #ifdef DEBUG
+ 		if (hpuxsigdebug & SDB_FOLLOW)
+ 			printf("sigreturn(%d): copy in %d of frame type %d\n",
+ 			       p->p_pid, sz, tstate.hss_frame.f_format);
+ #endif
+ 	}
+ 
+ 	/*
+ 	 * Finally we restore the original FP context
+ 	 */
+ 	if (flags & HSS_FPSTATE)
+ 		m68881_restore(&tstate.hss_fpstate);
+ 
+ #ifdef DEBUG
+ 	if ((hpuxsigdebug & SDB_FPSTATE) && *(char *)&tstate.hss_fpstate)
+ 		printf("sigreturn(%d): copied in FP state (%x) at %p\n",
+ 		       p->p_pid, *(u_int *)&tstate.hss_fpstate,
+ 		       &tstate.hss_fpstate);
+ 
+ 	if ((hpuxsigdebug & SDB_FOLLOW) ||
+ 	    ((hpuxsigdebug & SDB_KSTACK) && p->p_pid == hpuxsigpid))
+ 		printf("sigreturn(%d): returns\n", p->p_pid);
+ #endif
+ 	return (EJUSTRETURN);
+ }
+ 
+ /*
+  * Set registers on exec.
+  * XXX Should clear registers except sp, pc.
+  */
+ void
+ hpux_setregs(p, pack, stack, retval)
+ 	struct proc *p;
+ 	struct exec_package *pack;
+ 	u_long stack;
+ 	register_t *retval;
+ {
+ 	struct frame *frame = (struct frame *)p->p_md.md_regs;
+ 
+ 	frame->f_pc = pack->ep_entry & ~1;
+ 	frame->f_regs[SP] = stack;
+ 	frame->f_regs[A2] = (int)PS_STRINGS;
+ 
+ 	/* restore a null state frame */
+ 	p->p_addr->u_pcb.pcb_fpregs.fpf_null = 0;
+ 	if (fputype)
+ 		m68881_restore(&p->p_addr->u_pcb.pcb_fpregs);
+ 
+ 	p->p_md.md_flags &= ~MDP_HPUXMMAP;
+ 	frame->f_regs[A0] = 0;	/* not 68010 (bit 31), no FPA (30) */
+ 	retval[0] = 0;		/* no float card */
+ 	if (fputype)
+ 		retval[1] = 1;	/* yes 68881 */
+ 	else
+ 		retval[1] = 0;	/* no 68881 */
+ }
diff -crN /sys/arch/hp300/hp300/locore.s hp300/locore.s
*** /sys/arch/hp300/hp300/locore.s	Mon Apr 14 04:25:30 1997
--- hp300/locore.s	Thu Apr 24 09:40:17 1997
***************
*** 160,166 ****
  	movl	a1@(MMUCMD),d0		| read it back
  	btst	#16,d0			| still on?
  	jeq	Lstart1			| no, must be a 360
! 	movl	#HP_375,a0@		| yes, must be a 345/375
  	jra	Lhaspac
  Lisa370:
  	movl	#HP_370,a0@		| set to 370
--- 160,180 ----
  	movl	a1@(MMUCMD),d0		| read it back
  	btst	#16,d0			| still on?
  	jeq	Lstart1			| no, must be a 360
! 	RELOC(_mmuid, a0)		| save MMU ID byte
! 	lsrl	#8,d0
! 	movl	d0,a0@
! 	andl	#0xff,a0@
! 	cmpb	#1,d0			| id == 1?
! 	beq	Lisa345			| is a 345
! 	cmpb	#3,d0			| id == 3?
! 	beq	Lisa375			| is a 375
! 	movl	#HP_400,a0@		| must be a 400?
! 	jra	Lhaspac
! Lisa345:
! 	movl	#HP_345,a0@
! 	jra	Lhaspac
! Lisa375:
! 	movl	#HP_375,a0@
  	jra	Lhaspac
  Lisa370:
  	movl	#HP_370,a0@		| set to 370
***************
*** 184,198 ****
  	movl	#FPU_68040,a0@		| ...and FPU
  	RELOC(_ectype, a0)
  	movl	#EC_NONE,a0@		| and no cache (for now XXX)
! 	RELOC(_machineid, a0)
  	movl	a1@(MMUCMD),d0		| read MMU register
  	lsrl	#8,d0			| get apparent ID
  	cmpb	#6,d0			| id == 6?
! 	jeq	Lis33mhz		| yes, we have a 433s
  	movl	#HP_380,a0@		| no, we have a 380/425t
  	jra	Lstart1
  Lis33mhz:
! 	movl	#HP_433,a0@		| 433s (XXX 425s returns same ID, ugh!)
  	jra	Lstart1
  Lis68020:
  	movl	#1,a1@(MMUCMD)		| a 68020, write HP MMU location
--- 198,223 ----
  	movl	#FPU_68040,a0@		| ...and FPU
  	RELOC(_ectype, a0)
  	movl	#EC_NONE,a0@		| and no cache (for now XXX)
! 	RELOC(_mmuid, a0)
  	movl	a1@(MMUCMD),d0		| read MMU register
  	lsrl	#8,d0			| get apparent ID
+ 	movl	d0,a0@
+ 	andl	#0xff,a0@		| save MMU ID byte
+ 	RELOC(_machineid, a0)
+ 	cmpb	#4,d0			| id == 4?
+ 	jeq	Lis33mhz		| 33MHz Strider (433t)
  	cmpb	#6,d0			| id == 6?
! 	jeq	Lis33mhz		| 33MHz Trailways (433s)
! 	cmpb	#5,d0			| id == 5?
! 	jeq	Lis25mhz		| 25MHz Strider (425t)
! 	cmpb	#7,d0			| id == 7?
! 	jeq	Lis25mhz		| 25MHz Trailways (425s)
  	movl	#HP_380,a0@		| no, we have a 380/425t
  	jra	Lstart1
+ Lis25mhz:
+ 	movl	#HP_425,a0@		| running at 25MHz
  Lis33mhz:
! 	movl	#HP_433,a0@		| running at 33MHz
  	jra	Lstart1
  Lis68020:
  	movl	#1,a1@(MMUCMD)		| a 68020, write HP MMU location
***************
*** 1909,1918 ****
  #undef DOREBOOT

  	.data
! 	.globl	_machineid,_mmutype,_cputype,_ectype,_fputype
  	.globl	_protorp,_prototc
  _machineid:
  	.long	HP_320		| default to 320
  _mmutype:
  	.long	MMU_HP		| default to HP MMU
  _cputype:
--- 1934,1945 ----
  #undef DOREBOOT

  	.data
! 	.globl	_machineid,_mmuid,_mmutype,_cputype,_ectype,_fputype
  	.globl	_protorp,_prototc
  _machineid:
  	.long	HP_320		| default to 320
+ _mmuid:
+ 	.long	0		| default to ???
  _mmutype:
  	.long	MMU_HP		| default to HP MMU
  _cputype:
diff -crN /sys/arch/hp300/hp300/locore.s~ hp300/locore.s~
*** /sys/arch/hp300/hp300/locore.s~	Wed Dec 31 16:00:00 1969
--- hp300/locore.s~	Thu Apr 24 08:31:30 1997
***************
*** 0 ****
--- 1,2009 ----
+ /*	$NetBSD: locore.s,v 1.70 1997/04/14 02:28:47 thorpej Exp $	*/
+ 
+ /*
+  * Copyright (c) 1994, 1995 Gordon W. Ross
+  * Copyright (c) 1988 University of Utah.
+  * Copyright (c) 1980, 1990, 1993
+  *	The Regents of the University of California.  All rights reserved.
+  *
+  * This code is derived from software contributed to Berkeley by
+  * the Systems Programming Group of the University of Utah Computer
+  * Science Department.
+  *
+  * Redistribution and use in source and binary forms, with or without
+  * modification, are permitted provided that the following conditions
+  * are met:
+  * 1. Redistributions of source code must retain the above copyright
+  *    notice, this list of conditions and the following disclaimer.
+  * 2. Redistributions in binary form must reproduce the above copyright
+  *    notice, this list of conditions and the following disclaimer in the
+  *    documentation and/or other materials provided with the distribution.
+  * 3. All advertising materials mentioning features or use of this software
+  *    must display the following acknowledgement:
+  *	This product includes software developed by the University of
+  *	California, Berkeley and its contributors.
+  * 4. Neither the name of the University nor the names of its contributors
+  *    may be used to endorse or promote products derived from this software
+  *    without specific prior written permission.
+  *
+  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+  * SUCH DAMAGE.
+  *
+  * from: Utah $Hdr: locore.s 1.66 92/12/22$
+  *
+  *	@(#)locore.s	8.6 (Berkeley) 5/27/94
+  */
+ 
+ #include "assym.h"
+ #include <machine/trap.h>
+ 
+ #define MMUADDR(ar)	movl	_MMUbase,ar
+ #define CLKADDR(ar)	movl	_CLKbase,ar
+ 
+ /*
+  * This is for kvm_mkdb, and should be the address of the beginning
+  * of the kernel text segment (not necessarily the same as kernbase).
+  */
+ 	.text
+ 	.globl  _kernel_text
+ _kernel_text:
+ 
+ /*
+  * Clear and skip the first page of text; it will not be mapped.
+  */
+ 	.fill	NBPG/4,4,0
+ 
+ /*
+  * Temporary stack for a variety of purposes.
+  * Try and make this the first thing is the data segment so it
+  * is page aligned.  Note that if we overflow here, we run into
+  * our text segment.
+  */
+ 	.data
+ 	.space	NBPG
+ tmpstk:
+ 
+ #include <hp300/hp300/vectors.s>
+ 
+ 	.text
+ 
+ /*
+  * Macro to relocate a symbol, used before MMU is enabled.
+  */
+ #define	RELOC(var, ar)		\
+ 	lea	var,ar;		\
+ 	addl	a5,ar
+ 
+ /*
+  * Initialization
+  *
+  * A4 contains the address of the end of the symtab
+  * A5 contains physical load point from boot
+  * VBR contains zero from ROM.  Exceptions will continue to vector
+  * through ROM until MMU is turned on at which time they will vector
+  * through our table (vectors.s).
+  */
+ 	.comm	_lowram,4
+ 	.comm	_esym,4
+ 
+ 	.text
+ 	.globl	_edata
+ 	.globl	_etext,_end
+ 	.globl	start
+ start:
+ 	movw	#PSL_HIGHIPL,sr		| no interrupts
+ 	RELOC(tmpstk, a0)
+ 	movl	a0,sp			| give ourselves a temporary stack
+ 	RELOC(_esym, a0)
+ #if 1
+ 	movl	a4,a0@			| store end of symbol table
+ #else
+ 	clrl	a0@			| no symbol table, yet
+ #endif
+ 	RELOC(_lowram, a0)
+ 	movl	a5,a0@			| store start of physical memory
+ 	movl	#CACHE_OFF,d0
+ 	movc	d0,cacr			| clear and disable on-chip cache(s)
+ 
+ /* check for internal HP-IB in SYSFLAG */
+ 	btst	#5,0xfffffed2		| internal HP-IB?
+ 	jeq	Lhaveihpib		| yes, have HP-IB just continue
+ 	RELOC(_internalhpib, a0)
+ 	movl	#0,a0@			| no, clear associated address
+ Lhaveihpib:
+ 
+ 	RELOC(_boothowto, a0)		| save reboot flags
+ 	movl	d7,a0@
+ 	RELOC(_bootdev, a0)		|   and boot device
+ 	movl	d6,a0@
+ 
+ 	/*
+ 	 * All data registers are now free.  All address registers
+ 	 * except a5 are free.  a5 is used by the RELOC() macro,
+ 	 * and cannot be used until after the MMU is enabled.
+ 	 */
+ 
+ /* determine our CPU/MMU combo - check for all regardless of kernel config */
+ 	movl	#INTIOBASE+MMUBASE,a1
+ 	movl	#0x200,d0		| data freeze bit
+ 	movc	d0,cacr			|   only exists on 68030
+ 	movc	cacr,d0			| read it back
+ 	tstl	d0			| zero?
+ 	jeq	Lnot68030		| yes, we have 68020/68040
+ 	RELOC(_mmutype, a0)		| no, we have 68030
+ 	movl	#MMU_68030,a0@		| set to reflect 68030 PMMU
+ 	RELOC(_cputype, a0)
+ 	movl	#CPU_68030,a0@		| and 68030 CPU
+ 	RELOC(_machineid, a0)
+ 	movl	#0x80,a1@(MMUCMD)	| set magic cookie
+ 	movl	a1@(MMUCMD),d0		| read it back
+ 	btst	#7,d0			| cookie still on?
+ 	jeq	Lnot370			| no, 360 or 375
+ 	movl	#0,a1@(MMUCMD)		| clear magic cookie
+ 	movl	a1@(MMUCMD),d0		| read it back
+ 	btst	#7,d0			| still on?
+ 	jeq	Lisa370			| no, must be a 370
+ 	movl	#HP_340,a0@		| yes, must be a 340
+ 	jra	Lstart1
+ Lnot370:
+ 	movl	#HP_360,a0@		| type is at least a 360
+ 	movl	#0,a1@(MMUCMD)		| clear magic cookie2
+ 	movl	a1@(MMUCMD),d0		| read it back
+ 	btst	#16,d0			| still on?
+ 	jeq	Lstart1			| no, must be a 360
+ 	RELOC(_mmuid, a0)		| save MMU ID byte
+ 	lsrl	#8,d0
+ 	movl	d0,a0@
+ 	andl	#0xff,a0@
+ 	cmpb	#1,d0			| id == 1?
+ 	beq	Lisa345			| is a 345
+ 	cmpb	#3,d0			| id == 3?
+ 	beq	Lisa375			| is a 375
+ 	movl	#HP_400,a0@		| must be a 400?
+ 	jra	Lhaspac
+ Lisa345:
+ 	movl	#HP_345,a0@
+ 	jra	Lhaspac
+ Lisa375:
+ 	movl	#HP_375,a0@
+ 	jra	Lhaspac
+ Lisa370:
+ 	movl	#HP_370,a0@		| set to 370
+ Lhaspac:
+ 	RELOC(_ectype, a0)
+ 	movl	#EC_PHYS,a0@		| also has a physical address cache
+ 	jra	Lstart1
+ Lnot68030:
+ 	bset	#31,d0			| data cache enable bit
+ 	movc	d0,cacr			|   only exists on 68040
+ 	movc	cacr,d0			| read it back
+ 	tstl	d0			| zero?
+ 	beq	Lis68020		| yes, we have 68020
+ 	moveq	#0,d0			| now turn it back off
+ 	movec	d0,cacr			|   before we access any data
+ 	RELOC(_mmutype, a0)
+ 	movl	#MMU_68040,a0@		| with a 68040 MMU
+ 	RELOC(_cputype, a0)
+ 	movl	#CPU_68040,a0@		| and a 68040 CPU
+ 	RELOC(_fputype, a0)
+ 	movl	#FPU_68040,a0@		| ...and FPU
+ 	RELOC(_ectype, a0)
+ 	movl	#EC_NONE,a0@		| and no cache (for now XXX)
+ 	RELOC(_mmuid, a0)
+ 	movl	a1@(MMUCMD),d0		| read MMU register
+ 	lsrl	#8,d0			| get apparent ID
+ 	movl	d0,a0@
+ 	andl	#0xff,a0@		| save MMU ID byte
+ 	RELOC(_machineid, a0)
+ 	cmpb	#4,d0			| id == 4?
+ 	jeq	Lis33mhz		| 33MHz Strider (433t)
+ 	cmpb	#6,d0			| id == 6?
+ 	jeq	Lis33mhz		| 33MHz Trailways (433s)
+ 	cmpb	#5,d0			| id == 5?
+ 	jeq	Lis25mhz		| 25MHz Strider (425t)
+ 	cmpb	#7,d0			| id == 7?
+ 	jeq	Lis25mhz		| 25MHz Trailways (425s)
+ 	movl	#HP_380,a0@		| no, we have a 380/425t
+ 	jra	Lstart1
+ Lis25mhz:
+ 	movl	#HP_425,a0@
+ Lis33mhz:
+ 	movl	#HP_433,a0@		| 433s (XXX 425s returns same ID, ugh!)
+ 	jra	Lstart1
+ Lis68020:
+ 	movl	#1,a1@(MMUCMD)		| a 68020, write HP MMU location
+ 	movl	a1@(MMUCMD),d0		| read it back
+ 	btst	#0,d0			| non-zero?
+ 	jne	Lishpmmu		| yes, we have HP MMU
+ 	RELOC(_mmutype, a0)
+ 	movl	#MMU_68851,a0@		| no, we have PMMU
+ 	RELOC(_machineid, a0)
+ 	movl	#HP_330,a0@		| and 330 CPU
+ 	jra	Lstart1
+ Lishpmmu:
+ 	RELOC(_ectype, a0)		| 320 or 350
+ 	movl	#EC_VIRT,a0@		| both have a virtual address cache
+ 	movl	#0x80,a1@(MMUCMD)	| set magic cookie
+ 	movl	a1@(MMUCMD),d0		| read it back
+ 	btst	#7,d0			| cookie still on?
+ 	jeq	Lis320			| no, just a 320
+ 	RELOC(_machineid, a0)
+ 	movl	#HP_350,a0@		| yes, a 350
+ 	jra	Lstart1
+ Lis320:
+ 	RELOC(_machineid, a0)
+ 	movl	#HP_320,a0@
+ 
+ Lstart1:
+ 	movl	#0,a1@(MMUCMD)		| clear out MMU again
+ /* initialize source/destination control registers for movs */
+ 	moveq	#FC_USERD,d0		| user space
+ 	movc	d0,sfc			|   as source
+ 	movc	d0,dfc			|   and destination of transfers
+ /* initialize memory sizes (for pmap_bootstrap) */
+ 	movl	#MAXADDR,d1		| last page
+ 	moveq	#PGSHIFT,d2
+ 	lsrl	d2,d1			| convert to page (click) number
+ 	RELOC(_maxmem, a0)
+ 	movl	d1,a0@			| save as maxmem
+ 	movl	a5,d0			| lowram value from ROM via boot
+ 	lsrl	d2,d0			| convert to page number
+ 	subl	d0,d1			| compute amount of RAM present
+ 	RELOC(_physmem, a0)
+ 	movl	d1,a0@			| and physmem
+ /* configure kernel and proc0 VA space so we can get going */
+ 	.globl	_Sysseg, _pmap_bootstrap, _avail_start
+ #ifdef DDB
+ 	RELOC(_esym,a0)			| end of static kernel test/data/syms
+ 	movl	a0@,d5
+ 	jne	Lstart2
+ #endif
+ 	movl	#_end,d5		| end of static kernel text/data
+ Lstart2:
+ 	addl	#NBPG-1,d5
+ 	andl	#PG_FRAME,d5		| round to a page
+ 	movl	d5,a4
+ 	addl	a5,a4			| convert to PA
+ 	pea	a5@			| firstpa
+ 	pea	a4@			| nextpa
+ 	RELOC(_pmap_bootstrap,a0)
+ 	jbsr	a0@			| pmap_bootstrap(firstpa, nextpa)
+ 	addql	#8,sp
+ 
+ /*
+  * Prepare to enable MMU.
+  * Since the kernel is not mapped logical == physical we must insure
+  * that when the MMU is turned on, all prefetched addresses (including
+  * the PC) are valid.  In order guarentee that, we use the last physical
+  * page (which is conveniently mapped == VA) and load it up with enough
+  * code to defeat the prefetch, then we execute the jump back to here.
+  *
+  * Is this all really necessary, or am I paranoid??
+  */
+ 	RELOC(_Sysseg, a0)		| system segment table addr
+ 	movl	a0@,d1			| read value (a KVA)
+ 	addl	a5,d1			| convert to PA
+ 	RELOC(_mmutype, a0)
+ 	tstl	a0@			| HP MMU?
+ 	jeq	Lhpmmu2			| yes, skip
+ 	cmpl	#MMU_68040,a0@		| 68040?
+ 	jne	Lmotommu1		| no, skip
+ 	.long	0x4e7b1807		| movc d1,srp
+ 	jra	Lstploaddone
+ Lmotommu1:
+ 	RELOC(_protorp, a0)
+ 	movl	#0x80000202,a0@		| nolimit + share global + 4 byte PTEs
+ 	movl	d1,a0@(4)		| + segtable address
+ 	pmove	a0@,srp			| load the supervisor root pointer
+ 	movl	#0x80000002,a0@		| reinit upper half for CRP loads
+ 	jra	Lstploaddone		| done
+ Lhpmmu2:
+ 	moveq	#PGSHIFT,d2
+ 	lsrl	d2,d1			| convert to page frame
+ 	movl	d1,INTIOBASE+MMUBASE+MMUSSTP | load in sysseg table register
+ Lstploaddone:
+ 	lea	MAXADDR,a2		| PA of last RAM page
+ 	RELOC(Lhighcode, a1)		| addr of high code
+ 	RELOC(Lehighcode, a3)		| end addr
+ Lcodecopy:
+ 	movw	a1@+,a2@+		| copy a word
+ 	cmpl	a3,a1			| done yet?
+ 	jcs	Lcodecopy		| no, keep going
+ 	jmp	MAXADDR			| go for it!
+ 
+ 	/*
+ 	 * BEGIN MMU TRAMPOLINE.  This section of code is not
+ 	 * executed in-place.  It's copied to the last page
+ 	 * of RAM (mapped va == pa) and executed there.
+ 	 */
+ 
+ Lhighcode:
+ 	/*
+ 	 * Set up the vector table, and race to get the MMU
+ 	 * enabled.
+ 	 */
+ 	movl	#_vectab,d0		| set Vector Base Register
+ 	movc	d0,vbr
+ 
+ 	RELOC(_mmutype, a0)
+ 	tstl	a0@			| HP MMU?
+ 	jeq	Lhpmmu3			| yes, skip
+ 	cmpl	#MMU_68040,a0@		| 68040?
+ 	jne	Lmotommu2		| no, skip
+ 	movw	#0,INTIOBASE+MMUBASE+MMUCMD+2
+ 	movw	#MMU_IEN+MMU_CEN+MMU_FPE,INTIOBASE+MMUBASE+MMUCMD+2
+ 					| enable FPU and caches
+ 	moveq	#0,d0			| ensure TT regs are disabled
+ 	.long	0x4e7b0004		| movc d0,itt0
+ 	.long	0x4e7b0005		| movc d0,itt1
+ 	.long	0x4e7b0006		| movc d0,dtt0
+ 	.long	0x4e7b0007		| movc d0,dtt1
+ 	.word	0xf4d8			| cinva bc
+ 	.word	0xf518			| pflusha
+ 	movl	#0x8000,d0
+ 	.long	0x4e7b0003		| movc d0,tc
+ 	movl	#0x80008000,d0
+ 	movc	d0,cacr			| turn on both caches
+ 	jmp	Lenab1
+ Lmotommu2:
+ 	movl	#MMU_IEN+MMU_FPE,INTIOBASE+MMUBASE+MMUCMD
+ 					| enable 68881 and i-cache
+ 	RELOC(_prototc, a2)
+ 	movl	#0x82c0aa00,a2@		| value to load TC with
+ 	pmove	a2@,tc			| load it
+ 	jmp	Lenab1
+ Lhpmmu3:
+ 	movl	#0,INTIOBASE+MMUBASE+MMUCMD	| clear external cache
+ 	movl	#MMU_ENAB,INTIOBASE+MMUBASE+MMUCMD | turn on MMU
+ 	jmp	Lenab1				| jmp to mapped code
+ Lehighcode:
+ 
+ 	/*
+ 	 * END MMU TRAMPOLINE.  Address register a5 is now free.
+ 	 */
+ 
+ /*
+  * Should be running mapped from this point on
+  */
+ Lenab1:
+ /* select the software page size now */
+ 	lea	tmpstk,sp		| temporary stack
+ 	jbsr	_vm_set_page_size	| select software page size
+ /* set kernel stack, user SP, and initial pcb */
+ 	movl	_proc0paddr,a1		| get proc0 pcb addr
+ 	lea	a1@(USPACE-4),sp	| set kernel stack to end of area
+ 	lea	_proc0,a2		| initialize proc0.p_addr so that
+ 	movl	a1,a2@(P_ADDR)		|   we don't deref NULL in trap()
+ 	movl	#USRSTACK-4,a2
+ 	movl	a2,usp			| init user SP
+ 	movl	a1,_curpcb		| proc0 is running
+ 
+ 	tstl	_fputype		| Have an FPU?
+ 	jeq	Lenab2			| No, skip.
+ 	clrl	a1@(PCB_FPCTX)		| ensure null FP context
+ 	movl	a1,sp@-
+ 	jbsr	_m68881_restore		| restore it (does not kill a1)
+ 	addql	#4,sp
+ Lenab2:
+ /* flush TLB and turn on caches */
+ 	jbsr	_TBIA			| invalidate TLB
+ 	cmpl	#MMU_68040,_mmutype	| 68040?
+ 	jeq	Lnocache0		| yes, cache already on
+ 	movl	#CACHE_ON,d0
+ 	movc	d0,cacr			| clear cache(s)
+ 	tstl	_ectype
+ 	jeq	Lnocache0
+ 	MMUADDR(a0)
+ 	orl	#MMU_CEN,a0@(MMUCMD)	| turn on external cache
+ Lnocache0:
+ /* Final setup for call to main(). */
+ 	jbsr	_intr_init		| initialize interrupt handlers
+ 	jbsr	_hp300_calibrate_delay	| calibrate delay() loop
+ 
+ /*
+  * Create a fake exception frame so that cpu_fork() can copy it.
+  * main() nevers returns; we exit to user mode from a forked process
+  * later on.
+  */
+ 	clrw	sp@-			| vector offset/frame type
+ 	clrl	sp@-			| PC - filled in by "execve"
+ 	movw	#PSL_USER,sp@-		| in user mode
+ 	clrl	sp@-			| stack adjust count and padding
+ 	lea	sp@(-64),sp		| construct space for D0-D7/A0-A7
+ 	lea	_proc0,a0		| save pointer to frame
+ 	movl	sp,a0@(P_MD_REGS)	|   in proc0.p_md.md_regs
+ 
+ 	jra	_main			| main()
+ 
+ 	pea	Lmainreturned		| Yow!  Main returned!
+ 	jbsr	_panic
+ 	/* NOTREACHED */
+ Lmainreturned:
+ 	.asciz	"main() returned"
+ 	.even
+ 
+ 	.globl	_proc_trampoline
+ _proc_trampoline:
+ 	movl	a3,sp@-
+ 	jbsr	a2@
+ 	addql	#4,sp
+ 	movl	sp@(FR_SP),a0		| grab and load
+ 	movl	a0,usp			|   user SP
+ 	moveml	sp@+,#0x7FFF		| restore most user regs
+ 	addql	#8,sp			| toss SP and stack adjust
+ 	jra	rei			| and return
+ 
+ 
+ /*
+  * Trap/interrupt vector routines
+  */ 
+ 
+ 	.globl	_trap, _nofault, _longjmp
+ _buserr:
+ 	/*
+ 	 * XXX TODO: look at the mac68k _buserr and generalize
+ 	 * XXX the saving of the fault address so this routine
+ 	 * XXX can be shared.
+ 	 */
+ 	tstl	_nofault		| device probe?
+ 	jeq	Lberr			| no, handle as usual
+ 	movl	_nofault,sp@-		| yes,
+ 	jbsr	_longjmp		|  longjmp(nofault)
+ Lberr:
+ #if defined(M68040)
+ #if defined(M68020) || defined(M68030)
+ 	cmpl	#MMU_68040,_mmutype	| 68040?
+ 	jne	_addrerr		| no, skip
+ #endif
+ 	clrl	sp@-			| stack adjust count
+ 	moveml	#0xFFFF,sp@-		| save user registers
+ 	movl	usp,a0			| save the user SP
+ 	movl	a0,sp@(FR_SP)		|   in the savearea
+ 	lea	sp@(FR_HW),a1		| grab base of HW berr frame
+ 	moveq	#0,d0
+ 	movw	a1@(12),d0		| grab SSW
+ 	movl	a1@(20),d1		| and fault VA
+ 	btst	#11,d0			| check for mis-aligned access
+ 	jeq	Lberr2			| no, skip
+ 	addl	#3,d1			| yes, get into next page
+ 	andl	#PG_FRAME,d1		| and truncate
+ Lberr2:
+ 	movl	d1,sp@-			| push fault VA
+ 	movl	d0,sp@-			| and padded SSW
+ 	btst	#10,d0			| ATC bit set?
+ 	jeq	Lisberr			| no, must be a real bus error
+ 	movc	dfc,d1			| yes, get MMU fault
+ 	movc	d0,dfc			| store faulting function code
+ 	movl	sp@(4),a0		| get faulting address
+ 	.word	0xf568			| ptestr a0@
+ 	movc	d1,dfc
+ 	.long	0x4e7a0805		| movc mmusr,d0
+ 	movw	d0,sp@			| save (ONLY LOW 16 BITS!)
+ 	jra	Lismerr
+ #endif
+ _addrerr:
+ 	clrl	sp@-			| stack adjust count
+ 	moveml	#0xFFFF,sp@-		| save user registers
+ 	movl	usp,a0			| save the user SP
+ 	movl	a0,sp@(FR_SP)		|   in the savearea
+ 	lea	sp@(FR_HW),a1		| grab base of HW berr frame
+ #if defined(M68040)
+ #if defined(M68020) || defined(M68030)
+ 	cmpl	#MMU_68040,_mmutype	| 68040?
+ 	jne	Lbenot040		| no, skip
+ #endif
+ 	movl	a1@(8),sp@-		| yes, push fault address
+ 	clrl	sp@-			| no SSW for address fault
+ 	jra	Lisaerr			| go deal with it
+ Lbenot040:
+ #endif
+ 	moveq	#0,d0
+ 	movw	a1@(10),d0		| grab SSW for fault processing
+ 	btst	#12,d0			| RB set?
+ 	jeq	LbeX0			| no, test RC
+ 	bset	#14,d0			| yes, must set FB
+ 	movw	d0,a1@(10)		| for hardware too
+ LbeX0:
+ 	btst	#13,d0			| RC set?
+ 	jeq	LbeX1			| no, skip
+ 	bset	#15,d0			| yes, must set FC
+ 	movw	d0,a1@(10)		| for hardware too
+ LbeX1:
+ 	btst	#8,d0			| data fault?
+ 	jeq	Lbe0			| no, check for hard cases
+ 	movl	a1@(16),d1		| fault address is as given in frame
+ 	jra	Lbe10			| thats it
+ Lbe0:
+ 	btst	#4,a1@(6)		| long (type B) stack frame?
+ 	jne	Lbe4			| yes, go handle
+ 	movl	a1@(2),d1		| no, can use save PC
+ 	btst	#14,d0			| FB set?
+ 	jeq	Lbe3			| no, try FC
+ 	addql	#4,d1			| yes, adjust address
+ 	jra	Lbe10			| done
+ Lbe3:
+ 	btst	#15,d0			| FC set?
+ 	jeq	Lbe10			| no, done
+ 	addql	#2,d1			| yes, adjust address
+ 	jra	Lbe10			| done
+ Lbe4:
+ 	movl	a1@(36),d1		| long format, use stage B address
+ 	btst	#15,d0			| FC set?
+ 	jeq	Lbe10			| no, all done
+ 	subql	#2,d1			| yes, adjust address
+ Lbe10:
+ 	movl	d1,sp@-			| push fault VA
+ 	movl	d0,sp@-			| and padded SSW
+ 	movw	a1@(6),d0		| get frame format/vector offset
+ 	andw	#0x0FFF,d0		| clear out frame format
+ 	cmpw	#12,d0			| address error vector?
+ 	jeq	Lisaerr			| yes, go to it
+ #if defined(M68K_MMU_MOTOROLA)
+ #if defined(M68K_MMU_HP)
+ 	tstl	_mmutype		| HP MMU?
+ 	jeq	Lbehpmmu		| yes, skip
+ #endif
+ 	movl	d1,a0			| fault address
+ 	movl	sp@,d0			| function code from ssw
+ 	btst	#8,d0			| data fault?
+ 	jne	Lbe10a
+ 	movql	#1,d0			| user program access FC
+ 					| (we dont separate data/program)
+ 	btst	#5,a1@			| supervisor mode?
+ 	jeq	Lbe10a			| if no, done
+ 	movql	#5,d0			| else supervisor program access
+ Lbe10a:
+ 	ptestr	d0,a0@,#7		| do a table search
+ 	pmove	psr,sp@			| save result
+ 	movb	sp@,d1
+ 	btst	#2,d1			| invalid? (incl. limit viol and berr)
+ 	jeq	Lmightnotbemerr		| no -> wp check
+ 	btst	#7,d1			| is it MMU table berr?
+ 	jeq	Lismerr			| no, must be fast
+ 	jra	Lisberr1		| real bus err needs not be fast
+ Lmightnotbemerr:
+ 	btst	#3,d1			| write protect bit set?
+ 	jeq	Lisberr1		| no, must be bus error
+ 	movl	sp@,d0			| ssw into low word of d0
+ 	andw	#0xc0,d0		| write protect is set on page:
+ 	cmpw	#0x40,d0		| was it read cycle?
+ 	jeq	Lisberr1		| yes, was not WPE, must be bus err
+ 	jra	Lismerr			| no, must be mem err
+ Lbehpmmu:
+ #endif
+ #if defined(M68K_MMU_HP)
+ 	MMUADDR(a0)
+ 	movl	a0@(MMUSTAT),d0		| read status
+ 	btst	#3,d0			| MMU fault?
+ 	jeq	Lisberr			| no, just a non-MMU bus error so skip
+ 	andl	#~MMU_FAULT,a0@(MMUSTAT)| yes, clear fault bits
+ 	movw	d0,sp@			| pass MMU stat in upper half of code
+ #endif
+ Lismerr:
+ 	movl	#T_MMUFLT,sp@-		| show that we are an MMU fault
+ 	jra	Ltrapnstkadj		| and deal with it
+ Lisaerr:
+ 	movl	#T_ADDRERR,sp@-		| mark address error
+ 	jra	Ltrapnstkadj		| and deal with it
+ Lisberr1:
+ 	clrw	sp@			| re-clear pad word
+ Lisberr:
+ 	movl	#T_BUSERR,sp@-		| mark bus error
+ Ltrapnstkadj:
+ 	jbsr	_trap			| handle the error
+ 	lea	sp@(12),sp		| pop value args
+ 	movl	sp@(FR_SP),a0		| restore user SP
+ 	movl	a0,usp			|   from save area
+ 	movw	sp@(FR_ADJ),d0		| need to adjust stack?
+ 	jne	Lstkadj			| yes, go to it
+ 	moveml	sp@+,#0x7FFF		| no, restore most user regs
+ 	addql	#8,sp			| toss SSP and stkadj
+ 	jra	rei			| all done
+ Lstkadj:
+ 	lea	sp@(FR_HW),a1		| pointer to HW frame
+ 	addql	#8,a1			| source pointer
+ 	movl	a1,a0			| source
+ 	addw	d0,a0			|  + hole size = dest pointer
+ 	movl	a1@-,a0@-		| copy
+ 	movl	a1@-,a0@-		|  8 bytes
+ 	movl	a0,sp@(FR_SP)		| new SSP
+ 	moveml	sp@+,#0x7FFF		| restore user registers
+ 	movl	sp@,sp			| and our SP
+ 	jra	rei			| all done
+ 
+ /*
+  * FP exceptions.
+  */
+ _fpfline:		/* XXXthorpej - candidate for vector patch */
+ #if defined(M68040)
+ 	cmpl	#FPU_68040,_fputype	| 68040 FPU?
+ 	jne	Lfp_unimp		| no, skip FPSP
+ 	cmpw	#0x202c,sp@(6)		| format type 2?
+ 	jne	_illinst		| no, not an FP emulation
+ Ldofp_unimp:
+ #ifdef FPSP
+ 	.globl fpsp_unimp
+ 	jmp	fpsp_unimp		| yes, go handle it
+ #endif
+ Lfp_unimp:
+ #endif /* M68040 */
+ #ifdef FPU_EMULATE
+ 	clrl	sp@-			| stack adjust count
+ 	moveml	#0xFFFF,sp@-		| save registers
+ 	moveq	#T_FPEMULI,d0		| denote as FP emulation trap
+ 	jra	fault			| do it
+ #else
+ 	jra	_illinst
+ #endif
+ 
+ _fpunsupp:		/* XXXthorpej - candidate for vector patch */
+ #if defined(M68040)
+ 	cmpl	#FPU_68040,_fputype	| 68040 FPU?
+ 	jne	_illinst		| no, treat as illinst
+ #ifdef FPSP
+ 	.globl	fpsp_unsupp
+ 	jmp	fpsp_unsupp		| yes, go handle it
+ #endif
+ Lfp_unsupp:
+ #endif /* M68040 */
+ #ifdef FPU_EMULATE
+ 	clrl	sp@-			| stack adjust count
+ 	moveml	#0xFFFF,sp@-		| save registers
+ 	moveq	#T_FPEMULD,d0		| denote as FP emulation trap
+ 	jra	fault			| do it
+ #else
+ 	jra	_illinst
+ #endif
+ 
+ /*
+  * Handles all other FP coprocessor exceptions.
+  * Note that since some FP exceptions generate mid-instruction frames
+  * and may cause signal delivery, we need to test for stack adjustment
+  * after the trap call.
+  */
+ 	.globl	_fpfault
+ _fpfault:
+ 	clrl	sp@-		| stack adjust count
+ 	moveml	#0xFFFF,sp@-	| save user registers
+ 	movl	usp,a0		| and save
+ 	movl	a0,sp@(FR_SP)	|   the user stack pointer
+ 	clrl	sp@-		| no VA arg
+ 	movl	_curpcb,a0	| current pcb
+ 	lea	a0@(PCB_FPCTX),a0 | address of FP savearea
+ 	fsave	a0@		| save state
+ #if defined(M68040) || defined(M68060)
+ 	/* always null state frame on 68040, 68060 */
+ 	cmpl	#CPU_68040,_cputype
+ 	jle	Lfptnull
+ #endif
+ 	tstb	a0@		| null state frame?
+ 	jeq	Lfptnull	| yes, safe
+ 	clrw	d0		| no, need to tweak BIU
+ 	movb	a0@(1),d0	| get frame size
+ 	bset	#3,a0@(0,d0:w)	| set exc_pend bit of BIU
+ Lfptnull:
+ 	fmovem	fpsr,sp@-	| push fpsr as code argument
+ 	frestore a0@		| restore state
+ 	movl	#T_FPERR,sp@-	| push type arg
+ 	jra	Ltrapnstkadj	| call trap and deal with stack cleanup
+ 
+ /*
+  * Coprocessor and format errors can generate mid-instruction stack
+  * frames and cause signal delivery hence we need to check for potential
+  * stack adjustment.
+  */
+ _coperr:
+ 	clrl	sp@-		| stack adjust count
+ 	moveml	#0xFFFF,sp@-
+ 	movl	usp,a0		| get and save
+ 	movl	a0,sp@(FR_SP)	|   the user stack pointer
+ 	clrl	sp@-		| no VA arg
+ 	clrl	sp@-		| or code arg
+ 	movl	#T_COPERR,sp@-	| push trap type
+ 	jra	Ltrapnstkadj	| call trap and deal with stack adjustments
+ 
+ _fmterr:
+ 	clrl	sp@-		| stack adjust count
+ 	moveml	#0xFFFF,sp@-
+ 	movl	usp,a0		| get and save
+ 	movl	a0,sp@(FR_SP)	|   the user stack pointer
+ 	clrl	sp@-		| no VA arg
+ 	clrl	sp@-		| or code arg
+ 	movl	#T_FMTERR,sp@-	| push trap type
+ 	jra	Ltrapnstkadj	| call trap and deal with stack adjustments
+ 
+ /*
+  * Other exceptions only cause four and six word stack frame and require
+  * no post-trap stack adjustment.
+  */
+ _illinst:
+ 	clrl	sp@-
+ 	moveml	#0xFFFF,sp@-
+ 	moveq	#T_ILLINST,d0
+ 	jra	fault
+ 
+ _zerodiv:
+ 	clrl	sp@-
+ 	moveml	#0xFFFF,sp@-
+ 	moveq	#T_ZERODIV,d0
+ 	jra	fault
+ 
+ _chkinst:
+ 	clrl	sp@-
+ 	moveml	#0xFFFF,sp@-
+ 	moveq	#T_CHKINST,d0
+ 	jra	fault
+ 
+ _trapvinst:
+ 	clrl	sp@-
+ 	moveml	#0xFFFF,sp@-
+ 	moveq	#T_TRAPVINST,d0
+ 	jra	fault
+ 
+ _privinst:
+ 	clrl	sp@-
+ 	moveml	#0xFFFF,sp@-
+ 	moveq	#T_PRIVINST,d0
+ 	jra	fault
+ 
+ 	.globl	fault
+ fault:
+ 	movl	usp,a0			| get and save
+ 	movl	a0,sp@(FR_SP)		|   the user stack pointer
+ 	clrl	sp@-			| no VA arg
+ 	clrl	sp@-			| or code arg
+ 	movl	d0,sp@-			| push trap type
+ 	jbsr	_trap			| handle trap
+ 	lea	sp@(12),sp		| pop value args
+ 	movl	sp@(FR_SP),a0		| restore
+ 	movl	a0,usp			|   user SP
+ 	moveml	sp@+,#0x7FFF		| restore most user regs
+ 	addql	#8,sp			| pop SP and stack adjust
+ 	jra	rei			| all done
+ 
+ 	.globl	_straytrap
+ _badtrap:
+ 	moveml	#0xC0C0,sp@-		| save scratch regs
+ 	movw	sp@(22),sp@-		| push exception vector info
+ 	clrw	sp@-
+ 	movl	sp@(22),sp@-		| and PC
+ 	jbsr	_straytrap		| report
+ 	addql	#8,sp			| pop args
+ 	moveml	sp@+,#0x0303		| restore regs
+ 	jra	rei			| all done
+ 
+ 	.globl	_syscall
+ _trap0:
+ 	clrl	sp@-			| stack adjust count
+ 	moveml	#0xFFFF,sp@-		| save user registers
+ 	movl	usp,a0			| save the user SP
+ 	movl	a0,sp@(FR_SP)		|   in the savearea
+ 	movl	d0,sp@-			| push syscall number
+ 	jbsr	_syscall		| handle it
+ 	addql	#4,sp			| pop syscall arg
+ 	tstl	_astpending
+ 	jne	Lrei2
+ 	tstb	_ssir
+ 	jeq	Ltrap1
+ 	movw	#SPL1,sr
+ 	tstb	_ssir
+ 	jne	Lsir1
+ Ltrap1:	
+ 	movl	sp@(FR_SP),a0		| grab and restore
+ 	movl	a0,usp			|   user SP
+ 	moveml	sp@+,#0x7FFF		| restore most registers
+ 	addql	#8,sp			| pop SP and stack adjust
+ 	rte
+ 
+ /*
+  * Trap 1 - sigreturn
+  */
+ _trap1:
+ 	jra	sigreturn
+ 
+ /*
+  * Trap 2 - trace trap
+  */
+ _trap2:
+ 	jra	_trace
+ 
+ /*
+  * Trap 12 is the entry point for the cachectl "syscall" (both HPUX & BSD)
+  *	cachectl(command, addr, length)
+  * command in d0, addr in a1, length in d1
+  */
+ 	.globl	_cachectl
+ _trap12:
+ 	movl	d1,sp@-			| push length
+ 	movl	a1,sp@-			| push addr
+ 	movl	d0,sp@-			| push command
+ 	jbsr	_cachectl		| do it
+ 	lea	sp@(12),sp		| pop args
+ 	jra	rei			| all done
+ 
+ /*
+  * Trace (single-step) trap.  Kernel-mode is special.
+  * User mode traps are simply passed on to trap().
+  */
+ _trace:
+ 	clrl	sp@-			| stack adjust count
+ 	moveml	#0xFFFF,sp@-
+ 	moveq	#T_TRACE,d0
+ 	movw	sp@(FR_HW),d1		| get PSW
+ 	andw	#PSL_S,d1		| from system mode?
+ 	jne	kbrkpt			| yes, kernel breakpoint
+ 	jra	fault			| no, user-mode fault
+ 
+ /*
+  * Trap 15 is used for:
+  *	- GDB breakpoints (in user programs)
+  *	- KGDB breakpoints (in the kernel)
+  *	- trace traps for SUN binaries (not fully supported yet)
+  * User mode traps are simply passed to trap().
+  */
+ _trap15:
+ 	clrl	sp@-			| stack adjust count
+ 	moveml	#0xFFFF,sp@-
+ 	moveq	#T_TRAP15,d0
+ 	movw	sp@(FR_HW),d1		| get PSW
+ 	andw	#PSL_S,d1		| from system mode?
+ 	jne	kbrkpt			| yes, kernel breakpoint
+ 	jra	fault			| no, user-mode fault
+ 
+ kbrkpt:	| Kernel-mode breakpoint or trace trap. (d0=trap_type)
+ 	| Save the system sp rather than the user sp.
+ 	movw	#PSL_HIGHIPL,sr		| lock out interrupts
+ 	lea	sp@(FR_SIZE),a6		| Save stack pointer
+ 	movl	a6,sp@(FR_SP)		|  from before trap
+ 
+ 	| If were are not on tmpstk switch to it.
+ 	| (so debugger can change the stack pointer)
+ 	movl	a6,d1
+ 	cmpl	#tmpstk,d1
+ 	jls	Lbrkpt2			| already on tmpstk
+ 	| Copy frame to the temporary stack
+ 	movl	sp,a0			| a0=src
+ 	lea	tmpstk-96,a1		| a1=dst
+ 	movl	a1,sp			| sp=new frame
+ 	moveq	#FR_SIZE,d1
+ Lbrkpt1:
+ 	movl	a0@+,a1@+
+ 	subql	#4,d1
+ 	bgt	Lbrkpt1
+ 
+ Lbrkpt2:
+ 	| Call the trap handler for the kernel debugger.
+ 	| Do not call trap() to do it, so that we can
+ 	| set breakpoints in trap() if we want.  We know
+ 	| the trap type is either T_TRACE or T_BREAKPOINT.
+ 	| If we have both DDB and KGDB, let KGDB see it first,
+ 	| because KGDB will just return 0 if not connected.
+ 	| Save args in d2, a2
+ 	movl	d0,d2			| trap type
+ 	movl	sp,a2			| frame ptr
+ #ifdef KGDB
+ 	| Let KGDB handle it (if connected)
+ 	movl	a2,sp@-			| push frame ptr
+ 	movl	d2,sp@-			| push trap type
+ 	jbsr	_kgdb_trap		| handle the trap
+ 	addql	#8,sp			| pop args
+ 	cmpl	#0,d0			| did kgdb handle it?
+ 	jne	Lbrkpt3			| yes, done
+ #endif
+ #ifdef DDB
+ 	| Let DDB handle it
+ 	movl	a2,sp@-			| push frame ptr
+ 	movl	d2,sp@-			| push trap type
+ 	jbsr	_kdb_trap		| handle the trap
+ 	addql	#8,sp			| pop args
+ #if 0	/* not needed on hp300 */
+ 	cmpl	#0,d0			| did ddb handle it?
+ 	jne	Lbrkpt3			| yes, done
+ #endif
+ #endif
+ 	/* Sun 3 drops into PROM here. */
+ Lbrkpt3:
+ 	| The stack pointer may have been modified, or
+ 	| data below it modified (by kgdb push call),
+ 	| so push the hardware frame at the current sp
+ 	| before restoring registers and returning.
+ 
+ 	movl	sp@(FR_SP),a0		| modified sp
+ 	lea	sp@(FR_SIZE),a1		| end of our frame
+ 	movl	a1@-,a0@-		| copy 2 longs with
+ 	movl	a1@-,a0@-		| ... predecrement
+ 	movl	a0,sp@(FR_SP)		| sp = h/w frame
+ 	moveml	sp@+,#0x7FFF		| restore all but sp
+ 	movl	sp@,sp			| ... and sp
+ 	rte				| all done
+ 
+ /* Use common m68k sigreturn */
+ #include <m68k/m68k/sigreturn.s>
+ 
+ /*
+  * Interrupt handlers.
+  * All device interrupts are auto-vectored.  The CPU provides
+  * the vector 0x18+level.  Note we count spurious interrupts, but
+  * we don't do anything else with them.
+  */
+ 
+ #define INTERRUPT_SAVEREG	moveml	#0xC0C0,sp@-
+ #define INTERRUPT_RESTOREREG	moveml	sp@+,#0x0303
+ 
+ 	/* Externs. */
+ 	.globl	_hilint, _intr_dispatch, _nmihand
+ 	.globl	_hardclock, _statintr
+ 
+ _spurintr:	/* Level 0 */
+ 	addql	#1,_intrcnt+0
+ 	addql	#1,_cnt+V_INTR
+ 	jra	rei
+ 
+ _lev1intr:	/* Level 1: HIL XXX this needs to go away */
+ 	INTERRUPT_SAVEREG
+ 	jbsr	_hilint
+ 	INTERRUPT_RESTOREREG
+ 	addql	#1,_intrcnt+4
+ 	addql	#1,_cnt+V_INTR
+ 	jra	rei
+ 
+ _intrhand:	/* Levels 2 through 5 */
+ 	INTERRUPT_SAVEREG
+ 	movw	sp@(22),sp@-		| push exception vector info
+ 	clrw	sp@-
+ 	jbsr	_intr_dispatch		| call dispatch routine
+ 	addql	#4,sp
+ 	INTERRUPT_RESTOREREG
+ 	jra	rei			| all done
+ 
+ _lev6intr:	/* Level 6: clock */
+ 	INTERRUPT_SAVEREG
+ 	CLKADDR(a0)
+ 	movb	a0@(CLKSR),d0		| read clock status
+ Lclkagain:
+ 	btst	#0,d0			| clear timer1 int immediately to
+ 	jeq	Lnotim1			|  minimize chance of losing another
+ 	movpw	a0@(CLKMSB1),d1		|  due to statintr processing delay
+ Lnotim1:
+ 	btst	#2,d0			| timer3 interrupt?
+ 	jeq	Lnotim3			| no, skip statclock
+ 	movpw	a0@(CLKMSB3),d1		| clear timer3 interrupt
+ 	addql	#1,_intrcnt+28		| count clock interrupts
+ 	lea	sp@(16),a1		| a1 = &clockframe
+ 	movl	d0,sp@-			| save status
+ 	movl	a1,sp@-
+ 	jbsr	_statintr		| statintr(&frame)
+ 	addql	#4,sp
+ 	movl	sp@+,d0			| restore pre-statintr status
+ 	CLKADDR(a0)
+ Lnotim3:
+ 	btst	#0,d0			| timer1 interrupt?
+ 	jeq	Lrecheck		| no, skip hardclock
+ 	addql	#1,_intrcnt+24		| count hardclock interrupts
+ 	lea	sp@(16),a1		| a1 = &clockframe
+ 	movl	a1,sp@-
+ #ifdef USELEDS
+ 	.globl	_ledaddr, _inledcontrol, _ledcontrol, _hz
+ 	tstl	_ledaddr		| using LEDs?
+ 	jeq	Lnoled0			| no, skip this code
+ 	movl	heartbeat,d0		| get tick count
+ 	addql	#1,d0			|  increment
+ 	movl	_hz,d1
+ 	addl	#50,d1			| get the timing a little closer
+ 	cmpl	#0,beatstatus		| time to slow down?
+ 	jeq	SlowThrob
+ 	lsrl	#3,d1			| fast throb
+ SlowThrob:
+ 	lsrl	#1,d1			| slow throb
+ 	cmpl	d0,d1			| are we there yet?
+ 	jne	Lnoled1			| no, nothing to do
+ 	tstl	_inledcontrol		| already updating LEDs?
+ 	jne	Lnoled2			| yes, skip it
+ 	addl	#1,beatstatus		| incr beat status
+ 	cmpl	#3,beatstatus		| time to reset?
+ 	ble	SkipReset
+ 	movl	#0,beatstatus		| reset the status indicator
+ SkipReset:
+ 	movl	#LED_PULSE,sp@-
+ 	movl	#LED_DISK+LED_LANRCV+LED_LANXMT,sp@-
+ 	clrl	sp@-
+ 	jbsr	_ledcontrol		| toggle pulse, turn all others off
+ 	lea	sp@(12),sp
+ Lnoled2:
+ 	movql	#0,d0
+ Lnoled1:
+ 	movl	d0,heartbeat
+ Lnoled0:
+ #endif
+ 	jbsr	_hardclock		| hardclock(&frame)
+ 	addql	#4,sp
+ 	CLKADDR(a0)
+ Lrecheck:
+ 	addql	#1,_cnt+V_INTR		| chalk up another interrupt
+ 	movb	a0@(CLKSR),d0		| see if anything happened
+ 	jmi	Lclkagain		|  while we were in hardclock/statintr
+ 	INTERRUPT_RESTOREREG
+ 	jra	rei			| all done
+ 
+ _lev7intr:	/* Level 7: Parity errors, reset key */
+ 	addql	#1,_intrcnt+32
+ 	clrl	sp@-
+ 	moveml	#0xFFFF,sp@-		| save registers
+ 	movl	usp,a0			| and save
+ 	movl	a0,sp@(FR_SP)		|   the user stack pointer
+ 	jbsr	_nmihand		| call handler
+ 	movl	sp@(FR_SP),a0		| restore
+ 	movl	a0,usp			|   user SP
+ 	moveml	sp@+,#0x7FFF		| and remaining registers
+ 	addql	#8,sp			| pop SP and stack adjust
+ 	jra	rei			| all done
+ 
+ /*
+  * Emulation of VAX REI instruction.
+  *
+  * This code deals with checking for and servicing ASTs
+  * (profiling, scheduling) and software interrupts (network, softclock).
+  * We check for ASTs first, just like the VAX.  To avoid excess overhead
+  * the T_ASTFLT handling code will also check for software interrupts so we
+  * do not have to do it here.  After identifing that we need an AST we
+  * drop the IPL to allow device interrupts.
+  *
+  * This code is complicated by the fact that sendsig may have been called
+  * necessitating a stack cleanup.
+  */
+ 	.comm	_ssir,1
+ 	.globl	_astpending
+ 	.globl	rei
+ rei:
+ 	tstl	_astpending		| AST pending?
+ 	jeq	Lchksir			| no, go check for SIR
+ Lrei1:
+ 	btst	#5,sp@			| yes, are we returning to user mode?
+ 	jne	Lchksir			| no, go check for SIR
+ 	movw	#PSL_LOWIPL,sr		| lower SPL
+ 	clrl	sp@-			| stack adjust
+ 	moveml	#0xFFFF,sp@-		| save all registers
+ 	movl	usp,a1			| including
+ 	movl	a1,sp@(FR_SP)		|    the users SP
+ Lrei2:
+ 	clrl	sp@-			| VA == none
+ 	clrl	sp@-			| code == none
+ 	movl	#T_ASTFLT,sp@-		| type == async system trap
+ 	jbsr	_trap			| go handle it
+ 	lea	sp@(12),sp		| pop value args
+ 	movl	sp@(FR_SP),a0		| restore user SP
+ 	movl	a0,usp			|   from save area
+ 	movw	sp@(FR_ADJ),d0		| need to adjust stack?
+ 	jne	Laststkadj		| yes, go to it
+ 	moveml	sp@+,#0x7FFF		| no, restore most user regs
+ 	addql	#8,sp			| toss SP and stack adjust
+ 	rte				| and do real RTE
+ Laststkadj:
+ 	lea	sp@(FR_HW),a1		| pointer to HW frame
+ 	addql	#8,a1			| source pointer
+ 	movl	a1,a0			| source
+ 	addw	d0,a0			|  + hole size = dest pointer
+ 	movl	a1@-,a0@-		| copy
+ 	movl	a1@-,a0@-		|  8 bytes
+ 	movl	a0,sp@(FR_SP)		| new SSP
+ 	moveml	sp@+,#0x7FFF		| restore user registers
+ 	movl	sp@,sp			| and our SP
+ 	rte				| and do real RTE
+ Lchksir:
+ 	tstb	_ssir			| SIR pending?
+ 	jeq	Ldorte			| no, all done
+ 	movl	d0,sp@-			| need a scratch register
+ 	movw	sp@(4),d0		| get SR
+ 	andw	#PSL_IPL7,d0		| mask all but IPL
+ 	jne	Lnosir			| came from interrupt, no can do
+ 	movl	sp@+,d0			| restore scratch register
+ Lgotsir:
+ 	movw	#SPL1,sr		| prevent others from servicing int
+ 	tstb	_ssir			| too late?
+ 	jeq	Ldorte			| yes, oh well...
+ 	clrl	sp@-			| stack adjust
+ 	moveml	#0xFFFF,sp@-		| save all registers
+ 	movl	usp,a1			| including
+ 	movl	a1,sp@(FR_SP)		|    the users SP
+ Lsir1:	
+ 	clrl	sp@-			| VA == none
+ 	clrl	sp@-			| code == none
+ 	movl	#T_SSIR,sp@-		| type == software interrupt
+ 	jbsr	_trap			| go handle it
+ 	lea	sp@(12),sp		| pop value args
+ 	movl	sp@(FR_SP),a0		| restore
+ 	movl	a0,usp			|   user SP
+ 	moveml	sp@+,#0x7FFF		| and all remaining registers
+ 	addql	#8,sp			| pop SP and stack adjust
+ 	rte
+ Lnosir:
+ 	movl	sp@+,d0			| restore scratch register
+ Ldorte:
+ 	rte				| real return
+ 
+ /*
+  * Use common m68k sigcode.
+  */
+ #include <m68k/m68k/sigcode.s>
+ 
+ /*
+  * Primitives
+  */ 
+ 
+ #include <machine/asm.h>
+ 
+ /*
+  * Use common m68k support routines.
+  */
+ #include <m68k/m68k/support.s>
+ 
+ 	.globl	_whichqs,_qs,_cnt,_panic
+ 	.globl	_curproc,_want_resched
+ 
+ /*
+  * Use common m68k process manipulation routines.
+  */
+ #include <m68k/m68k/proc_subr.s>
+ 
+ Lsw0:
+ 	.asciz	"switch"
+ 	.even
+ 
+ 	.globl	_curpcb
+ 	.globl	_masterpaddr	| XXX compatibility (debuggers)
+ 	.data
+ _masterpaddr:			| XXX compatibility (debuggers)
+ _curpcb:
+ 	.long	0
+ mdpflag:
+ 	.byte	0		| copy of proc md_flags low byte
+ 	.align	2
+ 	.comm	nullpcb,SIZEOF_PCB
+ 	.text
+ 
+ /*
+  * At exit of a process, do a switch for the last time.
+  * Switch to a safe stack and PCB, and deallocate the process's resources.
+  */
+ ENTRY(switch_exit)
+ 	movl	sp@(4),a0
+ 	movl	#nullpcb,_curpcb	| save state into garbage pcb
+ 	lea	tmpstk,sp		| goto a tmp stack
+ 
+ 	/* Free old process's resources. */
+ 	movl	#USPACE,sp@-		| size of u-area
+ 	movl	a0@(P_ADDR),sp@-	| address of process's u-area
+ 	movl	_kernel_map,sp@-	| map it was allocated in
+ 	jbsr	_kmem_free		| deallocate it
+ 	lea	sp@(12),sp		| pop args
+ 
+ 	jra	_cpu_switch
+ 
+ /*
+  * When no processes are on the runq, Swtch branches to Idle
+  * to wait for something to come ready.
+  */
+ 	.globl	Idle
+ Idle:
+ 	stop	#PSL_LOWIPL
+ 	movw	#PSL_HIGHIPL,sr
+ 	movl	_whichqs,d0
+ 	jeq	Idle
+ 	jra	Lsw1
+ 
+ Lbadsw:
+ 	movl	#Lsw0,sp@-
+ 	jbsr	_panic
+ 	/*NOTREACHED*/
+ 
+ /*
+  * cpu_switch()
+  *
+  * NOTE: On the mc68851 (318/319/330) we attempt to avoid flushing the
+  * entire ATC.  The effort involved in selective flushing may not be
+  * worth it, maybe we should just flush the whole thing?
+  *
+  * NOTE 2: With the new VM layout we now no longer know if an inactive
+  * user's PTEs have been changed (formerly denoted by the SPTECHG p_flag
+  * bit).  For now, we just always flush the full ATC.
+  */
+ ENTRY(cpu_switch)
+ 	movl	_curpcb,a0		| current pcb
+ 	movw	sr,a0@(PCB_PS)		| save sr before changing ipl
+ #ifdef notyet
+ 	movl	_curproc,sp@-		| remember last proc running
+ #endif
+ 	clrl	_curproc
+ 
+ 	/*
+ 	 * Find the highest-priority queue that isn't empty,
+ 	 * then take the first proc from that queue.
+ 	 */
+ 	movw	#PSL_HIGHIPL,sr		| lock out interrupts
+ 	movl	_whichqs,d0
+ 	jeq	Idle
+ Lsw1:
+ 	movl	d0,d1
+ 	negl	d0
+ 	andl	d1,d0
+ 	bfffo	d0{#0:#32},d1
+ 	eorib	#31,d1
+ 
+ 	movl	d1,d0
+ 	lslb	#3,d1			| convert queue number to index
+ 	addl	#_qs,d1			| locate queue (q)
+ 	movl	d1,a1
+ 	movl	a1@(P_FORW),a0		| p = q->p_forw
+ 	cmpal	d1,a0			| anyone on queue?
+ 	jeq	Lbadsw			| no, panic
+ 	movl	a0@(P_FORW),a1@(P_FORW)	| q->p_forw = p->p_forw
+ 	movl	a0@(P_FORW),a1		| n = p->p_forw
+ 	movl	d1,a1@(P_BACK)		| n->p_back = q
+ 	cmpal	d1,a1			| anyone left on queue?
+ 	jne	Lsw2			| yes, skip
+ 	movl	_whichqs,d1
+ 	bclr	d0,d1			| no, clear bit
+ 	movl	d1,_whichqs
+ Lsw2:
+ 	movl	a0,_curproc
+ 	clrl	_want_resched
+ #ifdef notyet
+ 	movl	sp@+,a1
+ 	cmpl	a0,a1			| switching to same proc?
+ 	jeq	Lswdone			| yes, skip save and restore
+ #endif
+ 	/*
+ 	 * Save state of previous process in its pcb.
+ 	 */
+ 	movl	_curpcb,a1
+ 	moveml	#0xFCFC,a1@(PCB_REGS)	| save non-scratch registers
+ 	movl	usp,a2			| grab USP (a2 has been saved)
+ 	movl	a2,a1@(PCB_USP)		| and save it
+ 
+ 	tstl	_fputype		| Do we have an FPU?
+ 	jeq	Lswnofpsave		| No  Then don't attempt save.
+ 	lea	a1@(PCB_FPCTX),a2	| pointer to FP save area
+ 	fsave	a2@			| save FP state
+ 	tstb	a2@			| null state frame?
+ 	jeq	Lswnofpsave		| yes, all done
+ 	fmovem	fp0-fp7,a2@(216)	| save FP general registers
+ 	fmovem	fpcr/fpsr/fpi,a2@(312)	| save FP control registers
+ Lswnofpsave:
+ 
+ #ifdef DIAGNOSTIC
+ 	tstl	a0@(P_WCHAN)
+ 	jne	Lbadsw
+ 	cmpb	#SRUN,a0@(P_STAT)
+ 	jne	Lbadsw
+ #endif
+ 	clrl	a0@(P_BACK)		| clear back link
+ 	movb	a0@(P_MD_FLAGS+3),mdpflag | low byte of p_md.md_flags
+ 	movl	a0@(P_ADDR),a1		| get p_addr
+ 	movl	a1,_curpcb
+ 
+ 	/* see if pmap_activate needs to be called; should remove this */
+ 	movl	a0@(P_VMSPACE),a0	| vmspace = p->p_vmspace
+ #ifdef DIAGNOSTIC
+ 	tstl	a0			| map == VM_MAP_NULL?
+ 	jeq	Lbadsw			| panic
+ #endif
+ 	lea	a0@(VM_PMAP),a0		| pmap = &vmspace.vm_pmap
+ 	tstl	a0@(PM_STCHG)		| pmap->st_changed?
+ 	jeq	Lswnochg		| no, skip
+ 	pea	a1@			| push pcb (at p_addr)
+ 	pea	a0@			| push pmap
+ 	jbsr	_pmap_activate		| pmap_activate(pmap, pcb)
+ 	addql	#8,sp
+ 	movl	_curpcb,a1		| restore p_addr
+ Lswnochg:
+ 
+ 	lea	tmpstk,sp		| now goto a tmp stack for NMI
+ #if defined(M68040)
+ #if defined(M68020) || defined(M68030)
+ 	cmpl	#MMU_68040,_mmutype	| 68040?
+ 	jne	Lres1a			| no, skip
+ #endif
+ 	.word	0xf518			| yes, pflusha
+ 	movl	a1@(PCB_USTP),d0	| get USTP
+ 	moveq	#PGSHIFT,d1
+ 	lsll	d1,d0			| convert to addr
+ 	.long	0x4e7b0806		| movc d0,urp
+ 	jra	Lcxswdone
+ Lres1a:
+ #endif
+ 	movl	#CACHE_CLR,d0
+ 	movc	d0,cacr			| invalidate cache(s)
+ #if defined(M68K_MMU_MOTOROLA)
+ #if defined(M68K_MMU_HP)
+ 	tstl	_mmutype		| HP MMU?
+ 	jeq	Lhpmmu4			| yes, skip
+ #endif
+ 	pflusha				| flush entire TLB
+ 	movl	a1@(PCB_USTP),d0	| get USTP
+ 	moveq	#PGSHIFT,d1
+ 	lsll	d1,d0			| convert to addr
+ 	lea	_protorp,a0		| CRP prototype
+ 	movl	d0,a0@(4)		| stash USTP
+ 	pmove	a0@,crp			| load new user root pointer
+ 	jra	Lcxswdone		| thats it
+ Lhpmmu4:	
+ #endif
+ #if defined(M68K_MMU_HP)
+ 	MMUADDR(a0)
+ 	movl	a0@(MMUTBINVAL),d1	| invalidate TLB
+ 	tstl	_ectype			| got external VAC?
+ 	jle	Lnocache1		| no, skip
+ 	andl	#~MMU_CEN,a0@(MMUCMD)	| toggle cache enable
+ 	orl	#MMU_CEN,a0@(MMUCMD)	| to clear data cache
+ Lnocache1:
+ 	movl	a1@(PCB_USTP),a0@(MMUUSTP) | context switch
+ #endif
+ Lcxswdone:
+ 	moveml	a1@(PCB_REGS),#0xFCFC	| and registers
+ 	movl	a1@(PCB_USP),a0
+ 	movl	a0,usp			| and USP
+ 
+ 	tstl	_fputype		| If we don't have an FPU,
+ 	jeq	Lnofprest		|  don't try to restore it.
+ 	lea	a1@(PCB_FPCTX),a0	| pointer to FP save area
+ 	tstb	a0@			| null state frame?
+ 	jeq	Lresfprest		| yes, easy
+ #if defined(M68040)
+ #if defined(M68020) || defined(M68030)
+ 	cmpl	#MMU_68040,_mmutype	| 68040?
+ 	jne	Lresnot040		| no, skip
+ #endif
+ 	clrl	sp@-			| yes...
+ 	frestore sp@+			| ...magic!
+ Lresnot040:
+ #endif
+ 	fmovem	a0@(312),fpcr/fpsr/fpi	| restore FP control registers
+ 	fmovem	a0@(216),fp0-fp7	| restore FP general registers
+ Lresfprest:
+ 	frestore a0@			| restore state
+ 
+ Lnofprest:
+ 	movw	a1@(PCB_PS),sr		| no, restore PS
+ 	moveq	#1,d0			| return 1 (for alternate returns)
+ 	rts
+ 
+ /*
+  * savectx(pcb)
+  * Update pcb, saving current processor state.
+  */
+ ENTRY(savectx)
+ 	movl	sp@(4),a1
+ 	movw	sr,a1@(PCB_PS)
+ 	movl	usp,a0			| grab USP
+ 	movl	a0,a1@(PCB_USP)		| and save it
+ 	moveml	#0xFCFC,a1@(PCB_REGS)	| save non-scratch registers
+ 
+ 	tstl	_fputype		| Do we have FPU?
+ 	jeq	Lsvnofpsave		| No?  Then don't save state.
+ 	lea	a1@(PCB_FPCTX),a0	| pointer to FP save area
+ 	fsave	a0@			| save FP state
+ 	tstb	a0@			| null state frame?
+ 	jeq	Lsvnofpsave		| yes, all done
+ 	fmovem	fp0-fp7,a0@(216)	| save FP general registers
+ 	fmovem	fpcr/fpsr/fpi,a0@(312)	| save FP control registers
+ Lsvnofpsave:
+ 	moveq	#0,d0			| return 0
+ 	rts
+ 
+ #if defined(M68040)
+ ENTRY(suline)
+ 	movl	sp@(4),a0		| address to write
+ 	movl	_curpcb,a1		| current pcb
+ 	movl	#Lslerr,a1@(PCB_ONFAULT) | where to return to on a fault
+ 	movl	sp@(8),a1		| address of line
+ 	movl	a1@+,d0			| get lword
+ 	movsl	d0,a0@+			| put lword
+ 	nop				| sync
+ 	movl	a1@+,d0			| get lword
+ 	movsl	d0,a0@+			| put lword
+ 	nop				| sync
+ 	movl	a1@+,d0			| get lword
+ 	movsl	d0,a0@+			| put lword
+ 	nop				| sync
+ 	movl	a1@+,d0			| get lword
+ 	movsl	d0,a0@+			| put lword
+ 	nop				| sync
+ 	moveq	#0,d0			| indicate no fault
+ 	jra	Lsldone
+ Lslerr:
+ 	moveq	#-1,d0
+ Lsldone:
+ 	movl	_curpcb,a1		| current pcb
+ 	clrl	a1@(PCB_ONFAULT) 	| clear fault address
+ 	rts
+ #endif
+ 
+ /*
+  * Invalidate entire TLB.
+  */
+ ENTRY(TBIA)
+ __TBIA:
+ #if defined(M68040)
+ 	cmpl	#MMU_68040,_mmutype	| 68040?
+ 	jne	Lmotommu3		| no, skip
+ 	.word	0xf518			| yes, pflusha
+ 	rts
+ Lmotommu3:
+ #endif
+ #if defined(M68K_MMU_MOTOROLA)
+ 	tstl	_mmutype		| HP MMU?
+ 	jeq	Lhpmmu6			| yes, skip
+ 	pflusha				| flush entire TLB
+ 	jpl	Lmc68851a		| 68851 implies no d-cache
+ 	movl	#DC_CLEAR,d0
+ 	movc	d0,cacr			| invalidate on-chip d-cache
+ Lmc68851a:
+ 	rts
+ Lhpmmu6:
+ #endif
+ #if defined(M68K_MMU_HP)
+ 	MMUADDR(a0)
+ 	movl	a0@(MMUTBINVAL),sp@-	| do not ask me, this
+ 	addql	#4,sp			|   is how hpux does it
+ #ifdef DEBUG
+ 	tstl	fullcflush
+ 	jne	__DCIA			| XXX: invalidate entire cache
+ #endif
+ #endif
+ 	rts
+ 
+ /*
+  * Invalidate any TLB entry for given VA (TB Invalidate Single)
+  */
+ ENTRY(TBIS)
+ #ifdef DEBUG
+ 	tstl	fulltflush		| being conservative?
+ 	jne	__TBIA			| yes, flush entire TLB
+ #endif
+ #if defined(M68040)
+ 	cmpl	#MMU_68040,_mmutype	| 68040?
+ 	jne	Lmotommu4		| no, skip
+ 	movl	sp@(4),a0
+ 	movc	dfc,d1
+ 	moveq	#1,d0			| user space
+ 	movc	d0,dfc
+ 	.word	0xf508			| pflush a0@
+ 	moveq	#5,d0			| super space
+ 	movc	d0,dfc
+ 	.word	0xf508			| pflush a0@
+ 	movc	d1,dfc
+ 	rts
+ Lmotommu4:
+ #endif
+ #if defined(M68K_MMU_MOTOROLA)
+ 	tstl	_mmutype		| HP MMU?
+ 	jeq	Lhpmmu5			| yes, skip
+ 	movl	sp@(4),a0		| get addr to flush
+ 	jpl	Lmc68851b		| is 68851?
+ 	pflush	#0,#0,a0@		| flush address from both sides
+ 	movl	#DC_CLEAR,d0
+ 	movc	d0,cacr			| invalidate on-chip data cache
+ 	rts
+ Lmc68851b:
+ 	pflushs	#0,#0,a0@		| flush address from both sides
+ 	rts
+ Lhpmmu5:
+ #endif
+ #if defined(M68K_MMU_HP)
+ 	movl	sp@(4),d0		| VA to invalidate
+ 	bclr	#0,d0			| ensure even
+ 	movl	d0,a0
+ 	movw	sr,d1			| go critical
+ 	movw	#PSL_HIGHIPL,sr		|   while in purge space
+ 	moveq	#FC_PURGE,d0		| change address space
+ 	movc	d0,dfc			|   for destination
+ 	moveq	#0,d0			| zero to invalidate?
+ 	movsl	d0,a0@			| hit it
+ 	moveq	#FC_USERD,d0		| back to old
+ 	movc	d0,dfc			|   address space
+ 	movw	d1,sr			| restore IPL
+ #endif
+ 	rts
+ 
+ /*
+  * Invalidate supervisor side of TLB
+  */
+ ENTRY(TBIAS)
+ #ifdef DEBUG
+ 	tstl	fulltflush		| being conservative?
+ 	jne	__TBIA			| yes, flush everything
+ #endif
+ #if defined(M68040)
+ 	cmpl	#MMU_68040,_mmutype	| 68040?
+ 	jne	Lmotommu5		| no, skip
+ 	.word	0xf518			| yes, pflusha (for now) XXX
+ 	rts
+ Lmotommu5:
+ #endif
+ #if defined(M68K_MMU_MOTOROLA)
+ 	tstl	_mmutype		| HP MMU?
+ 	jeq	Lhpmmu7			| yes, skip
+ 	jpl	Lmc68851c		| 68851?
+ 	pflush #4,#4			| flush supervisor TLB entries
+ 	movl	#DC_CLEAR,d0
+ 	movc	d0,cacr			| invalidate on-chip d-cache
+ 	rts
+ Lmc68851c:
+ 	pflushs #4,#4			| flush supervisor TLB entries
+ 	rts
+ Lhpmmu7:
+ #endif
+ #if defined(M68K_MMU_HP)
+ 	MMUADDR(a0)
+ 	movl	#0x8000,d0		| more
+ 	movl	d0,a0@(MMUTBINVAL)	|   HP magic
+ #ifdef DEBUG
+ 	tstl	fullcflush
+ 	jne	__DCIS			| XXX: invalidate entire sup. cache
+ #endif
+ #endif
+ 	rts
+ 
+ /*
+  * Invalidate user side of TLB
+  */
+ ENTRY(TBIAU)
+ #ifdef DEBUG
+ 	tstl	fulltflush		| being conservative?
+ 	jne	__TBIA			| yes, flush everything
+ #endif
+ #if defined(M68040)
+ 	cmpl	#MMU_68040,_mmutype	| 68040?
+ 	jne	Lmotommu6		| no, skip
+ 	.word	0xf518			| yes, pflusha (for now) XXX
+ 	rts
+ Lmotommu6:
+ #endif
+ #if defined(M68K_MMU_MOTOROLA)
+ 	tstl	_mmutype		| HP MMU?
+ 	jeq	Lhpmmu8			| yes, skip
+ 	jpl	Lmc68851d		| 68851?
+ 	pflush	#0,#4			| flush user TLB entries
+ 	movl	#DC_CLEAR,d0
+ 	movc	d0,cacr			| invalidate on-chip d-cache
+ 	rts
+ Lmc68851d:
+ 	pflushs	#0,#4			| flush user TLB entries
+ 	rts
+ Lhpmmu8:
+ #endif
+ #if defined(M68K_MMU_HP)
+ 	MMUADDR(a0)
+ 	moveq	#0,d0			| more
+ 	movl	d0,a0@(MMUTBINVAL)	|   HP magic
+ #ifdef DEBUG
+ 	tstl	fullcflush
+ 	jne	__DCIU			| XXX: invalidate entire user cache
+ #endif
+ #endif
+ 	rts
+ 
+ /*
+  * Invalidate instruction cache
+  */
+ ENTRY(ICIA)
+ #if defined(M68040)
+ ENTRY(ICPA)
+ 	cmpl	#MMU_68040,_mmutype	| 68040
+ 	jne	Lmotommu7		| no, skip
+ 	.word	0xf498			| cinva ic
+ 	rts
+ Lmotommu7:
+ #endif
+ 	movl	#IC_CLEAR,d0
+ 	movc	d0,cacr			| invalidate i-cache
+ 	rts
+ 
+ /*
+  * Invalidate data cache.
+  * HP external cache allows for invalidation of user/supervisor portions.
+  * NOTE: we do not flush 68030 on-chip cache as there are no aliasing
+  * problems with DC_WA.  The only cases we have to worry about are context
+  * switch and TLB changes, both of which are handled "in-line" in resume
+  * and TBI*.
+  */
+ ENTRY(DCIA)
+ __DCIA:
+ #if defined(M68040)
+ 	cmpl	#MMU_68040,_mmutype	| 68040
+ 	jne	Lmotommu8		| no, skip
+ 	/* XXX implement */
+ 	rts
+ Lmotommu8:
+ #endif
+ #if defined(M68K_MMU_HP)
+ 	tstl	_ectype			| got external VAC?
+ 	jle	Lnocache2		| no, all done
+ 	MMUADDR(a0)
+ 	andl	#~MMU_CEN,a0@(MMUCMD)	| disable cache in MMU control reg
+ 	orl	#MMU_CEN,a0@(MMUCMD)	| reenable cache in MMU control reg
+ Lnocache2:
+ #endif
+ 	rts
+ 
+ ENTRY(DCIS)
+ __DCIS:
+ #if defined(M68040)
+ 	cmpl	#MMU_68040,_mmutype	| 68040
+ 	jne	Lmotommu9		| no, skip
+ 	/* XXX implement */
+ 	rts
+ Lmotommu9:
+ #endif
+ #if defined(M68K_MMU_HP)
+ 	tstl	_ectype			| got external VAC?
+ 	jle	Lnocache3		| no, all done
+ 	MMUADDR(a0)
+ 	movl	a0@(MMUSSTP),d0		| read the supervisor STP
+ 	movl	d0,a0@(MMUSSTP)		| write it back
+ Lnocache3:
+ #endif
+ 	rts
+ 
+ ENTRY(DCIU)
+ __DCIU:
+ #if defined(M68040)
+ 	cmpl	#MMU_68040,_mmutype	| 68040
+ 	jne	LmotommuA		| no, skip
+ 	/* XXX implement */
+ 	rts
+ LmotommuA:
+ #endif
+ #if defined(M68K_MMU_HP)
+ 	tstl	_ectype			| got external VAC?
+ 	jle	Lnocache4		| no, all done
+ 	MMUADDR(a0)
+ 	movl	a0@(MMUUSTP),d0		| read the user STP
+ 	movl	d0,a0@(MMUUSTP)		| write it back
+ Lnocache4:
+ #endif
+ 	rts
+ 
+ #if defined(M68040)
+ ENTRY(ICPL)
+ 	movl	sp@(4),a0		| address
+ 	.word	0xf488			| cinvl ic,a0@
+ 	rts
+ ENTRY(ICPP)
+ 	movl	sp@(4),a0		| address
+ 	.word	0xf490			| cinvp ic,a0@
+ 	rts
+ ENTRY(DCPL)
+ 	movl	sp@(4),a0		| address
+ 	.word	0xf448			| cinvl dc,a0@
+ 	rts
+ ENTRY(DCPP)
+ 	movl	sp@(4),a0		| address
+ 	.word	0xf450			| cinvp dc,a0@
+ 	rts
+ ENTRY(DCPA)
+ 	.word	0xf458			| cinva dc
+ 	rts
+ ENTRY(DCFL)
+ 	movl	sp@(4),a0		| address
+ 	.word	0xf468			| cpushl dc,a0@
+ 	rts
+ ENTRY(DCFP)
+ 	movl	sp@(4),a0		| address
+ 	.word	0xf470			| cpushp dc,a0@
+ 	rts
+ #endif
+ 
+ ENTRY(PCIA)
+ #if defined(M68040)
+ ENTRY(DCFA)
+ 	cmpl	#MMU_68040,_mmutype	| 68040
+ 	jne	LmotommuB		| no, skip
+ 	.word	0xf478			| cpusha dc
+ 	rts
+ LmotommuB:
+ #endif
+ #if defined(M68K_MMU_MOTOROLA)
+ 	movl	#DC_CLEAR,d0
+ 	movc	d0,cacr			| invalidate on-chip d-cache
+ 	tstl	_ectype			| got external PAC?
+ 	jge	Lnocache6		| no, all done
+ 	MMUADDR(a0)
+ 	andl	#~MMU_CEN,a0@(MMUCMD)	| disable cache in MMU control reg
+ 	orl	#MMU_CEN,a0@(MMUCMD)	| reenable cache in MMU control reg
+ Lnocache6:
+ #endif
+ 	rts
+ 
+ ENTRY(ecacheon)
+ 	tstl	_ectype
+ 	jeq	Lnocache7
+ 	MMUADDR(a0)
+ 	orl	#MMU_CEN,a0@(MMUCMD)
+ Lnocache7:
+ 	rts
+ 
+ ENTRY(ecacheoff)
+ 	tstl	_ectype
+ 	jeq	Lnocache8
+ 	MMUADDR(a0)
+ 	andl	#~MMU_CEN,a0@(MMUCMD)
+ Lnocache8:
+ 	rts
+ 
+ 	.globl	_getsfc, _getdfc
+ _getsfc:
+ 	movc	sfc,d0
+ 	rts
+ _getdfc:
+ 	movc	dfc,d0
+ 	rts
+ 
+ /*
+  * Load a new user segment table pointer.
+  */
+ ENTRY(loadustp)
+ #if defined(M68K_MMU_MOTOROLA)
+ 	tstl	_mmutype		| HP MMU?
+ 	jeq	Lhpmmu9			| yes, skip
+ 	movl	sp@(4),d0		| new USTP
+ 	moveq	#PGSHIFT,d1
+ 	lsll	d1,d0			| convert to addr
+ #if defined(M68040)
+ 	cmpl	#MMU_68040,_mmutype	| 68040?
+ 	jne	LmotommuC		| no, skip
+ 	.long	0x4e7b0806		| movc d0,urp
+ 	rts
+ LmotommuC:
+ #endif
+ 	lea	_protorp,a0		| CRP prototype
+ 	movl	d0,a0@(4)		| stash USTP
+ 	pmove	a0@,crp			| load root pointer
+ 	movl	#DC_CLEAR,d0
+ 	movc	d0,cacr			| invalidate on-chip d-cache
+ 	rts				|   since pmove flushes TLB
+ Lhpmmu9:
+ #endif
+ #if defined(M68K_MMU_HP)
+ 	MMUADDR(a0)
+ 	movl	sp@(4),a0@(MMUUSTP)	| load a new USTP
+ #endif
+ 	rts
+ 
+ ENTRY(ploadw)
+ #if defined(M68K_MMU_MOTOROLA)
+ 	movl	sp@(4),a0		| address to load
+ #if defined(M68K_MMU_HP)
+ 	tstl	_mmutype		| HP MMU?
+ 	jeq	Lploadwskp		| yes, skip
+ #endif
+ #if defined(M68040)
+ 	cmpl	#MMU_68040,_mmutype	| 68040?
+ 	jeq	Lploadwskp		| yes, skip
+ #endif
+ 	ploadw	#1,a0@			| pre-load translation
+ Lploadwskp:
+ #endif
+ 	rts
+ 
+ /*
+  * Set processor priority level calls.  Most are implemented with
+  * inline asm expansions.  However, spl0 requires special handling
+  * as we need to check for our emulated software interrupts.
+  */
+ 
+ ENTRY(spl0)
+ 	moveq	#0,d0
+ 	movw	sr,d0			| get old SR for return
+ 	movw	#PSL_LOWIPL,sr		| restore new SR
+ 	tstb	_ssir			| software interrupt pending?
+ 	jeq	Lspldone		| no, all done
+ 	subql	#4,sp			| make room for RTE frame
+ 	movl	sp@(4),sp@(2)		| position return address
+ 	clrw	sp@(6)			| set frame type 0
+ 	movw	#PSL_LOWIPL,sp@		| and new SR
+ 	jra	Lgotsir			| go handle it
+ Lspldone:
+ 	rts
+ 
+ /*
+  * _delay(u_int N)
+  *
+  * Delay for at least (N/256) microsecends.
+  * This routine depends on the variable:  delay_divisor
+  * which should be set based on the CPU clock rate.
+  */
+ 	.globl	__delay
+ __delay:
+ 	| d0 = arg = (usecs << 8)
+ 	movl	sp@(4),d0
+ 	| d1 = delay_divisor
+ 	movl	_delay_divisor,d1
+ L_delay:
+ 	subl	d1,d0
+ 	jgt	L_delay
+ 	rts
+ 
+ /*
+  * Save and restore 68881 state.
+  * Pretty awful looking since our assembler does not
+  * recognize FP mnemonics.
+  */
+ ENTRY(m68881_save)
+ 	movl	sp@(4),a0		| save area pointer
+ 	fsave	a0@			| save state
+ 	tstb	a0@			| null state frame?
+ 	jeq	Lm68881sdone		| yes, all done
+ 	fmovem fp0-fp7,a0@(216)		| save FP general registers
+ 	fmovem fpcr/fpsr/fpi,a0@(312)	| save FP control registers
+ Lm68881sdone:
+ 	rts
+ 
+ ENTRY(m68881_restore)
+ 	movl	sp@(4),a0		| save area pointer
+ 	tstb	a0@			| null state frame?
+ 	jeq	Lm68881rdone		| yes, easy
+ 	fmovem	a0@(312),fpcr/fpsr/fpi	| restore FP control registers
+ 	fmovem	a0@(216),fp0-fp7	| restore FP general registers
+ Lm68881rdone:
+ 	frestore a0@			| restore state
+ 	rts
+ 
+ /*
+  * Handle the nitty-gritty of rebooting the machine.
+  * Basically we just turn off the MMU and jump to the appropriate ROM routine.
+  * Note that we must be running in an address range that is mapped one-to-one
+  * logical to physical so that the PC is still valid immediately after the MMU
+  * is turned off.  We have conveniently mapped the last page of physical
+  * memory this way.
+  */
+ 	.globl	_doboot
+ _doboot:
+ #if defined(M68040)
+ 	cmpl	#MMU_68040,_mmutype	| 68040?
+ 	jeq	Lnocache5		| yes, skip
+ #endif
+ 	movl	#CACHE_OFF,d0
+ 	movc	d0,cacr			| disable on-chip cache(s)
+ 	tstl	_ectype			| external cache?
+ 	jeq	Lnocache5		| no, skip
+ 	MMUADDR(a0)
+ 	andl	#~MMU_CEN,a0@(MMUCMD)	| disable external cache
+ Lnocache5:
+ 	lea	MAXADDR,a0		| last page of physical memory
+ 	movl	_boothowto,a0@+		| store howto
+ 	movl	_bootdev,a0@+		| and devtype
+ 	lea	Lbootcode,a1		| start of boot code
+ 	lea	Lebootcode,a3		| end of boot code
+ Lbootcopy:
+ 	movw	a1@+,a0@+		| copy a word
+ 	cmpl	a3,a1			| done yet?
+ 	jcs	Lbootcopy		| no, keep going
+ #if defined(M68040)
+ 	cmpl	#MMU_68040,_mmutype	| 68040?
+ 	jne	LmotommuE		| no, skip
+ 	.word	0xf4f8			| cpusha bc
+ LmotommuE:
+ #endif
+ 	jmp	MAXADDR+8		| jump to last page
+ 
+ #define DOREBOOT						\
+ 	/* Reset Vector Base Register to what PROM expects. */	\
+ 	movl	#0,d0;						\
+ 	movc	d0,vbr;						\
+ 	/* Jump to REQ_REBOOT */				\
+ 	jmp	0x1A4;
+ 
+ Lbootcode:
+ 	lea	MAXADDR+0x800,sp	| physical SP in case of NMI
+ #if defined(M68040)
+ 	cmpl	#MMU_68040,_mmutype	| 68040?
+ 	jne	LmotommuF		| no, skip
+ 	movl	#0,d0
+ 	movc	d0,cacr			| caches off
+ 	.long	0x4e7b0003		| movc d0,tc
+ 	movl	d2,MAXADDR+NBPG-4	| restore old high page contents
+ 	DOREBOOT
+ LmotommuF:
+ #endif
+ #if defined(M68K_MMU_MOTOROLA)
+ 	tstl	_mmutype		| HP MMU?
+ 	jeq	LhpmmuB			| yes, skip
+ 	movl	#0,a0@			| value for pmove to TC (turn off MMU)
+ 	pmove	a0@,tc			| disable MMU
+ 	DOREBOOT
+ LhpmmuB:
+ #endif
+ #if defined(M68K_MMU_HP)
+ 	MMUADDR(a0)
+ 	movl	#0xFFFF0000,a0@(MMUCMD)	| totally disable MMU
+ 	movl	d2,MAXADDR+NBPG-4	| restore old high page contents
+ 	DOREBOOT
+ #endif
+ Lebootcode:
+ 
+ #undef DOREBOOT
+ 
+ 	.data
+ 	.globl	_machineid,_mmuid,_mmutype,_cputype,_ectype,_fputype
+ 	.globl	_protorp,_prototc
+ _machineid:
+ 	.long	HP_320		| default to 320
+ _mmuid:
+ 	.long	0		| default to ???
+ _mmutype:
+ 	.long	MMU_HP		| default to HP MMU
+ _cputype:
+ 	.long	CPU_68020	| default to 68020 CPU
+ _ectype:
+ 	.long	EC_NONE		| external cache type, default to none
+ _fputype:
+ 	.long	FPU_68881	| default to 68881 FPU
+ _protorp:
+ 	.long	0,0		| prototype root pointer
+ _prototc:
+ 	.long	0		| prototype translation control
+ 	.globl	_internalhpib
+ _internalhpib:
+ 	.long	1		| has internal HP-IB, default to yes
+ 	.globl	_cold
+ _cold:
+ 	.long	1		| cold start flag
+ 	.globl	_want_resched
+ _want_resched:
+ 	.long	0
+ 	.globl	_intiobase, _intiolimit, _extiobase, _CLKbase, _MMUbase
+ 	.globl	_proc0paddr, _pagezero
+ _proc0paddr:
+ 	.long	0		| KVA of proc0 u-area
+ _intiobase:
+ 	.long	0		| KVA of base of internal IO space
+ _intiolimit:
+ 	.long	0		| KVA of end of internal IO space
+ _extiobase:
+ 	.long	0		| KVA of base of external IO space
+ _CLKbase:
+ 	.long	0		| KVA of base of clock registers
+ _MMUbase:
+ 	.long	0		| KVA of base of HP MMU registers
+ _pagezero:
+ 	.long	0		| PA of first page of kernel text
+ #ifdef USELEDS
+ heartbeat:
+ 	.long	0		| clock ticks since last pulse of heartbeat
+ beatstatus:
+ 	.long	0		| for determining a fast or slow throb
+ #endif
+ #ifdef DEBUG
+ 	.globl	fulltflush, fullcflush
+ fulltflush:
+ 	.long	0
+ fullcflush:
+ 	.long	0
+ #endif
+ /* interrupt counters */
+ 	.globl	_intrcnt,_eintrcnt,_intrnames,_eintrnames
+ _intrnames:
+ 	.asciz	"spur"
+ 	.asciz	"hil"
+ 	.asciz	"lev2"
+ 	.asciz	"lev3"
+ 	.asciz	"lev4"
+ 	.asciz	"lev5"
+ 	.asciz	"clock"
+ 	.asciz  "statclock"
+ 	.asciz	"nmi"
+ _eintrnames:
+ 	.even
+ _intrcnt:
+ 	.long	0,0,0,0,0,0,0,0,0
+ _eintrcnt:
diff -crN /sys/arch/hp300/hp300/machdep.c hp300/machdep.c
*** /sys/arch/hp300/hp300/machdep.c	Thu Apr 10 04:18:24 1997
--- hp300/machdep.c	Wed Apr 23 20:12:11 1997
***************
*** 478,483 ****
--- 478,486 ----
  	case HP_340:
  		t = "340 (16.67MHz";
  		break;
+ 	case HP_345:
+ 		t = "345 (???MHz";
+ 		break;
  	case HP_350:
  		t = "350 (25MHz";
  		break;
***************
*** 493,498 ****
--- 496,507 ----
  	case HP_380:
  		t = "380/425 (25MHz";
  		break;
+ 	case HP_400:
+ 		t = "400 (50MHz";
+ 		break;
+ 	case HP_425:
+ 		t = "425 (25MHz";
+ 		break;
  	case HP_433:
  		t = "433 (33MHz";
  		break;
***************
*** 542,548 ****
  	}
  	strcat(cpu_model, ")");
  	printf("%s\n", cpu_model);
! 	printf("delay constant for this cpu: %d\n", delay_divisor);
  	/*
  	 * Now that we have told the user what they have,
  	 * let them know if that machine type isn't configured.
--- 551,558 ----
  	}
  	strcat(cpu_model, ")");
  	printf("%s\n", cpu_model);
! 	printf("delay constant for this cpu: %d   MMU ID: %x\n", 
! 	       delay_divisor, mmuid);
  	/*
  	 * Now that we have told the user what they have,
  	 * let them know if that machine type isn't configured.
diff -crN /sys/arch/hp300/stand/Makefile.inc stand/Makefile.inc
*** /sys/arch/hp300/stand/Makefile.inc	Tue Apr 15 04:17:55 1997
--- stand/Makefile.inc	Thu Apr 24 01:26:11 1997
***************
*** 16,24 ****

  COMMONSOURCE=		srt0.o autoconf.c clock.c conf.c cons.c devopen.c \
  			machdep.c prf.c rawfs.c netio.c
! DRIVERSOURCE=		ct.c dca.c dcm.c fhpib.c hil.c hpib.c if_le.c \
  			ite.c ite_dv.c ite_gb.c ite_rb.c ite_subr.c \
! 			ite_tc.c ite_hy.c nhpib.c rd.c scsi.c sd.c

  ### Figure out what to use for mkboot
  MKBOOTDIR=		${.CURDIR}/../mkboot
--- 16,25 ----

  COMMONSOURCE=		srt0.o autoconf.c clock.c conf.c cons.c devopen.c \
  			machdep.c prf.c rawfs.c netio.c
! DRIVERSOURCE=		ct.c dca.c dcm.c dnkbd.c fhpib.c hil.c hpib.c if_le.c \
  			ite.c ite_dv.c ite_gb.c ite_rb.c ite_subr.c \
! 			ite_tc.c ite_hy.c kbd.c kbdconf.c nhpib.c rd.c \
! 			scsi.c sd.c

  ### Figure out what to use for mkboot
  MKBOOTDIR=		${.CURDIR}/../mkboot
diff -crN /sys/arch/hp300/stand/common/hil.c stand/common/hil.c
*** /sys/arch/hp300/stand/common/hil.c	Tue Apr 15 04:17:55 1997
--- stand/common/hil.c	Wed Apr 23 19:49:28 1997
***************
*** 185,191 ****
   * The keyboard map table.
   * Lookup is by hardware returned language code.
   */
! struct kbdmap hilkbd_map[] = {
  	KBD_US,		NULL,
  	hil_us_keymap,	hil_us_shiftmap, hil_us_ctrlmap, NULL,	NULL,

--- 185,191 ----
   * The keyboard map table.
   * Lookup is by hardware returned language code.
   */
! struct hil_kbdmap hilkbd_map[] = {
  	KBD_US,		NULL,
  	hil_us_keymap,	hil_us_shiftmap, hil_us_ctrlmap, NULL,	NULL,

***************
*** 246,252 ****
  hilkbd_init()
  {
  	struct hil_dev *hiladdr = HILADDR;
! 	struct kbdmap *km;
  	u_char lang;

  	/*
--- 246,252 ----
  hilkbd_init()
  {
  	struct hil_dev *hiladdr = HILADDR;
! 	struct hil_kbdmap *km;
  	u_char lang;

  	/*
>Release-Note:
>Audit-Trail:
Responsible-Changed-From-To: kern-bug-people->thorpej 
Responsible-Changed-By: thorpej 
Responsible-Changed-When: Fri Apr 25 17:14:15 PDT 1997 
Responsible-Changed-Why:  
hp300 port is my responsibility. 
State-Changed-From-To: open->analyzed 
State-Changed-By: thorpej 
State-Changed-When: Fri Apr 25 17:15:04 PDT 1997 
State-Changed-Why:  
Needs some integration work, but is generally sane. 
From: "Izumi Tsutsui" <tsutsui@netbsd.org>
To: gnats-bugs@gnats.NetBSD.org
Cc: 
Subject: PR/3528 CVS commit: src/sys/arch/hp300
Date: Sat, 12 Feb 2011 15:49:02 +0000

 Module Name:	src
 Committed By:	tsutsui
 Date:		Sat Feb 12 15:49:02 UTC 2011

 Modified Files:
 	src/sys/arch/hp300/conf: GENERIC files.hp300
 Added Files:
 	src/sys/arch/hp300/dev: dnkbd.c dnkbdmap.c dnkbdmap.h

 Log Message:
 Pull Apollo Domain keyboard and mouse support from OpenBSD.
 Untested (no hardware), but no bad sideeffect on 425t without Domain keyboard.

 This is the last portion of "new hp300 kernel features" submitted in
 PR port-hp300/3528 back in 1997, and I think finally we can close it.


 To generate a diff of this commit:
 cvs rdiff -u -r1.163 -r1.164 src/sys/arch/hp300/conf/GENERIC
 cvs rdiff -u -r1.81 -r1.82 src/sys/arch/hp300/conf/files.hp300
 cvs rdiff -u -r0 -r1.1 src/sys/arch/hp300/dev/dnkbd.c \
     src/sys/arch/hp300/dev/dnkbdmap.c src/sys/arch/hp300/dev/dnkbdmap.h

 Please note that diffs are not public domain; they are subject to the
 copyright notices on the relevant files.

Responsible-Changed-From-To: thorpej->tsutsui
Responsible-Changed-By: tsutsui@NetBSD.org
Responsible-Changed-When: Sat, 05 Mar 2011 20:47:16 +0900
Responsible-Changed-Why:
as current maintainer


State-Changed-From-To: analyzed->closed
State-Changed-By: tsutsui@NetBSD.org
State-Changed-When: Sat, 05 Mar 2011 20:47:16 +0900
State-Changed-Why:
Finally NetBSD/hp300 kernel has all features including dnkbd.

>Unformatted:

NetBSD Home
NetBSD PR Database Search

(Contact us) $NetBSD: query-full-pr,v 1.39 2013/11/01 18:47:49 spz Exp $
$NetBSD: gnats_config.sh,v 1.8 2006/05/07 09:23:38 tsutsui Exp $
Copyright © 1994-2007 The NetBSD Foundation, Inc. ALL RIGHTS RESERVED.