[BACK]Return to hifn7751.c CVS log [TXT][DIR] Up to [cvs.NetBSD.org] / src / sys / dev / pci

Annotation of src/sys/dev/pci/hifn7751.c, Revision 1.54.2.1

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

CVSweb <webmaster@jp.NetBSD.org>