Root/target/linux/generic/files/crypto/ocf/hifn/hifn7751.c

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

Archive Download this file



interactive