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

Annotation of sys/dev/pci/noct.c, Revision 1.1.1.1

1.1       nbrk        1: /*     $OpenBSD: noct.c,v 1.17 2006/06/29 21:34:51 deraadt Exp $       */
                      2:
                      3: /*
                      4:  * Copyright (c) 2002 Jason L. Wright (jason@thought.net)
                      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:  * Effort sponsored in part by the Defense Advanced Research Projects
                     29:  * Agency (DARPA) and Air Force Research Laboratory, Air Force
                     30:  * Materiel Command, USAF, under agreement number F30602-01-2-0537.
                     31:  *
                     32:  */
                     33:
                     34: /*
                     35:  * Driver for the Netoctave NSP2000 security processor.
                     36:  */
                     37:
                     38: #include <sys/param.h>
                     39: #include <sys/systm.h>
                     40: #include <sys/proc.h>
                     41: #include <sys/errno.h>
                     42: #include <sys/malloc.h>
                     43: #include <sys/kernel.h>
                     44: #include <sys/mbuf.h>
                     45: #include <sys/device.h>
                     46: #include <sys/extent.h>
                     47: #include <sys/kthread.h>
                     48:
                     49: #include <crypto/cryptodev.h>
                     50: #include <dev/rndvar.h>
                     51:
                     52: #include <dev/pci/pcireg.h>
                     53: #include <dev/pci/pcivar.h>
                     54: #include <dev/pci/pcidevs.h>
                     55:
                     56: #include <dev/pci/noctreg.h>
                     57: #include <dev/pci/noctvar.h>
                     58:
                     59: int noct_probe(struct device *, void *, void *);
                     60: void noct_attach(struct device *, struct device *, void *);
                     61: int noct_intr(void *);
                     62:
                     63: int noct_ram_size(struct noct_softc *);
                     64: void noct_ram_write(struct noct_softc *, u_int32_t, u_int64_t);
                     65: u_int64_t noct_ram_read(struct noct_softc *, u_int32_t);
                     66:
                     67: void noct_rng_enable(struct noct_softc *);
                     68: void noct_rng_disable(struct noct_softc *);
                     69: void noct_rng_init(struct noct_softc *);
                     70: void noct_rng_intr(struct noct_softc *);
                     71: void noct_rng_tick(void *);
                     72:
                     73: void noct_pkh_enable(struct noct_softc *);
                     74: void noct_pkh_disable(struct noct_softc *);
                     75: void noct_pkh_init(struct noct_softc *);
                     76: void noct_pkh_intr(struct noct_softc *);
                     77: void noct_pkh_freedesc(struct noct_softc *, int);
                     78: u_int32_t noct_pkh_nfree(struct noct_softc *);
                     79: int noct_kload(struct noct_softc *, struct crparam *, u_int32_t);
                     80: void noct_kload_cb(struct noct_softc *, u_int32_t, int);
                     81: void noct_modmul_cb(struct noct_softc *, u_int32_t, int);
                     82:
                     83: void noct_ea_enable(struct noct_softc *);
                     84: void noct_ea_disable(struct noct_softc *);
                     85: void noct_ea_init(struct noct_softc *);
                     86: void noct_ea_intr(struct noct_softc *);
                     87: void noct_ea_create_thread(void *);
                     88: void noct_ea_thread(void *);
                     89: u_int32_t noct_ea_nfree(struct noct_softc *);
                     90: void noct_ea_start(struct noct_softc *, struct noct_workq *);
                     91: void noct_ea_start_hash(struct noct_softc *, struct noct_workq *,
                     92:     struct cryptop *, struct cryptodesc *);
                     93: void noct_ea_start_des(struct noct_softc *, struct noct_workq *,
                     94:     struct cryptop *, struct cryptodesc *);
                     95: int noct_newsession(u_int32_t *, struct cryptoini *);
                     96: int noct_freesession(u_int64_t);
                     97: int noct_process(struct cryptop *);
                     98:
                     99: u_int32_t noct_read_4(struct noct_softc *, bus_size_t);
                    100: void noct_write_4(struct noct_softc *, bus_size_t, u_int32_t);
                    101: u_int64_t noct_read_8(struct noct_softc *, u_int32_t);
                    102: void noct_write_8(struct noct_softc *, u_int32_t, u_int64_t);
                    103:
                    104: struct noct_softc *noct_kfind(struct cryptkop *);
                    105: int noct_ksigbits(struct crparam *);
                    106: int noct_kprocess(struct cryptkop *);
                    107: int noct_kprocess_modexp(struct noct_softc *, struct cryptkop *);
                    108:
                    109: struct cfattach noct_ca = {
                    110:        sizeof(struct noct_softc), noct_probe, noct_attach,
                    111: };
                    112:
                    113: struct cfdriver noct_cd = {
                    114:        0, "noct", DV_DULL
                    115: };
                    116:
                    117: #define        SWAP32(x) (x) = htole32(ntohl((x)))
                    118:
                    119: int
                    120: noct_probe(parent, match, aux)
                    121:        struct device *parent;
                    122:        void *match;
                    123:        void *aux;
                    124: {
                    125:        struct pci_attach_args *pa = (struct pci_attach_args *) aux;
                    126:
                    127:        if (PCI_VENDOR(pa->pa_id) == PCI_VENDOR_NETOCTAVE &&
                    128:            PCI_PRODUCT(pa->pa_id) == PCI_PRODUCT_NETOCTAVE_NSP2K)
                    129:                return (1);
                    130:        return (0);
                    131: }
                    132:
                    133: void
                    134: noct_attach(parent, self, aux)
                    135:        struct device *parent, *self;
                    136:        void *aux;
                    137: {
                    138:        struct noct_softc *sc = (struct noct_softc *)self;
                    139:        struct pci_attach_args *pa = aux;
                    140:        pci_chipset_tag_t pc = pa->pa_pc;
                    141:        pci_intr_handle_t ih;
                    142:        const char *intrstr = NULL;
                    143:        bus_size_t iosize = 0;
                    144:
                    145:        if (pci_mapreg_map(pa, NOCT_BAR0, PCI_MAPREG_MEM_TYPE_64BIT, 0,
                    146:            &sc->sc_st, &sc->sc_sh, NULL, &iosize, 0)) {
                    147:                printf(": can't map mem space\n");
                    148:                goto fail;
                    149:        }
                    150:
                    151:        /* Before we do anything else, put the chip in little endian mode */
                    152:        NOCT_WRITE_4(sc, NOCT_BRDG_ENDIAN, 0);
                    153:        sc->sc_rar_last = 0xffffffff;
                    154:        sc->sc_waw_last = 0xffffffff;
                    155:        sc->sc_dmat = pa->pa_dmat;
                    156:
                    157:        sc->sc_cid = crypto_get_driverid(0);
                    158:        if (sc->sc_cid < 0) {
                    159:                printf(": couldn't register cid\n");
                    160:                goto fail;
                    161:        }
                    162:
                    163:        if (pci_intr_map(pa, &ih)) {
                    164:                printf(": couldn't map interrupt\n");
                    165:                goto fail;
                    166:        }
                    167:        intrstr = pci_intr_string(pc, ih);
                    168:        sc->sc_ih = pci_intr_establish(pc, ih, IPL_NET, noct_intr, sc,
                    169:            self->dv_xname);
                    170:        if (sc->sc_ih == NULL) {
                    171:                printf(": couldn't establish interrupt");
                    172:                if (intrstr != NULL)
                    173:                        printf(" at %s", intrstr);
                    174:                printf("\n");
                    175:                goto fail;
                    176:        }
                    177:
                    178:        if (noct_ram_size(sc))
                    179:                goto fail;
                    180:
                    181:        printf(":");
                    182:
                    183:        noct_rng_init(sc);
                    184:        noct_pkh_init(sc);
                    185:        noct_ea_init(sc);
                    186:
                    187:        printf(", %uMB, %s\n", sc->sc_ramsize, intrstr);
                    188:
                    189:        return;
                    190:
                    191: fail:
                    192:        if (iosize != 0)
                    193:                bus_space_unmap(sc->sc_st, sc->sc_sh, iosize);
                    194: }
                    195:
                    196: int
                    197: noct_intr(vsc)
                    198:        void *vsc;
                    199: {
                    200:        struct noct_softc *sc = vsc;
                    201:        u_int32_t reg;
                    202:        int r = 0;
                    203:
                    204:        reg = NOCT_READ_4(sc, NOCT_BRDG_STAT);
                    205:
                    206:        if (reg & BRDGSTS_RNG_INT) {
                    207:                r = 1;
                    208:                noct_rng_intr(sc);
                    209:        }
                    210:
                    211:        if (reg & BRDGSTS_PKP_INT) {
                    212:                r = 1;
                    213:                noct_pkh_intr(sc);
                    214:        }
                    215:
                    216:        if (reg & BRDGSTS_CCH_INT) {
                    217:                r = 1;
                    218:                noct_ea_intr(sc);
                    219:        }
                    220:
                    221:        return (r);
                    222: }
                    223:
                    224: int
                    225: noct_ram_size(sc)
                    226:        struct noct_softc *sc;
                    227: {
                    228:        u_int64_t t;
                    229:
                    230:        noct_ram_write(sc, 0x000000, 64);
                    231:        noct_ram_write(sc, 0x400000, 32);
                    232:        t = noct_ram_read(sc, 0x000000);
                    233:        noct_ram_write(sc, 0x000000, 128);
                    234:        noct_ram_write(sc, 0x800000, t);
                    235:        t = noct_ram_read(sc, 0x000000);
                    236:
                    237:        if (t != 32 && t != 64 && t != 128) {
                    238:                printf(": invalid ram size %llx\n", (unsigned long long)t);
                    239:                return (1);
                    240:        }
                    241:
                    242:        sc->sc_ramsize = t;
                    243:        return (0);
                    244: }
                    245:
                    246: void
                    247: noct_ram_write(sc, adr, dat)
                    248:        struct noct_softc *sc;
                    249:        u_int32_t adr;
                    250:        u_int64_t dat;
                    251: {
                    252:        u_int32_t reg;
                    253:
                    254:        /* wait for pending writes to finish */
                    255:        for (;;) {
                    256:                reg = NOCT_READ_4(sc, NOCT_EA_CTX_ADDR);
                    257:                if ((reg & EACTXADDR_WRITEPEND) == 0)
                    258:                        break;
                    259:        }
                    260:
                    261:        NOCT_WRITE_4(sc, NOCT_EA_CTX_ADDR, adr);
                    262:        NOCT_WRITE_4(sc, NOCT_EA_CTX_DAT_1, (dat >> 32) & 0xffffffff);
                    263:        NOCT_WRITE_4(sc, NOCT_EA_CTX_DAT_0, (dat >>  0) & 0xffffffff);
                    264:
                    265:        for (;;) {
                    266:                reg = NOCT_READ_4(sc, NOCT_EA_CTX_ADDR);
                    267:                if ((reg & EACTXADDR_WRITEPEND) == 0)
                    268:                        break;
                    269:        }
                    270: }
                    271:
                    272: u_int64_t
                    273: noct_ram_read(sc, adr)
                    274:        struct noct_softc *sc;
                    275:        u_int32_t adr;
                    276: {
                    277:        u_int64_t dat;
                    278:        u_int32_t reg;
                    279:
                    280:        /* wait for pending reads to finish */
                    281:        for (;;) {
                    282:                reg = NOCT_READ_4(sc, NOCT_EA_CTX_ADDR);
                    283:                if ((reg & EACTXADDR_READPEND) == 0)
                    284:                        break;
                    285:        }
                    286:
                    287:        NOCT_WRITE_4(sc, NOCT_EA_CTX_ADDR, adr | EACTXADDR_READPEND);
                    288:
                    289:        for (;;) {
                    290:                reg = NOCT_READ_4(sc, NOCT_EA_CTX_ADDR);
                    291:                if ((reg & EACTXADDR_READPEND) == 0)
                    292:                        break;
                    293:        }
                    294:
                    295:        dat = NOCT_READ_4(sc, NOCT_EA_CTX_DAT_1);
                    296:        dat <<= 32;
                    297:        dat |= NOCT_READ_4(sc, NOCT_EA_CTX_DAT_0);
                    298:        return (dat);
                    299: }
                    300:
                    301: void
                    302: noct_pkh_disable(sc)
                    303:        struct noct_softc *sc;
                    304: {
                    305:        u_int32_t r;
                    306:
                    307:        /* Turn off PK irq */
                    308:        NOCT_WRITE_4(sc, NOCT_BRDG_CTL,
                    309:            NOCT_READ_4(sc, NOCT_BRDG_CTL) & ~(BRDGCTL_PKIRQ_ENA));
                    310:
                    311:        /* Turn off PK interrupts */
                    312:        r = NOCT_READ_4(sc, NOCT_PKH_IER);
                    313:        r &= ~(PKHIER_CMDSI | PKHIER_SKSWR | PKHIER_SKSOFF | PKHIER_PKHLEN |
                    314:            PKHIER_PKHOPCODE | PKHIER_BADQBASE | PKHIER_LOADERR |
                    315:            PKHIER_STOREERR | PKHIER_CMDERR | PKHIER_ILL | PKHIER_PKERESV |
                    316:            PKHIER_PKEWDT | PKHIER_PKENOTPRIME |
                    317:            PKHIER_PKE_B | PKHIER_PKE_A | PKHIER_PKE_M | PKHIER_PKE_R |
                    318:            PKHIER_PKEOPCODE);
                    319:        NOCT_WRITE_4(sc, NOCT_PKH_IER, r);
                    320:
                    321:        /* Disable PK unit */
                    322:        r = NOCT_READ_4(sc, NOCT_PKH_CSR);
                    323:        r &= ~PKHCSR_PKH_ENA;
                    324:        NOCT_WRITE_4(sc, NOCT_PKH_CSR, r);
                    325:        for (;;) {
                    326:                r = NOCT_READ_4(sc, NOCT_PKH_CSR);
                    327:                if ((r & PKHCSR_PKH_BUSY) == 0)
                    328:                        break;
                    329:        }
                    330:
                    331:        /* Clear status bits */
                    332:        r |= PKHCSR_CMDSI | PKHCSR_SKSWR | PKHCSR_SKSOFF | PKHCSR_PKHLEN |
                    333:            PKHCSR_PKHOPCODE | PKHCSR_BADQBASE | PKHCSR_LOADERR |
                    334:            PKHCSR_STOREERR | PKHCSR_CMDERR | PKHCSR_ILL | PKHCSR_PKERESV |
                    335:            PKHCSR_PKEWDT | PKHCSR_PKENOTPRIME |
                    336:            PKHCSR_PKE_B | PKHCSR_PKE_A | PKHCSR_PKE_M | PKHCSR_PKE_R |
                    337:            PKHCSR_PKEOPCODE;
                    338:        NOCT_WRITE_4(sc, NOCT_PKH_CSR, r);
                    339: }
                    340:
                    341: void
                    342: noct_pkh_enable(sc)
                    343:        struct noct_softc *sc;
                    344: {
                    345:        u_int64_t adr;
                    346:
                    347:        sc->sc_pkhwp = 0;
                    348:        sc->sc_pkhrp = 0;
                    349:
                    350:        adr = sc->sc_pkhmap->dm_segs[0].ds_addr;
                    351:        NOCT_WRITE_4(sc, NOCT_PKH_Q_BASE_HI, (adr >> 32) & 0xffffffff);
                    352:        NOCT_WRITE_4(sc, NOCT_PKH_Q_LEN, NOCT_PKH_QLEN);
                    353:        NOCT_WRITE_4(sc, NOCT_PKH_Q_BASE_LO, (adr >> 0) & 0xffffffff);
                    354:
                    355:        NOCT_WRITE_4(sc, NOCT_PKH_IER,
                    356:            PKHIER_CMDSI | PKHIER_SKSWR | PKHIER_SKSOFF | PKHIER_PKHLEN |
                    357:            PKHIER_PKHOPCODE | PKHIER_BADQBASE | PKHIER_LOADERR |
                    358:            PKHIER_STOREERR | PKHIER_CMDERR | PKHIER_ILL | PKHIER_PKERESV |
                    359:            PKHIER_PKEWDT | PKHIER_PKENOTPRIME |
                    360:            PKHIER_PKE_B | PKHIER_PKE_A | PKHIER_PKE_M | PKHIER_PKE_R |
                    361:            PKHIER_PKEOPCODE);
                    362:
                    363:        NOCT_WRITE_4(sc, NOCT_PKH_CSR,
                    364:            NOCT_READ_4(sc, NOCT_PKH_CSR) | PKHCSR_PKH_ENA);
                    365:
                    366:        NOCT_WRITE_4(sc, NOCT_BRDG_CTL,
                    367:            NOCT_READ_4(sc, NOCT_BRDG_CTL) | BRDGCTL_PKIRQ_ENA);
                    368: }
                    369:
                    370: void
                    371: noct_pkh_init(sc)
                    372:        struct noct_softc *sc;
                    373: {
                    374:        bus_dma_segment_t seg, bnseg;
                    375:        int rseg, bnrseg;
                    376:
                    377:        sc->sc_pkh_bn = extent_create("noctbn", 0, 255, M_DEVBUF,
                    378:            NULL, NULL, EX_NOWAIT | EX_NOCOALESCE);
                    379:        if (sc->sc_pkh_bn == NULL) {
                    380:                printf("%s: failed pkh bn extent\n", sc->sc_dv.dv_xname);
                    381:                goto fail;
                    382:        }
                    383:
                    384:        if (bus_dmamem_alloc(sc->sc_dmat, NOCT_PKH_BUFSIZE,
                    385:            PAGE_SIZE, 0, &seg, 1, &rseg, BUS_DMA_NOWAIT)) {
                    386:                printf("%s: failed pkh buf alloc\n", sc->sc_dv.dv_xname);
                    387:                goto fail;
                    388:        }
                    389:        if (bus_dmamem_map(sc->sc_dmat, &seg, rseg, NOCT_PKH_BUFSIZE,
                    390:            (caddr_t *)&sc->sc_pkhcmd, BUS_DMA_NOWAIT)) {
                    391:                printf("%s: failed pkh buf map\n", sc->sc_dv.dv_xname);
                    392:                goto fail_1;
                    393:        }
                    394:        if (bus_dmamap_create(sc->sc_dmat, NOCT_PKH_BUFSIZE, rseg,
                    395:            NOCT_PKH_BUFSIZE, 0, BUS_DMA_NOWAIT, &sc->sc_pkhmap)) {
                    396:                printf("%s: failed pkh map create\n", sc->sc_dv.dv_xname);
                    397:                goto fail_2;
                    398:        }
                    399:        if (bus_dmamap_load_raw(sc->sc_dmat, sc->sc_pkhmap,
                    400:            &seg, rseg, NOCT_PKH_BUFSIZE, BUS_DMA_NOWAIT)) {
                    401:                printf("%s: failed pkh buf load\n", sc->sc_dv.dv_xname);
                    402:                goto fail_3;
                    403:        }
                    404:
                    405:        /*
                    406:         * Allocate shadow big number cache.
                    407:         */
                    408:        if (bus_dmamem_alloc(sc->sc_dmat, NOCT_BN_CACHE_SIZE, PAGE_SIZE, 0,
                    409:            &bnseg, 1, &bnrseg, BUS_DMA_NOWAIT)) {
                    410:                printf("%s: failed bnc buf alloc\n", sc->sc_dv.dv_xname);
                    411:                goto fail_4;
                    412:        }
                    413:        if (bus_dmamem_map(sc->sc_dmat, &bnseg, bnrseg, NOCT_BN_CACHE_SIZE,
                    414:            (caddr_t *)&sc->sc_bncache, BUS_DMA_NOWAIT)) {
                    415:                printf("%s: failed bnc buf map\n", sc->sc_dv.dv_xname);
                    416:                goto fail_5;
                    417:        }
                    418:        if (bus_dmamap_create(sc->sc_dmat, NOCT_BN_CACHE_SIZE, bnrseg,
                    419:            NOCT_BN_CACHE_SIZE, 0, BUS_DMA_NOWAIT, &sc->sc_bnmap)) {
                    420:                printf("%s: failed bnc map create\n", sc->sc_dv.dv_xname);
                    421:                goto fail_6;
                    422:        }
                    423:        if (bus_dmamap_load_raw(sc->sc_dmat, sc->sc_bnmap,
                    424:            &bnseg, bnrseg, NOCT_BN_CACHE_SIZE, BUS_DMA_NOWAIT)) {
                    425:                printf("%s: failed bnc buf load\n", sc->sc_dv.dv_xname);
                    426:                goto fail_7;
                    427:        }
                    428:
                    429:        noct_pkh_disable(sc);
                    430:        noct_pkh_enable(sc);
                    431:
                    432: #if 0
                    433:        /*
                    434:         * XXX MODEXP is implemented as MODMUL for debugging, don't
                    435:         * XXX actually register.
                    436:         */
                    437:        crypto_kregister(sc->sc_cid, CRK_MOD_EXP, 0, noct_kprocess);
                    438:        printf(" PK");
                    439: #endif
                    440:
                    441:        return;
                    442:
                    443: fail_7:
                    444:        bus_dmamap_destroy(sc->sc_dmat, sc->sc_bnmap);
                    445: fail_6:
                    446:        bus_dmamem_unmap(sc->sc_dmat,
                    447:            (caddr_t)sc->sc_pkhcmd, NOCT_PKH_BUFSIZE);
                    448: fail_5:
                    449:        bus_dmamem_free(sc->sc_dmat, &bnseg, bnrseg);
                    450: fail_4:
                    451:        bus_dmamap_unload(sc->sc_dmat, sc->sc_pkhmap);
                    452: fail_3:
                    453:        bus_dmamap_destroy(sc->sc_dmat, sc->sc_pkhmap);
                    454: fail_2:
                    455:        bus_dmamem_unmap(sc->sc_dmat,
                    456:            (caddr_t)sc->sc_pkhcmd, NOCT_PKH_BUFSIZE);
                    457: fail_1:
                    458:        bus_dmamem_free(sc->sc_dmat, &seg, rseg);
                    459: fail:
                    460:        if (sc->sc_pkh_bn != NULL) {
                    461:                extent_destroy(sc->sc_pkh_bn);
                    462:                sc->sc_pkh_bn = NULL;
                    463:        }
                    464:        sc->sc_pkhcmd = NULL;
                    465:        sc->sc_pkhmap = NULL;
                    466: }
                    467:
                    468: void
                    469: noct_pkh_intr(sc)
                    470:        struct noct_softc *sc;
                    471: {
                    472:        u_int32_t csr;
                    473:        u_int32_t rp;
                    474:
                    475:        csr = NOCT_READ_4(sc, NOCT_PKH_CSR);
                    476:        NOCT_WRITE_4(sc, NOCT_PKH_CSR, csr |
                    477:            PKHCSR_CMDSI | PKHCSR_SKSWR | PKHCSR_SKSOFF | PKHCSR_PKHLEN |
                    478:            PKHCSR_PKHOPCODE | PKHCSR_BADQBASE | PKHCSR_LOADERR |
                    479:            PKHCSR_STOREERR | PKHCSR_CMDERR | PKHCSR_ILL | PKHCSR_PKERESV |
                    480:            PKHCSR_PKEWDT | PKHCSR_PKENOTPRIME |
                    481:            PKHCSR_PKE_B | PKHCSR_PKE_A | PKHCSR_PKE_M | PKHCSR_PKE_R |
                    482:            PKHCSR_PKEOPCODE);
                    483:
                    484:        rp = (NOCT_READ_4(sc, NOCT_PKH_Q_PTR) & PKHQPTR_READ_M) >>
                    485:            PKHQPTR_READ_S;
                    486:
                    487:        while (sc->sc_pkhrp != rp) {
                    488:                if (sc->sc_pkh_bnsw[sc->sc_pkhrp].bn_callback != NULL)
                    489:                        (*sc->sc_pkh_bnsw[sc->sc_pkhrp].bn_callback)(sc,
                    490:                            sc->sc_pkhrp, 0);
                    491:                if (++sc->sc_pkhrp == NOCT_PKH_ENTRIES)
                    492:                        sc->sc_pkhrp = 0;
                    493:        }
                    494:        sc->sc_pkhrp = rp;
                    495:
                    496:        if (csr & PKHCSR_CMDSI) {
                    497:                /* command completed */
                    498:        }
                    499:
                    500:        if (csr & PKHCSR_SKSWR)
                    501:                printf("%s:%x: sks write error\n", sc->sc_dv.dv_xname, rp);
                    502:        if (csr & PKHCSR_SKSOFF)
                    503:                printf("%s:%x: sks offset error\n", sc->sc_dv.dv_xname, rp);
                    504:        if (csr & PKHCSR_PKHLEN)
                    505:                printf("%s:%x: pkh invalid length\n", sc->sc_dv.dv_xname, rp);
                    506:        if (csr & PKHCSR_PKHOPCODE)
                    507:                printf("%s:%x: pkh bad opcode\n", sc->sc_dv.dv_xname, rp);
                    508:        if (csr & PKHCSR_BADQBASE)
                    509:                printf("%s:%x: pkh base qbase\n", sc->sc_dv.dv_xname, rp);
                    510:        if (csr & PKHCSR_LOADERR)
                    511:                printf("%s:%x: pkh load error\n", sc->sc_dv.dv_xname, rp);
                    512:        if (csr & PKHCSR_STOREERR)
                    513:                printf("%s:%x: pkh store error\n", sc->sc_dv.dv_xname, rp);
                    514:        if (csr & PKHCSR_CMDERR)
                    515:                printf("%s:%x: pkh command error\n", sc->sc_dv.dv_xname, rp);
                    516:        if (csr & PKHCSR_ILL)
                    517:                printf("%s:%x: pkh illegal access\n", sc->sc_dv.dv_xname, rp);
                    518:        if (csr & PKHCSR_PKERESV)
                    519:                printf("%s:%x: pke reserved error\n", sc->sc_dv.dv_xname, rp);
                    520:        if (csr & PKHCSR_PKEWDT)
                    521:                printf("%s:%x: pke watchdog\n", sc->sc_dv.dv_xname, rp);
                    522:        if (csr & PKHCSR_PKENOTPRIME)
                    523:                printf("%s:%x: pke not prime\n", sc->sc_dv.dv_xname, rp);
                    524:        if (csr & PKHCSR_PKE_B)
                    525:                printf("%s:%x: pke bad 'b'\n", sc->sc_dv.dv_xname, rp);
                    526:        if (csr & PKHCSR_PKE_A)
                    527:                printf("%s:%x: pke bad 'a'\n", sc->sc_dv.dv_xname, rp);
                    528:        if (csr & PKHCSR_PKE_M)
                    529:                printf("%s:%x: pke bad 'm'\n", sc->sc_dv.dv_xname, rp);
                    530:        if (csr & PKHCSR_PKE_R)
                    531:                printf("%s:%x: pke bad 'r'\n", sc->sc_dv.dv_xname, rp);
                    532:        if (csr & PKHCSR_PKEOPCODE)
                    533:                printf("%s:%x: pke bad opcode\n", sc->sc_dv.dv_xname, rp);
                    534: }
                    535:
                    536: void
                    537: noct_rng_disable(sc)
                    538:        struct noct_softc *sc;
                    539: {
                    540:        u_int64_t csr;
                    541:        u_int32_t r;
                    542:
                    543:        /* Turn off RN irq */
                    544:        NOCT_WRITE_4(sc, NOCT_BRDG_CTL,
                    545:            NOCT_READ_4(sc, NOCT_BRDG_CTL) & ~(BRDGCTL_RNIRQ_ENA));
                    546:
                    547:        /* Turn off RNH interrupts */
                    548:        r = NOCT_READ_4(sc, NOCT_RNG_CSR);
                    549:        r &= ~(RNGCSR_INT_KEY | RNGCSR_INT_DUP |
                    550:            RNGCSR_INT_BUS | RNGCSR_INT_ACCESS);
                    551:        NOCT_WRITE_4(sc, NOCT_RNG_CSR, r);
                    552:
                    553:        /* Turn off RN queue */
                    554:        r = NOCT_READ_4(sc, NOCT_RNG_CSR);
                    555:        r &= ~(RNGCSR_XFER_ENABLE | RNGCSR_INT_KEY | RNGCSR_INT_BUS |
                    556:            RNGCSR_INT_DUP | RNGCSR_INT_ACCESS);
                    557:        NOCT_WRITE_4(sc, NOCT_RNG_CSR, r);
                    558:
                    559:        for (;;) {
                    560:                r = NOCT_READ_4(sc, NOCT_RNG_CSR);
                    561:                if ((r & RNGCSR_XFER_BUSY) == 0)
                    562:                        break;
                    563:        }
                    564:
                    565:        /* Turn off RN generator */
                    566:        csr = NOCT_READ_8(sc, NOCT_RNG_CTL);
                    567:        csr &= ~RNGCTL_RNG_ENA;
                    568:        NOCT_WRITE_8(sc, NOCT_RNG_CTL, csr);
                    569: }
                    570:
                    571: void
                    572: noct_rng_enable(sc)
                    573:        struct noct_softc *sc;
                    574: {
                    575:        u_int64_t adr;
                    576:        u_int32_t r;
                    577:
                    578:        adr = sc->sc_rngmap->dm_segs[0].ds_addr;
                    579:        NOCT_WRITE_4(sc, NOCT_RNG_Q_BASE_HI, (adr >> 32) & 0xffffffff);
                    580:        NOCT_WRITE_4(sc, NOCT_RNG_Q_LEN, NOCT_RNG_QLEN);
                    581:        NOCT_WRITE_4(sc, NOCT_RNG_Q_BASE_LO, (adr >> 0 ) & 0xffffffff);
                    582:
                    583:        NOCT_WRITE_8(sc, NOCT_RNG_CTL,
                    584:            RNGCTL_RNG_ENA |
                    585:            RNGCTL_TOD_ENA |
                    586:            RNGCTL_BUFSRC_SEED |
                    587:            RNGCTL_SEEDSRC_INT |
                    588:            RNGCTL_EXTCLK_ENA |
                    589:            RNGCTL_DIAG |
                    590:            (100 & RNGCTL_ITERCNT));
                    591:
                    592:        /* Turn on interrupts and enable xfer */
                    593:        r = RNGCSR_XFER_ENABLE | RNGCSR_INT_ACCESS |
                    594:            RNGCSR_INT_KEY | RNGCSR_INT_BUS | RNGCSR_INT_DUP;
                    595:        NOCT_WRITE_4(sc, NOCT_RNG_CSR, r);
                    596:
                    597:        /* Turn on bridge/rng interrupts */
                    598:        r = NOCT_READ_4(sc, NOCT_BRDG_CTL);
                    599:        r |= BRDGCTL_RNIRQ_ENA;
                    600:        NOCT_WRITE_4(sc, NOCT_BRDG_CTL, r);
                    601: }
                    602:
                    603: void
                    604: noct_rng_init(sc)
                    605:        struct noct_softc *sc;
                    606: {
                    607:        bus_dma_segment_t seg;
                    608:        int rseg;
                    609:
                    610:        if (bus_dmamem_alloc(sc->sc_dmat, NOCT_RNG_BUFSIZE,
                    611:            PAGE_SIZE, 0, &seg, 1, &rseg, BUS_DMA_NOWAIT)) {
                    612:                printf("%s: failed rng buf alloc\n", sc->sc_dv.dv_xname);
                    613:                goto fail;
                    614:        }
                    615:        if (bus_dmamem_map(sc->sc_dmat, &seg, rseg, NOCT_RNG_BUFSIZE,
                    616:            (caddr_t *)&sc->sc_rngbuf, BUS_DMA_NOWAIT)) {
                    617:                printf("%s: failed rng buf map\n", sc->sc_dv.dv_xname);
                    618:                goto fail_1;
                    619:        }
                    620:        if (bus_dmamap_create(sc->sc_dmat, NOCT_RNG_BUFSIZE, rseg,
                    621:            NOCT_RNG_BUFSIZE, 0, BUS_DMA_NOWAIT, &sc->sc_rngmap)) {
                    622:                printf("%s: failed rng map create\n", sc->sc_dv.dv_xname);
                    623:                goto fail_2;
                    624:        }
                    625:        if (bus_dmamap_load_raw(sc->sc_dmat, sc->sc_rngmap,
                    626:            &seg, rseg, NOCT_RNG_BUFSIZE, BUS_DMA_NOWAIT)) {
                    627:                printf("%s: failed rng buf load\n", sc->sc_dv.dv_xname);
                    628:                goto fail_3;
                    629:        }
                    630:
                    631:        noct_rng_disable(sc);
                    632:        noct_rng_enable(sc);
                    633:
                    634:        printf(" RNG");
                    635:
                    636:        if (hz > 100)
                    637:                sc->sc_rngtick = hz/100;
                    638:        else
                    639:                sc->sc_rngtick = 1;
                    640:        timeout_set(&sc->sc_rngto, noct_rng_tick, sc);
                    641:        timeout_add(&sc->sc_rngto, sc->sc_rngtick);
                    642:
                    643:        return;
                    644:
                    645: fail_3:
                    646:        bus_dmamap_destroy(sc->sc_dmat, sc->sc_rngmap);
                    647: fail_2:
                    648:        bus_dmamem_unmap(sc->sc_dmat,
                    649:            (caddr_t)sc->sc_rngbuf, NOCT_RNG_BUFSIZE);
                    650: fail_1:
                    651:        bus_dmamem_free(sc->sc_dmat, &seg, rseg);
                    652: fail:
                    653:        sc->sc_rngbuf = NULL;
                    654:        sc->sc_rngmap = NULL;
                    655: }
                    656:
                    657: void
                    658: noct_rng_intr(sc)
                    659:        struct noct_softc *sc;
                    660: {
                    661:        u_int32_t csr;
                    662:        int enable = 1;
                    663:
                    664:        csr = NOCT_READ_4(sc, NOCT_RNG_CSR);
                    665:        NOCT_WRITE_4(sc, NOCT_RNG_CSR, csr);
                    666:
                    667:        if (csr & RNGCSR_ERR_KEY) {
                    668:                u_int32_t ctl;
                    669:
                    670:                enable = 0;
                    671:                ctl = NOCT_READ_4(sc, NOCT_RNG_CTL);
                    672:                printf("%s: rng bad key(s)", sc->sc_dv.dv_xname);
                    673:                if (ctl & RNGCTL_KEY1PAR_ERR)
                    674:                        printf(", key1 parity");
                    675:                if (ctl & RNGCTL_KEY2PAR_ERR)
                    676:                        printf(", key2 parity");
                    677:                printf("\n");
                    678:        }
                    679:        if (csr & RNGCSR_ERR_BUS) {
                    680:                enable = 0;
                    681:                printf("%s: rng bus error\n", sc->sc_dv.dv_xname);
                    682:        }
                    683:        if (csr & RNGCSR_ERR_DUP) {
                    684:                enable = 0;
                    685:                printf("%s: rng duplicate block\n", sc->sc_dv.dv_xname);
                    686:        }
                    687:        if (csr & RNGCSR_ERR_ACCESS) {
                    688:                enable = 0;
                    689:                printf("%s: rng invalid access\n", sc->sc_dv.dv_xname);
                    690:        }
                    691:
                    692:        if (!enable)
                    693:                noct_rng_disable(sc);
                    694: }
                    695:
                    696: void
                    697: noct_rng_tick(vsc)
                    698:        void *vsc;
                    699: {
                    700:        struct noct_softc *sc = vsc;
                    701:        u_int64_t val;
                    702:        u_int32_t reg, rd, wr;
                    703:        int cons = 0;
                    704:
                    705:        reg = NOCT_READ_4(sc, NOCT_RNG_Q_PTR);
                    706:        rd = (reg & RNGQPTR_READ_M) >> RNGQPTR_READ_S;
                    707:        wr = (reg & RNGQPTR_WRITE_M) >> RNGQPTR_WRITE_S;
                    708:
                    709:        while (rd != wr && cons < 32) {
                    710:                val = sc->sc_rngbuf[rd];
                    711:                add_true_randomness((val >> 32) & 0xffffffff);
                    712:                add_true_randomness((val >> 0) & 0xffffffff);
                    713:                if (++rd == NOCT_RNG_ENTRIES)
                    714:                        rd = 0;
                    715:                cons++;
                    716:        }
                    717:
                    718:        if (cons != 0)
                    719:                NOCT_WRITE_4(sc, NOCT_RNG_Q_PTR, rd);
                    720:        timeout_add(&sc->sc_rngto, sc->sc_rngtick);
                    721: }
                    722:
                    723: u_int32_t
                    724: noct_ea_nfree(sc)
                    725:        struct noct_softc *sc;
                    726: {
                    727:        if (sc->sc_eawp == sc->sc_earp)
                    728:                return (NOCT_EA_ENTRIES);
                    729:        if (sc->sc_eawp < sc->sc_earp)
                    730:                return (sc->sc_earp - sc->sc_eawp - 1);
                    731:        return (sc->sc_earp + NOCT_EA_ENTRIES - sc->sc_eawp - 1);
                    732: }
                    733:
                    734: void
                    735: noct_ea_disable(sc)
                    736:        struct noct_softc *sc;
                    737: {
                    738:        u_int32_t r;
                    739:
                    740:        /* Turn off EA irq */
                    741:        NOCT_WRITE_4(sc, NOCT_BRDG_CTL,
                    742:            NOCT_READ_4(sc, NOCT_BRDG_CTL) & ~(BRDGCTL_EAIRQ_ENA));
                    743:
                    744:        /* Turn off EA interrupts */
                    745:        r = NOCT_READ_4(sc, NOCT_EA_IER);
                    746:        r &= ~(EAIER_QALIGN | EAIER_CMDCMPL | EAIER_OPERR | EAIER_CMDREAD |
                    747:            EAIER_CMDWRITE | EAIER_DATAREAD | EAIER_DATAWRITE |
                    748:            EAIER_INTRNLLEN | EAIER_EXTRNLLEN | EAIER_DESBLOCK |
                    749:            EAIER_DESKEY | EAIER_ILL);
                    750:        NOCT_WRITE_4(sc, NOCT_EA_IER, r);
                    751:
                    752:        /* Disable EA unit */
                    753:        r = NOCT_READ_4(sc, NOCT_EA_CSR);
                    754:        r &= ~EACSR_ENABLE;
                    755:        NOCT_WRITE_4(sc, NOCT_EA_CSR, r);
                    756:        for (;;) {
                    757:                r = NOCT_READ_4(sc, NOCT_EA_CSR);
                    758:                if ((r & EACSR_BUSY) == 0)
                    759:                        break;
                    760:        }
                    761:
                    762:        /* Clear status bits */
                    763:        r = NOCT_READ_4(sc, NOCT_EA_CSR);
                    764:        r |= EACSR_QALIGN | EACSR_CMDCMPL | EACSR_OPERR | EACSR_CMDREAD |
                    765:            EACSR_CMDWRITE | EACSR_DATAREAD | EACSR_DATAWRITE |
                    766:            EACSR_INTRNLLEN | EACSR_EXTRNLLEN | EACSR_DESBLOCK |
                    767:            EACSR_DESKEY | EACSR_ILL;
                    768:        NOCT_WRITE_4(sc, NOCT_EA_CSR, r);
                    769: }
                    770:
                    771: void
                    772: noct_ea_enable(sc)
                    773:        struct noct_softc *sc;
                    774: {
                    775:        u_int64_t adr;
                    776:
                    777:        sc->sc_eawp = 0;
                    778:        sc->sc_earp = 0;
                    779:
                    780:        adr = sc->sc_eamap->dm_segs[0].ds_addr;
                    781:        NOCT_WRITE_4(sc, NOCT_EA_Q_BASE_HI, (adr >> 32) & 0xffffffff);
                    782:        NOCT_WRITE_4(sc, NOCT_EA_Q_LEN, NOCT_EA_QLEN);
                    783:        NOCT_WRITE_4(sc, NOCT_EA_Q_BASE_LO, (adr >> 0) & 0xffffffff);
                    784:
                    785:        NOCT_WRITE_4(sc, NOCT_EA_IER,
                    786:            EAIER_QALIGN | EAIER_CMDCMPL | EAIER_OPERR | EAIER_CMDREAD |
                    787:            EAIER_CMDWRITE | EAIER_DATAREAD | EAIER_DATAWRITE |
                    788:            EAIER_INTRNLLEN | EAIER_EXTRNLLEN | EAIER_DESBLOCK |
                    789:            EAIER_DESKEY | EAIER_ILL);
                    790:
                    791:        NOCT_WRITE_4(sc, NOCT_EA_CSR,
                    792:            NOCT_READ_4(sc, NOCT_EA_CSR) | EACSR_ENABLE);
                    793:
                    794:        NOCT_WRITE_4(sc, NOCT_BRDG_CTL,
                    795:            NOCT_READ_4(sc, NOCT_BRDG_CTL) | BRDGCTL_EAIRQ_ENA);
                    796: }
                    797:
                    798: void
                    799: noct_ea_init(sc)
                    800:        struct noct_softc *sc;
                    801: {
                    802:        bus_dma_segment_t seg;
                    803:        int rseg, algs[CRYPTO_ALGORITHM_MAX + 1];
                    804:
                    805:        if (bus_dmamem_alloc(sc->sc_dmat, NOCT_EA_BUFSIZE,
                    806:            PAGE_SIZE, 0, &seg, 1, &rseg, BUS_DMA_NOWAIT)) {
                    807:                printf("%s: failed ea buf alloc\n", sc->sc_dv.dv_xname);
                    808:                goto fail;
                    809:        }
                    810:        if (bus_dmamem_map(sc->sc_dmat, &seg, rseg, NOCT_EA_BUFSIZE,
                    811:            (caddr_t *)&sc->sc_eacmd, BUS_DMA_NOWAIT)) {
                    812:                printf("%s: failed ea buf map\n", sc->sc_dv.dv_xname);
                    813:                goto fail_1;
                    814:        }
                    815:        if (bus_dmamap_create(sc->sc_dmat, NOCT_EA_BUFSIZE, rseg,
                    816:            NOCT_EA_BUFSIZE, 0, BUS_DMA_NOWAIT, &sc->sc_eamap)) {
                    817:                printf("%s: failed ea map create\n", sc->sc_dv.dv_xname);
                    818:                goto fail_2;
                    819:        }
                    820:        if (bus_dmamap_load_raw(sc->sc_dmat, sc->sc_eamap,
                    821:            &seg, rseg, NOCT_EA_BUFSIZE, BUS_DMA_NOWAIT)) {
                    822:                printf("%s: failed ea buf load\n", sc->sc_dv.dv_xname);
                    823:                goto fail_3;
                    824:        }
                    825:
                    826:        noct_ea_disable(sc);
                    827:        noct_ea_enable(sc);
                    828:
                    829:        SIMPLEQ_INIT(&sc->sc_inq);
                    830:        SIMPLEQ_INIT(&sc->sc_chipq);
                    831:        SIMPLEQ_INIT(&sc->sc_outq);
                    832:
                    833:        bzero(algs, sizeof(algs));
                    834:
                    835:        algs[CRYPTO_MD5] = CRYPTO_ALG_FLAG_SUPPORTED;
                    836:        algs[CRYPTO_SHA1] = CRYPTO_ALG_FLAG_SUPPORTED;
                    837:        algs[CRYPTO_DES_CBC] = CRYPTO_ALG_FLAG_SUPPORTED;
                    838:        algs[CRYPTO_3DES_CBC] = CRYPTO_ALG_FLAG_SUPPORTED;
                    839:
                    840:        crypto_register(sc->sc_cid, algs,
                    841:            noct_newsession, noct_freesession, noct_process);
                    842:        printf(" MD5 SHA1 3DES");
                    843:
                    844:        kthread_create_deferred(noct_ea_create_thread, sc);
                    845:
                    846:        return;
                    847:
                    848: fail_3:
                    849:        bus_dmamap_destroy(sc->sc_dmat, sc->sc_eamap);
                    850: fail_2:
                    851:        bus_dmamem_unmap(sc->sc_dmat,
                    852:            (caddr_t)sc->sc_eacmd, NOCT_EA_BUFSIZE);
                    853: fail_1:
                    854:        bus_dmamem_free(sc->sc_dmat, &seg, rseg);
                    855: fail:
                    856:        sc->sc_eacmd = NULL;
                    857:        sc->sc_eamap = NULL;
                    858: }
                    859:
                    860: void
                    861: noct_ea_create_thread(vsc)
                    862:        void *vsc;
                    863: {
                    864:        struct noct_softc *sc = vsc;
                    865:
                    866:        if (kthread_create(noct_ea_thread, sc, NULL,
                    867:            "%s", sc->sc_dv.dv_xname))
                    868:                panic("%s: unable to create ea thread", sc->sc_dv.dv_xname);
                    869: }
                    870:
                    871: void
                    872: noct_ea_thread(vsc)
                    873:        void *vsc;
                    874: {
                    875:        struct noct_softc *sc = vsc;
                    876:        struct noct_workq *q;
                    877:        struct cryptop *crp;
                    878:        struct cryptodesc *crd;
                    879:        int s, rseg;
                    880:        u_int32_t len;
                    881:
                    882:        for (;;) {
                    883:                tsleep(&sc->sc_eawp, PWAIT, "noctea", 0);
                    884:
                    885:                /* Handle output queue */
                    886:                s = splnet();
                    887:                while (!SIMPLEQ_EMPTY(&sc->sc_outq)) {
                    888:                        q = SIMPLEQ_FIRST(&sc->sc_outq);
                    889:                        SIMPLEQ_REMOVE_HEAD(&sc->sc_outq, q_next);
                    890:                        splx(s);
                    891:
                    892:                        crp = q->q_crp;
                    893:                        crd = crp->crp_desc;
                    894:                        switch (crd->crd_alg) {
                    895:                        case CRYPTO_MD5:
                    896:                                len = 16;
                    897:                                break;
                    898:                        case CRYPTO_SHA1:
                    899:                                len = 20;
                    900:                                break;
                    901:                        default:
                    902:                                len = 0;
                    903:                                break;
                    904:                        }
                    905:
                    906:                        bus_dmamap_sync(sc->sc_dmat, q->q_dmamap,
                    907:                            0, q->q_dmamap->dm_mapsize,
                    908:                            BUS_DMASYNC_POSTWRITE | BUS_DMASYNC_POSTREAD);
                    909:
                    910:                        if (len != 0) {
                    911:                                if (crp->crp_flags & CRYPTO_F_IMBUF)
                    912:                                        m_copyback((struct mbuf *)crp->crp_buf,
                    913:                                            crd->crd_inject, len,
                    914:                                            q->q_macbuf);
                    915:                                else if (crp->crp_flags & CRYPTO_F_IOV)
                    916:                                        bcopy(q->q_macbuf, crp->crp_mac, len);
                    917:                        }
                    918:
                    919:                        if (crd->crd_alg == CRYPTO_DES_CBC ||
                    920:                            crd->crd_alg == CRYPTO_3DES_CBC) {
                    921:                                if (crp->crp_flags & CRYPTO_F_IMBUF)
                    922:                                        m_copyback((struct mbuf *)crp->crp_buf,
                    923:                                            crd->crd_skip, crd->crd_len,
                    924:                                            q->q_buf);
                    925:                                else if (crp->crp_flags & CRYPTO_F_IOV)
                    926:                                        cuio_copyback((struct uio *)crp->crp_buf,
                    927:                                            crd->crd_skip, crd->crd_len,
                    928:                                            q->q_buf);
                    929:                        }
                    930:
                    931:                        bus_dmamap_unload(sc->sc_dmat, q->q_dmamap);
                    932:                        bus_dmamap_destroy(sc->sc_dmat, q->q_dmamap);
                    933:                        bus_dmamem_unmap(sc->sc_dmat, q->q_buf, crd->crd_len);
                    934:                        bus_dmamem_free(sc->sc_dmat, &q->q_dmaseg, rseg);
                    935:                        crp->crp_etype = 0;
                    936:                        free(q, M_DEVBUF);
                    937:                        s = splnet();
                    938:                        crypto_done(crp);
                    939:                }
                    940:                splx(s);
                    941:
                    942:                /* Handle input queue */
                    943:                s = splnet();
                    944:                while (!SIMPLEQ_EMPTY(&sc->sc_inq)) {
                    945:                        q = SIMPLEQ_FIRST(&sc->sc_inq);
                    946:                        SIMPLEQ_REMOVE_HEAD(&sc->sc_inq, q_next);
                    947:                        splx(s);
                    948:
                    949:                        noct_ea_start(sc, q);
                    950:                        s = splnet();
                    951:                }
                    952:                splx(s);
                    953:        }
                    954: }
                    955:
                    956: void
                    957: noct_ea_start(sc, q)
                    958:        struct noct_softc *sc;
                    959:        struct noct_workq *q;
                    960: {
                    961:        struct cryptop *crp;
                    962:        struct cryptodesc *crd;
                    963:        int s, err;
                    964:
                    965:        crp = q->q_crp;
                    966:        crd = crp->crp_desc;
                    967:
                    968:        /* XXX Can't handle multiple ops yet */
                    969:        if (crd->crd_next != NULL) {
                    970:                err = EOPNOTSUPP;
                    971:                goto errout;
                    972:        }
                    973:
                    974:        switch (crd->crd_alg) {
                    975:        case CRYPTO_MD5:
                    976:        case CRYPTO_SHA1:
                    977:                noct_ea_start_hash(sc, q, crp, crd);
                    978:                break;
                    979:        case CRYPTO_DES_CBC:
                    980:        case CRYPTO_3DES_CBC:
                    981:                noct_ea_start_des(sc, q, crp, crd);
                    982:                break;
                    983:        default:
                    984:                err = EOPNOTSUPP;
                    985:                goto errout;
                    986:        }
                    987:
                    988:        return;
                    989:
                    990: errout:
                    991:        crp->crp_etype = err;
                    992:        free(q, M_DEVBUF);
                    993:        s = splnet();
                    994:        crypto_done(crp);
                    995:        splx(s);
                    996: }
                    997:
                    998: void
                    999: noct_ea_start_hash(sc, q, crp, crd)
                   1000:        struct noct_softc *sc;
                   1001:        struct noct_workq *q;
                   1002:        struct cryptop *crp;
                   1003:        struct cryptodesc *crd;
                   1004: {
                   1005:        u_int64_t adr;
                   1006:        int s, err, i, rseg;
                   1007:        u_int32_t wp;
                   1008:
                   1009:        if (crd->crd_len > 0x4800) {
                   1010:                err = ERANGE;
                   1011:                goto errout;
                   1012:        }
                   1013:
                   1014:        if ((err = bus_dmamem_alloc(sc->sc_dmat, crd->crd_len, PAGE_SIZE, 0,
                   1015:            &q->q_dmaseg, 1, &rseg, BUS_DMA_WAITOK | BUS_DMA_STREAMING)) != 0)
                   1016:                goto errout;
                   1017:
                   1018:        if ((err = bus_dmamem_map(sc->sc_dmat, &q->q_dmaseg, rseg,
                   1019:            crd->crd_len, (caddr_t *)&q->q_buf, BUS_DMA_WAITOK)) != 0)
                   1020:                goto errout_dmafree;
                   1021:
                   1022:        if ((err = bus_dmamap_create(sc->sc_dmat, crd->crd_len, 1,
                   1023:            crd->crd_len, 0, BUS_DMA_WAITOK, &q->q_dmamap)) != 0)
                   1024:                goto errout_dmaunmap;
                   1025:
                   1026:        if ((err = bus_dmamap_load_raw(sc->sc_dmat, q->q_dmamap, &q->q_dmaseg,
                   1027:            rseg, crd->crd_len, BUS_DMA_WAITOK)) != 0)
                   1028:                goto errout_dmadestroy;
                   1029:
                   1030:        if (crp->crp_flags & CRYPTO_F_IMBUF)
                   1031:                m_copydata((struct mbuf *)crp->crp_buf,
                   1032:                    crd->crd_skip, crd->crd_len, q->q_buf);
                   1033:        else if (crp->crp_flags & CRYPTO_F_IOV)
                   1034:                cuio_copydata((struct uio *)crp->crp_buf,
                   1035:                    crd->crd_skip, crd->crd_len, q->q_buf);
                   1036:        else {
                   1037:                err = EINVAL;
                   1038:                goto errout_dmaunload;
                   1039:        }
                   1040:
                   1041:        bus_dmamap_sync(sc->sc_dmat, q->q_dmamap, 0, q->q_dmamap->dm_mapsize,
                   1042:            BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE);
                   1043:
                   1044:        s = splnet();
                   1045:        if (noct_ea_nfree(sc) < 1) {
                   1046:                err = ENOMEM;
                   1047:                goto errout_dmaunload;
                   1048:        }
                   1049:        wp = sc->sc_eawp;
                   1050:        if (++sc->sc_eawp == NOCT_EA_ENTRIES)
                   1051:                sc->sc_eawp = 0;
                   1052:        for (i = 0; i < EA_CMD_WORDS; i++)
                   1053:                sc->sc_eacmd[wp].buf[i] = 0;
                   1054:        sc->sc_eacmd[wp].buf[0] = EA_0_SI;
                   1055:        switch (crd->crd_alg) {
                   1056:        case CRYPTO_MD5:
                   1057:                sc->sc_eacmd[wp].buf[1] = htole32(EA_OP_MD5);
                   1058:                break;
                   1059:        case CRYPTO_SHA1:
                   1060:                sc->sc_eacmd[wp].buf[1] = htole32(EA_OP_SHA1);
                   1061:                break;
                   1062:        }
                   1063:
                   1064:        /* Source, new buffer just allocated */
                   1065:        sc->sc_eacmd[wp].buf[1] |= htole32(crd->crd_len);
                   1066:        adr = q->q_dmamap->dm_segs[0].ds_addr;
                   1067:        sc->sc_eacmd[wp].buf[2] = htole32(adr >> 32);
                   1068:        sc->sc_eacmd[wp].buf[3] = htole32(adr & 0xffffffff);
                   1069:
                   1070:        /* Dest, hide it in the descriptor */
                   1071:        adr = sc->sc_eamap->dm_segs[0].ds_addr +
                   1072:            (wp * sizeof(struct noct_ea_cmd)) +
                   1073:            offsetof(struct noct_ea_cmd, buf[6]);
                   1074:        sc->sc_eacmd[wp].buf[4] = htole32(adr >> 32);
                   1075:        sc->sc_eacmd[wp].buf[5] = htole32(adr & 0xffffffff);
                   1076:
                   1077:        bus_dmamap_sync(sc->sc_dmat, sc->sc_eamap,
                   1078:            (wp * sizeof(struct noct_ea_cmd)), sizeof(struct noct_ea_cmd),
                   1079:            BUS_DMASYNC_PREWRITE | BUS_DMASYNC_PREREAD);
                   1080:
                   1081:        if (++wp == NOCT_EA_ENTRIES)
                   1082:                wp = 0;
                   1083:        NOCT_WRITE_4(sc, NOCT_EA_Q_PTR, wp);
                   1084:        sc->sc_eawp = wp;
                   1085:
                   1086:        SIMPLEQ_INSERT_TAIL(&sc->sc_chipq, q, q_next);
                   1087:        splx(s);
                   1088:
                   1089:        return;
                   1090:
                   1091: errout_dmaunload:
                   1092:        bus_dmamap_unload(sc->sc_dmat, q->q_dmamap);
                   1093: errout_dmadestroy:
                   1094:        bus_dmamap_destroy(sc->sc_dmat, q->q_dmamap);
                   1095: errout_dmaunmap:
                   1096:        bus_dmamem_unmap(sc->sc_dmat, q->q_buf, crd->crd_len);
                   1097: errout_dmafree:
                   1098:        bus_dmamem_free(sc->sc_dmat, &q->q_dmaseg, rseg);
                   1099: errout:
                   1100:        crp->crp_etype = err;
                   1101:        free(q, M_DEVBUF);
                   1102:        s = splnet();
                   1103:        crypto_done(crp);
                   1104:        splx(s);
                   1105: }
                   1106:
                   1107: void
                   1108: noct_ea_start_des(sc, q, crp, crd)
                   1109:        struct noct_softc *sc;
                   1110:        struct noct_workq *q;
                   1111:        struct cryptop *crp;
                   1112:        struct cryptodesc *crd;
                   1113: {
                   1114:        u_int64_t adr;
                   1115:        volatile u_int8_t *pb;
                   1116:        int s, err, i, rseg;
                   1117:        u_int32_t wp;
                   1118:        u_int8_t iv[8], key[24];
                   1119:
                   1120:        if (crd->crd_len > 0x4800) {
                   1121:                err = ERANGE;
                   1122:                goto errout;
                   1123:        }
                   1124:
                   1125:        if ((crd->crd_len & 3) != 0) {
                   1126:                err = ERANGE;
                   1127:                goto errout;
                   1128:        }
                   1129:
                   1130:        if (crd->crd_alg == CRYPTO_DES_CBC) {
                   1131:                for (i = 0; i < 8; i++)
                   1132:                        key[i] = key[i + 8] = key[i + 16] = crd->crd_key[i];
                   1133:        } else {
                   1134:                for (i = 0; i < 24; i++)
                   1135:                        key[i] = crd->crd_key[i];
                   1136:        }
                   1137:
                   1138:        if (crd->crd_flags & CRD_F_ENCRYPT) {
                   1139:                if (crd->crd_flags & CRD_F_IV_EXPLICIT)
                   1140:                        bcopy(crd->crd_iv, iv, 8);
                   1141:                else
                   1142:                        get_random_bytes(iv, sizeof(iv));
                   1143:
                   1144:                if (!(crd->crd_flags & CRD_F_IV_PRESENT)) {
                   1145:                        if (crp->crp_flags & CRYPTO_F_IMBUF)
                   1146:                                m_copyback((struct mbuf *)crp->crp_buf,
                   1147:                                    crd->crd_inject, 8, iv);
                   1148:                        else if (crp->crp_flags & CRYPTO_F_IOV)
                   1149:                                cuio_copyback((struct uio *)crp->crp_buf,
                   1150:                                    crd->crd_inject, 8, iv);
                   1151:                }
                   1152:        } else {
                   1153:                if (crd->crd_flags & CRD_F_IV_EXPLICIT)
                   1154:                        bcopy(crd->crd_iv, iv, 8);
                   1155:                else if (crp->crp_flags & CRYPTO_F_IMBUF)
                   1156:                        m_copydata((struct mbuf *)crp->crp_buf,
                   1157:                            crd->crd_inject, 8, iv);
                   1158:                else if (crp->crp_flags & CRYPTO_F_IOV)
                   1159:                        cuio_copydata((struct uio *)crp->crp_buf,
                   1160:                            crd->crd_inject, 8, iv);
                   1161:        }
                   1162:
                   1163:        if ((err = bus_dmamem_alloc(sc->sc_dmat, crd->crd_len, PAGE_SIZE, 0,
                   1164:            &q->q_dmaseg, 1, &rseg, BUS_DMA_WAITOK | BUS_DMA_STREAMING)) != 0)
                   1165:                goto errout;
                   1166:
                   1167:        if ((err = bus_dmamem_map(sc->sc_dmat, &q->q_dmaseg, rseg,
                   1168:            crd->crd_len, (caddr_t *)&q->q_buf, BUS_DMA_WAITOK)) != 0)
                   1169:                goto errout_dmafree;
                   1170:
                   1171:        if ((err = bus_dmamap_create(sc->sc_dmat, crd->crd_len, 1,
                   1172:            crd->crd_len, 0, BUS_DMA_WAITOK, &q->q_dmamap)) != 0)
                   1173:                goto errout_dmaunmap;
                   1174:
                   1175:        if ((err = bus_dmamap_load_raw(sc->sc_dmat, q->q_dmamap, &q->q_dmaseg,
                   1176:            rseg, crd->crd_len, BUS_DMA_WAITOK)) != 0)
                   1177:                goto errout_dmadestroy;
                   1178:
                   1179:        if (crp->crp_flags & CRYPTO_F_IMBUF)
                   1180:                m_copydata((struct mbuf *)crp->crp_buf,
                   1181:                    crd->crd_skip, crd->crd_len, q->q_buf);
                   1182:        else if (crp->crp_flags & CRYPTO_F_IOV)
                   1183:                cuio_copydata((struct uio *)crp->crp_buf,
                   1184:                    crd->crd_skip, crd->crd_len, q->q_buf);
                   1185:        else {
                   1186:                err = EINVAL;
                   1187:                goto errout_dmaunload;
                   1188:        }
                   1189:
                   1190:        bus_dmamap_sync(sc->sc_dmat, q->q_dmamap, 0, q->q_dmamap->dm_mapsize,
                   1191:            BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE);
                   1192:
                   1193:        s = splnet();
                   1194:        if (noct_ea_nfree(sc) < 1) {
                   1195:                err = ENOMEM;
                   1196:                goto errout_dmaunload;
                   1197:        }
                   1198:        wp = sc->sc_eawp;
                   1199:        if (++sc->sc_eawp == NOCT_EA_ENTRIES)
                   1200:                sc->sc_eawp = 0;
                   1201:
                   1202:        for (i = 0; i < EA_CMD_WORDS; i++)
                   1203:                sc->sc_eacmd[wp].buf[i] = 0;
                   1204:
                   1205:        sc->sc_eacmd[wp].buf[0] = EA_0_SI;
                   1206:
                   1207:        if (crd->crd_flags & CRD_F_ENCRYPT)
                   1208:                sc->sc_eacmd[wp].buf[1] = htole32(EA_OP_3DESCBCE);
                   1209:        else
                   1210:                sc->sc_eacmd[wp].buf[1] = htole32(EA_OP_3DESCBCD);
                   1211:
                   1212:        /* Source, new buffer just allocated */
                   1213:        sc->sc_eacmd[wp].buf[1] |= htole32(crd->crd_len);
                   1214:        adr = q->q_dmamap->dm_segs[0].ds_addr;
                   1215:        sc->sc_eacmd[wp].buf[2] = htole32(adr >> 32);
                   1216:        sc->sc_eacmd[wp].buf[3] = htole32(adr & 0xffffffff);
                   1217:
                   1218:        /* Dest, same as source. */
                   1219:        sc->sc_eacmd[wp].buf[4] = htole32(adr >> 32);
                   1220:        sc->sc_eacmd[wp].buf[5] = htole32(adr & 0xffffffff);
                   1221:
                   1222:        /* IV and key */
                   1223:        pb = (volatile u_int8_t *)&sc->sc_eacmd[wp].buf[20];
                   1224:        for (i = 0; i < 8; i++)
                   1225:                pb[i] = iv[i];
                   1226:        SWAP32(sc->sc_eacmd[wp].buf[20]);
                   1227:        SWAP32(sc->sc_eacmd[wp].buf[21]);
                   1228:        pb = (volatile u_int8_t *)&sc->sc_eacmd[wp].buf[24];
                   1229:        for (i = 0; i < 24; i++)
                   1230:                pb[i] = key[i];
                   1231:        SWAP32(sc->sc_eacmd[wp].buf[24]);
                   1232:        SWAP32(sc->sc_eacmd[wp].buf[25]);
                   1233:        SWAP32(sc->sc_eacmd[wp].buf[26]);
                   1234:        SWAP32(sc->sc_eacmd[wp].buf[27]);
                   1235:        SWAP32(sc->sc_eacmd[wp].buf[28]);
                   1236:        SWAP32(sc->sc_eacmd[wp].buf[29]);
                   1237:
                   1238:        bus_dmamap_sync(sc->sc_dmat, sc->sc_eamap,
                   1239:            (wp * sizeof(struct noct_ea_cmd)), sizeof(struct noct_ea_cmd),
                   1240:            BUS_DMASYNC_PREWRITE | BUS_DMASYNC_PREREAD);
                   1241:
                   1242:        if (++wp == NOCT_EA_ENTRIES)
                   1243:                wp = 0;
                   1244:        NOCT_WRITE_4(sc, NOCT_EA_Q_PTR, wp);
                   1245:        sc->sc_eawp = wp;
                   1246:
                   1247:        SIMPLEQ_INSERT_TAIL(&sc->sc_chipq, q, q_next);
                   1248:        splx(s);
                   1249:
                   1250:        return;
                   1251:
                   1252: errout_dmaunload:
                   1253:        bus_dmamap_unload(sc->sc_dmat, q->q_dmamap);
                   1254: errout_dmadestroy:
                   1255:        bus_dmamap_destroy(sc->sc_dmat, q->q_dmamap);
                   1256: errout_dmaunmap:
                   1257:        bus_dmamem_unmap(sc->sc_dmat, q->q_buf, crd->crd_len);
                   1258: errout_dmafree:
                   1259:        bus_dmamem_free(sc->sc_dmat, &q->q_dmaseg, rseg);
                   1260: errout:
                   1261:        crp->crp_etype = err;
                   1262:        free(q, M_DEVBUF);
                   1263:        s = splnet();
                   1264:        crypto_done(crp);
                   1265:        splx(s);
                   1266: }
                   1267:
                   1268: void
                   1269: noct_ea_intr(sc)
                   1270:        struct noct_softc *sc;
                   1271: {
                   1272:        struct noct_workq *q;
                   1273:        u_int32_t csr, rp;
                   1274:
                   1275:        csr = NOCT_READ_4(sc, NOCT_EA_CSR);
                   1276:        NOCT_WRITE_4(sc, NOCT_EA_CSR, csr |
                   1277:            EACSR_QALIGN | EACSR_CMDCMPL | EACSR_OPERR | EACSR_CMDREAD |
                   1278:            EACSR_CMDWRITE | EACSR_DATAREAD | EACSR_DATAWRITE |
                   1279:            EACSR_INTRNLLEN | EACSR_EXTRNLLEN | EACSR_DESBLOCK |
                   1280:            EACSR_DESKEY | EACSR_ILL);
                   1281:
                   1282:        rp = (NOCT_READ_4(sc, NOCT_EA_Q_PTR) & EAQPTR_READ_M) >>
                   1283:            EAQPTR_READ_S;
                   1284:        while (sc->sc_earp != rp) {
                   1285:                if (SIMPLEQ_EMPTY(&sc->sc_chipq))
                   1286:                        panic("%s: empty chipq", sc->sc_dv.dv_xname);
                   1287:                q = SIMPLEQ_FIRST(&sc->sc_chipq);
                   1288:                SIMPLEQ_REMOVE_HEAD(&sc->sc_chipq, q_next);
                   1289:                SIMPLEQ_INSERT_TAIL(&sc->sc_outq, q, q_next);
                   1290:
                   1291:                bus_dmamap_sync(sc->sc_dmat, sc->sc_eamap,
                   1292:                    (sc->sc_earp * sizeof(struct noct_ea_cmd)),
                   1293:                    sizeof(struct noct_ea_cmd),
                   1294:                    BUS_DMASYNC_POSTWRITE | BUS_DMASYNC_POSTREAD);
                   1295:                bcopy((u_int8_t *)&sc->sc_eacmd[sc->sc_earp].buf[6],
                   1296:                    q->q_macbuf, 20);
                   1297:
                   1298:                NOCT_WAKEUP(sc);
                   1299:                if (++sc->sc_earp == NOCT_EA_ENTRIES)
                   1300:                        sc->sc_earp = 0;
                   1301:        }
                   1302:        sc->sc_earp = rp;
                   1303:
                   1304:        if (csr & EACSR_QALIGN)
                   1305:                printf("%s: ea bad queue alignment\n", sc->sc_dv.dv_xname);
                   1306:        if (csr & EACSR_OPERR)
                   1307:                printf("%s: ea bad opcode\n", sc->sc_dv.dv_xname);
                   1308:        if (csr & EACSR_CMDREAD)
                   1309:                printf("%s: ea command read error\n", sc->sc_dv.dv_xname);
                   1310:        if (csr & EACSR_CMDWRITE)
                   1311:                printf("%s: ea command write error\n", sc->sc_dv.dv_xname);
                   1312:        if (csr & EACSR_DATAREAD)
                   1313:                printf("%s: ea data read error\n", sc->sc_dv.dv_xname);
                   1314:        if (csr & EACSR_DATAWRITE)
                   1315:                printf("%s: ea data write error\n", sc->sc_dv.dv_xname);
                   1316:        if (csr & EACSR_INTRNLLEN)
                   1317:                printf("%s: ea bad internal len\n", sc->sc_dv.dv_xname);
                   1318:        if (csr & EACSR_EXTRNLLEN)
                   1319:                printf("%s: ea bad external len\n", sc->sc_dv.dv_xname);
                   1320:        if (csr & EACSR_DESBLOCK)
                   1321:                printf("%s: ea bad des block\n", sc->sc_dv.dv_xname);
                   1322:        if (csr & EACSR_DESKEY)
                   1323:                printf("%s: ea bad des key\n", sc->sc_dv.dv_xname);
                   1324:        if (csr & EACSR_ILL)
                   1325:                printf("%s: ea illegal access\n", sc->sc_dv.dv_xname);
                   1326: }
                   1327:
                   1328: void
                   1329: noct_write_8(sc, reg, val)
                   1330:        struct noct_softc *sc;
                   1331:        u_int32_t reg;
                   1332:        u_int64_t val;
                   1333: {
                   1334:        NOCT_WRITE_4(sc, reg, (val >> 32) & 0xffffffff);
                   1335:        NOCT_WRITE_4(sc, reg + 4, (val >> 0) & 0xffffffff);
                   1336: }
                   1337:
                   1338: u_int64_t
                   1339: noct_read_8(sc, reg)
                   1340:        struct noct_softc *sc;
                   1341:        u_int32_t reg;
                   1342: {
                   1343:        u_int64_t ret;
                   1344:
                   1345:        ret = NOCT_READ_4(sc, reg);
                   1346:        ret <<= 32;
                   1347:        ret |= NOCT_READ_4(sc, reg + 4);
                   1348:        return (ret);
                   1349: }
                   1350:
                   1351: /*
                   1352:  * NSP2000 is has a nifty bug, writes or reads to consecutive addresses
                   1353:  * can be coalesced by a PCI bridge and executed as a burst read or write
                   1354:  * which NSP2000's AMBA bridge doesn't grok.  Avoid the hazard.
                   1355:  */
                   1356: u_int32_t
                   1357: noct_read_4(sc, off)
                   1358:        struct noct_softc *sc;
                   1359:        bus_size_t off;
                   1360: {
                   1361:        if (sc->sc_rar_last == off - 4 ||
                   1362:            sc->sc_rar_last == off + 4) {
                   1363:                bus_space_write_4(sc->sc_st, sc->sc_sh, NOCT_BRDG_TEST, 0);
                   1364:                sc->sc_rar_last = off;
                   1365:                sc->sc_waw_last = 0xffffffff;
                   1366:        }
                   1367:        return (bus_space_read_4(sc->sc_st, sc->sc_sh, off));
                   1368: }
                   1369:
                   1370: void
                   1371: noct_write_4(sc, off, val)
                   1372:        struct noct_softc *sc;
                   1373:        bus_size_t off;
                   1374:        u_int32_t val;
                   1375: {
                   1376:        if (sc->sc_waw_last == off - 4 ||
                   1377:            sc->sc_waw_last == off + 4) {
                   1378:                bus_space_read_4(sc->sc_st, sc->sc_sh, NOCT_BRDG_TEST);
                   1379:                sc->sc_waw_last = off;
                   1380:                sc->sc_rar_last = 0xffffffff;
                   1381:        }
                   1382:        bus_space_write_4(sc->sc_st, sc->sc_sh, off, val);
                   1383: }
                   1384:
                   1385: struct noct_softc *
                   1386: noct_kfind(krp)
                   1387:        struct cryptkop *krp;
                   1388: {
                   1389:        struct noct_softc *sc;
                   1390:        int i;
                   1391:
                   1392:        for (i = 0; i < noct_cd.cd_ndevs; i++) {
                   1393:                sc = noct_cd.cd_devs[i];
                   1394:                if (sc == NULL)
                   1395:                        continue;
                   1396:                if (sc->sc_cid == krp->krp_hid)
                   1397:                        return (sc);
                   1398:        }
                   1399:        return (NULL);
                   1400: }
                   1401:
                   1402: int
                   1403: noct_kprocess(krp)
                   1404:        struct cryptkop *krp;
                   1405: {
                   1406:        struct noct_softc *sc;
                   1407:
                   1408:        if (krp == NULL || krp->krp_callback == NULL)
                   1409:                return (EINVAL);
                   1410:        if ((sc = noct_kfind(krp)) == NULL) {
                   1411:                krp->krp_status = EINVAL;
                   1412:                crypto_kdone(krp);
                   1413:                return (0);
                   1414:        }
                   1415:
                   1416:        switch (krp->krp_op) {
                   1417:        case CRK_MOD_EXP:
                   1418:                noct_kprocess_modexp(sc, krp);
                   1419:                break;
                   1420:        default:
                   1421:                printf("%s: kprocess: invalid op 0x%x\n",
                   1422:                    sc->sc_dv.dv_xname, krp->krp_op);
                   1423:                krp->krp_status = EOPNOTSUPP;
                   1424:                crypto_kdone(krp);
                   1425:                break;
                   1426:        }
                   1427:        return (0);
                   1428: }
                   1429:
                   1430: u_int32_t
                   1431: noct_pkh_nfree(sc)
                   1432:        struct noct_softc *sc;
                   1433: {
                   1434:        if (sc->sc_pkhwp == sc->sc_pkhrp)
                   1435:                return (NOCT_PKH_ENTRIES);
                   1436:        if (sc->sc_pkhwp < sc->sc_pkhrp)
                   1437:                return (sc->sc_pkhrp - sc->sc_pkhwp - 1);
                   1438:        return (sc->sc_pkhrp + NOCT_PKH_ENTRIES - sc->sc_pkhwp - 1);
                   1439: }
                   1440:
                   1441: int
                   1442: noct_kprocess_modexp(sc, krp)
                   1443:        struct noct_softc *sc;
                   1444:        struct cryptkop *krp;
                   1445: {
                   1446:        int s, err;
                   1447:        u_int32_t wp, aidx, bidx, midx;
                   1448:        u_int64_t adr;
                   1449:        union noct_pkh_cmd *cmd;
                   1450:        int i, bits, mbits, digits, rmodidx, mmulidx;
                   1451:
                   1452:        s = splnet();
                   1453:        if (noct_pkh_nfree(sc) < 7) {
                   1454:                /* Need 7 entries: 3 loads, 1 store, 3 ops */
                   1455:                splx(s);
                   1456:                return (ENOMEM);
                   1457:        }
                   1458:
                   1459:        /* Load M */
                   1460:        midx = wp = sc->sc_pkhwp;
                   1461:        mbits = bits = noct_ksigbits(&krp->krp_param[2]);
                   1462:        if (bits > 4096) {
                   1463:                err = ERANGE;
                   1464:                goto errout;
                   1465:        }
                   1466:        sc->sc_pkh_bnsw[midx].bn_siz = (bits + 127) / 128;
                   1467:        if (extent_alloc(sc->sc_pkh_bn, sc->sc_pkh_bnsw[midx].bn_siz,
                   1468:            EX_NOALIGN, 0, EX_NOBOUNDARY, EX_NOWAIT,
                   1469:            &sc->sc_pkh_bnsw[midx].bn_off)) {
                   1470:                err = ENOMEM;
                   1471:                goto errout;
                   1472:        }
                   1473:        cmd = &sc->sc_pkhcmd[midx];
                   1474:        cmd->cache.op = htole32(PKH_OP_CODE_LOAD);
                   1475:        cmd->cache.r = htole32(sc->sc_pkh_bnsw[midx].bn_off);
                   1476:        adr = sc->sc_bnmap->dm_segs[0].ds_addr +
                   1477:            (sc->sc_pkh_bnsw[midx].bn_off * 16);
                   1478:        cmd->cache.addrhi = htole32((adr >> 32) & 0xffffffff);
                   1479:        cmd->cache.addrlo = htole32((adr >> 0 ) & 0xffffffff);
                   1480:        cmd->cache.len = htole32(sc->sc_pkh_bnsw[midx].bn_siz);
                   1481:        cmd->cache.unused[0] = cmd->cache.unused[1] = cmd->cache.unused[2] = 0;
                   1482:        bus_dmamap_sync(sc->sc_dmat, sc->sc_pkhmap,
                   1483:            midx * sizeof(union noct_pkh_cmd), sizeof(union noct_pkh_cmd),
                   1484:            BUS_DMASYNC_PREWRITE);
                   1485:        for (i = 0; i < (digits * 16); i++)
                   1486:                sc->sc_bncache[(sc->sc_pkh_bnsw[midx].bn_off * 16) + i] = 0;
                   1487:        for (i = 0; i < ((bits + 7) / 8); i++)
                   1488:                sc->sc_bncache[(sc->sc_pkh_bnsw[midx].bn_off * 16) +
                   1489:                    (digits * 16) - 1 - i] = krp->krp_param[2].crp_p[i];
                   1490:        bus_dmamap_sync(sc->sc_dmat, sc->sc_bnmap,
                   1491:            sc->sc_pkh_bnsw[midx].bn_off * 16, digits * 16,
                   1492:            BUS_DMASYNC_PREWRITE);
                   1493:        if (++wp == NOCT_PKH_ENTRIES)
                   1494:                wp = 0;
                   1495:
                   1496:        /* Store RMOD(m) -> location tmp1 */
                   1497:        rmodidx = wp;
                   1498:        sc->sc_pkh_bnsw[rmodidx].bn_siz = sc->sc_pkh_bnsw[midx].bn_siz;
                   1499:        if (extent_alloc(sc->sc_pkh_bn, sc->sc_pkh_bnsw[rmodidx].bn_siz,
                   1500:            EX_NOALIGN, 0, EX_NOBOUNDARY, EX_NOWAIT,
                   1501:            &sc->sc_pkh_bnsw[rmodidx].bn_off)) {
                   1502:                err = ENOMEM;
                   1503:                goto errout_m;
                   1504:        }
                   1505:        cmd = &sc->sc_pkhcmd[rmodidx];
                   1506:        cmd->arith.op = htole32(PKH_OP_CODE_RMOD);
                   1507:        cmd->arith.r = htole32(sc->sc_pkh_bnsw[rmodidx].bn_off);
                   1508:        cmd->arith.m = htole32(sc->sc_pkh_bnsw[midx].bn_off |
                   1509:            (sc->sc_pkh_bnsw[midx].bn_siz << 16));
                   1510:        cmd->arith.a = cmd->arith.b = cmd->arith.c = cmd->arith.unused[0] =
                   1511:            cmd->arith.unused[1] = 0;
                   1512:        bus_dmamap_sync(sc->sc_dmat, sc->sc_pkhmap,
                   1513:            rmodidx * sizeof(union noct_pkh_cmd), sizeof(union noct_pkh_cmd),
                   1514:            BUS_DMASYNC_PREWRITE);
                   1515:        if (++wp == NOCT_PKH_ENTRIES)
                   1516:                wp = 0;
                   1517:
                   1518:        /* Load A XXX deal with A < M padding ... */
                   1519:        aidx = wp = sc->sc_pkhwp;
                   1520:        bits = noct_ksigbits(&krp->krp_param[0]);
                   1521:        if (bits > 4096 || bits > mbits) {
                   1522:                err = ERANGE;
                   1523:                goto errout_rmod;
                   1524:        }
                   1525:        sc->sc_pkh_bnsw[aidx].bn_siz = (bits + 127) / 128;
                   1526:        if (extent_alloc(sc->sc_pkh_bn, sc->sc_pkh_bnsw[aidx].bn_siz,
                   1527:            EX_NOALIGN, 0, EX_NOBOUNDARY, EX_NOWAIT,
                   1528:            &sc->sc_pkh_bnsw[aidx].bn_off)) {
                   1529:                err = ENOMEM;
                   1530:                goto errout_rmod;
                   1531:        }
                   1532:        cmd = &sc->sc_pkhcmd[aidx];
                   1533:        cmd->cache.op = htole32(PKH_OP_CODE_LOAD);
                   1534:        cmd->cache.r = htole32(sc->sc_pkh_bnsw[aidx].bn_off);
                   1535:        adr = sc->sc_bnmap->dm_segs[0].ds_addr +
                   1536:            (sc->sc_pkh_bnsw[aidx].bn_off * 16);
                   1537:        cmd->cache.addrhi = htole32((adr >> 32) & 0xffffffff);
                   1538:        cmd->cache.addrlo = htole32((adr >> 0 ) & 0xffffffff);
                   1539:        cmd->cache.len = htole32(sc->sc_pkh_bnsw[aidx].bn_siz);
                   1540:        cmd->cache.unused[0] = cmd->cache.unused[1] = cmd->cache.unused[2] = 0;
                   1541:        bus_dmamap_sync(sc->sc_dmat, sc->sc_pkhmap,
                   1542:            aidx * sizeof(union noct_pkh_cmd), sizeof(union noct_pkh_cmd),
                   1543:            BUS_DMASYNC_PREWRITE);
                   1544:        for (i = 0; i < (digits * 16); i++)
                   1545:                sc->sc_bncache[(sc->sc_pkh_bnsw[aidx].bn_off * 16) + i] = 0;
                   1546:        for (i = 0; i < ((bits + 7) / 8); i++)
                   1547:                sc->sc_bncache[(sc->sc_pkh_bnsw[aidx].bn_off * 16) +
                   1548:                    (digits * 16) - 1 - i] = krp->krp_param[2].crp_p[i];
                   1549:        bus_dmamap_sync(sc->sc_dmat, sc->sc_bnmap,
                   1550:            sc->sc_pkh_bnsw[aidx].bn_off * 16, digits * 16,
                   1551:            BUS_DMASYNC_PREWRITE);
                   1552:        if (++wp == NOCT_PKH_ENTRIES)
                   1553:                wp = 0;
                   1554:
                   1555:        /* Compute (A * tmp1) mod m -> A */
                   1556:        mmulidx = wp;
                   1557:        sc->sc_pkh_bnsw[mmulidx].bn_siz = 0;
                   1558:        sc->sc_pkh_bnsw[mmulidx].bn_off = 0;
                   1559:        cmd = &sc->sc_pkhcmd[mmulidx];
                   1560:        cmd->arith.op = htole32(PKH_OP_CODE_MUL);
                   1561:        cmd->arith.r = htole32(sc->sc_pkh_bnsw[aidx].bn_off);
                   1562:        cmd->arith.m = htole32(sc->sc_pkh_bnsw[midx].bn_off |
                   1563:            (sc->sc_pkh_bnsw[midx].bn_siz << 16));
                   1564:        cmd->arith.a = htole32(sc->sc_pkh_bnsw[aidx].bn_off |
                   1565:            (sc->sc_pkh_bnsw[aidx].bn_siz << 16));
                   1566:        cmd->arith.b = htole32(sc->sc_pkh_bnsw[rmodidx].bn_off |
                   1567:            (sc->sc_pkh_bnsw[rmodidx].bn_siz << 16));
                   1568:        cmd->arith.c = cmd->arith.unused[0] = cmd->arith.unused[1] = 0;
                   1569:        bus_dmamap_sync(sc->sc_dmat, sc->sc_pkhmap,
                   1570:            rmodidx * sizeof(union noct_pkh_cmd), sizeof(union noct_pkh_cmd),
                   1571:            BUS_DMASYNC_PREWRITE);
                   1572:        if (++wp == NOCT_PKH_ENTRIES)
                   1573:                wp = 0;
                   1574:
                   1575:        /* Load B */
                   1576:        bidx = wp = sc->sc_pkhwp;
                   1577:        bits = noct_ksigbits(&krp->krp_param[1]);
                   1578:        if (bits > 4096) {
                   1579:                err = ERANGE;
                   1580:                goto errout_a;
                   1581:        }
                   1582:        sc->sc_pkh_bnsw[bidx].bn_siz = (bits + 127) / 128;
                   1583:        if (extent_alloc(sc->sc_pkh_bn, sc->sc_pkh_bnsw[bidx].bn_siz,
                   1584:            EX_NOALIGN, 0, EX_NOBOUNDARY, EX_NOWAIT,
                   1585:            &sc->sc_pkh_bnsw[bidx].bn_off)) {
                   1586:                err = ENOMEM;
                   1587:                goto errout_a;
                   1588:        }
                   1589:        cmd = &sc->sc_pkhcmd[bidx];
                   1590:        cmd->cache.op = htole32(PKH_OP_CODE_LOAD);
                   1591:        cmd->cache.r = htole32(sc->sc_pkh_bnsw[bidx].bn_off);
                   1592:        adr = sc->sc_bnmap->dm_segs[0].ds_addr +
                   1593:            (sc->sc_pkh_bnsw[bidx].bn_off * 16);
                   1594:        cmd->cache.addrhi = htole32((adr >> 32) & 0xffffffff);
                   1595:        cmd->cache.addrlo = htole32((adr >> 0 ) & 0xffffffff);
                   1596:        cmd->cache.len = htole32(sc->sc_pkh_bnsw[bidx].bn_siz);
                   1597:        cmd->cache.unused[0] = cmd->cache.unused[1] = cmd->cache.unused[2] = 0;
                   1598:        bus_dmamap_sync(sc->sc_dmat, sc->sc_pkhmap,
                   1599:            bidx * sizeof(union noct_pkh_cmd), sizeof(union noct_pkh_cmd),
                   1600:            BUS_DMASYNC_PREWRITE);
                   1601:        for (i = 0; i < (digits * 16); i++)
                   1602:                sc->sc_bncache[(sc->sc_pkh_bnsw[bidx].bn_off * 16) + i] = 0;
                   1603:        for (i = 0; i < ((bits + 7) / 8); i++)
                   1604:                sc->sc_bncache[(sc->sc_pkh_bnsw[bidx].bn_off * 16) +
                   1605:                    (digits * 16) - 1 - i] = krp->krp_param[2].crp_p[i];
                   1606:        bus_dmamap_sync(sc->sc_dmat, sc->sc_bnmap,
                   1607:            sc->sc_pkh_bnsw[bidx].bn_off * 16, digits * 16,
                   1608:            BUS_DMASYNC_PREWRITE);
                   1609:        if (++wp == NOCT_PKH_ENTRIES)
                   1610:                wp = 0;
                   1611:
                   1612:        NOCT_WRITE_4(sc, NOCT_PKH_Q_PTR, wp);
                   1613:        sc->sc_pkhwp = wp;
                   1614:
                   1615:        splx(s);
                   1616:
                   1617:        return (0);
                   1618:
                   1619: errout_a:
                   1620:        extent_free(sc->sc_pkh_bn, sc->sc_pkh_bnsw[aidx].bn_off,
                   1621:            sc->sc_pkh_bnsw[aidx].bn_siz, EX_NOWAIT);
                   1622: errout_rmod:
                   1623:        extent_free(sc->sc_pkh_bn, sc->sc_pkh_bnsw[rmodidx].bn_off,
                   1624:            sc->sc_pkh_bnsw[rmodidx].bn_siz, EX_NOWAIT);
                   1625: errout_m:
                   1626:        extent_free(sc->sc_pkh_bn, sc->sc_pkh_bnsw[midx].bn_off,
                   1627:            sc->sc_pkh_bnsw[midx].bn_siz, EX_NOWAIT);
                   1628: errout:
                   1629:        splx(s);
                   1630:        krp->krp_status = err;
                   1631:        crypto_kdone(krp);
                   1632:        return (1);
                   1633: }
                   1634:
                   1635: void
                   1636: noct_pkh_freedesc(sc, idx)
                   1637:        struct noct_softc *sc;
                   1638:        int idx;
                   1639: {
                   1640:        if (sc->sc_pkh_bnsw[idx].bn_callback != NULL)
                   1641:                (*sc->sc_pkh_bnsw[idx].bn_callback)(sc, idx, 0);
                   1642: }
                   1643:
                   1644: /*
                   1645:  * Return the number of significant bits of a big number.
                   1646:  */
                   1647: int
                   1648: noct_ksigbits(cr)
                   1649:        struct crparam *cr;
                   1650: {
                   1651:        u_int plen = (cr->crp_nbits + 7) / 8;
                   1652:        int i, sig = plen * 8;
                   1653:        u_int8_t c, *p = cr->crp_p;
                   1654:
                   1655:        for (i = plen - 1; i >= 0; i--) {
                   1656:                c = p[i];
                   1657:                if (c != 0) {
                   1658:                        while ((c & 0x80) == 0) {
                   1659:                                sig--;
                   1660:                                c <<= 1;
                   1661:                        }
                   1662:                        break;
                   1663:                }
                   1664:                sig -= 8;
                   1665:        }
                   1666:        return (sig);
                   1667: }
                   1668:
                   1669: int
                   1670: noct_kload(sc, cr, wp)
                   1671:        struct noct_softc *sc;
                   1672:        struct crparam *cr;
                   1673:        u_int32_t wp;
                   1674: {
                   1675:        u_int64_t adr;
                   1676:        union noct_pkh_cmd *cmd;
                   1677:        u_long off;
                   1678:        int bits, digits, i;
                   1679:        u_int32_t wpnext;
                   1680:
                   1681:        wpnext = wp + 1;
                   1682:        if (wpnext == NOCT_PKH_ENTRIES)
                   1683:                wpnext = 0;
                   1684:        if (wpnext == sc->sc_pkhrp)
                   1685:                return (ENOMEM);
                   1686:
                   1687:        bits = noct_ksigbits(cr);
                   1688:        if (bits > 4096)
                   1689:                return (E2BIG);
                   1690:
                   1691:        digits = (bits + 127) / 128;
                   1692:
                   1693:        if (extent_alloc(sc->sc_pkh_bn, digits, EX_NOALIGN, 0, EX_NOBOUNDARY,
                   1694:            EX_NOWAIT, &off))
                   1695:                return (ENOMEM);
                   1696:
                   1697:        cmd = &sc->sc_pkhcmd[wp];
                   1698:        cmd->cache.op = htole32(PKH_OP_CODE_LOAD);
                   1699:        cmd->cache.r = htole32(off);
                   1700:        adr = sc->sc_bnmap->dm_segs[0].ds_addr + (off * 16);
                   1701:        cmd->cache.addrhi = htole32((adr >> 32) & 0xffffffff);
                   1702:        cmd->cache.addrlo = htole32((adr >> 0 ) & 0xffffffff);
                   1703:        cmd->cache.len = htole32(digits * 16);
                   1704:        cmd->cache.unused[0] = cmd->cache.unused[1] = cmd->cache.unused[2] = 0;
                   1705:        bus_dmamap_sync(sc->sc_dmat, sc->sc_pkhmap,
                   1706:            wp * sizeof(union noct_pkh_cmd), sizeof(union noct_pkh_cmd),
                   1707:            BUS_DMASYNC_PREWRITE);
                   1708:
                   1709:        for (i = 0; i < (digits * 16); i++)
                   1710:                sc->sc_bncache[(off * 16) + i] = 0;
                   1711:        for (i = 0; i < ((bits + 7) / 8); i++)
                   1712:                sc->sc_bncache[(off * 16) + (digits * 16) - 1 - i] =
                   1713:                    cr->crp_p[i];
                   1714:        bus_dmamap_sync(sc->sc_dmat, sc->sc_bnmap, off * 16, digits * 16,
                   1715:            BUS_DMASYNC_PREWRITE);
                   1716:
                   1717:        sc->sc_pkh_bnsw[wp].bn_off = off;
                   1718:        sc->sc_pkh_bnsw[wp].bn_siz = digits;
                   1719:        sc->sc_pkh_bnsw[wp].bn_callback = noct_kload_cb;
                   1720:        return (0);
                   1721: }
                   1722:
                   1723: void
                   1724: noct_kload_cb(sc, wp, err)
                   1725:        struct noct_softc *sc;
                   1726:        u_int32_t wp;
                   1727:        int err;
                   1728: {
                   1729:        struct noct_bnc_sw *sw = &sc->sc_pkh_bnsw[wp];
                   1730:
                   1731:        extent_free(sc->sc_pkh_bn, sw->bn_off, sw->bn_siz, EX_NOWAIT);
                   1732:        bzero(&sc->sc_bncache[sw->bn_off * 16], sw->bn_siz * 16);
                   1733: }
                   1734:
                   1735: void
                   1736: noct_modmul_cb(sc, wp, err)
                   1737:        struct noct_softc *sc;
                   1738:        u_int32_t wp;
                   1739:        int err;
                   1740: {
                   1741:        struct noct_bnc_sw *sw = &sc->sc_pkh_bnsw[wp];
                   1742:        struct cryptkop *krp = sw->bn_krp;
                   1743:        int i, j;
                   1744:
                   1745:        if (err)
                   1746:                goto out;
                   1747:
                   1748:        i = (sw->bn_off * 16) + (sw->bn_siz * 16) - 1;
                   1749:        for (j = 0; j < (krp->krp_param[3].crp_nbits + 7) / 8; j++) {
                   1750:                krp->krp_param[3].crp_p[j] = sc->sc_bncache[i];
                   1751:                i--;
                   1752:        }
                   1753:
                   1754: out:
                   1755:        extent_free(sc->sc_pkh_bn, sw->bn_off, sw->bn_siz, EX_NOWAIT);
                   1756:        bzero(&sc->sc_bncache[sw->bn_off * 16], sw->bn_siz * 16);
                   1757:        krp->krp_status = err;
                   1758:        crypto_kdone(krp);
                   1759: }
                   1760:
                   1761: static const u_int8_t noct_odd_parity[] = {
                   1762:        0x01, 0x01, 0x02, 0x02, 0x04, 0x04, 0x07, 0x07,
                   1763:        0x08, 0x08, 0x0b, 0x0b, 0x0d, 0x0d, 0x0e, 0x0e,
                   1764:        0x10, 0x10, 0x13, 0x13, 0x15, 0x15, 0x16, 0x16,
                   1765:        0x19, 0x19, 0x1a, 0x1a, 0x1c, 0x1c, 0x1f, 0x1f,
                   1766:        0x20, 0x20, 0x23, 0x23, 0x25, 0x25, 0x26, 0x26,
                   1767:        0x29, 0x29, 0x2a, 0x2a, 0x2c, 0x2c, 0x2f, 0x2f,
                   1768:        0x31, 0x31, 0x32, 0x32, 0x34, 0x34, 0x37, 0x37,
                   1769:        0x38, 0x38, 0x3b, 0x3b, 0x3d, 0x3d, 0x3e, 0x3e,
                   1770:        0x40, 0x40, 0x43, 0x43, 0x45, 0x45, 0x46, 0x46,
                   1771:        0x49, 0x49, 0x4a, 0x4a, 0x4c, 0x4c, 0x4f, 0x4f,
                   1772:        0x51, 0x51, 0x52, 0x52, 0x54, 0x54, 0x57, 0x57,
                   1773:        0x58, 0x58, 0x5b, 0x5b, 0x5d, 0x5d, 0x5e, 0x5e,
                   1774:        0x61, 0x61, 0x62, 0x62, 0x64, 0x64, 0x67, 0x67,
                   1775:        0x68, 0x68, 0x6b, 0x6b, 0x6d, 0x6d, 0x6e, 0x6e,
                   1776:        0x70, 0x70, 0x73, 0x73, 0x75, 0x75, 0x76, 0x76,
                   1777:        0x79, 0x79, 0x7a, 0x7a, 0x7c, 0x7c, 0x7f, 0x7f,
                   1778:        0x80, 0x80, 0x83, 0x83, 0x85, 0x85, 0x86, 0x86,
                   1779:        0x89, 0x89, 0x8a, 0x8a, 0x8c, 0x8c, 0x8f, 0x8f,
                   1780:        0x91, 0x91, 0x92, 0x92, 0x94, 0x94, 0x97, 0x97,
                   1781:        0x98, 0x98, 0x9b, 0x9b, 0x9d, 0x9d, 0x9e, 0x9e,
                   1782:        0xa1, 0xa1, 0xa2, 0xa2, 0xa4, 0xa4, 0xa7, 0xa7,
                   1783:        0xa8, 0xa8, 0xab, 0xab, 0xad, 0xad, 0xae, 0xae,
                   1784:        0xb0, 0xb0, 0xb3, 0xb3, 0xb5, 0xb5, 0xb6, 0xb6,
                   1785:        0xb9, 0xb9, 0xba, 0xba, 0xbc, 0xbc, 0xbf, 0xbf,
                   1786:        0xc1, 0xc1, 0xc2, 0xc2, 0xc4, 0xc4, 0xc7, 0xc7,
                   1787:        0xc8, 0xc8, 0xcb, 0xcb, 0xcd, 0xcd, 0xce, 0xce,
                   1788:        0xd0, 0xd0, 0xd3, 0xd3, 0xd5, 0xd5, 0xd6, 0xd6,
                   1789:        0xd9, 0xd9, 0xda, 0xda, 0xdc, 0xdc, 0xdf, 0xdf,
                   1790:        0xe0, 0xe0, 0xe3, 0xe3, 0xe5, 0xe5, 0xe6, 0xe6,
                   1791:        0xe9, 0xe9, 0xea, 0xea, 0xec, 0xec, 0xef, 0xef,
                   1792:        0xf1, 0xf1, 0xf2, 0xf2, 0xf4, 0xf4, 0xf7, 0xf7,
                   1793:        0xf8, 0xf8, 0xfb, 0xfb, 0xfd, 0xfd, 0xfe, 0xfe,
                   1794: };
                   1795:
                   1796: int
                   1797: noct_newsession(sidp, cri)
                   1798:        u_int32_t *sidp;
                   1799:        struct cryptoini *cri;
                   1800: {
                   1801:        struct noct_softc *sc;
                   1802:        int i;
                   1803:
                   1804:        for (i = 0; i < noct_cd.cd_ndevs; i++) {
                   1805:                sc = noct_cd.cd_devs[i];
                   1806:                if (sc == NULL || sc->sc_cid == (*sidp))
                   1807:                        break;
                   1808:        }
                   1809:        if (sc == NULL)
                   1810:                return (EINVAL);
                   1811:
                   1812:        /* XXX Can only handle single operations */
                   1813:        if (cri->cri_next != NULL)
                   1814:                return (EINVAL);
                   1815:
                   1816:        if (cri->cri_alg == CRYPTO_DES_CBC || cri->cri_alg == CRYPTO_3DES_CBC) {
                   1817:                u_int8_t key[24];
                   1818:
                   1819:                if (cri->cri_alg == CRYPTO_DES_CBC) {
                   1820:                        if (cri->cri_klen != 64)
                   1821:                                return (EINVAL);
                   1822:                        for (i = 0; i < 8; i++)
                   1823:                                key[i] = key[i + 8] = key[i + 16] =
                   1824:                                    cri->cri_key[i];
                   1825:                } else {
                   1826:                        if (cri->cri_klen != 192)
                   1827:                                return (EINVAL);
                   1828:                        for (i = 0; i < 24; i++)
                   1829:                                key[i] = cri->cri_key[i];
                   1830:                }
                   1831:
                   1832:                /* Verify key parity */
                   1833:                for (i = 0; i < 24; i++)
                   1834:                        if (key[i] != noct_odd_parity[key[i]])
                   1835:                                return (ENOEXEC);
                   1836:        }
                   1837:
                   1838:        *sidp = NOCT_SID(sc->sc_dv.dv_unit, 0);
                   1839:        return (0);
                   1840: }
                   1841:
                   1842: int
                   1843: noct_freesession(tid)
                   1844:        u_int64_t tid;
                   1845: {
                   1846:        int card;
                   1847:        u_int32_t sid = ((u_int32_t)tid) & 0xffffffff;
                   1848:
                   1849:        card = NOCT_CARD(sid);
                   1850:        if (card >= noct_cd.cd_ndevs || noct_cd.cd_devs[card] == NULL)
                   1851:                return (EINVAL);
                   1852:        return (0);
                   1853: }
                   1854:
                   1855: int
                   1856: noct_process(crp)
                   1857:        struct cryptop *crp;
                   1858: {
                   1859:        struct noct_softc *sc;
                   1860:        struct noct_workq *q = NULL;
                   1861:        int card, err, s;
                   1862:
                   1863:        if (crp == NULL || crp->crp_callback == NULL)
                   1864:                return (EINVAL);
                   1865:
                   1866:        card = NOCT_CARD(crp->crp_sid);
                   1867:        if (card >= noct_cd.cd_ndevs || noct_cd.cd_devs[card] == NULL)
                   1868:                return (EINVAL);
                   1869:        sc = noct_cd.cd_devs[card];
                   1870:
                   1871:        q = (struct noct_workq *)malloc(sizeof(struct noct_workq),
                   1872:            M_DEVBUF, M_NOWAIT);
                   1873:        if (q == NULL) {
                   1874:                err = ENOMEM;
                   1875:                goto errout;
                   1876:        }
                   1877:        q->q_crp = crp;
                   1878:
                   1879:        s = splnet();
                   1880:        SIMPLEQ_INSERT_TAIL(&sc->sc_inq, q, q_next);
                   1881:        splx(s);
                   1882:        NOCT_WAKEUP(sc);
                   1883:        return (0);
                   1884:
                   1885: errout:
                   1886:        if (q != NULL)
                   1887:                free(q, M_DEVBUF);
                   1888:        crp->crp_etype = err;
                   1889:        crypto_done(crp);
                   1890:        return (0);
                   1891: }

CVSweb