root/dev/pci/hifn7751.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. hifn_probe
  2. hifn_attach
  3. hifn_init_pubrng
  4. hifn_rng
  5. hifn_puc_wait
  6. hifn_reset_puc
  7. hifn_set_retry
  8. hifn_reset_board
  9. hifn_next_signature
  10. hifn_enable_crypto
  11. hifn_init_pci_registers
  12. hifn_sessions
  13. hifn_ramtype
  14. hifn_sramsize
  15. hifn_dramsize
  16. hifn_alloc_slot
  17. hifn_writeramaddr
  18. hifn_readramaddr
  19. hifn_init_dma
  20. hifn_write_command
  21. hifn_dmamap_aligned
  22. hifn_dmamap_load_dst
  23. hifn_dmamap_load_src
  24. hifn_crypto
  25. hifn_tick
  26. hifn_intr
  27. hifn_newsession
  28. hifn_freesession
  29. hifn_process
  30. hifn_abort
  31. hifn_callback
  32. hifn_compression
  33. hifn_compress_enter
  34. hifn_callback_comp
  35. hifn_mkmbuf_chain
  36. hifn_write_4
  37. hifn_read_4

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

/* [<][>][^][v][top][bottom][index][help] */