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