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