root/dev/pci/noct.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. noct_probe
  2. noct_attach
  3. noct_intr
  4. noct_ram_size
  5. noct_ram_write
  6. noct_ram_read
  7. noct_pkh_disable
  8. noct_pkh_enable
  9. noct_pkh_init
  10. noct_pkh_intr
  11. noct_rng_disable
  12. noct_rng_enable
  13. noct_rng_init
  14. noct_rng_intr
  15. noct_rng_tick
  16. noct_ea_nfree
  17. noct_ea_disable
  18. noct_ea_enable
  19. noct_ea_init
  20. noct_ea_create_thread
  21. noct_ea_thread
  22. noct_ea_start
  23. noct_ea_start_hash
  24. noct_ea_start_des
  25. noct_ea_intr
  26. noct_write_8
  27. noct_read_8
  28. noct_read_4
  29. noct_write_4
  30. noct_kfind
  31. noct_kprocess
  32. noct_pkh_nfree
  33. noct_kprocess_modexp
  34. noct_pkh_freedesc
  35. noct_ksigbits
  36. noct_kload
  37. noct_kload_cb
  38. noct_modmul_cb
  39. noct_newsession
  40. noct_freesession
  41. noct_process

    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 }

/* [<][>][^][v][top][bottom][index][help] */