Annotation of sys/dev/pci/ises.c, Revision 1.1
1.1 ! nbrk 1: /* $OpenBSD: ises.c,v 1.31 2006/06/29 21:34:51 deraadt Exp $ */
! 2:
! 3: /*
! 4: * Copyright (c) 2000, 2001 Håkan Olsson (ho@crt.se)
! 5: * All rights reserved.
! 6: *
! 7: * Redistribution and use in source and binary forms, with or without
! 8: * modification, are permitted provided that the following conditions
! 9: * are met:
! 10: * 1. Redistributions of source code must retain the above copyright
! 11: * notice, this list of conditions and the following disclaimer.
! 12: * 2. Redistributions in binary form must reproduce the above copyright
! 13: * notice, this list of conditions and the following disclaimer in the
! 14: * documentation and/or other materials provided with the distribution.
! 15: *
! 16: * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
! 17: * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
! 18: * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
! 19: * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
! 20: * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
! 21: * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
! 22: * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
! 23: * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
! 24: * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
! 25: * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
! 26: * POSSIBILITY OF SUCH DAMAGE.
! 27: */
! 28:
! 29: /*
! 30: * PCC-ISES hardware crypto accelerator
! 31: */
! 32:
! 33: #include <sys/param.h>
! 34: #include <sys/systm.h>
! 35: #include <sys/proc.h>
! 36: #include <sys/errno.h>
! 37: #include <sys/malloc.h>
! 38: #include <sys/kernel.h>
! 39: #include <sys/mbuf.h>
! 40: #include <sys/timeout.h>
! 41: #include <sys/device.h>
! 42: #include <sys/queue.h>
! 43:
! 44: #include <crypto/cryptodev.h>
! 45: #include <crypto/cryptosoft.h>
! 46: #include <dev/rndvar.h>
! 47: #include <crypto/md5.h>
! 48: #include <crypto/sha1.h>
! 49: #include <crypto/rmd160.h>
! 50:
! 51: #include <dev/pci/pcireg.h>
! 52: #include <dev/pci/pcivar.h>
! 53: #include <dev/pci/pcidevs.h>
! 54:
! 55: #include <dev/pci/isesreg.h>
! 56: #include <dev/pci/isesvar.h>
! 57: #include <dev/microcode/ises/ises_fw.h>
! 58:
! 59: /*
! 60: * Prototypes and count for the pci_device structure
! 61: */
! 62: int ises_match(struct device *, void *, void *);
! 63: void ises_attach(struct device *, struct device *, void *);
! 64:
! 65: void ises_initstate(void *);
! 66: void ises_hrng_init(struct ises_softc *);
! 67: void ises_hrng(void *);
! 68: void ises_process_oqueue(struct ises_softc *);
! 69: int ises_queue_cmd(struct ises_softc *, u_int32_t, u_int32_t *,
! 70: u_int32_t (*)(struct ises_softc *, struct ises_cmd *));
! 71: u_int32_t ises_get_fwversion(struct ises_softc *);
! 72: int ises_assert_cmd_mode(struct ises_softc *);
! 73:
! 74: int ises_intr(void *);
! 75: int ises_newsession(u_int32_t *, struct cryptoini *);
! 76: int ises_freesession(u_int64_t);
! 77: int ises_process(struct cryptop *);
! 78: void ises_callback(struct ises_q *);
! 79: int ises_feed(struct ises_softc *);
! 80: int ises_bchu_switch_session(struct ises_softc *,
! 81: struct ises_session *, int);
! 82: u_int32_t ises_bchu_switch_final(struct ises_softc *, struct ises_cmd *);
! 83:
! 84: void ises_read_dma(struct ises_softc *);
! 85:
! 86: #define READ_REG(sc,r) \
! 87: bus_space_read_4((sc)->sc_memt, (sc)->sc_memh,r)
! 88:
! 89: #define WRITE_REG(sc,reg,val) \
! 90: bus_space_write_4((sc)->sc_memt, (sc)->sc_memh, reg, val)
! 91:
! 92: /* XXX This should probably be (x) = htole32((x)) */
! 93: #define SWAP32(x) ((x) = swap32((x)))
! 94:
! 95: #ifdef ISESDEBUG
! 96: # define DPRINTF(x) printf x
! 97: #else
! 98: # define DPRINTF(x)
! 99: #endif
! 100:
! 101: #ifdef ISESDEBUG
! 102: void ises_debug_init(struct ises_softc *);
! 103: void ises_debug_2(void);
! 104: void ises_debug_loop(void *);
! 105: void ises_showreg(void);
! 106: void ises_debug_parse_omr(struct ises_softc *);
! 107: void ises_debug_simple_cmd(struct ises_softc *, u_int32_t, u_int32_t);
! 108: struct ises_softc *ises_sc;
! 109: struct timeout ises_db_timeout;
! 110: int ises_db;
! 111: #endif
! 112:
! 113: /* For HRNG entropy collection, these values gather 1600 bytes/s */
! 114: #ifndef ISESRNGBITS
! 115: #define ISESRNGBITS 128 /* Bits per iteration (mult. of 32) */
! 116: #define ISESRNGIPS 100 /* Iterations per second */
! 117: #endif
! 118:
! 119: /* XXX Disable HRNG while debugging. */
! 120: #define ISES_HRNG_DISABLED
! 121:
! 122: /* Maximum number of times we try to download the firmware. */
! 123: #define ISES_MAX_DOWNLOAD_RETRIES 3
! 124:
! 125: struct cfattach ises_ca = {
! 126: sizeof(struct ises_softc), ises_match, ises_attach,
! 127: };
! 128:
! 129: struct cfdriver ises_cd = {
! 130: 0, "ises", DV_DULL
! 131: };
! 132:
! 133: struct ises_stats {
! 134: u_int64_t ibytes;
! 135: u_int64_t obytes;
! 136: u_int32_t ipkts;
! 137: u_int32_t opkts;
! 138: u_int32_t invalid;
! 139: u_int32_t nomem;
! 140: } isesstats;
! 141:
! 142: int
! 143: ises_match(struct device *parent, void *match, void *aux)
! 144: {
! 145: struct pci_attach_args *pa = (struct pci_attach_args *)aux;
! 146:
! 147: if (PCI_VENDOR(pa->pa_id) == PCI_VENDOR_PIJNENBURG &&
! 148: PCI_PRODUCT(pa->pa_id) == PCI_PRODUCT_PIJNENBURG_PCC_ISES)
! 149: return (1);
! 150:
! 151: return (0);
! 152: }
! 153:
! 154: void
! 155: ises_attach(struct device *parent, struct device *self, void *aux)
! 156: {
! 157: struct ises_softc *sc = (struct ises_softc *)self;
! 158: struct pci_attach_args *pa = aux;
! 159: pci_chipset_tag_t pc = pa->pa_pc;
! 160: pci_intr_handle_t ih;
! 161: const char *intrstr = NULL;
! 162: bus_size_t memsize;
! 163:
! 164: bus_dma_segment_t seg;
! 165: int nsegs, error, state;
! 166:
! 167: SIMPLEQ_INIT(&sc->sc_queue);
! 168: SIMPLEQ_INIT(&sc->sc_qchip);
! 169: SIMPLEQ_INIT(&sc->sc_cmdq);
! 170: state = 0;
! 171:
! 172: /* Map control/status registers. */
! 173: if (pci_mapreg_map(pa, PCI_MAPREG_START,
! 174: PCI_MAPREG_TYPE_MEM | PCI_MAPREG_MEM_TYPE_32BIT, 0, &sc->sc_memt,
! 175: &sc->sc_memh, NULL, &memsize, 0)) {
! 176: printf(": can't find mem space\n");
! 177: return;
! 178: }
! 179: state++;
! 180:
! 181: /* Map interrupt. */
! 182: if (pci_intr_map(pa, &ih)) {
! 183: printf(": couldn't map interrupt\n");
! 184: goto fail;
! 185: }
! 186: state++;
! 187:
! 188: intrstr = pci_intr_string(pc, ih);
! 189: sc->sc_ih = pci_intr_establish(pc, ih, IPL_NET, ises_intr, sc,
! 190: self->dv_xname);
! 191: if (sc->sc_ih == NULL) {
! 192: printf(": couldn't establish interrupt\n");
! 193: if (intrstr != NULL)
! 194: printf(" at %s", intrstr);
! 195: printf("\n");
! 196: goto fail;
! 197: }
! 198:
! 199: /* Initialize DMA map */
! 200: sc->sc_dmat = pa->pa_dmat;
! 201: error = bus_dmamap_create(sc->sc_dmat, 1 << PGSHIFT, 1, 1 << PGSHIFT,
! 202: 0, BUS_DMA_NOWAIT | BUS_DMA_ALLOCNOW, &sc->sc_dmamap);
! 203: if (error) {
! 204: printf(": cannot create dma map (%d)\n", error);
! 205: goto fail;
! 206: }
! 207: state++;
! 208:
! 209: /* Allocate in DMAable memory. */
! 210: if (bus_dmamem_alloc(sc->sc_dmat, ISES_B_DATASIZE, 1, 0, &seg, 1,
! 211: &nsegs, BUS_DMA_NOWAIT)) {
! 212: printf(": can't alloc dma buffer space\n");
! 213: goto fail;
! 214: }
! 215: state++;
! 216:
! 217: if (bus_dmamem_map(sc->sc_dmat, &seg, nsegs, ISES_B_DATASIZE,
! 218: &sc->sc_dma_data, 0)) {
! 219: printf(": can't map dma buffer space\n");
! 220: goto fail;
! 221: }
! 222: state++;
! 223:
! 224: printf(": %s\n", intrstr);
! 225:
! 226: bzero(&isesstats, sizeof(isesstats));
! 227:
! 228: sc->sc_cid = crypto_get_driverid(0);
! 229:
! 230: if (sc->sc_cid < 0)
! 231: goto fail;
! 232:
! 233: /*
! 234: * Since none of the initialization steps generate interrupts
! 235: * for example, the hardware reset, we use a number of timeouts
! 236: * (or init states) to do the rest of the chip initialization.
! 237: */
! 238:
! 239: sc->sc_initstate = 0;
! 240: startuphook_establish(ises_initstate, sc);
! 241:
! 242: #ifdef ISESDEBUG
! 243: ises_debug_init(sc);
! 244: #endif
! 245: return;
! 246:
! 247: fail:
! 248: switch (state) { /* Always fallthrough here. */
! 249: case 5:
! 250: bus_dmamem_unmap(sc->sc_dmat, (caddr_t)&sc->sc_dma_data,
! 251: sizeof sc->sc_dma_data);
! 252: /* FALLTHROUGH */
! 253: case 4:
! 254: bus_dmamem_free(sc->sc_dmat, &seg, nsegs);
! 255: /* FALLTHROUGH */
! 256: case 3:
! 257: bus_dmamap_destroy(sc->sc_dmat, sc->sc_dmamap);
! 258: /* FALLTHROUGH */
! 259: case 2:
! 260: pci_intr_disestablish(pc, sc->sc_ih);
! 261: /* FALLTHROUGH */
! 262: case 1:
! 263: bus_space_unmap(sc->sc_memt, sc->sc_memh, memsize);
! 264: /* FALLTHROUGH */
! 265: default: /* 0 */
! 266: break;
! 267: }
! 268: return;
! 269: }
! 270:
! 271: void
! 272: ises_initstate(void *v)
! 273: {
! 274: /*
! 275: * Step through chip initialization.
! 276: * sc->sc_initstate tells us what to do.
! 277: */
! 278: extern int hz;
! 279: struct ises_softc *sc = v;
! 280: char *dv = sc->sc_dv.dv_xname;
! 281: u_int32_t stat;
! 282: int p, ticks, algs[CRYPTO_ALGORITHM_MAX + 1];
! 283: static int retry_count = 0; /* XXX Should be in softc */
! 284:
! 285: ticks = hz * 3 / 2; /* 1.5s */
! 286:
! 287: p = ISES_STAT_IDP_STATE(READ_REG(sc, ISES_A_STAT));
! 288: DPRINTF(("%s: initstate %d, IDP state is %d \"%s\"\n", dv,
! 289: sc->sc_initstate, p, ises_idp_state[p]));
! 290:
! 291: switch (sc->sc_initstate) {
! 292: case 0:
! 293: /* Called by dostartuphooks(9). */
! 294: timeout_set(&sc->sc_timeout, ises_initstate, sc);
! 295: sc->sc_initstate++;
! 296:
! 297: /* FALLTHROUGH */
! 298: case 1:
! 299: /* Power up the chip (clear powerdown bit) */
! 300: stat = READ_REG(sc, ISES_BO_STAT);
! 301: if (stat & ISES_BO_STAT_POWERDOWN) {
! 302: stat &= ~ISES_BO_STAT_POWERDOWN;
! 303: WRITE_REG(sc, ISES_BO_STAT, stat);
! 304: /* Selftests will take 1 second. */
! 305: break;
! 306: }
! 307: #if 1
! 308: else {
! 309: /* Power down the chip for sane init, then rerun. */
! 310: stat |= ISES_BO_STAT_POWERDOWN;
! 311: WRITE_REG(sc, ISES_BO_STAT, stat);
! 312: sc->sc_initstate--; /* Rerun state 1. */
! 313: break;
! 314: }
! 315: #else
! 316: /* FALLTHROUGH (chip is already powered up) */
! 317: sc->sc_initstate++;
! 318: #endif
! 319:
! 320: case 2:
! 321: /* Perform a hardware reset */
! 322: stat = 0;
! 323:
! 324: printf ("%s: initializing...\n", dv);
! 325:
! 326: /* Clear all possible bypass bits. */
! 327: for (p = 0; p < 128; p++)
! 328: WRITE_REG(sc, ISES_B_BDATAOUT, 0L);
! 329:
! 330: stat |= ISES_BO_STAT_HWRESET;
! 331: WRITE_REG(sc, ISES_BO_STAT, stat);
! 332: stat &= ~ISES_BO_STAT_HWRESET;
! 333: WRITE_REG(sc, ISES_BO_STAT, stat);
! 334: /* Again, selftests will take 1 second. */
! 335: break;
! 336:
! 337: case 3:
! 338: /* Set AConf to zero, i.e 32-bits access to A-int. */
! 339: stat = READ_REG(sc, ISES_BO_STAT);
! 340: stat &= ~ISES_BO_STAT_ACONF;
! 341: WRITE_REG(sc, ISES_BO_STAT, stat);
! 342:
! 343: /* Is the firmware already loaded? */
! 344: if (READ_REG(sc, ISES_A_STAT) & ISES_STAT_HW_DA) {
! 345: /* Yes it is, jump ahead a bit */
! 346: ticks = 1;
! 347: sc->sc_initstate += 3; /* Next step --> 7 */
! 348: break;
! 349: }
! 350:
! 351: /*
! 352: * Download the Basic Functionality firmware.
! 353: */
! 354:
! 355: p = ISES_STAT_IDP_STATE(READ_REG(sc, ISES_A_STAT));
! 356: if (p == ISES_IDP_WFPL) {
! 357: /* We're ready to download. */
! 358: ticks = 1;
! 359: sc->sc_initstate += 2; /* Next step --> 6 */
! 360: break;
! 361: }
! 362:
! 363: /*
! 364: * Prior to downloading we need to reset the NSRAM.
! 365: * Setting the tamper bit will erase the contents
! 366: * in 1 microsecond.
! 367: */
! 368: stat = READ_REG(sc, ISES_BO_STAT);
! 369: stat |= ISES_BO_STAT_TAMPER;
! 370: WRITE_REG(sc, ISES_BO_STAT, stat);
! 371: ticks = 1;
! 372: break;
! 373:
! 374: case 4:
! 375: /* After tamper bit has been set, powerdown chip. */
! 376: stat = READ_REG(sc, ISES_BO_STAT);
! 377: stat |= ISES_BO_STAT_POWERDOWN;
! 378: WRITE_REG(sc, ISES_BO_STAT, stat);
! 379: /* Wait one second for power to dissipate. */
! 380: break;
! 381:
! 382: case 5:
! 383: /* Clear tamper and powerdown bits. */
! 384: stat = READ_REG(sc, ISES_BO_STAT);
! 385: stat &= ~(ISES_BO_STAT_TAMPER | ISES_BO_STAT_POWERDOWN);
! 386: WRITE_REG(sc, ISES_BO_STAT, stat);
! 387: /* Again we need to wait a second for selftests. */
! 388: break;
! 389:
! 390: case 6:
! 391: /*
! 392: * We'll need some space in the input queue (IQF)
! 393: * and we need to be in the 'waiting for program
! 394: * length' IDP state (0x4).
! 395: */
! 396: p = ISES_STAT_IDP_STATE(READ_REG(sc, ISES_A_STAT));
! 397: if (READ_REG(sc, ISES_A_IQF) < 4 || p != ISES_IDP_WFPL) {
! 398: if (retry_count++ < ISES_MAX_DOWNLOAD_RETRIES) {
! 399: /* Retry download. */
! 400: sc->sc_initstate -= 5; /* Next step --> 2 */
! 401: ticks = 1;
! 402: break;
! 403: }
! 404: retry_count = 0;
! 405: printf("%s: cannot download firmware, "
! 406: "IDP state is \"%s\"\n", dv, ises_idp_state[p]);
! 407: return;
! 408: }
! 409:
! 410: /* Write firmware length */
! 411: WRITE_REG(sc, ISES_A_IQD, ISES_BF_IDPLEN);
! 412:
! 413: /* Write firmware code */
! 414: for (p = 0; p < sizeof(ises_bf_fw)/sizeof(u_int32_t); p++) {
! 415: WRITE_REG(sc, ISES_A_IQD, ises_bf_fw[p]);
! 416: if (READ_REG(sc, ISES_A_IQF) < 4)
! 417: DELAY(10);
! 418: }
! 419:
! 420: /* Write firmware CRC */
! 421: WRITE_REG(sc, ISES_A_IQD, ISES_BF_IDPCRC);
! 422:
! 423: /* Wait 1s while chip resets and runs selftests */
! 424: break;
! 425:
! 426: case 7:
! 427: /* Did the download succed? */
! 428: if (READ_REG(sc, ISES_A_STAT) & ISES_STAT_HW_DA) {
! 429: ticks = 1;
! 430: break;
! 431: }
! 432:
! 433: /* We failed. */
! 434: goto fail;
! 435:
! 436: case 8:
! 437: if (ises_assert_cmd_mode(sc) < 0)
! 438: goto fail;
! 439:
! 440: /*
! 441: * Now that the basic functionality firmware should be
! 442: * up and running, try to get the firmware version.
! 443: */
! 444:
! 445: stat = ises_get_fwversion(sc);
! 446: if (stat == 0)
! 447: goto fail;
! 448:
! 449: printf("%s: firmware v%d.%d loaded (%d bytes)", dv,
! 450: stat & 0xffff, (stat >> 16) & 0xffff, ISES_BF_IDPLEN << 2);
! 451:
! 452: /* We can use firmware versions 1.x & 2.x */
! 453: switch (stat & 0xffff) {
! 454: case 0:
! 455: printf(" diagnostic, %s disabled\n", dv);
! 456: goto fail;
! 457: case 1: /* Basic Func "base" firmware */
! 458: case 2: /* Basic Func "ipsec" firmware, no ADP code */
! 459: break;
! 460: default:
! 461: printf(" unknown, %s disabled\n", dv);
! 462: goto fail;
! 463: }
! 464:
! 465: stat = READ_REG(sc, ISES_A_STAT);
! 466: DPRINTF((", mode %s",
! 467: ises_sw_mode[ISES_STAT_SW_MODE(stat)]));
! 468:
! 469: /* Reuse the timeout for HRNG entropy collection. */
! 470: timeout_del(&sc->sc_timeout);
! 471: ises_hrng_init(sc);
! 472:
! 473: /* Set the interrupt mask */
! 474: sc->sc_intrmask = ISES_STAT_BCHU_OAF | ISES_STAT_BCHU_ERR |
! 475: ISES_STAT_BCHU_OFHF | ISES_STAT_SW_OQSINC |
! 476: ISES_STAT_LNAU_BUSY_1 | ISES_STAT_LNAU_ERR_1 |
! 477: ISES_STAT_LNAU_BUSY_2 | ISES_STAT_LNAU_ERR_2;
! 478: #if 0
! 479: ISES_STAT_BCHU_ERR | ISES_STAT_BCHU_OAF |
! 480: ISES_STAT_BCHU_IFE | ISES_STAT_BCHU_IFHE |
! 481: ISES_STAT_BCHU_OFHF | ISES_STAT_BCHU_OFF;
! 482: #endif
! 483:
! 484: WRITE_REG(sc, ISES_A_INTE, sc->sc_intrmask);
! 485:
! 486: /* We're done. */
! 487: printf("\n");
! 488:
! 489: /* Register ourselves with crypto framework. */
! 490: bzero(algs, sizeof(algs));
! 491:
! 492: algs[CRYPTO_3DES_CBC] = CRYPTO_ALG_FLAG_SUPPORTED;
! 493: algs[CRYPTO_DES_CBC] = CRYPTO_ALG_FLAG_SUPPORTED;
! 494: algs[CRYPTO_MD5_HMAC] = CRYPTO_ALG_FLAG_SUPPORTED;
! 495: algs[CRYPTO_SHA1_HMAC] = CRYPTO_ALG_FLAG_SUPPORTED;
! 496: algs[CRYPTO_RIPEMD160_HMAC] = CRYPTO_ALG_FLAG_SUPPORTED;
! 497:
! 498: crypto_register(sc->sc_cid, algs,
! 499: ises_newsession, ises_freesession, ises_process);
! 500: return;
! 501:
! 502: default:
! 503: printf("%s: entered unknown initstate %d\n", dv,
! 504: sc->sc_initstate);
! 505: goto fail;
! 506: }
! 507:
! 508: /* Increment state counter and schedule next step in 'ticks' ticks. */
! 509: sc->sc_initstate++;
! 510: timeout_add(&sc->sc_timeout, ticks);
! 511: return;
! 512:
! 513: fail:
! 514: printf("%s: firmware failure\n", dv);
! 515: timeout_del(&sc->sc_timeout);
! 516: return;
! 517: }
! 518:
! 519: /* Put a command on the A-interface queue. */
! 520: int
! 521: ises_queue_cmd(struct ises_softc *sc, u_int32_t cmd, u_int32_t *data,
! 522: u_int32_t (*callback)(struct ises_softc *, struct ises_cmd *))
! 523: {
! 524: struct ises_cmd *cq;
! 525: int p, len, s, code;
! 526:
! 527: len = cmd >> 24;
! 528: code = (cmd >> 16) & 0xFF;
! 529:
! 530: #ifdef ISESDEBUG
! 531: if (code != ISES_CMD_HBITS) /* ... since this happens 100 times/s */
! 532: DPRINTF(("%s: queueing cmd 0x%x len %d\n", sc->sc_dv.dv_xname,
! 533: code, len));
! 534: #endif
! 535:
! 536: s = splnet();
! 537:
! 538: if (len > READ_REG(sc, ISES_A_IQF)) {
! 539: splx(s);
! 540: return (EAGAIN); /* XXX ENOMEM ? */
! 541: }
! 542:
! 543: cq = (struct ises_cmd *)
! 544: malloc(sizeof (struct ises_cmd), M_DEVBUF, M_NOWAIT);
! 545: if (cq == NULL) {
! 546: splx(s);
! 547: isesstats.nomem++;
! 548: return (ENOMEM);
! 549: }
! 550: bzero(cq, sizeof (struct ises_cmd));
! 551: cq->cmd_code = code;
! 552: cq->cmd_cb = callback;
! 553: cq->cmd_session = sc->sc_cursession;
! 554: SIMPLEQ_INSERT_TAIL(&sc->sc_cmdq, cq, cmd_next);
! 555:
! 556: WRITE_REG(sc, ISES_A_IQD, cmd);
! 557:
! 558: /* LNAU register data should be written in reverse order */
! 559: if ((code >= ISES_CMD_LW_A_1 && code <= ISES_CMD_LW_U_1) || /* LNAU1 */
! 560: (code >= ISES_CMD_LW_A_2 && code <= ISES_CMD_LW_U_2)) /* LNAU2 */
! 561: for (p = len - 1; p >= 0; p--)
! 562: WRITE_REG(sc, ISES_A_IQD, *(data + p));
! 563: else
! 564: for (p = 0; p < len; p++)
! 565: WRITE_REG(sc, ISES_A_IQD, *(data + p));
! 566:
! 567: /* Signal 'command ready'. */
! 568: WRITE_REG(sc, ISES_A_IQS, 0);
! 569:
! 570: splx(s);
! 571: return (0);
! 572: }
! 573:
! 574: /* Process all completed responses in the output queue. */
! 575: void
! 576: ises_process_oqueue(struct ises_softc *sc)
! 577: {
! 578: #ifdef ISESDEBUG
! 579: char *dv = sc->sc_dv.dv_xname;
! 580: #endif
! 581: struct ises_cmd *cq;
! 582: struct ises_session *ses;
! 583: u_int32_t oqs, r, d;
! 584: int cmd, len, c, s;
! 585:
! 586: r = READ_REG(sc, ISES_A_OQS);
! 587: if (r > 1)
! 588: DPRINTF(("%s:process_oqueue: OQS=%d\n", dv, r));
! 589:
! 590: /* OQS gives us the number of responses we have to process. */
! 591: while ((oqs = READ_REG(sc, ISES_A_OQS)) > 0) {
! 592: /* Read command response. [ len(8) | cmd(8) | rc(16) ] */
! 593: r = READ_REG(sc, ISES_A_OQD);
! 594: len = (r >> 24);
! 595: cmd = (r >> 16) & 0xff;
! 596: r = r & 0xffff;
! 597:
! 598: s = splnet();
! 599: if (!SIMPLEQ_EMPTY(&sc->sc_cmdq)) {
! 600: cq = SIMPLEQ_FIRST(&sc->sc_cmdq);
! 601: SIMPLEQ_REMOVE_HEAD(&sc->sc_cmdq, cmd_next);
! 602: cq->cmd_rlen = len;
! 603: } else {
! 604: cq = NULL;
! 605: DPRINTF(("%s:process_oqueue: cmd queue empty!\n", dv));
! 606: }
! 607: splx(s);
! 608:
! 609: if (r) {
! 610: /* Ouch. This command generated an error */
! 611: DPRINTF(("%s:process_oqueue: cmd 0x%x err %d\n", dv,
! 612: cmd, (r & ISES_RC_MASK)));
! 613: /* Abort any running session switch to force a retry.*/
! 614: sc->sc_switching = 0;
! 615: /* Return to CMD mode. This will reset all queues. */
! 616: (void)ises_assert_cmd_mode(sc);
! 617: } else {
! 618: /* Use specified callback, if any */
! 619: if (cq && cq->cmd_cb) {
! 620: if (cmd == cq->cmd_code) {
! 621: cq->cmd_cb(sc, cq);
! 622: cmd = ISES_CMD_NONE;
! 623: } else {
! 624: DPRINTF(("%s:process_oqueue: expected"
! 625: " cmd 0x%x, got 0x%x\n", dv,
! 626: cq->cmd_code, cmd));
! 627: /* XXX Some error handling here? */
! 628: }
! 629: }
! 630:
! 631: switch (cmd) {
! 632: case ISES_CMD_NONE:
! 633: break;
! 634:
! 635: case ISES_CMD_HBITS:
! 636: /* XXX How about increasing the pool size? */
! 637: /* XXX Use add_entropy_words instead? */
! 638: /* XXX ... at proper spl */
! 639: /* Cmd generated by ises_rng() via timeouts */
! 640: while (len--) {
! 641: d = READ_REG(sc, ISES_A_OQD);
! 642: add_true_randomness(d);
! 643: }
! 644: break;
! 645:
! 646: case ISES_CMD_LUPLOAD_1:
! 647: /* Get result of LNAU 1 operation. */
! 648: DPRINTF(("%s:process_oqueue: LNAU 1 result "
! 649: "upload (len=%d)\n", dv, len));
! 650: sc->sc_lnau1_rlen = len;
! 651: bzero(sc->sc_lnau1_r, 2048 / 8);
! 652: while (len--) {
! 653: /* first word is LSW */
! 654: sc->sc_lnau1_r[len] =
! 655: READ_REG(sc, ISES_A_OQD);
! 656: }
! 657: break;
! 658:
! 659: case ISES_CMD_LUPLOAD_2:
! 660: /* Get result of LNAU 1 operation. */
! 661: DPRINTF(("%s:process_oqueue: LNAU 2 result "
! 662: "upload (len=%d)\n", dv, len));
! 663: sc->sc_lnau2_rlen = len;
! 664: bzero(sc->sc_lnau1_r, 2048 / 8);
! 665: while (len--) {
! 666: /* first word is LSW */
! 667: sc->sc_lnau2_r[len] =
! 668: READ_REG(sc, ISES_A_OQD);
! 669: }
! 670: break;
! 671:
! 672: case ISES_CMD_BR_OMR:
! 673: ses = &sc->sc_sessions[cq->cmd_session];
! 674: ses->omr = READ_REG(sc, ISES_A_OQD);
! 675: DPRINTF(("%s:process_oqueue: read OMR[%08x]\n",
! 676: dv, ses->omr));
! 677: #ifdef ISESDEBUG
! 678: ises_debug_parse_omr(sc);
! 679: #endif
! 680: break;
! 681:
! 682: case ISES_CMD_BSWITCH:
! 683: /* XXX Currently BSWITCH does not work. */
! 684: DPRINTF(("%s:process_oqueue: BCHU_SWITCH\n"));
! 685: /* Put switched BCHU session in cur session. */
! 686: ses = &sc->sc_sessions[cq->cmd_session];
! 687: for(c = 0; len > 0; len--, c++)
! 688: #if 0 /* Don't store the key, just drain the data */
! 689: *((u_int32_t *)&ses + c) =
! 690: #endif
! 691: READ_REG(sc, ISES_A_OQD);
! 692:
! 693: sc->sc_switching = 0;
! 694: ises_feed (sc);
! 695: break;
! 696:
! 697: case ISES_CMD_BW_HMLR:
! 698: /* XXX Obsoleted by ises_bchu_switch_final */
! 699: DPRINTF(("%s:process_oqueue: CMD_BW_HMLR !?\n",
! 700: dv));
! 701: break;
! 702:
! 703: default:
! 704: /* All other are ok (no response data) */
! 705: DPRINTF(("%s:process_oqueue cmd 0x%x len %d\n",
! 706: dv, cmd, len));
! 707: if (cq && cq->cmd_cb)
! 708: len -= cq->cmd_cb(sc, cq);
! 709: }
! 710: }
! 711:
! 712: if (cq)
! 713: free(cq, M_DEVBUF);
! 714:
! 715: /* This will drain any remaining data and ACK this reponse. */
! 716: while (len-- > 0)
! 717: d = READ_REG(sc, ISES_A_OQD);
! 718: WRITE_REG(sc, ISES_A_OQS, 0);
! 719: if (oqs > 1)
! 720: DELAY(1); /* Wait for fw to decrement OQS (8 clocks) */
! 721: }
! 722: }
! 723:
! 724: int
! 725: ises_intr(void *arg)
! 726: {
! 727: struct ises_softc *sc = arg;
! 728: u_int32_t ints, dma_status, cmd;
! 729: char *dv = sc->sc_dv.dv_xname;
! 730:
! 731: dma_status = READ_REG(sc, ISES_DMA_STATUS);
! 732:
! 733: if (!(dma_status & (ISES_DMA_STATUS_R_ERR | ISES_DMA_STATUS_W_ERR))) {
! 734: if ((sc->sc_dma_mask & ISES_DMA_STATUS_R_RUN) != 0 &&
! 735: (dma_status & ISES_DMA_STATUS_R_RUN) == 0) {
! 736: DPRINTF(("%s: DMA read complete\n", dv));
! 737:
! 738: bus_dmamap_sync(sc->sc_dmat, sc->sc_dmamap, 0,
! 739: sc->sc_dmamap->dm_mapsize, BUS_DMASYNC_POSTREAD);
! 740:
! 741: /* XXX Pick up and return the data.*/
! 742:
! 743: WRITE_REG(sc, ISES_DMA_RESET, 0);
! 744: }
! 745: if ((sc->sc_dma_mask & ISES_DMA_STATUS_W_RUN) != 0 &&
! 746: (dma_status & ISES_DMA_STATUS_W_RUN) == 0) {
! 747: DPRINTF(("%s: DMA write complete\n", dv));
! 748:
! 749: bus_dmamap_sync(sc->sc_dmat, sc->sc_dmamap, 0,
! 750: sc->sc_dmamap->dm_mapsize, BUS_DMASYNC_POSTWRITE);
! 751:
! 752: WRITE_REG(sc, ISES_DMA_RESET, 0);
! 753: ises_feed(sc);
! 754: }
! 755: } else {
! 756: printf ("%s: DMA error\n", dv);
! 757: WRITE_REG(sc, ISES_DMA_RESET, 0);
! 758: }
! 759:
! 760: ints = READ_REG(sc, ISES_A_INTS);
! 761: if (!(ints & sc->sc_intrmask)) {
! 762: DPRINTF (("%s: other intr mask [%08x]\n", ints));
! 763: return (0); /* Not our interrupt. */
! 764: }
! 765:
! 766: /* Clear all set intr bits. */
! 767: WRITE_REG(sc, ISES_A_INTS, ints);
! 768:
! 769: #if 0
! 770: /* Check it we've got room for more data. */
! 771: if (READ_REG(sc, ISES_A_STAT) &
! 772: (ISES_STAT_BCHU_IFE | ISES_STAT_BCHU_IFHE))
! 773: ises_feed(sc);
! 774: #endif
! 775:
! 776: /* Does the A-intf output queue have data we need to process? */
! 777: if (ints & ISES_STAT_SW_OQSINC)
! 778: ises_process_oqueue(sc);
! 779:
! 780: if (ints & ISES_STAT_LNAU_BUSY_1) {
! 781: DPRINTF(("%s:ises_intr: LNAU 1 job complete\n", dv));
! 782: /* upload LNAU 1 result (into sc->sc_lnau1_r) */
! 783: cmd = ISES_MKCMD(ISES_CMD_LUPLOAD_1, 0);
! 784: ises_queue_cmd(sc, cmd, NULL, NULL);
! 785: }
! 786:
! 787: if (ints & ISES_STAT_LNAU_BUSY_2) {
! 788: DPRINTF(("%s:ises_intr: LNAU 2 job complete\n", dv));
! 789: /* upload LNAU 2 result (into sc->sc_lnau2_r) */
! 790: cmd = ISES_MKCMD(ISES_CMD_LUPLOAD_2, 0);
! 791: ises_queue_cmd(sc, cmd, NULL, NULL);
! 792: }
! 793:
! 794: if (ints & ISES_STAT_LNAU_ERR_1) {
! 795: DPRINTF(("%s:ises_intr: LNAU 1 error\n", dv));
! 796: sc->sc_lnau1_rlen = -1;
! 797: }
! 798:
! 799: if (ints & ISES_STAT_LNAU_ERR_2) {
! 800: DPRINTF(("%s:ises_intr: LNAU 2 error\n", dv));
! 801: sc->sc_lnau2_rlen = -1;
! 802: }
! 803:
! 804: if (ints & ISES_STAT_BCHU_OAF) { /* output data available */
! 805: DPRINTF(("%s:ises_intr: BCHU_OAF bit set\n", dv));
! 806: /* Read DMA data from B-interface. */
! 807: ises_read_dma (sc);
! 808: }
! 809:
! 810: if (ints & ISES_STAT_BCHU_ERR) { /* We got a BCHU error */
! 811: DPRINTF(("%s:ises_intr: BCHU error\n", dv));
! 812: /* XXX Error handling */
! 813: }
! 814:
! 815: if (ints & ISES_STAT_BCHU_OFHF) { /* Output is half full */
! 816: DPRINTF(("%s:ises_intr: BCHU output FIFO half full\n", dv));
! 817: /* XXX drain data? */
! 818: }
! 819:
! 820: #if 0 /* XXX Useful? */
! 821: if (ints & ISES_STAT_BCHU_OFF) { /* Output is full */
! 822: /* XXX drain data / error handling? */
! 823: }
! 824: #endif
! 825: return (1);
! 826: }
! 827:
! 828: int
! 829: ises_feed(struct ises_softc *sc)
! 830: {
! 831: struct ises_q *q;
! 832: bus_dma_segment_t *ds = &sc->sc_dmamap->dm_segs[0];
! 833: u_int32_t dma_status;
! 834: int s;
! 835: #ifdef ISESDEBUG
! 836: char *dv = sc->sc_dv.dv_xname;
! 837: #endif
! 838:
! 839: DPRINTF(("%s:ises_feed: called (sc = %p)\n", dv, sc));
! 840: DELAY(1000000);
! 841:
! 842: s = splnet();
! 843: /* Anything to do? */
! 844: if (SIMPLEQ_EMPTY(&sc->sc_queue) ||
! 845: (READ_REG(sc, ISES_A_STAT) & ISES_STAT_BCHU_IFF)) {
! 846: splx(s);
! 847: return (0);
! 848: }
! 849:
! 850: /* Pick the first */
! 851: q = SIMPLEQ_FIRST(&sc->sc_queue);
! 852: splx(s);
! 853:
! 854: /* If we're currently switching sessions, we'll have to wait. */
! 855: if (sc->sc_switching != 0) {
! 856: DPRINTF(("%s:ises_feed: waiting for session switch\n", dv));
! 857: return (0);
! 858: }
! 859:
! 860: /* If on-chip data is not correct for this data, switch session. */
! 861: if (sc->sc_cursession != q->q_sesn) {
! 862: /* Session switch required */
! 863: DPRINTF(("%s:ises_feed: initiating session switch\n", dv));
! 864: if (ises_bchu_switch_session (sc, &q->q_session, q->q_sesn))
! 865: sc->sc_cursession = q->q_sesn;
! 866: else
! 867: DPRINTF(("%s:ises_feed: session switch failed\n", dv));
! 868: return (0);
! 869: }
! 870:
! 871: DPRINTF(("%s:ises_feed: feed to chip (q = %p)\n", dv, q));
! 872: DELAY(2000000);
! 873:
! 874: s = splnet();
! 875: SIMPLEQ_REMOVE_HEAD(&sc->sc_queue, q_next);
! 876: SIMPLEQ_INSERT_TAIL(&sc->sc_qchip, q, q_next);
! 877: --sc->sc_nqueue;
! 878: splx(s);
! 879:
! 880: if (q->q_crp->crp_flags & CRYPTO_F_IMBUF)
! 881: bus_dmamap_load_mbuf(sc->sc_dmat, sc->sc_dmamap,
! 882: q->q_src.mbuf, BUS_DMA_NOWAIT);
! 883: else if (q->q_crp->crp_flags & CRYPTO_F_IOV)
! 884: bus_dmamap_load_uio(sc->sc_dmat, sc->sc_dmamap, q->q_src.uio,
! 885: BUS_DMA_NOWAIT);
! 886: /* ... else */
! 887:
! 888: /* Start writing data to the ises. */
! 889: bus_dmamap_sync(sc->sc_dmat, sc->sc_dmamap, 0,
! 890: sc->sc_dmamap->dm_mapsize, BUS_DMASYNC_PREWRITE);
! 891:
! 892: DPRINTF(("%s:ises_feed: writing DMA\n", dv));
! 893: DELAY(1000000);
! 894:
! 895: sc->sc_dma_mask |= ISES_DMA_STATUS_W_RUN;
! 896:
! 897: WRITE_REG(sc, ISES_DMA_WRITE_START, ds->ds_addr);
! 898: WRITE_REG(sc, ISES_DMA_WRITE_COUNT, ISES_DMA_WCOUNT(ds->ds_len));
! 899:
! 900: dma_status = READ_REG(sc, ISES_DMA_STATUS);
! 901: dma_status |= ISES_DMA_CTRL_ILT | ISES_DMA_CTRL_RLINE;
! 902: WRITE_REG(sc, ISES_DMA_CTRL, dma_status);
! 903:
! 904: DPRINTF(("%s:ises_feed: done\n", dv));
! 905: return (0);
! 906: }
! 907:
! 908: /*
! 909: * Allocate a new 'session' and return an encoded session id. 'sidp'
! 910: * contains our registration id, and should contain an encoded session
! 911: * id on successful allocation.
! 912: */
! 913: int
! 914: ises_newsession(u_int32_t *sidp, struct cryptoini *cri)
! 915: {
! 916: struct cryptoini *c, *mac = NULL, *enc = NULL;
! 917: struct ises_softc *sc = NULL;
! 918: struct ises_session *ses;
! 919: MD5_CTX md5ctx;
! 920: SHA1_CTX sha1ctx;
! 921: RMD160_CTX rmd160ctx;
! 922: int i, sesn;
! 923: #ifdef ISESDEBUG
! 924: char *dv;
! 925: #endif
! 926:
! 927: if (sidp == NULL || cri == NULL)
! 928: return (EINVAL);
! 929:
! 930: for (i = 0; i < ises_cd.cd_ndevs; i++) {
! 931: sc = ises_cd.cd_devs[i];
! 932: if (sc == NULL || sc->sc_cid == (*sidp))
! 933: break;
! 934: }
! 935: if (sc == NULL)
! 936: return (EINVAL);
! 937: #ifdef ISESDEBUG
! 938: dv = sc->sc_dv.dv_xname;
! 939: #endif
! 940:
! 941: DPRINTF(("%s:ises_newsession: start\n", dv));
! 942:
! 943: for (c = cri; c != NULL; c = c->cri_next) {
! 944: if (c->cri_alg == CRYPTO_MD5_HMAC ||
! 945: c->cri_alg == CRYPTO_SHA1_HMAC ||
! 946: c->cri_alg == CRYPTO_RIPEMD160_HMAC) {
! 947: if (mac)
! 948: return (EINVAL);
! 949: mac = c;
! 950: } else if (c->cri_alg == CRYPTO_DES_CBC ||
! 951: c->cri_alg == CRYPTO_3DES_CBC) {
! 952: if (enc)
! 953: return (EINVAL);
! 954: enc = c;
! 955: } else
! 956: return (EINVAL);
! 957: }
! 958: if (mac == 0 && enc == 0)
! 959: return (EINVAL);
! 960:
! 961: #ifdef ISESDEBUG
! 962: printf ("%s:ises_newsession: mac=%p(%d) enc=%p(%d)\n",
! 963: dv, mac, (mac ? mac->cri_alg : -1), enc, (enc ? enc->cri_alg : -1));
! 964: #endif
! 965:
! 966: /* Allocate a new session */
! 967: if (sc->sc_sessions == NULL) {
! 968: ses = sc->sc_sessions = (struct ises_session *)
! 969: malloc(sizeof(struct ises_session), M_DEVBUF, M_NOWAIT);
! 970: if (ses == NULL) {
! 971: isesstats.nomem++;
! 972: return (ENOMEM);
! 973: }
! 974: sc->sc_cursession = -1;
! 975: sesn = 0;
! 976: sc->sc_nsessions = 1;
! 977: } else {
! 978: ses = NULL;
! 979: for (sesn = 0; sesn < sc->sc_nsessions; sesn++)
! 980: if (sc->sc_sessions[sesn].omr == 0) {
! 981: ses = &sc->sc_sessions[sesn];
! 982: sc->sc_cursession = sesn;
! 983: break;
! 984: }
! 985:
! 986: if (ses == NULL) {
! 987: i = sc->sc_nsessions * sizeof(struct ises_session);
! 988: ses = (struct ises_session *)
! 989: malloc(i + sizeof(struct ises_session), M_DEVBUF,
! 990: M_NOWAIT);
! 991: if (ses == NULL) {
! 992: isesstats.nomem++;
! 993: return (ENOMEM);
! 994: }
! 995:
! 996: bcopy(sc->sc_sessions, ses, i);
! 997: bzero(sc->sc_sessions, i);
! 998: free(sc->sc_sessions, M_DEVBUF);
! 999: sc->sc_sessions = ses;
! 1000: ses = &sc->sc_sessions[sc->sc_nsessions];
! 1001: sc->sc_cursession = sc->sc_nsessions;
! 1002: sc->sc_nsessions++;
! 1003: }
! 1004: }
! 1005:
! 1006: DPRINTF(("%s:ises_newsession: nsessions=%d cursession=%d\n", dv,
! 1007: sc->sc_nsessions, sc->sc_cursession));
! 1008:
! 1009: bzero(ses, sizeof(struct ises_session));
! 1010:
! 1011: /* Select data path through B-interface. */
! 1012: ses->omr |= ISES_SELR_BCHU_DIS;
! 1013:
! 1014: if (enc) {
! 1015: /* get an IV, network byte order */
! 1016: /* XXX switch to using builtin HRNG ! */
! 1017: get_random_bytes(ses->sccr, sizeof(ses->sccr));
! 1018:
! 1019: /* crypto key */
! 1020: if (enc->cri_alg == CRYPTO_DES_CBC) {
! 1021: bcopy(enc->cri_key, &ses->kr[0], 8);
! 1022: bcopy(enc->cri_key, &ses->kr[2], 8);
! 1023: bcopy(enc->cri_key, &ses->kr[4], 8);
! 1024: } else
! 1025: bcopy(enc->cri_key, &ses->kr[0], 24);
! 1026:
! 1027: SWAP32(ses->kr[0]);
! 1028: SWAP32(ses->kr[1]);
! 1029: SWAP32(ses->kr[2]);
! 1030: SWAP32(ses->kr[3]);
! 1031: SWAP32(ses->kr[4]);
! 1032: SWAP32(ses->kr[5]);
! 1033: }
! 1034:
! 1035: if (mac) {
! 1036: for (i = 0; i < mac->cri_klen / 8; i++)
! 1037: mac->cri_key[i] ^= HMAC_IPAD_VAL;
! 1038:
! 1039: switch (mac->cri_alg) {
! 1040: case CRYPTO_MD5_HMAC:
! 1041: MD5Init(&md5ctx);
! 1042: MD5Update(&md5ctx, mac->cri_key, mac->cri_klen / 8);
! 1043: MD5Update(&md5ctx, hmac_ipad_buffer, HMAC_BLOCK_LEN -
! 1044: (mac->cri_klen / 8));
! 1045: MD5Final((u_int8_t *)&ses->cvr, &md5ctx);
! 1046: break;
! 1047: case CRYPTO_SHA1_HMAC:
! 1048: SHA1Init(&sha1ctx);
! 1049: SHA1Update(&sha1ctx, mac->cri_key, mac->cri_klen / 8);
! 1050: SHA1Update(&sha1ctx, hmac_ipad_buffer, HMAC_BLOCK_LEN -
! 1051: (mac->cri_klen / 8));
! 1052: SHA1Final((u_int8_t *)ses->cvr, &sha1ctx);
! 1053: break;
! 1054: case CRYPTO_RIPEMD160_HMAC:
! 1055: default:
! 1056: RMD160Init(&rmd160ctx);
! 1057: RMD160Update(&rmd160ctx, mac->cri_key,
! 1058: mac->cri_klen / 8);
! 1059: RMD160Update(&rmd160ctx, hmac_ipad_buffer,
! 1060: HMAC_BLOCK_LEN - (mac->cri_klen / 8));
! 1061: RMD160Final((u_int8_t *)ses->cvr, &rmd160ctx);
! 1062: break;
! 1063: }
! 1064:
! 1065: for (i = 0; i < mac->cri_klen / 8; i++)
! 1066: mac->cri_key[i] ^= (HMAC_IPAD_VAL ^ HMAC_OPAD_VAL);
! 1067:
! 1068: switch (mac->cri_alg) {
! 1069: case CRYPTO_MD5_HMAC:
! 1070: MD5Init(&md5ctx);
! 1071: MD5Update(&md5ctx, mac->cri_key, mac->cri_klen / 8);
! 1072: MD5Update(&md5ctx, hmac_opad_buffer, HMAC_BLOCK_LEN -
! 1073: (mac->cri_klen / 8));
! 1074: MD5Update(&md5ctx, (u_int8_t *)ses->cvr,
! 1075: sizeof(md5ctx.state));
! 1076: MD5Final((u_int8_t *)ses->cvr, &md5ctx);
! 1077: break;
! 1078: case CRYPTO_SHA1_HMAC:
! 1079: SHA1Init(&sha1ctx);
! 1080: SHA1Update(&sha1ctx, mac->cri_key, mac->cri_klen / 8);
! 1081: SHA1Update(&sha1ctx, hmac_opad_buffer, HMAC_BLOCK_LEN -
! 1082: (mac->cri_klen / 8));
! 1083: SHA1Update(&sha1ctx, (u_int8_t *)ses->cvr,
! 1084: sizeof(sha1ctx.state));
! 1085: SHA1Final((u_int8_t *)ses->cvr, &sha1ctx);
! 1086: break;
! 1087: case CRYPTO_RIPEMD160_HMAC:
! 1088: default:
! 1089: RMD160Init(&rmd160ctx);
! 1090: RMD160Update(&rmd160ctx, mac->cri_key,
! 1091: mac->cri_klen / 8);
! 1092: RMD160Update(&rmd160ctx, hmac_opad_buffer,
! 1093: HMAC_BLOCK_LEN - (mac->cri_klen / 8));
! 1094: RMD160Update(&rmd160ctx, (u_int8_t *)ses->cvr,
! 1095: sizeof(rmd160ctx.state));
! 1096: RMD160Final((u_int8_t *)ses->cvr, &rmd160ctx);
! 1097: break;
! 1098: }
! 1099:
! 1100: for (i = 0; i < mac->cri_klen / 8; i++)
! 1101: mac->cri_key[i] ^= HMAC_OPAD_VAL;
! 1102: }
! 1103:
! 1104: DPRINTF(("%s:ises_newsession: done\n", dv));
! 1105: *sidp = ISES_SID(sc->sc_dv.dv_unit, sesn);
! 1106: return (0);
! 1107: }
! 1108:
! 1109: /* Deallocate a session. */
! 1110: int
! 1111: ises_freesession(u_int64_t tsid)
! 1112: {
! 1113: struct ises_softc *sc;
! 1114: int card, sesn;
! 1115: u_int32_t sid = ((u_int32_t)tsid) & 0xffffffff;
! 1116:
! 1117: card = ISES_CARD(sid);
! 1118: if (card >= ises_cd.cd_ndevs || ises_cd.cd_devs[card] == NULL)
! 1119: return (EINVAL);
! 1120:
! 1121: sc = ises_cd.cd_devs[card];
! 1122: sesn = ISES_SESSION(sid);
! 1123:
! 1124: DPRINTF(("%s:ises_freesession: freeing session %d\n",
! 1125: sc->sc_dv.dv_xname, sesn));
! 1126:
! 1127: if (sc->sc_cursession == sesn)
! 1128: sc->sc_cursession = -1;
! 1129:
! 1130: bzero(&sc->sc_sessions[sesn], sizeof(sc->sc_sessions[sesn]));
! 1131:
! 1132: return (0);
! 1133: }
! 1134:
! 1135: /* Called by the crypto framework, crypto(9). */
! 1136: int
! 1137: ises_process(struct cryptop *crp)
! 1138: {
! 1139: struct ises_softc *sc;
! 1140: struct ises_q *q;
! 1141: struct cryptodesc *maccrd, *enccrd, *crd;
! 1142: struct ises_session *ses;
! 1143: int card, s, err = EINVAL;
! 1144: int encoffset, macoffset, cpskip, sskip, dskip, stheend, dtheend;
! 1145: int cpoffset, coffset;
! 1146: #if 0
! 1147: int nicealign;
! 1148: #endif
! 1149: #ifdef ISESDEBUG
! 1150: char *dv;
! 1151: #endif
! 1152:
! 1153: if (crp == NULL || crp->crp_callback == NULL)
! 1154: return (EINVAL);
! 1155:
! 1156: card = ISES_CARD(crp->crp_sid);
! 1157: if (card >= ises_cd.cd_ndevs || ises_cd.cd_devs[card] == NULL)
! 1158: goto errout;
! 1159:
! 1160: sc = ises_cd.cd_devs[card];
! 1161: #ifdef ISESDEBUG
! 1162: dv = sc->sc_dv.dv_xname;
! 1163: #endif
! 1164:
! 1165: DPRINTF(("%s:ises_process: start (crp = %p)\n", dv, crp));
! 1166:
! 1167: s = splnet();
! 1168: if (sc->sc_nqueue == ISES_MAX_NQUEUE) {
! 1169: splx(s);
! 1170: goto memerr;
! 1171: }
! 1172: splx(s);
! 1173:
! 1174: q = (struct ises_q *)malloc(sizeof(struct ises_q), M_DEVBUF, M_NOWAIT);
! 1175: if (q == NULL)
! 1176: goto memerr;
! 1177: bzero(q, sizeof(struct ises_q));
! 1178:
! 1179: q->q_sesn = ISES_SESSION(crp->crp_sid);
! 1180: ses = &sc->sc_sessions[q->q_sesn];
! 1181:
! 1182: DPRINTF(("%s:ises_process: session %d selected\n", dv, q->q_sesn));
! 1183:
! 1184: q->q_sc = sc;
! 1185: q->q_crp = crp;
! 1186:
! 1187: if (crp->crp_flags & CRYPTO_F_IMBUF) {
! 1188: q->q_src.mbuf = (struct mbuf *)crp->crp_buf;
! 1189: q->q_dst.mbuf = (struct mbuf *)crp->crp_buf;
! 1190: } else if (crp->crp_flags & CRYPTO_F_IOV) {
! 1191: q->q_src.uio = (struct uio *)crp->crp_buf;
! 1192: q->q_dst.uio = (struct uio *)crp->crp_buf;
! 1193: } else {
! 1194: /* XXX for now... */
! 1195: goto errout;
! 1196: }
! 1197:
! 1198: /*
! 1199: * Check if the crypto descriptors are sane. We accept:
! 1200: * - just one crd; either auth or crypto
! 1201: * - two crds; must be one auth and one crypto, although now
! 1202: * for encryption we only want the first to be crypto, while
! 1203: * for decryption the second one should be crypto.
! 1204: */
! 1205: maccrd = enccrd = NULL;
! 1206: for (crd = crp->crp_desc; crd; crd = crd->crd_next) {
! 1207: switch (crd->crd_alg) {
! 1208: case CRYPTO_MD5_HMAC:
! 1209: case CRYPTO_SHA1_HMAC:
! 1210: case CRYPTO_RIPEMD160_HMAC:
! 1211: if (maccrd || (enccrd &&
! 1212: (enccrd->crd_flags & CRD_F_ENCRYPT) == 0))
! 1213: goto errout;
! 1214: maccrd = crd;
! 1215: break;
! 1216: case CRYPTO_DES_CBC:
! 1217: case CRYPTO_3DES_CBC:
! 1218: if (enccrd ||
! 1219: (maccrd && (crd->crd_flags & CRD_F_ENCRYPT)))
! 1220: goto errout;
! 1221: enccrd = crd;
! 1222: break;
! 1223: default:
! 1224: goto errout;
! 1225: }
! 1226: }
! 1227: if (!maccrd && !enccrd)
! 1228: goto errout;
! 1229:
! 1230: DPRINTF(("%s:ises_process: enc=%p mac=%p\n", dv, enccrd, maccrd));
! 1231:
! 1232: /* Select data path through B-interface. */
! 1233: q->q_session.omr |= ISES_SELR_BCHU_DIS;
! 1234:
! 1235: if (enccrd) {
! 1236: encoffset = enccrd->crd_skip;
! 1237:
! 1238: /* Select algorithm */
! 1239: if (enccrd->crd_alg == CRYPTO_3DES_CBC)
! 1240: q->q_session.omr |= ISES_SOMR_BOMR_3DES;
! 1241: else
! 1242: q->q_session.omr |= ISES_SOMR_BOMR_DES;
! 1243:
! 1244: /* Set CBC mode */
! 1245: q->q_session.omr |= ISES_SOMR_FMR_CBC;
! 1246:
! 1247: if (enccrd->crd_flags & CRD_F_ENCRYPT) {
! 1248: /* Set encryption bit */
! 1249: q->q_session.omr |= ISES_SOMR_EDR;
! 1250:
! 1251: if (enccrd->crd_flags & CRD_F_IV_EXPLICIT)
! 1252: bcopy(enccrd->crd_iv, q->q_session.sccr, 8);
! 1253: else {
! 1254: q->q_session.sccr[0] = ses->sccr[0];
! 1255: q->q_session.sccr[1] = ses->sccr[1];
! 1256: }
! 1257:
! 1258: if ((enccrd->crd_flags & CRD_F_IV_PRESENT) == 0) {
! 1259: if (crp->crp_flags & CRYPTO_F_IMBUF)
! 1260: m_copyback(q->q_src.mbuf,
! 1261: enccrd->crd_inject, 8,
! 1262: (caddr_t)q->q_session.sccr);
! 1263: else if (crp->crp_flags & CRYPTO_F_IOV)
! 1264: cuio_copyback(q->q_src.uio,
! 1265: enccrd->crd_inject, 8,
! 1266: (caddr_t)q->q_session.sccr);
! 1267: /* XXX else ... */
! 1268: }
! 1269: } else {
! 1270: /* Clear encryption bit == decrypt mode */
! 1271: q->q_session.omr &= ~ISES_SOMR_EDR;
! 1272:
! 1273: if (enccrd->crd_flags & CRD_F_IV_EXPLICIT)
! 1274: bcopy(enccrd->crd_iv, q->q_session.sccr, 8);
! 1275: else if (crp->crp_flags & CRYPTO_F_IMBUF)
! 1276: m_copydata(q->q_src.mbuf, enccrd->crd_inject,
! 1277: 8, (caddr_t)q->q_session.sccr);
! 1278: else if (crp->crp_flags & CRYPTO_F_IOV)
! 1279: cuio_copydata(q->q_src.uio,
! 1280: enccrd->crd_inject, 8,
! 1281: (caddr_t)q->q_session.sccr);
! 1282: /* XXX else ... */
! 1283: }
! 1284:
! 1285: q->q_session.kr[0] = ses->kr[0];
! 1286: q->q_session.kr[1] = ses->kr[1];
! 1287: q->q_session.kr[2] = ses->kr[2];
! 1288: q->q_session.kr[3] = ses->kr[3];
! 1289: q->q_session.kr[4] = ses->kr[4];
! 1290: q->q_session.kr[5] = ses->kr[5];
! 1291:
! 1292: SWAP32(q->q_session.sccr[0]);
! 1293: SWAP32(q->q_session.sccr[1]);
! 1294: }
! 1295:
! 1296: if (maccrd) {
! 1297: macoffset = maccrd->crd_skip;
! 1298:
! 1299: /* Select algorithm */
! 1300: switch (crd->crd_alg) {
! 1301: case CRYPTO_MD5_HMAC:
! 1302: q->q_session.omr |= ISES_HOMR_HFR_MD5;
! 1303: break;
! 1304: case CRYPTO_SHA1_HMAC:
! 1305: q->q_session.omr |= ISES_HOMR_HFR_SHA1;
! 1306: break;
! 1307: case CRYPTO_RIPEMD160_HMAC:
! 1308: default:
! 1309: q->q_session.omr |= ISES_HOMR_HFR_RMD160;
! 1310: break;
! 1311: }
! 1312:
! 1313: q->q_session.cvr[0] = ses->cvr[0];
! 1314: q->q_session.cvr[1] = ses->cvr[1];
! 1315: q->q_session.cvr[2] = ses->cvr[2];
! 1316: q->q_session.cvr[3] = ses->cvr[3];
! 1317: q->q_session.cvr[4] = ses->cvr[4];
! 1318: }
! 1319:
! 1320: if (enccrd && maccrd) {
! 1321: /* XXX Check if ises handles differing end of auth/enc etc */
! 1322: /* XXX For now, assume not (same as ubsec). */
! 1323: if (((encoffset + enccrd->crd_len) !=
! 1324: (macoffset + maccrd->crd_len)) ||
! 1325: (enccrd->crd_skip < maccrd->crd_skip)) {
! 1326: goto errout;
! 1327: }
! 1328:
! 1329: sskip = maccrd->crd_skip;
! 1330: cpskip = dskip = enccrd->crd_skip;
! 1331: stheend = maccrd->crd_len;
! 1332: dtheend = enccrd->crd_len;
! 1333: coffset = cpskip - sskip;
! 1334: cpoffset = cpskip + dtheend;
! 1335: /* XXX DEBUG ? */
! 1336: } else {
! 1337: cpskip = dskip = sskip = macoffset + encoffset;
! 1338: dtheend = enccrd ? enccrd->crd_len : maccrd->crd_len;
! 1339: stheend = dtheend;
! 1340: cpoffset = cpskip + dtheend;
! 1341: coffset = 0;
! 1342: }
! 1343: q->q_offset = coffset >> 2;
! 1344:
! 1345: #if 0 /* XXX not sure about this, in bus_dma context */
! 1346:
! 1347: if (crp->crp_flags & CRYPTO_F_IMBUF)
! 1348: q->q_src_l = mbuf2pages(q->q_src.mbuf, &q->q_src_npa,
! 1349: q->q_src_packp, q->q_src_packl, 1, &nicealign);
! 1350: else if (crp->crp_flags & CRYPTO_F_IOV)
! 1351: q->q_src_l = iov2pages(q->q_src.uio, &q->q_src_npa,
! 1352: q->q_src_packp, q->q_src_packl, 1, &nicealign);
! 1353: /* XXX else */
! 1354:
! 1355: DPRINTF(("%s:ises_process: foo2pages called!\n", dv));
! 1356:
! 1357: if (q->q_src_l == 0)
! 1358: goto memerr;
! 1359: else if (q->q_src_l > 0xfffc) {
! 1360: err = EIO;
! 1361: goto errout;
! 1362: }
! 1363:
! 1364: /* XXX ... */
! 1365:
! 1366: if (enccrd == NULL && maccrd != NULL) {
! 1367: /* XXX ... */
! 1368: } else {
! 1369: if (!nicealign && (crp->crp_flags & CRYPTO_F_IOV)) {
! 1370: goto errout;
! 1371: } else if (!nicealign && (crp->crp_flags & CRYPTO_F_IMBUF)) {
! 1372: int totlen, len;
! 1373: struct mbuf *m, *top, **mp;
! 1374:
! 1375: totlen = q->q_dst_l = q->q_src_l;
! 1376: if (q->q_src.mbuf->m_flags & M_PKTHDR) {
! 1377: MGETHDR(m, M_DONTWAIT, MT_DATA);
! 1378: M_DUP_PKTHDR(m, q->q_src.mbuf);
! 1379: len = MHLEN;
! 1380: } else {
! 1381: MGET(m, M_DONTWAIT, MT_DATA);
! 1382: len = MLEN;
! 1383: }
! 1384: if (m == NULL)
! 1385: goto memerr;
! 1386: if (totlen >= MINCLSIZE) {
! 1387: MCLGET(m, M_DONTWAIT);
! 1388: if (m->m_flags & M_EXT)
! 1389: len = MCLBYTES;
! 1390: }
! 1391: m->m_len = len;
! 1392: top = NULL;
! 1393: mp = ⊤
! 1394:
! 1395: while (totlen > 0) {
! 1396: if (top) {
! 1397: MGET(m, M_DONTWAIT, MT_DATA);
! 1398: if (m == NULL) {
! 1399: m_freem(top);
! 1400: goto memerr;
! 1401: }
! 1402: len = MLEN;
! 1403: }
! 1404: if (top && totlen >= MINCLSIZE) {
! 1405: MCLGET(m, M_DONTWAIT);
! 1406: if (m->m_flags & M_EXT)
! 1407: len = MCLBYTES;
! 1408: }
! 1409: m->m_len = len = min(totlen, len);
! 1410: totlen -= len;
! 1411: *mp = m;
! 1412:
! 1413: mp = &m->m_next;
! 1414: }
! 1415: q->q_dst.mbuf = top;
! 1416: #if notyet
! 1417: ubsec_mcopy(q->q_src.mbuf, q->q_dst.mbuf, cpskip, cpoffset);
! 1418: #endif
! 1419: } else
! 1420: q->q_dst.mbuf = q->q_src.mbuf;
! 1421:
! 1422: #if 0
! 1423: /* XXX ? */
! 1424: q->q_dst_l = mbuf2pages(q->q_dst.mbuf, &q->q_dst_npa,
! 1425: &q->q_dst_packp, &q->q_dst_packl, 1, NULL);
! 1426: #endif
! 1427: }
! 1428:
! 1429: #endif /* XXX */
! 1430:
! 1431: DPRINTF(("%s:ises_process: queueing request\n", dv));
! 1432:
! 1433: s = splnet();
! 1434: SIMPLEQ_INSERT_TAIL(&sc->sc_queue, q, q_next);
! 1435: sc->sc_nqueue++;
! 1436: splx(s);
! 1437: ises_feed(sc);
! 1438:
! 1439: return (0);
! 1440:
! 1441: memerr:
! 1442: err = ENOMEM;
! 1443: isesstats.nomem++;
! 1444: errout:
! 1445: DPRINTF(("%s:ises_process: an error occurred, err=%d, q=%p\n", dv,
! 1446: err, q));
! 1447:
! 1448: if (err == EINVAL)
! 1449: isesstats.invalid++;
! 1450:
! 1451: if (q) {
! 1452: if (q->q_src.mbuf != q->q_dst.mbuf)
! 1453: m_freem(q->q_dst.mbuf);
! 1454: free(q, M_DEVBUF);
! 1455: }
! 1456: crp->crp_etype = err;
! 1457: crypto_done(crp);
! 1458: return (0);
! 1459: }
! 1460:
! 1461: void
! 1462: ises_callback(struct ises_q *q)
! 1463: {
! 1464: struct cryptop *crp = (struct cryptop *)q->q_crp;
! 1465: struct cryptodesc *crd;
! 1466: struct ises_softc *sc = q->q_sc;
! 1467: u_int8_t *sccr;
! 1468:
! 1469: if ((crp->crp_flags & CRYPTO_F_IMBUF) &&
! 1470: (q->q_src.mbuf != q->q_dst.mbuf)) {
! 1471: m_freem(q->q_src.mbuf);
! 1472: crp->crp_buf = (caddr_t)q->q_dst.mbuf;
! 1473: }
! 1474:
! 1475: if (q->q_session.omr & ISES_SOMR_EDR) {
! 1476: /* Copy out IV after encryption. */
! 1477: sccr = (u_int8_t *)&sc->sc_sessions[q->q_sesn].sccr;
! 1478: for (crd = crp->crp_desc; crd; crd = crd->crd_next) {
! 1479: if (crd->crd_alg != CRYPTO_DES_CBC &&
! 1480: crd->crd_alg != CRYPTO_3DES_CBC)
! 1481: continue;
! 1482: if (crp->crp_flags & CRYPTO_F_IMBUF)
! 1483: m_copydata((struct mbuf *)crp->crp_buf,
! 1484: crd->crd_skip + crd->crd_len - 8, 8, sccr);
! 1485: else if (crp->crp_flags & CRYPTO_F_IOV)
! 1486: cuio_copydata((struct uio *)crp->crp_buf,
! 1487: crd->crd_skip + crd->crd_len - 8, 8, sccr);
! 1488: }
! 1489: }
! 1490:
! 1491: for (crd = crp->crp_desc; crd; crd = crd->crd_next) {
! 1492: if (crd->crd_alg != CRYPTO_MD5_HMAC &&
! 1493: crd->crd_alg != CRYPTO_SHA1_HMAC &&
! 1494: crd->crd_alg != CRYPTO_RIPEMD160_HMAC)
! 1495: continue;
! 1496: if (crp->crp_flags & CRYPTO_F_IMBUF)
! 1497: m_copyback((struct mbuf *)crp->crp_buf,
! 1498: crd->crd_inject, 12, (u_int8_t *)q->q_macbuf);
! 1499: else if (crp->crp_flags & CRYPTO_F_IOV)
! 1500: bcopy((u_int8_t *)q->q_macbuf, crp->crp_mac, 12);
! 1501: /* XXX else ... */
! 1502: break;
! 1503: }
! 1504:
! 1505: free(q, M_DEVBUF);
! 1506: DPRINTF(("%s:ises_callback: calling crypto_done\n",
! 1507: sc->sc_dv.dv_xname));
! 1508: crypto_done(crp);
! 1509: }
! 1510:
! 1511: /* Initilize the ISES hardware RNG, and set up timeouts. */
! 1512: void
! 1513: ises_hrng_init(struct ises_softc *sc)
! 1514: {
! 1515: u_int32_t cmd, r;
! 1516: int i;
! 1517: #ifdef ISESDEBUG
! 1518: struct timeval tv1, tv2;
! 1519: #endif
! 1520:
! 1521: /* Asking for random data will seed LFSR and start the RBG */
! 1522: cmd = ISES_MKCMD(ISES_CMD_HBITS, 1);
! 1523: r = 8; /* 8 * 32 = 256 bits */
! 1524:
! 1525: if (ises_queue_cmd(sc, cmd, &r, NULL))
! 1526: return;
! 1527:
! 1528: /* Wait until response arrives. */
! 1529: for (i = 1000; i && READ_REG(sc, ISES_A_OQS) == 0; i--)
! 1530: DELAY(10);
! 1531:
! 1532: if (!READ_REG(sc, ISES_A_OQS))
! 1533: return;
! 1534:
! 1535: /* Drain cmd response and 8*32 bits data */
! 1536: for (i = 0; i <= r; i++)
! 1537: (void)READ_REG(sc, ISES_A_OQD);
! 1538:
! 1539: /* ACK the response */
! 1540: WRITE_REG(sc, ISES_A_OQS, 0);
! 1541: DELAY(1);
! 1542: printf(", rng active");
! 1543:
! 1544: #ifdef ISESDEBUG
! 1545: /* Benchmark the HRNG. */
! 1546:
! 1547: /*
! 1548: * XXX These values gets surprisingly large. Docs state the
! 1549: * HNRG produces > 1 mbit/s of random data. The values I'm seeing
! 1550: * are much higher, ca 2.7-2.8 mbit/s. AFAICT the algorithm is sound.
! 1551: * Compiler optimization issues, perhaps?
! 1552: */
! 1553:
! 1554: #define ISES_WPR 250
! 1555: #define ISES_ROUNDS 100
! 1556: cmd = ISES_MKCMD(ISES_CMD_HBITS, 1);
! 1557: r = ISES_WPR;
! 1558:
! 1559: /* Queue 100 cmds; each generate 250 32-bit words of rnd data. */
! 1560: microtime(&tv1);
! 1561: for (i = 0; i < ISES_ROUNDS; i++)
! 1562: ises_queue_cmd(sc, cmd, &r, NULL);
! 1563: for (i = 0; i < ISES_ROUNDS; i++) {
! 1564: while (READ_REG(sc, ISES_A_OQS) == 0) ; /* Wait for response */
! 1565:
! 1566: (void)READ_REG(sc, ISES_A_OQD); /* read response */
! 1567: for (r = ISES_WPR; r--;)
! 1568: (void)READ_REG(sc, ISES_A_OQD); /* read data */
! 1569: WRITE_REG(sc, ISES_A_OQS, 0); /* ACK resp */
! 1570: DELAY(1); /* OQS needs 1us to decrement */
! 1571: }
! 1572: microtime(&tv2);
! 1573:
! 1574: timersub(&tv2, &tv1, &tv1);
! 1575: tv1.tv_usec += 1000000 * tv1.tv_sec;
! 1576: printf(", %dKb/sec",
! 1577: ISES_WPR * ISES_ROUNDS * 32 / 1024 * 1000000 / tv1.tv_usec);
! 1578: #endif
! 1579:
! 1580: timeout_set(&sc->sc_timeout, ises_hrng, sc);
! 1581: #ifndef ISES_HRNG_DISABLED
! 1582: ises_hrng(sc); /* Call first update */
! 1583: #endif
! 1584: }
! 1585:
! 1586: /* Called by timeout (and once by ises_init_hrng()). */
! 1587: void
! 1588: ises_hrng(void *v)
! 1589: {
! 1590: /*
! 1591: * Throw a HRNG read random bits command on the command queue.
! 1592: * The normal loop will manage the result and add it to the pool.
! 1593: */
! 1594: struct ises_softc *sc = v;
! 1595: u_int32_t cmd, n;
! 1596: extern int hz; /* from param.c */
! 1597:
! 1598: timeout_add(&sc->sc_timeout, hz / ISESRNGIPS);
! 1599:
! 1600: if (ises_assert_cmd_mode(sc) != 0)
! 1601: return;
! 1602:
! 1603: cmd = ISES_MKCMD(ISES_CMD_HBITS, 1);
! 1604: n = (ISESRNGBITS >> 5) & 0xff; /* ask for N 32 bit words */
! 1605:
! 1606: ises_queue_cmd(sc, cmd, &n, NULL);
! 1607: }
! 1608:
! 1609: u_int32_t
! 1610: ises_get_fwversion(struct ises_softc *sc)
! 1611: {
! 1612: u_int32_t r;
! 1613: int i;
! 1614:
! 1615: r = ISES_MKCMD(ISES_CMD_CHIP_ID, 0);
! 1616: WRITE_REG(sc, ISES_A_IQD, r);
! 1617: WRITE_REG(sc, ISES_A_IQS, 0);
! 1618:
! 1619: for (i = 100; i > 0 && READ_REG(sc, ISES_A_OQS) == 0; i--)
! 1620: DELAY(1);
! 1621:
! 1622: if (i < 1)
! 1623: return (0); /* No response */
! 1624:
! 1625: r = READ_REG(sc, ISES_A_OQD);
! 1626:
! 1627: /* Check validity. On error drain reponse data. */
! 1628: if (((r >> 16) & 0xff) != ISES_CMD_CHIP_ID ||
! 1629: ((r >> 24) & 0xff) != 3 || (r & ISES_RC_MASK) != ISES_RC_SUCCESS) {
! 1630: if ((r & ISES_RC_MASK) == ISES_RC_SUCCESS)
! 1631: for (i = ((r >> 24) & 0xff); i; i--)
! 1632: (void)READ_REG(sc, ISES_A_OQD);
! 1633: r = 0;
! 1634: goto out;
! 1635: }
! 1636:
! 1637: r = READ_REG(sc, ISES_A_OQD); /* read version */
! 1638: (void)READ_REG(sc, ISES_A_OQD); /* Discard 64bit "chip-id" */
! 1639: (void)READ_REG(sc, ISES_A_OQD);
! 1640: out:
! 1641: WRITE_REG(sc, ISES_A_OQS, 0); /* Ack the response */
! 1642: DELAY(1);
! 1643: return (r);
! 1644: }
! 1645:
! 1646: /*
! 1647: * ises_assert_cmd_mode() returns
! 1648: * -1 for failure to go to cmd
! 1649: * 0 if mode already was cmd
! 1650: * >0 if mode was other (WFC/WFR) but now is cmd (this has reset the queues)
! 1651: */
! 1652: int
! 1653: ises_assert_cmd_mode(struct ises_softc *sc)
! 1654: {
! 1655: switch (ISES_STAT_SW_MODE(READ_REG(sc, ISES_A_STAT))) {
! 1656: case 0x0: /* Selftest. XXX This is a transient state. */
! 1657: DELAY(1000000);
! 1658: if (ISES_STAT_SW_MODE(READ_REG(sc, ISES_A_STAT)) == 0)
! 1659: return (-1);
! 1660: return (ises_assert_cmd_mode(sc));
! 1661: case 0x1: /* Command mode */
! 1662: return (0);
! 1663: case 0x2: /* Waiting For Continue / WFC */
! 1664: bus_space_write_2(sc->sc_memt, sc->sc_memh, ISES_A_CTRL,
! 1665: ISES_A_CTRL_CONTINUE);
! 1666: DELAY(1);
! 1667: return ((ISES_STAT_SW_MODE(READ_REG(sc, ISES_A_STAT)) == 0) ?
! 1668: 1 : -1);
! 1669: case 0x3: /* Waiting For Reset / WFR */
! 1670: bus_space_write_2(sc->sc_memt, sc->sc_memh, ISES_A_CTRL,
! 1671: ISES_A_CTRL_RESET);
! 1672: DELAY(1000000);
! 1673: return ((ISES_STAT_SW_MODE(READ_REG(sc, ISES_A_STAT)) == 0) ?
! 1674: 2 : -1);
! 1675: default:
! 1676: return (-1); /* Unknown mode */
! 1677: }
! 1678: }
! 1679:
! 1680: int
! 1681: ises_bchu_switch_session (struct ises_softc *sc, struct ises_session *ss,
! 1682: int new_session)
! 1683: {
! 1684: /* It appears that the BCHU_SWITCH_SESSION command is broken. */
! 1685: /* We have to work around it. */
! 1686:
! 1687: u_int32_t cmd;
! 1688:
! 1689: /* Do we have enough in-queue space? Count cmds + data, 16bit words. */
! 1690: if ((8 * 2 + sizeof (*ss) / 2) > READ_REG(sc, ISES_A_IQF))
! 1691: return (0);
! 1692:
! 1693: /* Mark 'switch' in progress. */
! 1694: sc->sc_switching = new_session + 1;
! 1695:
! 1696: /* Write the key. */
! 1697: cmd = ISES_MKCMD(ISES_CMD_BW_KR0, 2);
! 1698: ises_queue_cmd(sc, cmd, &ss->kr[4], NULL);
! 1699: cmd = ISES_MKCMD(ISES_CMD_BW_KR1, 2);
! 1700: ises_queue_cmd(sc, cmd, &ss->kr[2], NULL);
! 1701: cmd = ISES_MKCMD(ISES_CMD_BW_KR2, 2);
! 1702: ises_queue_cmd(sc, cmd, &ss->kr[0], NULL);
! 1703:
! 1704: /* Write OMR - Operation Method Register, clears SCCR+CVR+DBCR+HMLR */
! 1705: cmd = ISES_MKCMD(ISES_CMD_BW_OMR, 1);
! 1706: ises_queue_cmd(sc, cmd, &ss->omr, NULL);
! 1707:
! 1708: /* Write SCCR - Symmetric Crypto Chaining Register (IV) */
! 1709: cmd = ISES_MKCMD(ISES_CMD_BW_SCCR, 2);
! 1710: ises_queue_cmd(sc, cmd, &ss->sccr[0], NULL);
! 1711:
! 1712: /* Write CVR - Chaining Variables Register (hash state) */
! 1713: cmd = ISES_MKCMD(ISES_CMD_BW_CVR, 5);
! 1714: ises_queue_cmd(sc, cmd, &ss->cvr[0], NULL);
! 1715:
! 1716: /* Write DBCR - Data Block Count Register */
! 1717: cmd = ISES_MKCMD(ISES_CMD_BW_DBCR, 2);
! 1718: ises_queue_cmd(sc, cmd, &ss->dbcr[0], NULL);
! 1719:
! 1720: /* Write HMLR - Hash Message Length Register - last cmd in switch */
! 1721: cmd = ISES_MKCMD(ISES_CMD_BW_HMLR, 2);
! 1722: ises_queue_cmd(sc, cmd, &ss->hmlr[0], ises_bchu_switch_final);
! 1723:
! 1724: return (1);
! 1725: }
! 1726:
! 1727: u_int32_t
! 1728: ises_bchu_switch_final (struct ises_softc *sc, struct ises_cmd *cmd)
! 1729: {
! 1730: /* Session switch is complete. */
! 1731:
! 1732: DPRINTF(("%s:ises_bchu_switch_final: switch complete\n",
! 1733: sc->sc_dv.dv_xname));
! 1734:
! 1735: sc->sc_cursession = sc->sc_switching - 1;
! 1736: sc->sc_switching = 0;
! 1737:
! 1738: /* Retry/restart feed. */
! 1739: ises_feed(sc);
! 1740:
! 1741: return (0);
! 1742: }
! 1743:
! 1744: /* XXX Currently unused. */
! 1745: void
! 1746: ises_read_dma (struct ises_softc *sc)
! 1747: {
! 1748: bus_dma_segment_t *ds = &sc->sc_dmamap->dm_segs[0];
! 1749: u_int32_t dma_status;
! 1750:
! 1751: bus_dmamap_sync(sc->sc_dmat, sc->sc_dmamap, 0,
! 1752: sc->sc_dmamap->dm_mapsize, BUS_DMASYNC_PREREAD);
! 1753:
! 1754: WRITE_REG(sc, ISES_DMA_READ_START, ds->ds_addr);
! 1755: WRITE_REG(sc, ISES_DMA_READ_START, ISES_DMA_RCOUNT(ds->ds_len));
! 1756:
! 1757: dma_status = READ_REG(sc, ISES_DMA_STATUS);
! 1758: dma_status |= ISES_DMA_CTRL_ILT | ISES_DMA_CTRL_WRITE;
! 1759: WRITE_REG(sc, ISES_DMA_CTRL, dma_status);
! 1760: }
! 1761:
! 1762: #ifdef ISESDEBUG
! 1763: /*
! 1764: * Development code section below here.
! 1765: */
! 1766:
! 1767: void
! 1768: ises_debug_init (struct ises_softc *sc)
! 1769: {
! 1770: ises_sc = sc;
! 1771: ises_db = 0;
! 1772: timeout_set (&ises_db_timeout, ises_debug_loop, sc);
! 1773: timeout_add (&ises_db_timeout, 100);
! 1774: printf ("ises0: ISESDEBUG active (ises_sc = %p)\n", ises_sc);
! 1775: }
! 1776:
! 1777: void
! 1778: ises_debug_2 (void)
! 1779: {
! 1780: timeout_set (&ises_db_timeout, ises_debug_loop, ises_sc);
! 1781: timeout_add (&ises_db_timeout, 100);
! 1782: printf ("ises0: another debug timeout scheduled!\n");
! 1783: }
! 1784:
! 1785: void
! 1786: ises_debug_simple_cmd (struct ises_softc *sc, u_int32_t code, u_int32_t d)
! 1787: {
! 1788: u_int32_t cmd, data;
! 1789:
! 1790: cmd = ISES_MKCMD(code, (d ? 1 : 0));
! 1791: data = d;
! 1792: ises_queue_cmd(sc, cmd, &d, NULL);
! 1793: }
! 1794:
! 1795: void
! 1796: ises_debug_loop (void *v)
! 1797: {
! 1798: struct ises_softc *sc = (struct ises_softc *)v;
! 1799: struct ises_session ses;
! 1800: u_int32_t cmd, stat;
! 1801: int i;
! 1802:
! 1803: if (ises_db)
! 1804: printf ("ises0: ises_db = %d sc = %p\n", ises_db, sc);
! 1805:
! 1806: timeout_add (&ises_db_timeout, 300); /* Every 3 secs */
! 1807:
! 1808: stat = READ_REG(sc, ISES_A_OQS);
! 1809: cmd = READ_REG(sc, ISES_A_IQS);
! 1810: if (stat || cmd)
! 1811: printf ("ises0: IQS=%d OQS=%d / IQF=%d OQF=%d\n",
! 1812: cmd, stat, READ_REG(sc, ISES_A_IQF),
! 1813: READ_REG(sc, ISES_A_OQF));
! 1814:
! 1815: switch (ises_db) {
! 1816: default:
! 1817: /* 0 - do nothing (just loop) */
! 1818: break;
! 1819: case 1:
! 1820: /* Just dump register info */
! 1821: ises_showreg();
! 1822: break;
! 1823: case 2:
! 1824: /* Reset LNAU 1 registers */
! 1825: ises_debug_simple_cmd(sc, ISES_CMD_LRESET_1, 0);
! 1826:
! 1827: /* Compute R = (141 * 5623) % 117 (R should be 51 (0x33)) */
! 1828: ises_debug_simple_cmd(sc, ISES_CMD_LW_A_1, 141);
! 1829: ises_debug_simple_cmd(sc, ISES_CMD_LW_B_1, 5623);
! 1830: ises_debug_simple_cmd(sc, ISES_CMD_LW_N_1, 117);
! 1831:
! 1832: /* Launch LNAU operation. */
! 1833: ises_debug_simple_cmd(sc, ISES_CMD_LMULMOD_1, 0);
! 1834: break;
! 1835: case 3:
! 1836: /* Read result LNAU_1 R register (should not be necessary) */
! 1837: ises_debug_simple_cmd(sc, ISES_CMD_LUPLOAD_1, 0);
! 1838: break;
! 1839: case 4:
! 1840: /* Print result */
! 1841: printf ("LNAU_1 R length = %d\n", sc->sc_lnau1_rlen);
! 1842: for (i = 0; i < sc->sc_lnau1_rlen; i++)
! 1843: printf ("W%02d-[%08x]-(%u)\t%s", i, sc->sc_lnau1_r[i],
! 1844: sc->sc_lnau1_r[i], (i%4)==3 ? "\n" : "");
! 1845: printf ("%s", (i%4) ? "\n" : "");
! 1846: break;
! 1847: case 5:
! 1848: /* Crypto. */
! 1849:
! 1850: /* Load BCHU session data */
! 1851: bzero(&ses, sizeof ses);
! 1852: ses.kr[0] = 0xD0;
! 1853: ses.kr[1] = 0xD1;
! 1854: ses.kr[2] = 0xD2;
! 1855: ses.kr[3] = 0xD3;
! 1856: ses.kr[4] = 0xD4;
! 1857: ses.kr[5] = 0xD5;
! 1858:
! 1859: /* cipher data out is hash in, SHA1, 3DES, encrypt, ECB */
! 1860: ses.omr = ISES_SELR_BCHU_HISOF | ISES_HOMR_HFR_SHA1 |
! 1861: ISES_SOMR_BOMR_3DES | ISES_SOMR_EDR | ISES_SOMR_FMR_ECB;
! 1862:
! 1863: #if 1
! 1864: printf ("Queueing home-cooked session switch\n");
! 1865: ises_bchu_switch_session(sc, &ses, 0);
! 1866: #else /* switch session does not appear to work - it never returns */
! 1867: printf ("Queueing BCHU session switch\n");
! 1868: cmd = ISES_MKCMD(ISES_CMD_BSWITCH, sizeof ses / 4);
! 1869: printf ("session is %d 32bit words (== 18 ?), cmd = [%08x]\n",
! 1870: sizeof ses / 4, cmd);
! 1871: ises_queue_cmd(sc, cmd, (u_int32_t *)&ses, NULL);
! 1872: #endif
! 1873:
! 1874: break;
! 1875: case 96:
! 1876: printf ("Stopping HRNG data collection\n");
! 1877: timeout_del(&sc->sc_timeout);
! 1878: break;
! 1879: case 97:
! 1880: printf ("Restarting HRNG data collection\n");
! 1881: if (!timeout_pending(&sc->sc_timeout))
! 1882: timeout_add(&sc->sc_timeout, hz);
! 1883: break;
! 1884: case 98:
! 1885: printf ("Resetting (wait >1s before cont.)\n");
! 1886: stat = ISES_BO_STAT_HWRESET;
! 1887: WRITE_REG(sc, ISES_BO_STAT, stat);
! 1888: stat &= ~ISES_BO_STAT_HWRESET;
! 1889: WRITE_REG(sc, ISES_BO_STAT, stat);
! 1890: break;
! 1891: case 99:
! 1892: printf ("Resetting everything!\n");
! 1893: if (timeout_pending(&sc->sc_timeout))
! 1894: timeout_del(&sc->sc_timeout);
! 1895: timeout_set(&sc->sc_timeout, ises_initstate, sc);
! 1896: sc->sc_initstate = 0;
! 1897: ises_initstate(sc);
! 1898: break;
! 1899: }
! 1900:
! 1901: ises_db = 0;
! 1902: }
! 1903:
! 1904: void
! 1905: ises_showreg (void)
! 1906: {
! 1907: struct ises_softc *sc = ises_sc;
! 1908: u_int32_t stat, cmd;
! 1909:
! 1910: /* Board register */
! 1911:
! 1912: printf ("Board register: ");
! 1913: stat = READ_REG(sc, ISES_BO_STAT);
! 1914:
! 1915: if (stat & ISES_BO_STAT_LOOP)
! 1916: printf ("LoopMode ");
! 1917: if (stat & ISES_BO_STAT_TAMPER)
! 1918: printf ("Tamper ");
! 1919: if (stat & ISES_BO_STAT_POWERDOWN)
! 1920: printf ("PowerDown ");
! 1921: if (stat & ISES_BO_STAT_ACONF)
! 1922: printf ("16bitA-IF ");
! 1923: if (stat & ISES_BO_STAT_HWRESET)
! 1924: printf ("HWReset");
! 1925: if (stat & ISES_BO_STAT_AIRQ)
! 1926: printf ("A-IFintr");
! 1927: printf("\n");
! 1928:
! 1929: /* A interface */
! 1930:
! 1931: printf ("A Interface STAT register: \n\tLNAU-[");
! 1932: stat = READ_REG(sc, ISES_A_STAT);
! 1933: if (stat & ISES_STAT_LNAU_MASKED)
! 1934: printf ("masked");
! 1935: else {
! 1936: if (stat & ISES_STAT_LNAU_BUSY_1)
! 1937: printf ("busy1 ");
! 1938: if (stat & ISES_STAT_LNAU_ERR_1)
! 1939: printf ("err1 ");
! 1940: if (stat & ISES_STAT_LNAU_BUSY_2)
! 1941: printf ("busy2 ");
! 1942: if (stat & ISES_STAT_LNAU_ERR_2)
! 1943: printf ("err2 ");
! 1944: }
! 1945: printf ("]\n\tBCHU-[");
! 1946:
! 1947: if (stat & ISES_STAT_BCHU_MASKED)
! 1948: printf ("masked");
! 1949: else {
! 1950: if (stat & ISES_STAT_BCHU_BUSY)
! 1951: printf ("busy ");
! 1952: if (stat & ISES_STAT_BCHU_ERR)
! 1953: printf ("err ");
! 1954: if (stat & ISES_STAT_BCHU_SCIF)
! 1955: printf ("cr-inop ");
! 1956: if (stat & ISES_STAT_BCHU_HIF)
! 1957: printf ("ha-inop ");
! 1958: if (stat & ISES_STAT_BCHU_DDB)
! 1959: printf ("dscd-data ");
! 1960: if (stat & ISES_STAT_BCHU_IRF)
! 1961: printf ("inp-req ");
! 1962: if (stat & ISES_STAT_BCHU_OAF)
! 1963: printf ("out-avail ");
! 1964: if (stat & ISES_STAT_BCHU_DIE)
! 1965: printf ("inp-enabled ");
! 1966: if (stat & ISES_STAT_BCHU_UE)
! 1967: printf ("ififo-empty ");
! 1968: if (stat & ISES_STAT_BCHU_IFE)
! 1969: printf ("ififo-half ");
! 1970: if (stat & ISES_STAT_BCHU_IFHE)
! 1971: printf ("ififo-full ");
! 1972: if (stat & ISES_STAT_BCHU_OFE)
! 1973: printf ("ofifo-empty ");
! 1974: if (stat & ISES_STAT_BCHU_OFHF)
! 1975: printf ("ofifo-half ");
! 1976: if (stat & ISES_STAT_BCHU_OFF)
! 1977: printf ("ofifo-full ");
! 1978: }
! 1979: printf ("] \n\tmisc-[");
! 1980:
! 1981: if (stat & ISES_STAT_HW_DA)
! 1982: printf ("downloaded-appl ");
! 1983: if (stat & ISES_STAT_HW_ACONF)
! 1984: printf ("A-IF-conf ");
! 1985: if (stat & ISES_STAT_SW_WFOQ)
! 1986: printf ("OQ-wait ");
! 1987: if (stat & ISES_STAT_SW_OQSINC)
! 1988: printf ("OQS-increased ");
! 1989: printf ("]\n\t");
! 1990:
! 1991: if (stat & ISES_STAT_HW_DA)
! 1992: printf ("SW-mode is \"%s\"",
! 1993: ises_sw_mode[ISES_STAT_SW_MODE(stat)]);
! 1994: else
! 1995: printf ("IDP-state is \"%s\"",
! 1996: ises_idp_state[ISES_STAT_IDP_STATE(stat)]);
! 1997: printf ("\n");
! 1998:
! 1999: printf ("\tOQS = %d IQS = %d OQF = %d IQF = %d\n",
! 2000: READ_REG(sc, ISES_A_OQS), READ_REG(sc, ISES_A_IQS),
! 2001: READ_REG(sc, ISES_A_OQF), READ_REG(sc, ISES_A_IQF));
! 2002:
! 2003: /* B interface */
! 2004:
! 2005: printf ("B-interface status register contains [%08x]\n",
! 2006: READ_REG(sc, ISES_B_STAT));
! 2007:
! 2008: /* DMA */
! 2009:
! 2010: printf ("DMA read starts at 0x%x, length %d bytes\n",
! 2011: READ_REG(sc, ISES_DMA_READ_START),
! 2012: READ_REG(sc, ISES_DMA_READ_COUNT) >> 16);
! 2013:
! 2014: printf ("DMA write starts at 0x%x, length %d bytes\n",
! 2015: READ_REG(sc, ISES_DMA_WRITE_START),
! 2016: READ_REG(sc, ISES_DMA_WRITE_COUNT) & 0x00ff);
! 2017:
! 2018: stat = READ_REG(sc, ISES_DMA_STATUS);
! 2019: printf ("DMA status register contains [%08x]\n", stat);
! 2020:
! 2021: if (stat & ISES_DMA_CTRL_ILT)
! 2022: printf (" -- Ignore latency timer\n");
! 2023: if (stat & 0x0C000000)
! 2024: printf (" -- PCI Read - multiple\n");
! 2025: else if (stat & 0x08000000)
! 2026: printf (" -- PCI Read - line\n");
! 2027:
! 2028: if (stat & ISES_DMA_STATUS_R_RUN)
! 2029: printf (" -- PCI Read running/incomplete\n");
! 2030: else
! 2031: printf (" -- PCI Read complete\n");
! 2032: if (stat & ISES_DMA_STATUS_R_ERR)
! 2033: printf (" -- PCI Read DMA Error\n");
! 2034:
! 2035: if (stat & ISES_DMA_STATUS_W_RUN)
! 2036: printf (" -- PCI Write running/incomplete\n");
! 2037: else
! 2038: printf (" -- PCI Write complete\n");
! 2039: if (stat & ISES_DMA_STATUS_W_ERR)
! 2040: printf (" -- PCI Write DMA Error\n");
! 2041:
! 2042: /* OMR / HOMR / SOMR */
! 2043:
! 2044: /*
! 2045: * All these means throwing a cmd on to the A-interface, and then
! 2046: * reading the result.
! 2047: *
! 2048: * Currently, put debug output in process_oqueue...
! 2049: */
! 2050:
! 2051: printf ("Queueing Operation Method Register (OMR) READ cmd...\n");
! 2052: cmd = ISES_MKCMD(ISES_CMD_BR_OMR, 0);
! 2053: ises_queue_cmd(sc, cmd, NULL, NULL);
! 2054: }
! 2055:
! 2056: void
! 2057: ises_debug_parse_omr (struct ises_softc *sc)
! 2058: {
! 2059: u_int32_t omr = sc->sc_sessions[sc->sc_cursession].omr;
! 2060:
! 2061: printf ("SELR : ");
! 2062: if (omr & ISES_SELR_BCHU_EH)
! 2063: printf ("cont-on-error ");
! 2064: else
! 2065: printf ("stop-on-error ");
! 2066:
! 2067: if (omr & ISES_SELR_BCHU_HISOF)
! 2068: printf ("HU-input-is-SCU-output ");
! 2069:
! 2070: if (omr & ISES_SELR_BCHU_DIS)
! 2071: printf ("data-interface-select=B ");
! 2072: else
! 2073: printf ("data-interface-select=DataIn/DataOut ");
! 2074:
! 2075: printf ("\n");
! 2076:
! 2077: printf ("HOMR : ");
! 2078: if (omr & ISES_HOMR_HMTR)
! 2079: printf ("expect-padded-hash-msg ");
! 2080: else
! 2081: printf ("expect-plaintext-hash-msg ");
! 2082:
! 2083: printf ("ER=%d ", (omr & ISES_HOMR_ER) >> 20); /* ick */
! 2084:
! 2085: printf ("HFR=");
! 2086: switch (omr & ISES_HOMR_HFR) {
! 2087: case ISES_HOMR_HFR_NOP:
! 2088: printf ("inactive ");
! 2089: break;
! 2090: case ISES_HOMR_HFR_MD5:
! 2091: printf ("MD5 ");
! 2092: break;
! 2093: case ISES_HOMR_HFR_RMD160:
! 2094: printf ("RMD160 ");
! 2095: break;
! 2096: case ISES_HOMR_HFR_RMD128:
! 2097: printf ("RMD128 ");
! 2098: break;
! 2099: case ISES_HOMR_HFR_SHA1:
! 2100: printf ("SHA-1 ");
! 2101: break;
! 2102: default:
! 2103: printf ("reserved! ");
! 2104: break;
! 2105: }
! 2106: printf ("\nSOMR : ");
! 2107:
! 2108: switch (omr & ISES_SOMR_BOMR) {
! 2109: case ISES_SOMR_BOMR_NOP:
! 2110: printf ("NOP ");
! 2111: break;
! 2112: case ISES_SOMR_BOMR_TRANSPARENT:
! 2113: printf ("transparent ");
! 2114: break;
! 2115: case ISES_SOMR_BOMR_DES:
! 2116: printf ("DES ");
! 2117: break;
! 2118: case ISES_SOMR_BOMR_3DES2:
! 2119: printf ("3DES-2 ");
! 2120: break;
! 2121: case ISES_SOMR_BOMR_3DES:
! 2122: printf ("3DES-3 ");
! 2123: break;
! 2124: default:
! 2125: if (omr & ISES_SOMR_BOMR_SAFER)
! 2126: printf ("SAFER ");
! 2127: else
! 2128: printf ("reserved! ");
! 2129: break;
! 2130: }
! 2131:
! 2132: if (omr & ISES_SOMR_EDR)
! 2133: printf ("mode=encrypt ");
! 2134: else
! 2135: printf ("mode=decrypt ");
! 2136:
! 2137: switch (omr & ISES_SOMR_FMR) {
! 2138: case ISES_SOMR_FMR_ECB:
! 2139: printf ("ECB");
! 2140: break;
! 2141: case ISES_SOMR_FMR_CBC:
! 2142: printf ("CBC");
! 2143: break;
! 2144: case ISES_SOMR_FMR_CFB64:
! 2145: printf ("CFB64");
! 2146: break;
! 2147: case ISES_SOMR_FMR_OFB64:
! 2148: printf ("OFB64");
! 2149: break;
! 2150: default:
! 2151: /* Nada */
! 2152: }
! 2153: printf ("\n");
! 2154: }
! 2155:
! 2156: #endif /* ISESDEBUG */
CVSweb