1 /* $NetBSD: hifn7751.c,v 1.50 2012/02/02 19:43:04 tls Exp $ */ 2 /* $FreeBSD: hifn7751.c,v 1.5.2.7 2003/10/08 23:52:00 sam Exp $ */ 3 /* $OpenBSD: hifn7751.c,v 1.140 2003/08/01 17:55:54 deraadt Exp $ */ 4 5 /* 6 * Invertex AEON / Hifn 7751 driver 7 * Copyright (c) 1999 Invertex Inc. All rights reserved. 8 * Copyright (c) 1999 Theo de Raadt 9 * Copyright (c) 2000-2001 Network Security Technologies, Inc. 10 * http://www.netsec.net 11 * Copyright (c) 2003 Hifn Inc. 12 * 13 * This driver is based on a previous driver by Invertex, for which they 14 * requested: Please send any comments, feedback, bug-fixes, or feature 15 * requests to software@invertex.com. 16 * 17 * Redistribution and use in source and binary forms, with or without 18 * modification, are permitted provided that the following conditions 19 * are met: 20 * 21 * 1. Redistributions of source code must retain the above copyright 22 * notice, this list of conditions and the following disclaimer. 23 * 2. Redistributions in binary form must reproduce the above copyright 24 * notice, this list of conditions and the following disclaimer in the 25 * documentation and/or other materials provided with the distribution. 26 * 3. The name of the author may not be used to endorse or promote products 27 * derived from this software without specific prior written permission. 28 * 29 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 30 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 31 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 32 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 33 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 34 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 35 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 36 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 37 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 38 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 39 * 40 * Effort sponsored in part by the Defense Advanced Research Projects 41 * Agency (DARPA) and Air Force Research Laboratory, Air Force 42 * Materiel Command, USAF, under agreement number F30602-01-2-0537. 43 * 44 */ 45 46 /* 47 * Driver for various Hifn pre-HIPP encryption processors. 48 */ 49 50 #include <sys/cdefs.h> 51 __KERNEL_RCSID(0, "$NetBSD: hifn7751.c,v 1.50 2012/02/02 19:43:04 tls Exp $"); 52 53 #include <sys/param.h> 54 #include <sys/systm.h> 55 #include <sys/proc.h> 56 #include <sys/errno.h> 57 #include <sys/malloc.h> 58 #include <sys/kernel.h> 59 #include <sys/mbuf.h> 60 #include <sys/device.h> 61 62 #ifdef __OpenBSD__ 63 #include <crypto/crypto.h> 64 #include <dev/rndvar.h> 65 #else 66 #include <opencrypto/cryptodev.h> 67 #include <sys/cprng.h> 68 #include <sys/rnd.h> 69 #include <sys/sha1.h> 70 #endif 71 72 #include <dev/pci/pcireg.h> 73 #include <dev/pci/pcivar.h> 74 #include <dev/pci/pcidevs.h> 75 76 #include <dev/pci/hifn7751reg.h> 77 #include <dev/pci/hifn7751var.h> 78 79 #undef HIFN_DEBUG 80 81 #ifdef __NetBSD__ 82 #define M_DUP_PKTHDR M_COPY_PKTHDR /* XXX */ 83 #endif 84 85 #ifdef HIFN_DEBUG 86 extern int hifn_debug; /* patchable */ 87 int hifn_debug = 1; 88 #endif 89 90 #ifdef __OpenBSD__ 91 #define HAVE_CRYPTO_LZS /* OpenBSD OCF supports CRYPTO_COMP_LZS */ 92 #endif 93 94 /* 95 * Prototypes and count for the pci_device structure 96 */ 97 #ifdef __OpenBSD__ 98 static int hifn_probe((struct device *, void *, void *); 99 #else 100 static int hifn_probe(device_t, cfdata_t, void *); 101 #endif 102 static void hifn_attach(device_t, device_t, void *); 103 104 CFATTACH_DECL(hifn, sizeof(struct hifn_softc), 105 hifn_probe, hifn_attach, NULL, NULL); 106 107 #ifdef __OpenBSD__ 108 struct cfdriver hifn_cd = { 109 0, "hifn", DV_DULL 110 }; 111 #endif 112 113 static void hifn_reset_board(struct hifn_softc *, int); 114 static void hifn_reset_puc(struct hifn_softc *); 115 static void hifn_puc_wait(struct hifn_softc *); 116 static const char *hifn_enable_crypto(struct hifn_softc *, pcireg_t); 117 static void hifn_set_retry(struct hifn_softc *); 118 static void hifn_init_dma(struct hifn_softc *); 119 static void hifn_init_pci_registers(struct hifn_softc *); 120 static int hifn_sramsize(struct hifn_softc *); 121 static int hifn_dramsize(struct hifn_softc *); 122 static int hifn_ramtype(struct hifn_softc *); 123 static void hifn_sessions(struct hifn_softc *); 124 static int hifn_intr(void *); 125 static u_int hifn_write_command(struct hifn_command *, u_int8_t *); 126 static u_int32_t hifn_next_signature(u_int32_t a, u_int cnt); 127 static int hifn_newsession(void*, u_int32_t *, struct cryptoini *); 128 static int hifn_freesession(void*, u_int64_t); 129 static int hifn_process(void*, struct cryptop *, int); 130 static void hifn_callback(struct hifn_softc *, struct hifn_command *, 131 u_int8_t *); 132 static int hifn_crypto(struct hifn_softc *, struct hifn_command *, 133 struct cryptop*, int); 134 static int hifn_readramaddr(struct hifn_softc *, int, u_int8_t *); 135 static int hifn_writeramaddr(struct hifn_softc *, int, u_int8_t *); 136 static int hifn_dmamap_aligned(bus_dmamap_t); 137 static int hifn_dmamap_load_src(struct hifn_softc *, 138 struct hifn_command *); 139 static int hifn_dmamap_load_dst(struct hifn_softc *, 140 struct hifn_command *); 141 static int hifn_init_pubrng(struct hifn_softc *); 142 static void hifn_rng(void *); 143 static void hifn_tick(void *); 144 static void hifn_abort(struct hifn_softc *); 145 static void hifn_alloc_slot(struct hifn_softc *, int *, int *, int *, 146 int *); 147 static void hifn_write_4(struct hifn_softc *, int, bus_size_t, u_int32_t); 148 static u_int32_t hifn_read_4(struct hifn_softc *, int, bus_size_t); 149 #ifdef HAVE_CRYPTO_LZS 150 static int hifn_compression(struct hifn_softc *, struct cryptop *, 151 struct hifn_command *); 152 static struct mbuf *hifn_mkmbuf_chain(int, struct mbuf *); 153 static int hifn_compress_enter(struct hifn_softc *, struct hifn_command *); 154 static void hifn_callback_comp(struct hifn_softc *, struct hifn_command *, 155 u_int8_t *); 156 #endif /* HAVE_CRYPTO_LZS */ 157 158 159 struct hifn_stats hifnstats; 160 161 static const struct hifn_product { 162 pci_vendor_id_t hifn_vendor; 163 pci_product_id_t hifn_product; 164 int hifn_flags; 165 const char *hifn_name; 166 } hifn_products[] = { 167 { PCI_VENDOR_INVERTEX, PCI_PRODUCT_INVERTEX_AEON, 168 0, 169 "Invertex AEON", 170 }, 171 172 { PCI_VENDOR_HIFN, PCI_PRODUCT_HIFN_7751, 173 0, 174 "Hifn 7751", 175 }, 176 { PCI_VENDOR_NETSEC, PCI_PRODUCT_NETSEC_7751, 177 0, 178 "Hifn 7751 (NetSec)" 179 }, 180 181 { PCI_VENDOR_HIFN, PCI_PRODUCT_HIFN_7811, 182 HIFN_IS_7811 | HIFN_HAS_RNG | HIFN_HAS_LEDS | HIFN_NO_BURSTWRITE, 183 "Hifn 7811", 184 }, 185 186 { PCI_VENDOR_HIFN, PCI_PRODUCT_HIFN_7951, 187 HIFN_HAS_RNG | HIFN_HAS_PUBLIC, 188 "Hifn 7951", 189 }, 190 191 { PCI_VENDOR_HIFN, PCI_PRODUCT_HIFN_7955, 192 HIFN_HAS_RNG | HIFN_HAS_PUBLIC | HIFN_IS_7956 | HIFN_HAS_AES, 193 "Hifn 7955", 194 }, 195 196 { PCI_VENDOR_HIFN, PCI_PRODUCT_HIFN_7956, 197 HIFN_HAS_RNG | HIFN_HAS_PUBLIC | HIFN_IS_7956 | HIFN_HAS_AES, 198 "Hifn 7956", 199 }, 200 201 202 { 0, 0, 203 0, 204 NULL 205 } 206 }; 207 208 static const struct hifn_product * 209 hifn_lookup(const struct pci_attach_args *pa) 210 { 211 const struct hifn_product *hp; 212 213 for (hp = hifn_products; hp->hifn_name != NULL; hp++) { 214 if (PCI_VENDOR(pa->pa_id) == hp->hifn_vendor && 215 PCI_PRODUCT(pa->pa_id) == hp->hifn_product) 216 return (hp); 217 } 218 return (NULL); 219 } 220 221 static int 222 hifn_probe(device_t parent, cfdata_t match, void *aux) 223 { 224 struct pci_attach_args *pa = aux; 225 226 if (hifn_lookup(pa) != NULL) 227 return 1; 228 229 return 0; 230 } 231 232 static void 233 hifn_attach(device_t parent, device_t self, void *aux) 234 { 235 struct hifn_softc *sc = device_private(self); 236 struct pci_attach_args *pa = aux; 237 const struct hifn_product *hp; 238 pci_chipset_tag_t pc = pa->pa_pc; 239 pci_intr_handle_t ih; 240 const char *intrstr = NULL; 241 const char *hifncap; 242 char rbase; 243 bus_size_t iosize0, iosize1; 244 u_int32_t cmd; 245 u_int16_t ena; 246 bus_dma_segment_t seg; 247 bus_dmamap_t dmamap; 248 int rseg; 249 void *kva; 250 251 hp = hifn_lookup(pa); 252 if (hp == NULL) { 253 printf("\n"); 254 panic("hifn_attach: impossible"); 255 } 256 257 pci_aprint_devinfo_fancy(pa, "Crypto processor", hp->hifn_name, 1); 258 259 sc->sc_pci_pc = pa->pa_pc; 260 sc->sc_pci_tag = pa->pa_tag; 261 262 sc->sc_flags = hp->hifn_flags; 263 264 cmd = pci_conf_read(pc, pa->pa_tag, PCI_COMMAND_STATUS_REG); 265 cmd |= PCI_COMMAND_MASTER_ENABLE; 266 pci_conf_write(pc, pa->pa_tag, PCI_COMMAND_STATUS_REG, cmd); 267 268 if (pci_mapreg_map(pa, HIFN_BAR0, PCI_MAPREG_TYPE_MEM, 0, 269 &sc->sc_st0, &sc->sc_sh0, NULL, &iosize0)) { 270 aprint_error_dev(&sc->sc_dv, "can't map mem space %d\n", 0); 271 return; 272 } 273 274 if (pci_mapreg_map(pa, HIFN_BAR1, PCI_MAPREG_TYPE_MEM, 0, 275 &sc->sc_st1, &sc->sc_sh1, NULL, &iosize1)) { 276 aprint_error_dev(&sc->sc_dv, "can't find mem space %d\n", 1); 277 goto fail_io0; 278 } 279 280 hifn_set_retry(sc); 281 282 if (sc->sc_flags & HIFN_NO_BURSTWRITE) { 283 sc->sc_waw_lastgroup = -1; 284 sc->sc_waw_lastreg = 1; 285 } 286 287 sc->sc_dmat = pa->pa_dmat; 288 if (bus_dmamem_alloc(sc->sc_dmat, sizeof(*sc->sc_dma), PAGE_SIZE, 0, 289 &seg, 1, &rseg, BUS_DMA_NOWAIT)) { 290 aprint_error_dev(&sc->sc_dv, "can't alloc DMA buffer\n"); 291 goto fail_io1; 292 } 293 if (bus_dmamem_map(sc->sc_dmat, &seg, rseg, sizeof(*sc->sc_dma), &kva, 294 BUS_DMA_NOWAIT)) { 295 aprint_error_dev(&sc->sc_dv, "can't map DMA buffers (%lu bytes)\n", 296 (u_long)sizeof(*sc->sc_dma)); 297 bus_dmamem_free(sc->sc_dmat, &seg, rseg); 298 goto fail_io1; 299 } 300 if (bus_dmamap_create(sc->sc_dmat, sizeof(*sc->sc_dma), 1, 301 sizeof(*sc->sc_dma), 0, BUS_DMA_NOWAIT, &dmamap)) { 302 aprint_error_dev(&sc->sc_dv, "can't create DMA map\n"); 303 bus_dmamem_unmap(sc->sc_dmat, kva, sizeof(*sc->sc_dma)); 304 bus_dmamem_free(sc->sc_dmat, &seg, rseg); 305 goto fail_io1; 306 } 307 if (bus_dmamap_load(sc->sc_dmat, dmamap, kva, sizeof(*sc->sc_dma), 308 NULL, BUS_DMA_NOWAIT)) { 309 aprint_error_dev(&sc->sc_dv, "can't load DMA map\n"); 310 bus_dmamap_destroy(sc->sc_dmat, dmamap); 311 bus_dmamem_unmap(sc->sc_dmat, kva, sizeof(*sc->sc_dma)); 312 bus_dmamem_free(sc->sc_dmat, &seg, rseg); 313 goto fail_io1; 314 } 315 sc->sc_dmamap = dmamap; 316 sc->sc_dma = (struct hifn_dma *)kva; 317 memset(sc->sc_dma, 0, sizeof(*sc->sc_dma)); 318 319 hifn_reset_board(sc, 0); 320 321 if ((hifncap = hifn_enable_crypto(sc, pa->pa_id)) == NULL) { 322 aprint_error_dev(&sc->sc_dv, "crypto enabling failed\n"); 323 goto fail_mem; 324 } 325 hifn_reset_puc(sc); 326 327 hifn_init_dma(sc); 328 hifn_init_pci_registers(sc); 329 330 /* XXX can't dynamically determine ram type for 795x; force dram */ 331 if (sc->sc_flags & HIFN_IS_7956) 332 sc->sc_drammodel = 1; 333 else if (hifn_ramtype(sc)) 334 goto fail_mem; 335 336 if (sc->sc_drammodel == 0) 337 hifn_sramsize(sc); 338 else 339 hifn_dramsize(sc); 340 341 /* 342 * Workaround for NetSec 7751 rev A: half ram size because two 343 * of the address lines were left floating 344 */ 345 if (PCI_VENDOR(pa->pa_id) == PCI_VENDOR_NETSEC && 346 PCI_PRODUCT(pa->pa_id) == PCI_PRODUCT_NETSEC_7751 && 347 PCI_REVISION(pa->pa_class) == 0x61) 348 sc->sc_ramsize >>= 1; 349 350 if (pci_intr_map(pa, &ih)) { 351 aprint_error_dev(&sc->sc_dv, "couldn't map interrupt\n"); 352 goto fail_mem; 353 } 354 intrstr = pci_intr_string(pc, ih); 355 #ifdef __OpenBSD__ 356 sc->sc_ih = pci_intr_establish(pc, ih, IPL_NET, hifn_intr, sc, 357 self->dv_xname); 358 #else 359 sc->sc_ih = pci_intr_establish(pc, ih, IPL_NET, hifn_intr, sc); 360 #endif 361 if (sc->sc_ih == NULL) { 362 aprint_error_dev(&sc->sc_dv, "couldn't establish interrupt\n"); 363 if (intrstr != NULL) 364 aprint_error(" at %s", intrstr); 365 aprint_error("\n"); 366 goto fail_mem; 367 } 368 369 hifn_sessions(sc); 370 371 rseg = sc->sc_ramsize / 1024; 372 rbase = 'K'; 373 if (sc->sc_ramsize >= (1024 * 1024)) { 374 rbase = 'M'; 375 rseg /= 1024; 376 } 377 aprint_normal_dev(&sc->sc_dv, "%s, %d%cB %cRAM, interrupting at %s\n", 378 hifncap, rseg, rbase, 379 sc->sc_drammodel ? 'D' : 'S', intrstr); 380 381 sc->sc_cid = crypto_get_driverid(0); 382 if (sc->sc_cid < 0) { 383 aprint_error_dev(&sc->sc_dv, "couldn't get crypto driver id\n"); 384 goto fail_intr; 385 } 386 387 WRITE_REG_0(sc, HIFN_0_PUCNFG, 388 READ_REG_0(sc, HIFN_0_PUCNFG) | HIFN_PUCNFG_CHIPID); 389 ena = READ_REG_0(sc, HIFN_0_PUSTAT) & HIFN_PUSTAT_CHIPENA; 390 391 switch (ena) { 392 case HIFN_PUSTAT_ENA_2: 393 crypto_register(sc->sc_cid, CRYPTO_3DES_CBC, 0, 0, 394 hifn_newsession, hifn_freesession, hifn_process, sc); 395 crypto_register(sc->sc_cid, CRYPTO_ARC4, 0, 0, 396 hifn_newsession, hifn_freesession, hifn_process, sc); 397 if (sc->sc_flags & HIFN_HAS_AES) 398 crypto_register(sc->sc_cid, CRYPTO_AES_CBC, 0, 0, 399 hifn_newsession, hifn_freesession, 400 hifn_process, sc); 401 /*FALLTHROUGH*/ 402 case HIFN_PUSTAT_ENA_1: 403 crypto_register(sc->sc_cid, CRYPTO_MD5, 0, 0, 404 hifn_newsession, hifn_freesession, hifn_process, sc); 405 crypto_register(sc->sc_cid, CRYPTO_SHA1, 0, 0, 406 hifn_newsession, hifn_freesession, hifn_process, sc); 407 crypto_register(sc->sc_cid, CRYPTO_MD5_HMAC_96, 0, 0, 408 hifn_newsession, hifn_freesession, hifn_process, sc); 409 crypto_register(sc->sc_cid, CRYPTO_SHA1_HMAC_96, 0, 0, 410 hifn_newsession, hifn_freesession, hifn_process, sc); 411 crypto_register(sc->sc_cid, CRYPTO_DES_CBC, 0, 0, 412 hifn_newsession, hifn_freesession, hifn_process, sc); 413 break; 414 } 415 416 bus_dmamap_sync(sc->sc_dmat, sc->sc_dmamap, 0, 417 sc->sc_dmamap->dm_mapsize, 418 BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE); 419 420 if (sc->sc_flags & (HIFN_HAS_PUBLIC | HIFN_HAS_RNG)) 421 hifn_init_pubrng(sc); 422 423 #ifdef __OpenBSD__ 424 timeout_set(&sc->sc_tickto, hifn_tick, sc); 425 timeout_add(&sc->sc_tickto, hz); 426 #else 427 callout_init(&sc->sc_tickto, 0); 428 callout_reset(&sc->sc_tickto, hz, hifn_tick, sc); 429 #endif 430 return; 431 432 fail_intr: 433 pci_intr_disestablish(pc, sc->sc_ih); 434 fail_mem: 435 bus_dmamap_unload(sc->sc_dmat, dmamap); 436 bus_dmamap_destroy(sc->sc_dmat, dmamap); 437 bus_dmamem_unmap(sc->sc_dmat, kva, sizeof(*sc->sc_dma)); 438 bus_dmamem_free(sc->sc_dmat, &seg, rseg); 439 440 /* Turn off DMA polling */ 441 WRITE_REG_1(sc, HIFN_1_DMA_CNFG, HIFN_DMACNFG_MSTRESET | 442 HIFN_DMACNFG_DMARESET | HIFN_DMACNFG_MODE); 443 444 fail_io1: 445 bus_space_unmap(sc->sc_st1, sc->sc_sh1, iosize1); 446 fail_io0: 447 bus_space_unmap(sc->sc_st0, sc->sc_sh0, iosize0); 448 } 449 450 static int 451 hifn_init_pubrng(struct hifn_softc *sc) 452 { 453 u_int32_t r; 454 int i; 455 456 if ((sc->sc_flags & HIFN_IS_7811) == 0) { 457 /* Reset 7951 public key/rng engine */ 458 WRITE_REG_1(sc, HIFN_1_PUB_RESET, 459 READ_REG_1(sc, HIFN_1_PUB_RESET) | HIFN_PUBRST_RESET); 460 461 for (i = 0; i < 100; i++) { 462 DELAY(1000); 463 if ((READ_REG_1(sc, HIFN_1_PUB_RESET) & 464 HIFN_PUBRST_RESET) == 0) 465 break; 466 } 467 468 if (i == 100) { 469 printf("%s: public key init failed\n", 470 device_xname(&sc->sc_dv)); 471 return (1); 472 } 473 } 474 475 /* Enable the rng, if available */ 476 if (sc->sc_flags & HIFN_HAS_RNG) { 477 if (sc->sc_flags & HIFN_IS_7811) { 478 r = READ_REG_1(sc, HIFN_1_7811_RNGENA); 479 if (r & HIFN_7811_RNGENA_ENA) { 480 r &= ~HIFN_7811_RNGENA_ENA; 481 WRITE_REG_1(sc, HIFN_1_7811_RNGENA, r); 482 } 483 WRITE_REG_1(sc, HIFN_1_7811_RNGCFG, 484 HIFN_7811_RNGCFG_DEFL); 485 r |= HIFN_7811_RNGENA_ENA; 486 WRITE_REG_1(sc, HIFN_1_7811_RNGENA, r); 487 } else 488 WRITE_REG_1(sc, HIFN_1_RNG_CONFIG, 489 READ_REG_1(sc, HIFN_1_RNG_CONFIG) | 490 HIFN_RNGCFG_ENA); 491 492 /* 493 * The Hifn RNG documentation states that at their 494 * recommended "conservative" RNG config values, 495 * the RNG must warm up for 0.4s before providing 496 * data that meet their worst-case estimate of 0.06 497 * bits of random data per output register bit. 498 */ 499 DELAY(4000); 500 501 #ifdef __NetBSD__ 502 /* 503 * XXX Careful! The use of RND_FLAG_NO_ESTIMATE 504 * XXX here is unobvious: we later feed raw bits 505 * XXX into the "entropy pool" with rnd_add_data, 506 * XXX explicitly supplying an entropy estimate. 507 * XXX In this context, NO_ESTIMATE serves only 508 * XXX to prevent rnd_add_data from trying to 509 * XXX use the *time at which we added the data* 510 * XXX as entropy, which is not a good idea since 511 * XXX we add data periodically from a callout. 512 */ 513 rnd_attach_source(&sc->sc_rnd_source, device_xname(&sc->sc_dv), 514 RND_TYPE_RNG, RND_FLAG_NO_ESTIMATE); 515 #endif 516 517 sc->sc_rngfirst = 1; 518 if (hz >= 100) 519 sc->sc_rnghz = hz / 100; 520 else 521 sc->sc_rnghz = 1; 522 #ifdef __OpenBSD__ 523 timeout_set(&sc->sc_rngto, hifn_rng, sc); 524 #else /* !__OpenBSD__ */ 525 callout_init(&sc->sc_rngto, 0); 526 #endif /* !__OpenBSD__ */ 527 } 528 529 /* Enable public key engine, if available */ 530 if (sc->sc_flags & HIFN_HAS_PUBLIC) { 531 WRITE_REG_1(sc, HIFN_1_PUB_IEN, HIFN_PUBIEN_DONE); 532 sc->sc_dmaier |= HIFN_DMAIER_PUBDONE; 533 WRITE_REG_1(sc, HIFN_1_DMA_IER, sc->sc_dmaier); 534 } 535 536 /* Call directly into the RNG once to prime the pool. */ 537 hifn_rng(sc); /* Sets callout/timeout at end */ 538 539 return (0); 540 } 541 542 static void 543 hifn_rng(void *vsc) 544 { 545 struct hifn_softc *sc = vsc; 546 #ifdef __NetBSD__ 547 uint32_t num[64]; 548 #else 549 uint32_t num[2]; 550 #endif 551 uint32_t sts; 552 int i; 553 554 if (sc->sc_flags & HIFN_IS_7811) { 555 for (i = 0; i < 5; i++) { /* XXX why 5? */ 556 sts = READ_REG_1(sc, HIFN_1_7811_RNGSTS); 557 if (sts & HIFN_7811_RNGSTS_UFL) { 558 printf("%s: RNG underflow: disabling\n", 559 device_xname(&sc->sc_dv)); 560 return; 561 } 562 if ((sts & HIFN_7811_RNGSTS_RDY) == 0) 563 break; 564 565 /* 566 * There are at least two words in the RNG FIFO 567 * at this point. 568 */ 569 num[0] = READ_REG_1(sc, HIFN_1_7811_RNGDAT); 570 num[1] = READ_REG_1(sc, HIFN_1_7811_RNGDAT); 571 572 if (sc->sc_rngfirst) 573 sc->sc_rngfirst = 0; 574 #ifdef __NetBSD__ 575 rnd_add_data(&sc->sc_rnd_source, num, 576 2 * sizeof(num[0]), 577 (2 * sizeof(num[0]) * NBBY) / 578 HIFN_RNG_BITSPER); 579 #else 580 /* 581 * XXX This is a really bad idea. 582 * XXX Hifn estimate as little as 0.06 583 * XXX actual bits of entropy per output 584 * XXX register bit. How can we tell the 585 * XXX kernel RNG subsystem we're handing 586 * XXX it 64 "true" random bits, for any 587 * XXX sane value of "true"? 588 * XXX 589 * XXX The right thing to do here, if we 590 * XXX cannot supply an estimate ourselves, 591 * XXX would be to hash the bits locally. 592 */ 593 add_true_randomness(num[0]); 594 add_true_randomness(num[1]); 595 #endif 596 597 } 598 } else { 599 #ifdef __NetBSD__ 600 /* First time through, try to help fill the pool. */ 601 int nwords = sc->sc_rngfirst ? 602 sizeof(num) / sizeof(num[0]) : 4; 603 #else 604 int nwords = 2; 605 #endif 606 /* 607 * We must be *extremely* careful here. The Hifn 608 * 795x differ from the published 6500 RNG design 609 * in more ways than the obvious lack of the output 610 * FIFO and LFSR control registers. In fact, there 611 * is only one LFSR, instead of the 6500's two, and 612 * it's 32 bits, not 31. 613 * 614 * Further, a block diagram obtained from Hifn shows 615 * a very curious latching of this register: the LFSR 616 * rotates at a frequency of RNG_Clk / 8, but the 617 * RNG_Data register is latched at a frequency of 618 * RNG_Clk, which means that it is possible for 619 * consecutive reads of the RNG_Data register to read 620 * identical state from the LFSR. The simplest 621 * workaround seems to be to read eight samples from 622 * the register for each one that we use. Since each 623 * read must require at least one PCI cycle, and 624 * RNG_Clk is at least PCI_Clk, this is safe. 625 */ 626 627 628 if (sc->sc_rngfirst) { 629 sc->sc_rngfirst = 0; 630 } 631 632 633 for(i = 0 ; i < nwords * 8; i++) 634 { 635 volatile u_int32_t regtmp; 636 regtmp = READ_REG_1(sc, HIFN_1_RNG_DATA); 637 num[i / 8] = regtmp; 638 } 639 #ifdef __NetBSD__ 640 rnd_add_data(&sc->sc_rnd_source, num, 641 nwords * sizeof(num[0]), 642 (nwords * sizeof(num[0]) * NBBY) / 643 HIFN_RNG_BITSPER); 644 #else 645 /* XXX a bad idea; see 7811 block above */ 646 add_true_randomness(num[0]); 647 #endif 648 } 649 650 #ifdef __OpenBSD__ 651 timeout_add(&sc->sc_rngto, sc->sc_rnghz); 652 #else 653 callout_reset(&sc->sc_rngto, sc->sc_rnghz, hifn_rng, sc); 654 #endif 655 } 656 657 static void 658 hifn_puc_wait(struct hifn_softc *sc) 659 { 660 int i; 661 662 for (i = 5000; i > 0; i--) { 663 DELAY(1); 664 if (!(READ_REG_0(sc, HIFN_0_PUCTRL) & HIFN_PUCTRL_RESET)) 665 break; 666 } 667 if (!i) 668 printf("%s: proc unit did not reset\n", device_xname(&sc->sc_dv)); 669 } 670 671 /* 672 * Reset the processing unit. 673 */ 674 static void 675 hifn_reset_puc(struct hifn_softc *sc) 676 { 677 /* Reset processing unit */ 678 WRITE_REG_0(sc, HIFN_0_PUCTRL, HIFN_PUCTRL_DMAENA); 679 hifn_puc_wait(sc); 680 } 681 682 static void 683 hifn_set_retry(struct hifn_softc *sc) 684 { 685 u_int32_t r; 686 687 r = pci_conf_read(sc->sc_pci_pc, sc->sc_pci_tag, HIFN_TRDY_TIMEOUT); 688 r &= 0xffff0000; 689 pci_conf_write(sc->sc_pci_pc, sc->sc_pci_tag, HIFN_TRDY_TIMEOUT, r); 690 } 691 692 /* 693 * Resets the board. Values in the regesters are left as is 694 * from the reset (i.e. initial values are assigned elsewhere). 695 */ 696 static void 697 hifn_reset_board(struct hifn_softc *sc, int full) 698 { 699 u_int32_t reg; 700 701 /* 702 * Set polling in the DMA configuration register to zero. 0x7 avoids 703 * resetting the board and zeros out the other fields. 704 */ 705 WRITE_REG_1(sc, HIFN_1_DMA_CNFG, HIFN_DMACNFG_MSTRESET | 706 HIFN_DMACNFG_DMARESET | HIFN_DMACNFG_MODE); 707 708 /* 709 * Now that polling has been disabled, we have to wait 1 ms 710 * before resetting the board. 711 */ 712 DELAY(1000); 713 714 /* Reset the DMA unit */ 715 if (full) { 716 WRITE_REG_1(sc, HIFN_1_DMA_CNFG, HIFN_DMACNFG_MODE); 717 DELAY(1000); 718 } else { 719 WRITE_REG_1(sc, HIFN_1_DMA_CNFG, 720 HIFN_DMACNFG_MODE | HIFN_DMACNFG_MSTRESET); 721 hifn_reset_puc(sc); 722 } 723 724 memset(sc->sc_dma, 0, sizeof(*sc->sc_dma)); 725 726 /* Bring dma unit out of reset */ 727 WRITE_REG_1(sc, HIFN_1_DMA_CNFG, HIFN_DMACNFG_MSTRESET | 728 HIFN_DMACNFG_DMARESET | HIFN_DMACNFG_MODE); 729 730 hifn_puc_wait(sc); 731 732 hifn_set_retry(sc); 733 734 if (sc->sc_flags & HIFN_IS_7811) { 735 for (reg = 0; reg < 1000; reg++) { 736 if (READ_REG_1(sc, HIFN_1_7811_MIPSRST) & 737 HIFN_MIPSRST_CRAMINIT) 738 break; 739 DELAY(1000); 740 } 741 if (reg == 1000) 742 printf(": cram init timeout\n"); 743 } 744 } 745 746 static u_int32_t 747 hifn_next_signature(u_int32_t a, u_int cnt) 748 { 749 int i; 750 u_int32_t v; 751 752 for (i = 0; i < cnt; i++) { 753 754 /* get the parity */ 755 v = a & 0x80080125; 756 v ^= v >> 16; 757 v ^= v >> 8; 758 v ^= v >> 4; 759 v ^= v >> 2; 760 v ^= v >> 1; 761 762 a = (v & 1) ^ (a << 1); 763 } 764 765 return a; 766 } 767 768 static struct pci2id { 769 u_short pci_vendor; 770 u_short pci_prod; 771 char card_id[13]; 772 } const pci2id[] = { 773 { 774 PCI_VENDOR_HIFN, 775 PCI_PRODUCT_HIFN_7951, 776 { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 777 0x00, 0x00, 0x00, 0x00, 0x00 } 778 }, { 779 PCI_VENDOR_HIFN, 780 PCI_PRODUCT_HIFN_7955, 781 { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 782 0x00, 0x00, 0x00, 0x00, 0x00 } 783 }, { 784 PCI_VENDOR_HIFN, 785 PCI_PRODUCT_HIFN_7956, 786 { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 787 0x00, 0x00, 0x00, 0x00, 0x00 } 788 }, { 789 PCI_VENDOR_NETSEC, 790 PCI_PRODUCT_NETSEC_7751, 791 { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 792 0x00, 0x00, 0x00, 0x00, 0x00 } 793 }, { 794 PCI_VENDOR_INVERTEX, 795 PCI_PRODUCT_INVERTEX_AEON, 796 { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 797 0x00, 0x00, 0x00, 0x00, 0x00 } 798 }, { 799 PCI_VENDOR_HIFN, 800 PCI_PRODUCT_HIFN_7811, 801 { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 802 0x00, 0x00, 0x00, 0x00, 0x00 } 803 }, { 804 /* 805 * Other vendors share this PCI ID as well, such as 806 * http://www.powercrypt.com, and obviously they also 807 * use the same key. 808 */ 809 PCI_VENDOR_HIFN, 810 PCI_PRODUCT_HIFN_7751, 811 { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 812 0x00, 0x00, 0x00, 0x00, 0x00 } 813 }, 814 }; 815 816 /* 817 * Checks to see if crypto is already enabled. If crypto isn't enable, 818 * "hifn_enable_crypto" is called to enable it. The check is important, 819 * as enabling crypto twice will lock the board. 820 */ 821 static const char * 822 hifn_enable_crypto(struct hifn_softc *sc, pcireg_t pciid) 823 { 824 u_int32_t dmacfg, ramcfg, encl, addr, i; 825 const char *offtbl = NULL; 826 827 for (i = 0; i < sizeof(pci2id)/sizeof(pci2id[0]); i++) { 828 if (pci2id[i].pci_vendor == PCI_VENDOR(pciid) && 829 pci2id[i].pci_prod == PCI_PRODUCT(pciid)) { 830 offtbl = pci2id[i].card_id; 831 break; 832 } 833 } 834 835 if (offtbl == NULL) { 836 #ifdef HIFN_DEBUG 837 aprint_debug_dev(&sc->sc_dv, "Unknown card!\n"); 838 #endif 839 return (NULL); 840 } 841 842 ramcfg = READ_REG_0(sc, HIFN_0_PUCNFG); 843 dmacfg = READ_REG_1(sc, HIFN_1_DMA_CNFG); 844 845 /* 846 * The RAM config register's encrypt level bit needs to be set before 847 * every read performed on the encryption level register. 848 */ 849 WRITE_REG_0(sc, HIFN_0_PUCNFG, ramcfg | HIFN_PUCNFG_CHIPID); 850 851 encl = READ_REG_0(sc, HIFN_0_PUSTAT) & HIFN_PUSTAT_CHIPENA; 852 853 /* 854 * Make sure we don't re-unlock. Two unlocks kills chip until the 855 * next reboot. 856 */ 857 if (encl == HIFN_PUSTAT_ENA_1 || encl == HIFN_PUSTAT_ENA_2) { 858 #ifdef HIFN_DEBUG 859 aprint_debug_dev(&sc->sc_dv, "Strong Crypto already enabled!\n"); 860 #endif 861 goto report; 862 } 863 864 if (encl != 0 && encl != HIFN_PUSTAT_ENA_0) { 865 #ifdef HIFN_DEBUG 866 aprint_debug_dev(&sc->sc_dv, "Unknown encryption level\n"); 867 #endif 868 return (NULL); 869 } 870 871 WRITE_REG_1(sc, HIFN_1_DMA_CNFG, HIFN_DMACNFG_UNLOCK | 872 HIFN_DMACNFG_MSTRESET | HIFN_DMACNFG_DMARESET | HIFN_DMACNFG_MODE); 873 DELAY(1000); 874 addr = READ_REG_1(sc, HIFN_1_UNLOCK_SECRET1); 875 DELAY(1000); 876 WRITE_REG_1(sc, HIFN_1_UNLOCK_SECRET2, 0); 877 DELAY(1000); 878 879 for (i = 0; i <= 12; i++) { 880 addr = hifn_next_signature(addr, offtbl[i] + 0x101); 881 WRITE_REG_1(sc, HIFN_1_UNLOCK_SECRET2, addr); 882 883 DELAY(1000); 884 } 885 886 WRITE_REG_0(sc, HIFN_0_PUCNFG, ramcfg | HIFN_PUCNFG_CHIPID); 887 encl = READ_REG_0(sc, HIFN_0_PUSTAT) & HIFN_PUSTAT_CHIPENA; 888 889 #ifdef HIFN_DEBUG 890 if (encl != HIFN_PUSTAT_ENA_1 && encl != HIFN_PUSTAT_ENA_2) 891 aprint_debug("Encryption engine is permanently locked until next system reset."); 892 else 893 aprint_debug("Encryption engine enabled successfully!"); 894 #endif 895 896 report: 897 WRITE_REG_0(sc, HIFN_0_PUCNFG, ramcfg); 898 WRITE_REG_1(sc, HIFN_1_DMA_CNFG, dmacfg); 899 900 switch (encl) { 901 case HIFN_PUSTAT_ENA_0: 902 return ("LZS-only (no encr/auth)"); 903 904 case HIFN_PUSTAT_ENA_1: 905 return ("DES"); 906 907 case HIFN_PUSTAT_ENA_2: 908 if (sc->sc_flags & HIFN_HAS_AES) 909 return ("3DES/AES"); 910 else 911 return ("3DES"); 912 913 default: 914 return ("disabled"); 915 } 916 /* NOTREACHED */ 917 } 918 919 /* 920 * Give initial values to the registers listed in the "Register Space" 921 * section of the HIFN Software Development reference manual. 922 */ 923 static void 924 hifn_init_pci_registers(struct hifn_softc *sc) 925 { 926 /* write fixed values needed by the Initialization registers */ 927 WRITE_REG_0(sc, HIFN_0_PUCTRL, HIFN_PUCTRL_DMAENA); 928 WRITE_REG_0(sc, HIFN_0_FIFOCNFG, HIFN_FIFOCNFG_THRESHOLD); 929 WRITE_REG_0(sc, HIFN_0_PUIER, HIFN_PUIER_DSTOVER); 930 931 /* write all 4 ring address registers */ 932 WRITE_REG_1(sc, HIFN_1_DMA_CRAR, sc->sc_dmamap->dm_segs[0].ds_addr + 933 offsetof(struct hifn_dma, cmdr[0])); 934 WRITE_REG_1(sc, HIFN_1_DMA_SRAR, sc->sc_dmamap->dm_segs[0].ds_addr + 935 offsetof(struct hifn_dma, srcr[0])); 936 WRITE_REG_1(sc, HIFN_1_DMA_DRAR, sc->sc_dmamap->dm_segs[0].ds_addr + 937 offsetof(struct hifn_dma, dstr[0])); 938 WRITE_REG_1(sc, HIFN_1_DMA_RRAR, sc->sc_dmamap->dm_segs[0].ds_addr + 939 offsetof(struct hifn_dma, resr[0])); 940 941 DELAY(2000); 942 943 /* write status register */ 944 WRITE_REG_1(sc, HIFN_1_DMA_CSR, 945 HIFN_DMACSR_D_CTRL_DIS | HIFN_DMACSR_R_CTRL_DIS | 946 HIFN_DMACSR_S_CTRL_DIS | HIFN_DMACSR_C_CTRL_DIS | 947 HIFN_DMACSR_D_ABORT | HIFN_DMACSR_D_DONE | HIFN_DMACSR_D_LAST | 948 HIFN_DMACSR_D_WAIT | HIFN_DMACSR_D_OVER | 949 HIFN_DMACSR_R_ABORT | HIFN_DMACSR_R_DONE | HIFN_DMACSR_R_LAST | 950 HIFN_DMACSR_R_WAIT | HIFN_DMACSR_R_OVER | 951 HIFN_DMACSR_S_ABORT | HIFN_DMACSR_S_DONE | HIFN_DMACSR_S_LAST | 952 HIFN_DMACSR_S_WAIT | 953 HIFN_DMACSR_C_ABORT | HIFN_DMACSR_C_DONE | HIFN_DMACSR_C_LAST | 954 HIFN_DMACSR_C_WAIT | 955 HIFN_DMACSR_ENGINE | 956 ((sc->sc_flags & HIFN_HAS_PUBLIC) ? 957 HIFN_DMACSR_PUBDONE : 0) | 958 ((sc->sc_flags & HIFN_IS_7811) ? 959 HIFN_DMACSR_ILLW | HIFN_DMACSR_ILLR : 0)); 960 961 sc->sc_d_busy = sc->sc_r_busy = sc->sc_s_busy = sc->sc_c_busy = 0; 962 sc->sc_dmaier |= HIFN_DMAIER_R_DONE | HIFN_DMAIER_C_ABORT | 963 HIFN_DMAIER_D_OVER | HIFN_DMAIER_R_OVER | 964 HIFN_DMAIER_S_ABORT | HIFN_DMAIER_D_ABORT | HIFN_DMAIER_R_ABORT | 965 HIFN_DMAIER_ENGINE | 966 ((sc->sc_flags & HIFN_IS_7811) ? 967 HIFN_DMAIER_ILLW | HIFN_DMAIER_ILLR : 0); 968 sc->sc_dmaier &= ~HIFN_DMAIER_C_WAIT; 969 WRITE_REG_1(sc, HIFN_1_DMA_IER, sc->sc_dmaier); 970 CLR_LED(sc, HIFN_MIPSRST_LED0 | HIFN_MIPSRST_LED1 | HIFN_MIPSRST_LED2); 971 972 if (sc->sc_flags & HIFN_IS_7956) { 973 WRITE_REG_0(sc, HIFN_0_PUCNFG, HIFN_PUCNFG_COMPSING | 974 HIFN_PUCNFG_TCALLPHASES | 975 HIFN_PUCNFG_TCDRVTOTEM | HIFN_PUCNFG_BUS32); 976 WRITE_REG_1(sc, HIFN_1_PLL, HIFN_PLL_7956); 977 } else { 978 WRITE_REG_0(sc, HIFN_0_PUCNFG, HIFN_PUCNFG_COMPSING | 979 HIFN_PUCNFG_DRFR_128 | HIFN_PUCNFG_TCALLPHASES | 980 HIFN_PUCNFG_TCDRVTOTEM | HIFN_PUCNFG_BUS32 | 981 (sc->sc_drammodel ? HIFN_PUCNFG_DRAM : HIFN_PUCNFG_SRAM)); 982 } 983 984 WRITE_REG_0(sc, HIFN_0_PUISR, HIFN_PUISR_DSTOVER); 985 WRITE_REG_1(sc, HIFN_1_DMA_CNFG, HIFN_DMACNFG_MSTRESET | 986 HIFN_DMACNFG_DMARESET | HIFN_DMACNFG_MODE | HIFN_DMACNFG_LAST | 987 ((HIFN_POLL_FREQUENCY << 16 ) & HIFN_DMACNFG_POLLFREQ) | 988 ((HIFN_POLL_SCALAR << 8) & HIFN_DMACNFG_POLLINVAL)); 989 } 990 991 /* 992 * The maximum number of sessions supported by the card 993 * is dependent on the amount of context ram, which 994 * encryption algorithms are enabled, and how compression 995 * is configured. This should be configured before this 996 * routine is called. 997 */ 998 static void 999 hifn_sessions(struct hifn_softc *sc) 1000 { 1001 u_int32_t pucnfg; 1002 int ctxsize; 1003 1004 pucnfg = READ_REG_0(sc, HIFN_0_PUCNFG); 1005 1006 if (pucnfg & HIFN_PUCNFG_COMPSING) { 1007 if (pucnfg & HIFN_PUCNFG_ENCCNFG) 1008 ctxsize = 128; 1009 else 1010 ctxsize = 512; 1011 /* 1012 * 7955/7956 has internal context memory of 32K 1013 */ 1014 if (sc->sc_flags & HIFN_IS_7956) 1015 sc->sc_maxses = 32768 / ctxsize; 1016 else 1017 sc->sc_maxses = 1 + 1018 ((sc->sc_ramsize - 32768) / ctxsize); 1019 } 1020 else 1021 sc->sc_maxses = sc->sc_ramsize / 16384; 1022 1023 if (sc->sc_maxses > 2048) 1024 sc->sc_maxses = 2048; 1025 } 1026 1027 /* 1028 * Determine ram type (sram or dram). Board should be just out of a reset 1029 * state when this is called. 1030 */ 1031 static int 1032 hifn_ramtype(struct hifn_softc *sc) 1033 { 1034 u_int8_t data[8], dataexpect[8]; 1035 int i; 1036 1037 for (i = 0; i < sizeof(data); i++) 1038 data[i] = dataexpect[i] = 0x55; 1039 if (hifn_writeramaddr(sc, 0, data)) 1040 return (-1); 1041 if (hifn_readramaddr(sc, 0, data)) 1042 return (-1); 1043 if (memcmp(data, dataexpect, sizeof(data)) != 0) { 1044 sc->sc_drammodel = 1; 1045 return (0); 1046 } 1047 1048 for (i = 0; i < sizeof(data); i++) 1049 data[i] = dataexpect[i] = 0xaa; 1050 if (hifn_writeramaddr(sc, 0, data)) 1051 return (-1); 1052 if (hifn_readramaddr(sc, 0, data)) 1053 return (-1); 1054 if (memcmp(data, dataexpect, sizeof(data)) != 0) { 1055 sc->sc_drammodel = 1; 1056 return (0); 1057 } 1058 1059 return (0); 1060 } 1061 1062 #define HIFN_SRAM_MAX (32 << 20) 1063 #define HIFN_SRAM_STEP_SIZE 16384 1064 #define HIFN_SRAM_GRANULARITY (HIFN_SRAM_MAX / HIFN_SRAM_STEP_SIZE) 1065 1066 static int 1067 hifn_sramsize(struct hifn_softc *sc) 1068 { 1069 u_int32_t a; 1070 u_int8_t data[8]; 1071 u_int8_t dataexpect[sizeof(data)]; 1072 int32_t i; 1073 1074 for (i = 0; i < sizeof(data); i++) 1075 data[i] = dataexpect[i] = i ^ 0x5a; 1076 1077 for (i = HIFN_SRAM_GRANULARITY - 1; i >= 0; i--) { 1078 a = i * HIFN_SRAM_STEP_SIZE; 1079 memcpy(data, &i, sizeof(i)); 1080 hifn_writeramaddr(sc, a, data); 1081 } 1082 1083 for (i = 0; i < HIFN_SRAM_GRANULARITY; i++) { 1084 a = i * HIFN_SRAM_STEP_SIZE; 1085 memcpy(dataexpect, &i, sizeof(i)); 1086 if (hifn_readramaddr(sc, a, data) < 0) 1087 return (0); 1088 if (memcmp(data, dataexpect, sizeof(data)) != 0) 1089 return (0); 1090 sc->sc_ramsize = a + HIFN_SRAM_STEP_SIZE; 1091 } 1092 1093 return (0); 1094 } 1095 1096 /* 1097 * XXX For dram boards, one should really try all of the 1098 * HIFN_PUCNFG_DSZ_*'s. This just assumes that PUCNFG 1099 * is already set up correctly. 1100 */ 1101 static int 1102 hifn_dramsize(struct hifn_softc *sc) 1103 { 1104 u_int32_t cnfg; 1105 1106 if (sc->sc_flags & HIFN_IS_7956) { 1107 /* 1108 * 7955/7956 have a fixed internal ram of only 32K. 1109 */ 1110 sc->sc_ramsize = 32768; 1111 } else { 1112 cnfg = READ_REG_0(sc, HIFN_0_PUCNFG) & 1113 HIFN_PUCNFG_DRAMMASK; 1114 sc->sc_ramsize = 1 << ((cnfg >> 13) + 18); 1115 } 1116 return (0); 1117 } 1118 1119 static void 1120 hifn_alloc_slot(struct hifn_softc *sc, int *cmdp, int *srcp, int *dstp, 1121 int *resp) 1122 { 1123 struct hifn_dma *dma = sc->sc_dma; 1124 1125 if (dma->cmdi == HIFN_D_CMD_RSIZE) { 1126 dma->cmdi = 0; 1127 dma->cmdr[HIFN_D_CMD_RSIZE].l = htole32(HIFN_D_VALID | 1128 HIFN_D_JUMP | HIFN_D_MASKDONEIRQ); 1129 HIFN_CMDR_SYNC(sc, HIFN_D_CMD_RSIZE, 1130 BUS_DMASYNC_PREWRITE | BUS_DMASYNC_PREREAD); 1131 } 1132 *cmdp = dma->cmdi++; 1133 dma->cmdk = dma->cmdi; 1134 1135 if (dma->srci == HIFN_D_SRC_RSIZE) { 1136 dma->srci = 0; 1137 dma->srcr[HIFN_D_SRC_RSIZE].l = htole32(HIFN_D_VALID | 1138 HIFN_D_JUMP | HIFN_D_MASKDONEIRQ); 1139 HIFN_SRCR_SYNC(sc, HIFN_D_SRC_RSIZE, 1140 BUS_DMASYNC_PREWRITE | BUS_DMASYNC_PREREAD); 1141 } 1142 *srcp = dma->srci++; 1143 dma->srck = dma->srci; 1144 1145 if (dma->dsti == HIFN_D_DST_RSIZE) { 1146 dma->dsti = 0; 1147 dma->dstr[HIFN_D_DST_RSIZE].l = htole32(HIFN_D_VALID | 1148 HIFN_D_JUMP | HIFN_D_MASKDONEIRQ); 1149 HIFN_DSTR_SYNC(sc, HIFN_D_DST_RSIZE, 1150 BUS_DMASYNC_PREWRITE | BUS_DMASYNC_PREREAD); 1151 } 1152 *dstp = dma->dsti++; 1153 dma->dstk = dma->dsti; 1154 1155 if (dma->resi == HIFN_D_RES_RSIZE) { 1156 dma->resi = 0; 1157 dma->resr[HIFN_D_RES_RSIZE].l = htole32(HIFN_D_VALID | 1158 HIFN_D_JUMP | HIFN_D_MASKDONEIRQ); 1159 HIFN_RESR_SYNC(sc, HIFN_D_RES_RSIZE, 1160 BUS_DMASYNC_PREWRITE | BUS_DMASYNC_PREREAD); 1161 } 1162 *resp = dma->resi++; 1163 dma->resk = dma->resi; 1164 } 1165 1166 static int 1167 hifn_writeramaddr(struct hifn_softc *sc, int addr, u_int8_t *data) 1168 { 1169 struct hifn_dma *dma = sc->sc_dma; 1170 struct hifn_base_command wc; 1171 const u_int32_t masks = HIFN_D_VALID | HIFN_D_LAST | HIFN_D_MASKDONEIRQ; 1172 int r, cmdi, resi, srci, dsti; 1173 1174 wc.masks = htole16(3 << 13); 1175 wc.session_num = htole16(addr >> 14); 1176 wc.total_source_count = htole16(8); 1177 wc.total_dest_count = htole16(addr & 0x3fff); 1178 1179 hifn_alloc_slot(sc, &cmdi, &srci, &dsti, &resi); 1180 1181 WRITE_REG_1(sc, HIFN_1_DMA_CSR, 1182 HIFN_DMACSR_C_CTRL_ENA | HIFN_DMACSR_S_CTRL_ENA | 1183 HIFN_DMACSR_D_CTRL_ENA | HIFN_DMACSR_R_CTRL_ENA); 1184 1185 /* build write command */ 1186 memset(dma->command_bufs[cmdi], 0, HIFN_MAX_COMMAND); 1187 *(struct hifn_base_command *)dma->command_bufs[cmdi] = wc; 1188 memcpy(&dma->test_src, data, sizeof(dma->test_src)); 1189 1190 dma->srcr[srci].p = htole32(sc->sc_dmamap->dm_segs[0].ds_addr 1191 + offsetof(struct hifn_dma, test_src)); 1192 dma->dstr[dsti].p = htole32(sc->sc_dmamap->dm_segs[0].ds_addr 1193 + offsetof(struct hifn_dma, test_dst)); 1194 1195 dma->cmdr[cmdi].l = htole32(16 | masks); 1196 dma->srcr[srci].l = htole32(8 | masks); 1197 dma->dstr[dsti].l = htole32(4 | masks); 1198 dma->resr[resi].l = htole32(4 | masks); 1199 1200 bus_dmamap_sync(sc->sc_dmat, sc->sc_dmamap, 1201 0, sc->sc_dmamap->dm_mapsize, 1202 BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE); 1203 1204 for (r = 10000; r >= 0; r--) { 1205 DELAY(10); 1206 bus_dmamap_sync(sc->sc_dmat, sc->sc_dmamap, 1207 0, sc->sc_dmamap->dm_mapsize, 1208 BUS_DMASYNC_POSTREAD | BUS_DMASYNC_POSTWRITE); 1209 if ((dma->resr[resi].l & htole32(HIFN_D_VALID)) == 0) 1210 break; 1211 bus_dmamap_sync(sc->sc_dmat, sc->sc_dmamap, 1212 0, sc->sc_dmamap->dm_mapsize, 1213 BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE); 1214 } 1215 if (r == 0) { 1216 printf("%s: writeramaddr -- " 1217 "result[%d](addr %d) still valid\n", 1218 device_xname(&sc->sc_dv), resi, addr); 1219 r = -1; 1220 return (-1); 1221 } else 1222 r = 0; 1223 1224 WRITE_REG_1(sc, HIFN_1_DMA_CSR, 1225 HIFN_DMACSR_C_CTRL_DIS | HIFN_DMACSR_S_CTRL_DIS | 1226 HIFN_DMACSR_D_CTRL_DIS | HIFN_DMACSR_R_CTRL_DIS); 1227 1228 return (r); 1229 } 1230 1231 static int 1232 hifn_readramaddr(struct hifn_softc *sc, int addr, u_int8_t *data) 1233 { 1234 struct hifn_dma *dma = sc->sc_dma; 1235 struct hifn_base_command rc; 1236 const u_int32_t masks = HIFN_D_VALID | HIFN_D_LAST | HIFN_D_MASKDONEIRQ; 1237 int r, cmdi, srci, dsti, resi; 1238 1239 rc.masks = htole16(2 << 13); 1240 rc.session_num = htole16(addr >> 14); 1241 rc.total_source_count = htole16(addr & 0x3fff); 1242 rc.total_dest_count = htole16(8); 1243 1244 hifn_alloc_slot(sc, &cmdi, &srci, &dsti, &resi); 1245 1246 WRITE_REG_1(sc, HIFN_1_DMA_CSR, 1247 HIFN_DMACSR_C_CTRL_ENA | HIFN_DMACSR_S_CTRL_ENA | 1248 HIFN_DMACSR_D_CTRL_ENA | HIFN_DMACSR_R_CTRL_ENA); 1249 1250 memset(dma->command_bufs[cmdi], 0, HIFN_MAX_COMMAND); 1251 *(struct hifn_base_command *)dma->command_bufs[cmdi] = rc; 1252 1253 dma->srcr[srci].p = htole32(sc->sc_dmamap->dm_segs[0].ds_addr + 1254 offsetof(struct hifn_dma, test_src)); 1255 dma->test_src = 0; 1256 dma->dstr[dsti].p = htole32(sc->sc_dmamap->dm_segs[0].ds_addr + 1257 offsetof(struct hifn_dma, test_dst)); 1258 dma->test_dst = 0; 1259 dma->cmdr[cmdi].l = htole32(8 | masks); 1260 dma->srcr[srci].l = htole32(8 | masks); 1261 dma->dstr[dsti].l = htole32(8 | masks); 1262 dma->resr[resi].l = htole32(HIFN_MAX_RESULT | masks); 1263 1264 bus_dmamap_sync(sc->sc_dmat, sc->sc_dmamap, 1265 0, sc->sc_dmamap->dm_mapsize, 1266 BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE); 1267 1268 for (r = 10000; r >= 0; r--) { 1269 DELAY(10); 1270 bus_dmamap_sync(sc->sc_dmat, sc->sc_dmamap, 1271 0, sc->sc_dmamap->dm_mapsize, 1272 BUS_DMASYNC_POSTREAD | BUS_DMASYNC_POSTWRITE); 1273 if ((dma->resr[resi].l & htole32(HIFN_D_VALID)) == 0) 1274 break; 1275 bus_dmamap_sync(sc->sc_dmat, sc->sc_dmamap, 1276 0, sc->sc_dmamap->dm_mapsize, 1277 BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE); 1278 } 1279 if (r == 0) { 1280 printf("%s: readramaddr -- " 1281 "result[%d](addr %d) still valid\n", 1282 device_xname(&sc->sc_dv), resi, addr); 1283 r = -1; 1284 } else { 1285 r = 0; 1286 memcpy(data, &dma->test_dst, sizeof(dma->test_dst)); 1287 } 1288 1289 WRITE_REG_1(sc, HIFN_1_DMA_CSR, 1290 HIFN_DMACSR_C_CTRL_DIS | HIFN_DMACSR_S_CTRL_DIS | 1291 HIFN_DMACSR_D_CTRL_DIS | HIFN_DMACSR_R_CTRL_DIS); 1292 1293 return (r); 1294 } 1295 1296 /* 1297 * Initialize the descriptor rings. 1298 */ 1299 static void 1300 hifn_init_dma(struct hifn_softc *sc) 1301 { 1302 struct hifn_dma *dma = sc->sc_dma; 1303 int i; 1304 1305 hifn_set_retry(sc); 1306 1307 /* initialize static pointer values */ 1308 for (i = 0; i < HIFN_D_CMD_RSIZE; i++) 1309 dma->cmdr[i].p = htole32(sc->sc_dmamap->dm_segs[0].ds_addr + 1310 offsetof(struct hifn_dma, command_bufs[i][0])); 1311 for (i = 0; i < HIFN_D_RES_RSIZE; i++) 1312 dma->resr[i].p = htole32(sc->sc_dmamap->dm_segs[0].ds_addr + 1313 offsetof(struct hifn_dma, result_bufs[i][0])); 1314 1315 dma->cmdr[HIFN_D_CMD_RSIZE].p = 1316 htole32(sc->sc_dmamap->dm_segs[0].ds_addr + 1317 offsetof(struct hifn_dma, cmdr[0])); 1318 dma->srcr[HIFN_D_SRC_RSIZE].p = 1319 htole32(sc->sc_dmamap->dm_segs[0].ds_addr + 1320 offsetof(struct hifn_dma, srcr[0])); 1321 dma->dstr[HIFN_D_DST_RSIZE].p = 1322 htole32(sc->sc_dmamap->dm_segs[0].ds_addr + 1323 offsetof(struct hifn_dma, dstr[0])); 1324 dma->resr[HIFN_D_RES_RSIZE].p = 1325 htole32(sc->sc_dmamap->dm_segs[0].ds_addr + 1326 offsetof(struct hifn_dma, resr[0])); 1327 1328 dma->cmdu = dma->srcu = dma->dstu = dma->resu = 0; 1329 dma->cmdi = dma->srci = dma->dsti = dma->resi = 0; 1330 dma->cmdk = dma->srck = dma->dstk = dma->resk = 0; 1331 } 1332 1333 /* 1334 * Writes out the raw command buffer space. Returns the 1335 * command buffer size. 1336 */ 1337 static u_int 1338 hifn_write_command(struct hifn_command *cmd, u_int8_t *buf) 1339 { 1340 u_int8_t *buf_pos; 1341 struct hifn_base_command *base_cmd; 1342 struct hifn_mac_command *mac_cmd; 1343 struct hifn_crypt_command *cry_cmd; 1344 struct hifn_comp_command *comp_cmd; 1345 int using_mac, using_crypt, using_comp, len, ivlen; 1346 u_int32_t dlen, slen; 1347 1348 buf_pos = buf; 1349 using_mac = cmd->base_masks & HIFN_BASE_CMD_MAC; 1350 using_crypt = cmd->base_masks & HIFN_BASE_CMD_CRYPT; 1351 using_comp = cmd->base_masks & HIFN_BASE_CMD_COMP; 1352 1353 base_cmd = (struct hifn_base_command *)buf_pos; 1354 base_cmd->masks = htole16(cmd->base_masks); 1355 slen = cmd->src_map->dm_mapsize; 1356 if (cmd->sloplen) 1357 dlen = cmd->dst_map->dm_mapsize - cmd->sloplen + 1358 sizeof(u_int32_t); 1359 else 1360 dlen = cmd->dst_map->dm_mapsize; 1361 base_cmd->total_source_count = htole16(slen & HIFN_BASE_CMD_LENMASK_LO); 1362 base_cmd->total_dest_count = htole16(dlen & HIFN_BASE_CMD_LENMASK_LO); 1363 dlen >>= 16; 1364 slen >>= 16; 1365 base_cmd->session_num = htole16(cmd->session_num | 1366 ((slen << HIFN_BASE_CMD_SRCLEN_S) & HIFN_BASE_CMD_SRCLEN_M) | 1367 ((dlen << HIFN_BASE_CMD_DSTLEN_S) & HIFN_BASE_CMD_DSTLEN_M)); 1368 buf_pos += sizeof(struct hifn_base_command); 1369 1370 if (using_comp) { 1371 comp_cmd = (struct hifn_comp_command *)buf_pos; 1372 dlen = cmd->compcrd->crd_len; 1373 comp_cmd->source_count = htole16(dlen & 0xffff); 1374 dlen >>= 16; 1375 comp_cmd->masks = htole16(cmd->comp_masks | 1376 ((dlen << HIFN_COMP_CMD_SRCLEN_S) & HIFN_COMP_CMD_SRCLEN_M)); 1377 comp_cmd->header_skip = htole16(cmd->compcrd->crd_skip); 1378 comp_cmd->reserved = 0; 1379 buf_pos += sizeof(struct hifn_comp_command); 1380 } 1381 1382 if (using_mac) { 1383 mac_cmd = (struct hifn_mac_command *)buf_pos; 1384 dlen = cmd->maccrd->crd_len; 1385 mac_cmd->source_count = htole16(dlen & 0xffff); 1386 dlen >>= 16; 1387 mac_cmd->masks = htole16(cmd->mac_masks | 1388 ((dlen << HIFN_MAC_CMD_SRCLEN_S) & HIFN_MAC_CMD_SRCLEN_M)); 1389 mac_cmd->header_skip = htole16(cmd->maccrd->crd_skip); 1390 mac_cmd->reserved = 0; 1391 buf_pos += sizeof(struct hifn_mac_command); 1392 } 1393 1394 if (using_crypt) { 1395 cry_cmd = (struct hifn_crypt_command *)buf_pos; 1396 dlen = cmd->enccrd->crd_len; 1397 cry_cmd->source_count = htole16(dlen & 0xffff); 1398 dlen >>= 16; 1399 cry_cmd->masks = htole16(cmd->cry_masks | 1400 ((dlen << HIFN_CRYPT_CMD_SRCLEN_S) & HIFN_CRYPT_CMD_SRCLEN_M)); 1401 cry_cmd->header_skip = htole16(cmd->enccrd->crd_skip); 1402 cry_cmd->reserved = 0; 1403 buf_pos += sizeof(struct hifn_crypt_command); 1404 } 1405 1406 if (using_mac && cmd->mac_masks & HIFN_MAC_CMD_NEW_KEY) { 1407 memcpy(buf_pos, cmd->mac, HIFN_MAC_KEY_LENGTH); 1408 buf_pos += HIFN_MAC_KEY_LENGTH; 1409 } 1410 1411 if (using_crypt && cmd->cry_masks & HIFN_CRYPT_CMD_NEW_KEY) { 1412 switch (cmd->cry_masks & HIFN_CRYPT_CMD_ALG_MASK) { 1413 case HIFN_CRYPT_CMD_ALG_3DES: 1414 memcpy(buf_pos, cmd->ck, HIFN_3DES_KEY_LENGTH); 1415 buf_pos += HIFN_3DES_KEY_LENGTH; 1416 break; 1417 case HIFN_CRYPT_CMD_ALG_DES: 1418 memcpy(buf_pos, cmd->ck, HIFN_DES_KEY_LENGTH); 1419 buf_pos += HIFN_DES_KEY_LENGTH; 1420 break; 1421 case HIFN_CRYPT_CMD_ALG_RC4: 1422 len = 256; 1423 do { 1424 int clen; 1425 1426 clen = MIN(cmd->cklen, len); 1427 memcpy(buf_pos, cmd->ck, clen); 1428 len -= clen; 1429 buf_pos += clen; 1430 } while (len > 0); 1431 memset(buf_pos, 0, 4); 1432 buf_pos += 4; 1433 break; 1434 case HIFN_CRYPT_CMD_ALG_AES: 1435 /* 1436 * AES keys are variable 128, 192 and 1437 * 256 bits (16, 24 and 32 bytes). 1438 */ 1439 memcpy(buf_pos, cmd->ck, cmd->cklen); 1440 buf_pos += cmd->cklen; 1441 break; 1442 } 1443 } 1444 1445 if (using_crypt && cmd->cry_masks & HIFN_CRYPT_CMD_NEW_IV) { 1446 switch (cmd->cry_masks & HIFN_CRYPT_CMD_ALG_MASK) { 1447 case HIFN_CRYPT_CMD_ALG_AES: 1448 ivlen = HIFN_AES_IV_LENGTH; 1449 break; 1450 default: 1451 ivlen = HIFN_IV_LENGTH; 1452 break; 1453 } 1454 memcpy(buf_pos, cmd->iv, ivlen); 1455 buf_pos += ivlen; 1456 } 1457 1458 if ((cmd->base_masks & (HIFN_BASE_CMD_MAC | HIFN_BASE_CMD_CRYPT | 1459 HIFN_BASE_CMD_COMP)) == 0) { 1460 memset(buf_pos, 0, 8); 1461 buf_pos += 8; 1462 } 1463 1464 return (buf_pos - buf); 1465 } 1466 1467 static int 1468 hifn_dmamap_aligned(bus_dmamap_t map) 1469 { 1470 int i; 1471 1472 for (i = 0; i < map->dm_nsegs; i++) { 1473 if (map->dm_segs[i].ds_addr & 3) 1474 return (0); 1475 if ((i != (map->dm_nsegs - 1)) && 1476 (map->dm_segs[i].ds_len & 3)) 1477 return (0); 1478 } 1479 return (1); 1480 } 1481 1482 static int 1483 hifn_dmamap_load_dst(struct hifn_softc *sc, struct hifn_command *cmd) 1484 { 1485 struct hifn_dma *dma = sc->sc_dma; 1486 bus_dmamap_t map = cmd->dst_map; 1487 u_int32_t p, l; 1488 int idx, used = 0, i; 1489 1490 idx = dma->dsti; 1491 for (i = 0; i < map->dm_nsegs - 1; i++) { 1492 dma->dstr[idx].p = htole32(map->dm_segs[i].ds_addr); 1493 dma->dstr[idx].l = htole32(HIFN_D_VALID | 1494 HIFN_D_MASKDONEIRQ | map->dm_segs[i].ds_len); 1495 HIFN_DSTR_SYNC(sc, idx, 1496 BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE); 1497 used++; 1498 1499 if (++idx == HIFN_D_DST_RSIZE) { 1500 dma->dstr[idx].l = htole32(HIFN_D_VALID | 1501 HIFN_D_JUMP | HIFN_D_MASKDONEIRQ); 1502 HIFN_DSTR_SYNC(sc, idx, 1503 BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE); 1504 idx = 0; 1505 } 1506 } 1507 1508 if (cmd->sloplen == 0) { 1509 p = map->dm_segs[i].ds_addr; 1510 l = HIFN_D_VALID | HIFN_D_MASKDONEIRQ | HIFN_D_LAST | 1511 map->dm_segs[i].ds_len; 1512 } else { 1513 p = sc->sc_dmamap->dm_segs[0].ds_addr + 1514 offsetof(struct hifn_dma, slop[cmd->slopidx]); 1515 l = HIFN_D_VALID | HIFN_D_MASKDONEIRQ | HIFN_D_LAST | 1516 sizeof(u_int32_t); 1517 1518 if ((map->dm_segs[i].ds_len - cmd->sloplen) != 0) { 1519 dma->dstr[idx].p = htole32(map->dm_segs[i].ds_addr); 1520 dma->dstr[idx].l = htole32(HIFN_D_VALID | 1521 HIFN_D_MASKDONEIRQ | 1522 (map->dm_segs[i].ds_len - cmd->sloplen)); 1523 HIFN_DSTR_SYNC(sc, idx, 1524 BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE); 1525 used++; 1526 1527 if (++idx == HIFN_D_DST_RSIZE) { 1528 dma->dstr[idx].l = htole32(HIFN_D_VALID | 1529 HIFN_D_JUMP | HIFN_D_MASKDONEIRQ); 1530 HIFN_DSTR_SYNC(sc, idx, 1531 BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE); 1532 idx = 0; 1533 } 1534 } 1535 } 1536 dma->dstr[idx].p = htole32(p); 1537 dma->dstr[idx].l = htole32(l); 1538 HIFN_DSTR_SYNC(sc, idx, BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE); 1539 used++; 1540 1541 if (++idx == HIFN_D_DST_RSIZE) { 1542 dma->dstr[idx].l = htole32(HIFN_D_VALID | HIFN_D_JUMP | 1543 HIFN_D_MASKDONEIRQ); 1544 HIFN_DSTR_SYNC(sc, idx, 1545 BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE); 1546 idx = 0; 1547 } 1548 1549 dma->dsti = idx; 1550 dma->dstu += used; 1551 return (idx); 1552 } 1553 1554 static int 1555 hifn_dmamap_load_src(struct hifn_softc *sc, struct hifn_command *cmd) 1556 { 1557 struct hifn_dma *dma = sc->sc_dma; 1558 bus_dmamap_t map = cmd->src_map; 1559 int idx, i; 1560 u_int32_t last = 0; 1561 1562 idx = dma->srci; 1563 for (i = 0; i < map->dm_nsegs; i++) { 1564 if (i == map->dm_nsegs - 1) 1565 last = HIFN_D_LAST; 1566 1567 dma->srcr[idx].p = htole32(map->dm_segs[i].ds_addr); 1568 dma->srcr[idx].l = htole32(map->dm_segs[i].ds_len | 1569 HIFN_D_VALID | HIFN_D_MASKDONEIRQ | last); 1570 HIFN_SRCR_SYNC(sc, idx, 1571 BUS_DMASYNC_PREWRITE | BUS_DMASYNC_PREREAD); 1572 1573 if (++idx == HIFN_D_SRC_RSIZE) { 1574 dma->srcr[idx].l = htole32(HIFN_D_VALID | 1575 HIFN_D_JUMP | HIFN_D_MASKDONEIRQ); 1576 HIFN_SRCR_SYNC(sc, HIFN_D_SRC_RSIZE, 1577 BUS_DMASYNC_PREWRITE | BUS_DMASYNC_PREREAD); 1578 idx = 0; 1579 } 1580 } 1581 dma->srci = idx; 1582 dma->srcu += map->dm_nsegs; 1583 return (idx); 1584 } 1585 1586 static int 1587 hifn_crypto(struct hifn_softc *sc, struct hifn_command *cmd, 1588 struct cryptop *crp, int hint) 1589 { 1590 struct hifn_dma *dma = sc->sc_dma; 1591 u_int32_t cmdlen; 1592 int cmdi, resi, s, err = 0; 1593 1594 if (bus_dmamap_create(sc->sc_dmat, HIFN_MAX_DMALEN, MAX_SCATTER, 1595 HIFN_MAX_SEGLEN, 0, BUS_DMA_NOWAIT, &cmd->src_map)) 1596 return (ENOMEM); 1597 1598 if (crp->crp_flags & CRYPTO_F_IMBUF) { 1599 if (bus_dmamap_load_mbuf(sc->sc_dmat, cmd->src_map, 1600 cmd->srcu.src_m, BUS_DMA_NOWAIT)) { 1601 err = ENOMEM; 1602 goto err_srcmap1; 1603 } 1604 } else if (crp->crp_flags & CRYPTO_F_IOV) { 1605 if (bus_dmamap_load_uio(sc->sc_dmat, cmd->src_map, 1606 cmd->srcu.src_io, BUS_DMA_NOWAIT)) { 1607 err = ENOMEM; 1608 goto err_srcmap1; 1609 } 1610 } else { 1611 err = EINVAL; 1612 goto err_srcmap1; 1613 } 1614 1615 if (hifn_dmamap_aligned(cmd->src_map)) { 1616 cmd->sloplen = cmd->src_map->dm_mapsize & 3; 1617 if (crp->crp_flags & CRYPTO_F_IOV) 1618 cmd->dstu.dst_io = cmd->srcu.src_io; 1619 else if (crp->crp_flags & CRYPTO_F_IMBUF) 1620 cmd->dstu.dst_m = cmd->srcu.src_m; 1621 cmd->dst_map = cmd->src_map; 1622 } else { 1623 if (crp->crp_flags & CRYPTO_F_IOV) { 1624 err = EINVAL; 1625 goto err_srcmap; 1626 } else if (crp->crp_flags & CRYPTO_F_IMBUF) { 1627 int totlen, len; 1628 struct mbuf *m, *m0, *mlast; 1629 1630 totlen = cmd->src_map->dm_mapsize; 1631 if (cmd->srcu.src_m->m_flags & M_PKTHDR) { 1632 len = MHLEN; 1633 MGETHDR(m0, M_DONTWAIT, MT_DATA); 1634 } else { 1635 len = MLEN; 1636 MGET(m0, M_DONTWAIT, MT_DATA); 1637 } 1638 if (m0 == NULL) { 1639 err = ENOMEM; 1640 goto err_srcmap; 1641 } 1642 if (len == MHLEN) 1643 M_DUP_PKTHDR(m0, cmd->srcu.src_m); 1644 if (totlen >= MINCLSIZE) { 1645 MCLGET(m0, M_DONTWAIT); 1646 if (m0->m_flags & M_EXT) 1647 len = MCLBYTES; 1648 } 1649 totlen -= len; 1650 m0->m_pkthdr.len = m0->m_len = len; 1651 mlast = m0; 1652 1653 while (totlen > 0) { 1654 MGET(m, M_DONTWAIT, MT_DATA); 1655 if (m == NULL) { 1656 err = ENOMEM; 1657 m_freem(m0); 1658 goto err_srcmap; 1659 } 1660 len = MLEN; 1661 if (totlen >= MINCLSIZE) { 1662 MCLGET(m, M_DONTWAIT); 1663 if (m->m_flags & M_EXT) 1664 len = MCLBYTES; 1665 } 1666 1667 m->m_len = len; 1668 if (m0->m_flags & M_PKTHDR) 1669 m0->m_pkthdr.len += len; 1670 totlen -= len; 1671 1672 mlast->m_next = m; 1673 mlast = m; 1674 } 1675 cmd->dstu.dst_m = m0; 1676 } 1677 } 1678 1679 if (cmd->dst_map == NULL) { 1680 if (bus_dmamap_create(sc->sc_dmat, 1681 HIFN_MAX_SEGLEN * MAX_SCATTER, MAX_SCATTER, 1682 HIFN_MAX_SEGLEN, 0, BUS_DMA_NOWAIT, &cmd->dst_map)) { 1683 err = ENOMEM; 1684 goto err_srcmap; 1685 } 1686 if (crp->crp_flags & CRYPTO_F_IMBUF) { 1687 if (bus_dmamap_load_mbuf(sc->sc_dmat, cmd->dst_map, 1688 cmd->dstu.dst_m, BUS_DMA_NOWAIT)) { 1689 err = ENOMEM; 1690 goto err_dstmap1; 1691 } 1692 } else if (crp->crp_flags & CRYPTO_F_IOV) { 1693 if (bus_dmamap_load_uio(sc->sc_dmat, cmd->dst_map, 1694 cmd->dstu.dst_io, BUS_DMA_NOWAIT)) { 1695 err = ENOMEM; 1696 goto err_dstmap1; 1697 } 1698 } 1699 } 1700 1701 #ifdef HIFN_DEBUG 1702 if (hifn_debug) 1703 printf("%s: Entering cmd: stat %8x ien %8x u %d/%d/%d/%d n %d/%d\n", 1704 device_xname(&sc->sc_dv), 1705 READ_REG_1(sc, HIFN_1_DMA_CSR), 1706 READ_REG_1(sc, HIFN_1_DMA_IER), 1707 dma->cmdu, dma->srcu, dma->dstu, dma->resu, 1708 cmd->src_map->dm_nsegs, cmd->dst_map->dm_nsegs); 1709 #endif 1710 1711 if (cmd->src_map == cmd->dst_map) 1712 bus_dmamap_sync(sc->sc_dmat, cmd->src_map, 1713 0, cmd->src_map->dm_mapsize, 1714 BUS_DMASYNC_PREWRITE|BUS_DMASYNC_PREREAD); 1715 else { 1716 bus_dmamap_sync(sc->sc_dmat, cmd->src_map, 1717 0, cmd->src_map->dm_mapsize, BUS_DMASYNC_PREWRITE); 1718 bus_dmamap_sync(sc->sc_dmat, cmd->dst_map, 1719 0, cmd->dst_map->dm_mapsize, BUS_DMASYNC_PREREAD); 1720 } 1721 1722 s = splnet(); 1723 1724 /* 1725 * need 1 cmd, and 1 res 1726 * need N src, and N dst 1727 */ 1728 if ((dma->cmdu + 1) > HIFN_D_CMD_RSIZE || 1729 (dma->resu + 1) > HIFN_D_RES_RSIZE) { 1730 splx(s); 1731 err = ENOMEM; 1732 goto err_dstmap; 1733 } 1734 if ((dma->srcu + cmd->src_map->dm_nsegs) > HIFN_D_SRC_RSIZE || 1735 (dma->dstu + cmd->dst_map->dm_nsegs + 1) > HIFN_D_DST_RSIZE) { 1736 splx(s); 1737 err = ENOMEM; 1738 goto err_dstmap; 1739 } 1740 1741 if (dma->cmdi == HIFN_D_CMD_RSIZE) { 1742 dma->cmdi = 0; 1743 dma->cmdr[HIFN_D_CMD_RSIZE].l = htole32(HIFN_D_VALID | 1744 HIFN_D_JUMP | HIFN_D_MASKDONEIRQ); 1745 HIFN_CMDR_SYNC(sc, HIFN_D_CMD_RSIZE, 1746 BUS_DMASYNC_PREWRITE | BUS_DMASYNC_PREREAD); 1747 } 1748 cmdi = dma->cmdi++; 1749 cmdlen = hifn_write_command(cmd, dma->command_bufs[cmdi]); 1750 HIFN_CMD_SYNC(sc, cmdi, BUS_DMASYNC_PREWRITE); 1751 1752 /* .p for command/result already set */ 1753 dma->cmdr[cmdi].l = htole32(cmdlen | HIFN_D_VALID | HIFN_D_LAST | 1754 HIFN_D_MASKDONEIRQ); 1755 HIFN_CMDR_SYNC(sc, cmdi, 1756 BUS_DMASYNC_PREWRITE | BUS_DMASYNC_PREREAD); 1757 dma->cmdu++; 1758 if (sc->sc_c_busy == 0) { 1759 WRITE_REG_1(sc, HIFN_1_DMA_CSR, HIFN_DMACSR_C_CTRL_ENA); 1760 sc->sc_c_busy = 1; 1761 SET_LED(sc, HIFN_MIPSRST_LED0); 1762 } 1763 1764 /* 1765 * We don't worry about missing an interrupt (which a "command wait" 1766 * interrupt salvages us from), unless there is more than one command 1767 * in the queue. 1768 * 1769 * XXX We do seem to miss some interrupts. So we always enable 1770 * XXX command wait. From OpenBSD revision 1.149. 1771 * 1772 */ 1773 #if 0 1774 if (dma->cmdu > 1) { 1775 #endif 1776 sc->sc_dmaier |= HIFN_DMAIER_C_WAIT; 1777 WRITE_REG_1(sc, HIFN_1_DMA_IER, sc->sc_dmaier); 1778 #if 0 1779 } 1780 #endif 1781 1782 hifnstats.hst_ipackets++; 1783 hifnstats.hst_ibytes += cmd->src_map->dm_mapsize; 1784 1785 hifn_dmamap_load_src(sc, cmd); 1786 if (sc->sc_s_busy == 0) { 1787 WRITE_REG_1(sc, HIFN_1_DMA_CSR, HIFN_DMACSR_S_CTRL_ENA); 1788 sc->sc_s_busy = 1; 1789 SET_LED(sc, HIFN_MIPSRST_LED1); 1790 } 1791 1792 /* 1793 * Unlike other descriptors, we don't mask done interrupt from 1794 * result descriptor. 1795 */ 1796 #ifdef HIFN_DEBUG 1797 if (hifn_debug) 1798 printf("load res\n"); 1799 #endif 1800 if (dma->resi == HIFN_D_RES_RSIZE) { 1801 dma->resi = 0; 1802 dma->resr[HIFN_D_RES_RSIZE].l = htole32(HIFN_D_VALID | 1803 HIFN_D_JUMP | HIFN_D_MASKDONEIRQ); 1804 HIFN_RESR_SYNC(sc, HIFN_D_RES_RSIZE, 1805 BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE); 1806 } 1807 resi = dma->resi++; 1808 dma->hifn_commands[resi] = cmd; 1809 HIFN_RES_SYNC(sc, resi, BUS_DMASYNC_PREREAD); 1810 dma->resr[resi].l = htole32(HIFN_MAX_RESULT | 1811 HIFN_D_VALID | HIFN_D_LAST); 1812 HIFN_RESR_SYNC(sc, resi, 1813 BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE); 1814 dma->resu++; 1815 if (sc->sc_r_busy == 0) { 1816 WRITE_REG_1(sc, HIFN_1_DMA_CSR, HIFN_DMACSR_R_CTRL_ENA); 1817 sc->sc_r_busy = 1; 1818 SET_LED(sc, HIFN_MIPSRST_LED2); 1819 } 1820 1821 if (cmd->sloplen) 1822 cmd->slopidx = resi; 1823 1824 hifn_dmamap_load_dst(sc, cmd); 1825 1826 if (sc->sc_d_busy == 0) { 1827 WRITE_REG_1(sc, HIFN_1_DMA_CSR, HIFN_DMACSR_D_CTRL_ENA); 1828 sc->sc_d_busy = 1; 1829 } 1830 1831 #ifdef HIFN_DEBUG 1832 if (hifn_debug) 1833 printf("%s: command: stat %8x ier %8x\n", 1834 device_xname(&sc->sc_dv), 1835 READ_REG_1(sc, HIFN_1_DMA_CSR), READ_REG_1(sc, HIFN_1_DMA_IER)); 1836 #endif 1837 1838 sc->sc_active = 5; 1839 splx(s); 1840 return (err); /* success */ 1841 1842 err_dstmap: 1843 if (cmd->src_map != cmd->dst_map) 1844 bus_dmamap_unload(sc->sc_dmat, cmd->dst_map); 1845 err_dstmap1: 1846 if (cmd->src_map != cmd->dst_map) 1847 bus_dmamap_destroy(sc->sc_dmat, cmd->dst_map); 1848 err_srcmap: 1849 if (crp->crp_flags & CRYPTO_F_IMBUF && 1850 cmd->srcu.src_m != cmd->dstu.dst_m) 1851 m_freem(cmd->dstu.dst_m); 1852 bus_dmamap_unload(sc->sc_dmat, cmd->src_map); 1853 err_srcmap1: 1854 bus_dmamap_destroy(sc->sc_dmat, cmd->src_map); 1855 return (err); 1856 } 1857 1858 static void 1859 hifn_tick(void *vsc) 1860 { 1861 struct hifn_softc *sc = vsc; 1862 int s; 1863 1864 s = splnet(); 1865 if (sc->sc_active == 0) { 1866 struct hifn_dma *dma = sc->sc_dma; 1867 u_int32_t r = 0; 1868 1869 if (dma->cmdu == 0 && sc->sc_c_busy) { 1870 sc->sc_c_busy = 0; 1871 r |= HIFN_DMACSR_C_CTRL_DIS; 1872 CLR_LED(sc, HIFN_MIPSRST_LED0); 1873 } 1874 if (dma->srcu == 0 && sc->sc_s_busy) { 1875 sc->sc_s_busy = 0; 1876 r |= HIFN_DMACSR_S_CTRL_DIS; 1877 CLR_LED(sc, HIFN_MIPSRST_LED1); 1878 } 1879 if (dma->dstu == 0 && sc->sc_d_busy) { 1880 sc->sc_d_busy = 0; 1881 r |= HIFN_DMACSR_D_CTRL_DIS; 1882 } 1883 if (dma->resu == 0 && sc->sc_r_busy) { 1884 sc->sc_r_busy = 0; 1885 r |= HIFN_DMACSR_R_CTRL_DIS; 1886 CLR_LED(sc, HIFN_MIPSRST_LED2); 1887 } 1888 if (r) 1889 WRITE_REG_1(sc, HIFN_1_DMA_CSR, r); 1890 } 1891 else 1892 sc->sc_active--; 1893 splx(s); 1894 #ifdef __OpenBSD__ 1895 timeout_add(&sc->sc_tickto, hz); 1896 #else 1897 callout_reset(&sc->sc_tickto, hz, hifn_tick, sc); 1898 #endif 1899 } 1900 1901 static int 1902 hifn_intr(void *arg) 1903 { 1904 struct hifn_softc *sc = arg; 1905 struct hifn_dma *dma = sc->sc_dma; 1906 u_int32_t dmacsr, restart; 1907 int i, u; 1908 1909 dmacsr = READ_REG_1(sc, HIFN_1_DMA_CSR); 1910 1911 #ifdef HIFN_DEBUG 1912 if (hifn_debug) 1913 printf("%s: irq: stat %08x ien %08x u %d/%d/%d/%d\n", 1914 device_xname(&sc->sc_dv), 1915 dmacsr, READ_REG_1(sc, HIFN_1_DMA_IER), 1916 dma->cmdu, dma->srcu, dma->dstu, dma->resu); 1917 #endif 1918 1919 /* Nothing in the DMA unit interrupted */ 1920 if ((dmacsr & sc->sc_dmaier) == 0) 1921 return (0); 1922 1923 WRITE_REG_1(sc, HIFN_1_DMA_CSR, dmacsr & sc->sc_dmaier); 1924 1925 if (dmacsr & HIFN_DMACSR_ENGINE) 1926 WRITE_REG_0(sc, HIFN_0_PUISR, READ_REG_0(sc, HIFN_0_PUISR)); 1927 1928 if ((sc->sc_flags & HIFN_HAS_PUBLIC) && 1929 (dmacsr & HIFN_DMACSR_PUBDONE)) 1930 WRITE_REG_1(sc, HIFN_1_PUB_STATUS, 1931 READ_REG_1(sc, HIFN_1_PUB_STATUS) | HIFN_PUBSTS_DONE); 1932 1933 restart = dmacsr & (HIFN_DMACSR_R_OVER | HIFN_DMACSR_D_OVER); 1934 if (restart) 1935 printf("%s: overrun %x\n", device_xname(&sc->sc_dv), dmacsr); 1936 1937 if (sc->sc_flags & HIFN_IS_7811) { 1938 if (dmacsr & HIFN_DMACSR_ILLR) 1939 printf("%s: illegal read\n", device_xname(&sc->sc_dv)); 1940 if (dmacsr & HIFN_DMACSR_ILLW) 1941 printf("%s: illegal write\n", device_xname(&sc->sc_dv)); 1942 } 1943 1944 restart = dmacsr & (HIFN_DMACSR_C_ABORT | HIFN_DMACSR_S_ABORT | 1945 HIFN_DMACSR_D_ABORT | HIFN_DMACSR_R_ABORT); 1946 if (restart) { 1947 printf("%s: abort, resetting.\n", device_xname(&sc->sc_dv)); 1948 hifnstats.hst_abort++; 1949 hifn_abort(sc); 1950 return (1); 1951 } 1952 1953 if ((dmacsr & HIFN_DMACSR_C_WAIT) && (dma->resu == 0)) { 1954 /* 1955 * If no slots to process and we receive a "waiting on 1956 * command" interrupt, we disable the "waiting on command" 1957 * (by clearing it). 1958 */ 1959 sc->sc_dmaier &= ~HIFN_DMAIER_C_WAIT; 1960 WRITE_REG_1(sc, HIFN_1_DMA_IER, sc->sc_dmaier); 1961 } 1962 1963 /* clear the rings */ 1964 i = dma->resk; 1965 while (dma->resu != 0) { 1966 HIFN_RESR_SYNC(sc, i, 1967 BUS_DMASYNC_POSTREAD | BUS_DMASYNC_POSTWRITE); 1968 if (dma->resr[i].l & htole32(HIFN_D_VALID)) { 1969 HIFN_RESR_SYNC(sc, i, 1970 BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE); 1971 break; 1972 } 1973 1974 if (i != HIFN_D_RES_RSIZE) { 1975 struct hifn_command *cmd; 1976 1977 HIFN_RES_SYNC(sc, i, BUS_DMASYNC_POSTREAD); 1978 cmd = dma->hifn_commands[i]; 1979 KASSERT(cmd != NULL 1980 /*("hifn_intr: null command slot %u", i)*/); 1981 dma->hifn_commands[i] = NULL; 1982 1983 hifn_callback(sc, cmd, dma->result_bufs[i]); 1984 hifnstats.hst_opackets++; 1985 } 1986 1987 if (++i == (HIFN_D_RES_RSIZE + 1)) 1988 i = 0; 1989 else 1990 dma->resu--; 1991 } 1992 dma->resk = i; 1993 1994 i = dma->srck; u = dma->srcu; 1995 while (u != 0) { 1996 HIFN_SRCR_SYNC(sc, i, 1997 BUS_DMASYNC_POSTREAD | BUS_DMASYNC_POSTWRITE); 1998 if (dma->srcr[i].l & htole32(HIFN_D_VALID)) { 1999 HIFN_SRCR_SYNC(sc, i, 2000 BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE); 2001 break; 2002 } 2003 if (++i == (HIFN_D_SRC_RSIZE + 1)) 2004 i = 0; 2005 else 2006 u--; 2007 } 2008 dma->srck = i; dma->srcu = u; 2009 2010 i = dma->cmdk; u = dma->cmdu; 2011 while (u != 0) { 2012 HIFN_CMDR_SYNC(sc, i, 2013 BUS_DMASYNC_POSTREAD | BUS_DMASYNC_POSTWRITE); 2014 if (dma->cmdr[i].l & htole32(HIFN_D_VALID)) { 2015 HIFN_CMDR_SYNC(sc, i, 2016 BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE); 2017 break; 2018 } 2019 if (i != HIFN_D_CMD_RSIZE) { 2020 u--; 2021 HIFN_CMD_SYNC(sc, i, BUS_DMASYNC_POSTWRITE); 2022 } 2023 if (++i == (HIFN_D_CMD_RSIZE + 1)) 2024 i = 0; 2025 } 2026 dma->cmdk = i; dma->cmdu = u; 2027 2028 return (1); 2029 } 2030 2031 /* 2032 * Allocate a new 'session' and return an encoded session id. 'sidp' 2033 * contains our registration id, and should contain an encoded session 2034 * id on successful allocation. 2035 */ 2036 static int 2037 hifn_newsession(void *arg, u_int32_t *sidp, struct cryptoini *cri) 2038 { 2039 struct cryptoini *c; 2040 struct hifn_softc *sc = arg; 2041 int i, mac = 0, cry = 0, comp = 0; 2042 2043 KASSERT(sc != NULL /*, ("hifn_newsession: null softc")*/); 2044 if (sidp == NULL || cri == NULL || sc == NULL) 2045 return (EINVAL); 2046 2047 for (i = 0; i < sc->sc_maxses; i++) 2048 if (sc->sc_sessions[i].hs_state == HS_STATE_FREE) 2049 break; 2050 if (i == sc->sc_maxses) 2051 return (ENOMEM); 2052 2053 for (c = cri; c != NULL; c = c->cri_next) { 2054 switch (c->cri_alg) { 2055 case CRYPTO_MD5: 2056 case CRYPTO_SHA1: 2057 case CRYPTO_MD5_HMAC_96: 2058 case CRYPTO_SHA1_HMAC_96: 2059 if (mac) 2060 return (EINVAL); 2061 mac = 1; 2062 break; 2063 case CRYPTO_DES_CBC: 2064 case CRYPTO_3DES_CBC: 2065 case CRYPTO_AES_CBC: 2066 /* Note that this is an initialization 2067 vector, not a cipher key; any function 2068 giving sufficient Hamming distance 2069 between outputs is fine. Use of RC4 2070 to generate IVs has been FIPS140-2 2071 certified by several labs. */ 2072 #ifdef __NetBSD__ 2073 cprng_fast(sc->sc_sessions[i].hs_iv, 2074 c->cri_alg == CRYPTO_AES_CBC ? 2075 HIFN_AES_IV_LENGTH : HIFN_IV_LENGTH); 2076 #else /* FreeBSD and OpenBSD have get_random_bytes */ 2077 /* XXX this may read fewer, does it matter? */ 2078 get_random_bytes(sc->sc_sessions[i].hs_iv, 2079 c->cri_alg == CRYPTO_AES_CBC ? 2080 HIFN_AES_IV_LENGTH : HIFN_IV_LENGTH); 2081 #endif 2082 /*FALLTHROUGH*/ 2083 case CRYPTO_ARC4: 2084 if (cry) 2085 return (EINVAL); 2086 cry = 1; 2087 break; 2088 #ifdef HAVE_CRYPTO_LZS 2089 case CRYPTO_LZS_COMP: 2090 if (comp) 2091 return (EINVAL); 2092 comp = 1; 2093 break; 2094 #endif 2095 default: 2096 return (EINVAL); 2097 } 2098 } 2099 if (mac == 0 && cry == 0 && comp == 0) 2100 return (EINVAL); 2101 2102 /* 2103 * XXX only want to support compression without chaining to 2104 * MAC/crypt engine right now 2105 */ 2106 if ((comp && mac) || (comp && cry)) 2107 return (EINVAL); 2108 2109 *sidp = HIFN_SID(device_unit(&sc->sc_dv), i); 2110 sc->sc_sessions[i].hs_state = HS_STATE_USED; 2111 2112 return (0); 2113 } 2114 2115 /* 2116 * Deallocate a session. 2117 * XXX this routine should run a zero'd mac/encrypt key into context ram. 2118 * XXX to blow away any keys already stored there. 2119 */ 2120 static int 2121 hifn_freesession(void *arg, u_int64_t tid) 2122 { 2123 struct hifn_softc *sc = arg; 2124 int session; 2125 u_int32_t sid = ((u_int32_t) tid) & 0xffffffff; 2126 2127 KASSERT(sc != NULL /*, ("hifn_freesession: null softc")*/); 2128 if (sc == NULL) 2129 return (EINVAL); 2130 2131 session = HIFN_SESSION(sid); 2132 if (session >= sc->sc_maxses) 2133 return (EINVAL); 2134 2135 memset(&sc->sc_sessions[session], 0, sizeof(sc->sc_sessions[session])); 2136 return (0); 2137 } 2138 2139 static int 2140 hifn_process(void *arg, struct cryptop *crp, int hint) 2141 { 2142 struct hifn_softc *sc = arg; 2143 struct hifn_command *cmd = NULL; 2144 int session, err, ivlen; 2145 struct cryptodesc *crd1, *crd2, *maccrd, *enccrd; 2146 2147 if (crp == NULL || crp->crp_callback == NULL) { 2148 hifnstats.hst_invalid++; 2149 return (EINVAL); 2150 } 2151 session = HIFN_SESSION(crp->crp_sid); 2152 2153 if (sc == NULL || session >= sc->sc_maxses) { 2154 err = EINVAL; 2155 goto errout; 2156 } 2157 2158 cmd = (struct hifn_command *)malloc(sizeof(struct hifn_command), 2159 M_DEVBUF, M_NOWAIT|M_ZERO); 2160 if (cmd == NULL) { 2161 hifnstats.hst_nomem++; 2162 err = ENOMEM; 2163 goto errout; 2164 } 2165 2166 if (crp->crp_flags & CRYPTO_F_IMBUF) { 2167 cmd->srcu.src_m = (struct mbuf *)crp->crp_buf; 2168 cmd->dstu.dst_m = (struct mbuf *)crp->crp_buf; 2169 } else if (crp->crp_flags & CRYPTO_F_IOV) { 2170 cmd->srcu.src_io = (struct uio *)crp->crp_buf; 2171 cmd->dstu.dst_io = (struct uio *)crp->crp_buf; 2172 } else { 2173 err = EINVAL; 2174 goto errout; /* XXX we don't handle contiguous buffers! */ 2175 } 2176 2177 crd1 = crp->crp_desc; 2178 if (crd1 == NULL) { 2179 err = EINVAL; 2180 goto errout; 2181 } 2182 crd2 = crd1->crd_next; 2183 2184 if (crd2 == NULL) { 2185 if (crd1->crd_alg == CRYPTO_MD5_HMAC_96 || 2186 crd1->crd_alg == CRYPTO_SHA1_HMAC_96 || 2187 crd1->crd_alg == CRYPTO_SHA1 || 2188 crd1->crd_alg == CRYPTO_MD5) { 2189 maccrd = crd1; 2190 enccrd = NULL; 2191 } else if (crd1->crd_alg == CRYPTO_DES_CBC || 2192 crd1->crd_alg == CRYPTO_3DES_CBC || 2193 crd1->crd_alg == CRYPTO_AES_CBC || 2194 crd1->crd_alg == CRYPTO_ARC4) { 2195 if ((crd1->crd_flags & CRD_F_ENCRYPT) == 0) 2196 cmd->base_masks |= HIFN_BASE_CMD_DECODE; 2197 maccrd = NULL; 2198 enccrd = crd1; 2199 #ifdef HAVE_CRYPTO_LZS 2200 } else if (crd1->crd_alg == CRYPTO_LZS_COMP) { 2201 return (hifn_compression(sc, crp, cmd)); 2202 #endif 2203 } else { 2204 err = EINVAL; 2205 goto errout; 2206 } 2207 } else { 2208 if ((crd1->crd_alg == CRYPTO_MD5_HMAC_96 || 2209 crd1->crd_alg == CRYPTO_SHA1_HMAC_96 || 2210 crd1->crd_alg == CRYPTO_MD5 || 2211 crd1->crd_alg == CRYPTO_SHA1) && 2212 (crd2->crd_alg == CRYPTO_DES_CBC || 2213 crd2->crd_alg == CRYPTO_3DES_CBC || 2214 crd2->crd_alg == CRYPTO_AES_CBC || 2215 crd2->crd_alg == CRYPTO_ARC4) && 2216 ((crd2->crd_flags & CRD_F_ENCRYPT) == 0)) { 2217 cmd->base_masks = HIFN_BASE_CMD_DECODE; 2218 maccrd = crd1; 2219 enccrd = crd2; 2220 } else if ((crd1->crd_alg == CRYPTO_DES_CBC || 2221 crd1->crd_alg == CRYPTO_ARC4 || 2222 crd1->crd_alg == CRYPTO_3DES_CBC || 2223 crd1->crd_alg == CRYPTO_AES_CBC) && 2224 (crd2->crd_alg == CRYPTO_MD5_HMAC_96 || 2225 crd2->crd_alg == CRYPTO_SHA1_HMAC_96 || 2226 crd2->crd_alg == CRYPTO_MD5 || 2227 crd2->crd_alg == CRYPTO_SHA1) && 2228 (crd1->crd_flags & CRD_F_ENCRYPT)) { 2229 enccrd = crd1; 2230 maccrd = crd2; 2231 } else { 2232 /* 2233 * We cannot order the 7751 as requested 2234 */ 2235 err = EINVAL; 2236 goto errout; 2237 } 2238 } 2239 2240 if (enccrd) { 2241 cmd->enccrd = enccrd; 2242 cmd->base_masks |= HIFN_BASE_CMD_CRYPT; 2243 switch (enccrd->crd_alg) { 2244 case CRYPTO_ARC4: 2245 cmd->cry_masks |= HIFN_CRYPT_CMD_ALG_RC4; 2246 if ((enccrd->crd_flags & CRD_F_ENCRYPT) 2247 != sc->sc_sessions[session].hs_prev_op) 2248 sc->sc_sessions[session].hs_state = 2249 HS_STATE_USED; 2250 break; 2251 case CRYPTO_DES_CBC: 2252 cmd->cry_masks |= HIFN_CRYPT_CMD_ALG_DES | 2253 HIFN_CRYPT_CMD_MODE_CBC | 2254 HIFN_CRYPT_CMD_NEW_IV; 2255 break; 2256 case CRYPTO_3DES_CBC: 2257 cmd->cry_masks |= HIFN_CRYPT_CMD_ALG_3DES | 2258 HIFN_CRYPT_CMD_MODE_CBC | 2259 HIFN_CRYPT_CMD_NEW_IV; 2260 break; 2261 case CRYPTO_AES_CBC: 2262 cmd->cry_masks |= HIFN_CRYPT_CMD_ALG_AES | 2263 HIFN_CRYPT_CMD_MODE_CBC | 2264 HIFN_CRYPT_CMD_NEW_IV; 2265 break; 2266 default: 2267 err = EINVAL; 2268 goto errout; 2269 } 2270 if (enccrd->crd_alg != CRYPTO_ARC4) { 2271 ivlen = ((enccrd->crd_alg == CRYPTO_AES_CBC) ? 2272 HIFN_AES_IV_LENGTH : HIFN_IV_LENGTH); 2273 if (enccrd->crd_flags & CRD_F_ENCRYPT) { 2274 if (enccrd->crd_flags & CRD_F_IV_EXPLICIT) 2275 memcpy(cmd->iv, enccrd->crd_iv, ivlen); 2276 else 2277 bcopy(sc->sc_sessions[session].hs_iv, 2278 cmd->iv, ivlen); 2279 2280 if ((enccrd->crd_flags & CRD_F_IV_PRESENT) 2281 == 0) { 2282 if (crp->crp_flags & CRYPTO_F_IMBUF) 2283 m_copyback(cmd->srcu.src_m, 2284 enccrd->crd_inject, 2285 ivlen, cmd->iv); 2286 else if (crp->crp_flags & CRYPTO_F_IOV) 2287 cuio_copyback(cmd->srcu.src_io, 2288 enccrd->crd_inject, 2289 ivlen, cmd->iv); 2290 } 2291 } else { 2292 if (enccrd->crd_flags & CRD_F_IV_EXPLICIT) 2293 memcpy(cmd->iv, enccrd->crd_iv, ivlen); 2294 else if (crp->crp_flags & CRYPTO_F_IMBUF) 2295 m_copydata(cmd->srcu.src_m, 2296 enccrd->crd_inject, ivlen, cmd->iv); 2297 else if (crp->crp_flags & CRYPTO_F_IOV) 2298 cuio_copydata(cmd->srcu.src_io, 2299 enccrd->crd_inject, ivlen, cmd->iv); 2300 } 2301 } 2302 2303 cmd->ck = enccrd->crd_key; 2304 cmd->cklen = enccrd->crd_klen >> 3; 2305 2306 /* 2307 * Need to specify the size for the AES key in the masks. 2308 */ 2309 if ((cmd->cry_masks & HIFN_CRYPT_CMD_ALG_MASK) == 2310 HIFN_CRYPT_CMD_ALG_AES) { 2311 switch (cmd->cklen) { 2312 case 16: 2313 cmd->cry_masks |= HIFN_CRYPT_CMD_KSZ_128; 2314 break; 2315 case 24: 2316 cmd->cry_masks |= HIFN_CRYPT_CMD_KSZ_192; 2317 break; 2318 case 32: 2319 cmd->cry_masks |= HIFN_CRYPT_CMD_KSZ_256; 2320 break; 2321 default: 2322 err = EINVAL; 2323 goto errout; 2324 } 2325 } 2326 2327 if (sc->sc_sessions[session].hs_state == HS_STATE_USED) 2328 cmd->cry_masks |= HIFN_CRYPT_CMD_NEW_KEY; 2329 } 2330 2331 if (maccrd) { 2332 cmd->maccrd = maccrd; 2333 cmd->base_masks |= HIFN_BASE_CMD_MAC; 2334 2335 switch (maccrd->crd_alg) { 2336 case CRYPTO_MD5: 2337 cmd->mac_masks |= HIFN_MAC_CMD_ALG_MD5 | 2338 HIFN_MAC_CMD_RESULT | HIFN_MAC_CMD_MODE_HASH | 2339 HIFN_MAC_CMD_POS_IPSEC; 2340 break; 2341 case CRYPTO_MD5_HMAC_96: 2342 cmd->mac_masks |= HIFN_MAC_CMD_ALG_MD5 | 2343 HIFN_MAC_CMD_RESULT | HIFN_MAC_CMD_MODE_HMAC | 2344 HIFN_MAC_CMD_POS_IPSEC | HIFN_MAC_CMD_TRUNC; 2345 break; 2346 case CRYPTO_SHA1: 2347 cmd->mac_masks |= HIFN_MAC_CMD_ALG_SHA1 | 2348 HIFN_MAC_CMD_RESULT | HIFN_MAC_CMD_MODE_HASH | 2349 HIFN_MAC_CMD_POS_IPSEC; 2350 break; 2351 case CRYPTO_SHA1_HMAC_96: 2352 cmd->mac_masks |= HIFN_MAC_CMD_ALG_SHA1 | 2353 HIFN_MAC_CMD_RESULT | HIFN_MAC_CMD_MODE_HMAC | 2354 HIFN_MAC_CMD_POS_IPSEC | HIFN_MAC_CMD_TRUNC; 2355 break; 2356 } 2357 2358 if ((maccrd->crd_alg == CRYPTO_SHA1_HMAC_96 || 2359 maccrd->crd_alg == CRYPTO_MD5_HMAC_96) && 2360 sc->sc_sessions[session].hs_state == HS_STATE_USED) { 2361 cmd->mac_masks |= HIFN_MAC_CMD_NEW_KEY; 2362 memcpy(cmd->mac, maccrd->crd_key, maccrd->crd_klen >> 3); 2363 memset(cmd->mac + (maccrd->crd_klen >> 3), 0, 2364 HIFN_MAC_KEY_LENGTH - (maccrd->crd_klen >> 3)); 2365 } 2366 } 2367 2368 cmd->crp = crp; 2369 cmd->session_num = session; 2370 cmd->softc = sc; 2371 2372 err = hifn_crypto(sc, cmd, crp, hint); 2373 if (err == 0) { 2374 if (enccrd) 2375 sc->sc_sessions[session].hs_prev_op = 2376 enccrd->crd_flags & CRD_F_ENCRYPT; 2377 if (sc->sc_sessions[session].hs_state == HS_STATE_USED) 2378 sc->sc_sessions[session].hs_state = HS_STATE_KEY; 2379 return 0; 2380 } else if (err == ERESTART) { 2381 /* 2382 * There weren't enough resources to dispatch the request 2383 * to the part. Notify the caller so they'll requeue this 2384 * request and resubmit it again soon. 2385 */ 2386 #ifdef HIFN_DEBUG 2387 if (hifn_debug) 2388 printf("%s: requeue request\n", device_xname(&sc->sc_dv)); 2389 #endif 2390 free(cmd, M_DEVBUF); 2391 sc->sc_needwakeup |= CRYPTO_SYMQ; 2392 return (err); 2393 } 2394 2395 errout: 2396 if (cmd != NULL) 2397 free(cmd, M_DEVBUF); 2398 if (err == EINVAL) 2399 hifnstats.hst_invalid++; 2400 else 2401 hifnstats.hst_nomem++; 2402 crp->crp_etype = err; 2403 crypto_done(crp); 2404 return (0); 2405 } 2406 2407 static void 2408 hifn_abort(struct hifn_softc *sc) 2409 { 2410 struct hifn_dma *dma = sc->sc_dma; 2411 struct hifn_command *cmd; 2412 struct cryptop *crp; 2413 int i, u; 2414 2415 i = dma->resk; u = dma->resu; 2416 while (u != 0) { 2417 cmd = dma->hifn_commands[i]; 2418 KASSERT(cmd != NULL /*, ("hifn_abort: null cmd slot %u", i)*/); 2419 dma->hifn_commands[i] = NULL; 2420 crp = cmd->crp; 2421 2422 if ((dma->resr[i].l & htole32(HIFN_D_VALID)) == 0) { 2423 /* Salvage what we can. */ 2424 hifnstats.hst_opackets++; 2425 hifn_callback(sc, cmd, dma->result_bufs[i]); 2426 } else { 2427 if (cmd->src_map == cmd->dst_map) { 2428 bus_dmamap_sync(sc->sc_dmat, cmd->src_map, 2429 0, cmd->src_map->dm_mapsize, 2430 BUS_DMASYNC_POSTREAD|BUS_DMASYNC_POSTWRITE); 2431 } else { 2432 bus_dmamap_sync(sc->sc_dmat, cmd->src_map, 2433 0, cmd->src_map->dm_mapsize, 2434 BUS_DMASYNC_POSTWRITE); 2435 bus_dmamap_sync(sc->sc_dmat, cmd->dst_map, 2436 0, cmd->dst_map->dm_mapsize, 2437 BUS_DMASYNC_POSTREAD); 2438 } 2439 2440 if (cmd->srcu.src_m != cmd->dstu.dst_m) { 2441 m_freem(cmd->srcu.src_m); 2442 crp->crp_buf = (void *)cmd->dstu.dst_m; 2443 } 2444 2445 /* non-shared buffers cannot be restarted */ 2446 if (cmd->src_map != cmd->dst_map) { 2447 /* 2448 * XXX should be EAGAIN, delayed until 2449 * after the reset. 2450 */ 2451 crp->crp_etype = ENOMEM; 2452 bus_dmamap_unload(sc->sc_dmat, cmd->dst_map); 2453 bus_dmamap_destroy(sc->sc_dmat, cmd->dst_map); 2454 } else 2455 crp->crp_etype = ENOMEM; 2456 2457 bus_dmamap_unload(sc->sc_dmat, cmd->src_map); 2458 bus_dmamap_destroy(sc->sc_dmat, cmd->src_map); 2459 2460 free(cmd, M_DEVBUF); 2461 if (crp->crp_etype != EAGAIN) 2462 crypto_done(crp); 2463 } 2464 2465 if (++i == HIFN_D_RES_RSIZE) 2466 i = 0; 2467 u--; 2468 } 2469 dma->resk = i; dma->resu = u; 2470 2471 /* Force upload of key next time */ 2472 for (i = 0; i < sc->sc_maxses; i++) 2473 if (sc->sc_sessions[i].hs_state == HS_STATE_KEY) 2474 sc->sc_sessions[i].hs_state = HS_STATE_USED; 2475 2476 hifn_reset_board(sc, 1); 2477 hifn_init_dma(sc); 2478 hifn_init_pci_registers(sc); 2479 } 2480 2481 static void 2482 hifn_callback(struct hifn_softc *sc, struct hifn_command *cmd, u_int8_t *resbuf) 2483 { 2484 struct hifn_dma *dma = sc->sc_dma; 2485 struct cryptop *crp = cmd->crp; 2486 struct cryptodesc *crd; 2487 struct mbuf *m; 2488 int totlen, i, u, ivlen; 2489 2490 if (cmd->src_map == cmd->dst_map) 2491 bus_dmamap_sync(sc->sc_dmat, cmd->src_map, 2492 0, cmd->src_map->dm_mapsize, 2493 BUS_DMASYNC_POSTWRITE | BUS_DMASYNC_POSTREAD); 2494 else { 2495 bus_dmamap_sync(sc->sc_dmat, cmd->src_map, 2496 0, cmd->src_map->dm_mapsize, BUS_DMASYNC_POSTWRITE); 2497 bus_dmamap_sync(sc->sc_dmat, cmd->dst_map, 2498 0, cmd->dst_map->dm_mapsize, BUS_DMASYNC_POSTREAD); 2499 } 2500 2501 if (crp->crp_flags & CRYPTO_F_IMBUF) { 2502 if (cmd->srcu.src_m != cmd->dstu.dst_m) { 2503 crp->crp_buf = (void *)cmd->dstu.dst_m; 2504 totlen = cmd->src_map->dm_mapsize; 2505 for (m = cmd->dstu.dst_m; m != NULL; m = m->m_next) { 2506 if (totlen < m->m_len) { 2507 m->m_len = totlen; 2508 totlen = 0; 2509 } else 2510 totlen -= m->m_len; 2511 } 2512 cmd->dstu.dst_m->m_pkthdr.len = 2513 cmd->srcu.src_m->m_pkthdr.len; 2514 m_freem(cmd->srcu.src_m); 2515 } 2516 } 2517 2518 if (cmd->sloplen != 0) { 2519 if (crp->crp_flags & CRYPTO_F_IMBUF) 2520 m_copyback((struct mbuf *)crp->crp_buf, 2521 cmd->src_map->dm_mapsize - cmd->sloplen, 2522 cmd->sloplen, (void *)&dma->slop[cmd->slopidx]); 2523 else if (crp->crp_flags & CRYPTO_F_IOV) 2524 cuio_copyback((struct uio *)crp->crp_buf, 2525 cmd->src_map->dm_mapsize - cmd->sloplen, 2526 cmd->sloplen, (void *)&dma->slop[cmd->slopidx]); 2527 } 2528 2529 i = dma->dstk; u = dma->dstu; 2530 while (u != 0) { 2531 bus_dmamap_sync(sc->sc_dmat, sc->sc_dmamap, 2532 offsetof(struct hifn_dma, dstr[i]), sizeof(struct hifn_desc), 2533 BUS_DMASYNC_POSTREAD | BUS_DMASYNC_POSTWRITE); 2534 if (dma->dstr[i].l & htole32(HIFN_D_VALID)) { 2535 bus_dmamap_sync(sc->sc_dmat, sc->sc_dmamap, 2536 offsetof(struct hifn_dma, dstr[i]), 2537 sizeof(struct hifn_desc), 2538 BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE); 2539 break; 2540 } 2541 if (++i == (HIFN_D_DST_RSIZE + 1)) 2542 i = 0; 2543 else 2544 u--; 2545 } 2546 dma->dstk = i; dma->dstu = u; 2547 2548 hifnstats.hst_obytes += cmd->dst_map->dm_mapsize; 2549 2550 if ((cmd->base_masks & (HIFN_BASE_CMD_CRYPT | HIFN_BASE_CMD_DECODE)) == 2551 HIFN_BASE_CMD_CRYPT) { 2552 for (crd = crp->crp_desc; crd; crd = crd->crd_next) { 2553 if (crd->crd_alg != CRYPTO_DES_CBC && 2554 crd->crd_alg != CRYPTO_3DES_CBC && 2555 crd->crd_alg != CRYPTO_AES_CBC) 2556 continue; 2557 ivlen = ((crd->crd_alg == CRYPTO_AES_CBC) ? 2558 HIFN_AES_IV_LENGTH : HIFN_IV_LENGTH); 2559 if (crp->crp_flags & CRYPTO_F_IMBUF) 2560 m_copydata((struct mbuf *)crp->crp_buf, 2561 crd->crd_skip + crd->crd_len - ivlen, 2562 ivlen, 2563 cmd->softc->sc_sessions[cmd->session_num].hs_iv); 2564 else if (crp->crp_flags & CRYPTO_F_IOV) { 2565 cuio_copydata((struct uio *)crp->crp_buf, 2566 crd->crd_skip + crd->crd_len - ivlen, 2567 ivlen, 2568 cmd->softc->sc_sessions[cmd->session_num].hs_iv); 2569 } 2570 /* XXX We do not handle contig data */ 2571 break; 2572 } 2573 } 2574 2575 if (cmd->base_masks & HIFN_BASE_CMD_MAC) { 2576 u_int8_t *macbuf; 2577 2578 macbuf = resbuf + sizeof(struct hifn_base_result); 2579 if (cmd->base_masks & HIFN_BASE_CMD_COMP) 2580 macbuf += sizeof(struct hifn_comp_result); 2581 macbuf += sizeof(struct hifn_mac_result); 2582 2583 for (crd = crp->crp_desc; crd; crd = crd->crd_next) { 2584 int len; 2585 2586 if (crd->crd_alg == CRYPTO_MD5) 2587 len = 16; 2588 else if (crd->crd_alg == CRYPTO_SHA1) 2589 len = 20; 2590 else if (crd->crd_alg == CRYPTO_MD5_HMAC_96 || 2591 crd->crd_alg == CRYPTO_SHA1_HMAC_96) 2592 len = 12; 2593 else 2594 continue; 2595 2596 if (crp->crp_flags & CRYPTO_F_IMBUF) 2597 m_copyback((struct mbuf *)crp->crp_buf, 2598 crd->crd_inject, len, macbuf); 2599 else if ((crp->crp_flags & CRYPTO_F_IOV) && crp->crp_mac) 2600 memcpy(crp->crp_mac, (void *)macbuf, len); 2601 break; 2602 } 2603 } 2604 2605 if (cmd->src_map != cmd->dst_map) { 2606 bus_dmamap_unload(sc->sc_dmat, cmd->dst_map); 2607 bus_dmamap_destroy(sc->sc_dmat, cmd->dst_map); 2608 } 2609 bus_dmamap_unload(sc->sc_dmat, cmd->src_map); 2610 bus_dmamap_destroy(sc->sc_dmat, cmd->src_map); 2611 free(cmd, M_DEVBUF); 2612 crypto_done(crp); 2613 } 2614 2615 #ifdef HAVE_CRYPTO_LZS 2616 2617 static int 2618 hifn_compression(struct hifn_softc *sc, struct cryptop *crp, 2619 struct hifn_command *cmd) 2620 { 2621 struct cryptodesc *crd = crp->crp_desc; 2622 int s, err = 0; 2623 2624 cmd->compcrd = crd; 2625 cmd->base_masks |= HIFN_BASE_CMD_COMP; 2626 2627 if ((crp->crp_flags & CRYPTO_F_IMBUF) == 0) { 2628 /* 2629 * XXX can only handle mbufs right now since we can 2630 * XXX dynamically resize them. 2631 */ 2632 err = EINVAL; 2633 return (ENOMEM); 2634 } 2635 2636 if ((crd->crd_flags & CRD_F_COMP) == 0) 2637 cmd->base_masks |= HIFN_BASE_CMD_DECODE; 2638 if (crd->crd_alg == CRYPTO_LZS_COMP) 2639 cmd->comp_masks |= HIFN_COMP_CMD_ALG_LZS | 2640 HIFN_COMP_CMD_CLEARHIST; 2641 2642 if (bus_dmamap_create(sc->sc_dmat, HIFN_MAX_DMALEN, MAX_SCATTER, 2643 HIFN_MAX_SEGLEN, 0, BUS_DMA_NOWAIT, &cmd->src_map)) { 2644 err = ENOMEM; 2645 goto fail; 2646 } 2647 2648 if (bus_dmamap_create(sc->sc_dmat, HIFN_MAX_DMALEN, MAX_SCATTER, 2649 HIFN_MAX_SEGLEN, 0, BUS_DMA_NOWAIT, &cmd->dst_map)) { 2650 err = ENOMEM; 2651 goto fail; 2652 } 2653 2654 if (crp->crp_flags & CRYPTO_F_IMBUF) { 2655 int len; 2656 2657 if (bus_dmamap_load_mbuf(sc->sc_dmat, cmd->src_map, 2658 cmd->srcu.src_m, BUS_DMA_NOWAIT)) { 2659 err = ENOMEM; 2660 goto fail; 2661 } 2662 2663 len = cmd->src_map->dm_mapsize / MCLBYTES; 2664 if ((cmd->src_map->dm_mapsize % MCLBYTES) != 0) 2665 len++; 2666 len *= MCLBYTES; 2667 2668 if ((crd->crd_flags & CRD_F_COMP) == 0) 2669 len *= 4; 2670 2671 if (len > HIFN_MAX_DMALEN) 2672 len = HIFN_MAX_DMALEN; 2673 2674 cmd->dstu.dst_m = hifn_mkmbuf_chain(len, cmd->srcu.src_m); 2675 if (cmd->dstu.dst_m == NULL) { 2676 err = ENOMEM; 2677 goto fail; 2678 } 2679 2680 if (bus_dmamap_load_mbuf(sc->sc_dmat, cmd->dst_map, 2681 cmd->dstu.dst_m, BUS_DMA_NOWAIT)) { 2682 err = ENOMEM; 2683 goto fail; 2684 } 2685 } else if (crp->crp_flags & CRYPTO_F_IOV) { 2686 if (bus_dmamap_load_uio(sc->sc_dmat, cmd->src_map, 2687 cmd->srcu.src_io, BUS_DMA_NOWAIT)) { 2688 err = ENOMEM; 2689 goto fail; 2690 } 2691 if (bus_dmamap_load_uio(sc->sc_dmat, cmd->dst_map, 2692 cmd->dstu.dst_io, BUS_DMA_NOWAIT)) { 2693 err = ENOMEM; 2694 goto fail; 2695 } 2696 } 2697 2698 if (cmd->src_map == cmd->dst_map) 2699 bus_dmamap_sync(sc->sc_dmat, cmd->src_map, 2700 0, cmd->src_map->dm_mapsize, 2701 BUS_DMASYNC_PREWRITE|BUS_DMASYNC_PREREAD); 2702 else { 2703 bus_dmamap_sync(sc->sc_dmat, cmd->src_map, 2704 0, cmd->src_map->dm_mapsize, BUS_DMASYNC_PREWRITE); 2705 bus_dmamap_sync(sc->sc_dmat, cmd->dst_map, 2706 0, cmd->dst_map->dm_mapsize, BUS_DMASYNC_PREREAD); 2707 } 2708 2709 cmd->crp = crp; 2710 /* 2711 * Always use session 0. The modes of compression we use are 2712 * stateless and there is always at least one compression 2713 * context, zero. 2714 */ 2715 cmd->session_num = 0; 2716 cmd->softc = sc; 2717 2718 s = splnet(); 2719 err = hifn_compress_enter(sc, cmd); 2720 splx(s); 2721 2722 if (err != 0) 2723 goto fail; 2724 return (0); 2725 2726 fail: 2727 if (cmd->dst_map != NULL) { 2728 if (cmd->dst_map->dm_nsegs > 0) 2729 bus_dmamap_unload(sc->sc_dmat, cmd->dst_map); 2730 bus_dmamap_destroy(sc->sc_dmat, cmd->dst_map); 2731 } 2732 if (cmd->src_map != NULL) { 2733 if (cmd->src_map->dm_nsegs > 0) 2734 bus_dmamap_unload(sc->sc_dmat, cmd->src_map); 2735 bus_dmamap_destroy(sc->sc_dmat, cmd->src_map); 2736 } 2737 free(cmd, M_DEVBUF); 2738 if (err == EINVAL) 2739 hifnstats.hst_invalid++; 2740 else 2741 hifnstats.hst_nomem++; 2742 crp->crp_etype = err; 2743 crypto_done(crp); 2744 return (0); 2745 } 2746 2747 /* 2748 * must be called at splnet() 2749 */ 2750 static int 2751 hifn_compress_enter(struct hifn_softc *sc, struct hifn_command *cmd) 2752 { 2753 struct hifn_dma *dma = sc->sc_dma; 2754 int cmdi, resi; 2755 u_int32_t cmdlen; 2756 2757 if ((dma->cmdu + 1) > HIFN_D_CMD_RSIZE || 2758 (dma->resu + 1) > HIFN_D_CMD_RSIZE) 2759 return (ENOMEM); 2760 2761 if ((dma->srcu + cmd->src_map->dm_nsegs) > HIFN_D_SRC_RSIZE || 2762 (dma->dstu + cmd->dst_map->dm_nsegs) > HIFN_D_DST_RSIZE) 2763 return (ENOMEM); 2764 2765 if (dma->cmdi == HIFN_D_CMD_RSIZE) { 2766 dma->cmdi = 0; 2767 dma->cmdr[HIFN_D_CMD_RSIZE].l = htole32(HIFN_D_VALID | 2768 HIFN_D_JUMP | HIFN_D_MASKDONEIRQ); 2769 HIFN_CMDR_SYNC(sc, HIFN_D_CMD_RSIZE, 2770 BUS_DMASYNC_PREWRITE | BUS_DMASYNC_PREREAD); 2771 } 2772 cmdi = dma->cmdi++; 2773 cmdlen = hifn_write_command(cmd, dma->command_bufs[cmdi]); 2774 HIFN_CMD_SYNC(sc, cmdi, BUS_DMASYNC_PREWRITE); 2775 2776 /* .p for command/result already set */ 2777 dma->cmdr[cmdi].l = htole32(cmdlen | HIFN_D_VALID | HIFN_D_LAST | 2778 HIFN_D_MASKDONEIRQ); 2779 HIFN_CMDR_SYNC(sc, cmdi, 2780 BUS_DMASYNC_PREWRITE | BUS_DMASYNC_PREREAD); 2781 dma->cmdu++; 2782 if (sc->sc_c_busy == 0) { 2783 WRITE_REG_1(sc, HIFN_1_DMA_CSR, HIFN_DMACSR_C_CTRL_ENA); 2784 sc->sc_c_busy = 1; 2785 SET_LED(sc, HIFN_MIPSRST_LED0); 2786 } 2787 2788 /* 2789 * We don't worry about missing an interrupt (which a "command wait" 2790 * interrupt salvages us from), unless there is more than one command 2791 * in the queue. 2792 */ 2793 if (dma->cmdu > 1) { 2794 sc->sc_dmaier |= HIFN_DMAIER_C_WAIT; 2795 WRITE_REG_1(sc, HIFN_1_DMA_IER, sc->sc_dmaier); 2796 } 2797 2798 hifnstats.hst_ipackets++; 2799 hifnstats.hst_ibytes += cmd->src_map->dm_mapsize; 2800 2801 hifn_dmamap_load_src(sc, cmd); 2802 if (sc->sc_s_busy == 0) { 2803 WRITE_REG_1(sc, HIFN_1_DMA_CSR, HIFN_DMACSR_S_CTRL_ENA); 2804 sc->sc_s_busy = 1; 2805 SET_LED(sc, HIFN_MIPSRST_LED1); 2806 } 2807 2808 /* 2809 * Unlike other descriptors, we don't mask done interrupt from 2810 * result descriptor. 2811 */ 2812 if (dma->resi == HIFN_D_RES_RSIZE) { 2813 dma->resi = 0; 2814 dma->resr[HIFN_D_RES_RSIZE].l = htole32(HIFN_D_VALID | 2815 HIFN_D_JUMP | HIFN_D_MASKDONEIRQ); 2816 HIFN_RESR_SYNC(sc, HIFN_D_RES_RSIZE, 2817 BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE); 2818 } 2819 resi = dma->resi++; 2820 dma->hifn_commands[resi] = cmd; 2821 HIFN_RES_SYNC(sc, resi, BUS_DMASYNC_PREREAD); 2822 dma->resr[resi].l = htole32(HIFN_MAX_RESULT | 2823 HIFN_D_VALID | HIFN_D_LAST); 2824 HIFN_RESR_SYNC(sc, resi, 2825 BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE); 2826 dma->resu++; 2827 if (sc->sc_r_busy == 0) { 2828 WRITE_REG_1(sc, HIFN_1_DMA_CSR, HIFN_DMACSR_R_CTRL_ENA); 2829 sc->sc_r_busy = 1; 2830 SET_LED(sc, HIFN_MIPSRST_LED2); 2831 } 2832 2833 if (cmd->sloplen) 2834 cmd->slopidx = resi; 2835 2836 hifn_dmamap_load_dst(sc, cmd); 2837 2838 if (sc->sc_d_busy == 0) { 2839 WRITE_REG_1(sc, HIFN_1_DMA_CSR, HIFN_DMACSR_D_CTRL_ENA); 2840 sc->sc_d_busy = 1; 2841 } 2842 sc->sc_active = 5; 2843 cmd->cmd_callback = hifn_callback_comp; 2844 return (0); 2845 } 2846 2847 static void 2848 hifn_callback_comp(struct hifn_softc *sc, struct hifn_command *cmd, 2849 u_int8_t *resbuf) 2850 { 2851 struct hifn_base_result baseres; 2852 struct cryptop *crp = cmd->crp; 2853 struct hifn_dma *dma = sc->sc_dma; 2854 struct mbuf *m; 2855 int err = 0, i, u; 2856 u_int32_t olen; 2857 bus_size_t dstsize; 2858 2859 bus_dmamap_sync(sc->sc_dmat, cmd->src_map, 2860 0, cmd->src_map->dm_mapsize, BUS_DMASYNC_POSTWRITE); 2861 bus_dmamap_sync(sc->sc_dmat, cmd->dst_map, 2862 0, cmd->dst_map->dm_mapsize, BUS_DMASYNC_POSTREAD); 2863 2864 dstsize = cmd->dst_map->dm_mapsize; 2865 bus_dmamap_unload(sc->sc_dmat, cmd->dst_map); 2866 2867 memcpy(&baseres, resbuf, sizeof(struct hifn_base_result)); 2868 2869 i = dma->dstk; u = dma->dstu; 2870 while (u != 0) { 2871 bus_dmamap_sync(sc->sc_dmat, sc->sc_dmamap, 2872 offsetof(struct hifn_dma, dstr[i]), sizeof(struct hifn_desc), 2873 BUS_DMASYNC_POSTREAD | BUS_DMASYNC_POSTWRITE); 2874 if (dma->dstr[i].l & htole32(HIFN_D_VALID)) { 2875 bus_dmamap_sync(sc->sc_dmat, sc->sc_dmamap, 2876 offsetof(struct hifn_dma, dstr[i]), 2877 sizeof(struct hifn_desc), 2878 BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE); 2879 break; 2880 } 2881 if (++i == (HIFN_D_DST_RSIZE + 1)) 2882 i = 0; 2883 else 2884 u--; 2885 } 2886 dma->dstk = i; dma->dstu = u; 2887 2888 if (baseres.flags & htole16(HIFN_BASE_RES_DSTOVERRUN)) { 2889 bus_size_t xlen; 2890 2891 xlen = dstsize; 2892 2893 m_freem(cmd->dstu.dst_m); 2894 2895 if (xlen == HIFN_MAX_DMALEN) { 2896 /* We've done all we can. */ 2897 err = E2BIG; 2898 goto out; 2899 } 2900 2901 xlen += MCLBYTES; 2902 2903 if (xlen > HIFN_MAX_DMALEN) 2904 xlen = HIFN_MAX_DMALEN; 2905 2906 cmd->dstu.dst_m = hifn_mkmbuf_chain(xlen, 2907 cmd->srcu.src_m); 2908 if (cmd->dstu.dst_m == NULL) { 2909 err = ENOMEM; 2910 goto out; 2911 } 2912 if (bus_dmamap_load_mbuf(sc->sc_dmat, cmd->dst_map, 2913 cmd->dstu.dst_m, BUS_DMA_NOWAIT)) { 2914 err = ENOMEM; 2915 goto out; 2916 } 2917 2918 bus_dmamap_sync(sc->sc_dmat, cmd->src_map, 2919 0, cmd->src_map->dm_mapsize, BUS_DMASYNC_PREWRITE); 2920 bus_dmamap_sync(sc->sc_dmat, cmd->dst_map, 2921 0, cmd->dst_map->dm_mapsize, BUS_DMASYNC_PREREAD); 2922 2923 /* already at splnet... */ 2924 err = hifn_compress_enter(sc, cmd); 2925 if (err != 0) 2926 goto out; 2927 return; 2928 } 2929 2930 olen = dstsize - (letoh16(baseres.dst_cnt) | 2931 (((letoh16(baseres.session) & HIFN_BASE_RES_DSTLEN_M) >> 2932 HIFN_BASE_RES_DSTLEN_S) << 16)); 2933 2934 crp->crp_olen = olen - cmd->compcrd->crd_skip; 2935 2936 bus_dmamap_unload(sc->sc_dmat, cmd->src_map); 2937 bus_dmamap_destroy(sc->sc_dmat, cmd->src_map); 2938 bus_dmamap_destroy(sc->sc_dmat, cmd->dst_map); 2939 2940 m = cmd->dstu.dst_m; 2941 if (m->m_flags & M_PKTHDR) 2942 m->m_pkthdr.len = olen; 2943 crp->crp_buf = (void *)m; 2944 for (; m != NULL; m = m->m_next) { 2945 if (olen >= m->m_len) 2946 olen -= m->m_len; 2947 else { 2948 m->m_len = olen; 2949 olen = 0; 2950 } 2951 } 2952 2953 m_freem(cmd->srcu.src_m); 2954 free(cmd, M_DEVBUF); 2955 crp->crp_etype = 0; 2956 crypto_done(crp); 2957 return; 2958 2959 out: 2960 if (cmd->dst_map != NULL) { 2961 if (cmd->src_map->dm_nsegs != 0) 2962 bus_dmamap_unload(sc->sc_dmat, cmd->src_map); 2963 bus_dmamap_destroy(sc->sc_dmat, cmd->dst_map); 2964 } 2965 if (cmd->src_map != NULL) { 2966 if (cmd->src_map->dm_nsegs != 0) 2967 bus_dmamap_unload(sc->sc_dmat, cmd->src_map); 2968 bus_dmamap_destroy(sc->sc_dmat, cmd->src_map); 2969 } 2970 if (cmd->dstu.dst_m != NULL) 2971 m_freem(cmd->dstu.dst_m); 2972 free(cmd, M_DEVBUF); 2973 crp->crp_etype = err; 2974 crypto_done(crp); 2975 } 2976 2977 static struct mbuf * 2978 hifn_mkmbuf_chain(int totlen, struct mbuf *mtemplate) 2979 { 2980 int len; 2981 struct mbuf *m, *m0, *mlast; 2982 2983 if (mtemplate->m_flags & M_PKTHDR) { 2984 len = MHLEN; 2985 MGETHDR(m0, M_DONTWAIT, MT_DATA); 2986 } else { 2987 len = MLEN; 2988 MGET(m0, M_DONTWAIT, MT_DATA); 2989 } 2990 if (m0 == NULL) 2991 return (NULL); 2992 if (len == MHLEN) 2993 M_DUP_PKTHDR(m0, mtemplate); 2994 MCLGET(m0, M_DONTWAIT); 2995 if (!(m0->m_flags & M_EXT)) 2996 m_freem(m0); 2997 len = MCLBYTES; 2998 2999 totlen -= len; 3000 m0->m_pkthdr.len = m0->m_len = len; 3001 mlast = m0; 3002 3003 while (totlen > 0) { 3004 MGET(m, M_DONTWAIT, MT_DATA); 3005 if (m == NULL) { 3006 m_freem(m0); 3007 return (NULL); 3008 } 3009 MCLGET(m, M_DONTWAIT); 3010 if (!(m->m_flags & M_EXT)) { 3011 m_freem(m0); 3012 return (NULL); 3013 } 3014 len = MCLBYTES; 3015 m->m_len = len; 3016 if (m0->m_flags & M_PKTHDR) 3017 m0->m_pkthdr.len += len; 3018 totlen -= len; 3019 3020 mlast->m_next = m; 3021 mlast = m; 3022 } 3023 3024 return (m0); 3025 } 3026 #endif /* HAVE_CRYPTO_LZS */ 3027 3028 static void 3029 hifn_write_4(struct hifn_softc *sc, int reggrp, bus_size_t reg, u_int32_t val) 3030 { 3031 /* 3032 * 7811 PB3 rev/2 parts lock-up on burst writes to Group 0 3033 * and Group 1 registers; avoid conditions that could create 3034 * burst writes by doing a read in between the writes. 3035 */ 3036 if (sc->sc_flags & HIFN_NO_BURSTWRITE) { 3037 if (sc->sc_waw_lastgroup == reggrp && 3038 sc->sc_waw_lastreg == reg - 4) { 3039 bus_space_read_4(sc->sc_st1, sc->sc_sh1, HIFN_1_REVID); 3040 } 3041 sc->sc_waw_lastgroup = reggrp; 3042 sc->sc_waw_lastreg = reg; 3043 } 3044 if (reggrp == 0) 3045 bus_space_write_4(sc->sc_st0, sc->sc_sh0, reg, val); 3046 else 3047 bus_space_write_4(sc->sc_st1, sc->sc_sh1, reg, val); 3048 3049 } 3050 3051 static u_int32_t 3052 hifn_read_4(struct hifn_softc *sc, int reggrp, bus_size_t reg) 3053 { 3054 if (sc->sc_flags & HIFN_NO_BURSTWRITE) { 3055 sc->sc_waw_lastgroup = -1; 3056 sc->sc_waw_lastreg = 1; 3057 } 3058 if (reggrp == 0) 3059 return (bus_space_read_4(sc->sc_st0, sc->sc_sh0, reg)); 3060 return (bus_space_read_4(sc->sc_st1, sc->sc_sh1, reg)); 3061 } 3062