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