[BACK]Return to ises.c CVS log [TXT][DIR] Up to [local] / sys / dev / pci

Annotation of sys/dev/pci/ises.c, Revision 1.1.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 = &top;
                   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