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