Subject: kern/3528: New hp300 kernel features
To: None <gnats-bugs@gnats.netbsd.org>
From: Mike <mike@pressed.spam.frisbee.net.au>
List: netbsd-bugs
Date: 04/24/1997 09:40:13
>Number:         3528
>Category:       kern
>Synopsis:       New hp300 kernel features
>Confidential:   no
>Severity:       non-critical
>Priority:       medium
>Responsible:    kern-bug-people (Kernel Bug People)
>State:          open
>Class:          change-request
>Submitter-Id:   net
>Arrival-Date:   Thu Apr 24 09:50:01 1997
>Last-Modified:
>Originator:     Mike
>Organization:
	Mike Smith Network Support
>Release:        1.2D ~20/4/97
>Environment:
	HP9000/4xx
System: NetBSD pressed.spam.frisbee.net.au 1.2D NetBSD 1.2D (TEST) #4: Thu Apr 24 08:17:51 PDT 1997 mike@pressed.spam.frisbee.net.au:/remote6/hp300/playpen/sys/arch/hp300/compile/TEST hp300


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


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