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