rename target/linux/generic-2.6 to generic
[openwrt/svn-archive/archive.git] / target / linux / generic-2.6 / files / crypto / ocf / safe / safe.c
diff --git a/target/linux/generic-2.6/files/crypto/ocf/safe/safe.c b/target/linux/generic-2.6/files/crypto/ocf/safe/safe.c
deleted file mode 100644 (file)
index 7e65101..0000000
+++ /dev/null
@@ -1,2288 +0,0 @@
-/*-
- * Linux port done by David McCullough <david_mccullough@mcafee.com>
- * Copyright (C) 2004-2010 David McCullough
- * The license and original author are listed below.
- *
- * Copyright (c) 2003 Sam Leffler, Errno Consulting
- * Copyright (c) 2003 Global Technology Associates, Inc.
- * 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.
- *
-__FBSDID("$FreeBSD: src/sys/dev/safe/safe.c,v 1.18 2007/03/21 03:42:50 sam Exp $");
- */
-
-#ifndef AUTOCONF_INCLUDED
-#include <linux/config.h>
-#endif
-#include <linux/module.h>
-#include <linux/kernel.h>
-#include <linux/init.h>
-#include <linux/list.h>
-#include <linux/slab.h>
-#include <linux/wait.h>
-#include <linux/sched.h>
-#include <linux/pci.h>
-#include <linux/delay.h>
-#include <linux/interrupt.h>
-#include <linux/spinlock.h>
-#include <linux/random.h>
-#include <linux/version.h>
-#include <linux/skbuff.h>
-#include <asm/io.h>
-
-/*
- * SafeNet SafeXcel-1141 hardware crypto accelerator
- */
-
-#include <cryptodev.h>
-#include <uio.h>
-#include <safe/safereg.h>
-#include <safe/safevar.h>
-
-#if 1
-#define        DPRINTF(a)      do { \
-                                               if (debug) { \
-                                                       printk("%s: ", sc ? \
-                                                               device_get_nameunit(sc->sc_dev) : "safe"); \
-                                                       printk a; \
-                                               } \
-                                       } while (0)
-#else
-#define        DPRINTF(a)
-#endif
-
-/*
- * until we find a cleaner way, include the BSD md5/sha1 code
- * here
- */
-#define HMAC_HACK 1
-#ifdef HMAC_HACK
-#define LITTLE_ENDIAN 1234
-#define BIG_ENDIAN 4321
-#ifdef __LITTLE_ENDIAN
-#define BYTE_ORDER LITTLE_ENDIAN
-#endif
-#ifdef __BIG_ENDIAN
-#define BYTE_ORDER BIG_ENDIAN
-#endif
-#include <safe/md5.h>
-#include <safe/md5.c>
-#include <safe/sha1.h>
-#include <safe/sha1.c>
-
-u_int8_t hmac_ipad_buffer[64] = {
-    0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36,
-    0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36,
-    0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36,
-    0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36,
-    0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36,
-    0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36,
-    0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36,
-    0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36
-};
-
-u_int8_t hmac_opad_buffer[64] = {
-    0x5C, 0x5C, 0x5C, 0x5C, 0x5C, 0x5C, 0x5C, 0x5C,
-    0x5C, 0x5C, 0x5C, 0x5C, 0x5C, 0x5C, 0x5C, 0x5C,
-    0x5C, 0x5C, 0x5C, 0x5C, 0x5C, 0x5C, 0x5C, 0x5C,
-    0x5C, 0x5C, 0x5C, 0x5C, 0x5C, 0x5C, 0x5C, 0x5C,
-    0x5C, 0x5C, 0x5C, 0x5C, 0x5C, 0x5C, 0x5C, 0x5C,
-    0x5C, 0x5C, 0x5C, 0x5C, 0x5C, 0x5C, 0x5C, 0x5C,
-    0x5C, 0x5C, 0x5C, 0x5C, 0x5C, 0x5C, 0x5C, 0x5C,
-    0x5C, 0x5C, 0x5C, 0x5C, 0x5C, 0x5C, 0x5C, 0x5C
-};
-#endif /* HMAC_HACK */
-
-/* add proc entry for this */
-struct safe_stats safestats;
-
-#define debug safe_debug
-int safe_debug = 0;
-module_param(safe_debug, int, 0644);
-MODULE_PARM_DESC(safe_debug, "Enable debug");
-
-static void safe_callback(struct safe_softc *, struct safe_ringentry *);
-static void safe_feed(struct safe_softc *, struct safe_ringentry *);
-#if defined(CONFIG_OCF_RANDOMHARVEST) && !defined(SAFE_NO_RNG)
-static void safe_rng_init(struct safe_softc *);
-int safe_rngbufsize = 8;               /* 32 bytes each read  */
-module_param(safe_rngbufsize, int, 0644);
-MODULE_PARM_DESC(safe_rngbufsize, "RNG polling buffer size (32-bit words)");
-int safe_rngmaxalarm = 8;              /* max alarms before reset */
-module_param(safe_rngmaxalarm, int, 0644);
-MODULE_PARM_DESC(safe_rngmaxalarm, "RNG max alarms before reset");
-#endif /* SAFE_NO_RNG */
-
-static void safe_totalreset(struct safe_softc *sc);
-static int safe_dmamap_aligned(struct safe_softc *sc, const struct safe_operand *op);
-static int safe_dmamap_uniform(struct safe_softc *sc, const struct safe_operand *op);
-static int safe_free_entry(struct safe_softc *sc, struct safe_ringentry *re);
-static int safe_kprocess(device_t dev, struct cryptkop *krp, int hint);
-static int safe_kstart(struct safe_softc *sc);
-static int safe_ksigbits(struct safe_softc *sc, struct crparam *cr);
-static void safe_kfeed(struct safe_softc *sc);
-static void safe_kpoll(unsigned long arg);
-static void safe_kload_reg(struct safe_softc *sc, u_int32_t off,
-                                                               u_int32_t len, struct crparam *n);
-
-static int safe_newsession(device_t, u_int32_t *, struct cryptoini *);
-static int safe_freesession(device_t, u_int64_t);
-static int safe_process(device_t, struct cryptop *, int);
-
-static device_method_t safe_methods = {
-       /* crypto device methods */
-       DEVMETHOD(cryptodev_newsession, safe_newsession),
-       DEVMETHOD(cryptodev_freesession,safe_freesession),
-       DEVMETHOD(cryptodev_process,    safe_process),
-       DEVMETHOD(cryptodev_kprocess,   safe_kprocess),
-};
-
-#define        READ_REG(sc,r)                  readl((sc)->sc_base_addr + (r))
-#define WRITE_REG(sc,r,val)            writel((val), (sc)->sc_base_addr + (r))
-
-#define SAFE_MAX_CHIPS 8
-static struct safe_softc *safe_chip_idx[SAFE_MAX_CHIPS];
-
-/*
- * split our buffers up into safe DMAable byte fragments to avoid lockup
- * bug in 1141 HW on rev 1.0.
- */
-
-static int
-pci_map_linear(
-       struct safe_softc *sc,
-       struct safe_operand *buf,
-       void *addr,
-       int len)
-{
-       dma_addr_t tmp;
-       int chunk, tlen = len;
-
-       tmp = pci_map_single(sc->sc_pcidev, addr, len, PCI_DMA_BIDIRECTIONAL);
-
-       buf->mapsize += len;
-       while (len > 0) {
-               chunk = (len > sc->sc_max_dsize) ? sc->sc_max_dsize : len;
-               buf->segs[buf->nsegs].ds_addr = tmp;
-               buf->segs[buf->nsegs].ds_len  = chunk;
-               buf->segs[buf->nsegs].ds_tlen = tlen;
-               buf->nsegs++;
-               tmp  += chunk;
-               len  -= chunk;
-               tlen = 0;
-       }
-       return 0;
-}
-
-/*
- * map in a given uio buffer (great on some arches :-)
- */
-
-static int
-pci_map_uio(struct safe_softc *sc, struct safe_operand *buf, struct uio *uio)
-{
-       struct iovec *iov = uio->uio_iov;
-       int n;
-
-       DPRINTF(("%s()\n", __FUNCTION__));
-
-       buf->mapsize = 0;
-       buf->nsegs = 0;
-
-       for (n = 0; n < uio->uio_iovcnt; n++) {
-               pci_map_linear(sc, buf, iov->iov_base, iov->iov_len);
-               iov++;
-       }
-
-       /* identify this buffer by the first segment */
-       buf->map = (void *) buf->segs[0].ds_addr;
-       return(0);
-}
-
-/*
- * map in a given sk_buff
- */
-
-static int
-pci_map_skb(struct safe_softc *sc,struct safe_operand *buf,struct sk_buff *skb)
-{
-       int i;
-
-       DPRINTF(("%s()\n", __FUNCTION__));
-
-       buf->mapsize = 0;
-       buf->nsegs = 0;
-
-       pci_map_linear(sc, buf, skb->data, skb_headlen(skb));
-
-       for (i = 0; i < skb_shinfo(skb)->nr_frags; i++) {
-               pci_map_linear(sc, buf,
-                               page_address(skb_shinfo(skb)->frags[i].page) +
-                                                       skb_shinfo(skb)->frags[i].page_offset,
-                               skb_shinfo(skb)->frags[i].size);
-       }
-
-       /* identify this buffer by the first segment */
-       buf->map = (void *) buf->segs[0].ds_addr;
-       return(0);
-}
-
-
-#if 0 /* not needed at this time */
-static void
-pci_sync_operand(struct safe_softc *sc, struct safe_operand *buf)
-{
-       int i;
-
-       DPRINTF(("%s()\n", __FUNCTION__));
-       for (i = 0; i < buf->nsegs; i++)
-               pci_dma_sync_single_for_cpu(sc->sc_pcidev, buf->segs[i].ds_addr,
-                               buf->segs[i].ds_len, PCI_DMA_BIDIRECTIONAL);
-}
-#endif
-
-static void
-pci_unmap_operand(struct safe_softc *sc, struct safe_operand *buf)
-{
-       int i;
-       DPRINTF(("%s()\n", __FUNCTION__));
-       for (i = 0; i < buf->nsegs; i++) {
-               if (buf->segs[i].ds_tlen) {
-                       DPRINTF(("%s - unmap %d 0x%x %d\n", __FUNCTION__, i, buf->segs[i].ds_addr, buf->segs[i].ds_tlen));
-                       pci_unmap_single(sc->sc_pcidev, buf->segs[i].ds_addr,
-                                       buf->segs[i].ds_tlen, PCI_DMA_BIDIRECTIONAL);
-                       DPRINTF(("%s - unmap %d 0x%x %d done\n", __FUNCTION__, i, buf->segs[i].ds_addr, buf->segs[i].ds_tlen));
-               }
-               buf->segs[i].ds_addr = 0;
-               buf->segs[i].ds_len = 0;
-               buf->segs[i].ds_tlen = 0;
-       }
-       buf->nsegs = 0;
-       buf->mapsize = 0;
-       buf->map = 0;
-}
-
-
-/*
- * SafeXcel Interrupt routine
- */
-static irqreturn_t
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,19)
-safe_intr(int irq, void *arg)
-#else
-safe_intr(int irq, void *arg, struct pt_regs *regs)
-#endif
-{
-       struct safe_softc *sc = arg;
-       int stat;
-       unsigned long flags;
-
-       stat = READ_REG(sc, SAFE_HM_STAT);
-
-       DPRINTF(("%s(stat=0x%x)\n", __FUNCTION__, stat));
-
-       if (stat == 0)          /* shared irq, not for us */
-               return IRQ_NONE;
-
-       WRITE_REG(sc, SAFE_HI_CLR, stat);       /* IACK */
-
-       if ((stat & SAFE_INT_PE_DDONE)) {
-               /*
-                * Descriptor(s) done; scan the ring and
-                * process completed operations.
-                */
-               spin_lock_irqsave(&sc->sc_ringmtx, flags);
-               while (sc->sc_back != sc->sc_front) {
-                       struct safe_ringentry *re = sc->sc_back;
-
-#ifdef SAFE_DEBUG
-                       if (debug) {
-                               safe_dump_ringstate(sc, __func__);
-                               safe_dump_request(sc, __func__, re);
-                       }
-#endif
-                       /*
-                        * safe_process marks ring entries that were allocated
-                        * but not used with a csr of zero.  This insures the
-                        * ring front pointer never needs to be set backwards
-                        * in the event that an entry is allocated but not used
-                        * because of a setup error.
-                        */
-                       DPRINTF(("%s re->re_desc.d_csr=0x%x\n", __FUNCTION__, re->re_desc.d_csr));
-                       if (re->re_desc.d_csr != 0) {
-                               if (!SAFE_PE_CSR_IS_DONE(re->re_desc.d_csr)) {
-                                       DPRINTF(("%s !CSR_IS_DONE\n", __FUNCTION__));
-                                       break;
-                               }
-                               if (!SAFE_PE_LEN_IS_DONE(re->re_desc.d_len)) {
-                                       DPRINTF(("%s !LEN_IS_DONE\n", __FUNCTION__));
-                                       break;
-                               }
-                               sc->sc_nqchip--;
-                               safe_callback(sc, re);
-                       }
-                       if (++(sc->sc_back) == sc->sc_ringtop)
-                               sc->sc_back = sc->sc_ring;
-               }
-               spin_unlock_irqrestore(&sc->sc_ringmtx, flags);
-       }
-
-       /*
-        * Check to see if we got any DMA Error
-        */
-       if (stat & SAFE_INT_PE_ERROR) {
-               printk("%s: dmaerr dmastat %08x\n", device_get_nameunit(sc->sc_dev),
-                               (int)READ_REG(sc, SAFE_PE_DMASTAT));
-               safestats.st_dmaerr++;
-               safe_totalreset(sc);
-#if 0
-               safe_feed(sc);
-#endif
-       }
-
-       if (sc->sc_needwakeup) {                /* XXX check high watermark */
-               int wakeup = sc->sc_needwakeup & (CRYPTO_SYMQ|CRYPTO_ASYMQ);
-               DPRINTF(("%s: wakeup crypto %x\n", __func__,
-                       sc->sc_needwakeup));
-               sc->sc_needwakeup &= ~wakeup;
-               crypto_unblock(sc->sc_cid, wakeup);
-       }
-       
-       return IRQ_HANDLED;
-}
-
-/*
- * safe_feed() - post a request to chip
- */
-static void
-safe_feed(struct safe_softc *sc, struct safe_ringentry *re)
-{
-       DPRINTF(("%s()\n", __FUNCTION__));
-#ifdef SAFE_DEBUG
-       if (debug) {
-               safe_dump_ringstate(sc, __func__);
-               safe_dump_request(sc, __func__, re);
-       }
-#endif
-       sc->sc_nqchip++;
-       if (sc->sc_nqchip > safestats.st_maxqchip)
-               safestats.st_maxqchip = sc->sc_nqchip;
-       /* poke h/w to check descriptor ring, any value can be written */
-       WRITE_REG(sc, SAFE_HI_RD_DESCR, 0);
-}
-
-#define        N(a)    (sizeof(a) / sizeof (a[0]))
-static void
-safe_setup_enckey(struct safe_session *ses, caddr_t key)
-{
-       int i;
-
-       bcopy(key, ses->ses_key, ses->ses_klen / 8);
-
-       /* PE is little-endian, insure proper byte order */
-       for (i = 0; i < N(ses->ses_key); i++)
-               ses->ses_key[i] = htole32(ses->ses_key[i]);
-}
-
-static void
-safe_setup_mackey(struct safe_session *ses, int algo, caddr_t key, int klen)
-{
-#ifdef HMAC_HACK
-       MD5_CTX md5ctx;
-       SHA1_CTX sha1ctx;
-       int i;
-
-
-       for (i = 0; i < klen; i++)
-               key[i] ^= HMAC_IPAD_VAL;
-
-       if (algo == CRYPTO_MD5_HMAC) {
-               MD5Init(&md5ctx);
-               MD5Update(&md5ctx, key, klen);
-               MD5Update(&md5ctx, hmac_ipad_buffer, MD5_HMAC_BLOCK_LEN - klen);
-               bcopy(md5ctx.md5_st8, ses->ses_hminner, sizeof(md5ctx.md5_st8));
-       } else {
-               SHA1Init(&sha1ctx);
-               SHA1Update(&sha1ctx, key, klen);
-               SHA1Update(&sha1ctx, hmac_ipad_buffer,
-                   SHA1_HMAC_BLOCK_LEN - klen);
-               bcopy(sha1ctx.h.b32, ses->ses_hminner, sizeof(sha1ctx.h.b32));
-       }
-
-       for (i = 0; i < klen; i++)
-               key[i] ^= (HMAC_IPAD_VAL ^ HMAC_OPAD_VAL);
-
-       if (algo == CRYPTO_MD5_HMAC) {
-               MD5Init(&md5ctx);
-               MD5Update(&md5ctx, key, klen);
-               MD5Update(&md5ctx, hmac_opad_buffer, MD5_HMAC_BLOCK_LEN - klen);
-               bcopy(md5ctx.md5_st8, ses->ses_hmouter, sizeof(md5ctx.md5_st8));
-       } else {
-               SHA1Init(&sha1ctx);
-               SHA1Update(&sha1ctx, key, klen);
-               SHA1Update(&sha1ctx, hmac_opad_buffer,
-                   SHA1_HMAC_BLOCK_LEN - klen);
-               bcopy(sha1ctx.h.b32, ses->ses_hmouter, sizeof(sha1ctx.h.b32));
-       }
-
-       for (i = 0; i < klen; i++)
-               key[i] ^= HMAC_OPAD_VAL;
-
-#if 0
-       /*
-        * this code prevents SHA working on a BE host,
-        * so it is obviously wrong.  I think the byte
-        * swap setup we do with the chip fixes this for us
-        */
-
-       /* PE is little-endian, insure proper byte order */
-       for (i = 0; i < N(ses->ses_hminner); i++) {
-               ses->ses_hminner[i] = htole32(ses->ses_hminner[i]);
-               ses->ses_hmouter[i] = htole32(ses->ses_hmouter[i]);
-       }
-#endif
-#else /* HMAC_HACK */
-       printk("safe: md5/sha not implemented\n");
-#endif /* HMAC_HACK */
-}
-#undef N
-
-/*
- * 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.
- */
-static int
-safe_newsession(device_t dev, u_int32_t *sidp, struct cryptoini *cri)
-{
-       struct safe_softc *sc = device_get_softc(dev);
-       struct cryptoini *c, *encini = NULL, *macini = NULL;
-       struct safe_session *ses = NULL;
-       int sesn;
-
-       DPRINTF(("%s()\n", __FUNCTION__));
-
-       if (sidp == NULL || cri == NULL || 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_NULL_HMAC) {
-                       if (macini)
-                               return (EINVAL);
-                       macini = c;
-               } else if (c->cri_alg == CRYPTO_DES_CBC ||
-                   c->cri_alg == CRYPTO_3DES_CBC ||
-                   c->cri_alg == CRYPTO_AES_CBC ||
-                   c->cri_alg == CRYPTO_NULL_CBC) {
-                       if (encini)
-                               return (EINVAL);
-                       encini = c;
-               } else
-                       return (EINVAL);
-       }
-       if (encini == NULL && macini == NULL)
-               return (EINVAL);
-       if (encini) {                   /* validate key length */
-               switch (encini->cri_alg) {
-               case CRYPTO_DES_CBC:
-                       if (encini->cri_klen != 64)
-                               return (EINVAL);
-                       break;
-               case CRYPTO_3DES_CBC:
-                       if (encini->cri_klen != 192)
-                               return (EINVAL);
-                       break;
-               case CRYPTO_AES_CBC:
-                       if (encini->cri_klen != 128 &&
-                           encini->cri_klen != 192 &&
-                           encini->cri_klen != 256)
-                               return (EINVAL);
-                       break;
-               }
-       }
-
-       if (sc->sc_sessions == NULL) {
-               ses = sc->sc_sessions = (struct safe_session *)
-                       kmalloc(sizeof(struct safe_session), SLAB_ATOMIC);
-               if (ses == NULL)
-                       return (ENOMEM);
-               memset(ses, 0, sizeof(struct safe_session));
-               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) {
-                       sesn = sc->sc_nsessions;
-                       ses = (struct safe_session *)
-                               kmalloc((sesn + 1) * sizeof(struct safe_session), SLAB_ATOMIC);
-                       if (ses == NULL)
-                               return (ENOMEM);
-                       memset(ses, 0, (sesn + 1) * sizeof(struct safe_session));
-                       bcopy(sc->sc_sessions, ses, sesn *
-                           sizeof(struct safe_session));
-                       bzero(sc->sc_sessions, sesn *
-                           sizeof(struct safe_session));
-                       kfree(sc->sc_sessions);
-                       sc->sc_sessions = ses;
-                       ses = &sc->sc_sessions[sesn];
-                       sc->sc_nsessions++;
-               }
-       }
-
-       bzero(ses, sizeof(struct safe_session));
-       ses->ses_used = 1;
-
-       if (encini) {
-               /* get an IV */
-               /* XXX may read fewer than requested */
-               read_random(ses->ses_iv, sizeof(ses->ses_iv));
-
-               ses->ses_klen = encini->cri_klen;
-               if (encini->cri_key != NULL)
-                       safe_setup_enckey(ses, encini->cri_key);
-       }
-
-       if (macini) {
-               ses->ses_mlen = macini->cri_mlen;
-               if (ses->ses_mlen == 0) {
-                       if (macini->cri_alg == CRYPTO_MD5_HMAC)
-                               ses->ses_mlen = MD5_HASH_LEN;
-                       else
-                               ses->ses_mlen = SHA1_HASH_LEN;
-               }
-
-               if (macini->cri_key != NULL) {
-                       safe_setup_mackey(ses, macini->cri_alg, macini->cri_key,
-                           macini->cri_klen / 8);
-               }
-       }
-
-       *sidp = SAFE_SID(device_get_unit(sc->sc_dev), sesn);
-       return (0);
-}
-
-/*
- * Deallocate a session.
- */
-static int
-safe_freesession(device_t dev, u_int64_t tid)
-{
-       struct safe_softc *sc = device_get_softc(dev);
-       int session, ret;
-       u_int32_t sid = ((u_int32_t) tid) & 0xffffffff;
-
-       DPRINTF(("%s()\n", __FUNCTION__));
-
-       if (sc == NULL)
-               return (EINVAL);
-
-       session = SAFE_SESSION(sid);
-       if (session < sc->sc_nsessions) {
-               bzero(&sc->sc_sessions[session], sizeof(sc->sc_sessions[session]));
-               ret = 0;
-       } else
-               ret = EINVAL;
-       return (ret);
-}
-
-
-static int
-safe_process(device_t dev, struct cryptop *crp, int hint)
-{
-       struct safe_softc *sc = device_get_softc(dev);
-       int err = 0, i, nicealign, uniform;
-       struct cryptodesc *crd1, *crd2, *maccrd, *enccrd;
-       int bypass, oplen, ivsize;
-       caddr_t iv;
-       int16_t coffset;
-       struct safe_session *ses;
-       struct safe_ringentry *re;
-       struct safe_sarec *sa;
-       struct safe_pdesc *pd;
-       u_int32_t cmd0, cmd1, staterec;
-       unsigned long flags;
-
-       DPRINTF(("%s()\n", __FUNCTION__));
-
-       if (crp == NULL || crp->crp_callback == NULL || sc == NULL) {
-               safestats.st_invalid++;
-               return (EINVAL);
-       }
-       if (SAFE_SESSION(crp->crp_sid) >= sc->sc_nsessions) {
-               safestats.st_badsession++;
-               return (EINVAL);
-       }
-
-       spin_lock_irqsave(&sc->sc_ringmtx, flags);
-       if (sc->sc_front == sc->sc_back && sc->sc_nqchip != 0) {
-               safestats.st_ringfull++;
-               sc->sc_needwakeup |= CRYPTO_SYMQ;
-               spin_unlock_irqrestore(&sc->sc_ringmtx, flags);
-               return (ERESTART);
-       }
-       re = sc->sc_front;
-
-       staterec = re->re_sa.sa_staterec;       /* save */
-       /* NB: zero everything but the PE descriptor */
-       bzero(&re->re_sa, sizeof(struct safe_ringentry) - sizeof(re->re_desc));
-       re->re_sa.sa_staterec = staterec;       /* restore */
-
-       re->re_crp = crp;
-       re->re_sesn = SAFE_SESSION(crp->crp_sid);
-
-       re->re_src.nsegs = 0;
-       re->re_dst.nsegs = 0;
-
-       if (crp->crp_flags & CRYPTO_F_SKBUF) {
-               re->re_src_skb = (struct sk_buff *)crp->crp_buf;
-               re->re_dst_skb = (struct sk_buff *)crp->crp_buf;
-       } else if (crp->crp_flags & CRYPTO_F_IOV) {
-               re->re_src_io = (struct uio *)crp->crp_buf;
-               re->re_dst_io = (struct uio *)crp->crp_buf;
-       } else {
-               safestats.st_badflags++;
-               err = EINVAL;
-               goto errout;    /* XXX we don't handle contiguous blocks! */
-       }
-
-       sa = &re->re_sa;
-       ses = &sc->sc_sessions[re->re_sesn];
-
-       crd1 = crp->crp_desc;
-       if (crd1 == NULL) {
-               safestats.st_nodesc++;
-               err = EINVAL;
-               goto errout;
-       }
-       crd2 = crd1->crd_next;
-
-       cmd0 = SAFE_SA_CMD0_BASIC;              /* basic group operation */
-       cmd1 = 0;
-       if (crd2 == NULL) {
-               if (crd1->crd_alg == CRYPTO_MD5_HMAC ||
-                   crd1->crd_alg == CRYPTO_SHA1_HMAC ||
-                   crd1->crd_alg == CRYPTO_NULL_HMAC) {
-                       maccrd = crd1;
-                       enccrd = NULL;
-                       cmd0 |= SAFE_SA_CMD0_OP_HASH;
-               } else if (crd1->crd_alg == CRYPTO_DES_CBC ||
-                   crd1->crd_alg == CRYPTO_3DES_CBC ||
-                   crd1->crd_alg == CRYPTO_AES_CBC ||
-                   crd1->crd_alg == CRYPTO_NULL_CBC) {
-                       maccrd = NULL;
-                       enccrd = crd1;
-                       cmd0 |= SAFE_SA_CMD0_OP_CRYPT;
-               } else {
-                       safestats.st_badalg++;
-                       err = EINVAL;
-                       goto errout;
-               }
-       } else {
-               if ((crd1->crd_alg == CRYPTO_MD5_HMAC ||
-                   crd1->crd_alg == CRYPTO_SHA1_HMAC ||
-                   crd1->crd_alg == CRYPTO_NULL_HMAC) &&
-                   (crd2->crd_alg == CRYPTO_DES_CBC ||
-                       crd2->crd_alg == CRYPTO_3DES_CBC ||
-                       crd2->crd_alg == CRYPTO_AES_CBC ||
-                       crd2->crd_alg == CRYPTO_NULL_CBC) &&
-                   ((crd2->crd_flags & CRD_F_ENCRYPT) == 0)) {
-                       maccrd = crd1;
-                       enccrd = crd2;
-               } else if ((crd1->crd_alg == CRYPTO_DES_CBC ||
-                   crd1->crd_alg == CRYPTO_3DES_CBC ||
-                   crd1->crd_alg == CRYPTO_AES_CBC ||
-                   crd1->crd_alg == CRYPTO_NULL_CBC) &&
-                   (crd2->crd_alg == CRYPTO_MD5_HMAC ||
-                       crd2->crd_alg == CRYPTO_SHA1_HMAC ||
-                       crd2->crd_alg == CRYPTO_NULL_HMAC) &&
-                   (crd1->crd_flags & CRD_F_ENCRYPT)) {
-                       enccrd = crd1;
-                       maccrd = crd2;
-               } else {
-                       safestats.st_badalg++;
-                       err = EINVAL;
-                       goto errout;
-               }
-               cmd0 |= SAFE_SA_CMD0_OP_BOTH;
-       }
-
-       if (enccrd) {
-               if (enccrd->crd_flags & CRD_F_KEY_EXPLICIT)
-                       safe_setup_enckey(ses, enccrd->crd_key);
-
-               if (enccrd->crd_alg == CRYPTO_DES_CBC) {
-                       cmd0 |= SAFE_SA_CMD0_DES;
-                       cmd1 |= SAFE_SA_CMD1_CBC;
-                       ivsize = 2*sizeof(u_int32_t);
-               } else if (enccrd->crd_alg == CRYPTO_3DES_CBC) {
-                       cmd0 |= SAFE_SA_CMD0_3DES;
-                       cmd1 |= SAFE_SA_CMD1_CBC;
-                       ivsize = 2*sizeof(u_int32_t);
-               } else if (enccrd->crd_alg == CRYPTO_AES_CBC) {
-                       cmd0 |= SAFE_SA_CMD0_AES;
-                       cmd1 |= SAFE_SA_CMD1_CBC;
-                       if (ses->ses_klen == 128)
-                            cmd1 |=  SAFE_SA_CMD1_AES128;
-                       else if (ses->ses_klen == 192)
-                            cmd1 |=  SAFE_SA_CMD1_AES192;
-                       else
-                            cmd1 |=  SAFE_SA_CMD1_AES256;
-                       ivsize = 4*sizeof(u_int32_t);
-               } else {
-                       cmd0 |= SAFE_SA_CMD0_CRYPT_NULL;
-                       ivsize = 0;
-               }
-
-               /*
-                * Setup encrypt/decrypt state.  When using basic ops
-                * we can't use an inline IV because hash/crypt offset
-                * must be from the end of the IV to the start of the
-                * crypt data and this leaves out the preceding header
-                * from the hash calculation.  Instead we place the IV
-                * in the state record and set the hash/crypt offset to
-                * copy both the header+IV.
-                */
-               if (enccrd->crd_flags & CRD_F_ENCRYPT) {
-                       cmd0 |= SAFE_SA_CMD0_OUTBOUND;
-
-                       if (enccrd->crd_flags & CRD_F_IV_EXPLICIT)
-                               iv = enccrd->crd_iv;
-                       else
-                               iv = (caddr_t) ses->ses_iv;
-                       if ((enccrd->crd_flags & CRD_F_IV_PRESENT) == 0) {
-                               crypto_copyback(crp->crp_flags, crp->crp_buf,
-                                   enccrd->crd_inject, ivsize, iv);
-                       }
-                       bcopy(iv, re->re_sastate.sa_saved_iv, ivsize);
-                       /* make iv LE */
-                       for (i = 0; i < ivsize/sizeof(re->re_sastate.sa_saved_iv[0]); i++)
-                               re->re_sastate.sa_saved_iv[i] =
-                                       cpu_to_le32(re->re_sastate.sa_saved_iv[i]);
-                       cmd0 |= SAFE_SA_CMD0_IVLD_STATE | SAFE_SA_CMD0_SAVEIV;
-                       re->re_flags |= SAFE_QFLAGS_COPYOUTIV;
-               } else {
-                       cmd0 |= SAFE_SA_CMD0_INBOUND;
-
-                       if (enccrd->crd_flags & CRD_F_IV_EXPLICIT) {
-                               bcopy(enccrd->crd_iv,
-                                       re->re_sastate.sa_saved_iv, ivsize);
-                       } else {
-                               crypto_copydata(crp->crp_flags, crp->crp_buf,
-                                   enccrd->crd_inject, ivsize,
-                                   (caddr_t)re->re_sastate.sa_saved_iv);
-                       }
-                       /* make iv LE */
-                       for (i = 0; i < ivsize/sizeof(re->re_sastate.sa_saved_iv[0]); i++)
-                               re->re_sastate.sa_saved_iv[i] =
-                                       cpu_to_le32(re->re_sastate.sa_saved_iv[i]);
-                       cmd0 |= SAFE_SA_CMD0_IVLD_STATE;
-               }
-               /*
-                * For basic encryption use the zero pad algorithm.
-                * This pads results to an 8-byte boundary and
-                * suppresses padding verification for inbound (i.e.
-                * decrypt) operations.
-                *
-                * NB: Not sure if the 8-byte pad boundary is a problem.
-                */
-               cmd0 |= SAFE_SA_CMD0_PAD_ZERO;
-
-               /* XXX assert key bufs have the same size */
-               bcopy(ses->ses_key, sa->sa_key, sizeof(sa->sa_key));
-       }
-
-       if (maccrd) {
-               if (maccrd->crd_flags & CRD_F_KEY_EXPLICIT) {
-                       safe_setup_mackey(ses, maccrd->crd_alg,
-                           maccrd->crd_key, maccrd->crd_klen / 8);
-               }
-
-               if (maccrd->crd_alg == CRYPTO_MD5_HMAC) {
-                       cmd0 |= SAFE_SA_CMD0_MD5;
-                       cmd1 |= SAFE_SA_CMD1_HMAC;      /* NB: enable HMAC */
-               } else if (maccrd->crd_alg == CRYPTO_SHA1_HMAC) {
-                       cmd0 |= SAFE_SA_CMD0_SHA1;
-                       cmd1 |= SAFE_SA_CMD1_HMAC;      /* NB: enable HMAC */
-               } else {
-                       cmd0 |= SAFE_SA_CMD0_HASH_NULL;
-               }
-               /*
-                * Digest data is loaded from the SA and the hash
-                * result is saved to the state block where we
-                * retrieve it for return to the caller.
-                */
-               /* XXX assert digest bufs have the same size */
-               bcopy(ses->ses_hminner, sa->sa_indigest,
-                       sizeof(sa->sa_indigest));
-               bcopy(ses->ses_hmouter, sa->sa_outdigest,
-                       sizeof(sa->sa_outdigest));
-
-               cmd0 |= SAFE_SA_CMD0_HSLD_SA | SAFE_SA_CMD0_SAVEHASH;
-               re->re_flags |= SAFE_QFLAGS_COPYOUTICV;
-       }
-
-       if (enccrd && maccrd) {
-               /*
-                * The offset from hash data to the start of
-                * crypt data is the difference in the skips.
-                */
-               bypass = maccrd->crd_skip;
-               coffset = enccrd->crd_skip - maccrd->crd_skip;
-               if (coffset < 0) {
-                       DPRINTF(("%s: hash does not precede crypt; "
-                               "mac skip %u enc skip %u\n",
-                               __func__, maccrd->crd_skip, enccrd->crd_skip));
-                       safestats.st_skipmismatch++;
-                       err = EINVAL;
-                       goto errout;
-               }
-               oplen = enccrd->crd_skip + enccrd->crd_len;
-               if (maccrd->crd_skip + maccrd->crd_len != oplen) {
-                       DPRINTF(("%s: hash amount %u != crypt amount %u\n",
-                               __func__, maccrd->crd_skip + maccrd->crd_len,
-                               oplen));
-                       safestats.st_lenmismatch++;
-                       err = EINVAL;
-                       goto errout;
-               }
-#ifdef SAFE_DEBUG
-               if (debug) {
-                       printf("mac: skip %d, len %d, inject %d\n",
-                           maccrd->crd_skip, maccrd->crd_len,
-                           maccrd->crd_inject);
-                       printf("enc: skip %d, len %d, inject %d\n",
-                           enccrd->crd_skip, enccrd->crd_len,
-                           enccrd->crd_inject);
-                       printf("bypass %d coffset %d oplen %d\n",
-                               bypass, coffset, oplen);
-               }
-#endif
-               if (coffset & 3) {      /* offset must be 32-bit aligned */
-                       DPRINTF(("%s: coffset %u misaligned\n",
-                               __func__, coffset));
-                       safestats.st_coffmisaligned++;
-                       err = EINVAL;
-                       goto errout;
-               }
-               coffset >>= 2;
-               if (coffset > 255) {    /* offset must be <256 dwords */
-                       DPRINTF(("%s: coffset %u too big\n",
-                               __func__, coffset));
-                       safestats.st_cofftoobig++;
-                       err = EINVAL;
-                       goto errout;
-               }
-               /*
-                * Tell the hardware to copy the header to the output.
-                * The header is defined as the data from the end of
-                * the bypass to the start of data to be encrypted. 
-                * Typically this is the inline IV.  Note that you need
-                * to do this even if src+dst are the same; it appears
-                * that w/o this bit the crypted data is written
-                * immediately after the bypass data.
-                */
-               cmd1 |= SAFE_SA_CMD1_HDRCOPY;
-               /*
-                * Disable IP header mutable bit handling.  This is
-                * needed to get correct HMAC calculations.
-                */
-               cmd1 |= SAFE_SA_CMD1_MUTABLE;
-       } else {
-               if (enccrd) {
-                       bypass = enccrd->crd_skip;
-                       oplen = bypass + enccrd->crd_len;
-               } else {
-                       bypass = maccrd->crd_skip;
-                       oplen = bypass + maccrd->crd_len;
-               }
-               coffset = 0;
-       }
-       /* XXX verify multiple of 4 when using s/g */
-       if (bypass > 96) {              /* bypass offset must be <= 96 bytes */
-               DPRINTF(("%s: bypass %u too big\n", __func__, bypass));
-               safestats.st_bypasstoobig++;
-               err = EINVAL;
-               goto errout;
-       }
-
-       if (crp->crp_flags & CRYPTO_F_SKBUF) {
-               if (pci_map_skb(sc, &re->re_src, re->re_src_skb)) {
-                       safestats.st_noload++;
-                       err = ENOMEM;
-                       goto errout;
-               }
-       } else if (crp->crp_flags & CRYPTO_F_IOV) {
-               if (pci_map_uio(sc, &re->re_src, re->re_src_io)) {
-                       safestats.st_noload++;
-                       err = ENOMEM;
-                       goto errout;
-               }
-       }
-       nicealign = safe_dmamap_aligned(sc, &re->re_src);
-       uniform = safe_dmamap_uniform(sc, &re->re_src);
-
-       DPRINTF(("src nicealign %u uniform %u nsegs %u\n",
-               nicealign, uniform, re->re_src.nsegs));
-       if (re->re_src.nsegs > 1) {
-               re->re_desc.d_src = sc->sc_spalloc.dma_paddr +
-                       ((caddr_t) sc->sc_spfree - (caddr_t) sc->sc_spring);
-               for (i = 0; i < re->re_src_nsegs; i++) {
-                       /* NB: no need to check if there's space */
-                       pd = sc->sc_spfree;
-                       if (++(sc->sc_spfree) == sc->sc_springtop)
-                               sc->sc_spfree = sc->sc_spring;
-
-                       KASSERT((pd->pd_flags&3) == 0 ||
-                               (pd->pd_flags&3) == SAFE_PD_DONE,
-                               ("bogus source particle descriptor; flags %x",
-                               pd->pd_flags));
-                       pd->pd_addr = re->re_src_segs[i].ds_addr;
-                       pd->pd_size = re->re_src_segs[i].ds_len;
-                       pd->pd_flags = SAFE_PD_READY;
-               }
-               cmd0 |= SAFE_SA_CMD0_IGATHER;
-       } else {
-               /*
-                * No need for gather, reference the operand directly.
-                */
-               re->re_desc.d_src = re->re_src_segs[0].ds_addr;
-       }
-
-       if (enccrd == NULL && maccrd != NULL) {
-               /*
-                * Hash op; no destination needed.
-                */
-       } else {
-               if (crp->crp_flags & (CRYPTO_F_IOV|CRYPTO_F_SKBUF)) {
-                       if (!nicealign) {
-                               safestats.st_iovmisaligned++;
-                               err = EINVAL;
-                               goto errout;
-                       }
-                       if (uniform != 1) {
-                               device_printf(sc->sc_dev, "!uniform source\n");
-                               if (!uniform) {
-                                       /*
-                                        * There's no way to handle the DMA
-                                        * requirements with this uio.  We
-                                        * could create a separate DMA area for
-                                        * the result and then copy it back,
-                                        * but for now we just bail and return
-                                        * an error.  Note that uio requests
-                                        * > SAFE_MAX_DSIZE are handled because
-                                        * the DMA map and segment list for the
-                                        * destination wil result in a
-                                        * destination particle list that does
-                                        * the necessary scatter DMA.
-                                        */ 
-                                       safestats.st_iovnotuniform++;
-                                       err = EINVAL;
-                                       goto errout;
-                               }
-                       } else
-                               re->re_dst = re->re_src;
-               } else {
-                       safestats.st_badflags++;
-                       err = EINVAL;
-                       goto errout;
-               }
-
-               if (re->re_dst.nsegs > 1) {
-                       re->re_desc.d_dst = sc->sc_dpalloc.dma_paddr +
-                           ((caddr_t) sc->sc_dpfree - (caddr_t) sc->sc_dpring);
-                       for (i = 0; i < re->re_dst_nsegs; i++) {
-                               pd = sc->sc_dpfree;
-                               KASSERT((pd->pd_flags&3) == 0 ||
-                                       (pd->pd_flags&3) == SAFE_PD_DONE,
-                                       ("bogus dest particle descriptor; flags %x",
-                                               pd->pd_flags));
-                               if (++(sc->sc_dpfree) == sc->sc_dpringtop)
-                                       sc->sc_dpfree = sc->sc_dpring;
-                               pd->pd_addr = re->re_dst_segs[i].ds_addr;
-                               pd->pd_flags = SAFE_PD_READY;
-                       }
-                       cmd0 |= SAFE_SA_CMD0_OSCATTER;
-               } else {
-                       /*
-                        * No need for scatter, reference the operand directly.
-                        */
-                       re->re_desc.d_dst = re->re_dst_segs[0].ds_addr;
-               }
-       }
-
-       /*
-        * All done with setup; fillin the SA command words
-        * and the packet engine descriptor.  The operation
-        * is now ready for submission to the hardware.
-        */
-       sa->sa_cmd0 = cmd0 | SAFE_SA_CMD0_IPCI | SAFE_SA_CMD0_OPCI;
-       sa->sa_cmd1 = cmd1
-                   | (coffset << SAFE_SA_CMD1_OFFSET_S)
-                   | SAFE_SA_CMD1_SAREV1       /* Rev 1 SA data structure */
-                   | SAFE_SA_CMD1_SRPCI
-                   ;
-       /*
-        * NB: the order of writes is important here.  In case the
-        * chip is scanning the ring because of an outstanding request
-        * it might nab this one too.  In that case we need to make
-        * sure the setup is complete before we write the length
-        * field of the descriptor as it signals the descriptor is
-        * ready for processing.
-        */
-       re->re_desc.d_csr = SAFE_PE_CSR_READY | SAFE_PE_CSR_SAPCI;
-       if (maccrd)
-               re->re_desc.d_csr |= SAFE_PE_CSR_LOADSA | SAFE_PE_CSR_HASHFINAL;
-       wmb();
-       re->re_desc.d_len = oplen
-                         | SAFE_PE_LEN_READY
-                         | (bypass << SAFE_PE_LEN_BYPASS_S)
-                         ;
-
-       safestats.st_ipackets++;
-       safestats.st_ibytes += oplen;
-
-       if (++(sc->sc_front) == sc->sc_ringtop)
-               sc->sc_front = sc->sc_ring;
-
-       /* XXX honor batching */
-       safe_feed(sc, re);
-       spin_unlock_irqrestore(&sc->sc_ringmtx, flags);
-       return (0);
-
-errout:
-       if (re->re_src.map != re->re_dst.map)
-               pci_unmap_operand(sc, &re->re_dst);
-       if (re->re_src.map)
-               pci_unmap_operand(sc, &re->re_src);
-       spin_unlock_irqrestore(&sc->sc_ringmtx, flags);
-       if (err != ERESTART) {
-               crp->crp_etype = err;
-               crypto_done(crp);
-       } else {
-               sc->sc_needwakeup |= CRYPTO_SYMQ;
-       }
-       return (err);
-}
-
-static void
-safe_callback(struct safe_softc *sc, struct safe_ringentry *re)
-{
-       struct cryptop *crp = (struct cryptop *)re->re_crp;
-       struct cryptodesc *crd;
-
-       DPRINTF(("%s()\n", __FUNCTION__));
-
-       safestats.st_opackets++;
-       safestats.st_obytes += re->re_dst.mapsize;
-
-       if (re->re_desc.d_csr & SAFE_PE_CSR_STATUS) {
-               device_printf(sc->sc_dev, "csr 0x%x cmd0 0x%x cmd1 0x%x\n",
-                       re->re_desc.d_csr,
-                       re->re_sa.sa_cmd0, re->re_sa.sa_cmd1);
-               safestats.st_peoperr++;
-               crp->crp_etype = EIO;           /* something more meaningful? */
-       }
-
-       if (re->re_dst.map != NULL && re->re_dst.map != re->re_src.map)
-               pci_unmap_operand(sc, &re->re_dst);
-       pci_unmap_operand(sc, &re->re_src);
-
-       /* 
-        * If result was written to a differet mbuf chain, swap
-        * it in as the return value and reclaim the original.
-        */
-       if ((crp->crp_flags & CRYPTO_F_SKBUF) && re->re_src_skb != re->re_dst_skb) {
-               device_printf(sc->sc_dev, "no CRYPTO_F_SKBUF swapping support\n");
-               /* kfree_skb(skb) */
-               /* crp->crp_buf = (caddr_t)re->re_dst_skb */
-               return;
-       }
-
-       if (re->re_flags & SAFE_QFLAGS_COPYOUTIV) {
-               /* copy out IV for future use */
-               for (crd = crp->crp_desc; crd; crd = crd->crd_next) {
-                       int i;
-                       int ivsize;
-
-                       if (crd->crd_alg == CRYPTO_DES_CBC ||
-                           crd->crd_alg == CRYPTO_3DES_CBC) {
-                               ivsize = 2*sizeof(u_int32_t);
-                       } else if (crd->crd_alg == CRYPTO_AES_CBC) {
-                               ivsize = 4*sizeof(u_int32_t);
-                       } else
-                               continue;
-                       crypto_copydata(crp->crp_flags, crp->crp_buf,
-                           crd->crd_skip + crd->crd_len - ivsize, ivsize,
-                           (caddr_t)sc->sc_sessions[re->re_sesn].ses_iv);
-                       for (i = 0;
-                                       i < ivsize/sizeof(sc->sc_sessions[re->re_sesn].ses_iv[0]);
-                                       i++)
-                               sc->sc_sessions[re->re_sesn].ses_iv[i] =
-                                       cpu_to_le32(sc->sc_sessions[re->re_sesn].ses_iv[i]);
-                       break;
-               }
-       }
-
-       if (re->re_flags & SAFE_QFLAGS_COPYOUTICV) {
-               /* copy out ICV result */
-               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_NULL_HMAC))
-                               continue;
-                       if (crd->crd_alg == CRYPTO_SHA1_HMAC) {
-                               /*
-                                * SHA-1 ICV's are byte-swapped; fix 'em up
-                                * before copy them to their destination.
-                                */
-                               re->re_sastate.sa_saved_indigest[0] =
-                                       cpu_to_be32(re->re_sastate.sa_saved_indigest[0]);
-                               re->re_sastate.sa_saved_indigest[1] = 
-                                       cpu_to_be32(re->re_sastate.sa_saved_indigest[1]);
-                               re->re_sastate.sa_saved_indigest[2] =
-                                       cpu_to_be32(re->re_sastate.sa_saved_indigest[2]);
-                       } else {
-                               re->re_sastate.sa_saved_indigest[0] =
-                                       cpu_to_le32(re->re_sastate.sa_saved_indigest[0]);
-                               re->re_sastate.sa_saved_indigest[1] = 
-                                       cpu_to_le32(re->re_sastate.sa_saved_indigest[1]);
-                               re->re_sastate.sa_saved_indigest[2] =
-                                       cpu_to_le32(re->re_sastate.sa_saved_indigest[2]);
-                       }
-                       crypto_copyback(crp->crp_flags, crp->crp_buf,
-                           crd->crd_inject,
-                           sc->sc_sessions[re->re_sesn].ses_mlen,
-                           (caddr_t)re->re_sastate.sa_saved_indigest);
-                       break;
-               }
-       }
-       crypto_done(crp);
-}
-
-
-#if defined(CONFIG_OCF_RANDOMHARVEST) && !defined(SAFE_NO_RNG)
-#define        SAFE_RNG_MAXWAIT        1000
-
-static void
-safe_rng_init(struct safe_softc *sc)
-{
-       u_int32_t w, v;
-       int i;
-
-       DPRINTF(("%s()\n", __FUNCTION__));
-
-       WRITE_REG(sc, SAFE_RNG_CTRL, 0);
-       /* use default value according to the manual */
-       WRITE_REG(sc, SAFE_RNG_CNFG, 0x834);    /* magic from SafeNet */
-       WRITE_REG(sc, SAFE_RNG_ALM_CNT, 0);
-
-       /*
-        * There is a bug in rev 1.0 of the 1140 that when the RNG
-        * is brought out of reset the ready status flag does not
-        * work until the RNG has finished its internal initialization.
-        *
-        * So in order to determine the device is through its
-        * initialization we must read the data register, using the
-        * status reg in the read in case it is initialized.  Then read
-        * the data register until it changes from the first read.
-        * Once it changes read the data register until it changes
-        * again.  At this time the RNG is considered initialized. 
-        * This could take between 750ms - 1000ms in time.
-        */
-       i = 0;
-       w = READ_REG(sc, SAFE_RNG_OUT);
-       do {
-               v = READ_REG(sc, SAFE_RNG_OUT);
-               if (v != w) {
-                       w = v;
-                       break;
-               }
-               DELAY(10);
-       } while (++i < SAFE_RNG_MAXWAIT);
-
-       /* Wait Until data changes again */
-       i = 0;
-       do {
-               v = READ_REG(sc, SAFE_RNG_OUT);
-               if (v != w)
-                       break;
-               DELAY(10);
-       } while (++i < SAFE_RNG_MAXWAIT);
-}
-
-static __inline void
-safe_rng_disable_short_cycle(struct safe_softc *sc)
-{
-       DPRINTF(("%s()\n", __FUNCTION__));
-
-       WRITE_REG(sc, SAFE_RNG_CTRL,
-               READ_REG(sc, SAFE_RNG_CTRL) &~ SAFE_RNG_CTRL_SHORTEN);
-}
-
-static __inline void
-safe_rng_enable_short_cycle(struct safe_softc *sc)
-{
-       DPRINTF(("%s()\n", __FUNCTION__));
-
-       WRITE_REG(sc, SAFE_RNG_CTRL, 
-               READ_REG(sc, SAFE_RNG_CTRL) | SAFE_RNG_CTRL_SHORTEN);
-}
-
-static __inline u_int32_t
-safe_rng_read(struct safe_softc *sc)
-{
-       int i;
-
-       i = 0;
-       while (READ_REG(sc, SAFE_RNG_STAT) != 0 && ++i < SAFE_RNG_MAXWAIT)
-               ;
-       return READ_REG(sc, SAFE_RNG_OUT);
-}
-
-static int
-safe_read_random(void *arg, u_int32_t *buf, int maxwords)
-{
-       struct safe_softc *sc = (struct safe_softc *) arg;
-       int i, rc;
-
-       DPRINTF(("%s()\n", __FUNCTION__));
-       
-       safestats.st_rng++;
-       /*
-        * Fetch the next block of data.
-        */
-       if (maxwords > safe_rngbufsize)
-               maxwords = safe_rngbufsize;
-       if (maxwords > SAFE_RNG_MAXBUFSIZ)
-               maxwords = SAFE_RNG_MAXBUFSIZ;
-retry:
-       /* read as much as we can */
-       for (rc = 0; rc < maxwords; rc++) {
-               if (READ_REG(sc, SAFE_RNG_STAT) != 0)
-                       break;
-               buf[rc] = READ_REG(sc, SAFE_RNG_OUT);
-       }
-       if (rc == 0)
-               return 0;
-       /*
-        * Check the comparator alarm count and reset the h/w if
-        * it exceeds our threshold.  This guards against the
-        * hardware oscillators resonating with external signals.
-        */
-       if (READ_REG(sc, SAFE_RNG_ALM_CNT) > safe_rngmaxalarm) {
-               u_int32_t freq_inc, w;
-
-               DPRINTF(("%s: alarm count %u exceeds threshold %u\n", __func__,
-                       (unsigned)READ_REG(sc, SAFE_RNG_ALM_CNT), safe_rngmaxalarm));
-               safestats.st_rngalarm++;
-               safe_rng_enable_short_cycle(sc);
-               freq_inc = 18;
-               for (i = 0; i < 64; i++) {
-                       w = READ_REG(sc, SAFE_RNG_CNFG);
-                       freq_inc = ((w + freq_inc) & 0x3fL);
-                       w = ((w & ~0x3fL) | freq_inc);
-                       WRITE_REG(sc, SAFE_RNG_CNFG, w);
-
-                       WRITE_REG(sc, SAFE_RNG_ALM_CNT, 0);
-
-                       (void) safe_rng_read(sc);
-                       DELAY(25);
-
-                       if (READ_REG(sc, SAFE_RNG_ALM_CNT) == 0) {
-                               safe_rng_disable_short_cycle(sc);
-                               goto retry;
-                       }
-                       freq_inc = 1;
-               }
-               safe_rng_disable_short_cycle(sc);
-       } else
-               WRITE_REG(sc, SAFE_RNG_ALM_CNT, 0);
-
-       return(rc);
-}
-#endif /* defined(CONFIG_OCF_RANDOMHARVEST) && !defined(SAFE_NO_RNG) */
-
-
-/*
- * Resets the board.  Values in the regesters are left as is
- * from the reset (i.e. initial values are assigned elsewhere).
- */
-static void
-safe_reset_board(struct safe_softc *sc)
-{
-       u_int32_t v;
-       /*
-        * Reset the device.  The manual says no delay
-        * is needed between marking and clearing reset.
-        */
-       DPRINTF(("%s()\n", __FUNCTION__));
-
-       v = READ_REG(sc, SAFE_PE_DMACFG) &~
-               (SAFE_PE_DMACFG_PERESET | SAFE_PE_DMACFG_PDRRESET |
-                SAFE_PE_DMACFG_SGRESET);
-       WRITE_REG(sc, SAFE_PE_DMACFG, v
-                                   | SAFE_PE_DMACFG_PERESET
-                                   | SAFE_PE_DMACFG_PDRRESET
-                                   | SAFE_PE_DMACFG_SGRESET);
-       WRITE_REG(sc, SAFE_PE_DMACFG, v);
-}
-
-/*
- * Initialize registers we need to touch only once.
- */
-static void
-safe_init_board(struct safe_softc *sc)
-{
-       u_int32_t v, dwords;
-
-       DPRINTF(("%s()\n", __FUNCTION__));
-
-       v = READ_REG(sc, SAFE_PE_DMACFG);
-       v &=~ (   SAFE_PE_DMACFG_PEMODE
-                       | SAFE_PE_DMACFG_FSENA          /* failsafe enable */
-                       | SAFE_PE_DMACFG_GPRPCI         /* gather ring on PCI */
-                       | SAFE_PE_DMACFG_SPRPCI         /* scatter ring on PCI */
-                       | SAFE_PE_DMACFG_ESDESC         /* endian-swap descriptors */
-                       | SAFE_PE_DMACFG_ESPDESC        /* endian-swap part. desc's */
-                       | SAFE_PE_DMACFG_ESSA           /* endian-swap SA's */
-                       | SAFE_PE_DMACFG_ESPACKET       /* swap the packet data */
-                 );
-       v |= SAFE_PE_DMACFG_FSENA               /* failsafe enable */
-         |  SAFE_PE_DMACFG_GPRPCI              /* gather ring on PCI */
-         |  SAFE_PE_DMACFG_SPRPCI              /* scatter ring on PCI */
-         |  SAFE_PE_DMACFG_ESDESC              /* endian-swap descriptors */
-         |  SAFE_PE_DMACFG_ESPDESC             /* endian-swap part. desc's */
-         |  SAFE_PE_DMACFG_ESSA                /* endian-swap SA's */
-#if 0
-         |  SAFE_PE_DMACFG_ESPACKET    /* swap the packet data */
-#endif
-         ;
-       WRITE_REG(sc, SAFE_PE_DMACFG, v);
-
-#ifdef __BIG_ENDIAN
-       /* tell the safenet that we are 4321 and not 1234 */
-       WRITE_REG(sc, SAFE_ENDIAN, 0xe4e41b1b);
-#endif
-
-       if (sc->sc_chiprev == SAFE_REV(1,0)) {
-               /*
-                * Avoid large PCI DMA transfers.  Rev 1.0 has a bug where
-                * "target mode transfers" done while the chip is DMA'ing
-                * >1020 bytes cause the hardware to lockup.  To avoid this
-                * we reduce the max PCI transfer size and use small source
-                * particle descriptors (<= 256 bytes).
-                */
-               WRITE_REG(sc, SAFE_DMA_CFG, 256);
-               device_printf(sc->sc_dev,
-                       "Reduce max DMA size to %u words for rev %u.%u WAR\n",
-                       (unsigned) ((READ_REG(sc, SAFE_DMA_CFG)>>2) & 0xff),
-                       (unsigned) SAFE_REV_MAJ(sc->sc_chiprev),
-                       (unsigned) SAFE_REV_MIN(sc->sc_chiprev));
-               sc->sc_max_dsize = 256;
-       } else {
-               sc->sc_max_dsize = SAFE_MAX_DSIZE;
-       }
-
-       /* NB: operands+results are overlaid */
-       WRITE_REG(sc, SAFE_PE_PDRBASE, sc->sc_ringalloc.dma_paddr);
-       WRITE_REG(sc, SAFE_PE_RDRBASE, sc->sc_ringalloc.dma_paddr);
-       /*
-        * Configure ring entry size and number of items in the ring.
-        */
-       KASSERT((sizeof(struct safe_ringentry) % sizeof(u_int32_t)) == 0,
-               ("PE ring entry not 32-bit aligned!"));
-       dwords = sizeof(struct safe_ringentry) / sizeof(u_int32_t);
-       WRITE_REG(sc, SAFE_PE_RINGCFG,
-               (dwords << SAFE_PE_RINGCFG_OFFSET_S) | SAFE_MAX_NQUEUE);
-       WRITE_REG(sc, SAFE_PE_RINGPOLL, 0);     /* disable polling */
-
-       WRITE_REG(sc, SAFE_PE_GRNGBASE, sc->sc_spalloc.dma_paddr);
-       WRITE_REG(sc, SAFE_PE_SRNGBASE, sc->sc_dpalloc.dma_paddr);
-       WRITE_REG(sc, SAFE_PE_PARTSIZE,
-               (SAFE_TOTAL_DPART<<16) | SAFE_TOTAL_SPART);
-       /*
-        * NB: destination particles are fixed size.  We use
-        *     an mbuf cluster and require all results go to
-        *     clusters or smaller.
-        */
-       WRITE_REG(sc, SAFE_PE_PARTCFG, sc->sc_max_dsize);
-
-       /* it's now safe to enable PE mode, do it */
-       WRITE_REG(sc, SAFE_PE_DMACFG, v | SAFE_PE_DMACFG_PEMODE);
-
-       /*
-        * Configure hardware to use level-triggered interrupts and
-        * to interrupt after each descriptor is processed.
-        */
-       WRITE_REG(sc, SAFE_HI_CFG, SAFE_HI_CFG_LEVEL);
-       WRITE_REG(sc, SAFE_HI_CLR, 0xffffffff);
-       WRITE_REG(sc, SAFE_HI_DESC_CNT, 1);
-       WRITE_REG(sc, SAFE_HI_MASK, SAFE_INT_PE_DDONE | SAFE_INT_PE_ERROR);
-}
-
-
-/*
- * Clean up after a chip crash.
- * It is assumed that the caller in splimp()
- */
-static void
-safe_cleanchip(struct safe_softc *sc)
-{
-       DPRINTF(("%s()\n", __FUNCTION__));
-
-       if (sc->sc_nqchip != 0) {
-               struct safe_ringentry *re = sc->sc_back;
-
-               while (re != sc->sc_front) {
-                       if (re->re_desc.d_csr != 0)
-                               safe_free_entry(sc, re);
-                       if (++re == sc->sc_ringtop)
-                               re = sc->sc_ring;
-               }
-               sc->sc_back = re;
-               sc->sc_nqchip = 0;
-       }
-}
-
-/*
- * free a safe_q
- * It is assumed that the caller is within splimp().
- */
-static int
-safe_free_entry(struct safe_softc *sc, struct safe_ringentry *re)
-{
-       struct cryptop *crp;
-
-       DPRINTF(("%s()\n", __FUNCTION__));
-
-       /*
-        * Free header MCR
-        */
-       if ((re->re_dst_skb != NULL) && (re->re_src_skb != re->re_dst_skb))
-#ifdef NOTYET
-               m_freem(re->re_dst_m);
-#else
-               printk("%s,%d: SKB not supported\n", __FILE__, __LINE__);
-#endif
-
-       crp = (struct cryptop *)re->re_crp;
-       
-       re->re_desc.d_csr = 0;
-       
-       crp->crp_etype = EFAULT;
-       crypto_done(crp);
-       return(0);
-}
-
-/*
- * Routine to reset the chip and clean up.
- * It is assumed that the caller is in splimp()
- */
-static void
-safe_totalreset(struct safe_softc *sc)
-{
-       DPRINTF(("%s()\n", __FUNCTION__));
-
-       safe_reset_board(sc);
-       safe_init_board(sc);
-       safe_cleanchip(sc);
-}
-
-/*
- * Is the operand suitable aligned for direct DMA.  Each
- * segment must be aligned on a 32-bit boundary and all
- * but the last segment must be a multiple of 4 bytes.
- */
-static int
-safe_dmamap_aligned(struct safe_softc *sc, const struct safe_operand *op)
-{
-       int i;
-
-       DPRINTF(("%s()\n", __FUNCTION__));
-
-       for (i = 0; i < op->nsegs; i++) {
-               if (op->segs[i].ds_addr & 3)
-                       return (0);
-               if (i != (op->nsegs - 1) && (op->segs[i].ds_len & 3))
-                       return (0);
-       }
-       return (1);
-}
-
-/*
- * Is the operand suitable for direct DMA as the destination
- * of an operation.  The hardware requires that each ``particle''
- * but the last in an operation result have the same size.  We
- * fix that size at SAFE_MAX_DSIZE bytes.  This routine returns
- * 0 if some segment is not a multiple of of this size, 1 if all
- * segments are exactly this size, or 2 if segments are at worst
- * a multple of this size.
- */
-static int
-safe_dmamap_uniform(struct safe_softc *sc, const struct safe_operand *op)
-{
-       int result = 1;
-
-       DPRINTF(("%s()\n", __FUNCTION__));
-
-       if (op->nsegs > 0) {
-               int i;
-
-               for (i = 0; i < op->nsegs-1; i++) {
-                       if (op->segs[i].ds_len % sc->sc_max_dsize)
-                               return (0);
-                       if (op->segs[i].ds_len != sc->sc_max_dsize)
-                               result = 2;
-               }
-       }
-       return (result);
-}
-
-static int
-safe_kprocess(device_t dev, struct cryptkop *krp, int hint)
-{
-       struct safe_softc *sc = device_get_softc(dev);
-       struct safe_pkq *q;
-       unsigned long flags;
-
-       DPRINTF(("%s()\n", __FUNCTION__));
-
-       if (sc == NULL) {
-               krp->krp_status = EINVAL;
-               goto err;
-       }
-
-       if (krp->krp_op != CRK_MOD_EXP) {
-               krp->krp_status = EOPNOTSUPP;
-               goto err;
-       }
-
-       q = (struct safe_pkq *) kmalloc(sizeof(*q), GFP_KERNEL);
-       if (q == NULL) {
-               krp->krp_status = ENOMEM;
-               goto err;
-       }
-       memset(q, 0, sizeof(*q));
-       q->pkq_krp = krp;
-       INIT_LIST_HEAD(&q->pkq_list);
-
-       spin_lock_irqsave(&sc->sc_pkmtx, flags);
-       list_add_tail(&q->pkq_list, &sc->sc_pkq);
-       safe_kfeed(sc);
-       spin_unlock_irqrestore(&sc->sc_pkmtx, flags);
-       return (0);
-
-err:
-       crypto_kdone(krp);
-       return (0);
-}
-
-#define        SAFE_CRK_PARAM_BASE     0
-#define        SAFE_CRK_PARAM_EXP      1
-#define        SAFE_CRK_PARAM_MOD      2
-
-static int
-safe_kstart(struct safe_softc *sc)
-{
-       struct cryptkop *krp = sc->sc_pkq_cur->pkq_krp;
-       int exp_bits, mod_bits, base_bits;
-       u_int32_t op, a_off, b_off, c_off, d_off;
-
-       DPRINTF(("%s()\n", __FUNCTION__));
-
-       if (krp->krp_iparams < 3 || krp->krp_oparams != 1) {
-               krp->krp_status = EINVAL;
-               return (1);
-       }
-
-       base_bits = safe_ksigbits(sc, &krp->krp_param[SAFE_CRK_PARAM_BASE]);
-       if (base_bits > 2048)
-               goto too_big;
-       if (base_bits <= 0)             /* 5. base not zero */
-               goto too_small;
-
-       exp_bits = safe_ksigbits(sc, &krp->krp_param[SAFE_CRK_PARAM_EXP]);
-       if (exp_bits > 2048)
-               goto too_big;
-       if (exp_bits <= 0)              /* 1. exponent word length > 0 */
-               goto too_small;         /* 4. exponent not zero */
-
-       mod_bits = safe_ksigbits(sc, &krp->krp_param[SAFE_CRK_PARAM_MOD]);
-       if (mod_bits > 2048)
-               goto too_big;
-       if (mod_bits <= 32)             /* 2. modulus word length > 1 */
-               goto too_small;         /* 8. MSW of modulus != zero */
-       if (mod_bits < exp_bits)        /* 3 modulus len >= exponent len */
-               goto too_small;
-       if ((krp->krp_param[SAFE_CRK_PARAM_MOD].crp_p[0] & 1) == 0)
-               goto bad_domain;        /* 6. modulus is odd */
-       if (mod_bits > krp->krp_param[krp->krp_iparams].crp_nbits)
-               goto too_small;         /* make sure result will fit */
-
-       /* 7. modulus > base */
-       if (mod_bits < base_bits)
-               goto too_small;
-       if (mod_bits == base_bits) {
-               u_int8_t *basep, *modp;
-               int i;
-
-               basep = krp->krp_param[SAFE_CRK_PARAM_BASE].crp_p +
-                   ((base_bits + 7) / 8) - 1;
-               modp = krp->krp_param[SAFE_CRK_PARAM_MOD].crp_p +
-                   ((mod_bits + 7) / 8) - 1;
-               
-               for (i = 0; i < (mod_bits + 7) / 8; i++, basep--, modp--) {
-                       if (*modp < *basep)
-                               goto too_small;
-                       if (*modp > *basep)
-                               break;
-               }
-       }
-
-       /* And on the 9th step, he rested. */
-
-       WRITE_REG(sc, SAFE_PK_A_LEN, (exp_bits + 31) / 32);
-       WRITE_REG(sc, SAFE_PK_B_LEN, (mod_bits + 31) / 32);
-       if (mod_bits > 1024) {
-               op = SAFE_PK_FUNC_EXP4;
-               a_off = 0x000;
-               b_off = 0x100;
-               c_off = 0x200;
-               d_off = 0x300;
-       } else {
-               op = SAFE_PK_FUNC_EXP16;
-               a_off = 0x000;
-               b_off = 0x080;
-               c_off = 0x100;
-               d_off = 0x180;
-       }
-       sc->sc_pk_reslen = b_off - a_off;
-       sc->sc_pk_resoff = d_off;
-
-       /* A is exponent, B is modulus, C is base, D is result */
-       safe_kload_reg(sc, a_off, b_off - a_off,
-           &krp->krp_param[SAFE_CRK_PARAM_EXP]);
-       WRITE_REG(sc, SAFE_PK_A_ADDR, a_off >> 2);
-       safe_kload_reg(sc, b_off, b_off - a_off,
-           &krp->krp_param[SAFE_CRK_PARAM_MOD]);
-       WRITE_REG(sc, SAFE_PK_B_ADDR, b_off >> 2);
-       safe_kload_reg(sc, c_off, b_off - a_off,
-           &krp->krp_param[SAFE_CRK_PARAM_BASE]);
-       WRITE_REG(sc, SAFE_PK_C_ADDR, c_off >> 2);
-       WRITE_REG(sc, SAFE_PK_D_ADDR, d_off >> 2);
-
-       WRITE_REG(sc, SAFE_PK_FUNC, op | SAFE_PK_FUNC_RUN);
-
-       return (0);
-
-too_big:
-       krp->krp_status = E2BIG;
-       return (1);
-too_small:
-       krp->krp_status = ERANGE;
-       return (1);
-bad_domain:
-       krp->krp_status = EDOM;
-       return (1);
-}
-
-static int
-safe_ksigbits(struct safe_softc *sc, struct crparam *cr)
-{
-       u_int plen = (cr->crp_nbits + 7) / 8;
-       int i, sig = plen * 8;
-       u_int8_t c, *p = cr->crp_p;
-
-       DPRINTF(("%s()\n", __FUNCTION__));
-
-       for (i = plen - 1; i >= 0; i--) {
-               c = p[i];
-               if (c != 0) {
-                       while ((c & 0x80) == 0) {
-                               sig--;
-                               c <<= 1;
-                       }
-                       break;
-               }
-               sig -= 8;
-       }
-       return (sig);
-}
-
-static void
-safe_kfeed(struct safe_softc *sc)
-{
-       struct safe_pkq *q, *tmp;
-
-       DPRINTF(("%s()\n", __FUNCTION__));
-
-       if (list_empty(&sc->sc_pkq) && sc->sc_pkq_cur == NULL)
-               return;
-       if (sc->sc_pkq_cur != NULL)
-               return;
-       list_for_each_entry_safe(q, tmp, &sc->sc_pkq, pkq_list) {
-               sc->sc_pkq_cur = q;
-               list_del(&q->pkq_list);
-               if (safe_kstart(sc) != 0) {
-                       crypto_kdone(q->pkq_krp);
-                       kfree(q);
-                       sc->sc_pkq_cur = NULL;
-               } else {
-                       /* op started, start polling */
-                       mod_timer(&sc->sc_pkto, jiffies + 1);
-                       break;
-               }
-       }
-}
-
-static void
-safe_kpoll(unsigned long arg)
-{
-       struct safe_softc *sc = NULL;
-       struct safe_pkq *q;
-       struct crparam *res;
-       int i;
-       u_int32_t buf[64];
-       unsigned long flags;
-
-       DPRINTF(("%s()\n", __FUNCTION__));
-
-       if (arg >= SAFE_MAX_CHIPS)
-               return;
-       sc = safe_chip_idx[arg];
-       if (!sc) {
-               DPRINTF(("%s() - bad callback\n", __FUNCTION__));
-               return;
-       }
-
-       spin_lock_irqsave(&sc->sc_pkmtx, flags);
-       if (sc->sc_pkq_cur == NULL)
-               goto out;
-       if (READ_REG(sc, SAFE_PK_FUNC) & SAFE_PK_FUNC_RUN) {
-               /* still running, check back later */
-               mod_timer(&sc->sc_pkto, jiffies + 1);
-               goto out;
-       }
-
-       q = sc->sc_pkq_cur;
-       res = &q->pkq_krp->krp_param[q->pkq_krp->krp_iparams];
-       bzero(buf, sizeof(buf));
-       bzero(res->crp_p, (res->crp_nbits + 7) / 8);
-       for (i = 0; i < sc->sc_pk_reslen >> 2; i++)
-               buf[i] = le32_to_cpu(READ_REG(sc, SAFE_PK_RAM_START +
-                   sc->sc_pk_resoff + (i << 2)));
-       bcopy(buf, res->crp_p, (res->crp_nbits + 7) / 8);
-       /*
-        * reduce the bits that need copying if possible
-        */
-       res->crp_nbits = min(res->crp_nbits,sc->sc_pk_reslen * 8);
-       res->crp_nbits = safe_ksigbits(sc, res);
-
-       for (i = SAFE_PK_RAM_START; i < SAFE_PK_RAM_END; i += 4)
-               WRITE_REG(sc, i, 0);
-
-       crypto_kdone(q->pkq_krp);
-       kfree(q);
-       sc->sc_pkq_cur = NULL;
-
-       safe_kfeed(sc);
-out:
-       spin_unlock_irqrestore(&sc->sc_pkmtx, flags);
-}
-
-static void
-safe_kload_reg(struct safe_softc *sc, u_int32_t off, u_int32_t len,
-    struct crparam *n)
-{
-       u_int32_t buf[64], i;
-
-       DPRINTF(("%s()\n", __FUNCTION__));
-
-       bzero(buf, sizeof(buf));
-       bcopy(n->crp_p, buf, (n->crp_nbits + 7) / 8);
-
-       for (i = 0; i < len >> 2; i++)
-               WRITE_REG(sc, SAFE_PK_RAM_START + off + (i << 2),
-                   cpu_to_le32(buf[i]));
-}
-
-#ifdef SAFE_DEBUG
-static void
-safe_dump_dmastatus(struct safe_softc *sc, const char *tag)
-{
-       printf("%s: ENDIAN 0x%x SRC 0x%x DST 0x%x STAT 0x%x\n"
-               , tag
-               , READ_REG(sc, SAFE_DMA_ENDIAN)
-               , READ_REG(sc, SAFE_DMA_SRCADDR)
-               , READ_REG(sc, SAFE_DMA_DSTADDR)
-               , READ_REG(sc, SAFE_DMA_STAT)
-       );
-}
-
-static void
-safe_dump_intrstate(struct safe_softc *sc, const char *tag)
-{
-       printf("%s: HI_CFG 0x%x HI_MASK 0x%x HI_DESC_CNT 0x%x HU_STAT 0x%x HM_STAT 0x%x\n"
-               , tag
-               , READ_REG(sc, SAFE_HI_CFG)
-               , READ_REG(sc, SAFE_HI_MASK)
-               , READ_REG(sc, SAFE_HI_DESC_CNT)
-               , READ_REG(sc, SAFE_HU_STAT)
-               , READ_REG(sc, SAFE_HM_STAT)
-       );
-}
-
-static void
-safe_dump_ringstate(struct safe_softc *sc, const char *tag)
-{
-       u_int32_t estat = READ_REG(sc, SAFE_PE_ERNGSTAT);
-
-       /* NB: assume caller has lock on ring */
-       printf("%s: ERNGSTAT %x (next %u) back %lu front %lu\n",
-               tag,
-               estat, (estat >> SAFE_PE_ERNGSTAT_NEXT_S),
-               (unsigned long)(sc->sc_back - sc->sc_ring),
-               (unsigned long)(sc->sc_front - sc->sc_ring));
-}
-
-static void
-safe_dump_request(struct safe_softc *sc, const char* tag, struct safe_ringentry *re)
-{
-       int ix, nsegs;
-
-       ix = re - sc->sc_ring;
-       printf("%s: %p (%u): csr %x src %x dst %x sa %x len %x\n"
-               , tag
-               , re, ix
-               , re->re_desc.d_csr
-               , re->re_desc.d_src
-               , re->re_desc.d_dst
-               , re->re_desc.d_sa
-               , re->re_desc.d_len
-       );
-       if (re->re_src.nsegs > 1) {
-               ix = (re->re_desc.d_src - sc->sc_spalloc.dma_paddr) /
-                       sizeof(struct safe_pdesc);
-               for (nsegs = re->re_src.nsegs; nsegs; nsegs--) {
-                       printf(" spd[%u] %p: %p size %u flags %x"
-                               , ix, &sc->sc_spring[ix]
-                               , (caddr_t)(uintptr_t) sc->sc_spring[ix].pd_addr
-                               , sc->sc_spring[ix].pd_size
-                               , sc->sc_spring[ix].pd_flags
-                       );
-                       if (sc->sc_spring[ix].pd_size == 0)
-                               printf(" (zero!)");
-                       printf("\n");
-                       if (++ix == SAFE_TOTAL_SPART)
-                               ix = 0;
-               }
-       }
-       if (re->re_dst.nsegs > 1) {
-               ix = (re->re_desc.d_dst - sc->sc_dpalloc.dma_paddr) /
-                       sizeof(struct safe_pdesc);
-               for (nsegs = re->re_dst.nsegs; nsegs; nsegs--) {
-                       printf(" dpd[%u] %p: %p flags %x\n"
-                               , ix, &sc->sc_dpring[ix]
-                               , (caddr_t)(uintptr_t) sc->sc_dpring[ix].pd_addr
-                               , sc->sc_dpring[ix].pd_flags
-                       );
-                       if (++ix == SAFE_TOTAL_DPART)
-                               ix = 0;
-               }
-       }
-       printf("sa: cmd0 %08x cmd1 %08x staterec %x\n",
-               re->re_sa.sa_cmd0, re->re_sa.sa_cmd1, re->re_sa.sa_staterec);
-       printf("sa: key %x %x %x %x %x %x %x %x\n"
-               , re->re_sa.sa_key[0]
-               , re->re_sa.sa_key[1]
-               , re->re_sa.sa_key[2]
-               , re->re_sa.sa_key[3]
-               , re->re_sa.sa_key[4]
-               , re->re_sa.sa_key[5]
-               , re->re_sa.sa_key[6]
-               , re->re_sa.sa_key[7]
-       );
-       printf("sa: indigest %x %x %x %x %x\n"
-               , re->re_sa.sa_indigest[0]
-               , re->re_sa.sa_indigest[1]
-               , re->re_sa.sa_indigest[2]
-               , re->re_sa.sa_indigest[3]
-               , re->re_sa.sa_indigest[4]
-       );
-       printf("sa: outdigest %x %x %x %x %x\n"
-               , re->re_sa.sa_outdigest[0]
-               , re->re_sa.sa_outdigest[1]
-               , re->re_sa.sa_outdigest[2]
-               , re->re_sa.sa_outdigest[3]
-               , re->re_sa.sa_outdigest[4]
-       );
-       printf("sr: iv %x %x %x %x\n"
-               , re->re_sastate.sa_saved_iv[0]
-               , re->re_sastate.sa_saved_iv[1]
-               , re->re_sastate.sa_saved_iv[2]
-               , re->re_sastate.sa_saved_iv[3]
-       );
-       printf("sr: hashbc %u indigest %x %x %x %x %x\n"
-               , re->re_sastate.sa_saved_hashbc
-               , re->re_sastate.sa_saved_indigest[0]
-               , re->re_sastate.sa_saved_indigest[1]
-               , re->re_sastate.sa_saved_indigest[2]
-               , re->re_sastate.sa_saved_indigest[3]
-               , re->re_sastate.sa_saved_indigest[4]
-       );
-}
-
-static void
-safe_dump_ring(struct safe_softc *sc, const char *tag)
-{
-       unsigned long flags;
-
-       spin_lock_irqsave(&sc->sc_ringmtx, flags);
-       printf("\nSafeNet Ring State:\n");
-       safe_dump_intrstate(sc, tag);
-       safe_dump_dmastatus(sc, tag);
-       safe_dump_ringstate(sc, tag);
-       if (sc->sc_nqchip) {
-               struct safe_ringentry *re = sc->sc_back;
-               do {
-                       safe_dump_request(sc, tag, re);
-                       if (++re == sc->sc_ringtop)
-                               re = sc->sc_ring;
-               } while (re != sc->sc_front);
-       }
-       spin_unlock_irqrestore(&sc->sc_ringmtx, flags);
-}
-#endif /* SAFE_DEBUG */
-
-
-static int safe_probe(struct pci_dev *dev, const struct pci_device_id *ent)
-{
-       struct safe_softc *sc = NULL;
-       u32 mem_start, mem_len, cmd;
-       int i, rc, devinfo;
-       dma_addr_t raddr;
-       static int num_chips = 0;
-
-       DPRINTF(("%s()\n", __FUNCTION__));
-
-       if (pci_enable_device(dev) < 0)
-               return(-ENODEV);
-
-       if (!dev->irq) {
-               printk("safe: found device with no IRQ assigned. check BIOS settings!");
-               pci_disable_device(dev);
-               return(-ENODEV);
-       }
-
-       if (pci_set_mwi(dev)) {
-               printk("safe: pci_set_mwi failed!");
-               return(-ENODEV);
-       }
-
-       sc = (struct safe_softc *) kmalloc(sizeof(*sc), GFP_KERNEL);
-       if (!sc)
-               return(-ENOMEM);
-       memset(sc, 0, sizeof(*sc));
-
-       softc_device_init(sc, "safe", num_chips, safe_methods);
-
-       sc->sc_irq = -1;
-       sc->sc_cid = -1;
-       sc->sc_pcidev = dev;
-       if (num_chips < SAFE_MAX_CHIPS) {
-               safe_chip_idx[device_get_unit(sc->sc_dev)] = sc;
-               num_chips++;
-       }
-
-       INIT_LIST_HEAD(&sc->sc_pkq);
-       spin_lock_init(&sc->sc_pkmtx);
-
-       pci_set_drvdata(sc->sc_pcidev, sc);
-
-       /* we read its hardware registers as memory */
-       mem_start = pci_resource_start(sc->sc_pcidev, 0);
-       mem_len   = pci_resource_len(sc->sc_pcidev, 0);
-
-       sc->sc_base_addr = (ocf_iomem_t) ioremap(mem_start, mem_len);
-       if (!sc->sc_base_addr) {
-               device_printf(sc->sc_dev, "failed to ioremap 0x%x-0x%x\n",
-                               mem_start, mem_start + mem_len - 1);
-               goto out;
-       }
-
-       /* fix up the bus size */
-       if (pci_set_dma_mask(sc->sc_pcidev, DMA_32BIT_MASK)) {
-               device_printf(sc->sc_dev, "No usable DMA configuration, aborting.\n");
-               goto out;
-       }
-       if (pci_set_consistent_dma_mask(sc->sc_pcidev, DMA_32BIT_MASK)) {
-               device_printf(sc->sc_dev, "No usable consistent DMA configuration, aborting.\n");
-               goto out;
-       }
-
-       pci_set_master(sc->sc_pcidev);
-
-       pci_read_config_dword(sc->sc_pcidev, PCI_COMMAND, &cmd);
-
-       if (!(cmd & PCI_COMMAND_MEMORY)) {
-               device_printf(sc->sc_dev, "failed to enable memory mapping\n");
-               goto out;
-       }
-
-       if (!(cmd & PCI_COMMAND_MASTER)) {
-               device_printf(sc->sc_dev, "failed to enable bus mastering\n");
-               goto out;
-       }
-
-       rc = request_irq(dev->irq, safe_intr, IRQF_SHARED, "safe", sc);
-       if (rc) {
-               device_printf(sc->sc_dev, "failed to hook irq %d\n", sc->sc_irq);
-               goto out;
-       }
-       sc->sc_irq = dev->irq;
-
-       sc->sc_chiprev = READ_REG(sc, SAFE_DEVINFO) &
-                       (SAFE_DEVINFO_REV_MAJ | SAFE_DEVINFO_REV_MIN);
-
-       /*
-        * Allocate packet engine descriptors.
-        */
-       sc->sc_ringalloc.dma_vaddr = pci_alloc_consistent(sc->sc_pcidev,
-                       SAFE_MAX_NQUEUE * sizeof (struct safe_ringentry),
-                       &sc->sc_ringalloc.dma_paddr);
-       if (!sc->sc_ringalloc.dma_vaddr) {
-               device_printf(sc->sc_dev, "cannot allocate PE descriptor ring\n");
-               goto out;
-       }
-
-       /*
-        * Hookup the static portion of all our data structures.
-        */
-       sc->sc_ring = (struct safe_ringentry *) sc->sc_ringalloc.dma_vaddr;
-       sc->sc_ringtop = sc->sc_ring + SAFE_MAX_NQUEUE;
-       sc->sc_front = sc->sc_ring;
-       sc->sc_back = sc->sc_ring;
-       raddr = sc->sc_ringalloc.dma_paddr;
-       bzero(sc->sc_ring, SAFE_MAX_NQUEUE * sizeof(struct safe_ringentry));
-       for (i = 0; i < SAFE_MAX_NQUEUE; i++) {
-               struct safe_ringentry *re = &sc->sc_ring[i];
-
-               re->re_desc.d_sa = raddr +
-                       offsetof(struct safe_ringentry, re_sa);
-               re->re_sa.sa_staterec = raddr +
-                       offsetof(struct safe_ringentry, re_sastate);
-
-               raddr += sizeof (struct safe_ringentry);
-       }
-       spin_lock_init(&sc->sc_ringmtx);
-
-       /*
-        * Allocate scatter and gather particle descriptors.
-        */
-       sc->sc_spalloc.dma_vaddr = pci_alloc_consistent(sc->sc_pcidev,
-                       SAFE_TOTAL_SPART * sizeof (struct safe_pdesc),
-                       &sc->sc_spalloc.dma_paddr);
-       if (!sc->sc_spalloc.dma_vaddr) {
-               device_printf(sc->sc_dev, "cannot allocate source particle descriptor ring\n");
-               goto out;
-       }
-       sc->sc_spring = (struct safe_pdesc *) sc->sc_spalloc.dma_vaddr;
-       sc->sc_springtop = sc->sc_spring + SAFE_TOTAL_SPART;
-       sc->sc_spfree = sc->sc_spring;
-       bzero(sc->sc_spring, SAFE_TOTAL_SPART * sizeof(struct safe_pdesc));
-
-       sc->sc_dpalloc.dma_vaddr = pci_alloc_consistent(sc->sc_pcidev,
-                       SAFE_TOTAL_DPART * sizeof (struct safe_pdesc),
-                       &sc->sc_dpalloc.dma_paddr);
-       if (!sc->sc_dpalloc.dma_vaddr) {
-               device_printf(sc->sc_dev, "cannot allocate destination particle descriptor ring\n");
-               goto out;
-       }
-       sc->sc_dpring = (struct safe_pdesc *) sc->sc_dpalloc.dma_vaddr;
-       sc->sc_dpringtop = sc->sc_dpring + SAFE_TOTAL_DPART;
-       sc->sc_dpfree = sc->sc_dpring;
-       bzero(sc->sc_dpring, SAFE_TOTAL_DPART * sizeof(struct safe_pdesc));
-
-       sc->sc_cid = crypto_get_driverid(softc_get_device(sc), CRYPTOCAP_F_HARDWARE);
-       if (sc->sc_cid < 0) {
-               device_printf(sc->sc_dev, "could not get crypto driver id\n");
-               goto out;
-       }
-
-       printf("%s:", device_get_nameunit(sc->sc_dev));
-
-       devinfo = READ_REG(sc, SAFE_DEVINFO);
-       if (devinfo & SAFE_DEVINFO_RNG) {
-               sc->sc_flags |= SAFE_FLAGS_RNG;
-               printf(" rng");
-       }
-       if (devinfo & SAFE_DEVINFO_PKEY) {
-               printf(" key");
-               sc->sc_flags |= SAFE_FLAGS_KEY;
-               crypto_kregister(sc->sc_cid, CRK_MOD_EXP, 0);
-#if 0
-               crypto_kregister(sc->sc_cid, CRK_MOD_EXP_CRT, 0);
-#endif
-               init_timer(&sc->sc_pkto);
-               sc->sc_pkto.function = safe_kpoll;
-               sc->sc_pkto.data = (unsigned long) device_get_unit(sc->sc_dev);
-       }
-       if (devinfo & SAFE_DEVINFO_DES) {
-               printf(" des/3des");
-               crypto_register(sc->sc_cid, CRYPTO_3DES_CBC, 0, 0);
-               crypto_register(sc->sc_cid, CRYPTO_DES_CBC, 0, 0);
-       }
-       if (devinfo & SAFE_DEVINFO_AES) {
-               printf(" aes");
-               crypto_register(sc->sc_cid, CRYPTO_AES_CBC, 0, 0);
-       }
-       if (devinfo & SAFE_DEVINFO_MD5) {
-               printf(" md5");
-               crypto_register(sc->sc_cid, CRYPTO_MD5_HMAC, 0, 0);
-       }
-       if (devinfo & SAFE_DEVINFO_SHA1) {
-               printf(" sha1");
-               crypto_register(sc->sc_cid, CRYPTO_SHA1_HMAC, 0, 0);
-       }
-       printf(" null");
-       crypto_register(sc->sc_cid, CRYPTO_NULL_CBC, 0, 0);
-       crypto_register(sc->sc_cid, CRYPTO_NULL_HMAC, 0, 0);
-       /* XXX other supported algorithms */
-       printf("\n");
-
-       safe_reset_board(sc);           /* reset h/w */
-       safe_init_board(sc);            /* init h/w */
-
-#if defined(CONFIG_OCF_RANDOMHARVEST) && !defined(SAFE_NO_RNG)
-       if (sc->sc_flags & SAFE_FLAGS_RNG) {
-               safe_rng_init(sc);
-               crypto_rregister(sc->sc_cid, safe_read_random, sc);
-       }
-#endif /* SAFE_NO_RNG */
-
-       return (0);
-
-out:
-       if (sc->sc_cid >= 0)
-               crypto_unregister_all(sc->sc_cid);
-       if (sc->sc_irq != -1)
-               free_irq(sc->sc_irq, sc);
-       if (sc->sc_ringalloc.dma_vaddr)
-               pci_free_consistent(sc->sc_pcidev,
-                               SAFE_MAX_NQUEUE * sizeof (struct safe_ringentry),
-                               sc->sc_ringalloc.dma_vaddr, sc->sc_ringalloc.dma_paddr);
-       if (sc->sc_spalloc.dma_vaddr)
-               pci_free_consistent(sc->sc_pcidev,
-                               SAFE_TOTAL_DPART * sizeof (struct safe_pdesc),
-                               sc->sc_spalloc.dma_vaddr, sc->sc_spalloc.dma_paddr);
-       if (sc->sc_dpalloc.dma_vaddr)
-               pci_free_consistent(sc->sc_pcidev,
-                               SAFE_TOTAL_DPART * sizeof (struct safe_pdesc),
-                               sc->sc_dpalloc.dma_vaddr, sc->sc_dpalloc.dma_paddr);
-       kfree(sc);
-       return(-ENODEV);
-}
-
-static void safe_remove(struct pci_dev *dev)
-{
-       struct safe_softc *sc = pci_get_drvdata(dev);
-
-       DPRINTF(("%s()\n", __FUNCTION__));
-
-       /* XXX wait/abort active ops */
-
-       WRITE_REG(sc, SAFE_HI_MASK, 0);         /* disable interrupts */
-
-       del_timer_sync(&sc->sc_pkto);
-
-       crypto_unregister_all(sc->sc_cid);
-
-       safe_cleanchip(sc);
-
-       if (sc->sc_irq != -1)
-               free_irq(sc->sc_irq, sc);
-       if (sc->sc_ringalloc.dma_vaddr)
-               pci_free_consistent(sc->sc_pcidev,
-                               SAFE_MAX_NQUEUE * sizeof (struct safe_ringentry),
-                               sc->sc_ringalloc.dma_vaddr, sc->sc_ringalloc.dma_paddr);
-       if (sc->sc_spalloc.dma_vaddr)
-               pci_free_consistent(sc->sc_pcidev,
-                               SAFE_TOTAL_DPART * sizeof (struct safe_pdesc),
-                               sc->sc_spalloc.dma_vaddr, sc->sc_spalloc.dma_paddr);
-       if (sc->sc_dpalloc.dma_vaddr)
-               pci_free_consistent(sc->sc_pcidev,
-                               SAFE_TOTAL_DPART * sizeof (struct safe_pdesc),
-                               sc->sc_dpalloc.dma_vaddr, sc->sc_dpalloc.dma_paddr);
-       sc->sc_irq = -1;
-       sc->sc_ringalloc.dma_vaddr = NULL;
-       sc->sc_spalloc.dma_vaddr = NULL;
-       sc->sc_dpalloc.dma_vaddr = NULL;
-}
-
-static struct pci_device_id safe_pci_tbl[] = {
-       { PCI_VENDOR_SAFENET, PCI_PRODUCT_SAFEXCEL,
-         PCI_ANY_ID, PCI_ANY_ID, 0, 0, },
-       { },
-};
-MODULE_DEVICE_TABLE(pci, safe_pci_tbl);
-
-static struct pci_driver safe_driver = {
-       .name         = "safe",
-       .id_table     = safe_pci_tbl,
-       .probe        = safe_probe,
-       .remove       = safe_remove,
-       /* add PM stuff here one day */
-};
-
-static int __init safe_init (void)
-{
-       struct safe_softc *sc = NULL;
-       int rc;
-
-       DPRINTF(("%s(%p)\n", __FUNCTION__, safe_init));
-
-       rc = pci_register_driver(&safe_driver);
-       pci_register_driver_compat(&safe_driver, rc);
-
-       return rc;
-}
-
-static void __exit safe_exit (void)
-{
-       pci_unregister_driver(&safe_driver);
-}
-
-module_init(safe_init);
-module_exit(safe_exit);
-
-MODULE_LICENSE("BSD");
-MODULE_AUTHOR("David McCullough <david_mccullough@mcafee.com>");
-MODULE_DESCRIPTION("OCF driver for safenet PCI crypto devices");