From 003c873954c56a73b4954c316e1450ace0986f95 Mon Sep 17 00:00:00 2001
From: Hakan Olsson <ho@cvs.openbsd.org>
Date: Mon, 29 Jan 2001 08:45:59 +0000
Subject: Driver for the Pijnenburg PCC-ISES crypto chip. For now, it only
 generates random data for the system entropy pool. No crypto yet.

---
 sys/dev/pci/files.pci |    7 +-
 sys/dev/pci/ises.c    | 1366 +++++++++++++++++++++++++++++++++++++++++++++++++
 sys/dev/pci/isesreg.h |  645 +++++++++++++++++++++++
 sys/dev/pci/isesvar.h |   83 +++
 4 files changed, 2100 insertions(+), 1 deletion(-)
 create mode 100644 sys/dev/pci/ises.c
 create mode 100644 sys/dev/pci/isesreg.h
 create mode 100644 sys/dev/pci/isesvar.h

(limited to 'sys/dev/pci')

diff --git a/sys/dev/pci/files.pci b/sys/dev/pci/files.pci
index 7b630a71b71..635bb29c246 100644
--- a/sys/dev/pci/files.pci
+++ b/sys/dev/pci/files.pci
@@ -1,4 +1,4 @@
-#	$OpenBSD: files.pci,v 1.91 2001/01/23 04:19:42 krw Exp $
+#	$OpenBSD: files.pci,v 1.92 2001/01/29 08:45:58 ho Exp $
 #	$NetBSD: files.pci,v 1.20 1996/09/24 17:47:15 christos Exp $
 #
 # Config file and device description for machine-independent PCI code.
@@ -254,6 +254,11 @@ device	ubsec: crypto
 attach	ubsec at pci
 file	dev/pci/ubsec.c			ubsec
 
+# Pijnenburg PCC-ISES
+device	ises: crypto
+attach	ises at pci
+file	dev/pci/ises.c			ises
+
 # Winbond W89C840F ethernet
 device	wb: ether, ifnet, mii, ifmedia, mii_phy
 attach	wb at pci
diff --git a/sys/dev/pci/ises.c b/sys/dev/pci/ises.c
new file mode 100644
index 00000000000..ad0a4f3c638
--- /dev/null
+++ b/sys/dev/pci/ises.c
@@ -0,0 +1,1366 @@
+/*	$OpenBSD: ises.c,v 1.1 2001/01/29 08:45:58 ho Exp $	*/
+
+/*
+ * Copyright (c) 2000 H�kan Olsson (ho@crt.se)
+ * 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.
+ * 3. 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 AUTHOR ``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 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.
+ */
+
+/*
+ * PCC-ISES hardware crypto accelerator
+ */
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/proc.h>
+#include <sys/errno.h>
+#include <sys/malloc.h>
+#include <sys/kernel.h>
+#include <sys/mbuf.h>
+#include <sys/timeout.h>
+#include <vm/vm.h>
+#include <vm/vm_extern.h>
+#include <vm/pmap.h>
+#include <machine/pmap.h>
+#include <sys/device.h>
+#include <sys/queue.h>
+
+#include <crypto/crypto.h>
+#include <crypto/cryptosoft.h>
+#include <dev/rndvar.h>
+#include <sys/md5k.h>
+#include <crypto/sha1.h>
+#include <crypto/rmd160.h>
+
+#include <dev/pci/pcireg.h>
+#include <dev/pci/pcivar.h>
+#include <dev/pci/pcidevs.h>
+
+#include <dev/pci/isesreg.h>
+#include <dev/pci/isesvar.h>
+
+/*
+ * Prototypes and count for the pci_device structure
+ */
+int	ises_match __P((struct device *, void *, void *));
+void	ises_attach __P((struct device *, struct device *, void *));
+
+void	ises_initstate __P((void *));
+void	ises_hrng_init __P((struct ises_softc *));
+void	ises_hrng __P((void *));
+void	ises_process_oqueue __P((struct ises_softc *));
+int	ises_queue_cmd __P((struct ises_softc *, u_int32_t, u_int32_t *));
+u_int32_t ises_get_fwversion __P((struct ises_softc *));
+int	ises_assert_cmd_mode __P((struct ises_softc *));
+
+int	ises_intr __P((void *));
+int	ises_newsession __P((u_int32_t *, struct cryptoini *));
+int	ises_freesession __P((u_int64_t));
+int	ises_process __P((struct cryptop *));
+void	ises_callback __P((struct ises_q *));
+int	ises_feed __P((struct ises_softc *));
+
+/* XXX for now... */
+void    ubsec_mcopy __P((struct mbuf *, struct mbuf *, int, int));
+
+#define	READ_REG(sc,r) \
+    bus_space_read_4((sc)->sc_memt, (sc)->sc_memh,r)
+
+#define WRITE_REG(sc,reg,val) \
+    bus_space_write_4((sc)->sc_memt, (sc)->sc_memh, reg, val)
+
+#define	SWAP32(x) ((x) = swap32((x)))
+
+#ifdef ISESDEBUG
+#  define DPRINTF(x) printf x
+#else
+#  define DPRINTF(x)
+#endif
+
+/* For HRNG entropy collection, these values gather 5KB/s */
+#ifndef ISESRNGBITS
+#define ISESRNGBITS	4096		/* Bits per iteration */
+#define ISESRNGIPS	10		/* Iterations per second */
+#endif
+
+struct cfattach ises_ca = {
+	sizeof (struct ises_softc), ises_match, ises_attach,
+};
+
+struct cfdriver ises_cd = {
+	0, "ises", DV_DULL
+};
+
+int
+ises_match(struct device *parent, void *match, void *aux)
+{
+	struct pci_attach_args *pa = (struct pci_attach_args *) aux;
+
+	if (PCI_VENDOR(pa->pa_id) == PCI_VENDOR_PIJNENBURG &&
+	    PCI_PRODUCT(pa->pa_id) == PCI_PRODUCT_PIJNENBURG_PCC_ISES)
+		return (1);
+
+	return (0);
+}
+
+void
+ises_attach(struct device *parent, struct device *self, void *aux)
+{
+	struct ises_softc *sc = (struct ises_softc *)self;
+	struct pci_attach_args *pa = aux;
+	pci_chipset_tag_t pc = pa->pa_pc;
+	pci_intr_handle_t ih;
+	const char *intrstr = NULL;
+	bus_addr_t membase;
+	bus_size_t memsize;
+	u_int32_t cmd;
+
+	bus_dma_segment_t seg;
+	int nsegs, error, state;
+
+	SIMPLEQ_INIT(&sc->sc_queue);
+	SIMPLEQ_INIT(&sc->sc_qchip);
+	state = 0;
+
+	/* Verify PCI space */
+	cmd = pci_conf_read(pc, pa->pa_tag, PCI_COMMAND_STATUS_REG);
+	cmd |= PCI_COMMAND_MEM_ENABLE | PCI_COMMAND_MASTER_ENABLE;
+	pci_conf_write(pc, pa->pa_tag, PCI_COMMAND_STATUS_REG, cmd);
+	cmd = pci_conf_read(pc, pa->pa_tag, PCI_COMMAND_STATUS_REG);
+
+	if (!(cmd & PCI_COMMAND_MEM_ENABLE)) {
+		printf(": failed to enable memory mapping\n");
+		return;
+	}
+
+	if (!(cmd & PCI_COMMAND_MASTER_ENABLE)) {
+		printf(": failed to enable bus mastering\n");
+		return;
+	}
+
+	/* Map control/status registers. */
+	if (pci_mapreg_map (pa, PCI_MAPREG_START, 
+			    PCI_MAPREG_TYPE_MEM | PCI_MAPREG_MEM_TYPE_32BIT,
+			    0, &sc->sc_memt, &sc->sc_memh, &membase, 
+			    &memsize)) {
+		printf(": can't find mem space\n");
+		return;
+	}
+	state++;
+
+	/* Map interrupt. */
+	if (pci_intr_map(pc, pa->pa_intrtag, pa->pa_intrpin, pa->pa_intrline,
+			 &ih)) {
+		printf(": couldn't map interrupt\n");
+		goto fail;
+	}
+	state++;
+
+	intrstr = pci_intr_string(pc, ih);
+	sc->sc_ih = pci_intr_establish(pc, ih, IPL_NET, ises_intr, sc,
+	    self->dv_xname);
+	if (sc->sc_ih == NULL) {
+		printf(": couldn't establish interrupt\n");
+		if (intrstr != NULL)
+			printf(" at %s", intrstr);
+		printf("\n");
+		goto fail;
+	}
+
+	/* Initialize DMA map */
+	sc->sc_dmat = pa->pa_dmat;
+	error = bus_dmamap_create (sc->sc_dmat, 1 << PGSHIFT, 1, 1 << PGSHIFT,
+				   0, BUS_DMA_NOWAIT | BUS_DMA_ALLOCNOW, 
+				   &sc->sc_dmamap_xfer);
+	if (error) {
+		printf (": cannot create dma map (%d)\n", error);
+		goto fail;
+	}
+	state++;
+
+	/* Allocate in DMAable memory. */
+	if (bus_dmamem_alloc (sc->sc_dmat, sizeof sc->sc_dmamap, 1, 0, &seg, 
+			      1, &nsegs, BUS_DMA_NOWAIT)) {
+		printf (": can't alloc dma buffer space\n");
+		goto fail;
+	}
+	state++;
+
+	sc->sc_dmamap_phys = seg.ds_addr;
+	if (bus_dmamem_map (sc->sc_dmat, &seg, nsegs, sizeof sc->sc_dmamap,
+			    (caddr_t *)&sc->sc_dmamap, 0)) {
+		printf (": can't map dma buffer space\n");
+		goto fail;
+	}
+	state++;
+
+	printf(": %s\n", intrstr);
+
+	sc->sc_cid = crypto_get_driverid();
+
+	if (sc->sc_cid < 0)
+		goto fail;
+
+	/* 
+	 * Since none of the initialization steps generate interrupts
+	 * for example, the hardware reset, we use a number of timeouts
+	 * (or init states) to do the rest of the chip initialization.
+	 */
+
+	sc->sc_initstate = 0;
+	timeout_set (&sc->sc_timeout, ises_initstate, sc);
+	ises_initstate (sc); 
+
+	return;
+
+ fail:
+	switch (state) /* Always fallthrough here. */
+	  {
+	  case 4:
+		  bus_dmamem_unmap(sc->sc_dmat, (caddr_t)&sc->sc_dmamap, 
+				   sizeof sc->sc_dmamap);
+	  case 3:
+		  bus_dmamem_free(sc->sc_dmat, &seg, nsegs);
+	  case 2:
+		  bus_dmamap_destroy(sc->sc_dmat, sc->sc_dmamap_xfer);
+	  case 1:
+		  pci_intr_disestablish(pc, sc->sc_ih);
+	  default: /* 0 */
+		  bus_space_unmap(sc->sc_memt, sc->sc_memh, memsize);
+	  }
+	return;
+}
+
+void
+ises_initstate (void *v)
+{
+  	/* 
+	 * Step through chip initialization. 
+	 * sc->sc_initstate tells us what to do.
+	 */
+	extern int hz;
+  	struct ises_softc *sc = v;
+	char *dv = sc->sc_dv.dv_xname;
+	u_int32_t stat;
+	int p, ticks;
+
+	ticks = hz; 
+
+#if 0 /* Too noisy */
+	DPRINTF (("%s: entered initstate %d\n", dv, sc->sc_initstate));
+#endif
+
+	switch (sc->sc_initstate)
+		{
+		case 0:
+			/* Power up the chip (clear powerdown bit) */
+			stat = READ_REG(sc, ISES_BO_STAT);
+			if (stat & ISES_BO_STAT_POWERDOWN) {
+				stat &= ~ISES_BO_STAT_POWERDOWN;
+				WRITE_REG(sc, ISES_BO_STAT, stat);
+				/* Selftests will take 1 second. */
+				break;
+			} 
+			/* FALLTHROUGH (chip is already powered up) */
+			sc->sc_initstate++;
+
+		case 1:
+			/* Perform a hardware reset */
+			stat = 0;
+
+			printf ("%s: initializing...\n", dv);
+
+			/* Clear all possible bypass bits. */
+			for (p = 0; p < 128; p++)
+				WRITE_REG(sc, ISES_B_BDATAOUT, 0L);
+
+			stat |= ISES_BO_STAT_HWRESET;
+			WRITE_REG(sc, ISES_BO_STAT, stat);
+			stat &= ~ISES_BO_STAT_HWRESET;
+			WRITE_REG(sc, ISES_BO_STAT, stat);
+			/* Again, selftests will take 1 second. */
+			break;
+
+		case 2:
+			/* Set AConf to zero, i.e 32-bits access to A-int. */
+			stat = READ_REG(sc, ISES_BO_STAT);
+			stat &= ~ISES_BO_STAT_ACONF;
+			WRITE_REG(sc, ISES_BO_STAT, stat);
+			
+			/* Is the firmware already loaded? */
+			if (READ_REG(sc, ISES_A_STAT) & ISES_STAT_HW_DA) {
+				/* Yes it is, jump ahead a bit */
+				ticks = 1;
+				sc->sc_initstate += 4; /* Next step --> 7 */
+				break;
+			}
+			
+			/* 
+			 * Download the Basic Functionality firmware.
+			 * Prior to downloading we need to reset the NSRAM.
+			 * Setting the tamper bit will erase the contents
+			 * in 1 microsecond.
+			 */
+			stat = READ_REG(sc, ISES_BO_STAT);
+			stat |= ISES_BO_STAT_TAMPER;
+			WRITE_REG(sc, ISES_BO_STAT, stat);
+			ticks = 1;
+			break;
+
+		case 3:
+			/* After tamper bit has been set, powerdown chip. */
+			stat = READ_REG(sc, ISES_BO_STAT);
+			stat |= ISES_BO_STAT_POWERDOWN;
+			WRITE_REG(sc, ISES_BO_STAT, stat);
+			/* Wait one second for power to dissipate. */
+			break;
+
+		case 4:
+			/* Clear tamper and powerdown bits. */
+			stat = READ_REG(sc, ISES_BO_STAT);
+			stat &= ~(ISES_BO_STAT_TAMPER | 
+				  ISES_BO_STAT_POWERDOWN);
+			WRITE_REG(sc, ISES_BO_STAT, stat);
+			/* Again, wait one second for selftests. */
+			break;
+
+		case 5:
+			/*
+			 * We'll need some space in the input queue (IQF) 
+			 * and we need to be in the 'waiting for program
+			 * length' IDP state (0x4).
+			 */
+			p = ISES_STAT_IDP_STATE(READ_REG(sc, ISES_A_STAT));
+			if (READ_REG(sc, ISES_A_IQF) < 4 || p != 0x4) {
+				printf("%s: cannot download firmware, "
+				       "IDP state is \"%s\"\n", dv,
+				       ises_idp_state[p]);
+				return;
+			}
+
+			/* Write firmware length */
+			WRITE_REG(sc, ISES_A_IQD, ISES_BF_IDPLEN);
+
+			/* Write firmware code */
+			for (p = 0; p < sizeof (ises_bf_fw)/sizeof (u_int32_t);
+			     p++) {
+				WRITE_REG(sc, ISES_A_IQD, ises_bf_fw[p]);
+				if (READ_REG(sc, ISES_A_IQF) < 4)
+					DELAY(10);
+			}
+
+			/* Write firmware CRC */
+			WRITE_REG(sc, ISES_A_IQD, ISES_BF_IDPCRC);
+
+			/* Wait 1s while chip resets and runs selftests */
+			break;
+
+		case 6:
+			/* Did the download succed? */
+			if (READ_REG(sc, ISES_A_STAT) & ISES_STAT_HW_DA) {
+				ticks = 1;
+				break;
+			}
+
+			/* We failed. We cannot do anything else. */
+			printf ("%s: firmware download failed\n", dv);
+			return;
+			
+		case 7:
+			if (ises_assert_cmd_mode(sc) < 0)
+				goto fail;
+
+			/*
+			 * Now that the basic functionality firmware should be
+			 * up and running, try to get the firmware version.
+			 */
+			
+			stat = ises_get_fwversion(sc);
+			if (stat == 0)
+				goto fail;
+			
+			printf("%s: firmware v%d.%d loaded (%d bytes)", dv, 
+			       stat & 0xffff, (stat >> 16) & 0xffff,
+			       ISES_BF_IDPLEN << 2);
+			
+			/* We can use firmware version 1.x & 2.x */
+			switch (stat & 0xffff) {
+			case 0:
+				printf (" diagnostic, %s disabled\n", dv);
+				goto fail;
+			case 1: /* Basic Func "base" firmware */
+			case 2: /* Basic Func "ipsec" firmware, no ADP code */
+				break;
+			default:
+				printf(" unknown, %s disabled\n", dv);
+				goto fail;
+			}
+
+			stat = READ_REG(sc, ISES_A_STAT);
+			DPRINTF((", mode %s",
+				 ises_sw_mode[ISES_STAT_SW_MODE(stat)]));
+			
+			/* Reuse the timeout for HRNG entropy collection. */
+			timeout_del (&sc->sc_timeout);
+			ises_hrng_init (sc);
+			
+			/* Set the interrupt mask */
+			sc->sc_intrmask =
+				ISES_STAT_BCHU_OAF | ISES_STAT_BCHU_ERR | 
+				ISES_STAT_BCHU_OFHF | ISES_STAT_SW_OQSINC;
+#if 0
+				ISES_STAT_BCHU_ERR | ISES_STAT_BCHU_OAF |
+				ISES_STAT_BCHU_IFE | ISES_STAT_BCHU_IFHE |
+				ISES_STAT_BCHU_OFHF | ISES_STAT_BCHU_OFF;
+#endif
+
+			WRITE_REG(sc, ISES_A_INTE, sc->sc_intrmask);
+
+			/* We're done. */
+			printf("\n");
+
+			/* Register ourselves with crypto framework. */
+#ifdef notyet
+			crypto_register(sc->sc_cid, CRYPTO_3DES_CBC,
+					ises_newsession, ises_freesession, 
+					ises_process);
+			crypto_register(sc->sc_cid, CRYPTO_DES_CBC, 
+					NULL, NULL, NULL);
+			crypto_register(sc->sc_cid, CRYPTO_MD5_HMAC, 
+					NULL, NULL, NULL);
+			crypto_register(sc->sc_cid, CRYPTO_SHA1_HMAC, 
+					NULL, NULL, NULL);
+			crypto_register(sc->sc_cid, CRYPTO_RIPEMD160_HMAC, 
+					NULL, NULL, NULL);
+#endif
+
+			return;
+			
+		default:
+			printf ("%s: entered unknown initstate %d\n", dv, 
+				sc->sc_initstate);
+			goto fail;
+		}
+	
+	/* Increment state counter and schedule next step in 'ticks' ticks. */
+	sc->sc_initstate++;
+	timeout_add (&sc->sc_timeout, ticks);
+	return;
+
+ fail:
+	printf ("%s: firmware failure\n", dv);
+	timeout_del (&sc->sc_timeout);
+	return;
+}
+
+/* Put a command on the A-interface queue. */			
+int
+ises_queue_cmd(struct ises_softc *sc, u_int32_t cmd, u_int32_t *data)
+{
+	int p, len, s;
+
+	len = cmd >> 24;
+
+	s = splimp();
+
+	if (len > READ_REG(sc, ISES_A_IQF)) {
+		splx(s);
+		return (EAGAIN); /* XXX ENOMEM ? */
+	}
+
+	WRITE_REG(sc, ISES_A_IQD, cmd);
+
+	for (p = 0; p < len; p++)
+		WRITE_REG(sc, ISES_A_IQD, *(data + p));
+
+	WRITE_REG(sc, ISES_A_IQS, 0);
+
+	splx(s);
+	return (0);
+}
+
+/* Process all completed responses in the output queue. */
+void
+ises_process_oqueue(struct ises_softc *sc)
+{
+#ifdef ISESDEBUG
+	char *dv = sc->sc_dv.dv_xname;
+#endif
+	u_int32_t oqs, r, d;
+	int cmd, len;
+
+	/* OQS gives us the number of responses we have to process. */
+	while ((oqs = READ_REG(sc, ISES_A_OQS)) > 0) {
+		/* Read command response. [ len(8) | cmd(8) | rc(16) ] */
+		r = READ_REG(sc, ISES_A_OQD);
+		len = (r >> 24);
+		cmd = (r >> 16) & 0xff;
+		r   = r & 0xffff;
+
+		if (r) {
+			/* This command generated an error */
+			DPRINTF(("%s: cmd %d error %d\n", dv, cmd,
+			    (r & ISES_RC_MASK)));
+		} else
+			switch (cmd) {
+			case ISES_CMD_HBITS:
+				/* XXX How about increasing the pool size? */
+				/* XXX Use add_entropy_words instead? */
+				/* XXX ... at proper spl */
+				/* Cmd generated by ises_rng() via timeouts */
+				while (len--) {
+					d = READ_REG(sc, ISES_A_OQD);
+					add_true_randomness(d);
+				}
+				break;
+
+			case ISES_CMD_BR_OMR:
+				sc->sc_omr = READ_REG(sc, ISES_A_OQD);
+				DPRINTF(("%s: read sc->sc_omr [%08x]\n", dv,
+				    sc->sc_omr));
+				break;
+
+			default:
+				/* All other are ok (no response data) */
+			}
+
+	/* This will drain any remaining data and ACK this reponse. */
+	while (len-- > 0)
+		d = READ_REG(sc, ISES_A_OQD);
+	WRITE_REG(sc, ISES_A_OQS, 0);
+	if (oqs > 1)
+		DELAY(1); /* Wait for firmware to decrement OQS (8 clocks) */
+	}
+}
+
+int
+ises_intr(void *arg)
+{
+	struct ises_softc *sc = arg;
+	volatile u_int32_t ints;
+
+	ints = READ_REG(sc, ISES_A_INTS);
+	if (!(ints & sc->sc_intrmask))
+		return (0); /* Not our interrupt. */
+
+	WRITE_REG(sc, ISES_A_INTS, ints); /* Clear all set intr bits. */
+
+#if 0
+	/* Check it we've got room for more data. */
+	if (READ_REG(sc, ISES_A_STAT) &
+	    (ISES_STAT_BCHU_IFE | ISES_STAT_BCHU_IFHE))
+		ises_feed(sc);
+#endif
+
+	if (ints & ISES_STAT_SW_OQSINC) {	/* A-intf output q has data */
+		ises_process_oqueue(sc);
+	}
+	
+	if (ints & ISES_STAT_BCHU_OAF) {	/* output data available */
+		DPRINTF(("ises_intr: BCHU_OAF bit set\n"));
+		/* ises_process_oqueue(sc); */
+	}
+
+	if (ints & ISES_STAT_BCHU_ERR) {	/* We got a BCHU error */
+		DPRINTF(("ises_intr: BCHU error\n"));
+		/* XXX Error handling */
+	}
+
+	if (ints & ISES_STAT_BCHU_OFHF) {	/* Output is half full */
+		DPRINTF(("ises_intr: BCHU output FIFO half full\n"));
+		/* XXX drain data? */
+	}
+
+#if 0 /* XXX Useful? */
+	if (ints & ISES_STAT_BCHU_OFF) {	/* Output is full */
+		/* XXX drain data / error handling? */
+	}
+#endif
+	return (1);
+}
+
+int
+ises_feed(struct ises_softc *sc)
+{
+	struct ises_q *q;
+
+	while (!SIMPLEQ_EMPTY(&sc->sc_queue)) {
+		if (READ_REG(sc, ISES_A_STAT) & ISES_STAT_BCHU_IFF)
+			break;
+		q = SIMPLEQ_FIRST(&sc->sc_queue);
+#if 0
+		WRITE_REG(sc, ISES_OFFSET_BCHU_DATA,
+		    (u_int32_t)vtophys(&q->q_mcr));
+		printf("feed: q->chip %08x %08x\n", q,
+		    (u_int32_t)vtophys(&q->q_mcr));
+#endif
+		SIMPLEQ_REMOVE_HEAD(&sc->sc_queue, q, q_next);
+		--sc->sc_nqueue;
+		SIMPLEQ_INSERT_TAIL(&sc->sc_qchip, q, q_next);
+	}
+	return (0);
+}
+
+/*
+ * Allocate a new 'session' and return an encoded session id.  'sidp'
+ * contains our registration id, and should contain an encoded session
+ * id on successful allocation.
+ */
+int
+ises_newsession(u_int32_t *sidp, struct cryptoini *cri)
+{
+	struct cryptoini *c, *mac = NULL, *enc = NULL;
+	struct ises_softc *sc = NULL;
+	struct ises_session *ses = NULL;
+	MD5_CTX    md5ctx;
+	SHA1_CTX   sha1ctx;
+	RMD160_CTX rmd160ctx;
+	int i, sesn;
+
+	if (sidp == NULL || cri == NULL)
+		return (EINVAL);
+
+	for (i = 0; i < ises_cd.cd_ndevs; i++) {
+		sc = ises_cd.cd_devs[i];
+		if (sc == NULL || sc->sc_cid == (*sidp))
+			break;
+	}
+	if (sc == NULL)
+		return (EINVAL);
+
+	for (c = cri; c != NULL; c = c->cri_next) {
+		if (c->cri_alg == CRYPTO_MD5_HMAC ||
+		    c->cri_alg == CRYPTO_SHA1_HMAC ||
+		    c->cri_alg == CRYPTO_RIPEMD160_HMAC) {
+			if (mac)
+				return (EINVAL);
+			mac = c;
+		} else if (c->cri_alg == CRYPTO_DES_CBC ||
+		    c->cri_alg == CRYPTO_3DES_CBC) {
+			if (enc)
+				return (EINVAL);
+			enc = c;
+		} else
+			return (EINVAL);
+	}
+	if (mac == 0 && enc == 0)
+		return (EINVAL);
+
+	if (sc->sc_sessions == NULL) {
+		ses = sc->sc_sessions = (struct ises_session *)
+		    malloc(sizeof(struct ises_session), M_DEVBUF, M_NOWAIT);
+		if (ses == NULL)
+			return (ENOMEM);
+		sesn = 0;
+		sc->sc_nsessions = 1;
+	} else {
+		for (sesn = 0; sesn < sc->sc_nsessions; sesn++)
+			if (sc->sc_sessions[sesn].ses_used == 0) {
+				ses = &sc->sc_sessions[sesn];
+				break;
+			}
+		
+		if (ses == NULL)  {
+		  	i = sc->sc_nsessions * sizeof (struct ises_session);
+			ses = (struct ises_session *)
+			    malloc(i + sizeof (struct ises_session), M_DEVBUF,
+				   M_NOWAIT);
+			if (ses == NULL)
+				return (ENOMEM);
+			
+			memcpy(ses, sc->sc_sessions, i);
+			memset(sc->sc_sessions, 0, i);
+			free(sc->sc_sessions, M_DEVBUF);
+			sc->sc_sessions = ses;
+			ses = &sc->sc_sessions[sc->sc_nsessions];
+			sc->sc_nsessions++;
+		}
+	}	
+
+	memset(ses, 0, sizeof (struct ises_session));
+	ses->ses_used = 1;
+
+	if (enc) {
+		/* get an IV, network byte order */
+		/* XXX switch to using builtin HRNG ! */
+		get_random_bytes(ses->ses_iv, sizeof(ses->ses_iv));
+		
+		/* crypto key */
+		if (c->cri_alg == CRYPTO_DES_CBC) {
+			memcpy(&ses->ses_deskey[0], enc->cri_key, 8);
+			memcpy(&ses->ses_deskey[2], enc->cri_key, 8);
+			memcpy(&ses->ses_deskey[4], enc->cri_key, 8);
+		} else
+			memcpy(&ses->ses_deskey[0], enc->cri_key, 24);
+		
+		SWAP32(ses->ses_deskey[0]);
+		SWAP32(ses->ses_deskey[1]);
+		SWAP32(ses->ses_deskey[2]);
+		SWAP32(ses->ses_deskey[3]);
+		SWAP32(ses->ses_deskey[4]);
+		SWAP32(ses->ses_deskey[5]);
+	}
+
+	if (mac) {
+		for (i = 0; i < mac->cri_klen / 8; i++)
+			mac->cri_key[i] ^= HMAC_IPAD_VAL;
+		
+		if (mac->cri_alg == CRYPTO_MD5_HMAC) {
+			MD5Init(&md5ctx);
+			MD5Update(&md5ctx, mac->cri_key, mac->cri_klen / 8);
+			MD5Update(&md5ctx, hmac_ipad_buffer, HMAC_BLOCK_LEN -
+				  (mac->cri_klen / 8));
+			memcpy(ses->ses_hminner, md5ctx.state, 
+			       sizeof(md5ctx.state));
+		} else if (mac->cri_alg == CRYPTO_SHA1_HMAC) {
+			SHA1Init(&sha1ctx);
+			SHA1Update(&sha1ctx, mac->cri_key, mac->cri_klen / 8);
+			SHA1Update(&sha1ctx, hmac_ipad_buffer, HMAC_BLOCK_LEN -
+				  (mac->cri_klen / 8));
+			memcpy(ses->ses_hminner, sha1ctx.state, 
+			       sizeof(sha1ctx.state));
+		} else { 
+			RMD160Init(&rmd160ctx);
+			RMD160Update(&rmd160ctx, mac->cri_key, 
+				     mac->cri_klen / 8);
+			RMD160Update(&rmd160ctx, hmac_ipad_buffer, 
+				     HMAC_BLOCK_LEN - (mac->cri_klen / 8));
+			memcpy(ses->ses_hminner, rmd160ctx.state, 
+			       sizeof(rmd160ctx.state));
+		}
+
+		for (i = 0; i < mac->cri_klen / 8; i++)
+			mac->cri_key[i] ^= (HMAC_IPAD_VAL ^ HMAC_OPAD_VAL);
+		
+		if (mac->cri_alg == CRYPTO_MD5_HMAC) {
+			MD5Init(&md5ctx);
+			MD5Update(&md5ctx, mac->cri_key, mac->cri_klen / 8);
+			MD5Update(&md5ctx, hmac_ipad_buffer, HMAC_BLOCK_LEN -
+				  (mac->cri_klen / 8));
+			memcpy(ses->ses_hmouter, md5ctx.state, 
+			       sizeof(md5ctx.state));
+		} else if (mac->cri_alg == CRYPTO_SHA1_HMAC) {
+			SHA1Init(&sha1ctx);
+			SHA1Update(&sha1ctx, mac->cri_key, mac->cri_klen / 8);
+			SHA1Update(&sha1ctx, hmac_ipad_buffer, HMAC_BLOCK_LEN -
+				  (mac->cri_klen / 8));
+			memcpy(ses->ses_hmouter, sha1ctx.state, 
+			       sizeof(sha1ctx.state));
+		} else { 
+			RMD160Init(&rmd160ctx);
+			RMD160Update(&rmd160ctx, mac->cri_key, 
+				     mac->cri_klen / 8);
+			RMD160Update(&rmd160ctx, hmac_ipad_buffer, 
+				     HMAC_BLOCK_LEN - (mac->cri_klen / 8));
+			memcpy(ses->ses_hmouter, rmd160ctx.state, 
+			       sizeof(rmd160ctx.state));
+		}
+
+		for (i = 0; i < mac->cri_klen / 8; i++)
+			mac->cri_key[i] ^= HMAC_OPAD_VAL;
+	}
+
+	*sidp = ISES_SID(sc->sc_dv.dv_unit, sesn);
+	return (0);
+}
+
+/*
+ * Deallocate a session.
+ */
+int
+ises_freesession(u_int64_t tsid)
+{
+	struct ises_softc *sc;
+	int card, sesn;
+	u_int32_t sid = ((u_int32_t) tsid) & 0xffffffff;
+	
+	card = ISES_CARD(sid);
+	if (card >= ises_cd.cd_ndevs || ises_cd.cd_devs[card] == NULL)
+		return (EINVAL);
+
+	sc = ises_cd.cd_devs[card];
+	sesn = ISES_SESSION(sid);
+	memset(&sc->sc_sessions[sesn], 0, sizeof(sc->sc_sessions[sesn]));
+
+	return (0);
+}
+
+int
+ises_process(struct cryptop *crp)
+{
+	int card, err;
+	struct ises_softc *sc;
+	struct ises_q *q;
+	struct cryptodesc *maccrd, *enccrd, *crd;
+	struct ises_session *ses;
+#if 0
+	int s, i, j;
+#else
+	int s;
+#endif
+	int encoffset = 0, macoffset = 0;
+	int sskip, stheend, dtheend, cpskip, cpoffset, dskip, nicealign;
+	int16_t coffset;
+
+	if (crp == NULL || crp->crp_callback == NULL)
+		return (EINVAL);
+
+	card = ISES_CARD(crp->crp_sid);
+	if (card >= ises_cd.cd_ndevs || ises_cd.cd_devs[card] == NULL) {
+		err = EINVAL;
+		goto errout;
+	}
+
+	sc = ises_cd.cd_devs[card];
+
+	s = splnet();
+	if (sc->sc_nqueue == ISES_MAX_NQUEUE) {
+		splx(s);
+		err = ENOMEM;
+		goto errout;
+	}
+	splx(s);
+
+	q = (struct ises_q *)malloc(sizeof(struct ises_q), M_DEVBUF, M_NOWAIT);
+	if (q == NULL) {
+		err = ENOMEM;
+		goto errout;
+	}
+	memset(q, 0, sizeof(struct ises_q));
+
+	q->q_sesn = ISES_SESSION(crp->crp_sid);
+	ses = &sc->sc_sessions[q->q_sesn];
+
+	/* XXX */
+
+	q->q_sc = sc;
+	q->q_crp = crp;
+	
+	if (crp->crp_flags & CRYPTO_F_IMBUF) {
+		q->q_src_m = (struct mbuf *)crp->crp_buf;
+		q->q_dst_m = (struct mbuf *)crp->crp_buf;
+	} else {
+		err = EINVAL;
+		goto errout;
+	}
+
+	/* 
+	 * Check if the crypto descriptors are sane. We accept:
+	 * - just one crd; either auth or crypto
+	 * - two crds; must be one auth and one crypto, although now
+	 *   for encryption we only want the first to be crypto, while 
+	 *   for decryption the second one should be crypto.
+	 */
+	maccrd = enccrd = NULL;
+	err = EINVAL;
+	for (crd = crp->crp_desc; crd; crd = crd->crd_next) {
+		switch (crd->crd_alg) {
+		case CRYPTO_MD5_HMAC:
+		case CRYPTO_SHA1_HMAC:
+		case CRYPTO_RIPEMD160_HMAC:
+			if (maccrd || (enccrd && 
+			    (enccrd->crd_flags & CRD_F_ENCRYPT) == 0))
+				goto errout;
+			maccrd = crd;
+			break;
+		case CRYPTO_DES_CBC:
+		case CRYPTO_3DES_CBC:
+			if (enccrd || 
+			    (maccrd && (crd->crd_flags & CRD_F_ENCRYPT)))
+				goto errout;
+			enccrd = crd;
+			break;
+		default:
+			goto errout;
+		}
+	}
+	if (!maccrd && !enccrd)
+		goto errout;
+	err = 0;
+
+	if (enccrd) {
+		encoffset = enccrd->crd_skip;
+
+		if (enccrd->crd_alg == CRYPTO_3DES_CBC)
+			q->q_ctx.pc_omrflags |= ISES_SOMR_BOMR_3DES;
+		else
+			q->q_ctx.pc_omrflags |= ISES_SOMR_BOMR_DES;
+		q->q_ctx.pc_omrflags |= ISES_SOMR_FMR_CBC;
+
+		if (enccrd->crd_flags & CRD_F_ENCRYPT) {
+			q->q_ctx.pc_omrflags |= ISES_SOMR_EDR; /* XXX */
+
+			if (enccrd->crd_flags & CRD_F_IV_EXPLICIT)
+				bcopy(enccrd->crd_iv, q->q_ctx.pc_iv, 8);
+			else {
+				q->q_ctx.pc_iv[0] = ses->ses_iv[0];
+				q->q_ctx.pc_iv[1] = ses->ses_iv[1];
+			}
+			
+			if ((enccrd->crd_flags & CRD_F_IV_PRESENT) == 0)
+				m_copyback(q->q_src_m, enccrd->crd_inject,
+					   8, (caddr_t)q->q_ctx.pc_iv);
+		} else {
+			q->q_ctx.pc_omrflags &= ~ISES_SOMR_EDR; /* XXX */
+
+			if (enccrd->crd_flags & CRD_F_IV_EXPLICIT)
+				bcopy(enccrd->crd_iv, q->q_ctx.pc_iv, 8);
+			else 
+				m_copyback(q->q_src_m, enccrd->crd_inject,
+					   8, (caddr_t)q->q_ctx.pc_iv);
+		}
+
+		q->q_ctx.pc_deskey[0] = ses->ses_deskey[0];
+		q->q_ctx.pc_deskey[1] = ses->ses_deskey[1];
+		q->q_ctx.pc_deskey[2] = ses->ses_deskey[2];
+		q->q_ctx.pc_deskey[3] = ses->ses_deskey[3];
+		q->q_ctx.pc_deskey[4] = ses->ses_deskey[4];
+		q->q_ctx.pc_deskey[5] = ses->ses_deskey[5];
+
+		SWAP32(q->q_ctx.pc_iv[0]);
+		SWAP32(q->q_ctx.pc_iv[1]);
+	}
+
+	if (maccrd) {
+		macoffset = maccrd->crd_skip;
+		
+		switch (crd->crd_alg) {
+		case CRYPTO_MD5_HMAC:
+			q->q_ctx.pc_omrflags |= ISES_HOMR_HFR_MD5;
+			break;
+		case CRYPTO_SHA1_HMAC:
+			q->q_ctx.pc_omrflags |= ISES_HOMR_HFR_SHA1;
+			break;
+		case CRYPTO_RIPEMD160_HMAC:
+		default: 
+			q->q_ctx.pc_omrflags |= ISES_HOMR_HFR_RMD160;
+			break;
+		}
+
+		q->q_ctx.pc_hminner[0] = ses->ses_hminner[0];
+		q->q_ctx.pc_hminner[1] = ses->ses_hminner[1];
+		q->q_ctx.pc_hminner[2] = ses->ses_hminner[2];
+		q->q_ctx.pc_hminner[3] = ses->ses_hminner[3];
+		q->q_ctx.pc_hminner[4] = ses->ses_hminner[4];
+		q->q_ctx.pc_hminner[5] = ses->ses_hminner[5];
+		
+		q->q_ctx.pc_hmouter[0] = ses->ses_hmouter[0];
+		q->q_ctx.pc_hmouter[1] = ses->ses_hmouter[1];
+		q->q_ctx.pc_hmouter[2] = ses->ses_hmouter[2];
+		q->q_ctx.pc_hmouter[3] = ses->ses_hmouter[3];
+		q->q_ctx.pc_hmouter[4] = ses->ses_hmouter[4];
+		q->q_ctx.pc_hmouter[5] = ses->ses_hmouter[5];
+	}
+
+	if (enccrd && maccrd) {
+		/* XXX Check if ises handles differing end of auth/enc etc */
+		/* XXX For now, assume not (same as ubsec). */
+		if (((encoffset + enccrd->crd_len) !=
+		     (macoffset + maccrd->crd_len)) ||
+		    (enccrd->crd_skip < maccrd->crd_skip)) {
+			err = EINVAL;
+			goto errout;
+		}
+		
+		sskip = maccrd->crd_skip;
+		cpskip = dskip = enccrd->crd_skip;
+		stheend = maccrd->crd_len;
+		dtheend = enccrd->crd_len;
+		coffset = cpskip - sskip;
+		cpoffset = cpskip + dtheend;
+		/* XXX DEBUG ? */
+	} else {
+		cpskip = dskip = sskip = macoffset + encoffset;
+		dtheend = enccrd ? enccrd->crd_len : maccrd->crd_len;
+		stheend = dtheend;
+		cpoffset = cpskip + dtheend;
+		coffset = 0;
+	}
+	q->q_ctx.pc_offset = coffset >> 2;
+	
+	q->q_src_l = mbuf2pages (q->q_src_m, &q->q_src_npa, &q->q_src_packp,
+				 &q->q_src_packl, 1, &nicealign);
+	if (q->q_src_l == 0) {
+		err = ENOMEM;
+		goto errout;
+	}
+	
+	/* XXX mcr stuff; q->q_mcr->mcr_pktlen = stheend; */
+	
+#if 0 /* XXX */
+	for (i = j = 0; i < q->q_src_npa; i++) {
+		struct ises_pktbuf *pb;
+
+		/* XXX DEBUG? */
+		
+		if (sskip) {
+			if (sskip >= q->q_src_packl) {
+				sskip -= q->q_src_packl;
+				continue;
+			}
+			q->q_src_packp += sskip;
+			q->q_src_packl -= sskip;
+			sskip = 0;
+		}
+		
+		pb = NULL; /* XXX initial packet */
+		
+		pb->pb_addr = q->q_src_packp;
+		if (stheend) {
+			if (q->q_src_packl > stheend) {
+				pb->pb_len = stheend;
+				stheend = 0;
+			} else {
+				pb->pb_len = q->q_src_packl;
+				stheend -= pb->pb_len;
+			}
+		} else
+			pb->pb_len = q->q_src_packl;
+
+		if ((i + 1) == q->q_src_npa)
+			pb->pb_next = 0;
+		else
+			pb->pb_next = vtophys(&q->q_srcpkt);
+		
+		j++;
+	}
+
+#endif /* XXX */
+	/* XXX DEBUG ? */
+
+	if (enccrd == NULL && maccrd != NULL) {
+		/* XXX mcr stuff */
+	} else {
+		if (!nicealign) {
+                        int totlen, len;
+                        struct mbuf *m, *top, **mp;
+			
+                        totlen = q->q_dst_l = q->q_src_l;
+                        if (q->q_src_m->m_flags & M_PKTHDR) {
+                                MGETHDR(m, M_DONTWAIT, MT_DATA);
+                                M_COPY_PKTHDR(m, q->q_src_m);
+                                len = MHLEN;
+                        } else {
+                                MGET(m, M_DONTWAIT, MT_DATA);
+                                len = MLEN;
+                        }
+                        if (m == NULL) {
+                                err = ENOMEM;
+                                goto errout;
+                        }
+                        if (totlen >= MINCLSIZE) {
+                                MCLGET(m, M_DONTWAIT);
+                                if (m->m_flags & M_EXT)
+                                        len = MCLBYTES;
+                        }
+                        m->m_len = len;
+                        top = NULL;
+                        mp = &top;
+			
+                        while (totlen > 0) {
+                                if (top) {
+                                        MGET(m, M_DONTWAIT, MT_DATA);
+                                        if (m == NULL) {
+                                                m_freem(top);
+                                                err = ENOMEM;
+                                                goto errout;
+                                        }
+                                        len = MLEN;
+                                }
+                                if (top && totlen >= MINCLSIZE) {
+                                        MCLGET(m, M_DONTWAIT);
+                                        if (m->m_flags & M_EXT)
+                                                len = MCLBYTES;
+                                }
+                                m->m_len = len = min(totlen, len);
+                                totlen -= len;
+                                *mp = m;
+				
+				mp = &m->m_next;
+                        }
+                        q->q_dst_m = top;
+                        ubsec_mcopy(q->q_src_m, q->q_dst_m, cpskip, cpoffset);
+                } else
+                        q->q_dst_m = q->q_src_m;
+		
+                q->q_dst_l = mbuf2pages(q->q_dst_m, &q->q_dst_npa,
+					&q->q_dst_packp, &q->q_dst_packl, 
+					1, NULL);
+
+#if 0
+		for (i = j = 0; i < q->q_dst_npa; i++) {
+                        struct ises_pktbuf *pb;
+			
+			if (dskip) {
+                                if (dskip >= q->q_dst_packl[i]) {
+                                        dskip -= q->q_dst_packl[i];
+                                        continue;
+                                }
+                                q->q_dst_packp[i] += dskip;
+                                q->q_dst_packl[i] -= dskip;
+                                dskip = 0;
+                        }
+			
+                        if (j == 0)
+                                pb = NULL; /* &q->q_mcr->mcr_opktbuf; */
+                        else
+                                pb = &q->q_dstpkt[j - 1];
+
+                        pb->pb_addr = q->q_dst_packp[i];
+			
+                        if (dtheend) {
+                                if (q->q_dst_packl[i] > dtheend) {
+                                        pb->pb_len = dtheend;
+                                        dtheend = 0;
+                                } else {
+                                        pb->pb_len = q->q_dst_packl[i];
+                                        dtheend -= pb->pb_len;
+                                }
+                        } else
+                                pb->pb_len = q->q_dst_packl[i];
+			
+                        if ((i + 1) == q->q_dst_npa) {
+                                if (maccrd)
+                                        pb->pb_next = vtophys(q->q_macbuf);
+                                else
+					pb->pb_next = 0;
+                        } else
+                                pb->pb_next = vtophys(&q->q_dstpkt[j]);
+                        j++;
+                }
+#endif	
+	}
+
+	s = splnet();
+	SIMPLEQ_INSERT_TAIL(&sc->sc_queue, q, q_next);
+	sc->sc_nqueue++;
+	ises_feed(sc);
+	splx(s);
+
+	return (0);
+					
+errout:
+	if (q) {
+		if (q->q_src_m != q->q_dst_m)
+			m_freem(q->q_dst_m);
+		free(q, M_DEVBUF);
+	}
+	crp->crp_etype = err;
+	crp->crp_callback(crp);
+	return (0);
+}
+
+void
+ises_callback(struct ises_q *q)
+{
+	struct cryptop *crp = (struct cryptop *)q->q_crp;
+	struct cryptodesc *crd;
+
+	if ((crp->crp_flags & CRYPTO_F_IMBUF) && (q->q_src_m != q->q_dst_m)) {
+		m_freem(q->q_src_m);
+		crp->crp_buf = (caddr_t)q->q_dst_m;
+	}
+
+	for (crd = crp->crp_desc; crd; crd = crd->crd_next) {
+		if (crd->crd_alg != CRYPTO_MD5_HMAC &&
+		    crd->crd_alg != CRYPTO_SHA1_HMAC &&
+		    crd->crd_alg != CRYPTO_RIPEMD160_HMAC)
+			continue;
+		m_copyback((struct mbuf *)crp->crp_buf,
+		    crd->crd_inject, 12, (u_int8_t *)&q->q_macbuf[0]);
+		break;
+	}
+
+	free(q, M_DEVBUF);
+	crypto_done(crp);
+}
+
+/* Initilize the ISES hardware RNG, and set up timeouts. */
+void
+ises_hrng_init(struct ises_softc *sc)
+{
+	u_int32_t cmd, r;
+	int i;
+#ifdef ISESDEBUG
+	struct timeval tv1, tv2;
+#endif
+
+	/* Asking for random data will seed LFSR and start the RBG */
+	cmd = ISES_MKCMD(ISES_CMD_HBITS, 1);
+	r   = 8; /* 8 * 32 = 256 bits */
+
+	if (ises_queue_cmd(sc, cmd, &r))
+		return;
+
+	/* Wait until response arrives. */
+	for (i = 1000; i && READ_REG(sc, ISES_A_OQS) == 0; i--)
+		DELAY(10);
+
+	if (!READ_REG(sc, ISES_A_OQS))
+		return;
+
+	/* Drain cmd response and 8*32 bits data */
+	for (i = 0; i <= r; i++)
+		(void)READ_REG(sc, ISES_A_OQD);
+
+	/* ACK the response */
+	WRITE_REG(sc, ISES_A_OQS, 0);
+	DELAY(1);
+	printf(", rng active", sc->sc_dv.dv_xname);
+
+#ifdef ISESDEBUG
+	/* Benchmark the HRNG. */
+
+	/* 
+	 * XXX These values gets surprisingly large. Docs state the
+	 * HNRG produces > 1 mbit/s of random data. The values I'm seeing
+	 * are much higher, ca 2.7-2.8 mbit/s. AFAICT the algorithm is sound. 
+	 * Compiler optimization issues, perhaps?
+	 */
+
+#define ISES_WPR 250
+#define ISES_ROUNDS 100
+	cmd = ISES_MKCMD(ISES_CMD_HBITS, 1);
+	r = ISES_WPR;
+
+	/* Queue 100 cmds; each generate 250 32-bit words of rnd data. */
+	microtime(&tv1);
+	for (i = 0; i < ISES_ROUNDS; i++)
+		ises_queue_cmd(sc, cmd, &r);
+	for (i = 0; i < ISES_ROUNDS; i++) {
+		while (READ_REG(sc, ISES_A_OQS) == 0) ; /* Wait for response */
+
+		(void)READ_REG(sc, ISES_A_OQD);		/* read response */
+		for (r = ISES_WPR; r--;)
+			(void)READ_REG(sc, ISES_A_OQD);	/* read data */
+		WRITE_REG(sc, ISES_A_OQS, 0);		/* ACK resp */
+		DELAY(1); /* OQS needs 1us to decrement */
+	}
+	microtime(&tv2);
+	
+	timersub(&tv2, &tv1, &tv1);
+	tv1.tv_usec += 1000000 * tv1.tv_sec;
+	printf(", %dKb/sec", 
+	       ISES_WPR * ISES_ROUNDS * 32 / 1024 * 1000000 / tv1.tv_usec);
+#endif
+
+	printf ("\n");
+	timeout_set(&sc->sc_timeout, ises_hrng, sc);
+	ises_hrng(sc); /* Call first update */
+}
+
+/* Called by timeout (and once by ises_init_hrng()). */
+void
+ises_hrng(void *v)
+{
+	/*
+	 * Throw a HRNG read random bits command on the command queue.
+	 * The normal loop will manage the result and add it to the pool.
+	 */
+	struct ises_softc *sc = v;
+	u_int32_t cmd, n;
+	extern int hz; /* from param.c */
+
+	/* XXX How often should we repeat? */
+	timeout_add(&sc->sc_timeout, hz/ISESRNGIPS);
+
+	if (ises_assert_cmd_mode(sc) != 0)
+		return;
+
+	cmd = ISES_MKCMD(ISES_CMD_HBITS, 1);
+	n   = (ISESRNGBITS >> 5) & 0xff; /* ask for N 32 bit words */
+
+	ises_queue_cmd(sc, cmd, &n);
+}
+
+u_int32_t
+ises_get_fwversion(struct ises_softc *sc)
+{
+	u_int32_t r;
+	int i;
+  
+	r = ISES_MKCMD(ISES_CMD_CHIP_ID, 0);
+	WRITE_REG(sc, ISES_A_IQD, r);
+	WRITE_REG(sc, ISES_A_IQS, 0);
+
+	for (i = 100; i > 0 && READ_REG(sc, ISES_A_OQS) == 0; i--)
+		DELAY(1);
+  
+	if (i < 1)
+		return (0); /* No response */
+
+	r = READ_REG(sc, ISES_A_OQD);
+
+	/* Check validity. On error drain reponse data. */
+	if (((r >> 16) & 0xff) != ISES_CMD_CHIP_ID ||
+	    ((r >> 24) & 0xff) != 3 || (r & ISES_RC_MASK) != ISES_RC_SUCCESS) {
+		if ((r & ISES_RC_MASK) == ISES_RC_SUCCESS)
+			for (i = ((r >> 24) & 0xff); i; i--)
+				(void) READ_REG(sc, ISES_A_OQD);
+		r = 0;
+		goto out;
+	}
+
+	r = READ_REG(sc, ISES_A_OQD); /* read version */
+	(void) READ_REG (sc, ISES_A_OQD); /* Discard 64bit "chip-id" */
+	(void) READ_REG (sc, ISES_A_OQD);
+ out:
+	WRITE_REG(sc, ISES_A_OQS, 0); /* Ack the response */
+	DELAY(1);
+	return (r);
+}
+
+/* 
+ * ises_assert_cmd_mode() returns 
+ *   -1 for failure to go to cmd
+ *    0 if mode already was cmd
+ *   >0 if mode was other (WFC/WFR) but now is cmd (this has reset the queues)
+ */
+int
+ises_assert_cmd_mode(struct ises_softc *sc)
+{
+  switch (ISES_STAT_SW_MODE(READ_REG(sc, ISES_A_STAT))) {
+  case 0x0: /* Selftest. XXX This is a transient state. */
+  	DELAY(1000000);
+	if (ISES_STAT_SW_MODE(READ_REG(sc, ISES_A_STAT)) == 0)
+		return (-1);
+	return (ises_assert_cmd_mode(sc));
+  case 0x1: /* Command mode */
+  	return (0);
+  case 0x2: /* Waiting For Continue / WFC */
+    	bus_space_write_2(sc->sc_memt, sc->sc_memh, ISES_A_CTRL,
+	    ISES_A_CTRL_CONTINUE);
+	DELAY(1);
+	return ((ISES_STAT_SW_MODE(READ_REG(sc, ISES_A_STAT)) == 0) ? 1 : -1);
+  case 0x3: /* Waiting For Reset / WFR */
+    	bus_space_write_2(sc->sc_memt, sc->sc_memh, ISES_A_CTRL,
+	    ISES_A_CTRL_RESET);
+	DELAY(1000000);
+	return ((ISES_STAT_SW_MODE(READ_REG(sc, ISES_A_STAT)) == 0) ? 2 : -1);
+  default:
+  	return (-1); /* Unknown mode */
+  }
+}
+
diff --git a/sys/dev/pci/isesreg.h b/sys/dev/pci/isesreg.h
new file mode 100644
index 00000000000..e49bea9a676
--- /dev/null
+++ b/sys/dev/pci/isesreg.h
@@ -0,0 +1,645 @@
+/*	$OpenBSD: isesreg.h,v 1.1 2001/01/29 08:45:58 ho Exp $ $	*/
+
+/*
+ * Copyright (c) 2000 H�kan Olsson (ho@crt.se)
+ * Copyright (c) 2000 Theo de Raadt
+ *
+ * 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. 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 AUTHOR ``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 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.
+ */
+
+/*
+ * Register definitions for Pijnenburg PCC-ISES crypto chip.  
+ * Definitions from revision 1.6 of the product datasheet.
+ */
+
+/* DMA offsets */
+#define ISES_DMA_WRITE_COUNT	0x0100
+#define ISES_DMA_READ_COUNT	0x0102
+#define ISES_DMA_WRITE_START	0x0104
+#define ISES_DMA_READ_START	0x0108
+#define ISES_DMA_STATUS		0x010c
+
+/* 
+ * PCC-ISES A-interface 
+ */
+
+#define ISES_A_OFFSET		0x0200
+#define ISES_A(x)		(ISES_A_OFFSET + (x))
+
+#define ISES_A_STAT		ISES_A(0x00)	/* status register */
+#define ISES_A_INTS		ISES_A(0x04)	/* interupt status register */
+#define ISES_A_INTE		ISES_A(0x08)	/* interupt enable register */
+#define ISES_A_SREQ		ISES_A(0x0C)	/* service request (read) */
+#define ISES_A_CTRL		ISES_A_SREQ	/* control register (write) */
+#define ISES_A_OQD		ISES_A(0x10)	/* Output Queue Data (read) */
+#define ISES_A_IQD		ISES_A_OQD	/* Input Queue Data (write) */
+#define ISES_A_OQS		ISES_A(0x14)	/* Output Queue Semaphore */
+#define ISES_A_IQS		ISES_A(0x18)	/* Input Queue Semaphore */
+#define ISES_A_OQF		ISES_A(0x1C)	/* Output Queue Filled (ro) */
+#define ISES_A_IQF		ISES_A(0x20)	/* Input Queue Free (ro) */
+
+/*
+ * PCC-ISES B-interface 
+ */
+
+#define ISES_B_OFFSET		0x0300
+#define ISES_B(x)		(ISES_B_OFFSET + (x))
+
+#define ISES_B_BDATAIN		ISES_B(0x0)
+#define ISES_B_BDATAOUT		ISES_B(0x4)
+#define ISES_B_STAT		ISES_B(0x8)
+
+/*
+ * PCC-ISES I-interface (not used)
+ */
+
+#define ISES_I_OFFSET		0x0400
+
+/* 
+ * PCC-ISES board registers
+ */
+
+#define ISES_BO_OFFSET		0x0500
+#define ISES_BO(x)		(ISES_BO_OFFSET + (x))
+
+#define ISES_BO_STAT		ISES_BO(0x0)
+#define ISES_BO_LOOPCOUNTER	ISES_BO(0x4)
+#define ISES_BO_TESTREG		ISES_BO(0x8)
+
+#define ISES_BO_STAT_LOOP	0x00000001	/* B-interface LoopMode */
+#define ISES_BO_STAT_TAMPER	0x00000002	/* Set tamper */
+#define ISES_BO_STAT_POWERDOWN	0x00000004	/* Set power down */
+#define ISES_BO_STAT_ACONF	0x00000008	/* Set A-intf access to 16b */
+#define ISES_BO_STAT_HWRESET	0x00000010	/* Reset PCC-ISES (hw) */
+#define ISES_BO_STAT_AIRQ	0x00000020	/* A-interface interrupt (ro)*/
+
+/* 
+ * PCC-ISES A-interface STAT register bits 
+ */
+
+#define ISES_STAT_LNAU_MASKED	0x00000001	/* LNAU flags masked, this bit
+						   must be zero for the other
+						   LNAU flags to be read
+						   correctly. */
+#define ISES_STAT_LNAU_BUSY_1	0x00000002	/* LNAU unit 1 is busy */
+#define ISES_STAT_LNAU_ERR_1	0x00000004	/* LNAU unit 1 error */
+#define ISES_STAT_LNAU_BUSY_2	0x00000008	/* LNAU unit 2 is busy */
+#define ISES_STAT_LNAU_ERR_2	0x00000010	/* LNAU unit 2 error */
+#define ISES_STAT_BCHU_MASKED	0x00000020	/* BCHU flags masked */
+#define ISES_STAT_BCHU_BUSY	0x00000040	/* BCHU is busy */
+#define ISES_STAT_BCHU_ERR	0x00000080	/* BCHU error flag */
+#define ISES_STAT_BCHU_SCIF	0x00000100	/* symm. crypto inoperative */
+#define ISES_STAT_BCHU_HIF	0x00000200	/* hash unit inoperative */
+#define ISES_STAT_BCHU_DDB	0x00000400	/* discard data blocks */
+#define ISES_STAT_BCHU_IRF	0x00000800	/* input request flag */
+#define ISES_STAT_BCHU_OAF	0x00001000	/* output available flag */
+#define ISES_STAT_BCHU_DIE	0x00002000	/* data input enabled */
+#define ISES_STAT_BCHU_UE	0x00004000	/* unit enable bit */
+#define ISES_STAT_BCHU_IFE	0x00008000	/* input FIFO empty */
+#define ISES_STAT_BCHU_IFHE	0x00010000	/* input FIFO half emtpy */
+#define ISES_STAT_BCHU_IFF	0x00020000	/* input FIFO full */
+#define ISES_STAT_BCHU_OFE	0x00040000	/* output FIFO emtpy */
+#define ISES_STAT_BCHU_OFHF	0x00080000	/* output FIFO half full */
+#define ISES_STAT_BCHU_OFF	0x00100000	/* output FIFO full */
+#define ISES_STAT_HW_DA		0x00200000	/* downloaded appl flag */
+#define ISES_STAT_HW_ACONF	0x00400000	/* A-intf configuration flag */
+#define ISES_STAT_SW_WFOQ	0x00800000	/* SW: Waiting for out queue */
+#define ISES_STAT_SW_OQSINC	0x08000000	/* SW 2.x: OQS increased */
+
+#define ISES_STAT_IDP_MASK	0x0f000000	/* IDP state mask (HW_DA=0) */
+#define ISES_STAT_IDP_STATE(x)  (((x) & ISES_STAT_IDP_MASK) >> 24)
+
+static const char *ises_idp_state[] = 
+{
+	"reset state",				/* 0x0 */
+	"testing NSRAM",			/* 0x1 */
+	"checking for firmware",		/* 0x2 */
+	"clearing NSRAM",			/* 0x3 */
+	"waiting for program length",		/* 0x4 */
+	"waiting for program data",		/* 0x5 */
+	"waiting for program CRC",		/* 0x6 */
+	"functional test program",		/* 0x7 */
+	0, 0, 0, 0, 0, 0, 0,			/* 0x8-0xe */
+	"Error: NSRAM or firmware failed"	/* 0xf */
+};
+
+#define ISES_STAT_SW_MASK	0x03000000	/* SW mode (HW_DA=1) */
+#define ISES_STAT_SW_MODE(x)	(((x) & ISES_STAT_SW_MASK) >> 24)
+
+#define ISES_A_CTRL_RESET	0x0000		/* SW reset (go to ST mode) */
+#define ISES_A_CTRL_CONTINUE	0x0001		/* Return to CMD from WFC */
+
+#ifdef ISESDEBUG
+static const char *ises_sw_mode[] =
+{
+	"ST (SelfTest)",			/* 0x0 */
+	"CMD",					/* 0x1 (normal) */
+	"WFC (Wait for continue)",		/* 0x2 */
+	"CMD (Wait for reset)"			/* 0x3 */
+};
+#endif
+
+/* BERR (BCHU Error Register) */
+#define ISES_BERR_DPAR		0x00000001	/* DES parity error */
+#define ISES_BERR_IDESBCP	0x00000002	/* illegal DES mode value */
+#define ISES_BERR_ISFRBCP	0x00000004	/* illegal SAFER rounds spec */
+#define ISES_BERR_INCMBCP	0x00000008	/* illegal non-crypto mode */
+#define ISES_BERR_IBCF		0x00000010	/* illegal value in BCFR */
+#define ISES_BERR_reserved	0x00000020	/* reserved */
+#define ISES_BERR_SRB		0x00000040	/* write SCU while busy */
+#define ISES_BERR_HRB		0x00000080	/* write HU while busy */
+#define ISES_BERR_IHFR		0x00000100	/* illegal value in HFR */
+#define ISES_BERR_PADERR	0x00000200	/* padding error */
+#define ISES_BERR_BIDM		0x00000400	/* B-interface input data
+						   misalignment */
+/* BCHCR (BCHU Control Register) */
+#define ISES_BCHCR_BCHU_DIE	0x00000001	/* data input enabled */
+#define ISES_BCHCR_BCHU_UE	0x00000002	/* unit enable */
+#define ISES_BCHCR_BCHU_RST	0x00000004	/* BCHU reset */
+
+/* 
+ * OMR (Operation Method Register) 
+ */
+/* -- SELR (Selector Register) */
+#define ISES_SELR_BCHU_EH	0x80000000	/* stop/continue on error */
+#define ISES_SELR_BCHU_HISOF	0x01000000	/* HU input is SCU output */
+#define ISES_SELR_BCHU_DIS	0x02000000	/* data interface select */
+
+/* -- HOMR (HU Operation Mode Register) */
+#define ISES_HOMR_HMTR		0x00800000	/* hash message type reg bit */
+#define ISES_HOMR_ER		0x00300000	/* BE/LE, 2bit mask */
+
+#define ISES_HOMR_HFR		0x00070000	/* Hash function mask, 3bits */
+#define ISES_HOMR_HFR_NOP	0x00000000	/* NOP */
+#define ISES_HOMR_HFR_MD5	0x00010000	/* MD5 */
+#define ISES_HOMR_HFR_RMD160	0x00020000	/* RIPEMD-160 */
+#define ISES_HOMR_HFR_RMD128	0x00030000	/* RIPEMD-128 */
+#define ISES_HOMR_HFR_SHA1	0x00040000	/* SHA-1 */
+
+/* -- SOMR (Symmetric crypto Operation Method Register) */
+#define ISES_SOMR_BCFR		0x0000f000      /* block cipher function reg */
+#define ISES_SOMR_BCPR		0x00000ff0	/* block cipher parameters */
+#define ISES_SOMR_BOMR		(ISES_SOMR_BCFR | ISES_SOMR_BCPR)
+#define ISES_SOMR_BOMR_NOP	0x00000000	/* NOP */
+#define ISES_SOMR_BOMR_TRANSPARENT 0x00000010	/* Transparent */
+#define ISES_SOMR_BOMR_DES	0x00001000	/* DES */
+#define ISES_SOMR_BOMR_3DES2	0x00001010	/* 3DES-2 */
+#define ISES_SOMR_BOMR_3DES	0x00001020	/* 3DES-3 */
+#define ISES_SOMR_BOMR_SAFER	0x00002000	/* SAFER (actually more) */
+#define ISES_SOMR_EDR		0x00000008	/* Encrypt/Decrypt register */
+#define ISES_SOMR_FMR		0x00000003	/* feedback mode mask */
+#define ISES_SOMR_FMR_ECB	0x00000000	/* EBC */
+#define ISES_SOMR_FMR_CBC	0x00000001	/* CBC */
+#define ISES_SOMR_FMR_CFB64	0x00000002	/* CFB64 */
+#define ISES_SOMR_FMR_OFB64	0x00000003	/* OFB64 */
+
+/* 
+ * HRNG (Hardware Random Number Generator)
+ */
+#define ISES_OFFSET_HRNG_CTRL	0x00		/* Control register */
+#define ISES_OFFSET_HRNG_LFSR	0x04		/* Linear feedback shift reg */
+#define ISES_HRNG_CTRL_HE	0x00000001	/* HRNG enable */
+
+/*
+ * A-interface commands 
+ */
+#define ISES_MKCMD(cmd,len)	(cmd | cmd << 16 | len << 8 | len << 24)
+
+/*	Command name		Code	   Len	RLen    Desc                 */
+#define ISES_CMD_CHIP_ID	0x00	/* 0	3	Read chipID */
+/* LNAU commands */			
+#define ISES_CMD_LRESET_1	0x01	/* 0	0	LNAU 1 reset */
+#define ISES_CMD_LRSFLG_1	0x02	/* 0	0	LNAU 1 flags reset */
+#define ISES_CMD_LUPLOAD_1	0x03	/* 0	64	*/
+#define ISES_CMD_LW_A_1		0x04	/* ?64	0	*/
+#define ISES_CMD_LW_B_1		0x05	/* ?64	0	*/
+#define ISES_CMD_LW_N_1		0x06	/* ?64	0	*/
+#define ISES_CMD_LW_Bq_1	0x07	/* ?32	0	*/
+#define ISES_CMD_LW_Nq_1	0x08	/* ?32	0	*/
+#define ISES_CMD_LW_Bp_1	0x09	/* ?34	0	*/
+#define ISES_CMD_LW_Np_1	0x0a	/* ?34	0	*/
+#define ISES_CMD_LW_U_1		0x0b	/* ?34	0	*/
+#define ISES_CMD_LMOD_1		0x0c	/* 0	0	*/
+#define ISES_CMD_LMULMOD_1	0x0d	/* 0	0	*/
+#define ISES_CMD_LEXPMOD_1	0x0e	/* 0	0	*/
+#define ISES_CMD_LECMOD_1	0x0f	/* 0	0	*/
+#define ISES_CMD_LRESET_2	0x10	/* 0	0	*/
+#define ISES_CMD_LRSFLG_2	0x11	/* 0	0	*/
+#define ISES_CMD_LUPLOAD_2	0x12	/* 0	64	*/
+#define ISES_CMD_LW_A_2		0x13	/* ?64	0	*/
+#define ISES_CMD_LW_B_2		0x14	/* ?64	0	*/
+#define ISES_CMD_LW_N_2		0x15	/* ?64	0	*/
+#define ISES_CMD_LW_Bq_2	0x16	/* ?32	0	*/
+#define ISES_CMD_LW_Nq_2	0x17	/* ?32	0	*/
+#define ISES_CMD_LW_Bp_2	0x18	/* ?34	0	*/
+#define ISES_CMD_LW_Np_2	0x19	/* ?34	0	*/
+#define ISES_CMD_LW_U_2		0x1a	/* ?34	0	*/
+#define ISES_CMD_LMOD_2		0x1b	/* 0	0	*/
+#define ISES_CMD_LMULMOD_2	0x1c	/* 0	0	*/
+#define ISES_CMD_LEXPMOD_2	0x1d	/* 0	0	*/
+#define ISES_CMD_LECMOD_2	0x1e	/* 0	0	*/
+/* BCHU commands */
+#define ISES_CMD_RST_BERR	0x1f	/* 0	0	Reset BERR */
+#define ISES_CMD_BR_BERR	0x20	/* 0	0	Read BERR */
+#define ISES_CMD_BW_DATA	0x21	/* 2	0	Write DATA */
+#define ISES_CMD_BR_DATA	0x22	/* 0	2	Read DATA */
+#define ISES_CMD_BW_BCHCR	0x23	/* 1	0	Write BCHCR */
+#define ISES_CMD_BR_BCHCR	0x24	/* 0	0	Read BCHCR */
+#define ISES_CMD_BW_OMR		0x25	/* 1	0	Write OMR */
+#define ISES_CMD_BR_OMR		0x26	/* 0	1	Read OMR */
+#define ISES_CMD_BW_KR0		0x27	/* 2	0	Write key 0 */
+#define ISES_CMD_BR_KR0		0x28	/* 0	2	Read key 0 */
+#define ISES_CMD_BW_KR1		0x29	/* 2	0	Write key 1 */
+#define ISES_CMD_BR_KR1		0x2a	/* 0	2	Read key 1 */
+#define ISES_CMD_BW_KR2		0x2b	/* 2	0	Write key 2 */
+#define ISES_CMD_BR_KR2		0x2c	/* 0	2	Read key 2 */
+#define ISES_CMD_BW_SCCR	0x2d	/* 2	0	Write SCCR */
+#define ISES_CMD_BR_SCCR	0x2e	/* 0	2	Read SCCR */
+#define ISES_CMD_BW_DBCR	0x2f	/* 2	0	Write DBCR */
+#define ISES_CMD_BR_DBCR	0x30	/* 0	2	Read DBCR */
+#define ISES_CMD_BW_HMLR	0x31	/* 2	0	Write HMLR */
+#define ISES_CMD_BR_HMLR	0x32	/* 0	2	Read HMLR */
+#define ISES_CMD_BW_CVR		0x33	/* 5	0	Write CVR */
+#define ISES_CMD_BR_CVR		0x34	/* 0	5	Read CVR */
+#define ISES_CMD_BPROC		0x35	/* ?255	?255	Process data blocks */
+#define ISES_CMD_BTERM		0x36	/* 0	0	Terminate session */
+#define ISES_CMD_BSWITCH	0x37	/* 18	18	Switch BCHU session */
+/* HRNG commands */
+#define ISES_CMD_HSTART		0x38	/* 0	0	Start RBG unit */
+#define ISES_CMD_HSTOP		0x39	/* 0	0	Stop RGB unit */
+#define ISES_CMD_HSEED		0x3a	/* 1	0	Seed LFSR */
+#define ISES_CMD_HBITS		0x3b	/* 1	?255	Return n*32 rnd bits */
+
+/* Command return codes (RC) */
+#define ISES_RC_MASK		0x0000ffff	
+#define ISES_RC_SUCCESS		0x0000		/* success */
+#define ISES_RC_CMDERR		0x0001		/* cmd interpretation error */
+#define ISES_RC_QERR		0x0002		/* queue handling error */
+#define ISES_RC_LNAU_ERR	0x0003		/* LNAU cmd proc error */
+#define ISES_RC_BCHU_ERR	0x0004		/* BCHU cmd proc error */
+#define ISES_RC_BCHU_BIFCSEL	0x0005		/* OMR says B-if, must be A */
+#define ISES_RC_BCHU_ODD	0x0006		/* odd #words in param list */
+#define ISES_RC_HRNG_ILLEN	0x0007		/* too large bitstream */
+
+/* Interrupt bits, IRQE, IRQES, IRQEC, IRQSS, IRQ registers */
+#define ISES_IRQ_TIMER_1	0x00000001	/* Timer 1 reached zero */
+#define ISES_IRQ_TIMER_2	0x00000002	/* Timer 2 reached zero */
+#define ISES_IRQ_I_IIN0		0x00000004	/* I-int 'Iin0' */
+#define ISES_IRQ_I_IIN1		0x00000008	/* I-int 'Iin1' */
+#define ISES_IRQ_I_IIN2		0x00000010	/* I-int 'Iin2' */
+#define ISES_IRQ_I_IIN3		0x00000020	/* I-int 'Iin3' */
+#define ISES_IRQ_LNAU_1_ERROR	0x00000040	/* LNAU 1 op error/abort */
+#define ISES_IRQ_LNAU_1_DONE	0x00000080	/* LNAU 1 op done */
+#define ISES_IRQ_LNAU_2_ERROR	0x00000100	/* LNAU 2 op error/abort */
+#define ISES_IRQ_LNAU_2_DONE	0x00000200	/* LNAU 1 op done */
+#define ISES_IRQ_BCHU_DONE	0x00000400	/* BCHU operation done */
+#define ISES_IRQ_BCHU_ERROR	0x00000800	/* BCHU operation error/abrt */
+#define ISES_IRQ_BCHU_IRF	0x00001000	/* BCHU input request flag >1*/
+#define ISES_IRQ_BCHU_OAF	0x00002000	/* BCHU output avail flag >1 */
+#define ISES_IRQ_BCHU_IEF	0x00004000	/* BCHU input empty flag >1  */
+#define ISES_IRQ_A_WCTRL	0x00008000	/* A-int CTRL reg was written*/
+#define ISES_IRQ_A_RSREQ	0x00010000	/* A-int SREQ reg was read   */
+#define ISES_IRQ_A_DIQ		0x00020000	/* in queue emtpy, IQD write */
+#define ISES_IRQ_A_CIQ		0x00040000	/* in queue has complete cmd */
+#define ISES_IRQ_A_OQF		0x00080000	/* output queue full */
+
+#define ISES_SESSION(sid)	( (sid) & 0x0fffffff)
+#define	ISES_CARD(sid)		(((sid) & 0xf0000000) >> 28)
+#define	ISES_SID(crd,ses)	(((crd) << 28) | ((ses) & 0x0fffffff))
+
+struct ises_pktctx {
+	u_int32_t	pc_deskey[6];		/* 3DES key */
+	u_int32_t	pc_hminner[5];		/* hmac inner state */
+	u_int32_t	pc_hmouter[5];		/* hmac outer state */
+	u_int32_t	pc_iv[2];		/* [3]DES iv */
+	u_int32_t	pc_omrflags;		/* OMR flags, as above */
+	u_int32_t	pc_paddr;
+	u_int16_t	pc_offset;		/* crypto offset */
+	u_int8_t	pad[16];
+};
+
+struct ises_pktbuf {
+	volatile u_int32_t	pb_addr;	/* address of buffer start */
+	volatile u_int32_t	pb_len;		/* packet length */
+};
+
+#define ISES_B_DATASIZE			4096
+struct ises_databuf {
+	  u_int8_t data[ISES_B_DATASIZE];
+} __attribute__((packed));
+
+/* 
+ * ------------------------------------------
+ * PCC-ISES Basic Functionality firmware v2.0 
+ * ------------------------------------------
+ */
+
+/*
+�* Copyright (C) 1999, 2000 Pijnenburg Custom Chips B.V.
+�* All rights reserved.
+�*
+�* Redistribution and use in source and binary forms are permitted provided
+�* that the following conditions are met:
+�* 1. Redistribution of source code must retain the above copyright
+�*��� notice, this list of conditions and the following disclaimer.
+�* 2. Redistribution 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. 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 AUTHOR ``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 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.
+�*/
+
+#define ISES_BF_IDPLEN		0x00000403	/* Total length, 32bit words */
+#define ISES_BF_IDPCRC		0x59DE7DEF	/* Firmware CRC */
+
+static const u_int32_t ises_bf_fw[] = {
+	0xEA000006, 0xE1A00000, 0xE1A00000, 0xE1A00000,
+	0xE1A00000, 0xE1A00000, 0xEA000013, 0xEA000026,
+	0xE59FD0C4, 0xE3A000D2, 0xE121F000, 0xE59FD0BC,
+	0xE3A000D1, 0xE121F000, 0xE59FD0B0, 0xE3A000D3,
+	0xE121F000, 0xEB00029B, 0xEAFFFFFE, 0xE10F1000,
+	0xE1811000, 0xE121F001, 0xE12FFF1E, 0xE10F1000,
+	0xE1C11000, 0xE121F001, 0xE12FFF1E, 0xE92D0003,
+	0xE59F107C, 0xE5910004, 0xE5810000, 0xE3100902,
+	0x0A00000B, 0xE59F106C, 0xE5910000, 0xE3500000,
+	0x1A000003, 0xE59F1060, 0xE3A00001, 0xE5810000,
+	0xEA000003, 0xE3500001, 0x1A000001, 0xE59F1038,
+	0xE5810000, 0xE8BD0003, 0xE25EF004, 0xE25EF004,
+	0xE3A000D3, 0xE121F000, 0xE59FE030, 0xE3A00000,
+	0xE3A01032, 0xE48E0004, 0xE2511001, 0x1AFFFFFC,
+	0xE91E3FFE, 0xE3A0E000, 0xE3A0F000, 0x000017B4,
+	0x000017DC, 0xFFFFEA00, 0xFFFFE60C, 0xFFFFF000,
+	0x00001714, 0xE3A01001, 0xE3A00AFE, 0xE2400601,
+	0xE5A01624, 0xE1A0F00E, 0xE3A00AFE, 0xE2400601,
+	0xE5901620, 0xE3510000, 0x0AFFFFFC, 0xE5900610,
+	0xE1A0F00E, 0xE3A02000, 0xE3510000, 0x91A0F00E,
+	0xE3A03AFE, 0xE2433601, 0xE593C620, 0xE35C0000,
+	0x0AFFFFFC, 0xE593C610, 0xE2822001, 0xE1520001,
+	0xE480C004, 0x3AFFFFF7, 0xE1A0F00E, 0xE3A01000,
+	0xE3A00AFE, 0xE2400601, 0xE5A01618, 0xE1A0F00E,
+	0xE3A01002, 0xE3A00AFE, 0xE2400601, 0xE5A01624,
+	0xE1A0F00E, 0xE3A01AFE, 0xE2411601, 0xE591261C,
+	0xE3520000, 0x1A000006, 0xE3A02506, 0xE5812600,
+	0xE591261C, 0xE3520000, 0x0AFFFFFC, 0xE3A02401,
+	0xE5812600, 0xE5A10610, 0xE1A0F00E, 0xE3A03000,
+	0xE3510000, 0x91A0F00E, 0xE92D4010, 0xE3A0E506,
+	0xE3A0C401, 0xE3A02AFE, 0xE2422601, 0xE592461C,
+	0xE3540000, 0x1A000004, 0xE582E600, 0xE592461C,
+	0xE3540000, 0x0AFFFFFC, 0xE582C600, 0xE4904004,
+	0xE5824610, 0xE2833001, 0xE1530001, 0x3AFFFFF2,
+	0xE8BD8010, 0xE3A01000, 0xE3A00AFE, 0xE2400601,
+	0xE5A01614, 0xE3A00CE6, 0xE2400801, 0xE5901000,
+	0xE3811302, 0xE5801000, 0xE5901000, 0xE3C11302,
+	0xE5801000, 0xE1A0F00E, 0xE59F2038, 0xE59F0038,
+	0xE5901000, 0xE0821181, 0xE5D11006, 0xE20120F0,
+	0xE3A03BC2, 0xE2433701, 0xE0832402, 0xE5802008,
+	0xE2822004, 0xE580200C, 0xE2432B02, 0xE0821401,
+	0xE5A01010, 0xE1A0F00E, 0x00000E00, 0x00001000,
+	0xE92D4000, 0xEBFFFFB0, 0xE3A01002, 0xE59F0028,
+	0xE5801000, 0xE3A01AFE, 0xE2411601, 0xE5912204,
+	0xE5802004, 0xE5911208, 0xE5801008, 0xE3A01003,
+	0xEB000264, 0xE3A00000, 0xE8BD8000, 0x00001014,
+	0xE92D4000, 0xEBFFFFDB, 0xEBFFFF9F, 0xE51F005C,
+	0xE51F205C, 0xE5921000, 0xE0800181, 0xE5D01007,
+	0xE3510011, 0x1A000004, 0xE51F0074, 0xE5900008,
+	0xE5903000, 0xE3130008, 0x0AFFFFFC, 0xE5B2000C,
+	0xE5801000, 0xE3A00000, 0xEB000247, 0xE3A00000,
+	0xE8BD8000, 0xE92D4000, 0xEBFFFFC6, 0xEBFFFF8A,
+	0xE51F10AC, 0xE5910008, 0xE5902000, 0xE3120008,
+	0x0AFFFFFC, 0xE5900000, 0xE3100002, 0x0A000002,
+	0xE3A00003, 0xEB000238, 0xEA000002, 0xE5B10010,
+	0xE3A01040, 0xEB00023B, 0xE3A00000, 0xE8BD8000,
+	0xE92D4010, 0xEBFFFFB3, 0xE51F40F4, 0xE5940008,
+	0xE5901000, 0xE3110008, 0x0AFFFFFC, 0xE5900000,
+	0xE3100002, 0x0A000005, 0xE5B41004, 0xE51F00D8,
+	0xEBFFFF5F, 0xEBFFFF6C, 0xE3A00003, 0xEA00000B,
+	0xE5940010, 0xE5941004, 0xEBFFFF59, 0xEBFFFF66,
+	0xE51F0140, 0xE5941000, 0xE0800181, 0xE5D02007,
+	0xE5B41004, 0xE594000C, 0xEB00024E, 0xE3A00000,
+	0xEB000215, 0xE3A00000, 0xE8BD8010, 0xE92D4010,
+	0xEBFFFF94, 0xEBFFFF58, 0xE51F0174, 0xE5901008,
+	0xE5912000, 0xE3120008, 0x0AFFFFFC, 0xE5911000,
+	0xE3110002, 0xE3A04000, 0x13A00003, 0x1A00000F,
+	0xE51F11A0, 0xE5902000, 0xE0812182, 0xE5D22007,
+	0xE3520034, 0x1A000003, 0xE5902010, 0xE5224088,
+	0xE5902010, 0xE5224084, 0xE5902000, 0xE0811182,
+	0xE5D11007, 0xE590000C, 0xE5801000, 0xE3A00000,
+	0xEB0001F5, 0xE1A00004, 0xE8BD8010, 0xE92D4010,
+	0xEBFFFF39, 0xE3A04000, 0xE3A00AFE, 0xE2400601,
+	0xE5A04400, 0xE3A00000, 0xEB0001EB, 0xE1A00004,
+	0xE8BD8010, 0xE92D4010, 0xE51F01D4, 0xE1A04000,
+	0xE3A01002, 0xEBFFFF1E, 0xEBFFFF2B, 0xE3A00AFE,
+	0xE2400601, 0xE5901474, 0xE3110002, 0x1A00000F,
+	0xE5901424, 0xE3110402, 0x13A00005, 0x1A00000E,
+	0xE3A01003, 0xE5801470, 0xE5901474, 0xE3110020,
+	0x0AFFFFFC, 0xE5941000, 0xE5801478, 0xE5B41004,
+	0xE5801478, 0xE5900474, 0xE3100002, 0x0A000001,
+	0xE3A00004, 0xEA000000, 0xE3A00000, 0xEB0001CA,
+	0xE3A00000, 0xE8BD8010, 0xE92D4000, 0xEBFFFF0E,
+	0xE3A00AFE, 0xE2400601, 0xE5901474, 0xE3110002,
+	0xE51F126C, 0x1A00000D, 0xE5902424, 0xE3120402,
+	0x13A00005, 0x1A00000C, 0xE5902474, 0xE3120040,
+	0x0AFFFFFC, 0xE5902478, 0xE5812000, 0xE5902478,
+	0xE5812004, 0xE5900474, 0xE3100002, 0x0A000001,
+	0xE3A00004, 0xEA000000, 0xE3A00000, 0xE3500000,
+	0x1A000003, 0xE1A00001, 0xE3A01002, 0xEB0001B1,
+	0xEA000000, 0xEB0001A8, 0xE3A00000, 0xE8BD8000,
+	0xE92D40F0, 0xE51F6320, 0xE5961004, 0xE51F02E8,
+	0xE1A04000, 0xEBFFFEDA, 0xEBFFFEE7, 0xE3A05AFE,
+	0xE2455601, 0xE3A07000, 0xE5960000, 0xE3500023,
+	0x1A000004, 0xE5941000, 0xE3110004, 0x13A00004,
+	0x15A50470, 0x1A000018, 0xE3500023, 0x13500031,
+	0x0A000002, 0xE5951474, 0xE3110001, 0x1AFFFFFC,
+	0xE3500025, 0x1A000003, 0xE5940000, 0xE3C0033F,
+	0xE5840000, 0xE5857470, 0xE5960004, 0xE1A02100,
+	0xE51F03A0, 0xE5961000, 0xE0800181, 0xE5D00006,
+	0xE2400B07, 0xE1A01004, 0xEB0001D0, 0xE5B50474,
+	0xE3100002, 0x13A00004, 0x1A000000, 0xE3A00000,
+	0xEB000179, 0xE1A00007, 0xE8BD80F0, 0xE92D40F0,
+	0xEBFFFEBD, 0xE3A06AFE, 0xE2466601, 0xE5960474,
+	0xE3100002, 0xE51F73B0, 0xE51F43F4, 0x15940000,
+	0x13500020, 0x1A000014, 0xE5940000, 0xE350002E,
+	0x13500030, 0x13500034, 0x1A000002, 0xE5961474,
+	0xE3110001, 0x1AFFFFFC, 0xE51F1428, 0xE0810180,
+	0xE5D05007, 0xE1A02105, 0xE5D00006, 0xE2401B07,
+	0xE1A00007, 0xEB0001AD, 0xE5B60474, 0xE3100002,
+	0x15940000, 0x13500020, 0x0A000001, 0xE3A00004,
+	0xEA000000, 0xE3A00000, 0xE3500000, 0x1A000003,
+	0xE1A01005, 0xE1A00007, 0xEB000156, 0xEA000000,
+	0xEB00014D, 0xE3A00000, 0xE8BD80F0, 0xE92D41F0,
+	0xE3A04000, 0xE3A00003, 0xE3A08AFE, 0xE2488601,
+	0xE5880470, 0xE5980474, 0xE3100002, 0xE51F54A8,
+	0x13A04004, 0x1A000006, 0xE5950004, 0xE3100001,
+	0x13A04006, 0x1A000002, 0xE5980424, 0xE3100402,
+	0x13A04005, 0xE51F7490, 0xE3540000, 0x0A000004,
+	0xE1A00007, 0xE5951004, 0xEBFFFE6D, 0xEBFFFE7A,
+	0xEA00001D, 0xE3A06000, 0xE5950004, 0xE3500000,
+	0xDA000015, 0xE5980474, 0xE3100020, 0x0AFFFFFC,
+	0xEBFFFE5C, 0xE5880478, 0xEBFFFE5A, 0xE5880478,
+	0xE5980474, 0xE3100004, 0x1A000007, 0xE5980474,
+	0xE3100040, 0x0AFFFFFC, 0xE5980478, 0xE7870106,
+	0xE5980478, 0xE0871106, 0xE5A10004, 0xE2866002,
+	0xE5950004, 0xE1560000, 0xBAFFFFE9, 0xEBFFFE5E,
+	0xE5980474, 0xE3100002, 0x13A04004, 0xE3540000,
+	0x05B80474, 0x03100004, 0x1A000003, 0xE1A00007,
+	0xE5B51004, 0xEB000113, 0xEA000001, 0xE1A00004,
+	0xEB000109, 0xE3A00000, 0xE8BD81F0, 0xE92D4010,
+	0xEBFFFE4D, 0xE3A00AFE, 0xE2400601, 0xE5901474,
+	0xE3110002, 0xE3A04000, 0x1A000013, 0xE5901424,
+	0xE3110402, 0x0A000003, 0xE5901474, 0xE3110C02,
+	0x0AFFFFFC, 0xEA000002, 0xE5901474, 0xE3110020,
+	0x0AFFFFFC, 0xE5901470, 0xE3C11001, 0xE5801470,
+	0xE5901474, 0xE3110001, 0x1AFFFFFC, 0xE5804470,
+	0xE5900474, 0xE3100002, 0x0A000001, 0xE3A00004,
+	0xEA000000, 0xE3A00000, 0xEB0000E7, 0xE1A00004,
+	0xE8BD8010, 0xE92D4070, 0xE3A00AFE, 0xE2400601,
+	0xE5901474, 0xE3110002, 0xE51F55F4, 0xE3A06000,
+	0x0A000005, 0xE3A04004, 0xE1A00005, 0xE3A01012,
+	0xEBFFFE13, 0xEBFFFE20, 0xEA000027, 0xE5901424,
+	0xE3110402, 0x0A000003, 0xE5901474, 0xE3110C02,
+	0x0AFFFFFC, 0xEA000002, 0xE5901474, 0xE3110020,
+	0x0AFFFFFC, 0xE5901470, 0xE3C11001, 0xE5801470,
+	0xE5901474, 0xE3110001, 0x1AFFFFFC, 0xE1A04000,
+	0xE5806470, 0xE1A00005, 0xE3A02048, 0xE3A0100C,
+	0xE2411B07, 0xEB000111, 0xE3A01006, 0xE3A0000C,
+	0xE2400B07, 0xEBFFFDF6, 0xEBFFFDEE, 0xE3C0033F,
+	0xE5840424, 0xE3A0100B, 0xE3A00028, 0xE2400B07,
+	0xEBFFFDEF, 0xEBFFFDFC, 0xE3A00003, 0xE5840470,
+	0xE5B40474, 0xE2104002, 0x13A04004, 0xE3540000,
+	0x1A000003, 0xE1A00005, 0xE3A01012, 0xEB0000B1,
+	0xEA000001, 0xE1A00004, 0xEB0000A7, 0xE1A00006,
+	0xE8BD8070, 0xE92D4000, 0xEBFFFDEB, 0xE51F172C,
+	0xE51F072C, 0xE5900000, 0xE0810180, 0xE5D00007,
+	0xE3A01AFE, 0xE2411601, 0xE5A10C00, 0xE3A00000,
+	0xEB000099, 0xE3A00000, 0xE8BD8000, 0xE92D4000,
+	0xEBFFFDC8, 0xE3A01AFE, 0xE2411601, 0xE5A10C04,
+	0xEBFFFDD9, 0xE3A00000, 0xEB00008F, 0xE3A00000,
+	0xE8BD8000, 0xE92D41F0, 0xEBFFFDBE, 0xE1A04000,
+	0xEBFFFDD1, 0xE3A06000, 0xE35400FF, 0x9A000002,
+	0xE3A00007, 0xEB000084, 0xEA00001C, 0xE3A00000,
+	0xE51F376C, 0xE3540000, 0x9A000015, 0xE3A07064,
+	0xE3A0C080, 0xE3A02AFE, 0xE2422601, 0xE3A0E001,
+	0xE3A01000, 0xE5827800, 0xE582C808, 0xE5928A00,
+	0xE3180001, 0x0AFFFFFC, 0xE582EA00, 0xE5928C04,
+	0xE20880FF, 0xE0885405, 0xE2811001, 0xE3510004,
+	0x3AFFFFF3, 0xE7835100, 0xE2800001, 0xE1500004,
+	0x3AFFFFEE, 0xE1A01004, 0xE1A00003, 0xEB00006D,
+	0xE1A00006, 0xE8BD81F0, 0xE92D47F0, 0xEB0000A1,
+	0xE3A09004, 0xE3A08AFE, 0xE2488601, 0xE3A07010,
+	0xE1A06088, 0xE2485A01, 0xE3500000, 0x0A000001,
+	0xEB000084, 0xEA000015, 0xEB000082, 0xE5889470,
+	0xE3A0A000, 0xE59F4040, 0xEBFFFD81, 0xEBFFFD9F,
+	0xE3A00001, 0xEB000014, 0xEB000019, 0xE3500002,
+	0x0A00000A, 0xE5867804, 0xE5857804, 0xE5889470,
+	0xE3A00002, 0xEB00000C, 0xE584A000, 0xE5940000,
+	0xE3500000, 0x0AFFFFFC, 0xEAFFFFEE, 0x000017B4,
+	0xE5A67804, 0xE5A57804, 0xE5A89470, 0xE3A00003,
+	0xEB000001, 0xEAFFFFFF, 0xEAFFFFFE, 0xE1A00C00,
+	0xE3A01AFE, 0xE2411601, 0xE5A10600, 0xE1A0F00E,
+	0xE1A0F00E, 0xE92D43F0, 0xE3A07001, 0xE3A09AFE,
+	0xE2499601, 0xE3A080FF, 0xE59F6030, 0xE59F5030,
+	0xE59F4030, 0xE5990618, 0xE3500C01, 0x0A000005,
+	0xE5990618, 0xE3500000, 0x9A000007, 0xE5990620,
+	0xE3500000, 0x1A000004, 0xE3A00002, 0xEA000019,
+	0x00001004, 0x00001000, 0x00000E00, 0xE5990618,
+	0xE3500000, 0x0AFFFFFC, 0xEBFFFD4E, 0xE20010FF,
+	0xE0082420, 0xE5851000, 0xE1A03800, 0xE1A03823,
+	0xE1530820, 0xE5862000, 0x1A000007, 0xE351003E,
+	0xD0843181, 0xD5D3C004, 0xD15C0002, 0xCA000002,
+	0xE5D33005, 0xE1530002, 0xAA000006, 0xE1A00820,
+	0xE1A00800, 0xE3800001, 0xEBFFFD59, 0xEBFFFD7C,
+	0xE1A00007, 0xE8BD83F0, 0xE1A0E00F, 0xE794F181,
+	0xE3500000, 0x0AFFFFD2, 0xE8BD83F0, 0xE92D4000,
+	0xE51F1094, 0xE5911000, 0xE1800801, 0xEBFFFD4C,
+	0xE8BD4000, 0xEAFFFD6E, 0xE92D4030, 0xE1A05000,
+	0xE1A04001, 0xE1A00C01, 0xE51F10BC, 0xE5911000,
+	0xE1800801, 0xEBFFFD42, 0xE1A01004, 0xE1A00005,
+	0xEBFFFD4D, 0xE8BD4030, 0xEAFFFD61, 0xE59F1020,
+	0xE5910000, 0xE59F201C, 0xE1500002, 0x21A0F00E,
+	0xE5922000, 0xE5802000, 0xE3E00000, 0xE5810000,
+	0xE1A0F00E, 0x000017FC, 0x000017F8, 0xE92D4010,
+	0xE1A04000, 0xEB000010, 0xE3540018, 0x03A00080,
+	0x0A000002, 0xE354001C, 0x18BD8010, 0xE3A00040,
+	0xE8BD4010, 0xEAFFFCD8, 0xE92D4000, 0xE3A01001,
+	0xE3A00018, 0xEBFFFFF0, 0xE3A01902, 0xE3A00AFE,
+	0xE2400601, 0xE5A01A08, 0xE8BD8000, 0xE3A000C0,
+	0xEAFFFCC9, 0xE1A0F00E, 0xE3A03000, 0xE1510002,
+	0x21A0F00E, 0xE7803101, 0xE2811001, 0xE1510002,
+	0x3AFFFFFB, 0xE1A0F00E, 0xE3A00000, 0xE1A0F00E,
+	0xE3A00001, 0xE1A0F00E, 0xE3A00002, 0xE1A0F00E,
+	0xE92D4000, 0xE59F001C, 0xE5901000, 0xE59F0018,
+	0xEBFFFCEF, 0xEBFFFCFC, 0xE3A00011, 0xEBFFFFB2,
+	0xE3A00000, 0xE8BD8000, 0x00001004, 0x00001014,
+	0xE1803001, 0xE1833002, 0xE3130003, 0x1A00000B,
+	0xE1A0C122, 0xE1A03000, 0xE24C2001, 0xE35C0000,
+	0x91A0F00E, 0xE491C004, 0xE483C004, 0xE1A0C002,
+	0xE2422001, 0xE35C0000, 0x8AFFFFF9, 0xE1A0F00E,
+	0xE1A03000, 0xE1A0C002, 0xE2422001, 0xE35C0000,
+	0x91A0F00E, 0xE4D1C001, 0xE4C3C001, 0xE1A0C002,
+	0xE2422001, 0xE35C0000, 0x8AFFFFF9, 0xE1A0F00E,
+	0x000002A0, 0x00000000, 0x000002E0, 0x10C80000,
+	0x000002E0, 0x11C80000, 0x00000334, 0x00C00000,
+	0x00000380, 0x40C04000, 0x00000380, 0x40C14000,
+	0x00000380, 0x40C24000, 0x00000380, 0x20C52000,
+	0x00000380, 0x20C72000, 0x00000380, 0x22C42200,
+	0x00000380, 0x22C62200, 0x00000380, 0x22C32200,
+	0x000003FC, 0x34C80000, 0x000003FC, 0x35C80000,
+	0x000003FC, 0x36C80000, 0x000003FC, 0x37C80000,
+	0x000002E0, 0x10D80000, 0x000002E0, 0x11D80000,
+	0x00000334, 0x00D00000, 0x00000380, 0x40D04000,
+	0x00000380, 0x40D14000, 0x00000380, 0x40D24000,
+	0x00000380, 0x20D52000, 0x00000380, 0x20D72000,
+	0x00000380, 0x22D42200, 0x00000380, 0x22D62200,
+	0x00000380, 0x22D32200, 0x000003FC, 0x34D80000,
+	0x000003FC, 0x35D80000, 0x000003FC, 0x36D80000,
+	0x000003FC, 0x37D80000, 0x0000047C, 0x00000000,
+	0x0000066C, 0x01000000, 0x000004A4, 0x00000202,
+	0x00000528, 0x00000000, 0x000005B0, 0x01700101,
+	0x0000066C, 0x01700000, 0x000005B0, 0x01240101,
+	0x0000066C, 0x01240000, 0x000005B0, 0x021C0202,
+	0x0000066C, 0x021C0000, 0x000005B0, 0x02140202,
+	0x0000066C, 0x02140000, 0x000005B0, 0x020C0202,
+	0x0000066C, 0x020C0000, 0x000005B0, 0x02280202,
+	0x0000066C, 0x02280000, 0x000005B0, 0x02440202,
+	0x0000066C, 0x02440000, 0x000005B0, 0x024C0202,
+	0x0000066C, 0x024C0000, 0x000005B0, 0x05300505,
+	0x0000066C, 0x05300000, 0x0000071C, 0x0000FF00,
+	0x0000082C, 0x00000000, 0x000008B4, 0x00001212,
+	0x000009B4, 0x01000000, 0x000009B4, 0x00000000,
+	0x000009EC, 0x00000101, 0x00000A14, 0x00000101,
+	0x00000D58, 0x00004040, 0x00000D60, 0x00002020,
+	0x00000D60, 0x0000FF00, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000
+};
diff --git a/sys/dev/pci/isesvar.h b/sys/dev/pci/isesvar.h
new file mode 100644
index 00000000000..efe90d7acb2
--- /dev/null
+++ b/sys/dev/pci/isesvar.h
@@ -0,0 +1,83 @@
+/*	$OpenBSD: isesvar.h,v 1.1 2001/01/29 08:45:58 ho Exp $	*/
+
+/*
+ * Copyright (c) 2000 H�kan Olsson (ho@crt.se)
+ *
+ * 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. 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 AUTHOR ``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 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.
+ */
+
+struct ises_softc {
+	struct	device		sc_dv;		/* generic device */
+	void			*sc_ih;		/* interrupt handler cookie */
+	bus_space_handle_t	sc_memh;	/* memory handle */
+	bus_space_tag_t		sc_memt;	/* memory tag */
+	bus_dma_tag_t		sc_dmat;	/* dma tag */
+	bus_dmamap_t		sc_dmamap_xfer; /* dma xfer map */
+	struct ises_databuf     sc_dmamap;      /* data area */
+	bus_addr_t		sc_dmamap_phys; /* bus address of data area */
+	int32_t			sc_cid;		/* crypto tag */
+	u_int32_t		sc_intrmask;	/* interrupt mask */
+	u_int32_t		sc_omr;		/* OMR */
+	SIMPLEQ_HEAD(,ises_q)	sc_queue;	/* packet queue */
+	int			sc_nqueue;	/* count enqueued */
+	SIMPLEQ_HEAD(,ises_q)	sc_qchip;	/* on chip */
+	struct timeout		sc_timeout;	/* init + hrng timeout */
+	int			sc_nsessions;	/* nr of sessions */
+	struct ises_session	*sc_sessions;	/* sessions */
+	int			sc_initstate;	/* card initialization state */
+};
+
+struct ises_q {
+	SIMPLEQ_ENTRY(ises_q)	q_next;
+	struct cryptop		*q_crp;
+	struct ises_pktbuf	q_srcpkt;
+	struct ises_pktbuf	q_dstpkt;
+	struct ises_pktctx	q_ctx;
+
+	struct ises_softc	*q_sc;
+	struct mbuf 		*q_src_m, *q_dst_m;
+
+	int			q_sesn;
+	long			q_src_packp;
+	int			q_src_packl;
+	int			q_src_npa, q_src_l;
+
+	long			q_dst_packp;
+	int			q_dst_packl;
+	int			q_dst_npa, q_dst_l;
+	u_int32_t		q_macbuf[5];
+};
+
+struct ises_session {
+       u_int32_t    ses_used;
+       u_int32_t    ses_deskey[6];		/* 3DES key */
+       u_int32_t    ses_hminner[5];		/* hmac inner state */
+       u_int32_t    ses_hmouter[5];		/* hmac outer state */
+       u_int32_t    ses_iv[2];			/* DES/3DES iv */
+};
+
+/* Maximum queue length */
+#ifndef ISES_MAX_NQUEUE
+#define ISES_MAX_NQUEUE		24
+#endif
-- 
cgit v1.2.3