root/dev/pci/ises.c

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

DEFINITIONS

This source file includes following definitions.
  1. ises_match
  2. ises_attach
  3. ises_initstate
  4. ises_queue_cmd
  5. ises_process_oqueue
  6. ises_intr
  7. ises_feed
  8. ises_newsession
  9. ises_freesession
  10. ises_process
  11. ises_callback
  12. ises_hrng_init
  13. ises_hrng
  14. ises_get_fwversion
  15. ises_assert_cmd_mode
  16. ises_bchu_switch_session
  17. ises_bchu_switch_final
  18. ises_read_dma
  19. ises_debug_init
  20. ises_debug_2
  21. ises_debug_simple_cmd
  22. ises_debug_loop
  23. ises_showreg
  24. ises_debug_parse_omr

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

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