hifn7751.c revision 1.6 1 /* $NetBSD: hifn7751.c,v 1.6 2001/11/13 07:48:42 lukem Exp $ */
2 /* $OpenBSD: hifn7751.c,v 1.47 2000/10/11 13:15:41 itojun Exp $ */
3
4 /*
5 * Invertex AEON / Hi/fn 7751 driver
6 * Copyright (c) 1999 Invertex Inc. All rights reserved.
7 * Copyright (c) 1999 Theo de Raadt
8 * Copyright (c) 2000 Network Security Technologies, Inc.
9 * http://www.netsec.net
10 *
11 * This driver is based on a previous driver by Invertex, for which they
12 * requested: Please send any comments, feedback, bug-fixes, or feature
13 * requests to software (at) invertex.com.
14 *
15 * Redistribution and use in source and binary forms, with or without
16 * modification, are permitted provided that the following conditions
17 * are met:
18 *
19 * 1. Redistributions of source code must retain the above copyright
20 * notice, this list of conditions and the following disclaimer.
21 * 2. Redistributions in binary form must reproduce the above copyright
22 * notice, this list of conditions and the following disclaimer in the
23 * documentation and/or other materials provided with the distribution.
24 * 3. The name of the author may not be used to endorse or promote products
25 * derived from this software without specific prior written permission.
26 *
27 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
28 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
29 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
30 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
31 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
32 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
33 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
34 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
35 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
36 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
37 */
38
39 /*
40 * Driver for the Hi/Fn 7751 encryption processor.
41 */
42
43 #include <sys/cdefs.h>
44 __KERNEL_RCSID(0, "$NetBSD: hifn7751.c,v 1.6 2001/11/13 07:48:42 lukem Exp $");
45
46 #include <sys/param.h>
47 #include <sys/systm.h>
48 #include <sys/proc.h>
49 #include <sys/errno.h>
50 #include <sys/malloc.h>
51 #include <sys/kernel.h>
52 #include <sys/mbuf.h>
53 #ifdef __OpenBSD__
54 #include <vm/vm.h>
55 #include <vm/vm_extern.h>
56 #include <vm/pmap.h>
57 #else
58 #include <uvm/uvm.h>
59 #include <uvm/uvm_extern.h>
60 #include <uvm/uvm_pmap.h>
61 #endif
62 #include <machine/pmap.h>
63 #include <sys/device.h>
64
65 #ifdef __OpenBSD__
66 #include <crypto/crypto.h>
67 #include <dev/rndvar.h>
68 #endif
69
70 #include <dev/pci/pcireg.h>
71 #include <dev/pci/pcivar.h>
72 #include <dev/pci/pcidevs.h>
73
74 #include <dev/pci/hifn7751var.h>
75 #include <dev/pci/hifn7751reg.h>
76
77 #undef HIFN_DEBUG
78
79 /*
80 * Prototypes and count for the pci_device structure
81 */
82 #ifdef __OpenBSD__
83 int hifn_probe __P((struct device *, void *, void *));
84 #else
85 int hifn_probe __P((struct device *, struct cfdata *, void *));
86 #endif
87 void hifn_attach __P((struct device *, struct device *, void *));
88
89 struct cfattach hifn_ca = {
90 sizeof(struct hifn_softc), hifn_probe, hifn_attach,
91 };
92
93 #ifdef __OpenBSD__
94 struct cfdriver hifn_cd = {
95 0, "hifn", DV_DULL
96 };
97 #endif
98
99 void hifn_reset_board __P((struct hifn_softc *));
100 int hifn_enable_crypto __P((struct hifn_softc *, pcireg_t));
101 void hifn_init_dma __P((struct hifn_softc *));
102 void hifn_init_pci_registers __P((struct hifn_softc *));
103 int hifn_sramsize __P((struct hifn_softc *));
104 int hifn_dramsize __P((struct hifn_softc *));
105 void hifn_ramtype __P((struct hifn_softc *));
106 void hifn_sessions __P((struct hifn_softc *));
107 int hifn_intr __P((void *));
108 u_int hifn_write_command __P((struct hifn_command *, u_int8_t *));
109 u_int32_t hifn_next_signature __P((u_int32_t a, u_int cnt));
110 #ifdef __OpenBSD__
111 int hifn_newsession __P((u_int32_t *, struct cryptoini *));
112 int hifn_freesession __P((u_int64_t));
113 int hifn_process __P((struct cryptop *));
114 void hifn_callback __P((struct hifn_softc *, struct hifn_command *, u_int8_t *));
115 #endif
116 int hifn_crypto __P((struct hifn_softc *, hifn_command_t *));
117 int hifn_readramaddr __P((struct hifn_softc *, int, u_int8_t *, int));
118 int hifn_writeramaddr __P((struct hifn_softc *, int, u_int8_t *, int));
119
120 struct hifn_stats {
121 u_int64_t hst_ibytes;
122 u_int64_t hst_obytes;
123 u_int32_t hst_ipackets;
124 u_int32_t hst_opackets;
125 u_int32_t hst_invalid;
126 u_int32_t hst_nomem;
127 } hifnstats;
128
129 int
130 hifn_probe(parent, match, aux)
131 struct device *parent;
132 #ifdef __OpenBSD__
133 void *match;
134 #else
135 struct cfdata *match;
136 #endif
137 void *aux;
138 {
139 struct pci_attach_args *pa = (struct pci_attach_args *) aux;
140
141 if (PCI_VENDOR(pa->pa_id) == PCI_VENDOR_INVERTEX &&
142 PCI_PRODUCT(pa->pa_id) == PCI_PRODUCT_INVERTEX_AEON)
143 return (1);
144 if (PCI_VENDOR(pa->pa_id) == PCI_VENDOR_HIFN &&
145 PCI_PRODUCT(pa->pa_id) == PCI_PRODUCT_HIFN_7751)
146 return (1);
147 if (PCI_VENDOR(pa->pa_id) == PCI_VENDOR_NETSEC &&
148 PCI_PRODUCT(pa->pa_id) == PCI_PRODUCT_NETSEC_7751)
149 return (1);
150 return (0);
151 }
152
153 void
154 hifn_attach(parent, self, aux)
155 struct device *parent, *self;
156 void *aux;
157 {
158 struct hifn_softc *sc = (struct hifn_softc *)self;
159 struct pci_attach_args *pa = aux;
160 pci_chipset_tag_t pc = pa->pa_pc;
161 pci_intr_handle_t ih;
162 const char *intrstr = NULL;
163 char rbase;
164 bus_size_t iosize0, iosize1;
165 u_int32_t cmd;
166 u_int16_t ena;
167 bus_dma_segment_t seg;
168 bus_dmamap_t dmamap;
169 int rseg;
170 caddr_t kva;
171
172 cmd = pci_conf_read(pc, pa->pa_tag, PCI_COMMAND_STATUS_REG);
173 cmd |= PCI_COMMAND_MEM_ENABLE | PCI_COMMAND_MASTER_ENABLE;
174 pci_conf_write(pc, pa->pa_tag, PCI_COMMAND_STATUS_REG, cmd);
175 cmd = pci_conf_read(pc, pa->pa_tag, PCI_COMMAND_STATUS_REG);
176
177 if (!(cmd & PCI_COMMAND_MEM_ENABLE)) {
178 printf(": failed to enable memory mapping\n");
179 return;
180 }
181
182 if (pci_mapreg_map(pa, HIFN_BAR0, PCI_MAPREG_TYPE_MEM, 0,
183 &sc->sc_st0, &sc->sc_sh0, NULL, &iosize0)) {
184 printf(": can't find mem space %d\n", 0);
185 return;
186 }
187
188 if (pci_mapreg_map(pa, HIFN_BAR1, PCI_MAPREG_TYPE_MEM, 0,
189 &sc->sc_st1, &sc->sc_sh1, NULL, &iosize1)) {
190 printf(": can't find mem space %d\n", 1);
191 goto fail_io0;
192 }
193
194 sc->sc_dmat = pa->pa_dmat;
195 if (bus_dmamem_alloc(sc->sc_dmat, sizeof(*sc->sc_dma), PAGE_SIZE, 0,
196 &seg, 1, &rseg, BUS_DMA_NOWAIT)) {
197 printf(": can't alloc dma buffer\n");
198 goto fail_io1;
199 }
200 if (bus_dmamem_map(sc->sc_dmat, &seg, rseg, sizeof(*sc->sc_dma), &kva,
201 BUS_DMA_NOWAIT)) {
202 printf(": can't map dma buffers (%lu bytes)\n",
203 (u_long)sizeof(*sc->sc_dma));
204 bus_dmamem_free(sc->sc_dmat, &seg, rseg);
205 goto fail_io1;
206 }
207 if (bus_dmamap_create(sc->sc_dmat, sizeof(*sc->sc_dma), 1,
208 sizeof(*sc->sc_dma), 0, BUS_DMA_NOWAIT, &dmamap)) {
209 printf(": can't create dma map\n");
210 bus_dmamem_unmap(sc->sc_dmat, kva, sizeof(*sc->sc_dma));
211 bus_dmamem_free(sc->sc_dmat, &seg, rseg);
212 goto fail_io1;
213 }
214 if (bus_dmamap_load(sc->sc_dmat, dmamap, kva, sizeof(*sc->sc_dma),
215 NULL, BUS_DMA_NOWAIT)) {
216 printf(": can't load dma map\n");
217 bus_dmamap_destroy(sc->sc_dmat, dmamap);
218 bus_dmamem_unmap(sc->sc_dmat, kva, sizeof(*sc->sc_dma));
219 bus_dmamem_free(sc->sc_dmat, &seg, rseg);
220 goto fail_io1;
221 }
222 sc->sc_dma = (struct hifn_dma *)kva;
223 memset(sc->sc_dma, 0, sizeof(*sc->sc_dma));
224
225 hifn_reset_board(sc);
226
227 if (hifn_enable_crypto(sc, pa->pa_id) != 0) {
228 printf("%s: crypto enabling failed\n", sc->sc_dv.dv_xname);
229 goto fail_mem;
230 }
231
232 hifn_init_dma(sc);
233 hifn_init_pci_registers(sc);
234
235 hifn_ramtype(sc);
236
237 if (sc->sc_drammodel == 0)
238 hifn_sramsize(sc);
239 else
240 hifn_dramsize(sc);
241
242 if (PCI_VENDOR(pa->pa_id) == PCI_VENDOR_NETSEC &&
243 PCI_PRODUCT(pa->pa_id) == PCI_PRODUCT_NETSEC_7751 &&
244 PCI_REVISION(pa->pa_class) == 0x61)
245 sc->sc_ramsize >>= 1;
246
247 /*
248 * Reinitialize again, since the DRAM/SRAM detection shifted our ring
249 * pointers and may have changed the value we send to the RAM Config
250 * Register.
251 */
252 hifn_reset_board(sc);
253 hifn_init_dma(sc);
254 hifn_init_pci_registers(sc);
255
256 if (pci_intr_map(pa, &ih)) {
257 printf(": couldn't map interrupt\n");
258 goto fail_mem;
259 }
260 intrstr = pci_intr_string(pc, ih);
261 #ifdef __OpenBSD__
262 sc->sc_ih = pci_intr_establish(pc, ih, IPL_NET, hifn_intr, sc,
263 self->dv_xname);
264 #else
265 sc->sc_ih = pci_intr_establish(pc, ih, IPL_NET, hifn_intr, sc);
266 #endif
267 if (sc->sc_ih == NULL) {
268 printf(": couldn't establish interrupt\n");
269 if (intrstr != NULL)
270 printf(" at %s", intrstr);
271 printf("\n");
272 goto fail_mem;
273 }
274
275 hifn_sessions(sc);
276
277 rseg = sc->sc_ramsize / 1024;
278 rbase = 'K';
279 if (sc->sc_ramsize >= (1024 * 1024)) {
280 rbase = 'M';
281 rseg /= 1024;
282 }
283 printf(", %d%cB %cram, %s\n", rseg, rbase,
284 sc->sc_drammodel ? 'd' : 's', intrstr);
285
286 #ifdef __OpenBSD__
287 sc->sc_cid = crypto_get_driverid();
288 if (sc->sc_cid < 0)
289 goto fail_intr;
290 #endif
291
292 WRITE_REG_0(sc, HIFN_0_PUCNFG,
293 READ_REG_0(sc, HIFN_0_PUCNFG) | HIFN_PUCNFG_CHIPID);
294 ena = READ_REG_0(sc, HIFN_0_PUSTAT) & HIFN_PUSTAT_CHIPENA;
295
296 #ifdef __OpenBSD__
297 switch (ena) {
298 case HIFN_PUSTAT_ENA_2:
299 crypto_register(sc->sc_cid, CRYPTO_3DES_CBC,
300 hifn_newsession, hifn_freesession, hifn_process);
301 /*FALLTHROUGH*/
302 case HIFN_PUSTAT_ENA_1:
303 crypto_register(sc->sc_cid, CRYPTO_MD5_HMAC96,
304 hifn_newsession, hifn_freesession, hifn_process);
305 crypto_register(sc->sc_cid, CRYPTO_SHA1_HMAC96,
306 NULL, NULL, NULL);
307 crypto_register(sc->sc_cid, CRYPTO_DES_CBC,
308 NULL, NULL, NULL);
309 }
310 #endif
311
312 return;
313
314 #ifdef __OpenBSD__
315 fail_intr:
316 #endif
317 pci_intr_disestablish(pc, sc->sc_ih);
318 fail_mem:
319 bus_dmamap_unload(sc->sc_dmat, dmamap);
320 bus_dmamap_destroy(sc->sc_dmat, dmamap);
321 bus_dmamem_unmap(sc->sc_dmat, kva, sizeof(*sc->sc_dma));
322 bus_dmamem_free(sc->sc_dmat, &seg, rseg);
323 fail_io1:
324 bus_space_unmap(sc->sc_st1, sc->sc_sh1, iosize1);
325 fail_io0:
326 bus_space_unmap(sc->sc_st0, sc->sc_sh0, iosize0);
327 }
328
329 /*
330 * Resets the board. Values in the regesters are left as is
331 * from the reset (i.e. initial values are assigned elsewhere).
332 */
333 void
334 hifn_reset_board(sc)
335 struct hifn_softc *sc;
336 {
337 /*
338 * Set polling in the DMA configuration register to zero. 0x7 avoids
339 * resetting the board and zeros out the other fields.
340 */
341 WRITE_REG_1(sc, HIFN_1_DMA_CNFG, HIFN_DMACNFG_MSTRESET |
342 HIFN_DMACNFG_DMARESET | HIFN_DMACNFG_MODE);
343
344 /*
345 * Now that polling has been disabled, we have to wait 1 ms
346 * before resetting the board.
347 */
348 DELAY(1000);
349
350 /* Reset the board. We do this by writing zeros to the DMA reset
351 * field, the BRD reset field, and the manditory 1 at position 2.
352 * Every other field is set to zero.
353 */
354 WRITE_REG_1(sc, HIFN_1_DMA_CNFG, HIFN_DMACNFG_MODE);
355
356 /*
357 * Wait another millisecond for the board to reset.
358 */
359 DELAY(1000);
360
361 /*
362 * Turn off the reset! (No joke.)
363 */
364 WRITE_REG_1(sc, HIFN_1_DMA_CNFG, HIFN_DMACNFG_MSTRESET |
365 HIFN_DMACNFG_DMARESET | HIFN_DMACNFG_MODE);
366 }
367
368 u_int32_t
369 hifn_next_signature(a, cnt)
370 u_int32_t a;
371 u_int cnt;
372 {
373 int i;
374 u_int32_t v;
375
376 for (i = 0; i < cnt; i++) {
377
378 /* get the parity */
379 v = a & 0x80080125;
380 v ^= v >> 16;
381 v ^= v >> 8;
382 v ^= v >> 4;
383 v ^= v >> 2;
384 v ^= v >> 1;
385
386 a = (v & 1) ^ (a << 1);
387 }
388
389 return a;
390 }
391
392 struct pci2id {
393 u_short pci_vendor;
394 u_short pci_prod;
395 char card_id[13];
396 } pci2id[] = {
397 {
398 PCI_VENDOR_NETSEC,
399 PCI_PRODUCT_NETSEC_7751,
400 { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
401 0x00, 0x00, 0x00, 0x00, 0x00 }
402 }, {
403 PCI_VENDOR_INVERTEX,
404 PCI_PRODUCT_INVERTEX_AEON,
405 { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
406 0x00, 0x00, 0x00, 0x00, 0x00 }
407 }, {
408 /*
409 * Other vendors share this PCI ID as well, such as
410 * http://www.powercrypt.com, and obviously they also
411 * use the same key.
412 */
413 PCI_VENDOR_HIFN,
414 PCI_PRODUCT_HIFN_7751,
415 { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
416 0x00, 0x00, 0x00, 0x00, 0x00 }
417 },
418 };
419
420 /*
421 * Checks to see if crypto is already enabled. If crypto isn't enable,
422 * "hifn_enable_crypto" is called to enable it. The check is important,
423 * as enabling crypto twice will lock the board.
424 */
425 int
426 hifn_enable_crypto(sc, pciid)
427 struct hifn_softc *sc;
428 pcireg_t pciid;
429 {
430 u_int32_t dmacfg, ramcfg, encl, addr, i;
431 char *offtbl = NULL;
432
433 for (i = 0; i < sizeof(pci2id)/sizeof(pci2id[0]); i++) {
434 if (pci2id[i].pci_vendor == PCI_VENDOR(pciid) &&
435 pci2id[i].pci_prod == PCI_PRODUCT(pciid)) {
436 offtbl = pci2id[i].card_id;
437 break;
438 }
439 }
440
441 if (offtbl == NULL) {
442 #ifdef HIFN_DEBUG
443 printf("%s: Unknown card!\n", sc->sc_dv.dv_xname);
444 #endif
445 return (1);
446 }
447
448 ramcfg = READ_REG_0(sc, HIFN_0_PUCNFG);
449 dmacfg = READ_REG_1(sc, HIFN_1_DMA_CNFG);
450
451 /*
452 * The RAM config register's encrypt level bit needs to be set before
453 * every read performed on the encryption level register.
454 */
455 WRITE_REG_0(sc, HIFN_0_PUCNFG, ramcfg | HIFN_PUCNFG_CHIPID);
456
457 encl = READ_REG_0(sc, HIFN_0_PUSTAT) & HIFN_PUSTAT_CHIPENA;
458
459 /*
460 * Make sure we don't re-unlock. Two unlocks kills chip until the
461 * next reboot.
462 */
463 if (encl == HIFN_PUSTAT_ENA_1 || encl == HIFN_PUSTAT_ENA_2) {
464 #ifdef HIFN_DEBUG
465 printf("%s: Strong Crypto already enabled!\n",
466 sc->sc_dv.dv_xname);
467 #endif
468 WRITE_REG_0(sc, HIFN_0_PUCNFG, ramcfg);
469 WRITE_REG_1(sc, HIFN_1_DMA_CNFG, dmacfg);
470 return 0; /* success */
471 }
472
473 if (encl != 0 && encl != HIFN_PUSTAT_ENA_0) {
474 #ifdef HIFN_DEBUG
475 printf("%s: Unknown encryption level\n", sc->sc_dv.dv_xname);
476 #endif
477 return 1;
478 }
479
480 WRITE_REG_1(sc, HIFN_1_DMA_CNFG, HIFN_DMACNFG_UNLOCK |
481 HIFN_DMACNFG_MSTRESET | HIFN_DMACNFG_DMARESET | HIFN_DMACNFG_MODE);
482 DELAY(1000);
483 addr = READ_REG_1(sc, HIFN_UNLOCK_SECRET1);
484 DELAY(1000);
485 WRITE_REG_1(sc, HIFN_UNLOCK_SECRET2, 0);
486 DELAY(1000);
487
488 for (i = 0; i <= 12; i++) {
489 addr = hifn_next_signature(addr, offtbl[i] + 0x101);
490 WRITE_REG_1(sc, HIFN_UNLOCK_SECRET2, addr);
491
492 DELAY(1000);
493 }
494
495 WRITE_REG_0(sc, HIFN_0_PUCNFG, ramcfg | HIFN_PUCNFG_CHIPID);
496 encl = READ_REG_0(sc, HIFN_0_PUSTAT) & HIFN_PUSTAT_CHIPENA;
497
498 #ifdef HIFN_DEBUG
499 if (encl != HIFN_PUSTAT_ENA_1 && encl != HIFN_PUSTAT_ENA_2)
500 printf("Encryption engine is permanently locked until next system reset.");
501 else
502 printf("Encryption engine enabled successfully!");
503 #endif
504
505 WRITE_REG_0(sc, HIFN_0_PUCNFG, ramcfg);
506 WRITE_REG_1(sc, HIFN_1_DMA_CNFG, dmacfg);
507
508 switch (encl) {
509 case HIFN_PUSTAT_ENA_0:
510 printf(": no encr/auth");
511 break;
512 case HIFN_PUSTAT_ENA_1:
513 printf(": DES enabled");
514 break;
515 case HIFN_PUSTAT_ENA_2:
516 printf(": fully enabled");
517 break;
518 default:
519 printf(": disabled");
520 break;
521 }
522
523 return 0;
524 }
525
526 /*
527 * Give initial values to the registers listed in the "Register Space"
528 * section of the HIFN Software Development reference manual.
529 */
530 void
531 hifn_init_pci_registers(sc)
532 struct hifn_softc *sc;
533 {
534 /* write fixed values needed by the Initialization registers */
535 WRITE_REG_0(sc, HIFN_0_PUCTRL, HIFN_PUCTRL_DMAENA);
536 WRITE_REG_0(sc, HIFN_0_FIFOCNFG, HIFN_FIFOCNFG_THRESHOLD);
537 WRITE_REG_0(sc, HIFN_0_PUIER, HIFN_PUIER_DSTOVER);
538
539 /* write all 4 ring address registers */
540 WRITE_REG_1(sc, HIFN_1_DMA_CRAR, vtophys((vaddr_t)sc->sc_dma->cmdr));
541 WRITE_REG_1(sc, HIFN_1_DMA_SRAR, vtophys((vaddr_t)sc->sc_dma->srcr));
542 WRITE_REG_1(sc, HIFN_1_DMA_DRAR, vtophys((vaddr_t)sc->sc_dma->dstr));
543 WRITE_REG_1(sc, HIFN_1_DMA_RRAR, vtophys((vaddr_t)sc->sc_dma->resr));
544
545 /* write status register */
546 WRITE_REG_1(sc, HIFN_1_DMA_CSR, HIFN_DMACSR_D_CTRL_ENA |
547 HIFN_DMACSR_R_CTRL_ENA | HIFN_DMACSR_S_CTRL_ENA |
548 HIFN_DMACSR_C_CTRL_ENA);
549 WRITE_REG_1(sc, HIFN_1_DMA_IER, HIFN_DMAIER_R_DONE);
550
551 #if 0
552 #if BYTE_ORDER == BIG_ENDIAN
553 (0x1 << 7) |
554 #endif
555 #endif
556 WRITE_REG_0(sc, HIFN_0_PUCNFG, HIFN_PUCNFG_COMPSING |
557 HIFN_PUCNFG_DRFR_128 | HIFN_PUCNFG_TCALLPHASES |
558 HIFN_PUCNFG_TCDRVTOTEM | HIFN_PUCNFG_BUS32 |
559 (sc->sc_drammodel ? HIFN_PUCNFG_DRAM : HIFN_PUCNFG_SRAM));
560
561 WRITE_REG_0(sc, HIFN_0_PUISR, HIFN_PUISR_DSTOVER);
562 WRITE_REG_1(sc, HIFN_1_DMA_CNFG, HIFN_DMACNFG_MSTRESET |
563 HIFN_DMACNFG_DMARESET | HIFN_DMACNFG_MODE | HIFN_DMACNFG_LAST |
564 ((HIFN_POLL_FREQUENCY << 16 ) & HIFN_DMACNFG_POLLFREQ) |
565 ((HIFN_POLL_SCALAR << 8) & HIFN_DMACNFG_POLLINVAL));
566 }
567
568 /*
569 * The maximum number of sessions supported by the card
570 * is dependent on the amount of context ram, which
571 * encryption algorithms are enabled, and how compression
572 * is configured. This should be configured before this
573 * routine is called.
574 */
575 void
576 hifn_sessions(sc)
577 struct hifn_softc *sc;
578 {
579 u_int32_t pucnfg;
580 int ctxsize;
581
582 pucnfg = READ_REG_0(sc, HIFN_0_PUCNFG);
583
584 if (pucnfg & HIFN_PUCNFG_COMPSING) {
585 if (pucnfg & HIFN_PUCNFG_ENCCNFG)
586 ctxsize = 128;
587 else
588 ctxsize = 512;
589 sc->sc_maxses = 1 +
590 ((sc->sc_ramsize - 32768) / ctxsize);
591 }
592 else
593 sc->sc_maxses = sc->sc_ramsize / 16384;
594
595 if (sc->sc_maxses > 2048)
596 sc->sc_maxses = 2048;
597 }
598
599 void
600 hifn_ramtype(sc)
601 struct hifn_softc *sc;
602 {
603 u_int8_t data[8], dataexpect[8];
604 int i;
605
606 hifn_reset_board(sc);
607 hifn_init_dma(sc);
608 hifn_init_pci_registers(sc);
609
610 for (i = 0; i < sizeof(data); i++)
611 data[i] = dataexpect[i] = 0x55;
612 if (hifn_writeramaddr(sc, 0, data, 0) < 0)
613 return;
614 if (hifn_readramaddr(sc, 0, data, 1) < 0)
615 return;
616 if (memcmp(data, dataexpect, sizeof(data)) != 0) {
617 sc->sc_drammodel = 1;
618 return;
619 }
620
621 hifn_reset_board(sc);
622 hifn_init_dma(sc);
623 hifn_init_pci_registers(sc);
624
625 for (i = 0; i < sizeof(data); i++)
626 data[i] = dataexpect[i] = 0xaa;
627 if (hifn_writeramaddr(sc, 0, data, 0) < 0)
628 return;
629 if (hifn_readramaddr(sc, 0, data, 1) < 0)
630 return;
631 if (memcmp(data, dataexpect, sizeof(data)) != 0)
632 sc->sc_drammodel = 1;
633 }
634
635 /*
636 * For sram boards, just write/read memory until it fails, also check for
637 * banking.
638 */
639 int
640 hifn_sramsize(sc)
641 struct hifn_softc *sc;
642 {
643 u_int32_t a = 0, end;
644 u_int8_t data[8], dataexpect[8];
645
646 for (a = 0; a < sizeof(data); a++)
647 data[a] = dataexpect[a] = 0x5a;
648
649 hifn_reset_board(sc);
650 hifn_init_dma(sc);
651 hifn_init_pci_registers(sc);
652 end = 1 << 20; /* 1MB */
653 for (a = 0; a < end; a += 16384) {
654 if (hifn_writeramaddr(sc, a, data, 0) < 0)
655 return (0);
656 if (hifn_readramaddr(sc, a, data, 1) < 0)
657 return (0);
658 if (memcmp(data, dataexpect, sizeof(data)) != 0)
659 return (0);
660 hifn_reset_board(sc);
661 hifn_init_dma(sc);
662 hifn_init_pci_registers(sc);
663 sc->sc_ramsize = a + 16384;
664 }
665
666 for (a = 0; a < sizeof(data); a++)
667 data[a] = dataexpect[a] = 0xa5;
668 if (hifn_writeramaddr(sc, 0, data, 0) < 0)
669 return (0);
670
671 end = sc->sc_ramsize;
672 for (a = 0; a < end; a += 16384) {
673 hifn_reset_board(sc);
674 hifn_init_dma(sc);
675 hifn_init_pci_registers(sc);
676 if (hifn_readramaddr(sc, a, data, 0) < 0)
677 return (0);
678 if (a != 0 && memcmp(data, dataexpect, sizeof(data)) == 0)
679 return (0);
680 sc->sc_ramsize = a + 16384;
681 }
682
683 hifn_reset_board(sc);
684 hifn_init_dma(sc);
685 hifn_init_pci_registers(sc);
686
687 return (0);
688 }
689
690 /*
691 * XXX For dram boards, one should really try all of the
692 * HIFN_PUCNFG_DSZ_*'s. This just assumes that PUCNFG
693 * is already set up correctly.
694 */
695 int
696 hifn_dramsize(sc)
697 struct hifn_softc *sc;
698 {
699 u_int32_t cnfg;
700
701 cnfg = READ_REG_0(sc, HIFN_0_PUCNFG) &
702 HIFN_PUCNFG_DRAMMASK;
703 sc->sc_ramsize = 1 << ((cnfg >> 13) + 18);
704 return (0);
705 }
706
707 int
708 hifn_writeramaddr(sc, addr, data, slot)
709 struct hifn_softc *sc;
710 int addr, slot;
711 u_int8_t *data;
712 {
713 struct hifn_dma *dma = sc->sc_dma;
714 hifn_base_command_t wc;
715 const u_int32_t masks = HIFN_D_VALID | HIFN_D_LAST | HIFN_D_MASKDONEIRQ;
716 u_int64_t src, dst;
717
718 wc.masks = 3 << 13;
719 wc.session_num = addr >> 14;
720 wc.total_source_count = 8;
721 wc.total_dest_count = addr & 0x3fff;;
722
723 /* build write command */
724 *(hifn_base_command_t *) sc->sc_dma->command_bufs[slot] = wc;
725 memcpy(&src, data, sizeof(src));
726
727 dma->srcr[slot].p = vtophys((vaddr_t)&src);
728 dma->dstr[slot].p = vtophys((vaddr_t)&dst);
729
730 dma->cmdr[slot].l = 16 | masks;
731 dma->srcr[slot].l = 8 | masks;
732 dma->dstr[slot].l = 8 | masks;
733 dma->resr[slot].l = HIFN_MAX_RESULT | masks;
734
735 DELAY(1000); /* let write command execute */
736 if (dma->resr[slot].l & HIFN_D_VALID) {
737 printf("%s: SRAM/DRAM detection error -- "
738 "result[%d] valid still set\n", sc->sc_dv.dv_xname, slot);
739 return (-1);
740 }
741 return (0);
742 }
743
744 int
745 hifn_readramaddr(sc, addr, data, slot)
746 struct hifn_softc *sc;
747 int addr, slot;
748 u_int8_t *data;
749 {
750 struct hifn_dma *dma = sc->sc_dma;
751 hifn_base_command_t rc;
752 const u_int32_t masks = HIFN_D_VALID | HIFN_D_LAST | HIFN_D_MASKDONEIRQ;
753 u_int64_t src, dst;
754
755 rc.masks = 2 << 13;
756 rc.session_num = addr >> 14;
757 rc.total_source_count = addr & 0x3fff;
758 rc.total_dest_count = 8;
759
760 *(hifn_base_command_t *) sc->sc_dma->command_bufs[slot] = rc;
761
762 dma->srcr[slot].p = vtophys((vaddr_t)&src);
763 dma->dstr[slot].p = vtophys((vaddr_t)&dst);
764 dma->cmdr[slot].l = 16 | masks;
765 dma->srcr[slot].l = 8 | masks;
766 dma->dstr[slot].l = 8 | masks;
767 dma->resr[slot].l = HIFN_MAX_RESULT | masks;
768
769 DELAY(1000); /* let read command execute */
770 if (dma->resr[slot].l & HIFN_D_VALID) {
771 printf("%s: SRAM/DRAM detection error -- "
772 "result[%d] valid still set\n", sc->sc_dv.dv_xname, slot);
773 return (-1);
774 }
775 memcpy(data, &dst, sizeof(dst));
776 return (0);
777 }
778
779 /*
780 * Initialize the descriptor rings.
781 */
782 void
783 hifn_init_dma(sc)
784 struct hifn_softc *sc;
785 {
786 struct hifn_dma *dma = sc->sc_dma;
787 int i;
788
789 /* initialize static pointer values */
790 for (i = 0; i < HIFN_D_CMD_RSIZE; i++)
791 dma->cmdr[i].p = vtophys((vaddr_t)dma->command_bufs[i]);
792 for (i = 0; i < HIFN_D_RES_RSIZE; i++)
793 dma->resr[i].p = vtophys((vaddr_t)dma->result_bufs[i]);
794
795 dma->cmdr[HIFN_D_CMD_RSIZE].p = vtophys((vaddr_t)dma->cmdr);
796 dma->srcr[HIFN_D_SRC_RSIZE].p = vtophys((vaddr_t)dma->srcr);
797 dma->dstr[HIFN_D_DST_RSIZE].p = vtophys((vaddr_t)dma->dstr);
798 dma->resr[HIFN_D_RES_RSIZE].p = vtophys((vaddr_t)dma->resr);
799 dma->cmdu = dma->srcu = dma->dstu = dma->resu = 0;
800 dma->cmdi = dma->srci = dma->dsti = dma->resi = 0;
801 dma->cmdk = dma->srck = dma->dstk = dma->resk = 0;
802 }
803
804 /*
805 * Writes out the raw command buffer space. Returns the
806 * command buffer size.
807 */
808 u_int
809 hifn_write_command(cmd, buf)
810 struct hifn_command *cmd;
811 u_int8_t *buf;
812 {
813 u_int8_t *buf_pos;
814 hifn_base_command_t *base_cmd;
815 hifn_mac_command_t *mac_cmd;
816 hifn_crypt_command_t *cry_cmd;
817 int using_mac, using_crypt, len;
818
819 buf_pos = buf;
820 using_mac = cmd->base_masks & HIFN_BASE_CMD_MAC;
821 using_crypt = cmd->base_masks & HIFN_BASE_CMD_CRYPT;
822
823 base_cmd = (hifn_base_command_t *)buf_pos;
824 base_cmd->masks = cmd->base_masks;
825 base_cmd->total_source_count = cmd->src_l;
826 base_cmd->total_dest_count = cmd->dst_l;
827 base_cmd->session_num = cmd->session_num;
828 buf_pos += sizeof(hifn_base_command_t);
829
830 if (using_mac) {
831 mac_cmd = (hifn_mac_command_t *)buf_pos;
832 mac_cmd->masks = cmd->mac_masks;
833 mac_cmd->header_skip = cmd->mac_header_skip;
834 mac_cmd->source_count = cmd->mac_process_len;
835 buf_pos += sizeof(hifn_mac_command_t);
836 }
837
838 if (using_crypt) {
839 cry_cmd = (hifn_crypt_command_t *)buf_pos;
840 cry_cmd->masks = cmd->cry_masks;
841 cry_cmd->header_skip = cmd->crypt_header_skip;
842 cry_cmd->source_count = cmd->crypt_process_len;
843 buf_pos += sizeof(hifn_crypt_command_t);
844 }
845
846 if (using_mac && mac_cmd->masks & HIFN_MAC_CMD_NEW_KEY) {
847 memcpy(buf_pos, cmd->mac, HIFN_MAC_KEY_LENGTH);
848 buf_pos += HIFN_MAC_KEY_LENGTH;
849 }
850
851 if (using_crypt && cry_cmd->masks & HIFN_CRYPT_CMD_NEW_KEY) {
852 len = (cry_cmd->masks & HIFN_CRYPT_CMD_ALG_3DES) ?
853 HIFN_3DES_KEY_LENGTH : HIFN_DES_KEY_LENGTH;
854 memcpy(buf_pos, cmd->ck, len);
855 buf_pos += len;
856 }
857
858 if (using_crypt && cry_cmd->masks & HIFN_CRYPT_CMD_NEW_IV) {
859 memcpy(buf_pos, cmd->iv, HIFN_IV_LENGTH);
860 buf_pos += HIFN_IV_LENGTH;
861 }
862
863 if ((base_cmd->masks & (HIFN_BASE_CMD_MAC | HIFN_BASE_CMD_CRYPT)) == 0) {
864 memset(buf_pos, 0, 8);
865 buf_pos += 8;
866 }
867
868 return (buf_pos - buf);
869 }
870
871 int
872 hifn_crypto(sc, cmd)
873 struct hifn_softc *sc;
874 struct hifn_command *cmd;
875 {
876 #ifndef __OpenBSD__
877 return -1;
878 #else
879 u_int32_t cmdlen;
880 struct hifn_dma *dma = sc->sc_dma;
881 int cmdi, srci, dsti, resi, nicealign = 0;
882 int s, i;
883
884 if (cmd->src_npa == 0 && cmd->src_m)
885 cmd->src_l = mbuf2pages(cmd->src_m, &cmd->src_npa,
886 cmd->src_packp, cmd->src_packl, MAX_SCATTER, &nicealign);
887 if (cmd->src_l == 0)
888 return (-1);
889
890 if (nicealign == 0) {
891 int totlen, len;
892 struct mbuf *m, *top, **mp;
893
894 totlen = cmd->dst_l = cmd->src_l;
895 if (cmd->src_m->m_flags & M_PKTHDR) {
896 MGETHDR(m, M_DONTWAIT, MT_DATA);
897 M_COPY_PKTHDR(m, cmd->src_m);
898 len = MHLEN;
899 } else {
900 MGET(m, M_DONTWAIT, MT_DATA);
901 len = MLEN;
902 }
903 if (m == NULL)
904 return (-1);
905 if (totlen >= MINCLSIZE) {
906 MCLGET(m, M_DONTWAIT);
907 if (m->m_flags & M_EXT)
908 len = MCLBYTES;
909 }
910 m->m_len = len;
911 top = NULL;
912 mp = ⊤
913
914 while (totlen > 0) {
915 if (top) {
916 MGET(m, M_DONTWAIT, MT_DATA);
917 if (m == NULL) {
918 m_freem(top);
919 return (-1);
920 }
921 len = MLEN;
922 }
923 if (top && totlen >= MINCLSIZE) {
924 MCLGET(m, M_DONTWAIT);
925 if (m->m_flags & M_EXT)
926 len = MCLBYTES;
927 }
928 m->m_len = len;
929 totlen -= len;
930 *mp = m;
931 mp = &m->m_next;
932 }
933 cmd->dst_m = top;
934 }
935 else
936 cmd->dst_m = cmd->src_m;
937
938 cmd->dst_l = mbuf2pages(cmd->dst_m, &cmd->dst_npa,
939 cmd->dst_packp, cmd->dst_packl, MAX_SCATTER, NULL);
940 if (cmd->dst_l == 0)
941 return (-1);
942
943 #ifdef HIFN_DEBUG
944 printf("%s: Entering cmd: stat %8x ien %8x u %d/%d/%d/%d n %d/%d\n",
945 sc->sc_dv.dv_xname,
946 READ_REG_1(sc, HIFN_1_DMA_CSR), READ_REG_1(sc, HIFN_1_DMA_IER),
947 dma->cmdu, dma->srcu, dma->dstu, dma->resu, cmd->src_npa,
948 cmd->dst_npa);
949 #endif
950
951 s = splnet();
952
953 /*
954 * need 1 cmd, and 1 res
955 * need N src, and N dst
956 */
957 if (dma->cmdu+1 > HIFN_D_CMD_RSIZE ||
958 dma->srcu+cmd->src_npa > HIFN_D_SRC_RSIZE ||
959 dma->dstu+cmd->dst_npa > HIFN_D_DST_RSIZE ||
960 dma->resu+1 > HIFN_D_RES_RSIZE) {
961 splx(s);
962 return (HIFN_CRYPTO_RINGS_FULL);
963 }
964
965 if (dma->cmdi == HIFN_D_CMD_RSIZE) {
966 dma->cmdi = 0;
967 dma->cmdr[HIFN_D_CMD_RSIZE].l = HIFN_D_VALID | HIFN_D_LAST |
968 HIFN_D_MASKDONEIRQ | HIFN_D_JUMP;
969 }
970 cmdi = dma->cmdi++;
971
972 if (dma->resi == HIFN_D_RES_RSIZE) {
973 dma->resi = 0;
974 dma->resr[HIFN_D_RES_RSIZE].l = HIFN_D_VALID | HIFN_D_LAST |
975 HIFN_D_MASKDONEIRQ | HIFN_D_JUMP;
976 }
977 resi = dma->resi++;
978
979 cmdlen = hifn_write_command(cmd, dma->command_bufs[cmdi]);
980 #ifdef HIFN_DEBUG
981 printf("write_command %d (nice %d)\n", cmdlen, nicealign);
982 #endif
983 /* .p for command/result already set */
984 dma->cmdr[cmdi].l = cmdlen | HIFN_D_VALID | HIFN_D_LAST |
985 HIFN_D_MASKDONEIRQ;
986 dma->cmdu++;
987
988 /*
989 * We don't worry about missing an interrupt (which a "command wait"
990 * interrupt salvages us from), unless there is more than one command
991 * in the queue.
992 */
993 if (dma->cmdu > 1)
994 WRITE_REG_1(sc, HIFN_1_DMA_IER,
995 HIFN_DMAIER_C_WAIT | HIFN_DMAIER_R_DONE);
996
997 hifnstats.hst_ipackets++;
998
999 for (i = 0; i < cmd->src_npa; i++) {
1000 int last = 0;
1001
1002 if (i == cmd->src_npa-1)
1003 last = HIFN_D_LAST;
1004
1005 if (dma->srci == HIFN_D_SRC_RSIZE) {
1006 srci = 0, dma->srci = 1;
1007 dma->srcr[HIFN_D_SRC_RSIZE].l = HIFN_D_VALID |
1008 HIFN_D_MASKDONEIRQ | HIFN_D_JUMP | HIFN_D_LAST;
1009 } else
1010 srci = dma->srci++;
1011 dma->srcr[srci].p = cmd->src_packp[i];
1012 dma->srcr[srci].l = cmd->src_packl[i] | HIFN_D_VALID |
1013 HIFN_D_MASKDONEIRQ | last;
1014 hifnstats.hst_ibytes += cmd->src_packl[i];
1015 }
1016 dma->srcu += cmd->src_npa;
1017
1018 for (i = 0; i < cmd->dst_npa; i++) {
1019 int last = 0;
1020
1021 if (i == cmd->dst_npa-1)
1022 last = HIFN_D_LAST;
1023
1024 if (dma->dsti == HIFN_D_DST_RSIZE) {
1025 dsti = 0, dma->dsti = 1;
1026 dma->dstr[HIFN_D_DST_RSIZE].l = HIFN_D_VALID |
1027 HIFN_D_MASKDONEIRQ | HIFN_D_JUMP | HIFN_D_LAST;
1028 } else
1029 dsti = dma->dsti++;
1030 dma->dstr[dsti].p = cmd->dst_packp[i];
1031 dma->dstr[dsti].l = cmd->dst_packl[i] | HIFN_D_VALID |
1032 HIFN_D_MASKDONEIRQ | last;
1033 }
1034 dma->dstu += cmd->dst_npa;
1035
1036 /*
1037 * Unlike other descriptors, we don't mask done interrupt from
1038 * result descriptor.
1039 */
1040 #ifdef HIFN_DEBUG
1041 printf("load res\n");
1042 #endif
1043 dma->hifn_commands[resi] = cmd;
1044 dma->resr[resi].l = HIFN_MAX_RESULT | HIFN_D_VALID | HIFN_D_LAST;
1045 dma->resu++;
1046
1047 #ifdef HIFN_DEBUG
1048 printf("%s: command: stat %8x ier %8x\n",
1049 sc->sc_dv.dv_xname,
1050 READ_REG_1(sc, HIFN_1_DMA_CSR), READ_REG_1(sc, HIFN_1_DMA_IER));
1051 #endif
1052
1053 splx(s);
1054 return 0; /* success */
1055 #endif
1056 }
1057
1058 int
1059 hifn_intr(arg)
1060 void *arg;
1061 {
1062 struct hifn_softc *sc = arg;
1063 struct hifn_dma *dma = sc->sc_dma;
1064 u_int32_t dmacsr;
1065 int i, u;
1066
1067 dmacsr = READ_REG_1(sc, HIFN_1_DMA_CSR);
1068
1069 #ifdef HIFN_DEBUG
1070 printf("%s: irq: stat %08x ien %08x u %d/%d/%d/%d\n",
1071 sc->sc_dv.dv_xname,
1072 dmacsr, READ_REG_1(sc, HIFN_1_DMA_IER),
1073 dma->cmdu, dma->srcu, dma->dstu, dma->resu);
1074 #endif
1075
1076 if ((dmacsr & (HIFN_DMACSR_R_DONE | HIFN_DMACSR_C_WAIT)) == 0)
1077 return (0);
1078
1079 if (dma->resu > HIFN_D_RES_RSIZE)
1080 printf("%s: Internal Error -- ring overflow\n",
1081 sc->sc_dv.dv_xname);
1082
1083 if ((dmacsr & HIFN_DMACSR_C_WAIT) && (dma->cmdu == 0)) {
1084 /*
1085 * If no slots to process and we receive a "waiting on
1086 * command" interrupt, we disable the "waiting on command"
1087 * (by clearing it).
1088 */
1089 WRITE_REG_1(sc, HIFN_1_DMA_IER, HIFN_DMAIER_R_DONE);
1090 }
1091
1092 while (dma->resu > 0) {
1093 struct hifn_command *cmd;
1094 u_int8_t *macbuf = NULL;
1095
1096 cmd = dma->hifn_commands[dma->resk];
1097
1098 /* if still valid, stop processing */
1099 if (dma->resr[dma->resk].l & HIFN_D_VALID)
1100 break;
1101
1102 if (cmd->base_masks & HIFN_BASE_CMD_MAC) {
1103 macbuf = dma->result_bufs[dma->resk];
1104 macbuf += 12;
1105 }
1106
1107 #ifdef __OpenBSD__
1108 hifn_callback(sc, cmd, macbuf);
1109 #endif
1110
1111 if (++dma->resk == HIFN_D_RES_RSIZE)
1112 dma->resk = 0;
1113 dma->resu--;
1114 hifnstats.hst_opackets++;
1115 }
1116
1117 /* clear the rings */
1118
1119 i = dma->srck; u = dma->srcu;
1120 while (u != 0 && (dma->srcr[i].l & HIFN_D_VALID) == 0) {
1121 if (++i == HIFN_D_SRC_RSIZE)
1122 i = 0;
1123 u--;
1124 }
1125 dma->srck = i; dma->srcu = u;
1126
1127 i = dma->cmdk; u = dma->cmdu;
1128 while (u != 0 && (dma->cmdr[i].l & HIFN_D_VALID) == 0) {
1129 if (++i == HIFN_D_CMD_RSIZE)
1130 i = 0;
1131 u--;
1132 }
1133 dma->cmdk = i; dma->cmdu = u;
1134
1135 /*
1136 * Clear "result done" and "command wait" flags in status register.
1137 * If we still have slots to process and we received a "command wait"
1138 * interrupt, this will interupt us again.
1139 */
1140 WRITE_REG_1(sc, HIFN_1_DMA_CSR, HIFN_DMACSR_R_DONE|HIFN_DMACSR_C_WAIT);
1141 return (1);
1142 }
1143
1144 #ifdef __OpenBSD__
1145 /*
1146 * Allocate a new 'session' and return an encoded session id. 'sidp'
1147 * contains our registration id, and should contain an encoded session
1148 * id on successful allocation.
1149 */
1150 int
1151 hifn_newsession(sidp, cri)
1152 u_int32_t *sidp;
1153 struct cryptoini *cri;
1154 {
1155 struct cryptoini *c;
1156 struct hifn_softc *sc = NULL;
1157 int i, mac = 0, cry = 0;
1158
1159 if (sidp == NULL || cri == NULL)
1160 return (EINVAL);
1161
1162 for (i = 0; i < hifn_cd.cd_ndevs; i++) {
1163 sc = hifn_cd.cd_devs[i];
1164 if (sc == NULL)
1165 break;
1166 if (sc->sc_cid == (*sidp))
1167 break;
1168 }
1169 if (sc == NULL)
1170 return (EINVAL);
1171
1172 for (i = 0; i < sc->sc_maxses; i++)
1173 if (sc->sc_sessions[i].hs_flags == 0)
1174 break;
1175 if (i == sc->sc_maxses)
1176 return (ENOMEM);
1177
1178 for (c = cri; c != NULL; c = c->cri_next) {
1179 if (c->cri_alg == CRYPTO_MD5_HMAC96 ||
1180 c->cri_alg == CRYPTO_SHA1_HMAC96) {
1181 if (mac)
1182 return (EINVAL);
1183 mac = 1;
1184 } else if (c->cri_alg == CRYPTO_DES_CBC ||
1185 c->cri_alg == CRYPTO_3DES_CBC) {
1186 if (cry)
1187 return (EINVAL);
1188 cry = 1;
1189 }
1190 else
1191 return (EINVAL);
1192 }
1193 if (mac == 0 && cry == 0)
1194 return (EINVAL);
1195
1196 *sidp = HIFN_SID(sc->sc_dv.dv_unit, i);
1197 sc->sc_sessions[i].hs_flags = 1;
1198 get_random_bytes(sc->sc_sessions[i].hs_iv, HIFN_IV_LENGTH);
1199
1200 return (0);
1201 }
1202
1203 /*
1204 * Deallocate a session.
1205 * XXX this routine should run a zero'd mac/encrypt key into context ram.
1206 * XXX to blow away any keys already stored there.
1207 */
1208 int
1209 hifn_freesession(tid)
1210 u_int64_t tid;
1211 {
1212 struct hifn_softc *sc;
1213 int card, session;
1214 u_int32_t sid = ((u_int32_t) tid) & 0xffffffff;
1215
1216 card = HIFN_CARD(sid);
1217 if (card >= hifn_cd.cd_ndevs || hifn_cd.cd_devs[card] == NULL)
1218 return (EINVAL);
1219
1220 sc = hifn_cd.cd_devs[card];
1221 session = HIFN_SESSION(sid);
1222 if (session >= sc->sc_maxses)
1223 return (EINVAL);
1224
1225 memset(&sc->sc_sessions[session], 0, sizeof(sc->sc_sessions[session]));
1226 return (0);
1227 }
1228
1229 int
1230 hifn_process(crp)
1231 struct cryptop *crp;
1232 {
1233 struct hifn_command *cmd = NULL;
1234 int card, session, err;
1235 struct hifn_softc *sc;
1236 struct cryptodesc *crd1, *crd2, *maccrd, *enccrd;
1237
1238 if (crp == NULL || crp->crp_callback == NULL) {
1239 hifnstats.hst_invalid++;
1240 return (EINVAL);
1241 }
1242
1243 card = HIFN_CARD(crp->crp_sid);
1244 if (card >= hifn_cd.cd_ndevs || hifn_cd.cd_devs[card] == NULL) {
1245 err = EINVAL;
1246 goto errout;
1247 }
1248
1249 sc = hifn_cd.cd_devs[card];
1250 session = HIFN_SESSION(crp->crp_sid);
1251 if (session >= sc->sc_maxses) {
1252 err = EINVAL;
1253 goto errout;
1254 }
1255
1256 cmd = (struct hifn_command *)malloc(sizeof(struct hifn_command),
1257 M_DEVBUF, M_NOWAIT);
1258 if (cmd == NULL) {
1259 err = ENOMEM;
1260 goto errout;
1261 }
1262 memset(cmd, 0, sizeof(struct hifn_command));
1263
1264 if (crp->crp_flags & CRYPTO_F_IMBUF) {
1265 cmd->src_m = (struct mbuf *)crp->crp_buf;
1266 cmd->dst_m = (struct mbuf *)crp->crp_buf;
1267 } else {
1268 err = EINVAL;
1269 goto errout; /* XXX only handle mbufs right now */
1270 }
1271
1272 crd1 = crp->crp_desc;
1273 if (crd1 == NULL) {
1274 err = EINVAL;
1275 goto errout;
1276 }
1277 crd2 = crd1->crd_next;
1278
1279 if (crd2 == NULL) {
1280 if (crd1->crd_alg == CRYPTO_MD5_HMAC96 ||
1281 crd1->crd_alg == CRYPTO_SHA1_HMAC96) {
1282 maccrd = crd1;
1283 enccrd = NULL;
1284 } else if (crd1->crd_alg == CRYPTO_DES_CBC ||
1285 crd1->crd_alg == CRYPTO_3DES_CBC) {
1286 if ((crd1->crd_flags & CRD_F_ENCRYPT) == 0)
1287 cmd->base_masks |= HIFN_BASE_CMD_DECODE;
1288 maccrd = NULL;
1289 enccrd = crd1;
1290 } else {
1291 err = EINVAL;
1292 goto errout;
1293 }
1294 } else {
1295 if ((crd1->crd_alg == CRYPTO_MD5_HMAC96 ||
1296 crd1->crd_alg == CRYPTO_SHA1_HMAC96) &&
1297 (crd2->crd_alg == CRYPTO_DES_CBC ||
1298 crd2->crd_alg == CRYPTO_3DES_CBC) &&
1299 ((crd2->crd_flags & CRD_F_ENCRYPT) == 0)) {
1300 cmd->base_masks = HIFN_BASE_CMD_DECODE;
1301 maccrd = crd1;
1302 enccrd = crd2;
1303 } else if ((crd1->crd_alg == CRYPTO_DES_CBC ||
1304 crd1->crd_alg == CRYPTO_3DES_CBC) &&
1305 (crd2->crd_alg == CRYPTO_MD5_HMAC96 ||
1306 crd2->crd_alg == CRYPTO_SHA1_HMAC96) &&
1307 (crd1->crd_flags & CRD_F_ENCRYPT)) {
1308 enccrd = crd1;
1309 maccrd = crd2;
1310 } else {
1311 /*
1312 * We cannot order the 7751 as requested
1313 */
1314 err = EINVAL;
1315 goto errout;
1316 }
1317 }
1318
1319 if (enccrd) {
1320 cmd->base_masks |= HIFN_BASE_CMD_CRYPT;
1321 cmd->cry_masks |= HIFN_CRYPT_CMD_MODE_CBC |
1322 HIFN_CRYPT_CMD_NEW_IV;
1323 if (enccrd->crd_flags & CRD_F_ENCRYPT) {
1324 if (enccrd->crd_flags & CRD_F_IV_EXPLICIT)
1325 memcpy(cmd->iv, enccrd->crd_iv, HIFN_IV_LENGTH);
1326 else
1327 memcpy(cmd->iv, sc->sc_sessions[session].hs_iv,
1328 HIFN_IV_LENGTH);
1329
1330 if ((enccrd->crd_flags & CRD_F_IV_PRESENT) == 0)
1331 m_copyback(cmd->src_m, enccrd->crd_inject,
1332 HIFN_IV_LENGTH, cmd->iv);
1333 } else {
1334 if (enccrd->crd_flags & CRD_F_IV_EXPLICIT)
1335 memcpy(cmd->iv, enccrd->crd_iv, HIFN_IV_LENGTH);
1336 else
1337 m_copydata(cmd->src_m, enccrd->crd_inject,
1338 HIFN_IV_LENGTH, cmd->iv);
1339 }
1340
1341 if (enccrd->crd_alg == CRYPTO_DES_CBC)
1342 cmd->cry_masks |= HIFN_CRYPT_CMD_ALG_DES;
1343 else
1344 cmd->cry_masks |= HIFN_CRYPT_CMD_ALG_3DES;
1345
1346 cmd->crypt_header_skip = enccrd->crd_skip;
1347 cmd->crypt_process_len = enccrd->crd_len;
1348 cmd->ck = enccrd->crd_key;
1349
1350 if (sc->sc_sessions[session].hs_flags == 1)
1351 cmd->cry_masks |= HIFN_CRYPT_CMD_NEW_KEY;
1352 }
1353
1354 if (maccrd) {
1355 cmd->base_masks |= HIFN_BASE_CMD_MAC;
1356 cmd->mac_masks |= HIFN_MAC_CMD_RESULT |
1357 HIFN_MAC_CMD_MODE_HMAC | HIFN_MAC_CMD_RESULT |
1358 HIFN_MAC_CMD_POS_IPSEC | HIFN_MAC_CMD_TRUNC;
1359
1360 if (maccrd->crd_alg == CRYPTO_MD5_HMAC96)
1361 cmd->mac_masks |= HIFN_MAC_CMD_ALG_MD5;
1362 else
1363 cmd->mac_masks |= HIFN_MAC_CMD_ALG_SHA1;
1364
1365 if (sc->sc_sessions[session].hs_flags == 1) {
1366 cmd->mac_masks |= HIFN_MAC_CMD_NEW_KEY;
1367 memcpy(cmd->mac, maccrd->crd_key,
1368 maccrd->crd_klen >> 3);
1369 memset(cmd->mac + (maccrd->crd_klen >> 3), 0,
1370 HIFN_MAC_KEY_LENGTH - (maccrd->crd_klen >> 3));
1371 }
1372
1373 cmd->mac_header_skip = maccrd->crd_skip;
1374 cmd->mac_process_len = maccrd->crd_len;
1375 }
1376
1377 if (sc->sc_sessions[session].hs_flags == 1)
1378 sc->sc_sessions[session].hs_flags = 2;
1379
1380 cmd->private_data = (u_long)crp;
1381 cmd->session_num = session;
1382 cmd->softc = sc;
1383
1384 if (hifn_crypto(sc, cmd) == 0)
1385 return (0);
1386
1387 err = ENOMEM;
1388
1389 errout:
1390 if (cmd != NULL)
1391 free(cmd, M_DEVBUF);
1392 if (err == EINVAL)
1393 hifnstats.hst_invalid++;
1394 else
1395 hifnstats.hst_nomem++;
1396 crp->crp_etype = err;
1397 crp->crp_callback(crp);
1398 return (0);
1399 }
1400
1401 void
1402 hifn_callback(sc, cmd, macbuf)
1403 struct hifn_softc *sc;
1404 struct hifn_command *cmd;
1405 u_int8_t *macbuf;
1406 {
1407 struct hifn_dma *dma = sc->sc_dma;
1408 struct cryptop *crp = (struct cryptop *)cmd->private_data;
1409 struct cryptodesc *crd;
1410 struct mbuf *m;
1411 int totlen;
1412
1413 if ((crp->crp_flags & CRYPTO_F_IMBUF) && (cmd->src_m != cmd->dst_m)) {
1414 m_freem(cmd->src_m);
1415 crp->crp_buf = (caddr_t)cmd->dst_m;
1416 }
1417
1418 if ((m = cmd->dst_m) != NULL) {
1419 totlen = cmd->src_l;
1420 hifnstats.hst_obytes += totlen;
1421 while (m) {
1422 if (totlen < m->m_len) {
1423 m->m_len = totlen;
1424 totlen = 0;
1425 } else
1426 totlen -= m->m_len;
1427 m = m->m_next;
1428 if (++dma->dstk == HIFN_D_DST_RSIZE)
1429 dma->dstk = 0;
1430 dma->dstu--;
1431 }
1432 } else {
1433 hifnstats.hst_obytes += dma->dstr[dma->dstk].l & HIFN_D_LENGTH;
1434 if (++dma->dstk == HIFN_D_DST_RSIZE)
1435 dma->dstk = 0;
1436 dma->dstu--;
1437 }
1438
1439 if ((cmd->base_masks & (HIFN_BASE_CMD_CRYPT | HIFN_BASE_CMD_DECODE)) ==
1440 HIFN_BASE_CMD_CRYPT) {
1441 for (crd = crp->crp_desc; crd; crd = crd->crd_next) {
1442 if (crd->crd_alg != CRYPTO_DES_CBC &&
1443 crd->crd_alg != CRYPTO_3DES_CBC)
1444 continue;
1445 m_copydata((struct mbuf *)crp->crp_buf,
1446 crd->crd_skip + crd->crd_len - HIFN_IV_LENGTH,
1447 HIFN_IV_LENGTH,
1448 cmd->softc->sc_sessions[cmd->session_num].hs_iv);
1449 break;
1450 }
1451 }
1452
1453 if (macbuf != NULL) {
1454 for (crd = crp->crp_desc; crd; crd = crd->crd_next) {
1455 if (crd->crd_alg != CRYPTO_MD5_HMAC96 &&
1456 crd->crd_alg != CRYPTO_SHA1_HMAC96)
1457 continue;
1458 m_copyback((struct mbuf *)crp->crp_buf,
1459 crd->crd_inject, 12, macbuf);
1460 break;
1461 }
1462 }
1463
1464 free(cmd, M_DEVBUF);
1465 crypto_done(crp);
1466 }
1467 #endif
1468