Hifn 7955/7956 support to the hifn(4) driver.
authorHasso Tepper <hasso@dragonflybsd.org>
Tue, 4 Dec 2007 09:11:12 +0000 (09:11 +0000)
committerHasso Tepper <hasso@dragonflybsd.org>
Tue, 4 Dec 2007 09:11:12 +0000 (09:11 +0000)
Submitted-by: Andrew Atrens
Obtained-from: FreeBSD/OpenBSD

share/man/man4/hifn.4
sys/dev/crypto/hifn/hifn7751.c
sys/dev/crypto/hifn/hifn7751reg.h
sys/dev/crypto/hifn/hifn7751var.h
sys/opencrypto/cryptodev.h
sys/opencrypto/cryptosoft.c

index 5ee72fb..d751e8d 100644 (file)
@@ -1,6 +1,6 @@
 .\"    $OpenBSD: hifn.4,v 1.32 2002/09/26 07:55:40 miod Exp $
 .\"    $FreeBSD: src/share/man/man4/hifn.4,v 1.1.2.1 2002/11/21 23:57:24 sam Exp $
-.\"    $DragonFly: src/share/man/man4/hifn.4,v 1.5 2007/05/12 21:22:10 swildner Exp $
+.\"    $DragonFly: src/share/man/man4/hifn.4,v 1.6 2007/12/04 09:11:11 hasso Exp $
 .\"
 .\" Copyright (c) 2000 Theo de Raadt
 .\" All rights reserved.
 .Os
 .Sh NAME
 .Nm hifn
-.Nd Hifn 7751/7951/7811 crypto accelerator
+.Nd Hifn 7751/7951/7811/7955/7956 crypto accelerator
 .Sh SYNOPSIS
 .Cd device hifn
 .Sh DESCRIPTION
 The
 .Nm
-driver supports various cards containing the Hifn 7751, Hifn 7951, or
-Hifn 7811
+driver supports various cards containing the Hifn 7751, 7951,
+7811, 7955, and 7956
 chipsets, such as
 .Bl -tag -width namenamenamena -offset indent
 .It Invertex AEON
@@ -65,20 +65,27 @@ Supports the most IPsec sessions, with 1MB SRAM.
 See
 .Pa http://www.soekris.com/ .
 Contains a 7951 and supports symmetric and random number operations.
+.It Soekris Engineering vpn1401 and vpn1411
+See
+.Pa http://www.soekris.com/ .
+Contains a 7955 and supports symmetric and random number operations.
 .El
 .Pp
 The
 .Nm
-driver registers itself to accelerate DES, Triple-DES, ARC4, MD5,
+driver registers itself to accelerate DES, Triple-DES,
+AES (7955 and 7956 only), ARC4, MD5,
 MD5-HMAC, SHA1, and SHA1-HMAC operations for
 .Xr ipsec 4
 and
 .Xr crypto 4 .
 .Pp
-The
-.Tn Hifn 7951
+The Hifn
+.Tn 7951 ,
+.Tn 7811 ,
+.Tn 7955 ,
 and
-.Tn Hifn 7811
+.Tn 7956
 will also supply data to the kernel
 .Xr random 4
 subsystem.
@@ -95,6 +102,9 @@ This chip is basically a 7751, but with the cryptographic functions missing.
 Instead, the 9751 is only capable of doing compression.
 Since we do not currently attempt to use any of these chips to do
 compression, the 9751-based cards are not useful.
+.Pp
+Support for the 7955 and 7956 is incomplete; the asymetric crypto
+facilities are to be added and the performance is suboptimal.
 .Sh HISTORY
 The
 .Nm
index 0a03287..488f6de 100644 (file)
@@ -1,6 +1,6 @@
 /* $FreeBSD: src/sys/dev/hifn/hifn7751.c,v 1.5.2.5 2003/06/04 17:56:59 sam Exp $ */
-/* $DragonFly: src/sys/dev/crypto/hifn/hifn7751.c,v 1.13 2006/12/22 23:26:15 swildner Exp $ */
-/*     $OpenBSD: hifn7751.c,v 1.120 2002/05/17 00:33:34 deraadt Exp $  */
+/* $DragonFly: src/sys/dev/crypto/hifn/hifn7751.c,v 1.14 2007/12/04 09:11:12 hasso Exp $ */
+/* $OpenBSD: hifn7751.c,v 1.120 2002/05/17 00:33:34 deraadt Exp $      */
 
 /*
  * Invertex AEON / Hifn 7751 driver
@@ -8,6 +8,7 @@
  * Copyright (c) 1999 Theo de Raadt
  * Copyright (c) 2000-2001 Network Security Technologies, Inc.
  *                     http://www.netsec.net
+ * Copyright (c) 2003 Hifn Inc.
  *
  * This driver is based on a previous driver by Invertex, for which they
  * requested:  Please send any comments, feedback, bug-fixes, or feature
@@ -43,7 +44,7 @@
  */
 
 /*
- * Driver for the Hifn 7751 encryption processor.
+ * Driver for various Hifn encryption processors.
  */
 #include "opt_hifn.h"
 
@@ -59,6 +60,7 @@
 #include <sys/rman.h>
 #include <sys/random.h>
 #include <sys/thread2.h>
+#include <sys/uio.h>
 
 #include <vm/vm.h>
 #include <vm/pmap.h>
@@ -194,11 +196,17 @@ hifn_probe(device_t dev)
        if (pci_get_vendor(dev) == PCI_VENDOR_HIFN &&
            (pci_get_device(dev) == PCI_PRODUCT_HIFN_7751 ||
             pci_get_device(dev) == PCI_PRODUCT_HIFN_7951 ||
+            pci_get_device(dev) == PCI_PRODUCT_HIFN_7955 ||
+            pci_get_device(dev) == PCI_PRODUCT_HIFN_7956 ||
             pci_get_device(dev) == PCI_PRODUCT_HIFN_7811))
                return (0);
        if (pci_get_vendor(dev) == PCI_VENDOR_NETSEC &&
            pci_get_device(dev) == PCI_PRODUCT_NETSEC_7751)
                return (0);
+       if (pci_get_vendor(dev) == PCI_VENDOR_HIFN) {
+               device_printf(dev,"device id = 0x%x\n", pci_get_device(dev) );
+               return (0);
+       }
        return (ENXIO);
 }
 
@@ -220,6 +228,8 @@ hifn_partname(struct hifn_softc *sc)
                case PCI_PRODUCT_HIFN_7751:     return "Hifn 7751";
                case PCI_PRODUCT_HIFN_7811:     return "Hifn 7811";
                case PCI_PRODUCT_HIFN_7951:     return "Hifn 7951";
+               case PCI_PRODUCT_HIFN_7955:     return "Hifn 7955";
+               case PCI_PRODUCT_HIFN_7956:     return "Hifn 7956";
                }
                return "Hifn unknown-part";
        case PCI_VENDOR_INVERTEX:
@@ -244,6 +254,84 @@ default_harvest(struct rndtest_state *rsp, void *buf, u_int count)
                add_true_randomness(*p++);
 }
 
+static u_int
+checkmaxmin(device_t dev, const char *what, u_int v, u_int min, u_int max)
+{
+       if (v > max) {
+               device_printf(dev, "Warning, %s %u out of range, "
+                   "using max %u\n", what, v, max);
+               v = max;
+       } else if (v < min) {
+               device_printf(dev, "Warning, %s %u out of range, "
+                    "using min %u\n", what, v, min);
+               v = min;
+       }
+       return v;
+}
+
+/*
+ * Select PLL configuration for 795x parts.  This is complicated in
+ * that we cannot determine the optimal parameters without user input.
+ * The reference clock is derived from an external clock through a
+ * multiplier.  The external clock is either the host bus (i.e. PCI)
+ * or an external clock generator.  When using the PCI bus we assume
+ * the clock is either 33 or 66 MHz; for an external source we cannot
+ * tell the speed.
+ *
+ * PLL configuration is done with a string: "pci" for PCI bus, or "ext"
+ * for an external source, followed by the frequency.  We calculate
+ * the appropriate multiplier and PLL register contents accordingly.
+ * When no configuration is given we default to "pci66" since that
+ * always will allow the card to work.  If a card is using the PCI
+ * bus clock and in a 33MHz slot then it will be operating at half
+ * speed until the correct information is provided.
+ */
+static void
+hifn_getpllconfig(device_t dev, u_int *pll)
+{
+       char *pllspec;
+       u_int freq, mul, fl, fh;
+       u_int32_t pllconfig;
+       char *nxt;
+
+       if (resource_string_value("hifn", device_get_unit(dev),
+            "pllconfig", &pllspec))
+               pllspec = "pci66";
+       fl = 33, fh = 66;
+       pllconfig = 0;
+       if (strncmp(pllspec, "ext", 3) == 0) {
+               pllspec += 3;
+               pllconfig |= HIFN_PLL_REF_SEL;
+               switch (pci_get_device(dev)) {
+               case PCI_PRODUCT_HIFN_7955:
+               case PCI_PRODUCT_HIFN_7956:
+                       fl = 20, fh = 100;
+                       break;
+#ifdef notyet
+               case PCI_PRODUCT_HIFN_7954:
+                       fl = 20, fh = 66;
+                       break;
+#endif
+               }
+       } else if (strncmp(pllspec, "pci", 3) == 0)
+               pllspec += 3;
+       freq = strtoul(pllspec, &nxt, 10);
+       if (nxt == pllspec)
+               freq = 66;
+       else
+               freq = checkmaxmin(dev, "frequency", freq, fl, fh);
+       /*
+        * Calculate multiplier.  We target a Fck of 266 MHz,
+        * allowing only even values, possibly rounded down.
+        * Multipliers > 8 must set the charge pump current.
+        */
+       mul = checkmaxmin(dev, "PLL divisor", (266 / freq) &~ 1, 2, 12);
+       pllconfig |= (mul / 2 - 1) << HIFN_PLL_ND_SHIFT;
+       if (mul > 8)
+               pllconfig |= HIFN_PLL_IS;
+       *pll = pllconfig;
+}
+
 /*
  * Attach an interface that successfully probed.
  */
@@ -264,11 +352,13 @@ hifn_attach(device_t dev)
        /* XXX handle power management */
 
        /*
-        * The 7951 has a random number generator and
+        * The 7951 and 795x have a random number generator and
         * public key support; note this.
         */
        if (pci_get_vendor(dev) == PCI_VENDOR_HIFN &&
-           pci_get_device(dev) == PCI_PRODUCT_HIFN_7951)
+           (pci_get_device(dev) == PCI_PRODUCT_HIFN_7951 ||
+            pci_get_device(dev) == PCI_PRODUCT_HIFN_7955 ||
+            pci_get_device(dev) == PCI_PRODUCT_HIFN_7956))
                sc->sc_flags = HIFN_HAS_RNG | HIFN_HAS_PUBLIC;
        /*
         * The 7811 has a random number generator and
@@ -278,6 +368,21 @@ hifn_attach(device_t dev)
            pci_get_device(dev) == PCI_PRODUCT_HIFN_7811)
                sc->sc_flags |= HIFN_IS_7811 | HIFN_HAS_RNG;
 
+       /*
+        * The 795x parts support AES.
+        */
+       if (pci_get_vendor(dev) == PCI_VENDOR_HIFN &&
+           (pci_get_device(dev) == PCI_PRODUCT_HIFN_7955 ||
+            pci_get_device(dev) == PCI_PRODUCT_HIFN_7956)) {
+               sc->sc_flags |= HIFN_IS_7956 | HIFN_HAS_AES;
+               /*
+                * Select PLL configuration.  This depends on the
+                * bus and board design and must be manually configured
+                * if the default setting is unacceptable.
+                */
+               hifn_getpllconfig(dev, &sc->sc_pllconfig);
+       }
+
        /*
         * Configure support for memory-mapped access to
         * registers and for DMA operations.
@@ -368,10 +473,10 @@ hifn_attach(device_t dev)
        sc->sc_dma = (struct hifn_dma *)kva;
        bzero(sc->sc_dma, sizeof(*sc->sc_dma));
 
-       KASSERT(sc->sc_st0 != NULL, ("hifn_attach: null bar0 tag!"));
-       KASSERT(sc->sc_sh0 != NULL, ("hifn_attach: null bar0 handle!"));
-       KASSERT(sc->sc_st1 != NULL, ("hifn_attach: null bar1 tag!"));
-       KASSERT(sc->sc_sh1 != NULL, ("hifn_attach: null bar1 handle!"));
+       KASSERT(sc->sc_st0 != 0, ("hifn_attach: null bar0 tag!"));
+       KASSERT(sc->sc_sh0 != 0, ("hifn_attach: null bar0 handle!"));
+       KASSERT(sc->sc_st1 != 0, ("hifn_attach: null bar1 tag!"));
+       KASSERT(sc->sc_sh1 != 0, ("hifn_attach: null bar1 handle!"));
 
        /*
         * Reset the board and do the ``secret handshake''
@@ -392,7 +497,10 @@ hifn_attach(device_t dev)
        hifn_init_dma(sc);
        hifn_init_pci_registers(sc);
 
-       if (hifn_ramtype(sc))
+       /* XXX can't dynamically determine ram type for 795x; force dram */
+       if (sc->sc_flags & HIFN_IS_7956)
+               sc->sc_drammodel = 1;
+       else if (hifn_ramtype(sc))
                goto fail_mem;
 
        if (sc->sc_drammodel == 0)
@@ -423,7 +531,7 @@ hifn_attach(device_t dev)
         * NB: Network code assumes we are blocked with splimp()
         *     so make sure the IRQ is marked appropriately.
         */
-       if (bus_setup_intr(dev, sc->sc_irq, 0,
+       if (bus_setup_intr(dev, sc->sc_irq, INTR_FAST,
                           hifn_intr, sc,
                           &sc->sc_intrhand, NULL)) {
                device_printf(dev, "could not setup interrupt\n");
@@ -449,6 +557,13 @@ hifn_attach(device_t dev)
                rseg, rbase, sc->sc_drammodel ? 'd' : 's',
                sc->sc_maxses);
 
+       if (sc->sc_flags & HIFN_IS_7956)
+               kprintf(", pll=0x%x<%s clk, %ux mult>",
+                       sc->sc_pllconfig,
+                       sc->sc_pllconfig & HIFN_PLL_REF_SEL ? "ext" : "pci",
+                       2 + 2*((sc->sc_pllconfig & HIFN_PLL_ND) >> 11));
+       kprintf("\n");
+
        sc->sc_cid = crypto_get_driverid(0);
        if (sc->sc_cid < 0) {
                device_printf(dev, "could not get crypto driver id\n");
@@ -465,6 +580,10 @@ hifn_attach(device_t dev)
                    hifn_newsession, hifn_freesession, hifn_process, sc);
                crypto_register(sc->sc_cid, CRYPTO_ARC4, 0, 0,
                    hifn_newsession, hifn_freesession, hifn_process, sc);
+               if (sc->sc_flags & HIFN_HAS_AES)
+                       crypto_register(sc->sc_cid, CRYPTO_AES_CBC,  0, 0,
+                           hifn_newsession, hifn_freesession,
+                           hifn_process, sc);
                /*FALLTHROUGH*/
        case HIFN_PUSTAT_ENA_1:
                crypto_register(sc->sc_cid, CRYPTO_MD5, 0, 0,
@@ -524,6 +643,9 @@ hifn_detach(device_t dev)
 
        KASSERT(sc != NULL, ("hifn_detach: null software carrier!"));
 
+       /* disable interrupts */
+       WRITE_REG_1(sc, HIFN_1_DMA_IER, 0);
+
        crit_enter();
        /*XXX other resources */
        callout_stop(&sc->sc_tickto);
@@ -874,6 +996,16 @@ static struct pci2id pci2id[] = {
                PCI_PRODUCT_HIFN_7951,
                { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
                  0x00, 0x00, 0x00, 0x00, 0x00 }
+       }, {
+               PCI_VENDOR_HIFN,
+               PCI_PRODUCT_HIFN_7955,
+               { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+                 0x00, 0x00, 0x00, 0x00, 0x00 }
+       }, {
+               PCI_VENDOR_HIFN,
+               PCI_PRODUCT_HIFN_7956,
+               { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+                 0x00, 0x00, 0x00, 0x00, 0x00 }
        }, {
                PCI_VENDOR_NETSEC,
                PCI_PRODUCT_NETSEC_7751,
@@ -1055,10 +1187,35 @@ hifn_init_pci_registers(struct hifn_softc *sc)
        sc->sc_dmaier &= ~HIFN_DMAIER_C_WAIT;
        WRITE_REG_1(sc, HIFN_1_DMA_IER, sc->sc_dmaier);
 
-       WRITE_REG_0(sc, HIFN_0_PUCNFG, HIFN_PUCNFG_COMPSING |
-           HIFN_PUCNFG_DRFR_128 | HIFN_PUCNFG_TCALLPHASES |
-           HIFN_PUCNFG_TCDRVTOTEM | HIFN_PUCNFG_BUS32 |
-           (sc->sc_drammodel ? HIFN_PUCNFG_DRAM : HIFN_PUCNFG_SRAM));
+       if (sc->sc_flags & HIFN_IS_7956) {
+               u_int32_t pll;
+
+               WRITE_REG_0(sc, HIFN_0_PUCNFG, HIFN_PUCNFG_COMPSING |
+                   HIFN_PUCNFG_TCALLPHASES |
+                   HIFN_PUCNFG_TCDRVTOTEM | HIFN_PUCNFG_BUS32);
+
+               /* turn off the clocks and insure bypass is set */
+               pll = READ_REG_1(sc, HIFN_1_PLL);
+               pll = (pll &~ (HIFN_PLL_PK_CLK_SEL | HIFN_PLL_PE_CLK_SEL))
+                   | HIFN_PLL_BP;
+               WRITE_REG_1(sc, HIFN_1_PLL, pll);
+               DELAY(10*1000);         /* 10ms */
+               /* change configuration */
+               pll = (pll &~ HIFN_PLL_CONFIG) | sc->sc_pllconfig;
+               WRITE_REG_1(sc, HIFN_1_PLL, pll);
+               DELAY(10*1000);         /* 10ms */
+               /* disable bypass */
+               pll &= ~HIFN_PLL_BP;
+               WRITE_REG_1(sc, HIFN_1_PLL, pll);
+               /* enable clocks with new configuration */
+               pll |= HIFN_PLL_PK_CLK_SEL | HIFN_PLL_PE_CLK_SEL;
+               WRITE_REG_1(sc, HIFN_1_PLL, pll);
+       } else {
+               WRITE_REG_0(sc, HIFN_0_PUCNFG, HIFN_PUCNFG_COMPSING |
+                   HIFN_PUCNFG_DRFR_128 | HIFN_PUCNFG_TCALLPHASES |
+                   HIFN_PUCNFG_TCDRVTOTEM | HIFN_PUCNFG_BUS32 |
+                   (sc->sc_drammodel ? HIFN_PUCNFG_DRAM : HIFN_PUCNFG_SRAM));
+       }
 
        WRITE_REG_0(sc, HIFN_0_PUISR, HIFN_PUISR_DSTOVER);
        WRITE_REG_1(sc, HIFN_1_DMA_CNFG, HIFN_DMACNFG_MSTRESET |
@@ -1087,8 +1244,14 @@ hifn_sessions(struct hifn_softc *sc)
                        ctxsize = 128;
                else
                        ctxsize = 512;
-               sc->sc_maxses = 1 +
-                   ((sc->sc_ramsize - 32768) / ctxsize);
+               /*
+                * 7955/7956 has internal context memory of 32K
+                */
+               if (sc->sc_flags & HIFN_IS_7956)
+                       sc->sc_maxses = 32768 / ctxsize;
+               else
+                       sc->sc_maxses = 1 +
+                           ((sc->sc_ramsize - 32768) / ctxsize);
        } else
                sc->sc_maxses = sc->sc_ramsize / 16384;
 
@@ -1174,10 +1337,17 @@ static int
 hifn_dramsize(struct hifn_softc *sc)
 {
        u_int32_t cnfg;
-
-       cnfg = READ_REG_0(sc, HIFN_0_PUCNFG) &
-           HIFN_PUCNFG_DRAMMASK;
-       sc->sc_ramsize = 1 << ((cnfg >> 13) + 18);
+       
+       if (sc->sc_flags & HIFN_IS_7956) {
+               /*
+                * 7955/7956 have a fixed internal ram of only 32K.
+                */
+               sc->sc_ramsize = 32768;
+       } else {
+               cnfg = READ_REG_0(sc, HIFN_0_PUCNFG) &
+                   HIFN_PUCNFG_DRAMMASK;
+               sc->sc_ramsize = 1 << ((cnfg >> 13) + 18);
+       }
        return (0);
 }
 
@@ -1393,7 +1563,7 @@ hifn_write_command(struct hifn_command *cmd, u_int8_t *buf)
        hifn_base_command_t *base_cmd;
        hifn_mac_command_t *mac_cmd;
        hifn_crypt_command_t *cry_cmd;
-       int using_mac, using_crypt, len;
+       int using_mac, using_crypt, len, ivlen;
        u_int32_t dlen, slen;
 
        buf_pos = buf;
@@ -1411,7 +1581,11 @@ hifn_write_command(struct hifn_command *cmd, u_int8_t *buf)
        base_cmd->total_dest_count = htole16(dlen & HIFN_BASE_CMD_LENMASK_LO);
        dlen >>= 16;
        slen >>= 16;
+#if 0
        base_cmd->session_num = htole16(cmd->session_num |
+#else
+       base_cmd->session_num = htole16(
+#endif
            ((slen << HIFN_BASE_CMD_SRCLEN_S) & HIFN_BASE_CMD_SRCLEN_M) |
            ((dlen << HIFN_BASE_CMD_DSTLEN_S) & HIFN_BASE_CMD_DSTLEN_M));
        buf_pos += sizeof(hifn_base_command_t);
@@ -1453,7 +1627,7 @@ hifn_write_command(struct hifn_command *cmd, u_int8_t *buf)
                        break;
                case HIFN_CRYPT_CMD_ALG_DES:
                        bcopy(cmd->ck, buf_pos, HIFN_DES_KEY_LENGTH);
-                       buf_pos += cmd->cklen;
+                       buf_pos += HIFN_DES_KEY_LENGTH;
                        break;
                case HIFN_CRYPT_CMD_ALG_RC4:
                        len = 256;
@@ -1468,12 +1642,28 @@ hifn_write_command(struct hifn_command *cmd, u_int8_t *buf)
                        bzero(buf_pos, 4);
                        buf_pos += 4;
                        break;
+               case HIFN_CRYPT_CMD_ALG_AES:
+                       /*
+                        * AES keys are variable 128, 192 and
+                        * 256 bits (16, 24 and 32 bytes).
+                        */
+                       bcopy(cmd->ck, buf_pos, cmd->cklen);
+                       buf_pos += cmd->cklen;
+                       break;
                }
        }
 
        if (using_crypt && cmd->cry_masks & HIFN_CRYPT_CMD_NEW_IV) {
-               bcopy(cmd->iv, buf_pos, HIFN_IV_LENGTH);
-               buf_pos += HIFN_IV_LENGTH;
+               switch (cmd->cry_masks & HIFN_CRYPT_CMD_ALG_MASK) {
+               case HIFN_CRYPT_CMD_ALG_AES:
+                       ivlen = HIFN_AES_IV_LENGTH;
+                       break;
+               default:
+                       ivlen = HIFN_IV_LENGTH;
+                       break;
+               }
+               bcopy(cmd->iv, buf_pos, ivlen);
+               buf_pos += ivlen;
        }
 
        if ((cmd->base_masks & (HIFN_BASE_CMD_MAC|HIFN_BASE_CMD_CRYPT)) == 0) {
@@ -1658,6 +1848,7 @@ hifn_crypto(
                        goto err_srcmap1;
                }
        } else if (crp->crp_flags & CRYPTO_F_IOV) {
+               cmd->src_io->uio_segflg = UIO_USERSPACE;
                if (bus_dmamap_load_uio(sc->sc_dmat, cmd->src_map,
                    cmd->src_io, hifn_op_cb, &cmd->src, BUS_DMA_NOWAIT)) {
                        hifnstats.hst_nomem_load++;
@@ -1769,6 +1960,7 @@ hifn_crypto(
                                goto err_dstmap1;
                        }
                } else if (crp->crp_flags & CRYPTO_F_IOV) {
+                       cmd->dst_io->uio_segflg |= UIO_USERSPACE;
                        if (bus_dmamap_load_uio(sc->sc_dmat, cmd->dst_map,
                            cmd->dst_io, hifn_op_cb, &cmd->dst, BUS_DMA_NOWAIT)) {
                                hifnstats.hst_nomem_load++;
@@ -1979,9 +2171,15 @@ hifn_intr(void *arg)
        u_int32_t dmacsr, restart;
        int i, u;
 
-       dma = sc->sc_dma;
-
        dmacsr = READ_REG_1(sc, HIFN_1_DMA_CSR);
+       
+       /* Nothing in the DMA unit interrupted */
+       if ((dmacsr & sc->sc_dmaier) == 0) {
+               hifnstats.hst_noirq++;
+               return;
+       }
+
+       dma = sc->sc_dma;
 
 #ifdef HIFN_DEBUG
        if (hifn_debug) {
@@ -1994,12 +2192,6 @@ hifn_intr(void *arg)
        }
 #endif
 
-       /* Nothing in the DMA unit interrupted */
-       if ((dmacsr & sc->sc_dmaier) == 0) {
-               hifnstats.hst_noirq++;
-               return;
-       }
-
        WRITE_REG_1(sc, HIFN_1_DMA_CSR, dmacsr & sc->sc_dmaier);
 
        if ((sc->sc_flags & HIFN_HAS_PUBLIC) &&
@@ -2130,17 +2322,44 @@ hifn_newsession(void *arg, u_int32_t *sidp, struct cryptoini *cri)
 {
        struct cryptoini *c;
        struct hifn_softc *sc = arg;
-       int i, mac = 0, cry = 0;
+       int mac = 0, cry = 0, sesn;
+       struct hifn_session *ses = NULL;
 
        KASSERT(sc != NULL, ("hifn_newsession: null softc"));
        if (sidp == NULL || cri == NULL || sc == NULL)
                return (EINVAL);
 
-       for (i = 0; i < sc->sc_maxses; i++)
-               if (sc->sc_sessions[i].hs_state == HS_STATE_FREE)
-                       break;
-       if (i == sc->sc_maxses)
-               return (ENOMEM);
+       if (sc->sc_sessions == NULL) {
+               ses = sc->sc_sessions = (struct hifn_session *)kmalloc(
+                   sizeof(*ses), 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].hs_used) {
+                               ses = &sc->sc_sessions[sesn];
+                               break;
+                       }
+               }
+
+               if (ses == NULL) {
+                       sesn = sc->sc_nsessions;
+                       ses = (struct hifn_session *)kmalloc((sesn + 1) *
+                            sizeof(*ses), M_DEVBUF, M_NOWAIT);
+                       if (ses == NULL)
+                               return (ENOMEM);
+                       bcopy(sc->sc_sessions, ses, sesn * sizeof(*ses));
+                       bzero(sc->sc_sessions, sesn * sizeof(*ses));
+                       kfree(sc->sc_sessions, M_DEVBUF);
+                       sc->sc_sessions = ses;
+                       ses = &sc->sc_sessions[sesn];
+                       sc->sc_nsessions++;
+               }
+       }
+       bzero(ses, sizeof(*ses));
+       ses->hs_used = 1;
 
        for (c = cri; c != NULL; c = c->cri_next) {
                switch (c->cri_alg) {
@@ -2154,8 +2373,11 @@ hifn_newsession(void *arg, u_int32_t *sidp, struct cryptoini *cri)
                        break;
                case CRYPTO_DES_CBC:
                case CRYPTO_3DES_CBC:
+               case CRYPTO_AES_CBC:
                        /* XXX this may read fewer, does it matter? */
-                       read_random(sc->sc_sessions[i].hs_iv, HIFN_IV_LENGTH);
+                       read_random(ses->hs_iv,
+                               c->cri_alg == CRYPTO_AES_CBC ?
+                                       HIFN_AES_IV_LENGTH : HIFN_IV_LENGTH);
                        /*FALLTHROUGH*/
                case CRYPTO_ARC4:
                        if (cry)
@@ -2169,8 +2391,7 @@ hifn_newsession(void *arg, u_int32_t *sidp, struct cryptoini *cri)
        if (mac == 0 && cry == 0)
                return (EINVAL);
 
-       *sidp = HIFN_SID(device_get_unit(sc->sc_dev), i);
-       sc->sc_sessions[i].hs_state = HS_STATE_USED;
+       *sidp = HIFN_SID(device_get_unit(sc->sc_dev), sesn);
 
        return (0);
 }
@@ -2180,19 +2401,21 @@ hifn_newsession(void *arg, u_int32_t *sidp, struct cryptoini *cri)
  * XXX this routine should run a zero'd mac/encrypt key into context ram.
  * XXX to blow away any keys already stored there.
  */
+#define        CRYPTO_SESID2LID(_sid)  (((u_int32_t) (_sid)) & 0xffffffff)
+
 static int
 hifn_freesession(void *arg, u_int64_t tid)
 {
        struct hifn_softc *sc = arg;
        int session;
-       u_int32_t sid = ((u_int32_t) tid) & 0xffffffff;
+       u_int32_t sid = CRYPTO_SESID2LID(tid);
 
        KASSERT(sc != NULL, ("hifn_freesession: null softc"));
        if (sc == NULL)
                return (EINVAL);
 
        session = HIFN_SESSION(sid);
-       if (session >= sc->sc_maxses)
+       if (session >= sc->sc_nsessions)
                return (EINVAL);
 
        bzero(&sc->sc_sessions[session], sizeof(sc->sc_sessions[session]));
@@ -2204,7 +2427,7 @@ hifn_process(void *arg, struct cryptop *crp, int hint)
 {
        struct hifn_softc *sc = arg;
        struct hifn_command *cmd = NULL;
-       int session, err;
+       int session, err, ivlen;
        struct cryptodesc *crd1, *crd2, *maccrd, *enccrd;
 
        if (crp == NULL || crp->crp_callback == NULL) {
@@ -2213,12 +2436,17 @@ hifn_process(void *arg, struct cryptop *crp, int hint)
        }
        session = HIFN_SESSION(crp->crp_sid);
 
-       if (sc == NULL || session >= sc->sc_maxses) {
+       if (sc == NULL || session >= sc->sc_nsessions) {
                err = EINVAL;
                goto errout;
        }
 
        cmd = kmalloc(sizeof(struct hifn_command), M_DEVBUF, M_INTWAIT | M_ZERO);
+       if (cmd == NULL) {
+               hifnstats.hst_nomem++;
+               err = ENOMEM;
+               goto errout;
+       }
 
        if (crp->crp_flags & CRYPTO_F_IMBUF) {
                cmd->src_m = (struct mbuf *)crp->crp_buf;
@@ -2247,6 +2475,7 @@ hifn_process(void *arg, struct cryptop *crp, int hint)
                        enccrd = NULL;
                } else if (crd1->crd_alg == CRYPTO_DES_CBC ||
                    crd1->crd_alg == CRYPTO_3DES_CBC ||
+                   crd1->crd_alg == CRYPTO_AES_CBC ||
                    crd1->crd_alg == CRYPTO_ARC4) {
                        if ((crd1->crd_flags & CRD_F_ENCRYPT) == 0)
                                cmd->base_masks |= HIFN_BASE_CMD_DECODE;
@@ -2263,6 +2492,7 @@ hifn_process(void *arg, struct cryptop *crp, int hint)
                      crd1->crd_alg == CRYPTO_SHA1) &&
                    (crd2->crd_alg == CRYPTO_DES_CBC ||
                     crd2->crd_alg == CRYPTO_3DES_CBC ||
+                    crd2->crd_alg == CRYPTO_AES_CBC ||
                     crd2->crd_alg == CRYPTO_ARC4) &&
                    ((crd2->crd_flags & CRD_F_ENCRYPT) == 0)) {
                        cmd->base_masks = HIFN_BASE_CMD_DECODE;
@@ -2270,7 +2500,8 @@ hifn_process(void *arg, struct cryptop *crp, int hint)
                        enccrd = crd2;
                } else if ((crd1->crd_alg == CRYPTO_DES_CBC ||
                     crd1->crd_alg == CRYPTO_ARC4 ||
-                    crd1->crd_alg == CRYPTO_3DES_CBC) &&
+                    crd1->crd_alg == CRYPTO_3DES_CBC ||
+                    crd1->crd_alg == CRYPTO_AES_CBC) &&
                    (crd2->crd_alg == CRYPTO_MD5_HMAC ||
                      crd2->crd_alg == CRYPTO_SHA1_HMAC ||
                      crd2->crd_alg == CRYPTO_MD5 ||
@@ -2293,10 +2524,6 @@ hifn_process(void *arg, struct cryptop *crp, int hint)
                switch (enccrd->crd_alg) {
                case CRYPTO_ARC4:
                        cmd->cry_masks |= HIFN_CRYPT_CMD_ALG_RC4;
-                       if ((enccrd->crd_flags & CRD_F_ENCRYPT)
-                           != sc->sc_sessions[session].hs_prev_op)
-                               sc->sc_sessions[session].hs_state =
-                                   HS_STATE_USED;
                        break;
                case CRYPTO_DES_CBC:
                        cmd->cry_masks |= HIFN_CRYPT_CMD_ALG_DES |
@@ -2308,50 +2535,73 @@ hifn_process(void *arg, struct cryptop *crp, int hint)
                            HIFN_CRYPT_CMD_MODE_CBC |
                            HIFN_CRYPT_CMD_NEW_IV;
                        break;
+               case CRYPTO_AES_CBC:
+                       cmd->cry_masks |= HIFN_CRYPT_CMD_ALG_AES |
+                           HIFN_CRYPT_CMD_MODE_CBC |
+                           HIFN_CRYPT_CMD_NEW_IV;
+                       break;
                default:
                        err = EINVAL;
                        goto errout;
                }
                if (enccrd->crd_alg != CRYPTO_ARC4) {
+                       ivlen = ((enccrd->crd_alg == CRYPTO_AES_CBC) ?
+                               HIFN_AES_IV_LENGTH : HIFN_IV_LENGTH);
                        if (enccrd->crd_flags & CRD_F_ENCRYPT) {
                                if (enccrd->crd_flags & CRD_F_IV_EXPLICIT)
-                                       bcopy(enccrd->crd_iv, cmd->iv,
-                                           HIFN_IV_LENGTH);
+                                       bcopy(enccrd->crd_iv, cmd->iv, ivlen);
                                else
                                        bcopy(sc->sc_sessions[session].hs_iv,
-                                           cmd->iv, HIFN_IV_LENGTH);
+                                           cmd->iv, ivlen);
 
                                if ((enccrd->crd_flags & CRD_F_IV_PRESENT)
                                    == 0) {
                                        if (crp->crp_flags & CRYPTO_F_IMBUF)
                                                m_copyback(cmd->src_m,
                                                    enccrd->crd_inject,
-                                                   HIFN_IV_LENGTH, cmd->iv);
+                                                   ivlen, cmd->iv);
                                        else if (crp->crp_flags & CRYPTO_F_IOV)
                                                cuio_copyback(cmd->src_io,
                                                    enccrd->crd_inject,
-                                                   HIFN_IV_LENGTH, cmd->iv);
+                                                   ivlen, cmd->iv);
                                }
                        } else {
                                if (enccrd->crd_flags & CRD_F_IV_EXPLICIT)
-                                       bcopy(enccrd->crd_iv, cmd->iv,
-                                           HIFN_IV_LENGTH);
+                                       bcopy(enccrd->crd_iv, cmd->iv, ivlen);
                                else if (crp->crp_flags & CRYPTO_F_IMBUF)
                                        m_copydata(cmd->src_m,
-                                           enccrd->crd_inject,
-                                           HIFN_IV_LENGTH, cmd->iv);
+                                           enccrd->crd_inject, ivlen, cmd->iv);
                                else if (crp->crp_flags & CRYPTO_F_IOV)
                                        cuio_copydata(cmd->src_io,
-                                           enccrd->crd_inject,
-                                           HIFN_IV_LENGTH, cmd->iv);
+                                           enccrd->crd_inject, ivlen, cmd->iv);
                        }
                }
 
+               if (enccrd->crd_flags & CRD_F_KEY_EXPLICIT)
+                       cmd->cry_masks |= HIFN_CRYPT_CMD_NEW_KEY;
                cmd->ck = enccrd->crd_key;
                cmd->cklen = enccrd->crd_klen >> 3;
-
-               if (sc->sc_sessions[session].hs_state == HS_STATE_USED)
-                       cmd->cry_masks |= HIFN_CRYPT_CMD_NEW_KEY;
+               cmd->cry_masks |= HIFN_CRYPT_CMD_NEW_KEY;
+               /*
+                * Need to specify the size for the AES key in the masks.
+                */
+               if ((cmd->cry_masks & HIFN_CRYPT_CMD_ALG_MASK) ==
+                   HIFN_CRYPT_CMD_ALG_AES) {
+                       switch (cmd->cklen) {
+                       case 16:
+                               cmd->cry_masks |= HIFN_CRYPT_CMD_KSZ_128;
+                               break;
+                       case 24:
+                               cmd->cry_masks |= HIFN_CRYPT_CMD_KSZ_192;
+                               break;
+                       case 32:
+                               cmd->cry_masks |= HIFN_CRYPT_CMD_KSZ_256;
+                               break;
+                       default:
+                               err = EINVAL;
+                               goto errout;
+                       }
+               }
        }
 
        if (maccrd) {
@@ -2381,9 +2631,8 @@ hifn_process(void *arg, struct cryptop *crp, int hint)
                        break;
                }
 
-               if ((maccrd->crd_alg == CRYPTO_SHA1_HMAC ||
-                    maccrd->crd_alg == CRYPTO_MD5_HMAC) &&
-                   sc->sc_sessions[session].hs_state == HS_STATE_USED) {
+               if (maccrd->crd_alg == CRYPTO_SHA1_HMAC ||
+                   maccrd->crd_alg == CRYPTO_MD5_HMAC) {
                        cmd->mac_masks |= HIFN_MAC_CMD_NEW_KEY;
                        bcopy(maccrd->crd_key, cmd->mac, maccrd->crd_klen >> 3);
                        bzero(cmd->mac + (maccrd->crd_klen >> 3),
@@ -2397,11 +2646,6 @@ hifn_process(void *arg, struct cryptop *crp, int hint)
 
        err = hifn_crypto(sc, cmd, crp, hint);
        if (!err) {
-               if (enccrd)
-                       sc->sc_sessions[session].hs_prev_op =
-                               enccrd->crd_flags & CRD_F_ENCRYPT;
-               if (sc->sc_sessions[session].hs_state == HS_STATE_USED)
-                       sc->sc_sessions[session].hs_state = HS_STATE_KEY;
                return 0;
        } else if (err == ERESTART) {
                /*
@@ -2498,11 +2742,6 @@ hifn_abort(struct hifn_softc *sc)
        }
        dma->resk = i; dma->resu = u;
 
-       /* Force upload of key next time */
-       for (i = 0; i < sc->sc_maxses; i++)
-               if (sc->sc_sessions[i].hs_state == HS_STATE_KEY)
-                       sc->sc_sessions[i].hs_state = HS_STATE_USED;
-       
        hifn_reset_board(sc, 1);
        hifn_init_dma(sc);
        hifn_init_pci_registers(sc);
@@ -2515,7 +2754,7 @@ hifn_callback(struct hifn_softc *sc, struct hifn_command *cmd, u_int8_t *macbuf)
        struct cryptop *crp = cmd->crp;
        struct cryptodesc *crd;
        struct mbuf *m;
-       int totlen, i, u;
+       int totlen, i, u, ivlen;
 
        if (cmd->src_map == cmd->dst_map) {
                bus_dmamap_sync(sc->sc_dmat, cmd->src_map,
@@ -2575,17 +2814,18 @@ hifn_callback(struct hifn_softc *sc, struct hifn_command *cmd, u_int8_t *macbuf)
            HIFN_BASE_CMD_CRYPT) {
                for (crd = crp->crp_desc; crd; crd = crd->crd_next) {
                        if (crd->crd_alg != CRYPTO_DES_CBC &&
-                           crd->crd_alg != CRYPTO_3DES_CBC)
+                           crd->crd_alg != CRYPTO_3DES_CBC &&
+                           crd->crd_alg != CRYPTO_AES_CBC)
                                continue;
+                       ivlen = ((crd->crd_alg == CRYPTO_AES_CBC) ?
+                                HIFN_AES_IV_LENGTH : HIFN_IV_LENGTH);
                        if (crp->crp_flags & CRYPTO_F_IMBUF)
                                m_copydata((struct mbuf *)crp->crp_buf,
-                                   crd->crd_skip + crd->crd_len - HIFN_IV_LENGTH,
-                                   HIFN_IV_LENGTH,
+                                   crd->crd_skip + crd->crd_len - ivlen, ivlen,
                                    cmd->softc->sc_sessions[cmd->session_num].hs_iv);
                        else if (crp->crp_flags & CRYPTO_F_IOV) {
                                cuio_copydata((struct uio *)crp->crp_buf,
-                                   crd->crd_skip + crd->crd_len - HIFN_IV_LENGTH,
-                                   HIFN_IV_LENGTH,
+                                   crd->crd_skip + crd->crd_len - ivlen, ivlen,
                                    cmd->softc->sc_sessions[cmd->session_num].hs_iv);
                        }
                        break;
index 8e53c2d..3644ec3 100644 (file)
@@ -1,8 +1,8 @@
 /* $FreeBSD: src/sys/dev/hifn/hifn7751reg.h,v 1.1.2.1 2002/11/21 23:37:11 sam Exp $ */
-/* $DragonFly: src/sys/dev/crypto/hifn/hifn7751reg.h,v 1.2 2003/06/17 04:28:27 dillon Exp $ */
+/* $DragonFly: src/sys/dev/crypto/hifn/hifn7751reg.h,v 1.3 2007/12/04 09:11:12 hasso Exp $ */
 /*     $OpenBSD: hifn7751reg.h,v 1.35 2002/04/08 17:49:42 jason Exp $  */
 
-/*
+/*-
  * Invertex AEON / Hifn 7751 driver
  * Copyright (c) 1999 Invertex Inc. All rights reserved.
  * Copyright (c) 1999 Theo de Raadt
  * Some PCI configuration space offset defines.  The names were made
  * identical to the names used by the Linux kernel.
  */
+#ifdef notyet
 #define        HIFN_BAR0               (PCIR_MAPS+0x0) /* PUC register map */
 #define        HIFN_BAR1               (PCIR_MAPS+0x4) /* DMA register map */
+#else
+#define        HIFN_BAR0               PCIR_BAR(0)     /* PUC register map */
+#define        HIFN_BAR1               PCIR_BAR(1)     /* DMA register map */
+#endif
 #define        HIFN_TRDY_TIMEOUT       0x40
 #define        HIFN_RETRY_TIMEOUT      0x41
 
@@ -64,6 +69,8 @@
 #define        PCI_PRODUCT_HIFN_6500   0x0006          /* 6500 */
 #define        PCI_PRODUCT_HIFN_7811   0x0007          /* 7811 */
 #define        PCI_PRODUCT_HIFN_7951   0x0012          /* 7951 */
+#define        PCI_PRODUCT_HIFN_7955   0x0020          /* 7954/7955 */
+#define        PCI_PRODUCT_HIFN_7956   0x001d          /* 7956 */
 
 #define        PCI_VENDOR_INVERTEX     0x14e1          /* Invertex */
 #define        PCI_PRODUCT_INVERTEX_AEON 0x0005        /* AEON */
@@ -211,6 +218,7 @@ typedef struct hifn_desc {
 #define        HIFN_1_DMA_CSR          0x40    /* DMA Status and Control */
 #define        HIFN_1_DMA_IER          0x44    /* DMA Interrupt Enable */
 #define        HIFN_1_DMA_CNFG         0x48    /* DMA Configuration */
+#define        HIFN_1_PLL              0x4c    /* 7955/7956: PLL config */
 #define        HIFN_1_7811_RNGENA      0x60    /* 7811: rng enable */
 #define        HIFN_1_7811_RNGCFG      0x64    /* 7811: rng config */
 #define        HIFN_1_7811_RNGDAT      0x68    /* 7811: rng data */
@@ -370,6 +378,41 @@ typedef struct hifn_desc {
 #define        HIFN_UNLOCK_SECRET1     0xf4
 #define        HIFN_UNLOCK_SECRET2     0xfc
 
+/*
+ * PLL config register
+ *
+ * This register is present only on 7954/7955/7956 parts. It must be
+ * programmed according to the bus interface method used by the h/w.
+ * Note that the parts require a stable clock.  Since the PCI clock
+ * may vary the reference clock must usually be used.  To avoid
+ * overclocking the core logic, setup must be done carefully, refer
+ * to the driver for details.  The exact multiplier required varies
+ * by part and system configuration; refer to the Hifn documentation.
+ */
+#define        HIFN_PLL_REF_SEL        0x00000001      /* REF/HBI clk selection */
+#define        HIFN_PLL_BP             0x00000002      /* bypass (used during setup) */
+/* bit 2 reserved */
+#define        HIFN_PLL_PK_CLK_SEL     0x00000008      /* public key clk select */
+#define        HIFN_PLL_PE_CLK_SEL     0x00000010      /* packet engine clk select */
+/* bits 5-9 reserved */
+#define        HIFN_PLL_MBSET          0x00000400      /* must be set to 1 */
+#define        HIFN_PLL_ND             0x00003800      /* Fpll_ref multiplier select */
+#define        HIFN_PLL_ND_SHIFT       11
+#define        HIFN_PLL_ND_2           0x00000000      /* 2x */
+#define        HIFN_PLL_ND_4           0x00000800      /* 4x */
+#define        HIFN_PLL_ND_6           0x00001000      /* 6x */
+#define        HIFN_PLL_ND_8           0x00001800      /* 8x */
+#define        HIFN_PLL_ND_10          0x00002000      /* 10x */
+#define        HIFN_PLL_ND_12          0x00002800      /* 12x */
+/* bits 14-15 reserved */
+#define        HIFN_PLL_IS             0x00010000      /* charge pump current select */
+/* bits 17-31 reserved */
+
+/*
+ * Board configuration specifies only these bits.
+ */
+#define        HIFN_PLL_CONFIG         (HIFN_PLL_IS|HIFN_PLL_ND|HIFN_PLL_REF_SEL)
+
 /*********************************************************************
  * Structs for board commands 
  *
@@ -385,6 +428,8 @@ typedef struct hifn_base_command {
        volatile u_int16_t total_dest_count;
 } hifn_base_command_t;
 
+#define        HIFN_BASE_CMD_COMP              0x0100  /* enable compression engine */
+#define        HIFN_BASE_CMD_PAD               0x0200  /* enable padding engine */
 #define        HIFN_BASE_CMD_MAC               0x0400
 #define        HIFN_BASE_CMD_CRYPT             0x0800
 #define        HIFN_BASE_CMD_DECODE            0x2000
@@ -409,7 +454,8 @@ typedef struct hifn_crypt_command {
 #define        HIFN_CRYPT_CMD_ALG_DES          0x0000          /*   DES */
 #define        HIFN_CRYPT_CMD_ALG_3DES         0x0001          /*   3DES */
 #define        HIFN_CRYPT_CMD_ALG_RC4          0x0002          /*   RC4 */
-#define        HIFN_CRYPT_CMD_MODE_MASK        0x0018          /* DES mode: */
+#define        HIFN_CRYPT_CMD_ALG_AES          0x0003          /*   AES */
+#define        HIFN_CRYPT_CMD_MODE_MASK        0x0018          /* Encrypt/DES mode: */
 #define        HIFN_CRYPT_CMD_MODE_ECB         0x0000          /*   ECB */
 #define        HIFN_CRYPT_CMD_MODE_CBC         0x0008          /*   CBC */
 #define        HIFN_CRYPT_CMD_MODE_CFB         0x0010          /*   CFB */
@@ -421,6 +467,11 @@ typedef struct hifn_crypt_command {
 #define        HIFN_CRYPT_CMD_SRCLEN_M         0xc000
 #define        HIFN_CRYPT_CMD_SRCLEN_S         14
 
+#define        HIFN_CRYPT_CMD_KSZ_MASK         0x0600          /* AES key size: */
+#define        HIFN_CRYPT_CMD_KSZ_128          0x0000          /*  128 bit */
+#define        HIFN_CRYPT_CMD_KSZ_192          0x0200          /*  192 bit */
+#define        HIFN_CRYPT_CMD_KSZ_256          0x0400          /*  256 bit */
+
 /*
  * Structure to help build up the command data structure.
  */
@@ -452,6 +503,64 @@ typedef struct hifn_mac_command {
 #define        HIFN_MAC_CMD_POS_IPSEC          0x0200
 #define        HIFN_MAC_CMD_NEW_KEY            0x0800
 
+struct hifn_comp_command {
+       volatile u_int16_t masks;
+       volatile u_int16_t header_skip;
+       volatile u_int16_t source_count;
+       volatile u_int16_t reserved;
+};
+
+#define        HIFN_COMP_CMD_SRCLEN_M          0xc000
+#define        HIFN_COMP_CMD_SRCLEN_S          14
+#define        HIFN_COMP_CMD_ONE               0x0100  /* must be one */
+#define        HIFN_COMP_CMD_CLEARHIST         0x0010  /* clear history */
+#define        HIFN_COMP_CMD_UPDATEHIST        0x0008  /* update history */
+#define        HIFN_COMP_CMD_LZS_STRIP0        0x0004  /* LZS: strip zero */
+#define        HIFN_COMP_CMD_MPPC_RESTART      0x0004  /* MPPC: restart */
+#define        HIFN_COMP_CMD_ALG_MASK          0x0001  /* compression mode: */
+#define        HIFN_COMP_CMD_ALG_MPPC          0x0001  /*   MPPC */
+#define        HIFN_COMP_CMD_ALG_LZS           0x0000  /*   LZS */
+
+struct hifn_base_result {
+       volatile u_int16_t flags;
+       volatile u_int16_t session;
+       volatile u_int16_t src_cnt;             /* 15:0 of source count */
+       volatile u_int16_t dst_cnt;             /* 15:0 of dest count */
+};
+
+#define        HIFN_BASE_RES_DSTOVERRUN        0x0200  /* destination overrun */
+#define        HIFN_BASE_RES_SRCLEN_M          0xc000  /* 17:16 of source count */
+#define        HIFN_BASE_RES_SRCLEN_S          14
+#define        HIFN_BASE_RES_DSTLEN_M          0x3000  /* 17:16 of dest count */
+#define        HIFN_BASE_RES_DSTLEN_S          12
+
+struct hifn_comp_result {
+       volatile u_int16_t flags;
+       volatile u_int16_t crc;
+};
+
+#define        HIFN_COMP_RES_LCB_M             0xff00  /* longitudinal check byte */
+#define        HIFN_COMP_RES_LCB_S             8
+#define        HIFN_COMP_RES_RESTART           0x0004  /* MPPC: restart */
+#define        HIFN_COMP_RES_ENDMARKER         0x0002  /* LZS: end marker seen */
+#define        HIFN_COMP_RES_SRC_NOTZERO       0x0001  /* source expired */
+
+struct hifn_mac_result {
+       volatile u_int16_t flags;
+       volatile u_int16_t reserved;
+       /* followed by 0, 6, 8, or 10 u_int16_t's of the MAC, then crypt */
+};
+
+#define        HIFN_MAC_RES_MISCOMPARE         0x0002  /* compare failed */
+#define        HIFN_MAC_RES_SRC_NOTZERO        0x0001  /* source expired */
+
+struct hifn_crypt_result {
+       volatile u_int16_t flags;
+       volatile u_int16_t reserved;
+};
+
+#define        HIFN_CRYPT_RES_SRC_NOTZERO      0x0001  /* source expired */
+
 /*
  * The poll frequency and poll scalar defines are unshifted values used
  * to set fields in the DMA Configuration Register.
index a5e44fa..c8d3cc9 100644 (file)
@@ -1,8 +1,8 @@
 /* $FreeBSD: src/sys/dev/hifn/hifn7751var.h,v 1.1.2.2 2003/06/04 17:56:59 sam Exp $ */
-/* $DragonFly: src/sys/dev/crypto/hifn/hifn7751var.h,v 1.2 2003/06/17 04:28:27 dillon Exp $ */
-/*     $OpenBSD: hifn7751var.h,v 1.42 2002/04/08 17:49:42 jason Exp $  */
+/* $DragonFly: src/sys/dev/crypto/hifn/hifn7751var.h,v 1.3 2007/12/04 09:11:12 hasso Exp $ */
+/* $OpenBSD: hifn7751var.h,v 1.42 2002/04/08 17:49:42 jason Exp $ */
 
-/*
+/*-
  * Invertex AEON / Hifn 7751 driver
  * Copyright (c) 1999 Invertex Inc. All rights reserved.
  * Copyright (c) 1999 Theo de Raadt
@@ -68,6 +68,8 @@
 #define HIFN_3DES_KEY_LENGTH           24
 #define HIFN_MAX_CRYPT_KEY_LENGTH      HIFN_3DES_KEY_LENGTH
 #define HIFN_IV_LENGTH                 8
+#define HIFN_AES_IV_LENGTH             16
+#define HIFN_MAX_IV_LENGTH             HIFN_AES_IV_LENGTH
 
 /*
  *  Length values for authentication
@@ -110,9 +112,8 @@ struct hifn_dma {
 };
 
 struct hifn_session {
-       int hs_state;
-       int hs_prev_op; /* XXX collapse into hs_flags? */
-       u_int8_t hs_iv[HIFN_IV_LENGTH];
+       int hs_used;
+       u_int8_t hs_iv[HIFN_MAX_IV_LENGTH];
 };
 
 #define        HIFN_RING_SYNC(sc, r, i, f)                                     \
@@ -153,7 +154,7 @@ struct hifn_softc {
 
        u_int32_t               sc_dmaier;
        u_int32_t               sc_drammodel;   /* 1=dram, 0=sram */
-
+       u_int32_t               sc_pllconfig;   /* 7954/7955/7956 PLL config */
 
        struct hifn_dma         *sc_dma;
        bus_dmamap_t            sc_dmamap;
@@ -162,11 +163,15 @@ struct hifn_softc {
        int                     sc_dmansegs;
        int32_t                 sc_cid;
        int                     sc_maxses;
+       int                     sc_nsessions;
+       struct hifn_session     *sc_sessions;
        int                     sc_ramsize;
        int                     sc_flags;
 #define        HIFN_HAS_RNG            0x1     /* includes random number generator */
 #define        HIFN_HAS_PUBLIC         0x2     /* includes public key support */
-#define        HIFN_IS_7811            0x4     /* Hifn 7811 part */
+#define        HIFN_HAS_AES            0x4     /* includes AES support */
+#define        HIFN_IS_7811            0x8     /* Hifn 7811 part */
+#define        HIFN_IS_7956            0x10    /* Hifn 7956/7955 don't have SDRAM */
        struct callout          sc_rngto;       /* for polling RNG */
        struct callout          sc_tickto;      /* for managing DMA */
        int                     sc_rngfirst;
@@ -182,7 +187,6 @@ struct hifn_softc {
        int                     sc_needwakeup;  /* ops q'd wating on resources */
        int                     sc_curbatch;    /* # ops submitted w/o int */
        int                     sc_suspended;
-       struct hifn_session     sc_sessions[2048];
 };
 
 /*
@@ -263,7 +267,7 @@ struct hifn_operand {
 struct hifn_command {
        u_int16_t session_num;
        u_int16_t base_masks, cry_masks, mac_masks;
-       u_int8_t iv[HIFN_IV_LENGTH], *ck, mac[HIFN_MAC_KEY_LENGTH];
+       u_int8_t iv[HIFN_MAX_IV_LENGTH], *ck, mac[HIFN_MAC_KEY_LENGTH];
        int cklen;
        int sloplen, slopidx;
 
index 38a97e8..261bdb8 100644 (file)
@@ -1,5 +1,5 @@
 /*     $FreeBSD: src/sys/opencrypto/cryptodev.h,v 1.2.2.5 2003/06/03 00:09:02 sam Exp $        */
-/*     $DragonFly: src/sys/opencrypto/cryptodev.h,v 1.2 2003/06/17 04:28:54 dillon Exp $       */
+/*     $DragonFly: src/sys/opencrypto/cryptodev.h,v 1.3 2007/12/04 09:11:12 hasso Exp $        */
 /*     $OpenBSD: cryptodev.h,v 1.31 2002/06/11 11:14:29 beck Exp $     */
 
 /*
@@ -228,7 +228,8 @@ struct cryptodesc {
                                           place, so don't copy. */
 #define        CRD_F_IV_EXPLICIT       0x04    /* IV explicitly provided */
 #define        CRD_F_DSA_SHA_NEEDED    0x08    /* Compute SHA-1 of buffer for DSA */
-#define CRD_F_COMP             0x0f    /* Set when doing compression */
+#define        CRD_F_COMP              0x0f    /* Set when doing compression */
+#define        CRD_F_KEY_EXPLICIT      0x10    /* Key explicitly provided */
 
        struct cryptoini        CRD_INI; /* Initialization/context data */
 #define crd_iv         CRD_INI.cri_iv
index 4b56437..862c18f 100644 (file)
@@ -1,5 +1,5 @@
 /*     $FreeBSD: src/sys/opencrypto/cryptosoft.c,v 1.2.2.1 2002/11/21 23:34:23 sam Exp $       */
-/*     $DragonFly: src/sys/opencrypto/cryptosoft.c,v 1.5 2006/09/05 03:48:13 dillon Exp $      */
+/*     $DragonFly: src/sys/opencrypto/cryptosoft.c,v 1.6 2007/12/04 09:11:12 hasso Exp $       */
 /*     $OpenBSD: cryptosoft.c,v 1.35 2002/04/26 08:43:50 deraadt Exp $ */
 
 /*
@@ -154,6 +154,17 @@ swcr_encdec(struct cryptodesc *crd, struct swcr_data *sw, caddr_t buf,
                }
        }
 
+       if (crd->crd_flags & CRD_F_KEY_EXPLICIT) {
+               int error;
+
+               if (sw->sw_kschedule)
+                       exf->zerokey(&(sw->sw_kschedule));
+               error = exf->setkey(&sw->sw_kschedule,
+                               crd->crd_key, crd->crd_klen / 8);
+               if (error)
+                       return (error);
+       }
+
        ivp = iv;
 
        if (outtype == CRYPTO_BUF_CONTIG) {