1 /* *********************************************************************
2 * Broadcom Common Firmware Environment (CFE)
4 * BC5821 crypto accelerator driver File: dev_bcm5821.c
6 *********************************************************************
8 * Copyright 2000,2001,2002,2003
9 * Broadcom Corporation. All rights reserved.
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.
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.
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.
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 ********************************************************************* */
44 CFE Driver plus test programs for the BCM5820 and BCM5821 crypto
47 BCM5821 Super-eCommerce Processor
48 Data Sheet 5821-DS105-D1 (draft, 7/26/02)
49 Broadcom Corp., 16215 Alton Parkway, Irvine, CA.
52 /* The performance counter usage assumes a BCM11xx or BCM1250 part */
56 #if !defined(_SB14XX_) && !defined(_RM5200_) && !defined(_RM7000_)
57 #define _SB1250_PERF_ 1
59 #define _SB1250_PERF_ 0
63 #include "sb1250_defs.h"
64 #include "sb1250_regs.h"
68 #define _SB_MAKE64(x) ((uint64_t)(x))
71 #define _SB_MAKEMASK1(n) (_SB_MAKE64(1) << _SB_MAKE64(n))
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"
81 #include "addrspace.h"
84 #include "cfe_device.h"
85 #include "cfe_timer.h"
86 #include "cfe_devfuncs.h"
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. */
100 extern int32_t _getcause(void); /* return value of CP0 CAUSE */
102 #define IMR_POINTER(cpu,reg) \
103 ((volatile uint64_t *)(PHYS_TO_K1(A_IMR_REGISTER(cpu,reg))))
105 #define CACHE_LINE_SIZE 32
107 static void bcm5821_probe(cfe_driver_t
*drv
,
108 unsigned long probe_a
, unsigned long probe_b
,
111 typedef struct bcm5821_state_s
{
114 pcitag_t tag
; /* tag for configuration registers */
116 uint16_t device
; /* chip device code */
117 uint8_t revision
; /* chip revision */
122 /* Address mapping macros */
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))
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)
137 #define READCSR(sc,csr) (phys_read32((sc)->regbase + (csr)))
138 #define WRITECSR(sc,csr,val) (phys_write32((sc)->regbase + (csr), (val)))
142 dumpcsrs(bcm5821_state_t
*sc
, const char *legend
)
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");
156 bcm5821_init(bcm5821_state_t
*sc
)
161 bcm5821_hwinit(bcm5821_state_t
*sc
)
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
);
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
);
177 dumpcsrs(sc
, "init");
182 bcm5821_start(bcm5821_state_t
*sc
)
188 bcm5821_stop(bcm5821_state_t
*sc
)
190 WRITECSR(sc
, R_DMA_CTRL
, 0);
194 static int bcm5821_open(cfe_devctx_t
*ctx
);
195 static int bcm5821_read(cfe_devctx_t
*ctx
,iocb_buffer_t
*buffer
);
196 static int bcm5821_inpstat(cfe_devctx_t
*ctx
,iocb_inpstat_t
*inpstat
);
197 static int bcm5821_write(cfe_devctx_t
*ctx
,iocb_buffer_t
*buffer
);
198 static int bcm5821_ioctl(cfe_devctx_t
*ctx
,iocb_buffer_t
*buffer
);
199 static int bcm5821_close(cfe_devctx_t
*ctx
);
201 const static cfe_devdisp_t bcm5821_dispatch
= {
212 cfe_driver_t bcm5821drv
= {
222 bcm5821_attach(cfe_driver_t
*drv
, pcitag_t tag
, int index
)
228 pcireg_t device
, class;
230 pci_map_mem(tag
, PCI_MAPREG(0), PCI_MATCH_BITS
, &pa
);
233 sc
= (bcm5821_state_t
*) KMALLOC(sizeof(bcm5821_state_t
),0);
235 xprintf("BCM5821: No memory to complete probe\n");
239 memset(sc
, 0, sizeof(*sc
));
243 sc
->irq
= pci_conf_read(tag
, PCI_BPARAM_INTERRUPT_REG
) & 0xFF;
245 device
= pci_conf_read(tag
, PCI_ID_REG
);
246 class = pci_conf_read(tag
, PCI_CLASS_REG
);
249 sc
->device
= PCI_PRODUCT(device
);
250 sc
->revision
= PCI_REVISION(class);
254 xsprintf(descr
, "BCM%04X Crypto at 0x%08X", sc
->device
, base
);
255 cfe_attach(drv
, sc
, NULL
, descr
);
261 bcm5821_probe(cfe_driver_t
*drv
,
262 unsigned long probe_a
, unsigned long probe_b
,
274 if (pci_find_class(PCI_CLASS_PROCESSOR
, index
, &tag
) != 0)
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
);
291 /* The functions below are called via the dispatch vector for the 5821 */
294 bcm5821_open(cfe_devctx_t
*ctx
)
296 bcm5821_state_t
*sc
= ctx
->dev_softc
;
303 bcm5821_read(cfe_devctx_t
*ctx
, iocb_buffer_t
*buffer
)
309 bcm5821_inpstat(cfe_devctx_t
*ctx
, iocb_inpstat_t
*inpstat
)
315 bcm5821_write(cfe_devctx_t
*ctx
, iocb_buffer_t
*buffer
)
321 bcm5821_ioctl(cfe_devctx_t
*ctx
, iocb_buffer_t
*buffer
)
327 bcm5821_close(cfe_devctx_t
*ctx
)
329 bcm5821_state_t
*sc
= ctx
->dev_softc
;
336 /* Additional hooks for testing. */
339 bcm5821_dump_cc1 (uint32_t *cc
)
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 */
346 chain_out
= 1; /* default */
351 xprintf("(SSL_MAC)\n");
352 for (i
= 0; i
< SSL_MAC_CMD_WORDS
; i
++)
353 xprintf(" %2d: %08x\n", i
, cc
[i
]);
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]);
368 for (i
= 0; i
< 2; i
++)
369 xprintf(" %2d: %08x\n", i
, cc
[i
]);
377 default: /* NYI: K_IPSEC_3DES (5821 only), K_SSL_3DES */
379 for (i
= 0; i
< cc_words
; i
++)
380 xprintf(" %2d: %08x\n", i
, cc
[i
]);
388 bcm5821_dump_cc2 (uint32_t *cc
)
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 */
395 chain_out
= 1; /* default */
400 xprintf(" RNG_DIRECT\n");
402 for (i
= 0; i
< 1; i
++)
403 xprintf(" %2d: %08x\n", i
, cc
[i
]);
407 xprintf(" RNG_SHA1\n");
409 for (i
= 0; i
< 1; i
++)
410 xprintf(" %2d: %08x\n", i
, cc
[i
]);
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
]);
423 bcm5821_dump_pkt (uint32_t *pkt
, int port
)
425 uint32_t *cc
= PHYS_TO_PTR(PCI_TO_PHYS(pkt
[0]));
430 xprintf(" %2d: %08x ", 0, pkt
[0]);
431 chain_out
= (port
== 1 ? bcm5821_dump_cc1
: bcm5821_dump_cc2
)(cc
);
433 for (i
= 1; i
< PD_SIZE
/4; i
++) {
434 xprintf(" %2d: %08x\n", i
, pkt
[i
]);
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
]);
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
]);
458 bcm5821_dump_mcr (uint32_t mcr
[], int port
)
461 unsigned npkts
= G_MCR_NUM_PACKETS(mcr
[0]);
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
);
472 bcm5821_show_pkt1 (uint32_t *pkt
)
474 uint32_t *cc
= PHYS_TO_PTR(PCI_TO_PHYS(pkt
[0]));
475 unsigned op
= G_CC_OPCODE(cc
[0]);
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]);
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]);
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]));
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]);
516 uint8_t *digest
= PHYS_TO_PTR(PCI_TO_PHYS(pkt
[6]));
518 xprintf("HASH digest ");
519 for (i
= 0; i
< 16; i
++)
520 xprintf("%02x", digest
[i
]);
530 bcm5821_show_pkt2 (uint32_t *pkt
)
532 uint32_t *cc
= PHYS_TO_PTR(PCI_TO_PHYS(pkt
[0]));
533 unsigned op
= G_CC_OPCODE(cc
[0]);
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);
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]);
555 bcm5821_show_mcr (uint32_t mcr
[], int port
)
558 unsigned npkts
= G_MCR_NUM_PACKETS(mcr
[0]);
560 xprintf("MCR at %p:\n", mcr
);
561 for (i
= 0; i
< npkts
; i
++) {
562 xprintf("packet %d:\n", i
+1);
564 bcm5821_show_pkt1(&mcr
[1 + i
*(PD_SIZE
/4)]);
566 bcm5821_show_pkt2(&mcr
[1 + i
*(PD_SIZE
/4)]);
572 bcm5821_alloc_hash (const uint8_t *msg
, size_t msg_len
, int swap
)
575 uint32_t *cmd
; /* always reads at least 64 bytes */
580 message
= KMALLOC(msg_len
, CACHE_LINE_SIZE
);
581 for (i
= 0; i
< msg_len
; i
++)
584 digest
= KMALLOC(16, CACHE_LINE_SIZE
);
585 for (i
= 0; i
< 16; i
++)
588 mcr
= KMALLOC(MCR_WORDS(1)*4, CACHE_LINE_SIZE
);
589 mcr
[0] = V_MCR_NUM_PACKETS(1);
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
);
595 mcr
[1] = PHYS_TO_PCI(PTR_TO_PHYS(cmd
));
598 mcr
[2] = swap
? PHYS_TO_PCI_D(PTR_TO_PHYS(message
))
599 : PHYS_TO_PCI(PTR_TO_PHYS(message
));
601 mcr
[4] = V_DBC_DATA_LEN(msg_len
);
603 mcr
[5] = V_PD_PKT_LEN(msg_len
);
606 mcr
[7] = swap
? PHYS_TO_PCI_D(PTR_TO_PHYS(digest
))
607 : PHYS_TO_PCI(PTR_TO_PHYS(digest
));
614 bcm5821_free_hash (uint32_t mcr
[])
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])));
625 bcm5821_alloc_hmac (const char *key
, int key_len
,
626 const char *msg
, int msg_len
,
635 message
= KMALLOC(msg_len
, CACHE_LINE_SIZE
);
636 memcpy((uint8_t *)message
, msg
, msg_len
);
638 mcr
= KMALLOC(MCR_WORDS(1)*4, CACHE_LINE_SIZE
);
639 mcr
[0] = V_MCR_NUM_PACKETS(1);
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
);
647 for (i
= 2; i
< 7; i
++)
649 cmd
[6] = 0x00000000; /* must be zero for SSL */
650 for (i
= 8; i
< 13; i
++)
652 cmd
[13] = 0; /* seq num */
654 cmd
[15] = 0x03000000 | (msg_len
<< 8);
656 mcr
[1] = PHYS_TO_PCI(PTR_TO_PHYS(cmd
));
659 mcr
[2] = swap
? PHYS_TO_PCI_D(PTR_TO_PHYS(message
))
660 : PHYS_TO_PCI(PTR_TO_PHYS(message
));
662 mcr
[4] = V_DBC_DATA_LEN(msg_len
);
664 mcr
[5] = V_PD_PKT_LEN(msg_len
);
666 hash
= KMALLOC(5*4, CACHE_LINE_SIZE
);
667 for (i
= 0; i
< 5; i
++)
671 mcr
[7] = swap
? PHYS_TO_PCI_D(PTR_TO_PHYS(hash
))
672 : PHYS_TO_PCI(PTR_TO_PHYS(hash
));
679 bcm5821_free_hmac (uint32_t mcr
[])
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])));
689 static int test_init
= 0;
694 /* For Pass 1, dedicate an SCD peformance counter to use as a counter
696 #include "sb1250_scd.h"
697 #define ZCTR_MODULUS 0x10000000000LL
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. */
708 zclk_init(uint64_t val
)
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
;
720 ticks
= *((volatile uint64_t *) UNCADDR(A_SCD_PERF_CNT_0
));
721 if (ticks
== 0 || ticks
== ZCTR_MODULUS
-1) {
725 else if (ticks
>= ZCTR_MODULUS
/2) {
726 ticks
-= ZCTR_MODULUS
/2;
727 zclk_init(ticks
); /* Ignore the fudge and lose a few ticks */
733 zclk_elapsed(uint64_t stop
, uint64_t start
)
735 return ((stop
>= start
) ? stop
: stop
+ ZCTR_MODULUS
/2) - start
;
738 #else /* !_SB1250_PERF_ */
740 zclk_init(uint64_t val
)
751 zclk_elapsed(uint64_t stop
, uint64_t start
)
755 #endif /* _SB1250_PERF_ */
758 /* Auxiliary functions */
761 bcm5821_alloc_composite(int input_size
)
763 uint32_t *input
, *output
;
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;
779 mcr
= KMALLOC(MCR_WORDS(2)*4, CACHE_LINE_SIZE
);
780 mcr
[0] = V_MCR_NUM_PACKETS(2);
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
++)
789 cmd
[6] = 0x00000000; /* must be zero for SSL */
790 for (i
= 7; i
< 19; i
++)
792 cmd
[19] = 0; /* seq num */
794 cmd
[21] = 0x03000000 | (input_size
<< 8); /* type/len/rsvd */
796 mcr
[1] = PHYS_TO_PCI(PTR_TO_PHYS(cmd
));
799 mcr
[2] = PHYS_TO_PCI(PTR_TO_PHYS(input
));
801 mcr
[4] = V_DBC_DATA_LEN(input_size
);
803 mcr
[5] = V_PD_PKT_LEN(input_size
);
805 hash
= KMALLOC(5*4, CACHE_LINE_SIZE
);
806 for (i
= 0; i
< 5; i
++)
810 mcr
[7] = PHYS_TO_PCI(PTR_TO_PHYS(hash
));
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
;
819 arc4_state
= (uint8_t *)&cmd
[3];
820 for (i
= 0; i
< 256; i
++)
823 mcr
[8+1] = PHYS_TO_PCI(PTR_TO_PHYS(cmd
));
826 chain
= KMALLOC(CHAIN_WORDS
*4, CACHE_LINE_SIZE
);
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
);
833 chain
[0] = PHYS_TO_PCI(PTR_TO_PHYS(hash
));
835 chain
[2] = V_DBC_DATA_LEN(16);
837 mcr
[8+5] = V_PD_PKT_LEN(input_size
+ 16);
839 /* output fragment */
840 chain
= KMALLOC(CHAIN_WORDS
*4, CACHE_LINE_SIZE
);
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);
846 update
= KMALLOC(ARC4_STATE_WORDS
*4, CACHE_LINE_SIZE
);
847 for (i
= 0; i
< ARC4_STATE_WORDS
; i
++)
848 update
[i
] = 0xFFFFFFFF;
851 chain
[0] = PHYS_TO_PCI(PTR_TO_PHYS(update
));
853 chain
[2] = V_DBC_DATA_LEN(ARC4_STATE_WORDS
*4); /* not actually used */
859 bcm5821_free_composite (uint32_t mcr
[])
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])));
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
);
885 /* Temporary hack: churn through all of L2 */
886 volatile uint64_t *lomem
;
890 lomem
= (uint64_t *)(0xFFFFFFFF80000000LL
); /* kseg0 @ 0 */
892 for (i
= 0; i
< (512/8)*1024; i
++)
898 bcm5821_interrupt(void *ctx
)
905 #define MCR_QUEUE_DEPTH 2
908 bcm5821_composite (bcm5821_state_t
*sc
, size_t len
, int trials
)
910 uint32_t *mcr
[POOL_SIZE
];
912 uint64_t start
, stop
, ticks
;
917 for (i
= 0; i
< POOL_SIZE
; i
++)
918 mcr
[i
] = bcm5821_alloc_composite(len
);
920 (void)bcm5821_dump_mcr
; /*bcm5821_dump_mcr(mcr[0], 1);*/
925 /* Force all descriptors and buffers out of L1 */
926 cfe_flushcache(CFE_CACHE_FLUSH_D
);
929 status
= READCSR(sc
, R_DMA_STAT
);
930 WRITECSR(sc
, R_DMA_STAT
, status
); /* clear pending bits */
931 status
= READCSR(sc
, R_DMA_STAT
);
933 for (i
= 0; i
< 1000; i
++) {
934 status
= READCSR(sc
, R_DMA_STAT
);
935 if ((status
& M_DMA_STAT_MCR1_FULL
) == 0)
940 dumpcsrs(sc
, "bcm5821: full bit never clears");
945 /* Enable interrupt polling, but the handler is never called. */
946 cfe_request_irq(sc
->irq
, bcm5821_interrupt
, NULL
, 0, 0);
949 zclk_init(0); /* Time origin is arbitrary. */
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)
956 WRITECSR(sc
, R_MCR1
, PHYS_TO_PCI(PTR_TO_PHYS(mcr
[next
])));
957 next
= (next
+ 1) % POOL_SIZE
;
962 while ((_getcause() & M_CAUSE_IP2
) == 0)
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
);
974 WRITECSR(sc
, R_DMA_STAT
,
975 M_DMA_STAT_DMAERR_INTR
| M_DMA_STAT_MCR1_INTR
);
977 volatile uint32_t *last_mcr
= mcr
[last
];
979 while ((*last_mcr
& M_MCR_DONE
) == 0)
989 while ((READCSR(sc
, R_DMA_STAT
) & M_DMA_STAT_MCR1_FULL
) != 0)
991 WRITECSR(sc
, R_MCR1
, PHYS_TO_PCI(PTR_TO_PHYS(mcr
[next
])));
992 next
= (next
+ 1) % POOL_SIZE
;
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
;
1001 status
= READCSR(sc
, R_DMA_STAT
);
1002 WRITECSR(sc
, R_DMA_STAT
, status
); /* clear pending bits */
1003 cfe_free_irq(sc
->irq
, 0);
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);
1016 bcm5821_show_mcr(mcr
[0], 1);
1019 for (i
= 0; i
< POOL_SIZE
; i
++)
1020 bcm5821_free_composite(mcr
[i
]);
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
1031 bcm5821_state_t
*sc
;
1033 int index
[MCR_QUEUE_DEPTH
];
1040 bcm5821_composite2 (bcm5821_state_t
*sc0
, bcm5821_state_t
*sc1
,
1041 size_t len
, int trials
)
1043 uint32_t *mcr
[POOL_SIZE
];
1044 uint32_t ring
[POOL_SIZE
];
1046 uint64_t start
, stop
, ticks
;
1052 struct dev_info dev
[N_DEVICES
];
1054 bcm5821_state_t
*sc
;
1056 volatile uint64_t *irqstat
= IMR_POINTER(0, R_IMR_INTERRUPT_SOURCE_STATUS
);
1060 dev
[0].sc
= sc0
; dev
[1].sc
= sc1
;
1062 for (i
= 0; i
< POOL_SIZE
; i
++)
1063 mcr
[i
] = bcm5821_alloc_composite(len
);
1064 for (i
= 0; i
< POOL_SIZE
; i
++)
1068 (void)bcm5821_dump_mcr
; /*bcm5821_dump_mcr(mcr[0], 1);*/
1072 /* Force all descriptors and buffers out of L1 */
1073 cfe_flushcache(CFE_CACHE_FLUSH_D
);
1077 for (d
= 0; d
< N_DEVICES
; d
++) {
1079 dev
[d
].irq_mask
= 1LL << (sc
->irq
);
1080 masks
|= dev
[d
].irq_mask
;
1082 status
= READCSR(sc
, R_DMA_STAT
);
1083 WRITECSR(sc
, R_DMA_STAT
, status
); /* clear pending bits */
1084 status
= READCSR(sc
, R_DMA_STAT
);
1086 for (i
= 0; i
< 1000; i
++) {
1087 status
= READCSR(sc
, R_DMA_STAT
);
1088 if ((status
& M_DMA_STAT_MCR1_FULL
) == 0)
1094 dumpcsrs(sc
, "bcm5821: full bit never clears");
1099 /* Enable interrupt polling, but the handler is never called. */
1100 cfe_request_irq(sc
->irq
, bcm5821_interrupt
, NULL
, 0, 0);
1104 stop
= 0; /* Keep compiler happy */
1105 zclk_init(0); /* Time origin is arbitrary. */
1108 for (d
= 0; d
< N_DEVICES
; d
++) {
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)
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
;
1123 while (trials
== 0 || run
!= trials
) {
1125 while ((_getcause() & M_CAUSE_IP2
) == 0)
1131 while (pending
== 0) {
1132 for (d
= 0; d
< N_DEVICES
; d
++) {
1133 volatile uint32_t *last_mcr
= mcr
[dev
[d
].index
[0]];
1135 if ((*last_mcr
& M_MCR_DONE
) != 0)
1136 pending
|= dev
[d
].irq_mask
;
1143 for (d
= 0; d
< N_DEVICES
; d
++) {
1144 if ((dev
[d
].irq_mask
& pending
) != 0) {
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
);
1155 WRITECSR(sc
, R_DMA_STAT
,
1156 M_DMA_STAT_DMAERR_INTR
| M_DMA_STAT_MCR1_INTR
);
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
;
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)
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
;
1182 for (d
= 0; d
< N_DEVICES
; d
++) {
1184 status
= READCSR(sc
, R_DMA_STAT
);
1185 WRITECSR(sc
, R_DMA_STAT
, status
); /* clear pending bits */
1187 cfe_free_irq(sc
->irq
, 0);
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);
1199 for (i
= 0; i
< POOL_SIZE
; i
++)
1200 bcm5821_free_composite(mcr
[i
]);
1206 extern cfe_devctx_t
*cfe_handle_table
[];
1208 int bcm5821_test (int device
, int trials
);
1210 bcm5821_test (int device
, int trials
)
1212 cfe_devctx_t
*ctx
= cfe_handle_table
[device
];
1213 bcm5821_state_t
*sc
= ctx
->dev_softc
;
1216 zclk_init(0); /* Time origin is arbitrary */
1220 bcm5821_composite(sc
, 1472, trials
);
1225 int bcm5821_test2 (int device0
, int device2
, int trials
);
1227 bcm5821_test2 (int device0
, int device1
, int trials
)
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
;
1235 zclk_init(0); /* Time origin is arbitrary */
1239 bcm5821_composite2(sc0
, sc1
, 1472, trials
);
1246 bcm5821_hash_md5 (bcm5821_state_t
*sc
, const char *msg
)
1248 size_t len
= strlen(msg
);
1252 int swap
= (sc
->device
== K_PCI_ID_BCM5820
);
1254 mcr
= bcm5821_alloc_hash(msg
, len
, swap
);
1256 /* bcm5821_dump_mcr(mcr, 1); */
1258 status
= READCSR(sc
, R_DMA_STAT
);
1259 WRITECSR(sc
, R_DMA_STAT
, status
); /* clear pending bits */
1260 status
= READCSR(sc
, R_DMA_STAT
);
1262 for (i
= 0; i
< 1000; i
++) {
1263 status
= READCSR(sc
, R_DMA_STAT
);
1264 if ((status
& M_DMA_STAT_MCR1_FULL
) == 0)
1269 dumpcsrs(sc
, "bcm5821: full bit never clears");
1273 WRITECSR(sc
, R_MCR1
, PHYS_TO_PCI(PTR_TO_PHYS(mcr
)));
1275 for (i
= 0; i
< 1000; i
++) {
1277 status
= READCSR(sc
, R_DMA_STAT
);
1278 if ((status
& M_DMA_STAT_MCR1_INTR
) != 0)
1281 if ((mcr
[0] & M_MCR_DONE
) != 0)
1287 dumpcsrs(sc
, "bcm5821: done bit never sets");
1291 status
= READCSR(sc
, R_DMA_STAT
);
1292 WRITECSR(sc
, R_DMA_STAT
, status
); /* clear pending bits */
1294 /* bcm5821_dump_mcr(mcr, 1); */
1296 bcm5821_show_mcr(mcr
, 1);
1298 bcm5821_free_hash(mcr
);
1305 bcm5821_hmac_md5 (bcm5821_state_t
*sc
,
1306 const uint8_t key
[], size_t key_len
,
1307 const uint8_t data
[], size_t data_len
)
1312 int swap
= (sc
->device
== K_PCI_ID_BCM5820
);
1314 mcr
= bcm5821_alloc_hmac(key
, key_len
, data
, data_len
, swap
);
1316 status
= READCSR(sc
, R_DMA_STAT
);
1317 WRITECSR(sc
, R_DMA_STAT
, status
); /* clear pending bits */
1318 status
= READCSR(sc
, R_DMA_STAT
);
1320 for (i
= 0; i
< 1000; i
++) {
1321 status
= READCSR(sc
, R_DMA_STAT
);
1322 if ((status
& M_DMA_STAT_MCR1_FULL
) == 0)
1327 dumpcsrs(sc
, "bcm5821: full bit never clears");
1331 bcm5821_free_hmac(mcr
);
1335 /* Sanity check on the implementation using RFC test suites. */
1337 int bcm5821_check (int device
);
1339 bcm5821_check (int device
)
1341 static unsigned char k1
[16] = {
1342 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b,
1343 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b
1345 static unsigned char m1
[] = "Hi There";
1347 static unsigned char k2
[] = "Jefe";
1348 static unsigned char m2
[] = "what do ya want for nothing?";
1350 static unsigned char k3
[16] = {
1351 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA,
1352 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA
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
1362 cfe_devctx_t
*ctx
= cfe_handle_table
[device
];
1363 bcm5821_state_t
*sc
= ctx
->dev_softc
;
1366 zclk_init(0); /* Time origin is arbitrary */
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");
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
));
1384 /* Output of md5 test suite (md5 -x)
1387 MD5 ("") = d41d8cd98f00b204e9800998ecf8427e
1388 MD5 ("a") = 0cc175b9c0f1b6a831c399e269772661
1389 MD5 ("abc") = 900150983cd24fb0d6963f7d28e17f72
1390 MD5 ("message digest") = f96b697d7cb7938d525a2f31aaf161d0
1391 MD5 ("abcdefghijklmnopqrstuvwxyz") = c3fcd3d76192e4007dfb496cca67e13b
1392 MD5 ("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789") = d174ab98d277d9f5a5611c2c9f419d9f
1393 MD5 ("12345678901234567890123456789012345678901234567890123456789012345678901234567890") = 57edf4a22be3c955ac49da2e2107b67a
1397 /* HMAC-MD5 test suite
1399 Test Vectors (Trailing '\0' of a character string not included in test):
1401 key = 0x0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b
1405 digest = 0x9294727a3638bb1c13f48ef8158bfc9d
1408 data = "what do ya want for nothing?"
1410 digest = 0x750c783e6ab0b503eaa86e310a5db738
1412 key = 0xAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
1414 data = 0xDDDDDDDDDDDDDDDDDDDD...
1415 ..DDDDDDDDDDDDDDDDDDDD...
1416 ..DDDDDDDDDDDDDDDDDDDD...
1417 ..DDDDDDDDDDDDDDDDDDDD...
1418 ..DDDDDDDDDDDDDDDDDDDD
1420 digest = 0x56be34521d144c88dbb8c733f0e8b3f6