Home | History | Annotate | Line # | Download | only in marvell
mvxpsec.c revision 1.7
      1  1.7  riastrad /*	$NetBSD: mvxpsec.c,v 1.7 2020/07/25 22:37:48 riastradh Exp $	*/
      2  1.1  hsuenaga /*
      3  1.1  hsuenaga  * Copyright (c) 2015 Internet Initiative Japan Inc.
      4  1.1  hsuenaga  * All rights reserved.
      5  1.1  hsuenaga  *
      6  1.1  hsuenaga  * Redistribution and use in source and binary forms, with or without
      7  1.1  hsuenaga  * modification, are permitted provided that the following conditions
      8  1.1  hsuenaga  * are met:
      9  1.1  hsuenaga  * 1. Redistributions of source code must retain the above copyright
     10  1.1  hsuenaga  *    notice, this list of conditions and the following disclaimer.
     11  1.1  hsuenaga  * 2. Redistributions in binary form must reproduce the above copyright
     12  1.1  hsuenaga  *    notice, this list of conditions and the following disclaimer in the
     13  1.1  hsuenaga  *    documentation and/or other materials provided with the distribution.
     14  1.1  hsuenaga  *
     15  1.1  hsuenaga  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
     16  1.1  hsuenaga  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
     17  1.1  hsuenaga  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
     18  1.1  hsuenaga  * DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
     19  1.1  hsuenaga  * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
     20  1.1  hsuenaga  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
     21  1.1  hsuenaga  * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
     22  1.1  hsuenaga  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
     23  1.1  hsuenaga  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
     24  1.1  hsuenaga  * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
     25  1.1  hsuenaga  * POSSIBILITY OF SUCH DAMAGE.
     26  1.1  hsuenaga  */
     27  1.7  riastrad 
     28  1.7  riastrad #ifdef _KERNEL_OPT
     29  1.7  riastrad #include "opt_ipsec.h"
     30  1.7  riastrad #endif
     31  1.7  riastrad 
     32  1.1  hsuenaga /*
     33  1.1  hsuenaga  * Cryptographic Engine and Security Accelerator(MVXPSEC)
     34  1.1  hsuenaga  */
     35  1.1  hsuenaga #include <sys/cdefs.h>
     36  1.1  hsuenaga #include <sys/param.h>
     37  1.1  hsuenaga #include <sys/types.h>
     38  1.1  hsuenaga #include <sys/kernel.h>
     39  1.1  hsuenaga #include <sys/queue.h>
     40  1.1  hsuenaga #include <sys/conf.h>
     41  1.1  hsuenaga #include <sys/proc.h>
     42  1.1  hsuenaga #include <sys/bus.h>
     43  1.1  hsuenaga #include <sys/evcnt.h>
     44  1.1  hsuenaga #include <sys/device.h>
     45  1.1  hsuenaga #include <sys/endian.h>
     46  1.1  hsuenaga #include <sys/errno.h>
     47  1.1  hsuenaga #include <sys/kmem.h>
     48  1.1  hsuenaga #include <sys/mbuf.h>
     49  1.1  hsuenaga #include <sys/callout.h>
     50  1.1  hsuenaga #include <sys/pool.h>
     51  1.1  hsuenaga #include <sys/cprng.h>
     52  1.1  hsuenaga #include <sys/syslog.h>
     53  1.1  hsuenaga #include <sys/mutex.h>
     54  1.1  hsuenaga #include <sys/kthread.h>
     55  1.1  hsuenaga #include <sys/atomic.h>
     56  1.1  hsuenaga #include <sys/sha1.h>
     57  1.1  hsuenaga #include <sys/md5.h>
     58  1.1  hsuenaga 
     59  1.1  hsuenaga #include <uvm/uvm_extern.h>
     60  1.1  hsuenaga 
     61  1.1  hsuenaga #include <opencrypto/cryptodev.h>
     62  1.1  hsuenaga #include <opencrypto/xform.h>
     63  1.1  hsuenaga 
     64  1.1  hsuenaga #include <net/net_stats.h>
     65  1.1  hsuenaga 
     66  1.1  hsuenaga #include <netinet/in_systm.h>
     67  1.1  hsuenaga #include <netinet/in.h>
     68  1.1  hsuenaga #include <netinet/ip.h>
     69  1.1  hsuenaga #include <netinet/ip6.h>
     70  1.1  hsuenaga 
     71  1.7  riastrad #if NIPSEC > 0
     72  1.1  hsuenaga #include <netipsec/esp_var.h>
     73  1.7  riastrad #endif
     74  1.1  hsuenaga 
     75  1.1  hsuenaga #include <arm/cpufunc.h>
     76  1.1  hsuenaga #include <arm/marvell/mvsocvar.h>
     77  1.1  hsuenaga #include <arm/marvell/armadaxpreg.h>
     78  1.1  hsuenaga #include <dev/marvell/marvellreg.h>
     79  1.1  hsuenaga #include <dev/marvell/marvellvar.h>
     80  1.1  hsuenaga #include <dev/marvell/mvxpsecreg.h>
     81  1.1  hsuenaga #include <dev/marvell/mvxpsecvar.h>
     82  1.1  hsuenaga 
     83  1.1  hsuenaga #ifdef DEBUG
     84  1.1  hsuenaga #define STATIC __attribute__ ((noinline)) extern
     85  1.1  hsuenaga #define _STATIC __attribute__ ((noinline)) extern
     86  1.1  hsuenaga #define INLINE __attribute__ ((noinline)) extern
     87  1.1  hsuenaga #define _INLINE __attribute__ ((noinline)) extern
     88  1.1  hsuenaga #else
     89  1.1  hsuenaga #define STATIC static
     90  1.1  hsuenaga #define _STATIC __attribute__ ((unused)) static
     91  1.1  hsuenaga #define INLINE static inline
     92  1.1  hsuenaga #define _INLINE __attribute__ ((unused)) static inline
     93  1.1  hsuenaga #endif
     94  1.1  hsuenaga 
     95  1.1  hsuenaga /*
     96  1.1  hsuenaga  * IRQ and SRAM spaces for each of unit
     97  1.1  hsuenaga  * XXX: move to attach_args
     98  1.1  hsuenaga  */
     99  1.1  hsuenaga struct {
    100  1.1  hsuenaga 	int		err_int;
    101  1.1  hsuenaga } mvxpsec_config[] = {
    102  1.1  hsuenaga 	{ .err_int = ARMADAXP_IRQ_CESA0_ERR, }, /* unit 0 */
    103  1.1  hsuenaga 	{ .err_int = ARMADAXP_IRQ_CESA1_ERR, }, /* unit 1 */
    104  1.1  hsuenaga };
    105  1.1  hsuenaga #define MVXPSEC_ERR_INT(sc) \
    106  1.1  hsuenaga     mvxpsec_config[device_unit((sc)->sc_dev)].err_int
    107  1.1  hsuenaga 
    108  1.1  hsuenaga /*
    109  1.1  hsuenaga  * AES
    110  1.1  hsuenaga  */
    111  1.1  hsuenaga #define MAXBC				(128/32)
    112  1.1  hsuenaga #define MAXKC				(256/32)
    113  1.1  hsuenaga #define MAXROUNDS			14
    114  1.1  hsuenaga STATIC int mv_aes_ksched(uint8_t[4][MAXKC], int,
    115  1.1  hsuenaga     uint8_t[MAXROUNDS+1][4][MAXBC]);
    116  1.1  hsuenaga STATIC int mv_aes_deckey(uint8_t *, uint8_t *, int);
    117  1.1  hsuenaga 
    118  1.1  hsuenaga /*
    119  1.1  hsuenaga  * device driver autoconf interface
    120  1.1  hsuenaga  */
    121  1.1  hsuenaga STATIC int mvxpsec_match(device_t, cfdata_t, void *);
    122  1.1  hsuenaga STATIC void mvxpsec_attach(device_t, device_t, void *);
    123  1.1  hsuenaga STATIC void mvxpsec_evcnt_attach(struct mvxpsec_softc *);
    124  1.1  hsuenaga 
    125  1.1  hsuenaga /*
    126  1.1  hsuenaga  * register setup
    127  1.1  hsuenaga  */
    128  1.1  hsuenaga STATIC int mvxpsec_wininit(struct mvxpsec_softc *, enum marvell_tags *);
    129  1.1  hsuenaga 
    130  1.1  hsuenaga /*
    131  1.1  hsuenaga  * timer(callout) interface
    132  1.1  hsuenaga  *
    133  1.1  hsuenaga  * XXX: callout is not MP safe...
    134  1.1  hsuenaga  */
    135  1.1  hsuenaga STATIC void mvxpsec_timer(void *);
    136  1.1  hsuenaga 
    137  1.1  hsuenaga /*
    138  1.1  hsuenaga  * interrupt interface
    139  1.1  hsuenaga  */
    140  1.1  hsuenaga STATIC int mvxpsec_intr(void *);
    141  1.1  hsuenaga INLINE void mvxpsec_intr_cleanup(struct mvxpsec_softc *);
    142  1.1  hsuenaga STATIC int mvxpsec_eintr(void *);
    143  1.1  hsuenaga STATIC uint32_t mvxpsec_intr_ack(struct mvxpsec_softc *);
    144  1.1  hsuenaga STATIC uint32_t mvxpsec_eintr_ack(struct mvxpsec_softc *);
    145  1.1  hsuenaga INLINE void mvxpsec_intr_cnt(struct mvxpsec_softc *, int);
    146  1.1  hsuenaga 
    147  1.1  hsuenaga /*
    148  1.1  hsuenaga  * memory allocators and VM management
    149  1.1  hsuenaga  */
    150  1.1  hsuenaga STATIC struct mvxpsec_devmem *mvxpsec_alloc_devmem(struct mvxpsec_softc *,
    151  1.1  hsuenaga     paddr_t, int);
    152  1.1  hsuenaga STATIC int mvxpsec_init_sram(struct mvxpsec_softc *);
    153  1.1  hsuenaga 
    154  1.1  hsuenaga /*
    155  1.1  hsuenaga  * Low-level DMA interface
    156  1.1  hsuenaga  */
    157  1.1  hsuenaga STATIC int mvxpsec_init_dma(struct mvxpsec_softc *,
    158  1.1  hsuenaga     struct marvell_attach_args *);
    159  1.1  hsuenaga INLINE int mvxpsec_dma_wait(struct mvxpsec_softc *);
    160  1.1  hsuenaga INLINE int mvxpsec_acc_wait(struct mvxpsec_softc *);
    161  1.1  hsuenaga INLINE struct mvxpsec_descriptor_handle *mvxpsec_dma_getdesc(struct mvxpsec_softc *);
    162  1.1  hsuenaga _INLINE void mvxpsec_dma_putdesc(struct mvxpsec_softc *, struct mvxpsec_descriptor_handle *);
    163  1.1  hsuenaga INLINE void mvxpsec_dma_setup(struct mvxpsec_descriptor_handle *,
    164  1.1  hsuenaga     uint32_t, uint32_t, uint32_t);
    165  1.1  hsuenaga INLINE void mvxpsec_dma_cat(struct mvxpsec_softc *,
    166  1.1  hsuenaga     struct mvxpsec_descriptor_handle *, struct mvxpsec_descriptor_handle *);
    167  1.1  hsuenaga 
    168  1.1  hsuenaga /*
    169  1.1  hsuenaga  * High-level DMA interface
    170  1.1  hsuenaga  */
    171  1.1  hsuenaga INLINE int mvxpsec_dma_copy0(struct mvxpsec_softc *,
    172  1.1  hsuenaga     mvxpsec_dma_ring *, uint32_t, uint32_t, uint32_t);
    173  1.1  hsuenaga INLINE int mvxpsec_dma_copy(struct mvxpsec_softc *,
    174  1.1  hsuenaga     mvxpsec_dma_ring *, uint32_t, uint32_t, uint32_t);
    175  1.1  hsuenaga INLINE int mvxpsec_dma_acc_activate(struct mvxpsec_softc *,
    176  1.1  hsuenaga     mvxpsec_dma_ring *);
    177  1.1  hsuenaga INLINE void mvxpsec_dma_finalize(struct mvxpsec_softc *,
    178  1.1  hsuenaga     mvxpsec_dma_ring *);
    179  1.1  hsuenaga INLINE void mvxpsec_dma_free(struct mvxpsec_softc *,
    180  1.1  hsuenaga     mvxpsec_dma_ring *);
    181  1.1  hsuenaga INLINE int mvxpsec_dma_copy_packet(struct mvxpsec_softc *, struct mvxpsec_packet *);
    182  1.1  hsuenaga INLINE int mvxpsec_dma_sync_packet(struct mvxpsec_softc *, struct mvxpsec_packet *);
    183  1.1  hsuenaga 
    184  1.1  hsuenaga /*
    185  1.1  hsuenaga  * Session management interface (OpenCrypto)
    186  1.1  hsuenaga  */
    187  1.1  hsuenaga #define MVXPSEC_SESSION(sid)	((sid) & 0x0fffffff)
    188  1.1  hsuenaga #define MVXPSEC_SID(crd, sesn)	(((crd) << 28) | ((sesn) & 0x0fffffff))
    189  1.1  hsuenaga /* pool management */
    190  1.1  hsuenaga STATIC int mvxpsec_session_ctor(void *, void *, int);
    191  1.1  hsuenaga STATIC void mvxpsec_session_dtor(void *, void *);
    192  1.1  hsuenaga STATIC int mvxpsec_packet_ctor(void *, void *, int);
    193  1.1  hsuenaga STATIC void mvxpsec_packet_dtor(void *, void *);
    194  1.1  hsuenaga 
    195  1.1  hsuenaga /* session management */
    196  1.1  hsuenaga STATIC struct mvxpsec_session *mvxpsec_session_alloc(struct mvxpsec_softc *);
    197  1.1  hsuenaga STATIC void mvxpsec_session_dealloc(struct mvxpsec_session *);
    198  1.1  hsuenaga INLINE struct mvxpsec_session *mvxpsec_session_lookup(struct mvxpsec_softc *, int);
    199  1.1  hsuenaga INLINE int mvxpsec_session_ref(struct mvxpsec_session *);
    200  1.1  hsuenaga INLINE void mvxpsec_session_unref(struct mvxpsec_session *);
    201  1.1  hsuenaga 
    202  1.1  hsuenaga /* packet management */
    203  1.1  hsuenaga STATIC struct mvxpsec_packet *mvxpsec_packet_alloc(struct mvxpsec_session *);
    204  1.1  hsuenaga INLINE void mvxpsec_packet_enqueue(struct mvxpsec_packet *);
    205  1.1  hsuenaga STATIC void mvxpsec_packet_dealloc(struct mvxpsec_packet *);
    206  1.1  hsuenaga STATIC int mvxpsec_done_packet(struct mvxpsec_packet *);
    207  1.1  hsuenaga 
    208  1.1  hsuenaga /* session header manegement */
    209  1.1  hsuenaga STATIC int mvxpsec_header_finalize(struct mvxpsec_packet *);
    210  1.1  hsuenaga 
    211  1.1  hsuenaga /* packet queue management */
    212  1.1  hsuenaga INLINE void mvxpsec_drop(struct mvxpsec_softc *, struct cryptop *, struct mvxpsec_packet *, int);
    213  1.1  hsuenaga STATIC int mvxpsec_dispatch_queue(struct mvxpsec_softc *);
    214  1.1  hsuenaga 
    215  1.4   msaitoh /* opencrypto operation */
    216  1.1  hsuenaga INLINE int mvxpsec_parse_crd(struct mvxpsec_packet *, struct cryptodesc *);
    217  1.1  hsuenaga INLINE int mvxpsec_parse_crp(struct mvxpsec_packet *);
    218  1.1  hsuenaga 
    219  1.1  hsuenaga /* payload data management */
    220  1.1  hsuenaga INLINE int mvxpsec_packet_setcrp(struct mvxpsec_packet *, struct cryptop *);
    221  1.1  hsuenaga STATIC int mvxpsec_packet_setdata(struct mvxpsec_packet *, void *, uint32_t);
    222  1.1  hsuenaga STATIC int mvxpsec_packet_setmbuf(struct mvxpsec_packet *, struct mbuf *);
    223  1.1  hsuenaga STATIC int mvxpsec_packet_setuio(struct mvxpsec_packet *, struct uio *);
    224  1.1  hsuenaga STATIC int mvxpsec_packet_rdata(struct mvxpsec_packet *, int, int, void *);
    225  1.1  hsuenaga _STATIC int mvxpsec_packet_wdata(struct mvxpsec_packet *, int, int, void *);
    226  1.1  hsuenaga STATIC int mvxpsec_packet_write_iv(struct mvxpsec_packet *, void *, int);
    227  1.1  hsuenaga STATIC int mvxpsec_packet_copy_iv(struct mvxpsec_packet *, int, int);
    228  1.1  hsuenaga 
    229  1.1  hsuenaga /* key pre-computation */
    230  1.1  hsuenaga STATIC int mvxpsec_key_precomp(int, void *, int, void *, void *);
    231  1.1  hsuenaga STATIC int mvxpsec_hmac_precomp(int, void *, int, void *, void *);
    232  1.1  hsuenaga 
    233  1.1  hsuenaga /* crypto operation management */
    234  1.1  hsuenaga INLINE void mvxpsec_packet_reset_op(struct mvxpsec_packet *);
    235  1.1  hsuenaga INLINE void mvxpsec_packet_update_op_order(struct mvxpsec_packet *, int);
    236  1.1  hsuenaga 
    237  1.1  hsuenaga /*
    238  1.1  hsuenaga  * parameter converters
    239  1.1  hsuenaga  */
    240  1.1  hsuenaga INLINE uint32_t mvxpsec_alg2acc(uint32_t alg);
    241  1.1  hsuenaga INLINE uint32_t mvxpsec_aesklen(int klen);
    242  1.1  hsuenaga 
    243  1.1  hsuenaga /*
    244  1.1  hsuenaga  * string formatters
    245  1.1  hsuenaga  */
    246  1.1  hsuenaga _STATIC const char *s_ctrlreg(uint32_t);
    247  1.1  hsuenaga _STATIC const char *s_winreg(uint32_t);
    248  1.1  hsuenaga _STATIC const char *s_errreg(uint32_t);
    249  1.1  hsuenaga _STATIC const char *s_xpsecintr(uint32_t);
    250  1.1  hsuenaga _STATIC const char *s_ctlalg(uint32_t);
    251  1.1  hsuenaga _STATIC const char *s_xpsec_op(uint32_t);
    252  1.1  hsuenaga _STATIC const char *s_xpsec_enc(uint32_t);
    253  1.1  hsuenaga _STATIC const char *s_xpsec_mac(uint32_t);
    254  1.1  hsuenaga _STATIC const char *s_xpsec_frag(uint32_t);
    255  1.1  hsuenaga 
    256  1.1  hsuenaga /*
    257  1.1  hsuenaga  * debugging supports
    258  1.1  hsuenaga  */
    259  1.1  hsuenaga #ifdef MVXPSEC_DEBUG
    260  1.1  hsuenaga _STATIC void mvxpsec_dump_dmaq(struct mvxpsec_descriptor_handle *);
    261  1.1  hsuenaga _STATIC void mvxpsec_dump_reg(struct mvxpsec_softc *);
    262  1.1  hsuenaga _STATIC void mvxpsec_dump_sram(const char *, struct mvxpsec_softc *, size_t);
    263  1.1  hsuenaga _STATIC void mvxpsec_dump_data(const char *, void *, size_t);
    264  1.1  hsuenaga 
    265  1.1  hsuenaga _STATIC void mvxpsec_dump_packet(const char *, struct mvxpsec_packet *);
    266  1.1  hsuenaga _STATIC void mvxpsec_dump_packet_data(const char *, struct mvxpsec_packet *);
    267  1.1  hsuenaga _STATIC void mvxpsec_dump_packet_desc(const char *, struct mvxpsec_packet *);
    268  1.1  hsuenaga 
    269  1.1  hsuenaga _STATIC void mvxpsec_dump_acc_config(const char *, uint32_t);
    270  1.1  hsuenaga _STATIC void mvxpsec_dump_acc_encdata(const char *, uint32_t, uint32_t);
    271  1.1  hsuenaga _STATIC void mvxpsec_dump_acc_enclen(const char *, uint32_t);
    272  1.1  hsuenaga _STATIC void mvxpsec_dump_acc_enckey(const char *, uint32_t);
    273  1.1  hsuenaga _STATIC void mvxpsec_dump_acc_enciv(const char *, uint32_t);
    274  1.1  hsuenaga _STATIC void mvxpsec_dump_acc_macsrc(const char *, uint32_t);
    275  1.1  hsuenaga _STATIC void mvxpsec_dump_acc_macdst(const char *, uint32_t);
    276  1.1  hsuenaga _STATIC void mvxpsec_dump_acc_maciv(const char *, uint32_t);
    277  1.1  hsuenaga #endif
    278  1.1  hsuenaga 
    279  1.1  hsuenaga /*
    280  1.1  hsuenaga  * global configurations, params, work spaces, ...
    281  1.1  hsuenaga  *
    282  1.1  hsuenaga  * XXX: use sysctl for global configurations
    283  1.1  hsuenaga  */
    284  1.1  hsuenaga /* waiting for device */
    285  1.1  hsuenaga static int mvxpsec_wait_interval = 10;		/* usec */
    286  1.1  hsuenaga static int mvxpsec_wait_retry = 100;		/* times = wait for 1 [msec] */
    287  1.1  hsuenaga #ifdef MVXPSEC_DEBUG
    288  1.1  hsuenaga static uint32_t mvxpsec_debug = MVXPSEC_DEBUG;	/* debug level */
    289  1.1  hsuenaga #endif
    290  1.1  hsuenaga 
    291  1.1  hsuenaga /*
    292  1.1  hsuenaga  * Register accessors
    293  1.1  hsuenaga  */
    294  1.1  hsuenaga #define MVXPSEC_WRITE(sc, off, val) \
    295  1.1  hsuenaga 	bus_space_write_4((sc)->sc_iot, (sc)->sc_ioh, (off), (val))
    296  1.1  hsuenaga #define MVXPSEC_READ(sc, off) \
    297  1.1  hsuenaga 	bus_space_read_4((sc)->sc_iot, (sc)->sc_ioh, (off))
    298  1.1  hsuenaga 
    299  1.1  hsuenaga /*
    300  1.1  hsuenaga  * device driver autoconf interface
    301  1.1  hsuenaga  */
    302  1.1  hsuenaga CFATTACH_DECL2_NEW(mvxpsec_mbus, sizeof(struct mvxpsec_softc),
    303  1.1  hsuenaga     mvxpsec_match, mvxpsec_attach, NULL, NULL, NULL, NULL);
    304  1.1  hsuenaga 
    305  1.1  hsuenaga STATIC int
    306  1.1  hsuenaga mvxpsec_match(device_t dev, cfdata_t match, void *aux)
    307  1.1  hsuenaga {
    308  1.1  hsuenaga 	struct marvell_attach_args *mva = aux;
    309  1.1  hsuenaga 	uint32_t tag;
    310  1.1  hsuenaga 	int window;
    311  1.1  hsuenaga 
    312  1.1  hsuenaga 	if (strcmp(mva->mva_name, match->cf_name) != 0)
    313  1.1  hsuenaga 		return 0;
    314  1.1  hsuenaga 	if (mva->mva_offset == MVA_OFFSET_DEFAULT)
    315  1.1  hsuenaga 		return 0;
    316  1.1  hsuenaga 
    317  1.1  hsuenaga 	switch (mva->mva_unit) {
    318  1.1  hsuenaga 	case 0:
    319  1.1  hsuenaga 		tag = ARMADAXP_TAG_CRYPT0;
    320  1.1  hsuenaga 		break;
    321  1.1  hsuenaga 	case 1:
    322  1.1  hsuenaga 		tag = ARMADAXP_TAG_CRYPT1;
    323  1.1  hsuenaga 		break;
    324  1.1  hsuenaga 	default:
    325  1.1  hsuenaga 		aprint_error_dev(dev,
    326  1.1  hsuenaga 		    "unit %d is not supported\n", mva->mva_unit);
    327  1.1  hsuenaga 		return 0;
    328  1.1  hsuenaga 	}
    329  1.1  hsuenaga 
    330  1.1  hsuenaga 	window = mvsoc_target(tag, NULL, NULL, NULL, NULL);
    331  1.1  hsuenaga 	if (window >= nwindow) {
    332  1.1  hsuenaga 		aprint_error_dev(dev,
    333  1.1  hsuenaga 		    "Security Accelerator SRAM is not configured.\n");
    334  1.1  hsuenaga 		return 0;
    335  1.1  hsuenaga 	}
    336  1.1  hsuenaga 
    337  1.1  hsuenaga 	return 1;
    338  1.1  hsuenaga }
    339  1.1  hsuenaga 
    340  1.1  hsuenaga STATIC void
    341  1.1  hsuenaga mvxpsec_attach(device_t parent, device_t self, void *aux)
    342  1.1  hsuenaga {
    343  1.1  hsuenaga 	struct marvell_attach_args *mva = aux;
    344  1.1  hsuenaga 	struct mvxpsec_softc *sc = device_private(self);
    345  1.1  hsuenaga 	int v;
    346  1.1  hsuenaga 	int i;
    347  1.1  hsuenaga 
    348  1.1  hsuenaga 	sc->sc_dev = self;
    349  1.1  hsuenaga 
    350  1.1  hsuenaga 	aprint_normal(": Marvell Crypto Engines and Security Accelerator\n");
    351  1.1  hsuenaga 	aprint_naive("\n");
    352  1.1  hsuenaga #ifdef MVXPSEC_MULTI_PACKET
    353  1.1  hsuenaga 	aprint_normal_dev(sc->sc_dev, "multi-packet chained mode enabled.\n");
    354  1.1  hsuenaga #else
    355  1.1  hsuenaga 	aprint_normal_dev(sc->sc_dev, "multi-packet chained mode disabled.\n");
    356  1.1  hsuenaga #endif
    357  1.1  hsuenaga 	aprint_normal_dev(sc->sc_dev,
    358  1.1  hsuenaga 	    "Max %d sessions.\n", MVXPSEC_MAX_SESSIONS);
    359  1.1  hsuenaga 
    360  1.1  hsuenaga 	/* mutex */
    361  1.1  hsuenaga 	mutex_init(&sc->sc_session_mtx, MUTEX_DEFAULT, IPL_NET);
    362  1.1  hsuenaga 	mutex_init(&sc->sc_dma_mtx, MUTEX_DEFAULT, IPL_NET);
    363  1.1  hsuenaga 	mutex_init(&sc->sc_queue_mtx, MUTEX_DEFAULT, IPL_NET);
    364  1.1  hsuenaga 
    365  1.1  hsuenaga 	/* Packet queue */
    366  1.1  hsuenaga 	SIMPLEQ_INIT(&sc->sc_wait_queue);
    367  1.1  hsuenaga 	SIMPLEQ_INIT(&sc->sc_run_queue);
    368  1.1  hsuenaga 	SLIST_INIT(&sc->sc_free_list);
    369  1.1  hsuenaga 	sc->sc_wait_qlen = 0;
    370  1.1  hsuenaga #ifdef MVXPSEC_MULTI_PACKET
    371  1.1  hsuenaga 	sc->sc_wait_qlimit = 16;
    372  1.1  hsuenaga #else
    373  1.1  hsuenaga 	sc->sc_wait_qlimit = 0;
    374  1.1  hsuenaga #endif
    375  1.1  hsuenaga 	sc->sc_free_qlen = 0;
    376  1.1  hsuenaga 
    377  1.1  hsuenaga 	/* Timer */
    378  1.1  hsuenaga 	callout_init(&sc->sc_timeout, 0); /* XXX: use CALLOUT_MPSAFE */
    379  1.1  hsuenaga 	callout_setfunc(&sc->sc_timeout, mvxpsec_timer, sc);
    380  1.1  hsuenaga 
    381  1.1  hsuenaga 	/* I/O */
    382  1.1  hsuenaga 	sc->sc_iot = mva->mva_iot;
    383  1.1  hsuenaga 	if (bus_space_subregion(mva->mva_iot, mva->mva_ioh,
    384  1.1  hsuenaga 	    mva->mva_offset, mva->mva_size, &sc->sc_ioh)) {
    385  1.1  hsuenaga 		aprint_error_dev(self, "Cannot map registers\n");
    386  1.1  hsuenaga 		return;
    387  1.1  hsuenaga 	}
    388  1.1  hsuenaga 
    389  1.1  hsuenaga 	/* DMA */
    390  1.1  hsuenaga 	sc->sc_dmat = mva->mva_dmat;
    391  1.1  hsuenaga 	if (mvxpsec_init_dma(sc, mva) < 0)
    392  1.1  hsuenaga 		return;
    393  1.1  hsuenaga 
    394  1.1  hsuenaga 	/* SRAM */
    395  1.1  hsuenaga 	if (mvxpsec_init_sram(sc) < 0)
    396  1.1  hsuenaga 		return;
    397  1.1  hsuenaga 
    398  1.1  hsuenaga 	/* Registers */
    399  1.1  hsuenaga 	mvxpsec_wininit(sc, mva->mva_tags);
    400  1.1  hsuenaga 
    401  1.1  hsuenaga 	/* INTR */
    402  1.1  hsuenaga 	MVXPSEC_WRITE(sc, MVXPSEC_INT_MASK, MVXPSEC_DEFAULT_INT);
    403  1.1  hsuenaga 	MVXPSEC_WRITE(sc, MV_TDMA_ERR_MASK, MVXPSEC_DEFAULT_ERR);
    404  1.1  hsuenaga 	sc->sc_done_ih =
    405  1.1  hsuenaga 	    marvell_intr_establish(mva->mva_irq, IPL_NET, mvxpsec_intr, sc);
    406  1.1  hsuenaga 	/* XXX: sould pass error IRQ using mva */
    407  1.1  hsuenaga 	sc->sc_error_ih = marvell_intr_establish(MVXPSEC_ERR_INT(sc),
    408  1.1  hsuenaga 	    IPL_NET, mvxpsec_eintr, sc);
    409  1.1  hsuenaga 	aprint_normal_dev(self,
    410  1.1  hsuenaga 	    "Error Reporting IRQ %d\n", MVXPSEC_ERR_INT(sc));
    411  1.1  hsuenaga 
    412  1.1  hsuenaga 	/* Initialize TDMA (It's enabled here, but waiting for SA) */
    413  1.1  hsuenaga 	if (mvxpsec_dma_wait(sc) < 0)
    414  1.1  hsuenaga 		panic("%s: DMA DEVICE not responding\n", __func__);
    415  1.1  hsuenaga 	MVXPSEC_WRITE(sc, MV_TDMA_CNT, 0);
    416  1.1  hsuenaga 	MVXPSEC_WRITE(sc, MV_TDMA_SRC, 0);
    417  1.1  hsuenaga 	MVXPSEC_WRITE(sc, MV_TDMA_DST, 0);
    418  1.1  hsuenaga 	MVXPSEC_WRITE(sc, MV_TDMA_NXT, 0);
    419  1.1  hsuenaga 	MVXPSEC_WRITE(sc, MV_TDMA_CUR, 0);
    420  1.1  hsuenaga 	v  = MVXPSEC_READ(sc, MV_TDMA_CONTROL);
    421  1.1  hsuenaga 	v |= MV_TDMA_CONTROL_ENABLE;
    422  1.1  hsuenaga 	MVXPSEC_WRITE(sc, MV_TDMA_CONTROL, v);
    423  1.1  hsuenaga 
    424  1.1  hsuenaga 	/* Initialize SA */
    425  1.1  hsuenaga 	if (mvxpsec_acc_wait(sc) < 0)
    426  1.1  hsuenaga 		panic("%s: MVXPSEC not responding\n", __func__);
    427  1.1  hsuenaga 	v  = MVXPSEC_READ(sc, MV_ACC_CONFIG);
    428  1.1  hsuenaga 	v &= ~MV_ACC_CONFIG_STOP_ON_ERR;
    429  1.1  hsuenaga 	v |= MV_ACC_CONFIG_MULT_PKT;
    430  1.1  hsuenaga 	v |= MV_ACC_CONFIG_WAIT_TDMA;
    431  1.1  hsuenaga 	v |= MV_ACC_CONFIG_ACT_TDMA;
    432  1.1  hsuenaga 	MVXPSEC_WRITE(sc, MV_ACC_CONFIG, v);
    433  1.1  hsuenaga 	MVXPSEC_WRITE(sc, MV_ACC_DESC, 0);
    434  1.1  hsuenaga 	MVXPSEC_WRITE(sc, MV_ACC_COMMAND, MV_ACC_COMMAND_STOP);
    435  1.1  hsuenaga 
    436  1.1  hsuenaga 	/* Session */
    437  1.1  hsuenaga 	sc->sc_session_pool =
    438  1.1  hsuenaga 	    pool_cache_init(sizeof(struct mvxpsec_session), 0, 0, 0,
    439  1.1  hsuenaga 	    "mvxpsecpl", NULL, IPL_NET,
    440  1.1  hsuenaga 	    mvxpsec_session_ctor, mvxpsec_session_dtor, sc);
    441  1.1  hsuenaga 	pool_cache_sethiwat(sc->sc_session_pool, MVXPSEC_MAX_SESSIONS);
    442  1.1  hsuenaga 	pool_cache_setlowat(sc->sc_session_pool, MVXPSEC_MAX_SESSIONS / 2);
    443  1.1  hsuenaga 	sc->sc_last_session = NULL;
    444  1.1  hsuenaga 
    445  1.1  hsuenaga 	/* Pakcet */
    446  1.1  hsuenaga 	sc->sc_packet_pool =
    447  1.1  hsuenaga 	    pool_cache_init(sizeof(struct mvxpsec_session), 0, 0, 0,
    448  1.1  hsuenaga 	    "mvxpsec_pktpl", NULL, IPL_NET,
    449  1.1  hsuenaga 	    mvxpsec_packet_ctor, mvxpsec_packet_dtor, sc);
    450  1.1  hsuenaga 	pool_cache_sethiwat(sc->sc_packet_pool, MVXPSEC_MAX_SESSIONS);
    451  1.1  hsuenaga 	pool_cache_setlowat(sc->sc_packet_pool, MVXPSEC_MAX_SESSIONS / 2);
    452  1.1  hsuenaga 
    453  1.1  hsuenaga 	/* Register to EVCNT framework */
    454  1.1  hsuenaga 	mvxpsec_evcnt_attach(sc);
    455  1.1  hsuenaga 
    456  1.1  hsuenaga 	/* Register to Opencrypto */
    457  1.1  hsuenaga 	for (i = 0; i < MVXPSEC_MAX_SESSIONS; i++) {
    458  1.1  hsuenaga 		sc->sc_sessions[i] = NULL;
    459  1.1  hsuenaga 	}
    460  1.1  hsuenaga 	if (mvxpsec_register(sc))
    461  1.1  hsuenaga 		panic("cannot initialize OpenCrypto module.\n");
    462  1.1  hsuenaga 
    463  1.1  hsuenaga 	return;
    464  1.1  hsuenaga }
    465  1.1  hsuenaga 
    466  1.1  hsuenaga STATIC void
    467  1.1  hsuenaga mvxpsec_evcnt_attach(struct mvxpsec_softc *sc)
    468  1.1  hsuenaga {
    469  1.1  hsuenaga 	struct mvxpsec_evcnt *sc_ev = &sc->sc_ev;
    470  1.1  hsuenaga 
    471  1.1  hsuenaga 	evcnt_attach_dynamic(&sc_ev->intr_all, EVCNT_TYPE_INTR,
    472  1.1  hsuenaga 	    NULL, device_xname(sc->sc_dev), "Main Intr.");
    473  1.1  hsuenaga 	evcnt_attach_dynamic(&sc_ev->intr_auth, EVCNT_TYPE_INTR,
    474  1.1  hsuenaga 	    NULL, device_xname(sc->sc_dev), "Auth Intr.");
    475  1.1  hsuenaga 	evcnt_attach_dynamic(&sc_ev->intr_des, EVCNT_TYPE_INTR,
    476  1.1  hsuenaga 	    NULL, device_xname(sc->sc_dev), "DES Intr.");
    477  1.1  hsuenaga 	evcnt_attach_dynamic(&sc_ev->intr_aes_enc, EVCNT_TYPE_INTR,
    478  1.1  hsuenaga 	    NULL, device_xname(sc->sc_dev), "AES-Encrypt Intr.");
    479  1.1  hsuenaga 	evcnt_attach_dynamic(&sc_ev->intr_aes_dec, EVCNT_TYPE_INTR,
    480  1.1  hsuenaga 	    NULL, device_xname(sc->sc_dev), "AES-Decrypt Intr.");
    481  1.1  hsuenaga 	evcnt_attach_dynamic(&sc_ev->intr_enc, EVCNT_TYPE_INTR,
    482  1.1  hsuenaga 	    NULL, device_xname(sc->sc_dev), "Crypto Intr.");
    483  1.1  hsuenaga 	evcnt_attach_dynamic(&sc_ev->intr_sa, EVCNT_TYPE_INTR,
    484  1.1  hsuenaga 	    NULL, device_xname(sc->sc_dev), "SA Intr.");
    485  1.1  hsuenaga 	evcnt_attach_dynamic(&sc_ev->intr_acctdma, EVCNT_TYPE_INTR,
    486  1.1  hsuenaga 	    NULL, device_xname(sc->sc_dev), "AccTDMA Intr.");
    487  1.1  hsuenaga 	evcnt_attach_dynamic(&sc_ev->intr_comp, EVCNT_TYPE_INTR,
    488  1.1  hsuenaga 	    NULL, device_xname(sc->sc_dev), "TDMA-Complete Intr.");
    489  1.1  hsuenaga 	evcnt_attach_dynamic(&sc_ev->intr_own, EVCNT_TYPE_INTR,
    490  1.1  hsuenaga 	    NULL, device_xname(sc->sc_dev), "TDMA-Ownership Intr.");
    491  1.1  hsuenaga 	evcnt_attach_dynamic(&sc_ev->intr_acctdma_cont, EVCNT_TYPE_INTR,
    492  1.1  hsuenaga 	    NULL, device_xname(sc->sc_dev), "AccTDMA-Continue Intr.");
    493  1.1  hsuenaga 
    494  1.1  hsuenaga 	evcnt_attach_dynamic(&sc_ev->session_new, EVCNT_TYPE_MISC,
    495  1.1  hsuenaga 	    NULL, device_xname(sc->sc_dev), "New-Session");
    496  1.1  hsuenaga 	evcnt_attach_dynamic(&sc_ev->session_free, EVCNT_TYPE_MISC,
    497  1.1  hsuenaga 	    NULL, device_xname(sc->sc_dev), "Free-Session");
    498  1.1  hsuenaga 
    499  1.1  hsuenaga 	evcnt_attach_dynamic(&sc_ev->packet_ok, EVCNT_TYPE_MISC,
    500  1.1  hsuenaga 	    NULL, device_xname(sc->sc_dev), "Packet-OK");
    501  1.1  hsuenaga 	evcnt_attach_dynamic(&sc_ev->packet_err, EVCNT_TYPE_MISC,
    502  1.1  hsuenaga 	    NULL, device_xname(sc->sc_dev), "Packet-ERR");
    503  1.1  hsuenaga 
    504  1.1  hsuenaga 	evcnt_attach_dynamic(&sc_ev->dispatch_packets, EVCNT_TYPE_MISC,
    505  1.1  hsuenaga 	    NULL, device_xname(sc->sc_dev), "Packet-Dispatch");
    506  1.1  hsuenaga 	evcnt_attach_dynamic(&sc_ev->dispatch_queue, EVCNT_TYPE_MISC,
    507  1.1  hsuenaga 	    NULL, device_xname(sc->sc_dev), "Queue-Dispatch");
    508  1.1  hsuenaga 	evcnt_attach_dynamic(&sc_ev->queue_full, EVCNT_TYPE_MISC,
    509  1.1  hsuenaga 	    NULL, device_xname(sc->sc_dev), "Queue-Full");
    510  1.1  hsuenaga 	evcnt_attach_dynamic(&sc_ev->max_dispatch, EVCNT_TYPE_MISC,
    511  1.1  hsuenaga 	    NULL, device_xname(sc->sc_dev), "Max-Dispatch");
    512  1.1  hsuenaga 	evcnt_attach_dynamic(&sc_ev->max_done, EVCNT_TYPE_MISC,
    513  1.1  hsuenaga 	    NULL, device_xname(sc->sc_dev), "Max-Done");
    514  1.1  hsuenaga }
    515  1.1  hsuenaga 
    516  1.1  hsuenaga /*
    517  1.1  hsuenaga  * Register setup
    518  1.1  hsuenaga  */
    519  1.1  hsuenaga STATIC int mvxpsec_wininit(struct mvxpsec_softc *sc, enum marvell_tags *tags)
    520  1.1  hsuenaga {
    521  1.1  hsuenaga 	device_t pdev = device_parent(sc->sc_dev);
    522  1.1  hsuenaga 	uint64_t base;
    523  1.1  hsuenaga 	uint32_t size, reg;
    524  1.1  hsuenaga 	int window, target, attr, rv, i;
    525  1.1  hsuenaga 
    526  1.1  hsuenaga 	/* disable all window */
    527  1.1  hsuenaga 	for (window = 0; window < MV_TDMA_NWINDOW; window++)
    528  1.1  hsuenaga 	{
    529  1.1  hsuenaga 		MVXPSEC_WRITE(sc, MV_TDMA_BAR(window), 0);
    530  1.1  hsuenaga 		MVXPSEC_WRITE(sc, MV_TDMA_ATTR(window), 0);
    531  1.1  hsuenaga 	}
    532  1.1  hsuenaga 
    533  1.1  hsuenaga 	for (window = 0, i = 0;
    534  1.1  hsuenaga 	    tags[i] != MARVELL_TAG_UNDEFINED && window < MV_TDMA_NWINDOW; i++) {
    535  1.1  hsuenaga 		rv = marvell_winparams_by_tag(pdev, tags[i],
    536  1.1  hsuenaga 		    &target, &attr, &base, &size);
    537  1.1  hsuenaga 		if (rv != 0 || size == 0)
    538  1.1  hsuenaga 			continue;
    539  1.1  hsuenaga 
    540  1.1  hsuenaga 		if (base > 0xffffffffULL) {
    541  1.1  hsuenaga 			aprint_error_dev(sc->sc_dev,
    542  1.1  hsuenaga 			    "can't remap window %d\n", window);
    543  1.1  hsuenaga 			continue;
    544  1.1  hsuenaga 		}
    545  1.1  hsuenaga 
    546  1.1  hsuenaga 		reg  = MV_TDMA_BAR_BASE(base);
    547  1.1  hsuenaga 		MVXPSEC_WRITE(sc, MV_TDMA_BAR(window), reg);
    548  1.1  hsuenaga 
    549  1.1  hsuenaga 		reg  = MV_TDMA_ATTR_TARGET(target);
    550  1.1  hsuenaga 		reg |= MV_TDMA_ATTR_ATTR(attr);
    551  1.1  hsuenaga 		reg |= MV_TDMA_ATTR_SIZE(size);
    552  1.1  hsuenaga 		reg |= MV_TDMA_ATTR_ENABLE;
    553  1.1  hsuenaga 		MVXPSEC_WRITE(sc, MV_TDMA_ATTR(window), reg);
    554  1.1  hsuenaga 
    555  1.1  hsuenaga 		window++;
    556  1.1  hsuenaga 	}
    557  1.1  hsuenaga 
    558  1.1  hsuenaga 	return 0;
    559  1.1  hsuenaga }
    560  1.1  hsuenaga 
    561  1.1  hsuenaga /*
    562  1.1  hsuenaga  * Timer handling
    563  1.1  hsuenaga  */
    564  1.1  hsuenaga STATIC void
    565  1.1  hsuenaga mvxpsec_timer(void *aux)
    566  1.1  hsuenaga {
    567  1.1  hsuenaga 	struct mvxpsec_softc *sc = aux;
    568  1.1  hsuenaga 	struct mvxpsec_packet *mv_p;
    569  1.1  hsuenaga 	uint32_t reg;
    570  1.1  hsuenaga 	int ndone;
    571  1.1  hsuenaga 	int refill;
    572  1.1  hsuenaga 	int s;
    573  1.1  hsuenaga 
    574  1.1  hsuenaga 	/* IPL_SOFTCLOCK */
    575  1.1  hsuenaga 
    576  1.1  hsuenaga 	log(LOG_ERR, "%s: device timeout.\n", __func__);
    577  1.1  hsuenaga #ifdef MVXPSEC_DEBUG
    578  1.1  hsuenaga 	mvxpsec_dump_reg(sc);
    579  1.1  hsuenaga #endif
    580  1.1  hsuenaga 
    581  1.1  hsuenaga 	s = splnet();
    582  1.1  hsuenaga 	/* stop security accelerator */
    583  1.1  hsuenaga 	MVXPSEC_WRITE(sc, MV_ACC_COMMAND, MV_ACC_COMMAND_STOP);
    584  1.1  hsuenaga 
    585  1.1  hsuenaga 	/* stop TDMA */
    586  1.1  hsuenaga 	MVXPSEC_WRITE(sc, MV_TDMA_CONTROL, 0);
    587  1.1  hsuenaga 
    588  1.1  hsuenaga 	/* cleanup packet queue */
    589  1.1  hsuenaga 	mutex_enter(&sc->sc_queue_mtx);
    590  1.1  hsuenaga 	ndone = 0;
    591  1.1  hsuenaga 	while ( (mv_p = SIMPLEQ_FIRST(&sc->sc_run_queue)) != NULL) {
    592  1.1  hsuenaga 		SIMPLEQ_REMOVE_HEAD(&sc->sc_run_queue, queue);
    593  1.1  hsuenaga 
    594  1.1  hsuenaga 		mv_p->crp->crp_etype = EINVAL;
    595  1.1  hsuenaga 		mvxpsec_done_packet(mv_p);
    596  1.1  hsuenaga 		ndone++;
    597  1.1  hsuenaga 	}
    598  1.1  hsuenaga 	MVXPSEC_EVCNT_MAX(sc, max_done, ndone);
    599  1.1  hsuenaga 	sc->sc_flags &= ~HW_RUNNING;
    600  1.1  hsuenaga 	refill = (sc->sc_wait_qlen > 0) ? 1 : 0;
    601  1.1  hsuenaga 	mutex_exit(&sc->sc_queue_mtx);
    602  1.1  hsuenaga 
    603  1.1  hsuenaga 	/* reenable TDMA */
    604  1.1  hsuenaga 	if (mvxpsec_dma_wait(sc) < 0)
    605  1.1  hsuenaga 		panic("%s: failed to reset DMA DEVICE. give up.", __func__);
    606  1.1  hsuenaga 	MVXPSEC_WRITE(sc, MV_TDMA_CNT, 0);
    607  1.1  hsuenaga 	MVXPSEC_WRITE(sc, MV_TDMA_SRC, 0);
    608  1.1  hsuenaga 	MVXPSEC_WRITE(sc, MV_TDMA_DST, 0);
    609  1.1  hsuenaga 	MVXPSEC_WRITE(sc, MV_TDMA_CUR, 0);
    610  1.1  hsuenaga 	MVXPSEC_WRITE(sc, MV_TDMA_NXT, 0);
    611  1.1  hsuenaga 	reg  = MV_TDMA_DEFAULT_CONTROL;
    612  1.1  hsuenaga 	reg |= MV_TDMA_CONTROL_ENABLE;
    613  1.1  hsuenaga 	MVXPSEC_WRITE(sc, MV_TDMA_CONTROL, reg);
    614  1.1  hsuenaga 
    615  1.1  hsuenaga 	if (mvxpsec_acc_wait(sc) < 0)
    616  1.1  hsuenaga 		panic("%s: failed to reset MVXPSEC. give up.", __func__);
    617  1.1  hsuenaga 	reg  = MV_ACC_CONFIG_MULT_PKT;
    618  1.1  hsuenaga 	reg |= MV_ACC_CONFIG_WAIT_TDMA;
    619  1.1  hsuenaga 	reg |= MV_ACC_CONFIG_ACT_TDMA;
    620  1.1  hsuenaga 	MVXPSEC_WRITE(sc, MV_ACC_CONFIG, reg);
    621  1.1  hsuenaga 	MVXPSEC_WRITE(sc, MV_ACC_DESC, 0);
    622  1.1  hsuenaga 
    623  1.1  hsuenaga 	if (refill) {
    624  1.1  hsuenaga 		mutex_enter(&sc->sc_queue_mtx);
    625  1.1  hsuenaga 		mvxpsec_dispatch_queue(sc);
    626  1.1  hsuenaga 		mutex_exit(&sc->sc_queue_mtx);
    627  1.1  hsuenaga 	}
    628  1.1  hsuenaga 
    629  1.1  hsuenaga 	crypto_unblock(sc->sc_cid, CRYPTO_SYMQ|CRYPTO_ASYMQ);
    630  1.1  hsuenaga 	splx(s);
    631  1.1  hsuenaga }
    632  1.1  hsuenaga 
    633  1.1  hsuenaga /*
    634  1.1  hsuenaga  * DMA handling
    635  1.1  hsuenaga  */
    636  1.1  hsuenaga 
    637  1.1  hsuenaga /*
    638  1.1  hsuenaga  * Allocate kernel devmem and DMA safe memory with bus_dma API
    639  1.1  hsuenaga  * used for DMA descriptors.
    640  1.1  hsuenaga  *
    641  1.1  hsuenaga  * if phys != 0, assume phys is a DMA safe memory and bypass
    642  1.1  hsuenaga  * allocator.
    643  1.1  hsuenaga  */
    644  1.1  hsuenaga STATIC struct mvxpsec_devmem *
    645  1.1  hsuenaga mvxpsec_alloc_devmem(struct mvxpsec_softc *sc, paddr_t phys, int size)
    646  1.1  hsuenaga {
    647  1.1  hsuenaga 	struct mvxpsec_devmem *devmem;
    648  1.1  hsuenaga 	bus_dma_segment_t seg;
    649  1.1  hsuenaga 	int rseg;
    650  1.1  hsuenaga 	int err;
    651  1.1  hsuenaga 
    652  1.1  hsuenaga 	if (sc == NULL)
    653  1.1  hsuenaga 		return NULL;
    654  1.1  hsuenaga 
    655  1.3       chs 	devmem = kmem_alloc(sizeof(*devmem), KM_SLEEP);
    656  1.1  hsuenaga 	devmem->size = size;
    657  1.1  hsuenaga 
    658  1.1  hsuenaga 	if (phys) {
    659  1.1  hsuenaga 		seg.ds_addr = phys;
    660  1.1  hsuenaga 		seg.ds_len = devmem->size;
    661  1.1  hsuenaga 		rseg = 1;
    662  1.1  hsuenaga 		err = 0;
    663  1.1  hsuenaga 	}
    664  1.1  hsuenaga 	else {
    665  1.1  hsuenaga 		err = bus_dmamem_alloc(sc->sc_dmat,
    666  1.1  hsuenaga 		    devmem->size, PAGE_SIZE, 0,
    667  1.1  hsuenaga 		    &seg, MVXPSEC_DMA_MAX_SEGS, &rseg, BUS_DMA_NOWAIT);
    668  1.1  hsuenaga 	}
    669  1.1  hsuenaga 	if (err) {
    670  1.1  hsuenaga 		aprint_error_dev(sc->sc_dev, "can't alloc DMA buffer\n");
    671  1.1  hsuenaga 		goto fail_kmem_free;
    672  1.1  hsuenaga 	}
    673  1.1  hsuenaga 
    674  1.1  hsuenaga 	err = bus_dmamem_map(sc->sc_dmat, &seg, rseg,
    675  1.1  hsuenaga 	     devmem->size, &devmem->kva, BUS_DMA_NOWAIT);
    676  1.1  hsuenaga 	if (err) {
    677  1.1  hsuenaga 		aprint_error_dev(sc->sc_dev, "can't map DMA buffer\n");
    678  1.1  hsuenaga 		goto fail_dmamem_free;
    679  1.1  hsuenaga 	}
    680  1.1  hsuenaga 
    681  1.1  hsuenaga 	err = bus_dmamap_create(sc->sc_dmat,
    682  1.1  hsuenaga 	    size, 1, size, 0, BUS_DMA_NOWAIT, &devmem->map);
    683  1.1  hsuenaga 	if (err) {
    684  1.1  hsuenaga 		aprint_error_dev(sc->sc_dev, "can't create DMA map\n");
    685  1.1  hsuenaga 		goto fail_unmap;
    686  1.1  hsuenaga 	}
    687  1.1  hsuenaga 
    688  1.1  hsuenaga 	err = bus_dmamap_load(sc->sc_dmat,
    689  1.1  hsuenaga 	    devmem->map, devmem->kva, devmem->size, NULL,
    690  1.1  hsuenaga 	    BUS_DMA_NOWAIT);
    691  1.1  hsuenaga 	if (err) {
    692  1.1  hsuenaga 		aprint_error_dev(sc->sc_dev,
    693  1.1  hsuenaga 		   "can't load DMA buffer VA:%p PA:0x%08x\n",
    694  1.1  hsuenaga 		    devmem->kva, (int)seg.ds_addr);
    695  1.1  hsuenaga 		goto fail_destroy;
    696  1.1  hsuenaga 	}
    697  1.1  hsuenaga 
    698  1.1  hsuenaga 	return devmem;
    699  1.1  hsuenaga 
    700  1.1  hsuenaga fail_destroy:
    701  1.1  hsuenaga 	bus_dmamap_destroy(sc->sc_dmat, devmem->map);
    702  1.1  hsuenaga fail_unmap:
    703  1.1  hsuenaga 	bus_dmamem_unmap(sc->sc_dmat, devmem->kva, devmem->size);
    704  1.1  hsuenaga fail_dmamem_free:
    705  1.1  hsuenaga 	bus_dmamem_free(sc->sc_dmat, &seg, rseg);
    706  1.1  hsuenaga fail_kmem_free:
    707  1.1  hsuenaga 	kmem_free(devmem, sizeof(*devmem));
    708  1.1  hsuenaga 
    709  1.1  hsuenaga 	return NULL;
    710  1.1  hsuenaga }
    711  1.1  hsuenaga 
    712  1.1  hsuenaga /*
    713  1.1  hsuenaga  * Get DMA Descriptor from (DMA safe) descriptor pool.
    714  1.1  hsuenaga  */
    715  1.1  hsuenaga INLINE struct mvxpsec_descriptor_handle *
    716  1.1  hsuenaga mvxpsec_dma_getdesc(struct mvxpsec_softc *sc)
    717  1.1  hsuenaga {
    718  1.1  hsuenaga 	struct mvxpsec_descriptor_handle *entry;
    719  1.1  hsuenaga 
    720  1.1  hsuenaga 	/* must called with sc->sc_dma_mtx held */
    721  1.1  hsuenaga 	KASSERT(mutex_owned(&sc->sc_dma_mtx));
    722  1.1  hsuenaga 
    723  1.1  hsuenaga 	if (sc->sc_desc_ring_prod == sc->sc_desc_ring_cons)
    724  1.1  hsuenaga 		return NULL;
    725  1.1  hsuenaga 
    726  1.1  hsuenaga 	entry = &sc->sc_desc_ring[sc->sc_desc_ring_prod];
    727  1.1  hsuenaga 	sc->sc_desc_ring_prod++;
    728  1.1  hsuenaga 	if (sc->sc_desc_ring_prod >= sc->sc_desc_ring_size)
    729  1.1  hsuenaga 		sc->sc_desc_ring_prod -= sc->sc_desc_ring_size;
    730  1.1  hsuenaga 
    731  1.1  hsuenaga 	return entry;
    732  1.1  hsuenaga }
    733  1.1  hsuenaga 
    734  1.1  hsuenaga /*
    735  1.1  hsuenaga  * Put DMA Descriptor to descriptor pool.
    736  1.1  hsuenaga  */
    737  1.1  hsuenaga _INLINE void
    738  1.1  hsuenaga mvxpsec_dma_putdesc(struct mvxpsec_softc *sc,
    739  1.1  hsuenaga     struct mvxpsec_descriptor_handle *dh)
    740  1.1  hsuenaga {
    741  1.1  hsuenaga 	/* must called with sc->sc_dma_mtx held */
    742  1.1  hsuenaga 	KASSERT(mutex_owned(&sc->sc_dma_mtx));
    743  1.1  hsuenaga 
    744  1.1  hsuenaga 	sc->sc_desc_ring_cons++;
    745  1.1  hsuenaga 	if (sc->sc_desc_ring_cons >= sc->sc_desc_ring_size)
    746  1.1  hsuenaga 		sc->sc_desc_ring_cons -= sc->sc_desc_ring_size;
    747  1.1  hsuenaga 
    748  1.1  hsuenaga 	return;
    749  1.1  hsuenaga }
    750  1.1  hsuenaga 
    751  1.1  hsuenaga /*
    752  1.1  hsuenaga  * Setup DMA Descriptor
    753  1.1  hsuenaga  * copy from 'src' to 'dst' by 'size' bytes.
    754  1.1  hsuenaga  * 'src' or 'dst' must be SRAM address.
    755  1.1  hsuenaga  */
    756  1.1  hsuenaga INLINE void
    757  1.1  hsuenaga mvxpsec_dma_setup(struct mvxpsec_descriptor_handle *dh,
    758  1.1  hsuenaga     uint32_t dst, uint32_t src, uint32_t size)
    759  1.1  hsuenaga {
    760  1.1  hsuenaga 	struct mvxpsec_descriptor *desc;
    761  1.1  hsuenaga 
    762  1.1  hsuenaga 	desc = (struct mvxpsec_descriptor *)dh->_desc;
    763  1.1  hsuenaga 
    764  1.1  hsuenaga 	desc->tdma_dst = dst;
    765  1.1  hsuenaga 	desc->tdma_src = src;
    766  1.1  hsuenaga 	desc->tdma_word0 = size;
    767  1.1  hsuenaga 	if (size != 0)
    768  1.1  hsuenaga 		desc->tdma_word0 |= MV_TDMA_CNT_OWN;
    769  1.1  hsuenaga 	/* size == 0 is owned by ACC, not TDMA */
    770  1.1  hsuenaga 
    771  1.1  hsuenaga #ifdef MVXPSEC_DEBUG
    772  1.1  hsuenaga 	mvxpsec_dump_dmaq(dh);
    773  1.1  hsuenaga #endif
    774  1.1  hsuenaga 
    775  1.1  hsuenaga }
    776  1.1  hsuenaga 
    777  1.1  hsuenaga /*
    778  1.1  hsuenaga  * Concat 2 DMA
    779  1.1  hsuenaga  */
    780  1.1  hsuenaga INLINE void
    781  1.1  hsuenaga mvxpsec_dma_cat(struct mvxpsec_softc *sc,
    782  1.1  hsuenaga     struct mvxpsec_descriptor_handle *dh1,
    783  1.1  hsuenaga     struct mvxpsec_descriptor_handle *dh2)
    784  1.1  hsuenaga {
    785  1.1  hsuenaga 	((struct mvxpsec_descriptor*)dh1->_desc)->tdma_nxt = dh2->phys_addr;
    786  1.1  hsuenaga 	MVXPSEC_SYNC_DESC(sc, dh1, BUS_DMASYNC_PREWRITE);
    787  1.1  hsuenaga }
    788  1.1  hsuenaga 
    789  1.1  hsuenaga /*
    790  1.1  hsuenaga  * Schedule DMA Copy
    791  1.1  hsuenaga  */
    792  1.1  hsuenaga INLINE int
    793  1.1  hsuenaga mvxpsec_dma_copy0(struct mvxpsec_softc *sc, mvxpsec_dma_ring *r,
    794  1.1  hsuenaga     uint32_t dst, uint32_t src, uint32_t size)
    795  1.1  hsuenaga {
    796  1.1  hsuenaga 	struct mvxpsec_descriptor_handle *dh;
    797  1.1  hsuenaga 
    798  1.1  hsuenaga 	dh = mvxpsec_dma_getdesc(sc);
    799  1.1  hsuenaga 	if (dh == NULL) {
    800  1.1  hsuenaga 		log(LOG_ERR, "%s: descriptor full\n", __func__);
    801  1.1  hsuenaga 		return -1;
    802  1.1  hsuenaga 	}
    803  1.1  hsuenaga 
    804  1.1  hsuenaga 	mvxpsec_dma_setup(dh, dst, src, size);
    805  1.1  hsuenaga 	if (r->dma_head == NULL) {
    806  1.1  hsuenaga 		r->dma_head = dh;
    807  1.1  hsuenaga 		r->dma_last = dh;
    808  1.1  hsuenaga 		r->dma_size = 1;
    809  1.1  hsuenaga 	}
    810  1.1  hsuenaga 	else {
    811  1.1  hsuenaga 		mvxpsec_dma_cat(sc, r->dma_last, dh);
    812  1.1  hsuenaga 		r->dma_last = dh;
    813  1.1  hsuenaga 		r->dma_size++;
    814  1.1  hsuenaga 	}
    815  1.1  hsuenaga 
    816  1.1  hsuenaga 	return 0;
    817  1.1  hsuenaga }
    818  1.1  hsuenaga 
    819  1.1  hsuenaga INLINE int
    820  1.1  hsuenaga mvxpsec_dma_copy(struct mvxpsec_softc *sc, mvxpsec_dma_ring *r,
    821  1.1  hsuenaga     uint32_t dst, uint32_t src, uint32_t size)
    822  1.1  hsuenaga {
    823  1.1  hsuenaga 	if (size == 0) /* 0 is very special descriptor */
    824  1.1  hsuenaga 		return 0;
    825  1.1  hsuenaga 
    826  1.1  hsuenaga 	return mvxpsec_dma_copy0(sc, r, dst, src, size);
    827  1.1  hsuenaga }
    828  1.1  hsuenaga 
    829  1.1  hsuenaga /*
    830  1.1  hsuenaga  * Schedule ACC Activate
    831  1.1  hsuenaga  */
    832  1.1  hsuenaga INLINE int
    833  1.1  hsuenaga mvxpsec_dma_acc_activate(struct mvxpsec_softc *sc, mvxpsec_dma_ring *r)
    834  1.1  hsuenaga {
    835  1.1  hsuenaga 	return mvxpsec_dma_copy0(sc, r, 0, 0, 0);
    836  1.1  hsuenaga }
    837  1.1  hsuenaga 
    838  1.1  hsuenaga /*
    839  1.1  hsuenaga  * Finalize DMA setup
    840  1.1  hsuenaga  */
    841  1.1  hsuenaga INLINE void
    842  1.1  hsuenaga mvxpsec_dma_finalize(struct mvxpsec_softc *sc, mvxpsec_dma_ring *r)
    843  1.1  hsuenaga {
    844  1.1  hsuenaga 	struct mvxpsec_descriptor_handle *dh;
    845  1.1  hsuenaga 
    846  1.1  hsuenaga 	dh = r->dma_last;
    847  1.1  hsuenaga 	((struct mvxpsec_descriptor*)dh->_desc)->tdma_nxt = 0;
    848  1.1  hsuenaga 	MVXPSEC_SYNC_DESC(sc, dh, BUS_DMASYNC_PREWRITE);
    849  1.1  hsuenaga }
    850  1.1  hsuenaga 
    851  1.1  hsuenaga /*
    852  1.1  hsuenaga  * Free entire DMA ring
    853  1.1  hsuenaga  */
    854  1.1  hsuenaga INLINE void
    855  1.1  hsuenaga mvxpsec_dma_free(struct mvxpsec_softc *sc, mvxpsec_dma_ring *r)
    856  1.1  hsuenaga {
    857  1.1  hsuenaga 	sc->sc_desc_ring_cons += r->dma_size;
    858  1.1  hsuenaga 	if (sc->sc_desc_ring_cons >= sc->sc_desc_ring_size)
    859  1.1  hsuenaga 		sc->sc_desc_ring_cons -= sc->sc_desc_ring_size;
    860  1.1  hsuenaga 	r->dma_head = NULL;
    861  1.1  hsuenaga 	r->dma_last = NULL;
    862  1.1  hsuenaga 	r->dma_size = 0;
    863  1.1  hsuenaga }
    864  1.1  hsuenaga 
    865  1.1  hsuenaga /*
    866  1.1  hsuenaga  * create DMA descriptor chain for the packet
    867  1.1  hsuenaga  */
    868  1.1  hsuenaga INLINE int
    869  1.1  hsuenaga mvxpsec_dma_copy_packet(struct mvxpsec_softc *sc, struct mvxpsec_packet *mv_p)
    870  1.1  hsuenaga {
    871  1.1  hsuenaga 	struct mvxpsec_session *mv_s = mv_p->mv_s;
    872  1.1  hsuenaga 	uint32_t src, dst, len;
    873  1.1  hsuenaga 	uint32_t pkt_off, pkt_off_r;
    874  1.1  hsuenaga 	int err;
    875  1.1  hsuenaga 	int i;
    876  1.1  hsuenaga 
    877  1.1  hsuenaga 	/* must called with sc->sc_dma_mtx held */
    878  1.1  hsuenaga 	KASSERT(mutex_owned(&sc->sc_dma_mtx));
    879  1.1  hsuenaga 
    880  1.1  hsuenaga 	/*
    881  1.1  hsuenaga 	 * set offset for mem->device copy
    882  1.1  hsuenaga 	 *
    883  1.1  hsuenaga 	 * typical packet image:
    884  1.1  hsuenaga 	 *
    885  1.1  hsuenaga 	 *   enc_ivoff
    886  1.1  hsuenaga 	 *   mac_off
    887  1.1  hsuenaga 	 *   |
    888  1.1  hsuenaga 	 *   |    enc_off
    889  1.1  hsuenaga 	 *   |    |
    890  1.1  hsuenaga 	 *   v    v
    891  1.1  hsuenaga 	 *   +----+--------...
    892  1.1  hsuenaga 	 *   |IV  |DATA
    893  1.1  hsuenaga 	 *   +----+--------...
    894  1.1  hsuenaga 	 */
    895  1.1  hsuenaga 	pkt_off = 0;
    896  1.1  hsuenaga 	if (mv_p->mac_off > 0)
    897  1.1  hsuenaga 		pkt_off = mv_p->mac_off;
    898  1.1  hsuenaga 	if ((mv_p->flags & CRP_EXT_IV) == 0 && pkt_off > mv_p->enc_ivoff)
    899  1.1  hsuenaga 		pkt_off = mv_p->enc_ivoff;
    900  1.1  hsuenaga 	if (mv_p->enc_off > 0 && pkt_off > mv_p->enc_off)
    901  1.1  hsuenaga 		pkt_off = mv_p->enc_off;
    902  1.1  hsuenaga 	pkt_off_r = pkt_off;
    903  1.1  hsuenaga 
    904  1.1  hsuenaga 	/* make DMA descriptors to copy packet header: DRAM -> SRAM */
    905  1.1  hsuenaga 	dst = (uint32_t)MVXPSEC_SRAM_PKT_HDR_PA(sc);
    906  1.1  hsuenaga 	src = (uint32_t)mv_p->pkt_header_map->dm_segs[0].ds_addr;
    907  1.1  hsuenaga 	len = sizeof(mv_p->pkt_header);
    908  1.1  hsuenaga 	err = mvxpsec_dma_copy(sc, &mv_p->dma_ring, dst, src, len);
    909  1.1  hsuenaga 	if (__predict_false(err))
    910  1.1  hsuenaga 		return err;
    911  1.1  hsuenaga 
    912  1.1  hsuenaga 	/*
    913  1.1  hsuenaga 	 * make DMA descriptors to copy session header: DRAM -> SRAM
    914  1.1  hsuenaga 	 * we can reuse session header on SRAM if session is not changed.
    915  1.1  hsuenaga 	 */
    916  1.1  hsuenaga 	if (sc->sc_last_session != mv_s) {
    917  1.1  hsuenaga 		dst = (uint32_t)MVXPSEC_SRAM_SESS_HDR_PA(sc);
    918  1.1  hsuenaga 		src = (uint32_t)mv_s->session_header_map->dm_segs[0].ds_addr;
    919  1.1  hsuenaga 		len = sizeof(mv_s->session_header);
    920  1.1  hsuenaga 		err = mvxpsec_dma_copy(sc, &mv_p->dma_ring, dst, src, len);
    921  1.1  hsuenaga 		if (__predict_false(err))
    922  1.1  hsuenaga 			return err;
    923  1.1  hsuenaga 		sc->sc_last_session = mv_s;
    924  1.1  hsuenaga 	}
    925  1.1  hsuenaga 
    926  1.1  hsuenaga 	/* make DMA descriptor to copy payload data: DRAM -> SRAM */
    927  1.1  hsuenaga 	dst = MVXPSEC_SRAM_PAYLOAD_PA(sc, 0);
    928  1.1  hsuenaga 	for (i = 0; i < mv_p->data_map->dm_nsegs; i++) {
    929  1.1  hsuenaga 		src = mv_p->data_map->dm_segs[i].ds_addr;
    930  1.1  hsuenaga 		len = mv_p->data_map->dm_segs[i].ds_len;
    931  1.1  hsuenaga 		if (pkt_off) {
    932  1.1  hsuenaga 			if (len <= pkt_off) {
    933  1.1  hsuenaga 				/* ignore the segment */
    934  1.1  hsuenaga 				dst += len;
    935  1.1  hsuenaga 				pkt_off -= len;
    936  1.1  hsuenaga 				continue;
    937  1.1  hsuenaga 			}
    938  1.1  hsuenaga 			/* copy from the middle of the segment */
    939  1.1  hsuenaga 			dst += pkt_off;
    940  1.1  hsuenaga 			src += pkt_off;
    941  1.1  hsuenaga 			len -= pkt_off;
    942  1.1  hsuenaga 			pkt_off = 0;
    943  1.1  hsuenaga 		}
    944  1.1  hsuenaga 		err = mvxpsec_dma_copy(sc, &mv_p->dma_ring, dst, src, len);
    945  1.1  hsuenaga 		if (__predict_false(err))
    946  1.1  hsuenaga 			return err;
    947  1.1  hsuenaga 		dst += len;
    948  1.1  hsuenaga 	}
    949  1.1  hsuenaga 
    950  1.1  hsuenaga 	/* make special descriptor to activate security accelerator */
    951  1.1  hsuenaga 	err = mvxpsec_dma_acc_activate(sc, &mv_p->dma_ring);
    952  1.1  hsuenaga 	if (__predict_false(err))
    953  1.1  hsuenaga 		return err;
    954  1.1  hsuenaga 
    955  1.1  hsuenaga 	/* make DMA descriptors to copy payload: SRAM -> DRAM */
    956  1.1  hsuenaga 	src = (uint32_t)MVXPSEC_SRAM_PAYLOAD_PA(sc, 0);
    957  1.1  hsuenaga 	for (i = 0; i < mv_p->data_map->dm_nsegs; i++) {
    958  1.1  hsuenaga 		dst = (uint32_t)mv_p->data_map->dm_segs[i].ds_addr;
    959  1.1  hsuenaga 		len = (uint32_t)mv_p->data_map->dm_segs[i].ds_len;
    960  1.1  hsuenaga 		if (pkt_off_r) {
    961  1.1  hsuenaga 			if (len <= pkt_off_r) {
    962  1.1  hsuenaga 				/* ignore the segment */
    963  1.1  hsuenaga 				src += len;
    964  1.1  hsuenaga 				pkt_off_r -= len;
    965  1.1  hsuenaga 				continue;
    966  1.1  hsuenaga 			}
    967  1.1  hsuenaga 			/* copy from the middle of the segment */
    968  1.1  hsuenaga 			src += pkt_off_r;
    969  1.1  hsuenaga 			dst += pkt_off_r;
    970  1.1  hsuenaga 			len -= pkt_off_r;
    971  1.1  hsuenaga 			pkt_off_r = 0;
    972  1.1  hsuenaga 		}
    973  1.1  hsuenaga 		err = mvxpsec_dma_copy(sc, &mv_p->dma_ring, dst, src, len);
    974  1.1  hsuenaga 		if (__predict_false(err))
    975  1.1  hsuenaga 			return err;
    976  1.1  hsuenaga 		src += len;
    977  1.1  hsuenaga 	}
    978  1.1  hsuenaga 	KASSERT(pkt_off == 0);
    979  1.1  hsuenaga 	KASSERT(pkt_off_r == 0);
    980  1.1  hsuenaga 
    981  1.1  hsuenaga 	/*
    982  1.1  hsuenaga 	 * make DMA descriptors to copy packet header: SRAM->DRAM
    983  1.1  hsuenaga 	 * if IV is present in the payload, no need to copy.
    984  1.1  hsuenaga 	 */
    985  1.1  hsuenaga 	if (mv_p->flags & CRP_EXT_IV) {
    986  1.1  hsuenaga 		dst = (uint32_t)mv_p->pkt_header_map->dm_segs[0].ds_addr;
    987  1.1  hsuenaga 		src = (uint32_t)MVXPSEC_SRAM_PKT_HDR_PA(sc);
    988  1.1  hsuenaga 		len = sizeof(mv_p->pkt_header);
    989  1.1  hsuenaga 		err = mvxpsec_dma_copy(sc, &mv_p->dma_ring, dst, src, len);
    990  1.1  hsuenaga 		if (__predict_false(err))
    991  1.1  hsuenaga 			return err;
    992  1.1  hsuenaga 	}
    993  1.1  hsuenaga 
    994  1.1  hsuenaga 	return 0;
    995  1.1  hsuenaga }
    996  1.1  hsuenaga 
    997  1.1  hsuenaga INLINE int
    998  1.1  hsuenaga mvxpsec_dma_sync_packet(struct mvxpsec_softc *sc, struct mvxpsec_packet *mv_p)
    999  1.1  hsuenaga {
   1000  1.1  hsuenaga 	/* sync packet header */
   1001  1.1  hsuenaga 	bus_dmamap_sync(sc->sc_dmat,
   1002  1.1  hsuenaga 	    mv_p->pkt_header_map, 0, sizeof(mv_p->pkt_header),
   1003  1.1  hsuenaga 	    BUS_DMASYNC_PREWRITE);
   1004  1.1  hsuenaga 
   1005  1.1  hsuenaga #ifdef MVXPSEC_DEBUG
   1006  1.1  hsuenaga 	/* sync session header */
   1007  1.1  hsuenaga 	if (mvxpsec_debug != 0) {
   1008  1.1  hsuenaga 		struct mvxpsec_session *mv_s = mv_p->mv_s;
   1009  1.1  hsuenaga 
   1010  1.1  hsuenaga 		/* only debug code touch the session header after newsession */
   1011  1.1  hsuenaga 		bus_dmamap_sync(sc->sc_dmat,
   1012  1.1  hsuenaga 		    mv_s->session_header_map,
   1013  1.1  hsuenaga 		    0, sizeof(mv_s->session_header),
   1014  1.1  hsuenaga 		    BUS_DMASYNC_PREWRITE);
   1015  1.1  hsuenaga 	}
   1016  1.1  hsuenaga #endif
   1017  1.1  hsuenaga 
   1018  1.1  hsuenaga 	/* sync packet buffer */
   1019  1.1  hsuenaga 	bus_dmamap_sync(sc->sc_dmat,
   1020  1.1  hsuenaga 	    mv_p->data_map, 0, mv_p->data_len,
   1021  1.1  hsuenaga 	    BUS_DMASYNC_PREWRITE | BUS_DMASYNC_PREREAD);
   1022  1.1  hsuenaga 
   1023  1.1  hsuenaga 	return 0;
   1024  1.1  hsuenaga }
   1025  1.1  hsuenaga 
   1026  1.1  hsuenaga /*
   1027  1.1  hsuenaga  * Initialize MVXPSEC Internal SRAM
   1028  1.1  hsuenaga  *
   1029  1.1  hsuenaga  * - must be called after DMA initizlization.
   1030  1.1  hsuenaga  * - make VM mapping for SRAM area on MBus.
   1031  1.1  hsuenaga  */
   1032  1.1  hsuenaga STATIC int
   1033  1.1  hsuenaga mvxpsec_init_sram(struct mvxpsec_softc *sc)
   1034  1.1  hsuenaga {
   1035  1.1  hsuenaga 	uint32_t tag, target, attr, base, size;
   1036  1.1  hsuenaga 	vaddr_t va;
   1037  1.1  hsuenaga 	int window;
   1038  1.1  hsuenaga 
   1039  1.1  hsuenaga 	switch (sc->sc_dev->dv_unit) {
   1040  1.1  hsuenaga 	case 0:
   1041  1.1  hsuenaga 		tag = ARMADAXP_TAG_CRYPT0;
   1042  1.1  hsuenaga 		break;
   1043  1.1  hsuenaga 	case 1:
   1044  1.1  hsuenaga 		tag = ARMADAXP_TAG_CRYPT1;
   1045  1.1  hsuenaga 		break;
   1046  1.1  hsuenaga 	default:
   1047  1.1  hsuenaga 		aprint_error_dev(sc->sc_dev, "no internal SRAM mapping\n");
   1048  1.1  hsuenaga 		return -1;
   1049  1.1  hsuenaga 	}
   1050  1.1  hsuenaga 
   1051  1.1  hsuenaga 	window = mvsoc_target(tag, &target, &attr, &base, &size);
   1052  1.1  hsuenaga 	if (window >= nwindow) {
   1053  1.1  hsuenaga 		aprint_error_dev(sc->sc_dev, "no internal SRAM mapping\n");
   1054  1.1  hsuenaga 		return -1;
   1055  1.1  hsuenaga 	}
   1056  1.1  hsuenaga 
   1057  1.1  hsuenaga 	if (sizeof(struct mvxpsec_crypt_sram) > size) {
   1058  1.1  hsuenaga 		aprint_error_dev(sc->sc_dev,
   1059  1.1  hsuenaga 		    "SRAM Data Structure Excceeds SRAM window size.\n");
   1060  1.1  hsuenaga 		return -1;
   1061  1.1  hsuenaga 	}
   1062  1.1  hsuenaga 
   1063  1.1  hsuenaga 	aprint_normal_dev(sc->sc_dev,
   1064  1.1  hsuenaga 	    "internal SRAM window at 0x%08x-0x%08x",
   1065  1.1  hsuenaga 	    base, base + size - 1);
   1066  1.1  hsuenaga 	sc->sc_sram_pa = base;
   1067  1.1  hsuenaga 
   1068  1.1  hsuenaga 	/* get vmspace to read/write device internal SRAM */
   1069  1.1  hsuenaga 	va = uvm_km_alloc(kernel_map, PAGE_SIZE, PAGE_SIZE,
   1070  1.1  hsuenaga 			UVM_KMF_VAONLY | UVM_KMF_NOWAIT);
   1071  1.1  hsuenaga 	if (va == 0) {
   1072  1.1  hsuenaga 		aprint_error_dev(sc->sc_dev, "cannot map SRAM window\n");
   1073  1.1  hsuenaga 		sc->sc_sram_va = NULL;
   1074  1.1  hsuenaga 		aprint_normal("\n");
   1075  1.1  hsuenaga 		return 0;
   1076  1.1  hsuenaga 	}
   1077  1.1  hsuenaga 	/* XXX: not working. PMAP_NOCACHE is not affected? */
   1078  1.1  hsuenaga 	pmap_kenter_pa(va, base, VM_PROT_READ|VM_PROT_WRITE, PMAP_NOCACHE);
   1079  1.1  hsuenaga 	pmap_update(pmap_kernel());
   1080  1.1  hsuenaga 	sc->sc_sram_va = (void *)va;
   1081  1.1  hsuenaga 	aprint_normal(" va %p\n", sc->sc_sram_va);
   1082  1.1  hsuenaga 	memset(sc->sc_sram_va, 0xff, MV_ACC_SRAM_SIZE);
   1083  1.1  hsuenaga 
   1084  1.1  hsuenaga 	return 0;
   1085  1.1  hsuenaga }
   1086  1.1  hsuenaga 
   1087  1.1  hsuenaga /*
   1088  1.1  hsuenaga  * Initialize TDMA engine.
   1089  1.1  hsuenaga  */
   1090  1.1  hsuenaga STATIC int
   1091  1.1  hsuenaga mvxpsec_init_dma(struct mvxpsec_softc *sc, struct marvell_attach_args *mva)
   1092  1.1  hsuenaga {
   1093  1.1  hsuenaga 	struct mvxpsec_descriptor_handle *dh;
   1094  1.1  hsuenaga 	uint8_t *va;
   1095  1.1  hsuenaga 	paddr_t pa;
   1096  1.1  hsuenaga 	off_t va_off, pa_off;
   1097  1.1  hsuenaga 	int i, n, seg, ndh;
   1098  1.1  hsuenaga 
   1099  1.1  hsuenaga 	/* Init Deviced's control parameters (disabled yet) */
   1100  1.1  hsuenaga 	MVXPSEC_WRITE(sc, MV_TDMA_CONTROL, MV_TDMA_DEFAULT_CONTROL);
   1101  1.1  hsuenaga 
   1102  1.1  hsuenaga 	/* Init Software DMA Handlers */
   1103  1.1  hsuenaga 	sc->sc_devmem_desc =
   1104  1.1  hsuenaga 	    mvxpsec_alloc_devmem(sc, 0, PAGE_SIZE * MVXPSEC_DMA_DESC_PAGES);
   1105  1.1  hsuenaga 	ndh = (PAGE_SIZE / sizeof(struct mvxpsec_descriptor))
   1106  1.1  hsuenaga 	    * MVXPSEC_DMA_DESC_PAGES;
   1107  1.1  hsuenaga 	sc->sc_desc_ring =
   1108  1.1  hsuenaga 	    kmem_alloc(sizeof(struct mvxpsec_descriptor_handle) * ndh,
   1109  1.3       chs 	        KM_SLEEP);
   1110  1.1  hsuenaga 	aprint_normal_dev(sc->sc_dev, "%d DMA handles in %zu bytes array\n",
   1111  1.1  hsuenaga 	    ndh, sizeof(struct mvxpsec_descriptor_handle) * ndh);
   1112  1.1  hsuenaga 
   1113  1.1  hsuenaga 	ndh = 0;
   1114  1.1  hsuenaga 	for (seg = 0; seg < devmem_nseg(sc->sc_devmem_desc); seg++) {
   1115  1.1  hsuenaga 		va = devmem_va(sc->sc_devmem_desc);
   1116  1.1  hsuenaga 		pa = devmem_pa(sc->sc_devmem_desc, seg);
   1117  1.1  hsuenaga 		n = devmem_palen(sc->sc_devmem_desc, seg) /
   1118  1.1  hsuenaga 		       	sizeof(struct mvxpsec_descriptor);
   1119  1.1  hsuenaga 		va_off = (PAGE_SIZE * seg);
   1120  1.1  hsuenaga 		pa_off = 0;
   1121  1.1  hsuenaga 		for (i = 0; i < n; i++) {
   1122  1.1  hsuenaga 			dh = &sc->sc_desc_ring[ndh];
   1123  1.1  hsuenaga 			dh->map = devmem_map(sc->sc_devmem_desc);
   1124  1.1  hsuenaga 			dh->off = va_off + pa_off;
   1125  1.1  hsuenaga 			dh->_desc = (void *)(va + va_off + pa_off);
   1126  1.1  hsuenaga 			dh->phys_addr = pa + pa_off;
   1127  1.1  hsuenaga 			pa_off += sizeof(struct mvxpsec_descriptor);
   1128  1.1  hsuenaga 			ndh++;
   1129  1.1  hsuenaga 		}
   1130  1.1  hsuenaga 	}
   1131  1.1  hsuenaga 	sc->sc_desc_ring_size = ndh;
   1132  1.1  hsuenaga 	sc->sc_desc_ring_prod = 0;
   1133  1.1  hsuenaga 	sc->sc_desc_ring_cons = sc->sc_desc_ring_size - 1;
   1134  1.1  hsuenaga 
   1135  1.1  hsuenaga 	return 0;
   1136  1.1  hsuenaga }
   1137  1.1  hsuenaga 
   1138  1.1  hsuenaga /*
   1139  1.1  hsuenaga  * Wait for TDMA controller become idle
   1140  1.1  hsuenaga  */
   1141  1.1  hsuenaga INLINE int
   1142  1.1  hsuenaga mvxpsec_dma_wait(struct mvxpsec_softc *sc)
   1143  1.1  hsuenaga {
   1144  1.1  hsuenaga 	int retry = 0;
   1145  1.1  hsuenaga 
   1146  1.1  hsuenaga 	while (MVXPSEC_READ(sc, MV_TDMA_CONTROL) & MV_TDMA_CONTROL_ACT) {
   1147  1.1  hsuenaga 		delay(mvxpsec_wait_interval);
   1148  1.1  hsuenaga 		if (retry++ >= mvxpsec_wait_retry)
   1149  1.1  hsuenaga 			return -1;
   1150  1.1  hsuenaga 	}
   1151  1.1  hsuenaga 	return 0;
   1152  1.1  hsuenaga }
   1153  1.1  hsuenaga 
   1154  1.1  hsuenaga /*
   1155  1.1  hsuenaga  * Wait for Security Accelerator become idle
   1156  1.1  hsuenaga  */
   1157  1.1  hsuenaga INLINE int
   1158  1.1  hsuenaga mvxpsec_acc_wait(struct mvxpsec_softc *sc)
   1159  1.1  hsuenaga {
   1160  1.1  hsuenaga 	int retry = 0;
   1161  1.1  hsuenaga 
   1162  1.1  hsuenaga 	while (MVXPSEC_READ(sc, MV_ACC_COMMAND) & MV_ACC_COMMAND_ACT) {
   1163  1.1  hsuenaga 		delay(mvxpsec_wait_interval);
   1164  1.1  hsuenaga 		if (++retry >= mvxpsec_wait_retry)
   1165  1.1  hsuenaga 			return -1;
   1166  1.1  hsuenaga 	}
   1167  1.1  hsuenaga 	return 0;
   1168  1.1  hsuenaga }
   1169  1.1  hsuenaga 
   1170  1.1  hsuenaga /*
   1171  1.1  hsuenaga  * Entry of interrupt handler
   1172  1.1  hsuenaga  *
   1173  1.1  hsuenaga  * register this to kernel via marvell_intr_establish()
   1174  1.1  hsuenaga  */
   1175  1.1  hsuenaga int
   1176  1.1  hsuenaga mvxpsec_intr(void *arg)
   1177  1.1  hsuenaga {
   1178  1.1  hsuenaga 	struct mvxpsec_softc *sc = arg;
   1179  1.1  hsuenaga 	uint32_t v;
   1180  1.1  hsuenaga 
   1181  1.1  hsuenaga 	/* IPL_NET */
   1182  1.1  hsuenaga 	while ((v = mvxpsec_intr_ack(sc)) != 0) {
   1183  1.1  hsuenaga 		mvxpsec_intr_cnt(sc, v);
   1184  1.1  hsuenaga 		MVXPSEC_PRINTF(MVXPSEC_DEBUG_INTR, "MVXPSEC Intr 0x%08x\n", v);
   1185  1.1  hsuenaga 		MVXPSEC_PRINTF(MVXPSEC_DEBUG_INTR, "%s\n", s_xpsecintr(v));
   1186  1.1  hsuenaga #ifdef MVXPSEC_DEBUG
   1187  1.1  hsuenaga 		mvxpsec_dump_reg(sc);
   1188  1.1  hsuenaga #endif
   1189  1.1  hsuenaga 
   1190  1.1  hsuenaga 		/* call high-level handlers */
   1191  1.1  hsuenaga 		if (v & MVXPSEC_INT_ACCTDMA)
   1192  1.1  hsuenaga 			mvxpsec_done(sc);
   1193  1.1  hsuenaga 	}
   1194  1.1  hsuenaga 
   1195  1.1  hsuenaga 	return 0;
   1196  1.1  hsuenaga }
   1197  1.1  hsuenaga 
   1198  1.1  hsuenaga INLINE void
   1199  1.1  hsuenaga mvxpsec_intr_cleanup(struct mvxpsec_softc *sc)
   1200  1.1  hsuenaga {
   1201  1.1  hsuenaga 	struct mvxpsec_packet *mv_p;
   1202  1.1  hsuenaga 
   1203  1.1  hsuenaga 	/* must called with sc->sc_dma_mtx held */
   1204  1.1  hsuenaga 	KASSERT(mutex_owned(&sc->sc_dma_mtx));
   1205  1.1  hsuenaga 
   1206  1.1  hsuenaga 	/*
   1207  1.1  hsuenaga 	 * there is only one intr for run_queue.
   1208  1.1  hsuenaga 	 * no one touch sc_run_queue.
   1209  1.1  hsuenaga 	 */
   1210  1.1  hsuenaga 	SIMPLEQ_FOREACH(mv_p, &sc->sc_run_queue, queue)
   1211  1.1  hsuenaga 		mvxpsec_dma_free(sc, &mv_p->dma_ring);
   1212  1.1  hsuenaga }
   1213  1.1  hsuenaga 
   1214  1.1  hsuenaga /*
   1215  1.1  hsuenaga  * Acknowledge to interrupt
   1216  1.1  hsuenaga  *
   1217  1.1  hsuenaga  * read cause bits, clear it, and return it.
   1218  1.1  hsuenaga  * NOTE: multiple cause bits may be returned at once.
   1219  1.1  hsuenaga  */
   1220  1.1  hsuenaga STATIC uint32_t
   1221  1.1  hsuenaga mvxpsec_intr_ack(struct mvxpsec_softc *sc)
   1222  1.1  hsuenaga {
   1223  1.1  hsuenaga 	uint32_t reg;
   1224  1.1  hsuenaga 
   1225  1.1  hsuenaga 	reg  = MVXPSEC_READ(sc, MVXPSEC_INT_CAUSE);
   1226  1.1  hsuenaga 	reg &= MVXPSEC_DEFAULT_INT;
   1227  1.1  hsuenaga 	MVXPSEC_WRITE(sc, MVXPSEC_INT_CAUSE, ~reg);
   1228  1.1  hsuenaga 	MVXPSEC_PRINTF(MVXPSEC_DEBUG_INTR, "Int: %s\n", s_xpsecintr(reg));
   1229  1.1  hsuenaga 
   1230  1.1  hsuenaga 	return reg;
   1231  1.1  hsuenaga }
   1232  1.1  hsuenaga 
   1233  1.1  hsuenaga /*
   1234  1.1  hsuenaga  * Entry of TDMA error interrupt handler
   1235  1.1  hsuenaga  *
   1236  1.1  hsuenaga  * register this to kernel via marvell_intr_establish()
   1237  1.1  hsuenaga  */
   1238  1.1  hsuenaga int
   1239  1.1  hsuenaga mvxpsec_eintr(void *arg)
   1240  1.1  hsuenaga {
   1241  1.1  hsuenaga 	struct mvxpsec_softc *sc = arg;
   1242  1.1  hsuenaga 	uint32_t err;
   1243  1.1  hsuenaga 
   1244  1.1  hsuenaga 	/* IPL_NET */
   1245  1.1  hsuenaga again:
   1246  1.1  hsuenaga 	err = mvxpsec_eintr_ack(sc);
   1247  1.1  hsuenaga 	if (err == 0)
   1248  1.1  hsuenaga 		goto done;
   1249  1.1  hsuenaga 
   1250  1.1  hsuenaga 	log(LOG_ERR, "%s: DMA Error Interrupt: %s\n", __func__,
   1251  1.1  hsuenaga 	    s_errreg(err));
   1252  1.1  hsuenaga #ifdef MVXPSEC_DEBUG
   1253  1.1  hsuenaga 	mvxpsec_dump_reg(sc);
   1254  1.1  hsuenaga #endif
   1255  1.1  hsuenaga 
   1256  1.1  hsuenaga 	goto again;
   1257  1.1  hsuenaga done:
   1258  1.1  hsuenaga 	return 0;
   1259  1.1  hsuenaga }
   1260  1.1  hsuenaga 
   1261  1.1  hsuenaga /*
   1262  1.1  hsuenaga  * Acknowledge to TDMA error interrupt
   1263  1.1  hsuenaga  *
   1264  1.1  hsuenaga  * read cause bits, clear it, and return it.
   1265  1.1  hsuenaga  * NOTE: multiple cause bits may be returned at once.
   1266  1.1  hsuenaga  */
   1267  1.1  hsuenaga STATIC uint32_t
   1268  1.1  hsuenaga mvxpsec_eintr_ack(struct mvxpsec_softc *sc)
   1269  1.1  hsuenaga {
   1270  1.1  hsuenaga 	uint32_t reg;
   1271  1.1  hsuenaga 
   1272  1.1  hsuenaga 	reg  = MVXPSEC_READ(sc, MV_TDMA_ERR_CAUSE);
   1273  1.1  hsuenaga 	reg &= MVXPSEC_DEFAULT_ERR;
   1274  1.1  hsuenaga 	MVXPSEC_WRITE(sc, MV_TDMA_ERR_CAUSE, ~reg);
   1275  1.1  hsuenaga 	MVXPSEC_PRINTF(MVXPSEC_DEBUG_INTR, "Int: %s\n", s_xpsecintr(reg));
   1276  1.1  hsuenaga 
   1277  1.1  hsuenaga 	return reg;
   1278  1.1  hsuenaga }
   1279  1.1  hsuenaga 
   1280  1.1  hsuenaga /*
   1281  1.1  hsuenaga  * Interrupt statistics
   1282  1.1  hsuenaga  *
   1283  1.1  hsuenaga  * this is NOT a statistics of how may times the events 'occured'.
   1284  1.1  hsuenaga  * this ONLY means how many times the events 'handled'.
   1285  1.1  hsuenaga  */
   1286  1.1  hsuenaga INLINE void
   1287  1.1  hsuenaga mvxpsec_intr_cnt(struct mvxpsec_softc *sc, int cause)
   1288  1.1  hsuenaga {
   1289  1.1  hsuenaga 	MVXPSEC_EVCNT_INCR(sc, intr_all);
   1290  1.1  hsuenaga 	if (cause & MVXPSEC_INT_AUTH)
   1291  1.1  hsuenaga 		MVXPSEC_EVCNT_INCR(sc, intr_auth);
   1292  1.1  hsuenaga 	if (cause & MVXPSEC_INT_DES)
   1293  1.1  hsuenaga 		MVXPSEC_EVCNT_INCR(sc, intr_des);
   1294  1.1  hsuenaga 	if (cause & MVXPSEC_INT_AES_ENC)
   1295  1.1  hsuenaga 		MVXPSEC_EVCNT_INCR(sc, intr_aes_enc);
   1296  1.1  hsuenaga 	if (cause & MVXPSEC_INT_AES_DEC)
   1297  1.1  hsuenaga 		MVXPSEC_EVCNT_INCR(sc, intr_aes_dec);
   1298  1.1  hsuenaga 	if (cause & MVXPSEC_INT_ENC)
   1299  1.1  hsuenaga 		MVXPSEC_EVCNT_INCR(sc, intr_enc);
   1300  1.1  hsuenaga 	if (cause & MVXPSEC_INT_SA)
   1301  1.1  hsuenaga 		MVXPSEC_EVCNT_INCR(sc, intr_sa);
   1302  1.1  hsuenaga 	if (cause & MVXPSEC_INT_ACCTDMA)
   1303  1.1  hsuenaga 		MVXPSEC_EVCNT_INCR(sc, intr_acctdma);
   1304  1.1  hsuenaga 	if (cause & MVXPSEC_INT_TDMA_COMP)
   1305  1.1  hsuenaga 		MVXPSEC_EVCNT_INCR(sc, intr_comp);
   1306  1.1  hsuenaga 	if (cause & MVXPSEC_INT_TDMA_OWN)
   1307  1.1  hsuenaga 		MVXPSEC_EVCNT_INCR(sc, intr_own);
   1308  1.1  hsuenaga 	if (cause & MVXPSEC_INT_ACCTDMA_CONT)
   1309  1.1  hsuenaga 		MVXPSEC_EVCNT_INCR(sc, intr_acctdma_cont);
   1310  1.1  hsuenaga }
   1311  1.1  hsuenaga 
   1312  1.1  hsuenaga /*
   1313  1.1  hsuenaga  * Setup MVXPSEC header structure.
   1314  1.1  hsuenaga  *
   1315  1.1  hsuenaga  * the header contains descriptor of security accelerator,
   1316  1.1  hsuenaga  * key material of chiphers, iv of ciphers and macs, ...
   1317  1.1  hsuenaga  *
   1318  1.5   msaitoh  * the header is transferred to MVXPSEC Internal SRAM by TDMA,
   1319  1.1  hsuenaga  * and parsed by MVXPSEC H/W.
   1320  1.1  hsuenaga  */
   1321  1.1  hsuenaga STATIC int
   1322  1.1  hsuenaga mvxpsec_header_finalize(struct mvxpsec_packet *mv_p)
   1323  1.1  hsuenaga {
   1324  1.1  hsuenaga 	struct mvxpsec_acc_descriptor *desc = &mv_p->pkt_header.desc;
   1325  1.1  hsuenaga 	int enc_start, enc_len, iv_offset;
   1326  1.1  hsuenaga 	int mac_start, mac_len, mac_offset;
   1327  1.1  hsuenaga 
   1328  1.1  hsuenaga 	/* offset -> device address */
   1329  1.1  hsuenaga 	enc_start = MVXPSEC_SRAM_PAYLOAD_DA(mv_p->enc_off);
   1330  1.1  hsuenaga 	enc_len = mv_p->enc_len;
   1331  1.1  hsuenaga 	if (mv_p->flags & CRP_EXT_IV)
   1332  1.1  hsuenaga 		iv_offset = mv_p->enc_ivoff;
   1333  1.1  hsuenaga 	else
   1334  1.1  hsuenaga 		iv_offset = MVXPSEC_SRAM_PAYLOAD_DA(mv_p->enc_ivoff);
   1335  1.1  hsuenaga 	mac_start = MVXPSEC_SRAM_PAYLOAD_DA(mv_p->mac_off);
   1336  1.1  hsuenaga 	mac_len = mv_p->mac_len;
   1337  1.1  hsuenaga 	mac_offset = MVXPSEC_SRAM_PAYLOAD_DA(mv_p->mac_dst);
   1338  1.1  hsuenaga 
   1339  1.1  hsuenaga 	MVXPSEC_PRINTF(MVXPSEC_DEBUG_OPENCRYPTO,
   1340  1.1  hsuenaga 	    "PAYLOAD at 0x%08x\n", (int)MVXPSEC_SRAM_PAYLOAD_OFF);
   1341  1.1  hsuenaga 	MVXPSEC_PRINTF(MVXPSEC_DEBUG_OPENCRYPTO,
   1342  1.1  hsuenaga 	    "ENC from 0x%08x\n", enc_start);
   1343  1.1  hsuenaga 	MVXPSEC_PRINTF(MVXPSEC_DEBUG_OPENCRYPTO,
   1344  1.1  hsuenaga 	    "MAC from 0x%08x\n", mac_start);
   1345  1.1  hsuenaga 	MVXPSEC_PRINTF(MVXPSEC_DEBUG_OPENCRYPTO,
   1346  1.1  hsuenaga 	    "MAC to 0x%08x\n", mac_offset);
   1347  1.1  hsuenaga 	MVXPSEC_PRINTF(MVXPSEC_DEBUG_OPENCRYPTO,
   1348  1.1  hsuenaga 	    "ENC IV at 0x%08x\n", iv_offset);
   1349  1.1  hsuenaga 
   1350  1.1  hsuenaga 	/* setup device addresses in Security Accelerator Descriptors */
   1351  1.1  hsuenaga 	desc->acc_encdata = MV_ACC_DESC_ENC_DATA(enc_start, enc_start);
   1352  1.1  hsuenaga 	desc->acc_enclen = MV_ACC_DESC_ENC_LEN(enc_len);
   1353  1.1  hsuenaga 	if (desc->acc_config & MV_ACC_CRYPTO_DECRYPT)
   1354  1.1  hsuenaga 		desc->acc_enckey =
   1355  1.1  hsuenaga 		    MV_ACC_DESC_ENC_KEY(MVXPSEC_SRAM_KEY_D_DA);
   1356  1.1  hsuenaga 	else
   1357  1.1  hsuenaga 		desc->acc_enckey =
   1358  1.1  hsuenaga 		    MV_ACC_DESC_ENC_KEY(MVXPSEC_SRAM_KEY_DA);
   1359  1.1  hsuenaga 	desc->acc_enciv =
   1360  1.1  hsuenaga 	    MV_ACC_DESC_ENC_IV(MVXPSEC_SRAM_IV_WORK_DA, iv_offset);
   1361  1.1  hsuenaga 
   1362  1.1  hsuenaga 	desc->acc_macsrc = MV_ACC_DESC_MAC_SRC(mac_start, mac_len);
   1363  1.1  hsuenaga 	desc->acc_macdst = MV_ACC_DESC_MAC_DST(mac_offset, mac_len);
   1364  1.1  hsuenaga 	desc->acc_maciv =
   1365  1.1  hsuenaga 	    MV_ACC_DESC_MAC_IV(MVXPSEC_SRAM_MIV_IN_DA,
   1366  1.1  hsuenaga 	        MVXPSEC_SRAM_MIV_OUT_DA);
   1367  1.1  hsuenaga 
   1368  1.1  hsuenaga 	return 0;
   1369  1.1  hsuenaga }
   1370  1.1  hsuenaga 
   1371  1.1  hsuenaga /*
   1372  1.1  hsuenaga  * constractor of session structure.
   1373  1.1  hsuenaga  *
   1374  1.1  hsuenaga  * this constrator will be called by pool_cache framework.
   1375  1.1  hsuenaga  */
   1376  1.1  hsuenaga STATIC int
   1377  1.1  hsuenaga mvxpsec_session_ctor(void *arg, void *obj, int flags)
   1378  1.1  hsuenaga {
   1379  1.1  hsuenaga 	struct mvxpsec_softc *sc = arg;
   1380  1.1  hsuenaga 	struct mvxpsec_session *mv_s = obj;
   1381  1.1  hsuenaga 
   1382  1.1  hsuenaga 	/* pool is owned by softc */
   1383  1.1  hsuenaga 	mv_s->sc = sc;
   1384  1.1  hsuenaga 
   1385  1.1  hsuenaga 	/* Create and load DMA map for session header */
   1386  1.1  hsuenaga 	mv_s->session_header_map = 0;
   1387  1.1  hsuenaga 	if (bus_dmamap_create(sc->sc_dmat,
   1388  1.1  hsuenaga 	    sizeof(mv_s->session_header), 1,
   1389  1.1  hsuenaga 	    sizeof(mv_s->session_header), 0,
   1390  1.1  hsuenaga 	    BUS_DMA_NOWAIT | BUS_DMA_ALLOCNOW,
   1391  1.1  hsuenaga 	    &mv_s->session_header_map)) {
   1392  1.1  hsuenaga 		log(LOG_ERR, "%s: cannot create DMA map\n", __func__);
   1393  1.1  hsuenaga 		goto fail;
   1394  1.1  hsuenaga 	}
   1395  1.1  hsuenaga 	if (bus_dmamap_load(sc->sc_dmat, mv_s->session_header_map,
   1396  1.1  hsuenaga 	    &mv_s->session_header, sizeof(mv_s->session_header),
   1397  1.1  hsuenaga 	    NULL, BUS_DMA_NOWAIT)) {
   1398  1.1  hsuenaga 		log(LOG_ERR, "%s: cannot load header\n", __func__);
   1399  1.1  hsuenaga 		goto fail;
   1400  1.1  hsuenaga 	}
   1401  1.1  hsuenaga 
   1402  1.1  hsuenaga 	return 0;
   1403  1.1  hsuenaga fail:
   1404  1.1  hsuenaga 	if (mv_s->session_header_map)
   1405  1.1  hsuenaga 		bus_dmamap_destroy(sc->sc_dmat, mv_s->session_header_map);
   1406  1.1  hsuenaga 	return ENOMEM;
   1407  1.1  hsuenaga }
   1408  1.1  hsuenaga 
   1409  1.1  hsuenaga /*
   1410  1.1  hsuenaga  * destractor of session structure.
   1411  1.1  hsuenaga  *
   1412  1.1  hsuenaga  * this destrator will be called by pool_cache framework.
   1413  1.1  hsuenaga  */
   1414  1.1  hsuenaga STATIC void
   1415  1.1  hsuenaga mvxpsec_session_dtor(void *arg, void *obj)
   1416  1.1  hsuenaga {
   1417  1.1  hsuenaga 	struct mvxpsec_softc *sc = arg;
   1418  1.1  hsuenaga 	struct mvxpsec_session *mv_s = obj;
   1419  1.1  hsuenaga 
   1420  1.1  hsuenaga 	if (mv_s->sc != sc)
   1421  1.1  hsuenaga 		panic("inconsitent context\n");
   1422  1.1  hsuenaga 
   1423  1.1  hsuenaga 	bus_dmamap_destroy(sc->sc_dmat, mv_s->session_header_map);
   1424  1.1  hsuenaga }
   1425  1.1  hsuenaga 
   1426  1.1  hsuenaga /*
   1427  1.1  hsuenaga  * constructor of packet structure.
   1428  1.1  hsuenaga  */
   1429  1.1  hsuenaga STATIC int
   1430  1.1  hsuenaga mvxpsec_packet_ctor(void *arg, void *obj, int flags)
   1431  1.1  hsuenaga {
   1432  1.1  hsuenaga 	struct mvxpsec_softc *sc = arg;
   1433  1.1  hsuenaga 	struct mvxpsec_packet *mv_p = obj;
   1434  1.1  hsuenaga 
   1435  1.1  hsuenaga 	mv_p->dma_ring.dma_head = NULL;
   1436  1.1  hsuenaga 	mv_p->dma_ring.dma_last = NULL;
   1437  1.1  hsuenaga 	mv_p->dma_ring.dma_size = 0;
   1438  1.1  hsuenaga 
   1439  1.1  hsuenaga 	/* Create and load DMA map for packet header */
   1440  1.1  hsuenaga 	mv_p->pkt_header_map = 0;
   1441  1.1  hsuenaga 	if (bus_dmamap_create(sc->sc_dmat,
   1442  1.1  hsuenaga 	    sizeof(mv_p->pkt_header), 1, sizeof(mv_p->pkt_header), 0,
   1443  1.1  hsuenaga 	    BUS_DMA_NOWAIT | BUS_DMA_ALLOCNOW,
   1444  1.1  hsuenaga 	    &mv_p->pkt_header_map)) {
   1445  1.1  hsuenaga 		log(LOG_ERR, "%s: cannot create DMA map\n", __func__);
   1446  1.1  hsuenaga 		goto fail;
   1447  1.1  hsuenaga 	}
   1448  1.1  hsuenaga 	if (bus_dmamap_load(sc->sc_dmat, mv_p->pkt_header_map,
   1449  1.1  hsuenaga 	    &mv_p->pkt_header, sizeof(mv_p->pkt_header),
   1450  1.1  hsuenaga 	    NULL, BUS_DMA_NOWAIT)) {
   1451  1.1  hsuenaga 		log(LOG_ERR, "%s: cannot load header\n", __func__);
   1452  1.1  hsuenaga 		goto fail;
   1453  1.1  hsuenaga 	}
   1454  1.1  hsuenaga 
   1455  1.1  hsuenaga 	/* Create DMA map for session data. */
   1456  1.1  hsuenaga 	mv_p->data_map = 0;
   1457  1.1  hsuenaga 	if (bus_dmamap_create(sc->sc_dmat,
   1458  1.1  hsuenaga 	    MVXPSEC_DMA_MAX_SIZE, MVXPSEC_DMA_MAX_SEGS, MVXPSEC_DMA_MAX_SIZE,
   1459  1.1  hsuenaga 	    0, BUS_DMA_NOWAIT | BUS_DMA_ALLOCNOW, &mv_p->data_map)) {
   1460  1.1  hsuenaga 		log(LOG_ERR, "%s: cannot create DMA map\n", __func__);
   1461  1.1  hsuenaga 		goto fail;
   1462  1.1  hsuenaga 	}
   1463  1.1  hsuenaga 
   1464  1.1  hsuenaga 	return 0;
   1465  1.1  hsuenaga fail:
   1466  1.1  hsuenaga 	if (mv_p->pkt_header_map)
   1467  1.1  hsuenaga 		bus_dmamap_destroy(sc->sc_dmat, mv_p->pkt_header_map);
   1468  1.1  hsuenaga 	if (mv_p->data_map)
   1469  1.1  hsuenaga 		bus_dmamap_destroy(sc->sc_dmat, mv_p->data_map);
   1470  1.1  hsuenaga 	return ENOMEM;
   1471  1.1  hsuenaga }
   1472  1.1  hsuenaga 
   1473  1.1  hsuenaga /*
   1474  1.1  hsuenaga  * destractor of packet structure.
   1475  1.1  hsuenaga  */
   1476  1.1  hsuenaga STATIC void
   1477  1.1  hsuenaga mvxpsec_packet_dtor(void *arg, void *obj)
   1478  1.1  hsuenaga {
   1479  1.1  hsuenaga 	struct mvxpsec_softc *sc = arg;
   1480  1.1  hsuenaga 	struct mvxpsec_packet *mv_p = obj;
   1481  1.1  hsuenaga 
   1482  1.1  hsuenaga 	mutex_enter(&sc->sc_dma_mtx);
   1483  1.1  hsuenaga 	mvxpsec_dma_free(sc, &mv_p->dma_ring);
   1484  1.1  hsuenaga 	mutex_exit(&sc->sc_dma_mtx);
   1485  1.1  hsuenaga 	bus_dmamap_destroy(sc->sc_dmat, mv_p->pkt_header_map);
   1486  1.1  hsuenaga 	bus_dmamap_destroy(sc->sc_dmat, mv_p->data_map);
   1487  1.1  hsuenaga }
   1488  1.1  hsuenaga 
   1489  1.1  hsuenaga /*
   1490  1.1  hsuenaga  * allocate new session struture.
   1491  1.1  hsuenaga  */
   1492  1.1  hsuenaga STATIC struct mvxpsec_session *
   1493  1.1  hsuenaga mvxpsec_session_alloc(struct mvxpsec_softc *sc)
   1494  1.1  hsuenaga {
   1495  1.1  hsuenaga 	struct mvxpsec_session *mv_s;
   1496  1.1  hsuenaga 
   1497  1.2  christos 	mv_s = pool_cache_get(sc->sc_session_pool, PR_NOWAIT);
   1498  1.1  hsuenaga 	if (mv_s == NULL) {
   1499  1.1  hsuenaga 		log(LOG_ERR, "%s: cannot allocate memory\n", __func__);
   1500  1.1  hsuenaga 		return NULL;
   1501  1.1  hsuenaga 	}
   1502  1.1  hsuenaga 	mv_s->refs = 1; /* 0 means session is alredy invalid */
   1503  1.1  hsuenaga 	mv_s->sflags = 0;
   1504  1.1  hsuenaga 
   1505  1.1  hsuenaga 	return mv_s;
   1506  1.1  hsuenaga }
   1507  1.1  hsuenaga 
   1508  1.1  hsuenaga /*
   1509  1.1  hsuenaga  * deallocate session structure.
   1510  1.1  hsuenaga  */
   1511  1.1  hsuenaga STATIC void
   1512  1.1  hsuenaga mvxpsec_session_dealloc(struct mvxpsec_session *mv_s)
   1513  1.1  hsuenaga {
   1514  1.1  hsuenaga 	struct mvxpsec_softc *sc = mv_s->sc;
   1515  1.1  hsuenaga 
   1516  1.1  hsuenaga 	mv_s->sflags |= DELETED;
   1517  1.1  hsuenaga 	mvxpsec_session_unref(mv_s);
   1518  1.1  hsuenaga 	crypto_unblock(sc->sc_cid, CRYPTO_SYMQ|CRYPTO_ASYMQ);
   1519  1.1  hsuenaga 
   1520  1.1  hsuenaga 	return;
   1521  1.1  hsuenaga }
   1522  1.1  hsuenaga 
   1523  1.1  hsuenaga STATIC int
   1524  1.1  hsuenaga mvxpsec_session_ref(struct mvxpsec_session *mv_s)
   1525  1.1  hsuenaga {
   1526  1.1  hsuenaga 	uint32_t refs;
   1527  1.1  hsuenaga 
   1528  1.1  hsuenaga 	if (mv_s->sflags & DELETED) {
   1529  1.1  hsuenaga 		log(LOG_ERR,
   1530  1.1  hsuenaga 		    "%s: session is already deleted.\n", __func__);
   1531  1.1  hsuenaga 		return -1;
   1532  1.1  hsuenaga 	}
   1533  1.1  hsuenaga 
   1534  1.1  hsuenaga 	refs = atomic_inc_32_nv(&mv_s->refs);
   1535  1.1  hsuenaga 	if (refs == 1) {
   1536  1.1  hsuenaga 		/*
   1537  1.1  hsuenaga 		 * a session with refs == 0 is
   1538  1.1  hsuenaga 		 * already invalidated. revert it.
   1539  1.1  hsuenaga 		 * XXX: use CAS ?
   1540  1.1  hsuenaga 		 */
   1541  1.1  hsuenaga 		atomic_dec_32(&mv_s->refs);
   1542  1.1  hsuenaga 		log(LOG_ERR,
   1543  1.1  hsuenaga 		    "%s: session is already invalidated.\n", __func__);
   1544  1.1  hsuenaga 		return -1;
   1545  1.1  hsuenaga 	}
   1546  1.1  hsuenaga 
   1547  1.1  hsuenaga 	return 0;
   1548  1.1  hsuenaga }
   1549  1.1  hsuenaga 
   1550  1.1  hsuenaga STATIC void
   1551  1.1  hsuenaga mvxpsec_session_unref(struct mvxpsec_session *mv_s)
   1552  1.1  hsuenaga {
   1553  1.1  hsuenaga 	uint32_t refs;
   1554  1.1  hsuenaga 
   1555  1.1  hsuenaga 	refs = atomic_dec_32_nv(&mv_s->refs);
   1556  1.1  hsuenaga 	if (refs == 0)
   1557  1.1  hsuenaga 		pool_cache_put(mv_s->sc->sc_session_pool, mv_s);
   1558  1.1  hsuenaga }
   1559  1.1  hsuenaga 
   1560  1.1  hsuenaga /*
   1561  1.1  hsuenaga  * look for session is exist or not
   1562  1.1  hsuenaga  */
   1563  1.1  hsuenaga INLINE struct mvxpsec_session *
   1564  1.1  hsuenaga mvxpsec_session_lookup(struct mvxpsec_softc *sc, int sid)
   1565  1.1  hsuenaga {
   1566  1.1  hsuenaga 	struct mvxpsec_session *mv_s;
   1567  1.1  hsuenaga 	int session;
   1568  1.1  hsuenaga 
   1569  1.1  hsuenaga 	/* must called sc->sc_session_mtx held */
   1570  1.1  hsuenaga 	KASSERT(mutex_owned(&sc->sc_session_mtx));
   1571  1.1  hsuenaga 
   1572  1.1  hsuenaga 	session = MVXPSEC_SESSION(sid);
   1573  1.1  hsuenaga 	if (__predict_false(session > MVXPSEC_MAX_SESSIONS)) {
   1574  1.1  hsuenaga 		log(LOG_ERR, "%s: session number too large %d\n",
   1575  1.1  hsuenaga 		    __func__, session);
   1576  1.1  hsuenaga 		return NULL;
   1577  1.1  hsuenaga 	}
   1578  1.1  hsuenaga 	if (__predict_false( (mv_s = sc->sc_sessions[session]) == NULL)) {
   1579  1.1  hsuenaga 		log(LOG_ERR, "%s: invalid session %d\n",
   1580  1.1  hsuenaga 		    __func__, session);
   1581  1.1  hsuenaga 		return NULL;
   1582  1.1  hsuenaga 	}
   1583  1.1  hsuenaga 
   1584  1.1  hsuenaga 	KASSERT(mv_s->sid == session);
   1585  1.1  hsuenaga 
   1586  1.1  hsuenaga 	return mv_s;
   1587  1.1  hsuenaga }
   1588  1.1  hsuenaga 
   1589  1.1  hsuenaga /*
   1590  1.1  hsuenaga  * allocation new packet structure.
   1591  1.1  hsuenaga  */
   1592  1.1  hsuenaga STATIC struct mvxpsec_packet *
   1593  1.1  hsuenaga mvxpsec_packet_alloc(struct mvxpsec_session *mv_s)
   1594  1.1  hsuenaga {
   1595  1.1  hsuenaga 	struct mvxpsec_softc *sc = mv_s->sc;
   1596  1.1  hsuenaga 	struct mvxpsec_packet *mv_p;
   1597  1.1  hsuenaga 
   1598  1.1  hsuenaga 	/* must be called mv_queue_mtx held. */
   1599  1.1  hsuenaga 	KASSERT(mutex_owned(&sc->sc_queue_mtx));
   1600  1.1  hsuenaga 	/* must be called mv_session_mtx held. */
   1601  1.1  hsuenaga 	KASSERT(mutex_owned(&sc->sc_session_mtx));
   1602  1.1  hsuenaga 
   1603  1.1  hsuenaga 	if (mvxpsec_session_ref(mv_s) < 0) {
   1604  1.1  hsuenaga 		log(LOG_ERR, "%s: invalid session.\n", __func__);
   1605  1.1  hsuenaga 		return NULL;
   1606  1.1  hsuenaga 	}
   1607  1.1  hsuenaga 
   1608  1.1  hsuenaga 	if ( (mv_p = SLIST_FIRST(&sc->sc_free_list)) != NULL) {
   1609  1.1  hsuenaga 		SLIST_REMOVE_HEAD(&sc->sc_free_list, free_list);
   1610  1.1  hsuenaga 		sc->sc_free_qlen--;
   1611  1.1  hsuenaga 	}
   1612  1.1  hsuenaga 	else {
   1613  1.2  christos 		mv_p = pool_cache_get(sc->sc_packet_pool, PR_NOWAIT);
   1614  1.1  hsuenaga 		if (mv_p == NULL) {
   1615  1.1  hsuenaga 			log(LOG_ERR, "%s: cannot allocate memory\n",
   1616  1.1  hsuenaga 			    __func__);
   1617  1.1  hsuenaga 			mvxpsec_session_unref(mv_s);
   1618  1.1  hsuenaga 			return NULL;
   1619  1.1  hsuenaga 		}
   1620  1.1  hsuenaga 	}
   1621  1.1  hsuenaga 	mv_p->mv_s = mv_s;
   1622  1.1  hsuenaga 	mv_p->flags = 0;
   1623  1.1  hsuenaga 	mv_p->data_ptr = NULL;
   1624  1.1  hsuenaga 
   1625  1.1  hsuenaga 	return mv_p;
   1626  1.1  hsuenaga }
   1627  1.1  hsuenaga 
   1628  1.1  hsuenaga /*
   1629  1.1  hsuenaga  * free packet structure.
   1630  1.1  hsuenaga  */
   1631  1.1  hsuenaga STATIC void
   1632  1.1  hsuenaga mvxpsec_packet_dealloc(struct mvxpsec_packet *mv_p)
   1633  1.1  hsuenaga {
   1634  1.1  hsuenaga 	struct mvxpsec_session *mv_s = mv_p->mv_s;
   1635  1.1  hsuenaga 	struct mvxpsec_softc *sc = mv_s->sc;
   1636  1.1  hsuenaga 
   1637  1.1  hsuenaga 	/* must called with sc->sc_queue_mtx held */
   1638  1.1  hsuenaga 	KASSERT(mutex_owned(&sc->sc_queue_mtx));
   1639  1.1  hsuenaga 
   1640  1.1  hsuenaga 	if (mv_p->dma_ring.dma_size != 0) {
   1641  1.1  hsuenaga 		sc->sc_desc_ring_cons += mv_p->dma_ring.dma_size;
   1642  1.1  hsuenaga 	}
   1643  1.1  hsuenaga 	mv_p->dma_ring.dma_head = NULL;
   1644  1.1  hsuenaga 	mv_p->dma_ring.dma_last = NULL;
   1645  1.1  hsuenaga 	mv_p->dma_ring.dma_size = 0;
   1646  1.1  hsuenaga 
   1647  1.1  hsuenaga 	if (mv_p->data_map) {
   1648  1.1  hsuenaga 		if (mv_p->flags & RDY_DATA) {
   1649  1.1  hsuenaga 			bus_dmamap_unload(sc->sc_dmat, mv_p->data_map);
   1650  1.1  hsuenaga 			mv_p->flags &= ~RDY_DATA;
   1651  1.1  hsuenaga 		}
   1652  1.1  hsuenaga 	}
   1653  1.1  hsuenaga 
   1654  1.1  hsuenaga 	if (sc->sc_free_qlen > sc->sc_wait_qlimit)
   1655  1.1  hsuenaga 		pool_cache_put(sc->sc_packet_pool, mv_p);
   1656  1.1  hsuenaga 	else {
   1657  1.1  hsuenaga 		SLIST_INSERT_HEAD(&sc->sc_free_list, mv_p, free_list);
   1658  1.1  hsuenaga 		sc->sc_free_qlen++;
   1659  1.1  hsuenaga 	}
   1660  1.1  hsuenaga 	mvxpsec_session_unref(mv_s);
   1661  1.1  hsuenaga }
   1662  1.1  hsuenaga 
   1663  1.1  hsuenaga INLINE void
   1664  1.1  hsuenaga mvxpsec_packet_enqueue(struct mvxpsec_packet *mv_p)
   1665  1.1  hsuenaga {
   1666  1.1  hsuenaga 	struct mvxpsec_softc *sc = mv_p->mv_s->sc;
   1667  1.1  hsuenaga 	struct mvxpsec_packet *last_packet;
   1668  1.1  hsuenaga 	struct mvxpsec_descriptor_handle *cur_dma, *prev_dma;
   1669  1.1  hsuenaga 
   1670  1.1  hsuenaga 	/* must called with sc->sc_queue_mtx held */
   1671  1.1  hsuenaga 	KASSERT(mutex_owned(&sc->sc_queue_mtx));
   1672  1.1  hsuenaga 
   1673  1.1  hsuenaga 	if (sc->sc_wait_qlen == 0) {
   1674  1.1  hsuenaga 		SIMPLEQ_INSERT_TAIL(&sc->sc_wait_queue, mv_p, queue);
   1675  1.1  hsuenaga 		sc->sc_wait_qlen++;
   1676  1.1  hsuenaga 		mv_p->flags |= SETUP_DONE;
   1677  1.1  hsuenaga 		return;
   1678  1.1  hsuenaga 	}
   1679  1.1  hsuenaga 
   1680  1.1  hsuenaga 	last_packet = SIMPLEQ_LAST(&sc->sc_wait_queue, mvxpsec_packet, queue);
   1681  1.1  hsuenaga 	SIMPLEQ_INSERT_TAIL(&sc->sc_wait_queue, mv_p, queue);
   1682  1.1  hsuenaga 	sc->sc_wait_qlen++;
   1683  1.1  hsuenaga 
   1684  1.1  hsuenaga 	/* chain the DMA */
   1685  1.1  hsuenaga 	cur_dma = mv_p->dma_ring.dma_head;
   1686  1.1  hsuenaga 	prev_dma = last_packet->dma_ring.dma_last;
   1687  1.1  hsuenaga 	mvxpsec_dma_cat(sc, prev_dma, cur_dma);
   1688  1.1  hsuenaga 	mv_p->flags |= SETUP_DONE;
   1689  1.1  hsuenaga }
   1690  1.1  hsuenaga 
   1691  1.1  hsuenaga /*
   1692  1.1  hsuenaga  * called by interrupt handler
   1693  1.1  hsuenaga  */
   1694  1.1  hsuenaga STATIC int
   1695  1.1  hsuenaga mvxpsec_done_packet(struct mvxpsec_packet *mv_p)
   1696  1.1  hsuenaga {
   1697  1.1  hsuenaga 	struct mvxpsec_session *mv_s = mv_p->mv_s;
   1698  1.1  hsuenaga 	struct mvxpsec_softc *sc = mv_s->sc;
   1699  1.1  hsuenaga 
   1700  1.1  hsuenaga 	KASSERT((mv_p->flags & RDY_DATA));
   1701  1.1  hsuenaga 	KASSERT((mv_p->flags & SETUP_DONE));
   1702  1.1  hsuenaga 
   1703  1.1  hsuenaga 	/* unload data */
   1704  1.1  hsuenaga 	bus_dmamap_sync(sc->sc_dmat, mv_p->data_map,
   1705  1.1  hsuenaga 	    0, mv_p->data_len,
   1706  1.1  hsuenaga 	    BUS_DMASYNC_POSTWRITE | BUS_DMASYNC_POSTREAD);
   1707  1.1  hsuenaga 	bus_dmamap_unload(sc->sc_dmat, mv_p->data_map);
   1708  1.1  hsuenaga 	mv_p->flags &= ~RDY_DATA;
   1709  1.1  hsuenaga 
   1710  1.1  hsuenaga #ifdef MVXPSEC_DEBUG
   1711  1.1  hsuenaga 	if (mvxpsec_debug != 0) {
   1712  1.1  hsuenaga 		int s;
   1713  1.1  hsuenaga 
   1714  1.1  hsuenaga 		bus_dmamap_sync(sc->sc_dmat, mv_p->pkt_header_map,
   1715  1.1  hsuenaga 		    0, sizeof(mv_p->pkt_header),
   1716  1.1  hsuenaga 		    BUS_DMASYNC_POSTWRITE | BUS_DMASYNC_POSTREAD);
   1717  1.1  hsuenaga 		bus_dmamap_sync(sc->sc_dmat, mv_s->session_header_map,
   1718  1.1  hsuenaga 		    0, sizeof(mv_s->session_header),
   1719  1.1  hsuenaga 		    BUS_DMASYNC_POSTWRITE | BUS_DMASYNC_POSTREAD);
   1720  1.1  hsuenaga 
   1721  1.1  hsuenaga 		if (mvxpsec_debug & MVXPSEC_DEBUG_OPENCRYPTO) {
   1722  1.1  hsuenaga 			char buf[1500];
   1723  1.1  hsuenaga 			struct mbuf *m;
   1724  1.1  hsuenaga 			struct uio *uio;
   1725  1.1  hsuenaga 			size_t len;
   1726  1.1  hsuenaga 
   1727  1.1  hsuenaga 			switch (mv_p->data_type) {
   1728  1.1  hsuenaga 			case MVXPSEC_DATA_MBUF:
   1729  1.1  hsuenaga 				m = mv_p->data_mbuf;
   1730  1.1  hsuenaga 				len = m->m_pkthdr.len;
   1731  1.1  hsuenaga 				if (len > sizeof(buf))
   1732  1.1  hsuenaga 					len = sizeof(buf);
   1733  1.1  hsuenaga 				m_copydata(m, 0, len, buf);
   1734  1.1  hsuenaga 				break;
   1735  1.1  hsuenaga 			case MVXPSEC_DATA_UIO:
   1736  1.1  hsuenaga 				uio = mv_p->data_uio;
   1737  1.1  hsuenaga 				len = uio->uio_resid;
   1738  1.1  hsuenaga 				if (len > sizeof(buf))
   1739  1.1  hsuenaga 					len = sizeof(buf);
   1740  1.1  hsuenaga 				cuio_copydata(uio, 0, len, buf);
   1741  1.1  hsuenaga 				break;
   1742  1.1  hsuenaga 			default:
   1743  1.1  hsuenaga 				len = 0;
   1744  1.1  hsuenaga 			}
   1745  1.1  hsuenaga 			if (len > 0)
   1746  1.1  hsuenaga 				mvxpsec_dump_data(__func__, buf, len);
   1747  1.1  hsuenaga 		}
   1748  1.1  hsuenaga 
   1749  1.1  hsuenaga 		if (mvxpsec_debug & MVXPSEC_DEBUG_PAYLOAD) {
   1750  1.1  hsuenaga 			MVXPSEC_PRINTF(MVXPSEC_DEBUG_PAYLOAD,
   1751  1.1  hsuenaga 			    "%s: session_descriptor:\n", __func__);
   1752  1.1  hsuenaga 			mvxpsec_dump_packet_desc(__func__, mv_p);
   1753  1.1  hsuenaga 			MVXPSEC_PRINTF(MVXPSEC_DEBUG_PAYLOAD,
   1754  1.1  hsuenaga 			    "%s: session_data:\n", __func__);
   1755  1.1  hsuenaga 			mvxpsec_dump_packet_data(__func__, mv_p);
   1756  1.1  hsuenaga 		}
   1757  1.1  hsuenaga 
   1758  1.1  hsuenaga 		if (mvxpsec_debug & MVXPSEC_DEBUG_SRAM) {
   1759  1.1  hsuenaga 			MVXPSEC_PRINTF(MVXPSEC_DEBUG_SRAM,
   1760  1.1  hsuenaga 			    "%s: SRAM\n", __func__);
   1761  1.1  hsuenaga 			mvxpsec_dump_sram(__func__, sc, 2000);
   1762  1.1  hsuenaga 		}
   1763  1.1  hsuenaga 
   1764  1.1  hsuenaga 		s = MVXPSEC_READ(sc, MV_ACC_STATUS);
   1765  1.1  hsuenaga 		if (s & MV_ACC_STATUS_MAC_ERR) {
   1766  1.1  hsuenaga 			MVXPSEC_PRINTF(MVXPSEC_DEBUG_INTR,
   1767  1.1  hsuenaga 			    "%s: Message Authentication Failed.\n", __func__);
   1768  1.1  hsuenaga 		}
   1769  1.1  hsuenaga 	}
   1770  1.1  hsuenaga #endif
   1771  1.1  hsuenaga 
   1772  1.1  hsuenaga 	/* copy back IV */
   1773  1.1  hsuenaga 	if (mv_p->flags & CRP_EXT_IV) {
   1774  1.1  hsuenaga 		memcpy(mv_p->ext_iv,
   1775  1.1  hsuenaga 		    &mv_p->pkt_header.crp_iv_ext, mv_p->ext_ivlen);
   1776  1.1  hsuenaga 		mv_p->ext_iv = NULL;
   1777  1.1  hsuenaga 		mv_p->ext_ivlen = 0;
   1778  1.1  hsuenaga 	}
   1779  1.1  hsuenaga 
   1780  1.1  hsuenaga 	/* notify opencrypto */
   1781  1.1  hsuenaga 	mv_p->crp->crp_etype = 0;
   1782  1.1  hsuenaga 	crypto_done(mv_p->crp);
   1783  1.1  hsuenaga 	mv_p->crp = NULL;
   1784  1.1  hsuenaga 
   1785  1.1  hsuenaga 	/* unblock driver */
   1786  1.1  hsuenaga 	mvxpsec_packet_dealloc(mv_p);
   1787  1.1  hsuenaga 	crypto_unblock(sc->sc_cid, CRYPTO_SYMQ|CRYPTO_ASYMQ);
   1788  1.1  hsuenaga 
   1789  1.1  hsuenaga 	MVXPSEC_EVCNT_INCR(sc, packet_ok);
   1790  1.1  hsuenaga 
   1791  1.1  hsuenaga 	return 0;
   1792  1.1  hsuenaga }
   1793  1.1  hsuenaga 
   1794  1.1  hsuenaga 
   1795  1.1  hsuenaga /*
   1796  1.1  hsuenaga  * Opencrypto API registration
   1797  1.1  hsuenaga  */
   1798  1.1  hsuenaga int
   1799  1.1  hsuenaga mvxpsec_register(struct mvxpsec_softc *sc)
   1800  1.1  hsuenaga {
   1801  1.1  hsuenaga 	int oplen = SRAM_PAYLOAD_SIZE;
   1802  1.1  hsuenaga 	int flags = 0;
   1803  1.1  hsuenaga 	int err;
   1804  1.1  hsuenaga 
   1805  1.1  hsuenaga 	sc->sc_nsessions = 0;
   1806  1.1  hsuenaga 	sc->sc_cid = crypto_get_driverid(0);
   1807  1.1  hsuenaga 	if (sc->sc_cid < 0) {
   1808  1.1  hsuenaga 		log(LOG_ERR,
   1809  1.1  hsuenaga 		    "%s: crypto_get_driverid() failed.\n", __func__);
   1810  1.1  hsuenaga 		err = EINVAL;
   1811  1.1  hsuenaga 		goto done;
   1812  1.1  hsuenaga 	}
   1813  1.1  hsuenaga 
   1814  1.1  hsuenaga 	/* Ciphers */
   1815  1.1  hsuenaga 	err = crypto_register(sc->sc_cid, CRYPTO_DES_CBC, oplen, flags,
   1816  1.1  hsuenaga 	    mvxpsec_newsession, mvxpsec_freesession, mvxpsec_dispatch, sc);
   1817  1.1  hsuenaga 	if (err)
   1818  1.1  hsuenaga 		goto done;
   1819  1.1  hsuenaga 
   1820  1.1  hsuenaga 	err = crypto_register(sc->sc_cid, CRYPTO_3DES_CBC, oplen, flags,
   1821  1.1  hsuenaga 	    mvxpsec_newsession, mvxpsec_freesession, mvxpsec_dispatch, sc);
   1822  1.1  hsuenaga 	if (err)
   1823  1.1  hsuenaga 		goto done;
   1824  1.1  hsuenaga 
   1825  1.1  hsuenaga 	err = crypto_register(sc->sc_cid, CRYPTO_AES_CBC, oplen, flags,
   1826  1.1  hsuenaga 	    mvxpsec_newsession, mvxpsec_freesession, mvxpsec_dispatch, sc);
   1827  1.1  hsuenaga 	if (err)
   1828  1.1  hsuenaga 		goto done;
   1829  1.1  hsuenaga 
   1830  1.1  hsuenaga 	/* MACs */
   1831  1.1  hsuenaga 	err = crypto_register(sc->sc_cid, CRYPTO_SHA1_HMAC_96,
   1832  1.1  hsuenaga 	    oplen, flags,
   1833  1.1  hsuenaga 	    mvxpsec_newsession, mvxpsec_freesession, mvxpsec_dispatch, sc);
   1834  1.1  hsuenaga 	if (err)
   1835  1.1  hsuenaga 		goto done;
   1836  1.1  hsuenaga 
   1837  1.1  hsuenaga 	err = crypto_register(sc->sc_cid, CRYPTO_MD5_HMAC_96,
   1838  1.1  hsuenaga 	    oplen, flags,
   1839  1.1  hsuenaga 	    mvxpsec_newsession, mvxpsec_freesession, mvxpsec_dispatch, sc);
   1840  1.1  hsuenaga 	if (err)
   1841  1.1  hsuenaga 		goto done;
   1842  1.1  hsuenaga 
   1843  1.1  hsuenaga #ifdef DEBUG
   1844  1.1  hsuenaga 	log(LOG_DEBUG,
   1845  1.1  hsuenaga 	    "%s: registered to opencrypto(max data = %d bytes)\n",
   1846  1.1  hsuenaga 	    device_xname(sc->sc_dev), oplen);
   1847  1.1  hsuenaga #endif
   1848  1.1  hsuenaga 
   1849  1.1  hsuenaga 	err = 0;
   1850  1.1  hsuenaga done:
   1851  1.1  hsuenaga 	return err;
   1852  1.1  hsuenaga }
   1853  1.1  hsuenaga 
   1854  1.1  hsuenaga /*
   1855  1.1  hsuenaga  * Create new opencrypto session
   1856  1.1  hsuenaga  *
   1857  1.1  hsuenaga  *   - register cipher key, mac key.
   1858  1.1  hsuenaga  *   - initialize mac internal state.
   1859  1.1  hsuenaga  */
   1860  1.1  hsuenaga int
   1861  1.1  hsuenaga mvxpsec_newsession(void *arg, uint32_t *sidp, struct cryptoini *cri)
   1862  1.1  hsuenaga {
   1863  1.1  hsuenaga 	struct mvxpsec_softc *sc = arg;
   1864  1.1  hsuenaga 	struct mvxpsec_session *mv_s = NULL;
   1865  1.1  hsuenaga 	struct cryptoini *c;
   1866  1.1  hsuenaga 	static int hint = 0;
   1867  1.1  hsuenaga 	int session = -1;
   1868  1.1  hsuenaga 	int sid;
   1869  1.1  hsuenaga 	int err;
   1870  1.1  hsuenaga 	int i;
   1871  1.1  hsuenaga 
   1872  1.1  hsuenaga 	/* allocate driver session context */
   1873  1.1  hsuenaga 	mv_s = mvxpsec_session_alloc(sc);
   1874  1.1  hsuenaga 	if (mv_s == NULL)
   1875  1.1  hsuenaga 		return ENOMEM;
   1876  1.1  hsuenaga 
   1877  1.1  hsuenaga 	/*
   1878  1.1  hsuenaga 	 * lookup opencrypto session table
   1879  1.1  hsuenaga 	 *
   1880  1.1  hsuenaga 	 * we have sc_session_mtx after here.
   1881  1.1  hsuenaga 	 */
   1882  1.1  hsuenaga 	mutex_enter(&sc->sc_session_mtx);
   1883  1.1  hsuenaga 	if (sc->sc_nsessions >= MVXPSEC_MAX_SESSIONS) {
   1884  1.1  hsuenaga 		mutex_exit(&sc->sc_session_mtx);
   1885  1.1  hsuenaga 		log(LOG_ERR, "%s: too many IPsec SA(max %d)\n",
   1886  1.1  hsuenaga 				__func__, MVXPSEC_MAX_SESSIONS);
   1887  1.1  hsuenaga 		mvxpsec_session_dealloc(mv_s);
   1888  1.1  hsuenaga 		return ENOMEM;
   1889  1.1  hsuenaga 	}
   1890  1.1  hsuenaga 	for (i = hint; i < MVXPSEC_MAX_SESSIONS; i++) {
   1891  1.1  hsuenaga 		if (sc->sc_sessions[i])
   1892  1.1  hsuenaga 			continue;
   1893  1.1  hsuenaga 		session = i;
   1894  1.1  hsuenaga 		hint = session + 1;
   1895  1.1  hsuenaga 	       	break;
   1896  1.1  hsuenaga 	}
   1897  1.1  hsuenaga 	if (session < 0) {
   1898  1.1  hsuenaga 		for (i = 0; i < hint; i++) {
   1899  1.1  hsuenaga 			if (sc->sc_sessions[i])
   1900  1.1  hsuenaga 				continue;
   1901  1.1  hsuenaga 			session = i;
   1902  1.1  hsuenaga 			hint = session + 1;
   1903  1.1  hsuenaga 			break;
   1904  1.1  hsuenaga 		}
   1905  1.1  hsuenaga 		if (session < 0) {
   1906  1.1  hsuenaga 			mutex_exit(&sc->sc_session_mtx);
   1907  1.1  hsuenaga 			/* session full */
   1908  1.1  hsuenaga 			log(LOG_ERR, "%s: too many IPsec SA(max %d)\n",
   1909  1.1  hsuenaga 				__func__, MVXPSEC_MAX_SESSIONS);
   1910  1.1  hsuenaga 			mvxpsec_session_dealloc(mv_s);
   1911  1.1  hsuenaga 			hint = 0;
   1912  1.1  hsuenaga 			return ENOMEM;
   1913  1.1  hsuenaga 		}
   1914  1.1  hsuenaga 	}
   1915  1.1  hsuenaga 	if (hint >= MVXPSEC_MAX_SESSIONS)
   1916  1.1  hsuenaga 		hint = 0;
   1917  1.1  hsuenaga 	sc->sc_nsessions++;
   1918  1.1  hsuenaga 	sc->sc_sessions[session] = mv_s;
   1919  1.1  hsuenaga #ifdef DEBUG
   1920  1.1  hsuenaga 	log(LOG_DEBUG, "%s: new session %d allocated\n", __func__, session);
   1921  1.1  hsuenaga #endif
   1922  1.1  hsuenaga 
   1923  1.1  hsuenaga 	sid = MVXPSEC_SID(device_unit(sc->sc_dev), session);
   1924  1.1  hsuenaga 	mv_s->sid = sid;
   1925  1.1  hsuenaga 
   1926  1.1  hsuenaga 	/* setup the session key ... */
   1927  1.1  hsuenaga 	for (c = cri; c; c = c->cri_next) {
   1928  1.1  hsuenaga 		switch (c->cri_alg) {
   1929  1.1  hsuenaga 		case CRYPTO_DES_CBC:
   1930  1.1  hsuenaga 		case CRYPTO_3DES_CBC:
   1931  1.1  hsuenaga 		case CRYPTO_AES_CBC:
   1932  1.1  hsuenaga 			/* key */
   1933  1.1  hsuenaga 			if (mvxpsec_key_precomp(c->cri_alg,
   1934  1.1  hsuenaga 			    c->cri_key, c->cri_klen,
   1935  1.1  hsuenaga 			    &mv_s->session_header.crp_key,
   1936  1.1  hsuenaga 			    &mv_s->session_header.crp_key_d)) {
   1937  1.1  hsuenaga 				log(LOG_ERR,
   1938  1.1  hsuenaga 				    "%s: Invalid HMAC key for %s.\n",
   1939  1.1  hsuenaga 				    __func__, s_ctlalg(c->cri_alg));
   1940  1.1  hsuenaga 				err = EINVAL;
   1941  1.1  hsuenaga 				goto fail;
   1942  1.1  hsuenaga 			}
   1943  1.1  hsuenaga 			if (mv_s->sflags & RDY_CRP_KEY) {
   1944  1.1  hsuenaga 				log(LOG_WARNING,
   1945  1.1  hsuenaga 				    "%s: overwrite cipher: %s->%s.\n",
   1946  1.1  hsuenaga 				    __func__,
   1947  1.1  hsuenaga 				    s_ctlalg(mv_s->cipher_alg),
   1948  1.1  hsuenaga 				    s_ctlalg(c->cri_alg));
   1949  1.1  hsuenaga 			}
   1950  1.1  hsuenaga 			mv_s->sflags |= RDY_CRP_KEY;
   1951  1.1  hsuenaga 			mv_s->enc_klen = c->cri_klen;
   1952  1.1  hsuenaga 			mv_s->cipher_alg = c->cri_alg;
   1953  1.1  hsuenaga 			/* create per session IV (compatible with KAME IPsec) */
   1954  1.1  hsuenaga 			cprng_fast(&mv_s->session_iv, sizeof(mv_s->session_iv));
   1955  1.1  hsuenaga 			mv_s->sflags |= RDY_CRP_IV;
   1956  1.1  hsuenaga 			break;
   1957  1.1  hsuenaga 		case CRYPTO_SHA1_HMAC_96:
   1958  1.1  hsuenaga 		case CRYPTO_MD5_HMAC_96:
   1959  1.1  hsuenaga 			/* key */
   1960  1.1  hsuenaga 			if (mvxpsec_hmac_precomp(c->cri_alg,
   1961  1.1  hsuenaga 			    c->cri_key, c->cri_klen,
   1962  1.1  hsuenaga 			    (uint32_t *)&mv_s->session_header.miv_in,
   1963  1.1  hsuenaga 			    (uint32_t *)&mv_s->session_header.miv_out)) {
   1964  1.1  hsuenaga 				log(LOG_ERR,
   1965  1.1  hsuenaga 				    "%s: Invalid MAC key\n", __func__);
   1966  1.1  hsuenaga 				err = EINVAL;
   1967  1.1  hsuenaga 				goto fail;
   1968  1.1  hsuenaga 			}
   1969  1.1  hsuenaga 			if (mv_s->sflags & RDY_MAC_KEY ||
   1970  1.1  hsuenaga 			    mv_s->sflags & RDY_MAC_IV) {
   1971  1.1  hsuenaga 				log(LOG_ERR,
   1972  1.1  hsuenaga 				    "%s: overwrite HMAC: %s->%s.\n",
   1973  1.1  hsuenaga 				    __func__, s_ctlalg(mv_s->hmac_alg),
   1974  1.1  hsuenaga 				    s_ctlalg(c->cri_alg));
   1975  1.1  hsuenaga 			}
   1976  1.1  hsuenaga 			mv_s->sflags |= RDY_MAC_KEY;
   1977  1.1  hsuenaga 			mv_s->sflags |= RDY_MAC_IV;
   1978  1.1  hsuenaga 
   1979  1.1  hsuenaga 			mv_s->mac_klen = c->cri_klen;
   1980  1.1  hsuenaga 			mv_s->hmac_alg = c->cri_alg;
   1981  1.1  hsuenaga 			break;
   1982  1.1  hsuenaga 		default:
   1983  1.1  hsuenaga 			log(LOG_ERR, "%s: Unknown algorithm %d\n",
   1984  1.1  hsuenaga 			    __func__, c->cri_alg);
   1985  1.1  hsuenaga 			err = EINVAL;
   1986  1.1  hsuenaga 			goto fail;
   1987  1.1  hsuenaga 		}
   1988  1.1  hsuenaga 	}
   1989  1.1  hsuenaga 	MVXPSEC_PRINTF(MVXPSEC_DEBUG_OPENCRYPTO,
   1990  1.1  hsuenaga 	    "H/W Crypto session (id:%u) added.\n", session);
   1991  1.1  hsuenaga 
   1992  1.1  hsuenaga 	*sidp = sid;
   1993  1.1  hsuenaga 	MVXPSEC_EVCNT_INCR(sc, session_new);
   1994  1.1  hsuenaga 	mutex_exit(&sc->sc_session_mtx);
   1995  1.1  hsuenaga 
   1996  1.1  hsuenaga 	/* sync session header(it's never touched after here) */
   1997  1.1  hsuenaga 	bus_dmamap_sync(sc->sc_dmat,
   1998  1.1  hsuenaga 	    mv_s->session_header_map,
   1999  1.1  hsuenaga 	    0, sizeof(mv_s->session_header),
   2000  1.1  hsuenaga 	    BUS_DMASYNC_PREWRITE);
   2001  1.1  hsuenaga 
   2002  1.1  hsuenaga 	return 0;
   2003  1.1  hsuenaga 
   2004  1.1  hsuenaga fail:
   2005  1.1  hsuenaga 	sc->sc_nsessions--;
   2006  1.1  hsuenaga 	sc->sc_sessions[session] = NULL;
   2007  1.1  hsuenaga 	hint = session;
   2008  1.1  hsuenaga 	if (mv_s)
   2009  1.1  hsuenaga 		mvxpsec_session_dealloc(mv_s);
   2010  1.1  hsuenaga 	log(LOG_WARNING,
   2011  1.1  hsuenaga 	    "%s: Failed to add H/W crypto sessoin (id:%u): err=%d\n",
   2012  1.1  hsuenaga 	   __func__, session, err);
   2013  1.1  hsuenaga 
   2014  1.1  hsuenaga 	mutex_exit(&sc->sc_session_mtx);
   2015  1.1  hsuenaga 	return err;
   2016  1.1  hsuenaga }
   2017  1.1  hsuenaga 
   2018  1.1  hsuenaga /*
   2019  1.1  hsuenaga  * remove opencrypto session
   2020  1.1  hsuenaga  */
   2021  1.1  hsuenaga int
   2022  1.1  hsuenaga mvxpsec_freesession(void *arg, uint64_t tid)
   2023  1.1  hsuenaga {
   2024  1.1  hsuenaga 	struct mvxpsec_softc *sc = arg;
   2025  1.1  hsuenaga 	struct mvxpsec_session *mv_s;
   2026  1.1  hsuenaga 	int session;
   2027  1.1  hsuenaga 	uint32_t sid = ((uint32_t)tid) & 0xffffffff;
   2028  1.1  hsuenaga 
   2029  1.1  hsuenaga 	session = MVXPSEC_SESSION(sid);
   2030  1.1  hsuenaga 	if (session < 0 || session >= MVXPSEC_MAX_SESSIONS) {
   2031  1.1  hsuenaga 		log(LOG_ERR, "%s: invalid session (id:%u)\n",
   2032  1.1  hsuenaga 		    __func__, session);
   2033  1.1  hsuenaga 		return EINVAL;
   2034  1.1  hsuenaga 	}
   2035  1.1  hsuenaga 
   2036  1.1  hsuenaga 	mutex_enter(&sc->sc_session_mtx);
   2037  1.1  hsuenaga 	if ( (mv_s = sc->sc_sessions[session]) == NULL) {
   2038  1.1  hsuenaga 		mutex_exit(&sc->sc_session_mtx);
   2039  1.1  hsuenaga #ifdef DEBUG
   2040  1.1  hsuenaga 		log(LOG_DEBUG, "%s: session %d already inactivated\n",
   2041  1.1  hsuenaga 		    __func__, session);
   2042  1.1  hsuenaga #endif
   2043  1.1  hsuenaga 		return ENOENT;
   2044  1.1  hsuenaga 	}
   2045  1.1  hsuenaga 	MVXPSEC_PRINTF(MVXPSEC_DEBUG_OPENCRYPTO,
   2046  1.1  hsuenaga 	    "%s: inactivate session %d\n", __func__, session);
   2047  1.1  hsuenaga 
   2048  1.1  hsuenaga 	/* inactivate mvxpsec session */
   2049  1.1  hsuenaga 	sc->sc_sessions[session] = NULL;
   2050  1.1  hsuenaga 	sc->sc_nsessions--;
   2051  1.1  hsuenaga 	sc->sc_last_session = NULL;
   2052  1.1  hsuenaga 	mutex_exit(&sc->sc_session_mtx);
   2053  1.1  hsuenaga 
   2054  1.1  hsuenaga 	KASSERT(sc->sc_nsessions >= 0);
   2055  1.1  hsuenaga 	KASSERT(mv_s->sid == sid);
   2056  1.1  hsuenaga 
   2057  1.1  hsuenaga 	mvxpsec_session_dealloc(mv_s);
   2058  1.1  hsuenaga 	MVXPSEC_PRINTF(MVXPSEC_DEBUG_OPENCRYPTO,
   2059  1.1  hsuenaga 	    "H/W Crypto session (id: %d) deleted.\n", session);
   2060  1.1  hsuenaga 
   2061  1.1  hsuenaga 	/* force unblock opencrypto */
   2062  1.1  hsuenaga 	crypto_unblock(sc->sc_cid, CRYPTO_SYMQ|CRYPTO_ASYMQ);
   2063  1.1  hsuenaga 
   2064  1.1  hsuenaga 	MVXPSEC_EVCNT_INCR(sc, session_free);
   2065  1.1  hsuenaga 
   2066  1.1  hsuenaga 	return 0;
   2067  1.1  hsuenaga }
   2068  1.1  hsuenaga 
   2069  1.1  hsuenaga /*
   2070  1.1  hsuenaga  * process data with existing session
   2071  1.1  hsuenaga  */
   2072  1.1  hsuenaga int
   2073  1.1  hsuenaga mvxpsec_dispatch(void *arg, struct cryptop *crp, int hint)
   2074  1.1  hsuenaga {
   2075  1.1  hsuenaga 	struct mvxpsec_softc *sc = arg;
   2076  1.1  hsuenaga 	struct mvxpsec_session *mv_s;
   2077  1.1  hsuenaga 	struct mvxpsec_packet *mv_p;
   2078  1.1  hsuenaga 	int q_full;
   2079  1.1  hsuenaga 	int running;
   2080  1.1  hsuenaga 	int err;
   2081  1.1  hsuenaga 
   2082  1.1  hsuenaga 	mutex_enter(&sc->sc_queue_mtx);
   2083  1.1  hsuenaga 
   2084  1.1  hsuenaga 	/*
   2085  1.1  hsuenaga 	 * lookup session
   2086  1.1  hsuenaga 	 */
   2087  1.1  hsuenaga 	mutex_enter(&sc->sc_session_mtx);
   2088  1.1  hsuenaga 	mv_s = mvxpsec_session_lookup(sc, crp->crp_sid);
   2089  1.1  hsuenaga 	if (__predict_false(mv_s == NULL)) {
   2090  1.1  hsuenaga 		err = EINVAL;
   2091  1.1  hsuenaga 		mv_p = NULL;
   2092  1.1  hsuenaga 		mutex_exit(&sc->sc_session_mtx);
   2093  1.1  hsuenaga 		goto fail;
   2094  1.1  hsuenaga 	}
   2095  1.1  hsuenaga 	mv_p = mvxpsec_packet_alloc(mv_s);
   2096  1.1  hsuenaga 	if (__predict_false(mv_p == NULL)) {
   2097  1.1  hsuenaga 		mutex_exit(&sc->sc_session_mtx);
   2098  1.1  hsuenaga 		mutex_exit(&sc->sc_queue_mtx);
   2099  1.1  hsuenaga 		return ERESTART; /* => queued in opencrypto layer */
   2100  1.1  hsuenaga 	}
   2101  1.1  hsuenaga 	mutex_exit(&sc->sc_session_mtx);
   2102  1.1  hsuenaga 
   2103  1.1  hsuenaga 	/*
   2104  1.1  hsuenaga 	 * check queue status
   2105  1.1  hsuenaga 	 */
   2106  1.1  hsuenaga #ifdef MVXPSEC_MULTI_PACKET
   2107  1.1  hsuenaga 	q_full = (sc->sc_wait_qlen >= sc->sc_wait_qlimit) ? 1 : 0;
   2108  1.1  hsuenaga #else
   2109  1.1  hsuenaga 	q_full = (sc->sc_wait_qlen != 0) ? 1 : 0;
   2110  1.1  hsuenaga #endif
   2111  1.1  hsuenaga 	running = (sc->sc_flags & HW_RUNNING) ?  1: 0;
   2112  1.1  hsuenaga 	if (q_full) {
   2113  1.1  hsuenaga 		/* input queue is full. */
   2114  1.1  hsuenaga 		if (!running && sc->sc_wait_qlen > 0)
   2115  1.1  hsuenaga 			mvxpsec_dispatch_queue(sc);
   2116  1.1  hsuenaga 		MVXPSEC_EVCNT_INCR(sc, queue_full);
   2117  1.1  hsuenaga 		mvxpsec_packet_dealloc(mv_p);
   2118  1.1  hsuenaga 		mutex_exit(&sc->sc_queue_mtx);
   2119  1.1  hsuenaga 		return ERESTART; /* => queued in opencrypto layer */
   2120  1.1  hsuenaga 	}
   2121  1.1  hsuenaga 
   2122  1.1  hsuenaga 	/*
   2123  1.1  hsuenaga 	 * Load and setup packet data
   2124  1.1  hsuenaga 	 */
   2125  1.1  hsuenaga 	err = mvxpsec_packet_setcrp(mv_p, crp);
   2126  1.1  hsuenaga 	if (__predict_false(err))
   2127  1.1  hsuenaga 		goto fail;
   2128  1.1  hsuenaga 
   2129  1.1  hsuenaga 	/*
   2130  1.1  hsuenaga 	 * Setup DMA descriptor chains
   2131  1.1  hsuenaga 	 */
   2132  1.1  hsuenaga 	mutex_enter(&sc->sc_dma_mtx);
   2133  1.1  hsuenaga 	err = mvxpsec_dma_copy_packet(sc, mv_p);
   2134  1.1  hsuenaga 	mutex_exit(&sc->sc_dma_mtx);
   2135  1.1  hsuenaga 	if (__predict_false(err))
   2136  1.1  hsuenaga 		goto fail;
   2137  1.1  hsuenaga 
   2138  1.1  hsuenaga #ifdef MVXPSEC_DEBUG
   2139  1.1  hsuenaga 	mvxpsec_dump_packet(__func__, mv_p);
   2140  1.1  hsuenaga #endif
   2141  1.1  hsuenaga 
   2142  1.1  hsuenaga 	/*
   2143  1.1  hsuenaga 	 * Sync/inval the data cache
   2144  1.1  hsuenaga 	 */
   2145  1.1  hsuenaga 	err = mvxpsec_dma_sync_packet(sc, mv_p);
   2146  1.1  hsuenaga 	if (__predict_false(err))
   2147  1.1  hsuenaga 		goto fail;
   2148  1.1  hsuenaga 
   2149  1.1  hsuenaga 	/*
   2150  1.1  hsuenaga 	 * Enqueue the packet
   2151  1.1  hsuenaga 	 */
   2152  1.1  hsuenaga 	MVXPSEC_EVCNT_INCR(sc, dispatch_packets);
   2153  1.1  hsuenaga #ifdef MVXPSEC_MULTI_PACKET
   2154  1.1  hsuenaga 	mvxpsec_packet_enqueue(mv_p);
   2155  1.1  hsuenaga 	if (!running)
   2156  1.1  hsuenaga 		mvxpsec_dispatch_queue(sc);
   2157  1.1  hsuenaga #else
   2158  1.1  hsuenaga 	SIMPLEQ_INSERT_TAIL(&sc->sc_wait_queue, mv_p, queue);
   2159  1.1  hsuenaga 	sc->sc_wait_qlen++;
   2160  1.1  hsuenaga 	mv_p->flags |= SETUP_DONE;
   2161  1.1  hsuenaga 	if (!running)
   2162  1.1  hsuenaga 		mvxpsec_dispatch_queue(sc);
   2163  1.1  hsuenaga #endif
   2164  1.1  hsuenaga 	mutex_exit(&sc->sc_queue_mtx);
   2165  1.1  hsuenaga 	return 0;
   2166  1.1  hsuenaga 
   2167  1.1  hsuenaga fail:
   2168  1.1  hsuenaga 	/* Drop the incoming packet */
   2169  1.1  hsuenaga 	mvxpsec_drop(sc, crp, mv_p, err);
   2170  1.1  hsuenaga 	mutex_exit(&sc->sc_queue_mtx);
   2171  1.1  hsuenaga 	return 0;
   2172  1.1  hsuenaga }
   2173  1.1  hsuenaga 
   2174  1.1  hsuenaga /*
   2175  1.1  hsuenaga  * back the packet to the IP stack
   2176  1.1  hsuenaga  */
   2177  1.1  hsuenaga void
   2178  1.1  hsuenaga mvxpsec_done(void *arg)
   2179  1.1  hsuenaga {
   2180  1.1  hsuenaga 	struct mvxpsec_softc *sc = arg;
   2181  1.1  hsuenaga 	struct mvxpsec_packet *mv_p;
   2182  1.1  hsuenaga 	mvxpsec_queue_t ret_queue;
   2183  1.1  hsuenaga 	int ndone;
   2184  1.1  hsuenaga 
   2185  1.1  hsuenaga 	mutex_enter(&sc->sc_queue_mtx);
   2186  1.1  hsuenaga 
   2187  1.1  hsuenaga 	/* stop wdog timer */
   2188  1.1  hsuenaga 	callout_stop(&sc->sc_timeout);
   2189  1.1  hsuenaga 
   2190  1.1  hsuenaga 	/* refill MVXPSEC */
   2191  1.1  hsuenaga 	ret_queue = sc->sc_run_queue;
   2192  1.1  hsuenaga 	SIMPLEQ_INIT(&sc->sc_run_queue);
   2193  1.1  hsuenaga 	sc->sc_flags &= ~HW_RUNNING;
   2194  1.1  hsuenaga 	if (sc->sc_wait_qlen > 0)
   2195  1.1  hsuenaga 		mvxpsec_dispatch_queue(sc);
   2196  1.1  hsuenaga 
   2197  1.1  hsuenaga 	ndone = 0;
   2198  1.1  hsuenaga 	while ( (mv_p = SIMPLEQ_FIRST(&ret_queue)) != NULL) {
   2199  1.1  hsuenaga 		SIMPLEQ_REMOVE_HEAD(&ret_queue, queue);
   2200  1.1  hsuenaga 		mvxpsec_dma_free(sc, &mv_p->dma_ring);
   2201  1.1  hsuenaga 		mvxpsec_done_packet(mv_p);
   2202  1.1  hsuenaga 		ndone++;
   2203  1.1  hsuenaga 	}
   2204  1.1  hsuenaga 	MVXPSEC_EVCNT_MAX(sc, max_done, ndone);
   2205  1.1  hsuenaga 
   2206  1.1  hsuenaga 	mutex_exit(&sc->sc_queue_mtx);
   2207  1.1  hsuenaga }
   2208  1.1  hsuenaga 
   2209  1.1  hsuenaga /*
   2210  1.1  hsuenaga  * drop the packet
   2211  1.1  hsuenaga  */
   2212  1.1  hsuenaga INLINE void
   2213  1.1  hsuenaga mvxpsec_drop(struct mvxpsec_softc *sc, struct cryptop *crp,
   2214  1.1  hsuenaga     struct mvxpsec_packet *mv_p, int err)
   2215  1.1  hsuenaga {
   2216  1.1  hsuenaga 	/* must called with sc->sc_queue_mtx held */
   2217  1.1  hsuenaga 	KASSERT(mutex_owned(&sc->sc_queue_mtx));
   2218  1.1  hsuenaga 
   2219  1.1  hsuenaga 	if (mv_p)
   2220  1.1  hsuenaga 		mvxpsec_packet_dealloc(mv_p);
   2221  1.1  hsuenaga 	if (err < 0)
   2222  1.1  hsuenaga 		err = EINVAL;
   2223  1.1  hsuenaga 	crp->crp_etype = err;
   2224  1.1  hsuenaga 	crypto_done(crp);
   2225  1.1  hsuenaga 	MVXPSEC_EVCNT_INCR(sc, packet_err);
   2226  1.1  hsuenaga 
   2227  1.1  hsuenaga 	/* dispatch other packets in queue */
   2228  1.1  hsuenaga 	if (sc->sc_wait_qlen > 0 &&
   2229  1.1  hsuenaga 	    !(sc->sc_flags & HW_RUNNING))
   2230  1.1  hsuenaga 		mvxpsec_dispatch_queue(sc);
   2231  1.1  hsuenaga 
   2232  1.1  hsuenaga 	/* unblock driver for dropped packet */
   2233  1.1  hsuenaga 	crypto_unblock(sc->sc_cid, CRYPTO_SYMQ|CRYPTO_ASYMQ);
   2234  1.1  hsuenaga }
   2235  1.1  hsuenaga 
   2236  1.1  hsuenaga /* move wait queue entry to run queue */
   2237  1.1  hsuenaga STATIC int
   2238  1.1  hsuenaga mvxpsec_dispatch_queue(struct mvxpsec_softc *sc)
   2239  1.1  hsuenaga {
   2240  1.1  hsuenaga 	struct mvxpsec_packet *mv_p;
   2241  1.1  hsuenaga 	paddr_t head;
   2242  1.1  hsuenaga 	int ndispatch = 0;
   2243  1.1  hsuenaga 
   2244  1.1  hsuenaga 	/* must called with sc->sc_queue_mtx held */
   2245  1.1  hsuenaga 	KASSERT(mutex_owned(&sc->sc_queue_mtx));
   2246  1.1  hsuenaga 
   2247  1.1  hsuenaga 	/* check there is any task */
   2248  1.1  hsuenaga 	if (__predict_false(sc->sc_flags & HW_RUNNING)) {
   2249  1.1  hsuenaga 		log(LOG_WARNING,
   2250  1.1  hsuenaga 		    "%s: another packet already exist.\n", __func__);
   2251  1.1  hsuenaga 		return 0;
   2252  1.1  hsuenaga 	}
   2253  1.1  hsuenaga 	if (__predict_false(SIMPLEQ_EMPTY(&sc->sc_wait_queue))) {
   2254  1.1  hsuenaga 		log(LOG_WARNING,
   2255  1.1  hsuenaga 		    "%s: no waiting packet yet(qlen=%d).\n",
   2256  1.1  hsuenaga 		    __func__, sc->sc_wait_qlen);
   2257  1.1  hsuenaga 		return 0;
   2258  1.1  hsuenaga 	}
   2259  1.1  hsuenaga 
   2260  1.1  hsuenaga 	/* move queue */
   2261  1.1  hsuenaga 	sc->sc_run_queue = sc->sc_wait_queue;
   2262  1.1  hsuenaga 	sc->sc_flags |= HW_RUNNING; /* dropped by intr or timeout */
   2263  1.1  hsuenaga 	SIMPLEQ_INIT(&sc->sc_wait_queue);
   2264  1.1  hsuenaga 	ndispatch = sc->sc_wait_qlen;
   2265  1.1  hsuenaga 	sc->sc_wait_qlen = 0;
   2266  1.1  hsuenaga 
   2267  1.1  hsuenaga 	/* get 1st DMA descriptor */
   2268  1.1  hsuenaga 	mv_p = SIMPLEQ_FIRST(&sc->sc_run_queue);
   2269  1.1  hsuenaga 	head = mv_p->dma_ring.dma_head->phys_addr;
   2270  1.1  hsuenaga 
   2271  1.1  hsuenaga 	/* terminate last DMA descriptor */
   2272  1.1  hsuenaga 	mv_p = SIMPLEQ_LAST(&sc->sc_run_queue, mvxpsec_packet, queue);
   2273  1.1  hsuenaga 	mvxpsec_dma_finalize(sc, &mv_p->dma_ring);
   2274  1.1  hsuenaga 
   2275  1.1  hsuenaga 	/* configure TDMA */
   2276  1.1  hsuenaga 	if (mvxpsec_dma_wait(sc) < 0) {
   2277  1.1  hsuenaga 		log(LOG_ERR, "%s: DMA DEVICE not responding", __func__);
   2278  1.1  hsuenaga 		callout_schedule(&sc->sc_timeout, hz);
   2279  1.1  hsuenaga 		return 0;
   2280  1.1  hsuenaga 	}
   2281  1.1  hsuenaga 	MVXPSEC_WRITE(sc, MV_TDMA_NXT, head);
   2282  1.1  hsuenaga 
   2283  1.1  hsuenaga 	/* trigger ACC */
   2284  1.1  hsuenaga 	if (mvxpsec_acc_wait(sc) < 0) {
   2285  1.1  hsuenaga 		log(LOG_ERR, "%s: MVXPSEC not responding", __func__);
   2286  1.1  hsuenaga 		callout_schedule(&sc->sc_timeout, hz);
   2287  1.1  hsuenaga 		return 0;
   2288  1.1  hsuenaga 	}
   2289  1.1  hsuenaga 	MVXPSEC_WRITE(sc, MV_ACC_COMMAND, MV_ACC_COMMAND_ACT);
   2290  1.1  hsuenaga 
   2291  1.1  hsuenaga 	MVXPSEC_EVCNT_MAX(sc, max_dispatch, ndispatch);
   2292  1.1  hsuenaga 	MVXPSEC_EVCNT_INCR(sc, dispatch_queue);
   2293  1.1  hsuenaga 	callout_schedule(&sc->sc_timeout, hz);
   2294  1.1  hsuenaga 	return 0;
   2295  1.1  hsuenaga }
   2296  1.1  hsuenaga 
   2297  1.1  hsuenaga /*
   2298  1.1  hsuenaga  * process opencrypto operations(cryptop) for packets.
   2299  1.1  hsuenaga  */
   2300  1.1  hsuenaga INLINE int
   2301  1.1  hsuenaga mvxpsec_parse_crd(struct mvxpsec_packet *mv_p, struct cryptodesc *crd)
   2302  1.1  hsuenaga {
   2303  1.1  hsuenaga 	int ivlen;
   2304  1.1  hsuenaga 
   2305  1.1  hsuenaga 	KASSERT(mv_p->flags & RDY_DATA);
   2306  1.1  hsuenaga 
   2307  1.1  hsuenaga 	/* MAC & Ciphers: set data location and operation */
   2308  1.1  hsuenaga 	switch (crd->crd_alg) {
   2309  1.1  hsuenaga 	case CRYPTO_SHA1_HMAC_96:
   2310  1.1  hsuenaga 		mv_p->pkt_header.desc.acc_config |= MV_ACC_CRYPTO_MAC_96;
   2311  1.1  hsuenaga 		/* fall through */
   2312  1.1  hsuenaga 	case CRYPTO_SHA1_HMAC:
   2313  1.1  hsuenaga 		mv_p->mac_dst = crd->crd_inject;
   2314  1.1  hsuenaga 		mv_p->mac_off = crd->crd_skip;
   2315  1.1  hsuenaga 		mv_p->mac_len = crd->crd_len;
   2316  1.1  hsuenaga 		MV_ACC_CRYPTO_MAC_SET(mv_p->pkt_header.desc.acc_config,
   2317  1.1  hsuenaga 		    MV_ACC_CRYPTO_MAC_HMAC_SHA1);
   2318  1.1  hsuenaga 		mvxpsec_packet_update_op_order(mv_p, MV_ACC_CRYPTO_OP_MAC);
   2319  1.1  hsuenaga 		/* No more setup for MAC */
   2320  1.1  hsuenaga 		return 0;
   2321  1.1  hsuenaga 	case CRYPTO_MD5_HMAC_96:
   2322  1.1  hsuenaga 		mv_p->pkt_header.desc.acc_config |= MV_ACC_CRYPTO_MAC_96;
   2323  1.1  hsuenaga 		/* fall through */
   2324  1.1  hsuenaga 	case CRYPTO_MD5_HMAC:
   2325  1.1  hsuenaga 		mv_p->mac_dst = crd->crd_inject;
   2326  1.1  hsuenaga 		mv_p->mac_off = crd->crd_skip;
   2327  1.1  hsuenaga 		mv_p->mac_len = crd->crd_len;
   2328  1.1  hsuenaga 		MV_ACC_CRYPTO_MAC_SET(mv_p->pkt_header.desc.acc_config,
   2329  1.1  hsuenaga 		    MV_ACC_CRYPTO_MAC_HMAC_MD5);
   2330  1.1  hsuenaga 		mvxpsec_packet_update_op_order(mv_p, MV_ACC_CRYPTO_OP_MAC);
   2331  1.1  hsuenaga 		/* No more setup for MAC */
   2332  1.1  hsuenaga 		return 0;
   2333  1.1  hsuenaga 	case CRYPTO_DES_CBC:
   2334  1.1  hsuenaga 		mv_p->enc_ivoff = crd->crd_inject;
   2335  1.1  hsuenaga 		mv_p->enc_off = crd->crd_skip;
   2336  1.1  hsuenaga 		mv_p->enc_len = crd->crd_len;
   2337  1.1  hsuenaga 		ivlen = 8;
   2338  1.1  hsuenaga 		MV_ACC_CRYPTO_ENC_SET(mv_p->pkt_header.desc.acc_config,
   2339  1.1  hsuenaga 		    MV_ACC_CRYPTO_ENC_DES);
   2340  1.1  hsuenaga 		mv_p->pkt_header.desc.acc_config |= MV_ACC_CRYPTO_CBC;
   2341  1.1  hsuenaga 		mvxpsec_packet_update_op_order(mv_p, MV_ACC_CRYPTO_OP_ENC);
   2342  1.1  hsuenaga 		break;
   2343  1.1  hsuenaga 	case CRYPTO_3DES_CBC:
   2344  1.1  hsuenaga 		mv_p->enc_ivoff = crd->crd_inject;
   2345  1.1  hsuenaga 		mv_p->enc_off = crd->crd_skip;
   2346  1.1  hsuenaga 		mv_p->enc_len = crd->crd_len;
   2347  1.1  hsuenaga 		ivlen = 8;
   2348  1.1  hsuenaga 		MV_ACC_CRYPTO_ENC_SET(mv_p->pkt_header.desc.acc_config,
   2349  1.1  hsuenaga 		    MV_ACC_CRYPTO_ENC_3DES);
   2350  1.1  hsuenaga 		mv_p->pkt_header.desc.acc_config |= MV_ACC_CRYPTO_CBC;
   2351  1.1  hsuenaga 		mv_p->pkt_header.desc.acc_config |= MV_ACC_CRYPTO_3DES_EDE;
   2352  1.1  hsuenaga 		mvxpsec_packet_update_op_order(mv_p, MV_ACC_CRYPTO_OP_ENC);
   2353  1.1  hsuenaga 		break;
   2354  1.1  hsuenaga 	case CRYPTO_AES_CBC:
   2355  1.1  hsuenaga 		mv_p->enc_ivoff = crd->crd_inject;
   2356  1.1  hsuenaga 		mv_p->enc_off = crd->crd_skip;
   2357  1.1  hsuenaga 		mv_p->enc_len = crd->crd_len;
   2358  1.1  hsuenaga 		ivlen = 16;
   2359  1.1  hsuenaga 		MV_ACC_CRYPTO_ENC_SET(mv_p->pkt_header.desc.acc_config,
   2360  1.1  hsuenaga 		    MV_ACC_CRYPTO_ENC_AES);
   2361  1.1  hsuenaga 		MV_ACC_CRYPTO_AES_KLEN_SET(
   2362  1.1  hsuenaga 		    mv_p->pkt_header.desc.acc_config,
   2363  1.1  hsuenaga 		   mvxpsec_aesklen(mv_p->mv_s->enc_klen));
   2364  1.1  hsuenaga 		mv_p->pkt_header.desc.acc_config |= MV_ACC_CRYPTO_CBC;
   2365  1.1  hsuenaga 		mvxpsec_packet_update_op_order(mv_p, MV_ACC_CRYPTO_OP_ENC);
   2366  1.1  hsuenaga 		break;
   2367  1.1  hsuenaga 	default:
   2368  1.1  hsuenaga 		log(LOG_ERR, "%s: Unknown algorithm %d\n",
   2369  1.1  hsuenaga 		    __func__, crd->crd_alg);
   2370  1.1  hsuenaga 		return EINVAL;
   2371  1.1  hsuenaga 	}
   2372  1.1  hsuenaga 
   2373  1.1  hsuenaga 	/* Operations only for Cipher, not MAC */
   2374  1.1  hsuenaga 	if (crd->crd_flags & CRD_F_ENCRYPT) {
   2375  1.1  hsuenaga 		/* Ciphers: Originate IV for Encryption.*/
   2376  1.1  hsuenaga 		mv_p->pkt_header.desc.acc_config &= ~MV_ACC_CRYPTO_DECRYPT;
   2377  1.1  hsuenaga 		mv_p->flags |= DIR_ENCRYPT;
   2378  1.1  hsuenaga 
   2379  1.1  hsuenaga 		if (crd->crd_flags & CRD_F_IV_EXPLICIT) {
   2380  1.1  hsuenaga 			MVXPSEC_PRINTF(MVXPSEC_DEBUG_ENC_IV, "EXPLICIT IV\n");
   2381  1.1  hsuenaga 			mv_p->flags |= CRP_EXT_IV;
   2382  1.1  hsuenaga 			mvxpsec_packet_write_iv(mv_p, crd->crd_iv, ivlen);
   2383  1.1  hsuenaga 			mv_p->enc_ivoff = MVXPSEC_SRAM_IV_EXT_OFF;
   2384  1.1  hsuenaga 		}
   2385  1.1  hsuenaga 		else if (crd->crd_flags & CRD_F_IV_PRESENT) {
   2386  1.1  hsuenaga 			MVXPSEC_PRINTF(MVXPSEC_DEBUG_ENC_IV, "IV is present\n");
   2387  1.1  hsuenaga 			mvxpsec_packet_copy_iv(mv_p, crd->crd_inject, ivlen);
   2388  1.1  hsuenaga 		}
   2389  1.1  hsuenaga 		else {
   2390  1.1  hsuenaga 			MVXPSEC_PRINTF(MVXPSEC_DEBUG_ENC_IV, "Create New IV\n");
   2391  1.1  hsuenaga 			mvxpsec_packet_write_iv(mv_p, NULL, ivlen);
   2392  1.1  hsuenaga 		}
   2393  1.1  hsuenaga 	}
   2394  1.1  hsuenaga 	else {
   2395  1.1  hsuenaga 		/* Ciphers: IV is loadded from crd_inject when it's present */
   2396  1.1  hsuenaga 		mv_p->pkt_header.desc.acc_config |= MV_ACC_CRYPTO_DECRYPT;
   2397  1.1  hsuenaga 		mv_p->flags |= DIR_DECRYPT;
   2398  1.1  hsuenaga 
   2399  1.1  hsuenaga 		if (crd->crd_flags & CRD_F_IV_EXPLICIT) {
   2400  1.1  hsuenaga #ifdef MVXPSEC_DEBUG
   2401  1.1  hsuenaga 			if (mvxpsec_debug & MVXPSEC_DEBUG_ENC_IV) {
   2402  1.1  hsuenaga 				MVXPSEC_PRINTF(MVXPSEC_DEBUG_ENC_IV,
   2403  1.1  hsuenaga 				    "EXPLICIT IV(Decrypt)\n");
   2404  1.1  hsuenaga 				mvxpsec_dump_data(__func__, crd->crd_iv, ivlen);
   2405  1.1  hsuenaga 			}
   2406  1.1  hsuenaga #endif
   2407  1.1  hsuenaga 			mv_p->flags |= CRP_EXT_IV;
   2408  1.1  hsuenaga 			mvxpsec_packet_write_iv(mv_p, crd->crd_iv, ivlen);
   2409  1.1  hsuenaga 			mv_p->enc_ivoff = MVXPSEC_SRAM_IV_EXT_OFF;
   2410  1.1  hsuenaga 		}
   2411  1.1  hsuenaga 	}
   2412  1.1  hsuenaga 
   2413  1.1  hsuenaga 	KASSERT(!((mv_p->flags & DIR_ENCRYPT) && (mv_p->flags & DIR_DECRYPT)));
   2414  1.1  hsuenaga 
   2415  1.1  hsuenaga 	return 0;
   2416  1.1  hsuenaga }
   2417  1.1  hsuenaga 
   2418  1.1  hsuenaga INLINE int
   2419  1.1  hsuenaga mvxpsec_parse_crp(struct mvxpsec_packet *mv_p)
   2420  1.1  hsuenaga {
   2421  1.1  hsuenaga 	struct cryptop *crp = mv_p->crp;
   2422  1.1  hsuenaga 	struct cryptodesc *crd;
   2423  1.1  hsuenaga 	int err;
   2424  1.1  hsuenaga 
   2425  1.1  hsuenaga 	KASSERT(crp);
   2426  1.1  hsuenaga 
   2427  1.1  hsuenaga 	mvxpsec_packet_reset_op(mv_p);
   2428  1.1  hsuenaga 
   2429  1.1  hsuenaga 	for (crd = crp->crp_desc; crd; crd = crd->crd_next) {
   2430  1.1  hsuenaga 		err = mvxpsec_parse_crd(mv_p, crd);
   2431  1.1  hsuenaga 		if (err)
   2432  1.1  hsuenaga 			return err;
   2433  1.1  hsuenaga 	}
   2434  1.1  hsuenaga 
   2435  1.1  hsuenaga 	return 0;
   2436  1.1  hsuenaga }
   2437  1.1  hsuenaga 
   2438  1.1  hsuenaga INLINE int
   2439  1.1  hsuenaga mvxpsec_packet_setcrp(struct mvxpsec_packet *mv_p, struct cryptop *crp)
   2440  1.1  hsuenaga {
   2441  1.1  hsuenaga 	int err = EINVAL;
   2442  1.1  hsuenaga 
   2443  1.1  hsuenaga 	/* regiseter crp to the MVXPSEC packet */
   2444  1.1  hsuenaga 	if (crp->crp_flags & CRYPTO_F_IMBUF) {
   2445  1.1  hsuenaga 		err = mvxpsec_packet_setmbuf(mv_p,
   2446  1.1  hsuenaga 		    (struct mbuf *)crp->crp_buf);
   2447  1.1  hsuenaga 		mv_p->crp = crp;
   2448  1.1  hsuenaga 	}
   2449  1.1  hsuenaga 	else if (crp->crp_flags & CRYPTO_F_IOV) {
   2450  1.1  hsuenaga 		err = mvxpsec_packet_setuio(mv_p,
   2451  1.1  hsuenaga 		    (struct uio *)crp->crp_buf);
   2452  1.1  hsuenaga 		mv_p->crp = crp;
   2453  1.1  hsuenaga 	}
   2454  1.1  hsuenaga 	else {
   2455  1.1  hsuenaga 		err = mvxpsec_packet_setdata(mv_p,
   2456  1.1  hsuenaga 		    (struct mbuf *)crp->crp_buf, crp->crp_ilen);
   2457  1.1  hsuenaga 		mv_p->crp = crp;
   2458  1.1  hsuenaga 	}
   2459  1.1  hsuenaga 	if (__predict_false(err))
   2460  1.1  hsuenaga 		return err;
   2461  1.1  hsuenaga 
   2462  1.1  hsuenaga 	/* parse crp and setup MVXPSEC registers/descriptors */
   2463  1.1  hsuenaga 	err = mvxpsec_parse_crp(mv_p);
   2464  1.1  hsuenaga 	if (__predict_false(err))
   2465  1.1  hsuenaga 		return err;
   2466  1.1  hsuenaga 
   2467  1.1  hsuenaga 	/* fixup data offset to fit MVXPSEC internal SRAM */
   2468  1.1  hsuenaga 	err = mvxpsec_header_finalize(mv_p);
   2469  1.1  hsuenaga 	if (__predict_false(err))
   2470  1.1  hsuenaga 		return err;
   2471  1.1  hsuenaga 
   2472  1.1  hsuenaga 	return 0;
   2473  1.1  hsuenaga }
   2474  1.1  hsuenaga 
   2475  1.1  hsuenaga /*
   2476  1.1  hsuenaga  * load data for encrypt/decrypt/authentication
   2477  1.1  hsuenaga  *
   2478  1.1  hsuenaga  * data is raw kernel memory area.
   2479  1.1  hsuenaga  */
   2480  1.1  hsuenaga STATIC int
   2481  1.1  hsuenaga mvxpsec_packet_setdata(struct mvxpsec_packet *mv_p,
   2482  1.1  hsuenaga     void *data, uint32_t data_len)
   2483  1.1  hsuenaga {
   2484  1.1  hsuenaga 	struct mvxpsec_session *mv_s = mv_p->mv_s;
   2485  1.1  hsuenaga 	struct mvxpsec_softc *sc = mv_s->sc;
   2486  1.1  hsuenaga 
   2487  1.1  hsuenaga 	if (bus_dmamap_load(sc->sc_dmat, mv_p->data_map, data, data_len,
   2488  1.1  hsuenaga 	    NULL, BUS_DMA_NOWAIT)) {
   2489  1.1  hsuenaga 		log(LOG_ERR, "%s: cannot load data\n", __func__);
   2490  1.1  hsuenaga 		return -1;
   2491  1.1  hsuenaga 	}
   2492  1.1  hsuenaga 	mv_p->data_type = MVXPSEC_DATA_RAW;
   2493  1.1  hsuenaga 	mv_p->data_raw = data;
   2494  1.1  hsuenaga 	mv_p->data_len = data_len;
   2495  1.1  hsuenaga 	mv_p->flags |= RDY_DATA;
   2496  1.1  hsuenaga 
   2497  1.1  hsuenaga 	return 0;
   2498  1.1  hsuenaga }
   2499  1.1  hsuenaga 
   2500  1.1  hsuenaga /*
   2501  1.1  hsuenaga  * load data for encrypt/decrypt/authentication
   2502  1.1  hsuenaga  *
   2503  1.1  hsuenaga  * data is mbuf based network data.
   2504  1.1  hsuenaga  */
   2505  1.1  hsuenaga STATIC int
   2506  1.1  hsuenaga mvxpsec_packet_setmbuf(struct mvxpsec_packet *mv_p, struct mbuf *m)
   2507  1.1  hsuenaga {
   2508  1.1  hsuenaga 	struct mvxpsec_session *mv_s = mv_p->mv_s;
   2509  1.1  hsuenaga 	struct mvxpsec_softc *sc = mv_s->sc;
   2510  1.1  hsuenaga 	size_t pktlen = 0;
   2511  1.1  hsuenaga 
   2512  1.1  hsuenaga 	if (__predict_true(m->m_flags & M_PKTHDR))
   2513  1.1  hsuenaga 		pktlen = m->m_pkthdr.len;
   2514  1.1  hsuenaga 	else {
   2515  1.1  hsuenaga 		struct mbuf *mp = m;
   2516  1.1  hsuenaga 
   2517  1.1  hsuenaga 		while (mp != NULL) {
   2518  1.1  hsuenaga 			pktlen += m->m_len;
   2519  1.1  hsuenaga 			mp = mp->m_next;
   2520  1.1  hsuenaga 		}
   2521  1.1  hsuenaga 	}
   2522  1.1  hsuenaga 	if (pktlen > SRAM_PAYLOAD_SIZE) {
   2523  1.7  riastrad #if NIPSEC > 0
   2524  1.1  hsuenaga 		extern   percpu_t *espstat_percpu;
   2525  1.1  hsuenaga 	       	/* XXX:
   2526  1.1  hsuenaga 		 * layer violation. opencrypto knows our max packet size
   2527  1.1  hsuenaga 		 * from crypto_register(9) API.
   2528  1.1  hsuenaga 		 */
   2529  1.1  hsuenaga 
   2530  1.1  hsuenaga 		_NET_STATINC(espstat_percpu, ESP_STAT_TOOBIG);
   2531  1.7  riastrad #endif
   2532  1.1  hsuenaga 		log(LOG_ERR,
   2533  1.1  hsuenaga 		    "%s: ESP Packet too large: %zu [oct.] > %zu [oct.]\n",
   2534  1.1  hsuenaga 		    device_xname(sc->sc_dev),
   2535  1.1  hsuenaga 		    (size_t)pktlen, SRAM_PAYLOAD_SIZE);
   2536  1.1  hsuenaga 		mv_p->data_type = MVXPSEC_DATA_NONE;
   2537  1.1  hsuenaga 		mv_p->data_mbuf = NULL;
   2538  1.1  hsuenaga 		return -1;
   2539  1.1  hsuenaga 	}
   2540  1.1  hsuenaga 
   2541  1.1  hsuenaga 	if (bus_dmamap_load_mbuf(sc->sc_dmat, mv_p->data_map, m,
   2542  1.1  hsuenaga 	    BUS_DMA_NOWAIT)) {
   2543  1.1  hsuenaga 		mv_p->data_type = MVXPSEC_DATA_NONE;
   2544  1.1  hsuenaga 		mv_p->data_mbuf = NULL;
   2545  1.1  hsuenaga 		log(LOG_ERR, "%s: cannot load mbuf\n", __func__);
   2546  1.1  hsuenaga 		return -1;
   2547  1.1  hsuenaga 	}
   2548  1.1  hsuenaga 
   2549  1.1  hsuenaga 	/* set payload buffer */
   2550  1.1  hsuenaga 	mv_p->data_type = MVXPSEC_DATA_MBUF;
   2551  1.1  hsuenaga 	mv_p->data_mbuf = m;
   2552  1.1  hsuenaga 	if (m->m_flags & M_PKTHDR) {
   2553  1.1  hsuenaga 		mv_p->data_len = m->m_pkthdr.len;
   2554  1.1  hsuenaga 	}
   2555  1.1  hsuenaga 	else {
   2556  1.1  hsuenaga 		mv_p->data_len = 0;
   2557  1.1  hsuenaga 		while (m) {
   2558  1.1  hsuenaga 			mv_p->data_len += m->m_len;
   2559  1.1  hsuenaga 			m = m->m_next;
   2560  1.1  hsuenaga 		}
   2561  1.1  hsuenaga 	}
   2562  1.1  hsuenaga 	mv_p->flags |= RDY_DATA;
   2563  1.1  hsuenaga 
   2564  1.1  hsuenaga 	return 0;
   2565  1.1  hsuenaga }
   2566  1.1  hsuenaga 
   2567  1.1  hsuenaga STATIC int
   2568  1.1  hsuenaga mvxpsec_packet_setuio(struct mvxpsec_packet *mv_p, struct uio *uio)
   2569  1.1  hsuenaga {
   2570  1.1  hsuenaga 	struct mvxpsec_session *mv_s = mv_p->mv_s;
   2571  1.1  hsuenaga 	struct mvxpsec_softc *sc = mv_s->sc;
   2572  1.1  hsuenaga 
   2573  1.1  hsuenaga 	if (uio->uio_resid > SRAM_PAYLOAD_SIZE) {
   2574  1.7  riastrad #if NIPSEC > 0
   2575  1.1  hsuenaga 		extern   percpu_t *espstat_percpu;
   2576  1.1  hsuenaga 	       	/* XXX:
   2577  1.1  hsuenaga 		 * layer violation. opencrypto knows our max packet size
   2578  1.1  hsuenaga 		 * from crypto_register(9) API.
   2579  1.1  hsuenaga 		 */
   2580  1.1  hsuenaga 
   2581  1.1  hsuenaga 		_NET_STATINC(espstat_percpu, ESP_STAT_TOOBIG);
   2582  1.7  riastrad #endif
   2583  1.1  hsuenaga 		log(LOG_ERR,
   2584  1.1  hsuenaga 		    "%s: uio request too large: %zu [oct.] > %zu [oct.]\n",
   2585  1.1  hsuenaga 		    device_xname(sc->sc_dev),
   2586  1.1  hsuenaga 		    uio->uio_resid, SRAM_PAYLOAD_SIZE);
   2587  1.1  hsuenaga 		mv_p->data_type = MVXPSEC_DATA_NONE;
   2588  1.1  hsuenaga 		mv_p->data_mbuf = NULL;
   2589  1.1  hsuenaga 		return -1;
   2590  1.1  hsuenaga 	}
   2591  1.1  hsuenaga 
   2592  1.1  hsuenaga 	if (bus_dmamap_load_uio(sc->sc_dmat, mv_p->data_map, uio,
   2593  1.1  hsuenaga 	    BUS_DMA_NOWAIT)) {
   2594  1.1  hsuenaga 		mv_p->data_type = MVXPSEC_DATA_NONE;
   2595  1.1  hsuenaga 		mv_p->data_mbuf = NULL;
   2596  1.1  hsuenaga 		log(LOG_ERR, "%s: cannot load uio buf\n", __func__);
   2597  1.1  hsuenaga 		return -1;
   2598  1.1  hsuenaga 	}
   2599  1.1  hsuenaga 
   2600  1.1  hsuenaga 	/* set payload buffer */
   2601  1.1  hsuenaga 	mv_p->data_type = MVXPSEC_DATA_UIO;
   2602  1.1  hsuenaga 	mv_p->data_uio = uio;
   2603  1.1  hsuenaga 	mv_p->data_len = uio->uio_resid;
   2604  1.1  hsuenaga 	mv_p->flags |= RDY_DATA;
   2605  1.1  hsuenaga 
   2606  1.1  hsuenaga 	return 0;
   2607  1.1  hsuenaga }
   2608  1.1  hsuenaga 
   2609  1.1  hsuenaga STATIC int
   2610  1.1  hsuenaga mvxpsec_packet_rdata(struct mvxpsec_packet *mv_p,
   2611  1.1  hsuenaga     int off, int len, void *cp)
   2612  1.1  hsuenaga {
   2613  1.1  hsuenaga 	uint8_t *p;
   2614  1.1  hsuenaga 
   2615  1.1  hsuenaga 	if (mv_p->data_type == MVXPSEC_DATA_RAW) {
   2616  1.1  hsuenaga 		p = (uint8_t *)mv_p->data_raw + off;
   2617  1.1  hsuenaga 		memcpy(cp, p, len);
   2618  1.1  hsuenaga 	}
   2619  1.1  hsuenaga 	else if (mv_p->data_type == MVXPSEC_DATA_MBUF) {
   2620  1.1  hsuenaga 		m_copydata(mv_p->data_mbuf, off, len, cp);
   2621  1.1  hsuenaga 	}
   2622  1.1  hsuenaga 	else if (mv_p->data_type == MVXPSEC_DATA_UIO) {
   2623  1.1  hsuenaga 		cuio_copydata(mv_p->data_uio, off, len, cp);
   2624  1.1  hsuenaga 	}
   2625  1.1  hsuenaga 	else
   2626  1.1  hsuenaga 		return -1;
   2627  1.1  hsuenaga 
   2628  1.1  hsuenaga 	return 0;
   2629  1.1  hsuenaga }
   2630  1.1  hsuenaga 
   2631  1.1  hsuenaga STATIC int
   2632  1.1  hsuenaga mvxpsec_packet_wdata(struct mvxpsec_packet *mv_p,
   2633  1.1  hsuenaga     int off, int len, void *cp)
   2634  1.1  hsuenaga {
   2635  1.1  hsuenaga 	uint8_t *p;
   2636  1.1  hsuenaga 
   2637  1.1  hsuenaga 	if (mv_p->data_type == MVXPSEC_DATA_RAW) {
   2638  1.1  hsuenaga 		p = (uint8_t *)mv_p->data_raw + off;
   2639  1.1  hsuenaga 		memcpy(p, cp, len);
   2640  1.1  hsuenaga 	}
   2641  1.1  hsuenaga 	else if (mv_p->data_type == MVXPSEC_DATA_MBUF) {
   2642  1.1  hsuenaga 		m_copyback(mv_p->data_mbuf, off, len, cp);
   2643  1.1  hsuenaga 	}
   2644  1.1  hsuenaga 	else if (mv_p->data_type == MVXPSEC_DATA_UIO) {
   2645  1.1  hsuenaga 		cuio_copyback(mv_p->data_uio, off, len, cp);
   2646  1.1  hsuenaga 	}
   2647  1.1  hsuenaga 	else
   2648  1.1  hsuenaga 		return -1;
   2649  1.1  hsuenaga 
   2650  1.1  hsuenaga 	return 0;
   2651  1.1  hsuenaga }
   2652  1.1  hsuenaga 
   2653  1.1  hsuenaga /*
   2654  1.1  hsuenaga  * Set initial vector of cipher to the session.
   2655  1.1  hsuenaga  */
   2656  1.1  hsuenaga STATIC int
   2657  1.1  hsuenaga mvxpsec_packet_write_iv(struct mvxpsec_packet *mv_p, void *iv, int ivlen)
   2658  1.1  hsuenaga {
   2659  1.1  hsuenaga 	uint8_t ivbuf[16];
   2660  1.1  hsuenaga 
   2661  1.1  hsuenaga 	KASSERT(ivlen == 8 || ivlen == 16);
   2662  1.1  hsuenaga 
   2663  1.1  hsuenaga 	if (iv == NULL) {
   2664  1.1  hsuenaga 	       	if (mv_p->mv_s->sflags & RDY_CRP_IV) {
   2665  1.1  hsuenaga 			/* use per session IV (compatible with KAME IPsec) */
   2666  1.1  hsuenaga 			mv_p->pkt_header.crp_iv_work = mv_p->mv_s->session_iv;
   2667  1.1  hsuenaga 			mv_p->flags |= RDY_CRP_IV;
   2668  1.1  hsuenaga 			return 0;
   2669  1.1  hsuenaga 		}
   2670  1.1  hsuenaga 		cprng_fast(ivbuf, ivlen);
   2671  1.1  hsuenaga 		iv = ivbuf;
   2672  1.1  hsuenaga 	}
   2673  1.1  hsuenaga 	memcpy(&mv_p->pkt_header.crp_iv_work, iv, ivlen);
   2674  1.1  hsuenaga 	if (mv_p->flags & CRP_EXT_IV) {
   2675  1.1  hsuenaga 		memcpy(&mv_p->pkt_header.crp_iv_ext, iv, ivlen);
   2676  1.1  hsuenaga 		mv_p->ext_iv = iv;
   2677  1.1  hsuenaga 		mv_p->ext_ivlen = ivlen;
   2678  1.1  hsuenaga 	}
   2679  1.1  hsuenaga 	mv_p->flags |= RDY_CRP_IV;
   2680  1.1  hsuenaga 
   2681  1.1  hsuenaga 	return 0;
   2682  1.1  hsuenaga }
   2683  1.1  hsuenaga 
   2684  1.1  hsuenaga STATIC int
   2685  1.1  hsuenaga mvxpsec_packet_copy_iv(struct mvxpsec_packet *mv_p, int off, int ivlen)
   2686  1.1  hsuenaga {
   2687  1.1  hsuenaga 	mvxpsec_packet_rdata(mv_p, off, ivlen,
   2688  1.1  hsuenaga 	    &mv_p->pkt_header.crp_iv_work);
   2689  1.1  hsuenaga 	mv_p->flags |= RDY_CRP_IV;
   2690  1.1  hsuenaga 
   2691  1.1  hsuenaga 	return 0;
   2692  1.1  hsuenaga }
   2693  1.1  hsuenaga 
   2694  1.1  hsuenaga /*
   2695  1.1  hsuenaga  * set a encryption or decryption key to the session
   2696  1.1  hsuenaga  *
   2697  1.1  hsuenaga  * Input key material is big endian.
   2698  1.1  hsuenaga  */
   2699  1.1  hsuenaga STATIC int
   2700  1.1  hsuenaga mvxpsec_key_precomp(int alg, void *keymat, int kbitlen,
   2701  1.1  hsuenaga     void *key_encrypt, void *key_decrypt)
   2702  1.1  hsuenaga {
   2703  1.1  hsuenaga 	uint32_t *kp = keymat;
   2704  1.1  hsuenaga 	uint32_t *ekp = key_encrypt;
   2705  1.1  hsuenaga 	uint32_t *dkp = key_decrypt;
   2706  1.1  hsuenaga 	int i;
   2707  1.1  hsuenaga 
   2708  1.1  hsuenaga 	switch (alg) {
   2709  1.1  hsuenaga 	case CRYPTO_DES_CBC:
   2710  1.1  hsuenaga 		if (kbitlen < 64 || (kbitlen % 8) != 0) {
   2711  1.1  hsuenaga 			log(LOG_WARNING,
   2712  1.1  hsuenaga 			    "mvxpsec: invalid DES keylen %d\n", kbitlen);
   2713  1.1  hsuenaga 			return EINVAL;
   2714  1.1  hsuenaga 		}
   2715  1.1  hsuenaga 		for (i = 0; i < 2; i++)
   2716  1.1  hsuenaga 			dkp[i] = ekp[i] = kp[i];
   2717  1.1  hsuenaga 		for (; i < 8; i++)
   2718  1.1  hsuenaga 			dkp[i] = ekp[i] = 0;
   2719  1.1  hsuenaga 		break;
   2720  1.1  hsuenaga 	case CRYPTO_3DES_CBC:
   2721  1.1  hsuenaga 		if (kbitlen < 192 || (kbitlen % 8) != 0) {
   2722  1.1  hsuenaga 			log(LOG_WARNING,
   2723  1.1  hsuenaga 			    "mvxpsec: invalid 3DES keylen %d\n", kbitlen);
   2724  1.1  hsuenaga 			return EINVAL;
   2725  1.1  hsuenaga 		}
   2726  1.1  hsuenaga 		for (i = 0; i < 8; i++)
   2727  1.1  hsuenaga 			dkp[i] = ekp[i] = kp[i];
   2728  1.1  hsuenaga 		break;
   2729  1.1  hsuenaga 	case CRYPTO_AES_CBC:
   2730  1.1  hsuenaga 		if (kbitlen < 128) {
   2731  1.1  hsuenaga 			log(LOG_WARNING,
   2732  1.1  hsuenaga 			    "mvxpsec: invalid AES keylen %d\n", kbitlen);
   2733  1.1  hsuenaga 			return EINVAL;
   2734  1.1  hsuenaga 		}
   2735  1.1  hsuenaga 		else if (kbitlen < 192) {
   2736  1.1  hsuenaga 			/* AES-128 */
   2737  1.1  hsuenaga 			for (i = 0; i < 4; i++)
   2738  1.1  hsuenaga 				ekp[i] = kp[i];
   2739  1.1  hsuenaga 			for (; i < 8; i++)
   2740  1.1  hsuenaga 				ekp[i] = 0;
   2741  1.1  hsuenaga 		}
   2742  1.1  hsuenaga 	       	else if (kbitlen < 256) {
   2743  1.1  hsuenaga 			/* AES-192 */
   2744  1.1  hsuenaga 			for (i = 0; i < 6; i++)
   2745  1.1  hsuenaga 				ekp[i] = kp[i];
   2746  1.1  hsuenaga 			for (; i < 8; i++)
   2747  1.1  hsuenaga 				ekp[i] = 0;
   2748  1.1  hsuenaga 		}
   2749  1.1  hsuenaga 		else  {
   2750  1.1  hsuenaga 			/* AES-256 */
   2751  1.1  hsuenaga 			for (i = 0; i < 8; i++)
   2752  1.1  hsuenaga 				ekp[i] = kp[i];
   2753  1.1  hsuenaga 		}
   2754  1.1  hsuenaga 		/* make decryption key */
   2755  1.1  hsuenaga 		mv_aes_deckey((uint8_t *)dkp, (uint8_t *)ekp, kbitlen);
   2756  1.1  hsuenaga 		break;
   2757  1.1  hsuenaga 	default:
   2758  1.1  hsuenaga 		for (i = 0; i < 8; i++)
   2759  1.1  hsuenaga 			ekp[0] = dkp[0] = 0;
   2760  1.1  hsuenaga 		break;
   2761  1.1  hsuenaga 	}
   2762  1.1  hsuenaga 
   2763  1.1  hsuenaga #ifdef MVXPSEC_DEBUG
   2764  1.1  hsuenaga 	if (mvxpsec_debug & MVXPSEC_DEBUG_OPENCRYPTO) {
   2765  1.1  hsuenaga 		MVXPSEC_PRINTF(MVXPSEC_DEBUG_OPENCRYPTO,
   2766  1.1  hsuenaga 		    "%s: keyregistered\n", __func__);
   2767  1.1  hsuenaga 		mvxpsec_dump_data(__func__, ekp, 32);
   2768  1.1  hsuenaga 	}
   2769  1.1  hsuenaga #endif
   2770  1.1  hsuenaga 
   2771  1.1  hsuenaga 	return 0;
   2772  1.1  hsuenaga }
   2773  1.1  hsuenaga 
   2774  1.1  hsuenaga /*
   2775  1.1  hsuenaga  * set MAC key to the session
   2776  1.1  hsuenaga  *
   2777  1.1  hsuenaga  * MAC engine has no register for key itself, but the engine has
   2778  1.1  hsuenaga  * inner and outer IV register. software must compute IV before
   2779  1.1  hsuenaga  * enable the engine.
   2780  1.1  hsuenaga  *
   2781  1.1  hsuenaga  * IV is a hash of ipad/opad. these are defined by FIPS-198a
   2782  1.1  hsuenaga  * standard.
   2783  1.1  hsuenaga  */
   2784  1.1  hsuenaga STATIC int
   2785  1.1  hsuenaga mvxpsec_hmac_precomp(int alg, void *key, int kbitlen,
   2786  1.1  hsuenaga     void *iv_inner, void *iv_outer)
   2787  1.1  hsuenaga {
   2788  1.1  hsuenaga 	SHA1_CTX sha1;
   2789  1.1  hsuenaga 	MD5_CTX md5;
   2790  1.1  hsuenaga 	uint8_t *key8 = key;
   2791  1.1  hsuenaga 	uint8_t kbuf[64];
   2792  1.1  hsuenaga 	uint8_t ipad[64];
   2793  1.1  hsuenaga 	uint8_t opad[64];
   2794  1.1  hsuenaga 	uint32_t *iv_in = iv_inner;
   2795  1.1  hsuenaga 	uint32_t *iv_out = iv_outer;
   2796  1.1  hsuenaga 	int kbytelen;
   2797  1.1  hsuenaga 	int i;
   2798  1.1  hsuenaga #define HMAC_IPAD 0x36
   2799  1.1  hsuenaga #define HMAC_OPAD 0x5c
   2800  1.1  hsuenaga 
   2801  1.1  hsuenaga 	kbytelen = kbitlen / 8;
   2802  1.1  hsuenaga 	KASSERT(kbitlen == kbytelen * 8);
   2803  1.1  hsuenaga 	if (kbytelen > 64) {
   2804  1.1  hsuenaga 		SHA1Init(&sha1);
   2805  1.1  hsuenaga 		SHA1Update(&sha1, key, kbytelen);
   2806  1.1  hsuenaga 		SHA1Final(kbuf, &sha1);
   2807  1.1  hsuenaga 		key8 = kbuf;
   2808  1.1  hsuenaga 		kbytelen = 64;
   2809  1.1  hsuenaga 	}
   2810  1.1  hsuenaga 
   2811  1.1  hsuenaga 	/* make initial 64 oct. string */
   2812  1.1  hsuenaga 	switch (alg) {
   2813  1.1  hsuenaga 	case CRYPTO_SHA1_HMAC_96:
   2814  1.1  hsuenaga 	case CRYPTO_SHA1_HMAC:
   2815  1.1  hsuenaga 	case CRYPTO_MD5_HMAC_96:
   2816  1.1  hsuenaga 	case CRYPTO_MD5_HMAC:
   2817  1.1  hsuenaga 		for (i = 0; i < kbytelen; i++) {
   2818  1.1  hsuenaga 			ipad[i] = (key8[i] ^ HMAC_IPAD);
   2819  1.1  hsuenaga 			opad[i] = (key8[i] ^ HMAC_OPAD);
   2820  1.1  hsuenaga 		}
   2821  1.1  hsuenaga 		for (; i < 64; i++) {
   2822  1.1  hsuenaga 			ipad[i] = HMAC_IPAD;
   2823  1.1  hsuenaga 			opad[i] = HMAC_OPAD;
   2824  1.1  hsuenaga 		}
   2825  1.1  hsuenaga 		break;
   2826  1.1  hsuenaga 	default:
   2827  1.1  hsuenaga 		break;
   2828  1.1  hsuenaga 	}
   2829  1.1  hsuenaga #ifdef MVXPSEC_DEBUG
   2830  1.1  hsuenaga 	if (mvxpsec_debug & MVXPSEC_DEBUG_OPENCRYPTO) {
   2831  1.1  hsuenaga 		MVXPSEC_PRINTF(MVXPSEC_DEBUG_OPENCRYPTO,
   2832  1.1  hsuenaga 		    "%s: HMAC-KEY Pre-comp:\n", __func__);
   2833  1.1  hsuenaga 		mvxpsec_dump_data(__func__, key, 64);
   2834  1.1  hsuenaga 		MVXPSEC_PRINTF(MVXPSEC_DEBUG_OPENCRYPTO,
   2835  1.1  hsuenaga 		    "%s: ipad:\n", __func__);
   2836  1.1  hsuenaga 		mvxpsec_dump_data(__func__, ipad, sizeof(ipad));
   2837  1.1  hsuenaga 		MVXPSEC_PRINTF(MVXPSEC_DEBUG_OPENCRYPTO,
   2838  1.1  hsuenaga 		    "%s: opad:\n", __func__);
   2839  1.1  hsuenaga 		mvxpsec_dump_data(__func__, opad, sizeof(opad));
   2840  1.1  hsuenaga 	}
   2841  1.1  hsuenaga #endif
   2842  1.1  hsuenaga 
   2843  1.1  hsuenaga 	/* make iv from string */
   2844  1.1  hsuenaga 	switch (alg) {
   2845  1.1  hsuenaga 	case CRYPTO_SHA1_HMAC_96:
   2846  1.1  hsuenaga 	case CRYPTO_SHA1_HMAC:
   2847  1.1  hsuenaga 		MVXPSEC_PRINTF(MVXPSEC_DEBUG_OPENCRYPTO,
   2848  1.1  hsuenaga 		    "%s: Generate iv_in(SHA1)\n", __func__);
   2849  1.1  hsuenaga 		SHA1Init(&sha1);
   2850  1.1  hsuenaga 		SHA1Update(&sha1, ipad, 64);
   2851  1.1  hsuenaga 		/* XXX: private state... (LE) */
   2852  1.1  hsuenaga 		iv_in[0] = htobe32(sha1.state[0]);
   2853  1.1  hsuenaga 		iv_in[1] = htobe32(sha1.state[1]);
   2854  1.1  hsuenaga 		iv_in[2] = htobe32(sha1.state[2]);
   2855  1.1  hsuenaga 		iv_in[3] = htobe32(sha1.state[3]);
   2856  1.1  hsuenaga 		iv_in[4] = htobe32(sha1.state[4]);
   2857  1.1  hsuenaga 
   2858  1.1  hsuenaga 		MVXPSEC_PRINTF(MVXPSEC_DEBUG_OPENCRYPTO,
   2859  1.1  hsuenaga 		    "%s: Generate iv_out(SHA1)\n", __func__);
   2860  1.1  hsuenaga 		SHA1Init(&sha1);
   2861  1.1  hsuenaga 		SHA1Update(&sha1, opad, 64);
   2862  1.1  hsuenaga 		/* XXX: private state... (LE) */
   2863  1.1  hsuenaga 		iv_out[0] = htobe32(sha1.state[0]);
   2864  1.1  hsuenaga 		iv_out[1] = htobe32(sha1.state[1]);
   2865  1.1  hsuenaga 		iv_out[2] = htobe32(sha1.state[2]);
   2866  1.1  hsuenaga 		iv_out[3] = htobe32(sha1.state[3]);
   2867  1.1  hsuenaga 		iv_out[4] = htobe32(sha1.state[4]);
   2868  1.1  hsuenaga 		break;
   2869  1.1  hsuenaga 	case CRYPTO_MD5_HMAC_96:
   2870  1.1  hsuenaga 	case CRYPTO_MD5_HMAC:
   2871  1.1  hsuenaga 		MVXPSEC_PRINTF(MVXPSEC_DEBUG_OPENCRYPTO,
   2872  1.1  hsuenaga 		    "%s: Generate iv_in(MD5)\n", __func__);
   2873  1.1  hsuenaga 		MD5Init(&md5);
   2874  1.1  hsuenaga 		MD5Update(&md5, ipad, sizeof(ipad));
   2875  1.1  hsuenaga 		/* XXX: private state... (LE) */
   2876  1.1  hsuenaga 		iv_in[0] = htobe32(md5.state[0]);
   2877  1.1  hsuenaga 		iv_in[1] = htobe32(md5.state[1]);
   2878  1.1  hsuenaga 		iv_in[2] = htobe32(md5.state[2]);
   2879  1.1  hsuenaga 		iv_in[3] = htobe32(md5.state[3]);
   2880  1.1  hsuenaga 		iv_in[4] = 0;
   2881  1.1  hsuenaga 
   2882  1.1  hsuenaga 		MVXPSEC_PRINTF(MVXPSEC_DEBUG_OPENCRYPTO,
   2883  1.1  hsuenaga 		    "%s: Generate iv_out(MD5)\n", __func__);
   2884  1.1  hsuenaga 		MD5Init(&md5);
   2885  1.1  hsuenaga 		MD5Update(&md5, opad, sizeof(opad));
   2886  1.1  hsuenaga 		/* XXX: private state... (LE) */
   2887  1.1  hsuenaga 		iv_out[0] = htobe32(md5.state[0]);
   2888  1.1  hsuenaga 		iv_out[1] = htobe32(md5.state[1]);
   2889  1.1  hsuenaga 		iv_out[2] = htobe32(md5.state[2]);
   2890  1.1  hsuenaga 		iv_out[3] = htobe32(md5.state[3]);
   2891  1.1  hsuenaga 		iv_out[4] = 0;
   2892  1.1  hsuenaga 		break;
   2893  1.1  hsuenaga 	default:
   2894  1.1  hsuenaga 		break;
   2895  1.1  hsuenaga 	}
   2896  1.1  hsuenaga 
   2897  1.1  hsuenaga #ifdef MVXPSEC_DEBUG
   2898  1.1  hsuenaga 	if (mvxpsec_debug & MVXPSEC_DEBUG_HASH_IV) {
   2899  1.1  hsuenaga 		MVXPSEC_PRINTF(MVXPSEC_DEBUG_HASH_IV,
   2900  1.1  hsuenaga 		    "%s: HMAC IV-IN\n", __func__);
   2901  1.1  hsuenaga 		mvxpsec_dump_data(__func__, (uint8_t *)iv_in, 20);
   2902  1.1  hsuenaga 		MVXPSEC_PRINTF(MVXPSEC_DEBUG_HASH_IV,
   2903  1.1  hsuenaga 		    "%s: HMAC IV-OUT\n", __func__);
   2904  1.1  hsuenaga 		mvxpsec_dump_data(__func__, (uint8_t *)iv_out, 20);
   2905  1.1  hsuenaga 	}
   2906  1.1  hsuenaga #endif
   2907  1.1  hsuenaga 
   2908  1.1  hsuenaga 	return 0;
   2909  1.1  hsuenaga #undef HMAC_IPAD
   2910  1.1  hsuenaga #undef HMAC_OPAD
   2911  1.1  hsuenaga }
   2912  1.1  hsuenaga 
   2913  1.1  hsuenaga /*
   2914  1.1  hsuenaga  * AES Support routine
   2915  1.1  hsuenaga  */
   2916  1.1  hsuenaga static uint8_t AES_SBOX[256] = {
   2917  1.1  hsuenaga 	 99, 124, 119, 123, 242, 107, 111, 197,  48,   1, 103,  43, 254, 215,
   2918  1.1  hsuenaga        	171, 118, 202, 130, 201, 125, 250,  89,  71, 240, 173, 212, 162, 175,
   2919  1.1  hsuenaga        	156, 164, 114, 192, 183, 253, 147,  38,  54,  63, 247, 204,  52, 165,
   2920  1.1  hsuenaga        	229, 241, 113, 216,  49,  21,   4, 199,  35, 195,  24, 150,   5, 154,
   2921  1.1  hsuenaga        	  7,  18, 128, 226, 235,  39, 178, 117,   9, 131,  44,  26,  27, 110,
   2922  1.1  hsuenaga 	 90, 160,  82,  59, 214, 179,  41, 227,  47, 132,  83, 209,   0, 237,
   2923  1.1  hsuenaga        	 32, 252, 177,  91, 106, 203, 190,  57,  74,  76,  88, 207, 208, 239,
   2924  1.1  hsuenaga 	170, 251,  67,  77,  51, 133,  69, 249,   2, 127,  80,  60, 159, 168,
   2925  1.1  hsuenaga 	 81, 163,  64, 143, 146, 157,  56, 245, 188, 182, 218,  33,  16, 255,
   2926  1.1  hsuenaga 	243, 210, 205,  12,  19, 236,  95, 151,  68,  23, 196, 167, 126,  61,
   2927  1.1  hsuenaga        	100,  93,  25, 115,  96, 129,  79, 220,  34,  42, 144, 136,  70, 238,
   2928  1.1  hsuenaga        	184,  20, 222,  94,  11, 219, 224,  50,  58,  10,  73,   6,  36,  92,
   2929  1.1  hsuenaga        	194, 211, 172,  98, 145, 149, 228, 121, 231, 200,  55, 109, 141, 213,
   2930  1.1  hsuenaga       	 78, 169, 108,  86, 244, 234, 101, 122, 174,   8, 186, 120,  37,  46,
   2931  1.1  hsuenaga        	 28, 166, 180, 198, 232, 221, 116,  31,  75, 189, 139, 138, 112,  62,
   2932  1.1  hsuenaga 	181, 102,  72,   3, 246,  14,  97,  53,  87, 185, 134, 193,  29, 158,
   2933  1.1  hsuenaga        	225, 248, 152,  17, 105, 217, 142, 148, 155,  30, 135, 233, 206,  85,
   2934  1.1  hsuenaga       	 40, 223, 140, 161, 137,  13, 191, 230,  66, 104,  65, 153,  45,  15,
   2935  1.1  hsuenaga 	176,  84, 187,  22
   2936  1.1  hsuenaga };
   2937  1.1  hsuenaga 
   2938  1.1  hsuenaga static uint32_t AES_RCON[30] = {
   2939  1.1  hsuenaga 	0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x1b, 0x36, 0x6c, 0xd8,
   2940  1.1  hsuenaga        	0xab, 0x4d, 0x9a, 0x2f, 0x5e, 0xbc, 0x63, 0xc6, 0x97, 0x35, 0x6a, 0xd4,
   2941  1.1  hsuenaga        	0xb3, 0x7d, 0xfa, 0xef, 0xc5, 0x91
   2942  1.1  hsuenaga };
   2943  1.1  hsuenaga 
   2944  1.1  hsuenaga STATIC int
   2945  1.1  hsuenaga mv_aes_ksched(uint8_t k[4][MAXKC], int keyBits,
   2946  1.1  hsuenaga     uint8_t W[MAXROUNDS+1][4][MAXBC])
   2947  1.1  hsuenaga {
   2948  1.1  hsuenaga 	int KC, BC, ROUNDS;
   2949  1.1  hsuenaga 	int i, j, t, rconpointer = 0;
   2950  1.1  hsuenaga 	uint8_t tk[4][MAXKC];
   2951  1.1  hsuenaga 
   2952  1.1  hsuenaga 	switch (keyBits) {
   2953  1.1  hsuenaga 	case 128:
   2954  1.1  hsuenaga 		ROUNDS = 10;
   2955  1.1  hsuenaga 		KC = 4;
   2956  1.1  hsuenaga 		break;
   2957  1.1  hsuenaga 	case 192:
   2958  1.1  hsuenaga 		ROUNDS = 12;
   2959  1.1  hsuenaga 		KC = 6;
   2960  1.1  hsuenaga 	       	break;
   2961  1.1  hsuenaga 	case 256:
   2962  1.1  hsuenaga 		ROUNDS = 14;
   2963  1.1  hsuenaga 	       	KC = 8;
   2964  1.1  hsuenaga 	       	break;
   2965  1.1  hsuenaga 	default:
   2966  1.1  hsuenaga 	       	return (-1);
   2967  1.1  hsuenaga 	}
   2968  1.1  hsuenaga 	BC = 4; /* 128 bits */
   2969  1.1  hsuenaga 
   2970  1.1  hsuenaga 	for(j = 0; j < KC; j++)
   2971  1.1  hsuenaga 		for(i = 0; i < 4; i++)
   2972  1.1  hsuenaga 			tk[i][j] = k[i][j];
   2973  1.1  hsuenaga 	t = 0;
   2974  1.1  hsuenaga 
   2975  1.1  hsuenaga 	/* copy values into round key array */
   2976  1.1  hsuenaga 	for(j = 0; (j < KC) && (t < (ROUNDS+1)*BC); j++, t++)
   2977  1.1  hsuenaga 		for(i = 0; i < 4; i++) W[t / BC][i][t % BC] = tk[i][j];
   2978  1.1  hsuenaga 
   2979  1.1  hsuenaga 	while (t < (ROUNDS+1)*BC) { /* while not enough round key material calculated */
   2980  1.1  hsuenaga 		/* calculate new values */
   2981  1.1  hsuenaga 		for(i = 0; i < 4; i++)
   2982  1.1  hsuenaga 			tk[i][0] ^= AES_SBOX[tk[(i+1)%4][KC-1]];
   2983  1.1  hsuenaga 		tk[0][0] ^= AES_RCON[rconpointer++];
   2984  1.1  hsuenaga 
   2985  1.1  hsuenaga 		if (KC != 8)
   2986  1.1  hsuenaga 			for(j = 1; j < KC; j++)
   2987  1.1  hsuenaga 				for(i = 0; i < 4; i++)
   2988  1.1  hsuenaga 				       	tk[i][j] ^= tk[i][j-1];
   2989  1.1  hsuenaga 		else {
   2990  1.1  hsuenaga 			for(j = 1; j < KC/2; j++)
   2991  1.1  hsuenaga 				for(i = 0; i < 4; i++)
   2992  1.1  hsuenaga 				       	tk[i][j] ^= tk[i][j-1];
   2993  1.1  hsuenaga 			for(i = 0; i < 4; i++)
   2994  1.1  hsuenaga 			       	tk[i][KC/2] ^= AES_SBOX[tk[i][KC/2 - 1]];
   2995  1.1  hsuenaga 			for(j = KC/2 + 1; j < KC; j++)
   2996  1.1  hsuenaga 				for(i = 0; i < 4; i++)
   2997  1.1  hsuenaga 				       	tk[i][j] ^= tk[i][j-1];
   2998  1.1  hsuenaga 	}
   2999  1.1  hsuenaga 	/* copy values into round key array */
   3000  1.1  hsuenaga 	for(j = 0; (j < KC) && (t < (ROUNDS+1)*BC); j++, t++)
   3001  1.1  hsuenaga 		for(i = 0; i < 4; i++) W[t / BC][i][t % BC] = tk[i][j];
   3002  1.1  hsuenaga 	}
   3003  1.1  hsuenaga 
   3004  1.1  hsuenaga 	return 0;
   3005  1.1  hsuenaga }
   3006  1.1  hsuenaga 
   3007  1.1  hsuenaga STATIC int
   3008  1.1  hsuenaga mv_aes_deckey(uint8_t *expandedKey, uint8_t *keyMaterial, int keyLen)
   3009  1.1  hsuenaga {
   3010  1.1  hsuenaga 	uint8_t   W[MAXROUNDS+1][4][MAXBC];
   3011  1.1  hsuenaga 	uint8_t   k[4][MAXKC];
   3012  1.1  hsuenaga 	uint8_t   j;
   3013  1.1  hsuenaga 	int     i, rounds, KC;
   3014  1.1  hsuenaga 
   3015  1.1  hsuenaga 	if (expandedKey == NULL)
   3016  1.1  hsuenaga 		return -1;
   3017  1.1  hsuenaga 
   3018  1.1  hsuenaga 	if (!((keyLen == 128) || (keyLen == 192) || (keyLen == 256)))
   3019  1.1  hsuenaga 		return -1;
   3020  1.1  hsuenaga 
   3021  1.1  hsuenaga 	if (keyMaterial == NULL)
   3022  1.1  hsuenaga 		return -1;
   3023  1.1  hsuenaga 
   3024  1.1  hsuenaga 	/* initialize key schedule: */
   3025  1.1  hsuenaga 	for (i=0; i<keyLen/8; i++) {
   3026  1.1  hsuenaga 		j = keyMaterial[i];
   3027  1.1  hsuenaga 		k[i % 4][i / 4] = j;
   3028  1.1  hsuenaga 	}
   3029  1.1  hsuenaga 
   3030  1.1  hsuenaga 	mv_aes_ksched(k, keyLen, W);
   3031  1.1  hsuenaga 	switch (keyLen) {
   3032  1.1  hsuenaga 	case 128:
   3033  1.1  hsuenaga 		rounds = 10;
   3034  1.1  hsuenaga 		KC = 4;
   3035  1.1  hsuenaga 		break;
   3036  1.1  hsuenaga 	case 192:
   3037  1.1  hsuenaga 		rounds = 12;
   3038  1.1  hsuenaga 		KC = 6;
   3039  1.1  hsuenaga 		break;
   3040  1.1  hsuenaga 	case 256:
   3041  1.1  hsuenaga 		rounds = 14;
   3042  1.1  hsuenaga 		KC = 8;
   3043  1.1  hsuenaga 		break;
   3044  1.1  hsuenaga 	default:
   3045  1.1  hsuenaga 		return -1;
   3046  1.1  hsuenaga 	}
   3047  1.1  hsuenaga 
   3048  1.1  hsuenaga 	for(i=0; i<MAXBC; i++)
   3049  1.1  hsuenaga 		for(j=0; j<4; j++)
   3050  1.1  hsuenaga 			expandedKey[i*4+j] = W[rounds][j][i];
   3051  1.1  hsuenaga 	for(; i<KC; i++)
   3052  1.1  hsuenaga 		for(j=0; j<4; j++)
   3053  1.1  hsuenaga 			expandedKey[i*4+j] = W[rounds-1][j][i+MAXBC-KC];
   3054  1.1  hsuenaga 
   3055  1.1  hsuenaga 	return 0;
   3056  1.1  hsuenaga }
   3057  1.1  hsuenaga 
   3058  1.1  hsuenaga /*
   3059  1.1  hsuenaga  * Clear cipher/mac operation state
   3060  1.1  hsuenaga  */
   3061  1.1  hsuenaga INLINE void
   3062  1.1  hsuenaga mvxpsec_packet_reset_op(struct mvxpsec_packet *mv_p)
   3063  1.1  hsuenaga {
   3064  1.1  hsuenaga 	mv_p->pkt_header.desc.acc_config = 0;
   3065  1.1  hsuenaga 	mv_p->enc_off = mv_p->enc_ivoff = mv_p->enc_len = 0;
   3066  1.1  hsuenaga 	mv_p->mac_off = mv_p->mac_dst = mv_p->mac_len = 0;
   3067  1.1  hsuenaga }
   3068  1.1  hsuenaga 
   3069  1.1  hsuenaga /*
   3070  1.1  hsuenaga  * update MVXPSEC operation order
   3071  1.1  hsuenaga  */
   3072  1.1  hsuenaga INLINE void
   3073  1.1  hsuenaga mvxpsec_packet_update_op_order(struct mvxpsec_packet *mv_p, int op)
   3074  1.1  hsuenaga {
   3075  1.1  hsuenaga 	struct mvxpsec_acc_descriptor *acc_desc = &mv_p->pkt_header.desc;
   3076  1.1  hsuenaga 	uint32_t cur_op = acc_desc->acc_config & MV_ACC_CRYPTO_OP_MASK;
   3077  1.1  hsuenaga 
   3078  1.1  hsuenaga 	KASSERT(op == MV_ACC_CRYPTO_OP_MAC || op == MV_ACC_CRYPTO_OP_ENC);
   3079  1.1  hsuenaga 	KASSERT((op & MV_ACC_CRYPTO_OP_MASK) == op);
   3080  1.1  hsuenaga 
   3081  1.1  hsuenaga 	if (cur_op == 0)
   3082  1.1  hsuenaga 		acc_desc->acc_config |= op;
   3083  1.1  hsuenaga 	else if (cur_op == MV_ACC_CRYPTO_OP_MAC && op == MV_ACC_CRYPTO_OP_ENC) {
   3084  1.1  hsuenaga 		acc_desc->acc_config &= ~MV_ACC_CRYPTO_OP_MASK;
   3085  1.1  hsuenaga 		acc_desc->acc_config |= MV_ACC_CRYPTO_OP_MACENC;
   3086  1.1  hsuenaga 		/* MAC then ENC (= decryption) */
   3087  1.1  hsuenaga 	}
   3088  1.1  hsuenaga 	else if (cur_op == MV_ACC_CRYPTO_OP_ENC && op == MV_ACC_CRYPTO_OP_MAC) {
   3089  1.1  hsuenaga 		acc_desc->acc_config &= ~MV_ACC_CRYPTO_OP_MASK;
   3090  1.1  hsuenaga 		acc_desc->acc_config |= MV_ACC_CRYPTO_OP_ENCMAC;
   3091  1.1  hsuenaga 		/* ENC then MAC (= encryption) */
   3092  1.1  hsuenaga 	}
   3093  1.1  hsuenaga 	else {
   3094  1.1  hsuenaga 		log(LOG_ERR, "%s: multiple %s algorithm is not supported.\n",
   3095  1.1  hsuenaga 		    __func__,
   3096  1.1  hsuenaga 		    (op == MV_ACC_CRYPTO_OP_ENC) ?  "encryption" : "authentication");
   3097  1.1  hsuenaga 	}
   3098  1.1  hsuenaga }
   3099  1.1  hsuenaga 
   3100  1.1  hsuenaga /*
   3101  1.1  hsuenaga  * Parameter Conversions
   3102  1.1  hsuenaga  */
   3103  1.1  hsuenaga INLINE uint32_t
   3104  1.1  hsuenaga mvxpsec_alg2acc(uint32_t alg)
   3105  1.1  hsuenaga {
   3106  1.1  hsuenaga 	uint32_t reg;
   3107  1.1  hsuenaga 
   3108  1.1  hsuenaga 	switch (alg) {
   3109  1.1  hsuenaga 	case CRYPTO_DES_CBC:
   3110  1.1  hsuenaga 		reg = MV_ACC_CRYPTO_ENC_DES;
   3111  1.1  hsuenaga 		reg |= MV_ACC_CRYPTO_CBC;
   3112  1.1  hsuenaga 		break;
   3113  1.1  hsuenaga 	case CRYPTO_3DES_CBC:
   3114  1.1  hsuenaga 		reg = MV_ACC_CRYPTO_ENC_3DES;
   3115  1.1  hsuenaga 		reg |= MV_ACC_CRYPTO_3DES_EDE;
   3116  1.1  hsuenaga 		reg |= MV_ACC_CRYPTO_CBC;
   3117  1.1  hsuenaga 		break;
   3118  1.1  hsuenaga 	case CRYPTO_AES_CBC:
   3119  1.1  hsuenaga 		reg = MV_ACC_CRYPTO_ENC_AES;
   3120  1.1  hsuenaga 		reg |= MV_ACC_CRYPTO_CBC;
   3121  1.1  hsuenaga 		break;
   3122  1.1  hsuenaga 	case CRYPTO_SHA1_HMAC_96:
   3123  1.1  hsuenaga 		reg = MV_ACC_CRYPTO_MAC_HMAC_SHA1;
   3124  1.1  hsuenaga 		reg |= MV_ACC_CRYPTO_MAC_96;
   3125  1.1  hsuenaga 		break;
   3126  1.1  hsuenaga 	case CRYPTO_MD5_HMAC_96:
   3127  1.1  hsuenaga 		reg = MV_ACC_CRYPTO_MAC_HMAC_MD5;
   3128  1.1  hsuenaga 		reg |= MV_ACC_CRYPTO_MAC_96;
   3129  1.1  hsuenaga 		break;
   3130  1.1  hsuenaga 	default:
   3131  1.1  hsuenaga 		reg = 0;
   3132  1.1  hsuenaga 		break;
   3133  1.1  hsuenaga 	}
   3134  1.1  hsuenaga 
   3135  1.1  hsuenaga 	return reg;
   3136  1.1  hsuenaga }
   3137  1.1  hsuenaga 
   3138  1.1  hsuenaga INLINE uint32_t
   3139  1.1  hsuenaga mvxpsec_aesklen(int klen)
   3140  1.1  hsuenaga {
   3141  1.1  hsuenaga 	if (klen < 128)
   3142  1.1  hsuenaga 		return 0;
   3143  1.1  hsuenaga 	else if (klen < 192)
   3144  1.1  hsuenaga 		return MV_ACC_CRYPTO_AES_KLEN_128;
   3145  1.1  hsuenaga 	else if (klen < 256)
   3146  1.1  hsuenaga 		return MV_ACC_CRYPTO_AES_KLEN_192;
   3147  1.1  hsuenaga 	else
   3148  1.1  hsuenaga 		return MV_ACC_CRYPTO_AES_KLEN_256;
   3149  1.1  hsuenaga 
   3150  1.1  hsuenaga 	return 0;
   3151  1.1  hsuenaga }
   3152  1.1  hsuenaga 
   3153  1.1  hsuenaga /*
   3154  1.1  hsuenaga  * String Conversions
   3155  1.1  hsuenaga  */
   3156  1.1  hsuenaga STATIC const char *
   3157  1.1  hsuenaga s_errreg(uint32_t v)
   3158  1.1  hsuenaga {
   3159  1.1  hsuenaga 	static char buf[80];
   3160  1.1  hsuenaga 
   3161  1.1  hsuenaga 	snprintf(buf, sizeof(buf),
   3162  1.1  hsuenaga 	    "%sMiss %sDoubleHit %sBothHit %sDataError",
   3163  1.1  hsuenaga 	    (v & MV_TDMA_ERRC_MISS) ? "+" : "-",
   3164  1.1  hsuenaga 	    (v & MV_TDMA_ERRC_DHIT) ? "+" : "-",
   3165  1.1  hsuenaga 	    (v & MV_TDMA_ERRC_BHIT) ? "+" : "-",
   3166  1.1  hsuenaga 	    (v & MV_TDMA_ERRC_DERR) ? "+" : "-");
   3167  1.1  hsuenaga 
   3168  1.1  hsuenaga 	return (const char *)buf;
   3169  1.1  hsuenaga }
   3170  1.1  hsuenaga 
   3171  1.1  hsuenaga STATIC const char *
   3172  1.1  hsuenaga s_winreg(uint32_t v)
   3173  1.1  hsuenaga {
   3174  1.1  hsuenaga 	static char buf[80];
   3175  1.1  hsuenaga 
   3176  1.1  hsuenaga 	snprintf(buf, sizeof(buf),
   3177  1.1  hsuenaga 	    "%s TGT 0x%x ATTR 0x%02x size %u(0x%04x)[64KB]",
   3178  1.1  hsuenaga 	    (v & MV_TDMA_ATTR_ENABLE) ? "EN" : "DIS",
   3179  1.1  hsuenaga 	    MV_TDMA_ATTR_GET_TARGET(v), MV_TDMA_ATTR_GET_ATTR(v),
   3180  1.1  hsuenaga 	    MV_TDMA_ATTR_GET_SIZE(v), MV_TDMA_ATTR_GET_SIZE(v));
   3181  1.1  hsuenaga 
   3182  1.1  hsuenaga 	return (const char *)buf;
   3183  1.1  hsuenaga }
   3184  1.1  hsuenaga 
   3185  1.1  hsuenaga STATIC const char *
   3186  1.1  hsuenaga s_ctrlreg(uint32_t reg)
   3187  1.1  hsuenaga {
   3188  1.1  hsuenaga 	static char buf[80];
   3189  1.1  hsuenaga 
   3190  1.1  hsuenaga 	snprintf(buf, sizeof(buf),
   3191  1.1  hsuenaga 	    "%s: %sFETCH DBURST-%u SBURST-%u %sOUTS %sCHAIN %sBSWAP %sACT",
   3192  1.1  hsuenaga 	    (reg & MV_TDMA_CONTROL_ENABLE) ? "ENABLE" : "DISABLE",
   3193  1.1  hsuenaga 	    (reg & MV_TDMA_CONTROL_FETCH) ? "+" : "-",
   3194  1.1  hsuenaga 	    MV_TDMA_CONTROL_GET_DST_BURST(reg),
   3195  1.1  hsuenaga 	    MV_TDMA_CONTROL_GET_SRC_BURST(reg),
   3196  1.1  hsuenaga 	    (reg & MV_TDMA_CONTROL_OUTS_EN) ? "+" : "-",
   3197  1.1  hsuenaga 	    (reg & MV_TDMA_CONTROL_CHAIN_DIS) ? "-" : "+",
   3198  1.1  hsuenaga 	    (reg & MV_TDMA_CONTROL_BSWAP_DIS) ? "-" : "+",
   3199  1.1  hsuenaga 	    (reg & MV_TDMA_CONTROL_ACT) ? "+" : "-");
   3200  1.1  hsuenaga 
   3201  1.1  hsuenaga 	return (const char *)buf;
   3202  1.1  hsuenaga }
   3203  1.1  hsuenaga 
   3204  1.1  hsuenaga _STATIC const char *
   3205  1.1  hsuenaga s_xpsecintr(uint32_t v)
   3206  1.1  hsuenaga {
   3207  1.1  hsuenaga 	static char buf[160];
   3208  1.1  hsuenaga 
   3209  1.1  hsuenaga 	snprintf(buf, sizeof(buf),
   3210  1.1  hsuenaga 	    "%sAuth %sDES %sAES-ENC %sAES-DEC %sENC %sSA %sAccAndTDMA "
   3211  1.1  hsuenaga 	    "%sTDMAComp %sTDMAOwn %sAccAndTDMA_Cont",
   3212  1.1  hsuenaga 	    (v & MVXPSEC_INT_AUTH) ? "+" : "-",
   3213  1.1  hsuenaga 	    (v & MVXPSEC_INT_DES) ? "+" : "-",
   3214  1.1  hsuenaga 	    (v & MVXPSEC_INT_AES_ENC) ? "+" : "-",
   3215  1.1  hsuenaga 	    (v & MVXPSEC_INT_AES_DEC) ? "+" : "-",
   3216  1.1  hsuenaga 	    (v & MVXPSEC_INT_ENC) ? "+" : "-",
   3217  1.1  hsuenaga 	    (v & MVXPSEC_INT_SA) ? "+" : "-",
   3218  1.1  hsuenaga 	    (v & MVXPSEC_INT_ACCTDMA) ? "+" : "-",
   3219  1.1  hsuenaga 	    (v & MVXPSEC_INT_TDMA_COMP) ? "+" : "-",
   3220  1.1  hsuenaga 	    (v & MVXPSEC_INT_TDMA_OWN) ? "+" : "-",
   3221  1.1  hsuenaga 	    (v & MVXPSEC_INT_ACCTDMA_CONT) ? "+" : "-");
   3222  1.1  hsuenaga 
   3223  1.1  hsuenaga 	return (const char *)buf;
   3224  1.1  hsuenaga }
   3225  1.1  hsuenaga 
   3226  1.1  hsuenaga STATIC const char *
   3227  1.1  hsuenaga s_ctlalg(uint32_t alg)
   3228  1.1  hsuenaga {
   3229  1.1  hsuenaga 	switch (alg) {
   3230  1.1  hsuenaga 	case CRYPTO_SHA1_HMAC_96:
   3231  1.1  hsuenaga 		return "HMAC-SHA1-96";
   3232  1.1  hsuenaga 	case CRYPTO_SHA1_HMAC:
   3233  1.1  hsuenaga 		return "HMAC-SHA1";
   3234  1.1  hsuenaga 	case CRYPTO_SHA1:
   3235  1.1  hsuenaga 		return "SHA1";
   3236  1.1  hsuenaga 	case CRYPTO_MD5_HMAC_96:
   3237  1.1  hsuenaga 		return "HMAC-MD5-96";
   3238  1.1  hsuenaga 	case CRYPTO_MD5_HMAC:
   3239  1.1  hsuenaga 		return "HMAC-MD5";
   3240  1.1  hsuenaga 	case CRYPTO_MD5:
   3241  1.1  hsuenaga 		return "MD5";
   3242  1.1  hsuenaga 	case CRYPTO_DES_CBC:
   3243  1.1  hsuenaga 		return "DES-CBC";
   3244  1.1  hsuenaga 	case CRYPTO_3DES_CBC:
   3245  1.1  hsuenaga 		return "3DES-CBC";
   3246  1.1  hsuenaga 	case CRYPTO_AES_CBC:
   3247  1.1  hsuenaga 		return "AES-CBC";
   3248  1.1  hsuenaga 	default:
   3249  1.1  hsuenaga 		break;
   3250  1.1  hsuenaga 	}
   3251  1.1  hsuenaga 
   3252  1.1  hsuenaga 	return "Unknown";
   3253  1.1  hsuenaga }
   3254  1.1  hsuenaga 
   3255  1.1  hsuenaga STATIC const char *
   3256  1.1  hsuenaga s_xpsec_op(uint32_t reg)
   3257  1.1  hsuenaga {
   3258  1.1  hsuenaga 	reg &= MV_ACC_CRYPTO_OP_MASK;
   3259  1.1  hsuenaga 	switch (reg) {
   3260  1.1  hsuenaga 	case MV_ACC_CRYPTO_OP_ENC:
   3261  1.1  hsuenaga 		return "ENC";
   3262  1.1  hsuenaga 	case MV_ACC_CRYPTO_OP_MAC:
   3263  1.1  hsuenaga 		return "MAC";
   3264  1.1  hsuenaga 	case MV_ACC_CRYPTO_OP_ENCMAC:
   3265  1.1  hsuenaga 		return "ENC-MAC";
   3266  1.1  hsuenaga 	case MV_ACC_CRYPTO_OP_MACENC:
   3267  1.1  hsuenaga 		return "MAC-ENC";
   3268  1.1  hsuenaga 	default:
   3269  1.1  hsuenaga 		break;
   3270  1.1  hsuenaga 	}
   3271  1.1  hsuenaga 
   3272  1.1  hsuenaga 	return "Unknown";
   3273  1.1  hsuenaga 
   3274  1.1  hsuenaga }
   3275  1.1  hsuenaga 
   3276  1.1  hsuenaga STATIC const char *
   3277  1.1  hsuenaga s_xpsec_enc(uint32_t alg)
   3278  1.1  hsuenaga {
   3279  1.1  hsuenaga 	alg <<= MV_ACC_CRYPTO_ENC_SHIFT;
   3280  1.1  hsuenaga 	switch (alg) {
   3281  1.1  hsuenaga 	case MV_ACC_CRYPTO_ENC_DES:
   3282  1.1  hsuenaga 		return "DES";
   3283  1.1  hsuenaga 	case MV_ACC_CRYPTO_ENC_3DES:
   3284  1.1  hsuenaga 		return "3DES";
   3285  1.1  hsuenaga 	case MV_ACC_CRYPTO_ENC_AES:
   3286  1.1  hsuenaga 		return "AES";
   3287  1.1  hsuenaga 	default:
   3288  1.1  hsuenaga 		break;
   3289  1.1  hsuenaga 	}
   3290  1.1  hsuenaga 
   3291  1.1  hsuenaga 	return "Unknown";
   3292  1.1  hsuenaga }
   3293  1.1  hsuenaga 
   3294  1.1  hsuenaga STATIC const char *
   3295  1.1  hsuenaga s_xpsec_mac(uint32_t alg)
   3296  1.1  hsuenaga {
   3297  1.1  hsuenaga 	alg <<= MV_ACC_CRYPTO_MAC_SHIFT;
   3298  1.1  hsuenaga 	switch (alg) {
   3299  1.1  hsuenaga 	case MV_ACC_CRYPTO_MAC_NONE:
   3300  1.1  hsuenaga 		return "Disabled";
   3301  1.1  hsuenaga 	case MV_ACC_CRYPTO_MAC_MD5:
   3302  1.1  hsuenaga 		return "MD5";
   3303  1.1  hsuenaga 	case MV_ACC_CRYPTO_MAC_SHA1:
   3304  1.1  hsuenaga 		return "SHA1";
   3305  1.1  hsuenaga 	case MV_ACC_CRYPTO_MAC_HMAC_MD5:
   3306  1.1  hsuenaga 		return "HMAC-MD5";
   3307  1.1  hsuenaga 	case MV_ACC_CRYPTO_MAC_HMAC_SHA1:
   3308  1.1  hsuenaga 		return "HMAC-SHA1";
   3309  1.1  hsuenaga 	default:
   3310  1.1  hsuenaga 		break;
   3311  1.1  hsuenaga 	}
   3312  1.1  hsuenaga 
   3313  1.1  hsuenaga 	return "Unknown";
   3314  1.1  hsuenaga }
   3315  1.1  hsuenaga 
   3316  1.1  hsuenaga STATIC const char *
   3317  1.1  hsuenaga s_xpsec_frag(uint32_t frag)
   3318  1.1  hsuenaga {
   3319  1.1  hsuenaga 	frag <<= MV_ACC_CRYPTO_FRAG_SHIFT;
   3320  1.1  hsuenaga 	switch (frag) {
   3321  1.1  hsuenaga 	case MV_ACC_CRYPTO_NOFRAG:
   3322  1.1  hsuenaga 		return "NoFragment";
   3323  1.1  hsuenaga 	case MV_ACC_CRYPTO_FRAG_FIRST:
   3324  1.1  hsuenaga 		return "FirstFragment";
   3325  1.1  hsuenaga 	case MV_ACC_CRYPTO_FRAG_MID:
   3326  1.1  hsuenaga 		return "MiddleFragment";
   3327  1.1  hsuenaga 	case MV_ACC_CRYPTO_FRAG_LAST:
   3328  1.1  hsuenaga 		return "LastFragment";
   3329  1.1  hsuenaga 	default:
   3330  1.1  hsuenaga 		break;
   3331  1.1  hsuenaga 	}
   3332  1.1  hsuenaga 
   3333  1.1  hsuenaga 	return "Unknown";
   3334  1.1  hsuenaga }
   3335  1.1  hsuenaga 
   3336  1.1  hsuenaga #ifdef MVXPSEC_DEBUG
   3337  1.1  hsuenaga void
   3338  1.1  hsuenaga mvxpsec_dump_reg(struct mvxpsec_softc *sc)
   3339  1.1  hsuenaga {
   3340  1.1  hsuenaga 	uint32_t reg;
   3341  1.1  hsuenaga 	int i;
   3342  1.1  hsuenaga 
   3343  1.1  hsuenaga 	if ((mvxpsec_debug & MVXPSEC_DEBUG_DESC) == 0)
   3344  1.1  hsuenaga 		return;
   3345  1.1  hsuenaga 
   3346  1.1  hsuenaga 	printf("--- Interrupt Registers ---\n");
   3347  1.1  hsuenaga 	reg = MVXPSEC_READ(sc, MVXPSEC_INT_CAUSE);
   3348  1.1  hsuenaga 	printf("MVXPSEC INT CAUSE: 0x%08x\n", reg);
   3349  1.1  hsuenaga 	printf("MVXPSEC INT CAUSE: %s\n", s_xpsecintr(reg));
   3350  1.1  hsuenaga 	reg = MVXPSEC_READ(sc, MVXPSEC_INT_MASK);
   3351  1.1  hsuenaga 	printf("MVXPSEC INT MASK: 0x%08x\n", reg);
   3352  1.1  hsuenaga 	printf("MVXPSEC INT MASKE: %s\n", s_xpsecintr(reg));
   3353  1.1  hsuenaga 
   3354  1.1  hsuenaga 	printf("--- DMA Configuration Registers ---\n");
   3355  1.1  hsuenaga 	for (i = 0; i < MV_TDMA_NWINDOW; i++) {
   3356  1.1  hsuenaga 		reg = MVXPSEC_READ(sc, MV_TDMA_BAR(i));
   3357  1.1  hsuenaga 		printf("TDMA BAR%d: 0x%08x\n", i, reg);
   3358  1.1  hsuenaga 		reg = MVXPSEC_READ(sc, MV_TDMA_ATTR(i));
   3359  1.1  hsuenaga 		printf("TDMA ATTR%d: 0x%08x\n", i, reg);
   3360  1.1  hsuenaga 		printf("  -> %s\n", s_winreg(reg));
   3361  1.1  hsuenaga 	}
   3362  1.1  hsuenaga 
   3363  1.1  hsuenaga 	printf("--- DMA Control Registers ---\n");
   3364  1.1  hsuenaga 
   3365  1.1  hsuenaga 	reg = MVXPSEC_READ(sc, MV_TDMA_CONTROL);
   3366  1.1  hsuenaga 	printf("TDMA CONTROL: 0x%08x\n", reg);
   3367  1.1  hsuenaga 	printf("  -> %s\n", s_ctrlreg(reg));
   3368  1.1  hsuenaga 
   3369  1.1  hsuenaga 	printf("--- DMA Current Command Descriptors ---\n");
   3370  1.1  hsuenaga 
   3371  1.1  hsuenaga 	reg = MVXPSEC_READ(sc, MV_TDMA_ERR_CAUSE);
   3372  1.1  hsuenaga 	printf("TDMA ERR CAUSE: 0x%08x\n", reg);
   3373  1.1  hsuenaga 
   3374  1.1  hsuenaga 	reg = MVXPSEC_READ(sc, MV_TDMA_ERR_MASK);
   3375  1.1  hsuenaga 	printf("TDMA ERR MASK: 0x%08x\n", reg);
   3376  1.1  hsuenaga 
   3377  1.1  hsuenaga 	reg = MVXPSEC_READ(sc, MV_TDMA_CNT);
   3378  1.1  hsuenaga 	printf("TDMA DATA OWNER: %s\n",
   3379  1.1  hsuenaga 	    (reg & MV_TDMA_CNT_OWN) ? "DMAC" : "CPU");
   3380  1.1  hsuenaga 	printf("TDMA DATA COUNT: %d(0x%x)\n",
   3381  1.1  hsuenaga 	    (reg & ~MV_TDMA_CNT_OWN), (reg & ~MV_TDMA_CNT_OWN));
   3382  1.1  hsuenaga 
   3383  1.1  hsuenaga 	reg = MVXPSEC_READ(sc, MV_TDMA_SRC);
   3384  1.1  hsuenaga 	printf("TDMA DATA SRC: 0x%08x\n", reg);
   3385  1.1  hsuenaga 
   3386  1.1  hsuenaga 	reg = MVXPSEC_READ(sc, MV_TDMA_DST);
   3387  1.1  hsuenaga 	printf("TDMA DATA DST: 0x%08x\n", reg);
   3388  1.1  hsuenaga 
   3389  1.1  hsuenaga 	reg = MVXPSEC_READ(sc, MV_TDMA_NXT);
   3390  1.1  hsuenaga 	printf("TDMA DATA NXT: 0x%08x\n", reg);
   3391  1.1  hsuenaga 
   3392  1.1  hsuenaga 	reg = MVXPSEC_READ(sc, MV_TDMA_CUR);
   3393  1.1  hsuenaga 	printf("TDMA DATA CUR: 0x%08x\n", reg);
   3394  1.1  hsuenaga 
   3395  1.1  hsuenaga 	printf("--- ACC Command Register ---\n");
   3396  1.1  hsuenaga 	reg = MVXPSEC_READ(sc, MV_ACC_COMMAND);
   3397  1.1  hsuenaga 	printf("ACC COMMAND: 0x%08x\n", reg);
   3398  1.1  hsuenaga 	printf("ACC: %sACT %sSTOP\n",
   3399  1.1  hsuenaga 	    (reg & MV_ACC_COMMAND_ACT) ? "+" : "-",
   3400  1.1  hsuenaga 	    (reg & MV_ACC_COMMAND_STOP) ? "+" : "-");
   3401  1.1  hsuenaga 
   3402  1.1  hsuenaga 	reg = MVXPSEC_READ(sc, MV_ACC_CONFIG);
   3403  1.1  hsuenaga 	printf("ACC CONFIG: 0x%08x\n", reg);
   3404  1.1  hsuenaga 	reg = MVXPSEC_READ(sc, MV_ACC_DESC);
   3405  1.1  hsuenaga 	printf("ACC DESC: 0x%08x\n", reg);
   3406  1.1  hsuenaga 
   3407  1.1  hsuenaga 	printf("--- DES Key Register ---\n");
   3408  1.1  hsuenaga 	reg = MVXPSEC_READ(sc, MV_CE_DES_KEY0L);
   3409  1.1  hsuenaga 	printf("DES KEY0  Low: 0x%08x\n", reg);
   3410  1.1  hsuenaga 	reg = MVXPSEC_READ(sc, MV_CE_DES_KEY0H);
   3411  1.1  hsuenaga 	printf("DES KEY0 High: 0x%08x\n", reg);
   3412  1.1  hsuenaga 	reg = MVXPSEC_READ(sc, MV_CE_DES_KEY1L);
   3413  1.1  hsuenaga 	printf("DES KEY1  Low: 0x%08x\n", reg);
   3414  1.1  hsuenaga 	reg = MVXPSEC_READ(sc, MV_CE_DES_KEY1H);
   3415  1.1  hsuenaga 	printf("DES KEY1 High: 0x%08x\n", reg);
   3416  1.1  hsuenaga 	reg = MVXPSEC_READ(sc, MV_CE_DES_KEY2L);
   3417  1.1  hsuenaga 	printf("DES KEY2  Low: 0x%08x\n", reg);
   3418  1.1  hsuenaga 	reg = MVXPSEC_READ(sc, MV_CE_DES_KEY2H);
   3419  1.1  hsuenaga 	printf("DES KEY2 High: 0x%08x\n", reg);
   3420  1.1  hsuenaga 
   3421  1.1  hsuenaga 	printf("--- AES Key Register ---\n");
   3422  1.1  hsuenaga 	for (i = 0; i < 8; i++) {
   3423  1.1  hsuenaga 		reg = MVXPSEC_READ(sc, MV_CE_AES_EKEY(i));
   3424  1.1  hsuenaga 		printf("AES ENC KEY COL%d: %08x\n", i, reg);
   3425  1.1  hsuenaga 	}
   3426  1.1  hsuenaga 	for (i = 0; i < 8; i++) {
   3427  1.1  hsuenaga 		reg = MVXPSEC_READ(sc, MV_CE_AES_DKEY(i));
   3428  1.1  hsuenaga 		printf("AES DEC KEY COL%d: %08x\n", i, reg);
   3429  1.1  hsuenaga 	}
   3430  1.1  hsuenaga 
   3431  1.1  hsuenaga 	return;
   3432  1.1  hsuenaga }
   3433  1.1  hsuenaga 
   3434  1.1  hsuenaga STATIC void
   3435  1.1  hsuenaga mvxpsec_dump_sram(const char *name, struct mvxpsec_softc *sc, size_t len)
   3436  1.1  hsuenaga {
   3437  1.1  hsuenaga 	uint32_t reg;
   3438  1.1  hsuenaga 
   3439  1.1  hsuenaga 	if (sc->sc_sram_va == NULL)
   3440  1.1  hsuenaga 		return;
   3441  1.1  hsuenaga 
   3442  1.1  hsuenaga 	if (len == 0) {
   3443  1.1  hsuenaga 		printf("\n%s NO DATA(len=0)\n", name);
   3444  1.1  hsuenaga 		return;
   3445  1.1  hsuenaga 	}
   3446  1.1  hsuenaga 	else if (len > MV_ACC_SRAM_SIZE)
   3447  1.1  hsuenaga 		len = MV_ACC_SRAM_SIZE;
   3448  1.1  hsuenaga 
   3449  1.1  hsuenaga 	mutex_enter(&sc->sc_dma_mtx);
   3450  1.1  hsuenaga 	reg = MVXPSEC_READ(sc, MV_TDMA_CONTROL);
   3451  1.1  hsuenaga 	if (reg & MV_TDMA_CONTROL_ACT) {
   3452  1.1  hsuenaga 		printf("TDMA is active, cannot access SRAM\n");
   3453  1.1  hsuenaga 		mutex_exit(&sc->sc_dma_mtx);
   3454  1.1  hsuenaga 		return;
   3455  1.1  hsuenaga 	}
   3456  1.1  hsuenaga 	reg = MVXPSEC_READ(sc, MV_ACC_COMMAND);
   3457  1.1  hsuenaga 	if (reg & MV_ACC_COMMAND_ACT) {
   3458  1.1  hsuenaga 		printf("SA is active, cannot access SRAM\n");
   3459  1.1  hsuenaga 		mutex_exit(&sc->sc_dma_mtx);
   3460  1.1  hsuenaga 		return;
   3461  1.1  hsuenaga 	}
   3462  1.1  hsuenaga 
   3463  1.1  hsuenaga 	printf("%s: dump SRAM, %zu bytes\n", name, len);
   3464  1.1  hsuenaga 	mvxpsec_dump_data(name, sc->sc_sram_va, len);
   3465  1.1  hsuenaga 	mutex_exit(&sc->sc_dma_mtx);
   3466  1.1  hsuenaga 	return;
   3467  1.1  hsuenaga }
   3468  1.1  hsuenaga 
   3469  1.1  hsuenaga 
   3470  1.1  hsuenaga _STATIC void
   3471  1.1  hsuenaga mvxpsec_dump_dmaq(struct mvxpsec_descriptor_handle *dh)
   3472  1.1  hsuenaga {
   3473  1.1  hsuenaga 	struct mvxpsec_descriptor *d =
   3474  1.1  hsuenaga            (struct mvxpsec_descriptor *)dh->_desc;
   3475  1.1  hsuenaga 
   3476  1.1  hsuenaga 	printf("--- DMA Command Descriptor ---\n");
   3477  1.1  hsuenaga 	printf("DESC: VA=%p PA=0x%08x\n",
   3478  1.1  hsuenaga 	    d, (uint32_t)dh->phys_addr);
   3479  1.1  hsuenaga 	printf("DESC: WORD0 = 0x%08x\n", d->tdma_word0);
   3480  1.1  hsuenaga 	printf("DESC: SRC = 0x%08x\n", d->tdma_src);
   3481  1.1  hsuenaga 	printf("DESC: DST = 0x%08x\n", d->tdma_dst);
   3482  1.1  hsuenaga 	printf("DESC: NXT = 0x%08x\n", d->tdma_nxt);
   3483  1.1  hsuenaga 
   3484  1.1  hsuenaga 	return;
   3485  1.1  hsuenaga }
   3486  1.1  hsuenaga 
   3487  1.1  hsuenaga STATIC void
   3488  1.1  hsuenaga mvxpsec_dump_data(const char *name, void *p, size_t len)
   3489  1.1  hsuenaga {
   3490  1.1  hsuenaga 	uint8_t *data = p;
   3491  1.1  hsuenaga 	off_t off;
   3492  1.1  hsuenaga 
   3493  1.1  hsuenaga 	printf("%s: dump %p, %zu bytes", name, p, len);
   3494  1.1  hsuenaga 	if (p == NULL || len == 0) {
   3495  1.1  hsuenaga 		printf("\n%s: NO DATA\n", name);
   3496  1.1  hsuenaga 		return;
   3497  1.1  hsuenaga 	}
   3498  1.1  hsuenaga 	for (off = 0; off < len; off++) {
   3499  1.1  hsuenaga 		if ((off % 16) == 0) {
   3500  1.1  hsuenaga 			printf("\n%s: 0x%08x:", name, (uint32_t)off);
   3501  1.1  hsuenaga 		}
   3502  1.1  hsuenaga 		if ((off % 4) == 0) {
   3503  1.1  hsuenaga 			printf(" ");
   3504  1.1  hsuenaga 		}
   3505  1.1  hsuenaga 		printf("%02x", data[off]);
   3506  1.1  hsuenaga 	}
   3507  1.1  hsuenaga 	printf("\n");
   3508  1.1  hsuenaga 
   3509  1.1  hsuenaga 	return;
   3510  1.1  hsuenaga }
   3511  1.1  hsuenaga 
   3512  1.1  hsuenaga _STATIC void
   3513  1.1  hsuenaga mvxpsec_dump_packet(const char *name, struct mvxpsec_packet *mv_p)
   3514  1.1  hsuenaga {
   3515  1.1  hsuenaga 	struct mvxpsec_softc *sc = mv_p->mv_s->sc;
   3516  1.1  hsuenaga 
   3517  1.1  hsuenaga 	printf("%s: packet_data:\n", name);
   3518  1.1  hsuenaga 	mvxpsec_dump_packet_data(name, mv_p);
   3519  1.1  hsuenaga 
   3520  1.1  hsuenaga 	printf("%s: SRAM:\n", name);
   3521  1.1  hsuenaga 	mvxpsec_dump_sram(name, sc, 2000);
   3522  1.1  hsuenaga 
   3523  1.1  hsuenaga 	printf("%s: packet_descriptor:\n", name);
   3524  1.1  hsuenaga 	mvxpsec_dump_packet_desc(name, mv_p);
   3525  1.1  hsuenaga }
   3526  1.1  hsuenaga 
   3527  1.1  hsuenaga _STATIC void
   3528  1.1  hsuenaga mvxpsec_dump_packet_data(const char *name, struct mvxpsec_packet *mv_p)
   3529  1.1  hsuenaga {
   3530  1.1  hsuenaga 	static char buf[1500];
   3531  1.1  hsuenaga 	int len;
   3532  1.1  hsuenaga 
   3533  1.1  hsuenaga 	if (mv_p->data_type == MVXPSEC_DATA_MBUF) {
   3534  1.1  hsuenaga 		struct mbuf *m;
   3535  1.1  hsuenaga 
   3536  1.1  hsuenaga 		m = mv_p->data.mbuf;
   3537  1.1  hsuenaga 		len = m->m_pkthdr.len;
   3538  1.1  hsuenaga 		if (len > sizeof(buf))
   3539  1.1  hsuenaga 			len = sizeof(buf);
   3540  1.1  hsuenaga 		m_copydata(m, 0, len, buf);
   3541  1.1  hsuenaga 	}
   3542  1.1  hsuenaga 	else if (mv_p->data_type == MVXPSEC_DATA_UIO) {
   3543  1.1  hsuenaga 		struct uio *uio;
   3544  1.1  hsuenaga 
   3545  1.1  hsuenaga 		uio = mv_p->data.uio;
   3546  1.1  hsuenaga 		len = uio->uio_resid;
   3547  1.1  hsuenaga 		if (len > sizeof(buf))
   3548  1.1  hsuenaga 			len = sizeof(buf);
   3549  1.1  hsuenaga 		cuio_copydata(uio, 0, len, buf);
   3550  1.1  hsuenaga 	}
   3551  1.1  hsuenaga 	else if (mv_p->data_type == MVXPSEC_DATA_RAW) {
   3552  1.1  hsuenaga 		len = mv_p->data_len;
   3553  1.1  hsuenaga 		if (len > sizeof(buf))
   3554  1.1  hsuenaga 			len = sizeof(buf);
   3555  1.1  hsuenaga 		memcpy(buf, mv_p->data.raw, len);
   3556  1.1  hsuenaga 	}
   3557  1.1  hsuenaga 	else
   3558  1.1  hsuenaga 		return;
   3559  1.1  hsuenaga 	mvxpsec_dump_data(name, buf, len);
   3560  1.1  hsuenaga 
   3561  1.1  hsuenaga 	return;
   3562  1.1  hsuenaga }
   3563  1.1  hsuenaga 
   3564  1.1  hsuenaga _STATIC void
   3565  1.1  hsuenaga mvxpsec_dump_packet_desc(const char *name, struct mvxpsec_packet *mv_p)
   3566  1.1  hsuenaga {
   3567  1.1  hsuenaga 	uint32_t *words;
   3568  1.1  hsuenaga 
   3569  1.1  hsuenaga 	if (mv_p == NULL)
   3570  1.1  hsuenaga 		return;
   3571  1.1  hsuenaga 
   3572  1.1  hsuenaga 	words = &mv_p->pkt_header.desc.acc_desc_dword0;
   3573  1.1  hsuenaga 	mvxpsec_dump_acc_config(name, words[0]);
   3574  1.1  hsuenaga 	mvxpsec_dump_acc_encdata(name, words[1], words[2]);
   3575  1.1  hsuenaga 	mvxpsec_dump_acc_enclen(name, words[2]);
   3576  1.1  hsuenaga 	mvxpsec_dump_acc_enckey(name, words[3]);
   3577  1.1  hsuenaga 	mvxpsec_dump_acc_enciv(name, words[4]);
   3578  1.1  hsuenaga 	mvxpsec_dump_acc_macsrc(name, words[5]);
   3579  1.1  hsuenaga 	mvxpsec_dump_acc_macdst(name, words[6]);
   3580  1.1  hsuenaga 	mvxpsec_dump_acc_maciv(name, words[7]);
   3581  1.1  hsuenaga 
   3582  1.1  hsuenaga 	return;
   3583  1.1  hsuenaga }
   3584  1.1  hsuenaga 
   3585  1.1  hsuenaga _STATIC void
   3586  1.1  hsuenaga mvxpsec_dump_acc_config(const char *name, uint32_t w)
   3587  1.1  hsuenaga {
   3588  1.1  hsuenaga 	/* SA: Dword 0 */
   3589  1.1  hsuenaga 	printf("%s: Dword0=0x%08x\n", name, w);
   3590  1.1  hsuenaga 	printf("%s:   OP = %s\n", name,
   3591  1.1  hsuenaga 	    s_xpsec_op(MV_ACC_CRYPTO_OP(w)));
   3592  1.1  hsuenaga 	printf("%s:   MAC = %s\n", name,
   3593  1.1  hsuenaga 	    s_xpsec_mac(MV_ACC_CRYPTO_MAC(w)));
   3594  1.1  hsuenaga 	printf("%s:   MAC_LEN = %s\n", name,
   3595  1.1  hsuenaga 	    w & MV_ACC_CRYPTO_MAC_96 ? "96-bit" : "full-bit");
   3596  1.1  hsuenaga 	printf("%s:   ENC = %s\n", name,
   3597  1.1  hsuenaga 	    s_xpsec_enc(MV_ACC_CRYPTO_ENC(w)));
   3598  1.1  hsuenaga 	printf("%s:   DIR = %s\n", name,
   3599  1.1  hsuenaga 	    w & MV_ACC_CRYPTO_DECRYPT ? "decryption" : "encryption");
   3600  1.1  hsuenaga 	printf("%s:   CHAIN = %s\n", name,
   3601  1.1  hsuenaga 	    w & MV_ACC_CRYPTO_CBC ? "CBC" : "ECB");
   3602  1.1  hsuenaga 	printf("%s:   3DES = %s\n", name,
   3603  1.1  hsuenaga 	    w & MV_ACC_CRYPTO_3DES_EDE ? "EDE" : "EEE");
   3604  1.1  hsuenaga 	printf("%s:   FRAGMENT = %s\n", name,
   3605  1.1  hsuenaga 	    s_xpsec_frag(MV_ACC_CRYPTO_FRAG(w)));
   3606  1.1  hsuenaga 	return;
   3607  1.1  hsuenaga }
   3608  1.1  hsuenaga 
   3609  1.1  hsuenaga STATIC void
   3610  1.1  hsuenaga mvxpsec_dump_acc_encdata(const char *name, uint32_t w, uint32_t w2)
   3611  1.1  hsuenaga {
   3612  1.1  hsuenaga 	/* SA: Dword 1 */
   3613  1.1  hsuenaga 	printf("%s: Dword1=0x%08x\n", name, w);
   3614  1.1  hsuenaga 	printf("%s:   ENC SRC = 0x%x\n", name, MV_ACC_DESC_GET_VAL_1(w));
   3615  1.1  hsuenaga 	printf("%s:   ENC DST = 0x%x\n", name, MV_ACC_DESC_GET_VAL_2(w));
   3616  1.1  hsuenaga 	printf("%s:   ENC RANGE = 0x%x - 0x%x\n", name,
   3617  1.1  hsuenaga 	    MV_ACC_DESC_GET_VAL_1(w),
   3618  1.1  hsuenaga 	    MV_ACC_DESC_GET_VAL_1(w) + MV_ACC_DESC_GET_VAL_1(w2) - 1);
   3619  1.1  hsuenaga 	return;
   3620  1.1  hsuenaga }
   3621  1.1  hsuenaga 
   3622  1.1  hsuenaga STATIC void
   3623  1.1  hsuenaga mvxpsec_dump_acc_enclen(const char *name, uint32_t w)
   3624  1.1  hsuenaga {
   3625  1.1  hsuenaga 	/* SA: Dword 2 */
   3626  1.1  hsuenaga 	printf("%s: Dword2=0x%08x\n", name, w);
   3627  1.1  hsuenaga 	printf("%s:   ENC LEN = %d\n", name,
   3628  1.1  hsuenaga 	    MV_ACC_DESC_GET_VAL_1(w));
   3629  1.1  hsuenaga 	return;
   3630  1.1  hsuenaga }
   3631  1.1  hsuenaga 
   3632  1.1  hsuenaga STATIC void
   3633  1.1  hsuenaga mvxpsec_dump_acc_enckey(const char *name, uint32_t w)
   3634  1.1  hsuenaga {
   3635  1.1  hsuenaga 	/* SA: Dword 3 */
   3636  1.1  hsuenaga 	printf("%s: Dword3=0x%08x\n", name, w);
   3637  1.1  hsuenaga 	printf("%s:   EKEY = 0x%x\n", name,
   3638  1.1  hsuenaga 	    MV_ACC_DESC_GET_VAL_1(w));
   3639  1.1  hsuenaga 	return;
   3640  1.1  hsuenaga }
   3641  1.1  hsuenaga 
   3642  1.1  hsuenaga STATIC void
   3643  1.1  hsuenaga mvxpsec_dump_acc_enciv(const char *name, uint32_t w)
   3644  1.1  hsuenaga {
   3645  1.1  hsuenaga 	/* SA: Dword 4 */
   3646  1.1  hsuenaga 	printf("%s: Dword4=0x%08x\n", name, w);
   3647  1.1  hsuenaga 	printf("%s:   EIV = 0x%x\n", name, MV_ACC_DESC_GET_VAL_1(w));
   3648  1.1  hsuenaga 	printf("%s:   EIV_BUF = 0x%x\n", name, MV_ACC_DESC_GET_VAL_2(w));
   3649  1.1  hsuenaga 	return;
   3650  1.1  hsuenaga }
   3651  1.1  hsuenaga 
   3652  1.1  hsuenaga STATIC void
   3653  1.1  hsuenaga mvxpsec_dump_acc_macsrc(const char *name, uint32_t w)
   3654  1.1  hsuenaga {
   3655  1.1  hsuenaga 	/* SA: Dword 5 */
   3656  1.1  hsuenaga 	printf("%s: Dword5=0x%08x\n", name, w);
   3657  1.1  hsuenaga 	printf("%s:   MAC_SRC = 0x%x\n", name,
   3658  1.1  hsuenaga 	    MV_ACC_DESC_GET_VAL_1(w));
   3659  1.1  hsuenaga 	printf("%s:   MAC_TOTAL_LEN = %d\n", name,
   3660  1.1  hsuenaga 	    MV_ACC_DESC_GET_VAL_3(w));
   3661  1.1  hsuenaga 	printf("%s:   MAC_RANGE = 0x%0x - 0x%0x\n", name,
   3662  1.1  hsuenaga 	    MV_ACC_DESC_GET_VAL_1(w),
   3663  1.1  hsuenaga 	    MV_ACC_DESC_GET_VAL_1(w) + MV_ACC_DESC_GET_VAL_3(w) - 1);
   3664  1.1  hsuenaga 	return;
   3665  1.1  hsuenaga }
   3666  1.1  hsuenaga 
   3667  1.1  hsuenaga STATIC void
   3668  1.1  hsuenaga mvxpsec_dump_acc_macdst(const char *name, uint32_t w)
   3669  1.1  hsuenaga {
   3670  1.1  hsuenaga 	/* SA: Dword 6 */
   3671  1.1  hsuenaga 	printf("%s: Dword6=0x%08x\n", name, w);
   3672  1.1  hsuenaga 	printf("%s:   MAC_DST = 0x%x\n", name, MV_ACC_DESC_GET_VAL_1(w));
   3673  1.1  hsuenaga 	printf("%s:   MAC_BLOCK_LEN = %d\n", name,
   3674  1.1  hsuenaga 	    MV_ACC_DESC_GET_VAL_2(w));
   3675  1.1  hsuenaga 	return;
   3676  1.1  hsuenaga }
   3677  1.1  hsuenaga 
   3678  1.1  hsuenaga STATIC void
   3679  1.1  hsuenaga mvxpsec_dump_acc_maciv(const char *name, uint32_t w)
   3680  1.1  hsuenaga {
   3681  1.1  hsuenaga 	/* SA: Dword 7 */
   3682  1.1  hsuenaga 	printf("%s: Dword7=0x%08x\n", name, w);
   3683  1.1  hsuenaga 	printf("%s:   MAC_INNER_IV = 0x%x\n", name,
   3684  1.1  hsuenaga 	    MV_ACC_DESC_GET_VAL_1(w));
   3685  1.1  hsuenaga 	printf("%s:   MAC_OUTER_IV = 0x%x\n", name,
   3686  1.1  hsuenaga 	    MV_ACC_DESC_GET_VAL_2(w));
   3687  1.1  hsuenaga 	return;
   3688  1.1  hsuenaga }
   3689  1.1  hsuenaga #endif
   3690