[package] kernel/modules: move ixp4xx hardware crypto module package into crypto.mk
[openwrt/svn-archive/archive.git] / target / linux / generic-2.6 / patches-2.6.26 / 970-ocf_20080704.patch
1 --- a/crypto/Kconfig
2 +++ b/crypto/Kconfig
3 @@ -678,3 +678,6 @@ config CRYPTO_PRNG
4 source "drivers/crypto/Kconfig"
5
6 endif # if CRYPTO
7 +
8 +source "crypto/ocf/Kconfig"
9 +
10 --- a/crypto/Makefile
11 +++ b/crypto/Makefile
12 @@ -72,6 +72,8 @@ obj-$(CONFIG_CRYPTO_LZO) += lzo.o
13 obj-$(CONFIG_CRYPTO_PRNG) += prng.o
14 obj-$(CONFIG_CRYPTO_TEST) += tcrypt.o
15
16 +obj-$(CONFIG_OCF_OCF) += ocf/
17 +
18 #
19 # generic algorithms and the async_tx api
20 #
21 --- a/drivers/char/random.c
22 +++ b/drivers/char/random.c
23 @@ -129,6 +129,9 @@
24 * unsigned int value);
25 * void add_interrupt_randomness(int irq);
26 *
27 + * void random_input_words(__u32 *buf, size_t wordcount, int ent_count)
28 + * int random_input_wait(void);
29 + *
30 * add_input_randomness() uses the input layer interrupt timing, as well as
31 * the event type information from the hardware.
32 *
33 @@ -140,6 +143,13 @@
34 * a better measure, since the timing of the disk interrupts are more
35 * unpredictable.
36 *
37 + * random_input_words() just provides a raw block of entropy to the input
38 + * pool, such as from a hardware entropy generator.
39 + *
40 + * random_input_wait() suspends the caller until such time as the
41 + * entropy pool falls below the write threshold, and returns a count of how
42 + * much entropy (in bits) is needed to sustain the pool.
43 + *
44 * All of these routines try to estimate how many bits of randomness a
45 * particular randomness source. They do this by keeping track of the
46 * first and second order deltas of the event timings.
47 @@ -667,6 +677,61 @@ void add_disk_randomness(struct gendisk
48 }
49 #endif
50
51 +/*
52 + * random_input_words - add bulk entropy to pool
53 + *
54 + * @buf: buffer to add
55 + * @wordcount: number of __u32 words to add
56 + * @ent_count: total amount of entropy (in bits) to credit
57 + *
58 + * this provides bulk input of entropy to the input pool
59 + *
60 + */
61 +void random_input_words(__u32 *buf, size_t wordcount, int ent_count)
62 +{
63 + mix_pool_bytes(&input_pool, buf, wordcount);
64 +
65 + credit_entropy_bits(&input_pool, ent_count);
66 +
67 + DEBUG_ENT("crediting %d bits => %d\n",
68 + ent_count, input_pool.entropy_count);
69 + /*
70 + * Wake up waiting processes if we have enough
71 + * entropy.
72 + */
73 + if (input_pool.entropy_count >= random_read_wakeup_thresh)
74 + wake_up_interruptible(&random_read_wait);
75 +}
76 +EXPORT_SYMBOL(random_input_words);
77 +
78 +/*
79 + * random_input_wait - wait until random needs entropy
80 + *
81 + * this function sleeps until the /dev/random subsystem actually
82 + * needs more entropy, and then return the amount of entropy
83 + * that it would be nice to have added to the system.
84 + */
85 +int random_input_wait(void)
86 +{
87 + int count;
88 +
89 + wait_event_interruptible(random_write_wait,
90 + input_pool.entropy_count < random_write_wakeup_thresh);
91 +
92 + count = random_write_wakeup_thresh - input_pool.entropy_count;
93 +
94 + /* likely we got woken up due to a signal */
95 + if (count <= 0) count = random_read_wakeup_thresh;
96 +
97 + DEBUG_ENT("requesting %d bits from input_wait()er %d<%d\n",
98 + count,
99 + input_pool.entropy_count, random_write_wakeup_thresh);
100 +
101 + return count;
102 +}
103 +EXPORT_SYMBOL(random_input_wait);
104 +
105 +
106 #define EXTRACT_SIZE 10
107
108 /*********************************************************************
109 --- a/fs/fcntl.c
110 +++ b/fs/fcntl.c
111 @@ -191,6 +191,7 @@ asmlinkage long sys_dup(unsigned int fil
112 ret = dupfd(file, 0, 0);
113 return ret;
114 }
115 +EXPORT_SYMBOL(sys_dup);
116
117 #define SETFL_MASK (O_APPEND | O_NONBLOCK | O_NDELAY | FASYNC | O_DIRECT | O_NOATIME)
118
119 --- a/include/linux/miscdevice.h
120 +++ b/include/linux/miscdevice.h
121 @@ -12,6 +12,7 @@
122 #define APOLLO_MOUSE_MINOR 7
123 #define PC110PAD_MINOR 9
124 /*#define ADB_MOUSE_MINOR 10 FIXME OBSOLETE */
125 +#define CRYPTODEV_MINOR 70 /* /dev/crypto */
126 #define WATCHDOG_MINOR 130 /* Watchdog timer */
127 #define TEMP_MINOR 131 /* Temperature Sensor */
128 #define RTC_MINOR 135
129 --- a/include/linux/random.h
130 +++ b/include/linux/random.h
131 @@ -8,6 +8,7 @@
132 #define _LINUX_RANDOM_H
133
134 #include <linux/ioctl.h>
135 +#include <linux/types.h> /* for __u32 in user space */
136
137 /* ioctl()'s for the random number generator */
138
139 @@ -32,6 +33,30 @@
140 /* Clear the entropy pool and associated counters. (Superuser only.) */
141 #define RNDCLEARPOOL _IO( 'R', 0x06 )
142
143 +#ifdef CONFIG_FIPS_RNG
144 +
145 +/* Size of seed value - equal to AES blocksize */
146 +#define AES_BLOCK_SIZE_BYTES 16
147 +#define SEED_SIZE_BYTES AES_BLOCK_SIZE_BYTES
148 +/* Size of AES key */
149 +#define KEY_SIZE_BYTES 16
150 +
151 +/* ioctl() structure used by FIPS 140-2 Tests */
152 +struct rand_fips_test {
153 + unsigned char key[KEY_SIZE_BYTES]; /* Input */
154 + unsigned char datetime[SEED_SIZE_BYTES]; /* Input */
155 + unsigned char seed[SEED_SIZE_BYTES]; /* Input */
156 + unsigned char result[SEED_SIZE_BYTES]; /* Output */
157 +};
158 +
159 +/* FIPS 140-2 RNG Variable Seed Test. (Superuser only.) */
160 +#define RNDFIPSVST _IOWR('R', 0x10, struct rand_fips_test)
161 +
162 +/* FIPS 140-2 RNG Monte Carlo Test. (Superuser only.) */
163 +#define RNDFIPSMCT _IOWR('R', 0x11, struct rand_fips_test)
164 +
165 +#endif /* #ifdef CONFIG_FIPS_RNG */
166 +
167 struct rand_pool_info {
168 int entropy_count;
169 int buf_size;
170 @@ -48,6 +73,10 @@ extern void add_input_randomness(unsigne
171 unsigned int value);
172 extern void add_interrupt_randomness(int irq);
173
174 +extern void random_input_words(__u32 *buf, size_t wordcount, int ent_count);
175 +extern int random_input_wait(void);
176 +#define HAS_RANDOM_INPUT_WAIT 1
177 +
178 extern void get_random_bytes(void *buf, int nbytes);
179 void generate_random_uuid(unsigned char uuid_out[16]);
180
181 --- /dev/null
182 +++ b/crypto/ocf/hifn/Makefile
183 @@ -0,0 +1,13 @@
184 +# for SGlinux builds
185 +-include $(ROOTDIR)/modules/.config
186 +
187 +obj-$(CONFIG_OCF_HIFN) += hifn7751.o
188 +obj-$(CONFIG_OCF_HIFNHIPP) += hifnHIPP.o
189 +
190 +obj ?= .
191 +EXTRA_CFLAGS += -I$(obj)/.. -I$(obj)/
192 +
193 +ifdef TOPDIR
194 +-include $(TOPDIR)/Rules.make
195 +endif
196 +
197 --- /dev/null
198 +++ b/crypto/ocf/safe/Makefile
199 @@ -0,0 +1,12 @@
200 +# for SGlinux builds
201 +-include $(ROOTDIR)/modules/.config
202 +
203 +obj-$(CONFIG_OCF_SAFE) += safe.o
204 +
205 +obj ?= .
206 +EXTRA_CFLAGS += -I$(obj)/.. -I$(obj)/
207 +
208 +ifdef TOPDIR
209 +-include $(TOPDIR)/Rules.make
210 +endif
211 +
212 --- /dev/null
213 +++ b/crypto/ocf/Makefile
214 @@ -0,0 +1,120 @@
215 +# for SGlinux builds
216 +-include $(ROOTDIR)/modules/.config
217 +
218 +OCF_OBJS = crypto.o criov.o
219 +
220 +ifdef CONFIG_OCF_RANDOMHARVEST
221 + OCF_OBJS += random.o
222 +endif
223 +
224 +ifdef CONFIG_OCF_FIPS
225 + OCF_OBJS += rndtest.o
226 +endif
227 +
228 +# Add in autoconf.h to get #defines for CONFIG_xxx
229 +AUTOCONF_H=$(ROOTDIR)/modules/autoconf.h
230 +ifeq ($(AUTOCONF_H), $(wildcard $(AUTOCONF_H)))
231 + EXTRA_CFLAGS += -include $(AUTOCONF_H)
232 + export EXTRA_CFLAGS
233 +endif
234 +
235 +ifndef obj
236 + obj ?= .
237 + _obj = subdir
238 + mod-subdirs := safe hifn ixp4xx talitos ocfnull
239 + export-objs += crypto.o criov.o random.o
240 + list-multi += ocf.o
241 + _slash :=
242 +else
243 + _obj = obj
244 + _slash := /
245 +endif
246 +
247 +EXTRA_CFLAGS += -I$(obj)/.
248 +
249 +obj-$(CONFIG_OCF_OCF) += ocf.o
250 +obj-$(CONFIG_OCF_CRYPTODEV) += cryptodev.o
251 +obj-$(CONFIG_OCF_CRYPTOSOFT) += cryptosoft.o
252 +obj-$(CONFIG_OCF_BENCH) += ocf-bench.o
253 +
254 +$(_obj)-$(CONFIG_OCF_SAFE) += safe$(_slash)
255 +$(_obj)-$(CONFIG_OCF_HIFN) += hifn$(_slash)
256 +$(_obj)-$(CONFIG_OCF_IXP4XX) += ixp4xx$(_slash)
257 +$(_obj)-$(CONFIG_OCF_TALITOS) += talitos$(_slash)
258 +$(_obj)-$(CONFIG_OCF_PASEMI) += pasemi$(_slash)
259 +$(_obj)-$(CONFIG_OCF_OCFNULL) += ocfnull$(_slash)
260 +
261 +ocf-objs := $(OCF_OBJS)
262 +
263 +$(list-multi) dummy1: $(ocf-objs)
264 + $(LD) -r -o $@ $(ocf-objs)
265 +
266 +.PHONY:
267 +clean:
268 + rm -f *.o *.ko .*.o.flags .*.ko.cmd .*.o.cmd .*.mod.o.cmd *.mod.c
269 + rm -f */*.o */*.ko */.*.o.cmd */.*.ko.cmd */.*.mod.o.cmd */*.mod.c */.*.o.flags
270 +
271 +ifdef TOPDIR
272 +-include $(TOPDIR)/Rules.make
273 +endif
274 +
275 +#
276 +# release gen targets
277 +#
278 +
279 +.PHONY: patch
280 +patch:
281 + REL=`date +%Y%m%d`; \
282 + patch=ocf-linux-$$REL.patch; \
283 + patch24=ocf-linux-24-$$REL.patch; \
284 + patch26=ocf-linux-26-$$REL.patch; \
285 + ( \
286 + find . -name Makefile; \
287 + find . -name Config.in; \
288 + find . -name Kconfig; \
289 + find . -name README; \
290 + find . -name '*.[ch]' | grep -v '.mod.c'; \
291 + ) | while read t; do \
292 + diff -Nau /dev/null $$t | sed 's?^+++ \./?+++ linux/crypto/ocf/?'; \
293 + done > $$patch; \
294 + cat patches/linux-2.4.35-ocf.patch $$patch > $$patch24; \
295 + cat patches/linux-2.6.25-ocf.patch $$patch > $$patch26
296 +
297 +.PHONY: tarball
298 +tarball:
299 + REL=`date +%Y%m%d`; RELDIR=/tmp/ocf-linux-$$REL; \
300 + CURDIR=`pwd`; \
301 + rm -rf /tmp/ocf-linux-$$REL*; \
302 + mkdir -p $$RELDIR/tools; \
303 + cp README* $$RELDIR; \
304 + cp patches/openss*.patch $$RELDIR; \
305 + cp patches/crypto-tools.patch $$RELDIR; \
306 + cp tools/[!C]* $$RELDIR/tools; \
307 + cd ..; \
308 + tar cvf $$RELDIR/ocf-linux.tar \
309 + --exclude=CVS \
310 + --exclude=.* \
311 + --exclude=*.o \
312 + --exclude=*.ko \
313 + --exclude=*.mod.* \
314 + --exclude=README* \
315 + --exclude=ocf-*.patch \
316 + --exclude=ocf/patches/openss*.patch \
317 + --exclude=ocf/patches/crypto-tools.patch \
318 + --exclude=ocf/tools \
319 + ocf; \
320 + gzip -9 $$RELDIR/ocf-linux.tar; \
321 + cd /tmp; \
322 + tar cvf ocf-linux-$$REL.tar ocf-linux-$$REL; \
323 + gzip -9 ocf-linux-$$REL.tar; \
324 + cd $$CURDIR/../../user; \
325 + rm -rf /tmp/crypto-tools-$$REL*; \
326 + tar cvf /tmp/crypto-tools-$$REL.tar \
327 + --exclude=CVS \
328 + --exclude=.* \
329 + --exclude=*.o \
330 + --exclude=cryptotest \
331 + --exclude=cryptokeytest \
332 + crypto-tools; \
333 + gzip -9 /tmp/crypto-tools-$$REL.tar
334 +
335 --- /dev/null
336 +++ b/crypto/ocf/talitos/Makefile
337 @@ -0,0 +1,12 @@
338 +# for SGlinux builds
339 +-include $(ROOTDIR)/modules/.config
340 +
341 +obj-$(CONFIG_OCF_TALITOS) += talitos.o
342 +
343 +obj ?= .
344 +EXTRA_CFLAGS += -I$(obj)/.. -I$(obj)/
345 +
346 +ifdef TOPDIR
347 +-include $(TOPDIR)/Rules.make
348 +endif
349 +
350 --- /dev/null
351 +++ b/crypto/ocf/ixp4xx/Makefile
352 @@ -0,0 +1,104 @@
353 +# for SGlinux builds
354 +-include $(ROOTDIR)/modules/.config
355 +
356 +#
357 +# You will need to point this at your Intel ixp425 includes, this portion
358 +# of the Makefile only really works under SGLinux with the appropriate libs
359 +# installed. They can be downloaded from http://www.snapgear.org/
360 +#
361 +ifeq ($(CONFIG_CPU_IXP46X),y)
362 +IXPLATFORM = ixp46X
363 +else
364 +ifeq ($(CONFIG_CPU_IXP43X),y)
365 +IXPLATFORM = ixp43X
366 +else
367 +IXPLATFORM = ixp42X
368 +endif
369 +endif
370 +
371 +ifdef CONFIG_IXP400_LIB_2_4
372 +IX_XSCALE_SW = $(ROOTDIR)/modules/ixp425/ixp400-2.4/ixp400_xscale_sw
373 +OSAL_DIR = $(ROOTDIR)/modules/ixp425/ixp400-2.4/ixp_osal
374 +endif
375 +ifdef CONFIG_IXP400_LIB_2_1
376 +IX_XSCALE_SW = $(ROOTDIR)/modules/ixp425/ixp400-2.1/ixp400_xscale_sw
377 +OSAL_DIR = $(ROOTDIR)/modules/ixp425/ixp400-2.1/ixp_osal
378 +endif
379 +ifdef CONFIG_IXP400_LIB_2_0
380 +IX_XSCALE_SW = $(ROOTDIR)/modules/ixp425/ixp400-2.0/ixp400_xscale_sw
381 +OSAL_DIR = $(ROOTDIR)/modules/ixp425/ixp400-2.0/ixp_osal
382 +endif
383 +ifdef IX_XSCALE_SW
384 +ifdef CONFIG_IXP400_LIB_2_4
385 +IXP_CFLAGS = \
386 + -I$(ROOTDIR)/. \
387 + -I$(IX_XSCALE_SW)/src/include \
388 + -I$(OSAL_DIR)/common/include/ \
389 + -I$(OSAL_DIR)/common/include/modules/ \
390 + -I$(OSAL_DIR)/common/include/modules/ddk/ \
391 + -I$(OSAL_DIR)/common/include/modules/bufferMgt/ \
392 + -I$(OSAL_DIR)/common/include/modules/ioMem/ \
393 + -I$(OSAL_DIR)/common/os/linux/include/ \
394 + -I$(OSAL_DIR)/common/os/linux/include/core/ \
395 + -I$(OSAL_DIR)/common/os/linux/include/modules/ \
396 + -I$(OSAL_DIR)/common/os/linux/include/modules/ddk/ \
397 + -I$(OSAL_DIR)/common/os/linux/include/modules/bufferMgt/ \
398 + -I$(OSAL_DIR)/common/os/linux/include/modules/ioMem/ \
399 + -I$(OSAL_DIR)/platforms/$(IXPLATFORM)/include/ \
400 + -I$(OSAL_DIR)/platforms/$(IXPLATFORM)/os/linux/include/ \
401 + -DENABLE_IOMEM -DENABLE_BUFFERMGT -DENABLE_DDK \
402 + -DUSE_IXP4XX_CRYPTO
403 +else
404 +IXP_CFLAGS = \
405 + -I$(ROOTDIR)/. \
406 + -I$(IX_XSCALE_SW)/src/include \
407 + -I$(OSAL_DIR)/ \
408 + -I$(OSAL_DIR)/os/linux/include/ \
409 + -I$(OSAL_DIR)/os/linux/include/modules/ \
410 + -I$(OSAL_DIR)/os/linux/include/modules/ioMem/ \
411 + -I$(OSAL_DIR)/os/linux/include/modules/bufferMgt/ \
412 + -I$(OSAL_DIR)/os/linux/include/core/ \
413 + -I$(OSAL_DIR)/os/linux/include/platforms/ \
414 + -I$(OSAL_DIR)/os/linux/include/platforms/ixp400/ \
415 + -I$(OSAL_DIR)/os/linux/include/platforms/ixp400/ixp425 \
416 + -I$(OSAL_DIR)/os/linux/include/platforms/ixp400/ixp465 \
417 + -I$(OSAL_DIR)/os/linux/include/core/ \
418 + -I$(OSAL_DIR)/include/ \
419 + -I$(OSAL_DIR)/include/modules/ \
420 + -I$(OSAL_DIR)/include/modules/bufferMgt/ \
421 + -I$(OSAL_DIR)/include/modules/ioMem/ \
422 + -I$(OSAL_DIR)/include/platforms/ \
423 + -I$(OSAL_DIR)/include/platforms/ixp400/ \
424 + -DUSE_IXP4XX_CRYPTO
425 +endif
426 +endif
427 +ifdef CONFIG_IXP400_LIB_1_4
428 +IXP_CFLAGS = \
429 + -I$(ROOTDIR)/. \
430 + -I$(ROOTDIR)/modules/ixp425/ixp400-1.4/ixp400_xscale_sw/src/include \
431 + -I$(ROOTDIR)/modules/ixp425/ixp400-1.4/ixp400_xscale_sw/src/linux \
432 + -DUSE_IXP4XX_CRYPTO
433 +endif
434 +ifndef IXPDIR
435 +IXPDIR = ixp-version-is-not-supported
436 +endif
437 +
438 +ifeq ($(CONFIG_CPU_IXP46X),y)
439 +IXP_CFLAGS += -D__ixp46X
440 +else
441 +ifeq ($(CONFIG_CPU_IXP43X),y)
442 +IXP_CFLAGS += -D__ixp43X
443 +else
444 +IXP_CFLAGS += -D__ixp42X
445 +endif
446 +endif
447 +
448 +obj-$(CONFIG_OCF_IXP4XX) += ixp4xx.o
449 +
450 +obj ?= .
451 +EXTRA_CFLAGS += $(IXP_CFLAGS) -I$(obj)/.. -I$(obj)/.
452 +
453 +ifdef TOPDIR
454 +-include $(TOPDIR)/Rules.make
455 +endif
456 +
457 --- /dev/null
458 +++ b/crypto/ocf/ocfnull/Makefile
459 @@ -0,0 +1,12 @@
460 +# for SGlinux builds
461 +-include $(ROOTDIR)/modules/.config
462 +
463 +obj-$(CONFIG_OCF_OCFNULL) += ocfnull.o
464 +
465 +obj ?= .
466 +EXTRA_CFLAGS += -I$(obj)/..
467 +
468 +ifdef TOPDIR
469 +-include $(TOPDIR)/Rules.make
470 +endif
471 +
472 --- /dev/null
473 +++ b/crypto/ocf/pasemi/Makefile
474 @@ -0,0 +1,12 @@
475 +# for SGlinux builds
476 +-include $(ROOTDIR)/modules/.config
477 +
478 +obj-$(CONFIG_OCF_PASEMI) += pasemi.o
479 +
480 +obj ?= .
481 +EXTRA_CFLAGS += -I$(obj)/.. -I$(obj)/
482 +
483 +ifdef TOPDIR
484 +-include $(TOPDIR)/Rules.make
485 +endif
486 +
487 --- /dev/null
488 +++ b/crypto/ocf/Config.in
489 @@ -0,0 +1,32 @@
490 +#############################################################################
491 +
492 +mainmenu_option next_comment
493 +comment 'OCF Configuration'
494 +tristate 'OCF (Open Cryptograhic Framework)' CONFIG_OCF_OCF
495 +dep_mbool ' enable fips RNG checks (fips check on RNG data before use)' \
496 + CONFIG_OCF_FIPS $CONFIG_OCF_OCF
497 +dep_mbool ' enable harvesting entropy for /dev/random' \
498 + CONFIG_OCF_RANDOMHARVEST $CONFIG_OCF_OCF
499 +dep_tristate ' cryptodev (user space support)' \
500 + CONFIG_OCF_CRYPTODEV $CONFIG_OCF_OCF
501 +dep_tristate ' cryptosoft (software crypto engine)' \
502 + CONFIG_OCF_CRYPTOSOFT $CONFIG_OCF_OCF
503 +dep_tristate ' safenet (HW crypto engine)' \
504 + CONFIG_OCF_SAFE $CONFIG_OCF_OCF
505 +dep_tristate ' IXP4xx (HW crypto engine)' \
506 + CONFIG_OCF_IXP4XX $CONFIG_OCF_OCF
507 +dep_mbool ' Enable IXP4xx HW to perform SHA1 and MD5 hashing (very slow)' \
508 + CONFIG_OCF_IXP4XX_SHA1_MD5 $CONFIG_OCF_IXP4XX
509 +dep_tristate ' hifn (HW crypto engine)' \
510 + CONFIG_OCF_HIFN $CONFIG_OCF_OCF
511 +dep_tristate ' talitos (HW crypto engine)' \
512 + CONFIG_OCF_TALITOS $CONFIG_OCF_OCF
513 +dep_tristate ' pasemi (HW crypto engine)' \
514 + CONFIG_OCF_PASEMI $CONFIG_OCF_OCF
515 +dep_tristate ' ocfnull (does no crypto)' \
516 + CONFIG_OCF_OCFNULL $CONFIG_OCF_OCF
517 +dep_tristate ' ocf-bench (HW crypto in-kernel benchmark)' \
518 + CONFIG_OCF_BENCH $CONFIG_OCF_OCF
519 +endmenu
520 +
521 +#############################################################################
522 --- /dev/null
523 +++ b/crypto/ocf/Kconfig
524 @@ -0,0 +1,95 @@
525 +menu "OCF Configuration"
526 +
527 +config OCF_OCF
528 + tristate "OCF (Open Cryptograhic Framework)"
529 + help
530 + A linux port of the OpenBSD/FreeBSD crypto framework.
531 +
532 +config OCF_RANDOMHARVEST
533 + bool "crypto random --- harvest entropy for /dev/random"
534 + depends on OCF_OCF
535 + help
536 + Includes code to harvest random numbers from devices that support it.
537 +
538 +config OCF_FIPS
539 + bool "enable fips RNG checks"
540 + depends on OCF_OCF && OCF_RANDOMHARVEST
541 + help
542 + Run all RNG provided data through a fips check before
543 + adding it /dev/random's entropy pool.
544 +
545 +config OCF_CRYPTODEV
546 + tristate "cryptodev (user space support)"
547 + depends on OCF_OCF
548 + help
549 + The user space API to access crypto hardware.
550 +
551 +config OCF_CRYPTOSOFT
552 + tristate "cryptosoft (software crypto engine)"
553 + depends on OCF_OCF
554 + help
555 + A software driver for the OCF framework that uses
556 + the kernel CryptoAPI.
557 +
558 +config OCF_SAFE
559 + tristate "safenet (HW crypto engine)"
560 + depends on OCF_OCF
561 + help
562 + A driver for a number of the safenet Excel crypto accelerators.
563 + Currently tested and working on the 1141 and 1741.
564 +
565 +config OCF_IXP4XX
566 + tristate "IXP4xx (HW crypto engine)"
567 + depends on OCF_OCF
568 + help
569 + XScale IXP4xx crypto accelerator driver. Requires the
570 + Intel Access library.
571 +
572 +config OCF_IXP4XX_SHA1_MD5
573 + bool "IXP4xx SHA1 and MD5 Hashing"
574 + depends on OCF_IXP4XX
575 + help
576 + Allows the IXP4xx crypto accelerator to perform SHA1 and MD5 hashing.
577 + Note: this is MUCH slower than using cryptosoft (software crypto engine).
578 +
579 +config OCF_HIFN
580 + tristate "hifn (HW crypto engine)"
581 + depends on OCF_OCF
582 + help
583 + OCF driver for various HIFN based crypto accelerators.
584 + (7951, 7955, 7956, 7751, 7811)
585 +
586 +config OCF_HIFNHIPP
587 + tristate "Hifn HIPP (HW packet crypto engine)"
588 + depends on OCF_OCF
589 + help
590 + OCF driver for various HIFN (HIPP) based crypto accelerators
591 + (7855)
592 +
593 +config OCF_TALITOS
594 + tristate "talitos (HW crypto engine)"
595 + depends on OCF_OCF
596 + help
597 + OCF driver for Freescale's security engine (SEC/talitos).
598 +
599 +config OCF_PASEMI
600 + tristate "pasemi (HW crypto engine)"
601 + depends on OCF_OCF && PPC_PASEMI
602 + help
603 + OCF driver for for PA Semi PWRficient DMA Engine
604 +
605 +config OCF_OCFNULL
606 + tristate "ocfnull (fake crypto engine)"
607 + depends on OCF_OCF
608 + help
609 + OCF driver for measuring ipsec overheads (does no crypto)
610 +
611 +config OCF_BENCH
612 + tristate "ocf-bench (HW crypto in-kernel benchmark)"
613 + depends on OCF_OCF
614 + help
615 + A very simple encryption test for the in-kernel interface
616 + of OCF. Also includes code to benchmark the IXP Access library
617 + for comparison.
618 +
619 +endmenu
620 --- /dev/null
621 +++ b/crypto/ocf/README
622 @@ -0,0 +1,166 @@
623 +README - ocf-linux-20071215
624 +---------------------------
625 +
626 +This README provides instructions for getting ocf-linux compiled and
627 +operating in a generic linux environment. For other information you
628 +might like to visit the home page for this project:
629 +
630 + http://ocf-linux.sourceforge.net/
631 +
632 +Adding OCF to linux
633 +-------------------
634 +
635 + Not much in this file for now, just some notes. I usually build
636 + the ocf support as modules but it can be built into the kernel as
637 + well. To use it:
638 +
639 + * mknod /dev/crypto c 10 70
640 +
641 + * to add OCF to your kernel source, you have two options. Apply
642 + the kernel specific patch:
643 +
644 + cd linux-2.4*; gunzip < ocf-linux-24-XXXXXXXX.patch.gz | patch -p1
645 + cd linux-2.6*; gunzip < ocf-linux-26-XXXXXXXX.patch.gz | patch -p1
646 +
647 + if you do one of the above, then you can proceed to the next step,
648 + or you can do the above process by hand with using the patches against
649 + linux-2.4.35 and 2.6.23 to include the ocf code under crypto/ocf.
650 + Here's how to add it:
651 +
652 + for 2.4.35 (and later)
653 +
654 + cd linux-2.4.35/crypto
655 + tar xvzf ocf-linux.tar.gz
656 + cd ..
657 + patch -p1 < crypto/ocf/patches/linux-2.4.35-ocf.patch
658 +
659 + for 2.6.23 (and later)
660 +
661 + cd linux-2.6.23/crypto
662 + tar xvzf ocf-linux.tar.gz
663 + cd ..
664 + patch -p1 < crypto/ocf/patches/linux-2.6.23-ocf.patch
665 +
666 + It should be easy to take this patch and apply it to other more
667 + recent versions of the kernels. The same patches should also work
668 + relatively easily on kernels as old as 2.6.11 and 2.4.18.
669 +
670 + * under 2.4 if you are on a non-x86 platform, you may need to:
671 +
672 + cp linux-2.X.x/include/asm-i386/kmap_types.h linux-2.X.x/include/asm-YYY
673 +
674 + so that you can build the kernel crypto support needed for the cryptosoft
675 + driver.
676 +
677 + * For simplicity you should enable all the crypto support in your kernel
678 + except for the test driver. Likewise for the OCF options. Do not
679 + enable OCF crypto drivers for HW that you do not have (for example
680 + ixp4xx will not compile on non-Xscale systems).
681 +
682 + * make sure that cryptodev.h (from ocf-linux.tar.gz) is installed as
683 + crypto/cryptodev.h in an include directory that is used for building
684 + applications for your platform. For example on a host system that
685 + might be:
686 +
687 + /usr/include/crypto/cryptodev.h
688 +
689 + * patch your openssl-0.9.8g code with the openssl-0.9.8g.patch.
690 + (NOTE: there is no longer a need to patch ssh). The patch is against:
691 + openssl-0_9_8e
692 +
693 + If you need a patch for an older version of openssl, you should look
694 + to older OCF releases. This patch is unlikely to work on older
695 + openssl versions.
696 +
697 + openssl-0.9.8g.patch
698 + - enables --with-cryptodev for non BSD systems
699 + - adds -cpu option to openssl speed for calculating CPU load
700 + under linux
701 + - fixes null pointer in openssl speed multi thread output.
702 + - fixes test keys to work with linux crypto's more stringent
703 + key checking.
704 + - adds MD5/SHA acceleration (Ronen Shitrit), only enabled
705 + with the --with-cryptodev-digests option
706 + - fixes bug in engine code caching.
707 +
708 + * build crypto-tools-XXXXXXXX.tar.gz if you want to try some of the BSD
709 + tools for testing OCF (ie., cryptotest).
710 +
711 +How to load the OCF drivers
712 +---------------------------
713 +
714 + First insert the base modules:
715 +
716 + insmod ocf
717 + insmod cryptodev
718 +
719 + You can then install the software OCF driver with:
720 +
721 + insmod cryptosoft
722 +
723 + and one or more of the OCF HW drivers with:
724 +
725 + insmod safe
726 + insmod hifn7751
727 + insmod ixp4xx
728 + ...
729 +
730 + all the drivers take a debug option to enable verbose debug so that
731 + you can see what is going on. For debug you load them as:
732 +
733 + insmod ocf crypto_debug=1
734 + insmod cryptodev cryptodev_debug=1
735 + insmod cryptosoft swcr_debug=1
736 +
737 + You may load more than one OCF crypto driver but then there is no guarantee
738 + as to which will be used.
739 +
740 + You can also enable debug at run time on 2.6 systems with the following:
741 +
742 + echo 1 > /sys/module/ocf/parameters/crypto_debug
743 + echo 1 > /sys/module/cryptodev/parameters/cryptodev_debug
744 + echo 1 > /sys/module/cryptosoft/parameters/swcr_debug
745 + echo 1 > /sys/module/hifn7751/parameters/hifn_debug
746 + echo 1 > /sys/module/safe/parameters/safe_debug
747 + echo 1 > /sys/module/ixp4xx/parameters/ixp_debug
748 + ...
749 +
750 +Testing the OCF support
751 +-----------------------
752 +
753 + run "cryptotest", it should do a short test for a couple of
754 + des packets. If it does everything is working.
755 +
756 + If this works, then ssh will use the driver when invoked as:
757 +
758 + ssh -c 3des username@host
759 +
760 + to see for sure that it is operating, enable debug as defined above.
761 +
762 + To get a better idea of performance run:
763 +
764 + cryptotest 100 4096
765 +
766 + There are more options to cryptotest, see the help.
767 +
768 + It is also possible to use openssl to test the speed of the crypto
769 + drivers.
770 +
771 + openssl speed -evp des -engine cryptodev -elapsed
772 + openssl speed -evp des3 -engine cryptodev -elapsed
773 + openssl speed -evp aes128 -engine cryptodev -elapsed
774 +
775 + and multiple threads (10) with:
776 +
777 + openssl speed -evp des -engine cryptodev -elapsed -multi 10
778 + openssl speed -evp des3 -engine cryptodev -elapsed -multi 10
779 + openssl speed -evp aes128 -engine cryptodev -elapsed -multi 10
780 +
781 + for public key testing you can try:
782 +
783 + cryptokeytest
784 + openssl speed -engine cryptodev rsa -elapsed
785 + openssl speed -engine cryptodev dsa -elapsed
786 +
787 +David McCullough
788 +david_mccullough@securecomputing.com
789 --- /dev/null
790 +++ b/crypto/ocf/hifn/hifn7751reg.h
791 @@ -0,0 +1,540 @@
792 +/* $FreeBSD: src/sys/dev/hifn/hifn7751reg.h,v 1.7 2007/03/21 03:42:49 sam Exp $ */
793 +/* $OpenBSD: hifn7751reg.h,v 1.35 2002/04/08 17:49:42 jason Exp $ */
794 +
795 +/*-
796 + * Invertex AEON / Hifn 7751 driver
797 + * Copyright (c) 1999 Invertex Inc. All rights reserved.
798 + * Copyright (c) 1999 Theo de Raadt
799 + * Copyright (c) 2000-2001 Network Security Technologies, Inc.
800 + * http://www.netsec.net
801 + *
802 + * Please send any comments, feedback, bug-fixes, or feature requests to
803 + * software@invertex.com.
804 + *
805 + * Redistribution and use in source and binary forms, with or without
806 + * modification, are permitted provided that the following conditions
807 + * are met:
808 + *
809 + * 1. Redistributions of source code must retain the above copyright
810 + * notice, this list of conditions and the following disclaimer.
811 + * 2. Redistributions in binary form must reproduce the above copyright
812 + * notice, this list of conditions and the following disclaimer in the
813 + * documentation and/or other materials provided with the distribution.
814 + * 3. The name of the author may not be used to endorse or promote products
815 + * derived from this software without specific prior written permission.
816 + *
817 + *
818 + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
819 + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
820 + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
821 + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
822 + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
823 + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
824 + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
825 + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
826 + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
827 + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
828 + *
829 + * Effort sponsored in part by the Defense Advanced Research Projects
830 + * Agency (DARPA) and Air Force Research Laboratory, Air Force
831 + * Materiel Command, USAF, under agreement number F30602-01-2-0537.
832 + *
833 + */
834 +#ifndef __HIFN_H__
835 +#define __HIFN_H__
836 +
837 +/*
838 + * Some PCI configuration space offset defines. The names were made
839 + * identical to the names used by the Linux kernel.
840 + */
841 +#define HIFN_BAR0 PCIR_BAR(0) /* PUC register map */
842 +#define HIFN_BAR1 PCIR_BAR(1) /* DMA register map */
843 +#define HIFN_TRDY_TIMEOUT 0x40
844 +#define HIFN_RETRY_TIMEOUT 0x41
845 +
846 +/*
847 + * PCI vendor and device identifiers
848 + * (the names are preserved from their OpenBSD source).
849 + */
850 +#define PCI_VENDOR_HIFN 0x13a3 /* Hifn */
851 +#define PCI_PRODUCT_HIFN_7751 0x0005 /* 7751 */
852 +#define PCI_PRODUCT_HIFN_6500 0x0006 /* 6500 */
853 +#define PCI_PRODUCT_HIFN_7811 0x0007 /* 7811 */
854 +#define PCI_PRODUCT_HIFN_7855 0x001f /* 7855 */
855 +#define PCI_PRODUCT_HIFN_7951 0x0012 /* 7951 */
856 +#define PCI_PRODUCT_HIFN_7955 0x0020 /* 7954/7955 */
857 +#define PCI_PRODUCT_HIFN_7956 0x001d /* 7956 */
858 +
859 +#define PCI_VENDOR_INVERTEX 0x14e1 /* Invertex */
860 +#define PCI_PRODUCT_INVERTEX_AEON 0x0005 /* AEON */
861 +
862 +#define PCI_VENDOR_NETSEC 0x1660 /* NetSec */
863 +#define PCI_PRODUCT_NETSEC_7751 0x7751 /* 7751 */
864 +
865 +/*
866 + * The values below should multiple of 4 -- and be large enough to handle
867 + * any command the driver implements.
868 + *
869 + * MAX_COMMAND = base command + mac command + encrypt command +
870 + * mac-key + rc4-key
871 + * MAX_RESULT = base result + mac result + mac + encrypt result
872 + *
873 + *
874 + */
875 +#define HIFN_MAX_COMMAND (8 + 8 + 8 + 64 + 260)
876 +#define HIFN_MAX_RESULT (8 + 4 + 20 + 4)
877 +
878 +/*
879 + * hifn_desc_t
880 + *
881 + * Holds an individual descriptor for any of the rings.
882 + */
883 +typedef struct hifn_desc {
884 + volatile u_int32_t l; /* length and status bits */
885 + volatile u_int32_t p;
886 +} hifn_desc_t;
887 +
888 +/*
889 + * Masks for the "length" field of struct hifn_desc.
890 + */
891 +#define HIFN_D_LENGTH 0x0000ffff /* length bit mask */
892 +#define HIFN_D_MASKDONEIRQ 0x02000000 /* mask the done interrupt */
893 +#define HIFN_D_DESTOVER 0x04000000 /* destination overflow */
894 +#define HIFN_D_OVER 0x08000000 /* overflow */
895 +#define HIFN_D_LAST 0x20000000 /* last descriptor in chain */
896 +#define HIFN_D_JUMP 0x40000000 /* jump descriptor */
897 +#define HIFN_D_VALID 0x80000000 /* valid bit */
898 +
899 +
900 +/*
901 + * Processing Unit Registers (offset from BASEREG0)
902 + */
903 +#define HIFN_0_PUDATA 0x00 /* Processing Unit Data */
904 +#define HIFN_0_PUCTRL 0x04 /* Processing Unit Control */
905 +#define HIFN_0_PUISR 0x08 /* Processing Unit Interrupt Status */
906 +#define HIFN_0_PUCNFG 0x0c /* Processing Unit Configuration */
907 +#define HIFN_0_PUIER 0x10 /* Processing Unit Interrupt Enable */
908 +#define HIFN_0_PUSTAT 0x14 /* Processing Unit Status/Chip ID */
909 +#define HIFN_0_FIFOSTAT 0x18 /* FIFO Status */
910 +#define HIFN_0_FIFOCNFG 0x1c /* FIFO Configuration */
911 +#define HIFN_0_PUCTRL2 0x28 /* Processing Unit Control (2nd map) */
912 +#define HIFN_0_MUTE1 0x80
913 +#define HIFN_0_MUTE2 0x90
914 +#define HIFN_0_SPACESIZE 0x100 /* Register space size */
915 +
916 +/* Processing Unit Control Register (HIFN_0_PUCTRL) */
917 +#define HIFN_PUCTRL_CLRSRCFIFO 0x0010 /* clear source fifo */
918 +#define HIFN_PUCTRL_STOP 0x0008 /* stop pu */
919 +#define HIFN_PUCTRL_LOCKRAM 0x0004 /* lock ram */
920 +#define HIFN_PUCTRL_DMAENA 0x0002 /* enable dma */
921 +#define HIFN_PUCTRL_RESET 0x0001 /* Reset processing unit */
922 +
923 +/* Processing Unit Interrupt Status Register (HIFN_0_PUISR) */
924 +#define HIFN_PUISR_CMDINVAL 0x8000 /* Invalid command interrupt */
925 +#define HIFN_PUISR_DATAERR 0x4000 /* Data error interrupt */
926 +#define HIFN_PUISR_SRCFIFO 0x2000 /* Source FIFO ready interrupt */
927 +#define HIFN_PUISR_DSTFIFO 0x1000 /* Destination FIFO ready interrupt */
928 +#define HIFN_PUISR_DSTOVER 0x0200 /* Destination overrun interrupt */
929 +#define HIFN_PUISR_SRCCMD 0x0080 /* Source command interrupt */
930 +#define HIFN_PUISR_SRCCTX 0x0040 /* Source context interrupt */
931 +#define HIFN_PUISR_SRCDATA 0x0020 /* Source data interrupt */
932 +#define HIFN_PUISR_DSTDATA 0x0010 /* Destination data interrupt */
933 +#define HIFN_PUISR_DSTRESULT 0x0004 /* Destination result interrupt */
934 +
935 +/* Processing Unit Configuration Register (HIFN_0_PUCNFG) */
936 +#define HIFN_PUCNFG_DRAMMASK 0xe000 /* DRAM size mask */
937 +#define HIFN_PUCNFG_DSZ_256K 0x0000 /* 256k dram */
938 +#define HIFN_PUCNFG_DSZ_512K 0x2000 /* 512k dram */
939 +#define HIFN_PUCNFG_DSZ_1M 0x4000 /* 1m dram */
940 +#define HIFN_PUCNFG_DSZ_2M 0x6000 /* 2m dram */
941 +#define HIFN_PUCNFG_DSZ_4M 0x8000 /* 4m dram */
942 +#define HIFN_PUCNFG_DSZ_8M 0xa000 /* 8m dram */
943 +#define HIFN_PUNCFG_DSZ_16M 0xc000 /* 16m dram */
944 +#define HIFN_PUCNFG_DSZ_32M 0xe000 /* 32m dram */
945 +#define HIFN_PUCNFG_DRAMREFRESH 0x1800 /* DRAM refresh rate mask */
946 +#define HIFN_PUCNFG_DRFR_512 0x0000 /* 512 divisor of ECLK */
947 +#define HIFN_PUCNFG_DRFR_256 0x0800 /* 256 divisor of ECLK */
948 +#define HIFN_PUCNFG_DRFR_128 0x1000 /* 128 divisor of ECLK */
949 +#define HIFN_PUCNFG_TCALLPHASES 0x0200 /* your guess is as good as mine... */
950 +#define HIFN_PUCNFG_TCDRVTOTEM 0x0100 /* your guess is as good as mine... */
951 +#define HIFN_PUCNFG_BIGENDIAN 0x0080 /* DMA big endian mode */
952 +#define HIFN_PUCNFG_BUS32 0x0040 /* Bus width 32bits */
953 +#define HIFN_PUCNFG_BUS16 0x0000 /* Bus width 16 bits */
954 +#define HIFN_PUCNFG_CHIPID 0x0020 /* Allow chipid from PUSTAT */
955 +#define HIFN_PUCNFG_DRAM 0x0010 /* Context RAM is DRAM */
956 +#define HIFN_PUCNFG_SRAM 0x0000 /* Context RAM is SRAM */
957 +#define HIFN_PUCNFG_COMPSING 0x0004 /* Enable single compression context */
958 +#define HIFN_PUCNFG_ENCCNFG 0x0002 /* Encryption configuration */
959 +
960 +/* Processing Unit Interrupt Enable Register (HIFN_0_PUIER) */
961 +#define HIFN_PUIER_CMDINVAL 0x8000 /* Invalid command interrupt */
962 +#define HIFN_PUIER_DATAERR 0x4000 /* Data error interrupt */
963 +#define HIFN_PUIER_SRCFIFO 0x2000 /* Source FIFO ready interrupt */
964 +#define HIFN_PUIER_DSTFIFO 0x1000 /* Destination FIFO ready interrupt */
965 +#define HIFN_PUIER_DSTOVER 0x0200 /* Destination overrun interrupt */
966 +#define HIFN_PUIER_SRCCMD 0x0080 /* Source command interrupt */
967 +#define HIFN_PUIER_SRCCTX 0x0040 /* Source context interrupt */
968 +#define HIFN_PUIER_SRCDATA 0x0020 /* Source data interrupt */
969 +#define HIFN_PUIER_DSTDATA 0x0010 /* Destination data interrupt */
970 +#define HIFN_PUIER_DSTRESULT 0x0004 /* Destination result interrupt */
971 +
972 +/* Processing Unit Status Register/Chip ID (HIFN_0_PUSTAT) */
973 +#define HIFN_PUSTAT_CMDINVAL 0x8000 /* Invalid command interrupt */
974 +#define HIFN_PUSTAT_DATAERR 0x4000 /* Data error interrupt */
975 +#define HIFN_PUSTAT_SRCFIFO 0x2000 /* Source FIFO ready interrupt */
976 +#define HIFN_PUSTAT_DSTFIFO 0x1000 /* Destination FIFO ready interrupt */
977 +#define HIFN_PUSTAT_DSTOVER 0x0200 /* Destination overrun interrupt */
978 +#define HIFN_PUSTAT_SRCCMD 0x0080 /* Source command interrupt */
979 +#define HIFN_PUSTAT_SRCCTX 0x0040 /* Source context interrupt */
980 +#define HIFN_PUSTAT_SRCDATA 0x0020 /* Source data interrupt */
981 +#define HIFN_PUSTAT_DSTDATA 0x0010 /* Destination data interrupt */
982 +#define HIFN_PUSTAT_DSTRESULT 0x0004 /* Destination result interrupt */
983 +#define HIFN_PUSTAT_CHIPREV 0x00ff /* Chip revision mask */
984 +#define HIFN_PUSTAT_CHIPENA 0xff00 /* Chip enabled mask */
985 +#define HIFN_PUSTAT_ENA_2 0x1100 /* Level 2 enabled */
986 +#define HIFN_PUSTAT_ENA_1 0x1000 /* Level 1 enabled */
987 +#define HIFN_PUSTAT_ENA_0 0x3000 /* Level 0 enabled */
988 +#define HIFN_PUSTAT_REV_2 0x0020 /* 7751 PT6/2 */
989 +#define HIFN_PUSTAT_REV_3 0x0030 /* 7751 PT6/3 */
990 +
991 +/* FIFO Status Register (HIFN_0_FIFOSTAT) */
992 +#define HIFN_FIFOSTAT_SRC 0x7f00 /* Source FIFO available */
993 +#define HIFN_FIFOSTAT_DST 0x007f /* Destination FIFO available */
994 +
995 +/* FIFO Configuration Register (HIFN_0_FIFOCNFG) */
996 +#define HIFN_FIFOCNFG_THRESHOLD 0x0400 /* must be written as this value */
997 +
998 +/*
999 + * DMA Interface Registers (offset from BASEREG1)
1000 + */
1001 +#define HIFN_1_DMA_CRAR 0x0c /* DMA Command Ring Address */
1002 +#define HIFN_1_DMA_SRAR 0x1c /* DMA Source Ring Address */
1003 +#define HIFN_1_DMA_RRAR 0x2c /* DMA Result Ring Address */
1004 +#define HIFN_1_DMA_DRAR 0x3c /* DMA Destination Ring Address */
1005 +#define HIFN_1_DMA_CSR 0x40 /* DMA Status and Control */
1006 +#define HIFN_1_DMA_IER 0x44 /* DMA Interrupt Enable */
1007 +#define HIFN_1_DMA_CNFG 0x48 /* DMA Configuration */
1008 +#define HIFN_1_PLL 0x4c /* 7955/7956: PLL config */
1009 +#define HIFN_1_7811_RNGENA 0x60 /* 7811: rng enable */
1010 +#define HIFN_1_7811_RNGCFG 0x64 /* 7811: rng config */
1011 +#define HIFN_1_7811_RNGDAT 0x68 /* 7811: rng data */
1012 +#define HIFN_1_7811_RNGSTS 0x6c /* 7811: rng status */
1013 +#define HIFN_1_DMA_CNFG2 0x6c /* 7955/7956: dma config #2 */
1014 +#define HIFN_1_7811_MIPSRST 0x94 /* 7811: MIPS reset */
1015 +#define HIFN_1_REVID 0x98 /* Revision ID */
1016 +
1017 +#define HIFN_1_PUB_RESET 0x204 /* Public/RNG Reset */
1018 +#define HIFN_1_PUB_BASE 0x300 /* Public Base Address */
1019 +#define HIFN_1_PUB_OPLEN 0x304 /* 7951-compat Public Operand Length */
1020 +#define HIFN_1_PUB_OP 0x308 /* 7951-compat Public Operand */
1021 +#define HIFN_1_PUB_STATUS 0x30c /* 7951-compat Public Status */
1022 +#define HIFN_1_PUB_IEN 0x310 /* Public Interrupt enable */
1023 +#define HIFN_1_RNG_CONFIG 0x314 /* RNG config */
1024 +#define HIFN_1_RNG_DATA 0x318 /* RNG data */
1025 +#define HIFN_1_PUB_MODE 0x320 /* PK mode */
1026 +#define HIFN_1_PUB_FIFO_OPLEN 0x380 /* first element of oplen fifo */
1027 +#define HIFN_1_PUB_FIFO_OP 0x384 /* first element of op fifo */
1028 +#define HIFN_1_PUB_MEM 0x400 /* start of Public key memory */
1029 +#define HIFN_1_PUB_MEMEND 0xbff /* end of Public key memory */
1030 +
1031 +/* DMA Status and Control Register (HIFN_1_DMA_CSR) */
1032 +#define HIFN_DMACSR_D_CTRLMASK 0xc0000000 /* Destinition Ring Control */
1033 +#define HIFN_DMACSR_D_CTRL_NOP 0x00000000 /* Dest. Control: no-op */
1034 +#define HIFN_DMACSR_D_CTRL_DIS 0x40000000 /* Dest. Control: disable */
1035 +#define HIFN_DMACSR_D_CTRL_ENA 0x80000000 /* Dest. Control: enable */
1036 +#define HIFN_DMACSR_D_ABORT 0x20000000 /* Destinition Ring PCIAbort */
1037 +#define HIFN_DMACSR_D_DONE 0x10000000 /* Destinition Ring Done */
1038 +#define HIFN_DMACSR_D_LAST 0x08000000 /* Destinition Ring Last */
1039 +#define HIFN_DMACSR_D_WAIT 0x04000000 /* Destinition Ring Waiting */
1040 +#define HIFN_DMACSR_D_OVER 0x02000000 /* Destinition Ring Overflow */
1041 +#define HIFN_DMACSR_R_CTRL 0x00c00000 /* Result Ring Control */
1042 +#define HIFN_DMACSR_R_CTRL_NOP 0x00000000 /* Result Control: no-op */
1043 +#define HIFN_DMACSR_R_CTRL_DIS 0x00400000 /* Result Control: disable */
1044 +#define HIFN_DMACSR_R_CTRL_ENA 0x00800000 /* Result Control: enable */
1045 +#define HIFN_DMACSR_R_ABORT 0x00200000 /* Result Ring PCI Abort */
1046 +#define HIFN_DMACSR_R_DONE 0x00100000 /* Result Ring Done */
1047 +#define HIFN_DMACSR_R_LAST 0x00080000 /* Result Ring Last */
1048 +#define HIFN_DMACSR_R_WAIT 0x00040000 /* Result Ring Waiting */
1049 +#define HIFN_DMACSR_R_OVER 0x00020000 /* Result Ring Overflow */
1050 +#define HIFN_DMACSR_S_CTRL 0x0000c000 /* Source Ring Control */
1051 +#define HIFN_DMACSR_S_CTRL_NOP 0x00000000 /* Source Control: no-op */
1052 +#define HIFN_DMACSR_S_CTRL_DIS 0x00004000 /* Source Control: disable */
1053 +#define HIFN_DMACSR_S_CTRL_ENA 0x00008000 /* Source Control: enable */
1054 +#define HIFN_DMACSR_S_ABORT 0x00002000 /* Source Ring PCI Abort */
1055 +#define HIFN_DMACSR_S_DONE 0x00001000 /* Source Ring Done */
1056 +#define HIFN_DMACSR_S_LAST 0x00000800 /* Source Ring Last */
1057 +#define HIFN_DMACSR_S_WAIT 0x00000400 /* Source Ring Waiting */
1058 +#define HIFN_DMACSR_ILLW 0x00000200 /* Illegal write (7811 only) */
1059 +#define HIFN_DMACSR_ILLR 0x00000100 /* Illegal read (7811 only) */
1060 +#define HIFN_DMACSR_C_CTRL 0x000000c0 /* Command Ring Control */
1061 +#define HIFN_DMACSR_C_CTRL_NOP 0x00000000 /* Command Control: no-op */
1062 +#define HIFN_DMACSR_C_CTRL_DIS 0x00000040 /* Command Control: disable */
1063 +#define HIFN_DMACSR_C_CTRL_ENA 0x00000080 /* Command Control: enable */
1064 +#define HIFN_DMACSR_C_ABORT 0x00000020 /* Command Ring PCI Abort */
1065 +#define HIFN_DMACSR_C_DONE 0x00000010 /* Command Ring Done */
1066 +#define HIFN_DMACSR_C_LAST 0x00000008 /* Command Ring Last */
1067 +#define HIFN_DMACSR_C_WAIT 0x00000004 /* Command Ring Waiting */
1068 +#define HIFN_DMACSR_PUBDONE 0x00000002 /* Public op done (7951 only) */
1069 +#define HIFN_DMACSR_ENGINE 0x00000001 /* Command Ring Engine IRQ */
1070 +
1071 +/* DMA Interrupt Enable Register (HIFN_1_DMA_IER) */
1072 +#define HIFN_DMAIER_D_ABORT 0x20000000 /* Destination Ring PCIAbort */
1073 +#define HIFN_DMAIER_D_DONE 0x10000000 /* Destination Ring Done */
1074 +#define HIFN_DMAIER_D_LAST 0x08000000 /* Destination Ring Last */
1075 +#define HIFN_DMAIER_D_WAIT 0x04000000 /* Destination Ring Waiting */
1076 +#define HIFN_DMAIER_D_OVER 0x02000000 /* Destination Ring Overflow */
1077 +#define HIFN_DMAIER_R_ABORT 0x00200000 /* Result Ring PCI Abort */
1078 +#define HIFN_DMAIER_R_DONE 0x00100000 /* Result Ring Done */
1079 +#define HIFN_DMAIER_R_LAST 0x00080000 /* Result Ring Last */
1080 +#define HIFN_DMAIER_R_WAIT 0x00040000 /* Result Ring Waiting */
1081 +#define HIFN_DMAIER_R_OVER 0x00020000 /* Result Ring Overflow */
1082 +#define HIFN_DMAIER_S_ABORT 0x00002000 /* Source Ring PCI Abort */
1083 +#define HIFN_DMAIER_S_DONE 0x00001000 /* Source Ring Done */
1084 +#define HIFN_DMAIER_S_LAST 0x00000800 /* Source Ring Last */
1085 +#define HIFN_DMAIER_S_WAIT 0x00000400 /* Source Ring Waiting */
1086 +#define HIFN_DMAIER_ILLW 0x00000200 /* Illegal write (7811 only) */
1087 +#define HIFN_DMAIER_ILLR 0x00000100 /* Illegal read (7811 only) */
1088 +#define HIFN_DMAIER_C_ABORT 0x00000020 /* Command Ring PCI Abort */
1089 +#define HIFN_DMAIER_C_DONE 0x00000010 /* Command Ring Done */
1090 +#define HIFN_DMAIER_C_LAST 0x00000008 /* Command Ring Last */
1091 +#define HIFN_DMAIER_C_WAIT 0x00000004 /* Command Ring Waiting */
1092 +#define HIFN_DMAIER_PUBDONE 0x00000002 /* public op done (7951 only) */
1093 +#define HIFN_DMAIER_ENGINE 0x00000001 /* Engine IRQ */
1094 +
1095 +/* DMA Configuration Register (HIFN_1_DMA_CNFG) */
1096 +#define HIFN_DMACNFG_BIGENDIAN 0x10000000 /* big endian mode */
1097 +#define HIFN_DMACNFG_POLLFREQ 0x00ff0000 /* Poll frequency mask */
1098 +#define HIFN_DMACNFG_UNLOCK 0x00000800
1099 +#define HIFN_DMACNFG_POLLINVAL 0x00000700 /* Invalid Poll Scalar */
1100 +#define HIFN_DMACNFG_LAST 0x00000010 /* Host control LAST bit */
1101 +#define HIFN_DMACNFG_MODE 0x00000004 /* DMA mode */
1102 +#define HIFN_DMACNFG_DMARESET 0x00000002 /* DMA Reset # */
1103 +#define HIFN_DMACNFG_MSTRESET 0x00000001 /* Master Reset # */
1104 +
1105 +/* DMA Configuration Register (HIFN_1_DMA_CNFG2) */
1106 +#define HIFN_DMACNFG2_PKSWAP32 (1 << 19) /* swap the OPLEN/OP reg */
1107 +#define HIFN_DMACNFG2_PKSWAP8 (1 << 18) /* swap the bits of OPLEN/OP */
1108 +#define HIFN_DMACNFG2_BAR0_SWAP32 (1<<17) /* swap the bytes of BAR0 */
1109 +#define HIFN_DMACNFG2_BAR1_SWAP8 (1<<16) /* swap the bits of BAR0 */
1110 +#define HIFN_DMACNFG2_INIT_WRITE_BURST_SHIFT 12
1111 +#define HIFN_DMACNFG2_INIT_READ_BURST_SHIFT 8
1112 +#define HIFN_DMACNFG2_TGT_WRITE_BURST_SHIFT 4
1113 +#define HIFN_DMACNFG2_TGT_READ_BURST_SHIFT 0
1114 +
1115 +/* 7811 RNG Enable Register (HIFN_1_7811_RNGENA) */
1116 +#define HIFN_7811_RNGENA_ENA 0x00000001 /* enable RNG */
1117 +
1118 +/* 7811 RNG Config Register (HIFN_1_7811_RNGCFG) */
1119 +#define HIFN_7811_RNGCFG_PRE1 0x00000f00 /* first prescalar */
1120 +#define HIFN_7811_RNGCFG_OPRE 0x00000080 /* output prescalar */
1121 +#define HIFN_7811_RNGCFG_DEFL 0x00000f80 /* 2 words/ 1/100 sec */
1122 +
1123 +/* 7811 RNG Status Register (HIFN_1_7811_RNGSTS) */
1124 +#define HIFN_7811_RNGSTS_RDY 0x00004000 /* two numbers in FIFO */
1125 +#define HIFN_7811_RNGSTS_UFL 0x00001000 /* rng underflow */
1126 +
1127 +/* 7811 MIPS Reset Register (HIFN_1_7811_MIPSRST) */
1128 +#define HIFN_MIPSRST_BAR2SIZE 0xffff0000 /* sdram size */
1129 +#define HIFN_MIPSRST_GPRAMINIT 0x00008000 /* gpram can be accessed */
1130 +#define HIFN_MIPSRST_CRAMINIT 0x00004000 /* ctxram can be accessed */
1131 +#define HIFN_MIPSRST_LED2 0x00000400 /* external LED2 */
1132 +#define HIFN_MIPSRST_LED1 0x00000200 /* external LED1 */
1133 +#define HIFN_MIPSRST_LED0 0x00000100 /* external LED0 */
1134 +#define HIFN_MIPSRST_MIPSDIS 0x00000004 /* disable MIPS */
1135 +#define HIFN_MIPSRST_MIPSRST 0x00000002 /* warm reset MIPS */
1136 +#define HIFN_MIPSRST_MIPSCOLD 0x00000001 /* cold reset MIPS */
1137 +
1138 +/* Public key reset register (HIFN_1_PUB_RESET) */
1139 +#define HIFN_PUBRST_RESET 0x00000001 /* reset public/rng unit */
1140 +
1141 +/* Public operation register (HIFN_1_PUB_OP) */
1142 +#define HIFN_PUBOP_AOFFSET 0x0000003e /* A offset */
1143 +#define HIFN_PUBOP_BOFFSET 0x00000fc0 /* B offset */
1144 +#define HIFN_PUBOP_MOFFSET 0x0003f000 /* M offset */
1145 +#define HIFN_PUBOP_OP_MASK 0x003c0000 /* Opcode: */
1146 +#define HIFN_PUBOP_OP_NOP 0x00000000 /* NOP */
1147 +#define HIFN_PUBOP_OP_ADD 0x00040000 /* ADD */
1148 +#define HIFN_PUBOP_OP_ADDC 0x00080000 /* ADD w/carry */
1149 +#define HIFN_PUBOP_OP_SUB 0x000c0000 /* SUB */
1150 +#define HIFN_PUBOP_OP_SUBC 0x00100000 /* SUB w/carry */
1151 +#define HIFN_PUBOP_OP_MODADD 0x00140000 /* Modular ADD */
1152 +#define HIFN_PUBOP_OP_MODSUB 0x00180000 /* Modular SUB */
1153 +#define HIFN_PUBOP_OP_INCA 0x001c0000 /* INC A */
1154 +#define HIFN_PUBOP_OP_DECA 0x00200000 /* DEC A */
1155 +#define HIFN_PUBOP_OP_MULT 0x00240000 /* MULT */
1156 +#define HIFN_PUBOP_OP_MODMULT 0x00280000 /* Modular MULT */
1157 +#define HIFN_PUBOP_OP_MODRED 0x002c0000 /* Modular Red */
1158 +#define HIFN_PUBOP_OP_MODEXP 0x00300000 /* Modular Exp */
1159 +
1160 +/* Public operand length register (HIFN_1_PUB_OPLEN) */
1161 +#define HIFN_PUBOPLEN_MODLEN 0x0000007f
1162 +#define HIFN_PUBOPLEN_EXPLEN 0x0003ff80
1163 +#define HIFN_PUBOPLEN_REDLEN 0x003c0000
1164 +
1165 +/* Public status register (HIFN_1_PUB_STATUS) */
1166 +#define HIFN_PUBSTS_DONE 0x00000001 /* operation done */
1167 +#define HIFN_PUBSTS_CARRY 0x00000002 /* carry */
1168 +#define HIFN_PUBSTS_FIFO_EMPTY 0x00000100 /* fifo empty */
1169 +#define HIFN_PUBSTS_FIFO_FULL 0x00000200 /* fifo full */
1170 +#define HIFN_PUBSTS_FIFO_OVFL 0x00000400 /* fifo overflow */
1171 +#define HIFN_PUBSTS_FIFO_WRITE 0x000f0000 /* fifo write */
1172 +#define HIFN_PUBSTS_FIFO_READ 0x0f000000 /* fifo read */
1173 +
1174 +/* Public interrupt enable register (HIFN_1_PUB_IEN) */
1175 +#define HIFN_PUBIEN_DONE 0x00000001 /* operation done interrupt */
1176 +
1177 +/* Random number generator config register (HIFN_1_RNG_CONFIG) */
1178 +#define HIFN_RNGCFG_ENA 0x00000001 /* enable rng */
1179 +
1180 +/*
1181 + * Register offsets in register set 1
1182 + */
1183 +
1184 +#define HIFN_UNLOCK_SECRET1 0xf4
1185 +#define HIFN_UNLOCK_SECRET2 0xfc
1186 +
1187 +/*
1188 + * PLL config register
1189 + *
1190 + * This register is present only on 7954/7955/7956 parts. It must be
1191 + * programmed according to the bus interface method used by the h/w.
1192 + * Note that the parts require a stable clock. Since the PCI clock
1193 + * may vary the reference clock must usually be used. To avoid
1194 + * overclocking the core logic, setup must be done carefully, refer
1195 + * to the driver for details. The exact multiplier required varies
1196 + * by part and system configuration; refer to the Hifn documentation.
1197 + */
1198 +#define HIFN_PLL_REF_SEL 0x00000001 /* REF/HBI clk selection */
1199 +#define HIFN_PLL_BP 0x00000002 /* bypass (used during setup) */
1200 +/* bit 2 reserved */
1201 +#define HIFN_PLL_PK_CLK_SEL 0x00000008 /* public key clk select */
1202 +#define HIFN_PLL_PE_CLK_SEL 0x00000010 /* packet engine clk select */
1203 +/* bits 5-9 reserved */
1204 +#define HIFN_PLL_MBSET 0x00000400 /* must be set to 1 */
1205 +#define HIFN_PLL_ND 0x00003800 /* Fpll_ref multiplier select */
1206 +#define HIFN_PLL_ND_SHIFT 11
1207 +#define HIFN_PLL_ND_2 0x00000000 /* 2x */
1208 +#define HIFN_PLL_ND_4 0x00000800 /* 4x */
1209 +#define HIFN_PLL_ND_6 0x00001000 /* 6x */
1210 +#define HIFN_PLL_ND_8 0x00001800 /* 8x */
1211 +#define HIFN_PLL_ND_10 0x00002000 /* 10x */
1212 +#define HIFN_PLL_ND_12 0x00002800 /* 12x */
1213 +/* bits 14-15 reserved */
1214 +#define HIFN_PLL_IS 0x00010000 /* charge pump current select */
1215 +/* bits 17-31 reserved */
1216 +
1217 +/*
1218 + * Board configuration specifies only these bits.
1219 + */
1220 +#define HIFN_PLL_CONFIG (HIFN_PLL_IS|HIFN_PLL_ND|HIFN_PLL_REF_SEL)
1221 +
1222 +/*
1223 + * Public Key Engine Mode Register
1224 + */
1225 +#define HIFN_PKMODE_HOSTINVERT (1 << 0) /* HOST INVERT */
1226 +#define HIFN_PKMODE_ENHANCED (1 << 1) /* Enable enhanced mode */
1227 +
1228 +
1229 +/*********************************************************************
1230 + * Structs for board commands
1231 + *
1232 + *********************************************************************/
1233 +
1234 +/*
1235 + * Structure to help build up the command data structure.
1236 + */
1237 +typedef struct hifn_base_command {
1238 + volatile u_int16_t masks;
1239 + volatile u_int16_t session_num;
1240 + volatile u_int16_t total_source_count;
1241 + volatile u_int16_t total_dest_count;
1242 +} hifn_base_command_t;
1243 +
1244 +#define HIFN_BASE_CMD_MAC 0x0400
1245 +#define HIFN_BASE_CMD_CRYPT 0x0800
1246 +#define HIFN_BASE_CMD_DECODE 0x2000
1247 +#define HIFN_BASE_CMD_SRCLEN_M 0xc000
1248 +#define HIFN_BASE_CMD_SRCLEN_S 14
1249 +#define HIFN_BASE_CMD_DSTLEN_M 0x3000
1250 +#define HIFN_BASE_CMD_DSTLEN_S 12
1251 +#define HIFN_BASE_CMD_LENMASK_HI 0x30000
1252 +#define HIFN_BASE_CMD_LENMASK_LO 0x0ffff
1253 +
1254 +/*
1255 + * Structure to help build up the command data structure.
1256 + */
1257 +typedef struct hifn_crypt_command {
1258 + volatile u_int16_t masks;
1259 + volatile u_int16_t header_skip;
1260 + volatile u_int16_t source_count;
1261 + volatile u_int16_t reserved;
1262 +} hifn_crypt_command_t;
1263 +
1264 +#define HIFN_CRYPT_CMD_ALG_MASK 0x0003 /* algorithm: */
1265 +#define HIFN_CRYPT_CMD_ALG_DES 0x0000 /* DES */
1266 +#define HIFN_CRYPT_CMD_ALG_3DES 0x0001 /* 3DES */
1267 +#define HIFN_CRYPT_CMD_ALG_RC4 0x0002 /* RC4 */
1268 +#define HIFN_CRYPT_CMD_ALG_AES 0x0003 /* AES */
1269 +#define HIFN_CRYPT_CMD_MODE_MASK 0x0018 /* Encrypt mode: */
1270 +#define HIFN_CRYPT_CMD_MODE_ECB 0x0000 /* ECB */
1271 +#define HIFN_CRYPT_CMD_MODE_CBC 0x0008 /* CBC */
1272 +#define HIFN_CRYPT_CMD_MODE_CFB 0x0010 /* CFB */
1273 +#define HIFN_CRYPT_CMD_MODE_OFB 0x0018 /* OFB */
1274 +#define HIFN_CRYPT_CMD_CLR_CTX 0x0040 /* clear context */
1275 +#define HIFN_CRYPT_CMD_NEW_KEY 0x0800 /* expect new key */
1276 +#define HIFN_CRYPT_CMD_NEW_IV 0x1000 /* expect new iv */
1277 +
1278 +#define HIFN_CRYPT_CMD_SRCLEN_M 0xc000
1279 +#define HIFN_CRYPT_CMD_SRCLEN_S 14
1280 +
1281 +#define HIFN_CRYPT_CMD_KSZ_MASK 0x0600 /* AES key size: */
1282 +#define HIFN_CRYPT_CMD_KSZ_128 0x0000 /* 128 bit */
1283 +#define HIFN_CRYPT_CMD_KSZ_192 0x0200 /* 192 bit */
1284 +#define HIFN_CRYPT_CMD_KSZ_256 0x0400 /* 256 bit */
1285 +
1286 +/*
1287 + * Structure to help build up the command data structure.
1288 + */
1289 +typedef struct hifn_mac_command {
1290 + volatile u_int16_t masks;
1291 + volatile u_int16_t header_skip;
1292 + volatile u_int16_t source_count;
1293 + volatile u_int16_t reserved;
1294 +} hifn_mac_command_t;
1295 +
1296 +#define HIFN_MAC_CMD_ALG_MASK 0x0001
1297 +#define HIFN_MAC_CMD_ALG_SHA1 0x0000
1298 +#define HIFN_MAC_CMD_ALG_MD5 0x0001
1299 +#define HIFN_MAC_CMD_MODE_MASK 0x000c
1300 +#define HIFN_MAC_CMD_MODE_HMAC 0x0000
1301 +#define HIFN_MAC_CMD_MODE_SSL_MAC 0x0004
1302 +#define HIFN_MAC_CMD_MODE_HASH 0x0008
1303 +#define HIFN_MAC_CMD_MODE_FULL 0x0004
1304 +#define HIFN_MAC_CMD_TRUNC 0x0010
1305 +#define HIFN_MAC_CMD_RESULT 0x0020
1306 +#define HIFN_MAC_CMD_APPEND 0x0040
1307 +#define HIFN_MAC_CMD_SRCLEN_M 0xc000
1308 +#define HIFN_MAC_CMD_SRCLEN_S 14
1309 +
1310 +/*
1311 + * MAC POS IPsec initiates authentication after encryption on encodes
1312 + * and before decryption on decodes.
1313 + */
1314 +#define HIFN_MAC_CMD_POS_IPSEC 0x0200
1315 +#define HIFN_MAC_CMD_NEW_KEY 0x0800
1316 +
1317 +/*
1318 + * The poll frequency and poll scalar defines are unshifted values used
1319 + * to set fields in the DMA Configuration Register.
1320 + */
1321 +#ifndef HIFN_POLL_FREQUENCY
1322 +#define HIFN_POLL_FREQUENCY 0x1
1323 +#endif
1324 +
1325 +#ifndef HIFN_POLL_SCALAR
1326 +#define HIFN_POLL_SCALAR 0x0
1327 +#endif
1328 +
1329 +#define HIFN_MAX_SEGLEN 0xffff /* maximum dma segment len */
1330 +#define HIFN_MAX_DMALEN 0x3ffff /* maximum dma length */
1331 +#endif /* __HIFN_H__ */
1332 --- /dev/null
1333 +++ b/crypto/ocf/hifn/hifn7751var.h
1334 @@ -0,0 +1,369 @@
1335 +/* $FreeBSD: src/sys/dev/hifn/hifn7751var.h,v 1.9 2007/03/21 03:42:49 sam Exp $ */
1336 +/* $OpenBSD: hifn7751var.h,v 1.42 2002/04/08 17:49:42 jason Exp $ */
1337 +
1338 +/*-
1339 + * Invertex AEON / Hifn 7751 driver
1340 + * Copyright (c) 1999 Invertex Inc. All rights reserved.
1341 + * Copyright (c) 1999 Theo de Raadt
1342 + * Copyright (c) 2000-2001 Network Security Technologies, Inc.
1343 + * http://www.netsec.net
1344 + *
1345 + * Please send any comments, feedback, bug-fixes, or feature requests to
1346 + * software@invertex.com.
1347 + *
1348 + * Redistribution and use in source and binary forms, with or without
1349 + * modification, are permitted provided that the following conditions
1350 + * are met:
1351 + *
1352 + * 1. Redistributions of source code must retain the above copyright
1353 + * notice, this list of conditions and the following disclaimer.
1354 + * 2. Redistributions in binary form must reproduce the above copyright
1355 + * notice, this list of conditions and the following disclaimer in the
1356 + * documentation and/or other materials provided with the distribution.
1357 + * 3. The name of the author may not be used to endorse or promote products
1358 + * derived from this software without specific prior written permission.
1359 + *
1360 + *
1361 + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
1362 + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
1363 + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
1364 + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
1365 + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
1366 + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
1367 + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
1368 + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
1369 + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
1370 + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
1371 + *
1372 + * Effort sponsored in part by the Defense Advanced Research Projects
1373 + * Agency (DARPA) and Air Force Research Laboratory, Air Force
1374 + * Materiel Command, USAF, under agreement number F30602-01-2-0537.
1375 + *
1376 + */
1377 +
1378 +#ifndef __HIFN7751VAR_H__
1379 +#define __HIFN7751VAR_H__
1380 +
1381 +#ifdef __KERNEL__
1382 +
1383 +/*
1384 + * Some configurable values for the driver. By default command+result
1385 + * descriptor rings are the same size. The src+dst descriptor rings
1386 + * are sized at 3.5x the number of potential commands. Slower parts
1387 + * (e.g. 7951) tend to run out of src descriptors; faster parts (7811)
1388 + * src+cmd/result descriptors. It's not clear that increasing the size
1389 + * of the descriptor rings helps performance significantly as other
1390 + * factors tend to come into play (e.g. copying misaligned packets).
1391 + */
1392 +#define HIFN_D_CMD_RSIZE 24 /* command descriptors */
1393 +#define HIFN_D_SRC_RSIZE ((HIFN_D_CMD_RSIZE * 7) / 2) /* source descriptors */
1394 +#define HIFN_D_RES_RSIZE HIFN_D_CMD_RSIZE /* result descriptors */
1395 +#define HIFN_D_DST_RSIZE HIFN_D_SRC_RSIZE /* destination descriptors */
1396 +
1397 +/*
1398 + * Length values for cryptography
1399 + */
1400 +#define HIFN_DES_KEY_LENGTH 8
1401 +#define HIFN_3DES_KEY_LENGTH 24
1402 +#define HIFN_MAX_CRYPT_KEY_LENGTH HIFN_3DES_KEY_LENGTH
1403 +#define HIFN_IV_LENGTH 8
1404 +#define HIFN_AES_IV_LENGTH 16
1405 +#define HIFN_MAX_IV_LENGTH HIFN_AES_IV_LENGTH
1406 +
1407 +/*
1408 + * Length values for authentication
1409 + */
1410 +#define HIFN_MAC_KEY_LENGTH 64
1411 +#define HIFN_MD5_LENGTH 16
1412 +#define HIFN_SHA1_LENGTH 20
1413 +#define HIFN_MAC_TRUNC_LENGTH 12
1414 +
1415 +#define MAX_SCATTER 64
1416 +
1417 +/*
1418 + * Data structure to hold all 4 rings and any other ring related data.
1419 + */
1420 +struct hifn_dma {
1421 + /*
1422 + * Descriptor rings. We add +1 to the size to accomidate the
1423 + * jump descriptor.
1424 + */
1425 + struct hifn_desc cmdr[HIFN_D_CMD_RSIZE+1];
1426 + struct hifn_desc srcr[HIFN_D_SRC_RSIZE+1];
1427 + struct hifn_desc dstr[HIFN_D_DST_RSIZE+1];
1428 + struct hifn_desc resr[HIFN_D_RES_RSIZE+1];
1429 +
1430 + struct hifn_command *hifn_commands[HIFN_D_RES_RSIZE];
1431 +
1432 + u_char command_bufs[HIFN_D_CMD_RSIZE][HIFN_MAX_COMMAND];
1433 + u_char result_bufs[HIFN_D_CMD_RSIZE][HIFN_MAX_RESULT];
1434 + u_int32_t slop[HIFN_D_CMD_RSIZE];
1435 +
1436 + u_int64_t test_src, test_dst;
1437 +
1438 + /*
1439 + * Our current positions for insertion and removal from the desriptor
1440 + * rings.
1441 + */
1442 + int cmdi, srci, dsti, resi;
1443 + volatile int cmdu, srcu, dstu, resu;
1444 + int cmdk, srck, dstk, resk;
1445 +};
1446 +
1447 +struct hifn_session {
1448 + int hs_used;
1449 + int hs_mlen;
1450 + u_int8_t hs_iv[HIFN_MAX_IV_LENGTH];
1451 +};
1452 +
1453 +#define HIFN_RING_SYNC(sc, r, i, f) \
1454 + /* DAVIDM bus_dmamap_sync((sc)->sc_dmat, (sc)->sc_dmamap, (f)) */
1455 +
1456 +#define HIFN_CMDR_SYNC(sc, i, f) HIFN_RING_SYNC((sc), cmdr, (i), (f))
1457 +#define HIFN_RESR_SYNC(sc, i, f) HIFN_RING_SYNC((sc), resr, (i), (f))
1458 +#define HIFN_SRCR_SYNC(sc, i, f) HIFN_RING_SYNC((sc), srcr, (i), (f))
1459 +#define HIFN_DSTR_SYNC(sc, i, f) HIFN_RING_SYNC((sc), dstr, (i), (f))
1460 +
1461 +#define HIFN_CMD_SYNC(sc, i, f) \
1462 + /* DAVIDM bus_dmamap_sync((sc)->sc_dmat, (sc)->sc_dmamap, (f)) */
1463 +
1464 +#define HIFN_RES_SYNC(sc, i, f) \
1465 + /* DAVIDM bus_dmamap_sync((sc)->sc_dmat, (sc)->sc_dmamap, (f)) */
1466 +
1467 +typedef int bus_size_t;
1468 +
1469 +/*
1470 + * Holds data specific to a single HIFN board.
1471 + */
1472 +struct hifn_softc {
1473 + softc_device_decl sc_dev;
1474 +
1475 + struct pci_dev *sc_pcidev; /* PCI device pointer */
1476 + spinlock_t sc_mtx; /* per-instance lock */
1477 +
1478 + int sc_num; /* for multiple devs */
1479 +
1480 + ocf_iomem_t sc_bar0;
1481 + bus_size_t sc_bar0_lastreg;/* bar0 last reg written */
1482 + ocf_iomem_t sc_bar1;
1483 + bus_size_t sc_bar1_lastreg;/* bar1 last reg written */
1484 +
1485 + int sc_irq;
1486 +
1487 + u_int32_t sc_dmaier;
1488 + u_int32_t sc_drammodel; /* 1=dram, 0=sram */
1489 + u_int32_t sc_pllconfig; /* 7954/7955/7956 PLL config */
1490 +
1491 + struct hifn_dma *sc_dma;
1492 + dma_addr_t sc_dma_physaddr;/* physical address of sc_dma */
1493 +
1494 + int sc_dmansegs;
1495 + int32_t sc_cid;
1496 + int sc_maxses;
1497 + int sc_nsessions;
1498 + struct hifn_session *sc_sessions;
1499 + int sc_ramsize;
1500 + int sc_flags;
1501 +#define HIFN_HAS_RNG 0x1 /* includes random number generator */
1502 +#define HIFN_HAS_PUBLIC 0x2 /* includes public key support */
1503 +#define HIFN_HAS_AES 0x4 /* includes AES support */
1504 +#define HIFN_IS_7811 0x8 /* Hifn 7811 part */
1505 +#define HIFN_IS_7956 0x10 /* Hifn 7956/7955 don't have SDRAM */
1506 +
1507 + struct timer_list sc_tickto; /* for managing DMA */
1508 +
1509 + int sc_rngfirst;
1510 + int sc_rnghz; /* RNG polling frequency */
1511 +
1512 + int sc_c_busy; /* command ring busy */
1513 + int sc_s_busy; /* source data ring busy */
1514 + int sc_d_busy; /* destination data ring busy */
1515 + int sc_r_busy; /* result ring busy */
1516 + int sc_active; /* for initial countdown */
1517 + int sc_needwakeup; /* ops q'd wating on resources */
1518 + int sc_curbatch; /* # ops submitted w/o int */
1519 + int sc_suspended;
1520 +#ifdef HIFN_VULCANDEV
1521 + struct cdev *sc_pkdev;
1522 +#endif
1523 +};
1524 +
1525 +#define HIFN_LOCK(_sc) spin_lock_irqsave(&(_sc)->sc_mtx, l_flags)
1526 +#define HIFN_UNLOCK(_sc) spin_unlock_irqrestore(&(_sc)->sc_mtx, l_flags)
1527 +
1528 +/*
1529 + * hifn_command_t
1530 + *
1531 + * This is the control structure used to pass commands to hifn_encrypt().
1532 + *
1533 + * flags
1534 + * -----
1535 + * Flags is the bitwise "or" values for command configuration. A single
1536 + * encrypt direction needs to be set:
1537 + *
1538 + * HIFN_ENCODE or HIFN_DECODE
1539 + *
1540 + * To use cryptography, a single crypto algorithm must be included:
1541 + *
1542 + * HIFN_CRYPT_3DES or HIFN_CRYPT_DES
1543 + *
1544 + * To use authentication is used, a single MAC algorithm must be included:
1545 + *
1546 + * HIFN_MAC_MD5 or HIFN_MAC_SHA1
1547 + *
1548 + * By default MD5 uses a 16 byte hash and SHA-1 uses a 20 byte hash.
1549 + * If the value below is set, hash values are truncated or assumed
1550 + * truncated to 12 bytes:
1551 + *
1552 + * HIFN_MAC_TRUNC
1553 + *
1554 + * Keys for encryption and authentication can be sent as part of a command,
1555 + * or the last key value used with a particular session can be retrieved
1556 + * and used again if either of these flags are not specified.
1557 + *
1558 + * HIFN_CRYPT_NEW_KEY, HIFN_MAC_NEW_KEY
1559 + *
1560 + * session_num
1561 + * -----------
1562 + * A number between 0 and 2048 (for DRAM models) or a number between
1563 + * 0 and 768 (for SRAM models). Those who don't want to use session
1564 + * numbers should leave value at zero and send a new crypt key and/or
1565 + * new MAC key on every command. If you use session numbers and
1566 + * don't send a key with a command, the last key sent for that same
1567 + * session number will be used.
1568 + *
1569 + * Warning: Using session numbers and multiboard at the same time
1570 + * is currently broken.
1571 + *
1572 + * mbuf
1573 + * ----
1574 + * Either fill in the mbuf pointer and npa=0 or
1575 + * fill packp[] and packl[] and set npa to > 0
1576 + *
1577 + * mac_header_skip
1578 + * ---------------
1579 + * The number of bytes of the source_buf that are skipped over before
1580 + * authentication begins. This must be a number between 0 and 2^16-1
1581 + * and can be used by IPsec implementers to skip over IP headers.
1582 + * *** Value ignored if authentication not used ***
1583 + *
1584 + * crypt_header_skip
1585 + * -----------------
1586 + * The number of bytes of the source_buf that are skipped over before
1587 + * the cryptographic operation begins. This must be a number between 0
1588 + * and 2^16-1. For IPsec, this number will always be 8 bytes larger
1589 + * than the auth_header_skip (to skip over the ESP header).
1590 + * *** Value ignored if cryptography not used ***
1591 + *
1592 + */
1593 +struct hifn_operand {
1594 + union {
1595 + struct sk_buff *skb;
1596 + struct uio *io;
1597 + unsigned char *buf;
1598 + } u;
1599 + void *map;
1600 + bus_size_t mapsize;
1601 + int nsegs;
1602 + struct {
1603 + dma_addr_t ds_addr;
1604 + int ds_len;
1605 + } segs[MAX_SCATTER];
1606 +};
1607 +
1608 +struct hifn_command {
1609 + u_int16_t session_num;
1610 + u_int16_t base_masks, cry_masks, mac_masks;
1611 + u_int8_t iv[HIFN_MAX_IV_LENGTH], *ck, mac[HIFN_MAC_KEY_LENGTH];
1612 + int cklen;
1613 + int sloplen, slopidx;
1614 +
1615 + struct hifn_operand src;
1616 + struct hifn_operand dst;
1617 +
1618 + struct hifn_softc *softc;
1619 + struct cryptop *crp;
1620 + struct cryptodesc *enccrd, *maccrd;
1621 +};
1622 +
1623 +#define src_skb src.u.skb
1624 +#define src_io src.u.io
1625 +#define src_map src.map
1626 +#define src_mapsize src.mapsize
1627 +#define src_segs src.segs
1628 +#define src_nsegs src.nsegs
1629 +#define src_buf src.u.buf
1630 +
1631 +#define dst_skb dst.u.skb
1632 +#define dst_io dst.u.io
1633 +#define dst_map dst.map
1634 +#define dst_mapsize dst.mapsize
1635 +#define dst_segs dst.segs
1636 +#define dst_nsegs dst.nsegs
1637 +#define dst_buf dst.u.buf
1638 +
1639 +/*
1640 + * Return values for hifn_crypto()
1641 + */
1642 +#define HIFN_CRYPTO_SUCCESS 0
1643 +#define HIFN_CRYPTO_BAD_INPUT (-1)
1644 +#define HIFN_CRYPTO_RINGS_FULL (-2)
1645 +
1646 +/**************************************************************************
1647 + *
1648 + * Function: hifn_crypto
1649 + *
1650 + * Purpose: Called by external drivers to begin an encryption on the
1651 + * HIFN board.
1652 + *
1653 + * Blocking/Non-blocking Issues
1654 + * ============================
1655 + * The driver cannot block in hifn_crypto (no calls to tsleep) currently.
1656 + * hifn_crypto() returns HIFN_CRYPTO_RINGS_FULL if there is not enough
1657 + * room in any of the rings for the request to proceed.
1658 + *
1659 + * Return Values
1660 + * =============
1661 + * 0 for success, negative values on error
1662 + *
1663 + * Defines for negative error codes are:
1664 + *
1665 + * HIFN_CRYPTO_BAD_INPUT : The passed in command had invalid settings.
1666 + * HIFN_CRYPTO_RINGS_FULL : All DMA rings were full and non-blocking
1667 + * behaviour was requested.
1668 + *
1669 + *************************************************************************/
1670 +
1671 +/*
1672 + * Convert back and forth from 'sid' to 'card' and 'session'
1673 + */
1674 +#define HIFN_CARD(sid) (((sid) & 0xf0000000) >> 28)
1675 +#define HIFN_SESSION(sid) ((sid) & 0x000007ff)
1676 +#define HIFN_SID(crd,ses) (((crd) << 28) | ((ses) & 0x7ff))
1677 +
1678 +#endif /* _KERNEL */
1679 +
1680 +struct hifn_stats {
1681 + u_int64_t hst_ibytes;
1682 + u_int64_t hst_obytes;
1683 + u_int32_t hst_ipackets;
1684 + u_int32_t hst_opackets;
1685 + u_int32_t hst_invalid;
1686 + u_int32_t hst_nomem; /* malloc or one of hst_nomem_* */
1687 + u_int32_t hst_abort;
1688 + u_int32_t hst_noirq; /* IRQ for no reason */
1689 + u_int32_t hst_totbatch; /* ops submitted w/o interrupt */
1690 + u_int32_t hst_maxbatch; /* max ops submitted together */
1691 + u_int32_t hst_unaligned; /* unaligned src caused copy */
1692 + /*
1693 + * The following divides hst_nomem into more specific buckets.
1694 + */
1695 + u_int32_t hst_nomem_map; /* bus_dmamap_create failed */
1696 + u_int32_t hst_nomem_load; /* bus_dmamap_load_* failed */
1697 + u_int32_t hst_nomem_mbuf; /* MGET* failed */
1698 + u_int32_t hst_nomem_mcl; /* MCLGET* failed */
1699 + u_int32_t hst_nomem_cr; /* out of command/result descriptor */
1700 + u_int32_t hst_nomem_sd; /* out of src/dst descriptors */
1701 +};
1702 +
1703 +#endif /* __HIFN7751VAR_H__ */
1704 --- /dev/null
1705 +++ b/crypto/ocf/hifn/hifn7751.c
1706 @@ -0,0 +1,2970 @@
1707 +/* $OpenBSD: hifn7751.c,v 1.120 2002/05/17 00:33:34 deraadt Exp $ */
1708 +
1709 +/*-
1710 + * Invertex AEON / Hifn 7751 driver
1711 + * Copyright (c) 1999 Invertex Inc. All rights reserved.
1712 + * Copyright (c) 1999 Theo de Raadt
1713 + * Copyright (c) 2000-2001 Network Security Technologies, Inc.
1714 + * http://www.netsec.net
1715 + * Copyright (c) 2003 Hifn Inc.
1716 + *
1717 + * This driver is based on a previous driver by Invertex, for which they
1718 + * requested: Please send any comments, feedback, bug-fixes, or feature
1719 + * requests to software@invertex.com.
1720 + *
1721 + * Redistribution and use in source and binary forms, with or without
1722 + * modification, are permitted provided that the following conditions
1723 + * are met:
1724 + *
1725 + * 1. Redistributions of source code must retain the above copyright
1726 + * notice, this list of conditions and the following disclaimer.
1727 + * 2. Redistributions in binary form must reproduce the above copyright
1728 + * notice, this list of conditions and the following disclaimer in the
1729 + * documentation and/or other materials provided with the distribution.
1730 + * 3. The name of the author may not be used to endorse or promote products
1731 + * derived from this software without specific prior written permission.
1732 + *
1733 + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
1734 + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
1735 + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
1736 + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
1737 + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
1738 + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
1739 + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
1740 + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
1741 + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
1742 + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
1743 + *
1744 + * Effort sponsored in part by the Defense Advanced Research Projects
1745 + * Agency (DARPA) and Air Force Research Laboratory, Air Force
1746 + * Materiel Command, USAF, under agreement number F30602-01-2-0537.
1747 + *
1748 + *
1749 +__FBSDID("$FreeBSD: src/sys/dev/hifn/hifn7751.c,v 1.40 2007/03/21 03:42:49 sam Exp $");
1750 + */
1751 +
1752 +/*
1753 + * Driver for various Hifn encryption processors.
1754 + */
1755 +#ifndef AUTOCONF_INCLUDED
1756 +#include <linux/config.h>
1757 +#endif
1758 +#include <linux/module.h>
1759 +#include <linux/init.h>
1760 +#include <linux/list.h>
1761 +#include <linux/slab.h>
1762 +#include <linux/wait.h>
1763 +#include <linux/sched.h>
1764 +#include <linux/pci.h>
1765 +#include <linux/delay.h>
1766 +#include <linux/interrupt.h>
1767 +#include <linux/spinlock.h>
1768 +#include <linux/random.h>
1769 +#include <linux/version.h>
1770 +#include <linux/skbuff.h>
1771 +#include <asm/io.h>
1772 +
1773 +#include <cryptodev.h>
1774 +#include <uio.h>
1775 +#include <hifn/hifn7751reg.h>
1776 +#include <hifn/hifn7751var.h>
1777 +
1778 +#if 1
1779 +#define DPRINTF(a...) if (hifn_debug) { \
1780 + printk("%s: ", sc ? \
1781 + device_get_nameunit(sc->sc_dev) : "hifn"); \
1782 + printk(a); \
1783 + } else
1784 +#else
1785 +#define DPRINTF(a...)
1786 +#endif
1787 +
1788 +static inline int
1789 +pci_get_revid(struct pci_dev *dev)
1790 +{
1791 + u8 rid = 0;
1792 + pci_read_config_byte(dev, PCI_REVISION_ID, &rid);
1793 + return rid;
1794 +}
1795 +
1796 +static struct hifn_stats hifnstats;
1797 +
1798 +#define debug hifn_debug
1799 +int hifn_debug = 0;
1800 +module_param(hifn_debug, int, 0644);
1801 +MODULE_PARM_DESC(hifn_debug, "Enable debug");
1802 +
1803 +int hifn_maxbatch = 1;
1804 +module_param(hifn_maxbatch, int, 0644);
1805 +MODULE_PARM_DESC(hifn_maxbatch, "max ops to batch w/o interrupt");
1806 +
1807 +#ifdef MODULE_PARM
1808 +char *hifn_pllconfig = NULL;
1809 +MODULE_PARM(hifn_pllconfig, "s");
1810 +#else
1811 +char hifn_pllconfig[32]; /* This setting is RO after loading */
1812 +module_param_string(hifn_pllconfig, hifn_pllconfig, 32, 0444);
1813 +#endif
1814 +MODULE_PARM_DESC(hifn_pllconfig, "PLL config, ie., pci66, ext33, ...");
1815 +
1816 +#ifdef HIFN_VULCANDEV
1817 +#include <sys/conf.h>
1818 +#include <sys/uio.h>
1819 +
1820 +static struct cdevsw vulcanpk_cdevsw; /* forward declaration */
1821 +#endif
1822 +
1823 +/*
1824 + * Prototypes and count for the pci_device structure
1825 + */
1826 +static int hifn_probe(struct pci_dev *dev, const struct pci_device_id *ent);
1827 +static void hifn_remove(struct pci_dev *dev);
1828 +
1829 +static int hifn_newsession(device_t, u_int32_t *, struct cryptoini *);
1830 +static int hifn_freesession(device_t, u_int64_t);
1831 +static int hifn_process(device_t, struct cryptop *, int);
1832 +
1833 +static device_method_t hifn_methods = {
1834 + /* crypto device methods */
1835 + DEVMETHOD(cryptodev_newsession, hifn_newsession),
1836 + DEVMETHOD(cryptodev_freesession,hifn_freesession),
1837 + DEVMETHOD(cryptodev_process, hifn_process),
1838 +};
1839 +
1840 +static void hifn_reset_board(struct hifn_softc *, int);
1841 +static void hifn_reset_puc(struct hifn_softc *);
1842 +static void hifn_puc_wait(struct hifn_softc *);
1843 +static int hifn_enable_crypto(struct hifn_softc *);
1844 +static void hifn_set_retry(struct hifn_softc *sc);
1845 +static void hifn_init_dma(struct hifn_softc *);
1846 +static void hifn_init_pci_registers(struct hifn_softc *);
1847 +static int hifn_sramsize(struct hifn_softc *);
1848 +static int hifn_dramsize(struct hifn_softc *);
1849 +static int hifn_ramtype(struct hifn_softc *);
1850 +static void hifn_sessions(struct hifn_softc *);
1851 +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,19)
1852 +static irqreturn_t hifn_intr(int irq, void *arg);
1853 +#else
1854 +static irqreturn_t hifn_intr(int irq, void *arg, struct pt_regs *regs);
1855 +#endif
1856 +static u_int hifn_write_command(struct hifn_command *, u_int8_t *);
1857 +static u_int32_t hifn_next_signature(u_int32_t a, u_int cnt);
1858 +static void hifn_callback(struct hifn_softc *, struct hifn_command *, u_int8_t *);
1859 +static int hifn_crypto(struct hifn_softc *, struct hifn_command *, struct cryptop *, int);
1860 +static int hifn_readramaddr(struct hifn_softc *, int, u_int8_t *);
1861 +static int hifn_writeramaddr(struct hifn_softc *, int, u_int8_t *);
1862 +static int hifn_dmamap_load_src(struct hifn_softc *, struct hifn_command *);
1863 +static int hifn_dmamap_load_dst(struct hifn_softc *, struct hifn_command *);
1864 +static int hifn_init_pubrng(struct hifn_softc *);
1865 +static void hifn_tick(unsigned long arg);
1866 +static void hifn_abort(struct hifn_softc *);
1867 +static void hifn_alloc_slot(struct hifn_softc *, int *, int *, int *, int *);
1868 +
1869 +static void hifn_write_reg_0(struct hifn_softc *, bus_size_t, u_int32_t);
1870 +static void hifn_write_reg_1(struct hifn_softc *, bus_size_t, u_int32_t);
1871 +
1872 +#ifdef CONFIG_OCF_RANDOMHARVEST
1873 +static int hifn_read_random(void *arg, u_int32_t *buf, int len);
1874 +#endif
1875 +
1876 +#define HIFN_MAX_CHIPS 8
1877 +static struct hifn_softc *hifn_chip_idx[HIFN_MAX_CHIPS];
1878 +
1879 +static __inline u_int32_t
1880 +READ_REG_0(struct hifn_softc *sc, bus_size_t reg)
1881 +{
1882 + u_int32_t v = readl(sc->sc_bar0 + reg);
1883 + sc->sc_bar0_lastreg = (bus_size_t) -1;
1884 + return (v);
1885 +}
1886 +#define WRITE_REG_0(sc, reg, val) hifn_write_reg_0(sc, reg, val)
1887 +
1888 +static __inline u_int32_t
1889 +READ_REG_1(struct hifn_softc *sc, bus_size_t reg)
1890 +{
1891 + u_int32_t v = readl(sc->sc_bar1 + reg);
1892 + sc->sc_bar1_lastreg = (bus_size_t) -1;
1893 + return (v);
1894 +}
1895 +#define WRITE_REG_1(sc, reg, val) hifn_write_reg_1(sc, reg, val)
1896 +
1897 +/*
1898 + * map in a given buffer (great on some arches :-)
1899 + */
1900 +
1901 +static int
1902 +pci_map_uio(struct hifn_softc *sc, struct hifn_operand *buf, struct uio *uio)
1903 +{
1904 + struct iovec *iov = uio->uio_iov;
1905 +
1906 + DPRINTF("%s()\n", __FUNCTION__);
1907 +
1908 + buf->mapsize = 0;
1909 + for (buf->nsegs = 0; buf->nsegs < uio->uio_iovcnt; ) {
1910 + buf->segs[buf->nsegs].ds_addr = pci_map_single(sc->sc_pcidev,
1911 + iov->iov_base, iov->iov_len,
1912 + PCI_DMA_BIDIRECTIONAL);
1913 + buf->segs[buf->nsegs].ds_len = iov->iov_len;
1914 + buf->mapsize += iov->iov_len;
1915 + iov++;
1916 + buf->nsegs++;
1917 + }
1918 + /* identify this buffer by the first segment */
1919 + buf->map = (void *) buf->segs[0].ds_addr;
1920 + return(0);
1921 +}
1922 +
1923 +/*
1924 + * map in a given sk_buff
1925 + */
1926 +
1927 +static int
1928 +pci_map_skb(struct hifn_softc *sc,struct hifn_operand *buf,struct sk_buff *skb)
1929 +{
1930 + int i;
1931 +
1932 + DPRINTF("%s()\n", __FUNCTION__);
1933 +
1934 + buf->mapsize = 0;
1935 +
1936 + buf->segs[0].ds_addr = pci_map_single(sc->sc_pcidev,
1937 + skb->data, skb_headlen(skb), PCI_DMA_BIDIRECTIONAL);
1938 + buf->segs[0].ds_len = skb_headlen(skb);
1939 + buf->mapsize += buf->segs[0].ds_len;
1940 +
1941 + buf->nsegs = 1;
1942 +
1943 + for (i = 0; i < skb_shinfo(skb)->nr_frags; ) {
1944 + buf->segs[buf->nsegs].ds_len = skb_shinfo(skb)->frags[i].size;
1945 + buf->segs[buf->nsegs].ds_addr = pci_map_single(sc->sc_pcidev,
1946 + page_address(skb_shinfo(skb)->frags[i].page) +
1947 + skb_shinfo(skb)->frags[i].page_offset,
1948 + buf->segs[buf->nsegs].ds_len, PCI_DMA_BIDIRECTIONAL);
1949 + buf->mapsize += buf->segs[buf->nsegs].ds_len;
1950 + buf->nsegs++;
1951 + }
1952 +
1953 + /* identify this buffer by the first segment */
1954 + buf->map = (void *) buf->segs[0].ds_addr;
1955 + return(0);
1956 +}
1957 +
1958 +/*
1959 + * map in a given contiguous buffer
1960 + */
1961 +
1962 +static int
1963 +pci_map_buf(struct hifn_softc *sc,struct hifn_operand *buf, void *b, int len)
1964 +{
1965 + DPRINTF("%s()\n", __FUNCTION__);
1966 +
1967 + buf->mapsize = 0;
1968 + buf->segs[0].ds_addr = pci_map_single(sc->sc_pcidev,
1969 + b, len, PCI_DMA_BIDIRECTIONAL);
1970 + buf->segs[0].ds_len = len;
1971 + buf->mapsize += buf->segs[0].ds_len;
1972 + buf->nsegs = 1;
1973 +
1974 + /* identify this buffer by the first segment */
1975 + buf->map = (void *) buf->segs[0].ds_addr;
1976 + return(0);
1977 +}
1978 +
1979 +#if 0 /* not needed at this time */
1980 +static void
1981 +pci_sync_iov(struct hifn_softc *sc, struct hifn_operand *buf)
1982 +{
1983 + int i;
1984 +
1985 + DPRINTF("%s()\n", __FUNCTION__);
1986 + for (i = 0; i < buf->nsegs; i++)
1987 + pci_dma_sync_single_for_cpu(sc->sc_pcidev, buf->segs[i].ds_addr,
1988 + buf->segs[i].ds_len, PCI_DMA_BIDIRECTIONAL);
1989 +}
1990 +#endif
1991 +
1992 +static void
1993 +pci_unmap_buf(struct hifn_softc *sc, struct hifn_operand *buf)
1994 +{
1995 + int i;
1996 + DPRINTF("%s()\n", __FUNCTION__);
1997 + for (i = 0; i < buf->nsegs; i++) {
1998 + pci_unmap_single(sc->sc_pcidev, buf->segs[i].ds_addr,
1999 + buf->segs[i].ds_len, PCI_DMA_BIDIRECTIONAL);
2000 + buf->segs[i].ds_addr = 0;
2001 + buf->segs[i].ds_len = 0;
2002 + }
2003 + buf->nsegs = 0;
2004 + buf->mapsize = 0;
2005 + buf->map = 0;
2006 +}
2007 +
2008 +static const char*
2009 +hifn_partname(struct hifn_softc *sc)
2010 +{
2011 + /* XXX sprintf numbers when not decoded */
2012 + switch (pci_get_vendor(sc->sc_pcidev)) {
2013 + case PCI_VENDOR_HIFN:
2014 + switch (pci_get_device(sc->sc_pcidev)) {
2015 + case PCI_PRODUCT_HIFN_6500: return "Hifn 6500";
2016 + case PCI_PRODUCT_HIFN_7751: return "Hifn 7751";
2017 + case PCI_PRODUCT_HIFN_7811: return "Hifn 7811";
2018 + case PCI_PRODUCT_HIFN_7951: return "Hifn 7951";
2019 + case PCI_PRODUCT_HIFN_7955: return "Hifn 7955";
2020 + case PCI_PRODUCT_HIFN_7956: return "Hifn 7956";
2021 + }
2022 + return "Hifn unknown-part";
2023 + case PCI_VENDOR_INVERTEX:
2024 + switch (pci_get_device(sc->sc_pcidev)) {
2025 + case PCI_PRODUCT_INVERTEX_AEON: return "Invertex AEON";
2026 + }
2027 + return "Invertex unknown-part";
2028 + case PCI_VENDOR_NETSEC:
2029 + switch (pci_get_device(sc->sc_pcidev)) {
2030 + case PCI_PRODUCT_NETSEC_7751: return "NetSec 7751";
2031 + }
2032 + return "NetSec unknown-part";
2033 + }
2034 + return "Unknown-vendor unknown-part";
2035 +}
2036 +
2037 +static u_int
2038 +checkmaxmin(struct pci_dev *dev, const char *what, u_int v, u_int min, u_int max)
2039 +{
2040 + struct hifn_softc *sc = pci_get_drvdata(dev);
2041 + if (v > max) {
2042 + device_printf(sc->sc_dev, "Warning, %s %u out of range, "
2043 + "using max %u\n", what, v, max);
2044 + v = max;
2045 + } else if (v < min) {
2046 + device_printf(sc->sc_dev, "Warning, %s %u out of range, "
2047 + "using min %u\n", what, v, min);
2048 + v = min;
2049 + }
2050 + return v;
2051 +}
2052 +
2053 +/*
2054 + * Select PLL configuration for 795x parts. This is complicated in
2055 + * that we cannot determine the optimal parameters without user input.
2056 + * The reference clock is derived from an external clock through a
2057 + * multiplier. The external clock is either the host bus (i.e. PCI)
2058 + * or an external clock generator. When using the PCI bus we assume
2059 + * the clock is either 33 or 66 MHz; for an external source we cannot
2060 + * tell the speed.
2061 + *
2062 + * PLL configuration is done with a string: "pci" for PCI bus, or "ext"
2063 + * for an external source, followed by the frequency. We calculate
2064 + * the appropriate multiplier and PLL register contents accordingly.
2065 + * When no configuration is given we default to "pci66" since that
2066 + * always will allow the card to work. If a card is using the PCI
2067 + * bus clock and in a 33MHz slot then it will be operating at half
2068 + * speed until the correct information is provided.
2069 + *
2070 + * We use a default setting of "ext66" because according to Mike Ham
2071 + * of HiFn, almost every board in existence has an external crystal
2072 + * populated at 66Mhz. Using PCI can be a problem on modern motherboards,
2073 + * because PCI33 can have clocks from 0 to 33Mhz, and some have
2074 + * non-PCI-compliant spread-spectrum clocks, which can confuse the pll.
2075 + */
2076 +static void
2077 +hifn_getpllconfig(struct pci_dev *dev, u_int *pll)
2078 +{
2079 + const char *pllspec = hifn_pllconfig;
2080 + u_int freq, mul, fl, fh;
2081 + u_int32_t pllconfig;
2082 + char *nxt;
2083 +
2084 + if (pllspec == NULL)
2085 + pllspec = "ext66";
2086 + fl = 33, fh = 66;
2087 + pllconfig = 0;
2088 + if (strncmp(pllspec, "ext", 3) == 0) {
2089 + pllspec += 3;
2090 + pllconfig |= HIFN_PLL_REF_SEL;
2091 + switch (pci_get_device(dev)) {
2092 + case PCI_PRODUCT_HIFN_7955:
2093 + case PCI_PRODUCT_HIFN_7956:
2094 + fl = 20, fh = 100;
2095 + break;
2096 +#ifdef notyet
2097 + case PCI_PRODUCT_HIFN_7954:
2098 + fl = 20, fh = 66;
2099 + break;
2100 +#endif
2101 + }
2102 + } else if (strncmp(pllspec, "pci", 3) == 0)
2103 + pllspec += 3;
2104 + freq = strtoul(pllspec, &nxt, 10);
2105 + if (nxt == pllspec)
2106 + freq = 66;
2107 + else
2108 + freq = checkmaxmin(dev, "frequency", freq, fl, fh);
2109 + /*
2110 + * Calculate multiplier. We target a Fck of 266 MHz,
2111 + * allowing only even values, possibly rounded down.
2112 + * Multipliers > 8 must set the charge pump current.
2113 + */
2114 + mul = checkmaxmin(dev, "PLL divisor", (266 / freq) &~ 1, 2, 12);
2115 + pllconfig |= (mul / 2 - 1) << HIFN_PLL_ND_SHIFT;
2116 + if (mul > 8)
2117 + pllconfig |= HIFN_PLL_IS;
2118 + *pll = pllconfig;
2119 +}
2120 +
2121 +/*
2122 + * Attach an interface that successfully probed.
2123 + */
2124 +static int
2125 +hifn_probe(struct pci_dev *dev, const struct pci_device_id *ent)
2126 +{
2127 + struct hifn_softc *sc = NULL;
2128 + char rbase;
2129 + u_int16_t ena, rev;
2130 + int rseg, rc;
2131 + unsigned long mem_start, mem_len;
2132 + static int num_chips = 0;
2133 +
2134 + DPRINTF("%s()\n", __FUNCTION__);
2135 +
2136 + if (pci_enable_device(dev) < 0)
2137 + return(-ENODEV);
2138 +
2139 + if (pci_set_mwi(dev))
2140 + return(-ENODEV);
2141 +
2142 + if (!dev->irq) {
2143 + printk("hifn: found device with no IRQ assigned. check BIOS settings!");
2144 + pci_disable_device(dev);
2145 + return(-ENODEV);
2146 + }
2147 +
2148 + sc = (struct hifn_softc *) kmalloc(sizeof(*sc), GFP_KERNEL);
2149 + if (!sc)
2150 + return(-ENOMEM);
2151 + memset(sc, 0, sizeof(*sc));
2152 +
2153 + softc_device_init(sc, "hifn", num_chips, hifn_methods);
2154 +
2155 + sc->sc_pcidev = dev;
2156 + sc->sc_irq = -1;
2157 + sc->sc_cid = -1;
2158 + sc->sc_num = num_chips++;
2159 + if (sc->sc_num < HIFN_MAX_CHIPS)
2160 + hifn_chip_idx[sc->sc_num] = sc;
2161 +
2162 + pci_set_drvdata(sc->sc_pcidev, sc);
2163 +
2164 + spin_lock_init(&sc->sc_mtx);
2165 +
2166 + /* XXX handle power management */
2167 +
2168 + /*
2169 + * The 7951 and 795x have a random number generator and
2170 + * public key support; note this.
2171 + */
2172 + if (pci_get_vendor(dev) == PCI_VENDOR_HIFN &&
2173 + (pci_get_device(dev) == PCI_PRODUCT_HIFN_7951 ||
2174 + pci_get_device(dev) == PCI_PRODUCT_HIFN_7955 ||
2175 + pci_get_device(dev) == PCI_PRODUCT_HIFN_7956))
2176 + sc->sc_flags = HIFN_HAS_RNG | HIFN_HAS_PUBLIC;
2177 + /*
2178 + * The 7811 has a random number generator and
2179 + * we also note it's identity 'cuz of some quirks.
2180 + */
2181 + if (pci_get_vendor(dev) == PCI_VENDOR_HIFN &&
2182 + pci_get_device(dev) == PCI_PRODUCT_HIFN_7811)
2183 + sc->sc_flags |= HIFN_IS_7811 | HIFN_HAS_RNG;
2184 +
2185 + /*
2186 + * The 795x parts support AES.
2187 + */
2188 + if (pci_get_vendor(dev) == PCI_VENDOR_HIFN &&
2189 + (pci_get_device(dev) == PCI_PRODUCT_HIFN_7955 ||
2190 + pci_get_device(dev) == PCI_PRODUCT_HIFN_7956)) {
2191 + sc->sc_flags |= HIFN_IS_7956 | HIFN_HAS_AES;
2192 + /*
2193 + * Select PLL configuration. This depends on the
2194 + * bus and board design and must be manually configured
2195 + * if the default setting is unacceptable.
2196 + */
2197 + hifn_getpllconfig(dev, &sc->sc_pllconfig);
2198 + }
2199 +
2200 + /*
2201 + * Setup PCI resources. Note that we record the bus
2202 + * tag and handle for each register mapping, this is
2203 + * used by the READ_REG_0, WRITE_REG_0, READ_REG_1,
2204 + * and WRITE_REG_1 macros throughout the driver.
2205 + */
2206 + mem_start = pci_resource_start(sc->sc_pcidev, 0);
2207 + mem_len = pci_resource_len(sc->sc_pcidev, 0);
2208 + sc->sc_bar0 = (ocf_iomem_t) ioremap(mem_start, mem_len);
2209 + if (!sc->sc_bar0) {
2210 + device_printf(sc->sc_dev, "cannot map bar%d register space\n", 0);
2211 + goto fail;
2212 + }
2213 + sc->sc_bar0_lastreg = (bus_size_t) -1;
2214 +
2215 + mem_start = pci_resource_start(sc->sc_pcidev, 1);
2216 + mem_len = pci_resource_len(sc->sc_pcidev, 1);
2217 + sc->sc_bar1 = (ocf_iomem_t) ioremap(mem_start, mem_len);
2218 + if (!sc->sc_bar1) {
2219 + device_printf(sc->sc_dev, "cannot map bar%d register space\n", 1);
2220 + goto fail;
2221 + }
2222 + sc->sc_bar1_lastreg = (bus_size_t) -1;
2223 +
2224 + /* fix up the bus size */
2225 + if (pci_set_dma_mask(dev, DMA_32BIT_MASK)) {
2226 + device_printf(sc->sc_dev, "No usable DMA configuration, aborting.\n");
2227 + goto fail;
2228 + }
2229 + if (pci_set_consistent_dma_mask(dev, DMA_32BIT_MASK)) {
2230 + device_printf(sc->sc_dev,
2231 + "No usable consistent DMA configuration, aborting.\n");
2232 + goto fail;
2233 + }
2234 +
2235 + hifn_set_retry(sc);
2236 +
2237 + /*
2238 + * Setup the area where the Hifn DMA's descriptors
2239 + * and associated data structures.
2240 + */
2241 + sc->sc_dma = (struct hifn_dma *) pci_alloc_consistent(dev,
2242 + sizeof(*sc->sc_dma),
2243 + &sc->sc_dma_physaddr);
2244 + if (!sc->sc_dma) {
2245 + device_printf(sc->sc_dev, "cannot alloc sc_dma\n");
2246 + goto fail;
2247 + }
2248 + bzero(sc->sc_dma, sizeof(*sc->sc_dma));
2249 +
2250 + /*
2251 + * Reset the board and do the ``secret handshake''
2252 + * to enable the crypto support. Then complete the
2253 + * initialization procedure by setting up the interrupt
2254 + * and hooking in to the system crypto support so we'll
2255 + * get used for system services like the crypto device,
2256 + * IPsec, RNG device, etc.
2257 + */
2258 + hifn_reset_board(sc, 0);
2259 +
2260 + if (hifn_enable_crypto(sc) != 0) {
2261 + device_printf(sc->sc_dev, "crypto enabling failed\n");
2262 + goto fail;
2263 + }
2264 + hifn_reset_puc(sc);
2265 +
2266 + hifn_init_dma(sc);
2267 + hifn_init_pci_registers(sc);
2268 +
2269 + pci_set_master(sc->sc_pcidev);
2270 +
2271 + /* XXX can't dynamically determine ram type for 795x; force dram */
2272 + if (sc->sc_flags & HIFN_IS_7956)
2273 + sc->sc_drammodel = 1;
2274 + else if (hifn_ramtype(sc))
2275 + goto fail;
2276 +
2277 + if (sc->sc_drammodel == 0)
2278 + hifn_sramsize(sc);
2279 + else
2280 + hifn_dramsize(sc);
2281 +
2282 + /*
2283 + * Workaround for NetSec 7751 rev A: half ram size because two
2284 + * of the address lines were left floating
2285 + */
2286 + if (pci_get_vendor(dev) == PCI_VENDOR_NETSEC &&
2287 + pci_get_device(dev) == PCI_PRODUCT_NETSEC_7751 &&
2288 + pci_get_revid(dev) == 0x61) /*XXX???*/
2289 + sc->sc_ramsize >>= 1;
2290 +
2291 + /*
2292 + * Arrange the interrupt line.
2293 + */
2294 + rc = request_irq(dev->irq, hifn_intr, IRQF_SHARED, "hifn", sc);
2295 + if (rc) {
2296 + device_printf(sc->sc_dev, "could not map interrupt: %d\n", rc);
2297 + goto fail;
2298 + }
2299 + sc->sc_irq = dev->irq;
2300 +
2301 + hifn_sessions(sc);
2302 +
2303 + /*
2304 + * NB: Keep only the low 16 bits; this masks the chip id
2305 + * from the 7951.
2306 + */
2307 + rev = READ_REG_1(sc, HIFN_1_REVID) & 0xffff;
2308 +
2309 + rseg = sc->sc_ramsize / 1024;
2310 + rbase = 'K';
2311 + if (sc->sc_ramsize >= (1024 * 1024)) {
2312 + rbase = 'M';
2313 + rseg /= 1024;
2314 + }
2315 + device_printf(sc->sc_dev, "%s, rev %u, %d%cB %cram",
2316 + hifn_partname(sc), rev,
2317 + rseg, rbase, sc->sc_drammodel ? 'd' : 's');
2318 + if (sc->sc_flags & HIFN_IS_7956)
2319 + printf(", pll=0x%x<%s clk, %ux mult>",
2320 + sc->sc_pllconfig,
2321 + sc->sc_pllconfig & HIFN_PLL_REF_SEL ? "ext" : "pci",
2322 + 2 + 2*((sc->sc_pllconfig & HIFN_PLL_ND) >> 11));
2323 + printf("\n");
2324 +
2325 + sc->sc_cid = crypto_get_driverid(softc_get_device(sc),CRYPTOCAP_F_HARDWARE);
2326 + if (sc->sc_cid < 0) {
2327 + device_printf(sc->sc_dev, "could not get crypto driver id\n");
2328 + goto fail;
2329 + }
2330 +
2331 + WRITE_REG_0(sc, HIFN_0_PUCNFG,
2332 + READ_REG_0(sc, HIFN_0_PUCNFG) | HIFN_PUCNFG_CHIPID);
2333 + ena = READ_REG_0(sc, HIFN_0_PUSTAT) & HIFN_PUSTAT_CHIPENA;
2334 +
2335 + switch (ena) {
2336 + case HIFN_PUSTAT_ENA_2:
2337 + crypto_register(sc->sc_cid, CRYPTO_3DES_CBC, 0, 0);
2338 + crypto_register(sc->sc_cid, CRYPTO_ARC4, 0, 0);
2339 + if (sc->sc_flags & HIFN_HAS_AES)
2340 + crypto_register(sc->sc_cid, CRYPTO_AES_CBC, 0, 0);
2341 + /*FALLTHROUGH*/
2342 + case HIFN_PUSTAT_ENA_1:
2343 + crypto_register(sc->sc_cid, CRYPTO_MD5, 0, 0);
2344 + crypto_register(sc->sc_cid, CRYPTO_SHA1, 0, 0);
2345 + crypto_register(sc->sc_cid, CRYPTO_MD5_HMAC, 0, 0);
2346 + crypto_register(sc->sc_cid, CRYPTO_SHA1_HMAC, 0, 0);
2347 + crypto_register(sc->sc_cid, CRYPTO_DES_CBC, 0, 0);
2348 + break;
2349 + }
2350 +
2351 + if (sc->sc_flags & (HIFN_HAS_PUBLIC | HIFN_HAS_RNG))
2352 + hifn_init_pubrng(sc);
2353 +
2354 + init_timer(&sc->sc_tickto);
2355 + sc->sc_tickto.function = hifn_tick;
2356 + sc->sc_tickto.data = (unsigned long) sc->sc_num;
2357 + mod_timer(&sc->sc_tickto, jiffies + HZ);
2358 +
2359 + return (0);
2360 +
2361 +fail:
2362 + if (sc->sc_cid >= 0)
2363 + crypto_unregister_all(sc->sc_cid);
2364 + if (sc->sc_irq != -1)
2365 + free_irq(sc->sc_irq, sc);
2366 + if (sc->sc_dma) {
2367 + /* Turn off DMA polling */
2368 + WRITE_REG_1(sc, HIFN_1_DMA_CNFG, HIFN_DMACNFG_MSTRESET |
2369 + HIFN_DMACNFG_DMARESET | HIFN_DMACNFG_MODE);
2370 +
2371 + pci_free_consistent(sc->sc_pcidev,
2372 + sizeof(*sc->sc_dma),
2373 + sc->sc_dma, sc->sc_dma_physaddr);
2374 + }
2375 + kfree(sc);
2376 + return (-ENXIO);
2377 +}
2378 +
2379 +/*
2380 + * Detach an interface that successfully probed.
2381 + */
2382 +static void
2383 +hifn_remove(struct pci_dev *dev)
2384 +{
2385 + struct hifn_softc *sc = pci_get_drvdata(dev);
2386 + unsigned long l_flags;
2387 +
2388 + DPRINTF("%s()\n", __FUNCTION__);
2389 +
2390 + KASSERT(sc != NULL, ("hifn_detach: null software carrier!"));
2391 +
2392 + /* disable interrupts */
2393 + HIFN_LOCK(sc);
2394 + WRITE_REG_1(sc, HIFN_1_DMA_IER, 0);
2395 + HIFN_UNLOCK(sc);
2396 +
2397 + /*XXX other resources */
2398 + del_timer_sync(&sc->sc_tickto);
2399 +
2400 + /* Turn off DMA polling */
2401 + WRITE_REG_1(sc, HIFN_1_DMA_CNFG, HIFN_DMACNFG_MSTRESET |
2402 + HIFN_DMACNFG_DMARESET | HIFN_DMACNFG_MODE);
2403 +
2404 + crypto_unregister_all(sc->sc_cid);
2405 +
2406 + free_irq(sc->sc_irq, sc);
2407 +
2408 + pci_free_consistent(sc->sc_pcidev, sizeof(*sc->sc_dma),
2409 + sc->sc_dma, sc->sc_dma_physaddr);
2410 +}
2411 +
2412 +
2413 +static int
2414 +hifn_init_pubrng(struct hifn_softc *sc)
2415 +{
2416 + int i;
2417 +
2418 + DPRINTF("%s()\n", __FUNCTION__);
2419 +
2420 + if ((sc->sc_flags & HIFN_IS_7811) == 0) {
2421 + /* Reset 7951 public key/rng engine */
2422 + WRITE_REG_1(sc, HIFN_1_PUB_RESET,
2423 + READ_REG_1(sc, HIFN_1_PUB_RESET) | HIFN_PUBRST_RESET);
2424 +
2425 + for (i = 0; i < 100; i++) {
2426 + DELAY(1000);
2427 + if ((READ_REG_1(sc, HIFN_1_PUB_RESET) &
2428 + HIFN_PUBRST_RESET) == 0)
2429 + break;
2430 + }
2431 +
2432 + if (i == 100) {
2433 + device_printf(sc->sc_dev, "public key init failed\n");
2434 + return (1);
2435 + }
2436 + }
2437 +
2438 + /* Enable the rng, if available */
2439 +#ifdef CONFIG_OCF_RANDOMHARVEST
2440 + if (sc->sc_flags & HIFN_HAS_RNG) {
2441 + if (sc->sc_flags & HIFN_IS_7811) {
2442 + u_int32_t r;
2443 + r = READ_REG_1(sc, HIFN_1_7811_RNGENA);
2444 + if (r & HIFN_7811_RNGENA_ENA) {
2445 + r &= ~HIFN_7811_RNGENA_ENA;
2446 + WRITE_REG_1(sc, HIFN_1_7811_RNGENA, r);
2447 + }
2448 + WRITE_REG_1(sc, HIFN_1_7811_RNGCFG,
2449 + HIFN_7811_RNGCFG_DEFL);
2450 + r |= HIFN_7811_RNGENA_ENA;
2451 + WRITE_REG_1(sc, HIFN_1_7811_RNGENA, r);
2452 + } else
2453 + WRITE_REG_1(sc, HIFN_1_RNG_CONFIG,
2454 + READ_REG_1(sc, HIFN_1_RNG_CONFIG) |
2455 + HIFN_RNGCFG_ENA);
2456 +
2457 + sc->sc_rngfirst = 1;
2458 + crypto_rregister(sc->sc_cid, hifn_read_random, sc);
2459 + }
2460 +#endif
2461 +
2462 + /* Enable public key engine, if available */
2463 + if (sc->sc_flags & HIFN_HAS_PUBLIC) {
2464 + WRITE_REG_1(sc, HIFN_1_PUB_IEN, HIFN_PUBIEN_DONE);
2465 + sc->sc_dmaier |= HIFN_DMAIER_PUBDONE;
2466 + WRITE_REG_1(sc, HIFN_1_DMA_IER, sc->sc_dmaier);
2467 +#ifdef HIFN_VULCANDEV
2468 + sc->sc_pkdev = make_dev(&vulcanpk_cdevsw, 0,
2469 + UID_ROOT, GID_WHEEL, 0666,
2470 + "vulcanpk");
2471 + sc->sc_pkdev->si_drv1 = sc;
2472 +#endif
2473 + }
2474 +
2475 + return (0);
2476 +}
2477 +
2478 +#ifdef CONFIG_OCF_RANDOMHARVEST
2479 +static int
2480 +hifn_read_random(void *arg, u_int32_t *buf, int len)
2481 +{
2482 + struct hifn_softc *sc = (struct hifn_softc *) arg;
2483 + u_int32_t sts;
2484 + int i, rc = 0;
2485 +
2486 + if (len <= 0)
2487 + return rc;
2488 +
2489 + if (sc->sc_flags & HIFN_IS_7811) {
2490 + /* ONLY VALID ON 7811!!!! */
2491 + for (i = 0; i < 5; i++) {
2492 + sts = READ_REG_1(sc, HIFN_1_7811_RNGSTS);
2493 + if (sts & HIFN_7811_RNGSTS_UFL) {
2494 + device_printf(sc->sc_dev,
2495 + "RNG underflow: disabling\n");
2496 + /* DAVIDM perhaps return -1 */
2497 + break;
2498 + }
2499 + if ((sts & HIFN_7811_RNGSTS_RDY) == 0)
2500 + break;
2501 +
2502 + /*
2503 + * There are at least two words in the RNG FIFO
2504 + * at this point.
2505 + */
2506 + if (rc < len)
2507 + buf[rc++] = READ_REG_1(sc, HIFN_1_7811_RNGDAT);
2508 + if (rc < len)
2509 + buf[rc++] = READ_REG_1(sc, HIFN_1_7811_RNGDAT);
2510 + }
2511 + } else
2512 + buf[rc++] = READ_REG_1(sc, HIFN_1_RNG_DATA);
2513 +
2514 + /* NB: discard first data read */
2515 + if (sc->sc_rngfirst) {
2516 + sc->sc_rngfirst = 0;
2517 + rc = 0;
2518 + }
2519 +
2520 + return(rc);
2521 +}
2522 +#endif /* CONFIG_OCF_RANDOMHARVEST */
2523 +
2524 +static void
2525 +hifn_puc_wait(struct hifn_softc *sc)
2526 +{
2527 + int i;
2528 + int reg = HIFN_0_PUCTRL;
2529 +
2530 + if (sc->sc_flags & HIFN_IS_7956) {
2531 + reg = HIFN_0_PUCTRL2;
2532 + }
2533 +
2534 + for (i = 5000; i > 0; i--) {
2535 + DELAY(1);
2536 + if (!(READ_REG_0(sc, reg) & HIFN_PUCTRL_RESET))
2537 + break;
2538 + }
2539 + if (!i)
2540 + device_printf(sc->sc_dev, "proc unit did not reset(0x%x)\n",
2541 + READ_REG_0(sc, HIFN_0_PUCTRL));
2542 +}
2543 +
2544 +/*
2545 + * Reset the processing unit.
2546 + */
2547 +static void
2548 +hifn_reset_puc(struct hifn_softc *sc)
2549 +{
2550 + /* Reset processing unit */
2551 + int reg = HIFN_0_PUCTRL;
2552 +
2553 + if (sc->sc_flags & HIFN_IS_7956) {
2554 + reg = HIFN_0_PUCTRL2;
2555 + }
2556 + WRITE_REG_0(sc, reg, HIFN_PUCTRL_DMAENA);
2557 +
2558 + hifn_puc_wait(sc);
2559 +}
2560 +
2561 +/*
2562 + * Set the Retry and TRDY registers; note that we set them to
2563 + * zero because the 7811 locks up when forced to retry (section
2564 + * 3.6 of "Specification Update SU-0014-04". Not clear if we
2565 + * should do this for all Hifn parts, but it doesn't seem to hurt.
2566 + */
2567 +static void
2568 +hifn_set_retry(struct hifn_softc *sc)
2569 +{
2570 + DPRINTF("%s()\n", __FUNCTION__);
2571 + /* NB: RETRY only responds to 8-bit reads/writes */
2572 + pci_write_config_byte(sc->sc_pcidev, HIFN_RETRY_TIMEOUT, 0);
2573 + pci_write_config_dword(sc->sc_pcidev, HIFN_TRDY_TIMEOUT, 0);
2574 +}
2575 +
2576 +/*
2577 + * Resets the board. Values in the regesters are left as is
2578 + * from the reset (i.e. initial values are assigned elsewhere).
2579 + */
2580 +static void
2581 +hifn_reset_board(struct hifn_softc *sc, int full)
2582 +{
2583 + u_int32_t reg;
2584 +
2585 + DPRINTF("%s()\n", __FUNCTION__);
2586 + /*
2587 + * Set polling in the DMA configuration register to zero. 0x7 avoids
2588 + * resetting the board and zeros out the other fields.
2589 + */
2590 + WRITE_REG_1(sc, HIFN_1_DMA_CNFG, HIFN_DMACNFG_MSTRESET |
2591 + HIFN_DMACNFG_DMARESET | HIFN_DMACNFG_MODE);
2592 +
2593 + /*
2594 + * Now that polling has been disabled, we have to wait 1 ms
2595 + * before resetting the board.
2596 + */
2597 + DELAY(1000);
2598 +
2599 + /* Reset the DMA unit */
2600 + if (full) {
2601 + WRITE_REG_1(sc, HIFN_1_DMA_CNFG, HIFN_DMACNFG_MODE);
2602 + DELAY(1000);
2603 + } else {
2604 + WRITE_REG_1(sc, HIFN_1_DMA_CNFG,
2605 + HIFN_DMACNFG_MODE | HIFN_DMACNFG_MSTRESET);
2606 + hifn_reset_puc(sc);
2607 + }
2608 +
2609 + KASSERT(sc->sc_dma != NULL, ("hifn_reset_board: null DMA tag!"));
2610 + bzero(sc->sc_dma, sizeof(*sc->sc_dma));
2611 +
2612 + /* Bring dma unit out of reset */
2613 + WRITE_REG_1(sc, HIFN_1_DMA_CNFG, HIFN_DMACNFG_MSTRESET |
2614 + HIFN_DMACNFG_DMARESET | HIFN_DMACNFG_MODE);
2615 +
2616 + hifn_puc_wait(sc);
2617 + hifn_set_retry(sc);
2618 +
2619 + if (sc->sc_flags & HIFN_IS_7811) {
2620 + for (reg = 0; reg < 1000; reg++) {
2621 + if (READ_REG_1(sc, HIFN_1_7811_MIPSRST) &
2622 + HIFN_MIPSRST_CRAMINIT)
2623 + break;
2624 + DELAY(1000);
2625 + }
2626 + if (reg == 1000)
2627 + device_printf(sc->sc_dev, ": cram init timeout\n");
2628 + } else {
2629 + /* set up DMA configuration register #2 */
2630 + /* turn off all PK and BAR0 swaps */
2631 + WRITE_REG_1(sc, HIFN_1_DMA_CNFG2,
2632 + (3 << HIFN_DMACNFG2_INIT_WRITE_BURST_SHIFT)|
2633 + (3 << HIFN_DMACNFG2_INIT_READ_BURST_SHIFT)|
2634 + (2 << HIFN_DMACNFG2_TGT_WRITE_BURST_SHIFT)|
2635 + (2 << HIFN_DMACNFG2_TGT_READ_BURST_SHIFT));
2636 + }
2637 +}
2638 +
2639 +static u_int32_t
2640 +hifn_next_signature(u_int32_t a, u_int cnt)
2641 +{
2642 + int i;
2643 + u_int32_t v;
2644 +
2645 + for (i = 0; i < cnt; i++) {
2646 +
2647 + /* get the parity */
2648 + v = a & 0x80080125;
2649 + v ^= v >> 16;
2650 + v ^= v >> 8;
2651 + v ^= v >> 4;
2652 + v ^= v >> 2;
2653 + v ^= v >> 1;
2654 +
2655 + a = (v & 1) ^ (a << 1);
2656 + }
2657 +
2658 + return a;
2659 +}
2660 +
2661 +
2662 +/*
2663 + * Checks to see if crypto is already enabled. If crypto isn't enable,
2664 + * "hifn_enable_crypto" is called to enable it. The check is important,
2665 + * as enabling crypto twice will lock the board.
2666 + */
2667 +static int
2668 +hifn_enable_crypto(struct hifn_softc *sc)
2669 +{
2670 + u_int32_t dmacfg, ramcfg, encl, addr, i;
2671 + char offtbl[] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2672 + 0x00, 0x00, 0x00, 0x00 };
2673 +
2674 + DPRINTF("%s()\n", __FUNCTION__);
2675 +
2676 + ramcfg = READ_REG_0(sc, HIFN_0_PUCNFG);
2677 + dmacfg = READ_REG_1(sc, HIFN_1_DMA_CNFG);
2678 +
2679 + /*
2680 + * The RAM config register's encrypt level bit needs to be set before
2681 + * every read performed on the encryption level register.
2682 + */
2683 + WRITE_REG_0(sc, HIFN_0_PUCNFG, ramcfg | HIFN_PUCNFG_CHIPID);
2684 +
2685 + encl = READ_REG_0(sc, HIFN_0_PUSTAT) & HIFN_PUSTAT_CHIPENA;
2686 +
2687 + /*
2688 + * Make sure we don't re-unlock. Two unlocks kills chip until the
2689 + * next reboot.
2690 + */
2691 + if (encl == HIFN_PUSTAT_ENA_1 || encl == HIFN_PUSTAT_ENA_2) {
2692 +#ifdef HIFN_DEBUG
2693 + if (hifn_debug)
2694 + device_printf(sc->sc_dev,
2695 + "Strong crypto already enabled!\n");
2696 +#endif
2697 + goto report;
2698 + }
2699 +
2700 + if (encl != 0 && encl != HIFN_PUSTAT_ENA_0) {
2701 +#ifdef HIFN_DEBUG
2702 + if (hifn_debug)
2703 + device_printf(sc->sc_dev,
2704 + "Unknown encryption level 0x%x\n", encl);
2705 +#endif
2706 + return 1;
2707 + }
2708 +
2709 + WRITE_REG_1(sc, HIFN_1_DMA_CNFG, HIFN_DMACNFG_UNLOCK |
2710 + HIFN_DMACNFG_MSTRESET | HIFN_DMACNFG_DMARESET | HIFN_DMACNFG_MODE);
2711 + DELAY(1000);
2712 + addr = READ_REG_1(sc, HIFN_UNLOCK_SECRET1);
2713 + DELAY(1000);
2714 + WRITE_REG_1(sc, HIFN_UNLOCK_SECRET2, 0);
2715 + DELAY(1000);
2716 +
2717 + for (i = 0; i <= 12; i++) {
2718 + addr = hifn_next_signature(addr, offtbl[i] + 0x101);
2719 + WRITE_REG_1(sc, HIFN_UNLOCK_SECRET2, addr);
2720 +
2721 + DELAY(1000);
2722 + }
2723 +
2724 + WRITE_REG_0(sc, HIFN_0_PUCNFG, ramcfg | HIFN_PUCNFG_CHIPID);
2725 + encl = READ_REG_0(sc, HIFN_0_PUSTAT) & HIFN_PUSTAT_CHIPENA;
2726 +
2727 +#ifdef HIFN_DEBUG
2728 + if (hifn_debug) {
2729 + if (encl != HIFN_PUSTAT_ENA_1 && encl != HIFN_PUSTAT_ENA_2)
2730 + device_printf(sc->sc_dev, "Engine is permanently "
2731 + "locked until next system reset!\n");
2732 + else
2733 + device_printf(sc->sc_dev, "Engine enabled "
2734 + "successfully!\n");
2735 + }
2736 +#endif
2737 +
2738 +report:
2739 + WRITE_REG_0(sc, HIFN_0_PUCNFG, ramcfg);
2740 + WRITE_REG_1(sc, HIFN_1_DMA_CNFG, dmacfg);
2741 +
2742 + switch (encl) {
2743 + case HIFN_PUSTAT_ENA_1:
2744 + case HIFN_PUSTAT_ENA_2:
2745 + break;
2746 + case HIFN_PUSTAT_ENA_0:
2747 + default:
2748 + device_printf(sc->sc_dev, "disabled\n");
2749 + break;
2750 + }
2751 +
2752 + return 0;
2753 +}
2754 +
2755 +/*
2756 + * Give initial values to the registers listed in the "Register Space"
2757 + * section of the HIFN Software Development reference manual.
2758 + */
2759 +static void
2760 +hifn_init_pci_registers(struct hifn_softc *sc)
2761 +{
2762 + DPRINTF("%s()\n", __FUNCTION__);
2763 +
2764 + /* write fixed values needed by the Initialization registers */
2765 + WRITE_REG_0(sc, HIFN_0_PUCTRL, HIFN_PUCTRL_DMAENA);
2766 + WRITE_REG_0(sc, HIFN_0_FIFOCNFG, HIFN_FIFOCNFG_THRESHOLD);
2767 + WRITE_REG_0(sc, HIFN_0_PUIER, HIFN_PUIER_DSTOVER);
2768 +
2769 + /* write all 4 ring address registers */
2770 + WRITE_REG_1(sc, HIFN_1_DMA_CRAR, sc->sc_dma_physaddr +
2771 + offsetof(struct hifn_dma, cmdr[0]));
2772 + WRITE_REG_1(sc, HIFN_1_DMA_SRAR, sc->sc_dma_physaddr +
2773 + offsetof(struct hifn_dma, srcr[0]));
2774 + WRITE_REG_1(sc, HIFN_1_DMA_DRAR, sc->sc_dma_physaddr +
2775 + offsetof(struct hifn_dma, dstr[0]));
2776 + WRITE_REG_1(sc, HIFN_1_DMA_RRAR, sc->sc_dma_physaddr +
2777 + offsetof(struct hifn_dma, resr[0]));
2778 +
2779 + DELAY(2000);
2780 +
2781 + /* write status register */
2782 + WRITE_REG_1(sc, HIFN_1_DMA_CSR,
2783 + HIFN_DMACSR_D_CTRL_DIS | HIFN_DMACSR_R_CTRL_DIS |
2784 + HIFN_DMACSR_S_CTRL_DIS | HIFN_DMACSR_C_CTRL_DIS |
2785 + HIFN_DMACSR_D_ABORT | HIFN_DMACSR_D_DONE | HIFN_DMACSR_D_LAST |
2786 + HIFN_DMACSR_D_WAIT | HIFN_DMACSR_D_OVER |
2787 + HIFN_DMACSR_R_ABORT | HIFN_DMACSR_R_DONE | HIFN_DMACSR_R_LAST |
2788 + HIFN_DMACSR_R_WAIT | HIFN_DMACSR_R_OVER |
2789 + HIFN_DMACSR_S_ABORT | HIFN_DMACSR_S_DONE | HIFN_DMACSR_S_LAST |
2790 + HIFN_DMACSR_S_WAIT |
2791 + HIFN_DMACSR_C_ABORT | HIFN_DMACSR_C_DONE | HIFN_DMACSR_C_LAST |
2792 + HIFN_DMACSR_C_WAIT |
2793 + HIFN_DMACSR_ENGINE |
2794 + ((sc->sc_flags & HIFN_HAS_PUBLIC) ?
2795 + HIFN_DMACSR_PUBDONE : 0) |
2796 + ((sc->sc_flags & HIFN_IS_7811) ?
2797 + HIFN_DMACSR_ILLW | HIFN_DMACSR_ILLR : 0));
2798 +
2799 + sc->sc_d_busy = sc->sc_r_busy = sc->sc_s_busy = sc->sc_c_busy = 0;
2800 + sc->sc_dmaier |= HIFN_DMAIER_R_DONE | HIFN_DMAIER_C_ABORT |
2801 + HIFN_DMAIER_D_OVER | HIFN_DMAIER_R_OVER |
2802 + HIFN_DMAIER_S_ABORT | HIFN_DMAIER_D_ABORT | HIFN_DMAIER_R_ABORT |
2803 + ((sc->sc_flags & HIFN_IS_7811) ?
2804 + HIFN_DMAIER_ILLW | HIFN_DMAIER_ILLR : 0);
2805 + sc->sc_dmaier &= ~HIFN_DMAIER_C_WAIT;
2806 + WRITE_REG_1(sc, HIFN_1_DMA_IER, sc->sc_dmaier);
2807 +
2808 +
2809 + if (sc->sc_flags & HIFN_IS_7956) {
2810 + u_int32_t pll;
2811 +
2812 + WRITE_REG_0(sc, HIFN_0_PUCNFG, HIFN_PUCNFG_COMPSING |
2813 + HIFN_PUCNFG_TCALLPHASES |
2814 + HIFN_PUCNFG_TCDRVTOTEM | HIFN_PUCNFG_BUS32);
2815 +
2816 + /* turn off the clocks and insure bypass is set */
2817 + pll = READ_REG_1(sc, HIFN_1_PLL);
2818 + pll = (pll &~ (HIFN_PLL_PK_CLK_SEL | HIFN_PLL_PE_CLK_SEL))
2819 + | HIFN_PLL_BP | HIFN_PLL_MBSET;
2820 + WRITE_REG_1(sc, HIFN_1_PLL, pll);
2821 + DELAY(10*1000); /* 10ms */
2822 +
2823 + /* change configuration */
2824 + pll = (pll &~ HIFN_PLL_CONFIG) | sc->sc_pllconfig;
2825 + WRITE_REG_1(sc, HIFN_1_PLL, pll);
2826 + DELAY(10*1000); /* 10ms */
2827 +
2828 + /* disable bypass */
2829 + pll &= ~HIFN_PLL_BP;
2830 + WRITE_REG_1(sc, HIFN_1_PLL, pll);
2831 + /* enable clocks with new configuration */
2832 + pll |= HIFN_PLL_PK_CLK_SEL | HIFN_PLL_PE_CLK_SEL;
2833 + WRITE_REG_1(sc, HIFN_1_PLL, pll);
2834 + } else {
2835 + WRITE_REG_0(sc, HIFN_0_PUCNFG, HIFN_PUCNFG_COMPSING |
2836 + HIFN_PUCNFG_DRFR_128 | HIFN_PUCNFG_TCALLPHASES |
2837 + HIFN_PUCNFG_TCDRVTOTEM | HIFN_PUCNFG_BUS32 |
2838 + (sc->sc_drammodel ? HIFN_PUCNFG_DRAM : HIFN_PUCNFG_SRAM));
2839 + }
2840 +
2841 + WRITE_REG_0(sc, HIFN_0_PUISR, HIFN_PUISR_DSTOVER);
2842 + WRITE_REG_1(sc, HIFN_1_DMA_CNFG, HIFN_DMACNFG_MSTRESET |
2843 + HIFN_DMACNFG_DMARESET | HIFN_DMACNFG_MODE | HIFN_DMACNFG_LAST |
2844 + ((HIFN_POLL_FREQUENCY << 16 ) & HIFN_DMACNFG_POLLFREQ) |
2845 + ((HIFN_POLL_SCALAR << 8) & HIFN_DMACNFG_POLLINVAL));
2846 +}
2847 +
2848 +/*
2849 + * The maximum number of sessions supported by the card
2850 + * is dependent on the amount of context ram, which
2851 + * encryption algorithms are enabled, and how compression
2852 + * is configured. This should be configured before this
2853 + * routine is called.
2854 + */
2855 +static void
2856 +hifn_sessions(struct hifn_softc *sc)
2857 +{
2858 + u_int32_t pucnfg;
2859 + int ctxsize;
2860 +
2861 + DPRINTF("%s()\n", __FUNCTION__);
2862 +
2863 + pucnfg = READ_REG_0(sc, HIFN_0_PUCNFG);
2864 +
2865 + if (pucnfg & HIFN_PUCNFG_COMPSING) {
2866 + if (pucnfg & HIFN_PUCNFG_ENCCNFG)
2867 + ctxsize = 128;
2868 + else
2869 + ctxsize = 512;
2870 + /*
2871 + * 7955/7956 has internal context memory of 32K
2872 + */
2873 + if (sc->sc_flags & HIFN_IS_7956)
2874 + sc->sc_maxses = 32768 / ctxsize;
2875 + else
2876 + sc->sc_maxses = 1 +
2877 + ((sc->sc_ramsize - 32768) / ctxsize);
2878 + } else
2879 + sc->sc_maxses = sc->sc_ramsize / 16384;
2880 +
2881 + if (sc->sc_maxses > 2048)
2882 + sc->sc_maxses = 2048;
2883 +}
2884 +
2885 +/*
2886 + * Determine ram type (sram or dram). Board should be just out of a reset
2887 + * state when this is called.
2888 + */
2889 +static int
2890 +hifn_ramtype(struct hifn_softc *sc)
2891 +{
2892 + u_int8_t data[8], dataexpect[8];
2893 + int i;
2894 +
2895 + for (i = 0; i < sizeof(data); i++)
2896 + data[i] = dataexpect[i] = 0x55;
2897 + if (hifn_writeramaddr(sc, 0, data))
2898 + return (-1);
2899 + if (hifn_readramaddr(sc, 0, data))
2900 + return (-1);
2901 + if (bcmp(data, dataexpect, sizeof(data)) != 0) {
2902 + sc->sc_drammodel = 1;
2903 + return (0);
2904 + }
2905 +
2906 + for (i = 0; i < sizeof(data); i++)
2907 + data[i] = dataexpect[i] = 0xaa;
2908 + if (hifn_writeramaddr(sc, 0, data))
2909 + return (-1);
2910 + if (hifn_readramaddr(sc, 0, data))
2911 + return (-1);
2912 + if (bcmp(data, dataexpect, sizeof(data)) != 0) {
2913 + sc->sc_drammodel = 1;
2914 + return (0);
2915 + }
2916 +
2917 + return (0);
2918 +}
2919 +
2920 +#define HIFN_SRAM_MAX (32 << 20)
2921 +#define HIFN_SRAM_STEP_SIZE 16384
2922 +#define HIFN_SRAM_GRANULARITY (HIFN_SRAM_MAX / HIFN_SRAM_STEP_SIZE)
2923 +
2924 +static int
2925 +hifn_sramsize(struct hifn_softc *sc)
2926 +{
2927 + u_int32_t a;
2928 + u_int8_t data[8];
2929 + u_int8_t dataexpect[sizeof(data)];
2930 + int32_t i;
2931 +
2932 + for (i = 0; i < sizeof(data); i++)
2933 + data[i] = dataexpect[i] = i ^ 0x5a;
2934 +
2935 + for (i = HIFN_SRAM_GRANULARITY - 1; i >= 0; i--) {
2936 + a = i * HIFN_SRAM_STEP_SIZE;
2937 + bcopy(&i, data, sizeof(i));
2938 + hifn_writeramaddr(sc, a, data);
2939 + }
2940 +
2941 + for (i = 0; i < HIFN_SRAM_GRANULARITY; i++) {
2942 + a = i * HIFN_SRAM_STEP_SIZE;
2943 + bcopy(&i, dataexpect, sizeof(i));
2944 + if (hifn_readramaddr(sc, a, data) < 0)
2945 + return (0);
2946 + if (bcmp(data, dataexpect, sizeof(data)) != 0)
2947 + return (0);
2948 + sc->sc_ramsize = a + HIFN_SRAM_STEP_SIZE;
2949 + }
2950 +
2951 + return (0);
2952 +}
2953 +
2954 +/*
2955 + * XXX For dram boards, one should really try all of the
2956 + * HIFN_PUCNFG_DSZ_*'s. This just assumes that PUCNFG
2957 + * is already set up correctly.
2958 + */
2959 +static int
2960 +hifn_dramsize(struct hifn_softc *sc)
2961 +{
2962 + u_int32_t cnfg;
2963 +
2964 + if (sc->sc_flags & HIFN_IS_7956) {
2965 + /*
2966 + * 7955/7956 have a fixed internal ram of only 32K.
2967 + */
2968 + sc->sc_ramsize = 32768;
2969 + } else {
2970 + cnfg = READ_REG_0(sc, HIFN_0_PUCNFG) &
2971 + HIFN_PUCNFG_DRAMMASK;
2972 + sc->sc_ramsize = 1 << ((cnfg >> 13) + 18);
2973 + }
2974 + return (0);
2975 +}
2976 +
2977 +static void
2978 +hifn_alloc_slot(struct hifn_softc *sc, int *cmdp, int *srcp, int *dstp, int *resp)
2979 +{
2980 + struct hifn_dma *dma = sc->sc_dma;
2981 +
2982 + DPRINTF("%s()\n", __FUNCTION__);
2983 +
2984 + if (dma->cmdi == HIFN_D_CMD_RSIZE) {
2985 + dma->cmdi = 0;
2986 + dma->cmdr[HIFN_D_CMD_RSIZE].l = htole32(HIFN_D_JUMP|HIFN_D_MASKDONEIRQ);
2987 + wmb();
2988 + dma->cmdr[HIFN_D_CMD_RSIZE].l |= htole32(HIFN_D_VALID);
2989 + HIFN_CMDR_SYNC(sc, HIFN_D_CMD_RSIZE,
2990 + BUS_DMASYNC_PREWRITE | BUS_DMASYNC_PREREAD);
2991 + }
2992 + *cmdp = dma->cmdi++;
2993 + dma->cmdk = dma->cmdi;
2994 +
2995 + if (dma->srci == HIFN_D_SRC_RSIZE) {
2996 + dma->srci = 0;
2997 + dma->srcr[HIFN_D_SRC_RSIZE].l = htole32(HIFN_D_JUMP|HIFN_D_MASKDONEIRQ);
2998 + wmb();
2999 + dma->srcr[HIFN_D_SRC_RSIZE].l |= htole32(HIFN_D_VALID);
3000 + HIFN_SRCR_SYNC(sc, HIFN_D_SRC_RSIZE,
3001 + BUS_DMASYNC_PREWRITE | BUS_DMASYNC_PREREAD);
3002 + }
3003 + *srcp = dma->srci++;
3004 + dma->srck = dma->srci;
3005 +
3006 + if (dma->dsti == HIFN_D_DST_RSIZE) {
3007 + dma->dsti = 0;
3008 + dma->dstr[HIFN_D_DST_RSIZE].l = htole32(HIFN_D_JUMP|HIFN_D_MASKDONEIRQ);
3009 + wmb();
3010 + dma->dstr[HIFN_D_DST_RSIZE].l |= htole32(HIFN_D_VALID);
3011 + HIFN_DSTR_SYNC(sc, HIFN_D_DST_RSIZE,
3012 + BUS_DMASYNC_PREWRITE | BUS_DMASYNC_PREREAD);
3013 + }
3014 + *dstp = dma->dsti++;
3015 + dma->dstk = dma->dsti;
3016 +
3017 + if (dma->resi == HIFN_D_RES_RSIZE) {
3018 + dma->resi = 0;
3019 + dma->resr[HIFN_D_RES_RSIZE].l = htole32(HIFN_D_JUMP|HIFN_D_MASKDONEIRQ);
3020 + wmb();
3021 + dma->resr[HIFN_D_RES_RSIZE].l |= htole32(HIFN_D_VALID);
3022 + HIFN_RESR_SYNC(sc, HIFN_D_RES_RSIZE,
3023 + BUS_DMASYNC_PREWRITE | BUS_DMASYNC_PREREAD);
3024 + }
3025 + *resp = dma->resi++;
3026 + dma->resk = dma->resi;
3027 +}
3028 +
3029 +static int
3030 +hifn_writeramaddr(struct hifn_softc *sc, int addr, u_int8_t *data)
3031 +{
3032 + struct hifn_dma *dma = sc->sc_dma;
3033 + hifn_base_command_t wc;
3034 + const u_int32_t masks = HIFN_D_VALID | HIFN_D_LAST | HIFN_D_MASKDONEIRQ;
3035 + int r, cmdi, resi, srci, dsti;
3036 +
3037 + DPRINTF("%s()\n", __FUNCTION__);
3038 +
3039 + wc.masks = htole16(3 << 13);
3040 + wc.session_num = htole16(addr >> 14);
3041 + wc.total_source_count = htole16(8);
3042 + wc.total_dest_count = htole16(addr & 0x3fff);
3043 +
3044 + hifn_alloc_slot(sc, &cmdi, &srci, &dsti, &resi);
3045 +
3046 + WRITE_REG_1(sc, HIFN_1_DMA_CSR,
3047 + HIFN_DMACSR_C_CTRL_ENA | HIFN_DMACSR_S_CTRL_ENA |
3048 + HIFN_DMACSR_D_CTRL_ENA | HIFN_DMACSR_R_CTRL_ENA);
3049 +
3050 + /* build write command */
3051 + bzero(dma->command_bufs[cmdi], HIFN_MAX_COMMAND);
3052 + *(hifn_base_command_t *)dma->command_bufs[cmdi] = wc;
3053 + bcopy(data, &dma->test_src, sizeof(dma->test_src));
3054 +
3055 + dma->srcr[srci].p = htole32(sc->sc_dma_physaddr
3056 + + offsetof(struct hifn_dma, test_src));
3057 + dma->dstr[dsti].p = htole32(sc->sc_dma_physaddr
3058 + + offsetof(struct hifn_dma, test_dst));
3059 +
3060 + dma->cmdr[cmdi].l = htole32(16 | masks);
3061 + dma->srcr[srci].l = htole32(8 | masks);
3062 + dma->dstr[dsti].l = htole32(4 | masks);
3063 + dma->resr[resi].l = htole32(4 | masks);
3064 +
3065 + for (r = 10000; r >= 0; r--) {
3066 + DELAY(10);
3067 + if ((dma->resr[resi].l & htole32(HIFN_D_VALID)) == 0)
3068 + break;
3069 + }
3070 + if (r == 0) {
3071 + device_printf(sc->sc_dev, "writeramaddr -- "
3072 + "result[%d](addr %d) still valid\n", resi, addr);
3073 + r = -1;
3074 + return (-1);
3075 + } else
3076 + r = 0;
3077 +
3078 + WRITE_REG_1(sc, HIFN_1_DMA_CSR,
3079 + HIFN_DMACSR_C_CTRL_DIS | HIFN_DMACSR_S_CTRL_DIS |
3080 + HIFN_DMACSR_D_CTRL_DIS | HIFN_DMACSR_R_CTRL_DIS);
3081 +
3082 + return (r);
3083 +}
3084 +
3085 +static int
3086 +hifn_readramaddr(struct hifn_softc *sc, int addr, u_int8_t *data)
3087 +{
3088 + struct hifn_dma *dma = sc->sc_dma;
3089 + hifn_base_command_t rc;
3090 + const u_int32_t masks = HIFN_D_VALID | HIFN_D_LAST | HIFN_D_MASKDONEIRQ;
3091 + int r, cmdi, srci, dsti, resi;
3092 +
3093 + DPRINTF("%s()\n", __FUNCTION__);
3094 +
3095 + rc.masks = htole16(2 << 13);
3096 + rc.session_num = htole16(addr >> 14);
3097 + rc.total_source_count = htole16(addr & 0x3fff);
3098 + rc.total_dest_count = htole16(8);
3099 +
3100 + hifn_alloc_slot(sc, &cmdi, &srci, &dsti, &resi);
3101 +
3102 + WRITE_REG_1(sc, HIFN_1_DMA_CSR,
3103 + HIFN_DMACSR_C_CTRL_ENA | HIFN_DMACSR_S_CTRL_ENA |
3104 + HIFN_DMACSR_D_CTRL_ENA | HIFN_DMACSR_R_CTRL_ENA);
3105 +
3106 + bzero(dma->command_bufs[cmdi], HIFN_MAX_COMMAND);
3107 + *(hifn_base_command_t *)dma->command_bufs[cmdi] = rc;
3108 +
3109 + dma->srcr[srci].p = htole32(sc->sc_dma_physaddr +
3110 + offsetof(struct hifn_dma, test_src));
3111 + dma->test_src = 0;
3112 + dma->dstr[dsti].p = htole32(sc->sc_dma_physaddr +
3113 + offsetof(struct hifn_dma, test_dst));
3114 + dma->test_dst = 0;
3115 + dma->cmdr[cmdi].l = htole32(8 | masks);
3116 + dma->srcr[srci].l = htole32(8 | masks);
3117 + dma->dstr[dsti].l = htole32(8 | masks);
3118 + dma->resr[resi].l = htole32(HIFN_MAX_RESULT | masks);
3119 +
3120 + for (r = 10000; r >= 0; r--) {
3121 + DELAY(10);
3122 + if ((dma->resr[resi].l & htole32(HIFN_D_VALID)) == 0)
3123 + break;
3124 + }
3125 + if (r == 0) {
3126 + device_printf(sc->sc_dev, "readramaddr -- "
3127 + "result[%d](addr %d) still valid\n", resi, addr);
3128 + r = -1;
3129 + } else {
3130 + r = 0;
3131 + bcopy(&dma->test_dst, data, sizeof(dma->test_dst));
3132 + }
3133 +
3134 + WRITE_REG_1(sc, HIFN_1_DMA_CSR,
3135 + HIFN_DMACSR_C_CTRL_DIS | HIFN_DMACSR_S_CTRL_DIS |
3136 + HIFN_DMACSR_D_CTRL_DIS | HIFN_DMACSR_R_CTRL_DIS);
3137 +
3138 + return (r);
3139 +}
3140 +
3141 +/*
3142 + * Initialize the descriptor rings.
3143 + */
3144 +static void
3145 +hifn_init_dma(struct hifn_softc *sc)
3146 +{
3147 + struct hifn_dma *dma = sc->sc_dma;
3148 + int i;
3149 +
3150 + DPRINTF("%s()\n", __FUNCTION__);
3151 +
3152 + hifn_set_retry(sc);
3153 +
3154 + /* initialize static pointer values */
3155 + for (i = 0; i < HIFN_D_CMD_RSIZE; i++)
3156 + dma->cmdr[i].p = htole32(sc->sc_dma_physaddr +
3157 + offsetof(struct hifn_dma, command_bufs[i][0]));
3158 + for (i = 0; i < HIFN_D_RES_RSIZE; i++)
3159 + dma->resr[i].p = htole32(sc->sc_dma_physaddr +
3160 + offsetof(struct hifn_dma, result_bufs[i][0]));
3161 +
3162 + dma->cmdr[HIFN_D_CMD_RSIZE].p =
3163 + htole32(sc->sc_dma_physaddr + offsetof(struct hifn_dma, cmdr[0]));
3164 + dma->srcr[HIFN_D_SRC_RSIZE].p =
3165 + htole32(sc->sc_dma_physaddr + offsetof(struct hifn_dma, srcr[0]));
3166 + dma->dstr[HIFN_D_DST_RSIZE].p =
3167 + htole32(sc->sc_dma_physaddr + offsetof(struct hifn_dma, dstr[0]));
3168 + dma->resr[HIFN_D_RES_RSIZE].p =
3169 + htole32(sc->sc_dma_physaddr + offsetof(struct hifn_dma, resr[0]));
3170 +
3171 + dma->cmdu = dma->srcu = dma->dstu = dma->resu = 0;
3172 + dma->cmdi = dma->srci = dma->dsti = dma->resi = 0;
3173 + dma->cmdk = dma->srck = dma->dstk = dma->resk = 0;
3174 +}
3175 +
3176 +/*
3177 + * Writes out the raw command buffer space. Returns the
3178 + * command buffer size.
3179 + */
3180 +static u_int
3181 +hifn_write_command(struct hifn_command *cmd, u_int8_t *buf)
3182 +{
3183 + struct hifn_softc *sc = NULL;
3184 + u_int8_t *buf_pos;
3185 + hifn_base_command_t *base_cmd;
3186 + hifn_mac_command_t *mac_cmd;
3187 + hifn_crypt_command_t *cry_cmd;
3188 + int using_mac, using_crypt, len, ivlen;
3189 + u_int32_t dlen, slen;
3190 +
3191 + DPRINTF("%s()\n", __FUNCTION__);
3192 +
3193 + buf_pos = buf;
3194 + using_mac = cmd->base_masks & HIFN_BASE_CMD_MAC;
3195 + using_crypt = cmd->base_masks & HIFN_BASE_CMD_CRYPT;
3196 +
3197 + base_cmd = (hifn_base_command_t *)buf_pos;
3198 + base_cmd->masks = htole16(cmd->base_masks);
3199 + slen = cmd->src_mapsize;
3200 + if (cmd->sloplen)
3201 + dlen = cmd->dst_mapsize - cmd->sloplen + sizeof(u_int32_t);
3202 + else
3203 + dlen = cmd->dst_mapsize;
3204 + base_cmd->total_source_count = htole16(slen & HIFN_BASE_CMD_LENMASK_LO);
3205 + base_cmd->total_dest_count = htole16(dlen & HIFN_BASE_CMD_LENMASK_LO);
3206 + dlen >>= 16;
3207 + slen >>= 16;
3208 + base_cmd->session_num = htole16(
3209 + ((slen << HIFN_BASE_CMD_SRCLEN_S) & HIFN_BASE_CMD_SRCLEN_M) |
3210 + ((dlen << HIFN_BASE_CMD_DSTLEN_S) & HIFN_BASE_CMD_DSTLEN_M));
3211 + buf_pos += sizeof(hifn_base_command_t);
3212 +
3213 + if (using_mac) {
3214 + mac_cmd = (hifn_mac_command_t *)buf_pos;
3215 + dlen = cmd->maccrd->crd_len;
3216 + mac_cmd->source_count = htole16(dlen & 0xffff);
3217 + dlen >>= 16;
3218 + mac_cmd->masks = htole16(cmd->mac_masks |
3219 + ((dlen << HIFN_MAC_CMD_SRCLEN_S) & HIFN_MAC_CMD_SRCLEN_M));
3220 + mac_cmd->header_skip = htole16(cmd->maccrd->crd_skip);
3221 + mac_cmd->reserved = 0;
3222 + buf_pos += sizeof(hifn_mac_command_t);
3223 + }
3224 +
3225 + if (using_crypt) {
3226 + cry_cmd = (hifn_crypt_command_t *)buf_pos;
3227 + dlen = cmd->enccrd->crd_len;
3228 + cry_cmd->source_count = htole16(dlen & 0xffff);
3229 + dlen >>= 16;
3230 + cry_cmd->masks = htole16(cmd->cry_masks |
3231 + ((dlen << HIFN_CRYPT_CMD_SRCLEN_S) & HIFN_CRYPT_CMD_SRCLEN_M));
3232 + cry_cmd->header_skip = htole16(cmd->enccrd->crd_skip);
3233 + cry_cmd->reserved = 0;
3234 + buf_pos += sizeof(hifn_crypt_command_t);
3235 + }
3236 +
3237 + if (using_mac && cmd->mac_masks & HIFN_MAC_CMD_NEW_KEY) {
3238 + bcopy(cmd->mac, buf_pos, HIFN_MAC_KEY_LENGTH);
3239 + buf_pos += HIFN_MAC_KEY_LENGTH;
3240 + }
3241 +
3242 + if (using_crypt && cmd->cry_masks & HIFN_CRYPT_CMD_NEW_KEY) {
3243 + switch (cmd->cry_masks & HIFN_CRYPT_CMD_ALG_MASK) {
3244 + case HIFN_CRYPT_CMD_ALG_3DES:
3245 + bcopy(cmd->ck, buf_pos, HIFN_3DES_KEY_LENGTH);
3246 + buf_pos += HIFN_3DES_KEY_LENGTH;
3247 + break;
3248 + case HIFN_CRYPT_CMD_ALG_DES:
3249 + bcopy(cmd->ck, buf_pos, HIFN_DES_KEY_LENGTH);
3250 + buf_pos += HIFN_DES_KEY_LENGTH;
3251 + break;
3252 + case HIFN_CRYPT_CMD_ALG_RC4:
3253 + len = 256;
3254 + do {
3255 + int clen;
3256 +
3257 + clen = MIN(cmd->cklen, len);
3258 + bcopy(cmd->ck, buf_pos, clen);
3259 + len -= clen;
3260 + buf_pos += clen;
3261 + } while (len > 0);
3262 + bzero(buf_pos, 4);
3263 + buf_pos += 4;
3264 + break;
3265 + case HIFN_CRYPT_CMD_ALG_AES:
3266 + /*
3267 + * AES keys are variable 128, 192 and
3268 + * 256 bits (16, 24 and 32 bytes).
3269 + */
3270 + bcopy(cmd->ck, buf_pos, cmd->cklen);
3271 + buf_pos += cmd->cklen;
3272 + break;
3273 + }
3274 + }
3275 +
3276 + if (using_crypt && cmd->cry_masks & HIFN_CRYPT_CMD_NEW_IV) {
3277 + switch (cmd->cry_masks & HIFN_CRYPT_CMD_ALG_MASK) {
3278 + case HIFN_CRYPT_CMD_ALG_AES:
3279 + ivlen = HIFN_AES_IV_LENGTH;
3280 + break;
3281 + default:
3282 + ivlen = HIFN_IV_LENGTH;
3283 + break;
3284 + }
3285 + bcopy(cmd->iv, buf_pos, ivlen);
3286 + buf_pos += ivlen;
3287 + }
3288 +
3289 + if ((cmd->base_masks & (HIFN_BASE_CMD_MAC|HIFN_BASE_CMD_CRYPT)) == 0) {
3290 + bzero(buf_pos, 8);
3291 + buf_pos += 8;
3292 + }
3293 +
3294 + return (buf_pos - buf);
3295 +}
3296 +
3297 +static int
3298 +hifn_dmamap_aligned(struct hifn_operand *op)
3299 +{
3300 + struct hifn_softc *sc = NULL;
3301 + int i;
3302 +
3303 + DPRINTF("%s()\n", __FUNCTION__);
3304 +
3305 + for (i = 0; i < op->nsegs; i++) {
3306 + if (op->segs[i].ds_addr & 3)
3307 + return (0);
3308 + if ((i != (op->nsegs - 1)) && (op->segs[i].ds_len & 3))
3309 + return (0);
3310 + }
3311 + return (1);
3312 +}
3313 +
3314 +static __inline int
3315 +hifn_dmamap_dstwrap(struct hifn_softc *sc, int idx)
3316 +{
3317 + struct hifn_dma *dma = sc->sc_dma;
3318 +
3319 + if (++idx == HIFN_D_DST_RSIZE) {
3320 + dma->dstr[idx].l = htole32(HIFN_D_VALID | HIFN_D_JUMP |
3321 + HIFN_D_MASKDONEIRQ);
3322 + HIFN_DSTR_SYNC(sc, idx,
3323 + BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE);
3324 + idx = 0;
3325 + }
3326 + return (idx);
3327 +}
3328 +
3329 +static int
3330 +hifn_dmamap_load_dst(struct hifn_softc *sc, struct hifn_command *cmd)
3331 +{
3332 + struct hifn_dma *dma = sc->sc_dma;
3333 + struct hifn_operand *dst = &cmd->dst;
3334 + u_int32_t p, l;
3335 + int idx, used = 0, i;
3336 +
3337 + DPRINTF("%s()\n", __FUNCTION__);
3338 +
3339 + idx = dma->dsti;
3340 + for (i = 0; i < dst->nsegs - 1; i++) {
3341 + dma->dstr[idx].p = htole32(dst->segs[i].ds_addr);
3342 + dma->dstr[idx].l = htole32(HIFN_D_MASKDONEIRQ | dst->segs[i].ds_len);
3343 + wmb();
3344 + dma->dstr[idx].l |= htole32(HIFN_D_VALID);
3345 + HIFN_DSTR_SYNC(sc, idx,
3346 + BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE);
3347 + used++;
3348 +
3349 + idx = hifn_dmamap_dstwrap(sc, idx);
3350 + }
3351 +
3352 + if (cmd->sloplen == 0) {
3353 + p = dst->segs[i].ds_addr;
3354 + l = HIFN_D_MASKDONEIRQ | HIFN_D_LAST |
3355 + dst->segs[i].ds_len;
3356 + } else {
3357 + p = sc->sc_dma_physaddr +
3358 + offsetof(struct hifn_dma, slop[cmd->slopidx]);
3359 + l = HIFN_D_MASKDONEIRQ | HIFN_D_LAST |
3360 + sizeof(u_int32_t);
3361 +
3362 + if ((dst->segs[i].ds_len - cmd->sloplen) != 0) {
3363 + dma->dstr[idx].p = htole32(dst->segs[i].ds_addr);
3364 + dma->dstr[idx].l = htole32(HIFN_D_MASKDONEIRQ |
3365 + (dst->segs[i].ds_len - cmd->sloplen));
3366 + wmb();
3367 + dma->dstr[idx].l |= htole32(HIFN_D_VALID);
3368 + HIFN_DSTR_SYNC(sc, idx,
3369 + BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE);
3370 + used++;
3371 +
3372 + idx = hifn_dmamap_dstwrap(sc, idx);
3373 + }
3374 + }
3375 + dma->dstr[idx].p = htole32(p);
3376 + dma->dstr[idx].l = htole32(l);
3377 + wmb();
3378 + dma->dstr[idx].l |= htole32(HIFN_D_VALID);
3379 + HIFN_DSTR_SYNC(sc, idx, BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE);
3380 + used++;
3381 +
3382 + idx = hifn_dmamap_dstwrap(sc, idx);
3383 +
3384 + dma->dsti = idx;
3385 + dma->dstu += used;
3386 + return (idx);
3387 +}
3388 +
3389 +static __inline int
3390 +hifn_dmamap_srcwrap(struct hifn_softc *sc, int idx)
3391 +{
3392 + struct hifn_dma *dma = sc->sc_dma;
3393 +
3394 + if (++idx == HIFN_D_SRC_RSIZE) {
3395 + dma->srcr[idx].l = htole32(HIFN_D_VALID |
3396 + HIFN_D_JUMP | HIFN_D_MASKDONEIRQ);
3397 + HIFN_SRCR_SYNC(sc, HIFN_D_SRC_RSIZE,
3398 + BUS_DMASYNC_PREWRITE | BUS_DMASYNC_PREREAD);
3399 + idx = 0;
3400 + }
3401 + return (idx);
3402 +}
3403 +
3404 +static int
3405 +hifn_dmamap_load_src(struct hifn_softc *sc, struct hifn_command *cmd)
3406 +{
3407 + struct hifn_dma *dma = sc->sc_dma;
3408 + struct hifn_operand *src = &cmd->src;
3409 + int idx, i;
3410 + u_int32_t last = 0;
3411 +
3412 + DPRINTF("%s()\n", __FUNCTION__);
3413 +
3414 + idx = dma->srci;
3415 + for (i = 0; i < src->nsegs; i++) {
3416 + if (i == src->nsegs - 1)
3417 + last = HIFN_D_LAST;
3418 +
3419 + dma->srcr[idx].p = htole32(src->segs[i].ds_addr);
3420 + dma->srcr[idx].l = htole32(src->segs[i].ds_len |
3421 + HIFN_D_MASKDONEIRQ | last);
3422 + wmb();
3423 + dma->srcr[idx].l |= htole32(HIFN_D_VALID);
3424 + HIFN_SRCR_SYNC(sc, idx,
3425 + BUS_DMASYNC_PREWRITE | BUS_DMASYNC_PREREAD);
3426 +
3427 + idx = hifn_dmamap_srcwrap(sc, idx);
3428 + }
3429 + dma->srci = idx;
3430 + dma->srcu += src->nsegs;
3431 + return (idx);
3432 +}
3433 +
3434 +
3435 +static int
3436 +hifn_crypto(
3437 + struct hifn_softc *sc,
3438 + struct hifn_command *cmd,
3439 + struct cryptop *crp,
3440 + int hint)
3441 +{
3442 + struct hifn_dma *dma = sc->sc_dma;
3443 + u_int32_t cmdlen, csr;
3444 + int cmdi, resi, err = 0;
3445 + unsigned long l_flags;
3446 +
3447 + DPRINTF("%s()\n", __FUNCTION__);
3448 +
3449 + /*
3450 + * need 1 cmd, and 1 res
3451 + *
3452 + * NB: check this first since it's easy.
3453 + */
3454 + HIFN_LOCK(sc);
3455 + if ((dma->cmdu + 1) > HIFN_D_CMD_RSIZE ||
3456 + (dma->resu + 1) > HIFN_D_RES_RSIZE) {
3457 +#ifdef HIFN_DEBUG
3458 + if (hifn_debug) {
3459 + device_printf(sc->sc_dev,
3460 + "cmd/result exhaustion, cmdu %u resu %u\n",
3461 + dma->cmdu, dma->resu);
3462 + }
3463 +#endif
3464 + hifnstats.hst_nomem_cr++;
3465 + sc->sc_needwakeup |= CRYPTO_SYMQ;
3466 + HIFN_UNLOCK(sc);
3467 + return (ERESTART);
3468 + }
3469 +
3470 + if (crp->crp_flags & CRYPTO_F_SKBUF) {
3471 + if (pci_map_skb(sc, &cmd->src, cmd->src_skb)) {
3472 + hifnstats.hst_nomem_load++;
3473 + err = ENOMEM;
3474 + goto err_srcmap1;
3475 + }
3476 + } else if (crp->crp_flags & CRYPTO_F_IOV) {
3477 + if (pci_map_uio(sc, &cmd->src, cmd->src_io)) {
3478 + hifnstats.hst_nomem_load++;
3479 + err = ENOMEM;
3480 + goto err_srcmap1;
3481 + }
3482 + } else {
3483 + if (pci_map_buf(sc, &cmd->src, cmd->src_buf, crp->crp_ilen)) {
3484 + hifnstats.hst_nomem_load++;
3485 + err = ENOMEM;
3486 + goto err_srcmap1;
3487 + }
3488 + }
3489 +
3490 + if (hifn_dmamap_aligned(&cmd->src)) {
3491 + cmd->sloplen = cmd->src_mapsize & 3;
3492 + cmd->dst = cmd->src;
3493 + } else {
3494 + if (crp->crp_flags & CRYPTO_F_IOV) {
3495 + DPRINTF("%s,%d: %s - EINVAL\n",__FILE__,__LINE__,__FUNCTION__);
3496 + err = EINVAL;
3497 + goto err_srcmap;
3498 + } else if (crp->crp_flags & CRYPTO_F_SKBUF) {
3499 +#ifdef NOTYET
3500 + int totlen, len;
3501 + struct mbuf *m, *m0, *mlast;
3502 +
3503 + KASSERT(cmd->dst_m == cmd->src_m,
3504 + ("hifn_crypto: dst_m initialized improperly"));
3505 + hifnstats.hst_unaligned++;
3506 + /*
3507 + * Source is not aligned on a longword boundary.
3508 + * Copy the data to insure alignment. If we fail
3509 + * to allocate mbufs or clusters while doing this
3510 + * we return ERESTART so the operation is requeued
3511 + * at the crypto later, but only if there are
3512 + * ops already posted to the hardware; otherwise we
3513 + * have no guarantee that we'll be re-entered.
3514 + */
3515 + totlen = cmd->src_mapsize;
3516 + if (cmd->src_m->m_flags & M_PKTHDR) {
3517 + len = MHLEN;
3518 + MGETHDR(m0, M_DONTWAIT, MT_DATA);
3519 + if (m0 && !m_dup_pkthdr(m0, cmd->src_m, M_DONTWAIT)) {
3520 + m_free(m0);
3521 + m0 = NULL;
3522 + }
3523 + } else {
3524 + len = MLEN;
3525 + MGET(m0, M_DONTWAIT, MT_DATA);
3526 + }
3527 + if (m0 == NULL) {
3528 + hifnstats.hst_nomem_mbuf++;
3529 + err = dma->cmdu ? ERESTART : ENOMEM;
3530 + goto err_srcmap;
3531 + }
3532 + if (totlen >= MINCLSIZE) {
3533 + MCLGET(m0, M_DONTWAIT);
3534 + if ((m0->m_flags & M_EXT) == 0) {
3535 + hifnstats.hst_nomem_mcl++;
3536 + err = dma->cmdu ? ERESTART : ENOMEM;
3537 + m_freem(m0);
3538 + goto err_srcmap;
3539 + }
3540 + len = MCLBYTES;
3541 + }
3542 + totlen -= len;
3543 + m0->m_pkthdr.len = m0->m_len = len;
3544 + mlast = m0;
3545 +
3546 + while (totlen > 0) {
3547 + MGET(m, M_DONTWAIT, MT_DATA);
3548 + if (m == NULL) {
3549 + hifnstats.hst_nomem_mbuf++;
3550 + err = dma->cmdu ? ERESTART : ENOMEM;
3551 + m_freem(m0);
3552 + goto err_srcmap;
3553 + }
3554 + len = MLEN;
3555 + if (totlen >= MINCLSIZE) {
3556 + MCLGET(m, M_DONTWAIT);
3557 + if ((m->m_flags & M_EXT) == 0) {
3558 + hifnstats.hst_nomem_mcl++;
3559 + err = dma->cmdu ? ERESTART : ENOMEM;
3560 + mlast->m_next = m;
3561 + m_freem(m0);
3562 + goto err_srcmap;
3563 + }
3564 + len = MCLBYTES;
3565 + }
3566 +
3567 + m->m_len = len;
3568 + m0->m_pkthdr.len += len;
3569 + totlen -= len;
3570 +
3571 + mlast->m_next = m;
3572 + mlast = m;
3573 + }
3574 + cmd->dst_m = m0;
3575 +#else
3576 + device_printf(sc->sc_dev,
3577 + "%s,%d: CRYPTO_F_SKBUF unaligned not implemented\n",
3578 + __FILE__, __LINE__);
3579 + err = EINVAL;
3580 + goto err_srcmap;
3581 +#endif
3582 + } else {
3583 + device_printf(sc->sc_dev,
3584 + "%s,%d: unaligned contig buffers not implemented\n",
3585 + __FILE__, __LINE__);
3586 + err = EINVAL;
3587 + goto err_srcmap;
3588 + }
3589 + }
3590 +
3591 + if (cmd->dst_map == NULL) {
3592 + if (crp->crp_flags & CRYPTO_F_SKBUF) {
3593 + if (pci_map_skb(sc, &cmd->dst, cmd->dst_skb)) {
3594 + hifnstats.hst_nomem_map++;
3595 + err = ENOMEM;
3596 + goto err_dstmap1;
3597 + }
3598 + } else if (crp->crp_flags & CRYPTO_F_IOV) {
3599 + if (pci_map_uio(sc, &cmd->dst, cmd->dst_io)) {
3600 + hifnstats.hst_nomem_load++;
3601 + err = ENOMEM;
3602 + goto err_dstmap1;
3603 + }
3604 + } else {
3605 + if (pci_map_buf(sc, &cmd->dst, cmd->dst_buf, crp->crp_ilen)) {
3606 + hifnstats.hst_nomem_load++;
3607 + err = ENOMEM;
3608 + goto err_dstmap1;
3609 + }
3610 + }
3611 + }
3612 +
3613 +#ifdef HIFN_DEBUG
3614 + if (hifn_debug) {
3615 + device_printf(sc->sc_dev,
3616 + "Entering cmd: stat %8x ien %8x u %d/%d/%d/%d n %d/%d\n",
3617 + READ_REG_1(sc, HIFN_1_DMA_CSR),
3618 + READ_REG_1(sc, HIFN_1_DMA_IER),
3619 + dma->cmdu, dma->srcu, dma->dstu, dma->resu,
3620 + cmd->src_nsegs, cmd->dst_nsegs);
3621 + }
3622 +#endif
3623 +
3624 +#if 0
3625 + if (cmd->src_map == cmd->dst_map) {
3626 + bus_dmamap_sync(sc->sc_dmat, cmd->src_map,
3627 + BUS_DMASYNC_PREWRITE|BUS_DMASYNC_PREREAD);
3628 + } else {
3629 + bus_dmamap_sync(sc->sc_dmat, cmd->src_map,
3630 + BUS_DMASYNC_PREWRITE);
3631 + bus_dmamap_sync(sc->sc_dmat, cmd->dst_map,
3632 + BUS_DMASYNC_PREREAD);
3633 + }
3634 +#endif
3635 +
3636 + /*
3637 + * need N src, and N dst
3638 + */
3639 + if ((dma->srcu + cmd->src_nsegs) > HIFN_D_SRC_RSIZE ||
3640 + (dma->dstu + cmd->dst_nsegs + 1) > HIFN_D_DST_RSIZE) {
3641 +#ifdef HIFN_DEBUG
3642 + if (hifn_debug) {
3643 + device_printf(sc->sc_dev,
3644 + "src/dst exhaustion, srcu %u+%u dstu %u+%u\n",
3645 + dma->srcu, cmd->src_nsegs,
3646 + dma->dstu, cmd->dst_nsegs);
3647 + }
3648 +#endif
3649 + hifnstats.hst_nomem_sd++;
3650 + err = ERESTART;
3651 + goto err_dstmap;
3652 + }
3653 +
3654 + if (dma->cmdi == HIFN_D_CMD_RSIZE) {
3655 + dma->cmdi = 0;
3656 + dma->cmdr[HIFN_D_CMD_RSIZE].l = htole32(HIFN_D_JUMP|HIFN_D_MASKDONEIRQ);
3657 + wmb();
3658 + dma->cmdr[HIFN_D_CMD_RSIZE].l |= htole32(HIFN_D_VALID);
3659 + HIFN_CMDR_SYNC(sc, HIFN_D_CMD_RSIZE,
3660 + BUS_DMASYNC_PREWRITE | BUS_DMASYNC_PREREAD);
3661 + }
3662 + cmdi = dma->cmdi++;
3663 + cmdlen = hifn_write_command(cmd, dma->command_bufs[cmdi]);
3664 + HIFN_CMD_SYNC(sc, cmdi, BUS_DMASYNC_PREWRITE);
3665 +
3666 + /* .p for command/result already set */
3667 + dma->cmdr[cmdi].l = htole32(cmdlen | HIFN_D_LAST |
3668 + HIFN_D_MASKDONEIRQ);
3669 + wmb();
3670 + dma->cmdr[cmdi].l |= htole32(HIFN_D_VALID);
3671 + HIFN_CMDR_SYNC(sc, cmdi,
3672 + BUS_DMASYNC_PREWRITE | BUS_DMASYNC_PREREAD);
3673 + dma->cmdu++;
3674 +
3675 + /*
3676 + * We don't worry about missing an interrupt (which a "command wait"
3677 + * interrupt salvages us from), unless there is more than one command
3678 + * in the queue.
3679 + */
3680 + if (dma->cmdu > 1) {
3681 + sc->sc_dmaier |= HIFN_DMAIER_C_WAIT;
3682 + WRITE_REG_1(sc, HIFN_1_DMA_IER, sc->sc_dmaier);
3683 + }
3684 +
3685 + hifnstats.hst_ipackets++;
3686 + hifnstats.hst_ibytes += cmd->src_mapsize;
3687 +
3688 + hifn_dmamap_load_src(sc, cmd);
3689 +
3690 + /*
3691 + * Unlike other descriptors, we don't mask done interrupt from
3692 + * result descriptor.
3693 + */
3694 +#ifdef HIFN_DEBUG
3695 + if (hifn_debug)
3696 + device_printf(sc->sc_dev, "load res\n");
3697 +#endif
3698 + if (dma->resi == HIFN_D_RES_RSIZE) {
3699 + dma->resi = 0;
3700 + dma->resr[HIFN_D_RES_RSIZE].l = htole32(HIFN_D_JUMP|HIFN_D_MASKDONEIRQ);
3701 + wmb();
3702 + dma->resr[HIFN_D_RES_RSIZE].l |= htole32(HIFN_D_VALID);
3703 + HIFN_RESR_SYNC(sc, HIFN_D_RES_RSIZE,
3704 + BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE);
3705 + }
3706 + resi = dma->resi++;
3707 + KASSERT(dma->hifn_commands[resi] == NULL,
3708 + ("hifn_crypto: command slot %u busy", resi));
3709 + dma->hifn_commands[resi] = cmd;
3710 + HIFN_RES_SYNC(sc, resi, BUS_DMASYNC_PREREAD);
3711 + if ((hint & CRYPTO_HINT_MORE) && sc->sc_curbatch < hifn_maxbatch) {
3712 + dma->resr[resi].l = htole32(HIFN_MAX_RESULT |
3713 + HIFN_D_LAST | HIFN_D_MASKDONEIRQ);
3714 + wmb();
3715 + dma->resr[resi].l |= htole32(HIFN_D_VALID);
3716 + sc->sc_curbatch++;
3717 + if (sc->sc_curbatch > hifnstats.hst_maxbatch)
3718 + hifnstats.hst_maxbatch = sc->sc_curbatch;
3719 + hifnstats.hst_totbatch++;
3720 + } else {
3721 + dma->resr[resi].l = htole32(HIFN_MAX_RESULT | HIFN_D_LAST);
3722 + wmb();
3723 + dma->resr[resi].l |= htole32(HIFN_D_VALID);
3724 + sc->sc_curbatch = 0;
3725 + }
3726 + HIFN_RESR_SYNC(sc, resi,
3727 + BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE);
3728 + dma->resu++;
3729 +
3730 + if (cmd->sloplen)
3731 + cmd->slopidx = resi;
3732 +
3733 + hifn_dmamap_load_dst(sc, cmd);
3734 +
3735 + csr = 0;
3736 + if (sc->sc_c_busy == 0) {
3737 + csr |= HIFN_DMACSR_C_CTRL_ENA;
3738 + sc->sc_c_busy = 1;
3739 + }
3740 + if (sc->sc_s_busy == 0) {
3741 + csr |= HIFN_DMACSR_S_CTRL_ENA;
3742 + sc->sc_s_busy = 1;
3743 + }
3744 + if (sc->sc_r_busy == 0) {
3745 + csr |= HIFN_DMACSR_R_CTRL_ENA;
3746 + sc->sc_r_busy = 1;
3747 + }
3748 + if (sc->sc_d_busy == 0) {
3749 + csr |= HIFN_DMACSR_D_CTRL_ENA;
3750 + sc->sc_d_busy = 1;
3751 + }
3752 + if (csr)
3753 + WRITE_REG_1(sc, HIFN_1_DMA_CSR, csr);
3754 +
3755 +#ifdef HIFN_DEBUG
3756 + if (hifn_debug) {
3757 + device_printf(sc->sc_dev, "command: stat %8x ier %8x\n",
3758 + READ_REG_1(sc, HIFN_1_DMA_CSR),
3759 + READ_REG_1(sc, HIFN_1_DMA_IER));
3760 + }
3761 +#endif
3762 +
3763 + sc->sc_active = 5;
3764 + HIFN_UNLOCK(sc);
3765 + KASSERT(err == 0, ("hifn_crypto: success with error %u", err));
3766 + return (err); /* success */
3767 +
3768 +err_dstmap:
3769 + if (cmd->src_map != cmd->dst_map)
3770 + pci_unmap_buf(sc, &cmd->dst);
3771 +err_dstmap1:
3772 +err_srcmap:
3773 + if (crp->crp_flags & CRYPTO_F_SKBUF) {
3774 + if (cmd->src_skb != cmd->dst_skb)
3775 +#ifdef NOTYET
3776 + m_freem(cmd->dst_m);
3777 +#else
3778 + device_printf(sc->sc_dev,
3779 + "%s,%d: CRYPTO_F_SKBUF src != dst not implemented\n",
3780 + __FILE__, __LINE__);
3781 +#endif
3782 + }
3783 + pci_unmap_buf(sc, &cmd->src);
3784 +err_srcmap1:
3785 + HIFN_UNLOCK(sc);
3786 + return (err);
3787 +}
3788 +
3789 +static void
3790 +hifn_tick(unsigned long arg)
3791 +{
3792 + struct hifn_softc *sc;
3793 + unsigned long l_flags;
3794 +
3795 + if (arg >= HIFN_MAX_CHIPS)
3796 + return;
3797 + sc = hifn_chip_idx[arg];
3798 + if (!sc)
3799 + return;
3800 +
3801 + HIFN_LOCK(sc);
3802 + if (sc->sc_active == 0) {
3803 + struct hifn_dma *dma = sc->sc_dma;
3804 + u_int32_t r = 0;
3805 +
3806 + if (dma->cmdu == 0 && sc->sc_c_busy) {
3807 + sc->sc_c_busy = 0;
3808 + r |= HIFN_DMACSR_C_CTRL_DIS;
3809 + }
3810 + if (dma->srcu == 0 && sc->sc_s_busy) {
3811 + sc->sc_s_busy = 0;
3812 + r |= HIFN_DMACSR_S_CTRL_DIS;
3813 + }
3814 + if (dma->dstu == 0 && sc->sc_d_busy) {
3815 + sc->sc_d_busy = 0;
3816 + r |= HIFN_DMACSR_D_CTRL_DIS;
3817 + }
3818 + if (dma->resu == 0 && sc->sc_r_busy) {
3819 + sc->sc_r_busy = 0;
3820 + r |= HIFN_DMACSR_R_CTRL_DIS;
3821 + }
3822 + if (r)
3823 + WRITE_REG_1(sc, HIFN_1_DMA_CSR, r);
3824 + } else
3825 + sc->sc_active--;
3826 + HIFN_UNLOCK(sc);
3827 + mod_timer(&sc->sc_tickto, jiffies + HZ);
3828 +}
3829 +
3830 +static irqreturn_t
3831 +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,19)
3832 +hifn_intr(int irq, void *arg)
3833 +#else
3834 +hifn_intr(int irq, void *arg, struct pt_regs *regs)
3835 +#endif
3836 +{
3837 + struct hifn_softc *sc = arg;
3838 + struct hifn_dma *dma;
3839 + u_int32_t dmacsr, restart;
3840 + int i, u;
3841 + unsigned long l_flags;
3842 +
3843 + dmacsr = READ_REG_1(sc, HIFN_1_DMA_CSR);
3844 +
3845 + /* Nothing in the DMA unit interrupted */
3846 + if ((dmacsr & sc->sc_dmaier) == 0)
3847 + return IRQ_NONE;
3848 +
3849 + HIFN_LOCK(sc);
3850 +
3851 + dma = sc->sc_dma;
3852 +
3853 +#ifdef HIFN_DEBUG
3854 + if (hifn_debug) {
3855 + device_printf(sc->sc_dev,
3856 + "irq: stat %08x ien %08x damier %08x i %d/%d/%d/%d k %d/%d/%d/%d u %d/%d/%d/%d\n",
3857 + dmacsr, READ_REG_1(sc, HIFN_1_DMA_IER), sc->sc_dmaier,
3858 + dma->cmdi, dma->srci, dma->dsti, dma->resi,
3859 + dma->cmdk, dma->srck, dma->dstk, dma->resk,
3860 + dma->cmdu, dma->srcu, dma->dstu, dma->resu);
3861 + }
3862 +#endif
3863 +
3864 + WRITE_REG_1(sc, HIFN_1_DMA_CSR, dmacsr & sc->sc_dmaier);
3865 +
3866 + if ((sc->sc_flags & HIFN_HAS_PUBLIC) &&
3867 + (dmacsr & HIFN_DMACSR_PUBDONE))
3868 + WRITE_REG_1(sc, HIFN_1_PUB_STATUS,
3869 + READ_REG_1(sc, HIFN_1_PUB_STATUS) | HIFN_PUBSTS_DONE);
3870 +
3871 + restart = dmacsr & (HIFN_DMACSR_D_OVER | HIFN_DMACSR_R_OVER);
3872 + if (restart)
3873 + device_printf(sc->sc_dev, "overrun %x\n", dmacsr);
3874 +
3875 + if (sc->sc_flags & HIFN_IS_7811) {
3876 + if (dmacsr & HIFN_DMACSR_ILLR)
3877 + device_printf(sc->sc_dev, "illegal read\n");
3878 + if (dmacsr & HIFN_DMACSR_ILLW)
3879 + device_printf(sc->sc_dev, "illegal write\n");
3880 + }
3881 +
3882 + restart = dmacsr & (HIFN_DMACSR_C_ABORT | HIFN_DMACSR_S_ABORT |
3883 + HIFN_DMACSR_D_ABORT | HIFN_DMACSR_R_ABORT);
3884 + if (restart) {
3885 + device_printf(sc->sc_dev, "abort, resetting.\n");
3886 + hifnstats.hst_abort++;
3887 + hifn_abort(sc);
3888 + HIFN_UNLOCK(sc);
3889 + return IRQ_HANDLED;
3890 + }
3891 +
3892 + if ((dmacsr & HIFN_DMACSR_C_WAIT) && (dma->cmdu == 0)) {
3893 + /*
3894 + * If no slots to process and we receive a "waiting on
3895 + * command" interrupt, we disable the "waiting on command"
3896 + * (by clearing it).
3897 + */
3898 + sc->sc_dmaier &= ~HIFN_DMAIER_C_WAIT;
3899 + WRITE_REG_1(sc, HIFN_1_DMA_IER, sc->sc_dmaier);
3900 + }
3901 +
3902 + /* clear the rings */
3903 + i = dma->resk; u = dma->resu;
3904 + while (u != 0) {
3905 + HIFN_RESR_SYNC(sc, i,
3906 + BUS_DMASYNC_POSTREAD | BUS_DMASYNC_POSTWRITE);
3907 + if (dma->resr[i].l & htole32(HIFN_D_VALID)) {
3908 + HIFN_RESR_SYNC(sc, i,
3909 + BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE);
3910 + break;
3911 + }
3912 +
3913 + if (i != HIFN_D_RES_RSIZE) {
3914 + struct hifn_command *cmd;
3915 + u_int8_t *macbuf = NULL;
3916 +
3917 + HIFN_RES_SYNC(sc, i, BUS_DMASYNC_POSTREAD);
3918 + cmd = dma->hifn_commands[i];
3919 + KASSERT(cmd != NULL,
3920 + ("hifn_intr: null command slot %u", i));
3921 + dma->hifn_commands[i] = NULL;
3922 +
3923 + if (cmd->base_masks & HIFN_BASE_CMD_MAC) {
3924 + macbuf = dma->result_bufs[i];
3925 + macbuf += 12;
3926 + }
3927 +
3928 + hifn_callback(sc, cmd, macbuf);
3929 + hifnstats.hst_opackets++;
3930 + u--;
3931 + }
3932 +
3933 + if (++i == (HIFN_D_RES_RSIZE + 1))
3934 + i = 0;
3935 + }
3936 + dma->resk = i; dma->resu = u;
3937 +
3938 + i = dma->srck; u = dma->srcu;
3939 + while (u != 0) {
3940 + if (i == HIFN_D_SRC_RSIZE)
3941 + i = 0;
3942 + HIFN_SRCR_SYNC(sc, i,
3943 + BUS_DMASYNC_POSTREAD | BUS_DMASYNC_POSTWRITE);
3944 + if (dma->srcr[i].l & htole32(HIFN_D_VALID)) {
3945 + HIFN_SRCR_SYNC(sc, i,
3946 + BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE);
3947 + break;
3948 + }
3949 + i++, u--;
3950 + }
3951 + dma->srck = i; dma->srcu = u;
3952 +
3953 + i = dma->cmdk; u = dma->cmdu;
3954 + while (u != 0) {
3955 + HIFN_CMDR_SYNC(sc, i,
3956 + BUS_DMASYNC_POSTREAD | BUS_DMASYNC_POSTWRITE);
3957 + if (dma->cmdr[i].l & htole32(HIFN_D_VALID)) {
3958 + HIFN_CMDR_SYNC(sc, i,
3959 + BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE);
3960 + break;
3961 + }
3962 + if (i != HIFN_D_CMD_RSIZE) {
3963 + u--;
3964 + HIFN_CMD_SYNC(sc, i, BUS_DMASYNC_POSTWRITE);
3965 + }
3966 + if (++i == (HIFN_D_CMD_RSIZE + 1))
3967 + i = 0;
3968 + }
3969 + dma->cmdk = i; dma->cmdu = u;
3970 +
3971 + HIFN_UNLOCK(sc);
3972 +
3973 + if (sc->sc_needwakeup) { /* XXX check high watermark */
3974 + int wakeup = sc->sc_needwakeup & (CRYPTO_SYMQ|CRYPTO_ASYMQ);
3975 +#ifdef HIFN_DEBUG
3976 + if (hifn_debug)
3977 + device_printf(sc->sc_dev,
3978 + "wakeup crypto (%x) u %d/%d/%d/%d\n",
3979 + sc->sc_needwakeup,
3980 + dma->cmdu, dma->srcu, dma->dstu, dma->resu);
3981 +#endif
3982 + sc->sc_needwakeup &= ~wakeup;
3983 + crypto_unblock(sc->sc_cid, wakeup);
3984 + }
3985 +
3986 + return IRQ_HANDLED;
3987 +}
3988 +
3989 +/*
3990 + * Allocate a new 'session' and return an encoded session id. 'sidp'
3991 + * contains our registration id, and should contain an encoded session
3992 + * id on successful allocation.
3993 + */
3994 +static int
3995 +hifn_newsession(device_t dev, u_int32_t *sidp, struct cryptoini *cri)
3996 +{
3997 + struct hifn_softc *sc = device_get_softc(dev);
3998 + struct cryptoini *c;
3999 + int mac = 0, cry = 0, sesn;
4000 + struct hifn_session *ses = NULL;
4001 + unsigned long l_flags;
4002 +
4003 + DPRINTF("%s()\n", __FUNCTION__);
4004 +
4005 + KASSERT(sc != NULL, ("hifn_newsession: null softc"));
4006 + if (sidp == NULL || cri == NULL || sc == NULL) {
4007 + DPRINTF("%s,%d: %s - EINVAL\n", __FILE__, __LINE__, __FUNCTION__);
4008 + return (EINVAL);
4009 + }
4010 +
4011 + HIFN_LOCK(sc);
4012 + if (sc->sc_sessions == NULL) {
4013 + ses = sc->sc_sessions = (struct hifn_session *)kmalloc(sizeof(*ses),
4014 + SLAB_ATOMIC);
4015 + if (ses == NULL) {
4016 + HIFN_UNLOCK(sc);
4017 + return (ENOMEM);
4018 + }
4019 + sesn = 0;
4020 + sc->sc_nsessions = 1;
4021 + } else {
4022 + for (sesn = 0; sesn < sc->sc_nsessions; sesn++) {
4023 + if (!sc->sc_sessions[sesn].hs_used) {
4024 + ses = &sc->sc_sessions[sesn];
4025 + break;
4026 + }
4027 + }
4028 +
4029 + if (ses == NULL) {
4030 + sesn = sc->sc_nsessions;
4031 + ses = (struct hifn_session *)kmalloc((sesn + 1) * sizeof(*ses),
4032 + SLAB_ATOMIC);
4033 + if (ses == NULL) {
4034 + HIFN_UNLOCK(sc);
4035 + return (ENOMEM);
4036 + }
4037 + bcopy(sc->sc_sessions, ses, sesn * sizeof(*ses));
4038 + bzero(sc->sc_sessions, sesn * sizeof(*ses));
4039 + kfree(sc->sc_sessions);
4040 + sc->sc_sessions = ses;
4041 + ses = &sc->sc_sessions[sesn];
4042 + sc->sc_nsessions++;
4043 + }
4044 + }
4045 + HIFN_UNLOCK(sc);
4046 +
4047 + bzero(ses, sizeof(*ses));
4048 + ses->hs_used = 1;
4049 +
4050 + for (c = cri; c != NULL; c = c->cri_next) {
4051 + switch (c->cri_alg) {
4052 + case CRYPTO_MD5:
4053 + case CRYPTO_SHA1:
4054 + case CRYPTO_MD5_HMAC:
4055 + case CRYPTO_SHA1_HMAC:
4056 + if (mac) {
4057 + DPRINTF("%s,%d: %s - EINVAL\n",__FILE__,__LINE__,__FUNCTION__);
4058 + return (EINVAL);
4059 + }
4060 + mac = 1;
4061 + ses->hs_mlen = c->cri_mlen;
4062 + if (ses->hs_mlen == 0) {
4063 + switch (c->cri_alg) {
4064 + case CRYPTO_MD5:
4065 + case CRYPTO_MD5_HMAC:
4066 + ses->hs_mlen = 16;
4067 + break;
4068 + case CRYPTO_SHA1:
4069 + case CRYPTO_SHA1_HMAC:
4070 + ses->hs_mlen = 20;
4071 + break;
4072 + }
4073 + }
4074 + break;
4075 + case CRYPTO_DES_CBC:
4076 + case CRYPTO_3DES_CBC:
4077 + case CRYPTO_AES_CBC:
4078 + /* XXX this may read fewer, does it matter? */
4079 + read_random(ses->hs_iv,
4080 + c->cri_alg == CRYPTO_AES_CBC ?
4081 + HIFN_AES_IV_LENGTH : HIFN_IV_LENGTH);
4082 + /*FALLTHROUGH*/
4083 + case CRYPTO_ARC4:
4084 + if (cry) {
4085 + DPRINTF("%s,%d: %s - EINVAL\n",__FILE__,__LINE__,__FUNCTION__);
4086 + return (EINVAL);
4087 + }
4088 + cry = 1;
4089 + break;
4090 + default:
4091 + DPRINTF("%s,%d: %s - EINVAL\n",__FILE__,__LINE__,__FUNCTION__);
4092 + return (EINVAL);
4093 + }
4094 + }
4095 + if (mac == 0 && cry == 0) {
4096 + DPRINTF("%s,%d: %s - EINVAL\n",__FILE__,__LINE__,__FUNCTION__);
4097 + return (EINVAL);
4098 + }
4099 +
4100 + *sidp = HIFN_SID(device_get_unit(sc->sc_dev), sesn);
4101 +
4102 + return (0);
4103 +}
4104 +
4105 +/*
4106 + * Deallocate a session.
4107 + * XXX this routine should run a zero'd mac/encrypt key into context ram.
4108 + * XXX to blow away any keys already stored there.
4109 + */
4110 +static int
4111 +hifn_freesession(device_t dev, u_int64_t tid)
4112 +{
4113 + struct hifn_softc *sc = device_get_softc(dev);
4114 + int session, error;
4115 + u_int32_t sid = CRYPTO_SESID2LID(tid);
4116 + unsigned long l_flags;
4117 +
4118 + DPRINTF("%s()\n", __FUNCTION__);
4119 +
4120 + KASSERT(sc != NULL, ("hifn_freesession: null softc"));
4121 + if (sc == NULL) {
4122 + DPRINTF("%s,%d: %s - EINVAL\n",__FILE__,__LINE__,__FUNCTION__);
4123 + return (EINVAL);
4124 + }
4125 +
4126 + HIFN_LOCK(sc);
4127 + session = HIFN_SESSION(sid);
4128 + if (session < sc->sc_nsessions) {
4129 + bzero(&sc->sc_sessions[session], sizeof(struct hifn_session));
4130 + error = 0;
4131 + } else {
4132 + DPRINTF("%s,%d: %s - EINVAL\n",__FILE__,__LINE__,__FUNCTION__);
4133 + error = EINVAL;
4134 + }
4135 + HIFN_UNLOCK(sc);
4136 +
4137 + return (error);
4138 +}
4139 +
4140 +static int
4141 +hifn_process(device_t dev, struct cryptop *crp, int hint)
4142 +{
4143 + struct hifn_softc *sc = device_get_softc(dev);
4144 + struct hifn_command *cmd = NULL;
4145 + int session, err, ivlen;
4146 + struct cryptodesc *crd1, *crd2, *maccrd, *enccrd;
4147 +
4148 + DPRINTF("%s()\n", __FUNCTION__);
4149 +
4150 + if (crp == NULL || crp->crp_callback == NULL) {
4151 + hifnstats.hst_invalid++;
4152 + DPRINTF("%s,%d: %s - EINVAL\n",__FILE__,__LINE__,__FUNCTION__);
4153 + return (EINVAL);
4154 + }
4155 + session = HIFN_SESSION(crp->crp_sid);
4156 +
4157 + if (sc == NULL || session >= sc->sc_nsessions) {
4158 + DPRINTF("%s,%d: %s - EINVAL\n",__FILE__,__LINE__,__FUNCTION__);
4159 + err = EINVAL;
4160 + goto errout;
4161 + }
4162 +
4163 + cmd = kmalloc(sizeof(struct hifn_command), SLAB_ATOMIC);
4164 + if (cmd == NULL) {
4165 + hifnstats.hst_nomem++;
4166 + err = ENOMEM;
4167 + goto errout;
4168 + }
4169 + memset(cmd, 0, sizeof(*cmd));
4170 +
4171 + if (crp->crp_flags & CRYPTO_F_SKBUF) {
4172 + cmd->src_skb = (struct sk_buff *)crp->crp_buf;
4173 + cmd->dst_skb = (struct sk_buff *)crp->crp_buf;
4174 + } else if (crp->crp_flags & CRYPTO_F_IOV) {
4175 + cmd->src_io = (struct uio *)crp->crp_buf;
4176 + cmd->dst_io = (struct uio *)crp->crp_buf;
4177 + } else {
4178 + cmd->src_buf = crp->crp_buf;
4179 + cmd->dst_buf = crp->crp_buf;
4180 + }
4181 +
4182 + crd1 = crp->crp_desc;
4183 + if (crd1 == NULL) {
4184 + DPRINTF("%s,%d: %s - EINVAL\n",__FILE__,__LINE__,__FUNCTION__);
4185 + err = EINVAL;
4186 + goto errout;
4187 + }
4188 + crd2 = crd1->crd_next;
4189 +
4190 + if (crd2 == NULL) {
4191 + if (crd1->crd_alg == CRYPTO_MD5_HMAC ||
4192 + crd1->crd_alg == CRYPTO_SHA1_HMAC ||
4193 + crd1->crd_alg == CRYPTO_SHA1 ||
4194 + crd1->crd_alg == CRYPTO_MD5) {
4195 + maccrd = crd1;
4196 + enccrd = NULL;
4197 + } else if (crd1->crd_alg == CRYPTO_DES_CBC ||
4198 + crd1->crd_alg == CRYPTO_3DES_CBC ||
4199 + crd1->crd_alg == CRYPTO_AES_CBC ||
4200 + crd1->crd_alg == CRYPTO_ARC4) {
4201 + if ((crd1->crd_flags & CRD_F_ENCRYPT) == 0)
4202 + cmd->base_masks |= HIFN_BASE_CMD_DECODE;
4203 + maccrd = NULL;
4204 + enccrd = crd1;
4205 + } else {
4206 + DPRINTF("%s,%d: %s - EINVAL\n",__FILE__,__LINE__,__FUNCTION__);
4207 + err = EINVAL;
4208 + goto errout;
4209 + }
4210 + } else {
4211 + if ((crd1->crd_alg == CRYPTO_MD5_HMAC ||
4212 + crd1->crd_alg == CRYPTO_SHA1_HMAC ||
4213 + crd1->crd_alg == CRYPTO_MD5 ||
4214 + crd1->crd_alg == CRYPTO_SHA1) &&
4215 + (crd2->crd_alg == CRYPTO_DES_CBC ||
4216 + crd2->crd_alg == CRYPTO_3DES_CBC ||
4217 + crd2->crd_alg == CRYPTO_AES_CBC ||
4218 + crd2->crd_alg == CRYPTO_ARC4) &&
4219 + ((crd2->crd_flags & CRD_F_ENCRYPT) == 0)) {
4220 + cmd->base_masks = HIFN_BASE_CMD_DECODE;
4221 + maccrd = crd1;
4222 + enccrd = crd2;
4223 + } else if ((crd1->crd_alg == CRYPTO_DES_CBC ||
4224 + crd1->crd_alg == CRYPTO_ARC4 ||
4225 + crd1->crd_alg == CRYPTO_3DES_CBC ||
4226 + crd1->crd_alg == CRYPTO_AES_CBC) &&
4227 + (crd2->crd_alg == CRYPTO_MD5_HMAC ||
4228 + crd2->crd_alg == CRYPTO_SHA1_HMAC ||
4229 + crd2->crd_alg == CRYPTO_MD5 ||
4230 + crd2->crd_alg == CRYPTO_SHA1) &&
4231 + (crd1->crd_flags & CRD_F_ENCRYPT)) {
4232 + enccrd = crd1;
4233 + maccrd = crd2;
4234 + } else {
4235 + /*
4236 + * We cannot order the 7751 as requested
4237 + */
4238 + DPRINTF("%s,%d: %s %d,%d,%d - EINVAL\n",__FILE__,__LINE__,__FUNCTION__, crd1->crd_alg, crd2->crd_alg, crd1->crd_flags & CRD_F_ENCRYPT);
4239 + err = EINVAL;
4240 + goto errout;
4241 + }
4242 + }
4243 +
4244 + if (enccrd) {
4245 + cmd->enccrd = enccrd;
4246 + cmd->base_masks |= HIFN_BASE_CMD_CRYPT;
4247 + switch (enccrd->crd_alg) {
4248 + case CRYPTO_ARC4:
4249 + cmd->cry_masks |= HIFN_CRYPT_CMD_ALG_RC4;
4250 + break;
4251 + case CRYPTO_DES_CBC:
4252 + cmd->cry_masks |= HIFN_CRYPT_CMD_ALG_DES |
4253 + HIFN_CRYPT_CMD_MODE_CBC |
4254 + HIFN_CRYPT_CMD_NEW_IV;
4255 + break;
4256 + case CRYPTO_3DES_CBC:
4257 + cmd->cry_masks |= HIFN_CRYPT_CMD_ALG_3DES |
4258 + HIFN_CRYPT_CMD_MODE_CBC |
4259 + HIFN_CRYPT_CMD_NEW_IV;
4260 + break;
4261 + case CRYPTO_AES_CBC:
4262 + cmd->cry_masks |= HIFN_CRYPT_CMD_ALG_AES |
4263 + HIFN_CRYPT_CMD_MODE_CBC |
4264 + HIFN_CRYPT_CMD_NEW_IV;
4265 + break;
4266 + default:
4267 + DPRINTF("%s,%d: %s - EINVAL\n",__FILE__,__LINE__,__FUNCTION__);
4268 + err = EINVAL;
4269 + goto errout;
4270 + }
4271 + if (enccrd->crd_alg != CRYPTO_ARC4) {
4272 + ivlen = ((enccrd->crd_alg == CRYPTO_AES_CBC) ?
4273 + HIFN_AES_IV_LENGTH : HIFN_IV_LENGTH);
4274 + if (enccrd->crd_flags & CRD_F_ENCRYPT) {
4275 + if (enccrd->crd_flags & CRD_F_IV_EXPLICIT)
4276 + bcopy(enccrd->crd_iv, cmd->iv, ivlen);
4277 + else
4278 + bcopy(sc->sc_sessions[session].hs_iv,
4279 + cmd->iv, ivlen);
4280 +
4281 + if ((enccrd->crd_flags & CRD_F_IV_PRESENT)
4282 + == 0) {
4283 + crypto_copyback(crp->crp_flags,
4284 + crp->crp_buf, enccrd->crd_inject,
4285 + ivlen, cmd->iv);
4286 + }
4287 + } else {
4288 + if (enccrd->crd_flags & CRD_F_IV_EXPLICIT)
4289 + bcopy(enccrd->crd_iv, cmd->iv, ivlen);
4290 + else {
4291 + crypto_copydata(crp->crp_flags,
4292 + crp->crp_buf, enccrd->crd_inject,
4293 + ivlen, cmd->iv);
4294 + }
4295 + }
4296 + }
4297 +
4298 + if (enccrd->crd_flags & CRD_F_KEY_EXPLICIT)
4299 + cmd->cry_masks |= HIFN_CRYPT_CMD_NEW_KEY;
4300 + cmd->ck = enccrd->crd_key;
4301 + cmd->cklen = enccrd->crd_klen >> 3;
4302 + cmd->cry_masks |= HIFN_CRYPT_CMD_NEW_KEY;
4303 +
4304 + /*
4305 + * Need to specify the size for the AES key in the masks.
4306 + */
4307 + if ((cmd->cry_masks & HIFN_CRYPT_CMD_ALG_MASK) ==
4308 + HIFN_CRYPT_CMD_ALG_AES) {
4309 + switch (cmd->cklen) {
4310 + case 16:
4311 + cmd->cry_masks |= HIFN_CRYPT_CMD_KSZ_128;
4312 + break;
4313 + case 24:
4314 + cmd->cry_masks |= HIFN_CRYPT_CMD_KSZ_192;
4315 + break;
4316 + case 32:
4317 + cmd->cry_masks |= HIFN_CRYPT_CMD_KSZ_256;
4318 + break;
4319 + default:
4320 + DPRINTF("%s,%d: %s - EINVAL\n",__FILE__,__LINE__,__FUNCTION__);
4321 + err = EINVAL;
4322 + goto errout;
4323 + }
4324 + }
4325 + }
4326 +
4327 + if (maccrd) {
4328 + cmd->maccrd = maccrd;
4329 + cmd->base_masks |= HIFN_BASE_CMD_MAC;
4330 +
4331 + switch (maccrd->crd_alg) {
4332 + case CRYPTO_MD5:
4333 + cmd->mac_masks |= HIFN_MAC_CMD_ALG_MD5 |
4334 + HIFN_MAC_CMD_RESULT | HIFN_MAC_CMD_MODE_HASH |
4335 + HIFN_MAC_CMD_POS_IPSEC;
4336 + break;
4337 + case CRYPTO_MD5_HMAC:
4338 + cmd->mac_masks |= HIFN_MAC_CMD_ALG_MD5 |
4339 + HIFN_MAC_CMD_RESULT | HIFN_MAC_CMD_MODE_HMAC |
4340 + HIFN_MAC_CMD_POS_IPSEC | HIFN_MAC_CMD_TRUNC;
4341 + break;
4342 + case CRYPTO_SHA1:
4343 + cmd->mac_masks |= HIFN_MAC_CMD_ALG_SHA1 |
4344 + HIFN_MAC_CMD_RESULT | HIFN_MAC_CMD_MODE_HASH |
4345 + HIFN_MAC_CMD_POS_IPSEC;
4346 + break;
4347 + case CRYPTO_SHA1_HMAC:
4348 + cmd->mac_masks |= HIFN_MAC_CMD_ALG_SHA1 |
4349 + HIFN_MAC_CMD_RESULT | HIFN_MAC_CMD_MODE_HMAC |
4350 + HIFN_MAC_CMD_POS_IPSEC | HIFN_MAC_CMD_TRUNC;
4351 + break;
4352 + }
4353 +
4354 + if (maccrd->crd_alg == CRYPTO_SHA1_HMAC ||
4355 + maccrd->crd_alg == CRYPTO_MD5_HMAC) {
4356 + cmd->mac_masks |= HIFN_MAC_CMD_NEW_KEY;
4357 + bcopy(maccrd->crd_key, cmd->mac, maccrd->crd_klen >> 3);
4358 + bzero(cmd->mac + (maccrd->crd_klen >> 3),
4359 + HIFN_MAC_KEY_LENGTH - (maccrd->crd_klen >> 3));
4360 + }
4361 + }
4362 +
4363 + cmd->crp = crp;
4364 + cmd->session_num = session;
4365 + cmd->softc = sc;
4366 +
4367 + err = hifn_crypto(sc, cmd, crp, hint);
4368 + if (!err) {
4369 + return 0;
4370 + } else if (err == ERESTART) {
4371 + /*
4372 + * There weren't enough resources to dispatch the request
4373 + * to the part. Notify the caller so they'll requeue this
4374 + * request and resubmit it again soon.
4375 + */
4376 +#ifdef HIFN_DEBUG
4377 + if (hifn_debug)
4378 + device_printf(sc->sc_dev, "requeue request\n");
4379 +#endif
4380 + kfree(cmd);
4381 + sc->sc_needwakeup |= CRYPTO_SYMQ;
4382 + return (err);
4383 + }
4384 +
4385 +errout:
4386 + if (cmd != NULL)
4387 + kfree(cmd);
4388 + if (err == EINVAL)
4389 + hifnstats.hst_invalid++;
4390 + else
4391 + hifnstats.hst_nomem++;
4392 + crp->crp_etype = err;
4393 + crypto_done(crp);
4394 + return (err);
4395 +}
4396 +
4397 +static void
4398 +hifn_abort(struct hifn_softc *sc)
4399 +{
4400 + struct hifn_dma *dma = sc->sc_dma;
4401 + struct hifn_command *cmd;
4402 + struct cryptop *crp;
4403 + int i, u;
4404 +
4405 + DPRINTF("%s()\n", __FUNCTION__);
4406 +
4407 + i = dma->resk; u = dma->resu;
4408 + while (u != 0) {
4409 + cmd = dma->hifn_commands[i];
4410 + KASSERT(cmd != NULL, ("hifn_abort: null command slot %u", i));
4411 + dma->hifn_commands[i] = NULL;
4412 + crp = cmd->crp;
4413 +
4414 + if ((dma->resr[i].l & htole32(HIFN_D_VALID)) == 0) {
4415 + /* Salvage what we can. */
4416 + u_int8_t *macbuf;
4417 +
4418 + if (cmd->base_masks & HIFN_BASE_CMD_MAC) {
4419 + macbuf = dma->result_bufs[i];
4420 + macbuf += 12;
4421 + } else
4422 + macbuf = NULL;
4423 + hifnstats.hst_opackets++;
4424 + hifn_callback(sc, cmd, macbuf);
4425 + } else {
4426 +#if 0
4427 + if (cmd->src_map == cmd->dst_map) {
4428 + bus_dmamap_sync(sc->sc_dmat, cmd->src_map,
4429 + BUS_DMASYNC_POSTREAD|BUS_DMASYNC_POSTWRITE);
4430 + } else {
4431 + bus_dmamap_sync(sc->sc_dmat, cmd->src_map,
4432 + BUS_DMASYNC_POSTWRITE);
4433 + bus_dmamap_sync(sc->sc_dmat, cmd->dst_map,
4434 + BUS_DMASYNC_POSTREAD);
4435 + }
4436 +#endif
4437 +
4438 + if (cmd->src_skb != cmd->dst_skb) {
4439 +#ifdef NOTYET
4440 + m_freem(cmd->src_m);
4441 + crp->crp_buf = (caddr_t)cmd->dst_m;
4442 +#else
4443 + device_printf(sc->sc_dev,
4444 + "%s,%d: CRYPTO_F_SKBUF src != dst not implemented\n",
4445 + __FILE__, __LINE__);
4446 +#endif
4447 + }
4448 +
4449 + /* non-shared buffers cannot be restarted */
4450 + if (cmd->src_map != cmd->dst_map) {
4451 + /*
4452 + * XXX should be EAGAIN, delayed until
4453 + * after the reset.
4454 + */
4455 + crp->crp_etype = ENOMEM;
4456 + pci_unmap_buf(sc, &cmd->dst);
4457 + } else
4458 + crp->crp_etype = ENOMEM;
4459 +
4460 + pci_unmap_buf(sc, &cmd->src);
4461 +
4462 + kfree(cmd);
4463 + if (crp->crp_etype != EAGAIN)
4464 + crypto_done(crp);
4465 + }
4466 +
4467 + if (++i == HIFN_D_RES_RSIZE)
4468 + i = 0;
4469 + u--;
4470 + }
4471 + dma->resk = i; dma->resu = u;
4472 +
4473 + hifn_reset_board(sc, 1);
4474 + hifn_init_dma(sc);
4475 + hifn_init_pci_registers(sc);
4476 +}
4477 +
4478 +static void
4479 +hifn_callback(struct hifn_softc *sc, struct hifn_command *cmd, u_int8_t *macbuf)
4480 +{
4481 + struct hifn_dma *dma = sc->sc_dma;
4482 + struct cryptop *crp = cmd->crp;
4483 + struct cryptodesc *crd;
4484 + int i, u, ivlen;
4485 +
4486 + DPRINTF("%s()\n", __FUNCTION__);
4487 +
4488 +#if 0
4489 + if (cmd->src_map == cmd->dst_map) {
4490 + bus_dmamap_sync(sc->sc_dmat, cmd->src_map,
4491 + BUS_DMASYNC_POSTWRITE | BUS_DMASYNC_POSTREAD);
4492 + } else {
4493 + bus_dmamap_sync(sc->sc_dmat, cmd->src_map,
4494 + BUS_DMASYNC_POSTWRITE);
4495 + bus_dmamap_sync(sc->sc_dmat, cmd->dst_map,
4496 + BUS_DMASYNC_POSTREAD);
4497 + }
4498 +#endif
4499 +
4500 + if (crp->crp_flags & CRYPTO_F_SKBUF) {
4501 + if (cmd->src_skb != cmd->dst_skb) {
4502 +#ifdef NOTYET
4503 + crp->crp_buf = (caddr_t)cmd->dst_m;
4504 + totlen = cmd->src_mapsize;
4505 + for (m = cmd->dst_m; m != NULL; m = m->m_next) {
4506 + if (totlen < m->m_len) {
4507 + m->m_len = totlen;
4508 + totlen = 0;
4509 + } else
4510 + totlen -= m->m_len;
4511 + }
4512 + cmd->dst_m->m_pkthdr.len = cmd->src_m->m_pkthdr.len;
4513 + m_freem(cmd->src_m);
4514 +#else
4515 + device_printf(sc->sc_dev,
4516 + "%s,%d: CRYPTO_F_SKBUF src != dst not implemented\n",
4517 + __FILE__, __LINE__);
4518 +#endif
4519 + }
4520 + }
4521 +
4522 + if (cmd->sloplen != 0) {
4523 + crypto_copyback(crp->crp_flags, crp->crp_buf,
4524 + cmd->src_mapsize - cmd->sloplen, cmd->sloplen,
4525 + (caddr_t)&dma->slop[cmd->slopidx]);
4526 + }
4527 +
4528 + i = dma->dstk; u = dma->dstu;
4529 + while (u != 0) {
4530 + if (i == HIFN_D_DST_RSIZE)
4531 + i = 0;
4532 +#if 0
4533 + bus_dmamap_sync(sc->sc_dmat, sc->sc_dmamap,
4534 + BUS_DMASYNC_POSTREAD | BUS_DMASYNC_POSTWRITE);
4535 +#endif
4536 + if (dma->dstr[i].l & htole32(HIFN_D_VALID)) {
4537 +#if 0
4538 + bus_dmamap_sync(sc->sc_dmat, sc->sc_dmamap,
4539 + BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE);
4540 +#endif
4541 + break;
4542 + }
4543 + i++, u--;
4544 + }
4545 + dma->dstk = i; dma->dstu = u;
4546 +
4547 + hifnstats.hst_obytes += cmd->dst_mapsize;
4548 +
4549 + if ((cmd->base_masks & (HIFN_BASE_CMD_CRYPT | HIFN_BASE_CMD_DECODE)) ==
4550 + HIFN_BASE_CMD_CRYPT) {
4551 + for (crd = crp->crp_desc; crd; crd = crd->crd_next) {
4552 + if (crd->crd_alg != CRYPTO_DES_CBC &&
4553 + crd->crd_alg != CRYPTO_3DES_CBC &&
4554 + crd->crd_alg != CRYPTO_AES_CBC)
4555 + continue;
4556 + ivlen = ((crd->crd_alg == CRYPTO_AES_CBC) ?
4557 + HIFN_AES_IV_LENGTH : HIFN_IV_LENGTH);
4558 + crypto_copydata(crp->crp_flags, crp->crp_buf,
4559 + crd->crd_skip + crd->crd_len - ivlen, ivlen,
4560 + cmd->softc->sc_sessions[cmd->session_num].hs_iv);
4561 + break;
4562 + }
4563 + }
4564 +
4565 + if (macbuf != NULL) {
4566 + for (crd = crp->crp_desc; crd; crd = crd->crd_next) {
4567 + int len;
4568 +
4569 + if (crd->crd_alg != CRYPTO_MD5 &&
4570 + crd->crd_alg != CRYPTO_SHA1 &&
4571 + crd->crd_alg != CRYPTO_MD5_HMAC &&
4572 + crd->crd_alg != CRYPTO_SHA1_HMAC) {
4573 + continue;
4574 + }
4575 + len = cmd->softc->sc_sessions[cmd->session_num].hs_mlen;
4576 + crypto_copyback(crp->crp_flags, crp->crp_buf,
4577 + crd->crd_inject, len, macbuf);
4578 + break;
4579 + }
4580 + }
4581 +
4582 + if (cmd->src_map != cmd->dst_map)
4583 + pci_unmap_buf(sc, &cmd->dst);
4584 + pci_unmap_buf(sc, &cmd->src);
4585 + kfree(cmd);
4586 + crypto_done(crp);
4587 +}
4588 +
4589 +/*
4590 + * 7811 PB3 rev/2 parts lock-up on burst writes to Group 0
4591 + * and Group 1 registers; avoid conditions that could create
4592 + * burst writes by doing a read in between the writes.
4593 + *
4594 + * NB: The read we interpose is always to the same register;
4595 + * we do this because reading from an arbitrary (e.g. last)
4596 + * register may not always work.
4597 + */
4598 +static void
4599 +hifn_write_reg_0(struct hifn_softc *sc, bus_size_t reg, u_int32_t val)
4600 +{
4601 + if (sc->sc_flags & HIFN_IS_7811) {
4602 + if (sc->sc_bar0_lastreg == reg - 4)
4603 + readl(sc->sc_bar0 + HIFN_0_PUCNFG);
4604 + sc->sc_bar0_lastreg = reg;
4605 + }
4606 + writel(val, sc->sc_bar0 + reg);
4607 +}
4608 +
4609 +static void
4610 +hifn_write_reg_1(struct hifn_softc *sc, bus_size_t reg, u_int32_t val)
4611 +{
4612 + if (sc->sc_flags & HIFN_IS_7811) {
4613 + if (sc->sc_bar1_lastreg == reg - 4)
4614 + readl(sc->sc_bar1 + HIFN_1_REVID);
4615 + sc->sc_bar1_lastreg = reg;
4616 + }
4617 + writel(val, sc->sc_bar1 + reg);
4618 +}
4619 +
4620 +
4621 +static struct pci_device_id hifn_pci_tbl[] = {
4622 + { PCI_VENDOR_HIFN, PCI_PRODUCT_HIFN_7951,
4623 + PCI_ANY_ID, PCI_ANY_ID, 0, 0, },
4624 + { PCI_VENDOR_HIFN, PCI_PRODUCT_HIFN_7955,
4625 + PCI_ANY_ID, PCI_ANY_ID, 0, 0, },
4626 + { PCI_VENDOR_HIFN, PCI_PRODUCT_HIFN_7956,
4627 + PCI_ANY_ID, PCI_ANY_ID, 0, 0, },
4628 + { PCI_VENDOR_NETSEC, PCI_PRODUCT_NETSEC_7751,
4629 + PCI_ANY_ID, PCI_ANY_ID, 0, 0, },
4630 + { PCI_VENDOR_INVERTEX, PCI_PRODUCT_INVERTEX_AEON,
4631 + PCI_ANY_ID, PCI_ANY_ID, 0, 0, },
4632 + { PCI_VENDOR_HIFN, PCI_PRODUCT_HIFN_7811,
4633 + PCI_ANY_ID, PCI_ANY_ID, 0, 0, },
4634 + /*
4635 + * Other vendors share this PCI ID as well, such as
4636 + * http://www.powercrypt.com, and obviously they also
4637 + * use the same key.
4638 + */
4639 + { PCI_VENDOR_HIFN, PCI_PRODUCT_HIFN_7751,
4640 + PCI_ANY_ID, PCI_ANY_ID, 0, 0, },
4641 + { 0, 0, 0, 0, 0, 0, }
4642 +};
4643 +MODULE_DEVICE_TABLE(pci, hifn_pci_tbl);
4644 +
4645 +static struct pci_driver hifn_driver = {
4646 + .name = "hifn",
4647 + .id_table = hifn_pci_tbl,
4648 + .probe = hifn_probe,
4649 + .remove = hifn_remove,
4650 + /* add PM stuff here one day */
4651 +};
4652 +
4653 +static int __init hifn_init (void)
4654 +{
4655 + struct hifn_softc *sc = NULL;
4656 + int rc;
4657 +
4658 + DPRINTF("%s(%p)\n", __FUNCTION__, hifn_init);
4659 +
4660 + rc = pci_register_driver(&hifn_driver);
4661 + pci_register_driver_compat(&hifn_driver, rc);
4662 +
4663 + return rc;
4664 +}
4665 +
4666 +static void __exit hifn_exit (void)
4667 +{
4668 + pci_unregister_driver(&hifn_driver);
4669 +}
4670 +
4671 +module_init(hifn_init);
4672 +module_exit(hifn_exit);
4673 +
4674 +MODULE_LICENSE("BSD");
4675 +MODULE_AUTHOR("David McCullough <david_mccullough@securecomputing.com>");
4676 +MODULE_DESCRIPTION("OCF driver for hifn PCI crypto devices");
4677 --- /dev/null
4678 +++ b/crypto/ocf/hifn/hifnHIPP.c
4679 @@ -0,0 +1,420 @@
4680 +/*-
4681 + * Driver for Hifn HIPP-I/II chipset
4682 + * Copyright (c) 2006 Michael Richardson <mcr@xelerance.com>
4683 + *
4684 + * Redistribution and use in source and binary forms, with or without
4685 + * modification, are permitted provided that the following conditions
4686 + * are met:
4687 + *
4688 + * 1. Redistributions of source code must retain the above copyright
4689 + * notice, this list of conditions and the following disclaimer.
4690 + * 2. Redistributions in binary form must reproduce the above copyright
4691 + * notice, this list of conditions and the following disclaimer in the
4692 + * documentation and/or other materials provided with the distribution.
4693 + * 3. The name of the author may not be used to endorse or promote products
4694 + * derived from this software without specific prior written permission.
4695 + *
4696 + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
4697 + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
4698 + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
4699 + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
4700 + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
4701 + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
4702 + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
4703 + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
4704 + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
4705 + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
4706 + *
4707 + * Effort sponsored by Hifn Inc.
4708 + *
4709 + */
4710 +
4711 +/*
4712 + * Driver for various Hifn encryption processors.
4713 + */
4714 +#ifndef AUTOCONF_INCLUDED
4715 +#include <linux/config.h>
4716 +#endif
4717 +#include <linux/module.h>
4718 +#include <linux/init.h>
4719 +#include <linux/list.h>
4720 +#include <linux/slab.h>
4721 +#include <linux/wait.h>
4722 +#include <linux/sched.h>
4723 +#include <linux/pci.h>
4724 +#include <linux/delay.h>
4725 +#include <linux/interrupt.h>
4726 +#include <linux/spinlock.h>
4727 +#include <linux/random.h>
4728 +#include <linux/version.h>
4729 +#include <linux/skbuff.h>
4730 +#include <linux/uio.h>
4731 +#include <linux/sysfs.h>
4732 +#include <linux/miscdevice.h>
4733 +#include <asm/io.h>
4734 +
4735 +#include <cryptodev.h>
4736 +
4737 +#include "hifnHIPPreg.h"
4738 +#include "hifnHIPPvar.h"
4739 +
4740 +#if 1
4741 +#define DPRINTF(a...) if (hipp_debug) { \
4742 + printk("%s: ", sc ? \
4743 + device_get_nameunit(sc->sc_dev) : "hifn"); \
4744 + printk(a); \
4745 + } else
4746 +#else
4747 +#define DPRINTF(a...)
4748 +#endif
4749 +
4750 +typedef int bus_size_t;
4751 +
4752 +static inline int
4753 +pci_get_revid(struct pci_dev *dev)
4754 +{
4755 + u8 rid = 0;
4756 + pci_read_config_byte(dev, PCI_REVISION_ID, &rid);
4757 + return rid;
4758 +}
4759 +
4760 +#define debug hipp_debug
4761 +int hipp_debug = 0;
4762 +module_param(hipp_debug, int, 0644);
4763 +MODULE_PARM_DESC(hipp_debug, "Enable debug");
4764 +
4765 +int hipp_maxbatch = 1;
4766 +module_param(hipp_maxbatch, int, 0644);
4767 +MODULE_PARM_DESC(hipp_maxbatch, "max ops to batch w/o interrupt");
4768 +
4769 +static int hipp_probe(struct pci_dev *dev, const struct pci_device_id *ent);
4770 +static void hipp_remove(struct pci_dev *dev);
4771 +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,19)
4772 +static irqreturn_t hipp_intr(int irq, void *arg);
4773 +#else
4774 +static irqreturn_t hipp_intr(int irq, void *arg, struct pt_regs *regs);
4775 +#endif
4776 +
4777 +static int hipp_num_chips = 0;
4778 +static struct hipp_softc *hipp_chip_idx[HIPP_MAX_CHIPS];
4779 +
4780 +static int hipp_newsession(device_t, u_int32_t *, struct cryptoini *);
4781 +static int hipp_freesession(device_t, u_int64_t);
4782 +static int hipp_process(device_t, struct cryptop *, int);
4783 +
4784 +static device_method_t hipp_methods = {
4785 + /* crypto device methods */
4786 + DEVMETHOD(cryptodev_newsession, hipp_newsession),
4787 + DEVMETHOD(cryptodev_freesession,hipp_freesession),
4788 + DEVMETHOD(cryptodev_process, hipp_process),
4789 +};
4790 +
4791 +static __inline u_int32_t
4792 +READ_REG(struct hipp_softc *sc, unsigned int barno, bus_size_t reg)
4793 +{
4794 + u_int32_t v = readl(sc->sc_bar[barno] + reg);
4795 + //sc->sc_bar0_lastreg = (bus_size_t) -1;
4796 + return (v);
4797 +}
4798 +static __inline void
4799 +WRITE_REG(struct hipp_softc *sc, unsigned int barno, bus_size_t reg, u_int32_t val)
4800 +{
4801 + writel(val, sc->sc_bar[barno] + reg);
4802 +}
4803 +
4804 +#define READ_REG_0(sc, reg) READ_REG(sc, 0, reg)
4805 +#define WRITE_REG_0(sc, reg, val) WRITE_REG(sc,0, reg, val)
4806 +#define READ_REG_1(sc, reg) READ_REG(sc, 1, reg)
4807 +#define WRITE_REG_1(sc, reg, val) WRITE_REG(sc,1, reg, val)
4808 +
4809 +static int
4810 +hipp_newsession(device_t dev, u_int32_t *sidp, struct cryptoini *cri)
4811 +{
4812 + return EINVAL;
4813 +}
4814 +
4815 +static int
4816 +hipp_freesession(device_t dev, u_int64_t tid)
4817 +{
4818 + return EINVAL;
4819 +}
4820 +
4821 +static int
4822 +hipp_process(device_t dev, struct cryptop *crp, int hint)
4823 +{
4824 + return EINVAL;
4825 +}
4826 +
4827 +static const char*
4828 +hipp_partname(struct hipp_softc *sc, char buf[128], size_t blen)
4829 +{
4830 + char *n = NULL;
4831 +
4832 + switch (pci_get_vendor(sc->sc_pcidev)) {
4833 + case PCI_VENDOR_HIFN:
4834 + switch (pci_get_device(sc->sc_pcidev)) {
4835 + case PCI_PRODUCT_HIFN_7855: n = "Hifn 7855";
4836 + case PCI_PRODUCT_HIFN_8155: n = "Hifn 8155";
4837 + case PCI_PRODUCT_HIFN_6500: n = "Hifn 6500";
4838 + }
4839 + }
4840 +
4841 + if(n==NULL) {
4842 + snprintf(buf, blen, "VID=%02x,PID=%02x",
4843 + pci_get_vendor(sc->sc_pcidev),
4844 + pci_get_device(sc->sc_pcidev));
4845 + } else {
4846 + buf[0]='\0';
4847 + strncat(buf, n, blen);
4848 + }
4849 + return buf;
4850 +}
4851 +
4852 +struct hipp_fs_entry {
4853 + struct attribute attr;
4854 + /* other stuff */
4855 +};
4856 +
4857 +
4858 +static ssize_t
4859 +cryptoid_show(struct device *dev,
4860 + struct device_attribute *attr,
4861 + char *buf)
4862 +{
4863 + struct hipp_softc *sc;
4864 +
4865 + sc = pci_get_drvdata(to_pci_dev (dev));
4866 + return sprintf (buf, "%d\n", sc->sc_cid);
4867 +}
4868 +
4869 +struct device_attribute hipp_dev_cryptoid = __ATTR_RO(cryptoid);
4870 +
4871 +/*
4872 + * Attach an interface that successfully probed.
4873 + */
4874 +static int
4875 +hipp_probe(struct pci_dev *dev, const struct pci_device_id *ent)
4876 +{
4877 + struct hipp_softc *sc = NULL;
4878 + int i;
4879 + //char rbase;
4880 + //u_int16_t ena;
4881 + int rev;
4882 + //int rseg;
4883 + int rc;
4884 +
4885 + DPRINTF("%s()\n", __FUNCTION__);
4886 +
4887 + if (pci_enable_device(dev) < 0)
4888 + return(-ENODEV);
4889 +
4890 + if (pci_set_mwi(dev))
4891 + return(-ENODEV);
4892 +
4893 + if (!dev->irq) {
4894 + printk("hifn: found device with no IRQ assigned. check BIOS settings!");
4895 + pci_disable_device(dev);
4896 + return(-ENODEV);
4897 + }
4898 +
4899 + sc = (struct hipp_softc *) kmalloc(sizeof(*sc), GFP_KERNEL);
4900 + if (!sc)
4901 + return(-ENOMEM);
4902 + memset(sc, 0, sizeof(*sc));
4903 +
4904 + softc_device_init(sc, "hifn-hipp", hipp_num_chips, hipp_methods);
4905 +
4906 + sc->sc_pcidev = dev;
4907 + sc->sc_irq = -1;
4908 + sc->sc_cid = -1;
4909 + sc->sc_num = hipp_num_chips++;
4910 +
4911 + if (sc->sc_num < HIPP_MAX_CHIPS)
4912 + hipp_chip_idx[sc->sc_num] = sc;
4913 +
4914 + pci_set_drvdata(sc->sc_pcidev, sc);
4915 +
4916 + spin_lock_init(&sc->sc_mtx);
4917 +
4918 + /*
4919 + * Setup PCI resources.
4920 + * The READ_REG_0, WRITE_REG_0, READ_REG_1,
4921 + * and WRITE_REG_1 macros throughout the driver are used
4922 + * to permit better debugging.
4923 + */
4924 + for(i=0; i<4; i++) {
4925 + unsigned long mem_start, mem_len;
4926 + mem_start = pci_resource_start(sc->sc_pcidev, i);
4927 + mem_len = pci_resource_len(sc->sc_pcidev, i);
4928 + sc->sc_barphy[i] = (caddr_t)mem_start;
4929 + sc->sc_bar[i] = (ocf_iomem_t) ioremap(mem_start, mem_len);
4930 + if (!sc->sc_bar[i]) {
4931 + device_printf(sc->sc_dev, "cannot map bar%d register space\n", i);
4932 + goto fail;
4933 + }
4934 + }
4935 +
4936 + //hipp_reset_board(sc, 0);
4937 + pci_set_master(sc->sc_pcidev);
4938 +
4939 + /*
4940 + * Arrange the interrupt line.
4941 + */
4942 + rc = request_irq(dev->irq, hipp_intr, IRQF_SHARED, "hifn", sc);
4943 + if (rc) {
4944 + device_printf(sc->sc_dev, "could not map interrupt: %d\n", rc);
4945 + goto fail;
4946 + }
4947 + sc->sc_irq = dev->irq;
4948 +
4949 + rev = READ_REG_1(sc, HIPP_1_REVID) & 0xffff;
4950 +
4951 + {
4952 + char b[32];
4953 + device_printf(sc->sc_dev, "%s, rev %u",
4954 + hipp_partname(sc, b, sizeof(b)), rev);
4955 + }
4956 +
4957 +#if 0
4958 + if (sc->sc_flags & HIFN_IS_7956)
4959 + printf(", pll=0x%x<%s clk, %ux mult>",
4960 + sc->sc_pllconfig,
4961 + sc->sc_pllconfig & HIFN_PLL_REF_SEL ? "ext" : "pci",
4962 + 2 + 2*((sc->sc_pllconfig & HIFN_PLL_ND) >> 11));
4963 +#endif
4964 + printf("\n");
4965 +
4966 + sc->sc_cid = crypto_get_driverid(softc_get_device(sc),CRYPTOCAP_F_HARDWARE);
4967 + if (sc->sc_cid < 0) {
4968 + device_printf(sc->sc_dev, "could not get crypto driver id\n");
4969 + goto fail;
4970 + }
4971 +
4972 +#if 0 /* cannot work with a non-GPL module */
4973 + /* make a sysfs entry to let the world know what entry we got */
4974 + sysfs_create_file(&sc->sc_pcidev->dev.kobj, &hipp_dev_cryptoid.attr);
4975 +#endif
4976 +
4977 +#if 0
4978 + init_timer(&sc->sc_tickto);
4979 + sc->sc_tickto.function = hifn_tick;
4980 + sc->sc_tickto.data = (unsigned long) sc->sc_num;
4981 + mod_timer(&sc->sc_tickto, jiffies + HZ);
4982 +#endif
4983 +
4984 +#if 0 /* no code here yet ?? */
4985 + crypto_register(sc->sc_cid, CRYPTO_3DES_CBC, 0, 0);
4986 +#endif
4987 +
4988 + return (0);
4989 +
4990 +fail:
4991 + if (sc->sc_cid >= 0)
4992 + crypto_unregister_all(sc->sc_cid);
4993 + if (sc->sc_irq != -1)
4994 + free_irq(sc->sc_irq, sc);
4995 +
4996 +#if 0
4997 + if (sc->sc_dma) {
4998 + /* Turn off DMA polling */
4999 + WRITE_REG_1(sc, HIFN_1_DMA_CNFG, HIFN_DMACNFG_MSTRESET |
5000 + HIFN_DMACNFG_DMARESET | HIFN_DMACNFG_MODE);
5001 +
5002 + pci_free_consistent(sc->sc_pcidev,
5003 + sizeof(*sc->sc_dma),
5004 + sc->sc_dma, sc->sc_dma_physaddr);
5005 + }
5006 +#endif
5007 + kfree(sc);
5008 + return (-ENXIO);
5009 +}
5010 +
5011 +/*
5012 + * Detach an interface that successfully probed.
5013 + */
5014 +static void
5015 +hipp_remove(struct pci_dev *dev)
5016 +{
5017 + struct hipp_softc *sc = pci_get_drvdata(dev);
5018 + unsigned long l_flags;
5019 +
5020 + DPRINTF("%s()\n", __FUNCTION__);
5021 +
5022 + /* disable interrupts */
5023 + HIPP_LOCK(sc);
5024 +
5025 +#if 0
5026 + WRITE_REG_1(sc, HIFN_1_DMA_IER, 0);
5027 + HIFN_UNLOCK(sc);
5028 +
5029 + /*XXX other resources */
5030 + del_timer_sync(&sc->sc_tickto);
5031 +
5032 + /* Turn off DMA polling */
5033 + WRITE_REG_1(sc, HIFN_1_DMA_CNFG, HIFN_DMACNFG_MSTRESET |
5034 + HIFN_DMACNFG_DMARESET | HIFN_DMACNFG_MODE);
5035 +#endif
5036 +
5037 + crypto_unregister_all(sc->sc_cid);
5038 +
5039 + free_irq(sc->sc_irq, sc);
5040 +
5041 +#if 0
5042 + pci_free_consistent(sc->sc_pcidev, sizeof(*sc->sc_dma),
5043 + sc->sc_dma, sc->sc_dma_physaddr);
5044 +#endif
5045 +}
5046 +
5047 +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,19)
5048 +static irqreturn_t hipp_intr(int irq, void *arg)
5049 +#else
5050 +static irqreturn_t hipp_intr(int irq, void *arg, struct pt_regs *regs)
5051 +#endif
5052 +{
5053 + struct hipp_softc *sc = arg;
5054 +
5055 + sc = sc; /* shut up compiler */
5056 +
5057 + return IRQ_HANDLED;
5058 +}
5059 +
5060 +static struct pci_device_id hipp_pci_tbl[] = {
5061 + { PCI_VENDOR_HIFN, PCI_PRODUCT_HIFN_7855,
5062 + PCI_ANY_ID, PCI_ANY_ID, 0, 0, },
5063 + { PCI_VENDOR_HIFN, PCI_PRODUCT_HIFN_8155,
5064 + PCI_ANY_ID, PCI_ANY_ID, 0, 0, },
5065 +};
5066 +MODULE_DEVICE_TABLE(pci, hipp_pci_tbl);
5067 +
5068 +static struct pci_driver hipp_driver = {
5069 + .name = "hipp",
5070 + .id_table = hipp_pci_tbl,
5071 + .probe = hipp_probe,
5072 + .remove = hipp_remove,
5073 + /* add PM stuff here one day */
5074 +};
5075 +
5076 +static int __init hipp_init (void)
5077 +{
5078 + struct hipp_softc *sc = NULL;
5079 + int rc;
5080 +
5081 + DPRINTF("%s(%p)\n", __FUNCTION__, hipp_init);
5082 +
5083 + rc = pci_register_driver(&hipp_driver);
5084 + pci_register_driver_compat(&hipp_driver, rc);
5085 +
5086 + return rc;
5087 +}
5088 +
5089 +static void __exit hipp_exit (void)
5090 +{
5091 + pci_unregister_driver(&hipp_driver);
5092 +}
5093 +
5094 +module_init(hipp_init);
5095 +module_exit(hipp_exit);
5096 +
5097 +MODULE_LICENSE("BSD");
5098 +MODULE_AUTHOR("Michael Richardson <mcr@xelerance.com>");
5099 +MODULE_DESCRIPTION("OCF driver for hifn HIPP-I/II PCI crypto devices");
5100 --- /dev/null
5101 +++ b/crypto/ocf/hifn/hifnHIPPreg.h
5102 @@ -0,0 +1,46 @@
5103 +/*-
5104 + * Hifn HIPP-I/HIPP-II (7855/8155) driver.
5105 + * Copyright (c) 2006 Michael Richardson <mcr@xelerance.com>
5106 + *
5107 + * Redistribution and use in source and binary forms, with or without
5108 + * modification, are permitted provided that the following conditions
5109 + * are met:
5110 + *
5111 + * 1. Redistributions of source code must retain the above copyright
5112 + * notice, this list of conditions and the following disclaimer.
5113 + * 2. Redistributions in binary form must reproduce the above copyright
5114 + * notice, this list of conditions and the following disclaimer in the
5115 + * documentation and/or other materials provided with the distribution.
5116 + * 3. The name of the author may not be used to endorse or promote products
5117 + * derived from this software without specific prior written permission.
5118 + *
5119 + *
5120 + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
5121 + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
5122 + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
5123 + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
5124 + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
5125 + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
5126 + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
5127 + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
5128 + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
5129 + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
5130 + *
5131 + * Effort sponsored by Hifn inc.
5132 + *
5133 + */
5134 +
5135 +#ifndef __HIFNHIPP_H__
5136 +#define __HIFNHIPP_H__
5137 +
5138 +/*
5139 + * PCI vendor and device identifiers
5140 + */
5141 +#define PCI_VENDOR_HIFN 0x13a3 /* Hifn */
5142 +#define PCI_PRODUCT_HIFN_6500 0x0006 /* 6500 */
5143 +#define PCI_PRODUCT_HIFN_7855 0x001f /* 7855 */
5144 +#define PCI_PRODUCT_HIFN_8155 0x999 /* XXX 8155 */
5145 +
5146 +#define HIPP_1_REVID 0x01 /* BOGUS */
5147 +
5148 +#endif /* __HIPP_H__ */
5149 --- /dev/null
5150 +++ b/crypto/ocf/hifn/hifnHIPPvar.h
5151 @@ -0,0 +1,93 @@
5152 +/*
5153 + * Hifn HIPP-I/HIPP-II (7855/8155) driver.
5154 + * Copyright (c) 2006 Michael Richardson <mcr@xelerance.com> *
5155 + *
5156 + * Redistribution and use in source and binary forms, with or without
5157 + * modification, are permitted provided that the following conditions
5158 + * are met:
5159 + *
5160 + * 1. Redistributions of source code must retain the above copyright
5161 + * notice, this list of conditions and the following disclaimer.
5162 + * 2. Redistributions in binary form must reproduce the above copyright
5163 + * notice, this list of conditions and the following disclaimer in the
5164 + * documentation and/or other materials provided with the distribution.
5165 + * 3. The name of the author may not be used to endorse or promote products
5166 + * derived from this software without specific prior written permission.
5167 + *
5168 + *
5169 + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
5170 + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
5171 + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
5172 + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
5173 + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
5174 + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
5175 + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
5176 + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
5177 + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
5178 + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
5179 + *
5180 + * Effort sponsored by Hifn inc.
5181 + *
5182 + */
5183 +
5184 +#ifndef __HIFNHIPPVAR_H__
5185 +#define __HIFNHIPPVAR_H__
5186 +
5187 +#define HIPP_MAX_CHIPS 8
5188 +
5189 +/*
5190 + * Holds data specific to a single Hifn HIPP-I board.
5191 + */
5192 +struct hipp_softc {
5193 + softc_device_decl sc_dev;
5194 +
5195 + struct pci_dev *sc_pcidev; /* device backpointer */
5196 + ocf_iomem_t sc_bar[5];
5197 + caddr_t sc_barphy[5]; /* physical address */
5198 + int sc_num; /* for multiple devs */
5199 + spinlock_t sc_mtx; /* per-instance lock */
5200 + int32_t sc_cid;
5201 + int sc_irq;
5202 +
5203 +#if 0
5204 +
5205 + u_int32_t sc_dmaier;
5206 + u_int32_t sc_drammodel; /* 1=dram, 0=sram */
5207 + u_int32_t sc_pllconfig; /* 7954/7955/7956 PLL config */
5208 +
5209 + struct hifn_dma *sc_dma;
5210 + dma_addr_t sc_dma_physaddr;/* physical address of sc_dma */
5211 +
5212 + int sc_dmansegs;
5213 + int sc_maxses;
5214 + int sc_nsessions;
5215 + struct hifn_session *sc_sessions;
5216 + int sc_ramsize;
5217 + int sc_flags;
5218 +#define HIFN_HAS_RNG 0x1 /* includes random number generator */
5219 +#define HIFN_HAS_PUBLIC 0x2 /* includes public key support */
5220 +#define HIFN_HAS_AES 0x4 /* includes AES support */
5221 +#define HIFN_IS_7811 0x8 /* Hifn 7811 part */
5222 +#define HIFN_IS_7956 0x10 /* Hifn 7956/7955 don't have SDRAM */
5223 +
5224 + struct timer_list sc_tickto; /* for managing DMA */
5225 +
5226 + int sc_rngfirst;
5227 + int sc_rnghz; /* RNG polling frequency */
5228 +
5229 + int sc_c_busy; /* command ring busy */
5230 + int sc_s_busy; /* source data ring busy */
5231 + int sc_d_busy; /* destination data ring busy */
5232 + int sc_r_busy; /* result ring busy */
5233 + int sc_active; /* for initial countdown */
5234 + int sc_needwakeup; /* ops q'd wating on resources */
5235 + int sc_curbatch; /* # ops submitted w/o int */
5236 + int sc_suspended;
5237 + struct miscdevice sc_miscdev;
5238 +#endif
5239 +};
5240 +
5241 +#define HIPP_LOCK(_sc) spin_lock_irqsave(&(_sc)->sc_mtx, l_flags)
5242 +#define HIPP_UNLOCK(_sc) spin_unlock_irqrestore(&(_sc)->sc_mtx, l_flags)
5243 +
5244 +#endif /* __HIFNHIPPVAR_H__ */
5245 --- /dev/null
5246 +++ b/crypto/ocf/safe/md5.c
5247 @@ -0,0 +1,308 @@
5248 +/* $KAME: md5.c,v 1.5 2000/11/08 06:13:08 itojun Exp $ */
5249 +/*
5250 + * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
5251 + * All rights reserved.
5252 + *
5253 + * Redistribution and use in source and binary forms, with or without
5254 + * modification, are permitted provided that the following conditions
5255 + * are met:
5256 + * 1. Redistributions of source code must retain the above copyright
5257 + * notice, this list of conditions and the following disclaimer.
5258 + * 2. Redistributions in binary form must reproduce the above copyright
5259 + * notice, this list of conditions and the following disclaimer in the
5260 + * documentation and/or other materials provided with the distribution.
5261 + * 3. Neither the name of the project nor the names of its contributors
5262 + * may be used to endorse or promote products derived from this software
5263 + * without specific prior written permission.
5264 + *
5265 + * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
5266 + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
5267 + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
5268 + * ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
5269 + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
5270 + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
5271 + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
5272 + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
5273 + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
5274 + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
5275 + * SUCH DAMAGE.
5276 + */
5277 +
5278 +#if 0
5279 +#include <sys/cdefs.h>
5280 +__FBSDID("$FreeBSD: src/sys/crypto/md5.c,v 1.9 2004/01/27 19:49:19 des Exp $");
5281 +
5282 +#include <sys/types.h>
5283 +#include <sys/cdefs.h>
5284 +#include <sys/time.h>
5285 +#include <sys/systm.h>
5286 +#include <crypto/md5.h>
5287 +#endif
5288 +
5289 +#define SHIFT(X, s) (((X) << (s)) | ((X) >> (32 - (s))))
5290 +
5291 +#define F(X, Y, Z) (((X) & (Y)) | ((~X) & (Z)))
5292 +#define G(X, Y, Z) (((X) & (Z)) | ((Y) & (~Z)))
5293 +#define H(X, Y, Z) ((X) ^ (Y) ^ (Z))
5294 +#define I(X, Y, Z) ((Y) ^ ((X) | (~Z)))
5295 +
5296 +#define ROUND1(a, b, c, d, k, s, i) { \
5297 + (a) = (a) + F((b), (c), (d)) + X[(k)] + T[(i)]; \
5298 + (a) = SHIFT((a), (s)); \
5299 + (a) = (b) + (a); \
5300 +}
5301 +
5302 +#define ROUND2(a, b, c, d, k, s, i) { \
5303 + (a) = (a) + G((b), (c), (d)) + X[(k)] + T[(i)]; \
5304 + (a) = SHIFT((a), (s)); \
5305 + (a) = (b) + (a); \
5306 +}
5307 +
5308 +#define ROUND3(a, b, c, d, k, s, i) { \
5309 + (a) = (a) + H((b), (c), (d)) + X[(k)] + T[(i)]; \
5310 + (a) = SHIFT((a), (s)); \
5311 + (a) = (b) + (a); \
5312 +}
5313 +
5314 +#define ROUND4(a, b, c, d, k, s, i) { \
5315 + (a) = (a) + I((b), (c), (d)) + X[(k)] + T[(i)]; \
5316 + (a) = SHIFT((a), (s)); \
5317 + (a) = (b) + (a); \
5318 +}
5319 +
5320 +#define Sa 7
5321 +#define Sb 12
5322 +#define Sc 17
5323 +#define Sd 22
5324 +
5325 +#define Se 5
5326 +#define Sf 9
5327 +#define Sg 14
5328 +#define Sh 20
5329 +
5330 +#define Si 4
5331 +#define Sj 11
5332 +#define Sk 16
5333 +#define Sl 23
5334 +
5335 +#define Sm 6
5336 +#define Sn 10
5337 +#define So 15
5338 +#define Sp 21
5339 +
5340 +#define MD5_A0 0x67452301
5341 +#define MD5_B0 0xefcdab89
5342 +#define MD5_C0 0x98badcfe
5343 +#define MD5_D0 0x10325476
5344 +
5345 +/* Integer part of 4294967296 times abs(sin(i)), where i is in radians. */
5346 +static const u_int32_t T[65] = {
5347 + 0,
5348 + 0xd76aa478, 0xe8c7b756, 0x242070db, 0xc1bdceee,
5349 + 0xf57c0faf, 0x4787c62a, 0xa8304613, 0xfd469501,
5350 + 0x698098d8, 0x8b44f7af, 0xffff5bb1, 0x895cd7be,
5351 + 0x6b901122, 0xfd987193, 0xa679438e, 0x49b40821,
5352 +
5353 + 0xf61e2562, 0xc040b340, 0x265e5a51, 0xe9b6c7aa,
5354 + 0xd62f105d, 0x2441453, 0xd8a1e681, 0xe7d3fbc8,
5355 + 0x21e1cde6, 0xc33707d6, 0xf4d50d87, 0x455a14ed,
5356 + 0xa9e3e905, 0xfcefa3f8, 0x676f02d9, 0x8d2a4c8a,
5357 +
5358 + 0xfffa3942, 0x8771f681, 0x6d9d6122, 0xfde5380c,
5359 + 0xa4beea44, 0x4bdecfa9, 0xf6bb4b60, 0xbebfbc70,
5360 + 0x289b7ec6, 0xeaa127fa, 0xd4ef3085, 0x4881d05,
5361 + 0xd9d4d039, 0xe6db99e5, 0x1fa27cf8, 0xc4ac5665,
5362 +
5363 + 0xf4292244, 0x432aff97, 0xab9423a7, 0xfc93a039,
5364 + 0x655b59c3, 0x8f0ccc92, 0xffeff47d, 0x85845dd1,
5365 + 0x6fa87e4f, 0xfe2ce6e0, 0xa3014314, 0x4e0811a1,
5366 + 0xf7537e82, 0xbd3af235, 0x2ad7d2bb, 0xeb86d391,
5367 +};
5368 +
5369 +static const u_int8_t md5_paddat[MD5_BUFLEN] = {
5370 + 0x80, 0, 0, 0, 0, 0, 0, 0,
5371 + 0, 0, 0, 0, 0, 0, 0, 0,
5372 + 0, 0, 0, 0, 0, 0, 0, 0,
5373 + 0, 0, 0, 0, 0, 0, 0, 0,
5374 + 0, 0, 0, 0, 0, 0, 0, 0,
5375 + 0, 0, 0, 0, 0, 0, 0, 0,
5376 + 0, 0, 0, 0, 0, 0, 0, 0,
5377 + 0, 0, 0, 0, 0, 0, 0, 0,
5378 +};
5379 +
5380 +static void md5_calc(u_int8_t *, md5_ctxt *);
5381 +
5382 +void md5_init(ctxt)
5383 + md5_ctxt *ctxt;
5384 +{
5385 + ctxt->md5_n = 0;
5386 + ctxt->md5_i = 0;
5387 + ctxt->md5_sta = MD5_A0;
5388 + ctxt->md5_stb = MD5_B0;
5389 + ctxt->md5_stc = MD5_C0;
5390 + ctxt->md5_std = MD5_D0;
5391 + bzero(ctxt->md5_buf, sizeof(ctxt->md5_buf));
5392 +}
5393 +
5394 +void md5_loop(ctxt, input, len)
5395 + md5_ctxt *ctxt;
5396 + u_int8_t *input;
5397 + u_int len; /* number of bytes */
5398 +{
5399 + u_int gap, i;
5400 +
5401 + ctxt->md5_n += len * 8; /* byte to bit */
5402 + gap = MD5_BUFLEN - ctxt->md5_i;
5403 +
5404 + if (len >= gap) {
5405 + bcopy((void *)input, (void *)(ctxt->md5_buf + ctxt->md5_i),
5406 + gap);
5407 + md5_calc(ctxt->md5_buf, ctxt);
5408 +
5409 + for (i = gap; i + MD5_BUFLEN <= len; i += MD5_BUFLEN) {
5410 + md5_calc((u_int8_t *)(input + i), ctxt);
5411 + }
5412 +
5413 + ctxt->md5_i = len - i;
5414 + bcopy((void *)(input + i), (void *)ctxt->md5_buf, ctxt->md5_i);
5415 + } else {
5416 + bcopy((void *)input, (void *)(ctxt->md5_buf + ctxt->md5_i),
5417 + len);
5418 + ctxt->md5_i += len;
5419 + }
5420 +}
5421 +
5422 +void md5_pad(ctxt)
5423 + md5_ctxt *ctxt;
5424 +{
5425 + u_int gap;
5426 +
5427 + /* Don't count up padding. Keep md5_n. */
5428 + gap = MD5_BUFLEN - ctxt->md5_i;
5429 + if (gap > 8) {
5430 + bcopy(md5_paddat,
5431 + (void *)(ctxt->md5_buf + ctxt->md5_i),
5432 + gap - sizeof(ctxt->md5_n));
5433 + } else {
5434 + /* including gap == 8 */
5435 + bcopy(md5_paddat, (void *)(ctxt->md5_buf + ctxt->md5_i),
5436 + gap);
5437 + md5_calc(ctxt->md5_buf, ctxt);
5438 + bcopy((md5_paddat + gap),
5439 + (void *)ctxt->md5_buf,
5440 + MD5_BUFLEN - sizeof(ctxt->md5_n));
5441 + }
5442 +
5443 + /* 8 byte word */
5444 +#if BYTE_ORDER == LITTLE_ENDIAN
5445 + bcopy(&ctxt->md5_n8[0], &ctxt->md5_buf[56], 8);
5446 +#endif
5447 +#if BYTE_ORDER == BIG_ENDIAN
5448 + ctxt->md5_buf[56] = ctxt->md5_n8[7];
5449 + ctxt->md5_buf[57] = ctxt->md5_n8[6];
5450 + ctxt->md5_buf[58] = ctxt->md5_n8[5];
5451 + ctxt->md5_buf[59] = ctxt->md5_n8[4];
5452 + ctxt->md5_buf[60] = ctxt->md5_n8[3];
5453 + ctxt->md5_buf[61] = ctxt->md5_n8[2];
5454 + ctxt->md5_buf[62] = ctxt->md5_n8[1];
5455 + ctxt->md5_buf[63] = ctxt->md5_n8[0];
5456 +#endif
5457 +
5458 + md5_calc(ctxt->md5_buf, ctxt);
5459 +}
5460 +
5461 +void md5_result(digest, ctxt)
5462 + u_int8_t *digest;
5463 + md5_ctxt *ctxt;
5464 +{
5465 + /* 4 byte words */
5466 +#if BYTE_ORDER == LITTLE_ENDIAN
5467 + bcopy(&ctxt->md5_st8[0], digest, 16);
5468 +#endif
5469 +#if BYTE_ORDER == BIG_ENDIAN
5470 + digest[ 0] = ctxt->md5_st8[ 3]; digest[ 1] = ctxt->md5_st8[ 2];
5471 + digest[ 2] = ctxt->md5_st8[ 1]; digest[ 3] = ctxt->md5_st8[ 0];
5472 + digest[ 4] = ctxt->md5_st8[ 7]; digest[ 5] = ctxt->md5_st8[ 6];
5473 + digest[ 6] = ctxt->md5_st8[ 5]; digest[ 7] = ctxt->md5_st8[ 4];
5474 + digest[ 8] = ctxt->md5_st8[11]; digest[ 9] = ctxt->md5_st8[10];
5475 + digest[10] = ctxt->md5_st8[ 9]; digest[11] = ctxt->md5_st8[ 8];
5476 + digest[12] = ctxt->md5_st8[15]; digest[13] = ctxt->md5_st8[14];
5477 + digest[14] = ctxt->md5_st8[13]; digest[15] = ctxt->md5_st8[12];
5478 +#endif
5479 +}
5480 +
5481 +static void md5_calc(b64, ctxt)
5482 + u_int8_t *b64;
5483 + md5_ctxt *ctxt;
5484 +{
5485 + u_int32_t A = ctxt->md5_sta;
5486 + u_int32_t B = ctxt->md5_stb;
5487 + u_int32_t C = ctxt->md5_stc;
5488 + u_int32_t D = ctxt->md5_std;
5489 +#if BYTE_ORDER == LITTLE_ENDIAN
5490 + u_int32_t *X = (u_int32_t *)b64;
5491 +#endif
5492 +#if BYTE_ORDER == BIG_ENDIAN
5493 + /* 4 byte words */
5494 + /* what a brute force but fast! */
5495 + u_int32_t X[16];
5496 + u_int8_t *y = (u_int8_t *)X;
5497 + y[ 0] = b64[ 3]; y[ 1] = b64[ 2]; y[ 2] = b64[ 1]; y[ 3] = b64[ 0];
5498 + y[ 4] = b64[ 7]; y[ 5] = b64[ 6]; y[ 6] = b64[ 5]; y[ 7] = b64[ 4];
5499 + y[ 8] = b64[11]; y[ 9] = b64[10]; y[10] = b64[ 9]; y[11] = b64[ 8];
5500 + y[12] = b64[15]; y[13] = b64[14]; y[14] = b64[13]; y[15] = b64[12];
5501 + y[16] = b64[19]; y[17] = b64[18]; y[18] = b64[17]; y[19] = b64[16];
5502 + y[20] = b64[23]; y[21] = b64[22]; y[22] = b64[21]; y[23] = b64[20];
5503 + y[24] = b64[27]; y[25] = b64[26]; y[26] = b64[25]; y[27] = b64[24];
5504 + y[28] = b64[31]; y[29] = b64[30]; y[30] = b64[29]; y[31] = b64[28];
5505 + y[32] = b64[35]; y[33] = b64[34]; y[34] = b64[33]; y[35] = b64[32];
5506 + y[36] = b64[39]; y[37] = b64[38]; y[38] = b64[37]; y[39] = b64[36];
5507 + y[40] = b64[43]; y[41] = b64[42]; y[42] = b64[41]; y[43] = b64[40];
5508 + y[44] = b64[47]; y[45] = b64[46]; y[46] = b64[45]; y[47] = b64[44];
5509 + y[48] = b64[51]; y[49] = b64[50]; y[50] = b64[49]; y[51] = b64[48];
5510 + y[52] = b64[55]; y[53] = b64[54]; y[54] = b64[53]; y[55] = b64[52];
5511 + y[56] = b64[59]; y[57] = b64[58]; y[58] = b64[57]; y[59] = b64[56];
5512 + y[60] = b64[63]; y[61] = b64[62]; y[62] = b64[61]; y[63] = b64[60];
5513 +#endif
5514 +
5515 + ROUND1(A, B, C, D, 0, Sa, 1); ROUND1(D, A, B, C, 1, Sb, 2);
5516 + ROUND1(C, D, A, B, 2, Sc, 3); ROUND1(B, C, D, A, 3, Sd, 4);
5517 + ROUND1(A, B, C, D, 4, Sa, 5); ROUND1(D, A, B, C, 5, Sb, 6);
5518 + ROUND1(C, D, A, B, 6, Sc, 7); ROUND1(B, C, D, A, 7, Sd, 8);
5519 + ROUND1(A, B, C, D, 8, Sa, 9); ROUND1(D, A, B, C, 9, Sb, 10);
5520 + ROUND1(C, D, A, B, 10, Sc, 11); ROUND1(B, C, D, A, 11, Sd, 12);
5521 + ROUND1(A, B, C, D, 12, Sa, 13); ROUND1(D, A, B, C, 13, Sb, 14);
5522 + ROUND1(C, D, A, B, 14, Sc, 15); ROUND1(B, C, D, A, 15, Sd, 16);
5523 +
5524 + ROUND2(A, B, C, D, 1, Se, 17); ROUND2(D, A, B, C, 6, Sf, 18);
5525 + ROUND2(C, D, A, B, 11, Sg, 19); ROUND2(B, C, D, A, 0, Sh, 20);
5526 + ROUND2(A, B, C, D, 5, Se, 21); ROUND2(D, A, B, C, 10, Sf, 22);
5527 + ROUND2(C, D, A, B, 15, Sg, 23); ROUND2(B, C, D, A, 4, Sh, 24);
5528 + ROUND2(A, B, C, D, 9, Se, 25); ROUND2(D, A, B, C, 14, Sf, 26);
5529 + ROUND2(C, D, A, B, 3, Sg, 27); ROUND2(B, C, D, A, 8, Sh, 28);
5530 + ROUND2(A, B, C, D, 13, Se, 29); ROUND2(D, A, B, C, 2, Sf, 30);
5531 + ROUND2(C, D, A, B, 7, Sg, 31); ROUND2(B, C, D, A, 12, Sh, 32);
5532 +
5533 + ROUND3(A, B, C, D, 5, Si, 33); ROUND3(D, A, B, C, 8, Sj, 34);
5534 + ROUND3(C, D, A, B, 11, Sk, 35); ROUND3(B, C, D, A, 14, Sl, 36);
5535 + ROUND3(A, B, C, D, 1, Si, 37); ROUND3(D, A, B, C, 4, Sj, 38);
5536 + ROUND3(C, D, A, B, 7, Sk, 39); ROUND3(B, C, D, A, 10, Sl, 40);
5537 + ROUND3(A, B, C, D, 13, Si, 41); ROUND3(D, A, B, C, 0, Sj, 42);
5538 + ROUND3(C, D, A, B, 3, Sk, 43); ROUND3(B, C, D, A, 6, Sl, 44);
5539 + ROUND3(A, B, C, D, 9, Si, 45); ROUND3(D, A, B, C, 12, Sj, 46);
5540 + ROUND3(C, D, A, B, 15, Sk, 47); ROUND3(B, C, D, A, 2, Sl, 48);
5541 +
5542 + ROUND4(A, B, C, D, 0, Sm, 49); ROUND4(D, A, B, C, 7, Sn, 50);
5543 + ROUND4(C, D, A, B, 14, So, 51); ROUND4(B, C, D, A, 5, Sp, 52);
5544 + ROUND4(A, B, C, D, 12, Sm, 53); ROUND4(D, A, B, C, 3, Sn, 54);
5545 + ROUND4(C, D, A, B, 10, So, 55); ROUND4(B, C, D, A, 1, Sp, 56);
5546 + ROUND4(A, B, C, D, 8, Sm, 57); ROUND4(D, A, B, C, 15, Sn, 58);
5547 + ROUND4(C, D, A, B, 6, So, 59); ROUND4(B, C, D, A, 13, Sp, 60);
5548 + ROUND4(A, B, C, D, 4, Sm, 61); ROUND4(D, A, B, C, 11, Sn, 62);
5549 + ROUND4(C, D, A, B, 2, So, 63); ROUND4(B, C, D, A, 9, Sp, 64);
5550 +
5551 + ctxt->md5_sta += A;
5552 + ctxt->md5_stb += B;
5553 + ctxt->md5_stc += C;
5554 + ctxt->md5_std += D;
5555 +}
5556 --- /dev/null
5557 +++ b/crypto/ocf/safe/md5.h
5558 @@ -0,0 +1,76 @@
5559 +/* $FreeBSD: src/sys/crypto/md5.h,v 1.4 2002/03/20 05:13:50 alfred Exp $ */
5560 +/* $KAME: md5.h,v 1.4 2000/03/27 04:36:22 sumikawa Exp $ */
5561 +
5562 +/*
5563 + * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
5564 + * All rights reserved.
5565 + *
5566 + * Redistribution and use in source and binary forms, with or without
5567 + * modification, are permitted provided that the following conditions
5568 + * are met:
5569 + * 1. Redistributions of source code must retain the above copyright
5570 + * notice, this list of conditions and the following disclaimer.
5571 + * 2. Redistributions in binary form must reproduce the above copyright
5572 + * notice, this list of conditions and the following disclaimer in the
5573 + * documentation and/or other materials provided with the distribution.
5574 + * 3. Neither the name of the project nor the names of its contributors
5575 + * may be used to endorse or promote products derived from this software
5576 + * without specific prior written permission.
5577 + *
5578 + * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
5579 + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
5580 + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
5581 + * ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
5582 + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
5583 + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
5584 + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
5585 + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
5586 + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
5587 + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
5588 + * SUCH DAMAGE.
5589 + */
5590 +
5591 +#ifndef _NETINET6_MD5_H_
5592 +#define _NETINET6_MD5_H_
5593 +
5594 +#define MD5_BUFLEN 64
5595 +
5596 +typedef struct {
5597 + union {
5598 + u_int32_t md5_state32[4];
5599 + u_int8_t md5_state8[16];
5600 + } md5_st;
5601 +
5602 +#define md5_sta md5_st.md5_state32[0]
5603 +#define md5_stb md5_st.md5_state32[1]
5604 +#define md5_stc md5_st.md5_state32[2]
5605 +#define md5_std md5_st.md5_state32[3]
5606 +#define md5_st8 md5_st.md5_state8
5607 +
5608 + union {
5609 + u_int64_t md5_count64;
5610 + u_int8_t md5_count8[8];
5611 + } md5_count;
5612 +#define md5_n md5_count.md5_count64
5613 +#define md5_n8 md5_count.md5_count8
5614 +
5615 + u_int md5_i;
5616 + u_int8_t md5_buf[MD5_BUFLEN];
5617 +} md5_ctxt;
5618 +
5619 +extern void md5_init(md5_ctxt *);
5620 +extern void md5_loop(md5_ctxt *, u_int8_t *, u_int);
5621 +extern void md5_pad(md5_ctxt *);
5622 +extern void md5_result(u_int8_t *, md5_ctxt *);
5623 +
5624 +/* compatibility */
5625 +#define MD5_CTX md5_ctxt
5626 +#define MD5Init(x) md5_init((x))
5627 +#define MD5Update(x, y, z) md5_loop((x), (y), (z))
5628 +#define MD5Final(x, y) \
5629 +do { \
5630 + md5_pad((y)); \
5631 + md5_result((x), (y)); \
5632 +} while (0)
5633 +
5634 +#endif /* ! _NETINET6_MD5_H_*/
5635 --- /dev/null
5636 +++ b/crypto/ocf/safe/safe.c
5637 @@ -0,0 +1,2288 @@
5638 +/*-
5639 + * Linux port done by David McCullough <david_mccullough@securecomputing.com>
5640 + * Copyright (C) 2004-2007 David McCullough
5641 + * The license and original author are listed below.
5642 + *
5643 + * Copyright (c) 2003 Sam Leffler, Errno Consulting
5644 + * Copyright (c) 2003 Global Technology Associates, Inc.
5645 + * All rights reserved.
5646 + *
5647 + * Redistribution and use in source and binary forms, with or without
5648 + * modification, are permitted provided that the following conditions
5649 + * are met:
5650 + * 1. Redistributions of source code must retain the above copyright
5651 + * notice, this list of conditions and the following disclaimer.
5652 + * 2. Redistributions in binary form must reproduce the above copyright
5653 + * notice, this list of conditions and the following disclaimer in the
5654 + * documentation and/or other materials provided with the distribution.
5655 + *
5656 + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
5657 + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
5658 + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
5659 + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
5660 + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
5661 + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
5662 + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
5663 + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
5664 + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
5665 + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
5666 + * SUCH DAMAGE.
5667 + *
5668 +__FBSDID("$FreeBSD: src/sys/dev/safe/safe.c,v 1.18 2007/03/21 03:42:50 sam Exp $");
5669 + */
5670 +
5671 +#ifndef AUTOCONF_INCLUDED
5672 +#include <linux/config.h>
5673 +#endif
5674 +#include <linux/module.h>
5675 +#include <linux/kernel.h>
5676 +#include <linux/init.h>
5677 +#include <linux/list.h>
5678 +#include <linux/slab.h>
5679 +#include <linux/wait.h>
5680 +#include <linux/sched.h>
5681 +#include <linux/pci.h>
5682 +#include <linux/delay.h>
5683 +#include <linux/interrupt.h>
5684 +#include <linux/spinlock.h>
5685 +#include <linux/random.h>
5686 +#include <linux/version.h>
5687 +#include <linux/skbuff.h>
5688 +#include <asm/io.h>
5689 +
5690 +/*
5691 + * SafeNet SafeXcel-1141 hardware crypto accelerator
5692 + */
5693 +
5694 +#include <cryptodev.h>
5695 +#include <uio.h>
5696 +#include <safe/safereg.h>
5697 +#include <safe/safevar.h>
5698 +
5699 +#if 1
5700 +#define DPRINTF(a) do { \
5701 + if (debug) { \
5702 + printk("%s: ", sc ? \
5703 + device_get_nameunit(sc->sc_dev) : "safe"); \
5704 + printk a; \
5705 + } \
5706 + } while (0)
5707 +#else
5708 +#define DPRINTF(a)
5709 +#endif
5710 +
5711 +/*
5712 + * until we find a cleaner way, include the BSD md5/sha1 code
5713 + * here
5714 + */
5715 +#define HMAC_HACK 1
5716 +#ifdef HMAC_HACK
5717 +#define LITTLE_ENDIAN 1234
5718 +#define BIG_ENDIAN 4321
5719 +#ifdef __LITTLE_ENDIAN
5720 +#define BYTE_ORDER LITTLE_ENDIAN
5721 +#endif
5722 +#ifdef __BIG_ENDIAN
5723 +#define BYTE_ORDER BIG_ENDIAN
5724 +#endif
5725 +#include <safe/md5.h>
5726 +#include <safe/md5.c>
5727 +#include <safe/sha1.h>
5728 +#include <safe/sha1.c>
5729 +
5730 +u_int8_t hmac_ipad_buffer[64] = {
5731 + 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36,
5732 + 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36,
5733 + 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36,
5734 + 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36,
5735 + 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36,
5736 + 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36,
5737 + 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36,
5738 + 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36
5739 +};
5740 +
5741 +u_int8_t hmac_opad_buffer[64] = {
5742 + 0x5C, 0x5C, 0x5C, 0x5C, 0x5C, 0x5C, 0x5C, 0x5C,
5743 + 0x5C, 0x5C, 0x5C, 0x5C, 0x5C, 0x5C, 0x5C, 0x5C,
5744 + 0x5C, 0x5C, 0x5C, 0x5C, 0x5C, 0x5C, 0x5C, 0x5C,
5745 + 0x5C, 0x5C, 0x5C, 0x5C, 0x5C, 0x5C, 0x5C, 0x5C,
5746 + 0x5C, 0x5C, 0x5C, 0x5C, 0x5C, 0x5C, 0x5C, 0x5C,
5747 + 0x5C, 0x5C, 0x5C, 0x5C, 0x5C, 0x5C, 0x5C, 0x5C,
5748 + 0x5C, 0x5C, 0x5C, 0x5C, 0x5C, 0x5C, 0x5C, 0x5C,
5749 + 0x5C, 0x5C, 0x5C, 0x5C, 0x5C, 0x5C, 0x5C, 0x5C
5750 +};
5751 +#endif /* HMAC_HACK */
5752 +
5753 +/* add proc entry for this */
5754 +struct safe_stats safestats;
5755 +
5756 +#define debug safe_debug
5757 +int safe_debug = 0;
5758 +module_param(safe_debug, int, 0644);
5759 +MODULE_PARM_DESC(safe_debug, "Enable debug");
5760 +
5761 +static void safe_callback(struct safe_softc *, struct safe_ringentry *);
5762 +static void safe_feed(struct safe_softc *, struct safe_ringentry *);
5763 +#if defined(CONFIG_OCF_RANDOMHARVEST) && !defined(SAFE_NO_RNG)
5764 +static void safe_rng_init(struct safe_softc *);
5765 +int safe_rngbufsize = 8; /* 32 bytes each read */
5766 +module_param(safe_rngbufsize, int, 0644);
5767 +MODULE_PARM_DESC(safe_rngbufsize, "RNG polling buffer size (32-bit words)");
5768 +int safe_rngmaxalarm = 8; /* max alarms before reset */
5769 +module_param(safe_rngmaxalarm, int, 0644);
5770 +MODULE_PARM_DESC(safe_rngmaxalarm, "RNG max alarms before reset");
5771 +#endif /* SAFE_NO_RNG */
5772 +
5773 +static void safe_totalreset(struct safe_softc *sc);
5774 +static int safe_dmamap_aligned(struct safe_softc *sc, const struct safe_operand *op);
5775 +static int safe_dmamap_uniform(struct safe_softc *sc, const struct safe_operand *op);
5776 +static int safe_free_entry(struct safe_softc *sc, struct safe_ringentry *re);
5777 +static int safe_kprocess(device_t dev, struct cryptkop *krp, int hint);
5778 +static int safe_kstart(struct safe_softc *sc);
5779 +static int safe_ksigbits(struct safe_softc *sc, struct crparam *cr);
5780 +static void safe_kfeed(struct safe_softc *sc);
5781 +static void safe_kpoll(unsigned long arg);
5782 +static void safe_kload_reg(struct safe_softc *sc, u_int32_t off,
5783 + u_int32_t len, struct crparam *n);
5784 +
5785 +static int safe_newsession(device_t, u_int32_t *, struct cryptoini *);
5786 +static int safe_freesession(device_t, u_int64_t);
5787 +static int safe_process(device_t, struct cryptop *, int);
5788 +
5789 +static device_method_t safe_methods = {
5790 + /* crypto device methods */
5791 + DEVMETHOD(cryptodev_newsession, safe_newsession),
5792 + DEVMETHOD(cryptodev_freesession,safe_freesession),
5793 + DEVMETHOD(cryptodev_process, safe_process),
5794 + DEVMETHOD(cryptodev_kprocess, safe_kprocess),
5795 +};
5796 +
5797 +#define READ_REG(sc,r) readl((sc)->sc_base_addr + (r))
5798 +#define WRITE_REG(sc,r,val) writel((val), (sc)->sc_base_addr + (r))
5799 +
5800 +#define SAFE_MAX_CHIPS 8
5801 +static struct safe_softc *safe_chip_idx[SAFE_MAX_CHIPS];
5802 +
5803 +/*
5804 + * split our buffers up into safe DMAable byte fragments to avoid lockup
5805 + * bug in 1141 HW on rev 1.0.
5806 + */
5807 +
5808 +static int
5809 +pci_map_linear(
5810 + struct safe_softc *sc,
5811 + struct safe_operand *buf,
5812 + void *addr,
5813 + int len)
5814 +{
5815 + dma_addr_t tmp;
5816 + int chunk, tlen = len;
5817 +
5818 + tmp = pci_map_single(sc->sc_pcidev, addr, len, PCI_DMA_BIDIRECTIONAL);
5819 +
5820 + buf->mapsize += len;
5821 + while (len > 0) {
5822 + chunk = (len > sc->sc_max_dsize) ? sc->sc_max_dsize : len;
5823 + buf->segs[buf->nsegs].ds_addr = tmp;
5824 + buf->segs[buf->nsegs].ds_len = chunk;
5825 + buf->segs[buf->nsegs].ds_tlen = tlen;
5826 + buf->nsegs++;
5827 + tmp += chunk;
5828 + len -= chunk;
5829 + tlen = 0;
5830 + }
5831 + return 0;
5832 +}
5833 +
5834 +/*
5835 + * map in a given uio buffer (great on some arches :-)
5836 + */
5837 +
5838 +static int
5839 +pci_map_uio(struct safe_softc *sc, struct safe_operand *buf, struct uio *uio)
5840 +{
5841 + struct iovec *iov = uio->uio_iov;
5842 + int n;
5843 +
5844 + DPRINTF(("%s()\n", __FUNCTION__));
5845 +
5846 + buf->mapsize = 0;
5847 + buf->nsegs = 0;
5848 +
5849 + for (n = 0; n < uio->uio_iovcnt; n++) {
5850 + pci_map_linear(sc, buf, iov->iov_base, iov->iov_len);
5851 + iov++;
5852 + }
5853 +
5854 + /* identify this buffer by the first segment */
5855 + buf->map = (void *) buf->segs[0].ds_addr;
5856 + return(0);
5857 +}
5858 +
5859 +/*
5860 + * map in a given sk_buff
5861 + */
5862 +
5863 +static int
5864 +pci_map_skb(struct safe_softc *sc,struct safe_operand *buf,struct sk_buff *skb)
5865 +{
5866 + int i;
5867 +
5868 + DPRINTF(("%s()\n", __FUNCTION__));
5869 +
5870 + buf->mapsize = 0;
5871 + buf->nsegs = 0;
5872 +
5873 + pci_map_linear(sc, buf, skb->data, skb_headlen(skb));
5874 +
5875 + for (i = 0; i < skb_shinfo(skb)->nr_frags; i++) {
5876 + pci_map_linear(sc, buf,
5877 + page_address(skb_shinfo(skb)->frags[i].page) +
5878 + skb_shinfo(skb)->frags[i].page_offset,
5879 + skb_shinfo(skb)->frags[i].size);
5880 + }
5881 +
5882 + /* identify this buffer by the first segment */
5883 + buf->map = (void *) buf->segs[0].ds_addr;
5884 + return(0);
5885 +}
5886 +
5887 +
5888 +#if 0 /* not needed at this time */
5889 +static void
5890 +pci_sync_operand(struct safe_softc *sc, struct safe_operand *buf)
5891 +{
5892 + int i;
5893 +
5894 + DPRINTF(("%s()\n", __FUNCTION__));
5895 + for (i = 0; i < buf->nsegs; i++)
5896 + pci_dma_sync_single_for_cpu(sc->sc_pcidev, buf->segs[i].ds_addr,
5897 + buf->segs[i].ds_len, PCI_DMA_BIDIRECTIONAL);
5898 +}
5899 +#endif
5900 +
5901 +static void
5902 +pci_unmap_operand(struct safe_softc *sc, struct safe_operand *buf)
5903 +{
5904 + int i;
5905 + DPRINTF(("%s()\n", __FUNCTION__));
5906 + for (i = 0; i < buf->nsegs; i++) {
5907 + if (buf->segs[i].ds_tlen) {
5908 + DPRINTF(("%s - unmap %d 0x%x %d\n", __FUNCTION__, i, buf->segs[i].ds_addr, buf->segs[i].ds_tlen));
5909 + pci_unmap_single(sc->sc_pcidev, buf->segs[i].ds_addr,
5910 + buf->segs[i].ds_tlen, PCI_DMA_BIDIRECTIONAL);
5911 + DPRINTF(("%s - unmap %d 0x%x %d done\n", __FUNCTION__, i, buf->segs[i].ds_addr, buf->segs[i].ds_tlen));
5912 + }
5913 + buf->segs[i].ds_addr = 0;
5914 + buf->segs[i].ds_len = 0;
5915 + buf->segs[i].ds_tlen = 0;
5916 + }
5917 + buf->nsegs = 0;
5918 + buf->mapsize = 0;
5919 + buf->map = 0;
5920 +}
5921 +
5922 +
5923 +/*
5924 + * SafeXcel Interrupt routine
5925 + */
5926 +static irqreturn_t
5927 +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,19)
5928 +safe_intr(int irq, void *arg)
5929 +#else
5930 +safe_intr(int irq, void *arg, struct pt_regs *regs)
5931 +#endif
5932 +{
5933 + struct safe_softc *sc = arg;
5934 + int stat;
5935 + unsigned long flags;
5936 +
5937 + stat = READ_REG(sc, SAFE_HM_STAT);
5938 +
5939 + DPRINTF(("%s(stat=0x%x)\n", __FUNCTION__, stat));
5940 +
5941 + if (stat == 0) /* shared irq, not for us */
5942 + return IRQ_NONE;
5943 +
5944 + WRITE_REG(sc, SAFE_HI_CLR, stat); /* IACK */
5945 +
5946 + if ((stat & SAFE_INT_PE_DDONE)) {
5947 + /*
5948 + * Descriptor(s) done; scan the ring and
5949 + * process completed operations.
5950 + */
5951 + spin_lock_irqsave(&sc->sc_ringmtx, flags);
5952 + while (sc->sc_back != sc->sc_front) {
5953 + struct safe_ringentry *re = sc->sc_back;
5954 +
5955 +#ifdef SAFE_DEBUG
5956 + if (debug) {
5957 + safe_dump_ringstate(sc, __func__);
5958 + safe_dump_request(sc, __func__, re);
5959 + }
5960 +#endif
5961 + /*
5962 + * safe_process marks ring entries that were allocated
5963 + * but not used with a csr of zero. This insures the
5964 + * ring front pointer never needs to be set backwards
5965 + * in the event that an entry is allocated but not used
5966 + * because of a setup error.
5967 + */
5968 + DPRINTF(("%s re->re_desc.d_csr=0x%x\n", __FUNCTION__, re->re_desc.d_csr));
5969 + if (re->re_desc.d_csr != 0) {
5970 + if (!SAFE_PE_CSR_IS_DONE(re->re_desc.d_csr)) {
5971 + DPRINTF(("%s !CSR_IS_DONE\n", __FUNCTION__));
5972 + break;
5973 + }
5974 + if (!SAFE_PE_LEN_IS_DONE(re->re_desc.d_len)) {
5975 + DPRINTF(("%s !LEN_IS_DONE\n", __FUNCTION__));
5976 + break;
5977 + }
5978 + sc->sc_nqchip--;
5979 + safe_callback(sc, re);
5980 + }
5981 + if (++(sc->sc_back) == sc->sc_ringtop)
5982 + sc->sc_back = sc->sc_ring;
5983 + }
5984 + spin_unlock_irqrestore(&sc->sc_ringmtx, flags);
5985 + }
5986 +
5987 + /*
5988 + * Check to see if we got any DMA Error
5989 + */
5990 + if (stat & SAFE_INT_PE_ERROR) {
5991 + printk("%s: dmaerr dmastat %08x\n", device_get_nameunit(sc->sc_dev),
5992 + (int)READ_REG(sc, SAFE_PE_DMASTAT));
5993 + safestats.st_dmaerr++;
5994 + safe_totalreset(sc);
5995 +#if 0
5996 + safe_feed(sc);
5997 +#endif
5998 + }
5999 +
6000 + if (sc->sc_needwakeup) { /* XXX check high watermark */
6001 + int wakeup = sc->sc_needwakeup & (CRYPTO_SYMQ|CRYPTO_ASYMQ);
6002 + DPRINTF(("%s: wakeup crypto %x\n", __func__,
6003 + sc->sc_needwakeup));
6004 + sc->sc_needwakeup &= ~wakeup;
6005 + crypto_unblock(sc->sc_cid, wakeup);
6006 + }
6007 +
6008 + return IRQ_HANDLED;
6009 +}
6010 +
6011 +/*
6012 + * safe_feed() - post a request to chip
6013 + */
6014 +static void
6015 +safe_feed(struct safe_softc *sc, struct safe_ringentry *re)
6016 +{
6017 + DPRINTF(("%s()\n", __FUNCTION__));
6018 +#ifdef SAFE_DEBUG
6019 + if (debug) {
6020 + safe_dump_ringstate(sc, __func__);
6021 + safe_dump_request(sc, __func__, re);
6022 + }
6023 +#endif
6024 + sc->sc_nqchip++;
6025 + if (sc->sc_nqchip > safestats.st_maxqchip)
6026 + safestats.st_maxqchip = sc->sc_nqchip;
6027 + /* poke h/w to check descriptor ring, any value can be written */
6028 + WRITE_REG(sc, SAFE_HI_RD_DESCR, 0);
6029 +}
6030 +
6031 +#define N(a) (sizeof(a) / sizeof (a[0]))
6032 +static void
6033 +safe_setup_enckey(struct safe_session *ses, caddr_t key)
6034 +{
6035 + int i;
6036 +
6037 + bcopy(key, ses->ses_key, ses->ses_klen / 8);
6038 +
6039 + /* PE is little-endian, insure proper byte order */
6040 + for (i = 0; i < N(ses->ses_key); i++)
6041 + ses->ses_key[i] = htole32(ses->ses_key[i]);
6042 +}
6043 +
6044 +static void
6045 +safe_setup_mackey(struct safe_session *ses, int algo, caddr_t key, int klen)
6046 +{
6047 +#ifdef HMAC_HACK
6048 + MD5_CTX md5ctx;
6049 + SHA1_CTX sha1ctx;
6050 + int i;
6051 +
6052 +
6053 + for (i = 0; i < klen; i++)
6054 + key[i] ^= HMAC_IPAD_VAL;
6055 +
6056 + if (algo == CRYPTO_MD5_HMAC) {
6057 + MD5Init(&md5ctx);
6058 + MD5Update(&md5ctx, key, klen);
6059 + MD5Update(&md5ctx, hmac_ipad_buffer, MD5_HMAC_BLOCK_LEN - klen);
6060 + bcopy(md5ctx.md5_st8, ses->ses_hminner, sizeof(md5ctx.md5_st8));
6061 + } else {
6062 + SHA1Init(&sha1ctx);
6063 + SHA1Update(&sha1ctx, key, klen);
6064 + SHA1Update(&sha1ctx, hmac_ipad_buffer,
6065 + SHA1_HMAC_BLOCK_LEN - klen);
6066 + bcopy(sha1ctx.h.b32, ses->ses_hminner, sizeof(sha1ctx.h.b32));
6067 + }
6068 +
6069 + for (i = 0; i < klen; i++)
6070 + key[i] ^= (HMAC_IPAD_VAL ^ HMAC_OPAD_VAL);
6071 +
6072 + if (algo == CRYPTO_MD5_HMAC) {
6073 + MD5Init(&md5ctx);
6074 + MD5Update(&md5ctx, key, klen);
6075 + MD5Update(&md5ctx, hmac_opad_buffer, MD5_HMAC_BLOCK_LEN - klen);
6076 + bcopy(md5ctx.md5_st8, ses->ses_hmouter, sizeof(md5ctx.md5_st8));
6077 + } else {
6078 + SHA1Init(&sha1ctx);
6079 + SHA1Update(&sha1ctx, key, klen);
6080 + SHA1Update(&sha1ctx, hmac_opad_buffer,
6081 + SHA1_HMAC_BLOCK_LEN - klen);
6082 + bcopy(sha1ctx.h.b32, ses->ses_hmouter, sizeof(sha1ctx.h.b32));
6083 + }
6084 +
6085 + for (i = 0; i < klen; i++)
6086 + key[i] ^= HMAC_OPAD_VAL;
6087 +
6088 +#if 0
6089 + /*
6090 + * this code prevents SHA working on a BE host,
6091 + * so it is obviously wrong. I think the byte
6092 + * swap setup we do with the chip fixes this for us
6093 + */
6094 +
6095 + /* PE is little-endian, insure proper byte order */
6096 + for (i = 0; i < N(ses->ses_hminner); i++) {
6097 + ses->ses_hminner[i] = htole32(ses->ses_hminner[i]);
6098 + ses->ses_hmouter[i] = htole32(ses->ses_hmouter[i]);
6099 + }
6100 +#endif
6101 +#else /* HMAC_HACK */
6102 + printk("safe: md5/sha not implemented\n");
6103 +#endif /* HMAC_HACK */
6104 +}
6105 +#undef N
6106 +
6107 +/*
6108 + * Allocate a new 'session' and return an encoded session id. 'sidp'
6109 + * contains our registration id, and should contain an encoded session
6110 + * id on successful allocation.
6111 + */
6112 +static int
6113 +safe_newsession(device_t dev, u_int32_t *sidp, struct cryptoini *cri)
6114 +{
6115 + struct safe_softc *sc = device_get_softc(dev);
6116 + struct cryptoini *c, *encini = NULL, *macini = NULL;
6117 + struct safe_session *ses = NULL;
6118 + int sesn;
6119 +
6120 + DPRINTF(("%s()\n", __FUNCTION__));
6121 +
6122 + if (sidp == NULL || cri == NULL || sc == NULL)
6123 + return (EINVAL);
6124 +
6125 + for (c = cri; c != NULL; c = c->cri_next) {
6126 + if (c->cri_alg == CRYPTO_MD5_HMAC ||
6127 + c->cri_alg == CRYPTO_SHA1_HMAC ||
6128 + c->cri_alg == CRYPTO_NULL_HMAC) {
6129 + if (macini)
6130 + return (EINVAL);
6131 + macini = c;
6132 + } else if (c->cri_alg == CRYPTO_DES_CBC ||
6133 + c->cri_alg == CRYPTO_3DES_CBC ||
6134 + c->cri_alg == CRYPTO_AES_CBC ||
6135 + c->cri_alg == CRYPTO_NULL_CBC) {
6136 + if (encini)
6137 + return (EINVAL);
6138 + encini = c;
6139 + } else
6140 + return (EINVAL);
6141 + }
6142 + if (encini == NULL && macini == NULL)
6143 + return (EINVAL);
6144 + if (encini) { /* validate key length */
6145 + switch (encini->cri_alg) {
6146 + case CRYPTO_DES_CBC:
6147 + if (encini->cri_klen != 64)
6148 + return (EINVAL);
6149 + break;
6150 + case CRYPTO_3DES_CBC:
6151 + if (encini->cri_klen != 192)
6152 + return (EINVAL);
6153 + break;
6154 + case CRYPTO_AES_CBC:
6155 + if (encini->cri_klen != 128 &&
6156 + encini->cri_klen != 192 &&
6157 + encini->cri_klen != 256)
6158 + return (EINVAL);
6159 + break;
6160 + }
6161 + }
6162 +
6163 + if (sc->sc_sessions == NULL) {
6164 + ses = sc->sc_sessions = (struct safe_session *)
6165 + kmalloc(sizeof(struct safe_session), SLAB_ATOMIC);
6166 + if (ses == NULL)
6167 + return (ENOMEM);
6168 + memset(ses, 0, sizeof(struct safe_session));
6169 + sesn = 0;
6170 + sc->sc_nsessions = 1;
6171 + } else {
6172 + for (sesn = 0; sesn < sc->sc_nsessions; sesn++) {
6173 + if (sc->sc_sessions[sesn].ses_used == 0) {
6174 + ses = &sc->sc_sessions[sesn];
6175 + break;
6176 + }
6177 + }
6178 +
6179 + if (ses == NULL) {
6180 + sesn = sc->sc_nsessions;
6181 + ses = (struct safe_session *)
6182 + kmalloc((sesn + 1) * sizeof(struct safe_session), SLAB_ATOMIC);
6183 + if (ses == NULL)
6184 + return (ENOMEM);
6185 + memset(ses, 0, (sesn + 1) * sizeof(struct safe_session));
6186 + bcopy(sc->sc_sessions, ses, sesn *
6187 + sizeof(struct safe_session));
6188 + bzero(sc->sc_sessions, sesn *
6189 + sizeof(struct safe_session));
6190 + kfree(sc->sc_sessions);
6191 + sc->sc_sessions = ses;
6192 + ses = &sc->sc_sessions[sesn];
6193 + sc->sc_nsessions++;
6194 + }
6195 + }
6196 +
6197 + bzero(ses, sizeof(struct safe_session));
6198 + ses->ses_used = 1;
6199 +
6200 + if (encini) {
6201 + /* get an IV */
6202 + /* XXX may read fewer than requested */
6203 + read_random(ses->ses_iv, sizeof(ses->ses_iv));
6204 +
6205 + ses->ses_klen = encini->cri_klen;
6206 + if (encini->cri_key != NULL)
6207 + safe_setup_enckey(ses, encini->cri_key);
6208 + }
6209 +
6210 + if (macini) {
6211 + ses->ses_mlen = macini->cri_mlen;
6212 + if (ses->ses_mlen == 0) {
6213 + if (macini->cri_alg == CRYPTO_MD5_HMAC)
6214 + ses->ses_mlen = MD5_HASH_LEN;
6215 + else
6216 + ses->ses_mlen = SHA1_HASH_LEN;
6217 + }
6218 +
6219 + if (macini->cri_key != NULL) {
6220 + safe_setup_mackey(ses, macini->cri_alg, macini->cri_key,
6221 + macini->cri_klen / 8);
6222 + }
6223 + }
6224 +
6225 + *sidp = SAFE_SID(device_get_unit(sc->sc_dev), sesn);
6226 + return (0);
6227 +}
6228 +
6229 +/*
6230 + * Deallocate a session.
6231 + */
6232 +static int
6233 +safe_freesession(device_t dev, u_int64_t tid)
6234 +{
6235 + struct safe_softc *sc = device_get_softc(dev);
6236 + int session, ret;
6237 + u_int32_t sid = ((u_int32_t) tid) & 0xffffffff;
6238 +
6239 + DPRINTF(("%s()\n", __FUNCTION__));
6240 +
6241 + if (sc == NULL)
6242 + return (EINVAL);
6243 +
6244 + session = SAFE_SESSION(sid);
6245 + if (session < sc->sc_nsessions) {
6246 + bzero(&sc->sc_sessions[session], sizeof(sc->sc_sessions[session]));
6247 + ret = 0;
6248 + } else
6249 + ret = EINVAL;
6250 + return (ret);
6251 +}
6252 +
6253 +
6254 +static int
6255 +safe_process(device_t dev, struct cryptop *crp, int hint)
6256 +{
6257 + struct safe_softc *sc = device_get_softc(dev);
6258 + int err = 0, i, nicealign, uniform;
6259 + struct cryptodesc *crd1, *crd2, *maccrd, *enccrd;
6260 + int bypass, oplen, ivsize;
6261 + caddr_t iv;
6262 + int16_t coffset;
6263 + struct safe_session *ses;
6264 + struct safe_ringentry *re;
6265 + struct safe_sarec *sa;
6266 + struct safe_pdesc *pd;
6267 + u_int32_t cmd0, cmd1, staterec;
6268 + unsigned long flags;
6269 +
6270 + DPRINTF(("%s()\n", __FUNCTION__));
6271 +
6272 + if (crp == NULL || crp->crp_callback == NULL || sc == NULL) {
6273 + safestats.st_invalid++;
6274 + return (EINVAL);
6275 + }
6276 + if (SAFE_SESSION(crp->crp_sid) >= sc->sc_nsessions) {
6277 + safestats.st_badsession++;
6278 + return (EINVAL);
6279 + }
6280 +
6281 + spin_lock_irqsave(&sc->sc_ringmtx, flags);
6282 + if (sc->sc_front == sc->sc_back && sc->sc_nqchip != 0) {
6283 + safestats.st_ringfull++;
6284 + sc->sc_needwakeup |= CRYPTO_SYMQ;
6285 + spin_unlock_irqrestore(&sc->sc_ringmtx, flags);
6286 + return (ERESTART);
6287 + }
6288 + re = sc->sc_front;
6289 +
6290 + staterec = re->re_sa.sa_staterec; /* save */
6291 + /* NB: zero everything but the PE descriptor */
6292 + bzero(&re->re_sa, sizeof(struct safe_ringentry) - sizeof(re->re_desc));
6293 + re->re_sa.sa_staterec = staterec; /* restore */
6294 +
6295 + re->re_crp = crp;
6296 + re->re_sesn = SAFE_SESSION(crp->crp_sid);
6297 +
6298 + re->re_src.nsegs = 0;
6299 + re->re_dst.nsegs = 0;
6300 +
6301 + if (crp->crp_flags & CRYPTO_F_SKBUF) {
6302 + re->re_src_skb = (struct sk_buff *)crp->crp_buf;
6303 + re->re_dst_skb = (struct sk_buff *)crp->crp_buf;
6304 + } else if (crp->crp_flags & CRYPTO_F_IOV) {
6305 + re->re_src_io = (struct uio *)crp->crp_buf;
6306 + re->re_dst_io = (struct uio *)crp->crp_buf;
6307 + } else {
6308 + safestats.st_badflags++;
6309 + err = EINVAL;
6310 + goto errout; /* XXX we don't handle contiguous blocks! */
6311 + }
6312 +
6313 + sa = &re->re_sa;
6314 + ses = &sc->sc_sessions[re->re_sesn];
6315 +
6316 + crd1 = crp->crp_desc;
6317 + if (crd1 == NULL) {
6318 + safestats.st_nodesc++;
6319 + err = EINVAL;
6320 + goto errout;
6321 + }
6322 + crd2 = crd1->crd_next;
6323 +
6324 + cmd0 = SAFE_SA_CMD0_BASIC; /* basic group operation */
6325 + cmd1 = 0;
6326 + if (crd2 == NULL) {
6327 + if (crd1->crd_alg == CRYPTO_MD5_HMAC ||
6328 + crd1->crd_alg == CRYPTO_SHA1_HMAC ||
6329 + crd1->crd_alg == CRYPTO_NULL_HMAC) {
6330 + maccrd = crd1;
6331 + enccrd = NULL;
6332 + cmd0 |= SAFE_SA_CMD0_OP_HASH;
6333 + } else if (crd1->crd_alg == CRYPTO_DES_CBC ||
6334 + crd1->crd_alg == CRYPTO_3DES_CBC ||
6335 + crd1->crd_alg == CRYPTO_AES_CBC ||
6336 + crd1->crd_alg == CRYPTO_NULL_CBC) {
6337 + maccrd = NULL;
6338 + enccrd = crd1;
6339 + cmd0 |= SAFE_SA_CMD0_OP_CRYPT;
6340 + } else {
6341 + safestats.st_badalg++;
6342 + err = EINVAL;
6343 + goto errout;
6344 + }
6345 + } else {
6346 + if ((crd1->crd_alg == CRYPTO_MD5_HMAC ||
6347 + crd1->crd_alg == CRYPTO_SHA1_HMAC ||
6348 + crd1->crd_alg == CRYPTO_NULL_HMAC) &&
6349 + (crd2->crd_alg == CRYPTO_DES_CBC ||
6350 + crd2->crd_alg == CRYPTO_3DES_CBC ||
6351 + crd2->crd_alg == CRYPTO_AES_CBC ||
6352 + crd2->crd_alg == CRYPTO_NULL_CBC) &&
6353 + ((crd2->crd_flags & CRD_F_ENCRYPT) == 0)) {
6354 + maccrd = crd1;
6355 + enccrd = crd2;
6356 + } else if ((crd1->crd_alg == CRYPTO_DES_CBC ||
6357 + crd1->crd_alg == CRYPTO_3DES_CBC ||
6358 + crd1->crd_alg == CRYPTO_AES_CBC ||
6359 + crd1->crd_alg == CRYPTO_NULL_CBC) &&
6360 + (crd2->crd_alg == CRYPTO_MD5_HMAC ||
6361 + crd2->crd_alg == CRYPTO_SHA1_HMAC ||
6362 + crd2->crd_alg == CRYPTO_NULL_HMAC) &&
6363 + (crd1->crd_flags & CRD_F_ENCRYPT)) {
6364 + enccrd = crd1;
6365 + maccrd = crd2;
6366 + } else {
6367 + safestats.st_badalg++;
6368 + err = EINVAL;
6369 + goto errout;
6370 + }
6371 + cmd0 |= SAFE_SA_CMD0_OP_BOTH;
6372 + }
6373 +
6374 + if (enccrd) {
6375 + if (enccrd->crd_flags & CRD_F_KEY_EXPLICIT)
6376 + safe_setup_enckey(ses, enccrd->crd_key);
6377 +
6378 + if (enccrd->crd_alg == CRYPTO_DES_CBC) {
6379 + cmd0 |= SAFE_SA_CMD0_DES;
6380 + cmd1 |= SAFE_SA_CMD1_CBC;
6381 + ivsize = 2*sizeof(u_int32_t);
6382 + } else if (enccrd->crd_alg == CRYPTO_3DES_CBC) {
6383 + cmd0 |= SAFE_SA_CMD0_3DES;
6384 + cmd1 |= SAFE_SA_CMD1_CBC;
6385 + ivsize = 2*sizeof(u_int32_t);
6386 + } else if (enccrd->crd_alg == CRYPTO_AES_CBC) {
6387 + cmd0 |= SAFE_SA_CMD0_AES;
6388 + cmd1 |= SAFE_SA_CMD1_CBC;
6389 + if (ses->ses_klen == 128)
6390 + cmd1 |= SAFE_SA_CMD1_AES128;
6391 + else if (ses->ses_klen == 192)
6392 + cmd1 |= SAFE_SA_CMD1_AES192;
6393 + else
6394 + cmd1 |= SAFE_SA_CMD1_AES256;
6395 + ivsize = 4*sizeof(u_int32_t);
6396 + } else {
6397 + cmd0 |= SAFE_SA_CMD0_CRYPT_NULL;
6398 + ivsize = 0;
6399 + }
6400 +
6401 + /*
6402 + * Setup encrypt/decrypt state. When using basic ops
6403 + * we can't use an inline IV because hash/crypt offset
6404 + * must be from the end of the IV to the start of the
6405 + * crypt data and this leaves out the preceding header
6406 + * from the hash calculation. Instead we place the IV
6407 + * in the state record and set the hash/crypt offset to
6408 + * copy both the header+IV.
6409 + */
6410 + if (enccrd->crd_flags & CRD_F_ENCRYPT) {
6411 + cmd0 |= SAFE_SA_CMD0_OUTBOUND;
6412 +
6413 + if (enccrd->crd_flags & CRD_F_IV_EXPLICIT)
6414 + iv = enccrd->crd_iv;
6415 + else
6416 + iv = (caddr_t) ses->ses_iv;
6417 + if ((enccrd->crd_flags & CRD_F_IV_PRESENT) == 0) {
6418 + crypto_copyback(crp->crp_flags, crp->crp_buf,
6419 + enccrd->crd_inject, ivsize, iv);
6420 + }
6421 + bcopy(iv, re->re_sastate.sa_saved_iv, ivsize);
6422 + /* make iv LE */
6423 + for (i = 0; i < ivsize/sizeof(re->re_sastate.sa_saved_iv[0]); i++)
6424 + re->re_sastate.sa_saved_iv[i] =
6425 + cpu_to_le32(re->re_sastate.sa_saved_iv[i]);
6426 + cmd0 |= SAFE_SA_CMD0_IVLD_STATE | SAFE_SA_CMD0_SAVEIV;
6427 + re->re_flags |= SAFE_QFLAGS_COPYOUTIV;
6428 + } else {
6429 + cmd0 |= SAFE_SA_CMD0_INBOUND;
6430 +
6431 + if (enccrd->crd_flags & CRD_F_IV_EXPLICIT) {
6432 + bcopy(enccrd->crd_iv,
6433 + re->re_sastate.sa_saved_iv, ivsize);
6434 + } else {
6435 + crypto_copydata(crp->crp_flags, crp->crp_buf,
6436 + enccrd->crd_inject, ivsize,
6437 + (caddr_t)re->re_sastate.sa_saved_iv);
6438 + }
6439 + /* make iv LE */
6440 + for (i = 0; i < ivsize/sizeof(re->re_sastate.sa_saved_iv[0]); i++)
6441 + re->re_sastate.sa_saved_iv[i] =
6442 + cpu_to_le32(re->re_sastate.sa_saved_iv[i]);
6443 + cmd0 |= SAFE_SA_CMD0_IVLD_STATE;
6444 + }
6445 + /*
6446 + * For basic encryption use the zero pad algorithm.
6447 + * This pads results to an 8-byte boundary and
6448 + * suppresses padding verification for inbound (i.e.
6449 + * decrypt) operations.
6450 + *
6451 + * NB: Not sure if the 8-byte pad boundary is a problem.
6452 + */
6453 + cmd0 |= SAFE_SA_CMD0_PAD_ZERO;
6454 +
6455 + /* XXX assert key bufs have the same size */
6456 + bcopy(ses->ses_key, sa->sa_key, sizeof(sa->sa_key));
6457 + }
6458 +
6459 + if (maccrd) {
6460 + if (maccrd->crd_flags & CRD_F_KEY_EXPLICIT) {
6461 + safe_setup_mackey(ses, maccrd->crd_alg,
6462 + maccrd->crd_key, maccrd->crd_klen / 8);
6463 + }
6464 +
6465 + if (maccrd->crd_alg == CRYPTO_MD5_HMAC) {
6466 + cmd0 |= SAFE_SA_CMD0_MD5;
6467 + cmd1 |= SAFE_SA_CMD1_HMAC; /* NB: enable HMAC */
6468 + } else if (maccrd->crd_alg == CRYPTO_SHA1_HMAC) {
6469 + cmd0 |= SAFE_SA_CMD0_SHA1;
6470 + cmd1 |= SAFE_SA_CMD1_HMAC; /* NB: enable HMAC */
6471 + } else {
6472 + cmd0 |= SAFE_SA_CMD0_HASH_NULL;
6473 + }
6474 + /*
6475 + * Digest data is loaded from the SA and the hash
6476 + * result is saved to the state block where we
6477 + * retrieve it for return to the caller.
6478 + */
6479 + /* XXX assert digest bufs have the same size */
6480 + bcopy(ses->ses_hminner, sa->sa_indigest,
6481 + sizeof(sa->sa_indigest));
6482 + bcopy(ses->ses_hmouter, sa->sa_outdigest,
6483 + sizeof(sa->sa_outdigest));
6484 +
6485 + cmd0 |= SAFE_SA_CMD0_HSLD_SA | SAFE_SA_CMD0_SAVEHASH;
6486 + re->re_flags |= SAFE_QFLAGS_COPYOUTICV;
6487 + }
6488 +
6489 + if (enccrd && maccrd) {
6490 + /*
6491 + * The offset from hash data to the start of
6492 + * crypt data is the difference in the skips.
6493 + */
6494 + bypass = maccrd->crd_skip;
6495 + coffset = enccrd->crd_skip - maccrd->crd_skip;
6496 + if (coffset < 0) {
6497 + DPRINTF(("%s: hash does not precede crypt; "
6498 + "mac skip %u enc skip %u\n",
6499 + __func__, maccrd->crd_skip, enccrd->crd_skip));
6500 + safestats.st_skipmismatch++;
6501 + err = EINVAL;
6502 + goto errout;
6503 + }
6504 + oplen = enccrd->crd_skip + enccrd->crd_len;
6505 + if (maccrd->crd_skip + maccrd->crd_len != oplen) {
6506 + DPRINTF(("%s: hash amount %u != crypt amount %u\n",
6507 + __func__, maccrd->crd_skip + maccrd->crd_len,
6508 + oplen));
6509 + safestats.st_lenmismatch++;
6510 + err = EINVAL;
6511 + goto errout;
6512 + }
6513 +#ifdef SAFE_DEBUG
6514 + if (debug) {
6515 + printf("mac: skip %d, len %d, inject %d\n",
6516 + maccrd->crd_skip, maccrd->crd_len,
6517 + maccrd->crd_inject);
6518 + printf("enc: skip %d, len %d, inject %d\n",
6519 + enccrd->crd_skip, enccrd->crd_len,
6520 + enccrd->crd_inject);
6521 + printf("bypass %d coffset %d oplen %d\n",
6522 + bypass, coffset, oplen);
6523 + }
6524 +#endif
6525 + if (coffset & 3) { /* offset must be 32-bit aligned */
6526 + DPRINTF(("%s: coffset %u misaligned\n",
6527 + __func__, coffset));
6528 + safestats.st_coffmisaligned++;
6529 + err = EINVAL;
6530 + goto errout;
6531 + }
6532 + coffset >>= 2;
6533 + if (coffset > 255) { /* offset must be <256 dwords */
6534 + DPRINTF(("%s: coffset %u too big\n",
6535 + __func__, coffset));
6536 + safestats.st_cofftoobig++;
6537 + err = EINVAL;
6538 + goto errout;
6539 + }
6540 + /*
6541 + * Tell the hardware to copy the header to the output.
6542 + * The header is defined as the data from the end of
6543 + * the bypass to the start of data to be encrypted.
6544 + * Typically this is the inline IV. Note that you need
6545 + * to do this even if src+dst are the same; it appears
6546 + * that w/o this bit the crypted data is written
6547 + * immediately after the bypass data.
6548 + */
6549 + cmd1 |= SAFE_SA_CMD1_HDRCOPY;
6550 + /*
6551 + * Disable IP header mutable bit handling. This is
6552 + * needed to get correct HMAC calculations.
6553 + */
6554 + cmd1 |= SAFE_SA_CMD1_MUTABLE;
6555 + } else {
6556 + if (enccrd) {
6557 + bypass = enccrd->crd_skip;
6558 + oplen = bypass + enccrd->crd_len;
6559 + } else {
6560 + bypass = maccrd->crd_skip;
6561 + oplen = bypass + maccrd->crd_len;
6562 + }
6563 + coffset = 0;
6564 + }
6565 + /* XXX verify multiple of 4 when using s/g */
6566 + if (bypass > 96) { /* bypass offset must be <= 96 bytes */
6567 + DPRINTF(("%s: bypass %u too big\n", __func__, bypass));
6568 + safestats.st_bypasstoobig++;
6569 + err = EINVAL;
6570 + goto errout;
6571 + }
6572 +
6573 + if (crp->crp_flags & CRYPTO_F_SKBUF) {
6574 + if (pci_map_skb(sc, &re->re_src, re->re_src_skb)) {
6575 + safestats.st_noload++;
6576 + err = ENOMEM;
6577 + goto errout;
6578 + }
6579 + } else if (crp->crp_flags & CRYPTO_F_IOV) {
6580 + if (pci_map_uio(sc, &re->re_src, re->re_src_io)) {
6581 + safestats.st_noload++;
6582 + err = ENOMEM;
6583 + goto errout;
6584 + }
6585 + }
6586 + nicealign = safe_dmamap_aligned(sc, &re->re_src);
6587 + uniform = safe_dmamap_uniform(sc, &re->re_src);
6588 +
6589 + DPRINTF(("src nicealign %u uniform %u nsegs %u\n",
6590 + nicealign, uniform, re->re_src.nsegs));
6591 + if (re->re_src.nsegs > 1) {
6592 + re->re_desc.d_src = sc->sc_spalloc.dma_paddr +
6593 + ((caddr_t) sc->sc_spfree - (caddr_t) sc->sc_spring);
6594 + for (i = 0; i < re->re_src_nsegs; i++) {
6595 + /* NB: no need to check if there's space */
6596 + pd = sc->sc_spfree;
6597 + if (++(sc->sc_spfree) == sc->sc_springtop)
6598 + sc->sc_spfree = sc->sc_spring;
6599 +
6600 + KASSERT((pd->pd_flags&3) == 0 ||
6601 + (pd->pd_flags&3) == SAFE_PD_DONE,
6602 + ("bogus source particle descriptor; flags %x",
6603 + pd->pd_flags));
6604 + pd->pd_addr = re->re_src_segs[i].ds_addr;
6605 + pd->pd_size = re->re_src_segs[i].ds_len;
6606 + pd->pd_flags = SAFE_PD_READY;
6607 + }
6608 + cmd0 |= SAFE_SA_CMD0_IGATHER;
6609 + } else {
6610 + /*
6611 + * No need for gather, reference the operand directly.
6612 + */
6613 + re->re_desc.d_src = re->re_src_segs[0].ds_addr;
6614 + }
6615 +
6616 + if (enccrd == NULL && maccrd != NULL) {
6617 + /*
6618 + * Hash op; no destination needed.
6619 + */
6620 + } else {
6621 + if (crp->crp_flags & (CRYPTO_F_IOV|CRYPTO_F_SKBUF)) {
6622 + if (!nicealign) {
6623 + safestats.st_iovmisaligned++;
6624 + err = EINVAL;
6625 + goto errout;
6626 + }
6627 + if (uniform != 1) {
6628 + device_printf(sc->sc_dev, "!uniform source\n");
6629 + if (!uniform) {
6630 + /*
6631 + * There's no way to handle the DMA
6632 + * requirements with this uio. We
6633 + * could create a separate DMA area for
6634 + * the result and then copy it back,
6635 + * but for now we just bail and return
6636 + * an error. Note that uio requests
6637 + * > SAFE_MAX_DSIZE are handled because
6638 + * the DMA map and segment list for the
6639 + * destination wil result in a
6640 + * destination particle list that does
6641 + * the necessary scatter DMA.
6642 + */
6643 + safestats.st_iovnotuniform++;
6644 + err = EINVAL;
6645 + goto errout;
6646 + }
6647 + } else
6648 + re->re_dst = re->re_src;
6649 + } else {
6650 + safestats.st_badflags++;
6651 + err = EINVAL;
6652 + goto errout;
6653 + }
6654 +
6655 + if (re->re_dst.nsegs > 1) {
6656 + re->re_desc.d_dst = sc->sc_dpalloc.dma_paddr +
6657 + ((caddr_t) sc->sc_dpfree - (caddr_t) sc->sc_dpring);
6658 + for (i = 0; i < re->re_dst_nsegs; i++) {
6659 + pd = sc->sc_dpfree;
6660 + KASSERT((pd->pd_flags&3) == 0 ||
6661 + (pd->pd_flags&3) == SAFE_PD_DONE,
6662 + ("bogus dest particle descriptor; flags %x",
6663 + pd->pd_flags));
6664 + if (++(sc->sc_dpfree) == sc->sc_dpringtop)
6665 + sc->sc_dpfree = sc->sc_dpring;
6666 + pd->pd_addr = re->re_dst_segs[i].ds_addr;
6667 + pd->pd_flags = SAFE_PD_READY;
6668 + }
6669 + cmd0 |= SAFE_SA_CMD0_OSCATTER;
6670 + } else {
6671 + /*
6672 + * No need for scatter, reference the operand directly.
6673 + */
6674 + re->re_desc.d_dst = re->re_dst_segs[0].ds_addr;
6675 + }
6676 + }
6677 +
6678 + /*
6679 + * All done with setup; fillin the SA command words
6680 + * and the packet engine descriptor. The operation
6681 + * is now ready for submission to the hardware.
6682 + */
6683 + sa->sa_cmd0 = cmd0 | SAFE_SA_CMD0_IPCI | SAFE_SA_CMD0_OPCI;
6684 + sa->sa_cmd1 = cmd1
6685 + | (coffset << SAFE_SA_CMD1_OFFSET_S)
6686 + | SAFE_SA_CMD1_SAREV1 /* Rev 1 SA data structure */
6687 + | SAFE_SA_CMD1_SRPCI
6688 + ;
6689 + /*
6690 + * NB: the order of writes is important here. In case the
6691 + * chip is scanning the ring because of an outstanding request
6692 + * it might nab this one too. In that case we need to make
6693 + * sure the setup is complete before we write the length
6694 + * field of the descriptor as it signals the descriptor is
6695 + * ready for processing.
6696 + */
6697 + re->re_desc.d_csr = SAFE_PE_CSR_READY | SAFE_PE_CSR_SAPCI;
6698 + if (maccrd)
6699 + re->re_desc.d_csr |= SAFE_PE_CSR_LOADSA | SAFE_PE_CSR_HASHFINAL;
6700 + wmb();
6701 + re->re_desc.d_len = oplen
6702 + | SAFE_PE_LEN_READY
6703 + | (bypass << SAFE_PE_LEN_BYPASS_S)
6704 + ;
6705 +
6706 + safestats.st_ipackets++;
6707 + safestats.st_ibytes += oplen;
6708 +
6709 + if (++(sc->sc_front) == sc->sc_ringtop)
6710 + sc->sc_front = sc->sc_ring;
6711 +
6712 + /* XXX honor batching */
6713 + safe_feed(sc, re);
6714 + spin_unlock_irqrestore(&sc->sc_ringmtx, flags);
6715 + return (0);
6716 +
6717 +errout:
6718 + if (re->re_src.map != re->re_dst.map)
6719 + pci_unmap_operand(sc, &re->re_dst);
6720 + if (re->re_src.map)
6721 + pci_unmap_operand(sc, &re->re_src);
6722 + spin_unlock_irqrestore(&sc->sc_ringmtx, flags);
6723 + if (err != ERESTART) {
6724 + crp->crp_etype = err;
6725 + crypto_done(crp);
6726 + } else {
6727 + sc->sc_needwakeup |= CRYPTO_SYMQ;
6728 + }
6729 + return (err);
6730 +}
6731 +
6732 +static void
6733 +safe_callback(struct safe_softc *sc, struct safe_ringentry *re)
6734 +{
6735 + struct cryptop *crp = (struct cryptop *)re->re_crp;
6736 + struct cryptodesc *crd;
6737 +
6738 + DPRINTF(("%s()\n", __FUNCTION__));
6739 +
6740 + safestats.st_opackets++;
6741 + safestats.st_obytes += re->re_dst.mapsize;
6742 +
6743 + if (re->re_desc.d_csr & SAFE_PE_CSR_STATUS) {
6744 + device_printf(sc->sc_dev, "csr 0x%x cmd0 0x%x cmd1 0x%x\n",
6745 + re->re_desc.d_csr,
6746 + re->re_sa.sa_cmd0, re->re_sa.sa_cmd1);
6747 + safestats.st_peoperr++;
6748 + crp->crp_etype = EIO; /* something more meaningful? */
6749 + }
6750 +
6751 + if (re->re_dst.map != NULL && re->re_dst.map != re->re_src.map)
6752 + pci_unmap_operand(sc, &re->re_dst);
6753 + pci_unmap_operand(sc, &re->re_src);
6754 +
6755 + /*
6756 + * If result was written to a differet mbuf chain, swap
6757 + * it in as the return value and reclaim the original.
6758 + */
6759 + if ((crp->crp_flags & CRYPTO_F_SKBUF) && re->re_src_skb != re->re_dst_skb) {
6760 + device_printf(sc->sc_dev, "no CRYPTO_F_SKBUF swapping support\n");
6761 + /* kfree_skb(skb) */
6762 + /* crp->crp_buf = (caddr_t)re->re_dst_skb */
6763 + return;
6764 + }
6765 +
6766 + if (re->re_flags & SAFE_QFLAGS_COPYOUTIV) {
6767 + /* copy out IV for future use */
6768 + for (crd = crp->crp_desc; crd; crd = crd->crd_next) {
6769 + int i;
6770 + int ivsize;
6771 +
6772 + if (crd->crd_alg == CRYPTO_DES_CBC ||
6773 + crd->crd_alg == CRYPTO_3DES_CBC) {
6774 + ivsize = 2*sizeof(u_int32_t);
6775 + } else if (crd->crd_alg == CRYPTO_AES_CBC) {
6776 + ivsize = 4*sizeof(u_int32_t);
6777 + } else
6778 + continue;
6779 + crypto_copydata(crp->crp_flags, crp->crp_buf,
6780 + crd->crd_skip + crd->crd_len - ivsize, ivsize,
6781 + (caddr_t)sc->sc_sessions[re->re_sesn].ses_iv);
6782 + for (i = 0;
6783 + i < ivsize/sizeof(sc->sc_sessions[re->re_sesn].ses_iv[0]);
6784 + i++)
6785 + sc->sc_sessions[re->re_sesn].ses_iv[i] =
6786 + cpu_to_le32(sc->sc_sessions[re->re_sesn].ses_iv[i]);
6787 + break;
6788 + }
6789 + }
6790 +
6791 + if (re->re_flags & SAFE_QFLAGS_COPYOUTICV) {
6792 + /* copy out ICV result */
6793 + for (crd = crp->crp_desc; crd; crd = crd->crd_next) {
6794 + if (!(crd->crd_alg == CRYPTO_MD5_HMAC ||
6795 + crd->crd_alg == CRYPTO_SHA1_HMAC ||
6796 + crd->crd_alg == CRYPTO_NULL_HMAC))
6797 + continue;
6798 + if (crd->crd_alg == CRYPTO_SHA1_HMAC) {
6799 + /*
6800 + * SHA-1 ICV's are byte-swapped; fix 'em up
6801 + * before copy them to their destination.
6802 + */
6803 + re->re_sastate.sa_saved_indigest[0] =
6804 + cpu_to_be32(re->re_sastate.sa_saved_indigest[0]);
6805 + re->re_sastate.sa_saved_indigest[1] =
6806 + cpu_to_be32(re->re_sastate.sa_saved_indigest[1]);
6807 + re->re_sastate.sa_saved_indigest[2] =
6808 + cpu_to_be32(re->re_sastate.sa_saved_indigest[2]);
6809 + } else {
6810 + re->re_sastate.sa_saved_indigest[0] =
6811 + cpu_to_le32(re->re_sastate.sa_saved_indigest[0]);
6812 + re->re_sastate.sa_saved_indigest[1] =
6813 + cpu_to_le32(re->re_sastate.sa_saved_indigest[1]);
6814 + re->re_sastate.sa_saved_indigest[2] =
6815 + cpu_to_le32(re->re_sastate.sa_saved_indigest[2]);
6816 + }
6817 + crypto_copyback(crp->crp_flags, crp->crp_buf,
6818 + crd->crd_inject,
6819 + sc->sc_sessions[re->re_sesn].ses_mlen,
6820 + (caddr_t)re->re_sastate.sa_saved_indigest);
6821 + break;
6822 + }
6823 + }
6824 + crypto_done(crp);
6825 +}
6826 +
6827 +
6828 +#if defined(CONFIG_OCF_RANDOMHARVEST) && !defined(SAFE_NO_RNG)
6829 +#define SAFE_RNG_MAXWAIT 1000
6830 +
6831 +static void
6832 +safe_rng_init(struct safe_softc *sc)
6833 +{
6834 + u_int32_t w, v;
6835 + int i;
6836 +
6837 + DPRINTF(("%s()\n", __FUNCTION__));
6838 +
6839 + WRITE_REG(sc, SAFE_RNG_CTRL, 0);
6840 + /* use default value according to the manual */
6841 + WRITE_REG(sc, SAFE_RNG_CNFG, 0x834); /* magic from SafeNet */
6842 + WRITE_REG(sc, SAFE_RNG_ALM_CNT, 0);
6843 +
6844 + /*
6845 + * There is a bug in rev 1.0 of the 1140 that when the RNG
6846 + * is brought out of reset the ready status flag does not
6847 + * work until the RNG has finished its internal initialization.
6848 + *
6849 + * So in order to determine the device is through its
6850 + * initialization we must read the data register, using the
6851 + * status reg in the read in case it is initialized. Then read
6852 + * the data register until it changes from the first read.
6853 + * Once it changes read the data register until it changes
6854 + * again. At this time the RNG is considered initialized.
6855 + * This could take between 750ms - 1000ms in time.
6856 + */
6857 + i = 0;
6858 + w = READ_REG(sc, SAFE_RNG_OUT);
6859 + do {
6860 + v = READ_REG(sc, SAFE_RNG_OUT);
6861 + if (v != w) {
6862 + w = v;
6863 + break;
6864 + }
6865 + DELAY(10);
6866 + } while (++i < SAFE_RNG_MAXWAIT);
6867 +
6868 + /* Wait Until data changes again */
6869 + i = 0;
6870 + do {
6871 + v = READ_REG(sc, SAFE_RNG_OUT);
6872 + if (v != w)
6873 + break;
6874 + DELAY(10);
6875 + } while (++i < SAFE_RNG_MAXWAIT);
6876 +}
6877 +
6878 +static __inline void
6879 +safe_rng_disable_short_cycle(struct safe_softc *sc)
6880 +{
6881 + DPRINTF(("%s()\n", __FUNCTION__));
6882 +
6883 + WRITE_REG(sc, SAFE_RNG_CTRL,
6884 + READ_REG(sc, SAFE_RNG_CTRL) &~ SAFE_RNG_CTRL_SHORTEN);
6885 +}
6886 +
6887 +static __inline void
6888 +safe_rng_enable_short_cycle(struct safe_softc *sc)
6889 +{
6890 + DPRINTF(("%s()\n", __FUNCTION__));
6891 +
6892 + WRITE_REG(sc, SAFE_RNG_CTRL,
6893 + READ_REG(sc, SAFE_RNG_CTRL) | SAFE_RNG_CTRL_SHORTEN);
6894 +}
6895 +
6896 +static __inline u_int32_t
6897 +safe_rng_read(struct safe_softc *sc)
6898 +{
6899 + int i;
6900 +
6901 + i = 0;
6902 + while (READ_REG(sc, SAFE_RNG_STAT) != 0 && ++i < SAFE_RNG_MAXWAIT)
6903 + ;
6904 + return READ_REG(sc, SAFE_RNG_OUT);
6905 +}
6906 +
6907 +static int
6908 +safe_read_random(void *arg, u_int32_t *buf, int maxwords)
6909 +{
6910 + struct safe_softc *sc = (struct safe_softc *) arg;
6911 + int i, rc;
6912 +
6913 + DPRINTF(("%s()\n", __FUNCTION__));
6914 +
6915 + safestats.st_rng++;
6916 + /*
6917 + * Fetch the next block of data.
6918 + */
6919 + if (maxwords > safe_rngbufsize)
6920 + maxwords = safe_rngbufsize;
6921 + if (maxwords > SAFE_RNG_MAXBUFSIZ)
6922 + maxwords = SAFE_RNG_MAXBUFSIZ;
6923 +retry:
6924 + /* read as much as we can */
6925 + for (rc = 0; rc < maxwords; rc++) {
6926 + if (READ_REG(sc, SAFE_RNG_STAT) != 0)
6927 + break;
6928 + buf[rc] = READ_REG(sc, SAFE_RNG_OUT);
6929 + }
6930 + if (rc == 0)
6931 + return 0;
6932 + /*
6933 + * Check the comparator alarm count and reset the h/w if
6934 + * it exceeds our threshold. This guards against the
6935 + * hardware oscillators resonating with external signals.
6936 + */
6937 + if (READ_REG(sc, SAFE_RNG_ALM_CNT) > safe_rngmaxalarm) {
6938 + u_int32_t freq_inc, w;
6939 +
6940 + DPRINTF(("%s: alarm count %u exceeds threshold %u\n", __func__,
6941 + (unsigned)READ_REG(sc, SAFE_RNG_ALM_CNT), safe_rngmaxalarm));
6942 + safestats.st_rngalarm++;
6943 + safe_rng_enable_short_cycle(sc);
6944 + freq_inc = 18;
6945 + for (i = 0; i < 64; i++) {
6946 + w = READ_REG(sc, SAFE_RNG_CNFG);
6947 + freq_inc = ((w + freq_inc) & 0x3fL);
6948 + w = ((w & ~0x3fL) | freq_inc);
6949 + WRITE_REG(sc, SAFE_RNG_CNFG, w);
6950 +
6951 + WRITE_REG(sc, SAFE_RNG_ALM_CNT, 0);
6952 +
6953 + (void) safe_rng_read(sc);
6954 + DELAY(25);
6955 +
6956 + if (READ_REG(sc, SAFE_RNG_ALM_CNT) == 0) {
6957 + safe_rng_disable_short_cycle(sc);
6958 + goto retry;
6959 + }
6960 + freq_inc = 1;
6961 + }
6962 + safe_rng_disable_short_cycle(sc);
6963 + } else
6964 + WRITE_REG(sc, SAFE_RNG_ALM_CNT, 0);
6965 +
6966 + return(rc);
6967 +}
6968 +#endif /* defined(CONFIG_OCF_RANDOMHARVEST) && !defined(SAFE_NO_RNG) */
6969 +
6970 +
6971 +/*
6972 + * Resets the board. Values in the regesters are left as is
6973 + * from the reset (i.e. initial values are assigned elsewhere).
6974 + */
6975 +static void
6976 +safe_reset_board(struct safe_softc *sc)
6977 +{
6978 + u_int32_t v;
6979 + /*
6980 + * Reset the device. The manual says no delay
6981 + * is needed between marking and clearing reset.
6982 + */
6983 + DPRINTF(("%s()\n", __FUNCTION__));
6984 +
6985 + v = READ_REG(sc, SAFE_PE_DMACFG) &~
6986 + (SAFE_PE_DMACFG_PERESET | SAFE_PE_DMACFG_PDRRESET |
6987 + SAFE_PE_DMACFG_SGRESET);
6988 + WRITE_REG(sc, SAFE_PE_DMACFG, v
6989 + | SAFE_PE_DMACFG_PERESET
6990 + | SAFE_PE_DMACFG_PDRRESET
6991 + | SAFE_PE_DMACFG_SGRESET);
6992 + WRITE_REG(sc, SAFE_PE_DMACFG, v);
6993 +}
6994 +
6995 +/*
6996 + * Initialize registers we need to touch only once.
6997 + */
6998 +static void
6999 +safe_init_board(struct safe_softc *sc)
7000 +{
7001 + u_int32_t v, dwords;
7002 +
7003 + DPRINTF(("%s()\n", __FUNCTION__));
7004 +
7005 + v = READ_REG(sc, SAFE_PE_DMACFG);
7006 + v &=~ ( SAFE_PE_DMACFG_PEMODE
7007 + | SAFE_PE_DMACFG_FSENA /* failsafe enable */
7008 + | SAFE_PE_DMACFG_GPRPCI /* gather ring on PCI */
7009 + | SAFE_PE_DMACFG_SPRPCI /* scatter ring on PCI */
7010 + | SAFE_PE_DMACFG_ESDESC /* endian-swap descriptors */
7011 + | SAFE_PE_DMACFG_ESPDESC /* endian-swap part. desc's */
7012 + | SAFE_PE_DMACFG_ESSA /* endian-swap SA's */
7013 + | SAFE_PE_DMACFG_ESPACKET /* swap the packet data */
7014 + );
7015 + v |= SAFE_PE_DMACFG_FSENA /* failsafe enable */
7016 + | SAFE_PE_DMACFG_GPRPCI /* gather ring on PCI */
7017 + | SAFE_PE_DMACFG_SPRPCI /* scatter ring on PCI */
7018 + | SAFE_PE_DMACFG_ESDESC /* endian-swap descriptors */
7019 + | SAFE_PE_DMACFG_ESPDESC /* endian-swap part. desc's */
7020 + | SAFE_PE_DMACFG_ESSA /* endian-swap SA's */
7021 +#if 0
7022 + | SAFE_PE_DMACFG_ESPACKET /* swap the packet data */
7023 +#endif
7024 + ;
7025 + WRITE_REG(sc, SAFE_PE_DMACFG, v);
7026 +
7027 +#ifdef __BIG_ENDIAN
7028 + /* tell the safenet that we are 4321 and not 1234 */
7029 + WRITE_REG(sc, SAFE_ENDIAN, 0xe4e41b1b);
7030 +#endif
7031 +
7032 + if (sc->sc_chiprev == SAFE_REV(1,0)) {
7033 + /*
7034 + * Avoid large PCI DMA transfers. Rev 1.0 has a bug where
7035 + * "target mode transfers" done while the chip is DMA'ing
7036 + * >1020 bytes cause the hardware to lockup. To avoid this
7037 + * we reduce the max PCI transfer size and use small source
7038 + * particle descriptors (<= 256 bytes).
7039 + */
7040 + WRITE_REG(sc, SAFE_DMA_CFG, 256);
7041 + device_printf(sc->sc_dev,
7042 + "Reduce max DMA size to %u words for rev %u.%u WAR\n",
7043 + (unsigned) ((READ_REG(sc, SAFE_DMA_CFG)>>2) & 0xff),
7044 + (unsigned) SAFE_REV_MAJ(sc->sc_chiprev),
7045 + (unsigned) SAFE_REV_MIN(sc->sc_chiprev));
7046 + sc->sc_max_dsize = 256;
7047 + } else {
7048 + sc->sc_max_dsize = SAFE_MAX_DSIZE;
7049 + }
7050 +
7051 + /* NB: operands+results are overlaid */
7052 + WRITE_REG(sc, SAFE_PE_PDRBASE, sc->sc_ringalloc.dma_paddr);
7053 + WRITE_REG(sc, SAFE_PE_RDRBASE, sc->sc_ringalloc.dma_paddr);
7054 + /*
7055 + * Configure ring entry size and number of items in the ring.
7056 + */
7057 + KASSERT((sizeof(struct safe_ringentry) % sizeof(u_int32_t)) == 0,
7058 + ("PE ring entry not 32-bit aligned!"));
7059 + dwords = sizeof(struct safe_ringentry) / sizeof(u_int32_t);
7060 + WRITE_REG(sc, SAFE_PE_RINGCFG,
7061 + (dwords << SAFE_PE_RINGCFG_OFFSET_S) | SAFE_MAX_NQUEUE);
7062 + WRITE_REG(sc, SAFE_PE_RINGPOLL, 0); /* disable polling */
7063 +
7064 + WRITE_REG(sc, SAFE_PE_GRNGBASE, sc->sc_spalloc.dma_paddr);
7065 + WRITE_REG(sc, SAFE_PE_SRNGBASE, sc->sc_dpalloc.dma_paddr);
7066 + WRITE_REG(sc, SAFE_PE_PARTSIZE,
7067 + (SAFE_TOTAL_DPART<<16) | SAFE_TOTAL_SPART);
7068 + /*
7069 + * NB: destination particles are fixed size. We use
7070 + * an mbuf cluster and require all results go to
7071 + * clusters or smaller.
7072 + */
7073 + WRITE_REG(sc, SAFE_PE_PARTCFG, sc->sc_max_dsize);
7074 +
7075 + /* it's now safe to enable PE mode, do it */
7076 + WRITE_REG(sc, SAFE_PE_DMACFG, v | SAFE_PE_DMACFG_PEMODE);
7077 +
7078 + /*
7079 + * Configure hardware to use level-triggered interrupts and
7080 + * to interrupt after each descriptor is processed.
7081 + */
7082 + WRITE_REG(sc, SAFE_HI_CFG, SAFE_HI_CFG_LEVEL);
7083 + WRITE_REG(sc, SAFE_HI_CLR, 0xffffffff);
7084 + WRITE_REG(sc, SAFE_HI_DESC_CNT, 1);
7085 + WRITE_REG(sc, SAFE_HI_MASK, SAFE_INT_PE_DDONE | SAFE_INT_PE_ERROR);
7086 +}
7087 +
7088 +
7089 +/*
7090 + * Clean up after a chip crash.
7091 + * It is assumed that the caller in splimp()
7092 + */
7093 +static void
7094 +safe_cleanchip(struct safe_softc *sc)
7095 +{
7096 + DPRINTF(("%s()\n", __FUNCTION__));
7097 +
7098 + if (sc->sc_nqchip != 0) {
7099 + struct safe_ringentry *re = sc->sc_back;
7100 +
7101 + while (re != sc->sc_front) {
7102 + if (re->re_desc.d_csr != 0)
7103 + safe_free_entry(sc, re);
7104 + if (++re == sc->sc_ringtop)
7105 + re = sc->sc_ring;
7106 + }
7107 + sc->sc_back = re;
7108 + sc->sc_nqchip = 0;
7109 + }
7110 +}
7111 +
7112 +/*
7113 + * free a safe_q
7114 + * It is assumed that the caller is within splimp().
7115 + */
7116 +static int
7117 +safe_free_entry(struct safe_softc *sc, struct safe_ringentry *re)
7118 +{
7119 + struct cryptop *crp;
7120 +
7121 + DPRINTF(("%s()\n", __FUNCTION__));
7122 +
7123 + /*
7124 + * Free header MCR
7125 + */
7126 + if ((re->re_dst_skb != NULL) && (re->re_src_skb != re->re_dst_skb))
7127 +#ifdef NOTYET
7128 + m_freem(re->re_dst_m);
7129 +#else
7130 + printk("%s,%d: SKB not supported\n", __FILE__, __LINE__);
7131 +#endif
7132 +
7133 + crp = (struct cryptop *)re->re_crp;
7134 +
7135 + re->re_desc.d_csr = 0;
7136 +
7137 + crp->crp_etype = EFAULT;
7138 + crypto_done(crp);
7139 + return(0);
7140 +}
7141 +
7142 +/*
7143 + * Routine to reset the chip and clean up.
7144 + * It is assumed that the caller is in splimp()
7145 + */
7146 +static void
7147 +safe_totalreset(struct safe_softc *sc)
7148 +{
7149 + DPRINTF(("%s()\n", __FUNCTION__));
7150 +
7151 + safe_reset_board(sc);
7152 + safe_init_board(sc);
7153 + safe_cleanchip(sc);
7154 +}
7155 +
7156 +/*
7157 + * Is the operand suitable aligned for direct DMA. Each
7158 + * segment must be aligned on a 32-bit boundary and all
7159 + * but the last segment must be a multiple of 4 bytes.
7160 + */
7161 +static int
7162 +safe_dmamap_aligned(struct safe_softc *sc, const struct safe_operand *op)
7163 +{
7164 + int i;
7165 +
7166 + DPRINTF(("%s()\n", __FUNCTION__));
7167 +
7168 + for (i = 0; i < op->nsegs; i++) {
7169 + if (op->segs[i].ds_addr & 3)
7170 + return (0);
7171 + if (i != (op->nsegs - 1) && (op->segs[i].ds_len & 3))
7172 + return (0);
7173 + }
7174 + return (1);
7175 +}
7176 +
7177 +/*
7178 + * Is the operand suitable for direct DMA as the destination
7179 + * of an operation. The hardware requires that each ``particle''
7180 + * but the last in an operation result have the same size. We
7181 + * fix that size at SAFE_MAX_DSIZE bytes. This routine returns
7182 + * 0 if some segment is not a multiple of of this size, 1 if all
7183 + * segments are exactly this size, or 2 if segments are at worst
7184 + * a multple of this size.
7185 + */
7186 +static int
7187 +safe_dmamap_uniform(struct safe_softc *sc, const struct safe_operand *op)
7188 +{
7189 + int result = 1;
7190 +
7191 + DPRINTF(("%s()\n", __FUNCTION__));
7192 +
7193 + if (op->nsegs > 0) {
7194 + int i;
7195 +
7196 + for (i = 0; i < op->nsegs-1; i++) {
7197 + if (op->segs[i].ds_len % sc->sc_max_dsize)
7198 + return (0);
7199 + if (op->segs[i].ds_len != sc->sc_max_dsize)
7200 + result = 2;
7201 + }
7202 + }
7203 + return (result);
7204 +}
7205 +
7206 +static int
7207 +safe_kprocess(device_t dev, struct cryptkop *krp, int hint)
7208 +{
7209 + struct safe_softc *sc = device_get_softc(dev);
7210 + struct safe_pkq *q;
7211 + unsigned long flags;
7212 +
7213 + DPRINTF(("%s()\n", __FUNCTION__));
7214 +
7215 + if (sc == NULL) {
7216 + krp->krp_status = EINVAL;
7217 + goto err;
7218 + }
7219 +
7220 + if (krp->krp_op != CRK_MOD_EXP) {
7221 + krp->krp_status = EOPNOTSUPP;
7222 + goto err;
7223 + }
7224 +
7225 + q = (struct safe_pkq *) kmalloc(sizeof(*q), GFP_KERNEL);
7226 + if (q == NULL) {
7227 + krp->krp_status = ENOMEM;
7228 + goto err;
7229 + }
7230 + memset(q, 0, sizeof(*q));
7231 + q->pkq_krp = krp;
7232 + INIT_LIST_HEAD(&q->pkq_list);
7233 +
7234 + spin_lock_irqsave(&sc->sc_pkmtx, flags);
7235 + list_add_tail(&q->pkq_list, &sc->sc_pkq);
7236 + safe_kfeed(sc);
7237 + spin_unlock_irqrestore(&sc->sc_pkmtx, flags);
7238 + return (0);
7239 +
7240 +err:
7241 + crypto_kdone(krp);
7242 + return (0);
7243 +}
7244 +
7245 +#define SAFE_CRK_PARAM_BASE 0
7246 +#define SAFE_CRK_PARAM_EXP 1
7247 +#define SAFE_CRK_PARAM_MOD 2
7248 +
7249 +static int
7250 +safe_kstart(struct safe_softc *sc)
7251 +{
7252 + struct cryptkop *krp = sc->sc_pkq_cur->pkq_krp;
7253 + int exp_bits, mod_bits, base_bits;
7254 + u_int32_t op, a_off, b_off, c_off, d_off;
7255 +
7256 + DPRINTF(("%s()\n", __FUNCTION__));
7257 +
7258 + if (krp->krp_iparams < 3 || krp->krp_oparams != 1) {
7259 + krp->krp_status = EINVAL;
7260 + return (1);
7261 + }
7262 +
7263 + base_bits = safe_ksigbits(sc, &krp->krp_param[SAFE_CRK_PARAM_BASE]);
7264 + if (base_bits > 2048)
7265 + goto too_big;
7266 + if (base_bits <= 0) /* 5. base not zero */
7267 + goto too_small;
7268 +
7269 + exp_bits = safe_ksigbits(sc, &krp->krp_param[SAFE_CRK_PARAM_EXP]);
7270 + if (exp_bits > 2048)
7271 + goto too_big;
7272 + if (exp_bits <= 0) /* 1. exponent word length > 0 */
7273 + goto too_small; /* 4. exponent not zero */
7274 +
7275 + mod_bits = safe_ksigbits(sc, &krp->krp_param[SAFE_CRK_PARAM_MOD]);
7276 + if (mod_bits > 2048)
7277 + goto too_big;
7278 + if (mod_bits <= 32) /* 2. modulus word length > 1 */
7279 + goto too_small; /* 8. MSW of modulus != zero */
7280 + if (mod_bits < exp_bits) /* 3 modulus len >= exponent len */
7281 + goto too_small;
7282 + if ((krp->krp_param[SAFE_CRK_PARAM_MOD].crp_p[0] & 1) == 0)
7283 + goto bad_domain; /* 6. modulus is odd */
7284 + if (mod_bits > krp->krp_param[krp->krp_iparams].crp_nbits)
7285 + goto too_small; /* make sure result will fit */
7286 +
7287 + /* 7. modulus > base */
7288 + if (mod_bits < base_bits)
7289 + goto too_small;
7290 + if (mod_bits == base_bits) {
7291 + u_int8_t *basep, *modp;
7292 + int i;
7293 +
7294 + basep = krp->krp_param[SAFE_CRK_PARAM_BASE].crp_p +
7295 + ((base_bits + 7) / 8) - 1;
7296 + modp = krp->krp_param[SAFE_CRK_PARAM_MOD].crp_p +
7297 + ((mod_bits + 7) / 8) - 1;
7298 +
7299 + for (i = 0; i < (mod_bits + 7) / 8; i++, basep--, modp--) {
7300 + if (*modp < *basep)
7301 + goto too_small;
7302 + if (*modp > *basep)
7303 + break;
7304 + }
7305 + }
7306 +
7307 + /* And on the 9th step, he rested. */
7308 +
7309 + WRITE_REG(sc, SAFE_PK_A_LEN, (exp_bits + 31) / 32);
7310 + WRITE_REG(sc, SAFE_PK_B_LEN, (mod_bits + 31) / 32);
7311 + if (mod_bits > 1024) {
7312 + op = SAFE_PK_FUNC_EXP4;
7313 + a_off = 0x000;
7314 + b_off = 0x100;
7315 + c_off = 0x200;
7316 + d_off = 0x300;
7317 + } else {
7318 + op = SAFE_PK_FUNC_EXP16;
7319 + a_off = 0x000;
7320 + b_off = 0x080;
7321 + c_off = 0x100;
7322 + d_off = 0x180;
7323 + }
7324 + sc->sc_pk_reslen = b_off - a_off;
7325 + sc->sc_pk_resoff = d_off;
7326 +
7327 + /* A is exponent, B is modulus, C is base, D is result */
7328 + safe_kload_reg(sc, a_off, b_off - a_off,
7329 + &krp->krp_param[SAFE_CRK_PARAM_EXP]);
7330 + WRITE_REG(sc, SAFE_PK_A_ADDR, a_off >> 2);
7331 + safe_kload_reg(sc, b_off, b_off - a_off,
7332 + &krp->krp_param[SAFE_CRK_PARAM_MOD]);
7333 + WRITE_REG(sc, SAFE_PK_B_ADDR, b_off >> 2);
7334 + safe_kload_reg(sc, c_off, b_off - a_off,
7335 + &krp->krp_param[SAFE_CRK_PARAM_BASE]);
7336 + WRITE_REG(sc, SAFE_PK_C_ADDR, c_off >> 2);
7337 + WRITE_REG(sc, SAFE_PK_D_ADDR, d_off >> 2);
7338 +
7339 + WRITE_REG(sc, SAFE_PK_FUNC, op | SAFE_PK_FUNC_RUN);
7340 +
7341 + return (0);
7342 +
7343 +too_big:
7344 + krp->krp_status = E2BIG;
7345 + return (1);
7346 +too_small:
7347 + krp->krp_status = ERANGE;
7348 + return (1);
7349 +bad_domain:
7350 + krp->krp_status = EDOM;
7351 + return (1);
7352 +}
7353 +
7354 +static int
7355 +safe_ksigbits(struct safe_softc *sc, struct crparam *cr)
7356 +{
7357 + u_int plen = (cr->crp_nbits + 7) / 8;
7358 + int i, sig = plen * 8;
7359 + u_int8_t c, *p = cr->crp_p;
7360 +
7361 + DPRINTF(("%s()\n", __FUNCTION__));
7362 +
7363 + for (i = plen - 1; i >= 0; i--) {
7364 + c = p[i];
7365 + if (c != 0) {
7366 + while ((c & 0x80) == 0) {
7367 + sig--;
7368 + c <<= 1;
7369 + }
7370 + break;
7371 + }
7372 + sig -= 8;
7373 + }
7374 + return (sig);
7375 +}
7376 +
7377 +static void
7378 +safe_kfeed(struct safe_softc *sc)
7379 +{
7380 + struct safe_pkq *q, *tmp;
7381 +
7382 + DPRINTF(("%s()\n", __FUNCTION__));
7383 +
7384 + if (list_empty(&sc->sc_pkq) && sc->sc_pkq_cur == NULL)
7385 + return;
7386 + if (sc->sc_pkq_cur != NULL)
7387 + return;
7388 + list_for_each_entry_safe(q, tmp, &sc->sc_pkq, pkq_list) {
7389 + sc->sc_pkq_cur = q;
7390 + list_del(&q->pkq_list);
7391 + if (safe_kstart(sc) != 0) {
7392 + crypto_kdone(q->pkq_krp);
7393 + kfree(q);
7394 + sc->sc_pkq_cur = NULL;
7395 + } else {
7396 + /* op started, start polling */
7397 + mod_timer(&sc->sc_pkto, jiffies + 1);
7398 + break;
7399 + }
7400 + }
7401 +}
7402 +
7403 +static void
7404 +safe_kpoll(unsigned long arg)
7405 +{
7406 + struct safe_softc *sc = NULL;
7407 + struct safe_pkq *q;
7408 + struct crparam *res;
7409 + int i;
7410 + u_int32_t buf[64];
7411 + unsigned long flags;
7412 +
7413 + DPRINTF(("%s()\n", __FUNCTION__));
7414 +
7415 + if (arg >= SAFE_MAX_CHIPS)
7416 + return;
7417 + sc = safe_chip_idx[arg];
7418 + if (!sc) {
7419 + DPRINTF(("%s() - bad callback\n", __FUNCTION__));
7420 + return;
7421 + }
7422 +
7423 + spin_lock_irqsave(&sc->sc_pkmtx, flags);
7424 + if (sc->sc_pkq_cur == NULL)
7425 + goto out;
7426 + if (READ_REG(sc, SAFE_PK_FUNC) & SAFE_PK_FUNC_RUN) {
7427 + /* still running, check back later */
7428 + mod_timer(&sc->sc_pkto, jiffies + 1);
7429 + goto out;
7430 + }
7431 +
7432 + q = sc->sc_pkq_cur;
7433 + res = &q->pkq_krp->krp_param[q->pkq_krp->krp_iparams];
7434 + bzero(buf, sizeof(buf));
7435 + bzero(res->crp_p, (res->crp_nbits + 7) / 8);
7436 + for (i = 0; i < sc->sc_pk_reslen >> 2; i++)
7437 + buf[i] = le32_to_cpu(READ_REG(sc, SAFE_PK_RAM_START +
7438 + sc->sc_pk_resoff + (i << 2)));
7439 + bcopy(buf, res->crp_p, (res->crp_nbits + 7) / 8);
7440 + /*
7441 + * reduce the bits that need copying if possible
7442 + */
7443 + res->crp_nbits = min(res->crp_nbits,sc->sc_pk_reslen * 8);
7444 + res->crp_nbits = safe_ksigbits(sc, res);
7445 +
7446 + for (i = SAFE_PK_RAM_START; i < SAFE_PK_RAM_END; i += 4)
7447 + WRITE_REG(sc, i, 0);
7448 +
7449 + crypto_kdone(q->pkq_krp);
7450 + kfree(q);
7451 + sc->sc_pkq_cur = NULL;
7452 +
7453 + safe_kfeed(sc);
7454 +out:
7455 + spin_unlock_irqrestore(&sc->sc_pkmtx, flags);
7456 +}
7457 +
7458 +static void
7459 +safe_kload_reg(struct safe_softc *sc, u_int32_t off, u_int32_t len,
7460 + struct crparam *n)
7461 +{
7462 + u_int32_t buf[64], i;
7463 +
7464 + DPRINTF(("%s()\n", __FUNCTION__));
7465 +
7466 + bzero(buf, sizeof(buf));
7467 + bcopy(n->crp_p, buf, (n->crp_nbits + 7) / 8);
7468 +
7469 + for (i = 0; i < len >> 2; i++)
7470 + WRITE_REG(sc, SAFE_PK_RAM_START + off + (i << 2),
7471 + cpu_to_le32(buf[i]));
7472 +}
7473 +
7474 +#ifdef SAFE_DEBUG
7475 +static void
7476 +safe_dump_dmastatus(struct safe_softc *sc, const char *tag)
7477 +{
7478 + printf("%s: ENDIAN 0x%x SRC 0x%x DST 0x%x STAT 0x%x\n"
7479 + , tag
7480 + , READ_REG(sc, SAFE_DMA_ENDIAN)
7481 + , READ_REG(sc, SAFE_DMA_SRCADDR)
7482 + , READ_REG(sc, SAFE_DMA_DSTADDR)
7483 + , READ_REG(sc, SAFE_DMA_STAT)
7484 + );
7485 +}
7486 +
7487 +static void
7488 +safe_dump_intrstate(struct safe_softc *sc, const char *tag)
7489 +{
7490 + printf("%s: HI_CFG 0x%x HI_MASK 0x%x HI_DESC_CNT 0x%x HU_STAT 0x%x HM_STAT 0x%x\n"
7491 + , tag
7492 + , READ_REG(sc, SAFE_HI_CFG)
7493 + , READ_REG(sc, SAFE_HI_MASK)
7494 + , READ_REG(sc, SAFE_HI_DESC_CNT)
7495 + , READ_REG(sc, SAFE_HU_STAT)
7496 + , READ_REG(sc, SAFE_HM_STAT)
7497 + );
7498 +}
7499 +
7500 +static void
7501 +safe_dump_ringstate(struct safe_softc *sc, const char *tag)
7502 +{
7503 + u_int32_t estat = READ_REG(sc, SAFE_PE_ERNGSTAT);
7504 +
7505 + /* NB: assume caller has lock on ring */
7506 + printf("%s: ERNGSTAT %x (next %u) back %lu front %lu\n",
7507 + tag,
7508 + estat, (estat >> SAFE_PE_ERNGSTAT_NEXT_S),
7509 + (unsigned long)(sc->sc_back - sc->sc_ring),
7510 + (unsigned long)(sc->sc_front - sc->sc_ring));
7511 +}
7512 +
7513 +static void
7514 +safe_dump_request(struct safe_softc *sc, const char* tag, struct safe_ringentry *re)
7515 +{
7516 + int ix, nsegs;
7517 +
7518 + ix = re - sc->sc_ring;
7519 + printf("%s: %p (%u): csr %x src %x dst %x sa %x len %x\n"
7520 + , tag
7521 + , re, ix
7522 + , re->re_desc.d_csr
7523 + , re->re_desc.d_src
7524 + , re->re_desc.d_dst
7525 + , re->re_desc.d_sa
7526 + , re->re_desc.d_len
7527 + );
7528 + if (re->re_src.nsegs > 1) {
7529 + ix = (re->re_desc.d_src - sc->sc_spalloc.dma_paddr) /
7530 + sizeof(struct safe_pdesc);
7531 + for (nsegs = re->re_src.nsegs; nsegs; nsegs--) {
7532 + printf(" spd[%u] %p: %p size %u flags %x"
7533 + , ix, &sc->sc_spring[ix]
7534 + , (caddr_t)(uintptr_t) sc->sc_spring[ix].pd_addr
7535 + , sc->sc_spring[ix].pd_size
7536 + , sc->sc_spring[ix].pd_flags
7537 + );
7538 + if (sc->sc_spring[ix].pd_size == 0)
7539 + printf(" (zero!)");
7540 + printf("\n");
7541 + if (++ix == SAFE_TOTAL_SPART)
7542 + ix = 0;
7543 + }
7544 + }
7545 + if (re->re_dst.nsegs > 1) {
7546 + ix = (re->re_desc.d_dst - sc->sc_dpalloc.dma_paddr) /
7547 + sizeof(struct safe_pdesc);
7548 + for (nsegs = re->re_dst.nsegs; nsegs; nsegs--) {
7549 + printf(" dpd[%u] %p: %p flags %x\n"
7550 + , ix, &sc->sc_dpring[ix]
7551 + , (caddr_t)(uintptr_t) sc->sc_dpring[ix].pd_addr
7552 + , sc->sc_dpring[ix].pd_flags
7553 + );
7554 + if (++ix == SAFE_TOTAL_DPART)
7555 + ix = 0;
7556 + }
7557 + }
7558 + printf("sa: cmd0 %08x cmd1 %08x staterec %x\n",
7559 + re->re_sa.sa_cmd0, re->re_sa.sa_cmd1, re->re_sa.sa_staterec);
7560 + printf("sa: key %x %x %x %x %x %x %x %x\n"
7561 + , re->re_sa.sa_key[0]
7562 + , re->re_sa.sa_key[1]
7563 + , re->re_sa.sa_key[2]
7564 + , re->re_sa.sa_key[3]
7565 + , re->re_sa.sa_key[4]
7566 + , re->re_sa.sa_key[5]
7567 + , re->re_sa.sa_key[6]
7568 + , re->re_sa.sa_key[7]
7569 + );
7570 + printf("sa: indigest %x %x %x %x %x\n"
7571 + , re->re_sa.sa_indigest[0]
7572 + , re->re_sa.sa_indigest[1]
7573 + , re->re_sa.sa_indigest[2]
7574 + , re->re_sa.sa_indigest[3]
7575 + , re->re_sa.sa_indigest[4]
7576 + );
7577 + printf("sa: outdigest %x %x %x %x %x\n"
7578 + , re->re_sa.sa_outdigest[0]
7579 + , re->re_sa.sa_outdigest[1]
7580 + , re->re_sa.sa_outdigest[2]
7581 + , re->re_sa.sa_outdigest[3]
7582 + , re->re_sa.sa_outdigest[4]
7583 + );
7584 + printf("sr: iv %x %x %x %x\n"
7585 + , re->re_sastate.sa_saved_iv[0]
7586 + , re->re_sastate.sa_saved_iv[1]
7587 + , re->re_sastate.sa_saved_iv[2]
7588 + , re->re_sastate.sa_saved_iv[3]
7589 + );
7590 + printf("sr: hashbc %u indigest %x %x %x %x %x\n"
7591 + , re->re_sastate.sa_saved_hashbc
7592 + , re->re_sastate.sa_saved_indigest[0]
7593 + , re->re_sastate.sa_saved_indigest[1]
7594 + , re->re_sastate.sa_saved_indigest[2]
7595 + , re->re_sastate.sa_saved_indigest[3]
7596 + , re->re_sastate.sa_saved_indigest[4]
7597 + );
7598 +}
7599 +
7600 +static void
7601 +safe_dump_ring(struct safe_softc *sc, const char *tag)
7602 +{
7603 + unsigned long flags;
7604 +
7605 + spin_lock_irqsave(&sc->sc_ringmtx, flags);
7606 + printf("\nSafeNet Ring State:\n");
7607 + safe_dump_intrstate(sc, tag);
7608 + safe_dump_dmastatus(sc, tag);
7609 + safe_dump_ringstate(sc, tag);
7610 + if (sc->sc_nqchip) {
7611 + struct safe_ringentry *re = sc->sc_back;
7612 + do {
7613 + safe_dump_request(sc, tag, re);
7614 + if (++re == sc->sc_ringtop)
7615 + re = sc->sc_ring;
7616 + } while (re != sc->sc_front);
7617 + }
7618 + spin_unlock_irqrestore(&sc->sc_ringmtx, flags);
7619 +}
7620 +#endif /* SAFE_DEBUG */
7621 +
7622 +
7623 +static int safe_probe(struct pci_dev *dev, const struct pci_device_id *ent)
7624 +{
7625 + struct safe_softc *sc = NULL;
7626 + u32 mem_start, mem_len, cmd;
7627 + int i, rc, devinfo;
7628 + dma_addr_t raddr;
7629 + static int num_chips = 0;
7630 +
7631 + DPRINTF(("%s()\n", __FUNCTION__));
7632 +
7633 + if (pci_enable_device(dev) < 0)
7634 + return(-ENODEV);
7635 +
7636 + if (!dev->irq) {
7637 + printk("safe: found device with no IRQ assigned. check BIOS settings!");
7638 + pci_disable_device(dev);
7639 + return(-ENODEV);
7640 + }
7641 +
7642 + if (pci_set_mwi(dev)) {
7643 + printk("safe: pci_set_mwi failed!");
7644 + return(-ENODEV);
7645 + }
7646 +
7647 + sc = (struct safe_softc *) kmalloc(sizeof(*sc), GFP_KERNEL);
7648 + if (!sc)
7649 + return(-ENOMEM);
7650 + memset(sc, 0, sizeof(*sc));
7651 +
7652 + softc_device_init(sc, "safe", num_chips, safe_methods);
7653 +
7654 + sc->sc_irq = -1;
7655 + sc->sc_cid = -1;
7656 + sc->sc_pcidev = dev;
7657 + if (num_chips < SAFE_MAX_CHIPS) {
7658 + safe_chip_idx[device_get_unit(sc->sc_dev)] = sc;
7659 + num_chips++;
7660 + }
7661 +
7662 + INIT_LIST_HEAD(&sc->sc_pkq);
7663 + spin_lock_init(&sc->sc_pkmtx);
7664 +
7665 + pci_set_drvdata(sc->sc_pcidev, sc);
7666 +
7667 + /* we read its hardware registers as memory */
7668 + mem_start = pci_resource_start(sc->sc_pcidev, 0);
7669 + mem_len = pci_resource_len(sc->sc_pcidev, 0);
7670 +
7671 + sc->sc_base_addr = (ocf_iomem_t) ioremap(mem_start, mem_len);
7672 + if (!sc->sc_base_addr) {
7673 + device_printf(sc->sc_dev, "failed to ioremap 0x%x-0x%x\n",
7674 + mem_start, mem_start + mem_len - 1);
7675 + goto out;
7676 + }
7677 +
7678 + /* fix up the bus size */
7679 + if (pci_set_dma_mask(sc->sc_pcidev, DMA_32BIT_MASK)) {
7680 + device_printf(sc->sc_dev, "No usable DMA configuration, aborting.\n");
7681 + goto out;
7682 + }
7683 + if (pci_set_consistent_dma_mask(sc->sc_pcidev, DMA_32BIT_MASK)) {
7684 + device_printf(sc->sc_dev, "No usable consistent DMA configuration, aborting.\n");
7685 + goto out;
7686 + }
7687 +
7688 + pci_set_master(sc->sc_pcidev);
7689 +
7690 + pci_read_config_dword(sc->sc_pcidev, PCI_COMMAND, &cmd);
7691 +
7692 + if (!(cmd & PCI_COMMAND_MEMORY)) {
7693 + device_printf(sc->sc_dev, "failed to enable memory mapping\n");
7694 + goto out;
7695 + }
7696 +
7697 + if (!(cmd & PCI_COMMAND_MASTER)) {
7698 + device_printf(sc->sc_dev, "failed to enable bus mastering\n");
7699 + goto out;
7700 + }
7701 +
7702 + rc = request_irq(dev->irq, safe_intr, IRQF_SHARED, "safe", sc);
7703 + if (rc) {
7704 + device_printf(sc->sc_dev, "failed to hook irq %d\n", sc->sc_irq);
7705 + goto out;
7706 + }
7707 + sc->sc_irq = dev->irq;
7708 +
7709 + sc->sc_chiprev = READ_REG(sc, SAFE_DEVINFO) &
7710 + (SAFE_DEVINFO_REV_MAJ | SAFE_DEVINFO_REV_MIN);
7711 +
7712 + /*
7713 + * Allocate packet engine descriptors.
7714 + */
7715 + sc->sc_ringalloc.dma_vaddr = pci_alloc_consistent(sc->sc_pcidev,
7716 + SAFE_MAX_NQUEUE * sizeof (struct safe_ringentry),
7717 + &sc->sc_ringalloc.dma_paddr);
7718 + if (!sc->sc_ringalloc.dma_vaddr) {
7719 + device_printf(sc->sc_dev, "cannot allocate PE descriptor ring\n");
7720 + goto out;
7721 + }
7722 +
7723 + /*
7724 + * Hookup the static portion of all our data structures.
7725 + */
7726 + sc->sc_ring = (struct safe_ringentry *) sc->sc_ringalloc.dma_vaddr;
7727 + sc->sc_ringtop = sc->sc_ring + SAFE_MAX_NQUEUE;
7728 + sc->sc_front = sc->sc_ring;
7729 + sc->sc_back = sc->sc_ring;
7730 + raddr = sc->sc_ringalloc.dma_paddr;
7731 + bzero(sc->sc_ring, SAFE_MAX_NQUEUE * sizeof(struct safe_ringentry));
7732 + for (i = 0; i < SAFE_MAX_NQUEUE; i++) {
7733 + struct safe_ringentry *re = &sc->sc_ring[i];
7734 +
7735 + re->re_desc.d_sa = raddr +
7736 + offsetof(struct safe_ringentry, re_sa);
7737 + re->re_sa.sa_staterec = raddr +
7738 + offsetof(struct safe_ringentry, re_sastate);
7739 +
7740 + raddr += sizeof (struct safe_ringentry);
7741 + }
7742 + spin_lock_init(&sc->sc_ringmtx);
7743 +
7744 + /*
7745 + * Allocate scatter and gather particle descriptors.
7746 + */
7747 + sc->sc_spalloc.dma_vaddr = pci_alloc_consistent(sc->sc_pcidev,
7748 + SAFE_TOTAL_SPART * sizeof (struct safe_pdesc),
7749 + &sc->sc_spalloc.dma_paddr);
7750 + if (!sc->sc_spalloc.dma_vaddr) {
7751 + device_printf(sc->sc_dev, "cannot allocate source particle descriptor ring\n");
7752 + goto out;
7753 + }
7754 + sc->sc_spring = (struct safe_pdesc *) sc->sc_spalloc.dma_vaddr;
7755 + sc->sc_springtop = sc->sc_spring + SAFE_TOTAL_SPART;
7756 + sc->sc_spfree = sc->sc_spring;
7757 + bzero(sc->sc_spring, SAFE_TOTAL_SPART * sizeof(struct safe_pdesc));
7758 +
7759 + sc->sc_dpalloc.dma_vaddr = pci_alloc_consistent(sc->sc_pcidev,
7760 + SAFE_TOTAL_DPART * sizeof (struct safe_pdesc),
7761 + &sc->sc_dpalloc.dma_paddr);
7762 + if (!sc->sc_dpalloc.dma_vaddr) {
7763 + device_printf(sc->sc_dev, "cannot allocate destination particle descriptor ring\n");
7764 + goto out;
7765 + }
7766 + sc->sc_dpring = (struct safe_pdesc *) sc->sc_dpalloc.dma_vaddr;
7767 + sc->sc_dpringtop = sc->sc_dpring + SAFE_TOTAL_DPART;
7768 + sc->sc_dpfree = sc->sc_dpring;
7769 + bzero(sc->sc_dpring, SAFE_TOTAL_DPART * sizeof(struct safe_pdesc));
7770 +
7771 + sc->sc_cid = crypto_get_driverid(softc_get_device(sc), CRYPTOCAP_F_HARDWARE);
7772 + if (sc->sc_cid < 0) {
7773 + device_printf(sc->sc_dev, "could not get crypto driver id\n");
7774 + goto out;
7775 + }
7776 +
7777 + printf("%s:", device_get_nameunit(sc->sc_dev));
7778 +
7779 + devinfo = READ_REG(sc, SAFE_DEVINFO);
7780 + if (devinfo & SAFE_DEVINFO_RNG) {
7781 + sc->sc_flags |= SAFE_FLAGS_RNG;
7782 + printf(" rng");
7783 + }
7784 + if (devinfo & SAFE_DEVINFO_PKEY) {
7785 + printf(" key");
7786 + sc->sc_flags |= SAFE_FLAGS_KEY;
7787 + crypto_kregister(sc->sc_cid, CRK_MOD_EXP, 0);
7788 +#if 0
7789 + crypto_kregister(sc->sc_cid, CRK_MOD_EXP_CRT, 0);
7790 +#endif
7791 + init_timer(&sc->sc_pkto);
7792 + sc->sc_pkto.function = safe_kpoll;
7793 + sc->sc_pkto.data = (unsigned long) device_get_unit(sc->sc_dev);
7794 + }
7795 + if (devinfo & SAFE_DEVINFO_DES) {
7796 + printf(" des/3des");
7797 + crypto_register(sc->sc_cid, CRYPTO_3DES_CBC, 0, 0);
7798 + crypto_register(sc->sc_cid, CRYPTO_DES_CBC, 0, 0);
7799 + }
7800 + if (devinfo & SAFE_DEVINFO_AES) {
7801 + printf(" aes");
7802 + crypto_register(sc->sc_cid, CRYPTO_AES_CBC, 0, 0);
7803 + }
7804 + if (devinfo & SAFE_DEVINFO_MD5) {
7805 + printf(" md5");
7806 + crypto_register(sc->sc_cid, CRYPTO_MD5_HMAC, 0, 0);
7807 + }
7808 + if (devinfo & SAFE_DEVINFO_SHA1) {
7809 + printf(" sha1");
7810 + crypto_register(sc->sc_cid, CRYPTO_SHA1_HMAC, 0, 0);
7811 + }
7812 + printf(" null");
7813 + crypto_register(sc->sc_cid, CRYPTO_NULL_CBC, 0, 0);
7814 + crypto_register(sc->sc_cid, CRYPTO_NULL_HMAC, 0, 0);
7815 + /* XXX other supported algorithms */
7816 + printf("\n");
7817 +
7818 + safe_reset_board(sc); /* reset h/w */
7819 + safe_init_board(sc); /* init h/w */
7820 +
7821 +#if defined(CONFIG_OCF_RANDOMHARVEST) && !defined(SAFE_NO_RNG)
7822 + if (sc->sc_flags & SAFE_FLAGS_RNG) {
7823 + safe_rng_init(sc);
7824 + crypto_rregister(sc->sc_cid, safe_read_random, sc);
7825 + }
7826 +#endif /* SAFE_NO_RNG */
7827 +
7828 + return (0);
7829 +
7830 +out:
7831 + if (sc->sc_cid >= 0)
7832 + crypto_unregister_all(sc->sc_cid);
7833 + if (sc->sc_irq != -1)
7834 + free_irq(sc->sc_irq, sc);
7835 + if (sc->sc_ringalloc.dma_vaddr)
7836 + pci_free_consistent(sc->sc_pcidev,
7837 + SAFE_MAX_NQUEUE * sizeof (struct safe_ringentry),
7838 + sc->sc_ringalloc.dma_vaddr, sc->sc_ringalloc.dma_paddr);
7839 + if (sc->sc_spalloc.dma_vaddr)
7840 + pci_free_consistent(sc->sc_pcidev,
7841 + SAFE_TOTAL_DPART * sizeof (struct safe_pdesc),
7842 + sc->sc_spalloc.dma_vaddr, sc->sc_spalloc.dma_paddr);
7843 + if (sc->sc_dpalloc.dma_vaddr)
7844 + pci_free_consistent(sc->sc_pcidev,
7845 + SAFE_TOTAL_DPART * sizeof (struct safe_pdesc),
7846 + sc->sc_dpalloc.dma_vaddr, sc->sc_dpalloc.dma_paddr);
7847 + kfree(sc);
7848 + return(-ENODEV);
7849 +}
7850 +
7851 +static void safe_remove(struct pci_dev *dev)
7852 +{
7853 + struct safe_softc *sc = pci_get_drvdata(dev);
7854 +
7855 + DPRINTF(("%s()\n", __FUNCTION__));
7856 +
7857 + /* XXX wait/abort active ops */
7858 +
7859 + WRITE_REG(sc, SAFE_HI_MASK, 0); /* disable interrupts */
7860 +
7861 + del_timer_sync(&sc->sc_pkto);
7862 +
7863 + crypto_unregister_all(sc->sc_cid);
7864 +
7865 + safe_cleanchip(sc);
7866 +
7867 + if (sc->sc_irq != -1)
7868 + free_irq(sc->sc_irq, sc);
7869 + if (sc->sc_ringalloc.dma_vaddr)
7870 + pci_free_consistent(sc->sc_pcidev,
7871 + SAFE_MAX_NQUEUE * sizeof (struct safe_ringentry),
7872 + sc->sc_ringalloc.dma_vaddr, sc->sc_ringalloc.dma_paddr);
7873 + if (sc->sc_spalloc.dma_vaddr)
7874 + pci_free_consistent(sc->sc_pcidev,
7875 + SAFE_TOTAL_DPART * sizeof (struct safe_pdesc),
7876 + sc->sc_spalloc.dma_vaddr, sc->sc_spalloc.dma_paddr);
7877 + if (sc->sc_dpalloc.dma_vaddr)
7878 + pci_free_consistent(sc->sc_pcidev,
7879 + SAFE_TOTAL_DPART * sizeof (struct safe_pdesc),
7880 + sc->sc_dpalloc.dma_vaddr, sc->sc_dpalloc.dma_paddr);
7881 + sc->sc_irq = -1;
7882 + sc->sc_ringalloc.dma_vaddr = NULL;
7883 + sc->sc_spalloc.dma_vaddr = NULL;
7884 + sc->sc_dpalloc.dma_vaddr = NULL;
7885 +}
7886 +
7887 +static struct pci_device_id safe_pci_tbl[] = {
7888 + { PCI_VENDOR_SAFENET, PCI_PRODUCT_SAFEXCEL,
7889 + PCI_ANY_ID, PCI_ANY_ID, 0, 0, },
7890 + { },
7891 +};
7892 +MODULE_DEVICE_TABLE(pci, safe_pci_tbl);
7893 +
7894 +static struct pci_driver safe_driver = {
7895 + .name = "safe",
7896 + .id_table = safe_pci_tbl,
7897 + .probe = safe_probe,
7898 + .remove = safe_remove,
7899 + /* add PM stuff here one day */
7900 +};
7901 +
7902 +static int __init safe_init (void)
7903 +{
7904 + struct safe_softc *sc = NULL;
7905 + int rc;
7906 +
7907 + DPRINTF(("%s(%p)\n", __FUNCTION__, safe_init));
7908 +
7909 + rc = pci_register_driver(&safe_driver);
7910 + pci_register_driver_compat(&safe_driver, rc);
7911 +
7912 + return rc;
7913 +}
7914 +
7915 +static void __exit safe_exit (void)
7916 +{
7917 + pci_unregister_driver(&safe_driver);
7918 +}
7919 +
7920 +module_init(safe_init);
7921 +module_exit(safe_exit);
7922 +
7923 +MODULE_LICENSE("BSD");
7924 +MODULE_AUTHOR("David McCullough <david_mccullough@securecomputing.com>");
7925 +MODULE_DESCRIPTION("OCF driver for safenet PCI crypto devices");
7926 --- /dev/null
7927 +++ b/crypto/ocf/safe/sha1.c
7928 @@ -0,0 +1,279 @@
7929 +/* $KAME: sha1.c,v 1.5 2000/11/08 06:13:08 itojun Exp $ */
7930 +/*
7931 + * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
7932 + * All rights reserved.
7933 + *
7934 + * Redistribution and use in source and binary forms, with or without
7935 + * modification, are permitted provided that the following conditions
7936 + * are met:
7937 + * 1. Redistributions of source code must retain the above copyright
7938 + * notice, this list of conditions and the following disclaimer.
7939 + * 2. Redistributions in binary form must reproduce the above copyright
7940 + * notice, this list of conditions and the following disclaimer in the
7941 + * documentation and/or other materials provided with the distribution.
7942 + * 3. Neither the name of the project nor the names of its contributors
7943 + * may be used to endorse or promote products derived from this software
7944 + * without specific prior written permission.
7945 + *
7946 + * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
7947 + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
7948 + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
7949 + * ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
7950 + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
7951 + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
7952 + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
7953 + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
7954 + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
7955 + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
7956 + * SUCH DAMAGE.
7957 + */
7958 +
7959 +/*
7960 + * FIPS pub 180-1: Secure Hash Algorithm (SHA-1)
7961 + * based on: http://csrc.nist.gov/fips/fip180-1.txt
7962 + * implemented by Jun-ichiro itojun Itoh <itojun@itojun.org>
7963 + */
7964 +
7965 +#if 0
7966 +#include <sys/cdefs.h>
7967 +__FBSDID("$FreeBSD: src/sys/crypto/sha1.c,v 1.9 2003/06/10 21:36:57 obrien Exp $");
7968 +
7969 +#include <sys/types.h>
7970 +#include <sys/cdefs.h>
7971 +#include <sys/time.h>
7972 +#include <sys/systm.h>
7973 +
7974 +#include <crypto/sha1.h>
7975 +#endif
7976 +
7977 +/* sanity check */
7978 +#if BYTE_ORDER != BIG_ENDIAN
7979 +# if BYTE_ORDER != LITTLE_ENDIAN
7980 +# define unsupported 1
7981 +# endif
7982 +#endif
7983 +
7984 +#ifndef unsupported
7985 +
7986 +/* constant table */
7987 +static u_int32_t _K[] = { 0x5a827999, 0x6ed9eba1, 0x8f1bbcdc, 0xca62c1d6 };
7988 +#define K(t) _K[(t) / 20]
7989 +
7990 +#define F0(b, c, d) (((b) & (c)) | ((~(b)) & (d)))
7991 +#define F1(b, c, d) (((b) ^ (c)) ^ (d))
7992 +#define F2(b, c, d) (((b) & (c)) | ((b) & (d)) | ((c) & (d)))
7993 +#define F3(b, c, d) (((b) ^ (c)) ^ (d))
7994 +
7995 +#define S(n, x) (((x) << (n)) | ((x) >> (32 - n)))
7996 +
7997 +#undef H
7998 +#define H(n) (ctxt->h.b32[(n)])
7999 +#define COUNT (ctxt->count)
8000 +#define BCOUNT (ctxt->c.b64[0] / 8)
8001 +#define W(n) (ctxt->m.b32[(n)])
8002 +
8003 +#define PUTBYTE(x) { \
8004 + ctxt->m.b8[(COUNT % 64)] = (x); \
8005 + COUNT++; \
8006 + COUNT %= 64; \
8007 + ctxt->c.b64[0] += 8; \
8008 + if (COUNT % 64 == 0) \
8009 + sha1_step(ctxt); \
8010 + }
8011 +
8012 +#define PUTPAD(x) { \
8013 + ctxt->m.b8[(COUNT % 64)] = (x); \
8014 + COUNT++; \
8015 + COUNT %= 64; \
8016 + if (COUNT % 64 == 0) \
8017 + sha1_step(ctxt); \
8018 + }
8019 +
8020 +static void sha1_step(struct sha1_ctxt *);
8021 +
8022 +static void
8023 +sha1_step(ctxt)
8024 + struct sha1_ctxt *ctxt;
8025 +{
8026 + u_int32_t a, b, c, d, e;
8027 + size_t t, s;
8028 + u_int32_t tmp;
8029 +
8030 +#if BYTE_ORDER == LITTLE_ENDIAN
8031 + struct sha1_ctxt tctxt;
8032 + bcopy(&ctxt->m.b8[0], &tctxt.m.b8[0], 64);
8033 + ctxt->m.b8[0] = tctxt.m.b8[3]; ctxt->m.b8[1] = tctxt.m.b8[2];
8034 + ctxt->m.b8[2] = tctxt.m.b8[1]; ctxt->m.b8[3] = tctxt.m.b8[0];
8035 + ctxt->m.b8[4] = tctxt.m.b8[7]; ctxt->m.b8[5] = tctxt.m.b8[6];
8036 + ctxt->m.b8[6] = tctxt.m.b8[5]; ctxt->m.b8[7] = tctxt.m.b8[4];
8037 + ctxt->m.b8[8] = tctxt.m.b8[11]; ctxt->m.b8[9] = tctxt.m.b8[10];
8038 + ctxt->m.b8[10] = tctxt.m.b8[9]; ctxt->m.b8[11] = tctxt.m.b8[8];
8039 + ctxt->m.b8[12] = tctxt.m.b8[15]; ctxt->m.b8[13] = tctxt.m.b8[14];
8040 + ctxt->m.b8[14] = tctxt.m.b8[13]; ctxt->m.b8[15] = tctxt.m.b8[12];
8041 + ctxt->m.b8[16] = tctxt.m.b8[19]; ctxt->m.b8[17] = tctxt.m.b8[18];
8042 + ctxt->m.b8[18] = tctxt.m.b8[17]; ctxt->m.b8[19] = tctxt.m.b8[16];
8043 + ctxt->m.b8[20] = tctxt.m.b8[23]; ctxt->m.b8[21] = tctxt.m.b8[22];
8044 + ctxt->m.b8[22] = tctxt.m.b8[21]; ctxt->m.b8[23] = tctxt.m.b8[20];
8045 + ctxt->m.b8[24] = tctxt.m.b8[27]; ctxt->m.b8[25] = tctxt.m.b8[26];
8046 + ctxt->m.b8[26] = tctxt.m.b8[25]; ctxt->m.b8[27] = tctxt.m.b8[24];
8047 + ctxt->m.b8[28] = tctxt.m.b8[31]; ctxt->m.b8[29] = tctxt.m.b8[30];
8048 + ctxt->m.b8[30] = tctxt.m.b8[29]; ctxt->m.b8[31] = tctxt.m.b8[28];
8049 + ctxt->m.b8[32] = tctxt.m.b8[35]; ctxt->m.b8[33] = tctxt.m.b8[34];
8050 + ctxt->m.b8[34] = tctxt.m.b8[33]; ctxt->m.b8[35] = tctxt.m.b8[32];
8051 + ctxt->m.b8[36] = tctxt.m.b8[39]; ctxt->m.b8[37] = tctxt.m.b8[38];
8052 + ctxt->m.b8[38] = tctxt.m.b8[37]; ctxt->m.b8[39] = tctxt.m.b8[36];
8053 + ctxt->m.b8[40] = tctxt.m.b8[43]; ctxt->m.b8[41] = tctxt.m.b8[42];
8054 + ctxt->m.b8[42] = tctxt.m.b8[41]; ctxt->m.b8[43] = tctxt.m.b8[40];
8055 + ctxt->m.b8[44] = tctxt.m.b8[47]; ctxt->m.b8[45] = tctxt.m.b8[46];
8056 + ctxt->m.b8[46] = tctxt.m.b8[45]; ctxt->m.b8[47] = tctxt.m.b8[44];
8057 + ctxt->m.b8[48] = tctxt.m.b8[51]; ctxt->m.b8[49] = tctxt.m.b8[50];
8058 + ctxt->m.b8[50] = tctxt.m.b8[49]; ctxt->m.b8[51] = tctxt.m.b8[48];
8059 + ctxt->m.b8[52] = tctxt.m.b8[55]; ctxt->m.b8[53] = tctxt.m.b8[54];
8060 + ctxt->m.b8[54] = tctxt.m.b8[53]; ctxt->m.b8[55] = tctxt.m.b8[52];
8061 + ctxt->m.b8[56] = tctxt.m.b8[59]; ctxt->m.b8[57] = tctxt.m.b8[58];
8062 + ctxt->m.b8[58] = tctxt.m.b8[57]; ctxt->m.b8[59] = tctxt.m.b8[56];
8063 + ctxt->m.b8[60] = tctxt.m.b8[63]; ctxt->m.b8[61] = tctxt.m.b8[62];
8064 + ctxt->m.b8[62] = tctxt.m.b8[61]; ctxt->m.b8[63] = tctxt.m.b8[60];
8065 +#endif
8066 +
8067 + a = H(0); b = H(1); c = H(2); d = H(3); e = H(4);
8068 +
8069 + for (t = 0; t < 20; t++) {
8070 + s = t & 0x0f;
8071 + if (t >= 16) {
8072 + W(s) = S(1, W((s+13) & 0x0f) ^ W((s+8) & 0x0f) ^ W((s+2) & 0x0f) ^ W(s));
8073 + }
8074 + tmp = S(5, a) + F0(b, c, d) + e + W(s) + K(t);
8075 + e = d; d = c; c = S(30, b); b = a; a = tmp;
8076 + }
8077 + for (t = 20; t < 40; t++) {
8078 + s = t & 0x0f;
8079 + W(s) = S(1, W((s+13) & 0x0f) ^ W((s+8) & 0x0f) ^ W((s+2) & 0x0f) ^ W(s));
8080 + tmp = S(5, a) + F1(b, c, d) + e + W(s) + K(t);
8081 + e = d; d = c; c = S(30, b); b = a; a = tmp;
8082 + }
8083 + for (t = 40; t < 60; t++) {
8084 + s = t & 0x0f;
8085 + W(s) = S(1, W((s+13) & 0x0f) ^ W((s+8) & 0x0f) ^ W((s+2) & 0x0f) ^ W(s));
8086 + tmp = S(5, a) + F2(b, c, d) + e + W(s) + K(t);
8087 + e = d; d = c; c = S(30, b); b = a; a = tmp;
8088 + }
8089 + for (t = 60; t < 80; t++) {
8090 + s = t & 0x0f;
8091 + W(s) = S(1, W((s+13) & 0x0f) ^ W((s+8) & 0x0f) ^ W((s+2) & 0x0f) ^ W(s));
8092 + tmp = S(5, a) + F3(b, c, d) + e + W(s) + K(t);
8093 + e = d; d = c; c = S(30, b); b = a; a = tmp;
8094 + }
8095 +
8096 + H(0) = H(0) + a;
8097 + H(1) = H(1) + b;
8098 + H(2) = H(2) + c;
8099 + H(3) = H(3) + d;
8100 + H(4) = H(4) + e;
8101 +
8102 + bzero(&ctxt->m.b8[0], 64);
8103 +}
8104 +
8105 +/*------------------------------------------------------------*/
8106 +
8107 +void
8108 +sha1_init(ctxt)
8109 + struct sha1_ctxt *ctxt;
8110 +{
8111 + bzero(ctxt, sizeof(struct sha1_ctxt));
8112 + H(0) = 0x67452301;
8113 + H(1) = 0xefcdab89;
8114 + H(2) = 0x98badcfe;
8115 + H(3) = 0x10325476;
8116 + H(4) = 0xc3d2e1f0;
8117 +}
8118 +
8119 +void
8120 +sha1_pad(ctxt)
8121 + struct sha1_ctxt *ctxt;
8122 +{
8123 + size_t padlen; /*pad length in bytes*/
8124 + size_t padstart;
8125 +
8126 + PUTPAD(0x80);
8127 +
8128 + padstart = COUNT % 64;
8129 + padlen = 64 - padstart;
8130 + if (padlen < 8) {
8131 + bzero(&ctxt->m.b8[padstart], padlen);
8132 + COUNT += padlen;
8133 + COUNT %= 64;
8134 + sha1_step(ctxt);
8135 + padstart = COUNT % 64; /* should be 0 */
8136 + padlen = 64 - padstart; /* should be 64 */
8137 + }
8138 + bzero(&ctxt->m.b8[padstart], padlen - 8);
8139 + COUNT += (padlen - 8);
8140 + COUNT %= 64;
8141 +#if BYTE_ORDER == BIG_ENDIAN
8142 + PUTPAD(ctxt->c.b8[0]); PUTPAD(ctxt->c.b8[1]);
8143 + PUTPAD(ctxt->c.b8[2]); PUTPAD(ctxt->c.b8[3]);
8144 + PUTPAD(ctxt->c.b8[4]); PUTPAD(ctxt->c.b8[5]);
8145 + PUTPAD(ctxt->c.b8[6]); PUTPAD(ctxt->c.b8[7]);
8146 +#else
8147 + PUTPAD(ctxt->c.b8[7]); PUTPAD(ctxt->c.b8[6]);
8148 + PUTPAD(ctxt->c.b8[5]); PUTPAD(ctxt->c.b8[4]);
8149 + PUTPAD(ctxt->c.b8[3]); PUTPAD(ctxt->c.b8[2]);
8150 + PUTPAD(ctxt->c.b8[1]); PUTPAD(ctxt->c.b8[0]);
8151 +#endif
8152 +}
8153 +
8154 +void
8155 +sha1_loop(ctxt, input, len)
8156 + struct sha1_ctxt *ctxt;
8157 + const u_int8_t *input;
8158 + size_t len;
8159 +{
8160 + size_t gaplen;
8161 + size_t gapstart;
8162 + size_t off;
8163 + size_t copysiz;
8164 +
8165 + off = 0;
8166 +
8167 + while (off < len) {
8168 + gapstart = COUNT % 64;
8169 + gaplen = 64 - gapstart;
8170 +
8171 + copysiz = (gaplen < len - off) ? gaplen : len - off;
8172 + bcopy(&input[off], &ctxt->m.b8[gapstart], copysiz);
8173 + COUNT += copysiz;
8174 + COUNT %= 64;
8175 + ctxt->c.b64[0] += copysiz * 8;
8176 + if (COUNT % 64 == 0)
8177 + sha1_step(ctxt);
8178 + off += copysiz;
8179 + }
8180 +}
8181 +
8182 +void
8183 +sha1_result(ctxt, digest0)
8184 + struct sha1_ctxt *ctxt;
8185 + caddr_t digest0;
8186 +{
8187 + u_int8_t *digest;
8188 +
8189 + digest = (u_int8_t *)digest0;
8190 + sha1_pad(ctxt);
8191 +#if BYTE_ORDER == BIG_ENDIAN
8192 + bcopy(&ctxt->h.b8[0], digest, 20);
8193 +#else
8194 + digest[0] = ctxt->h.b8[3]; digest[1] = ctxt->h.b8[2];
8195 + digest[2] = ctxt->h.b8[1]; digest[3] = ctxt->h.b8[0];
8196 + digest[4] = ctxt->h.b8[7]; digest[5] = ctxt->h.b8[6];
8197 + digest[6] = ctxt->h.b8[5]; digest[7] = ctxt->h.b8[4];
8198 + digest[8] = ctxt->h.b8[11]; digest[9] = ctxt->h.b8[10];
8199 + digest[10] = ctxt->h.b8[9]; digest[11] = ctxt->h.b8[8];
8200 + digest[12] = ctxt->h.b8[15]; digest[13] = ctxt->h.b8[14];
8201 + digest[14] = ctxt->h.b8[13]; digest[15] = ctxt->h.b8[12];
8202 + digest[16] = ctxt->h.b8[19]; digest[17] = ctxt->h.b8[18];
8203 + digest[18] = ctxt->h.b8[17]; digest[19] = ctxt->h.b8[16];
8204 +#endif
8205 +}
8206 +
8207 +#endif /*unsupported*/
8208 --- /dev/null
8209 +++ b/crypto/ocf/safe/sha1.h
8210 @@ -0,0 +1,72 @@
8211 +/* $FreeBSD: src/sys/crypto/sha1.h,v 1.8 2002/03/20 05:13:50 alfred Exp $ */
8212 +/* $KAME: sha1.h,v 1.5 2000/03/27 04:36:23 sumikawa Exp $ */
8213 +
8214 +/*
8215 + * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
8216 + * All rights reserved.
8217 + *
8218 + * Redistribution and use in source and binary forms, with or without
8219 + * modification, are permitted provided that the following conditions
8220 + * are met:
8221 + * 1. Redistributions of source code must retain the above copyright
8222 + * notice, this list of conditions and the following disclaimer.
8223 + * 2. Redistributions in binary form must reproduce the above copyright
8224 + * notice, this list of conditions and the following disclaimer in the
8225 + * documentation and/or other materials provided with the distribution.
8226 + * 3. Neither the name of the project nor the names of its contributors
8227 + * may be used to endorse or promote products derived from this software
8228 + * without specific prior written permission.
8229 + *
8230 + * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
8231 + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
8232 + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
8233 + * ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
8234 + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
8235 + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
8236 + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
8237 + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
8238 + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
8239 + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
8240 + * SUCH DAMAGE.
8241 + */
8242 +/*
8243 + * FIPS pub 180-1: Secure Hash Algorithm (SHA-1)
8244 + * based on: http://csrc.nist.gov/fips/fip180-1.txt
8245 + * implemented by Jun-ichiro itojun Itoh <itojun@itojun.org>
8246 + */
8247 +
8248 +#ifndef _NETINET6_SHA1_H_
8249 +#define _NETINET6_SHA1_H_
8250 +
8251 +struct sha1_ctxt {
8252 + union {
8253 + u_int8_t b8[20];
8254 + u_int32_t b32[5];
8255 + } h;
8256 + union {
8257 + u_int8_t b8[8];
8258 + u_int64_t b64[1];
8259 + } c;
8260 + union {
8261 + u_int8_t b8[64];
8262 + u_int32_t b32[16];
8263 + } m;
8264 + u_int8_t count;
8265 +};
8266 +
8267 +#ifdef __KERNEL__
8268 +extern void sha1_init(struct sha1_ctxt *);
8269 +extern void sha1_pad(struct sha1_ctxt *);
8270 +extern void sha1_loop(struct sha1_ctxt *, const u_int8_t *, size_t);
8271 +extern void sha1_result(struct sha1_ctxt *, caddr_t);
8272 +
8273 +/* compatibilty with other SHA1 source codes */
8274 +typedef struct sha1_ctxt SHA1_CTX;
8275 +#define SHA1Init(x) sha1_init((x))
8276 +#define SHA1Update(x, y, z) sha1_loop((x), (y), (z))
8277 +#define SHA1Final(x, y) sha1_result((y), (x))
8278 +#endif /* __KERNEL__ */
8279 +
8280 +#define SHA1_RESULTLEN (160/8)
8281 +
8282 +#endif /*_NETINET6_SHA1_H_*/
8283 --- /dev/null
8284 +++ b/crypto/ocf/safe/safereg.h
8285 @@ -0,0 +1,421 @@
8286 +/*-
8287 + * Copyright (c) 2003 Sam Leffler, Errno Consulting
8288 + * Copyright (c) 2003 Global Technology Associates, Inc.
8289 + * All rights reserved.
8290 + *
8291 + * Redistribution and use in source and binary forms, with or without
8292 + * modification, are permitted provided that the following conditions
8293 + * are met:
8294 + * 1. Redistributions of source code must retain the above copyright
8295 + * notice, this list of conditions and the following disclaimer.
8296 + * 2. Redistributions in binary form must reproduce the above copyright
8297 + * notice, this list of conditions and the following disclaimer in the
8298 + * documentation and/or other materials provided with the distribution.
8299 + *
8300 + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
8301 + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
8302 + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
8303 + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
8304 + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
8305 + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
8306 + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
8307 + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
8308 + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
8309 + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
8310 + * SUCH DAMAGE.
8311 + *
8312 + * $FreeBSD: src/sys/dev/safe/safereg.h,v 1.1 2003/07/21 21:46:07 sam Exp $
8313 + */
8314 +#ifndef _SAFE_SAFEREG_H_
8315 +#define _SAFE_SAFEREG_H_
8316 +
8317 +/*
8318 + * Register definitions for SafeNet SafeXcel-1141 crypto device.
8319 + * Definitions from revision 1.3 (Nov 6 2002) of the User's Manual.
8320 + */
8321 +
8322 +#define BS_BAR 0x10 /* DMA base address register */
8323 +#define BS_TRDY_TIMEOUT 0x40 /* TRDY timeout */
8324 +#define BS_RETRY_TIMEOUT 0x41 /* DMA retry timeout */
8325 +
8326 +#define PCI_VENDOR_SAFENET 0x16ae /* SafeNet, Inc. */
8327 +
8328 +/* SafeNet */
8329 +#define PCI_PRODUCT_SAFEXCEL 0x1141 /* 1141 */
8330 +
8331 +#define SAFE_PE_CSR 0x0000 /* Packet Enginge Ctrl/Status */
8332 +#define SAFE_PE_SRC 0x0004 /* Packet Engine Source */
8333 +#define SAFE_PE_DST 0x0008 /* Packet Engine Destination */
8334 +#define SAFE_PE_SA 0x000c /* Packet Engine SA */
8335 +#define SAFE_PE_LEN 0x0010 /* Packet Engine Length */
8336 +#define SAFE_PE_DMACFG 0x0040 /* Packet Engine DMA Configuration */
8337 +#define SAFE_PE_DMASTAT 0x0044 /* Packet Engine DMA Status */
8338 +#define SAFE_PE_PDRBASE 0x0048 /* Packet Engine Descriptor Ring Base */
8339 +#define SAFE_PE_RDRBASE 0x004c /* Packet Engine Result Ring Base */
8340 +#define SAFE_PE_RINGCFG 0x0050 /* Packet Engine Ring Configuration */
8341 +#define SAFE_PE_RINGPOLL 0x0054 /* Packet Engine Ring Poll */
8342 +#define SAFE_PE_IRNGSTAT 0x0058 /* Packet Engine Internal Ring Status */
8343 +#define SAFE_PE_ERNGSTAT 0x005c /* Packet Engine External Ring Status */
8344 +#define SAFE_PE_IOTHRESH 0x0060 /* Packet Engine I/O Threshold */
8345 +#define SAFE_PE_GRNGBASE 0x0064 /* Packet Engine Gather Ring Base */
8346 +#define SAFE_PE_SRNGBASE 0x0068 /* Packet Engine Scatter Ring Base */
8347 +#define SAFE_PE_PARTSIZE 0x006c /* Packet Engine Particlar Ring Size */
8348 +#define SAFE_PE_PARTCFG 0x0070 /* Packet Engine Particle Ring Config */
8349 +#define SAFE_CRYPTO_CTRL 0x0080 /* Crypto Control */
8350 +#define SAFE_DEVID 0x0084 /* Device ID */
8351 +#define SAFE_DEVINFO 0x0088 /* Device Info */
8352 +#define SAFE_HU_STAT 0x00a0 /* Host Unmasked Status */
8353 +#define SAFE_HM_STAT 0x00a4 /* Host Masked Status (read-only) */
8354 +#define SAFE_HI_CLR 0x00a4 /* Host Clear Interrupt (write-only) */
8355 +#define SAFE_HI_MASK 0x00a8 /* Host Mask Control */
8356 +#define SAFE_HI_CFG 0x00ac /* Interrupt Configuration */
8357 +#define SAFE_HI_RD_DESCR 0x00b4 /* Force Descriptor Read */
8358 +#define SAFE_HI_DESC_CNT 0x00b8 /* Host Descriptor Done Count */
8359 +#define SAFE_DMA_ENDIAN 0x00c0 /* Master Endian Status */
8360 +#define SAFE_DMA_SRCADDR 0x00c4 /* DMA Source Address Status */
8361 +#define SAFE_DMA_DSTADDR 0x00c8 /* DMA Destination Address Status */
8362 +#define SAFE_DMA_STAT 0x00cc /* DMA Current Status */
8363 +#define SAFE_DMA_CFG 0x00d4 /* DMA Configuration/Status */
8364 +#define SAFE_ENDIAN 0x00e0 /* Endian Configuration */
8365 +#define SAFE_PK_A_ADDR 0x0800 /* Public Key A Address */
8366 +#define SAFE_PK_B_ADDR 0x0804 /* Public Key B Address */
8367 +#define SAFE_PK_C_ADDR 0x0808 /* Public Key C Address */
8368 +#define SAFE_PK_D_ADDR 0x080c /* Public Key D Address */
8369 +#define SAFE_PK_A_LEN 0x0810 /* Public Key A Length */
8370 +#define SAFE_PK_B_LEN 0x0814 /* Public Key B Length */
8371 +#define SAFE_PK_SHIFT 0x0818 /* Public Key Shift */
8372 +#define SAFE_PK_FUNC 0x081c /* Public Key Function */
8373 +#define SAFE_PK_RAM_START 0x1000 /* Public Key RAM start address */
8374 +#define SAFE_PK_RAM_END 0x1fff /* Public Key RAM end address */
8375 +
8376 +#define SAFE_RNG_OUT 0x0100 /* RNG Output */
8377 +#define SAFE_RNG_STAT 0x0104 /* RNG Status */
8378 +#define SAFE_RNG_CTRL 0x0108 /* RNG Control */
8379 +#define SAFE_RNG_A 0x010c /* RNG A */
8380 +#define SAFE_RNG_B 0x0110 /* RNG B */
8381 +#define SAFE_RNG_X_LO 0x0114 /* RNG X [31:0] */
8382 +#define SAFE_RNG_X_MID 0x0118 /* RNG X [63:32] */
8383 +#define SAFE_RNG_X_HI 0x011c /* RNG X [80:64] */
8384 +#define SAFE_RNG_X_CNTR 0x0120 /* RNG Counter */
8385 +#define SAFE_RNG_ALM_CNT 0x0124 /* RNG Alarm Count */
8386 +#define SAFE_RNG_CNFG 0x0128 /* RNG Configuration */
8387 +#define SAFE_RNG_LFSR1_LO 0x012c /* RNG LFSR1 [31:0] */
8388 +#define SAFE_RNG_LFSR1_HI 0x0130 /* RNG LFSR1 [47:32] */
8389 +#define SAFE_RNG_LFSR2_LO 0x0134 /* RNG LFSR1 [31:0] */
8390 +#define SAFE_RNG_LFSR2_HI 0x0138 /* RNG LFSR1 [47:32] */
8391 +
8392 +#define SAFE_PE_CSR_READY 0x00000001 /* ready for processing */
8393 +#define SAFE_PE_CSR_DONE 0x00000002 /* h/w completed processing */
8394 +#define SAFE_PE_CSR_LOADSA 0x00000004 /* load SA digests */
8395 +#define SAFE_PE_CSR_HASHFINAL 0x00000010 /* do hash pad & write result */
8396 +#define SAFE_PE_CSR_SABUSID 0x000000c0 /* bus id for SA */
8397 +#define SAFE_PE_CSR_SAPCI 0x00000040 /* PCI bus id for SA */
8398 +#define SAFE_PE_CSR_NXTHDR 0x0000ff00 /* next hdr value for IPsec */
8399 +#define SAFE_PE_CSR_FPAD 0x0000ff00 /* fixed pad for basic ops */
8400 +#define SAFE_PE_CSR_STATUS 0x00ff0000 /* operation result status */
8401 +#define SAFE_PE_CSR_AUTH_FAIL 0x00010000 /* ICV mismatch (inbound) */
8402 +#define SAFE_PE_CSR_PAD_FAIL 0x00020000 /* pad verify fail (inbound) */
8403 +#define SAFE_PE_CSR_SEQ_FAIL 0x00040000 /* sequence number (inbound) */
8404 +#define SAFE_PE_CSR_XERROR 0x00080000 /* extended error follows */
8405 +#define SAFE_PE_CSR_XECODE 0x00f00000 /* extended error code */
8406 +#define SAFE_PE_CSR_XECODE_S 20
8407 +#define SAFE_PE_CSR_XECODE_BADCMD 0 /* invalid command */
8408 +#define SAFE_PE_CSR_XECODE_BADALG 1 /* invalid algorithm */
8409 +#define SAFE_PE_CSR_XECODE_ALGDIS 2 /* algorithm disabled */
8410 +#define SAFE_PE_CSR_XECODE_ZEROLEN 3 /* zero packet length */
8411 +#define SAFE_PE_CSR_XECODE_DMAERR 4 /* bus DMA error */
8412 +#define SAFE_PE_CSR_XECODE_PIPEABORT 5 /* secondary bus DMA error */
8413 +#define SAFE_PE_CSR_XECODE_BADSPI 6 /* IPsec SPI mismatch */
8414 +#define SAFE_PE_CSR_XECODE_TIMEOUT 10 /* failsafe timeout */
8415 +#define SAFE_PE_CSR_PAD 0xff000000 /* ESP padding control/status */
8416 +#define SAFE_PE_CSR_PAD_MIN 0x00000000 /* minimum IPsec padding */
8417 +#define SAFE_PE_CSR_PAD_16 0x08000000 /* pad to 16-byte boundary */
8418 +#define SAFE_PE_CSR_PAD_32 0x10000000 /* pad to 32-byte boundary */
8419 +#define SAFE_PE_CSR_PAD_64 0x20000000 /* pad to 64-byte boundary */
8420 +#define SAFE_PE_CSR_PAD_128 0x40000000 /* pad to 128-byte boundary */
8421 +#define SAFE_PE_CSR_PAD_256 0x80000000 /* pad to 256-byte boundary */
8422 +
8423 +/*
8424 + * Check the CSR to see if the PE has returned ownership to
8425 + * the host. Note that before processing a descriptor this
8426 + * must be done followed by a check of the SAFE_PE_LEN register
8427 + * status bits to avoid premature processing of a descriptor
8428 + * on its way back to the host.
8429 + */
8430 +#define SAFE_PE_CSR_IS_DONE(_csr) \
8431 + (((_csr) & (SAFE_PE_CSR_READY | SAFE_PE_CSR_DONE)) == SAFE_PE_CSR_DONE)
8432 +
8433 +#define SAFE_PE_LEN_LENGTH 0x000fffff /* total length (bytes) */
8434 +#define SAFE_PE_LEN_READY 0x00400000 /* ready for processing */
8435 +#define SAFE_PE_LEN_DONE 0x00800000 /* h/w completed processing */
8436 +#define SAFE_PE_LEN_BYPASS 0xff000000 /* bypass offset (bytes) */
8437 +#define SAFE_PE_LEN_BYPASS_S 24
8438 +
8439 +#define SAFE_PE_LEN_IS_DONE(_len) \
8440 + (((_len) & (SAFE_PE_LEN_READY | SAFE_PE_LEN_DONE)) == SAFE_PE_LEN_DONE)
8441 +
8442 +/* NB: these apply to HU_STAT, HM_STAT, HI_CLR, and HI_MASK */
8443 +#define SAFE_INT_PE_CDONE 0x00000002 /* PE context done */
8444 +#define SAFE_INT_PE_DDONE 0x00000008 /* PE descriptor done */
8445 +#define SAFE_INT_PE_ERROR 0x00000010 /* PE error */
8446 +#define SAFE_INT_PE_ODONE 0x00000020 /* PE operation done */
8447 +
8448 +#define SAFE_HI_CFG_PULSE 0x00000001 /* use pulse interrupt */
8449 +#define SAFE_HI_CFG_LEVEL 0x00000000 /* use level interrupt */
8450 +#define SAFE_HI_CFG_AUTOCLR 0x00000002 /* auto-clear pulse interrupt */
8451 +
8452 +#define SAFE_ENDIAN_PASS 0x000000e4 /* straight pass-thru */
8453 +#define SAFE_ENDIAN_SWAB 0x0000001b /* swap bytes in 32-bit word */
8454 +
8455 +#define SAFE_PE_DMACFG_PERESET 0x00000001 /* reset packet engine */
8456 +#define SAFE_PE_DMACFG_PDRRESET 0x00000002 /* reset PDR counters/ptrs */
8457 +#define SAFE_PE_DMACFG_SGRESET 0x00000004 /* reset scatter/gather cache */
8458 +#define SAFE_PE_DMACFG_FSENA 0x00000008 /* enable failsafe reset */
8459 +#define SAFE_PE_DMACFG_PEMODE 0x00000100 /* packet engine mode */
8460 +#define SAFE_PE_DMACFG_SAPREC 0x00000200 /* SA precedes packet */
8461 +#define SAFE_PE_DMACFG_PKFOLL 0x00000400 /* packet follows descriptor */
8462 +#define SAFE_PE_DMACFG_GPRBID 0x00003000 /* gather particle ring busid */
8463 +#define SAFE_PE_DMACFG_GPRPCI 0x00001000 /* PCI gather particle ring */
8464 +#define SAFE_PE_DMACFG_SPRBID 0x0000c000 /* scatter part. ring busid */
8465 +#define SAFE_PE_DMACFG_SPRPCI 0x00004000 /* PCI scatter part. ring */
8466 +#define SAFE_PE_DMACFG_ESDESC 0x00010000 /* endian swap descriptors */
8467 +#define SAFE_PE_DMACFG_ESSA 0x00020000 /* endian swap SA data */
8468 +#define SAFE_PE_DMACFG_ESPACKET 0x00040000 /* endian swap packet data */
8469 +#define SAFE_PE_DMACFG_ESPDESC 0x00080000 /* endian swap particle desc. */
8470 +#define SAFE_PE_DMACFG_NOPDRUP 0x00100000 /* supp. PDR ownership update */
8471 +#define SAFE_PD_EDMACFG_PCIMODE 0x01000000 /* PCI target mode */
8472 +
8473 +#define SAFE_PE_DMASTAT_PEIDONE 0x00000001 /* PE core input done */
8474 +#define SAFE_PE_DMASTAT_PEODONE 0x00000002 /* PE core output done */
8475 +#define SAFE_PE_DMASTAT_ENCDONE 0x00000004 /* encryption done */
8476 +#define SAFE_PE_DMASTAT_IHDONE 0x00000008 /* inner hash done */
8477 +#define SAFE_PE_DMASTAT_OHDONE 0x00000010 /* outer hash (HMAC) done */
8478 +#define SAFE_PE_DMASTAT_PADFLT 0x00000020 /* crypto pad fault */
8479 +#define SAFE_PE_DMASTAT_ICVFLT 0x00000040 /* ICV fault */
8480 +#define SAFE_PE_DMASTAT_SPIMIS 0x00000080 /* SPI mismatch */
8481 +#define SAFE_PE_DMASTAT_CRYPTO 0x00000100 /* crypto engine timeout */
8482 +#define SAFE_PE_DMASTAT_CQACT 0x00000200 /* command queue active */
8483 +#define SAFE_PE_DMASTAT_IRACT 0x00000400 /* input request active */
8484 +#define SAFE_PE_DMASTAT_ORACT 0x00000800 /* output request active */
8485 +#define SAFE_PE_DMASTAT_PEISIZE 0x003ff000 /* PE input size:32-bit words */
8486 +#define SAFE_PE_DMASTAT_PEOSIZE 0xffc00000 /* PE out. size:32-bit words */
8487 +
8488 +#define SAFE_PE_RINGCFG_SIZE 0x000003ff /* ring size (descriptors) */
8489 +#define SAFE_PE_RINGCFG_OFFSET 0xffff0000 /* offset btw desc's (dwords) */
8490 +#define SAFE_PE_RINGCFG_OFFSET_S 16
8491 +
8492 +#define SAFE_PE_RINGPOLL_POLL 0x00000fff /* polling frequency/divisor */
8493 +#define SAFE_PE_RINGPOLL_RETRY 0x03ff0000 /* polling frequency/divisor */
8494 +#define SAFE_PE_RINGPOLL_CONT 0x80000000 /* continuously poll */
8495 +
8496 +#define SAFE_PE_IRNGSTAT_CQAVAIL 0x00000001 /* command queue available */
8497 +
8498 +#define SAFE_PE_ERNGSTAT_NEXT 0x03ff0000 /* index of next packet desc. */
8499 +#define SAFE_PE_ERNGSTAT_NEXT_S 16
8500 +
8501 +#define SAFE_PE_IOTHRESH_INPUT 0x000003ff /* input threshold (dwords) */
8502 +#define SAFE_PE_IOTHRESH_OUTPUT 0x03ff0000 /* output threshold (dwords) */
8503 +
8504 +#define SAFE_PE_PARTCFG_SIZE 0x0000ffff /* scatter particle size */
8505 +#define SAFE_PE_PARTCFG_GBURST 0x00030000 /* gather particle burst */
8506 +#define SAFE_PE_PARTCFG_GBURST_2 0x00000000
8507 +#define SAFE_PE_PARTCFG_GBURST_4 0x00010000
8508 +#define SAFE_PE_PARTCFG_GBURST_8 0x00020000
8509 +#define SAFE_PE_PARTCFG_GBURST_16 0x00030000
8510 +#define SAFE_PE_PARTCFG_SBURST 0x000c0000 /* scatter particle burst */
8511 +#define SAFE_PE_PARTCFG_SBURST_2 0x00000000
8512 +#define SAFE_PE_PARTCFG_SBURST_4 0x00040000
8513 +#define SAFE_PE_PARTCFG_SBURST_8 0x00080000
8514 +#define SAFE_PE_PARTCFG_SBURST_16 0x000c0000
8515 +
8516 +#define SAFE_PE_PARTSIZE_SCAT 0xffff0000 /* scatter particle ring size */
8517 +#define SAFE_PE_PARTSIZE_GATH 0x0000ffff /* gather particle ring size */
8518 +
8519 +#define SAFE_CRYPTO_CTRL_3DES 0x00000001 /* enable 3DES support */
8520 +#define SAFE_CRYPTO_CTRL_PKEY 0x00010000 /* enable public key support */
8521 +#define SAFE_CRYPTO_CTRL_RNG 0x00020000 /* enable RNG support */
8522 +
8523 +#define SAFE_DEVINFO_REV_MIN 0x0000000f /* minor rev for chip */
8524 +#define SAFE_DEVINFO_REV_MAJ 0x000000f0 /* major rev for chip */
8525 +#define SAFE_DEVINFO_REV_MAJ_S 4
8526 +#define SAFE_DEVINFO_DES 0x00000100 /* DES/3DES support present */
8527 +#define SAFE_DEVINFO_ARC4 0x00000200 /* ARC4 support present */
8528 +#define SAFE_DEVINFO_AES 0x00000400 /* AES support present */
8529 +#define SAFE_DEVINFO_MD5 0x00001000 /* MD5 support present */
8530 +#define SAFE_DEVINFO_SHA1 0x00002000 /* SHA-1 support present */
8531 +#define SAFE_DEVINFO_RIPEMD 0x00004000 /* RIPEMD support present */
8532 +#define SAFE_DEVINFO_DEFLATE 0x00010000 /* Deflate support present */
8533 +#define SAFE_DEVINFO_SARAM 0x00100000 /* on-chip SA RAM present */
8534 +#define SAFE_DEVINFO_EMIBUS 0x00200000 /* EMI bus present */
8535 +#define SAFE_DEVINFO_PKEY 0x00400000 /* public key support present */
8536 +#define SAFE_DEVINFO_RNG 0x00800000 /* RNG present */
8537 +
8538 +#define SAFE_REV(_maj, _min) (((_maj) << SAFE_DEVINFO_REV_MAJ_S) | (_min))
8539 +#define SAFE_REV_MAJ(_chiprev) \
8540 + (((_chiprev) & SAFE_DEVINFO_REV_MAJ) >> SAFE_DEVINFO_REV_MAJ_S)
8541 +#define SAFE_REV_MIN(_chiprev) ((_chiprev) & SAFE_DEVINFO_REV_MIN)
8542 +
8543 +#define SAFE_PK_FUNC_MULT 0x00000001 /* Multiply function */
8544 +#define SAFE_PK_FUNC_SQUARE 0x00000004 /* Square function */
8545 +#define SAFE_PK_FUNC_ADD 0x00000010 /* Add function */
8546 +#define SAFE_PK_FUNC_SUB 0x00000020 /* Subtract function */
8547 +#define SAFE_PK_FUNC_LSHIFT 0x00000040 /* Left-shift function */
8548 +#define SAFE_PK_FUNC_RSHIFT 0x00000080 /* Right-shift function */
8549 +#define SAFE_PK_FUNC_DIV 0x00000100 /* Divide function */
8550 +#define SAFE_PK_FUNC_CMP 0x00000400 /* Compare function */
8551 +#define SAFE_PK_FUNC_COPY 0x00000800 /* Copy function */
8552 +#define SAFE_PK_FUNC_EXP16 0x00002000 /* Exponentiate (4-bit ACT) */
8553 +#define SAFE_PK_FUNC_EXP4 0x00004000 /* Exponentiate (2-bit ACT) */
8554 +#define SAFE_PK_FUNC_RUN 0x00008000 /* start/status */
8555 +
8556 +#define SAFE_RNG_STAT_BUSY 0x00000001 /* busy, data not valid */
8557 +
8558 +#define SAFE_RNG_CTRL_PRE_LFSR 0x00000001 /* enable output pre-LFSR */
8559 +#define SAFE_RNG_CTRL_TST_MODE 0x00000002 /* enable test mode */
8560 +#define SAFE_RNG_CTRL_TST_RUN 0x00000004 /* start test state machine */
8561 +#define SAFE_RNG_CTRL_ENA_RING1 0x00000008 /* test entropy oscillator #1 */
8562 +#define SAFE_RNG_CTRL_ENA_RING2 0x00000010 /* test entropy oscillator #2 */
8563 +#define SAFE_RNG_CTRL_DIS_ALARM 0x00000020 /* disable RNG alarm reports */
8564 +#define SAFE_RNG_CTRL_TST_CLOCK 0x00000040 /* enable test clock */
8565 +#define SAFE_RNG_CTRL_SHORTEN 0x00000080 /* shorten state timers */
8566 +#define SAFE_RNG_CTRL_TST_ALARM 0x00000100 /* simulate alarm state */
8567 +#define SAFE_RNG_CTRL_RST_LFSR 0x00000200 /* reset LFSR */
8568 +
8569 +/*
8570 + * Packet engine descriptor. Note that d_csr is a copy of the
8571 + * SAFE_PE_CSR register and all definitions apply, and d_len
8572 + * is a copy of the SAFE_PE_LEN register and all definitions apply.
8573 + * d_src and d_len may point directly to contiguous data or to a
8574 + * list of ``particle descriptors'' when using scatter/gather i/o.
8575 + */
8576 +struct safe_desc {
8577 + u_int32_t d_csr; /* per-packet control/status */
8578 + u_int32_t d_src; /* source address */
8579 + u_int32_t d_dst; /* destination address */
8580 + u_int32_t d_sa; /* SA address */
8581 + u_int32_t d_len; /* length, bypass, status */
8582 +};
8583 +
8584 +/*
8585 + * Scatter/Gather particle descriptor.
8586 + *
8587 + * NB: scatter descriptors do not specify a size; this is fixed
8588 + * by the setting of the SAFE_PE_PARTCFG register.
8589 + */
8590 +struct safe_pdesc {
8591 + u_int32_t pd_addr; /* particle address */
8592 +#ifdef __BIG_ENDIAN
8593 + u_int16_t pd_flags; /* control word */
8594 + u_int16_t pd_size; /* particle size (bytes) */
8595 +#else
8596 + u_int16_t pd_flags; /* control word */
8597 + u_int16_t pd_size; /* particle size (bytes) */
8598 +#endif
8599 +};
8600 +
8601 +#define SAFE_PD_READY 0x0001 /* ready for processing */
8602 +#define SAFE_PD_DONE 0x0002 /* h/w completed processing */
8603 +
8604 +/*
8605 + * Security Association (SA) Record (Rev 1). One of these is
8606 + * required for each operation processed by the packet engine.
8607 + */
8608 +struct safe_sarec {
8609 + u_int32_t sa_cmd0;
8610 + u_int32_t sa_cmd1;
8611 + u_int32_t sa_resv0;
8612 + u_int32_t sa_resv1;
8613 + u_int32_t sa_key[8]; /* DES/3DES/AES key */
8614 + u_int32_t sa_indigest[5]; /* inner digest */
8615 + u_int32_t sa_outdigest[5]; /* outer digest */
8616 + u_int32_t sa_spi; /* SPI */
8617 + u_int32_t sa_seqnum; /* sequence number */
8618 + u_int32_t sa_seqmask[2]; /* sequence number mask */
8619 + u_int32_t sa_resv2;
8620 + u_int32_t sa_staterec; /* address of state record */
8621 + u_int32_t sa_resv3[2];
8622 + u_int32_t sa_samgmt0; /* SA management field 0 */
8623 + u_int32_t sa_samgmt1; /* SA management field 0 */
8624 +};
8625 +
8626 +#define SAFE_SA_CMD0_OP 0x00000007 /* operation code */
8627 +#define SAFE_SA_CMD0_OP_CRYPT 0x00000000 /* encrypt/decrypt (basic) */
8628 +#define SAFE_SA_CMD0_OP_BOTH 0x00000001 /* encrypt-hash/hash-decrypto */
8629 +#define SAFE_SA_CMD0_OP_HASH 0x00000003 /* hash (outbound-only) */
8630 +#define SAFE_SA_CMD0_OP_ESP 0x00000000 /* ESP in/out (proto) */
8631 +#define SAFE_SA_CMD0_OP_AH 0x00000001 /* AH in/out (proto) */
8632 +#define SAFE_SA_CMD0_INBOUND 0x00000008 /* inbound operation */
8633 +#define SAFE_SA_CMD0_OUTBOUND 0x00000000 /* outbound operation */
8634 +#define SAFE_SA_CMD0_GROUP 0x00000030 /* operation group */
8635 +#define SAFE_SA_CMD0_BASIC 0x00000000 /* basic operation */
8636 +#define SAFE_SA_CMD0_PROTO 0x00000010 /* protocol/packet operation */
8637 +#define SAFE_SA_CMD0_BUNDLE 0x00000020 /* bundled operation (resvd) */
8638 +#define SAFE_SA_CMD0_PAD 0x000000c0 /* crypto pad method */
8639 +#define SAFE_SA_CMD0_PAD_IPSEC 0x00000000 /* IPsec padding */
8640 +#define SAFE_SA_CMD0_PAD_PKCS7 0x00000040 /* PKCS#7 padding */
8641 +#define SAFE_SA_CMD0_PAD_CONS 0x00000080 /* constant padding */
8642 +#define SAFE_SA_CMD0_PAD_ZERO 0x000000c0 /* zero padding */
8643 +#define SAFE_SA_CMD0_CRYPT_ALG 0x00000f00 /* symmetric crypto algorithm */
8644 +#define SAFE_SA_CMD0_DES 0x00000000 /* DES crypto algorithm */
8645 +#define SAFE_SA_CMD0_3DES 0x00000100 /* 3DES crypto algorithm */
8646 +#define SAFE_SA_CMD0_AES 0x00000300 /* AES crypto algorithm */
8647 +#define SAFE_SA_CMD0_CRYPT_NULL 0x00000f00 /* null crypto algorithm */
8648 +#define SAFE_SA_CMD0_HASH_ALG 0x0000f000 /* hash algorithm */
8649 +#define SAFE_SA_CMD0_MD5 0x00000000 /* MD5 hash algorithm */
8650 +#define SAFE_SA_CMD0_SHA1 0x00001000 /* SHA-1 hash algorithm */
8651 +#define SAFE_SA_CMD0_HASH_NULL 0x0000f000 /* null hash algorithm */
8652 +#define SAFE_SA_CMD0_HDR_PROC 0x00080000 /* header processing */
8653 +#define SAFE_SA_CMD0_IBUSID 0x00300000 /* input bus id */
8654 +#define SAFE_SA_CMD0_IPCI 0x00100000 /* PCI input bus id */
8655 +#define SAFE_SA_CMD0_OBUSID 0x00c00000 /* output bus id */
8656 +#define SAFE_SA_CMD0_OPCI 0x00400000 /* PCI output bus id */
8657 +#define SAFE_SA_CMD0_IVLD 0x03000000 /* IV loading */
8658 +#define SAFE_SA_CMD0_IVLD_NONE 0x00000000 /* IV no load (reuse) */
8659 +#define SAFE_SA_CMD0_IVLD_IBUF 0x01000000 /* IV load from input buffer */
8660 +#define SAFE_SA_CMD0_IVLD_STATE 0x02000000 /* IV load from state */
8661 +#define SAFE_SA_CMD0_HSLD 0x0c000000 /* hash state loading */
8662 +#define SAFE_SA_CMD0_HSLD_SA 0x00000000 /* hash state load from SA */
8663 +#define SAFE_SA_CMD0_HSLD_STATE 0x08000000 /* hash state load from state */
8664 +#define SAFE_SA_CMD0_HSLD_NONE 0x0c000000 /* hash state no load */
8665 +#define SAFE_SA_CMD0_SAVEIV 0x10000000 /* save IV */
8666 +#define SAFE_SA_CMD0_SAVEHASH 0x20000000 /* save hash state */
8667 +#define SAFE_SA_CMD0_IGATHER 0x40000000 /* input gather */
8668 +#define SAFE_SA_CMD0_OSCATTER 0x80000000 /* output scatter */
8669 +
8670 +#define SAFE_SA_CMD1_HDRCOPY 0x00000002 /* copy header to output */
8671 +#define SAFE_SA_CMD1_PAYCOPY 0x00000004 /* copy payload to output */
8672 +#define SAFE_SA_CMD1_PADCOPY 0x00000008 /* copy pad to output */
8673 +#define SAFE_SA_CMD1_IPV4 0x00000000 /* IPv4 protocol */
8674 +#define SAFE_SA_CMD1_IPV6 0x00000010 /* IPv6 protocol */
8675 +#define SAFE_SA_CMD1_MUTABLE 0x00000020 /* mutable bit processing */
8676 +#define SAFE_SA_CMD1_SRBUSID 0x000000c0 /* state record bus id */
8677 +#define SAFE_SA_CMD1_SRPCI 0x00000040 /* state record from PCI */
8678 +#define SAFE_SA_CMD1_CRMODE 0x00000300 /* crypto mode */
8679 +#define SAFE_SA_CMD1_ECB 0x00000000 /* ECB crypto mode */
8680 +#define SAFE_SA_CMD1_CBC 0x00000100 /* CBC crypto mode */
8681 +#define SAFE_SA_CMD1_OFB 0x00000200 /* OFB crypto mode */
8682 +#define SAFE_SA_CMD1_CFB 0x00000300 /* CFB crypto mode */
8683 +#define SAFE_SA_CMD1_CRFEEDBACK 0x00000c00 /* crypto feedback mode */
8684 +#define SAFE_SA_CMD1_64BIT 0x00000000 /* 64-bit crypto feedback */
8685 +#define SAFE_SA_CMD1_8BIT 0x00000400 /* 8-bit crypto feedback */
8686 +#define SAFE_SA_CMD1_1BIT 0x00000800 /* 1-bit crypto feedback */
8687 +#define SAFE_SA_CMD1_128BIT 0x00000c00 /* 128-bit crypto feedback */
8688 +#define SAFE_SA_CMD1_OPTIONS 0x00001000 /* HMAC/options mutable bit */
8689 +#define SAFE_SA_CMD1_HMAC SAFE_SA_CMD1_OPTIONS
8690 +#define SAFE_SA_CMD1_SAREV1 0x00008000 /* SA Revision 1 */
8691 +#define SAFE_SA_CMD1_OFFSET 0x00ff0000 /* hash/crypto offset(dwords) */
8692 +#define SAFE_SA_CMD1_OFFSET_S 16
8693 +#define SAFE_SA_CMD1_AESKEYLEN 0x0f000000 /* AES key length */
8694 +#define SAFE_SA_CMD1_AES128 0x02000000 /* 128-bit AES key */
8695 +#define SAFE_SA_CMD1_AES192 0x03000000 /* 192-bit AES key */
8696 +#define SAFE_SA_CMD1_AES256 0x04000000 /* 256-bit AES key */
8697 +
8698 +/*
8699 + * Security Associate State Record (Rev 1).
8700 + */
8701 +struct safe_sastate {
8702 + u_int32_t sa_saved_iv[4]; /* saved IV (DES/3DES/AES) */
8703 + u_int32_t sa_saved_hashbc; /* saved hash byte count */
8704 + u_int32_t sa_saved_indigest[5]; /* saved inner digest */
8705 +};
8706 +#endif /* _SAFE_SAFEREG_H_ */
8707 --- /dev/null
8708 +++ b/crypto/ocf/safe/safevar.h
8709 @@ -0,0 +1,230 @@
8710 +/*-
8711 + * The linux port of this code done by David McCullough
8712 + * Copyright (C) 2004-2007 David McCullough <david_mccullough@securecomputing.com>
8713 + * The license and original author are listed below.
8714 + *
8715 + * Copyright (c) 2003 Sam Leffler, Errno Consulting
8716 + * Copyright (c) 2003 Global Technology Associates, Inc.
8717 + * All rights reserved.
8718 + *
8719 + * Redistribution and use in source and binary forms, with or without
8720 + * modification, are permitted provided that the following conditions
8721 + * are met:
8722 + * 1. Redistributions of source code must retain the above copyright
8723 + * notice, this list of conditions and the following disclaimer.
8724 + * 2. Redistributions in binary form must reproduce the above copyright
8725 + * notice, this list of conditions and the following disclaimer in the
8726 + * documentation and/or other materials provided with the distribution.
8727 + *
8728 + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
8729 + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
8730 + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
8731 + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
8732 + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
8733 + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
8734 + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
8735 + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
8736 + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
8737 + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
8738 + * SUCH DAMAGE.
8739 + *
8740 + * $FreeBSD: src/sys/dev/safe/safevar.h,v 1.2 2006/05/17 18:34:26 pjd Exp $
8741 + */
8742 +#ifndef _SAFE_SAFEVAR_H_
8743 +#define _SAFE_SAFEVAR_H_
8744 +
8745 +/* Maximum queue length */
8746 +#ifndef SAFE_MAX_NQUEUE
8747 +#define SAFE_MAX_NQUEUE 60
8748 +#endif
8749 +
8750 +#define SAFE_MAX_PART 64 /* Maximum scatter/gather depth */
8751 +#define SAFE_DMA_BOUNDARY 0 /* No boundary for source DMA ops */
8752 +#define SAFE_MAX_DSIZE 2048 /* MCLBYTES Fixed scatter particle size */
8753 +#define SAFE_MAX_SSIZE 0x0ffff /* Maximum gather particle size */
8754 +#define SAFE_MAX_DMA 0xfffff /* Maximum PE operand size (20 bits) */
8755 +/* total src+dst particle descriptors */
8756 +#define SAFE_TOTAL_DPART (SAFE_MAX_NQUEUE * SAFE_MAX_PART)
8757 +#define SAFE_TOTAL_SPART (SAFE_MAX_NQUEUE * SAFE_MAX_PART)
8758 +
8759 +#define SAFE_RNG_MAXBUFSIZ 128 /* 32-bit words */
8760 +
8761 +#define SAFE_CARD(sid) (((sid) & 0xf0000000) >> 28)
8762 +#define SAFE_SESSION(sid) ( (sid) & 0x0fffffff)
8763 +#define SAFE_SID(crd, sesn) (((crd) << 28) | ((sesn) & 0x0fffffff))
8764 +
8765 +#define SAFE_DEF_RTY 0xff /* PCI Retry Timeout */
8766 +#define SAFE_DEF_TOUT 0xff /* PCI TRDY Timeout */
8767 +#define SAFE_DEF_CACHELINE 0x01 /* Cache Line setting */
8768 +
8769 +#ifdef __KERNEL__
8770 +/*
8771 + * State associated with the allocation of each chunk
8772 + * of memory setup for DMA.
8773 + */
8774 +struct safe_dma_alloc {
8775 + dma_addr_t dma_paddr;
8776 + void *dma_vaddr;
8777 +};
8778 +
8779 +/*
8780 + * Cryptographic operand state. One of these exists for each
8781 + * source and destination operand passed in from the crypto
8782 + * subsystem. When possible source and destination operands
8783 + * refer to the same memory. More often they are distinct.
8784 + * We track the virtual address of each operand as well as
8785 + * where each is mapped for DMA.
8786 + */
8787 +struct safe_operand {
8788 + union {
8789 + struct sk_buff *skb;
8790 + struct uio *io;
8791 + } u;
8792 + void *map;
8793 + int mapsize; /* total number of bytes in segs */
8794 + struct {
8795 + dma_addr_t ds_addr;
8796 + int ds_len;
8797 + int ds_tlen;
8798 + } segs[SAFE_MAX_PART];
8799 + int nsegs;
8800 +};
8801 +
8802 +/*
8803 + * Packet engine ring entry and cryptographic operation state.
8804 + * The packet engine requires a ring of descriptors that contain
8805 + * pointers to various cryptographic state. However the ring
8806 + * configuration register allows you to specify an arbitrary size
8807 + * for ring entries. We use this feature to collect most of the
8808 + * state for each cryptographic request into one spot. Other than
8809 + * ring entries only the ``particle descriptors'' (scatter/gather
8810 + * lists) and the actual operand data are kept separate. The
8811 + * particle descriptors must also be organized in rings. The
8812 + * operand data can be located aribtrarily (modulo alignment constraints).
8813 + *
8814 + * Note that the descriptor ring is mapped onto the PCI bus so
8815 + * the hardware can DMA data. This means the entire ring must be
8816 + * contiguous.
8817 + */
8818 +struct safe_ringentry {
8819 + struct safe_desc re_desc; /* command descriptor */
8820 + struct safe_sarec re_sa; /* SA record */
8821 + struct safe_sastate re_sastate; /* SA state record */
8822 +
8823 + struct cryptop *re_crp; /* crypto operation */
8824 +
8825 + struct safe_operand re_src; /* source operand */
8826 + struct safe_operand re_dst; /* destination operand */
8827 +
8828 + int re_sesn; /* crypto session ID */
8829 + int re_flags;
8830 +#define SAFE_QFLAGS_COPYOUTIV 0x1 /* copy back on completion */
8831 +#define SAFE_QFLAGS_COPYOUTICV 0x2 /* copy back on completion */
8832 +};
8833 +
8834 +#define re_src_skb re_src.u.skb
8835 +#define re_src_io re_src.u.io
8836 +#define re_src_map re_src.map
8837 +#define re_src_nsegs re_src.nsegs
8838 +#define re_src_segs re_src.segs
8839 +#define re_src_mapsize re_src.mapsize
8840 +
8841 +#define re_dst_skb re_dst.u.skb
8842 +#define re_dst_io re_dst.u.io
8843 +#define re_dst_map re_dst.map
8844 +#define re_dst_nsegs re_dst.nsegs
8845 +#define re_dst_segs re_dst.segs
8846 +#define re_dst_mapsize re_dst.mapsize
8847 +
8848 +struct rndstate_test;
8849 +
8850 +struct safe_session {
8851 + u_int32_t ses_used;
8852 + u_int32_t ses_klen; /* key length in bits */
8853 + u_int32_t ses_key[8]; /* DES/3DES/AES key */
8854 + u_int32_t ses_mlen; /* hmac length in bytes */
8855 + u_int32_t ses_hminner[5]; /* hmac inner state */
8856 + u_int32_t ses_hmouter[5]; /* hmac outer state */
8857 + u_int32_t ses_iv[4]; /* DES/3DES/AES iv */
8858 +};
8859 +
8860 +struct safe_pkq {
8861 + struct list_head pkq_list;
8862 + struct cryptkop *pkq_krp;
8863 +};
8864 +
8865 +struct safe_softc {
8866 + softc_device_decl sc_dev;
8867 + u32 sc_irq;
8868 +
8869 + struct pci_dev *sc_pcidev;
8870 + ocf_iomem_t sc_base_addr;
8871 +
8872 + u_int sc_chiprev; /* major/minor chip revision */
8873 + int sc_flags; /* device specific flags */
8874 +#define SAFE_FLAGS_KEY 0x01 /* has key accelerator */
8875 +#define SAFE_FLAGS_RNG 0x02 /* hardware rng */
8876 + int sc_suspended;
8877 + int sc_needwakeup; /* notify crypto layer */
8878 + int32_t sc_cid; /* crypto tag */
8879 +
8880 + struct safe_dma_alloc sc_ringalloc; /* PE ring allocation state */
8881 + struct safe_ringentry *sc_ring; /* PE ring */
8882 + struct safe_ringentry *sc_ringtop; /* PE ring top */
8883 + struct safe_ringentry *sc_front; /* next free entry */
8884 + struct safe_ringentry *sc_back; /* next pending entry */
8885 + int sc_nqchip; /* # passed to chip */
8886 + spinlock_t sc_ringmtx; /* PE ring lock */
8887 + struct safe_pdesc *sc_spring; /* src particle ring */
8888 + struct safe_pdesc *sc_springtop; /* src particle ring top */
8889 + struct safe_pdesc *sc_spfree; /* next free src particle */
8890 + struct safe_dma_alloc sc_spalloc; /* src particle ring state */
8891 + struct safe_pdesc *sc_dpring; /* dest particle ring */
8892 + struct safe_pdesc *sc_dpringtop; /* dest particle ring top */
8893 + struct safe_pdesc *sc_dpfree; /* next free dest particle */
8894 + struct safe_dma_alloc sc_dpalloc; /* dst particle ring state */
8895 + int sc_nsessions; /* # of sessions */
8896 + struct safe_session *sc_sessions; /* sessions */
8897 +
8898 + struct timer_list sc_pkto; /* PK polling */
8899 + spinlock_t sc_pkmtx; /* PK lock */
8900 + struct list_head sc_pkq; /* queue of PK requests */
8901 + struct safe_pkq *sc_pkq_cur; /* current processing request */
8902 + u_int32_t sc_pk_reslen, sc_pk_resoff;
8903 +
8904 + int sc_max_dsize; /* maximum safe DMA size */
8905 +};
8906 +#endif /* __KERNEL__ */
8907 +
8908 +struct safe_stats {
8909 + u_int64_t st_ibytes;
8910 + u_int64_t st_obytes;
8911 + u_int32_t st_ipackets;
8912 + u_int32_t st_opackets;
8913 + u_int32_t st_invalid; /* invalid argument */
8914 + u_int32_t st_badsession; /* invalid session id */
8915 + u_int32_t st_badflags; /* flags indicate !(mbuf | uio) */
8916 + u_int32_t st_nodesc; /* op submitted w/o descriptors */
8917 + u_int32_t st_badalg; /* unsupported algorithm */
8918 + u_int32_t st_ringfull; /* PE descriptor ring full */
8919 + u_int32_t st_peoperr; /* PE marked error */
8920 + u_int32_t st_dmaerr; /* PE DMA error */
8921 + u_int32_t st_bypasstoobig; /* bypass > 96 bytes */
8922 + u_int32_t st_skipmismatch; /* enc part begins before auth part */
8923 + u_int32_t st_lenmismatch; /* enc length different auth length */
8924 + u_int32_t st_coffmisaligned; /* crypto offset not 32-bit aligned */
8925 + u_int32_t st_cofftoobig; /* crypto offset > 255 words */
8926 + u_int32_t st_iovmisaligned; /* iov op not aligned */
8927 + u_int32_t st_iovnotuniform; /* iov op not suitable */
8928 + u_int32_t st_unaligned; /* unaligned src caused copy */
8929 + u_int32_t st_notuniform; /* non-uniform src caused copy */
8930 + u_int32_t st_nomap; /* bus_dmamap_create failed */
8931 + u_int32_t st_noload; /* bus_dmamap_load_* failed */
8932 + u_int32_t st_nombuf; /* MGET* failed */
8933 + u_int32_t st_nomcl; /* MCLGET* failed */
8934 + u_int32_t st_maxqchip; /* max mcr1 ops out for processing */
8935 + u_int32_t st_rng; /* RNG requests */
8936 + u_int32_t st_rngalarm; /* RNG alarm requests */
8937 + u_int32_t st_noicvcopy; /* ICV data copies suppressed */
8938 +};
8939 +#endif /* _SAFE_SAFEVAR_H_ */
8940 --- /dev/null
8941 +++ b/crypto/ocf/crypto.c
8942 @@ -0,0 +1,1741 @@
8943 +/*-
8944 + * Linux port done by David McCullough <david_mccullough@securecomputing.com>
8945 + * Copyright (C) 2006-2007 David McCullough
8946 + * Copyright (C) 2004-2005 Intel Corporation.
8947 + * The license and original author are listed below.
8948 + *
8949 + * Redistribution and use in source and binary forms, with or without
8950 + * Copyright (c) 2002-2006 Sam Leffler. All rights reserved.
8951 + *
8952 + * modification, are permitted provided that the following conditions
8953 + * are met:
8954 + * 1. Redistributions of source code must retain the above copyright
8955 + * notice, this list of conditions and the following disclaimer.
8956 + * 2. Redistributions in binary form must reproduce the above copyright
8957 + * notice, this list of conditions and the following disclaimer in the
8958 + * documentation and/or other materials provided with the distribution.
8959 + *
8960 + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
8961 + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
8962 + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
8963 + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
8964 + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
8965 + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
8966 + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
8967 + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
8968 + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
8969 + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
8970 + */
8971 +
8972 +#if 0
8973 +#include <sys/cdefs.h>
8974 +__FBSDID("$FreeBSD: src/sys/opencrypto/crypto.c,v 1.27 2007/03/21 03:42:51 sam Exp $");
8975 +#endif
8976 +
8977 +/*
8978 + * Cryptographic Subsystem.
8979 + *
8980 + * This code is derived from the Openbsd Cryptographic Framework (OCF)
8981 + * that has the copyright shown below. Very little of the original
8982 + * code remains.
8983 + */
8984 +/*-
8985 + * The author of this code is Angelos D. Keromytis (angelos@cis.upenn.edu)
8986 + *
8987 + * This code was written by Angelos D. Keromytis in Athens, Greece, in
8988 + * February 2000. Network Security Technologies Inc. (NSTI) kindly
8989 + * supported the development of this code.
8990 + *
8991 + * Copyright (c) 2000, 2001 Angelos D. Keromytis
8992 + *
8993 + * Permission to use, copy, and modify this software with or without fee
8994 + * is hereby granted, provided that this entire notice is included in
8995 + * all source code copies of any software which is or includes a copy or
8996 + * modification of this software.
8997 + *
8998 + * THIS SOFTWARE IS BEING PROVIDED "AS IS", WITHOUT ANY EXPRESS OR
8999 + * IMPLIED WARRANTY. IN PARTICULAR, NONE OF THE AUTHORS MAKES ANY
9000 + * REPRESENTATION OR WARRANTY OF ANY KIND CONCERNING THE
9001 + * MERCHANTABILITY OF THIS SOFTWARE OR ITS FITNESS FOR ANY PARTICULAR
9002 + * PURPOSE.
9003 + *
9004 +__FBSDID("$FreeBSD: src/sys/opencrypto/crypto.c,v 1.16 2005/01/07 02:29:16 imp Exp $");
9005 + */
9006 +
9007 +
9008 +#ifndef AUTOCONF_INCLUDED
9009 +#include <linux/config.h>
9010 +#endif
9011 +#include <linux/module.h>
9012 +#include <linux/init.h>
9013 +#include <linux/list.h>
9014 +#include <linux/slab.h>
9015 +#include <linux/wait.h>
9016 +#include <linux/sched.h>
9017 +#include <linux/spinlock.h>
9018 +#include <linux/version.h>
9019 +#include <cryptodev.h>
9020 +
9021 +/*
9022 + * keep track of whether or not we have been initialised, a big
9023 + * issue if we are linked into the kernel and a driver gets started before
9024 + * us
9025 + */
9026 +static int crypto_initted = 0;
9027 +
9028 +/*
9029 + * Crypto drivers register themselves by allocating a slot in the
9030 + * crypto_drivers table with crypto_get_driverid() and then registering
9031 + * each algorithm they support with crypto_register() and crypto_kregister().
9032 + */
9033 +
9034 +/*
9035 + * lock on driver table
9036 + * we track its state as spin_is_locked does not do anything on non-SMP boxes
9037 + */
9038 +static spinlock_t crypto_drivers_lock;
9039 +static int crypto_drivers_locked; /* for non-SMP boxes */
9040 +
9041 +#define CRYPTO_DRIVER_LOCK() \
9042 + ({ \
9043 + spin_lock_irqsave(&crypto_drivers_lock, d_flags); \
9044 + crypto_drivers_locked = 1; \
9045 + dprintk("%s,%d: DRIVER_LOCK()\n", __FILE__, __LINE__); \
9046 + })
9047 +#define CRYPTO_DRIVER_UNLOCK() \
9048 + ({ \
9049 + dprintk("%s,%d: DRIVER_UNLOCK()\n", __FILE__, __LINE__); \
9050 + crypto_drivers_locked = 0; \
9051 + spin_unlock_irqrestore(&crypto_drivers_lock, d_flags); \
9052 + })
9053 +#define CRYPTO_DRIVER_ASSERT() \
9054 + ({ \
9055 + if (!crypto_drivers_locked) { \
9056 + dprintk("%s,%d: DRIVER_ASSERT!\n", __FILE__, __LINE__); \
9057 + } \
9058 + })
9059 +
9060 +/*
9061 + * Crypto device/driver capabilities structure.
9062 + *
9063 + * Synchronization:
9064 + * (d) - protected by CRYPTO_DRIVER_LOCK()
9065 + * (q) - protected by CRYPTO_Q_LOCK()
9066 + * Not tagged fields are read-only.
9067 + */
9068 +struct cryptocap {
9069 + device_t cc_dev; /* (d) device/driver */
9070 + u_int32_t cc_sessions; /* (d) # of sessions */
9071 + u_int32_t cc_koperations; /* (d) # os asym operations */
9072 + /*
9073 + * Largest possible operator length (in bits) for each type of
9074 + * encryption algorithm. XXX not used
9075 + */
9076 + u_int16_t cc_max_op_len[CRYPTO_ALGORITHM_MAX + 1];
9077 + u_int8_t cc_alg[CRYPTO_ALGORITHM_MAX + 1];
9078 + u_int8_t cc_kalg[CRK_ALGORITHM_MAX + 1];
9079 +
9080 + int cc_flags; /* (d) flags */
9081 +#define CRYPTOCAP_F_CLEANUP 0x80000000 /* needs resource cleanup */
9082 + int cc_qblocked; /* (q) symmetric q blocked */
9083 + int cc_kqblocked; /* (q) asymmetric q blocked */
9084 +};
9085 +static struct cryptocap *crypto_drivers = NULL;
9086 +static int crypto_drivers_num = 0;
9087 +
9088 +/*
9089 + * There are two queues for crypto requests; one for symmetric (e.g.
9090 + * cipher) operations and one for asymmetric (e.g. MOD)operations.
9091 + * A single mutex is used to lock access to both queues. We could
9092 + * have one per-queue but having one simplifies handling of block/unblock
9093 + * operations.
9094 + */
9095 +static int crp_sleep = 0;
9096 +static LIST_HEAD(crp_q); /* request queues */
9097 +static LIST_HEAD(crp_kq);
9098 +
9099 +static spinlock_t crypto_q_lock;
9100 +
9101 +int crypto_all_qblocked = 0; /* protect with Q_LOCK */
9102 +module_param(crypto_all_qblocked, int, 0444);
9103 +MODULE_PARM_DESC(crypto_all_qblocked, "Are all crypto queues blocked");
9104 +
9105 +int crypto_all_kqblocked = 0; /* protect with Q_LOCK */
9106 +module_param(crypto_all_kqblocked, int, 0444);
9107 +MODULE_PARM_DESC(crypto_all_kqblocked, "Are all asym crypto queues blocked");
9108 +
9109 +#define CRYPTO_Q_LOCK() \
9110 + ({ \
9111 + spin_lock_irqsave(&crypto_q_lock, q_flags); \
9112 + dprintk("%s,%d: Q_LOCK()\n", __FILE__, __LINE__); \
9113 + })
9114 +#define CRYPTO_Q_UNLOCK() \
9115 + ({ \
9116 + dprintk("%s,%d: Q_UNLOCK()\n", __FILE__, __LINE__); \
9117 + spin_unlock_irqrestore(&crypto_q_lock, q_flags); \
9118 + })
9119 +
9120 +/*
9121 + * There are two queues for processing completed crypto requests; one
9122 + * for the symmetric and one for the asymmetric ops. We only need one
9123 + * but have two to avoid type futzing (cryptop vs. cryptkop). A single
9124 + * mutex is used to lock access to both queues. Note that this lock
9125 + * must be separate from the lock on request queues to insure driver
9126 + * callbacks don't generate lock order reversals.
9127 + */
9128 +static LIST_HEAD(crp_ret_q); /* callback queues */
9129 +static LIST_HEAD(crp_ret_kq);
9130 +
9131 +static spinlock_t crypto_ret_q_lock;
9132 +#define CRYPTO_RETQ_LOCK() \
9133 + ({ \
9134 + spin_lock_irqsave(&crypto_ret_q_lock, r_flags); \
9135 + dprintk("%s,%d: RETQ_LOCK\n", __FILE__, __LINE__); \
9136 + })
9137 +#define CRYPTO_RETQ_UNLOCK() \
9138 + ({ \
9139 + dprintk("%s,%d: RETQ_UNLOCK\n", __FILE__, __LINE__); \
9140 + spin_unlock_irqrestore(&crypto_ret_q_lock, r_flags); \
9141 + })
9142 +#define CRYPTO_RETQ_EMPTY() (list_empty(&crp_ret_q) && list_empty(&crp_ret_kq))
9143 +
9144 +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,20)
9145 +static kmem_cache_t *cryptop_zone;
9146 +static kmem_cache_t *cryptodesc_zone;
9147 +#else
9148 +static struct kmem_cache *cryptop_zone;
9149 +static struct kmem_cache *cryptodesc_zone;
9150 +#endif
9151 +
9152 +#define debug crypto_debug
9153 +int crypto_debug = 0;
9154 +module_param(crypto_debug, int, 0644);
9155 +MODULE_PARM_DESC(crypto_debug, "Enable debug");
9156 +EXPORT_SYMBOL(crypto_debug);
9157 +
9158 +/*
9159 + * Maximum number of outstanding crypto requests before we start
9160 + * failing requests. We need this to prevent DOS when too many
9161 + * requests are arriving for us to keep up. Otherwise we will
9162 + * run the system out of memory. Since crypto is slow, we are
9163 + * usually the bottleneck that needs to say, enough is enough.
9164 + *
9165 + * We cannot print errors when this condition occurs, we are already too
9166 + * slow, printing anything will just kill us
9167 + */
9168 +
9169 +static int crypto_q_cnt = 0;
9170 +module_param(crypto_q_cnt, int, 0444);
9171 +MODULE_PARM_DESC(crypto_q_cnt,
9172 + "Current number of outstanding crypto requests");
9173 +
9174 +static int crypto_q_max = 1000;
9175 +module_param(crypto_q_max, int, 0644);
9176 +MODULE_PARM_DESC(crypto_q_max,
9177 + "Maximum number of outstanding crypto requests");
9178 +
9179 +#define bootverbose crypto_verbose
9180 +static int crypto_verbose = 0;
9181 +module_param(crypto_verbose, int, 0644);
9182 +MODULE_PARM_DESC(crypto_verbose,
9183 + "Enable verbose crypto startup");
9184 +
9185 +int crypto_usercrypto = 1; /* userland may do crypto reqs */
9186 +module_param(crypto_usercrypto, int, 0644);
9187 +MODULE_PARM_DESC(crypto_usercrypto,
9188 + "Enable/disable user-mode access to crypto support");
9189 +
9190 +int crypto_userasymcrypto = 1; /* userland may do asym crypto reqs */
9191 +module_param(crypto_userasymcrypto, int, 0644);
9192 +MODULE_PARM_DESC(crypto_userasymcrypto,
9193 + "Enable/disable user-mode access to asymmetric crypto support");
9194 +
9195 +int crypto_devallowsoft = 0; /* only use hardware crypto */
9196 +module_param(crypto_devallowsoft, int, 0644);
9197 +MODULE_PARM_DESC(crypto_devallowsoft,
9198 + "Enable/disable use of software crypto support");
9199 +
9200 +static pid_t cryptoproc = (pid_t) -1;
9201 +static struct completion cryptoproc_exited;
9202 +static DECLARE_WAIT_QUEUE_HEAD(cryptoproc_wait);
9203 +static pid_t cryptoretproc = (pid_t) -1;
9204 +static struct completion cryptoretproc_exited;
9205 +static DECLARE_WAIT_QUEUE_HEAD(cryptoretproc_wait);
9206 +
9207 +static int crypto_proc(void *arg);
9208 +static int crypto_ret_proc(void *arg);
9209 +static int crypto_invoke(struct cryptocap *cap, struct cryptop *crp, int hint);
9210 +static int crypto_kinvoke(struct cryptkop *krp, int flags);
9211 +static void crypto_exit(void);
9212 +static int crypto_init(void);
9213 +
9214 +static struct cryptostats cryptostats;
9215 +
9216 +static struct cryptocap *
9217 +crypto_checkdriver(u_int32_t hid)
9218 +{
9219 + if (crypto_drivers == NULL)
9220 + return NULL;
9221 + return (hid >= crypto_drivers_num ? NULL : &crypto_drivers[hid]);
9222 +}
9223 +
9224 +/*
9225 + * Compare a driver's list of supported algorithms against another
9226 + * list; return non-zero if all algorithms are supported.
9227 + */
9228 +static int
9229 +driver_suitable(const struct cryptocap *cap, const struct cryptoini *cri)
9230 +{
9231 + const struct cryptoini *cr;
9232 +
9233 + /* See if all the algorithms are supported. */
9234 + for (cr = cri; cr; cr = cr->cri_next)
9235 + if (cap->cc_alg[cr->cri_alg] == 0)
9236 + return 0;
9237 + return 1;
9238 +}
9239 +
9240 +/*
9241 + * Select a driver for a new session that supports the specified
9242 + * algorithms and, optionally, is constrained according to the flags.
9243 + * The algorithm we use here is pretty stupid; just use the
9244 + * first driver that supports all the algorithms we need. If there
9245 + * are multiple drivers we choose the driver with the fewest active
9246 + * sessions. We prefer hardware-backed drivers to software ones.
9247 + *
9248 + * XXX We need more smarts here (in real life too, but that's
9249 + * XXX another story altogether).
9250 + */
9251 +static struct cryptocap *
9252 +crypto_select_driver(const struct cryptoini *cri, int flags)
9253 +{
9254 + struct cryptocap *cap, *best;
9255 + int match, hid;
9256 +
9257 + CRYPTO_DRIVER_ASSERT();
9258 +
9259 + /*
9260 + * Look first for hardware crypto devices if permitted.
9261 + */
9262 + if (flags & CRYPTOCAP_F_HARDWARE)
9263 + match = CRYPTOCAP_F_HARDWARE;
9264 + else
9265 + match = CRYPTOCAP_F_SOFTWARE;
9266 + best = NULL;
9267 +again:
9268 + for (hid = 0; hid < crypto_drivers_num; hid++) {
9269 + cap = &crypto_drivers[hid];
9270 + /*
9271 + * If it's not initialized, is in the process of
9272 + * going away, or is not appropriate (hardware
9273 + * or software based on match), then skip.
9274 + */
9275 + if (cap->cc_dev == NULL ||
9276 + (cap->cc_flags & CRYPTOCAP_F_CLEANUP) ||
9277 + (cap->cc_flags & match) == 0)
9278 + continue;
9279 +
9280 + /* verify all the algorithms are supported. */
9281 + if (driver_suitable(cap, cri)) {
9282 + if (best == NULL ||
9283 + cap->cc_sessions < best->cc_sessions)
9284 + best = cap;
9285 + }
9286 + }
9287 + if (best != NULL)
9288 + return best;
9289 + if (match == CRYPTOCAP_F_HARDWARE && (flags & CRYPTOCAP_F_SOFTWARE)) {
9290 + /* sort of an Algol 68-style for loop */
9291 + match = CRYPTOCAP_F_SOFTWARE;
9292 + goto again;
9293 + }
9294 + return best;
9295 +}
9296 +
9297 +/*
9298 + * Create a new session. The crid argument specifies a crypto
9299 + * driver to use or constraints on a driver to select (hardware
9300 + * only, software only, either). Whatever driver is selected
9301 + * must be capable of the requested crypto algorithms.
9302 + */
9303 +int
9304 +crypto_newsession(u_int64_t *sid, struct cryptoini *cri, int crid)
9305 +{
9306 + struct cryptocap *cap;
9307 + u_int32_t hid, lid;
9308 + int err;
9309 + unsigned long d_flags;
9310 +
9311 + CRYPTO_DRIVER_LOCK();
9312 + if ((crid & (CRYPTOCAP_F_HARDWARE | CRYPTOCAP_F_SOFTWARE)) == 0) {
9313 + /*
9314 + * Use specified driver; verify it is capable.
9315 + */
9316 + cap = crypto_checkdriver(crid);
9317 + if (cap != NULL && !driver_suitable(cap, cri))
9318 + cap = NULL;
9319 + } else {
9320 + /*
9321 + * No requested driver; select based on crid flags.
9322 + */
9323 + cap = crypto_select_driver(cri, crid);
9324 + /*
9325 + * if NULL then can't do everything in one session.
9326 + * XXX Fix this. We need to inject a "virtual" session
9327 + * XXX layer right about here.
9328 + */
9329 + }
9330 + if (cap != NULL) {
9331 + /* Call the driver initialization routine. */
9332 + hid = cap - crypto_drivers;
9333 + lid = hid; /* Pass the driver ID. */
9334 + cap->cc_sessions++;
9335 + CRYPTO_DRIVER_UNLOCK();
9336 + err = CRYPTODEV_NEWSESSION(cap->cc_dev, &lid, cri);
9337 + CRYPTO_DRIVER_LOCK();
9338 + if (err == 0) {
9339 + (*sid) = (cap->cc_flags & 0xff000000)
9340 + | (hid & 0x00ffffff);
9341 + (*sid) <<= 32;
9342 + (*sid) |= (lid & 0xffffffff);
9343 + } else
9344 + cap->cc_sessions--;
9345 + } else
9346 + err = EINVAL;
9347 + CRYPTO_DRIVER_UNLOCK();
9348 + return err;
9349 +}
9350 +
9351 +static void
9352 +crypto_remove(struct cryptocap *cap)
9353 +{
9354 + CRYPTO_DRIVER_ASSERT();
9355 + if (cap->cc_sessions == 0 && cap->cc_koperations == 0)
9356 + bzero(cap, sizeof(*cap));
9357 +}
9358 +
9359 +/*
9360 + * Delete an existing session (or a reserved session on an unregistered
9361 + * driver).
9362 + */
9363 +int
9364 +crypto_freesession(u_int64_t sid)
9365 +{
9366 + struct cryptocap *cap;
9367 + u_int32_t hid;
9368 + int err = 0;
9369 + unsigned long d_flags;
9370 +
9371 + dprintk("%s()\n", __FUNCTION__);
9372 + CRYPTO_DRIVER_LOCK();
9373 +
9374 + if (crypto_drivers == NULL) {
9375 + err = EINVAL;
9376 + goto done;
9377 + }
9378 +
9379 + /* Determine two IDs. */
9380 + hid = CRYPTO_SESID2HID(sid);
9381 +
9382 + if (hid >= crypto_drivers_num) {
9383 + dprintk("%s - INVALID DRIVER NUM %d\n", __FUNCTION__, hid);
9384 + err = ENOENT;
9385 + goto done;
9386 + }
9387 + cap = &crypto_drivers[hid];
9388 +
9389 + if (cap->cc_dev) {
9390 + CRYPTO_DRIVER_UNLOCK();
9391 + /* Call the driver cleanup routine, if available, unlocked. */
9392 + err = CRYPTODEV_FREESESSION(cap->cc_dev, sid);
9393 + CRYPTO_DRIVER_LOCK();
9394 + }
9395 +
9396 + if (cap->cc_sessions)
9397 + cap->cc_sessions--;
9398 +
9399 + if (cap->cc_flags & CRYPTOCAP_F_CLEANUP)
9400 + crypto_remove(cap);
9401 +
9402 +done:
9403 + CRYPTO_DRIVER_UNLOCK();
9404 + return err;
9405 +}
9406 +
9407 +/*
9408 + * Return an unused driver id. Used by drivers prior to registering
9409 + * support for the algorithms they handle.
9410 + */
9411 +int32_t
9412 +crypto_get_driverid(device_t dev, int flags)
9413 +{
9414 + struct cryptocap *newdrv;
9415 + int i;
9416 + unsigned long d_flags;
9417 +
9418 + if ((flags & (CRYPTOCAP_F_HARDWARE | CRYPTOCAP_F_SOFTWARE)) == 0) {
9419 + printf("%s: no flags specified when registering driver\n",
9420 + device_get_nameunit(dev));
9421 + return -1;
9422 + }
9423 +
9424 + CRYPTO_DRIVER_LOCK();
9425 +
9426 + for (i = 0; i < crypto_drivers_num; i++) {
9427 + if (crypto_drivers[i].cc_dev == NULL &&
9428 + (crypto_drivers[i].cc_flags & CRYPTOCAP_F_CLEANUP) == 0) {
9429 + break;
9430 + }
9431 + }
9432 +
9433 + /* Out of entries, allocate some more. */
9434 + if (i == crypto_drivers_num) {
9435 + /* Be careful about wrap-around. */
9436 + if (2 * crypto_drivers_num <= crypto_drivers_num) {
9437 + CRYPTO_DRIVER_UNLOCK();
9438 + printk("crypto: driver count wraparound!\n");
9439 + return -1;
9440 + }
9441 +
9442 + newdrv = kmalloc(2 * crypto_drivers_num * sizeof(struct cryptocap),
9443 + GFP_KERNEL);
9444 + if (newdrv == NULL) {
9445 + CRYPTO_DRIVER_UNLOCK();
9446 + printk("crypto: no space to expand driver table!\n");
9447 + return -1;
9448 + }
9449 +
9450 + memcpy(newdrv, crypto_drivers,
9451 + crypto_drivers_num * sizeof(struct cryptocap));
9452 + memset(&newdrv[crypto_drivers_num], 0,
9453 + crypto_drivers_num * sizeof(struct cryptocap));
9454 +
9455 + crypto_drivers_num *= 2;
9456 +
9457 + kfree(crypto_drivers);
9458 + crypto_drivers = newdrv;
9459 + }
9460 +
9461 + /* NB: state is zero'd on free */
9462 + crypto_drivers[i].cc_sessions = 1; /* Mark */
9463 + crypto_drivers[i].cc_dev = dev;
9464 + crypto_drivers[i].cc_flags = flags;
9465 + if (bootverbose)
9466 + printf("crypto: assign %s driver id %u, flags %u\n",
9467 + device_get_nameunit(dev), i, flags);
9468 +
9469 + CRYPTO_DRIVER_UNLOCK();
9470 +
9471 + return i;
9472 +}
9473 +
9474 +/*
9475 + * Lookup a driver by name. We match against the full device
9476 + * name and unit, and against just the name. The latter gives
9477 + * us a simple widlcarding by device name. On success return the
9478 + * driver/hardware identifier; otherwise return -1.
9479 + */
9480 +int
9481 +crypto_find_driver(const char *match)
9482 +{
9483 + int i, len = strlen(match);
9484 + unsigned long d_flags;
9485 +
9486 + CRYPTO_DRIVER_LOCK();
9487 + for (i = 0; i < crypto_drivers_num; i++) {
9488 + device_t dev = crypto_drivers[i].cc_dev;
9489 + if (dev == NULL ||
9490 + (crypto_drivers[i].cc_flags & CRYPTOCAP_F_CLEANUP))
9491 + continue;
9492 + if (strncmp(match, device_get_nameunit(dev), len) == 0 ||
9493 + strncmp(match, device_get_name(dev), len) == 0)
9494 + break;
9495 + }
9496 + CRYPTO_DRIVER_UNLOCK();
9497 + return i < crypto_drivers_num ? i : -1;
9498 +}
9499 +
9500 +/*
9501 + * Return the device_t for the specified driver or NULL
9502 + * if the driver identifier is invalid.
9503 + */
9504 +device_t
9505 +crypto_find_device_byhid(int hid)
9506 +{
9507 + struct cryptocap *cap = crypto_checkdriver(hid);
9508 + return cap != NULL ? cap->cc_dev : NULL;
9509 +}
9510 +
9511 +/*
9512 + * Return the device/driver capabilities.
9513 + */
9514 +int
9515 +crypto_getcaps(int hid)
9516 +{
9517 + struct cryptocap *cap = crypto_checkdriver(hid);
9518 + return cap != NULL ? cap->cc_flags : 0;
9519 +}
9520 +
9521 +/*
9522 + * Register support for a key-related algorithm. This routine
9523 + * is called once for each algorithm supported a driver.
9524 + */
9525 +int
9526 +crypto_kregister(u_int32_t driverid, int kalg, u_int32_t flags)
9527 +{
9528 + struct cryptocap *cap;
9529 + int err;
9530 + unsigned long d_flags;
9531 +
9532 + dprintk("%s()\n", __FUNCTION__);
9533 + CRYPTO_DRIVER_LOCK();
9534 +
9535 + cap = crypto_checkdriver(driverid);
9536 + if (cap != NULL &&
9537 + (CRK_ALGORITM_MIN <= kalg && kalg <= CRK_ALGORITHM_MAX)) {
9538 + /*
9539 + * XXX Do some performance testing to determine placing.
9540 + * XXX We probably need an auxiliary data structure that
9541 + * XXX describes relative performances.
9542 + */
9543 +
9544 + cap->cc_kalg[kalg] = flags | CRYPTO_ALG_FLAG_SUPPORTED;
9545 + if (bootverbose)
9546 + printf("crypto: %s registers key alg %u flags %u\n"
9547 + , device_get_nameunit(cap->cc_dev)
9548 + , kalg
9549 + , flags
9550 + );
9551 + err = 0;
9552 + } else
9553 + err = EINVAL;
9554 +
9555 + CRYPTO_DRIVER_UNLOCK();
9556 + return err;
9557 +}
9558 +
9559 +/*
9560 + * Register support for a non-key-related algorithm. This routine
9561 + * is called once for each such algorithm supported by a driver.
9562 + */
9563 +int
9564 +crypto_register(u_int32_t driverid, int alg, u_int16_t maxoplen,
9565 + u_int32_t flags)
9566 +{
9567 + struct cryptocap *cap;
9568 + int err;
9569 + unsigned long d_flags;
9570 +
9571 + dprintk("%s(id=0x%x, alg=%d, maxoplen=%d, flags=0x%x)\n", __FUNCTION__,
9572 + driverid, alg, maxoplen, flags);
9573 +
9574 + CRYPTO_DRIVER_LOCK();
9575 +
9576 + cap = crypto_checkdriver(driverid);
9577 + /* NB: algorithms are in the range [1..max] */
9578 + if (cap != NULL &&
9579 + (CRYPTO_ALGORITHM_MIN <= alg && alg <= CRYPTO_ALGORITHM_MAX)) {
9580 + /*
9581 + * XXX Do some performance testing to determine placing.
9582 + * XXX We probably need an auxiliary data structure that
9583 + * XXX describes relative performances.
9584 + */
9585 +
9586 + cap->cc_alg[alg] = flags | CRYPTO_ALG_FLAG_SUPPORTED;
9587 + cap->cc_max_op_len[alg] = maxoplen;
9588 + if (bootverbose)
9589 + printf("crypto: %s registers alg %u flags %u maxoplen %u\n"
9590 + , device_get_nameunit(cap->cc_dev)
9591 + , alg
9592 + , flags
9593 + , maxoplen
9594 + );
9595 + cap->cc_sessions = 0; /* Unmark */
9596 + err = 0;
9597 + } else
9598 + err = EINVAL;
9599 +
9600 + CRYPTO_DRIVER_UNLOCK();
9601 + return err;
9602 +}
9603 +
9604 +static void
9605 +driver_finis(struct cryptocap *cap)
9606 +{
9607 + u_int32_t ses, kops;
9608 +
9609 + CRYPTO_DRIVER_ASSERT();
9610 +
9611 + ses = cap->cc_sessions;
9612 + kops = cap->cc_koperations;
9613 + bzero(cap, sizeof(*cap));
9614 + if (ses != 0 || kops != 0) {
9615 + /*
9616 + * If there are pending sessions,
9617 + * just mark as invalid.
9618 + */
9619 + cap->cc_flags |= CRYPTOCAP_F_CLEANUP;
9620 + cap->cc_sessions = ses;
9621 + cap->cc_koperations = kops;
9622 + }
9623 +}
9624 +
9625 +/*
9626 + * Unregister a crypto driver. If there are pending sessions using it,
9627 + * leave enough information around so that subsequent calls using those
9628 + * sessions will correctly detect the driver has been unregistered and
9629 + * reroute requests.
9630 + */
9631 +int
9632 +crypto_unregister(u_int32_t driverid, int alg)
9633 +{
9634 + struct cryptocap *cap;
9635 + int i, err;
9636 + unsigned long d_flags;
9637 +
9638 + dprintk("%s()\n", __FUNCTION__);
9639 + CRYPTO_DRIVER_LOCK();
9640 +
9641 + cap = crypto_checkdriver(driverid);
9642 + if (cap != NULL &&
9643 + (CRYPTO_ALGORITHM_MIN <= alg && alg <= CRYPTO_ALGORITHM_MAX) &&
9644 + cap->cc_alg[alg] != 0) {
9645 + cap->cc_alg[alg] = 0;
9646 + cap->cc_max_op_len[alg] = 0;
9647 +
9648 + /* Was this the last algorithm ? */
9649 + for (i = 1; i <= CRYPTO_ALGORITHM_MAX; i++)
9650 + if (cap->cc_alg[i] != 0)
9651 + break;
9652 +
9653 + if (i == CRYPTO_ALGORITHM_MAX + 1)
9654 + driver_finis(cap);
9655 + err = 0;
9656 + } else
9657 + err = EINVAL;
9658 + CRYPTO_DRIVER_UNLOCK();
9659 + return err;
9660 +}
9661 +
9662 +/*
9663 + * Unregister all algorithms associated with a crypto driver.
9664 + * If there are pending sessions using it, leave enough information
9665 + * around so that subsequent calls using those sessions will
9666 + * correctly detect the driver has been unregistered and reroute
9667 + * requests.
9668 + */
9669 +int
9670 +crypto_unregister_all(u_int32_t driverid)
9671 +{
9672 + struct cryptocap *cap;
9673 + int err;
9674 + unsigned long d_flags;
9675 +
9676 + dprintk("%s()\n", __FUNCTION__);
9677 + CRYPTO_DRIVER_LOCK();
9678 + cap = crypto_checkdriver(driverid);
9679 + if (cap != NULL) {
9680 + driver_finis(cap);
9681 + err = 0;
9682 + } else
9683 + err = EINVAL;
9684 + CRYPTO_DRIVER_UNLOCK();
9685 +
9686 + return err;
9687 +}
9688 +
9689 +/*
9690 + * Clear blockage on a driver. The what parameter indicates whether
9691 + * the driver is now ready for cryptop's and/or cryptokop's.
9692 + */
9693 +int
9694 +crypto_unblock(u_int32_t driverid, int what)
9695 +{
9696 + struct cryptocap *cap;
9697 + int err;
9698 + unsigned long q_flags;
9699 +
9700 + CRYPTO_Q_LOCK();
9701 + cap = crypto_checkdriver(driverid);
9702 + if (cap != NULL) {
9703 + if (what & CRYPTO_SYMQ) {
9704 + cap->cc_qblocked = 0;
9705 + crypto_all_qblocked = 0;
9706 + }
9707 + if (what & CRYPTO_ASYMQ) {
9708 + cap->cc_kqblocked = 0;
9709 + crypto_all_kqblocked = 0;
9710 + }
9711 + if (crp_sleep)
9712 + wake_up_interruptible(&cryptoproc_wait);
9713 + err = 0;
9714 + } else
9715 + err = EINVAL;
9716 + CRYPTO_Q_UNLOCK(); //DAVIDM should this be a driver lock
9717 +
9718 + return err;
9719 +}
9720 +
9721 +/*
9722 + * Add a crypto request to a queue, to be processed by the kernel thread.
9723 + */
9724 +int
9725 +crypto_dispatch(struct cryptop *crp)
9726 +{
9727 + struct cryptocap *cap;
9728 + int result = -1;
9729 + unsigned long q_flags;
9730 +
9731 + dprintk("%s()\n", __FUNCTION__);
9732 +
9733 + cryptostats.cs_ops++;
9734 +
9735 + CRYPTO_Q_LOCK();
9736 + if (crypto_q_cnt >= crypto_q_max) {
9737 + CRYPTO_Q_UNLOCK();
9738 + cryptostats.cs_drops++;
9739 + return ENOMEM;
9740 + }
9741 + crypto_q_cnt++;
9742 +
9743 + /*
9744 + * Caller marked the request to be processed immediately; dispatch
9745 + * it directly to the driver unless the driver is currently blocked.
9746 + */
9747 + if ((crp->crp_flags & CRYPTO_F_BATCH) == 0) {
9748 + int hid = CRYPTO_SESID2HID(crp->crp_sid);
9749 + cap = crypto_checkdriver(hid);
9750 + /* Driver cannot disappear when there is an active session. */
9751 + KASSERT(cap != NULL, ("%s: Driver disappeared.", __func__));
9752 + if (!cap->cc_qblocked) {
9753 + crypto_all_qblocked = 0;
9754 + crypto_drivers[hid].cc_qblocked = 1;
9755 + CRYPTO_Q_UNLOCK();
9756 + result = crypto_invoke(cap, crp, 0);
9757 + CRYPTO_Q_LOCK();
9758 + if (result != ERESTART)
9759 + crypto_drivers[hid].cc_qblocked = 0;
9760 + }
9761 + }
9762 + if (result == ERESTART) {
9763 + /*
9764 + * The driver ran out of resources, mark the
9765 + * driver ``blocked'' for cryptop's and put
9766 + * the request back in the queue. It would
9767 + * best to put the request back where we got
9768 + * it but that's hard so for now we put it
9769 + * at the front. This should be ok; putting
9770 + * it at the end does not work.
9771 + */
9772 + list_add(&crp->crp_next, &crp_q);
9773 + cryptostats.cs_blocks++;
9774 + } else if (result == -1) {
9775 + TAILQ_INSERT_TAIL(&crp_q, crp, crp_next);
9776 + }
9777 + if (crp_sleep)
9778 + wake_up_interruptible(&cryptoproc_wait);
9779 + CRYPTO_Q_UNLOCK();
9780 + return 0;
9781 +}
9782 +
9783 +/*
9784 + * Add an asymetric crypto request to a queue,
9785 + * to be processed by the kernel thread.
9786 + */
9787 +int
9788 +crypto_kdispatch(struct cryptkop *krp)
9789 +{
9790 + int error;
9791 + unsigned long q_flags;
9792 +
9793 + cryptostats.cs_kops++;
9794 +
9795 + error = crypto_kinvoke(krp, krp->krp_crid);
9796 + if (error == ERESTART) {
9797 + CRYPTO_Q_LOCK();
9798 + TAILQ_INSERT_TAIL(&crp_kq, krp, krp_next);
9799 + if (crp_sleep)
9800 + wake_up_interruptible(&cryptoproc_wait);
9801 + CRYPTO_Q_UNLOCK();
9802 + error = 0;
9803 + }
9804 + return error;
9805 +}
9806 +
9807 +/*
9808 + * Verify a driver is suitable for the specified operation.
9809 + */
9810 +static __inline int
9811 +kdriver_suitable(const struct cryptocap *cap, const struct cryptkop *krp)
9812 +{
9813 + return (cap->cc_kalg[krp->krp_op] & CRYPTO_ALG_FLAG_SUPPORTED) != 0;
9814 +}
9815 +
9816 +/*
9817 + * Select a driver for an asym operation. The driver must
9818 + * support the necessary algorithm. The caller can constrain
9819 + * which device is selected with the flags parameter. The
9820 + * algorithm we use here is pretty stupid; just use the first
9821 + * driver that supports the algorithms we need. If there are
9822 + * multiple suitable drivers we choose the driver with the
9823 + * fewest active operations. We prefer hardware-backed
9824 + * drivers to software ones when either may be used.
9825 + */
9826 +static struct cryptocap *
9827 +crypto_select_kdriver(const struct cryptkop *krp, int flags)
9828 +{
9829 + struct cryptocap *cap, *best, *blocked;
9830 + int match, hid;
9831 +
9832 + CRYPTO_DRIVER_ASSERT();
9833 +
9834 + /*
9835 + * Look first for hardware crypto devices if permitted.
9836 + */
9837 + if (flags & CRYPTOCAP_F_HARDWARE)
9838 + match = CRYPTOCAP_F_HARDWARE;
9839 + else
9840 + match = CRYPTOCAP_F_SOFTWARE;
9841 + best = NULL;
9842 + blocked = NULL;
9843 +again:
9844 + for (hid = 0; hid < crypto_drivers_num; hid++) {
9845 + cap = &crypto_drivers[hid];
9846 + /*
9847 + * If it's not initialized, is in the process of
9848 + * going away, or is not appropriate (hardware
9849 + * or software based on match), then skip.
9850 + */
9851 + if (cap->cc_dev == NULL ||
9852 + (cap->cc_flags & CRYPTOCAP_F_CLEANUP) ||
9853 + (cap->cc_flags & match) == 0)
9854 + continue;
9855 +
9856 + /* verify all the algorithms are supported. */
9857 + if (kdriver_suitable(cap, krp)) {
9858 + if (best == NULL ||
9859 + cap->cc_koperations < best->cc_koperations)
9860 + best = cap;
9861 + }
9862 + }
9863 + if (best != NULL)
9864 + return best;
9865 + if (match == CRYPTOCAP_F_HARDWARE && (flags & CRYPTOCAP_F_SOFTWARE)) {
9866 + /* sort of an Algol 68-style for loop */
9867 + match = CRYPTOCAP_F_SOFTWARE;
9868 + goto again;
9869 + }
9870 + return best;
9871 +}
9872 +
9873 +/*
9874 + * Dispatch an assymetric crypto request.
9875 + */
9876 +static int
9877 +crypto_kinvoke(struct cryptkop *krp, int crid)
9878 +{
9879 + struct cryptocap *cap = NULL;
9880 + int error;
9881 + unsigned long d_flags;
9882 +
9883 + KASSERT(krp != NULL, ("%s: krp == NULL", __func__));
9884 + KASSERT(krp->krp_callback != NULL,
9885 + ("%s: krp->crp_callback == NULL", __func__));
9886 +
9887 + CRYPTO_DRIVER_LOCK();
9888 + if ((crid & (CRYPTOCAP_F_HARDWARE | CRYPTOCAP_F_SOFTWARE)) == 0) {
9889 + cap = crypto_checkdriver(crid);
9890 + if (cap != NULL) {
9891 + /*
9892 + * Driver present, it must support the necessary
9893 + * algorithm and, if s/w drivers are excluded,
9894 + * it must be registered as hardware-backed.
9895 + */
9896 + if (!kdriver_suitable(cap, krp) ||
9897 + (!crypto_devallowsoft &&
9898 + (cap->cc_flags & CRYPTOCAP_F_HARDWARE) == 0))
9899 + cap = NULL;
9900 + }
9901 + } else {
9902 + /*
9903 + * No requested driver; select based on crid flags.
9904 + */
9905 + if (!crypto_devallowsoft) /* NB: disallow s/w drivers */
9906 + crid &= ~CRYPTOCAP_F_SOFTWARE;
9907 + cap = crypto_select_kdriver(krp, crid);
9908 + }
9909 + if (cap != NULL && !cap->cc_kqblocked) {
9910 + krp->krp_hid = cap - crypto_drivers;
9911 + cap->cc_koperations++;
9912 + CRYPTO_DRIVER_UNLOCK();
9913 + error = CRYPTODEV_KPROCESS(cap->cc_dev, krp, 0);
9914 + CRYPTO_DRIVER_LOCK();
9915 + if (error == ERESTART) {
9916 + cap->cc_koperations--;
9917 + CRYPTO_DRIVER_UNLOCK();
9918 + return (error);
9919 + }
9920 + /* return the actual device used */
9921 + krp->krp_crid = krp->krp_hid;
9922 + } else {
9923 + /*
9924 + * NB: cap is !NULL if device is blocked; in
9925 + * that case return ERESTART so the operation
9926 + * is resubmitted if possible.
9927 + */
9928 + error = (cap == NULL) ? ENODEV : ERESTART;
9929 + }
9930 + CRYPTO_DRIVER_UNLOCK();
9931 +
9932 + if (error) {
9933 + krp->krp_status = error;
9934 + crypto_kdone(krp);
9935 + }
9936 + return 0;
9937 +}
9938 +
9939 +
9940 +/*
9941 + * Dispatch a crypto request to the appropriate crypto devices.
9942 + */
9943 +static int
9944 +crypto_invoke(struct cryptocap *cap, struct cryptop *crp, int hint)
9945 +{
9946 + KASSERT(crp != NULL, ("%s: crp == NULL", __func__));
9947 + KASSERT(crp->crp_callback != NULL,
9948 + ("%s: crp->crp_callback == NULL", __func__));
9949 + KASSERT(crp->crp_desc != NULL, ("%s: crp->crp_desc == NULL", __func__));
9950 +
9951 + dprintk("%s()\n", __FUNCTION__);
9952 +
9953 +#ifdef CRYPTO_TIMING
9954 + if (crypto_timing)
9955 + crypto_tstat(&cryptostats.cs_invoke, &crp->crp_tstamp);
9956 +#endif
9957 + if (cap->cc_flags & CRYPTOCAP_F_CLEANUP) {
9958 + struct cryptodesc *crd;
9959 + u_int64_t nid;
9960 +
9961 + /*
9962 + * Driver has unregistered; migrate the session and return
9963 + * an error to the caller so they'll resubmit the op.
9964 + *
9965 + * XXX: What if there are more already queued requests for this
9966 + * session?
9967 + */
9968 + crypto_freesession(crp->crp_sid);
9969 +
9970 + for (crd = crp->crp_desc; crd->crd_next; crd = crd->crd_next)
9971 + crd->CRD_INI.cri_next = &(crd->crd_next->CRD_INI);
9972 +
9973 + /* XXX propagate flags from initial session? */
9974 + if (crypto_newsession(&nid, &(crp->crp_desc->CRD_INI),
9975 + CRYPTOCAP_F_HARDWARE | CRYPTOCAP_F_SOFTWARE) == 0)
9976 + crp->crp_sid = nid;
9977 +
9978 + crp->crp_etype = EAGAIN;
9979 + crypto_done(crp);
9980 + return 0;
9981 + } else {
9982 + /*
9983 + * Invoke the driver to process the request.
9984 + */
9985 + return CRYPTODEV_PROCESS(cap->cc_dev, crp, hint);
9986 + }
9987 +}
9988 +
9989 +/*
9990 + * Release a set of crypto descriptors.
9991 + */
9992 +void
9993 +crypto_freereq(struct cryptop *crp)
9994 +{
9995 + struct cryptodesc *crd;
9996 +
9997 + if (crp == NULL)
9998 + return;
9999 +
10000 +#ifdef DIAGNOSTIC
10001 + {
10002 + struct cryptop *crp2;
10003 + unsigned long q_flags;
10004 +
10005 + CRYPTO_Q_LOCK();
10006 + TAILQ_FOREACH(crp2, &crp_q, crp_next) {
10007 + KASSERT(crp2 != crp,
10008 + ("Freeing cryptop from the crypto queue (%p).",
10009 + crp));
10010 + }
10011 + CRYPTO_Q_UNLOCK();
10012 + CRYPTO_RETQ_LOCK();
10013 + TAILQ_FOREACH(crp2, &crp_ret_q, crp_next) {
10014 + KASSERT(crp2 != crp,
10015 + ("Freeing cryptop from the return queue (%p).",
10016 + crp));
10017 + }
10018 + CRYPTO_RETQ_UNLOCK();
10019 + }
10020 +#endif
10021 +
10022 + while ((crd = crp->crp_desc) != NULL) {
10023 + crp->crp_desc = crd->crd_next;
10024 + kmem_cache_free(cryptodesc_zone, crd);
10025 + }
10026 + kmem_cache_free(cryptop_zone, crp);
10027 +}
10028 +
10029 +/*
10030 + * Acquire a set of crypto descriptors.
10031 + */
10032 +struct cryptop *
10033 +crypto_getreq(int num)
10034 +{
10035 + struct cryptodesc *crd;
10036 + struct cryptop *crp;
10037 +
10038 + crp = kmem_cache_alloc(cryptop_zone, SLAB_ATOMIC);
10039 + if (crp != NULL) {
10040 + memset(crp, 0, sizeof(*crp));
10041 + INIT_LIST_HEAD(&crp->crp_next);
10042 + init_waitqueue_head(&crp->crp_waitq);
10043 + while (num--) {
10044 + crd = kmem_cache_alloc(cryptodesc_zone, SLAB_ATOMIC);
10045 + if (crd == NULL) {
10046 + crypto_freereq(crp);
10047 + return NULL;
10048 + }
10049 + memset(crd, 0, sizeof(*crd));
10050 + crd->crd_next = crp->crp_desc;
10051 + crp->crp_desc = crd;
10052 + }
10053 + }
10054 + return crp;
10055 +}
10056 +
10057 +/*
10058 + * Invoke the callback on behalf of the driver.
10059 + */
10060 +void
10061 +crypto_done(struct cryptop *crp)
10062 +{
10063 + unsigned long q_flags;
10064 +
10065 + dprintk("%s()\n", __FUNCTION__);
10066 + if ((crp->crp_flags & CRYPTO_F_DONE) == 0) {
10067 + crp->crp_flags |= CRYPTO_F_DONE;
10068 + CRYPTO_Q_LOCK();
10069 + crypto_q_cnt--;
10070 + CRYPTO_Q_UNLOCK();
10071 + } else
10072 + printk("crypto: crypto_done op already done, flags 0x%x",
10073 + crp->crp_flags);
10074 + if (crp->crp_etype != 0)
10075 + cryptostats.cs_errs++;
10076 + /*
10077 + * CBIMM means unconditionally do the callback immediately;
10078 + * CBIFSYNC means do the callback immediately only if the
10079 + * operation was done synchronously. Both are used to avoid
10080 + * doing extraneous context switches; the latter is mostly
10081 + * used with the software crypto driver.
10082 + */
10083 + if ((crp->crp_flags & CRYPTO_F_CBIMM) ||
10084 + ((crp->crp_flags & CRYPTO_F_CBIFSYNC) &&
10085 + (CRYPTO_SESID2CAPS(crp->crp_sid) & CRYPTOCAP_F_SYNC))) {
10086 + /*
10087 + * Do the callback directly. This is ok when the
10088 + * callback routine does very little (e.g. the
10089 + * /dev/crypto callback method just does a wakeup).
10090 + */
10091 + crp->crp_callback(crp);
10092 + } else {
10093 + unsigned long r_flags;
10094 + /*
10095 + * Normal case; queue the callback for the thread.
10096 + */
10097 + CRYPTO_RETQ_LOCK();
10098 + if (CRYPTO_RETQ_EMPTY())
10099 + wake_up_interruptible(&cryptoretproc_wait);/* shared wait channel */
10100 + TAILQ_INSERT_TAIL(&crp_ret_q, crp, crp_next);
10101 + CRYPTO_RETQ_UNLOCK();
10102 + }
10103 +}
10104 +
10105 +/*
10106 + * Invoke the callback on behalf of the driver.
10107 + */
10108 +void
10109 +crypto_kdone(struct cryptkop *krp)
10110 +{
10111 + struct cryptocap *cap;
10112 + unsigned long d_flags;
10113 +
10114 + if ((krp->krp_flags & CRYPTO_KF_DONE) != 0)
10115 + printk("crypto: crypto_kdone op already done, flags 0x%x",
10116 + krp->krp_flags);
10117 + krp->krp_flags |= CRYPTO_KF_DONE;
10118 + if (krp->krp_status != 0)
10119 + cryptostats.cs_kerrs++;
10120 +
10121 + CRYPTO_DRIVER_LOCK();
10122 + /* XXX: What if driver is loaded in the meantime? */
10123 + if (krp->krp_hid < crypto_drivers_num) {
10124 + cap = &crypto_drivers[krp->krp_hid];
10125 + cap->cc_koperations--;
10126 + KASSERT(cap->cc_koperations >= 0, ("cc_koperations < 0"));
10127 + if (cap->cc_flags & CRYPTOCAP_F_CLEANUP)
10128 + crypto_remove(cap);
10129 + }
10130 + CRYPTO_DRIVER_UNLOCK();
10131 +
10132 + /*
10133 + * CBIMM means unconditionally do the callback immediately;
10134 + * This is used to avoid doing extraneous context switches
10135 + */
10136 + if ((krp->krp_flags & CRYPTO_KF_CBIMM)) {
10137 + /*
10138 + * Do the callback directly. This is ok when the
10139 + * callback routine does very little (e.g. the
10140 + * /dev/crypto callback method just does a wakeup).
10141 + */
10142 + krp->krp_callback(krp);
10143 + } else {
10144 + unsigned long r_flags;
10145 + /*
10146 + * Normal case; queue the callback for the thread.
10147 + */
10148 + CRYPTO_RETQ_LOCK();
10149 + if (CRYPTO_RETQ_EMPTY())
10150 + wake_up_interruptible(&cryptoretproc_wait);/* shared wait channel */
10151 + TAILQ_INSERT_TAIL(&crp_ret_kq, krp, krp_next);
10152 + CRYPTO_RETQ_UNLOCK();
10153 + }
10154 +}
10155 +
10156 +int
10157 +crypto_getfeat(int *featp)
10158 +{
10159 + int hid, kalg, feat = 0;
10160 + unsigned long d_flags;
10161 +
10162 + CRYPTO_DRIVER_LOCK();
10163 + for (hid = 0; hid < crypto_drivers_num; hid++) {
10164 + const struct cryptocap *cap = &crypto_drivers[hid];
10165 +
10166 + if ((cap->cc_flags & CRYPTOCAP_F_SOFTWARE) &&
10167 + !crypto_devallowsoft) {
10168 + continue;
10169 + }
10170 + for (kalg = 0; kalg < CRK_ALGORITHM_MAX; kalg++)
10171 + if (cap->cc_kalg[kalg] & CRYPTO_ALG_FLAG_SUPPORTED)
10172 + feat |= 1 << kalg;
10173 + }
10174 + CRYPTO_DRIVER_UNLOCK();
10175 + *featp = feat;
10176 + return (0);
10177 +}
10178 +
10179 +/*
10180 + * Crypto thread, dispatches crypto requests.
10181 + */
10182 +static int
10183 +crypto_proc(void *arg)
10184 +{
10185 + struct cryptop *crp, *submit;
10186 + struct cryptkop *krp, *krpp;
10187 + struct cryptocap *cap;
10188 + u_int32_t hid;
10189 + int result, hint;
10190 + unsigned long q_flags;
10191 +
10192 + ocf_daemonize("crypto");
10193 +
10194 + CRYPTO_Q_LOCK();
10195 + for (;;) {
10196 + /*
10197 + * we need to make sure we don't get into a busy loop with nothing
10198 + * to do, the two crypto_all_*blocked vars help us find out when
10199 + * we are all full and can do nothing on any driver or Q. If so we
10200 + * wait for an unblock.
10201 + */
10202 + crypto_all_qblocked = !list_empty(&crp_q);
10203 +
10204 + /*
10205 + * Find the first element in the queue that can be
10206 + * processed and look-ahead to see if multiple ops
10207 + * are ready for the same driver.
10208 + */
10209 + submit = NULL;
10210 + hint = 0;
10211 + list_for_each_entry(crp, &crp_q, crp_next) {
10212 + hid = CRYPTO_SESID2HID(crp->crp_sid);
10213 + cap = crypto_checkdriver(hid);
10214 + /*
10215 + * Driver cannot disappear when there is an active
10216 + * session.
10217 + */
10218 + KASSERT(cap != NULL, ("%s:%u Driver disappeared.",
10219 + __func__, __LINE__));
10220 + if (cap == NULL || cap->cc_dev == NULL) {
10221 + /* Op needs to be migrated, process it. */
10222 + if (submit == NULL)
10223 + submit = crp;
10224 + break;
10225 + }
10226 + if (!cap->cc_qblocked) {
10227 + if (submit != NULL) {
10228 + /*
10229 + * We stop on finding another op,
10230 + * regardless whether its for the same
10231 + * driver or not. We could keep
10232 + * searching the queue but it might be
10233 + * better to just use a per-driver
10234 + * queue instead.
10235 + */
10236 + if (CRYPTO_SESID2HID(submit->crp_sid) == hid)
10237 + hint = CRYPTO_HINT_MORE;
10238 + break;
10239 + } else {
10240 + submit = crp;
10241 + if ((submit->crp_flags & CRYPTO_F_BATCH) == 0)
10242 + break;
10243 + /* keep scanning for more are q'd */
10244 + }
10245 + }
10246 + }
10247 + if (submit != NULL) {
10248 + hid = CRYPTO_SESID2HID(submit->crp_sid);
10249 + crypto_all_qblocked = 0;
10250 + list_del(&submit->crp_next);
10251 + crypto_drivers[hid].cc_qblocked = 1;
10252 + cap = crypto_checkdriver(hid);
10253 + CRYPTO_Q_UNLOCK();
10254 + KASSERT(cap != NULL, ("%s:%u Driver disappeared.",
10255 + __func__, __LINE__));
10256 + result = crypto_invoke(cap, submit, hint);
10257 + CRYPTO_Q_LOCK();
10258 + if (result == ERESTART) {
10259 + /*
10260 + * The driver ran out of resources, mark the
10261 + * driver ``blocked'' for cryptop's and put
10262 + * the request back in the queue. It would
10263 + * best to put the request back where we got
10264 + * it but that's hard so for now we put it
10265 + * at the front. This should be ok; putting
10266 + * it at the end does not work.
10267 + */
10268 + /* XXX validate sid again? */
10269 + list_add(&submit->crp_next, &crp_q);
10270 + cryptostats.cs_blocks++;
10271 + } else
10272 + crypto_drivers[hid].cc_qblocked=0;
10273 + }
10274 +
10275 + crypto_all_kqblocked = !list_empty(&crp_kq);
10276 +
10277 + /* As above, but for key ops */
10278 + krp = NULL;
10279 + list_for_each_entry(krpp, &crp_kq, krp_next) {
10280 + cap = crypto_checkdriver(krpp->krp_hid);
10281 + if (cap == NULL || cap->cc_dev == NULL) {
10282 + /*
10283 + * Operation needs to be migrated, invalidate
10284 + * the assigned device so it will reselect a
10285 + * new one below. Propagate the original
10286 + * crid selection flags if supplied.
10287 + */
10288 + krp->krp_hid = krp->krp_crid &
10289 + (CRYPTOCAP_F_SOFTWARE|CRYPTOCAP_F_HARDWARE);
10290 + if (krp->krp_hid == 0)
10291 + krp->krp_hid =
10292 + CRYPTOCAP_F_SOFTWARE|CRYPTOCAP_F_HARDWARE;
10293 + break;
10294 + }
10295 + if (!cap->cc_kqblocked) {
10296 + krp = krpp;
10297 + break;
10298 + }
10299 + }
10300 + if (krp != NULL) {
10301 + crypto_all_kqblocked = 0;
10302 + list_del(&krp->krp_next);
10303 + crypto_drivers[krp->krp_hid].cc_kqblocked = 1;
10304 + CRYPTO_Q_UNLOCK();
10305 + result = crypto_kinvoke(krp, krp->krp_hid);
10306 + CRYPTO_Q_LOCK();
10307 + if (result == ERESTART) {
10308 + /*
10309 + * The driver ran out of resources, mark the
10310 + * driver ``blocked'' for cryptkop's and put
10311 + * the request back in the queue. It would
10312 + * best to put the request back where we got
10313 + * it but that's hard so for now we put it
10314 + * at the front. This should be ok; putting
10315 + * it at the end does not work.
10316 + */
10317 + /* XXX validate sid again? */
10318 + list_add(&krp->krp_next, &crp_kq);
10319 + cryptostats.cs_kblocks++;
10320 + } else
10321 + crypto_drivers[krp->krp_hid].cc_kqblocked = 0;
10322 + }
10323 +
10324 + if (submit == NULL && krp == NULL) {
10325 + /*
10326 + * Nothing more to be processed. Sleep until we're
10327 + * woken because there are more ops to process.
10328 + * This happens either by submission or by a driver
10329 + * becoming unblocked and notifying us through
10330 + * crypto_unblock. Note that when we wakeup we
10331 + * start processing each queue again from the
10332 + * front. It's not clear that it's important to
10333 + * preserve this ordering since ops may finish
10334 + * out of order if dispatched to different devices
10335 + * and some become blocked while others do not.
10336 + */
10337 + dprintk("%s - sleeping (qe=%d qb=%d kqe=%d kqb=%d)\n",
10338 + __FUNCTION__,
10339 + list_empty(&crp_q), crypto_all_qblocked,
10340 + list_empty(&crp_kq), crypto_all_kqblocked);
10341 + CRYPTO_Q_UNLOCK();
10342 + crp_sleep = 1;
10343 + wait_event_interruptible(cryptoproc_wait,
10344 + !(list_empty(&crp_q) || crypto_all_qblocked) ||
10345 + !(list_empty(&crp_kq) || crypto_all_kqblocked) ||
10346 + cryptoproc == (pid_t) -1);
10347 + crp_sleep = 0;
10348 + if (signal_pending (current)) {
10349 +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,0)
10350 + spin_lock_irq(&current->sigmask_lock);
10351 +#endif
10352 + flush_signals(current);
10353 +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,0)
10354 + spin_unlock_irq(&current->sigmask_lock);
10355 +#endif
10356 + }
10357 + CRYPTO_Q_LOCK();
10358 + dprintk("%s - awake\n", __FUNCTION__);
10359 + if (cryptoproc == (pid_t) -1)
10360 + break;
10361 + cryptostats.cs_intrs++;
10362 + }
10363 + }
10364 + CRYPTO_Q_UNLOCK();
10365 + complete_and_exit(&cryptoproc_exited, 0);
10366 +}
10367 +
10368 +/*
10369 + * Crypto returns thread, does callbacks for processed crypto requests.
10370 + * Callbacks are done here, rather than in the crypto drivers, because
10371 + * callbacks typically are expensive and would slow interrupt handling.
10372 + */
10373 +static int
10374 +crypto_ret_proc(void *arg)
10375 +{
10376 + struct cryptop *crpt;
10377 + struct cryptkop *krpt;
10378 + unsigned long r_flags;
10379 +
10380 + ocf_daemonize("crypto_ret");
10381 +
10382 + CRYPTO_RETQ_LOCK();
10383 + for (;;) {
10384 + /* Harvest return q's for completed ops */
10385 + crpt = NULL;
10386 + if (!list_empty(&crp_ret_q))
10387 + crpt = list_entry(crp_ret_q.next, typeof(*crpt), crp_next);
10388 + if (crpt != NULL)
10389 + list_del(&crpt->crp_next);
10390 +
10391 + krpt = NULL;
10392 + if (!list_empty(&crp_ret_kq))
10393 + krpt = list_entry(crp_ret_kq.next, typeof(*krpt), krp_next);
10394 + if (krpt != NULL)
10395 + list_del(&krpt->krp_next);
10396 +
10397 + if (crpt != NULL || krpt != NULL) {
10398 + CRYPTO_RETQ_UNLOCK();
10399 + /*
10400 + * Run callbacks unlocked.
10401 + */
10402 + if (crpt != NULL)
10403 + crpt->crp_callback(crpt);
10404 + if (krpt != NULL)
10405 + krpt->krp_callback(krpt);
10406 + CRYPTO_RETQ_LOCK();
10407 + } else {
10408 + /*
10409 + * Nothing more to be processed. Sleep until we're
10410 + * woken because there are more returns to process.
10411 + */
10412 + dprintk("%s - sleeping\n", __FUNCTION__);
10413 + CRYPTO_RETQ_UNLOCK();
10414 + wait_event_interruptible(cryptoretproc_wait,
10415 + cryptoretproc == (pid_t) -1 ||
10416 + !list_empty(&crp_ret_q) ||
10417 + !list_empty(&crp_ret_kq));
10418 + if (signal_pending (current)) {
10419 +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,0)
10420 + spin_lock_irq(&current->sigmask_lock);
10421 +#endif
10422 + flush_signals(current);
10423 +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,0)
10424 + spin_unlock_irq(&current->sigmask_lock);
10425 +#endif
10426 + }
10427 + CRYPTO_RETQ_LOCK();
10428 + dprintk("%s - awake\n", __FUNCTION__);
10429 + if (cryptoretproc == (pid_t) -1) {
10430 + dprintk("%s - EXITING!\n", __FUNCTION__);
10431 + break;
10432 + }
10433 + cryptostats.cs_rets++;
10434 + }
10435 + }
10436 + CRYPTO_RETQ_UNLOCK();
10437 + complete_and_exit(&cryptoretproc_exited, 0);
10438 +}
10439 +
10440 +
10441 +#if 0 /* should put this into /proc or something */
10442 +static void
10443 +db_show_drivers(void)
10444 +{
10445 + int hid;
10446 +
10447 + db_printf("%12s %4s %4s %8s %2s %2s\n"
10448 + , "Device"
10449 + , "Ses"
10450 + , "Kops"
10451 + , "Flags"
10452 + , "QB"
10453 + , "KB"
10454 + );
10455 + for (hid = 0; hid < crypto_drivers_num; hid++) {
10456 + const struct cryptocap *cap = &crypto_drivers[hid];
10457 + if (cap->cc_dev == NULL)
10458 + continue;
10459 + db_printf("%-12s %4u %4u %08x %2u %2u\n"
10460 + , device_get_nameunit(cap->cc_dev)
10461 + , cap->cc_sessions
10462 + , cap->cc_koperations
10463 + , cap->cc_flags
10464 + , cap->cc_qblocked
10465 + , cap->cc_kqblocked
10466 + );
10467 + }
10468 +}
10469 +
10470 +DB_SHOW_COMMAND(crypto, db_show_crypto)
10471 +{
10472 + struct cryptop *crp;
10473 +
10474 + db_show_drivers();
10475 + db_printf("\n");
10476 +
10477 + db_printf("%4s %8s %4s %4s %4s %4s %8s %8s\n",
10478 + "HID", "Caps", "Ilen", "Olen", "Etype", "Flags",
10479 + "Desc", "Callback");
10480 + TAILQ_FOREACH(crp, &crp_q, crp_next) {
10481 + db_printf("%4u %08x %4u %4u %4u %04x %8p %8p\n"
10482 + , (int) CRYPTO_SESID2HID(crp->crp_sid)
10483 + , (int) CRYPTO_SESID2CAPS(crp->crp_sid)
10484 + , crp->crp_ilen, crp->crp_olen
10485 + , crp->crp_etype
10486 + , crp->crp_flags
10487 + , crp->crp_desc
10488 + , crp->crp_callback
10489 + );
10490 + }
10491 + if (!TAILQ_EMPTY(&crp_ret_q)) {
10492 + db_printf("\n%4s %4s %4s %8s\n",
10493 + "HID", "Etype", "Flags", "Callback");
10494 + TAILQ_FOREACH(crp, &crp_ret_q, crp_next) {
10495 + db_printf("%4u %4u %04x %8p\n"
10496 + , (int) CRYPTO_SESID2HID(crp->crp_sid)
10497 + , crp->crp_etype
10498 + , crp->crp_flags
10499 + , crp->crp_callback
10500 + );
10501 + }
10502 + }
10503 +}
10504 +
10505 +DB_SHOW_COMMAND(kcrypto, db_show_kcrypto)
10506 +{
10507 + struct cryptkop *krp;
10508 +
10509 + db_show_drivers();
10510 + db_printf("\n");
10511 +
10512 + db_printf("%4s %5s %4s %4s %8s %4s %8s\n",
10513 + "Op", "Status", "#IP", "#OP", "CRID", "HID", "Callback");
10514 + TAILQ_FOREACH(krp, &crp_kq, krp_next) {
10515 + db_printf("%4u %5u %4u %4u %08x %4u %8p\n"
10516 + , krp->krp_op
10517 + , krp->krp_status
10518 + , krp->krp_iparams, krp->krp_oparams
10519 + , krp->krp_crid, krp->krp_hid
10520 + , krp->krp_callback
10521 + );
10522 + }
10523 + if (!TAILQ_EMPTY(&crp_ret_q)) {
10524 + db_printf("%4s %5s %8s %4s %8s\n",
10525 + "Op", "Status", "CRID", "HID", "Callback");
10526 + TAILQ_FOREACH(krp, &crp_ret_kq, krp_next) {
10527 + db_printf("%4u %5u %08x %4u %8p\n"
10528 + , krp->krp_op
10529 + , krp->krp_status
10530 + , krp->krp_crid, krp->krp_hid
10531 + , krp->krp_callback
10532 + );
10533 + }
10534 + }
10535 +}
10536 +#endif
10537 +
10538 +
10539 +static int
10540 +crypto_init(void)
10541 +{
10542 + int error;
10543 +
10544 + dprintk("%s(0x%x)\n", __FUNCTION__, (int) crypto_init);
10545 +
10546 + if (crypto_initted)
10547 + return 0;
10548 + crypto_initted = 1;
10549 +
10550 + spin_lock_init(&crypto_drivers_lock);
10551 + spin_lock_init(&crypto_q_lock);
10552 + spin_lock_init(&crypto_ret_q_lock);
10553 +
10554 + cryptop_zone = kmem_cache_create("cryptop", sizeof(struct cryptop),
10555 + 0, SLAB_HWCACHE_ALIGN, NULL
10556 +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,23)
10557 + , NULL
10558 +#endif
10559 + );
10560 +
10561 + cryptodesc_zone = kmem_cache_create("cryptodesc", sizeof(struct cryptodesc),
10562 + 0, SLAB_HWCACHE_ALIGN, NULL
10563 +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,23)
10564 + , NULL
10565 +#endif
10566 + );
10567 +
10568 + if (cryptodesc_zone == NULL || cryptop_zone == NULL) {
10569 + printk("crypto: crypto_init cannot setup crypto zones\n");
10570 + error = ENOMEM;
10571 + goto bad;
10572 + }
10573 +
10574 + crypto_drivers_num = CRYPTO_DRIVERS_INITIAL;
10575 + crypto_drivers = kmalloc(crypto_drivers_num * sizeof(struct cryptocap),
10576 + GFP_KERNEL);
10577 + if (crypto_drivers == NULL) {
10578 + printk("crypto: crypto_init cannot setup crypto drivers\n");
10579 + error = ENOMEM;
10580 + goto bad;
10581 + }
10582 +
10583 + memset(crypto_drivers, 0, crypto_drivers_num * sizeof(struct cryptocap));
10584 +
10585 + init_completion(&cryptoproc_exited);
10586 + init_completion(&cryptoretproc_exited);
10587 +
10588 + cryptoproc = 0; /* to avoid race condition where proc runs first */
10589 + cryptoproc = kernel_thread(crypto_proc, NULL, CLONE_FS|CLONE_FILES);
10590 + if (cryptoproc < 0) {
10591 + error = cryptoproc;
10592 + printk("crypto: crypto_init cannot start crypto thread; error %d",
10593 + error);
10594 + goto bad;
10595 + }
10596 +
10597 + cryptoretproc = 0; /* to avoid race condition where proc runs first */
10598 + cryptoretproc = kernel_thread(crypto_ret_proc, NULL, CLONE_FS|CLONE_FILES);
10599 + if (cryptoretproc < 0) {
10600 + error = cryptoretproc;
10601 + printk("crypto: crypto_init cannot start cryptoret thread; error %d",
10602 + error);
10603 + goto bad;
10604 + }
10605 +
10606 + return 0;
10607 +bad:
10608 + crypto_exit();
10609 + return error;
10610 +}
10611 +
10612 +
10613 +static void
10614 +crypto_exit(void)
10615 +{
10616 + pid_t p;
10617 + unsigned long d_flags;
10618 +
10619 + dprintk("%s()\n", __FUNCTION__);
10620 +
10621 + /*
10622 + * Terminate any crypto threads.
10623 + */
10624 +
10625 + CRYPTO_DRIVER_LOCK();
10626 + p = cryptoproc;
10627 + cryptoproc = (pid_t) -1;
10628 + kill_proc(p, SIGTERM, 1);
10629 + wake_up_interruptible(&cryptoproc_wait);
10630 + CRYPTO_DRIVER_UNLOCK();
10631 +
10632 + wait_for_completion(&cryptoproc_exited);
10633 +
10634 + CRYPTO_DRIVER_LOCK();
10635 + p = cryptoretproc;
10636 + cryptoretproc = (pid_t) -1;
10637 + kill_proc(p, SIGTERM, 1);
10638 + wake_up_interruptible(&cryptoretproc_wait);
10639 + CRYPTO_DRIVER_UNLOCK();
10640 +
10641 + wait_for_completion(&cryptoretproc_exited);
10642 +
10643 + /* XXX flush queues??? */
10644 +
10645 + /*
10646 + * Reclaim dynamically allocated resources.
10647 + */
10648 + if (crypto_drivers != NULL)
10649 + kfree(crypto_drivers);
10650 +
10651 + if (cryptodesc_zone != NULL)
10652 + kmem_cache_destroy(cryptodesc_zone);
10653 + if (cryptop_zone != NULL)
10654 + kmem_cache_destroy(cryptop_zone);
10655 +}
10656 +
10657 +
10658 +EXPORT_SYMBOL(crypto_newsession);
10659 +EXPORT_SYMBOL(crypto_freesession);
10660 +EXPORT_SYMBOL(crypto_get_driverid);
10661 +EXPORT_SYMBOL(crypto_kregister);
10662 +EXPORT_SYMBOL(crypto_register);
10663 +EXPORT_SYMBOL(crypto_unregister);
10664 +EXPORT_SYMBOL(crypto_unregister_all);
10665 +EXPORT_SYMBOL(crypto_unblock);
10666 +EXPORT_SYMBOL(crypto_dispatch);
10667 +EXPORT_SYMBOL(crypto_kdispatch);
10668 +EXPORT_SYMBOL(crypto_freereq);
10669 +EXPORT_SYMBOL(crypto_getreq);
10670 +EXPORT_SYMBOL(crypto_done);
10671 +EXPORT_SYMBOL(crypto_kdone);
10672 +EXPORT_SYMBOL(crypto_getfeat);
10673 +EXPORT_SYMBOL(crypto_userasymcrypto);
10674 +EXPORT_SYMBOL(crypto_getcaps);
10675 +EXPORT_SYMBOL(crypto_find_driver);
10676 +EXPORT_SYMBOL(crypto_find_device_byhid);
10677 +
10678 +module_init(crypto_init);
10679 +module_exit(crypto_exit);
10680 +
10681 +MODULE_LICENSE("BSD");
10682 +MODULE_AUTHOR("David McCullough <david_mccullough@securecomputing.com>");
10683 +MODULE_DESCRIPTION("OCF (OpenBSD Cryptographic Framework)");
10684 --- /dev/null
10685 +++ b/crypto/ocf/criov.c
10686 @@ -0,0 +1,215 @@
10687 +/* $OpenBSD: criov.c,v 1.9 2002/01/29 15:48:29 jason Exp $ */
10688 +
10689 +/*
10690 + * Linux port done by David McCullough <david_mccullough@securecomputing.com>
10691 + * Copyright (C) 2006-2007 David McCullough
10692 + * Copyright (C) 2004-2005 Intel Corporation.
10693 + * The license and original author are listed below.
10694 + *
10695 + * Copyright (c) 1999 Theo de Raadt
10696 + *
10697 + * Redistribution and use in source and binary forms, with or without
10698 + * modification, are permitted provided that the following conditions
10699 + * are met:
10700 + *
10701 + * 1. Redistributions of source code must retain the above copyright
10702 + * notice, this list of conditions and the following disclaimer.
10703 + * 2. Redistributions in binary form must reproduce the above copyright
10704 + * notice, this list of conditions and the following disclaimer in the
10705 + * documentation and/or other materials provided with the distribution.
10706 + * 3. The name of the author may not be used to endorse or promote products
10707 + * derived from this software without specific prior written permission.
10708 + *
10709 + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
10710 + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
10711 + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
10712 + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
10713 + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
10714 + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
10715 + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
10716 + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
10717 + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
10718 + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
10719 + *
10720 +__FBSDID("$FreeBSD: src/sys/opencrypto/criov.c,v 1.5 2006/06/04 22:15:13 pjd Exp $");
10721 + */
10722 +
10723 +#ifndef AUTOCONF_INCLUDED
10724 +#include <linux/config.h>
10725 +#endif
10726 +#include <linux/module.h>
10727 +#include <linux/init.h>
10728 +#include <linux/slab.h>
10729 +#include <linux/uio.h>
10730 +#include <linux/skbuff.h>
10731 +#include <linux/kernel.h>
10732 +#include <linux/mm.h>
10733 +#include <asm/io.h>
10734 +
10735 +#include <uio.h>
10736 +#include <cryptodev.h>
10737 +
10738 +/*
10739 + * This macro is only for avoiding code duplication, as we need to skip
10740 + * given number of bytes in the same way in three functions below.
10741 + */
10742 +#define CUIO_SKIP() do { \
10743 + KASSERT(off >= 0, ("%s: off %d < 0", __func__, off)); \
10744 + KASSERT(len >= 0, ("%s: len %d < 0", __func__, len)); \
10745 + while (off > 0) { \
10746 + KASSERT(iol >= 0, ("%s: empty in skip", __func__)); \
10747 + if (off < iov->iov_len) \
10748 + break; \
10749 + off -= iov->iov_len; \
10750 + iol--; \
10751 + iov++; \
10752 + } \
10753 +} while (0)
10754 +
10755 +void
10756 +cuio_copydata(struct uio* uio, int off, int len, caddr_t cp)
10757 +{
10758 + struct iovec *iov = uio->uio_iov;
10759 + int iol = uio->uio_iovcnt;
10760 + unsigned count;
10761 +
10762 + CUIO_SKIP();
10763 + while (len > 0) {
10764 + KASSERT(iol >= 0, ("%s: empty", __func__));
10765 + count = min((int)(iov->iov_len - off), len);
10766 + memcpy(cp, ((caddr_t)iov->iov_base) + off, count);
10767 + len -= count;
10768 + cp += count;
10769 + off = 0;
10770 + iol--;
10771 + iov++;
10772 + }
10773 +}
10774 +
10775 +void
10776 +cuio_copyback(struct uio* uio, int off, int len, caddr_t cp)
10777 +{
10778 + struct iovec *iov = uio->uio_iov;
10779 + int iol = uio->uio_iovcnt;
10780 + unsigned count;
10781 +
10782 + CUIO_SKIP();
10783 + while (len > 0) {
10784 + KASSERT(iol >= 0, ("%s: empty", __func__));
10785 + count = min((int)(iov->iov_len - off), len);
10786 + memcpy(((caddr_t)iov->iov_base) + off, cp, count);
10787 + len -= count;
10788 + cp += count;
10789 + off = 0;
10790 + iol--;
10791 + iov++;
10792 + }
10793 +}
10794 +
10795 +/*
10796 + * Return a pointer to iov/offset of location in iovec list.
10797 + */
10798 +struct iovec *
10799 +cuio_getptr(struct uio *uio, int loc, int *off)
10800 +{
10801 + struct iovec *iov = uio->uio_iov;
10802 + int iol = uio->uio_iovcnt;
10803 +
10804 + while (loc >= 0) {
10805 + /* Normal end of search */
10806 + if (loc < iov->iov_len) {
10807 + *off = loc;
10808 + return (iov);
10809 + }
10810 +
10811 + loc -= iov->iov_len;
10812 + if (iol == 0) {
10813 + if (loc == 0) {
10814 + /* Point at the end of valid data */
10815 + *off = iov->iov_len;
10816 + return (iov);
10817 + } else
10818 + return (NULL);
10819 + } else {
10820 + iov++, iol--;
10821 + }
10822 + }
10823 +
10824 + return (NULL);
10825 +}
10826 +
10827 +EXPORT_SYMBOL(cuio_copyback);
10828 +EXPORT_SYMBOL(cuio_copydata);
10829 +EXPORT_SYMBOL(cuio_getptr);
10830 +
10831 +
10832 +static void
10833 +skb_copy_bits_back(struct sk_buff *skb, int offset, caddr_t cp, int len)
10834 +{
10835 + int i;
10836 + if (offset < skb_headlen(skb)) {
10837 + memcpy(skb->data + offset, cp, min_t(int, skb_headlen(skb), len));
10838 + len -= skb_headlen(skb);
10839 + cp += skb_headlen(skb);
10840 + }
10841 + offset -= skb_headlen(skb);
10842 + for (i = 0; len > 0 && i < skb_shinfo(skb)->nr_frags; i++) {
10843 + if (offset < skb_shinfo(skb)->frags[i].size) {
10844 + memcpy(page_address(skb_shinfo(skb)->frags[i].page) +
10845 + skb_shinfo(skb)->frags[i].page_offset,
10846 + cp, min_t(int, skb_shinfo(skb)->frags[i].size, len));
10847 + len -= skb_shinfo(skb)->frags[i].size;
10848 + cp += skb_shinfo(skb)->frags[i].size;
10849 + }
10850 + offset -= skb_shinfo(skb)->frags[i].size;
10851 + }
10852 +}
10853 +
10854 +void
10855 +crypto_copyback(int flags, caddr_t buf, int off, int size, caddr_t in)
10856 +{
10857 +
10858 + if ((flags & CRYPTO_F_SKBUF) != 0)
10859 + skb_copy_bits_back((struct sk_buff *)buf, off, in, size);
10860 + else if ((flags & CRYPTO_F_IOV) != 0)
10861 + cuio_copyback((struct uio *)buf, off, size, in);
10862 + else
10863 + bcopy(in, buf + off, size);
10864 +}
10865 +
10866 +void
10867 +crypto_copydata(int flags, caddr_t buf, int off, int size, caddr_t out)
10868 +{
10869 +
10870 + if ((flags & CRYPTO_F_SKBUF) != 0)
10871 + skb_copy_bits((struct sk_buff *)buf, off, out, size);
10872 + else if ((flags & CRYPTO_F_IOV) != 0)
10873 + cuio_copydata((struct uio *)buf, off, size, out);
10874 + else
10875 + bcopy(buf + off, out, size);
10876 +}
10877 +
10878 +int
10879 +crypto_apply(int flags, caddr_t buf, int off, int len,
10880 + int (*f)(void *, void *, u_int), void *arg)
10881 +{
10882 +#if 0
10883 + int error;
10884 +
10885 + if ((flags & CRYPTO_F_SKBUF) != 0)
10886 + error = XXXXXX((struct mbuf *)buf, off, len, f, arg);
10887 + else if ((flags & CRYPTO_F_IOV) != 0)
10888 + error = cuio_apply((struct uio *)buf, off, len, f, arg);
10889 + else
10890 + error = (*f)(arg, buf + off, len);
10891 + return (error);
10892 +#else
10893 + KASSERT(0, ("crypto_apply not implemented!\n"));
10894 +#endif
10895 + return 0;
10896 +}
10897 +
10898 +EXPORT_SYMBOL(crypto_copyback);
10899 +EXPORT_SYMBOL(crypto_copydata);
10900 +EXPORT_SYMBOL(crypto_apply);
10901 +
10902 --- /dev/null
10903 +++ b/crypto/ocf/uio.h
10904 @@ -0,0 +1,54 @@
10905 +#ifndef _OCF_UIO_H_
10906 +#define _OCF_UIO_H_
10907 +
10908 +#include <linux/uio.h>
10909 +
10910 +/*
10911 + * The linux uio.h doesn't have all we need. To be fully api compatible
10912 + * with the BSD cryptodev, we need to keep this around. Perhaps this can
10913 + * be moved back into the linux/uio.h
10914 + *
10915 + * Linux port done by David McCullough <david_mccullough@securecomputing.com>
10916 + * Copyright (C) 2006-2007 David McCullough
10917 + * Copyright (C) 2004-2005 Intel Corporation.
10918 + *
10919 + * LICENSE TERMS
10920 + *
10921 + * The free distribution and use of this software in both source and binary
10922 + * form is allowed (with or without changes) provided that:
10923 + *
10924 + * 1. distributions of this source code include the above copyright
10925 + * notice, this list of conditions and the following disclaimer;
10926 + *
10927 + * 2. distributions in binary form include the above copyright
10928 + * notice, this list of conditions and the following disclaimer
10929 + * in the documentation and/or other associated materials;
10930 + *
10931 + * 3. the copyright holder's name is not used to endorse products
10932 + * built using this software without specific written permission.
10933 + *
10934 + * ALTERNATIVELY, provided that this notice is retained in full, this product
10935 + * may be distributed under the terms of the GNU General Public License (GPL),
10936 + * in which case the provisions of the GPL apply INSTEAD OF those given above.
10937 + *
10938 + * DISCLAIMER
10939 + *
10940 + * This software is provided 'as is' with no explicit or implied warranties
10941 + * in respect of its properties, including, but not limited to, correctness
10942 + * and/or fitness for purpose.
10943 + * ---------------------------------------------------------------------------
10944 + */
10945 +
10946 +struct uio {
10947 + struct iovec *uio_iov;
10948 + int uio_iovcnt;
10949 + off_t uio_offset;
10950 + int uio_resid;
10951 +#if 0
10952 + enum uio_seg uio_segflg;
10953 + enum uio_rw uio_rw;
10954 + struct thread *uio_td;
10955 +#endif
10956 +};
10957 +
10958 +#endif
10959 --- /dev/null
10960 +++ b/crypto/ocf/talitos/talitos.c
10961 @@ -0,0 +1,1359 @@
10962 +/*
10963 + * crypto/ocf/talitos/talitos.c
10964 + *
10965 + * An OCF-Linux module that uses Freescale's SEC to do the crypto.
10966 + * Based on crypto/ocf/hifn and crypto/ocf/safe OCF drivers
10967 + *
10968 + * Copyright (c) 2006 Freescale Semiconductor, Inc.
10969 + *
10970 + * This code written by Kim A. B. Phillips <kim.phillips@freescale.com>
10971 + * some code copied from files with the following:
10972 + * Copyright (C) 2004-2007 David McCullough <david_mccullough@securecomputing.com
10973 + *
10974 + * Redistribution and use in source and binary forms, with or without
10975 + * modification, are permitted provided that the following conditions
10976 + * are met:
10977 + *
10978 + * 1. Redistributions of source code must retain the above copyright
10979 + * notice, this list of conditions and the following disclaimer.
10980 + * 2. Redistributions in binary form must reproduce the above copyright
10981 + * notice, this list of conditions and the following disclaimer in the
10982 + * documentation and/or other materials provided with the distribution.
10983 + * 3. The name of the author may not be used to endorse or promote products
10984 + * derived from this software without specific prior written permission.
10985 + *
10986 + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
10987 + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
10988 + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
10989 + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
10990 + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
10991 + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
10992 + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
10993 + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
10994 + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
10995 + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
10996 + *
10997 + * ---------------------------------------------------------------------------
10998 + *
10999 + * NOTES:
11000 + *
11001 + * The Freescale SEC (also known as 'talitos') resides on the
11002 + * internal bus, and runs asynchronous to the processor core. It has
11003 + * a wide gamut of cryptographic acceleration features, including single-
11004 + * pass IPsec (also known as algorithm chaining). To properly utilize
11005 + * all of the SEC's performance enhancing features, further reworking
11006 + * of higher level code (framework, applications) will be necessary.
11007 + *
11008 + * The following table shows which SEC version is present in which devices:
11009 + *
11010 + * Devices SEC version
11011 + *
11012 + * 8272, 8248 SEC 1.0
11013 + * 885, 875 SEC 1.2
11014 + * 8555E, 8541E SEC 2.0
11015 + * 8349E SEC 2.01
11016 + * 8548E SEC 2.1
11017 + *
11018 + * The following table shows the features offered by each SEC version:
11019 + *
11020 + * Max. chan-
11021 + * version Bus I/F Clock nels DEU AESU AFEU MDEU PKEU RNG KEU
11022 + *
11023 + * SEC 1.0 internal 64b 100MHz 4 1 1 1 1 1 1 0
11024 + * SEC 1.2 internal 32b 66MHz 1 1 1 0 1 0 0 0
11025 + * SEC 2.0 internal 64b 166MHz 4 1 1 1 1 1 1 0
11026 + * SEC 2.01 internal 64b 166MHz 4 1 1 1 1 1 1 0
11027 + * SEC 2.1 internal 64b 333MHz 4 1 1 1 1 1 1 1
11028 + *
11029 + * Each execution unit in the SEC has two modes of execution; channel and
11030 + * slave/debug. This driver employs the channel infrastructure in the
11031 + * device for convenience. Only the RNG is directly accessed due to the
11032 + * convenience of its random fifo pool. The relationship between the
11033 + * channels and execution units is depicted in the following diagram:
11034 + *
11035 + * ------- ------------
11036 + * ---| ch0 |---| |
11037 + * ------- | |
11038 + * | |------+-------+-------+-------+------------
11039 + * ------- | | | | | | |
11040 + * ---| ch1 |---| | | | | | |
11041 + * ------- | | ------ ------ ------ ------ ------
11042 + * |controller| |DEU | |AESU| |MDEU| |PKEU| ... |RNG |
11043 + * ------- | | ------ ------ ------ ------ ------
11044 + * ---| ch2 |---| | | | | | |
11045 + * ------- | | | | | | |
11046 + * | |------+-------+-------+-------+------------
11047 + * ------- | |
11048 + * ---| ch3 |---| |
11049 + * ------- ------------
11050 + *
11051 + * Channel ch0 may drive an aes operation to the aes unit (AESU),
11052 + * and, at the same time, ch1 may drive a message digest operation
11053 + * to the mdeu. Each channel has an input descriptor FIFO, and the
11054 + * FIFO can contain, e.g. on the 8541E, up to 24 entries, before a
11055 + * a buffer overrun error is triggered. The controller is responsible
11056 + * for fetching the data from descriptor pointers, and passing the
11057 + * data to the appropriate EUs. The controller also writes the
11058 + * cryptographic operation's result to memory. The SEC notifies
11059 + * completion by triggering an interrupt and/or setting the 1st byte
11060 + * of the hdr field to 0xff.
11061 + *
11062 + * TODO:
11063 + * o support more algorithms
11064 + * o support more versions of the SEC
11065 + * o add support for linux 2.4
11066 + * o scatter-gather (sg) support
11067 + * o add support for public key ops (PKEU)
11068 + * o add statistics
11069 + */
11070 +
11071 +#ifndef AUTOCONF_INCLUDED
11072 +#include <linux/config.h>
11073 +#endif
11074 +#include <linux/module.h>
11075 +#include <linux/init.h>
11076 +#include <linux/interrupt.h>
11077 +#include <linux/spinlock.h>
11078 +#include <linux/random.h>
11079 +#include <linux/skbuff.h>
11080 +#include <asm/scatterlist.h>
11081 +#include <linux/dma-mapping.h> /* dma_map_single() */
11082 +#include <linux/moduleparam.h>
11083 +
11084 +#include <linux/version.h>
11085 +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,15)
11086 +#include <linux/platform_device.h>
11087 +#endif
11088 +
11089 +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,19)
11090 +#include <linux/of_platform.h>
11091 +#endif
11092 +
11093 +#include <cryptodev.h>
11094 +#include <uio.h>
11095 +
11096 +#define DRV_NAME "talitos"
11097 +
11098 +#include "talitos_dev.h"
11099 +#include "talitos_soft.h"
11100 +
11101 +#define read_random(p,l) get_random_bytes(p,l)
11102 +
11103 +const char talitos_driver_name[] = "Talitos OCF";
11104 +const char talitos_driver_version[] = "0.2";
11105 +
11106 +static int talitos_newsession(device_t dev, u_int32_t *sidp,
11107 + struct cryptoini *cri);
11108 +static int talitos_freesession(device_t dev, u_int64_t tid);
11109 +static int talitos_process(device_t dev, struct cryptop *crp, int hint);
11110 +static void dump_talitos_status(struct talitos_softc *sc);
11111 +static int talitos_submit(struct talitos_softc *sc, struct talitos_desc *td,
11112 + int chsel);
11113 +static void talitos_doneprocessing(struct talitos_softc *sc);
11114 +static void talitos_init_device(struct talitos_softc *sc);
11115 +static void talitos_reset_device_master(struct talitos_softc *sc);
11116 +static void talitos_reset_device(struct talitos_softc *sc);
11117 +static void talitos_errorprocessing(struct talitos_softc *sc);
11118 +#ifdef CONFIG_PPC_MERGE
11119 +static int talitos_probe(struct of_device *ofdev, const struct of_device_id *match);
11120 +static int talitos_remove(struct of_device *ofdev);
11121 +#else
11122 +static int talitos_probe(struct platform_device *pdev);
11123 +static int talitos_remove(struct platform_device *pdev);
11124 +#endif
11125 +#ifdef CONFIG_OCF_RANDOMHARVEST
11126 +static int talitos_read_random(void *arg, u_int32_t *buf, int maxwords);
11127 +static void talitos_rng_init(struct talitos_softc *sc);
11128 +#endif
11129 +
11130 +static device_method_t talitos_methods = {
11131 + /* crypto device methods */
11132 + DEVMETHOD(cryptodev_newsession, talitos_newsession),
11133 + DEVMETHOD(cryptodev_freesession,talitos_freesession),
11134 + DEVMETHOD(cryptodev_process, talitos_process),
11135 +};
11136 +
11137 +#define debug talitos_debug
11138 +int talitos_debug = 0;
11139 +module_param(talitos_debug, int, 0644);
11140 +MODULE_PARM_DESC(talitos_debug, "Enable debug");
11141 +
11142 +static inline void talitos_write(volatile unsigned *addr, u32 val)
11143 +{
11144 + out_be32(addr, val);
11145 +}
11146 +
11147 +static inline u32 talitos_read(volatile unsigned *addr)
11148 +{
11149 + u32 val;
11150 + val = in_be32(addr);
11151 + return val;
11152 +}
11153 +
11154 +static void dump_talitos_status(struct talitos_softc *sc)
11155 +{
11156 + unsigned int v, v_hi, i, *ptr;
11157 + v = talitos_read(sc->sc_base_addr + TALITOS_MCR);
11158 + v_hi = talitos_read(sc->sc_base_addr + TALITOS_MCR_HI);
11159 + printk(KERN_INFO "%s: MCR 0x%08x_%08x\n",
11160 + device_get_nameunit(sc->sc_cdev), v, v_hi);
11161 + v = talitos_read(sc->sc_base_addr + TALITOS_IMR);
11162 + v_hi = talitos_read(sc->sc_base_addr + TALITOS_IMR_HI);
11163 + printk(KERN_INFO "%s: IMR 0x%08x_%08x\n",
11164 + device_get_nameunit(sc->sc_cdev), v, v_hi);
11165 + v = talitos_read(sc->sc_base_addr + TALITOS_ISR);
11166 + v_hi = talitos_read(sc->sc_base_addr + TALITOS_ISR_HI);
11167 + printk(KERN_INFO "%s: ISR 0x%08x_%08x\n",
11168 + device_get_nameunit(sc->sc_cdev), v, v_hi);
11169 + for (i = 0; i < sc->sc_num_channels; i++) {
11170 + v = talitos_read(sc->sc_base_addr + i*TALITOS_CH_OFFSET +
11171 + TALITOS_CH_CDPR);
11172 + v_hi = talitos_read(sc->sc_base_addr + i*TALITOS_CH_OFFSET +
11173 + TALITOS_CH_CDPR_HI);
11174 + printk(KERN_INFO "%s: CDPR ch%d 0x%08x_%08x\n",
11175 + device_get_nameunit(sc->sc_cdev), i, v, v_hi);
11176 + }
11177 + for (i = 0; i < sc->sc_num_channels; i++) {
11178 + v = talitos_read(sc->sc_base_addr + i*TALITOS_CH_OFFSET +
11179 + TALITOS_CH_CCPSR);
11180 + v_hi = talitos_read(sc->sc_base_addr + i*TALITOS_CH_OFFSET +
11181 + TALITOS_CH_CCPSR_HI);
11182 + printk(KERN_INFO "%s: CCPSR ch%d 0x%08x_%08x\n",
11183 + device_get_nameunit(sc->sc_cdev), i, v, v_hi);
11184 + }
11185 + ptr = sc->sc_base_addr + TALITOS_CH_DESCBUF;
11186 + for (i = 0; i < 16; i++) {
11187 + v = talitos_read(ptr++); v_hi = talitos_read(ptr++);
11188 + printk(KERN_INFO "%s: DESCBUF ch0 0x%08x_%08x (tdp%02d)\n",
11189 + device_get_nameunit(sc->sc_cdev), v, v_hi, i);
11190 + }
11191 + return;
11192 +}
11193 +
11194 +
11195 +#ifdef CONFIG_OCF_RANDOMHARVEST
11196 +/*
11197 + * pull random numbers off the RNG FIFO, not exceeding amount available
11198 + */
11199 +static int
11200 +talitos_read_random(void *arg, u_int32_t *buf, int maxwords)
11201 +{
11202 + struct talitos_softc *sc = (struct talitos_softc *) arg;
11203 + int rc;
11204 + u_int32_t v;
11205 +
11206 + DPRINTF("%s()\n", __FUNCTION__);
11207 +
11208 + /* check for things like FIFO underflow */
11209 + v = talitos_read(sc->sc_base_addr + TALITOS_RNGISR_HI);
11210 + if (unlikely(v)) {
11211 + printk(KERN_ERR "%s: RNGISR_HI error %08x\n",
11212 + device_get_nameunit(sc->sc_cdev), v);
11213 + return 0;
11214 + }
11215 + /*
11216 + * OFL is number of available 64-bit words,
11217 + * shift and convert to a 32-bit word count
11218 + */
11219 + v = talitos_read(sc->sc_base_addr + TALITOS_RNGSR_HI);
11220 + v = (v & TALITOS_RNGSR_HI_OFL) >> (16 - 1);
11221 + if (maxwords > v)
11222 + maxwords = v;
11223 + for (rc = 0; rc < maxwords; rc++) {
11224 + buf[rc] = talitos_read(sc->sc_base_addr +
11225 + TALITOS_RNG_FIFO + rc*sizeof(u_int32_t));
11226 + }
11227 + if (maxwords & 1) {
11228 + /*
11229 + * RNG will complain with an AE in the RNGISR
11230 + * if we don't complete the pairs of 32-bit reads
11231 + * to its 64-bit register based FIFO
11232 + */
11233 + v = talitos_read(sc->sc_base_addr +
11234 + TALITOS_RNG_FIFO + rc*sizeof(u_int32_t));
11235 + }
11236 +
11237 + return rc;
11238 +}
11239 +
11240 +static void
11241 +talitos_rng_init(struct talitos_softc *sc)
11242 +{
11243 + u_int32_t v;
11244 +
11245 + DPRINTF("%s()\n", __FUNCTION__);
11246 + /* reset RNG EU */
11247 + v = talitos_read(sc->sc_base_addr + TALITOS_RNGRCR_HI);
11248 + v |= TALITOS_RNGRCR_HI_SR;
11249 + talitos_write(sc->sc_base_addr + TALITOS_RNGRCR_HI, v);
11250 + while ((talitos_read(sc->sc_base_addr + TALITOS_RNGSR_HI)
11251 + & TALITOS_RNGSR_HI_RD) == 0)
11252 + cpu_relax();
11253 + /*
11254 + * we tell the RNG to start filling the RNG FIFO
11255 + * by writing the RNGDSR
11256 + */
11257 + v = talitos_read(sc->sc_base_addr + TALITOS_RNGDSR_HI);
11258 + talitos_write(sc->sc_base_addr + TALITOS_RNGDSR_HI, v);
11259 + /*
11260 + * 64 bits of data will be pushed onto the FIFO every
11261 + * 256 SEC cycles until the FIFO is full. The RNG then
11262 + * attempts to keep the FIFO full.
11263 + */
11264 + v = talitos_read(sc->sc_base_addr + TALITOS_RNGISR_HI);
11265 + if (v) {
11266 + printk(KERN_ERR "%s: RNGISR_HI error %08x\n",
11267 + device_get_nameunit(sc->sc_cdev), v);
11268 + return;
11269 + }
11270 + /*
11271 + * n.b. we need to add a FIPS test here - if the RNG is going
11272 + * to fail, it's going to fail at reset time
11273 + */
11274 + return;
11275 +}
11276 +#endif /* CONFIG_OCF_RANDOMHARVEST */
11277 +
11278 +/*
11279 + * Generate a new software session.
11280 + */
11281 +static int
11282 +talitos_newsession(device_t dev, u_int32_t *sidp, struct cryptoini *cri)
11283 +{
11284 + struct cryptoini *c, *encini = NULL, *macini = NULL;
11285 + struct talitos_softc *sc = device_get_softc(dev);
11286 + struct talitos_session *ses = NULL;
11287 + int sesn;
11288 +
11289 + DPRINTF("%s()\n", __FUNCTION__);
11290 + if (sidp == NULL || cri == NULL || sc == NULL) {
11291 + DPRINTF("%s,%d - EINVAL\n", __FILE__, __LINE__);
11292 + return EINVAL;
11293 + }
11294 + for (c = cri; c != NULL; c = c->cri_next) {
11295 + if (c->cri_alg == CRYPTO_MD5 ||
11296 + c->cri_alg == CRYPTO_MD5_HMAC ||
11297 + c->cri_alg == CRYPTO_SHA1 ||
11298 + c->cri_alg == CRYPTO_SHA1_HMAC ||
11299 + c->cri_alg == CRYPTO_NULL_HMAC) {
11300 + if (macini)
11301 + return EINVAL;
11302 + macini = c;
11303 + } else if (c->cri_alg == CRYPTO_DES_CBC ||
11304 + c->cri_alg == CRYPTO_3DES_CBC ||
11305 + c->cri_alg == CRYPTO_AES_CBC ||
11306 + c->cri_alg == CRYPTO_NULL_CBC) {
11307 + if (encini)
11308 + return EINVAL;
11309 + encini = c;
11310 + } else {
11311 + DPRINTF("UNKNOWN c->cri_alg %d\n", encini->cri_alg);
11312 + return EINVAL;
11313 + }
11314 + }
11315 + if (encini == NULL && macini == NULL)
11316 + return EINVAL;
11317 + if (encini) {
11318 + /* validate key length */
11319 + switch (encini->cri_alg) {
11320 + case CRYPTO_DES_CBC:
11321 + if (encini->cri_klen != 64)
11322 + return EINVAL;
11323 + break;
11324 + case CRYPTO_3DES_CBC:
11325 + if (encini->cri_klen != 192) {
11326 + return EINVAL;
11327 + }
11328 + break;
11329 + case CRYPTO_AES_CBC:
11330 + if (encini->cri_klen != 128 &&
11331 + encini->cri_klen != 192 &&
11332 + encini->cri_klen != 256)
11333 + return EINVAL;
11334 + break;
11335 + default:
11336 + DPRINTF("UNKNOWN encini->cri_alg %d\n",
11337 + encini->cri_alg);
11338 + return EINVAL;
11339 + }
11340 + }
11341 +
11342 + if (sc->sc_sessions == NULL) {
11343 + ses = sc->sc_sessions = (struct talitos_session *)
11344 + kmalloc(sizeof(struct talitos_session), SLAB_ATOMIC);
11345 + if (ses == NULL)
11346 + return ENOMEM;
11347 + memset(ses, 0, sizeof(struct talitos_session));
11348 + sesn = 0;
11349 + sc->sc_nsessions = 1;
11350 + } else {
11351 + for (sesn = 0; sesn < sc->sc_nsessions; sesn++) {
11352 + if (sc->sc_sessions[sesn].ses_used == 0) {
11353 + ses = &sc->sc_sessions[sesn];
11354 + break;
11355 + }
11356 + }
11357 +
11358 + if (ses == NULL) {
11359 + /* allocating session */
11360 + sesn = sc->sc_nsessions;
11361 + ses = (struct talitos_session *) kmalloc(
11362 + (sesn + 1) * sizeof(struct talitos_session),
11363 + SLAB_ATOMIC);
11364 + if (ses == NULL)
11365 + return ENOMEM;
11366 + memset(ses, 0,
11367 + (sesn + 1) * sizeof(struct talitos_session));
11368 + memcpy(ses, sc->sc_sessions,
11369 + sesn * sizeof(struct talitos_session));
11370 + memset(sc->sc_sessions, 0,
11371 + sesn * sizeof(struct talitos_session));
11372 + kfree(sc->sc_sessions);
11373 + sc->sc_sessions = ses;
11374 + ses = &sc->sc_sessions[sesn];
11375 + sc->sc_nsessions++;
11376 + }
11377 + }
11378 +
11379 + ses->ses_used = 1;
11380 +
11381 + if (encini) {
11382 + /* get an IV */
11383 + /* XXX may read fewer than requested */
11384 + read_random(ses->ses_iv, sizeof(ses->ses_iv));
11385 +
11386 + ses->ses_klen = (encini->cri_klen + 7) / 8;
11387 + memcpy(ses->ses_key, encini->cri_key, ses->ses_klen);
11388 + if (macini) {
11389 + /* doing hash on top of cipher */
11390 + ses->ses_hmac_len = (macini->cri_klen + 7) / 8;
11391 + memcpy(ses->ses_hmac, macini->cri_key,
11392 + ses->ses_hmac_len);
11393 + }
11394 + } else if (macini) {
11395 + /* doing hash */
11396 + ses->ses_klen = (macini->cri_klen + 7) / 8;
11397 + memcpy(ses->ses_key, macini->cri_key, ses->ses_klen);
11398 + }
11399 +
11400 + /* back compat way of determining MSC result len */
11401 + if (macini) {
11402 + ses->ses_mlen = macini->cri_mlen;
11403 + if (ses->ses_mlen == 0) {
11404 + if (macini->cri_alg == CRYPTO_MD5_HMAC)
11405 + ses->ses_mlen = MD5_HASH_LEN;
11406 + else
11407 + ses->ses_mlen = SHA1_HASH_LEN;
11408 + }
11409 + }
11410 +
11411 + /* really should make up a template td here,
11412 + * and only fill things like i/o and direction in process() */
11413 +
11414 + /* assign session ID */
11415 + *sidp = TALITOS_SID(sc->sc_num, sesn);
11416 + return 0;
11417 +}
11418 +
11419 +/*
11420 + * Deallocate a session.
11421 + */
11422 +static int
11423 +talitos_freesession(device_t dev, u_int64_t tid)
11424 +{
11425 + struct talitos_softc *sc = device_get_softc(dev);
11426 + int session, ret;
11427 + u_int32_t sid = ((u_int32_t) tid) & 0xffffffff;
11428 +
11429 + if (sc == NULL)
11430 + return EINVAL;
11431 + session = TALITOS_SESSION(sid);
11432 + if (session < sc->sc_nsessions) {
11433 + memset(&sc->sc_sessions[session], 0,
11434 + sizeof(sc->sc_sessions[session]));
11435 + ret = 0;
11436 + } else
11437 + ret = EINVAL;
11438 + return ret;
11439 +}
11440 +
11441 +/*
11442 + * launch device processing - it will come back with done notification
11443 + * in the form of an interrupt and/or HDR_DONE_BITS in header
11444 + */
11445 +static int
11446 +talitos_submit(
11447 + struct talitos_softc *sc,
11448 + struct talitos_desc *td,
11449 + int chsel)
11450 +{
11451 + u_int32_t v;
11452 +
11453 + v = dma_map_single(NULL, td, sizeof(*td), DMA_TO_DEVICE);
11454 + talitos_write(sc->sc_base_addr +
11455 + chsel*TALITOS_CH_OFFSET + TALITOS_CH_FF, 0);
11456 + talitos_write(sc->sc_base_addr +
11457 + chsel*TALITOS_CH_OFFSET + TALITOS_CH_FF_HI, v);
11458 + return 0;
11459 +}
11460 +
11461 +static int
11462 +talitos_process(device_t dev, struct cryptop *crp, int hint)
11463 +{
11464 + int i, err = 0, ivsize;
11465 + struct talitos_softc *sc = device_get_softc(dev);
11466 + struct cryptodesc *crd1, *crd2, *maccrd, *enccrd;
11467 + caddr_t iv;
11468 + struct talitos_session *ses;
11469 + struct talitos_desc *td;
11470 + unsigned long flags;
11471 + /* descriptor mappings */
11472 + int hmac_key, hmac_data, cipher_iv, cipher_key,
11473 + in_fifo, out_fifo, cipher_iv_out;
11474 + static int chsel = -1;
11475 +
11476 + DPRINTF("%s()\n", __FUNCTION__);
11477 +
11478 + if (crp == NULL || crp->crp_callback == NULL || sc == NULL) {
11479 + return EINVAL;
11480 + }
11481 + crp->crp_etype = 0;
11482 + if (TALITOS_SESSION(crp->crp_sid) >= sc->sc_nsessions) {
11483 + return EINVAL;
11484 + }
11485 +
11486 + ses = &sc->sc_sessions[TALITOS_SESSION(crp->crp_sid)];
11487 +
11488 + /* enter the channel scheduler */
11489 + spin_lock_irqsave(&sc->sc_chnfifolock[sc->sc_num_channels], flags);
11490 +
11491 + /* reuse channel that already had/has requests for the required EU */
11492 + for (i = 0; i < sc->sc_num_channels; i++) {
11493 + if (sc->sc_chnlastalg[i] == crp->crp_desc->crd_alg)
11494 + break;
11495 + }
11496 + if (i == sc->sc_num_channels) {
11497 + /*
11498 + * haven't seen this algo the last sc_num_channels or more
11499 + * use round robin in this case
11500 + * nb: sc->sc_num_channels must be power of 2
11501 + */
11502 + chsel = (chsel + 1) & (sc->sc_num_channels - 1);
11503 + } else {
11504 + /*
11505 + * matches channel with same target execution unit;
11506 + * use same channel in this case
11507 + */
11508 + chsel = i;
11509 + }
11510 + sc->sc_chnlastalg[chsel] = crp->crp_desc->crd_alg;
11511 +
11512 + /* release the channel scheduler lock */
11513 + spin_unlock_irqrestore(&sc->sc_chnfifolock[sc->sc_num_channels], flags);
11514 +
11515 + /* acquire the selected channel fifo lock */
11516 + spin_lock_irqsave(&sc->sc_chnfifolock[chsel], flags);
11517 +
11518 + /* find and reserve next available descriptor-cryptop pair */
11519 + for (i = 0; i < sc->sc_chfifo_len; i++) {
11520 + if (sc->sc_chnfifo[chsel][i].cf_desc.hdr == 0) {
11521 + /*
11522 + * ensure correct descriptor formation by
11523 + * avoiding inadvertently setting "optional" entries
11524 + * e.g. not using "optional" dptr2 for MD/HMAC descs
11525 + */
11526 + memset(&sc->sc_chnfifo[chsel][i].cf_desc,
11527 + 0, sizeof(*td));
11528 + /* reserve it with done notification request bit */
11529 + sc->sc_chnfifo[chsel][i].cf_desc.hdr |=
11530 + TALITOS_DONE_NOTIFY;
11531 + break;
11532 + }
11533 + }
11534 + spin_unlock_irqrestore(&sc->sc_chnfifolock[chsel], flags);
11535 +
11536 + if (i == sc->sc_chfifo_len) {
11537 + /* fifo full */
11538 + err = ERESTART;
11539 + goto errout;
11540 + }
11541 +
11542 + td = &sc->sc_chnfifo[chsel][i].cf_desc;
11543 + sc->sc_chnfifo[chsel][i].cf_crp = crp;
11544 +
11545 + crd1 = crp->crp_desc;
11546 + if (crd1 == NULL) {
11547 + err = EINVAL;
11548 + goto errout;
11549 + }
11550 + crd2 = crd1->crd_next;
11551 + /* prevent compiler warning */
11552 + hmac_key = 0;
11553 + hmac_data = 0;
11554 + if (crd2 == NULL) {
11555 + td->hdr |= TD_TYPE_COMMON_NONSNOOP_NO_AFEU;
11556 + /* assign descriptor dword ptr mappings for this desc. type */
11557 + cipher_iv = 1;
11558 + cipher_key = 2;
11559 + in_fifo = 3;
11560 + cipher_iv_out = 5;
11561 + if (crd1->crd_alg == CRYPTO_MD5_HMAC ||
11562 + crd1->crd_alg == CRYPTO_SHA1_HMAC ||
11563 + crd1->crd_alg == CRYPTO_SHA1 ||
11564 + crd1->crd_alg == CRYPTO_MD5) {
11565 + out_fifo = 5;
11566 + maccrd = crd1;
11567 + enccrd = NULL;
11568 + } else if (crd1->crd_alg == CRYPTO_DES_CBC ||
11569 + crd1->crd_alg == CRYPTO_3DES_CBC ||
11570 + crd1->crd_alg == CRYPTO_AES_CBC ||
11571 + crd1->crd_alg == CRYPTO_ARC4) {
11572 + out_fifo = 4;
11573 + maccrd = NULL;
11574 + enccrd = crd1;
11575 + } else {
11576 + DPRINTF("UNKNOWN crd1->crd_alg %d\n", crd1->crd_alg);
11577 + err = EINVAL;
11578 + goto errout;
11579 + }
11580 + } else {
11581 + if (sc->sc_desc_types & TALITOS_HAS_DT_IPSEC_ESP) {
11582 + td->hdr |= TD_TYPE_IPSEC_ESP;
11583 + } else {
11584 + DPRINTF("unimplemented: multiple descriptor ipsec\n");
11585 + err = EINVAL;
11586 + goto errout;
11587 + }
11588 + /* assign descriptor dword ptr mappings for this desc. type */
11589 + hmac_key = 0;
11590 + hmac_data = 1;
11591 + cipher_iv = 2;
11592 + cipher_key = 3;
11593 + in_fifo = 4;
11594 + out_fifo = 5;
11595 + cipher_iv_out = 6;
11596 + if ((crd1->crd_alg == CRYPTO_MD5_HMAC ||
11597 + crd1->crd_alg == CRYPTO_SHA1_HMAC ||
11598 + crd1->crd_alg == CRYPTO_MD5 ||
11599 + crd1->crd_alg == CRYPTO_SHA1) &&
11600 + (crd2->crd_alg == CRYPTO_DES_CBC ||
11601 + crd2->crd_alg == CRYPTO_3DES_CBC ||
11602 + crd2->crd_alg == CRYPTO_AES_CBC ||
11603 + crd2->crd_alg == CRYPTO_ARC4) &&
11604 + ((crd2->crd_flags & CRD_F_ENCRYPT) == 0)) {
11605 + maccrd = crd1;
11606 + enccrd = crd2;
11607 + } else if ((crd1->crd_alg == CRYPTO_DES_CBC ||
11608 + crd1->crd_alg == CRYPTO_ARC4 ||
11609 + crd1->crd_alg == CRYPTO_3DES_CBC ||
11610 + crd1->crd_alg == CRYPTO_AES_CBC) &&
11611 + (crd2->crd_alg == CRYPTO_MD5_HMAC ||
11612 + crd2->crd_alg == CRYPTO_SHA1_HMAC ||
11613 + crd2->crd_alg == CRYPTO_MD5 ||
11614 + crd2->crd_alg == CRYPTO_SHA1) &&
11615 + (crd1->crd_flags & CRD_F_ENCRYPT)) {
11616 + enccrd = crd1;
11617 + maccrd = crd2;
11618 + } else {
11619 + /* We cannot order the SEC as requested */
11620 + printk("%s: cannot do the order\n",
11621 + device_get_nameunit(sc->sc_cdev));
11622 + err = EINVAL;
11623 + goto errout;
11624 + }
11625 + }
11626 + /* assign in_fifo and out_fifo based on input/output struct type */
11627 + if (crp->crp_flags & CRYPTO_F_SKBUF) {
11628 + /* using SKB buffers */
11629 + struct sk_buff *skb = (struct sk_buff *)crp->crp_buf;
11630 + if (skb_shinfo(skb)->nr_frags) {
11631 + printk("%s: skb frags unimplemented\n",
11632 + device_get_nameunit(sc->sc_cdev));
11633 + err = EINVAL;
11634 + goto errout;
11635 + }
11636 + td->ptr[in_fifo].ptr = dma_map_single(NULL, skb->data,
11637 + skb->len, DMA_TO_DEVICE);
11638 + td->ptr[in_fifo].len = skb->len;
11639 + td->ptr[out_fifo].ptr = dma_map_single(NULL, skb->data,
11640 + skb->len, DMA_TO_DEVICE);
11641 + td->ptr[out_fifo].len = skb->len;
11642 + td->ptr[hmac_data].ptr = dma_map_single(NULL, skb->data,
11643 + skb->len, DMA_TO_DEVICE);
11644 + } else if (crp->crp_flags & CRYPTO_F_IOV) {
11645 + /* using IOV buffers */
11646 + struct uio *uiop = (struct uio *)crp->crp_buf;
11647 + if (uiop->uio_iovcnt > 1) {
11648 + printk("%s: iov frags unimplemented\n",
11649 + device_get_nameunit(sc->sc_cdev));
11650 + err = EINVAL;
11651 + goto errout;
11652 + }
11653 + td->ptr[in_fifo].ptr = dma_map_single(NULL,
11654 + uiop->uio_iov->iov_base, crp->crp_ilen, DMA_TO_DEVICE);
11655 + td->ptr[in_fifo].len = crp->crp_ilen;
11656 + /* crp_olen is never set; always use crp_ilen */
11657 + td->ptr[out_fifo].ptr = dma_map_single(NULL,
11658 + uiop->uio_iov->iov_base,
11659 + crp->crp_ilen, DMA_TO_DEVICE);
11660 + td->ptr[out_fifo].len = crp->crp_ilen;
11661 + } else {
11662 + /* using contig buffers */
11663 + td->ptr[in_fifo].ptr = dma_map_single(NULL,
11664 + crp->crp_buf, crp->crp_ilen, DMA_TO_DEVICE);
11665 + td->ptr[in_fifo].len = crp->crp_ilen;
11666 + td->ptr[out_fifo].ptr = dma_map_single(NULL,
11667 + crp->crp_buf, crp->crp_ilen, DMA_TO_DEVICE);
11668 + td->ptr[out_fifo].len = crp->crp_ilen;
11669 + }
11670 + if (enccrd) {
11671 + switch (enccrd->crd_alg) {
11672 + case CRYPTO_3DES_CBC:
11673 + td->hdr |= TALITOS_MODE0_DEU_3DES;
11674 + /* FALLTHROUGH */
11675 + case CRYPTO_DES_CBC:
11676 + td->hdr |= TALITOS_SEL0_DEU
11677 + | TALITOS_MODE0_DEU_CBC;
11678 + if (enccrd->crd_flags & CRD_F_ENCRYPT)
11679 + td->hdr |= TALITOS_MODE0_DEU_ENC;
11680 + ivsize = 2*sizeof(u_int32_t);
11681 + DPRINTF("%cDES ses %d ch %d len %d\n",
11682 + (td->hdr & TALITOS_MODE0_DEU_3DES)?'3':'1',
11683 + (u32)TALITOS_SESSION(crp->crp_sid),
11684 + chsel, td->ptr[in_fifo].len);
11685 + break;
11686 + case CRYPTO_AES_CBC:
11687 + td->hdr |= TALITOS_SEL0_AESU
11688 + | TALITOS_MODE0_AESU_CBC;
11689 + if (enccrd->crd_flags & CRD_F_ENCRYPT)
11690 + td->hdr |= TALITOS_MODE0_AESU_ENC;
11691 + ivsize = 4*sizeof(u_int32_t);
11692 + DPRINTF("AES ses %d ch %d len %d\n",
11693 + (u32)TALITOS_SESSION(crp->crp_sid),
11694 + chsel, td->ptr[in_fifo].len);
11695 + break;
11696 + default:
11697 + printk("%s: unimplemented enccrd->crd_alg %d\n",
11698 + device_get_nameunit(sc->sc_cdev), enccrd->crd_alg);
11699 + err = EINVAL;
11700 + goto errout;
11701 + }
11702 + /*
11703 + * Setup encrypt/decrypt state. When using basic ops
11704 + * we can't use an inline IV because hash/crypt offset
11705 + * must be from the end of the IV to the start of the
11706 + * crypt data and this leaves out the preceding header
11707 + * from the hash calculation. Instead we place the IV
11708 + * in the state record and set the hash/crypt offset to
11709 + * copy both the header+IV.
11710 + */
11711 + if (enccrd->crd_flags & CRD_F_ENCRYPT) {
11712 + td->hdr |= TALITOS_DIR_OUTBOUND;
11713 + if (enccrd->crd_flags & CRD_F_IV_EXPLICIT)
11714 + iv = enccrd->crd_iv;
11715 + else
11716 + iv = (caddr_t) ses->ses_iv;
11717 + if ((enccrd->crd_flags & CRD_F_IV_PRESENT) == 0) {
11718 + crypto_copyback(crp->crp_flags, crp->crp_buf,
11719 + enccrd->crd_inject, ivsize, iv);
11720 + }
11721 + } else {
11722 + td->hdr |= TALITOS_DIR_INBOUND;
11723 + if (enccrd->crd_flags & CRD_F_IV_EXPLICIT) {
11724 + iv = enccrd->crd_iv;
11725 + bcopy(enccrd->crd_iv, iv, ivsize);
11726 + } else {
11727 + iv = (caddr_t) ses->ses_iv;
11728 + crypto_copydata(crp->crp_flags, crp->crp_buf,
11729 + enccrd->crd_inject, ivsize, iv);
11730 + }
11731 + }
11732 + td->ptr[cipher_iv].ptr = dma_map_single(NULL, iv, ivsize,
11733 + DMA_TO_DEVICE);
11734 + td->ptr[cipher_iv].len = ivsize;
11735 + /*
11736 + * we don't need the cipher iv out length/pointer
11737 + * field to do ESP IPsec. Therefore we set the len field as 0,
11738 + * which tells the SEC not to do anything with this len/ptr
11739 + * field. Previously, when length/pointer as pointing to iv,
11740 + * it gave us corruption of packets.
11741 + */
11742 + td->ptr[cipher_iv_out].len = 0;
11743 + }
11744 + if (enccrd && maccrd) {
11745 + /* this is ipsec only for now */
11746 + td->hdr |= TALITOS_SEL1_MDEU
11747 + | TALITOS_MODE1_MDEU_INIT
11748 + | TALITOS_MODE1_MDEU_PAD;
11749 + switch (maccrd->crd_alg) {
11750 + case CRYPTO_MD5:
11751 + td->hdr |= TALITOS_MODE1_MDEU_MD5;
11752 + break;
11753 + case CRYPTO_MD5_HMAC:
11754 + td->hdr |= TALITOS_MODE1_MDEU_MD5_HMAC;
11755 + break;
11756 + case CRYPTO_SHA1:
11757 + td->hdr |= TALITOS_MODE1_MDEU_SHA1;
11758 + break;
11759 + case CRYPTO_SHA1_HMAC:
11760 + td->hdr |= TALITOS_MODE1_MDEU_SHA1_HMAC;
11761 + break;
11762 + default:
11763 + /* We cannot order the SEC as requested */
11764 + printk("%s: cannot do the order\n",
11765 + device_get_nameunit(sc->sc_cdev));
11766 + err = EINVAL;
11767 + goto errout;
11768 + }
11769 + if ((maccrd->crd_alg == CRYPTO_MD5_HMAC) ||
11770 + (maccrd->crd_alg == CRYPTO_SHA1_HMAC)) {
11771 + /*
11772 + * The offset from hash data to the start of
11773 + * crypt data is the difference in the skips.
11774 + */
11775 + /* ipsec only for now */
11776 + td->ptr[hmac_key].ptr = dma_map_single(NULL,
11777 + ses->ses_hmac, ses->ses_hmac_len, DMA_TO_DEVICE);
11778 + td->ptr[hmac_key].len = ses->ses_hmac_len;
11779 + td->ptr[in_fifo].ptr += enccrd->crd_skip;
11780 + td->ptr[in_fifo].len = enccrd->crd_len;
11781 + td->ptr[out_fifo].ptr += enccrd->crd_skip;
11782 + td->ptr[out_fifo].len = enccrd->crd_len;
11783 + /* bytes of HMAC to postpend to ciphertext */
11784 + td->ptr[out_fifo].extent = ses->ses_mlen;
11785 + td->ptr[hmac_data].ptr += maccrd->crd_skip;
11786 + td->ptr[hmac_data].len = enccrd->crd_skip - maccrd->crd_skip;
11787 + }
11788 + if (enccrd->crd_flags & CRD_F_KEY_EXPLICIT) {
11789 + printk("%s: CRD_F_KEY_EXPLICIT unimplemented\n",
11790 + device_get_nameunit(sc->sc_cdev));
11791 + }
11792 + }
11793 + if (!enccrd && maccrd) {
11794 + /* single MD5 or SHA */
11795 + td->hdr |= TALITOS_SEL0_MDEU
11796 + | TALITOS_MODE0_MDEU_INIT
11797 + | TALITOS_MODE0_MDEU_PAD;
11798 + switch (maccrd->crd_alg) {
11799 + case CRYPTO_MD5:
11800 + td->hdr |= TALITOS_MODE0_MDEU_MD5;
11801 + DPRINTF("MD5 ses %d ch %d len %d\n",
11802 + (u32)TALITOS_SESSION(crp->crp_sid),
11803 + chsel, td->ptr[in_fifo].len);
11804 + break;
11805 + case CRYPTO_MD5_HMAC:
11806 + td->hdr |= TALITOS_MODE0_MDEU_MD5_HMAC;
11807 + break;
11808 + case CRYPTO_SHA1:
11809 + td->hdr |= TALITOS_MODE0_MDEU_SHA1;
11810 + DPRINTF("SHA1 ses %d ch %d len %d\n",
11811 + (u32)TALITOS_SESSION(crp->crp_sid),
11812 + chsel, td->ptr[in_fifo].len);
11813 + break;
11814 + case CRYPTO_SHA1_HMAC:
11815 + td->hdr |= TALITOS_MODE0_MDEU_SHA1_HMAC;
11816 + break;
11817 + default:
11818 + /* We cannot order the SEC as requested */
11819 + DPRINTF("cannot do the order\n");
11820 + err = EINVAL;
11821 + goto errout;
11822 + }
11823 +
11824 + if (crp->crp_flags & CRYPTO_F_IOV)
11825 + td->ptr[out_fifo].ptr += maccrd->crd_inject;
11826 +
11827 + if ((maccrd->crd_alg == CRYPTO_MD5_HMAC) ||
11828 + (maccrd->crd_alg == CRYPTO_SHA1_HMAC)) {
11829 + td->ptr[hmac_key].ptr = dma_map_single(NULL,
11830 + ses->ses_hmac, ses->ses_hmac_len,
11831 + DMA_TO_DEVICE);
11832 + td->ptr[hmac_key].len = ses->ses_hmac_len;
11833 + }
11834 + }
11835 + else {
11836 + /* using process key (session data has duplicate) */
11837 + td->ptr[cipher_key].ptr = dma_map_single(NULL,
11838 + enccrd->crd_key, (enccrd->crd_klen + 7) / 8,
11839 + DMA_TO_DEVICE);
11840 + td->ptr[cipher_key].len = (enccrd->crd_klen + 7) / 8;
11841 + }
11842 + /* descriptor complete - GO! */
11843 + return talitos_submit(sc, td, chsel);
11844 +
11845 +errout:
11846 + if (err != ERESTART) {
11847 + crp->crp_etype = err;
11848 + crypto_done(crp);
11849 + }
11850 + return err;
11851 +}
11852 +
11853 +/* go through all channels descriptors, notifying OCF what has
11854 + * _and_hasn't_ successfully completed and reset the device
11855 + * (otherwise it's up to decoding desc hdrs!)
11856 + */
11857 +static void talitos_errorprocessing(struct talitos_softc *sc)
11858 +{
11859 + unsigned long flags;
11860 + int i, j;
11861 +
11862 + /* disable further scheduling until under control */
11863 + spin_lock_irqsave(&sc->sc_chnfifolock[sc->sc_num_channels], flags);
11864 +
11865 + if (debug) dump_talitos_status(sc);
11866 + /* go through descriptors, try and salvage those successfully done,
11867 + * and EIO those that weren't
11868 + */
11869 + for (i = 0; i < sc->sc_num_channels; i++) {
11870 + spin_lock_irqsave(&sc->sc_chnfifolock[i], flags);
11871 + for (j = 0; j < sc->sc_chfifo_len; j++) {
11872 + if (sc->sc_chnfifo[i][j].cf_desc.hdr) {
11873 + if ((sc->sc_chnfifo[i][j].cf_desc.hdr
11874 + & TALITOS_HDR_DONE_BITS)
11875 + != TALITOS_HDR_DONE_BITS) {
11876 + /* this one didn't finish */
11877 + /* signify in crp->etype */
11878 + sc->sc_chnfifo[i][j].cf_crp->crp_etype
11879 + = EIO;
11880 + }
11881 + } else
11882 + continue; /* free entry */
11883 + /* either way, notify ocf */
11884 + crypto_done(sc->sc_chnfifo[i][j].cf_crp);
11885 + /* and tag it available again
11886 + *
11887 + * memset to ensure correct descriptor formation by
11888 + * avoiding inadvertently setting "optional" entries
11889 + * e.g. not using "optional" dptr2 MD/HMAC processing
11890 + */
11891 + memset(&sc->sc_chnfifo[i][j].cf_desc,
11892 + 0, sizeof(struct talitos_desc));
11893 + }
11894 + spin_unlock_irqrestore(&sc->sc_chnfifolock[i], flags);
11895 + }
11896 + /* reset and initialize the SEC h/w device */
11897 + talitos_reset_device(sc);
11898 + talitos_init_device(sc);
11899 +#ifdef CONFIG_OCF_RANDOMHARVEST
11900 + if (sc->sc_exec_units & TALITOS_HAS_EU_RNG)
11901 + talitos_rng_init(sc);
11902 +#endif
11903 +
11904 + /* Okay. Stand by. */
11905 + spin_unlock_irqrestore(&sc->sc_chnfifolock[sc->sc_num_channels], flags);
11906 +
11907 + return;
11908 +}
11909 +
11910 +/* go through all channels descriptors, notifying OCF what's been done */
11911 +static void talitos_doneprocessing(struct talitos_softc *sc)
11912 +{
11913 + unsigned long flags;
11914 + int i, j;
11915 +
11916 + /* go through descriptors looking for done bits */
11917 + for (i = 0; i < sc->sc_num_channels; i++) {
11918 + spin_lock_irqsave(&sc->sc_chnfifolock[i], flags);
11919 + for (j = 0; j < sc->sc_chfifo_len; j++) {
11920 + /* descriptor has done bits set? */
11921 + if ((sc->sc_chnfifo[i][j].cf_desc.hdr
11922 + & TALITOS_HDR_DONE_BITS)
11923 + == TALITOS_HDR_DONE_BITS) {
11924 + /* notify ocf */
11925 + crypto_done(sc->sc_chnfifo[i][j].cf_crp);
11926 + /* and tag it available again
11927 + *
11928 + * memset to ensure correct descriptor formation by
11929 + * avoiding inadvertently setting "optional" entries
11930 + * e.g. not using "optional" dptr2 MD/HMAC processing
11931 + */
11932 + memset(&sc->sc_chnfifo[i][j].cf_desc,
11933 + 0, sizeof(struct talitos_desc));
11934 + }
11935 + }
11936 + spin_unlock_irqrestore(&sc->sc_chnfifolock[i], flags);
11937 + }
11938 + return;
11939 +}
11940 +
11941 +static irqreturn_t
11942 +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,19)
11943 +talitos_intr(int irq, void *arg)
11944 +#else
11945 +talitos_intr(int irq, void *arg, struct pt_regs *regs)
11946 +#endif
11947 +{
11948 + struct talitos_softc *sc = arg;
11949 + u_int32_t v, v_hi;
11950 +
11951 + /* ack */
11952 + v = talitos_read(sc->sc_base_addr + TALITOS_ISR);
11953 + v_hi = talitos_read(sc->sc_base_addr + TALITOS_ISR_HI);
11954 + talitos_write(sc->sc_base_addr + TALITOS_ICR, v);
11955 + talitos_write(sc->sc_base_addr + TALITOS_ICR_HI, v_hi);
11956 +
11957 + if (unlikely(v & TALITOS_ISR_ERROR)) {
11958 + /* Okay, Houston, we've had a problem here. */
11959 + printk(KERN_DEBUG "%s: got error interrupt - ISR 0x%08x_%08x\n",
11960 + device_get_nameunit(sc->sc_cdev), v, v_hi);
11961 + talitos_errorprocessing(sc);
11962 + } else
11963 + if (likely(v & TALITOS_ISR_DONE)) {
11964 + talitos_doneprocessing(sc);
11965 + }
11966 + return IRQ_HANDLED;
11967 +}
11968 +
11969 +/*
11970 + * Initialize registers we need to touch only once.
11971 + */
11972 +static void
11973 +talitos_init_device(struct talitos_softc *sc)
11974 +{
11975 + u_int32_t v;
11976 + int i;
11977 +
11978 + DPRINTF("%s()\n", __FUNCTION__);
11979 +
11980 + /* init all channels */
11981 + for (i = 0; i < sc->sc_num_channels; i++) {
11982 + v = talitos_read(sc->sc_base_addr +
11983 + i*TALITOS_CH_OFFSET + TALITOS_CH_CCCR_HI);
11984 + v |= TALITOS_CH_CCCR_HI_CDWE
11985 + | TALITOS_CH_CCCR_HI_CDIE; /* invoke interrupt if done */
11986 + talitos_write(sc->sc_base_addr +
11987 + i*TALITOS_CH_OFFSET + TALITOS_CH_CCCR_HI, v);
11988 + }
11989 + /* enable all interrupts */
11990 + v = talitos_read(sc->sc_base_addr + TALITOS_IMR);
11991 + v |= TALITOS_IMR_ALL;
11992 + talitos_write(sc->sc_base_addr + TALITOS_IMR, v);
11993 + v = talitos_read(sc->sc_base_addr + TALITOS_IMR_HI);
11994 + v |= TALITOS_IMR_HI_ERRONLY;
11995 + talitos_write(sc->sc_base_addr + TALITOS_IMR_HI, v);
11996 + return;
11997 +}
11998 +
11999 +/*
12000 + * set the master reset bit on the device.
12001 + */
12002 +static void
12003 +talitos_reset_device_master(struct talitos_softc *sc)
12004 +{
12005 + u_int32_t v;
12006 +
12007 + /* Reset the device by writing 1 to MCR:SWR and waiting 'til cleared */
12008 + v = talitos_read(sc->sc_base_addr + TALITOS_MCR);
12009 + talitos_write(sc->sc_base_addr + TALITOS_MCR, v | TALITOS_MCR_SWR);
12010 +
12011 + while (talitos_read(sc->sc_base_addr + TALITOS_MCR) & TALITOS_MCR_SWR)
12012 + cpu_relax();
12013 +
12014 + return;
12015 +}
12016 +
12017 +/*
12018 + * Resets the device. Values in the registers are left as is
12019 + * from the reset (i.e. initial values are assigned elsewhere).
12020 + */
12021 +static void
12022 +talitos_reset_device(struct talitos_softc *sc)
12023 +{
12024 + u_int32_t v;
12025 + int i;
12026 +
12027 + DPRINTF("%s()\n", __FUNCTION__);
12028 +
12029 + /*
12030 + * Master reset
12031 + * errata documentation: warning: certain SEC interrupts
12032 + * are not fully cleared by writing the MCR:SWR bit,
12033 + * set bit twice to completely reset
12034 + */
12035 + talitos_reset_device_master(sc); /* once */
12036 + talitos_reset_device_master(sc); /* and once again */
12037 +
12038 + /* reset all channels */
12039 + for (i = 0; i < sc->sc_num_channels; i++) {
12040 + v = talitos_read(sc->sc_base_addr + i*TALITOS_CH_OFFSET +
12041 + TALITOS_CH_CCCR);
12042 + talitos_write(sc->sc_base_addr + i*TALITOS_CH_OFFSET +
12043 + TALITOS_CH_CCCR, v | TALITOS_CH_CCCR_RESET);
12044 + }
12045 +}
12046 +
12047 +/* Set up the crypto device structure, private data,
12048 + * and anything else we need before we start */
12049 +#ifdef CONFIG_PPC_MERGE
12050 +static int talitos_probe(struct of_device *ofdev, const struct of_device_id *match)
12051 +#else
12052 +static int talitos_probe(struct platform_device *pdev)
12053 +#endif
12054 +{
12055 + struct talitos_softc *sc = NULL;
12056 + struct resource *r;
12057 +#ifdef CONFIG_PPC_MERGE
12058 + struct device *device = &ofdev->dev;
12059 + struct device_node *np = ofdev->node;
12060 + const unsigned int *prop;
12061 + int err;
12062 + struct resource res;
12063 +#endif
12064 + static int num_chips = 0;
12065 + int rc;
12066 + int i;
12067 +
12068 + DPRINTF("%s()\n", __FUNCTION__);
12069 +
12070 + sc = (struct talitos_softc *) kmalloc(sizeof(*sc), GFP_KERNEL);
12071 + if (!sc)
12072 + return -ENOMEM;
12073 + memset(sc, 0, sizeof(*sc));
12074 +
12075 + softc_device_init(sc, DRV_NAME, num_chips, talitos_methods);
12076 +
12077 + sc->sc_irq = -1;
12078 + sc->sc_cid = -1;
12079 +#ifndef CONFIG_PPC_MERGE
12080 + sc->sc_dev = pdev;
12081 +#endif
12082 + sc->sc_num = num_chips++;
12083 +
12084 +#ifdef CONFIG_PPC_MERGE
12085 + dev_set_drvdata(device, sc);
12086 +#else
12087 + platform_set_drvdata(sc->sc_dev, sc);
12088 +#endif
12089 +
12090 + /* get the irq line */
12091 +#ifdef CONFIG_PPC_MERGE
12092 + err = of_address_to_resource(np, 0, &res);
12093 + if (err)
12094 + return -EINVAL;
12095 + r = &res;
12096 +
12097 + sc->sc_irq = irq_of_parse_and_map(np, 0);
12098 +#else
12099 + /* get a pointer to the register memory */
12100 + r = platform_get_resource(pdev, IORESOURCE_MEM, 0);
12101 +
12102 + sc->sc_irq = platform_get_irq(pdev, 0);
12103 +#endif
12104 + rc = request_irq(sc->sc_irq, talitos_intr, 0,
12105 + device_get_nameunit(sc->sc_cdev), sc);
12106 + if (rc) {
12107 + printk(KERN_ERR "%s: failed to hook irq %d\n",
12108 + device_get_nameunit(sc->sc_cdev), sc->sc_irq);
12109 + sc->sc_irq = -1;
12110 + goto out;
12111 + }
12112 +
12113 + sc->sc_base_addr = (ocf_iomem_t) ioremap(r->start, (r->end - r->start));
12114 + if (!sc->sc_base_addr) {
12115 + printk(KERN_ERR "%s: failed to ioremap\n",
12116 + device_get_nameunit(sc->sc_cdev));
12117 + goto out;
12118 + }
12119 +
12120 + /* figure out our SEC's properties and capabilities */
12121 + sc->sc_chiprev = (u64)talitos_read(sc->sc_base_addr + TALITOS_ID) << 32
12122 + | talitos_read(sc->sc_base_addr + TALITOS_ID_HI);
12123 + DPRINTF("sec id 0x%llx\n", sc->sc_chiprev);
12124 +
12125 +#ifdef CONFIG_PPC_MERGE
12126 + /* get SEC properties from device tree, defaulting to SEC 2.0 */
12127 +
12128 + prop = of_get_property(np, "num-channels", NULL);
12129 + sc->sc_num_channels = prop ? *prop : TALITOS_NCHANNELS_SEC_2_0;
12130 +
12131 + prop = of_get_property(np, "channel-fifo-len", NULL);
12132 + sc->sc_chfifo_len = prop ? *prop : TALITOS_CHFIFOLEN_SEC_2_0;
12133 +
12134 + prop = of_get_property(np, "exec-units-mask", NULL);
12135 + sc->sc_exec_units = prop ? *prop : TALITOS_HAS_EUS_SEC_2_0;
12136 +
12137 + prop = of_get_property(np, "descriptor-types-mask", NULL);
12138 + sc->sc_desc_types = prop ? *prop : TALITOS_HAS_DESCTYPES_SEC_2_0;
12139 +#else
12140 + /* bulk should go away with openfirmware flat device tree support */
12141 + if (sc->sc_chiprev & TALITOS_ID_SEC_2_0) {
12142 + sc->sc_num_channels = TALITOS_NCHANNELS_SEC_2_0;
12143 + sc->sc_chfifo_len = TALITOS_CHFIFOLEN_SEC_2_0;
12144 + sc->sc_exec_units = TALITOS_HAS_EUS_SEC_2_0;
12145 + sc->sc_desc_types = TALITOS_HAS_DESCTYPES_SEC_2_0;
12146 + } else {
12147 + printk(KERN_ERR "%s: failed to id device\n",
12148 + device_get_nameunit(sc->sc_cdev));
12149 + goto out;
12150 + }
12151 +#endif
12152 +
12153 + /* + 1 is for the meta-channel lock used by the channel scheduler */
12154 + sc->sc_chnfifolock = (spinlock_t *) kmalloc(
12155 + (sc->sc_num_channels + 1) * sizeof(spinlock_t), GFP_KERNEL);
12156 + if (!sc->sc_chnfifolock)
12157 + goto out;
12158 + for (i = 0; i < sc->sc_num_channels + 1; i++) {
12159 + spin_lock_init(&sc->sc_chnfifolock[i]);
12160 + }
12161 +
12162 + sc->sc_chnlastalg = (int *) kmalloc(
12163 + sc->sc_num_channels * sizeof(int), GFP_KERNEL);
12164 + if (!sc->sc_chnlastalg)
12165 + goto out;
12166 + memset(sc->sc_chnlastalg, 0, sc->sc_num_channels * sizeof(int));
12167 +
12168 + sc->sc_chnfifo = (struct desc_cryptop_pair **) kmalloc(
12169 + sc->sc_num_channels * sizeof(struct desc_cryptop_pair *),
12170 + GFP_KERNEL);
12171 + if (!sc->sc_chnfifo)
12172 + goto out;
12173 + for (i = 0; i < sc->sc_num_channels; i++) {
12174 + sc->sc_chnfifo[i] = (struct desc_cryptop_pair *) kmalloc(
12175 + sc->sc_chfifo_len * sizeof(struct desc_cryptop_pair),
12176 + GFP_KERNEL);
12177 + if (!sc->sc_chnfifo[i])
12178 + goto out;
12179 + memset(sc->sc_chnfifo[i], 0,
12180 + sc->sc_chfifo_len * sizeof(struct desc_cryptop_pair));
12181 + }
12182 +
12183 + /* reset and initialize the SEC h/w device */
12184 + talitos_reset_device(sc);
12185 + talitos_init_device(sc);
12186 +
12187 + sc->sc_cid = crypto_get_driverid(softc_get_device(sc),CRYPTOCAP_F_HARDWARE);
12188 + if (sc->sc_cid < 0) {
12189 + printk(KERN_ERR "%s: could not get crypto driver id\n",
12190 + device_get_nameunit(sc->sc_cdev));
12191 + goto out;
12192 + }
12193 +
12194 + /* register algorithms with the framework */
12195 + printk("%s:", device_get_nameunit(sc->sc_cdev));
12196 +
12197 + if (sc->sc_exec_units & TALITOS_HAS_EU_RNG) {
12198 + printk(" rng");
12199 +#ifdef CONFIG_OCF_RANDOMHARVEST
12200 + talitos_rng_init(sc);
12201 + crypto_rregister(sc->sc_cid, talitos_read_random, sc);
12202 +#endif
12203 + }
12204 + if (sc->sc_exec_units & TALITOS_HAS_EU_DEU) {
12205 + printk(" des/3des");
12206 + crypto_register(sc->sc_cid, CRYPTO_3DES_CBC, 0, 0);
12207 + crypto_register(sc->sc_cid, CRYPTO_DES_CBC, 0, 0);
12208 + }
12209 + if (sc->sc_exec_units & TALITOS_HAS_EU_AESU) {
12210 + printk(" aes");
12211 + crypto_register(sc->sc_cid, CRYPTO_AES_CBC, 0, 0);
12212 + }
12213 + if (sc->sc_exec_units & TALITOS_HAS_EU_MDEU) {
12214 + printk(" md5");
12215 + crypto_register(sc->sc_cid, CRYPTO_MD5, 0, 0);
12216 + /* HMAC support only with IPsec for now */
12217 + crypto_register(sc->sc_cid, CRYPTO_MD5_HMAC, 0, 0);
12218 + printk(" sha1");
12219 + crypto_register(sc->sc_cid, CRYPTO_SHA1, 0, 0);
12220 + /* HMAC support only with IPsec for now */
12221 + crypto_register(sc->sc_cid, CRYPTO_SHA1_HMAC, 0, 0);
12222 + }
12223 + printk("\n");
12224 + return 0;
12225 +
12226 +out:
12227 +#ifndef CONFIG_PPC_MERGE
12228 + talitos_remove(pdev);
12229 +#endif
12230 + return -ENOMEM;
12231 +}
12232 +
12233 +#ifdef CONFIG_PPC_MERGE
12234 +static int talitos_remove(struct of_device *ofdev)
12235 +#else
12236 +static int talitos_remove(struct platform_device *pdev)
12237 +#endif
12238 +{
12239 +#ifdef CONFIG_PPC_MERGE
12240 + struct talitos_softc *sc = dev_get_drvdata(&ofdev->dev);
12241 +#else
12242 + struct talitos_softc *sc = platform_get_drvdata(pdev);
12243 +#endif
12244 + int i;
12245 +
12246 + DPRINTF("%s()\n", __FUNCTION__);
12247 + if (sc->sc_cid >= 0)
12248 + crypto_unregister_all(sc->sc_cid);
12249 + if (sc->sc_chnfifo) {
12250 + for (i = 0; i < sc->sc_num_channels; i++)
12251 + if (sc->sc_chnfifo[i])
12252 + kfree(sc->sc_chnfifo[i]);
12253 + kfree(sc->sc_chnfifo);
12254 + }
12255 + if (sc->sc_chnlastalg)
12256 + kfree(sc->sc_chnlastalg);
12257 + if (sc->sc_chnfifolock)
12258 + kfree(sc->sc_chnfifolock);
12259 + if (sc->sc_irq != -1)
12260 + free_irq(sc->sc_irq, sc);
12261 + if (sc->sc_base_addr)
12262 + iounmap((void *) sc->sc_base_addr);
12263 + kfree(sc);
12264 + return 0;
12265 +}
12266 +
12267 +#ifdef CONFIG_PPC_MERGE
12268 +static struct of_device_id talitos_match[] = {
12269 + {
12270 + .type = "crypto",
12271 + .compatible = "talitos",
12272 + },
12273 + {},
12274 +};
12275 +
12276 +MODULE_DEVICE_TABLE(of, talitos_match);
12277 +
12278 +static struct of_platform_driver talitos_driver = {
12279 + .name = DRV_NAME,
12280 + .match_table = talitos_match,
12281 + .probe = talitos_probe,
12282 + .remove = talitos_remove,
12283 +};
12284 +
12285 +static int __init talitos_init(void)
12286 +{
12287 + return of_register_platform_driver(&talitos_driver);
12288 +}
12289 +
12290 +static void __exit talitos_exit(void)
12291 +{
12292 + of_unregister_platform_driver(&talitos_driver);
12293 +}
12294 +#else
12295 +/* Structure for a platform device driver */
12296 +static struct platform_driver talitos_driver = {
12297 + .probe = talitos_probe,
12298 + .remove = talitos_remove,
12299 + .driver = {
12300 + .name = "fsl-sec2",
12301 + }
12302 +};
12303 +
12304 +static int __init talitos_init(void)
12305 +{
12306 + return platform_driver_register(&talitos_driver);
12307 +}
12308 +
12309 +static void __exit talitos_exit(void)
12310 +{
12311 + platform_driver_unregister(&talitos_driver);
12312 +}
12313 +#endif
12314 +
12315 +module_init(talitos_init);
12316 +module_exit(talitos_exit);
12317 +
12318 +MODULE_LICENSE("Dual BSD/GPL");
12319 +MODULE_AUTHOR("kim.phillips@freescale.com");
12320 +MODULE_DESCRIPTION("OCF driver for Freescale SEC (talitos)");
12321 --- /dev/null
12322 +++ b/crypto/ocf/talitos/talitos_soft.h
12323 @@ -0,0 +1,77 @@
12324 +/*
12325 + * Freescale SEC data structures for integration with ocf-linux
12326 + *
12327 + * Copyright (c) 2006 Freescale Semiconductor, Inc.
12328 + *
12329 + * Redistribution and use in source and binary forms, with or without
12330 + * modification, are permitted provided that the following conditions
12331 + * are met:
12332 + *
12333 + * 1. Redistributions of source code must retain the above copyright
12334 + * notice, this list of conditions and the following disclaimer.
12335 + * 2. Redistributions in binary form must reproduce the above copyright
12336 + * notice, this list of conditions and the following disclaimer in the
12337 + * documentation and/or other materials provided with the distribution.
12338 + * 3. The name of the author may not be used to endorse or promote products
12339 + * derived from this software without specific prior written permission.
12340 + *
12341 + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
12342 + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
12343 + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
12344 + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
12345 + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
12346 + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
12347 + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
12348 + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
12349 + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
12350 + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
12351 + */
12352 +
12353 +/*
12354 + * paired descriptor and associated crypto operation
12355 + */
12356 +struct desc_cryptop_pair {
12357 + struct talitos_desc cf_desc; /* descriptor ptr */
12358 + struct cryptop *cf_crp; /* cryptop ptr */
12359 +};
12360 +
12361 +/*
12362 + * Holds data specific to a single talitos device.
12363 + */
12364 +struct talitos_softc {
12365 + softc_device_decl sc_cdev;
12366 + struct platform_device *sc_dev; /* device backpointer */
12367 + ocf_iomem_t sc_base_addr;
12368 + int sc_irq;
12369 + int sc_num; /* if we have multiple chips */
12370 + int32_t sc_cid; /* crypto tag */
12371 + u64 sc_chiprev; /* major/minor chip revision */
12372 + int sc_nsessions;
12373 + struct talitos_session *sc_sessions;
12374 + int sc_num_channels;/* number of crypto channels */
12375 + int sc_chfifo_len; /* channel fetch fifo len */
12376 + int sc_exec_units; /* execution units mask */
12377 + int sc_desc_types; /* descriptor types mask */
12378 + /*
12379 + * mutual exclusion for intra-channel resources, e.g. fetch fifos
12380 + * the last entry is a meta-channel lock used by the channel scheduler
12381 + */
12382 + spinlock_t *sc_chnfifolock;
12383 + /* sc_chnlastalgo contains last algorithm for that channel */
12384 + int *sc_chnlastalg;
12385 + /* sc_chnfifo holds pending descriptor--crypto operation pairs */
12386 + struct desc_cryptop_pair **sc_chnfifo;
12387 +};
12388 +
12389 +struct talitos_session {
12390 + u_int32_t ses_used;
12391 + u_int32_t ses_klen; /* key length in bits */
12392 + u_int32_t ses_key[8]; /* DES/3DES/AES key */
12393 + u_int32_t ses_hmac[5]; /* hmac inner state */
12394 + u_int32_t ses_hmac_len; /* hmac length */
12395 + u_int32_t ses_iv[4]; /* DES/3DES/AES iv */
12396 + u_int32_t ses_mlen; /* desired hash result len (12=ipsec or 16) */
12397 +};
12398 +
12399 +#define TALITOS_SESSION(sid) ((sid) & 0x0fffffff)
12400 +#define TALITOS_SID(crd, sesn) (((crd) << 28) | ((sesn) & 0x0fffffff))
12401 --- /dev/null
12402 +++ b/crypto/ocf/talitos/talitos_dev.h
12403 @@ -0,0 +1,277 @@
12404 +/*
12405 + * Freescale SEC (talitos) device dependent data structures
12406 + *
12407 + * Copyright (c) 2006 Freescale Semiconductor, Inc.
12408 + *
12409 + * Redistribution and use in source and binary forms, with or without
12410 + * modification, are permitted provided that the following conditions
12411 + * are met:
12412 + *
12413 + * 1. Redistributions of source code must retain the above copyright
12414 + * notice, this list of conditions and the following disclaimer.
12415 + * 2. Redistributions in binary form must reproduce the above copyright
12416 + * notice, this list of conditions and the following disclaimer in the
12417 + * documentation and/or other materials provided with the distribution.
12418 + * 3. The name of the author may not be used to endorse or promote products
12419 + * derived from this software without specific prior written permission.
12420 + *
12421 + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
12422 + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
12423 + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
12424 + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
12425 + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
12426 + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
12427 + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
12428 + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
12429 + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
12430 + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
12431 + *
12432 + */
12433 +
12434 +/* device ID register values */
12435 +#define TALITOS_ID_SEC_2_0 0x40
12436 +#define TALITOS_ID_SEC_2_1 0x40 /* cross ref with IP block revision reg */
12437 +
12438 +/*
12439 + * following num_channels, channel-fifo-depth, exec-unit-mask, and
12440 + * descriptor-types-mask are for forward-compatibility with openfirmware
12441 + * flat device trees
12442 + */
12443 +
12444 +/*
12445 + * num_channels : the number of channels available in each SEC version.
12446 + */
12447 +
12448 +/* n.b. this driver requires these values be a power of 2 */
12449 +#define TALITOS_NCHANNELS_SEC_1_0 4
12450 +#define TALITOS_NCHANNELS_SEC_1_2 1
12451 +#define TALITOS_NCHANNELS_SEC_2_0 4
12452 +#define TALITOS_NCHANNELS_SEC_2_01 4
12453 +#define TALITOS_NCHANNELS_SEC_2_1 4
12454 +#define TALITOS_NCHANNELS_SEC_2_4 4
12455 +
12456 +/*
12457 + * channel-fifo-depth : The number of descriptor
12458 + * pointers a channel fetch fifo can hold.
12459 + */
12460 +#define TALITOS_CHFIFOLEN_SEC_1_0 1
12461 +#define TALITOS_CHFIFOLEN_SEC_1_2 1
12462 +#define TALITOS_CHFIFOLEN_SEC_2_0 24
12463 +#define TALITOS_CHFIFOLEN_SEC_2_01 24
12464 +#define TALITOS_CHFIFOLEN_SEC_2_1 24
12465 +#define TALITOS_CHFIFOLEN_SEC_2_4 24
12466 +
12467 +/*
12468 + * exec-unit-mask : The bitmask representing what Execution Units (EUs)
12469 + * are available. EU information should be encoded following the SEC's
12470 + * EU_SEL0 bitfield documentation, i.e. as follows:
12471 + *
12472 + * bit 31 = set if SEC permits no-EU selection (should be always set)
12473 + * bit 30 = set if SEC has the ARC4 EU (AFEU)
12474 + * bit 29 = set if SEC has the des/3des EU (DEU)
12475 + * bit 28 = set if SEC has the message digest EU (MDEU)
12476 + * bit 27 = set if SEC has the random number generator EU (RNG)
12477 + * bit 26 = set if SEC has the public key EU (PKEU)
12478 + * bit 25 = set if SEC has the aes EU (AESU)
12479 + * bit 24 = set if SEC has the Kasumi EU (KEU)
12480 + *
12481 + */
12482 +#define TALITOS_HAS_EU_NONE (1<<0)
12483 +#define TALITOS_HAS_EU_AFEU (1<<1)
12484 +#define TALITOS_HAS_EU_DEU (1<<2)
12485 +#define TALITOS_HAS_EU_MDEU (1<<3)
12486 +#define TALITOS_HAS_EU_RNG (1<<4)
12487 +#define TALITOS_HAS_EU_PKEU (1<<5)
12488 +#define TALITOS_HAS_EU_AESU (1<<6)
12489 +#define TALITOS_HAS_EU_KEU (1<<7)
12490 +
12491 +/* the corresponding masks for each SEC version */
12492 +#define TALITOS_HAS_EUS_SEC_1_0 0x7f
12493 +#define TALITOS_HAS_EUS_SEC_1_2 0x4d
12494 +#define TALITOS_HAS_EUS_SEC_2_0 0x7f
12495 +#define TALITOS_HAS_EUS_SEC_2_01 0x7f
12496 +#define TALITOS_HAS_EUS_SEC_2_1 0xff
12497 +#define TALITOS_HAS_EUS_SEC_2_4 0x7f
12498 +
12499 +/*
12500 + * descriptor-types-mask : The bitmask representing what descriptors
12501 + * are available. Descriptor type information should be encoded
12502 + * following the SEC's Descriptor Header Dword DESC_TYPE field
12503 + * documentation, i.e. as follows:
12504 + *
12505 + * bit 0 = set if SEC supports the aesu_ctr_nonsnoop desc. type
12506 + * bit 1 = set if SEC supports the ipsec_esp descriptor type
12507 + * bit 2 = set if SEC supports the common_nonsnoop desc. type
12508 + * bit 3 = set if SEC supports the 802.11i AES ccmp desc. type
12509 + * bit 4 = set if SEC supports the hmac_snoop_no_afeu desc. type
12510 + * bit 5 = set if SEC supports the srtp descriptor type
12511 + * bit 6 = set if SEC supports the non_hmac_snoop_no_afeu desc.type
12512 + * bit 7 = set if SEC supports the pkeu_assemble descriptor type
12513 + * bit 8 = set if SEC supports the aesu_key_expand_output desc.type
12514 + * bit 9 = set if SEC supports the pkeu_ptmul descriptor type
12515 + * bit 10 = set if SEC supports the common_nonsnoop_afeu desc. type
12516 + * bit 11 = set if SEC supports the pkeu_ptadd_dbl descriptor type
12517 + *
12518 + * ..and so on and so forth.
12519 + */
12520 +#define TALITOS_HAS_DT_AESU_CTR_NONSNOOP (1<<0)
12521 +#define TALITOS_HAS_DT_IPSEC_ESP (1<<1)
12522 +#define TALITOS_HAS_DT_COMMON_NONSNOOP (1<<2)
12523 +
12524 +/* the corresponding masks for each SEC version */
12525 +#define TALITOS_HAS_DESCTYPES_SEC_2_0 0x01010ebf
12526 +#define TALITOS_HAS_DESCTYPES_SEC_2_1 0x012b0ebf
12527 +
12528 +/*
12529 + * a TALITOS_xxx_HI address points to the low data bits (32-63) of the register
12530 + */
12531 +
12532 +/* global register offset addresses */
12533 +#define TALITOS_ID 0x1020
12534 +#define TALITOS_ID_HI 0x1024
12535 +#define TALITOS_MCR 0x1030 /* master control register */
12536 +#define TALITOS_MCR_HI 0x1038 /* master control register */
12537 +#define TALITOS_MCR_SWR 0x1
12538 +#define TALITOS_IMR 0x1008 /* interrupt mask register */
12539 +#define TALITOS_IMR_ALL 0x00010fff /* enable all interrupts mask */
12540 +#define TALITOS_IMR_ERRONLY 0x00010aaa /* enable error interrupts */
12541 +#define TALITOS_IMR_HI 0x100C /* interrupt mask register */
12542 +#define TALITOS_IMR_HI_ALL 0x00323333 /* enable all interrupts mask */
12543 +#define TALITOS_IMR_HI_ERRONLY 0x00222222 /* enable error interrupts */
12544 +#define TALITOS_ISR 0x1010 /* interrupt status register */
12545 +#define TALITOS_ISR_ERROR 0x00010faa /* errors mask */
12546 +#define TALITOS_ISR_DONE 0x00000055 /* channel(s) done mask */
12547 +#define TALITOS_ISR_HI 0x1014 /* interrupt status register */
12548 +#define TALITOS_ICR 0x1018 /* interrupt clear register */
12549 +#define TALITOS_ICR_HI 0x101C /* interrupt clear register */
12550 +
12551 +/* channel register address stride */
12552 +#define TALITOS_CH_OFFSET 0x100
12553 +
12554 +/* channel register offset addresses and bits */
12555 +#define TALITOS_CH_CCCR 0x1108 /* Crypto-Channel Config Register */
12556 +#define TALITOS_CH_CCCR_RESET 0x1 /* Channel Reset bit */
12557 +#define TALITOS_CH_CCCR_HI 0x110c /* Crypto-Channel Config Register */
12558 +#define TALITOS_CH_CCCR_HI_CDWE 0x10 /* Channel done writeback enable bit */
12559 +#define TALITOS_CH_CCCR_HI_NT 0x4 /* Notification type bit */
12560 +#define TALITOS_CH_CCCR_HI_CDIE 0x2 /* Channel Done Interrupt Enable bit */
12561 +#define TALITOS_CH_CCPSR 0x1110 /* Crypto-Channel Pointer Status Reg */
12562 +#define TALITOS_CH_CCPSR_HI 0x1114 /* Crypto-Channel Pointer Status Reg */
12563 +#define TALITOS_CH_FF 0x1148 /* Fetch FIFO */
12564 +#define TALITOS_CH_FF_HI 0x114c /* Fetch FIFO's FETCH_ADRS */
12565 +#define TALITOS_CH_CDPR 0x1140 /* Crypto-Channel Pointer Status Reg */
12566 +#define TALITOS_CH_CDPR_HI 0x1144 /* Crypto-Channel Pointer Status Reg */
12567 +#define TALITOS_CH_DESCBUF 0x1180 /* (thru 11bf) Crypto-Channel
12568 + * Descriptor Buffer (debug) */
12569 +
12570 +/* execution unit register offset addresses and bits */
12571 +#define TALITOS_DEUSR 0x2028 /* DEU status register */
12572 +#define TALITOS_DEUSR_HI 0x202c /* DEU status register */
12573 +#define TALITOS_DEUISR 0x2030 /* DEU interrupt status register */
12574 +#define TALITOS_DEUISR_HI 0x2034 /* DEU interrupt status register */
12575 +#define TALITOS_DEUICR 0x2038 /* DEU interrupt control register */
12576 +#define TALITOS_DEUICR_HI 0x203c /* DEU interrupt control register */
12577 +#define TALITOS_AESUISR 0x4030 /* AESU interrupt status register */
12578 +#define TALITOS_AESUISR_HI 0x4034 /* AESU interrupt status register */
12579 +#define TALITOS_AESUICR 0x4038 /* AESU interrupt control register */
12580 +#define TALITOS_AESUICR_HI 0x403c /* AESU interrupt control register */
12581 +#define TALITOS_MDEUISR 0x6030 /* MDEU interrupt status register */
12582 +#define TALITOS_MDEUISR_HI 0x6034 /* MDEU interrupt status register */
12583 +#define TALITOS_RNGSR 0xa028 /* RNG status register */
12584 +#define TALITOS_RNGSR_HI 0xa02c /* RNG status register */
12585 +#define TALITOS_RNGSR_HI_RD 0x1 /* RNG Reset done */
12586 +#define TALITOS_RNGSR_HI_OFL 0xff0000/* number of dwords in RNG output FIFO*/
12587 +#define TALITOS_RNGDSR 0xa010 /* RNG data size register */
12588 +#define TALITOS_RNGDSR_HI 0xa014 /* RNG data size register */
12589 +#define TALITOS_RNG_FIFO 0xa800 /* RNG FIFO - pool of random numbers */
12590 +#define TALITOS_RNGISR 0xa030 /* RNG Interrupt status register */
12591 +#define TALITOS_RNGISR_HI 0xa034 /* RNG Interrupt status register */
12592 +#define TALITOS_RNGRCR 0xa018 /* RNG Reset control register */
12593 +#define TALITOS_RNGRCR_HI 0xa01c /* RNG Reset control register */
12594 +#define TALITOS_RNGRCR_HI_SR 0x1 /* RNG RNGRCR:Software Reset */
12595 +
12596 +/* descriptor pointer entry */
12597 +struct talitos_desc_ptr {
12598 + u16 len; /* length */
12599 + u8 extent; /* jump (to s/g link table) and extent */
12600 + u8 res; /* reserved */
12601 + u32 ptr; /* pointer */
12602 +};
12603 +
12604 +/* descriptor */
12605 +struct talitos_desc {
12606 + u32 hdr; /* header */
12607 + u32 res; /* reserved */
12608 + struct talitos_desc_ptr ptr[7]; /* ptr/len pair array */
12609 +};
12610 +
12611 +/* talitos descriptor header (hdr) bits */
12612 +
12613 +/* primary execution unit select */
12614 +#define TALITOS_SEL0_AFEU 0x10000000
12615 +#define TALITOS_SEL0_DEU 0x20000000
12616 +#define TALITOS_SEL0_MDEU 0x30000000
12617 +#define TALITOS_SEL0_RNG 0x40000000
12618 +#define TALITOS_SEL0_PKEU 0x50000000
12619 +#define TALITOS_SEL0_AESU 0x60000000
12620 +
12621 +/* primary execution unit mode (MODE0) and derivatives */
12622 +#define TALITOS_MODE0_AESU_CBC 0x00200000
12623 +#define TALITOS_MODE0_AESU_ENC 0x00100000
12624 +#define TALITOS_MODE0_DEU_CBC 0x00400000
12625 +#define TALITOS_MODE0_DEU_3DES 0x00200000
12626 +#define TALITOS_MODE0_DEU_ENC 0x00100000
12627 +#define TALITOS_MODE0_MDEU_INIT 0x01000000 /* init starting regs */
12628 +#define TALITOS_MODE0_MDEU_HMAC 0x00800000
12629 +#define TALITOS_MODE0_MDEU_PAD 0x00400000 /* PD */
12630 +#define TALITOS_MODE0_MDEU_MD5 0x00200000
12631 +#define TALITOS_MODE0_MDEU_SHA256 0x00100000
12632 +#define TALITOS_MODE0_MDEU_SHA1 0x00000000 /* SHA-160 */
12633 +#define TALITOS_MODE0_MDEU_MD5_HMAC \
12634 + (TALITOS_MODE0_MDEU_MD5 | TALITOS_MODE0_MDEU_HMAC)
12635 +#define TALITOS_MODE0_MDEU_SHA256_HMAC \
12636 + (TALITOS_MODE0_MDEU_SHA256 | TALITOS_MODE0_MDEU_HMAC)
12637 +#define TALITOS_MODE0_MDEU_SHA1_HMAC \
12638 + (TALITOS_MODE0_MDEU_SHA1 | TALITOS_MODE0_MDEU_HMAC)
12639 +
12640 +/* secondary execution unit select (SEL1) */
12641 +/* it's MDEU or nothing */
12642 +#define TALITOS_SEL1_MDEU 0x00030000
12643 +
12644 +/* secondary execution unit mode (MODE1) and derivatives */
12645 +#define TALITOS_MODE1_MDEU_INIT 0x00001000 /* init starting regs */
12646 +#define TALITOS_MODE1_MDEU_HMAC 0x00000800
12647 +#define TALITOS_MODE1_MDEU_PAD 0x00000400 /* PD */
12648 +#define TALITOS_MODE1_MDEU_MD5 0x00000200
12649 +#define TALITOS_MODE1_MDEU_SHA256 0x00000100
12650 +#define TALITOS_MODE1_MDEU_SHA1 0x00000000 /* SHA-160 */
12651 +#define TALITOS_MODE1_MDEU_MD5_HMAC \
12652 + (TALITOS_MODE1_MDEU_MD5 | TALITOS_MODE1_MDEU_HMAC)
12653 +#define TALITOS_MODE1_MDEU_SHA256_HMAC \
12654 + (TALITOS_MODE1_MDEU_SHA256 | TALITOS_MODE1_MDEU_HMAC)
12655 +#define TALITOS_MODE1_MDEU_SHA1_HMAC \
12656 + (TALITOS_MODE1_MDEU_SHA1 | TALITOS_MODE1_MDEU_HMAC)
12657 +
12658 +/* direction of overall data flow (DIR) */
12659 +#define TALITOS_DIR_OUTBOUND 0x00000000
12660 +#define TALITOS_DIR_INBOUND 0x00000002
12661 +
12662 +/* done notification (DN) */
12663 +#define TALITOS_DONE_NOTIFY 0x00000001
12664 +
12665 +/* descriptor types */
12666 +/* odd numbers here are valid on SEC2 and greater only (e.g. ipsec_esp) */
12667 +#define TD_TYPE_AESU_CTR_NONSNOOP (0 << 3)
12668 +#define TD_TYPE_IPSEC_ESP (1 << 3)
12669 +#define TD_TYPE_COMMON_NONSNOOP_NO_AFEU (2 << 3)
12670 +#define TD_TYPE_HMAC_SNOOP_NO_AFEU (4 << 3)
12671 +
12672 +#define TALITOS_HDR_DONE_BITS 0xff000000
12673 +
12674 +#define DPRINTF(a...) do { \
12675 + if (debug) { \
12676 + printk("%s: ", sc ? \
12677 + device_get_nameunit(sc->sc_cdev) : "talitos"); \
12678 + printk(a); \
12679 + } \
12680 + } while (0)
12681 --- /dev/null
12682 +++ b/crypto/ocf/random.c
12683 @@ -0,0 +1,317 @@
12684 +/*
12685 + * A system independant way of adding entropy to the kernels pool
12686 + * this way the drivers can focus on the real work and we can take
12687 + * care of pushing it to the appropriate place in the kernel.
12688 + *
12689 + * This should be fast and callable from timers/interrupts
12690 + *
12691 + * Written by David McCullough <david_mccullough@securecomputing.com>
12692 + * Copyright (C) 2006-2007 David McCullough
12693 + * Copyright (C) 2004-2005 Intel Corporation.
12694 + *
12695 + * LICENSE TERMS
12696 + *
12697 + * The free distribution and use of this software in both source and binary
12698 + * form is allowed (with or without changes) provided that:
12699 + *
12700 + * 1. distributions of this source code include the above copyright
12701 + * notice, this list of conditions and the following disclaimer;
12702 + *
12703 + * 2. distributions in binary form include the above copyright
12704 + * notice, this list of conditions and the following disclaimer
12705 + * in the documentation and/or other associated materials;
12706 + *
12707 + * 3. the copyright holder's name is not used to endorse products
12708 + * built using this software without specific written permission.
12709 + *
12710 + * ALTERNATIVELY, provided that this notice is retained in full, this product
12711 + * may be distributed under the terms of the GNU General Public License (GPL),
12712 + * in which case the provisions of the GPL apply INSTEAD OF those given above.
12713 + *
12714 + * DISCLAIMER
12715 + *
12716 + * This software is provided 'as is' with no explicit or implied warranties
12717 + * in respect of its properties, including, but not limited to, correctness
12718 + * and/or fitness for purpose.
12719 + */
12720 +
12721 +#ifndef AUTOCONF_INCLUDED
12722 +#include <linux/config.h>
12723 +#endif
12724 +#include <linux/module.h>
12725 +#include <linux/init.h>
12726 +#include <linux/list.h>
12727 +#include <linux/slab.h>
12728 +#include <linux/wait.h>
12729 +#include <linux/sched.h>
12730 +#include <linux/spinlock.h>
12731 +#include <linux/version.h>
12732 +#include <linux/unistd.h>
12733 +#include <linux/poll.h>
12734 +#include <linux/random.h>
12735 +#include <cryptodev.h>
12736 +
12737 +#ifdef CONFIG_OCF_FIPS
12738 +#include "rndtest.h"
12739 +#endif
12740 +
12741 +#ifndef HAS_RANDOM_INPUT_WAIT
12742 +#error "Please do not enable OCF_RANDOMHARVEST unless you have applied patches"
12743 +#endif
12744 +
12745 +/*
12746 + * a hack to access the debug levels from the crypto driver
12747 + */
12748 +extern int crypto_debug;
12749 +#define debug crypto_debug
12750 +
12751 +/*
12752 + * a list of all registered random providers
12753 + */
12754 +static LIST_HEAD(random_ops);
12755 +static int started = 0;
12756 +static int initted = 0;
12757 +
12758 +struct random_op {
12759 + struct list_head random_list;
12760 + u_int32_t driverid;
12761 + int (*read_random)(void *arg, u_int32_t *buf, int len);
12762 + void *arg;
12763 +};
12764 +
12765 +static int random_proc(void *arg);
12766 +
12767 +static pid_t randomproc = (pid_t) -1;
12768 +static spinlock_t random_lock;
12769 +
12770 +/*
12771 + * just init the spin locks
12772 + */
12773 +static int
12774 +crypto_random_init(void)
12775 +{
12776 + spin_lock_init(&random_lock);
12777 + initted = 1;
12778 + return(0);
12779 +}
12780 +
12781 +/*
12782 + * Add the given random reader to our list (if not present)
12783 + * and start the thread (if not already started)
12784 + *
12785 + * we have to assume that driver id is ok for now
12786 + */
12787 +int
12788 +crypto_rregister(
12789 + u_int32_t driverid,
12790 + int (*read_random)(void *arg, u_int32_t *buf, int len),
12791 + void *arg)
12792 +{
12793 + unsigned long flags;
12794 + int ret = 0;
12795 + struct random_op *rops, *tmp;
12796 +
12797 + dprintk("%s,%d: %s(0x%x, %p, %p)\n", __FILE__, __LINE__,
12798 + __FUNCTION__, driverid, read_random, arg);
12799 +
12800 + if (!initted)
12801 + crypto_random_init();
12802 +
12803 +#if 0
12804 + struct cryptocap *cap;
12805 +
12806 + cap = crypto_checkdriver(driverid);
12807 + if (!cap)
12808 + return EINVAL;
12809 +#endif
12810 +
12811 + list_for_each_entry_safe(rops, tmp, &random_ops, random_list) {
12812 + if (rops->driverid == driverid && rops->read_random == read_random)
12813 + return EEXIST;
12814 + }
12815 +
12816 + rops = (struct random_op *) kmalloc(sizeof(*rops), GFP_KERNEL);
12817 + if (!rops)
12818 + return ENOMEM;
12819 +
12820 + rops->driverid = driverid;
12821 + rops->read_random = read_random;
12822 + rops->arg = arg;
12823 +
12824 + spin_lock_irqsave(&random_lock, flags);
12825 + list_add_tail(&rops->random_list, &random_ops);
12826 + if (!started) {
12827 + randomproc = kernel_thread(random_proc, NULL, CLONE_FS|CLONE_FILES);
12828 + if (randomproc < 0) {
12829 + ret = randomproc;
12830 + printk("crypto: crypto_rregister cannot start random thread; "
12831 + "error %d", ret);
12832 + } else
12833 + started = 1;
12834 + }
12835 + spin_unlock_irqrestore(&random_lock, flags);
12836 +
12837 + return ret;
12838 +}
12839 +EXPORT_SYMBOL(crypto_rregister);
12840 +
12841 +int
12842 +crypto_runregister_all(u_int32_t driverid)
12843 +{
12844 + struct random_op *rops, *tmp;
12845 + unsigned long flags;
12846 +
12847 + dprintk("%s,%d: %s(0x%x)\n", __FILE__, __LINE__, __FUNCTION__, driverid);
12848 +
12849 + list_for_each_entry_safe(rops, tmp, &random_ops, random_list) {
12850 + if (rops->driverid == driverid) {
12851 + list_del(&rops->random_list);
12852 + kfree(rops);
12853 + }
12854 + }
12855 +
12856 + spin_lock_irqsave(&random_lock, flags);
12857 + if (list_empty(&random_ops) && started)
12858 + kill_proc(randomproc, SIGKILL, 1);
12859 + spin_unlock_irqrestore(&random_lock, flags);
12860 + return(0);
12861 +}
12862 +EXPORT_SYMBOL(crypto_runregister_all);
12863 +
12864 +/*
12865 + * while we can add entropy to random.c continue to read random data from
12866 + * the drivers and push it to random.
12867 + */
12868 +static int
12869 +random_proc(void *arg)
12870 +{
12871 + int n;
12872 + int wantcnt;
12873 + int bufcnt = 0;
12874 + int retval = 0;
12875 + int *buf = NULL;
12876 +
12877 +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,0)
12878 + daemonize();
12879 + spin_lock_irq(&current->sigmask_lock);
12880 + sigemptyset(&current->blocked);
12881 + recalc_sigpending(current);
12882 + spin_unlock_irq(&current->sigmask_lock);
12883 + sprintf(current->comm, "ocf-random");
12884 +#else
12885 + daemonize("ocf-random");
12886 + allow_signal(SIGKILL);
12887 +#endif
12888 +
12889 + (void) get_fs();
12890 + set_fs(get_ds());
12891 +
12892 +#ifdef CONFIG_OCF_FIPS
12893 +#define NUM_INT (RNDTEST_NBYTES/sizeof(int))
12894 +#else
12895 +#define NUM_INT 32
12896 +#endif
12897 +
12898 + /*
12899 + * some devices can transferr their RNG data direct into memory,
12900 + * so make sure it is device friendly
12901 + */
12902 + buf = kmalloc(NUM_INT * sizeof(int), GFP_DMA);
12903 + if (NULL == buf) {
12904 + printk("crypto: RNG could not allocate memory\n");
12905 + retval = -ENOMEM;
12906 + goto bad_alloc;
12907 + }
12908 +
12909 + wantcnt = NUM_INT; /* start by adding some entropy */
12910 +
12911 + /*
12912 + * its possible due to errors or driver removal that we no longer
12913 + * have anything to do, if so exit or we will consume all the CPU
12914 + * doing nothing
12915 + */
12916 + while (!list_empty(&random_ops)) {
12917 + struct random_op *rops, *tmp;
12918 +
12919 +#ifdef CONFIG_OCF_FIPS
12920 + if (wantcnt)
12921 + wantcnt = NUM_INT; /* FIPs mode can do 20000 bits or none */
12922 +#endif
12923 +
12924 + /* see if we can get enough entropy to make the world
12925 + * a better place.
12926 + */
12927 + while (bufcnt < wantcnt && bufcnt < NUM_INT) {
12928 + list_for_each_entry_safe(rops, tmp, &random_ops, random_list) {
12929 +
12930 + n = (*rops->read_random)(rops->arg, &buf[bufcnt],
12931 + NUM_INT - bufcnt);
12932 +
12933 + /* on failure remove the random number generator */
12934 + if (n == -1) {
12935 + list_del(&rops->random_list);
12936 + printk("crypto: RNG (driverid=0x%x) failed, disabling\n",
12937 + rops->driverid);
12938 + kfree(rops);
12939 + } else if (n > 0)
12940 + bufcnt += n;
12941 + }
12942 + /* give up CPU for a bit, just in case as this is a loop */
12943 + schedule();
12944 + }
12945 +
12946 +
12947 +#ifdef CONFIG_OCF_FIPS
12948 + if (bufcnt > 0 && rndtest_buf((unsigned char *) &buf[0])) {
12949 + dprintk("crypto: buffer had fips errors, discarding\n");
12950 + bufcnt = 0;
12951 + }
12952 +#endif
12953 +
12954 + /*
12955 + * if we have a certified buffer, we can send some data
12956 + * to /dev/random and move along
12957 + */
12958 + if (bufcnt > 0) {
12959 + /* add what we have */
12960 + random_input_words(buf, bufcnt, bufcnt*sizeof(int)*8);
12961 + bufcnt = 0;
12962 + }
12963 +
12964 + /* give up CPU for a bit so we don't hog while filling */
12965 + schedule();
12966 +
12967 + /* wait for needing more */
12968 + wantcnt = random_input_wait();
12969 +
12970 + if (wantcnt <= 0)
12971 + wantcnt = 0; /* try to get some info again */
12972 + else
12973 + /* round up to one word or we can loop forever */
12974 + wantcnt = (wantcnt + (sizeof(int)*8)) / (sizeof(int)*8);
12975 + if (wantcnt > NUM_INT) {
12976 + wantcnt = NUM_INT;
12977 + }
12978 +
12979 + if (signal_pending(current)) {
12980 +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,0)
12981 + spin_lock_irq(&current->sigmask_lock);
12982 +#endif
12983 + flush_signals(current);
12984 +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,0)
12985 + spin_unlock_irq(&current->sigmask_lock);
12986 +#endif
12987 + }
12988 + }
12989 +
12990 + kfree(buf);
12991 +
12992 +bad_alloc:
12993 + spin_lock_irq(&random_lock);
12994 + randomproc = (pid_t) -1;
12995 + started = 0;
12996 + spin_unlock_irq(&random_lock);
12997 +
12998 + return retval;
12999 +}
13000 +
13001 --- /dev/null
13002 +++ b/crypto/ocf/ocf-bench.c
13003 @@ -0,0 +1,436 @@
13004 +/*
13005 + * A loadable module that benchmarks the OCF crypto speed from kernel space.
13006 + *
13007 + * Copyright (C) 2004-2007 David McCullough <david_mccullough@securecomputing.com>
13008 + *
13009 + * LICENSE TERMS
13010 + *
13011 + * The free distribution and use of this software in both source and binary
13012 + * form is allowed (with or without changes) provided that:
13013 + *
13014 + * 1. distributions of this source code include the above copyright
13015 + * notice, this list of conditions and the following disclaimer;
13016 + *
13017 + * 2. distributions in binary form include the above copyright
13018 + * notice, this list of conditions and the following disclaimer
13019 + * in the documentation and/or other associated materials;
13020 + *
13021 + * 3. the copyright holder's name is not used to endorse products
13022 + * built using this software without specific written permission.
13023 + *
13024 + * ALTERNATIVELY, provided that this notice is retained in full, this product
13025 + * may be distributed under the terms of the GNU General Public License (GPL),
13026 + * in which case the provisions of the GPL apply INSTEAD OF those given above.
13027 + *
13028 + * DISCLAIMER
13029 + *
13030 + * This software is provided 'as is' with no explicit or implied warranties
13031 + * in respect of its properties, including, but not limited to, correctness
13032 + * and/or fitness for purpose.
13033 + */
13034 +
13035 +
13036 +#ifndef AUTOCONF_INCLUDED
13037 +#include <linux/config.h>
13038 +#endif
13039 +#include <linux/module.h>
13040 +#include <linux/init.h>
13041 +#include <linux/list.h>
13042 +#include <linux/slab.h>
13043 +#include <linux/wait.h>
13044 +#include <linux/sched.h>
13045 +#include <linux/spinlock.h>
13046 +#include <linux/version.h>
13047 +#include <linux/interrupt.h>
13048 +#include <cryptodev.h>
13049 +
13050 +#ifdef I_HAVE_AN_XSCALE_WITH_INTEL_SDK
13051 +#define BENCH_IXP_ACCESS_LIB 1
13052 +#endif
13053 +#ifdef BENCH_IXP_ACCESS_LIB
13054 +#include <IxTypes.h>
13055 +#include <IxOsBuffMgt.h>
13056 +#include <IxNpeDl.h>
13057 +#include <IxCryptoAcc.h>
13058 +#include <IxQMgr.h>
13059 +#include <IxOsServices.h>
13060 +#include <IxOsCacheMMU.h>
13061 +#endif
13062 +
13063 +/*
13064 + * support for access lib version 1.4
13065 + */
13066 +#ifndef IX_MBUF_PRIV
13067 +#define IX_MBUF_PRIV(x) ((x)->priv)
13068 +#endif
13069 +
13070 +/*
13071 + * the number of simultaneously active requests
13072 + */
13073 +static int request_q_len = 20;
13074 +module_param(request_q_len, int, 0);
13075 +MODULE_PARM_DESC(request_q_len, "Number of outstanding requests");
13076 +/*
13077 + * how many requests we want to have processed
13078 + */
13079 +static int request_num = 1024;
13080 +module_param(request_num, int, 0);
13081 +MODULE_PARM_DESC(request_num, "run for at least this many requests");
13082 +/*
13083 + * the size of each request
13084 + */
13085 +static int request_size = 1500;
13086 +module_param(request_size, int, 0);
13087 +MODULE_PARM_DESC(request_size, "size of each request");
13088 +
13089 +/*
13090 + * a structure for each request
13091 + */
13092 +typedef struct {
13093 + struct work_struct work;
13094 +#ifdef BENCH_IXP_ACCESS_LIB
13095 + IX_MBUF mbuf;
13096 +#endif
13097 + unsigned char *buffer;
13098 +} request_t;
13099 +
13100 +static request_t *requests;
13101 +
13102 +static int outstanding;
13103 +static int total;
13104 +
13105 +/*************************************************************************/
13106 +/*
13107 + * OCF benchmark routines
13108 + */
13109 +
13110 +static uint64_t ocf_cryptoid;
13111 +static int ocf_init(void);
13112 +static int ocf_cb(struct cryptop *crp);
13113 +static void ocf_request(void *arg);
13114 +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,20)
13115 +static void ocf_request_wq(struct work_struct *work);
13116 +#endif
13117 +
13118 +static int
13119 +ocf_init(void)
13120 +{
13121 + int error;
13122 + struct cryptoini crie, cria;
13123 + struct cryptodesc crda, crde;
13124 +
13125 + memset(&crie, 0, sizeof(crie));
13126 + memset(&cria, 0, sizeof(cria));
13127 + memset(&crde, 0, sizeof(crde));
13128 + memset(&crda, 0, sizeof(crda));
13129 +
13130 + cria.cri_alg = CRYPTO_SHA1_HMAC;
13131 + cria.cri_klen = 20 * 8;
13132 + cria.cri_key = "0123456789abcdefghij";
13133 +
13134 + crie.cri_alg = CRYPTO_3DES_CBC;
13135 + crie.cri_klen = 24 * 8;
13136 + crie.cri_key = "0123456789abcdefghijklmn";
13137 +
13138 + crie.cri_next = &cria;
13139 +
13140 + error = crypto_newsession(&ocf_cryptoid, &crie, 0);
13141 + if (error) {
13142 + printk("crypto_newsession failed %d\n", error);
13143 + return -1;
13144 + }
13145 + return 0;
13146 +}
13147 +
13148 +static int
13149 +ocf_cb(struct cryptop *crp)
13150 +{
13151 + request_t *r = (request_t *) crp->crp_opaque;
13152 +
13153 + if (crp->crp_etype)
13154 + printk("Error in OCF processing: %d\n", crp->crp_etype);
13155 + total++;
13156 + crypto_freereq(crp);
13157 + crp = NULL;
13158 +
13159 + if (total > request_num) {
13160 + outstanding--;
13161 + return 0;
13162 + }
13163 +
13164 +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,20)
13165 + INIT_WORK(&r->work, ocf_request_wq);
13166 +#else
13167 + INIT_WORK(&r->work, ocf_request, r);
13168 +#endif
13169 + schedule_work(&r->work);
13170 + return 0;
13171 +}
13172 +
13173 +
13174 +static void
13175 +ocf_request(void *arg)
13176 +{
13177 + request_t *r = arg;
13178 + struct cryptop *crp = crypto_getreq(2);
13179 + struct cryptodesc *crde, *crda;
13180 +
13181 + if (!crp) {
13182 + outstanding--;
13183 + return;
13184 + }
13185 +
13186 + crde = crp->crp_desc;
13187 + crda = crde->crd_next;
13188 +
13189 + crda->crd_skip = 0;
13190 + crda->crd_flags = 0;
13191 + crda->crd_len = request_size;
13192 + crda->crd_inject = request_size;
13193 + crda->crd_alg = CRYPTO_SHA1_HMAC;
13194 + crda->crd_key = "0123456789abcdefghij";
13195 + crda->crd_klen = 20 * 8;
13196 +
13197 + crde->crd_skip = 0;
13198 + crde->crd_flags = CRD_F_IV_EXPLICIT | CRD_F_ENCRYPT;
13199 + crde->crd_len = request_size;
13200 + crde->crd_inject = request_size;
13201 + crde->crd_alg = CRYPTO_3DES_CBC;
13202 + crde->crd_key = "0123456789abcdefghijklmn";
13203 + crde->crd_klen = 24 * 8;
13204 +
13205 + crp->crp_ilen = request_size + 64;
13206 + crp->crp_flags = CRYPTO_F_CBIMM;
13207 + crp->crp_buf = (caddr_t) r->buffer;
13208 + crp->crp_callback = ocf_cb;
13209 + crp->crp_sid = ocf_cryptoid;
13210 + crp->crp_opaque = (caddr_t) r;
13211 + crypto_dispatch(crp);
13212 +}
13213 +
13214 +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,20)
13215 +static void
13216 +ocf_request_wq(struct work_struct *work)
13217 +{
13218 + request_t *r = container_of(work, request_t, work);
13219 + ocf_request(r);
13220 +}
13221 +#endif
13222 +
13223 +/*************************************************************************/
13224 +#ifdef BENCH_IXP_ACCESS_LIB
13225 +/*************************************************************************/
13226 +/*
13227 + * CryptoAcc benchmark routines
13228 + */
13229 +
13230 +static IxCryptoAccCtx ixp_ctx;
13231 +static UINT32 ixp_ctx_id;
13232 +static IX_MBUF ixp_pri;
13233 +static IX_MBUF ixp_sec;
13234 +static int ixp_registered = 0;
13235 +
13236 +static void ixp_register_cb(UINT32 ctx_id, IX_MBUF *bufp,
13237 + IxCryptoAccStatus status);
13238 +static void ixp_perform_cb(UINT32 ctx_id, IX_MBUF *sbufp, IX_MBUF *dbufp,
13239 + IxCryptoAccStatus status);
13240 +static void ixp_request(void *arg);
13241 +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,20)
13242 +static void ixp_request_wq(struct work_struct *work);
13243 +#endif
13244 +
13245 +static int
13246 +ixp_init(void)
13247 +{
13248 + IxCryptoAccStatus status;
13249 +
13250 + ixp_ctx.cipherCtx.cipherAlgo = IX_CRYPTO_ACC_CIPHER_3DES;
13251 + ixp_ctx.cipherCtx.cipherMode = IX_CRYPTO_ACC_MODE_CBC;
13252 + ixp_ctx.cipherCtx.cipherKeyLen = 24;
13253 + ixp_ctx.cipherCtx.cipherBlockLen = IX_CRYPTO_ACC_DES_BLOCK_64;
13254 + ixp_ctx.cipherCtx.cipherInitialVectorLen = IX_CRYPTO_ACC_DES_IV_64;
13255 + memcpy(ixp_ctx.cipherCtx.key.cipherKey, "0123456789abcdefghijklmn", 24);
13256 +
13257 + ixp_ctx.authCtx.authAlgo = IX_CRYPTO_ACC_AUTH_SHA1;
13258 + ixp_ctx.authCtx.authDigestLen = 12;
13259 + ixp_ctx.authCtx.aadLen = 0;
13260 + ixp_ctx.authCtx.authKeyLen = 20;
13261 + memcpy(ixp_ctx.authCtx.key.authKey, "0123456789abcdefghij", 20);
13262 +
13263 + ixp_ctx.useDifferentSrcAndDestMbufs = 0;
13264 + ixp_ctx.operation = IX_CRYPTO_ACC_OP_ENCRYPT_AUTH ;
13265 +
13266 + IX_MBUF_MLEN(&ixp_pri) = IX_MBUF_PKT_LEN(&ixp_pri) = 128;
13267 + IX_MBUF_MDATA(&ixp_pri) = (unsigned char *) kmalloc(128, SLAB_ATOMIC);
13268 + IX_MBUF_MLEN(&ixp_sec) = IX_MBUF_PKT_LEN(&ixp_sec) = 128;
13269 + IX_MBUF_MDATA(&ixp_sec) = (unsigned char *) kmalloc(128, SLAB_ATOMIC);
13270 +
13271 + status = ixCryptoAccCtxRegister(&ixp_ctx, &ixp_pri, &ixp_sec,
13272 + ixp_register_cb, ixp_perform_cb, &ixp_ctx_id);
13273 +
13274 + if (IX_CRYPTO_ACC_STATUS_SUCCESS == status) {
13275 + while (!ixp_registered)
13276 + schedule();
13277 + return ixp_registered < 0 ? -1 : 0;
13278 + }
13279 +
13280 + printk("ixp: ixCryptoAccCtxRegister failed %d\n", status);
13281 + return -1;
13282 +}
13283 +
13284 +static void
13285 +ixp_register_cb(UINT32 ctx_id, IX_MBUF *bufp, IxCryptoAccStatus status)
13286 +{
13287 + if (bufp) {
13288 + IX_MBUF_MLEN(bufp) = IX_MBUF_PKT_LEN(bufp) = 0;
13289 + kfree(IX_MBUF_MDATA(bufp));
13290 + IX_MBUF_MDATA(bufp) = NULL;
13291 + }
13292 +
13293 + if (IX_CRYPTO_ACC_STATUS_WAIT == status)
13294 + return;
13295 + if (IX_CRYPTO_ACC_STATUS_SUCCESS == status)
13296 + ixp_registered = 1;
13297 + else
13298 + ixp_registered = -1;
13299 +}
13300 +
13301 +static void
13302 +ixp_perform_cb(
13303 + UINT32 ctx_id,
13304 + IX_MBUF *sbufp,
13305 + IX_MBUF *dbufp,
13306 + IxCryptoAccStatus status)
13307 +{
13308 + request_t *r = NULL;
13309 +
13310 + total++;
13311 + if (total > request_num) {
13312 + outstanding--;
13313 + return;
13314 + }
13315 +
13316 + if (!sbufp || !(r = IX_MBUF_PRIV(sbufp))) {
13317 + printk("crappo %p %p\n", sbufp, r);
13318 + outstanding--;
13319 + return;
13320 + }
13321 +
13322 +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,20)
13323 + INIT_WORK(&r->work, ixp_request_wq);
13324 +#else
13325 + INIT_WORK(&r->work, ixp_request, r);
13326 +#endif
13327 + schedule_work(&r->work);
13328 +}
13329 +
13330 +static void
13331 +ixp_request(void *arg)
13332 +{
13333 + request_t *r = arg;
13334 + IxCryptoAccStatus status;
13335 +
13336 + memset(&r->mbuf, 0, sizeof(r->mbuf));
13337 + IX_MBUF_MLEN(&r->mbuf) = IX_MBUF_PKT_LEN(&r->mbuf) = request_size + 64;
13338 + IX_MBUF_MDATA(&r->mbuf) = r->buffer;
13339 + IX_MBUF_PRIV(&r->mbuf) = r;
13340 + status = ixCryptoAccAuthCryptPerform(ixp_ctx_id, &r->mbuf, NULL,
13341 + 0, request_size, 0, request_size, request_size, r->buffer);
13342 + if (IX_CRYPTO_ACC_STATUS_SUCCESS != status) {
13343 + printk("status1 = %d\n", status);
13344 + outstanding--;
13345 + return;
13346 + }
13347 + return;
13348 +}
13349 +
13350 +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,20)
13351 +static void
13352 +ixp_request_wq(struct work_struct *work)
13353 +{
13354 + request_t *r = container_of(work, request_t, work);
13355 + ixp_request(r);
13356 +}
13357 +#endif
13358 +
13359 +/*************************************************************************/
13360 +#endif /* BENCH_IXP_ACCESS_LIB */
13361 +/*************************************************************************/
13362 +
13363 +int
13364 +ocfbench_init(void)
13365 +{
13366 + int i, jstart, jstop;
13367 +
13368 + printk("Crypto Speed tests\n");
13369 +
13370 + requests = kmalloc(sizeof(request_t) * request_q_len, GFP_KERNEL);
13371 + if (!requests) {
13372 + printk("malloc failed\n");
13373 + return -EINVAL;
13374 + }
13375 +
13376 + for (i = 0; i < request_q_len; i++) {
13377 + /* +64 for return data */
13378 + requests[i].buffer = kmalloc(request_size + 128, GFP_DMA);
13379 + if (!requests[i].buffer) {
13380 + printk("malloc failed\n");
13381 + return -EINVAL;
13382 + }
13383 + memset(requests[i].buffer, '0' + i, request_size + 128);
13384 + }
13385 +
13386 + /*
13387 + * OCF benchmark
13388 + */
13389 + printk("OCF: testing ...\n");
13390 + ocf_init();
13391 + total = outstanding = 0;
13392 + jstart = jiffies;
13393 + for (i = 0; i < request_q_len; i++) {
13394 + outstanding++;
13395 + ocf_request(&requests[i]);
13396 + }
13397 + while (outstanding > 0)
13398 + schedule();
13399 + jstop = jiffies;
13400 +
13401 + printk("OCF: %d requests of %d bytes in %d jiffies\n", total, request_size,
13402 + jstop - jstart);
13403 +
13404 +#ifdef BENCH_IXP_ACCESS_LIB
13405 + /*
13406 + * IXP benchmark
13407 + */
13408 + printk("IXP: testing ...\n");
13409 + ixp_init();
13410 + total = outstanding = 0;
13411 + jstart = jiffies;
13412 + for (i = 0; i < request_q_len; i++) {
13413 + outstanding++;
13414 + ixp_request(&requests[i]);
13415 + }
13416 + while (outstanding > 0)
13417 + schedule();
13418 + jstop = jiffies;
13419 +
13420 + printk("IXP: %d requests of %d bytes in %d jiffies\n", total, request_size,
13421 + jstop - jstart);
13422 +#endif /* BENCH_IXP_ACCESS_LIB */
13423 +
13424 + for (i = 0; i < request_q_len; i++)
13425 + kfree(requests[i].buffer);
13426 + kfree(requests);
13427 + return -EINVAL; /* always fail to load so it can be re-run quickly ;-) */
13428 +}
13429 +
13430 +static void __exit ocfbench_exit(void)
13431 +{
13432 +}
13433 +
13434 +module_init(ocfbench_init);
13435 +module_exit(ocfbench_exit);
13436 +
13437 +MODULE_LICENSE("BSD");
13438 +MODULE_AUTHOR("David McCullough <david_mccullough@securecomputing.com>");
13439 +MODULE_DESCRIPTION("Benchmark various in-kernel crypto speeds");
13440 --- /dev/null
13441 +++ b/crypto/ocf/ixp4xx/ixp4xx.c
13442 @@ -0,0 +1,1328 @@
13443 +/*
13444 + * An OCF module that uses Intels IXP CryptACC API to do the crypto.
13445 + * This driver requires the IXP400 Access Library that is available
13446 + * from Intel in order to operate (or compile).
13447 + *
13448 + * Written by David McCullough <david_mccullough@securecomputing.com>
13449 + * Copyright (C) 2006-2007 David McCullough
13450 + * Copyright (C) 2004-2005 Intel Corporation.
13451 + *
13452 + * LICENSE TERMS
13453 + *
13454 + * The free distribution and use of this software in both source and binary
13455 + * form is allowed (with or without changes) provided that:
13456 + *
13457 + * 1. distributions of this source code include the above copyright
13458 + * notice, this list of conditions and the following disclaimer;
13459 + *
13460 + * 2. distributions in binary form include the above copyright
13461 + * notice, this list of conditions and the following disclaimer
13462 + * in the documentation and/or other associated materials;
13463 + *
13464 + * 3. the copyright holder's name is not used to endorse products
13465 + * built using this software without specific written permission.
13466 + *
13467 + * ALTERNATIVELY, provided that this notice is retained in full, this product
13468 + * may be distributed under the terms of the GNU General Public License (GPL),
13469 + * in which case the provisions of the GPL apply INSTEAD OF those given above.
13470 + *
13471 + * DISCLAIMER
13472 + *
13473 + * This software is provided 'as is' with no explicit or implied warranties
13474 + * in respect of its properties, including, but not limited to, correctness
13475 + * and/or fitness for purpose.
13476 + */
13477 +
13478 +#ifndef AUTOCONF_INCLUDED
13479 +#include <linux/config.h>
13480 +#endif
13481 +#include <linux/module.h>
13482 +#include <linux/init.h>
13483 +#include <linux/list.h>
13484 +#include <linux/slab.h>
13485 +#include <linux/sched.h>
13486 +#include <linux/wait.h>
13487 +#include <linux/crypto.h>
13488 +#include <linux/interrupt.h>
13489 +#include <asm/scatterlist.h>
13490 +
13491 +#include <IxTypes.h>
13492 +#include <IxOsBuffMgt.h>
13493 +#include <IxNpeDl.h>
13494 +#include <IxCryptoAcc.h>
13495 +#include <IxQMgr.h>
13496 +#include <IxOsServices.h>
13497 +#include <IxOsCacheMMU.h>
13498 +
13499 +#include <cryptodev.h>
13500 +#include <uio.h>
13501 +
13502 +#ifndef IX_MBUF_PRIV
13503 +#define IX_MBUF_PRIV(x) ((x)->priv)
13504 +#endif
13505 +
13506 +struct ixp_data;
13507 +
13508 +struct ixp_q {
13509 + struct list_head ixp_q_list;
13510 + struct ixp_data *ixp_q_data;
13511 + struct cryptop *ixp_q_crp;
13512 + struct cryptodesc *ixp_q_ccrd;
13513 + struct cryptodesc *ixp_q_acrd;
13514 + IX_MBUF ixp_q_mbuf;
13515 + UINT8 *ixp_hash_dest; /* Location for hash in client buffer */
13516 + UINT8 *ixp_hash_src; /* Location of hash in internal buffer */
13517 + unsigned char ixp_q_iv_data[IX_CRYPTO_ACC_MAX_CIPHER_IV_LENGTH];
13518 + unsigned char *ixp_q_iv;
13519 +};
13520 +
13521 +struct ixp_data {
13522 + int ixp_registered; /* is the context registered */
13523 + int ixp_crd_flags; /* detect direction changes */
13524 +
13525 + int ixp_cipher_alg;
13526 + int ixp_auth_alg;
13527 +
13528 + UINT32 ixp_ctx_id;
13529 + UINT32 ixp_hash_key_id; /* used when hashing */
13530 + IxCryptoAccCtx ixp_ctx;
13531 + IX_MBUF ixp_pri_mbuf;
13532 + IX_MBUF ixp_sec_mbuf;
13533 +
13534 + struct work_struct ixp_pending_work;
13535 + struct work_struct ixp_registration_work;
13536 + struct list_head ixp_q; /* unprocessed requests */
13537 +};
13538 +
13539 +#ifdef __ixp46X
13540 +
13541 +#define MAX_IOP_SIZE 64 /* words */
13542 +#define MAX_OOP_SIZE 128
13543 +
13544 +#define MAX_PARAMS 3
13545 +
13546 +struct ixp_pkq {
13547 + struct list_head pkq_list;
13548 + struct cryptkop *pkq_krp;
13549 +
13550 + IxCryptoAccPkeEauInOperands pkq_op;
13551 + IxCryptoAccPkeEauOpResult pkq_result;
13552 +
13553 + UINT32 pkq_ibuf0[MAX_IOP_SIZE];
13554 + UINT32 pkq_ibuf1[MAX_IOP_SIZE];
13555 + UINT32 pkq_ibuf2[MAX_IOP_SIZE];
13556 + UINT32 pkq_obuf[MAX_OOP_SIZE];
13557 +};
13558 +
13559 +static LIST_HEAD(ixp_pkq); /* current PK wait list */
13560 +static struct ixp_pkq *ixp_pk_cur;
13561 +static spinlock_t ixp_pkq_lock;
13562 +
13563 +#endif /* __ixp46X */
13564 +
13565 +static int ixp_blocked = 0;
13566 +
13567 +static int32_t ixp_id = -1;
13568 +static struct ixp_data **ixp_sessions = NULL;
13569 +static u_int32_t ixp_sesnum = 0;
13570 +
13571 +static int ixp_process(device_t, struct cryptop *, int);
13572 +static int ixp_newsession(device_t, u_int32_t *, struct cryptoini *);
13573 +static int ixp_freesession(device_t, u_int64_t);
13574 +#ifdef __ixp46X
13575 +static int ixp_kprocess(device_t, struct cryptkop *krp, int hint);
13576 +#endif
13577 +
13578 +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,20)
13579 +static kmem_cache_t *qcache;
13580 +#else
13581 +static struct kmem_cache *qcache;
13582 +#endif
13583 +
13584 +#define debug ixp_debug
13585 +static int ixp_debug = 0;
13586 +module_param(ixp_debug, int, 0644);
13587 +MODULE_PARM_DESC(ixp_debug, "Enable debug");
13588 +
13589 +static int ixp_init_crypto = 1;
13590 +module_param(ixp_init_crypto, int, 0444); /* RO after load/boot */
13591 +MODULE_PARM_DESC(ixp_init_crypto, "Call ixCryptoAccInit (default is 1)");
13592 +
13593 +static void ixp_process_pending(void *arg);
13594 +static void ixp_registration(void *arg);
13595 +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,20)
13596 +static void ixp_process_pending_wq(struct work_struct *work);
13597 +static void ixp_registration_wq(struct work_struct *work);
13598 +#endif
13599 +
13600 +/*
13601 + * dummy device structure
13602 + */
13603 +
13604 +static struct {
13605 + softc_device_decl sc_dev;
13606 +} ixpdev;
13607 +
13608 +static device_method_t ixp_methods = {
13609 + /* crypto device methods */
13610 + DEVMETHOD(cryptodev_newsession, ixp_newsession),
13611 + DEVMETHOD(cryptodev_freesession,ixp_freesession),
13612 + DEVMETHOD(cryptodev_process, ixp_process),
13613 +#ifdef __ixp46X
13614 + DEVMETHOD(cryptodev_kprocess, ixp_kprocess),
13615 +#endif
13616 +};
13617 +
13618 +/*
13619 + * Generate a new software session.
13620 + */
13621 +static int
13622 +ixp_newsession(device_t dev, u_int32_t *sid, struct cryptoini *cri)
13623 +{
13624 + struct ixp_data *ixp;
13625 + u_int32_t i;
13626 +#define AUTH_LEN(cri, def) \
13627 + (cri->cri_mlen ? cri->cri_mlen : (def))
13628 +
13629 + dprintk("%s():alg %d\n", __FUNCTION__,cri->cri_alg);
13630 + if (sid == NULL || cri == NULL) {
13631 + dprintk("%s,%d - EINVAL\n", __FILE__, __LINE__);
13632 + return EINVAL;
13633 + }
13634 +
13635 + if (ixp_sessions) {
13636 + for (i = 1; i < ixp_sesnum; i++)
13637 + if (ixp_sessions[i] == NULL)
13638 + break;
13639 + } else
13640 + i = 1; /* NB: to silence compiler warning */
13641 +
13642 + if (ixp_sessions == NULL || i == ixp_sesnum) {
13643 + struct ixp_data **ixpd;
13644 +
13645 + if (ixp_sessions == NULL) {
13646 + i = 1; /* We leave ixp_sessions[0] empty */
13647 + ixp_sesnum = CRYPTO_SW_SESSIONS;
13648 + } else
13649 + ixp_sesnum *= 2;
13650 +
13651 + ixpd = kmalloc(ixp_sesnum * sizeof(struct ixp_data *), SLAB_ATOMIC);
13652 + if (ixpd == NULL) {
13653 + /* Reset session number */
13654 + if (ixp_sesnum == CRYPTO_SW_SESSIONS)
13655 + ixp_sesnum = 0;
13656 + else
13657 + ixp_sesnum /= 2;
13658 + dprintk("%s,%d: ENOBUFS\n", __FILE__, __LINE__);
13659 + return ENOBUFS;
13660 + }
13661 + memset(ixpd, 0, ixp_sesnum * sizeof(struct ixp_data *));
13662 +
13663 + /* Copy existing sessions */
13664 + if (ixp_sessions) {
13665 + memcpy(ixpd, ixp_sessions,
13666 + (ixp_sesnum / 2) * sizeof(struct ixp_data *));
13667 + kfree(ixp_sessions);
13668 + }
13669 +
13670 + ixp_sessions = ixpd;
13671 + }
13672 +
13673 + ixp_sessions[i] = (struct ixp_data *) kmalloc(sizeof(struct ixp_data),
13674 + SLAB_ATOMIC);
13675 + if (ixp_sessions[i] == NULL) {
13676 + ixp_freesession(NULL, i);
13677 + dprintk("%s,%d: EINVAL\n", __FILE__, __LINE__);
13678 + return ENOBUFS;
13679 + }
13680 +
13681 + *sid = i;
13682 +
13683 + ixp = ixp_sessions[i];
13684 + memset(ixp, 0, sizeof(*ixp));
13685 +
13686 + ixp->ixp_cipher_alg = -1;
13687 + ixp->ixp_auth_alg = -1;
13688 + ixp->ixp_ctx_id = -1;
13689 + INIT_LIST_HEAD(&ixp->ixp_q);
13690 +
13691 + ixp->ixp_ctx.useDifferentSrcAndDestMbufs = 0;
13692 +
13693 + while (cri) {
13694 + switch (cri->cri_alg) {
13695 + case CRYPTO_DES_CBC:
13696 + ixp->ixp_cipher_alg = cri->cri_alg;
13697 + ixp->ixp_ctx.cipherCtx.cipherAlgo = IX_CRYPTO_ACC_CIPHER_DES;
13698 + ixp->ixp_ctx.cipherCtx.cipherMode = IX_CRYPTO_ACC_MODE_CBC;
13699 + ixp->ixp_ctx.cipherCtx.cipherKeyLen = (cri->cri_klen + 7) / 8;
13700 + ixp->ixp_ctx.cipherCtx.cipherBlockLen = IX_CRYPTO_ACC_DES_BLOCK_64;
13701 + ixp->ixp_ctx.cipherCtx.cipherInitialVectorLen =
13702 + IX_CRYPTO_ACC_DES_IV_64;
13703 + memcpy(ixp->ixp_ctx.cipherCtx.key.cipherKey,
13704 + cri->cri_key, (cri->cri_klen + 7) / 8);
13705 + break;
13706 +
13707 + case CRYPTO_3DES_CBC:
13708 + ixp->ixp_cipher_alg = cri->cri_alg;
13709 + ixp->ixp_ctx.cipherCtx.cipherAlgo = IX_CRYPTO_ACC_CIPHER_3DES;
13710 + ixp->ixp_ctx.cipherCtx.cipherMode = IX_CRYPTO_ACC_MODE_CBC;
13711 + ixp->ixp_ctx.cipherCtx.cipherKeyLen = (cri->cri_klen + 7) / 8;
13712 + ixp->ixp_ctx.cipherCtx.cipherBlockLen = IX_CRYPTO_ACC_DES_BLOCK_64;
13713 + ixp->ixp_ctx.cipherCtx.cipherInitialVectorLen =
13714 + IX_CRYPTO_ACC_DES_IV_64;
13715 + memcpy(ixp->ixp_ctx.cipherCtx.key.cipherKey,
13716 + cri->cri_key, (cri->cri_klen + 7) / 8);
13717 + break;
13718 +
13719 + case CRYPTO_RIJNDAEL128_CBC:
13720 + ixp->ixp_cipher_alg = cri->cri_alg;
13721 + ixp->ixp_ctx.cipherCtx.cipherAlgo = IX_CRYPTO_ACC_CIPHER_AES;
13722 + ixp->ixp_ctx.cipherCtx.cipherMode = IX_CRYPTO_ACC_MODE_CBC;
13723 + ixp->ixp_ctx.cipherCtx.cipherKeyLen = (cri->cri_klen + 7) / 8;
13724 + ixp->ixp_ctx.cipherCtx.cipherBlockLen = 16;
13725 + ixp->ixp_ctx.cipherCtx.cipherInitialVectorLen = 16;
13726 + memcpy(ixp->ixp_ctx.cipherCtx.key.cipherKey,
13727 + cri->cri_key, (cri->cri_klen + 7) / 8);
13728 + break;
13729 +
13730 + case CRYPTO_MD5:
13731 + case CRYPTO_MD5_HMAC:
13732 + ixp->ixp_auth_alg = cri->cri_alg;
13733 + ixp->ixp_ctx.authCtx.authAlgo = IX_CRYPTO_ACC_AUTH_MD5;
13734 + ixp->ixp_ctx.authCtx.authDigestLen = AUTH_LEN(cri, MD5_HASH_LEN);
13735 + ixp->ixp_ctx.authCtx.aadLen = 0;
13736 + /* Only MD5_HMAC needs a key */
13737 + if (cri->cri_alg == CRYPTO_MD5_HMAC) {
13738 + ixp->ixp_ctx.authCtx.authKeyLen = (cri->cri_klen + 7) / 8;
13739 + if (ixp->ixp_ctx.authCtx.authKeyLen >
13740 + sizeof(ixp->ixp_ctx.authCtx.key.authKey)) {
13741 + printk(
13742 + "ixp4xx: Invalid key length for MD5_HMAC - %d bits\n",
13743 + cri->cri_klen);
13744 + ixp_freesession(NULL, i);
13745 + return EINVAL;
13746 + }
13747 + memcpy(ixp->ixp_ctx.authCtx.key.authKey,
13748 + cri->cri_key, (cri->cri_klen + 7) / 8);
13749 + }
13750 + break;
13751 +
13752 + case CRYPTO_SHA1:
13753 + case CRYPTO_SHA1_HMAC:
13754 + ixp->ixp_auth_alg = cri->cri_alg;
13755 + ixp->ixp_ctx.authCtx.authAlgo = IX_CRYPTO_ACC_AUTH_SHA1;
13756 + ixp->ixp_ctx.authCtx.authDigestLen = AUTH_LEN(cri, SHA1_HASH_LEN);
13757 + ixp->ixp_ctx.authCtx.aadLen = 0;
13758 + /* Only SHA1_HMAC needs a key */
13759 + if (cri->cri_alg == CRYPTO_SHA1_HMAC) {
13760 + ixp->ixp_ctx.authCtx.authKeyLen = (cri->cri_klen + 7) / 8;
13761 + if (ixp->ixp_ctx.authCtx.authKeyLen >
13762 + sizeof(ixp->ixp_ctx.authCtx.key.authKey)) {
13763 + printk(
13764 + "ixp4xx: Invalid key length for SHA1_HMAC - %d bits\n",
13765 + cri->cri_klen);
13766 + ixp_freesession(NULL, i);
13767 + return EINVAL;
13768 + }
13769 + memcpy(ixp->ixp_ctx.authCtx.key.authKey,
13770 + cri->cri_key, (cri->cri_klen + 7) / 8);
13771 + }
13772 + break;
13773 +
13774 + default:
13775 + printk("ixp: unknown algo 0x%x\n", cri->cri_alg);
13776 + ixp_freesession(NULL, i);
13777 + return EINVAL;
13778 + }
13779 + cri = cri->cri_next;
13780 + }
13781 +
13782 +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,20)
13783 + INIT_WORK(&ixp->ixp_pending_work, ixp_process_pending_wq);
13784 + INIT_WORK(&ixp->ixp_registration_work, ixp_registration_wq);
13785 +#else
13786 + INIT_WORK(&ixp->ixp_pending_work, ixp_process_pending, ixp);
13787 + INIT_WORK(&ixp->ixp_registration_work, ixp_registration, ixp);
13788 +#endif
13789 +
13790 + return 0;
13791 +}
13792 +
13793 +
13794 +/*
13795 + * Free a session.
13796 + */
13797 +static int
13798 +ixp_freesession(device_t dev, u_int64_t tid)
13799 +{
13800 + u_int32_t sid = CRYPTO_SESID2LID(tid);
13801 +
13802 + dprintk("%s()\n", __FUNCTION__);
13803 + if (sid > ixp_sesnum || ixp_sessions == NULL ||
13804 + ixp_sessions[sid] == NULL) {
13805 + dprintk("%s,%d: EINVAL\n", __FILE__, __LINE__);
13806 + return EINVAL;
13807 + }
13808 +
13809 + /* Silently accept and return */
13810 + if (sid == 0)
13811 + return 0;
13812 +
13813 + if (ixp_sessions[sid]) {
13814 + if (ixp_sessions[sid]->ixp_ctx_id != -1) {
13815 + ixCryptoAccCtxUnregister(ixp_sessions[sid]->ixp_ctx_id);
13816 + ixp_sessions[sid]->ixp_ctx_id = -1;
13817 + }
13818 +
13819 + flush_scheduled_work();
13820 +
13821 + kfree(ixp_sessions[sid]);
13822 + }
13823 + ixp_sessions[sid] = NULL;
13824 + if (ixp_blocked) {
13825 + ixp_blocked = 0;
13826 + crypto_unblock(ixp_id, CRYPTO_SYMQ);
13827 + }
13828 + return 0;
13829 +}
13830 +
13831 +
13832 +/*
13833 + * callback for when hash processing is complete
13834 + */
13835 +
13836 +static void
13837 +ixp_hash_perform_cb(
13838 + UINT32 hash_key_id,
13839 + IX_MBUF *bufp,
13840 + IxCryptoAccStatus status)
13841 +{
13842 + struct ixp_q *q;
13843 +
13844 + dprintk("%s(%u, %p, 0x%x)\n", __FUNCTION__, hash_key_id, bufp, status);
13845 +
13846 + if (bufp == NULL) {
13847 + printk("ixp: NULL buf in %s\n", __FUNCTION__);
13848 + return;
13849 + }
13850 +
13851 + q = IX_MBUF_PRIV(bufp);
13852 + if (q == NULL) {
13853 + printk("ixp: NULL priv in %s\n", __FUNCTION__);
13854 + return;
13855 + }
13856 +
13857 + if (status == IX_CRYPTO_ACC_STATUS_SUCCESS) {
13858 + /* On success, need to copy hash back into original client buffer */
13859 + memcpy(q->ixp_hash_dest, q->ixp_hash_src,
13860 + (q->ixp_q_data->ixp_auth_alg == CRYPTO_SHA1) ?
13861 + SHA1_HASH_LEN : MD5_HASH_LEN);
13862 + }
13863 + else {
13864 + printk("ixp: hash perform failed status=%d\n", status);
13865 + q->ixp_q_crp->crp_etype = EINVAL;
13866 + }
13867 +
13868 + /* Free internal buffer used for hashing */
13869 + kfree(IX_MBUF_MDATA(&q->ixp_q_mbuf));
13870 +
13871 + crypto_done(q->ixp_q_crp);
13872 + kmem_cache_free(qcache, q);
13873 +}
13874 +
13875 +/*
13876 + * setup a request and perform it
13877 + */
13878 +static void
13879 +ixp_q_process(struct ixp_q *q)
13880 +{
13881 + IxCryptoAccStatus status;
13882 + struct ixp_data *ixp = q->ixp_q_data;
13883 + int auth_off = 0;
13884 + int auth_len = 0;
13885 + int crypt_off = 0;
13886 + int crypt_len = 0;
13887 + int icv_off = 0;
13888 + char *crypt_func;
13889 +
13890 + dprintk("%s(%p)\n", __FUNCTION__, q);
13891 +
13892 + if (q->ixp_q_ccrd) {
13893 + if (q->ixp_q_ccrd->crd_flags & CRD_F_IV_EXPLICIT) {
13894 + q->ixp_q_iv = q->ixp_q_ccrd->crd_iv;
13895 + } else {
13896 + q->ixp_q_iv = q->ixp_q_iv_data;
13897 + crypto_copydata(q->ixp_q_crp->crp_flags, q->ixp_q_crp->crp_buf,
13898 + q->ixp_q_ccrd->crd_inject,
13899 + ixp->ixp_ctx.cipherCtx.cipherInitialVectorLen,
13900 + (caddr_t) q->ixp_q_iv);
13901 + }
13902 +
13903 + if (q->ixp_q_acrd) {
13904 + auth_off = q->ixp_q_acrd->crd_skip;
13905 + auth_len = q->ixp_q_acrd->crd_len;
13906 + icv_off = q->ixp_q_acrd->crd_inject;
13907 + }
13908 +
13909 + crypt_off = q->ixp_q_ccrd->crd_skip;
13910 + crypt_len = q->ixp_q_ccrd->crd_len;
13911 + } else { /* if (q->ixp_q_acrd) */
13912 + auth_off = q->ixp_q_acrd->crd_skip;
13913 + auth_len = q->ixp_q_acrd->crd_len;
13914 + icv_off = q->ixp_q_acrd->crd_inject;
13915 + }
13916 +
13917 + if (q->ixp_q_crp->crp_flags & CRYPTO_F_SKBUF) {
13918 + struct sk_buff *skb = (struct sk_buff *) q->ixp_q_crp->crp_buf;
13919 + if (skb_shinfo(skb)->nr_frags) {
13920 + /*
13921 + * DAVIDM fix this limitation one day by using
13922 + * a buffer pool and chaining, it is not currently
13923 + * needed for current user/kernel space acceleration
13924 + */
13925 + printk("ixp: Cannot handle fragmented skb's yet !\n");
13926 + q->ixp_q_crp->crp_etype = ENOENT;
13927 + goto done;
13928 + }
13929 + IX_MBUF_MLEN(&q->ixp_q_mbuf) =
13930 + IX_MBUF_PKT_LEN(&q->ixp_q_mbuf) = skb->len;
13931 + IX_MBUF_MDATA(&q->ixp_q_mbuf) = skb->data;
13932 + } else if (q->ixp_q_crp->crp_flags & CRYPTO_F_IOV) {
13933 + struct uio *uiop = (struct uio *) q->ixp_q_crp->crp_buf;
13934 + if (uiop->uio_iovcnt != 1) {
13935 + /*
13936 + * DAVIDM fix this limitation one day by using
13937 + * a buffer pool and chaining, it is not currently
13938 + * needed for current user/kernel space acceleration
13939 + */
13940 + printk("ixp: Cannot handle more than 1 iovec yet !\n");
13941 + q->ixp_q_crp->crp_etype = ENOENT;
13942 + goto done;
13943 + }
13944 + IX_MBUF_MLEN(&q->ixp_q_mbuf) =
13945 + IX_MBUF_PKT_LEN(&q->ixp_q_mbuf) = uiop->uio_iov[0].iov_len;
13946 + IX_MBUF_MDATA(&q->ixp_q_mbuf) = uiop->uio_iov[0].iov_base;
13947 + } else /* contig buffer */ {
13948 + IX_MBUF_MLEN(&q->ixp_q_mbuf) =
13949 + IX_MBUF_PKT_LEN(&q->ixp_q_mbuf) = q->ixp_q_crp->crp_ilen;
13950 + IX_MBUF_MDATA(&q->ixp_q_mbuf) = q->ixp_q_crp->crp_buf;
13951 + }
13952 +
13953 + IX_MBUF_PRIV(&q->ixp_q_mbuf) = q;
13954 +
13955 + if (ixp->ixp_auth_alg == CRYPTO_SHA1 || ixp->ixp_auth_alg == CRYPTO_MD5) {
13956 + /*
13957 + * For SHA1 and MD5 hash, need to create an internal buffer that is big
13958 + * enough to hold the original data + the appropriate padding for the
13959 + * hash algorithm.
13960 + */
13961 + UINT8 *tbuf = NULL;
13962 +
13963 + IX_MBUF_MLEN(&q->ixp_q_mbuf) = IX_MBUF_PKT_LEN(&q->ixp_q_mbuf) =
13964 + ((IX_MBUF_MLEN(&q->ixp_q_mbuf) * 8) + 72 + 511) / 8;
13965 + tbuf = kmalloc(IX_MBUF_MLEN(&q->ixp_q_mbuf), SLAB_ATOMIC);
13966 +
13967 + if (IX_MBUF_MDATA(&q->ixp_q_mbuf) == NULL) {
13968 + printk("ixp: kmalloc(%u, SLAB_ATOMIC) failed\n",
13969 + IX_MBUF_MLEN(&q->ixp_q_mbuf));
13970 + q->ixp_q_crp->crp_etype = ENOMEM;
13971 + goto done;
13972 + }
13973 + memcpy(tbuf, &(IX_MBUF_MDATA(&q->ixp_q_mbuf))[auth_off], auth_len);
13974 +
13975 + /* Set location in client buffer to copy hash into */
13976 + q->ixp_hash_dest =
13977 + &(IX_MBUF_MDATA(&q->ixp_q_mbuf))[auth_off + auth_len];
13978 +
13979 + IX_MBUF_MDATA(&q->ixp_q_mbuf) = tbuf;
13980 +
13981 + /* Set location in internal buffer for where hash starts */
13982 + q->ixp_hash_src = &(IX_MBUF_MDATA(&q->ixp_q_mbuf))[auth_len];
13983 +
13984 + crypt_func = "ixCryptoAccHashPerform";
13985 + status = ixCryptoAccHashPerform(ixp->ixp_ctx.authCtx.authAlgo,
13986 + &q->ixp_q_mbuf, ixp_hash_perform_cb, 0, auth_len, auth_len,
13987 + &ixp->ixp_hash_key_id);
13988 + }
13989 + else {
13990 + crypt_func = "ixCryptoAccAuthCryptPerform";
13991 + status = ixCryptoAccAuthCryptPerform(ixp->ixp_ctx_id, &q->ixp_q_mbuf,
13992 + NULL, auth_off, auth_len, crypt_off, crypt_len, icv_off,
13993 + q->ixp_q_iv);
13994 + }
13995 +
13996 + if (IX_CRYPTO_ACC_STATUS_SUCCESS == status)
13997 + return;
13998 +
13999 + if (IX_CRYPTO_ACC_STATUS_QUEUE_FULL == status) {
14000 + q->ixp_q_crp->crp_etype = ENOMEM;
14001 + goto done;
14002 + }
14003 +
14004 + printk("ixp: %s failed %u\n", crypt_func, status);
14005 + q->ixp_q_crp->crp_etype = EINVAL;
14006 +
14007 +done:
14008 + crypto_done(q->ixp_q_crp);
14009 + kmem_cache_free(qcache, q);
14010 +}
14011 +
14012 +
14013 +/*
14014 + * because we cannot process the Q from the Register callback
14015 + * we do it here on a task Q.
14016 + */
14017 +
14018 +static void
14019 +ixp_process_pending(void *arg)
14020 +{
14021 + struct ixp_data *ixp = arg;
14022 + struct ixp_q *q = NULL;
14023 +
14024 + dprintk("%s(%p)\n", __FUNCTION__, arg);
14025 +
14026 + if (!ixp)
14027 + return;
14028 +
14029 + while (!list_empty(&ixp->ixp_q)) {
14030 + q = list_entry(ixp->ixp_q.next, struct ixp_q, ixp_q_list);
14031 + list_del(&q->ixp_q_list);
14032 + ixp_q_process(q);
14033 + }
14034 +}
14035 +
14036 +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,20)
14037 +static void
14038 +ixp_process_pending_wq(struct work_struct *work)
14039 +{
14040 + struct ixp_data *ixp = container_of(work, struct ixp_data,
14041 + ixp_pending_work);
14042 + ixp_process_pending(ixp);
14043 +}
14044 +#endif
14045 +
14046 +/*
14047 + * callback for when context registration is complete
14048 + */
14049 +
14050 +static void
14051 +ixp_register_cb(UINT32 ctx_id, IX_MBUF *bufp, IxCryptoAccStatus status)
14052 +{
14053 + int i;
14054 + struct ixp_data *ixp;
14055 + struct ixp_q *q;
14056 +
14057 + dprintk("%s(%d, %p, %d)\n", __FUNCTION__, ctx_id, bufp, status);
14058 +
14059 + /*
14060 + * free any buffer passed in to this routine
14061 + */
14062 + if (bufp) {
14063 + IX_MBUF_MLEN(bufp) = IX_MBUF_PKT_LEN(bufp) = 0;
14064 + kfree(IX_MBUF_MDATA(bufp));
14065 + IX_MBUF_MDATA(bufp) = NULL;
14066 + }
14067 +
14068 + for (i = 0; i < ixp_sesnum; i++) {
14069 + ixp = ixp_sessions[i];
14070 + if (ixp && ixp->ixp_ctx_id == ctx_id)
14071 + break;
14072 + }
14073 + if (i >= ixp_sesnum) {
14074 + printk("ixp: invalid context id %d\n", ctx_id);
14075 + return;
14076 + }
14077 +
14078 + if (IX_CRYPTO_ACC_STATUS_WAIT == status) {
14079 + /* this is normal to free the first of two buffers */
14080 + dprintk("ixp: register not finished yet.\n");
14081 + return;
14082 + }
14083 +
14084 + if (IX_CRYPTO_ACC_STATUS_SUCCESS != status) {
14085 + printk("ixp: register failed 0x%x\n", status);
14086 + while (!list_empty(&ixp->ixp_q)) {
14087 + q = list_entry(ixp->ixp_q.next, struct ixp_q, ixp_q_list);
14088 + list_del(&q->ixp_q_list);
14089 + q->ixp_q_crp->crp_etype = EINVAL;
14090 + crypto_done(q->ixp_q_crp);
14091 + kmem_cache_free(qcache, q);
14092 + }
14093 + return;
14094 + }
14095 +
14096 + /*
14097 + * we are now registered, we cannot start processing the Q here
14098 + * or we get strange errors with AES (DES/3DES seem to be ok).
14099 + */
14100 + ixp->ixp_registered = 1;
14101 + schedule_work(&ixp->ixp_pending_work);
14102 +}
14103 +
14104 +
14105 +/*
14106 + * callback for when data processing is complete
14107 + */
14108 +
14109 +static void
14110 +ixp_perform_cb(
14111 + UINT32 ctx_id,
14112 + IX_MBUF *sbufp,
14113 + IX_MBUF *dbufp,
14114 + IxCryptoAccStatus status)
14115 +{
14116 + struct ixp_q *q;
14117 +
14118 + dprintk("%s(%d, %p, %p, 0x%x)\n", __FUNCTION__, ctx_id, sbufp,
14119 + dbufp, status);
14120 +
14121 + if (sbufp == NULL) {
14122 + printk("ixp: NULL sbuf in ixp_perform_cb\n");
14123 + return;
14124 + }
14125 +
14126 + q = IX_MBUF_PRIV(sbufp);
14127 + if (q == NULL) {
14128 + printk("ixp: NULL priv in ixp_perform_cb\n");
14129 + return;
14130 + }
14131 +
14132 + if (status != IX_CRYPTO_ACC_STATUS_SUCCESS) {
14133 + printk("ixp: perform failed status=%d\n", status);
14134 + q->ixp_q_crp->crp_etype = EINVAL;
14135 + }
14136 +
14137 + crypto_done(q->ixp_q_crp);
14138 + kmem_cache_free(qcache, q);
14139 +}
14140 +
14141 +
14142 +/*
14143 + * registration is not callable at IRQ time, so we defer
14144 + * to a task queue, this routines completes the registration for us
14145 + * when the task queue runs
14146 + *
14147 + * Unfortunately this means we cannot tell OCF that the driver is blocked,
14148 + * we do that on the next request.
14149 + */
14150 +
14151 +static void
14152 +ixp_registration(void *arg)
14153 +{
14154 + struct ixp_data *ixp = arg;
14155 + struct ixp_q *q = NULL;
14156 + IX_MBUF *pri = NULL, *sec = NULL;
14157 + int status = IX_CRYPTO_ACC_STATUS_SUCCESS;
14158 +
14159 + if (!ixp) {
14160 + printk("ixp: ixp_registration with no arg\n");
14161 + return;
14162 + }
14163 +
14164 + if (ixp->ixp_ctx_id != -1) {
14165 + ixCryptoAccCtxUnregister(ixp->ixp_ctx_id);
14166 + ixp->ixp_ctx_id = -1;
14167 + }
14168 +
14169 + if (list_empty(&ixp->ixp_q)) {
14170 + printk("ixp: ixp_registration with no Q\n");
14171 + return;
14172 + }
14173 +
14174 + /*
14175 + * setup the primary and secondary buffers
14176 + */
14177 + q = list_entry(ixp->ixp_q.next, struct ixp_q, ixp_q_list);
14178 + if (q->ixp_q_acrd) {
14179 + pri = &ixp->ixp_pri_mbuf;
14180 + sec = &ixp->ixp_sec_mbuf;
14181 + IX_MBUF_MLEN(pri) = IX_MBUF_PKT_LEN(pri) = 128;
14182 + IX_MBUF_MDATA(pri) = (unsigned char *) kmalloc(128, SLAB_ATOMIC);
14183 + IX_MBUF_MLEN(sec) = IX_MBUF_PKT_LEN(sec) = 128;
14184 + IX_MBUF_MDATA(sec) = (unsigned char *) kmalloc(128, SLAB_ATOMIC);
14185 + }
14186 +
14187 + /* Only need to register if a crypt op or HMAC op */
14188 + if (!(ixp->ixp_auth_alg == CRYPTO_SHA1 ||
14189 + ixp->ixp_auth_alg == CRYPTO_MD5)) {
14190 + status = ixCryptoAccCtxRegister(
14191 + &ixp->ixp_ctx,
14192 + pri, sec,
14193 + ixp_register_cb,
14194 + ixp_perform_cb,
14195 + &ixp->ixp_ctx_id);
14196 + }
14197 + else {
14198 + /* Otherwise we start processing pending q */
14199 + schedule_work(&ixp->ixp_pending_work);
14200 + }
14201 +
14202 + if (IX_CRYPTO_ACC_STATUS_SUCCESS == status)
14203 + return;
14204 +
14205 + if (IX_CRYPTO_ACC_STATUS_EXCEED_MAX_TUNNELS == status) {
14206 + printk("ixp: ixCryptoAccCtxRegister failed (out of tunnels)\n");
14207 + ixp_blocked = 1;
14208 + /* perhaps we should return EGAIN on queued ops ? */
14209 + return;
14210 + }
14211 +
14212 + printk("ixp: ixCryptoAccCtxRegister failed %d\n", status);
14213 + ixp->ixp_ctx_id = -1;
14214 +
14215 + /*
14216 + * everything waiting is toasted
14217 + */
14218 + while (!list_empty(&ixp->ixp_q)) {
14219 + q = list_entry(ixp->ixp_q.next, struct ixp_q, ixp_q_list);
14220 + list_del(&q->ixp_q_list);
14221 + q->ixp_q_crp->crp_etype = ENOENT;
14222 + crypto_done(q->ixp_q_crp);
14223 + kmem_cache_free(qcache, q);
14224 + }
14225 +}
14226 +
14227 +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,20)
14228 +static void
14229 +ixp_registration_wq(struct work_struct *work)
14230 +{
14231 + struct ixp_data *ixp = container_of(work, struct ixp_data,
14232 + ixp_registration_work);
14233 + ixp_registration(ixp);
14234 +}
14235 +#endif
14236 +
14237 +/*
14238 + * Process a request.
14239 + */
14240 +static int
14241 +ixp_process(device_t dev, struct cryptop *crp, int hint)
14242 +{
14243 + struct ixp_data *ixp;
14244 + unsigned int lid;
14245 + struct ixp_q *q = NULL;
14246 + int status;
14247 +
14248 + dprintk("%s()\n", __FUNCTION__);
14249 +
14250 + /* Sanity check */
14251 + if (crp == NULL) {
14252 + dprintk("%s,%d: EINVAL\n", __FILE__, __LINE__);
14253 + return EINVAL;
14254 + }
14255 +
14256 + crp->crp_etype = 0;
14257 +
14258 + if (ixp_blocked)
14259 + return ERESTART;
14260 +
14261 + if (crp->crp_desc == NULL || crp->crp_buf == NULL) {
14262 + dprintk("%s,%d: EINVAL\n", __FILE__, __LINE__);
14263 + crp->crp_etype = EINVAL;
14264 + goto done;
14265 + }
14266 +
14267 + /*
14268 + * find the session we are using
14269 + */
14270 +
14271 + lid = crp->crp_sid & 0xffffffff;
14272 + if (lid >= ixp_sesnum || lid == 0 || ixp_sessions == NULL ||
14273 + ixp_sessions[lid] == NULL) {
14274 + crp->crp_etype = ENOENT;
14275 + dprintk("%s,%d: ENOENT\n", __FILE__, __LINE__);
14276 + goto done;
14277 + }
14278 + ixp = ixp_sessions[lid];
14279 +
14280 + /*
14281 + * setup a new request ready for queuing
14282 + */
14283 + q = kmem_cache_alloc(qcache, SLAB_ATOMIC);
14284 + if (q == NULL) {
14285 + dprintk("%s,%d: ENOMEM\n", __FILE__, __LINE__);
14286 + crp->crp_etype = ENOMEM;
14287 + goto done;
14288 + }
14289 + /*
14290 + * save some cycles by only zeroing the important bits
14291 + */
14292 + memset(&q->ixp_q_mbuf, 0, sizeof(q->ixp_q_mbuf));
14293 + q->ixp_q_ccrd = NULL;
14294 + q->ixp_q_acrd = NULL;
14295 + q->ixp_q_crp = crp;
14296 + q->ixp_q_data = ixp;
14297 +
14298 + /*
14299 + * point the cipher and auth descriptors appropriately
14300 + * check that we have something to do
14301 + */
14302 + if (crp->crp_desc->crd_alg == ixp->ixp_cipher_alg)
14303 + q->ixp_q_ccrd = crp->crp_desc;
14304 + else if (crp->crp_desc->crd_alg == ixp->ixp_auth_alg)
14305 + q->ixp_q_acrd = crp->crp_desc;
14306 + else {
14307 + crp->crp_etype = ENOENT;
14308 + dprintk("%s,%d: bad desc match: ENOENT\n", __FILE__, __LINE__);
14309 + goto done;
14310 + }
14311 + if (crp->crp_desc->crd_next) {
14312 + if (crp->crp_desc->crd_next->crd_alg == ixp->ixp_cipher_alg)
14313 + q->ixp_q_ccrd = crp->crp_desc->crd_next;
14314 + else if (crp->crp_desc->crd_next->crd_alg == ixp->ixp_auth_alg)
14315 + q->ixp_q_acrd = crp->crp_desc->crd_next;
14316 + else {
14317 + crp->crp_etype = ENOENT;
14318 + dprintk("%s,%d: bad desc match: ENOENT\n", __FILE__, __LINE__);
14319 + goto done;
14320 + }
14321 + }
14322 +
14323 + /*
14324 + * If there is a direction change for this context then we mark it as
14325 + * unregistered and re-register is for the new direction. This is not
14326 + * a very expensive operation and currently only tends to happen when
14327 + * user-space application are doing benchmarks
14328 + *
14329 + * DM - we should be checking for pending requests before unregistering.
14330 + */
14331 + if (q->ixp_q_ccrd && ixp->ixp_registered &&
14332 + ixp->ixp_crd_flags != (q->ixp_q_ccrd->crd_flags & CRD_F_ENCRYPT)) {
14333 + dprintk("%s - detected direction change on session\n", __FUNCTION__);
14334 + ixp->ixp_registered = 0;
14335 + }
14336 +
14337 + /*
14338 + * if we are registered, call straight into the perform code
14339 + */
14340 + if (ixp->ixp_registered) {
14341 + ixp_q_process(q);
14342 + return 0;
14343 + }
14344 +
14345 + /*
14346 + * the only part of the context not set in newsession is the direction
14347 + * dependent parts
14348 + */
14349 + if (q->ixp_q_ccrd) {
14350 + ixp->ixp_crd_flags = (q->ixp_q_ccrd->crd_flags & CRD_F_ENCRYPT);
14351 + if (q->ixp_q_ccrd->crd_flags & CRD_F_ENCRYPT) {
14352 + ixp->ixp_ctx.operation = q->ixp_q_acrd ?
14353 + IX_CRYPTO_ACC_OP_ENCRYPT_AUTH : IX_CRYPTO_ACC_OP_ENCRYPT;
14354 + } else {
14355 + ixp->ixp_ctx.operation = q->ixp_q_acrd ?
14356 + IX_CRYPTO_ACC_OP_AUTH_DECRYPT : IX_CRYPTO_ACC_OP_DECRYPT;
14357 + }
14358 + } else {
14359 + /* q->ixp_q_acrd must be set if we are here */
14360 + ixp->ixp_ctx.operation = IX_CRYPTO_ACC_OP_AUTH_CALC;
14361 + }
14362 +
14363 + status = list_empty(&ixp->ixp_q);
14364 + list_add_tail(&q->ixp_q_list, &ixp->ixp_q);
14365 + if (status)
14366 + schedule_work(&ixp->ixp_registration_work);
14367 + return 0;
14368 +
14369 +done:
14370 + if (q)
14371 + kmem_cache_free(qcache, q);
14372 + crypto_done(crp);
14373 + return 0;
14374 +}
14375 +
14376 +
14377 +#ifdef __ixp46X
14378 +/*
14379 + * key processing support for the ixp465
14380 + */
14381 +
14382 +
14383 +/*
14384 + * copy a BN (LE) into a buffer (BE) an fill out the op appropriately
14385 + * assume zeroed and only copy bits that are significant
14386 + */
14387 +
14388 +static int
14389 +ixp_copy_ibuf(struct crparam *p, IxCryptoAccPkeEauOperand *op, UINT32 *buf)
14390 +{
14391 + unsigned char *src = (unsigned char *) p->crp_p;
14392 + unsigned char *dst;
14393 + int len, bits = p->crp_nbits;
14394 +
14395 + dprintk("%s()\n", __FUNCTION__);
14396 +
14397 + if (bits > MAX_IOP_SIZE * sizeof(UINT32) * 8) {
14398 + dprintk("%s - ibuf too big (%d > %d)\n", __FUNCTION__,
14399 + bits, MAX_IOP_SIZE * sizeof(UINT32) * 8);
14400 + return -1;
14401 + }
14402 +
14403 + len = (bits + 31) / 32; /* the number UINT32's needed */
14404 +
14405 + dst = (unsigned char *) &buf[len];
14406 + dst--;
14407 +
14408 + while (bits > 0) {
14409 + *dst-- = *src++;
14410 + bits -= 8;
14411 + }
14412 +
14413 +#if 0 /* no need to zero remaining bits as it is done during request alloc */
14414 + while (dst > (unsigned char *) buf)
14415 + *dst-- = '\0';
14416 +#endif
14417 +
14418 + op->pData = buf;
14419 + op->dataLen = len;
14420 + return 0;
14421 +}
14422 +
14423 +/*
14424 + * copy out the result, be as forgiving as we can about small output buffers
14425 + */
14426 +
14427 +static int
14428 +ixp_copy_obuf(struct crparam *p, IxCryptoAccPkeEauOpResult *op, UINT32 *buf)
14429 +{
14430 + unsigned char *dst = (unsigned char *) p->crp_p;
14431 + unsigned char *src = (unsigned char *) buf;
14432 + int len, z, bits = p->crp_nbits;
14433 +
14434 + dprintk("%s()\n", __FUNCTION__);
14435 +
14436 + len = op->dataLen * sizeof(UINT32);
14437 +
14438 + /* skip leading zeroes to be small buffer friendly */
14439 + z = 0;
14440 + while (z < len && src[z] == '\0')
14441 + z++;
14442 +
14443 + src += len;
14444 + src--;
14445 + len -= z;
14446 +
14447 + while (len > 0 && bits > 0) {
14448 + *dst++ = *src--;
14449 + len--;
14450 + bits -= 8;
14451 + }
14452 +
14453 + while (bits > 0) {
14454 + *dst++ = '\0';
14455 + bits -= 8;
14456 + }
14457 +
14458 + if (len > 0) {
14459 + dprintk("%s - obuf is %d (z=%d, ob=%d) bytes too small\n",
14460 + __FUNCTION__, len, z, p->crp_nbits / 8);
14461 + return -1;
14462 + }
14463 +
14464 + return 0;
14465 +}
14466 +
14467 +
14468 +/*
14469 + * the parameter offsets for exp_mod
14470 + */
14471 +
14472 +#define IXP_PARAM_BASE 0
14473 +#define IXP_PARAM_EXP 1
14474 +#define IXP_PARAM_MOD 2
14475 +#define IXP_PARAM_RES 3
14476 +
14477 +/*
14478 + * key processing complete callback, is also used to start processing
14479 + * by passing a NULL for pResult
14480 + */
14481 +
14482 +static void
14483 +ixp_kperform_cb(
14484 + IxCryptoAccPkeEauOperation operation,
14485 + IxCryptoAccPkeEauOpResult *pResult,
14486 + BOOL carryOrBorrow,
14487 + IxCryptoAccStatus status)
14488 +{
14489 + struct ixp_pkq *q, *tmp;
14490 + unsigned long flags;
14491 +
14492 + dprintk("%s(0x%x, %p, %d, 0x%x)\n", __FUNCTION__, operation, pResult,
14493 + carryOrBorrow, status);
14494 +
14495 + /* handle a completed request */
14496 + if (pResult) {
14497 + if (ixp_pk_cur && &ixp_pk_cur->pkq_result == pResult) {
14498 + q = ixp_pk_cur;
14499 + if (status != IX_CRYPTO_ACC_STATUS_SUCCESS) {
14500 + dprintk("%s() - op failed 0x%x\n", __FUNCTION__, status);
14501 + q->pkq_krp->krp_status = ERANGE; /* could do better */
14502 + } else {
14503 + /* copy out the result */
14504 + if (ixp_copy_obuf(&q->pkq_krp->krp_param[IXP_PARAM_RES],
14505 + &q->pkq_result, q->pkq_obuf))
14506 + q->pkq_krp->krp_status = ERANGE;
14507 + }
14508 + crypto_kdone(q->pkq_krp);
14509 + kfree(q);
14510 + ixp_pk_cur = NULL;
14511 + } else
14512 + printk("%s - callback with invalid result pointer\n", __FUNCTION__);
14513 + }
14514 +
14515 + spin_lock_irqsave(&ixp_pkq_lock, flags);
14516 + if (ixp_pk_cur || list_empty(&ixp_pkq)) {
14517 + spin_unlock_irqrestore(&ixp_pkq_lock, flags);
14518 + return;
14519 + }
14520 +
14521 + list_for_each_entry_safe(q, tmp, &ixp_pkq, pkq_list) {
14522 +
14523 + list_del(&q->pkq_list);
14524 + ixp_pk_cur = q;
14525 +
14526 + spin_unlock_irqrestore(&ixp_pkq_lock, flags);
14527 +
14528 + status = ixCryptoAccPkeEauPerform(
14529 + IX_CRYPTO_ACC_OP_EAU_MOD_EXP,
14530 + &q->pkq_op,
14531 + ixp_kperform_cb,
14532 + &q->pkq_result);
14533 +
14534 + if (status == IX_CRYPTO_ACC_STATUS_SUCCESS) {
14535 + dprintk("%s() - ixCryptoAccPkeEauPerform SUCCESS\n", __FUNCTION__);
14536 + return; /* callback will return here for callback */
14537 + } else if (status == IX_CRYPTO_ACC_STATUS_RETRY) {
14538 + printk("%s() - ixCryptoAccPkeEauPerform RETRY\n", __FUNCTION__);
14539 + } else {
14540 + printk("%s() - ixCryptoAccPkeEauPerform failed %d\n",
14541 + __FUNCTION__, status);
14542 + }
14543 + q->pkq_krp->krp_status = ERANGE; /* could do better */
14544 + crypto_kdone(q->pkq_krp);
14545 + kfree(q);
14546 + spin_lock_irqsave(&ixp_pkq_lock, flags);
14547 + }
14548 + spin_unlock_irqrestore(&ixp_pkq_lock, flags);
14549 +}
14550 +
14551 +
14552 +static int
14553 +ixp_kprocess(device_t dev, struct cryptkop *krp, int hint)
14554 +{
14555 + struct ixp_pkq *q;
14556 + int rc = 0;
14557 + unsigned long flags;
14558 +
14559 + dprintk("%s l1=%d l2=%d l3=%d l4=%d\n", __FUNCTION__,
14560 + krp->krp_param[IXP_PARAM_BASE].crp_nbits,
14561 + krp->krp_param[IXP_PARAM_EXP].crp_nbits,
14562 + krp->krp_param[IXP_PARAM_MOD].crp_nbits,
14563 + krp->krp_param[IXP_PARAM_RES].crp_nbits);
14564 +
14565 +
14566 + if (krp->krp_op != CRK_MOD_EXP) {
14567 + krp->krp_status = EOPNOTSUPP;
14568 + goto err;
14569 + }
14570 +
14571 + q = (struct ixp_pkq *) kmalloc(sizeof(*q), GFP_KERNEL);
14572 + if (q == NULL) {
14573 + krp->krp_status = ENOMEM;
14574 + goto err;
14575 + }
14576 +
14577 + /*
14578 + * The PKE engine does not appear to zero the output buffer
14579 + * appropriately, so we need to do it all here.
14580 + */
14581 + memset(q, 0, sizeof(*q));
14582 +
14583 + q->pkq_krp = krp;
14584 + INIT_LIST_HEAD(&q->pkq_list);
14585 +
14586 + if (ixp_copy_ibuf(&krp->krp_param[IXP_PARAM_BASE], &q->pkq_op.modExpOpr.M,
14587 + q->pkq_ibuf0))
14588 + rc = 1;
14589 + if (!rc && ixp_copy_ibuf(&krp->krp_param[IXP_PARAM_EXP],
14590 + &q->pkq_op.modExpOpr.e, q->pkq_ibuf1))
14591 + rc = 2;
14592 + if (!rc && ixp_copy_ibuf(&krp->krp_param[IXP_PARAM_MOD],
14593 + &q->pkq_op.modExpOpr.N, q->pkq_ibuf2))
14594 + rc = 3;
14595 +
14596 + if (rc) {
14597 + kfree(q);
14598 + krp->krp_status = ERANGE;
14599 + goto err;
14600 + }
14601 +
14602 + q->pkq_result.pData = q->pkq_obuf;
14603 + q->pkq_result.dataLen =
14604 + (krp->krp_param[IXP_PARAM_RES].crp_nbits + 31) / 32;
14605 +
14606 + spin_lock_irqsave(&ixp_pkq_lock, flags);
14607 + list_add_tail(&q->pkq_list, &ixp_pkq);
14608 + spin_unlock_irqrestore(&ixp_pkq_lock, flags);
14609 +
14610 + if (!ixp_pk_cur)
14611 + ixp_kperform_cb(0, NULL, 0, 0);
14612 + return (0);
14613 +
14614 +err:
14615 + crypto_kdone(krp);
14616 + return (0);
14617 +}
14618 +
14619 +
14620 +
14621 +#ifdef CONFIG_OCF_RANDOMHARVEST
14622 +/*
14623 + * We run the random number generator output through SHA so that it
14624 + * is FIPS compliant.
14625 + */
14626 +
14627 +static volatile int sha_done = 0;
14628 +static unsigned char sha_digest[20];
14629 +
14630 +static void
14631 +ixp_hash_cb(UINT8 *digest, IxCryptoAccStatus status)
14632 +{
14633 + dprintk("%s(%p, %d)\n", __FUNCTION__, digest, status);
14634 + if (sha_digest != digest)
14635 + printk("digest error\n");
14636 + if (IX_CRYPTO_ACC_STATUS_SUCCESS == status)
14637 + sha_done = 1;
14638 + else
14639 + sha_done = -status;
14640 +}
14641 +
14642 +static int
14643 +ixp_read_random(void *arg, u_int32_t *buf, int maxwords)
14644 +{
14645 + IxCryptoAccStatus status;
14646 + int i, n, rc;
14647 +
14648 + dprintk("%s(%p, %d)\n", __FUNCTION__, buf, maxwords);
14649 + memset(buf, 0, maxwords * sizeof(*buf));
14650 + status = ixCryptoAccPkePseudoRandomNumberGet(maxwords, buf);
14651 + if (status != IX_CRYPTO_ACC_STATUS_SUCCESS) {
14652 + dprintk("%s: ixCryptoAccPkePseudoRandomNumberGet failed %d\n",
14653 + __FUNCTION__, status);
14654 + return 0;
14655 + }
14656 +
14657 + /*
14658 + * run the random data through SHA to make it look more random
14659 + */
14660 +
14661 + n = sizeof(sha_digest); /* process digest bytes at a time */
14662 +
14663 + rc = 0;
14664 + for (i = 0; i < maxwords; i += n / sizeof(*buf)) {
14665 + if ((maxwords - i) * sizeof(*buf) < n)
14666 + n = (maxwords - i) * sizeof(*buf);
14667 + sha_done = 0;
14668 + status = ixCryptoAccPkeHashPerform(IX_CRYPTO_ACC_AUTH_SHA1,
14669 + (UINT8 *) &buf[i], n, ixp_hash_cb, sha_digest);
14670 + if (status != IX_CRYPTO_ACC_STATUS_SUCCESS) {
14671 + dprintk("ixCryptoAccPkeHashPerform failed %d\n", status);
14672 + return -EIO;
14673 + }
14674 + while (!sha_done)
14675 + schedule();
14676 + if (sha_done < 0) {
14677 + dprintk("ixCryptoAccPkeHashPerform failed CB %d\n", -sha_done);
14678 + return 0;
14679 + }
14680 + memcpy(&buf[i], sha_digest, n);
14681 + rc += n / sizeof(*buf);;
14682 + }
14683 +
14684 + return rc;
14685 +}
14686 +#endif /* CONFIG_OCF_RANDOMHARVEST */
14687 +
14688 +#endif /* __ixp46X */
14689 +
14690 +
14691 +
14692 +/*
14693 + * our driver startup and shutdown routines
14694 + */
14695 +
14696 +static int
14697 +ixp_init(void)
14698 +{
14699 + dprintk("%s(%p)\n", __FUNCTION__, ixp_init);
14700 +
14701 + if (ixp_init_crypto && ixCryptoAccInit() != IX_CRYPTO_ACC_STATUS_SUCCESS)
14702 + printk("ixCryptoAccInit failed, assuming already initialised!\n");
14703 +
14704 + qcache = kmem_cache_create("ixp4xx_q", sizeof(struct ixp_q), 0,
14705 + SLAB_HWCACHE_ALIGN, NULL
14706 +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,23)
14707 + , NULL
14708 +#endif
14709 + );
14710 + if (!qcache) {
14711 + printk("failed to create Qcache\n");
14712 + return -ENOENT;
14713 + }
14714 +
14715 + memset(&ixpdev, 0, sizeof(ixpdev));
14716 + softc_device_init(&ixpdev, "ixp4xx", 0, ixp_methods);
14717 +
14718 + ixp_id = crypto_get_driverid(softc_get_device(&ixpdev),
14719 + CRYPTOCAP_F_HARDWARE);
14720 + if (ixp_id < 0)
14721 + panic("IXP/OCF crypto device cannot initialize!");
14722 +
14723 +#define REGISTER(alg) \
14724 + crypto_register(ixp_id,alg,0,0)
14725 +
14726 + REGISTER(CRYPTO_DES_CBC);
14727 + REGISTER(CRYPTO_3DES_CBC);
14728 + REGISTER(CRYPTO_RIJNDAEL128_CBC);
14729 +#ifdef CONFIG_OCF_IXP4XX_SHA1_MD5
14730 + REGISTER(CRYPTO_MD5);
14731 + REGISTER(CRYPTO_SHA1);
14732 +#endif
14733 + REGISTER(CRYPTO_MD5_HMAC);
14734 + REGISTER(CRYPTO_SHA1_HMAC);
14735 +#undef REGISTER
14736 +
14737 +#ifdef __ixp46X
14738 + spin_lock_init(&ixp_pkq_lock);
14739 + /*
14740 + * we do not enable the go fast options here as they can potentially
14741 + * allow timing based attacks
14742 + *
14743 + * http://www.openssl.org/news/secadv_20030219.txt
14744 + */
14745 + ixCryptoAccPkeEauExpConfig(0, 0);
14746 + crypto_kregister(ixp_id, CRK_MOD_EXP, 0);
14747 +#ifdef CONFIG_OCF_RANDOMHARVEST
14748 + crypto_rregister(ixp_id, ixp_read_random, NULL);
14749 +#endif
14750 +#endif
14751 +
14752 + return 0;
14753 +}
14754 +
14755 +static void
14756 +ixp_exit(void)
14757 +{
14758 + dprintk("%s()\n", __FUNCTION__);
14759 + crypto_unregister_all(ixp_id);
14760 + ixp_id = -1;
14761 + kmem_cache_destroy(qcache);
14762 + qcache = NULL;
14763 +}
14764 +
14765 +module_init(ixp_init);
14766 +module_exit(ixp_exit);
14767 +
14768 +MODULE_LICENSE("Dual BSD/GPL");
14769 +MODULE_AUTHOR("David McCullough <dmccullough@cyberguard.com>");
14770 +MODULE_DESCRIPTION("ixp (OCF module for IXP4xx crypto)");
14771 --- /dev/null
14772 +++ b/crypto/ocf/cryptodev.c
14773 @@ -0,0 +1,1048 @@
14774 +/* $OpenBSD: cryptodev.c,v 1.52 2002/06/19 07:22:46 deraadt Exp $ */
14775 +
14776 +/*-
14777 + * Linux port done by David McCullough <david_mccullough@securecomputing.com>
14778 + * Copyright (C) 2006-2007 David McCullough
14779 + * Copyright (C) 2004-2005 Intel Corporation.
14780 + * The license and original author are listed below.
14781 + *
14782 + * Copyright (c) 2001 Theo de Raadt
14783 + * Copyright (c) 2002-2006 Sam Leffler, Errno Consulting
14784 + *
14785 + * Redistribution and use in source and binary forms, with or without
14786 + * modification, are permitted provided that the following conditions
14787 + * are met:
14788 + *
14789 + * 1. Redistributions of source code must retain the above copyright
14790 + * notice, this list of conditions and the following disclaimer.
14791 + * 2. Redistributions in binary form must reproduce the above copyright
14792 + * notice, this list of conditions and the following disclaimer in the
14793 + * documentation and/or other materials provided with the distribution.
14794 + * 3. The name of the author may not be used to endorse or promote products
14795 + * derived from this software without specific prior written permission.
14796 + *
14797 + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
14798 + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
14799 + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
14800 + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
14801 + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
14802 + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
14803 + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
14804 + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
14805 + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
14806 + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
14807 + *
14808 + * Effort sponsored in part by the Defense Advanced Research Projects
14809 + * Agency (DARPA) and Air Force Research Laboratory, Air Force
14810 + * Materiel Command, USAF, under agreement number F30602-01-2-0537.
14811 + *
14812 +__FBSDID("$FreeBSD: src/sys/opencrypto/cryptodev.c,v 1.34 2007/05/09 19:37:02 gnn Exp $");
14813 + */
14814 +
14815 +#ifndef AUTOCONF_INCLUDED
14816 +#include <linux/config.h>
14817 +#endif
14818 +#include <linux/types.h>
14819 +#include <linux/time.h>
14820 +#include <linux/delay.h>
14821 +#include <linux/list.h>
14822 +#include <linux/init.h>
14823 +#include <linux/sched.h>
14824 +#include <linux/unistd.h>
14825 +#include <linux/module.h>
14826 +#include <linux/wait.h>
14827 +#include <linux/slab.h>
14828 +#include <linux/fs.h>
14829 +#include <linux/dcache.h>
14830 +#include <linux/fdtable.h>
14831 +#include <linux/mount.h>
14832 +#include <linux/miscdevice.h>
14833 +#include <linux/version.h>
14834 +#include <asm/uaccess.h>
14835 +
14836 +#include <cryptodev.h>
14837 +#include <uio.h>
14838 +
14839 +extern asmlinkage long sys_dup(unsigned int fildes);
14840 +
14841 +#define debug cryptodev_debug
14842 +int cryptodev_debug = 0;
14843 +module_param(cryptodev_debug, int, 0644);
14844 +MODULE_PARM_DESC(cryptodev_debug, "Enable cryptodev debug");
14845 +
14846 +struct csession_info {
14847 + u_int16_t blocksize;
14848 + u_int16_t minkey, maxkey;
14849 +
14850 + u_int16_t keysize;
14851 + /* u_int16_t hashsize; */
14852 + u_int16_t authsize;
14853 + /* u_int16_t ctxsize; */
14854 +};
14855 +
14856 +struct csession {
14857 + struct list_head list;
14858 + u_int64_t sid;
14859 + u_int32_t ses;
14860 +
14861 + wait_queue_head_t waitq;
14862 +
14863 + u_int32_t cipher;
14864 +
14865 + u_int32_t mac;
14866 +
14867 + caddr_t key;
14868 + int keylen;
14869 + u_char tmp_iv[EALG_MAX_BLOCK_LEN];
14870 +
14871 + caddr_t mackey;
14872 + int mackeylen;
14873 +
14874 + struct csession_info info;
14875 +
14876 + struct iovec iovec;
14877 + struct uio uio;
14878 + int error;
14879 +};
14880 +
14881 +struct fcrypt {
14882 + struct list_head csessions;
14883 + int sesn;
14884 +};
14885 +
14886 +static struct csession *csefind(struct fcrypt *, u_int);
14887 +static int csedelete(struct fcrypt *, struct csession *);
14888 +static struct csession *cseadd(struct fcrypt *, struct csession *);
14889 +static struct csession *csecreate(struct fcrypt *, u_int64_t,
14890 + struct cryptoini *crie, struct cryptoini *cria, struct csession_info *);
14891 +static int csefree(struct csession *);
14892 +
14893 +static int cryptodev_op(struct csession *, struct crypt_op *);
14894 +static int cryptodev_key(struct crypt_kop *);
14895 +static int cryptodev_find(struct crypt_find_op *);
14896 +
14897 +static int cryptodev_cb(void *);
14898 +static int cryptodev_open(struct inode *inode, struct file *filp);
14899 +
14900 +/*
14901 + * Check a crypto identifier to see if it requested
14902 + * a valid crid and it's capabilities match.
14903 + */
14904 +static int
14905 +checkcrid(int crid)
14906 +{
14907 + int hid = crid & ~(CRYPTOCAP_F_SOFTWARE | CRYPTOCAP_F_HARDWARE);
14908 + int typ = crid & (CRYPTOCAP_F_SOFTWARE | CRYPTOCAP_F_HARDWARE);
14909 + int caps = 0;
14910 +
14911 + /* if the user hasn't selected a driver, then just call newsession */
14912 + if (hid == 0 && typ != 0)
14913 + return 0;
14914 +
14915 + caps = crypto_getcaps(hid);
14916 +
14917 + /* didn't find anything with capabilities */
14918 + if (caps == 0) {
14919 + dprintk("%s: hid=%x typ=%x not matched\n", __FUNCTION__, hid, typ);
14920 + return EINVAL;
14921 + }
14922 +
14923 + /* the user didn't specify SW or HW, so the driver is ok */
14924 + if (typ == 0)
14925 + return 0;
14926 +
14927 + /* if the type specified didn't match */
14928 + if (typ != (caps & (CRYPTOCAP_F_SOFTWARE | CRYPTOCAP_F_HARDWARE))) {
14929 + dprintk("%s: hid=%x typ=%x caps=%x not matched\n", __FUNCTION__,
14930 + hid, typ, caps);
14931 + return EINVAL;
14932 + }
14933 +
14934 + return 0;
14935 +}
14936 +
14937 +static int
14938 +cryptodev_op(struct csession *cse, struct crypt_op *cop)
14939 +{
14940 + struct cryptop *crp = NULL;
14941 + struct cryptodesc *crde = NULL, *crda = NULL;
14942 + int error = 0;
14943 +
14944 + dprintk("%s()\n", __FUNCTION__);
14945 + if (cop->len > CRYPTO_MAX_DATA_LEN) {
14946 + dprintk("%s: %d > %d\n", __FUNCTION__, cop->len, CRYPTO_MAX_DATA_LEN);
14947 + return (E2BIG);
14948 + }
14949 +
14950 + if (cse->info.blocksize && (cop->len % cse->info.blocksize) != 0) {
14951 + dprintk("%s: blocksize=%d len=%d\n", __FUNCTION__, cse->info.blocksize,
14952 + cop->len);
14953 + return (EINVAL);
14954 + }
14955 +
14956 + cse->uio.uio_iov = &cse->iovec;
14957 + cse->uio.uio_iovcnt = 1;
14958 + cse->uio.uio_offset = 0;
14959 +#if 0
14960 + cse->uio.uio_resid = cop->len;
14961 + cse->uio.uio_segflg = UIO_SYSSPACE;
14962 + cse->uio.uio_rw = UIO_WRITE;
14963 + cse->uio.uio_td = td;
14964 +#endif
14965 + cse->uio.uio_iov[0].iov_len = cop->len;
14966 + if (cse->info.authsize)
14967 + cse->uio.uio_iov[0].iov_len += cse->info.authsize;
14968 + cse->uio.uio_iov[0].iov_base = kmalloc(cse->uio.uio_iov[0].iov_len,
14969 + GFP_KERNEL);
14970 +
14971 + if (cse->uio.uio_iov[0].iov_base == NULL) {
14972 + dprintk("%s: iov_base kmalloc(%d) failed\n", __FUNCTION__,
14973 + cse->uio.uio_iov[0].iov_len);
14974 + return (ENOMEM);
14975 + }
14976 +
14977 + crp = crypto_getreq((cse->info.blocksize != 0) + (cse->info.authsize != 0));
14978 + if (crp == NULL) {
14979 + dprintk("%s: ENOMEM\n", __FUNCTION__);
14980 + error = ENOMEM;
14981 + goto bail;
14982 + }
14983 +
14984 + if (cse->info.authsize) {
14985 + crda = crp->crp_desc;
14986 + if (cse->info.blocksize)
14987 + crde = crda->crd_next;
14988 + } else {
14989 + if (cse->info.blocksize)
14990 + crde = crp->crp_desc;
14991 + else {
14992 + dprintk("%s: bad request\n", __FUNCTION__);
14993 + error = EINVAL;
14994 + goto bail;
14995 + }
14996 + }
14997 +
14998 + if ((error = copy_from_user(cse->uio.uio_iov[0].iov_base, cop->src,
14999 + cop->len))) {
15000 + dprintk("%s: bad copy\n", __FUNCTION__);
15001 + goto bail;
15002 + }
15003 +
15004 + if (crda) {
15005 + crda->crd_skip = 0;
15006 + crda->crd_len = cop->len;
15007 + crda->crd_inject = cop->len;
15008 +
15009 + crda->crd_alg = cse->mac;
15010 + crda->crd_key = cse->mackey;
15011 + crda->crd_klen = cse->mackeylen * 8;
15012 + }
15013 +
15014 + if (crde) {
15015 + if (cop->op == COP_ENCRYPT)
15016 + crde->crd_flags |= CRD_F_ENCRYPT;
15017 + else
15018 + crde->crd_flags &= ~CRD_F_ENCRYPT;
15019 + crde->crd_len = cop->len;
15020 + crde->crd_inject = 0;
15021 +
15022 + crde->crd_alg = cse->cipher;
15023 + crde->crd_key = cse->key;
15024 + crde->crd_klen = cse->keylen * 8;
15025 + }
15026 +
15027 + crp->crp_ilen = cse->uio.uio_iov[0].iov_len;
15028 + crp->crp_flags = CRYPTO_F_IOV | CRYPTO_F_CBIMM
15029 + | (cop->flags & COP_F_BATCH);
15030 + crp->crp_buf = (caddr_t)&cse->uio;
15031 + crp->crp_callback = (int (*) (struct cryptop *)) cryptodev_cb;
15032 + crp->crp_sid = cse->sid;
15033 + crp->crp_opaque = (void *)cse;
15034 +
15035 + if (cop->iv) {
15036 + if (crde == NULL) {
15037 + error = EINVAL;
15038 + dprintk("%s no crde\n", __FUNCTION__);
15039 + goto bail;
15040 + }
15041 + if (cse->cipher == CRYPTO_ARC4) { /* XXX use flag? */
15042 + error = EINVAL;
15043 + dprintk("%s arc4 with IV\n", __FUNCTION__);
15044 + goto bail;
15045 + }
15046 + if ((error = copy_from_user(cse->tmp_iv, cop->iv,
15047 + cse->info.blocksize))) {
15048 + dprintk("%s bad iv copy\n", __FUNCTION__);
15049 + goto bail;
15050 + }
15051 + memcpy(crde->crd_iv, cse->tmp_iv, cse->info.blocksize);
15052 + crde->crd_flags |= CRD_F_IV_EXPLICIT | CRD_F_IV_PRESENT;
15053 + crde->crd_skip = 0;
15054 + } else if (cse->cipher == CRYPTO_ARC4) { /* XXX use flag? */
15055 + crde->crd_skip = 0;
15056 + } else if (crde) {
15057 + crde->crd_flags |= CRD_F_IV_PRESENT;
15058 + crde->crd_skip = cse->info.blocksize;
15059 + crde->crd_len -= cse->info.blocksize;
15060 + }
15061 +
15062 + if (cop->mac && crda == NULL) {
15063 + error = EINVAL;
15064 + dprintk("%s no crda\n", __FUNCTION__);
15065 + goto bail;
15066 + }
15067 +
15068 + /*
15069 + * Let the dispatch run unlocked, then, interlock against the
15070 + * callback before checking if the operation completed and going
15071 + * to sleep. This insures drivers don't inherit our lock which
15072 + * results in a lock order reversal between crypto_dispatch forced
15073 + * entry and the crypto_done callback into us.
15074 + */
15075 + error = crypto_dispatch(crp);
15076 + if (error == 0) {
15077 + dprintk("%s about to WAIT\n", __FUNCTION__);
15078 + /*
15079 + * we really need to wait for driver to complete to maintain
15080 + * state, luckily interrupts will be remembered
15081 + */
15082 + do {
15083 + error = wait_event_interruptible(crp->crp_waitq,
15084 + ((crp->crp_flags & CRYPTO_F_DONE) != 0));
15085 + /*
15086 + * we can't break out of this loop or we will leave behind
15087 + * a huge mess, however, staying here means if your driver
15088 + * is broken user applications can hang and not be killed.
15089 + * The solution, fix your driver :-)
15090 + */
15091 + if (error) {
15092 + schedule();
15093 + error = 0;
15094 + }
15095 + } while ((crp->crp_flags & CRYPTO_F_DONE) == 0);
15096 + dprintk("%s finished WAITING error=%d\n", __FUNCTION__, error);
15097 + }
15098 +
15099 + if (crp->crp_etype != 0) {
15100 + error = crp->crp_etype;
15101 + dprintk("%s error in crp processing\n", __FUNCTION__);
15102 + goto bail;
15103 + }
15104 +
15105 + if (cse->error) {
15106 + error = cse->error;
15107 + dprintk("%s error in cse processing\n", __FUNCTION__);
15108 + goto bail;
15109 + }
15110 +
15111 + if (cop->dst && (error = copy_to_user(cop->dst,
15112 + cse->uio.uio_iov[0].iov_base, cop->len))) {
15113 + dprintk("%s bad dst copy\n", __FUNCTION__);
15114 + goto bail;
15115 + }
15116 +
15117 + if (cop->mac &&
15118 + (error=copy_to_user(cop->mac,
15119 + (caddr_t)cse->uio.uio_iov[0].iov_base + cop->len,
15120 + cse->info.authsize))) {
15121 + dprintk("%s bad mac copy\n", __FUNCTION__);
15122 + goto bail;
15123 + }
15124 +
15125 +bail:
15126 + if (crp)
15127 + crypto_freereq(crp);
15128 + if (cse->uio.uio_iov[0].iov_base)
15129 + kfree(cse->uio.uio_iov[0].iov_base);
15130 +
15131 + return (error);
15132 +}
15133 +
15134 +static int
15135 +cryptodev_cb(void *op)
15136 +{
15137 + struct cryptop *crp = (struct cryptop *) op;
15138 + struct csession *cse = (struct csession *)crp->crp_opaque;
15139 + int error;
15140 +
15141 + dprintk("%s()\n", __FUNCTION__);
15142 + error = crp->crp_etype;
15143 + if (error == EAGAIN) {
15144 + crp->crp_flags &= ~CRYPTO_F_DONE;
15145 +#ifdef NOTYET
15146 + /*
15147 + * DAVIDM I am fairly sure that we should turn this into a batch
15148 + * request to stop bad karma/lockup, revisit
15149 + */
15150 + crp->crp_flags |= CRYPTO_F_BATCH;
15151 +#endif
15152 + return crypto_dispatch(crp);
15153 + }
15154 + if (error != 0 || (crp->crp_flags & CRYPTO_F_DONE)) {
15155 + cse->error = error;
15156 + wake_up_interruptible(&crp->crp_waitq);
15157 + }
15158 + return (0);
15159 +}
15160 +
15161 +static int
15162 +cryptodevkey_cb(void *op)
15163 +{
15164 + struct cryptkop *krp = (struct cryptkop *) op;
15165 + dprintk("%s()\n", __FUNCTION__);
15166 + wake_up_interruptible(&krp->krp_waitq);
15167 + return (0);
15168 +}
15169 +
15170 +static int
15171 +cryptodev_key(struct crypt_kop *kop)
15172 +{
15173 + struct cryptkop *krp = NULL;
15174 + int error = EINVAL;
15175 + int in, out, size, i;
15176 +
15177 + dprintk("%s()\n", __FUNCTION__);
15178 + if (kop->crk_iparams + kop->crk_oparams > CRK_MAXPARAM) {
15179 + dprintk("%s params too big\n", __FUNCTION__);
15180 + return (EFBIG);
15181 + }
15182 +
15183 + in = kop->crk_iparams;
15184 + out = kop->crk_oparams;
15185 + switch (kop->crk_op) {
15186 + case CRK_MOD_EXP:
15187 + if (in == 3 && out == 1)
15188 + break;
15189 + return (EINVAL);
15190 + case CRK_MOD_EXP_CRT:
15191 + if (in == 6 && out == 1)
15192 + break;
15193 + return (EINVAL);
15194 + case CRK_DSA_SIGN:
15195 + if (in == 5 && out == 2)
15196 + break;
15197 + return (EINVAL);
15198 + case CRK_DSA_VERIFY:
15199 + if (in == 7 && out == 0)
15200 + break;
15201 + return (EINVAL);
15202 + case CRK_DH_COMPUTE_KEY:
15203 + if (in == 3 && out == 1)
15204 + break;
15205 + return (EINVAL);
15206 + default:
15207 + return (EINVAL);
15208 + }
15209 +
15210 + krp = (struct cryptkop *)kmalloc(sizeof *krp, GFP_KERNEL);
15211 + if (!krp)
15212 + return (ENOMEM);
15213 + bzero(krp, sizeof *krp);
15214 + krp->krp_op = kop->crk_op;
15215 + krp->krp_status = kop->crk_status;
15216 + krp->krp_iparams = kop->crk_iparams;
15217 + krp->krp_oparams = kop->crk_oparams;
15218 + krp->krp_crid = kop->crk_crid;
15219 + krp->krp_status = 0;
15220 + krp->krp_flags = CRYPTO_KF_CBIMM;
15221 + krp->krp_callback = (int (*) (struct cryptkop *)) cryptodevkey_cb;
15222 + init_waitqueue_head(&krp->krp_waitq);
15223 +
15224 + for (i = 0; i < CRK_MAXPARAM; i++)
15225 + krp->krp_param[i].crp_nbits = kop->crk_param[i].crp_nbits;
15226 + for (i = 0; i < krp->krp_iparams + krp->krp_oparams; i++) {
15227 + size = (krp->krp_param[i].crp_nbits + 7) / 8;
15228 + if (size == 0)
15229 + continue;
15230 + krp->krp_param[i].crp_p = (caddr_t) kmalloc(size, GFP_KERNEL);
15231 + if (i >= krp->krp_iparams)
15232 + continue;
15233 + error = copy_from_user(krp->krp_param[i].crp_p,
15234 + kop->crk_param[i].crp_p, size);
15235 + if (error)
15236 + goto fail;
15237 + }
15238 +
15239 + error = crypto_kdispatch(krp);
15240 + if (error)
15241 + goto fail;
15242 +
15243 + do {
15244 + error = wait_event_interruptible(krp->krp_waitq,
15245 + ((krp->krp_flags & CRYPTO_KF_DONE) != 0));
15246 + /*
15247 + * we can't break out of this loop or we will leave behind
15248 + * a huge mess, however, staying here means if your driver
15249 + * is broken user applications can hang and not be killed.
15250 + * The solution, fix your driver :-)
15251 + */
15252 + if (error) {
15253 + schedule();
15254 + error = 0;
15255 + }
15256 + } while ((krp->krp_flags & CRYPTO_KF_DONE) == 0);
15257 +
15258 + dprintk("%s finished WAITING error=%d\n", __FUNCTION__, error);
15259 +
15260 + kop->crk_crid = krp->krp_crid; /* device that did the work */
15261 + if (krp->krp_status != 0) {
15262 + error = krp->krp_status;
15263 + goto fail;
15264 + }
15265 +
15266 + for (i = krp->krp_iparams; i < krp->krp_iparams + krp->krp_oparams; i++) {
15267 + size = (krp->krp_param[i].crp_nbits + 7) / 8;
15268 + if (size == 0)
15269 + continue;
15270 + error = copy_to_user(kop->crk_param[i].crp_p, krp->krp_param[i].crp_p,
15271 + size);
15272 + if (error)
15273 + goto fail;
15274 + }
15275 +
15276 +fail:
15277 + if (krp) {
15278 + kop->crk_status = krp->krp_status;
15279 + for (i = 0; i < CRK_MAXPARAM; i++) {
15280 + if (krp->krp_param[i].crp_p)
15281 + kfree(krp->krp_param[i].crp_p);
15282 + }
15283 + kfree(krp);
15284 + }
15285 + return (error);
15286 +}
15287 +
15288 +static int
15289 +cryptodev_find(struct crypt_find_op *find)
15290 +{
15291 + device_t dev;
15292 +
15293 + if (find->crid != -1) {
15294 + dev = crypto_find_device_byhid(find->crid);
15295 + if (dev == NULL)
15296 + return (ENOENT);
15297 + strlcpy(find->name, device_get_nameunit(dev),
15298 + sizeof(find->name));
15299 + } else {
15300 + find->crid = crypto_find_driver(find->name);
15301 + if (find->crid == -1)
15302 + return (ENOENT);
15303 + }
15304 + return (0);
15305 +}
15306 +
15307 +static struct csession *
15308 +csefind(struct fcrypt *fcr, u_int ses)
15309 +{
15310 + struct csession *cse;
15311 +
15312 + dprintk("%s()\n", __FUNCTION__);
15313 + list_for_each_entry(cse, &fcr->csessions, list)
15314 + if (cse->ses == ses)
15315 + return (cse);
15316 + return (NULL);
15317 +}
15318 +
15319 +static int
15320 +csedelete(struct fcrypt *fcr, struct csession *cse_del)
15321 +{
15322 + struct csession *cse;
15323 +
15324 + dprintk("%s()\n", __FUNCTION__);
15325 + list_for_each_entry(cse, &fcr->csessions, list) {
15326 + if (cse == cse_del) {
15327 + list_del(&cse->list);
15328 + return (1);
15329 + }
15330 + }
15331 + return (0);
15332 +}
15333 +
15334 +static struct csession *
15335 +cseadd(struct fcrypt *fcr, struct csession *cse)
15336 +{
15337 + dprintk("%s()\n", __FUNCTION__);
15338 + list_add_tail(&cse->list, &fcr->csessions);
15339 + cse->ses = fcr->sesn++;
15340 + return (cse);
15341 +}
15342 +
15343 +static struct csession *
15344 +csecreate(struct fcrypt *fcr, u_int64_t sid, struct cryptoini *crie,
15345 + struct cryptoini *cria, struct csession_info *info)
15346 +{
15347 + struct csession *cse;
15348 +
15349 + dprintk("%s()\n", __FUNCTION__);
15350 + cse = (struct csession *) kmalloc(sizeof(struct csession), GFP_KERNEL);
15351 + if (cse == NULL)
15352 + return NULL;
15353 + memset(cse, 0, sizeof(struct csession));
15354 +
15355 + INIT_LIST_HEAD(&cse->list);
15356 + init_waitqueue_head(&cse->waitq);
15357 +
15358 + cse->key = crie->cri_key;
15359 + cse->keylen = crie->cri_klen/8;
15360 + cse->mackey = cria->cri_key;
15361 + cse->mackeylen = cria->cri_klen/8;
15362 + cse->sid = sid;
15363 + cse->cipher = crie->cri_alg;
15364 + cse->mac = cria->cri_alg;
15365 + cse->info = *info;
15366 + cseadd(fcr, cse);
15367 + return (cse);
15368 +}
15369 +
15370 +static int
15371 +csefree(struct csession *cse)
15372 +{
15373 + int error;
15374 +
15375 + dprintk("%s()\n", __FUNCTION__);
15376 + error = crypto_freesession(cse->sid);
15377 + if (cse->key)
15378 + kfree(cse->key);
15379 + if (cse->mackey)
15380 + kfree(cse->mackey);
15381 + kfree(cse);
15382 + return(error);
15383 +}
15384 +
15385 +static int
15386 +cryptodev_ioctl(
15387 + struct inode *inode,
15388 + struct file *filp,
15389 + unsigned int cmd,
15390 + unsigned long arg)
15391 +{
15392 + struct cryptoini cria, crie;
15393 + struct fcrypt *fcr = filp->private_data;
15394 + struct csession *cse;
15395 + struct csession_info info;
15396 + struct session2_op sop;
15397 + struct crypt_op cop;
15398 + struct crypt_kop kop;
15399 + struct crypt_find_op fop;
15400 + u_int64_t sid;
15401 + u_int32_t ses;
15402 + int feat, fd, error = 0, crid;
15403 + mm_segment_t fs;
15404 +
15405 + dprintk("%s(cmd=%x arg=%lx)\n", __FUNCTION__, cmd, arg);
15406 +
15407 + switch (cmd) {
15408 +
15409 + case CRIOGET: {
15410 + dprintk("%s(CRIOGET)\n", __FUNCTION__);
15411 + fs = get_fs();
15412 + set_fs(get_ds());
15413 + for (fd = 0; fd < files_fdtable(current->files)->max_fds; fd++)
15414 + if (files_fdtable(current->files)->fd[fd] == filp)
15415 + break;
15416 + fd = sys_dup(fd);
15417 + set_fs(fs);
15418 + put_user(fd, (int *) arg);
15419 + return IS_ERR_VALUE(fd) ? fd : 0;
15420 + }
15421 +
15422 +#define CIOCGSESSSTR (cmd == CIOCGSESSION ? "CIOCGSESSION" : "CIOCGSESSION2")
15423 + case CIOCGSESSION:
15424 + case CIOCGSESSION2:
15425 + dprintk("%s(%s)\n", __FUNCTION__, CIOCGSESSSTR);
15426 + memset(&crie, 0, sizeof(crie));
15427 + memset(&cria, 0, sizeof(cria));
15428 + memset(&info, 0, sizeof(info));
15429 + memset(&sop, 0, sizeof(sop));
15430 +
15431 + if (copy_from_user(&sop, (void*)arg, (cmd == CIOCGSESSION) ?
15432 + sizeof(struct session_op) : sizeof(sop))) {
15433 + dprintk("%s(%s) - bad copy\n", __FUNCTION__, CIOCGSESSSTR);
15434 + error = EFAULT;
15435 + goto bail;
15436 + }
15437 +
15438 + switch (sop.cipher) {
15439 + case 0:
15440 + dprintk("%s(%s) - no cipher\n", __FUNCTION__, CIOCGSESSSTR);
15441 + break;
15442 + case CRYPTO_NULL_CBC:
15443 + info.blocksize = NULL_BLOCK_LEN;
15444 + info.minkey = NULL_MIN_KEY_LEN;
15445 + info.maxkey = NULL_MAX_KEY_LEN;
15446 + break;
15447 + case CRYPTO_DES_CBC:
15448 + info.blocksize = DES_BLOCK_LEN;
15449 + info.minkey = DES_MIN_KEY_LEN;
15450 + info.maxkey = DES_MAX_KEY_LEN;
15451 + break;
15452 + case CRYPTO_3DES_CBC:
15453 + info.blocksize = DES3_BLOCK_LEN;
15454 + info.minkey = DES3_MIN_KEY_LEN;
15455 + info.maxkey = DES3_MAX_KEY_LEN;
15456 + break;
15457 + case CRYPTO_BLF_CBC:
15458 + info.blocksize = BLOWFISH_BLOCK_LEN;
15459 + info.minkey = BLOWFISH_MIN_KEY_LEN;
15460 + info.maxkey = BLOWFISH_MAX_KEY_LEN;
15461 + break;
15462 + case CRYPTO_CAST_CBC:
15463 + info.blocksize = CAST128_BLOCK_LEN;
15464 + info.minkey = CAST128_MIN_KEY_LEN;
15465 + info.maxkey = CAST128_MAX_KEY_LEN;
15466 + break;
15467 + case CRYPTO_SKIPJACK_CBC:
15468 + info.blocksize = SKIPJACK_BLOCK_LEN;
15469 + info.minkey = SKIPJACK_MIN_KEY_LEN;
15470 + info.maxkey = SKIPJACK_MAX_KEY_LEN;
15471 + break;
15472 + case CRYPTO_AES_CBC:
15473 + info.blocksize = AES_BLOCK_LEN;
15474 + info.minkey = AES_MIN_KEY_LEN;
15475 + info.maxkey = AES_MAX_KEY_LEN;
15476 + break;
15477 + case CRYPTO_ARC4:
15478 + info.blocksize = ARC4_BLOCK_LEN;
15479 + info.minkey = ARC4_MIN_KEY_LEN;
15480 + info.maxkey = ARC4_MAX_KEY_LEN;
15481 + break;
15482 + case CRYPTO_CAMELLIA_CBC:
15483 + info.blocksize = CAMELLIA_BLOCK_LEN;
15484 + info.minkey = CAMELLIA_MIN_KEY_LEN;
15485 + info.maxkey = CAMELLIA_MAX_KEY_LEN;
15486 + break;
15487 + default:
15488 + dprintk("%s(%s) - bad cipher\n", __FUNCTION__, CIOCGSESSSTR);
15489 + error = EINVAL;
15490 + goto bail;
15491 + }
15492 +
15493 + switch (sop.mac) {
15494 + case 0:
15495 + dprintk("%s(%s) - no mac\n", __FUNCTION__, CIOCGSESSSTR);
15496 + break;
15497 + case CRYPTO_NULL_HMAC:
15498 + info.authsize = NULL_HASH_LEN;
15499 + break;
15500 + case CRYPTO_MD5:
15501 + info.authsize = MD5_HASH_LEN;
15502 + break;
15503 + case CRYPTO_SHA1:
15504 + info.authsize = SHA1_HASH_LEN;
15505 + break;
15506 + case CRYPTO_SHA2_256:
15507 + info.authsize = SHA2_256_HASH_LEN;
15508 + break;
15509 + case CRYPTO_SHA2_384:
15510 + info.authsize = SHA2_384_HASH_LEN;
15511 + break;
15512 + case CRYPTO_SHA2_512:
15513 + info.authsize = SHA2_512_HASH_LEN;
15514 + break;
15515 + case CRYPTO_RIPEMD160:
15516 + info.authsize = RIPEMD160_HASH_LEN;
15517 + break;
15518 + case CRYPTO_MD5_HMAC:
15519 + info.authsize = MD5_HASH_LEN;
15520 + break;
15521 + case CRYPTO_SHA1_HMAC:
15522 + info.authsize = SHA1_HASH_LEN;
15523 + break;
15524 + case CRYPTO_SHA2_256_HMAC:
15525 + info.authsize = SHA2_256_HASH_LEN;
15526 + break;
15527 + case CRYPTO_SHA2_384_HMAC:
15528 + info.authsize = SHA2_384_HASH_LEN;
15529 + break;
15530 + case CRYPTO_SHA2_512_HMAC:
15531 + info.authsize = SHA2_512_HASH_LEN;
15532 + break;
15533 + case CRYPTO_RIPEMD160_HMAC:
15534 + info.authsize = RIPEMD160_HASH_LEN;
15535 + break;
15536 + default:
15537 + dprintk("%s(%s) - bad mac\n", __FUNCTION__, CIOCGSESSSTR);
15538 + error = EINVAL;
15539 + goto bail;
15540 + }
15541 +
15542 + if (info.blocksize) {
15543 + crie.cri_alg = sop.cipher;
15544 + crie.cri_klen = sop.keylen * 8;
15545 + if ((info.maxkey && sop.keylen > info.maxkey) ||
15546 + sop.keylen < info.minkey) {
15547 + dprintk("%s(%s) - bad key\n", __FUNCTION__, CIOCGSESSSTR);
15548 + error = EINVAL;
15549 + goto bail;
15550 + }
15551 +
15552 + crie.cri_key = (u_int8_t *) kmalloc(crie.cri_klen/8+1, GFP_KERNEL);
15553 + if (copy_from_user(crie.cri_key, sop.key,
15554 + crie.cri_klen/8)) {
15555 + dprintk("%s(%s) - bad copy\n", __FUNCTION__, CIOCGSESSSTR);
15556 + error = EFAULT;
15557 + goto bail;
15558 + }
15559 + if (info.authsize)
15560 + crie.cri_next = &cria;
15561 + }
15562 +
15563 + if (info.authsize) {
15564 + cria.cri_alg = sop.mac;
15565 + cria.cri_klen = sop.mackeylen * 8;
15566 + if ((info.maxkey && sop.mackeylen > info.maxkey) ||
15567 + sop.keylen < info.minkey) {
15568 + dprintk("%s(%s) - mackeylen %d\n", __FUNCTION__, CIOCGSESSSTR,
15569 + sop.mackeylen);
15570 + error = EINVAL;
15571 + goto bail;
15572 + }
15573 +
15574 + if (cria.cri_klen) {
15575 + cria.cri_key = (u_int8_t *) kmalloc(cria.cri_klen/8,GFP_KERNEL);
15576 + if (copy_from_user(cria.cri_key, sop.mackey,
15577 + cria.cri_klen / 8)) {
15578 + dprintk("%s(%s) - bad copy\n", __FUNCTION__, CIOCGSESSSTR);
15579 + error = EFAULT;
15580 + goto bail;
15581 + }
15582 + }
15583 + }
15584 +
15585 + /* NB: CIOGSESSION2 has the crid */
15586 + if (cmd == CIOCGSESSION2) {
15587 + crid = sop.crid;
15588 + error = checkcrid(crid);
15589 + if (error) {
15590 + dprintk("%s(%s) - checkcrid %x\n", __FUNCTION__,
15591 + CIOCGSESSSTR, error);
15592 + goto bail;
15593 + }
15594 + } else {
15595 + /* allow either HW or SW to be used */
15596 + crid = CRYPTOCAP_F_HARDWARE | CRYPTOCAP_F_SOFTWARE;
15597 + }
15598 + error = crypto_newsession(&sid, (info.blocksize ? &crie : &cria), crid);
15599 + if (error) {
15600 + dprintk("%s(%s) - newsession %d\n",__FUNCTION__,CIOCGSESSSTR,error);
15601 + goto bail;
15602 + }
15603 +
15604 + cse = csecreate(fcr, sid, &crie, &cria, &info);
15605 + if (cse == NULL) {
15606 + crypto_freesession(sid);
15607 + error = EINVAL;
15608 + dprintk("%s(%s) - csecreate failed\n", __FUNCTION__, CIOCGSESSSTR);
15609 + goto bail;
15610 + }
15611 + sop.ses = cse->ses;
15612 +
15613 + if (cmd == CIOCGSESSION2) {
15614 + /* return hardware/driver id */
15615 + sop.crid = CRYPTO_SESID2HID(cse->sid);
15616 + }
15617 +
15618 + if (copy_to_user((void*)arg, &sop, (cmd == CIOCGSESSION) ?
15619 + sizeof(struct session_op) : sizeof(sop))) {
15620 + dprintk("%s(%s) - bad copy\n", __FUNCTION__, CIOCGSESSSTR);
15621 + error = EFAULT;
15622 + }
15623 +bail:
15624 + if (error) {
15625 + dprintk("%s(%s) - bail %d\n", __FUNCTION__, CIOCGSESSSTR, error);
15626 + if (crie.cri_key)
15627 + kfree(crie.cri_key);
15628 + if (cria.cri_key)
15629 + kfree(cria.cri_key);
15630 + }
15631 + break;
15632 + case CIOCFSESSION:
15633 + dprintk("%s(CIOCFSESSION)\n", __FUNCTION__);
15634 + get_user(ses, (uint32_t*)arg);
15635 + cse = csefind(fcr, ses);
15636 + if (cse == NULL) {
15637 + error = EINVAL;
15638 + dprintk("%s(CIOCFSESSION) - Fail %d\n", __FUNCTION__, error);
15639 + break;
15640 + }
15641 + csedelete(fcr, cse);
15642 + error = csefree(cse);
15643 + break;
15644 + case CIOCCRYPT:
15645 + dprintk("%s(CIOCCRYPT)\n", __FUNCTION__);
15646 + if(copy_from_user(&cop, (void*)arg, sizeof(cop))) {
15647 + dprintk("%s(CIOCCRYPT) - bad copy\n", __FUNCTION__);
15648 + error = EFAULT;
15649 + goto bail;
15650 + }
15651 + cse = csefind(fcr, cop.ses);
15652 + if (cse == NULL) {
15653 + error = EINVAL;
15654 + dprintk("%s(CIOCCRYPT) - Fail %d\n", __FUNCTION__, error);
15655 + break;
15656 + }
15657 + error = cryptodev_op(cse, &cop);
15658 + if(copy_to_user((void*)arg, &cop, sizeof(cop))) {
15659 + dprintk("%s(CIOCCRYPT) - bad return copy\n", __FUNCTION__);
15660 + error = EFAULT;
15661 + goto bail;
15662 + }
15663 + break;
15664 + case CIOCKEY:
15665 + case CIOCKEY2:
15666 + dprintk("%s(CIOCKEY)\n", __FUNCTION__);
15667 + if (!crypto_userasymcrypto)
15668 + return (EPERM); /* XXX compat? */
15669 + if(copy_from_user(&kop, (void*)arg, sizeof(kop))) {
15670 + dprintk("%s(CIOCKEY) - bad copy\n", __FUNCTION__);
15671 + error = EFAULT;
15672 + goto bail;
15673 + }
15674 + if (cmd == CIOCKEY) {
15675 + /* NB: crypto core enforces s/w driver use */
15676 + kop.crk_crid =
15677 + CRYPTOCAP_F_HARDWARE | CRYPTOCAP_F_SOFTWARE;
15678 + }
15679 + error = cryptodev_key(&kop);
15680 + if(copy_to_user((void*)arg, &kop, sizeof(kop))) {
15681 + dprintk("%s(CIOCGKEY) - bad return copy\n", __FUNCTION__);
15682 + error = EFAULT;
15683 + goto bail;
15684 + }
15685 + break;
15686 + case CIOCASYMFEAT:
15687 + dprintk("%s(CIOCASYMFEAT)\n", __FUNCTION__);
15688 + if (!crypto_userasymcrypto) {
15689 + /*
15690 + * NB: if user asym crypto operations are
15691 + * not permitted return "no algorithms"
15692 + * so well-behaved applications will just
15693 + * fallback to doing them in software.
15694 + */
15695 + feat = 0;
15696 + } else
15697 + error = crypto_getfeat(&feat);
15698 + if (!error) {
15699 + error = copy_to_user((void*)arg, &feat, sizeof(feat));
15700 + }
15701 + break;
15702 + case CIOCFINDDEV:
15703 + if (copy_from_user(&fop, (void*)arg, sizeof(fop))) {
15704 + dprintk("%s(CIOCFINDDEV) - bad copy\n", __FUNCTION__);
15705 + error = EFAULT;
15706 + goto bail;
15707 + }
15708 + error = cryptodev_find(&fop);
15709 + if (copy_to_user((void*)arg, &fop, sizeof(fop))) {
15710 + dprintk("%s(CIOCFINDDEV) - bad return copy\n", __FUNCTION__);
15711 + error = EFAULT;
15712 + goto bail;
15713 + }
15714 + break;
15715 + default:
15716 + dprintk("%s(unknown ioctl 0x%x)\n", __FUNCTION__, cmd);
15717 + error = EINVAL;
15718 + break;
15719 + }
15720 + return(-error);
15721 +}
15722 +
15723 +#ifdef HAVE_UNLOCKED_IOCTL
15724 +static long
15725 +cryptodev_unlocked_ioctl(
15726 + struct file *filp,
15727 + unsigned int cmd,
15728 + unsigned long arg)
15729 +{
15730 + return cryptodev_ioctl(NULL, filp, cmd, arg);
15731 +}
15732 +#endif
15733 +
15734 +static int
15735 +cryptodev_open(struct inode *inode, struct file *filp)
15736 +{
15737 + struct fcrypt *fcr;
15738 +
15739 + dprintk("%s()\n", __FUNCTION__);
15740 + if (filp->private_data) {
15741 + printk("cryptodev: Private data already exists !\n");
15742 + return(0);
15743 + }
15744 +
15745 + fcr = kmalloc(sizeof(*fcr), GFP_KERNEL);
15746 + if (!fcr) {
15747 + dprintk("%s() - malloc failed\n", __FUNCTION__);
15748 + return(-ENOMEM);
15749 + }
15750 + memset(fcr, 0, sizeof(*fcr));
15751 +
15752 + INIT_LIST_HEAD(&fcr->csessions);
15753 + filp->private_data = fcr;
15754 + return(0);
15755 +}
15756 +
15757 +static int
15758 +cryptodev_release(struct inode *inode, struct file *filp)
15759 +{
15760 + struct fcrypt *fcr = filp->private_data;
15761 + struct csession *cse, *tmp;
15762 +
15763 + dprintk("%s()\n", __FUNCTION__);
15764 + if (!filp) {
15765 + printk("cryptodev: No private data on release\n");
15766 + return(0);
15767 + }
15768 +
15769 + list_for_each_entry_safe(cse, tmp, &fcr->csessions, list) {
15770 + list_del(&cse->list);
15771 + (void)csefree(cse);
15772 + }
15773 + filp->private_data = NULL;
15774 + kfree(fcr);
15775 + return(0);
15776 +}
15777 +
15778 +static struct file_operations cryptodev_fops = {
15779 + .owner = THIS_MODULE,
15780 + .open = cryptodev_open,
15781 + .release = cryptodev_release,
15782 + .ioctl = cryptodev_ioctl,
15783 +#ifdef HAVE_UNLOCKED_IOCTL
15784 + .unlocked_ioctl = cryptodev_unlocked_ioctl,
15785 +#endif
15786 +};
15787 +
15788 +static struct miscdevice cryptodev = {
15789 + .minor = CRYPTODEV_MINOR,
15790 + .name = "crypto",
15791 + .fops = &cryptodev_fops,
15792 +};
15793 +
15794 +static int __init
15795 +cryptodev_init(void)
15796 +{
15797 + int rc;
15798 +
15799 + dprintk("%s(%p)\n", __FUNCTION__, cryptodev_init);
15800 + rc = misc_register(&cryptodev);
15801 + if (rc) {
15802 + printk(KERN_ERR "cryptodev: registration of /dev/crypto failed\n");
15803 + return(rc);
15804 + }
15805 +
15806 + return(0);
15807 +}
15808 +
15809 +static void __exit
15810 +cryptodev_exit(void)
15811 +{
15812 + dprintk("%s()\n", __FUNCTION__);
15813 + misc_deregister(&cryptodev);
15814 +}
15815 +
15816 +module_init(cryptodev_init);
15817 +module_exit(cryptodev_exit);
15818 +
15819 +MODULE_LICENSE("BSD");
15820 +MODULE_AUTHOR("David McCullough <david_mccullough@securecomputing.com>");
15821 +MODULE_DESCRIPTION("Cryptodev (user interface to OCF)");
15822 --- /dev/null
15823 +++ b/crypto/ocf/cryptodev.h
15824 @@ -0,0 +1,478 @@
15825 +/* $FreeBSD: src/sys/opencrypto/cryptodev.h,v 1.25 2007/05/09 19:37:02 gnn Exp $ */
15826 +/* $OpenBSD: cryptodev.h,v 1.31 2002/06/11 11:14:29 beck Exp $ */
15827 +
15828 +/*-
15829 + * Linux port done by David McCullough <david_mccullough@securecomputing.com>
15830 + * Copyright (C) 2006-2007 David McCullough
15831 + * Copyright (C) 2004-2005 Intel Corporation.
15832 + * The license and original author are listed below.
15833 + *
15834 + * The author of this code is Angelos D. Keromytis (angelos@cis.upenn.edu)
15835 + * Copyright (c) 2002-2006 Sam Leffler, Errno Consulting
15836 + *
15837 + * This code was written by Angelos D. Keromytis in Athens, Greece, in
15838 + * February 2000. Network Security Technologies Inc. (NSTI) kindly
15839 + * supported the development of this code.
15840 + *
15841 + * Copyright (c) 2000 Angelos D. Keromytis
15842 + *
15843 + * Permission to use, copy, and modify this software with or without fee
15844 + * is hereby granted, provided that this entire notice is included in
15845 + * all source code copies of any software which is or includes a copy or
15846 + * modification of this software.
15847 + *
15848 + * THIS SOFTWARE IS BEING PROVIDED "AS IS", WITHOUT ANY EXPRESS OR
15849 + * IMPLIED WARRANTY. IN PARTICULAR, NONE OF THE AUTHORS MAKES ANY
15850 + * REPRESENTATION OR WARRANTY OF ANY KIND CONCERNING THE
15851 + * MERCHANTABILITY OF THIS SOFTWARE OR ITS FITNESS FOR ANY PARTICULAR
15852 + * PURPOSE.
15853 + *
15854 + * Copyright (c) 2001 Theo de Raadt
15855 + *
15856 + * Redistribution and use in source and binary forms, with or without
15857 + * modification, are permitted provided that the following conditions
15858 + * are met:
15859 + *
15860 + * 1. Redistributions of source code must retain the above copyright
15861 + * notice, this list of conditions and the following disclaimer.
15862 + * 2. Redistributions in binary form must reproduce the above copyright
15863 + * notice, this list of conditions and the following disclaimer in the
15864 + * documentation and/or other materials provided with the distribution.
15865 + * 3. The name of the author may not be used to endorse or promote products
15866 + * derived from this software without specific prior written permission.
15867 + *
15868 + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
15869 + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
15870 + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
15871 + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
15872 + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
15873 + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
15874 + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
15875 + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
15876 + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
15877 + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
15878 + *
15879 + * Effort sponsored in part by the Defense Advanced Research Projects
15880 + * Agency (DARPA) and Air Force Research Laboratory, Air Force
15881 + * Materiel Command, USAF, under agreement number F30602-01-2-0537.
15882 + *
15883 + */
15884 +
15885 +#ifndef _CRYPTO_CRYPTO_H_
15886 +#define _CRYPTO_CRYPTO_H_
15887 +
15888 +/* Some initial values */
15889 +#define CRYPTO_DRIVERS_INITIAL 4
15890 +#define CRYPTO_SW_SESSIONS 32
15891 +
15892 +/* Hash values */
15893 +#define NULL_HASH_LEN 0
15894 +#define MD5_HASH_LEN 16
15895 +#define SHA1_HASH_LEN 20
15896 +#define RIPEMD160_HASH_LEN 20
15897 +#define SHA2_256_HASH_LEN 32
15898 +#define SHA2_384_HASH_LEN 48
15899 +#define SHA2_512_HASH_LEN 64
15900 +#define MD5_KPDK_HASH_LEN 16
15901 +#define SHA1_KPDK_HASH_LEN 20
15902 +/* Maximum hash algorithm result length */
15903 +#define HASH_MAX_LEN SHA2_512_HASH_LEN /* Keep this updated */
15904 +
15905 +/* HMAC values */
15906 +#define NULL_HMAC_BLOCK_LEN 1
15907 +#define MD5_HMAC_BLOCK_LEN 64
15908 +#define SHA1_HMAC_BLOCK_LEN 64
15909 +#define RIPEMD160_HMAC_BLOCK_LEN 64
15910 +#define SHA2_256_HMAC_BLOCK_LEN 64
15911 +#define SHA2_384_HMAC_BLOCK_LEN 128
15912 +#define SHA2_512_HMAC_BLOCK_LEN 128
15913 +/* Maximum HMAC block length */
15914 +#define HMAC_MAX_BLOCK_LEN SHA2_512_HMAC_BLOCK_LEN /* Keep this updated */
15915 +#define HMAC_IPAD_VAL 0x36
15916 +#define HMAC_OPAD_VAL 0x5C
15917 +
15918 +/* Encryption algorithm block sizes */
15919 +#define NULL_BLOCK_LEN 1
15920 +#define DES_BLOCK_LEN 8
15921 +#define DES3_BLOCK_LEN 8
15922 +#define BLOWFISH_BLOCK_LEN 8
15923 +#define SKIPJACK_BLOCK_LEN 8
15924 +#define CAST128_BLOCK_LEN 8
15925 +#define RIJNDAEL128_BLOCK_LEN 16
15926 +#define AES_BLOCK_LEN RIJNDAEL128_BLOCK_LEN
15927 +#define CAMELLIA_BLOCK_LEN 16
15928 +#define ARC4_BLOCK_LEN 1
15929 +#define EALG_MAX_BLOCK_LEN AES_BLOCK_LEN /* Keep this updated */
15930 +
15931 +/* Encryption algorithm min and max key sizes */
15932 +#define NULL_MIN_KEY_LEN 0
15933 +#define NULL_MAX_KEY_LEN 0
15934 +#define DES_MIN_KEY_LEN 8
15935 +#define DES_MAX_KEY_LEN 8
15936 +#define DES3_MIN_KEY_LEN 24
15937 +#define DES3_MAX_KEY_LEN 24
15938 +#define BLOWFISH_MIN_KEY_LEN 4
15939 +#define BLOWFISH_MAX_KEY_LEN 56
15940 +#define SKIPJACK_MIN_KEY_LEN 10
15941 +#define SKIPJACK_MAX_KEY_LEN 10
15942 +#define CAST128_MIN_KEY_LEN 5
15943 +#define CAST128_MAX_KEY_LEN 16
15944 +#define RIJNDAEL128_MIN_KEY_LEN 16
15945 +#define RIJNDAEL128_MAX_KEY_LEN 32
15946 +#define AES_MIN_KEY_LEN RIJNDAEL128_MIN_KEY_LEN
15947 +#define AES_MAX_KEY_LEN RIJNDAEL128_MAX_KEY_LEN
15948 +#define CAMELLIA_MIN_KEY_LEN 16
15949 +#define CAMELLIA_MAX_KEY_LEN 32
15950 +#define ARC4_MIN_KEY_LEN 1
15951 +#define ARC4_MAX_KEY_LEN 256
15952 +
15953 +/* Max size of data that can be processed */
15954 +#define CRYPTO_MAX_DATA_LEN 64*1024 - 1
15955 +
15956 +#define CRYPTO_ALGORITHM_MIN 1
15957 +#define CRYPTO_DES_CBC 1
15958 +#define CRYPTO_3DES_CBC 2
15959 +#define CRYPTO_BLF_CBC 3
15960 +#define CRYPTO_CAST_CBC 4
15961 +#define CRYPTO_SKIPJACK_CBC 5
15962 +#define CRYPTO_MD5_HMAC 6
15963 +#define CRYPTO_SHA1_HMAC 7
15964 +#define CRYPTO_RIPEMD160_HMAC 8
15965 +#define CRYPTO_MD5_KPDK 9
15966 +#define CRYPTO_SHA1_KPDK 10
15967 +#define CRYPTO_RIJNDAEL128_CBC 11 /* 128 bit blocksize */
15968 +#define CRYPTO_AES_CBC 11 /* 128 bit blocksize -- the same as above */
15969 +#define CRYPTO_ARC4 12
15970 +#define CRYPTO_MD5 13
15971 +#define CRYPTO_SHA1 14
15972 +#define CRYPTO_NULL_HMAC 15
15973 +#define CRYPTO_NULL_CBC 16
15974 +#define CRYPTO_DEFLATE_COMP 17 /* Deflate compression algorithm */
15975 +#define CRYPTO_SHA2_256_HMAC 18
15976 +#define CRYPTO_SHA2_384_HMAC 19
15977 +#define CRYPTO_SHA2_512_HMAC 20
15978 +#define CRYPTO_CAMELLIA_CBC 21
15979 +#define CRYPTO_SHA2_256 22
15980 +#define CRYPTO_SHA2_384 23
15981 +#define CRYPTO_SHA2_512 24
15982 +#define CRYPTO_RIPEMD160 25
15983 +#define CRYPTO_ALGORITHM_MAX 25 /* Keep updated - see below */
15984 +
15985 +/* Algorithm flags */
15986 +#define CRYPTO_ALG_FLAG_SUPPORTED 0x01 /* Algorithm is supported */
15987 +#define CRYPTO_ALG_FLAG_RNG_ENABLE 0x02 /* Has HW RNG for DH/DSA */
15988 +#define CRYPTO_ALG_FLAG_DSA_SHA 0x04 /* Can do SHA on msg */
15989 +
15990 +/*
15991 + * Crypto driver/device flags. They can set in the crid
15992 + * parameter when creating a session or submitting a key
15993 + * op to affect the device/driver assigned. If neither
15994 + * of these are specified then the crid is assumed to hold
15995 + * the driver id of an existing (and suitable) device that
15996 + * must be used to satisfy the request.
15997 + */
15998 +#define CRYPTO_FLAG_HARDWARE 0x01000000 /* hardware accelerated */
15999 +#define CRYPTO_FLAG_SOFTWARE 0x02000000 /* software implementation */
16000 +
16001 +/* NB: deprecated */
16002 +struct session_op {
16003 + u_int32_t cipher; /* ie. CRYPTO_DES_CBC */
16004 + u_int32_t mac; /* ie. CRYPTO_MD5_HMAC */
16005 +
16006 + u_int32_t keylen; /* cipher key */
16007 + caddr_t key;
16008 + int mackeylen; /* mac key */
16009 + caddr_t mackey;
16010 +
16011 + u_int32_t ses; /* returns: session # */
16012 +};
16013 +
16014 +struct session2_op {
16015 + u_int32_t cipher; /* ie. CRYPTO_DES_CBC */
16016 + u_int32_t mac; /* ie. CRYPTO_MD5_HMAC */
16017 +
16018 + u_int32_t keylen; /* cipher key */
16019 + caddr_t key;
16020 + int mackeylen; /* mac key */
16021 + caddr_t mackey;
16022 +
16023 + u_int32_t ses; /* returns: session # */
16024 + int crid; /* driver id + flags (rw) */
16025 + int pad[4]; /* for future expansion */
16026 +};
16027 +
16028 +struct crypt_op {
16029 + u_int32_t ses;
16030 + u_int16_t op; /* i.e. COP_ENCRYPT */
16031 +#define COP_NONE 0
16032 +#define COP_ENCRYPT 1
16033 +#define COP_DECRYPT 2
16034 + u_int16_t flags;
16035 +#define COP_F_BATCH 0x0008 /* Batch op if possible */
16036 + u_int len;
16037 + caddr_t src, dst; /* become iov[] inside kernel */
16038 + caddr_t mac; /* must be big enough for chosen MAC */
16039 + caddr_t iv;
16040 +};
16041 +
16042 +/*
16043 + * Parameters for looking up a crypto driver/device by
16044 + * device name or by id. The latter are returned for
16045 + * created sessions (crid) and completed key operations.
16046 + */
16047 +struct crypt_find_op {
16048 + int crid; /* driver id + flags */
16049 + char name[32]; /* device/driver name */
16050 +};
16051 +
16052 +/* bignum parameter, in packed bytes, ... */
16053 +struct crparam {
16054 + caddr_t crp_p;
16055 + u_int crp_nbits;
16056 +};
16057 +
16058 +#define CRK_MAXPARAM 8
16059 +
16060 +struct crypt_kop {
16061 + u_int crk_op; /* ie. CRK_MOD_EXP or other */
16062 + u_int crk_status; /* return status */
16063 + u_short crk_iparams; /* # of input parameters */
16064 + u_short crk_oparams; /* # of output parameters */
16065 + u_int crk_crid; /* NB: only used by CIOCKEY2 (rw) */
16066 + struct crparam crk_param[CRK_MAXPARAM];
16067 +};
16068 +#define CRK_ALGORITM_MIN 0
16069 +#define CRK_MOD_EXP 0
16070 +#define CRK_MOD_EXP_CRT 1
16071 +#define CRK_DSA_SIGN 2
16072 +#define CRK_DSA_VERIFY 3
16073 +#define CRK_DH_COMPUTE_KEY 4
16074 +#define CRK_ALGORITHM_MAX 4 /* Keep updated - see below */
16075 +
16076 +#define CRF_MOD_EXP (1 << CRK_MOD_EXP)
16077 +#define CRF_MOD_EXP_CRT (1 << CRK_MOD_EXP_CRT)
16078 +#define CRF_DSA_SIGN (1 << CRK_DSA_SIGN)
16079 +#define CRF_DSA_VERIFY (1 << CRK_DSA_VERIFY)
16080 +#define CRF_DH_COMPUTE_KEY (1 << CRK_DH_COMPUTE_KEY)
16081 +
16082 +/*
16083 + * done against open of /dev/crypto, to get a cloned descriptor.
16084 + * Please use F_SETFD against the cloned descriptor.
16085 + */
16086 +#define CRIOGET _IOWR('c', 100, u_int32_t)
16087 +#define CRIOASYMFEAT CIOCASYMFEAT
16088 +#define CRIOFINDDEV CIOCFINDDEV
16089 +
16090 +/* the following are done against the cloned descriptor */
16091 +#define CIOCGSESSION _IOWR('c', 101, struct session_op)
16092 +#define CIOCFSESSION _IOW('c', 102, u_int32_t)
16093 +#define CIOCCRYPT _IOWR('c', 103, struct crypt_op)
16094 +#define CIOCKEY _IOWR('c', 104, struct crypt_kop)
16095 +#define CIOCASYMFEAT _IOR('c', 105, u_int32_t)
16096 +#define CIOCGSESSION2 _IOWR('c', 106, struct session2_op)
16097 +#define CIOCKEY2 _IOWR('c', 107, struct crypt_kop)
16098 +#define CIOCFINDDEV _IOWR('c', 108, struct crypt_find_op)
16099 +
16100 +struct cryptotstat {
16101 + struct timespec acc; /* total accumulated time */
16102 + struct timespec min; /* min time */
16103 + struct timespec max; /* max time */
16104 + u_int32_t count; /* number of observations */
16105 +};
16106 +
16107 +struct cryptostats {
16108 + u_int32_t cs_ops; /* symmetric crypto ops submitted */
16109 + u_int32_t cs_errs; /* symmetric crypto ops that failed */
16110 + u_int32_t cs_kops; /* asymetric/key ops submitted */
16111 + u_int32_t cs_kerrs; /* asymetric/key ops that failed */
16112 + u_int32_t cs_intrs; /* crypto swi thread activations */
16113 + u_int32_t cs_rets; /* crypto return thread activations */
16114 + u_int32_t cs_blocks; /* symmetric op driver block */
16115 + u_int32_t cs_kblocks; /* symmetric op driver block */
16116 + /*
16117 + * When CRYPTO_TIMING is defined at compile time and the
16118 + * sysctl debug.crypto is set to 1, the crypto system will
16119 + * accumulate statistics about how long it takes to process
16120 + * crypto requests at various points during processing.
16121 + */
16122 + struct cryptotstat cs_invoke; /* crypto_dipsatch -> crypto_invoke */
16123 + struct cryptotstat cs_done; /* crypto_invoke -> crypto_done */
16124 + struct cryptotstat cs_cb; /* crypto_done -> callback */
16125 + struct cryptotstat cs_finis; /* callback -> callback return */
16126 +
16127 + u_int32_t cs_drops; /* crypto ops dropped due to congestion */
16128 +};
16129 +
16130 +#ifdef __KERNEL__
16131 +
16132 +/* Standard initialization structure beginning */
16133 +struct cryptoini {
16134 + int cri_alg; /* Algorithm to use */
16135 + int cri_klen; /* Key length, in bits */
16136 + int cri_mlen; /* Number of bytes we want from the
16137 + entire hash. 0 means all. */
16138 + caddr_t cri_key; /* key to use */
16139 + u_int8_t cri_iv[EALG_MAX_BLOCK_LEN]; /* IV to use */
16140 + struct cryptoini *cri_next;
16141 +};
16142 +
16143 +/* Describe boundaries of a single crypto operation */
16144 +struct cryptodesc {
16145 + int crd_skip; /* How many bytes to ignore from start */
16146 + int crd_len; /* How many bytes to process */
16147 + int crd_inject; /* Where to inject results, if applicable */
16148 + int crd_flags;
16149 +
16150 +#define CRD_F_ENCRYPT 0x01 /* Set when doing encryption */
16151 +#define CRD_F_IV_PRESENT 0x02 /* When encrypting, IV is already in
16152 + place, so don't copy. */
16153 +#define CRD_F_IV_EXPLICIT 0x04 /* IV explicitly provided */
16154 +#define CRD_F_DSA_SHA_NEEDED 0x08 /* Compute SHA-1 of buffer for DSA */
16155 +#define CRD_F_KEY_EXPLICIT 0x10 /* Key explicitly provided */
16156 +#define CRD_F_COMP 0x0f /* Set when doing compression */
16157 +
16158 + struct cryptoini CRD_INI; /* Initialization/context data */
16159 +#define crd_iv CRD_INI.cri_iv
16160 +#define crd_key CRD_INI.cri_key
16161 +#define crd_alg CRD_INI.cri_alg
16162 +#define crd_klen CRD_INI.cri_klen
16163 +
16164 + struct cryptodesc *crd_next;
16165 +};
16166 +
16167 +/* Structure describing complete operation */
16168 +struct cryptop {
16169 + struct list_head crp_next;
16170 + wait_queue_head_t crp_waitq;
16171 +
16172 + u_int64_t crp_sid; /* Session ID */
16173 + int crp_ilen; /* Input data total length */
16174 + int crp_olen; /* Result total length */
16175 +
16176 + int crp_etype; /*
16177 + * Error type (zero means no error).
16178 + * All error codes except EAGAIN
16179 + * indicate possible data corruption (as in,
16180 + * the data have been touched). On all
16181 + * errors, the crp_sid may have changed
16182 + * (reset to a new one), so the caller
16183 + * should always check and use the new
16184 + * value on future requests.
16185 + */
16186 + int crp_flags;
16187 +
16188 +#define CRYPTO_F_SKBUF 0x0001 /* Input/output are skbuf chains */
16189 +#define CRYPTO_F_IOV 0x0002 /* Input/output are uio */
16190 +#define CRYPTO_F_REL 0x0004 /* Must return data in same place */
16191 +#define CRYPTO_F_BATCH 0x0008 /* Batch op if possible */
16192 +#define CRYPTO_F_CBIMM 0x0010 /* Do callback immediately */
16193 +#define CRYPTO_F_DONE 0x0020 /* Operation completed */
16194 +#define CRYPTO_F_CBIFSYNC 0x0040 /* Do CBIMM if op is synchronous */
16195 +
16196 + caddr_t crp_buf; /* Data to be processed */
16197 + caddr_t crp_opaque; /* Opaque pointer, passed along */
16198 + struct cryptodesc *crp_desc; /* Linked list of processing descriptors */
16199 +
16200 + int (*crp_callback)(struct cryptop *); /* Callback function */
16201 +};
16202 +
16203 +#define CRYPTO_BUF_CONTIG 0x0
16204 +#define CRYPTO_BUF_IOV 0x1
16205 +#define CRYPTO_BUF_SKBUF 0x2
16206 +
16207 +#define CRYPTO_OP_DECRYPT 0x0
16208 +#define CRYPTO_OP_ENCRYPT 0x1
16209 +
16210 +/*
16211 + * Hints passed to process methods.
16212 + */
16213 +#define CRYPTO_HINT_MORE 0x1 /* more ops coming shortly */
16214 +
16215 +struct cryptkop {
16216 + struct list_head krp_next;
16217 + wait_queue_head_t krp_waitq;
16218 +
16219 + int krp_flags;
16220 +#define CRYPTO_KF_DONE 0x0001 /* Operation completed */
16221 +#define CRYPTO_KF_CBIMM 0x0002 /* Do callback immediately */
16222 +
16223 + u_int krp_op; /* ie. CRK_MOD_EXP or other */
16224 + u_int krp_status; /* return status */
16225 + u_short krp_iparams; /* # of input parameters */
16226 + u_short krp_oparams; /* # of output parameters */
16227 + u_int krp_crid; /* desired device, etc. */
16228 + u_int32_t krp_hid;
16229 + struct crparam krp_param[CRK_MAXPARAM]; /* kvm */
16230 + int (*krp_callback)(struct cryptkop *);
16231 +};
16232 +
16233 +#include <ocf-compat.h>
16234 +
16235 +/*
16236 + * Session ids are 64 bits. The lower 32 bits contain a "local id" which
16237 + * is a driver-private session identifier. The upper 32 bits contain a
16238 + * "hardware id" used by the core crypto code to identify the driver and
16239 + * a copy of the driver's capabilities that can be used by client code to
16240 + * optimize operation.
16241 + */
16242 +#define CRYPTO_SESID2HID(_sid) (((_sid) >> 32) & 0x00ffffff)
16243 +#define CRYPTO_SESID2CAPS(_sid) (((_sid) >> 32) & 0xff000000)
16244 +#define CRYPTO_SESID2LID(_sid) (((u_int32_t) (_sid)) & 0xffffffff)
16245 +
16246 +extern int crypto_newsession(u_int64_t *sid, struct cryptoini *cri, int hard);
16247 +extern int crypto_freesession(u_int64_t sid);
16248 +#define CRYPTOCAP_F_HARDWARE CRYPTO_FLAG_HARDWARE
16249 +#define CRYPTOCAP_F_SOFTWARE CRYPTO_FLAG_SOFTWARE
16250 +#define CRYPTOCAP_F_SYNC 0x04000000 /* operates synchronously */
16251 +extern int32_t crypto_get_driverid(device_t dev, int flags);
16252 +extern int crypto_find_driver(const char *);
16253 +extern device_t crypto_find_device_byhid(int hid);
16254 +extern int crypto_getcaps(int hid);
16255 +extern int crypto_register(u_int32_t driverid, int alg, u_int16_t maxoplen,
16256 + u_int32_t flags);
16257 +extern int crypto_kregister(u_int32_t, int, u_int32_t);
16258 +extern int crypto_unregister(u_int32_t driverid, int alg);
16259 +extern int crypto_unregister_all(u_int32_t driverid);
16260 +extern int crypto_dispatch(struct cryptop *crp);
16261 +extern int crypto_kdispatch(struct cryptkop *);
16262 +#define CRYPTO_SYMQ 0x1
16263 +#define CRYPTO_ASYMQ 0x2
16264 +extern int crypto_unblock(u_int32_t, int);
16265 +extern void crypto_done(struct cryptop *crp);
16266 +extern void crypto_kdone(struct cryptkop *);
16267 +extern int crypto_getfeat(int *);
16268 +
16269 +extern void crypto_freereq(struct cryptop *crp);
16270 +extern struct cryptop *crypto_getreq(int num);
16271 +
16272 +extern int crypto_usercrypto; /* userland may do crypto requests */
16273 +extern int crypto_userasymcrypto; /* userland may do asym crypto reqs */
16274 +extern int crypto_devallowsoft; /* only use hardware crypto */
16275 +
16276 +/*
16277 + * random number support, crypto_unregister_all will unregister
16278 + */
16279 +extern int crypto_rregister(u_int32_t driverid,
16280 + int (*read_random)(void *arg, u_int32_t *buf, int len), void *arg);
16281 +extern int crypto_runregister_all(u_int32_t driverid);
16282 +
16283 +/*
16284 + * Crypto-related utility routines used mainly by drivers.
16285 + *
16286 + * XXX these don't really belong here; but for now they're
16287 + * kept apart from the rest of the system.
16288 + */
16289 +struct uio;
16290 +extern void cuio_copydata(struct uio* uio, int off, int len, caddr_t cp);
16291 +extern void cuio_copyback(struct uio* uio, int off, int len, caddr_t cp);
16292 +extern struct iovec *cuio_getptr(struct uio *uio, int loc, int *off);
16293 +
16294 +extern void crypto_copyback(int flags, caddr_t buf, int off, int size,
16295 + caddr_t in);
16296 +extern void crypto_copydata(int flags, caddr_t buf, int off, int size,
16297 + caddr_t out);
16298 +extern int crypto_apply(int flags, caddr_t buf, int off, int len,
16299 + int (*f)(void *, void *, u_int), void *arg);
16300 +
16301 +#endif /* __KERNEL__ */
16302 +#endif /* _CRYPTO_CRYPTO_H_ */
16303 --- /dev/null
16304 +++ b/crypto/ocf/ocfnull/ocfnull.c
16305 @@ -0,0 +1,203 @@
16306 +/*
16307 + * An OCF module for determining the cost of crypto versus the cost of
16308 + * IPSec processing outside of OCF. This modules gives us the effect of
16309 + * zero cost encryption, of course you will need to run it at both ends
16310 + * since it does no crypto at all.
16311 + *
16312 + * Written by David McCullough <david_mccullough@securecomputing.com>
16313 + * Copyright (C) 2006-2007 David McCullough
16314 + *
16315 + * LICENSE TERMS
16316 + *
16317 + * The free distribution and use of this software in both source and binary
16318 + * form is allowed (with or without changes) provided that:
16319 + *
16320 + * 1. distributions of this source code include the above copyright
16321 + * notice, this list of conditions and the following disclaimer;
16322 + *
16323 + * 2. distributions in binary form include the above copyright
16324 + * notice, this list of conditions and the following disclaimer
16325 + * in the documentation and/or other associated materials;
16326 + *
16327 + * 3. the copyright holder's name is not used to endorse products
16328 + * built using this software without specific written permission.
16329 + *
16330 + * ALTERNATIVELY, provided that this notice is retained in full, this product
16331 + * may be distributed under the terms of the GNU General Public License (GPL),
16332 + * in which case the provisions of the GPL apply INSTEAD OF those given above.
16333 + *
16334 + * DISCLAIMER
16335 + *
16336 + * This software is provided 'as is' with no explicit or implied warranties
16337 + * in respect of its properties, including, but not limited to, correctness
16338 + * and/or fitness for purpose.
16339 + */
16340 +
16341 +#ifndef AUTOCONF_INCLUDED
16342 +#include <linux/config.h>
16343 +#endif
16344 +#include <linux/module.h>
16345 +#include <linux/init.h>
16346 +#include <linux/list.h>
16347 +#include <linux/slab.h>
16348 +#include <linux/sched.h>
16349 +#include <linux/wait.h>
16350 +#include <linux/crypto.h>
16351 +#include <linux/interrupt.h>
16352 +
16353 +#include <cryptodev.h>
16354 +#include <uio.h>
16355 +
16356 +static int32_t null_id = -1;
16357 +static u_int32_t null_sesnum = 0;
16358 +
16359 +static int null_process(device_t, struct cryptop *, int);
16360 +static int null_newsession(device_t, u_int32_t *, struct cryptoini *);
16361 +static int null_freesession(device_t, u_int64_t);
16362 +
16363 +#define debug ocfnull_debug
16364 +int ocfnull_debug = 0;
16365 +module_param(ocfnull_debug, int, 0644);
16366 +MODULE_PARM_DESC(ocfnull_debug, "Enable debug");
16367 +
16368 +/*
16369 + * dummy device structure
16370 + */
16371 +
16372 +static struct {
16373 + softc_device_decl sc_dev;
16374 +} nulldev;
16375 +
16376 +static device_method_t null_methods = {
16377 + /* crypto device methods */
16378 + DEVMETHOD(cryptodev_newsession, null_newsession),
16379 + DEVMETHOD(cryptodev_freesession,null_freesession),
16380 + DEVMETHOD(cryptodev_process, null_process),
16381 +};
16382 +
16383 +/*
16384 + * Generate a new software session.
16385 + */
16386 +static int
16387 +null_newsession(device_t arg, u_int32_t *sid, struct cryptoini *cri)
16388 +{
16389 + dprintk("%s()\n", __FUNCTION__);
16390 + if (sid == NULL || cri == NULL) {
16391 + dprintk("%s,%d - EINVAL\n", __FILE__, __LINE__);
16392 + return EINVAL;
16393 + }
16394 +
16395 + if (null_sesnum == 0)
16396 + null_sesnum++;
16397 + *sid = null_sesnum++;
16398 + return 0;
16399 +}
16400 +
16401 +
16402 +/*
16403 + * Free a session.
16404 + */
16405 +static int
16406 +null_freesession(device_t arg, u_int64_t tid)
16407 +{
16408 + u_int32_t sid = CRYPTO_SESID2LID(tid);
16409 +
16410 + dprintk("%s()\n", __FUNCTION__);
16411 + if (sid > null_sesnum) {
16412 + dprintk("%s,%d: EINVAL\n", __FILE__, __LINE__);
16413 + return EINVAL;
16414 + }
16415 +
16416 + /* Silently accept and return */
16417 + if (sid == 0)
16418 + return 0;
16419 + return 0;
16420 +}
16421 +
16422 +
16423 +/*
16424 + * Process a request.
16425 + */
16426 +static int
16427 +null_process(device_t arg, struct cryptop *crp, int hint)
16428 +{
16429 + unsigned int lid;
16430 +
16431 + dprintk("%s()\n", __FUNCTION__);
16432 +
16433 + /* Sanity check */
16434 + if (crp == NULL) {
16435 + dprintk("%s,%d: EINVAL\n", __FILE__, __LINE__);
16436 + return EINVAL;
16437 + }
16438 +
16439 + crp->crp_etype = 0;
16440 +
16441 + if (crp->crp_desc == NULL || crp->crp_buf == NULL) {
16442 + dprintk("%s,%d: EINVAL\n", __FILE__, __LINE__);
16443 + crp->crp_etype = EINVAL;
16444 + goto done;
16445 + }
16446 +
16447 + /*
16448 + * find the session we are using
16449 + */
16450 +
16451 + lid = crp->crp_sid & 0xffffffff;
16452 + if (lid >= null_sesnum || lid == 0) {
16453 + crp->crp_etype = ENOENT;
16454 + dprintk("%s,%d: ENOENT\n", __FILE__, __LINE__);
16455 + goto done;
16456 + }
16457 +
16458 +done:
16459 + crypto_done(crp);
16460 + return 0;
16461 +}
16462 +
16463 +
16464 +/*
16465 + * our driver startup and shutdown routines
16466 + */
16467 +
16468 +static int
16469 +null_init(void)
16470 +{
16471 + dprintk("%s(%p)\n", __FUNCTION__, null_init);
16472 +
16473 + memset(&nulldev, 0, sizeof(nulldev));
16474 + softc_device_init(&nulldev, "ocfnull", 0, null_methods);
16475 +
16476 + null_id = crypto_get_driverid(softc_get_device(&nulldev),
16477 + CRYPTOCAP_F_HARDWARE);
16478 + if (null_id < 0)
16479 + panic("ocfnull: crypto device cannot initialize!");
16480 +
16481 +#define REGISTER(alg) \
16482 + crypto_register(null_id,alg,0,0)
16483 + REGISTER(CRYPTO_DES_CBC);
16484 + REGISTER(CRYPTO_3DES_CBC);
16485 + REGISTER(CRYPTO_RIJNDAEL128_CBC);
16486 + REGISTER(CRYPTO_MD5);
16487 + REGISTER(CRYPTO_SHA1);
16488 + REGISTER(CRYPTO_MD5_HMAC);
16489 + REGISTER(CRYPTO_SHA1_HMAC);
16490 +#undef REGISTER
16491 +
16492 + return 0;
16493 +}
16494 +
16495 +static void
16496 +null_exit(void)
16497 +{
16498 + dprintk("%s()\n", __FUNCTION__);
16499 + crypto_unregister_all(null_id);
16500 + null_id = -1;
16501 +}
16502 +
16503 +module_init(null_init);
16504 +module_exit(null_exit);
16505 +
16506 +MODULE_LICENSE("Dual BSD/GPL");
16507 +MODULE_AUTHOR("David McCullough <david_mccullough@securecomputing.com>");
16508 +MODULE_DESCRIPTION("ocfnull - claims a lot but does nothing");
16509 --- /dev/null
16510 +++ b/crypto/ocf/cryptosoft.c
16511 @@ -0,0 +1,898 @@
16512 +/*
16513 + * An OCF module that uses the linux kernel cryptoapi, based on the
16514 + * original cryptosoft for BSD by Angelos D. Keromytis (angelos@cis.upenn.edu)
16515 + * but is mostly unrecognisable,
16516 + *
16517 + * Written by David McCullough <david_mccullough@securecomputing.com>
16518 + * Copyright (C) 2004-2007 David McCullough
16519 + * Copyright (C) 2004-2005 Intel Corporation.
16520 + *
16521 + * LICENSE TERMS
16522 + *
16523 + * The free distribution and use of this software in both source and binary
16524 + * form is allowed (with or without changes) provided that:
16525 + *
16526 + * 1. distributions of this source code include the above copyright
16527 + * notice, this list of conditions and the following disclaimer;
16528 + *
16529 + * 2. distributions in binary form include the above copyright
16530 + * notice, this list of conditions and the following disclaimer
16531 + * in the documentation and/or other associated materials;
16532 + *
16533 + * 3. the copyright holder's name is not used to endorse products
16534 + * built using this software without specific written permission.
16535 + *
16536 + * ALTERNATIVELY, provided that this notice is retained in full, this product
16537 + * may be distributed under the terms of the GNU General Public License (GPL),
16538 + * in which case the provisions of the GPL apply INSTEAD OF those given above.
16539 + *
16540 + * DISCLAIMER
16541 + *
16542 + * This software is provided 'as is' with no explicit or implied warranties
16543 + * in respect of its properties, including, but not limited to, correctness
16544 + * and/or fitness for purpose.
16545 + * ---------------------------------------------------------------------------
16546 + */
16547 +
16548 +#ifndef AUTOCONF_INCLUDED
16549 +#include <linux/config.h>
16550 +#endif
16551 +#include <linux/module.h>
16552 +#include <linux/init.h>
16553 +#include <linux/list.h>
16554 +#include <linux/slab.h>
16555 +#include <linux/sched.h>
16556 +#include <linux/wait.h>
16557 +#include <linux/crypto.h>
16558 +#include <linux/mm.h>
16559 +#include <linux/skbuff.h>
16560 +#include <linux/random.h>
16561 +#include <asm/scatterlist.h>
16562 +
16563 +#include <cryptodev.h>
16564 +#include <uio.h>
16565 +
16566 +struct {
16567 + softc_device_decl sc_dev;
16568 +} swcr_softc;
16569 +
16570 +#define offset_in_page(p) ((unsigned long)(p) & ~PAGE_MASK)
16571 +
16572 +/* Software session entry */
16573 +
16574 +#define SW_TYPE_CIPHER 0
16575 +#define SW_TYPE_HMAC 1
16576 +#define SW_TYPE_AUTH2 2
16577 +#define SW_TYPE_HASH 3
16578 +#define SW_TYPE_COMP 4
16579 +#define SW_TYPE_BLKCIPHER 5
16580 +
16581 +struct swcr_data {
16582 + int sw_type;
16583 + int sw_alg;
16584 + struct crypto_tfm *sw_tfm;
16585 + union {
16586 + struct {
16587 + char *sw_key;
16588 + int sw_klen;
16589 + int sw_mlen;
16590 + } hmac;
16591 + void *sw_comp_buf;
16592 + } u;
16593 + struct swcr_data *sw_next;
16594 +};
16595 +
16596 +#ifndef CRYPTO_TFM_MODE_CBC
16597 +/*
16598 + * As of linux-2.6.21 this is no longer defined, and presumably no longer
16599 + * needed to be passed into the crypto core code.
16600 + */
16601 +#define CRYPTO_TFM_MODE_CBC 0
16602 +#define CRYPTO_TFM_MODE_ECB 0
16603 +#endif
16604 +
16605 +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,19)
16606 + /*
16607 + * Linux 2.6.19 introduced a new Crypto API, setup macro's to convert new
16608 + * API into old API.
16609 + */
16610 +
16611 + /* Symmetric/Block Cipher */
16612 + struct blkcipher_desc
16613 + {
16614 + struct crypto_tfm *tfm;
16615 + void *info;
16616 + };
16617 + #define ecb(X) #X
16618 + #define cbc(X) #X
16619 + #define crypto_has_blkcipher(X, Y, Z) crypto_alg_available(X, 0)
16620 + #define crypto_blkcipher_cast(X) X
16621 + #define crypto_blkcipher_tfm(X) X
16622 + #define crypto_alloc_blkcipher(X, Y, Z) crypto_alloc_tfm(X, mode)
16623 + #define crypto_blkcipher_ivsize(X) crypto_tfm_alg_ivsize(X)
16624 + #define crypto_blkcipher_blocksize(X) crypto_tfm_alg_blocksize(X)
16625 + #define crypto_blkcipher_setkey(X, Y, Z) crypto_cipher_setkey(X, Y, Z)
16626 + #define crypto_blkcipher_encrypt_iv(W, X, Y, Z) \
16627 + crypto_cipher_encrypt_iv((W)->tfm, X, Y, Z, (u8 *)((W)->info))
16628 + #define crypto_blkcipher_decrypt_iv(W, X, Y, Z) \
16629 + crypto_cipher_decrypt_iv((W)->tfm, X, Y, Z, (u8 *)((W)->info))
16630 +
16631 + /* Hash/HMAC/Digest */
16632 + struct hash_desc
16633 + {
16634 + struct crypto_tfm *tfm;
16635 + };
16636 + #define hmac(X) #X
16637 + #define crypto_has_hash(X, Y, Z) crypto_alg_available(X, 0)
16638 + #define crypto_hash_cast(X) X
16639 + #define crypto_hash_tfm(X) X
16640 + #define crypto_alloc_hash(X, Y, Z) crypto_alloc_tfm(X, mode)
16641 + #define crypto_hash_digestsize(X) crypto_tfm_alg_digestsize(X)
16642 + #define crypto_hash_digest(W, X, Y, Z) \
16643 + crypto_digest_digest((W)->tfm, X, sg_num, Z)
16644 +
16645 + /* Asymmetric Cipher */
16646 + #define crypto_has_cipher(X, Y, Z) crypto_alg_available(X, 0)
16647 +
16648 + /* Compression */
16649 + #define crypto_has_comp(X, Y, Z) crypto_alg_available(X, 0)
16650 + #define crypto_comp_tfm(X) X
16651 + #define crypto_comp_cast(X) X
16652 + #define crypto_alloc_comp(X, Y, Z) crypto_alloc_tfm(X, mode)
16653 +#else
16654 + #define ecb(X) "ecb(" #X ")"
16655 + #define cbc(X) "cbc(" #X ")"
16656 + #define hmac(X) "hmac(" #X ")"
16657 +#endif /* if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,19) */
16658 +
16659 +struct crypto_details
16660 +{
16661 + char *alg_name;
16662 + int mode;
16663 + int sw_type;
16664 +};
16665 +
16666 +/*
16667 + * This needs to be kept updated with CRYPTO_xxx list (cryptodev.h).
16668 + * If the Algorithm is not supported, then insert a {NULL, 0, 0} entry.
16669 + *
16670 + * IMPORTANT: The index to the array IS CRYPTO_xxx.
16671 + */
16672 +static struct crypto_details crypto_details[CRYPTO_ALGORITHM_MAX + 1] = {
16673 + { NULL, 0, 0 },
16674 + /* CRYPTO_xxx index starts at 1 */
16675 + { cbc(des), CRYPTO_TFM_MODE_CBC, SW_TYPE_BLKCIPHER },
16676 + { cbc(des3_ede), CRYPTO_TFM_MODE_CBC, SW_TYPE_BLKCIPHER },
16677 + { cbc(blowfish), CRYPTO_TFM_MODE_CBC, SW_TYPE_BLKCIPHER },
16678 + { cbc(cast5), CRYPTO_TFM_MODE_CBC, SW_TYPE_BLKCIPHER },
16679 + { cbc(skipjack), CRYPTO_TFM_MODE_CBC, SW_TYPE_BLKCIPHER },
16680 + { hmac(md5), 0, SW_TYPE_HMAC },
16681 + { hmac(sha1), 0, SW_TYPE_HMAC },
16682 + { hmac(ripemd160), 0, SW_TYPE_HMAC },
16683 + { "md5-kpdk??", 0, SW_TYPE_HASH },
16684 + { "sha1-kpdk??", 0, SW_TYPE_HASH },
16685 + { cbc(aes), CRYPTO_TFM_MODE_CBC, SW_TYPE_BLKCIPHER },
16686 + { ecb(arc4), CRYPTO_TFM_MODE_ECB, SW_TYPE_BLKCIPHER },
16687 + { "md5", 0, SW_TYPE_HASH },
16688 + { "sha1", 0, SW_TYPE_HASH },
16689 + { hmac(digest_null), 0, SW_TYPE_HMAC },
16690 + { cbc(cipher_null), CRYPTO_TFM_MODE_CBC, SW_TYPE_BLKCIPHER },
16691 + { "deflate", 0, SW_TYPE_COMP },
16692 + { hmac(sha256), 0, SW_TYPE_HMAC },
16693 + { hmac(sha384), 0, SW_TYPE_HMAC },
16694 + { hmac(sha512), 0, SW_TYPE_HMAC },
16695 + { cbc(camellia), CRYPTO_TFM_MODE_CBC, SW_TYPE_BLKCIPHER },
16696 + { "sha256", 0, SW_TYPE_HASH },
16697 + { "sha384", 0, SW_TYPE_HASH },
16698 + { "sha512", 0, SW_TYPE_HASH },
16699 + { "ripemd160", 0, SW_TYPE_HASH },
16700 +};
16701 +
16702 +int32_t swcr_id = -1;
16703 +module_param(swcr_id, int, 0444);
16704 +MODULE_PARM_DESC(swcr_id, "Read-Only OCF ID for cryptosoft driver");
16705 +
16706 +int swcr_fail_if_compression_grows = 1;
16707 +module_param(swcr_fail_if_compression_grows, int, 0644);
16708 +MODULE_PARM_DESC(swcr_fail_if_compression_grows,
16709 + "Treat compression that results in more data as a failure");
16710 +
16711 +static struct swcr_data **swcr_sessions = NULL;
16712 +static u_int32_t swcr_sesnum = 0;
16713 +
16714 +static int swcr_process(device_t, struct cryptop *, int);
16715 +static int swcr_newsession(device_t, u_int32_t *, struct cryptoini *);
16716 +static int swcr_freesession(device_t, u_int64_t);
16717 +
16718 +static device_method_t swcr_methods = {
16719 + /* crypto device methods */
16720 + DEVMETHOD(cryptodev_newsession, swcr_newsession),
16721 + DEVMETHOD(cryptodev_freesession,swcr_freesession),
16722 + DEVMETHOD(cryptodev_process, swcr_process),
16723 +};
16724 +
16725 +#define debug swcr_debug
16726 +int swcr_debug = 0;
16727 +module_param(swcr_debug, int, 0644);
16728 +MODULE_PARM_DESC(swcr_debug, "Enable debug");
16729 +
16730 +/*
16731 + * Generate a new software session.
16732 + */
16733 +static int
16734 +swcr_newsession(device_t dev, u_int32_t *sid, struct cryptoini *cri)
16735 +{
16736 + struct swcr_data **swd;
16737 + u_int32_t i;
16738 + int error;
16739 + char *algo;
16740 + int mode, sw_type;
16741 +
16742 + dprintk("%s()\n", __FUNCTION__);
16743 + if (sid == NULL || cri == NULL) {
16744 + dprintk("%s,%d - EINVAL\n", __FILE__, __LINE__);
16745 + return EINVAL;
16746 + }
16747 +
16748 + if (swcr_sessions) {
16749 + for (i = 1; i < swcr_sesnum; i++)
16750 + if (swcr_sessions[i] == NULL)
16751 + break;
16752 + } else
16753 + i = 1; /* NB: to silence compiler warning */
16754 +
16755 + if (swcr_sessions == NULL || i == swcr_sesnum) {
16756 + if (swcr_sessions == NULL) {
16757 + i = 1; /* We leave swcr_sessions[0] empty */
16758 + swcr_sesnum = CRYPTO_SW_SESSIONS;
16759 + } else
16760 + swcr_sesnum *= 2;
16761 +
16762 + swd = kmalloc(swcr_sesnum * sizeof(struct swcr_data *), SLAB_ATOMIC);
16763 + if (swd == NULL) {
16764 + /* Reset session number */
16765 + if (swcr_sesnum == CRYPTO_SW_SESSIONS)
16766 + swcr_sesnum = 0;
16767 + else
16768 + swcr_sesnum /= 2;
16769 + dprintk("%s,%d: ENOBUFS\n", __FILE__, __LINE__);
16770 + return ENOBUFS;
16771 + }
16772 + memset(swd, 0, swcr_sesnum * sizeof(struct swcr_data *));
16773 +
16774 + /* Copy existing sessions */
16775 + if (swcr_sessions) {
16776 + memcpy(swd, swcr_sessions,
16777 + (swcr_sesnum / 2) * sizeof(struct swcr_data *));
16778 + kfree(swcr_sessions);
16779 + }
16780 +
16781 + swcr_sessions = swd;
16782 + }
16783 +
16784 + swd = &swcr_sessions[i];
16785 + *sid = i;
16786 +
16787 + while (cri) {
16788 + *swd = (struct swcr_data *) kmalloc(sizeof(struct swcr_data),
16789 + SLAB_ATOMIC);
16790 + if (*swd == NULL) {
16791 + swcr_freesession(NULL, i);
16792 + dprintk("%s,%d: ENOBUFS\n", __FILE__, __LINE__);
16793 + return ENOBUFS;
16794 + }
16795 + memset(*swd, 0, sizeof(struct swcr_data));
16796 +
16797 + if (cri->cri_alg > CRYPTO_ALGORITHM_MAX) {
16798 + printk("cryptosoft: Unknown algorithm 0x%x\n", cri->cri_alg);
16799 + swcr_freesession(NULL, i);
16800 + return EINVAL;
16801 + }
16802 +
16803 + algo = crypto_details[cri->cri_alg].alg_name;
16804 + if (!algo || !*algo) {
16805 + printk("cryptosoft: Unsupported algorithm 0x%x\n", cri->cri_alg);
16806 + swcr_freesession(NULL, i);
16807 + return EINVAL;
16808 + }
16809 +
16810 + mode = crypto_details[cri->cri_alg].mode;
16811 + sw_type = crypto_details[cri->cri_alg].sw_type;
16812 +
16813 + /* Algorithm specific configuration */
16814 + switch (cri->cri_alg) {
16815 + case CRYPTO_NULL_CBC:
16816 + cri->cri_klen = 0; /* make it work with crypto API */
16817 + break;
16818 + default:
16819 + break;
16820 + }
16821 +
16822 + if (sw_type == SW_TYPE_BLKCIPHER) {
16823 + dprintk("%s crypto_alloc_blkcipher(%s, 0x%x)\n", __FUNCTION__,
16824 + algo, mode);
16825 +
16826 + (*swd)->sw_tfm = crypto_blkcipher_tfm(
16827 + crypto_alloc_blkcipher(algo, 0,
16828 + CRYPTO_ALG_ASYNC));
16829 + if (!(*swd)->sw_tfm) {
16830 + dprintk("cryptosoft: crypto_alloc_blkcipher failed(%s,0x%x)\n",
16831 + algo,mode);
16832 + swcr_freesession(NULL, i);
16833 + return EINVAL;
16834 + }
16835 +
16836 + if (debug) {
16837 + dprintk("%s key:cri->cri_klen=%d,(cri->cri_klen + 7)/8=%d",
16838 + __FUNCTION__,cri->cri_klen,(cri->cri_klen + 7)/8);
16839 + for (i = 0; i < (cri->cri_klen + 7) / 8; i++)
16840 + {
16841 + dprintk("%s0x%x", (i % 8) ? " " : "\n ",cri->cri_key[i]);
16842 + }
16843 + dprintk("\n");
16844 + }
16845 + error = crypto_blkcipher_setkey(
16846 + crypto_blkcipher_cast((*swd)->sw_tfm), cri->cri_key,
16847 + (cri->cri_klen + 7) / 8);
16848 + if (error) {
16849 + printk("cryptosoft: setkey failed %d (crt_flags=0x%x)\n", error,
16850 + (*swd)->sw_tfm->crt_flags);
16851 + swcr_freesession(NULL, i);
16852 + return error;
16853 + }
16854 + } else if (sw_type == SW_TYPE_HMAC || sw_type == SW_TYPE_HASH) {
16855 + dprintk("%s crypto_alloc_hash(%s, 0x%x)\n", __FUNCTION__,
16856 + algo, mode);
16857 +
16858 + (*swd)->sw_tfm = crypto_hash_tfm(
16859 + crypto_alloc_hash(algo, 0, CRYPTO_ALG_ASYNC));
16860 +
16861 + if (!(*swd)->sw_tfm) {
16862 + dprintk("cryptosoft: crypto_alloc_hash failed(%s,0x%x)\n",
16863 + algo, mode);
16864 + swcr_freesession(NULL, i);
16865 + return EINVAL;
16866 + }
16867 +
16868 + (*swd)->u.hmac.sw_klen = (cri->cri_klen + 7) / 8;
16869 + (*swd)->u.hmac.sw_key = (char *)kmalloc((*swd)->u.hmac.sw_klen,
16870 + SLAB_ATOMIC);
16871 + if ((*swd)->u.hmac.sw_key == NULL) {
16872 + swcr_freesession(NULL, i);
16873 + dprintk("%s,%d: ENOBUFS\n", __FILE__, __LINE__);
16874 + return ENOBUFS;
16875 + }
16876 + memcpy((*swd)->u.hmac.sw_key, cri->cri_key, (*swd)->u.hmac.sw_klen);
16877 + if (cri->cri_mlen) {
16878 + (*swd)->u.hmac.sw_mlen = cri->cri_mlen;
16879 + } else {
16880 + (*swd)->u.hmac.sw_mlen =
16881 + crypto_hash_digestsize(
16882 + crypto_hash_cast((*swd)->sw_tfm));
16883 + }
16884 + } else if (sw_type == SW_TYPE_COMP) {
16885 + (*swd)->sw_tfm = crypto_comp_tfm(
16886 + crypto_alloc_comp(algo, 0, CRYPTO_ALG_ASYNC));
16887 + if (!(*swd)->sw_tfm) {
16888 + dprintk("cryptosoft: crypto_alloc_comp failed(%s,0x%x)\n",
16889 + algo, mode);
16890 + swcr_freesession(NULL, i);
16891 + return EINVAL;
16892 + }
16893 + (*swd)->u.sw_comp_buf = kmalloc(CRYPTO_MAX_DATA_LEN, SLAB_ATOMIC);
16894 + if ((*swd)->u.sw_comp_buf == NULL) {
16895 + swcr_freesession(NULL, i);
16896 + dprintk("%s,%d: ENOBUFS\n", __FILE__, __LINE__);
16897 + return ENOBUFS;
16898 + }
16899 + } else {
16900 + printk("cryptosoft: Unhandled sw_type %d\n", sw_type);
16901 + swcr_freesession(NULL, i);
16902 + return EINVAL;
16903 + }
16904 +
16905 + (*swd)->sw_alg = cri->cri_alg;
16906 + (*swd)->sw_type = sw_type;
16907 +
16908 + cri = cri->cri_next;
16909 + swd = &((*swd)->sw_next);
16910 + }
16911 + return 0;
16912 +}
16913 +
16914 +/*
16915 + * Free a session.
16916 + */
16917 +static int
16918 +swcr_freesession(device_t dev, u_int64_t tid)
16919 +{
16920 + struct swcr_data *swd;
16921 + u_int32_t sid = CRYPTO_SESID2LID(tid);
16922 +
16923 + dprintk("%s()\n", __FUNCTION__);
16924 + if (sid > swcr_sesnum || swcr_sessions == NULL ||
16925 + swcr_sessions[sid] == NULL) {
16926 + dprintk("%s,%d: EINVAL\n", __FILE__, __LINE__);
16927 + return(EINVAL);
16928 + }
16929 +
16930 + /* Silently accept and return */
16931 + if (sid == 0)
16932 + return(0);
16933 +
16934 + while ((swd = swcr_sessions[sid]) != NULL) {
16935 + swcr_sessions[sid] = swd->sw_next;
16936 + if (swd->sw_tfm)
16937 + crypto_free_tfm(swd->sw_tfm);
16938 + if (swd->sw_type == SW_TYPE_COMP) {
16939 + if (swd->u.sw_comp_buf)
16940 + kfree(swd->u.sw_comp_buf);
16941 + } else {
16942 + if (swd->u.hmac.sw_key)
16943 + kfree(swd->u.hmac.sw_key);
16944 + }
16945 + kfree(swd);
16946 + }
16947 + return 0;
16948 +}
16949 +
16950 +/*
16951 + * Process a software request.
16952 + */
16953 +static int
16954 +swcr_process(device_t dev, struct cryptop *crp, int hint)
16955 +{
16956 + struct cryptodesc *crd;
16957 + struct swcr_data *sw;
16958 + u_int32_t lid;
16959 +#define SCATTERLIST_MAX 16
16960 + struct scatterlist sg[SCATTERLIST_MAX];
16961 + int sg_num, sg_len, skip;
16962 + struct sk_buff *skb = NULL;
16963 + struct uio *uiop = NULL;
16964 +
16965 + dprintk("%s()\n", __FUNCTION__);
16966 + /* Sanity check */
16967 + if (crp == NULL) {
16968 + dprintk("%s,%d: EINVAL\n", __FILE__, __LINE__);
16969 + return EINVAL;
16970 + }
16971 +
16972 + crp->crp_etype = 0;
16973 +
16974 + if (crp->crp_desc == NULL || crp->crp_buf == NULL) {
16975 + dprintk("%s,%d: EINVAL\n", __FILE__, __LINE__);
16976 + crp->crp_etype = EINVAL;
16977 + goto done;
16978 + }
16979 +
16980 + lid = crp->crp_sid & 0xffffffff;
16981 + if (lid >= swcr_sesnum || lid == 0 || swcr_sessions == NULL ||
16982 + swcr_sessions[lid] == NULL) {
16983 + crp->crp_etype = ENOENT;
16984 + dprintk("%s,%d: ENOENT\n", __FILE__, __LINE__);
16985 + goto done;
16986 + }
16987 +
16988 + /*
16989 + * do some error checking outside of the loop for SKB and IOV processing
16990 + * this leaves us with valid skb or uiop pointers for later
16991 + */
16992 + if (crp->crp_flags & CRYPTO_F_SKBUF) {
16993 + skb = (struct sk_buff *) crp->crp_buf;
16994 + if (skb_shinfo(skb)->nr_frags >= SCATTERLIST_MAX) {
16995 + printk("%s,%d: %d nr_frags > SCATTERLIST_MAX", __FILE__, __LINE__,
16996 + skb_shinfo(skb)->nr_frags);
16997 + goto done;
16998 + }
16999 + } else if (crp->crp_flags & CRYPTO_F_IOV) {
17000 + uiop = (struct uio *) crp->crp_buf;
17001 + if (uiop->uio_iovcnt > SCATTERLIST_MAX) {
17002 + printk("%s,%d: %d uio_iovcnt > SCATTERLIST_MAX", __FILE__, __LINE__,
17003 + uiop->uio_iovcnt);
17004 + goto done;
17005 + }
17006 + }
17007 +
17008 + /* Go through crypto descriptors, processing as we go */
17009 + for (crd = crp->crp_desc; crd; crd = crd->crd_next) {
17010 + /*
17011 + * Find the crypto context.
17012 + *
17013 + * XXX Note that the logic here prevents us from having
17014 + * XXX the same algorithm multiple times in a session
17015 + * XXX (or rather, we can but it won't give us the right
17016 + * XXX results). To do that, we'd need some way of differentiating
17017 + * XXX between the various instances of an algorithm (so we can
17018 + * XXX locate the correct crypto context).
17019 + */
17020 + for (sw = swcr_sessions[lid]; sw && sw->sw_alg != crd->crd_alg;
17021 + sw = sw->sw_next)
17022 + ;
17023 +
17024 + /* No such context ? */
17025 + if (sw == NULL) {
17026 + crp->crp_etype = EINVAL;
17027 + dprintk("%s,%d: EINVAL\n", __FILE__, __LINE__);
17028 + goto done;
17029 + }
17030 +
17031 + skip = crd->crd_skip;
17032 +
17033 + /*
17034 + * setup the SG list skip from the start of the buffer
17035 + */
17036 + memset(sg, 0, sizeof(sg));
17037 + if (crp->crp_flags & CRYPTO_F_SKBUF) {
17038 + int i, len;
17039 +
17040 + sg_num = 0;
17041 + sg_len = 0;
17042 +
17043 + if (skip < skb_headlen(skb)) {
17044 + len = skb_headlen(skb) - skip;
17045 + if (len + sg_len > crd->crd_len)
17046 + len = crd->crd_len - sg_len;
17047 + sg_set_page(&sg[sg_num],
17048 + virt_to_page(skb->data + skip), len,
17049 + offset_in_page(skb->data + skip));
17050 + sg_len += len;
17051 + sg_num++;
17052 + skip = 0;
17053 + } else
17054 + skip -= skb_headlen(skb);
17055 +
17056 + for (i = 0; sg_len < crd->crd_len &&
17057 + i < skb_shinfo(skb)->nr_frags &&
17058 + sg_num < SCATTERLIST_MAX; i++) {
17059 + if (skip < skb_shinfo(skb)->frags[i].size) {
17060 + len = skb_shinfo(skb)->frags[i].size - skip;
17061 + if (len + sg_len > crd->crd_len)
17062 + len = crd->crd_len - sg_len;
17063 + sg_set_page(&sg[sg_num],
17064 + skb_shinfo(skb)->frags[i].page,
17065 + len,
17066 + skb_shinfo(skb)->frags[i].page_offset + skip);
17067 + sg_len += len;
17068 + sg_num++;
17069 + skip = 0;
17070 + } else
17071 + skip -= skb_shinfo(skb)->frags[i].size;
17072 + }
17073 + } else if (crp->crp_flags & CRYPTO_F_IOV) {
17074 + int len;
17075 +
17076 + sg_len = 0;
17077 + for (sg_num = 0; sg_len <= crd->crd_len &&
17078 + sg_num < uiop->uio_iovcnt &&
17079 + sg_num < SCATTERLIST_MAX; sg_num++) {
17080 + if (skip <= uiop->uio_iov[sg_num].iov_len) {
17081 + len = uiop->uio_iov[sg_num].iov_len - skip;
17082 + if (len + sg_len > crd->crd_len)
17083 + len = crd->crd_len - sg_len;
17084 + sg_set_page(&sg[sg_num],
17085 + virt_to_page(uiop->uio_iov[sg_num].iov_base+skip),
17086 + len,
17087 + offset_in_page(uiop->uio_iov[sg_num].iov_base+skip));
17088 + sg_len += len;
17089 + skip = 0;
17090 + } else
17091 + skip -= uiop->uio_iov[sg_num].iov_len;
17092 + }
17093 + } else {
17094 + sg_len = (crp->crp_ilen - skip);
17095 + if (sg_len > crd->crd_len)
17096 + sg_len = crd->crd_len;
17097 + sg_set_page(&sg[0], virt_to_page(crp->crp_buf + skip),
17098 + sg_len, offset_in_page(crp->crp_buf + skip));
17099 + sg_num = 1;
17100 + }
17101 +
17102 +
17103 + switch (sw->sw_type) {
17104 + case SW_TYPE_BLKCIPHER: {
17105 + unsigned char iv[EALG_MAX_BLOCK_LEN];
17106 + unsigned char *ivp = iv;
17107 + int ivsize =
17108 + crypto_blkcipher_ivsize(crypto_blkcipher_cast(sw->sw_tfm));
17109 + struct blkcipher_desc desc;
17110 +
17111 + if (sg_len < crypto_blkcipher_blocksize(
17112 + crypto_blkcipher_cast(sw->sw_tfm))) {
17113 + crp->crp_etype = EINVAL;
17114 + dprintk("%s,%d: EINVAL len %d < %d\n", __FILE__, __LINE__,
17115 + sg_len, crypto_blkcipher_blocksize(
17116 + crypto_blkcipher_cast(sw->sw_tfm)));
17117 + goto done;
17118 + }
17119 +
17120 + if (ivsize > sizeof(iv)) {
17121 + crp->crp_etype = EINVAL;
17122 + dprintk("%s,%d: EINVAL\n", __FILE__, __LINE__);
17123 + goto done;
17124 + }
17125 +
17126 + if (crd->crd_flags & CRD_F_KEY_EXPLICIT) {
17127 + int i, error;
17128 +
17129 + if (debug) {
17130 + dprintk("%s key:", __FUNCTION__);
17131 + for (i = 0; i < (crd->crd_klen + 7) / 8; i++)
17132 + dprintk("%s0x%x", (i % 8) ? " " : "\n ",
17133 + crd->crd_key[i]);
17134 + dprintk("\n");
17135 + }
17136 + error = crypto_blkcipher_setkey(
17137 + crypto_blkcipher_cast(sw->sw_tfm), crd->crd_key,
17138 + (crd->crd_klen + 7) / 8);
17139 + if (error) {
17140 + dprintk("cryptosoft: setkey failed %d (crt_flags=0x%x)\n",
17141 + error, sw->sw_tfm->crt_flags);
17142 + crp->crp_etype = -error;
17143 + }
17144 + }
17145 +
17146 + memset(&desc, 0, sizeof(desc));
17147 + desc.tfm = crypto_blkcipher_cast(sw->sw_tfm);
17148 +
17149 + if (crd->crd_flags & CRD_F_ENCRYPT) { /* encrypt */
17150 +
17151 + if (crd->crd_flags & CRD_F_IV_EXPLICIT) {
17152 + ivp = crd->crd_iv;
17153 + } else {
17154 + get_random_bytes(ivp, ivsize);
17155 + }
17156 + /*
17157 + * do we have to copy the IV back to the buffer ?
17158 + */
17159 + if ((crd->crd_flags & CRD_F_IV_PRESENT) == 0) {
17160 + crypto_copyback(crp->crp_flags, crp->crp_buf,
17161 + crd->crd_inject, ivsize, (caddr_t)ivp);
17162 + }
17163 + desc.info = ivp;
17164 + crypto_blkcipher_encrypt_iv(&desc, sg, sg, sg_len);
17165 +
17166 + } else { /*decrypt */
17167 +
17168 + if (crd->crd_flags & CRD_F_IV_EXPLICIT) {
17169 + ivp = crd->crd_iv;
17170 + } else {
17171 + crypto_copydata(crp->crp_flags, crp->crp_buf,
17172 + crd->crd_inject, ivsize, (caddr_t)ivp);
17173 + }
17174 + desc.info = ivp;
17175 + crypto_blkcipher_decrypt_iv(&desc, sg, sg, sg_len);
17176 + }
17177 + } break;
17178 + case SW_TYPE_HMAC:
17179 + case SW_TYPE_HASH:
17180 + {
17181 + char result[HASH_MAX_LEN];
17182 + struct hash_desc desc;
17183 +
17184 + /* check we have room for the result */
17185 + if (crp->crp_ilen - crd->crd_inject < sw->u.hmac.sw_mlen) {
17186 + dprintk(
17187 + "cryptosoft: EINVAL crp_ilen=%d, len=%d, inject=%d digestsize=%d\n",
17188 + crp->crp_ilen, crd->crd_skip + sg_len, crd->crd_inject,
17189 + sw->u.hmac.sw_mlen);
17190 + crp->crp_etype = EINVAL;
17191 + goto done;
17192 + }
17193 +
17194 + memset(&desc, 0, sizeof(desc));
17195 + desc.tfm = crypto_hash_cast(sw->sw_tfm);
17196 +
17197 + memset(result, 0, sizeof(result));
17198 +
17199 + if (sw->sw_type == SW_TYPE_HMAC) {
17200 +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,19)
17201 + crypto_hmac(sw->sw_tfm, sw->u.hmac.sw_key, &sw->u.hmac.sw_klen,
17202 + sg, sg_num, result);
17203 +#else
17204 + crypto_hash_setkey(desc.tfm, sw->u.hmac.sw_key,
17205 + sw->u.hmac.sw_klen);
17206 + crypto_hash_digest(&desc, sg, sg_len, result);
17207 +#endif /* #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,19) */
17208 +
17209 + } else { /* SW_TYPE_HASH */
17210 + crypto_hash_digest(&desc, sg, sg_len, result);
17211 + }
17212 +
17213 + crypto_copyback(crp->crp_flags, crp->crp_buf,
17214 + crd->crd_inject, sw->u.hmac.sw_mlen, result);
17215 + }
17216 + break;
17217 +
17218 + case SW_TYPE_COMP: {
17219 + void *ibuf = NULL;
17220 + void *obuf = sw->u.sw_comp_buf;
17221 + int ilen = sg_len, olen = CRYPTO_MAX_DATA_LEN;
17222 + int ret = 0;
17223 +
17224 + /*
17225 + * we need to use an additional copy if there is more than one
17226 + * input chunk since the kernel comp routines do not handle
17227 + * SG yet. Otherwise we just use the input buffer as is.
17228 + * Rather than allocate another buffer we just split the tmp
17229 + * buffer we already have.
17230 + * Perhaps we should just use zlib directly ?
17231 + */
17232 + if (sg_num > 1) {
17233 + int blk;
17234 +
17235 + ibuf = obuf;
17236 + for (blk = 0; blk < sg_num; blk++) {
17237 + memcpy(obuf, sg_virt(&sg[blk]),
17238 + sg[blk].length);
17239 + obuf += sg[blk].length;
17240 + }
17241 + olen -= sg_len;
17242 + } else
17243 + ibuf = sg_virt(&sg[0]);
17244 +
17245 + if (crd->crd_flags & CRD_F_ENCRYPT) { /* compress */
17246 + ret = crypto_comp_compress(crypto_comp_cast(sw->sw_tfm),
17247 + ibuf, ilen, obuf, &olen);
17248 + if (!ret && olen > crd->crd_len) {
17249 + dprintk("cryptosoft: ERANGE compress %d into %d\n",
17250 + crd->crd_len, olen);
17251 + if (swcr_fail_if_compression_grows)
17252 + ret = ERANGE;
17253 + }
17254 + } else { /* decompress */
17255 + ret = crypto_comp_decompress(crypto_comp_cast(sw->sw_tfm),
17256 + ibuf, ilen, obuf, &olen);
17257 + if (!ret && (olen + crd->crd_inject) > crp->crp_olen) {
17258 + dprintk("cryptosoft: ETOOSMALL decompress %d into %d, "
17259 + "space for %d,at offset %d\n",
17260 + crd->crd_len, olen, crp->crp_olen, crd->crd_inject);
17261 + ret = ETOOSMALL;
17262 + }
17263 + }
17264 + if (ret)
17265 + dprintk("%s,%d: ret = %d\n", __FILE__, __LINE__, ret);
17266 +
17267 + /*
17268 + * on success copy result back,
17269 + * linux crpyto API returns -errno, we need to fix that
17270 + */
17271 + crp->crp_etype = ret < 0 ? -ret : ret;
17272 + if (ret == 0) {
17273 + /* copy back the result and return it's size */
17274 + crypto_copyback(crp->crp_flags, crp->crp_buf,
17275 + crd->crd_inject, olen, obuf);
17276 + crp->crp_olen = olen;
17277 + }
17278 +
17279 +
17280 + } break;
17281 +
17282 + default:
17283 + /* Unknown/unsupported algorithm */
17284 + dprintk("%s,%d: EINVAL\n", __FILE__, __LINE__);
17285 + crp->crp_etype = EINVAL;
17286 + goto done;
17287 + }
17288 + }
17289 +
17290 +done:
17291 + crypto_done(crp);
17292 + return 0;
17293 +}
17294 +
17295 +static int
17296 +cryptosoft_init(void)
17297 +{
17298 + int i, sw_type, mode;
17299 + char *algo;
17300 +
17301 + dprintk("%s(%p)\n", __FUNCTION__, cryptosoft_init);
17302 +
17303 + softc_device_init(&swcr_softc, "cryptosoft", 0, swcr_methods);
17304 +
17305 + swcr_id = crypto_get_driverid(softc_get_device(&swcr_softc),
17306 + CRYPTOCAP_F_SOFTWARE | CRYPTOCAP_F_SYNC);
17307 + if (swcr_id < 0) {
17308 + printk("Software crypto device cannot initialize!");
17309 + return -ENODEV;
17310 + }
17311 +
17312 +#define REGISTER(alg) \
17313 + crypto_register(swcr_id, alg, 0,0);
17314 +
17315 + for (i = CRYPTO_ALGORITHM_MIN; i <= CRYPTO_ALGORITHM_MAX; ++i)
17316 + {
17317 +
17318 + algo = crypto_details[i].alg_name;
17319 + if (!algo || !*algo)
17320 + {
17321 + dprintk("%s:Algorithm %d not supported\n", __FUNCTION__, i);
17322 + continue;
17323 + }
17324 +
17325 + mode = crypto_details[i].mode;
17326 + sw_type = crypto_details[i].sw_type;
17327 +
17328 + switch (sw_type)
17329 + {
17330 + case SW_TYPE_CIPHER:
17331 + if (crypto_has_cipher(algo, 0, CRYPTO_ALG_ASYNC))
17332 + {
17333 + REGISTER(i);
17334 + }
17335 + else
17336 + {
17337 + dprintk("%s:CIPHER algorithm %d:'%s' not supported\n",
17338 + __FUNCTION__, i, algo);
17339 + }
17340 + break;
17341 + case SW_TYPE_HMAC:
17342 + if (crypto_has_hash(algo, 0, CRYPTO_ALG_ASYNC))
17343 + {
17344 + REGISTER(i);
17345 + }
17346 + else
17347 + {
17348 + dprintk("%s:HMAC algorithm %d:'%s' not supported\n",
17349 + __FUNCTION__, i, algo);
17350 + }
17351 + break;
17352 + case SW_TYPE_HASH:
17353 + if (crypto_has_hash(algo, 0, CRYPTO_ALG_ASYNC))
17354 + {
17355 + REGISTER(i);
17356 + }
17357 + else
17358 + {
17359 + dprintk("%s:HASH algorithm %d:'%s' not supported\n",
17360 + __FUNCTION__, i, algo);
17361 + }
17362 + break;
17363 + case SW_TYPE_COMP:
17364 + if (crypto_has_comp(algo, 0, CRYPTO_ALG_ASYNC))
17365 + {
17366 + REGISTER(i);
17367 + }
17368 + else
17369 + {
17370 + dprintk("%s:COMP algorithm %d:'%s' not supported\n",
17371 + __FUNCTION__, i, algo);
17372 + }
17373 + break;
17374 + case SW_TYPE_BLKCIPHER:
17375 + if (crypto_has_blkcipher(algo, 0, CRYPTO_ALG_ASYNC))
17376 + {
17377 + REGISTER(i);
17378 + }
17379 + else
17380 + {
17381 + dprintk("%s:BLKCIPHER algorithm %d:'%s' not supported\n",
17382 + __FUNCTION__, i, algo);
17383 + }
17384 + break;
17385 + default:
17386 + dprintk(
17387 + "%s:Algorithm Type %d not supported (algorithm %d:'%s')\n",
17388 + __FUNCTION__, sw_type, i, algo);
17389 + break;
17390 + }
17391 + }
17392 +
17393 + return(0);
17394 +}
17395 +
17396 +static void
17397 +cryptosoft_exit(void)
17398 +{
17399 + dprintk("%s()\n", __FUNCTION__);
17400 + crypto_unregister_all(swcr_id);
17401 + swcr_id = -1;
17402 +}
17403 +
17404 +module_init(cryptosoft_init);
17405 +module_exit(cryptosoft_exit);
17406 +
17407 +MODULE_LICENSE("Dual BSD/GPL");
17408 +MODULE_AUTHOR("David McCullough <david_mccullough@securecomputing.com>");
17409 +MODULE_DESCRIPTION("Cryptosoft (OCF module for kernel crypto)");
17410 --- /dev/null
17411 +++ b/crypto/ocf/rndtest.c
17412 @@ -0,0 +1,300 @@
17413 +/* $OpenBSD$ */
17414 +
17415 +/*
17416 + * OCF/Linux port done by David McCullough <david_mccullough@securecomputing.com>
17417 + * Copyright (C) 2006-2007 David McCullough
17418 + * Copyright (C) 2004-2005 Intel Corporation.
17419 + * The license and original author are listed below.
17420 + *
17421 + * Copyright (c) 2002 Jason L. Wright (jason@thought.net)
17422 + * All rights reserved.
17423 + *
17424 + * Redistribution and use in source and binary forms, with or without
17425 + * modification, are permitted provided that the following conditions
17426 + * are met:
17427 + * 1. Redistributions of source code must retain the above copyright
17428 + * notice, this list of conditions and the following disclaimer.
17429 + * 2. Redistributions in binary form must reproduce the above copyright
17430 + * notice, this list of conditions and the following disclaimer in the
17431 + * documentation and/or other materials provided with the distribution.
17432 + * 3. All advertising materials mentioning features or use of this software
17433 + * must display the following acknowledgement:
17434 + * This product includes software developed by Jason L. Wright
17435 + * 4. The name of the author may not be used to endorse or promote products
17436 + * derived from this software without specific prior written permission.
17437 + *
17438 + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
17439 + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
17440 + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
17441 + * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
17442 + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
17443 + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
17444 + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
17445 + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
17446 + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
17447 + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
17448 + * POSSIBILITY OF SUCH DAMAGE.
17449 + */
17450 +
17451 +#ifndef AUTOCONF_INCLUDED
17452 +#include <linux/config.h>
17453 +#endif
17454 +#include <linux/module.h>
17455 +#include <linux/list.h>
17456 +#include <linux/wait.h>
17457 +#include <linux/time.h>
17458 +#include <linux/version.h>
17459 +#include <linux/unistd.h>
17460 +#include <linux/kernel.h>
17461 +#include <linux/string.h>
17462 +#include <linux/time.h>
17463 +#include <cryptodev.h>
17464 +#include "rndtest.h"
17465 +
17466 +static struct rndtest_stats rndstats;
17467 +
17468 +static void rndtest_test(struct rndtest_state *);
17469 +
17470 +/* The tests themselves */
17471 +static int rndtest_monobit(struct rndtest_state *);
17472 +static int rndtest_runs(struct rndtest_state *);
17473 +static int rndtest_longruns(struct rndtest_state *);
17474 +static int rndtest_chi_4(struct rndtest_state *);
17475 +
17476 +static int rndtest_runs_check(struct rndtest_state *, int, int *);
17477 +static void rndtest_runs_record(struct rndtest_state *, int, int *);
17478 +
17479 +static const struct rndtest_testfunc {
17480 + int (*test)(struct rndtest_state *);
17481 +} rndtest_funcs[] = {
17482 + { rndtest_monobit },
17483 + { rndtest_runs },
17484 + { rndtest_chi_4 },
17485 + { rndtest_longruns },
17486 +};
17487 +
17488 +#define RNDTEST_NTESTS (sizeof(rndtest_funcs)/sizeof(rndtest_funcs[0]))
17489 +
17490 +static void
17491 +rndtest_test(struct rndtest_state *rsp)
17492 +{
17493 + int i, rv = 0;
17494 +
17495 + rndstats.rst_tests++;
17496 + for (i = 0; i < RNDTEST_NTESTS; i++)
17497 + rv |= (*rndtest_funcs[i].test)(rsp);
17498 + rsp->rs_discard = (rv != 0);
17499 +}
17500 +
17501 +
17502 +extern int crypto_debug;
17503 +#define rndtest_verbose 2
17504 +#define rndtest_report(rsp, failure, fmt, a...) \
17505 + { if (failure || crypto_debug) { printk("rng_test: " fmt "\n", a); } else; }
17506 +
17507 +#define RNDTEST_MONOBIT_MINONES 9725
17508 +#define RNDTEST_MONOBIT_MAXONES 10275
17509 +
17510 +static int
17511 +rndtest_monobit(struct rndtest_state *rsp)
17512 +{
17513 + int i, ones = 0, j;
17514 + u_int8_t r;
17515 +
17516 + for (i = 0; i < RNDTEST_NBYTES; i++) {
17517 + r = rsp->rs_buf[i];
17518 + for (j = 0; j < 8; j++, r <<= 1)
17519 + if (r & 0x80)
17520 + ones++;
17521 + }
17522 + if (ones > RNDTEST_MONOBIT_MINONES &&
17523 + ones < RNDTEST_MONOBIT_MAXONES) {
17524 + if (rndtest_verbose > 1)
17525 + rndtest_report(rsp, 0, "monobit pass (%d < %d < %d)",
17526 + RNDTEST_MONOBIT_MINONES, ones,
17527 + RNDTEST_MONOBIT_MAXONES);
17528 + return (0);
17529 + } else {
17530 + if (rndtest_verbose)
17531 + rndtest_report(rsp, 1,
17532 + "monobit failed (%d ones)", ones);
17533 + rndstats.rst_monobit++;
17534 + return (-1);
17535 + }
17536 +}
17537 +
17538 +#define RNDTEST_RUNS_NINTERVAL 6
17539 +
17540 +static const struct rndtest_runs_tabs {
17541 + u_int16_t min, max;
17542 +} rndtest_runs_tab[] = {
17543 + { 2343, 2657 },
17544 + { 1135, 1365 },
17545 + { 542, 708 },
17546 + { 251, 373 },
17547 + { 111, 201 },
17548 + { 111, 201 },
17549 +};
17550 +
17551 +static int
17552 +rndtest_runs(struct rndtest_state *rsp)
17553 +{
17554 + int i, j, ones, zeros, rv = 0;
17555 + int onei[RNDTEST_RUNS_NINTERVAL], zeroi[RNDTEST_RUNS_NINTERVAL];
17556 + u_int8_t c;
17557 +
17558 + bzero(onei, sizeof(onei));
17559 + bzero(zeroi, sizeof(zeroi));
17560 + ones = zeros = 0;
17561 + for (i = 0; i < RNDTEST_NBYTES; i++) {
17562 + c = rsp->rs_buf[i];
17563 + for (j = 0; j < 8; j++, c <<= 1) {
17564 + if (c & 0x80) {
17565 + ones++;
17566 + rndtest_runs_record(rsp, zeros, zeroi);
17567 + zeros = 0;
17568 + } else {
17569 + zeros++;
17570 + rndtest_runs_record(rsp, ones, onei);
17571 + ones = 0;
17572 + }
17573 + }
17574 + }
17575 + rndtest_runs_record(rsp, ones, onei);
17576 + rndtest_runs_record(rsp, zeros, zeroi);
17577 +
17578 + rv |= rndtest_runs_check(rsp, 0, zeroi);
17579 + rv |= rndtest_runs_check(rsp, 1, onei);
17580 +
17581 + if (rv)
17582 + rndstats.rst_runs++;
17583 +
17584 + return (rv);
17585 +}
17586 +
17587 +static void
17588 +rndtest_runs_record(struct rndtest_state *rsp, int len, int *intrv)
17589 +{
17590 + if (len == 0)
17591 + return;
17592 + if (len > RNDTEST_RUNS_NINTERVAL)
17593 + len = RNDTEST_RUNS_NINTERVAL;
17594 + len -= 1;
17595 + intrv[len]++;
17596 +}
17597 +
17598 +static int
17599 +rndtest_runs_check(struct rndtest_state *rsp, int val, int *src)
17600 +{
17601 + int i, rv = 0;
17602 +
17603 + for (i = 0; i < RNDTEST_RUNS_NINTERVAL; i++) {
17604 + if (src[i] < rndtest_runs_tab[i].min ||
17605 + src[i] > rndtest_runs_tab[i].max) {
17606 + rndtest_report(rsp, 1,
17607 + "%s interval %d failed (%d, %d-%d)",
17608 + val ? "ones" : "zeros",
17609 + i + 1, src[i], rndtest_runs_tab[i].min,
17610 + rndtest_runs_tab[i].max);
17611 + rv = -1;
17612 + } else {
17613 + rndtest_report(rsp, 0,
17614 + "runs pass %s interval %d (%d < %d < %d)",
17615 + val ? "ones" : "zeros",
17616 + i + 1, rndtest_runs_tab[i].min, src[i],
17617 + rndtest_runs_tab[i].max);
17618 + }
17619 + }
17620 + return (rv);
17621 +}
17622 +
17623 +static int
17624 +rndtest_longruns(struct rndtest_state *rsp)
17625 +{
17626 + int i, j, ones = 0, zeros = 0, maxones = 0, maxzeros = 0;
17627 + u_int8_t c;
17628 +
17629 + for (i = 0; i < RNDTEST_NBYTES; i++) {
17630 + c = rsp->rs_buf[i];
17631 + for (j = 0; j < 8; j++, c <<= 1) {
17632 + if (c & 0x80) {
17633 + zeros = 0;
17634 + ones++;
17635 + if (ones > maxones)
17636 + maxones = ones;
17637 + } else {
17638 + ones = 0;
17639 + zeros++;
17640 + if (zeros > maxzeros)
17641 + maxzeros = zeros;
17642 + }
17643 + }
17644 + }
17645 +
17646 + if (maxones < 26 && maxzeros < 26) {
17647 + rndtest_report(rsp, 0, "longruns pass (%d ones, %d zeros)",
17648 + maxones, maxzeros);
17649 + return (0);
17650 + } else {
17651 + rndtest_report(rsp, 1, "longruns fail (%d ones, %d zeros)",
17652 + maxones, maxzeros);
17653 + rndstats.rst_longruns++;
17654 + return (-1);
17655 + }
17656 +}
17657 +
17658 +/*
17659 + * chi^2 test over 4 bits: (this is called the poker test in FIPS 140-2,
17660 + * but it is really the chi^2 test over 4 bits (the poker test as described
17661 + * by Knuth vol 2 is something different, and I take him as authoritative
17662 + * on nomenclature over NIST).
17663 + */
17664 +#define RNDTEST_CHI4_K 16
17665 +#define RNDTEST_CHI4_K_MASK (RNDTEST_CHI4_K - 1)
17666 +
17667 +/*
17668 + * The unnormalized values are used so that we don't have to worry about
17669 + * fractional precision. The "real" value is found by:
17670 + * (V - 1562500) * (16 / 5000) = Vn (where V is the unnormalized value)
17671 + */
17672 +#define RNDTEST_CHI4_VMIN 1563181 /* 2.1792 */
17673 +#define RNDTEST_CHI4_VMAX 1576929 /* 46.1728 */
17674 +
17675 +static int
17676 +rndtest_chi_4(struct rndtest_state *rsp)
17677 +{
17678 + unsigned int freq[RNDTEST_CHI4_K], i, sum;
17679 +
17680 + for (i = 0; i < RNDTEST_CHI4_K; i++)
17681 + freq[i] = 0;
17682 +
17683 + /* Get number of occurances of each 4 bit pattern */
17684 + for (i = 0; i < RNDTEST_NBYTES; i++) {
17685 + freq[(rsp->rs_buf[i] >> 4) & RNDTEST_CHI4_K_MASK]++;
17686 + freq[(rsp->rs_buf[i] >> 0) & RNDTEST_CHI4_K_MASK]++;
17687 + }
17688 +
17689 + for (i = 0, sum = 0; i < RNDTEST_CHI4_K; i++)
17690 + sum += freq[i] * freq[i];
17691 +
17692 + if (sum >= 1563181 && sum <= 1576929) {
17693 + rndtest_report(rsp, 0, "chi^2(4): pass (sum %u)", sum);
17694 + return (0);
17695 + } else {
17696 + rndtest_report(rsp, 1, "chi^2(4): failed (sum %u)", sum);
17697 + rndstats.rst_chi++;
17698 + return (-1);
17699 + }
17700 +}
17701 +
17702 +int
17703 +rndtest_buf(unsigned char *buf)
17704 +{
17705 + struct rndtest_state rsp;
17706 +
17707 + memset(&rsp, 0, sizeof(rsp));
17708 + rsp.rs_buf = buf;
17709 + rndtest_test(&rsp);
17710 + return(rsp.rs_discard);
17711 +}
17712 +
17713 --- /dev/null
17714 +++ b/crypto/ocf/rndtest.h
17715 @@ -0,0 +1,54 @@
17716 +/* $FreeBSD: src/sys/dev/rndtest/rndtest.h,v 1.1 2003/03/11 22:54:44 sam Exp $ */
17717 +/* $OpenBSD$ */
17718 +
17719 +/*
17720 + * Copyright (c) 2002 Jason L. Wright (jason@thought.net)
17721 + * All rights reserved.
17722 + *
17723 + * Redistribution and use in source and binary forms, with or without
17724 + * modification, are permitted provided that the following conditions
17725 + * are met:
17726 + * 1. Redistributions of source code must retain the above copyright
17727 + * notice, this list of conditions and the following disclaimer.
17728 + * 2. Redistributions in binary form must reproduce the above copyright
17729 + * notice, this list of conditions and the following disclaimer in the
17730 + * documentation and/or other materials provided with the distribution.
17731 + * 3. All advertising materials mentioning features or use of this software
17732 + * must display the following acknowledgement:
17733 + * This product includes software developed by Jason L. Wright
17734 + * 4. The name of the author may not be used to endorse or promote products
17735 + * derived from this software without specific prior written permission.
17736 + *
17737 + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
17738 + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
17739 + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
17740 + * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
17741 + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
17742 + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
17743 + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
17744 + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
17745 + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
17746 + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
17747 + * POSSIBILITY OF SUCH DAMAGE.
17748 + */
17749 +
17750 +
17751 +/* Some of the tests depend on these values */
17752 +#define RNDTEST_NBYTES 2500
17753 +#define RNDTEST_NBITS (8 * RNDTEST_NBYTES)
17754 +
17755 +struct rndtest_state {
17756 + int rs_discard; /* discard/accept random data */
17757 + u_int8_t *rs_buf;
17758 +};
17759 +
17760 +struct rndtest_stats {
17761 + u_int32_t rst_discard; /* number of bytes discarded */
17762 + u_int32_t rst_tests; /* number of test runs */
17763 + u_int32_t rst_monobit; /* monobit test failures */
17764 + u_int32_t rst_runs; /* 0/1 runs failures */
17765 + u_int32_t rst_longruns; /* longruns failures */
17766 + u_int32_t rst_chi; /* chi^2 failures */
17767 +};
17768 +
17769 +extern int rndtest_buf(unsigned char *buf);
17770 --- /dev/null
17771 +++ b/crypto/ocf/ocf-compat.h
17772 @@ -0,0 +1,268 @@
17773 +#ifndef _BSD_COMPAT_H_
17774 +#define _BSD_COMPAT_H_ 1
17775 +/****************************************************************************/
17776 +/*
17777 + * Provide compat routines for older linux kernels and BSD kernels
17778 + *
17779 + * Written by David McCullough <david_mccullough@securecomputing.com>
17780 + * Copyright (C) 2007 David McCullough <david_mccullough@securecomputing.com>
17781 + *
17782 + * LICENSE TERMS
17783 + *
17784 + * The free distribution and use of this software in both source and binary
17785 + * form is allowed (with or without changes) provided that:
17786 + *
17787 + * 1. distributions of this source code include the above copyright
17788 + * notice, this list of conditions and the following disclaimer;
17789 + *
17790 + * 2. distributions in binary form include the above copyright
17791 + * notice, this list of conditions and the following disclaimer
17792 + * in the documentation and/or other associated materials;
17793 + *
17794 + * 3. the copyright holder's name is not used to endorse products
17795 + * built using this software without specific written permission.
17796 + *
17797 + * ALTERNATIVELY, provided that this notice is retained in full, this file
17798 + * may be distributed under the terms of the GNU General Public License (GPL),
17799 + * in which case the provisions of the GPL apply INSTEAD OF those given above.
17800 + *
17801 + * DISCLAIMER
17802 + *
17803 + * This software is provided 'as is' with no explicit or implied warranties
17804 + * in respect of its properties, including, but not limited to, correctness
17805 + * and/or fitness for purpose.
17806 + */
17807 +/****************************************************************************/
17808 +#ifdef __KERNEL__
17809 +/*
17810 + * fake some BSD driver interface stuff specifically for OCF use
17811 + */
17812 +
17813 +typedef struct ocf_device *device_t;
17814 +
17815 +typedef struct {
17816 + int (*cryptodev_newsession)(device_t dev, u_int32_t *sidp, struct cryptoini *cri);
17817 + int (*cryptodev_freesession)(device_t dev, u_int64_t tid);
17818 + int (*cryptodev_process)(device_t dev, struct cryptop *crp, int hint);
17819 + int (*cryptodev_kprocess)(device_t dev, struct cryptkop *krp, int hint);
17820 +} device_method_t;
17821 +#define DEVMETHOD(id, func) id: func
17822 +
17823 +struct ocf_device {
17824 + char name[32]; /* the driver name */
17825 + char nameunit[32]; /* the driver name + HW instance */
17826 + int unit;
17827 + device_method_t methods;
17828 + void *softc;
17829 +};
17830 +
17831 +#define CRYPTODEV_NEWSESSION(dev, sid, cri) \
17832 + ((*(dev)->methods.cryptodev_newsession)(dev,sid,cri))
17833 +#define CRYPTODEV_FREESESSION(dev, sid) \
17834 + ((*(dev)->methods.cryptodev_freesession)(dev, sid))
17835 +#define CRYPTODEV_PROCESS(dev, crp, hint) \
17836 + ((*(dev)->methods.cryptodev_process)(dev, crp, hint))
17837 +#define CRYPTODEV_KPROCESS(dev, krp, hint) \
17838 + ((*(dev)->methods.cryptodev_kprocess)(dev, krp, hint))
17839 +
17840 +#define device_get_name(dev) ((dev)->name)
17841 +#define device_get_nameunit(dev) ((dev)->nameunit)
17842 +#define device_get_unit(dev) ((dev)->unit)
17843 +#define device_get_softc(dev) ((dev)->softc)
17844 +
17845 +#define softc_device_decl \
17846 + struct ocf_device _device; \
17847 + device_t
17848 +
17849 +#define softc_device_init(_sc, _name, _unit, _methods) \
17850 + if (1) {\
17851 + strncpy((_sc)->_device.name, _name, sizeof((_sc)->_device.name) - 1); \
17852 + snprintf((_sc)->_device.nameunit, sizeof((_sc)->_device.name), "%s%d", _name, _unit); \
17853 + (_sc)->_device.unit = _unit; \
17854 + (_sc)->_device.methods = _methods; \
17855 + (_sc)->_device.softc = (void *) _sc; \
17856 + *(device_t *)((softc_get_device(_sc))+1) = &(_sc)->_device; \
17857 + } else
17858 +
17859 +#define softc_get_device(_sc) (&(_sc)->_device)
17860 +
17861 +/*
17862 + * iomem support for 2.4 and 2.6 kernels
17863 + */
17864 +#include <linux/version.h>
17865 +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,0)
17866 +#define ocf_iomem_t unsigned long
17867 +
17868 +/*
17869 + * implement simple workqueue like support for older kernels
17870 + */
17871 +
17872 +#include <linux/tqueue.h>
17873 +
17874 +#define work_struct tq_struct
17875 +
17876 +#define INIT_WORK(wp, fp, ap) \
17877 + do { \
17878 + (wp)->sync = 0; \
17879 + (wp)->routine = (fp); \
17880 + (wp)->data = (ap); \
17881 + } while (0)
17882 +
17883 +#define schedule_work(wp) \
17884 + do { \
17885 + queue_task((wp), &tq_immediate); \
17886 + mark_bh(IMMEDIATE_BH); \
17887 + } while (0)
17888 +
17889 +#define flush_scheduled_work() run_task_queue(&tq_immediate)
17890 +
17891 +#else
17892 +#define ocf_iomem_t void __iomem *
17893 +
17894 +#include <linux/workqueue.h>
17895 +
17896 +#endif
17897 +
17898 +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,11)
17899 +#define files_fdtable(files) (files)
17900 +#endif
17901 +
17902 +#ifdef MODULE_PARM
17903 +#undef module_param /* just in case */
17904 +#define module_param(a,b,c) MODULE_PARM(a,"i")
17905 +#endif
17906 +
17907 +#define bzero(s,l) memset(s,0,l)
17908 +#define bcopy(s,d,l) memcpy(d,s,l)
17909 +#define bcmp(x, y, l) memcmp(x,y,l)
17910 +
17911 +#define MIN(x,y) ((x) < (y) ? (x) : (y))
17912 +
17913 +#define device_printf(dev, a...) ({ \
17914 + printk("%s: ", device_get_nameunit(dev)); printk(a); \
17915 + })
17916 +
17917 +#undef printf
17918 +#define printf(fmt...) printk(fmt)
17919 +
17920 +#define KASSERT(c,p) if (!(c)) { printk p ; } else
17921 +
17922 +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,0)
17923 +#define ocf_daemonize(str) \
17924 + daemonize(); \
17925 + spin_lock_irq(&current->sigmask_lock); \
17926 + sigemptyset(&current->blocked); \
17927 + recalc_sigpending(current); \
17928 + spin_unlock_irq(&current->sigmask_lock); \
17929 + sprintf(current->comm, str);
17930 +#else
17931 +#define ocf_daemonize(str) daemonize(str);
17932 +#endif
17933 +
17934 +#define TAILQ_INSERT_TAIL(q,d,m) list_add_tail(&(d)->m, (q))
17935 +#define TAILQ_EMPTY(q) list_empty(q)
17936 +#define TAILQ_FOREACH(v, q, m) list_for_each_entry(v, q, m)
17937 +
17938 +#define read_random(p,l) get_random_bytes(p,l)
17939 +
17940 +#define DELAY(x) ((x) > 2000 ? mdelay((x)/1000) : udelay(x))
17941 +#define strtoul simple_strtoul
17942 +
17943 +#define pci_get_vendor(dev) ((dev)->vendor)
17944 +#define pci_get_device(dev) ((dev)->device)
17945 +
17946 +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,0)
17947 +#define pci_set_consistent_dma_mask(dev, mask) (0)
17948 +#endif
17949 +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,10)
17950 +#define pci_dma_sync_single_for_cpu pci_dma_sync_single
17951 +#endif
17952 +
17953 +#ifndef DMA_32BIT_MASK
17954 +#define DMA_32BIT_MASK 0x00000000ffffffffULL
17955 +#endif
17956 +
17957 +#define htole32(x) cpu_to_le32(x)
17958 +#define htobe32(x) cpu_to_be32(x)
17959 +#define htole16(x) cpu_to_le16(x)
17960 +#define htobe16(x) cpu_to_be16(x)
17961 +
17962 +/* older kernels don't have these */
17963 +
17964 +#ifndef IRQ_NONE
17965 +#define IRQ_NONE
17966 +#define IRQ_HANDLED
17967 +#define irqreturn_t void
17968 +#endif
17969 +#ifndef IRQF_SHARED
17970 +#define IRQF_SHARED SA_SHIRQ
17971 +#endif
17972 +
17973 +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)
17974 +# define strlcpy(dest,src,len) \
17975 + ({strncpy(dest,src,(len)-1); ((char *)dest)[(len)-1] = '\0'; })
17976 +#endif
17977 +
17978 +#ifndef MAX_ERRNO
17979 +#define MAX_ERRNO 4095
17980 +#endif
17981 +#ifndef IS_ERR_VALUE
17982 +#define IS_ERR_VALUE(x) ((unsigned long)(x) >= (unsigned long)-MAX_ERRNO)
17983 +#endif
17984 +
17985 +/*
17986 + * common debug for all
17987 + */
17988 +#if 1
17989 +#define dprintk(a...) do { if (debug) printk(a); } while(0)
17990 +#else
17991 +#define dprintk(a...)
17992 +#endif
17993 +
17994 +#ifndef SLAB_ATOMIC
17995 +/* Changed in 2.6.20, must use GFP_ATOMIC now */
17996 +#define SLAB_ATOMIC GFP_ATOMIC
17997 +#endif
17998 +
17999 +/*
18000 + * need some additional support for older kernels */
18001 +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,2)
18002 +#define pci_register_driver_compat(driver, rc) \
18003 + do { \
18004 + if ((rc) > 0) { \
18005 + (rc) = 0; \
18006 + } else if (rc == 0) { \
18007 + (rc) = -ENODEV; \
18008 + } else { \
18009 + pci_unregister_driver(driver); \
18010 + } \
18011 + } while (0)
18012 +#elif LINUX_VERSION_CODE < KERNEL_VERSION(2,6,10)
18013 +#define pci_register_driver_compat(driver,rc) ((rc) = (rc) < 0 ? (rc) : 0)
18014 +#else
18015 +#define pci_register_driver_compat(driver,rc)
18016 +#endif
18017 +
18018 +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,24)
18019 +
18020 +#include <asm/scatterlist.h>
18021 +
18022 +static inline void sg_set_page(struct scatterlist *sg, struct page *page,
18023 + unsigned int len, unsigned int offset)
18024 +{
18025 + sg->page = page;
18026 + sg->offset = offset;
18027 + sg->length = len;
18028 +}
18029 +
18030 +static inline void *sg_virt(struct scatterlist *sg)
18031 +{
18032 + return page_address(sg->page) + sg->offset;
18033 +}
18034 +
18035 +#endif
18036 +
18037 +#endif /* __KERNEL__ */
18038 +
18039 +/****************************************************************************/
18040 +#endif /* _BSD_COMPAT_H_ */
18041 --- /dev/null
18042 +++ b/crypto/ocf/pasemi/pasemi.c
18043 @@ -0,0 +1,1009 @@
18044 +/*
18045 + * Copyright (C) 2007 PA Semi, Inc
18046 + *
18047 + * Driver for the PA Semi PWRficient DMA Crypto Engine
18048 + *
18049 + * This program is free software; you can redistribute it and/or modify
18050 + * it under the terms of the GNU General Public License version 2 as
18051 + * published by the Free Software Foundation.
18052 + *
18053 + * This program is distributed in the hope that it will be useful,
18054 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
18055 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18056 + * GNU General Public License for more details.
18057 + *
18058 + * You should have received a copy of the GNU General Public License
18059 + * along with this program; if not, write to the Free Software
18060 + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
18061 + */
18062 +
18063 +#ifndef AUTOCONF_INCLUDED
18064 +#include <linux/config.h>
18065 +#endif
18066 +#include <linux/module.h>
18067 +#include <linux/init.h>
18068 +#include <linux/interrupt.h>
18069 +#include <linux/timer.h>
18070 +#include <linux/random.h>
18071 +#include <linux/skbuff.h>
18072 +#include <asm/scatterlist.h>
18073 +#include <linux/moduleparam.h>
18074 +#include <linux/pci.h>
18075 +#include <cryptodev.h>
18076 +#include <uio.h>
18077 +#include "pasemi_fnu.h"
18078 +
18079 +#define DRV_NAME "pasemi"
18080 +
18081 +#define TIMER_INTERVAL 1000
18082 +
18083 +static void __devexit pasemi_dma_remove(struct pci_dev *pdev);
18084 +static struct pasdma_status volatile * dma_status;
18085 +
18086 +static int debug;
18087 +module_param(debug, int, 0644);
18088 +MODULE_PARM_DESC(debug, "Enable debug");
18089 +
18090 +static void pasemi_desc_start(struct pasemi_desc *desc, u64 hdr)
18091 +{
18092 + desc->postop = 0;
18093 + desc->quad[0] = hdr;
18094 + desc->quad_cnt = 1;
18095 + desc->size = 1;
18096 +}
18097 +
18098 +static void pasemi_desc_build(struct pasemi_desc *desc, u64 val)
18099 +{
18100 + desc->quad[desc->quad_cnt++] = val;
18101 + desc->size = (desc->quad_cnt + 1) / 2;
18102 +}
18103 +
18104 +static void pasemi_desc_hdr(struct pasemi_desc *desc, u64 hdr)
18105 +{
18106 + desc->quad[0] |= hdr;
18107 +}
18108 +
18109 +static int pasemi_desc_size(struct pasemi_desc *desc)
18110 +{
18111 + return desc->size;
18112 +}
18113 +
18114 +static void pasemi_ring_add_desc(
18115 + struct pasemi_fnu_txring *ring,
18116 + struct pasemi_desc *desc,
18117 + struct cryptop *crp) {
18118 + int i;
18119 + int ring_index = 2 * (ring->next_to_fill & (TX_RING_SIZE-1));
18120 +
18121 + TX_DESC_INFO(ring, ring->next_to_fill).desc_size = desc->size;
18122 + TX_DESC_INFO(ring, ring->next_to_fill).desc_postop = desc->postop;
18123 + TX_DESC_INFO(ring, ring->next_to_fill).cf_crp = crp;
18124 +
18125 + for (i = 0; i < desc->quad_cnt; i += 2) {
18126 + ring_index = 2 * (ring->next_to_fill & (TX_RING_SIZE-1));
18127 + ring->desc[ring_index] = desc->quad[i];
18128 + ring->desc[ring_index + 1] = desc->quad[i + 1];
18129 + ring->next_to_fill++;
18130 + }
18131 +
18132 + if (desc->quad_cnt & 1)
18133 + ring->desc[ring_index + 1] = 0;
18134 +}
18135 +
18136 +static void pasemi_ring_incr(struct pasemi_softc *sc, int chan_index, int incr)
18137 +{
18138 + out_le32(sc->dma_regs + PAS_DMA_TXCHAN_INCR(sc->base_chan + chan_index),
18139 + incr);
18140 +}
18141 +
18142 +/*
18143 + * Generate a new software session.
18144 + */
18145 +static int
18146 +pasemi_newsession(device_t dev, u_int32_t *sidp, struct cryptoini *cri)
18147 +{
18148 + struct cryptoini *c, *encini = NULL, *macini = NULL;
18149 + struct pasemi_softc *sc = device_get_softc(dev);
18150 + struct pasemi_session *ses = NULL, **sespp;
18151 + int sesn, blksz = 0;
18152 + u64 ccmd = 0;
18153 + unsigned long flags;
18154 + struct pasemi_desc init_desc;
18155 + struct pasemi_fnu_txring *txring;
18156 +
18157 + DPRINTF("%s()\n", __FUNCTION__);
18158 + if (sidp == NULL || cri == NULL || sc == NULL) {
18159 + DPRINTF("%s,%d - EINVAL\n", __FILE__, __LINE__);
18160 + return -EINVAL;
18161 + }
18162 + for (c = cri; c != NULL; c = c->cri_next) {
18163 + if (ALG_IS_SIG(c->cri_alg)) {
18164 + if (macini)
18165 + return -EINVAL;
18166 + macini = c;
18167 + } else if (ALG_IS_CIPHER(c->cri_alg)) {
18168 + if (encini)
18169 + return -EINVAL;
18170 + encini = c;
18171 + } else {
18172 + DPRINTF("UNKNOWN c->cri_alg %d\n", c->cri_alg);
18173 + return -EINVAL;
18174 + }
18175 + }
18176 + if (encini == NULL && macini == NULL)
18177 + return -EINVAL;
18178 + if (encini) {
18179 + /* validate key length */
18180 + switch (encini->cri_alg) {
18181 + case CRYPTO_DES_CBC:
18182 + if (encini->cri_klen != 64)
18183 + return -EINVAL;
18184 + ccmd = DMA_CALGO_DES;
18185 + break;
18186 + case CRYPTO_3DES_CBC:
18187 + if (encini->cri_klen != 192)
18188 + return -EINVAL;
18189 + ccmd = DMA_CALGO_3DES;
18190 + break;
18191 + case CRYPTO_AES_CBC:
18192 + if (encini->cri_klen != 128 &&
18193 + encini->cri_klen != 192 &&
18194 + encini->cri_klen != 256)
18195 + return -EINVAL;
18196 + ccmd = DMA_CALGO_AES;
18197 + break;
18198 + case CRYPTO_ARC4:
18199 + if (encini->cri_klen != 128)
18200 + return -EINVAL;
18201 + ccmd = DMA_CALGO_ARC;
18202 + break;
18203 + default:
18204 + DPRINTF("UNKNOWN encini->cri_alg %d\n",
18205 + encini->cri_alg);
18206 + return -EINVAL;
18207 + }
18208 + }
18209 +
18210 + if (macini) {
18211 + switch (macini->cri_alg) {
18212 + case CRYPTO_MD5:
18213 + case CRYPTO_MD5_HMAC:
18214 + blksz = 16;
18215 + break;
18216 + case CRYPTO_SHA1:
18217 + case CRYPTO_SHA1_HMAC:
18218 + blksz = 20;
18219 + break;
18220 + default:
18221 + DPRINTF("UNKNOWN macini->cri_alg %d\n",
18222 + macini->cri_alg);
18223 + return -EINVAL;
18224 + }
18225 + if (((macini->cri_klen + 7) / 8) > blksz) {
18226 + DPRINTF("key length %d bigger than blksize %d not supported\n",
18227 + ((macini->cri_klen + 7) / 8), blksz);
18228 + return -EINVAL;
18229 + }
18230 + }
18231 +
18232 + for (sesn = 0; sesn < sc->sc_nsessions; sesn++) {
18233 + if (sc->sc_sessions[sesn] == NULL) {
18234 + sc->sc_sessions[sesn] = (struct pasemi_session *)
18235 + kzalloc(sizeof(struct pasemi_session), GFP_ATOMIC);
18236 + ses = sc->sc_sessions[sesn];
18237 + break;
18238 + } else if (sc->sc_sessions[sesn]->used == 0) {
18239 + ses = sc->sc_sessions[sesn];
18240 + break;
18241 + }
18242 + }
18243 +
18244 + if (ses == NULL) {
18245 + sespp = (struct pasemi_session **)
18246 + kzalloc(sc->sc_nsessions * 2 *
18247 + sizeof(struct pasemi_session *), GFP_ATOMIC);
18248 + if (sespp == NULL)
18249 + return -ENOMEM;
18250 + memcpy(sespp, sc->sc_sessions,
18251 + sc->sc_nsessions * sizeof(struct pasemi_session *));
18252 + kfree(sc->sc_sessions);
18253 + sc->sc_sessions = sespp;
18254 + sesn = sc->sc_nsessions;
18255 + ses = sc->sc_sessions[sesn] = (struct pasemi_session *)
18256 + kzalloc(sizeof(struct pasemi_session), GFP_ATOMIC);
18257 + if (ses == NULL)
18258 + return -ENOMEM;
18259 + sc->sc_nsessions *= 2;
18260 + }
18261 +
18262 + ses->used = 1;
18263 +
18264 + ses->dma_addr = pci_map_single(sc->dma_pdev, (void *) ses->civ,
18265 + sizeof(struct pasemi_session), DMA_TO_DEVICE);
18266 +
18267 + /* enter the channel scheduler */
18268 + spin_lock_irqsave(&sc->sc_chnlock, flags);
18269 +
18270 + /* ARC4 has to be processed by the even channel */
18271 + if (encini && (encini->cri_alg == CRYPTO_ARC4))
18272 + ses->chan = sc->sc_lastchn & ~1;
18273 + else
18274 + ses->chan = sc->sc_lastchn;
18275 + sc->sc_lastchn = (sc->sc_lastchn + 1) % sc->sc_num_channels;
18276 +
18277 + spin_unlock_irqrestore(&sc->sc_chnlock, flags);
18278 +
18279 + txring = &sc->tx[ses->chan];
18280 +
18281 + if (encini) {
18282 + ses->ccmd = ccmd;
18283 +
18284 + /* get an IV */
18285 + /* XXX may read fewer than requested */
18286 + get_random_bytes(ses->civ, sizeof(ses->civ));
18287 +
18288 + ses->keysz = (encini->cri_klen - 63) / 64;
18289 + memcpy(ses->key, encini->cri_key, (ses->keysz + 1) * 8);
18290 +
18291 + pasemi_desc_start(&init_desc,
18292 + XCT_CTRL_HDR(ses->chan, (encini && macini) ? 0x68 : 0x40, DMA_FN_CIV0));
18293 + pasemi_desc_build(&init_desc,
18294 + XCT_FUN_SRC_PTR((encini && macini) ? 0x68 : 0x40, ses->dma_addr));
18295 + }
18296 + if (macini) {
18297 + if (macini->cri_alg == CRYPTO_MD5_HMAC ||
18298 + macini->cri_alg == CRYPTO_SHA1_HMAC)
18299 + memcpy(ses->hkey, macini->cri_key, blksz);
18300 + else {
18301 + /* Load initialization constants(RFC 1321, 3174) */
18302 + ses->hiv[0] = 0x67452301efcdab89ULL;
18303 + ses->hiv[1] = 0x98badcfe10325476ULL;
18304 + ses->hiv[2] = 0xc3d2e1f000000000ULL;
18305 + }
18306 + ses->hseq = 0ULL;
18307 + }
18308 +
18309 + spin_lock_irqsave(&txring->fill_lock, flags);
18310 +
18311 + if (((txring->next_to_fill + pasemi_desc_size(&init_desc)) -
18312 + txring->next_to_clean) > TX_RING_SIZE) {
18313 + spin_unlock_irqrestore(&txring->fill_lock, flags);
18314 + return ERESTART;
18315 + }
18316 +
18317 + if (encini) {
18318 + pasemi_ring_add_desc(txring, &init_desc, NULL);
18319 + pasemi_ring_incr(sc, ses->chan,
18320 + pasemi_desc_size(&init_desc));
18321 + }
18322 +
18323 + txring->sesn = sesn;
18324 + spin_unlock_irqrestore(&txring->fill_lock, flags);
18325 +
18326 + *sidp = PASEMI_SID(sesn);
18327 + return 0;
18328 +}
18329 +
18330 +/*
18331 + * Deallocate a session.
18332 + */
18333 +static int
18334 +pasemi_freesession(device_t dev, u_int64_t tid)
18335 +{
18336 + struct pasemi_softc *sc = device_get_softc(dev);
18337 + int session;
18338 + u_int32_t sid = ((u_int32_t) tid) & 0xffffffff;
18339 +
18340 + DPRINTF("%s()\n", __FUNCTION__);
18341 +
18342 + if (sc == NULL)
18343 + return -EINVAL;
18344 + session = PASEMI_SESSION(sid);
18345 + if (session >= sc->sc_nsessions || !sc->sc_sessions[session])
18346 + return -EINVAL;
18347 +
18348 + pci_unmap_single(sc->dma_pdev,
18349 + sc->sc_sessions[session]->dma_addr,
18350 + sizeof(struct pasemi_session), DMA_TO_DEVICE);
18351 + memset(sc->sc_sessions[session], 0,
18352 + sizeof(struct pasemi_session));
18353 +
18354 + return 0;
18355 +}
18356 +
18357 +static int
18358 +pasemi_process(device_t dev, struct cryptop *crp, int hint)
18359 +{
18360 +
18361 + int err = 0, ivsize, srclen = 0, reinit = 0, reinit_size = 0, chsel;
18362 + struct pasemi_softc *sc = device_get_softc(dev);
18363 + struct cryptodesc *crd1, *crd2, *maccrd, *enccrd;
18364 + caddr_t ivp;
18365 + struct pasemi_desc init_desc, work_desc;
18366 + struct pasemi_session *ses;
18367 + struct sk_buff *skb;
18368 + struct uio *uiop;
18369 + unsigned long flags;
18370 + struct pasemi_fnu_txring *txring;
18371 +
18372 + DPRINTF("%s()\n", __FUNCTION__);
18373 +
18374 + if (crp == NULL || crp->crp_callback == NULL || sc == NULL)
18375 + return -EINVAL;
18376 +
18377 + crp->crp_etype = 0;
18378 + if (PASEMI_SESSION(crp->crp_sid) >= sc->sc_nsessions)
18379 + return -EINVAL;
18380 +
18381 + ses = sc->sc_sessions[PASEMI_SESSION(crp->crp_sid)];
18382 +
18383 + crd1 = crp->crp_desc;
18384 + if (crd1 == NULL) {
18385 + err = -EINVAL;
18386 + goto errout;
18387 + }
18388 + crd2 = crd1->crd_next;
18389 +
18390 + if (ALG_IS_SIG(crd1->crd_alg)) {
18391 + maccrd = crd1;
18392 + if (crd2 == NULL)
18393 + enccrd = NULL;
18394 + else if (ALG_IS_CIPHER(crd2->crd_alg) &&
18395 + (crd2->crd_flags & CRD_F_ENCRYPT) == 0)
18396 + enccrd = crd2;
18397 + else
18398 + goto erralg;
18399 + } else if (ALG_IS_CIPHER(crd1->crd_alg)) {
18400 + enccrd = crd1;
18401 + if (crd2 == NULL)
18402 + maccrd = NULL;
18403 + else if (ALG_IS_SIG(crd2->crd_alg) &&
18404 + (crd1->crd_flags & CRD_F_ENCRYPT))
18405 + maccrd = crd2;
18406 + else
18407 + goto erralg;
18408 + } else
18409 + goto erralg;
18410 +
18411 + chsel = ses->chan;
18412 +
18413 + txring = &sc->tx[chsel];
18414 +
18415 + if (enccrd && !maccrd) {
18416 + if (enccrd->crd_alg == CRYPTO_ARC4)
18417 + reinit = 1;
18418 + reinit_size = 0x40;
18419 + srclen = crp->crp_ilen;
18420 +
18421 + pasemi_desc_start(&work_desc, XCT_FUN_O | XCT_FUN_I
18422 + | XCT_FUN_FUN(chsel));
18423 + if (enccrd->crd_flags & CRD_F_ENCRYPT)
18424 + pasemi_desc_hdr(&work_desc, XCT_FUN_CRM_ENC);
18425 + else
18426 + pasemi_desc_hdr(&work_desc, XCT_FUN_CRM_DEC);
18427 + } else if (enccrd && maccrd) {
18428 + if (enccrd->crd_alg == CRYPTO_ARC4)
18429 + reinit = 1;
18430 + reinit_size = 0x68;
18431 +
18432 + if (enccrd->crd_flags & CRD_F_ENCRYPT) {
18433 + /* Encrypt -> Authenticate */
18434 + pasemi_desc_start(&work_desc, XCT_FUN_O | XCT_FUN_I | XCT_FUN_CRM_ENC_SIG
18435 + | XCT_FUN_A | XCT_FUN_FUN(chsel));
18436 + srclen = maccrd->crd_skip + maccrd->crd_len;
18437 + } else {
18438 + /* Authenticate -> Decrypt */
18439 + pasemi_desc_start(&work_desc, XCT_FUN_O | XCT_FUN_I | XCT_FUN_CRM_SIG_DEC
18440 + | XCT_FUN_24BRES | XCT_FUN_FUN(chsel));
18441 + pasemi_desc_build(&work_desc, 0);
18442 + pasemi_desc_build(&work_desc, 0);
18443 + pasemi_desc_build(&work_desc, 0);
18444 + work_desc.postop = PASEMI_CHECK_SIG;
18445 + srclen = crp->crp_ilen;
18446 + }
18447 +
18448 + pasemi_desc_hdr(&work_desc, XCT_FUN_SHL(maccrd->crd_skip / 4));
18449 + pasemi_desc_hdr(&work_desc, XCT_FUN_CHL(enccrd->crd_skip - maccrd->crd_skip));
18450 + } else if (!enccrd && maccrd) {
18451 + srclen = maccrd->crd_len;
18452 +
18453 + pasemi_desc_start(&init_desc,
18454 + XCT_CTRL_HDR(chsel, 0x58, DMA_FN_HKEY0));
18455 + pasemi_desc_build(&init_desc,
18456 + XCT_FUN_SRC_PTR(0x58, ((struct pasemi_session *)ses->dma_addr)->hkey));
18457 +
18458 + pasemi_desc_start(&work_desc, XCT_FUN_O | XCT_FUN_I | XCT_FUN_CRM_SIG
18459 + | XCT_FUN_A | XCT_FUN_FUN(chsel));
18460 + }
18461 +
18462 + if (enccrd) {
18463 + switch (enccrd->crd_alg) {
18464 + case CRYPTO_3DES_CBC:
18465 + pasemi_desc_hdr(&work_desc, XCT_FUN_ALG_3DES |
18466 + XCT_FUN_BCM_CBC);
18467 + ivsize = sizeof(u64);
18468 + break;
18469 + case CRYPTO_DES_CBC:
18470 + pasemi_desc_hdr(&work_desc, XCT_FUN_ALG_DES |
18471 + XCT_FUN_BCM_CBC);
18472 + ivsize = sizeof(u64);
18473 + break;
18474 + case CRYPTO_AES_CBC:
18475 + pasemi_desc_hdr(&work_desc, XCT_FUN_ALG_AES |
18476 + XCT_FUN_BCM_CBC);
18477 + ivsize = 2 * sizeof(u64);
18478 + break;
18479 + case CRYPTO_ARC4:
18480 + pasemi_desc_hdr(&work_desc, XCT_FUN_ALG_ARC);
18481 + ivsize = 0;
18482 + break;
18483 + default:
18484 + printk(DRV_NAME ": unimplemented enccrd->crd_alg %d\n",
18485 + enccrd->crd_alg);
18486 + err = -EINVAL;
18487 + goto errout;
18488 + }
18489 +
18490 + ivp = (ivsize == sizeof(u64)) ? (caddr_t) &ses->civ[1] : (caddr_t) &ses->civ[0];
18491 + if (enccrd->crd_flags & CRD_F_ENCRYPT) {
18492 + if (enccrd->crd_flags & CRD_F_IV_EXPLICIT)
18493 + memcpy(ivp, enccrd->crd_iv, ivsize);
18494 + /* If IV is not present in the buffer already, it has to be copied there */
18495 + if ((enccrd->crd_flags & CRD_F_IV_PRESENT) == 0)
18496 + crypto_copyback(crp->crp_flags, crp->crp_buf,
18497 + enccrd->crd_inject, ivsize, ivp);
18498 + } else {
18499 + if (enccrd->crd_flags & CRD_F_IV_EXPLICIT)
18500 + /* IV is provided expicitly in descriptor */
18501 + memcpy(ivp, enccrd->crd_iv, ivsize);
18502 + else
18503 + /* IV is provided in the packet */
18504 + crypto_copydata(crp->crp_flags, crp->crp_buf,
18505 + enccrd->crd_inject, ivsize,
18506 + ivp);
18507 + }
18508 + }
18509 +
18510 + if (maccrd) {
18511 + switch (maccrd->crd_alg) {
18512 + case CRYPTO_MD5:
18513 + pasemi_desc_hdr(&work_desc, XCT_FUN_SIG_MD5 |
18514 + XCT_FUN_HSZ((crp->crp_ilen - maccrd->crd_inject) / 4));
18515 + break;
18516 + case CRYPTO_SHA1:
18517 + pasemi_desc_hdr(&work_desc, XCT_FUN_SIG_SHA1 |
18518 + XCT_FUN_HSZ((crp->crp_ilen - maccrd->crd_inject) / 4));
18519 + break;
18520 + case CRYPTO_MD5_HMAC:
18521 + pasemi_desc_hdr(&work_desc, XCT_FUN_SIG_HMAC_MD5 |
18522 + XCT_FUN_HSZ((crp->crp_ilen - maccrd->crd_inject) / 4));
18523 + break;
18524 + case CRYPTO_SHA1_HMAC:
18525 + pasemi_desc_hdr(&work_desc, XCT_FUN_SIG_HMAC_SHA1 |
18526 + XCT_FUN_HSZ((crp->crp_ilen - maccrd->crd_inject) / 4));
18527 + break;
18528 + default:
18529 + printk(DRV_NAME ": unimplemented maccrd->crd_alg %d\n",
18530 + maccrd->crd_alg);
18531 + err = -EINVAL;
18532 + goto errout;
18533 + }
18534 + }
18535 +
18536 + if (crp->crp_flags & CRYPTO_F_SKBUF) {
18537 + /* using SKB buffers */
18538 + skb = (struct sk_buff *)crp->crp_buf;
18539 + if (skb_shinfo(skb)->nr_frags) {
18540 + printk(DRV_NAME ": skb frags unimplemented\n");
18541 + err = -EINVAL;
18542 + goto errout;
18543 + }
18544 + pasemi_desc_build(
18545 + &work_desc,
18546 + XCT_FUN_DST_PTR(skb->len, pci_map_single(
18547 + sc->dma_pdev, skb->data,
18548 + skb->len, DMA_TO_DEVICE)));
18549 + pasemi_desc_build(
18550 + &work_desc,
18551 + XCT_FUN_SRC_PTR(
18552 + srclen, pci_map_single(
18553 + sc->dma_pdev, skb->data,
18554 + srclen, DMA_TO_DEVICE)));
18555 + pasemi_desc_hdr(&work_desc, XCT_FUN_LLEN(srclen));
18556 + } else if (crp->crp_flags & CRYPTO_F_IOV) {
18557 + /* using IOV buffers */
18558 + uiop = (struct uio *)crp->crp_buf;
18559 + if (uiop->uio_iovcnt > 1) {
18560 + printk(DRV_NAME ": iov frags unimplemented\n");
18561 + err = -EINVAL;
18562 + goto errout;
18563 + }
18564 +
18565 + /* crp_olen is never set; always use crp_ilen */
18566 + pasemi_desc_build(
18567 + &work_desc,
18568 + XCT_FUN_DST_PTR(crp->crp_ilen, pci_map_single(
18569 + sc->dma_pdev,
18570 + uiop->uio_iov->iov_base,
18571 + crp->crp_ilen, DMA_TO_DEVICE)));
18572 + pasemi_desc_hdr(&work_desc, XCT_FUN_LLEN(srclen));
18573 +
18574 + pasemi_desc_build(
18575 + &work_desc,
18576 + XCT_FUN_SRC_PTR(srclen, pci_map_single(
18577 + sc->dma_pdev,
18578 + uiop->uio_iov->iov_base,
18579 + srclen, DMA_TO_DEVICE)));
18580 + } else {
18581 + /* using contig buffers */
18582 + pasemi_desc_build(
18583 + &work_desc,
18584 + XCT_FUN_DST_PTR(crp->crp_ilen, pci_map_single(
18585 + sc->dma_pdev,
18586 + crp->crp_buf,
18587 + crp->crp_ilen, DMA_TO_DEVICE)));
18588 + pasemi_desc_build(
18589 + &work_desc,
18590 + XCT_FUN_SRC_PTR(srclen, pci_map_single(
18591 + sc->dma_pdev,
18592 + crp->crp_buf, srclen,
18593 + DMA_TO_DEVICE)));
18594 + pasemi_desc_hdr(&work_desc, XCT_FUN_LLEN(srclen));
18595 + }
18596 +
18597 + spin_lock_irqsave(&txring->fill_lock, flags);
18598 +
18599 + if (txring->sesn != PASEMI_SESSION(crp->crp_sid)) {
18600 + txring->sesn = PASEMI_SESSION(crp->crp_sid);
18601 + reinit = 1;
18602 + }
18603 +
18604 + if (enccrd) {
18605 + pasemi_desc_start(&init_desc,
18606 + XCT_CTRL_HDR(chsel, reinit ? reinit_size : 0x10, DMA_FN_CIV0));
18607 + pasemi_desc_build(&init_desc,
18608 + XCT_FUN_SRC_PTR(reinit ? reinit_size : 0x10, ses->dma_addr));
18609 + }
18610 +
18611 + if (((txring->next_to_fill + pasemi_desc_size(&init_desc) +
18612 + pasemi_desc_size(&work_desc)) -
18613 + txring->next_to_clean) > TX_RING_SIZE) {
18614 + spin_unlock_irqrestore(&txring->fill_lock, flags);
18615 + err = ERESTART;
18616 + goto errout;
18617 + }
18618 +
18619 + pasemi_ring_add_desc(txring, &init_desc, NULL);
18620 + pasemi_ring_add_desc(txring, &work_desc, crp);
18621 +
18622 + pasemi_ring_incr(sc, chsel,
18623 + pasemi_desc_size(&init_desc) +
18624 + pasemi_desc_size(&work_desc));
18625 +
18626 + spin_unlock_irqrestore(&txring->fill_lock, flags);
18627 +
18628 + mod_timer(&txring->crypto_timer, jiffies + TIMER_INTERVAL);
18629 +
18630 + return 0;
18631 +
18632 +erralg:
18633 + printk(DRV_NAME ": unsupported algorithm or algorithm order alg1 %d alg2 %d\n",
18634 + crd1->crd_alg, crd2->crd_alg);
18635 + err = -EINVAL;
18636 +
18637 +errout:
18638 + if (err != ERESTART) {
18639 + crp->crp_etype = err;
18640 + crypto_done(crp);
18641 + }
18642 + return err;
18643 +}
18644 +
18645 +static int pasemi_clean_tx(struct pasemi_softc *sc, int chan)
18646 +{
18647 + int i, j, ring_idx;
18648 + struct pasemi_fnu_txring *ring = &sc->tx[chan];
18649 + u16 delta_cnt;
18650 + int flags, loops = 10;
18651 + int desc_size;
18652 + struct cryptop *crp;
18653 +
18654 + spin_lock_irqsave(&ring->clean_lock, flags);
18655 +
18656 + while ((delta_cnt = (dma_status->tx_sta[sc->base_chan + chan]
18657 + & PAS_STATUS_PCNT_M) - ring->total_pktcnt)
18658 + && loops--) {
18659 +
18660 + for (i = 0; i < delta_cnt; i++) {
18661 + desc_size = TX_DESC_INFO(ring, ring->next_to_clean).desc_size;
18662 + crp = TX_DESC_INFO(ring, ring->next_to_clean).cf_crp;
18663 + if (crp) {
18664 + ring_idx = 2 * (ring->next_to_clean & (TX_RING_SIZE-1));
18665 + if (TX_DESC_INFO(ring, ring->next_to_clean).desc_postop & PASEMI_CHECK_SIG) {
18666 + /* Need to make sure signature matched,
18667 + * if not - return error */
18668 + if (!(ring->desc[ring_idx + 1] & (1ULL << 63)))
18669 + crp->crp_etype = -EINVAL;
18670 + }
18671 + crypto_done(TX_DESC_INFO(ring,
18672 + ring->next_to_clean).cf_crp);
18673 + TX_DESC_INFO(ring, ring->next_to_clean).cf_crp = NULL;
18674 + pci_unmap_single(
18675 + sc->dma_pdev,
18676 + XCT_PTR_ADDR_LEN(ring->desc[ring_idx + 1]),
18677 + PCI_DMA_TODEVICE);
18678 +
18679 + ring->desc[ring_idx] = ring->desc[ring_idx + 1] = 0;
18680 +
18681 + ring->next_to_clean++;
18682 + for (j = 1; j < desc_size; j++) {
18683 + ring_idx = 2 *
18684 + (ring->next_to_clean &
18685 + (TX_RING_SIZE-1));
18686 + pci_unmap_single(
18687 + sc->dma_pdev,
18688 + XCT_PTR_ADDR_LEN(ring->desc[ring_idx]),
18689 + PCI_DMA_TODEVICE);
18690 + if (ring->desc[ring_idx + 1])
18691 + pci_unmap_single(
18692 + sc->dma_pdev,
18693 + XCT_PTR_ADDR_LEN(
18694 + ring->desc[
18695 + ring_idx + 1]),
18696 + PCI_DMA_TODEVICE);
18697 + ring->desc[ring_idx] =
18698 + ring->desc[ring_idx + 1] = 0;
18699 + ring->next_to_clean++;
18700 + }
18701 + } else {
18702 + for (j = 0; j < desc_size; j++) {
18703 + ring_idx = 2 * (ring->next_to_clean & (TX_RING_SIZE-1));
18704 + ring->desc[ring_idx] =
18705 + ring->desc[ring_idx + 1] = 0;
18706 + ring->next_to_clean++;
18707 + }
18708 + }
18709 + }
18710 +
18711 + ring->total_pktcnt += delta_cnt;
18712 + }
18713 + spin_unlock_irqrestore(&ring->clean_lock, flags);
18714 +
18715 + return 0;
18716 +}
18717 +
18718 +static void sweepup_tx(struct pasemi_softc *sc)
18719 +{
18720 + int i;
18721 +
18722 + for (i = 0; i < sc->sc_num_channels; i++)
18723 + pasemi_clean_tx(sc, i);
18724 +}
18725 +
18726 +static irqreturn_t pasemi_intr(int irq, void *arg, struct pt_regs *regs)
18727 +{
18728 + struct pasemi_softc *sc = arg;
18729 + unsigned int reg;
18730 + int chan = irq - sc->base_irq;
18731 + int chan_index = sc->base_chan + chan;
18732 + u64 stat = dma_status->tx_sta[chan_index];
18733 +
18734 + DPRINTF("%s()\n", __FUNCTION__);
18735 +
18736 + if (!(stat & PAS_STATUS_CAUSE_M))
18737 + return IRQ_NONE;
18738 +
18739 + pasemi_clean_tx(sc, chan);
18740 +
18741 + stat = dma_status->tx_sta[chan_index];
18742 +
18743 + reg = PAS_IOB_DMA_TXCH_RESET_PINTC |
18744 + PAS_IOB_DMA_TXCH_RESET_PCNT(sc->tx[chan].total_pktcnt);
18745 +
18746 + if (stat & PAS_STATUS_SOFT)
18747 + reg |= PAS_IOB_DMA_RXCH_RESET_SINTC;
18748 +
18749 + out_le32(sc->iob_regs + PAS_IOB_DMA_TXCH_RESET(chan_index), reg);
18750 +
18751 +
18752 + return IRQ_HANDLED;
18753 +}
18754 +
18755 +static int pasemi_dma_setup_tx_resources(struct pasemi_softc *sc, int chan)
18756 +{
18757 + u32 val;
18758 + int chan_index = chan + sc->base_chan;
18759 + int ret;
18760 + struct pasemi_fnu_txring *ring;
18761 +
18762 + ring = &sc->tx[chan];
18763 +
18764 + spin_lock_init(&ring->fill_lock);
18765 + spin_lock_init(&ring->clean_lock);
18766 +
18767 + ring->desc_info = kzalloc(sizeof(struct pasemi_desc_info) *
18768 + TX_RING_SIZE, GFP_KERNEL);
18769 + if (!ring->desc_info)
18770 + return -ENOMEM;
18771 +
18772 + /* Allocate descriptors */
18773 + ring->desc = dma_alloc_coherent(&sc->dma_pdev->dev,
18774 + TX_RING_SIZE *
18775 + 2 * sizeof(u64),
18776 + &ring->dma, GFP_KERNEL);
18777 + if (!ring->desc)
18778 + return -ENOMEM;
18779 +
18780 + memset((void *) ring->desc, 0, TX_RING_SIZE * 2 * sizeof(u64));
18781 +
18782 + out_le32(sc->iob_regs + PAS_IOB_DMA_TXCH_RESET(chan_index), 0x30);
18783 +
18784 + ring->total_pktcnt = 0;
18785 +
18786 + out_le32(sc->dma_regs + PAS_DMA_TXCHAN_BASEL(chan_index),
18787 + PAS_DMA_TXCHAN_BASEL_BRBL(ring->dma));
18788 +
18789 + val = PAS_DMA_TXCHAN_BASEU_BRBH(ring->dma >> 32);
18790 + val |= PAS_DMA_TXCHAN_BASEU_SIZ(TX_RING_SIZE >> 2);
18791 +
18792 + out_le32(sc->dma_regs + PAS_DMA_TXCHAN_BASEU(chan_index), val);
18793 +
18794 + out_le32(sc->dma_regs + PAS_DMA_TXCHAN_CFG(chan_index),
18795 + PAS_DMA_TXCHAN_CFG_TY_FUNC |
18796 + PAS_DMA_TXCHAN_CFG_TATTR(chan) |
18797 + PAS_DMA_TXCHAN_CFG_WT(2));
18798 +
18799 + /* enable tx channel */
18800 + out_le32(sc->dma_regs +
18801 + PAS_DMA_TXCHAN_TCMDSTA(chan_index),
18802 + PAS_DMA_TXCHAN_TCMDSTA_EN);
18803 +
18804 + out_le32(sc->iob_regs + PAS_IOB_DMA_TXCH_CFG(chan_index),
18805 + PAS_IOB_DMA_TXCH_CFG_CNTTH(1000));
18806 +
18807 + ring->next_to_fill = 0;
18808 + ring->next_to_clean = 0;
18809 +
18810 + snprintf(ring->irq_name, sizeof(ring->irq_name),
18811 + "%s%d", "crypto", chan);
18812 +
18813 + ring->irq = irq_create_mapping(NULL, sc->base_irq + chan);
18814 + ret = request_irq(ring->irq, (irq_handler_t)
18815 + pasemi_intr, IRQF_DISABLED, ring->irq_name, sc);
18816 + if (ret) {
18817 + printk(KERN_ERR DRV_NAME ": failed to hook irq %d ret %d\n",
18818 + ring->irq, ret);
18819 + ring->irq = -1;
18820 + return ret;
18821 + }
18822 +
18823 + setup_timer(&ring->crypto_timer, (void *) sweepup_tx, (unsigned long) sc);
18824 +
18825 + return 0;
18826 +}
18827 +
18828 +static device_method_t pasemi_methods = {
18829 + /* crypto device methods */
18830 + DEVMETHOD(cryptodev_newsession, pasemi_newsession),
18831 + DEVMETHOD(cryptodev_freesession, pasemi_freesession),
18832 + DEVMETHOD(cryptodev_process, pasemi_process),
18833 +};
18834 +
18835 +/* Set up the crypto device structure, private data,
18836 + * and anything else we need before we start */
18837 +
18838 +static int __devinit
18839 +pasemi_dma_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
18840 +{
18841 + struct pasemi_softc *sc;
18842 + int ret, i;
18843 +
18844 + DPRINTF(KERN_ERR "%s()\n", __FUNCTION__);
18845 +
18846 + sc = kzalloc(sizeof(*sc), GFP_KERNEL);
18847 + if (!sc)
18848 + return -ENOMEM;
18849 +
18850 + softc_device_init(sc, DRV_NAME, 1, pasemi_methods);
18851 +
18852 + pci_set_drvdata(pdev, sc);
18853 +
18854 + spin_lock_init(&sc->sc_chnlock);
18855 +
18856 + sc->sc_sessions = (struct pasemi_session **)
18857 + kzalloc(PASEMI_INITIAL_SESSIONS *
18858 + sizeof(struct pasemi_session *), GFP_ATOMIC);
18859 + if (sc->sc_sessions == NULL) {
18860 + ret = -ENOMEM;
18861 + goto out;
18862 + }
18863 +
18864 + sc->sc_nsessions = PASEMI_INITIAL_SESSIONS;
18865 + sc->sc_lastchn = 0;
18866 + sc->base_irq = pdev->irq + 6;
18867 + sc->base_chan = 6;
18868 + sc->sc_cid = -1;
18869 + sc->dma_pdev = pdev;
18870 +
18871 + sc->iob_pdev = pci_get_device(PCI_VENDOR_ID_PASEMI, 0xa001, NULL);
18872 + if (!sc->iob_pdev) {
18873 + dev_err(&pdev->dev, "Can't find I/O Bridge\n");
18874 + ret = -ENODEV;
18875 + goto out;
18876 + }
18877 +
18878 + /* This is hardcoded and ugly, but we have some firmware versions
18879 + * who don't provide the register space in the device tree. Luckily
18880 + * they are at well-known locations so we can just do the math here.
18881 + */
18882 + sc->dma_regs =
18883 + ioremap(0xe0000000 + (sc->dma_pdev->devfn << 12), 0x2000);
18884 + sc->iob_regs =
18885 + ioremap(0xe0000000 + (sc->iob_pdev->devfn << 12), 0x2000);
18886 + if (!sc->dma_regs || !sc->iob_regs) {
18887 + dev_err(&pdev->dev, "Can't map registers\n");
18888 + ret = -ENODEV;
18889 + goto out;
18890 + }
18891 +
18892 + dma_status = __ioremap(0xfd800000, 0x1000, 0);
18893 + if (!dma_status) {
18894 + ret = -ENODEV;
18895 + dev_err(&pdev->dev, "Can't map dmastatus space\n");
18896 + goto out;
18897 + }
18898 +
18899 + sc->tx = (struct pasemi_fnu_txring *)
18900 + kzalloc(sizeof(struct pasemi_fnu_txring)
18901 + * 8, GFP_KERNEL);
18902 + if (!sc->tx) {
18903 + ret = -ENOMEM;
18904 + goto out;
18905 + }
18906 +
18907 + /* Initialize the h/w */
18908 + out_le32(sc->dma_regs + PAS_DMA_COM_CFG,
18909 + (in_le32(sc->dma_regs + PAS_DMA_COM_CFG) |
18910 + PAS_DMA_COM_CFG_FWF));
18911 + out_le32(sc->dma_regs + PAS_DMA_COM_TXCMD, PAS_DMA_COM_TXCMD_EN);
18912 +
18913 + for (i = 0; i < PASEMI_FNU_CHANNELS; i++) {
18914 + sc->sc_num_channels++;
18915 + ret = pasemi_dma_setup_tx_resources(sc, i);
18916 + if (ret)
18917 + goto out;
18918 + }
18919 +
18920 + sc->sc_cid = crypto_get_driverid(softc_get_device(sc),
18921 + CRYPTOCAP_F_HARDWARE);
18922 + if (sc->sc_cid < 0) {
18923 + printk(KERN_ERR DRV_NAME ": could not get crypto driver id\n");
18924 + ret = -ENXIO;
18925 + goto out;
18926 + }
18927 +
18928 + /* register algorithms with the framework */
18929 + printk(DRV_NAME ":");
18930 +
18931 + crypto_register(sc->sc_cid, CRYPTO_DES_CBC, 0, 0);
18932 + crypto_register(sc->sc_cid, CRYPTO_3DES_CBC, 0, 0);
18933 + crypto_register(sc->sc_cid, CRYPTO_AES_CBC, 0, 0);
18934 + crypto_register(sc->sc_cid, CRYPTO_ARC4, 0, 0);
18935 + crypto_register(sc->sc_cid, CRYPTO_SHA1, 0, 0);
18936 + crypto_register(sc->sc_cid, CRYPTO_MD5, 0, 0);
18937 + crypto_register(sc->sc_cid, CRYPTO_SHA1_HMAC, 0, 0);
18938 + crypto_register(sc->sc_cid, CRYPTO_MD5_HMAC, 0, 0);
18939 +
18940 + return 0;
18941 +
18942 +out:
18943 + pasemi_dma_remove(pdev);
18944 + return ret;
18945 +}
18946 +
18947 +#define MAX_RETRIES 5000
18948 +
18949 +static void pasemi_free_tx_resources(struct pasemi_softc *sc, int chan)
18950 +{
18951 + struct pasemi_fnu_txring *ring = &sc->tx[chan];
18952 + int chan_index = chan + sc->base_chan;
18953 + int retries;
18954 + u32 stat;
18955 +
18956 + /* Stop the channel */
18957 + out_le32(sc->dma_regs +
18958 + PAS_DMA_TXCHAN_TCMDSTA(chan_index),
18959 + PAS_DMA_TXCHAN_TCMDSTA_ST);
18960 +
18961 + for (retries = 0; retries < MAX_RETRIES; retries++) {
18962 + stat = in_le32(sc->dma_regs +
18963 + PAS_DMA_TXCHAN_TCMDSTA(chan_index));
18964 + if (!(stat & PAS_DMA_TXCHAN_TCMDSTA_ACT))
18965 + break;
18966 + cond_resched();
18967 + }
18968 +
18969 + if (stat & PAS_DMA_TXCHAN_TCMDSTA_ACT)
18970 + dev_err(&sc->dma_pdev->dev, "Failed to stop tx channel %d\n",
18971 + chan_index);
18972 +
18973 + /* Disable the channel */
18974 + out_le32(sc->dma_regs +
18975 + PAS_DMA_TXCHAN_TCMDSTA(chan_index),
18976 + 0);
18977 +
18978 + if (ring->desc_info)
18979 + kfree((void *) ring->desc_info);
18980 + if (ring->desc)
18981 + dma_free_coherent(&sc->dma_pdev->dev,
18982 + TX_RING_SIZE *
18983 + 2 * sizeof(u64),
18984 + (void *) ring->desc, ring->dma);
18985 + if (ring->irq != -1)
18986 + free_irq(ring->irq, sc);
18987 +
18988 + del_timer(&ring->crypto_timer);
18989 +}
18990 +
18991 +static void __devexit pasemi_dma_remove(struct pci_dev *pdev)
18992 +{
18993 + struct pasemi_softc *sc = pci_get_drvdata(pdev);
18994 + int i;
18995 +
18996 + DPRINTF("%s()\n", __FUNCTION__);
18997 +
18998 + if (sc->sc_cid >= 0) {
18999 + crypto_unregister_all(sc->sc_cid);
19000 + }
19001 +
19002 + if (sc->tx) {
19003 + for (i = 0; i < sc->sc_num_channels; i++)
19004 + pasemi_free_tx_resources(sc, i);
19005 +
19006 + kfree(sc->tx);
19007 + }
19008 + if (sc->sc_sessions) {
19009 + for (i = 0; i < sc->sc_nsessions; i++)
19010 + kfree(sc->sc_sessions[i]);
19011 + kfree(sc->sc_sessions);
19012 + }
19013 + if (sc->iob_pdev)
19014 + pci_dev_put(sc->iob_pdev);
19015 + if (sc->dma_regs)
19016 + iounmap(sc->dma_regs);
19017 + if (sc->iob_regs)
19018 + iounmap(sc->iob_regs);
19019 + kfree(sc);
19020 +}
19021 +
19022 +static struct pci_device_id pasemi_dma_pci_tbl[] = {
19023 + { PCI_DEVICE(PCI_VENDOR_ID_PASEMI, 0xa007) },
19024 +};
19025 +
19026 +MODULE_DEVICE_TABLE(pci, pasemi_dma_pci_tbl);
19027 +
19028 +static struct pci_driver pasemi_dma_driver = {
19029 + .name = "pasemi_dma",
19030 + .id_table = pasemi_dma_pci_tbl,
19031 + .probe = pasemi_dma_probe,
19032 + .remove = __devexit_p(pasemi_dma_remove),
19033 +};
19034 +
19035 +static void __exit pasemi_dma_cleanup_module(void)
19036 +{
19037 + pci_unregister_driver(&pasemi_dma_driver);
19038 + __iounmap(dma_status);
19039 + dma_status = NULL;
19040 +}
19041 +
19042 +int pasemi_dma_init_module(void)
19043 +{
19044 + return pci_register_driver(&pasemi_dma_driver);
19045 +}
19046 +
19047 +module_init(pasemi_dma_init_module);
19048 +module_exit(pasemi_dma_cleanup_module);
19049 +
19050 +MODULE_LICENSE("Dual BSD/GPL");
19051 +MODULE_AUTHOR("Egor Martovetsky egor@pasemi.com");
19052 +MODULE_DESCRIPTION("OCF driver for PA Semi PWRficient DMA Crypto Engine");
19053 --- /dev/null
19054 +++ b/crypto/ocf/pasemi/pasemi_fnu.h
19055 @@ -0,0 +1,410 @@
19056 +/*
19057 + * Copyright (C) 2007 PA Semi, Inc
19058 + *
19059 + * Driver for the PA Semi PWRficient DMA Crypto Engine, soft state and
19060 + * hardware register layouts.
19061 + *
19062 + * This program is free software; you can redistribute it and/or modify
19063 + * it under the terms of the GNU General Public License version 2 as
19064 + * published by the Free Software Foundation.
19065 + *
19066 + * This program is distributed in the hope that it will be useful,
19067 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
19068 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19069 + * GNU General Public License for more details.
19070 + *
19071 + * You should have received a copy of the GNU General Public License
19072 + * along with this program; if not, write to the Free Software
19073 + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19074 + */
19075 +
19076 +#ifndef PASEMI_FNU_H
19077 +#define PASEMI_FNU_H
19078 +
19079 +#include <linux/spinlock.h>
19080 +
19081 +#define PASEMI_SESSION(sid) ((sid) & 0xffffffff)
19082 +#define PASEMI_SID(sesn) ((sesn) & 0xffffffff)
19083 +#define DPRINTF(a...) if (debug) { printk(DRV_NAME ": " a); }
19084 +
19085 +/* Must be a power of two */
19086 +#define RX_RING_SIZE 512
19087 +#define TX_RING_SIZE 512
19088 +#define TX_DESC(ring, num) ((ring)->desc[2 * (num & (TX_RING_SIZE-1))])
19089 +#define TX_DESC_INFO(ring, num) ((ring)->desc_info[(num) & (TX_RING_SIZE-1)])
19090 +#define MAX_DESC_SIZE 8
19091 +#define PASEMI_INITIAL_SESSIONS 10
19092 +#define PASEMI_FNU_CHANNELS 8
19093 +
19094 +/* DMA descriptor */
19095 +struct pasemi_desc {
19096 + u64 quad[2*MAX_DESC_SIZE];
19097 + int quad_cnt;
19098 + int size;
19099 + int postop;
19100 +};
19101 +
19102 +/*
19103 + * Holds per descriptor data
19104 + */
19105 +struct pasemi_desc_info {
19106 + int desc_size;
19107 + int desc_postop;
19108 +#define PASEMI_CHECK_SIG 0x1
19109 +
19110 + struct cryptop *cf_crp;
19111 +};
19112 +
19113 +/*
19114 + * Holds per channel data
19115 + */
19116 +struct pasemi_fnu_txring {
19117 + volatile u64 *desc;
19118 + volatile struct
19119 + pasemi_desc_info *desc_info;
19120 + dma_addr_t dma;
19121 + struct timer_list crypto_timer;
19122 + spinlock_t fill_lock;
19123 + spinlock_t clean_lock;
19124 + unsigned int next_to_fill;
19125 + unsigned int next_to_clean;
19126 + u16 total_pktcnt;
19127 + int irq;
19128 + int sesn;
19129 + char irq_name[10];
19130 +};
19131 +
19132 +/*
19133 + * Holds data specific to a single pasemi device.
19134 + */
19135 +struct pasemi_softc {
19136 + softc_device_decl sc_cdev;
19137 + struct pci_dev *dma_pdev; /* device backpointer */
19138 + struct pci_dev *iob_pdev; /* device backpointer */
19139 + void __iomem *dma_regs;
19140 + void __iomem *iob_regs;
19141 + int base_irq;
19142 + int base_chan;
19143 + int32_t sc_cid; /* crypto tag */
19144 + int sc_nsessions;
19145 + struct pasemi_session **sc_sessions;
19146 + int sc_num_channels;/* number of crypto channels */
19147 +
19148 + /* pointer to the array of txring datastructures, one txring per channel */
19149 + struct pasemi_fnu_txring *tx;
19150 +
19151 + /*
19152 + * mutual exclusion for the channel scheduler
19153 + */
19154 + spinlock_t sc_chnlock;
19155 + /* last channel used, for now use round-robin to allocate channels */
19156 + int sc_lastchn;
19157 +};
19158 +
19159 +struct pasemi_session {
19160 + u64 civ[2];
19161 + u64 keysz;
19162 + u64 key[4];
19163 + u64 ccmd;
19164 + u64 hkey[4];
19165 + u64 hseq;
19166 + u64 giv[2];
19167 + u64 hiv[4];
19168 +
19169 + int used;
19170 + dma_addr_t dma_addr;
19171 + int chan;
19172 +};
19173 +
19174 +/* status register layout in IOB region, at 0xfd800000 */
19175 +struct pasdma_status {
19176 + u64 rx_sta[64];
19177 + u64 tx_sta[20];
19178 +};
19179 +
19180 +#define ALG_IS_CIPHER(alg) ((alg == CRYPTO_DES_CBC) || \
19181 + (alg == CRYPTO_3DES_CBC) || \
19182 + (alg == CRYPTO_AES_CBC) || \
19183 + (alg == CRYPTO_ARC4) || \
19184 + (alg == CRYPTO_NULL_CBC))
19185 +
19186 +#define ALG_IS_SIG(alg) ((alg == CRYPTO_MD5) || \
19187 + (alg == CRYPTO_MD5_HMAC) || \
19188 + (alg == CRYPTO_SHA1) || \
19189 + (alg == CRYPTO_SHA1_HMAC) || \
19190 + (alg == CRYPTO_NULL_HMAC))
19191 +
19192 +enum {
19193 + PAS_DMA_COM_TXCMD = 0x100, /* Transmit Command Register */
19194 + PAS_DMA_COM_TXSTA = 0x104, /* Transmit Status Register */
19195 + PAS_DMA_COM_RXCMD = 0x108, /* Receive Command Register */
19196 + PAS_DMA_COM_RXSTA = 0x10c, /* Receive Status Register */
19197 + PAS_DMA_COM_CFG = 0x114, /* DMA Configuration Register */
19198 +};
19199 +
19200 +/* All these registers live in the PCI configuration space for the DMA PCI
19201 + * device. Use the normal PCI config access functions for them.
19202 + */
19203 +
19204 +#define PAS_DMA_COM_CFG_FWF 0x18000000
19205 +
19206 +#define PAS_DMA_COM_TXCMD_EN 0x00000001 /* enable */
19207 +#define PAS_DMA_COM_TXSTA_ACT 0x00000001 /* active */
19208 +#define PAS_DMA_COM_RXCMD_EN 0x00000001 /* enable */
19209 +#define PAS_DMA_COM_RXSTA_ACT 0x00000001 /* active */
19210 +
19211 +#define _PAS_DMA_TXCHAN_STRIDE 0x20 /* Size per channel */
19212 +#define _PAS_DMA_TXCHAN_TCMDSTA 0x300 /* Command / Status */
19213 +#define _PAS_DMA_TXCHAN_CFG 0x304 /* Configuration */
19214 +#define _PAS_DMA_TXCHAN_DSCRBU 0x308 /* Descriptor BU Allocation */
19215 +#define _PAS_DMA_TXCHAN_INCR 0x310 /* Descriptor increment */
19216 +#define _PAS_DMA_TXCHAN_CNT 0x314 /* Descriptor count/offset */
19217 +#define _PAS_DMA_TXCHAN_BASEL 0x318 /* Descriptor ring base (low) */
19218 +#define _PAS_DMA_TXCHAN_BASEU 0x31c /* (high) */
19219 +#define PAS_DMA_TXCHAN_TCMDSTA(c) (0x300+(c)*_PAS_DMA_TXCHAN_STRIDE)
19220 +#define PAS_DMA_TXCHAN_TCMDSTA_EN 0x00000001 /* Enabled */
19221 +#define PAS_DMA_TXCHAN_TCMDSTA_ST 0x00000002 /* Stop interface */
19222 +#define PAS_DMA_TXCHAN_TCMDSTA_ACT 0x00010000 /* Active */
19223 +#define PAS_DMA_TXCHAN_CFG(c) (0x304+(c)*_PAS_DMA_TXCHAN_STRIDE)
19224 +#define PAS_DMA_TXCHAN_CFG_TY_FUNC 0x00000002 /* Type = interface */
19225 +#define PAS_DMA_TXCHAN_CFG_TY_IFACE 0x00000000 /* Type = interface */
19226 +#define PAS_DMA_TXCHAN_CFG_TATTR_M 0x0000003c
19227 +#define PAS_DMA_TXCHAN_CFG_TATTR_S 2
19228 +#define PAS_DMA_TXCHAN_CFG_TATTR(x) (((x) << PAS_DMA_TXCHAN_CFG_TATTR_S) & \
19229 + PAS_DMA_TXCHAN_CFG_TATTR_M)
19230 +#define PAS_DMA_TXCHAN_CFG_WT_M 0x000001c0
19231 +#define PAS_DMA_TXCHAN_CFG_WT_S 6
19232 +#define PAS_DMA_TXCHAN_CFG_WT(x) (((x) << PAS_DMA_TXCHAN_CFG_WT_S) & \
19233 + PAS_DMA_TXCHAN_CFG_WT_M)
19234 +#define PAS_DMA_TXCHAN_CFG_LPSQ_FAST 0x00000400
19235 +#define PAS_DMA_TXCHAN_CFG_LPDQ_FAST 0x00000800
19236 +#define PAS_DMA_TXCHAN_CFG_CF 0x00001000 /* Clean first line */
19237 +#define PAS_DMA_TXCHAN_CFG_CL 0x00002000 /* Clean last line */
19238 +#define PAS_DMA_TXCHAN_CFG_UP 0x00004000 /* update tx descr when sent */
19239 +#define PAS_DMA_TXCHAN_INCR(c) (0x310+(c)*_PAS_DMA_TXCHAN_STRIDE)
19240 +#define PAS_DMA_TXCHAN_BASEL(c) (0x318+(c)*_PAS_DMA_TXCHAN_STRIDE)
19241 +#define PAS_DMA_TXCHAN_BASEL_BRBL_M 0xffffffc0
19242 +#define PAS_DMA_TXCHAN_BASEL_BRBL_S 0
19243 +#define PAS_DMA_TXCHAN_BASEL_BRBL(x) (((x) << PAS_DMA_TXCHAN_BASEL_BRBL_S) & \
19244 + PAS_DMA_TXCHAN_BASEL_BRBL_M)
19245 +#define PAS_DMA_TXCHAN_BASEU(c) (0x31c+(c)*_PAS_DMA_TXCHAN_STRIDE)
19246 +#define PAS_DMA_TXCHAN_BASEU_BRBH_M 0x00000fff
19247 +#define PAS_DMA_TXCHAN_BASEU_BRBH_S 0
19248 +#define PAS_DMA_TXCHAN_BASEU_BRBH(x) (((x) << PAS_DMA_TXCHAN_BASEU_BRBH_S) & \
19249 + PAS_DMA_TXCHAN_BASEU_BRBH_M)
19250 +/* # of cache lines worth of buffer ring */
19251 +#define PAS_DMA_TXCHAN_BASEU_SIZ_M 0x3fff0000
19252 +#define PAS_DMA_TXCHAN_BASEU_SIZ_S 16 /* 0 = 16K */
19253 +#define PAS_DMA_TXCHAN_BASEU_SIZ(x) (((x) << PAS_DMA_TXCHAN_BASEU_SIZ_S) & \
19254 + PAS_DMA_TXCHAN_BASEU_SIZ_M)
19255 +
19256 +#define PAS_STATUS_PCNT_M 0x000000000000ffffull
19257 +#define PAS_STATUS_PCNT_S 0
19258 +#define PAS_STATUS_DCNT_M 0x00000000ffff0000ull
19259 +#define PAS_STATUS_DCNT_S 16
19260 +#define PAS_STATUS_BPCNT_M 0x0000ffff00000000ull
19261 +#define PAS_STATUS_BPCNT_S 32
19262 +#define PAS_STATUS_CAUSE_M 0xf000000000000000ull
19263 +#define PAS_STATUS_TIMER 0x1000000000000000ull
19264 +#define PAS_STATUS_ERROR 0x2000000000000000ull
19265 +#define PAS_STATUS_SOFT 0x4000000000000000ull
19266 +#define PAS_STATUS_INT 0x8000000000000000ull
19267 +
19268 +#define PAS_IOB_DMA_RXCH_CFG(i) (0x1100 + (i)*4)
19269 +#define PAS_IOB_DMA_RXCH_CFG_CNTTH_M 0x00000fff
19270 +#define PAS_IOB_DMA_RXCH_CFG_CNTTH_S 0
19271 +#define PAS_IOB_DMA_RXCH_CFG_CNTTH(x) (((x) << PAS_IOB_DMA_RXCH_CFG_CNTTH_S) & \
19272 + PAS_IOB_DMA_RXCH_CFG_CNTTH_M)
19273 +#define PAS_IOB_DMA_TXCH_CFG(i) (0x1200 + (i)*4)
19274 +#define PAS_IOB_DMA_TXCH_CFG_CNTTH_M 0x00000fff
19275 +#define PAS_IOB_DMA_TXCH_CFG_CNTTH_S 0
19276 +#define PAS_IOB_DMA_TXCH_CFG_CNTTH(x) (((x) << PAS_IOB_DMA_TXCH_CFG_CNTTH_S) & \
19277 + PAS_IOB_DMA_TXCH_CFG_CNTTH_M)
19278 +#define PAS_IOB_DMA_RXCH_STAT(i) (0x1300 + (i)*4)
19279 +#define PAS_IOB_DMA_RXCH_STAT_INTGEN 0x00001000
19280 +#define PAS_IOB_DMA_RXCH_STAT_CNTDEL_M 0x00000fff
19281 +#define PAS_IOB_DMA_RXCH_STAT_CNTDEL_S 0
19282 +#define PAS_IOB_DMA_RXCH_STAT_CNTDEL(x) (((x) << PAS_IOB_DMA_RXCH_STAT_CNTDEL_S) &\
19283 + PAS_IOB_DMA_RXCH_STAT_CNTDEL_M)
19284 +#define PAS_IOB_DMA_TXCH_STAT(i) (0x1400 + (i)*4)
19285 +#define PAS_IOB_DMA_TXCH_STAT_INTGEN 0x00001000
19286 +#define PAS_IOB_DMA_TXCH_STAT_CNTDEL_M 0x00000fff
19287 +#define PAS_IOB_DMA_TXCH_STAT_CNTDEL_S 0
19288 +#define PAS_IOB_DMA_TXCH_STAT_CNTDEL(x) (((x) << PAS_IOB_DMA_TXCH_STAT_CNTDEL_S) &\
19289 + PAS_IOB_DMA_TXCH_STAT_CNTDEL_M)
19290 +#define PAS_IOB_DMA_RXCH_RESET(i) (0x1500 + (i)*4)
19291 +#define PAS_IOB_DMA_RXCH_RESET_PCNT_M 0xffff0000
19292 +#define PAS_IOB_DMA_RXCH_RESET_PCNT_S 16
19293 +#define PAS_IOB_DMA_RXCH_RESET_PCNT(x) (((x) << PAS_IOB_DMA_RXCH_RESET_PCNT_S) & \
19294 + PAS_IOB_DMA_RXCH_RESET_PCNT_M)
19295 +#define PAS_IOB_DMA_RXCH_RESET_PCNTRST 0x00000020
19296 +#define PAS_IOB_DMA_RXCH_RESET_DCNTRST 0x00000010
19297 +#define PAS_IOB_DMA_RXCH_RESET_TINTC 0x00000008
19298 +#define PAS_IOB_DMA_RXCH_RESET_DINTC 0x00000004
19299 +#define PAS_IOB_DMA_RXCH_RESET_SINTC 0x00000002
19300 +#define PAS_IOB_DMA_RXCH_RESET_PINTC 0x00000001
19301 +#define PAS_IOB_DMA_TXCH_RESET(i) (0x1600 + (i)*4)
19302 +#define PAS_IOB_DMA_TXCH_RESET_PCNT_M 0xffff0000
19303 +#define PAS_IOB_DMA_TXCH_RESET_PCNT_S 16
19304 +#define PAS_IOB_DMA_TXCH_RESET_PCNT(x) (((x) << PAS_IOB_DMA_TXCH_RESET_PCNT_S) & \
19305 + PAS_IOB_DMA_TXCH_RESET_PCNT_M)
19306 +#define PAS_IOB_DMA_TXCH_RESET_PCNTRST 0x00000020
19307 +#define PAS_IOB_DMA_TXCH_RESET_DCNTRST 0x00000010
19308 +#define PAS_IOB_DMA_TXCH_RESET_TINTC 0x00000008
19309 +#define PAS_IOB_DMA_TXCH_RESET_DINTC 0x00000004
19310 +#define PAS_IOB_DMA_TXCH_RESET_SINTC 0x00000002
19311 +#define PAS_IOB_DMA_TXCH_RESET_PINTC 0x00000001
19312 +
19313 +#define PAS_IOB_DMA_COM_TIMEOUTCFG 0x1700
19314 +#define PAS_IOB_DMA_COM_TIMEOUTCFG_TCNT_M 0x00ffffff
19315 +#define PAS_IOB_DMA_COM_TIMEOUTCFG_TCNT_S 0
19316 +#define PAS_IOB_DMA_COM_TIMEOUTCFG_TCNT(x) (((x) << PAS_IOB_DMA_COM_TIMEOUTCFG_TCNT_S) & \
19317 + PAS_IOB_DMA_COM_TIMEOUTCFG_TCNT_M)
19318 +
19319 +/* Transmit descriptor fields */
19320 +#define XCT_MACTX_T 0x8000000000000000ull
19321 +#define XCT_MACTX_ST 0x4000000000000000ull
19322 +#define XCT_MACTX_NORES 0x0000000000000000ull
19323 +#define XCT_MACTX_8BRES 0x1000000000000000ull
19324 +#define XCT_MACTX_24BRES 0x2000000000000000ull
19325 +#define XCT_MACTX_40BRES 0x3000000000000000ull
19326 +#define XCT_MACTX_I 0x0800000000000000ull
19327 +#define XCT_MACTX_O 0x0400000000000000ull
19328 +#define XCT_MACTX_E 0x0200000000000000ull
19329 +#define XCT_MACTX_VLAN_M 0x0180000000000000ull
19330 +#define XCT_MACTX_VLAN_NOP 0x0000000000000000ull
19331 +#define XCT_MACTX_VLAN_REMOVE 0x0080000000000000ull
19332 +#define XCT_MACTX_VLAN_INSERT 0x0100000000000000ull
19333 +#define XCT_MACTX_VLAN_REPLACE 0x0180000000000000ull
19334 +#define XCT_MACTX_CRC_M 0x0060000000000000ull
19335 +#define XCT_MACTX_CRC_NOP 0x0000000000000000ull
19336 +#define XCT_MACTX_CRC_INSERT 0x0020000000000000ull
19337 +#define XCT_MACTX_CRC_PAD 0x0040000000000000ull
19338 +#define XCT_MACTX_CRC_REPLACE 0x0060000000000000ull
19339 +#define XCT_MACTX_SS 0x0010000000000000ull
19340 +#define XCT_MACTX_LLEN_M 0x00007fff00000000ull
19341 +#define XCT_MACTX_LLEN_S 32ull
19342 +#define XCT_MACTX_LLEN(x) ((((long)(x)) << XCT_MACTX_LLEN_S) & \
19343 + XCT_MACTX_LLEN_M)
19344 +#define XCT_MACTX_IPH_M 0x00000000f8000000ull
19345 +#define XCT_MACTX_IPH_S 27ull
19346 +#define XCT_MACTX_IPH(x) ((((long)(x)) << XCT_MACTX_IPH_S) & \
19347 + XCT_MACTX_IPH_M)
19348 +#define XCT_MACTX_IPO_M 0x0000000007c00000ull
19349 +#define XCT_MACTX_IPO_S 22ull
19350 +#define XCT_MACTX_IPO(x) ((((long)(x)) << XCT_MACTX_IPO_S) & \
19351 + XCT_MACTX_IPO_M)
19352 +#define XCT_MACTX_CSUM_M 0x0000000000000060ull
19353 +#define XCT_MACTX_CSUM_NOP 0x0000000000000000ull
19354 +#define XCT_MACTX_CSUM_TCP 0x0000000000000040ull
19355 +#define XCT_MACTX_CSUM_UDP 0x0000000000000060ull
19356 +#define XCT_MACTX_V6 0x0000000000000010ull
19357 +#define XCT_MACTX_C 0x0000000000000004ull
19358 +#define XCT_MACTX_AL2 0x0000000000000002ull
19359 +
19360 +#define XCT_PTR_T 0x8000000000000000ull
19361 +#define XCT_PTR_LEN_M 0x7ffff00000000000ull
19362 +#define XCT_PTR_LEN_S 44
19363 +#define XCT_PTR_LEN(x) ((((long)(x)) << XCT_PTR_LEN_S) & \
19364 + XCT_PTR_LEN_M)
19365 +#define XCT_PTR_ADDR_M 0x00000fffffffffffull
19366 +#define XCT_PTR_ADDR_S 0
19367 +#define XCT_PTR_ADDR(x) ((((long)(x)) << XCT_PTR_ADDR_S) & \
19368 + XCT_PTR_ADDR_M)
19369 +
19370 +/* Function descriptor fields */
19371 +#define XCT_FUN_T 0x8000000000000000ull
19372 +#define XCT_FUN_ST 0x4000000000000000ull
19373 +#define XCT_FUN_NORES 0x0000000000000000ull
19374 +#define XCT_FUN_8BRES 0x1000000000000000ull
19375 +#define XCT_FUN_24BRES 0x2000000000000000ull
19376 +#define XCT_FUN_40BRES 0x3000000000000000ull
19377 +#define XCT_FUN_I 0x0800000000000000ull
19378 +#define XCT_FUN_O 0x0400000000000000ull
19379 +#define XCT_FUN_E 0x0200000000000000ull
19380 +#define XCT_FUN_FUN_S 54
19381 +#define XCT_FUN_FUN_M 0x01c0000000000000ull
19382 +#define XCT_FUN_FUN(num) ((((long)(num)) << XCT_FUN_FUN_S) & \
19383 + XCT_FUN_FUN_M)
19384 +#define XCT_FUN_CRM_NOP 0x0000000000000000ull
19385 +#define XCT_FUN_CRM_SIG 0x0008000000000000ull
19386 +#define XCT_FUN_CRM_ENC 0x0010000000000000ull
19387 +#define XCT_FUN_CRM_DEC 0x0018000000000000ull
19388 +#define XCT_FUN_CRM_SIG_ENC 0x0020000000000000ull
19389 +#define XCT_FUN_CRM_ENC_SIG 0x0028000000000000ull
19390 +#define XCT_FUN_CRM_SIG_DEC 0x0030000000000000ull
19391 +#define XCT_FUN_CRM_DEC_SIG 0x0038000000000000ull
19392 +#define XCT_FUN_LLEN_M 0x0007ffff00000000ull
19393 +#define XCT_FUN_LLEN_S 32ULL
19394 +#define XCT_FUN_LLEN(x) ((((long)(x)) << XCT_FUN_LLEN_S) & \
19395 + XCT_FUN_LLEN_M)
19396 +#define XCT_FUN_SHL_M 0x00000000f8000000ull
19397 +#define XCT_FUN_SHL_S 27ull
19398 +#define XCT_FUN_SHL(x) ((((long)(x)) << XCT_FUN_SHL_S) & \
19399 + XCT_FUN_SHL_M)
19400 +#define XCT_FUN_CHL_M 0x0000000007c00000ull
19401 +#define XCT_FUN_CHL_S 22ull
19402 +#define XCT_FUN_CHL(x) ((((long)(x)) << XCT_FUN_CHL_S) & \
19403 + XCT_FUN_CHL_M)
19404 +#define XCT_FUN_HSZ_M 0x00000000003c0000ull
19405 +#define XCT_FUN_HSZ_S 18ull
19406 +#define XCT_FUN_HSZ(x) ((((long)(x)) << XCT_FUN_HSZ_S) & \
19407 + XCT_FUN_HSZ_M)
19408 +#define XCT_FUN_ALG_DES 0x0000000000000000ull
19409 +#define XCT_FUN_ALG_3DES 0x0000000000008000ull
19410 +#define XCT_FUN_ALG_AES 0x0000000000010000ull
19411 +#define XCT_FUN_ALG_ARC 0x0000000000018000ull
19412 +#define XCT_FUN_ALG_KASUMI 0x0000000000020000ull
19413 +#define XCT_FUN_BCM_ECB 0x0000000000000000ull
19414 +#define XCT_FUN_BCM_CBC 0x0000000000001000ull
19415 +#define XCT_FUN_BCM_CFB 0x0000000000002000ull
19416 +#define XCT_FUN_BCM_OFB 0x0000000000003000ull
19417 +#define XCT_FUN_BCM_CNT 0x0000000000003800ull
19418 +#define XCT_FUN_BCM_KAS_F8 0x0000000000002800ull
19419 +#define XCT_FUN_BCM_KAS_F9 0x0000000000001800ull
19420 +#define XCT_FUN_BCP_NO_PAD 0x0000000000000000ull
19421 +#define XCT_FUN_BCP_ZRO 0x0000000000000200ull
19422 +#define XCT_FUN_BCP_PL 0x0000000000000400ull
19423 +#define XCT_FUN_BCP_INCR 0x0000000000000600ull
19424 +#define XCT_FUN_SIG_MD5 (0ull << 4)
19425 +#define XCT_FUN_SIG_SHA1 (2ull << 4)
19426 +#define XCT_FUN_SIG_HMAC_MD5 (8ull << 4)
19427 +#define XCT_FUN_SIG_HMAC_SHA1 (10ull << 4)
19428 +#define XCT_FUN_A 0x0000000000000008ull
19429 +#define XCT_FUN_C 0x0000000000000004ull
19430 +#define XCT_FUN_AL2 0x0000000000000002ull
19431 +#define XCT_FUN_SE 0x0000000000000001ull
19432 +
19433 +#define XCT_FUN_SRC_PTR(len, addr) (XCT_PTR_LEN(len) | XCT_PTR_ADDR(addr))
19434 +#define XCT_FUN_DST_PTR(len, addr) (XCT_FUN_SRC_PTR(len, addr) | \
19435 + 0x8000000000000000ull)
19436 +
19437 +#define XCT_CTRL_HDR_FUN_NUM_M 0x01c0000000000000ull
19438 +#define XCT_CTRL_HDR_FUN_NUM_S 54
19439 +#define XCT_CTRL_HDR_LEN_M 0x0007ffff00000000ull
19440 +#define XCT_CTRL_HDR_LEN_S 32
19441 +#define XCT_CTRL_HDR_REG_M 0x00000000000000ffull
19442 +#define XCT_CTRL_HDR_REG_S 0
19443 +
19444 +#define XCT_CTRL_HDR(funcN,len,reg) (0x9400000000000000ull | \
19445 + ((((long)(funcN)) << XCT_CTRL_HDR_FUN_NUM_S) \
19446 + & XCT_CTRL_HDR_FUN_NUM_M) | \
19447 + ((((long)(len)) << \
19448 + XCT_CTRL_HDR_LEN_S) & XCT_CTRL_HDR_LEN_M) | \
19449 + ((((long)(reg)) << \
19450 + XCT_CTRL_HDR_REG_S) & XCT_CTRL_HDR_REG_M))
19451 +
19452 +/* Function config command options */
19453 +#define DMA_CALGO_DES 0x00
19454 +#define DMA_CALGO_3DES 0x01
19455 +#define DMA_CALGO_AES 0x02
19456 +#define DMA_CALGO_ARC 0x03
19457 +
19458 +#define DMA_FN_CIV0 0x02
19459 +#define DMA_FN_CIV1 0x03
19460 +#define DMA_FN_HKEY0 0x0a
19461 +
19462 +#define XCT_PTR_ADDR_LEN(ptr) ((ptr) & XCT_PTR_ADDR_M), \
19463 + (((ptr) & XCT_PTR_LEN_M) >> XCT_PTR_LEN_S)
19464 +
19465 +#endif /* PASEMI_FNU_H */