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