dca.c revision 3383b6dda001791704e0e66f7b78dd0dfe74f547
/*
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
* Common Development and Distribution License (the "License").
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
* See the License for the specific language governing permissions
* and limitations under the License.
*
* When distributing Covered Code, include this CDDL HEADER in each
* file and include the License file at usr/src/OPENSOLARIS.LICENSE.
* If applicable, add the following below this CDDL HEADER, with the
* fields enclosed by brackets "[]" replaced with your own identifying
* information: Portions Copyright [yyyy] [name of copyright owner]
*
* CDDL HEADER END
*/
/*
* Copyright 2006 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
#pragma ident "%Z%%M% %I% %E% SMI"
/*
* Deimos - cryptographic acceleration based upon Broadcom 582x.
*/
/*
* Core Deimos driver.
*/
kmutex_t *);
static int dca_suspend(dca_t *);
static int dca_resume(dca_t *);
static void dca_uninit(dca_t *);
static void dca_initq(dca_listnode_t *);
static void dca_freework(dca_work_t *);
static void dca_destroywork(dca_work_t *);
static void dca_schedule(dca_t *, int);
static void dca_reclaim(dca_t *, int);
static void dca_jobtimeout(void *);
static void dca_undrain(dca_t *);
static void dca_rejectjobs(dca_t *);
#ifdef SCHEDDELAY
static void dca_schedtimeout(void *);
#endif
/*
* We want these inlined for performance.
*/
#ifndef DEBUG
#pragma inline(dca_reverse, dca_length)
#endif
/*
* Device operations.
*/
DEVO_REV, /* devo_rev */
0, /* devo_refcnt */
nodev, /* devo_getinfo */
nulldev, /* devo_identify */
nulldev, /* devo_probe */
dca_attach, /* devo_attach */
dca_detach, /* devo_detach */
nodev, /* devo_reset */
NULL, /* devo_cb_ops */
NULL, /* devo_bus_ops */
ddi_power /* devo_power */
};
#define IDENT "PCI Crypto Accelerator 2.0"
#define IDENT_SYM "Crypto Accel Sym 2.0"
#define IDENT_ASYM "Crypto Accel Asym 2.0"
/* Space-padded, will be filled in dynamically during registration */
#define IDENT3 "PCI Crypto Accelerator Mod 2.0"
#define VENDOR "Sun Microsystems, Inc."
/* A 28 char function name doesn't leave much line space */
/*
* Module linkage.
*/
&mod_driverops, /* drv_modops */
IDENT, /* drv_linkinfo */
&devops, /* drv_dev_ops */
};
extern struct mod_ops mod_cryptoops;
static struct modlcrypto modlcrypto = {
};
static struct modlinkage modlinkage = {
MODREV_1, /* ml_rev */
&modldrv, /* ml_linkage */
};
/*
* CSPI information (entry points, provider info, etc.)
*/
/* Mechanisms for the symmetric cipher provider */
static crypto_mech_info_t dca_mech_info_tab1[] = {
/* DES-CBC */
/* 3DES-CBC */
};
/* Mechanisms for the asymmetric cipher provider */
static crypto_mech_info_t dca_mech_info_tab2[] = {
/* DSA */
/* RSA */
};
static crypto_control_ops_t dca_control_ops = {
};
static crypto_cipher_ops_t dca_cipher_ops = {
};
static int dca_sign_recover_atomic(crypto_provider_handle_t,
static crypto_sign_ops_t dca_sign_ops = {
};
static int dca_verify_recover_atomic(crypto_provider_handle_t,
static crypto_verify_ops_t dca_verify_ops = {
};
static crypto_random_number_ops_t dca_random_number_ops = {
NULL,
};
ext_info_sym, /* ext_info */
NULL, /* init_token */
NULL, /* init_pin */
NULL /* set_pin */
};
ext_info_asym, /* ext_info */
NULL, /* init_token */
NULL, /* init_pin */
NULL /* set_pin */
};
int dca_free_context(crypto_ctx_t *);
static crypto_ctx_ops_t dca_ctx_ops = {
NULL,
};
/* Operations for the symmetric cipher provider */
static crypto_ops_t dca_crypto_ops1 = {
NULL, /* digest_ops */
NULL, /* mac_ops */
NULL, /* sign_ops */
NULL, /* verify_ops */
NULL, /* dual_ops */
NULL, /* cipher_mac_ops */
NULL, /* random_number_ops */
NULL, /* session_ops */
NULL, /* object_ops */
NULL, /* key_ops */
&dca_provmanage_ops_1, /* management_ops */
};
/* Operations for the asymmetric cipher provider */
static crypto_ops_t dca_crypto_ops2 = {
NULL, /* digest_ops */
NULL, /* mac_ops */
NULL, /* dual_ops */
NULL, /* cipher_mac_ops */
NULL, /* session_ops */
NULL, /* object_ops */
NULL, /* key_ops */
&dca_provmanage_ops_2, /* management_ops */
};
/* Provider information for the symmetric cipher provider */
static crypto_provider_info_t dca_prov_info1 = {
NULL, /* pi_provider_description */
NULL, /* pi_provider_dev */
NULL, /* pi_provider_handle */
sizeof (dca_mech_info_tab1)/sizeof (crypto_mech_info_t),
0, /* pi_logical_provider_count */
NULL /* pi_logical_providers */
};
/* Provider information for the asymmetric cipher provider */
static crypto_provider_info_t dca_prov_info2 = {
NULL, /* pi_provider_description */
NULL, /* pi_provider_dev */
NULL, /* pi_provider_handle */
sizeof (dca_mech_info_tab2)/sizeof (crypto_mech_info_t),
0, /* pi_logical_provider_count */
NULL /* pi_logical_providers */
};
/* Convenience macros */
/* Retrieve the softc and instance number from a SPI crypto context */
}
#define DCA_MECH_FROM_CTX(ctx) \
const void *impl_data);
static dca_device_t dca_devices[] = {
/* Broadcom vanilla variants */
{ 0x14e4, 0x5820, "Broadcom 5820" },
{ 0x14e4, 0x5821, "Broadcom 5821" },
{ 0x14e4, 0x5822, "Broadcom 5822" },
{ 0x14e4, 0x5825, "Broadcom 5825" },
/* Sun specific OEMd variants */
{ 0x108e, 0x5454, "SCA" },
{ 0x108e, 0x5455, "SCA 1000" },
{ 0x108e, 0x5457, "SCA 500" },
/* subsysid should be 0x5457, but got 0x1 from HW. Assume both here. */
{ 0x108e, 0x1, "SCA 500" },
};
/*
* Device attributes.
*/
static struct ddi_device_acc_attr dca_regsattr = {
};
static struct ddi_device_acc_attr dca_devattr = {
};
static struct ddi_device_acc_attr dca_bufattr = {
};
#endif
static struct ddi_dma_attr dca_dmaattr = {
DMA_ATTR_V0, /* dma_attr_version */
0x0, /* dma_attr_addr_lo */
0xffffffffUL, /* dma_attr_addr_hi */
0x00ffffffUL, /* dma_attr_count_max */
0x40, /* dma_attr_align */
0x40, /* dma_attr_burstsizes */
0x1, /* dma_attr_minxfer */
0x00ffffffUL, /* dma_attr_maxxfer */
0xffffffffUL, /* dma_attr_seg */
512, /* dma_attr_sgllen */
#else
1, /* dma_attr_sgllen */
#endif
1, /* dma_attr_granular */
DDI_DMA_FLAGERR /* dma_attr_flags */
};
int dca_mindma = 2500;
/*
* FMA eclass string definitions. Note that these string arrays must be
* consistent with the dca_fma_eclass_t enum.
*/
static char *dca_fma_eclass_sca1000[] = {
"sca1000.hw.device",
"sca1000.hw.timeout",
"sca1000.none"
};
static char *dca_fma_eclass_sca500[] = {
"sca500.hw.device",
"sca500.hw.timeout",
"sca500.none"
};
/*
* DDI entry points.
*/
int
_init(void)
{
int rv;
/* this should *never* happen! */
return (rv);
}
/* cleanup here */
return (rv);
}
return (0);
}
int
_fini(void)
{
int rv;
/* cleanup here */
}
return (rv);
}
int
{
}
int
{
int instance;
int intr_added = 0;
int i;
int ret;
char ID[64];
static char *unknowndev = "Unknown device";
#if DEBUG
/* these are only used for debugging */
#endif
switch (cmd) {
case DDI_RESUME:
return (DDI_FAILURE);
}
/* assumption: we won't be DDI_DETACHed until we return */
return (dca_resume(dca));
case DDI_ATTACH:
break;
default:
return (DDI_FAILURE);
}
return (DDI_FAILURE);
}
if (ddi_intr_hilevel(dip, 0) != 0) {
return (DDI_FAILURE);
}
return (DDI_FAILURE);
}
/* common PCI attributes */
/*
* Broadcom-specific timings.
* incorrect false failures when the bus is just a little
* bit slow, or busy.
*/
/* initialize PCI access settings */
/* set up our PCI latency timer */
#if DEBUG
/* read registers (for debugging) */
#endif
return (DDI_FAILURE);
}
return (DDI_FAILURE);
}
/* figure pagesize */
/*
* Search for the device in our supported devices table. This
* is here for two reasons. First, we want to ensure that
* only Sun-qualified (and presumably Sun-labeled) devices can
* be used with this driver. Second, some devices have
* specific differences. E.g. the 5821 has support for a
* special mode of RC4, deeper queues, power management, and
* other changes. Also, the export versions of some of these
* chips don't support RC4 or 3DES, so we catch that here.
*
* Note that we only look at the upper nibble of the device
* id, which is used to distinguish export vs. domestic
* versions of the chip. (The lower nibble is used for
* stepping information.)
*/
for (i = 0; i < (sizeof (dca_devices) / sizeof (dca_device_t)); i++) {
/*
* Try to match the subsystem information first.
*/
break;
}
/*
* Failing that, try the generic vendor and device id.
* Even if we find a match, we keep searching anyway,
* since we would prefer to find a match based on the
* subsystem ids.
*/
}
}
/* try and handle an unrecognized device */
}
return (DDI_FAILURE);
}
/*
* initialize locks, etc.
*/
/* use RNGSHA1 by default */
}
/* initialize FMA */
/* initialize some key data structures */
goto failed;
}
/* initialize kstats */
/* setup access to registers */
goto failed;
}
/* reset the chip */
goto failed;
}
/* initialize the chip */
DCA_FM_ECLASS_NONE) != DDI_SUCCESS) {
goto failed;
}
/* add the interrupt */
(void *)dca) != DDI_SUCCESS) {
goto failed;
} else {
intr_added = 1;
}
/* enable interrupts on the device */
/*
* XXX: Note, 5820A1 errata indicates that this may clobber
* bits 24 and 23, which affect the speed of the RNG. Since
* we always want to run in full-speed mode, this should be
* harmless.
*/
/* for 5825 - increase the DMA read size */
} else {
}
DCA_FM_ECLASS_NONE) != DDI_SUCCESS) {
goto failed;
}
/* register MCR1 with the crypto framework */
/* Be careful not to exceed 32 chars */
"crypto_register_provider() failed (%d) for MCR1", ret);
goto failed;
}
/* register MCR2 with the crypto framework */
/* Be careful not to exceed 32 chars */
"crypto_register_provider() failed (%d) for MCR2", ret);
goto failed;
}
/* Initialize the local random number pool for this instance */
goto failed;
}
}
return (DDI_SUCCESS);
/* unregister from the crypto framework */
}
}
if (intr_added) {
/* unregister intr handler */
}
if (dca->dca_regs_handle) {
}
if (dca->dca_intrstats) {
}
}
/* finalize FMA */
return (DDI_FAILURE);
}
int
{
int instance;
switch (cmd) {
case DDI_SUSPEND:
return (DDI_FAILURE);
}
/* assumption: we won't be DDI_DETACHed until we return */
return (dca_suspend(dca));
case DDI_DETACH:
break;
default:
return (DDI_FAILURE);
}
return (DDI_FAILURE);
}
/*
* Unregister from kCF.
* This needs to be done at the beginning of detach.
*/
return (DDI_FAILURE);
}
}
return (DDI_FAILURE);
}
}
/*
* Cleanup the private context list. Once the
* crypto_unregister_provider returns, it is safe to do so.
*/
/* Cleanup the local random number pool */
/* send any jobs in the waitq back to kCF */
/* untimeout the timeouts */
dca->dca_jobtid = 0;
if (tid) {
}
/* disable device interrupts */
/* unregister interrupt handlers */
/* release our regs handle */
/* toss out kstats */
if (dca->dca_intrstats) {
}
}
/* finalize FMA */
return (DDI_SUCCESS);
}
int
{
return (DDI_FAILURE);
}
/*
* Reprogram registers in PCI configuration space.
*/
/* Broadcom-specific timers -- we disable them. */
/* initialize PCI access settings */
/* set up our PCI latency timer */
return (DDI_FAILURE);
}
/*
* Now restore the card-specific CSRs.
*/
/* restore endianness settings */
return (DDI_FAILURE);
/* restore interrupt enables */
/* for 5825 set 256 byte read size to improve performance */
} else {
}
return (DDI_FAILURE);
/* resume scheduling jobs on the device */
return (DDI_SUCCESS);
}
int
{
return (DDI_FAILURE);
}
return (DDI_FAILURE);
}
return (DDI_SUCCESS);
}
/*
* Hardware access stuff.
*/
int
{
int i;
return (-1);
}
if (!failreset) {
return (-1);
}
/* now wait for a reset */
for (i = 1; i < 100; i++) {
drv_usecwait(100);
if (!failreset) {
return (-1);
}
if ((dmactl & DMACTL_RESET) == 0) {
return (0);
}
}
if (!failreset) {
"timeout waiting for reset after %d usec", i * 100);
}
return (-1);
}
int
{
int i;
/*
* Set up work queue.
*/
dca->dca_icookie);
for (i = 0; i < MAXWORK; i++) {
return (DDI_FAILURE);
}
}
for (i = 0; i < reqprealloc; i++) {
return (DDI_FAILURE);
}
}
return (DDI_SUCCESS);
}
int
{
/* Initialize the private context list and the corresponding lock. */
/*
* MCR1 algorithms.
*/
"mcr1_lowater", MCR1LOWATER);
"mcr1_hiwater", MCR1HIWATER);
return (DDI_FAILURE);
}
/*
* MCR2 algorithms.
*/
"mcr2_lowater", MCR2LOWATER);
"mcr2_hiwater", MCR2HIWATER);
return (DDI_FAILURE);
}
return (DDI_SUCCESS);
}
/*
* Uninitialize worklists. This routine should only be called when no
* active jobs (hence DMA mappings) exist. One way to ensure this is
* to unregister from kCF before calling this routine. (This is done
* e.g. in detach(9e).)
*/
void
{
int mcr;
continue;
}
}
}
}
}
static void
{
if (!q || !node)
return;
}
static void
{
if (!node)
return;
}
static dca_listnode_t *
{
return (NULL);
}
return (node);
}
void
{
q->dl_next = q;
q->dl_prev = q;
q->dl_next2 = q;
q->dl_prev2 = q;
}
void
{
/*
* Enqueue submits at the "tail" of the list, i.e. just
* behind the sentinel.
*/
}
void
{
}
{
/*
* Dequeue takes from the "head" of the list, i.e. just after
* the sentinel.
*/
/* queue is empty */
return (NULL);
}
return (node);
}
/* this is the opposite of dequeue, it takes things off in LIFO order */
{
/*
* unqueue takes from the "tail" of the list, i.e. just before
* the sentinel.
*/
/* queue is empty */
return (NULL);
}
return (node);
}
{
return (NULL);
} else {
return (node);
}
}
/*
* Interrupt service routine.
*/
{
DCA_FM_ECLASS_NONE) != DDI_SUCCESS) {
return ((uint_t)DDI_FAILURE);
}
if ((status & DMASTAT_INTERRUPTS) == 0) {
/* increment spurious interrupt kstat */
if (dca->dca_intrstats) {
}
return (DDI_INTR_UNCLAIMED);
}
if (dca->dca_intrstats) {
}
if (status & DMASTAT_MCR1INT) {
}
if (status & DMASTAT_MCR2INT) {
}
if (status & DMASTAT_ERRINT) {
/*
* bit 1 of the error address indicates failure during
* read if set, during write otherwise.
*/
"DMA master access error %s address 0x%x",
return (DDI_INTR_CLAIMED);
}
return (DDI_INTR_CLAIMED);
}
/*
* Reverse a string of bytes from s1 into s2. The reversal happens
* from the tail of s1. If len1 < len2, then null bytes will be
* padded to the end of s2. If len2 < len1, then (presumably null)
* bytes will be dropped from the start of s1.
*
* The rationale here is that when s1 (source) is shorter, then we
* are reversing from big-endian ordering, into device ordering, and
* want to add some extra nulls to the tail (MSB) side of the device.
*
* Similarly, when s2 (dest) is shorter, then we are truncating what
* are presumably null MSB bits from the device.
*
* There is an expectation when reversing from the device back into
* big-endian, that the number of bytes to reverse and the target size
* will match, and no truncation or padding occurs.
*/
void
{
if (len1 == 0) {
if (len2) {
}
return;
}
len2--;
}
while (len2 > 0) {
*dst++ = 0;
len2--;
}
}
dca_padfull(int num)
{
if (num <= 512) {
return (BITS2BYTES(512));
}
if (num <= 768) {
return (BITS2BYTES(768));
}
if (num <= 1024) {
return (BITS2BYTES(1024));
}
if (num <= 1536) {
return (BITS2BYTES(1536));
}
if (num <= 2048) {
return (BITS2BYTES(2048));
}
return (0);
}
dca_padhalf(int num)
{
if (num <= 256) {
return (BITS2BYTES(256));
}
if (num <= 384) {
return (BITS2BYTES(384));
}
if (num <= 512) {
return (BITS2BYTES(512));
}
if (num <= 768) {
return (BITS2BYTES(768));
}
if (num <= 1024) {
return (BITS2BYTES(1024));
}
return (0);
}
{
unsigned nc;
int rv;
if (rv != 0) {
return (NULL);
}
if (rv != 0) {
return (NULL);
}
if (rv != DDI_DMA_MAPPED) {
return (NULL);
}
return (workp);
}
void
{
if (workp->dw_mcr_paddr) {
}
if (workp->dw_mcr_acch) {
}
if (workp->dw_mcr_dmah) {
}
}
{
unsigned nc;
int rv;
int n_chain = 0;
/*
* Setup the DMA region for the context and descriptors.
*/
if (rv != DDI_SUCCESS) {
return (NULL);
}
/* for driver hardening, allocate in whole pages */
&reqp->dr_ctx_acch);
if (rv != DDI_SUCCESS) {
return (NULL);
}
DDI_DMA_SLEEP, 0, &c, &nc);
if (rv != DDI_DMA_MAPPED) {
return (NULL);
}
/*
*/
if (rv != DDI_SUCCESS) {
return (NULL);
}
if (rv != DDI_SUCCESS) {
return (NULL);
}
if (rv != DDI_SUCCESS) {
return (NULL);
}
if (rv != DDI_SUCCESS) {
return (NULL);
}
/*
* for driver hardening, allocate in whole pages.
*/
/*
* Use kmem_alloc instead of ddi_dma_mem_alloc here since the latter
* may fail on x86 platform if a physically contigous memory chunk
* cannot be found. From initial testing, we did not see performance
* degration as seen on Sparc.
*/
return (NULL);
}
return (NULL);
}
#else
/*
* We could kmem_alloc for sparc too. However, it gives worse
* performance when transfering more than one page data. For example,
* using 4 threads and 12032 byte data and 3DES on 900MHZ sparc system,
* kmem_alloc uses 80% CPU and ddi_dma_mem_alloc uses 50% CPU for
* the same throughput.
*/
size, &dca_bufattr,
if (rv != DDI_SUCCESS) {
return (NULL);
}
size, &dca_bufattr,
if (rv != DDI_SUCCESS) {
return (NULL);
}
#endif
/* Skip the used portion in the context page */
(void) dca_destroyreq(reqp);
return (NULL);
}
/* Skip the space used by the input buffer */
(void) dca_destroyreq(reqp);
return (NULL);
}
/* Skip the space used by the output buffer */
return (reqp);
}
void
{
#endif
/*
* Clean up DMA for the context structure.
*/
if (reqp->dr_ctx_paddr) {
}
if (reqp->dr_ctx_acch) {
}
if (reqp->dr_ctx_dmah) {
}
/*
* Clean up DMA for the scratch buffer.
*/
if (reqp->dr_ibuf_dmah) {
}
if (reqp->dr_obuf_dmah) {
}
#else
if (reqp->dr_ibuf_paddr) {
}
if (reqp->dr_obuf_paddr) {
}
if (reqp->dr_ibuf_acch) {
}
if (reqp->dr_obuf_acch) {
}
if (reqp->dr_ibuf_dmah) {
}
if (reqp->dr_obuf_dmah) {
}
#endif
/*
* These two DMA handles should have been unbinded in
* dca_unbindchains() function
*/
if (reqp->dr_chain_in_dmah) {
}
if (reqp->dr_chain_out_dmah) {
}
}
{
if (workp) {
int nreqs;
/* clear out old requests */
}
}
return (workp);
}
void
{
}
{
if (reqp) {
} else if (tryhard) {
/*
* failed to get a free one, try an allocation, the hard way.
* XXX: Kstat desired here.
*/
}
}
return (reqp);
}
void
{
(dca_listnode_t *)reqp);
}
}
/*
* Binds user buffers to DMA handles dynamically. On Sparc, a user buffer
* is mapped to a single physicall address. On x86, a user buffer is mapped
* to multiple physically addresses. These phsyical addresses are chained
* using the method specified in Broadcom BCM5820 specification
*/
int
{
int rv;
int n_chain = 0;
} else {
}
/* first the input */
if (incnt) {
return (DDI_FAILURE);
}
(void) dca_unbindchains(reqp);
return (rv);
}
/*
* The offset and length are altered by the calling routine
* reqp->dr_in->cd_offset += incnt;
* reqp->dr_in->cd_length -= incnt;
*/
/* Save the first one in the chain for MCR */
} else {
reqp->dr_in_next = 0;
}
return (DDI_SUCCESS);
}
/* then the output */
if (outcnt) {
(void) dca_unbindchains(reqp);
return (DDI_FAILURE);
}
if (rv != DDI_SUCCESS) {
(void) dca_unbindchains(reqp);
return (DDI_FAILURE);
}
/* Save the first one in the chain for MCR */
} else {
reqp->dr_out_next = 0;
reqp->dr_out_len = 0;
}
return (DDI_SUCCESS);
}
/*
* Unbind the user buffers from the DMA handles.
*/
int
{
int rv = DDI_SUCCESS;
int rv1 = DDI_SUCCESS;
/* Clear the input chain */
}
/* Clear the output chain */
}
}
/*
* Build either input chain or output chain. It is single-item chain for Sparc,
* and possible mutiple-item chain for x86.
*/
static int
{
int rv;
int i;
/* Advance past the context structure to the starting address */
/*
* Bind the kernel address to the DMA handle. On x86, the actual
* buffer is mapped into multiple physical addresses. On Sparc,
* the actual buffer is mapped into a single address.
*/
if (rv != DDI_DMA_MAPPED) {
return (DDI_FAILURE);
}
DCA_FM_ECLASS_NONE)) != DDI_SUCCESS) {
return (rv);
}
/* Setup the data buffer chain for DMA transfer */
head->dc_buffer_paddr = 0;
head->dc_next_paddr = 0;
head->dc_buffer_length = 0;
for (i = 0; i < nc; i++) {
/* PIO */
/* Remember the head of the chain */
if (head->dc_buffer_paddr == 0) {
}
/* Link to the previous one if one exists */
if (chain_kaddr_pre) {
if (head->dc_next_paddr == 0)
}
/* Maintain pointers */
chain_paddr += DESC_SIZE;
chain_kaddr += DESC_SIZE;
/* Retrieve the next cookie if there is one */
if (i < nc-1)
ddi_dma_nextcookie(handle, &c);
}
/* Set the next pointer in the last entry to NULL */
return (DDI_SUCCESS);
}
/*
* Schedule some work.
*/
int
{
/* sync out the entire context and descriptor chains */
DCA_FM_ECLASS_NONE) != DDI_SUCCESS) {
return (CRYPTO_DEVICE_ERROR);
}
/* we are fully loaded now, let kCF know */
wlp->dwl_flowctl++;
}
if (dosched) {
#ifdef SCHEDDELAY
/* possibly wait for more work to arrive */
} else if (!wlp->dwl_schedtid) {
/* wait 1 msec for more work before doing it */
}
#else
#endif
}
return (CRYPTO_QUEUED);
}
void
{
int csr;
int full;
/*
* If the card is draining or has an outstanding failure,
* don't schedule any more work on it right now
*/
return;
}
} else {
}
for (;;) {
int nreqs;
return;
break;
#ifdef SCHEDDELAY
/* if there isn't enough to do, don't bother now */
drv_usectohz(MSEC)))) {
/* wait a bit longer... */
if (wlp->dwl_schedtid == 0) {
}
return;
}
#endif
/* grab a work structure */
/*
* There must be work ready to be reclaimed,
* in this case, since the chip can only hold
* less work outstanding than there are total.
*/
continue;
}
nreqs = 0;
/* nothing left to process */
break;
}
/*
* Update flow control.
*/
}
/*
* Context address.
*/
offset += 4;
/*
* Input chain.
*/
/* input buffer address */
offset += 4;
/* next input buffer entry */
offset += 4;
/* input buffer length */
offset += 2;
/* zero the reserved field */
offset += 2;
/*
* Overall length.
*/
/* reserved field */
offset += 2;
/* total packet length */
offset += 2;
/*
* Output chain.
*/
/* output buffer address */
offset += 4;
/* next output buffer entry */
offset += 4;
/* output buffer length */
offset += 2;
/* zero the reserved field */
offset += 2;
/*
* Note submission.
*/
nreqs++;
}
if (nreqs == 0) {
/* nothing in the queue! */
return;
}
wlp->dwl_submit++;
"posting work (phys %x, virt 0x%p) (%d reqs) to MCR%d",
/* Make sure MCR is synced out to device. */
DCA_FM_ECLASS_NONE) != DDI_SUCCESS) {
return;
}
DCA_FM_ECLASS_NONE) != DDI_SUCCESS) {
return;
} else {
}
}
}
/*
* Reclaim completed work, called in interrupt context.
*/
void
{
int nreclaimed = 0;
int i;
/*
* For each MCR in the submitted (runq), we check to see if
* it has been processed. If so, then we note each individual
* job in the MCR, and and do the completion processing for
* each of such job.
*/
for (;;) {
break;
}
/* only sync the MCR flags, since that's all we need */
DCA_FM_ECLASS_NONE) != DDI_SUCCESS) {
return;
}
if ((flags & MCRFLAG_FINISHED) == 0) {
/* chip is still working on it */
"chip still working on it (MCR%d)", mcr);
break;
}
/* its really for us, so remove it from the queue */
/* if we were draining, signal on the cv */
}
/* update statistics, done under the lock */
for (i = 0; i < wlp->dwl_reqspermcr; i++) {
continue;
}
if (reqp->dr_byte_stat >= 0) {
}
if (reqp->dr_job_stat >= 0) {
}
}
for (i = 0; i < wlp->dwl_reqspermcr; i++) {
continue;
}
/* Do the callback. */
nreclaimed++;
}
/* now we can release the work */
}
}
int
{
}
/*
* This is the callback function called from the interrupt when a kCF job
* completes. It does some driver-specific things, and then calls the
* kCF-provided callback. Finally, it cleans up the state for the work
* request and drops the reference count to allow for DR.
*/
void
{
/* unbind any chains we were using */
/* DMA failure */
"fault on buffer DMA handle");
if (err == CRYPTO_SUCCESS) {
}
}
} else {
}
}
/*
* Call this when a failure is detected. It will reset the chip,
* log a message, alert kCF, and mark jobs in the runq as failed.
*/
/* ARGSUSED */
void
{
char buf[256];
int mcr;
char *eclass;
int have_mutex;
index != DCA_FM_ECLASS_NONE) {
/* Report the impact of the failure to the DDI. */
} else {
/* Just log the error string to the message log */
}
/*
* Indicate a failure (keeps schedule from running).
*/
/*
* Reset the chip. This should also have as a side effect, the
* disabling of all interrupts from the device.
*/
/*
* Report the failure to kCF.
*/
}
}
/*
* Return jobs not sent to hardware back to kCF.
*/
/*
* From this point on, no new work should be arriving, and the
* chip should not be doing any active DMA.
*/
/*
* Now find all the work submitted to the device and fail
* them.
*/
int i;
continue;
}
for (;;) {
if (have_mutex)
break;
}
/*
* Free up requests
*/
for (i = 0; i < wlp->dwl_reqspermcr; i++) {
if (reqp) {
} else {
/*
* cause it to get retried
* elsewhere (software)
*/
}
}
}
/*
* If waiting to drain, signal on the waiter.
*/
}
/*
* Return the work and request structures to
* the free pool.
*/
if (have_mutex)
}
}
}
#ifdef SCHEDDELAY
/*
* Reschedule worklist as needed.
*/
void
dca_schedtimeout(void *arg)
{
wlp->dwl_schedtid = 0;
}
#endif
/*
* Check for stalled jobs.
*/
void
dca_jobtimeout(void *arg)
{
int mcr;
int hung = 0;
when = ddi_get_lbolt();
/* nothing sitting in the queue */
continue;
}
/* request has been queued for less than STALETIME */
continue;
}
/* job has been sitting around for over 1 second, badness */
mcr);
/* put it back in the queue, until we reset the chip */
hung++;
}
if (hung) {
"timeout processing job.)");
}
/* reschedule ourself */
if (dca->dca_jobtid == 0) {
/* timeout has been canceled, prior to DR */
return;
}
/* check again in 1 second */
}
/*
* This returns all jobs back to kCF. It assumes that processing
* on the worklist has halted.
*/
void
{
int mcr;
int have_mutex;
continue;
}
for (;;) {
break;
}
/* update flow control */
}
(void) dca_unbindchains(reqp);
}
if (have_mutex)
}
}
int
{
int mcr;
#ifdef SCHEDDELAY
#endif
/* give it up to a second to drain from the chip */
return (EBUSY);
}
}
#ifdef SCHEDDELAY
/*
* untimeout outside the lock -- this is safe because we
* have set the drain flag, so dca_schedule() will not
* reschedule another timeout
*/
if (tid) {
}
#else
#endif
}
return (0);
}
void
{
int mcr;
}
}
/*
* Duplicate the crypto_data_t structure, but point to the original
* buffers.
*/
int
{
case CRYPTO_DATA_RAW:
break;
case CRYPTO_DATA_UIO:
break;
case CRYPTO_DATA_MBLK:
break;
default:
"dca_dupcrypto: unrecognised crypto data format");
return (CRYPTO_FAILED);
}
return (CRYPTO_SUCCESS);
}
/*
* Performs validation checks on the input and output data structures.
*/
int
{
int rv = CRYPTO_SUCCESS;
case CRYPTO_DATA_RAW:
break;
case CRYPTO_DATA_UIO:
/* we support only kernel buffer */
}
break;
case CRYPTO_DATA_MBLK:
break;
default:
}
case CRYPTO_DATA_RAW:
break;
case CRYPTO_DATA_UIO:
/* we support only kernel buffer */
}
break;
case CRYPTO_DATA_MBLK:
break;
default:
}
return (rv);
}
/*
* data: source crypto_data_t struct
* off: offset into the source before commencing copy
* count: the amount of data to copy
* dest: destination buffer
*/
int
{
int rv = CRYPTO_SUCCESS;
if (count == 0) {
/* We don't want anything so we're done. */
return (rv);
}
/*
* Sanity check that we haven't specified a length greater than the
* offset adjusted size of the buffer.
*/
return (CRYPTO_DATA_LEN_RANGE);
}
/* Add the internal crypto_data offset to the requested offset. */
case CRYPTO_DATA_RAW:
break;
case CRYPTO_DATA_UIO:
/*
* Jump to the first iovec containing data to be
* processed.
*/
/*
* The caller specified an offset that is larger than
* the total size of the buffers it provided.
*/
return (CRYPTO_DATA_LEN_RANGE);
}
/*
* Now process the iovecs.
*/
cur_len);
vec_idx++;
off = 0;
}
/*
* The end of the specified iovec's was reached but
* the length requested could not be processed
* (requested to digest more data than it provided).
*/
return (CRYPTO_DATA_LEN_RANGE);
}
break;
case CRYPTO_DATA_MBLK:
/*
* Jump to the first mblk_t containing data to be processed.
*/
/*
* The caller specified an offset that is larger than
* the total size of the buffers it provided.
*/
return (CRYPTO_DATA_LEN_RANGE);
}
/*
* Now do the processing on the mblk chain.
*/
off = 0;
}
/*
* The end of the mblk was reached but the length
* requested could not be processed, (requested to
* digest more data than it provided).
*/
return (CRYPTO_DATA_LEN_RANGE);
}
break;
default:
}
return (rv);
}
/*
* ie fails the test.
*/
int
{
switch (val) {
case DCA_SG_CONTIG:
/*
* Check for a contiguous data buffer.
*/
case CRYPTO_DATA_RAW:
/* Contiguous in nature */
break;
case CRYPTO_DATA_UIO:
break;
case CRYPTO_DATA_MBLK:
break;
default:
}
break;
case DCA_SG_WALIGN:
/*
* Check for a contiguous data buffer that is 32-bit word
* aligned and is of word multiples in size.
*/
case CRYPTO_DATA_RAW:
sizeof (uint32_t))) {
}
break;
case CRYPTO_DATA_UIO:
return (TRUE);
}
/* So there is only one iovec */
sizeof (uint32_t))) {
}
break;
case CRYPTO_DATA_MBLK:
return (TRUE);
}
/* So there is only one mblk in the chain */
}
break;
default:
}
break;
case DCA_SG_PALIGN:
/*
* Check that the data buffer is page aligned and is of
* page multiples in size.
*/
case CRYPTO_DATA_RAW:
dca->dca_pagesize)) {
}
break;
case CRYPTO_DATA_UIO:
dca->dca_pagesize)) {
}
break;
case CRYPTO_DATA_MBLK:
}
break;
default:
}
break;
default:
}
return (rv);
}
/*
* Increments the cd_offset and decrements the cd_length as the data is
* gathered from the crypto_data_t struct.
* The data is reverse-copied into the dest buffer if the flag is true.
*/
int
{
int rv = CRYPTO_SUCCESS;
case CRYPTO_DATA_RAW:
/*
* The caller specified a length greater than the
* size of the buffer.
*/
return (CRYPTO_DATA_LEN_RANGE);
}
if (reverse)
count);
else
break;
case CRYPTO_DATA_UIO:
/*
* Jump to the first iovec containing data to be processed.
*/
/*
* The caller specified an offset that is larger than
* the total size of the buffers it provided.
*/
return (CRYPTO_DATA_LEN_RANGE);
}
/*
* Now process the iovecs.
*/
if (reverse) {
/* Fill the dest buffer from the end */
} else {
}
vec_idx++;
off = 0;
}
/*
* The end of the specified iovec's was reached but
* the length requested could not be processed
* (requested to digest more data than it provided).
*/
return (CRYPTO_DATA_LEN_RANGE);
}
break;
case CRYPTO_DATA_MBLK:
/*
* Jump to the first mblk_t containing data to be processed.
*/
/*
* The caller specified an offset that is larger than
* the total size of the buffers it provided.
*/
return (CRYPTO_DATA_LEN_RANGE);
}
/*
* Now do the processing on the mblk chain.
*/
if (reverse) {
/* Fill the dest buffer from the end */
} else {
cur_len);
}
off = 0;
}
/*
* The end of the mblk was reached but the length
* requested could not be processed, (requested to
* digest more data than it provided).
*/
return (CRYPTO_DATA_LEN_RANGE);
}
break;
default:
}
return (rv);
}
/*
* Increments the cd_offset and decrements the cd_length as the data is
* gathered from the crypto_data_t struct.
*/
int
int count)
{
int rv = CRYPTO_SUCCESS;
/* Process the residual first */
if (*residlen > 0) {
if (*residlen > 0) {
/*
* Requested amount 'count' is less than what's in
* the residual, so shuffle any remaining resid to
* the front.
*/
}
}
/* Now process what's in the crypto_data_t structs */
case CRYPTO_DATA_RAW:
/*
* The caller specified a length greater than the
* size of the buffer.
*/
return (CRYPTO_DATA_LEN_RANGE);
}
break;
case CRYPTO_DATA_UIO:
/*
* Jump to the first iovec containing data to be processed.
*/
/*
* The caller specified an offset that is larger than
* the total size of the buffers it provided.
*/
return (CRYPTO_DATA_LEN_RANGE);
}
/*
* Now process the iovecs.
*/
cur_len);
vec_idx++;
off = 0;
}
/*
* The end of the specified iovec's was reached but
* the length requested could not be processed
* (requested to digest more data than it provided).
*/
return (CRYPTO_DATA_LEN_RANGE);
}
break;
case CRYPTO_DATA_MBLK:
/*
* Jump to the first mblk_t containing data to be processed.
*/
/*
* The caller specified an offset that is larger than
* the total size of the buffers it provided.
*/
return (CRYPTO_DATA_LEN_RANGE);
}
/*
* Now do the processing on the mblk chain.
*/
off = 0;
}
/*
* The end of the mblk was reached but the length
* requested could not be processed, (requested to
* digest more data than it provided).
*/
return (CRYPTO_DATA_LEN_RANGE);
}
break;
default:
"dca_resid_gather: unrecognised crypto data format");
}
return (rv);
}
/*
* Appends the data to the crypto_data_t struct increasing cd_length.
* cd_offset is left unchanged.
* Data is reverse-copied if the flag is TRUE.
*/
int
{
int rv = CRYPTO_SUCCESS;
case CRYPTO_DATA_RAW:
/* Trying to write out more than space available. */
return (CRYPTO_DATA_LEN_RANGE);
}
if (reverse)
else
break;
case CRYPTO_DATA_UIO:
/*
* Jump to the first iovec that can be written to.
*/
/*
* The caller specified an offset that is larger than
* the total size of the buffers it provided.
*/
return (CRYPTO_DATA_LEN_RANGE);
}
/*
* Now process the iovecs.
*/
if (reverse) {
} else {
}
vec_idx++;
offset = 0;
}
/*
* The end of the specified iovec's was reached but
* the length requested could not be processed
* (requested to write more data than space provided).
*/
return (CRYPTO_DATA_LEN_RANGE);
}
break;
case CRYPTO_DATA_MBLK:
/*
* Jump to the first mblk_t that can be written to.
*/
/*
* The caller specified an offset that is larger than
* the total size of the buffers it provided.
*/
return (CRYPTO_DATA_LEN_RANGE);
}
/*
* Now do the processing on the mblk chain.
*/
if (reverse) {
cur_len);
} else {
cur_len);
}
offset = 0;
}
/*
* The end of the mblk was reached but the length
* requested could not be processed, (requested to
* digest more data than it provided).
*/
return (CRYPTO_DATA_LEN_RANGE);
}
break;
default:
}
return (rv);
}
/*
* Compare two byte arrays in reverse order.
* Return 0 if they are identical, 1 otherwise.
*/
int
{
int i;
if (!n)
return (0);
for (i = 0; i < n; i++) {
return (1);
src--;
dst++;
}
return (0);
}
/*
* This calculates the size of a bignum in bits, specifically not counting
* leading zero bits. This size calculation must be done *before* any
* endian reversal takes place (i.e. the numbers are in absolute big-endian
* order.)
*/
int
{
unsigned char msbyte;
int i, j;
for (i = 0; i < bytelen - 1; i++) {
if (bignum[i] != 0) {
break;
}
}
for (j = 8; j > 1; j--) {
if (msbyte & 0x80) {
break;
}
msbyte <<= 1;
}
}
/*
* This compares to bignums (in big-endian order). It ignores leading
* null bytes. The result semantics follow bcmp, mempcmp, strcmp, etc.
*/
int
{
n1len--;
n1++;
}
n2len--;
n2++;
}
}
n1++;
n2++;
n1len--;
}
}
/*
* Return array of key attributes.
*/
{
return (NULL);
}
}
/*
* If attribute type exists valp points to it's 32-bit value.
*/
int
{
return (CRYPTO_ATTRIBUTE_TYPE_INVALID);
}
return (CRYPTO_SUCCESS);
}
/*
* If attribute type exists data contains the start address of the value,
* and numelems contains it's length.
*/
int
{
return (CRYPTO_ATTRIBUTE_TYPE_INVALID);
}
return (CRYPTO_SUCCESS);
}
/*
* Finds entry of specified name. If it is not found dca_find_attribute returns
* NULL.
*/
{
while (atnum) {
return (attrp);
atnum--;
attrp++;
}
return (NULL);
}
/*
* Return the address of the first data buffer. If the data format is
* unrecognised return NULL.
*/
{
case CRYPTO_DATA_RAW:
case CRYPTO_DATA_UIO:
case CRYPTO_DATA_MBLK:
default:
"dca_bufdaddr: unrecognised crypto data format");
return (NULL);
}
}
static caddr_t
{
case CRYPTO_DATA_RAW:
case CRYPTO_DATA_UIO:
case CRYPTO_DATA_MBLK:
default:
"dca_bufdaddr_out: unrecognised crypto data format");
return (NULL);
}
}
/*
* Control entry points.
*/
/* ARGSUSED */
static void
{
}
/*
*/
/* ARGSUSED */
static int
{
int error = CRYPTO_FAILED;
/* LINTED E_FUNC_SET_NOT_USED */
int instance;
/* extract softc and instance number from context */
/* check mechanism */
case DES_CBC_MECH_INFO_TYPE:
break;
case DES3_CBC_MECH_INFO_TYPE:
DR_ENCRYPT | DR_TRIPLE);
break;
case RSA_PKCS_MECH_INFO_TYPE:
case RSA_X_509_MECH_INFO_TYPE:
break;
default:
}
if (error == CRYPTO_SUCCESS)
return (error);
}
/* ARGSUSED */
static int
{
int error = CRYPTO_FAILED;
/* LINTED E_FUNC_SET_NOT_USED */
int instance;
return (CRYPTO_OPERATION_NOT_INITIALIZED);
/* extract softc and instance number from context */
/* check mechanism */
switch (DCA_MECH_FROM_CTX(ctx)) {
case DES_CBC_MECH_INFO_TYPE:
break;
case DES3_CBC_MECH_INFO_TYPE:
DR_ENCRYPT | DR_TRIPLE);
break;
case RSA_PKCS_MECH_INFO_TYPE:
case RSA_X_509_MECH_INFO_TYPE:
break;
default:
/* Should never reach here */
}
(error != CRYPTO_BUFFER_TOO_SMALL)) {
ciphertext->cd_length = 0;
}
return (error);
}
/* ARGSUSED */
static int
{
int error = CRYPTO_FAILED;
/* LINTED E_FUNC_SET_NOT_USED */
int instance;
return (CRYPTO_OPERATION_NOT_INITIALIZED);
/* extract softc and instance number from context */
/* check mechanism */
switch (DCA_MECH_FROM_CTX(ctx)) {
case DES_CBC_MECH_INFO_TYPE:
break;
case DES3_CBC_MECH_INFO_TYPE:
DR_ENCRYPT | DR_TRIPLE);
break;
default:
/* Should never reach here */
}
return (error);
}
/* ARGSUSED */
static int
{
int error = CRYPTO_FAILED;
/* LINTED E_FUNC_SET_NOT_USED */
int instance;
return (CRYPTO_OPERATION_NOT_INITIALIZED);
/* extract softc and instance number from context */
/* check mechanism */
switch (DCA_MECH_FROM_CTX(ctx)) {
case DES_CBC_MECH_INFO_TYPE:
break;
case DES3_CBC_MECH_INFO_TYPE:
break;
default:
/* Should never reach here */
}
return (error);
}
/* ARGSUSED */
static int
{
int error = CRYPTO_FAILED;
if (ctx_template != NULL)
return (CRYPTO_ARGUMENTS_BAD);
/* check mechanism */
case DES_CBC_MECH_INFO_TYPE:
DR_ENCRYPT | DR_ATOMIC);
break;
case DES3_CBC_MECH_INFO_TYPE:
break;
case RSA_PKCS_MECH_INFO_TYPE:
case RSA_X_509_MECH_INFO_TYPE:
break;
default:
}
ciphertext->cd_length = 0;
}
return (error);
}
/* ARGSUSED */
static int
{
int error = CRYPTO_FAILED;
/* LINTED E_FUNC_SET_NOT_USED */
int instance;
/* extract softc and instance number from context */
/* check mechanism */
case DES_CBC_MECH_INFO_TYPE:
break;
case DES3_CBC_MECH_INFO_TYPE:
DR_DECRYPT | DR_TRIPLE);
break;
case RSA_PKCS_MECH_INFO_TYPE:
case RSA_X_509_MECH_INFO_TYPE:
break;
default:
}
if (error == CRYPTO_SUCCESS)
return (error);
}
/* ARGSUSED */
static int
{
int error = CRYPTO_FAILED;
/* LINTED E_FUNC_SET_NOT_USED */
int instance;
return (CRYPTO_OPERATION_NOT_INITIALIZED);
/* extract softc and instance number from context */
/* check mechanism */
switch (DCA_MECH_FROM_CTX(ctx)) {
case DES_CBC_MECH_INFO_TYPE:
break;
case DES3_CBC_MECH_INFO_TYPE:
DR_DECRYPT | DR_TRIPLE);
break;
case RSA_PKCS_MECH_INFO_TYPE:
case RSA_X_509_MECH_INFO_TYPE:
break;
default:
/* Should never reach here */
}
(error != CRYPTO_BUFFER_TOO_SMALL)) {
if (plaintext)
}
return (error);
}
/* ARGSUSED */
static int
{
int error = CRYPTO_FAILED;
/* LINTED E_FUNC_SET_NOT_USED */
int instance;
return (CRYPTO_OPERATION_NOT_INITIALIZED);
/* extract softc and instance number from context */
/* check mechanism */
switch (DCA_MECH_FROM_CTX(ctx)) {
case DES_CBC_MECH_INFO_TYPE:
break;
case DES3_CBC_MECH_INFO_TYPE:
DR_DECRYPT | DR_TRIPLE);
break;
default:
/* Should never reach here */
}
return (error);
}
/* ARGSUSED */
static int
{
int error = CRYPTO_FAILED;
/* LINTED E_FUNC_SET_NOT_USED */
int instance;
return (CRYPTO_OPERATION_NOT_INITIALIZED);
/* extract softc and instance number from context */
/* check mechanism */
switch (DCA_MECH_FROM_CTX(ctx)) {
case DES_CBC_MECH_INFO_TYPE:
break;
case DES3_CBC_MECH_INFO_TYPE:
break;
default:
/* Should never reach here */
}
return (error);
}
/* ARGSUSED */
static int
{
int error = CRYPTO_FAILED;
if (ctx_template != NULL)
return (CRYPTO_ARGUMENTS_BAD);
/* check mechanism */
case DES_CBC_MECH_INFO_TYPE:
DR_DECRYPT | DR_ATOMIC);
break;
case DES3_CBC_MECH_INFO_TYPE:
break;
case RSA_PKCS_MECH_INFO_TYPE:
case RSA_X_509_MECH_INFO_TYPE:
break;
default:
}
}
return (error);
}
/*
* Sign entry points.
*/
/* ARGSUSED */
static int
{
int error = CRYPTO_FAILED;
/* LINTED E_FUNC_SET_NOT_USED */
int instance;
/* extract softc and instance number from context */
if (ctx_template != NULL)
return (CRYPTO_ARGUMENTS_BAD);
/* check mechanism */
case RSA_PKCS_MECH_INFO_TYPE:
case RSA_X_509_MECH_INFO_TYPE:
break;
case DSA_MECH_INFO_TYPE:
break;
default:
}
if (error == CRYPTO_SUCCESS)
return (error);
}
static int
{
int error = CRYPTO_FAILED;
/* LINTED E_FUNC_SET_NOT_USED */
int instance;
return (CRYPTO_OPERATION_NOT_INITIALIZED);
/* extract softc and instance number from context */
/* check mechanism */
switch (DCA_MECH_FROM_CTX(ctx)) {
case RSA_PKCS_MECH_INFO_TYPE:
case RSA_X_509_MECH_INFO_TYPE:
break;
case DSA_MECH_INFO_TYPE:
break;
default:
}
return (error);
}
/* ARGSUSED */
static int
{
int error = CRYPTO_MECHANISM_INVALID;
/* LINTED E_FUNC_SET_NOT_USED */
int instance;
return (CRYPTO_OPERATION_NOT_INITIALIZED);
/* extract softc and instance number from context */
return (error);
}
/* ARGSUSED */
static int
{
int error = CRYPTO_MECHANISM_INVALID;
/* LINTED E_FUNC_SET_NOT_USED */
int instance;
return (CRYPTO_OPERATION_NOT_INITIALIZED);
/* extract softc and instance number from context */
return (error);
}
static int
{
int error = CRYPTO_FAILED;
if (ctx_template != NULL)
return (CRYPTO_ARGUMENTS_BAD);
/* check mechanism */
case RSA_PKCS_MECH_INFO_TYPE:
case RSA_X_509_MECH_INFO_TYPE:
break;
case DSA_MECH_INFO_TYPE:
break;
default:
}
return (error);
}
/* ARGSUSED */
static int
{
int error = CRYPTO_FAILED;
/* LINTED E_FUNC_SET_NOT_USED */
int instance;
/* extract softc and instance number from context */
if (ctx_template != NULL)
return (CRYPTO_ARGUMENTS_BAD);
/* check mechanism */
case RSA_PKCS_MECH_INFO_TYPE:
case RSA_X_509_MECH_INFO_TYPE:
break;
default:
}
if (error == CRYPTO_SUCCESS)
return (error);
}
static int
{
int error = CRYPTO_FAILED;
/* LINTED E_FUNC_SET_NOT_USED */
int instance;
return (CRYPTO_OPERATION_NOT_INITIALIZED);
/* extract softc and instance number from context */
/* check mechanism */
switch (DCA_MECH_FROM_CTX(ctx)) {
case RSA_PKCS_MECH_INFO_TYPE:
case RSA_X_509_MECH_INFO_TYPE:
break;
default:
}
return (error);
}
static int
{
int error = CRYPTO_FAILED;
/* LINTED E_FUNC_SET_NOT_USED */
int instance;
if (ctx_template != NULL)
return (CRYPTO_ARGUMENTS_BAD);
/* check mechanism */
case RSA_PKCS_MECH_INFO_TYPE:
case RSA_X_509_MECH_INFO_TYPE:
break;
default:
}
return (error);
}
/*
* Verify entry points.
*/
/* ARGSUSED */
static int
{
int error = CRYPTO_FAILED;
/* LINTED E_FUNC_SET_NOT_USED */
int instance;
/* extract softc and instance number from context */
if (ctx_template != NULL)
return (CRYPTO_ARGUMENTS_BAD);
/* check mechanism */
case RSA_PKCS_MECH_INFO_TYPE:
case RSA_X_509_MECH_INFO_TYPE:
break;
case DSA_MECH_INFO_TYPE:
break;
default:
}
if (error == CRYPTO_SUCCESS)
return (error);
}
static int
{
int error = CRYPTO_FAILED;
/* LINTED E_FUNC_SET_NOT_USED */
int instance;
return (CRYPTO_OPERATION_NOT_INITIALIZED);
/* extract softc and instance number from context */
/* check mechanism */
switch (DCA_MECH_FROM_CTX(ctx)) {
case RSA_PKCS_MECH_INFO_TYPE:
case RSA_X_509_MECH_INFO_TYPE:
break;
case DSA_MECH_INFO_TYPE:
break;
default:
}
return (error);
}
/* ARGSUSED */
static int
{
int error = CRYPTO_MECHANISM_INVALID;
/* LINTED E_FUNC_SET_NOT_USED */
int instance;
return (CRYPTO_OPERATION_NOT_INITIALIZED);
/* extract softc and instance number from context */
return (error);
}
/* ARGSUSED */
static int
{
int error = CRYPTO_MECHANISM_INVALID;
/* LINTED E_FUNC_SET_NOT_USED */
int instance;
return (CRYPTO_OPERATION_NOT_INITIALIZED);
/* extract softc and instance number from context */
return (error);
}
static int
{
int error = CRYPTO_FAILED;
if (ctx_template != NULL)
return (CRYPTO_ARGUMENTS_BAD);
/* check mechanism */
case RSA_PKCS_MECH_INFO_TYPE:
case RSA_X_509_MECH_INFO_TYPE:
break;
case DSA_MECH_INFO_TYPE:
break;
default:
}
return (error);
}
/* ARGSUSED */
static int
{
int error = CRYPTO_MECHANISM_INVALID;
/* LINTED E_FUNC_SET_NOT_USED */
int instance;
/* extract softc and instance number from context */
if (ctx_template != NULL)
return (CRYPTO_ARGUMENTS_BAD);
/* check mechanism */
case RSA_PKCS_MECH_INFO_TYPE:
case RSA_X_509_MECH_INFO_TYPE:
break;
default:
}
if (error == CRYPTO_SUCCESS)
return (error);
}
static int
{
int error = CRYPTO_MECHANISM_INVALID;
/* LINTED E_FUNC_SET_NOT_USED */
int instance;
return (CRYPTO_OPERATION_NOT_INITIALIZED);
/* extract softc and instance number from context */
/* check mechanism */
switch (DCA_MECH_FROM_CTX(ctx)) {
case RSA_PKCS_MECH_INFO_TYPE:
case RSA_X_509_MECH_INFO_TYPE:
break;
default:
}
return (error);
}
static int
{
int error = CRYPTO_MECHANISM_INVALID;
if (ctx_template != NULL)
return (CRYPTO_ARGUMENTS_BAD);
/* check mechanism */
case RSA_PKCS_MECH_INFO_TYPE:
case RSA_X_509_MECH_INFO_TYPE:
break;
default:
}
"dca_verify_recover_atomic: done, err = 0x%x", error);
return (error);
}
/*
* Random number entry points.
*/
/* ARGSUSED */
static int
{
int error = CRYPTO_FAILED;
/* LINTED E_FUNC_SET_NOT_USED */
int instance;
return (error);
}
/*
* Context management entry points.
*/
int
{
int error = CRYPTO_SUCCESS;
/* LINTED E_FUNC_SET_NOT_USED */
int instance;
/* extract softc and instance number from context */
return (error);
return (error);
}
static int
{
int error = CRYPTO_SUCCESS;
/* check mechanism */
switch (DCA_MECH_FROM_CTX(ctx)) {
case DES_CBC_MECH_INFO_TYPE:
case DES3_CBC_MECH_INFO_TYPE:
break;
case RSA_PKCS_MECH_INFO_TYPE:
case RSA_X_509_MECH_INFO_TYPE:
break;
case DSA_MECH_INFO_TYPE:
break;
default:
/* Should never reach here */
}
return (error);
}
/* Free any unfreed private context. It is called in detach. */
static void
{
(void) dca_free_context_low(&ctx);
}
}
static int
{
}
static int
{
int rv;
/* The asymmetric cipher slot supports random */
return (rv);
}
/* ARGSUSED */
static int
{
int len;
/* Label */
/* Manufacturer ID */
/* Model */
/* Serial Number. Blank for Deimos */
/* Time. No need to be supplied for token without a clock */
return (CRYPTO_SUCCESS);
}
static void
{
/* Read FMA capabilities from dca.conf file (if present) */
/* Only register with IO Fault Services if we have some capability */
if (dca->fm_capabilities) {
/* Register capabilities with IO Fault Services */
/*
* Initialize pci ereport capabilities if ereport capable
*/
/*
* Initialize callback mutex and register error callback if
* error callback capable.
*/
(void *)dca);
}
} else {
/*
* These fields have to be cleared of FMA if there are no
* FMA capabilities at runtime.
*/
}
}
static void
{
/* Only unregister FMA capabilities if we registered some */
if (dca->fm_capabilities) {
/*
* Release any resources allocated by pci_ereport_setup()
*/
}
/*
* Free callback mutex and un-register error callback if
* error callback capable.
*/
}
/* Unregister from IO Fault Services */
}
}
/*
* The IO fault service error handling callback function
*/
/*ARGSUSED*/
static int
{
"fault PCI in FMA callback.");
}
return (err->fme_status);
}
static int
{
int version = 0;
CRYPTO_DEVICE_ERROR, "");
return (DDI_FAILURE);
}
return (DDI_SUCCESS);
}
int
{
int version = 0;
CRYPTO_DEVICE_ERROR, "");
return (DDI_FAILURE);
}
return (DDI_SUCCESS);
}
static uint64_t
{
if (ena == 0)
else
return (ena);
}
static char *
{
return (dca_fma_eclass_sca500[index]);
else
return (dca_fma_eclass_sca1000[index]);
}