xref: /illumos-gate/usr/src/uts/common/crypto/io/dca.c (revision 56f33205c9ed776c3c909e07d52e94610a675740)
1 /*
2  * CDDL HEADER START
3  *
4  * The contents of this file are subject to the terms of the
5  * Common Development and Distribution License (the "License").
6  * You may not use this file except in compliance with the License.
7  *
8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9  * or http://www.opensolaris.org/os/licensing.
10  * See the License for the specific language governing permissions
11  * and limitations under the License.
12  *
13  * When distributing Covered Code, include this CDDL HEADER in each
14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15  * If applicable, add the following below this CDDL HEADER, with the
16  * fields enclosed by brackets "[]" replaced with your own identifying
17  * information: Portions Copyright [yyyy] [name of copyright owner]
18  *
19  * CDDL HEADER END
20  */
21 
22 /*
23  * Copyright 2010 Sun Microsystems, Inc.  All rights reserved.
24  * Use is subject to license terms.
25  */
26 
27 
28 /*
29  * Deimos - cryptographic acceleration based upon Broadcom 582x.
30  */
31 
32 #include <sys/types.h>
33 #include <sys/modctl.h>
34 #include <sys/conf.h>
35 #include <sys/devops.h>
36 #include <sys/ddi.h>
37 #include <sys/sunddi.h>
38 #include <sys/cmn_err.h>
39 #include <sys/varargs.h>
40 #include <sys/file.h>
41 #include <sys/stat.h>
42 #include <sys/kmem.h>
43 #include <sys/ioccom.h>
44 #include <sys/open.h>
45 #include <sys/cred.h>
46 #include <sys/kstat.h>
47 #include <sys/strsun.h>
48 #include <sys/note.h>
49 #include <sys/crypto/common.h>
50 #include <sys/crypto/spi.h>
51 #include <sys/ddifm.h>
52 #include <sys/fm/protocol.h>
53 #include <sys/fm/util.h>
54 #include <sys/fm/io/ddi.h>
55 #include <sys/crypto/dca.h>
56 
57 /*
58  * Core Deimos driver.
59  */
60 
61 static void		dca_enlist2(dca_listnode_t *, dca_listnode_t *,
62     kmutex_t *);
63 static void		dca_rmlist2(dca_listnode_t *node, kmutex_t *);
64 static dca_listnode_t	*dca_delist2(dca_listnode_t *q, kmutex_t *);
65 static void		dca_free_context_list(dca_t *dca);
66 static int		dca_free_context_low(crypto_ctx_t *ctx);
67 static int		dca_attach(dev_info_t *, ddi_attach_cmd_t);
68 static int		dca_detach(dev_info_t *, ddi_detach_cmd_t);
69 static int		dca_suspend(dca_t *);
70 static int		dca_resume(dca_t *);
71 static int		dca_init(dca_t *);
72 static int		dca_reset(dca_t *, int);
73 static int		dca_initworklist(dca_t *, dca_worklist_t *);
74 static void		dca_uninit(dca_t *);
75 static void		dca_initq(dca_listnode_t *);
76 static void		dca_enqueue(dca_listnode_t *, dca_listnode_t *);
77 static dca_listnode_t	*dca_dequeue(dca_listnode_t *);
78 static dca_listnode_t	*dca_unqueue(dca_listnode_t *);
79 static dca_request_t	*dca_newreq(dca_t *);
80 static dca_work_t	*dca_getwork(dca_t *, int);
81 static void		dca_freework(dca_work_t *);
82 static dca_work_t	*dca_newwork(dca_t *);
83 static void		dca_destroywork(dca_work_t *);
84 static void		dca_schedule(dca_t *, int);
85 static void		dca_reclaim(dca_t *, int);
86 static uint_t		dca_intr(char *);
87 static void		dca_failure(dca_t *, ddi_fault_location_t,
88 			    dca_fma_eclass_t index, uint64_t, int, char *, ...);
89 static void		dca_jobtimeout(void *);
90 static int		dca_drain(dca_t *);
91 static void		dca_undrain(dca_t *);
92 static void		dca_rejectjobs(dca_t *);
93 
94 #ifdef	SCHEDDELAY
95 static void		dca_schedtimeout(void *);
96 #endif
97 
98 /*
99  * We want these inlined for performance.
100  */
101 #ifndef	DEBUG
102 #pragma inline(dca_freereq, dca_getreq, dca_freework, dca_getwork)
103 #pragma inline(dca_enqueue, dca_dequeue, dca_rmqueue, dca_done)
104 #pragma inline(dca_reverse, dca_length)
105 #endif
106 
107 /*
108  * Device operations.
109  */
110 static struct dev_ops devops = {
111 	DEVO_REV,		/* devo_rev */
112 	0,			/* devo_refcnt */
113 	nodev,			/* devo_getinfo */
114 	nulldev,		/* devo_identify */
115 	nulldev,		/* devo_probe */
116 	dca_attach,		/* devo_attach */
117 	dca_detach,		/* devo_detach */
118 	nodev,			/* devo_reset */
119 	NULL,			/* devo_cb_ops */
120 	NULL,			/* devo_bus_ops */
121 	ddi_power,		/* devo_power */
122 	ddi_quiesce_not_supported,	/* devo_quiesce */
123 };
124 
125 #define	IDENT		"PCI Crypto Accelerator"
126 #define	IDENT_SYM	"Crypto Accel Sym 2.0"
127 #define	IDENT_ASYM	"Crypto Accel Asym 2.0"
128 
129 /* Space-padded, will be filled in dynamically during registration */
130 #define	IDENT3	"PCI Crypto Accelerator Mod 2.0"
131 
132 #define	VENDOR	"Sun Microsystems, Inc."
133 
134 #define	STALETIME	(30 * SECOND)
135 
136 #define	crypto_prov_notify	crypto_provider_notification
137 		/* A 28 char function name doesn't leave much line space */
138 
139 /*
140  * Module linkage.
141  */
142 static struct modldrv modldrv = {
143 	&mod_driverops,		/* drv_modops */
144 	IDENT,			/* drv_linkinfo */
145 	&devops,		/* drv_dev_ops */
146 };
147 
148 extern struct mod_ops mod_cryptoops;
149 
150 static struct modlcrypto modlcrypto = {
151 	&mod_cryptoops,
152 	IDENT3
153 };
154 
155 static struct modlinkage modlinkage = {
156 	MODREV_1,		/* ml_rev */
157 	&modldrv,		/* ml_linkage */
158 	&modlcrypto,
159 	NULL
160 };
161 
162 /*
163  * CSPI information (entry points, provider info, etc.)
164  */
165 
166 /* Mechanisms for the symmetric cipher provider */
167 static crypto_mech_info_t dca_mech_info_tab1[] = {
168 	/* DES-CBC */
169 	{SUN_CKM_DES_CBC, DES_CBC_MECH_INFO_TYPE,
170 	    CRYPTO_FG_ENCRYPT | CRYPTO_FG_DECRYPT |
171 	    CRYPTO_FG_ENCRYPT_ATOMIC | CRYPTO_FG_DECRYPT_ATOMIC,
172 	    DES_KEY_LEN, DES_KEY_LEN, CRYPTO_KEYSIZE_UNIT_IN_BYTES},
173 	/* 3DES-CBC */
174 	{SUN_CKM_DES3_CBC, DES3_CBC_MECH_INFO_TYPE,
175 	    CRYPTO_FG_ENCRYPT | CRYPTO_FG_DECRYPT |
176 	    CRYPTO_FG_ENCRYPT_ATOMIC | CRYPTO_FG_DECRYPT_ATOMIC,
177 	    DES3_MIN_KEY_LEN, DES3_MAX_KEY_LEN, CRYPTO_KEYSIZE_UNIT_IN_BYTES}
178 };
179 
180 /* Mechanisms for the asymmetric cipher provider */
181 static crypto_mech_info_t dca_mech_info_tab2[] = {
182 	/* DSA */
183 	{SUN_CKM_DSA, DSA_MECH_INFO_TYPE,
184 	    CRYPTO_FG_SIGN | CRYPTO_FG_VERIFY |
185 	    CRYPTO_FG_SIGN_ATOMIC | CRYPTO_FG_VERIFY_ATOMIC,
186 	    CRYPTO_BYTES2BITS(DSA_MIN_KEY_LEN),
187 	    CRYPTO_BYTES2BITS(DSA_MAX_KEY_LEN),
188 	    CRYPTO_KEYSIZE_UNIT_IN_BITS},
189 
190 	/* RSA */
191 	{SUN_CKM_RSA_X_509, RSA_X_509_MECH_INFO_TYPE,
192 	    CRYPTO_FG_ENCRYPT | CRYPTO_FG_DECRYPT | CRYPTO_FG_SIGN |
193 	    CRYPTO_FG_SIGN_RECOVER | CRYPTO_FG_VERIFY |
194 	    CRYPTO_FG_VERIFY_RECOVER |
195 	    CRYPTO_FG_ENCRYPT_ATOMIC | CRYPTO_FG_DECRYPT_ATOMIC |
196 	    CRYPTO_FG_SIGN_ATOMIC | CRYPTO_FG_SIGN_RECOVER_ATOMIC |
197 	    CRYPTO_FG_VERIFY_ATOMIC | CRYPTO_FG_VERIFY_RECOVER_ATOMIC,
198 	    CRYPTO_BYTES2BITS(RSA_MIN_KEY_LEN),
199 	    CRYPTO_BYTES2BITS(RSA_MAX_KEY_LEN),
200 	    CRYPTO_KEYSIZE_UNIT_IN_BITS},
201 	{SUN_CKM_RSA_PKCS, RSA_PKCS_MECH_INFO_TYPE,
202 	    CRYPTO_FG_ENCRYPT | CRYPTO_FG_DECRYPT | CRYPTO_FG_SIGN |
203 	    CRYPTO_FG_SIGN_RECOVER | CRYPTO_FG_VERIFY |
204 	    CRYPTO_FG_VERIFY_RECOVER |
205 	    CRYPTO_FG_ENCRYPT_ATOMIC | CRYPTO_FG_DECRYPT_ATOMIC |
206 	    CRYPTO_FG_SIGN_ATOMIC | CRYPTO_FG_SIGN_RECOVER_ATOMIC |
207 	    CRYPTO_FG_VERIFY_ATOMIC | CRYPTO_FG_VERIFY_RECOVER_ATOMIC,
208 	    CRYPTO_BYTES2BITS(RSA_MIN_KEY_LEN),
209 	    CRYPTO_BYTES2BITS(RSA_MAX_KEY_LEN),
210 	    CRYPTO_KEYSIZE_UNIT_IN_BITS}
211 };
212 
213 static void dca_provider_status(crypto_provider_handle_t, uint_t *);
214 
215 static crypto_control_ops_t dca_control_ops = {
216 	dca_provider_status
217 };
218 
219 static int dca_encrypt_init(crypto_ctx_t *, crypto_mechanism_t *,
220     crypto_key_t *, crypto_spi_ctx_template_t, crypto_req_handle_t);
221 static int dca_encrypt(crypto_ctx_t *, crypto_data_t *, crypto_data_t *,
222     crypto_req_handle_t);
223 static int dca_encrypt_update(crypto_ctx_t *, crypto_data_t *,
224     crypto_data_t *, crypto_req_handle_t);
225 static int dca_encrypt_final(crypto_ctx_t *, crypto_data_t *,
226     crypto_req_handle_t);
227 static int dca_encrypt_atomic(crypto_provider_handle_t, crypto_session_id_t,
228     crypto_mechanism_t *, crypto_key_t *, crypto_data_t *,
229     crypto_data_t *, crypto_spi_ctx_template_t, crypto_req_handle_t);
230 
231 static int dca_decrypt_init(crypto_ctx_t *, crypto_mechanism_t *,
232     crypto_key_t *, crypto_spi_ctx_template_t, crypto_req_handle_t);
233 static int dca_decrypt(crypto_ctx_t *, crypto_data_t *, crypto_data_t *,
234     crypto_req_handle_t);
235 static int dca_decrypt_update(crypto_ctx_t *, crypto_data_t *,
236     crypto_data_t *, crypto_req_handle_t);
237 static int dca_decrypt_final(crypto_ctx_t *, crypto_data_t *,
238     crypto_req_handle_t);
239 static int dca_decrypt_atomic(crypto_provider_handle_t, crypto_session_id_t,
240     crypto_mechanism_t *, crypto_key_t *, crypto_data_t *,
241     crypto_data_t *, crypto_spi_ctx_template_t, crypto_req_handle_t);
242 
243 static crypto_cipher_ops_t dca_cipher_ops = {
244 	dca_encrypt_init,
245 	dca_encrypt,
246 	dca_encrypt_update,
247 	dca_encrypt_final,
248 	dca_encrypt_atomic,
249 	dca_decrypt_init,
250 	dca_decrypt,
251 	dca_decrypt_update,
252 	dca_decrypt_final,
253 	dca_decrypt_atomic
254 };
255 
256 static int dca_sign_init(crypto_ctx_t *, crypto_mechanism_t *, crypto_key_t *,
257     crypto_spi_ctx_template_t, crypto_req_handle_t);
258 static int dca_sign(crypto_ctx_t *, crypto_data_t *, crypto_data_t *,
259     crypto_req_handle_t);
260 static int dca_sign_update(crypto_ctx_t *, crypto_data_t *,
261     crypto_req_handle_t);
262 static int dca_sign_final(crypto_ctx_t *, crypto_data_t *,
263     crypto_req_handle_t);
264 static int dca_sign_atomic(crypto_provider_handle_t, crypto_session_id_t,
265     crypto_mechanism_t *, crypto_key_t *, crypto_data_t *, crypto_data_t *,
266     crypto_spi_ctx_template_t, crypto_req_handle_t);
267 static int dca_sign_recover_init(crypto_ctx_t *, crypto_mechanism_t *,
268     crypto_key_t *, crypto_spi_ctx_template_t, crypto_req_handle_t);
269 static int dca_sign_recover(crypto_ctx_t *, crypto_data_t *, crypto_data_t *,
270     crypto_req_handle_t);
271 static int dca_sign_recover_atomic(crypto_provider_handle_t,
272     crypto_session_id_t, crypto_mechanism_t *, crypto_key_t *, crypto_data_t *,
273     crypto_data_t *, crypto_spi_ctx_template_t, crypto_req_handle_t);
274 
275 static crypto_sign_ops_t dca_sign_ops = {
276 	dca_sign_init,
277 	dca_sign,
278 	dca_sign_update,
279 	dca_sign_final,
280 	dca_sign_atomic,
281 	dca_sign_recover_init,
282 	dca_sign_recover,
283 	dca_sign_recover_atomic
284 };
285 
286 static int dca_verify_init(crypto_ctx_t *, crypto_mechanism_t *,
287     crypto_key_t *, crypto_spi_ctx_template_t, crypto_req_handle_t);
288 static int dca_verify(crypto_ctx_t *, crypto_data_t *, crypto_data_t *,
289     crypto_req_handle_t);
290 static int dca_verify_update(crypto_ctx_t *, crypto_data_t *,
291     crypto_req_handle_t);
292 static int dca_verify_final(crypto_ctx_t *, crypto_data_t *,
293     crypto_req_handle_t);
294 static int dca_verify_atomic(crypto_provider_handle_t, crypto_session_id_t,
295     crypto_mechanism_t *, crypto_key_t *, crypto_data_t *,
296     crypto_data_t *, crypto_spi_ctx_template_t, crypto_req_handle_t);
297 static int dca_verify_recover_init(crypto_ctx_t *, crypto_mechanism_t *,
298     crypto_key_t *, crypto_spi_ctx_template_t, crypto_req_handle_t);
299 static int dca_verify_recover(crypto_ctx_t *, crypto_data_t *,
300     crypto_data_t *, crypto_req_handle_t);
301 static int dca_verify_recover_atomic(crypto_provider_handle_t,
302     crypto_session_id_t, crypto_mechanism_t *, crypto_key_t *, crypto_data_t *,
303     crypto_data_t *, crypto_spi_ctx_template_t, crypto_req_handle_t);
304 
305 static crypto_verify_ops_t dca_verify_ops = {
306 	dca_verify_init,
307 	dca_verify,
308 	dca_verify_update,
309 	dca_verify_final,
310 	dca_verify_atomic,
311 	dca_verify_recover_init,
312 	dca_verify_recover,
313 	dca_verify_recover_atomic
314 };
315 
316 static int dca_generate_random(crypto_provider_handle_t, crypto_session_id_t,
317     uchar_t *, size_t, crypto_req_handle_t);
318 
319 static crypto_random_number_ops_t dca_random_number_ops = {
320 	NULL,
321 	dca_generate_random
322 };
323 
324 static int ext_info_sym(crypto_provider_handle_t prov,
325     crypto_provider_ext_info_t *ext_info, crypto_req_handle_t cfreq);
326 static int ext_info_asym(crypto_provider_handle_t prov,
327     crypto_provider_ext_info_t *ext_info, crypto_req_handle_t cfreq);
328 static int ext_info_base(crypto_provider_handle_t prov,
329     crypto_provider_ext_info_t *ext_info, crypto_req_handle_t cfreq, char *id);
330 
331 static crypto_provider_management_ops_t dca_provmanage_ops_1 = {
332 	ext_info_sym,		/* ext_info */
333 	NULL,			/* init_token */
334 	NULL,			/* init_pin */
335 	NULL			/* set_pin */
336 };
337 
338 static crypto_provider_management_ops_t dca_provmanage_ops_2 = {
339 	ext_info_asym,		/* ext_info */
340 	NULL,			/* init_token */
341 	NULL,			/* init_pin */
342 	NULL			/* set_pin */
343 };
344 
345 int dca_free_context(crypto_ctx_t *);
346 
347 static crypto_ctx_ops_t dca_ctx_ops = {
348 	NULL,
349 	dca_free_context
350 };
351 
352 /* Operations for the symmetric cipher provider */
353 static crypto_ops_t dca_crypto_ops1 = {
354 	&dca_control_ops,
355 	NULL,				/* digest_ops */
356 	&dca_cipher_ops,
357 	NULL,				/* mac_ops */
358 	NULL,				/* sign_ops */
359 	NULL,				/* verify_ops */
360 	NULL,				/* dual_ops */
361 	NULL,				/* cipher_mac_ops */
362 	NULL,				/* random_number_ops */
363 	NULL,				/* session_ops */
364 	NULL,				/* object_ops */
365 	NULL,				/* key_ops */
366 	&dca_provmanage_ops_1,		/* management_ops */
367 	&dca_ctx_ops
368 };
369 
370 /* Operations for the asymmetric cipher provider */
371 static crypto_ops_t dca_crypto_ops2 = {
372 	&dca_control_ops,
373 	NULL,				/* digest_ops */
374 	&dca_cipher_ops,
375 	NULL,				/* mac_ops */
376 	&dca_sign_ops,
377 	&dca_verify_ops,
378 	NULL,				/* dual_ops */
379 	NULL,				/* cipher_mac_ops */
380 	&dca_random_number_ops,
381 	NULL,				/* session_ops */
382 	NULL,				/* object_ops */
383 	NULL,				/* key_ops */
384 	&dca_provmanage_ops_2,		/* management_ops */
385 	&dca_ctx_ops
386 };
387 
388 /* Provider information for the symmetric cipher provider */
389 static crypto_provider_info_t dca_prov_info1 = {
390 	CRYPTO_SPI_VERSION_1,
391 	NULL,				/* pi_provider_description */
392 	CRYPTO_HW_PROVIDER,
393 	NULL,				/* pi_provider_dev */
394 	NULL,				/* pi_provider_handle */
395 	&dca_crypto_ops1,
396 	sizeof (dca_mech_info_tab1)/sizeof (crypto_mech_info_t),
397 	dca_mech_info_tab1,
398 	0,				/* pi_logical_provider_count */
399 	NULL				/* pi_logical_providers */
400 };
401 
402 /* Provider information for the asymmetric cipher provider */
403 static crypto_provider_info_t dca_prov_info2 = {
404 	CRYPTO_SPI_VERSION_1,
405 	NULL,				/* pi_provider_description */
406 	CRYPTO_HW_PROVIDER,
407 	NULL,				/* pi_provider_dev */
408 	NULL,				/* pi_provider_handle */
409 	&dca_crypto_ops2,
410 	sizeof (dca_mech_info_tab2)/sizeof (crypto_mech_info_t),
411 	dca_mech_info_tab2,
412 	0,				/* pi_logical_provider_count */
413 	NULL				/* pi_logical_providers */
414 };
415 
416 /* Convenience macros */
417 /* Retrieve the softc and instance number from a SPI crypto context */
418 #define	DCA_SOFTC_FROM_CTX(ctx, softc, instance) {		\
419 	(softc) = (dca_t *)(ctx)->cc_provider;			\
420 	(instance) = ddi_get_instance((softc)->dca_dip);	\
421 }
422 
423 #define	DCA_MECH_FROM_CTX(ctx) \
424 	(((dca_request_t *)(ctx)->cc_provider_private)->dr_ctx.ctx_cm_type)
425 
426 static int dca_bindchains_one(dca_request_t *reqp, size_t cnt, int dr_offset,
427     caddr_t kaddr, ddi_dma_handle_t handle, uint_t flags,
428     dca_chain_t *head, int *n_chain);
429 static uint64_t dca_ena(uint64_t ena);
430 static caddr_t dca_bufdaddr_out(crypto_data_t *data);
431 static char *dca_fma_eclass_string(char *model, dca_fma_eclass_t index);
432 static int dca_check_acc_handle(dca_t *dca, ddi_acc_handle_t handle,
433     dca_fma_eclass_t eclass_index);
434 
435 static void dca_fma_init(dca_t *dca);
436 static void dca_fma_fini(dca_t *dca);
437 static int dca_fm_error_cb(dev_info_t *dip, ddi_fm_error_t *err,
438     const void *impl_data);
439 
440 
441 static dca_device_t dca_devices[] = {
442 	/* Broadcom vanilla variants */
443 	{	0x14e4, 0x5820, "Broadcom 5820" },
444 	{	0x14e4, 0x5821, "Broadcom 5821" },
445 	{	0x14e4, 0x5822, "Broadcom 5822" },
446 	{	0x14e4, 0x5825, "Broadcom 5825" },
447 	/* Sun specific OEMd variants */
448 	{	0x108e, 0x5454, "SCA" },
449 	{	0x108e, 0x5455, "SCA 1000" },
450 	{	0x108e, 0x5457, "SCA 500" },
451 	/* subsysid should be 0x5457, but got 0x1 from HW. Assume both here. */
452 	{	0x108e, 0x1, "SCA 500" },
453 };
454 
455 /*
456  * Device attributes.
457  */
458 static struct ddi_device_acc_attr dca_regsattr = {
459 	DDI_DEVICE_ATTR_V1,
460 	DDI_STRUCTURE_LE_ACC,
461 	DDI_STRICTORDER_ACC,
462 	DDI_FLAGERR_ACC
463 };
464 
465 static struct ddi_device_acc_attr dca_devattr = {
466 	DDI_DEVICE_ATTR_V0,
467 	DDI_STRUCTURE_LE_ACC,
468 	DDI_STRICTORDER_ACC
469 };
470 
471 #if !defined(i386) && !defined(__i386)
472 static struct ddi_device_acc_attr dca_bufattr = {
473 	DDI_DEVICE_ATTR_V0,
474 	DDI_NEVERSWAP_ACC,
475 	DDI_STRICTORDER_ACC
476 };
477 #endif
478 
479 static struct ddi_dma_attr dca_dmaattr = {
480 	DMA_ATTR_V0,		/* dma_attr_version */
481 	0x0,			/* dma_attr_addr_lo */
482 	0xffffffffUL,		/* dma_attr_addr_hi */
483 	0x00ffffffUL,		/* dma_attr_count_max */
484 	0x40,			/* dma_attr_align */
485 	0x40,			/* dma_attr_burstsizes */
486 	0x1,			/* dma_attr_minxfer */
487 	0x00ffffffUL,		/* dma_attr_maxxfer */
488 	0xffffffffUL,		/* dma_attr_seg */
489 #if defined(i386) || defined(__i386) || defined(__amd64)
490 	512,			/* dma_attr_sgllen */
491 #else
492 	1,			/* dma_attr_sgllen */
493 #endif
494 	1,			/* dma_attr_granular */
495 	DDI_DMA_FLAGERR		/* dma_attr_flags */
496 };
497 
498 static void	*dca_state = NULL;
499 int	dca_mindma = 2500;
500 
501 /*
502  * FMA eclass string definitions. Note that these string arrays must be
503  * consistent with the dca_fma_eclass_t enum.
504  */
505 static char *dca_fma_eclass_sca1000[] = {
506 	"sca1000.hw.device",
507 	"sca1000.hw.timeout",
508 	"sca1000.none"
509 };
510 
511 static char *dca_fma_eclass_sca500[] = {
512 	"sca500.hw.device",
513 	"sca500.hw.timeout",
514 	"sca500.none"
515 };
516 
517 /*
518  * DDI entry points.
519  */
520 int
521 _init(void)
522 {
523 	int rv;
524 
525 	DBG(NULL, DMOD, "dca: in _init");
526 
527 	if ((rv = ddi_soft_state_init(&dca_state, sizeof (dca_t), 1)) != 0) {
528 		/* this should *never* happen! */
529 		return (rv);
530 	}
531 
532 	if ((rv = mod_install(&modlinkage)) != 0) {
533 		/* cleanup here */
534 		ddi_soft_state_fini(&dca_state);
535 		return (rv);
536 	}
537 
538 	return (0);
539 }
540 
541 int
542 _fini(void)
543 {
544 	int rv;
545 
546 	DBG(NULL, DMOD, "dca: in _fini");
547 
548 	if ((rv = mod_remove(&modlinkage)) == 0) {
549 		/* cleanup here */
550 		ddi_soft_state_fini(&dca_state);
551 	}
552 	return (rv);
553 }
554 
555 int
556 _info(struct modinfo *modinfop)
557 {
558 	DBG(NULL, DMOD, "dca: in _info");
559 
560 	return (mod_info(&modlinkage, modinfop));
561 }
562 
563 int
564 dca_attach(dev_info_t *dip, ddi_attach_cmd_t cmd)
565 {
566 	ddi_acc_handle_t	pci;
567 	int			instance;
568 	ddi_iblock_cookie_t	ibc;
569 	int			intr_added = 0;
570 	dca_t			*dca;
571 	ushort_t		venid;
572 	ushort_t		devid;
573 	ushort_t		revid;
574 	ushort_t		subsysid;
575 	ushort_t		subvenid;
576 	int			i;
577 	int			ret;
578 	char			ID[64];
579 	static char		*unknowndev = "Unknown device";
580 
581 #if DEBUG
582 	/* these are only used for debugging */
583 	ushort_t		pcicomm;
584 	ushort_t		pcistat;
585 	uchar_t			cachelinesz;
586 	uchar_t			mingnt;
587 	uchar_t			maxlat;
588 	uchar_t			lattmr;
589 #endif
590 
591 	instance = ddi_get_instance(dip);
592 
593 	DBG(NULL, DMOD, "dca: in dca_attach() for %d", instance);
594 
595 	switch (cmd) {
596 	case DDI_RESUME:
597 		if ((dca = (dca_t *)ddi_get_driver_private(dip)) == NULL) {
598 			dca_diperror(dip, "no soft state in detach");
599 			return (DDI_FAILURE);
600 		}
601 		/* assumption: we won't be DDI_DETACHed until we return */
602 		return (dca_resume(dca));
603 	case DDI_ATTACH:
604 		break;
605 	default:
606 		return (DDI_FAILURE);
607 	}
608 
609 	if (ddi_slaveonly(dip) == DDI_SUCCESS) {
610 		dca_diperror(dip, "slot does not support PCI bus-master");
611 		return (DDI_FAILURE);
612 	}
613 
614 	if (ddi_intr_hilevel(dip, 0) != 0) {
615 		dca_diperror(dip, "hilevel interrupts not supported");
616 		return (DDI_FAILURE);
617 	}
618 
619 	if (pci_config_setup(dip, &pci) != DDI_SUCCESS) {
620 		dca_diperror(dip, "unable to setup PCI config handle");
621 		return (DDI_FAILURE);
622 	}
623 
624 	/* common PCI attributes */
625 	venid = pci_config_get16(pci, PCI_VENID);
626 	devid = pci_config_get16(pci, PCI_DEVID);
627 	revid = pci_config_get8(pci, PCI_REVID);
628 	subvenid = pci_config_get16(pci, PCI_SUBVENID);
629 	subsysid = pci_config_get16(pci, PCI_SUBSYSID);
630 
631 	/*
632 	 * Broadcom-specific timings.
633 	 * We disable these timers/counters since they can cause
634 	 * incorrect false failures when the bus is just a little
635 	 * bit slow, or busy.
636 	 */
637 	pci_config_put8(pci, PCI_TRDYTO, 0);
638 	pci_config_put8(pci, PCI_RETRIES, 0);
639 
640 	/* initialize PCI access settings */
641 	pci_config_put16(pci, PCI_COMM, PCICOMM_SEE |
642 	    PCICOMM_PEE | PCICOMM_BME | PCICOMM_MAE);
643 
644 	/* set up our PCI latency timer */
645 	pci_config_put8(pci, PCI_LATTMR, 0x40);
646 
647 #if DEBUG
648 	/* read registers (for debugging) */
649 	pcicomm = pci_config_get16(pci, PCI_COMM);
650 	pcistat = pci_config_get16(pci, PCI_STATUS);
651 	cachelinesz = pci_config_get8(pci, PCI_CACHELINESZ);
652 	mingnt = pci_config_get8(pci, PCI_MINGNT);
653 	maxlat = pci_config_get8(pci, PCI_MAXLAT);
654 	lattmr = pci_config_get8(pci, PCI_LATTMR);
655 #endif
656 
657 	pci_config_teardown(&pci);
658 
659 	if (ddi_get_iblock_cookie(dip, 0, &ibc) != DDI_SUCCESS) {
660 		dca_diperror(dip, "unable to get iblock cookie");
661 		return (DDI_FAILURE);
662 	}
663 
664 	if (ddi_soft_state_zalloc(dca_state, instance) != DDI_SUCCESS) {
665 		dca_diperror(dip, "unable to allocate soft state");
666 		return (DDI_FAILURE);
667 	}
668 
669 	dca = ddi_get_soft_state(dca_state, instance);
670 	ASSERT(dca != NULL);
671 	dca->dca_dip = dip;
672 	WORKLIST(dca, MCR1)->dwl_prov = NULL;
673 	WORKLIST(dca, MCR2)->dwl_prov = NULL;
674 	/* figure pagesize */
675 	dca->dca_pagesize = ddi_ptob(dip, 1);
676 
677 	/*
678 	 * Search for the device in our supported devices table.  This
679 	 * is here for two reasons.  First, we want to ensure that
680 	 * only Sun-qualified (and presumably Sun-labeled) devices can
681 	 * be used with this driver.  Second, some devices have
682 	 * specific differences.  E.g. the 5821 has support for a
683 	 * special mode of RC4, deeper queues, power management, and
684 	 * other changes.  Also, the export versions of some of these
685 	 * chips don't support RC4 or 3DES, so we catch that here.
686 	 *
687 	 * Note that we only look at the upper nibble of the device
688 	 * id, which is used to distinguish export vs. domestic
689 	 * versions of the chip.  (The lower nibble is used for
690 	 * stepping information.)
691 	 */
692 	for (i = 0; i < (sizeof (dca_devices) / sizeof (dca_device_t)); i++) {
693 		/*
694 		 * Try to match the subsystem information first.
695 		 */
696 		if (subvenid && (subvenid == dca_devices[i].dd_vendor_id) &&
697 		    subsysid && (subsysid == dca_devices[i].dd_device_id)) {
698 			dca->dca_model = dca_devices[i].dd_model;
699 			dca->dca_devid = dca_devices[i].dd_device_id;
700 			break;
701 		}
702 		/*
703 		 * Failing that, try the generic vendor and device id.
704 		 * Even if we find a match, we keep searching anyway,
705 		 * since we would prefer to find a match based on the
706 		 * subsystem ids.
707 		 */
708 		if ((venid == dca_devices[i].dd_vendor_id) &&
709 		    (devid == dca_devices[i].dd_device_id)) {
710 			dca->dca_model = dca_devices[i].dd_model;
711 			dca->dca_devid = dca_devices[i].dd_device_id;
712 		}
713 	}
714 	/* try and handle an unrecognized device */
715 	if (dca->dca_model == NULL) {
716 		dca->dca_model = unknowndev;
717 		dca_error(dca, "device not recognized, not supported");
718 		DBG(dca, DPCI, "i=%d venid=%x devid=%x rev=%d",
719 		    i, venid, devid, revid);
720 	}
721 
722 	if (ddi_prop_update_string(DDI_DEV_T_NONE, dip, "description",
723 	    dca->dca_model) != DDI_SUCCESS) {
724 		dca_error(dca, "unable to create description property");
725 		return (DDI_FAILURE);
726 	}
727 
728 	DBG(dca, DPCI, "PCI command=0x%x status=%x cachelinesz=%x",
729 	    pcicomm, pcistat, cachelinesz);
730 	DBG(dca, DPCI, "mingnt=0x%x maxlat=0x%x lattmr=0x%x",
731 	    mingnt, maxlat, lattmr);
732 
733 	/*
734 	 * initialize locks, etc.
735 	 */
736 	(void) mutex_init(&dca->dca_intrlock, NULL, MUTEX_DRIVER, ibc);
737 
738 	/* use RNGSHA1 by default */
739 	if (ddi_getprop(DDI_DEV_T_ANY, dip,
740 	    DDI_PROP_CANSLEEP | DDI_PROP_DONTPASS, "rngdirect", 0) == 0) {
741 		dca->dca_flags |= DCA_RNGSHA1;
742 	}
743 
744 	/* initialize FMA */
745 	dca_fma_init(dca);
746 
747 	/* initialize some key data structures */
748 	if (dca_init(dca) != DDI_SUCCESS) {
749 		goto failed;
750 	}
751 
752 	/* initialize kstats */
753 	dca_ksinit(dca);
754 
755 	/* setup access to registers */
756 	if (ddi_regs_map_setup(dip, 1, (caddr_t *)&dca->dca_regs,
757 	    0, 0, &dca_regsattr, &dca->dca_regs_handle) != DDI_SUCCESS) {
758 		dca_error(dca, "unable to map registers");
759 		goto failed;
760 	}
761 
762 	DBG(dca, DCHATTY, "MCR1 = %x", GETCSR(dca, CSR_MCR1));
763 	DBG(dca, DCHATTY, "CONTROL = %x", GETCSR(dca, CSR_DMACTL));
764 	DBG(dca, DCHATTY, "STATUS = %x", GETCSR(dca, CSR_DMASTAT));
765 	DBG(dca, DCHATTY, "DMAEA = %x", GETCSR(dca, CSR_DMAEA));
766 	DBG(dca, DCHATTY, "MCR2 = %x", GETCSR(dca, CSR_MCR2));
767 
768 	/* reset the chip */
769 	if (dca_reset(dca, 0) < 0) {
770 		goto failed;
771 	}
772 
773 	/* initialize the chip */
774 	PUTCSR(dca, CSR_DMACTL, DMACTL_BE32 | DMACTL_BE64);
775 	if (dca_check_acc_handle(dca, dca->dca_regs_handle,
776 	    DCA_FM_ECLASS_NONE) != DDI_SUCCESS) {
777 		goto failed;
778 	}
779 
780 	/* add the interrupt */
781 	if (ddi_add_intr(dip, 0, &dca->dca_icookie, NULL, dca_intr,
782 	    (void *)dca) != DDI_SUCCESS) {
783 		DBG(dca, DWARN, "ddi_add_intr failed");
784 		goto failed;
785 	} else {
786 		intr_added = 1;
787 	}
788 
789 	/* enable interrupts on the device */
790 	/*
791 	 * XXX: Note, 5820A1 errata indicates that this may clobber
792 	 * bits 24 and 23, which affect the speed of the RNG.  Since
793 	 * we always want to run in full-speed mode, this should be
794 	 * harmless.
795 	 */
796 	if (dca->dca_devid == 0x5825) {
797 		/* for 5825 - increase the DMA read size */
798 		SETBIT(dca, CSR_DMACTL,
799 		    DMACTL_MCR1IE | DMACTL_MCR2IE | DMACTL_EIE | DMACTL_RD256);
800 	} else {
801 		SETBIT(dca, CSR_DMACTL,
802 		    DMACTL_MCR1IE | DMACTL_MCR2IE | DMACTL_EIE);
803 	}
804 	if (dca_check_acc_handle(dca, dca->dca_regs_handle,
805 	    DCA_FM_ECLASS_NONE) != DDI_SUCCESS) {
806 		goto failed;
807 	}
808 
809 	/* register MCR1 with the crypto framework */
810 	/* Be careful not to exceed 32 chars */
811 	(void) sprintf(ID, "%s/%d %s",
812 	    ddi_driver_name(dip), ddi_get_instance(dip), IDENT_SYM);
813 	dca_prov_info1.pi_provider_description = ID;
814 	dca_prov_info1.pi_provider_dev.pd_hw = dip;
815 	dca_prov_info1.pi_provider_handle = dca;
816 	if ((ret = crypto_register_provider(&dca_prov_info1,
817 	    &WORKLIST(dca, MCR1)->dwl_prov)) != CRYPTO_SUCCESS) {
818 		cmn_err(CE_WARN,
819 		    "crypto_register_provider() failed (%d) for MCR1", ret);
820 		goto failed;
821 	}
822 
823 	/* register MCR2 with the crypto framework */
824 	/* Be careful not to exceed 32 chars */
825 	(void) sprintf(ID, "%s/%d %s",
826 	    ddi_driver_name(dip), ddi_get_instance(dip), IDENT_ASYM);
827 	dca_prov_info2.pi_provider_description = ID;
828 	dca_prov_info2.pi_provider_dev.pd_hw = dip;
829 	dca_prov_info2.pi_provider_handle = dca;
830 	if ((ret = crypto_register_provider(&dca_prov_info2,
831 	    &WORKLIST(dca, MCR2)->dwl_prov)) != CRYPTO_SUCCESS) {
832 		cmn_err(CE_WARN,
833 		    "crypto_register_provider() failed (%d) for MCR2", ret);
834 		goto failed;
835 	}
836 
837 	crypto_prov_notify(WORKLIST(dca, MCR1)->dwl_prov,
838 	    CRYPTO_PROVIDER_READY);
839 	crypto_prov_notify(WORKLIST(dca, MCR2)->dwl_prov,
840 	    CRYPTO_PROVIDER_READY);
841 
842 	/* Initialize the local random number pool for this instance */
843 	if ((ret = dca_random_init(dca)) != CRYPTO_SUCCESS) {
844 		goto failed;
845 	}
846 
847 	mutex_enter(&dca->dca_intrlock);
848 	dca->dca_jobtid = timeout(dca_jobtimeout, (void *)dca,
849 	    drv_usectohz(SECOND));
850 	mutex_exit(&dca->dca_intrlock);
851 
852 	ddi_set_driver_private(dip, (caddr_t)dca);
853 
854 	ddi_report_dev(dip);
855 
856 	if (ddi_get_devstate(dca->dca_dip) != DDI_DEVSTATE_UP) {
857 		ddi_fm_service_impact(dca->dca_dip, DDI_SERVICE_RESTORED);
858 	}
859 
860 	return (DDI_SUCCESS);
861 
862 failed:
863 	/* unregister from the crypto framework */
864 	if (WORKLIST(dca, MCR1)->dwl_prov != NULL) {
865 		(void) crypto_unregister_provider(
866 		    WORKLIST(dca, MCR1)->dwl_prov);
867 	}
868 	if (WORKLIST(dca, MCR2)->dwl_prov != NULL) {
869 		(void) crypto_unregister_provider(
870 		    WORKLIST(dca, MCR2)->dwl_prov);
871 	}
872 	if (intr_added) {
873 		CLRBIT(dca, CSR_DMACTL,
874 		    DMACTL_MCR1IE | DMACTL_MCR2IE | DMACTL_EIE);
875 		/* unregister intr handler */
876 		ddi_remove_intr(dip, 0, dca->dca_icookie);
877 	}
878 	if (dca->dca_regs_handle) {
879 		ddi_regs_map_free(&dca->dca_regs_handle);
880 	}
881 	if (dca->dca_intrstats) {
882 		kstat_delete(dca->dca_intrstats);
883 	}
884 	if (dca->dca_ksp) {
885 		kstat_delete(dca->dca_ksp);
886 	}
887 	dca_uninit(dca);
888 
889 	/* finalize FMA */
890 	dca_fma_fini(dca);
891 
892 	mutex_destroy(&dca->dca_intrlock);
893 	ddi_soft_state_free(dca_state, instance);
894 	return (DDI_FAILURE);
895 
896 }
897 
898 int
899 dca_detach(dev_info_t *dip, ddi_detach_cmd_t cmd)
900 {
901 	int		instance;
902 	dca_t		*dca;
903 	timeout_id_t	tid;
904 
905 	instance = ddi_get_instance(dip);
906 
907 	DBG(NULL, DMOD, "dca: in dca_detach() for %d", instance);
908 
909 	switch (cmd) {
910 	case DDI_SUSPEND:
911 		if ((dca = (dca_t *)ddi_get_driver_private(dip)) == NULL) {
912 			dca_diperror(dip, "no soft state in detach");
913 			return (DDI_FAILURE);
914 		}
915 		/* assumption: we won't be DDI_DETACHed until we return */
916 		return (dca_suspend(dca));
917 
918 	case DDI_DETACH:
919 		break;
920 	default:
921 		return (DDI_FAILURE);
922 	}
923 
924 	if ((dca = (dca_t *)ddi_get_driver_private(dip)) == NULL) {
925 		dca_diperror(dip, "no soft state in detach");
926 		return (DDI_FAILURE);
927 	}
928 
929 	/*
930 	 * Unregister from kCF.
931 	 * This needs to be done at the beginning of detach.
932 	 */
933 	if (WORKLIST(dca, MCR1)->dwl_prov != NULL) {
934 		if (crypto_unregister_provider(
935 		    WORKLIST(dca, MCR1)->dwl_prov) != CRYPTO_SUCCESS) {
936 			dca_error(dca, "unable to unregister MCR1 from kcf");
937 			return (DDI_FAILURE);
938 		}
939 	}
940 
941 	if (WORKLIST(dca, MCR2)->dwl_prov != NULL) {
942 		if (crypto_unregister_provider(
943 		    WORKLIST(dca, MCR2)->dwl_prov) != CRYPTO_SUCCESS) {
944 			dca_error(dca, "unable to unregister MCR2 from kcf");
945 			return (DDI_FAILURE);
946 		}
947 	}
948 
949 	/*
950 	 * Cleanup the private context list. Once the
951 	 * crypto_unregister_provider returns, it is safe to do so.
952 	 */
953 	dca_free_context_list(dca);
954 
955 	/* Cleanup the local random number pool */
956 	dca_random_fini(dca);
957 
958 	/* send any jobs in the waitq back to kCF */
959 	dca_rejectjobs(dca);
960 
961 	/* untimeout the timeouts */
962 	mutex_enter(&dca->dca_intrlock);
963 	tid = dca->dca_jobtid;
964 	dca->dca_jobtid = 0;
965 	mutex_exit(&dca->dca_intrlock);
966 	if (tid) {
967 		(void) untimeout(tid);
968 	}
969 
970 	/* disable device interrupts */
971 	CLRBIT(dca, CSR_DMACTL, DMACTL_MCR1IE | DMACTL_MCR2IE | DMACTL_EIE);
972 
973 	/* unregister interrupt handlers */
974 	ddi_remove_intr(dip, 0, dca->dca_icookie);
975 
976 	/* release our regs handle */
977 	ddi_regs_map_free(&dca->dca_regs_handle);
978 
979 	/* toss out kstats */
980 	if (dca->dca_intrstats) {
981 		kstat_delete(dca->dca_intrstats);
982 	}
983 	if (dca->dca_ksp) {
984 		kstat_delete(dca->dca_ksp);
985 	}
986 
987 	mutex_destroy(&dca->dca_intrlock);
988 	dca_uninit(dca);
989 
990 	/* finalize FMA */
991 	dca_fma_fini(dca);
992 
993 	ddi_soft_state_free(dca_state, instance);
994 
995 	return (DDI_SUCCESS);
996 }
997 
998 int
999 dca_resume(dca_t *dca)
1000 {
1001 	ddi_acc_handle_t	pci;
1002 
1003 	if (pci_config_setup(dca->dca_dip, &pci) != DDI_SUCCESS) {
1004 		dca_error(dca, "unable to setup PCI config handle");
1005 		return (DDI_FAILURE);
1006 	}
1007 
1008 	/*
1009 	 * Reprogram registers in PCI configuration space.
1010 	 */
1011 
1012 	/* Broadcom-specific timers -- we disable them. */
1013 	pci_config_put8(pci, PCI_TRDYTO, 0);
1014 	pci_config_put8(pci, PCI_RETRIES, 0);
1015 
1016 	/* initialize PCI access settings */
1017 	pci_config_put16(pci, PCI_COMM, PCICOMM_SEE |
1018 	    PCICOMM_PEE | PCICOMM_BME | PCICOMM_MAE);
1019 
1020 	/* set up our PCI latency timer */
1021 	pci_config_put8(pci, PCI_LATTMR, 0x40);
1022 
1023 	pci_config_teardown(&pci);
1024 
1025 	if (dca_reset(dca, 0) < 0) {
1026 		dca_error(dca, "unable to reset device during resume");
1027 		return (DDI_FAILURE);
1028 	}
1029 
1030 	/*
1031 	 * Now restore the card-specific CSRs.
1032 	 */
1033 
1034 	/* restore endianness settings */
1035 	PUTCSR(dca, CSR_DMACTL, DMACTL_BE32 | DMACTL_BE64);
1036 	if (dca_check_acc_handle(dca, dca->dca_regs_handle,
1037 	    DCA_FM_ECLASS_NONE) != DDI_SUCCESS)
1038 		return (DDI_FAILURE);
1039 
1040 	/* restore interrupt enables */
1041 	if (dca->dca_devid == 0x5825) {
1042 		/* for 5825 set 256 byte read size to improve performance */
1043 		SETBIT(dca, CSR_DMACTL,
1044 		    DMACTL_MCR1IE | DMACTL_MCR2IE | DMACTL_EIE | DMACTL_RD256);
1045 	} else {
1046 		SETBIT(dca, CSR_DMACTL,
1047 		    DMACTL_MCR1IE | DMACTL_MCR2IE | DMACTL_EIE);
1048 	}
1049 	if (dca_check_acc_handle(dca, dca->dca_regs_handle,
1050 	    DCA_FM_ECLASS_NONE) != DDI_SUCCESS)
1051 		return (DDI_FAILURE);
1052 
1053 	/* resume scheduling jobs on the device */
1054 	dca_undrain(dca);
1055 
1056 	return (DDI_SUCCESS);
1057 }
1058 
1059 int
1060 dca_suspend(dca_t *dca)
1061 {
1062 	if ((dca_drain(dca)) != 0) {
1063 		return (DDI_FAILURE);
1064 	}
1065 	if (dca_reset(dca, 0) < 0) {
1066 		dca_error(dca, "unable to reset device during suspend");
1067 		return (DDI_FAILURE);
1068 	}
1069 	return (DDI_SUCCESS);
1070 }
1071 
1072 /*
1073  * Hardware access stuff.
1074  */
1075 int
1076 dca_reset(dca_t *dca, int failreset)
1077 {
1078 	int i;
1079 
1080 	if (dca->dca_regs_handle == NULL) {
1081 		return (-1);
1082 	}
1083 
1084 	PUTCSR(dca, CSR_DMACTL, DMACTL_RESET);
1085 	if (!failreset) {
1086 		if (dca_check_acc_handle(dca, dca->dca_regs_handle,
1087 		    DCA_FM_ECLASS_NONE) != DDI_SUCCESS)
1088 			return (-1);
1089 	}
1090 
1091 	/* now wait for a reset */
1092 	for (i = 1; i < 100; i++) {
1093 		uint32_t	dmactl;
1094 		drv_usecwait(100);
1095 		dmactl = GETCSR(dca, CSR_DMACTL);
1096 		if (!failreset) {
1097 			if (dca_check_acc_handle(dca, dca->dca_regs_handle,
1098 			    DCA_FM_ECLASS_NONE) != DDI_SUCCESS)
1099 				return (-1);
1100 		}
1101 		if ((dmactl & DMACTL_RESET) == 0) {
1102 			DBG(dca, DCHATTY, "reset in %d usec", i * 100);
1103 			return (0);
1104 		}
1105 	}
1106 	if (!failreset) {
1107 		dca_failure(dca, DDI_DEVICE_FAULT,
1108 		    DCA_FM_ECLASS_NONE, dca_ena(0), CRYPTO_DEVICE_ERROR,
1109 		    "timeout waiting for reset after %d usec", i * 100);
1110 	}
1111 	return (-1);
1112 }
1113 
1114 int
1115 dca_initworklist(dca_t *dca, dca_worklist_t *wlp)
1116 {
1117 	int	i;
1118 	int	reqprealloc = wlp->dwl_hiwater + (MAXWORK * MAXREQSPERMCR);
1119 
1120 	/*
1121 	 * Set up work queue.
1122 	 */
1123 	mutex_init(&wlp->dwl_lock, NULL, MUTEX_DRIVER, dca->dca_icookie);
1124 	mutex_init(&wlp->dwl_freereqslock, NULL, MUTEX_DRIVER,
1125 	    dca->dca_icookie);
1126 	mutex_init(&wlp->dwl_freelock, NULL, MUTEX_DRIVER, dca->dca_icookie);
1127 	cv_init(&wlp->dwl_cv, NULL, CV_DRIVER, NULL);
1128 
1129 	mutex_enter(&wlp->dwl_lock);
1130 
1131 	dca_initq(&wlp->dwl_freereqs);
1132 	dca_initq(&wlp->dwl_waitq);
1133 	dca_initq(&wlp->dwl_freework);
1134 	dca_initq(&wlp->dwl_runq);
1135 
1136 	for (i = 0; i < MAXWORK; i++) {
1137 		dca_work_t		*workp;
1138 
1139 		if ((workp = dca_newwork(dca)) == NULL) {
1140 			dca_error(dca, "unable to allocate work");
1141 			mutex_exit(&wlp->dwl_lock);
1142 			return (DDI_FAILURE);
1143 		}
1144 		workp->dw_wlp = wlp;
1145 		dca_freework(workp);
1146 	}
1147 	mutex_exit(&wlp->dwl_lock);
1148 
1149 	for (i = 0; i < reqprealloc; i++) {
1150 		dca_request_t *reqp;
1151 
1152 		if ((reqp = dca_newreq(dca)) == NULL) {
1153 			dca_error(dca, "unable to allocate request");
1154 			return (DDI_FAILURE);
1155 		}
1156 		reqp->dr_dca = dca;
1157 		reqp->dr_wlp = wlp;
1158 		dca_freereq(reqp);
1159 	}
1160 	return (DDI_SUCCESS);
1161 }
1162 
1163 int
1164 dca_init(dca_t *dca)
1165 {
1166 	dca_worklist_t		*wlp;
1167 
1168 	/* Initialize the private context list and the corresponding lock. */
1169 	mutex_init(&dca->dca_ctx_list_lock, NULL, MUTEX_DRIVER, NULL);
1170 	dca_initq(&dca->dca_ctx_list);
1171 
1172 	/*
1173 	 * MCR1 algorithms.
1174 	 */
1175 	wlp = WORKLIST(dca, MCR1);
1176 	(void) sprintf(wlp->dwl_name, "dca%d:mcr1",
1177 	    ddi_get_instance(dca->dca_dip));
1178 	wlp->dwl_lowater = ddi_getprop(DDI_DEV_T_ANY,
1179 	    dca->dca_dip, DDI_PROP_CANSLEEP | DDI_PROP_DONTPASS,
1180 	    "mcr1_lowater", MCR1LOWATER);
1181 	wlp->dwl_hiwater = ddi_getprop(DDI_DEV_T_ANY,
1182 	    dca->dca_dip, DDI_PROP_CANSLEEP | DDI_PROP_DONTPASS,
1183 	    "mcr1_hiwater", MCR1HIWATER);
1184 	wlp->dwl_reqspermcr = min(ddi_getprop(DDI_DEV_T_ANY,
1185 	    dca->dca_dip, DDI_PROP_CANSLEEP | DDI_PROP_DONTPASS,
1186 	    "mcr1_maxreqs", MCR1MAXREQS), MAXREQSPERMCR);
1187 	wlp->dwl_dca = dca;
1188 	wlp->dwl_mcr = MCR1;
1189 	if (dca_initworklist(dca, wlp) != DDI_SUCCESS) {
1190 		return (DDI_FAILURE);
1191 	}
1192 
1193 	/*
1194 	 * MCR2 algorithms.
1195 	 */
1196 	wlp = WORKLIST(dca, MCR2);
1197 	(void) sprintf(wlp->dwl_name, "dca%d:mcr2",
1198 	    ddi_get_instance(dca->dca_dip));
1199 	wlp->dwl_lowater = ddi_getprop(DDI_DEV_T_ANY,
1200 	    dca->dca_dip, DDI_PROP_CANSLEEP | DDI_PROP_DONTPASS,
1201 	    "mcr2_lowater", MCR2LOWATER);
1202 	wlp->dwl_hiwater = ddi_getprop(DDI_DEV_T_ANY,
1203 	    dca->dca_dip, DDI_PROP_CANSLEEP | DDI_PROP_DONTPASS,
1204 	    "mcr2_hiwater", MCR2HIWATER);
1205 	wlp->dwl_reqspermcr = min(ddi_getprop(DDI_DEV_T_ANY,
1206 	    dca->dca_dip, DDI_PROP_CANSLEEP | DDI_PROP_DONTPASS,
1207 	    "mcr2_maxreqs", MCR2MAXREQS), MAXREQSPERMCR);
1208 	wlp->dwl_dca = dca;
1209 	wlp->dwl_mcr = MCR2;
1210 	if (dca_initworklist(dca, wlp) != DDI_SUCCESS) {
1211 		return (DDI_FAILURE);
1212 	}
1213 	return (DDI_SUCCESS);
1214 }
1215 
1216 /*
1217  * Uninitialize worklists.  This routine should only be called when no
1218  * active jobs (hence DMA mappings) exist.  One way to ensure this is
1219  * to unregister from kCF before calling this routine.  (This is done
1220  * e.g. in detach(9e).)
1221  */
1222 void
1223 dca_uninit(dca_t *dca)
1224 {
1225 	int	mcr;
1226 
1227 	mutex_destroy(&dca->dca_ctx_list_lock);
1228 
1229 	for (mcr = MCR1; mcr <= MCR2; mcr++) {
1230 		dca_worklist_t	*wlp = WORKLIST(dca, mcr);
1231 		dca_work_t	*workp;
1232 		dca_request_t	*reqp;
1233 
1234 		if (dca->dca_regs_handle == NULL) {
1235 			continue;
1236 		}
1237 
1238 		mutex_enter(&wlp->dwl_lock);
1239 		while ((workp = dca_getwork(dca, mcr)) != NULL) {
1240 			dca_destroywork(workp);
1241 		}
1242 		mutex_exit(&wlp->dwl_lock);
1243 		while ((reqp = dca_getreq(dca, mcr, 0)) != NULL) {
1244 			dca_destroyreq(reqp);
1245 		}
1246 
1247 		mutex_destroy(&wlp->dwl_lock);
1248 		mutex_destroy(&wlp->dwl_freereqslock);
1249 		mutex_destroy(&wlp->dwl_freelock);
1250 		cv_destroy(&wlp->dwl_cv);
1251 		wlp->dwl_prov = NULL;
1252 	}
1253 }
1254 
1255 static void
1256 dca_enlist2(dca_listnode_t *q, dca_listnode_t *node, kmutex_t *lock)
1257 {
1258 	if (!q || !node)
1259 		return;
1260 
1261 	mutex_enter(lock);
1262 	node->dl_next2 = q;
1263 	node->dl_prev2 = q->dl_prev2;
1264 	node->dl_next2->dl_prev2 = node;
1265 	node->dl_prev2->dl_next2 = node;
1266 	mutex_exit(lock);
1267 }
1268 
1269 static void
1270 dca_rmlist2(dca_listnode_t *node, kmutex_t *lock)
1271 {
1272 	if (!node)
1273 		return;
1274 
1275 	mutex_enter(lock);
1276 	node->dl_next2->dl_prev2 = node->dl_prev2;
1277 	node->dl_prev2->dl_next2 = node->dl_next2;
1278 	node->dl_next2 = NULL;
1279 	node->dl_prev2 = NULL;
1280 	mutex_exit(lock);
1281 }
1282 
1283 static dca_listnode_t *
1284 dca_delist2(dca_listnode_t *q, kmutex_t *lock)
1285 {
1286 	dca_listnode_t *node;
1287 
1288 	mutex_enter(lock);
1289 	if ((node = q->dl_next2) == q) {
1290 		mutex_exit(lock);
1291 		return (NULL);
1292 	}
1293 
1294 	node->dl_next2->dl_prev2 = node->dl_prev2;
1295 	node->dl_prev2->dl_next2 = node->dl_next2;
1296 	node->dl_next2 = NULL;
1297 	node->dl_prev2 = NULL;
1298 	mutex_exit(lock);
1299 
1300 	return (node);
1301 }
1302 
1303 void
1304 dca_initq(dca_listnode_t *q)
1305 {
1306 	q->dl_next = q;
1307 	q->dl_prev = q;
1308 	q->dl_next2 = q;
1309 	q->dl_prev2 = q;
1310 }
1311 
1312 void
1313 dca_enqueue(dca_listnode_t *q, dca_listnode_t *node)
1314 {
1315 	/*
1316 	 * Enqueue submits at the "tail" of the list, i.e. just
1317 	 * behind the sentinel.
1318 	 */
1319 	node->dl_next = q;
1320 	node->dl_prev = q->dl_prev;
1321 	node->dl_next->dl_prev = node;
1322 	node->dl_prev->dl_next = node;
1323 }
1324 
1325 void
1326 dca_rmqueue(dca_listnode_t *node)
1327 {
1328 	node->dl_next->dl_prev = node->dl_prev;
1329 	node->dl_prev->dl_next = node->dl_next;
1330 	node->dl_next = NULL;
1331 	node->dl_prev = NULL;
1332 }
1333 
1334 dca_listnode_t *
1335 dca_dequeue(dca_listnode_t *q)
1336 {
1337 	dca_listnode_t *node;
1338 	/*
1339 	 * Dequeue takes from the "head" of the list, i.e. just after
1340 	 * the sentinel.
1341 	 */
1342 	if ((node = q->dl_next) == q) {
1343 		/* queue is empty */
1344 		return (NULL);
1345 	}
1346 	dca_rmqueue(node);
1347 	return (node);
1348 }
1349 
1350 /* this is the opposite of dequeue, it takes things off in LIFO order */
1351 dca_listnode_t *
1352 dca_unqueue(dca_listnode_t *q)
1353 {
1354 	dca_listnode_t *node;
1355 	/*
1356 	 * unqueue takes from the "tail" of the list, i.e. just before
1357 	 * the sentinel.
1358 	 */
1359 	if ((node = q->dl_prev) == q) {
1360 		/* queue is empty */
1361 		return (NULL);
1362 	}
1363 	dca_rmqueue(node);
1364 	return (node);
1365 }
1366 
1367 dca_listnode_t *
1368 dca_peekqueue(dca_listnode_t *q)
1369 {
1370 	dca_listnode_t *node;
1371 
1372 	if ((node = q->dl_next) == q) {
1373 		return (NULL);
1374 	} else {
1375 		return (node);
1376 	}
1377 }
1378 
1379 /*
1380  * Interrupt service routine.
1381  */
1382 uint_t
1383 dca_intr(char *arg)
1384 {
1385 	dca_t		*dca = (dca_t *)arg;
1386 	uint32_t	status;
1387 
1388 	mutex_enter(&dca->dca_intrlock);
1389 	status = GETCSR(dca, CSR_DMASTAT);
1390 	PUTCSR(dca, CSR_DMASTAT, status & DMASTAT_INTERRUPTS);
1391 	if (dca_check_acc_handle(dca, dca->dca_regs_handle,
1392 	    DCA_FM_ECLASS_NONE) != DDI_SUCCESS) {
1393 		mutex_exit(&dca->dca_intrlock);
1394 		return ((uint_t)DDI_FAILURE);
1395 	}
1396 
1397 	DBG(dca, DINTR, "interrupted, status = 0x%x!", status);
1398 
1399 	if ((status & DMASTAT_INTERRUPTS) == 0) {
1400 		/* increment spurious interrupt kstat */
1401 		if (dca->dca_intrstats) {
1402 			KIOIP(dca)->intrs[KSTAT_INTR_SPURIOUS]++;
1403 		}
1404 		mutex_exit(&dca->dca_intrlock);
1405 		return (DDI_INTR_UNCLAIMED);
1406 	}
1407 
1408 	if (dca->dca_intrstats) {
1409 		KIOIP(dca)->intrs[KSTAT_INTR_HARD]++;
1410 	}
1411 	if (status & DMASTAT_MCR1INT) {
1412 		DBG(dca, DINTR, "MCR1 interrupted");
1413 		mutex_enter(&(WORKLIST(dca, MCR1)->dwl_lock));
1414 		dca_schedule(dca, MCR1);
1415 		dca_reclaim(dca, MCR1);
1416 		mutex_exit(&(WORKLIST(dca, MCR1)->dwl_lock));
1417 	}
1418 
1419 	if (status & DMASTAT_MCR2INT) {
1420 		DBG(dca, DINTR, "MCR2 interrupted");
1421 		mutex_enter(&(WORKLIST(dca, MCR2)->dwl_lock));
1422 		dca_schedule(dca, MCR2);
1423 		dca_reclaim(dca, MCR2);
1424 		mutex_exit(&(WORKLIST(dca, MCR2)->dwl_lock));
1425 	}
1426 
1427 	if (status & DMASTAT_ERRINT) {
1428 		uint32_t	erraddr;
1429 		erraddr = GETCSR(dca, CSR_DMAEA);
1430 		mutex_exit(&dca->dca_intrlock);
1431 
1432 		/*
1433 		 * bit 1 of the error address indicates failure during
1434 		 * read if set, during write otherwise.
1435 		 */
1436 		dca_failure(dca, DDI_DEVICE_FAULT,
1437 		    DCA_FM_ECLASS_HW_DEVICE, dca_ena(0), CRYPTO_DEVICE_ERROR,
1438 		    "DMA master access error %s address 0x%x",
1439 		    erraddr & 0x1 ? "reading" : "writing", erraddr & ~1);
1440 		return (DDI_INTR_CLAIMED);
1441 	}
1442 
1443 	mutex_exit(&dca->dca_intrlock);
1444 
1445 	return (DDI_INTR_CLAIMED);
1446 }
1447 
1448 /*
1449  * Reverse a string of bytes from s1 into s2.  The reversal happens
1450  * from the tail of s1.  If len1 < len2, then null bytes will be
1451  * padded to the end of s2.  If len2 < len1, then (presumably null)
1452  * bytes will be dropped from the start of s1.
1453  *
1454  * The rationale here is that when s1 (source) is shorter, then we
1455  * are reversing from big-endian ordering, into device ordering, and
1456  * want to add some extra nulls to the tail (MSB) side of the device.
1457  *
1458  * Similarly, when s2 (dest) is shorter, then we are truncating what
1459  * are presumably null MSB bits from the device.
1460  *
1461  * There is an expectation when reversing from the device back into
1462  * big-endian, that the number of bytes to reverse and the target size
1463  * will match, and no truncation or padding occurs.
1464  */
1465 void
1466 dca_reverse(void *s1, void *s2, int len1, int len2)
1467 {
1468 	caddr_t	src, dst;
1469 
1470 	if (len1 == 0) {
1471 		if (len2) {
1472 			bzero(s2, len2);
1473 		}
1474 		return;
1475 	}
1476 	src = (caddr_t)s1 + len1 - 1;
1477 	dst = s2;
1478 	while ((src >= (caddr_t)s1) && (len2)) {
1479 		*dst++ = *src--;
1480 		len2--;
1481 	}
1482 	while (len2 > 0) {
1483 		*dst++ = 0;
1484 		len2--;
1485 	}
1486 }
1487 
1488 uint16_t
1489 dca_padfull(int num)
1490 {
1491 	if (num <= 512) {
1492 		return (BITS2BYTES(512));
1493 	}
1494 	if (num <= 768) {
1495 		return (BITS2BYTES(768));
1496 	}
1497 	if (num <= 1024) {
1498 		return (BITS2BYTES(1024));
1499 	}
1500 	if (num <= 1536) {
1501 		return (BITS2BYTES(1536));
1502 	}
1503 	if (num <= 2048) {
1504 		return (BITS2BYTES(2048));
1505 	}
1506 	return (0);
1507 }
1508 
1509 uint16_t
1510 dca_padhalf(int num)
1511 {
1512 	if (num <= 256) {
1513 		return (BITS2BYTES(256));
1514 	}
1515 	if (num <= 384) {
1516 		return (BITS2BYTES(384));
1517 	}
1518 	if (num <= 512) {
1519 		return (BITS2BYTES(512));
1520 	}
1521 	if (num <= 768) {
1522 		return (BITS2BYTES(768));
1523 	}
1524 	if (num <= 1024) {
1525 		return (BITS2BYTES(1024));
1526 	}
1527 	return (0);
1528 }
1529 
1530 dca_work_t *
1531 dca_newwork(dca_t *dca)
1532 {
1533 	dca_work_t		*workp;
1534 	size_t			size;
1535 	ddi_dma_cookie_t	c;
1536 	unsigned		nc;
1537 	int			rv;
1538 
1539 	workp = kmem_zalloc(sizeof (dca_work_t), KM_SLEEP);
1540 
1541 	rv = ddi_dma_alloc_handle(dca->dca_dip, &dca_dmaattr,
1542 	    DDI_DMA_SLEEP, NULL, &workp->dw_mcr_dmah);
1543 	if (rv != 0) {
1544 		dca_error(dca, "unable to alloc MCR DMA handle");
1545 		dca_destroywork(workp);
1546 		return (NULL);
1547 	}
1548 
1549 	rv = ddi_dma_mem_alloc(workp->dw_mcr_dmah,
1550 	    ROUNDUP(MCR_SIZE, dca->dca_pagesize),
1551 	    &dca_devattr, DDI_DMA_CONSISTENT, DDI_DMA_SLEEP, NULL,
1552 	    &workp->dw_mcr_kaddr, &size, &workp->dw_mcr_acch);
1553 	if (rv != 0) {
1554 		dca_error(dca, "unable to alloc MCR DMA memory");
1555 		dca_destroywork(workp);
1556 		return (NULL);
1557 	}
1558 
1559 	rv = ddi_dma_addr_bind_handle(workp->dw_mcr_dmah, NULL,
1560 	    workp->dw_mcr_kaddr, size, DDI_DMA_CONSISTENT | DDI_DMA_RDWR,
1561 	    DDI_DMA_SLEEP, NULL, &c, &nc);
1562 	if (rv != DDI_DMA_MAPPED) {
1563 		dca_error(dca, "unable to map MCR DMA memory");
1564 		dca_destroywork(workp);
1565 		return (NULL);
1566 	}
1567 
1568 	workp->dw_mcr_paddr = c.dmac_address;
1569 	return (workp);
1570 }
1571 
1572 void
1573 dca_destroywork(dca_work_t *workp)
1574 {
1575 	if (workp->dw_mcr_paddr) {
1576 		(void) ddi_dma_unbind_handle(workp->dw_mcr_dmah);
1577 	}
1578 	if (workp->dw_mcr_acch) {
1579 		ddi_dma_mem_free(&workp->dw_mcr_acch);
1580 	}
1581 	if (workp->dw_mcr_dmah) {
1582 		ddi_dma_free_handle(&workp->dw_mcr_dmah);
1583 	}
1584 	kmem_free(workp, sizeof (dca_work_t));
1585 }
1586 
1587 dca_request_t *
1588 dca_newreq(dca_t *dca)
1589 {
1590 	dca_request_t		*reqp;
1591 	size_t			size;
1592 	ddi_dma_cookie_t	c;
1593 	unsigned		nc;
1594 	int			rv;
1595 	int			n_chain = 0;
1596 
1597 	size = (DESC_SIZE * MAXFRAGS) + CTX_MAXLENGTH;
1598 
1599 	reqp = kmem_zalloc(sizeof (dca_request_t), KM_SLEEP);
1600 
1601 	reqp->dr_dca = dca;
1602 
1603 	/*
1604 	 * Setup the DMA region for the context and descriptors.
1605 	 */
1606 	rv = ddi_dma_alloc_handle(dca->dca_dip, &dca_dmaattr, DDI_DMA_SLEEP,
1607 	    NULL, &reqp->dr_ctx_dmah);
1608 	if (rv != DDI_SUCCESS) {
1609 		dca_error(dca, "failure allocating request DMA handle");
1610 		dca_destroyreq(reqp);
1611 		return (NULL);
1612 	}
1613 
1614 	/* for driver hardening, allocate in whole pages */
1615 	rv = ddi_dma_mem_alloc(reqp->dr_ctx_dmah,
1616 	    ROUNDUP(size, dca->dca_pagesize), &dca_devattr, DDI_DMA_CONSISTENT,
1617 	    DDI_DMA_SLEEP, NULL, &reqp->dr_ctx_kaddr, &size,
1618 	    &reqp->dr_ctx_acch);
1619 	if (rv != DDI_SUCCESS) {
1620 		dca_error(dca, "unable to alloc request DMA memory");
1621 		dca_destroyreq(reqp);
1622 		return (NULL);
1623 	}
1624 
1625 	rv = ddi_dma_addr_bind_handle(reqp->dr_ctx_dmah, NULL,
1626 	    reqp->dr_ctx_kaddr, size, DDI_DMA_CONSISTENT | DDI_DMA_WRITE,
1627 	    DDI_DMA_SLEEP, 0, &c, &nc);
1628 	if (rv != DDI_DMA_MAPPED) {
1629 		dca_error(dca, "failed binding request DMA handle");
1630 		dca_destroyreq(reqp);
1631 		return (NULL);
1632 	}
1633 	reqp->dr_ctx_paddr = c.dmac_address;
1634 
1635 	reqp->dr_dma_size = size;
1636 
1637 	/*
1638 	 * Set up the dma for our scratch/shared buffers.
1639 	 */
1640 	rv = ddi_dma_alloc_handle(dca->dca_dip, &dca_dmaattr,
1641 	    DDI_DMA_SLEEP, NULL, &reqp->dr_ibuf_dmah);
1642 	if (rv != DDI_SUCCESS) {
1643 		dca_error(dca, "failure allocating ibuf DMA handle");
1644 		dca_destroyreq(reqp);
1645 		return (NULL);
1646 	}
1647 	rv = ddi_dma_alloc_handle(dca->dca_dip, &dca_dmaattr,
1648 	    DDI_DMA_SLEEP, NULL, &reqp->dr_obuf_dmah);
1649 	if (rv != DDI_SUCCESS) {
1650 		dca_error(dca, "failure allocating obuf DMA handle");
1651 		dca_destroyreq(reqp);
1652 		return (NULL);
1653 	}
1654 
1655 	rv = ddi_dma_alloc_handle(dca->dca_dip, &dca_dmaattr,
1656 	    DDI_DMA_SLEEP, NULL, &reqp->dr_chain_in_dmah);
1657 	if (rv != DDI_SUCCESS) {
1658 		dca_error(dca, "failure allocating chain_in DMA handle");
1659 		dca_destroyreq(reqp);
1660 		return (NULL);
1661 	}
1662 
1663 	rv = ddi_dma_alloc_handle(dca->dca_dip, &dca_dmaattr,
1664 	    DDI_DMA_SLEEP, NULL, &reqp->dr_chain_out_dmah);
1665 	if (rv != DDI_SUCCESS) {
1666 		dca_error(dca, "failure allocating chain_out DMA handle");
1667 		dca_destroyreq(reqp);
1668 		return (NULL);
1669 	}
1670 
1671 	/*
1672 	 * for driver hardening, allocate in whole pages.
1673 	 */
1674 	size = ROUNDUP(MAXPACKET, dca->dca_pagesize);
1675 #if defined(i386) || defined(__i386)
1676 	/*
1677 	 * Use kmem_alloc instead of ddi_dma_mem_alloc here since the latter
1678 	 * may fail on x86 platform if a physically contiguous memory chunk
1679 	 * cannot be found. From initial testing, we did not see performance
1680 	 * degradation as seen on Sparc.
1681 	 */
1682 	if ((reqp->dr_ibuf_kaddr = kmem_alloc(size, KM_SLEEP)) == NULL) {
1683 		dca_error(dca, "unable to alloc request ibuf memory");
1684 		dca_destroyreq(reqp);
1685 		return (NULL);
1686 	}
1687 	if ((reqp->dr_obuf_kaddr = kmem_alloc(size, KM_SLEEP)) == NULL) {
1688 		dca_error(dca, "unable to alloc request obuf memory");
1689 		dca_destroyreq(reqp);
1690 		return (NULL);
1691 	}
1692 #else
1693 	/*
1694 	 * We could kmem_alloc for Sparc too. However, it gives worse
1695 	 * performance when transferring more than one page data. For example,
1696 	 * using 4 threads and 12032 byte data and 3DES on 900MHZ Sparc system,
1697 	 * kmem_alloc uses 80% CPU and ddi_dma_mem_alloc uses 50% CPU for
1698 	 * the same throughput.
1699 	 */
1700 	rv = ddi_dma_mem_alloc(reqp->dr_ibuf_dmah,
1701 	    size, &dca_bufattr,
1702 	    DDI_DMA_STREAMING, DDI_DMA_SLEEP, NULL, &reqp->dr_ibuf_kaddr,
1703 	    &size, &reqp->dr_ibuf_acch);
1704 	if (rv != DDI_SUCCESS) {
1705 		dca_error(dca, "unable to alloc request DMA memory");
1706 		dca_destroyreq(reqp);
1707 		return (NULL);
1708 	}
1709 
1710 	rv = ddi_dma_mem_alloc(reqp->dr_obuf_dmah,
1711 	    size, &dca_bufattr,
1712 	    DDI_DMA_STREAMING, DDI_DMA_SLEEP, NULL, &reqp->dr_obuf_kaddr,
1713 	    &size, &reqp->dr_obuf_acch);
1714 	if (rv != DDI_SUCCESS) {
1715 		dca_error(dca, "unable to alloc request DMA memory");
1716 		dca_destroyreq(reqp);
1717 		return (NULL);
1718 	}
1719 #endif
1720 
1721 	/* Skip the used portion in the context page */
1722 	reqp->dr_offset = CTX_MAXLENGTH;
1723 	if ((rv = dca_bindchains_one(reqp, size, reqp->dr_offset,
1724 	    reqp->dr_ibuf_kaddr, reqp->dr_ibuf_dmah,
1725 	    DDI_DMA_WRITE | DDI_DMA_STREAMING,
1726 	    &reqp->dr_ibuf_head, &n_chain)) != DDI_SUCCESS) {
1727 		(void) dca_destroyreq(reqp);
1728 		return (NULL);
1729 	}
1730 	reqp->dr_ibuf_paddr = reqp->dr_ibuf_head.dc_buffer_paddr;
1731 	/* Skip the space used by the input buffer */
1732 	reqp->dr_offset += DESC_SIZE * n_chain;
1733 
1734 	if ((rv = dca_bindchains_one(reqp, size, reqp->dr_offset,
1735 	    reqp->dr_obuf_kaddr, reqp->dr_obuf_dmah,
1736 	    DDI_DMA_READ | DDI_DMA_STREAMING,
1737 	    &reqp->dr_obuf_head, &n_chain)) != DDI_SUCCESS) {
1738 		(void) dca_destroyreq(reqp);
1739 		return (NULL);
1740 	}
1741 	reqp->dr_obuf_paddr = reqp->dr_obuf_head.dc_buffer_paddr;
1742 	/* Skip the space used by the output buffer */
1743 	reqp->dr_offset += DESC_SIZE * n_chain;
1744 
1745 	DBG(dca, DCHATTY, "CTX is 0x%p, phys 0x%x, len %d",
1746 	    reqp->dr_ctx_kaddr, reqp->dr_ctx_paddr, CTX_MAXLENGTH);
1747 	return (reqp);
1748 }
1749 
1750 void
1751 dca_destroyreq(dca_request_t *reqp)
1752 {
1753 #if defined(i386) || defined(__i386)
1754 	dca_t		*dca = reqp->dr_dca;
1755 	size_t		size = ROUNDUP(MAXPACKET, dca->dca_pagesize);
1756 #endif
1757 
1758 	/*
1759 	 * Clean up DMA for the context structure.
1760 	 */
1761 	if (reqp->dr_ctx_paddr) {
1762 		(void) ddi_dma_unbind_handle(reqp->dr_ctx_dmah);
1763 	}
1764 
1765 	if (reqp->dr_ctx_acch) {
1766 		ddi_dma_mem_free(&reqp->dr_ctx_acch);
1767 	}
1768 
1769 	if (reqp->dr_ctx_dmah) {
1770 		ddi_dma_free_handle(&reqp->dr_ctx_dmah);
1771 	}
1772 
1773 	/*
1774 	 * Clean up DMA for the scratch buffer.
1775 	 */
1776 #if defined(i386) || defined(__i386)
1777 	if (reqp->dr_ibuf_dmah) {
1778 		(void) ddi_dma_unbind_handle(reqp->dr_ibuf_dmah);
1779 		ddi_dma_free_handle(&reqp->dr_ibuf_dmah);
1780 	}
1781 	if (reqp->dr_obuf_dmah) {
1782 		(void) ddi_dma_unbind_handle(reqp->dr_obuf_dmah);
1783 		ddi_dma_free_handle(&reqp->dr_obuf_dmah);
1784 	}
1785 
1786 	kmem_free(reqp->dr_ibuf_kaddr, size);
1787 	kmem_free(reqp->dr_obuf_kaddr, size);
1788 #else
1789 	if (reqp->dr_ibuf_paddr) {
1790 		(void) ddi_dma_unbind_handle(reqp->dr_ibuf_dmah);
1791 	}
1792 	if (reqp->dr_obuf_paddr) {
1793 		(void) ddi_dma_unbind_handle(reqp->dr_obuf_dmah);
1794 	}
1795 
1796 	if (reqp->dr_ibuf_acch) {
1797 		ddi_dma_mem_free(&reqp->dr_ibuf_acch);
1798 	}
1799 	if (reqp->dr_obuf_acch) {
1800 		ddi_dma_mem_free(&reqp->dr_obuf_acch);
1801 	}
1802 
1803 	if (reqp->dr_ibuf_dmah) {
1804 		ddi_dma_free_handle(&reqp->dr_ibuf_dmah);
1805 	}
1806 	if (reqp->dr_obuf_dmah) {
1807 		ddi_dma_free_handle(&reqp->dr_obuf_dmah);
1808 	}
1809 #endif
1810 	/*
1811 	 * These two DMA handles should have been unbinded in
1812 	 * dca_unbindchains() function
1813 	 */
1814 	if (reqp->dr_chain_in_dmah) {
1815 		ddi_dma_free_handle(&reqp->dr_chain_in_dmah);
1816 	}
1817 	if (reqp->dr_chain_out_dmah) {
1818 		ddi_dma_free_handle(&reqp->dr_chain_out_dmah);
1819 	}
1820 
1821 	kmem_free(reqp, sizeof (dca_request_t));
1822 }
1823 
1824 dca_work_t *
1825 dca_getwork(dca_t *dca, int mcr)
1826 {
1827 	dca_worklist_t	*wlp = WORKLIST(dca, mcr);
1828 	dca_work_t	*workp;
1829 
1830 	mutex_enter(&wlp->dwl_freelock);
1831 	workp = (dca_work_t *)dca_dequeue(&wlp->dwl_freework);
1832 	mutex_exit(&wlp->dwl_freelock);
1833 	if (workp) {
1834 		int	nreqs;
1835 		bzero(workp->dw_mcr_kaddr, 8);
1836 
1837 		/* clear out old requests */
1838 		for (nreqs = 0; nreqs < MAXREQSPERMCR; nreqs++) {
1839 			workp->dw_reqs[nreqs] = NULL;
1840 		}
1841 	}
1842 	return (workp);
1843 }
1844 
1845 void
1846 dca_freework(dca_work_t *workp)
1847 {
1848 	mutex_enter(&workp->dw_wlp->dwl_freelock);
1849 	dca_enqueue(&workp->dw_wlp->dwl_freework, (dca_listnode_t *)workp);
1850 	mutex_exit(&workp->dw_wlp->dwl_freelock);
1851 }
1852 
1853 dca_request_t *
1854 dca_getreq(dca_t *dca, int mcr, int tryhard)
1855 {
1856 	dca_worklist_t	*wlp = WORKLIST(dca, mcr);
1857 	dca_request_t	*reqp;
1858 
1859 	mutex_enter(&wlp->dwl_freereqslock);
1860 	reqp = (dca_request_t *)dca_dequeue(&wlp->dwl_freereqs);
1861 	mutex_exit(&wlp->dwl_freereqslock);
1862 	if (reqp) {
1863 		reqp->dr_flags = 0;
1864 		reqp->dr_callback = NULL;
1865 	} else if (tryhard) {
1866 		/*
1867 		 * failed to get a free one, try an allocation, the hard way.
1868 		 * XXX: Kstat desired here.
1869 		 */
1870 		if ((reqp = dca_newreq(dca)) != NULL) {
1871 			reqp->dr_wlp = wlp;
1872 			reqp->dr_dca = dca;
1873 			reqp->dr_flags = 0;
1874 			reqp->dr_callback = NULL;
1875 		}
1876 	}
1877 	return (reqp);
1878 }
1879 
1880 void
1881 dca_freereq(dca_request_t *reqp)
1882 {
1883 	reqp->dr_kcf_req = NULL;
1884 	if (!(reqp->dr_flags & DR_NOCACHE)) {
1885 		mutex_enter(&reqp->dr_wlp->dwl_freereqslock);
1886 		dca_enqueue(&reqp->dr_wlp->dwl_freereqs,
1887 		    (dca_listnode_t *)reqp);
1888 		mutex_exit(&reqp->dr_wlp->dwl_freereqslock);
1889 	}
1890 }
1891 
1892 /*
1893  * Binds user buffers to DMA handles dynamically. On Sparc, a user buffer
1894  * is mapped to a single physical address. On x86, a user buffer is mapped
1895  * to multiple physical addresses. These physical addresses are chained
1896  * using the method specified in Broadcom BCM5820 specification.
1897  */
1898 int
1899 dca_bindchains(dca_request_t *reqp, size_t incnt, size_t outcnt)
1900 {
1901 	int			rv;
1902 	caddr_t			kaddr;
1903 	uint_t			flags;
1904 	int			n_chain = 0;
1905 
1906 	if (reqp->dr_flags & DR_INPLACE) {
1907 		flags = DDI_DMA_RDWR | DDI_DMA_CONSISTENT;
1908 	} else {
1909 		flags = DDI_DMA_WRITE | DDI_DMA_STREAMING;
1910 	}
1911 
1912 	/* first the input */
1913 	if (incnt) {
1914 		if ((kaddr = dca_bufdaddr(reqp->dr_in)) == NULL) {
1915 			DBG(NULL, DWARN, "unrecognised crypto data format");
1916 			return (DDI_FAILURE);
1917 		}
1918 		if ((rv = dca_bindchains_one(reqp, incnt, reqp->dr_offset,
1919 		    kaddr, reqp->dr_chain_in_dmah, flags,
1920 		    &reqp->dr_chain_in_head, &n_chain)) != DDI_SUCCESS) {
1921 			(void) dca_unbindchains(reqp);
1922 			return (rv);
1923 		}
1924 
1925 		/*
1926 		 * The offset and length are altered by the calling routine
1927 		 * reqp->dr_in->cd_offset += incnt;
1928 		 * reqp->dr_in->cd_length -= incnt;
1929 		 */
1930 		/* Save the first one in the chain for MCR */
1931 		reqp->dr_in_paddr = reqp->dr_chain_in_head.dc_buffer_paddr;
1932 		reqp->dr_in_next = reqp->dr_chain_in_head.dc_next_paddr;
1933 		reqp->dr_in_len = reqp->dr_chain_in_head.dc_buffer_length;
1934 	} else {
1935 		reqp->dr_in_paddr = NULL;
1936 		reqp->dr_in_next = 0;
1937 		reqp->dr_in_len = 0;
1938 	}
1939 
1940 	if (reqp->dr_flags & DR_INPLACE) {
1941 		reqp->dr_out_paddr = reqp->dr_in_paddr;
1942 		reqp->dr_out_len = reqp->dr_in_len;
1943 		reqp->dr_out_next = reqp->dr_in_next;
1944 		return (DDI_SUCCESS);
1945 	}
1946 
1947 	/* then the output */
1948 	if (outcnt) {
1949 		flags = DDI_DMA_READ | DDI_DMA_STREAMING;
1950 		if ((kaddr = dca_bufdaddr_out(reqp->dr_out)) == NULL) {
1951 			DBG(NULL, DWARN, "unrecognised crypto data format");
1952 			(void) dca_unbindchains(reqp);
1953 			return (DDI_FAILURE);
1954 		}
1955 		rv = dca_bindchains_one(reqp, outcnt, reqp->dr_offset +
1956 		    n_chain * DESC_SIZE, kaddr, reqp->dr_chain_out_dmah,
1957 		    flags, &reqp->dr_chain_out_head, &n_chain);
1958 		if (rv != DDI_SUCCESS) {
1959 			(void) dca_unbindchains(reqp);
1960 			return (DDI_FAILURE);
1961 		}
1962 
1963 		/* Save the first one in the chain for MCR */
1964 		reqp->dr_out_paddr = reqp->dr_chain_out_head.dc_buffer_paddr;
1965 		reqp->dr_out_next = reqp->dr_chain_out_head.dc_next_paddr;
1966 		reqp->dr_out_len = reqp->dr_chain_out_head.dc_buffer_length;
1967 	} else {
1968 		reqp->dr_out_paddr = NULL;
1969 		reqp->dr_out_next = 0;
1970 		reqp->dr_out_len = 0;
1971 	}
1972 
1973 	return (DDI_SUCCESS);
1974 }
1975 
1976 /*
1977  * Unbind the user buffers from the DMA handles.
1978  */
1979 int
1980 dca_unbindchains(dca_request_t *reqp)
1981 {
1982 	int rv = DDI_SUCCESS;
1983 	int rv1 = DDI_SUCCESS;
1984 
1985 	/* Clear the input chain */
1986 	if (reqp->dr_chain_in_head.dc_buffer_paddr != NULL) {
1987 		(void) ddi_dma_unbind_handle(reqp->dr_chain_in_dmah);
1988 		reqp->dr_chain_in_head.dc_buffer_paddr = 0;
1989 	}
1990 
1991 	if (reqp->dr_flags & DR_INPLACE) {
1992 		return (rv);
1993 	}
1994 
1995 	/* Clear the output chain */
1996 	if (reqp->dr_chain_out_head.dc_buffer_paddr != NULL) {
1997 		(void) ddi_dma_unbind_handle(reqp->dr_chain_out_dmah);
1998 		reqp->dr_chain_out_head.dc_buffer_paddr = 0;
1999 	}
2000 
2001 	return ((rv != DDI_SUCCESS)? rv : rv1);
2002 }
2003 
2004 /*
2005  * Build either input chain or output chain. It is single-item chain for Sparc,
2006  * and possible mutiple-item chain for x86.
2007  */
2008 static int
2009 dca_bindchains_one(dca_request_t *reqp, size_t cnt, int dr_offset,
2010     caddr_t kaddr, ddi_dma_handle_t handle, uint_t flags,
2011     dca_chain_t *head, int *n_chain)
2012 {
2013 	ddi_dma_cookie_t	c;
2014 	uint_t			nc;
2015 	int			rv;
2016 	caddr_t			chain_kaddr_pre;
2017 	caddr_t			chain_kaddr;
2018 	uint32_t		chain_paddr;
2019 	int 			i;
2020 
2021 	/* Advance past the context structure to the starting address */
2022 	chain_paddr = reqp->dr_ctx_paddr + dr_offset;
2023 	chain_kaddr = reqp->dr_ctx_kaddr + dr_offset;
2024 
2025 	/*
2026 	 * Bind the kernel address to the DMA handle. On x86, the actual
2027 	 * buffer is mapped into multiple physical addresses. On Sparc,
2028 	 * the actual buffer is mapped into a single address.
2029 	 */
2030 	rv = ddi_dma_addr_bind_handle(handle,
2031 	    NULL, kaddr, cnt, flags, DDI_DMA_DONTWAIT, NULL, &c, &nc);
2032 	if (rv != DDI_DMA_MAPPED) {
2033 		return (DDI_FAILURE);
2034 	}
2035 
2036 	(void) ddi_dma_sync(handle, 0, cnt, DDI_DMA_SYNC_FORDEV);
2037 	if ((rv = dca_check_dma_handle(reqp->dr_dca, handle,
2038 	    DCA_FM_ECLASS_NONE)) != DDI_SUCCESS) {
2039 		reqp->destroy = TRUE;
2040 		return (rv);
2041 	}
2042 
2043 	*n_chain = nc;
2044 
2045 	/* Setup the data buffer chain for DMA transfer */
2046 	chain_kaddr_pre = NULL;
2047 	head->dc_buffer_paddr = 0;
2048 	head->dc_next_paddr = 0;
2049 	head->dc_buffer_length = 0;
2050 	for (i = 0; i < nc; i++) {
2051 		/* PIO */
2052 		PUTDESC32(reqp, chain_kaddr, DESC_BUFADDR, c.dmac_address);
2053 		PUTDESC16(reqp, chain_kaddr, DESC_RSVD, 0);
2054 		PUTDESC16(reqp, chain_kaddr, DESC_LENGTH, c.dmac_size);
2055 
2056 		/* Remember the head of the chain */
2057 		if (head->dc_buffer_paddr == 0) {
2058 			head->dc_buffer_paddr = c.dmac_address;
2059 			head->dc_buffer_length = c.dmac_size;
2060 		}
2061 
2062 		/* Link to the previous one if one exists */
2063 		if (chain_kaddr_pre) {
2064 			PUTDESC32(reqp, chain_kaddr_pre, DESC_NEXT,
2065 			    chain_paddr);
2066 			if (head->dc_next_paddr == 0)
2067 				head->dc_next_paddr = chain_paddr;
2068 		}
2069 		chain_kaddr_pre = chain_kaddr;
2070 
2071 		/* Maintain pointers */
2072 		chain_paddr += DESC_SIZE;
2073 		chain_kaddr += DESC_SIZE;
2074 
2075 		/* Retrieve the next cookie if there is one */
2076 		if (i < nc-1)
2077 			ddi_dma_nextcookie(handle, &c);
2078 	}
2079 
2080 	/* Set the next pointer in the last entry to NULL */
2081 	PUTDESC32(reqp, chain_kaddr_pre, DESC_NEXT, 0);
2082 
2083 	return (DDI_SUCCESS);
2084 }
2085 
2086 /*
2087  * Schedule some work.
2088  */
2089 int
2090 dca_start(dca_t *dca, dca_request_t *reqp, int mcr, int dosched)
2091 {
2092 	dca_worklist_t	*wlp = WORKLIST(dca, mcr);
2093 
2094 	mutex_enter(&wlp->dwl_lock);
2095 
2096 	DBG(dca, DCHATTY, "req=%p, in=%p, out=%p, ctx=%p, ibuf=%p, obuf=%p",
2097 	    reqp, reqp->dr_in, reqp->dr_out, reqp->dr_ctx_kaddr,
2098 	    reqp->dr_ibuf_kaddr, reqp->dr_obuf_kaddr);
2099 	DBG(dca, DCHATTY, "ctx paddr = %x, ibuf paddr = %x, obuf paddr = %x",
2100 	    reqp->dr_ctx_paddr, reqp->dr_ibuf_paddr, reqp->dr_obuf_paddr);
2101 	/* sync out the entire context and descriptor chains */
2102 	(void) ddi_dma_sync(reqp->dr_ctx_dmah, 0, 0, DDI_DMA_SYNC_FORDEV);
2103 	if (dca_check_dma_handle(dca, reqp->dr_ctx_dmah,
2104 	    DCA_FM_ECLASS_NONE) != DDI_SUCCESS) {
2105 		reqp->destroy = TRUE;
2106 		mutex_exit(&wlp->dwl_lock);
2107 		return (CRYPTO_DEVICE_ERROR);
2108 	}
2109 
2110 	dca_enqueue(&wlp->dwl_waitq, (dca_listnode_t *)reqp);
2111 	wlp->dwl_count++;
2112 	wlp->dwl_lastsubmit = ddi_get_lbolt();
2113 	reqp->dr_wlp = wlp;
2114 
2115 	if ((wlp->dwl_count == wlp->dwl_hiwater) && (wlp->dwl_busy == 0)) {
2116 		/* we are fully loaded now, let kCF know */
2117 
2118 		wlp->dwl_flowctl++;
2119 		wlp->dwl_busy = 1;
2120 
2121 		crypto_prov_notify(wlp->dwl_prov, CRYPTO_PROVIDER_BUSY);
2122 	}
2123 
2124 	if (dosched) {
2125 #ifdef	SCHEDDELAY
2126 		/* possibly wait for more work to arrive */
2127 		if (wlp->dwl_count >= wlp->dwl_reqspermcr) {
2128 			dca_schedule(dca, mcr);
2129 		} else if (!wlp->dwl_schedtid) {
2130 			/* wait 1 msec for more work before doing it */
2131 			wlp->dwl_schedtid = timeout(dca_schedtimeout,
2132 			    (void *)wlp, drv_usectohz(MSEC));
2133 		}
2134 #else
2135 		dca_schedule(dca, mcr);
2136 #endif
2137 	}
2138 	mutex_exit(&wlp->dwl_lock);
2139 
2140 	return (CRYPTO_QUEUED);
2141 }
2142 
2143 void
2144 dca_schedule(dca_t *dca, int mcr)
2145 {
2146 	dca_worklist_t	*wlp = WORKLIST(dca, mcr);
2147 	int		csr;
2148 	int		full;
2149 	uint32_t	status;
2150 
2151 	ASSERT(mutex_owned(&wlp->dwl_lock));
2152 	/*
2153 	 * If the card is draining or has an outstanding failure,
2154 	 * don't schedule any more work on it right now
2155 	 */
2156 	if (wlp->dwl_drain || (dca->dca_flags & DCA_FAILED)) {
2157 		return;
2158 	}
2159 
2160 	if (mcr == MCR2) {
2161 		csr = CSR_MCR2;
2162 		full = DMASTAT_MCR2FULL;
2163 	} else {
2164 		csr = CSR_MCR1;
2165 		full = DMASTAT_MCR1FULL;
2166 	}
2167 
2168 	for (;;) {
2169 		dca_work_t	*workp;
2170 		uint32_t	offset;
2171 		int		nreqs;
2172 
2173 		status = GETCSR(dca, CSR_DMASTAT);
2174 		if (dca_check_acc_handle(dca, dca->dca_regs_handle,
2175 		    DCA_FM_ECLASS_NONE) != DDI_SUCCESS)
2176 			return;
2177 
2178 		if ((status & full) != 0)
2179 			break;
2180 
2181 #ifdef	SCHEDDELAY
2182 		/* if there isn't enough to do, don't bother now */
2183 		if ((wlp->dwl_count < wlp->dwl_reqspermcr) &&
2184 		    (ddi_get_lbolt() < (wlp->dwl_lastsubmit +
2185 		    drv_usectohz(MSEC)))) {
2186 			/* wait a bit longer... */
2187 			if (wlp->dwl_schedtid == 0) {
2188 				wlp->dwl_schedtid = timeout(dca_schedtimeout,
2189 				    (void *)wlp, drv_usectohz(MSEC));
2190 			}
2191 			return;
2192 		}
2193 #endif
2194 
2195 		/* grab a work structure */
2196 		workp = dca_getwork(dca, mcr);
2197 
2198 		if (workp == NULL) {
2199 			/*
2200 			 * There must be work ready to be reclaimed,
2201 			 * in this case, since the chip can only hold
2202 			 * less work outstanding than there are total.
2203 			 */
2204 			dca_reclaim(dca, mcr);
2205 			continue;
2206 		}
2207 
2208 		nreqs = 0;
2209 		offset = MCR_CTXADDR;
2210 
2211 		while (nreqs < wlp->dwl_reqspermcr) {
2212 			dca_request_t	*reqp;
2213 
2214 			reqp = (dca_request_t *)dca_dequeue(&wlp->dwl_waitq);
2215 			if (reqp == NULL) {
2216 				/* nothing left to process */
2217 				break;
2218 			}
2219 			/*
2220 			 * Update flow control.
2221 			 */
2222 			wlp->dwl_count--;
2223 			if ((wlp->dwl_count == wlp->dwl_lowater) &&
2224 			    (wlp->dwl_busy))  {
2225 				wlp->dwl_busy = 0;
2226 				crypto_prov_notify(wlp->dwl_prov,
2227 				    CRYPTO_PROVIDER_READY);
2228 			}
2229 
2230 			/*
2231 			 * Context address.
2232 			 */
2233 			PUTMCR32(workp, offset, reqp->dr_ctx_paddr);
2234 			offset += 4;
2235 
2236 			/*
2237 			 * Input chain.
2238 			 */
2239 			/* input buffer address */
2240 			PUTMCR32(workp, offset, reqp->dr_in_paddr);
2241 			offset += 4;
2242 			/* next input buffer entry */
2243 			PUTMCR32(workp, offset, reqp->dr_in_next);
2244 			offset += 4;
2245 			/* input buffer length */
2246 			PUTMCR16(workp, offset, reqp->dr_in_len);
2247 			offset += 2;
2248 			/* zero the reserved field */
2249 			PUTMCR16(workp, offset, 0);
2250 			offset += 2;
2251 
2252 			/*
2253 			 * Overall length.
2254 			 */
2255 			/* reserved field */
2256 			PUTMCR16(workp, offset, 0);
2257 			offset += 2;
2258 			/* total packet length */
2259 			PUTMCR16(workp, offset, reqp->dr_pkt_length);
2260 			offset += 2;
2261 
2262 			/*
2263 			 * Output chain.
2264 			 */
2265 			/* output buffer address */
2266 			PUTMCR32(workp, offset, reqp->dr_out_paddr);
2267 			offset += 4;
2268 			/* next output buffer entry */
2269 			PUTMCR32(workp, offset, reqp->dr_out_next);
2270 			offset += 4;
2271 			/* output buffer length */
2272 			PUTMCR16(workp, offset, reqp->dr_out_len);
2273 			offset += 2;
2274 			/* zero the reserved field */
2275 			PUTMCR16(workp, offset, 0);
2276 			offset += 2;
2277 
2278 			/*
2279 			 * Note submission.
2280 			 */
2281 			workp->dw_reqs[nreqs] = reqp;
2282 			nreqs++;
2283 		}
2284 
2285 		if (nreqs == 0) {
2286 			/* nothing in the queue! */
2287 			dca_freework(workp);
2288 			return;
2289 		}
2290 
2291 		wlp->dwl_submit++;
2292 
2293 		PUTMCR16(workp, MCR_FLAGS, 0);
2294 		PUTMCR16(workp, MCR_COUNT, nreqs);
2295 
2296 		DBG(dca, DCHATTY,
2297 		    "posting work (phys %x, virt 0x%p) (%d reqs) to MCR%d",
2298 		    workp->dw_mcr_paddr, workp->dw_mcr_kaddr,
2299 		    nreqs, mcr);
2300 
2301 		workp->dw_lbolt = ddi_get_lbolt();
2302 		/* Make sure MCR is synced out to device. */
2303 		(void) ddi_dma_sync(workp->dw_mcr_dmah, 0, 0,
2304 		    DDI_DMA_SYNC_FORDEV);
2305 		if (dca_check_dma_handle(dca, workp->dw_mcr_dmah,
2306 		    DCA_FM_ECLASS_NONE) != DDI_SUCCESS) {
2307 			dca_destroywork(workp);
2308 			return;
2309 		}
2310 
2311 		PUTCSR(dca, csr, workp->dw_mcr_paddr);
2312 		if (dca_check_acc_handle(dca, dca->dca_regs_handle,
2313 		    DCA_FM_ECLASS_NONE) != DDI_SUCCESS) {
2314 			dca_destroywork(workp);
2315 			return;
2316 		} else {
2317 			dca_enqueue(&wlp->dwl_runq, (dca_listnode_t *)workp);
2318 		}
2319 
2320 		DBG(dca, DCHATTY, "posted");
2321 	}
2322 }
2323 
2324 /*
2325  * Reclaim completed work, called in interrupt context.
2326  */
2327 void
2328 dca_reclaim(dca_t *dca, int mcr)
2329 {
2330 	dca_worklist_t	*wlp = WORKLIST(dca, mcr);
2331 	dca_work_t	*workp;
2332 	ushort_t	flags;
2333 	int		nreclaimed = 0;
2334 	int		i;
2335 
2336 	DBG(dca, DRECLAIM, "worklist = 0x%p (MCR%d)", wlp, mcr);
2337 	ASSERT(mutex_owned(&wlp->dwl_lock));
2338 	/*
2339 	 * For each MCR in the submitted (runq), we check to see if
2340 	 * it has been processed.  If so, then we note each individual
2341 	 * job in the MCR, and and do the completion processing for
2342 	 * each of such job.
2343 	 */
2344 	for (;;) {
2345 
2346 		workp = (dca_work_t *)dca_peekqueue(&wlp->dwl_runq);
2347 		if (workp == NULL) {
2348 			break;
2349 		}
2350 
2351 		/* only sync the MCR flags, since that's all we need */
2352 		(void) ddi_dma_sync(workp->dw_mcr_dmah, 0, 4,
2353 		    DDI_DMA_SYNC_FORKERNEL);
2354 		if (dca_check_dma_handle(dca, workp->dw_mcr_dmah,
2355 		    DCA_FM_ECLASS_NONE) != DDI_SUCCESS) {
2356 			dca_rmqueue((dca_listnode_t *)workp);
2357 			dca_destroywork(workp);
2358 			return;
2359 		}
2360 
2361 		flags = GETMCR16(workp, MCR_FLAGS);
2362 		if ((flags & MCRFLAG_FINISHED) == 0) {
2363 			/* chip is still working on it */
2364 			DBG(dca, DRECLAIM,
2365 			    "chip still working on it (MCR%d)", mcr);
2366 			break;
2367 		}
2368 
2369 		/* its really for us, so remove it from the queue */
2370 		dca_rmqueue((dca_listnode_t *)workp);
2371 
2372 		/* if we were draining, signal on the cv */
2373 		if (wlp->dwl_drain && QEMPTY(&wlp->dwl_runq)) {
2374 			cv_signal(&wlp->dwl_cv);
2375 		}
2376 
2377 		/* update statistics, done under the lock */
2378 		for (i = 0; i < wlp->dwl_reqspermcr; i++) {
2379 			dca_request_t *reqp = workp->dw_reqs[i];
2380 			if (reqp == NULL) {
2381 				continue;
2382 			}
2383 			if (reqp->dr_byte_stat >= 0) {
2384 				dca->dca_stats[reqp->dr_byte_stat] +=
2385 				    reqp->dr_pkt_length;
2386 			}
2387 			if (reqp->dr_job_stat >= 0) {
2388 				dca->dca_stats[reqp->dr_job_stat]++;
2389 			}
2390 		}
2391 		mutex_exit(&wlp->dwl_lock);
2392 
2393 		for (i = 0; i < wlp->dwl_reqspermcr; i++) {
2394 			dca_request_t *reqp = workp->dw_reqs[i];
2395 
2396 			if (reqp == NULL) {
2397 				continue;
2398 			}
2399 
2400 			/* Do the callback. */
2401 			workp->dw_reqs[i] = NULL;
2402 			dca_done(reqp, CRYPTO_SUCCESS);
2403 
2404 			nreclaimed++;
2405 		}
2406 
2407 		/* now we can release the work */
2408 		dca_freework(workp);
2409 
2410 		mutex_enter(&wlp->dwl_lock);
2411 	}
2412 	DBG(dca, DRECLAIM, "reclaimed %d cmds", nreclaimed);
2413 }
2414 
2415 int
2416 dca_length(crypto_data_t *cdata)
2417 {
2418 	return (cdata->cd_length);
2419 }
2420 
2421 /*
2422  * This is the callback function called from the interrupt when a kCF job
2423  * completes.  It does some driver-specific things, and then calls the
2424  * kCF-provided callback.  Finally, it cleans up the state for the work
2425  * request and drops the reference count to allow for DR.
2426  */
2427 void
2428 dca_done(dca_request_t *reqp, int err)
2429 {
2430 	uint64_t	ena = 0;
2431 
2432 	/* unbind any chains we were using */
2433 	if (dca_unbindchains(reqp) != DDI_SUCCESS) {
2434 		/* DMA failure */
2435 		ena = dca_ena(ena);
2436 		dca_failure(reqp->dr_dca, DDI_DATAPATH_FAULT,
2437 		    DCA_FM_ECLASS_NONE, ena, CRYPTO_DEVICE_ERROR,
2438 		    "fault on buffer DMA handle");
2439 		if (err == CRYPTO_SUCCESS) {
2440 			err = CRYPTO_DEVICE_ERROR;
2441 		}
2442 	}
2443 
2444 	if (reqp->dr_callback != NULL) {
2445 		reqp->dr_callback(reqp, err);
2446 	} else {
2447 		dca_freereq(reqp);
2448 	}
2449 }
2450 
2451 /*
2452  * Call this when a failure is detected.  It will reset the chip,
2453  * log a message, alert kCF, and mark jobs in the runq as failed.
2454  */
2455 /* ARGSUSED */
2456 void
2457 dca_failure(dca_t *dca, ddi_fault_location_t loc, dca_fma_eclass_t index,
2458     uint64_t ena, int errno, char *mess, ...)
2459 {
2460 	va_list	ap;
2461 	char	buf[256];
2462 	int	mcr;
2463 	char	*eclass;
2464 	int	have_mutex;
2465 
2466 	va_start(ap, mess);
2467 	(void) vsprintf(buf, mess, ap);
2468 	va_end(ap);
2469 
2470 	eclass = dca_fma_eclass_string(dca->dca_model, index);
2471 
2472 	if (DDI_FM_EREPORT_CAP(dca->fm_capabilities) &&
2473 	    index != DCA_FM_ECLASS_NONE) {
2474 		ddi_fm_ereport_post(dca->dca_dip, eclass, ena,
2475 		    DDI_NOSLEEP, FM_VERSION, DATA_TYPE_UINT8,
2476 		    FM_EREPORT_VERS0, NULL);
2477 
2478 		/* Report the impact of the failure to the DDI. */
2479 		ddi_fm_service_impact(dca->dca_dip, DDI_SERVICE_LOST);
2480 	} else {
2481 		/* Just log the error string to the message log */
2482 		dca_error(dca, buf);
2483 	}
2484 
2485 	/*
2486 	 * Indicate a failure (keeps schedule from running).
2487 	 */
2488 	dca->dca_flags |= DCA_FAILED;
2489 
2490 	/*
2491 	 * Reset the chip.  This should also have as a side effect, the
2492 	 * disabling of all interrupts from the device.
2493 	 */
2494 	(void) dca_reset(dca, 1);
2495 
2496 	/*
2497 	 * Report the failure to kCF.
2498 	 */
2499 	for (mcr = MCR1; mcr <= MCR2; mcr++) {
2500 		if (WORKLIST(dca, mcr)->dwl_prov) {
2501 			crypto_prov_notify(WORKLIST(dca, mcr)->dwl_prov,
2502 			    CRYPTO_PROVIDER_FAILED);
2503 		}
2504 	}
2505 
2506 	/*
2507 	 * Return jobs not sent to hardware back to kCF.
2508 	 */
2509 	dca_rejectjobs(dca);
2510 
2511 	/*
2512 	 * From this point on, no new work should be arriving, and the
2513 	 * chip should not be doing any active DMA.
2514 	 */
2515 
2516 	/*
2517 	 * Now find all the work submitted to the device and fail
2518 	 * them.
2519 	 */
2520 	for (mcr = MCR1; mcr <= MCR2; mcr++) {
2521 		dca_worklist_t	*wlp;
2522 		int		i;
2523 
2524 		wlp = WORKLIST(dca, mcr);
2525 
2526 		if (wlp == NULL || wlp->dwl_waitq.dl_prev == NULL) {
2527 			continue;
2528 		}
2529 		for (;;) {
2530 			dca_work_t	*workp;
2531 
2532 			have_mutex = mutex_tryenter(&wlp->dwl_lock);
2533 			workp = (dca_work_t *)dca_dequeue(&wlp->dwl_runq);
2534 			if (workp == NULL) {
2535 				if (have_mutex)
2536 					mutex_exit(&wlp->dwl_lock);
2537 				break;
2538 			}
2539 			mutex_exit(&wlp->dwl_lock);
2540 
2541 			/*
2542 			 * Free up requests
2543 			 */
2544 			for (i = 0; i < wlp->dwl_reqspermcr; i++) {
2545 				dca_request_t *reqp = workp->dw_reqs[i];
2546 				if (reqp) {
2547 					dca_done(reqp, errno);
2548 					workp->dw_reqs[i] = NULL;
2549 				}
2550 			}
2551 
2552 			mutex_enter(&wlp->dwl_lock);
2553 			/*
2554 			 * If waiting to drain, signal on the waiter.
2555 			 */
2556 			if (wlp->dwl_drain && QEMPTY(&wlp->dwl_runq)) {
2557 				cv_signal(&wlp->dwl_cv);
2558 			}
2559 
2560 			/*
2561 			 * Return the work and request structures to
2562 			 * the free pool.
2563 			 */
2564 			dca_freework(workp);
2565 			if (have_mutex)
2566 				mutex_exit(&wlp->dwl_lock);
2567 		}
2568 	}
2569 
2570 }
2571 
2572 #ifdef	SCHEDDELAY
2573 /*
2574  * Reschedule worklist as needed.
2575  */
2576 void
2577 dca_schedtimeout(void *arg)
2578 {
2579 	dca_worklist_t	*wlp = (dca_worklist_t *)arg;
2580 	mutex_enter(&wlp->dwl_lock);
2581 	wlp->dwl_schedtid = 0;
2582 	dca_schedule(wlp->dwl_dca, wlp->dwl_mcr);
2583 	mutex_exit(&wlp->dwl_lock);
2584 }
2585 #endif
2586 
2587 /*
2588  * Check for stalled jobs.
2589  */
2590 void
2591 dca_jobtimeout(void *arg)
2592 {
2593 	int		mcr;
2594 	dca_t		*dca = (dca_t *)arg;
2595 	int		hung = 0;
2596 
2597 	for (mcr = MCR1; mcr <= MCR2; mcr++) {
2598 		dca_worklist_t	*wlp = WORKLIST(dca, mcr);
2599 		dca_work_t	*workp;
2600 		clock_t		when;
2601 
2602 		mutex_enter(&wlp->dwl_lock);
2603 		when = ddi_get_lbolt();
2604 
2605 		workp = (dca_work_t *)dca_peekqueue(&wlp->dwl_runq);
2606 		if (workp == NULL) {
2607 			/* nothing sitting in the queue */
2608 			mutex_exit(&wlp->dwl_lock);
2609 			continue;
2610 		}
2611 
2612 		if ((when - workp->dw_lbolt) < drv_usectohz(STALETIME)) {
2613 			/* request has been queued for less than STALETIME */
2614 			mutex_exit(&wlp->dwl_lock);
2615 			continue;
2616 		}
2617 
2618 		/* job has been sitting around for over 1 second, badness */
2619 		DBG(dca, DWARN, "stale job (0x%p) found in MCR%d!", workp,
2620 		    mcr);
2621 
2622 		/* put it back in the queue, until we reset the chip */
2623 		hung++;
2624 		mutex_exit(&wlp->dwl_lock);
2625 	}
2626 
2627 	if (hung) {
2628 		dca_failure(dca, DDI_DEVICE_FAULT,
2629 		    DCA_FM_ECLASS_HW_TIMEOUT, dca_ena(0), CRYPTO_DEVICE_ERROR,
2630 		    "timeout processing job.)");
2631 	}
2632 
2633 	/* reschedule ourself */
2634 	mutex_enter(&dca->dca_intrlock);
2635 	if (dca->dca_jobtid == 0) {
2636 		/* timeout has been canceled, prior to DR */
2637 		mutex_exit(&dca->dca_intrlock);
2638 		return;
2639 	}
2640 
2641 	/* check again in 1 second */
2642 	dca->dca_jobtid = timeout(dca_jobtimeout, arg,
2643 	    drv_usectohz(SECOND));
2644 	mutex_exit(&dca->dca_intrlock);
2645 }
2646 
2647 /*
2648  * This returns all jobs back to kCF.  It assumes that processing
2649  * on the worklist has halted.
2650  */
2651 void
2652 dca_rejectjobs(dca_t *dca)
2653 {
2654 	int mcr;
2655 	int have_mutex;
2656 	for (mcr = MCR1; mcr <= MCR2; mcr++) {
2657 		dca_worklist_t	*wlp = WORKLIST(dca, mcr);
2658 		dca_request_t	*reqp;
2659 
2660 		if (wlp == NULL || wlp->dwl_waitq.dl_prev == NULL) {
2661 			continue;
2662 		}
2663 		have_mutex = mutex_tryenter(&wlp->dwl_lock);
2664 		for (;;) {
2665 			reqp = (dca_request_t *)dca_unqueue(&wlp->dwl_waitq);
2666 			if (reqp == NULL) {
2667 				break;
2668 			}
2669 			/* update flow control */
2670 			wlp->dwl_count--;
2671 			if ((wlp->dwl_count == wlp->dwl_lowater) &&
2672 			    (wlp->dwl_busy))  {
2673 				wlp->dwl_busy = 0;
2674 				crypto_prov_notify(wlp->dwl_prov,
2675 				    CRYPTO_PROVIDER_READY);
2676 			}
2677 			mutex_exit(&wlp->dwl_lock);
2678 
2679 			(void) dca_unbindchains(reqp);
2680 			reqp->dr_callback(reqp, EAGAIN);
2681 			mutex_enter(&wlp->dwl_lock);
2682 		}
2683 		if (have_mutex)
2684 			mutex_exit(&wlp->dwl_lock);
2685 	}
2686 }
2687 
2688 int
2689 dca_drain(dca_t *dca)
2690 {
2691 	int mcr;
2692 	for (mcr = MCR1; mcr <= MCR2; mcr++) {
2693 #ifdef	SCHEDDELAY
2694 		timeout_id_t	tid;
2695 #endif
2696 		dca_worklist_t *wlp = WORKLIST(dca, mcr);
2697 
2698 		mutex_enter(&wlp->dwl_lock);
2699 		wlp->dwl_drain = 1;
2700 
2701 		/* give it up to a second to drain from the chip */
2702 		if (!QEMPTY(&wlp->dwl_runq)) {
2703 			(void) cv_reltimedwait(&wlp->dwl_cv, &wlp->dwl_lock,
2704 			    drv_usectohz(STALETIME), TR_CLOCK_TICK);
2705 
2706 			if (!QEMPTY(&wlp->dwl_runq)) {
2707 				dca_error(dca, "unable to drain device");
2708 				mutex_exit(&wlp->dwl_lock);
2709 				dca_undrain(dca);
2710 				return (EBUSY);
2711 			}
2712 		}
2713 
2714 #ifdef	SCHEDDELAY
2715 		tid = wlp->dwl_schedtid;
2716 		mutex_exit(&wlp->dwl_lock);
2717 
2718 		/*
2719 		 * untimeout outside the lock -- this is safe because we
2720 		 * have set the drain flag, so dca_schedule() will not
2721 		 * reschedule another timeout
2722 		 */
2723 		if (tid) {
2724 			untimeout(tid);
2725 		}
2726 #else
2727 		mutex_exit(&wlp->dwl_lock);
2728 #endif
2729 	}
2730 	return (0);
2731 }
2732 
2733 void
2734 dca_undrain(dca_t *dca)
2735 {
2736 	int	mcr;
2737 
2738 	for (mcr = MCR1; mcr <= MCR2; mcr++) {
2739 		dca_worklist_t	*wlp = WORKLIST(dca, mcr);
2740 		mutex_enter(&wlp->dwl_lock);
2741 		wlp->dwl_drain = 0;
2742 		dca_schedule(dca, mcr);
2743 		mutex_exit(&wlp->dwl_lock);
2744 	}
2745 }
2746 
2747 /*
2748  * Duplicate the crypto_data_t structure, but point to the original
2749  * buffers.
2750  */
2751 int
2752 dca_dupcrypto(crypto_data_t *input, crypto_data_t *ninput)
2753 {
2754 	ninput->cd_format = input->cd_format;
2755 	ninput->cd_offset = input->cd_offset;
2756 	ninput->cd_length = input->cd_length;
2757 	ninput->cd_miscdata = input->cd_miscdata;
2758 
2759 	switch (input->cd_format) {
2760 	case CRYPTO_DATA_RAW:
2761 		ninput->cd_raw.iov_base = input->cd_raw.iov_base;
2762 		ninput->cd_raw.iov_len = input->cd_raw.iov_len;
2763 		break;
2764 
2765 	case CRYPTO_DATA_UIO:
2766 		ninput->cd_uio = input->cd_uio;
2767 		break;
2768 
2769 	case CRYPTO_DATA_MBLK:
2770 		ninput->cd_mp = input->cd_mp;
2771 		break;
2772 
2773 	default:
2774 		DBG(NULL, DWARN,
2775 		    "dca_dupcrypto: unrecognised crypto data format");
2776 		return (CRYPTO_FAILED);
2777 	}
2778 
2779 	return (CRYPTO_SUCCESS);
2780 }
2781 
2782 /*
2783  * Performs validation checks on the input and output data structures.
2784  */
2785 int
2786 dca_verifyio(crypto_data_t *input, crypto_data_t *output)
2787 {
2788 	int	rv = CRYPTO_SUCCESS;
2789 
2790 	switch (input->cd_format) {
2791 	case CRYPTO_DATA_RAW:
2792 		break;
2793 
2794 	case CRYPTO_DATA_UIO:
2795 		/* we support only kernel buffer */
2796 		if (input->cd_uio->uio_segflg != UIO_SYSSPACE) {
2797 			DBG(NULL, DWARN, "non kernel input uio buffer");
2798 			rv = CRYPTO_ARGUMENTS_BAD;
2799 		}
2800 		break;
2801 
2802 	case CRYPTO_DATA_MBLK:
2803 		break;
2804 
2805 	default:
2806 		DBG(NULL, DWARN, "unrecognised input crypto data format");
2807 		rv = CRYPTO_ARGUMENTS_BAD;
2808 	}
2809 
2810 	switch (output->cd_format) {
2811 	case CRYPTO_DATA_RAW:
2812 		break;
2813 
2814 	case CRYPTO_DATA_UIO:
2815 		/* we support only kernel buffer */
2816 		if (output->cd_uio->uio_segflg != UIO_SYSSPACE) {
2817 			DBG(NULL, DWARN, "non kernel output uio buffer");
2818 			rv = CRYPTO_ARGUMENTS_BAD;
2819 		}
2820 		break;
2821 
2822 	case CRYPTO_DATA_MBLK:
2823 		break;
2824 
2825 	default:
2826 		DBG(NULL, DWARN, "unrecognised output crypto data format");
2827 		rv = CRYPTO_ARGUMENTS_BAD;
2828 	}
2829 
2830 	return (rv);
2831 }
2832 
2833 /*
2834  * data: source crypto_data_t struct
2835  * off:	offset into the source before commencing copy
2836  * count: the amount of data to copy
2837  * dest: destination buffer
2838  */
2839 int
2840 dca_getbufbytes(crypto_data_t *data, size_t off, int count, uchar_t *dest)
2841 {
2842 	int rv = CRYPTO_SUCCESS;
2843 	uio_t *uiop;
2844 	uint_t vec_idx;
2845 	size_t cur_len;
2846 	mblk_t *mp;
2847 
2848 	if (count == 0) {
2849 		/* We don't want anything so we're done. */
2850 		return (rv);
2851 	}
2852 
2853 	/*
2854 	 * Sanity check that we haven't specified a length greater than the
2855 	 * offset adjusted size of the buffer.
2856 	 */
2857 	if (count > (data->cd_length - off)) {
2858 		return (CRYPTO_DATA_LEN_RANGE);
2859 	}
2860 
2861 	/* Add the internal crypto_data offset to the requested offset. */
2862 	off += data->cd_offset;
2863 
2864 	switch (data->cd_format) {
2865 	case CRYPTO_DATA_RAW:
2866 		bcopy(data->cd_raw.iov_base + off, dest, count);
2867 		break;
2868 
2869 	case CRYPTO_DATA_UIO:
2870 		/*
2871 		 * Jump to the first iovec containing data to be
2872 		 * processed.
2873 		 */
2874 		uiop = data->cd_uio;
2875 		for (vec_idx = 0; vec_idx < uiop->uio_iovcnt &&
2876 		    off >= uiop->uio_iov[vec_idx].iov_len;
2877 		    off -= uiop->uio_iov[vec_idx++].iov_len)
2878 			;
2879 		if (vec_idx == uiop->uio_iovcnt) {
2880 			/*
2881 			 * The caller specified an offset that is larger than
2882 			 * the total size of the buffers it provided.
2883 			 */
2884 			return (CRYPTO_DATA_LEN_RANGE);
2885 		}
2886 
2887 		/*
2888 		 * Now process the iovecs.
2889 		 */
2890 		while (vec_idx < uiop->uio_iovcnt && count > 0) {
2891 			cur_len = min(uiop->uio_iov[vec_idx].iov_len -
2892 			    off, count);
2893 			bcopy(uiop->uio_iov[vec_idx].iov_base + off, dest,
2894 			    cur_len);
2895 			count -= cur_len;
2896 			dest += cur_len;
2897 			vec_idx++;
2898 			off = 0;
2899 		}
2900 
2901 		if (vec_idx == uiop->uio_iovcnt && count > 0) {
2902 			/*
2903 			 * The end of the specified iovec's was reached but
2904 			 * the length requested could not be processed
2905 			 * (requested to digest more data than it provided).
2906 			 */
2907 			return (CRYPTO_DATA_LEN_RANGE);
2908 		}
2909 		break;
2910 
2911 	case CRYPTO_DATA_MBLK:
2912 		/*
2913 		 * Jump to the first mblk_t containing data to be processed.
2914 		 */
2915 		for (mp = data->cd_mp; mp != NULL && off >= MBLKL(mp);
2916 		    off -= MBLKL(mp), mp = mp->b_cont)
2917 			;
2918 		if (mp == NULL) {
2919 			/*
2920 			 * The caller specified an offset that is larger than
2921 			 * the total size of the buffers it provided.
2922 			 */
2923 			return (CRYPTO_DATA_LEN_RANGE);
2924 		}
2925 
2926 		/*
2927 		 * Now do the processing on the mblk chain.
2928 		 */
2929 		while (mp != NULL && count > 0) {
2930 			cur_len = min(MBLKL(mp) - off, count);
2931 			bcopy((char *)(mp->b_rptr + off), dest, cur_len);
2932 			count -= cur_len;
2933 			dest += cur_len;
2934 			mp = mp->b_cont;
2935 			off = 0;
2936 		}
2937 
2938 		if (mp == NULL && count > 0) {
2939 			/*
2940 			 * The end of the mblk was reached but the length
2941 			 * requested could not be processed, (requested to
2942 			 * digest more data than it provided).
2943 			 */
2944 			return (CRYPTO_DATA_LEN_RANGE);
2945 		}
2946 		break;
2947 
2948 	default:
2949 		DBG(NULL, DWARN, "unrecognised crypto data format");
2950 		rv = CRYPTO_ARGUMENTS_BAD;
2951 	}
2952 	return (rv);
2953 }
2954 
2955 
2956 /*
2957  * Performs the input, output or hard scatter/gather checks on the specified
2958  * crypto_data_t struct. Returns true if the data is scatter/gather in nature
2959  * ie fails the test.
2960  */
2961 int
2962 dca_sgcheck(dca_t *dca, crypto_data_t *data, dca_sg_param_t val)
2963 {
2964 	uio_t *uiop;
2965 	mblk_t *mp;
2966 	int rv = FALSE;
2967 
2968 	switch (val) {
2969 	case DCA_SG_CONTIG:
2970 		/*
2971 		 * Check for a contiguous data buffer.
2972 		 */
2973 		switch (data->cd_format) {
2974 		case CRYPTO_DATA_RAW:
2975 			/* Contiguous in nature */
2976 			break;
2977 
2978 		case CRYPTO_DATA_UIO:
2979 			if (data->cd_uio->uio_iovcnt > 1)
2980 				rv = TRUE;
2981 			break;
2982 
2983 		case CRYPTO_DATA_MBLK:
2984 			mp = data->cd_mp;
2985 			if (mp->b_cont != NULL)
2986 				rv = TRUE;
2987 			break;
2988 
2989 		default:
2990 			DBG(NULL, DWARN, "unrecognised crypto data format");
2991 		}
2992 		break;
2993 
2994 	case DCA_SG_WALIGN:
2995 		/*
2996 		 * Check for a contiguous data buffer that is 32-bit word
2997 		 * aligned and is of word multiples in size.
2998 		 */
2999 		switch (data->cd_format) {
3000 		case CRYPTO_DATA_RAW:
3001 			if ((data->cd_raw.iov_len % sizeof (uint32_t)) ||
3002 			    ((uintptr_t)data->cd_raw.iov_base %
3003 			    sizeof (uint32_t))) {
3004 				rv = TRUE;
3005 			}
3006 			break;
3007 
3008 		case CRYPTO_DATA_UIO:
3009 			uiop = data->cd_uio;
3010 			if (uiop->uio_iovcnt > 1) {
3011 				return (TRUE);
3012 			}
3013 			/* So there is only one iovec */
3014 			if ((uiop->uio_iov[0].iov_len % sizeof (uint32_t)) ||
3015 			    ((uintptr_t)uiop->uio_iov[0].iov_base %
3016 			    sizeof (uint32_t))) {
3017 				rv = TRUE;
3018 			}
3019 			break;
3020 
3021 		case CRYPTO_DATA_MBLK:
3022 			mp = data->cd_mp;
3023 			if (mp->b_cont != NULL) {
3024 				return (TRUE);
3025 			}
3026 			/* So there is only one mblk in the chain */
3027 			if ((MBLKL(mp) % sizeof (uint32_t)) ||
3028 			    ((uintptr_t)mp->b_rptr % sizeof (uint32_t))) {
3029 				rv = TRUE;
3030 			}
3031 			break;
3032 
3033 		default:
3034 			DBG(NULL, DWARN, "unrecognised crypto data format");
3035 		}
3036 		break;
3037 
3038 	case DCA_SG_PALIGN:
3039 		/*
3040 		 * Check that the data buffer is page aligned and is of
3041 		 * page multiples in size.
3042 		 */
3043 		switch (data->cd_format) {
3044 		case CRYPTO_DATA_RAW:
3045 			if ((data->cd_length % dca->dca_pagesize) ||
3046 			    ((uintptr_t)data->cd_raw.iov_base %
3047 			    dca->dca_pagesize)) {
3048 				rv = TRUE;
3049 			}
3050 			break;
3051 
3052 		case CRYPTO_DATA_UIO:
3053 			uiop = data->cd_uio;
3054 			if ((uiop->uio_iov[0].iov_len % dca->dca_pagesize) ||
3055 			    ((uintptr_t)uiop->uio_iov[0].iov_base %
3056 			    dca->dca_pagesize)) {
3057 				rv = TRUE;
3058 			}
3059 			break;
3060 
3061 		case CRYPTO_DATA_MBLK:
3062 			mp = data->cd_mp;
3063 			if ((MBLKL(mp) % dca->dca_pagesize) ||
3064 			    ((uintptr_t)mp->b_rptr % dca->dca_pagesize)) {
3065 				rv = TRUE;
3066 			}
3067 			break;
3068 
3069 		default:
3070 			DBG(NULL, DWARN, "unrecognised crypto data format");
3071 		}
3072 		break;
3073 
3074 	default:
3075 		DBG(NULL, DWARN, "unrecognised scatter/gather param type");
3076 	}
3077 
3078 	return (rv);
3079 }
3080 
3081 /*
3082  * Increments the cd_offset and decrements the cd_length as the data is
3083  * gathered from the crypto_data_t struct.
3084  * The data is reverse-copied into the dest buffer if the flag is true.
3085  */
3086 int
3087 dca_gather(crypto_data_t *in, char *dest, int count, int reverse)
3088 {
3089 	int	rv = CRYPTO_SUCCESS;
3090 	uint_t	vec_idx;
3091 	uio_t	*uiop;
3092 	off_t	off = in->cd_offset;
3093 	size_t	cur_len;
3094 	mblk_t	*mp;
3095 
3096 	switch (in->cd_format) {
3097 	case CRYPTO_DATA_RAW:
3098 		if (count > in->cd_length) {
3099 			/*
3100 			 * The caller specified a length greater than the
3101 			 * size of the buffer.
3102 			 */
3103 			return (CRYPTO_DATA_LEN_RANGE);
3104 		}
3105 		if (reverse)
3106 			dca_reverse(in->cd_raw.iov_base + off, dest, count,
3107 			    count);
3108 		else
3109 			bcopy(in->cd_raw.iov_base + in->cd_offset, dest, count);
3110 		in->cd_offset += count;
3111 		in->cd_length -= count;
3112 		break;
3113 
3114 	case CRYPTO_DATA_UIO:
3115 		/*
3116 		 * Jump to the first iovec containing data to be processed.
3117 		 */
3118 		uiop = in->cd_uio;
3119 		for (vec_idx = 0; vec_idx < uiop->uio_iovcnt &&
3120 		    off >= uiop->uio_iov[vec_idx].iov_len;
3121 		    off -= uiop->uio_iov[vec_idx++].iov_len)
3122 			;
3123 		if (vec_idx == uiop->uio_iovcnt) {
3124 			/*
3125 			 * The caller specified an offset that is larger than
3126 			 * the total size of the buffers it provided.
3127 			 */
3128 			return (CRYPTO_DATA_LEN_RANGE);
3129 		}
3130 
3131 		/*
3132 		 * Now process the iovecs.
3133 		 */
3134 		while (vec_idx < uiop->uio_iovcnt && count > 0) {
3135 			cur_len = min(uiop->uio_iov[vec_idx].iov_len -
3136 			    off, count);
3137 			count -= cur_len;
3138 			if (reverse) {
3139 				/* Fill the dest buffer from the end */
3140 				dca_reverse(uiop->uio_iov[vec_idx].iov_base +
3141 				    off, dest+count, cur_len, cur_len);
3142 			} else {
3143 				bcopy(uiop->uio_iov[vec_idx].iov_base + off,
3144 				    dest, cur_len);
3145 				dest += cur_len;
3146 			}
3147 			in->cd_offset += cur_len;
3148 			in->cd_length -= cur_len;
3149 			vec_idx++;
3150 			off = 0;
3151 		}
3152 
3153 		if (vec_idx == uiop->uio_iovcnt && count > 0) {
3154 			/*
3155 			 * The end of the specified iovec's was reached but
3156 			 * the length requested could not be processed
3157 			 * (requested to digest more data than it provided).
3158 			 */
3159 			return (CRYPTO_DATA_LEN_RANGE);
3160 		}
3161 		break;
3162 
3163 	case CRYPTO_DATA_MBLK:
3164 		/*
3165 		 * Jump to the first mblk_t containing data to be processed.
3166 		 */
3167 		for (mp = in->cd_mp; mp != NULL && off >= MBLKL(mp);
3168 		    off -= MBLKL(mp), mp = mp->b_cont)
3169 			;
3170 		if (mp == NULL) {
3171 			/*
3172 			 * The caller specified an offset that is larger than
3173 			 * the total size of the buffers it provided.
3174 			 */
3175 			return (CRYPTO_DATA_LEN_RANGE);
3176 		}
3177 
3178 		/*
3179 		 * Now do the processing on the mblk chain.
3180 		 */
3181 		while (mp != NULL && count > 0) {
3182 			cur_len = min(MBLKL(mp) - off, count);
3183 			count -= cur_len;
3184 			if (reverse) {
3185 				/* Fill the dest buffer from the end */
3186 				dca_reverse((char *)(mp->b_rptr + off),
3187 				    dest+count, cur_len, cur_len);
3188 			} else {
3189 				bcopy((char *)(mp->b_rptr + off), dest,
3190 				    cur_len);
3191 				dest += cur_len;
3192 			}
3193 			in->cd_offset += cur_len;
3194 			in->cd_length -= cur_len;
3195 			mp = mp->b_cont;
3196 			off = 0;
3197 		}
3198 
3199 		if (mp == NULL && count > 0) {
3200 			/*
3201 			 * The end of the mblk was reached but the length
3202 			 * requested could not be processed, (requested to
3203 			 * digest more data than it provided).
3204 			 */
3205 			return (CRYPTO_DATA_LEN_RANGE);
3206 		}
3207 		break;
3208 
3209 	default:
3210 		DBG(NULL, DWARN, "dca_gather: unrecognised crypto data format");
3211 		rv = CRYPTO_ARGUMENTS_BAD;
3212 	}
3213 	return (rv);
3214 }
3215 
3216 /*
3217  * Increments the cd_offset and decrements the cd_length as the data is
3218  * gathered from the crypto_data_t struct.
3219  */
3220 int
3221 dca_resid_gather(crypto_data_t *in, char *resid, int *residlen, char *dest,
3222     int count)
3223 {
3224 	int	rv = CRYPTO_SUCCESS;
3225 	caddr_t	baddr;
3226 	uint_t	vec_idx;
3227 	uio_t	*uiop;
3228 	off_t	off = in->cd_offset;
3229 	size_t	cur_len;
3230 	mblk_t	*mp;
3231 
3232 	/* Process the residual first */
3233 	if (*residlen > 0) {
3234 		uint_t	num = min(count, *residlen);
3235 		bcopy(resid, dest, num);
3236 		*residlen -= num;
3237 		if (*residlen > 0) {
3238 			/*
3239 			 * Requested amount 'count' is less than what's in
3240 			 * the residual, so shuffle any remaining resid to
3241 			 * the front.
3242 			 */
3243 			baddr = resid + num;
3244 			bcopy(baddr, resid, *residlen);
3245 		}
3246 		dest += num;
3247 		count -= num;
3248 	}
3249 
3250 	/* Now process what's in the crypto_data_t structs */
3251 	switch (in->cd_format) {
3252 	case CRYPTO_DATA_RAW:
3253 		if (count > in->cd_length) {
3254 			/*
3255 			 * The caller specified a length greater than the
3256 			 * size of the buffer.
3257 			 */
3258 			return (CRYPTO_DATA_LEN_RANGE);
3259 		}
3260 		bcopy(in->cd_raw.iov_base + in->cd_offset, dest, count);
3261 		in->cd_offset += count;
3262 		in->cd_length -= count;
3263 		break;
3264 
3265 	case CRYPTO_DATA_UIO:
3266 		/*
3267 		 * Jump to the first iovec containing data to be processed.
3268 		 */
3269 		uiop = in->cd_uio;
3270 		for (vec_idx = 0; vec_idx < uiop->uio_iovcnt &&
3271 		    off >= uiop->uio_iov[vec_idx].iov_len;
3272 		    off -= uiop->uio_iov[vec_idx++].iov_len)
3273 			;
3274 		if (vec_idx == uiop->uio_iovcnt) {
3275 			/*
3276 			 * The caller specified an offset that is larger than
3277 			 * the total size of the buffers it provided.
3278 			 */
3279 			return (CRYPTO_DATA_LEN_RANGE);
3280 		}
3281 
3282 		/*
3283 		 * Now process the iovecs.
3284 		 */
3285 		while (vec_idx < uiop->uio_iovcnt && count > 0) {
3286 			cur_len = min(uiop->uio_iov[vec_idx].iov_len -
3287 			    off, count);
3288 			bcopy(uiop->uio_iov[vec_idx].iov_base + off, dest,
3289 			    cur_len);
3290 			count -= cur_len;
3291 			dest += cur_len;
3292 			in->cd_offset += cur_len;
3293 			in->cd_length -= cur_len;
3294 			vec_idx++;
3295 			off = 0;
3296 		}
3297 
3298 		if (vec_idx == uiop->uio_iovcnt && count > 0) {
3299 			/*
3300 			 * The end of the specified iovec's was reached but
3301 			 * the length requested could not be processed
3302 			 * (requested to digest more data than it provided).
3303 			 */
3304 			return (CRYPTO_DATA_LEN_RANGE);
3305 		}
3306 		break;
3307 
3308 	case CRYPTO_DATA_MBLK:
3309 		/*
3310 		 * Jump to the first mblk_t containing data to be processed.
3311 		 */
3312 		for (mp = in->cd_mp; mp != NULL && off >= MBLKL(mp);
3313 		    off -= MBLKL(mp), mp = mp->b_cont)
3314 			;
3315 		if (mp == NULL) {
3316 			/*
3317 			 * The caller specified an offset that is larger than
3318 			 * the total size of the buffers it provided.
3319 			 */
3320 			return (CRYPTO_DATA_LEN_RANGE);
3321 		}
3322 
3323 		/*
3324 		 * Now do the processing on the mblk chain.
3325 		 */
3326 		while (mp != NULL && count > 0) {
3327 			cur_len = min(MBLKL(mp) - off, count);
3328 			bcopy((char *)(mp->b_rptr + off), dest, cur_len);
3329 			count -= cur_len;
3330 			dest += cur_len;
3331 			in->cd_offset += cur_len;
3332 			in->cd_length -= cur_len;
3333 			mp = mp->b_cont;
3334 			off = 0;
3335 		}
3336 
3337 		if (mp == NULL && count > 0) {
3338 			/*
3339 			 * The end of the mblk was reached but the length
3340 			 * requested could not be processed, (requested to
3341 			 * digest more data than it provided).
3342 			 */
3343 			return (CRYPTO_DATA_LEN_RANGE);
3344 		}
3345 		break;
3346 
3347 	default:
3348 		DBG(NULL, DWARN,
3349 		    "dca_resid_gather: unrecognised crypto data format");
3350 		rv = CRYPTO_ARGUMENTS_BAD;
3351 	}
3352 	return (rv);
3353 }
3354 
3355 /*
3356  * Appends the data to the crypto_data_t struct increasing cd_length.
3357  * cd_offset is left unchanged.
3358  * Data is reverse-copied if the flag is TRUE.
3359  */
3360 int
3361 dca_scatter(const char *src, crypto_data_t *out, int count, int reverse)
3362 {
3363 	int	rv = CRYPTO_SUCCESS;
3364 	off_t	offset = out->cd_offset + out->cd_length;
3365 	uint_t	vec_idx;
3366 	uio_t	*uiop;
3367 	size_t	cur_len;
3368 	mblk_t	*mp;
3369 
3370 	switch (out->cd_format) {
3371 	case CRYPTO_DATA_RAW:
3372 		if (out->cd_raw.iov_len - offset < count) {
3373 			/* Trying to write out more than space available. */
3374 			return (CRYPTO_DATA_LEN_RANGE);
3375 		}
3376 		if (reverse)
3377 			dca_reverse((void*) src, out->cd_raw.iov_base + offset,
3378 			    count, count);
3379 		else
3380 			bcopy(src, out->cd_raw.iov_base + offset, count);
3381 		out->cd_length += count;
3382 		break;
3383 
3384 	case CRYPTO_DATA_UIO:
3385 		/*
3386 		 * Jump to the first iovec that can be written to.
3387 		 */
3388 		uiop = out->cd_uio;
3389 		for (vec_idx = 0; vec_idx < uiop->uio_iovcnt &&
3390 		    offset >= uiop->uio_iov[vec_idx].iov_len;
3391 		    offset -= uiop->uio_iov[vec_idx++].iov_len)
3392 			;
3393 		if (vec_idx == uiop->uio_iovcnt) {
3394 			/*
3395 			 * The caller specified an offset that is larger than
3396 			 * the total size of the buffers it provided.
3397 			 */
3398 			return (CRYPTO_DATA_LEN_RANGE);
3399 		}
3400 
3401 		/*
3402 		 * Now process the iovecs.
3403 		 */
3404 		while (vec_idx < uiop->uio_iovcnt && count > 0) {
3405 			cur_len = min(uiop->uio_iov[vec_idx].iov_len -
3406 			    offset, count);
3407 			count -= cur_len;
3408 			if (reverse) {
3409 				dca_reverse((void*) (src+count),
3410 				    uiop->uio_iov[vec_idx].iov_base +
3411 				    offset, cur_len, cur_len);
3412 			} else {
3413 				bcopy(src, uiop->uio_iov[vec_idx].iov_base +
3414 				    offset, cur_len);
3415 				src += cur_len;
3416 			}
3417 			out->cd_length += cur_len;
3418 			vec_idx++;
3419 			offset = 0;
3420 		}
3421 
3422 		if (vec_idx == uiop->uio_iovcnt && count > 0) {
3423 			/*
3424 			 * The end of the specified iovec's was reached but
3425 			 * the length requested could not be processed
3426 			 * (requested to write more data than space provided).
3427 			 */
3428 			return (CRYPTO_DATA_LEN_RANGE);
3429 		}
3430 		break;
3431 
3432 	case CRYPTO_DATA_MBLK:
3433 		/*
3434 		 * Jump to the first mblk_t that can be written to.
3435 		 */
3436 		for (mp = out->cd_mp; mp != NULL && offset >= MBLKL(mp);
3437 		    offset -= MBLKL(mp), mp = mp->b_cont)
3438 			;
3439 		if (mp == NULL) {
3440 			/*
3441 			 * The caller specified an offset that is larger than
3442 			 * the total size of the buffers it provided.
3443 			 */
3444 			return (CRYPTO_DATA_LEN_RANGE);
3445 		}
3446 
3447 		/*
3448 		 * Now do the processing on the mblk chain.
3449 		 */
3450 		while (mp != NULL && count > 0) {
3451 			cur_len = min(MBLKL(mp) - offset, count);
3452 			count -= cur_len;
3453 			if (reverse) {
3454 				dca_reverse((void*) (src+count),
3455 				    (char *)(mp->b_rptr + offset), cur_len,
3456 				    cur_len);
3457 			} else {
3458 				bcopy(src, (char *)(mp->b_rptr + offset),
3459 				    cur_len);
3460 				src += cur_len;
3461 			}
3462 			out->cd_length += cur_len;
3463 			mp = mp->b_cont;
3464 			offset = 0;
3465 		}
3466 
3467 		if (mp == NULL && count > 0) {
3468 			/*
3469 			 * The end of the mblk was reached but the length
3470 			 * requested could not be processed, (requested to
3471 			 * digest more data than it provided).
3472 			 */
3473 			return (CRYPTO_DATA_LEN_RANGE);
3474 		}
3475 		break;
3476 
3477 	default:
3478 		DBG(NULL, DWARN, "unrecognised crypto data format");
3479 		rv = CRYPTO_ARGUMENTS_BAD;
3480 	}
3481 	return (rv);
3482 }
3483 
3484 /*
3485  * Compare two byte arrays in reverse order.
3486  * Return 0 if they are identical, 1 otherwise.
3487  */
3488 int
3489 dca_bcmp_reverse(const void *s1, const void *s2, size_t n)
3490 {
3491 	int i;
3492 	caddr_t src, dst;
3493 
3494 	if (!n)
3495 		return (0);
3496 
3497 	src = ((caddr_t)s1) + n - 1;
3498 	dst = (caddr_t)s2;
3499 	for (i = 0; i < n; i++) {
3500 		if (*src != *dst)
3501 			return (1);
3502 		src--;
3503 		dst++;
3504 	}
3505 
3506 	return (0);
3507 }
3508 
3509 
3510 /*
3511  * This calculates the size of a bignum in bits, specifically not counting
3512  * leading zero bits.  This size calculation must be done *before* any
3513  * endian reversal takes place (i.e. the numbers are in absolute big-endian
3514  * order.)
3515  */
3516 int
3517 dca_bitlen(unsigned char *bignum, int bytelen)
3518 {
3519 	unsigned char	msbyte;
3520 	int		i, j;
3521 
3522 	for (i = 0; i < bytelen - 1; i++) {
3523 		if (bignum[i] != 0) {
3524 			break;
3525 		}
3526 	}
3527 	msbyte = bignum[i];
3528 	for (j = 8; j > 1; j--) {
3529 		if (msbyte & 0x80) {
3530 			break;
3531 		}
3532 		msbyte <<= 1;
3533 	}
3534 	return ((8 * (bytelen - i - 1)) + j);
3535 }
3536 
3537 /*
3538  * This compares to bignums (in big-endian order).  It ignores leading
3539  * null bytes.  The result semantics follow bcmp, mempcmp, strcmp, etc.
3540  */
3541 int
3542 dca_numcmp(caddr_t n1, int n1len, caddr_t n2, int n2len)
3543 {
3544 	while ((n1len > 1) && (*n1 == 0)) {
3545 		n1len--;
3546 		n1++;
3547 	}
3548 	while ((n2len > 1) && (*n2 == 0)) {
3549 		n2len--;
3550 		n2++;
3551 	}
3552 	if (n1len != n2len) {
3553 		return (n1len - n2len);
3554 	}
3555 	while ((n1len > 1) && (*n1 == *n2)) {
3556 		n1++;
3557 		n2++;
3558 		n1len--;
3559 	}
3560 	return ((int)(*(uchar_t *)n1) - (int)(*(uchar_t *)n2));
3561 }
3562 
3563 /*
3564  * Return array of key attributes.
3565  */
3566 crypto_object_attribute_t *
3567 dca_get_key_attr(crypto_key_t *key)
3568 {
3569 	if ((key->ck_format != CRYPTO_KEY_ATTR_LIST) ||
3570 	    (key->ck_count == 0)) {
3571 		return (NULL);
3572 	}
3573 
3574 	return (key->ck_attrs);
3575 }
3576 
3577 /*
3578  * If attribute type exists valp points to it's 32-bit value.
3579  */
3580 int
3581 dca_attr_lookup_uint32(crypto_object_attribute_t *attrp, uint_t atnum,
3582     uint64_t atype, uint32_t *valp)
3583 {
3584 	crypto_object_attribute_t	*bap;
3585 
3586 	bap = dca_find_attribute(attrp, atnum, atype);
3587 	if (bap == NULL) {
3588 		return (CRYPTO_ATTRIBUTE_TYPE_INVALID);
3589 	}
3590 
3591 	*valp = *bap->oa_value;
3592 
3593 	return (CRYPTO_SUCCESS);
3594 }
3595 
3596 /*
3597  * If attribute type exists data contains the start address of the value,
3598  * and numelems contains it's length.
3599  */
3600 int
3601 dca_attr_lookup_uint8_array(crypto_object_attribute_t *attrp, uint_t atnum,
3602     uint64_t atype, void **data, unsigned int *numelems)
3603 {
3604 	crypto_object_attribute_t	*bap;
3605 
3606 	bap = dca_find_attribute(attrp, atnum, atype);
3607 	if (bap == NULL) {
3608 		return (CRYPTO_ATTRIBUTE_TYPE_INVALID);
3609 	}
3610 
3611 	*data = bap->oa_value;
3612 	*numelems = bap->oa_value_len;
3613 
3614 	return (CRYPTO_SUCCESS);
3615 }
3616 
3617 /*
3618  * Finds entry of specified name. If it is not found dca_find_attribute returns
3619  * NULL.
3620  */
3621 crypto_object_attribute_t *
3622 dca_find_attribute(crypto_object_attribute_t *attrp, uint_t atnum,
3623     uint64_t atype)
3624 {
3625 	while (atnum) {
3626 		if (attrp->oa_type == atype)
3627 			return (attrp);
3628 		atnum--;
3629 		attrp++;
3630 	}
3631 	return (NULL);
3632 }
3633 
3634 /*
3635  * Return the address of the first data buffer. If the data format is
3636  * unrecognised return NULL.
3637  */
3638 caddr_t
3639 dca_bufdaddr(crypto_data_t *data)
3640 {
3641 	switch (data->cd_format) {
3642 	case CRYPTO_DATA_RAW:
3643 		return (data->cd_raw.iov_base + data->cd_offset);
3644 	case CRYPTO_DATA_UIO:
3645 		return (data->cd_uio->uio_iov[0].iov_base + data->cd_offset);
3646 	case CRYPTO_DATA_MBLK:
3647 		return ((char *)data->cd_mp->b_rptr + data->cd_offset);
3648 	default:
3649 		DBG(NULL, DWARN,
3650 		    "dca_bufdaddr: unrecognised crypto data format");
3651 		return (NULL);
3652 	}
3653 }
3654 
3655 static caddr_t
3656 dca_bufdaddr_out(crypto_data_t *data)
3657 {
3658 	size_t offset = data->cd_offset + data->cd_length;
3659 
3660 	switch (data->cd_format) {
3661 	case CRYPTO_DATA_RAW:
3662 		return (data->cd_raw.iov_base + offset);
3663 	case CRYPTO_DATA_UIO:
3664 		return (data->cd_uio->uio_iov[0].iov_base + offset);
3665 	case CRYPTO_DATA_MBLK:
3666 		return ((char *)data->cd_mp->b_rptr + offset);
3667 	default:
3668 		DBG(NULL, DWARN,
3669 		    "dca_bufdaddr_out: unrecognised crypto data format");
3670 		return (NULL);
3671 	}
3672 }
3673 
3674 /*
3675  * Control entry points.
3676  */
3677 
3678 /* ARGSUSED */
3679 static void
3680 dca_provider_status(crypto_provider_handle_t provider, uint_t *status)
3681 {
3682 	*status = CRYPTO_PROVIDER_READY;
3683 }
3684 
3685 /*
3686  * Cipher (encrypt/decrypt) entry points.
3687  */
3688 
3689 /* ARGSUSED */
3690 static int
3691 dca_encrypt_init(crypto_ctx_t *ctx, crypto_mechanism_t *mechanism,
3692     crypto_key_t *key, crypto_spi_ctx_template_t ctx_template,
3693     crypto_req_handle_t req)
3694 {
3695 	int error = CRYPTO_FAILED;
3696 	dca_t *softc;
3697 	/* LINTED E_FUNC_SET_NOT_USED */
3698 	int instance;
3699 
3700 	/* extract softc and instance number from context */
3701 	DCA_SOFTC_FROM_CTX(ctx, softc, instance);
3702 	DBG(softc, DENTRY, "dca_encrypt_init: started");
3703 
3704 	/* check mechanism */
3705 	switch (mechanism->cm_type) {
3706 	case DES_CBC_MECH_INFO_TYPE:
3707 		error = dca_3desctxinit(ctx, mechanism, key, KM_SLEEP,
3708 		    DR_ENCRYPT);
3709 		break;
3710 	case DES3_CBC_MECH_INFO_TYPE:
3711 		error = dca_3desctxinit(ctx, mechanism, key, KM_SLEEP,
3712 		    DR_ENCRYPT | DR_TRIPLE);
3713 		break;
3714 	case RSA_PKCS_MECH_INFO_TYPE:
3715 	case RSA_X_509_MECH_INFO_TYPE:
3716 		error = dca_rsainit(ctx, mechanism, key, KM_SLEEP);
3717 		break;
3718 	default:
3719 		cmn_err(CE_WARN, "dca_encrypt_init: unexpected mech type "
3720 		    "0x%llx\n", (unsigned long long)mechanism->cm_type);
3721 		error = CRYPTO_MECHANISM_INVALID;
3722 	}
3723 
3724 	DBG(softc, DENTRY, "dca_encrypt_init: done, err = 0x%x", error);
3725 
3726 	if (error == CRYPTO_SUCCESS)
3727 		dca_enlist2(&softc->dca_ctx_list, ctx->cc_provider_private,
3728 		    &softc->dca_ctx_list_lock);
3729 
3730 	return (error);
3731 }
3732 
3733 /* ARGSUSED */
3734 static int
3735 dca_encrypt(crypto_ctx_t *ctx, crypto_data_t *plaintext,
3736     crypto_data_t *ciphertext, crypto_req_handle_t req)
3737 {
3738 	int error = CRYPTO_FAILED;
3739 	dca_t *softc;
3740 	/* LINTED E_FUNC_SET_NOT_USED */
3741 	int instance;
3742 
3743 	if (!ctx || !ctx->cc_provider || !ctx->cc_provider_private)
3744 		return (CRYPTO_OPERATION_NOT_INITIALIZED);
3745 
3746 	/* extract softc and instance number from context */
3747 	DCA_SOFTC_FROM_CTX(ctx, softc, instance);
3748 	DBG(softc, DENTRY, "dca_encrypt: started");
3749 
3750 	/* handle inplace ops */
3751 	if (!ciphertext) {
3752 		dca_request_t *reqp = ctx->cc_provider_private;
3753 		reqp->dr_flags |= DR_INPLACE;
3754 		ciphertext = plaintext;
3755 	}
3756 
3757 	/* check mechanism */
3758 	switch (DCA_MECH_FROM_CTX(ctx)) {
3759 	case DES_CBC_MECH_INFO_TYPE:
3760 		error = dca_3des(ctx, plaintext, ciphertext, req, DR_ENCRYPT);
3761 		break;
3762 	case DES3_CBC_MECH_INFO_TYPE:
3763 		error = dca_3des(ctx, plaintext, ciphertext, req,
3764 		    DR_ENCRYPT | DR_TRIPLE);
3765 		break;
3766 	case RSA_PKCS_MECH_INFO_TYPE:
3767 	case RSA_X_509_MECH_INFO_TYPE:
3768 		error = dca_rsastart(ctx, plaintext, ciphertext, req,
3769 		    DCA_RSA_ENC);
3770 		break;
3771 	default:
3772 		/* Should never reach here */
3773 		cmn_err(CE_WARN, "dca_encrypt: unexpected mech type "
3774 		    "0x%llx\n", (unsigned long long)DCA_MECH_FROM_CTX(ctx));
3775 		error = CRYPTO_MECHANISM_INVALID;
3776 	}
3777 
3778 	if ((error != CRYPTO_QUEUED) && (error != CRYPTO_SUCCESS) &&
3779 	    (error != CRYPTO_BUFFER_TOO_SMALL)) {
3780 		ciphertext->cd_length = 0;
3781 	}
3782 
3783 	DBG(softc, DENTRY, "dca_encrypt: done, err = 0x%x", error);
3784 
3785 	return (error);
3786 }
3787 
3788 /* ARGSUSED */
3789 static int
3790 dca_encrypt_update(crypto_ctx_t *ctx, crypto_data_t *plaintext,
3791     crypto_data_t *ciphertext, crypto_req_handle_t req)
3792 {
3793 	int error = CRYPTO_FAILED;
3794 	dca_t *softc;
3795 	/* LINTED E_FUNC_SET_NOT_USED */
3796 	int instance;
3797 
3798 	if (!ctx || !ctx->cc_provider || !ctx->cc_provider_private)
3799 		return (CRYPTO_OPERATION_NOT_INITIALIZED);
3800 
3801 	/* extract softc and instance number from context */
3802 	DCA_SOFTC_FROM_CTX(ctx, softc, instance);
3803 	DBG(softc, DENTRY, "dca_encrypt_update: started");
3804 
3805 	/* handle inplace ops */
3806 	if (!ciphertext) {
3807 		dca_request_t *reqp = ctx->cc_provider_private;
3808 		reqp->dr_flags |= DR_INPLACE;
3809 		ciphertext = plaintext;
3810 	}
3811 
3812 	/* check mechanism */
3813 	switch (DCA_MECH_FROM_CTX(ctx)) {
3814 	case DES_CBC_MECH_INFO_TYPE:
3815 		error = dca_3desupdate(ctx, plaintext, ciphertext, req,
3816 		    DR_ENCRYPT);
3817 		break;
3818 	case DES3_CBC_MECH_INFO_TYPE:
3819 		error = dca_3desupdate(ctx, plaintext, ciphertext, req,
3820 		    DR_ENCRYPT | DR_TRIPLE);
3821 		break;
3822 	default:
3823 		/* Should never reach here */
3824 		cmn_err(CE_WARN, "dca_encrypt_update: unexpected mech type "
3825 		    "0x%llx\n", (unsigned long long)DCA_MECH_FROM_CTX(ctx));
3826 		error = CRYPTO_MECHANISM_INVALID;
3827 	}
3828 
3829 	DBG(softc, DENTRY, "dca_encrypt_update: done, err = 0x%x", error);
3830 
3831 	return (error);
3832 }
3833 
3834 /* ARGSUSED */
3835 static int
3836 dca_encrypt_final(crypto_ctx_t *ctx, crypto_data_t *ciphertext,
3837     crypto_req_handle_t req)
3838 {
3839 	int error = CRYPTO_FAILED;
3840 	dca_t *softc;
3841 	/* LINTED E_FUNC_SET_NOT_USED */
3842 	int instance;
3843 
3844 	if (!ctx || !ctx->cc_provider || !ctx->cc_provider_private)
3845 		return (CRYPTO_OPERATION_NOT_INITIALIZED);
3846 
3847 	/* extract softc and instance number from context */
3848 	DCA_SOFTC_FROM_CTX(ctx, softc, instance);
3849 	DBG(softc, DENTRY, "dca_encrypt_final: started");
3850 
3851 	/* check mechanism */
3852 	switch (DCA_MECH_FROM_CTX(ctx)) {
3853 	case DES_CBC_MECH_INFO_TYPE:
3854 		error = dca_3desfinal(ctx, ciphertext, DR_ENCRYPT);
3855 		break;
3856 	case DES3_CBC_MECH_INFO_TYPE:
3857 		error = dca_3desfinal(ctx, ciphertext, DR_ENCRYPT | DR_TRIPLE);
3858 		break;
3859 	default:
3860 		/* Should never reach here */
3861 		cmn_err(CE_WARN, "dca_encrypt_final: unexpected mech type "
3862 		    "0x%llx\n", (unsigned long long)DCA_MECH_FROM_CTX(ctx));
3863 		error = CRYPTO_MECHANISM_INVALID;
3864 	}
3865 
3866 	DBG(softc, DENTRY, "dca_encrypt_final: done, err = 0x%x", error);
3867 
3868 	return (error);
3869 }
3870 
3871 /* ARGSUSED */
3872 static int
3873 dca_encrypt_atomic(crypto_provider_handle_t provider,
3874     crypto_session_id_t session_id, crypto_mechanism_t *mechanism,
3875     crypto_key_t *key, crypto_data_t *plaintext, crypto_data_t *ciphertext,
3876     crypto_spi_ctx_template_t ctx_template, crypto_req_handle_t req)
3877 {
3878 	int error = CRYPTO_FAILED;
3879 	dca_t *softc = (dca_t *)provider;
3880 
3881 	DBG(softc, DENTRY, "dca_encrypt_atomic: started");
3882 
3883 	if (ctx_template != NULL)
3884 		return (CRYPTO_ARGUMENTS_BAD);
3885 
3886 	/* handle inplace ops */
3887 	if (!ciphertext) {
3888 		ciphertext = plaintext;
3889 	}
3890 
3891 	/* check mechanism */
3892 	switch (mechanism->cm_type) {
3893 	case DES_CBC_MECH_INFO_TYPE:
3894 		error = dca_3desatomic(provider, session_id, mechanism, key,
3895 		    plaintext, ciphertext, KM_SLEEP, req,
3896 		    DR_ENCRYPT | DR_ATOMIC);
3897 		break;
3898 	case DES3_CBC_MECH_INFO_TYPE:
3899 		error = dca_3desatomic(provider, session_id, mechanism, key,
3900 		    plaintext, ciphertext, KM_SLEEP, req,
3901 		    DR_ENCRYPT | DR_TRIPLE | DR_ATOMIC);
3902 		break;
3903 	case RSA_PKCS_MECH_INFO_TYPE:
3904 	case RSA_X_509_MECH_INFO_TYPE:
3905 		error = dca_rsaatomic(provider, session_id, mechanism, key,
3906 		    plaintext, ciphertext, KM_SLEEP, req, DCA_RSA_ENC);
3907 		break;
3908 	default:
3909 		cmn_err(CE_WARN, "dca_encrypt_atomic: unexpected mech type "
3910 		    "0x%llx\n", (unsigned long long)mechanism->cm_type);
3911 		error = CRYPTO_MECHANISM_INVALID;
3912 	}
3913 
3914 	if ((error != CRYPTO_QUEUED) && (error != CRYPTO_SUCCESS)) {
3915 		ciphertext->cd_length = 0;
3916 	}
3917 
3918 	DBG(softc, DENTRY, "dca_encrypt_atomic: done, err = 0x%x", error);
3919 
3920 	return (error);
3921 }
3922 
3923 /* ARGSUSED */
3924 static int
3925 dca_decrypt_init(crypto_ctx_t *ctx, crypto_mechanism_t *mechanism,
3926     crypto_key_t *key, crypto_spi_ctx_template_t ctx_template,
3927     crypto_req_handle_t req)
3928 {
3929 	int error = CRYPTO_FAILED;
3930 	dca_t *softc;
3931 	/* LINTED E_FUNC_SET_NOT_USED */
3932 	int instance;
3933 
3934 	/* extract softc and instance number from context */
3935 	DCA_SOFTC_FROM_CTX(ctx, softc, instance);
3936 	DBG(softc, DENTRY, "dca_decrypt_init: started");
3937 
3938 	/* check mechanism */
3939 	switch (mechanism->cm_type) {
3940 	case DES_CBC_MECH_INFO_TYPE:
3941 		error = dca_3desctxinit(ctx, mechanism, key, KM_SLEEP,
3942 		    DR_DECRYPT);
3943 		break;
3944 	case DES3_CBC_MECH_INFO_TYPE:
3945 		error = dca_3desctxinit(ctx, mechanism, key, KM_SLEEP,
3946 		    DR_DECRYPT | DR_TRIPLE);
3947 		break;
3948 	case RSA_PKCS_MECH_INFO_TYPE:
3949 	case RSA_X_509_MECH_INFO_TYPE:
3950 		error = dca_rsainit(ctx, mechanism, key, KM_SLEEP);
3951 		break;
3952 	default:
3953 		cmn_err(CE_WARN, "dca_decrypt_init: unexpected mech type "
3954 		    "0x%llx\n", (unsigned long long)mechanism->cm_type);
3955 		error = CRYPTO_MECHANISM_INVALID;
3956 	}
3957 
3958 	DBG(softc, DENTRY, "dca_decrypt_init: done, err = 0x%x", error);
3959 
3960 	if (error == CRYPTO_SUCCESS)
3961 		dca_enlist2(&softc->dca_ctx_list, ctx->cc_provider_private,
3962 		    &softc->dca_ctx_list_lock);
3963 
3964 	return (error);
3965 }
3966 
3967 /* ARGSUSED */
3968 static int
3969 dca_decrypt(crypto_ctx_t *ctx, crypto_data_t *ciphertext,
3970     crypto_data_t *plaintext, crypto_req_handle_t req)
3971 {
3972 	int error = CRYPTO_FAILED;
3973 	dca_t *softc;
3974 	/* LINTED E_FUNC_SET_NOT_USED */
3975 	int instance;
3976 
3977 	if (!ctx || !ctx->cc_provider || !ctx->cc_provider_private)
3978 		return (CRYPTO_OPERATION_NOT_INITIALIZED);
3979 
3980 	/* extract softc and instance number from context */
3981 	DCA_SOFTC_FROM_CTX(ctx, softc, instance);
3982 	DBG(softc, DENTRY, "dca_decrypt: started");
3983 
3984 	/* handle inplace ops */
3985 	if (!plaintext) {
3986 		dca_request_t *reqp = ctx->cc_provider_private;
3987 		reqp->dr_flags |= DR_INPLACE;
3988 		plaintext = ciphertext;
3989 	}
3990 
3991 	/* check mechanism */
3992 	switch (DCA_MECH_FROM_CTX(ctx)) {
3993 	case DES_CBC_MECH_INFO_TYPE:
3994 		error = dca_3des(ctx, ciphertext, plaintext, req, DR_DECRYPT);
3995 		break;
3996 	case DES3_CBC_MECH_INFO_TYPE:
3997 		error = dca_3des(ctx, ciphertext, plaintext, req,
3998 		    DR_DECRYPT | DR_TRIPLE);
3999 		break;
4000 	case RSA_PKCS_MECH_INFO_TYPE:
4001 	case RSA_X_509_MECH_INFO_TYPE:
4002 		error = dca_rsastart(ctx, ciphertext, plaintext, req,
4003 		    DCA_RSA_DEC);
4004 		break;
4005 	default:
4006 		/* Should never reach here */
4007 		cmn_err(CE_WARN, "dca_decrypt: unexpected mech type "
4008 		    "0x%llx\n", (unsigned long long)DCA_MECH_FROM_CTX(ctx));
4009 		error = CRYPTO_MECHANISM_INVALID;
4010 	}
4011 
4012 	if ((error != CRYPTO_QUEUED) && (error != CRYPTO_SUCCESS) &&
4013 	    (error != CRYPTO_BUFFER_TOO_SMALL)) {
4014 		if (plaintext)
4015 			plaintext->cd_length = 0;
4016 	}
4017 
4018 	DBG(softc, DENTRY, "dca_decrypt: done, err = 0x%x", error);
4019 
4020 	return (error);
4021 }
4022 
4023 /* ARGSUSED */
4024 static int
4025 dca_decrypt_update(crypto_ctx_t *ctx, crypto_data_t *ciphertext,
4026     crypto_data_t *plaintext, crypto_req_handle_t req)
4027 {
4028 	int error = CRYPTO_FAILED;
4029 	dca_t *softc;
4030 	/* LINTED E_FUNC_SET_NOT_USED */
4031 	int instance;
4032 
4033 	if (!ctx || !ctx->cc_provider || !ctx->cc_provider_private)
4034 		return (CRYPTO_OPERATION_NOT_INITIALIZED);
4035 
4036 	/* extract softc and instance number from context */
4037 	DCA_SOFTC_FROM_CTX(ctx, softc, instance);
4038 	DBG(softc, DENTRY, "dca_decrypt_update: started");
4039 
4040 	/* handle inplace ops */
4041 	if (!plaintext) {
4042 		dca_request_t *reqp = ctx->cc_provider_private;
4043 		reqp->dr_flags |= DR_INPLACE;
4044 		plaintext = ciphertext;
4045 	}
4046 
4047 	/* check mechanism */
4048 	switch (DCA_MECH_FROM_CTX(ctx)) {
4049 	case DES_CBC_MECH_INFO_TYPE:
4050 		error = dca_3desupdate(ctx, ciphertext, plaintext, req,
4051 		    DR_DECRYPT);
4052 		break;
4053 	case DES3_CBC_MECH_INFO_TYPE:
4054 		error = dca_3desupdate(ctx, ciphertext, plaintext, req,
4055 		    DR_DECRYPT | DR_TRIPLE);
4056 		break;
4057 	default:
4058 		/* Should never reach here */
4059 		cmn_err(CE_WARN, "dca_decrypt_update: unexpected mech type "
4060 		    "0x%llx\n", (unsigned long long)DCA_MECH_FROM_CTX(ctx));
4061 		error = CRYPTO_MECHANISM_INVALID;
4062 	}
4063 
4064 	DBG(softc, DENTRY, "dca_decrypt_update: done, err = 0x%x", error);
4065 
4066 	return (error);
4067 }
4068 
4069 /* ARGSUSED */
4070 static int
4071 dca_decrypt_final(crypto_ctx_t *ctx, crypto_data_t *plaintext,
4072     crypto_req_handle_t req)
4073 {
4074 	int error = CRYPTO_FAILED;
4075 	dca_t *softc;
4076 	/* LINTED E_FUNC_SET_NOT_USED */
4077 	int instance;
4078 
4079 	if (!ctx || !ctx->cc_provider || !ctx->cc_provider_private)
4080 		return (CRYPTO_OPERATION_NOT_INITIALIZED);
4081 
4082 	/* extract softc and instance number from context */
4083 	DCA_SOFTC_FROM_CTX(ctx, softc, instance);
4084 	DBG(softc, DENTRY, "dca_decrypt_final: started");
4085 
4086 	/* check mechanism */
4087 	switch (DCA_MECH_FROM_CTX(ctx)) {
4088 	case DES_CBC_MECH_INFO_TYPE:
4089 		error = dca_3desfinal(ctx, plaintext, DR_DECRYPT);
4090 		break;
4091 	case DES3_CBC_MECH_INFO_TYPE:
4092 		error = dca_3desfinal(ctx, plaintext, DR_DECRYPT | DR_TRIPLE);
4093 		break;
4094 	default:
4095 		/* Should never reach here */
4096 		cmn_err(CE_WARN, "dca_decrypt_final: unexpected mech type "
4097 		    "0x%llx\n", (unsigned long long)DCA_MECH_FROM_CTX(ctx));
4098 		error = CRYPTO_MECHANISM_INVALID;
4099 	}
4100 
4101 	DBG(softc, DENTRY, "dca_decrypt_final: done, err = 0x%x", error);
4102 
4103 	return (error);
4104 }
4105 
4106 /* ARGSUSED */
4107 static int
4108 dca_decrypt_atomic(crypto_provider_handle_t provider,
4109     crypto_session_id_t session_id, crypto_mechanism_t *mechanism,
4110     crypto_key_t *key, crypto_data_t *ciphertext, crypto_data_t *plaintext,
4111     crypto_spi_ctx_template_t ctx_template, crypto_req_handle_t req)
4112 {
4113 	int error = CRYPTO_FAILED;
4114 	dca_t *softc = (dca_t *)provider;
4115 
4116 	DBG(softc, DENTRY, "dca_decrypt_atomic: started");
4117 
4118 	if (ctx_template != NULL)
4119 		return (CRYPTO_ARGUMENTS_BAD);
4120 
4121 	/* handle inplace ops */
4122 	if (!plaintext) {
4123 		plaintext = ciphertext;
4124 	}
4125 
4126 	/* check mechanism */
4127 	switch (mechanism->cm_type) {
4128 	case DES_CBC_MECH_INFO_TYPE:
4129 		error = dca_3desatomic(provider, session_id, mechanism, key,
4130 		    ciphertext, plaintext, KM_SLEEP, req,
4131 		    DR_DECRYPT | DR_ATOMIC);
4132 		break;
4133 	case DES3_CBC_MECH_INFO_TYPE:
4134 		error = dca_3desatomic(provider, session_id, mechanism, key,
4135 		    ciphertext, plaintext, KM_SLEEP, req,
4136 		    DR_DECRYPT | DR_TRIPLE | DR_ATOMIC);
4137 		break;
4138 	case RSA_PKCS_MECH_INFO_TYPE:
4139 	case RSA_X_509_MECH_INFO_TYPE:
4140 		error = dca_rsaatomic(provider, session_id, mechanism, key,
4141 		    ciphertext, plaintext, KM_SLEEP, req, DCA_RSA_DEC);
4142 		break;
4143 	default:
4144 		cmn_err(CE_WARN, "dca_decrypt_atomic: unexpected mech type "
4145 		    "0x%llx\n", (unsigned long long)mechanism->cm_type);
4146 		error = CRYPTO_MECHANISM_INVALID;
4147 	}
4148 
4149 	if ((error != CRYPTO_QUEUED) && (error != CRYPTO_SUCCESS)) {
4150 		plaintext->cd_length = 0;
4151 	}
4152 
4153 	DBG(softc, DENTRY, "dca_decrypt_atomic: done, err = 0x%x", error);
4154 
4155 	return (error);
4156 }
4157 
4158 /*
4159  * Sign entry points.
4160  */
4161 
4162 /* ARGSUSED */
4163 static int
4164 dca_sign_init(crypto_ctx_t *ctx, crypto_mechanism_t *mechanism,
4165     crypto_key_t *key, crypto_spi_ctx_template_t ctx_template,
4166     crypto_req_handle_t req)
4167 {
4168 	int error = CRYPTO_FAILED;
4169 	dca_t *softc;
4170 	/* LINTED E_FUNC_SET_NOT_USED */
4171 	int instance;
4172 
4173 	/* extract softc and instance number from context */
4174 	DCA_SOFTC_FROM_CTX(ctx, softc, instance);
4175 	DBG(softc, DENTRY, "dca_sign_init: started\n");
4176 
4177 	if (ctx_template != NULL)
4178 		return (CRYPTO_ARGUMENTS_BAD);
4179 
4180 	/* check mechanism */
4181 	switch (mechanism->cm_type) {
4182 	case RSA_PKCS_MECH_INFO_TYPE:
4183 	case RSA_X_509_MECH_INFO_TYPE:
4184 		error = dca_rsainit(ctx, mechanism, key, KM_SLEEP);
4185 		break;
4186 	case DSA_MECH_INFO_TYPE:
4187 		error = dca_dsainit(ctx, mechanism, key, KM_SLEEP,
4188 		    DCA_DSA_SIGN);
4189 		break;
4190 	default:
4191 		cmn_err(CE_WARN, "dca_sign_init: unexpected mech type "
4192 		    "0x%llx\n", (unsigned long long)mechanism->cm_type);
4193 		error = CRYPTO_MECHANISM_INVALID;
4194 	}
4195 
4196 	DBG(softc, DENTRY, "dca_sign_init: done, err = 0x%x", error);
4197 
4198 	if (error == CRYPTO_SUCCESS)
4199 		dca_enlist2(&softc->dca_ctx_list, ctx->cc_provider_private,
4200 		    &softc->dca_ctx_list_lock);
4201 
4202 	return (error);
4203 }
4204 
4205 static int
4206 dca_sign(crypto_ctx_t *ctx, crypto_data_t *data,
4207     crypto_data_t *signature, crypto_req_handle_t req)
4208 {
4209 	int error = CRYPTO_FAILED;
4210 	dca_t *softc;
4211 	/* LINTED E_FUNC_SET_NOT_USED */
4212 	int instance;
4213 
4214 	if (!ctx || !ctx->cc_provider || !ctx->cc_provider_private)
4215 		return (CRYPTO_OPERATION_NOT_INITIALIZED);
4216 
4217 	/* extract softc and instance number from context */
4218 	DCA_SOFTC_FROM_CTX(ctx, softc, instance);
4219 	DBG(softc, DENTRY, "dca_sign: started\n");
4220 
4221 	/* check mechanism */
4222 	switch (DCA_MECH_FROM_CTX(ctx)) {
4223 	case RSA_PKCS_MECH_INFO_TYPE:
4224 	case RSA_X_509_MECH_INFO_TYPE:
4225 		error = dca_rsastart(ctx, data, signature, req, DCA_RSA_SIGN);
4226 		break;
4227 	case DSA_MECH_INFO_TYPE:
4228 		error = dca_dsa_sign(ctx, data, signature, req);
4229 		break;
4230 	default:
4231 		cmn_err(CE_WARN, "dca_sign: unexpected mech type "
4232 		    "0x%llx\n", (unsigned long long)DCA_MECH_FROM_CTX(ctx));
4233 		error = CRYPTO_MECHANISM_INVALID;
4234 	}
4235 
4236 	DBG(softc, DENTRY, "dca_sign: done, err = 0x%x", error);
4237 
4238 	return (error);
4239 }
4240 
4241 /* ARGSUSED */
4242 static int
4243 dca_sign_update(crypto_ctx_t *ctx, crypto_data_t *data,
4244     crypto_req_handle_t req)
4245 {
4246 	int error = CRYPTO_MECHANISM_INVALID;
4247 	dca_t *softc;
4248 	/* LINTED E_FUNC_SET_NOT_USED */
4249 	int instance;
4250 
4251 	if (!ctx || !ctx->cc_provider || !ctx->cc_provider_private)
4252 		return (CRYPTO_OPERATION_NOT_INITIALIZED);
4253 
4254 	/* extract softc and instance number from context */
4255 	DCA_SOFTC_FROM_CTX(ctx, softc, instance);
4256 	DBG(softc, DENTRY, "dca_sign_update: started\n");
4257 
4258 	cmn_err(CE_WARN, "dca_sign_update: unexpected mech type "
4259 	    "0x%llx\n", (unsigned long long)DCA_MECH_FROM_CTX(ctx));
4260 
4261 	DBG(softc, DENTRY, "dca_sign_update: done, err = 0x%x", error);
4262 
4263 	return (error);
4264 }
4265 
4266 /* ARGSUSED */
4267 static int
4268 dca_sign_final(crypto_ctx_t *ctx, crypto_data_t *signature,
4269     crypto_req_handle_t req)
4270 {
4271 	int error = CRYPTO_MECHANISM_INVALID;
4272 	dca_t *softc;
4273 	/* LINTED E_FUNC_SET_NOT_USED */
4274 	int instance;
4275 
4276 	if (!ctx || !ctx->cc_provider || !ctx->cc_provider_private)
4277 		return (CRYPTO_OPERATION_NOT_INITIALIZED);
4278 
4279 	/* extract softc and instance number from context */
4280 	DCA_SOFTC_FROM_CTX(ctx, softc, instance);
4281 	DBG(softc, DENTRY, "dca_sign_final: started\n");
4282 
4283 	cmn_err(CE_WARN, "dca_sign_final: unexpected mech type "
4284 	    "0x%llx\n", (unsigned long long)DCA_MECH_FROM_CTX(ctx));
4285 
4286 	DBG(softc, DENTRY, "dca_sign_final: done, err = 0x%x", error);
4287 
4288 	return (error);
4289 }
4290 
4291 static int
4292 dca_sign_atomic(crypto_provider_handle_t provider,
4293     crypto_session_id_t session_id, crypto_mechanism_t *mechanism,
4294     crypto_key_t *key, crypto_data_t *data, crypto_data_t *signature,
4295     crypto_spi_ctx_template_t ctx_template, crypto_req_handle_t req)
4296 {
4297 	int error = CRYPTO_FAILED;
4298 	dca_t *softc = (dca_t *)provider;
4299 
4300 	DBG(softc, DENTRY, "dca_sign_atomic: started\n");
4301 
4302 	if (ctx_template != NULL)
4303 		return (CRYPTO_ARGUMENTS_BAD);
4304 
4305 	/* check mechanism */
4306 	switch (mechanism->cm_type) {
4307 	case RSA_PKCS_MECH_INFO_TYPE:
4308 	case RSA_X_509_MECH_INFO_TYPE:
4309 		error = dca_rsaatomic(provider, session_id, mechanism, key,
4310 		    data, signature, KM_SLEEP, req, DCA_RSA_SIGN);
4311 		break;
4312 	case DSA_MECH_INFO_TYPE:
4313 		error = dca_dsaatomic(provider, session_id, mechanism, key,
4314 		    data, signature, KM_SLEEP, req, DCA_DSA_SIGN);
4315 		break;
4316 	default:
4317 		cmn_err(CE_WARN, "dca_sign_atomic: unexpected mech type "
4318 		    "0x%llx\n", (unsigned long long)mechanism->cm_type);
4319 		error = CRYPTO_MECHANISM_INVALID;
4320 	}
4321 
4322 	DBG(softc, DENTRY, "dca_sign_atomic: done, err = 0x%x", error);
4323 
4324 	return (error);
4325 }
4326 
4327 /* ARGSUSED */
4328 static int
4329 dca_sign_recover_init(crypto_ctx_t *ctx, crypto_mechanism_t *mechanism,
4330     crypto_key_t *key, crypto_spi_ctx_template_t ctx_template,
4331     crypto_req_handle_t req)
4332 {
4333 	int error = CRYPTO_FAILED;
4334 	dca_t *softc;
4335 	/* LINTED E_FUNC_SET_NOT_USED */
4336 	int instance;
4337 
4338 	/* extract softc and instance number from context */
4339 	DCA_SOFTC_FROM_CTX(ctx, softc, instance);
4340 	DBG(softc, DENTRY, "dca_sign_recover_init: started\n");
4341 
4342 	if (ctx_template != NULL)
4343 		return (CRYPTO_ARGUMENTS_BAD);
4344 
4345 	/* check mechanism */
4346 	switch (mechanism->cm_type) {
4347 	case RSA_PKCS_MECH_INFO_TYPE:
4348 	case RSA_X_509_MECH_INFO_TYPE:
4349 		error = dca_rsainit(ctx, mechanism, key, KM_SLEEP);
4350 		break;
4351 	default:
4352 		cmn_err(CE_WARN, "dca_sign_recover_init: unexpected mech type "
4353 		    "0x%llx\n", (unsigned long long)mechanism->cm_type);
4354 		error = CRYPTO_MECHANISM_INVALID;
4355 	}
4356 
4357 	DBG(softc, DENTRY, "dca_sign_recover_init: done, err = 0x%x", error);
4358 
4359 	if (error == CRYPTO_SUCCESS)
4360 		dca_enlist2(&softc->dca_ctx_list, ctx->cc_provider_private,
4361 		    &softc->dca_ctx_list_lock);
4362 
4363 	return (error);
4364 }
4365 
4366 static int
4367 dca_sign_recover(crypto_ctx_t *ctx, crypto_data_t *data,
4368     crypto_data_t *signature, crypto_req_handle_t req)
4369 {
4370 	int error = CRYPTO_FAILED;
4371 	dca_t *softc;
4372 	/* LINTED E_FUNC_SET_NOT_USED */
4373 	int instance;
4374 
4375 	if (!ctx || !ctx->cc_provider || !ctx->cc_provider_private)
4376 		return (CRYPTO_OPERATION_NOT_INITIALIZED);
4377 
4378 	/* extract softc and instance number from context */
4379 	DCA_SOFTC_FROM_CTX(ctx, softc, instance);
4380 	DBG(softc, DENTRY, "dca_sign_recover: started\n");
4381 
4382 	/* check mechanism */
4383 	switch (DCA_MECH_FROM_CTX(ctx)) {
4384 	case RSA_PKCS_MECH_INFO_TYPE:
4385 	case RSA_X_509_MECH_INFO_TYPE:
4386 		error = dca_rsastart(ctx, data, signature, req, DCA_RSA_SIGNR);
4387 		break;
4388 	default:
4389 		cmn_err(CE_WARN, "dca_sign_recover: unexpected mech type "
4390 		    "0x%llx\n", (unsigned long long)DCA_MECH_FROM_CTX(ctx));
4391 		error = CRYPTO_MECHANISM_INVALID;
4392 	}
4393 
4394 	DBG(softc, DENTRY, "dca_sign_recover: done, err = 0x%x", error);
4395 
4396 	return (error);
4397 }
4398 
4399 static int
4400 dca_sign_recover_atomic(crypto_provider_handle_t provider,
4401     crypto_session_id_t session_id, crypto_mechanism_t *mechanism,
4402     crypto_key_t *key, crypto_data_t *data, crypto_data_t *signature,
4403     crypto_spi_ctx_template_t ctx_template, crypto_req_handle_t req)
4404 {
4405 	int error = CRYPTO_FAILED;
4406 	dca_t *softc = (dca_t *)provider;
4407 	/* LINTED E_FUNC_SET_NOT_USED */
4408 	int instance;
4409 
4410 	instance = ddi_get_instance(softc->dca_dip);
4411 	DBG(softc, DENTRY, "dca_sign_recover_atomic: started\n");
4412 
4413 	if (ctx_template != NULL)
4414 		return (CRYPTO_ARGUMENTS_BAD);
4415 
4416 	/* check mechanism */
4417 	switch (mechanism->cm_type) {
4418 	case RSA_PKCS_MECH_INFO_TYPE:
4419 	case RSA_X_509_MECH_INFO_TYPE:
4420 		error = dca_rsaatomic(provider, session_id, mechanism, key,
4421 		    data, signature, KM_SLEEP, req, DCA_RSA_SIGNR);
4422 		break;
4423 	default:
4424 		cmn_err(CE_WARN, "dca_sign_recover_atomic: unexpected mech type"
4425 		    " 0x%llx\n", (unsigned long long)mechanism->cm_type);
4426 		error = CRYPTO_MECHANISM_INVALID;
4427 	}
4428 
4429 	DBG(softc, DENTRY, "dca_sign_recover_atomic: done, err = 0x%x", error);
4430 
4431 	return (error);
4432 }
4433 
4434 /*
4435  * Verify entry points.
4436  */
4437 
4438 /* ARGSUSED */
4439 static int
4440 dca_verify_init(crypto_ctx_t *ctx, crypto_mechanism_t *mechanism,
4441     crypto_key_t *key, crypto_spi_ctx_template_t ctx_template,
4442     crypto_req_handle_t req)
4443 {
4444 	int error = CRYPTO_FAILED;
4445 	dca_t *softc;
4446 	/* LINTED E_FUNC_SET_NOT_USED */
4447 	int instance;
4448 
4449 	/* extract softc and instance number from context */
4450 	DCA_SOFTC_FROM_CTX(ctx, softc, instance);
4451 	DBG(softc, DENTRY, "dca_verify_init: started\n");
4452 
4453 	if (ctx_template != NULL)
4454 		return (CRYPTO_ARGUMENTS_BAD);
4455 
4456 	/* check mechanism */
4457 	switch (mechanism->cm_type) {
4458 	case RSA_PKCS_MECH_INFO_TYPE:
4459 	case RSA_X_509_MECH_INFO_TYPE:
4460 		error = dca_rsainit(ctx, mechanism, key, KM_SLEEP);
4461 		break;
4462 	case DSA_MECH_INFO_TYPE:
4463 		error = dca_dsainit(ctx, mechanism, key, KM_SLEEP,
4464 		    DCA_DSA_VRFY);
4465 		break;
4466 	default:
4467 		cmn_err(CE_WARN, "dca_verify_init: unexpected mech type "
4468 		    "0x%llx\n", (unsigned long long)mechanism->cm_type);
4469 		error = CRYPTO_MECHANISM_INVALID;
4470 	}
4471 
4472 	DBG(softc, DENTRY, "dca_verify_init: done, err = 0x%x", error);
4473 
4474 	if (error == CRYPTO_SUCCESS)
4475 		dca_enlist2(&softc->dca_ctx_list, ctx->cc_provider_private,
4476 		    &softc->dca_ctx_list_lock);
4477 
4478 	return (error);
4479 }
4480 
4481 static int
4482 dca_verify(crypto_ctx_t *ctx, crypto_data_t *data, crypto_data_t *signature,
4483     crypto_req_handle_t req)
4484 {
4485 	int error = CRYPTO_FAILED;
4486 	dca_t *softc;
4487 	/* LINTED E_FUNC_SET_NOT_USED */
4488 	int instance;
4489 
4490 	if (!ctx || !ctx->cc_provider || !ctx->cc_provider_private)
4491 		return (CRYPTO_OPERATION_NOT_INITIALIZED);
4492 
4493 	/* extract softc and instance number from context */
4494 	DCA_SOFTC_FROM_CTX(ctx, softc, instance);
4495 	DBG(softc, DENTRY, "dca_verify: started\n");
4496 
4497 	/* check mechanism */
4498 	switch (DCA_MECH_FROM_CTX(ctx)) {
4499 	case RSA_PKCS_MECH_INFO_TYPE:
4500 	case RSA_X_509_MECH_INFO_TYPE:
4501 		error = dca_rsastart(ctx, signature, data, req, DCA_RSA_VRFY);
4502 		break;
4503 	case DSA_MECH_INFO_TYPE:
4504 		error = dca_dsa_verify(ctx, data, signature, req);
4505 		break;
4506 	default:
4507 		cmn_err(CE_WARN, "dca_verify: unexpected mech type "
4508 		    "0x%llx\n", (unsigned long long)DCA_MECH_FROM_CTX(ctx));
4509 		error = CRYPTO_MECHANISM_INVALID;
4510 	}
4511 
4512 	DBG(softc, DENTRY, "dca_verify: done, err = 0x%x", error);
4513 
4514 	return (error);
4515 }
4516 
4517 /* ARGSUSED */
4518 static int
4519 dca_verify_update(crypto_ctx_t *ctx, crypto_data_t *data,
4520     crypto_req_handle_t req)
4521 {
4522 	int error = CRYPTO_MECHANISM_INVALID;
4523 	dca_t *softc;
4524 	/* LINTED E_FUNC_SET_NOT_USED */
4525 	int instance;
4526 
4527 	if (!ctx || !ctx->cc_provider || !ctx->cc_provider_private)
4528 		return (CRYPTO_OPERATION_NOT_INITIALIZED);
4529 
4530 	/* extract softc and instance number from context */
4531 	DCA_SOFTC_FROM_CTX(ctx, softc, instance);
4532 	DBG(softc, DENTRY, "dca_verify_update: started\n");
4533 
4534 	cmn_err(CE_WARN, "dca_verify_update: unexpected mech type "
4535 	    "0x%llx\n", (unsigned long long)DCA_MECH_FROM_CTX(ctx));
4536 
4537 	DBG(softc, DENTRY, "dca_verify_update: done, err = 0x%x", error);
4538 
4539 	return (error);
4540 }
4541 
4542 /* ARGSUSED */
4543 static int
4544 dca_verify_final(crypto_ctx_t *ctx, crypto_data_t *signature,
4545     crypto_req_handle_t req)
4546 {
4547 	int error = CRYPTO_MECHANISM_INVALID;
4548 	dca_t *softc;
4549 	/* LINTED E_FUNC_SET_NOT_USED */
4550 	int instance;
4551 
4552 	if (!ctx || !ctx->cc_provider || !ctx->cc_provider_private)
4553 		return (CRYPTO_OPERATION_NOT_INITIALIZED);
4554 
4555 	/* extract softc and instance number from context */
4556 	DCA_SOFTC_FROM_CTX(ctx, softc, instance);
4557 	DBG(softc, DENTRY, "dca_verify_final: started\n");
4558 
4559 	cmn_err(CE_WARN, "dca_verify_final: unexpected mech type "
4560 	    "0x%llx\n", (unsigned long long)DCA_MECH_FROM_CTX(ctx));
4561 
4562 	DBG(softc, DENTRY, "dca_verify_final: done, err = 0x%x", error);
4563 
4564 	return (error);
4565 }
4566 
4567 static int
4568 dca_verify_atomic(crypto_provider_handle_t provider,
4569     crypto_session_id_t session_id, crypto_mechanism_t *mechanism,
4570     crypto_key_t *key, crypto_data_t *data, crypto_data_t *signature,
4571     crypto_spi_ctx_template_t ctx_template, crypto_req_handle_t req)
4572 {
4573 	int error = CRYPTO_FAILED;
4574 	dca_t *softc = (dca_t *)provider;
4575 
4576 	DBG(softc, DENTRY, "dca_verify_atomic: started\n");
4577 
4578 	if (ctx_template != NULL)
4579 		return (CRYPTO_ARGUMENTS_BAD);
4580 
4581 	/* check mechanism */
4582 	switch (mechanism->cm_type) {
4583 	case RSA_PKCS_MECH_INFO_TYPE:
4584 	case RSA_X_509_MECH_INFO_TYPE:
4585 		error = dca_rsaatomic(provider, session_id, mechanism, key,
4586 		    signature, data, KM_SLEEP, req, DCA_RSA_VRFY);
4587 		break;
4588 	case DSA_MECH_INFO_TYPE:
4589 		error = dca_dsaatomic(provider, session_id, mechanism, key,
4590 		    data, signature, KM_SLEEP, req, DCA_DSA_VRFY);
4591 		break;
4592 	default:
4593 		cmn_err(CE_WARN, "dca_verify_atomic: unexpected mech type "
4594 		    "0x%llx\n", (unsigned long long)mechanism->cm_type);
4595 		error = CRYPTO_MECHANISM_INVALID;
4596 	}
4597 
4598 	DBG(softc, DENTRY, "dca_verify_atomic: done, err = 0x%x", error);
4599 
4600 	return (error);
4601 }
4602 
4603 /* ARGSUSED */
4604 static int
4605 dca_verify_recover_init(crypto_ctx_t *ctx, crypto_mechanism_t *mechanism,
4606     crypto_key_t *key, crypto_spi_ctx_template_t ctx_template,
4607     crypto_req_handle_t req)
4608 {
4609 	int error = CRYPTO_MECHANISM_INVALID;
4610 	dca_t *softc;
4611 	/* LINTED E_FUNC_SET_NOT_USED */
4612 	int instance;
4613 
4614 	/* extract softc and instance number from context */
4615 	DCA_SOFTC_FROM_CTX(ctx, softc, instance);
4616 	DBG(softc, DENTRY, "dca_verify_recover_init: started\n");
4617 
4618 	if (ctx_template != NULL)
4619 		return (CRYPTO_ARGUMENTS_BAD);
4620 
4621 	/* check mechanism */
4622 	switch (mechanism->cm_type) {
4623 	case RSA_PKCS_MECH_INFO_TYPE:
4624 	case RSA_X_509_MECH_INFO_TYPE:
4625 		error = dca_rsainit(ctx, mechanism, key, KM_SLEEP);
4626 		break;
4627 	default:
4628 		cmn_err(CE_WARN, "dca_verify_recover_init: unexpected mech type"
4629 		    " 0x%llx\n", (unsigned long long)mechanism->cm_type);
4630 	}
4631 
4632 	DBG(softc, DENTRY, "dca_verify_recover_init: done, err = 0x%x", error);
4633 
4634 	if (error == CRYPTO_SUCCESS)
4635 		dca_enlist2(&softc->dca_ctx_list, ctx->cc_provider_private,
4636 		    &softc->dca_ctx_list_lock);
4637 
4638 	return (error);
4639 }
4640 
4641 static int
4642 dca_verify_recover(crypto_ctx_t *ctx, crypto_data_t *signature,
4643     crypto_data_t *data, crypto_req_handle_t req)
4644 {
4645 	int error = CRYPTO_MECHANISM_INVALID;
4646 	dca_t *softc;
4647 	/* LINTED E_FUNC_SET_NOT_USED */
4648 	int instance;
4649 
4650 	if (!ctx || !ctx->cc_provider || !ctx->cc_provider_private)
4651 		return (CRYPTO_OPERATION_NOT_INITIALIZED);
4652 
4653 	/* extract softc and instance number from context */
4654 	DCA_SOFTC_FROM_CTX(ctx, softc, instance);
4655 	DBG(softc, DENTRY, "dca_verify_recover: started\n");
4656 
4657 	/* check mechanism */
4658 	switch (DCA_MECH_FROM_CTX(ctx)) {
4659 	case RSA_PKCS_MECH_INFO_TYPE:
4660 	case RSA_X_509_MECH_INFO_TYPE:
4661 		error = dca_rsastart(ctx, signature, data, req, DCA_RSA_VRFYR);
4662 		break;
4663 	default:
4664 		cmn_err(CE_WARN, "dca_verify_recover: unexpected mech type "
4665 		    "0x%llx\n", (unsigned long long)DCA_MECH_FROM_CTX(ctx));
4666 	}
4667 
4668 	DBG(softc, DENTRY, "dca_verify_recover: done, err = 0x%x", error);
4669 
4670 	return (error);
4671 }
4672 
4673 static int
4674 dca_verify_recover_atomic(crypto_provider_handle_t provider,
4675     crypto_session_id_t session_id, crypto_mechanism_t *mechanism,
4676     crypto_key_t *key, crypto_data_t *data, crypto_data_t *signature,
4677     crypto_spi_ctx_template_t ctx_template, crypto_req_handle_t req)
4678 {
4679 	int error = CRYPTO_MECHANISM_INVALID;
4680 	dca_t *softc = (dca_t *)provider;
4681 
4682 	DBG(softc, DENTRY, "dca_verify_recover_atomic: started\n");
4683 
4684 	if (ctx_template != NULL)
4685 		return (CRYPTO_ARGUMENTS_BAD);
4686 
4687 	/* check mechanism */
4688 	switch (mechanism->cm_type) {
4689 	case RSA_PKCS_MECH_INFO_TYPE:
4690 	case RSA_X_509_MECH_INFO_TYPE:
4691 		error = dca_rsaatomic(provider, session_id, mechanism, key,
4692 		    signature, data, KM_SLEEP, req, DCA_RSA_VRFYR);
4693 		break;
4694 	default:
4695 		cmn_err(CE_WARN, "dca_verify_recover_atomic: unexpected mech "
4696 		    "type 0x%llx\n", (unsigned long long)mechanism->cm_type);
4697 		error = CRYPTO_MECHANISM_INVALID;
4698 	}
4699 
4700 	DBG(softc, DENTRY,
4701 	    "dca_verify_recover_atomic: done, err = 0x%x", error);
4702 
4703 	return (error);
4704 }
4705 
4706 /*
4707  * Random number entry points.
4708  */
4709 
4710 /* ARGSUSED */
4711 static int
4712 dca_generate_random(crypto_provider_handle_t provider,
4713     crypto_session_id_t session_id,
4714     uchar_t *buf, size_t len, crypto_req_handle_t req)
4715 {
4716 	int error = CRYPTO_FAILED;
4717 	dca_t *softc = (dca_t *)provider;
4718 	/* LINTED E_FUNC_SET_NOT_USED */
4719 	int instance;
4720 
4721 	instance = ddi_get_instance(softc->dca_dip);
4722 	DBG(softc, DENTRY, "dca_generate_random: started");
4723 
4724 	error = dca_rng(softc, buf, len, req);
4725 
4726 	DBG(softc, DENTRY, "dca_generate_random: done, err = 0x%x", error);
4727 
4728 	return (error);
4729 }
4730 
4731 /*
4732  * Context management entry points.
4733  */
4734 
4735 int
4736 dca_free_context(crypto_ctx_t *ctx)
4737 {
4738 	int error = CRYPTO_SUCCESS;
4739 	dca_t *softc;
4740 	/* LINTED E_FUNC_SET_NOT_USED */
4741 	int instance;
4742 
4743 	/* extract softc and instance number from context */
4744 	DCA_SOFTC_FROM_CTX(ctx, softc, instance);
4745 	DBG(softc, DENTRY, "dca_free_context: entered");
4746 
4747 	if (ctx->cc_provider_private == NULL)
4748 		return (error);
4749 
4750 	dca_rmlist2(ctx->cc_provider_private, &softc->dca_ctx_list_lock);
4751 
4752 	error = dca_free_context_low(ctx);
4753 
4754 	DBG(softc, DENTRY, "dca_free_context: done, err = 0x%x", error);
4755 
4756 	return (error);
4757 }
4758 
4759 static int
4760 dca_free_context_low(crypto_ctx_t *ctx)
4761 {
4762 	int error = CRYPTO_SUCCESS;
4763 
4764 	/* check mechanism */
4765 	switch (DCA_MECH_FROM_CTX(ctx)) {
4766 	case DES_CBC_MECH_INFO_TYPE:
4767 	case DES3_CBC_MECH_INFO_TYPE:
4768 		dca_3desctxfree(ctx);
4769 		break;
4770 	case RSA_PKCS_MECH_INFO_TYPE:
4771 	case RSA_X_509_MECH_INFO_TYPE:
4772 		dca_rsactxfree(ctx);
4773 		break;
4774 	case DSA_MECH_INFO_TYPE:
4775 		dca_dsactxfree(ctx);
4776 		break;
4777 	default:
4778 		/* Should never reach here */
4779 		cmn_err(CE_WARN, "dca_free_context_low: unexpected mech type "
4780 		    "0x%llx\n", (unsigned long long)DCA_MECH_FROM_CTX(ctx));
4781 		error = CRYPTO_MECHANISM_INVALID;
4782 	}
4783 
4784 	return (error);
4785 }
4786 
4787 
4788 /* Free any unfreed private context. It is called in detach. */
4789 static void
4790 dca_free_context_list(dca_t *dca)
4791 {
4792 	dca_listnode_t	*node;
4793 	crypto_ctx_t	ctx;
4794 
4795 	(void) memset(&ctx, 0, sizeof (ctx));
4796 	ctx.cc_provider = dca;
4797 
4798 	while ((node = dca_delist2(&dca->dca_ctx_list,
4799 	    &dca->dca_ctx_list_lock)) != NULL) {
4800 		ctx.cc_provider_private = node;
4801 		(void) dca_free_context_low(&ctx);
4802 	}
4803 }
4804 
4805 static int
4806 ext_info_sym(crypto_provider_handle_t prov,
4807     crypto_provider_ext_info_t *ext_info, crypto_req_handle_t cfreq)
4808 {
4809 	return (ext_info_base(prov, ext_info, cfreq, IDENT_SYM));
4810 }
4811 
4812 static int
4813 ext_info_asym(crypto_provider_handle_t prov,
4814     crypto_provider_ext_info_t *ext_info, crypto_req_handle_t cfreq)
4815 {
4816 	int rv;
4817 
4818 	rv = ext_info_base(prov, ext_info, cfreq, IDENT_ASYM);
4819 	/* The asymmetric cipher slot supports random */
4820 	ext_info->ei_flags |= CRYPTO_EXTF_RNG;
4821 
4822 	return (rv);
4823 }
4824 
4825 /* ARGSUSED */
4826 static int
4827 ext_info_base(crypto_provider_handle_t prov,
4828     crypto_provider_ext_info_t *ext_info, crypto_req_handle_t cfreq, char *id)
4829 {
4830 	dca_t   *dca = (dca_t *)prov;
4831 	int len;
4832 
4833 	/* Label */
4834 	(void) sprintf((char *)ext_info->ei_label, "%s/%d %s",
4835 	    ddi_driver_name(dca->dca_dip), ddi_get_instance(dca->dca_dip), id);
4836 	len = strlen((char *)ext_info->ei_label);
4837 	(void) memset(ext_info->ei_label + len, ' ',
4838 	    CRYPTO_EXT_SIZE_LABEL - len);
4839 
4840 	/* Manufacturer ID */
4841 	(void) sprintf((char *)ext_info->ei_manufacturerID, "%s",
4842 	    DCA_MANUFACTURER_ID);
4843 	len = strlen((char *)ext_info->ei_manufacturerID);
4844 	(void) memset(ext_info->ei_manufacturerID + len, ' ',
4845 	    CRYPTO_EXT_SIZE_MANUF - len);
4846 
4847 	/* Model */
4848 	(void) sprintf((char *)ext_info->ei_model, dca->dca_model);
4849 
4850 	DBG(dca, DWARN, "kCF MODEL: %s", (char *)ext_info->ei_model);
4851 
4852 	len = strlen((char *)ext_info->ei_model);
4853 	(void) memset(ext_info->ei_model + len, ' ',
4854 	    CRYPTO_EXT_SIZE_MODEL - len);
4855 
4856 	/* Serial Number. Blank for Deimos */
4857 	(void) memset(ext_info->ei_serial_number, ' ', CRYPTO_EXT_SIZE_SERIAL);
4858 
4859 	ext_info->ei_flags = CRYPTO_EXTF_WRITE_PROTECTED;
4860 
4861 	ext_info->ei_max_session_count = CRYPTO_UNAVAILABLE_INFO;
4862 	ext_info->ei_max_pin_len = CRYPTO_UNAVAILABLE_INFO;
4863 	ext_info->ei_min_pin_len = CRYPTO_UNAVAILABLE_INFO;
4864 	ext_info->ei_total_public_memory = CRYPTO_UNAVAILABLE_INFO;
4865 	ext_info->ei_free_public_memory = CRYPTO_UNAVAILABLE_INFO;
4866 	ext_info->ei_total_private_memory = CRYPTO_UNAVAILABLE_INFO;
4867 	ext_info->ei_free_private_memory = CRYPTO_UNAVAILABLE_INFO;
4868 	ext_info->ei_hardware_version.cv_major = 0;
4869 	ext_info->ei_hardware_version.cv_minor = 0;
4870 	ext_info->ei_firmware_version.cv_major = 0;
4871 	ext_info->ei_firmware_version.cv_minor = 0;
4872 
4873 	/* Time. No need to be supplied for token without a clock */
4874 	ext_info->ei_time[0] = '\000';
4875 
4876 	return (CRYPTO_SUCCESS);
4877 }
4878 
4879 static void
4880 dca_fma_init(dca_t *dca)
4881 {
4882 	ddi_iblock_cookie_t fm_ibc;
4883 	int fm_capabilities = DDI_FM_EREPORT_CAPABLE |
4884 	    DDI_FM_ACCCHK_CAPABLE | DDI_FM_DMACHK_CAPABLE |
4885 	    DDI_FM_ERRCB_CAPABLE;
4886 
4887 	/* Read FMA capabilities from dca.conf file (if present) */
4888 	dca->fm_capabilities = ddi_getprop(DDI_DEV_T_ANY, dca->dca_dip,
4889 	    DDI_PROP_CANSLEEP | DDI_PROP_DONTPASS, "fm-capable",
4890 	    fm_capabilities);
4891 
4892 	DBG(dca, DWARN, "dca->fm_capabilities = 0x%x", dca->fm_capabilities);
4893 
4894 	/* Only register with IO Fault Services if we have some capability */
4895 	if (dca->fm_capabilities) {
4896 		dca_regsattr.devacc_attr_access = DDI_FLAGERR_ACC;
4897 		dca_dmaattr.dma_attr_flags = DDI_DMA_FLAGERR;
4898 
4899 		/* Register capabilities with IO Fault Services */
4900 		ddi_fm_init(dca->dca_dip, &dca->fm_capabilities, &fm_ibc);
4901 		DBG(dca, DWARN, "fm_capable() =  0x%x",
4902 		    ddi_fm_capable(dca->dca_dip));
4903 
4904 		/*
4905 		 * Initialize pci ereport capabilities if ereport capable
4906 		 */
4907 		if (DDI_FM_EREPORT_CAP(dca->fm_capabilities) ||
4908 		    DDI_FM_ERRCB_CAP(dca->fm_capabilities))
4909 			pci_ereport_setup(dca->dca_dip);
4910 
4911 		/*
4912 		 * Initialize callback mutex and register error callback if
4913 		 * error callback capable.
4914 		 */
4915 		if (DDI_FM_ERRCB_CAP(dca->fm_capabilities)) {
4916 			ddi_fm_handler_register(dca->dca_dip, dca_fm_error_cb,
4917 			    (void *)dca);
4918 		}
4919 	} else {
4920 		/*
4921 		 * These fields have to be cleared of FMA if there are no
4922 		 * FMA capabilities at runtime.
4923 		 */
4924 		dca_regsattr.devacc_attr_access = DDI_DEFAULT_ACC;
4925 		dca_dmaattr.dma_attr_flags = 0;
4926 	}
4927 }
4928 
4929 
4930 static void
4931 dca_fma_fini(dca_t *dca)
4932 {
4933 	/* Only unregister FMA capabilities if we registered some */
4934 	if (dca->fm_capabilities) {
4935 
4936 		/*
4937 		 * Release any resources allocated by pci_ereport_setup()
4938 		 */
4939 		if (DDI_FM_EREPORT_CAP(dca->fm_capabilities) ||
4940 		    DDI_FM_ERRCB_CAP(dca->fm_capabilities)) {
4941 			pci_ereport_teardown(dca->dca_dip);
4942 		}
4943 
4944 		/*
4945 		 * Free callback mutex and un-register error callback if
4946 		 * error callback capable.
4947 		 */
4948 		if (DDI_FM_ERRCB_CAP(dca->fm_capabilities)) {
4949 			ddi_fm_handler_unregister(dca->dca_dip);
4950 		}
4951 
4952 		/* Unregister from IO Fault Services */
4953 		ddi_fm_fini(dca->dca_dip);
4954 		DBG(dca, DWARN, "fm_capable() = 0x%x",
4955 		    ddi_fm_capable(dca->dca_dip));
4956 	}
4957 }
4958 
4959 
4960 /*
4961  * The IO fault service error handling callback function
4962  */
4963 /*ARGSUSED*/
4964 static int
4965 dca_fm_error_cb(dev_info_t *dip, ddi_fm_error_t *err, const void *impl_data)
4966 {
4967 	dca_t		*dca = (dca_t *)impl_data;
4968 
4969 	pci_ereport_post(dip, err, NULL);
4970 	if (err->fme_status == DDI_FM_FATAL) {
4971 		dca_failure(dca, DDI_DATAPATH_FAULT,
4972 		    DCA_FM_ECLASS_NONE, dca_ena(0), CRYPTO_DEVICE_ERROR,
4973 		    "fault PCI in FMA callback.");
4974 	}
4975 	return (err->fme_status);
4976 }
4977 
4978 
4979 static int
4980 dca_check_acc_handle(dca_t *dca, ddi_acc_handle_t handle,
4981     dca_fma_eclass_t eclass_index)
4982 {
4983 	ddi_fm_error_t	de;
4984 	int		version = 0;
4985 
4986 	ddi_fm_acc_err_get(handle, &de, version);
4987 	if (de.fme_status != DDI_FM_OK) {
4988 		dca_failure(dca, DDI_DATAPATH_FAULT,
4989 		    eclass_index, fm_ena_increment(de.fme_ena),
4990 		    CRYPTO_DEVICE_ERROR, "");
4991 		return (DDI_FAILURE);
4992 	}
4993 
4994 	return (DDI_SUCCESS);
4995 }
4996 
4997 int
4998 dca_check_dma_handle(dca_t *dca, ddi_dma_handle_t handle,
4999     dca_fma_eclass_t eclass_index)
5000 {
5001 	ddi_fm_error_t	de;
5002 	int		version = 0;
5003 
5004 	ddi_fm_dma_err_get(handle, &de, version);
5005 	if (de.fme_status != DDI_FM_OK) {
5006 		dca_failure(dca, DDI_DATAPATH_FAULT,
5007 		    eclass_index, fm_ena_increment(de.fme_ena),
5008 		    CRYPTO_DEVICE_ERROR, "");
5009 		return (DDI_FAILURE);
5010 	}
5011 	return (DDI_SUCCESS);
5012 }
5013 
5014 static uint64_t
5015 dca_ena(uint64_t ena)
5016 {
5017 	if (ena == 0)
5018 		ena = fm_ena_generate(0, FM_ENA_FMT1);
5019 	else
5020 		ena = fm_ena_increment(ena);
5021 	return (ena);
5022 }
5023 
5024 static char *
5025 dca_fma_eclass_string(char *model, dca_fma_eclass_t index)
5026 {
5027 	if (strstr(model, "500"))
5028 		return (dca_fma_eclass_sca500[index]);
5029 	else
5030 		return (dca_fma_eclass_sca1000[index]);
5031 }
5032