LCOV - code coverage report
Current view: top level - dev/pci - hifn7751.c (source / functions) Hit Total Coverage
Test: 6.4 Lines: 0 1403 0.0 %
Date: 2018-10-19 03:25:38 Functions: 0 37 0.0 %
Legend: Lines: hit not hit

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

Generated by: LCOV version 1.13