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