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

Archive Download this file



interactive