Annotation of sys/dev/pci/safe.c, Revision 1.1
1.1 ! nbrk 1: /* $OpenBSD: safe.c,v 1.21 2007/02/28 22:16:55 deraadt Exp $ */
! 2:
! 3: /*-
! 4: * Copyright (c) 2003 Sam Leffler, Errno Consulting
! 5: * Copyright (c) 2003 Global Technology Associates, Inc.
! 6: * All rights reserved.
! 7: *
! 8: * Redistribution and use in source and binary forms, with or without
! 9: * modification, are permitted provided that the following conditions
! 10: * are met:
! 11: * 1. Redistributions of source code must retain the above copyright
! 12: * notice, this list of conditions and the following disclaimer.
! 13: * 2. Redistributions in binary form must reproduce the above copyright
! 14: * notice, this list of conditions and the following disclaimer in the
! 15: * documentation and/or other materials provided with the distribution.
! 16: *
! 17: * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
! 18: * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
! 19: * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
! 20: * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
! 21: * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
! 22: * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
! 23: * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
! 24: * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
! 25: * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
! 26: * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
! 27: * SUCH DAMAGE.
! 28: *
! 29: * $FreeBSD: /repoman/r/ncvs/src/sys/dev/safe/safe.c,v 1.1 2003/07/21 21:46:07 sam Exp $
! 30: */
! 31:
! 32: #include <sys/cdefs.h>
! 33:
! 34: /*
! 35: * SafeNet SafeXcel-1141 hardware crypto accelerator
! 36: */
! 37: #include <sys/param.h>
! 38: #include <sys/systm.h>
! 39: #include <sys/proc.h>
! 40: #include <sys/errno.h>
! 41: #include <sys/malloc.h>
! 42: #include <sys/kernel.h>
! 43: #include <sys/mbuf.h>
! 44: #include <sys/device.h>
! 45: #include <sys/timeout.h>
! 46:
! 47: #include <machine/bus.h>
! 48:
! 49: #include <crypto/md5.h>
! 50: #include <crypto/sha1.h>
! 51: #include <crypto/cryptodev.h>
! 52: #include <crypto/cryptosoft.h>
! 53: #include <dev/rndvar.h>
! 54:
! 55: #include <dev/pci/pcivar.h>
! 56: #include <dev/pci/pcireg.h>
! 57: #include <dev/pci/pcidevs.h>
! 58:
! 59: #include <dev/pci/safereg.h>
! 60: #include <dev/pci/safevar.h>
! 61:
! 62: #ifndef bswap32
! 63: #define bswap32 NTOHL
! 64: #endif
! 65:
! 66: #define KASSERT_X(x,y)
! 67:
! 68: /*
! 69: * Prototypes and count for the pci_device structure
! 70: */
! 71: int safe_probe(struct device *, void *, void *);
! 72: void safe_attach(struct device *, struct device *, void *);
! 73:
! 74: struct cfattach safe_ca = {
! 75: sizeof(struct safe_softc), safe_probe, safe_attach
! 76: };
! 77:
! 78: struct cfdriver safe_cd = {
! 79: 0, "safe", DV_DULL
! 80: };
! 81:
! 82: int safe_intr(void *);
! 83: int safe_newsession(u_int32_t *, struct cryptoini *);
! 84: int safe_freesession(u_int64_t);
! 85: int safe_process(struct cryptop *);
! 86: int safe_kprocess(struct cryptkop *);
! 87: int safe_kstart(struct safe_softc *);
! 88: void safe_kload_reg(struct safe_softc *, u_int32_t, u_int32_t,
! 89: struct crparam *);
! 90: struct safe_softc *safe_kfind(struct cryptkop *);
! 91: void safe_kpoll(void *);
! 92: void safe_kfeed(struct safe_softc *);
! 93: int safe_ksigbits(struct crparam *cr);
! 94: void safe_callback(struct safe_softc *, struct safe_ringentry *);
! 95: void safe_feed(struct safe_softc *, struct safe_ringentry *);
! 96: void safe_mcopy(struct mbuf *, struct mbuf *, u_int);
! 97: void safe_rng_init(struct safe_softc *);
! 98: void safe_rng(void *);
! 99: int safe_dma_malloc(struct safe_softc *, bus_size_t,
! 100: struct safe_dma_alloc *, int);
! 101: #define safe_dma_sync(_sc, _dma, _flags) \
! 102: bus_dmamap_sync((_sc)->sc_dmat, (_dma)->dma_map, 0, \
! 103: (_dma)->dma_map->dm_mapsize, (_flags))
! 104: void safe_dma_free(struct safe_softc *, struct safe_dma_alloc *);
! 105: int safe_dmamap_aligned(const struct safe_operand *);
! 106: int safe_dmamap_uniform(const struct safe_operand *);
! 107:
! 108: void safe_reset_board(struct safe_softc *);
! 109: void safe_init_board(struct safe_softc *);
! 110: void safe_init_pciregs(struct safe_softc *);
! 111: void safe_cleanchip(struct safe_softc *);
! 112: __inline u_int32_t safe_rng_read(struct safe_softc *);
! 113:
! 114: int safe_free_entry(struct safe_softc *, struct safe_ringentry *);
! 115:
! 116: #ifdef SAFE_DEBUG
! 117: int safe_debug;
! 118: #define DPRINTF(_x) if (safe_debug) printf _x
! 119:
! 120: void safe_dump_dmastatus(struct safe_softc *, const char *);
! 121: void safe_dump_intrstate(struct safe_softc *, const char *);
! 122: void safe_dump_ringstate(struct safe_softc *, const char *);
! 123: void safe_dump_request(struct safe_softc *, const char *,
! 124: struct safe_ringentry *);
! 125: void safe_dump_ring(struct safe_softc *sc, const char *tag);
! 126: #else
! 127: #define DPRINTF(_x)
! 128: #endif
! 129:
! 130: #define READ_REG(sc,r) \
! 131: bus_space_read_4((sc)->sc_st, (sc)->sc_sh, (r))
! 132:
! 133: #define WRITE_REG(sc,reg,val) \
! 134: bus_space_write_4((sc)->sc_st, (sc)->sc_sh, reg, val)
! 135:
! 136: struct safe_stats safestats;
! 137:
! 138: int safe_rnginterval = 1; /* poll once a second */
! 139: int safe_rngbufsize = 16; /* 64 bytes each poll */
! 140: int safe_rngmaxalarm = 8; /* max alarms before reset */
! 141:
! 142: int
! 143: safe_probe(struct device *parent, void *match, void *aux)
! 144: {
! 145: struct pci_attach_args *pa = aux;
! 146:
! 147: if (PCI_VENDOR(pa->pa_id) == PCI_VENDOR_SAFENET &&
! 148: PCI_PRODUCT(pa->pa_id) == PCI_PRODUCT_SAFENET_SAFEXCEL)
! 149: return (1);
! 150: return (0);
! 151: }
! 152:
! 153: void
! 154: safe_attach(struct device *parent, struct device *self, void *aux)
! 155: {
! 156: struct safe_softc *sc = (struct safe_softc *)self;
! 157: struct pci_attach_args *pa = aux;
! 158: pci_intr_handle_t ih;
! 159: const char *intrstr = NULL;
! 160: bus_size_t iosize;
! 161: bus_addr_t raddr;
! 162: u_int32_t devinfo;
! 163: int algs[CRYPTO_ALGORITHM_MAX + 1], i;
! 164:
! 165: /* XXX handle power management */
! 166:
! 167: SIMPLEQ_INIT(&sc->sc_pkq);
! 168: sc->sc_dmat = pa->pa_dmat;
! 169:
! 170: /*
! 171: * Setup memory-mapping of PCI registers.
! 172: */
! 173: if (pci_mapreg_map(pa, SAFE_BAR, PCI_MAPREG_TYPE_MEM, 0,
! 174: &sc->sc_st, &sc->sc_sh, NULL, &iosize, 0)) {
! 175: printf(": can't map register space\n");
! 176: goto bad;
! 177: }
! 178:
! 179: if (pci_intr_map(pa, &ih)) {
! 180: printf(": couldn't map interrupt\n");
! 181: goto bad1;
! 182: }
! 183: intrstr = pci_intr_string(pa->pa_pc, ih);
! 184: sc->sc_ih = pci_intr_establish(pa->pa_pc, ih, IPL_NET, safe_intr, sc,
! 185: self->dv_xname);
! 186: if (sc->sc_ih == NULL) {
! 187: printf(": couldn't establish interrupt");
! 188: if (intrstr != NULL)
! 189: printf(" at %s", intrstr);
! 190: printf("\n");
! 191: goto bad2;
! 192: }
! 193:
! 194: sc->sc_cid = crypto_get_driverid(0);
! 195: if (sc->sc_cid < 0) {
! 196: printf(": could not get crypto driver id\n");
! 197: goto bad3;
! 198: }
! 199:
! 200: sc->sc_chiprev = READ_REG(sc, SAFE_DEVINFO) &
! 201: (SAFE_DEVINFO_REV_MAJ | SAFE_DEVINFO_REV_MIN);
! 202:
! 203: /*
! 204: * Allocate packet engine descriptors.
! 205: */
! 206: if (safe_dma_malloc(sc,
! 207: SAFE_MAX_NQUEUE * sizeof (struct safe_ringentry),
! 208: &sc->sc_ringalloc, 0)) {
! 209: printf(": cannot allocate PE descriptor ring\n");
! 210: goto bad4;
! 211: }
! 212: /*
! 213: * Hookup the static portion of all our data structures.
! 214: */
! 215: sc->sc_ring = (struct safe_ringentry *) sc->sc_ringalloc.dma_vaddr;
! 216: sc->sc_ringtop = sc->sc_ring + SAFE_MAX_NQUEUE;
! 217: sc->sc_front = sc->sc_ring;
! 218: sc->sc_back = sc->sc_ring;
! 219: raddr = sc->sc_ringalloc.dma_paddr;
! 220: bzero(sc->sc_ring, SAFE_MAX_NQUEUE * sizeof(struct safe_ringentry));
! 221: for (i = 0; i < SAFE_MAX_NQUEUE; i++) {
! 222: struct safe_ringentry *re = &sc->sc_ring[i];
! 223:
! 224: re->re_desc.d_sa = raddr +
! 225: offsetof(struct safe_ringentry, re_sa);
! 226: re->re_sa.sa_staterec = raddr +
! 227: offsetof(struct safe_ringentry, re_sastate);
! 228:
! 229: raddr += sizeof (struct safe_ringentry);
! 230: }
! 231:
! 232: /*
! 233: * Allocate scatter and gather particle descriptors.
! 234: */
! 235: if (safe_dma_malloc(sc, SAFE_TOTAL_SPART * sizeof (struct safe_pdesc),
! 236: &sc->sc_spalloc, 0)) {
! 237: printf(": cannot allocate source particle descriptor ring\n");
! 238: safe_dma_free(sc, &sc->sc_ringalloc);
! 239: goto bad4;
! 240: }
! 241: sc->sc_spring = (struct safe_pdesc *) sc->sc_spalloc.dma_vaddr;
! 242: sc->sc_springtop = sc->sc_spring + SAFE_TOTAL_SPART;
! 243: sc->sc_spfree = sc->sc_spring;
! 244: bzero(sc->sc_spring, SAFE_TOTAL_SPART * sizeof(struct safe_pdesc));
! 245:
! 246: if (safe_dma_malloc(sc, SAFE_TOTAL_DPART * sizeof (struct safe_pdesc),
! 247: &sc->sc_dpalloc, 0)) {
! 248: printf(": cannot allocate destination particle "
! 249: "descriptor ring\n");
! 250: safe_dma_free(sc, &sc->sc_spalloc);
! 251: safe_dma_free(sc, &sc->sc_ringalloc);
! 252: goto bad4;
! 253: }
! 254: sc->sc_dpring = (struct safe_pdesc *) sc->sc_dpalloc.dma_vaddr;
! 255: sc->sc_dpringtop = sc->sc_dpring + SAFE_TOTAL_DPART;
! 256: sc->sc_dpfree = sc->sc_dpring;
! 257: bzero(sc->sc_dpring, SAFE_TOTAL_DPART * sizeof(struct safe_pdesc));
! 258:
! 259: printf(":");
! 260:
! 261: devinfo = READ_REG(sc, SAFE_DEVINFO);
! 262: if (devinfo & SAFE_DEVINFO_RNG)
! 263: printf(" RNG");
! 264:
! 265: bzero(algs, sizeof(algs));
! 266: if (devinfo & SAFE_DEVINFO_PKEY) {
! 267: printf(" PK");
! 268: algs[CRK_MOD_EXP] = CRYPTO_ALG_FLAG_SUPPORTED;
! 269: crypto_kregister(sc->sc_cid, algs, safe_kprocess);
! 270: timeout_set(&sc->sc_pkto, safe_kpoll, sc);
! 271: }
! 272:
! 273: bzero(algs, sizeof(algs));
! 274: if (devinfo & SAFE_DEVINFO_DES) {
! 275: printf(" 3DES");
! 276: algs[CRYPTO_3DES_CBC] = CRYPTO_ALG_FLAG_SUPPORTED;
! 277: algs[CRYPTO_DES_CBC] = CRYPTO_ALG_FLAG_SUPPORTED;
! 278: }
! 279: if (devinfo & SAFE_DEVINFO_AES) {
! 280: printf(" AES");
! 281: algs[CRYPTO_AES_CBC] = CRYPTO_ALG_FLAG_SUPPORTED;
! 282: }
! 283: if (devinfo & SAFE_DEVINFO_MD5) {
! 284: printf(" MD5");
! 285: algs[CRYPTO_MD5_HMAC] = CRYPTO_ALG_FLAG_SUPPORTED;
! 286: }
! 287: if (devinfo & SAFE_DEVINFO_SHA1) {
! 288: printf(" SHA1");
! 289: algs[CRYPTO_SHA1_HMAC] = CRYPTO_ALG_FLAG_SUPPORTED;
! 290: }
! 291: crypto_register(sc->sc_cid, algs, safe_newsession,
! 292: safe_freesession, safe_process);
! 293: /* XXX other supported algorithms? */
! 294:
! 295: printf(", %s\n", intrstr);
! 296:
! 297: safe_reset_board(sc); /* reset h/w */
! 298: safe_init_pciregs(sc); /* init pci settings */
! 299: safe_init_board(sc); /* init h/w */
! 300:
! 301: if (devinfo & SAFE_DEVINFO_RNG) {
! 302: safe_rng_init(sc);
! 303:
! 304: timeout_set(&sc->sc_rngto, safe_rng, sc);
! 305: timeout_add(&sc->sc_rngto, hz * safe_rnginterval);
! 306: }
! 307: return;
! 308:
! 309: bad4:
! 310: /* XXX crypto_unregister_all(sc->sc_cid); */
! 311: bad3:
! 312: pci_intr_disestablish(pa->pa_pc, sc->sc_ih);
! 313: bad2:
! 314: /* pci_intr_unmap? */;
! 315: bad1:
! 316: bus_space_unmap(sc->sc_st, sc->sc_sh, iosize);
! 317: bad:
! 318: return;
! 319: }
! 320:
! 321: int
! 322: safe_process(struct cryptop *crp)
! 323: {
! 324: int err = 0, i, nicealign, uniform, s;
! 325: struct safe_softc *sc;
! 326: struct cryptodesc *crd1, *crd2, *maccrd, *enccrd;
! 327: int bypass, oplen, ivsize, card;
! 328: int16_t coffset;
! 329: struct safe_session *ses;
! 330: struct safe_ringentry *re;
! 331: struct safe_sarec *sa;
! 332: struct safe_pdesc *pd;
! 333: u_int32_t cmd0, cmd1, staterec, iv[4];
! 334:
! 335: s = splnet();
! 336: if (crp == NULL || crp->crp_callback == NULL) {
! 337: safestats.st_invalid++;
! 338: splx(s);
! 339: return (EINVAL);
! 340: }
! 341: card = SAFE_CARD(crp->crp_sid);
! 342: if (card >= safe_cd.cd_ndevs || safe_cd.cd_devs[card] == NULL) {
! 343: safestats.st_invalid++;
! 344: splx(s);
! 345: return (EINVAL);
! 346: }
! 347: sc = safe_cd.cd_devs[card];
! 348:
! 349: if (SAFE_SESSION(crp->crp_sid) >= sc->sc_nsessions) {
! 350: safestats.st_badsession++;
! 351: splx(s);
! 352: return (EINVAL);
! 353: }
! 354:
! 355: if (sc->sc_front == sc->sc_back && sc->sc_nqchip != 0) {
! 356: safestats.st_ringfull++;
! 357: splx(s);
! 358: return (ERESTART);
! 359: }
! 360: re = sc->sc_front;
! 361:
! 362: staterec = re->re_sa.sa_staterec; /* save */
! 363: /* NB: zero everything but the PE descriptor */
! 364: bzero(&re->re_sa, sizeof(struct safe_ringentry) - sizeof(re->re_desc));
! 365: re->re_sa.sa_staterec = staterec; /* restore */
! 366:
! 367: re->re_crp = crp;
! 368: re->re_sesn = SAFE_SESSION(crp->crp_sid);
! 369:
! 370: if (crp->crp_flags & CRYPTO_F_IMBUF) {
! 371: re->re_src_m = (struct mbuf *)crp->crp_buf;
! 372: re->re_dst_m = (struct mbuf *)crp->crp_buf;
! 373: } else if (crp->crp_flags & CRYPTO_F_IOV) {
! 374: re->re_src_io = (struct uio *)crp->crp_buf;
! 375: re->re_dst_io = (struct uio *)crp->crp_buf;
! 376: } else {
! 377: safestats.st_badflags++;
! 378: err = EINVAL;
! 379: goto errout; /* XXX we don't handle contiguous blocks! */
! 380: }
! 381:
! 382: sa = &re->re_sa;
! 383: ses = &sc->sc_sessions[re->re_sesn];
! 384:
! 385: crd1 = crp->crp_desc;
! 386: if (crd1 == NULL) {
! 387: safestats.st_nodesc++;
! 388: err = EINVAL;
! 389: goto errout;
! 390: }
! 391: crd2 = crd1->crd_next;
! 392:
! 393: cmd0 = SAFE_SA_CMD0_BASIC; /* basic group operation */
! 394: cmd1 = 0;
! 395: if (crd2 == NULL) {
! 396: if (crd1->crd_alg == CRYPTO_MD5_HMAC ||
! 397: crd1->crd_alg == CRYPTO_SHA1_HMAC) {
! 398: maccrd = crd1;
! 399: enccrd = NULL;
! 400: cmd0 |= SAFE_SA_CMD0_OP_HASH;
! 401: } else if (crd1->crd_alg == CRYPTO_DES_CBC ||
! 402: crd1->crd_alg == CRYPTO_3DES_CBC ||
! 403: crd1->crd_alg == CRYPTO_AES_CBC) {
! 404: maccrd = NULL;
! 405: enccrd = crd1;
! 406: cmd0 |= SAFE_SA_CMD0_OP_CRYPT;
! 407: } else {
! 408: safestats.st_badalg++;
! 409: err = EINVAL;
! 410: goto errout;
! 411: }
! 412: } else {
! 413: if ((crd1->crd_alg == CRYPTO_MD5_HMAC ||
! 414: crd1->crd_alg == CRYPTO_SHA1_HMAC) &&
! 415: (crd2->crd_alg == CRYPTO_DES_CBC ||
! 416: crd2->crd_alg == CRYPTO_3DES_CBC ||
! 417: crd2->crd_alg == CRYPTO_AES_CBC) &&
! 418: ((crd2->crd_flags & CRD_F_ENCRYPT) == 0)) {
! 419: maccrd = crd1;
! 420: enccrd = crd2;
! 421: } else if ((crd1->crd_alg == CRYPTO_DES_CBC ||
! 422: crd1->crd_alg == CRYPTO_3DES_CBC ||
! 423: crd1->crd_alg == CRYPTO_AES_CBC) &&
! 424: (crd2->crd_alg == CRYPTO_MD5_HMAC ||
! 425: crd2->crd_alg == CRYPTO_SHA1_HMAC) &&
! 426: (crd1->crd_flags & CRD_F_ENCRYPT)) {
! 427: enccrd = crd1;
! 428: maccrd = crd2;
! 429: } else {
! 430: safestats.st_badalg++;
! 431: err = EINVAL;
! 432: goto errout;
! 433: }
! 434: cmd0 |= SAFE_SA_CMD0_OP_BOTH;
! 435: }
! 436:
! 437: if (enccrd) {
! 438: if (enccrd->crd_alg == CRYPTO_DES_CBC) {
! 439: cmd0 |= SAFE_SA_CMD0_DES;
! 440: cmd1 |= SAFE_SA_CMD1_CBC;
! 441: ivsize = 2*sizeof(u_int32_t);
! 442: } else if (enccrd->crd_alg == CRYPTO_3DES_CBC) {
! 443: cmd0 |= SAFE_SA_CMD0_3DES;
! 444: cmd1 |= SAFE_SA_CMD1_CBC;
! 445: ivsize = 2*sizeof(u_int32_t);
! 446: } else if (enccrd->crd_alg == CRYPTO_AES_CBC) {
! 447: cmd0 |= SAFE_SA_CMD0_AES;
! 448: cmd1 |= SAFE_SA_CMD1_CBC;
! 449: if (ses->ses_klen == 128)
! 450: cmd1 |= SAFE_SA_CMD1_AES128;
! 451: else if (ses->ses_klen == 192)
! 452: cmd1 |= SAFE_SA_CMD1_AES192;
! 453: else
! 454: cmd1 |= SAFE_SA_CMD1_AES256;
! 455: ivsize = 4*sizeof(u_int32_t);
! 456: } else {
! 457: cmd0 |= SAFE_SA_CMD0_CRYPT_NULL;
! 458: ivsize = 0;
! 459: }
! 460:
! 461: /*
! 462: * Setup encrypt/decrypt state. When using basic ops
! 463: * we can't use an inline IV because hash/crypt offset
! 464: * must be from the end of the IV to the start of the
! 465: * crypt data and this leaves out the preceding header
! 466: * from the hash calculation. Instead we place the IV
! 467: * in the state record and set the hash/crypt offset to
! 468: * copy both the header+IV.
! 469: */
! 470: if (enccrd->crd_flags & CRD_F_ENCRYPT) {
! 471: cmd0 |= SAFE_SA_CMD0_OUTBOUND;
! 472:
! 473: if (enccrd->crd_flags & CRD_F_IV_EXPLICIT)
! 474: bcopy(enccrd->crd_iv, iv, ivsize);
! 475: else
! 476: bcopy(ses->ses_iv, iv, ivsize);
! 477: if ((enccrd->crd_flags & CRD_F_IV_PRESENT) == 0) {
! 478: if (crp->crp_flags & CRYPTO_F_IMBUF)
! 479: m_copyback(re->re_src_m,
! 480: enccrd->crd_inject, ivsize, iv);
! 481: else if (crp->crp_flags & CRYPTO_F_IOV)
! 482: cuio_copyback(re->re_src_io,
! 483: enccrd->crd_inject, ivsize, iv);
! 484: }
! 485: for (i = 0; i < ivsize / sizeof(iv[0]); i++)
! 486: re->re_sastate.sa_saved_iv[i] = htole32(iv[i]);
! 487: cmd0 |= SAFE_SA_CMD0_IVLD_STATE | SAFE_SA_CMD0_SAVEIV;
! 488: re->re_flags |= SAFE_QFLAGS_COPYOUTIV;
! 489: } else {
! 490: cmd0 |= SAFE_SA_CMD0_INBOUND;
! 491:
! 492: if (enccrd->crd_flags & CRD_F_IV_EXPLICIT)
! 493: bcopy(enccrd->crd_iv, iv, ivsize);
! 494: else if (crp->crp_flags & CRYPTO_F_IMBUF)
! 495: m_copydata(re->re_src_m, enccrd->crd_inject,
! 496: ivsize, (caddr_t)iv);
! 497: else if (crp->crp_flags & CRYPTO_F_IOV)
! 498: cuio_copydata(re->re_src_io, enccrd->crd_inject,
! 499: ivsize, (caddr_t)iv);
! 500: for (i = 0; i < ivsize / sizeof(iv[0]); i++)
! 501: re->re_sastate.sa_saved_iv[i] = htole32(iv[i]);
! 502: cmd0 |= SAFE_SA_CMD0_IVLD_STATE;
! 503: }
! 504: /*
! 505: * For basic encryption use the zero pad algorithm.
! 506: * This pads results to an 8-byte boundary and
! 507: * suppresses padding verification for inbound (i.e.
! 508: * decrypt) operations.
! 509: *
! 510: * NB: Not sure if the 8-byte pad boundary is a problem.
! 511: */
! 512: cmd0 |= SAFE_SA_CMD0_PAD_ZERO;
! 513:
! 514: /* XXX assert key bufs have the same size */
! 515: for (i = 0; i < sizeof(sa->sa_key)/sizeof(sa->sa_key[0]); i++)
! 516: sa->sa_key[i] = ses->ses_key[i];
! 517: }
! 518:
! 519: if (maccrd) {
! 520: if (maccrd->crd_alg == CRYPTO_MD5_HMAC) {
! 521: cmd0 |= SAFE_SA_CMD0_MD5;
! 522: cmd1 |= SAFE_SA_CMD1_HMAC; /* NB: enable HMAC */
! 523: } else if (maccrd->crd_alg == CRYPTO_SHA1_HMAC) {
! 524: cmd0 |= SAFE_SA_CMD0_SHA1;
! 525: cmd1 |= SAFE_SA_CMD1_HMAC; /* NB: enable HMAC */
! 526: } else {
! 527: cmd0 |= SAFE_SA_CMD0_HASH_NULL;
! 528: }
! 529: /*
! 530: * Digest data is loaded from the SA and the hash
! 531: * result is saved to the state block where we
! 532: * retrieve it for return to the caller.
! 533: */
! 534: /* XXX assert digest bufs have the same size */
! 535: for (i = 0;
! 536: i < sizeof(sa->sa_outdigest)/sizeof(sa->sa_outdigest[i]);
! 537: i++) {
! 538: sa->sa_indigest[i] = ses->ses_hminner[i];
! 539: sa->sa_outdigest[i] = ses->ses_hmouter[i];
! 540: }
! 541:
! 542: cmd0 |= SAFE_SA_CMD0_HSLD_SA | SAFE_SA_CMD0_SAVEHASH;
! 543: re->re_flags |= SAFE_QFLAGS_COPYOUTICV;
! 544: }
! 545:
! 546: if (enccrd && maccrd) {
! 547: /*
! 548: * The offset from hash data to the start of
! 549: * crypt data is the difference in the skips.
! 550: */
! 551: bypass = maccrd->crd_skip;
! 552: coffset = enccrd->crd_skip - maccrd->crd_skip;
! 553: if (coffset < 0) {
! 554: DPRINTF(("%s: hash does not precede crypt; "
! 555: "mac skip %u enc skip %u\n",
! 556: __func__, maccrd->crd_skip, enccrd->crd_skip));
! 557: safestats.st_skipmismatch++;
! 558: err = EINVAL;
! 559: goto errout;
! 560: }
! 561: oplen = enccrd->crd_skip + enccrd->crd_len;
! 562: if (maccrd->crd_skip + maccrd->crd_len != oplen) {
! 563: DPRINTF(("%s: hash amount %u != crypt amount %u\n",
! 564: __func__, maccrd->crd_skip + maccrd->crd_len,
! 565: oplen));
! 566: safestats.st_lenmismatch++;
! 567: err = EINVAL;
! 568: goto errout;
! 569: }
! 570: #ifdef SAFE_DEBUG
! 571: if (safe_debug) {
! 572: printf("mac: skip %d, len %d, inject %d\n",
! 573: maccrd->crd_skip, maccrd->crd_len,
! 574: maccrd->crd_inject);
! 575: printf("enc: skip %d, len %d, inject %d\n",
! 576: enccrd->crd_skip, enccrd->crd_len,
! 577: enccrd->crd_inject);
! 578: printf("bypass %d coffset %d oplen %d\n",
! 579: bypass, coffset, oplen);
! 580: }
! 581: #endif
! 582: if (coffset & 3) { /* offset must be 32-bit aligned */
! 583: DPRINTF(("%s: coffset %u misaligned\n",
! 584: __func__, coffset));
! 585: safestats.st_coffmisaligned++;
! 586: err = EINVAL;
! 587: goto errout;
! 588: }
! 589: coffset >>= 2;
! 590: if (coffset > 255) { /* offset must be <256 dwords */
! 591: DPRINTF(("%s: coffset %u too big\n",
! 592: __func__, coffset));
! 593: safestats.st_cofftoobig++;
! 594: err = EINVAL;
! 595: goto errout;
! 596: }
! 597: /*
! 598: * Tell the hardware to copy the header to the output.
! 599: * The header is defined as the data from the end of
! 600: * the bypass to the start of data to be encrypted.
! 601: * Typically this is the inline IV. Note that you need
! 602: * to do this even if src+dst are the same; it appears
! 603: * that w/o this bit the crypted data is written
! 604: * immediately after the bypass data.
! 605: */
! 606: cmd1 |= SAFE_SA_CMD1_HDRCOPY;
! 607: /*
! 608: * Disable IP header mutable bit handling. This is
! 609: * needed to get correct HMAC calculations.
! 610: */
! 611: cmd1 |= SAFE_SA_CMD1_MUTABLE;
! 612: } else {
! 613: if (enccrd) {
! 614: bypass = enccrd->crd_skip;
! 615: oplen = bypass + enccrd->crd_len;
! 616: } else {
! 617: bypass = maccrd->crd_skip;
! 618: oplen = bypass + maccrd->crd_len;
! 619: }
! 620: coffset = 0;
! 621: }
! 622: /* XXX verify multiple of 4 when using s/g */
! 623: if (bypass > 96) { /* bypass offset must be <= 96 bytes */
! 624: DPRINTF(("%s: bypass %u too big\n", __func__, bypass));
! 625: safestats.st_bypasstoobig++;
! 626: err = EINVAL;
! 627: goto errout;
! 628: }
! 629:
! 630: if (bus_dmamap_create(sc->sc_dmat, SAFE_MAX_DMA, SAFE_MAX_PART,
! 631: SAFE_MAX_DSIZE, SAFE_MAX_DSIZE, BUS_DMA_ALLOCNOW | BUS_DMA_NOWAIT,
! 632: &re->re_src_map)) {
! 633: safestats.st_nomap++;
! 634: err = ENOMEM;
! 635: goto errout;
! 636: }
! 637: if (crp->crp_flags & CRYPTO_F_IMBUF) {
! 638: if (bus_dmamap_load_mbuf(sc->sc_dmat, re->re_src_map,
! 639: re->re_src_m, BUS_DMA_NOWAIT)) {
! 640: bus_dmamap_destroy(sc->sc_dmat, re->re_src_map);
! 641: re->re_src_map = NULL;
! 642: safestats.st_noload++;
! 643: err = ENOMEM;
! 644: goto errout;
! 645: }
! 646: } else if (crp->crp_flags & CRYPTO_F_IOV) {
! 647: if (bus_dmamap_load_uio(sc->sc_dmat, re->re_src_map,
! 648: re->re_src_io, BUS_DMA_NOWAIT) != 0) {
! 649: bus_dmamap_destroy(sc->sc_dmat, re->re_src_map);
! 650: re->re_src_map = NULL;
! 651: safestats.st_noload++;
! 652: err = ENOMEM;
! 653: goto errout;
! 654: }
! 655: }
! 656: nicealign = safe_dmamap_aligned(&re->re_src);
! 657: uniform = safe_dmamap_uniform(&re->re_src);
! 658:
! 659: DPRINTF(("src nicealign %u uniform %u nsegs %u\n",
! 660: nicealign, uniform, re->re_src_nsegs));
! 661: if (re->re_src_nsegs > 1) {
! 662: re->re_desc.d_src = sc->sc_spalloc.dma_paddr +
! 663: ((caddr_t) sc->sc_spfree - (caddr_t) sc->sc_spring);
! 664: for (i = 0; i < re->re_src_nsegs; i++) {
! 665: /* NB: no need to check if there's space */
! 666: pd = sc->sc_spfree;
! 667: if (++(sc->sc_spfree) == sc->sc_springtop)
! 668: sc->sc_spfree = sc->sc_spring;
! 669:
! 670: KASSERT_X((pd->pd_flags&3) == 0 ||
! 671: (pd->pd_flags&3) == SAFE_PD_DONE,
! 672: ("bogus source particle descriptor; flags %x",
! 673: pd->pd_flags));
! 674: pd->pd_addr = re->re_src_segs[i].ds_addr;
! 675: pd->pd_ctrl = SAFE_PD_READY |
! 676: ((re->re_src_segs[i].ds_len << SAFE_PD_LEN_S)
! 677: & SAFE_PD_LEN_M);
! 678: }
! 679: cmd0 |= SAFE_SA_CMD0_IGATHER;
! 680: } else {
! 681: /*
! 682: * No need for gather, reference the operand directly.
! 683: */
! 684: re->re_desc.d_src = re->re_src_segs[0].ds_addr;
! 685: }
! 686:
! 687: if (enccrd == NULL && maccrd != NULL) {
! 688: /*
! 689: * Hash op; no destination needed.
! 690: */
! 691: } else {
! 692: if (crp->crp_flags & CRYPTO_F_IOV) {
! 693: if (!nicealign) {
! 694: safestats.st_iovmisaligned++;
! 695: err = EINVAL;
! 696: goto errout;
! 697: }
! 698: if (uniform != 1) {
! 699: /*
! 700: * Source is not suitable for direct use as
! 701: * the destination. Create a new scatter/gather
! 702: * list based on the destination requirements
! 703: * and check if that's ok.
! 704: */
! 705: if (bus_dmamap_create(sc->sc_dmat,
! 706: SAFE_MAX_DMA, SAFE_MAX_PART,
! 707: SAFE_MAX_DSIZE, SAFE_MAX_DSIZE,
! 708: BUS_DMA_ALLOCNOW | BUS_DMA_NOWAIT,
! 709: &re->re_dst_map)) {
! 710: safestats.st_nomap++;
! 711: err = ENOMEM;
! 712: goto errout;
! 713: }
! 714: if (bus_dmamap_load_uio(sc->sc_dmat,
! 715: re->re_dst_map, re->re_dst_io,
! 716: BUS_DMA_NOWAIT) != 0) {
! 717: bus_dmamap_destroy(sc->sc_dmat,
! 718: re->re_dst_map);
! 719: re->re_dst_map = NULL;
! 720: safestats.st_noload++;
! 721: err = ENOMEM;
! 722: goto errout;
! 723: }
! 724: uniform = safe_dmamap_uniform(&re->re_dst);
! 725: if (!uniform) {
! 726: /*
! 727: * There's no way to handle the DMA
! 728: * requirements with this uio. We
! 729: * could create a separate DMA area for
! 730: * the result and then copy it back,
! 731: * but for now we just bail and return
! 732: * an error. Note that uio requests
! 733: * > SAFE_MAX_DSIZE are handled because
! 734: * the DMA map and segment list for the
! 735: * destination will result in a
! 736: * destination particle list that does
! 737: * the necessary scatter DMA.
! 738: */
! 739: safestats.st_iovnotuniform++;
! 740: err = EINVAL;
! 741: goto errout;
! 742: }
! 743: } else
! 744: re->re_dst = re->re_src;
! 745: } else if (crp->crp_flags & CRYPTO_F_IMBUF) {
! 746: if (nicealign && uniform == 1) {
! 747: /*
! 748: * Source layout is suitable for direct
! 749: * sharing of the DMA map and segment list.
! 750: */
! 751: re->re_dst = re->re_src;
! 752: } else if (nicealign && uniform == 2) {
! 753: /*
! 754: * The source is properly aligned but requires a
! 755: * different particle list to handle DMA of the
! 756: * result. Create a new map and do the load to
! 757: * create the segment list. The particle
! 758: * descriptor setup code below will handle the
! 759: * rest.
! 760: */
! 761: if (bus_dmamap_create(sc->sc_dmat,
! 762: SAFE_MAX_DMA, SAFE_MAX_PART,
! 763: SAFE_MAX_DSIZE, SAFE_MAX_DSIZE,
! 764: BUS_DMA_ALLOCNOW | BUS_DMA_NOWAIT,
! 765: &re->re_dst_map)) {
! 766: safestats.st_nomap++;
! 767: err = ENOMEM;
! 768: goto errout;
! 769: }
! 770: if (bus_dmamap_load_mbuf(sc->sc_dmat,
! 771: re->re_dst_map, re->re_dst_m,
! 772: BUS_DMA_NOWAIT) != 0) {
! 773: bus_dmamap_destroy(sc->sc_dmat,
! 774: re->re_dst_map);
! 775: re->re_dst_map = NULL;
! 776: safestats.st_noload++;
! 777: err = ENOMEM;
! 778: goto errout;
! 779: }
! 780: } else { /* !(aligned and/or uniform) */
! 781: int totlen, len;
! 782: struct mbuf *m, *top, **mp;
! 783:
! 784: /*
! 785: * DMA constraints require that we allocate a
! 786: * new mbuf chain for the destination. We
! 787: * allocate an entire new set of mbufs of
! 788: * optimal/required size and then tell the
! 789: * hardware to copy any bits that are not
! 790: * created as a byproduct of the operation.
! 791: */
! 792: if (!nicealign)
! 793: safestats.st_unaligned++;
! 794: if (!uniform)
! 795: safestats.st_notuniform++;
! 796: totlen = re->re_src_mapsize;
! 797: if (re->re_src_m->m_flags & M_PKTHDR) {
! 798: len = MHLEN;
! 799: MGETHDR(m, M_DONTWAIT, MT_DATA);
! 800: } else {
! 801: len = MLEN;
! 802: MGET(m, M_DONTWAIT, MT_DATA);
! 803: }
! 804: if (m == NULL) {
! 805: safestats.st_nombuf++;
! 806: err = sc->sc_nqchip ? ERESTART : ENOMEM;
! 807: goto errout;
! 808: }
! 809: if (len == MHLEN)
! 810: M_DUP_PKTHDR(m, re->re_src_m);
! 811: if (totlen >= MINCLSIZE) {
! 812: MCLGET(m, M_DONTWAIT);
! 813: if ((m->m_flags & M_EXT) == 0) {
! 814: m_free(m);
! 815: safestats.st_nomcl++;
! 816: err = sc->sc_nqchip ?
! 817: ERESTART : ENOMEM;
! 818: goto errout;
! 819: }
! 820: len = MCLBYTES;
! 821: }
! 822: m->m_len = len;
! 823: top = NULL;
! 824: mp = ⊤
! 825:
! 826: while (totlen > 0) {
! 827: if (top) {
! 828: MGET(m, M_DONTWAIT, MT_DATA);
! 829: if (m == NULL) {
! 830: m_freem(top);
! 831: safestats.st_nombuf++;
! 832: err = sc->sc_nqchip ?
! 833: ERESTART : ENOMEM;
! 834: goto errout;
! 835: }
! 836: len = MLEN;
! 837: }
! 838: if (top && totlen >= MINCLSIZE) {
! 839: MCLGET(m, M_DONTWAIT);
! 840: if ((m->m_flags & M_EXT) == 0) {
! 841: *mp = m;
! 842: m_freem(top);
! 843: safestats.st_nomcl++;
! 844: err = sc->sc_nqchip ?
! 845: ERESTART : ENOMEM;
! 846: goto errout;
! 847: }
! 848: len = MCLBYTES;
! 849: }
! 850: m->m_len = len = min(totlen, len);
! 851: totlen -= len;
! 852: *mp = m;
! 853: mp = &m->m_next;
! 854: }
! 855: re->re_dst_m = top;
! 856: if (bus_dmamap_create(sc->sc_dmat,
! 857: SAFE_MAX_DMA, SAFE_MAX_PART,
! 858: SAFE_MAX_DSIZE, SAFE_MAX_DSIZE,
! 859: BUS_DMA_ALLOCNOW | BUS_DMA_NOWAIT,
! 860: &re->re_dst_map) != 0) {
! 861: safestats.st_nomap++;
! 862: err = ENOMEM;
! 863: goto errout;
! 864: }
! 865: if (bus_dmamap_load_mbuf(sc->sc_dmat,
! 866: re->re_dst_map, re->re_dst_m,
! 867: BUS_DMA_NOWAIT) != 0) {
! 868: bus_dmamap_destroy(sc->sc_dmat,
! 869: re->re_dst_map);
! 870: re->re_dst_map = NULL;
! 871: safestats.st_noload++;
! 872: err = ENOMEM;
! 873: goto errout;
! 874: }
! 875: if (re->re_src_mapsize > oplen) {
! 876: /*
! 877: * There's data following what the
! 878: * hardware will copy for us. If this
! 879: * isn't just the ICV (that's going to
! 880: * be written on completion), copy it
! 881: * to the new mbufs
! 882: */
! 883: if (!(maccrd &&
! 884: (re->re_src_mapsize-oplen) == 12 &&
! 885: maccrd->crd_inject == oplen))
! 886: safe_mcopy(re->re_src_m,
! 887: re->re_dst_m,
! 888: oplen);
! 889: else
! 890: safestats.st_noicvcopy++;
! 891: }
! 892: }
! 893: } else {
! 894: safestats.st_badflags++;
! 895: err = EINVAL;
! 896: goto errout;
! 897: }
! 898:
! 899: if (re->re_dst_nsegs > 1) {
! 900: re->re_desc.d_dst = sc->sc_dpalloc.dma_paddr +
! 901: ((caddr_t) sc->sc_dpfree - (caddr_t) sc->sc_dpring);
! 902: for (i = 0; i < re->re_dst_nsegs; i++) {
! 903: pd = sc->sc_dpfree;
! 904: KASSERT_X((pd->pd_flags&3) == 0 ||
! 905: (pd->pd_flags&3) == SAFE_PD_DONE,
! 906: ("bogus dest particle descriptor; flags %x",
! 907: pd->pd_flags));
! 908: if (++(sc->sc_dpfree) == sc->sc_dpringtop)
! 909: sc->sc_dpfree = sc->sc_dpring;
! 910: pd->pd_addr = re->re_dst_segs[i].ds_addr;
! 911: pd->pd_ctrl = SAFE_PD_READY;
! 912: }
! 913: cmd0 |= SAFE_SA_CMD0_OSCATTER;
! 914: } else {
! 915: /*
! 916: * No need for scatter, reference the operand directly.
! 917: */
! 918: re->re_desc.d_dst = re->re_dst_segs[0].ds_addr;
! 919: }
! 920: }
! 921:
! 922: /*
! 923: * All done with setup; fillin the SA command words
! 924: * and the packet engine descriptor. The operation
! 925: * is now ready for submission to the hardware.
! 926: */
! 927: sa->sa_cmd0 = cmd0 | SAFE_SA_CMD0_IPCI | SAFE_SA_CMD0_OPCI;
! 928: sa->sa_cmd1 = cmd1
! 929: | (coffset << SAFE_SA_CMD1_OFFSET_S)
! 930: | SAFE_SA_CMD1_SAREV1 /* Rev 1 SA data structure */
! 931: | SAFE_SA_CMD1_SRPCI;
! 932:
! 933: /*
! 934: * NB: the order of writes is important here. In case the
! 935: * chip is scanning the ring because of an outstanding request
! 936: * it might nab this one too. In that case we need to make
! 937: * sure the setup is complete before we write the length
! 938: * field of the descriptor as it signals the descriptor is
! 939: * ready for processing.
! 940: */
! 941: re->re_desc.d_csr = SAFE_PE_CSR_READY | SAFE_PE_CSR_SAPCI;
! 942: if (maccrd)
! 943: re->re_desc.d_csr |= SAFE_PE_CSR_LOADSA | SAFE_PE_CSR_HASHFINAL;
! 944: re->re_desc.d_len = oplen
! 945: | SAFE_PE_LEN_READY
! 946: | (bypass << SAFE_PE_LEN_BYPASS_S)
! 947: ;
! 948:
! 949: safestats.st_ipackets++;
! 950: safestats.st_ibytes += oplen;
! 951:
! 952: if (++(sc->sc_front) == sc->sc_ringtop)
! 953: sc->sc_front = sc->sc_ring;
! 954:
! 955: /* XXX honor batching */
! 956: safe_feed(sc, re);
! 957: splx(s);
! 958: return (0);
! 959:
! 960: errout:
! 961: if ((re->re_dst_m != NULL) && (re->re_src_m != re->re_dst_m))
! 962: m_freem(re->re_dst_m);
! 963:
! 964: if (re->re_dst_map != NULL && re->re_dst_map != re->re_src_map) {
! 965: bus_dmamap_unload(sc->sc_dmat, re->re_dst_map);
! 966: bus_dmamap_destroy(sc->sc_dmat, re->re_dst_map);
! 967: }
! 968: if (re->re_src_map != NULL) {
! 969: bus_dmamap_unload(sc->sc_dmat, re->re_src_map);
! 970: bus_dmamap_destroy(sc->sc_dmat, re->re_src_map);
! 971: }
! 972: crp->crp_etype = err;
! 973: crypto_done(crp);
! 974: splx(s);
! 975: return (err);
! 976: }
! 977:
! 978: /*
! 979: * Resets the board. Values in the regesters are left as is
! 980: * from the reset (i.e. initial values are assigned elsewhere).
! 981: */
! 982: void
! 983: safe_reset_board(struct safe_softc *sc)
! 984: {
! 985: u_int32_t v;
! 986:
! 987: /*
! 988: * Reset the device. The manual says no delay
! 989: * is needed between marking and clearing reset.
! 990: */
! 991: v = READ_REG(sc, SAFE_PE_DMACFG) &
! 992: ~(SAFE_PE_DMACFG_PERESET | SAFE_PE_DMACFG_PDRRESET |
! 993: SAFE_PE_DMACFG_SGRESET);
! 994: WRITE_REG(sc, SAFE_PE_DMACFG, v
! 995: | SAFE_PE_DMACFG_PERESET
! 996: | SAFE_PE_DMACFG_PDRRESET
! 997: | SAFE_PE_DMACFG_SGRESET);
! 998: WRITE_REG(sc, SAFE_PE_DMACFG, v);
! 999: }
! 1000:
! 1001: /*
! 1002: * Initialize registers we need to touch only once.
! 1003: */
! 1004: void
! 1005: safe_init_board(struct safe_softc *sc)
! 1006: {
! 1007: u_int32_t v, dwords;
! 1008:
! 1009: v = READ_REG(sc, SAFE_PE_DMACFG);
! 1010: v &= ~(SAFE_PE_DMACFG_PEMODE | SAFE_PE_DMACFG_ESPACKET);
! 1011: v |= SAFE_PE_DMACFG_FSENA /* failsafe enable */
! 1012: | SAFE_PE_DMACFG_GPRPCI /* gather ring on PCI */
! 1013: | SAFE_PE_DMACFG_SPRPCI /* scatter ring on PCI */
! 1014: | SAFE_PE_DMACFG_ESDESC /* endian-swap descriptors */
! 1015: | SAFE_PE_DMACFG_ESPDESC /* endian-swap part. desc's */
! 1016: | SAFE_PE_DMACFG_ESSA /* endian-swap SA data */
! 1017: ;
! 1018: WRITE_REG(sc, SAFE_PE_DMACFG, v);
! 1019:
! 1020: WRITE_REG(sc, SAFE_CRYPTO_CTRL, SAFE_CRYPTO_CTRL_PKEY |
! 1021: SAFE_CRYPTO_CTRL_3DES | SAFE_CRYPTO_CTRL_RNG);
! 1022:
! 1023: #if BYTE_ORDER == LITTLE_ENDIAN
! 1024: WRITE_REG(sc, SAFE_ENDIAN, SAFE_ENDIAN_TGT_PASS|SAFE_ENDIAN_DMA_PASS);
! 1025: #elif BYTE_ORDER == BIG_ENDIAN
! 1026: WRITE_REG(sc, SAFE_ENDIAN, SAFE_ENDIAN_TGT_PASS|SAFE_ENDIAN_DMA_SWAB);
! 1027: #endif
! 1028:
! 1029: if (sc->sc_chiprev == SAFE_REV(1,0)) {
! 1030: /*
! 1031: * Avoid large PCI DMA transfers. Rev 1.0 has a bug where
! 1032: * "target mode transfers" done while the chip is DMA'ing
! 1033: * >1020 bytes cause the hardware to lockup. To avoid this
! 1034: * we reduce the max PCI transfer size and use small source
! 1035: * particle descriptors (<= 256 bytes).
! 1036: */
! 1037: WRITE_REG(sc, SAFE_DMA_CFG, 256);
! 1038: printf("%s: Reduce max DMA size to %u words for rev %u.%u WAR\n",
! 1039: sc->sc_dev.dv_xname,
! 1040: (READ_REG(sc, SAFE_DMA_CFG)>>2) & 0xff,
! 1041: SAFE_REV_MAJ(sc->sc_chiprev),
! 1042: SAFE_REV_MIN(sc->sc_chiprev));
! 1043: }
! 1044:
! 1045: /* NB: operands+results are overlaid */
! 1046: WRITE_REG(sc, SAFE_PE_PDRBASE, sc->sc_ringalloc.dma_paddr);
! 1047: WRITE_REG(sc, SAFE_PE_RDRBASE, sc->sc_ringalloc.dma_paddr);
! 1048: /*
! 1049: * Configure ring entry size and number of items in the ring.
! 1050: */
! 1051: KASSERT_X((sizeof(struct safe_ringentry) % sizeof(u_int32_t)) == 0,
! 1052: ("PE ring entry not 32-bit aligned!"));
! 1053: dwords = sizeof(struct safe_ringentry) / sizeof(u_int32_t);
! 1054: WRITE_REG(sc, SAFE_PE_RINGCFG,
! 1055: (dwords << SAFE_PE_RINGCFG_OFFSET_S) | SAFE_MAX_NQUEUE);
! 1056: WRITE_REG(sc, SAFE_PE_RINGPOLL, 0); /* disable polling */
! 1057:
! 1058: WRITE_REG(sc, SAFE_PE_GRNGBASE, sc->sc_spalloc.dma_paddr);
! 1059: WRITE_REG(sc, SAFE_PE_SRNGBASE, sc->sc_dpalloc.dma_paddr);
! 1060: WRITE_REG(sc, SAFE_PE_PARTSIZE,
! 1061: (SAFE_TOTAL_DPART<<16) | SAFE_TOTAL_SPART);
! 1062: /*
! 1063: * NB: destination particles are fixed size. We use
! 1064: * an mbuf cluster and require all results go to
! 1065: * clusters or smaller.
! 1066: */
! 1067: WRITE_REG(sc, SAFE_PE_PARTCFG, SAFE_MAX_DSIZE);
! 1068:
! 1069: WRITE_REG(sc, SAFE_HI_CLR, SAFE_INT_PE_CDONE | SAFE_INT_PE_DDONE |
! 1070: SAFE_INT_PE_ERROR | SAFE_INT_PE_ODONE);
! 1071:
! 1072: /* it's now safe to enable PE mode, do it */
! 1073: WRITE_REG(sc, SAFE_PE_DMACFG, v | SAFE_PE_DMACFG_PEMODE);
! 1074:
! 1075: /*
! 1076: * Configure hardware to use level-triggered interrupts and
! 1077: * to interrupt after each descriptor is processed.
! 1078: */
! 1079: DELAY(1000);
! 1080: WRITE_REG(sc, SAFE_HI_CFG, SAFE_HI_CFG_LEVEL);
! 1081: DELAY(1000);
! 1082: WRITE_REG(sc, SAFE_HI_MASK, SAFE_INT_PE_DDONE | SAFE_INT_PE_ERROR);
! 1083: DELAY(1000);
! 1084: WRITE_REG(sc, SAFE_HI_DESC_CNT, 1);
! 1085: DELAY(1000);
! 1086: }
! 1087:
! 1088: /*
! 1089: * Init PCI registers
! 1090: */
! 1091: void
! 1092: safe_init_pciregs(struct safe_softc *sc)
! 1093: {
! 1094: }
! 1095:
! 1096: int
! 1097: safe_dma_malloc(struct safe_softc *sc, bus_size_t size,
! 1098: struct safe_dma_alloc *dma, int mapflags)
! 1099: {
! 1100: int r;
! 1101:
! 1102: if ((r = bus_dmamem_alloc(sc->sc_dmat, size, PAGE_SIZE, 0,
! 1103: &dma->dma_seg, 1, &dma->dma_nseg, BUS_DMA_NOWAIT)) != 0)
! 1104: goto fail_0;
! 1105:
! 1106: if ((r = bus_dmamem_map(sc->sc_dmat, &dma->dma_seg, dma->dma_nseg,
! 1107: size, &dma->dma_vaddr, mapflags | BUS_DMA_NOWAIT)) != 0)
! 1108: goto fail_1;
! 1109:
! 1110: if ((r = bus_dmamap_create(sc->sc_dmat, size, 1, size, 0,
! 1111: BUS_DMA_NOWAIT, &dma->dma_map)) != 0)
! 1112: goto fail_2;
! 1113:
! 1114: if ((r = bus_dmamap_load(sc->sc_dmat, dma->dma_map, dma->dma_vaddr,
! 1115: size, NULL, BUS_DMA_NOWAIT)) != 0)
! 1116: goto fail_3;
! 1117:
! 1118: dma->dma_paddr = dma->dma_map->dm_segs[0].ds_addr;
! 1119: dma->dma_size = size;
! 1120: return (0);
! 1121:
! 1122: fail_3:
! 1123: bus_dmamap_destroy(sc->sc_dmat, dma->dma_map);
! 1124: fail_2:
! 1125: bus_dmamem_unmap(sc->sc_dmat, dma->dma_vaddr, size);
! 1126: fail_1:
! 1127: bus_dmamem_free(sc->sc_dmat, &dma->dma_seg, dma->dma_nseg);
! 1128: fail_0:
! 1129: dma->dma_map = NULL;
! 1130: return (r);
! 1131: }
! 1132:
! 1133: void
! 1134: safe_dma_free(struct safe_softc *sc, struct safe_dma_alloc *dma)
! 1135: {
! 1136: bus_dmamap_unload(sc->sc_dmat, dma->dma_map);
! 1137: bus_dmamem_unmap(sc->sc_dmat, dma->dma_vaddr, dma->dma_size);
! 1138: bus_dmamem_free(sc->sc_dmat, &dma->dma_seg, dma->dma_nseg);
! 1139: bus_dmamap_destroy(sc->sc_dmat, dma->dma_map);
! 1140: }
! 1141:
! 1142:
! 1143: #define SAFE_RNG_MAXWAIT 1000
! 1144:
! 1145: void
! 1146: safe_rng_init(struct safe_softc *sc)
! 1147: {
! 1148: u_int32_t w, v;
! 1149: int i;
! 1150:
! 1151: WRITE_REG(sc, SAFE_RNG_CTRL, 0);
! 1152: /* use default value according to the manual */
! 1153: WRITE_REG(sc, SAFE_RNG_CNFG, 0x834); /* magic from SafeNet */
! 1154: WRITE_REG(sc, SAFE_RNG_ALM_CNT, 0);
! 1155:
! 1156: /*
! 1157: * There is a bug in rev 1.0 of the 1140 that when the RNG
! 1158: * is brought out of reset the ready status flag does not
! 1159: * work until the RNG has finished its internal initialization.
! 1160: *
! 1161: * So in order to determine the device is through its
! 1162: * initialization we must read the data register, using the
! 1163: * status reg in the read in case it is initialized. Then read
! 1164: * the data register until it changes from the first read.
! 1165: * Once it changes read the data register until it changes
! 1166: * again. At this time the RNG is considered initialized.
! 1167: * This could take between 750ms - 1000ms in time.
! 1168: */
! 1169: i = 0;
! 1170: w = READ_REG(sc, SAFE_RNG_OUT);
! 1171: do {
! 1172: v = READ_REG(sc, SAFE_RNG_OUT);
! 1173: if (v != w) {
! 1174: w = v;
! 1175: break;
! 1176: }
! 1177: DELAY(10);
! 1178: } while (++i < SAFE_RNG_MAXWAIT);
! 1179:
! 1180: /* Wait Until data changes again */
! 1181: i = 0;
! 1182: do {
! 1183: v = READ_REG(sc, SAFE_RNG_OUT);
! 1184: if (v != w)
! 1185: break;
! 1186: DELAY(10);
! 1187: } while (++i < SAFE_RNG_MAXWAIT);
! 1188: }
! 1189:
! 1190: __inline u_int32_t
! 1191: safe_rng_read(struct safe_softc *sc)
! 1192: {
! 1193: int i;
! 1194:
! 1195: i = 0;
! 1196: while (READ_REG(sc, SAFE_RNG_STAT) != 0 && ++i < SAFE_RNG_MAXWAIT)
! 1197: ;
! 1198: return (READ_REG(sc, SAFE_RNG_OUT));
! 1199: }
! 1200:
! 1201: void
! 1202: safe_rng(void *arg)
! 1203: {
! 1204: struct safe_softc *sc = arg;
! 1205: u_int32_t buf[SAFE_RNG_MAXBUFSIZ]; /* NB: maybe move to softc */
! 1206: u_int maxwords;
! 1207: int i;
! 1208:
! 1209: safestats.st_rng++;
! 1210: /*
! 1211: * Fetch the next block of data.
! 1212: */
! 1213: maxwords = safe_rngbufsize;
! 1214: if (maxwords > SAFE_RNG_MAXBUFSIZ)
! 1215: maxwords = SAFE_RNG_MAXBUFSIZ;
! 1216: retry:
! 1217: for (i = 0; i < maxwords; i++)
! 1218: buf[i] = safe_rng_read(sc);
! 1219: /*
! 1220: * Check the comparator alarm count and reset the h/w if
! 1221: * it exceeds our threshold. This guards against the
! 1222: * hardware oscillators resonating with external signals.
! 1223: */
! 1224: if (READ_REG(sc, SAFE_RNG_ALM_CNT) > safe_rngmaxalarm) {
! 1225: u_int32_t freq_inc, w;
! 1226:
! 1227: DPRINTF(("%s: alarm count %u exceeds threshold %u\n", __func__,
! 1228: READ_REG(sc, SAFE_RNG_ALM_CNT), safe_rngmaxalarm));
! 1229: safestats.st_rngalarm++;
! 1230: WRITE_REG(sc, SAFE_RNG_CTRL,
! 1231: READ_REG(sc, SAFE_RNG_CTRL) | SAFE_RNG_CTRL_SHORTEN);
! 1232: freq_inc = 18;
! 1233: for (i = 0; i < 64; i++) {
! 1234: w = READ_REG(sc, SAFE_RNG_CNFG);
! 1235: freq_inc = ((w + freq_inc) & 0x3fL);
! 1236: w = ((w & ~0x3fL) | freq_inc);
! 1237: WRITE_REG(sc, SAFE_RNG_CNFG, w);
! 1238:
! 1239: WRITE_REG(sc, SAFE_RNG_ALM_CNT, 0);
! 1240:
! 1241: (void) safe_rng_read(sc);
! 1242: DELAY(25);
! 1243:
! 1244: if (READ_REG(sc, SAFE_RNG_ALM_CNT) == 0) {
! 1245: WRITE_REG(sc, SAFE_RNG_CTRL,
! 1246: READ_REG(sc, SAFE_RNG_CTRL) &
! 1247: ~SAFE_RNG_CTRL_SHORTEN);
! 1248: goto retry;
! 1249: }
! 1250: freq_inc = 1;
! 1251: }
! 1252: WRITE_REG(sc, SAFE_RNG_CTRL,
! 1253: READ_REG(sc, SAFE_RNG_CTRL) & ~SAFE_RNG_CTRL_SHORTEN);
! 1254: } else
! 1255: WRITE_REG(sc, SAFE_RNG_ALM_CNT, 0);
! 1256:
! 1257: for (i = 0; i < maxwords; i++)
! 1258: add_true_randomness(buf[i]);
! 1259:
! 1260: timeout_add(&sc->sc_rngto, hz * safe_rnginterval);
! 1261: }
! 1262:
! 1263: /*
! 1264: * Allocate a new 'session' and return an encoded session id. 'sidp'
! 1265: * contains our registration id, and should contain an encoded session
! 1266: * id on successful allocation.
! 1267: */
! 1268: int
! 1269: safe_newsession(u_int32_t *sidp, struct cryptoini *cri)
! 1270: {
! 1271: struct cryptoini *c, *encini = NULL, *macini = NULL;
! 1272: struct safe_softc *sc = NULL;
! 1273: struct safe_session *ses = NULL;
! 1274: MD5_CTX md5ctx;
! 1275: SHA1_CTX sha1ctx;
! 1276: int i, sesn;
! 1277:
! 1278: if (sidp == NULL || cri == NULL)
! 1279: return (EINVAL);
! 1280: for (i = 0; i < safe_cd.cd_ndevs; i++) {
! 1281: sc = safe_cd.cd_devs[i];
! 1282: if (sc == NULL || sc->sc_cid == (*sidp))
! 1283: break;
! 1284: }
! 1285: if (sc == NULL)
! 1286: return (EINVAL);
! 1287:
! 1288: for (c = cri; c != NULL; c = c->cri_next) {
! 1289: if (c->cri_alg == CRYPTO_MD5_HMAC ||
! 1290: c->cri_alg == CRYPTO_SHA1_HMAC) {
! 1291: if (macini)
! 1292: return (EINVAL);
! 1293: macini = c;
! 1294: } else if (c->cri_alg == CRYPTO_DES_CBC ||
! 1295: c->cri_alg == CRYPTO_3DES_CBC ||
! 1296: c->cri_alg == CRYPTO_AES_CBC) {
! 1297: if (encini)
! 1298: return (EINVAL);
! 1299: encini = c;
! 1300: } else
! 1301: return (EINVAL);
! 1302: }
! 1303: if (encini == NULL && macini == NULL)
! 1304: return (EINVAL);
! 1305: if (encini) { /* validate key length */
! 1306: switch (encini->cri_alg) {
! 1307: case CRYPTO_DES_CBC:
! 1308: if (encini->cri_klen != 64)
! 1309: return (EINVAL);
! 1310: break;
! 1311: case CRYPTO_3DES_CBC:
! 1312: if (encini->cri_klen != 192)
! 1313: return (EINVAL);
! 1314: break;
! 1315: case CRYPTO_AES_CBC:
! 1316: if (encini->cri_klen != 128 &&
! 1317: encini->cri_klen != 192 &&
! 1318: encini->cri_klen != 256)
! 1319: return (EINVAL);
! 1320: break;
! 1321: }
! 1322: }
! 1323:
! 1324: if (sc->sc_sessions == NULL) {
! 1325: ses = sc->sc_sessions = (struct safe_session *)malloc(
! 1326: sizeof(struct safe_session), M_DEVBUF, M_NOWAIT);
! 1327: if (ses == NULL)
! 1328: return (ENOMEM);
! 1329: sesn = 0;
! 1330: sc->sc_nsessions = 1;
! 1331: } else {
! 1332: for (sesn = 0; sesn < sc->sc_nsessions; sesn++) {
! 1333: if (sc->sc_sessions[sesn].ses_used == 0) {
! 1334: ses = &sc->sc_sessions[sesn];
! 1335: break;
! 1336: }
! 1337: }
! 1338:
! 1339: if (ses == NULL) {
! 1340: sesn = sc->sc_nsessions;
! 1341: ses = (struct safe_session *)malloc((sesn + 1) *
! 1342: sizeof(struct safe_session), M_DEVBUF, M_NOWAIT);
! 1343: if (ses == NULL)
! 1344: return (ENOMEM);
! 1345: bcopy(sc->sc_sessions, ses, sesn *
! 1346: sizeof(struct safe_session));
! 1347: bzero(sc->sc_sessions, sesn *
! 1348: sizeof(struct safe_session));
! 1349: free(sc->sc_sessions, M_DEVBUF);
! 1350: sc->sc_sessions = ses;
! 1351: ses = &sc->sc_sessions[sesn];
! 1352: sc->sc_nsessions++;
! 1353: }
! 1354: }
! 1355:
! 1356: bzero(ses, sizeof(struct safe_session));
! 1357: ses->ses_used = 1;
! 1358:
! 1359: if (encini) {
! 1360: /* get an IV */
! 1361: get_random_bytes(ses->ses_iv, sizeof(ses->ses_iv));
! 1362:
! 1363: ses->ses_klen = encini->cri_klen;
! 1364: bcopy(encini->cri_key, ses->ses_key, ses->ses_klen / 8);
! 1365:
! 1366: for (i = 0;
! 1367: i < sizeof(ses->ses_key)/sizeof(ses->ses_key[0]); i++)
! 1368: ses->ses_key[i] = htole32(ses->ses_key[i]);
! 1369: }
! 1370:
! 1371: if (macini) {
! 1372: for (i = 0; i < macini->cri_klen / 8; i++)
! 1373: macini->cri_key[i] ^= HMAC_IPAD_VAL;
! 1374:
! 1375: if (macini->cri_alg == CRYPTO_MD5_HMAC) {
! 1376: MD5Init(&md5ctx);
! 1377: MD5Update(&md5ctx, macini->cri_key,
! 1378: macini->cri_klen / 8);
! 1379: MD5Update(&md5ctx, hmac_ipad_buffer,
! 1380: HMAC_BLOCK_LEN - (macini->cri_klen / 8));
! 1381: bcopy(md5ctx.state, ses->ses_hminner,
! 1382: sizeof(md5ctx.state));
! 1383: } else {
! 1384: SHA1Init(&sha1ctx);
! 1385: SHA1Update(&sha1ctx, macini->cri_key,
! 1386: macini->cri_klen / 8);
! 1387: SHA1Update(&sha1ctx, hmac_ipad_buffer,
! 1388: HMAC_BLOCK_LEN - (macini->cri_klen / 8));
! 1389: bcopy(sha1ctx.state, ses->ses_hminner,
! 1390: sizeof(sha1ctx.state));
! 1391: }
! 1392:
! 1393: for (i = 0; i < macini->cri_klen / 8; i++)
! 1394: macini->cri_key[i] ^= (HMAC_IPAD_VAL ^ HMAC_OPAD_VAL);
! 1395:
! 1396: if (macini->cri_alg == CRYPTO_MD5_HMAC) {
! 1397: MD5Init(&md5ctx);
! 1398: MD5Update(&md5ctx, macini->cri_key,
! 1399: macini->cri_klen / 8);
! 1400: MD5Update(&md5ctx, hmac_opad_buffer,
! 1401: HMAC_BLOCK_LEN - (macini->cri_klen / 8));
! 1402: bcopy(md5ctx.state, ses->ses_hmouter,
! 1403: sizeof(md5ctx.state));
! 1404: } else {
! 1405: SHA1Init(&sha1ctx);
! 1406: SHA1Update(&sha1ctx, macini->cri_key,
! 1407: macini->cri_klen / 8);
! 1408: SHA1Update(&sha1ctx, hmac_opad_buffer,
! 1409: HMAC_BLOCK_LEN - (macini->cri_klen / 8));
! 1410: bcopy(sha1ctx.state, ses->ses_hmouter,
! 1411: sizeof(sha1ctx.state));
! 1412: }
! 1413:
! 1414: for (i = 0; i < macini->cri_klen / 8; i++)
! 1415: macini->cri_key[i] ^= HMAC_OPAD_VAL;
! 1416:
! 1417: /* PE is little-endian, insure proper byte order */
! 1418: for (i = 0;
! 1419: i < sizeof(ses->ses_hminner)/sizeof(ses->ses_hminner[0]);
! 1420: i++) {
! 1421: ses->ses_hminner[i] = htole32(ses->ses_hminner[i]);
! 1422: ses->ses_hmouter[i] = htole32(ses->ses_hmouter[i]);
! 1423: }
! 1424: }
! 1425:
! 1426: *sidp = SAFE_SID(sc->sc_dev.dv_unit, sesn);
! 1427: return (0);
! 1428: }
! 1429:
! 1430: /*
! 1431: * Deallocate a session.
! 1432: */
! 1433: int
! 1434: safe_freesession(u_int64_t tid)
! 1435: {
! 1436: struct safe_softc *sc;
! 1437: int session, ret, card;
! 1438: u_int32_t sid = ((u_int32_t) tid) & 0xffffffff;
! 1439:
! 1440: card = SAFE_CARD(sid);
! 1441: if (card >= safe_cd.cd_ndevs || safe_cd.cd_devs[card] == NULL)
! 1442: return (EINVAL);
! 1443: sc = safe_cd.cd_devs[card];
! 1444:
! 1445: if (sc == NULL)
! 1446: return (EINVAL);
! 1447:
! 1448: session = SAFE_SESSION(sid);
! 1449: if (session < sc->sc_nsessions) {
! 1450: bzero(&sc->sc_sessions[session], sizeof(sc->sc_sessions[session]));
! 1451: ret = 0;
! 1452: } else
! 1453: ret = EINVAL;
! 1454: return (ret);
! 1455: }
! 1456:
! 1457: /*
! 1458: * Is the operand suitable aligned for direct DMA. Each
! 1459: * segment must be aligned on a 32-bit boundary and all
! 1460: * but the last segment must be a multiple of 4 bytes.
! 1461: */
! 1462: int
! 1463: safe_dmamap_aligned(const struct safe_operand *op)
! 1464: {
! 1465: int i;
! 1466:
! 1467: for (i = 0; i < op->map->dm_nsegs; i++) {
! 1468: if (op->map->dm_segs[i].ds_addr & 3)
! 1469: return (0);
! 1470: if (i != (op->map->dm_nsegs - 1) &&
! 1471: (op->map->dm_segs[i].ds_len & 3))
! 1472: return (0);
! 1473: }
! 1474: return (1);
! 1475: }
! 1476:
! 1477: /*
! 1478: * Clean up after a chip crash.
! 1479: * It is assumed that the caller in splnet()
! 1480: */
! 1481: void
! 1482: safe_cleanchip(struct safe_softc *sc)
! 1483: {
! 1484:
! 1485: if (sc->sc_nqchip != 0) {
! 1486: struct safe_ringentry *re = sc->sc_back;
! 1487:
! 1488: while (re != sc->sc_front) {
! 1489: if (re->re_desc.d_csr != 0)
! 1490: safe_free_entry(sc, re);
! 1491: if (++re == sc->sc_ringtop)
! 1492: re = sc->sc_ring;
! 1493: }
! 1494: sc->sc_back = re;
! 1495: sc->sc_nqchip = 0;
! 1496: }
! 1497: }
! 1498:
! 1499: /*
! 1500: * free a safe_q
! 1501: * It is assumed that the caller is within splnet().
! 1502: */
! 1503: int
! 1504: safe_free_entry(struct safe_softc *sc, struct safe_ringentry *re)
! 1505: {
! 1506: struct cryptop *crp;
! 1507:
! 1508: /*
! 1509: * Free header MCR
! 1510: */
! 1511: if ((re->re_dst_m != NULL) && (re->re_src_m != re->re_dst_m))
! 1512: m_freem(re->re_dst_m);
! 1513:
! 1514: crp = (struct cryptop *)re->re_crp;
! 1515:
! 1516: re->re_desc.d_csr = 0;
! 1517:
! 1518: crp->crp_etype = EFAULT;
! 1519: crypto_done(crp);
! 1520: return (0);
! 1521: }
! 1522:
! 1523: /*
! 1524: * safe_feed() - post a request to chip
! 1525: */
! 1526: void
! 1527: safe_feed(struct safe_softc *sc, struct safe_ringentry *re)
! 1528: {
! 1529: bus_dmamap_sync(sc->sc_dmat, re->re_src_map,
! 1530: 0, re->re_src_map->dm_mapsize, BUS_DMASYNC_PREWRITE);
! 1531: if (re->re_dst_map != NULL)
! 1532: bus_dmamap_sync(sc->sc_dmat, re->re_dst_map, 0,
! 1533: re->re_dst_map->dm_mapsize, BUS_DMASYNC_PREREAD);
! 1534: /* XXX have no smaller granularity */
! 1535: safe_dma_sync(sc, &sc->sc_ringalloc,
! 1536: BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE);
! 1537: safe_dma_sync(sc, &sc->sc_spalloc, BUS_DMASYNC_PREWRITE);
! 1538: safe_dma_sync(sc, &sc->sc_dpalloc, BUS_DMASYNC_PREWRITE);
! 1539:
! 1540: #ifdef SAFE_DEBUG
! 1541: if (safe_debug) {
! 1542: safe_dump_ringstate(sc, __func__);
! 1543: safe_dump_request(sc, __func__, re);
! 1544: }
! 1545: #endif
! 1546: sc->sc_nqchip++;
! 1547: if (sc->sc_nqchip > safestats.st_maxqchip)
! 1548: safestats.st_maxqchip = sc->sc_nqchip;
! 1549: /* poke h/w to check descriptor ring, any value can be written */
! 1550: WRITE_REG(sc, SAFE_HI_RD_DESCR, 0);
! 1551: }
! 1552:
! 1553: /*
! 1554: * Is the operand suitable for direct DMA as the destination
! 1555: * of an operation. The hardware requires that each ``particle''
! 1556: * but the last in an operation result have the same size. We
! 1557: * fix that size at SAFE_MAX_DSIZE bytes. This routine returns
! 1558: * 0 if some segment is not a multiple of this size, 1 if all
! 1559: * segments are exactly this size, or 2 if segments are at worst
! 1560: * a multple of this size.
! 1561: */
! 1562: int
! 1563: safe_dmamap_uniform(const struct safe_operand *op)
! 1564: {
! 1565: int result = 1, i;
! 1566:
! 1567: if (op->map->dm_nsegs <= 0)
! 1568: return (result);
! 1569:
! 1570: for (i = 0; i < op->map->dm_nsegs-1; i++) {
! 1571: if (op->map->dm_segs[i].ds_len % SAFE_MAX_DSIZE)
! 1572: return (0);
! 1573: if (op->map->dm_segs[i].ds_len != SAFE_MAX_DSIZE)
! 1574: result = 2;
! 1575: }
! 1576: return (result);
! 1577: }
! 1578:
! 1579: /*
! 1580: * Copy all data past offset from srcm to dstm.
! 1581: */
! 1582: void
! 1583: safe_mcopy(struct mbuf *srcm, struct mbuf *dstm, u_int offset)
! 1584: {
! 1585: u_int j, dlen, slen;
! 1586: caddr_t dptr, sptr;
! 1587:
! 1588: /*
! 1589: * Advance src and dst to offset.
! 1590: */
! 1591: for (j = offset; srcm->m_len <= j;) {
! 1592: j -= srcm->m_len;
! 1593: srcm = srcm->m_next;
! 1594: if (srcm == NULL)
! 1595: return;
! 1596: }
! 1597: sptr = mtod(srcm, caddr_t) + j;
! 1598: slen = srcm->m_len - j;
! 1599:
! 1600: for (j = offset; dstm->m_len <= j;) {
! 1601: j -= dstm->m_len;
! 1602: dstm = dstm->m_next;
! 1603: if (dstm == NULL)
! 1604: return;
! 1605: }
! 1606: dptr = mtod(dstm, caddr_t) + j;
! 1607: dlen = dstm->m_len - j;
! 1608:
! 1609: /*
! 1610: * Copy everything that remains.
! 1611: */
! 1612: for (;;) {
! 1613: j = min(slen, dlen);
! 1614: bcopy(sptr, dptr, j);
! 1615: if (slen == j) {
! 1616: srcm = srcm->m_next;
! 1617: if (srcm == NULL)
! 1618: return;
! 1619: sptr = srcm->m_data;
! 1620: slen = srcm->m_len;
! 1621: } else
! 1622: sptr += j, slen -= j;
! 1623: if (dlen == j) {
! 1624: dstm = dstm->m_next;
! 1625: if (dstm == NULL)
! 1626: return;
! 1627: dptr = dstm->m_data;
! 1628: dlen = dstm->m_len;
! 1629: } else
! 1630: dptr += j, dlen -= j;
! 1631: }
! 1632: }
! 1633:
! 1634: void
! 1635: safe_callback(struct safe_softc *sc, struct safe_ringentry *re)
! 1636: {
! 1637: struct cryptop *crp = (struct cryptop *)re->re_crp;
! 1638: struct cryptodesc *crd;
! 1639:
! 1640: safestats.st_opackets++;
! 1641: safestats.st_obytes += (re->re_dst_map == NULL) ?
! 1642: re->re_src_mapsize : re->re_dst_mapsize;
! 1643:
! 1644: safe_dma_sync(sc, &sc->sc_ringalloc,
! 1645: BUS_DMASYNC_POSTREAD|BUS_DMASYNC_POSTWRITE);
! 1646: if (re->re_desc.d_csr & SAFE_PE_CSR_STATUS) {
! 1647: printf("%s: csr 0x%x cmd0 0x%x cmd1 0x%x\n",
! 1648: sc->sc_dev.dv_xname, re->re_desc.d_csr,
! 1649: re->re_sa.sa_cmd0, re->re_sa.sa_cmd1);
! 1650: safestats.st_peoperr++;
! 1651: crp->crp_etype = EIO; /* something more meaningful? */
! 1652: }
! 1653: if (re->re_dst_map != NULL && re->re_dst_map != re->re_src_map) {
! 1654: bus_dmamap_sync(sc->sc_dmat, re->re_dst_map, 0,
! 1655: re->re_dst_map->dm_mapsize, BUS_DMASYNC_POSTREAD);
! 1656: bus_dmamap_unload(sc->sc_dmat, re->re_dst_map);
! 1657: bus_dmamap_destroy(sc->sc_dmat, re->re_dst_map);
! 1658: }
! 1659: bus_dmamap_sync(sc->sc_dmat, re->re_src_map, 0,
! 1660: re->re_src_map->dm_mapsize, BUS_DMASYNC_POSTWRITE);
! 1661: bus_dmamap_unload(sc->sc_dmat, re->re_src_map);
! 1662: bus_dmamap_destroy(sc->sc_dmat, re->re_src_map);
! 1663:
! 1664: /*
! 1665: * If result was written to a different mbuf chain, swap
! 1666: * it in as the return value and reclaim the original.
! 1667: */
! 1668: if ((crp->crp_flags & CRYPTO_F_IMBUF) && re->re_src_m != re->re_dst_m) {
! 1669: m_freem(re->re_src_m);
! 1670: crp->crp_buf = (caddr_t)re->re_dst_m;
! 1671: }
! 1672:
! 1673: if (re->re_flags & SAFE_QFLAGS_COPYOUTIV) {
! 1674: /* copy out IV for future use */
! 1675: for (crd = crp->crp_desc; crd; crd = crd->crd_next) {
! 1676: int ivsize;
! 1677:
! 1678: if (crd->crd_alg == CRYPTO_DES_CBC ||
! 1679: crd->crd_alg == CRYPTO_3DES_CBC) {
! 1680: ivsize = 2*sizeof(u_int32_t);
! 1681: } else if (crd->crd_alg == CRYPTO_AES_CBC) {
! 1682: ivsize = 4*sizeof(u_int32_t);
! 1683: } else
! 1684: continue;
! 1685: if (crp->crp_flags & CRYPTO_F_IMBUF) {
! 1686: m_copydata((struct mbuf *)crp->crp_buf,
! 1687: crd->crd_skip + crd->crd_len - ivsize,
! 1688: ivsize,
! 1689: (caddr_t) sc->sc_sessions[re->re_sesn].ses_iv);
! 1690: } else if (crp->crp_flags & CRYPTO_F_IOV) {
! 1691: cuio_copydata((struct uio *)crp->crp_buf,
! 1692: crd->crd_skip + crd->crd_len - ivsize,
! 1693: ivsize,
! 1694: (caddr_t)sc->sc_sessions[re->re_sesn].ses_iv);
! 1695: }
! 1696: break;
! 1697: }
! 1698: }
! 1699:
! 1700: if (re->re_flags & SAFE_QFLAGS_COPYOUTICV) {
! 1701: /* copy out ICV result */
! 1702: for (crd = crp->crp_desc; crd; crd = crd->crd_next) {
! 1703: if (!(crd->crd_alg == CRYPTO_MD5_HMAC ||
! 1704: crd->crd_alg == CRYPTO_SHA1_HMAC))
! 1705: continue;
! 1706: if (crd->crd_alg == CRYPTO_SHA1_HMAC) {
! 1707: /*
! 1708: * SHA-1 ICV's are byte-swapped; fix 'em up
! 1709: * before copy them to their destination.
! 1710: */
! 1711: bswap32(re->re_sastate.sa_saved_indigest[0]);
! 1712: bswap32(re->re_sastate.sa_saved_indigest[1]);
! 1713: bswap32(re->re_sastate.sa_saved_indigest[2]);
! 1714: }
! 1715: if (crp->crp_flags & CRYPTO_F_IMBUF) {
! 1716: m_copyback((struct mbuf *)crp->crp_buf,
! 1717: crd->crd_inject, 12,
! 1718: (caddr_t)re->re_sastate.sa_saved_indigest);
! 1719: } else if (crp->crp_flags & CRYPTO_F_IOV && crp->crp_mac) {
! 1720: bcopy((caddr_t)re->re_sastate.sa_saved_indigest,
! 1721: crp->crp_mac, 12);
! 1722: }
! 1723: break;
! 1724: }
! 1725: }
! 1726:
! 1727: crypto_done(crp);
! 1728: }
! 1729:
! 1730: /*
! 1731: * SafeXcel Interrupt routine
! 1732: */
! 1733: int
! 1734: safe_intr(void *arg)
! 1735: {
! 1736: struct safe_softc *sc = arg;
! 1737: volatile u_int32_t stat;
! 1738:
! 1739: stat = READ_REG(sc, SAFE_HM_STAT);
! 1740: if (stat == 0) /* shared irq, not for us */
! 1741: return (0);
! 1742:
! 1743: WRITE_REG(sc, SAFE_HI_CLR, stat); /* IACK */
! 1744:
! 1745: if ((stat & SAFE_INT_PE_DDONE)) {
! 1746: /*
! 1747: * Descriptor(s) done; scan the ring and
! 1748: * process completed operations.
! 1749: */
! 1750: while (sc->sc_back != sc->sc_front) {
! 1751: struct safe_ringentry *re = sc->sc_back;
! 1752: #ifdef SAFE_DEBUG
! 1753: if (safe_debug) {
! 1754: safe_dump_ringstate(sc, __func__);
! 1755: safe_dump_request(sc, __func__, re);
! 1756: }
! 1757: #endif
! 1758: /*
! 1759: * safe_process marks ring entries that were allocated
! 1760: * but not used with a csr of zero. This insures the
! 1761: * ring front pointer never needs to be set backwards
! 1762: * in the event that an entry is allocated but not used
! 1763: * because of a setup error.
! 1764: */
! 1765: if (re->re_desc.d_csr != 0) {
! 1766: if (!SAFE_PE_CSR_IS_DONE(re->re_desc.d_csr))
! 1767: break;
! 1768: if (!SAFE_PE_LEN_IS_DONE(re->re_desc.d_len))
! 1769: break;
! 1770: sc->sc_nqchip--;
! 1771: safe_callback(sc, re);
! 1772: }
! 1773: if (++(sc->sc_back) == sc->sc_ringtop)
! 1774: sc->sc_back = sc->sc_ring;
! 1775: }
! 1776: }
! 1777:
! 1778: return (1);
! 1779: }
! 1780:
! 1781: struct safe_softc *
! 1782: safe_kfind(struct cryptkop *krp)
! 1783: {
! 1784: struct safe_softc *sc;
! 1785: int i;
! 1786:
! 1787: for (i = 0; i < safe_cd.cd_ndevs; i++) {
! 1788: sc = safe_cd.cd_devs[i];
! 1789: if (sc == NULL)
! 1790: continue;
! 1791: if (sc->sc_cid == krp->krp_hid)
! 1792: return (sc);
! 1793: }
! 1794: return (NULL);
! 1795: }
! 1796:
! 1797: int
! 1798: safe_kprocess(struct cryptkop *krp)
! 1799: {
! 1800: struct safe_softc *sc;
! 1801: struct safe_pkq *q;
! 1802: int s;
! 1803:
! 1804: if ((sc = safe_kfind(krp)) == NULL) {
! 1805: krp->krp_status = EINVAL;
! 1806: goto err;
! 1807: }
! 1808:
! 1809: if (krp->krp_op != CRK_MOD_EXP) {
! 1810: krp->krp_status = EOPNOTSUPP;
! 1811: goto err;
! 1812: }
! 1813:
! 1814: q = (struct safe_pkq *)malloc(sizeof(*q), M_DEVBUF, M_NOWAIT);
! 1815: if (q == NULL) {
! 1816: krp->krp_status = ENOMEM;
! 1817: goto err;
! 1818: }
! 1819: q->pkq_krp = krp;
! 1820:
! 1821: s = splnet();
! 1822: SIMPLEQ_INSERT_TAIL(&sc->sc_pkq, q, pkq_next);
! 1823: safe_kfeed(sc);
! 1824: splx(s);
! 1825: return (0);
! 1826:
! 1827: err:
! 1828: crypto_kdone(krp);
! 1829: return (0);
! 1830: }
! 1831:
! 1832: #define SAFE_CRK_PARAM_BASE 0
! 1833: #define SAFE_CRK_PARAM_EXP 1
! 1834: #define SAFE_CRK_PARAM_MOD 2
! 1835:
! 1836: int
! 1837: safe_kstart(struct safe_softc *sc)
! 1838: {
! 1839: struct cryptkop *krp = sc->sc_pkq_cur->pkq_krp;
! 1840: int exp_bits, mod_bits, base_bits;
! 1841: u_int32_t op, a_off, b_off, c_off, d_off;
! 1842:
! 1843: if (krp->krp_iparams < 3 || krp->krp_oparams != 1) {
! 1844: krp->krp_status = EINVAL;
! 1845: return (1);
! 1846: }
! 1847:
! 1848: base_bits = safe_ksigbits(&krp->krp_param[SAFE_CRK_PARAM_BASE]);
! 1849: if (base_bits > 2048)
! 1850: goto too_big;
! 1851: if (base_bits <= 0) /* 5. base not zero */
! 1852: goto too_small;
! 1853:
! 1854: exp_bits = safe_ksigbits(&krp->krp_param[SAFE_CRK_PARAM_EXP]);
! 1855: if (exp_bits > 2048)
! 1856: goto too_big;
! 1857: if (exp_bits <= 0) /* 1. exponent word length > 0 */
! 1858: goto too_small; /* 4. exponent not zero */
! 1859:
! 1860: mod_bits = safe_ksigbits(&krp->krp_param[SAFE_CRK_PARAM_MOD]);
! 1861: if (mod_bits > 2048)
! 1862: goto too_big;
! 1863: if (mod_bits <= 32) /* 2. modulus word length > 1 */
! 1864: goto too_small; /* 8. MSW of modulus != zero */
! 1865: if (mod_bits < exp_bits) /* 3 modulus len >= exponent len */
! 1866: goto too_small;
! 1867: if ((krp->krp_param[SAFE_CRK_PARAM_MOD].crp_p[0] & 1) == 0)
! 1868: goto bad_domain; /* 6. modulus is odd */
! 1869: if (mod_bits > krp->krp_param[krp->krp_iparams].crp_nbits)
! 1870: goto too_small; /* make sure result will fit */
! 1871:
! 1872: /* 7. modulus > base */
! 1873: if (mod_bits < base_bits)
! 1874: goto too_small;
! 1875: if (mod_bits == base_bits) {
! 1876: u_int8_t *basep, *modp;
! 1877: int i;
! 1878:
! 1879: basep = krp->krp_param[SAFE_CRK_PARAM_BASE].crp_p +
! 1880: ((base_bits + 7) / 8) - 1;
! 1881: modp = krp->krp_param[SAFE_CRK_PARAM_MOD].crp_p +
! 1882: ((mod_bits + 7) / 8) - 1;
! 1883:
! 1884: for (i = 0; i < (mod_bits + 7) / 8; i++, basep--, modp--) {
! 1885: if (*modp < *basep)
! 1886: goto too_small;
! 1887: if (*modp > *basep)
! 1888: break;
! 1889: }
! 1890: }
! 1891:
! 1892: /* And on the 9th step, he rested. */
! 1893:
! 1894: WRITE_REG(sc, SAFE_PK_A_LEN, (exp_bits + 31) / 32);
! 1895: WRITE_REG(sc, SAFE_PK_B_LEN, (mod_bits + 31) / 32);
! 1896: if (mod_bits > 1024) {
! 1897: op = SAFE_PK_FUNC_EXP4;
! 1898: a_off = 0x000;
! 1899: b_off = 0x100;
! 1900: c_off = 0x200;
! 1901: d_off = 0x300;
! 1902: } else {
! 1903: op = SAFE_PK_FUNC_EXP16;
! 1904: a_off = 0x000;
! 1905: b_off = 0x080;
! 1906: c_off = 0x100;
! 1907: d_off = 0x180;
! 1908: }
! 1909: sc->sc_pk_reslen = b_off - a_off;
! 1910: sc->sc_pk_resoff = d_off;
! 1911:
! 1912: /* A is exponent, B is modulus, C is base, D is result */
! 1913: safe_kload_reg(sc, a_off, b_off - a_off,
! 1914: &krp->krp_param[SAFE_CRK_PARAM_EXP]);
! 1915: WRITE_REG(sc, SAFE_PK_A_ADDR, a_off >> 2);
! 1916: safe_kload_reg(sc, b_off, b_off - a_off,
! 1917: &krp->krp_param[SAFE_CRK_PARAM_MOD]);
! 1918: WRITE_REG(sc, SAFE_PK_B_ADDR, b_off >> 2);
! 1919: safe_kload_reg(sc, c_off, b_off - a_off,
! 1920: &krp->krp_param[SAFE_CRK_PARAM_BASE]);
! 1921: WRITE_REG(sc, SAFE_PK_C_ADDR, c_off >> 2);
! 1922: WRITE_REG(sc, SAFE_PK_D_ADDR, d_off >> 2);
! 1923:
! 1924: WRITE_REG(sc, SAFE_PK_FUNC, op | SAFE_PK_FUNC_RUN);
! 1925:
! 1926: return (0);
! 1927:
! 1928: too_big:
! 1929: krp->krp_status = E2BIG;
! 1930: return (1);
! 1931: too_small:
! 1932: krp->krp_status = ERANGE;
! 1933: return (1);
! 1934: bad_domain:
! 1935: krp->krp_status = EDOM;
! 1936: return (1);
! 1937: }
! 1938:
! 1939: int
! 1940: safe_ksigbits(struct crparam *cr)
! 1941: {
! 1942: u_int plen = (cr->crp_nbits + 7) / 8;
! 1943: int i, sig = plen * 8;
! 1944: u_int8_t c, *p = cr->crp_p;
! 1945:
! 1946: for (i = plen - 1; i >= 0; i--) {
! 1947: c = p[i];
! 1948: if (c != 0) {
! 1949: while ((c & 0x80) == 0) {
! 1950: sig--;
! 1951: c <<= 1;
! 1952: }
! 1953: break;
! 1954: }
! 1955: sig -= 8;
! 1956: }
! 1957: return (sig);
! 1958: }
! 1959:
! 1960: void
! 1961: safe_kfeed(struct safe_softc *sc)
! 1962: {
! 1963: if (SIMPLEQ_EMPTY(&sc->sc_pkq) && sc->sc_pkq_cur == NULL)
! 1964: return;
! 1965: if (sc->sc_pkq_cur != NULL)
! 1966: return;
! 1967: while (!SIMPLEQ_EMPTY(&sc->sc_pkq)) {
! 1968: struct safe_pkq *q = SIMPLEQ_FIRST(&sc->sc_pkq);
! 1969:
! 1970: sc->sc_pkq_cur = q;
! 1971: SIMPLEQ_REMOVE_HEAD(&sc->sc_pkq, pkq_next);
! 1972: if (safe_kstart(sc) != 0) {
! 1973: crypto_kdone(q->pkq_krp);
! 1974: free(q, M_DEVBUF);
! 1975: sc->sc_pkq_cur = NULL;
! 1976: } else {
! 1977: /* op started, start polling */
! 1978: timeout_add(&sc->sc_pkto, 1);
! 1979: break;
! 1980: }
! 1981: }
! 1982: }
! 1983:
! 1984: void
! 1985: safe_kpoll(void *vsc)
! 1986: {
! 1987: struct safe_softc *sc = vsc;
! 1988: struct safe_pkq *q;
! 1989: struct crparam *res;
! 1990: int s, i;
! 1991: u_int32_t buf[64];
! 1992:
! 1993: s = splnet();
! 1994: if (sc->sc_pkq_cur == NULL)
! 1995: goto out;
! 1996: if (READ_REG(sc, SAFE_PK_FUNC) & SAFE_PK_FUNC_RUN) {
! 1997: /* still running, check back later */
! 1998: timeout_add(&sc->sc_pkto, 1);
! 1999: goto out;
! 2000: }
! 2001:
! 2002: q = sc->sc_pkq_cur;
! 2003: res = &q->pkq_krp->krp_param[q->pkq_krp->krp_iparams];
! 2004: bzero(buf, sizeof(buf));
! 2005: bzero(res->crp_p, (res->crp_nbits + 7) / 8);
! 2006: for (i = 0; i < sc->sc_pk_reslen >> 2; i++)
! 2007: buf[i] = letoh32(READ_REG(sc, SAFE_PK_RAM_START +
! 2008: sc->sc_pk_resoff + (i << 2)));
! 2009: bcopy(buf, res->crp_p, (res->crp_nbits + 7) / 8);
! 2010: res->crp_nbits = sc->sc_pk_reslen * 8;
! 2011: res->crp_nbits = safe_ksigbits(res);
! 2012:
! 2013: for (i = SAFE_PK_RAM_START; i < SAFE_PK_RAM_END; i += 4)
! 2014: WRITE_REG(sc, i, 0);
! 2015:
! 2016: crypto_kdone(q->pkq_krp);
! 2017: free(q, M_DEVBUF);
! 2018: sc->sc_pkq_cur = NULL;
! 2019:
! 2020: safe_kfeed(sc);
! 2021: out:
! 2022: splx(s);
! 2023: }
! 2024:
! 2025: void
! 2026: safe_kload_reg(struct safe_softc *sc, u_int32_t off, u_int32_t len,
! 2027: struct crparam *n)
! 2028: {
! 2029: u_int32_t buf[64], i;
! 2030:
! 2031: bzero(buf, sizeof(buf));
! 2032: bcopy(n->crp_p, buf, (n->crp_nbits + 7) / 8);
! 2033:
! 2034: for (i = 0; i < len >> 2; i++)
! 2035: WRITE_REG(sc, SAFE_PK_RAM_START + off + (i << 2),
! 2036: htole32(buf[i]));
! 2037: }
! 2038:
! 2039: #ifdef SAFE_DEBUG
! 2040:
! 2041: void
! 2042: safe_dump_dmastatus(struct safe_softc *sc, const char *tag)
! 2043: {
! 2044: printf("%s: ENDIAN 0x%x SRC 0x%x DST 0x%x STAT 0x%x\n", tag,
! 2045: READ_REG(sc, SAFE_DMA_ENDIAN), READ_REG(sc, SAFE_DMA_SRCADDR),
! 2046: READ_REG(sc, SAFE_DMA_DSTADDR), READ_REG(sc, SAFE_DMA_STAT));
! 2047: }
! 2048:
! 2049: void
! 2050: safe_dump_intrstate(struct safe_softc *sc, const char *tag)
! 2051: {
! 2052: printf("%s: HI_CFG 0x%x HI_MASK 0x%x HI_DESC_CNT 0x%x HU_STAT 0x%x HM_STAT 0x%x\n",
! 2053: tag, READ_REG(sc, SAFE_HI_CFG), READ_REG(sc, SAFE_HI_MASK),
! 2054: READ_REG(sc, SAFE_HI_DESC_CNT), READ_REG(sc, SAFE_HU_STAT),
! 2055: READ_REG(sc, SAFE_HM_STAT));
! 2056: }
! 2057:
! 2058: void
! 2059: safe_dump_ringstate(struct safe_softc *sc, const char *tag)
! 2060: {
! 2061: u_int32_t estat = READ_REG(sc, SAFE_PE_ERNGSTAT);
! 2062:
! 2063: /* NB: assume caller has lock on ring */
! 2064: printf("%s: ERNGSTAT %x (next %u) back %u front %u\n",
! 2065: tag, estat, (estat >> SAFE_PE_ERNGSTAT_NEXT_S),
! 2066: sc->sc_back - sc->sc_ring, sc->sc_front - sc->sc_ring);
! 2067: }
! 2068:
! 2069: void
! 2070: safe_dump_request(struct safe_softc *sc, const char* tag, struct safe_ringentry *re)
! 2071: {
! 2072: int ix, nsegs;
! 2073:
! 2074: ix = re - sc->sc_ring;
! 2075: printf("%s: %p (%u): csr %x src %x dst %x sa %x len %x\n", tag,
! 2076: re, ix, re->re_desc.d_csr, re->re_desc.d_src, re->re_desc.d_dst,
! 2077: re->re_desc.d_sa, re->re_desc.d_len);
! 2078: if (re->re_src_nsegs > 1) {
! 2079: ix = (re->re_desc.d_src - sc->sc_spalloc.dma_paddr) /
! 2080: sizeof(struct safe_pdesc);
! 2081: for (nsegs = re->re_src_nsegs; nsegs; nsegs--) {
! 2082: printf(" spd[%u] %p: %p", ix,
! 2083: &sc->sc_spring[ix],
! 2084: (caddr_t)sc->sc_spring[ix].pd_addr);
! 2085: printf("\n");
! 2086: if (++ix == SAFE_TOTAL_SPART)
! 2087: ix = 0;
! 2088: }
! 2089: }
! 2090: if (re->re_dst_nsegs > 1) {
! 2091: ix = (re->re_desc.d_dst - sc->sc_dpalloc.dma_paddr) /
! 2092: sizeof(struct safe_pdesc);
! 2093: for (nsegs = re->re_dst_nsegs; nsegs; nsegs--) {
! 2094: printf(" dpd[%u] %p: %p\n", ix,
! 2095: &sc->sc_dpring[ix],
! 2096: (caddr_t) sc->sc_dpring[ix].pd_addr);
! 2097: if (++ix == SAFE_TOTAL_DPART)
! 2098: ix = 0;
! 2099: }
! 2100: }
! 2101: printf("sa: cmd0 %08x cmd1 %08x staterec %x\n",
! 2102: re->re_sa.sa_cmd0, re->re_sa.sa_cmd1, re->re_sa.sa_staterec);
! 2103: printf("sa: key %x %x %x %x %x %x %x %x\n", re->re_sa.sa_key[0],
! 2104: re->re_sa.sa_key[1], re->re_sa.sa_key[2], re->re_sa.sa_key[3],
! 2105: re->re_sa.sa_key[4], re->re_sa.sa_key[5], re->re_sa.sa_key[6],
! 2106: re->re_sa.sa_key[7]);
! 2107: printf("sa: indigest %x %x %x %x %x\n", re->re_sa.sa_indigest[0],
! 2108: re->re_sa.sa_indigest[1], re->re_sa.sa_indigest[2],
! 2109: re->re_sa.sa_indigest[3], re->re_sa.sa_indigest[4]);
! 2110: printf("sa: outdigest %x %x %x %x %x\n", re->re_sa.sa_outdigest[0],
! 2111: re->re_sa.sa_outdigest[1], re->re_sa.sa_outdigest[2],
! 2112: re->re_sa.sa_outdigest[3], re->re_sa.sa_outdigest[4]);
! 2113: printf("sr: iv %x %x %x %x\n",
! 2114: re->re_sastate.sa_saved_iv[0], re->re_sastate.sa_saved_iv[1],
! 2115: re->re_sastate.sa_saved_iv[2], re->re_sastate.sa_saved_iv[3]);
! 2116: printf("sr: hashbc %u indigest %x %x %x %x %x\n",
! 2117: re->re_sastate.sa_saved_hashbc,
! 2118: re->re_sastate.sa_saved_indigest[0],
! 2119: re->re_sastate.sa_saved_indigest[1],
! 2120: re->re_sastate.sa_saved_indigest[2],
! 2121: re->re_sastate.sa_saved_indigest[3],
! 2122: re->re_sastate.sa_saved_indigest[4]);
! 2123: }
! 2124:
! 2125: void
! 2126: safe_dump_ring(struct safe_softc *sc, const char *tag)
! 2127: {
! 2128: printf("\nSafeNet Ring State:\n");
! 2129: safe_dump_intrstate(sc, tag);
! 2130: safe_dump_dmastatus(sc, tag);
! 2131: safe_dump_ringstate(sc, tag);
! 2132: if (sc->sc_nqchip) {
! 2133: struct safe_ringentry *re = sc->sc_back;
! 2134: do {
! 2135: safe_dump_request(sc, tag, re);
! 2136: if (++re == sc->sc_ringtop)
! 2137: re = sc->sc_ring;
! 2138: } while (re != sc->sc_front);
! 2139: }
! 2140: }
! 2141:
! 2142: #endif /* SAFE_DEBUG */
CVSweb