summaryrefslogtreecommitdiffstats
path: root/sys/dev/hifn/hifn7751.c
diff options
context:
space:
mode:
authorsam <sam@FreeBSD.org>2007-03-21 03:42:51 +0000
committersam <sam@FreeBSD.org>2007-03-21 03:42:51 +0000
commitf96ba7ffdacde02e9c3e989c8f6e3e7539b74b46 (patch)
tree05fc03ec94859546cbef49b9fe30d492c4f7bf19 /sys/dev/hifn/hifn7751.c
parent3f9dd9edcb00155dff6a9b7686ce432606296d79 (diff)
downloadFreeBSD-src-f96ba7ffdacde02e9c3e989c8f6e3e7539b74b46.zip
FreeBSD-src-f96ba7ffdacde02e9c3e989c8f6e3e7539b74b46.tar.gz
Overhaul driver/subsystem api's:
o make all crypto drivers have a device_t; pseudo drivers like the s/w crypto driver synthesize one o change the api between the crypto subsystem and drivers to use kobj; cryptodev_if.m defines this api o use the fact that all crypto drivers now have a device_t to add support for specifying which of several potential devices to use when doing crypto operations o add new ioctls that allow user apps to select a specific crypto device to use (previous ioctls maintained for compatibility) o overhaul crypto subsystem code to eliminate lots of cruft and hide implementation details from drivers o bring in numerous fixes from Michale Richardson/hifn; mostly for 795x parts o add an optional mechanism for mmap'ing the hifn 795x public key h/w to user space for use by openssl (not enabled by default) o update crypto test tools to use new ioctl's and add cmd line options to specify a device to use for tests These changes will also enable much future work on improving the core crypto subsystem; including proper load balancing and interposing code between the core and drivers to dispatch small operations to the s/w driver as appropriate. These changes were instigated by the work of Michael Richardson. Reviewed by: pjd Approved by: re
Diffstat (limited to 'sys/dev/hifn/hifn7751.c')
-rw-r--r--sys/dev/hifn/hifn7751.c262
1 files changed, 181 insertions, 81 deletions
diff --git a/sys/dev/hifn/hifn7751.c b/sys/dev/hifn/hifn7751.c
index 6f2666f..d3a66e6 100644
--- a/sys/dev/hifn/hifn7751.c
+++ b/sys/dev/hifn/hifn7751.c
@@ -70,6 +70,9 @@ __FBSDID("$FreeBSD$");
#include <opencrypto/cryptodev.h>
#include <sys/random.h>
+#include <sys/kobj.h>
+
+#include "cryptodev_if.h"
#include <dev/pci/pcivar.h>
#include <dev/pci/pcireg.h>
@@ -80,6 +83,13 @@ __FBSDID("$FreeBSD$");
#include <dev/hifn/hifn7751reg.h>
#include <dev/hifn/hifn7751var.h>
+#ifdef HIFN_VULCANDEV
+#include <sys/conf.h>
+#include <sys/uio.h>
+
+static struct cdevsw vulcanpk_cdevsw; /* forward declaration */
+#endif
+
/*
* Prototypes and count for the pci_device structure
*/
@@ -90,6 +100,10 @@ static int hifn_suspend(device_t);
static int hifn_resume(device_t);
static void hifn_shutdown(device_t);
+static int hifn_newsession(device_t, u_int32_t *, struct cryptoini *);
+static int hifn_freesession(device_t, u_int64_t);
+static int hifn_process(device_t, struct cryptop *, int);
+
static device_method_t hifn_methods[] = {
/* Device interface */
DEVMETHOD(device_probe, hifn_probe),
@@ -103,6 +117,11 @@ static device_method_t hifn_methods[] = {
DEVMETHOD(bus_print_child, bus_generic_print_child),
DEVMETHOD(bus_driver_added, bus_generic_driver_added),
+ /* crypto device methods */
+ DEVMETHOD(cryptodev_newsession, hifn_newsession),
+ DEVMETHOD(cryptodev_freesession,hifn_freesession),
+ DEVMETHOD(cryptodev_process, hifn_process),
+
{ 0, 0 }
};
static driver_t hifn_driver = {
@@ -132,9 +151,6 @@ static void hifn_sessions(struct hifn_softc *);
static void hifn_intr(void *);
static u_int hifn_write_command(struct hifn_command *, u_int8_t *);
static u_int32_t hifn_next_signature(u_int32_t a, u_int cnt);
-static int hifn_newsession(void *, u_int32_t *, struct cryptoini *);
-static int hifn_freesession(void *, u_int64_t);
-static int hifn_process(void *, struct cryptop *, int);
static void hifn_callback(struct hifn_softc *, struct hifn_command *, u_int8_t *);
static int hifn_crypto(struct hifn_softc *, struct hifn_command *, struct cryptop *, int);
static int hifn_readramaddr(struct hifn_softc *, int, u_int8_t *);
@@ -279,6 +295,12 @@ checkmaxmin(device_t dev, const char *what, u_int v, u_int min, u_int max)
* always will allow the card to work. If a card is using the PCI
* bus clock and in a 33MHz slot then it will be operating at half
* speed until the correct information is provided.
+ *
+ * We use a default setting of "ext66" because according to Mike Ham
+ * of HiFn, almost every board in existence has an external crystal
+ * populated at 66Mhz. Using PCI can be a problem on modern motherboards,
+ * because PCI33 can have clocks from 0 to 33Mhz, and some have
+ * non-PCI-compliant spread-spectrum clocks, which can confuse the pll.
*/
static void
hifn_getpllconfig(device_t dev, u_int *pll)
@@ -290,7 +312,7 @@ hifn_getpllconfig(device_t dev, u_int *pll)
if (resource_string_value("hifn", device_get_unit(dev),
"pllconfig", &pllspec))
- pllspec = "pci66";
+ pllspec = "ext66";
fl = 33, fh = 66;
pllconfig = 0;
if (strncmp(pllspec, "ext", 3) == 0) {
@@ -559,7 +581,7 @@ hifn_attach(device_t dev)
2 + 2*((sc->sc_pllconfig & HIFN_PLL_ND) >> 11));
printf("\n");
- sc->sc_cid = crypto_get_driverid(0);
+ sc->sc_cid = crypto_get_driverid(dev, CRYPTOCAP_F_HARDWARE);
if (sc->sc_cid < 0) {
device_printf(dev, "could not get crypto driver id\n");
goto fail_intr;
@@ -571,26 +593,17 @@ hifn_attach(device_t dev)
switch (ena) {
case HIFN_PUSTAT_ENA_2:
- crypto_register(sc->sc_cid, CRYPTO_3DES_CBC, 0, 0,
- hifn_newsession, hifn_freesession, hifn_process, sc);
- crypto_register(sc->sc_cid, CRYPTO_ARC4, 0, 0,
- hifn_newsession, hifn_freesession, hifn_process, sc);
+ crypto_register(sc->sc_cid, CRYPTO_3DES_CBC, 0, 0);
+ crypto_register(sc->sc_cid, CRYPTO_ARC4, 0, 0);
if (sc->sc_flags & HIFN_HAS_AES)
- crypto_register(sc->sc_cid, CRYPTO_AES_CBC, 0, 0,
- hifn_newsession, hifn_freesession,
- hifn_process, sc);
+ crypto_register(sc->sc_cid, CRYPTO_AES_CBC, 0, 0);
/*FALLTHROUGH*/
case HIFN_PUSTAT_ENA_1:
- crypto_register(sc->sc_cid, CRYPTO_MD5, 0, 0,
- hifn_newsession, hifn_freesession, hifn_process, sc);
- crypto_register(sc->sc_cid, CRYPTO_SHA1, 0, 0,
- hifn_newsession, hifn_freesession, hifn_process, sc);
- crypto_register(sc->sc_cid, CRYPTO_MD5_HMAC, 0, 0,
- hifn_newsession, hifn_freesession, hifn_process, sc);
- crypto_register(sc->sc_cid, CRYPTO_SHA1_HMAC, 0, 0,
- hifn_newsession, hifn_freesession, hifn_process, sc);
- crypto_register(sc->sc_cid, CRYPTO_DES_CBC, 0, 0,
- hifn_newsession, hifn_freesession, hifn_process, sc);
+ crypto_register(sc->sc_cid, CRYPTO_MD5, 0, 0);
+ crypto_register(sc->sc_cid, CRYPTO_SHA1, 0, 0);
+ crypto_register(sc->sc_cid, CRYPTO_MD5_HMAC, 0, 0);
+ crypto_register(sc->sc_cid, CRYPTO_SHA1_HMAC, 0, 0);
+ crypto_register(sc->sc_cid, CRYPTO_DES_CBC, 0, 0);
break;
}
@@ -790,6 +803,12 @@ hifn_init_pubrng(struct hifn_softc *sc)
WRITE_REG_1(sc, HIFN_1_PUB_IEN, HIFN_PUBIEN_DONE);
sc->sc_dmaier |= HIFN_DMAIER_PUBDONE;
WRITE_REG_1(sc, HIFN_1_DMA_IER, sc->sc_dmaier);
+#ifdef HIFN_VULCANDEV
+ sc->sc_pkdev = make_dev(&vulcanpk_cdevsw, 0,
+ UID_ROOT, GID_WHEEL, 0666,
+ "vulcanpk");
+ sc->sc_pkdev->si_drv1 = sc;
+#endif
}
return (0);
@@ -804,6 +823,7 @@ hifn_rng(void *vsc)
int i;
if (sc->sc_flags & HIFN_IS_7811) {
+ /* ONLY VALID ON 7811!!!! */
for (i = 0; i < 5; i++) {
sts = READ_REG_1(sc, HIFN_1_7811_RNGSTS);
if (sts & HIFN_7811_RNGSTS_UFL) {
@@ -846,10 +866,15 @@ static void
hifn_puc_wait(struct hifn_softc *sc)
{
int i;
+ int reg = HIFN_0_PUCTRL;
+
+ if (sc->sc_flags & HIFN_IS_7956) {
+ reg = HIFN_0_PUCTRL2;
+ }
for (i = 5000; i > 0; i--) {
DELAY(1);
- if (!(READ_REG_0(sc, HIFN_0_PUCTRL) & HIFN_PUCTRL_RESET))
+ if (!(READ_REG_0(sc, reg) & HIFN_PUCTRL_RESET))
break;
}
if (!i)
@@ -863,7 +888,13 @@ static void
hifn_reset_puc(struct hifn_softc *sc)
{
/* Reset processing unit */
- WRITE_REG_0(sc, HIFN_0_PUCTRL, HIFN_PUCTRL_DMAENA);
+ int reg = HIFN_0_PUCTRL;
+
+ if (sc->sc_flags & HIFN_IS_7956) {
+ reg = HIFN_0_PUCTRL2;
+ }
+ WRITE_REG_0(sc, reg, HIFN_PUCTRL_DMAENA);
+
hifn_puc_wait(sc);
}
@@ -932,7 +963,16 @@ hifn_reset_board(struct hifn_softc *sc, int full)
}
if (reg == 1000)
printf(": cram init timeout\n");
- }
+ } else {
+ /* set up DMA configuration register #2 */
+ /* turn off all PK and BAR0 swaps */
+ WRITE_REG_1(sc, HIFN_1_DMA_CNFG2,
+ (3 << HIFN_DMACNFG2_INIT_WRITE_BURST_SHIFT)|
+ (3 << HIFN_DMACNFG2_INIT_READ_BURST_SHIFT)|
+ (2 << HIFN_DMACNFG2_TGT_WRITE_BURST_SHIFT)|
+ (2 << HIFN_DMACNFG2_TGT_READ_BURST_SHIFT));
+ }
+
}
static u_int32_t
@@ -1170,13 +1210,15 @@ hifn_init_pci_registers(struct hifn_softc *sc)
/* turn off the clocks and insure bypass is set */
pll = READ_REG_1(sc, HIFN_1_PLL);
pll = (pll &~ (HIFN_PLL_PK_CLK_SEL | HIFN_PLL_PE_CLK_SEL))
- | HIFN_PLL_BP;
+ | HIFN_PLL_BP | HIFN_PLL_MBSET;
WRITE_REG_1(sc, HIFN_1_PLL, pll);
DELAY(10*1000); /* 10ms */
+
/* change configuration */
pll = (pll &~ HIFN_PLL_CONFIG) | sc->sc_pllconfig;
WRITE_REG_1(sc, HIFN_1_PLL, pll);
DELAY(10*1000); /* 10ms */
+
/* disable bypass */
pll &= ~HIFN_PLL_BP;
WRITE_REG_1(sc, HIFN_1_PLL, pll);
@@ -1657,6 +1699,21 @@ hifn_dmamap_aligned(struct hifn_operand *op)
return (1);
}
+static __inline int
+hifn_dmamap_dstwrap(struct hifn_softc *sc, int idx)
+{
+ struct hifn_dma *dma = sc->sc_dma;
+
+ if (++idx == HIFN_D_DST_RSIZE) {
+ dma->dstr[idx].l = htole32(HIFN_D_VALID | HIFN_D_JUMP |
+ HIFN_D_MASKDONEIRQ);
+ HIFN_DSTR_SYNC(sc, idx,
+ BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE);
+ idx = 0;
+ }
+ return (idx);
+}
+
static int
hifn_dmamap_load_dst(struct hifn_softc *sc, struct hifn_command *cmd)
{
@@ -1674,13 +1731,7 @@ hifn_dmamap_load_dst(struct hifn_softc *sc, struct hifn_command *cmd)
BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE);
used++;
- if (++idx == HIFN_D_DST_RSIZE) {
- dma->dstr[idx].l = htole32(HIFN_D_VALID |
- HIFN_D_JUMP | HIFN_D_MASKDONEIRQ);
- HIFN_DSTR_SYNC(sc, idx,
- BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE);
- idx = 0;
- }
+ idx = hifn_dmamap_dstwrap(sc, idx);
}
if (cmd->sloplen == 0) {
@@ -1702,13 +1753,7 @@ hifn_dmamap_load_dst(struct hifn_softc *sc, struct hifn_command *cmd)
BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE);
used++;
- if (++idx == HIFN_D_DST_RSIZE) {
- dma->dstr[idx].l = htole32(HIFN_D_VALID |
- HIFN_D_JUMP | HIFN_D_MASKDONEIRQ);
- HIFN_DSTR_SYNC(sc, idx,
- BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE);
- idx = 0;
- }
+ idx = hifn_dmamap_dstwrap(sc, idx);
}
}
dma->dstr[idx].p = htole32(p);
@@ -1716,19 +1761,28 @@ hifn_dmamap_load_dst(struct hifn_softc *sc, struct hifn_command *cmd)
HIFN_DSTR_SYNC(sc, idx, BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE);
used++;
- if (++idx == HIFN_D_DST_RSIZE) {
- dma->dstr[idx].l = htole32(HIFN_D_VALID | HIFN_D_JUMP |
- HIFN_D_MASKDONEIRQ);
- HIFN_DSTR_SYNC(sc, idx,
- BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE);
- idx = 0;
- }
+ idx = hifn_dmamap_dstwrap(sc, idx);
dma->dsti = idx;
dma->dstu += used;
return (idx);
}
+static __inline int
+hifn_dmamap_srcwrap(struct hifn_softc *sc, int idx)
+{
+ struct hifn_dma *dma = sc->sc_dma;
+
+ if (++idx == HIFN_D_SRC_RSIZE) {
+ dma->srcr[idx].l = htole32(HIFN_D_VALID |
+ HIFN_D_JUMP | HIFN_D_MASKDONEIRQ);
+ HIFN_SRCR_SYNC(sc, HIFN_D_SRC_RSIZE,
+ BUS_DMASYNC_PREWRITE | BUS_DMASYNC_PREREAD);
+ idx = 0;
+ }
+ return (idx);
+}
+
static int
hifn_dmamap_load_src(struct hifn_softc *sc, struct hifn_command *cmd)
{
@@ -1748,13 +1802,7 @@ hifn_dmamap_load_src(struct hifn_softc *sc, struct hifn_command *cmd)
HIFN_SRCR_SYNC(sc, idx,
BUS_DMASYNC_PREWRITE | BUS_DMASYNC_PREREAD);
- if (++idx == HIFN_D_SRC_RSIZE) {
- dma->srcr[idx].l = htole32(HIFN_D_VALID |
- HIFN_D_JUMP | HIFN_D_MASKDONEIRQ);
- HIFN_SRCR_SYNC(sc, HIFN_D_SRC_RSIZE,
- BUS_DMASYNC_PREWRITE | BUS_DMASYNC_PREREAD);
- idx = 0;
- }
+ idx = hifn_dmamap_srcwrap(sc, idx);
}
dma->srci = idx;
dma->srcu += src->nsegs;
@@ -1782,7 +1830,7 @@ hifn_crypto(
int hint)
{
struct hifn_dma *dma = sc->sc_dma;
- u_int32_t cmdlen;
+ u_int32_t cmdlen, csr;
int cmdi, resi, err = 0;
/*
@@ -1995,10 +2043,6 @@ hifn_crypto(
HIFN_CMDR_SYNC(sc, cmdi,
BUS_DMASYNC_PREWRITE | BUS_DMASYNC_PREREAD);
dma->cmdu++;
- if (sc->sc_c_busy == 0) {
- WRITE_REG_1(sc, HIFN_1_DMA_CSR, HIFN_DMACSR_C_CTRL_ENA);
- sc->sc_c_busy = 1;
- }
/*
* We don't worry about missing an interrupt (which a "command wait"
@@ -2014,10 +2058,6 @@ hifn_crypto(
hifnstats.hst_ibytes += cmd->src_mapsize;
hifn_dmamap_load_src(sc, cmd);
- if (sc->sc_s_busy == 0) {
- WRITE_REG_1(sc, HIFN_1_DMA_CSR, HIFN_DMACSR_S_CTRL_ENA);
- sc->sc_s_busy = 1;
- }
/*
* Unlike other descriptors, we don't mask done interrupt from
@@ -2054,20 +2094,31 @@ hifn_crypto(
HIFN_RESR_SYNC(sc, resi,
BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE);
dma->resu++;
- if (sc->sc_r_busy == 0) {
- WRITE_REG_1(sc, HIFN_1_DMA_CSR, HIFN_DMACSR_R_CTRL_ENA);
- sc->sc_r_busy = 1;
- }
if (cmd->sloplen)
cmd->slopidx = resi;
hifn_dmamap_load_dst(sc, cmd);
+ csr = 0;
+ if (sc->sc_c_busy == 0) {
+ csr |= HIFN_DMACSR_C_CTRL_ENA;
+ sc->sc_c_busy = 1;
+ }
+ if (sc->sc_s_busy == 0) {
+ csr |= HIFN_DMACSR_S_CTRL_ENA;
+ sc->sc_s_busy = 1;
+ }
+ if (sc->sc_r_busy == 0) {
+ csr |= HIFN_DMACSR_R_CTRL_ENA;
+ sc->sc_r_busy = 1;
+ }
if (sc->sc_d_busy == 0) {
- WRITE_REG_1(sc, HIFN_1_DMA_CSR, HIFN_DMACSR_D_CTRL_ENA);
+ csr |= HIFN_DMACSR_D_CTRL_ENA;
sc->sc_d_busy = 1;
}
+ if (csr)
+ WRITE_REG_1(sc, HIFN_1_DMA_CSR, csr);
#ifdef HIFN_DEBUG
if (hifn_debug) {
@@ -2292,10 +2343,10 @@ hifn_intr(void *arg)
* id on successful allocation.
*/
static int
-hifn_newsession(void *arg, u_int32_t *sidp, struct cryptoini *cri)
+hifn_newsession(device_t dev, u_int32_t *sidp, struct cryptoini *cri)
{
+ struct hifn_softc *sc = device_get_softc(dev);
struct cryptoini *c;
- struct hifn_softc *sc = arg;
int mac = 0, cry = 0, sesn;
struct hifn_session *ses = NULL;
@@ -2303,11 +2354,14 @@ hifn_newsession(void *arg, u_int32_t *sidp, struct cryptoini *cri)
if (sidp == NULL || cri == NULL || sc == NULL)
return (EINVAL);
+ HIFN_LOCK(sc);
if (sc->sc_sessions == NULL) {
ses = sc->sc_sessions = (struct hifn_session *)malloc(
sizeof(*ses), M_DEVBUF, M_NOWAIT);
- if (ses == NULL)
+ if (ses == NULL) {
+ HIFN_UNLOCK(sc);
return (ENOMEM);
+ }
sesn = 0;
sc->sc_nsessions = 1;
} else {
@@ -2322,8 +2376,10 @@ hifn_newsession(void *arg, u_int32_t *sidp, struct cryptoini *cri)
sesn = sc->sc_nsessions;
ses = (struct hifn_session *)malloc((sesn + 1) *
sizeof(*ses), M_DEVBUF, M_NOWAIT);
- if (ses == NULL)
+ if (ses == NULL) {
+ HIFN_UNLOCK(sc);
return (ENOMEM);
+ }
bcopy(sc->sc_sessions, ses, sesn * sizeof(*ses));
bzero(sc->sc_sessions, sesn * sizeof(*ses));
free(sc->sc_sessions, M_DEVBUF);
@@ -2332,6 +2388,8 @@ hifn_newsession(void *arg, u_int32_t *sidp, struct cryptoini *cri)
sc->sc_nsessions++;
}
}
+ HIFN_UNLOCK(sc);
+
bzero(ses, sizeof(*ses));
ses->hs_used = 1;
@@ -2389,28 +2447,32 @@ hifn_newsession(void *arg, u_int32_t *sidp, struct cryptoini *cri)
* XXX to blow away any keys already stored there.
*/
static int
-hifn_freesession(void *arg, u_int64_t tid)
+hifn_freesession(device_t dev, u_int64_t tid)
{
- struct hifn_softc *sc = arg;
- int session;
+ struct hifn_softc *sc = device_get_softc(dev);
+ int session, error;
u_int32_t sid = CRYPTO_SESID2LID(tid);
KASSERT(sc != NULL, ("hifn_freesession: null softc"));
if (sc == NULL)
return (EINVAL);
+ HIFN_LOCK(sc);
session = HIFN_SESSION(sid);
- if (session >= sc->sc_nsessions)
- return (EINVAL);
+ if (session < sc->sc_nsessions) {
+ bzero(&sc->sc_sessions[session], sizeof(struct hifn_session));
+ error = 0;
+ } else
+ error = EINVAL;
+ HIFN_UNLOCK(sc);
- bzero(&sc->sc_sessions[session], sizeof(sc->sc_sessions[session]));
- return (0);
+ return (error);
}
static int
-hifn_process(void *arg, struct cryptop *crp, int hint)
+hifn_process(device_t dev, struct cryptop *crp, int hint)
{
- struct hifn_softc *sc = arg;
+ struct hifn_softc *sc = device_get_softc(dev);
struct hifn_command *cmd = NULL;
int session, err, ivlen;
struct cryptodesc *crd1, *crd2, *maccrd, *enccrd;
@@ -2858,3 +2920,41 @@ hifn_write_reg_1(struct hifn_softc *sc, bus_size_t reg, u_int32_t val)
}
bus_space_write_4(sc->sc_st1, sc->sc_sh1, reg, val);
}
+
+#ifdef HIFN_VULCANDEV
+/*
+ * this code provides support for mapping the PK engine's register
+ * into a userspace program.
+ *
+ */
+static int
+vulcanpk_mmap(struct cdev *dev, vm_offset_t offset,
+ vm_paddr_t *paddr, int nprot)
+{
+ struct hifn_softc *sc;
+ vm_paddr_t pd;
+ void *b;
+
+ sc = dev->si_drv1;
+
+ pd = rman_get_start(sc->sc_bar1res);
+ b = rman_get_virtual(sc->sc_bar1res);
+
+#if 0
+ printf("vpk mmap: %p(%08x) offset=%d\n", b, pd, offset);
+ hexdump(b, HIFN_1_PUB_MEMEND, "vpk", 0);
+#endif
+
+ if (offset == 0) {
+ *paddr = pd;
+ return (0);
+ }
+ return (-1);
+}
+
+static struct cdevsw vulcanpk_cdevsw = {
+ .d_version = D_VERSION,
+ .d_mmap = vulcanpk_mmap,
+ .d_name = "vulcanpk",
+};
+#endif /* HIFN_VULCANDEV */
OpenPOWER on IntegriCloud