The Design and Implementation of the FreeBSD Operating System, Second Edition
Now available: The Design and Implementation of the FreeBSD Operating System (Second Edition)


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]

FreeBSD/Linux Kernel Cross Reference
sys/dev/hifn/hifn7751.c

Version: -  FREEBSD  -  FREEBSD-13-STABLE  -  FREEBSD-13-0  -  FREEBSD-12-STABLE  -  FREEBSD-12-0  -  FREEBSD-11-STABLE  -  FREEBSD-11-0  -  FREEBSD-10-STABLE  -  FREEBSD-10-0  -  FREEBSD-9-STABLE  -  FREEBSD-9-0  -  FREEBSD-8-STABLE  -  FREEBSD-8-0  -  FREEBSD-7-STABLE  -  FREEBSD-7-0  -  FREEBSD-6-STABLE  -  FREEBSD-6-0  -  FREEBSD-5-STABLE  -  FREEBSD-5-0  -  FREEBSD-4-STABLE  -  FREEBSD-3-STABLE  -  FREEBSD22  -  l41  -  OPENBSD  -  linux-2.6  -  MK84  -  PLAN9  -  xnu-8792 
SearchContext: -  none  -  3  -  10 

    1 /*      $OpenBSD: hifn7751.c,v 1.120 2002/05/17 00:33:34 deraadt Exp $  */
    2 
    3 /*-
    4  * Invertex AEON / Hifn 7751 driver
    5  * Copyright (c) 1999 Invertex Inc. All rights reserved.
    6  * Copyright (c) 1999 Theo de Raadt
    7  * Copyright (c) 2000-2001 Network Security Technologies, Inc.
    8  *                      http://www.netsec.net
    9  * Copyright (c) 2003 Hifn Inc.
   10  *
   11  * This driver is based on a previous driver by Invertex, for which they
   12  * requested:  Please send any comments, feedback, bug-fixes, or feature
   13  * requests to software@invertex.com.
   14  *
   15  * Redistribution and use in source and binary forms, with or without
   16  * modification, are permitted provided that the following conditions
   17  * are met:
   18  *
   19  * 1. Redistributions of source code must retain the above copyright
   20  *   notice, this list of conditions and the following disclaimer.
   21  * 2. Redistributions in binary form must reproduce the above copyright
   22  *   notice, this list of conditions and the following disclaimer in the
   23  *   documentation and/or other materials provided with the distribution.
   24  * 3. The name of the author may not be used to endorse or promote products
   25  *   derived from this software without specific prior written permission.
   26  *
   27  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
   28  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
   29  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
   30  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
   31  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
   32  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
   33  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
   34  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
   35  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
   36  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
   37  *
   38  * Effort sponsored in part by the Defense Advanced Research Projects
   39  * Agency (DARPA) and Air Force Research Laboratory, Air Force
   40  * Materiel Command, USAF, under agreement number F30602-01-2-0537.
   41  */
   42 
   43 #include <sys/cdefs.h>
   44 __FBSDID("$FreeBSD$");
   45 
   46 /*
   47  * Driver for various Hifn encryption processors.
   48  */
   49 #include "opt_hifn.h"
   50 
   51 #include <sys/param.h>
   52 #include <sys/systm.h>
   53 #include <sys/proc.h>
   54 #include <sys/errno.h>
   55 #include <sys/malloc.h>
   56 #include <sys/kernel.h>
   57 #include <sys/module.h>
   58 #include <sys/mbuf.h>
   59 #include <sys/lock.h>
   60 #include <sys/mutex.h>
   61 #include <sys/sysctl.h>
   62 
   63 #include <vm/vm.h>
   64 #include <vm/pmap.h>
   65 
   66 #include <machine/clock.h>
   67 #include <machine/bus.h>
   68 #include <machine/resource.h>
   69 #include <sys/bus.h>
   70 #include <sys/rman.h>
   71 
   72 #include <opencrypto/cryptodev.h>
   73 #include <sys/random.h>
   74 
   75 #include <dev/pci/pcivar.h>
   76 #include <dev/pci/pcireg.h>
   77 
   78 #ifdef HIFN_RNDTEST
   79 #include <dev/rndtest/rndtest.h>
   80 #endif
   81 #include <dev/hifn/hifn7751reg.h>
   82 #include <dev/hifn/hifn7751var.h>
   83 
   84 /*
   85  * Prototypes and count for the pci_device structure
   86  */
   87 static  int hifn_probe(device_t);
   88 static  int hifn_attach(device_t);
   89 static  int hifn_detach(device_t);
   90 static  int hifn_suspend(device_t);
   91 static  int hifn_resume(device_t);
   92 static  void hifn_shutdown(device_t);
   93 
   94 static device_method_t hifn_methods[] = {
   95         /* Device interface */
   96         DEVMETHOD(device_probe,         hifn_probe),
   97         DEVMETHOD(device_attach,        hifn_attach),
   98         DEVMETHOD(device_detach,        hifn_detach),
   99         DEVMETHOD(device_suspend,       hifn_suspend),
  100         DEVMETHOD(device_resume,        hifn_resume),
  101         DEVMETHOD(device_shutdown,      hifn_shutdown),
  102 
  103         /* bus interface */
  104         DEVMETHOD(bus_print_child,      bus_generic_print_child),
  105         DEVMETHOD(bus_driver_added,     bus_generic_driver_added),
  106 
  107         { 0, 0 }
  108 };
  109 static driver_t hifn_driver = {
  110         "hifn",
  111         hifn_methods,
  112         sizeof (struct hifn_softc)
  113 };
  114 static devclass_t hifn_devclass;
  115 
  116 DRIVER_MODULE(hifn, pci, hifn_driver, hifn_devclass, 0, 0);
  117 MODULE_DEPEND(hifn, crypto, 1, 1, 1);
  118 #ifdef HIFN_RNDTEST
  119 MODULE_DEPEND(hifn, rndtest, 1, 1, 1);
  120 #endif
  121 
  122 static  void hifn_reset_board(struct hifn_softc *, int);
  123 static  void hifn_reset_puc(struct hifn_softc *);
  124 static  void hifn_puc_wait(struct hifn_softc *);
  125 static  int hifn_enable_crypto(struct hifn_softc *);
  126 static  void hifn_set_retry(struct hifn_softc *sc);
  127 static  void hifn_init_dma(struct hifn_softc *);
  128 static  void hifn_init_pci_registers(struct hifn_softc *);
  129 static  int hifn_sramsize(struct hifn_softc *);
  130 static  int hifn_dramsize(struct hifn_softc *);
  131 static  int hifn_ramtype(struct hifn_softc *);
  132 static  void hifn_sessions(struct hifn_softc *);
  133 static  void hifn_intr(void *);
  134 static  u_int hifn_write_command(struct hifn_command *, u_int8_t *);
  135 static  u_int32_t hifn_next_signature(u_int32_t a, u_int cnt);
  136 static  int hifn_newsession(void *, u_int32_t *, struct cryptoini *);
  137 static  int hifn_freesession(void *, u_int64_t);
  138 static  int hifn_process(void *, struct cryptop *, int);
  139 static  void hifn_callback(struct hifn_softc *, struct hifn_command *, u_int8_t *);
  140 static  int hifn_crypto(struct hifn_softc *, struct hifn_command *, struct cryptop *, int);
  141 static  int hifn_readramaddr(struct hifn_softc *, int, u_int8_t *);
  142 static  int hifn_writeramaddr(struct hifn_softc *, int, u_int8_t *);
  143 static  int hifn_dmamap_load_src(struct hifn_softc *, struct hifn_command *);
  144 static  int hifn_dmamap_load_dst(struct hifn_softc *, struct hifn_command *);
  145 static  int hifn_init_pubrng(struct hifn_softc *);
  146 static  void hifn_rng(void *);
  147 static  void hifn_tick(void *);
  148 static  void hifn_abort(struct hifn_softc *);
  149 static  void hifn_alloc_slot(struct hifn_softc *, int *, int *, int *, int *);
  150 
  151 static  void hifn_write_reg_0(struct hifn_softc *, bus_size_t, u_int32_t);
  152 static  void hifn_write_reg_1(struct hifn_softc *, bus_size_t, u_int32_t);
  153 
  154 static __inline u_int32_t
  155 READ_REG_0(struct hifn_softc *sc, bus_size_t reg)
  156 {
  157     u_int32_t v = bus_space_read_4(sc->sc_st0, sc->sc_sh0, reg);
  158     sc->sc_bar0_lastreg = (bus_size_t) -1;
  159     return (v);
  160 }
  161 #define WRITE_REG_0(sc, reg, val)       hifn_write_reg_0(sc, reg, val)
  162 
  163 static __inline u_int32_t
  164 READ_REG_1(struct hifn_softc *sc, bus_size_t reg)
  165 {
  166     u_int32_t v = bus_space_read_4(sc->sc_st1, sc->sc_sh1, reg);
  167     sc->sc_bar1_lastreg = (bus_size_t) -1;
  168     return (v);
  169 }
  170 #define WRITE_REG_1(sc, reg, val)       hifn_write_reg_1(sc, reg, val)
  171 
  172 SYSCTL_NODE(_hw, OID_AUTO, hifn, CTLFLAG_RD, 0, "Hifn driver parameters");
  173 
  174 #ifdef HIFN_DEBUG
  175 static  int hifn_debug = 0;
  176 SYSCTL_INT(_hw_hifn, OID_AUTO, debug, CTLFLAG_RW, &hifn_debug,
  177             0, "control debugging msgs");
  178 #endif
  179 
  180 static  struct hifn_stats hifnstats;
  181 SYSCTL_STRUCT(_hw_hifn, OID_AUTO, stats, CTLFLAG_RD, &hifnstats,
  182             hifn_stats, "driver statistics");
  183 static  int hifn_maxbatch = 1;
  184 SYSCTL_INT(_hw_hifn, OID_AUTO, maxbatch, CTLFLAG_RW, &hifn_maxbatch,
  185             0, "max ops to batch w/o interrupt");
  186 
  187 /*
  188  * Probe for a supported device.  The PCI vendor and device
  189  * IDs are used to detect devices we know how to handle.
  190  */
  191 static int
  192 hifn_probe(device_t dev)
  193 {
  194         if (pci_get_vendor(dev) == PCI_VENDOR_INVERTEX &&
  195             pci_get_device(dev) == PCI_PRODUCT_INVERTEX_AEON)
  196                 return (0);
  197         if (pci_get_vendor(dev) == PCI_VENDOR_HIFN &&
  198             (pci_get_device(dev) == PCI_PRODUCT_HIFN_7751 ||
  199              pci_get_device(dev) == PCI_PRODUCT_HIFN_7951 ||
  200              pci_get_device(dev) == PCI_PRODUCT_HIFN_7955 ||
  201              pci_get_device(dev) == PCI_PRODUCT_HIFN_7956 ||
  202              pci_get_device(dev) == PCI_PRODUCT_HIFN_7811))
  203                 return (0);
  204         if (pci_get_vendor(dev) == PCI_VENDOR_NETSEC &&
  205             pci_get_device(dev) == PCI_PRODUCT_NETSEC_7751)
  206                 return (0);
  207         return (ENXIO);
  208 }
  209 
  210 static void
  211 hifn_dmamap_cb(void *arg, bus_dma_segment_t *segs, int nseg, int error)
  212 {
  213         bus_addr_t *paddr = (bus_addr_t*) arg;
  214         *paddr = segs->ds_addr;
  215 }
  216 
  217 static const char*
  218 hifn_partname(struct hifn_softc *sc)
  219 {
  220         /* XXX sprintf numbers when not decoded */
  221         switch (pci_get_vendor(sc->sc_dev)) {
  222         case PCI_VENDOR_HIFN:
  223                 switch (pci_get_device(sc->sc_dev)) {
  224                 case PCI_PRODUCT_HIFN_6500:     return "Hifn 6500";
  225                 case PCI_PRODUCT_HIFN_7751:     return "Hifn 7751";
  226                 case PCI_PRODUCT_HIFN_7811:     return "Hifn 7811";
  227                 case PCI_PRODUCT_HIFN_7951:     return "Hifn 7951";
  228                 case PCI_PRODUCT_HIFN_7955:     return "Hifn 7955";
  229                 case PCI_PRODUCT_HIFN_7956:     return "Hifn 7956";
  230                 }
  231                 return "Hifn unknown-part";
  232         case PCI_VENDOR_INVERTEX:
  233                 switch (pci_get_device(sc->sc_dev)) {
  234                 case PCI_PRODUCT_INVERTEX_AEON: return "Invertex AEON";
  235                 }
  236                 return "Invertex unknown-part";
  237         case PCI_VENDOR_NETSEC:
  238                 switch (pci_get_device(sc->sc_dev)) {
  239                 case PCI_PRODUCT_NETSEC_7751:   return "NetSec 7751";
  240                 }
  241                 return "NetSec unknown-part";
  242         }
  243         return "Unknown-vendor unknown-part";
  244 }
  245 
  246 static void
  247 default_harvest(struct rndtest_state *rsp, void *buf, u_int count)
  248 {
  249         random_harvest(buf, count, count*NBBY, 0, RANDOM_PURE);
  250 }
  251 
  252 static u_int
  253 checkmaxmin(device_t dev, const char *what, u_int v, u_int min, u_int max)
  254 {
  255         if (v > max) {
  256                 device_printf(dev, "Warning, %s %u out of range, "
  257                         "using max %u\n", what, v, max);
  258                 v = max;
  259         } else if (v < min) {
  260                 device_printf(dev, "Warning, %s %u out of range, "
  261                         "using min %u\n", what, v, min);
  262                 v = min;
  263         }
  264         return v;
  265 }
  266 
  267 /*
  268  * Select PLL configuration for 795x parts.  This is complicated in
  269  * that we cannot determine the optimal parameters without user input.
  270  * The reference clock is derived from an external clock through a
  271  * multiplier.  The external clock is either the host bus (i.e. PCI)
  272  * or an external clock generator.  When using the PCI bus we assume
  273  * the clock is either 33 or 66 MHz; for an external source we cannot
  274  * tell the speed.
  275  *
  276  * PLL configuration is done with a string: "pci" for PCI bus, or "ext"
  277  * for an external source, followed by the frequency.  We calculate
  278  * the appropriate multiplier and PLL register contents accordingly.
  279  * When no configuration is given we default to "pci66" since that
  280  * always will allow the card to work.  If a card is using the PCI
  281  * bus clock and in a 33MHz slot then it will be operating at half
  282  * speed until the correct information is provided.
  283  */
  284 static void
  285 hifn_getpllconfig(device_t dev, u_int *pll)
  286 {
  287         const char *pllspec;
  288         u_int freq, mul, fl, fh;
  289         u_int32_t pllconfig;
  290         char *nxt;
  291 
  292         if (resource_string_value("hifn", device_get_unit(dev),
  293             "pllconfig", &pllspec))
  294                 pllspec = "pci66";
  295         fl = 33, fh = 66;
  296         pllconfig = 0;
  297         if (strncmp(pllspec, "ext", 3) == 0) {
  298                 pllspec += 3;
  299                 pllconfig |= HIFN_PLL_REF_SEL;
  300                 switch (pci_get_device(dev)) {
  301                 case PCI_PRODUCT_HIFN_7955:
  302                 case PCI_PRODUCT_HIFN_7956:
  303                         fl = 20, fh = 100;
  304                         break;
  305 #ifdef notyet
  306                 case PCI_PRODUCT_HIFN_7954:
  307                         fl = 20, fh = 66;
  308                         break;
  309 #endif
  310                 }
  311         } else if (strncmp(pllspec, "pci", 3) == 0)
  312                 pllspec += 3;
  313         freq = strtoul(pllspec, &nxt, 10);
  314         if (nxt == pllspec)
  315                 freq = 66;
  316         else
  317                 freq = checkmaxmin(dev, "frequency", freq, fl, fh);
  318         /*
  319          * Calculate multiplier.  We target a Fck of 266 MHz,
  320          * allowing only even values, possibly rounded down.
  321          * Multipliers > 8 must set the charge pump current.
  322          */
  323         mul = checkmaxmin(dev, "PLL divisor", (266 / freq) &~ 1, 2, 12);
  324         pllconfig |= (mul / 2 - 1) << HIFN_PLL_ND_SHIFT;
  325         if (mul > 8)
  326                 pllconfig |= HIFN_PLL_IS;
  327         *pll = pllconfig;
  328 }
  329 
  330 /*
  331  * Attach an interface that successfully probed.
  332  */
  333 static int 
  334 hifn_attach(device_t dev)
  335 {
  336         struct hifn_softc *sc = device_get_softc(dev);
  337         u_int32_t cmd;
  338         caddr_t kva;
  339         int rseg, rid;
  340         char rbase;
  341         u_int16_t ena, rev;
  342 
  343         KASSERT(sc != NULL, ("hifn_attach: null software carrier!"));
  344         bzero(sc, sizeof (*sc));
  345         sc->sc_dev = dev;
  346 
  347         mtx_init(&sc->sc_mtx, device_get_nameunit(dev), "hifn driver", MTX_DEF);
  348 
  349         /* XXX handle power management */
  350 
  351         /*
  352          * The 7951 and 795x have a random number generator and
  353          * public key support; note this.
  354          */
  355         if (pci_get_vendor(dev) == PCI_VENDOR_HIFN &&
  356             (pci_get_device(dev) == PCI_PRODUCT_HIFN_7951 ||
  357              pci_get_device(dev) == PCI_PRODUCT_HIFN_7955 ||
  358              pci_get_device(dev) == PCI_PRODUCT_HIFN_7956))
  359                 sc->sc_flags = HIFN_HAS_RNG | HIFN_HAS_PUBLIC;
  360         /*
  361          * The 7811 has a random number generator and
  362          * we also note it's identity 'cuz of some quirks.
  363          */
  364         if (pci_get_vendor(dev) == PCI_VENDOR_HIFN &&
  365             pci_get_device(dev) == PCI_PRODUCT_HIFN_7811)
  366                 sc->sc_flags |= HIFN_IS_7811 | HIFN_HAS_RNG;
  367 
  368         /*
  369          * The 795x parts support AES.
  370          */
  371         if (pci_get_vendor(dev) == PCI_VENDOR_HIFN &&
  372             (pci_get_device(dev) == PCI_PRODUCT_HIFN_7955 ||
  373              pci_get_device(dev) == PCI_PRODUCT_HIFN_7956)) {
  374                 sc->sc_flags |= HIFN_IS_7956 | HIFN_HAS_AES;
  375                 /*
  376                  * Select PLL configuration.  This depends on the
  377                  * bus and board design and must be manually configured
  378                  * if the default setting is unacceptable.
  379                  */
  380                 hifn_getpllconfig(dev, &sc->sc_pllconfig);
  381         }
  382 
  383         /*
  384          * Configure support for memory-mapped access to
  385          * registers and for DMA operations.
  386          */
  387 #define PCIM_ENA        (PCIM_CMD_MEMEN|PCIM_CMD_BUSMASTEREN)
  388         cmd = pci_read_config(dev, PCIR_COMMAND, 4);
  389         cmd |= PCIM_ENA;
  390         pci_write_config(dev, PCIR_COMMAND, cmd, 4);
  391         cmd = pci_read_config(dev, PCIR_COMMAND, 4);
  392         if ((cmd & PCIM_ENA) != PCIM_ENA) {
  393                 device_printf(dev, "failed to enable %s\n",
  394                         (cmd & PCIM_ENA) == 0 ?
  395                                 "memory mapping & bus mastering" :
  396                         (cmd & PCIM_CMD_MEMEN) == 0 ?
  397                                 "memory mapping" : "bus mastering");
  398                 goto fail_pci;
  399         }
  400 #undef PCIM_ENA
  401 
  402         /*
  403          * Setup PCI resources. Note that we record the bus
  404          * tag and handle for each register mapping, this is
  405          * used by the READ_REG_0, WRITE_REG_0, READ_REG_1,
  406          * and WRITE_REG_1 macros throughout the driver.
  407          */
  408         rid = HIFN_BAR0;
  409         sc->sc_bar0res = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &rid,
  410                                                 RF_ACTIVE);
  411         if (sc->sc_bar0res == NULL) {
  412                 device_printf(dev, "cannot map bar%d register space\n", 0);
  413                 goto fail_pci;
  414         }
  415         sc->sc_st0 = rman_get_bustag(sc->sc_bar0res);
  416         sc->sc_sh0 = rman_get_bushandle(sc->sc_bar0res);
  417         sc->sc_bar0_lastreg = (bus_size_t) -1;
  418 
  419         rid = HIFN_BAR1;
  420         sc->sc_bar1res = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &rid,
  421                                                 RF_ACTIVE);
  422         if (sc->sc_bar1res == NULL) {
  423                 device_printf(dev, "cannot map bar%d register space\n", 1);
  424                 goto fail_io0;
  425         }
  426         sc->sc_st1 = rman_get_bustag(sc->sc_bar1res);
  427         sc->sc_sh1 = rman_get_bushandle(sc->sc_bar1res);
  428         sc->sc_bar1_lastreg = (bus_size_t) -1;
  429 
  430         hifn_set_retry(sc);
  431 
  432         /*
  433          * Setup the area where the Hifn DMA's descriptors
  434          * and associated data structures.
  435          */
  436         if (bus_dma_tag_create(NULL,                    /* parent */
  437                                1, 0,                    /* alignment,boundary */
  438                                BUS_SPACE_MAXADDR_32BIT, /* lowaddr */
  439                                BUS_SPACE_MAXADDR,       /* highaddr */
  440                                NULL, NULL,              /* filter, filterarg */
  441                                HIFN_MAX_DMALEN,         /* maxsize */
  442                                MAX_SCATTER,             /* nsegments */
  443                                HIFN_MAX_SEGLEN,         /* maxsegsize */
  444                                BUS_DMA_ALLOCNOW,        /* flags */
  445                                NULL,                    /* lockfunc */
  446                                NULL,                    /* lockarg */
  447                                &sc->sc_dmat)) {
  448                 device_printf(dev, "cannot allocate DMA tag\n");
  449                 goto fail_io1;
  450         }
  451         if (bus_dmamap_create(sc->sc_dmat, BUS_DMA_NOWAIT, &sc->sc_dmamap)) {
  452                 device_printf(dev, "cannot create dma map\n");
  453                 bus_dma_tag_destroy(sc->sc_dmat);
  454                 goto fail_io1;
  455         }
  456         if (bus_dmamem_alloc(sc->sc_dmat, (void**) &kva, BUS_DMA_NOWAIT, &sc->sc_dmamap)) {
  457                 device_printf(dev, "cannot alloc dma buffer\n");
  458                 bus_dmamap_destroy(sc->sc_dmat, sc->sc_dmamap);
  459                 bus_dma_tag_destroy(sc->sc_dmat);
  460                 goto fail_io1;
  461         }
  462         if (bus_dmamap_load(sc->sc_dmat, sc->sc_dmamap, kva,
  463                              sizeof (*sc->sc_dma),
  464                              hifn_dmamap_cb, &sc->sc_dma_physaddr,
  465                              BUS_DMA_NOWAIT)) {
  466                 device_printf(dev, "cannot load dma map\n");
  467                 bus_dmamem_free(sc->sc_dmat, kva, sc->sc_dmamap);
  468                 bus_dmamap_destroy(sc->sc_dmat, sc->sc_dmamap);
  469                 bus_dma_tag_destroy(sc->sc_dmat);
  470                 goto fail_io1;
  471         }
  472         sc->sc_dma = (struct hifn_dma *)kva;
  473         bzero(sc->sc_dma, sizeof(*sc->sc_dma));
  474 
  475         KASSERT(sc->sc_st0 != 0, ("hifn_attach: null bar0 tag!"));
  476         KASSERT(sc->sc_sh0 != 0, ("hifn_attach: null bar0 handle!"));
  477         KASSERT(sc->sc_st1 != 0, ("hifn_attach: null bar1 tag!"));
  478         KASSERT(sc->sc_sh1 != 0, ("hifn_attach: null bar1 handle!"));
  479 
  480         /*
  481          * Reset the board and do the ``secret handshake''
  482          * to enable the crypto support.  Then complete the
  483          * initialization procedure by setting up the interrupt
  484          * and hooking in to the system crypto support so we'll
  485          * get used for system services like the crypto device,
  486          * IPsec, RNG device, etc.
  487          */
  488         hifn_reset_board(sc, 0);
  489 
  490         if (hifn_enable_crypto(sc) != 0) {
  491                 device_printf(dev, "crypto enabling failed\n");
  492                 goto fail_mem;
  493         }
  494         hifn_reset_puc(sc);
  495 
  496         hifn_init_dma(sc);
  497         hifn_init_pci_registers(sc);
  498 
  499         /* XXX can't dynamically determine ram type for 795x; force dram */
  500         if (sc->sc_flags & HIFN_IS_7956)
  501                 sc->sc_drammodel = 1;
  502         else if (hifn_ramtype(sc))
  503                 goto fail_mem;
  504 
  505         if (sc->sc_drammodel == 0)
  506                 hifn_sramsize(sc);
  507         else
  508                 hifn_dramsize(sc);
  509 
  510         /*
  511          * Workaround for NetSec 7751 rev A: half ram size because two
  512          * of the address lines were left floating
  513          */
  514         if (pci_get_vendor(dev) == PCI_VENDOR_NETSEC &&
  515             pci_get_device(dev) == PCI_PRODUCT_NETSEC_7751 &&
  516             pci_get_revid(dev) == 0x61) /*XXX???*/
  517                 sc->sc_ramsize >>= 1;
  518 
  519         /*
  520          * Arrange the interrupt line.
  521          */
  522         rid = 0;
  523         sc->sc_irq = bus_alloc_resource_any(dev, SYS_RES_IRQ, &rid,
  524                                             RF_SHAREABLE|RF_ACTIVE);
  525         if (sc->sc_irq == NULL) {
  526                 device_printf(dev, "could not map interrupt\n");
  527                 goto fail_mem;
  528         }
  529         /*
  530          * NB: Network code assumes we are blocked with splimp()
  531          *     so make sure the IRQ is marked appropriately.
  532          */
  533         if (bus_setup_intr(dev, sc->sc_irq, INTR_TYPE_NET | INTR_MPSAFE,
  534                            hifn_intr, sc, &sc->sc_intrhand)) {
  535                 device_printf(dev, "could not setup interrupt\n");
  536                 goto fail_intr2;
  537         }
  538 
  539         hifn_sessions(sc);
  540 
  541         /*
  542          * NB: Keep only the low 16 bits; this masks the chip id
  543          *     from the 7951.
  544          */
  545         rev = READ_REG_1(sc, HIFN_1_REVID) & 0xffff;
  546 
  547         rseg = sc->sc_ramsize / 1024;
  548         rbase = 'K';
  549         if (sc->sc_ramsize >= (1024 * 1024)) {
  550                 rbase = 'M';
  551                 rseg /= 1024;
  552         }
  553         device_printf(sc->sc_dev, "%s, rev %u, %d%cB %cram",
  554                 hifn_partname(sc), rev,
  555                 rseg, rbase, sc->sc_drammodel ? 'd' : 's');
  556         if (sc->sc_flags & HIFN_IS_7956)
  557                 printf(", pll=0x%x<%s clk, %ux mult>",
  558                         sc->sc_pllconfig,
  559                         sc->sc_pllconfig & HIFN_PLL_REF_SEL ? "ext" : "pci",
  560                         2 + 2*((sc->sc_pllconfig & HIFN_PLL_ND) >> 11));
  561         printf("\n");
  562 
  563         sc->sc_cid = crypto_get_driverid(0);
  564         if (sc->sc_cid < 0) {
  565                 device_printf(dev, "could not get crypto driver id\n");
  566                 goto fail_intr;
  567         }
  568 
  569         WRITE_REG_0(sc, HIFN_0_PUCNFG,
  570             READ_REG_0(sc, HIFN_0_PUCNFG) | HIFN_PUCNFG_CHIPID);
  571         ena = READ_REG_0(sc, HIFN_0_PUSTAT) & HIFN_PUSTAT_CHIPENA;
  572 
  573         switch (ena) {
  574         case HIFN_PUSTAT_ENA_2:
  575                 crypto_register(sc->sc_cid, CRYPTO_3DES_CBC, 0, 0,
  576                     hifn_newsession, hifn_freesession, hifn_process, sc);
  577                 crypto_register(sc->sc_cid, CRYPTO_ARC4, 0, 0,
  578                     hifn_newsession, hifn_freesession, hifn_process, sc);
  579                 if (sc->sc_flags & HIFN_HAS_AES)
  580                         crypto_register(sc->sc_cid, CRYPTO_AES_CBC,  0, 0,
  581                                 hifn_newsession, hifn_freesession,
  582                                 hifn_process, sc);
  583                 /*FALLTHROUGH*/
  584         case HIFN_PUSTAT_ENA_1:
  585                 crypto_register(sc->sc_cid, CRYPTO_MD5, 0, 0,
  586                     hifn_newsession, hifn_freesession, hifn_process, sc);
  587                 crypto_register(sc->sc_cid, CRYPTO_SHA1, 0, 0,
  588                     hifn_newsession, hifn_freesession, hifn_process, sc);
  589                 crypto_register(sc->sc_cid, CRYPTO_MD5_HMAC, 0, 0,
  590                     hifn_newsession, hifn_freesession, hifn_process, sc);
  591                 crypto_register(sc->sc_cid, CRYPTO_SHA1_HMAC, 0, 0,
  592                     hifn_newsession, hifn_freesession, hifn_process, sc);
  593                 crypto_register(sc->sc_cid, CRYPTO_DES_CBC, 0, 0,
  594                     hifn_newsession, hifn_freesession, hifn_process, sc);
  595                 break;
  596         }
  597 
  598         bus_dmamap_sync(sc->sc_dmat, sc->sc_dmamap,
  599             BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE);
  600 
  601         if (sc->sc_flags & (HIFN_HAS_PUBLIC | HIFN_HAS_RNG))
  602                 hifn_init_pubrng(sc);
  603 
  604         callout_init(&sc->sc_tickto, CALLOUT_MPSAFE);
  605         callout_reset(&sc->sc_tickto, hz, hifn_tick, sc);
  606 
  607         return (0);
  608 
  609 fail_intr:
  610         bus_teardown_intr(dev, sc->sc_irq, sc->sc_intrhand);
  611 fail_intr2:
  612         /* XXX don't store rid */
  613         bus_release_resource(dev, SYS_RES_IRQ, 0, sc->sc_irq);
  614 fail_mem:
  615         bus_dmamap_unload(sc->sc_dmat, sc->sc_dmamap);
  616         bus_dmamem_free(sc->sc_dmat, sc->sc_dma, sc->sc_dmamap);
  617         bus_dmamap_destroy(sc->sc_dmat, sc->sc_dmamap);
  618         bus_dma_tag_destroy(sc->sc_dmat);
  619 
  620         /* Turn off DMA polling */
  621         WRITE_REG_1(sc, HIFN_1_DMA_CNFG, HIFN_DMACNFG_MSTRESET |
  622             HIFN_DMACNFG_DMARESET | HIFN_DMACNFG_MODE);
  623 fail_io1:
  624         bus_release_resource(dev, SYS_RES_MEMORY, HIFN_BAR1, sc->sc_bar1res);
  625 fail_io0:
  626         bus_release_resource(dev, SYS_RES_MEMORY, HIFN_BAR0, sc->sc_bar0res);
  627 fail_pci:
  628         mtx_destroy(&sc->sc_mtx);
  629         return (ENXIO);
  630 }
  631 
  632 /*
  633  * Detach an interface that successfully probed.
  634  */
  635 static int 
  636 hifn_detach(device_t dev)
  637 {
  638         struct hifn_softc *sc = device_get_softc(dev);
  639 
  640         KASSERT(sc != NULL, ("hifn_detach: null software carrier!"));
  641 
  642         /* disable interrupts */
  643         WRITE_REG_1(sc, HIFN_1_DMA_IER, 0);
  644 
  645         /*XXX other resources */
  646         callout_stop(&sc->sc_tickto);
  647         callout_stop(&sc->sc_rngto);
  648 #ifdef HIFN_RNDTEST
  649         if (sc->sc_rndtest)
  650                 rndtest_detach(sc->sc_rndtest);
  651 #endif
  652 
  653         /* Turn off DMA polling */
  654         WRITE_REG_1(sc, HIFN_1_DMA_CNFG, HIFN_DMACNFG_MSTRESET |
  655             HIFN_DMACNFG_DMARESET | HIFN_DMACNFG_MODE);
  656 
  657         crypto_unregister_all(sc->sc_cid);
  658 
  659         bus_generic_detach(dev);        /*XXX should be no children, right? */
  660 
  661         bus_teardown_intr(dev, sc->sc_irq, sc->sc_intrhand);
  662         /* XXX don't store rid */
  663         bus_release_resource(dev, SYS_RES_IRQ, 0, sc->sc_irq);
  664 
  665         bus_dmamap_unload(sc->sc_dmat, sc->sc_dmamap);
  666         bus_dmamem_free(sc->sc_dmat, sc->sc_dma, sc->sc_dmamap);
  667         bus_dmamap_destroy(sc->sc_dmat, sc->sc_dmamap);
  668         bus_dma_tag_destroy(sc->sc_dmat);
  669 
  670         bus_release_resource(dev, SYS_RES_MEMORY, HIFN_BAR1, sc->sc_bar1res);
  671         bus_release_resource(dev, SYS_RES_MEMORY, HIFN_BAR0, sc->sc_bar0res);
  672 
  673         mtx_destroy(&sc->sc_mtx);
  674 
  675         return (0);
  676 }
  677 
  678 /*
  679  * Stop all chip I/O so that the kernel's probe routines don't
  680  * get confused by errant DMAs when rebooting.
  681  */
  682 static void
  683 hifn_shutdown(device_t dev)
  684 {
  685 #ifdef notyet
  686         hifn_stop(device_get_softc(dev));
  687 #endif
  688 }
  689 
  690 /*
  691  * Device suspend routine.  Stop the interface and save some PCI
  692  * settings in case the BIOS doesn't restore them properly on
  693  * resume.
  694  */
  695 static int
  696 hifn_suspend(device_t dev)
  697 {
  698         struct hifn_softc *sc = device_get_softc(dev);
  699 #ifdef notyet
  700         int i;
  701 
  702         hifn_stop(sc);
  703         for (i = 0; i < 5; i++)
  704                 sc->saved_maps[i] = pci_read_config(dev, PCIR_BAR(i), 4);
  705         sc->saved_biosaddr = pci_read_config(dev, PCIR_BIOS, 4);
  706         sc->saved_intline = pci_read_config(dev, PCIR_INTLINE, 1);
  707         sc->saved_cachelnsz = pci_read_config(dev, PCIR_CACHELNSZ, 1);
  708         sc->saved_lattimer = pci_read_config(dev, PCIR_LATTIMER, 1);
  709 #endif
  710         sc->sc_suspended = 1;
  711 
  712         return (0);
  713 }
  714 
  715 /*
  716  * Device resume routine.  Restore some PCI settings in case the BIOS
  717  * doesn't, re-enable busmastering, and restart the interface if
  718  * appropriate.
  719  */
  720 static int
  721 hifn_resume(device_t dev)
  722 {
  723         struct hifn_softc *sc = device_get_softc(dev);
  724 #ifdef notyet
  725         int i;
  726 
  727         /* better way to do this? */
  728         for (i = 0; i < 5; i++)
  729                 pci_write_config(dev, PCIR_BAR(i), sc->saved_maps[i], 4);
  730         pci_write_config(dev, PCIR_BIOS, sc->saved_biosaddr, 4);
  731         pci_write_config(dev, PCIR_INTLINE, sc->saved_intline, 1);
  732         pci_write_config(dev, PCIR_CACHELNSZ, sc->saved_cachelnsz, 1);
  733         pci_write_config(dev, PCIR_LATTIMER, sc->saved_lattimer, 1);
  734 
  735         /* reenable busmastering */
  736         pci_enable_busmaster(dev);
  737         pci_enable_io(dev, HIFN_RES);
  738 
  739         /* reinitialize interface if necessary */
  740         if (ifp->if_flags & IFF_UP)
  741                 rl_init(sc);
  742 #endif
  743         sc->sc_suspended = 0;
  744 
  745         return (0);
  746 }
  747 
  748 static int
  749 hifn_init_pubrng(struct hifn_softc *sc)
  750 {
  751         u_int32_t r;
  752         int i;
  753 
  754 #ifdef HIFN_RNDTEST
  755         sc->sc_rndtest = rndtest_attach(sc->sc_dev);
  756         if (sc->sc_rndtest)
  757                 sc->sc_harvest = rndtest_harvest;
  758         else
  759                 sc->sc_harvest = default_harvest;
  760 #else
  761         sc->sc_harvest = default_harvest;
  762 #endif
  763         if ((sc->sc_flags & HIFN_IS_7811) == 0) {
  764                 /* Reset 7951 public key/rng engine */
  765                 WRITE_REG_1(sc, HIFN_1_PUB_RESET,
  766                     READ_REG_1(sc, HIFN_1_PUB_RESET) | HIFN_PUBRST_RESET);
  767 
  768                 for (i = 0; i < 100; i++) {
  769                         DELAY(1000);
  770                         if ((READ_REG_1(sc, HIFN_1_PUB_RESET) &
  771                             HIFN_PUBRST_RESET) == 0)
  772                                 break;
  773                 }
  774 
  775                 if (i == 100) {
  776                         device_printf(sc->sc_dev, "public key init failed\n");
  777                         return (1);
  778                 }
  779         }
  780 
  781         /* Enable the rng, if available */
  782         if (sc->sc_flags & HIFN_HAS_RNG) {
  783                 if (sc->sc_flags & HIFN_IS_7811) {
  784                         r = READ_REG_1(sc, HIFN_1_7811_RNGENA);
  785                         if (r & HIFN_7811_RNGENA_ENA) {
  786                                 r &= ~HIFN_7811_RNGENA_ENA;
  787                                 WRITE_REG_1(sc, HIFN_1_7811_RNGENA, r);
  788                         }
  789                         WRITE_REG_1(sc, HIFN_1_7811_RNGCFG,
  790                             HIFN_7811_RNGCFG_DEFL);
  791                         r |= HIFN_7811_RNGENA_ENA;
  792                         WRITE_REG_1(sc, HIFN_1_7811_RNGENA, r);
  793                 } else
  794                         WRITE_REG_1(sc, HIFN_1_RNG_CONFIG,
  795                             READ_REG_1(sc, HIFN_1_RNG_CONFIG) |
  796                             HIFN_RNGCFG_ENA);
  797 
  798                 sc->sc_rngfirst = 1;
  799                 if (hz >= 100)
  800                         sc->sc_rnghz = hz / 100;
  801                 else
  802                         sc->sc_rnghz = 1;
  803                 callout_init(&sc->sc_rngto, CALLOUT_MPSAFE);
  804                 callout_reset(&sc->sc_rngto, sc->sc_rnghz, hifn_rng, sc);
  805         }
  806 
  807         /* Enable public key engine, if available */
  808         if (sc->sc_flags & HIFN_HAS_PUBLIC) {
  809                 WRITE_REG_1(sc, HIFN_1_PUB_IEN, HIFN_PUBIEN_DONE);
  810                 sc->sc_dmaier |= HIFN_DMAIER_PUBDONE;
  811                 WRITE_REG_1(sc, HIFN_1_DMA_IER, sc->sc_dmaier);
  812         }
  813 
  814         return (0);
  815 }
  816 
  817 static void
  818 hifn_rng(void *vsc)
  819 {
  820 #define RANDOM_BITS(n)  (n)*sizeof (u_int32_t), (n)*sizeof (u_int32_t)*NBBY, 0
  821         struct hifn_softc *sc = vsc;
  822         u_int32_t sts, num[2];
  823         int i;
  824 
  825         if (sc->sc_flags & HIFN_IS_7811) {
  826                 for (i = 0; i < 5; i++) {
  827                         sts = READ_REG_1(sc, HIFN_1_7811_RNGSTS);
  828                         if (sts & HIFN_7811_RNGSTS_UFL) {
  829                                 device_printf(sc->sc_dev,
  830                                               "RNG underflow: disabling\n");
  831                                 return;
  832                         }
  833                         if ((sts & HIFN_7811_RNGSTS_RDY) == 0)
  834                                 break;
  835 
  836                         /*
  837                          * There are at least two words in the RNG FIFO
  838                          * at this point.
  839                          */
  840                         num[0] = READ_REG_1(sc, HIFN_1_7811_RNGDAT);
  841                         num[1] = READ_REG_1(sc, HIFN_1_7811_RNGDAT);
  842                         /* NB: discard first data read */
  843                         if (sc->sc_rngfirst)
  844                                 sc->sc_rngfirst = 0;
  845                         else
  846                                 (*sc->sc_harvest)(sc->sc_rndtest,
  847                                         num, sizeof (num));
  848                 }
  849         } else {
  850                 num[0] = READ_REG_1(sc, HIFN_1_RNG_DATA);
  851 
  852                 /* NB: discard first data read */
  853                 if (sc->sc_rngfirst)
  854                         sc->sc_rngfirst = 0;
  855                 else
  856                         (*sc->sc_harvest)(sc->sc_rndtest,
  857                                 num, sizeof (num[0]));
  858         }
  859 
  860         callout_reset(&sc->sc_rngto, sc->sc_rnghz, hifn_rng, sc);
  861 #undef RANDOM_BITS
  862 }
  863 
  864 static void
  865 hifn_puc_wait(struct hifn_softc *sc)
  866 {
  867         int i;
  868 
  869         for (i = 5000; i > 0; i--) {
  870                 DELAY(1);
  871                 if (!(READ_REG_0(sc, HIFN_0_PUCTRL) & HIFN_PUCTRL_RESET))
  872                         break;
  873         }
  874         if (!i)
  875                 device_printf(sc->sc_dev, "proc unit did not reset\n");
  876 }
  877 
  878 /*
  879  * Reset the processing unit.
  880  */
  881 static void
  882 hifn_reset_puc(struct hifn_softc *sc)
  883 {
  884         /* Reset processing unit */
  885         WRITE_REG_0(sc, HIFN_0_PUCTRL, HIFN_PUCTRL_DMAENA);
  886         hifn_puc_wait(sc);
  887 }
  888 
  889 /*
  890  * Set the Retry and TRDY registers; note that we set them to
  891  * zero because the 7811 locks up when forced to retry (section
  892  * 3.6 of "Specification Update SU-0014-04".  Not clear if we
  893  * should do this for all Hifn parts, but it doesn't seem to hurt.
  894  */
  895 static void
  896 hifn_set_retry(struct hifn_softc *sc)
  897 {
  898         /* NB: RETRY only responds to 8-bit reads/writes */
  899         pci_write_config(sc->sc_dev, HIFN_RETRY_TIMEOUT, 0, 1);
  900         pci_write_config(sc->sc_dev, HIFN_TRDY_TIMEOUT, 0, 4);
  901 }
  902 
  903 /*
  904  * Resets the board.  Values in the regesters are left as is
  905  * from the reset (i.e. initial values are assigned elsewhere).
  906  */
  907 static void
  908 hifn_reset_board(struct hifn_softc *sc, int full)
  909 {
  910         u_int32_t reg;
  911 
  912         /*
  913          * Set polling in the DMA configuration register to zero.  0x7 avoids
  914          * resetting the board and zeros out the other fields.
  915          */
  916         WRITE_REG_1(sc, HIFN_1_DMA_CNFG, HIFN_DMACNFG_MSTRESET |
  917             HIFN_DMACNFG_DMARESET | HIFN_DMACNFG_MODE);
  918 
  919         /*
  920          * Now that polling has been disabled, we have to wait 1 ms
  921          * before resetting the board.
  922          */
  923         DELAY(1000);
  924 
  925         /* Reset the DMA unit */
  926         if (full) {
  927                 WRITE_REG_1(sc, HIFN_1_DMA_CNFG, HIFN_DMACNFG_MODE);
  928                 DELAY(1000);
  929         } else {
  930                 WRITE_REG_1(sc, HIFN_1_DMA_CNFG,
  931                     HIFN_DMACNFG_MODE | HIFN_DMACNFG_MSTRESET);
  932                 hifn_reset_puc(sc);
  933         }
  934 
  935         KASSERT(sc->sc_dma != NULL, ("hifn_reset_board: null DMA tag!"));
  936         bzero(sc->sc_dma, sizeof(*sc->sc_dma));
  937 
  938         /* Bring dma unit out of reset */
  939         WRITE_REG_1(sc, HIFN_1_DMA_CNFG, HIFN_DMACNFG_MSTRESET |
  940             HIFN_DMACNFG_DMARESET | HIFN_DMACNFG_MODE);
  941 
  942         hifn_puc_wait(sc);
  943         hifn_set_retry(sc);
  944 
  945         if (sc->sc_flags & HIFN_IS_7811) {
  946                 for (reg = 0; reg < 1000; reg++) {
  947                         if (READ_REG_1(sc, HIFN_1_7811_MIPSRST) &
  948                             HIFN_MIPSRST_CRAMINIT)
  949                                 break;
  950                         DELAY(1000);
  951                 }
  952                 if (reg == 1000)
  953                         printf(": cram init timeout\n");
  954         }
  955 }
  956 
  957 static u_int32_t
  958 hifn_next_signature(u_int32_t a, u_int cnt)
  959 {
  960         int i;
  961         u_int32_t v;
  962 
  963         for (i = 0; i < cnt; i++) {
  964 
  965                 /* get the parity */
  966                 v = a & 0x80080125;
  967                 v ^= v >> 16;
  968                 v ^= v >> 8;
  969                 v ^= v >> 4;
  970                 v ^= v >> 2;
  971                 v ^= v >> 1;
  972 
  973                 a = (v & 1) ^ (a << 1);
  974         }
  975 
  976         return a;
  977 }
  978 
  979 struct pci2id {
  980         u_short         pci_vendor;
  981         u_short         pci_prod;
  982         char            card_id[13];
  983 };
  984 static struct pci2id pci2id[] = {
  985         {
  986                 PCI_VENDOR_HIFN,
  987                 PCI_PRODUCT_HIFN_7951,
  988                 { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  989                   0x00, 0x00, 0x00, 0x00, 0x00 }
  990         }, {
  991                 PCI_VENDOR_HIFN,
  992                 PCI_PRODUCT_HIFN_7955,
  993                 { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  994                   0x00, 0x00, 0x00, 0x00, 0x00 }
  995         }, {
  996                 PCI_VENDOR_HIFN,
  997                 PCI_PRODUCT_HIFN_7956,
  998                 { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  999                   0x00, 0x00, 0x00, 0x00, 0x00 }
 1000         }, {
 1001                 PCI_VENDOR_NETSEC,
 1002                 PCI_PRODUCT_NETSEC_7751,
 1003                 { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
 1004                   0x00, 0x00, 0x00, 0x00, 0x00 }
 1005         }, {
 1006                 PCI_VENDOR_INVERTEX,
 1007                 PCI_PRODUCT_INVERTEX_AEON,
 1008                 { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
 1009                   0x00, 0x00, 0x00, 0x00, 0x00 }
 1010         }, {
 1011                 PCI_VENDOR_HIFN,
 1012                 PCI_PRODUCT_HIFN_7811,
 1013                 { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
 1014                   0x00, 0x00, 0x00, 0x00, 0x00 }
 1015         }, {
 1016                 /*
 1017                  * Other vendors share this PCI ID as well, such as
 1018                  * http://www.powercrypt.com, and obviously they also
 1019                  * use the same key.
 1020                  */
 1021                 PCI_VENDOR_HIFN,
 1022                 PCI_PRODUCT_HIFN_7751,
 1023                 { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
 1024                   0x00, 0x00, 0x00, 0x00, 0x00 }
 1025         },
 1026 };
 1027 
 1028 /*
 1029  * Checks to see if crypto is already enabled.  If crypto isn't enable,
 1030  * "hifn_enable_crypto" is called to enable it.  The check is important,
 1031  * as enabling crypto twice will lock the board.
 1032  */
 1033 static int 
 1034 hifn_enable_crypto(struct hifn_softc *sc)
 1035 {
 1036         u_int32_t dmacfg, ramcfg, encl, addr, i;
 1037         char *offtbl = NULL;
 1038 
 1039         for (i = 0; i < sizeof(pci2id)/sizeof(pci2id[0]); i++) {
 1040                 if (pci2id[i].pci_vendor == pci_get_vendor(sc->sc_dev) &&
 1041                     pci2id[i].pci_prod == pci_get_device(sc->sc_dev)) {
 1042                         offtbl = pci2id[i].card_id;
 1043                         break;
 1044                 }
 1045         }
 1046         if (offtbl == NULL) {
 1047                 device_printf(sc->sc_dev, "Unknown card!\n");
 1048                 return (1);
 1049         }
 1050 
 1051         ramcfg = READ_REG_0(sc, HIFN_0_PUCNFG);
 1052         dmacfg = READ_REG_1(sc, HIFN_1_DMA_CNFG);
 1053 
 1054         /*
 1055          * The RAM config register's encrypt level bit needs to be set before
 1056          * every read performed on the encryption level register.
 1057          */
 1058         WRITE_REG_0(sc, HIFN_0_PUCNFG, ramcfg | HIFN_PUCNFG_CHIPID);
 1059 
 1060         encl = READ_REG_0(sc, HIFN_0_PUSTAT) & HIFN_PUSTAT_CHIPENA;
 1061 
 1062         /*
 1063          * Make sure we don't re-unlock.  Two unlocks kills chip until the
 1064          * next reboot.
 1065          */
 1066         if (encl == HIFN_PUSTAT_ENA_1 || encl == HIFN_PUSTAT_ENA_2) {
 1067 #ifdef HIFN_DEBUG
 1068                 if (hifn_debug)
 1069                         device_printf(sc->sc_dev,
 1070                             "Strong crypto already enabled!\n");
 1071 #endif
 1072                 goto report;
 1073         }
 1074 
 1075         if (encl != 0 && encl != HIFN_PUSTAT_ENA_0) {
 1076 #ifdef HIFN_DEBUG
 1077                 if (hifn_debug)
 1078                         device_printf(sc->sc_dev,
 1079                               "Unknown encryption level 0x%x\n", encl);
 1080 #endif
 1081                 return 1;
 1082         }
 1083 
 1084         WRITE_REG_1(sc, HIFN_1_DMA_CNFG, HIFN_DMACNFG_UNLOCK |
 1085             HIFN_DMACNFG_MSTRESET | HIFN_DMACNFG_DMARESET | HIFN_DMACNFG_MODE);
 1086         DELAY(1000);
 1087         addr = READ_REG_1(sc, HIFN_UNLOCK_SECRET1);
 1088         DELAY(1000);
 1089         WRITE_REG_1(sc, HIFN_UNLOCK_SECRET2, 0);
 1090         DELAY(1000);
 1091 
 1092         for (i = 0; i <= 12; i++) {
 1093                 addr = hifn_next_signature(addr, offtbl[i] + 0x101);
 1094                 WRITE_REG_1(sc, HIFN_UNLOCK_SECRET2, addr);
 1095 
 1096                 DELAY(1000);
 1097         }
 1098 
 1099         WRITE_REG_0(sc, HIFN_0_PUCNFG, ramcfg | HIFN_PUCNFG_CHIPID);
 1100         encl = READ_REG_0(sc, HIFN_0_PUSTAT) & HIFN_PUSTAT_CHIPENA;
 1101 
 1102 #ifdef HIFN_DEBUG
 1103         if (hifn_debug) {
 1104                 if (encl != HIFN_PUSTAT_ENA_1 && encl != HIFN_PUSTAT_ENA_2)
 1105                         device_printf(sc->sc_dev, "Engine is permanently "
 1106                                 "locked until next system reset!\n");
 1107                 else
 1108                         device_printf(sc->sc_dev, "Engine enabled "
 1109                                 "successfully!\n");
 1110         }
 1111 #endif
 1112 
 1113 report:
 1114         WRITE_REG_0(sc, HIFN_0_PUCNFG, ramcfg);
 1115         WRITE_REG_1(sc, HIFN_1_DMA_CNFG, dmacfg);
 1116 
 1117         switch (encl) {
 1118         case HIFN_PUSTAT_ENA_1:
 1119         case HIFN_PUSTAT_ENA_2:
 1120                 break;
 1121         case HIFN_PUSTAT_ENA_0:
 1122         default:
 1123                 device_printf(sc->sc_dev, "disabled");
 1124                 break;
 1125         }
 1126 
 1127         return 0;
 1128 }
 1129 
 1130 /*
 1131  * Give initial values to the registers listed in the "Register Space"
 1132  * section of the HIFN Software Development reference manual.
 1133  */
 1134 static void 
 1135 hifn_init_pci_registers(struct hifn_softc *sc)
 1136 {
 1137         /* write fixed values needed by the Initialization registers */
 1138         WRITE_REG_0(sc, HIFN_0_PUCTRL, HIFN_PUCTRL_DMAENA);
 1139         WRITE_REG_0(sc, HIFN_0_FIFOCNFG, HIFN_FIFOCNFG_THRESHOLD);
 1140         WRITE_REG_0(sc, HIFN_0_PUIER, HIFN_PUIER_DSTOVER);
 1141 
 1142         /* write all 4 ring address registers */
 1143         WRITE_REG_1(sc, HIFN_1_DMA_CRAR, sc->sc_dma_physaddr +
 1144             offsetof(struct hifn_dma, cmdr[0]));
 1145         WRITE_REG_1(sc, HIFN_1_DMA_SRAR, sc->sc_dma_physaddr +
 1146             offsetof(struct hifn_dma, srcr[0]));
 1147         WRITE_REG_1(sc, HIFN_1_DMA_DRAR, sc->sc_dma_physaddr +
 1148             offsetof(struct hifn_dma, dstr[0]));
 1149         WRITE_REG_1(sc, HIFN_1_DMA_RRAR, sc->sc_dma_physaddr +
 1150             offsetof(struct hifn_dma, resr[0]));
 1151 
 1152         DELAY(2000);
 1153 
 1154         /* write status register */
 1155         WRITE_REG_1(sc, HIFN_1_DMA_CSR,
 1156             HIFN_DMACSR_D_CTRL_DIS | HIFN_DMACSR_R_CTRL_DIS |
 1157             HIFN_DMACSR_S_CTRL_DIS | HIFN_DMACSR_C_CTRL_DIS |
 1158             HIFN_DMACSR_D_ABORT | HIFN_DMACSR_D_DONE | HIFN_DMACSR_D_LAST |
 1159             HIFN_DMACSR_D_WAIT | HIFN_DMACSR_D_OVER |
 1160             HIFN_DMACSR_R_ABORT | HIFN_DMACSR_R_DONE | HIFN_DMACSR_R_LAST |
 1161             HIFN_DMACSR_R_WAIT | HIFN_DMACSR_R_OVER |
 1162             HIFN_DMACSR_S_ABORT | HIFN_DMACSR_S_DONE | HIFN_DMACSR_S_LAST |
 1163             HIFN_DMACSR_S_WAIT |
 1164             HIFN_DMACSR_C_ABORT | HIFN_DMACSR_C_DONE | HIFN_DMACSR_C_LAST |
 1165             HIFN_DMACSR_C_WAIT |
 1166             HIFN_DMACSR_ENGINE |
 1167             ((sc->sc_flags & HIFN_HAS_PUBLIC) ?
 1168                 HIFN_DMACSR_PUBDONE : 0) |
 1169             ((sc->sc_flags & HIFN_IS_7811) ?
 1170                 HIFN_DMACSR_ILLW | HIFN_DMACSR_ILLR : 0));
 1171 
 1172         sc->sc_d_busy = sc->sc_r_busy = sc->sc_s_busy = sc->sc_c_busy = 0;
 1173         sc->sc_dmaier |= HIFN_DMAIER_R_DONE | HIFN_DMAIER_C_ABORT |
 1174             HIFN_DMAIER_D_OVER | HIFN_DMAIER_R_OVER |
 1175             HIFN_DMAIER_S_ABORT | HIFN_DMAIER_D_ABORT | HIFN_DMAIER_R_ABORT |
 1176             ((sc->sc_flags & HIFN_IS_7811) ?
 1177                 HIFN_DMAIER_ILLW | HIFN_DMAIER_ILLR : 0);
 1178         sc->sc_dmaier &= ~HIFN_DMAIER_C_WAIT;
 1179         WRITE_REG_1(sc, HIFN_1_DMA_IER, sc->sc_dmaier);
 1180 
 1181 
 1182         if (sc->sc_flags & HIFN_IS_7956) {
 1183                 u_int32_t pll;
 1184 
 1185                 WRITE_REG_0(sc, HIFN_0_PUCNFG, HIFN_PUCNFG_COMPSING |
 1186                     HIFN_PUCNFG_TCALLPHASES |
 1187                     HIFN_PUCNFG_TCDRVTOTEM | HIFN_PUCNFG_BUS32);
 1188 
 1189                 /* turn off the clocks and insure bypass is set */
 1190                 pll = READ_REG_1(sc, HIFN_1_PLL);
 1191                 pll = (pll &~ (HIFN_PLL_PK_CLK_SEL | HIFN_PLL_PE_CLK_SEL))
 1192                     | HIFN_PLL_BP;
 1193                 WRITE_REG_1(sc, HIFN_1_PLL, pll);
 1194                 DELAY(10*1000);         /* 10ms */
 1195                 /* change configuration */
 1196                 pll = (pll &~ HIFN_PLL_CONFIG) | sc->sc_pllconfig;
 1197                 WRITE_REG_1(sc, HIFN_1_PLL, pll);
 1198                 DELAY(10*1000);         /* 10ms */
 1199                 /* disable bypass */
 1200                 pll &= ~HIFN_PLL_BP;
 1201                 WRITE_REG_1(sc, HIFN_1_PLL, pll);
 1202                 /* enable clocks with new configuration */
 1203                 pll |= HIFN_PLL_PK_CLK_SEL | HIFN_PLL_PE_CLK_SEL;
 1204                 WRITE_REG_1(sc, HIFN_1_PLL, pll);
 1205         } else {
 1206                 WRITE_REG_0(sc, HIFN_0_PUCNFG, HIFN_PUCNFG_COMPSING |
 1207                     HIFN_PUCNFG_DRFR_128 | HIFN_PUCNFG_TCALLPHASES |
 1208                     HIFN_PUCNFG_TCDRVTOTEM | HIFN_PUCNFG_BUS32 |
 1209                     (sc->sc_drammodel ? HIFN_PUCNFG_DRAM : HIFN_PUCNFG_SRAM));
 1210         }
 1211 
 1212         WRITE_REG_0(sc, HIFN_0_PUISR, HIFN_PUISR_DSTOVER);
 1213         WRITE_REG_1(sc, HIFN_1_DMA_CNFG, HIFN_DMACNFG_MSTRESET |
 1214             HIFN_DMACNFG_DMARESET | HIFN_DMACNFG_MODE | HIFN_DMACNFG_LAST |
 1215             ((HIFN_POLL_FREQUENCY << 16 ) & HIFN_DMACNFG_POLLFREQ) |
 1216             ((HIFN_POLL_SCALAR << 8) & HIFN_DMACNFG_POLLINVAL));
 1217 }
 1218 
 1219 /*
 1220  * The maximum number of sessions supported by the card
 1221  * is dependent on the amount of context ram, which
 1222  * encryption algorithms are enabled, and how compression
 1223  * is configured.  This should be configured before this
 1224  * routine is called.
 1225  */
 1226 static void
 1227 hifn_sessions(struct hifn_softc *sc)
 1228 {
 1229         u_int32_t pucnfg;
 1230         int ctxsize;
 1231 
 1232         pucnfg = READ_REG_0(sc, HIFN_0_PUCNFG);
 1233 
 1234         if (pucnfg & HIFN_PUCNFG_COMPSING) {
 1235                 if (pucnfg & HIFN_PUCNFG_ENCCNFG)
 1236                         ctxsize = 128;
 1237                 else
 1238                         ctxsize = 512;
 1239                 /*
 1240                  * 7955/7956 has internal context memory of 32K
 1241                  */
 1242                 if (sc->sc_flags & HIFN_IS_7956)
 1243                         sc->sc_maxses = 32768 / ctxsize;
 1244                 else
 1245                         sc->sc_maxses = 1 +
 1246                             ((sc->sc_ramsize - 32768) / ctxsize);
 1247         } else
 1248                 sc->sc_maxses = sc->sc_ramsize / 16384;
 1249 
 1250         if (sc->sc_maxses > 2048)
 1251                 sc->sc_maxses = 2048;
 1252 }
 1253 
 1254 /*
 1255  * Determine ram type (sram or dram).  Board should be just out of a reset
 1256  * state when this is called.
 1257  */
 1258 static int
 1259 hifn_ramtype(struct hifn_softc *sc)
 1260 {
 1261         u_int8_t data[8], dataexpect[8];
 1262         int i;
 1263 
 1264         for (i = 0; i < sizeof(data); i++)
 1265                 data[i] = dataexpect[i] = 0x55;
 1266         if (hifn_writeramaddr(sc, 0, data))
 1267                 return (-1);
 1268         if (hifn_readramaddr(sc, 0, data))
 1269                 return (-1);
 1270         if (bcmp(data, dataexpect, sizeof(data)) != 0) {
 1271                 sc->sc_drammodel = 1;
 1272                 return (0);
 1273         }
 1274 
 1275         for (i = 0; i < sizeof(data); i++)
 1276                 data[i] = dataexpect[i] = 0xaa;
 1277         if (hifn_writeramaddr(sc, 0, data))
 1278                 return (-1);
 1279         if (hifn_readramaddr(sc, 0, data))
 1280                 return (-1);
 1281         if (bcmp(data, dataexpect, sizeof(data)) != 0) {
 1282                 sc->sc_drammodel = 1;
 1283                 return (0);
 1284         }
 1285 
 1286         return (0);
 1287 }
 1288 
 1289 #define HIFN_SRAM_MAX           (32 << 20)
 1290 #define HIFN_SRAM_STEP_SIZE     16384
 1291 #define HIFN_SRAM_GRANULARITY   (HIFN_SRAM_MAX / HIFN_SRAM_STEP_SIZE)
 1292 
 1293 static int
 1294 hifn_sramsize(struct hifn_softc *sc)
 1295 {
 1296         u_int32_t a;
 1297         u_int8_t data[8];
 1298         u_int8_t dataexpect[sizeof(data)];
 1299         int32_t i;
 1300 
 1301         for (i = 0; i < sizeof(data); i++)
 1302                 data[i] = dataexpect[i] = i ^ 0x5a;
 1303 
 1304         for (i = HIFN_SRAM_GRANULARITY - 1; i >= 0; i--) {
 1305                 a = i * HIFN_SRAM_STEP_SIZE;
 1306                 bcopy(&i, data, sizeof(i));
 1307                 hifn_writeramaddr(sc, a, data);
 1308         }
 1309 
 1310         for (i = 0; i < HIFN_SRAM_GRANULARITY; i++) {
 1311                 a = i * HIFN_SRAM_STEP_SIZE;
 1312                 bcopy(&i, dataexpect, sizeof(i));
 1313                 if (hifn_readramaddr(sc, a, data) < 0)
 1314                         return (0);
 1315                 if (bcmp(data, dataexpect, sizeof(data)) != 0)
 1316                         return (0);
 1317                 sc->sc_ramsize = a + HIFN_SRAM_STEP_SIZE;
 1318         }
 1319 
 1320         return (0);
 1321 }
 1322 
 1323 /*
 1324  * XXX For dram boards, one should really try all of the
 1325  * HIFN_PUCNFG_DSZ_*'s.  This just assumes that PUCNFG
 1326  * is already set up correctly.
 1327  */
 1328 static int
 1329 hifn_dramsize(struct hifn_softc *sc)
 1330 {
 1331         u_int32_t cnfg;
 1332 
 1333         if (sc->sc_flags & HIFN_IS_7956) {
 1334                 /*
 1335                  * 7955/7956 have a fixed internal ram of only 32K.
 1336                  */
 1337                 sc->sc_ramsize = 32768;
 1338         } else {
 1339                 cnfg = READ_REG_0(sc, HIFN_0_PUCNFG) &
 1340                     HIFN_PUCNFG_DRAMMASK;
 1341                 sc->sc_ramsize = 1 << ((cnfg >> 13) + 18);
 1342         }
 1343         return (0);
 1344 }
 1345 
 1346 static void
 1347 hifn_alloc_slot(struct hifn_softc *sc, int *cmdp, int *srcp, int *dstp, int *resp)
 1348 {
 1349         struct hifn_dma *dma = sc->sc_dma;
 1350 
 1351         if (dma->cmdi == HIFN_D_CMD_RSIZE) {
 1352                 dma->cmdi = 0;
 1353                 dma->cmdr[HIFN_D_CMD_RSIZE].l = htole32(HIFN_D_VALID |
 1354                     HIFN_D_JUMP | HIFN_D_MASKDONEIRQ);
 1355                 HIFN_CMDR_SYNC(sc, HIFN_D_CMD_RSIZE,
 1356                     BUS_DMASYNC_PREWRITE | BUS_DMASYNC_PREREAD);
 1357         }
 1358         *cmdp = dma->cmdi++;
 1359         dma->cmdk = dma->cmdi;
 1360 
 1361         if (dma->srci == HIFN_D_SRC_RSIZE) {
 1362                 dma->srci = 0;
 1363                 dma->srcr[HIFN_D_SRC_RSIZE].l = htole32(HIFN_D_VALID |
 1364                     HIFN_D_JUMP | HIFN_D_MASKDONEIRQ);
 1365                 HIFN_SRCR_SYNC(sc, HIFN_D_SRC_RSIZE,
 1366                     BUS_DMASYNC_PREWRITE | BUS_DMASYNC_PREREAD);
 1367         }
 1368         *srcp = dma->srci++;
 1369         dma->srck = dma->srci;
 1370 
 1371         if (dma->dsti == HIFN_D_DST_RSIZE) {
 1372                 dma->dsti = 0;
 1373                 dma->dstr[HIFN_D_DST_RSIZE].l = htole32(HIFN_D_VALID |
 1374                     HIFN_D_JUMP | HIFN_D_MASKDONEIRQ);
 1375                 HIFN_DSTR_SYNC(sc, HIFN_D_DST_RSIZE,
 1376                     BUS_DMASYNC_PREWRITE | BUS_DMASYNC_PREREAD);
 1377         }
 1378         *dstp = dma->dsti++;
 1379         dma->dstk = dma->dsti;
 1380 
 1381         if (dma->resi == HIFN_D_RES_RSIZE) {
 1382                 dma->resi = 0;
 1383                 dma->resr[HIFN_D_RES_RSIZE].l = htole32(HIFN_D_VALID |
 1384                     HIFN_D_JUMP | HIFN_D_MASKDONEIRQ);
 1385                 HIFN_RESR_SYNC(sc, HIFN_D_RES_RSIZE,
 1386                     BUS_DMASYNC_PREWRITE | BUS_DMASYNC_PREREAD);
 1387         }
 1388         *resp = dma->resi++;
 1389         dma->resk = dma->resi;
 1390 }
 1391 
 1392 static int
 1393 hifn_writeramaddr(struct hifn_softc *sc, int addr, u_int8_t *data)
 1394 {
 1395         struct hifn_dma *dma = sc->sc_dma;
 1396         hifn_base_command_t wc;
 1397         const u_int32_t masks = HIFN_D_VALID | HIFN_D_LAST | HIFN_D_MASKDONEIRQ;
 1398         int r, cmdi, resi, srci, dsti;
 1399 
 1400         wc.masks = htole16(3 << 13);
 1401         wc.session_num = htole16(addr >> 14);
 1402         wc.total_source_count = htole16(8);
 1403         wc.total_dest_count = htole16(addr & 0x3fff);
 1404 
 1405         hifn_alloc_slot(sc, &cmdi, &srci, &dsti, &resi);
 1406 
 1407         WRITE_REG_1(sc, HIFN_1_DMA_CSR,
 1408             HIFN_DMACSR_C_CTRL_ENA | HIFN_DMACSR_S_CTRL_ENA |
 1409             HIFN_DMACSR_D_CTRL_ENA | HIFN_DMACSR_R_CTRL_ENA);
 1410 
 1411         /* build write command */
 1412         bzero(dma->command_bufs[cmdi], HIFN_MAX_COMMAND);
 1413         *(hifn_base_command_t *)dma->command_bufs[cmdi] = wc;
 1414         bcopy(data, &dma->test_src, sizeof(dma->test_src));
 1415 
 1416         dma->srcr[srci].p = htole32(sc->sc_dma_physaddr
 1417             + offsetof(struct hifn_dma, test_src));
 1418         dma->dstr[dsti].p = htole32(sc->sc_dma_physaddr
 1419             + offsetof(struct hifn_dma, test_dst));
 1420 
 1421         dma->cmdr[cmdi].l = htole32(16 | masks);
 1422         dma->srcr[srci].l = htole32(8 | masks);
 1423         dma->dstr[dsti].l = htole32(4 | masks);
 1424         dma->resr[resi].l = htole32(4 | masks);
 1425 
 1426         bus_dmamap_sync(sc->sc_dmat, sc->sc_dmamap,
 1427             BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE);
 1428 
 1429         for (r = 10000; r >= 0; r--) {
 1430                 DELAY(10);
 1431                 bus_dmamap_sync(sc->sc_dmat, sc->sc_dmamap,
 1432                     BUS_DMASYNC_POSTREAD | BUS_DMASYNC_POSTWRITE);
 1433                 if ((dma->resr[resi].l & htole32(HIFN_D_VALID)) == 0)
 1434                         break;
 1435                 bus_dmamap_sync(sc->sc_dmat, sc->sc_dmamap,
 1436                     BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE);
 1437         }
 1438         if (r == 0) {
 1439                 device_printf(sc->sc_dev, "writeramaddr -- "
 1440                     "result[%d](addr %d) still valid\n", resi, addr);
 1441                 r = -1;
 1442                 return (-1);
 1443         } else
 1444                 r = 0;
 1445 
 1446         WRITE_REG_1(sc, HIFN_1_DMA_CSR,
 1447             HIFN_DMACSR_C_CTRL_DIS | HIFN_DMACSR_S_CTRL_DIS |
 1448             HIFN_DMACSR_D_CTRL_DIS | HIFN_DMACSR_R_CTRL_DIS);
 1449 
 1450         return (r);
 1451 }
 1452 
 1453 static int
 1454 hifn_readramaddr(struct hifn_softc *sc, int addr, u_int8_t *data)
 1455 {
 1456         struct hifn_dma *dma = sc->sc_dma;
 1457         hifn_base_command_t rc;
 1458         const u_int32_t masks = HIFN_D_VALID | HIFN_D_LAST | HIFN_D_MASKDONEIRQ;
 1459         int r, cmdi, srci, dsti, resi;
 1460 
 1461         rc.masks = htole16(2 << 13);
 1462         rc.session_num = htole16(addr >> 14);
 1463         rc.total_source_count = htole16(addr & 0x3fff);
 1464         rc.total_dest_count = htole16(8);
 1465 
 1466         hifn_alloc_slot(sc, &cmdi, &srci, &dsti, &resi);
 1467 
 1468         WRITE_REG_1(sc, HIFN_1_DMA_CSR,
 1469             HIFN_DMACSR_C_CTRL_ENA | HIFN_DMACSR_S_CTRL_ENA |
 1470             HIFN_DMACSR_D_CTRL_ENA | HIFN_DMACSR_R_CTRL_ENA);
 1471 
 1472         bzero(dma->command_bufs[cmdi], HIFN_MAX_COMMAND);
 1473         *(hifn_base_command_t *)dma->command_bufs[cmdi] = rc;
 1474 
 1475         dma->srcr[srci].p = htole32(sc->sc_dma_physaddr +
 1476             offsetof(struct hifn_dma, test_src));
 1477         dma->test_src = 0;
 1478         dma->dstr[dsti].p =  htole32(sc->sc_dma_physaddr +
 1479             offsetof(struct hifn_dma, test_dst));
 1480         dma->test_dst = 0;
 1481         dma->cmdr[cmdi].l = htole32(8 | masks);
 1482         dma->srcr[srci].l = htole32(8 | masks);
 1483         dma->dstr[dsti].l = htole32(8 | masks);
 1484         dma->resr[resi].l = htole32(HIFN_MAX_RESULT | masks);
 1485 
 1486         bus_dmamap_sync(sc->sc_dmat, sc->sc_dmamap,
 1487             BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE);
 1488 
 1489         for (r = 10000; r >= 0; r--) {
 1490                 DELAY(10);
 1491                 bus_dmamap_sync(sc->sc_dmat, sc->sc_dmamap,
 1492                     BUS_DMASYNC_POSTREAD | BUS_DMASYNC_POSTWRITE);
 1493                 if ((dma->resr[resi].l & htole32(HIFN_D_VALID)) == 0)
 1494                         break;
 1495                 bus_dmamap_sync(sc->sc_dmat, sc->sc_dmamap,
 1496                     BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE);
 1497         }
 1498         if (r == 0) {
 1499                 device_printf(sc->sc_dev, "readramaddr -- "
 1500                     "result[%d](addr %d) still valid\n", resi, addr);
 1501                 r = -1;
 1502         } else {
 1503                 r = 0;
 1504                 bcopy(&dma->test_dst, data, sizeof(dma->test_dst));
 1505         }
 1506 
 1507         WRITE_REG_1(sc, HIFN_1_DMA_CSR,
 1508             HIFN_DMACSR_C_CTRL_DIS | HIFN_DMACSR_S_CTRL_DIS |
 1509             HIFN_DMACSR_D_CTRL_DIS | HIFN_DMACSR_R_CTRL_DIS);
 1510 
 1511         return (r);
 1512 }
 1513 
 1514 /*
 1515  * Initialize the descriptor rings.
 1516  */
 1517 static void 
 1518 hifn_init_dma(struct hifn_softc *sc)
 1519 {
 1520         struct hifn_dma *dma = sc->sc_dma;
 1521         int i;
 1522 
 1523         hifn_set_retry(sc);
 1524 
 1525         /* initialize static pointer values */
 1526         for (i = 0; i < HIFN_D_CMD_RSIZE; i++)
 1527                 dma->cmdr[i].p = htole32(sc->sc_dma_physaddr +
 1528                     offsetof(struct hifn_dma, command_bufs[i][0]));
 1529         for (i = 0; i < HIFN_D_RES_RSIZE; i++)
 1530                 dma->resr[i].p = htole32(sc->sc_dma_physaddr +
 1531                     offsetof(struct hifn_dma, result_bufs[i][0]));
 1532 
 1533         dma->cmdr[HIFN_D_CMD_RSIZE].p =
 1534             htole32(sc->sc_dma_physaddr + offsetof(struct hifn_dma, cmdr[0]));
 1535         dma->srcr[HIFN_D_SRC_RSIZE].p =
 1536             htole32(sc->sc_dma_physaddr + offsetof(struct hifn_dma, srcr[0]));
 1537         dma->dstr[HIFN_D_DST_RSIZE].p =
 1538             htole32(sc->sc_dma_physaddr + offsetof(struct hifn_dma, dstr[0]));
 1539         dma->resr[HIFN_D_RES_RSIZE].p =
 1540             htole32(sc->sc_dma_physaddr + offsetof(struct hifn_dma, resr[0]));
 1541 
 1542         dma->cmdu = dma->srcu = dma->dstu = dma->resu = 0;
 1543         dma->cmdi = dma->srci = dma->dsti = dma->resi = 0;
 1544         dma->cmdk = dma->srck = dma->dstk = dma->resk = 0;
 1545 }
 1546 
 1547 /*
 1548  * Writes out the raw command buffer space.  Returns the
 1549  * command buffer size.
 1550  */
 1551 static u_int
 1552 hifn_write_command(struct hifn_command *cmd, u_int8_t *buf)
 1553 {
 1554         u_int8_t *buf_pos;
 1555         hifn_base_command_t *base_cmd;
 1556         hifn_mac_command_t *mac_cmd;
 1557         hifn_crypt_command_t *cry_cmd;
 1558         int using_mac, using_crypt, len, ivlen;
 1559         u_int32_t dlen, slen;
 1560 
 1561         buf_pos = buf;
 1562         using_mac = cmd->base_masks & HIFN_BASE_CMD_MAC;
 1563         using_crypt = cmd->base_masks & HIFN_BASE_CMD_CRYPT;
 1564 
 1565         base_cmd = (hifn_base_command_t *)buf_pos;
 1566         base_cmd->masks = htole16(cmd->base_masks);
 1567         slen = cmd->src_mapsize;
 1568         if (cmd->sloplen)
 1569                 dlen = cmd->dst_mapsize - cmd->sloplen + sizeof(u_int32_t);
 1570         else
 1571                 dlen = cmd->dst_mapsize;
 1572         base_cmd->total_source_count = htole16(slen & HIFN_BASE_CMD_LENMASK_LO);
 1573         base_cmd->total_dest_count = htole16(dlen & HIFN_BASE_CMD_LENMASK_LO);
 1574         dlen >>= 16;
 1575         slen >>= 16;
 1576         base_cmd->session_num = htole16(
 1577             ((slen << HIFN_BASE_CMD_SRCLEN_S) & HIFN_BASE_CMD_SRCLEN_M) |
 1578             ((dlen << HIFN_BASE_CMD_DSTLEN_S) & HIFN_BASE_CMD_DSTLEN_M));
 1579         buf_pos += sizeof(hifn_base_command_t);
 1580 
 1581         if (using_mac) {
 1582                 mac_cmd = (hifn_mac_command_t *)buf_pos;
 1583                 dlen = cmd->maccrd->crd_len;
 1584                 mac_cmd->source_count = htole16(dlen & 0xffff);
 1585                 dlen >>= 16;
 1586                 mac_cmd->masks = htole16(cmd->mac_masks |
 1587                     ((dlen << HIFN_MAC_CMD_SRCLEN_S) & HIFN_MAC_CMD_SRCLEN_M));
 1588                 mac_cmd->header_skip = htole16(cmd->maccrd->crd_skip);
 1589                 mac_cmd->reserved = 0;
 1590                 buf_pos += sizeof(hifn_mac_command_t);
 1591         }
 1592 
 1593         if (using_crypt) {
 1594                 cry_cmd = (hifn_crypt_command_t *)buf_pos;
 1595                 dlen = cmd->enccrd->crd_len;
 1596                 cry_cmd->source_count = htole16(dlen & 0xffff);
 1597                 dlen >>= 16;
 1598                 cry_cmd->masks = htole16(cmd->cry_masks |
 1599                     ((dlen << HIFN_CRYPT_CMD_SRCLEN_S) & HIFN_CRYPT_CMD_SRCLEN_M));
 1600                 cry_cmd->header_skip = htole16(cmd->enccrd->crd_skip);
 1601                 cry_cmd->reserved = 0;
 1602                 buf_pos += sizeof(hifn_crypt_command_t);
 1603         }
 1604 
 1605         if (using_mac && cmd->mac_masks & HIFN_MAC_CMD_NEW_KEY) {
 1606                 bcopy(cmd->mac, buf_pos, HIFN_MAC_KEY_LENGTH);
 1607                 buf_pos += HIFN_MAC_KEY_LENGTH;
 1608         }
 1609 
 1610         if (using_crypt && cmd->cry_masks & HIFN_CRYPT_CMD_NEW_KEY) {
 1611                 switch (cmd->cry_masks & HIFN_CRYPT_CMD_ALG_MASK) {
 1612                 case HIFN_CRYPT_CMD_ALG_3DES:
 1613                         bcopy(cmd->ck, buf_pos, HIFN_3DES_KEY_LENGTH);
 1614                         buf_pos += HIFN_3DES_KEY_LENGTH;
 1615                         break;
 1616                 case HIFN_CRYPT_CMD_ALG_DES:
 1617                         bcopy(cmd->ck, buf_pos, HIFN_DES_KEY_LENGTH);
 1618                         buf_pos += HIFN_DES_KEY_LENGTH;
 1619                         break;
 1620                 case HIFN_CRYPT_CMD_ALG_RC4:
 1621                         len = 256;
 1622                         do {
 1623                                 int clen;
 1624 
 1625                                 clen = MIN(cmd->cklen, len);
 1626                                 bcopy(cmd->ck, buf_pos, clen);
 1627                                 len -= clen;
 1628                                 buf_pos += clen;
 1629                         } while (len > 0);
 1630                         bzero(buf_pos, 4);
 1631                         buf_pos += 4;
 1632                         break;
 1633                 case HIFN_CRYPT_CMD_ALG_AES:
 1634                         /*
 1635                          * AES keys are variable 128, 192 and
 1636                          * 256 bits (16, 24 and 32 bytes).
 1637                          */
 1638                         bcopy(cmd->ck, buf_pos, cmd->cklen);
 1639                         buf_pos += cmd->cklen;
 1640                         break;
 1641                 }
 1642         }
 1643 
 1644         if (using_crypt && cmd->cry_masks & HIFN_CRYPT_CMD_NEW_IV) {
 1645                 switch (cmd->cry_masks & HIFN_CRYPT_CMD_ALG_MASK) {
 1646                 case HIFN_CRYPT_CMD_ALG_AES:
 1647                         ivlen = HIFN_AES_IV_LENGTH;
 1648                         break;
 1649                 default:
 1650                         ivlen = HIFN_IV_LENGTH;
 1651                         break;
 1652                 }
 1653                 bcopy(cmd->iv, buf_pos, ivlen);
 1654                 buf_pos += ivlen;
 1655         }
 1656 
 1657         if ((cmd->base_masks & (HIFN_BASE_CMD_MAC|HIFN_BASE_CMD_CRYPT)) == 0) {
 1658                 bzero(buf_pos, 8);
 1659                 buf_pos += 8;
 1660         }
 1661 
 1662         return (buf_pos - buf);
 1663 }
 1664 
 1665 static int
 1666 hifn_dmamap_aligned(struct hifn_operand *op)
 1667 {
 1668         int i;
 1669 
 1670         for (i = 0; i < op->nsegs; i++) {
 1671                 if (op->segs[i].ds_addr & 3)
 1672                         return (0);
 1673                 if ((i != (op->nsegs - 1)) && (op->segs[i].ds_len & 3))
 1674                         return (0);
 1675         }
 1676         return (1);
 1677 }
 1678 
 1679 static int
 1680 hifn_dmamap_load_dst(struct hifn_softc *sc, struct hifn_command *cmd)
 1681 {
 1682         struct hifn_dma *dma = sc->sc_dma;
 1683         struct hifn_operand *dst = &cmd->dst;
 1684         u_int32_t p, l;
 1685         int idx, used = 0, i;
 1686 
 1687         idx = dma->dsti;
 1688         for (i = 0; i < dst->nsegs - 1; i++) {
 1689                 dma->dstr[idx].p = htole32(dst->segs[i].ds_addr);
 1690                 dma->dstr[idx].l = htole32(HIFN_D_VALID |
 1691                     HIFN_D_MASKDONEIRQ | dst->segs[i].ds_len);
 1692                 HIFN_DSTR_SYNC(sc, idx,
 1693                     BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE);
 1694                 used++;
 1695 
 1696                 if (++idx == HIFN_D_DST_RSIZE) {
 1697                         dma->dstr[idx].l = htole32(HIFN_D_VALID |
 1698                             HIFN_D_JUMP | HIFN_D_MASKDONEIRQ);
 1699                         HIFN_DSTR_SYNC(sc, idx,
 1700                             BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE);
 1701                         idx = 0;
 1702                 }
 1703         }
 1704 
 1705         if (cmd->sloplen == 0) {
 1706                 p = dst->segs[i].ds_addr;
 1707                 l = HIFN_D_VALID | HIFN_D_MASKDONEIRQ | HIFN_D_LAST |
 1708                     dst->segs[i].ds_len;
 1709         } else {
 1710                 p = sc->sc_dma_physaddr +
 1711                     offsetof(struct hifn_dma, slop[cmd->slopidx]);
 1712                 l = HIFN_D_VALID | HIFN_D_MASKDONEIRQ | HIFN_D_LAST |
 1713                     sizeof(u_int32_t);
 1714 
 1715                 if ((dst->segs[i].ds_len - cmd->sloplen) != 0) {
 1716                         dma->dstr[idx].p = htole32(dst->segs[i].ds_addr);
 1717                         dma->dstr[idx].l = htole32(HIFN_D_VALID |
 1718                             HIFN_D_MASKDONEIRQ |
 1719                             (dst->segs[i].ds_len - cmd->sloplen));
 1720                         HIFN_DSTR_SYNC(sc, idx,
 1721                             BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE);
 1722                         used++;
 1723 
 1724                         if (++idx == HIFN_D_DST_RSIZE) {
 1725                                 dma->dstr[idx].l = htole32(HIFN_D_VALID |
 1726                                     HIFN_D_JUMP | HIFN_D_MASKDONEIRQ);
 1727                                 HIFN_DSTR_SYNC(sc, idx,
 1728                                     BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE);
 1729                                 idx = 0;
 1730                         }
 1731                 }
 1732         }
 1733         dma->dstr[idx].p = htole32(p);
 1734         dma->dstr[idx].l = htole32(l);
 1735         HIFN_DSTR_SYNC(sc, idx, BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE);
 1736         used++;
 1737 
 1738         if (++idx == HIFN_D_DST_RSIZE) {
 1739                 dma->dstr[idx].l = htole32(HIFN_D_VALID | HIFN_D_JUMP |
 1740                     HIFN_D_MASKDONEIRQ);
 1741                 HIFN_DSTR_SYNC(sc, idx,
 1742                     BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE);
 1743                 idx = 0;
 1744         }
 1745 
 1746         dma->dsti = idx;
 1747         dma->dstu += used;
 1748         return (idx);
 1749 }
 1750 
 1751 static int
 1752 hifn_dmamap_load_src(struct hifn_softc *sc, struct hifn_command *cmd)
 1753 {
 1754         struct hifn_dma *dma = sc->sc_dma;
 1755         struct hifn_operand *src = &cmd->src;
 1756         int idx, i;
 1757         u_int32_t last = 0;
 1758 
 1759         idx = dma->srci;
 1760         for (i = 0; i < src->nsegs; i++) {
 1761                 if (i == src->nsegs - 1)
 1762                         last = HIFN_D_LAST;
 1763 
 1764                 dma->srcr[idx].p = htole32(src->segs[i].ds_addr);
 1765                 dma->srcr[idx].l = htole32(src->segs[i].ds_len |
 1766                     HIFN_D_VALID | HIFN_D_MASKDONEIRQ | last);
 1767                 HIFN_SRCR_SYNC(sc, idx,
 1768                     BUS_DMASYNC_PREWRITE | BUS_DMASYNC_PREREAD);
 1769 
 1770                 if (++idx == HIFN_D_SRC_RSIZE) {
 1771                         dma->srcr[idx].l = htole32(HIFN_D_VALID |
 1772                             HIFN_D_JUMP | HIFN_D_MASKDONEIRQ);
 1773                         HIFN_SRCR_SYNC(sc, HIFN_D_SRC_RSIZE,
 1774                             BUS_DMASYNC_PREWRITE | BUS_DMASYNC_PREREAD);
 1775                         idx = 0;
 1776                 }
 1777         }
 1778         dma->srci = idx;
 1779         dma->srcu += src->nsegs;
 1780         return (idx);
 1781 } 
 1782 
 1783 static void
 1784 hifn_op_cb(void* arg, bus_dma_segment_t *seg, int nsegs, bus_size_t mapsize, int error)
 1785 {
 1786         struct hifn_operand *op = arg;
 1787 
 1788         KASSERT(nsegs <= MAX_SCATTER,
 1789                 ("hifn_op_cb: too many DMA segments (%u > %u) "
 1790                  "returned when mapping operand", nsegs, MAX_SCATTER));
 1791         op->mapsize = mapsize;
 1792         op->nsegs = nsegs;
 1793         bcopy(seg, op->segs, nsegs * sizeof (seg[0]));
 1794 }
 1795 
 1796 static int 
 1797 hifn_crypto(
 1798         struct hifn_softc *sc,
 1799         struct hifn_command *cmd,
 1800         struct cryptop *crp,
 1801         int hint)
 1802 {
 1803         struct  hifn_dma *dma = sc->sc_dma;
 1804         u_int32_t cmdlen;
 1805         int cmdi, resi, err = 0;
 1806 
 1807         /*
 1808          * need 1 cmd, and 1 res
 1809          *
 1810          * NB: check this first since it's easy.
 1811          */
 1812         HIFN_LOCK(sc);
 1813         if ((dma->cmdu + 1) > HIFN_D_CMD_RSIZE ||
 1814             (dma->resu + 1) > HIFN_D_RES_RSIZE) {
 1815 #ifdef HIFN_DEBUG
 1816                 if (hifn_debug) {
 1817                         device_printf(sc->sc_dev,
 1818                                 "cmd/result exhaustion, cmdu %u resu %u\n",
 1819                                 dma->cmdu, dma->resu);
 1820                 }
 1821 #endif
 1822                 hifnstats.hst_nomem_cr++;
 1823                 HIFN_UNLOCK(sc);
 1824                 return (ERESTART);
 1825         }
 1826 
 1827         if (bus_dmamap_create(sc->sc_dmat, BUS_DMA_NOWAIT, &cmd->src_map)) {
 1828                 hifnstats.hst_nomem_map++;
 1829                 HIFN_UNLOCK(sc);
 1830                 return (ENOMEM);
 1831         }
 1832 
 1833         if (crp->crp_flags & CRYPTO_F_IMBUF) {
 1834                 if (bus_dmamap_load_mbuf(sc->sc_dmat, cmd->src_map,
 1835                     cmd->src_m, hifn_op_cb, &cmd->src, BUS_DMA_NOWAIT)) {
 1836                         hifnstats.hst_nomem_load++;
 1837                         err = ENOMEM;
 1838                         goto err_srcmap1;
 1839                 }
 1840         } else if (crp->crp_flags & CRYPTO_F_IOV) {
 1841                 if (bus_dmamap_load_uio(sc->sc_dmat, cmd->src_map,
 1842                     cmd->src_io, hifn_op_cb, &cmd->src, BUS_DMA_NOWAIT)) {
 1843                         hifnstats.hst_nomem_load++;
 1844                         err = ENOMEM;
 1845                         goto err_srcmap1;
 1846                 }
 1847         } else {
 1848                 err = EINVAL;
 1849                 goto err_srcmap1;
 1850         }
 1851 
 1852         if (hifn_dmamap_aligned(&cmd->src)) {
 1853                 cmd->sloplen = cmd->src_mapsize & 3;
 1854                 cmd->dst = cmd->src;
 1855         } else {
 1856                 if (crp->crp_flags & CRYPTO_F_IOV) {
 1857                         err = EINVAL;
 1858                         goto err_srcmap;
 1859                 } else if (crp->crp_flags & CRYPTO_F_IMBUF) {
 1860                         int totlen, len;
 1861                         struct mbuf *m, *m0, *mlast;
 1862 
 1863                         KASSERT(cmd->dst_m == cmd->src_m,
 1864                                 ("hifn_crypto: dst_m initialized improperly"));
 1865                         hifnstats.hst_unaligned++;
 1866                         /*
 1867                          * Source is not aligned on a longword boundary.
 1868                          * Copy the data to insure alignment.  If we fail
 1869                          * to allocate mbufs or clusters while doing this
 1870                          * we return ERESTART so the operation is requeued
 1871                          * at the crypto later, but only if there are
 1872                          * ops already posted to the hardware; otherwise we
 1873                          * have no guarantee that we'll be re-entered.
 1874                          */
 1875                         totlen = cmd->src_mapsize;
 1876                         if (cmd->src_m->m_flags & M_PKTHDR) {
 1877                                 len = MHLEN;
 1878                                 MGETHDR(m0, M_DONTWAIT, MT_DATA);
 1879                                 if (m0 && !m_dup_pkthdr(m0, cmd->src_m, M_DONTWAIT)) {
 1880                                         m_free(m0);
 1881                                         m0 = NULL;
 1882                                 }
 1883                         } else {
 1884                                 len = MLEN;
 1885                                 MGET(m0, M_DONTWAIT, MT_DATA);
 1886                         }
 1887                         if (m0 == NULL) {
 1888                                 hifnstats.hst_nomem_mbuf++;
 1889                                 err = dma->cmdu ? ERESTART : ENOMEM;
 1890                                 goto err_srcmap;
 1891                         }
 1892                         if (totlen >= MINCLSIZE) {
 1893                                 MCLGET(m0, M_DONTWAIT);
 1894                                 if ((m0->m_flags & M_EXT) == 0) {
 1895                                         hifnstats.hst_nomem_mcl++;
 1896                                         err = dma->cmdu ? ERESTART : ENOMEM;
 1897                                         m_freem(m0);
 1898                                         goto err_srcmap;
 1899                                 }
 1900                                 len = MCLBYTES;
 1901                         }
 1902                         totlen -= len;
 1903                         m0->m_pkthdr.len = m0->m_len = len;
 1904                         mlast = m0;
 1905 
 1906                         while (totlen > 0) {
 1907                                 MGET(m, M_DONTWAIT, MT_DATA);
 1908                                 if (m == NULL) {
 1909                                         hifnstats.hst_nomem_mbuf++;
 1910                                         err = dma->cmdu ? ERESTART : ENOMEM;
 1911                                         m_freem(m0);
 1912                                         goto err_srcmap;
 1913                                 }
 1914                                 len = MLEN;
 1915                                 if (totlen >= MINCLSIZE) {
 1916                                         MCLGET(m, M_DONTWAIT);
 1917                                         if ((m->m_flags & M_EXT) == 0) {
 1918                                                 hifnstats.hst_nomem_mcl++;
 1919                                                 err = dma->cmdu ? ERESTART : ENOMEM;
 1920                                                 mlast->m_next = m;
 1921                                                 m_freem(m0);
 1922                                                 goto err_srcmap;
 1923                                         }
 1924                                         len = MCLBYTES;
 1925                                 }
 1926 
 1927                                 m->m_len = len;
 1928                                 m0->m_pkthdr.len += len;
 1929                                 totlen -= len;
 1930 
 1931                                 mlast->m_next = m;
 1932                                 mlast = m;
 1933                         }
 1934                         cmd->dst_m = m0;
 1935                 }
 1936         }
 1937 
 1938         if (cmd->dst_map == NULL) {
 1939                 if (bus_dmamap_create(sc->sc_dmat, BUS_DMA_NOWAIT, &cmd->dst_map)) {
 1940                         hifnstats.hst_nomem_map++;
 1941                         err = ENOMEM;
 1942                         goto err_srcmap;
 1943                 }
 1944                 if (crp->crp_flags & CRYPTO_F_IMBUF) {
 1945                         if (bus_dmamap_load_mbuf(sc->sc_dmat, cmd->dst_map,
 1946                             cmd->dst_m, hifn_op_cb, &cmd->dst, BUS_DMA_NOWAIT)) {
 1947                                 hifnstats.hst_nomem_map++;
 1948                                 err = ENOMEM;
 1949                                 goto err_dstmap1;
 1950                         }
 1951                 } else if (crp->crp_flags & CRYPTO_F_IOV) {
 1952                         if (bus_dmamap_load_uio(sc->sc_dmat, cmd->dst_map,
 1953                             cmd->dst_io, hifn_op_cb, &cmd->dst, BUS_DMA_NOWAIT)) {
 1954                                 hifnstats.hst_nomem_load++;
 1955                                 err = ENOMEM;
 1956                                 goto err_dstmap1;
 1957                         }
 1958                 }
 1959         }
 1960 
 1961 #ifdef HIFN_DEBUG
 1962         if (hifn_debug) {
 1963                 device_printf(sc->sc_dev,
 1964                     "Entering cmd: stat %8x ien %8x u %d/%d/%d/%d n %d/%d\n",
 1965                     READ_REG_1(sc, HIFN_1_DMA_CSR),
 1966                     READ_REG_1(sc, HIFN_1_DMA_IER),
 1967                     dma->cmdu, dma->srcu, dma->dstu, dma->resu,
 1968                     cmd->src_nsegs, cmd->dst_nsegs);
 1969         }
 1970 #endif
 1971 
 1972         if (cmd->src_map == cmd->dst_map) {
 1973                 bus_dmamap_sync(sc->sc_dmat, cmd->src_map,
 1974                     BUS_DMASYNC_PREWRITE|BUS_DMASYNC_PREREAD);
 1975         } else {
 1976                 bus_dmamap_sync(sc->sc_dmat, cmd->src_map,
 1977                     BUS_DMASYNC_PREWRITE);
 1978                 bus_dmamap_sync(sc->sc_dmat, cmd->dst_map,
 1979                     BUS_DMASYNC_PREREAD);
 1980         }
 1981 
 1982         /*
 1983          * need N src, and N dst
 1984          */
 1985         if ((dma->srcu + cmd->src_nsegs) > HIFN_D_SRC_RSIZE ||
 1986             (dma->dstu + cmd->dst_nsegs + 1) > HIFN_D_DST_RSIZE) {
 1987 #ifdef HIFN_DEBUG
 1988                 if (hifn_debug) {
 1989                         device_printf(sc->sc_dev,
 1990                                 "src/dst exhaustion, srcu %u+%u dstu %u+%u\n",
 1991                                 dma->srcu, cmd->src_nsegs,
 1992                                 dma->dstu, cmd->dst_nsegs);
 1993                 }
 1994 #endif
 1995                 hifnstats.hst_nomem_sd++;
 1996                 err = ERESTART;
 1997                 goto err_dstmap;
 1998         }
 1999 
 2000         if (dma->cmdi == HIFN_D_CMD_RSIZE) {
 2001                 dma->cmdi = 0;
 2002                 dma->cmdr[HIFN_D_CMD_RSIZE].l = htole32(HIFN_D_VALID |
 2003                     HIFN_D_JUMP | HIFN_D_MASKDONEIRQ);
 2004                 HIFN_CMDR_SYNC(sc, HIFN_D_CMD_RSIZE,
 2005                     BUS_DMASYNC_PREWRITE | BUS_DMASYNC_PREREAD);
 2006         }
 2007         cmdi = dma->cmdi++;
 2008         cmdlen = hifn_write_command(cmd, dma->command_bufs[cmdi]);
 2009         HIFN_CMD_SYNC(sc, cmdi, BUS_DMASYNC_PREWRITE);
 2010 
 2011         /* .p for command/result already set */
 2012         dma->cmdr[cmdi].l = htole32(cmdlen | HIFN_D_VALID | HIFN_D_LAST |
 2013             HIFN_D_MASKDONEIRQ);
 2014         HIFN_CMDR_SYNC(sc, cmdi,
 2015             BUS_DMASYNC_PREWRITE | BUS_DMASYNC_PREREAD);
 2016         dma->cmdu++;
 2017         if (sc->sc_c_busy == 0) {
 2018                 WRITE_REG_1(sc, HIFN_1_DMA_CSR, HIFN_DMACSR_C_CTRL_ENA);
 2019                 sc->sc_c_busy = 1;
 2020         }
 2021 
 2022         /*
 2023          * We don't worry about missing an interrupt (which a "command wait"
 2024          * interrupt salvages us from), unless there is more than one command
 2025          * in the queue.
 2026          */
 2027         if (dma->cmdu > 1) {
 2028                 sc->sc_dmaier |= HIFN_DMAIER_C_WAIT;
 2029                 WRITE_REG_1(sc, HIFN_1_DMA_IER, sc->sc_dmaier);
 2030         }
 2031 
 2032         hifnstats.hst_ipackets++;
 2033         hifnstats.hst_ibytes += cmd->src_mapsize;
 2034 
 2035         hifn_dmamap_load_src(sc, cmd);
 2036         if (sc->sc_s_busy == 0) {
 2037                 WRITE_REG_1(sc, HIFN_1_DMA_CSR, HIFN_DMACSR_S_CTRL_ENA);
 2038                 sc->sc_s_busy = 1;
 2039         }
 2040 
 2041         /*
 2042          * Unlike other descriptors, we don't mask done interrupt from
 2043          * result descriptor.
 2044          */
 2045 #ifdef HIFN_DEBUG
 2046         if (hifn_debug)
 2047                 printf("load res\n");
 2048 #endif
 2049         if (dma->resi == HIFN_D_RES_RSIZE) {
 2050                 dma->resi = 0;
 2051                 dma->resr[HIFN_D_RES_RSIZE].l = htole32(HIFN_D_VALID |
 2052                     HIFN_D_JUMP | HIFN_D_MASKDONEIRQ);
 2053                 HIFN_RESR_SYNC(sc, HIFN_D_RES_RSIZE,
 2054                     BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE);
 2055         }
 2056         resi = dma->resi++;
 2057         KASSERT(dma->hifn_commands[resi] == NULL,
 2058                 ("hifn_crypto: command slot %u busy", resi));
 2059         dma->hifn_commands[resi] = cmd;
 2060         HIFN_RES_SYNC(sc, resi, BUS_DMASYNC_PREREAD);
 2061         if ((hint & CRYPTO_HINT_MORE) && sc->sc_curbatch < hifn_maxbatch) {
 2062                 dma->resr[resi].l = htole32(HIFN_MAX_RESULT |
 2063                     HIFN_D_VALID | HIFN_D_LAST | HIFN_D_MASKDONEIRQ);
 2064                 sc->sc_curbatch++;
 2065                 if (sc->sc_curbatch > hifnstats.hst_maxbatch)
 2066                         hifnstats.hst_maxbatch = sc->sc_curbatch;
 2067                 hifnstats.hst_totbatch++;
 2068         } else {
 2069                 dma->resr[resi].l = htole32(HIFN_MAX_RESULT |
 2070                     HIFN_D_VALID | HIFN_D_LAST);
 2071                 sc->sc_curbatch = 0;
 2072         }
 2073         HIFN_RESR_SYNC(sc, resi,
 2074             BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE);
 2075         dma->resu++;
 2076         if (sc->sc_r_busy == 0) {
 2077                 WRITE_REG_1(sc, HIFN_1_DMA_CSR, HIFN_DMACSR_R_CTRL_ENA);
 2078                 sc->sc_r_busy = 1;
 2079         }
 2080 
 2081         if (cmd->sloplen)
 2082                 cmd->slopidx = resi;
 2083 
 2084         hifn_dmamap_load_dst(sc, cmd);
 2085 
 2086         if (sc->sc_d_busy == 0) {
 2087                 WRITE_REG_1(sc, HIFN_1_DMA_CSR, HIFN_DMACSR_D_CTRL_ENA);
 2088                 sc->sc_d_busy = 1;
 2089         }
 2090 
 2091 #ifdef HIFN_DEBUG
 2092         if (hifn_debug) {
 2093                 device_printf(sc->sc_dev, "command: stat %8x ier %8x\n",
 2094                     READ_REG_1(sc, HIFN_1_DMA_CSR),
 2095                     READ_REG_1(sc, HIFN_1_DMA_IER));
 2096         }
 2097 #endif
 2098 
 2099         sc->sc_active = 5;
 2100         HIFN_UNLOCK(sc);
 2101         KASSERT(err == 0, ("hifn_crypto: success with error %u", err));
 2102         return (err);           /* success */
 2103 
 2104 err_dstmap:
 2105         if (cmd->src_map != cmd->dst_map)
 2106                 bus_dmamap_unload(sc->sc_dmat, cmd->dst_map);
 2107 err_dstmap1:
 2108         if (cmd->src_map != cmd->dst_map)
 2109                 bus_dmamap_destroy(sc->sc_dmat, cmd->dst_map);
 2110 err_srcmap:
 2111         if (crp->crp_flags & CRYPTO_F_IMBUF) {
 2112                 if (cmd->src_m != cmd->dst_m)
 2113                         m_freem(cmd->dst_m);
 2114         }
 2115         bus_dmamap_unload(sc->sc_dmat, cmd->src_map);
 2116 err_srcmap1:
 2117         bus_dmamap_destroy(sc->sc_dmat, cmd->src_map);
 2118         HIFN_UNLOCK(sc);
 2119         return (err);
 2120 }
 2121 
 2122 static void
 2123 hifn_tick(void* vsc)
 2124 {
 2125         struct hifn_softc *sc = vsc;
 2126 
 2127         HIFN_LOCK(sc);
 2128         if (sc->sc_active == 0) {
 2129                 struct hifn_dma *dma = sc->sc_dma;
 2130                 u_int32_t r = 0;
 2131 
 2132                 if (dma->cmdu == 0 && sc->sc_c_busy) {
 2133                         sc->sc_c_busy = 0;
 2134                         r |= HIFN_DMACSR_C_CTRL_DIS;
 2135                 }
 2136                 if (dma->srcu == 0 && sc->sc_s_busy) {
 2137                         sc->sc_s_busy = 0;
 2138                         r |= HIFN_DMACSR_S_CTRL_DIS;
 2139                 }
 2140                 if (dma->dstu == 0 && sc->sc_d_busy) {
 2141                         sc->sc_d_busy = 0;
 2142                         r |= HIFN_DMACSR_D_CTRL_DIS;
 2143                 }
 2144                 if (dma->resu == 0 && sc->sc_r_busy) {
 2145                         sc->sc_r_busy = 0;
 2146                         r |= HIFN_DMACSR_R_CTRL_DIS;
 2147                 }
 2148                 if (r)
 2149                         WRITE_REG_1(sc, HIFN_1_DMA_CSR, r);
 2150         } else
 2151                 sc->sc_active--;
 2152         HIFN_UNLOCK(sc);
 2153         callout_reset(&sc->sc_tickto, hz, hifn_tick, sc);
 2154 }
 2155 
 2156 static void 
 2157 hifn_intr(void *arg)
 2158 {
 2159         struct hifn_softc *sc = arg;
 2160         struct hifn_dma *dma;
 2161         u_int32_t dmacsr, restart;
 2162         int i, u;
 2163 
 2164         dmacsr = READ_REG_1(sc, HIFN_1_DMA_CSR);
 2165 
 2166         /* Nothing in the DMA unit interrupted */
 2167         if ((dmacsr & sc->sc_dmaier) == 0)
 2168                 return;
 2169 
 2170         HIFN_LOCK(sc);
 2171 
 2172         dma = sc->sc_dma;
 2173 
 2174 #ifdef HIFN_DEBUG
 2175         if (hifn_debug) {
 2176                 device_printf(sc->sc_dev,
 2177                     "irq: stat %08x ien %08x damier %08x i %d/%d/%d/%d k %d/%d/%d/%d u %d/%d/%d/%d\n",
 2178                     dmacsr, READ_REG_1(sc, HIFN_1_DMA_IER), sc->sc_dmaier,
 2179                     dma->cmdi, dma->srci, dma->dsti, dma->resi,
 2180                     dma->cmdk, dma->srck, dma->dstk, dma->resk,
 2181                     dma->cmdu, dma->srcu, dma->dstu, dma->resu);
 2182         }
 2183 #endif
 2184 
 2185         WRITE_REG_1(sc, HIFN_1_DMA_CSR, dmacsr & sc->sc_dmaier);
 2186 
 2187         if ((sc->sc_flags & HIFN_HAS_PUBLIC) &&
 2188             (dmacsr & HIFN_DMACSR_PUBDONE))
 2189                 WRITE_REG_1(sc, HIFN_1_PUB_STATUS,
 2190                     READ_REG_1(sc, HIFN_1_PUB_STATUS) | HIFN_PUBSTS_DONE);
 2191 
 2192         restart = dmacsr & (HIFN_DMACSR_D_OVER | HIFN_DMACSR_R_OVER);
 2193         if (restart)
 2194                 device_printf(sc->sc_dev, "overrun %x\n", dmacsr);
 2195 
 2196         if (sc->sc_flags & HIFN_IS_7811) {
 2197                 if (dmacsr & HIFN_DMACSR_ILLR)
 2198                         device_printf(sc->sc_dev, "illegal read\n");
 2199                 if (dmacsr & HIFN_DMACSR_ILLW)
 2200                         device_printf(sc->sc_dev, "illegal write\n");
 2201         }
 2202 
 2203         restart = dmacsr & (HIFN_DMACSR_C_ABORT | HIFN_DMACSR_S_ABORT |
 2204             HIFN_DMACSR_D_ABORT | HIFN_DMACSR_R_ABORT);
 2205         if (restart) {
 2206                 device_printf(sc->sc_dev, "abort, resetting.\n");
 2207                 hifnstats.hst_abort++;
 2208                 hifn_abort(sc);
 2209                 HIFN_UNLOCK(sc);
 2210                 return;
 2211         }
 2212 
 2213         if ((dmacsr & HIFN_DMACSR_C_WAIT) && (dma->cmdu == 0)) {
 2214                 /*
 2215                  * If no slots to process and we receive a "waiting on
 2216                  * command" interrupt, we disable the "waiting on command"
 2217                  * (by clearing it).
 2218                  */
 2219                 sc->sc_dmaier &= ~HIFN_DMAIER_C_WAIT;
 2220                 WRITE_REG_1(sc, HIFN_1_DMA_IER, sc->sc_dmaier);
 2221         }
 2222 
 2223         /* clear the rings */
 2224         i = dma->resk; u = dma->resu;
 2225         while (u != 0) {
 2226                 HIFN_RESR_SYNC(sc, i,
 2227                     BUS_DMASYNC_POSTREAD | BUS_DMASYNC_POSTWRITE);
 2228                 if (dma->resr[i].l & htole32(HIFN_D_VALID)) {
 2229                         HIFN_RESR_SYNC(sc, i,
 2230                             BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE);
 2231                         break;
 2232                 }
 2233 
 2234                 if (i != HIFN_D_RES_RSIZE) {
 2235                         struct hifn_command *cmd;
 2236                         u_int8_t *macbuf = NULL;
 2237 
 2238                         HIFN_RES_SYNC(sc, i, BUS_DMASYNC_POSTREAD);
 2239                         cmd = dma->hifn_commands[i];
 2240                         KASSERT(cmd != NULL,
 2241                                 ("hifn_intr: null command slot %u", i));
 2242                         dma->hifn_commands[i] = NULL;
 2243 
 2244                         if (cmd->base_masks & HIFN_BASE_CMD_MAC) {
 2245                                 macbuf = dma->result_bufs[i];
 2246                                 macbuf += 12;
 2247                         }
 2248 
 2249                         hifn_callback(sc, cmd, macbuf);
 2250                         hifnstats.hst_opackets++;
 2251                         u--;
 2252                 }
 2253 
 2254                 if (++i == (HIFN_D_RES_RSIZE + 1))
 2255                         i = 0;
 2256         }
 2257         dma->resk = i; dma->resu = u;
 2258 
 2259         i = dma->srck; u = dma->srcu;
 2260         while (u != 0) {
 2261                 if (i == HIFN_D_SRC_RSIZE)
 2262                         i = 0;
 2263                 HIFN_SRCR_SYNC(sc, i,
 2264                     BUS_DMASYNC_POSTREAD | BUS_DMASYNC_POSTWRITE);
 2265                 if (dma->srcr[i].l & htole32(HIFN_D_VALID)) {
 2266                         HIFN_SRCR_SYNC(sc, i,
 2267                             BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE);
 2268                         break;
 2269                 }
 2270                 i++, u--;
 2271         }
 2272         dma->srck = i; dma->srcu = u;
 2273 
 2274         i = dma->cmdk; u = dma->cmdu;
 2275         while (u != 0) {
 2276                 HIFN_CMDR_SYNC(sc, i,
 2277                     BUS_DMASYNC_POSTREAD | BUS_DMASYNC_POSTWRITE);
 2278                 if (dma->cmdr[i].l & htole32(HIFN_D_VALID)) {
 2279                         HIFN_CMDR_SYNC(sc, i,
 2280                             BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE);
 2281                         break;
 2282                 }
 2283                 if (i != HIFN_D_CMD_RSIZE) {
 2284                         u--;
 2285                         HIFN_CMD_SYNC(sc, i, BUS_DMASYNC_POSTWRITE);
 2286                 }
 2287                 if (++i == (HIFN_D_CMD_RSIZE + 1))
 2288                         i = 0;
 2289         }
 2290         dma->cmdk = i; dma->cmdu = u;
 2291 
 2292         HIFN_UNLOCK(sc);
 2293 
 2294         if (sc->sc_needwakeup) {                /* XXX check high watermark */
 2295                 int wakeup = sc->sc_needwakeup & (CRYPTO_SYMQ|CRYPTO_ASYMQ);
 2296 #ifdef HIFN_DEBUG
 2297                 if (hifn_debug)
 2298                         device_printf(sc->sc_dev,
 2299                                 "wakeup crypto (%x) u %d/%d/%d/%d\n",
 2300                                 sc->sc_needwakeup,
 2301                                 dma->cmdu, dma->srcu, dma->dstu, dma->resu);
 2302 #endif
 2303                 sc->sc_needwakeup &= ~wakeup;
 2304                 crypto_unblock(sc->sc_cid, wakeup);
 2305         }
 2306 }
 2307 
 2308 /*
 2309  * Allocate a new 'session' and return an encoded session id.  'sidp'
 2310  * contains our registration id, and should contain an encoded session
 2311  * id on successful allocation.
 2312  */
 2313 static int
 2314 hifn_newsession(void *arg, u_int32_t *sidp, struct cryptoini *cri)
 2315 {
 2316         struct cryptoini *c;
 2317         struct hifn_softc *sc = arg;
 2318         int mac = 0, cry = 0, sesn;
 2319         struct hifn_session *ses = NULL;
 2320 
 2321         KASSERT(sc != NULL, ("hifn_newsession: null softc"));
 2322         if (sidp == NULL || cri == NULL || sc == NULL)
 2323                 return (EINVAL);
 2324 
 2325         if (sc->sc_sessions == NULL) {
 2326                 ses = sc->sc_sessions = (struct hifn_session *)malloc(
 2327                     sizeof(*ses), M_DEVBUF, M_NOWAIT);
 2328                 if (ses == NULL)
 2329                         return (ENOMEM);
 2330                 sesn = 0;
 2331                 sc->sc_nsessions = 1;
 2332         } else {
 2333                 for (sesn = 0; sesn < sc->sc_nsessions; sesn++) {
 2334                         if (!sc->sc_sessions[sesn].hs_used) {
 2335                                 ses = &sc->sc_sessions[sesn];
 2336                                 break;
 2337                         }
 2338                 }
 2339 
 2340                 if (ses == NULL) {
 2341                         sesn = sc->sc_nsessions;
 2342                         ses = (struct hifn_session *)malloc((sesn + 1) *
 2343                             sizeof(*ses), M_DEVBUF, M_NOWAIT);
 2344                         if (ses == NULL)
 2345                                 return (ENOMEM);
 2346                         bcopy(sc->sc_sessions, ses, sesn * sizeof(*ses));
 2347                         bzero(sc->sc_sessions, sesn * sizeof(*ses));
 2348                         free(sc->sc_sessions, M_DEVBUF);
 2349                         sc->sc_sessions = ses;
 2350                         ses = &sc->sc_sessions[sesn];
 2351                         sc->sc_nsessions++;
 2352                 }
 2353         }
 2354         bzero(ses, sizeof(*ses));
 2355         ses->hs_used = 1;
 2356 
 2357         for (c = cri; c != NULL; c = c->cri_next) {
 2358                 switch (c->cri_alg) {
 2359                 case CRYPTO_MD5:
 2360                 case CRYPTO_SHA1:
 2361                 case CRYPTO_MD5_HMAC:
 2362                 case CRYPTO_SHA1_HMAC:
 2363                         if (mac)
 2364                                 return (EINVAL);
 2365                         mac = 1;
 2366                         break;
 2367                 case CRYPTO_DES_CBC:
 2368                 case CRYPTO_3DES_CBC:
 2369                 case CRYPTO_AES_CBC:
 2370                         /* XXX this may read fewer, does it matter? */
 2371                         read_random(ses->hs_iv,
 2372                                 c->cri_alg == CRYPTO_AES_CBC ?
 2373                                         HIFN_AES_IV_LENGTH : HIFN_IV_LENGTH);
 2374                         /*FALLTHROUGH*/
 2375                 case CRYPTO_ARC4:
 2376                         if (cry)
 2377                                 return (EINVAL);
 2378                         cry = 1;
 2379                         break;
 2380                 default:
 2381                         return (EINVAL);
 2382                 }
 2383         }
 2384         if (mac == 0 && cry == 0)
 2385                 return (EINVAL);
 2386 
 2387         *sidp = HIFN_SID(device_get_unit(sc->sc_dev), sesn);
 2388 
 2389         return (0);
 2390 }
 2391 
 2392 /*
 2393  * Deallocate a session.
 2394  * XXX this routine should run a zero'd mac/encrypt key into context ram.
 2395  * XXX to blow away any keys already stored there.
 2396  */
 2397 static int
 2398 hifn_freesession(void *arg, u_int64_t tid)
 2399 {
 2400         struct hifn_softc *sc = arg;
 2401         int session;
 2402         u_int32_t sid = CRYPTO_SESID2LID(tid);
 2403 
 2404         KASSERT(sc != NULL, ("hifn_freesession: null softc"));
 2405         if (sc == NULL)
 2406                 return (EINVAL);
 2407 
 2408         session = HIFN_SESSION(sid);
 2409         if (session >= sc->sc_nsessions)
 2410                 return (EINVAL);
 2411 
 2412         bzero(&sc->sc_sessions[session], sizeof(sc->sc_sessions[session]));
 2413         return (0);
 2414 }
 2415 
 2416 static int
 2417 hifn_process(void *arg, struct cryptop *crp, int hint)
 2418 {
 2419         struct hifn_softc *sc = arg;
 2420         struct hifn_command *cmd = NULL;
 2421         int session, err, ivlen;
 2422         struct cryptodesc *crd1, *crd2, *maccrd, *enccrd;
 2423 
 2424         if (crp == NULL || crp->crp_callback == NULL) {
 2425                 hifnstats.hst_invalid++;
 2426                 return (EINVAL);
 2427         }
 2428         session = HIFN_SESSION(crp->crp_sid);
 2429 
 2430         if (sc == NULL || session >= sc->sc_nsessions) {
 2431                 err = EINVAL;
 2432                 goto errout;
 2433         }
 2434 
 2435         cmd = malloc(sizeof(struct hifn_command), M_DEVBUF, M_NOWAIT | M_ZERO);
 2436         if (cmd == NULL) {
 2437                 hifnstats.hst_nomem++;
 2438                 err = ENOMEM;
 2439                 goto errout;
 2440         }
 2441 
 2442         if (crp->crp_flags & CRYPTO_F_IMBUF) {
 2443                 cmd->src_m = (struct mbuf *)crp->crp_buf;
 2444                 cmd->dst_m = (struct mbuf *)crp->crp_buf;
 2445         } else if (crp->crp_flags & CRYPTO_F_IOV) {
 2446                 cmd->src_io = (struct uio *)crp->crp_buf;
 2447                 cmd->dst_io = (struct uio *)crp->crp_buf;
 2448         } else {
 2449                 err = EINVAL;
 2450                 goto errout;    /* XXX we don't handle contiguous buffers! */
 2451         }
 2452 
 2453         crd1 = crp->crp_desc;
 2454         if (crd1 == NULL) {
 2455                 err = EINVAL;
 2456                 goto errout;
 2457         }
 2458         crd2 = crd1->crd_next;
 2459 
 2460         if (crd2 == NULL) {
 2461                 if (crd1->crd_alg == CRYPTO_MD5_HMAC ||
 2462                     crd1->crd_alg == CRYPTO_SHA1_HMAC ||
 2463                     crd1->crd_alg == CRYPTO_SHA1 ||
 2464                     crd1->crd_alg == CRYPTO_MD5) {
 2465                         maccrd = crd1;
 2466                         enccrd = NULL;
 2467                 } else if (crd1->crd_alg == CRYPTO_DES_CBC ||
 2468                     crd1->crd_alg == CRYPTO_3DES_CBC ||
 2469                     crd1->crd_alg == CRYPTO_AES_CBC ||
 2470                     crd1->crd_alg == CRYPTO_ARC4) {
 2471                         if ((crd1->crd_flags & CRD_F_ENCRYPT) == 0)
 2472                                 cmd->base_masks |= HIFN_BASE_CMD_DECODE;
 2473                         maccrd = NULL;
 2474                         enccrd = crd1;
 2475                 } else {
 2476                         err = EINVAL;
 2477                         goto errout;
 2478                 }
 2479         } else {
 2480                 if ((crd1->crd_alg == CRYPTO_MD5_HMAC ||
 2481                      crd1->crd_alg == CRYPTO_SHA1_HMAC ||
 2482                      crd1->crd_alg == CRYPTO_MD5 ||
 2483                      crd1->crd_alg == CRYPTO_SHA1) &&
 2484                     (crd2->crd_alg == CRYPTO_DES_CBC ||
 2485                      crd2->crd_alg == CRYPTO_3DES_CBC ||
 2486                      crd2->crd_alg == CRYPTO_AES_CBC ||
 2487                      crd2->crd_alg == CRYPTO_ARC4) &&
 2488                     ((crd2->crd_flags & CRD_F_ENCRYPT) == 0)) {
 2489                         cmd->base_masks = HIFN_BASE_CMD_DECODE;
 2490                         maccrd = crd1;
 2491                         enccrd = crd2;
 2492                 } else if ((crd1->crd_alg == CRYPTO_DES_CBC ||
 2493                      crd1->crd_alg == CRYPTO_ARC4 ||
 2494                      crd1->crd_alg == CRYPTO_3DES_CBC ||
 2495                      crd1->crd_alg == CRYPTO_AES_CBC) &&
 2496                     (crd2->crd_alg == CRYPTO_MD5_HMAC ||
 2497                      crd2->crd_alg == CRYPTO_SHA1_HMAC ||
 2498                      crd2->crd_alg == CRYPTO_MD5 ||
 2499                      crd2->crd_alg == CRYPTO_SHA1) &&
 2500                     (crd1->crd_flags & CRD_F_ENCRYPT)) {
 2501                         enccrd = crd1;
 2502                         maccrd = crd2;
 2503                 } else {
 2504                         /*
 2505                          * We cannot order the 7751 as requested
 2506                          */
 2507                         err = EINVAL;
 2508                         goto errout;
 2509                 }
 2510         }
 2511 
 2512         if (enccrd) {
 2513                 cmd->enccrd = enccrd;
 2514                 cmd->base_masks |= HIFN_BASE_CMD_CRYPT;
 2515                 switch (enccrd->crd_alg) {
 2516                 case CRYPTO_ARC4:
 2517                         cmd->cry_masks |= HIFN_CRYPT_CMD_ALG_RC4;
 2518                         break;
 2519                 case CRYPTO_DES_CBC:
 2520                         cmd->cry_masks |= HIFN_CRYPT_CMD_ALG_DES |
 2521                             HIFN_CRYPT_CMD_MODE_CBC |
 2522                             HIFN_CRYPT_CMD_NEW_IV;
 2523                         break;
 2524                 case CRYPTO_3DES_CBC:
 2525                         cmd->cry_masks |= HIFN_CRYPT_CMD_ALG_3DES |
 2526                             HIFN_CRYPT_CMD_MODE_CBC |
 2527                             HIFN_CRYPT_CMD_NEW_IV;
 2528                         break;
 2529                 case CRYPTO_AES_CBC:
 2530                         cmd->cry_masks |= HIFN_CRYPT_CMD_ALG_AES |
 2531                             HIFN_CRYPT_CMD_MODE_CBC |
 2532                             HIFN_CRYPT_CMD_NEW_IV;
 2533                         break;
 2534                 default:
 2535                         err = EINVAL;
 2536                         goto errout;
 2537                 }
 2538                 if (enccrd->crd_alg != CRYPTO_ARC4) {
 2539                         ivlen = ((enccrd->crd_alg == CRYPTO_AES_CBC) ?
 2540                                 HIFN_AES_IV_LENGTH : HIFN_IV_LENGTH);
 2541                         if (enccrd->crd_flags & CRD_F_ENCRYPT) {
 2542                                 if (enccrd->crd_flags & CRD_F_IV_EXPLICIT)
 2543                                         bcopy(enccrd->crd_iv, cmd->iv, ivlen);
 2544                                 else
 2545                                         bcopy(sc->sc_sessions[session].hs_iv,
 2546                                             cmd->iv, ivlen);
 2547 
 2548                                 if ((enccrd->crd_flags & CRD_F_IV_PRESENT)
 2549                                     == 0) {
 2550                                         if (crp->crp_flags & CRYPTO_F_IMBUF)
 2551                                                 m_copyback(cmd->src_m,
 2552                                                     enccrd->crd_inject,
 2553                                                     ivlen, cmd->iv);
 2554                                         else if (crp->crp_flags & CRYPTO_F_IOV)
 2555                                                 cuio_copyback(cmd->src_io,
 2556                                                     enccrd->crd_inject,
 2557                                                     ivlen, cmd->iv);
 2558                                 }
 2559                         } else {
 2560                                 if (enccrd->crd_flags & CRD_F_IV_EXPLICIT)
 2561                                         bcopy(enccrd->crd_iv, cmd->iv, ivlen);
 2562                                 else if (crp->crp_flags & CRYPTO_F_IMBUF)
 2563                                         m_copydata(cmd->src_m,
 2564                                             enccrd->crd_inject, ivlen, cmd->iv);
 2565                                 else if (crp->crp_flags & CRYPTO_F_IOV)
 2566                                         cuio_copydata(cmd->src_io,
 2567                                             enccrd->crd_inject, ivlen, cmd->iv);
 2568                         }
 2569                 }
 2570 
 2571                 if (enccrd->crd_flags & CRD_F_KEY_EXPLICIT)
 2572                         cmd->cry_masks |= HIFN_CRYPT_CMD_NEW_KEY;
 2573                 cmd->ck = enccrd->crd_key;
 2574                 cmd->cklen = enccrd->crd_klen >> 3;
 2575                 cmd->cry_masks |= HIFN_CRYPT_CMD_NEW_KEY;
 2576 
 2577                 /* 
 2578                  * Need to specify the size for the AES key in the masks.
 2579                  */
 2580                 if ((cmd->cry_masks & HIFN_CRYPT_CMD_ALG_MASK) ==
 2581                     HIFN_CRYPT_CMD_ALG_AES) {
 2582                         switch (cmd->cklen) {
 2583                         case 16:
 2584                                 cmd->cry_masks |= HIFN_CRYPT_CMD_KSZ_128;
 2585                                 break;
 2586                         case 24:
 2587                                 cmd->cry_masks |= HIFN_CRYPT_CMD_KSZ_192;
 2588                                 break;
 2589                         case 32:
 2590                                 cmd->cry_masks |= HIFN_CRYPT_CMD_KSZ_256;
 2591                                 break;
 2592                         default:
 2593                                 err = EINVAL;
 2594                                 goto errout;
 2595                         }
 2596                 }
 2597         }
 2598 
 2599         if (maccrd) {
 2600                 cmd->maccrd = maccrd;
 2601                 cmd->base_masks |= HIFN_BASE_CMD_MAC;
 2602 
 2603                 switch (maccrd->crd_alg) {
 2604                 case CRYPTO_MD5:
 2605                         cmd->mac_masks |= HIFN_MAC_CMD_ALG_MD5 |
 2606                             HIFN_MAC_CMD_RESULT | HIFN_MAC_CMD_MODE_HASH |
 2607                             HIFN_MAC_CMD_POS_IPSEC;
 2608                        break;
 2609                 case CRYPTO_MD5_HMAC:
 2610                         cmd->mac_masks |= HIFN_MAC_CMD_ALG_MD5 |
 2611                             HIFN_MAC_CMD_RESULT | HIFN_MAC_CMD_MODE_HMAC |
 2612                             HIFN_MAC_CMD_POS_IPSEC | HIFN_MAC_CMD_TRUNC;
 2613                         break;
 2614                 case CRYPTO_SHA1:
 2615                         cmd->mac_masks |= HIFN_MAC_CMD_ALG_SHA1 |
 2616                             HIFN_MAC_CMD_RESULT | HIFN_MAC_CMD_MODE_HASH |
 2617                             HIFN_MAC_CMD_POS_IPSEC;
 2618                         break;
 2619                 case CRYPTO_SHA1_HMAC:
 2620                         cmd->mac_masks |= HIFN_MAC_CMD_ALG_SHA1 |
 2621                             HIFN_MAC_CMD_RESULT | HIFN_MAC_CMD_MODE_HMAC |
 2622                             HIFN_MAC_CMD_POS_IPSEC | HIFN_MAC_CMD_TRUNC;
 2623                         break;
 2624                 }
 2625 
 2626                 if (maccrd->crd_alg == CRYPTO_SHA1_HMAC ||
 2627                      maccrd->crd_alg == CRYPTO_MD5_HMAC) {
 2628                         cmd->mac_masks |= HIFN_MAC_CMD_NEW_KEY;
 2629                         bcopy(maccrd->crd_key, cmd->mac, maccrd->crd_klen >> 3);
 2630                         bzero(cmd->mac + (maccrd->crd_klen >> 3),
 2631                             HIFN_MAC_KEY_LENGTH - (maccrd->crd_klen >> 3));
 2632                 }
 2633         }
 2634 
 2635         cmd->crp = crp;
 2636         cmd->session_num = session;
 2637         cmd->softc = sc;
 2638 
 2639         err = hifn_crypto(sc, cmd, crp, hint);
 2640         if (!err) {
 2641                 return 0;
 2642         } else if (err == ERESTART) {
 2643                 /*
 2644                  * There weren't enough resources to dispatch the request
 2645                  * to the part.  Notify the caller so they'll requeue this
 2646                  * request and resubmit it again soon.
 2647                  */
 2648 #ifdef HIFN_DEBUG
 2649                 if (hifn_debug)
 2650                         device_printf(sc->sc_dev, "requeue request\n");
 2651 #endif
 2652                 free(cmd, M_DEVBUF);
 2653                 sc->sc_needwakeup |= CRYPTO_SYMQ;
 2654                 return (err);
 2655         }
 2656 
 2657 errout:
 2658         if (cmd != NULL)
 2659                 free(cmd, M_DEVBUF);
 2660         if (err == EINVAL)
 2661                 hifnstats.hst_invalid++;
 2662         else
 2663                 hifnstats.hst_nomem++;
 2664         crp->crp_etype = err;
 2665         crypto_done(crp);
 2666         return (err);
 2667 }
 2668 
 2669 static void
 2670 hifn_abort(struct hifn_softc *sc)
 2671 {
 2672         struct hifn_dma *dma = sc->sc_dma;
 2673         struct hifn_command *cmd;
 2674         struct cryptop *crp;
 2675         int i, u;
 2676 
 2677         i = dma->resk; u = dma->resu;
 2678         while (u != 0) {
 2679                 cmd = dma->hifn_commands[i];
 2680                 KASSERT(cmd != NULL, ("hifn_abort: null command slot %u", i));
 2681                 dma->hifn_commands[i] = NULL;
 2682                 crp = cmd->crp;
 2683 
 2684                 if ((dma->resr[i].l & htole32(HIFN_D_VALID)) == 0) {
 2685                         /* Salvage what we can. */
 2686                         u_int8_t *macbuf;
 2687 
 2688                         if (cmd->base_masks & HIFN_BASE_CMD_MAC) {
 2689                                 macbuf = dma->result_bufs[i];
 2690                                 macbuf += 12;
 2691                         } else
 2692                                 macbuf = NULL;
 2693                         hifnstats.hst_opackets++;
 2694                         hifn_callback(sc, cmd, macbuf);
 2695                 } else {
 2696                         if (cmd->src_map == cmd->dst_map) {
 2697                                 bus_dmamap_sync(sc->sc_dmat, cmd->src_map,
 2698                                     BUS_DMASYNC_POSTREAD|BUS_DMASYNC_POSTWRITE);
 2699                         } else {
 2700                                 bus_dmamap_sync(sc->sc_dmat, cmd->src_map,
 2701                                     BUS_DMASYNC_POSTWRITE);
 2702                                 bus_dmamap_sync(sc->sc_dmat, cmd->dst_map,
 2703                                     BUS_DMASYNC_POSTREAD);
 2704                         }
 2705 
 2706                         if (cmd->src_m != cmd->dst_m) {
 2707                                 m_freem(cmd->src_m);
 2708                                 crp->crp_buf = (caddr_t)cmd->dst_m;
 2709                         }
 2710 
 2711                         /* non-shared buffers cannot be restarted */
 2712                         if (cmd->src_map != cmd->dst_map) {
 2713                                 /*
 2714                                  * XXX should be EAGAIN, delayed until
 2715                                  * after the reset.
 2716                                  */
 2717                                 crp->crp_etype = ENOMEM;
 2718                                 bus_dmamap_unload(sc->sc_dmat, cmd->dst_map);
 2719                                 bus_dmamap_destroy(sc->sc_dmat, cmd->dst_map);
 2720                         } else
 2721                                 crp->crp_etype = ENOMEM;
 2722 
 2723                         bus_dmamap_unload(sc->sc_dmat, cmd->src_map);
 2724                         bus_dmamap_destroy(sc->sc_dmat, cmd->src_map);
 2725 
 2726                         free(cmd, M_DEVBUF);
 2727                         if (crp->crp_etype != EAGAIN)
 2728                                 crypto_done(crp);
 2729                 }
 2730 
 2731                 if (++i == HIFN_D_RES_RSIZE)
 2732                         i = 0;
 2733                 u--;
 2734         }
 2735         dma->resk = i; dma->resu = u;
 2736 
 2737         hifn_reset_board(sc, 1);
 2738         hifn_init_dma(sc);
 2739         hifn_init_pci_registers(sc);
 2740 }
 2741 
 2742 static void
 2743 hifn_callback(struct hifn_softc *sc, struct hifn_command *cmd, u_int8_t *macbuf)
 2744 {
 2745         struct hifn_dma *dma = sc->sc_dma;
 2746         struct cryptop *crp = cmd->crp;
 2747         struct cryptodesc *crd;
 2748         struct mbuf *m;
 2749         int totlen, i, u, ivlen;
 2750 
 2751         if (cmd->src_map == cmd->dst_map) {
 2752                 bus_dmamap_sync(sc->sc_dmat, cmd->src_map,
 2753                     BUS_DMASYNC_POSTWRITE | BUS_DMASYNC_POSTREAD);
 2754         } else {
 2755                 bus_dmamap_sync(sc->sc_dmat, cmd->src_map,
 2756                     BUS_DMASYNC_POSTWRITE);
 2757                 bus_dmamap_sync(sc->sc_dmat, cmd->dst_map,
 2758                     BUS_DMASYNC_POSTREAD);
 2759         }
 2760 
 2761         if (crp->crp_flags & CRYPTO_F_IMBUF) {
 2762                 if (cmd->src_m != cmd->dst_m) {
 2763                         crp->crp_buf = (caddr_t)cmd->dst_m;
 2764                         totlen = cmd->src_mapsize;
 2765                         for (m = cmd->dst_m; m != NULL; m = m->m_next) {
 2766                                 if (totlen < m->m_len) {
 2767                                         m->m_len = totlen;
 2768                                         totlen = 0;
 2769                                 } else
 2770                                         totlen -= m->m_len;
 2771                         }
 2772                         cmd->dst_m->m_pkthdr.len = cmd->src_m->m_pkthdr.len;
 2773                         m_freem(cmd->src_m);
 2774                 }
 2775         }
 2776 
 2777         if (cmd->sloplen != 0) {
 2778                 if (crp->crp_flags & CRYPTO_F_IMBUF)
 2779                         m_copyback((struct mbuf *)crp->crp_buf,
 2780                             cmd->src_mapsize - cmd->sloplen,
 2781                             cmd->sloplen, (caddr_t)&dma->slop[cmd->slopidx]);
 2782                 else if (crp->crp_flags & CRYPTO_F_IOV)
 2783                         cuio_copyback((struct uio *)crp->crp_buf,
 2784                             cmd->src_mapsize - cmd->sloplen,
 2785                             cmd->sloplen, (caddr_t)&dma->slop[cmd->slopidx]);
 2786         }
 2787 
 2788         i = dma->dstk; u = dma->dstu;
 2789         while (u != 0) {
 2790                 if (i == HIFN_D_DST_RSIZE)
 2791                         i = 0;
 2792                 bus_dmamap_sync(sc->sc_dmat, sc->sc_dmamap,
 2793                     BUS_DMASYNC_POSTREAD | BUS_DMASYNC_POSTWRITE);
 2794                 if (dma->dstr[i].l & htole32(HIFN_D_VALID)) {
 2795                         bus_dmamap_sync(sc->sc_dmat, sc->sc_dmamap,
 2796                             BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE);
 2797                         break;
 2798                 }
 2799                 i++, u--;
 2800         }
 2801         dma->dstk = i; dma->dstu = u;
 2802 
 2803         hifnstats.hst_obytes += cmd->dst_mapsize;
 2804 
 2805         if ((cmd->base_masks & (HIFN_BASE_CMD_CRYPT | HIFN_BASE_CMD_DECODE)) ==
 2806             HIFN_BASE_CMD_CRYPT) {
 2807                 for (crd = crp->crp_desc; crd; crd = crd->crd_next) {
 2808                         if (crd->crd_alg != CRYPTO_DES_CBC &&
 2809                             crd->crd_alg != CRYPTO_3DES_CBC &&
 2810                             crd->crd_alg != CRYPTO_AES_CBC)
 2811                                 continue;
 2812                         ivlen = ((crd->crd_alg == CRYPTO_AES_CBC) ?
 2813                                 HIFN_AES_IV_LENGTH : HIFN_IV_LENGTH);
 2814                         if (crp->crp_flags & CRYPTO_F_IMBUF)
 2815                                 m_copydata((struct mbuf *)crp->crp_buf,
 2816                                     crd->crd_skip + crd->crd_len - ivlen, ivlen,
 2817                                     cmd->softc->sc_sessions[cmd->session_num].hs_iv);
 2818                         else if (crp->crp_flags & CRYPTO_F_IOV) {
 2819                                 cuio_copydata((struct uio *)crp->crp_buf,
 2820                                     crd->crd_skip + crd->crd_len - ivlen, ivlen,
 2821                                     cmd->softc->sc_sessions[cmd->session_num].hs_iv);
 2822                         }
 2823                         break;
 2824                 }
 2825         }
 2826 
 2827         if (macbuf != NULL) {
 2828                 for (crd = crp->crp_desc; crd; crd = crd->crd_next) {
 2829                         int len;
 2830 
 2831                         if (crd->crd_alg == CRYPTO_MD5)
 2832                                 len = 16;
 2833                         else if (crd->crd_alg == CRYPTO_SHA1)
 2834                                 len = 20;
 2835                         else if (crd->crd_alg == CRYPTO_MD5_HMAC ||
 2836                             crd->crd_alg == CRYPTO_SHA1_HMAC)
 2837                                 len = 12;
 2838                         else
 2839                                 continue;
 2840 
 2841                         if (crp->crp_flags & CRYPTO_F_IMBUF)
 2842                                 m_copyback((struct mbuf *)crp->crp_buf,
 2843                                    crd->crd_inject, len, macbuf);
 2844                         else if ((crp->crp_flags & CRYPTO_F_IOV) && crp->crp_mac)
 2845                                 bcopy((caddr_t)macbuf, crp->crp_mac, len);
 2846                         break;
 2847                 }
 2848         }
 2849 
 2850         if (cmd->src_map != cmd->dst_map) {
 2851                 bus_dmamap_unload(sc->sc_dmat, cmd->dst_map);
 2852                 bus_dmamap_destroy(sc->sc_dmat, cmd->dst_map);
 2853         }
 2854         bus_dmamap_unload(sc->sc_dmat, cmd->src_map);
 2855         bus_dmamap_destroy(sc->sc_dmat, cmd->src_map);
 2856         free(cmd, M_DEVBUF);
 2857         crypto_done(crp);
 2858 }
 2859 
 2860 /*
 2861  * 7811 PB3 rev/2 parts lock-up on burst writes to Group 0
 2862  * and Group 1 registers; avoid conditions that could create
 2863  * burst writes by doing a read in between the writes.
 2864  *
 2865  * NB: The read we interpose is always to the same register;
 2866  *     we do this because reading from an arbitrary (e.g. last)
 2867  *     register may not always work.
 2868  */
 2869 static void
 2870 hifn_write_reg_0(struct hifn_softc *sc, bus_size_t reg, u_int32_t val)
 2871 {
 2872         if (sc->sc_flags & HIFN_IS_7811) {
 2873                 if (sc->sc_bar0_lastreg == reg - 4)
 2874                         bus_space_read_4(sc->sc_st0, sc->sc_sh0, HIFN_0_PUCNFG);
 2875                 sc->sc_bar0_lastreg = reg;
 2876         }
 2877         bus_space_write_4(sc->sc_st0, sc->sc_sh0, reg, val);
 2878 }
 2879 
 2880 static void
 2881 hifn_write_reg_1(struct hifn_softc *sc, bus_size_t reg, u_int32_t val)
 2882 {
 2883         if (sc->sc_flags & HIFN_IS_7811) {
 2884                 if (sc->sc_bar1_lastreg == reg - 4)
 2885                         bus_space_read_4(sc->sc_st1, sc->sc_sh1, HIFN_1_REVID);
 2886                 sc->sc_bar1_lastreg = reg;
 2887         }
 2888         bus_space_write_4(sc->sc_st1, sc->sc_sh1, reg, val);
 2889 }

Cache object: 3861725f4e299e84308cef155075de38


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]


This page is part of the FreeBSD/Linux Linux Kernel Cross-Reference, and was automatically generated using a modified version of the LXR engine.