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