1/*  *********************************************************************
2    *  Broadcom Common Firmware Environment (CFE)
3    *
4    *  BC5821 crypto accelerator driver	File: dev_bcm5821.c
5    *
6    *********************************************************************
7    *
8    *  Copyright 2000,2001,2002,2003
9    *  Broadcom Corporation. All rights reserved.
10    *
11    *  This software is furnished under license and may be used and
12    *  copied only in accordance with the following terms and
13    *  conditions.  Subject to these conditions, you may download,
14    *  copy, install, use, modify and distribute modified or unmodified
15    *  copies of this software in source and/or binary form.  No title
16    *  or ownership is transferred hereby.
17    *
18    *  1) Any source code used, modified or distributed must reproduce
19    *     and retain this copyright notice and list of conditions
20    *     as they appear in the source file.
21    *
22    *  2) No right is granted to use any trade name, trademark, or
23    *     logo of Broadcom Corporation.  The "Broadcom Corporation"
24    *     name may not be used to endorse or promote products derived
25    *     from this software without the prior written permission of
26    *     Broadcom Corporation.
27    *
28    *  3) THIS SOFTWARE IS PROVIDED "AS-IS" AND ANY EXPRESS OR
29    *     IMPLIED WARRANTIES, INCLUDING BUT NOT LIMITED TO, ANY IMPLIED
30    *     WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
31    *     PURPOSE, OR NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT
32    *     SHALL BROADCOM BE LIABLE FOR ANY DAMAGES WHATSOEVER, AND IN
33    *     PARTICULAR, BROADCOM SHALL NOT BE LIABLE FOR DIRECT, INDIRECT,
34    *     INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
35    *     (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
36    *     GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
37    *     BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
38    *     OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
39    *     TORT (INCLUDING NEGLIGENCE OR OTHERWISE), EVEN IF ADVISED OF
40    *     THE POSSIBILITY OF SUCH DAMAGE.
41    ********************************************************************* */
42
43/*
44   CFE Driver plus test programs for the BCM5820 and BCM5821 crypto
45   coprocessor chips.
46   Reference:
47     BCM5821 Super-eCommerce Processor
48     Data Sheet 5821-DS105-D1 (draft, 7/26/02)
49     Broadcom Corp., 16215 Alton Parkway, Irvine, CA.
50*/
51
52/* The performance counter usage assumes a BCM11xx or BCM1250 part */
53
54#include "sbmips.h"
55
56#if !defined(_SB14XX_) && !defined(_RM5200_) && !defined(_RM7000_)
57#define _SB1250_PERF_ 1
58#else
59#define _SB1250_PERF_ 0
60#endif
61
62#if _SB1250_PERF_
63#include "sb1250_defs.h"
64#include "sb1250_regs.h"
65#endif
66
67#ifndef _SB_MAKE64
68#define _SB_MAKE64(x) ((uint64_t)(x))
69#endif
70#ifndef _SB_MAKEMASK1
71#define _SB_MAKEMASK1(n) (_SB_MAKE64(1) << _SB_MAKE64(n))
72#endif
73
74#include "lib_types.h"
75#include "lib_physio.h"
76#include "lib_malloc.h"
77#include "lib_string.h"
78#include "lib_printf.h"
79#include "lib_queue.h"
80
81#include "addrspace.h"
82
83#include "cfe_iocb.h"
84#include "cfe_device.h"
85#include "cfe_timer.h"
86#include "cfe_devfuncs.h"
87#include "cfe_irq.h"
88
89#include "pcivar.h"
90#include "pcireg.h"
91
92#include "bcm5821.h"
93
94/* The version that works by polling the CPU's Cause register doesn't
95   do handshakes or checks to detect merged interrupts.  It currently
96   works when the 5821 is on the direct PCI bus but can behave
97   erratically when the 5821 is behind an LDT-to-PCI bridge that does
98   interrupt mapping and relies on EOI. */
99
100extern int32_t _getcause(void);		/* return value of CP0 CAUSE */
101
102#define IMR_POINTER(cpu,reg) \
103    ((volatile uint64_t *)(PHYS_TO_K1(A_IMR_REGISTER(cpu,reg))))
104
105#define CACHE_LINE_SIZE  32
106
107static void bcm5821_probe(cfe_driver_t *drv,
108			  unsigned long probe_a, unsigned long probe_b,
109			  void *probe_ptr);
110
111typedef struct bcm5821_state_s {
112    uint32_t  regbase;
113    uint8_t irq;
114    pcitag_t tag;		/* tag for configuration registers */
115
116    uint16_t  device;           /* chip device code */
117    uint8_t revision;           /* chip revision */
118
119} bcm5821_state_t;
120
121
122/* Address mapping macros */
123
124/* Note that PTR_TO_PHYS only works with 32-bit addresses, but then
125   so does the bcm528x. */
126#define PTR_TO_PHYS(x) (K0_TO_PHYS((uintptr_t)(x)))
127#define PHYS_TO_PTR(a) ((void *)PHYS_TO_K0(a))
128
129/* For the 5821, all mappings through the PCI host bridge use match
130   bits mode.  This works because the NORM_PCI bit in DMA Control is
131   clear.  The 5820 does not have such a bit, so pointers to data byte
132   sequences use match bytes, but control blocks use match bits. */
133#define PHYS_TO_PCI(a) ((uint32_t) (a) | 0x20000000)
134#define PHYS_TO_PCI_D(a) (a)
135#define PCI_TO_PHYS(a) ((uint32_t) (a) & 0x1FFFFFFF)
136
137#define READCSR(sc,csr)      (phys_read32((sc)->regbase + (csr)))
138#define WRITECSR(sc,csr,val) (phys_write32((sc)->regbase + (csr), (val)))
139
140
141static void
142dumpcsrs(bcm5821_state_t *sc, const char *legend)
143{
144    xprintf("%s:\n", legend);
145    xprintf("---DMA---\n");
146    /* DMA control and status registers */
147    xprintf("MCR1: %08X  CTRL: %08X  STAT: %08X  ERR:  %08X\n",
148	    READCSR(sc, R_MCR1), READCSR(sc, R_DMA_CTRL),
149	    READCSR(sc, R_DMA_STAT), READCSR(sc, R_DMA_ERR));
150    xprintf("MCR2: %08X\n", READCSR(sc, R_MCR2));
151    xprintf("-------------\n");
152}
153
154
155static void
156bcm5821_init(bcm5821_state_t *sc)
157{
158}
159
160static void
161bcm5821_hwinit(bcm5821_state_t *sc)
162{
163    uint32_t ctrl;
164    uint32_t status;
165
166    ctrl = (M_DMA_CTRL_MCR1_INT_EN | M_DMA_CTRL_MCR2_INT_EN |
167	    M_DMA_CTRL_DMAERR_EN);
168    if (sc->device == K_PCI_ID_BCM5820)
169      ctrl |= (M_DMA_CTRL_NORM_PCI | M_DMA_CTRL_LE_CRYPTO);
170    /* Note for 5821: M_DMA_CTRL_NORM_PCI, M_DMA_CTRL_LE_CRYPTO not set. */
171    WRITECSR(sc, R_DMA_CTRL, ctrl);
172
173    status = READCSR(sc, R_DMA_STAT);
174    WRITECSR(sc, R_DMA_STAT, status);    /* reset write-to-clear bits */
175    status = READCSR(sc, R_DMA_STAT);
176
177    dumpcsrs(sc, "init");
178}
179
180
181static void
182bcm5821_start(bcm5821_state_t *sc)
183{
184    bcm5821_hwinit(sc);
185}
186
187static void
188bcm5821_stop(bcm5821_state_t *sc)
189{
190    WRITECSR(sc, R_DMA_CTRL, 0);
191}
192
193
194static int bcm5821_open(cfe_devctx_t *ctx);
195static int bcm5821_read(cfe_devctx_t *ctx,iocb_buffer_t *buffer);
196static int bcm5821_inpstat(cfe_devctx_t *ctx,iocb_inpstat_t *inpstat);
197static int bcm5821_write(cfe_devctx_t *ctx,iocb_buffer_t *buffer);
198static int bcm5821_ioctl(cfe_devctx_t *ctx,iocb_buffer_t *buffer);
199static int bcm5821_close(cfe_devctx_t *ctx);
200
201const static cfe_devdisp_t bcm5821_dispatch = {
202    bcm5821_open,
203    bcm5821_read,
204    bcm5821_inpstat,
205    bcm5821_write,
206    bcm5821_ioctl,
207    bcm5821_close,
208    NULL,
209    NULL
210};
211
212cfe_driver_t bcm5821drv = {
213    "BCM582x crypto",
214    "crypt",
215    CFE_DEV_OTHER,
216    &bcm5821_dispatch,
217    bcm5821_probe
218};
219
220
221static int
222bcm5821_attach(cfe_driver_t *drv, pcitag_t tag, int index)
223{
224    bcm5821_state_t *sc;
225    char descr[80];
226    phys_addr_t pa;
227    uint32_t base;
228    pcireg_t device, class;
229
230    pci_map_mem(tag, PCI_MAPREG(0), PCI_MATCH_BITS, &pa);
231    base = (uint32_t)pa;
232
233    sc = (bcm5821_state_t *) KMALLOC(sizeof(bcm5821_state_t),0);
234    if (sc == NULL) {
235	xprintf("BCM5821: No memory to complete probe\n");
236	return 0;
237	}
238
239    memset(sc, 0, sizeof(*sc));
240
241    sc->regbase = base;
242
243    sc->irq = pci_conf_read(tag, PCI_BPARAM_INTERRUPT_REG) & 0xFF;
244
245    device = pci_conf_read(tag, PCI_ID_REG);
246    class = pci_conf_read(tag, PCI_CLASS_REG);
247
248    sc->tag = tag;
249    sc->device = PCI_PRODUCT(device);
250    sc->revision = PCI_REVISION(class);
251
252    bcm5821_init(sc);
253
254    xsprintf(descr, "BCM%04X Crypto at 0x%08X", sc->device, base);
255    cfe_attach(drv, sc, NULL, descr);
256
257    return 1;
258}
259
260static void
261bcm5821_probe(cfe_driver_t *drv,
262	      unsigned long probe_a, unsigned long probe_b,
263	      void *probe_ptr)
264{
265    int index;
266    int n;
267
268    n = 0;
269    index = 0;
270    for (;;) {
271	pcitag_t tag;
272	pcireg_t device;
273
274	if (pci_find_class(PCI_CLASS_PROCESSOR, index, &tag) != 0)
275	   break;
276
277	index++;
278
279	device = pci_conf_read(tag, PCI_ID_REG);
280	if (PCI_VENDOR(device) == K_PCI_VENDOR_BROADCOM) {
281	    if (PCI_PRODUCT(device) == K_PCI_ID_BCM5820 ||
282		PCI_PRODUCT(device) == K_PCI_ID_BCM5821) {
283		bcm5821_attach(drv, tag, n);
284		n++;
285		}
286	    }
287	}
288}
289
290
291/* The functions below are called via the dispatch vector for the 5821 */
292
293static int
294bcm5821_open(cfe_devctx_t *ctx)
295{
296    bcm5821_state_t *sc = ctx->dev_softc;
297
298    bcm5821_start(sc);
299    return 0;
300}
301
302static int
303bcm5821_read(cfe_devctx_t *ctx, iocb_buffer_t *buffer)
304{
305    return -1;
306}
307
308static int
309bcm5821_inpstat(cfe_devctx_t *ctx, iocb_inpstat_t *inpstat)
310{
311    return 0;
312}
313
314static int
315bcm5821_write(cfe_devctx_t *ctx, iocb_buffer_t *buffer)
316{
317    return -1;
318}
319
320static int
321bcm5821_ioctl(cfe_devctx_t *ctx, iocb_buffer_t *buffer)
322{
323    return -1;
324}
325
326static int
327bcm5821_close(cfe_devctx_t *ctx)
328{
329    bcm5821_state_t *sc = ctx->dev_softc;
330
331    bcm5821_stop(sc);
332    return 0;
333}
334
335
336/* Additional hooks for testing. */
337
338static int
339bcm5821_dump_cc1 (uint32_t *cc)
340{
341    int  i;
342    unsigned op = G_CC_OPCODE(cc[0]);
343    unsigned cc_words = G_CC_LEN(cc[0])/4;
344    int chain_out;        /* Whether the output is chained or fixed */
345
346    chain_out = 1;        /* default */
347
348    switch (op) {
349
350    case K_SSL_MAC:
351      xprintf("(SSL_MAC)\n");
352      for (i = 0; i < SSL_MAC_CMD_WORDS; i++)
353	xprintf("    %2d: %08x\n", i, cc[i]);
354      chain_out = 0;
355      break;
356
357    case K_ARC4:
358      xprintf("(ARCFOUR)\n");
359      for (i = 0; i < 3; i++)
360	xprintf("    %2d: %08x\n", i, cc[i]);
361      for (i = 0; i < 256/4; i += 4)
362	xprintf("    %2d: %08x %08x %08x %08x\n",
363		i+3, cc[i+3], cc[i+4], cc[i+5], cc[i+6]);
364      break;
365
366    case K_HASH:
367      xprintf("(HASH)\n");
368      for (i = 0; i < 2; i++)
369	xprintf("    %2d: %08x\n", i, cc[i]);
370      chain_out = 0;
371      break;
372
373    case K_TLS_HMAC:
374      chain_out = 0;
375      /* fall through */
376
377    default:  /* NYI: K_IPSEC_3DES (5821 only), K_SSL_3DES */
378      xprintf("\n");
379      for (i = 0; i < cc_words; i++)
380	xprintf("    %2d: %08x\n", i, cc[i]);
381      break;
382    }
383
384    return chain_out;
385}
386
387static int
388bcm5821_dump_cc2 (uint32_t *cc)
389{
390    int  i;
391    unsigned op = G_CC_OPCODE(cc[0]);
392    unsigned cc_words = G_CC_LEN(cc[0])/4;
393    int chain_out;        /* Whether the output is chained or fixed */
394
395    chain_out = 1;        /* default */
396
397    switch (op) {
398
399    case K_RNG_DIRECT:
400      xprintf("  RNG_DIRECT\n");
401      chain_out = 0;
402      for (i = 0; i < 1; i++)
403	xprintf("    %2d: %08x\n", i, cc[i]);
404      break;
405
406    case K_RNG_SHA1:
407      xprintf("  RNG_SHA1\n");
408      chain_out = 0;
409      for (i = 0; i < 1; i++)
410	xprintf("    %2d: %08x\n", i, cc[i]);
411      break;
412
413    default:  /* NYI: K_DH_*_GEN, K_RSA_*_OP, K_DSA_*, K_MOD_* */
414      xprintf("  %04x\n", op);
415      for (i = 0; i < cc_words; i++)
416	xprintf("    %2d: %08x\n", i, cc[i]);
417      break;
418    }
419    return chain_out;
420}
421
422static void
423bcm5821_dump_pkt (uint32_t *pkt, int port)
424{
425    uint32_t *cc = PHYS_TO_PTR(PCI_TO_PHYS(pkt[0]));
426    uint32_t *chain;
427    int chain_out;
428    int i, j;
429
430    xprintf("  %2d: %08x ", 0, pkt[0]);
431    chain_out = (port == 1 ? bcm5821_dump_cc1 : bcm5821_dump_cc2)(cc);
432
433    for (i = 1; i < PD_SIZE/4; i++) {
434      xprintf("  %2d: %08x\n", i, pkt[i]);
435
436      if (pkt[i] != 0) {
437	switch (i) {
438	case 2:
439	  chain = PHYS_TO_PTR(PCI_TO_PHYS(pkt[i]));
440	  for (j = 0; j < CHAIN_WORDS; j++)
441	    xprintf("    %2d: %08x\n", j, chain[j]);
442	  break;
443	case 6:
444	  if (chain_out) {
445	    chain = PHYS_TO_PTR(PCI_TO_PHYS(pkt[i]));
446	    for (j = 0; j < CHAIN_WORDS; j++)
447	      xprintf("    %2d: %08x\n", j, chain[j]);
448	  }
449	  break;
450	default:
451	  break;
452	}
453      }
454    }
455}
456
457static void
458bcm5821_dump_mcr (uint32_t mcr[], int port)
459{
460    unsigned i;
461    unsigned npkts = G_MCR_NUM_PACKETS(mcr[0]);
462
463    xprintf("MCR header %08x at %p:\n", mcr[0], mcr);
464    for (i = 0; i < npkts; i++) {
465      xprintf(" packet %d:\n", i+1);
466      bcm5821_dump_pkt(&mcr[1 + i*(PD_SIZE/4)], port);
467    }
468}
469
470
471static void
472bcm5821_show_pkt1 (uint32_t *pkt)
473{
474    uint32_t *cc = PHYS_TO_PTR(PCI_TO_PHYS(pkt[0]));
475    unsigned op = G_CC_OPCODE(cc[0]);
476    int i;
477
478    switch (op) {
479    case K_SSL_MAC:
480      {
481	uint32_t *hash = PHYS_TO_PTR(PCI_TO_PHYS(pkt[6]));
482	xprintf("SSL_MAC hash:\n");
483	xprintf("  %08x %08x %08x %08x\n",
484		hash[0], hash[1], hash[2], hash[3]);
485	xprintf("  %08x\n", hash[4]);
486      }
487      break;
488    case K_TLS_HMAC:
489      {
490	uint32_t *hash = PHYS_TO_PTR(PCI_TO_PHYS(pkt[7]));
491	xprintf("TLS_HMAC hash:\n");
492	xprintf("  %08x %08x %08x %08x\n",
493		hash[0], hash[1], hash[2], hash[3]);
494	xprintf("  %08x\n", hash[4]);
495      }
496      break;
497    case K_ARC4:
498      {
499	uint32_t *output = PHYS_TO_PTR(PCI_TO_PHYS(pkt[5]));
500	uint32_t *chain =  PHYS_TO_PTR(PCI_TO_PHYS(pkt[6]));
501	uint32_t *update = PHYS_TO_PTR(PCI_TO_PHYS(chain[0]));
502
503	xprintf("ARCFOUR output\n");
504	for (i = 0; i < 64; i += 4)
505	  xprintf (" %08x %08x %08x %08x\n",
506		   output[i+0], output[i+1], output[i+2], output[i+3]);
507	xprintf("ARCFOUR update\n");
508	xprintf(" %08x\n", update[0]);
509	for (i = 0; i < 256/4; i += 4)
510	  xprintf (" %08x %08x %08x %08x\n",
511		   update[i+1], update[i+2], update[i+3], update[i+4]);
512      }
513      break;
514    case K_HASH:
515      {
516	uint8_t *digest = PHYS_TO_PTR(PCI_TO_PHYS(pkt[6]));
517
518	xprintf("HASH digest ");
519	for (i = 0; i < 16; i++)
520	  xprintf("%02x", digest[i]);
521	xprintf("\n");
522      }
523      break;
524    default:
525      break;
526    }
527}
528
529static void
530bcm5821_show_pkt2 (uint32_t *pkt)
531{
532    uint32_t *cc = PHYS_TO_PTR(PCI_TO_PHYS(pkt[0]));
533    unsigned op = G_CC_OPCODE(cc[0]);
534    int i;
535
536    switch (op) {
537    case K_RNG_DIRECT:
538    case K_RNG_SHA1:
539      {
540	uint32_t *output = PHYS_TO_PTR(PCI_TO_PHYS(pkt[5]));
541	size_t len = V_DBC_DATA_LEN(pkt[7])/sizeof(uint32_t);
542
543	xprintf("RNG output\n");
544	for (i = 0; i < len; i += 4)
545	  xprintf (" %08x %08x %08x %08x\n",
546		   output[i+0], output[i+1], output[i+2], output[i+3]);
547      }
548      break;
549    default:
550      break;
551    }
552}
553
554static void
555bcm5821_show_mcr (uint32_t mcr[], int port)
556{
557    unsigned i;
558    unsigned npkts = G_MCR_NUM_PACKETS(mcr[0]);
559
560    xprintf("MCR at %p:\n", mcr);
561    for (i = 0; i < npkts; i++) {
562      xprintf("packet %d:\n", i+1);
563      if (port == 1)
564	bcm5821_show_pkt1(&mcr[1 + i*(PD_SIZE/4)]);
565      else
566	bcm5821_show_pkt2(&mcr[1 + i*(PD_SIZE/4)]);
567    }
568}
569
570
571static uint32_t *
572bcm5821_alloc_hash (const uint8_t *msg, size_t msg_len, int swap)
573{
574    uint32_t *mcr;
575    uint32_t *cmd;    /* always reads at least 64 bytes */
576    uint8_t  *message;
577    uint8_t  *digest;
578    int i;
579
580    message = KMALLOC(msg_len, CACHE_LINE_SIZE);
581    for (i = 0; i < msg_len; i++)
582      message[i] = msg[i];
583
584    digest = KMALLOC(16, CACHE_LINE_SIZE);
585    for (i = 0; i < 16; i++)
586      digest[i] = 0;
587
588    mcr = KMALLOC(MCR_WORDS(1)*4, CACHE_LINE_SIZE);
589    mcr[0] = V_MCR_NUM_PACKETS(1);
590
591    cmd = KMALLOC(64, CACHE_LINE_SIZE);   /* Always allocate >= 64 bytes */
592    cmd[0] = V_CC_OPCODE(K_HASH) | V_CC_LEN(8);
593    cmd[1] = V_CC_FLAGS(K_HASH_FLAGS_MD5);
594
595    mcr[1] = PHYS_TO_PCI(PTR_TO_PHYS(cmd));
596
597    /* input fragment */
598    mcr[2] = swap ? PHYS_TO_PCI_D(PTR_TO_PHYS(message))
599                  : PHYS_TO_PCI(PTR_TO_PHYS(message));
600    mcr[3] = 0;
601    mcr[4] = V_DBC_DATA_LEN(msg_len);
602
603    mcr[5] = V_PD_PKT_LEN(msg_len);
604
605    mcr[6] = 0;
606    mcr[7] = swap ? PHYS_TO_PCI_D(PTR_TO_PHYS(digest))
607                  : PHYS_TO_PCI(PTR_TO_PHYS(digest));
608    mcr[8] = 0;
609
610    return mcr;
611}
612
613static void
614bcm5821_free_hash (uint32_t mcr[])
615{
616    KFREE(PHYS_TO_PTR(PCI_TO_PHYS(mcr[1])));
617    KFREE(PHYS_TO_PTR(PCI_TO_PHYS(mcr[2])));
618    KFREE(PHYS_TO_PTR(PCI_TO_PHYS(mcr[7])));
619
620    KFREE(mcr);
621}
622
623
624static uint32_t *
625bcm5821_alloc_hmac (const char *key, int key_len,
626		    const char *msg, int msg_len,
627		    int swap)
628{
629    uint32_t *message;
630    uint32_t *cmd;
631    uint32_t *mcr;
632    uint32_t *hash;
633    int i;
634
635    message = KMALLOC(msg_len, CACHE_LINE_SIZE);
636    memcpy((uint8_t *)message, msg, msg_len);
637
638    mcr = KMALLOC(MCR_WORDS(1)*4, CACHE_LINE_SIZE);
639    mcr[0] = V_MCR_NUM_PACKETS(1);
640
641    /* packet 1 */
642
643    cmd = KMALLOC(TLS_HMAC_CMD_WORDS*4, CACHE_LINE_SIZE);
644    cmd[0] = V_CC_OPCODE(K_TLS_HMAC) | V_CC_LEN(TLS_HMAC_CMD_WORDS*4);
645    cmd[1] = V_CC_FLAGS(K_HASH_FLAGS_MD5);
646
647    for (i = 2; i < 7; i++)
648      cmd[i] = 0x36363636;
649    cmd[6] = 0x00000000;      /* must be zero for SSL */
650    for (i = 8; i < 13; i++)
651      cmd[i] = 0x5c5c5c5c;
652    cmd[13] = 0;              /* seq num */
653    cmd[14] = 1;
654    cmd[15] = 0x03000000 | (msg_len << 8);
655
656    mcr[1] = PHYS_TO_PCI(PTR_TO_PHYS(cmd));
657
658    /* input fragment */
659    mcr[2] = swap ? PHYS_TO_PCI_D(PTR_TO_PHYS(message))
660                  : PHYS_TO_PCI(PTR_TO_PHYS(message));
661    mcr[3] = 0;
662    mcr[4] = V_DBC_DATA_LEN(msg_len);
663
664    mcr[5] = V_PD_PKT_LEN(msg_len);
665
666    hash = KMALLOC(5*4, CACHE_LINE_SIZE);
667    for (i = 0; i < 5; i++)
668      hash[i] = 0;
669
670    mcr[6] = 0;
671    mcr[7] = swap ? PHYS_TO_PCI_D(PTR_TO_PHYS(hash))
672                  : PHYS_TO_PCI(PTR_TO_PHYS(hash));
673    mcr[8] = 0;
674
675    return mcr;
676}
677
678static void
679bcm5821_free_hmac (uint32_t mcr[])
680{
681    KFREE(PHYS_TO_PTR(PCI_TO_PHYS(mcr[1])));
682    KFREE(PHYS_TO_PTR(PCI_TO_PHYS(mcr[2])));
683    KFREE(PHYS_TO_PTR(PCI_TO_PHYS(mcr[7])));
684
685    KFREE(mcr);
686}
687
688
689static int test_init = 0;
690
691/* Timing */
692
693#if _SB1250_PERF_
694/* For Pass 1, dedicate an SCD peformance counter to use as a counter
695   of ZBbus cycles. */
696#include "sb1250_scd.h"
697#define ZCTR_MODULUS  0x10000000000LL
698
699/* The counter is a shared resource that must be reset periodically
700   since it doesn't roll over.  Furthermore, there is a pass one bug
701   that makes the interrupt unreliable and the final value either all
702   ones or all zeros.  We therefore reset the count when it exceeds
703   half the modulus.  We also assume that intervals of interest
704   are much less than half the modulus and attempt to adjust for
705   the reset in zclk_elapsed. */
706
707static void
708zclk_init(uint64_t val)
709{
710    *((volatile uint64_t *) UNCADDR(A_SCD_PERF_CNT_0)) = val;
711    *((volatile uint64_t *) UNCADDR(A_SCD_PERF_CNT_CFG)) =
712        V_SPC_CFG_SRC0(1) | M_SPC_CFG_ENABLE;
713}
714
715static uint64_t
716zclk_get(void)
717{
718    uint64_t ticks;
719
720    ticks = *((volatile uint64_t *) UNCADDR(A_SCD_PERF_CNT_0));
721    if (ticks == 0 || ticks == ZCTR_MODULUS-1) {
722	ticks = 0;
723	zclk_init(ticks);
724	}
725    else if (ticks >= ZCTR_MODULUS/2) {
726	ticks -= ZCTR_MODULUS/2;
727	zclk_init(ticks);  /* Ignore the fudge and lose a few ticks */
728	}
729    return ticks;
730}
731
732static uint64_t
733zclk_elapsed(uint64_t stop, uint64_t start)
734{
735    return ((stop >= start) ? stop : stop + ZCTR_MODULUS/2) - start;
736}
737
738#else /* !_SB1250_PERF_ */
739static void
740zclk_init(uint64_t val)
741{
742}
743
744static uint64_t
745zclk_get(void)
746{
747    return 0;
748}
749
750static uint64_t
751zclk_elapsed(uint64_t stop, uint64_t start)
752{
753    return 0;
754}
755#endif /* _SB1250_PERF_ */
756
757
758/* Auxiliary functions */
759
760static uint32_t *
761bcm5821_alloc_composite(int input_size)
762{
763    uint32_t *input, *output;
764    uint32_t *cmd;
765    uint32_t *chain;
766    uint32_t *mcr;
767    uint32_t *hash;
768    uint32_t *update;
769    uint8_t *arc4_state;
770    int i;
771
772    input = KMALLOC(input_size, CACHE_LINE_SIZE);
773    for (i = 0; i < input_size; i++)
774      ((uint8_t *)input)[i] = i & 0xFF;
775    output = KMALLOC(input_size + 16, CACHE_LINE_SIZE);
776    for (i = 0; i < input_size + 16; i++)
777      ((uint8_t *)output)[i] = 0xFF;
778
779    mcr = KMALLOC(MCR_WORDS(2)*4, CACHE_LINE_SIZE);
780    mcr[0] = V_MCR_NUM_PACKETS(2);
781
782    /* packet 1 */
783
784    cmd = KMALLOC(SSL_MAC_CMD_WORDS*4, CACHE_LINE_SIZE);
785    cmd[0] = V_CC_OPCODE(K_SSL_MAC) | V_CC_LEN(SSL_MAC_CMD_WORDS*4);
786    cmd[1] = V_CC_FLAGS(K_HASH_FLAGS_MD5);
787    for (i = 2; i < 6; i++)
788      cmd[i] = 0x01020304;
789    cmd[6] = 0x00000000;      /* must be zero for SSL */
790    for (i = 7; i < 19; i++)
791      cmd[i] = 0x36363636;
792    cmd[19] = 0;              /* seq num */
793    cmd[20] = 1;
794    cmd[21] = 0x03000000 | (input_size << 8);   /* type/len/rsvd */
795
796    mcr[1] = PHYS_TO_PCI(PTR_TO_PHYS(cmd));
797
798    /* input fragment */
799    mcr[2] = PHYS_TO_PCI(PTR_TO_PHYS(input));
800    mcr[3] = 0;
801    mcr[4] = V_DBC_DATA_LEN(input_size);
802
803    mcr[5] = V_PD_PKT_LEN(input_size);
804
805    hash = KMALLOC(5*4, CACHE_LINE_SIZE);
806    for (i = 0; i < 5; i++)
807      hash[i] = 0;
808
809    mcr[6] = 0;
810    mcr[7] = PHYS_TO_PCI(PTR_TO_PHYS(hash));
811    mcr[8] = 0;
812
813    /* packet 2 */
814
815    cmd = KMALLOC(ARC4_CMD_WORDS*4, CACHE_LINE_SIZE);
816    cmd[0] = V_CC_OPCODE(K_ARC4) | V_CC_LEN(ARC4_CMD_WORDS*4);
817    cmd[1] = M_ARC4_FLAGS_WRITEBACK;
818    cmd[2] = 0x000100F3;
819    arc4_state = (uint8_t *)&cmd[3];
820    for (i = 0; i < 256; i++)
821      arc4_state[i] = i;
822
823    mcr[8+1] = PHYS_TO_PCI(PTR_TO_PHYS(cmd));
824
825    /* input fragment */
826    chain = KMALLOC(CHAIN_WORDS*4, CACHE_LINE_SIZE);
827
828    mcr[8+2] = PHYS_TO_PCI(PTR_TO_PHYS(input));
829    mcr[8+3] = PHYS_TO_PCI(PTR_TO_PHYS(chain));
830    mcr[8+4] = V_DBC_DATA_LEN(input_size);
831
832    /* MAC fragment */
833    chain[0] = PHYS_TO_PCI(PTR_TO_PHYS(hash));
834    chain[1] = 0;
835    chain[2] = V_DBC_DATA_LEN(16);
836
837    mcr[8+5] = V_PD_PKT_LEN(input_size + 16);
838
839    /* output fragment */
840    chain = KMALLOC(CHAIN_WORDS*4, CACHE_LINE_SIZE);
841
842    mcr[8+6] = PHYS_TO_PCI(PTR_TO_PHYS(output));
843    mcr[8+7] = PHYS_TO_PCI(PTR_TO_PHYS(chain));
844    mcr[8+8] = V_DBC_DATA_LEN(input_size + 16);
845
846    update = KMALLOC(ARC4_STATE_WORDS*4, CACHE_LINE_SIZE);
847    for (i = 0; i < ARC4_STATE_WORDS; i++)
848      update[i] = 0xFFFFFFFF;
849
850    /* output update */
851    chain[0] = PHYS_TO_PCI(PTR_TO_PHYS(update));
852    chain[1] = 0;
853    chain[2] = V_DBC_DATA_LEN(ARC4_STATE_WORDS*4);  /* not actually used */
854
855    return mcr;
856}
857
858static void
859bcm5821_free_composite (uint32_t mcr[])
860{
861    uint32_t *chain;
862
863    /* packet 1 */
864
865    KFREE(PHYS_TO_PTR(PCI_TO_PHYS(mcr[1])));
866    KFREE(PHYS_TO_PTR(PCI_TO_PHYS(mcr[2])));
867    KFREE(PHYS_TO_PTR(PCI_TO_PHYS(mcr[7])));
868
869    /* packet 2 */
870    KFREE(PHYS_TO_PTR(PCI_TO_PHYS(mcr[8+1])));
871    /* mcr[8+2] already freed */
872    chain = PHYS_TO_PTR(PCI_TO_PHYS(mcr[8+3]));
873    KFREE(PHYS_TO_PTR(PCI_TO_PHYS(chain[0])));  KFREE(chain);
874    KFREE(PHYS_TO_PTR(PCI_TO_PHYS(mcr[8+6])));
875    chain = PHYS_TO_PTR(PCI_TO_PHYS(mcr[8+7]));
876    KFREE(PHYS_TO_PTR(PCI_TO_PHYS(chain[0])));  KFREE(chain);
877
878    KFREE(mcr);
879}
880
881
882static void
883flush_l2(void)
884{
885  /* Temporary hack: churn through all of L2 */
886  volatile uint64_t *lomem;
887  uint64_t t;
888  int i;
889
890  lomem = (uint64_t *)(0xFFFFFFFF80000000LL);   /* kseg0 @ 0 */
891  t = 0;
892  for (i = 0; i < (512/8)*1024; i++)
893    t ^= lomem[i];
894}
895
896#ifdef IRQ
897static void
898bcm5821_interrupt(void *ctx)
899{
900}
901#endif
902
903
904#define POOL_SIZE       4
905#define MCR_QUEUE_DEPTH 2
906
907static int
908bcm5821_composite (bcm5821_state_t *sc, size_t len, int trials)
909{
910    uint32_t *mcr[POOL_SIZE];
911    uint32_t status;
912    uint64_t start, stop, ticks;
913    uint64_t tpb, Mbs;
914    int i;
915    int next, last, run;
916
917    for (i = 0; i < POOL_SIZE; i++)
918      mcr[i] = bcm5821_alloc_composite(len);
919
920    (void)bcm5821_dump_mcr;  /*bcm5821_dump_mcr(mcr[0], 1);*/
921
922    next = last = 0;
923    run = 0;
924
925    /* Force all descriptors and buffers out of L1 */
926    cfe_flushcache(CFE_CACHE_FLUSH_D);
927    (void)flush_l2;
928
929    status = READCSR(sc, R_DMA_STAT);
930    WRITECSR(sc, R_DMA_STAT, status);    /* clear pending bits */
931    status = READCSR(sc, R_DMA_STAT);
932
933    for (i = 0; i < 1000; i++) {
934      status = READCSR(sc, R_DMA_STAT);
935      if ((status & M_DMA_STAT_MCR1_FULL) == 0)
936	break;
937      cfe_sleep(1);
938    }
939    if (i == 1000) {
940      dumpcsrs(sc, "bcm5821: full bit never clears");
941      return -1;
942    }
943
944#ifdef IRQ
945    /* Enable interrupt polling, but the handler is never called. */
946    cfe_request_irq(sc->irq, bcm5821_interrupt, NULL, 0, 0);
947#endif
948
949    zclk_init(0);     /* Time origin is arbitrary. */
950    start = zclk_get();
951
952    /* MCR ports are double buffered. */
953    for (i = 0; i < MCR_QUEUE_DEPTH; i++) {
954      while ((READCSR(sc, R_DMA_STAT) & M_DMA_STAT_MCR1_FULL) != 0)
955	continue;
956      WRITECSR(sc, R_MCR1, PHYS_TO_PCI(PTR_TO_PHYS(mcr[next])));
957      next = (next + 1) % POOL_SIZE;
958    }
959
960    while (1) {
961#ifdef IRQ
962      while ((_getcause() & M_CAUSE_IP2) == 0)
963	continue;
964
965      status = READCSR(sc, R_DMA_STAT);
966      if ((status & M_DMA_STAT_MCR1_INTR) == 0) {
967	/* This apparently is MCR1_ALL_EMPTY, timing of which is unclear. */
968	WRITECSR(sc, R_DMA_STAT,
969		 M_DMA_STAT_DMAERR_INTR | M_DMA_STAT_MCR1_INTR);
970	continue;
971      }
972
973      stop = zclk_get();
974      WRITECSR(sc, R_DMA_STAT,
975	       M_DMA_STAT_DMAERR_INTR | M_DMA_STAT_MCR1_INTR);
976#else
977      volatile uint32_t *last_mcr = mcr[last];
978
979      while ((*last_mcr & M_MCR_DONE) == 0)
980	continue;
981
982      stop = zclk_get();
983#endif
984
985      run++;
986      if (run == trials)
987	break;
988
989      while ((READCSR(sc, R_DMA_STAT) & M_DMA_STAT_MCR1_FULL) != 0)
990	continue;
991      WRITECSR(sc, R_MCR1, PHYS_TO_PCI(PTR_TO_PHYS(mcr[next])));
992      next = (next + 1) % POOL_SIZE;
993
994      /* Clear the DONE and ERROR bits.  This will bring one line of
995         the MCR back into L1.  Flush? */
996      mcr[last][0] = V_MCR_NUM_PACKETS(2);
997      last = (last + 1) % POOL_SIZE;
998    }
999
1000#ifdef IRQ
1001    status = READCSR(sc, R_DMA_STAT);
1002    WRITECSR(sc, R_DMA_STAT, status);    /* clear pending bits */
1003    cfe_free_irq(sc->irq, 0);
1004#endif
1005
1006    ticks = zclk_elapsed(stop, start) / trials;
1007    xprintf("bcm5821: Composite %lld ticks for %d bytes, %d packets\n",
1008	    ticks, len, trials);
1009    /* Scaling for two decimal places. */
1010    tpb = (ticks*100) / len;
1011    Mbs = (2000*100)*100 / tpb;
1012    xprintf("  rate %lld.%02lld Mbps\n", Mbs/100, Mbs % 100);
1013
1014    if (trials == 1)
1015      {
1016	bcm5821_show_mcr(mcr[0], 1);
1017      }
1018
1019    for (i = 0; i < POOL_SIZE; i++)
1020      bcm5821_free_composite(mcr[i]);
1021
1022    return 0;
1023}
1024
1025
1026/* The following code depends on having a separate interrupt per
1027   device, and there are only 4 PCI interrupts. */
1028#define MAX_DEVICES 4
1029
1030struct dev_info {
1031    bcm5821_state_t *sc;
1032    uint64_t         irq_mask;
1033    int              index[MCR_QUEUE_DEPTH];
1034};
1035
1036
1037#define N_DEVICES  2
1038
1039static int
1040bcm5821_composite2 (bcm5821_state_t *sc0, bcm5821_state_t *sc1,
1041		    size_t len, int trials)
1042{
1043    uint32_t *mcr[POOL_SIZE];
1044    uint32_t ring[POOL_SIZE];
1045    uint32_t status;
1046    uint64_t start, stop, ticks;
1047    uint64_t tpb, Mbs;
1048    int i;
1049    int next, last;
1050    int started, run;
1051    int d;
1052    struct dev_info dev[N_DEVICES];
1053    uint64_t masks;
1054    bcm5821_state_t *sc;
1055#ifdef IRQ
1056    volatile uint64_t *irqstat = IMR_POINTER(0, R_IMR_INTERRUPT_SOURCE_STATUS);
1057#endif
1058    uint64_t pending;
1059
1060    dev[0].sc = sc0;  dev[1].sc = sc1;
1061
1062    for (i = 0; i < POOL_SIZE; i++)
1063      mcr[i] = bcm5821_alloc_composite(len);
1064    for (i = 0; i < POOL_SIZE; i++)
1065      ring[i] = i;
1066    next = last = 0;
1067
1068    (void)bcm5821_dump_mcr;  /*bcm5821_dump_mcr(mcr[0], 1);*/
1069
1070    started = run = 0;
1071
1072    /* Force all descriptors and buffers out of L1 */
1073    cfe_flushcache(CFE_CACHE_FLUSH_D);
1074    (void)flush_l2;
1075
1076    masks = 0;
1077    for (d = 0; d < N_DEVICES; d++) {
1078      sc = dev[d].sc;
1079      dev[d].irq_mask = 1LL << (sc->irq);
1080      masks |= dev[d].irq_mask;
1081
1082      status = READCSR(sc, R_DMA_STAT);
1083      WRITECSR(sc, R_DMA_STAT, status);    /* clear pending bits */
1084      status = READCSR(sc, R_DMA_STAT);
1085
1086      for (i = 0; i < 1000; i++) {
1087	status = READCSR(sc, R_DMA_STAT);
1088	if ((status & M_DMA_STAT_MCR1_FULL) == 0)
1089	  break;
1090	cfe_sleep(1);
1091      }
1092
1093      if (i == 1000) {
1094	dumpcsrs(sc, "bcm5821: full bit never clears");
1095	return -1;
1096      }
1097
1098#ifdef IRQ
1099      /* Enable interrupt polling, but the handler is never called. */
1100      cfe_request_irq(sc->irq, bcm5821_interrupt, NULL, 0, 0);
1101#endif
1102    }
1103
1104    stop = 0;         /* Keep compiler happy */
1105    zclk_init(0);     /* Time origin is arbitrary. */
1106    start = zclk_get();
1107
1108    for (d = 0; d < N_DEVICES; d++) {
1109      sc = dev[d].sc;
1110
1111      /* MCR ports are double buffered. */
1112      for (i = 0; i < 2; i++) {
1113	int index = ring[next];
1114	while ((READCSR(sc, R_DMA_STAT) & M_DMA_STAT_MCR1_FULL) != 0)
1115	  continue;
1116	WRITECSR(sc, R_MCR1, PHYS_TO_PCI(PTR_TO_PHYS(mcr[index])));
1117	dev[d].index[i] = index;
1118	next = (next + 1) % POOL_SIZE;
1119	started++;
1120      }
1121    }
1122
1123    while (trials == 0 || run != trials) {
1124#ifdef IRQ
1125      while ((_getcause() & M_CAUSE_IP2) == 0)
1126	continue;
1127
1128      pending = *irqstat;
1129#else
1130      pending = 0;
1131      while (pending == 0) {
1132	for (d = 0; d < N_DEVICES; d++) {
1133	  volatile uint32_t *last_mcr = mcr[dev[d].index[0]];
1134
1135	  if ((*last_mcr & M_MCR_DONE) != 0)
1136	    pending |= dev[d].irq_mask;
1137	}
1138      }
1139#endif
1140
1141      stop = zclk_get();
1142
1143      for (d = 0; d < N_DEVICES; d++) {
1144	if ((dev[d].irq_mask & pending) != 0) {
1145	  sc = dev[d].sc;
1146
1147#ifdef IRQ
1148          status = READCSR(sc, R_DMA_STAT);
1149	  if ((status & M_DMA_STAT_MCR1_INTR) == 0) {
1150	    /* Apparently MCR1_ALL_EMPTY, timing of which is unclear. */
1151	    WRITECSR(sc, R_DMA_STAT,
1152		     M_DMA_STAT_DMAERR_INTR | M_DMA_STAT_MCR1_INTR);
1153	    continue;
1154	  }
1155	  WRITECSR(sc, R_DMA_STAT,
1156		   M_DMA_STAT_DMAERR_INTR | M_DMA_STAT_MCR1_INTR);
1157#endif
1158	  ring[last] = dev[d].index[0];
1159	  /* Clear the DONE and ERROR bits.  This will bring one line of
1160	     the MCR back into L1.  Flush? */
1161	  mcr[ring[last]][0] = V_MCR_NUM_PACKETS(2);
1162	  last = (last + 1) % POOL_SIZE;
1163
1164	  run++;
1165	  if (run == trials)
1166	    break;
1167
1168	  dev[d].index[0] = dev[d].index[1];
1169	  if (trials == 0 || started < trials) {
1170	    int index = ring[next];
1171	    while ((READCSR(sc, R_DMA_STAT) & M_DMA_STAT_MCR1_FULL) != 0)
1172	      continue;
1173	    WRITECSR(sc, R_MCR1, PHYS_TO_PCI(PTR_TO_PHYS(mcr[index])));
1174	    dev[d].index[1] = index;
1175	    next = (next + 1) % POOL_SIZE;
1176	    started++;
1177	  }
1178	}
1179      }
1180    }
1181
1182    for (d = 0; d < N_DEVICES; d++) {
1183      sc = dev[d].sc;
1184      status = READCSR(sc, R_DMA_STAT);
1185      WRITECSR(sc, R_DMA_STAT, status);    /* clear pending bits */
1186#ifdef IRQ
1187      cfe_free_irq(sc->irq, 0);
1188#endif
1189    }
1190
1191    ticks = zclk_elapsed(stop, start) / trials;
1192    xprintf("bcm5821: Composite %lld ticks for %d bytes, %d packets\n",
1193	    ticks, len, trials);
1194    /* Scaling for two decimal places. */
1195    tpb = (ticks*100) / len;
1196    Mbs = (2000*100)*100 / tpb;
1197    xprintf("  rate %lld.%02lld Mbps\n", Mbs/100, Mbs % 100);
1198
1199    for (i = 0; i < POOL_SIZE; i++)
1200      bcm5821_free_composite(mcr[i]);
1201
1202    return 0;
1203}
1204
1205
1206extern cfe_devctx_t *cfe_handle_table[];
1207
1208int bcm5821_test (int device, int trials);
1209int
1210bcm5821_test (int device, int trials)
1211{
1212    cfe_devctx_t *ctx = cfe_handle_table[device];
1213    bcm5821_state_t *sc = ctx->dev_softc;
1214
1215    if (!test_init) {
1216      zclk_init(0);     /* Time origin is arbitrary */
1217      test_init = 1;
1218    }
1219
1220    bcm5821_composite(sc, 1472, trials);
1221
1222    return 0;
1223}
1224
1225int bcm5821_test2 (int device0, int device2, int trials);
1226int
1227bcm5821_test2 (int device0, int device1, int trials)
1228{
1229    cfe_devctx_t *ctx0 = cfe_handle_table[device0];
1230    cfe_devctx_t *ctx1 = cfe_handle_table[device1];
1231    bcm5821_state_t *sc0 = ctx0->dev_softc;
1232    bcm5821_state_t *sc1 = ctx1->dev_softc;
1233
1234    if (!test_init) {
1235      zclk_init(0);     /* Time origin is arbitrary */
1236      test_init = 1;
1237    }
1238
1239    bcm5821_composite2(sc0, sc1, 1472, trials);
1240
1241    return 0;
1242}
1243
1244
1245static int
1246bcm5821_hash_md5 (bcm5821_state_t *sc, const char *msg)
1247{
1248    size_t len = strlen(msg);
1249    uint32_t *mcr;
1250    uint32_t status;
1251    int i;
1252    int swap = (sc->device == K_PCI_ID_BCM5820);
1253
1254    mcr = bcm5821_alloc_hash(msg, len, swap);
1255
1256    /* bcm5821_dump_mcr(mcr, 1); */
1257
1258    status = READCSR(sc, R_DMA_STAT);
1259    WRITECSR(sc, R_DMA_STAT, status);    /* clear pending bits */
1260    status = READCSR(sc, R_DMA_STAT);
1261
1262    for (i = 0; i < 1000; i++) {
1263      status = READCSR(sc, R_DMA_STAT);
1264      if ((status & M_DMA_STAT_MCR1_FULL) == 0)
1265	break;
1266      cfe_sleep(1);
1267    }
1268    if (i == 1000) {
1269      dumpcsrs(sc, "bcm5821: full bit never clears");
1270      return -1;
1271    }
1272
1273    WRITECSR(sc, R_MCR1, PHYS_TO_PCI(PTR_TO_PHYS(mcr)));
1274
1275    for (i = 0; i < 1000; i++) {
1276#ifdef IRQ
1277      status = READCSR(sc, R_DMA_STAT);
1278      if ((status & M_DMA_STAT_MCR1_INTR) != 0)
1279	break;
1280#else
1281      if ((mcr[0] & M_MCR_DONE) != 0)
1282	break;
1283#endif
1284      cfe_sleep(1);
1285    }
1286    if (i == 1000) {
1287      dumpcsrs(sc, "bcm5821: done bit never sets");
1288      /*return -1;*/
1289    }
1290
1291    status = READCSR(sc, R_DMA_STAT);
1292    WRITECSR(sc, R_DMA_STAT, status);    /* clear pending bits */
1293
1294    /* bcm5821_dump_mcr(mcr, 1); */
1295
1296    bcm5821_show_mcr(mcr, 1);
1297
1298    bcm5821_free_hash(mcr);
1299
1300    return 0;
1301}
1302
1303
1304static int
1305bcm5821_hmac_md5 (bcm5821_state_t *sc,
1306		  const uint8_t key[],  size_t key_len,
1307		  const uint8_t data[], size_t data_len)
1308{
1309    uint32_t *mcr;
1310    uint32_t status;
1311    int i;
1312    int swap = (sc->device == K_PCI_ID_BCM5820);
1313
1314    mcr = bcm5821_alloc_hmac(key, key_len, data, data_len, swap);
1315
1316    status = READCSR(sc, R_DMA_STAT);
1317    WRITECSR(sc, R_DMA_STAT, status);    /* clear pending bits */
1318    status = READCSR(sc, R_DMA_STAT);
1319
1320    for (i = 0; i < 1000; i++) {
1321      status = READCSR(sc, R_DMA_STAT);
1322      if ((status & M_DMA_STAT_MCR1_FULL) == 0)
1323	break;
1324      cfe_sleep(1);
1325    }
1326    if (i == 1000) {
1327      dumpcsrs(sc, "bcm5821: full bit never clears");
1328      return -1;
1329    }
1330
1331    bcm5821_free_hmac(mcr);
1332    return 0;
1333}
1334
1335/* Sanity check on the implementation using RFC test suites. */
1336
1337int bcm5821_check (int device);
1338int
1339bcm5821_check (int device)
1340{
1341    static unsigned char k1[16] = {
1342      0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b,
1343      0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b
1344    };
1345    static unsigned char m1[] = "Hi There";
1346
1347    static unsigned char k2[] = "Jefe";
1348    static unsigned char m2[] = "what do ya want for nothing?";
1349
1350    static unsigned char k3[16] = {
1351      0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA,
1352      0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA
1353    };
1354    static unsigned char m3[50] = {
1355      0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD,
1356      0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD,
1357      0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD,
1358      0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD,
1359      0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD
1360    };
1361
1362    cfe_devctx_t *ctx = cfe_handle_table[device];
1363    bcm5821_state_t *sc = ctx->dev_softc;
1364
1365    if (!test_init) {
1366      zclk_init(0);     /* Time origin is arbitrary */
1367      test_init = 1;
1368    }
1369
1370    bcm5821_hash_md5(sc, "a");
1371    bcm5821_hash_md5(sc, "abc");
1372    bcm5821_hash_md5(sc, "message digest");
1373    bcm5821_hash_md5(sc, "abcdefghijklmnopqrstuvwxyz");
1374    bcm5821_hash_md5(sc, "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789");
1375    bcm5821_hash_md5(sc, "12345678901234567890123456789012345678901234567890123456789012345678901234567890");
1376
1377    bcm5821_hmac_md5(sc, k1, sizeof(k1), m1, strlen(m1));
1378    bcm5821_hmac_md5(sc, k2, strlen(k2), m2, strlen(m2));
1379    bcm5821_hmac_md5(sc, k3, sizeof(k3), m3, sizeof(m3));
1380
1381    return 0;
1382}
1383
1384/* Output of md5 test suite (md5 -x)
1385
1386MD5 test suite:
1387MD5 ("") = d41d8cd98f00b204e9800998ecf8427e
1388MD5 ("a") = 0cc175b9c0f1b6a831c399e269772661
1389MD5 ("abc") = 900150983cd24fb0d6963f7d28e17f72
1390MD5 ("message digest") = f96b697d7cb7938d525a2f31aaf161d0
1391MD5 ("abcdefghijklmnopqrstuvwxyz") = c3fcd3d76192e4007dfb496cca67e13b
1392MD5 ("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789") = d174ab98d277d9f5a5611c2c9f419d9f
1393MD5 ("12345678901234567890123456789012345678901234567890123456789012345678901234567890") = 57edf4a22be3c955ac49da2e2107b67a
1394
1395*/
1396
1397/* HMAC-MD5 test suite
1398
1399Test Vectors (Trailing '\0' of a character string not included in test):
1400
1401  key =         0x0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b
1402  key_len =     16 bytes
1403  data =        "Hi There"
1404  data_len =    8  bytes
1405  digest =      0x9294727a3638bb1c13f48ef8158bfc9d
1406
1407  key =         "Jefe"
1408  data =        "what do ya want for nothing?"
1409  data_len =    28 bytes
1410  digest =      0x750c783e6ab0b503eaa86e310a5db738
1411
1412  key =         0xAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
1413  key_len       16 bytes
1414  data =        0xDDDDDDDDDDDDDDDDDDDD...
1415                ..DDDDDDDDDDDDDDDDDDDD...
1416                ..DDDDDDDDDDDDDDDDDDDD...
1417                ..DDDDDDDDDDDDDDDDDDDD...
1418                ..DDDDDDDDDDDDDDDDDDDD
1419  data_len =    50 bytes
1420  digest =      0x56be34521d144c88dbb8c733f0e8b3f6
1421
1422*/
1423
1424
1425