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