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