/*
 * CDDL HEADER START
 *
 * The contents of this file are subject to the terms of the
 * Common Development and Distribution License (the "License").
 * You may not use this file except in compliance with the License.
 *
 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
 * or http://www.opensolaris.org/os/licensing.
 * See the License for the specific language governing permissions
 * and limitations under the License.
 *
 * When distributing Covered Code, include this CDDL HEADER in each
 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
 * If applicable, add the following below this CDDL HEADER, with the
 * fields enclosed by brackets "[]" replaced with your own identifying
 * information: Portions Copyright [yyyy] [name of copyright owner]
 *
 * CDDL HEADER END
 */

/*
 * Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
 * Use is subject to license terms.
 */

#ifndef	_SYS_CRYPTO_DCA_H
#define	_SYS_CRYPTO_DCA_H

#ifdef	__cplusplus
extern "C" {
#endif

#include <sys/zfs_context.h>
#include <sys/crypto/spi.h>

/*
 * Deimos - cryptographic acceleration based upon Broadcom 582x.
 *
 * Note: Everything in this file is private to the Deimos device
 *	 driver!  Do not include this in any other file.
 */

#define	DRIVER			"dca"
#define	DCA_MANUFACTURER_ID	"SUNWdca"

/*
 * Tunables.
 */
#define	MCR1LOWATER	16	/* these numbers favor overall throughput */
#define	MCR1HIWATER	24
#define	MCR1MAXREQS	8
#define	MCR2LOWATER	16
#define	MCR2HIWATER	24
#define	MCR2MAXREQS	4
#define	MAXMCR		2	/* there are 2 mcrs */
#define	MAXREQSPERMCR	16	/* there are 4 subunits serviced by MCR2 */
#define	MAXFRAGS	6	/* Limit on the number of fragments */
#define	MAXWORK		6	/* How many work structures to preallocate */

/*
 * These are constants.  Do not change them.
 */
#if defined(i386) || defined(__i386) || defined(__amd64)
#define	MAXPACKET	0xefff	/* rootnex INT_MAX_BUF hack. */
#else
#define	MAXPACKET	0xffff	/* Max size of a packet or fragment */
#endif
#define	DESBLOCK	8	/* Size of a DES or 3DES block */
#define	DSAPARTLEN	20	/* Size of fixed DSA parts (r, s, q, x, v) */
#define	DSASIGLEN	40	/* Size of a DSA signature */
#define	SHA1LEN		20	/* Size of a SHA1 hash */
#define	SECOND		1000000	/* One second in usec */
#define	MSEC		1000	/* One millisecond in usec */
#define	DES_KEYSIZE	8
#define	DES_IV_LEN	8
#define	DES3_KEYSIZE	(3 * DES_KEYSIZE)

/*
 * Mechanism info structure passed to KCF during registration.
 */

#define	MD5_HMAC_BLOCK_SIZE	64	/* MD5-HMAC block size */
#define	MD5_HMAC_MIN_KEY_LEN	1	/* MD5-HMAC min key length in bytes */
#define	MD5_HMAC_MAX_KEY_LEN	64	/* MD5-HMAC max key length in bytes */

#define	SHA1_HMAC_BLOCK_SIZE	64	/* SHA1-HMAC block size */
#define	SHA1_HMAC_MIN_KEY_LEN	1	/* SHA1-HMAC min key length in bytes */
#define	SHA1_HMAC_MAX_KEY_LEN	64	/* SHA1-HMAC max key length in bytes */

#define	DES_KEY_LEN		8	/* DES key length in bytes */
#define	DES3_KEY_LEN		24	/* 3DES key length in bytes */

#define	DSA_MIN_KEY_LEN		64	/* DSA min key length in bytes */
#define	DSA_MAX_KEY_LEN		128	/* DSA max key length in bytes */

#define	RSA_MIN_KEY_LEN		32	/* RSA min key length in bytes */
#define	RSA_MAX_KEY_LEN		256	/* RSA max key length in bytes */

/*
 * RSA implementation.
 */

#define	DCA_RSA_ENC	0
#define	DCA_RSA_DEC	1
#define	DCA_RSA_SIGN	2
#define	DCA_RSA_VRFY	3
#define	DCA_RSA_SIGNR	4
#define	DCA_RSA_VRFYR	5

/*
 * DSA implementation.
 */

#define	DCA_DSA_SIGN	0
#define	DCA_DSA_VRFY	1

/*
 * FMA eclass index definitions. Note that this enum must be consistent
 * with the dca_fma_eclass_sca1000 and dca_fma_eclass_sca500 string arrays.
 */
typedef enum dca_fma_eclass {
	DCA_FM_ECLASS_HW_DEVICE = 0,
	DCA_FM_ECLASS_HW_TIMEOUT,
	DCA_FM_ECLASS_NONE
} dca_fma_eclass_t;

/*
 * Forward typedefs.
 */
typedef struct dca dca_t;
typedef struct dca_chain dca_chain_t;
typedef struct dca_listnode dca_listnode_t;
typedef struct dca_worklist dca_worklist_t;
typedef struct dca_work dca_work_t;
typedef struct dca_request dca_request_t;
typedef struct dca_stat dca_stat_t;
typedef struct dca_cookie dca_cookie_t;
typedef struct dca_device dca_device_t;

/*
 * This structure is used to identify a specific board.
 */
struct dca_device {
	ushort_t		dd_vendor_id;
	ushort_t		dd_device_id;
	char			*dd_model;
};

/*
 * Structure representing a node in a DMA chain.  (Broadcom calls
 * these "Data Buffer Chain Entries".)
 *
 * note, this structure must be a multiple of sizeof (intptr_t)
 */
struct dca_chain {
	/* the descriptor */
	caddr_t			dc_desc_kaddr;
	/* and the buffer to which it points */
	size_t			dc_buffer_length;
	ddi_dma_handle_t	dc_buffer_dmah;
	caddr_t			dc_buffer_kaddr;
	/* physical addresses */
	uint32_t		dc_desc_paddr;
	uint32_t		dc_buffer_paddr;
	uint32_t		dc_next_paddr;
};

/*
 * Linked-list linkage.
 */
struct dca_listnode {
	dca_listnode_t		*dl_next;
	dca_listnode_t		*dl_prev;
	dca_listnode_t		*dl_next2;
	dca_listnode_t		*dl_prev2;
};

typedef enum dca_mech_type {
	DES_CBC_MECH_INFO_TYPE,		/* SUN_CKM_DES_CBC */
	DES3_CBC_MECH_INFO_TYPE,	/* SUN_CKM_DES3_CBC */
	DSA_MECH_INFO_TYPE,		/* SUN_CKM_DSA */
	RSA_X_509_MECH_INFO_TYPE,	/* SUN_CKM_RSA_X_509 */
	RSA_PKCS_MECH_INFO_TYPE		/* SUN_CKM_RSA_PKCS */
} dca_mech_type_t;

#define	SUN_CKM_DSA			"CKM_DSA"

struct dca_rng {
	uint32_t		dr_chunklen;
};

union dca_parameters {
	struct dca_rng		dp_rng;
};

typedef struct dca_ctx {
	/*
	 * The following are context fields for Deimos 2.0.
	 */
	crypto_mech_type_t	ctx_cm_type;	/* Mechanism type */
	int			mode;		/* Mode of operation */
	int 			atomic;		/* Boolean */

	/* Fields for RSA and DSA */
	uchar_t			*mod;		/* RSA modulus */
	unsigned		modlen;		/* RSA modulus length */
	unsigned		pqfix;		/* RSA flag */

	/* Fields for DES and 3DES */
	uint32_t		iv[2];
	uint32_t		key[6];
	int			residlen;
	uchar_t			resid[DESBLOCK];
	int			activeresidlen;
	uchar_t			activeresid[DESBLOCK];
	crypto_data_t		in_dup;		/* input data duplicate */
} dca_ctx_t;

/*
 * Work structure.  One of these per actual job submitted to an MCR.
 * Contains everything we need to submit the job, and everything we
 * need to notify caller and release resources when the completion
 * interrupt comes.
 */
struct dca_request {
	dca_listnode_t		dr_linkage;
	uint16_t		dr_pkt_length;
	crypto_req_handle_t	dr_kcf_req;
	dca_t			*dr_dca;
	dca_worklist_t		*dr_wlp;
	/*
	 * Consumer's I/O buffers.
	 */
	crypto_data_t		*dr_in;
	crypto_data_t		*dr_out;
	dca_ctx_t		dr_ctx;
	/*
	 * Chains and DMA structures.
	 */
	size_t			dr_dma_size;
	uint32_t		dr_ctx_paddr;
	caddr_t			dr_ctx_kaddr;
	ddi_acc_handle_t	dr_ctx_acch;
	ddi_dma_handle_t	dr_ctx_dmah;
	/*
	 * Scratch input buffer.
	 */
	ddi_acc_handle_t	dr_ibuf_acch;
	ddi_dma_handle_t	dr_ibuf_dmah;
	caddr_t			dr_ibuf_kaddr;
	uint32_t		dr_ibuf_paddr;

	/*
	 * Scratch output buffer.
	 */
	ddi_acc_handle_t	dr_obuf_acch;
	ddi_dma_handle_t	dr_obuf_dmah;
	caddr_t			dr_obuf_kaddr;
	uint32_t		dr_obuf_paddr;

	/*
	 * Values to program MCR with.
	 */
	uint32_t		dr_in_paddr;
	uint32_t		dr_out_paddr;
	uint32_t		dr_in_next;
	uint32_t		dr_out_next;
	uint16_t		dr_in_len;
	uint16_t		dr_out_len;
	/*
	 * Callback.
	 */
	void			(*dr_callback)(dca_request_t *, int);
	/*
	 * Other stuff.
	 */
	uint32_t		dr_flags;
	/*
	 * Algorithm specific parameters.
	 */
	void			*dr_context;
	union dca_parameters	dr_param;
	/*
	 * Statistics.
	 */
	int			dr_job_stat;
	int			dr_byte_stat;

	/* Pre-mapped input and output data buffer chain support */
	dca_chain_t		dr_ibuf_head;
	dca_chain_t		dr_obuf_head;

	/*
	 * User buffers are mapped to DMA handles dynamically. The physically
	 * contigous blocks ( >= a page) are built into a data buffer chain.
	 */
	dca_chain_t		dr_chain_in_head;
	ddi_dma_handle_t	dr_chain_in_dmah;

	dca_chain_t		dr_chain_out_head;
	ddi_dma_handle_t	dr_chain_out_dmah;

	/* Offset in the context page for storing dynamic buffer chains */
	int			dr_offset;

	/* Destroy this request if true */
	int			destroy;
};

/*
 * Request flags (dca_request_t.dr_flags).
 */
#define	DR_INPLACE		0x002
#define	DR_SCATTER		0x004
#define	DR_GATHER		0x008
#define	DR_NOCACHE		0x020
#define	DR_ENCRYPT		0x040
#define	DR_DECRYPT		0x080
#define	DR_TRIPLE		0x100	/* triple DES vs. single DES */
#define	DR_ATOMIC		0x200	/* for atomic operation */

struct dca_work {
	dca_listnode_t		dw_linkage;
	dca_worklist_t		*dw_wlp;

	/* DMA access to the MCR and context */
	ddi_acc_handle_t	dw_mcr_acch;
	ddi_dma_handle_t	dw_mcr_dmah;
	caddr_t			dw_mcr_kaddr;
	uint32_t		dw_mcr_paddr;

	dca_request_t		*dw_reqs[MAXREQSPERMCR];
	clock_t			dw_lbolt;
};

/*
 * MCRs.
 */
#define	MCR1			0x1
#define	MCR2			0x2

struct dca_worklist {
	dca_t			*dwl_dca;
	crypto_kcf_provider_handle_t	dwl_prov;
	char			dwl_name[16];
	int			dwl_mcr;
	kmutex_t		dwl_lock;
	kmutex_t		dwl_freelock;
	kmutex_t		dwl_freereqslock;
	kcondvar_t		dwl_cv;
	dca_listnode_t		dwl_freereqs;	/* available requests */
	dca_listnode_t		dwl_waitq;	/* requests arrive here */
	dca_listnode_t		dwl_freework;	/* available work structures */
	dca_listnode_t		dwl_runq;	/* work structs sent to chip */
	timeout_id_t		dwl_schedtid;
	clock_t			dwl_lastsubmit;
	int			dwl_count;
	int			dwl_busy;
	int			dwl_lowater;
	int			dwl_hiwater;
	int			dwl_reqspermcr;
	int			dwl_drain;	/* for DR (suspend) */
	/* Kstats */
	u_longlong_t		dwl_submit;
	u_longlong_t		dwl_flowctl;
};

/*
 * Operations for MCR1 (bulk stuff).
 */
#define	CMD_IPSEC		0x0	/* IPsec packet processing */
#define	CMD_SSLMAC		0x1	/* SSL HMAC processing */
#define	CMD_TLSMAC		0x2	/* TLS HMAC processing */
#define	CMD_3DES		0x3	/* SSL/TLS/raw 3DES processing */
#define	CMD_RC4			0x4	/* ARCFOUR procesing */
#define	CMD_PUREHASH		0x5	/* Pure MD5/SHA1 hash processing */

/*
 * Operations for MCR2 (key stuff).
 */
#define	CMD_DHPUBLIC		0x1	/* DH public key generation */
#define	CMD_DHSHARED		0x2	/* DH shared secret generation */
#define	CMD_RSAPUBLIC		0x3	/* RSA public key operation */
#define	CMD_RSAPRIVATE		0x4	/* RSA private key operation (CRT) */
#define	CMD_DSASIGN		0x5	/* DSA signing operation */
#define	CMD_DSAVERIFY		0x6	/* DSA verification operation */
#define	CMD_RNGDIRECT		0x41	/* Direct access to the RNG */
#define	CMD_RNGSHA1		0x42	/* RNG output processed by SHA1 */
#define	CMD_MODADD		0x43	/* Modular add */
#define	CMD_MODSUB		0x44	/* Moduler subtract */
#define	CMD_MODMUL		0x45	/* Modular multiply */
#define	CMD_MODREM		0x46	/* Modular remainder */
#define	CMD_MODEXP		0x47	/* Modular exponentiation */
#define	CMD_MODINV		0x48	/* Modular inverse */

/*
 * Kstats.
 */
#define	DS_3DESJOBS		0
#define	DS_3DESBYTES		1
#define	DS_RSAPUBLIC		2
#define	DS_RSAPRIVATE		3
#define	DS_DSASIGN		4
#define	DS_DSAVERIFY		5
#define	DS_RNGJOBS		6
#define	DS_RNGBYTES		7
#define	DS_RNGSHA1JOBS		8
#define	DS_RNGSHA1BYTES		9
#define	DS_MAX			10

#if 0
/*
 * note that when reenabling any of these stats, DS_MAX will need to
 * be adjusted.
 */
#define	DS_RC4JOBS		11
#define	DS_RC4BYTES		12
#define	DS_DHPUBLIC		13
#define	DS_DHSECRET		14
#endif

struct dca_stat {
	kstat_named_t		ds_status;
	kstat_named_t		ds_algs[DS_MAX];
	struct {
		kstat_named_t	ds_submit;
		kstat_named_t	ds_flowctl;
		kstat_named_t	ds_lowater;
		kstat_named_t	ds_hiwater;
		kstat_named_t	ds_maxreqs;
	}			ds_mcr[MAXMCR];
};

/*
 * Blocking structure for ioctls.
 */
struct dca_cookie {
	kmutex_t		dc_mx;
	kcondvar_t		dc_cv;
	int			dc_outstanding;
	int			dc_status;
};

/*
 * Per instance structure.
 */
struct dca {
	dev_info_t		*dca_dip;
	kmutex_t		dca_intrlock;
	caddr_t			dca_regs;
	ddi_acc_handle_t	dca_regs_handle;
	ddi_iblock_cookie_t	dca_icookie;
	timeout_id_t		dca_jobtid;
	ulong_t			dca_pagesize;
	unsigned		dca_flags;	/* dev state flags */

	/*
	 * Work requests.
	 */
	dca_worklist_t		dca_worklist[MAXMCR];

	/*
	 * hardware model
	 */
	char			*dca_model;
	ushort_t		dca_devid;

	/*
	 * Kstats.  There is no standard for what standards
	 * Cryptographic Providers should supply, so we're
	 * making them up for now.
	 */
	kstat_t			*dca_ksp;
	kstat_t			*dca_intrstats;
	u_longlong_t		dca_stats[DS_MAX];

	/* For the local random number pool used internally by the dca driver */
	char 			*dca_buf1;
	char 			*dca_buf2;
	char 			*dca_buf_ptr;
	int 			dca_index;
	uint32_t 		dca_random_filling;
	kmutex_t 		dca_random_lock;

	/* FMA capabilities */
	int			fm_capabilities;	/* FMA capabilities */

	kmutex_t		dca_ctx_list_lock;
	dca_listnode_t		dca_ctx_list;
};

/*
 * Device flags (dca_t.dca_flags)
 */
#define	DCA_FAILED		0x1
#define	DCA_POWERMGMT		0x4
#define	DCA_RNGSHA1		0x8

#define	KIOIP(dca)		KSTAT_INTR_PTR((dca)->dca_intrstats)

/*
 * Scatter/gather checks.
 */
typedef enum dca_sg_param {
	DCA_SG_CONTIG = 1,
	DCA_SG_WALIGN,
	DCA_SG_PALIGN
} dca_sg_param_t;

#define	FALSE		0
#define	TRUE		1

/*
 * PCI configuration registers.
 */
#define	PCI_VENID		0x00	/* vendor id, 16 bits */
#define	PCI_DEVID		0x02	/* device id, 16 bits */
#define	PCI_COMM		0x04	/* command, 16 bits */
#define	PCI_STATUS		0x06	/* status, 16 bits */
#define	PCI_REVID		0x08	/* revision id, 8 bits */
#define	PCI_PROGCLASS		0x09	/* programming class, 8 bits */
#define	PCI_SUBCLASS		0x0A	/* subclass, 8 bits */
#define	PCI_CACHELINESZ		0x0C	/* cache line size, 8 bits */
#define	PCI_LATTMR		0x0D	/* latency timer, 8 bits */
#define	PCI_BIST		0x0F	/* builtin-self-test, 8 bits */
#define	PCI_SUBVENID		0x2C	/* subsystem vendor id, 16 bits */
#define	PCI_SUBSYSID		0x2E	/* subsystem id, 16 bits */
#define	PCI_MINGNT		0x3E	/* min grant for burst, 8 bits */
#define	PCI_MAXLAT		0x3F	/* maximum grant for burst, 8 bits */
#define	PCI_TRDYTO		0x40	/* TRDY timeout, 8 bits */
#define	PCI_RETRIES		0x41	/* retries bus will perform, 8 bits */

/*
 * PCI configuration register bit values.
 */
#define	PCICOMM_FBBE		0x0200	/* fast back-to-back enable */
#define	PCICOMM_SEE		0x0100	/* system error enable */
#define	PCICOMM_PEE		0x0040	/* parity error enable */
#define	PCICOMM_MWIE		0x0010	/* memory write & invalidate enable */
#define	PCICOMM_BME		0x0004	/* bus master enable */
#define	PCICOMM_MAE		0x0002	/* memory access enable */

#define	PCISTAT_PERR		0x8000	/* parity error detected */
#define	PCISTAT_SERR		0x4000	/* system error detected */
#define	PCISTAT_MABRT		0x2000	/* master abort detected */
#define	PCISTAT_TABRT		0x1000	/* target abort detected */
#define	PCISTAT_TABRTS		0x0800	/* target abort signaled */
#define	PCISTAT_PARITY		0x0100	/* data parity error detected */

#define	PCIREVID_DOMESTIC	0x01	/* domestic version */
#define	PCIREVID_EXPORT		0xE1	/* export version */

/* Note: 5820 errata: BIST feature does not work */
#define	PCIBIST_CAP		0x80	/* BIST capable */
#define	PCIBIST_START		0x40	/* start BIST test */
#define	PCIBIST_ERRMASK		0x0F	/* mask of BIST error codes */

/*
 * Command and Status Registers.
 */
#define	CSR_MCR1		0x00	/* pointer to MCR1 (bulk) */
#define	CSR_DMACTL		0x04	/* DMA control */
#define	CSR_DMASTAT		0x08	/* DMA status */
#define	CSR_DMAEA		0x0C	/* DMA error address */
#define	CSR_MCR2		0x10	/* pointer to MCR2 (exponentiator) */

/*
 * Command and status register bits.
 */
#define	DMACTL_RESET		0x80000000U	/* reset the chip */
#define	DMACTL_MCR2IE		0x40000000U	/* MCR2 interrupt enable */
#define	DMACTL_MCR1IE		0x20000000U	/* MCR1 interrupt enable */
#define	DMACTL_OFM		0x10000000U	/* output fragment mode */
#define	DMACTL_BE32		0x08000000U	/* 32-bit big endian mode */
#define	DMACTL_BE64		0x04000000U	/* 64-bit big endian mode */
#define	DMACTL_EIE		0x02000000U	/* error interrupt enable */
#define	DMACTL_RNGMASK		0x01800000U	/* RNG mode mask */
#define	DMACTL_RNG1		0x00000000U	/* 1 RNG bit per cycle */
#define	DMACTL_RNG4		0x00800000U	/* 1 RNG bit per 4 cycles */
#define	DMACTL_RNG8		0x01000000U	/* 1 RNG bit per 8 cycles */
#define	DMACTL_RNG16		0x01800000U	/* 1 RNG bit per 16 cycles */
#define	DMACTL_MODNORM		0x00400000U	/* s/w modulus normalization */
#define	DMACTL_RD256		0x00020000U	/* 256 byte read DMA size */
#define	DMACTL_FRAGMASK		0x0000FFFFU	/* output fragment size */

#define	DMASTAT_MAIP		0x80000000U	/* master access in progress */
#define	DMASTAT_MCR1FULL	0x40000000U	/* MCR1 is full */
#define	DMASTAT_MCR1INT		0x20000000U	/* MCR1 interrupted */
#define	DMASTAT_ERRINT		0x10000000U	/* error interrupted */
#define	DMASTAT_MCR2FULL	0x08000000U	/* MCR2 is full */
#define	DMASTAT_MCR2INT		0x04000000U	/* MCR2 interrupted */
#define	DMASTAT_INTERRUPTS	0x34000000U	/* all interrupts */

/*
 * Offsets of things relative to an MCR.
 */
#define	MCR_COUNT	0	/* 16 bits */
#define	MCR_FLAGS	2	/* 16 bits */
#define	MCR_CTXADDR	4	/* 32 bits */

/*
 * Basis for size (should be optimized by constant folding):
 *	4 bytes for flags and #packets.
 *	for each packet:
 *		2 descriptors (DESC_SIZE)
 *		4 bytes for context address
 *		4 bytes for packet length and reserved
 */
#define	MCR_SIZE	(4 + MAXREQSPERMCR * ((2 * DESC_SIZE) + 8))

/*
 * MCR flags.
 */
#define	MCRFLAG_FINISHED	0x0001		/* MCR processing complete */
#define	MCRFLAG_ERROR		0x0002		/* set if an error occured */
#define	MCRFLAG_ERRORMASK	0xff00		/* error code bits */

/*
 * Fields within a descriptor (data buffer chain).
 */
#define	DESC_BUFADDR	0	/* 32 bits */
#define	DESC_NEXT	4	/* 32 bits */
#define	DESC_LENGTH	8	/* 16 bits */
#define	DESC_RSVD	10	/* 16 bits */
#define	DESC_SIZE	16	/* ROUNDUP(12, 16) - descriptor size (bytes) */

/*
 * Offsets of fields within context structures, see Broadcom spec.
 */
#define	CTX_LENGTH		0	/* 16 bits */
#define	CTX_CMD			2	/* 16 bits */
#define	CTX_MAXLENGTH		768	/* max size of ctx, fits anything */

#define	CTX_3DESDIRECTION	4	/* 16 bits */
#define	CTX_3DESKEY1HI		8	/* 32 bits */
#define	CTX_3DESKEY1LO		12	/* 32 bits */
#define	CTX_3DESKEY2HI		16	/* 32 bits */
#define	CTX_3DESKEY2LO		20	/* 32 bits */
#define	CTX_3DESKEY3HI		24	/* 32 bits */
#define	CTX_3DESKEY3LO		28	/* 32 bits */
#define	CTX_3DESIVHI		32	/* 32 bits */
#define	CTX_3DESIVLO		36	/* 32 bits */

#define	CTX_IPSECFLAGS		4	/* 16 bits */
#define	CTX_IPSECOFFSET		6	/* 16 bits */
#define	CTX_IPSECKEY1HI		8	/* 32 bits */
#define	CTX_IPSECKEY1LO		12	/* 32 bits */
#define	CTX_IPSECKEY2HI		16	/* 32 bits */
#define	CTX_IPSECKEY2LO		20	/* 32 bits */
#define	CTX_IPSECKEY3HI		24	/* 32 bits */
#define	CTX_IPSECKEY3LO		28	/* 32 bits */
#define	CTX_IPSECIVHI		32	/* 32 bits */
#define	CTX_IPSECIVLO		36	/* 32 bits */
#define	CTX_IPSECHMACINNER1	40	/* 32 bits */
#define	CTX_IPSECHMACINNER2	44	/* 32 bits */
#define	CTX_IPSECHMACINNER3	48	/* 32 bits */
#define	CTX_IPSECHMACINNER4	52	/* 32 bits */
#define	CTX_IPSECHMACINNER5	56	/* 32 bits */
#define	CTX_IPSECHMACOUTER1	60	/* 32 bits */
#define	CTX_IPSECHMACOUTER2	64	/* 32 bits */
#define	CTX_IPSECHMACOUTER3	68	/* 32 bits */
#define	CTX_IPSECHMACOUTER4	72	/* 32 bits */
#define	CTX_IPSECHMACOUTER5	76	/* 32 bits */

#define	CTX_RSAEXPLEN		4	/* 16 bits */
#define	CTX_RSAMODLEN		6	/* 16 bits */
#define	CTX_RSABIGNUMS		8	/* variable length */
#define	CTX_RSAQLEN		4	/* 16 bits */
#define	CTX_RSAPLEN		6	/* 16 bits */

#define	CTX_DSAMSGTYPE		4	/* 16 bits */
#define	CTX_DSARSVD		6	/* 16 bits */
#define	CTX_DSARNG		8	/* 16 bits */
#define	CTX_DSAPLEN		10	/* 16 bits */
#define	CTX_DSABIGNUMS		12	/* variable length */

/*
 * Values for specific operations.
 */
#define	CTX_RNG_LENGTH		64	/* context length for RNG (64 min) */
#define	CTX_3DES_LENGTH		64	/* context length for 3DES (64 min) */
#define	CTX_3DES_DECRYPT	0x4000	/* perform decryption */
#define	CTX_3DES_ENCRYPT	0x0000	/* perform encryption */
#define	CTX_IPSEC_LENGTH	80	/* context length for IPsec */
#define	CTX_IPSEC_ENCRYPT	0x8000	/* perform encryption */
#define	CTX_IPSEC_DECRYPT	0xc000	/* perform decryption */
#define	CTX_IPSEC_HMAC_MD5	0x1000	/* HMAC-MD5 authentication */
#define	CTX_IPSEC_HMAC_SHA1	0x2000	/* HMAC-MD5 authentication */
#define	CTX_DSAMSGTYPE_SHA1	0	/* Message is SHA1 */
#define	CTX_DSAMSGTYPE_TEXT	1	/* Generate SHA1 hash first */
#define	CTX_DSARNG_GEN		1	/* Generate random k */
#define	CTX_DSARNG_SUPPLY	0	/* Random k is supplied */

/*
 * Macros to access fields within the MCR.  Note that this includes the
 * context fields as well, since the context is just offset from the
 * base of the MCR.
 */

#define	PUTMCR32(work, reg, val)	\
	ddi_put32(work->dw_mcr_acch,	\
	(uint32_t *)(work->dw_mcr_kaddr + reg), val)

#define	PUTMCR16(work, reg, val)	\
	ddi_put16(work->dw_mcr_acch,	\
	(uint16_t *)(work->dw_mcr_kaddr + reg), val)

#define	GETMCR32(work, reg)	\
	ddi_get32(work->dw_mcr_acch, (uint32_t *)(work->dw_mcr_kaddr + reg))

#define	GETMCR16(work, reg)	\
	ddi_get16(work->dw_mcr_acch, (uint16_t *)(work->dw_mcr_kaddr + reg))

#define	PUTDESC32(req, dc_desc_kaddr, reg, val)	\
	ddi_put32(req->dr_ctx_acch,	\
	(uint32_t *)(dc_desc_kaddr + reg), val)

#define	PUTDESC16(req, dc_desc_kaddr, reg, val)	\
	ddi_put16(req->dr_ctx_acch,	\
	(uint16_t *)(dc_desc_kaddr + reg), val)

/* XXX: define the GET forms for descriptors only if needed */

#define	PUTCTX32(req, reg, val)	\
	ddi_put32(req->dr_ctx_acch,	\
	(uint32_t *)(req->dr_ctx_kaddr + reg), val)

#define	PUTCTX16(req, reg, val)	\
	ddi_put16(req->dr_ctx_acch,	\
	(uint16_t *)(req->dr_ctx_kaddr + reg), val)

#define	CTXBCOPY(req, src, dst, count)	\
	ddi_rep_put8(req->dr_ctx_acch, (uchar_t *)src, (uchar_t *)dst, count, \
	DDI_DEV_AUTOINCR)

/*
 * Register access.
 */
#define	GETCSR(dca, reg)	\
	ddi_get32(dca->dca_regs_handle, (uint_t *)(dca->dca_regs + reg))

#define	PUTCSR(dca, reg, val)	\
	ddi_put32(dca->dca_regs_handle, (uint_t *)(dca->dca_regs + reg), val)

#define	SETBIT(dca, reg, val)	\
	PUTCSR(dca, reg, GETCSR(dca, reg) | val)

#define	CLRBIT(dca, reg, val)	\
	PUTCSR(dca, reg, GETCSR(dca, reg) & ~val)

/*
 * Used to guarantee alignment.
 */
#define	ROUNDUP(a, n)	(((a) + ((n) - 1)) & ~((n) - 1))
#define	ROUNDDOWN(a, n)	(((a) & ~((n) - 1)))
#define	HIDBLWORD(x)	(((x) & 0xffffffff00000000ULL) >> 32)
#define	LODBLWORD(x)	((x) & 0xffffffffULL)

/*
 * Driver hardening related.
 */
#define	CHECK_REGS(dca)	ddi_check_acc_handle(dca->dca_regs_handle)

/*
 * Other utility macros.
 */
#define	QEMPTY(q)	((q)->dl_next == (q))
#define	BITS2BYTES(b)	((b) >> 3)
#define	WORKLIST(dca, mcr)	(&((dca)->dca_worklist[mcr - 1]))

/*
 * Debug stuff.
 */
#ifdef	DEBUG
#define	DWARN		0x0001
#define	DPCI		0x0002
#define	DINTR		0x0004
#define	DSTART		0x0008
#define	DRECLAIM	0x0010
#define	DCHATTY		0x0020
#define	DMOD		0x0040	/* _init/_fini/_info/attach/detach */
#define	DENTRY		0x0080	/* crypto routine entry/exit points */

void	dca_dprintf(dca_t *, int, const char *, ...);
#define	DBG	dca_dprintf
#else
#define	DBG(dca, lvl, ...)
#endif

/*
 * Some pkcs#11 defines as there are no pkcs#11 header files included.
 */
#define	CKO_PUBLIC_KEY		0x00000002
#define	CKO_PRIVATE_KEY		0x00000003

#define	CKA_CLASS		0x00000000
#define	CKA_VALUE		0x00000011
#define	CKA_KEY_TYPE		0x00000100
#define	CKA_MODULUS		0x00000120
#define	CKA_PUBLIC_EXPONENT	0x00000122
#define	CKA_PRIVATE_EXPONENT	0x00000123
#define	CKA_PRIME_1		0x00000124
#define	CKA_PRIME_2		0x00000125
#define	CKA_EXPONENT_1		0x00000126
#define	CKA_EXPONENT_2		0x00000127
#define	CKA_COEFFICIENT		0x00000128
#define	CKA_PRIME		0x00000130
#define	CKA_SUBPRIME		0x00000131
#define	CKA_BASE		0x00000132
/*
 * Driver globals.
 */
extern int	dca_mindma;
extern int	dca_hardening;

/*
 * Prototypes.
 */

/*
 * dca_debug.c
 */
void	dca_error(dca_t *, const char *, ...);
void	dca_diperror(dev_info_t *, const char *, ...);
void	dca_dipverror(dev_info_t *, const char *, va_list);
/*
 * dca_3des.c
 */
int	dca_3desctxinit(crypto_ctx_t *, crypto_mechanism_t *, crypto_key_t *,
    int, int);
int	dca_3des(crypto_ctx_t *, crypto_data_t *, crypto_data_t *,
    crypto_req_handle_t, int);
int	dca_3desupdate(crypto_ctx_t *, crypto_data_t *, crypto_data_t *,
    crypto_req_handle_t, int);
int	dca_3desfinal(crypto_ctx_t *, crypto_data_t *, int);
int	dca_3desatomic(crypto_provider_handle_t, crypto_session_id_t,
    crypto_mechanism_t *, crypto_key_t *, crypto_data_t *, crypto_data_t *,
    int, crypto_req_handle_t, int);
void	dca_3desctxfree(void *);

/*
 * dca_rsa.c
 */
int	dca_rsastart(crypto_ctx_t *, crypto_data_t *, crypto_data_t *,
    crypto_req_handle_t, int);
int	dca_rsainit(crypto_ctx_t *, crypto_mechanism_t *, crypto_key_t *, int);
void	dca_rsactxfree(void *);
int	dca_rsaatomic(crypto_provider_handle_t, crypto_session_id_t,
    crypto_mechanism_t *, crypto_key_t *, crypto_data_t *, crypto_data_t *,
    int, crypto_req_handle_t, int);

/*
 * dca_dsa.c
 */
int	dca_dsa_sign(crypto_ctx_t *, crypto_data_t *, crypto_data_t *,
    crypto_req_handle_t);
int	dca_dsa_verify(crypto_ctx_t *, crypto_data_t *, crypto_data_t *,
    crypto_req_handle_t);
int	dca_dsainit(crypto_ctx_t *, crypto_mechanism_t *, crypto_key_t *, int,
    int);
void	dca_dsactxfree(void *);
int	dca_dsaatomic(crypto_provider_handle_t, crypto_session_id_t,
    crypto_mechanism_t *, crypto_key_t *, crypto_data_t *, crypto_data_t *,
    int, crypto_req_handle_t, int);

/*
 * dca_rng.c
 */
int	dca_rng(dca_t *, uchar_t *, size_t len, crypto_req_handle_t);
int	dca_random_buffer(dca_t *dca, caddr_t buf, int len);
int	dca_random_init();
void	dca_random_fini();

/*
 * dca_kstat.c
 */
void	dca_ksinit(dca_t *);
/*
 * dca.c
 */
void	dca_rmqueue(dca_listnode_t *);
dca_request_t *dca_getreq(dca_t *, int, int);
void	dca_freereq(dca_request_t *);
int	dca_bindchains(dca_request_t *, size_t, size_t);
int	dca_unbindchains(dca_request_t *);
int	dca_start(dca_t *, dca_request_t *, int, int);
void	dca_done(dca_request_t *, int);
void	dca_destroyreq(dca_request_t *);
int	dca_length(crypto_data_t *);
int	dca_gather(crypto_data_t *, char *, int, int);
int	dca_resid_gather(crypto_data_t *, char *, int *, char *, int);
int	dca_scatter(const char *, crypto_data_t *, int, int);
int	dca_bcmp_reverse(const void *s1, const void *s2, size_t n);
int	dca_dupcrypto(crypto_data_t *, crypto_data_t *);
int	dca_verifyio(crypto_data_t *, crypto_data_t *);
int	dca_getbufbytes(crypto_data_t *, size_t, int, uchar_t *);
int	dca_sgcheck(dca_t *, crypto_data_t *, dca_sg_param_t);
crypto_object_attribute_t *
	dca_get_key_attr(crypto_key_t *);
int	dca_attr_lookup_uint32(crypto_object_attribute_t *, uint_t, uint64_t,
	    uint32_t *);
int	dca_attr_lookup_uint8_array(crypto_object_attribute_t *, uint_t,
	    uint64_t, void **, unsigned int *);
crypto_object_attribute_t *
	dca_find_attribute(crypto_object_attribute_t *, uint_t, uint64_t);
caddr_t	dca_bufdaddr(crypto_data_t *);
void	dca_rcoalesce(dca_request_t *, int);
void	dca_runcoalesce(dca_request_t *);
int	dca_bitlen(unsigned char *, int);
uint16_t dca_padhalf(int);
uint16_t dca_padfull(int);
void	dca_reverse(void *, void *, int, int);
int	dca_numcmp(caddr_t, int, caddr_t, int);
int dca_check_dma_handle(dca_t *dca, ddi_dma_handle_t handle,
	dca_fma_eclass_t eclass_index);
int dca_free_context(crypto_ctx_t *ctx);

#ifdef	__cplusplus
}
#endif

#endif	/* _SYS_CRYPTO_DCA_H */
